Skip to content

Commit

Permalink
md: more 32x timing tweaks
Browse files Browse the repository at this point in the history
 - Brutal: Above The Claw no longer hangs
 - The Chaotix pre-release prototypes boot again
  • Loading branch information
LukeUsher committed Mar 25, 2024
1 parent 5815c9d commit 9ae2e43
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 18 deletions.
2 changes: 1 addition & 1 deletion ares/component/processor/sh2/instruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ auto SH2::instruction() -> void {
do {
auto block = recompiler.block(PC - 4);
block->execute(*this);
ID = 0;
} while (CCR < cyclesUntilRecompilerExit);

// Reset the count as it may have been set to 0 for an early exit
cyclesUntilRecompilerExit = recompilerStepCycles;

step(CCR);
CCR = 0;
ID = 0;
}
}

Expand Down
17 changes: 7 additions & 10 deletions ares/md/m32x/bus-internal.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
auto M32X::readInternal(n1 upper, n1 lower, n32 address, n16 data) -> n16 {
if(address >= 0x0000'0000 && address <= 0x0000'3fff) {
if(shm.active()) shm.step(1); if(shs.active()) shs.step(1);
if(shm.active()) return shm.bootROM[address >> 1];
if(shs.active()) return shs.bootROM[address >> 1];
}
Expand All @@ -16,12 +17,12 @@ auto M32X::readInternal(n1 upper, n1 lower, n32 address, n16 data) -> n16 {
}

// TODO: SH2 ROM accesses need to stall while the m68k is on the bus
if(shm.active()) shm.step(6);
if(shs.active()) shs.step(6);
if(shm.active()) shm.step(6); if(shs.active()) shs.step(6);
return cartridge.child->read(upper, lower, address, data);
}

if(address >= 0x0400'0000 && address <= 0x0405'ffff) {
if(shm.active()) shm.step(5); if(shs.active()) shs.step(5);
return vdp.bbram[address >> 1 & 0xffff];
}

