From 214ca7072704e046825340384490d7aa67844e18 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 10 Mar 2026 15:55:01 +0100 Subject: [PATCH] MMC3: Make the Kick Master hack work on multicarts as well. --- src/boards/asic_mmc3.c | 14 ++++++++++++++ src/boards/asic_mmc3.h | 1 + src/boards/mmc3.c | 11 +++++++++++ 3 files changed, 26 insertions(+) diff --git a/src/boards/asic_mmc3.c b/src/boards/asic_mmc3.c index 330ba74..717ac0e 100644 --- a/src/boards/asic_mmc3.c +++ b/src/boards/asic_mmc3.c @@ -83,6 +83,15 @@ DECLFW (MMC3_writeWRAM) { void MMC3_syncPRG (int AND, int OR) { int bank; for (bank = 0; bank < 4; bank++) setprg8(0x8000 | bank <<13, MMC3_cbGetPRGBank(bank) &AND |OR); + /* Enable or disable the Kick Master hack on multicarts */ + if (CartBR(0xF885) == 0xA2 && CartBR(0xF886) == 0x08 && CartBR(0xF887) == 0xCA && CartBR(0xF888) == 0xD0 && + CartBR(0xF894) == 0x20 && CartBR(0xF895) == 0xA7 && CartBR(0xF896) == 0xFA && CartBR(0xF897) == 0xAD) { + /* Kick Master is active. If the previous Horizontal Blanking handler was the standard MMC3 handler, switch it to the Kick-Master-specific one. */ + if (GameHBIRQHook == MMC3_clockCounter) GameHBIRQHook = MMC3_clockCounter_KickMaster; + } else { + /* Kick Master is not or no longer active. If the previous handler was the Kick-Master-specific one, switch it to the standard MMC3 one. */ + if (GameHBIRQHook == MMC3_clockCounter_KickMaster) GameHBIRQHook = MMC3_clockCounter; + } } void MMC3_syncCHR (int AND, int OR) { @@ -101,6 +110,11 @@ void MMC3_clockCounter () { MMC3_reloadRequest = 0; } +void MMC3_clockCounter_KickMaster () { + if (scanline == 238) MMC3_clockCounter(); + MMC3_clockCounter(); +} + DECLFW(MMC3_writeReg) { switch(A &0xE001) { case 0x8000: MMC3_index = V; break; diff --git a/src/boards/asic_mmc3.h b/src/boards/asic_mmc3.h index 3e4527b..a782d62 100644 --- a/src/boards/asic_mmc3.h +++ b/src/boards/asic_mmc3.h @@ -35,6 +35,7 @@ void MMC3_syncPRG (int, int); void MMC3_syncCHR (int, int); void MMC3_syncMirror (); void MMC3_clockCounter (); +void MMC3_clockCounter_KickMaster (); DECLFW (MMC3_writeReg); void MMC3_clear (); void MMC3_activate (uint8, void (*)(), uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*))); diff --git a/src/boards/mmc3.c b/src/boards/mmc3.c index 356ce56..78a179d 100644 --- a/src/boards/mmc3.c +++ b/src/boards/mmc3.c @@ -75,6 +75,8 @@ int MMC3CanWriteToWRAM(void) { return ((A001B & 0x80) && !(A001B & 0x40)); } +static void MMC3_hb (void); +static void MMC3_hb_KickMasterHack (void); void FixMMC3PRG(int V) { if (V & 0x40) { pwrap(0xC000, DRegBuf[6]); @@ -85,6 +87,15 @@ void FixMMC3PRG(int V) { } pwrap(0xA000, DRegBuf[7]); pwrap(0xE000, ~0); + /* Enable or disable the Kick Master hack on multicarts */ + if (CartBR(0xF885) == 0xA2 && CartBR(0xF886) == 0x08 && CartBR(0xF887) == 0xCA && CartBR(0xF888) == 0xD0 && + CartBR(0xF894) == 0x20 && CartBR(0xF895) == 0xA7 && CartBR(0xF896) == 0xFA && CartBR(0xF897) == 0xAD) { + /* Kick Master is active. If the previous Horizontal Blanking handler was the standard MMC3 handler, switch it to the Kick-Master-specific one. */ + if (GameHBIRQHook == MMC3_hb) GameHBIRQHook = MMC3_hb_KickMasterHack; + } else { + /* Kick Master is not or no longer active. If the previous handler was the Kick-Master-specific one, switch it to the standard MMC3 one. */ + if (GameHBIRQHook == MMC3_hb_KickMasterHack) GameHBIRQHook = MMC3_hb; + } } void FixMMC3CHR(int V) {