Skip to content

Commit

Permalink
[SCD] don't apply main CPU writes until after running the sub CPU for…
Browse files Browse the repository at this point in the history
… the appropriate number of cycles; this fixes random freezing in Silpheed, hopefully for good this time
  • Loading branch information
jsgroth committed Oct 16, 2023
1 parent 1136b0d commit 5c73673
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 108 deletions.
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ Cross-platform multi-console Sega emulator that supports the Sega Genesis / Mega
* Some simple horizontal blur and naive anti-dither shaders for blending dithered pixel patterns, which were extremely common on these consoles due to limited color palettes and lack of hardware-supported transparency
* Optional 2x CPU overclocking for Sega Master System and Game Gear emulation

Major TODOs:
* Investigate and fix why _Silpheed_ randomly freezes during gameplay

Minor TODOs:
TODOs:
* Support multiple Sega CD BIOS versions in GUI and automatically use the correct one based on disc region
* Support CHD files for Sega CD in addition to BIN/CUE
* Investigate and fix a few minor issues, like the EA logo flickering for a single frame in _Galahad_
Expand Down
45 changes: 25 additions & 20 deletions genesis-core/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use crate::audio::GenesisAudioDownsampler;
use crate::input::{GenesisInputs, InputState};
use crate::memory::{Cartridge, MainBus, MainBusSignals, Memory};
use crate::memory::{Cartridge, MainBus, MainBusSignals, MainBusWrites, Memory};
use crate::vdp::{Vdp, VdpConfig, VdpTickEffect};
use crate::ym2612::{Ym2612, YmTickEffect};
use bincode::{Decode, Encode};
Expand Down Expand Up @@ -155,12 +155,29 @@ pub struct GenesisEmulator {
ym2612: Ym2612,
input: InputState,
timing_mode: TimingMode,
main_bus_writes: MainBusWrites,
aspect_ratio: GenesisAspectRatio,
adjust_aspect_ratio_in_2x_resolution: bool,
audio_downsampler: GenesisAudioDownsampler,
master_clock_cycles: u64,
}

// This is a macro instead of a function so that it only mutably borrows the needed fields
macro_rules! new_main_bus {
($self:expr, m68k_reset: $m68k_reset:expr) => {
MainBus::new(
&mut $self.memory,
&mut $self.vdp,
&mut $self.psg,
&mut $self.ym2612,
&mut $self.input,
$self.timing_mode,
MainBusSignals { z80_busack: $self.z80.stalled(), m68k_reset: $m68k_reset },
std::mem::take(&mut $self.main_bus_writes),
)
};
}

impl GenesisEmulator {
/// Initialize the emulator from the given ROM.
///
Expand Down Expand Up @@ -200,6 +217,7 @@ impl GenesisEmulator {
&mut input,
timing_mode,
MainBusSignals { z80_busack: false, m68k_reset: true },
MainBusWrites::new(),
));

Self {
Expand All @@ -210,11 +228,12 @@ impl GenesisEmulator {
psg,
ym2612,
input,
timing_mode,
main_bus_writes: MainBusWrites::new(),
aspect_ratio: config.aspect_ratio,
adjust_aspect_ratio_in_2x_resolution: config.adjust_aspect_ratio_in_2x_resolution,
audio_downsampler: GenesisAudioDownsampler::new(timing_mode),
master_clock_cycles: 0,
timing_mode,
}
}

Expand Down Expand Up @@ -302,15 +321,7 @@ impl TickableEmulator for GenesisEmulator {
S: SaveWriter,
S::Err: Debug + Display + Send + Sync + 'static,
{
let mut bus = MainBus::new(
&mut self.memory,
&mut self.vdp,
&mut self.psg,
&mut self.ym2612,
&mut self.input,
self.timing_mode,
MainBusSignals { z80_busack: self.z80.stalled(), m68k_reset: false },
);
let mut bus = new_main_bus!(self, m68k_reset: false);
let m68k_cycles = self.m68k.execute_instruction(&mut bus);

let elapsed_mclk_cycles = u64::from(m68k_cycles) * M68K_MCLK_DIVIDER;
Expand All @@ -322,6 +333,8 @@ impl TickableEmulator for GenesisEmulator {
self.z80.tick(&mut bus);
}

self.main_bus_writes = bus.apply_writes();

self.memory.medium_mut().tick(m68k_cycles);

self.input.tick(m68k_cycles);
Expand Down Expand Up @@ -377,15 +390,7 @@ impl Resettable for GenesisEmulator {
fn soft_reset(&mut self) {
log::info!("Soft resetting console");

self.m68k.execute_instruction(&mut MainBus::new(
&mut self.memory,
&mut self.vdp,
&mut self.psg,
&mut self.ym2612,
&mut self.input,
self.timing_mode,
MainBusSignals { z80_busack: false, m68k_reset: true },
));
self.m68k.execute_instruction(&mut new_main_bus!(self, m68k_reset: true));
self.memory.reset_z80_signals();
self.ym2612.reset();
}
Expand Down
Loading

0 comments on commit 5c73673

Please sign in to comment.