Expand All @@ -40,17 +41,15 @@ auto M32X::writeInternal(n1 upper, n1 lower, n32 address, n16 data) -> void {
if(address >= 0x0400'0000 && address <= 0x0401'ffff) {
if (!vdp.framebufferAccess) return;
if(!data && (!upper || !lower)) return; //8-bit 0x00 writes do not go through
if(shm.active()) shm.step(4);
if(shs.active()) shs.step(4);
if(shm.active()) shm.step(4); if(shs.active()) shs.step(4);
if(upper) vdp.bbram[address >> 1 & 0xffff].byte(1) = data.byte(1);
if(lower) vdp.bbram[address >> 1 & 0xffff].byte(0) = data.byte(0);
return;
}

if(address >= 0x0402'0000 && address <= 0x0403'ffff) {
if (!vdp.framebufferAccess) return;
if(shm.active()) shm.step(4);
if(shs.active()) shs.step(4);
if(shm.active()) shm.step(4); if(shs.active()) shs.step(4);
if(upper && data.byte(1)) vdp.bbram[address >> 1 & 0xffff].byte(1) = data.byte(1);
if(lower && data.byte(0)) vdp.bbram[address >> 1 & 0xffff].byte(0) = data.byte(0);
return;
Expand All @@ -59,16 +58,14 @@ auto M32X::writeInternal(n1 upper, n1 lower, n32 address, n16 data) -> void {
if(address >= 0x0404'0000 && address <= 0x0405'ffff) {
if (!vdp.framebufferAccess) return;
if(!data && (!upper || !lower)) return; //8-bit 0x00 writes do not go through
if(shm.active()) shm.step(4);
if(shs.active()) shs.step(4);
if(shm.active()) shm.step(4); if(shs.active()) shs.step(4);
if(upper) vdp.bbram[address >> 1 & 0xffff].byte(1) = data.byte(1);
if(lower) vdp.bbram[address >> 1 & 0xffff].byte(0) = data.byte(0);
return;
}

if(address >= 0x0600'0000 && address <= 0x0603'ffff) {
if(shm.active()) shm.step(1);
if(shs.active()) shs.step(1);
if(shm.active()) shm.step(1); if(shs.active()) shs.step(1);
if(upper) sdram[address >> 1 & 0x1ffff].byte(1) = data.byte(1);
if(lower) sdram[address >> 1 & 0x1ffff].byte(0) = data.byte(0);
return;
Expand Down
16 changes: 12 additions & 4 deletions ares/md/m32x/io-internal.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
auto M32X::readInternalIO(n1 upper, n1 lower, n29 address, n16 data) -> n16 {
if(shm.active()) shm.step(1); if(shs.active()) shs.step(1);

//interrupt mask
if(address == 0x4000) {
if(shm.active()) {
Expand Down Expand Up @@ -69,8 +71,8 @@ auto M32X::readInternalIO(n1 upper, n1 lower, n29 address, n16 data) -> n16 {
//communication
if(address >= 0x4020 && address <= 0x402f) {
data = communication[address >> 1 & 7];
if(shm.active()) shm.syncOtherSh2();
if(shs.active()) shs.syncOtherSh2();
if(shm.active()) { shm.syncOtherSh2(); shm.syncM68k(); }
if(shs.active()) { shs.syncOtherSh2(); shs.syncM68k(); }
}

//PWM control
Expand Down Expand Up @@ -136,8 +138,8 @@ auto M32X::readInternalIO(n1 upper, n1 lower, n29 address, n16 data) -> n16 {

//frame buffer control
if(address == 0x410a) {
if(shm.active()) shm.synchronize(cpu);
if(shs.active()) shs.synchronize(cpu);
if(shm.active()) shm.syncM68k();
if(shs.active()) shs.syncM68k();
data.bit( 0) = vdp.framebufferActive;
data.bit( 1) = MegaDrive::vdp.refreshing(); //framebuffer access
data.bit(13) = vdp.vblank || vdp.hblank; //palette access
Expand All @@ -147,13 +149,16 @@ auto M32X::readInternalIO(n1 upper, n1 lower, n29 address, n16 data) -> n16 {

//palette
if(address >= 0x4200 && address <= 0x43ff) {
if(shm.active()) shm.step(4); if(shs.active()) shs.step(4);
data = vdp.cram[address >> 1 & 0xff];
}

return data;
}

auto M32X::writeInternalIO(n1 upper, n1 lower, n29 address, n16 data) -> void {
if(shm.active()) shm.step(1); if(shs.active()) shs.step(1);

//interrupt mask
if(address == 0x4000) {
if(lower && shm.active()) {
Expand Down Expand Up @@ -220,6 +225,8 @@ auto M32X::writeInternalIO(n1 upper, n1 lower, n29 address, n16 data) -> void {

//communication
if(address >= 0x4020 && address <= 0x402f) {
if(shm.active()) { shm.syncOtherSh2(); shm.syncM68k(); }
if(shs.active()) { shs.syncOtherSh2(); shs.syncM68k(); }
if(upper) communication[address >> 1 & 7].byte(1) = data.byte(1);
if(lower) communication[address >> 1 & 7].byte(0) = data.byte(0);
}
Expand Down Expand Up @@ -321,6 +328,7 @@ auto M32X::writeInternalIO(n1 upper, n1 lower, n29 address, n16 data) -> void {
//palette
if(address >= 0x4200 && address <= 0x43ff) {
if (!vdp.framebufferAccess) return;
if(shm.active()) shm.step(4); if(shs.active()) shs.step(4);
if(upper) vdp.cram[address >> 1 & 0xff].byte(1) = data.byte(1);
if(lower) vdp.cram[address >> 1 & 0xff].byte(0) = data.byte(0);
}
Expand Down
5 changes: 4 additions & 1 deletion ares/md/m32x/m32x.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ struct M32X {
auto power(bool reset) -> void;
auto restart() -> void;
auto syncOtherSh2() -> void;
auto syncM68k() -> void;

auto busReadByte(u32 address) -> u32 override;
auto busReadWord(u32 address) -> u32 override;
Expand All @@ -66,9 +67,11 @@ struct M32X {
} irq;

s32 cyclesUntilSh2Sync = 0;
s32 cyclesUntilM68kSync = 0;
s32 cyclesUntilFullSync = 0;
s32 minCyclesBetweenFullSyncs = 0;
s32 minCyclesBetweenSh2Syncs = 0;
s32 minCyclesBetweenM68kSyncs = 0;
s32 minCyclesBetweenFullSyncs = 0;
};

struct VDP {
Expand Down
13 changes: 11 additions & 2 deletions ares/md/m32x/sh7604.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ auto M32X::SH7604::step(u32 clocks) -> void {

Thread::step(clocks);
cyclesUntilSh2Sync -= clocks;
cyclesUntilM68kSync -= clocks;
cyclesUntilFullSync -= clocks;

if(cyclesUntilFullSync <= 0) {
Expand All @@ -71,9 +72,10 @@ auto M32X::SH7604::step(u32 clocks) -> void {

auto M32X::SH7604::power(bool reset) -> void {
Thread::create(23'000'000, {&M32X::SH7604::main, this});
SH2::recompilerStepCycles = 20; // Minimum cycles for recompiler to run for each batch of instructions
SH2::recompilerStepCycles = 20; // Minimum cycles for recompiler to run for each batch of instructions
minCyclesBetweenFullSyncs = 200; // Minimum cycles between full sync with the M68K/MD side
minCyclesBetweenSh2Syncs = 5; // Minimum Cycles between sync with the other SH2 (syncOtherSh2)
minCyclesBetweenSh2Syncs = 5; // Minimum Cycles between sync with the other SH2 (syncOtherSh2)
minCyclesBetweenM68kSyncs = 10; // Minimum Cycles between sync with the M68K (syncM68k)
SH2::power(reset);
irq = {};
irq.vres.enable = 1;
Expand All @@ -94,6 +96,13 @@ auto M32X::SH7604::syncOtherSh2() -> void {
cyclesUntilSh2Sync = minCyclesBetweenSh2Syncs;
}

auto M32X::SH7604::syncM68k() -> void {
// avoid synchronizing if we recently have
if(cyclesUntilM68kSync > 0) return;
Thread::synchronize(cpu);
cyclesUntilM68kSync = minCyclesBetweenM68kSyncs;
}

auto M32X::SH7604::busReadByte(u32 address) -> u32 {
if(address & 1) {
return m32x.readInternal(0, 1, address & ~1).byte(0);
Expand Down

0 comments on commit 9ae2e43

Please sign in to comment.