From a2fdeee096162cef9c74fe1f34effc3d697f9899 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Mon, 1 Sep 2025 01:13:46 +0200 Subject: [PATCH 001/109] Add mapper 446 using mapper emulation cores that can be included in other multi-ASIC mappers. --- src/boards/183.c | 8 +- src/boards/21_22_23_25.c | 42 ++-- src/boards/222.c | 4 +- src/boards/252_253.c | 20 +- src/boards/266.c | 7 +- src/boards/298.c | 5 +- src/boards/308.c | 4 +- src/boards/362.c | 10 +- src/boards/384.c | 11 +- src/boards/398.c | 11 +- src/boards/432.c | 81 ++++--- src/boards/446.c | 423 +++++++++++++++++++++++++++++++++++++ src/boards/447.c | 16 +- src/boards/448.c | 27 ++- src/boards/450.c | 6 +- src/boards/520.c | 6 +- src/boards/524.c | 4 +- src/boards/525.c | 8 +- src/boards/527.c | 6 +- src/boards/529.c | 6 +- src/boards/530.c | 10 +- src/boards/542.c | 6 +- src/boards/544.c | 16 +- src/boards/559.c | 10 +- src/boards/563.c | 4 +- src/boards/asic_h3001.c | 165 +++++++++++++++ src/boards/asic_h3001.h | 34 +++ src/boards/asic_latch.c | 89 ++++++++ src/boards/asic_latch.h | 35 +++ src/boards/asic_mmc1.c | 169 +++++++++++++++ src/boards/asic_mmc1.h | 41 ++++ src/boards/asic_mmc2.c | 108 ++++++++++ src/boards/asic_mmc2.h | 34 +++ src/boards/asic_mmc3.c | 165 +++++++++++++++ src/boards/asic_mmc3.h | 44 ++++ src/boards/asic_pt8154.c | 103 +++++++++ src/boards/asic_pt8154.h | 35 +++ src/boards/asic_qj.c | 93 ++++++++ src/boards/asic_qj.h | 35 +++ src/boards/asic_tc3294.c | 106 ++++++++++ src/boards/asic_tc3294.h | 35 +++ src/boards/asic_vrc1.c | 95 +++++++++ src/boards/asic_vrc1.h | 34 +++ src/boards/asic_vrc2and4.c | 297 ++++++++++++++++++++++++++ src/boards/asic_vrc2and4.h | 50 +++++ src/boards/asic_vrc3.c | 129 +++++++++++ src/boards/asic_vrc3.h | 34 +++ src/boards/asic_vrc6.c | 208 ++++++++++++++++++ src/boards/asic_vrc6.h | 40 ++++ src/boards/asic_vrc7.c | 180 ++++++++++++++++ src/boards/asic_vrc7.h | 41 ++++ src/boards/vrc2and4.c | 242 --------------------- src/boards/vrc2and4.h | 36 ---- src/boards/wram.c | 46 ++++ src/boards/wram.h | 28 +++ src/ines.c | 1 + src/ines.h | 1 + 57 files changed, 3063 insertions(+), 441 deletions(-) create mode 100644 src/boards/446.c create mode 100644 src/boards/asic_h3001.c create mode 100644 src/boards/asic_h3001.h create mode 100644 src/boards/asic_latch.c create mode 100644 src/boards/asic_latch.h create mode 100644 src/boards/asic_mmc1.c create mode 100644 src/boards/asic_mmc1.h create mode 100644 src/boards/asic_mmc2.c create mode 100644 src/boards/asic_mmc2.h create mode 100644 src/boards/asic_mmc3.c create mode 100644 src/boards/asic_mmc3.h create mode 100644 src/boards/asic_pt8154.c create mode 100644 src/boards/asic_pt8154.h create mode 100644 src/boards/asic_qj.c create mode 100644 src/boards/asic_qj.h create mode 100644 src/boards/asic_tc3294.c create mode 100644 src/boards/asic_tc3294.h create mode 100644 src/boards/asic_vrc1.c create mode 100644 src/boards/asic_vrc1.h create mode 100644 src/boards/asic_vrc2and4.c create mode 100644 src/boards/asic_vrc2and4.h create mode 100644 src/boards/asic_vrc3.c create mode 100644 src/boards/asic_vrc3.h create mode 100644 src/boards/asic_vrc6.c create mode 100644 src/boards/asic_vrc6.h create mode 100644 src/boards/asic_vrc7.c create mode 100644 src/boards/asic_vrc7.h delete mode 100644 src/boards/vrc2and4.c delete mode 100644 src/boards/vrc2and4.h create mode 100644 src/boards/wram.c create mode 100644 src/boards/wram.h diff --git a/src/boards/183.c b/src/boards/183.c index 85a9822..c494dcf 100644 --- a/src/boards/183.c +++ b/src/boards/183.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static uint8 prg; @@ -37,7 +37,7 @@ static void sync () { DECLFW(Mapper183_writePRG) { prg =A &0xFF; - VRC24_Sync(); + sync(); } void Mapper183_power(void) { @@ -46,9 +46,7 @@ void Mapper183_power(void) { } void Mapper183_Init (CartInfo *info) { - VRC24_init(info, sync, 0x04, 0x08, 1, 1, 0); - VRC24_WRAMRead =CartBR; - VRC24_WRAMWrite =Mapper183_writePRG; + VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, CartBR, Mapper183_writePRG, NULL); AddExState(Mapper183_stateRegs, ~0, 0, 0); info->Power =Mapper183_power; } diff --git a/src/boards/21_22_23_25.c b/src/boards/21_22_23_25.c index da73aa8..1f9f988 100644 --- a/src/boards/21_22_23_25.c +++ b/src/boards/21_22_23_25.c @@ -19,7 +19,8 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" +#include "wram.h" static void sync () { VRC24_syncWRAM(0); @@ -31,41 +32,38 @@ static void sync () { void Mapper21_Init (CartInfo *info) { switch(info->submapper) { - case 1: VRC24_init(info, sync, 0x02, 0x04, 1, 1, 8); break; - case 2: VRC24_init(info, sync, 0x40, 0x80, 1, 1, 8); break; - default: VRC24_init(info, sync, 0x42, 0x84, 1, 1, 8); break; + case 1: VRC4_init(info, sync, 0x02, 0x04, 1, NULL, NULL, NULL, NULL, NULL); break; + case 2: VRC4_init(info, sync, 0x40, 0x80, 1, NULL, NULL, NULL, NULL, NULL); break; + default: VRC4_init(info, sync, 0x42, 0x84, 1, NULL, NULL, NULL, NULL, NULL); break; } + WRAM_init(info, 8); } -int Mapper22_getCHRBank(int bank) { - return VRC24_chr[bank &7] >>1; +static int Mapper22_getCHRBank(uint8 bank) { + return VRC24_getCHRBank(bank &7) >>1; } void Mapper22_Init (CartInfo *info) { - VRC24_init(info, sync, 0x02, 0x01, 0, 0, 8); - VRC24_GetCHRBank =Mapper22_getCHRBank; -} - -DECLFR(Mapper23_readProtection) { - return VRC2_pins; + VRC2_init(info, sync, 0x02, 0x01, NULL, Mapper22_getCHRBank, NULL, NULL); + WRAM_init(info, 8); } void Mapper23_Init (CartInfo *info) { switch(info->submapper) { - case 1: VRC24_init(info, sync, 0x01, 0x02, 1, 1, 8); break; - case 2: VRC24_init(info, sync, 0x04, 0x08, 1, 1, 8); break; - case 3: VRC24_init(info, sync, 0x01, 0x02, 0, 0, 8); - VRC24_WRAMRead =Mapper23_readProtection; - break; - default: VRC24_init(info, sync, 0x05, 0x0A, 1, 1, 8); break; + case 1: VRC4_init(info, sync, 0x01, 0x02, 1, NULL, NULL, NULL, NULL, NULL); break; + case 2: VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, NULL, NULL, NULL); break; + case 3: VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); break; + default: VRC4_init(info, sync, 0x05, 0x0A, 1, NULL, NULL, NULL, NULL, NULL); break; } + WRAM_init(info, 8); } void Mapper25_Init (CartInfo *info) { switch(info->submapper) { - case 1: VRC24_init(info, sync, 0x02, 0x01, 1, 1, 8); break; - case 2: VRC24_init(info, sync, 0x08, 0x04, 1, 1, 8); break; - case 3: VRC24_init(info, sync, 0x02, 0x01, 0, 0, 8); break; - default: VRC24_init(info, sync, 0x0A, 0x05, 1, 1, 8); break; + case 1: VRC4_init(info, sync, 0x02, 0x01, 1, NULL, NULL, NULL, NULL, NULL); break; + case 2: VRC4_init(info, sync, 0x08, 0x04, 1, NULL, NULL, NULL, NULL, NULL); break; + case 3: VRC2_init(info, sync, 0x02, 0x01, NULL, NULL, NULL, NULL); break; + default: VRC4_init(info, sync, 0x0A, 0x05, 1, NULL, NULL, NULL, NULL, NULL); break; } + WRAM_init(info, 8); } diff --git a/src/boards/222.c b/src/boards/222.c index 9ecf914..832d3d4 100644 --- a/src/boards/222.c +++ b/src/boards/222.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static uint8 clockMode; static uint8 pending; @@ -91,7 +91,7 @@ void Mapper222_power(void) { } void Mapper222_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0); + VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); AddExState(Mapper222_stateRegs, ~0, 0, 0); info->Power =Mapper222_power; MapIRQHook =Mapper222_cpuCycle; diff --git a/src/boards/252_253.c b/src/boards/252_253.c index 06d3133..8e70fb7 100644 --- a/src/boards/252_253.c +++ b/src/boards/252_253.c @@ -19,7 +19,8 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" +#include "wram.h" static uint8 *CHRRAM; static uint32 CHRRAMSize; @@ -39,17 +40,17 @@ static void sync () { int bank; VRC24_syncWRAM(0); VRC24_syncPRG(0x01F, 0x000); - for (bank =0; bank <8; bank++) setchr1r((VRC24_chr[bank] &mask) ==compare? 0x10: 0x00, bank <<10, VRC24_chr[bank]); + for (bank =0; bank <8; bank++) setchr1r((VRC24_getCHRBank(bank) &mask) ==compare? 0x10: 0x00, bank <<10, VRC24_getCHRBank(bank)); VRC24_syncMirror(); } static DECLFW(Mapper252_253_interceptPPUWrite) { if (~RefreshAddr &0x2000) { - int bank =VRC24_chr[RefreshAddr >>10 &7]; + int bank =VRC24_getCHRBank(RefreshAddr >>10 &7); switch(bank) { - case 0x88: mask =0xFC; compare =0x4C; VRC24_Sync(); break; - case 0xC2: mask =0xFE; compare =0x7C; VRC24_Sync(); break; - case 0xC8: mask =0xFE; compare =0x04; VRC24_Sync(); break; + case 0x88: mask =0xFC; compare =0x4C; sync(); break; + case 0xC2: mask =0xFE; compare =0x7C; sync(); break; + case 0xC8: mask =0xFE; compare =0x04; sync(); break; } } writePPU(A, V); @@ -76,10 +77,12 @@ void Mapper252_253_close(void) { FCEU_gfree(CHRRAM); CHRRAM =NULL; } + WRAM_close(); } void Mapper252_Init (CartInfo *info) { - VRC24_init(info, sync, 0x4, 0x8, 1, 1, 0); + VRC4_init(info, sync, 0x4, 0x8, 1, NULL, NULL, NULL, NULL, NULL); + WRAM_init(info, 8); info->Power =Mapper252_power; info->Close =Mapper252_253_close; AddExState(stateRegs, ~0, 0, 0); @@ -91,7 +94,8 @@ void Mapper252_Init (CartInfo *info) { } void Mapper253_Init (CartInfo *info) { - VRC24_init(info, sync, 0x4, 0x8, 1, 1, 0); + VRC4_init(info, sync, 0x4, 0x8, 1, NULL, NULL, NULL, NULL, NULL); + WRAM_init(info, 8); info->Power =Mapper253_power; info->Close =Mapper252_253_close; AddExState(stateRegs, ~0, 0, 0); diff --git a/src/boards/266.c b/src/boards/266.c index 64e405a..5a0e2ec 100644 --- a/src/boards/266.c +++ b/src/boards/266.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static uint8 prg; @@ -39,7 +39,7 @@ DECLFW(UNLCITYFIGHT_externalSelect) { (GetWriteHandler(0x4011))(0x4011, V <<3 &0x78); else { prg =V >>2; - VRC24_Sync(); + sync(); } } @@ -54,8 +54,7 @@ void UNLCITYFIGHT_power(void) { } void UNLCITYFIGHT_Init (CartInfo *info) { - VRC24_init(info, sync, 0x04, 0x08, 1, 1, 0); - VRC24_ExternalSelect =UNLCITYFIGHT_externalSelect; + VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, NULL, NULL, UNLCITYFIGHT_externalSelect); AddExState(UNLCITYFIGHT_stateRegs, ~0, 0, 0); info->Power =UNLCITYFIGHT_power; } diff --git a/src/boards/298.c b/src/boards/298.c index af557d8..cdf6682 100644 --- a/src/boards/298.c +++ b/src/boards/298.c @@ -19,15 +19,14 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static void sync () { - VRC24_syncWRAM(0); VRC24_syncPRG(0x01F, 0x000); VRC24_syncCHR(0x1FF, 0x000); VRC24_syncMirror(); } void UNLTF1201_Init (CartInfo *info) { - VRC24_init(info, sync, 0x02, 0x01, 1, 0, 8); + VRC4_init(info, sync, 0x02, 0x01, 0, NULL, NULL, NULL, NULL, NULL); } diff --git a/src/boards/308.c b/src/boards/308.c index e9a8212..0c636f8 100644 --- a/src/boards/308.c +++ b/src/boards/308.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static uint8 irqEnabled; static uint16 irqCounterLow; @@ -65,7 +65,7 @@ void UNLTH21311_power(void) { } void UNLTH21311_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0); + VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); AddExState(UNLTH21311_stateRegs, ~0, 0, 0); info->Power =UNLTH21311_power; MapIRQHook =UNLTH21311_cpuCycle; diff --git a/src/boards/362.c b/src/boards/362.c index 6a77c4e..187050d 100644 --- a/src/boards/362.c +++ b/src/boards/362.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static uint8 game; @@ -34,8 +34,8 @@ static void sync () { VRC24_syncCHR(0x1FF, 0x200); VRC24_syncMirror(); } else { - VRC24_syncPRG(0x00F, VRC24_chr[0] >>3 &0x30); - VRC24_syncCHR(0x07F, VRC24_chr[0] &0x180); + VRC24_syncPRG(0x00F, VRC24_getCHRBank(0) >>3 &0x30); + VRC24_syncCHR(0x07F, VRC24_getCHRBank(0) &0x180); VRC24_syncMirror(); } } @@ -47,11 +47,11 @@ void Mapper362_power(void) { void Mapper362_reset(void) { game ^=1; - VRC24_Sync(); + sync(); } void Mapper362_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 1, 0, 0); + VRC4_init(info, sync, 0x01, 0x02, 0, NULL, NULL, NULL, NULL, NULL); info->Power =Mapper362_power; if (PRGsize[0] >512*1024) { info->Reset =Mapper362_reset; diff --git a/src/boards/384.c b/src/boards/384.c index 9333622..410e396 100644 --- a/src/boards/384.c +++ b/src/boards/384.c @@ -19,7 +19,8 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" +#include "wram.h" static uint8 reg; @@ -38,7 +39,7 @@ static void sync () { DECLFW(Mapper384_writeReg) { if (A &0x800 && ~reg &0x08) { reg =V; - VRC24_Sync(); + sync(); } CartBW(A, V); } @@ -50,12 +51,12 @@ void Mapper384_power(void) { void Mapper384_reset(void) { reg =0; - VRC24_Sync(); + sync(); } void Mapper384_Init (CartInfo *info) { - VRC24_init(info, sync, 0x04, 0x08, 1, 0, 2); - VRC24_WRAMWrite =Mapper384_writeReg; + VRC4_init(info, sync, 0x04, 0x08, 0, NULL, NULL, NULL, Mapper384_writeReg, NULL); + WRAM_init(info, 2); info->Power =Mapper384_power; info->Reset =Mapper384_reset; AddExState(Mapper384_stateRegs, ~0, 0, 0); diff --git a/src/boards/398.c b/src/boards/398.c index b0e69e7..d0785ff 100644 --- a/src/boards/398.c +++ b/src/boards/398.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static uint8 reg; @@ -30,8 +30,8 @@ static SFORMAT Mapper398_stateRegs[] ={ static void sync () { if (reg &0x80) { - setprg32(0x8000, reg >>5 &6 | VRC24_chr[0] >>2 &1); - setchr8(0x40 | reg >>3 &8 | VRC24_chr[0] &7); + setprg32(0x8000, reg >>5 &6 | VRC24_getCHRBank(0) >>2 &1); + setchr8(0x40 | reg >>3 &8 | VRC24_getCHRBank(0) &7); } else { VRC24_syncPRG(0x0F, 0x00); VRC24_syncCHR(0x1FF, 0x000); @@ -41,7 +41,6 @@ static void sync () { DECLFW(Mapper398_writeReg) { reg =A &0xFF; - VRC24_Sync(); VRC24_writeReg(A, V); } @@ -53,11 +52,11 @@ void Mapper398_power(void) { void Mapper398_reset(void) { reg =0xC0; - VRC24_Sync(); + sync(); } void Mapper398_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 1, 1, 0); + VRC4_init(info, sync, 0x01, 0x02, 1, NULL, NULL, NULL, NULL, NULL); info->Power =Mapper398_power; info->Reset =Mapper398_reset; AddExState(Mapper398_stateRegs, ~0, 0, 0); diff --git a/src/boards/432.c b/src/boards/432.c index e006fc9..dadf0d4 100644 --- a/src/boards/432.c +++ b/src/boards/432.c @@ -21,56 +21,67 @@ */ #include "mapinc.h" -#include "mmc3.h" +#include "asic_mmc3.h" static uint8 submapper; +static uint8 reg[2]; +static uint8 pad; -static void M432CW(uint32 A, uint8 V) { - int chrAND = (EXPREGS[1] & 0x04) ? 0x7F : 0xFF; - int chrOR = (EXPREGS[1] << 7) & 0x080 | (EXPREGS[1] << 5) & 0x100 | (EXPREGS[1] << 4) & 0x200; - setchr1(A, (V & chrAND) | (chrOR & ~chrAND)); +static DECLFR(readPad) { + return pad; } -static void M432PW(uint32 A, uint8 V) { - int prgAND = (EXPREGS[1] & 0x02) ? 0x0F : 0x1F; - int prgOR = ((EXPREGS[1] << 4) & 0x10) | (EXPREGS[1] << 1) & 0x60; - if ((A < 0xC000) || (~EXPREGS[1] & 0x40)) setprg8(A, (V & prgAND) | (prgOR & ~prgAND) & (EXPREGS[1] &(submapper ==2? 0x20: 0x80)?~2:~0)); - if ((A < 0xC000) && (EXPREGS[1] & 0x40)) setprg8(A | 0x4000, (V & prgAND) | (prgOR & ~prgAND) | (EXPREGS[1] &(submapper ==2? 0x20: 0x80)? 2: 0)); +static void sync() { + int prgAND =reg[1] &0x02? 0x0F: 0x1F; + int chrAND =reg[1] &0x20 && submapper == 3? 0x1FF: reg[1] &0x04? 0x7F: 0xFF; + int prgOR =reg[1] <<4 &0x10 | reg[1] <<1 &0x60; + int chrOR =reg[1] <<7 &0x80 | reg[1] <<5 &0x100 | reg[1] <<4 &0x200; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); + SetReadHandler(0x8000, 0xFFFF, submapper == 1 && reg[1] &0x20 || submapper != 1 && reg[0] &0x01? readPad: CartBR); } -static DECLFR(M432Read) { - if (submapper ==1? !!(EXPREGS[1] &0x20): !!(EXPREGS[0] &0x01)) return EXPREGS[2]; - return CartBR(A); +static int getPRGBank(uint8 bank) { + if (reg[1] &0x40) { + int mask = reg[1] &(submapper == 2? 0x20: 0x80)? 3: 1; + return MMC3_getPRGBank(bank & 1) &~mask | bank &mask; + } else + return MMC3_getPRGBank(bank); } -static DECLFW(M432Write) { - EXPREGS[A & 1] = V; - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); +static int getCHRBank(uint8 bank) { + if (reg[1] &0x20 && submapper == 3) + return MMC3_getCHRBank(bank &6 | bank >>1 &1) <<1 | bank &1; + else + return MMC3_getCHRBank(bank); } -static void M432Reset(void) { - EXPREGS[0] = 0; - EXPREGS[1] = 0; - EXPREGS[2]++; - MMC3RegReset(); +static DECLFW(writeReg) { + if (submapper == 3 && reg[1] &0x80) + ; + else { + reg[A &1] = V; + sync(); + } } -static void M432Power(void) { - EXPREGS[0] = 0; - EXPREGS[1] = 0; - EXPREGS[2] = 0; - GenMMC3Power(); - SetReadHandler(0x8000, 0xFFFF, M432Read); - SetWriteHandler(0x6000, 0x7FFF, M432Write); +static void reset() { + reg[0] = reg[1] = 0; + ++pad; + sync(); +} + +static void power() { + reg[0] = reg[1] = 0; + pad = 0; + MMC3_power(); } void Mapper432_Init(CartInfo *info) { submapper =info->submapper; - GenMMC3_Init(info, 256, 256, 0, 0); - cwrap = M432CW; - pwrap = M432PW; - info->Power = M432Power; - info->Reset = M432Reset; - AddExState(EXPREGS, 3, 0, "EXPR"); + MMC3_init(info, sync, MMC3_TYPE_AX5202P, getPRGBank, getCHRBank, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(reg, 2, 0, "EXPR"); } diff --git a/src/boards/446.c b/src/boards/446.c new file mode 100644 index 0000000..76551e8 --- /dev/null +++ b/src/boards/446.c @@ -0,0 +1,423 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_h3001.h" +#include "asic_latch.h" +#include "asic_mmc1.h" +#include "asic_mmc2.h" +#include "asic_mmc3.h" +#include "asic_pt8154.h" +#include "asic_qj.h" +#include "asic_tc3294.h" +#include "asic_vrc1.h" +#include "asic_vrc2and4.h" +#include "asic_vrc3.h" +#include "asic_vrc6.h" +#include "asic_vrc7.h" +#include "flashrom.h" +#include "wram.h" + +static uint8 submapper; +static uint8 reg[8]; + +static void (*mapperSync)(int, int, int, int) = NULL; +static void applyMode (uint8); + +static void sync () { + int prgAND = reg[3] ^ (submapper == 2? 0x00: 0xFF); + int prgOR = reg[1] | reg[2] <<8; + int chrAND = reg[4] <<2 &0xE0 ^0xFF; + int chrOR = reg[6]; + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], !(reg[5] &0x04)); + if (mapperSync) mapperSync(prgAND, prgOR, chrAND, chrOR); +} + +static void sync_152 (int prgAND, int prgOR, int chrAND, int chrOR) { + prgAND >>=1; + chrAND >>=3; + prgOR >>=1; + chrOR >>=3; + setprg16(0x8000, Latch_data >>4 &prgAND | prgOR &~prgAND); + setprg16(0xC000, prgOR | prgAND); + setchr8(Latch_data &chrAND | chrOR &~chrAND); + setmirror(Latch_data &0x80? MI_1: MI_0); +} + +static void sync_AxROM (int prgAND, int prgOR, int chrAND, int chrOR) { + prgAND >>=2; + prgOR >>=2; + setprg32(0x8000, Latch_data &prgAND | prgOR &~prgAND); + setchr8(chrOR); + setmirror(Latch_data &0x10? MI_1: MI_0); +} + +static void sync_BNROM (int prgAND, int prgOR, int chrAND, int chrOR) { + setprg8(0x8000, (Latch_data <<2 |0) &prgAND |prgOR); + setprg8(0xA000, (Latch_data <<2 |1) &prgAND |prgOR); + setprg8(0xC000, (Latch_data <<2 |2) &prgAND |prgOR); + setprg8(0xE000, (Latch_data <<2 |3) &prgAND |prgOR); + setchr8(chrOR); + setmirror(reg[4] &0x01? MI_V: MI_H); +} + +static void sync_CNROM (int prgAND, int prgOR, int chrAND, int chrOR) { + chrAND >>=3; + chrOR >>=3; + setprg8(0x8000, 0 &prgAND |prgOR); + setprg8(0xA000, 1 &prgAND |prgOR); + setprg8(0xC000, 2 &prgAND |prgOR); + setprg8(0xE000, 3 &prgAND |prgOR); + setchr8(Latch_data &(reg[4] &1? 7: 3)); + setmirror(reg[4] &0x01? MI_V: MI_H); +} + +static void sync_CNROM_Konami (int prgAND, int prgOR, int chrAND, int chrOR) { + chrAND >>=3; + chrOR >>=3; + setprg8(0x8000, 0 &prgAND |prgOR); + setprg8(0xA000, 1 &prgAND |prgOR); + setprg8(0xC000, 2 &prgAND |prgOR); + setprg8(0xE000, 3 &prgAND |prgOR); + setchr8(Latch_data <<1 &2 | Latch_data >>1 &1); + setmirror(reg[4] &0x01? MI_V: MI_H); +} + +static void sync_GNROM (int prgAND, int prgOR, int chrAND, int chrOR) { + prgAND >>=2; + chrAND >>=3; + prgOR >>=2; + chrOR >>=3; + setprg32(0x8000, Latch_data >>4 &prgAND | prgOR &~prgAND); + setchr8(Latch_data &3); + setmirror(reg[4] &0x01? MI_V: MI_H); +} + +static void sync_H3001 (int prgAND, int prgOR, int chrAND, int chrOR) { + H3001_syncPRG(prgAND, prgOR &~prgAND); + H3001_syncCHR(chrAND, chrOR &~chrAND); + H3001_syncMirror(); +} + +static void sync_PNROM (int prgAND, int prgOR, int chrAND, int chrOR) { + MMC2_syncPRG(prgAND, prgOR &~prgAND); + MMC2_syncCHR(chrAND, chrOR &~chrAND); + MMC2_syncMirror(); +} + +static void sync_SKROM (int prgAND, int prgOR, int chrAND, int chrOR) { + prgAND >>=1; + chrAND >>=2; + prgOR >>=1; + chrOR >>=2; + MMC1_syncWRAM(reg[5]); + MMC1_syncPRG(prgAND, prgOR &~prgAND); + MMC1_syncCHR(chrAND, chrOR &~chrAND); + MMC1_syncMirror(); +} + +static void sync_SNROM (int prgAND, int prgOR, int chrAND, int chrOR) { + prgAND >>=1; + chrAND >>=2; + prgOR >>=1; + chrOR >>=2; + MMC1_syncWRAM(reg[5]); + MMC1_syncPRG(prgAND, prgOR &~prgAND); + MMC1_syncCHR(chrAND, chrOR &~chrAND); + MMC1_syncMirror(); +} + +static void sync_SUROM (int prgAND, int prgOR, int chrAND, int chrOR) { + prgAND >>=1; + chrAND =chrAND >>2 &0x0F; /* The highest CHR bit switches 256 KiB PRG banks, so don't use that as a CHR bank bit. */ + prgOR >>=1; + chrOR >>=2; + MMC1_syncWRAM(reg[5]); + MMC1_syncPRG(prgAND, prgOR &~prgAND); + MMC1_syncCHR(chrAND, chrOR &~chrAND); + MMC1_syncMirror(); +} + +static void sync_PT8154 (int prgAND, int prgOR, int chrAND, int chrOR) { + PT8154_syncPRG(prgAND, prgOR &~prgAND); + PT8154_syncCHR(chrAND, chrOR &~chrAND); + PT8154_syncMirror(); +} + +static void sync_QJ (int prgAND, int prgOR, int chrAND, int chrOR) { + QJ_syncPRG(prgAND, prgOR &~prgAND); + QJ_syncCHR(chrAND, chrOR &~chrAND); + QJ_syncMirror(); +} +static void sync_TC3294(int prgAND, int prgOR, int chrAND, int chrOR) { + TC3294_syncWRAM(reg[5]); + TC3294_syncPRG(prgAND, prgOR &~prgAND); + setchr8(0); + TC3294_syncMirror(); +} + +static void sync_TxROM (int prgAND, int prgOR, int chrAND, int chrOR) { + MMC3_syncWRAM(reg[5]); + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static void sync_TxSROM (int prgAND, int prgOR, int chrAND, int chrOR) { + MMC3_syncWRAM(reg[5]); + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND &0x7F, chrOR &~chrAND); + setmirror(MMC3_getCHRBank(0) &0x80? MI_1: MI_0); +} + +static void sync_UxROM (int prgAND, int prgOR, int chrAND, int chrOR) { + prgAND >>=1; + prgOR >>=1; + setprg16(0x8000, Latch_data &prgAND | prgOR &~prgAND); + setprg16(0xC000, prgOR | prgAND); + setchr8(chrOR); + setmirror(reg[4] &0x01? MI_V: MI_H); +} + +static void sync_VRC1 (int prgAND, int prgOR, int chrAND, int chrOR) { + VRC1_syncPRG(prgAND, prgOR &~prgAND); + VRC1_syncCHR(chrAND, chrOR &~chrAND); + VRC1_syncMirror(); +} + +static void sync_VRC3 (int prgAND, int prgOR, int chrAND, int chrOR) { + prgAND >>=1; + prgOR >>=1; + VRC3_syncWRAM(reg[5]); + VRC3_syncPRG(prgAND, prgOR &~prgAND); + VRC3_syncCHR(chrAND, chrOR &~chrAND); + setmirror(reg[4] &0x01? MI_V: MI_H); +} + +static void sync_VRC4 (int prgAND, int prgOR, int chrAND, int chrOR) { + VRC24_syncWRAM(reg[5]); + VRC24_syncPRG(prgAND, prgOR &~prgAND); + VRC24_syncCHR(chrAND, chrOR &~chrAND); + VRC24_syncMirror(); +} + +static void sync_VRC6 (int prgAND, int prgOR, int chrAND, int chrOR) { + VRC6_syncWRAM(reg[5]); + VRC6_syncPRG(prgAND, prgOR &~prgAND); + VRC6_syncCHR(chrAND, chrOR &~chrAND); + VRC6_syncMirror(); +} + +static void sync_VRC7 (int prgAND, int prgOR, int chrAND, int chrOR) { + VRC7_syncWRAM(reg[5]); + VRC7_syncPRG(prgAND, prgOR &~prgAND); + VRC7_syncCHR(chrAND, chrOR &~chrAND); + VRC7_syncMirror(); +} + +static void sync_supervisor (int prgAND, int prgOR, int chrAND, int chrOR) { + setprg8(0x8000, prgOR); + setprg8(0xA000, prgOR +1); + setprg8(0xC000, submapper == 3? 0x1E: 0x3E); + setprg8(0xE000, submapper == 3? 0x1F: 0x3F); + setchr8(chrOR); + setmirror(reg[4] &0x01? MI_V: MI_H); +} + +static DECLFW(writeFlash) { + flashrom_write(A &0x1FFF | (Page[A >>11] +A -PRGptr[0]) &~0x1FFF, V); +} + +static int SUROM_getPRGBank(uint8 bank) { + return MMC1_getPRGBank(bank) | MMC1_getCHRBank(0) &0x10; +} + +static int Mapper22_getCHRBank(uint8 bank) { + return VRC24_getCHRBank(bank &7) >>1; +} + +static DECLFW(writeReg) { + reg[A &7] = V; + if ((A &7) == 0) + applyMode(1); + else + sync(); +} + +static void applyMode (uint8 clear) { + if (reg[0] &0x80) { + SetWriteHandler(0x5000, 0x5FFF, CartBW); + switch(submapper <<8 | reg[0] &0x1F) { + case 0x000: case 0x100: case 0x200: + mapperSync = sync_UxROM; + Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); + break; + case 0x001: case 0x105: case 0x205: + mapperSync = sync_SKROM; + MMC1_activate(clear, sync, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL); + break; + case 0x002: case 0x102: case 0x202: /* NROM or BNROM */ + mapperSync = sync_BNROM; + Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); + break; + case 0x003: case 0x103: case 0x203: + mapperSync = sync_CNROM; + Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); + break; + case 0x004: case 0x101: case 0x201: case 0x209: /* MMC3 or Namco 118 */ + mapperSync = sync_TxROM; + MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, NULL); + if (clear) MMC3_write(0xA000, reg[4] &0x04? 0: 1); + break; + case 0x10E: case 0x20E: /* MMC3 with single-screen mirroring. 239-in-1's Goal! Two has a screen where MMC3 scanline counter emulation fails. */ + mapperSync = sync_TxSROM; + MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, NULL); + break; + case 0x006: + mapperSync = sync_VRC4; + VRC4_activate(clear, sync, 0x42, 0x84, 1, NULL, NULL, NULL, NULL, NULL); + break; + case 0x007: case 0x112: case 0x212: + mapperSync = sync_VRC4; + VRC2_activate(clear, sync, 0x02, 0x01, NULL, Mapper22_getCHRBank, NULL, NULL); + break; + case 0x008: case 0x118: case 0x218: + mapperSync = sync_VRC4; + VRC4_activate(clear, sync, 0x05, 0x0A, 1, NULL, NULL, NULL, NULL, NULL); + break; + case 0x009: case 0x110: + mapperSync = sync_VRC6; + VRC6_activate(clear, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); + break; + case 0x00A: case 0x115: case 0x215: + mapperSync = sync_VRC4; + VRC4_activate(clear, sync, 0x0A, 0x05, 1, NULL, NULL, NULL, NULL, NULL); + break; + case 0x00B: + mapperSync = sync_VRC6; + VRC6_activate(clear, sync, 0x02, 0x01, NULL, NULL, NULL, NULL); + break; + case 0x00C: + mapperSync = sync_VRC3; + VRC3_activate(clear, sync); + break; + case 0x00D: + mapperSync = sync_VRC7; + VRC7_activate(clear, sync, 0x18); + break; + case 0x00E: + mapperSync = sync_CNROM_Konami; + Latch_activate(clear, sync, 0x6000, 0x7FFF, NULL); + break; + case 0x104: case 0x204: + mapperSync = sync_AxROM; + Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); + break; + case 0x106: case 0x206: + mapperSync = sync_SNROM; + MMC1_activate(clear, sync, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL); + break; + case 0x107: case 0x208: + mapperSync = sync_SUROM; + MMC1_activate(clear, sync, MMC1_TYPE_MMC1B, SUROM_getPRGBank, NULL, NULL, NULL); + break; + case 0x108: + mapperSync = sync_GNROM; + Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); + break; + case 0x109: + mapperSync = sync_PNROM; + MMC2_activate(clear, sync); + break; + case 0x10A: case 0x20A: + mapperSync = sync_TxROM; + MMC3_activate(clear, sync, MMC3_TYPE_MMC6, NULL, NULL, NULL, NULL); + break; + case 0x10B: case 0x20B: + mapperSync = sync_152; + Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); + break; + case 0x10F: + mapperSync = sync_PT8154; + PT8154_activate(clear, sync); + break; + case 0x119: + mapperSync = sync_QJ; + QJ_activate(clear, sync); + break; + case 0x11A: case 0x21A: + mapperSync = sync_VRC1; + VRC1_activate(clear, sync); + break; + case 0x301: + mapperSync = sync_H3001; + H3001_activate(clear, sync); + break; + case 0x401: + mapperSync = sync_TC3294; + TC3294_activate(clear, sync); + break; + default: + break; + } + } else { + SetWriteHandler(0x5000, 0x5FFF, writeReg); + SetReadHandler(0x8000, 0xFFFF, flashrom_read); + SetWriteHandler(0x8000, 0xFFFF, writeFlash); + mapperSync = sync_supervisor; + PPU_hook = NULL; + MapIRQHook =flashrom_cpuCycle; + GameHBIRQHook = NULL; + sync(); + } +} + +static void power() { + reg[0] = reg[1] = reg[2] = reg[3] = reg[4] = reg[5] = reg[6] = reg[7] = 0; + applyMode(1); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void stateRestore(int version) { + applyMode(0); +} + +void Mapper446_Init(CartInfo *info) { + submapper =info->submapper; + H3001_addExState(); + Latch_addExState(); + MMC1_addExState(); + MMC2_addExState(); + MMC3_addExState(); + VRC1_addExState(); + VRC24_addExState(); + VRC3_addExState(); + VRC6_addExState(); + VRC7_addExState(); + QJ_addExState(); + PT8154_addExState(); + TC3294_addExState(); + WRAM_init(info, 32); + flashrom_init (0x01, 0x7E, 131072, 0xAAA, 0x555, 0xFFF); + info->Reset =power; + info->Power =power; + GameStateRestore =stateRestore; + AddExState(reg, 8, 0, "REGS"); +} diff --git a/src/boards/447.c b/src/boards/447.c index f97ffba..3fd1d8b 100644 --- a/src/boards/447.c +++ b/src/boards/447.c @@ -19,7 +19,8 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" +#include "wram.h" static uint8 reg; static uint8 dip; @@ -37,7 +38,7 @@ static void sync () { VRC24_syncWRAM(0); } -static int Mapper447_getPRGBank(int bank) { +static int Mapper447_getPRGBank(uint8 bank) { if (reg &4) { if (~reg &2) return VRC24_getPRGBank(bank &1) &~2 | bank &2; @@ -52,9 +53,9 @@ DECLFR(Mapper447_readPRG) { } DECLFW(Mapper447_writeReg) { - if (VRC24_misc &1 && ~reg &1) { + if (~reg &1) { reg =A &0xFF; - VRC24_Sync(); + sync(); } CartBW(A, V); } @@ -69,13 +70,12 @@ void Mapper447_power(void) { void Mapper447_reset(void) { reg =0; dip++; - VRC24_Sync(); + sync(); } void Mapper447_Init (CartInfo *info) { - VRC24_init(info, sync, 0x04, 0x08, 1, 0, 2); - VRC24_WRAMWrite =Mapper447_writeReg; - VRC24_GetPRGBank =Mapper447_getPRGBank; + VRC4_init(info, sync, 0x04, 0x08, 0, Mapper447_getPRGBank, NULL, NULL, Mapper447_writeReg, NULL ); + WRAM_init(info, 2); info->Power =Mapper447_power; info->Reset =Mapper447_reset; AddExState(Mapper447_stateRegs, ~0, 0, 0); diff --git a/src/boards/448.c b/src/boards/448.c index 4b4c850..ac2d799 100644 --- a/src/boards/448.c +++ b/src/boards/448.c @@ -19,7 +19,8 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" +#include "wram.h" static uint8 reg; @@ -30,15 +31,15 @@ static SFORMAT Mapper448_stateRegs[] ={ static void sync () { if (reg &8) { /* AOROM */ - setprg32(0x8000, VRC24_prg[0] &0x07 | reg <<2 &~0x07); - setmirror(VRC24_prg[0] &0x10? MI_1: MI_0); + setprg32(0x8000, VRC24_getPRGBank(0) &0x07 | reg <<2 &~0x07); + setmirror(VRC24_getPRGBank(0) &0x10? MI_1: MI_0); } else { if (reg &4) { /* UOROM */ - setprg16(0x8000, VRC24_prg[0] &0xF | reg <<3 &~0xF); - setprg16(0xC000, 0xF | reg <<3 &~0xF); + setprg16(0x8000, VRC24_getPRGBank(0) &0xF | reg <<3 &~0xF); + setprg16(0xC000, 0xF | reg <<3 &~0xF); } else { /* UNROM */ - setprg16(0x8000, VRC24_prg[0] &0x7 | reg <<3 &~0x7); - setprg16(0xC000, 0x7 | reg <<3 &~0x7); + setprg16(0x8000, VRC24_getPRGBank(0) &0x7 | reg <<3 &~0x7); + setprg16(0xC000, 0x7 | reg <<3 &~0x7); } VRC24_syncMirror(); } @@ -46,10 +47,8 @@ static void sync () { } DECLFW(Mapper448_writeReg) { - if (VRC24_misc &1) { - reg =A &0xFF; - VRC24_Sync(); - } + reg =A &0xFF; + sync(); CartBW(A, V); } @@ -65,12 +64,12 @@ void Mapper448_power(void) { void Mapper448_reset(void) { reg =0; - VRC24_Sync(); + sync(); } void Mapper448_Init (CartInfo *info) { - VRC24_init(info, sync, 0x04, 0x08, 1, 0, 2); - VRC24_WRAMWrite =Mapper448_writeReg; + VRC4_init(info, sync, 0x04, 0x08, 0, NULL, NULL, NULL, Mapper448_writeReg, NULL); + WRAM_init(info, 2); info->Power =Mapper448_power; info->Reset =Mapper448_reset; AddExState(Mapper448_stateRegs, ~0, 0, 0); diff --git a/src/boards/450.c b/src/boards/450.c index 990c651..f0432d8 100644 --- a/src/boards/450.c +++ b/src/boards/450.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static void sync () { VRC24_syncPRG(0x0F, VRC2_pins <<4); @@ -29,10 +29,10 @@ static void sync () { void Mapper450_reset(void) { VRC2_pins =0; - VRC24_Sync(); + sync(); } void Mapper450_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0); + VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); info->Reset =Mapper450_reset; } diff --git a/src/boards/520.c b/src/boards/520.c index e87fdd1..2484892 100644 --- a/src/boards/520.c +++ b/src/boards/520.c @@ -19,14 +19,14 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static void sync () { - VRC24_syncPRG(0x1F, VRC24_chr[0] <<2 &0x20); + VRC24_syncPRG(0x1F, VRC24_getCHRBank(0) <<2 &0x20); VRC24_syncCHR(0x07, 0x00); VRC24_syncMirror(); } void Mapper520_Init (CartInfo *info) { - VRC24_init(info, sync, 0x04, 0x08, 1, 1, 0); + VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, NULL, NULL, NULL); } diff --git a/src/boards/524.c b/src/boards/524.c index 7aff38d..5e8d0af 100644 --- a/src/boards/524.c +++ b/src/boards/524.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static uint8 irqEnabled; static uint16 irqCounter; @@ -58,7 +58,7 @@ void BTL900218_power(void) { } void BTL900218_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0); + VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); AddExState(BTL900218_stateRegs, ~0, 0, 0); info->Power =BTL900218_power; MapIRQHook =BTL900218_cpuCycle; diff --git a/src/boards/525.c b/src/boards/525.c index b60948b..f398a2f 100644 --- a/src/boards/525.c +++ b/src/boards/525.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static void sync () { VRC24_syncPRG(0x01F, 0x000); @@ -28,8 +28,8 @@ static void sync () { } DECLFW(UNLKS7021A_writeCHR) { - VRC24_chr[A &7] =V; - VRC24_Sync(); + VRC24_writeReg(0xB000 +(A <<11 &0x3000 | A <<1 &0x0002), V &0x0F); + VRC24_writeReg(0xB001 +(A <<11 &0x3000 | A <<1 &0x0002), V >>4); } void UNLKS7021A_power (void) { @@ -38,6 +38,6 @@ void UNLKS7021A_power (void) { } void UNLKS7021A_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0); + VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); info->Power =UNLKS7021A_power; } diff --git a/src/boards/527.c b/src/boards/527.c index 9b7a9ab..8f9bd69 100644 --- a/src/boards/527.c +++ b/src/boards/527.c @@ -19,14 +19,14 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static void sync () { VRC24_syncPRG(0x01F, 0x000); VRC24_syncCHR(0x1FF, 0x000); - setmirrorw(VRC24_chr[0] >>7, VRC24_chr[0] >>7, VRC24_chr[1] >>7, VRC24_chr[1] >>7); + setmirrorw(VRC24_getCHRBank(0) >>7, VRC24_getCHRBank(0) >>7, VRC24_getCHRBank(1) >>7, VRC24_getCHRBank(1) >>7); } void UNLAX40G_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0); + VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); } diff --git a/src/boards/529.c b/src/boards/529.c index cd79f5d..ff5c7a0 100644 --- a/src/boards/529.c +++ b/src/boards/529.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" #include "eeprom_93Cx6.h" static uint8 eeprom_data[256]; @@ -30,7 +30,7 @@ static SFORMAT stateRegs[] ={ }; static void sync () { - setprg16(0x8000, VRC24_prg[1]); + setprg16(0x8000, VRC24_getPRGBank(1)); setprg16(0xC000, 0xFF); VRC24_syncCHR(0x1FF, 0x000); VRC24_syncMirror(); @@ -52,7 +52,7 @@ void UNLT230_power (void) { } void UNLT230_Init (CartInfo *info) { - VRC24_init(info, sync, 0x04, 0x08, 1, 1, 0); + VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, NULL, NULL, NULL); if (info->PRGRamSaveSize) { info->Power =UNLT230_power; AddExState(stateRegs, ~0, 0, 0); diff --git a/src/boards/530.c b/src/boards/530.c index 2f7dcd6..9a2e780 100644 --- a/src/boards/530.c +++ b/src/boards/530.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static void sync () { VRC24_syncPRG(0x01F, 0x000); @@ -27,12 +27,12 @@ static void sync () { VRC24_syncMirror(); } -int UNLAX5705_getPRGBank(int bank) { +int UNLAX5705_getPRGBank(uint8 bank) { int result =VRC24_getPRGBank(bank); return result <<2 &0x8 | result >>2 &0x2 | result &~0xA; } -int UNLAX5705_getCHRBank(int bank) { +int UNLAX5705_getCHRBank(uint8 bank) { int result =VRC24_getCHRBank(bank); return result <<1 &0x40 | result >>1 &0x20 | result &~0x60; } @@ -47,8 +47,6 @@ void UNLAX5705_power (void) { } void UNLAX5705_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 1, 1, 0); + VRC4_init(info, sync, 0x01, 0x02, 1, UNLAX5705_getPRGBank, UNLAX5705_getCHRBank, NULL, NULL, NULL); info->Power =UNLAX5705_power; - VRC24_GetPRGBank =UNLAX5705_getPRGBank; - VRC24_GetCHRBank =UNLAX5705_getCHRBank; } diff --git a/src/boards/542.c b/src/boards/542.c index 5e7ed8c..3dcb258 100644 --- a/src/boards/542.c +++ b/src/boards/542.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static uint8 reg; @@ -39,7 +39,7 @@ static void sync () { DECLFW(Mapper542_writeExtra) { if (A &0x800) { reg =A >>12; - VRC24_Sync(); + sync(); } else VRC24_writeReg(A, V); } @@ -53,7 +53,7 @@ void Mapper542_power (void) { } void Mapper542_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 1, 1, 0); + VRC4_init(info, sync, 0x01, 0x02, 1, NULL, NULL, NULL, NULL, NULL); info->Power =Mapper542_power; AddExState(stateRegs, ~0, 0, 0); SetupCartCHRMapping(0x10, NTARAM, 0x200, 1); diff --git a/src/boards/544.c b/src/boards/544.c index ec9eefe..eb5cf0a 100644 --- a/src/boards/544.c +++ b/src/boards/544.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static uint8 *CHRRAM; static uint32 CHRRAMSize; @@ -43,14 +43,14 @@ static void sync () { int bank; VRC24_syncWRAM(0); VRC24_syncPRG(0x01F, 0x000); - for (bank =0; bank <8; bank++) setchr1r((VRC24_chr[bank] &mask) ==compare? 0x10: 0x00, bank <<10, VRC24_chr[bank]); + for (bank =0; bank <8; bank++) setchr1r((VRC24_getCHRBank(bank) &mask) ==compare? 0x10: 0x00, bank <<10, VRC24_getCHRBank(bank)); setmirrorw(nt[0] &1, nt[1] &1, nt[2] &1, nt[3] &1); } static const uint8 compares[8] = { 0x28, 0x00, 0x4C, 0x64, 0x46, 0x7C, 0x04, 0xFF }; static DECLFW(Mapper544_interceptPPUWrite) { if (~RefreshAddr &0x2000) { - int bank =VRC24_chr[RefreshAddr >>10 &7]; + int bank =VRC24_getCHRBank(RefreshAddr >>10 &7); if (bank &0x80) { if (bank &0x10) { mask =0x00; @@ -60,13 +60,13 @@ static DECLFW(Mapper544_interceptPPUWrite) { mask =bank &0x40? 0xFE: 0xFC; compare =compares[index]; } - VRC24_Sync(); + sync(); } } writePPU(A, V); } -int Mapper544_getPRGBank(int bank) { +int Mapper544_getPRGBank(uint8 bank) { return bank ==2? prg: VRC24_getPRGBank(bank); } @@ -75,7 +75,7 @@ DECLFW(Mapper544_externalSelect) { nt[A &3] =V; else prg =V; - VRC24_Sync(); + sync(); } @@ -98,11 +98,9 @@ void Mapper544_close(void) { } void Mapper544_Init (CartInfo *info) { - VRC24_init(info, sync, 0x400, 0x800, 1, 1, 0); + VRC4_init(info, sync, 0x400, 0x800, 1, Mapper544_getPRGBank, NULL, NULL, NULL, Mapper544_externalSelect); info->Power =Mapper544_power; info->Close =Mapper544_close; - VRC24_GetPRGBank =Mapper544_getPRGBank; - VRC24_ExternalSelect =Mapper544_externalSelect; AddExState(stateRegs, ~0, 0, 0); CHRRAMSize =info->CHRRamSize +info->CHRRamSaveSize; diff --git a/src/boards/559.c b/src/boards/559.c index a9a2c15..9b725a3 100644 --- a/src/boards/559.c +++ b/src/boards/559.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static uint8 nt[4]; static uint8 prg; @@ -38,7 +38,7 @@ static void sync () { setmirrorw(nt[0] &1, nt[1] &1, nt[2] &1, nt[3] &1); } -int Mapper559_getPRGBank(int bank) { +int Mapper559_getPRGBank(uint8 bank) { return bank ==2? prg: VRC24_getPRGBank(bank); } @@ -47,7 +47,7 @@ DECLFW(Mapper559_externalSelect) { nt[A &3] =V; else prg =V; - VRC24_Sync(); + sync(); } DECLFW(Mapper559_nibblizeData) { @@ -63,9 +63,7 @@ void Mapper559_power (void) { } void Mapper559_Init (CartInfo *info) { - VRC24_init(info, sync, 0x400, 0x800, 1, 1, 0); + VRC4_init(info, sync, 0x400, 0x800, 1, Mapper559_getPRGBank, NULL, NULL, NULL, Mapper559_externalSelect); info->Power =Mapper559_power; - VRC24_GetPRGBank =Mapper559_getPRGBank; - VRC24_ExternalSelect =Mapper559_externalSelect; AddExState(stateRegs, ~0, 0, 0); } diff --git a/src/boards/563.c b/src/boards/563.c index a074442..a67be11 100644 --- a/src/boards/563.c +++ b/src/boards/563.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static uint8 irqEnabled; static uint8 irqCounter; @@ -56,7 +56,7 @@ void Mapper563_power(void) { } void Mapper563_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0); + VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); AddExState(Mapper563_stateRegs, ~0, 0, 0); info->Power =Mapper563_power; GameHBIRQHook = Mapper563_scanline; diff --git a/src/boards/asic_h3001.c b/src/boards/asic_h3001.c new file mode 100644 index 0000000..308b45b --- /dev/null +++ b/src/boards/asic_h3001.c @@ -0,0 +1,165 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_h3001.h" + +static void (*H3001_cbSync)(); +static uint8 H3001_prg[2]; +static uint8 H3001_chr[8]; +static uint8 H3001_layout; +static uint8 H3001_nt; +static uint8 H3001_irq; +static uint16 H3001_reload; +static uint16 H3001_count; + +static SFORMAT H3001_state[] = { + { H3001_prg, 2, "H31P" }, + { H3001_chr, 8, "H31C" }, + {&H3001_layout, 4, "H31L" }, + {&H3001_nt, 4, "H31M" }, + {&H3001_irq, 4, "H31N" }, + {&H3001_reload, 2, "H31R" }, + {&H3001_count, 2, "H31T" }, + { 0 } +}; + +static int H3001_getPRGBank (uint8 bank) { + if (H3001_layout &0x80 && ~bank &1) bank ^= 2; + return bank &2? 0xFE | bank &1: H3001_prg[bank &1]; +} + +void H3001_syncPRG (int AND, int OR) { + setprg8(0x8000, H3001_getPRGBank(0) &AND |OR); + setprg8(0xA000, H3001_getPRGBank(1) &AND |OR); + setprg8(0xC000, H3001_getPRGBank(2) &AND |OR); + setprg8(0xE000, H3001_getPRGBank(3) &AND |OR); +} + +void H3001_syncCHR (int AND, int OR) { + setchr1(0x0000, H3001_chr[0]); + setchr1(0x0400, H3001_chr[1]); + setchr1(0x0800, H3001_chr[2]); + setchr1(0x0C00, H3001_chr[3]); + setchr1(0x1000, H3001_chr[4]); + setchr1(0x1400, H3001_chr[5]); + setchr1(0x1800, H3001_chr[6]); + setchr1(0x1C00, H3001_chr[7]); +} + +void H3001_syncMirror () { + setmirror(H3001_nt &0x40? (H3001_nt &0x80? MI_1: MI_0): H3001_nt &0x80? MI_H: MI_V); +} + +DECLFW(H3001_write) { + switch(A >>12 &7) { + case 0: case 2: + H3001_prg[A >>13 &1] = V; + H3001_cbSync(); + break; + case 1: + switch(A &7) { + case 0: + H3001_layout = V; + H3001_cbSync(); + break; + case 1: + H3001_nt = V; + H3001_cbSync(); + break; + case 3: + H3001_irq = V; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 4: + H3001_count = H3001_reload; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 5: + H3001_reload = H3001_reload &0x00FF | V <<8; + break; + case 6: + H3001_reload = H3001_reload &0xFF00 | V; + break; + } + break; + case 3: + H3001_chr[A &7] = V; + H3001_cbSync(); + break; + } +} + +void FP_FASTAPASS(1) H3001_cpuCycle (int a) { + while (a--) if (H3001_irq &0x80 && !--H3001_count) { + X6502_IRQBegin(FCEU_IQEXT); + H3001_irq = 0; + } +} + +static void H3001_clear () { + int i; + for (i = 0; i < 2; i++) H3001_prg[i] = i; + for (i = 0; i < 8; i++) H3001_chr[i] = i; + H3001_layout = H3001_nt = H3001_irq = 0; + H3001_reload = H3001_count = 0; + H3001_cbSync(); +} + +static void H3001_setHandlers () { + SetReadHandler (0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xBFFF, H3001_write); + MapIRQHook =H3001_cpuCycle; +} + +static void H3001_configure (void (*sync)()) { + H3001_cbSync = sync; +} + +void H3001_activate (uint8 clear, void (*sync)()) { + H3001_configure(sync); + H3001_setHandlers(); + if (clear) + H3001_clear(); + else + H3001_cbSync(); + +} + +void H3001_addExState () { + AddExState(H3001_state, ~0, 0, 0); +} + +void H3001_restore (int version) { + H3001_cbSync(); +} + +void H3001_power () { + H3001_setHandlers(); + H3001_clear(); +} + +void H3001_init (CartInfo *info, void (*sync)()) { + H3001_addExState(); + H3001_configure(sync); + info->Power = H3001_power; + info->Reset = H3001_cbSync; + GameStateRestore = H3001_cbSync; +} diff --git a/src/boards/asic_h3001.h b/src/boards/asic_h3001.h new file mode 100644 index 0000000..97dfd58 --- /dev/null +++ b/src/boards/asic_h3001.h @@ -0,0 +1,34 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_H3001_H +#define _ASIC_H3001_H + +void H3001_syncPRG (int, int); +void H3001_syncCHR (int, int); +void H3001_syncMirror (); +DECLFW (H3001_write); +void H3001_activate (uint8, void (*)()); +void H3001_addExState (); +void H3001_restore (int); +void H3001_power (); +void H3001_init (CartInfo *, void (*)()); + +#endif diff --git a/src/boards/asic_latch.c b/src/boards/asic_latch.c new file mode 100644 index 0000000..03df1d2 --- /dev/null +++ b/src/boards/asic_latch.c @@ -0,0 +1,89 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void (*Latch_cbSync)(); +static uint16 Latch_from, Latch_to; +static void (*Latch_cbWrite)(uint16*, uint8*, uint8); +uint16 Latch_address; +uint8 Latch_data; + +static SFORMAT Latch_state[] = { + {&Latch_address, 2, "LATA" }, + {&Latch_data, 1, "LATD" }, + { 0 } +}; + +DECLFW(Latch_write) { + uint16 newAddress = A &0xFFFF; + if (Latch_cbWrite) Latch_cbWrite(&newAddress, &V, CartBR(A)); + Latch_address = A; + Latch_data = V; + Latch_cbSync(); +} + +static void Latch_clear () { + Latch_address = 0; + Latch_data = 0; + Latch_cbSync(); +} + +static void Latch_setHandlers() { + SetWriteHandler(Latch_from, Latch_to, Latch_write); +} + +static void Latch_configure (void (*sync)(), uint16 from, uint16 to, void (*write)(uint16*, uint8*, uint8)) { + Latch_cbSync = sync; + Latch_from = from; + Latch_to = to; + Latch_cbWrite = write; +} + +void Latch_activate (uint8 clear, void (*sync)(), uint16 from, uint16 to, void (*write)(uint16*, uint8*, uint8)) { + Latch_configure(sync, from, to, write); + Latch_setHandlers(); + if (clear) + Latch_clear(); + else + Latch_cbSync(); +} + +void Latch_addExState () { + AddExState(Latch_state, ~0, 0, 0); +} + +void Latch_restore (int version) { + Latch_cbSync(); +} + +void Latch_power () { + Latch_setHandlers(); + Latch_clear(); +} + +void Latch_init (CartInfo *info, void (*sync)(), uint16 from, uint16 to, void (*write)(uint16*, uint8*, uint8)) { + Latch_addExState(); + Latch_configure(sync, from, to, write); + info->Power = Latch_power; + info->Reset = Latch_cbSync; + GameStateRestore = Latch_restore; +} diff --git a/src/boards/asic_latch.h b/src/boards/asic_latch.h new file mode 100644 index 0000000..07e4c87 --- /dev/null +++ b/src/boards/asic_latch.h @@ -0,0 +1,35 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_LATCH_H +#define _ASIC_LATCH_H + +extern uint16 Latch_address; +extern uint8 Latch_data; + +DECLFW (Latch_write); +void Latch_addExState (); +void Latch_restore (int); +void Latch_power (); +void Latch_activate (uint8, void (*)(), uint16, uint16, void (*)(uint16*, uint8*, uint8)); +void Latch6_activate (uint8, void (*)(), uint16, uint16, void (*)(uint16*, uint8*, uint8)); +void Latch_init (CartInfo *, void (*)(), uint16, uint16, void (*)(uint16*, uint8*, uint8)); + +#endif diff --git a/src/boards/asic_mmc1.c b/src/boards/asic_mmc1.c new file mode 100644 index 0000000..91fad25 --- /dev/null +++ b/src/boards/asic_mmc1.c @@ -0,0 +1,169 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_mmc1.h" + +static void (*MMC1_cbSync)(); +static int (*MMC1_cbGetPRGBank)(uint8); +static int (*MMC1_cbGetCHRBank)(uint8); +static DECLFR ((*MMC1_cbReadWRAM)); +static DECLFW ((*MMC1_cbWriteWRAM)); +static uint8 MMC1_type; +static uint8 MMC1_bits; +static uint8 MMC1_shift; +static uint8 MMC1_filter; +static uint8 MMC1_reg[4]; + +static SFORMAT MMC1_state[] = { + { MMC1_reg, 4, "MC1R" }, + {&MMC1_bits, 1, "MC1B" }, + {&MMC1_shift, 1, "MC1S" }, + {&MMC1_filter, 1, "MC1F" }, + { 0 } +}; + +void MMC1_syncWRAM (int OR) { + if (PRGsize[0x10]) setprg8r(0x10, 0x6000, OR); +} + +int MMC1_getPRGBank (uint8 bank) { + int result; + if (MMC1_reg[0] &0x08) + result = MMC1_reg[0] &0x04? (MMC1_reg[3] |bank*0xF): (MMC1_reg[3] &bank*0xF); + else + result = MMC1_reg[3] &~1 |bank; + + if (MMC1_reg[3] &0x10 && MMC1_type == MMC1_TYPE_MMC1A) + return result &0x07 | MMC1_reg[3] &0x08; + else + return result &0x0F; +} + +int MMC1_getCHRBank (uint8 bank) { + if (MMC1_reg[0] &0x10) + return MMC1_reg[1 +bank]; + else + return MMC1_reg[1] &~1 |bank; +} + +DECLFR(MMC1_readWRAM) { + if (MMC1_type == MMC1_TYPE_MMC1A || ~MMC1_reg[3] &0x10) + return MMC1_cbReadWRAM? MMC1_cbReadWRAM(A): CartBR(A); + else + return A >>8; +} + +DECLFW(MMC1_writeWRAM) { + if (MMC1_type == MMC1_TYPE_MMC1A || ~MMC1_reg[3] &0x10) { + CartBW(A, V); + if (MMC1_cbWriteWRAM) MMC1_cbWriteWRAM(A, V); + } +} + +void MMC1_syncPRG (int AND, int OR) { + setprg16(0x8000, MMC1_cbGetPRGBank(0) &AND |OR); + setprg16(0xC000, MMC1_cbGetPRGBank(1) &AND |OR); +} + +void MMC1_syncCHR (int AND, int OR) { + setchr4(0x0000, MMC1_cbGetCHRBank(0) &AND |OR); + setchr4(0x1000, MMC1_cbGetCHRBank(1) &AND |OR); +} + +void MMC1_syncMirror () { + setmirror(MMC1_reg[0] &2? (MMC1_reg[0] &1? MI_H: MI_V): (MMC1_reg[0] &1? MI_1: MI_0)); +} + +void FP_FASTAPASS(1) MMC1_cpuCycle(int a) { + while (a--) if (MMC1_filter) MMC1_filter--; +} + +DECLFW(MMC1_write) { + if (V &0x80) { + MMC1_reg[0] |= 0x0C; + MMC1_shift = 0; + MMC1_bits = 0; + MMC1_cbSync(); + } else + if (!MMC1_filter) { + MMC1_shift |= (V &1) <>13 &3] = MMC1_shift; + MMC1_shift = 0; + MMC1_bits = 0; + MMC1_cbSync(); + } + } + MMC1_filter = 2; +} + +static void MMC1_clear() { + MMC1_reg[0] = 0x0C; MMC1_reg[1] = 0; MMC1_reg[2] = 2; MMC1_reg[3] = 0; + MMC1_bits = 0; MMC1_shift = 0; MMC1_filter = 0; + MMC1_cbSync(); +} + +static void MMC1_setHandlers () { + SetReadHandler (0x6000, 0x7FFF, MMC1_readWRAM); + SetWriteHandler(0x6000, 0x7FFF, MMC1_writeWRAM); + SetReadHandler (0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, MMC1_write); + MapIRQHook = MMC1_cpuCycle; +} + +static void MMC1_configure (void (*sync)(), uint8 type, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) { + MMC1_type = type; + MMC1_cbSync = sync; + MMC1_cbGetPRGBank = prg? prg: MMC1_getPRGBank; + MMC1_cbGetCHRBank = chr? chr: MMC1_getCHRBank; + MMC1_cbReadWRAM = read; + MMC1_cbWriteWRAM = write; +} + +void MMC1_activate (uint8 clear, void (*sync)(), uint8 type, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) { + MMC1_configure(sync, type, prg, chr, read, write); + MMC1_setHandlers(); + if (clear) + MMC1_clear(); + else + MMC1_cbSync(); +} + +void MMC1_addExState () { + AddExState(MMC1_state, ~0, 0, 0); +} + +void MMC1_restore (int version) { + MMC1_cbSync(); +} + +void MMC1_power () { + MMC1_setHandlers(); + MMC1_clear(); +} + +void MMC1_init (CartInfo *info, void (*sync)(), uint8 type, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) { + MMC1_addExState(); + MMC1_configure(sync, type, prg, chr, read, write); + info->Power = MMC1_power; + info->Reset = MMC1_cbSync; + GameStateRestore = MMC1_restore; +} diff --git a/src/boards/asic_mmc1.h b/src/boards/asic_mmc1.h new file mode 100644 index 0000000..25f26a3 --- /dev/null +++ b/src/boards/asic_mmc1.h @@ -0,0 +1,41 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_MMC1_H +#define _ASIC_MMC1_H + +#define MMC1_TYPE_MMC1A 0 +#define MMC1_TYPE_MMC1B 1 + +void MMC1_syncWRAM (int); +int MMC1_getPRGBank (uint8); +int MMC1_getCHRBank (uint8); +void MMC1_syncPRG (int, int); +void MMC1_syncCHR (int, int); +void MMC1_syncMirror (); +void FP_FASTAPASS(1) MMC1_cpuCycle(int); +DECLFW (MMC1_write); +void MMC1_addExState (); +void MMC1_restore (int); +void MMC1_power (); +void MMC1_activate (uint8, void (*)(), uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*))); +void MMC1_init (CartInfo *, void (*)(), uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*))); + +#endif diff --git a/src/boards/asic_mmc2.c b/src/boards/asic_mmc2.c new file mode 100644 index 0000000..52f494f --- /dev/null +++ b/src/boards/asic_mmc2.c @@ -0,0 +1,108 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_mmc2.h" + +static void (*MMC2_cbSync)(); +static uint8 MMC2_reg[6]; +static uint8 MMC2_latch[2]; + +static SFORMAT MMC2_state[] = { + { MMC2_reg, 6, "MC2R" }, + { MMC2_latch, 2, "MC2S" }, + { 0 } +}; + +static void (*MMC2_cbSync)(); + +void MMC2_syncPRG (int AND, int OR) { + setprg8(0x8000, MMC2_reg[0] &AND |OR); + setprg8(0xA000, 0xD &AND |OR); + setprg8(0xC000, 0xE &AND |OR); + setprg8(0xE000, 0xF &AND |OR); +} + +void MMC2_syncCHR (int AND, int OR) { + setchr4(0x0000, MMC2_reg[1 +MMC2_latch[0]] &AND |OR); + setchr4(0x1000, MMC2_reg[3 +MMC2_latch[1]] &AND |OR); +} + +void MMC2_syncMirror () { + setmirror(MMC2_reg[5] &1? MI_H: MI_V); +} + +static void FP_FASTAPASS(1) MMC2_trapPPUAddressChange (uint32 A) { + if ((A &0x2FF0) == 0xFD0 || (A &0x2FF0) == 0xFE0) { + MMC2_latch[A >>12 &1] = A >>5 &1; + MMC2_cbSync(); + } +} + +DECLFW(MMC2_write) { + MMC2_reg[(A >>12) -0xA] = V; + MMC2_cbSync(); +} + +static void MMC2_clear () { + MMC2_reg[0] = 0; MMC2_reg[1] = 0; MMC2_reg[2] = 2; MMC2_reg[3] = 0; MMC2_reg[4] = 0; MMC2_reg[5] = 0; + MMC2_latch[0] = 0; MMC2_latch[1] = 0; + MMC2_cbSync(); +} + +static void MMC2_setHandlers() { + SetReadHandler (0x8000, 0xFFFF, CartBR); + SetWriteHandler(0xA000, 0xFFFF, MMC2_write); + PPU_hook = MMC2_trapPPUAddressChange; +} + +static void MMC2_configure (void (*sync)()) { + MMC2_cbSync = sync; +} + +void MMC2_activate (uint8 clear, void (*sync)()) { + MMC2_configure(sync); + MMC2_setHandlers(); + if (clear) + MMC2_clear(); + else + MMC2_cbSync(); +} + +void MMC2_addExState () { + AddExState(MMC2_state, ~0, 0, 0); +} + +void MMC2_restore (int version) { + MMC2_cbSync(); +} + +void MMC2_power () { + MMC2_setHandlers(); + MMC2_clear(); +} + +void MMC2_init (CartInfo *info, void (*sync)()) { + MMC2_addExState(); + MMC2_configure(sync); + info->Power = MMC2_power; + info->Reset = MMC2_cbSync; + GameStateRestore = MMC2_restore; +} diff --git a/src/boards/asic_mmc2.h b/src/boards/asic_mmc2.h new file mode 100644 index 0000000..09d9036 --- /dev/null +++ b/src/boards/asic_mmc2.h @@ -0,0 +1,34 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_MMC2_H +#define _ASIC_MMC2_H + +void MMC2_syncPRG (int, int); +void MMC2_syncCHR (int, int); +void MMC2_syncMirror (); +DECLFW (MMC2_write); +void MMC2_power (); +void MMC2_restore (int); +void MMC2_addExState (); +void MMC2_activate (uint8, void (*)()); +void MMC2_init (CartInfo *, void (*)()); + +#endif diff --git a/src/boards/asic_mmc3.c b/src/boards/asic_mmc3.c new file mode 100644 index 0000000..2b8b4ea --- /dev/null +++ b/src/boards/asic_mmc3.c @@ -0,0 +1,165 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static void (*MMC3_cbSync)(); +static int (*MMC3_cbGetPRGBank)(uint8); +static int (*MMC3_cbGetCHRBank)(uint8); +static DECLFR ((*MMC3_cbReadWRAM)); +static DECLFW ((*MMC3_cbWriteWRAM)); +static uint8 MMC3_type; +static uint8 MMC3_index; +static uint8 MMC3_reg[8]; +static uint8 MMC3_mirroring; +static uint8 MMC3_wramControl; +static uint8 MMC3_reloadValue; +static uint8 MMC3_reloadRequest; +static uint8 MMC3_irqEnable; +static uint8 MMC3_counter; + +static SFORMAT MMC3_state[] = { + { MMC3_reg, 8, "M3GS" }, + {&MMC3_index, 1, "M3IX" }, + {&MMC3_mirroring, 1, "M3NT" }, + {&MMC3_wramControl, 1, "M3WR" }, + {&MMC3_reloadRequest, 1, "M3IR" }, + {&MMC3_counter, 1, "M3IC" }, + {&MMC3_reloadValue, 1, "M3IL" }, + {&MMC3_irqEnable, 1, "M3IA" }, + { 0 } +}; + +void MMC3_syncWRAM (int OR) { + if (PRGsize[0x10]) setprg8r(0x10, 0x6000, OR); +} + +int MMC3_getPRGBank (uint8 bank) { + if (MMC3_index &0x40 && ~bank &1) bank ^= 2; + return bank &2? 0xFE | bank &1: MMC3_reg[6 | bank &1]; +} + +int MMC3_getCHRBank (uint8 bank) { + if (MMC3_index &0x80) bank ^= 4; + return bank &4? MMC3_reg[bank -2]: MMC3_reg[bank >>1] &~1 | bank &1; +} + +DECLFR(MMC3_readWRAM) { + if (MMC3_wramControl &0x80 || MMC3_type == MMC3_TYPE_AX5202P || MMC3_type == MMC3_TYPE_MMC6) + return MMC3_cbReadWRAM? MMC3_cbReadWRAM(A): CartBR(A); + else + return A >>8; +} + +DECLFW(MMC3_writeWRAM) { + if ((MMC3_wramControl &0x80 || MMC3_type == MMC3_TYPE_AX5202P) && ~MMC3_wramControl &0x40 || MMC3_type == MMC3_TYPE_MMC6) { + CartBW(A, V); + if (MMC3_cbWriteWRAM) MMC3_cbWriteWRAM(A, V); + } +} + +void MMC3_syncPRG (int AND, int OR) { + int bank; + for (bank = 0; bank < 4; bank++) setprg8(0x8000 | bank <<13, MMC3_cbGetPRGBank(bank) &AND |OR); +} + +void MMC3_syncCHR (int AND, int OR) { + int bank; + for (bank = 0; bank < 8; bank++) setchr1(bank <<10, MMC3_cbGetCHRBank(bank) &AND |OR); +} + +void MMC3_syncMirror () { + setmirror(MMC3_mirroring &1? MI_H: MI_V); +} + +void MMC3_clockCounter () { + uint8 prevCounter = MMC3_counter; + MMC3_counter = MMC3_reloadRequest || !MMC3_counter? MMC3_reloadValue: --MMC3_counter; + if ((prevCounter || MMC3_type != MMC3_TYPE_NEC || MMC3_reloadRequest) && !MMC3_counter && MMC3_irqEnable) X6502_IRQBegin(FCEU_IQEXT); + MMC3_reloadRequest = 0; +} + +DECLFW(MMC3_write) { + switch(A &0xE001) { + case 0x8000: MMC3_index = V; break; + case 0x8001: MMC3_reg[MMC3_index &7] = V; break; + case 0xA000: MMC3_mirroring = V; break; + case 0xA001: MMC3_wramControl = V; break; + case 0xC000: MMC3_reloadValue = V; break; + case 0xC001: MMC3_reloadRequest = 1; MMC3_counter = 0; break; + case 0xE000: X6502_IRQEnd(FCEU_IQEXT); /* Fall-through */ + case 0xE001: MMC3_irqEnable = A &1; break; + } + if (A <0xC000) MMC3_cbSync(); +} + +static void MMC3_clear () { + MMC3_reg[0] = 0; MMC3_reg[1] = 2; MMC3_reg[2] = 4; MMC3_reg[3] = 5; MMC3_reg[4] = 6; MMC3_reg[5] = 7; MMC3_reg[6] = 0; MMC3_reg[7] = 1; + MMC3_index = MMC3_mirroring = MMC3_wramControl = MMC3_reloadValue = MMC3_reloadRequest = MMC3_irqEnable = MMC3_counter = 0; + MMC3_cbSync(); +} + +static void MMC3_setHandlers () { + SetReadHandler (0x6000, 0x7FFF, MMC3_readWRAM); + SetWriteHandler(0x6000, 0x7FFF, MMC3_writeWRAM); + SetReadHandler (0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, MMC3_write); + GameHBIRQHook = MMC3_clockCounter; +} + +static void MMC3_configure (void (*sync)(), uint8 type, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) { + MMC3_type = type; + MMC3_cbSync = sync; + MMC3_cbGetPRGBank = prg? prg: MMC3_getPRGBank; + MMC3_cbGetCHRBank = chr? chr: MMC3_getCHRBank; + MMC3_cbReadWRAM = read; + MMC3_cbWriteWRAM = write; +} + +void MMC3_activate (uint8 clear, void (*sync)(), uint8 type, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) { + MMC3_configure(sync, type, prg, chr, read, write); + MMC3_setHandlers(); + if (clear) + MMC3_clear(); + else + MMC3_cbSync(); +} + +void MMC3_addExState () { + AddExState(MMC3_state, ~0, 0, 0); +} + +void MMC3_restore (int version) { + MMC3_cbSync(); +} + +void MMC3_power () { + MMC3_setHandlers(); + MMC3_clear(); +} + +void MMC3_init (CartInfo *info, void (*sync)(), uint8 type, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) { + MMC3_addExState(); + MMC3_configure(sync, type, prg, chr, read, write); + info->Power = MMC3_power; + info->Reset = MMC3_cbSync; + GameStateRestore = MMC3_restore; +} diff --git a/src/boards/asic_mmc3.h b/src/boards/asic_mmc3.h new file mode 100644 index 0000000..0f78399 --- /dev/null +++ b/src/boards/asic_mmc3.h @@ -0,0 +1,44 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_MMC3_H +#define _ASIC_MMC3_H + +#define MMC3_TYPE_NEC 0 /* C000=00 causes single IRQ */ +#define MMC3_TYPE_SHARP 1 /* C000=00 causes continuous IRQs */ +#define MMC3_TYPE_ACCLAIM 2 /* No difference to SHARP with FCEU*'s PPU implementation */ +#define MMC3_TYPE_AX5202P 3 /* WRAM always enabled */ +#define MMC3_TYPE_MMC6 4 /* 1 KiB of built-in WRAM */ + +void MMC3_syncWRAM (int); +int MMC3_getPRGBank (uint8); +int MMC3_getCHRBank (uint8); +void MMC3_syncPRG (int, int); +void MMC3_syncCHR (int, int); +void MMC3_syncMirror (); +void MMC3_clockCounter (); +DECLFW (MMC3_write); +void MMC3_activate (uint8, void (*)(), uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*))); +void MMC3_addExState(); +void MMC3_restore (int); +void MMC3_power (); +void MMC3_init (CartInfo *, void (*)(), uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*))); + +#endif diff --git a/src/boards/asic_pt8154.c b/src/boards/asic_pt8154.c new file mode 100644 index 0000000..cdcda37 --- /dev/null +++ b/src/boards/asic_pt8154.c @@ -0,0 +1,103 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_PT8154.h" +#include "asic_mmc3.h" + +static void (*PT8154_cbSync)(); +static uint8 PT8154_reg; + +static SFORMAT PT8154_state[] = { + {&PT8154_reg, 1, "189R" }, + { 0 } +}; + +void PT8154_syncPRG (int AND, int OR) { + AND >>=2; + OR >>=2; + setprg32(0x8000, PT8154_reg &AND | OR &~AND); +} + +void PT8154_syncCHR (int AND, int OR) { + MMC3_syncCHR(AND, OR &~AND); +} + +void PT8154_syncMirror () { + MMC3_syncMirror(); +} + +DECLFW(PT8154_writeExtra) { + if (A &0x100) { + PT8154_reg = V >>4; + PT8154_cbSync(); + } +} + +DECLFW(PT8154_writeWRAM) { + PT8154_reg = A; + PT8154_cbSync(); +} + +static void PT8154_clear () { + PT8154_reg = 0; + PT8154_cbSync(); +} + +static void PT8154_setHandlers () { + SetWriteHandler(0x4020, 0x5FFF, PT8154_writeExtra); +} + +static void PT8154_configure (void (*sync)()) { + PT8154_cbSync = sync; +} + +void PT8154_activate (uint8 clear, void (*sync)()) { + MMC3_activate(clear, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, PT8154_writeWRAM); + PT8154_configure(sync); + PT8154_setHandlers(); + if (clear) + PT8154_clear(); + else + PT8154_cbSync(); +} + +void PT8154_addExState () { + AddExState(PT8154_state, ~0, 0, 0); +} + +void PT8154_restore (int version) { + PT8154_cbSync(); +} + +void PT8154_power () { + MMC3_power(); + PT8154_setHandlers(); + PT8154_clear(); +} + +void PT8154_init (CartInfo *info, void (*sync)()) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, PT8154_writeWRAM); + PT8154_addExState(); + PT8154_configure(PT8154_cbSync); + info->Power = PT8154_power; + info->Reset = PT8154_cbSync; + GameStateRestore = PT8154_restore; +} diff --git a/src/boards/asic_pt8154.h b/src/boards/asic_pt8154.h new file mode 100644 index 0000000..f5c9dda --- /dev/null +++ b/src/boards/asic_pt8154.h @@ -0,0 +1,35 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_PT8154_H +#define _ASIC_PT8154_H + +void PT8154_syncPRG (int, int); +void PT8154_syncCHR (int, int); +void PT8154_syncMirror (); +DECLFW (PT8154_writeExtra); +DECLFW (PT8154_writeWRAM); +void PT8154_activate (uint8, void (*)()); +void PT8154_addExState (); +void PT8154_restore (int); +void PT8154_power (); +void PT8154_init (CartInfo *, void (*)()); + +#endif diff --git a/src/boards/asic_qj.c b/src/boards/asic_qj.c new file mode 100644 index 0000000..7c72557 --- /dev/null +++ b/src/boards/asic_qj.c @@ -0,0 +1,93 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_QJ.h" +#include "asic_mmc3.h" + +static void (*QJ_cbSync)(); +static uint8 QJ_reg; + +static SFORMAT QJ_state[] = { + {&QJ_reg, 1, "QJRG" }, + { 0 } +}; + +void QJ_syncPRG (int AND, int OR) { + MMC3_syncPRG(0x0F &AND, QJ_reg <<4 &AND | OR &~AND); +} + +void QJ_syncCHR (int AND, int OR) { + MMC3_syncCHR(0x7F &AND, QJ_reg <<7 &AND | OR &~AND); +} + +void QJ_syncMirror () { + MMC3_syncMirror(); +} + +DECLFW(QJ_writeWRAM) { + QJ_reg = V; + QJ_cbSync(); +} + +static void QJ_clear () { + QJ_reg = 0; + QJ_cbSync(); +} + +static void QJ_setHandlers () { +} + +static void QJ_configure (void (*sync)()) { + QJ_cbSync = sync; +} + +void QJ_activate (uint8 clear, void (*sync)()) { + MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, QJ_writeWRAM); + QJ_configure(sync); + QJ_setHandlers(); + if (clear) + QJ_clear(); + else + QJ_cbSync(); +} + +void QJ_addExState () { + AddExState(QJ_state, ~0, 0, 0); +} + +void QJ_restore (int version) { + QJ_cbSync(); +} + +void QJ_power () { + MMC3_power(); + QJ_setHandlers(); + QJ_clear(); +} + +void QJ_init (CartInfo *info, void (*sync)()) { + MMC3_addExState(); + QJ_addExState(); + QJ_configure(QJ_cbSync); + info->Power = QJ_power; + info->Reset = QJ_cbSync; + GameStateRestore = QJ_restore; +} diff --git a/src/boards/asic_qj.h b/src/boards/asic_qj.h new file mode 100644 index 0000000..0e8eddc --- /dev/null +++ b/src/boards/asic_qj.h @@ -0,0 +1,35 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_QJ_H +#define _ASIC_QJ_H + +void QJ_syncWRAM (int); +void QJ_syncPRG (int, int); +void QJ_syncCHR (int, int); +void QJ_syncMirror (); +DECLFW (QJ_write); +void QJ_activate (uint8, void (*)()); +void QJ_addExState (); +void QJ_restore (int); +void QJ_power (); +void QJ_init (CartInfo *, void (*)()); + +#endif diff --git a/src/boards/asic_tc3294.c b/src/boards/asic_tc3294.c new file mode 100644 index 0000000..04a9787 --- /dev/null +++ b/src/boards/asic_tc3294.c @@ -0,0 +1,106 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_tc3294.h" +#include "asic_mmc3.h" + +static void (*TC3294_cbSync)(); +static uint8 TC3294_index; +static uint8 TC3294_reg[4]; + +static SFORMAT TC3294_state[] = { + { TC3294_reg, 8, "329S" }, + {&TC3294_index, 1, "329I" }, + { 0 } +}; + +void TC3294_syncWRAM (int OR) { + MMC3_syncWRAM(OR); +} + +void TC3294_syncPRG (int AND, int OR) { + int prgAND =~TC3294_reg[3] &0x3F; + int prgOR = TC3294_reg[1] | TC3294_reg[2] <<2 &0x300; + MMC3_syncPRG(prgAND &AND, prgOR &~prgAND &AND | OR &~AND); +} + +void TC3294_syncCHR (int AND, int OR) { + int chrAND =0xFF >>(~TC3294_reg[2] &0xF); + int chrOR =TC3294_reg[0] | TC3294_reg[2] <<4 &0xF00; + MMC3_syncCHR(chrAND &AND, chrOR &~chrAND &AND | OR &~AND); +} + +void TC3294_syncMirror () { + MMC3_syncMirror(); +} + +DECLFW(TC3294_write) { + if (~TC3294_reg[3] &0x40) { + TC3294_reg[TC3294_index++ &3] =V; + TC3294_cbSync(); + } +} + +static void TC3294_clear () { + TC3294_reg[0] = 0x00; TC3294_reg[1] = 0x00; TC3294_reg[2] = 0x0F; TC3294_reg[3] = 0x00; + TC3294_index = 0; + TC3294_cbSync(); +} + +static void TC3294_setHandlers () { +} + +static void TC3294_configure (void (*sync)()) { + TC3294_cbSync = sync; +} + +void TC3294_activate (uint8 clear, void (*sync)()) { + MMC3_activate(clear, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, TC3294_write); + TC3294_configure(sync); + TC3294_setHandlers(); + if (clear) + TC3294_clear(); + else + TC3294_cbSync(); +} + +void TC3294_addExState () { + AddExState(TC3294_state, ~0, 0, 0); +} + +void TC3294_restore (int version) { + TC3294_cbSync(); +} + +void TC3294_power () { + MMC3_power(); + TC3294_setHandlers(); + TC3294_clear(); +} + +void TC3294_init (CartInfo *info, void (*sync)()) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, TC3294_write); + TC3294_addExState(); + TC3294_configure(TC3294_cbSync); + info->Power = TC3294_power; + info->Reset = TC3294_cbSync; + GameStateRestore = TC3294_restore; +} diff --git a/src/boards/asic_tc3294.h b/src/boards/asic_tc3294.h new file mode 100644 index 0000000..baa4e6e --- /dev/null +++ b/src/boards/asic_tc3294.h @@ -0,0 +1,35 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_TC3294_H +#define _ASIC_TC3294_H + +void TC3294_syncWRAM (int); +void TC3294_syncPRG (int, int); +void TC3294_syncCHR (int, int); +void TC3294_syncMirror (); +DECLFW (TC3294_write); +void TC3294_activate (uint8, void (*)()); +void TC3294_addExState (); +void TC3294_restore (int); +void TC3294_power (); +void TC3294_init (CartInfo *, void (*)()); + +#endif diff --git a/src/boards/asic_vrc1.c b/src/boards/asic_vrc1.c new file mode 100644 index 0000000..63ece13 --- /dev/null +++ b/src/boards/asic_vrc1.c @@ -0,0 +1,95 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_vrc1.h" + +static void (*VRC1_cbSync)(); +static uint8 VRC1_reg[8]; + +static SFORMAT VRC1_state[] = { + { VRC1_reg, 8, "VC1R" }, + { 0 } +}; + +void VRC1_syncPRG (int AND, int OR) { + setprg8(0x8000, VRC1_reg[0] &AND |OR); + setprg8(0xA000, VRC1_reg[2] &AND |OR); + setprg8(0xC000, VRC1_reg[4] &AND |OR); + setprg8(0xE000, 0xFF &AND |OR); +} + +void VRC1_syncCHR (int AND, int OR) { + setchr4(0x0000, (VRC1_reg[6] &0x0F | VRC1_reg[1] <<3 &0x10) &AND |OR); + setchr4(0x1000, (VRC1_reg[7] &0x0F | VRC1_reg[1] <<2 &0x10) &AND |OR); +} + +void VRC1_syncMirror () { + setmirror(VRC1_reg[1] &0x01? MI_H: MI_V); +} + +DECLFW(VRC1_write) { + VRC1_reg[A >>12 &7] = V; + VRC1_cbSync(); +} + +static void VRC1_clear () { + VRC1_reg[0] = 0x00; VRC1_reg[1] = 0; VRC1_reg[2] = 2; VRC1_reg[3] = 0;VRC1_reg[4] = 0x00; VRC1_reg[5] = 0; VRC1_reg[6] = 2; VRC1_reg[7] = 0; + VRC1_cbSync(); +} + +static void VRC1_setHandlers () { + SetReadHandler (0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, VRC1_write); +} + +static void VRC1_configure (void (*sync)()) { + VRC1_cbSync = sync; +} + +void VRC1_activate (uint8 clear, void (*sync)()) { + VRC1_configure(sync); + VRC1_setHandlers(); + if (clear) + VRC1_clear(); + else + VRC1_cbSync(); +} + +void VRC1_addExState () { + AddExState(VRC1_state, ~0, 0, 0); +} + +void VRC1_restore (int version) { + VRC1_cbSync(); +} + +void VRC1_power () { + VRC1_setHandlers(); + VRC1_clear(); +} + +void VRC1_init (CartInfo *info, void (*sync)()) { + VRC1_addExState(); + VRC1_configure(sync); + info->Power = VRC1_power; + info->Reset = VRC1_cbSync; + GameStateRestore = VRC1_restore; +} diff --git a/src/boards/asic_vrc1.h b/src/boards/asic_vrc1.h new file mode 100644 index 0000000..040c2b0 --- /dev/null +++ b/src/boards/asic_vrc1.h @@ -0,0 +1,34 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_VRC1_H +#define _ASIC_VRC1_H + +void VRC1_syncPRG (int, int); +void VRC1_syncCHR (int, int); +void VRC1_syncMirror (); +DECLFW (VRC1_write); +void VRC1_activate (uint8, void (*)()); +void VRC1_addExState (); +void VRC1_restore (int); +void VRC1_power (); +void VRC1_init (CartInfo *, void (*)()); + +#endif diff --git a/src/boards/asic_vrc2and4.c b/src/boards/asic_vrc2and4.c new file mode 100644 index 0000000..a457185 --- /dev/null +++ b/src/boards/asic_vrc2and4.c @@ -0,0 +1,297 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_vrc2and4.h" +#include "wram.h" + +static void (*VRC24_cbSync)(); +static int VRC24_A0, VRC24_A1; +static int (*VRC24_cbGetPRGBank)(uint8); +static int (*VRC24_cbGetCHRBank)(uint8); +static DECLFR((*VRC24_cbReadWRAM)); +static DECLFW((*VRC24_cbWriteWRAM)); +static DECLFW((*VRC24_cbExternalSelect)); +static uint8 VRC24_isVRC4; /* VRC2 or VRC4? VRC2 has no single-screen mirroring, no PRG A14 swap and no IRQ counter */ +static uint8 VRC24_useRepeatBit; /* Some VRC4 clones ignore the "repeat" bit in the IRQ Mode register */ +static uint8 VRC24_prg[2]; +static uint16 VRC24_chr[8]; +static uint8 VRC24_mirroring; +static uint8 VRC24_misc; +uint8 VRC2_pins; /* EEPROM interface */ +static uint8 VRC4_latch; +static uint8 VRC4_mode; +static uint8 VRC4_count; +static signed short int VRC4_cycles; + +static SFORMAT VRC24_stateRegs[] = { + { VRC24_prg, 2, "PREG" }, + { &VRC24_chr[0], 2 | FCEUSTATE_RLSB, "CRH0" }, + { &VRC24_chr[1], 2 | FCEUSTATE_RLSB, "CRH1" }, + { &VRC24_chr[2], 2 | FCEUSTATE_RLSB, "CRH2" }, + { &VRC24_chr[3], 2 | FCEUSTATE_RLSB, "CRH3" }, + { &VRC24_chr[4], 2 | FCEUSTATE_RLSB, "CRH4" }, + { &VRC24_chr[5], 2 | FCEUSTATE_RLSB, "CRH5" }, + { &VRC24_chr[6], 2 | FCEUSTATE_RLSB, "CRH6" }, + { &VRC24_chr[7], 2 | FCEUSTATE_RLSB, "CRH7" }, + { &VRC24_mirroring, 1, "MIRR" }, + { &VRC24_misc, 1, "MISC" }, + { 0 } +}; + +static SFORMAT VRC2_stateRegs[] = { + { &VRC2_pins, 1, "PINS" }, +}; + +static SFORMAT VRC4_stateRegs[] = { + { &VRC4_latch, 1, "LATC" }, + { &VRC4_mode, 1, "MODE" }, + { &VRC4_count, 1, "COUN" }, + { &VRC4_cycles, 2 | FCEUSTATE_RLSB, "CYCL" }, + { 0 } +}; + +void VRC24_syncPRG (int AND, int OR) { + setprg8(0x8000, VRC24_cbGetPRGBank(0) &AND | OR); + setprg8(0xA000, VRC24_cbGetPRGBank(1) &AND | OR); + setprg8(0xC000, VRC24_cbGetPRGBank(2) &AND | OR); + setprg8(0xE000, VRC24_cbGetPRGBank(3) &AND | OR); +} + +void VRC24_syncCHR (int AND, int OR) { + setchr1(0x0000, VRC24_cbGetCHRBank(0) &AND | OR); + setchr1(0x0400, VRC24_cbGetCHRBank(1) &AND | OR); + setchr1(0x0800, VRC24_cbGetCHRBank(2) &AND | OR); + setchr1(0x0C00, VRC24_cbGetCHRBank(3) &AND | OR); + setchr1(0x1000, VRC24_cbGetCHRBank(4) &AND | OR); + setchr1(0x1400, VRC24_cbGetCHRBank(5) &AND | OR); + setchr1(0x1800, VRC24_cbGetCHRBank(6) &AND | OR); + setchr1(0x1C00, VRC24_cbGetCHRBank(7) &AND | OR); +} + +void VRC24_syncWRAM (int OR) { + if (PRGsize[0x10]) setprg8r(0x10, 0x6000, OR); +} + +int VRC24_getPRGBank (uint8 bank) { + if (~bank &1 && VRC24_misc &2) bank ^= 2; + return bank &2? (0xFE | bank &1): VRC24_prg[bank &1]; +} + +int VRC24_getCHRBank (uint8 bank) { + return VRC24_chr[bank &7]; +} + +void VRC24_syncMirror () { + setmirror(VRC24_isVRC4 && VRC24_mirroring &2? (VRC24_mirroring &1? MI_1: MI_0): (VRC24_mirroring &1? MI_H: MI_V)); +} + +DECLFR(VRC2_readMicrowire) { + return VRC2_pins; +} + +DECLFR(VRC24_readWRAM) { + if (VRC24_misc &1 || !VRC24_isVRC4) { + if (VRC24_cbReadWRAM) + return VRC24_cbReadWRAM(A); + else + if (WRAMSize) + CartBR(((A -0x6000) &(WRAMSize -1)) +0x6000); + else + return A >>8; + } else + return A >>8; +} + +DECLFW(VRC2_writeMicrowire) { + VRC2_pins = V; + VRC24_cbSync(); +} + +DECLFW(VRC24_writeWRAM) { + if (VRC24_misc &1 || !VRC24_isVRC4) { + if (WRAMSize) + CartBW(((A -0x6000) &(WRAMSize -1)) +0x6000, V); + if (VRC24_cbWriteWRAM) + VRC24_cbWriteWRAM(A, V); + } +} + +DECLFW(VRC24_writeReg) { + unsigned int index, addr; + addr = A &0xF000 | (A &VRC24_A0? 1: 0) | (A &VRC24_A1? 2: 0); /* address as the chip sees it */ + switch (addr &0xF000) { + case 0x8000: case 0xA000: + VRC24_prg[addr >>13 &1] = V; + VRC24_cbSync(); + break; + case 0x9000: + if (!VRC24_isVRC4 || (addr &3) == 0) { + VRC24_mirroring = V; + VRC24_cbSync(); + } else + if (VRC24_isVRC4 && (addr &3) == 2) { + VRC24_misc = V; + VRC24_cbSync(); + } + if (VRC24_isVRC4 && (addr &3) == 3 && VRC24_cbExternalSelect) { + VRC24_cbExternalSelect(A, V); /* Provide original address */ + } + break; + case 0xF000: + if (VRC24_isVRC4) switch (addr &3) { + case 0: VRC4_latch = VRC4_latch &0xF0 | V &0x0F; break; + case 1: VRC4_latch = VRC4_latch &0x0F | V <<4; break; + case 2: VRC4_mode = V; + if (VRC4_mode &0x02) { + VRC4_count = VRC4_latch; + VRC4_cycles = 341; + } + X6502_IRQEnd(FCEU_IQEXT); + break; + case 3: if (VRC24_useRepeatBit) VRC4_mode = VRC4_mode &~0x02 | VRC4_mode <<1 &0x02; + X6502_IRQEnd(FCEU_IQEXT); + break; + } + break; + default: + index = (addr -0xB000) >>11 | addr >>1 &1; + if (addr &1) + VRC24_chr[index] = VRC24_chr[index] & 0x0F | V <<4; + else + VRC24_chr[index] = VRC24_chr[index] &~0x0F | V &0x0F; + VRC24_cbSync(); + break; + } +} + +void FP_FASTAPASS(1) VRC4_cpuCycle (int a) { + while (a--) { + if (VRC4_mode &0x02 && (VRC4_mode &0x04 || (VRC4_cycles -= 3) <= 0)) { + if (~VRC4_mode &0x04) VRC4_cycles += 341; + if (!++VRC4_count) { + VRC4_count = VRC4_latch; + X6502_IRQBegin(FCEU_IQEXT); + } + } + } +} + +static void VRC24_clear() { + VRC24_prg[0] = 0; VRC24_prg[1] = 0; + VRC24_chr[0] = 0; VRC24_chr[1] = 1; VRC24_chr[2] = 2; VRC24_chr[3] = 3; VRC24_chr[4] = 4; VRC24_chr[5] = 5; VRC24_chr[6] = 6; VRC24_chr[7] = 7; + VRC24_mirroring = VRC2_pins = VRC4_latch = VRC4_mode = VRC4_count = VRC4_cycles = 0; + VRC24_misc = 1; /* Start with WRAM enabled */ + VRC24_cbSync(); +} + +static void VRC24_setHandlers () { + if (VRC24_isVRC4 || WRAMSize) { + SetReadHandler(0x6000, 0x7FFF, VRC24_readWRAM); + SetWriteHandler(0x6000, 0x7FFF, VRC24_writeWRAM); + } else { + SetReadHandler(0x6000, 0x6FFF, VRC2_readMicrowire); + SetWriteHandler(0x6000, 0x6FFF, VRC2_writeMicrowire); + } + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, VRC24_writeReg); + if (VRC24_isVRC4) MapIRQHook = VRC4_cpuCycle; +} + +static void VRC2_configure (void (*sync)(), int A0, int A1, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) { + VRC24_cbSync = sync; + VRC24_A0 = A0; + VRC24_A1 = A1; + VRC24_isVRC4 = 0; + VRC24_cbGetPRGBank = prg? prg: VRC24_getPRGBank; + VRC24_cbGetCHRBank = chr? chr: VRC24_getCHRBank; + VRC24_cbReadWRAM = read; + VRC24_cbWriteWRAM = write; +} + +static void VRC4_configure (void (*sync)(), int A0, int A1, uint8 useRepeatBit, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write)), DECLFW((*externalSelect))) { + VRC24_cbSync = sync; + VRC24_A0 = A0; + VRC24_A1 = A1; + VRC24_isVRC4 = 1; + VRC24_useRepeatBit = useRepeatBit; + VRC24_cbGetPRGBank = prg? prg: VRC24_getPRGBank; + VRC24_cbGetCHRBank = chr? chr: VRC24_getCHRBank; + VRC24_cbReadWRAM = read; + VRC24_cbWriteWRAM = write; + VRC24_cbExternalSelect = externalSelect; +} + +void VRC2_activate (uint8 clear, void (*sync)(), int A0, int A1, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) { + VRC2_configure(sync, A0, A1, prg, chr, read, write); + VRC24_setHandlers(); + if (clear) + VRC24_clear(); + else + VRC24_cbSync(); +} + +void VRC4_activate (uint8 clear, void (*sync)(), int A0, int A1, uint8 useRepeatBit, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write)), DECLFW((*externalSelect))) { + VRC4_configure(sync, A0, A1, useRepeatBit, prg, chr, read, write, externalSelect); + VRC24_setHandlers(); + if (clear) + VRC24_clear(); + else + VRC24_cbSync(); +} + +void VRC2_addExState () { + AddExState(VRC24_stateRegs, ~0, 0, 0); + AddExState(VRC2_stateRegs, ~0, 0, 0); +} + +void VRC4_addExState () { + AddExState(VRC24_stateRegs, ~0, 0, 0); + AddExState(VRC4_stateRegs, ~0, 0, 0); +} + +void VRC24_addExState () { + AddExState(VRC24_stateRegs, ~0, 0, 0); + AddExState(VRC2_stateRegs, ~0, 0, 0); + AddExState(VRC4_stateRegs, ~0, 0, 0); +} + +void VRC24_restore (int version) { + VRC24_cbSync(); +} + +void VRC24_power () { + VRC24_setHandlers(); + VRC24_clear(); +} + +void VRC2_init (CartInfo *info, void (*sync)(), int A0, int A1, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) { + VRC2_addExState(); + VRC2_configure(sync, A0, A1, prg, chr, read, write); + info->Power = VRC24_power; + GameStateRestore = VRC24_cbSync; +} + +void VRC4_init (CartInfo *info, void (*sync)(), int A0, int A1, uint8 useRepeatBit, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write)), DECLFW((*externalSelect))) { + VRC4_addExState(); + VRC4_configure(sync, A0, A1, useRepeatBit, prg, chr, read, write, externalSelect); + info->Power = VRC24_power; + GameStateRestore = VRC24_restore; +} diff --git a/src/boards/asic_vrc2and4.h b/src/boards/asic_vrc2and4.h new file mode 100644 index 0000000..c5ae48c --- /dev/null +++ b/src/boards/asic_vrc2and4.h @@ -0,0 +1,50 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _VRC2AND4_H +#define _VRC2AND4_H + +extern uint8 VRC2_pins; + +DECLFR(VRC2_readMicrowire); +DECLFW(VRC2_writeMicrowire); +DECLFR(VRC24_readWRAM); +DECLFW(VRC24_writeWRAM); + +void VRC24_syncWRAM (int); +void VRC24_syncPRG (int, int); +void VRC24_syncCHR (int, int); +int VRC24_getPRGBank (uint8); +int VRC24_getCHRBank (uint8); +void VRC24_syncMirror (); +DECLFW(VRC24_writeReg); + +void FP_FASTAPASS(1) VRC4_cpuCycle(int); +void VRC2_activate (uint8, void (*)(), int, int, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*))); +void VRC4_activate (uint8, void (*)(), int, int, uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*)), DECLFW((*))); +void VRC2_addExState (); +void VRC4_addExState (); +void VRC24_addExState (); +void VRC24_restore (int); +void VRC24_power (); +void VRC2_init (CartInfo *, void (*)(), int, int, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*))); +void VRC4_init (CartInfo *, void (*)(), int, int, uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*)), DECLFW((*))); + +#endif diff --git a/src/boards/asic_vrc3.c b/src/boards/asic_vrc3.c new file mode 100644 index 0000000..717ad5b --- /dev/null +++ b/src/boards/asic_vrc3.c @@ -0,0 +1,129 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_VRC3.h" + +static void (*VRC3_cbSync)(); +static uint8 VRC3_prg; +static uint8 VRC3_irq; +static uint16 VRC3_count; +static uint16 VRC3_reload; + +static SFORMAT VRC3_state[] = { + {&VRC3_prg, 1, "VC3P" }, + {&VRC3_irq, 1, "VC3I" }, + {&VRC3_count, 1, "VC3C" }, + {&VRC3_reload, 1, "VC3R" }, + { 0 } +}; + +void VRC3_syncWRAM (int OR) { + if (PRGsize[0x10]) setprg8r(0x10, 0x6000, OR); +} + +void VRC3_syncPRG (int AND, int OR) { + setprg16(0x8000, VRC3_prg &AND |OR); + setprg16(0xC000, 0xFF &AND |OR); +} + +void VRC3_syncCHR (int AND, int OR) { + setchr8(OR); +} + +DECLFW(VRC3_write) { + int shift; + switch (A >>12 &7) { + case 0: case 1: case 2: case 3: + V &=0xF; + shift = A >>10 &0xC; + VRC3_reload = VRC3_reload &~(0xF <Power = VRC3_power; + info->Reset = VRC3_cbSync; + GameStateRestore = VRC3_restore; +} diff --git a/src/boards/asic_vrc3.h b/src/boards/asic_vrc3.h new file mode 100644 index 0000000..28147bb --- /dev/null +++ b/src/boards/asic_vrc3.h @@ -0,0 +1,34 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_VRC3_H +#define _ASIC_VRC3_H + +void VRC3_syncWRAM (int); +void VRC3_syncPRG (int, int); +void VRC3_syncCHR (int, int); +DECLFW (VRC3_write); +void VRC3_activate (uint8, void (*)()); +void VRC3_addExState (); +void VRC3_restore (int); +void VRC3_power (); +void VRC3_init (CartInfo *, void (*)()); + +#endif diff --git a/src/boards/asic_vrc6.c b/src/boards/asic_vrc6.c new file mode 100644 index 0000000..6c7d517 --- /dev/null +++ b/src/boards/asic_vrc6.c @@ -0,0 +1,208 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_vrc6.h" +#include "wram.h" + +static void (*VRC6_cbSync)(); +static int VRC6_A0, VRC6_A1; +static int (*VRC6_cbGetPRGBank)(uint8); +static int (*VRC6_cbGetCHRBank)(uint8); +static DECLFR ((*VRC6_cbReadWRAM)); +static DECLFW ((*VRC6_cbWriteWRAM)); +static uint8 VRC6_prg[2]; +static uint8 VRC6_chr[8]; +static uint8 VRC6_misc; +static uint8 VRC6_latch; +static uint8 VRC6_mode; +static uint8 VRC6_count; +static signed short int VRC6_cycles; + +static SFORMAT VRC6_stateRegs[] = { + { VRC6_prg, 2, "VC6P" }, + { VRC6_chr, 6, "VC6C" }, + { &VRC6_misc, 1, "VC6M" }, + { &VRC6_latch, 1, "LATC" }, + { &VRC6_mode, 1, "MODE" }, + { &VRC6_count, 1, "COUN" }, + { &VRC6_cycles, 2 | FCEUSTATE_RLSB, "CYCL" }, + { 0 } +}; + +void VRC6_syncWRAM (int OR) { + if (PRGsize[0x10]) setprg8r(0x10, 0x6000, OR); +} + +void VRC6_syncPRG (int AND, int OR) { + setprg8(0x8000, VRC6_cbGetPRGBank(0) &AND | OR); + setprg8(0xA000, VRC6_cbGetPRGBank(1) &AND | OR); + setprg8(0xC000, VRC6_cbGetPRGBank(2) &AND | OR); + setprg8(0xE000, VRC6_cbGetPRGBank(3) &AND | OR); +} + +void VRC6_syncCHR (int AND, int OR) { + setchr1(0x0000, VRC6_cbGetCHRBank(0) &AND | OR); + setchr1(0x0400, VRC6_cbGetCHRBank(1) &AND | OR); + setchr1(0x0800, VRC6_cbGetCHRBank(2) &AND | OR); + setchr1(0x0C00, VRC6_cbGetCHRBank(3) &AND | OR); + setchr1(0x1000, VRC6_cbGetCHRBank(4) &AND | OR); + setchr1(0x1400, VRC6_cbGetCHRBank(5) &AND | OR); + setchr1(0x1800, VRC6_cbGetCHRBank(6) &AND | OR); + setchr1(0x1C00, VRC6_cbGetCHRBank(7) &AND | OR); +} + +void VRC6_syncMirror () { /* Only emulates features used by known games, meaning mode 0 with CHR A10 substitution */ + setmirror(VRC6_misc &8? (VRC6_misc &4? MI_1: MI_0): VRC6_misc &4? MI_H: MI_V); +} + +int VRC6_getPRGBank (uint8 bank) { + if (bank &2) + return bank &1? 0xFF: VRC6_prg[1]; + else + return VRC6_prg[0] <<1 | bank &1; +} + +int VRC6_getCHRBank (uint8 bank) { /* Only emulates features used by known games, meaning mode 0 with CHR A10 substitution */ + return VRC6_chr[bank &7]; +} + +DECLFR(VRC6_readWRAM) { + if (VRC6_misc &0x80) + return VRC6_cbReadWRAM? VRC6_cbReadWRAM(A): CartBR(A); + else + return A >>8; +} + +DECLFW(VRC6_writeWRAM) { + if (VRC6_misc &0x80) { + CartBW(A, V); + if (VRC6_cbWriteWRAM) VRC6_cbWriteWRAM(A, V); + } +} + +DECLFW(VRC6_writeReg) { + unsigned int index; + index = (A &VRC6_A0? 1: 0) | (A &VRC6_A1? 2: 0); + switch (A >>12 &7) { + case 0: case 4: + VRC6_prg[A >>14 &1] = V; + VRC6_cbSync(); + break; + case 1: case 2: /* Sound */ + break; + case 3: + if (index == 3) { + VRC6_misc = V; + VRC6_cbSync(); + } + break; + case 5: case 6: + VRC6_chr[A >>11 &4 | index] = V; + VRC6_cbSync(); + break; + case 7: + switch (index) { + case 0: + VRC6_latch = V; + break; + case 1: + VRC6_mode = V; + if (VRC6_mode &0x02) { + VRC6_count = VRC6_latch; + VRC6_cycles = 341; + } + X6502_IRQEnd(FCEU_IQEXT); + break; + case 2: + VRC6_mode = VRC6_mode &~0x02 | VRC6_mode <<1 &0x02; + X6502_IRQEnd(FCEU_IQEXT); + break; + } + break; + } +} + +void FP_FASTAPASS(1) VRC6_cpuCycle (int a) { + while (a--) { + if (VRC6_mode &0x02 && (VRC6_mode &0x04 || (VRC6_cycles -= 3) <= 0)) { + if (~VRC6_mode &0x04) VRC6_cycles += 341; + if (!++VRC6_count) { + VRC6_count = VRC6_latch; + X6502_IRQBegin(FCEU_IQEXT); + } + } + } +} + +static void VRC6_clear () { + VRC6_prg[0] = 0; VRC6_prg[1] = 0xFE; + VRC6_chr[0] = 0; VRC6_chr[1] = 1; VRC6_chr[2] = 2; VRC6_chr[3] = 3; VRC6_chr[4] = 4; VRC6_chr[5] = 5; VRC6_chr[6] = 6; VRC6_chr[7] = 7; + VRC6_misc = VRC6_latch = VRC6_mode = VRC6_count = VRC6_cycles = 0; + VRC6_cbSync(); +} + +static void VRC6_setHandlers () { + SetReadHandler(0x6000, 0x7FFF, VRC6_readWRAM); + SetWriteHandler(0x6000, 0x7FFF, VRC6_writeWRAM); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, VRC6_writeReg); + MapIRQHook =VRC6_cpuCycle; +} + +static void VRC6_configure (void (*sync)(), int A0, int A1, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) { + VRC6_A0 = A0; + VRC6_A1 = A1; + VRC6_cbSync = sync; + VRC6_cbGetPRGBank = prg? prg: VRC6_getPRGBank; + VRC6_cbGetCHRBank = chr? chr: VRC6_getCHRBank; + VRC6_cbReadWRAM = read; + VRC6_cbWriteWRAM = write; +} + +void VRC6_activate (uint8 clear, void (*sync)(), int A0, int A1, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) { + VRC6_configure(sync, A0, A1, prg, chr, read, write); + VRC6_setHandlers(); + if (clear) + VRC6_clear(); + else + VRC6_cbSync(); +} + +void VRC6_addExState () { + AddExState(VRC6_stateRegs, ~0, 0, 0); +} + +void VRC6_restore (int version) { + VRC6_cbSync(); +} + +void VRC6_power () { + VRC6_setHandlers(); + VRC6_clear(); +} + +void VRC6_init (CartInfo *info, void (*sync)(), int A0, int A1, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) { + VRC6_addExState(); + VRC6_configure(sync, A0, A1, prg, chr, read, write); + info->Power = VRC6_power; + info->Reset = VRC6_cbSync; + GameStateRestore = VRC6_restore; +} diff --git a/src/boards/asic_vrc6.h b/src/boards/asic_vrc6.h new file mode 100644 index 0000000..ae5cbf0 --- /dev/null +++ b/src/boards/asic_vrc6.h @@ -0,0 +1,40 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_VRC6_H +#define _ASIC_VRC6_H + +void VRC6_syncWRAM (int); +void VRC6_syncPRG (int, int); +void VRC6_syncCHR (int, int); +void VRC6_syncMirror (); +int VRC6_getPRGBank (uint8); +int VRC6_getCHRBank (uint8); +DECLFR(VRC6_readWRAM); +DECLFW(MMC3_writeWRAM); +DECLFW(VRC6_writeReg); +void FP_FASTAPASS(1) VRC6_cpuCycle (int); +void VRC6_activate (uint8, void (*)(), int, int, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*))); +void VRC6_addExState (); +void VRC6_restore (int); +void VRC6_power (); +void VRC6_init (CartInfo *, void (*)(), int, int, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*))); + +#endif \ No newline at end of file diff --git a/src/boards/asic_vrc7.c b/src/boards/asic_vrc7.c new file mode 100644 index 0000000..0777e5f --- /dev/null +++ b/src/boards/asic_vrc7.c @@ -0,0 +1,180 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_VRC7.h" +#include "wram.h" + +static void (*VRC7_cbSync)(); +static int VRC7_A0; +static uint8 VRC7_prg[3]; +static uint8 VRC7_chr[8]; +static uint8 VRC7_misc; +static uint8 VRC7_latch; +static uint8 VRC7_mode; +static uint8 VRC7_count; +static signed short int VRC7_cycles; + +static SFORMAT VRC7_stateRegs[] = { + { VRC7_prg, 3, "VC6P" }, + { VRC7_chr, 6, "VC6C" }, + { &VRC7_misc, 1, "VC6M" }, + { &VRC7_latch, 1, "LATC" }, + { &VRC7_mode, 1, "MODE" }, + { &VRC7_count, 1, "COUN" }, + { &VRC7_cycles, 2 | FCEUSTATE_RLSB, "CYCL" }, + { 0 } +}; + +void VRC7_syncWRAM (int OR) { + if (PRGsize[0x10]) setprg8r(0x10, 0x6000, OR); +} + +void VRC7_syncPRG (int AND, int OR) { + setprg8(0x8000, VRC7_prg[0] &AND | OR); + setprg8(0xA000, VRC7_prg[1] &AND | OR); + setprg8(0xC000, VRC7_prg[2] &AND | OR); + setprg8(0xE000, 0xFF &AND | OR); +} + +void VRC7_syncCHR (int AND, int OR) { + setchr1(0x0000, VRC7_chr[0] &AND | OR); + setchr1(0x0400, VRC7_chr[1] &AND | OR); + setchr1(0x0800, VRC7_chr[2] &AND | OR); + setchr1(0x0C00, VRC7_chr[3] &AND | OR); + setchr1(0x1000, VRC7_chr[4] &AND | OR); + setchr1(0x1400, VRC7_chr[5] &AND | OR); + setchr1(0x1800, VRC7_chr[6] &AND | OR); + setchr1(0x1C00, VRC7_chr[7] &AND | OR); +} + +void VRC7_syncMirror () { + setmirror(VRC7_misc &2? (VRC7_misc &1? MI_1: MI_0): VRC7_misc &1? MI_H: MI_V); +} + +DECLFR(VRC7_readWRAM) { + return VRC7_misc &0x80? CartBR(A): A >>8; +} + +DECLFW(VRC7_writeWRAM) { + if (VRC7_misc &0x80) CartBW(A, V); +} + +DECLFW(VRC7_writeReg) { + unsigned int index; + index = A &VRC7_A0? 1: 0; + switch (A >>12 &7) { + case 0: + VRC7_prg[index &1] = V; + VRC7_cbSync(); + break; + case 1: + if (!index) { + VRC7_prg[2] = V; + VRC7_cbSync(); + } + break; + case 2: case 3: case 4: case 5: + VRC7_chr[(A -0xA000) >>11 &6 | index] = V; + VRC7_cbSync(); + break; + case 6: if (!index) { + VRC7_misc = V; + VRC7_cbSync(); + } else + VRC7_latch = V; + break; + case 7: + if (!index) { + VRC7_mode = V; + if (VRC7_mode &0x02) { + VRC7_count = VRC7_latch; + VRC7_cycles = 341; + } + X6502_IRQEnd(FCEU_IQEXT); + } else { + VRC7_mode = VRC7_mode &~0x02 | VRC7_mode <<1 &0x02; + X6502_IRQEnd(FCEU_IQEXT); + } + break; + } +} + +void FP_FASTAPASS(1) VRC7_cpuCycle (int a) { + while (a--) { + if (VRC7_mode &0x02 && (VRC7_mode &0x04 || (VRC7_cycles -= 3) <= 0)) { + if (~VRC7_mode &0x04) VRC7_cycles += 341; + if (!++VRC7_count) { + VRC7_count = VRC7_latch; + X6502_IRQBegin(FCEU_IQEXT); + } + } + } +} + +static void VRC7_clear () { + VRC7_prg[0] = 0; VRC7_prg[1] = 1; VRC7_prg[2] = 0xFE; + VRC7_chr[0] = 0; VRC7_chr[1] = 1; VRC7_chr[2] = 2; VRC7_chr[3] = 3; VRC7_chr[4] = 4; VRC7_chr[5] = 5; VRC7_chr[6] = 6; VRC7_chr[7] = 7; + VRC7_misc = VRC7_latch = VRC7_mode = VRC7_count = VRC7_cycles = 0; + VRC7_cbSync(); +} + +static void VRC7_setHandlers () { + SetReadHandler(0x6000, 0x7FFF, VRC7_readWRAM); + SetWriteHandler(0x6000, 0x7FFF, VRC7_writeWRAM); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, VRC7_writeReg); + MapIRQHook =VRC7_cpuCycle; +} + +static void VRC7_configure (void (*sync)(), int A0) { + VRC7_A0 = A0; + VRC7_cbSync = sync; +} + +void VRC7_activate (uint8 clear, void (*sync)(), int A0) { + VRC7_configure(sync, A0); + VRC7_setHandlers(); + if (clear) + VRC7_clear(); + else + VRC7_cbSync(); +} + +void VRC7_addExState () { + AddExState(VRC7_stateRegs, ~0, 0, 0); +} + +void VRC7_restore (int version) { + VRC7_cbSync(); +} + +void VRC7_power () { + VRC7_setHandlers(); + VRC7_clear(); +} + +void VRC7_init (CartInfo *info, void (*sync)(), int A0) { + VRC7_addExState(); + VRC7_configure(sync, A0); + info->Power = VRC7_power; + info->Reset = VRC7_cbSync; + GameStateRestore = VRC7_restore; +} diff --git a/src/boards/asic_vrc7.h b/src/boards/asic_vrc7.h new file mode 100644 index 0000000..a547cf5 --- /dev/null +++ b/src/boards/asic_vrc7.h @@ -0,0 +1,41 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_VRC7_H +#define _ASIC_VRC7_H + +void VRC7_syncWRAM (int); +void VRC7_syncPRG (int, int); +void VRC7_syncCHR (int, int); +void VRC7_syncMirror (); +int VRC7_getPRGBank (uint8); +int VRC7_getCHRBank (uint8); +int VRC7_getNTBank (uint8); +DECLFR(VRC7_readWRAM); +DECLFW(MMC3_writeWRAM); +DECLFW(VRC7_writeReg); +void FP_FASTAPASS(1) VRC7_cpuCycle (int); +void VRC7_activate (uint8, void (*)(), int); +void VRC7_addExState (); +void VRC7_restore (int); +void VRC7_power (); +void VRC7_init (CartInfo *, void (*)(), int); + +#endif \ No newline at end of file diff --git a/src/boards/vrc2and4.c b/src/boards/vrc2and4.c deleted file mode 100644 index 6cd451f..0000000 --- a/src/boards/vrc2and4.c +++ /dev/null @@ -1,242 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2025 NewRisingSun - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "vrc2and4.h" - -int VRC24_A0, VRC24_A1; /* What cartridge connector address pins are connected to the chip's A0 and A1 input pins? */ -uint8 VRC24_isVRC4; /* VRC2 or VRC4? VRC2 has no single-screen mirroring, no PRG A14 swap and no IRQ counter */ -uint8 VRC24_useRepeatBit; /* VRC4 clones ignore the "repeat" bit in the IRQ Mode register */ -uint8 VRC24_prg[2]; -uint16 VRC24_chr[8]; -uint8 VRC24_mirroring; -uint8 VRC24_misc; -uint8 VRC2_pins; /* EEPROM interface */ -uint8 VRC4_latch; -uint8 VRC4_mode; -uint8 VRC4_count; -signed short int VRC4_cycles; - -static uint8 *WRAM; -static uint32 WRAMSize; - -int (*VRC24_GetPRGBank)(int); -int (*VRC24_GetCHRBank)(int); -void (*VRC24_Sync)(); -DECLFW((*VRC24_ExternalSelect)); -DECLFR((*VRC24_WRAMRead)); -DECLFW((*VRC24_WRAMWrite)); - -static SFORMAT VRC24_stateRegs[] ={ - { VRC24_prg, 2, "PREG" }, - { &VRC24_chr[0], 2 | FCEUSTATE_RLSB, "CRH0" }, - { &VRC24_chr[1], 2 | FCEUSTATE_RLSB, "CRH1" }, - { &VRC24_chr[2], 2 | FCEUSTATE_RLSB, "CRH2" }, - { &VRC24_chr[3], 2 | FCEUSTATE_RLSB, "CRH3" }, - { &VRC24_chr[4], 2 | FCEUSTATE_RLSB, "CRH4" }, - { &VRC24_chr[5], 2 | FCEUSTATE_RLSB, "CRH5" }, - { &VRC24_chr[6], 2 | FCEUSTATE_RLSB, "CRH6" }, - { &VRC24_chr[7], 2 | FCEUSTATE_RLSB, "CRH7" }, - { &VRC24_mirroring, 1, "MIRR" }, - { &VRC24_misc, 1, "MISC" }, - { 0 } -}; - -static SFORMAT VRC2_stateRegs[] ={ - { &VRC2_pins, 1, "PINS" }, -}; - -static SFORMAT VRC4_stateRegs[] ={ - { &VRC4_latch, 1, "LATC" }, - { &VRC4_mode, 1, "MODE" }, - { &VRC4_count, 1, "COUN" }, - { &VRC4_cycles, 2 | FCEUSTATE_RLSB, "CYCL" }, - { 0 } -}; - -void VRC24_syncPRG(int AND, int OR) { - setprg8(0x8000, VRC24_GetPRGBank(0) &AND | OR); - setprg8(0xA000, VRC24_GetPRGBank(1) &AND | OR); - setprg8(0xC000, VRC24_GetPRGBank(2) &AND | OR); - setprg8(0xE000, VRC24_GetPRGBank(3) &AND | OR); -} - -void VRC24_syncCHR(int AND, int OR) { - setchr1(0x0000, VRC24_GetCHRBank(0) &AND | OR); - setchr1(0x0400, VRC24_GetCHRBank(1) &AND | OR); - setchr1(0x0800, VRC24_GetCHRBank(2) &AND | OR); - setchr1(0x0C00, VRC24_GetCHRBank(3) &AND | OR); - setchr1(0x1000, VRC24_GetCHRBank(4) &AND | OR); - setchr1(0x1400, VRC24_GetCHRBank(5) &AND | OR); - setchr1(0x1800, VRC24_GetCHRBank(6) &AND | OR); - setchr1(0x1C00, VRC24_GetCHRBank(7) &AND | OR); -} - -void VRC24_syncWRAM(int OR) { - setprg8r(0x10, 0x6000, OR); -} - -int VRC24_getPRGBank(int bank) { - if (~bank &1 && VRC24_misc &2) bank ^=2; - return bank &2? (0xFE | bank &1): VRC24_prg[bank &1]; -} - -int VRC24_getCHRBank(int bank) { - return VRC24_chr[bank &7]; -} - -void VRC24_syncMirror() { - setmirror(VRC24_isVRC4 && VRC24_mirroring &2? (VRC24_mirroring &1? MI_1: MI_0): (VRC24_mirroring &1? MI_H: MI_V)); -} - -DECLFR(VRC24_wramRead) { - if (VRC24_WRAMRead) - VRC24_WRAMRead(A); - else - if (WRAMSize) - return CartBR(((A -0x6000) &(WRAMSize -1)) +0x6000); - else - return 0xFF; -} - -DECLFW(VRC24_wramWrite) { - if (WRAMSize) - CartBW(((A -0x6000) &(WRAMSize -1)) +0x6000, V); - else - if (!VRC24_isVRC4) { - VRC2_pins =V; - VRC24_Sync(); - } - - if (VRC24_WRAMWrite) - VRC24_WRAMWrite(A, V); -} - -DECLFW(VRC24_writeReg) { - unsigned int index, addr; - addr =A &0xF000 | (A &VRC24_A0? 1: 0) | (A &VRC24_A1? 2: 0); /* address as the chip sees it */ - switch (addr &0xF000) { - case 0x8000: case 0xA000: - VRC24_prg[addr >>13 &1] =V; - VRC24_Sync(); - break; - case 0x9000: - if (!VRC24_isVRC4 || (addr &3) ==0) { - VRC24_mirroring =V; - VRC24_Sync(); - } else - if (VRC24_isVRC4 && (addr &3) ==2) { - VRC24_misc =V; - VRC24_Sync(); - } - if (VRC24_isVRC4 && (addr &3) ==3 && VRC24_ExternalSelect) { - VRC24_ExternalSelect(A, V); /* Provide original address */ - } - break; - case 0xF000: - if (VRC24_isVRC4) switch (addr &3) { - case 0: VRC4_latch =VRC4_latch &0xF0 | V &0x0F; break; - case 1: VRC4_latch =VRC4_latch &0x0F | V <<4; break; - case 2: VRC4_mode =V; - if (VRC4_mode &0x02) { - VRC4_count =VRC4_latch; - VRC4_cycles =341; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 3: if (VRC24_useRepeatBit) VRC4_mode =VRC4_mode &~0x02 | VRC4_mode <<1 &0x02; - X6502_IRQEnd(FCEU_IQEXT); - break; - } - break; - default: - index =(addr -0xB000) >>11 | addr >>1 &1; - if (addr &1) - VRC24_chr[index] =VRC24_chr[index] & 0x0F | V <<4; - else - VRC24_chr[index] =VRC24_chr[index] &~0x0F | V &0x0F; - VRC24_Sync(); - break; - } -} - -void FP_FASTAPASS(1) VRC4_cpuCycle(int a) { - while (a--) { - if (VRC4_mode &0x02 && (VRC4_mode &0x04 || (VRC4_cycles -=3) <=0)) { - if (~VRC4_mode &0x04) VRC4_cycles +=341; - if (!++VRC4_count) { - VRC4_count =VRC4_latch; - X6502_IRQBegin(FCEU_IQEXT); - } - } - } -} - -void VRC24_power(void) { - VRC24_prg[0] =0; VRC24_prg[1] =0; - VRC24_chr[0] =0; VRC24_chr[1] =1; VRC24_chr[2] =2; VRC24_chr[3] =3; VRC24_chr[4] =4; VRC24_chr[5] =5; VRC24_chr[6] =6; VRC24_chr[7] =7; - VRC24_mirroring =VRC24_misc =VRC2_pins =VRC4_latch =VRC4_mode =VRC4_count =VRC4_cycles =0; - SetReadHandler(0x6000, 0x7FFF, VRC24_wramRead); - SetWriteHandler(0x6000, 0x7FFF, VRC24_wramWrite); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, VRC24_writeReg); - VRC24_Sync(); -} - -void VRC24_close(void) { - if (WRAM) { - FCEU_gfree(WRAM); - WRAM =NULL; - } -} - -void VRC24_init(CartInfo *info, void (*_sync)(), int _A0, int _A1, uint8 _isVRC4, uint8 _useRepeatBit, uint8 defaultWRAMSizeKiB) { - VRC24_Sync =_sync; - VRC24_A0 =_A0; - VRC24_A1 =_A1; - VRC24_isVRC4 =_isVRC4; - VRC24_useRepeatBit =_useRepeatBit; - VRC24_GetPRGBank =VRC24_getPRGBank; - VRC24_GetCHRBank =VRC24_getCHRBank; - VRC24_WRAMRead =NULL; - VRC24_WRAMWrite =NULL; - VRC24_ExternalSelect =NULL; - info->Power =VRC24_power; - info->Close =VRC24_close; - GameStateRestore =_sync; - AddExState(VRC24_stateRegs, ~0, 0, 0); - if (VRC24_isVRC4) { - MapIRQHook =VRC4_cpuCycle; - AddExState(VRC4_stateRegs, ~0, 0, 0); - } else { - AddExState(VRC2_stateRegs, ~0, 0, 0); - } - - WRAMSize =info->iNES2? (info->PRGRamSize +info->PRGRamSaveSize): (defaultWRAMSizeKiB *1024); - if (WRAMSize) { - WRAM =(uint8*)FCEU_gmalloc(WRAMSize); - SetupCartPRGMapping(0x10, WRAM, WRAMSize, 1); - AddExState(WRAM, WRAMSize, 0, "WRAM"); - if (info->battery) { - info->SaveGame[0] =WRAM; - info->SaveGameLen[0] =WRAMSize; - } - } -} diff --git a/src/boards/vrc2and4.h b/src/boards/vrc2and4.h deleted file mode 100644 index 0f3445a..0000000 --- a/src/boards/vrc2and4.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef _VRC2AND4_H -#define _VRC2AND4_H - -extern int VRC24_A0, VRC24_A1; -extern uint8 VRC24_isVRC4; -extern uint8 VRC24_useRepeatBit; -extern uint8 VRC24_prg[2]; -extern uint16 VRC24_chr[8]; -extern uint8 VRC24_mirroring; -extern uint8 VRC24_misc; -extern uint8 VRC2_pins; -extern uint8 VRC4_latch; -extern uint8 VRC4_mode; -extern uint8 VRC4_count; -extern signed short int VRC4_cycles; - -extern int (*VRC24_GetPRGBank)(int); -extern int (*VRC24_GetCHRBank)(int); -extern void (*VRC24_Sync)(); -extern DECLFW((*VRC24_ExternalSelect)); -extern DECLFR((*VRC24_WRAMRead)); -extern DECLFW((*VRC24_WRAMWrite)); - -void VRC24_syncPRG (int AND, int OR); -void VRC24_syncCHR (int AND, int OR); -void VRC24_syncWRAM (int OR); -int VRC24_getPRGBank (int bank); -int VRC24_getCHRBank (int bank); -void VRC24_syncMirror (); -DECLFW(VRC24_writeReg); - -void VRC24_power(void); -void VRC24_close(void); -void VRC24_init(CartInfo *info, void (*_sync)(), int _A0, int _A1, uint8 _isVRC4, uint8 _useRepeatBit, uint8 defaultWRAMSizeKiB); - -#endif diff --git a/src/boards/wram.c b/src/boards/wram.c new file mode 100644 index 0000000..8e3de6b --- /dev/null +++ b/src/boards/wram.c @@ -0,0 +1,46 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "wram.h" + +static uint8 *WRAMData = NULL; +uint32 WRAMSize = 0; + +void WRAM_close (void) { + if (WRAMData) { + FCEU_gfree(WRAMData); + WRAMData =NULL; + } +} + +void WRAM_init (CartInfo *info, uint8 defaultWRAMSizeKiB) { + WRAMSize =info->iNES2? (info->PRGRamSize +info->PRGRamSaveSize): (defaultWRAMSizeKiB *1024); + if (WRAMSize) { + info->Close =WRAM_close; + WRAMData =(uint8*)FCEU_gmalloc(WRAMSize); + SetupCartPRGMapping(0x10, WRAMData, WRAMSize, 1); + AddExState(WRAMData, WRAMSize, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] =WRAMData; + info->SaveGameLen[0] =WRAMSize; + } + } +} diff --git a/src/boards/wram.h b/src/boards/wram.h new file mode 100644 index 0000000..2544f2d --- /dev/null +++ b/src/boards/wram.h @@ -0,0 +1,28 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _WRAM_H +#define _WRAM_H + +extern uint32 WRAMSize; +void WRAM_init (CartInfo *, uint8); +void WRAM_close (); + +#endif diff --git a/src/ines.c b/src/ines.c index c30942f..f6e9c3e 100644 --- a/src/ines.c +++ b/src/ines.c @@ -869,6 +869,7 @@ INES_BOARD_BEGIN() INES_BOARD( "NC-3000M", 443, Mapper443_Init ) INES_BOARD( "NC-7000M/NC-8000M", 444, Mapper444_Init ) INES_BOARD( "DG574B", 445, Mapper445_Init ) + INES_BOARD( "SMD172B_FPGA", 446, Mapper446_Init ) INES_BOARD( "KL-06", 447, Mapper447_Init ) INES_BOARD( "830768C", 448, Mapper448_Init ) INES_BOARD( "22-in-1 King Series", 449, Mapper449_Init ) diff --git a/src/ines.h b/src/ines.h index 07d87fc..832438b 100644 --- a/src/ines.h +++ b/src/ines.h @@ -348,6 +348,7 @@ void Mapper441_Init(CartInfo *); void Mapper443_Init(CartInfo *); void Mapper444_Init(CartInfo *); void Mapper445_Init(CartInfo *); +void Mapper446_Init(CartInfo *); void Mapper447_Init(CartInfo *); void Mapper448_Init(CartInfo *); void Mapper449_Init(CartInfo *); From 14f77b1d54ea0a3de1c1efb18d017d47172db26d Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 5 Sep 2025 23:37:53 +0200 Subject: [PATCH 002/109] Mapper 351: use the modularized ASIC cores. --- src/boards/351.c | 347 ++++++++++--------------------------- src/boards/446.c | 4 +- src/boards/asic_mmc3.c | 4 +- src/boards/asic_mmc3.h | 2 +- src/boards/asic_vrc2and4.c | 2 +- 5 files changed, 98 insertions(+), 261 deletions(-) diff --git a/src/boards/351.c b/src/boards/351.c index be65643..606361c 100644 --- a/src/boards/351.c +++ b/src/boards/351.c @@ -19,246 +19,96 @@ */ #include "mapinc.h" +#include "asic_mmc1.h" +#include "asic_mmc3.h" +#include "asic_vrc2and4.h" static uint8 reg[4], dip; -static uint8 MMC1_reg[4], MMC1_shift, MMC1_count, MMC1_filter; -static uint8 MMC3_reg[8], MMC3_index, MMC3_mirroring, MMC3_wram, MMC3_reload, MMC3_count, MMC3_irq; -static uint8 VRC4_prg[2]; -static uint8 VRC4_mirroring; -static uint8 VRC4_misc; -static uint16 VRC4_chr[8]; -static uint8 VRCIRQ_latch; -static uint8 VRCIRQ_mode; -static uint8 VRCIRQ_count; -static signed short int VRCIRQ_cycles; -static uint8 *CHRRAM =NULL; -static uint8 *PRGCHR =NULL; +static uint8 *CHRRAM = NULL; +static uint8 *PRGCHR = NULL; +static int prgMask_CHRROM; /* PRG-ROM bank mask when CHR-ROM is active (outside of PRG address space */ +static int prgMask_CHRRAM; /* PRG-ROM bank mask when CHR-RAM is active (CHR-ROM becomes part of PRG address space) */ static SFORMAT stateRegs[] = { - { reg, 4, "REGS" }, - { &dip, 1, "DIPS" }, - { MMC1_reg, 4, "MMC1" }, - { &MMC1_shift, 1, "M1SH" }, - { &MMC1_count, 1, "M1CN" }, - { &MMC1_filter, 1, "M1FI" }, - { MMC3_reg, 1, "MMC3" }, - { &MMC3_index, 1, "M3IX" }, - { &MMC3_mirroring, 1, "M3MI" }, - { &MMC3_wram, 1, "M3WR" }, - { &MMC3_reload, 1, "M3RL" }, - { &MMC3_count, 1, "M3CN" }, - { &MMC3_irq, 1, "M3IQ" }, - { VRC4_prg, 2, "V4PR" }, - { &VRC4_mirroring, 1, "V4MI" }, - { &VRC4_misc, 1, "V4MS" }, - { VRC4_chr, 16, "V4CH" }, - { &VRCIRQ_latch, 1, "VILA" }, - { &VRCIRQ_mode, 1, "VIMO" }, - { &VRCIRQ_count, 1, "VICO" }, - { &VRCIRQ_cycles, 2, "VICY" }, + { reg, 4, "REGS" }, + { &dip, 1, "DIPS" }, { 0 } }; - static void sync () { - int chrAND; - int chrOR; - int prgAND =reg[2] &0x04? 0x0F: 0x1F; - int prgOR =reg[1] >>1; - int chip =reg[2] &0x01 && CHRRAM? 0x10: 0x00; + int prgAND = reg[2] &0x10? 0x00: reg[2] &0x04? 0x0F: 0x1F; /* No inner bank in NROM mode, 128K or 256K for others */ + int chrAND = reg[2] &0x40? 0x00: reg[2] &0x20? 0x7F: reg[2] &0x10? 0x1F: 0xFF; /* No inner bank in (C)NROM mode, 128K or 256K for others */ + int prgOR = reg[1] >>1 &(reg[2] &0x01 && CHRRAM? prgMask_CHRRAM: prgMask_CHRROM) &~prgAND; + int chrOR = reg[0] <<1 &~chrAND; if (reg[2] &0x10) { /* NROM mode */ if (reg[2] &0x08) { /* NROM-64 */ - setprg8r(chip, 0x8000, prgOR); - setprg8r(chip, 0xA000, prgOR); - setprg8r(chip, 0xC000, prgOR); - setprg8r(chip, 0xE000, prgOR); + setprg8(0x8000, prgOR); + setprg8(0xA000, prgOR); + setprg8(0xC000, prgOR); + setprg8(0xE000, prgOR); } else if (reg[2] &0x04) { /* NROM-128 */ - setprg16r(chip, 0x8000, prgOR >>1); - setprg16r(chip, 0xC000, prgOR >>1); + setprg16(0x8000, prgOR >>1); + setprg16(0xC000, prgOR >>1); } else /* NROM-256 */ - setprg32r(chip, 0x8000, prgOR >>2); + setprg32(0x8000, prgOR >>2); } else - if (~reg[0] &0x02) { /* MMC3 mode */ - setprg8r(chip, 0x8000 ^(MMC3_index <<8 &0x4000), MMC3_reg[6] &prgAND | prgOR &~prgAND); - setprg8r(chip, 0xA000, MMC3_reg[7] &prgAND | prgOR &~prgAND); - setprg8r(chip, 0xC000 ^(MMC3_index <<8 &0x4000), 0xFE &prgAND | prgOR &~prgAND); - setprg8r(chip, 0xE000, 0xFF &prgAND | prgOR &~prgAND); - } else - if (reg[0] &0x01) { /* VRC4 mode */ - setprg8r(chip, 0x8000 ^(VRC4_misc <<13 &0x4000), VRC4_prg[0] &prgAND | prgOR &~prgAND); - setprg8r(chip, 0xA000, VRC4_prg[1] &prgAND | prgOR &~prgAND); - setprg8r(chip, 0xC000 ^(VRC4_misc <<13 &0x4000), 0xFE &prgAND | prgOR &~prgAND); - setprg8r(chip, 0xE000, 0xFF &prgAND | prgOR &~prgAND); - } else { /* MMC1 mode */ - prgAND >>=1; - prgOR >>=1; - if (MMC1_reg[0] &0x8) { /* 16 KiB mode */ - if (MMC1_reg[0] &0x04) { /* OR logic */ - setprg16r(chip, 0x8000, MMC1_reg[3] &prgAND | prgOR &~prgAND); - setprg16r(chip, 0xC000, 0xFF &prgAND | prgOR &~prgAND); - } else { /* AND logic */ - setprg16r(chip, 0x8000, 0x00 &prgAND | prgOR &~prgAND); - setprg16r(chip, 0xC000, MMC1_reg[3] &prgAND | prgOR &~prgAND); - } - } else - setprg32(0x8000, (MMC1_reg[3] &prgAND | prgOR &~prgAND) >>1); - } - - chrAND =reg[2] &0x10 && ~reg[2] &0x20? 0x1F: reg[2] &0x20? 0x7F: 0xFF; - chrOR =reg[0] <<1; - if (reg[2] &0x01) /* CHR RAM mode */ + if (~reg[0] &0x02) + MMC3_syncPRG(prgAND, prgOR); + else + if (reg[0] &0x01) + VRC24_syncPRG(prgAND, prgOR); + else + MMC1_syncPRG(prgAND >>1, prgOR >>1); + + if (reg[2] &0x01 && CHRRAM) setchr8r(0x10, 0); else - if (reg[2] &0x40) /* CNROM mode */ + if (reg[2] &0x40) setchr8(chrOR >>3); else - if (~reg[0] &0x02) { /* MMC3 mode */ - setchr1(0x0000 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] &0xFE)&chrAND | chrOR &~chrAND); - setchr1(0x0400 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] |0x01)&chrAND | chrOR &~chrAND); - setchr1(0x0800 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] &0xFE)&chrAND | chrOR &~chrAND); - setchr1(0x0C00 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] |0x01)&chrAND | chrOR &~chrAND); - setchr1(0x1000 ^(MMC3_index <<5 &0x1000), MMC3_reg[2] &chrAND | chrOR &~chrAND); - setchr1(0x1400 ^(MMC3_index <<5 &0x1000), MMC3_reg[3] &chrAND | chrOR &~chrAND); - setchr1(0x1800 ^(MMC3_index <<5 &0x1000), MMC3_reg[4] &chrAND | chrOR &~chrAND); - setchr1(0x1C00 ^(MMC3_index <<5 &0x1000), MMC3_reg[5] &chrAND | chrOR &~chrAND); - } else - if (reg[0] &0x01) { /* VRC4 mode */ - setchr1(0x0000, VRC4_chr[0] &chrAND | chrOR &~chrAND); - setchr1(0x0400, VRC4_chr[1] &chrAND | chrOR &~chrAND); - setchr1(0x0800, VRC4_chr[2] &chrAND | chrOR &~chrAND); - setchr1(0x0C00, VRC4_chr[3] &chrAND | chrOR &~chrAND); - setchr1(0x1000, VRC4_chr[4] &chrAND | chrOR &~chrAND); - setchr1(0x1400, VRC4_chr[5] &chrAND | chrOR &~chrAND); - setchr1(0x1800, VRC4_chr[6] &chrAND | chrOR &~chrAND); - setchr1(0x1C00, VRC4_chr[7] &chrAND | chrOR &~chrAND); - } else { /* MMC1 mode */ - chrAND >>=2; - chrOR >>=2; - if (MMC1_reg[0] &0x10) { /* 4 KiB mode */ - setchr4(0x0000, MMC1_reg[1] &chrAND | chrOR &~chrAND); - setchr4(0x1000, MMC1_reg[2] &chrAND | chrOR &~chrAND); - } else /* 8 KiB mode */ - setchr8((MMC1_reg[1] &chrAND |chrOR &~chrAND) >>1); - } - - if (~reg[0] &0x02) /* MMC3 mode */ - setmirror(MMC3_mirroring &1 ^1); + if (~reg[0] &0x02) + MMC3_syncCHR(chrAND, chrOR); else - if ( reg[0] &0x01) /* VRC4 mode */ - setmirror(VRC4_mirroring &3 ^(VRC4_mirroring &2? 0: 1)); - else /* MMC1 mode */ - setmirror(MMC1_reg[0] &3 ^3); -} - -static DECLFW(writeMMC3) { - switch(A &0xE001) { - case 0x8000: MMC3_index =V; sync(); break; - case 0x8001: MMC3_reg[MMC3_index &7] =V; sync(); break; - case 0xA000: MMC3_mirroring =V; sync(); break; - case 0xA001: MMC3_wram =V; sync(); break; - case 0xC000: MMC3_reload =V; break; - case 0xC001: MMC3_count =0; break; - case 0xE000: MMC3_irq =0; X6502_IRQEnd(FCEU_IQEXT); break; - case 0xE001: MMC3_irq =1; break; - } -} - -static DECLFW(writeMMC1) { - if (V &0x80) { - MMC1_shift =MMC1_count =0; - MMC1_reg[0] |=0x0C; - sync(); - } else - if (!MMC1_filter) { - MMC1_shift |=(V &1) <>13 &3] =MMC1_shift; - MMC1_count =0; - MMC1_shift =0; - sync(); - } - } - MMC1_filter =2; -} - -static DECLFW(writeVRC4) { - uint8 index; - if (~reg[2] &4) A =A &0xF800 | A >>1 &0x3FF; /* A2,A1 -> A1,A0 if 5002.2=1 */ - A |=A >>2 &3; /* A3,A2 -> A1,A0 */ - if (A &0x800) A =A >>1 &1 | A <<1 &2 | A &~3; /* A8==1 => Swap A1,A0 */ - switch (A &0xF000) { - case 0x8000: case 0xA000: - VRC4_prg[A >>13 &1] =V; - sync(); - break; - case 0x9000: - if (~A &2) - VRC4_mirroring =V; - else - if (~A &1) - VRC4_misc =V; - sync(); - break; - case 0xF000: - switch (A &3) { - case 0: VRCIRQ_latch =VRCIRQ_latch &0xF0 | V &0x0F; break; - case 1: VRCIRQ_latch =VRCIRQ_latch &0x0F | V <<4; break; - case 2: VRCIRQ_mode =V; - if (VRCIRQ_mode &0x02) { - VRCIRQ_count =VRCIRQ_latch; - VRCIRQ_cycles =341; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 3: VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02; - X6502_IRQEnd(FCEU_IQEXT); - break; - } - break; - default: - index =(A -0xB000) >>11 &~1 | A >>1 &1; - if (A &1) - VRC4_chr[index] =VRC4_chr[index] & 0x0F | V <<4; - else - VRC4_chr[index] =VRC4_chr[index] &~0x0F | V &0x0F; - sync(); - break; - } -} - -static void FP_FASTAPASS(1) cpuCycle(int a) { - if ((reg[0] &3) ==3) while (a--) { /* VRC4 mode */ - if (VRCIRQ_mode &0x02 && (VRCIRQ_mode &0x04 || (VRCIRQ_cycles -=3) <=0)) { - if (~VRCIRQ_mode &0x04) VRCIRQ_cycles +=341; - if (!++VRCIRQ_count) { - VRCIRQ_count =VRCIRQ_latch; - X6502_IRQBegin(FCEU_IQEXT); - } - } - } - if (MMC1_filter) MMC1_filter--; -} + if (reg[0] &0x01) + VRC24_syncCHR(chrAND, chrOR); + else + MMC1_syncCHR(chrAND >>2, chrOR >>2); -static void horizontalBlanking(void) { - if (~reg[0] &2) { /* MMC3 mode */ - MMC3_count =!MMC3_count? MMC3_reload: --MMC3_count; - if (!MMC3_count && MMC3_irq) X6502_IRQBegin(FCEU_IQEXT); - } + if (~reg[0] &0x02) + MMC3_syncMirror(); + else + if (reg[0] &0x01) + VRC24_syncMirror(); + else + MMC1_syncMirror(); } -static void applyMode() { - switch (reg[0] &3) { - case 0: - case 1: SetWriteHandler(0x8000, 0xFFFF, writeMMC3); break; - case 2: SetWriteHandler(0x8000, 0xFFFF, writeMMC1); break; - case 3: SetWriteHandler(0x8000, 0xFFFF, writeVRC4); break; - } +DECLFW(VRC24_trapWriteReg) { /* When A11 is set, VRC4's A0 and A1 are swapped */ + if (A &0x800) A = A &~0xF | A >>1 &0x5 | A <<1 &0xA; + VRC24_writeReg(A, V); +} + +static void applyMode (uint8 clear) { + PPU_hook = NULL; + MapIRQHook = NULL; + GameHBIRQHook = NULL; + if (~reg[0] &0x02) + MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, NULL); + else + if (reg[0] &0x01) { + if (reg[2] &0x04) + VRC4_activate(clear, sync, 0x05, 0x0A, 1, NULL, NULL, NULL, NULL, NULL); + else + VRC4_activate(clear, sync, 0x02, 0x04, 1, NULL, NULL, NULL, NULL, NULL); + SetWriteHandler(0x8000, 0xFFFF, VRC24_trapWriteReg); + } else + MMC1_activate(clear, sync, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL); } static void Mapper351_restore (int version) { - applyMode(); + applyMode(0); sync(); } @@ -267,74 +117,61 @@ static DECLFR(readDIP) { } static DECLFW(writeReg) { - uint8 previousMode =reg[0] &3; - reg[A &3] =V; - if ((reg[0] &3) !=previousMode) applyMode(); - sync(); + reg[A &3] = V; + applyMode(A == 2); } static DECLFW(writeFDSMirroring) { - MMC3_mirroring =V >>3 &1; - sync(); + MMC3_writeReg(0xA000, V >>3 &1); } static void Mapper351_power(void) { - int i; - for (i =0; i <4; i++) reg[i] =0; - for (i =0; i <4; i++) MMC1_reg[i] =0; - for (i =0; i <8; i++) MMC3_reg[i] =0; - for (i =0; i <2; i++) VRC4_prg[i] =0; - for (i =0; i <8; i++) VRC4_chr[i] =0; - MMC1_shift =MMC1_count =MMC1_filter =0; - MMC1_reg[0] =0x0C; - MMC3_index =MMC3_mirroring =MMC3_wram =MMC3_reload =MMC3_count =MMC3_irq =0; - VRC4_mirroring =VRC4_misc =VRCIRQ_latch =VRCIRQ_mode =VRCIRQ_count =VRCIRQ_cycles =0; - dip =0; - - SetReadHandler(0x6000, 0xFFFF, CartBR); + reg[0] = reg[1] = reg[2] = reg[3] = 0; + dip = 0; SetReadHandler(0x5000, 0x5FFF, readDIP); + SetReadHandler(0x6000, 0xFFFF, CartBR); SetWriteHandler(0x5000, 0x5FFF, writeReg); SetWriteHandler(0x4025, 0x4025, writeFDSMirroring); - applyMode(); - sync(); + applyMode(1); } static void Mapper351_reset (void) { - int i; - for (i =0; i <4; i++) reg[i] =0; + reg[0] = reg[1] = reg[2] = reg[3] = 0; dip++; - applyMode(); - sync(); + applyMode(1); } static void Mapper351_close(void) { if (CHRRAM) FCEU_gfree(CHRRAM); if (PRGCHR) FCEU_gfree(PRGCHR); - CHRRAM =NULL; - PRGCHR =NULL; + CHRRAM = NULL; + PRGCHR = NULL; } void Mapper351_Init (CartInfo *info) { - int CHRRAMSIZE =info->CHRRamSize + info->CHRRamSaveSize; - + int CHRRAMSIZE = info->CHRRamSize + info->CHRRamSaveSize; + MMC1_addExState(); + MMC3_addExState(); + VRC24_addExState(); info->Reset = Mapper351_reset; info->Power = Mapper351_power; info->Close = Mapper351_close; - MapIRQHook = cpuCycle; - GameHBIRQHook = horizontalBlanking; GameStateRestore = Mapper351_restore; - AddExState(stateRegs, ~0, 0, 0); - + AddExState(stateRegs, ~0, 0, 0); + + /* When CHR-RAM is enabled, CHR-ROM becomes part of PRG-ROM address space. */ + prgMask_CHRROM = prgMask_CHRRAM = PRGsize[0] /8192 -1; if (CHRRAMSIZE) { - CHRRAM =(uint8 *)FCEU_gmalloc(CHRRAMSIZE); + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); - - /* This crazy thing can map CHR-ROM into CPU address space. Allocate a combined PRG+CHR address space and treat it a second "chip". */ - PRGCHR =(uint8 *)FCEU_gmalloc(PRGsize[0] +CHRsize[0]); - memcpy(PRGCHR, PRGptr[0], PRGsize[0]); - memcpy(PRGCHR +PRGsize[0], CHRptr[0], CHRsize[0]); - SetupCartPRGMapping(0x10, PRGCHR, PRGsize[0] +CHRsize[0], 0); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); + prgMask_CHRRAM = (PRGsize[0] +CHRsize[0]) /8192 -1; + uint8* newROM = (uint8*)FCEU_gmalloc(PRGsize[0] +CHRsize[0]); + memcpy(newROM, ROM, info->PRGRomSize); + memcpy(newROM +PRGsize[0], VROM, info->CHRRomSize); + FCEU_gfree(ROM); + ROM = newROM; + SetupCartPRGMapping(0, ROM, PRGsize[0] +CHRsize[0], 0); } } diff --git a/src/boards/446.c b/src/boards/446.c index 76551e8..3dfcb9d 100644 --- a/src/boards/446.c +++ b/src/boards/446.c @@ -284,7 +284,7 @@ static void applyMode (uint8 clear) { case 0x004: case 0x101: case 0x201: case 0x209: /* MMC3 or Namco 118 */ mapperSync = sync_TxROM; MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, NULL); - if (clear) MMC3_write(0xA000, reg[4] &0x04? 0: 1); + if (clear) MMC3_writeReg(0xA000, reg[4] &0x04? 0: 1); break; case 0x10E: case 0x20E: /* MMC3 with single-screen mirroring. 239-in-1's Goal! Two has a screen where MMC3 scanline counter emulation fails. */ mapperSync = sync_TxSROM; @@ -383,7 +383,7 @@ static void applyMode (uint8 clear) { SetWriteHandler(0x8000, 0xFFFF, writeFlash); mapperSync = sync_supervisor; PPU_hook = NULL; - MapIRQHook =flashrom_cpuCycle; + MapIRQHook = flashrom_cpuCycle; GameHBIRQHook = NULL; sync(); } diff --git a/src/boards/asic_mmc3.c b/src/boards/asic_mmc3.c index 2b8b4ea..af018a6 100644 --- a/src/boards/asic_mmc3.c +++ b/src/boards/asic_mmc3.c @@ -97,7 +97,7 @@ void MMC3_clockCounter () { MMC3_reloadRequest = 0; } -DECLFW(MMC3_write) { +DECLFW(MMC3_writeReg) { switch(A &0xE001) { case 0x8000: MMC3_index = V; break; case 0x8001: MMC3_reg[MMC3_index &7] = V; break; @@ -121,7 +121,7 @@ static void MMC3_setHandlers () { SetReadHandler (0x6000, 0x7FFF, MMC3_readWRAM); SetWriteHandler(0x6000, 0x7FFF, MMC3_writeWRAM); SetReadHandler (0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, MMC3_write); + SetWriteHandler(0x8000, 0xFFFF, MMC3_writeReg); GameHBIRQHook = MMC3_clockCounter; } diff --git a/src/boards/asic_mmc3.h b/src/boards/asic_mmc3.h index 0f78399..448f1ab 100644 --- a/src/boards/asic_mmc3.h +++ b/src/boards/asic_mmc3.h @@ -34,7 +34,7 @@ void MMC3_syncPRG (int, int); void MMC3_syncCHR (int, int); void MMC3_syncMirror (); void MMC3_clockCounter (); -DECLFW (MMC3_write); +DECLFW (MMC3_writeReg); void MMC3_activate (uint8, void (*)(), uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*))); void MMC3_addExState(); void MMC3_restore (int); diff --git a/src/boards/asic_vrc2and4.c b/src/boards/asic_vrc2and4.c index a457185..c2e1d3d 100644 --- a/src/boards/asic_vrc2and4.c +++ b/src/boards/asic_vrc2and4.c @@ -286,7 +286,7 @@ void VRC2_init (CartInfo *info, void (*sync)(), int A0, int A1, int (*prg)(uint8 VRC2_addExState(); VRC2_configure(sync, A0, A1, prg, chr, read, write); info->Power = VRC24_power; - GameStateRestore = VRC24_cbSync; + GameStateRestore = VRC24_restore; } void VRC4_init (CartInfo *info, void (*sync)(), int A0, int A1, uint8 useRepeatBit, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write)), DECLFW((*externalSelect))) { From dbe15a79105cf01a9ee75dfe876e26e46ac7134d Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sat, 6 Sep 2025 00:15:49 +0200 Subject: [PATCH 003/109] Mapper 445: use the modularized ASIC cores. --- src/boards/445.c | 244 ++++++++++------------------------------------- 1 file changed, 51 insertions(+), 193 deletions(-) diff --git a/src/boards/445.c b/src/boards/445.c index 19980d8..80bc5ac 100644 --- a/src/boards/445.c +++ b/src/boards/445.c @@ -19,242 +19,100 @@ */ #include "mapinc.h" +#include "asic_latch.h" +#include "asic_mmc3.h" +#include "asic_vrc2and4.h" -static uint8 reg[5], dip; /* Fourth register is the CNROM latch */ -static uint8 MMC3_reg[8], MMC3_index, MMC3_mirroring, MMC3_wram, MMC3_reload, MMC3_count, MMC3_irq; -static uint8 VRC4_prg[2]; -static uint8 VRC4_mirroring; -static uint8 VRC4_misc; -static uint16 VRC4_chr[8]; -static uint8 VRCIRQ_latch; -static uint8 VRCIRQ_mode; -static uint8 VRCIRQ_count; -static signed short int VRCIRQ_cycles; -static uint8 *PRGCHR =NULL; +static uint8 reg[4]; +static uint8 dip; static SFORMAT stateRegs[] = { - { reg, 5, "REGS" }, - { &dip, 1, "DIPS" }, - { MMC3_reg, 1, "MMC3" }, - { &MMC3_index, 1, "M3IX" }, - { &MMC3_mirroring, 1, "M3MI" }, - { &MMC3_wram, 1, "M3WR" }, - { &MMC3_reload, 1, "M3RL" }, - { &MMC3_count, 1, "M3CN" }, - { &MMC3_irq, 1, "M3IQ" }, - { VRC4_prg, 2, "V4PR" }, - { &VRC4_mirroring, 1, "V4MI" }, - { &VRC4_misc, 1, "V4MS" }, - { VRC4_chr, 16, "V4CH" }, - { &VRCIRQ_latch, 1, "VILA" }, - { &VRCIRQ_mode, 1, "VIMO" }, - { &VRCIRQ_count, 1, "VICO" }, - { &VRCIRQ_cycles, 2, "VICY" }, + { reg, 4, "REGS" }, + { &dip, 1, "DIPS" }, { 0 } }; - static void sync () { - int chrAND; - int chrOR; - /*/ 5003.0-2: PRG size (1 MiB->8 KiB, although 1 MiB and 512 KiB are not connected and so function as 256 KiB) and mode (>=64 KiB: MMC3, <64 KiB: NROM-256/128/64) */ - int prgAND =0x7F >>(reg[2] &7) &0x1F; + int prgAND = 0x7F >>(reg[2] &7) &0x1F; /* 5003.0-2: PRG size (1 MiB->8 KiB, although 1 MiB and 512 KiB are not connected and so function as 256 KiB) and mode (>=64 KiB: MMC3, <64 KiB: NROM-256/128/64) */ + int chrAND = 0x3FF >>(reg[2] >>3 &7) &0xFF; /* 5003.3-5: CHR size (1 MiB->8 KiB, though 1 MiB and 512 KiB are not reachable with inner bank registers and so function as 256 KiB) and mode (>=64 KiB: MMC3, <64 KiB: (C)NROM-256/128/64) */ + int prgOR = reg[0] &~prgAND; + int chrOR = reg[1] <<3 &~chrAND; + if (prgAND &0x04) { - if (reg[3] &0x10) { - setprg8(0x8000 ^(VRC4_misc <<13 &0x4000), VRC4_prg[0] &prgAND | reg[0] &~prgAND); - setprg8(0xA000, VRC4_prg[1] &prgAND | reg[0] &~prgAND); - setprg8(0xC000 ^(VRC4_misc <<13 &0x4000), 0xFE &prgAND | reg[0] &~prgAND); - setprg8(0xE000, 0xFF &prgAND | reg[0] &~prgAND); - } else { - setprg8(0x8000 ^(MMC3_index <<8 &0x4000), MMC3_reg[6] &prgAND | reg[0] &~prgAND); - setprg8(0xA000, MMC3_reg[7] &prgAND | reg[0] &~prgAND); - setprg8(0xC000 ^(MMC3_index <<8 &0x4000), 0xFE &prgAND | reg[0] &~prgAND); - setprg8(0xE000, 0xFF &prgAND | reg[0] &~prgAND); - } + if (reg[3] &0x10) + VRC24_syncPRG(prgAND, prgOR); + else + MMC3_syncPRG(prgAND, prgOR); } else { - setprg8(0x8000, 0 &prgAND | reg[0] &~prgAND); - setprg8(0xA000, 1 &prgAND | reg[0] &~prgAND); - setprg8(0xC000, 2 &prgAND | reg[0] &~prgAND); - setprg8(0xE000, 3 &prgAND | reg[0] &~prgAND); + setprg8(0x8000, 0 &prgAND | prgOR); + setprg8(0xA000, 1 &prgAND | prgOR); + setprg8(0xC000, 2 &prgAND | prgOR); + setprg8(0xE000, 3 &prgAND | prgOR); } - - /* // 5003.3-5: CHR size (1 MiB->8 KiB, though 1 MiB and 512 KiB are not reachable with inner bank registers and so function as 256 KiB) and mode (>=64 KiB: MMC3, <64 KiB: (C)NROM-256/128/64) */ - chrAND =0x3FF >>(reg[2] >>3 &7) &0xFF; if (chrAND &0x20) { - if (reg[3] &0x10) { - setchr1(0x0000, VRC4_chr[0] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x0400, VRC4_chr[1] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x0800, VRC4_chr[2] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x0C00, VRC4_chr[3] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x1000, VRC4_chr[4] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x1400, VRC4_chr[5] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x1800, VRC4_chr[6] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x1C00, VRC4_chr[7] &chrAND | (reg[1] <<3) &~chrAND); - } else { - setchr1(0x0000 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] &0xFE)&chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x0400 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] |0x01)&chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x0800 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] &0xFE)&chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x0C00 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] |0x01)&chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x1000 ^(MMC3_index <<5 &0x1000), MMC3_reg[2] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x1400 ^(MMC3_index <<5 &0x1000), MMC3_reg[3] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x1800 ^(MMC3_index <<5 &0x1000), MMC3_reg[4] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x1C00 ^(MMC3_index <<5 &0x1000), MMC3_reg[5] &chrAND | (reg[1] <<3) &~chrAND); - } + if (reg[3] &0x10) + VRC24_syncCHR(chrAND, chrOR); + else + MMC3_syncCHR(chrAND, chrOR); } else { - chrAND >>=3; - setchr8(reg[4] &chrAND | reg[1] &~chrAND); + chrAND >>= 3; + chrOR >>= 3; + setchr8(Latch_data &chrAND | chrOR); } - if (reg[3] &0x10) - setmirror(VRC4_mirroring &3 ^(VRC4_mirroring &2? 0: 1)); + VRC24_syncMirror(); else - setmirror(MMC3_mirroring &1 ^1); - - SetReadHandler(0x8000, 0xFFFF, reg[0] &0xC0 && (reg[0] &0xC0) ==dip? NULL: CartBR); + MMC3_syncMirror(); + SetReadHandler(0x8000, 0xFFFF, reg[0] &0xC0 && (reg[0] &0xC0) == dip? NULL: CartBR); } -static DECLFW(writeCNROM) { - reg[4] =V; - sync(); -} - -static DECLFW(writeMMC3) { - switch(A &0xE001) { - case 0x8000: MMC3_index =V; sync(); break; - case 0x8001: MMC3_reg[MMC3_index &7] =V; sync(); break; - case 0xA000: MMC3_mirroring =V; sync(); break; - case 0xA001: MMC3_wram =V; sync(); break; - case 0xC000: MMC3_reload =V; break; - case 0xC001: MMC3_count =0; break; - case 0xE000: MMC3_irq =0; X6502_IRQEnd(FCEU_IQEXT); break; - case 0xE001: MMC3_irq =1; break; - } -} - -static DECLFW(writeVRC4) { - uint8 index; - if (reg[3] &1) - A =(A &0xA? 1: 0) | (A &0x5? 2: 0) | A &0xF000; +static void applyMode(uint8 clear) { + if ((reg[2] >>3 &7) >= 5) + Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); else - A =(A &0x5? 1: 0) | (A &0xA? 2: 0) | A &0xF000; - switch (A &0xF000) { - case 0x8000: case 0xA000: - VRC4_prg[A >>13 &1] =V; - sync(); - break; - case 0x9000: - if (~A &2) - VRC4_mirroring =V; + if (reg[3] &0x10) { + if (reg[3] &0x01) + VRC4_activate(clear, sync, 0x0A, 0x05, 1, NULL, NULL, NULL, NULL, NULL); else - if (~A &1) - VRC4_misc =V; - sync(); - break; - case 0xF000: - switch (A &3) { - case 0: VRCIRQ_latch =VRCIRQ_latch &0xF0 | V &0x0F; break; - case 1: VRCIRQ_latch =VRCIRQ_latch &0x0F | V <<4; break; - case 2: VRCIRQ_mode =V; - if (VRCIRQ_mode &0x02) { - VRCIRQ_count =VRCIRQ_latch; - VRCIRQ_cycles =341; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 3: VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02; - X6502_IRQEnd(FCEU_IQEXT); - break; - } - break; - default: - index =(A -0xB000) >>11 &~1 | A >>1 &1; - if (A &1) - VRC4_chr[index] =VRC4_chr[index] & 0x0F | V <<4; - else - VRC4_chr[index] =VRC4_chr[index] &~0x0F | V &0x0F; - sync(); - break; - } -} - -static void FP_FASTAPASS(1) cpuCycle(int a) { - if ((reg[0] &3) ==3) while (a--) { /* VRC4 mode */ - if (VRCIRQ_mode &0x02 && (VRCIRQ_mode &0x04 || (VRCIRQ_cycles -=3) <=0)) { - if (~VRCIRQ_mode &0x04) VRCIRQ_cycles +=341; - if (!++VRCIRQ_count) { - VRCIRQ_count =VRCIRQ_latch; - X6502_IRQBegin(FCEU_IQEXT); - } - } - } -} - -static void horizontalBlanking(void) { - if (~reg[0] &2) { /* MMC3 mode */ - MMC3_count =!MMC3_count? MMC3_reload: --MMC3_count; - if (!MMC3_count && MMC3_irq) X6502_IRQBegin(FCEU_IQEXT); - } -} - -static void applyMode() { - if ((reg[2] >>3 &7) >=5) - SetWriteHandler(0x8000, 0xFFFF, writeCNROM); - else - if (reg[3] &0x10) - SetWriteHandler(0x8000, 0xFFFF, writeVRC4); - else - SetWriteHandler(0x8000, 0xFFFF, writeMMC3); + VRC4_activate(clear, sync, 0x05, 0x0A, 1, NULL, NULL, NULL, NULL, NULL); + } else + MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, NULL); } static void Mapper445_restore (int version) { - applyMode(); + applyMode(0); sync(); } static DECLFW(writeReg) { if (~reg[3] &0x20) { - reg[A &3] =V; - if ((A &3) ==3) applyMode(); + reg[A &3] = V; + if ((A &3) == 3) applyMode(1); sync(); } } static void Mapper445_power(void) { - int i; - for (i =0; i <4; i++) reg[i] =0; - for (i =0; i <8; i++) MMC3_reg[i] =0; - for (i =0; i <2; i++) VRC4_prg[i] =0; - for (i =0; i <8; i++) VRC4_chr[i] =0; - MMC3_index =MMC3_mirroring =MMC3_wram =MMC3_reload =MMC3_count =MMC3_irq =0; - VRC4_mirroring =VRC4_misc =VRCIRQ_latch =VRCIRQ_mode =VRCIRQ_count =VRCIRQ_cycles =0; + reg[0] = reg[1] = reg[2] = reg[3] = 0; dip =0; - SetReadHandler(0x6000, 0xFFFF, CartBR); SetWriteHandler(0x5000, 0x5FFF, writeReg); - applyMode(); - sync(); + applyMode(1); } static void Mapper445_reset (void) { - int i; - for (i =0; i <5; i++) reg[i] =0; - dip +=0x40; - applyMode(); - sync(); -} - -static void Mapper445_close(void) { - if (PRGCHR) FCEU_gfree(PRGCHR); - PRGCHR =NULL; + reg[0] = reg[1] = reg[2] = reg[3] = 0; + dip += 0x40; + applyMode(1); } void Mapper445_Init (CartInfo *info) { + Latch_addExState(); + MMC3_addExState(); + VRC24_addExState(); info->Reset = Mapper445_reset; info->Power = Mapper445_power; - info->Close = Mapper445_close; - MapIRQHook = cpuCycle; - GameHBIRQHook = horizontalBlanking; GameStateRestore = Mapper445_restore; - AddExState(stateRegs, ~0, 0, 0); + AddExState(stateRegs, ~0, 0, 0); } From bf1aa2b02d717be55de700c0b102beb9ec70f83d Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sat, 6 Sep 2025 01:52:42 +0200 Subject: [PATCH 004/109] Mapper 556: use the modularized ASIC cores. --- src/boards/556.c | 336 +++++++-------------------------------- src/boards/asic_tc3294.c | 8 +- 2 files changed, 58 insertions(+), 286 deletions(-) diff --git a/src/boards/556.c b/src/boards/556.c index 04fa6b3..c1806f5 100644 --- a/src/boards/556.c +++ b/src/boards/556.c @@ -19,312 +19,84 @@ */ /* NES 2.0 Mapper 556 - * Used for the for the 超强小新2+瑪莉家族 7-in-1 (JY-215) multicart. + * Used for the for the 餓狼傳說 激鬥篇 HiK 7-in-1 (JY-215) multicart. */ #include "mapinc.h" +#include "asic_mmc3.h" +#include "asic_vrc2and4.h" +#include "wram.h" -static uint8 reg[5]; -static uint8 mmc3Reg[8]; -static uint8 mmc3Cmd; -static uint8 mmc3Mirr; -static uint8 mmc3Wram; -static uint8 mmc3IRQLatch; -static uint8 mmc3IRQCount; -static uint8 mmc3IRQa; -static uint8 mmc3IRQReload; -static uint8 vrc4Prg[2]; -static uint8 vrc4Mirr; -static uint8 vrc4Misc; -static uint16 vrc4Chr[8]; -static uint8 vrc4IRQLatch; -static uint8 vrc4IRQa; -static uint8 vrc4IRQCount; -static int16 vrc4IRQCycles; -static uint8 *WRAM = NULL; -static uint32 WRAMSIZE = 0; +static uint8 reg[4]; +static uint8 index; static SFORMAT StateRegs[] = { { reg, 5, "REGS" }, - { mmc3Reg, 8, "MMC3" }, - { &mmc3Cmd, 1, "M3IX" }, - { &mmc3Mirr, 1, "M3MI" }, - { &mmc3Wram, 1, "M3WR" }, - { &mmc3IRQLatch, 1, "M3RL" }, - { &mmc3IRQCount, 1, "M3CN" }, - { &mmc3IRQa, 1, "M3IQ" }, - { &mmc3IRQReload, 1, "M3IR" }, - { vrc4Prg, 2, "V4PR" }, - { &vrc4Mirr, 1, "V4MI" }, - { &vrc4Misc, 1, "V4MS" }, - { vrc4Chr, 16, "V4CH" }, - { &vrc4IRQLatch, 1, "VILA" }, - { &vrc4IRQa, 1, "VIMO" }, - { &vrc4IRQCount, 1, "VICO" }, - { &vrc4IRQCycles, 2, "VICY" }, + { &index, 1, "INDX" }, { 0 }, }; -static void Sync(void) { - uint32 prgmask = ~reg[3] & 0x3F; - uint32 prgbase = ((reg[3] & 0x40) << 2) | reg[1]; - uint32 chrmask = 0xFF >> (~reg[2] & 0x0F); - uint32 chrbase = ((reg[3] & 0x40) << 6) | ((reg[2] & 0xF0) << 4) | reg[0]; - uint32 cbase = 0; /* prg/chr bank flip flag */ - - if (~reg[2] & 0x80) { - /* MMC3 */ - cbase = (mmc3Cmd << 8) & 0x4000; - setprg8(0x8000 ^ cbase, (prgbase & ~prgmask) | (mmc3Reg[6] & prgmask)); - setprg8(0xA000, (prgbase & ~prgmask) | (mmc3Reg[7] & prgmask)); - setprg8(0xC000 ^ cbase, (prgbase & ~prgmask) | (0xFE & prgmask)); - setprg8(0xE000, (prgbase & ~prgmask) | (0xFF & prgmask)); - - cbase = (mmc3Cmd << 5) & 0x1000; - setchr1(0x0000 ^ cbase, (chrbase & ~chrmask) | ((mmc3Reg[0] & 0xFE) & chrmask)); - setchr1(0x0400 ^ cbase, (chrbase & ~chrmask) | ((mmc3Reg[0] | 0x01) & chrmask)); - setchr1(0x0800 ^ cbase, (chrbase & ~chrmask) | ((mmc3Reg[1] & 0xFE) & chrmask)); - setchr1(0x0C00 ^ cbase, (chrbase & ~chrmask) | ((mmc3Reg[1] | 0x01) & chrmask)); - setchr1(0x1000 ^ cbase, (chrbase & ~chrmask) | (mmc3Reg[2] & chrmask)); - setchr1(0x1400 ^ cbase, (chrbase & ~chrmask) | (mmc3Reg[3] & chrmask)); - setchr1(0x1800 ^ cbase, (chrbase & ~chrmask) | (mmc3Reg[4] & chrmask)); - setchr1(0x1C00 ^ cbase, (chrbase & ~chrmask) | (mmc3Reg[5] & chrmask)); - - setmirror((mmc3Mirr & 0x01) ^ 1); +static void sync (void) { + int prgAND = ~reg[3] &0x3F; + int chrAND = 0xFF >>(~reg[2] &0xF); + int prgOR = (reg[1] | reg[3] <<2 &0x100) &~prgAND; + int chrOR = (reg[0] | reg[2] <<4 &0x0F00 | reg[3] <<6 &0x1000) &~chrAND; + if (reg[2] &0x80) { + VRC24_syncWRAM(0); + VRC24_syncPRG(prgAND, prgOR); + VRC24_syncCHR(chrAND, chrOR); + VRC24_syncMirror(); } else { - /* VRC4 mode */ - cbase = (vrc4Misc << 13) & 0x4000; - setprg8(0x8000 ^ cbase, (prgbase & ~prgmask) | (vrc4Prg[0] & prgmask)); - setprg8(0xA000, (prgbase & ~prgmask) | (vrc4Prg[1] & prgmask)); - setprg8(0xC000 ^ cbase, (prgbase & ~prgmask) | (0xFE & prgmask)); - setprg8(0xE000, (prgbase & ~prgmask) | (0xFF & prgmask)); - - setchr1(0x0000, (chrbase & ~chrmask) | (vrc4Chr[0] & chrmask)); - setchr1(0x0400, (chrbase & ~chrmask) | (vrc4Chr[1] & chrmask)); - setchr1(0x0800, (chrbase & ~chrmask) | (vrc4Chr[2] & chrmask)); - setchr1(0x0C00, (chrbase & ~chrmask) | (vrc4Chr[3] & chrmask)); - setchr1(0x1000, (chrbase & ~chrmask) | (vrc4Chr[4] & chrmask)); - setchr1(0x1400, (chrbase & ~chrmask) | (vrc4Chr[5] & chrmask)); - setchr1(0x1800, (chrbase & ~chrmask) | (vrc4Chr[6] & chrmask)); - setchr1(0x1C00, (chrbase & ~chrmask) | (vrc4Chr[7] & chrmask)); - - switch (vrc4Mirr & 0x03) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_0); break; - case 3: setmirror(MI_1); break; - } + MMC3_syncWRAM(0); + MMC3_syncPRG(prgAND, prgOR); + MMC3_syncCHR(chrAND, chrOR); + MMC3_syncMirror(); } } -static DECLFW(writeMMC3) { - switch (A & 0xE001) { - case 0x8000: - mmc3Cmd = V; - Sync(); - break; - case 0x8001: - mmc3Reg[mmc3Cmd & 7] = V; - Sync(); - break; - case 0xA000: - mmc3Mirr = V; - Sync(); - break; - case 0xA001: - mmc3Wram = V; - Sync(); - break; - case 0xC000: - mmc3IRQLatch = V; - break; - case 0xC001: - mmc3IRQReload = 1; - break; - case 0xE000: - mmc3IRQa = 0; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xE001: - mmc3IRQa = 1; - break; +static void applyMode (uint8 clear) { + if (reg[2] &0x80) + VRC4_activate(clear, sync, 0x05, 0x0A, 1, NULL, NULL, NULL, NULL, NULL); + else + MMC3_activate(clear, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, NULL); +} + +static DECLFW(writeReg) { + if (~reg[3] &0x80) { + reg[index++ &3] = V; + if (index == 3) + applyMode(1); + else + sync(); } } -static DECLFW(writeVRC4) { - uint8 index; - A = (A & 0xF000) | ((A >> 2) & 3) | (A & 3); - switch (A & 0xF000) { - case 0x8000: - case 0xA000: - vrc4Prg[(A >> 13) & 1] = V; - Sync(); - break; - case 0x9000: - if (~A & 2) { - vrc4Mirr = V; - } else if (~A & 1) { - vrc4Misc = V; - } - Sync(); - break; - case 0xF000: - switch (A & 3) { - case 0: - vrc4IRQLatch = (vrc4IRQLatch & 0xF0) | (V & 0x0F); - break; - case 1: - vrc4IRQLatch = (vrc4IRQLatch & 0x0F) | (V << 4); - break; - case 2: - vrc4IRQa = V; - if (vrc4IRQa & 0x02) { - vrc4IRQCount = vrc4IRQLatch; - vrc4IRQCycles = 341; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 3: - vrc4IRQa = (vrc4IRQa & ~0x02) | ((vrc4IRQa << 1) & 0x02); - X6502_IRQEnd(FCEU_IQEXT); - break; - } - break; - default: - index = ((A - 0xB000) >> 11) | ((A >> 1) & 1); - if (A & 1) { - vrc4Chr[index] = (vrc4Chr[index] & 0x0F) | (V << 4); - } else { - vrc4Chr[index] = (vrc4Chr[index] & ~0x0F) | (V & 0x0F); - } - Sync(); - break; - } -} - -static DECLFW(M556WriteReg) { - if (~reg[3] & 0x80) { - reg[reg[4] & 3] = V; - reg[4]++; - Sync(); - } -} - -static DECLFW(M556Write) { - if (~reg[2] & 0x80) { - writeMMC3(A, V); - } else { - writeVRC4(A, V); - } -} - -static void FP_FASTAPASS(1) M556CPUHook(int a) { - int count = a; - - if (~reg[2] & 0x80) { - return; - } - - /* VRC4 IRQ mode */ - while (count--) { - if ((vrc4IRQa & 0x02) && ((vrc4IRQa & 0x04) || ((vrc4IRQCycles -= 3) <= 0))) { - if (~vrc4IRQa & 0x04) { - vrc4IRQCycles += 341; - } - if (!++vrc4IRQCount) { - vrc4IRQCount = vrc4IRQLatch; - X6502_IRQBegin(FCEU_IQEXT); - } - } - } -} - -static void M556HBHook(void) { - int count = mmc3IRQCount; - - if (reg[2] & 0x80) { - return; - } - - /* MMC3 IRQ mode */ - if (!count || mmc3IRQReload) { - mmc3IRQCount = mmc3IRQLatch; - } else { - mmc3IRQCount--; - } - if (count && !mmc3IRQCount && mmc3IRQa) { - X6502_IRQBegin(FCEU_IQEXT); - } - mmc3IRQReload = 0; -} - -static void M556Reset(void) { - int i; - for (i = 0; i < 5; i++) { - reg[i] = 0; - } +static void reset (void) { + reg[0] = reg[1] = reg[3] = 0; reg[2] = 0x0F; - Sync(); + index = 0; + applyMode(1); } -static void M556Power(void) { - int i; - for (i = 0; i < 5; i++) { - reg[i] = 0; - } - for (i = 0; i < 8; i++) { - mmc3Reg[i] = 0; - } - for (i = 0; i < 2; i++) { - vrc4Prg[i] = 0; - } - for (i = 0; i < 8; i++) { - vrc4Chr[i] = 0; - } - mmc3Cmd = mmc3Mirr = mmc3Wram = mmc3IRQLatch = mmc3IRQCount = mmc3IRQa = mmc3IRQReload = 0; - vrc4Mirr = vrc4Misc = vrc4IRQLatch = vrc4IRQa = vrc4IRQCount = vrc4IRQCycles = 0; +static void power (void) { + reg[0] = reg[1] = reg[3] = 0; reg[2] = 0x0F; - Sync(); - - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x5000, 0x5FFF, M556WriteReg); - SetWriteHandler(0x8000, 0xFFFF, M556Write); - - if (WRAM) { - setprg8r(0x10, 0x6000, 0); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - } + index = 0; + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x5000, 0x5FFF, writeReg); + applyMode(1); } -static void M556Close(void) { - if (WRAM) { - FCEU_gfree(WRAM); - } - WRAM = NULL; +static void restore (int version) { + applyMode(0); } -static void StateRestore(int version) { - Sync(); -} - -void Mapper556_Init(CartInfo *info) { - info->Reset = M556Reset; - info->Power = M556Power; - info->Close = M556Close; - MapIRQHook = M556CPUHook; - GameHBIRQHook = M556HBHook; - GameStateRestore = StateRestore; +void Mapper556_Init (CartInfo *info) { + MMC3_addExState(); + VRC24_addExState(); + WRAM_init(info, 8); + info->Reset = reset; + info->Power = power; + GameStateRestore = restore; AddExState(StateRegs, ~0, 0, 0); - - WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - } } diff --git a/src/boards/asic_tc3294.c b/src/boards/asic_tc3294.c index 04a9787..467bb48 100644 --- a/src/boards/asic_tc3294.c +++ b/src/boards/asic_tc3294.c @@ -37,14 +37,14 @@ void TC3294_syncWRAM (int OR) { } void TC3294_syncPRG (int AND, int OR) { - int prgAND =~TC3294_reg[3] &0x3F; + int prgAND = ~TC3294_reg[3] &0x3F; int prgOR = TC3294_reg[1] | TC3294_reg[2] <<2 &0x300; MMC3_syncPRG(prgAND &AND, prgOR &~prgAND &AND | OR &~AND); } void TC3294_syncCHR (int AND, int OR) { - int chrAND =0xFF >>(~TC3294_reg[2] &0xF); - int chrOR =TC3294_reg[0] | TC3294_reg[2] <<4 &0xF00; + int chrAND = 0xFF >>(~TC3294_reg[2] &0xF); + int chrOR = TC3294_reg[0] | TC3294_reg[2] <<4 &0xF00; MMC3_syncCHR(chrAND &AND, chrOR &~chrAND &AND | OR &~AND); } @@ -54,7 +54,7 @@ void TC3294_syncMirror () { DECLFW(TC3294_write) { if (~TC3294_reg[3] &0x40) { - TC3294_reg[TC3294_index++ &3] =V; + TC3294_reg[TC3294_index++ &3] = V; TC3294_cbSync(); } } From b5fff6c80f380885fdb04b679e232265ef41f211 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sat, 6 Sep 2025 02:19:07 +0200 Subject: [PATCH 005/109] Mapper 116: use the modularized ASIC cores. --- src/boards/116.c | 416 +++++++++-------------------------------- src/boards/asic_mmc1.c | 4 +- src/boards/asic_mmc1.h | 2 +- 3 files changed, 91 insertions(+), 331 deletions(-) diff --git a/src/boards/116.c b/src/boards/116.c index b9c8b2c..f9052d4 100644 --- a/src/boards/116.c +++ b/src/boards/116.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2011 CaH4e3 + * Copyright (C) 2023 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,353 +16,113 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * SL12 Protected 3-in-1 mapper hardware (VRC2, MMC3, MMC1) - * the same as 603-5052 board (TODO: add reading registers, merge) - * SL1632 2-in-1 protected board, similar to SL12 (TODO: find difference) - * - * Known PCB: - * - * Garou Densetsu Special (G0904.PCB, Huang-1, GAL dip: W conf.) - * Kart Fighter (008, Huang-1, GAL dip: W conf.) - * Somari (008, C5052-13, GAL dip: P conf., GK2-P/GK2-V maskroms) - * Somari (008, Huang-1, GAL dip: W conf., GK1-P/GK1-V maskroms) - * AV Mei Shao Nv Zhan Shi (aka AV Pretty Girl Fighting) (SL-12 PCB, Hunag-1, GAL dip: unk conf. SL-11A/SL-11B maskroms) - * Samurai Spirits (Full version) (Huang-1, GAL dip: unk conf. GS-2A/GS-4A maskroms) - * Contra Fighter (603-5052 PCB, C5052-3, GAL dip: unk conf. SC603-A/SCB603-B maskroms) - * + */ + +/* NES 2.0 Mapper 556 + * Used for the for the 餓狼傳說 激鬥篇 HiK 7-in-1 (JY-215) multicart. */ #include "mapinc.h" +#include "asic_mmc1.h" +#include "asic_mmc3.h" +#include "asic_vrc2and4.h" -static uint8 vrc2_chr[8] = { 0 }; -static uint8 vrc2_prg[2] = { 0 }; -static uint8 vrc2_mirr = 0; +static uint8 submapper; +static uint8 reg; +static uint8 init; -static uint8 mmc3_regs[10] = { 0 }; -static uint8 mmc3_ctrl = 0; -static uint8 mmc3_mirr = 0; - -static uint8 mmc1_regs[4] = { 0 }; -static uint8 mmc1_buffer = 0; -static uint8 mmc1_shift = 0; - -static uint8 IRQCount = 0; -static uint8 IRQLatch = 0; -static uint8 IRQa = 0; -static uint8 IRQReload = 0; -static uint8 mode = 0; - -static uint8 submapper = 0; -static uint8 game = 0; - -extern uint32 ROM_size; -extern uint32 VROM_size; - -static SFORMAT StateRegs[] = -{ - { &mode, 1, "MODE" }, - { vrc2_chr, 8, "VRCC" }, - { vrc2_prg, 2, "VRCP" }, - { &vrc2_mirr, 1, "VRCM" }, - { mmc3_regs, 10, "M3RG" }, - { &mmc3_ctrl, 1, "M3CT" }, - { &mmc3_mirr, 1, "M3MR" }, - { &IRQReload, 1, "IRQR" }, - { &IRQCount, 1, "IRQC" }, - { &IRQLatch, 1, "IRQL" }, - { &IRQa, 1, "IRQA" }, - { mmc1_regs, 4, "M1RG" }, - { &mmc1_buffer, 1, "M1BF" }, - { &mmc1_shift, 1, "M1MR" }, - { &submapper, 1, "SUBM" }, - { &game, 1, "GAME" }, - { 0 } +static SFORMAT StateRegs[] = { + { ®, 1, "MODE" }, + { &init, 1, "INIT" }, + { 0 }, }; -static void SyncPRG(void) { - uint8 mask = (submapper != 3) ? 0x3F : (game ? 0x0F : 0x1F); - uint8 outer = game ? (game + 1) * 0x10 : 0; - switch (mode & 3) { - case 0: - setprg8(0x8000, (outer & ~mask) | (vrc2_prg[0] & mask)); - setprg8(0xA000, (outer & ~mask) | (vrc2_prg[1] & mask)); - setprg8(0xC000, (outer & ~mask) | (~1 & mask)); - setprg8(0xE000, (outer & ~mask) | (~0 & mask)); - break; - case 1: - { - uint32 swap = (mmc3_ctrl >> 5) & 2; - setprg8(0x8000, (outer & ~mask) | (mmc3_regs[6 + swap] & mask)); - setprg8(0xA000, (outer & ~mask) | (mmc3_regs[7] & mask)); - setprg8(0xC000, (outer & ~mask) | (mmc3_regs[6 + (swap ^ 2)] & mask)); - setprg8(0xE000, (outer & ~mask) | (mmc3_regs[9] & mask)); - break; - } - case 2: - case 3: - { - uint8 bank = mmc1_regs[3] & mask; - if (mmc1_regs[0] & 8) { - if (submapper == 2) - bank >>= 1; - if (mmc1_regs[0] & 4) { - setprg16(0x8000, bank); - setprg16(0xC000, 0x0F); - } else { - setprg16(0x8000, 0); - setprg16(0xC000, bank); - } - } else - setprg32(0x8000, ((outer & ~mask) >> 1) | (bank >> 1)); - } - break; +static void sync (void) { + int prgAND = 0x3F; + int chrAND = 0xFF; + int prgOR = 0x00 &~prgAND; + int chrOR = reg <<6 &0x100 &~chrAND; + if (reg &0x02) { + prgAND >>= 1; + prgOR >>= 1; + chrAND >>= 2; + chrOR >>= 2; + MMC1_syncPRG(prgAND, prgOR); + MMC1_syncCHR(chrAND, chrOR); + MMC1_syncMirror(); + } else + if (reg &0x01) { + MMC3_syncPRG(prgAND, prgOR); + MMC3_syncCHR(chrAND, chrOR); + MMC3_syncMirror(); + } else { + VRC24_syncPRG(prgAND, prgOR); + VRC24_syncCHR(chrAND, chrOR); + VRC24_syncMirror(); } } -static void SyncCHR(void) { - uint32 mask = game ? 0x7F : 0xFF; - uint32 outer = game ? (game + 1) * 0x80 : 0; - uint32 base = (mode & 4) << 6; - switch (mode & 3) { - case 0: - setchr1(0x0000, ((outer | base) & ~mask) | (vrc2_chr[0] & mask)); - setchr1(0x0400, ((outer | base) & ~mask) | (vrc2_chr[1] & mask)); - setchr1(0x0800, ((outer | base) & ~mask) | (vrc2_chr[2] & mask)); - setchr1(0x0c00, ((outer | base) & ~mask) | (vrc2_chr[3] & mask)); - setchr1(0x1000, ((outer | base) & ~mask) | (vrc2_chr[4] & mask)); - setchr1(0x1400, ((outer | base) & ~mask) | (vrc2_chr[5] & mask)); - setchr1(0x1800, ((outer | base) & ~mask) | (vrc2_chr[6] & mask)); - setchr1(0x1c00, ((outer | base) & ~mask) | (vrc2_chr[7] & mask)); - break; - case 1: { - uint32 swap = (mmc3_ctrl & 0x80) << 5; - setchr1(0x0000 ^ swap, ((outer | base) & ~mask) | ((mmc3_regs[0] & 0xFE) & mask)); - setchr1(0x0400 ^ swap, ((outer | base) & ~mask) | ((mmc3_regs[0] | 1) & mask)); - setchr1(0x0800 ^ swap, ((outer | base) & ~mask) | ((mmc3_regs[1] & 0xFE) & mask)); - setchr1(0x0c00 ^ swap, ((outer | base) & ~mask) | ((mmc3_regs[1] | 1) & mask)); - setchr1(0x1000 ^ swap, ((outer | base) & ~mask) | (mmc3_regs[2] & mask)); - setchr1(0x1400 ^ swap, ((outer | base) & ~mask) | (mmc3_regs[3] & mask)); - setchr1(0x1800 ^ swap, ((outer | base) & ~mask) | (mmc3_regs[4] & mask)); - setchr1(0x1c00 ^ swap, ((outer | base) & ~mask) | (mmc3_regs[5] & mask)); - break; - } - case 2: - case 3: - if (mmc1_regs[0] & 0x10) { - setchr4(0x0000, (outer & ~mask) | (mmc1_regs[1] & mask)); - setchr4(0x1000, (outer & ~mask) | (mmc1_regs[2] & mask)); - } else - setchr8(((outer & ~mask) >> 1) | (mmc1_regs[1] & mask) >> 1); - break; - } +int Huang2_getPRGBank (uint8 bank) { + return MMC1_getPRGBank(bank) >>1; } -static void SyncMIR(void) { - switch (mode & 3) { - case 0: { - setmirror((vrc2_mirr & 1) ^ 1); - break; - } - case 1: { - setmirror((mmc3_mirr & 1) ^ 1); - break; - } - case 2: - case 3: { - switch (mmc1_regs[0] & 3) { - case 0: setmirror(MI_0); break; - case 1: setmirror(MI_1); break; - case 2: setmirror(MI_V); break; - case 3: setmirror(MI_H); break; - } - break; - } - } -} - -static void Sync(void) { - SyncPRG(); - SyncCHR(); - SyncMIR(); -} - -static DECLFW(UNLSL12ModeWrite) { - if (A & 0x100) { - mode = V; - if (A & 1) { /* hacky hacky, there are two configuration modes on SOMARI HUANG-1 PCBs - * Solder pads with P1/P2 shorted called SOMARI P, - * Solder pads with W1/W2 shorted called SOMARI W - * Both identical 3-in-1 but W wanted MMC1 registers - * to be reset when switch to MMC1 mode P one - doesn't - * There is issue with W version of Somari at starting copyrights - */ - mmc1_regs[0] = 0xc; - mmc1_regs[3] = 0; - mmc1_buffer = 0; - mmc1_shift = 0; - } - Sync(); - } -} - -static DECLFW(UNLSL12Write) { -/* FCEU_printf("%04X:%02X\n",A,V); */ - switch (mode & 3) { - case 0: { - if ((A >= 0xB000) && (A <= 0xE003)) { - int32 ind = ((((A & 2) | (A >> 10)) >> 1) + 2) & 7; - int32 sar = ((A & 1) << 2); - vrc2_chr[ind] = (vrc2_chr[ind] & (0xF0 >> sar)) | ((V & 0x0F) << sar); - SyncCHR(); - } else - switch (A & 0xF000) { - case 0x8000: vrc2_prg[0] = V; SyncPRG(); break; - case 0xA000: vrc2_prg[1] = V; SyncPRG(); break; - case 0x9000: vrc2_mirr = V; SyncMIR(); break; - } - break; - } - case 1: { - switch (A & 0xE001) { - case 0x8000: { - uint8 old_ctrl = mmc3_ctrl; - mmc3_ctrl = V; - if ((old_ctrl & 0x40) != (mmc3_ctrl & 0x40)) - SyncPRG(); - if ((old_ctrl & 0x80) != (mmc3_ctrl & 0x80)) - SyncCHR(); - break; - } - case 0x8001: - mmc3_regs[mmc3_ctrl & 7] = V; - if ((mmc3_ctrl & 7) < 6) - SyncCHR(); - else - SyncPRG(); - break; - case 0xA000: - mmc3_mirr = V; - SyncMIR(); - break; - case 0xC000: - IRQLatch = V; - break; - case 0xC001: - IRQReload = 1; - break; - case 0xE000: - X6502_IRQEnd(FCEU_IQEXT); - IRQa = 0; - break; - case 0xE001: - IRQa = 1; - break; - } - break; - } - case 2: - case 3: { - if (V & 0x80) { - mmc1_regs[0] |= 0xc; - mmc1_buffer = mmc1_shift = 0; - SyncPRG(); - } else { - uint8 n = (A >> 13) - 4; - mmc1_buffer |= (V & 1) << (mmc1_shift++); - if (mmc1_shift == 5) { - mmc1_regs[n] = mmc1_buffer; - mmc1_buffer = mmc1_shift = 0; - switch (n) { - case 0: SyncMIR(); break; - case 2: SyncCHR(); break; - case 3: - case 1: SyncPRG(); break; - } - } - } - break; - } - } -} - -static void UNLSL12HBIRQ(void) { - if ((mode & 3) == 1) { - int32 count = IRQCount; - if (!count || IRQReload) { - IRQCount = IRQLatch; - IRQReload = 0; - } else - IRQCount--; - if (!IRQCount) { - if (IRQa) - X6502_IRQBegin(FCEU_IQEXT); +static void applyMode (uint8 clear) { + if (reg &0x02) { + MMC1_activate(clear && init &1, sync, MMC1_TYPE_MMC1B, submapper == 2? Huang2_getPRGBank: NULL, NULL, NULL, NULL); + MMC1_writeReg(0x8000, 0x80); + init &= ~1; + } else + if (reg &0x01) { + MMC3_activate(clear && init &2, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, NULL); + init &= ~2; + } else { + VRC2_activate(clear && init &4, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); + if (init &4) { + VRC24_writeReg(0xB000, 0xFF); VRC24_writeReg(0xB001, 0xFF); VRC24_writeReg(0xB002, 0xFF); VRC24_writeReg(0xB003, 0xFF); + VRC24_writeReg(0xC000, 0xFF); VRC24_writeReg(0xC001, 0xFF); VRC24_writeReg(0xC002, 0xFF); VRC24_writeReg(0xC003, 0xFF); + VRC24_writeReg(0xD000, 0xFF); VRC24_writeReg(0xD001, 0xFF); VRC24_writeReg(0xD002, 0xFF); VRC24_writeReg(0xD003, 0xFF); + VRC24_writeReg(0xE000, 0xFF); VRC24_writeReg(0xE001, 0xFF); VRC24_writeReg(0xE002, 0xFF); VRC24_writeReg(0xE003, 0xFF); + init &= ~4; } } } -static void StateRestore(int version) { - Sync(); -} - -static void UNLSL12Reset(void) { - /* this is suppose to increment during power cycle */ - /* but we dont have a way to do that, so increment on reset instead. */ - if (submapper == 3) { - game = game + 1; - if (game > 4) - game = 0; +static DECLFW(writeReg) { + if (A &0x100) { + uint8 previousReg = reg; + reg = V; + if ((previousReg ^V) &3) + applyMode(1); + else + sync(); } - Sync(); } -static void UNLSL12Power(void) { - game = (submapper == 3) ? 4 : 0; - mode = 1; - vrc2_chr[0] = ~0; - vrc2_chr[1] = ~0; - vrc2_chr[2] = ~0; - vrc2_chr[3] = ~0; /* W conf. of Somari wanted CHR3 has to be set to BB bank (or similar), but doesn't do that directly */ - vrc2_chr[4] = 4; - vrc2_chr[5] = 5; - vrc2_chr[6] = 6; - vrc2_chr[7] = 7; - vrc2_prg[0] = 0; - vrc2_prg[1] = 1; - vrc2_mirr = 0; - mmc3_regs[0] = 0; - mmc3_regs[1] = 2; - mmc3_regs[2] = 4; - mmc3_regs[3] = 5; - mmc3_regs[4] = 6; - mmc3_regs[5] = 7; - mmc3_regs[6] = ~3; - mmc3_regs[7] = ~2; - mmc3_regs[8] = ~1; - mmc3_regs[9] = ~0; - mmc3_ctrl = mmc3_mirr = IRQCount = IRQLatch = IRQa = 0; - mmc1_regs[0] = 0xc; - mmc1_regs[1] = 0; - mmc1_regs[2] = 0; - mmc1_regs[3] = 0; - mmc1_buffer = 0; - mmc1_shift = 0; - Sync(); +static void reset (void) { + reg = 0; + init = 7; + applyMode(1); +} + +static void power (void) { + reg = 0; + init = 7; SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x4100, 0x5FFF, UNLSL12ModeWrite); - SetWriteHandler(0x8000, 0xFFFF, UNLSL12Write); + SetWriteHandler(0x4020, 0x5FFF, writeReg); + applyMode(1); } -void UNLSL12_Init(CartInfo *info) { - info->Power = UNLSL12Power; - info->Reset = UNLSL12Reset; - GameHBIRQHook = UNLSL12HBIRQ; - GameStateRestore = StateRestore; - AddExState(&StateRegs, ~0, 0, 0); - submapper = info->submapper; - if (submapper == 0) { - /* PRG 128K and CHR 128K is Huang-2 (submapper 2) */ - if (ROM_size == 8 && VROM_size == 16) - submapper = 2; - } +static void restore (int version) { + applyMode(0); +} + +void UNLSL12_Init (CartInfo *info) { + submapper = info->submapper; + MMC1_addExState(); + MMC3_addExState(); + VRC24_addExState(); + info->Reset = reset; + info->Power = power; + GameStateRestore = restore; + AddExState(StateRegs, ~0, 0, 0); } diff --git a/src/boards/asic_mmc1.c b/src/boards/asic_mmc1.c index 91fad25..3093cbd 100644 --- a/src/boards/asic_mmc1.c +++ b/src/boards/asic_mmc1.c @@ -96,7 +96,7 @@ void FP_FASTAPASS(1) MMC1_cpuCycle(int a) { while (a--) if (MMC1_filter) MMC1_filter--; } -DECLFW(MMC1_write) { +DECLFW(MMC1_writeReg) { if (V &0x80) { MMC1_reg[0] |= 0x0C; MMC1_shift = 0; @@ -125,7 +125,7 @@ static void MMC1_setHandlers () { SetReadHandler (0x6000, 0x7FFF, MMC1_readWRAM); SetWriteHandler(0x6000, 0x7FFF, MMC1_writeWRAM); SetReadHandler (0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, MMC1_write); + SetWriteHandler(0x8000, 0xFFFF, MMC1_writeReg); MapIRQHook = MMC1_cpuCycle; } diff --git a/src/boards/asic_mmc1.h b/src/boards/asic_mmc1.h index 25f26a3..971d719 100644 --- a/src/boards/asic_mmc1.h +++ b/src/boards/asic_mmc1.h @@ -31,7 +31,7 @@ void MMC1_syncPRG (int, int); void MMC1_syncCHR (int, int); void MMC1_syncMirror (); void FP_FASTAPASS(1) MMC1_cpuCycle(int); -DECLFW (MMC1_write); +DECLFW (MMC1_writeReg); void MMC1_addExState (); void MMC1_restore (int); void MMC1_power (); From 399daf7a61b25490118ce144d99d03786493c2d2 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sat, 6 Sep 2025 13:12:15 +0200 Subject: [PATCH 006/109] Mapper 14: use the modularized ASIC cores. Mapper 116: Add multicart variant. --- src/boards/116.c | 47 +++++++++++++------ src/boards/14.c | 101 ++++++++++++++++++++++++++++++++++++++++ src/boards/sl1632.c | 111 -------------------------------------------- 3 files changed, 133 insertions(+), 126 deletions(-) create mode 100644 src/boards/14.c delete mode 100644 src/boards/sl1632.c diff --git a/src/boards/116.c b/src/boards/116.c index f9052d4..d8ded64 100644 --- a/src/boards/116.c +++ b/src/boards/116.c @@ -18,10 +18,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* NES 2.0 Mapper 556 - * Used for the for the 餓狼傳說 激鬥篇 HiK 7-in-1 (JY-215) multicart. - */ - #include "mapinc.h" #include "asic_mmc1.h" #include "asic_mmc3.h" @@ -29,19 +25,33 @@ static uint8 submapper; static uint8 reg; -static uint8 init; +static uint8 init; /* Games switch between ASICs expecting registers to keep their value, so initialize each ASIC only on the first switch and use this bitfield */ +static uint8 game; -static SFORMAT StateRegs[] = { +static SFORMAT stateRegs[] = { { ®, 1, "MODE" }, { &init, 1, "INIT" }, { 0 }, }; +static SFORMAT stateRegsMulti[] = { + { &game, 1, "GAME" }, + { 0 }, +}; + static void sync (void) { - int prgAND = 0x3F; - int chrAND = 0xFF; - int prgOR = 0x00 &~prgAND; - int chrOR = reg <<6 &0x100 &~chrAND; + int prgAND, chrAND, prgOR, chrOR; + if (submapper == 3) { /* First game is 256K+256K, the others 128K+128K */ + prgAND = game? 0x0F: 0x1F; + chrAND = game? 0x7F: 0xFF; + prgOR = game <<4 &~prgAND; + chrOR = game <<7 &~chrAND; + } else { + prgAND = 0x3F; + chrAND = 0xFF; + prgOR = 0x00 &~prgAND; + chrOR = reg <<6 &0x100 &~chrAND; + } if (reg &0x02) { prgAND >>= 1; prgOR >>= 1; @@ -67,9 +77,12 @@ int Huang2_getPRGBank (uint8 bank) { } static void applyMode (uint8 clear) { + PPU_hook = NULL; + MapIRQHook = NULL; + GameHBIRQHook = NULL; if (reg &0x02) { MMC1_activate(clear && init &1, sync, MMC1_TYPE_MMC1B, submapper == 2? Huang2_getPRGBank: NULL, NULL, NULL, NULL); - MMC1_writeReg(0x8000, 0x80); + if (submapper != 1) MMC1_writeReg(0x8000, 0x80); init &= ~1; } else if (reg &0x01) { @@ -77,7 +90,7 @@ static void applyMode (uint8 clear) { init &= ~2; } else { VRC2_activate(clear && init &4, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); - if (init &4) { + if (init &4) { /* The earlier version of Somari needs specific VRC2 CHR register initialization */ VRC24_writeReg(0xB000, 0xFF); VRC24_writeReg(0xB001, 0xFF); VRC24_writeReg(0xB002, 0xFF); VRC24_writeReg(0xB003, 0xFF); VRC24_writeReg(0xC000, 0xFF); VRC24_writeReg(0xC001, 0xFF); VRC24_writeReg(0xC002, 0xFF); VRC24_writeReg(0xC003, 0xFF); VRC24_writeReg(0xD000, 0xFF); VRC24_writeReg(0xD001, 0xFF); VRC24_writeReg(0xD002, 0xFF); VRC24_writeReg(0xD003, 0xFF); @@ -99,14 +112,17 @@ static DECLFW(writeReg) { } static void reset (void) { - reg = 0; + reg = 1; init = 7; + if (++game == 1) ++game; /* First game is twice as large */ + if (game >= ROM_size /8) game = 0; applyMode(1); } static void power (void) { - reg = 0; + reg = 1; init = 7; + game = 0; SetReadHandler(0x8000, 0xFFFF, CartBR); SetWriteHandler(0x4020, 0x5FFF, writeReg); applyMode(1); @@ -124,5 +140,6 @@ void UNLSL12_Init (CartInfo *info) { info->Reset = reset; info->Power = power; GameStateRestore = restore; - AddExState(StateRegs, ~0, 0, 0); + AddExState(stateRegs, ~0, 0, 0); + if (submapper == 3) AddExState(stateRegsMulti, ~0, 0, 0); } diff --git a/src/boards/14.c b/src/boards/14.c new file mode 100644 index 0000000..1c974c3 --- /dev/null +++ b/src/boards/14.c @@ -0,0 +1,101 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_mmc3.h" +#include "asic_vrc2and4.h" + +static uint8 reg; +static uint8 init; /* Games switch between ASICs expecting registers to keep their value, so initialize each ASIC only on the first switch and use this bitfield */ +static void applyMode (uint8); + +static SFORMAT StateRegs[] = { + { ®, 1, "MODE" }, + { &init, 1, "INIT" }, + { 0 }, +}; + +static void sync (void) { + if (reg &0x02) { + MMC3_syncPRG(0x3F, 0x00); + MMC3_syncCHR(0x1FF, 0x00); + MMC3_syncMirror(); + } else { + VRC24_syncPRG(0x3F, 0x00); + VRC24_syncCHR(0x1FF, 0x00); + VRC24_syncMirror(); + } +} + +int getCHRBank_MMC3 (uint8 bank) { + return MMC3_getCHRBank(bank) | reg <<(~bank &4? 5: ~bank &2? 3: 1) &0x100; +} + +int getCHRBank_VRC2 (uint8 bank) { + return VRC24_getCHRBank(bank) | reg <<(~bank &4? 5: ~bank &2? 3: 1) &0x100; +} + +static DECLFW(writeReg) { + uint8 previousReg = reg; + reg = V; + if ((previousReg ^V) &2) + applyMode(1); + else + sync(); +} + +static void applyMode (uint8 clear) { + PPU_hook = NULL; + MapIRQHook = NULL; + GameHBIRQHook = NULL; + if (reg &0x02) { + MMC3_activate(clear && init &1, sync, MMC3_TYPE_AX5202P, NULL, getCHRBank_MMC3, NULL, NULL); + init &= ~1; + } else { + VRC2_activate(clear && init &2, sync, 0x01, 0x02, NULL, getCHRBank_VRC2, NULL, NULL); + init &= ~2; + } + SetWriteHandler(0xA131, 0xA131, writeReg); +} + +static void reset (void) { + reg = 0; + init = 3; + applyMode(1); +} + +static void power (void) { + reg = 0; + init = 3; + applyMode(1); +} + +static void restore (int version) { + applyMode(0); +} + +void UNLSL1632_Init (CartInfo *info) { + MMC3_addExState(); + VRC24_addExState(); + info->Reset = reset; + info->Power = power; + GameStateRestore = restore; + AddExState(StateRegs, ~0, 0, 0); +} diff --git a/src/boards/sl1632.c b/src/boards/sl1632.c deleted file mode 100644 index 33c38ee..0000000 --- a/src/boards/sl1632.c +++ /dev/null @@ -1,111 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * SL1632 2-in-1 protected board, similar to SL12 - * Samurai Spirits Rex (Full) - * - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 chrcmd[8], prg0, prg1, bbrk, mirr, swap; -static SFORMAT StateRegs[] = -{ - { chrcmd, 8, "CHRC" }, - { &prg0, 1, "PRG0" }, - { &prg1, 1, "PRG1" }, - { &bbrk, 1, "BRK" }, - { &mirr, 1, "MIRR" }, - { &swap, 1, "SWAP" }, - { 0 } -}; - -static void Sync(void) { - int i; - setprg8(0x8000, prg0); - setprg8(0xA000, prg1); - setprg8(0xC000, ~1); - setprg8(0xE000, ~0); - for (i = 0; i < 8; i++) - setchr1(i << 10, chrcmd[i]); - setmirror(mirr ^ 1); -} - -static void UNLSL1632CW(uint32 A, uint8 V) { - int cbase = (MMC3_cmd & 0x80) << 5; - int page0 = (bbrk & 0x08) << 5; - int page1 = (bbrk & 0x20) << 3; - int page2 = (bbrk & 0x80) << 1; - setchr1(cbase ^ 0x0000, page0 | (DRegBuf[0] & (~1))); - setchr1(cbase ^ 0x0400, page0 | DRegBuf[0] | 1); - setchr1(cbase ^ 0x0800, page0 | (DRegBuf[1] & (~1))); - setchr1(cbase ^ 0x0C00, page0 | DRegBuf[1] | 1); - setchr1(cbase ^ 0x1000, page1 | DRegBuf[2]); - setchr1(cbase ^ 0x1400, page1 | DRegBuf[3]); - setchr1(cbase ^ 0x1800, page2 | DRegBuf[4]); - setchr1(cbase ^ 0x1c00, page2 | DRegBuf[5]); -} - -static DECLFW(UNLSL1632CMDWrite) { - if (A == 0xA131) { - bbrk = V; - } - if (bbrk & 2) { - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); - if (A < 0xC000) - MMC3_CMDWrite(A, V); - else - MMC3_IRQWrite(A, V); - } else { - if ((A >= 0xB000) && (A <= 0xE003)) { - int ind = ((((A & 2) | (A >> 10)) >> 1) + 2) & 7; - int sar = ((A & 1) << 2); - chrcmd[ind] = (chrcmd[ind] & (0xF0 >> sar)) | ((V & 0x0F) << sar); - } else - switch (A & 0xF003) { - case 0x8000: prg0 = V; break; - case 0xA000: prg1 = V; break; - case 0x9000: mirr = V & 1; break; - } - Sync(); - } -} - -static void StateRestore(int version) { - if (bbrk & 2) { - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); - } else - Sync(); -} - -static void UNLSL1632Power(void) { - GenMMC3Power(); - SetWriteHandler(0x4100, 0xFFFF, UNLSL1632CMDWrite); -} - -void UNLSL1632_Init(CartInfo *info) { - GenMMC3_Init(info, 256, 512, 0, 0); - cwrap = UNLSL1632CW; - info->Power = UNLSL1632Power; - GameStateRestore = StateRestore; - AddExState(&StateRegs, ~0, 0, 0); -} From 5744764e246e13ecf452d1553f146fb865092a6b Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 7 Sep 2025 00:32:28 +0200 Subject: [PATCH 007/109] Mapper 468: use the modularized ASIC cores. --- src/boards/116.c | 2 +- src/boards/14.c | 2 +- src/boards/446.c | 11 +- src/boards/468.c | 633 ++++++++++++++------ src/boards/468_cnrom.h | 45 -- src/boards/468_discrete.h | 73 --- src/boards/468_fme7.h | 72 --- src/boards/468_if12.h | 31 - src/boards/468_lf36.h | 46 -- src/boards/468_mmc1.h | 72 --- src/boards/468_mmc24.h | 67 --- src/boards/468_mmc3.h | 80 --- src/boards/468_nanjing.h | 29 - src/boards/468_vrc1.h | 25 - src/boards/468_vrc24.h | 92 --- src/boards/468_vrc3.h | 63 -- src/boards/468_vrc6.h | 72 --- src/boards/468_vrc7.h | 82 --- src/boards/asic_fme7.c | 134 +++++ src/boards/asic_fme7.h | 38 ++ src/boards/asic_mmc2.c | 108 ---- src/boards/asic_mmc2and4.c | 117 ++++ src/boards/{asic_mmc2.h => asic_mmc2and4.h} | 22 +- src/boards/asic_mmc3.c | 4 + src/boards/asic_mmc3.h | 1 + src/boards/asic_vrc7.h | 3 - 26 files changed, 756 insertions(+), 1168 deletions(-) delete mode 100644 src/boards/468_cnrom.h delete mode 100644 src/boards/468_discrete.h delete mode 100644 src/boards/468_fme7.h delete mode 100644 src/boards/468_if12.h delete mode 100644 src/boards/468_lf36.h delete mode 100644 src/boards/468_mmc1.h delete mode 100644 src/boards/468_mmc24.h delete mode 100644 src/boards/468_mmc3.h delete mode 100644 src/boards/468_nanjing.h delete mode 100644 src/boards/468_vrc1.h delete mode 100644 src/boards/468_vrc24.h delete mode 100644 src/boards/468_vrc3.h delete mode 100644 src/boards/468_vrc6.h delete mode 100644 src/boards/468_vrc7.h create mode 100644 src/boards/asic_fme7.c create mode 100644 src/boards/asic_fme7.h delete mode 100644 src/boards/asic_mmc2.c create mode 100644 src/boards/asic_mmc2and4.c rename src/boards/{asic_mmc2.h => asic_mmc2and4.h} (71%) diff --git a/src/boards/116.c b/src/boards/116.c index d8ded64..465efb4 100644 --- a/src/boards/116.c +++ b/src/boards/116.c @@ -25,7 +25,7 @@ static uint8 submapper; static uint8 reg; -static uint8 init; /* Games switch between ASICs expecting registers to keep their value, so initialize each ASIC only on the first switch and use this bitfield */ +static uint8 init; /* Games switch between ASICs expecting registers to keep their value, so initialize each ASIC only on the first switch and use this bitfield to track it */ static uint8 game; static SFORMAT stateRegs[] = { diff --git a/src/boards/14.c b/src/boards/14.c index 1c974c3..ad47557 100644 --- a/src/boards/14.c +++ b/src/boards/14.c @@ -23,7 +23,7 @@ #include "asic_vrc2and4.h" static uint8 reg; -static uint8 init; /* Games switch between ASICs expecting registers to keep their value, so initialize each ASIC only on the first switch and use this bitfield */ +static uint8 init; /* Games switch between ASICs expecting registers to keep their value, so initialize each ASIC only on the first switch and use this bitfield to track it */ static void applyMode (uint8); static SFORMAT StateRegs[] = { diff --git a/src/boards/446.c b/src/boards/446.c index 3dfcb9d..0683c35 100644 --- a/src/boards/446.c +++ b/src/boards/446.c @@ -22,7 +22,7 @@ #include "asic_h3001.h" #include "asic_latch.h" #include "asic_mmc1.h" -#include "asic_mmc2.h" +#include "asic_mmc2and4.h" #include "asic_mmc3.h" #include "asic_pt8154.h" #include "asic_qj.h" @@ -37,7 +37,6 @@ static uint8 submapper; static uint8 reg[8]; - static void (*mapperSync)(int, int, int, int) = NULL; static void applyMode (uint8); @@ -118,8 +117,8 @@ static void sync_H3001 (int prgAND, int prgOR, int chrAND, int chrOR) { static void sync_PNROM (int prgAND, int prgOR, int chrAND, int chrOR) { MMC2_syncPRG(prgAND, prgOR &~prgAND); - MMC2_syncCHR(chrAND, chrOR &~chrAND); - MMC2_syncMirror(); + MMC24_syncCHR(chrAND, chrOR &~chrAND); + MMC24_syncMirror(); } static void sync_SKROM (int prgAND, int prgOR, int chrAND, int chrOR) { @@ -344,7 +343,7 @@ static void applyMode (uint8 clear) { break; case 0x109: mapperSync = sync_PNROM; - MMC2_activate(clear, sync); + MMC24_activate(clear, sync); break; case 0x10A: case 0x20A: mapperSync = sync_TxROM; @@ -404,7 +403,7 @@ void Mapper446_Init(CartInfo *info) { H3001_addExState(); Latch_addExState(); MMC1_addExState(); - MMC2_addExState(); + MMC24_addExState(); MMC3_addExState(); VRC1_addExState(); VRC24_addExState(); diff --git a/src/boards/468.c b/src/boards/468.c index a6ba217..6b5025e 100644 --- a/src/boards/468.c +++ b/src/boards/468.c @@ -7,7 +7,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -18,93 +18,40 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* BlazePro CPLD-based multicarts - - Unsolved issue: how is CHR RAM write-protection triggered? - - Known problems: - - Forever Duo of NES 852-in-1 (rev1): - #A370 Time Lord: Hangs with glitchy status bar on NTSC and PAL but not Dendy - #A133 Galactic Crusader: Wrong mirroring - #A249 Mission Cobra: Wrong mirroring - - Legendary Games of NES 509-in-1: - #189 Huang Di Battle of Zhuolu: Wrong mirroring during intro - #227 Kid Niki Niki 2: Title screen animation flickers and looks strange - #234 Klax: Screen in wrong position during options screen - #365 Rocman X: Graphical garbage in waterfall (middle) level - #403 Star Wars: Blank tiles due to lack of CHR RAM write-protection - #404 The Empire Strikes Back: Blank tiles due to lack of CHR RAM write-protection - #460 Twin Dragons: Wrong mirroring - - Unlicensed Collection 142-in-1: - #59 Huang Di: Wrong mirroring during intro - #84 Ms. Pac-Man: Wrong mirroring - #102 Rocman X: Graphical garbage in waterfall (middle) level - #132 Trolls on Treasure Island: Wrong mirroring during map - - Unreleased Collection 73-in-1 (v1.01): - #38 Holy Diver: Wrong mirroring during first scene -*/ - #include "mapinc.h" -#include "state.h" +#include "asic_fme7.h" +#include "asic_latch.h" +#include "asic_mmc1.h" +#include "asic_mmc2and4.h" +#include "asic_mmc3.h" +#include "asic_vrc1.h" +#include "asic_vrc2and4.h" +#include "asic_vrc3.h" +#include "asic_vrc6.h" +#include "asic_vrc7.h" +#include "wram.h" static uint8 submapper; -static uint8 eeprom[16], eep_clock, state, command, output; /* Some strange serial EEPROM */ -static uint8 *WRAM; -static uint32 WRAMSIZE; +static uint8 reg[4]; /* Supervisor registers */ +static uint8 Custom_reg[4]; /* Registers for custom mappers */ +static uint8 eeprom[16], eep_clock, state, command, output; /* Serial EEPROM */ -static int prevSFEXINDEX; -extern int SFEXINDEX; -extern SFORMAT SFMDATA[64]; - -static uint8 mapper; /* 5700 MSB >>4 OR'd with submapper <<4 */ -static uint8 mapperFlags; /* 5700 LSB */ -static uint8 misc; /* 5601 */ -static uint8 misc2; /* 5702 */ -static void (*sync)(); - -static uint16 prgOR; -static uint8 prgAND; - -static uint8 regByte[16]; -static int16 regWord[9]; - -#include "468_mmc1.h" -#include "468_mmc24.h" -#include "468_mmc3.h" -#include "468_vrc1.h" -#include "468_vrc24.h" -#include "468_vrc3.h" -#include "468_vrc6.h" -#include "468_vrc7.h" -#include "468_fme7.h" -#include "468_discrete.h" -#include "468_cnrom.h" -#include "468_if12.h" -#include "468_lf36.h" -#include "468_nanjing.h" +static void (*mapperSync)(int) = NULL; +static void applyMode (uint8); static SFORMAT stateRegs[] = { - { &mapper, 1, "SUP0" }, - { &mapperFlags, 1, "SUP1" }, - { &misc, 1, "SUP2" }, - { &misc2, 1, "SUP3" }, - { &prgOR, 2, "SUP4" }, - { &prgAND, 1, "SUP5" }, - { eeprom, 16,"EEPR" }, - { &eep_clock, 1, "EEP0" }, - { &state, 1, "EEP1" }, - { &command, 1, "EEP2" }, - { &output, 1, "EEP3" }, - { regByte, 16,"REGB" }, - { regWord, 16,"REGW" }, + { ®, 4, "REGS" }, + { &Custom_reg, 4, "CURG" }, + { eeprom, 16, "EEPR" }, + { &eep_clock, 1, "EEP0" }, + { &state, 1, "EEP1" }, + { &command, 1, "EEP2" }, + { &output, 1, "EEP3" }, { 0 } }; -static const uint16 lut509[512] ={ /* Strange look-up table, used only by Legendary Games of NES 509-in-1 */ +/* Serial EEPROM */ +static const uint16 lut509[512] = { /* Look-up table, used only by Legendary Games of NES 509-in-1 */ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 0, 1, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 4, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, @@ -122,151 +69,457 @@ static const uint16 lut509[512] ={ /* Strange look-up table, used only by Legend void setPins(uint8 select, uint8 newClock, uint8 newData) { /* Serial EEPROM */ if (select) - state =0; + state = 0; else if (!eep_clock && !!newClock) { if (state <8) { - command =command <<1 | !!(newData)*1; - if (++state ==8 && (command &0xF0) !=0x50 && (command &0xF0) !=0xA0) state =0; + command = command <<1 | !!(newData)*1; + if (++state == 8 && (command &0xF0) != 0x50 && (command &0xF0) != 0xA0) state = 0; } else { - int mask =1 <<(15 -state); - int address =command &0x0F; - if ((command &0xF0) ==0xA0) { - eeprom[address] =eeprom[address] &~mask | !!(newData)*mask; - /* The "write" command also silently returns the content of a strange lookup table */ - output =!!(lut509[eeprom[0] | eeprom[1] | eeprom[2] <<8 &0x1FF] >>(address &1? 0: 8) &mask); + int mask = 1 <<(15 -state); + int address = command &0x0F; + if ((command &0xF0) == 0xA0) { + eeprom[address] = eeprom[address] &~mask | !!(newData)*mask; + /* The "write" command also silently returns the content of a lookup table */ + output = !!(lut509[eeprom[0] | eeprom[1] | eeprom[2] <<8 &0x1FF] >>(address &1? 0: 8) &mask); } else - if ((command &0xF0) ==0x50) - output =!!(eeprom[address] &mask); - - if (++state ==16) state =0; + if ((command &0xF0) == 0x50) + output = !!(eeprom[address] &mask); + + if (++state == 16) state = 0; } } - eep_clock =newClock; + eep_clock = newClock; } -static DECLFR(readReg); -static DECLFW(writeReg); -static void setMapper(uint8 clearRegs) { - int i; - if (clearRegs) { - for (i =0; i <16; i++) regByte[i] =0; - for (i =0; i < 8; i++) regWord[i] =0; - X6502_IRQEnd(FCEU_IQEXT); - } - SetReadHandler(0x5000, 0x5FFF, readReg); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x5000, 0x5FFF, writeReg); - SetWriteHandler(0x6000, 0xFFFF, CartBW); - MapIRQHook = NULL; - PPU_hook = NULL; - GameHBIRQHook = NULL; - setprg8r(0x10, 0x6000, 0); +/* Mapper syncs */ +static void sync () { + if (mapperSync) mapperSync(reg[submapper == 1? 2: 3] <<9 &0x2000 | reg[1] <<5 &0x1FE0 | reg[0] <<4 &0x0010); +} - switch(mapper) { /* 5700 MSB >>4 OR'd with submapper <<4 */ - case 0x00: case 0x01: case 0x32: MMC1_reset(clearRegs); break; - case 0x0A: MMC2_reset(clearRegs); break; - case 0x10: case 0x11: case 0x12: MMC3_reset(clearRegs); break; - case 0x08: MMC4_reset(clearRegs); break; - case 0x40: VRC1_reset(clearRegs); break; - case 0x20: case 0x21: case 0x22: case 0x23: VRC24_reset(clearRegs); break; - case 0x44: VRC3_reset(clearRegs); break; - case 0x30: case 0x31: VRC6_reset(clearRegs); break; - case 0x41: VRC7_reset(clearRegs); break; - case 0x07: LF36_reset(clearRegs); break; - case 0x50: FME7_reset(clearRegs); break; - case 0x0E: case 0x1E: NANJING_reset(clearRegs); break; - case 0x09: case 0x0B: case 0x17: case 0x37: UNROM_IF12_reset(clearRegs); break; - case 0x04: case 0x06: case 0x14: case 0x16: ANROM_BNROM_reset(clearRegs); break; - case 0x05: case 0x15: CNROM_BF9097_reset(clearRegs); break; - case 0x0C: case 0x0D: case 0x1C: case 0x1D: GNROM_reset(clearRegs); break; - default: break; +static void sync_AxROM (int prgOR) { + int prgAND = reg[0] &0x20? 0x0F: reg[0] &0x02? 0x03: 0x07; + setprg32(0x8000, Latch_data &prgAND | prgOR >>2 &~prgAND); + setchr8(0); + setmirror(Latch_data &0x10? MI_1: MI_0); +} + +static void sync_BxROM (int prgOR) { + int prgAND = reg[0] &0x20? 0x0F: reg[0] &0x02? 0x03: 0x07; + setprg32(0x8000, Latch_data &prgAND | prgOR >>2 &~prgAND); + setchr8(0); + setmirror(reg[0] &0x04? MI_H: MI_V); +} + +static void sync_FME7 (int prgOR) { + int prgAND = reg[0] &0x02? 0x0F: 0x1F; + FME7_syncWRAM(0); + FME7_syncPRG(prgAND, prgOR &~prgAND); + FME7_syncCHR(0xFF, 0x00); + FME7_syncMirror(); +} + +static void sync_FxROM (int prgOR) { + int prgAND = reg[0] &0x02? 0x07: 0x0F; + MMC24_syncWRAM(0); + MMC4_syncPRG(prgAND, prgOR >>1 &~prgAND); + MMC24_syncCHR(0xFF, 0x00); + MMC24_syncMirror(); +} + +static void sync_GNROM (int prgOR) { + int prgAND = reg[0] &0x08? 0x01: 0x03; + int value = prgOR &0x2000 && submapper != 1? (Latch_data >>4 &0x0F | Latch_data <<4 &0xF0): Latch_data; + prgOR = prgOR >>2 | reg[0] >>1 &0x02; + setprg32(0x8000, value >>0 &prgAND | prgOR &~prgAND); + setchr8(value >>4); + setmirror(reg[0] &0x10? MI_H: MI_V); +} + +static void sync_IF12 (int prgOR) { + int prgAND = reg[0] &0x02? 0x07: 0x0F; + setprg16(0x8000, Custom_reg[1] &prgAND | prgOR >>1 &~prgAND); + setprg16(0xC000, prgOR >>1 | prgAND); + setchr8(Custom_reg[0] >>1 &0x0F); + setmirror(Custom_reg[0] &0x01? MI_H: MI_V); +} + +static void sync_LF36 (int prgOR) { + prgOR |= reg[0] &0x08; + setprg8(0x8000, 0x04 | prgOR); + setprg8(0xA000, 0x05 | prgOR); + setprg8(0xC000, Custom_reg[0] &0x07 | prgOR); + setprg8(0xE000, 0x07 | prgOR); + setchr8(0); + setmirror(reg[0] &0x04? MI_H: MI_V); +} + +static void sync_Misc (int prgOR) { + if (reg[0] &0x02) { + setprg16(0x8000, Custom_reg[2] <<1 &0x0E | reg[0] &0x01 | prgOR >>1 &~0x0F); + setprg16(0xC000, Custom_reg[2] <<1 &0x0E | reg[0] &0x01 | prgOR >>1 &~0x0F); + setchr8(Custom_reg[0] &0x03); + } else { + setprg32(0x8000, Custom_reg[2] &0x07 | prgOR >>2 &~0x07); + setchr8(Custom_reg[0] &0x0F); } + if (reg[0] &0x08) + setmirror(reg[0] &0x04? MI_H: MI_V); + else + setmirror(Custom_reg[1] &0x10? MI_1: MI_0); +} + +static void sync_Nanjing (int prgOR) { + setprg32(0x8000, Custom_reg[2] <<4 &0x30 | Custom_reg[0] &0x0F | (Custom_reg[3] &0x04? 0x00: 0x03) | prgOR >>2); + setchr8(0); + setmirror(reg[0] &0x04? MI_H: MI_V); +} + +static void sync_PNROM (int prgOR) { + MMC24_syncWRAM(0); + MMC2_syncPRG(0x0F, prgOR &~0x0F); + MMC24_syncCHR(0xFF, 0x00); + MMC24_syncMirror(); +} + +static void sync_SxROM (int prgOR) { + int prgAND = reg[0] &0x02? (reg[0] &0x08? 0x03: 0x07): 0x0F; + MMC1_syncWRAM(0); + MMC1_syncPRG(prgAND, (prgOR >>1 | reg[0] &0x06) &~prgAND); + MMC1_syncCHR(0x1F, 0x00); + MMC1_syncMirror(); +} + +static void sync_SUROM (int prgOR) { + MMC1_syncWRAM(0); + MMC1_syncPRG(0x1F, prgOR >>1 &~0x1F); + MMC1_syncCHR(0x0F, 0x00); + MMC1_syncMirror(); +} + +static void sync_TxROM (int prgOR) { + int prgAND = reg[0] &0x08? (reg[0] &0x04? (reg[0] &0x02? (reg[2] &0x02? 0x07: 0x0F): 0x1F): 0x3F): 0x7F; + prgOR |= reg[2] &0x01? 0x0C: 0x00; + MMC3_syncWRAM(0); + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(reg[0] &0x10? 0xFF: 0x7F, 0x00); + MMC3_syncMirror(); +} + +static void sync_TxSROM (int prgOR) { + int prgAND = reg[0] &0x08? (reg[0] &0x04? (reg[0] &0x02? (reg[2] &0x02? 0x07: 0x0F): 0x1F): 0x3F): 0x7F; + prgOR |= reg[2] &0x01? 0x0C: 0x00; + MMC3_syncWRAM(0); + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(0x7F, 0x00); + switch(MMC3_getMirroring() &3) { /* Only A000=02 is TxSROM. H/V mirroring is necessary for Ys 1, modified for MMC3. */ + case 0: + setmirror(MI_V); + break; + case 1: + setmirror(MI_H); + break; + case 2: + setmirror(MMC3_getCHRBank(0) &0x80? MI_1: MI_0); + break; + case 3: + setmirror(MI_1); + break; + } +} + +static void sync_UxROM (int prgOR) { + int prgAND = reg[0] &0x02? 0x07: 0x0F; + setprg16(0x8000, Latch_data &prgAND | prgOR >>1 &~prgAND); + setprg16(0xC000, prgOR >>1 | prgAND); + setchr8(0); + setmirror(reg[0] &0x04? MI_H: MI_V); +} + +static void sync_UNROM512 (int prgOR) { + setprg16(0x8000, Latch_data &0x1F | prgOR >>1 &~0x1F); + setprg16(0xC000, prgOR >>1 | 0x1F); + setchr8(Latch_data >>5); + setmirror(reg[0] &0x04? MI_H: MI_V); +} + +static void sync_VRC1 (int prgOR) { + int prgAND = reg[0] &0x08? (reg[0] &0x04? (reg[0] &0x02? 0x0F: 0x1F): 0x3F): 0x7F; + VRC1_syncPRG(prgAND, prgOR &~prgAND); + VRC1_syncCHR(0x1F, 0x00); + VRC1_syncMirror(); +} + +static void sync_VRC24 (int prgOR) { + int prgAND = reg[0] &0x02? 0x0F: 0x1F; + VRC24_syncWRAM(0); + VRC24_syncPRG(prgAND, prgOR &~prgAND); + VRC24_syncCHR(0xFF, 0x00); + VRC24_syncMirror(); +} + +static void sync_VRC3 (int prgOR) { + VRC3_syncWRAM(0); + VRC3_syncPRG(0x07, prgOR >>1 &~0x07); + VRC3_syncCHR(0x01, 0x00); + setmirror(reg[0] &0x04? MI_H: MI_V); +} + +static void sync_VRC6 (int prgOR) { + int prgAND = reg[0] &0x02? 0x0F: 0x1F; + VRC6_syncWRAM(0); + VRC6_syncPRG(prgAND, prgOR &~prgAND); + VRC6_syncCHR(0xFF, 0x00); + VRC6_syncMirror(); +} + +static void sync_VRC7 (int prgOR) { + int prgAND = reg[0] &0x08? (reg[0] &0x04? (reg[0] &0x02? 0x0F: 0x1F): 0x3F): 0x7F; + VRC7_syncWRAM(0); + VRC7_syncPRG(prgAND, prgOR &~prgAND); + VRC7_syncCHR(0xFF, 0x00); + VRC7_syncMirror(); +} + +/* Mapper callbacks and handlers */ +static int SUROM_getPRGBank(uint8 bank) { + return MMC1_getPRGBank(bank) | MMC1_getCHRBank(0) &0x10; +} + +static DECLFW(IF12_writeReg) { + Custom_reg[A >>14 &1] = V; sync(); } +void FP_FASTAPASS(1) LF36_cpuCycle (int a) { + while (a--) { + if (Custom_reg[1] &1) { + if (!++Custom_reg[2]) ++Custom_reg[3]; + if (Custom_reg[3] &0x10) + X6502_IRQBegin(FCEU_IQEXT); + else + X6502_IRQEnd(FCEU_IQEXT); + } else { + Custom_reg[2] = Custom_reg[3] = 0; + X6502_IRQEnd(FCEU_IQEXT); + } + } +} + +static DECLFW(LF36_writeReg) { + switch(A >>13 &3) { + case 0: case 1: + Custom_reg[1] = A >>13 &1; + break; + case 3: + Custom_reg[0] = V; + sync(); + } +} + +static DECLFW(Misc_writeReg) { + switch(A >>12 &7) { + case 0: case 2: case 3: + Custom_reg[0] = V; + sync(); + break; + case 1: + Custom_reg[1] = V; + sync(); + break; + case 6: case 7: + Custom_reg[2] = V; + sync(); + break; + } +} + +static void Nanjing_scanline (void) { + if (Custom_reg[0] &0x80 && scanline <239) { + setchr4(0x0000, scanline >= 127? 1: 0); + setchr4(0x1000, scanline >= 127? 1: 0); + } else + setchr8(0); +} + +static DECLFW(Nanjing_writeReg) { + Custom_reg[A >>8 &3] = V; + sync(); +} + +/* Supervisor */ static DECLFR(readReg) { switch(A) { - case 0x5301: case 0x5601: - return output? 0x80: 0x00; - default: - return 0xFF; + case 0x5301: case 0x5601: + return output? 0x80: 0x00; + default: + return 0xFF; } } static DECLFW(writeReg) { switch(A) { - case 0x5301: - if (submapper ==0) setPins(!!(V &0x04), !!(V &0x02), !!(V &0x01)); - break; - case 0x5601: - if (~misc &0x80) { - misc =V; - if (submapper !=1) { - prgOR =prgOR &~0x2000 | V <<9 &0x2000; + case 0x5301: + if (submapper == 0) setPins(!!(V &0x04), !!(V &0x02), !!(V &0x01)); + break; + case 0x5601: + if (submapper == 1) setPins(!!(V &0x10), !!(V &0x02), !!(V &0x01)); + if (~reg[3] &0x80) { + reg[3] = V; sync(); } - } - if (submapper ==1) setPins(!!(V &0x10), !!(V &0x02), !!(V &0x01)); - break; - case 0x5700: - mapper =V >>4 | submapper <<4; - mapperFlags =V &0xF; - prgOR =prgOR &~0x0010 | V <<4 &0x0010; - setMapper(1); - break; - case 0x5701: - prgOR =prgOR &~0x1FE0 | V <<5 &0x1FE0; - sync(); - break; - case 0x5702: - if (submapper ==1) { - misc2 =V; - prgOR =prgOR &~0x2000 | V <<9 &0x2000; - setMapper(0); /* The misc2 value is required for prgAND by MMC3 and UNROM */ - } - break; + break; + case 0x5700: + reg[A &3] = V; + applyMode(1); + break; + case 0x5701: case 0x5702: + reg[A &3] = V; + sync(); + break; } } -static void reset(void) { - mapper =submapper <<4; - mapperFlags =0x0F; - misc =0; - misc2 =0; - prgOR =0x7FF0; - eep_clock =command =output =1; - command =state =0; - setMapper(1); +static void applyMode (uint8 clear) { + MapIRQHook = NULL; + PPU_hook = NULL; + GameHBIRQHook = NULL; + SetReadHandler(0x5000, 0x5FFF, readReg); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x5000, 0x5FFF, writeReg); + SetWriteHandler(0x6000, 0xFFFF, CartBW); + switch(submapper <<8 | reg[0] >>4) { + case 0x000: case 0x302: + mapperSync = sync_SxROM; + MMC1_activate(clear, sync, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL); + break; + case 0x001: + mapperSync = sync_SUROM; + MMC1_activate(clear, sync, MMC1_TYPE_MMC1B, SUROM_getPRGBank, NULL, NULL, NULL); + break; + case 0x004: case 0x006: case 0x104: case 0x106: + mapperSync = reg[0] &0x08? sync_BxROM: sync_AxROM; + Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); + break; + case 0x005: case 0x105: + mapperSync = sync_Misc; /* NROM, CNROM, Fire Hawk */ + SetWriteHandler(0x8000, 0xFFFF, Misc_writeReg); + break; + case 0x007: + mapperSync = sync_LF36; /* SMB2J */ + MapIRQHook = LF36_cpuCycle; + SetWriteHandler(0x8000, 0xFFFF, LF36_writeReg); + break; + case 0x008: + mapperSync = sync_FxROM; + MMC24_activate(clear, sync); + break; + case 0x009: case 0x107: case 0x307: + if (reg[0] &0x08) { + mapperSync = sync_UxROM; + Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); + } else { + mapperSync = sync_IF12; /* Not Irem's actual IF-12 mapper, but something custom by BlazePro */ + SetWriteHandler(0x8000, 0xFFFF, IF12_writeReg); + } + break; + case 0x00A: + mapperSync = sync_PNROM; + MMC24_activate(clear, sync); + break; + case 0x00B: + mapperSync = sync_UNROM512; + Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); + break; + case 0x00C: case 0x00D: case 0x10C: case 0x10D: + mapperSync = sync_GNROM; + Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); + break; + case 0x00E: case 0x10E: + mapperSync = sync_Nanjing; /* Partial emulation only */ + GameHBIRQHook = Nanjing_scanline; + SetWriteHandler(0x5000, 0x53FF, Nanjing_writeReg); + break; + case 0x100: case 0x101: + mapperSync = sync_TxROM; + MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, NULL); + break; + case 0x102: + mapperSync = sync_TxSROM; + MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, NULL); + break; + case 0x200: + mapperSync = sync_VRC24; + VRC2_activate(clear, sync, 0x05, 0x0A, NULL, NULL, NULL, NULL); + break; + case 0x201: + mapperSync = sync_VRC24; + VRC4_activate(clear, sync, 0x05, 0x0A, 1, NULL, NULL, NULL, NULL, NULL); + break; + case 0x202: + mapperSync = sync_VRC24; + VRC2_activate(clear, sync, 0x0A, 0x05, NULL, NULL, NULL, NULL); + break; + case 0x203: + mapperSync = sync_VRC24; + VRC4_activate(clear, sync, 0x0A, 0x05, 1, NULL, NULL, NULL, NULL, NULL); + break; + case 0x300: + mapperSync = sync_VRC6; + VRC6_activate(clear, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); + break; + case 0x400: + mapperSync = sync_VRC1; + VRC1_activate(clear, sync); + break; + case 0x401: + mapperSync = sync_VRC7; + VRC7_activate(clear, sync, 0x18); + break; + case 0x404: + mapperSync = sync_VRC3; + VRC3_activate(clear, sync); + break; + case 0x500: + mapperSync = sync_FME7; + FME7_activate(clear, sync); + break; + default: + break; + } } -static void power(void) { - int i; - for (i =0; i <16; i++) eeprom[i] =0; - reset(); +static void power() { + reg[0] = 0x0F; + reg[1] = 0xFF; + reg[2] = submapper == 1? 0x10: 0x00; + reg[3] = 0x00; + Custom_reg[0] = Custom_reg[1] = Custom_reg[2] = Custom_reg[3] = 0; + eep_clock = command = output = 1; + command = state = 0; + applyMode(1); } -static void close(void) { - if (WRAM) - FCEU_gfree(WRAM); - WRAM = NULL; -} static void stateRestore(int version) { - setMapper(0); + applyMode(0); } void Mapper468_Init(CartInfo *info) { - submapper =info->submapper; - info->Reset =reset; - info->Power =power; - info->Close =close; - GameStateRestore =stateRestore; - - WRAMSIZE =8192; - WRAM =(uint8*) FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + submapper = info->submapper; + FME7_addExState(); + Latch_addExState(); + MMC1_addExState(); + MMC24_addExState(); + MMC3_addExState(); + VRC1_addExState(); + VRC24_addExState(); + VRC3_addExState(); + VRC6_addExState(); + VRC7_addExState(); + WRAM_init(info, 8); + info->Reset = power; + info->Power = power; + GameStateRestore = stateRestore; AddExState(stateRegs, ~0, 0, 0); - prevSFEXINDEX =SFEXINDEX; } diff --git a/src/boards/468_cnrom.h b/src/boards/468_cnrom.h deleted file mode 100644 index 00dc2dc..0000000 --- a/src/boards/468_cnrom.h +++ /dev/null @@ -1,45 +0,0 @@ -#define CNROM_reg regByte - -static void CNROM_sync () { - int OR =prgOR >>1; - if (mapperFlags &2) { - setprg16(0x8000, CNROM_reg[2] <<1 &0xE | mapperFlags &1 | OR &~0xF); - setprg16(0xC000, CNROM_reg[2] <<1 &0xE | mapperFlags &1 | OR &~0xF); - setchr8(CNROM_reg[0] &0x03); - } else { - OR >>=1; - setprg32(0x8000, CNROM_reg[2] &0x7 | OR &~0x7); - setchr8(CNROM_reg[0] &0x0F); - } - if (mapperFlags &8) - setmirror(mapperFlags &0x04? MI_H: MI_V); - else - setmirror(CNROM_reg[1] &0x10? MI_1: MI_0); -} - -static DECLFW(CNROM_writeReg) { - switch(A &0xE000) { - case 0x8000: case 0xA000: - CNROM_reg[0] =V; - break; - case 0xE000: - CNROM_reg[2] =V; - break; - } - sync(); -} - -static DECLFW(BF9097_writeMirroring) { - CNROM_reg[1] =V; - sync(); -} - -void CNROM_BF9097_reset(uint8 clearRegs) { /* This strange mapper is used for both (C)NROM games and FireHawk. What an absurd combination!*/ - sync =CNROM_sync; - SetWriteHandler(0x8000, 0xFFFF, CNROM_writeReg); - if (~mapperFlags &8) - SetWriteHandler(0x9000, 0x9FFF, BF9097_writeMirroring); - sync(); -} - -#undef CNROM_reg diff --git a/src/boards/468_discrete.h b/src/boards/468_discrete.h deleted file mode 100644 index e42c438..0000000 --- a/src/boards/468_discrete.h +++ /dev/null @@ -1,73 +0,0 @@ -#define latch regByte[0] - -static void ANROM_sync () { - int AND =prgAND >>2; - int OR =prgOR >>2; - setprg32(0x8000, latch &AND | OR &~AND); - setchr8(0); - setmirror(latch &0x10? MI_1: MI_0); -} - -static void BNROM_sync () { - int AND =prgAND >>2; - int OR =prgOR >>2; - setprg32(0x8000, latch &AND | OR &~AND); - setchr8(0); - setmirror(mapperFlags &4? MI_H: MI_V); -} - -static void GNROM_sync () { - int AND =prgAND >>2; - int OR =prgOR >>2 | (mapperFlags &4? 2: 0); - setprg32(0x8000, latch >>4 &AND | OR &~AND); - setchr8(latch &0x0F); - setmirror(mapper &1? MI_H: MI_V); -} - -static void UNROM_sync () { - int AND =prgAND >>1; - int OR =prgOR >>1; - setprg16(0x8000, latch &AND | OR &~AND); - setprg16(0xC000, 0xFF &AND | OR &~AND); - setchr8(0); - setmirror(mapperFlags &4? MI_H: MI_V); -} - -static DECLFW(DISCRETE_writeLatch) { - latch =V; - sync(); -} - -static DECLFW(Portopia_writeLatch) { - DISCRETE_writeLatch(A, A ==0xA000 && V ==0x00? 0x06: V); /* Strange hack, needed to get #282 "Portopia Serial Murder Case" on 852-in-1 running */ -} - -static DECLFW(ColorDreams_writeLatch) { - DISCRETE_writeLatch(A, V >>4 &0xF | V <<4 &0xF0); /* Sswap nibbles to mimic GNROM */ -} - - -void ANROM_BNROM_reset(uint8 clearRegs) { - sync =mapperFlags &8? BNROM_sync: ANROM_sync; - prgAND =(mapper ==0x06 || mapper ==0x16)? 0x3F: mapperFlags &2? 0x0F: 0x1F; - SetWriteHandler(0x8000, 0xFFFF, DISCRETE_writeLatch); - latch =0; - sync(); -} - -void GNROM_reset(uint8 clearRegs) { - sync =GNROM_sync; - prgAND =mapperFlags &8? 0x07: 0x0F; - SetWriteHandler(0x8000, 0xFFFF, misc &0x10 && mapper &~0x10? DISCRETE_writeLatch: ColorDreams_writeLatch); - latch =0; - sync(); -} - -void UNROM_reset(uint8 clearRegs) { - sync =UNROM_sync; - prgAND =mapper ==0x0B || misc2 &0x10? 0x3F: mapperFlags &2? 0x0F: 0x1F; - SetWriteHandler(0x8000, 0xFFFF, mapper ==0x09 && mapperFlags ==0xE? Portopia_writeLatch: DISCRETE_writeLatch); - sync(); -} - -#undef latch diff --git a/src/boards/468_fme7.h b/src/boards/468_fme7.h deleted file mode 100644 index 0e3d311..0000000 --- a/src/boards/468_fme7.h +++ /dev/null @@ -1,72 +0,0 @@ -#define FME7_reg regByte -#define FME7_index regByte[15] -#define FME7_counter regWord[0] - -static void FME7_sync() { - int AND =mapperFlags &8? 0xFF: 0x7F; - switch(FME7_reg[8] &0xC0) { - case 0x00: case 0x80: - setprg8(0x6000, FME7_reg[0x8] &prgAND | prgOR &~prgAND); - break; - case 0x40: - /* Open Bus */ - break; - case 0xC0: - setprg8r(0x10, 0x6000, 0); - break; - } - - setprg8(0x8000, FME7_reg[0x9] &prgAND | prgOR &~prgAND); - setprg8(0xA000, FME7_reg[0xA] &prgAND | prgOR &~prgAND); - setprg8(0xC000, FME7_reg[0xB] &prgAND | prgOR &~prgAND); - setprg8(0xE000, prgAND | prgOR &~prgAND); - setchr1(0x0000, FME7_reg[0x0] &AND); - setchr1(0x0400, FME7_reg[0x1] &AND); - setchr1(0x0800, FME7_reg[0x2] &AND); - setchr1(0x0C00, FME7_reg[0x3] &AND); - setchr1(0x1000, FME7_reg[0x4] &AND); - setchr1(0x1400, FME7_reg[0x5] &AND); - setchr1(0x1800, FME7_reg[0x6] &AND); - setchr1(0x1C00, FME7_reg[0x7] &AND); - setmirror(FME7_reg[0xC] &3 ^(FME7_reg[0xC] &2? 0: 1)); -} - -static DECLFW(FME7_writeIndex) { - FME7_index =V &0xF; -} - -static DECLFW(FME7_writeReg) { - switch(FME7_index) { - case 0xE: - FME7_counter =FME7_counter &0xFF00 |V; - break; - case 0xF: - FME7_counter =FME7_counter &0x00FF |V <<8; - break; - case 0xD: - X6502_IRQEnd(FCEU_IQEXT); - /* Falling through */ - default: - FME7_reg[FME7_index] =V; - sync(); - } -} - -static void FP_FASTAPASS(1) FME7_cpuCycle(int a) { - while (a--) { - if (FME7_reg[0xD] &0x80 && !--FME7_counter && FME7_reg[0xD] &0x01) X6502_IRQBegin(FCEU_IQEXT); - } -} - -void FME7_reset(uint8 clearRegs) { - sync =FME7_sync; - prgAND =mapperFlags &2? 0x0F: 0x1F; - MapIRQHook =FME7_cpuCycle; - SetWriteHandler(0x8000, 0x9FFF, FME7_writeIndex); - SetWriteHandler(0xA000, 0xBFFF, FME7_writeReg); - sync(); -} - -#undef FME7_reg -#undef FME7_index -#undef FME7_counter diff --git a/src/boards/468_if12.h b/src/boards/468_if12.h deleted file mode 100644 index 12ec1e7..0000000 --- a/src/boards/468_if12.h +++ /dev/null @@ -1,31 +0,0 @@ -#define IF12_reg regByte - -static void IF12_sync () { - int AND =prgAND >>1; - int OR =prgOR >>1; - setprg16(0x8000, IF12_reg[1] &AND | OR &~AND); - setprg16(0xC000, 0xFF &AND | OR &~AND); - setchr8(IF12_reg[0] >>1 &0xF); - setmirror(IF12_reg[0] &1? MI_H: MI_V); -} - -static DECLFW(IF12_writeReg) { - IF12_reg[A >>14 &1] =V; - sync(); -} - -void IF12_reset(uint8 clearRegs) { - sync =IF12_sync; - prgAND =mapperFlags &2? 0x0F: 0x1F; - SetWriteHandler(0x8000, 0xFFFF, IF12_writeReg); - sync(); -} - -void UNROM_IF12_reset(uint8 clearRegs) { - if (mapperFlags &8) - UNROM_reset(clearRegs); - else - IF12_reset(clearRegs); -} - -#undef IF12_reg diff --git a/src/boards/468_lf36.h b/src/boards/468_lf36.h deleted file mode 100644 index 73f9407..0000000 --- a/src/boards/468_lf36.h +++ /dev/null @@ -1,46 +0,0 @@ -#define LF36_prg regByte[0] -#define LF36_irq regByte[1] -#define LF36_counter regWord[0] - -static void LF36_sync () { - int OR =prgOR | mapperFlags &0x08; - setprg8(0x8000, 0x04 | OR); - setprg8(0xA000, 0x05 | OR); - setprg8(0xC000, LF36_prg &0x07 | OR); - setprg8(0xE000, 0x07 | OR); - setchr8(0); - setmirror(mapperFlags &4? MI_H: MI_V); -} - -static DECLFW(LF36_writeReg) { - switch (A &0xE000) { - case 0x8000: LF36_irq =0; break; - case 0xA000: LF36_irq =1; break; - case 0XE000: LF36_prg =V; sync(); break; - } -} - -static void FP_FASTAPASS(1) LF36_cpuCycle(int a) { - while (a--) { - if (LF36_irq) { - if (++LF36_counter &0x1000) - X6502_IRQBegin(FCEU_IQEXT); - else - X6502_IRQEnd(FCEU_IQEXT); - } else { - X6502_IRQEnd(FCEU_IQEXT); - LF36_counter =0; - } - } -} - -void LF36_reset(uint8 clearRegs) { - sync =LF36_sync; - MapIRQHook =LF36_cpuCycle; - SetWriteHandler(0x8000, 0xFFFF, LF36_writeReg); - sync(); -} - -#undef LF36_prg -#undef LF36_irq -#undef LF36_counter diff --git a/src/boards/468_mmc1.h b/src/boards/468_mmc1.h deleted file mode 100644 index b780ce2..0000000 --- a/src/boards/468_mmc1.h +++ /dev/null @@ -1,72 +0,0 @@ -#define MMC1_reg regByte -#define MMC1_control regByte[0] -#define MMC1_chr0 regByte[1] -#define MMC1_chr1 regByte[2] -#define MMC1_prg regByte[3] -#define MMC1_shift regByte[4] -#define MMC1_count regByte[5] -#define MMC1_filter regByte[6] - -static void MMC1_sync () { - int AND =prgAND >>1; - int OR =prgOR >>1 | (mapper &0x01? (MMC1_chr0 &0x10): (mapperFlags &0x06)); - if (MMC1_control &0x08) { /* 16 KiB mode */ - if (MMC1_control &0x04) { /* OR logic */ - setprg16(0x8000, MMC1_prg &AND | OR &~AND); - setprg16(0xC000, 0xFF &AND | OR &~AND); - } else { /* AND logic */ - setprg16(0x8000, 0 &AND | OR &~AND); - setprg16(0xC000, MMC1_prg &AND | OR &~AND); - } - } else - setprg32(0x8000, (MMC1_prg &AND | OR &~AND) >>1); - - AND =mapper &0x01? 0x0F: 0x1F; /* SUROM needs to have the upper PRG bank bit, which is in the CHR registers, masked off */ - if (MMC1_control &0x10) { /* 4 KiB mode */ - setchr4(0x0000, MMC1_chr0 &AND); - setchr4(0x1000, MMC1_chr1 &AND); - } else /* 8 KiB mode */ - setchr8(MMC1_chr0 >>1 &(AND >>1)); - - setmirror(MMC1_control &2? (MMC1_control &1? MI_H: MI_V): (MMC1_control &1? MI_1: MI_0)); -} - -static DECLFW(MMC1_writeReg) { - if (V &0x80) { - MMC1_shift =MMC1_count =0; - MMC1_control |=0x0C; - sync(); - } else - if (!MMC1_filter) { - MMC1_shift |=(V &1) <>13 &3] =MMC1_shift; - MMC1_count =0; - MMC1_shift =0; - sync(); - } - } - MMC1_filter =2; -} - -static void FP_FASTAPASS(1) MMC1_cpuCycle(int a) { - while (a--) if (MMC1_filter) MMC1_filter--; -} - -void MMC1_reset(uint8 clearRegs) { - sync =MMC1_sync; - MapIRQHook =MMC1_cpuCycle; - prgAND =mapperFlags &2? (mapperFlags &8? 0x07: 0x0F): 0x1F; - SetWriteHandler(0x8000, 0xFFFF, MMC1_writeReg); - if (clearRegs) MMC1_control =0x0C; - sync(); -} - -#undef MMC1_reg -#undef MMC1_control -#undef MMC1_chr0 -#undef MMC1_chr1 -#undef MMC1_prg -#undef MMC1_shift -#undef MMC1_count -#undef MMC1_filter diff --git a/src/boards/468_mmc24.h b/src/boards/468_mmc24.h deleted file mode 100644 index 398fcc0..0000000 --- a/src/boards/468_mmc24.h +++ /dev/null @@ -1,67 +0,0 @@ -#define MMC24_reg regByte - -static void MMC2_sync() { - setprg8(0x8000, MMC24_reg[0] &prgAND | prgOR &~prgAND); - setprg8(0xA000, 0xFD &prgAND | prgOR &~prgAND); - setprg8(0xC000, 0xFE &prgAND | prgOR &~prgAND); - setprg8(0xE000, 0xFF &prgAND | prgOR &~prgAND); - setchr4(0x0000, MMC24_reg[1 +MMC24_reg[6]]); - setchr4(0x1000, MMC24_reg[3 +MMC24_reg[7]]); - setmirror(MMC24_reg[5] &1? MI_H: MI_V); -} - -static void MMC4_sync() { - int AND =prgAND >>1; - int OR =prgOR >>1; - setprg16(0x8000, MMC24_reg[0] &AND | OR &~AND); - setprg16(0xC000, 0xFF &AND | OR &~AND); - setchr4(0x0000, MMC24_reg[1 +MMC24_reg[6]]); - setchr4(0x1000, MMC24_reg[3 +MMC24_reg[7]]); - setmirror(MMC24_reg[5] &1? MI_H: MI_V); -} - -static DECLFW(MMC24_writeReg) { - MMC24_reg[(A >>12) -0xA] =V; - sync(); -} - -static void FP_FASTAPASS(1) MMC24_ppuHook(uint32 A) { - uint8 l, h = A >> 8; - if (h >= 0x20 || ((h & 0xF) != 0xF)) return; - l = A & 0xF0; - if (h < 0x10) { - if (l == 0xD0) { - MMC24_reg[6] =0; - sync(); - } else if (l == 0xE0) { - MMC24_reg[6] =1; - sync(); - } - } else { - if (l == 0xD0) { - MMC24_reg[7] =0; - sync(); - } else if (l == 0xE0) { - MMC24_reg[7] =1; - sync(); - } - } -} - -void MMC2_reset(uint8 clearRegs) { - sync =MMC2_sync; - prgAND =0x0F; - PPU_hook =MMC24_ppuHook; - SetWriteHandler(0xA000, 0xFFFF, MMC24_writeReg); - sync(); -} - -void MMC4_reset(uint8 clearRegs) { - sync =MMC4_sync; - prgAND =mapperFlags &2? 0x0F: 0x1F; - PPU_hook =MMC24_ppuHook; - SetWriteHandler(0xA000, 0xFFFF, MMC24_writeReg); - sync(); -} - -#undef MMC24_reg diff --git a/src/boards/468_mmc3.h b/src/boards/468_mmc3.h deleted file mode 100644 index f46c64d..0000000 --- a/src/boards/468_mmc3.h +++ /dev/null @@ -1,80 +0,0 @@ -#define MMC3_reg regByte -#define MMC3_index regByte[8] -#define MMC3_mirroring regByte[9] -#define MMC3_wram regByte[10] -#define MMC3_reload regByte[11] -#define MMC3_count regByte[12] -#define MMC3_irq regByte[13] -#define MMC3_lastReg regByte[14] - -static void MMC3_sync () { - int chrAND =mapper &0x01? 0xFF: 0x7F; - int OR =prgOR | (misc2 &1? 12: 0); - setprg8(0x8000 ^(MMC3_index <<8 &0x4000), MMC3_reg[6] &prgAND | OR &~prgAND); - setprg8(0xA000, MMC3_reg[7] &prgAND | OR &~prgAND); - setprg8(0xC000 ^(MMC3_index <<8 &0x4000), 0xFE &prgAND | OR &~prgAND); - setprg8(0xE000, 0xFF &prgAND | OR &~prgAND); - setchr1(0x0000 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] &0xFE)&chrAND); - setchr1(0x0400 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] |0x01)&chrAND); - setchr1(0x0800 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] &0xFE)&chrAND); - setchr1(0x0C00 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] |0x01)&chrAND); - setchr1(0x1000 ^(MMC3_index <<5 &0x1000), MMC3_reg[2] &chrAND); - setchr1(0x1400 ^(MMC3_index <<5 &0x1000), MMC3_reg[3] &chrAND); - setchr1(0x1800 ^(MMC3_index <<5 &0x1000), MMC3_reg[4] &chrAND); - setchr1(0x1C00 ^(MMC3_index <<5 &0x1000), MMC3_reg[5] &chrAND); - - if (mapper &2) switch(MMC3_mirroring &3) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MMC3_reg[MMC3_lastReg] &0x80? MI_1: MI_0); break; - case 3: setmirror(MI_1); break; - } else - setmirror(MMC3_mirroring &1? MI_H: MI_V); -} - -static DECLFW(MMC3_writeReg) { - switch(A &0xE001) { - case 0x8000: MMC3_index =V; sync(); break; - case 0x8001: MMC3_reg[MMC3_index &7] =V; sync(); break; - case 0xA000: MMC3_mirroring =V; sync(); break; - case 0xA001: MMC3_wram =V; sync(); break; - case 0xC000: MMC3_reload =V; break; - case 0xC001: MMC3_count =0; break; - case 0xE000: MMC3_irq =0; X6502_IRQEnd(FCEU_IQEXT); break; - case 0xE001: MMC3_irq =1; break; - } -} - -static void MMC3_horizontalBlanking(void) { - MMC3_count =!MMC3_count? MMC3_reload: --MMC3_count; - if (!MMC3_count && MMC3_irq) X6502_IRQBegin(FCEU_IQEXT); -} - -static void FP_FASTAPASS(1) MMC3_ppuHook(uint32 A) { - A &=0x1FFF; - if (MMC3_index &0x80) A ^=0x1000; - if (A <0x1000) - MMC3_lastReg =A >>11; - else - MMC3_lastReg =(A >>10) -2; - if ((MMC3_mirroring &3) ==2) setmirror(MMC3_reg[MMC3_lastReg] &0x80? MI_1: MI_0); -} - -void MMC3_reset(uint8 clearRegs) { - sync =MMC3_sync; - GameHBIRQHook =MMC3_horizontalBlanking; - if (mapper &2) PPU_hook =MMC3_ppuHook; - prgAND =mapperFlags &8? (mapperFlags &4? (mapperFlags &2? (misc2 &2? 0x07: 0x0F): 0x1F): 0x3F): 0x7F; - SetWriteHandler(0x8000, 0xFFFF, MMC3_writeReg); - MMC3_mirroring =1; /* "Legendary Games of NES' 509-in-1"'s menu runs as MMC3 with H mirroring and expects that setting to stay when running a mapper 206 game such as Legend of Valkyrie. */ - sync(); -} - -#undef MMC3_reg -#undef MMC3_index -#undef MMC3_mirroring -#undef MMC3_wram -#undef MMC3_reload -#undef MMC3_count -#undef MMC3_irq -#undef MMC3_lastReg diff --git a/src/boards/468_nanjing.h b/src/boards/468_nanjing.h deleted file mode 100644 index fa5f555..0000000 --- a/src/boards/468_nanjing.h +++ /dev/null @@ -1,29 +0,0 @@ -#define NANJING_reg regByte - -static void NANJING_sync () { - setprg32(0x8000, NANJING_reg[2] <<4 &0x30 | NANJING_reg[0] &0x0F | (NANJING_reg[3] &4? 0x00: 0x03) | prgOR >>2); - setchr8(0); - setmirror(mapperFlags &4? MI_H: MI_V); -} - -static DECLFW(NANJING_writeReg) { - NANJING_reg[A >>8 &3] =V; - sync(); -} - -static void NANJING_horizontalBlanking(void) { - if (NANJING_reg[0] &0x80 && scanline <239) { /* Actual hardware cannot look at the current scanline number, but instead latches PA09 on PA13 rises. This does not seem possible with the current PPU emulation however. */ - setchr4(0x0000, scanline >=127? 1: 0); - setchr4(0x1000, scanline >=127? 1: 0); - } else - setchr8(0); -} - -void NANJING_reset(uint8 clearRegs) { - sync =NANJING_sync; - GameHBIRQHook = NANJING_horizontalBlanking; - SetWriteHandler(0x5000, 0x53FF, NANJING_writeReg); - sync(); -} - -#undef NANJING_reg diff --git a/src/boards/468_vrc1.h b/src/boards/468_vrc1.h deleted file mode 100644 index 087e65e..0000000 --- a/src/boards/468_vrc1.h +++ /dev/null @@ -1,25 +0,0 @@ -#define VRC1_reg regByte - -static void VRC1_sync () { - setprg8(0x8000, VRC1_reg[0] &prgAND | prgOR &~prgAND); - setprg8(0xA000, VRC1_reg[2] &prgAND | prgOR &~prgAND); - setprg8(0xC000, VRC1_reg[4] &prgAND | prgOR &~prgAND); - setprg8(0xE000, 0xFF &prgAND | prgOR &~prgAND); - setchr4(0x0000, VRC1_reg[6] &0x0F | VRC1_reg[1] <<3 &0x10); - setchr4(0x1000, VRC1_reg[7] &0x0F | VRC1_reg[1] <<2 &0x10); - setmirror(VRC1_reg[1] &1? MI_H: MI_V); -} - -static DECLFW(VRC1_writeReg) { - VRC1_reg[A >>12 &7] =V; - sync(); -} - -void VRC1_reset(uint8 clearRegs) { - sync =VRC1_sync; - prgAND =mapperFlags &8? (mapperFlags &4? (mapperFlags &2? 0x0F: 0x1F): 0x3F): 0x7F; - SetWriteHandler(0x8000, 0xFFFF, VRC1_writeReg); - sync(); -} - -#undef VRC1_reg diff --git a/src/boards/468_vrc24.h b/src/boards/468_vrc24.h deleted file mode 100644 index 9916147..0000000 --- a/src/boards/468_vrc24.h +++ /dev/null @@ -1,92 +0,0 @@ -#define VRC24_prg regByte -#define VRC24_mirroring regByte[2] -#define VRC24_misc regByte[3] -#define VRC24_chr regWord -#define VRCIRQ_latch regByte[13] -#define VRCIRQ_mode regByte[14] -#define VRCIRQ_count regByte[15] -#define VRCIRQ_cycles regWord[8] - -static void VRC24_sync() { - setprg8(0x8000 ^(VRC24_misc <<13 &0x4000), VRC24_prg[0] &prgAND | prgOR &~prgAND); - setprg8(0xA000, VRC24_prg[1] &prgAND | prgOR &~prgAND); - setprg8(0xC000 ^(VRC24_misc <<13 &0x4000), 0xFE &prgAND | prgOR &~prgAND); - setprg8(0xE000, 0xFF &prgAND | prgOR &~prgAND); - setchr1(0x0000, VRC24_chr[0]); - setchr1(0x0400, VRC24_chr[1]); - setchr1(0x0800, VRC24_chr[2]); - setchr1(0x0C00, VRC24_chr[3]); - setchr1(0x1000, VRC24_chr[4]); - setchr1(0x1400, VRC24_chr[5]); - setchr1(0x1800, VRC24_chr[6]); - setchr1(0x1C00, VRC24_chr[7]); - setmirror(VRC24_mirroring &3 ^(VRC24_mirroring &2? 0: 1)); -} - -static DECLFW(VRC24_writeReg) { - uint8 index; - A =A &0xF000 | (mapper &2? ((A &0xA? 1: 0) | (A &0x5? 2: 0)): ((A &0x5? 1: 0) | (A &0xA? 2: 0))); - switch (A &0xF000) { - case 0x8000: case 0xA000: - VRC24_prg[A >>13 &1] =V; - sync(); - break; - case 0x9000: - if (~A &2) - VRC24_mirroring =V & (mapper &1? 3: 1); - else - if (~A &1 && mapper &1) - VRC24_misc =V; - sync(); - break; - case 0xF000: - if (mapper &1) switch (A &3) { - case 0: VRCIRQ_latch =VRCIRQ_latch &0xF0 | V &0x0F; break; - case 1: VRCIRQ_latch =VRCIRQ_latch &0x0F | V <<4; break; - case 2: VRCIRQ_mode =V; - if (VRCIRQ_mode &0x02) { - VRCIRQ_count =VRCIRQ_latch; - VRCIRQ_cycles =341; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 3: VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02; - X6502_IRQEnd(FCEU_IQEXT); - break; - } - break; - default: - index =(A -0xB000) >>11 | A >>1 &1; - if (A &1) - VRC24_chr[index] =VRC24_chr[index] & 0x0F | V <<4; - else - VRC24_chr[index] =VRC24_chr[index] &~0x0F | V &0x0F; - sync(); - break; - } -} - -static void FP_FASTAPASS(1) VRCIRQ_cpuCycle(int a) { - while (a--) { - if (VRCIRQ_mode &0x02 && (VRCIRQ_mode &0x04 || (VRCIRQ_cycles -=3) <=0)) { - if (~VRCIRQ_mode &0x04) VRCIRQ_cycles +=341; - if (!++VRCIRQ_count) { - VRCIRQ_count =VRCIRQ_latch; - X6502_IRQBegin(FCEU_IQEXT); - } - } - } -} - -void VRC24_reset(uint8 clearRegs) { - sync =VRC24_sync; - prgAND =mapperFlags &2? 0x0F: 0x1F; - if (mapper &1) MapIRQHook =VRCIRQ_cpuCycle; - SetWriteHandler(0x8000, 0xFFFF, VRC24_writeReg); - sync(); -} - -#undef VRC24_prg -#undef VRC24_mirroring -#undef VRC24_misc -#undef VRC24_chr diff --git a/src/boards/468_vrc3.h b/src/boards/468_vrc3.h deleted file mode 100644 index 5553b23..0000000 --- a/src/boards/468_vrc3.h +++ /dev/null @@ -1,63 +0,0 @@ -#define VRC3_prg regByte[0] -#define VRC3_latch regWord[0] -#define VRC3_mode regByte[1] -#define VRC3_count regWord[1] - -static void VRC3_sync() { - int AND =prgAND >>1; - int OR =prgOR >>1; - setprg16(0x8000, VRC3_prg &AND | OR &~AND); - setprg16(0xC000, AND | OR &~AND); - setchr8(0); - setmirror(mapperFlags &4? MI_H: MI_V); -} - -static DECLFW(VRC3_writeReg) { - int shift; - switch(A &0xF000) { - case 0x8000: case 0x9000: case 0xA000: case 0xB000: - V &=0xF; - shift =A >>10 &0xC; - VRC3_latch =VRC3_latch &~(0xF <>1; - int OR =prgOR >>1; - setprg16(0x8000, VRC6_prg16 & AND | OR & ~AND); - setprg8(0xC000, VRC6_prg8 &prgAND | prgOR &~prgAND); - setprg8(0xE000, prgAND | prgOR &~prgAND); - setchr1(0x0000, VRC6_chr[0]); - setchr1(0x0400, VRC6_chr[1]); - setchr1(0x0800, VRC6_chr[2]); - setchr1(0x0C00, VRC6_chr[3]); - setchr1(0x1000, VRC6_chr[4]); - setchr1(0x1400, VRC6_chr[5]); - setchr1(0x1800, VRC6_chr[6]); - setchr1(0x1C00, VRC6_chr[7]); - setmirror((VRC6_misc &0xC ^(VRC6_misc &0x8? 0: 0x4)) >>2); -} - -static DECLFW(VRC6_writeReg) { - uint8 index; - switch (A &0xF003) { - case 0x8000: case 0x8001: case 0x8002: case 0x8003: - VRC6_prg16 =V; - sync(); - break; - case 0xB003: - VRC6_misc =V; - sync(); - break; - case 0xC000: case 0xC001: case 0xC002: case 0xC003: - VRC6_prg8 =V; - sync(); - break; - case 0xD000: case 0xD001: case 0xD002: case 0xD003: case 0xE000: case 0xE001: case 0xE002: case 0xE003: - index =(A -0xD000) >>10 | A &3; - VRC6_chr[index] =V; - sync(); - break; - case 0xF000: - VRCIRQ_latch =V; - break; - case 0xF001: - VRCIRQ_mode =V; - if (VRCIRQ_mode &0x02) { - VRCIRQ_count =VRCIRQ_latch; - VRCIRQ_cycles =341; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xF002: - VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02; - X6502_IRQEnd(FCEU_IQEXT); - break; - } -} - -void VRC6_reset(uint8 clearRegs) { - sync =VRC6_sync; - prgAND =mapperFlags &2? 0x0F: 0x1F; - MapIRQHook =VRCIRQ_cpuCycle; - SetWriteHandler(0x8000, 0xFFFF, VRC6_writeReg); - sync(); -} - -#undef VRC6_chr -#undef VRC6_prg16 -#undef VRC6_prg8 -#undef VRC6_misc diff --git a/src/boards/468_vrc7.h b/src/boards/468_vrc7.h deleted file mode 100644 index 24e5938..0000000 --- a/src/boards/468_vrc7.h +++ /dev/null @@ -1,82 +0,0 @@ -#define VRC7_chr regByte -#define VRC7_prg0 regByte[8] -#define VRC7_prg1 regByte[9] -#define VRC7_prg2 regByte[10] -#define VRC7_misc regByte[11] - -static void VRC7_sync() { - setprg8(0x8000, VRC7_prg0 &prgAND | prgOR &~prgAND); - setprg8(0xA000, VRC7_prg1 &prgAND | prgOR &~prgAND); - setprg8(0xC000, VRC7_prg2 &prgAND | prgOR &~prgAND); - setprg8(0xE000, prgAND | prgOR &~prgAND); - setchr1(0x0000, VRC7_chr[0]); - setchr1(0x0400, VRC7_chr[1]); - setchr1(0x0800, VRC7_chr[2]); - setchr1(0x0C00, VRC7_chr[3]); - setchr1(0x1000, VRC7_chr[4]); - setchr1(0x1400, VRC7_chr[5]); - setchr1(0x1800, VRC7_chr[6]); - setchr1(0x1C00, VRC7_chr[7]); - setmirror(VRC7_misc &3 ^(VRC7_misc &2? 0: 1)); -} - -static DECLFW(VRC7_writeReg) { - uint8 index; - A =A &0xF000 | (A &0x18? 1: 0) | (A &0x20? 2: 0); - switch (A &0xF003) { - case 0x8000: - VRC7_prg0 =V; - sync(); - break; - case 0x8001: - VRC7_prg1 =V; - sync(); - break; - case 0x9000: - VRC7_prg2 =V; - sync(); - break; - case 0x9001: case 0x9002: - /* sound */ - break; - case 0xA000: case 0xA001: case 0xB000: case 0xB001: case 0xC000: case 0xC001: case 0xD000: case 0xD001: - index =(A -0xA000) >>11 | A &1; - VRC7_chr[index] =V; - sync(); - break; - case 0xE000: - VRC7_misc =V; - sync(); - break; - case 0xE001: - VRCIRQ_latch =V; - break; - case 0xF000: - VRCIRQ_mode =V; - if (VRCIRQ_mode &0x02) { - VRCIRQ_count =VRCIRQ_latch; - VRCIRQ_cycles =341; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xF001: - VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02; - X6502_IRQEnd(FCEU_IQEXT); - break; - } -} - -void VRC7_reset(uint8 clearRegs) { - sync =VRC7_sync; - prgAND =mapperFlags &8? (mapperFlags &4? (mapperFlags &2? 0x0F: 0x1F): 0x3F): 0x7F; - MapIRQHook =VRCIRQ_cpuCycle; - SetWriteHandler(0x8000, 0xFFFF, VRC7_writeReg); - sync(); -} - -#undef VRC7_chr -#undef VRC7_prg0 -#undef VRC7_prg1 -#undef VRC7_prg2 -#undef VRC7_misc - diff --git a/src/boards/asic_fme7.c b/src/boards/asic_fme7.c new file mode 100644 index 0000000..124ec5e --- /dev/null +++ b/src/boards/asic_fme7.c @@ -0,0 +1,134 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_FME7.h" +#include "wram.h" + +static void (*FME7_cbSync)(); +static uint8 FME7_index; +static uint8 FME7_reg[16]; + +static SFORMAT FME7_stateRegs[] = { + { &FME7_index, 1, "FM7I" }, + { FME7_reg, 16, "FM7R" }, + { 0 } +}; + +void FME7_syncWRAM (int OR) { + if (PRGsize[0x10] && FME7_reg[8] &0x40) setprg8r(0x10, 0x6000, FME7_reg[8] | OR); +} + +void FME7_syncPRG (int AND, int OR) { + if (~FME7_reg[8] &0x40) setprg8(0x6000, FME7_reg[8] &AND | OR); + setprg8(0x8000, FME7_reg[ 9] &AND | OR); + setprg8(0xA000, FME7_reg[10] &AND | OR); + setprg8(0xC000, FME7_reg[11] &AND | OR); + setprg8(0xE000, 0xFF &AND | OR); +} + +void FME7_syncCHR (int AND, int OR) { + setchr1(0x0000, FME7_reg[0] &AND | OR); + setchr1(0x0400, FME7_reg[1] &AND | OR); + setchr1(0x0800, FME7_reg[2] &AND | OR); + setchr1(0x0C00, FME7_reg[3] &AND | OR); + setchr1(0x1000, FME7_reg[4] &AND | OR); + setchr1(0x1400, FME7_reg[5] &AND | OR); + setchr1(0x1800, FME7_reg[6] &AND | OR); + setchr1(0x1C00, FME7_reg[7] &AND | OR); +} + +void FME7_syncMirror () { + setmirror(FME7_reg[12] &2? (FME7_reg[12] &1? MI_1: MI_0): FME7_reg[12] &1? MI_H: MI_V); +} + +DECLFR(FME7_readWRAM) { + return ~FME7_reg[8] &0x40 || FME7_reg[8] &0x80? CartBR(A): A >>8; +} + +DECLFW(FME7_writeWRAM) { + if (FME7_reg[8] &0x80) CartBW(A, V); +} + +DECLFW(FME7_writeReg) { + if (A &0x2000) { + FME7_reg[FME7_index &0xF] = V; + if ((FME7_index &0xF) == 13) X6502_IRQEnd(FCEU_IQEXT); + FME7_cbSync(); + } else + FME7_index = V; +} + +void FP_FASTAPASS(1) FME7_cpuCycle (int a) { + while (a--) { + int16_t counter = FME7_reg[14] | FME7_reg[15] <<8; + if (FME7_reg[13] &0x80 && !--counter && FME7_reg[13] &0x01) X6502_IRQBegin(FCEU_IQEXT); + FME7_reg[14] = counter &0xFF; + FME7_reg[15] = counter >>8; + } +} + +static void FME7_clear () { + int i; + for (i = 0; i < 16; i++) FME7_reg[i] = 0; + FME7_cbSync(); +} + +static void FME7_setHandlers () { + SetReadHandler(0x6000, 0x7FFF, FME7_readWRAM); + SetWriteHandler(0x6000, 0x7FFF, FME7_writeWRAM); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xBFFF, FME7_writeReg); + MapIRQHook = FME7_cpuCycle; +} + +static void FME7_configure (void (*sync)()) { + FME7_cbSync = sync; +} + +void FME7_activate (uint8 clear, void (*sync)()) { + FME7_configure(sync); + FME7_setHandlers(); + if (clear) + FME7_clear(); + else + FME7_cbSync(); +} + +void FME7_addExState () { + AddExState(FME7_stateRegs, ~0, 0, 0); +} + +void FME7_restore (int version) { + FME7_cbSync(); +} + +void FME7_power () { + FME7_setHandlers(); + FME7_clear(); +} + +void FME7_init (CartInfo *info, void (*sync)()) { + FME7_addExState(); + FME7_configure(sync); + info->Power = FME7_power; + info->Reset = FME7_cbSync; + GameStateRestore = FME7_restore; +} diff --git a/src/boards/asic_fme7.h b/src/boards/asic_fme7.h new file mode 100644 index 0000000..1528e9f --- /dev/null +++ b/src/boards/asic_fme7.h @@ -0,0 +1,38 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_FME7_H +#define _ASIC_FME7_H + +void FME7_syncWRAM (int); +void FME7_syncPRG (int, int); +void FME7_syncCHR (int, int); +void FME7_syncMirror (); +DECLFR(FME7_readWRAM); +DECLFW(MMC3_writeWRAM); +DECLFW(FME7_writeReg); +void FP_FASTAPASS(1) FME7_cpuCycle (int); +void FME7_activate (uint8, void (*)()); +void FME7_addExState (); +void FME7_restore (int); +void FME7_power (); +void FME7_init (CartInfo *, void (*)()); + +#endif \ No newline at end of file diff --git a/src/boards/asic_mmc2.c b/src/boards/asic_mmc2.c deleted file mode 100644 index 52f494f..0000000 --- a/src/boards/asic_mmc2.c +++ /dev/null @@ -1,108 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2025 NewRisingSun - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "asic_mmc2.h" - -static void (*MMC2_cbSync)(); -static uint8 MMC2_reg[6]; -static uint8 MMC2_latch[2]; - -static SFORMAT MMC2_state[] = { - { MMC2_reg, 6, "MC2R" }, - { MMC2_latch, 2, "MC2S" }, - { 0 } -}; - -static void (*MMC2_cbSync)(); - -void MMC2_syncPRG (int AND, int OR) { - setprg8(0x8000, MMC2_reg[0] &AND |OR); - setprg8(0xA000, 0xD &AND |OR); - setprg8(0xC000, 0xE &AND |OR); - setprg8(0xE000, 0xF &AND |OR); -} - -void MMC2_syncCHR (int AND, int OR) { - setchr4(0x0000, MMC2_reg[1 +MMC2_latch[0]] &AND |OR); - setchr4(0x1000, MMC2_reg[3 +MMC2_latch[1]] &AND |OR); -} - -void MMC2_syncMirror () { - setmirror(MMC2_reg[5] &1? MI_H: MI_V); -} - -static void FP_FASTAPASS(1) MMC2_trapPPUAddressChange (uint32 A) { - if ((A &0x2FF0) == 0xFD0 || (A &0x2FF0) == 0xFE0) { - MMC2_latch[A >>12 &1] = A >>5 &1; - MMC2_cbSync(); - } -} - -DECLFW(MMC2_write) { - MMC2_reg[(A >>12) -0xA] = V; - MMC2_cbSync(); -} - -static void MMC2_clear () { - MMC2_reg[0] = 0; MMC2_reg[1] = 0; MMC2_reg[2] = 2; MMC2_reg[3] = 0; MMC2_reg[4] = 0; MMC2_reg[5] = 0; - MMC2_latch[0] = 0; MMC2_latch[1] = 0; - MMC2_cbSync(); -} - -static void MMC2_setHandlers() { - SetReadHandler (0x8000, 0xFFFF, CartBR); - SetWriteHandler(0xA000, 0xFFFF, MMC2_write); - PPU_hook = MMC2_trapPPUAddressChange; -} - -static void MMC2_configure (void (*sync)()) { - MMC2_cbSync = sync; -} - -void MMC2_activate (uint8 clear, void (*sync)()) { - MMC2_configure(sync); - MMC2_setHandlers(); - if (clear) - MMC2_clear(); - else - MMC2_cbSync(); -} - -void MMC2_addExState () { - AddExState(MMC2_state, ~0, 0, 0); -} - -void MMC2_restore (int version) { - MMC2_cbSync(); -} - -void MMC2_power () { - MMC2_setHandlers(); - MMC2_clear(); -} - -void MMC2_init (CartInfo *info, void (*sync)()) { - MMC2_addExState(); - MMC2_configure(sync); - info->Power = MMC2_power; - info->Reset = MMC2_cbSync; - GameStateRestore = MMC2_restore; -} diff --git a/src/boards/asic_mmc2and4.c b/src/boards/asic_mmc2and4.c new file mode 100644 index 0000000..9be02c3 --- /dev/null +++ b/src/boards/asic_mmc2and4.c @@ -0,0 +1,117 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_mmc2and4.h" + +static void (*MMC24_cbSync)(); +static uint8 MMC24_reg[6]; +static uint8 MMC24_latch[2]; + +static SFORMAT MMC24_state[] = { + { MMC24_reg, 6, "MC2R" }, + { MMC24_latch, 2, "MC2S" }, + { 0 } +}; + +static void (*MMC24_cbSync)(); + +void MMC24_syncWRAM (int OR) { + if (PRGsize[0x10]) setprg8r(0x10, 0x6000, OR); +} + +void MMC2_syncPRG (int AND, int OR) { + setprg8(0x8000, MMC24_reg[0] &AND |OR); + setprg8(0xA000, 0xFD &AND |OR); + setprg8(0xC000, 0xFE &AND |OR); + setprg8(0xE000, 0xFF &AND |OR); +} + +void MMC4_syncPRG (int AND, int OR) { + setprg16(0x8000, MMC24_reg[0] &AND |OR); + setprg16(0xC000, 0xFF &AND |OR); +} + +void MMC24_syncCHR (int AND, int OR) { + setchr4(0x0000, MMC24_reg[1 +MMC24_latch[0]] &AND |OR); + setchr4(0x1000, MMC24_reg[3 +MMC24_latch[1]] &AND |OR); +} + +void MMC24_syncMirror () { + setmirror(MMC24_reg[5] &1? MI_H: MI_V); +} + +static void FP_FASTAPASS(1) MMC24_trapPPUAddressChange (uint32 A) { + if ((A &0x2FF0) == 0xFD0 || (A &0x2FF0) == 0xFE0) { + MMC24_latch[A >>12 &1] = A >>5 &1; + MMC24_cbSync(); + } +} + +DECLFW(MMC24_write) { + MMC24_reg[(A >>12) -0xA] = V; + MMC24_cbSync(); +} + +static void MMC24_clear () { + MMC24_reg[0] = 0; MMC24_reg[1] = 0; MMC24_reg[2] = 2; MMC24_reg[3] = 0; MMC24_reg[4] = 0; MMC24_reg[5] = 0; + MMC24_latch[0] = 0; MMC24_latch[1] = 0; + MMC24_cbSync(); +} + +static void MMC24_setHandlers() { + SetReadHandler (0x8000, 0xFFFF, CartBR); + SetWriteHandler(0xA000, 0xFFFF, MMC24_write); + PPU_hook = MMC24_trapPPUAddressChange; +} + +static void MMC24_configure (void (*sync)()) { + MMC24_cbSync = sync; +} + +void MMC24_activate (uint8 clear, void (*sync)()) { + MMC24_configure(sync); + MMC24_setHandlers(); + if (clear) + MMC24_clear(); + else + MMC24_cbSync(); +} + +void MMC24_addExState () { + AddExState(MMC24_state, ~0, 0, 0); +} + +void MMC24_restore (int version) { + MMC24_cbSync(); +} + +void MMC24_power () { + MMC24_setHandlers(); + MMC24_clear(); +} + +void MMC24_init (CartInfo *info, void (*sync)()) { + MMC24_addExState(); + MMC24_configure(sync); + info->Power = MMC24_power; + info->Reset = MMC24_cbSync; + GameStateRestore = MMC24_restore; +} diff --git a/src/boards/asic_mmc2.h b/src/boards/asic_mmc2and4.h similarity index 71% rename from src/boards/asic_mmc2.h rename to src/boards/asic_mmc2and4.h index 09d9036..176890c 100644 --- a/src/boards/asic_mmc2.h +++ b/src/boards/asic_mmc2and4.h @@ -18,17 +18,19 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef _ASIC_MMC2_H -#define _ASIC_MMC2_H +#ifndef _ASIC_MMC2AND4_H +#define _ASIC_MMC2AND4_H +void MMC24_syncWRAM (int); void MMC2_syncPRG (int, int); -void MMC2_syncCHR (int, int); -void MMC2_syncMirror (); -DECLFW (MMC2_write); -void MMC2_power (); -void MMC2_restore (int); -void MMC2_addExState (); -void MMC2_activate (uint8, void (*)()); -void MMC2_init (CartInfo *, void (*)()); +void MMC4_syncPRG (int, int); +void MMC24_syncCHR (int, int); +void MMC24_syncMirror (); +DECLFW (MMC24_write); +void MMC24_power (); +void MMC24_restore (int); +void MMC24_addExState (); +void MMC24_activate (uint8, void (*)()); +void MMC24_init (CartInfo *, void (*)()); #endif diff --git a/src/boards/asic_mmc3.c b/src/boards/asic_mmc3.c index af018a6..fea628a 100644 --- a/src/boards/asic_mmc3.c +++ b/src/boards/asic_mmc3.c @@ -62,6 +62,10 @@ int MMC3_getCHRBank (uint8 bank) { return bank &4? MMC3_reg[bank -2]: MMC3_reg[bank >>1] &~1 | bank &1; } +int MMC3_getMirroring (void) { + return MMC3_mirroring; +} + DECLFR(MMC3_readWRAM) { if (MMC3_wramControl &0x80 || MMC3_type == MMC3_TYPE_AX5202P || MMC3_type == MMC3_TYPE_MMC6) return MMC3_cbReadWRAM? MMC3_cbReadWRAM(A): CartBR(A); diff --git a/src/boards/asic_mmc3.h b/src/boards/asic_mmc3.h index 448f1ab..773d4f0 100644 --- a/src/boards/asic_mmc3.h +++ b/src/boards/asic_mmc3.h @@ -30,6 +30,7 @@ void MMC3_syncWRAM (int); int MMC3_getPRGBank (uint8); int MMC3_getCHRBank (uint8); +int MMC3_getMirroring (void); void MMC3_syncPRG (int, int); void MMC3_syncCHR (int, int); void MMC3_syncMirror (); diff --git a/src/boards/asic_vrc7.h b/src/boards/asic_vrc7.h index a547cf5..8320468 100644 --- a/src/boards/asic_vrc7.h +++ b/src/boards/asic_vrc7.h @@ -25,9 +25,6 @@ void VRC7_syncWRAM (int); void VRC7_syncPRG (int, int); void VRC7_syncCHR (int, int); void VRC7_syncMirror (); -int VRC7_getPRGBank (uint8); -int VRC7_getCHRBank (uint8); -int VRC7_getNTBank (uint8); DECLFR(VRC7_readWRAM); DECLFW(MMC3_writeWRAM); DECLFW(VRC7_writeReg); From da42e08e1a9258f14fb6775d7685e4263217e7d0 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Mon, 8 Sep 2025 16:25:54 +0200 Subject: [PATCH 008/109] Mapper 468: bugfixes --- src/boards/468.c | 156 ++++++++++++++++++++----------------- src/boards/asic_mmc1.c | 2 +- src/boards/asic_mmc3.c | 2 +- src/boards/asic_mmc3.h | 2 +- src/boards/asic_vrc2and4.c | 32 ++++---- src/boards/asic_vrc6.c | 10 +-- src/boards/asic_vrc7.c | 14 ++-- 7 files changed, 114 insertions(+), 104 deletions(-) diff --git a/src/boards/468.c b/src/boards/468.c index 6b5025e..eb9eb42 100644 --- a/src/boards/468.c +++ b/src/boards/468.c @@ -129,9 +129,10 @@ static void sync_FxROM (int prgOR) { static void sync_GNROM (int prgOR) { int prgAND = reg[0] &0x08? 0x01: 0x03; - int value = prgOR &0x2000 && submapper != 1? (Latch_data >>4 &0x0F | Latch_data <<4 &0xF0): Latch_data; + int value = Latch_data; + if (submapper == 1 && ~reg[0] &0x08 || submapper != 1 && prgOR &0x2000) value = Latch_data >>4 &0x0F | Latch_data <<4 &0xF0; prgOR = prgOR >>2 | reg[0] >>1 &0x02; - setprg32(0x8000, value >>0 &prgAND | prgOR &~prgAND); + setprg32(0x8000, value &prgAND | prgOR &~prgAND); setchr8(value >>4); setmirror(reg[0] &0x10? MI_H: MI_V); } @@ -144,6 +145,11 @@ static void sync_IF12 (int prgOR) { setmirror(Custom_reg[0] &0x01? MI_H: MI_V); } +static DECLFW(IF12_writeReg) { + Custom_reg[A >>14 &1] = V; + sync(); +} + static void sync_LF36 (int prgOR) { prgOR |= reg[0] &0x08; setprg8(0x8000, 0x04 | prgOR); @@ -154,6 +160,32 @@ static void sync_LF36 (int prgOR) { setmirror(reg[0] &0x04? MI_H: MI_V); } +void FP_FASTAPASS(1) LF36_cpuCycle (int a) { + while (a--) { + if (Custom_reg[1] &1) { + if (!++Custom_reg[2]) ++Custom_reg[3]; + if (Custom_reg[3] &0x10) + X6502_IRQBegin(FCEU_IQEXT); + else + X6502_IRQEnd(FCEU_IQEXT); + } else { + Custom_reg[2] = Custom_reg[3] = 0; + X6502_IRQEnd(FCEU_IQEXT); + } + } +} + +static DECLFW(LF36_writeReg) { + switch(A >>13 &3) { + case 0: case 1: + Custom_reg[1] = A >>13 &1; + break; + case 3: + Custom_reg[0] = V; + sync(); + } +} + static void sync_Misc (int prgOR) { if (reg[0] &0x02) { setprg16(0x8000, Custom_reg[2] <<1 &0x0E | reg[0] &0x01 | prgOR >>1 &~0x0F); @@ -169,12 +201,42 @@ static void sync_Misc (int prgOR) { setmirror(Custom_reg[1] &0x10? MI_1: MI_0); } +static DECLFW(Misc_writeReg) { + switch(A >>12 &7) { + case 0: case 2: case 3: + Custom_reg[0] = V; + sync(); + break; + case 1: + Custom_reg[reg[0] &0x08? 0: 1] = V; + sync(); + break; + case 6: case 7: + Custom_reg[2] = V; + sync(); + break; + } +} + static void sync_Nanjing (int prgOR) { setprg32(0x8000, Custom_reg[2] <<4 &0x30 | Custom_reg[0] &0x0F | (Custom_reg[3] &0x04? 0x00: 0x03) | prgOR >>2); setchr8(0); setmirror(reg[0] &0x04? MI_H: MI_V); } +static void Nanjing_scanline (void) { + if (Custom_reg[0] &0x80 && scanline <239) { + setchr4(0x0000, scanline >= 127? 1: 0); + setchr4(0x1000, scanline >= 127? 1: 0); + } else + setchr8(0); +} + +static DECLFW(Nanjing_writeReg) { + Custom_reg[A >>8 &3] = V; + sync(); +} + static void sync_PNROM (int prgOR) { MMC24_syncWRAM(0); MMC2_syncPRG(0x0F, prgOR &~0x0F); @@ -197,6 +259,10 @@ static void sync_SUROM (int prgOR) { MMC1_syncMirror(); } +static int SUROM_getPRGBank(uint8 bank) { + return MMC1_getPRGBank(bank) | MMC1_getCHRBank(0) &0x10; +} + static void sync_TxROM (int prgOR) { int prgAND = reg[0] &0x08? (reg[0] &0x04? (reg[0] &0x02? (reg[2] &0x02? 0x07: 0x0F): 0x1F): 0x3F): 0x7F; prgOR |= reg[2] &0x01? 0x0C: 0x00; @@ -229,7 +295,7 @@ static void sync_TxSROM (int prgOR) { } static void sync_UxROM (int prgOR) { - int prgAND = reg[0] &0x02? 0x07: 0x0F; + int prgAND = reg[0] &0x02? 0x07: submapper == 1 && ~reg[0] &0x04? 0x1F: 0x0F; setprg16(0x8000, Latch_data &prgAND | prgOR >>1 &~prgAND); setprg16(0xC000, prgOR >>1 | prgAND); setchr8(0); @@ -277,76 +343,10 @@ static void sync_VRC7 (int prgOR) { int prgAND = reg[0] &0x08? (reg[0] &0x04? (reg[0] &0x02? 0x0F: 0x1F): 0x3F): 0x7F; VRC7_syncWRAM(0); VRC7_syncPRG(prgAND, prgOR &~prgAND); - VRC7_syncCHR(0xFF, 0x00); + VRC7_syncCHR(reg[0] &0x10? 0xFF: 0x7F, 0x00); VRC7_syncMirror(); } -/* Mapper callbacks and handlers */ -static int SUROM_getPRGBank(uint8 bank) { - return MMC1_getPRGBank(bank) | MMC1_getCHRBank(0) &0x10; -} - -static DECLFW(IF12_writeReg) { - Custom_reg[A >>14 &1] = V; - sync(); -} - -void FP_FASTAPASS(1) LF36_cpuCycle (int a) { - while (a--) { - if (Custom_reg[1] &1) { - if (!++Custom_reg[2]) ++Custom_reg[3]; - if (Custom_reg[3] &0x10) - X6502_IRQBegin(FCEU_IQEXT); - else - X6502_IRQEnd(FCEU_IQEXT); - } else { - Custom_reg[2] = Custom_reg[3] = 0; - X6502_IRQEnd(FCEU_IQEXT); - } - } -} - -static DECLFW(LF36_writeReg) { - switch(A >>13 &3) { - case 0: case 1: - Custom_reg[1] = A >>13 &1; - break; - case 3: - Custom_reg[0] = V; - sync(); - } -} - -static DECLFW(Misc_writeReg) { - switch(A >>12 &7) { - case 0: case 2: case 3: - Custom_reg[0] = V; - sync(); - break; - case 1: - Custom_reg[1] = V; - sync(); - break; - case 6: case 7: - Custom_reg[2] = V; - sync(); - break; - } -} - -static void Nanjing_scanline (void) { - if (Custom_reg[0] &0x80 && scanline <239) { - setchr4(0x0000, scanline >= 127? 1: 0); - setchr4(0x1000, scanline >= 127? 1: 0); - } else - setchr8(0); -} - -static DECLFW(Nanjing_writeReg) { - Custom_reg[A >>8 &3] = V; - sync(); -} - /* Supervisor */ static DECLFR(readReg) { switch(A) { @@ -381,6 +381,7 @@ static DECLFW(writeReg) { } static void applyMode (uint8 clear) { + uint8 previousMirroring; MapIRQHook = NULL; PPU_hook = NULL; GameHBIRQHook = NULL; @@ -404,11 +405,15 @@ static void applyMode (uint8 clear) { case 0x005: case 0x105: mapperSync = sync_Misc; /* NROM, CNROM, Fire Hawk */ SetWriteHandler(0x8000, 0xFFFF, Misc_writeReg); + if (clear) Custom_reg[0] = Custom_reg[1] = Custom_reg[2] = Custom_reg[3] = 0; + sync(); break; case 0x007: mapperSync = sync_LF36; /* SMB2J */ MapIRQHook = LF36_cpuCycle; SetWriteHandler(0x8000, 0xFFFF, LF36_writeReg); + if (clear) Custom_reg[0] = Custom_reg[1] = Custom_reg[2] = Custom_reg[3] = 0; + sync(); break; case 0x008: mapperSync = sync_FxROM; @@ -421,6 +426,8 @@ static void applyMode (uint8 clear) { } else { mapperSync = sync_IF12; /* Not Irem's actual IF-12 mapper, but something custom by BlazePro */ SetWriteHandler(0x8000, 0xFFFF, IF12_writeReg); + if (clear) Custom_reg[0] = Custom_reg[1] = Custom_reg[2] = Custom_reg[3] = 0; + sync(); } break; case 0x00A: @@ -436,13 +443,17 @@ static void applyMode (uint8 clear) { Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); break; case 0x00E: case 0x10E: - mapperSync = sync_Nanjing; /* Partial emulation only */ + mapperSync = sync_Nanjing; GameHBIRQHook = Nanjing_scanline; SetWriteHandler(0x5000, 0x53FF, Nanjing_writeReg); + if (clear) Custom_reg[0] = Custom_reg[1] = Custom_reg[2] = Custom_reg[3] = 0; + sync(); break; case 0x100: case 0x101: mapperSync = sync_TxROM; + previousMirroring = MMC3_getMirroring(); MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, NULL); + MMC3_writeReg(0xA000, previousMirroring); break; case 0x102: mapperSync = sync_TxSROM; @@ -464,7 +475,7 @@ static void applyMode (uint8 clear) { mapperSync = sync_VRC24; VRC4_activate(clear, sync, 0x0A, 0x05, 1, NULL, NULL, NULL, NULL, NULL); break; - case 0x300: + case 0x300: case 0x301: mapperSync = sync_VRC6; VRC6_activate(clear, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); break; @@ -494,7 +505,6 @@ static void power() { reg[1] = 0xFF; reg[2] = submapper == 1? 0x10: 0x00; reg[3] = 0x00; - Custom_reg[0] = Custom_reg[1] = Custom_reg[2] = Custom_reg[3] = 0; eep_clock = command = output = 1; command = state = 0; applyMode(1); diff --git a/src/boards/asic_mmc1.c b/src/boards/asic_mmc1.c index 3093cbd..ca3eb69 100644 --- a/src/boards/asic_mmc1.c +++ b/src/boards/asic_mmc1.c @@ -116,7 +116,7 @@ DECLFW(MMC1_writeReg) { } static void MMC1_clear() { - MMC1_reg[0] = 0x0C; MMC1_reg[1] = 0; MMC1_reg[2] = 2; MMC1_reg[3] = 0; + MMC1_reg[0] = 0x0C; MMC1_reg[1] = 0; MMC1_reg[2] = 0; MMC1_reg[3] = 0; /* "Bad News Baseball" is sensitive to the initial CHR bank register content. 0/0 seems to work. */ MMC1_bits = 0; MMC1_shift = 0; MMC1_filter = 0; MMC1_cbSync(); } diff --git a/src/boards/asic_mmc3.c b/src/boards/asic_mmc3.c index fea628a..3786dba 100644 --- a/src/boards/asic_mmc3.c +++ b/src/boards/asic_mmc3.c @@ -62,7 +62,7 @@ int MMC3_getCHRBank (uint8 bank) { return bank &4? MMC3_reg[bank -2]: MMC3_reg[bank >>1] &~1 | bank &1; } -int MMC3_getMirroring (void) { +uint8 MMC3_getMirroring (void) { return MMC3_mirroring; } diff --git a/src/boards/asic_mmc3.h b/src/boards/asic_mmc3.h index 773d4f0..210940d 100644 --- a/src/boards/asic_mmc3.h +++ b/src/boards/asic_mmc3.h @@ -30,7 +30,7 @@ void MMC3_syncWRAM (int); int MMC3_getPRGBank (uint8); int MMC3_getCHRBank (uint8); -int MMC3_getMirroring (void); +uint8 MMC3_getMirroring (void); void MMC3_syncPRG (int, int); void MMC3_syncCHR (int, int); void MMC3_syncMirror (); diff --git a/src/boards/asic_vrc2and4.c b/src/boards/asic_vrc2and4.c index c2e1d3d..16166bf 100644 --- a/src/boards/asic_vrc2and4.c +++ b/src/boards/asic_vrc2and4.c @@ -42,29 +42,29 @@ static uint8 VRC4_count; static signed short int VRC4_cycles; static SFORMAT VRC24_stateRegs[] = { - { VRC24_prg, 2, "PREG" }, - { &VRC24_chr[0], 2 | FCEUSTATE_RLSB, "CRH0" }, - { &VRC24_chr[1], 2 | FCEUSTATE_RLSB, "CRH1" }, - { &VRC24_chr[2], 2 | FCEUSTATE_RLSB, "CRH2" }, - { &VRC24_chr[3], 2 | FCEUSTATE_RLSB, "CRH3" }, - { &VRC24_chr[4], 2 | FCEUSTATE_RLSB, "CRH4" }, - { &VRC24_chr[5], 2 | FCEUSTATE_RLSB, "CRH5" }, - { &VRC24_chr[6], 2 | FCEUSTATE_RLSB, "CRH6" }, - { &VRC24_chr[7], 2 | FCEUSTATE_RLSB, "CRH7" }, - { &VRC24_mirroring, 1, "MIRR" }, - { &VRC24_misc, 1, "MISC" }, + { VRC24_prg, 2, "VC2P" }, + { &VRC24_chr[0], 2 | FCEUSTATE_RLSB, "V2C0" }, + { &VRC24_chr[1], 2 | FCEUSTATE_RLSB, "V2C1" }, + { &VRC24_chr[2], 2 | FCEUSTATE_RLSB, "V2C2" }, + { &VRC24_chr[3], 2 | FCEUSTATE_RLSB, "V2C3" }, + { &VRC24_chr[4], 2 | FCEUSTATE_RLSB, "V2C4" }, + { &VRC24_chr[5], 2 | FCEUSTATE_RLSB, "V2C5" }, + { &VRC24_chr[6], 2 | FCEUSTATE_RLSB, "V2C6" }, + { &VRC24_chr[7], 2 | FCEUSTATE_RLSB, "V2C7" }, + { &VRC24_mirroring, 1, "VC2N" }, + { &VRC24_misc, 1, "VC4M" }, { 0 } }; static SFORMAT VRC2_stateRegs[] = { - { &VRC2_pins, 1, "PINS" }, + { &VRC2_pins, 1, "VC2E" }, }; static SFORMAT VRC4_stateRegs[] = { - { &VRC4_latch, 1, "LATC" }, - { &VRC4_mode, 1, "MODE" }, - { &VRC4_count, 1, "COUN" }, - { &VRC4_cycles, 2 | FCEUSTATE_RLSB, "CYCL" }, + { &VRC4_latch, 1, "V4LT" }, + { &VRC4_mode, 1, "V4MO" }, + { &VRC4_count, 1, "V4CT" }, + { &VRC4_cycles, 2 | FCEUSTATE_RLSB, "V4CY" }, { 0 } }; diff --git a/src/boards/asic_vrc6.c b/src/boards/asic_vrc6.c index 6c7d517..95df036 100644 --- a/src/boards/asic_vrc6.c +++ b/src/boards/asic_vrc6.c @@ -38,12 +38,12 @@ static signed short int VRC6_cycles; static SFORMAT VRC6_stateRegs[] = { { VRC6_prg, 2, "VC6P" }, - { VRC6_chr, 6, "VC6C" }, + { VRC6_chr, 8, "VC6C" }, { &VRC6_misc, 1, "VC6M" }, - { &VRC6_latch, 1, "LATC" }, - { &VRC6_mode, 1, "MODE" }, - { &VRC6_count, 1, "COUN" }, - { &VRC6_cycles, 2 | FCEUSTATE_RLSB, "CYCL" }, + { &VRC6_latch, 1, "V6LT" }, + { &VRC6_mode, 1, "V6MO" }, + { &VRC6_count, 1, "V6CT" }, + { &VRC6_cycles, 2 | FCEUSTATE_RLSB, "V6CY" }, { 0 } }; diff --git a/src/boards/asic_vrc7.c b/src/boards/asic_vrc7.c index 0777e5f..7c31f02 100644 --- a/src/boards/asic_vrc7.c +++ b/src/boards/asic_vrc7.c @@ -33,13 +33,13 @@ static uint8 VRC7_count; static signed short int VRC7_cycles; static SFORMAT VRC7_stateRegs[] = { - { VRC7_prg, 3, "VC6P" }, - { VRC7_chr, 6, "VC6C" }, - { &VRC7_misc, 1, "VC6M" }, - { &VRC7_latch, 1, "LATC" }, - { &VRC7_mode, 1, "MODE" }, - { &VRC7_count, 1, "COUN" }, - { &VRC7_cycles, 2 | FCEUSTATE_RLSB, "CYCL" }, + { VRC7_prg, 3, "VC7P" }, + { VRC7_chr, 8, "VC7C" }, + { &VRC7_misc, 1, "VC7M" }, + { &VRC7_latch, 1, "V7LT" }, + { &VRC7_mode, 1, "V7MO" }, + { &VRC7_count, 1, "V7CT" }, + { &VRC7_cycles, 2 | FCEUSTATE_RLSB, "V7CY" }, { 0 } }; From 03c7199a42dcd830632bc8bcb91c55d46545f211 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Mon, 8 Sep 2025 16:37:15 +0200 Subject: [PATCH 009/109] Mapper 314: Add support for 4 MiB variant. --- src/boards/bmc64in1nr.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/boards/bmc64in1nr.c b/src/boards/bmc64in1nr.c index 8a6cdb5..86d2abe 100644 --- a/src/boards/bmc64in1nr.c +++ b/src/boards/bmc64in1nr.c @@ -31,17 +31,17 @@ static SFORMAT StateRegs[] = }; static void Sync(void) { + int prg = regs[0] <<7 &0x80 | regs[1] <<1 &0x7E | regs[1] >>6 &0x01; if (regs[0] & 0x80) { /* NROM mode */ if (regs[1] & 0x80) - setprg32(0x8000, regs[1] & 0x3F); + setprg32(0x8000, prg >>1); else { - int bank = ((regs[1] & 0x3F) << 1) | ((regs[1] >> 6) & 1); - setprg16(0x8000, bank); - setprg16(0xC000, bank); + setprg16(0x8000, prg); + setprg16(0xC000, prg); } } else { /* UNROM mode */ - setprg16(0x8000, regs[1] <<1 | regs[3] &7); - setprg16(0xC000, regs[1] <<1 | 7); + setprg16(0x8000, prg &~7 | regs[3] &7); + setprg16(0xC000, prg | 7); } if (regs[0] & 0x20) setmirror(MI_H); @@ -51,9 +51,7 @@ static void Sync(void) { } static DECLFW(BMC64in1nrWriteLo) { - A &=3; - if (A ==3) A =1; /* K-42001's "Aladdin III" */ - regs[A & 3] = V; + regs[A &(VROM_size? 3: 1)] = V; Sync(); } From 8b2d37d8c7d8c7d2b30a63afbbbb0a43266a8550 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Mon, 8 Sep 2025 16:54:21 +0200 Subject: [PATCH 010/109] Add mapper 586. --- src/boards/586.c | 37 +++++++++++++++++++++++++++++++++++++ src/boards/asic_latch.c | 3 ++- src/ines.c | 1 + src/ines.h | 1 + 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/boards/586.c diff --git a/src/boards/586.c b/src/boards/586.c new file mode 100644 index 0000000..2cf2bfc --- /dev/null +++ b/src/boards/586.c @@ -0,0 +1,37 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_address &0x08) { + setprg16(0x8000, Latch_address); + setprg16(0xC000, Latch_address); + } else + setprg32(0x8000, Latch_address >>1); + setchr8(Latch_address); + setmirror(Latch_address &0x08? MI_V: MI_H); +} + +void Mapper586_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_power; +} diff --git a/src/boards/asic_latch.c b/src/boards/asic_latch.c index 03df1d2..4eebcfd 100644 --- a/src/boards/asic_latch.c +++ b/src/boards/asic_latch.c @@ -36,7 +36,7 @@ static SFORMAT Latch_state[] = { DECLFW(Latch_write) { uint16 newAddress = A &0xFFFF; if (Latch_cbWrite) Latch_cbWrite(&newAddress, &V, CartBR(A)); - Latch_address = A; + Latch_address = newAddress; Latch_data = V; Latch_cbSync(); } @@ -48,6 +48,7 @@ static void Latch_clear () { } static void Latch_setHandlers() { + SetReadHandler(0x8000, 0xFFFF, CartBR); SetWriteHandler(Latch_from, Latch_to, Latch_write); } diff --git a/src/ines.c b/src/ines.c index f6e9c3e..547adc5 100644 --- a/src/ines.c +++ b/src/ines.c @@ -948,6 +948,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Bung Super Game Doctor", 561, Mapper561_562_Init ) INES_BOARD( "Venus Turbo Game Doctor", 562, Mapper561_562_Init ) INES_BOARD( "J-2020", 563, Mapper563_Init ) + INES_BOARD( "HN-02", 586, Mapper586_Init ) INES_BOARD_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index 832438b..0991fed 100644 --- a/src/ines.h +++ b/src/ines.h @@ -413,6 +413,7 @@ void Mapper558_Init(CartInfo *); void Mapper559_Init(CartInfo *); void Mapper561_562_Init(CartInfo *); void Mapper563_Init(CartInfo *); +void Mapper586_Init(CartInfo *); void FFE_Init(CartInfo *); From 943cccd0feb2469eb7f1b2d88d54624ccf0d1905 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Mon, 8 Sep 2025 17:05:45 +0200 Subject: [PATCH 011/109] Add mapper 579. --- src/boards/579.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 51 insertions(+) create mode 100644 src/boards/579.c diff --git a/src/boards/579.c b/src/boards/579.c new file mode 100644 index 0000000..0357e52 --- /dev/null +++ b/src/boards/579.c @@ -0,0 +1,49 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + int prg = Latch_address >>2 &0x1F; + if (Latch_address &0x200) { + setprg16(0x8000, prg); + setprg16(0xC000, prg |7); + } else { + if (Latch_address &0x001) + setprg32(0x8000, prg >>1); + else { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } + } + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], Latch_address &0x80? 0: 1); + setchr8(0); + setmirror(Latch_address &0x02? MI_H: MI_V); +} + +void protectLatchBits (uint16 *address, uint8 *newValue, uint8 romValue) { /* Once bit 9 is set, only the inner bank bits can be modified. */ + if (Latch_address &0x200) *address = *address &0x01C | Latch_address &~0x01C; +} + +void Mapper579_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, protectLatchBits); + info->Reset = Latch_power; +} diff --git a/src/ines.c b/src/ines.c index 547adc5..bd4d6ef 100644 --- a/src/ines.c +++ b/src/ines.c @@ -948,6 +948,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Bung Super Game Doctor", 561, Mapper561_562_Init ) INES_BOARD( "Venus Turbo Game Doctor", 562, Mapper561_562_Init ) INES_BOARD( "J-2020", 563, Mapper563_Init ) + INES_BOARD( "T-215", 579, Mapper579_Init ) INES_BOARD( "HN-02", 586, Mapper586_Init ) INES_BOARD_END() diff --git a/src/ines.h b/src/ines.h index 0991fed..423ba96 100644 --- a/src/ines.h +++ b/src/ines.h @@ -413,6 +413,7 @@ void Mapper558_Init(CartInfo *); void Mapper559_Init(CartInfo *); void Mapper561_562_Init(CartInfo *); void Mapper563_Init(CartInfo *); +void Mapper579_Init(CartInfo *); void Mapper586_Init(CartInfo *); void FFE_Init(CartInfo *); From 4a1c734466d96a958c632150ac96ad79edc84aff Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Mon, 8 Sep 2025 17:16:13 +0200 Subject: [PATCH 012/109] Add mappers 588 and 592. --- src/boards/588.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ src/boards/592.c | 34 ++++++++++++++++++++++++++++ src/ines.c | 2 ++ src/ines.h | 2 ++ 4 files changed, 97 insertions(+) create mode 100644 src/boards/588.c create mode 100644 src/boards/592.c diff --git a/src/boards/588.c b/src/boards/588.c new file mode 100644 index 0000000..a656607 --- /dev/null +++ b/src/boards/588.c @@ -0,0 +1,59 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[2]; + +static SFORMAT stateRegs[] = { + { ®, 2, "REGS" }, + { 0 } +}; + + +static void sync () { + setprg8(0x6000, reg[1] &0x07 |0x08); + setprg32(0x8000, reg[0] >>4 &0x07); + setchr8(reg[0] &0x0F); + setmirror(reg[0] &0x80? MI_H: MI_V); +} + +static DECLFW(writeReg) { + reg[A >>12 &1] = V; + sync(); +} + +static void power() { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0xE000, 0xFFFF, writeReg); + reg[0] = reg[1] = 0; + sync(); +} + +static void stateRestore(int version) { + sync(); +} + +void Mapper588_Init (CartInfo *info) { + info->Reset = power; + info->Power = power; + GameStateRestore = stateRestore; + AddExState(stateRegs, ~0, 0, 0); +} diff --git a/src/boards/592.c b/src/boards/592.c new file mode 100644 index 0000000..6464e04 --- /dev/null +++ b/src/boards/592.c @@ -0,0 +1,34 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + setprg16(0x8000, Latch_data); + setprg16(0xC000, Latch_data); + setchr8(Latch_data); + setmirror(Latch_data &0x08? MI_H: MI_V); +} + +void Mapper592_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_power; +} diff --git a/src/ines.c b/src/ines.c index bd4d6ef..e7f3d19 100644 --- a/src/ines.c +++ b/src/ines.c @@ -950,6 +950,8 @@ INES_BOARD_BEGIN() INES_BOARD( "J-2020", 563, Mapper563_Init ) INES_BOARD( "T-215", 579, Mapper579_Init ) INES_BOARD( "HN-02", 586, Mapper586_Init ) + INES_BOARD( "ET-81", 588, Mapper588_Init ) + INES_BOARD( "8-in-1 1991", 592, Mapper592_Init ) INES_BOARD_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index 423ba96..ebb8e70 100644 --- a/src/ines.h +++ b/src/ines.h @@ -415,6 +415,8 @@ void Mapper561_562_Init(CartInfo *); void Mapper563_Init(CartInfo *); void Mapper579_Init(CartInfo *); void Mapper586_Init(CartInfo *); +void Mapper588_Init(CartInfo *); +void Mapper592_Init(CartInfo *); void FFE_Init(CartInfo *); From 74ee38f3e3ca2247975dbd515185c482fb31f94a Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Mon, 8 Sep 2025 17:32:10 +0200 Subject: [PATCH 013/109] Mapper 435: Add solder pad setting. --- src/boards/addrlatch.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c index 2f581c3..48eb759 100644 --- a/src/boards/addrlatch.c +++ b/src/boards/addrlatch.c @@ -766,6 +766,10 @@ void Mapper409_Init(CartInfo *info) { } /*------------------ Map 435 ---------------------------*/ +static DECLFR(ReadOB) { + return X.DB; +} + static void M435Sync(void) { int p =latche >>2 &0x1F | latche >>3 &0x20 | latche >>4 &0x40; if (latche &0x200) { @@ -787,10 +791,27 @@ static void M435Sync(void) { setmirror(latche &0x002? MI_H: MI_V); setchr8(0); + SetReadHandler(0x8000, 0xFFFF, ~latche &0x200 && latche &(submapper == 1? 0x001: 0x400) && dipswitch &1? ReadOB: CartBR); +} + +void Mapper435_Power() { + LatchPower(); + dipswitch = 0; + M435Sync(); +} + +void Mapper435_Reset() { + latche = 0; + dipswitch++; + M435Sync(); } void Mapper435_Init(CartInfo *info) { + submapper = info->submapper; Latch_Init(info, M435Sync, NULL, 0x0000, 0x8000, 0xFFFF, 1); + info->Power = Mapper435_Power; + info->Reset = Mapper435_Reset; + AddExState(&dipswitch, 1, 0, "DIPSW"); } /*------------------ Map 459 ---------------------------*/ From 4c697c7909c7a831116687ce9dab394ea1d5cbde Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Mon, 8 Sep 2025 17:40:34 +0200 Subject: [PATCH 014/109] Add mapper 590. --- src/boards/590.c | 37 +++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 39 insertions(+) create mode 100644 src/boards/590.c diff --git a/src/boards/590.c b/src/boards/590.c new file mode 100644 index 0000000..e77b6dd --- /dev/null +++ b/src/boards/590.c @@ -0,0 +1,37 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_data &0x08) + setprg32(0x8000, Latch_data >>1); + else { + setprg16(0x8000, Latch_data); + setprg16(0xC000, Latch_data); + } + setchr8(Latch_data); +} + +void Mapper590_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_power; +} diff --git a/src/ines.c b/src/ines.c index e7f3d19..4414a18 100644 --- a/src/ines.c +++ b/src/ines.c @@ -951,6 +951,7 @@ INES_BOARD_BEGIN() INES_BOARD( "T-215", 579, Mapper579_Init ) INES_BOARD( "HN-02", 586, Mapper586_Init ) INES_BOARD( "ET-81", 588, Mapper588_Init ) + INES_BOARD( "810430", 590, Mapper590_Init ) INES_BOARD( "8-in-1 1991", 592, Mapper592_Init ) INES_BOARD_END() diff --git a/src/ines.h b/src/ines.h index ebb8e70..7982645 100644 --- a/src/ines.h +++ b/src/ines.h @@ -416,6 +416,7 @@ void Mapper563_Init(CartInfo *); void Mapper579_Init(CartInfo *); void Mapper586_Init(CartInfo *); void Mapper588_Init(CartInfo *); +void Mapper590_Init(CartInfo *); void Mapper592_Init(CartInfo *); void FFE_Init(CartInfo *); From 92b64e5e0605f0c6dc5eb03b285ea753457e3ff1 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Mon, 8 Sep 2025 18:15:39 +0200 Subject: [PATCH 015/109] Add mapper 581. --- src/boards/579.c | 6 +++--- src/boards/581.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 4 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 src/boards/581.c diff --git a/src/boards/579.c b/src/boards/579.c index 0357e52..8490691 100644 --- a/src/boards/579.c +++ b/src/boards/579.c @@ -39,11 +39,11 @@ static void sync () { setmirror(Latch_address &0x02? MI_H: MI_V); } -void protectLatchBits (uint16 *address, uint8 *newValue, uint8 romValue) { /* Once bit 9 is set, only the inner bank bits can be modified. */ - if (Latch_address &0x200) *address = *address &0x01C | Latch_address &~0x01C; +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { /* Once bit 9 is set, only the inner bank bits can be modified. */ + if (Latch_address &0x200) *newAddress = *newAddress &0x01C | Latch_address &~0x01C; } void Mapper579_Init (CartInfo *info) { - Latch_init(info, sync, 0x8000, 0xFFFF, protectLatchBits); + Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); info->Reset = Latch_power; } diff --git a/src/boards/581.c b/src/boards/581.c new file mode 100644 index 0000000..2435623 --- /dev/null +++ b/src/boards/581.c @@ -0,0 +1,51 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + int prg = Latch_address >>1 &0x20 | Latch_address &0x1F; + if (Latch_address &0x20) { + if (Latch_address &0x01) { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } else + setprg32(0x8000, prg >>1); + } else { + setprg16(0x8000, prg); + setprg16(0xC000, prg |7); + } + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], Latch_address &0x20? 0: 1); + setchr8(0); + setmirror(Latch_address &0x80? MI_H: MI_V); +} + +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { /* The upper bits are only writable on a falling edge of A5. */ + if (Latch_address &0x20 && !(*newAddress &0x20)) + ; + else + *newAddress = *newAddress &~0xC0 | Latch_address &0xC0; +} + +void Mapper581_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); + info->Reset = Latch_power; +} diff --git a/src/ines.c b/src/ines.c index 4414a18..2c1b2e0 100644 --- a/src/ines.c +++ b/src/ines.c @@ -949,6 +949,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Venus Turbo Game Doctor", 562, Mapper561_562_Init ) INES_BOARD( "J-2020", 563, Mapper563_Init ) INES_BOARD( "T-215", 579, Mapper579_Init ) + INES_BOARD( "ET-82", 581, Mapper581_Init ) INES_BOARD( "HN-02", 586, Mapper586_Init ) INES_BOARD( "ET-81", 588, Mapper588_Init ) INES_BOARD( "810430", 590, Mapper590_Init ) diff --git a/src/ines.h b/src/ines.h index 7982645..dc04179 100644 --- a/src/ines.h +++ b/src/ines.h @@ -414,6 +414,7 @@ void Mapper559_Init(CartInfo *); void Mapper561_562_Init(CartInfo *); void Mapper563_Init(CartInfo *); void Mapper579_Init(CartInfo *); +void Mapper581_Init(CartInfo *); void Mapper586_Init(CartInfo *); void Mapper588_Init(CartInfo *); void Mapper590_Init(CartInfo *); From 20ef307ee57c4dbabec400644bae35e7e05237bf Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Mon, 8 Sep 2025 18:31:06 +0200 Subject: [PATCH 016/109] Mapper 380: Correct solder pad menu selection. --- src/boards/380.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boards/380.c b/src/boards/380.c index f14ac63..2b53fb1 100644 --- a/src/boards/380.c +++ b/src/boards/380.c @@ -57,7 +57,7 @@ static void Sync(void) static DECLFR(M380Read) { if (latche & 0x100 && !isKN35A) - return CartBR(A | dipswitch); + return CartBR(A &~0x0F | dipswitch); return CartBR(A); } From 5a1cabfda836f8499ae307b83cd402d224be8994 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Mon, 8 Sep 2025 23:09:14 +0200 Subject: [PATCH 017/109] Add mapper 503. --- src/boards/503.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 69 insertions(+) create mode 100644 src/boards/503.c diff --git a/src/boards/503.c b/src/boards/503.c new file mode 100644 index 0000000..83bc127 --- /dev/null +++ b/src/boards/503.c @@ -0,0 +1,67 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; +static uint8 pad; + +static DECLFR(readPad) { + return CartBR(A &~3 | pad &3); +} + +static void sync() { + if (reg &0x10) + setprg32(0x8000, reg >>1); + else { + setprg16(0x8000, reg); + setprg16(0xC000, reg); + } + MMC3_syncCHR(0x7F, reg <<4 &~0x7F); + MMC3_syncMirror(); + SetReadHandler(0x8000, 0xFFFF, reg &0x20? readPad: CartBR); +} + +static DECLFW(writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset() { + reg = 0; + ++pad; + sync(); +} + +static void power() { + reg = 0; + pad = 0; + MMC3_power(); +} + +void Mapper503_Init(CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/ines.c b/src/ines.c index 2c1b2e0..93faa2c 100644 --- a/src/ines.c +++ b/src/ines.c @@ -912,6 +912,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Yhc-000", 500, Mapper500_Init ) INES_BOARD( "Yhc-001", 501, Mapper501_Init ) INES_BOARD( "Yhc-002", 502, Mapper502_Init ) + INES_BOARD( "ET-170", 503, Mapper503_Init ) INES_BOARD( "SA-9602B", 513, SA9602B_Init ) INES_BOARD( "Brilliant Com Cocoma Pack",516, Mapper516_Init ) INES_BOARD( "DANCE2000", 518, UNLD2000_Init ) diff --git a/src/ines.h b/src/ines.h index dc04179..c16b741 100644 --- a/src/ines.h +++ b/src/ines.h @@ -391,6 +391,7 @@ void Mapper488_Init(CartInfo *); void Mapper500_Init(CartInfo *); void Mapper501_Init(CartInfo *); void Mapper502_Init(CartInfo *); +void Mapper503_Init(CartInfo *); void Mapper516_Init(CartInfo *); void Mapper520_Init(CartInfo *); void Mapper523_Init(CartInfo *); From 2c0c3c1876be55141032d218b464d4192251e3c5 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Mon, 8 Sep 2025 23:14:17 +0200 Subject: [PATCH 018/109] Add mapper 504. --- src/boards/432.c | 2 +- src/boards/504.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 src/boards/504.c diff --git a/src/boards/432.c b/src/boards/432.c index dadf0d4..002718d 100644 --- a/src/boards/432.c +++ b/src/boards/432.c @@ -45,7 +45,7 @@ static void sync() { static int getPRGBank(uint8 bank) { if (reg[1] &0x40) { int mask = reg[1] &(submapper == 2? 0x20: 0x80)? 3: 1; - return MMC3_getPRGBank(bank & 1) &~mask | bank &mask; + return MMC3_getPRGBank(bank &1) &~mask | bank &mask; } else return MMC3_getPRGBank(bank); } diff --git a/src/boards/504.c b/src/boards/504.c new file mode 100644 index 0000000..1d4b777 --- /dev/null +++ b/src/boards/504.c @@ -0,0 +1,65 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync() { + int prgAND = reg &0x02? 0x0F: 0x1F; + int chrAND = reg &0x02? 0x7F: 0xFF; + int prgOR = reg <<4; + int chrOR = reg <<7; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static int getPRGBank(uint8 bank) { + if ((reg &0x03) == 0x03 && ~reg &0x08) + return MMC3_getPRGBank(bank &1) &~1 | bank &1; + else + return MMC3_getPRGBank(bank); +} + +static DECLFW(writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset() { + reg = 0; + sync(); +} + +static void power() { + reg = 0; + MMC3_power(); +} + +void Mapper504_Init(CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, getPRGBank, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/ines.c b/src/ines.c index 93faa2c..77957e7 100644 --- a/src/ines.c +++ b/src/ines.c @@ -913,6 +913,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Yhc-001", 501, Mapper501_Init ) INES_BOARD( "Yhc-002", 502, Mapper502_Init ) INES_BOARD( "ET-170", 503, Mapper503_Init ) + INES_BOARD( "K-3054", 504, Mapper504_Init ) INES_BOARD( "SA-9602B", 513, SA9602B_Init ) INES_BOARD( "Brilliant Com Cocoma Pack",516, Mapper516_Init ) INES_BOARD( "DANCE2000", 518, UNLD2000_Init ) diff --git a/src/ines.h b/src/ines.h index c16b741..a8e4590 100644 --- a/src/ines.h +++ b/src/ines.h @@ -392,6 +392,7 @@ void Mapper500_Init(CartInfo *); void Mapper501_Init(CartInfo *); void Mapper502_Init(CartInfo *); void Mapper503_Init(CartInfo *); +void Mapper504_Init(CartInfo *); void Mapper516_Init(CartInfo *); void Mapper520_Init(CartInfo *); void Mapper523_Init(CartInfo *); From 4d48988cf4226670629472a8d1440c77b384e525 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Mon, 8 Sep 2025 23:32:43 +0200 Subject: [PATCH 019/109] Add mappers 589 and 591. --- src/boards/581.c | 7 ++----- src/boards/588.c | 8 +------- src/boards/589.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/boards/591.c | 38 ++++++++++++++++++++++++++++++++++++++ src/ines.c | 2 ++ src/ines.h | 2 ++ 6 files changed, 88 insertions(+), 12 deletions(-) create mode 100644 src/boards/589.c create mode 100644 src/boards/591.c diff --git a/src/boards/581.c b/src/boards/581.c index 2435623..54dbce4 100644 --- a/src/boards/581.c +++ b/src/boards/581.c @@ -38,11 +38,8 @@ static void sync () { setmirror(Latch_address &0x80? MI_H: MI_V); } -static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { /* The upper bits are only writable on a falling edge of A5. */ - if (Latch_address &0x20 && !(*newAddress &0x20)) - ; - else - *newAddress = *newAddress &~0xC0 | Latch_address &0xC0; +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { /* The upper two address bits are only updated on a falling edge of A5. */ + if (!(Latch_address &0x20 && ~*newAddress &0x20)) *newAddress = *newAddress &~0xC0 | Latch_address &0xC0; } void Mapper581_Init (CartInfo *info) { diff --git a/src/boards/588.c b/src/boards/588.c index a656607..4021269 100644 --- a/src/boards/588.c +++ b/src/boards/588.c @@ -22,12 +22,6 @@ static uint8 reg[2]; -static SFORMAT stateRegs[] = { - { ®, 2, "REGS" }, - { 0 } -}; - - static void sync () { setprg8(0x6000, reg[1] &0x07 |0x08); setprg32(0x8000, reg[0] >>4 &0x07); @@ -55,5 +49,5 @@ void Mapper588_Init (CartInfo *info) { info->Reset = power; info->Power = power; GameStateRestore = stateRestore; - AddExState(stateRegs, ~0, 0, 0); + AddExState(reg, 2, 0, "REGS"); } diff --git a/src/boards/589.c b/src/boards/589.c new file mode 100644 index 0000000..a613f08 --- /dev/null +++ b/src/boards/589.c @@ -0,0 +1,43 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_address &0x20) { /* First chip: 256 KiB */ + setprg16(0x8000, Latch_address >>1 &0x08 | Latch_data &0x07); + setprg16(0xC000, Latch_address >>1 &0x08 | 0x07); + } else { /* Second chip: 128 KiB (boot) */ + setprg16(0x8000, 0x10 | Latch_address >>1 &0x07); + setprg16(0xC000, 0x10 | Latch_address >>1 &0x07); + } + setchr8(0); + setmirror(Latch_address &1? MI_H: MI_V); +} + +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { /* The address bits are only updated on a falling edge of D3. */ + if (!(Latch_data &0x08 && ~*newValue &0x08)) *newAddress = Latch_address; +} + +void Mapper589_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); + info->Reset = Latch_power; +} diff --git a/src/boards/591.c b/src/boards/591.c new file mode 100644 index 0000000..d2f3ad1 --- /dev/null +++ b/src/boards/591.c @@ -0,0 +1,38 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if ((Latch_address &0x0C) == 0x0C) + setprg32(0x8000, Latch_address >>2); + else { + setprg16(0x8000, Latch_address >>1); + setprg16(0xC000, Latch_address >>1); + } + setchr8(Latch_address); + setmirror(Latch_address &0x08? MI_V: MI_H); +} + +void Mapper591_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_power; +} diff --git a/src/ines.c b/src/ines.c index 77957e7..139f2aa 100644 --- a/src/ines.c +++ b/src/ines.c @@ -954,7 +954,9 @@ INES_BOARD_BEGIN() INES_BOARD( "ET-82", 581, Mapper581_Init ) INES_BOARD( "HN-02", 586, Mapper586_Init ) INES_BOARD( "ET-81", 588, Mapper588_Init ) + INES_BOARD( "810706", 589, Mapper589_Init ) INES_BOARD( "810430", 590, Mapper590_Init ) + INES_BOARD( "07027/810543", 591, Mapper591_Init ) INES_BOARD( "8-in-1 1991", 592, Mapper592_Init ) INES_BOARD_END() diff --git a/src/ines.h b/src/ines.h index a8e4590..842b4c5 100644 --- a/src/ines.h +++ b/src/ines.h @@ -419,7 +419,9 @@ void Mapper579_Init(CartInfo *); void Mapper581_Init(CartInfo *); void Mapper586_Init(CartInfo *); void Mapper588_Init(CartInfo *); +void Mapper589_Init(CartInfo *); void Mapper590_Init(CartInfo *); +void Mapper591_Init(CartInfo *); void Mapper592_Init(CartInfo *); void FFE_Init(CartInfo *); From a08ae1ad0a2891e36f439afe5cdd7b078402a077 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Mon, 8 Sep 2025 23:48:54 +0200 Subject: [PATCH 020/109] Mapper 178: added submapper 3, which is a variant having a solder pad for menu selection. --- src/boards/178.c | 46 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/src/boards/178.c b/src/boards/178.c index 87187cc..60fedf8 100644 --- a/src/boards/178.c +++ b/src/boards/178.c @@ -27,7 +27,9 @@ #include "mapinc.h" +static uint8 submapper; static uint8 reg[4]; +static uint8 pad[2]; static uint8 *WRAM = NULL; static uint32 WRAMSIZE; @@ -79,6 +81,10 @@ static uint8 decode(uint8 code) { return (acc >> 8) & 0xff; } +static DECLFR(readPad) { + return CartBR(A &~3 | pad[1] &3); +} + static void M178Sync(void) { uint32 sbank = reg[1] & 0x7; uint32 bbank = reg[2]; @@ -100,6 +106,7 @@ static void M178Sync(void) { } setmirror((reg[0] & 1) ^ 1); + if (submapper == 3) SetReadHandler(0x8000, 0xffff, pad[0] &1? readPad: CartBR); } static void M551Sync(void) { @@ -152,6 +159,11 @@ static DECLFR(M178ReadSnd) { return X.DB; } +static DECLFW(writePad) { + pad[0] = V; + M178Sync(); +} + static void M551Power(void) { reg[0] = reg[1] = reg[2] = reg[3] = 0; M551Sync(); @@ -159,9 +171,9 @@ static void M551Power(void) { SetWriteHandler(0x4800, 0x4fff, M551Write); SetWriteHandler(0x5800, 0x5fff, M178WriteSnd); SetReadHandler(0x5800, 0x5fff, M178ReadSnd); + SetReadHandler(0x8000, 0xffff, CartBR); SetReadHandler(0x6000, 0x7fff, CartBR); SetWriteHandler(0x6000, 0x7fff, CartBW); - SetReadHandler(0x8000, 0xffff, CartBR); FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); } @@ -172,10 +184,15 @@ static void M178Power(void) { SetWriteHandler(0x4800, 0x4fff, M178Write); SetWriteHandler(0x5800, 0x5fff, M178WriteSnd); SetReadHandler(0x5800, 0x5fff, M178ReadSnd); - SetReadHandler(0x6000, 0x7fff, CartBR); - SetWriteHandler(0x6000, 0x7fff, CartBW); SetReadHandler(0x8000, 0xffff, CartBR); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + if (submapper == 3) + SetWriteHandler(0x6000, 0x7fff, writePad); + else { + SetReadHandler(0x6000, 0x7fff, CartBR); + SetWriteHandler(0x6000, 0x7fff, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + } + pad[0] = pad[1] = 0; } static void M551Reset(void) { @@ -189,6 +206,8 @@ static void M178Reset(void) /* Always reset to menu */ reg[0] = reg[1] = reg[2] = reg[3] = 0; M178Sync(); + pad[0] = 0; + pad[1]++; } static void M178SndClk(int a) @@ -217,6 +236,7 @@ static void M178StateRestore(int version) { } void Mapper178_Init(CartInfo *info) { + submapper = info->submapper; info->Power = M178Power; info->Reset = M178Reset; info->Close = M178Close; @@ -225,14 +245,18 @@ void Mapper178_Init(CartInfo *info) { jedi_table_init(); - WRAMSIZE = 32768; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; + if (submapper == 3) + AddExState(pad, 2, 0, "DIPS"); + else { + WRAMSIZE = 32768; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); } - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); AddExState(&StateRegs, ~0, 0, 0); From fc816dacf7b9cbf04aab0b696e3089a0b4ae3243 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 00:00:23 +0200 Subject: [PATCH 021/109] Add mapper 567. --- src/boards/567.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 73 insertions(+) create mode 100644 src/boards/567.c diff --git a/src/boards/567.c b/src/boards/567.c new file mode 100644 index 0000000..e62cd33 --- /dev/null +++ b/src/boards/567.c @@ -0,0 +1,71 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync() { + MMC3_syncPRG(0x0F, reg <<4); + if (reg == 0x0F) + MMC3_syncCHR(0x1FF, 0x400); + else + MMC3_syncCHR(0x07F, reg <<7 &0x380); + MMC3_syncMirror(); +} + +static int getPRGBank(uint8 bank) { + if (reg == 0x08) { + return MMC3_getPRGBank(bank &1) &~3 | bank &3; + } else + return MMC3_getPRGBank(bank); +} + +static int getCHRBank(uint8 bank) { + if (reg == 0x0F) + return MMC3_getCHRBank(bank &6 | bank >>1 &1) <<1 | bank &1; + else + return MMC3_getCHRBank(bank); +} + +static DECLFW(writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset() { + reg = 0; + sync(); +} + +static void power() { + reg = 0; + MMC3_power(); +} + +void Mapper567_Init(CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_SHARP, getPRGBank, getCHRBank, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/ines.c b/src/ines.c index 139f2aa..918a36c 100644 --- a/src/ines.c +++ b/src/ines.c @@ -950,6 +950,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Bung Super Game Doctor", 561, Mapper561_562_Init ) INES_BOARD( "Venus Turbo Game Doctor", 562, Mapper561_562_Init ) INES_BOARD( "J-2020", 563, Mapper563_Init ) + INES_BOARD( "Top Ten Variety (SF III)", 567, Mapper567_Init ) INES_BOARD( "T-215", 579, Mapper579_Init ) INES_BOARD( "ET-82", 581, Mapper581_Init ) INES_BOARD( "HN-02", 586, Mapper586_Init ) diff --git a/src/ines.h b/src/ines.h index 842b4c5..10e5854 100644 --- a/src/ines.h +++ b/src/ines.h @@ -415,6 +415,7 @@ void Mapper558_Init(CartInfo *); void Mapper559_Init(CartInfo *); void Mapper561_562_Init(CartInfo *); void Mapper563_Init(CartInfo *); +void Mapper567_Init(CartInfo *); void Mapper579_Init(CartInfo *); void Mapper581_Init(CartInfo *); void Mapper586_Init(CartInfo *); From 297e4f58649bfccffdbe685b18cda43f112b4839 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 00:07:49 +0200 Subject: [PATCH 022/109] Add mapper 573. --- src/boards/573.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 50 insertions(+) create mode 100644 src/boards/573.c diff --git a/src/boards/573.c b/src/boards/573.c new file mode 100644 index 0000000..c49243d --- /dev/null +++ b/src/boards/573.c @@ -0,0 +1,48 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static DECLFR(readOB) { + return X.DB; +} + +static void sync () { + if (Latch_address &0x02) { + setprg16(0x8000, Latch_address <<3 &0x10 | Latch_data &0x0F); + setprg16(0xC000, Latch_address <<3 &0x10 | 0x0F); + } else { + setprg16(0x8000, Latch_address <<3 &0x18 | Latch_data &0x07); + setprg16(0xC000, Latch_address <<3 &0x18 | 0x07); + } + SetReadHandler(0x8000, 0xFFFF, Latch_address &0x10 && ROM_size >8? readOB: CartBR); + setchr8(0); +} + +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { + if (Latch_address &0x20) *newAddress = Latch_address; /* Once bit 5 is set, only the inner bank bits can be modified. */ + *newValue &= romValue; /* AND-type bus conflicts */ +} + +void Mapper573_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); + info->Reset = Latch_power; +} diff --git a/src/ines.c b/src/ines.c index 918a36c..1253b3c 100644 --- a/src/ines.c +++ b/src/ines.c @@ -951,6 +951,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Venus Turbo Game Doctor", 562, Mapper561_562_Init ) INES_BOARD( "J-2020", 563, Mapper563_Init ) INES_BOARD( "Top Ten Variety (SF III)", 567, Mapper567_Init ) + INES_BOARD( "5068", 573, Mapper573_Init ) INES_BOARD( "T-215", 579, Mapper579_Init ) INES_BOARD( "ET-82", 581, Mapper581_Init ) INES_BOARD( "HN-02", 586, Mapper586_Init ) diff --git a/src/ines.h b/src/ines.h index 10e5854..5d55090 100644 --- a/src/ines.h +++ b/src/ines.h @@ -416,6 +416,7 @@ void Mapper559_Init(CartInfo *); void Mapper561_562_Init(CartInfo *); void Mapper563_Init(CartInfo *); void Mapper567_Init(CartInfo *); +void Mapper573_Init(CartInfo *); void Mapper579_Init(CartInfo *); void Mapper581_Init(CartInfo *); void Mapper586_Init(CartInfo *); From 51b74cebdc216504f7e864924c2a267606c1782c Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 00:13:05 +0200 Subject: [PATCH 023/109] Mapper 394: Allow 1 MiB CHR-ROM with submapper 0. --- src/boards/jyasic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boards/jyasic.c b/src/boards/jyasic.c index 544648b..ef0d708 100644 --- a/src/boards/jyasic.c +++ b/src/boards/jyasic.c @@ -710,7 +710,7 @@ static void Mapper394_PWrap(uint32 A, uint8 V) static void Mapper394_CWrap(uint32 A, uint8 V) { int chrAND =HSK007Reg[3] &0x80? 0xFF: 0x7F; - int chrOR =submapper ==1? (HSK007Reg[3] <<1 &0x080 | HSK007Reg[1] <<8 &0x200 | HSK007Reg[1] <<6 &0x100): (HSK007Reg[3] <<1 &0x080 | HSK007Reg[1] <<8 &0x100); + int chrOR =submapper ==1? (HSK007Reg[3] <<1 &0x080 | HSK007Reg[1] <<8 &0x200 | HSK007Reg[1] <<6 &0x100): (HSK007Reg[3] <<1 &0x080 | HSK007Reg[1] <<8 &0x300); setchr1(A, V &chrAND | chrOR &~chrAND); } static DECLFW(Mapper394_Write) From a57d1d595548a994ad641f383011b97e20b09b80 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 00:30:58 +0200 Subject: [PATCH 024/109] Mapper 327: add submapper 1, used for Mario IV (Armadillo)'s 1-screen mirroring. --- src/boards/et-100.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/boards/et-100.c b/src/boards/et-100.c index 5e41622..1ad553c 100644 --- a/src/boards/et-100.c +++ b/src/boards/et-100.c @@ -41,6 +41,7 @@ #include "mapinc.h" #include "mmc3.h" +static uint8 submapper; static uint8 *CHRRAM = NULL; static uint32 CHRRAMSize; @@ -58,6 +59,16 @@ static void BMC1024CA1CW(uint32 A, uint8 V) { setchr1(A, V | ((EXPREGS[0] & 7) << 7)); else setchr1(A, (V&0x7F) | ((EXPREGS[0] & 7) << 7)); + + if (submapper == 1 && EXPREGS[0] &0x08) setmirror(DRegBuf[MMC3_cmd &0x80? 2: 0] &0x80? MI_1: MI_0); +} + +static void BMC1024CA1MW(uint8 V) { + A000B = V; + if (EXPREGS[0] &0x08) + setmirror(DRegBuf[MMC3_cmd &0x80? 2: 0] &0x80? MI_1: MI_0); + else + setmirror(V &1? MI_H: MI_V); } static DECLFW(BMC1024CA1Write) { @@ -90,6 +101,7 @@ static void BMC1024CA1Close(void) { } void BMC1024CA1_Init(CartInfo *info) { + submapper = info->submapper; GenMMC3_Init(info, 256, 256, 8, 0); CHRRAMSize = 8192; CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize); @@ -97,6 +109,7 @@ void BMC1024CA1_Init(CartInfo *info) { AddExState(CHRRAM, CHRRAMSize, 0, "CHRR"); pwrap = BMC1024CA1PW; cwrap = BMC1024CA1CW; + if (submapper == 1) mwrap = BMC1024CA1MW; info->Power = BMC1024CA1Power; info->Reset = BMC1024CA1Reset; info->Close = BMC1024CA1Close; From ced209604c017bcf00002a35046462d713fd6e95 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 00:44:10 +0200 Subject: [PATCH 025/109] Add mapper 583. --- src/boards/583.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 52 insertions(+) create mode 100644 src/boards/583.c diff --git a/src/boards/583.c b/src/boards/583.c new file mode 100644 index 0000000..483e3ed --- /dev/null +++ b/src/boards/583.c @@ -0,0 +1,50 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + int prg = Latch_address &~0xF | Latch_address <<3 &0x08; + if (Latch_address &0x20) { + setprg32(0x8000, prg >>1 &~7 | Latch_data &7); + setmirror(Latch_data &0x10? MI_1: MI_0); + } else { + if (Latch_address &0x10 && Latch_address &0x08) { + setprg16(0x8000, prg &~0x03 | Latch_data &0x03); + setprg16(0xC000, prg | 0x03); + setmirror(MI_H); + } else { + setprg16(0x8000, prg &~0x07 | Latch_data &0x07); + setprg16(0xC000, prg | 0x07); + setmirror(MI_V); + } + } + setchr8(0); +} + +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { /* The address bits are only updated on a rising edge of A7. */ + if (!(~Latch_address &0x80 && *newAddress &0x80)) *newAddress = Latch_address; +} + +void Mapper583_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); + info->Reset = Latch_power; +} diff --git a/src/ines.c b/src/ines.c index 1253b3c..93cf2f2 100644 --- a/src/ines.c +++ b/src/ines.c @@ -954,6 +954,7 @@ INES_BOARD_BEGIN() INES_BOARD( "5068", 573, Mapper573_Init ) INES_BOARD( "T-215", 579, Mapper579_Init ) INES_BOARD( "ET-82", 581, Mapper581_Init ) + INES_BOARD( "8203", 583, Mapper583_Init ) INES_BOARD( "HN-02", 586, Mapper586_Init ) INES_BOARD( "ET-81", 588, Mapper588_Init ) INES_BOARD( "810706", 589, Mapper589_Init ) diff --git a/src/ines.h b/src/ines.h index 5d55090..5ba4eb1 100644 --- a/src/ines.h +++ b/src/ines.h @@ -419,6 +419,7 @@ void Mapper567_Init(CartInfo *); void Mapper573_Init(CartInfo *); void Mapper579_Init(CartInfo *); void Mapper581_Init(CartInfo *); +void Mapper583_Init(CartInfo *); void Mapper586_Init(CartInfo *); void Mapper588_Init(CartInfo *); void Mapper589_Init(CartInfo *); From 7b4f0848308c313745c409cc2830cf551bc05c87 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 00:51:25 +0200 Subject: [PATCH 026/109] Add mapper 578. --- src/boards/432.c | 8 +++---- src/boards/578.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 4 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 src/boards/578.c diff --git a/src/boards/432.c b/src/boards/432.c index 002718d..c17c897 100644 --- a/src/boards/432.c +++ b/src/boards/432.c @@ -32,10 +32,10 @@ static DECLFR(readPad) { } static void sync() { - int prgAND =reg[1] &0x02? 0x0F: 0x1F; - int chrAND =reg[1] &0x20 && submapper == 3? 0x1FF: reg[1] &0x04? 0x7F: 0xFF; - int prgOR =reg[1] <<4 &0x10 | reg[1] <<1 &0x60; - int chrOR =reg[1] <<7 &0x80 | reg[1] <<5 &0x100 | reg[1] <<4 &0x200; + int prgAND = reg[1] &0x02? 0x0F: 0x1F; + int chrAND = reg[1] &0x20 && submapper == 3? 0x1FF: reg[1] &0x04? 0x7F: 0xFF; + int prgOR = reg[1] <<4 &0x10 | reg[1] <<1 &0x60; + int chrOR = reg[1] <<7 &0x80 | reg[1] <<5 &0x100 | reg[1] <<4 &0x200; MMC3_syncPRG(prgAND, prgOR &~prgAND); MMC3_syncCHR(chrAND, chrOR &~chrAND); MMC3_syncMirror(); diff --git a/src/boards/578.c b/src/boards/578.c new file mode 100644 index 0000000..c70a936 --- /dev/null +++ b/src/boards/578.c @@ -0,0 +1,60 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync() { + int prgAND = reg &0x02 && reg &0x04? 0x1F: 0x0F; + int chrAND = reg &0x02 && reg &0x04? 0xFF: 0x7F; + int prgOR = reg <<4; + int chrOR = reg <<7; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static DECLFW(writeReg) { + reg = V; + sync(); +} + +static void reset() { + reg = 0; + sync(); +} + +static void power() { + int i; + reg = 0; + MMC3_power(); + for (int i = 0x8000; i < 0xFFFF; i +=4) SetWriteHandler(i |2, i |3, writeReg); +} + +void Mapper578_Init(CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/ines.c b/src/ines.c index 93cf2f2..39716d5 100644 --- a/src/ines.c +++ b/src/ines.c @@ -952,6 +952,7 @@ INES_BOARD_BEGIN() INES_BOARD( "J-2020", 563, Mapper563_Init ) INES_BOARD( "Top Ten Variety (SF III)", 567, Mapper567_Init ) INES_BOARD( "5068", 573, Mapper573_Init ) + INES_BOARD( "910610", 578, Mapper578_Init ) INES_BOARD( "T-215", 579, Mapper579_Init ) INES_BOARD( "ET-82", 581, Mapper581_Init ) INES_BOARD( "8203", 583, Mapper583_Init ) diff --git a/src/ines.h b/src/ines.h index 5ba4eb1..d262f3f 100644 --- a/src/ines.h +++ b/src/ines.h @@ -417,6 +417,7 @@ void Mapper561_562_Init(CartInfo *); void Mapper563_Init(CartInfo *); void Mapper567_Init(CartInfo *); void Mapper573_Init(CartInfo *); +void Mapper578_Init(CartInfo *); void Mapper579_Init(CartInfo *); void Mapper581_Init(CartInfo *); void Mapper583_Init(CartInfo *); From a95b1191b85ead1642b4abf15bb668142b7cbb00 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 00:53:55 +0200 Subject: [PATCH 027/109] Add mapper 280 submapper 1 (235-in-1). --- src/boards/280.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/boards/280.c b/src/boards/280.c index 07deac1..b831be7 100644 --- a/src/boards/280.c +++ b/src/boards/280.c @@ -23,6 +23,7 @@ static uint16 latchAddr; static uint8 latchData; static uint8 mode; +static uint8 submapper; static SFORMAT StateRegs[] = { { &latchAddr, 2 | FCEUSTATE_RLSB, "LATC" }, @@ -33,8 +34,13 @@ static SFORMAT StateRegs[] = { static void Sync(void) { if (mode &1) { - setprg16(0x8000, 0x20 | latchData &0x07); - setprg16(0xC000, 0x27); + if (submapper == 1) { + setprg16(0x8000, latchAddr >>2 &7 |0x20); + setprg16(0xC000, 0x27); + } else { + setprg16(0x8000, 0x20 | latchData &0x07); + setprg16(0xC000, 0x27); + } } else { if (latchAddr &0x01) setprg32(0x8000, latchAddr >>3 &0x0F); @@ -76,6 +82,7 @@ static void StateRestore(int version) { } void Mapper280_Init(CartInfo *info) { + submapper = info->submapper; info->Power = M280Power; info->Reset = M280Reset; GameStateRestore = StateRestore; From 2d55ac5532452ec80b9ab256bce3796180d8cdaf Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 10:57:02 +0200 Subject: [PATCH 028/109] Mapper 449: Distinguish three circuit boards that differ in their menu selection mechanism via submapper. --- src/boards/449.c | 129 ++++++++++++++++++++--------------------------- 1 file changed, 56 insertions(+), 73 deletions(-) diff --git a/src/boards/449.c b/src/boards/449.c index 72e4b4c..6fcefc2 100644 --- a/src/boards/449.c +++ b/src/boards/449.c @@ -1,7 +1,7 @@ -/* FCEUmm - NES/Famicom Emulator +/* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2022 + * Copyright (C) 2025 NewRisingSun * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,88 +19,71 @@ */ #include "mapinc.h" +#include "asic_latch.h" -static uint16 latchAddr; -static uint8 latchData; -static uint8 dipswitch; -static uint8 dipselect; +uint8 submapper; +uint8 pad; +uint8 padSelect; -static SFORMAT StateRegs[] = -{ - { &latchAddr, 2, "ADDR" }, - { &latchData, 1, "DATA" }, - { &latchData, 1, "DIPS" }, - { &dipselect, 1, "DSEL" }, - { 0 } -}; - -static void Mapper449_Sync(void) -{ - int prg =latchAddr >>2 &0x1F | latchAddr >>3 &0x20; - if (~latchAddr &0x080) - { - setprg16(0x8000, prg); - setprg16(0xC000, prg |7); - } - else - { - if (latchAddr &0x001) - { - setprg32(0x8000, prg >>1); - } - else - { - setprg16(0x8000, prg); - setprg16(0xC000, prg); - } - } - setchr8(latchData); - setmirror(latchAddr &0x002? MI_H: MI_V); +static DECLFR(readPad_submapper0) { + return CartBR(A &~0xF | pad &0xF); } -static DECLFR(Mapper449_Read) -{ - if (dipselect) - return dipswitch &0x3; - else - if (latchAddr &0x200) - return CartBR(A | dipswitch &0xF); - else - return CartBR(A); +static DECLFR(readPad_submapper1) { + return pad; } -static DECLFW(Mapper449_WriteDIPSelect) -{ - dipselect =V &1; +static DECLFR(readPad_submapper2) { + return CartBR(A &~0x3 | pad &0x3); } -static DECLFW(Mapper449_WriteLatch) -{ - latchData =V; - latchAddr =A &0xFFFF; - Mapper449_Sync(); +static void sync () { + int prg = Latch_address >>2 &0x1F | Latch_address >>3 &0x20 | Latch_address >>4 &0x40; + if (Latch_address &0x080) { + if (Latch_address &0x001) + setprg32(0x8000, prg >>1); + else { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } + setmirror(Latch_data &0x10? MI_1: MI_0); + } else { + setprg16(0x8000, prg); + setprg16(0xC000, prg | 7); + } + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], submapper == 0 && Latch_address &0x80? 0: 1); + setchr8(Latch_data); + setmirror(Latch_address &0x002? MI_H: MI_V); + SetReadHandler(0x8000, 0xFFFF, submapper == 0 && Latch_address &0x200? readPad_submapper0: submapper == 2 && padSelect &1? readPad_submapper2: CartBR); } -static void Mapper449_Reset(void) -{ - dipswitch++; - latchAddr =latchData =0; - Mapper449_Sync(); +static DECLFW(writePad_submapper2) { + padSelect = V; + sync(); } -static void Mapper449_Power(void) -{ - dipselect =dipswitch =latchAddr =latchData =0; - Mapper449_Sync(); - SetWriteHandler(0x6000, 0x7FFF, Mapper449_WriteDIPSelect); - SetWriteHandler(0x8000, 0xFFFF, Mapper449_WriteLatch); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetReadHandler(0x8000, 0xFFFF, Mapper449_Read); +static void power () { + pad = padSelect = 0; + Latch_power(); + if (submapper == 1) + SetReadHandler(0x5000, 0x5FFF, readPad_submapper1); + else + if (submapper == 2) + SetWriteHandler(0x6000, 0x7FFF, writePad_submapper2); } -void Mapper449_Init(CartInfo *info) -{ - info->Power = Mapper449_Power; - info->Reset = Mapper449_Reset; - AddExState(StateRegs, ~0, 0, 0); -} \ No newline at end of file +static void reset () { + pad++; + padSelect = 0; + Latch_address = 0; + sync(); +} + +void Mapper449_Init (CartInfo *info) { + submapper = info->submapper; + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; + AddExState(&pad, 1, 0, "DIPS"); + if (submapper == 2) AddExState(&padSelect, 1, 0, "DIPE"); +} From 2cbeafc880877afaef8fddbae7eca3b1db5af7b5 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 11:11:16 +0200 Subject: [PATCH 029/109] Add mapper 587. --- src/boards/587.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 67 insertions(+) create mode 100644 src/boards/587.c diff --git a/src/boards/587.c b/src/boards/587.c new file mode 100644 index 0000000..91fe1b9 --- /dev/null +++ b/src/boards/587.c @@ -0,0 +1,65 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[2]; + +static void sync () { + if (reg[0] &0x02) { + setprg16(0x8000, reg[0] &~0x07 | reg[1] &0x07); + setprg16(0xC000, reg[0] |0x07); + } else { + if (reg[0] &0x80) + setprg32(0x8000, reg[0] >>1 &~0x03 | reg[1] &0x03); + else { + setprg16(0x8000, reg[0] &~0x07 | reg[1] &0x07); + setprg16(0xC000, reg[0] &~0x07 | reg[1] &0x07); + } + } + setchr8(0); + if (reg[0] &0x04) + setmirror(reg[1] &0x10? MI_1: MI_0); + else + setmirror(reg[0] &0x01? MI_H: MI_V); +} + +static DECLFW(writeReg) { + reg[reg[0] &0x80? 1: 0] = V; + sync(); +} + +static void power() { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, writeReg); + reg[0] = reg[1] = 0; + sync(); +} + +static void stateRestore(int version) { + sync(); +} + +void Mapper587_Init (CartInfo *info) { + info->Reset = power; + info->Power = power; + GameStateRestore = stateRestore; + AddExState(reg, 2, 0, "REGS"); +} diff --git a/src/ines.c b/src/ines.c index 39716d5..28121de 100644 --- a/src/ines.c +++ b/src/ines.c @@ -957,6 +957,7 @@ INES_BOARD_BEGIN() INES_BOARD( "ET-82", 581, Mapper581_Init ) INES_BOARD( "8203", 583, Mapper583_Init ) INES_BOARD( "HN-02", 586, Mapper586_Init ) + INES_BOARD( "3355", 587, Mapper587_Init ) INES_BOARD( "ET-81", 588, Mapper588_Init ) INES_BOARD( "810706", 589, Mapper589_Init ) INES_BOARD( "810430", 590, Mapper590_Init ) diff --git a/src/ines.h b/src/ines.h index d262f3f..e0fa2c1 100644 --- a/src/ines.h +++ b/src/ines.h @@ -422,6 +422,7 @@ void Mapper579_Init(CartInfo *); void Mapper581_Init(CartInfo *); void Mapper583_Init(CartInfo *); void Mapper586_Init(CartInfo *); +void Mapper587_Init(CartInfo *); void Mapper588_Init(CartInfo *); void Mapper589_Init(CartInfo *); void Mapper590_Init(CartInfo *); From edd3029dc4d5fb2fc3ed4d123fd28a53ad23152f Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 11:26:45 +0200 Subject: [PATCH 030/109] Add mappers 506 and 572. --- src/boards/506.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++ src/boards/572.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 2 ++ src/ines.h | 2 ++ 4 files changed, 122 insertions(+) create mode 100644 src/boards/506.c create mode 100644 src/boards/572.c diff --git a/src/boards/506.c b/src/boards/506.c new file mode 100644 index 0000000..69d049e --- /dev/null +++ b/src/boards/506.c @@ -0,0 +1,58 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync() { + int prgAND =~reg &3? 0x0F: 0x1F; + int chrAND = reg &3? 0x7F: 0xFF; + int prgOR = reg <<5 &0x20 | reg <<3 &0x10; + int chrOR = reg <<7 &0x100 |~reg <<7 &0x80; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static DECLFW(writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset() { + reg = 0; + sync(); +} + +static void power() { + reg = 0; + MMC3_power(); +} + +void Mapper506_Init(CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/572.c b/src/boards/572.c new file mode 100644 index 0000000..ce59940 --- /dev/null +++ b/src/boards/572.c @@ -0,0 +1,60 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync() { + int prgAND = 0x1F; + int chrAND = 0x7F; + int prgOR = reg <<5; + int chrOR = reg <<7; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static DECLFW(writeReg) { + if (~reg &0x08) { + reg = A &0xFF; + sync(); + } +} + +static void reset() { + reg = 0; + sync(); +} + +static void power() { + reg = 0; + MMC3_power(); +} + +void Mapper572_Init(CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/ines.c b/src/ines.c index 28121de..22d0d6c 100644 --- a/src/ines.c +++ b/src/ines.c @@ -914,6 +914,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Yhc-002", 502, Mapper502_Init ) INES_BOARD( "ET-170", 503, Mapper503_Init ) INES_BOARD( "K-3054", 504, Mapper504_Init ) + INES_BOARD( "GA-009", 506, Mapper506_Init ) INES_BOARD( "SA-9602B", 513, SA9602B_Init ) INES_BOARD( "Brilliant Com Cocoma Pack",516, Mapper516_Init ) INES_BOARD( "DANCE2000", 518, UNLD2000_Init ) @@ -951,6 +952,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Venus Turbo Game Doctor", 562, Mapper561_562_Init ) INES_BOARD( "J-2020", 563, Mapper563_Init ) INES_BOARD( "Top Ten Variety (SF III)", 567, Mapper567_Init ) + INES_BOARD( "F-648", 572, Mapper572_Init ) INES_BOARD( "5068", 573, Mapper573_Init ) INES_BOARD( "910610", 578, Mapper578_Init ) INES_BOARD( "T-215", 579, Mapper579_Init ) diff --git a/src/ines.h b/src/ines.h index e0fa2c1..b3b0f22 100644 --- a/src/ines.h +++ b/src/ines.h @@ -393,6 +393,7 @@ void Mapper501_Init(CartInfo *); void Mapper502_Init(CartInfo *); void Mapper503_Init(CartInfo *); void Mapper504_Init(CartInfo *); +void Mapper506_Init(CartInfo *); void Mapper516_Init(CartInfo *); void Mapper520_Init(CartInfo *); void Mapper523_Init(CartInfo *); @@ -416,6 +417,7 @@ void Mapper559_Init(CartInfo *); void Mapper561_562_Init(CartInfo *); void Mapper563_Init(CartInfo *); void Mapper567_Init(CartInfo *); +void Mapper572_Init(CartInfo *); void Mapper573_Init(CartInfo *); void Mapper578_Init(CartInfo *); void Mapper579_Init(CartInfo *); From 67c7a5e4c6d170a6b4df88d254922d5b8c148c73 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 11:36:10 +0200 Subject: [PATCH 031/109] Add mapper 570. --- src/boards/570.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 61 insertions(+) create mode 100644 src/boards/570.c diff --git a/src/boards/570.c b/src/boards/570.c new file mode 100644 index 0000000..a30a5cc --- /dev/null +++ b/src/boards/570.c @@ -0,0 +1,59 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_vrc2and4.h" + +static uint8 reg; + +static void sync() { + int prgAND = 0x0F; + int chrAND = reg &0x03? 0x0FF: 0x1FF; + int prgOR = reg <<4; + int chrOR = !!(reg &0x03)*0x200 | !!(reg &0x02)*0x100; + VRC24_syncPRG(prgAND, prgOR &~prgAND); + VRC24_syncCHR(chrAND, chrOR &~chrAND); + VRC24_syncMirror(); +} + +static DECLFW(writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset() { + reg = 0; + sync(); +} + +static void power() { + reg = 0; + VRC24_power(); + SetWriteHandler(0x5000, 0x5FFF, writeReg); +} + +void Mapper570_Init(CartInfo *info) { + VRC4_init(info, sync, 1, 2, 1, NULL, NULL, NULL, NULL, NULL); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/ines.c b/src/ines.c index 22d0d6c..918d7e8 100644 --- a/src/ines.c +++ b/src/ines.c @@ -952,6 +952,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Venus Turbo Game Doctor", 562, Mapper561_562_Init ) INES_BOARD( "J-2020", 563, Mapper563_Init ) INES_BOARD( "Top Ten Variety (SF III)", 567, Mapper567_Init ) + INES_BOARD( "9052", 570, Mapper570_Init ) INES_BOARD( "F-648", 572, Mapper572_Init ) INES_BOARD( "5068", 573, Mapper573_Init ) INES_BOARD( "910610", 578, Mapper578_Init ) diff --git a/src/ines.h b/src/ines.h index b3b0f22..b737c57 100644 --- a/src/ines.h +++ b/src/ines.h @@ -417,6 +417,7 @@ void Mapper559_Init(CartInfo *); void Mapper561_562_Init(CartInfo *); void Mapper563_Init(CartInfo *); void Mapper567_Init(CartInfo *); +void Mapper570_Init(CartInfo *); void Mapper572_Init(CartInfo *); void Mapper573_Init(CartInfo *); void Mapper578_Init(CartInfo *); From bb4d5490e279f4c1e78b994a8bb26be6ef320df7 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 12:36:25 +0200 Subject: [PATCH 032/109] Add mapper 580. --- src/boards/580.c | 39 +++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 41 insertions(+) create mode 100644 src/boards/580.c diff --git a/src/boards/580.c b/src/boards/580.c new file mode 100644 index 0000000..963c8ae --- /dev/null +++ b/src/boards/580.c @@ -0,0 +1,39 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_address &0x01) { + setprg32(0x8000, Latch_address >>5); + setchr8(Latch_address >>3 &~3 | Latch_address >>2 &3); + } else { + setprg16(0x8000, Latch_address >>4); + setprg16(0xC000, Latch_address >>4); + setchr8(Latch_address >>3 &~1 | Latch_address >>2 &1); + } + setmirror(Latch_address &0x02? MI_H: MI_V); +} + +void Mapper580_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_power; +} diff --git a/src/ines.c b/src/ines.c index 918d7e8..ac9a627 100644 --- a/src/ines.c +++ b/src/ines.c @@ -957,6 +957,7 @@ INES_BOARD_BEGIN() INES_BOARD( "5068", 573, Mapper573_Init ) INES_BOARD( "910610", 578, Mapper578_Init ) INES_BOARD( "T-215", 579, Mapper579_Init ) + INES_BOARD( "ET-156", 580, Mapper580_Init ) INES_BOARD( "ET-82", 581, Mapper581_Init ) INES_BOARD( "8203", 583, Mapper583_Init ) INES_BOARD( "HN-02", 586, Mapper586_Init ) diff --git a/src/ines.h b/src/ines.h index b737c57..237f0c0 100644 --- a/src/ines.h +++ b/src/ines.h @@ -422,6 +422,7 @@ void Mapper572_Init(CartInfo *); void Mapper573_Init(CartInfo *); void Mapper578_Init(CartInfo *); void Mapper579_Init(CartInfo *); +void Mapper580_Init(CartInfo *); void Mapper581_Init(CartInfo *); void Mapper583_Init(CartInfo *); void Mapper586_Init(CartInfo *); From 869cb56472c5a69bb52ccee7e31d8c657da9be73 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 12:41:15 +0200 Subject: [PATCH 033/109] Add mapper 61 submapper 1. --- src/boards/addrlatch.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c index 48eb759..d2bb821 100644 --- a/src/boards/addrlatch.c +++ b/src/boards/addrlatch.c @@ -181,7 +181,10 @@ static void M61Sync(void) { setprg16(0xC000, latche <<1 &0x1E | latche >>5 &0x01); } else setprg32(0x8000, latche & 0xF); - setchr8(latche >> 8); + if (submapper == 1) + setchr8(latche >> 7 &~1 | latche >> 6 &1); + else + setchr8(latche >> 8); setmirror(((latche >> 7) & 1) ^ 1); } @@ -193,6 +196,7 @@ void Mapper61_Reset() { } void Mapper61_Init(CartInfo *info) { + submapper = info->submapper; Latch_Init(info, M61Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); info->Reset = Mapper61_Reset; } From ee20cce026815dc8c95b5bd2c1aface2f903b056 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 12:48:24 +0200 Subject: [PATCH 034/109] Add mapper 585. --- src/boards/585.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 60 insertions(+) create mode 100644 src/boards/585.c diff --git a/src/boards/585.c b/src/boards/585.c new file mode 100644 index 0000000..52dbdd0 --- /dev/null +++ b/src/boards/585.c @@ -0,0 +1,58 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static uint8 pad; + +static DECLFR(readOB) { + return X.DB; +} + +static void sync () { + if (Latch_address &0x01) + setprg32(0x8000, Latch_address >>2); + else { + setprg16(0x8000, Latch_address >>1); + setprg16(0xC000, Latch_address >>1); + } + SetReadHandler(0x8000, 0xFFFF, Latch_address &pad &0x60? readOB: CartBR); + setchr8(Latch_address >>1); + setmirror(Latch_address &0x10? MI_V: MI_H); +} + +static void power() { + pad = 0; + Latch_power(); +} + +static void reset() { + pad += 0x20; + Latch_address = 0; + sync(); +} + +void Mapper585_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/ines.c b/src/ines.c index ac9a627..79a2696 100644 --- a/src/ines.c +++ b/src/ines.c @@ -960,6 +960,7 @@ INES_BOARD_BEGIN() INES_BOARD( "ET-156", 580, Mapper580_Init ) INES_BOARD( "ET-82", 581, Mapper581_Init ) INES_BOARD( "8203", 583, Mapper583_Init ) + INES_BOARD( "FE-01-1", 585, Mapper585_Init ) INES_BOARD( "HN-02", 586, Mapper586_Init ) INES_BOARD( "3355", 587, Mapper587_Init ) INES_BOARD( "ET-81", 588, Mapper588_Init ) diff --git a/src/ines.h b/src/ines.h index 237f0c0..2a33021 100644 --- a/src/ines.h +++ b/src/ines.h @@ -425,6 +425,7 @@ void Mapper579_Init(CartInfo *); void Mapper580_Init(CartInfo *); void Mapper581_Init(CartInfo *); void Mapper583_Init(CartInfo *); +void Mapper585_Init(CartInfo *); void Mapper586_Init(CartInfo *); void Mapper587_Init(CartInfo *); void Mapper588_Init(CartInfo *); From b2de421d4d33c6af5431f4edb9efc834a5f0932b Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 13:44:14 +0200 Subject: [PATCH 035/109] Add solder-pad-based menu selection to mapper 285. Make Latch_clear public and use it to reset multicarts to menu instead of Latch_power. --- src/boards/285.c | 78 +++++++++++++++++++++++++++++++++++++++++ src/boards/573.c | 2 +- src/boards/579.c | 2 +- src/boards/580.c | 2 +- src/boards/581.c | 2 +- src/boards/583.c | 2 +- src/boards/584.c | 59 +++++++++++++++++++++++++++++++ src/boards/585.c | 3 +- src/boards/586.c | 2 +- src/boards/589.c | 2 +- src/boards/590.c | 2 +- src/boards/591.c | 2 +- src/boards/592.c | 2 +- src/boards/asic_latch.c | 2 +- src/boards/asic_latch.h | 1 + src/boards/datalatch.c | 47 ------------------------- src/ines.c | 3 +- src/ines.h | 1 + src/unif.c | 2 +- src/unif.h | 2 +- 20 files changed, 155 insertions(+), 63 deletions(-) create mode 100644 src/boards/285.c create mode 100644 src/boards/584.c diff --git a/src/boards/285.c b/src/boards/285.c new file mode 100644 index 0000000..9c90393 --- /dev/null +++ b/src/boards/285.c @@ -0,0 +1,78 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static uint8 pad; + +static void sync_submapper0 () { + if (Latch_data &0x40) + setprg32(0x8000, Latch_data >>1); + else { + setprg16(0x8000, Latch_data); + setprg16(0xC000, Latch_data |7); + } + setchr8(0); + if (Latch_data &0x80) + setmirror(Latch_data &0x20? MI_1: MI_0); + else + setmirror(Latch_data &0x20? MI_H: MI_V); +} + +static void sync_submapper1 () { + if (Latch_data &0x40) + setprg32(0x8000, Latch_data >>1 &0x03 | Latch_data >>2 &~0x03); + else { + setprg16(0x8000, Latch_data >>1 &~0x07 | Latch_data &0x07); + setprg16(0xC000, Latch_data >>1 | 0x07); + } + setchr8(0); + if (Latch_data &0x80) + setmirror(Latch_data &0x20? MI_1: MI_0); + else + setmirror(Latch_data &0x08? MI_H: MI_V); +} + +static DECLFR (readPad) { + if (A &0x80) return pad >= 20? (4 | pad % 20): 0; else + if (A &0x40) return pad >= 16? (4 | pad % 16): 0; else + if (A &0x20) return pad >= 12? (4 | pad % 12): 0; else + if (A &0x10) return pad >= 8? (4 | pad % 8): 0; else + return pad >= 8? 0: pad &7; +} + +static void power() { + pad = 0; + Latch_power(); + SetReadHandler(0x5000, 0x5FFF, readPad); +} + +static void reset() { + pad = ++pad %24; + Latch_clear(); +} + +void Mapper285_Init (CartInfo *info) { + Latch_init(info, info->submapper ==1? sync_submapper1: sync_submapper0, 0x8000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/boards/573.c b/src/boards/573.c index c49243d..9829cce 100644 --- a/src/boards/573.c +++ b/src/boards/573.c @@ -44,5 +44,5 @@ static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) void Mapper573_Init (CartInfo *info) { Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); - info->Reset = Latch_power; + info->Reset = Latch_clear; } diff --git a/src/boards/579.c b/src/boards/579.c index 8490691..2170c21 100644 --- a/src/boards/579.c +++ b/src/boards/579.c @@ -45,5 +45,5 @@ static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) void Mapper579_Init (CartInfo *info) { Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); - info->Reset = Latch_power; + info->Reset = Latch_clear; } diff --git a/src/boards/580.c b/src/boards/580.c index 963c8ae..724c297 100644 --- a/src/boards/580.c +++ b/src/boards/580.c @@ -35,5 +35,5 @@ static void sync () { void Mapper580_Init (CartInfo *info) { Latch_init(info, sync, 0x8000, 0xFFFF, NULL); - info->Reset = Latch_power; + info->Reset = Latch_clear; } diff --git a/src/boards/581.c b/src/boards/581.c index 54dbce4..e35c8ac 100644 --- a/src/boards/581.c +++ b/src/boards/581.c @@ -44,5 +44,5 @@ static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) void Mapper581_Init (CartInfo *info) { Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); - info->Reset = Latch_power; + info->Reset = Latch_clear; } diff --git a/src/boards/583.c b/src/boards/583.c index 483e3ed..37ef1f4 100644 --- a/src/boards/583.c +++ b/src/boards/583.c @@ -46,5 +46,5 @@ static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) void Mapper583_Init (CartInfo *info) { Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); - info->Reset = Latch_power; + info->Reset = Latch_clear; } diff --git a/src/boards/584.c b/src/boards/584.c new file mode 100644 index 0000000..45519aa --- /dev/null +++ b/src/boards/584.c @@ -0,0 +1,59 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[2]; + +static void sync () { + if (reg[0] &0x20) + setprg32(0x8000, reg[0] >>1); + else { + setprg16(0x8000, reg[0]); + setprg16(0xC000, reg[0]); + } + setchr8(reg[1]); + setmirror(reg[1] &0x20? MI_V: MI_H); +} + +static DECLFW(writeReg) { + if (A &0x100) { + reg[A >>13 &1] = V; + sync(); + } +} + +static void power() { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x4020, 0x7FFF, writeReg); + reg[0] = reg[1] = 0; + sync(); +} + +static void stateRestore(int version) { + sync(); +} + +void Mapper584_Init (CartInfo *info) { + info->Reset = power; + info->Power = power; + GameStateRestore = stateRestore; + AddExState(reg, 2, 0, "REGS"); +} diff --git a/src/boards/585.c b/src/boards/585.c index 52dbdd0..0e60577 100644 --- a/src/boards/585.c +++ b/src/boards/585.c @@ -46,8 +46,7 @@ static void power() { static void reset() { pad += 0x20; - Latch_address = 0; - sync(); + Latch_clear(); } void Mapper585_Init (CartInfo *info) { diff --git a/src/boards/586.c b/src/boards/586.c index 2cf2bfc..3872a9b 100644 --- a/src/boards/586.c +++ b/src/boards/586.c @@ -33,5 +33,5 @@ static void sync () { void Mapper586_Init (CartInfo *info) { Latch_init(info, sync, 0x8000, 0xFFFF, NULL); - info->Reset = Latch_power; + info->Reset = Latch_clear; } diff --git a/src/boards/589.c b/src/boards/589.c index a613f08..6610761 100644 --- a/src/boards/589.c +++ b/src/boards/589.c @@ -39,5 +39,5 @@ static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) void Mapper589_Init (CartInfo *info) { Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); - info->Reset = Latch_power; + info->Reset = Latch_clear; } diff --git a/src/boards/590.c b/src/boards/590.c index e77b6dd..2d90cb1 100644 --- a/src/boards/590.c +++ b/src/boards/590.c @@ -33,5 +33,5 @@ static void sync () { void Mapper590_Init (CartInfo *info) { Latch_init(info, sync, 0x8000, 0xFFFF, NULL); - info->Reset = Latch_power; + info->Reset = Latch_clear; } diff --git a/src/boards/591.c b/src/boards/591.c index d2f3ad1..dc417d2 100644 --- a/src/boards/591.c +++ b/src/boards/591.c @@ -34,5 +34,5 @@ static void sync () { void Mapper591_Init (CartInfo *info) { Latch_init(info, sync, 0x8000, 0xFFFF, NULL); - info->Reset = Latch_power; + info->Reset = Latch_clear; } diff --git a/src/boards/592.c b/src/boards/592.c index 6464e04..3c91f35 100644 --- a/src/boards/592.c +++ b/src/boards/592.c @@ -30,5 +30,5 @@ static void sync () { void Mapper592_Init (CartInfo *info) { Latch_init(info, sync, 0x8000, 0xFFFF, NULL); - info->Reset = Latch_power; + info->Reset = Latch_clear; } diff --git a/src/boards/asic_latch.c b/src/boards/asic_latch.c index 4eebcfd..f94286b 100644 --- a/src/boards/asic_latch.c +++ b/src/boards/asic_latch.c @@ -41,7 +41,7 @@ DECLFW(Latch_write) { Latch_cbSync(); } -static void Latch_clear () { +void Latch_clear () { Latch_address = 0; Latch_data = 0; Latch_cbSync(); diff --git a/src/boards/asic_latch.h b/src/boards/asic_latch.h index 07e4c87..80c9ef2 100644 --- a/src/boards/asic_latch.h +++ b/src/boards/asic_latch.h @@ -27,6 +27,7 @@ extern uint8 Latch_data; DECLFW (Latch_write); void Latch_addExState (); void Latch_restore (int); +void Latch_clear (); void Latch_power (); void Latch_activate (uint8, void (*)(), uint16, uint16, void (*)(uint16*, uint8*, uint8)); void Latch6_activate (uint8, void (*)(), uint16, uint16, void (*)(uint16*, uint8*, uint8)); diff --git a/src/boards/datalatch.c b/src/boards/datalatch.c index 09a0da6..32d3d92 100644 --- a/src/boards/datalatch.c +++ b/src/boards/datalatch.c @@ -507,53 +507,6 @@ void Mapper538_Init(CartInfo *info) { info->Power = M538Power; } -/* ------------------ A65AS --------------------------- */ - -/* actually, there is two cart in one... First have extra mirroring - * mode (one screen) and 32K bankswitching, second one have only - * 16 bankswitching mode and normal mirroring... But there is no any - * correlations between modes and they can be used in one mapper code. - * - * Submapper 0 - 3-in-1 (N068) - * Submapper 0 - 3-in-1 (N080) - * Submapper 1 - 4-in-1 (JY-066) - */ - -static int A65ASsubmapper; -static void BMCA65ASSync(void) { - if (latche & 0x40) - setprg32(0x8000, (latche >> 1) & 0x0F); - else { - if (A65ASsubmapper == 1) { - setprg16(0x8000, ((latche & 0x30) >> 1) | (latche & 7)); - setprg16(0xC000, ((latche & 0x30) >> 1) | 7); - } else { - setprg16(0x8000, latche & 0x0F); - setprg16(0xC000, latche & 0x0F | 7); - } - } - setchr8(0); - if (latche & 0x80) - setmirror(MI_0 + (((latche >> 5) & 1))); - else { - if (A65ASsubmapper == 1) - setmirror(latche &0x08? MI_H: MI_V); - else - setmirror(latche &0x20? MI_H: MI_V); - } -} - -void BMCA65AS_Reset() { - latche =0; - BMCA65ASSync(); -} - -void BMCA65AS_Init(CartInfo *info) { - A65ASsubmapper = info->submapper; - info->Reset = BMCA65AS_Reset; - Latch_Init(info, BMCA65ASSync, 0, 0x8000, 0xFFFF, 0, 0); -} - /*------------------ BMC-11160 ---------------------------*/ /* Simple BMC discrete mapper by TXC */ diff --git a/src/ines.c b/src/ines.c index 79a2696..bab8f75 100644 --- a/src/ines.c +++ b/src/ines.c @@ -734,7 +734,7 @@ INES_BOARD_BEGIN() INES_BOARD( "YY860417C", 281, Mapper281_Init ) INES_BOARD( "860224C", 282, Mapper282_Init ) INES_BOARD( "GS-2004/GS-2013", 283, Mapper283_Init ) - INES_BOARD( "A65AS", 285, BMCA65AS_Init ) + INES_BOARD( "A65AS", 285, Mapper285_Init ) INES_BOARD( "BS-5", 286, BMCBS5_Init ) INES_BOARD( "411120-C, 811120-C", 287, BMC411120C_Init ) INES_BOARD( "GKCX1", 288, Mapper288_Init ) @@ -960,6 +960,7 @@ INES_BOARD_BEGIN() INES_BOARD( "ET-156", 580, Mapper580_Init ) INES_BOARD( "ET-82", 581, Mapper581_Init ) INES_BOARD( "8203", 583, Mapper583_Init ) + INES_BOARD( "ST-32", 584, Mapper584_Init ) INES_BOARD( "FE-01-1", 585, Mapper585_Init ) INES_BOARD( "HN-02", 586, Mapper586_Init ) INES_BOARD( "3355", 587, Mapper587_Init ) diff --git a/src/ines.h b/src/ines.h index 2a33021..ee54f1d 100644 --- a/src/ines.h +++ b/src/ines.h @@ -425,6 +425,7 @@ void Mapper579_Init(CartInfo *); void Mapper580_Init(CartInfo *); void Mapper581_Init(CartInfo *); void Mapper583_Init(CartInfo *); +void Mapper584_Init(CartInfo *); void Mapper585_Init(CartInfo *); void Mapper586_Init(CartInfo *); void Mapper587_Init(CartInfo *); diff --git a/src/unif.c b/src/unif.c index a022ec8..7260b1e 100644 --- a/src/unif.c +++ b/src/unif.c @@ -437,7 +437,7 @@ static BMAPPING bmap[] = { { "8237", 215, UNL8237_Init, 0 }, { "8237A", 215, UNL8237A_Init, 0 }, { "830118C", 348, BMC830118C_Init, 0 }, - { "A65AS", 285, BMCA65AS_Init, 0 }, + { "A65AS", 285, Mapper285_Init, 0 }, { "AB-G1L", 428, Mapper428_Init, 0 }, { "WELL-NO-DG450", 428, Mapper428_Init, 0 }, { "TF2740", 428, Mapper428_Init, 0 }, diff --git a/src/unif.h b/src/unif.h index 353235a..4a07fe4 100644 --- a/src/unif.h +++ b/src/unif.h @@ -30,7 +30,7 @@ void BMC411120C_Init(CartInfo *info); void BMC64in1nr_Init(CartInfo *info); void BMC810544CA1_Init(CartInfo *info); void BMC830118C_Init(CartInfo *info); -void BMCA65AS_Init(CartInfo *info); +void Mapper285_Init(CartInfo *info); void BMCBS5_Init(CartInfo *info); void BMCD1038_Init(CartInfo *info); void BMCFK23CA_Init(CartInfo *info); From 0b9c4d9fcd9a3e33ef5eb1d3f4fd68d9d271f64a Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 13:45:32 +0200 Subject: [PATCH 036/109] Add mapper 577. --- src/boards/577.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 54 insertions(+) create mode 100644 src/boards/577.c diff --git a/src/boards/577.c b/src/boards/577.c new file mode 100644 index 0000000..b2e0502 --- /dev/null +++ b/src/boards/577.c @@ -0,0 +1,52 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static uint8 pad; + +static DECLFR(readOB) { + return X.DB; +} + +static void sync () { + setprg16(0x8000, Latch_address); + setprg16(0xC000, Latch_address); + SetReadHandler(0x8000, 0xFFFF, Latch_address &pad &0x30? readOB: CartBR); + setchr8(Latch_address >>1); +} + +static void power() { + pad = 0; + Latch_power(); +} + +static void reset() { + pad += 0x10; + Latch_clear(); +} + +void Mapper577_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/ines.c b/src/ines.c index bab8f75..2607ef0 100644 --- a/src/ines.c +++ b/src/ines.c @@ -955,6 +955,7 @@ INES_BOARD_BEGIN() INES_BOARD( "9052", 570, Mapper570_Init ) INES_BOARD( "F-648", 572, Mapper572_Init ) INES_BOARD( "5068", 573, Mapper573_Init ) + INES_BOARD( "KN-29", 577, Mapper577_Init ) INES_BOARD( "910610", 578, Mapper578_Init ) INES_BOARD( "T-215", 579, Mapper579_Init ) INES_BOARD( "ET-156", 580, Mapper580_Init ) diff --git a/src/ines.h b/src/ines.h index ee54f1d..7b899d4 100644 --- a/src/ines.h +++ b/src/ines.h @@ -420,6 +420,7 @@ void Mapper567_Init(CartInfo *); void Mapper570_Init(CartInfo *); void Mapper572_Init(CartInfo *); void Mapper573_Init(CartInfo *); +void Mapper577_Init(CartInfo *); void Mapper578_Init(CartInfo *); void Mapper579_Init(CartInfo *); void Mapper580_Init(CartInfo *); From 55e5d617600eea7d128ed41e403c4f4efcc0db49 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 13:53:00 +0200 Subject: [PATCH 037/109] Add mapper 576. --- src/boards/576.c | 37 +++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 39 insertions(+) create mode 100644 src/boards/576.c diff --git a/src/boards/576.c b/src/boards/576.c new file mode 100644 index 0000000..837b822 --- /dev/null +++ b/src/boards/576.c @@ -0,0 +1,37 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_address &0x100) { + setprg16(0x8000, Latch_address >>4); + setprg16(0xC000, Latch_address >>4); + } else + setprg32(0x8000, Latch_address >>5); + setchr8(Latch_address); + setmirror(Latch_address &0x200? MI_H: MI_V); +} + +void Mapper576_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/ines.c b/src/ines.c index 2607ef0..4c4868c 100644 --- a/src/ines.c +++ b/src/ines.c @@ -955,6 +955,7 @@ INES_BOARD_BEGIN() INES_BOARD( "9052", 570, Mapper570_Init ) INES_BOARD( "F-648", 572, Mapper572_Init ) INES_BOARD( "5068", 573, Mapper573_Init ) + INES_BOARD( "J-2096", 576, Mapper576_Init ) INES_BOARD( "KN-29", 577, Mapper577_Init ) INES_BOARD( "910610", 578, Mapper578_Init ) INES_BOARD( "T-215", 579, Mapper579_Init ) diff --git a/src/ines.h b/src/ines.h index 7b899d4..f342e56 100644 --- a/src/ines.h +++ b/src/ines.h @@ -420,6 +420,7 @@ void Mapper567_Init(CartInfo *); void Mapper570_Init(CartInfo *); void Mapper572_Init(CartInfo *); void Mapper573_Init(CartInfo *); +void Mapper576_Init(CartInfo *); void Mapper577_Init(CartInfo *); void Mapper578_Init(CartInfo *); void Mapper579_Init(CartInfo *); From 3ebde99916e6c5f790d63ebe768cbed6189a491e Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 13:55:13 +0200 Subject: [PATCH 038/109] Add mapper 239. --- src/boards/239.c | 38 ++++++++++++++++++++++++++++++++++++++ src/ines.c | 2 +- src/ines.h | 1 + 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/boards/239.c diff --git a/src/boards/239.c b/src/boards/239.c new file mode 100644 index 0000000..72e1192 --- /dev/null +++ b/src/boards/239.c @@ -0,0 +1,38 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_address &0x04) + setprg32(0x8000, Latch_address >>1); + else { + setprg16(0x8000, Latch_address); + setprg16(0xC000, Latch_address); + } + setchr8(Latch_address); + setmirror(Latch_address &0x10? MI_H: MI_V); +} + +void Mapper239_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/ines.c b/src/ines.c index 4c4868c..2774856 100644 --- a/src/ines.c +++ b/src/ines.c @@ -692,7 +692,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Realtec 8031/8155/8099/8106", 236, Mapper236_Init ) INES_BOARD( "Teletubbies / Y2K", 237, Mapper237_Init ) INES_BOARD( "UNL6035052", 238, UNL6035052_Init ) -/* INES_BOARD( "", 239, Mapper239_Init ) */ + INES_BOARD( "OK-043", 239, Mapper239_Init ) INES_BOARD( "", 240, Mapper240_Init ) INES_BOARD( "", 241, Mapper241_Init ) INES_BOARD( "43272", 242, Mapper242_Init ) diff --git a/src/ines.h b/src/ines.h index f342e56..9c5f9ba 100644 --- a/src/ines.h +++ b/src/ines.h @@ -236,6 +236,7 @@ void Mapper234_Init(CartInfo *); void Mapper235_Init(CartInfo *); void Mapper236_Init(CartInfo *); void Mapper237_Init(CartInfo *); +void Mapper239_Init(CartInfo *); void Mapper240_Init(CartInfo *); void Mapper241_Init(CartInfo *); void Mapper242_Init(CartInfo *); From 68cb735a6a4fe8beddcd0322b3d9a762fc4e0348 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 13:57:52 +0200 Subject: [PATCH 039/109] Add mapper 575. --- src/boards/575.c | 38 ++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 40 insertions(+) create mode 100644 src/boards/575.c diff --git a/src/boards/575.c b/src/boards/575.c new file mode 100644 index 0000000..b652f5c --- /dev/null +++ b/src/boards/575.c @@ -0,0 +1,38 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if ((Latch_address &0x06) == 0x06) + setprg32(0x8000, Latch_address >>1); + else { + setprg16(0x8000, Latch_address); + setprg16(0xC000, Latch_address); + } + setchr8(Latch_address); + setmirror(Latch_address &0x08? MI_H: MI_V); +} + +void Mapper575_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/ines.c b/src/ines.c index 2774856..e01debc 100644 --- a/src/ines.c +++ b/src/ines.c @@ -955,6 +955,7 @@ INES_BOARD_BEGIN() INES_BOARD( "9052", 570, Mapper570_Init ) INES_BOARD( "F-648", 572, Mapper572_Init ) INES_BOARD( "5068", 573, Mapper573_Init ) + INES_BOARD( "W-03", 575, Mapper575_Init ) INES_BOARD( "J-2096", 576, Mapper576_Init ) INES_BOARD( "KN-29", 577, Mapper577_Init ) INES_BOARD( "910610", 578, Mapper578_Init ) diff --git a/src/ines.h b/src/ines.h index 9c5f9ba..ee24aae 100644 --- a/src/ines.h +++ b/src/ines.h @@ -421,6 +421,7 @@ void Mapper567_Init(CartInfo *); void Mapper570_Init(CartInfo *); void Mapper572_Init(CartInfo *); void Mapper573_Init(CartInfo *); +void Mapper575_Init(CartInfo *); void Mapper576_Init(CartInfo *); void Mapper577_Init(CartInfo *); void Mapper578_Init(CartInfo *); From 25b3ee1ad70403ee1e66d59c37d81c0f2c605c58 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 14:08:49 +0200 Subject: [PATCH 040/109] Add mapper 574. --- src/boards/574.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 48 insertions(+) create mode 100644 src/boards/574.c diff --git a/src/boards/574.c b/src/boards/574.c new file mode 100644 index 0000000..089a73a --- /dev/null +++ b/src/boards/574.c @@ -0,0 +1,46 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_address &0x40) /* AOROM */ + setprg32(0x8000, Latch_address >>2 &~0x07 | Latch_data &0x07); + else + if (Latch_address &0x20) /* ANROM */ + setprg32(0x8000, Latch_address >>2 &~0x03 | Latch_data &0x03); + else /* NROM-256 */ + setprg32(0x8000, Latch_address >>2 &~0x03 | Latch_address &0x03); + setchr8(0); + if (Latch_address &0x60) /* AxROM */ + setmirror(Latch_data &0x10? MI_1: MI_0); + else + setmirror(Latch_data &0x10? MI_H: MI_V); +} + +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { /* After the lock bit is set, only update the data bits and the lowest two address bits. */ + if (Latch_address &0x80) *newAddress = Latch_address &~0x03 | *newAddress &0x03; +} + +void Mapper574_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); + info->Reset = Latch_clear; +} diff --git a/src/ines.c b/src/ines.c index e01debc..fa7dccf 100644 --- a/src/ines.c +++ b/src/ines.c @@ -955,6 +955,7 @@ INES_BOARD_BEGIN() INES_BOARD( "9052", 570, Mapper570_Init ) INES_BOARD( "F-648", 572, Mapper572_Init ) INES_BOARD( "5068", 573, Mapper573_Init ) + INES_BOARD( "FC-40", 574, Mapper574_Init ) INES_BOARD( "W-03", 575, Mapper575_Init ) INES_BOARD( "J-2096", 576, Mapper576_Init ) INES_BOARD( "KN-29", 577, Mapper577_Init ) diff --git a/src/ines.h b/src/ines.h index ee24aae..30c073c 100644 --- a/src/ines.h +++ b/src/ines.h @@ -421,6 +421,7 @@ void Mapper567_Init(CartInfo *); void Mapper570_Init(CartInfo *); void Mapper572_Init(CartInfo *); void Mapper573_Init(CartInfo *); +void Mapper574_Init(CartInfo *); void Mapper575_Init(CartInfo *); void Mapper576_Init(CartInfo *); void Mapper577_Init(CartInfo *); From eca2c72eee88b8a642a722f9841affcd6a8a3ef0 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 14:12:08 +0200 Subject: [PATCH 041/109] Add mapper 213. Was a duplicate of 58 before, now a new mapper. --- src/boards/213.c | 37 +++++++++++++++++++++++++++++++++++++ src/boards/addrlatch.c | 4 ---- src/ines.c | 2 +- 3 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 src/boards/213.c diff --git a/src/boards/213.c b/src/boards/213.c new file mode 100644 index 0000000..ac48393 --- /dev/null +++ b/src/boards/213.c @@ -0,0 +1,37 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_address &0x08) { + setprg16(0x8000, Latch_address >>1 &~1 | Latch_address &1); + setprg16(0xC000, Latch_address >>1 &~1 | Latch_address &1); + } else + setprg32(0x8000, Latch_address >>2); + setchr8(Latch_address >>1 &~1 | Latch_address &1); + setmirror(Latch_address &0x02? MI_H: MI_V); +} + +void Mapper213_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c index d2bb821..bf2ebb8 100644 --- a/src/boards/addrlatch.c +++ b/src/boards/addrlatch.c @@ -346,10 +346,6 @@ void Mapper212_Init(CartInfo *info) { Latch_Init(info, M212Sync, M212Read, 0x0000, 0x8000, 0xFFFF, 0); } -/*------------------ Map 213 ---------------------------*/ - -/* SEE MAPPER 58 */ - /*------------------ Map 214 ---------------------------*/ static void M214Sync(void) { diff --git a/src/ines.c b/src/ines.c index fa7dccf..04431f2 100644 --- a/src/ines.c +++ b/src/ines.c @@ -666,7 +666,7 @@ INES_BOARD_BEGIN() INES_BOARD( "", 210, Mapper210_Init ) INES_BOARD( "HUMMER/JY BOARD", 211, Mapper211_Init ) INES_BOARD( "", 212, Mapper212_Init ) - INES_BOARD( "", 213, Mapper58_Init ) /* in mapper 58 */ + INES_BOARD( "EJ-3003/820428-C", 213, Mapper213_Init ) INES_BOARD( "", 214, Mapper214_Init ) INES_BOARD( "UNL-8237", 215, UNL8237_Init ) INES_BOARD( "", 216, Mapper216_Init ) From 890da4f859d0be9042d2e41ebb76e04dbbf23676 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 14:30:55 +0200 Subject: [PATCH 042/109] Add mapper 571. --- src/boards/571.c | 72 ++++++++++++++++++++++++++++++++++++++ src/boards/asic_vrc2and4.c | 5 +++ src/boards/asic_vrc2and4.h | 1 + src/ines.c | 1 + src/ines.h | 1 + 5 files changed, 80 insertions(+) create mode 100644 src/boards/571.c diff --git a/src/boards/571.c b/src/boards/571.c new file mode 100644 index 0000000..c759426 --- /dev/null +++ b/src/boards/571.c @@ -0,0 +1,72 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_vrc2and4.h" + +static uint8 reg; + +static void sync () { + int prgAND = reg &0x10? 0x1F: 0x0F; + int chrAND = reg &0x10? 0xFF: 0x7F; + int prgOR = reg <<1; + int chrOR = reg <<4; + if (reg &0x20) + VRC24_syncPRG(prgAND, prgOR &~prgAND); + else + if (reg &0x6) + setprg32(0x8000, reg >>1); + else { + setprg16(0x8000, reg); + setprg16(0xC000, reg); + } + VRC24_syncCHR(chrAND, chrOR &~chrAND); + VRC24_syncMirror(); + if (reg &0x10) + VRC24_reconfigure(8, 4); + else + VRC24_reconfigure(4, 8); +} + +static DECLFW (writeReg) { + if (~reg &0x01) { + reg = A &0xFF; + sync(); + } +} + +static void reset () { + reg = 0; + sync(); +} + +static void power () { + reg = 0; + VRC24_power(); +} + +void Mapper571_Init (CartInfo *info) { + VRC4_init(info, sync, 4, 8, 1, NULL, NULL, NULL, writeReg, NULL); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/asic_vrc2and4.c b/src/boards/asic_vrc2and4.c index 16166bf..6dfe81d 100644 --- a/src/boards/asic_vrc2and4.c +++ b/src/boards/asic_vrc2and4.c @@ -239,6 +239,11 @@ static void VRC4_configure (void (*sync)(), int A0, int A1, uint8 useRepeatBit, VRC24_cbExternalSelect = externalSelect; } +void VRC24_reconfigure(int A0, int A1) { + VRC24_A0 = A0; + VRC24_A1 = A1; +} + void VRC2_activate (uint8 clear, void (*sync)(), int A0, int A1, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) { VRC2_configure(sync, A0, A1, prg, chr, read, write); VRC24_setHandlers(); diff --git a/src/boards/asic_vrc2and4.h b/src/boards/asic_vrc2and4.h index c5ae48c..ed82969 100644 --- a/src/boards/asic_vrc2and4.h +++ b/src/boards/asic_vrc2and4.h @@ -37,6 +37,7 @@ void VRC24_syncMirror (); DECLFW(VRC24_writeReg); void FP_FASTAPASS(1) VRC4_cpuCycle(int); +void VRC24_reconfigure (int, int); void VRC2_activate (uint8, void (*)(), int, int, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*))); void VRC4_activate (uint8, void (*)(), int, int, uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*)), DECLFW((*))); void VRC2_addExState (); diff --git a/src/ines.c b/src/ines.c index 04431f2..75ec390 100644 --- a/src/ines.c +++ b/src/ines.c @@ -953,6 +953,7 @@ INES_BOARD_BEGIN() INES_BOARD( "J-2020", 563, Mapper563_Init ) INES_BOARD( "Top Ten Variety (SF III)", 567, Mapper567_Init ) INES_BOARD( "9052", 570, Mapper570_Init ) + INES_BOARD( "JC-011", 571, Mapper571_Init ) INES_BOARD( "F-648", 572, Mapper572_Init ) INES_BOARD( "5068", 573, Mapper573_Init ) INES_BOARD( "FC-40", 574, Mapper574_Init ) diff --git a/src/ines.h b/src/ines.h index 30c073c..172ae2b 100644 --- a/src/ines.h +++ b/src/ines.h @@ -419,6 +419,7 @@ void Mapper561_562_Init(CartInfo *); void Mapper563_Init(CartInfo *); void Mapper567_Init(CartInfo *); void Mapper570_Init(CartInfo *); +void Mapper571_Init(CartInfo *); void Mapper572_Init(CartInfo *); void Mapper573_Init(CartInfo *); void Mapper574_Init(CartInfo *); From 788c9e45ab522512f1d299b0f21d42bccdebe9b5 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 14:43:27 +0200 Subject: [PATCH 043/109] Add mapper 569. --- src/boards/569.c | 70 ++++++++++++++++++++++++++++++++++++++++++ src/boards/asic_mmc3.c | 2 +- src/boards/asic_mmc3.h | 1 + src/ines.c | 1 + src/ines.h | 1 + 5 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 src/boards/569.c diff --git a/src/boards/569.c b/src/boards/569.c new file mode 100644 index 0000000..6d21d4e --- /dev/null +++ b/src/boards/569.c @@ -0,0 +1,70 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync() { + int chrAND = reg &0x04? 0x1FF: reg &0x02? 0xFF: 0x7F; + int chrOR = reg <<7; + MMC3_syncPRG(0x0F, reg <<4 &~0x0F); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static int getPRGBank(uint8 bank) { + if (reg &0x08) { + return MMC3_getPRGBank(0) &~3 | bank &3; + } else + return MMC3_getPRGBank(bank); +} + +static int getCHRBank(uint8 bank) { + if (reg &0x04) + return MMC3_getCHRBank(bank &6 | bank >>1 &1) <<1 | bank &1; + else + return MMC3_getCHRBank(bank); +} + +static DECLFW(writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset() { + reg = 0; + MMC3_clear(); +} + +static void power() { + reg = 0; + MMC3_power(); +} + +void Mapper569_Init(CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_SHARP, getPRGBank, getCHRBank, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/asic_mmc3.c b/src/boards/asic_mmc3.c index 3786dba..d7267ce 100644 --- a/src/boards/asic_mmc3.c +++ b/src/boards/asic_mmc3.c @@ -115,7 +115,7 @@ DECLFW(MMC3_writeReg) { if (A <0xC000) MMC3_cbSync(); } -static void MMC3_clear () { +void MMC3_clear () { MMC3_reg[0] = 0; MMC3_reg[1] = 2; MMC3_reg[2] = 4; MMC3_reg[3] = 5; MMC3_reg[4] = 6; MMC3_reg[5] = 7; MMC3_reg[6] = 0; MMC3_reg[7] = 1; MMC3_index = MMC3_mirroring = MMC3_wramControl = MMC3_reloadValue = MMC3_reloadRequest = MMC3_irqEnable = MMC3_counter = 0; MMC3_cbSync(); diff --git a/src/boards/asic_mmc3.h b/src/boards/asic_mmc3.h index 210940d..3e4527b 100644 --- a/src/boards/asic_mmc3.h +++ b/src/boards/asic_mmc3.h @@ -36,6 +36,7 @@ void MMC3_syncCHR (int, int); void MMC3_syncMirror (); void MMC3_clockCounter (); DECLFW (MMC3_writeReg); +void MMC3_clear (); void MMC3_activate (uint8, void (*)(), uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*))); void MMC3_addExState(); void MMC3_restore (int); diff --git a/src/ines.c b/src/ines.c index 75ec390..7bf3342 100644 --- a/src/ines.c +++ b/src/ines.c @@ -952,6 +952,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Venus Turbo Game Doctor", 562, Mapper561_562_Init ) INES_BOARD( "J-2020", 563, Mapper563_Init ) INES_BOARD( "Top Ten Variety (SF III)", 567, Mapper567_Init ) + INES_BOARD( "820315-C", 569, Mapper569_Init ) INES_BOARD( "9052", 570, Mapper570_Init ) INES_BOARD( "JC-011", 571, Mapper571_Init ) INES_BOARD( "F-648", 572, Mapper572_Init ) diff --git a/src/ines.h b/src/ines.h index 172ae2b..5f52377 100644 --- a/src/ines.h +++ b/src/ines.h @@ -418,6 +418,7 @@ void Mapper559_Init(CartInfo *); void Mapper561_562_Init(CartInfo *); void Mapper563_Init(CartInfo *); void Mapper567_Init(CartInfo *); +void Mapper569_Init(CartInfo *); void Mapper570_Init(CartInfo *); void Mapper571_Init(CartInfo *); void Mapper572_Init(CartInfo *); From c124b6bc6d9608d901fb3775811222a9ee3873b4 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 21:03:14 +0200 Subject: [PATCH 044/109] Add mapper 568. --- src/boards/568.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++ src/boards/578.c | 2 +- src/ines.c | 1 + src/ines.h | 1 + 4 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 src/boards/568.c diff --git a/src/boards/568.c b/src/boards/568.c new file mode 100644 index 0000000..bec0ca5 --- /dev/null +++ b/src/boards/568.c @@ -0,0 +1,75 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; +static uint8 pad; + +static DECLFR (readPad) { + return CartBR(A &~0xF | pad &0xF); +} + +static void sync () { + int prgAND = reg &0x20? 0x1F: 0x0F; + int chrAND = reg &0x20? 0xFF: 0x7F; + int prgOR = reg <<1; + int chrOR = reg <<4; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); + SetReadHandler(0x8000, 0xFFFF, reg &0x40? readPad: CartBR); +} + +static int getPRGBank (uint8 bank) { + if (reg &0x02) { + int mask = reg &0x01? 3: 1; + return MMC3_getPRGBank(0) &~mask | bank &mask; + } else + return MMC3_getPRGBank(bank); +} + +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset () { + reg = 0; + pad++; + MMC3_clear(); +} + +static void power () { + reg = 0; + pad = 0; + MMC3_power(); +} + +void Mapper568_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, getPRGBank, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/boards/578.c b/src/boards/578.c index c70a936..a45954e 100644 --- a/src/boards/578.c +++ b/src/boards/578.c @@ -42,7 +42,7 @@ static DECLFW(writeReg) { static void reset() { reg = 0; - sync(); + MMC3_clear(); } static void power() { diff --git a/src/ines.c b/src/ines.c index 7bf3342..e5b2eb6 100644 --- a/src/ines.c +++ b/src/ines.c @@ -952,6 +952,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Venus Turbo Game Doctor", 562, Mapper561_562_Init ) INES_BOARD( "J-2020", 563, Mapper563_Init ) INES_BOARD( "Top Ten Variety (SF III)", 567, Mapper567_Init ) + INES_BOARD( "T-227", 568, Mapper568_Init ) INES_BOARD( "820315-C", 569, Mapper569_Init ) INES_BOARD( "9052", 570, Mapper570_Init ) INES_BOARD( "JC-011", 571, Mapper571_Init ) diff --git a/src/ines.h b/src/ines.h index 5f52377..225df50 100644 --- a/src/ines.h +++ b/src/ines.h @@ -418,6 +418,7 @@ void Mapper559_Init(CartInfo *); void Mapper561_562_Init(CartInfo *); void Mapper563_Init(CartInfo *); void Mapper567_Init(CartInfo *); +void Mapper568_Init(CartInfo *); void Mapper569_Init(CartInfo *); void Mapper570_Init(CartInfo *); void Mapper571_Init(CartInfo *); From 5c3fa225ee51665116f73958bf2e6ac19e7218e5 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 21:15:43 +0200 Subject: [PATCH 045/109] Mapper 460: Rewrite and correct submapper-specific solder pad menu selection. --- src/boards/460.c | 114 ++++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 56 deletions(-) diff --git a/src/boards/460.c b/src/boards/460.c index 02d94e0..f09ae7e 100644 --- a/src/boards/460.c +++ b/src/boards/460.c @@ -1,7 +1,7 @@ /* FCEUmm - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2022 + * Copyright (C) 2020 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,79 +16,81 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * */ + #include "mapinc.h" -#include "mmc3.h" +#include "asic_mmc3.h" -static uint8 *CHRRAM =NULL; +static uint8 submapper; +static uint8 reg; +static uint8 pad; +static uint8 *CHRRAM = NULL; -static DECLFR(Mapper460_ReadOB) -{ - return X.DB; +static DECLFR (readPad) { + return CartBR(A &~3 | pad &3); } -static void Mapper460_PRGWrap(uint32 A, uint8 V) { - int prgAND =0x0F; - int prgOR =EXPREGS[0] <<4; - if (EXPREGS[0] &0x38) { /* Menu selection by selectively connecting CPU D7 to reg or not */ - if (~A &0x4000) { - setprg8(A, (EXPREGS[0] &0x10? ~2: ~0) &V &prgAND | prgOR &~prgAND); - setprg8(A |0x4000, (EXPREGS[0] &0x10? 2: 0) |V &prgAND | prgOR &~prgAND); - } - } else - setprg8(A, V &prgAND | prgOR &~prgAND); - - /* Menu selection by selectively connecting reg's D7 to PRG /CE or not */ - if (EXPREGS[0] &0x80 && EXPREGS[1] &1) - SetReadHandler(0x8000, 0xFFFF, Mapper460_ReadOB); +static void sync () { + MMC3_syncPRG(0x0F, reg <<4 &~0x0F); + if (reg &0x04) + MMC3_syncCHR(0x1FF, 0x000); else - SetReadHandler(0x8000, 0xFFFF, CartBR); -} - -static void Mapper460_CHRWrap(uint32 A, uint8 V) { - if (EXPREGS[0] &0x04) { - setchr2(0x0000, DRegBuf[0] &0xFE); - setchr2(0x0800, DRegBuf[0] |0x01); - setchr2(0x1000, DRegBuf[2]); - setchr2(0x1800, DRegBuf[5]); - } else setchr8r(0x10, 0); + MMC3_syncMirror(); + SetReadHandler(0x8000, 0xFFFF, submapper == 0 && reg &0x80 || submapper == 1 && reg &0x20? readPad: CartBR); } -static DECLFW(Mapper460_WriteExtra) { - if (A001B &0x80 && ~A001B &0x40) EXPREGS[0] =A &0xFF; - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); +static int getPRGBank (uint8 bank) { + if (reg &0x08) { + int mask = reg &0x10? 3: 1; + return MMC3_getPRGBank(bank &1) &~mask | bank &mask; + } else + return MMC3_getPRGBank(bank); } -static void Mapper460_Reset(void) { - EXPREGS[0] =0; - EXPREGS[1]++; - MMC3RegReset(); +static int getCHRBank (uint8 bank) { + if (reg &0x04) + return MMC3_getCHRBank(bank &6 | bank >>1 &1) <<1 | bank &1; + else + return MMC3_getCHRBank(bank); } -static void Mapper460_Power(void) { - EXPREGS[0] =0; - EXPREGS[1] =0; - GenMMC3Power(); - SetWriteHandler(0x6000, 0x7FFF, Mapper460_WriteExtra); +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); } -static void Mapper460_close(void) { - if (CHRRAM) FCEU_gfree(CHRRAM); - CHRRAM =NULL; +static void reset () { + reg = 0; + pad++; + MMC3_clear(); } -void Mapper460_Init(CartInfo *info) { - GenMMC3_Init(info, 128, 512, 0, 0); - cwrap = Mapper460_CHRWrap; - pwrap = Mapper460_PRGWrap; - info->Power = Mapper460_Power; - info->Reset = Mapper460_Reset; - info->Close = Mapper460_close; - AddExState(EXPREGS, 2, 0, "EXPR"); - - CHRRAM =(uint8 *)FCEU_gmalloc(8192); +static void power () { + reg = 0; + pad = 0; + MMC3_power(); +} + +static void close () { + if (CHRRAM) { + FCEU_gfree(CHRRAM); + CHRRAM = NULL; + } +} + +void Mapper460_Init (CartInfo *info) { + submapper = info->submapper; + MMC3_init(info, sync, MMC3_TYPE_SHARP, getPRGBank, getCHRBank, NULL, writeReg); + info->Power = power; + info->Reset = reset; + info->Close = close; + AddExState(®, 1, 0, "EXPR"); + AddExState(®, 1, 0, "DIPS"); + + CHRRAM = (uint8 *)FCEU_gmalloc(8192); SetupCartCHRMapping(0x10, CHRRAM, 8192, 1); AddExState(CHRRAM, 8192, 0, "CRAM"); } From 8af42518f72ab435edbbc93523b2752c7460072f Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 21:20:20 +0200 Subject: [PATCH 046/109] Add mapper 566. --- src/boards/566.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 63 insertions(+) create mode 100644 src/boards/566.c diff --git a/src/boards/566.c b/src/boards/566.c new file mode 100644 index 0000000..592fd11 --- /dev/null +++ b/src/boards/566.c @@ -0,0 +1,61 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync () { + int prgAND = reg &0x04? 0x0F: 0x1F; + int chrAND = reg &0x02? 0x7F: 0xFF; + int prgOR = reg <<4 &0x10 | reg <<2 &0x20 | reg <<1 &0xC0; + int chrOR = reg <<7 &0x80 | reg <<4 &0x700; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + if (reg &0x80) + setmirror(MMC3_getCHRBank(0) &0x80? MI_1: MI_0); + else + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +void Mapper566_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/ines.c b/src/ines.c index e5b2eb6..b64cb24 100644 --- a/src/ines.c +++ b/src/ines.c @@ -951,6 +951,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Bung Super Game Doctor", 561, Mapper561_562_Init ) INES_BOARD( "Venus Turbo Game Doctor", 562, Mapper561_562_Init ) INES_BOARD( "J-2020", 563, Mapper563_Init ) + INES_BOARD( "ET-149", 566, Mapper566_Init ) INES_BOARD( "Top Ten Variety (SF III)", 567, Mapper567_Init ) INES_BOARD( "T-227", 568, Mapper568_Init ) INES_BOARD( "820315-C", 569, Mapper569_Init ) diff --git a/src/ines.h b/src/ines.h index 225df50..ed48f1d 100644 --- a/src/ines.h +++ b/src/ines.h @@ -417,6 +417,7 @@ void Mapper558_Init(CartInfo *); void Mapper559_Init(CartInfo *); void Mapper561_562_Init(CartInfo *); void Mapper563_Init(CartInfo *); +void Mapper566_Init(CartInfo *); void Mapper567_Init(CartInfo *); void Mapper568_Init(CartInfo *); void Mapper569_Init(CartInfo *); From e46914d42e12ab7e5bd5ef251d0a22b53797cbdf Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 21:24:00 +0200 Subject: [PATCH 047/109] Add mapper 537. Note that the UNIF dump of this mapper's JY-103 game has a strange bank order and will not run. --- src/boards/537.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 62 insertions(+) create mode 100644 src/boards/537.c diff --git a/src/boards/537.c b/src/boards/537.c new file mode 100644 index 0000000..e628180 --- /dev/null +++ b/src/boards/537.c @@ -0,0 +1,60 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +/* The UNIF dump of "(JY-103) 3-in-1" (JY4M4 MAPR) has a strange bank order and will not run with this emulation. */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg[2]; + +static void sync () { + int prgAND = reg[0] &0x80? 0x0F: 0x1F; + int chrAND = 0xFF; + int prgOR = reg[0] >>1 &0x20 | reg[1] <<4 &0x10; + int chrOR = reg[0] <<2 &0x100; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + reg[A &1] = V; + sync(); +} + +static void reset () { + reg[0] = reg[1] = 0; + MMC3_clear(); +} + +static void power () { + reg[0] = reg[1] = 0; + MMC3_power(); +} + +void Mapper537_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(reg, 2, 0, "EXPR"); +} diff --git a/src/ines.c b/src/ines.c index b64cb24..490e7a5 100644 --- a/src/ines.c +++ b/src/ines.c @@ -933,6 +933,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Sachen 3014", 533, Mapper533_Init ) INES_BOARD( "NJ064", 534, Mapper534_Init ) INES_BOARD( "LH53", 535, LH53_Init ) + INES_BOARD( "JY4M4", 537, Mapper537_Init ) INES_BOARD( "60-1064-16L (FDS)", 538, Mapper538_Init ) INES_BOARD( "Kid Ikarus (FDS)", 539, Mapper539_Init ) INES_BOARD( "82112C", 540, Mapper540_Init ) diff --git a/src/ines.h b/src/ines.h index ed48f1d..8a0ca24 100644 --- a/src/ines.h +++ b/src/ines.h @@ -401,6 +401,7 @@ void Mapper523_Init(CartInfo *); void Mapper528_Init(CartInfo *); void Mapper533_Init(CartInfo *); void Mapper534_Init(CartInfo *); +void Mapper537_Init(CartInfo *); void Mapper538_Init(CartInfo *); void Mapper539_Init(CartInfo *); void Mapper540_Init(CartInfo *); From 094a28093fbd59d7520de211e0bc67fb8f2d625b Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 21:27:32 +0200 Subject: [PATCH 048/109] Add mapper 536. --- src/boards/536.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 69 insertions(+) create mode 100644 src/boards/536.c diff --git a/src/boards/536.c b/src/boards/536.c new file mode 100644 index 0000000..935e777 --- /dev/null +++ b/src/boards/536.c @@ -0,0 +1,67 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +/* The UNIF dump of "(JY-103) 3-in-1" (JY4M4 MAPR) has a strange bank order and will not run with this emulation. */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg[2]; + +static void sync () { + int prg = reg[0] &0x1F | reg[0] >>1 &0x20; + if (reg[0] &0x80) + MMC3_syncPRG(0x0F, prg <<2); + else + if (reg[0] &0x20) + setprg32(0x8000, prg >>1); + else { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } + setchr8(0); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + reg[A &1] = V; + sync(); +} + +static void reset () { + reg[0] = 0x60; + reg[1] = 0x00; + MMC3_clear(); +} + +static void power () { + reg[0] = 0x60; + reg[1] = 0x00; + MMC3_power(); +} + +void Mapper536_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(reg, 2, 0, "EXPR"); +} diff --git a/src/ines.c b/src/ines.c index 490e7a5..c44aee7 100644 --- a/src/ines.c +++ b/src/ines.c @@ -933,6 +933,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Sachen 3014", 533, Mapper533_Init ) INES_BOARD( "NJ064", 534, Mapper534_Init ) INES_BOARD( "LH53", 535, LH53_Init ) + INES_BOARD( "N42S-2", 536, Mapper536_Init ) INES_BOARD( "JY4M4", 537, Mapper537_Init ) INES_BOARD( "60-1064-16L (FDS)", 538, Mapper538_Init ) INES_BOARD( "Kid Ikarus (FDS)", 539, Mapper539_Init ) diff --git a/src/ines.h b/src/ines.h index 8a0ca24..096eee4 100644 --- a/src/ines.h +++ b/src/ines.h @@ -401,6 +401,7 @@ void Mapper523_Init(CartInfo *); void Mapper528_Init(CartInfo *); void Mapper533_Init(CartInfo *); void Mapper534_Init(CartInfo *); +void Mapper536_Init(CartInfo *); void Mapper537_Init(CartInfo *); void Mapper538_Init(CartInfo *); void Mapper539_Init(CartInfo *); From e4cf15709c515049f45a4ae83c26d237c4b66cea Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 21:31:39 +0200 Subject: [PATCH 049/109] Add mapper 511. --- src/boards/511.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 77 insertions(+) create mode 100644 src/boards/511.c diff --git a/src/boards/511.c b/src/boards/511.c new file mode 100644 index 0000000..3929975 --- /dev/null +++ b/src/boards/511.c @@ -0,0 +1,75 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; +static uint8 pad; + +static DECLFR (readPad) { + return CartBR(A &~0x3 | pad &0x3); +} + +static void sync () { + int prgAND = 0x0F; + int chrAND = 0xFF; + int prgOR = reg <<4; + int chrOR = reg <<7; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); + SetReadHandler(0x8000, 0xFFFF, reg &0x08? readPad: CartBR); +} + +static int getPRGBank (uint8 bank) { + if (reg &0x04) { + int mask = reg &0x02? 1: 3; + return MMC3_getPRGBank(bank &1) &~mask | bank &mask; + } else + return MMC3_getPRGBank(bank); +} + +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset () { + reg = 0; + pad++; + MMC3_clear(); +} + +static void power () { + reg = 0; + pad = 0; + MMC3_power(); +} + +void Mapper511_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, getPRGBank, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/ines.c b/src/ines.c index c44aee7..c962f42 100644 --- a/src/ines.c +++ b/src/ines.c @@ -915,6 +915,7 @@ INES_BOARD_BEGIN() INES_BOARD( "ET-170", 503, Mapper503_Init ) INES_BOARD( "K-3054", 504, Mapper504_Init ) INES_BOARD( "GA-009", 506, Mapper506_Init ) + INES_BOARD( "1n4148", 511, Mapper511_Init ) INES_BOARD( "SA-9602B", 513, SA9602B_Init ) INES_BOARD( "Brilliant Com Cocoma Pack",516, Mapper516_Init ) INES_BOARD( "DANCE2000", 518, UNLD2000_Init ) diff --git a/src/ines.h b/src/ines.h index 096eee4..0dcec82 100644 --- a/src/ines.h +++ b/src/ines.h @@ -395,6 +395,7 @@ void Mapper502_Init(CartInfo *); void Mapper503_Init(CartInfo *); void Mapper504_Init(CartInfo *); void Mapper506_Init(CartInfo *); +void Mapper511_Init(CartInfo *); void Mapper516_Init(CartInfo *); void Mapper520_Init(CartInfo *); void Mapper523_Init(CartInfo *); From e6d6c874dbf6464d717e4a49310833639f32376e Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 21:43:07 +0200 Subject: [PATCH 050/109] Add mapper 512. --- src/boards/512.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 87 insertions(+) create mode 100644 src/boards/512.c diff --git a/src/boards/512.c b/src/boards/512.c new file mode 100644 index 0000000..0645355 --- /dev/null +++ b/src/boards/512.c @@ -0,0 +1,85 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" +#include "wram.h" + +static uint8 reg; +static uint8 *CHRRAM = NULL; + +static void sync () { + MMC3_syncPRG(0x3F, 0x00); + MMC3_syncWRAM(0); + + if (reg &0x02) { + setchr4r(0x10, 0x0000, 0); + setchr4r(0x10, 0x1000, 0); + } else + MMC3_syncCHR(0xFF, 0x000); + + if (reg == 1) { /* The game uses six nametables - the two console-internal ones, plus four occupying the second half of 8 KiB CHR-RAM.*/ + setntamem(CHRptr[0x10] +0x1000, 1, 0); + setntamem(CHRptr[0x10] +0x1400, 1, 1); + setntamem(CHRptr[0x10] +0x1800, 1, 2); + setntamem(CHRptr[0x10] +0x1C00, 1, 3); + } else + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + if (A &0x100) { + reg = V; + sync(); + } +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); + SetWriteHandler(0x4020, 0x5FFF, writeReg); +} + +static void close () { + if (CHRRAM) { + FCEU_gfree(CHRRAM); + CHRRAM = NULL; + } +} + +void Mapper512_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, NULL); + WRAM_init(info, 8); + info->Power = power; + info->Reset = reset; + info->Close = close; + AddExState(®, 1, 0, "EXPR"); + + CHRRAM = (uint8 *)FCEU_gmalloc(8192); + SetupCartCHRMapping(0x10, CHRRAM, 8192, 1); + AddExState(CHRRAM, 8192, 0, "CRAM"); +} diff --git a/src/ines.c b/src/ines.c index c962f42..b987b4c 100644 --- a/src/ines.c +++ b/src/ines.c @@ -916,6 +916,7 @@ INES_BOARD_BEGIN() INES_BOARD( "K-3054", 504, Mapper504_Init ) INES_BOARD( "GA-009", 506, Mapper506_Init ) INES_BOARD( "1n4148", 511, Mapper511_Init ) + INES_BOARD( "Zhonggguo Daheng", 512, Mapper512_Init ) INES_BOARD( "SA-9602B", 513, SA9602B_Init ) INES_BOARD( "Brilliant Com Cocoma Pack",516, Mapper516_Init ) INES_BOARD( "DANCE2000", 518, UNLD2000_Init ) diff --git a/src/ines.h b/src/ines.h index 0dcec82..1297a22 100644 --- a/src/ines.h +++ b/src/ines.h @@ -396,6 +396,7 @@ void Mapper503_Init(CartInfo *); void Mapper504_Init(CartInfo *); void Mapper506_Init(CartInfo *); void Mapper511_Init(CartInfo *); +void Mapper512_Init(CartInfo *); void Mapper516_Init(CartInfo *); void Mapper520_Init(CartInfo *); void Mapper523_Init(CartInfo *); From 6d0a33654a4cfe72f754ebf4448506dc24ba7342 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 21:55:33 +0200 Subject: [PATCH 051/109] Add mapper 510. --- src/boards/510.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 65 insertions(+) create mode 100644 src/boards/510.c diff --git a/src/boards/510.c b/src/boards/510.c new file mode 100644 index 0000000..c0d0d70 --- /dev/null +++ b/src/boards/510.c @@ -0,0 +1,63 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" +#include "wram.h" + +static uint8 reg; + +static void sync () { + int prgAND = reg &0x20? 0x0F: 0x1F; + int chrAND = reg &0x01? 0xFF: 0x7F; + int prgOR = (reg &0x08? 0x020: 0x000) | (reg &0x40? 0x010: 0x000); + int chrOR = (reg &0x04? 0x100: 0x000) | (reg &0x02? 0x080: 0x000); + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncWRAM(0); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + if (reg == 0) { + reg = V; + sync(); + } +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +void Mapper510_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + WRAM_init(info, 8); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/ines.c b/src/ines.c index b987b4c..8c50877 100644 --- a/src/ines.c +++ b/src/ines.c @@ -915,6 +915,7 @@ INES_BOARD_BEGIN() INES_BOARD( "ET-170", 503, Mapper503_Init ) INES_BOARD( "K-3054", 504, Mapper504_Init ) INES_BOARD( "GA-009", 506, Mapper506_Init ) + INES_BOARD( "FC-53A", 510, Mapper510_Init ) INES_BOARD( "1n4148", 511, Mapper511_Init ) INES_BOARD( "Zhonggguo Daheng", 512, Mapper512_Init ) INES_BOARD( "SA-9602B", 513, SA9602B_Init ) diff --git a/src/ines.h b/src/ines.h index 1297a22..32bd5b9 100644 --- a/src/ines.h +++ b/src/ines.h @@ -395,6 +395,7 @@ void Mapper502_Init(CartInfo *); void Mapper503_Init(CartInfo *); void Mapper504_Init(CartInfo *); void Mapper506_Init(CartInfo *); +void Mapper510_Init(CartInfo *); void Mapper511_Init(CartInfo *); void Mapper512_Init(CartInfo *); void Mapper516_Init(CartInfo *); From 80df4283af4c53724122f15e6906e0e93317f9ed Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 21:58:47 +0200 Subject: [PATCH 052/109] Add mapper 509. --- src/boards/509.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 73 insertions(+) create mode 100644 src/boards/509.c diff --git a/src/boards/509.c b/src/boards/509.c new file mode 100644 index 0000000..f13e678 --- /dev/null +++ b/src/boards/509.c @@ -0,0 +1,71 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" +#include "wram.h" + +static uint8 reg; + +static void sync () { + int prgAND = reg &0x10? 0x1F: 0x0F; + int chrAND = reg &0x10? 0xFF: 0x7F; + int prgOR = reg <<1; + int chrOR = reg <<4; + if (reg &0x20) + MMC3_syncPRG(prgAND, prgOR &~prgAND); + else + if (reg &0x06) + setprg32(0x8000, reg >>1); + else { + setprg16(0x8000, reg); + setprg16(0xC000, reg); + } + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncWRAM(0); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + if (~reg &0x20) { + reg = A &0xFF; + sync(); + } +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +void Mapper509_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + WRAM_init(info, 8); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/ines.c b/src/ines.c index 8c50877..cc48f6b 100644 --- a/src/ines.c +++ b/src/ines.c @@ -915,6 +915,7 @@ INES_BOARD_BEGIN() INES_BOARD( "ET-170", 503, Mapper503_Init ) INES_BOARD( "K-3054", 504, Mapper504_Init ) INES_BOARD( "GA-009", 506, Mapper506_Init ) + INES_BOARD( "K-3022", 509, Mapper509_Init ) INES_BOARD( "FC-53A", 510, Mapper510_Init ) INES_BOARD( "1n4148", 511, Mapper511_Init ) INES_BOARD( "Zhonggguo Daheng", 512, Mapper512_Init ) diff --git a/src/ines.h b/src/ines.h index 32bd5b9..c37a89c 100644 --- a/src/ines.h +++ b/src/ines.h @@ -395,6 +395,7 @@ void Mapper502_Init(CartInfo *); void Mapper503_Init(CartInfo *); void Mapper504_Init(CartInfo *); void Mapper506_Init(CartInfo *); +void Mapper509_Init(CartInfo *); void Mapper510_Init(CartInfo *); void Mapper511_Init(CartInfo *); void Mapper512_Init(CartInfo *); From 03a761fa911311041bd0a8daa80abc39b22ac4e0 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 22:03:21 +0200 Subject: [PATCH 053/109] Add mapper 508. --- src/boards/508.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 72 insertions(+) create mode 100644 src/boards/508.c diff --git a/src/boards/508.c b/src/boards/508.c new file mode 100644 index 0000000..9a8a16b --- /dev/null +++ b/src/boards/508.c @@ -0,0 +1,70 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; +static uint8 pad; + +static void sync () { + if (reg &0x80) + MMC3_syncPRG(0x1F, reg >>1 &~0x1F); + else + if (reg &0x20) + setprg32(0x8000, (reg &0x0F | reg >>2 &~0x0F) >>1); + else { + setprg16(0x8000, reg &0x0F | reg >>2 &~0x0F); + setprg16(0xC000, reg &0x0F | reg >>2 &~0x0F); + } + setchr8(0); + MMC3_syncMirror(); +} + +static DECLFR (readPad) { + return pad; +} + +static DECLFW (writeReg) { + reg = V; + sync(); +} + +static void reset () { + reg = 0x0F; + pad++; + MMC3_clear(); +} + +static void power () { + reg = 0x0F; + pad = 0; + MMC3_power(); +} + +void Mapper508_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, readPad, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/ines.c b/src/ines.c index cc48f6b..50254bd 100644 --- a/src/ines.c +++ b/src/ines.c @@ -915,6 +915,7 @@ INES_BOARD_BEGIN() INES_BOARD( "ET-170", 503, Mapper503_Init ) INES_BOARD( "K-3054", 504, Mapper504_Init ) INES_BOARD( "GA-009", 506, Mapper506_Init ) + INES_BOARD( "JY-014", 508, Mapper508_Init ) INES_BOARD( "K-3022", 509, Mapper509_Init ) INES_BOARD( "FC-53A", 510, Mapper510_Init ) INES_BOARD( "1n4148", 511, Mapper511_Init ) diff --git a/src/ines.h b/src/ines.h index c37a89c..168610a 100644 --- a/src/ines.h +++ b/src/ines.h @@ -395,6 +395,7 @@ void Mapper502_Init(CartInfo *); void Mapper503_Init(CartInfo *); void Mapper504_Init(CartInfo *); void Mapper506_Init(CartInfo *); +void Mapper508_Init(CartInfo *); void Mapper509_Init(CartInfo *); void Mapper510_Init(CartInfo *); void Mapper511_Init(CartInfo *); From b8d3d58b1e7a87e01cc4154fc3c4796724f24193 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 22:09:42 +0200 Subject: [PATCH 054/109] Add mapper 498. --- src/boards/498.c | 62 ++++++++++++++++++++++++++++++++++++++++++ src/boards/asic_mmc1.c | 2 +- src/boards/asic_mmc1.h | 1 + src/ines.c | 1 + src/ines.h | 1 + 5 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 src/boards/498.c diff --git a/src/boards/498.c b/src/boards/498.c new file mode 100644 index 0000000..000005a --- /dev/null +++ b/src/boards/498.c @@ -0,0 +1,62 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc1.h" + +static uint8 reg; + +static void sync () { + if (reg &0x20) + MMC1_syncPRG(0x07, reg &~0x07); + else + if (reg &0x04) + setprg32(0x8000, reg >>1); + else { + setprg16(0x8000, reg); + setprg16(0xC000, reg); + } + MMC1_syncCHR(0x1F, reg <<2 &~0x1F); + MMC1_syncMirror(); +} + +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset () { + reg = 0; + MMC1_clear(); +} + +static void power () { + reg = 0; + MMC1_power(); +} + +void Mapper498_Init (CartInfo *info) { + MMC1_init(info, sync, MMC1_TYPE_MMC1A, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/asic_mmc1.c b/src/boards/asic_mmc1.c index ca3eb69..42fdc6a 100644 --- a/src/boards/asic_mmc1.c +++ b/src/boards/asic_mmc1.c @@ -115,7 +115,7 @@ DECLFW(MMC1_writeReg) { MMC1_filter = 2; } -static void MMC1_clear() { +void MMC1_clear() { MMC1_reg[0] = 0x0C; MMC1_reg[1] = 0; MMC1_reg[2] = 0; MMC1_reg[3] = 0; /* "Bad News Baseball" is sensitive to the initial CHR bank register content. 0/0 seems to work. */ MMC1_bits = 0; MMC1_shift = 0; MMC1_filter = 0; MMC1_cbSync(); diff --git a/src/boards/asic_mmc1.h b/src/boards/asic_mmc1.h index 971d719..e72260c 100644 --- a/src/boards/asic_mmc1.h +++ b/src/boards/asic_mmc1.h @@ -32,6 +32,7 @@ void MMC1_syncCHR (int, int); void MMC1_syncMirror (); void FP_FASTAPASS(1) MMC1_cpuCycle(int); DECLFW (MMC1_writeReg); +void MMC1_clear (); void MMC1_addExState (); void MMC1_restore (int); void MMC1_power (); diff --git a/src/ines.c b/src/ines.c index 50254bd..eb5ea51 100644 --- a/src/ines.c +++ b/src/ines.c @@ -909,6 +909,7 @@ INES_BOARD_BEGIN() INES_BOARD( "KS7009", 486, Mapper486_Init ) INES_BOARD( "AVE NINA-08", 487, Mapper487_Init ) INES_BOARD( "HC001", 488, Mapper488_Init ) + INES_BOARD( "K-3011", 498, Mapper498_Init ) INES_BOARD( "Yhc-000", 500, Mapper500_Init ) INES_BOARD( "Yhc-001", 501, Mapper501_Init ) INES_BOARD( "Yhc-002", 502, Mapper502_Init ) diff --git a/src/ines.h b/src/ines.h index 168610a..e532a34 100644 --- a/src/ines.h +++ b/src/ines.h @@ -389,6 +389,7 @@ void Mapper485_Init(CartInfo *); void Mapper486_Init(CartInfo *); void Mapper487_Init(CartInfo *); void Mapper488_Init(CartInfo *); +void Mapper498_Init(CartInfo *); void Mapper500_Init(CartInfo *); void Mapper501_Init(CartInfo *); void Mapper502_Init(CartInfo *); From 6cb168cce3a615ef500d4dcfd2e04c015da94103 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 22:13:17 +0200 Subject: [PATCH 055/109] Add mapper 507. --- src/boards/507.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 68 insertions(+) create mode 100644 src/boards/507.c diff --git a/src/boards/507.c b/src/boards/507.c new file mode 100644 index 0000000..0c01414 --- /dev/null +++ b/src/boards/507.c @@ -0,0 +1,66 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; +static uint8 pad; + +static void sync () { + int prgAND = reg &0x20? 0x0F: 0x1F; + int chrAND = reg &0x20? 0x7F: 0xFF; + int prgOR = reg; + int chrOR = reg <<3; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static DECLFR (readPad) { + return pad; +} + +static DECLFW (writeReg) { + reg = V; + sync(); +} + +static void reset () { + reg = 0; + pad ^= 0x80; + MMC3_clear(); +} + +static void power () { + reg = 0; + pad = 0; + MMC3_power(); +} + +void Mapper507_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, readPad, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/ines.c b/src/ines.c index eb5ea51..2154039 100644 --- a/src/ines.c +++ b/src/ines.c @@ -916,6 +916,7 @@ INES_BOARD_BEGIN() INES_BOARD( "ET-170", 503, Mapper503_Init ) INES_BOARD( "K-3054", 504, Mapper504_Init ) INES_BOARD( "GA-009", 506, Mapper506_Init ) + INES_BOARD( "A-018", 507, Mapper507_Init ) INES_BOARD( "JY-014", 508, Mapper508_Init ) INES_BOARD( "K-3022", 509, Mapper509_Init ) INES_BOARD( "FC-53A", 510, Mapper510_Init ) diff --git a/src/ines.h b/src/ines.h index e532a34..66e44fe 100644 --- a/src/ines.h +++ b/src/ines.h @@ -396,6 +396,7 @@ void Mapper502_Init(CartInfo *); void Mapper503_Init(CartInfo *); void Mapper504_Init(CartInfo *); void Mapper506_Init(CartInfo *); +void Mapper507_Init(CartInfo *); void Mapper508_Init(CartInfo *); void Mapper509_Init(CartInfo *); void Mapper510_Init(CartInfo *); From f47947dae8c23149823137f3f0f969eafc4ea264 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 22:23:59 +0200 Subject: [PATCH 056/109] Mapper 339: Add submappers 2 and 3, solder pad menu selection --- src/boards/bmck3006.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/boards/bmck3006.c b/src/boards/bmck3006.c index 0e62d5e..f4deed0 100644 --- a/src/boards/bmck3006.c +++ b/src/boards/bmck3006.c @@ -26,7 +26,11 @@ #include "mapinc.h" #include "mmc3.h" -static uint8 submapper; +static uint8 submapper; // 0: K-3006, 1: unmarked, 2: TL 8058, 3: K-3091/GN-16 + +static DECLFR (readPad) { + return CartBR(A &~3 | EXPREGS[2] &3); +} static void BMCK3006CW(uint32 A, uint8 V) { setchr1(A, (V & 0x7F) | (EXPREGS[0] & 0x18) << 4); @@ -36,9 +40,12 @@ static void BMCK3006PW(uint32 A, uint8 V) { if (EXPREGS[0] & 0x20) { /* MMC3 mode */ setprg8(A, (V & 0x0F) | (EXPREGS[0] & 0x18) << 1); } else { - if ((EXPREGS[0] & 0x07) == 0x06 && submapper ==0 || EXPREGS[0] &4 && submapper ==1) { /* NROM-256 */ + if (submapper ==0 && (EXPREGS[0] & 0x06) == 0x06 || + submapper ==1 && EXPREGS[0] &4 || + submapper ==2 && (EXPREGS[0] &1 || EXPREGS[1] &1) || + submapper ==3 && EXPREGS[0] &0x18) { /* NROM-256 */ setprg32(0x8000, (EXPREGS[0] >> 1) & 0x0F); - } else { /* NROM-128 */ + } else { /* NROM-128 */ setprg16(0x8000, EXPREGS[0] & 0x1F); setprg16(0xC000, EXPREGS[0] & 0x1F); } @@ -46,18 +53,21 @@ static void BMCK3006PW(uint32 A, uint8 V) { } static DECLFW(BMCK3006Write) { - EXPREGS[0] = A & 0x3F; + EXPREGS[0] = A &0xFF; + EXPREGS[1] = A >>8 &0xFF; FixMMC3PRG(MMC3_cmd); FixMMC3CHR(MMC3_cmd); + if (submapper == 2 || submapper == 3) SetReadHandler(0x8000, 0xFFFF, EXPREGS[0] &0x80? readPad: CartBR); } static void BMCK3006Reset(void) { - EXPREGS[0] = 0; + EXPREGS[0] = EXPREGS[1] = 0; + EXPREGS[2]++; MMC3RegReset(); } static void BMCK3006Power(void) { - EXPREGS[0] = 0; + EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = 0; GenMMC3Power(); SetWriteHandler(0x6000, 0x7FFF, BMCK3006Write); } @@ -69,5 +79,5 @@ void BMCK3006_Init(CartInfo *info) { cwrap = BMCK3006CW; info->Power = BMCK3006Power; info->Reset = BMCK3006Reset; - AddExState(EXPREGS, 1, 0, "EXPR"); + AddExState(EXPREGS, 3, 0, "EXPR"); } From 9eb4a4c233dbf9729b37fc06754d0af6f42bab0b Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 22:30:23 +0200 Subject: [PATCH 057/109] Add mapper 505. --- src/boards/505.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 67 insertions(+) create mode 100644 src/boards/505.c diff --git a/src/boards/505.c b/src/boards/505.c new file mode 100644 index 0000000..82027eb --- /dev/null +++ b/src/boards/505.c @@ -0,0 +1,65 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint16 reg; +static uint8 pad; + +static void sync () { + if (reg &0x01) + MMC3_syncPRG(0x1F, reg &0x60); + else + setprg32(0x8000, reg >>2); + MMC3_syncCHR(reg &0x100? 0x7F: 0xFF, reg >>1 &0x100 | reg &0x080); + MMC3_syncMirror(); +} + +static DECLFR (readPad) { + return pad; +} + +static DECLFW (writeReg) { + reg = A ^0x1C; + sync(); +} + +static void reset () { + reg = 0xFE; + pad++; + MMC3_clear(); +} + +static void power () { + reg = 0xFE; + pad = 0; + MMC3_power(); +} + +void Mapper505_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, readPad, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 2, 0, "EXPR"); + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/ines.c b/src/ines.c index 2154039..9ef3e89 100644 --- a/src/ines.c +++ b/src/ines.c @@ -915,6 +915,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Yhc-002", 502, Mapper502_Init ) INES_BOARD( "ET-170", 503, Mapper503_Init ) INES_BOARD( "K-3054", 504, Mapper504_Init ) + INES_BOARD( "5426757A-Y2-230630", 505, Mapper505_Init ) INES_BOARD( "GA-009", 506, Mapper506_Init ) INES_BOARD( "A-018", 507, Mapper507_Init ) INES_BOARD( "JY-014", 508, Mapper508_Init ) diff --git a/src/ines.h b/src/ines.h index 66e44fe..d900670 100644 --- a/src/ines.h +++ b/src/ines.h @@ -395,6 +395,7 @@ void Mapper501_Init(CartInfo *); void Mapper502_Init(CartInfo *); void Mapper503_Init(CartInfo *); void Mapper504_Init(CartInfo *); +void Mapper505_Init(CartInfo *); void Mapper506_Init(CartInfo *); void Mapper507_Init(CartInfo *); void Mapper508_Init(CartInfo *); From fbf29ed127eabb8f74c96d5a4eefaa27fae7f7d3 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 22:33:03 +0200 Subject: [PATCH 058/109] Add mapper 499. --- src/boards/499.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 58 insertions(+) create mode 100644 src/boards/499.c diff --git a/src/boards/499.c b/src/boards/499.c new file mode 100644 index 0000000..340c0fd --- /dev/null +++ b/src/boards/499.c @@ -0,0 +1,56 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc1.h" + +static uint8 reg; + +static void sync () { + MMC1_syncPRG(0x07, reg <<3); + MMC1_syncCHR(0x1F, reg <<5); + MMC1_syncMirror(); +} + +static DECLFW (writeReg) { + if (~reg &8) { + reg = A &0xFF; + sync(); + } +} + +static void reset () { + reg = 0; + MMC1_clear(); +} + +static void power () { + reg = 0; + MMC1_power(); +} + +void Mapper499_Init (CartInfo *info) { + MMC1_init(info, sync, MMC1_TYPE_MMC1A, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/ines.c b/src/ines.c index 9ef3e89..2564ed3 100644 --- a/src/ines.c +++ b/src/ines.c @@ -910,6 +910,7 @@ INES_BOARD_BEGIN() INES_BOARD( "AVE NINA-08", 487, Mapper487_Init ) INES_BOARD( "HC001", 488, Mapper488_Init ) INES_BOARD( "K-3011", 498, Mapper498_Init ) + INES_BOARD( "FC-41", 499, Mapper499_Init ) INES_BOARD( "Yhc-000", 500, Mapper500_Init ) INES_BOARD( "Yhc-001", 501, Mapper501_Init ) INES_BOARD( "Yhc-002", 502, Mapper502_Init ) diff --git a/src/ines.h b/src/ines.h index d900670..805cb7b 100644 --- a/src/ines.h +++ b/src/ines.h @@ -390,6 +390,7 @@ void Mapper486_Init(CartInfo *); void Mapper487_Init(CartInfo *); void Mapper488_Init(CartInfo *); void Mapper498_Init(CartInfo *); +void Mapper499_Init(CartInfo *); void Mapper500_Init(CartInfo *); void Mapper501_Init(CartInfo *); void Mapper502_Init(CartInfo *); From a44e23ea6b606532a49889737e3373dd8d13592f Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 22:36:17 +0200 Subject: [PATCH 059/109] Mapper 227: Add submapper 3. --- src/boards/addrlatch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c index bf2ebb8..6178337 100644 --- a/src/boards/addrlatch.c +++ b/src/boards/addrlatch.c @@ -395,10 +395,10 @@ static void M227Sync(void) { } else { if (L) { setprg16(0x8000, p); - setprg16(0xC000, p | 7); + setprg16(0xC000, submapper ==3? 0: (p | 7)); } else { setprg16(0x8000, p); - setprg16(0xC000, submapper ==2? 0: p & 0x38); + setprg16(0xC000, submapper ==2? 0: (p & 0x38)); } } } From b359daeb99a74fa46c00a9f15d5ba1007b3652f5 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 22:45:00 +0200 Subject: [PATCH 060/109] Add mapper 494. --- src/boards/494.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 63 insertions(+) create mode 100644 src/boards/494.c diff --git a/src/boards/494.c b/src/boards/494.c new file mode 100644 index 0000000..7820751 --- /dev/null +++ b/src/boards/494.c @@ -0,0 +1,61 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static uint8 pad; + +static DECLFR(readOB) { + return X.DB; +} + +static void sync () { + if (Latch_address &0x100) { + if (Latch_address &0x001) { + setprg16(0x8000, Latch_address >>2); + setprg16(0xC000, Latch_address >>2); + } else + setprg32(0x8000, Latch_address >>3); + } else { + setprg16(0x8000, Latch_address >>2); + setprg16(0xC000, Latch_address >>2 |7); + } + setchr8(Latch_address >>5 &7 | Latch_address >>1 &8); + setmirror(Latch_address &0x002? MI_H: MI_V); + SetReadHandler(0x8000, 0xFFFF, ~Latch_address &0x100 && Latch_address &0x001 &pad? readOB: CartBR); +} + +static void power() { + pad = 0; + Latch_power(); +} + +static void reset() { + pad++; + Latch_clear(); +} + +void Mapper494_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/ines.c b/src/ines.c index 2564ed3..593ac88 100644 --- a/src/ines.c +++ b/src/ines.c @@ -909,6 +909,7 @@ INES_BOARD_BEGIN() INES_BOARD( "KS7009", 486, Mapper486_Init ) INES_BOARD( "AVE NINA-08", 487, Mapper487_Init ) INES_BOARD( "HC001", 488, Mapper488_Init ) + INES_BOARD( "CH512K/OK-103", 494, Mapper494_Init ) INES_BOARD( "K-3011", 498, Mapper498_Init ) INES_BOARD( "FC-41", 499, Mapper499_Init ) INES_BOARD( "Yhc-000", 500, Mapper500_Init ) diff --git a/src/ines.h b/src/ines.h index 805cb7b..2683ea9 100644 --- a/src/ines.h +++ b/src/ines.h @@ -389,6 +389,7 @@ void Mapper485_Init(CartInfo *); void Mapper486_Init(CartInfo *); void Mapper487_Init(CartInfo *); void Mapper488_Init(CartInfo *); +void Mapper494_Init(CartInfo *); void Mapper498_Init(CartInfo *); void Mapper499_Init(CartInfo *); void Mapper500_Init(CartInfo *); From a6e5ee7c498572130dee541ab33a4db6fab25cbe Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 22:53:52 +0200 Subject: [PATCH 061/109] Add mapper 493. --- src/boards/493.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 54 insertions(+) create mode 100644 src/boards/493.c diff --git a/src/boards/493.c b/src/boards/493.c new file mode 100644 index 0000000..bef0875 --- /dev/null +++ b/src/boards/493.c @@ -0,0 +1,52 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[2]; + +static void sync () { + setprg32(0x8000, reg[0] <<1 | reg[1] &0x01); + setchr8(reg[0] <<3 | reg[1] >>4 &0x07); +} + +static DECLFW (writeReg) { + reg[A >>15 &1] = V; + sync(); +} + +static void power () { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0xFFFF, writeReg); + reg[0] = reg[1] = 0; + RAM[0x07] =0; + sync(); +} + +static void stateRestore (int version) { + sync(); +} + +void Mapper493_Init (CartInfo *info) { + info->Reset = power; + info->Power = power; + GameStateRestore = stateRestore; + AddExState(reg, 2, 0, "REGS"); +} diff --git a/src/ines.c b/src/ines.c index 593ac88..5f62b5a 100644 --- a/src/ines.c +++ b/src/ines.c @@ -909,6 +909,7 @@ INES_BOARD_BEGIN() INES_BOARD( "KS7009", 486, Mapper486_Init ) INES_BOARD( "AVE NINA-08", 487, Mapper487_Init ) INES_BOARD( "HC001", 488, Mapper488_Init ) + INES_BOARD( "AVE-NTDEC 30-in-1", 493, Mapper493_Init ) INES_BOARD( "CH512K/OK-103", 494, Mapper494_Init ) INES_BOARD( "K-3011", 498, Mapper498_Init ) INES_BOARD( "FC-41", 499, Mapper499_Init ) diff --git a/src/ines.h b/src/ines.h index 2683ea9..cde2181 100644 --- a/src/ines.h +++ b/src/ines.h @@ -389,6 +389,7 @@ void Mapper485_Init(CartInfo *); void Mapper486_Init(CartInfo *); void Mapper487_Init(CartInfo *); void Mapper488_Init(CartInfo *); +void Mapper493_Init(CartInfo *); void Mapper494_Init(CartInfo *); void Mapper498_Init(CartInfo *); void Mapper499_Init(CartInfo *); From 60ff97dd99a880be69090e31b396ef12b08dd376 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 22:59:23 +0200 Subject: [PATCH 062/109] Add mapper 492. --- src/boards/492.c | 38 ++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 40 insertions(+) create mode 100644 src/boards/492.c diff --git a/src/boards/492.c b/src/boards/492.c new file mode 100644 index 0000000..6f2b96a --- /dev/null +++ b/src/boards/492.c @@ -0,0 +1,38 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_address &0x20) + setprg32(0x8000, Latch_address >>4); + else { + setprg16(0x8000, Latch_address >>3); + setprg16(0xC000, Latch_address >>3); + } + setchr8(Latch_address >>1 &0x03 | Latch_address >>2 &0x0C); + setmirror(Latch_address &0x01? MI_H: MI_V); +} + +void Mapper492_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/ines.c b/src/ines.c index 5f62b5a..7065183 100644 --- a/src/ines.c +++ b/src/ines.c @@ -909,6 +909,7 @@ INES_BOARD_BEGIN() INES_BOARD( "KS7009", 486, Mapper486_Init ) INES_BOARD( "AVE NINA-08", 487, Mapper487_Init ) INES_BOARD( "HC001", 488, Mapper488_Init ) + INES_BOARD( "K-3069/12-28", 492, Mapper492_Init ) INES_BOARD( "AVE-NTDEC 30-in-1", 493, Mapper493_Init ) INES_BOARD( "CH512K/OK-103", 494, Mapper494_Init ) INES_BOARD( "K-3011", 498, Mapper498_Init ) diff --git a/src/ines.h b/src/ines.h index cde2181..7d1c29c 100644 --- a/src/ines.h +++ b/src/ines.h @@ -389,6 +389,7 @@ void Mapper485_Init(CartInfo *); void Mapper486_Init(CartInfo *); void Mapper487_Init(CartInfo *); void Mapper488_Init(CartInfo *); +void Mapper492_Init(CartInfo *); void Mapper493_Init(CartInfo *); void Mapper494_Init(CartInfo *); void Mapper498_Init(CartInfo *); From 4d9dc2c4cb58db18d60c2cac08475e8b5403e200 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 23:01:50 +0200 Subject: [PATCH 063/109] Add mapper 491. --- src/boards/491.c | 37 +++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 39 insertions(+) create mode 100644 src/boards/491.c diff --git a/src/boards/491.c b/src/boards/491.c new file mode 100644 index 0000000..17d2783 --- /dev/null +++ b/src/boards/491.c @@ -0,0 +1,37 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_address &0x08) { + setprg16(0x8000, Latch_address); + setprg16(0xC000, Latch_address); + } else + setprg32(0x8000, Latch_address >>1); + setchr8(Latch_data); + setmirror(Latch_address &0x10? MI_H: MI_V); +} + +void Mapper491_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/ines.c b/src/ines.c index 7065183..cb49002 100644 --- a/src/ines.c +++ b/src/ines.c @@ -909,6 +909,7 @@ INES_BOARD_BEGIN() INES_BOARD( "KS7009", 486, Mapper486_Init ) INES_BOARD( "AVE NINA-08", 487, Mapper487_Init ) INES_BOARD( "HC001", 488, Mapper488_Init ) + INES_BOARD( "Sane Ting 5-in-1", 491, Mapper491_Init ) INES_BOARD( "K-3069/12-28", 492, Mapper492_Init ) INES_BOARD( "AVE-NTDEC 30-in-1", 493, Mapper493_Init ) INES_BOARD( "CH512K/OK-103", 494, Mapper494_Init ) diff --git a/src/ines.h b/src/ines.h index 7d1c29c..0b330ae 100644 --- a/src/ines.h +++ b/src/ines.h @@ -389,6 +389,7 @@ void Mapper485_Init(CartInfo *); void Mapper486_Init(CartInfo *); void Mapper487_Init(CartInfo *); void Mapper488_Init(CartInfo *); +void Mapper491_Init(CartInfo *); void Mapper492_Init(CartInfo *); void Mapper493_Init(CartInfo *); void Mapper494_Init(CartInfo *); From 35033127b5c205a203f2c1ba551929b9ab52f815 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 23:17:07 +0200 Subject: [PATCH 064/109] Add mappers 489 and 490. --- src/boards/489.c | 43 +++++++++++++++++++++++++++++++ src/boards/490.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 2 ++ src/ines.h | 2 ++ 4 files changed, 114 insertions(+) create mode 100644 src/boards/489.c create mode 100644 src/boards/490.c diff --git a/src/boards/489.c b/src/boards/489.c new file mode 100644 index 0000000..f84753e --- /dev/null +++ b/src/boards/489.c @@ -0,0 +1,43 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if ((Latch_data &0x1F) == 2) + setprg32(0x8000, Latch_data >>1); + else { + setprg16(0x8000, Latch_data); + setprg16(0xC000, Latch_data); + } + setchr8(Latch_data); + switch(Latch_data >>6) { + case 0: setmirrorw(0, 0, 0, 1); break; + case 1: setmirror(MI_V); break; + case 2: setmirror(MI_H); break; + case 3: setmirror(MI_1); break; + } +} + +void Mapper489_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/490.c b/src/boards/490.c new file mode 100644 index 0000000..67bc48a --- /dev/null +++ b/src/boards/490.c @@ -0,0 +1,67 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; +static uint8 pad; + +static DECLFR(readPad) { + return CartBR(A &~0xF | pad &0xF); +} + +static void sync() { + if (reg &0x20) + setprg32(0x8000, reg >>1); + else { + setprg16(0x8000, reg); + setprg16(0xC000, reg); + } + MMC3_syncCHR(0xFF, reg <<4 &~0xFF); + MMC3_syncMirror(); + SetReadHandler(0x8000, 0xFFFF, reg &0x80? readPad: CartBR); +} + +static DECLFW(writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset() { + reg = 0; + ++pad; + sync(); +} + +static void power() { + reg = 0; + pad = 0; + MMC3_power(); +} + +void Mapper490_Init(CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/ines.c b/src/ines.c index cb49002..67fcaa1 100644 --- a/src/ines.c +++ b/src/ines.c @@ -909,6 +909,8 @@ INES_BOARD_BEGIN() INES_BOARD( "KS7009", 486, Mapper486_Init ) INES_BOARD( "AVE NINA-08", 487, Mapper487_Init ) INES_BOARD( "HC001", 488, Mapper488_Init ) + INES_BOARD( "N-80", 489, Mapper489_Init ) + INES_BOARD( "K-3101", 490, Mapper490_Init ) INES_BOARD( "Sane Ting 5-in-1", 491, Mapper491_Init ) INES_BOARD( "K-3069/12-28", 492, Mapper492_Init ) INES_BOARD( "AVE-NTDEC 30-in-1", 493, Mapper493_Init ) diff --git a/src/ines.h b/src/ines.h index 0b330ae..9618844 100644 --- a/src/ines.h +++ b/src/ines.h @@ -389,6 +389,8 @@ void Mapper485_Init(CartInfo *); void Mapper486_Init(CartInfo *); void Mapper487_Init(CartInfo *); void Mapper488_Init(CartInfo *); +void Mapper489_Init(CartInfo *); +void Mapper490_Init(CartInfo *); void Mapper491_Init(CartInfo *); void Mapper492_Init(CartInfo *); void Mapper493_Init(CartInfo *); From 7e023ec4884073b953e2be9d859976991675e5df Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 23:35:32 +0200 Subject: [PATCH 065/109] Mapper 30: Add submappers. --- src/boards/unrom512.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/boards/unrom512.c b/src/boards/unrom512.c index ca3f63b..4f136d0 100644 --- a/src/boards/unrom512.c +++ b/src/boards/unrom512.c @@ -43,6 +43,7 @@ static uint8 fceumm_flash_buf[flashdata_size + flash_write_count_size]; static uint32 fceumm_flash_buf_size = sizeof(fceumm_flash_buf); +static uint8 submapper; static uint8 latche, latcheinit, bus_conflict, chrram_mask, software_id=0; static uint16 latcha; static uint8 *flashdata = fceumm_flash_buf + flash_write_count_size; @@ -135,11 +136,11 @@ static void UNROM512LatchPower(void) { latche = latcheinit; WHSync(); SetReadHandler(0x8000, 0xFFFF, UNROM512LatchRead); - if (!flash_save) + if (submapper == 0 && !flash_save || submapper == 2) SetWriteHandler(0x8000, 0xFFFF, UNROM512HLatchWrite); else { - SetWriteHandler(0x8000, 0xBFFF, UNROM512LLatchWrite); + if (submapper != 4) SetWriteHandler(0x8000, 0xBFFF, UNROM512LLatchWrite); SetWriteHandler(0xC000, 0xFFFF, UNROM512HLatchWrite); } } @@ -205,12 +206,15 @@ static void UNROM512HSync(void) { setfprg16(0x8000, flash_bank); setfprg16(0xC000, ~0); setchr8r(0, (latche & chrram_mask) >> 5); - setmirror(MI_0 + (latche >> 7)); + if (submapper == 3) + setmirror(latche &0x80? MI_V: MI_H); + else + setmirror(MI_0 + (latche >> 7)); } void UNROM512_Init(CartInfo *info) { int mirror; - + submapper = info->submapper; memset(fceumm_flash_buf, 0x00, fceumm_flash_buf_size); flash_state = 0; flash_bank = 0; @@ -224,6 +228,9 @@ void UNROM512_Init(CartInfo *info) { chrram_mask = 0x60; mirror = (head.ROM_type & 1) | ((head.ROM_type & 8) >> 2); + if (submapper == 3) /* Mega Man II (30th Anniversary Edition): switchable H/V */ + SetupCartMirroring(MI_V, 0, NULL); + else switch (mirror) { case 0: /* hard horizontal, internal */ SetupCartMirroring(MI_H, 1, NULL); @@ -238,7 +245,7 @@ void UNROM512_Init(CartInfo *info) { SetupCartMirroring(4, 1, VROM + (info->CHRRamSize - 8192)); break; } - bus_conflict = !info->battery; + bus_conflict = submapper == 0 && !info->battery || submapper == 2; latcheinit = 0; WLSync = UNROM512LSync; WHSync = UNROM512HSync; From cea8fc87eba91a40dad48922c6644c4627bccc1c Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 9 Sep 2025 23:52:54 +0200 Subject: [PATCH 066/109] Add mapper 400. --- src/boards/400.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 60 insertions(+) create mode 100644 src/boards/400.c diff --git a/src/boards/400.c b/src/boards/400.c new file mode 100644 index 0000000..3965439 --- /dev/null +++ b/src/boards/400.c @@ -0,0 +1,58 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static uint8 reg[4]; + +static void sync () { + setprg16(0x8000, reg[2] &~0x07 | Latch_data &0x07); + setprg16(0xC000, reg[3] &~0x07 | 0x07); + setchr8(Latch_data >>5); + setmirror(reg[3] &0x20? MI_H: MI_V); +} + +static DECLFW (writeReg) { + if (!(A &0x7FF)) { /* Exclude 8 Bit Xmas 2008's writes to second APU (also at 7001-7015) */ + reg[A >>11 &3] = V; + sync(); + } +} + +static void power () { + reg[0] = reg[1] = reg[2] = 0; + reg[3] = 0x80; + Latch_power(); + SetWriteHandler(0x6000, 0x7FFF, writeReg); +} + +static void reset () { + reg[0] = reg[1] = reg[2] = 0; + reg[3] = 0x80; + Latch_clear(); +} + +void Mapper400_Init (CartInfo *info) { + Latch_init(info, sync, 0xC000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; + AddExState(reg, 4, 0, "REGS"); +} diff --git a/src/ines.c b/src/ines.c index 67fcaa1..c79e6a4 100644 --- a/src/ines.c +++ b/src/ines.c @@ -836,6 +836,7 @@ INES_BOARD_BEGIN() INES_BOARD( "YY850439C", 397, Mapper397_Init ) INES_BOARD( "YY840820C", 398, Mapper398_Init ) INES_BOARD( "BATMAP-000", 399, Mapper399_Init ) + INES_BOARD( "8BIT-XMAS", 400, Mapper400_Init ) INES_BOARD( "BMC Super 19-in-1 (VIP19)",401, Mapper401_Init ) INES_BOARD( "831019C J-2282", 402, J2282_Init ) INES_BOARD( "89433", 403, Mapper403_Init ) diff --git a/src/ines.h b/src/ines.h index 9618844..d305db7 100644 --- a/src/ines.h +++ b/src/ines.h @@ -317,6 +317,7 @@ void Mapper396_Init(CartInfo *); void Mapper397_Init(CartInfo *); void Mapper398_Init(CartInfo *); void Mapper399_Init(CartInfo *); +void Mapper400_Init(CartInfo *); void Mapper401_Init(CartInfo *); void Mapper403_Init(CartInfo *); void Mapper404_Init(CartInfo *); From 549161fa7d9b95575b8f550dd3d71c404ba5324c Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Wed, 10 Sep 2025 22:42:08 +0200 Subject: [PATCH 067/109] Add mapper 495. --- src/boards/495.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 3 +- src/ines.h | 1 + 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 src/boards/495.c diff --git a/src/boards/495.c b/src/boards/495.c new file mode 100644 index 0000000..0867fae --- /dev/null +++ b/src/boards/495.c @@ -0,0 +1,83 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 prg[3]; +static uint8 chr[4]; +static uint8 latch[2]; + +static SFORMAT stateRegs[] = { + { prg, 3, "PRGR" }, + { chr, 4, "CHRR" }, + { latch, 2, "LATC" }, + { 0 } +}; + +static void sync() { + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg8(0xC000, prg[2]); + setprg8(0xE000, 0xFF); + setchr4(0x0000, chr[0 | latch[0]]); + setchr4(0x1000, chr[2 | latch[1]]); + switch(chr[latch[0]] >>6) { + case 0: setmirrorw(0, 0, 0, 1); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_V); break; + case 3: setmirror(MI_1); break; + } +} + +static void FP_FASTAPASS(1) trapPPUAddressChange (uint32 A) { + if ((A &0x2FF0) == 0xFD0 || (A &0x2FF0) == 0xFE0) { + latch[A >>12 &1] = ~A >>5 &1; + sync(); + } +} + +static DECLFW(writeReg) { + if (A <0xE000) + prg[A >>13 &3] = V; + else + chr[A >>10 &3] = V; + sync(); +} + +static void restore (int version) { + sync(); +} + +static void power () { + prg[0] = prg[1] = prg[2] = 0; + chr[0] = chr[1] = chr[2] = chr[3] = 0; + latch[0] = 0; latch[1] = 0; + sync(); + SetReadHandler (0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, writeReg); + PPU_hook = trapPPUAddressChange; +} + +void Mapper495_Init (CartInfo *info) { + AddExState(stateRegs, ~0, 0, 0); + info->Power = power; + info->Reset = sync; + GameStateRestore = restore; +} diff --git a/src/ines.c b/src/ines.c index c79e6a4..d712588 100644 --- a/src/ines.c +++ b/src/ines.c @@ -916,6 +916,7 @@ INES_BOARD_BEGIN() INES_BOARD( "K-3069/12-28", 492, Mapper492_Init ) INES_BOARD( "AVE-NTDEC 30-in-1", 493, Mapper493_Init ) INES_BOARD( "CH512K/OK-103", 494, Mapper494_Init ) + INES_BOARD( "N-46", 495, Mapper495_Init ) INES_BOARD( "K-3011", 498, Mapper498_Init ) INES_BOARD( "FC-41", 499, Mapper499_Init ) INES_BOARD( "Yhc-000", 500, Mapper500_Init ) @@ -958,12 +959,12 @@ INES_BOARD_BEGIN() INES_BOARD( "JYV610 830626C", 542, Mapper542_Init ) INES_BOARD( "5-in-1 (CH-501)", 543, Mapper543_Init ) INES_BOARD( "WAIXING FS306", 544, Mapper544_Init ) + INES_BOARD( "", 550, Mapper550_Init ) INES_BOARD( "", 551, Mapper178_Init ) INES_BOARD( "SACHEN 3013", 553, Mapper553_Init ) INES_BOARD( "KS-7010", 554, Mapper554_Init ) INES_BOARD( "", 555, Mapper555_Init ) INES_BOARD( "JY-215", 556, Mapper556_Init ) - INES_BOARD( "", 550, Mapper550_Init ) INES_BOARD( "YC-03-09", 558, Mapper558_Init ) INES_BOARD( "Subor Sango II", 559, Mapper559_Init ) INES_BOARD( "Bung Super Game Doctor", 561, Mapper561_562_Init ) diff --git a/src/ines.h b/src/ines.h index d305db7..de5fac7 100644 --- a/src/ines.h +++ b/src/ines.h @@ -396,6 +396,7 @@ void Mapper491_Init(CartInfo *); void Mapper492_Init(CartInfo *); void Mapper493_Init(CartInfo *); void Mapper494_Init(CartInfo *); +void Mapper495_Init(CartInfo *); void Mapper498_Init(CartInfo *); void Mapper499_Init(CartInfo *); void Mapper500_Init(CartInfo *); From d81416649fc3f8020b19f693eac6656a2ed47ab9 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Wed, 10 Sep 2025 22:51:02 +0200 Subject: [PATCH 068/109] Add mapper 564. --- src/boards/564.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 47 insertions(+) create mode 100644 src/boards/564.c diff --git a/src/boards/564.c b/src/boards/564.c new file mode 100644 index 0000000..94fa23c --- /dev/null +++ b/src/boards/564.c @@ -0,0 +1,45 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + setprg32(0x8000, Latch_data); + setchr8(0); + if (Latch_data &0x20) + setmirror(Latch_data &0x10? MI_1: MI_0); + else + setmirror(Latch_data &0x10? MI_H: MI_V); +} + +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { /* After the lock bit is set, only update the (mode-specific) inner bank bits. */ + if (Latch_data &0x20) { + if (Latch_data &0x08) + *newValue = Latch_data &0x28 | *newValue &~0x28; /* AOROM */ + else + *newValue = Latch_data &0x2C | *newValue &~0x2C; /* ANROM */ + } +} + +void Mapper564_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); + info->Reset = Latch_clear; +} diff --git a/src/ines.c b/src/ines.c index d712588..a371765 100644 --- a/src/ines.c +++ b/src/ines.c @@ -970,6 +970,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Bung Super Game Doctor", 561, Mapper561_562_Init ) INES_BOARD( "Venus Turbo Game Doctor", 562, Mapper561_562_Init ) INES_BOARD( "J-2020", 563, Mapper563_Init ) + INES_BOARD( "bd23.pcb", 564, Mapper564_Init ) INES_BOARD( "ET-149", 566, Mapper566_Init ) INES_BOARD( "Top Ten Variety (SF III)", 567, Mapper567_Init ) INES_BOARD( "T-227", 568, Mapper568_Init ) diff --git a/src/ines.h b/src/ines.h index de5fac7..d494b40 100644 --- a/src/ines.h +++ b/src/ines.h @@ -436,6 +436,7 @@ void Mapper558_Init(CartInfo *); void Mapper559_Init(CartInfo *); void Mapper561_562_Init(CartInfo *); void Mapper563_Init(CartInfo *); +void Mapper564_Init(CartInfo *); void Mapper566_Init(CartInfo *); void Mapper567_Init(CartInfo *); void Mapper568_Init(CartInfo *); From 33974f54384b73e07e8e5cbb93c157220762cd5a Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Wed, 10 Sep 2025 22:57:05 +0200 Subject: [PATCH 069/109] Add mapper 582. --- src/boards/582.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 58 insertions(+) create mode 100644 src/boards/582.c diff --git a/src/boards/582.c b/src/boards/582.c new file mode 100644 index 0000000..f12ce07 --- /dev/null +++ b/src/boards/582.c @@ -0,0 +1,56 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[4]; + +static void sync () { + setprg16(0x8000, reg[1] <<3 | reg[0] &0x07); + setprg16(0xC000, reg[3] <<3 | reg[2] &0x07); + setchr8(0); +} + +static DECLFW (writeReg) { + reg[A >>13 &3] = V; + sync(); +} + +static void reset () { + reg[0] = reg[1] = reg[2] = reg[3] = 0xFF; + sync(); +} + +static void power () { + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, writeReg); + reset(); +} + +static void stateRestore (int version) { + sync(); +} + +void Mapper582_Init (CartInfo *info) { + info->Reset = reset; + info->Power = power; + GameStateRestore = stateRestore; + AddExState(reg, 4, 0, "REGS"); +} diff --git a/src/ines.c b/src/ines.c index a371765..d26c3a3 100644 --- a/src/ines.c +++ b/src/ines.c @@ -987,6 +987,7 @@ INES_BOARD_BEGIN() INES_BOARD( "T-215", 579, Mapper579_Init ) INES_BOARD( "ET-156", 580, Mapper580_Init ) INES_BOARD( "ET-82", 581, Mapper581_Init ) + INES_BOARD( "A9778", 582, Mapper582_Init ) INES_BOARD( "8203", 583, Mapper583_Init ) INES_BOARD( "ST-32", 584, Mapper584_Init ) INES_BOARD( "FE-01-1", 585, Mapper585_Init ) diff --git a/src/ines.h b/src/ines.h index d494b40..7eb4527 100644 --- a/src/ines.h +++ b/src/ines.h @@ -453,6 +453,7 @@ void Mapper578_Init(CartInfo *); void Mapper579_Init(CartInfo *); void Mapper580_Init(CartInfo *); void Mapper581_Init(CartInfo *); +void Mapper582_Init(CartInfo *); void Mapper583_Init(CartInfo *); void Mapper584_Init(CartInfo *); void Mapper585_Init(CartInfo *); From acdf0b83c137d11d797f411fd77c9136aab14027 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Wed, 10 Sep 2025 23:06:31 +0200 Subject: [PATCH 070/109] Add mapper 565. --- src/boards/563.c | 4 +-- src/boards/565.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 4 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 src/boards/565.c diff --git a/src/boards/563.c b/src/boards/563.c index a67be11..9605464 100644 --- a/src/boards/563.c +++ b/src/boards/563.c @@ -36,7 +36,7 @@ static void sync () { VRC24_syncMirror(); } -DECLFW(Mapper563_writeIRQ) { +static DECLFW(Mapper563_writeIRQ) { X6502_IRQEnd(FCEU_IQEXT); switch(A &0x1C) { case 0x0C: irqEnabled =0; break; @@ -49,7 +49,7 @@ static void Mapper563_scanline (void) { /* Actually, a sixteen-stage counter tri if (!(++irqCounter &1) && irqEnabled) X6502_IRQBegin(FCEU_IQEXT); } -void Mapper563_power(void) { +static void Mapper563_power(void) { irqEnabled =irqCounter =0; VRC24_power(); SetWriteHandler(0xF000, 0xFFFF, Mapper563_writeIRQ); diff --git a/src/boards/565.c b/src/boards/565.c new file mode 100644 index 0000000..76ccfde --- /dev/null +++ b/src/boards/565.c @@ -0,0 +1,80 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_vrc2and4.h" + +static uint8 irqEnabled; +static uint8 irqCounter; +static uint8 irqPrescaler; +static uint8 irqMask; + +static SFORMAT stateRegs[] ={ + { &irqEnabled, 1, "IRQE" }, + { &irqCounter, 1, "CNTL" }, + { &irqPrescaler, 1, "IRQP" }, + { &irqMask, 1, "IRQC" }, + { 0 } +}; + +static void sync () { + VRC24_syncPRG(0x01F, 0x000); + VRC24_syncCHR(0x1FF, 0x000); + VRC24_syncMirror(); +} + +static DECLFW(writeIRQ) { + switch(A &0x0C) { + case 0: + irqCounter = V; + irqPrescaler = 0; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 4: + irqEnabled = V; + break; + } +} + +void FP_FASTAPASS(1) cpuCycle (int a) { + while (a--) { + if (irqEnabled &1) { + irqPrescaler++; + if (irqPrescaler == 64 && !++irqCounter) X6502_IRQBegin(FCEU_IQEXT); + if (irqPrescaler == 112) irqPrescaler = 0; + } else { + irqPrescaler = 0; + X6502_IRQEnd(FCEU_IQEXT); + } + } +} + +static void power(void) { + irqEnabled = irqCounter = irqPrescaler = irqMask = 0; + VRC24_power(); + SetWriteHandler(0xF000, 0xFFFF, writeIRQ); +} + +void Mapper565_Init (CartInfo *info) { + VRC2_init(info, sync, 0x08, 0x04, NULL, NULL, NULL, NULL); + AddExState(stateRegs, ~0, 0, 0); + info->Power = power; + MapIRQHook = cpuCycle; +} diff --git a/src/ines.c b/src/ines.c index d26c3a3..6145274 100644 --- a/src/ines.c +++ b/src/ines.c @@ -971,6 +971,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Venus Turbo Game Doctor", 562, Mapper561_562_Init ) INES_BOARD( "J-2020", 563, Mapper563_Init ) INES_BOARD( "bd23.pcb", 564, Mapper564_Init ) + INES_BOARD( "J-33-C", 565, Mapper565_Init ) INES_BOARD( "ET-149", 566, Mapper566_Init ) INES_BOARD( "Top Ten Variety (SF III)", 567, Mapper567_Init ) INES_BOARD( "T-227", 568, Mapper568_Init ) diff --git a/src/ines.h b/src/ines.h index 7eb4527..5af07f2 100644 --- a/src/ines.h +++ b/src/ines.h @@ -437,6 +437,7 @@ void Mapper559_Init(CartInfo *); void Mapper561_562_Init(CartInfo *); void Mapper563_Init(CartInfo *); void Mapper564_Init(CartInfo *); +void Mapper565_Init(CartInfo *); void Mapper566_Init(CartInfo *); void Mapper567_Init(CartInfo *); void Mapper568_Init(CartInfo *); From 00b1bd0e9f2abb8eab76f1eb2ac4e97ce5187c44 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Thu, 11 Sep 2025 00:03:29 +0200 Subject: [PATCH 071/109] Add mapper 557. --- src/boards/557.c | 37 ++++++++++++++ src/boards/asic_n118.c | 108 +++++++++++++++++++++++++++++++++++++++++ src/boards/asic_n118.h | 36 ++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 5 files changed, 183 insertions(+) create mode 100644 src/boards/557.c create mode 100644 src/boards/asic_n118.c create mode 100644 src/boards/asic_n118.h diff --git a/src/boards/557.c b/src/boards/557.c new file mode 100644 index 0000000..4f8dff5 --- /dev/null +++ b/src/boards/557.c @@ -0,0 +1,37 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_n118.h" +#include "wram.h" + +static void sync() { + setprg8r(0x10, 0x6000, 0); + N118_syncPRG(0x0F, 0x00); + setchr8(0); + setmirror(N118_getCHRBank(7) &0x20? MI_H: MI_V); +} + +void Mapper557_Init(CartInfo *info) { + N118_init(info, sync, NULL, NULL); + WRAM_init(info, 8); +} diff --git a/src/boards/asic_n118.c b/src/boards/asic_n118.c new file mode 100644 index 0000000..757875a --- /dev/null +++ b/src/boards/asic_n118.c @@ -0,0 +1,108 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_n118.h" + +static void (*N118_cbSync)(); +static int (*N118_cbGetPRGBank)(uint8); +static int (*N118_cbGetCHRBank)(uint8); +static uint8 N118_index; +static uint8 N118_reg[8]; + +static SFORMAT N118_state[] = { + { N118_reg, 8, "N8RG" }, + {&N118_index, 1, "N8IX" }, + { 0 } +}; + +int N118_getPRGBank (uint8 bank) { + return bank &2? (0xFE | bank &1): N118_reg[6 | bank &1]; +} + +int N118_getCHRBank (uint8 bank) { + return bank &4? N118_reg[bank -2]: (N118_reg[bank >>1] &~1 | bank &1); +} + +void N118_syncPRG (int AND, int OR) { + int bank; + for (bank = 0; bank < 4; bank++) setprg8(0x8000 | bank <<13, N118_cbGetPRGBank(bank) &AND |OR); +} + +void N118_syncCHR (int AND, int OR) { + int bank; + for (bank = 0; bank < 8; bank++) setchr1(bank <<10, N118_cbGetCHRBank(bank) &AND |OR); +} + +DECLFW(N118_writeReg) { + if (A &1) { + N118_reg[N118_index &7] = V; + N118_cbSync(); + } else + N118_index = V; +} + +void N118_clear () { + N118_reg[0] = 0; N118_reg[1] = 2; N118_reg[2] = 4; N118_reg[3] = 5; N118_reg[4] = 6; N118_reg[5] = 7; N118_reg[6] = 0; N118_reg[7] = 1; + N118_index = 0; + N118_cbSync(); +} + +static void N118_setHandlers () { + SetReadHandler (0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0x9FFF, N118_writeReg); +} + +static void N118_configure (void (*sync)(), int (*prg)(uint8), int (*chr)(uint8)) { + N118_cbSync = sync; + N118_cbGetPRGBank = prg? prg: N118_getPRGBank; + N118_cbGetCHRBank = chr? chr: N118_getCHRBank; +} + +void N118_activate (uint8 clear, void (*sync)(), int (*prg)(uint8), int (*chr)(uint8)) { + N118_configure(sync, prg, chr); + N118_setHandlers(); + if (clear) + N118_clear(); + else + N118_cbSync(); +} + +void N118_addExState () { + AddExState(N118_state, ~0, 0, 0); +} + +void N118_restore (int version) { + N118_cbSync(); +} + +void N118_power () { + N118_setHandlers(); + N118_clear(); +} + +void N118_init (CartInfo *info, void (*sync)(), int (*prg)(uint8), int (*chr)(uint8)) { + N118_addExState(); + N118_configure(sync, prg, chr); + info->Power = N118_power; + info->Reset = N118_cbSync; + GameStateRestore = N118_restore; +} diff --git a/src/boards/asic_n118.h b/src/boards/asic_n118.h new file mode 100644 index 0000000..77438ae --- /dev/null +++ b/src/boards/asic_n118.h @@ -0,0 +1,36 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_N118_H +#define _ASIC_N118_H + +int N118_getPRGBank (uint8); +int N118_getCHRBank (uint8); +void N118_syncPRG (int, int); +void N118_syncCHR (int, int); +DECLFW (N118_writeReg); +void N118_clear (); +void N118_activate (uint8, void (*)(), int (*)(uint8), int (*)(uint8)); +void N118_addExState(); +void N118_restore (int); +void N118_power (); +void N118_init (CartInfo *, void (*)(), int (*)(uint8), int (*)(uint8)); + +#endif diff --git a/src/ines.c b/src/ines.c index 6145274..0825ede 100644 --- a/src/ines.c +++ b/src/ines.c @@ -965,6 +965,7 @@ INES_BOARD_BEGIN() INES_BOARD( "KS-7010", 554, Mapper554_Init ) INES_BOARD( "", 555, Mapper555_Init ) INES_BOARD( "JY-215", 556, Mapper556_Init ) + INES_BOARD( "NTDEC 2718", 557, Mapper557_Init ) INES_BOARD( "YC-03-09", 558, Mapper558_Init ) INES_BOARD( "Subor Sango II", 559, Mapper559_Init ) INES_BOARD( "Bung Super Game Doctor", 561, Mapper561_562_Init ) diff --git a/src/ines.h b/src/ines.h index 5af07f2..37695a7 100644 --- a/src/ines.h +++ b/src/ines.h @@ -432,6 +432,7 @@ void Mapper553_Init(CartInfo *); void Mapper554_Init(CartInfo *); void Mapper555_Init(CartInfo *); void Mapper556_Init(CartInfo *); +void Mapper557_Init(CartInfo *); void Mapper558_Init(CartInfo *); void Mapper559_Init(CartInfo *); void Mapper561_562_Init(CartInfo *); From 3182bb3ec99092f40bf0af27dc4e204e5866851a Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Thu, 11 Sep 2025 00:06:28 +0200 Subject: [PATCH 072/109] Add mapper 122. --- src/boards/122.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 2 +- src/ines.h | 1 + 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src/boards/122.c diff --git a/src/boards/122.c b/src/boards/122.c new file mode 100644 index 0000000..9021045 --- /dev/null +++ b/src/boards/122.c @@ -0,0 +1,56 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[2]; + +static void sync () { + setprg32(0x8000, 0); + setchr4(0x0000, reg[0]); + setchr4(0x1000, reg[1]); +} + +static DECLFW (writeReg) { + reg[A &1] = V; + sync(); +} + +static void reset () { + reg[0] = reg[1] = 0; + sync(); +} + +static void power () { + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, writeReg); + reset(); +} + +static void stateRestore (int version) { + sync(); +} + +void Mapper122_Init (CartInfo *info) { + info->Reset = reset; + info->Power = power; + GameStateRestore = stateRestore; + AddExState(reg, 2, 0, "REGS"); +} diff --git a/src/ines.c b/src/ines.c index 0825ede..f1fceb1 100644 --- a/src/ines.c +++ b/src/ines.c @@ -575,7 +575,7 @@ INES_BOARD_BEGIN() INES_BOARD( "NES-TQROM", 119, Mapper119_Init ) INES_BOARD( "FDS TOBIDASE", 120, Mapper120_Init ) INES_BOARD( "MMC3 PIRATE PROT. A", 121, Mapper121_Init ) -/* INES_BOARD( "", 122, Mapper122_Init ) */ + INES_BOARD( "JY043", 122, Mapper122_Init ) INES_BOARD( "MMC3 PIRATE H2288", 123, UNLH2288_Init ) /* INES_BOARD( "", 124, Mapper124_Init ) */ INES_BOARD( "FDS LH32", 125, LH32_Init ) diff --git a/src/ines.h b/src/ines.h index 37695a7..6258ca9 100644 --- a/src/ines.h +++ b/src/ines.h @@ -150,6 +150,7 @@ void Mapper117_Init(CartInfo *); void Mapper119_Init(CartInfo *); void Mapper120_Init(CartInfo *); void Mapper121_Init(CartInfo *); +void Mapper122_Init(CartInfo *); void Mapper125_Init(CartInfo *); void Mapper126_Init(CartInfo *); void Mapper128_Init(CartInfo *); From 69ddfae35cafc6be1ed09a0a303589597c4a7d87 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Thu, 11 Sep 2025 00:14:36 +0200 Subject: [PATCH 073/109] Add mapper 552. --- src/boards/{82.c => 82_552.c} | 26 ++++++++++++++++++++------ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 22 insertions(+), 6 deletions(-) rename src/boards/{82.c => 82_552.c} (82%) diff --git a/src/boards/82.c b/src/boards/82_552.c similarity index 82% rename from src/boards/82.c rename to src/boards/82_552.c index fd71c75..5ed4d6b 100644 --- a/src/boards/82.c +++ b/src/boards/82_552.c @@ -26,6 +26,7 @@ static uint8 regs[9], ctrl; static uint8 *WRAM = NULL; static uint32 WRAMSIZE; +static uint8 is552; static SFORMAT StateRegs[] = { @@ -34,6 +35,13 @@ static SFORMAT StateRegs[] = { 0 } }; +uint8 prgBits (uint8 val) { + if (is552) + return val >>5 &0x01 | val >>3 &0x02 | val >>1 &0x04 | val <<1 &0x08 | val <<3 &0x10 | val <<5 &0x20; + else + return val >>2; +} + static void Sync(void) { uint32 swap = ((ctrl & 2) << 11); setchr2(0x0000 ^ swap, regs[0] >> 1); @@ -43,9 +51,9 @@ static void Sync(void) { setchr1(0x1800 ^ swap, regs[4]); setchr1(0x1c00 ^ swap, regs[5]); setprg8r(0x10, 0x6000, 0); - setprg8(0x8000, regs[6]); - setprg8(0xA000, regs[7]); - setprg8(0xC000, regs[8]); + setprg8(0x8000, prgBits(regs[6])); + setprg8(0xA000, prgBits(regs[7])); + setprg8(0xC000, prgBits(regs[8])); setprg8(0xE000, ~0); setmirror(ctrl & 1); } @@ -56,9 +64,9 @@ static DECLFW(M82Write) { else switch (A) { case 0x7ef6: ctrl = V & 3; break; - case 0x7efa: regs[6] = V >> 2; break; - case 0x7efb: regs[7] = V >> 2; break; - case 0x7efc: regs[8] = V >> 2; break; + case 0x7efa: regs[6] = V; break; + case 0x7efb: regs[7] = V; break; + case 0x7efc: regs[8] = V; break; } Sync(); } @@ -82,6 +90,7 @@ static void StateRestore(int version) { } void Mapper82_Init(CartInfo *info) { + is552 = 0; info->Power = M82Power; info->Close = M82Close; @@ -96,3 +105,8 @@ void Mapper82_Init(CartInfo *info) { GameStateRestore = StateRestore; AddExState(&StateRegs, ~0, 0, 0); } + +void Mapper552_Init(CartInfo *info) { + Mapper82_Init(info); + is552 = 1; +} diff --git a/src/ines.c b/src/ines.c index f1fceb1..5d8a1b2 100644 --- a/src/ines.c +++ b/src/ines.c @@ -961,6 +961,7 @@ INES_BOARD_BEGIN() INES_BOARD( "WAIXING FS306", 544, Mapper544_Init ) INES_BOARD( "", 550, Mapper550_Init ) INES_BOARD( "", 551, Mapper178_Init ) + INES_BOARD( "TAITO X1-017", 552, Mapper552_Init ) INES_BOARD( "SACHEN 3013", 553, Mapper553_Init ) INES_BOARD( "KS-7010", 554, Mapper554_Init ) INES_BOARD( "", 555, Mapper555_Init ) diff --git a/src/ines.h b/src/ines.h index 6258ca9..e7fd9f1 100644 --- a/src/ines.h +++ b/src/ines.h @@ -429,6 +429,7 @@ void Mapper542_Init(CartInfo *); void Mapper543_Init(CartInfo *); void Mapper544_Init(CartInfo *); void Mapper550_Init(CartInfo *); +void Mapper552_Init(CartInfo *); void Mapper553_Init(CartInfo *); void Mapper554_Init(CartInfo *); void Mapper555_Init(CartInfo *); From f1576fd15ad272148068c76b9af32aa5a5afb123 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Thu, 11 Sep 2025 00:20:34 +0200 Subject: [PATCH 074/109] Add mapper 549. --- src/boards/549.c | 33 +++++++++++++++++++++++++++++++++ src/boards/asic_latch.c | 3 ++- src/ines.c | 1 + src/ines.h | 1 + 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 src/boards/549.c diff --git a/src/boards/549.c b/src/boards/549.c new file mode 100644 index 0000000..3d62dae --- /dev/null +++ b/src/boards/549.c @@ -0,0 +1,33 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + setprg8(0x6000, Latch_address >>2 | Latch_address >>3 &0x04); + setprg32(0x8000, 2); + setchr8(0); +} + +void Mapper549_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/asic_latch.c b/src/boards/asic_latch.c index f94286b..538ccd0 100644 --- a/src/boards/asic_latch.c +++ b/src/boards/asic_latch.c @@ -48,7 +48,8 @@ void Latch_clear () { } static void Latch_setHandlers() { - SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); SetWriteHandler(Latch_from, Latch_to, Latch_write); } diff --git a/src/ines.c b/src/ines.c index 5d8a1b2..fe5448a 100644 --- a/src/ines.c +++ b/src/ines.c @@ -959,6 +959,7 @@ INES_BOARD_BEGIN() INES_BOARD( "JYV610 830626C", 542, Mapper542_Init ) INES_BOARD( "5-in-1 (CH-501)", 543, Mapper543_Init ) INES_BOARD( "WAIXING FS306", 544, Mapper544_Init ) + INES_BOARD( "Kaiser KS-7016B", 549, Mapper549_Init ) INES_BOARD( "", 550, Mapper550_Init ) INES_BOARD( "", 551, Mapper178_Init ) INES_BOARD( "TAITO X1-017", 552, Mapper552_Init ) diff --git a/src/ines.h b/src/ines.h index e7fd9f1..bcaff87 100644 --- a/src/ines.h +++ b/src/ines.h @@ -428,6 +428,7 @@ void Mapper541_Init(CartInfo *); void Mapper542_Init(CartInfo *); void Mapper543_Init(CartInfo *); void Mapper544_Init(CartInfo *); +void Mapper549_Init(CartInfo *); void Mapper550_Init(CartInfo *); void Mapper552_Init(CartInfo *); void Mapper553_Init(CartInfo *); From eb35ef36df6a154e7ec0ed3758eae80320e151df Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Thu, 11 Sep 2025 00:55:05 +0200 Subject: [PATCH 075/109] Add mapper 273. --- src/boards/273.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++ src/boards/565.c | 8 ++--- src/ines.c | 1 + src/ines.h | 1 + 4 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 src/boards/273.c diff --git a/src/boards/273.c b/src/boards/273.c new file mode 100644 index 0000000..5310d1f --- /dev/null +++ b/src/boards/273.c @@ -0,0 +1,83 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_vrc2and4.h" + +static uint8 irqEnabled; +static uint8 irqCounter; +static uint8 irqPrescaler; +static uint8 irqMask; + +static SFORMAT stateRegs[] ={ + { &irqEnabled, 1, "IRQE" }, + { &irqCounter, 1, "CNTR" }, + { &irqPrescaler, 1, "IRQP" }, + { &irqMask, 1, "IRQM" }, + { 0 } +}; + +static void sync () { + VRC24_syncPRG(0x01F, 0x000); + VRC24_syncCHR(0x1FF, 0x000); + VRC24_syncMirror(); +} + +static DECLFW(writeIRQ) { + switch(A &8) { + case 0: + irqCounter = V; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 8: + irqEnabled = V; + if (~irqEnabled &1) { + irqPrescaler = 0; + irqMask = 0x7F; + X6502_IRQEnd(FCEU_IQEXT); + } + break; + } +} + +static void FP_FASTAPASS(1) cpuCycle (int a) { + while (a--) { + if (irqEnabled &1 && !(++irqPrescaler &irqMask)) { + irqMask = 0xFF; + if (!++irqCounter) + X6502_IRQBegin(FCEU_IQEXT); + else + X6502_IRQEnd(FCEU_IQEXT); + } + } +} + +static void power(void) { + irqEnabled = irqCounter = irqPrescaler = irqMask = 0; + VRC24_power(); + SetWriteHandler(0xF000, 0xFFFF, writeIRQ); +} + +void Mapper273_Init (CartInfo *info) { + VRC2_init(info, sync, 0x04, 0x08, NULL, NULL, NULL, NULL); + AddExState(stateRegs, ~0, 0, 0); + info->Power = power; + MapIRQHook = cpuCycle; +} diff --git a/src/boards/565.c b/src/boards/565.c index 76ccfde..722cf17 100644 --- a/src/boards/565.c +++ b/src/boards/565.c @@ -24,13 +24,11 @@ static uint8 irqEnabled; static uint8 irqCounter; static uint8 irqPrescaler; -static uint8 irqMask; static SFORMAT stateRegs[] ={ { &irqEnabled, 1, "IRQE" }, - { &irqCounter, 1, "CNTL" }, + { &irqCounter, 1, "CNTR" }, { &irqPrescaler, 1, "IRQP" }, - { &irqMask, 1, "IRQC" }, { 0 } }; @@ -53,7 +51,7 @@ static DECLFW(writeIRQ) { } } -void FP_FASTAPASS(1) cpuCycle (int a) { +static void FP_FASTAPASS(1) cpuCycle (int a) { while (a--) { if (irqEnabled &1) { irqPrescaler++; @@ -67,7 +65,7 @@ void FP_FASTAPASS(1) cpuCycle (int a) { } static void power(void) { - irqEnabled = irqCounter = irqPrescaler = irqMask = 0; + irqEnabled = irqCounter = irqPrescaler = 0; VRC24_power(); SetWriteHandler(0xF000, 0xFFFF, writeIRQ); } diff --git a/src/ines.c b/src/ines.c index fe5448a..3acaa15 100644 --- a/src/ines.c +++ b/src/ines.c @@ -728,6 +728,7 @@ INES_BOARD_BEGIN() INES_BOARD( "OneBus+412C Bankswitch", 270, Mapper270_Init ) INES_BOARD( "MGC-026", 271, Mapper271_Init ) INES_BOARD( "Akumajō Special: Boku Dracula-kun", 272, Mapper272_Init ) + INES_BOARD( "J-3?-C", 273, Mapper273_Init ) INES_BOARD( "80013-B", 274, BMC80013B_Init ) INES_BOARD( "", 277, Mapper277_Init ) INES_BOARD( "K-3017", 280, Mapper280_Init ) diff --git a/src/ines.h b/src/ines.h index bcaff87..5024027 100644 --- a/src/ines.h +++ b/src/ines.h @@ -254,6 +254,7 @@ void Mapper255_Init(CartInfo *); void GN45_Init(CartInfo *info); /* m361, m366 */ void Mapper270_Init(CartInfo *); void Mapper272_Init(CartInfo *); +void Mapper273_Init(CartInfo *); void Mapper277_Init(CartInfo *); void Mapper280_Init(CartInfo *); void Mapper281_Init(CartInfo *); From bb0f65dc0cbf06af7c4ff7a4706ab394675d149e Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Thu, 11 Sep 2025 22:52:54 +0200 Subject: [PATCH 076/109] Add mapper 321. --- src/boards/321.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ src/boards/490.c | 1 + src/ines.c | 1 + src/ines.h | 1 + 4 files changed, 60 insertions(+) create mode 100644 src/boards/321.c diff --git a/src/boards/321.c b/src/boards/321.c new file mode 100644 index 0000000..8b5f0a0 --- /dev/null +++ b/src/boards/321.c @@ -0,0 +1,57 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync () { + if (reg &0x08) + setprg32(0x8000, reg &0x04 | reg >>4 &0x03); + else + MMC3_syncPRG(0x0F, reg <<2 &~0x0F); + MMC3_syncCHR(0x7F, reg <<5 &~0x7F); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + reg = V; + sync(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +void Mapper321_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/490.c b/src/boards/490.c index 67bc48a..2403ed9 100644 --- a/src/boards/490.c +++ b/src/boards/490.c @@ -64,4 +64,5 @@ void Mapper490_Init(CartInfo *info) { info->Power = power; info->Reset = reset; AddExState(®, 1, 0, "EXPR"); + AddExState(&pad, 1, 0, "DIPS"); } diff --git a/src/ines.c b/src/ines.c index 3acaa15..650452a 100644 --- a/src/ines.c +++ b/src/ines.c @@ -766,6 +766,7 @@ INES_BOARD_BEGIN() INES_BOARD( "830134C", 315, BMC830134C_Init ) INES_BOARD( "HP898F", 319, Mapper319_Init ) INES_BOARD( "830425C-4391T", 320, BMC830425C4391T_Init ) + INES_BOARD( "820310", 321, Mapper321_Init ) INES_BOARD( "K-3033", 322, BMCK3033_Init ) INES_BOARD( "FARID_SLROM_8-IN-1", 323, FARIDSLROM8IN1_Init ) INES_BOARD( "FARID_UNROM_8-IN-1", 324, FARIDUNROM_Init ) diff --git a/src/ines.h b/src/ines.h index 5024027..35b3670 100644 --- a/src/ines.h +++ b/src/ines.h @@ -276,6 +276,7 @@ void Mapper294_Init(CartInfo *); void Mapper297_Init(CartInfo *); void Mapper310_Init(CartInfo *); void Mapper319_Init(CartInfo *); +void Mapper321_Init(CartInfo *); void Mapper326_Init(CartInfo *); void Mapper330_Init(CartInfo *); void Mapper334_Init(CartInfo *); From 05983b1b28999e6984c00a78c2163c868d3e9039 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Thu, 11 Sep 2025 22:58:04 +0200 Subject: [PATCH 077/109] Add mapper 352. --- src/boards/352.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 52 insertions(+) create mode 100644 src/boards/352.c diff --git a/src/boards/352.c b/src/boards/352.c new file mode 100644 index 0000000..10c6986 --- /dev/null +++ b/src/boards/352.c @@ -0,0 +1,50 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 game; + +static void sync () { + setprg32(0x8000, game); + setchr8(game); +} + +static void power() { + SetReadHandler(0x6000, 0xFFFF, CartBR); + game = 0; + sync(); +} + +static void reset() { + if (++game >= ROM_size /2) game = 0; + sync(); +} + +static void stateRestore(int version) { + sync(); +} + +void Mapper352_Init (CartInfo *info) { + info->Power = power; + info->Reset = reset; + GameStateRestore = stateRestore; + AddExState(&game, 1, 0, "GAME"); +} diff --git a/src/ines.c b/src/ines.c index 650452a..9a962ae 100644 --- a/src/ines.c +++ b/src/ines.c @@ -796,6 +796,7 @@ INES_BOARD_BEGIN() INES_BOARD( "G-146", 349, BMCG146_Init ) INES_BOARD( "891227", 350, BMC891227_Init ) INES_BOARD( "Techline XB", 351, Mapper351_Init ) + INES_BOARD( "Reset-based NROM-256", 352, Mapper352_Init ) INES_BOARD( "Super Mario Family", 353, Mapper353_Init ) INES_BOARD( "FAM250/81-01-39-C/SCHI-24",354, Mapper354_Init ) INES_BOARD( "3D-BLOCK", 355, UNL3DBlock_Init ) diff --git a/src/ines.h b/src/ines.h index 35b3670..34a42bf 100644 --- a/src/ines.h +++ b/src/ines.h @@ -281,6 +281,7 @@ void Mapper326_Init(CartInfo *); void Mapper330_Init(CartInfo *); void Mapper334_Init(CartInfo *); void Mapper351_Init(CartInfo *); +void Mapper352_Init(CartInfo *); void Mapper353_Init(CartInfo *); void Mapper354_Init(CartInfo *); void Mapper356_Init(CartInfo *); From ca898191dbeebb96f279f9f7357c370fb409bdb6 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Thu, 11 Sep 2025 23:11:47 +0200 Subject: [PATCH 078/109] Add mapper 363. --- src/boards/363.c | 39 +++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 41 insertions(+) create mode 100644 src/boards/363.c diff --git a/src/boards/363.c b/src/boards/363.c new file mode 100644 index 0000000..2916e41 --- /dev/null +++ b/src/boards/363.c @@ -0,0 +1,39 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + setprg16(0x8000, Latch_address <<3 | Latch_data &0x07); + setprg16(0xC000, Latch_address <<3 | 0x07); + setchr8(0); + setmirror(Latch_address &0x20? MI_H: MI_V); +} + +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { + if (!(~Latch_address &0x10 && *newAddress &0x10)) *newAddress = Latch_address; /* Address bits only latched on a rising edge of A4 */ + *newValue &= romValue; /* AND-type bus conflicts */ +} + +void Mapper363_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); + info->Reset = Latch_clear; +} diff --git a/src/ines.c b/src/ines.c index 9a962ae..8e98837 100644 --- a/src/ines.c +++ b/src/ines.c @@ -807,6 +807,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Bitcorp 31-in-1", 360, Mapper360_Init ) INES_BOARD( "OK-411", 361, GN45_Init ) /* OK-411 is emulated together with GN-45 */ INES_BOARD( "830506C", 362, Mapper362_Init ) + INES_BOARD( "5069", 363, Mapper363_Init ) INES_BOARD( "JY830832C", 364, Mapper364_Init ) INES_BOARD( "GN-45", 366, GN45_Init ) INES_BOARD( "JC-016-2 variant", 367, Mapper367_Init ) diff --git a/src/ines.h b/src/ines.h index 34a42bf..ee6f074 100644 --- a/src/ines.h +++ b/src/ines.h @@ -290,6 +290,7 @@ void Mapper358_Init(CartInfo *); void Mapper359_Init(CartInfo *); void Mapper360_Init(CartInfo *); void Mapper362_Init(CartInfo *); +void Mapper363_Init(CartInfo *); void Mapper364_Init(CartInfo *); void Mapper367_Init(CartInfo *); void Mapper368_Init(CartInfo *); From 05df68148fe373aad6af904dc8d19c4770c2ae54 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Thu, 11 Sep 2025 23:15:49 +0200 Subject: [PATCH 079/109] Add mapper 378. --- src/boards/378.c | 39 +++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 41 insertions(+) create mode 100644 src/boards/378.c diff --git a/src/boards/378.c b/src/boards/378.c new file mode 100644 index 0000000..8e595d0 --- /dev/null +++ b/src/boards/378.c @@ -0,0 +1,39 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_data &0x20) { + setprg16(0x8000, 0x10 | Latch_data <<1 &0x0E | Latch_data >>3 &0x01); + setprg16(0xC000, 0x10 | Latch_data <<1 &0x0E | 0x07); + setmirror(Latch_data &0x04? MI_H: MI_V); + } else { + setprg32(0x8000, Latch_data &0x07); + setmirror(Latch_data &0x10? MI_1: MI_0); + } + setchr8(0); +} + +void Mapper378_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/ines.c b/src/ines.c index 8e98837..fba0f83 100644 --- a/src/ines.c +++ b/src/ines.c @@ -820,6 +820,7 @@ INES_BOARD_BEGIN() INES_BOARD( "135-in-1", 375, Mapper375_Init ) INES_BOARD( "YY841155C", 376, Mapper376_Init ) INES_BOARD( "JY-111/JY-112", 377, Mapper377_Init ) + INES_BOARD( "8-in-1 AOROM+UNROM", 378, Mapper378_Init ) INES_BOARD( "42 to 80,000 (970630C)", 380, Mapper380_Init ) INES_BOARD( "KN-42", 381, Mapper381_Init ) INES_BOARD( "830928C", 382, Mapper382_Init ) diff --git a/src/ines.h b/src/ines.h index ee6f074..6c78cb4 100644 --- a/src/ines.h +++ b/src/ines.h @@ -302,6 +302,7 @@ void Mapper374_Init(CartInfo *); void Mapper375_Init(CartInfo *); void Mapper376_Init(CartInfo *); void Mapper377_Init(CartInfo *); +void Mapper378_Init(CartInfo *); void Mapper380_Init(CartInfo *); void Mapper381_Init(CartInfo *); void Mapper382_Init(CartInfo *); From 1fc60df5413049ca670346928c81339a93020ae2 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Thu, 11 Sep 2025 23:17:46 +0200 Subject: [PATCH 080/109] Add mapper 379. --- src/boards/379.c | 32 ++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 34 insertions(+) create mode 100644 src/boards/379.c diff --git a/src/boards/379.c b/src/boards/379.c new file mode 100644 index 0000000..3e798bf --- /dev/null +++ b/src/boards/379.c @@ -0,0 +1,32 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + setprg32(0x8000, Latch_data &0x03); + setchr8(Latch_data >>2); +} + +void Mapper379_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/ines.c b/src/ines.c index fba0f83..2a02322 100644 --- a/src/ines.c +++ b/src/ines.c @@ -821,6 +821,7 @@ INES_BOARD_BEGIN() INES_BOARD( "YY841155C", 376, Mapper376_Init ) INES_BOARD( "JY-111/JY-112", 377, Mapper377_Init ) INES_BOARD( "8-in-1 AOROM+UNROM", 378, Mapper378_Init ) + INES_BOARD( "35BH-1", 379, Mapper379_Init ) INES_BOARD( "42 to 80,000 (970630C)", 380, Mapper380_Init ) INES_BOARD( "KN-42", 381, Mapper381_Init ) INES_BOARD( "830928C", 382, Mapper382_Init ) diff --git a/src/ines.h b/src/ines.h index 6c78cb4..be3e826 100644 --- a/src/ines.h +++ b/src/ines.h @@ -303,6 +303,7 @@ void Mapper375_Init(CartInfo *); void Mapper376_Init(CartInfo *); void Mapper377_Init(CartInfo *); void Mapper378_Init(CartInfo *); +void Mapper379_Init(CartInfo *); void Mapper380_Init(CartInfo *); void Mapper381_Init(CartInfo *); void Mapper382_Init(CartInfo *); From 7a06acbacb8040a110692f302b677bfb39ed6426 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Thu, 11 Sep 2025 23:21:34 +0200 Subject: [PATCH 081/109] Add mapper 418. --- src/boards/418.c | 34 ++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 36 insertions(+) create mode 100644 src/boards/418.c diff --git a/src/boards/418.c b/src/boards/418.c new file mode 100644 index 0000000..26a5996 --- /dev/null +++ b/src/boards/418.c @@ -0,0 +1,34 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_n118.h" + +static void sync () { + N118_syncPRG(0x0F, 0x00); + setchr8(0); + setmirror(N118_getCHRBank(7) &0x01? MI_H: MI_V); +} + +void Mapper418_Init (CartInfo *info) { + N118_init(info, sync, NULL, NULL); +} diff --git a/src/ines.c b/src/ines.c index 2a02322..5f86258 100644 --- a/src/ines.c +++ b/src/ines.c @@ -857,6 +857,7 @@ INES_BOARD_BEGIN() INES_BOARD( "0353", 415, Mapper415_Init ) INES_BOARD( "4-in-1/N-32", 416, Mapper416_Init ) INES_BOARD( "", 417, Mapper417_Init ) + INES_BOARD( "820106-C/821007C", 418, Mapper418_Init ) INES_BOARD( "A971210", 420, Mapper420_Init ) INES_BOARD( "SC871115C", 421, Mapper421_Init ) INES_BOARD( "BS-400R/BS-4040", 422, Mapper422_Init ) diff --git a/src/ines.h b/src/ines.h index be3e826..36f1d25 100644 --- a/src/ines.h +++ b/src/ines.h @@ -338,6 +338,7 @@ void Mapper414_Init(CartInfo *); void Mapper415_Init(CartInfo *); void Mapper416_Init(CartInfo *); void Mapper417_Init(CartInfo *); +void Mapper418_Init(CartInfo *); void Mapper420_Init(CartInfo *); void Mapper421_Init(CartInfo *); void Mapper422_Init(CartInfo *); From ed8ab6a450215158c6ae4215861ae1bc559a70b6 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Thu, 11 Sep 2025 23:39:40 +0200 Subject: [PATCH 082/109] Add mapper 483. --- src/boards/483.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 81 insertions(+) create mode 100644 src/boards/483.c diff --git a/src/boards/483.c b/src/boards/483.c new file mode 100644 index 0000000..d033363 --- /dev/null +++ b/src/boards/483.c @@ -0,0 +1,79 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +/* 3927 PCB, reset-based MMC1/CNROM multicart. The common dump with mapper number 3927 has an unrealistic bank order. */ + +#include "mapinc.h" +#include "asic_latch.h" +#include "asic_mmc1.h" + +static uint8 game; + +static void sync_SLROM () { + MMC1_syncPRG(0x07, game <<3); + MMC1_syncCHR(0x1F, game <<5); + MMC1_syncMirror(); +} + +static void sync_CNROM () { + setprg32(0x8000, 0x0C +game -3); + setchr8(0x30 | (game -3) <<2 | Latch_data &0x03); + setmirror(MI_V); +} + +static void sync_SEROM () { + setprg32(0x8000, 0x0F); + MMC1_syncCHR(0x07, 0x78); + MMC1_syncMirror(); +} + +static void applyMode (uint8 clear) { + if (game <= 2) + MMC1_activate(clear, sync_SLROM, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL); + else + if (game <= 5) + Latch_activate(clear, sync_CNROM, 0x8000, 0xFFFF, NULL); + else + MMC1_activate(clear, sync_SEROM, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL); +} + +static void reset () { + if (++game >=7) game = 0; + applyMode(1); +} + +static void power () { + game = 0; + applyMode(1); +} + +static void stateRestore(int version) { + applyMode(0); +} +void Mapper483_Init (CartInfo *info) { + AddExState(&game, 1, 0, "GAME"); + Latch_addExState(); + MMC1_addExState(); + info->Power = power; + info->Reset = reset; + GameStateRestore = stateRestore; +} diff --git a/src/ines.c b/src/ines.c index 5f86258..14cb968 100644 --- a/src/ines.c +++ b/src/ines.c @@ -912,6 +912,7 @@ INES_BOARD_BEGIN() INES_BOARD( "480", 480, Mapper480_Init ) INES_BOARD( "045N", 481, Mapper481_Init ) INES_BOARD( "K-1079", 482, Mapper482_Init ) + INES_BOARD( "3927", 483, Mapper483_Init ) INES_BOARD( "ESTIQUE", 484, Mapper484_Init ) INES_BOARD( "0359", 485, Mapper485_Init ) INES_BOARD( "KS7009", 486, Mapper486_Init ) diff --git a/src/ines.h b/src/ines.h index 36f1d25..e179c7f 100644 --- a/src/ines.h +++ b/src/ines.h @@ -393,6 +393,7 @@ void Mapper478_Init(CartInfo *); void Mapper480_Init(CartInfo *); void Mapper481_Init(CartInfo *); void Mapper482_Init(CartInfo *); +void Mapper483_Init(CartInfo *); void Mapper484_Init(CartInfo *); void Mapper485_Init(CartInfo *); void Mapper486_Init(CartInfo *); From 6a647bab8fce658ed37a7f3648085c35820dda0d Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Thu, 11 Sep 2025 23:42:41 +0200 Subject: [PATCH 083/109] Add mapper 517 (partial, no microphone input, so identical to UNROM). --- src/ines.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ines.c b/src/ines.c index 14cb968..7e1110a 100644 --- a/src/ines.c +++ b/src/ines.c @@ -941,7 +941,8 @@ INES_BOARD_BEGIN() INES_BOARD( "1n4148", 511, Mapper511_Init ) INES_BOARD( "Zhonggguo Daheng", 512, Mapper512_Init ) INES_BOARD( "SA-9602B", 513, SA9602B_Init ) - INES_BOARD( "Brilliant Com Cocoma Pack",516, Mapper516_Init ) + INES_BOARD( "Brilliant Com Cocoma Pack",516, Mapper516_Init ) + INES_BOARD( "Kkachi-wa Nolae Chingu", 517, UNROM_Init ) /* Microphone input currently not emulated */ INES_BOARD( "DANCE2000", 518, UNLD2000_Init ) INES_BOARD( "EH8813A", 519, UNLEH8813A_Init ) INES_BOARD( "YuYuHakusho+DBZ", 520, Mapper520_Init ) From 93e4f5905f86af26213204461918f5f1097bb3df Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 00:29:19 +0200 Subject: [PATCH 084/109] Add mapper 518. --- src/boards/514.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 50 insertions(+) create mode 100644 src/boards/514.c diff --git a/src/boards/514.c b/src/boards/514.c new file mode 100644 index 0000000..fb8d823 --- /dev/null +++ b/src/boards/514.c @@ -0,0 +1,48 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" +#include "wram.h" + +uint8 chr; + +static void sync () { + setprg8r(0x10, 0x6000, 0); + setprg32(0x8000, Latch_data); + setchr4(0x0000, Latch_data &0x80? chr: 0); + setchr4(0x1000, 1); + setmirror(Latch_data &0x40? MI_H: MI_V); +} + +static void FP_FASTAPASS(1) trapPPUAddressChange (uint32 A) { + if (A &0x2000 && (A &0x23C0) < 0x23C0) { + chr = A >>(10 +(Latch_data &0x40? 1: 0)) &1; + setchr4(0x0000, Latch_data &0x80? chr: 0); + } +} + +void Mapper514_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + WRAM_init(info, 8); + info->Reset = Latch_clear; + PPU_hook = trapPPUAddressChange; + AddExState(&chr, 1, 0, "CHRB"); +} diff --git a/src/ines.c b/src/ines.c index 7e1110a..5969e5d 100644 --- a/src/ines.c +++ b/src/ines.c @@ -941,6 +941,7 @@ INES_BOARD_BEGIN() INES_BOARD( "1n4148", 511, Mapper511_Init ) INES_BOARD( "Zhonggguo Daheng", 512, Mapper512_Init ) INES_BOARD( "SA-9602B", 513, SA9602B_Init ) + INES_BOARD( "Subor Karaoke", 514, Mapper514_Init ) INES_BOARD( "Brilliant Com Cocoma Pack",516, Mapper516_Init ) INES_BOARD( "Kkachi-wa Nolae Chingu", 517, UNROM_Init ) /* Microphone input currently not emulated */ INES_BOARD( "DANCE2000", 518, UNLD2000_Init ) diff --git a/src/ines.h b/src/ines.h index e179c7f..b255d79 100644 --- a/src/ines.h +++ b/src/ines.h @@ -421,6 +421,7 @@ void Mapper509_Init(CartInfo *); void Mapper510_Init(CartInfo *); void Mapper511_Init(CartInfo *); void Mapper512_Init(CartInfo *); +void Mapper514_Init(CartInfo *); void Mapper516_Init(CartInfo *); void Mapper520_Init(CartInfo *); void Mapper523_Init(CartInfo *); From f134f99237a8176bdc0a6ffbedd9c0c0fc9029fa Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 00:57:17 +0200 Subject: [PATCH 085/109] Add mapper 545. --- src/boards/514.c | 2 +- src/boards/545.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/boards/545.c diff --git a/src/boards/514.c b/src/boards/514.c index fb8d823..a8b674d 100644 --- a/src/boards/514.c +++ b/src/boards/514.c @@ -22,7 +22,7 @@ #include "asic_latch.h" #include "wram.h" -uint8 chr; +static uint8 chr; static void sync () { setprg8r(0x10, 0x6000, 0); diff --git a/src/boards/545.c b/src/boards/545.c new file mode 100644 index 0000000..5a339e5 --- /dev/null +++ b/src/boards/545.c @@ -0,0 +1,70 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" +#include "wram.h" + +static uint8 reg; + +static void sync () { + MMC3_syncWRAM(0); + MMC3_syncPRG(0x7F, 0x00); + MMC3_syncCHR(0x7F, reg <<7 | ~reg <<4 &0x40); + MMC3_syncMirror(); +} + +static int getPRGBank (uint8 bank) { + int result = MMC3_getPRGBank(bank); + if (reg &0x08 && ~result &0x10) + result = 0x40 | result &0x0F; + else + result = reg <<4 &0x30 | result &0x0F; + return result; +} + +static DECLFW (writeReg) { + if (A &0x020 && A &0x100) { + reg = V; + sync(); + } else + MMC3_writeReg(A, V); +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); + SetWriteHandler(0xF000, 0xFFFF, writeReg); +} + +void Mapper545_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, getPRGBank, NULL, NULL, NULL); + WRAM_init(info, 8); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/ines.c b/src/ines.c index 5969e5d..4fb2ea5 100644 --- a/src/ines.c +++ b/src/ines.c @@ -969,6 +969,7 @@ INES_BOARD_BEGIN() INES_BOARD( "JYV610 830626C", 542, Mapper542_Init ) INES_BOARD( "5-in-1 (CH-501)", 543, Mapper543_Init ) INES_BOARD( "WAIXING FS306", 544, Mapper544_Init ) + INES_BOARD( "ST-80", 545, Mapper545_Init ) INES_BOARD( "Kaiser KS-7016B", 549, Mapper549_Init ) INES_BOARD( "", 550, Mapper550_Init ) INES_BOARD( "", 551, Mapper178_Init ) diff --git a/src/ines.h b/src/ines.h index b255d79..f6cb9d4 100644 --- a/src/ines.h +++ b/src/ines.h @@ -437,6 +437,7 @@ void Mapper541_Init(CartInfo *); void Mapper542_Init(CartInfo *); void Mapper543_Init(CartInfo *); void Mapper544_Init(CartInfo *); +void Mapper545_Init(CartInfo *); void Mapper549_Init(CartInfo *); void Mapper550_Init(CartInfo *); void Mapper552_Init(CartInfo *); From 48018ab086ae401682871f7b007463eccb84412a Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 01:05:43 +0200 Subject: [PATCH 086/109] Add mapper 546. --- src/boards/546.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 72 insertions(+) create mode 100644 src/boards/546.c diff --git a/src/boards/546.c b/src/boards/546.c new file mode 100644 index 0000000..df9e8ef --- /dev/null +++ b/src/boards/546.c @@ -0,0 +1,70 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc1.h" +#include "wram.h" + +static uint8 reg; + +static void sync () { + MMC1_syncWRAM(0); + if (reg &0x10) + MMC1_syncPRG(0x0F, 0x10); + else + if (reg &0x20) + setprg32(0x8000, reg >>1); + else { + setprg16(0x8000, reg); + setprg16(0xC000, reg); + } + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], reg &0x80? 0: 1); + setchr8(0); + MMC1_syncMirror(); +} + +static DECLFW (writeReg) { + if (!(A &0x0F00)) { + reg = A &0xFF; + sync(); + } + MMC1_writeReg(A, V); +} + +static void reset () { + reg = 0; + MMC1_clear(); +} + +static void power () { + reg = 0; + MMC1_power(); + SetWriteHandler(0x8000, 0x9FFF, writeReg); +} + +void Mapper546_Init (CartInfo *info) { + MMC1_init(info, sync, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL); + WRAM_init(info, 8); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/ines.c b/src/ines.c index 4fb2ea5..51df3dd 100644 --- a/src/ines.c +++ b/src/ines.c @@ -970,6 +970,7 @@ INES_BOARD_BEGIN() INES_BOARD( "5-in-1 (CH-501)", 543, Mapper543_Init ) INES_BOARD( "WAIXING FS306", 544, Mapper544_Init ) INES_BOARD( "ST-80", 545, Mapper545_Init ) + INES_BOARD( "03-101", 546, Mapper546_Init ) INES_BOARD( "Kaiser KS-7016B", 549, Mapper549_Init ) INES_BOARD( "", 550, Mapper550_Init ) INES_BOARD( "", 551, Mapper178_Init ) diff --git a/src/ines.h b/src/ines.h index f6cb9d4..a7b1b53 100644 --- a/src/ines.h +++ b/src/ines.h @@ -438,6 +438,7 @@ void Mapper542_Init(CartInfo *); void Mapper543_Init(CartInfo *); void Mapper544_Init(CartInfo *); void Mapper545_Init(CartInfo *); +void Mapper546_Init(CartInfo *); void Mapper549_Init(CartInfo *); void Mapper550_Init(CartInfo *); void Mapper552_Init(CartInfo *); From f56be8ce5e5c379c0ae12d64107744aee769592a Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 01:25:50 +0200 Subject: [PATCH 087/109] Add mapper 548. --- src/boards/548.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 109 insertions(+) create mode 100644 src/boards/548.c diff --git a/src/boards/548.c b/src/boards/548.c new file mode 100644 index 0000000..0ca04ca --- /dev/null +++ b/src/boards/548.c @@ -0,0 +1,107 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +/* The UNIF dump of "(JY-103) 3-in-1" (JY4M4 MAPR) has a strange bank order and will not run with this emulation. */ + +#include "mapinc.h" +#include "wram.h" +#include "../fds_apu.h" + +static uint8 reg; +static uint8 latch; +static uint8 counting; +static uint16 counter; + +static SFORMAT stateRegs[] ={ + { ®, 1, "REGM" }, + { &latch, 1, "LATC" }, + { &counting, 1, "IRQA" }, + { &counter, 2, "IRQC" }, + { 0 } +}; + +static void sync () { + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, reg); + setprg16(0xC000, 3); + setchr8(0); +} + +static DECLFW (writeLatch) { + latch = A >>2 &0x03 | A >>3 &0x04; + if (A &4) { + counting = 0; + counter = 0; + X6502_IRQEnd(FCEU_IQEXT); + } else + counting = 1; +} + +static DECLFW (writeReg) { + reg = latch ^0x05; + sync(); +} + +static void FP_FASTAPASS(1) cpuCycle (int a) { + while (a--) { + if (counting) { + if (counter == 23680) + X6502_IRQBegin(FCEU_IQEXT); + else + if (counter == 24320) + X6502_IRQEnd(FCEU_IQEXT); + counter++; + } + } +} + +static void reset() { + FDSSoundReset(); + X6502_IRQEnd(FCEU_IQEXT); + latch = 0x07; + reg = latch ^0x05; + counting = 0; + counter = 0; + sync(); +} + +static void power() { + FDSSoundPower(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x4800, 0x4FFF, writeLatch); + SetWriteHandler(0x5000, 0x57FF, writeReg); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + reset(); +} + +static void stateRestore(int version) { + sync(); +} + +void Mapper548_Init (CartInfo *info) { + WRAM_init(info, 8); + info->Power = power; + info->Reset = reset; + MapIRQHook = cpuCycle; + GameStateRestore = stateRestore; + AddExState(stateRegs, ~0, 0, 0); +} diff --git a/src/ines.c b/src/ines.c index 51df3dd..ae50efc 100644 --- a/src/ines.c +++ b/src/ines.c @@ -971,6 +971,7 @@ INES_BOARD_BEGIN() INES_BOARD( "WAIXING FS306", 544, Mapper544_Init ) INES_BOARD( "ST-80", 545, Mapper545_Init ) INES_BOARD( "03-101", 546, Mapper546_Init ) + INES_BOARD( "CTC-15", 548, Mapper548_Init ) INES_BOARD( "Kaiser KS-7016B", 549, Mapper549_Init ) INES_BOARD( "", 550, Mapper550_Init ) INES_BOARD( "", 551, Mapper178_Init ) diff --git a/src/ines.h b/src/ines.h index a7b1b53..a56fd6b 100644 --- a/src/ines.h +++ b/src/ines.h @@ -439,6 +439,7 @@ void Mapper543_Init(CartInfo *); void Mapper544_Init(CartInfo *); void Mapper545_Init(CartInfo *); void Mapper546_Init(CartInfo *); +void Mapper548_Init(CartInfo *); void Mapper549_Init(CartInfo *); void Mapper550_Init(CartInfo *); void Mapper552_Init(CartInfo *); From 92d2a150adb77543360c479b318612fc11d96022 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 01:28:11 +0200 Subject: [PATCH 088/109] Cleanup mappers 548 and 549. --- src/boards/548.c | 2 -- src/boards/549.c | 14 +++++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/boards/548.c b/src/boards/548.c index 0ca04ca..013dc7c 100644 --- a/src/boards/548.c +++ b/src/boards/548.c @@ -20,8 +20,6 @@ * */ -/* The UNIF dump of "(JY-103) 3-in-1" (JY4M4 MAPR) has a strange bank order and will not run with this emulation. */ - #include "mapinc.h" #include "wram.h" #include "../fds_apu.h" diff --git a/src/boards/549.c b/src/boards/549.c index 3d62dae..18cfa13 100644 --- a/src/boards/549.c +++ b/src/boards/549.c @@ -20,6 +20,7 @@ #include "mapinc.h" #include "asic_latch.h" +#include "../fds_apu.h" static void sync () { setprg8(0x6000, Latch_address >>2 | Latch_address >>3 &0x04); @@ -27,7 +28,18 @@ static void sync () { setchr8(0); } +static void power() { + Latch_power(); + FDSSoundPower(); +} + +static void reset() { + FDSSoundReset(); + Latch_clear(); +} + void Mapper549_Init (CartInfo *info) { Latch_init(info, sync, 0x8000, 0xFFFF, NULL); - info->Reset = Latch_clear; + info->Power = power; + info->Reset = reset; } From 21979314851bba25523158763145f7c3fd3558a5 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 01:41:42 +0200 Subject: [PATCH 089/109] Replaced mapper 461 with Wuzi Gun 6-in-1 (previous mapper 461 was reassigned to to 61 for a long time). --- src/boards/461.c | 60 ++++++++++++++++++++++++++++++++++++++++++ src/boards/addrlatch.c | 18 ------------- src/ines.c | 2 +- 3 files changed, 61 insertions(+), 19 deletions(-) create mode 100644 src/boards/461.c diff --git a/src/boards/461.c b/src/boards/461.c new file mode 100644 index 0000000..47d20c8 --- /dev/null +++ b/src/boards/461.c @@ -0,0 +1,60 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc1.h" + +static uint8 reg; + +static void sync () { + if (reg &0x04) { + MMC1_syncPRG(reg &0x08? 0x07: 0x03, reg &0x0C); + MMC1_syncCHR(0x1F, reg <<2 &0x20); + } else { + setprg16(0x8000, reg &0x03); + setprg16(0xC000, reg &0x03); + MMC1_syncCHR(0x07, 0x40); + } + MMC1_syncMirror(); +} + +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset () { + reg = 0; + MMC1_clear(); +} + +static void power () { + reg = 0; + MMC1_power(); +} + +void Mapper461_Init (CartInfo *info) { + MMC1_init(info, sync, MMC1_TYPE_MMC1A, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c index 6178337..ea3c0ed 100644 --- a/src/boards/addrlatch.c +++ b/src/boards/addrlatch.c @@ -832,24 +832,6 @@ void Mapper459_Init(CartInfo *info) { Latch_Init(info, M459Sync, NULL, 0x0000, 0x8000, 0xFFFF, 1); } -/*------------------ Map 461 ---------------------------*/ -static void M461Sync(void) { - int p =latche <<1 | latche >>5 &1; - int c =latche >>8; - if (latche &0x10) { - setprg16(0x8000, p); - setprg16(0xC000, p); - } else { - setprg32(0x8000, p >>1); - } - setchr8(c); - setmirror(latche &0x80? MI_H: MI_V); -} - -void Mapper461_Init(CartInfo *info) { - Latch_Init(info, M461Sync, NULL, 0x0000, 0x8000, 0xFFFF, 1); -} - /*------------------ Map 464 ---------------------------*/ static void M464Sync(void) { int p =latche >>7; diff --git a/src/ines.c b/src/ines.c index ae50efc..70222f9 100644 --- a/src/ines.c +++ b/src/ines.c @@ -892,7 +892,7 @@ INES_BOARD_BEGIN() INES_BOARD( "", 458, Mapper458_Init ) INES_BOARD( "8-in-1", 459, Mapper459_Init ) INES_BOARD( "FC-29-40/K-3101", 460, Mapper460_Init ) - INES_BOARD( "0324", 461, Mapper461_Init ) + INES_BOARD( "CM-9309", 461, Mapper461_Init ) INES_BOARD( "BMC-971107-00G", 462, Mapper462_Init ) INES_BOARD( "YH810X1", 463, Mapper463_Init ) INES_BOARD( "NTDEC 9012", 464, Mapper464_Init ) From b6870c3e146105b646e5d3505fcddf34ebaa9603 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 01:54:00 +0200 Subject: [PATCH 090/109] Mapper 176: Fixed issues with Kirby 13-in-1 and Jingxuan Mali 25-in-1. --- src/boards/fk23c.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/boards/fk23c.c b/src/boards/fk23c.c index ac22b6d..5218f3f 100644 --- a/src/boards/fk23c.c +++ b/src/boards/fk23c.c @@ -107,7 +107,7 @@ static void cwrap(uint32 A, uint32 V) /* some workaround for chr rom / ram access */ if (!VROM_size) bank = 0; - else if (CHRRAMSIZE && fk23_regs[0] & 0x20) + else if (fk23_regs[0] &0x20 && ~fk23_regs[0] &0x40 && CHRRAMSIZE || VROM_size == 0) bank = 0x10; if (CHR_MIXED && V < 8) bank = 0x10; /* first 8K of chr bank is RAM */ @@ -175,7 +175,7 @@ static void SyncPRG(void) switch (subType) { case 1: /* FK-xxx */ - if (PRG_MODE == 0) mask = 0xFF; /* Mode 0 allows the MMC3 to address 2 MiB rather than the usual 512 KiB. */ + if (PRG_MODE == 0 && MMC3_EXTENDED) mask = 0xFF; /* Mode 0 allows the MMC3 to address 2 MiB rather than the usual 512 KiB. */ break; case 2: /* FS005 */ prg_base |= fk23_regs[0] << 4 & 0x080 | fk23_regs[0] << 1 & 0x100 | fk23_regs[2] << 3 & 0x600 | fk23_regs[2] << 6 & 0x800; @@ -394,6 +394,7 @@ static void Reset(void) } fk23_regs[0] = fk23_regs[1] = fk23_regs[2] = fk23_regs[3] = fk23_regs[4] = fk23_regs[5] = fk23_regs[6] = fk23_regs[7] = 0; + if (subType == 1) fk23_regs[1] = 0xFF; mmc3_regs[0] = 0; mmc3_regs[1] = 2; mmc3_regs[2] = 4; @@ -415,6 +416,7 @@ static void Reset(void) static void Power(void) { fk23_regs[0] = fk23_regs[1] = fk23_regs[2] = fk23_regs[3] = fk23_regs[4] = fk23_regs[5] = fk23_regs[6] = fk23_regs[7] = 0; + if (subType == 1) fk23_regs[1] = 0xFF; mmc3_regs[0] = 0; mmc3_regs[1] = 2; mmc3_regs[2] = 4; From 095a2f90ec0dd1adc88b457406582be988bdc195 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 10:49:16 +0200 Subject: [PATCH 091/109] Revise mapper 356. --- src/boards/356.c | 112 ++++++++++++--------------------------- src/boards/asic_tc3294.c | 8 +-- src/boards/asic_tc3294.h | 1 + 3 files changed, 38 insertions(+), 83 deletions(-) diff --git a/src/boards/356.c b/src/boards/356.c index 666b7aa..60e8e5a 100644 --- a/src/boards/356.c +++ b/src/boards/356.c @@ -3,10 +3,10 @@ * Copyright notice for this file: * Copyright (C) 2020 * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -15,90 +15,44 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* NES 2.0 Mapper 356 - J.Y. Company's 7-in-1 Rockman (JY-208) - * All registers work as INES Mapper 045, except $6000 sequential register 2 (third write): + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * */ #include "mapinc.h" -#include "mmc3.h" +#include "asic_tc3294.h" -static uint8* CHRRAM = NULL; -static uint32 CHRRAMSIZE = 0; +static uint8 *CHRRAM = NULL; +static uint32 CHRRAMSize; -static void M356CW(uint32 A, uint8 V) { - if (EXPREGS[2] & 0x20) { - uint8 NV = V; - if (EXPREGS[2] & 8) - NV &= (1 << ((EXPREGS[2] & 7) + 1)) - 1; - else - if (EXPREGS[2]) - NV &= 0; /* hack ;( don't know exactly how it should be */ - NV |= EXPREGS[0] | ((EXPREGS[2] & 0xF0) << 4); - setchr1(A, NV); - } else - setchr8r(0x10, 0); -} - -static void M356PW(uint32 A, uint8 V) { - uint8 MV = V & ((EXPREGS[3] & 0x3F) ^ 0x3F); - MV |= EXPREGS[1]; - if (UNIFchrrama) - MV |= ((EXPREGS[2] & 0x40) << 2); - setprg8(A, MV); -} - -static void M356MW(uint8 V) { - if (EXPREGS[2] & 0x40) - SetupCartMirroring(4, 1, CHRRAM); +static void sync () { + TC3294_syncPRG(0xFF, 0x00); + if (TC3294_reg[2] &0x20) + TC3294_syncCHR(0x1FF, 0x00); else - setmirror((V & 1) ^ 1); + setchr8r(0x10, 0); + if (TC3294_reg[2] &0x40) { + setntamem(CHRptr[0x10] +0x0000, 1, 0); + setntamem(CHRptr[0x10] +0x0400, 1, 1); + setntamem(CHRptr[0x10] +0x0800, 1, 2); + setntamem(CHRptr[0x10] +0x0C00, 1, 3); + } else + TC3294_syncMirror(); } -static DECLFW(M356Write) { - if (!(EXPREGS[3] & 0x40)) { - EXPREGS[EXPREGS[4]] = V; - EXPREGS[4] = (EXPREGS[4] + 1) & 3; - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); +static void close (void) { + if (CHRRAM) { + FCEU_gfree(CHRRAM); + CHRRAM =NULL; } } -static void M356Close(void) { - GenMMC3Close(); - if (CHRRAM) - FCEU_free(CHRRAM); - CHRRAM = NULL; -} - -static void M356Reset(void) { - EXPREGS[0] = EXPREGS[1] = EXPREGS[3] = EXPREGS[4] = 0; - EXPREGS[2] = 0x0F; - MMC3RegReset(); -} - -static void M356Power(void) { - EXPREGS[4] = 0; - EXPREGS[0] = EXPREGS[1] = EXPREGS[3] = EXPREGS[4] = 0; - EXPREGS[2] = 0x0F; - GenMMC3Power(); - SetWriteHandler(0x6000, 0x7FFF, M356Write); -} - -void Mapper356_Init(CartInfo* info) { - GenMMC3_Init(info, 128, 128, 0, 0); - cwrap = M356CW; - pwrap = M356PW; - mwrap = M356MW; - info->Reset = M356Reset; - info->Power = M356Power; - info->Close = M356Close; - AddExState(EXPREGS, 5, 0, "EXPR"); - - CHRRAMSIZE = 8192; - CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +void Mapper356_Init (CartInfo *info) { + TC3294_init(info, sync); + info->Close = close; + CHRRAMSize = 8192; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize); + AddExState(CHRRAM, CHRRAMSize, 0, "CRAM"); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1); } diff --git a/src/boards/asic_tc3294.c b/src/boards/asic_tc3294.c index 467bb48..04ccc41 100644 --- a/src/boards/asic_tc3294.c +++ b/src/boards/asic_tc3294.c @@ -24,10 +24,10 @@ static void (*TC3294_cbSync)(); static uint8 TC3294_index; -static uint8 TC3294_reg[4]; +uint8 TC3294_reg[4]; static SFORMAT TC3294_state[] = { - { TC3294_reg, 8, "329S" }, + { TC3294_reg, 4, "329S" }, {&TC3294_index, 1, "329I" }, { 0 } }; @@ -99,8 +99,8 @@ void TC3294_power () { void TC3294_init (CartInfo *info, void (*sync)()) { MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, TC3294_write); TC3294_addExState(); - TC3294_configure(TC3294_cbSync); + TC3294_configure(sync); info->Power = TC3294_power; - info->Reset = TC3294_cbSync; + info->Reset = TC3294_clear; GameStateRestore = TC3294_restore; } diff --git a/src/boards/asic_tc3294.h b/src/boards/asic_tc3294.h index baa4e6e..1be126c 100644 --- a/src/boards/asic_tc3294.h +++ b/src/boards/asic_tc3294.h @@ -21,6 +21,7 @@ #ifndef _ASIC_TC3294_H #define _ASIC_TC3294_H +extern uint8 TC3294_reg[4]; void TC3294_syncWRAM (int); void TC3294_syncPRG (int, int); void TC3294_syncCHR (int, int); From c7960e9e0cf8df8378e5d654bb7fc15010e37eba Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 11:22:37 +0200 Subject: [PATCH 092/109] Refactoring: move extra CHR-RAM and WRAM into one CartRAM module. --- src/boards/21_22_23_25.c | 2 +- src/boards/252_253.c | 28 +++------------------------ src/boards/384.c | 2 +- src/boards/446.c | 2 +- src/boards/447.c | 2 +- src/boards/448.c | 2 +- src/boards/468.c | 2 +- src/boards/509.c | 2 +- src/boards/510.c | 2 +- src/boards/512.c | 17 ++-------------- src/boards/514.c | 2 +- src/boards/544.c | 31 +++++++++--------------------- src/boards/545.c | 2 +- src/boards/546.c | 2 +- src/boards/548.c | 2 +- src/boards/556.c | 2 +- src/boards/557.c | 2 +- src/boards/asic_fme7.c | 1 - src/boards/asic_vrc2and4.c | 2 +- src/boards/asic_vrc6.c | 1 - src/boards/asic_vrc7.c | 3 +-- src/boards/{wram.c => cartram.c} | 33 ++++++++++++++++++++++++++++---- src/boards/{wram.h => cartram.h} | 9 ++++++--- 23 files changed, 65 insertions(+), 88 deletions(-) rename src/boards/{wram.c => cartram.c} (53%) rename src/boards/{wram.h => cartram.h} (84%) diff --git a/src/boards/21_22_23_25.c b/src/boards/21_22_23_25.c index 1f9f988..ea66dc9 100644 --- a/src/boards/21_22_23_25.c +++ b/src/boards/21_22_23_25.c @@ -20,7 +20,7 @@ #include "mapinc.h" #include "asic_vrc2and4.h" -#include "wram.h" +#include "cartram.h" static void sync () { VRC24_syncWRAM(0); diff --git a/src/boards/252_253.c b/src/boards/252_253.c index 8e70fb7..f087149 100644 --- a/src/boards/252_253.c +++ b/src/boards/252_253.c @@ -20,10 +20,8 @@ #include "mapinc.h" #include "asic_vrc2and4.h" -#include "wram.h" +#include "cartram.h" -static uint8 *CHRRAM; -static uint32 CHRRAMSize; static uint8 mask; static uint8 compare; @@ -72,36 +70,16 @@ void Mapper253_power (void) { SetWriteHandler(0x2007, 0x2007, Mapper252_253_interceptPPUWrite); } -void Mapper252_253_close(void) { - if (CHRRAM) { - FCEU_gfree(CHRRAM); - CHRRAM =NULL; - } - WRAM_close(); -} - void Mapper252_Init (CartInfo *info) { VRC4_init(info, sync, 0x4, 0x8, 1, NULL, NULL, NULL, NULL, NULL); - WRAM_init(info, 8); + CartRAM_init(info, 8, 2); info->Power =Mapper252_power; - info->Close =Mapper252_253_close; AddExState(stateRegs, ~0, 0, 0); - - CHRRAMSize =info->iNES2? (info->CHRRamSize +info->CHRRamSaveSize): 2048; - CHRRAM =(uint8*)FCEU_gmalloc(CHRRAMSize); - AddExState(CHRRAM, CHRRAMSize, 0, "CRAM"); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1); } void Mapper253_Init (CartInfo *info) { VRC4_init(info, sync, 0x4, 0x8, 1, NULL, NULL, NULL, NULL, NULL); - WRAM_init(info, 8); + CartRAM_init(info, 8, 2); info->Power =Mapper253_power; - info->Close =Mapper252_253_close; AddExState(stateRegs, ~0, 0, 0); - - CHRRAMSize =info->iNES2? (info->CHRRamSize +info->CHRRamSaveSize): 2048; - CHRRAM =(uint8*)FCEU_gmalloc(CHRRAMSize); - AddExState(CHRRAM, CHRRAMSize, 0, "CRAM"); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1); } diff --git a/src/boards/384.c b/src/boards/384.c index 410e396..07f5dd1 100644 --- a/src/boards/384.c +++ b/src/boards/384.c @@ -20,7 +20,7 @@ #include "mapinc.h" #include "asic_vrc2and4.h" -#include "wram.h" +#include "cartram.h" static uint8 reg; diff --git a/src/boards/446.c b/src/boards/446.c index 0683c35..b2ef936 100644 --- a/src/boards/446.c +++ b/src/boards/446.c @@ -33,7 +33,7 @@ #include "asic_vrc6.h" #include "asic_vrc7.h" #include "flashrom.h" -#include "wram.h" +#include "cartram.h" static uint8 submapper; static uint8 reg[8]; diff --git a/src/boards/447.c b/src/boards/447.c index 3fd1d8b..352d8d6 100644 --- a/src/boards/447.c +++ b/src/boards/447.c @@ -20,7 +20,7 @@ #include "mapinc.h" #include "asic_vrc2and4.h" -#include "wram.h" +#include "cartram.h" static uint8 reg; static uint8 dip; diff --git a/src/boards/448.c b/src/boards/448.c index ac2d799..e31396e 100644 --- a/src/boards/448.c +++ b/src/boards/448.c @@ -20,7 +20,7 @@ #include "mapinc.h" #include "asic_vrc2and4.h" -#include "wram.h" +#include "cartram.h" static uint8 reg; diff --git a/src/boards/468.c b/src/boards/468.c index eb9eb42..48958ac 100644 --- a/src/boards/468.c +++ b/src/boards/468.c @@ -29,7 +29,7 @@ #include "asic_vrc3.h" #include "asic_vrc6.h" #include "asic_vrc7.h" -#include "wram.h" +#include "cartram.h" static uint8 submapper; static uint8 reg[4]; /* Supervisor registers */ diff --git a/src/boards/509.c b/src/boards/509.c index f13e678..4e61254 100644 --- a/src/boards/509.c +++ b/src/boards/509.c @@ -22,7 +22,7 @@ #include "mapinc.h" #include "asic_mmc3.h" -#include "wram.h" +#include "cartram.h" static uint8 reg; diff --git a/src/boards/510.c b/src/boards/510.c index c0d0d70..b57eabe 100644 --- a/src/boards/510.c +++ b/src/boards/510.c @@ -22,7 +22,7 @@ #include "mapinc.h" #include "asic_mmc3.h" -#include "wram.h" +#include "cartram.h" static uint8 reg; diff --git a/src/boards/512.c b/src/boards/512.c index 0645355..9563843 100644 --- a/src/boards/512.c +++ b/src/boards/512.c @@ -22,10 +22,9 @@ #include "mapinc.h" #include "asic_mmc3.h" -#include "wram.h" +#include "cartram.h" static uint8 reg; -static uint8 *CHRRAM = NULL; static void sync () { MMC3_syncPRG(0x3F, 0x00); @@ -64,22 +63,10 @@ static void power () { SetWriteHandler(0x4020, 0x5FFF, writeReg); } -static void close () { - if (CHRRAM) { - FCEU_gfree(CHRRAM); - CHRRAM = NULL; - } -} - void Mapper512_Init (CartInfo *info) { MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, NULL); - WRAM_init(info, 8); + CartRAM_init(info, 8, 8); info->Power = power; info->Reset = reset; - info->Close = close; AddExState(®, 1, 0, "EXPR"); - - CHRRAM = (uint8 *)FCEU_gmalloc(8192); - SetupCartCHRMapping(0x10, CHRRAM, 8192, 1); - AddExState(CHRRAM, 8192, 0, "CRAM"); } diff --git a/src/boards/514.c b/src/boards/514.c index a8b674d..292a5cd 100644 --- a/src/boards/514.c +++ b/src/boards/514.c @@ -20,7 +20,7 @@ #include "mapinc.h" #include "asic_latch.h" -#include "wram.h" +#include "cartram.h" static uint8 chr; diff --git a/src/boards/544.c b/src/boards/544.c index eb5cf0a..0918bc5 100644 --- a/src/boards/544.c +++ b/src/boards/544.c @@ -20,9 +20,8 @@ #include "mapinc.h" #include "asic_vrc2and4.h" +#include "cartram.h" -static uint8 *CHRRAM; -static uint32 CHRRAMSize; static uint8 nt[4]; static uint8 prg; static uint8 mask; @@ -48,7 +47,7 @@ static void sync () { } static const uint8 compares[8] = { 0x28, 0x00, 0x4C, 0x64, 0x46, 0x7C, 0x04, 0xFF }; -static DECLFW(Mapper544_interceptPPUWrite) { +static DECLFW (interceptPPUWrite) { if (~RefreshAddr &0x2000) { int bank =VRC24_getCHRBank(RefreshAddr >>10 &7); if (bank &0x80) { @@ -66,11 +65,11 @@ static DECLFW(Mapper544_interceptPPUWrite) { writePPU(A, V); } -int Mapper544_getPRGBank(uint8 bank) { +static int getPRGBank (uint8 bank) { return bank ==2? prg: VRC24_getPRGBank(bank); } -DECLFW(Mapper544_externalSelect) { +static DECLFW (externalSelect) { if (A &4) nt[A &3] =V; else @@ -79,7 +78,7 @@ DECLFW(Mapper544_externalSelect) { } -void Mapper544_power (void) { +void power (void) { mask =0xFC; compare =0x28; nt[0] =nt[1] =0xE0; @@ -87,24 +86,12 @@ void Mapper544_power (void) { prg =0xFE; VRC24_power(); writePPU =GetWriteHandler(0x2007); - SetWriteHandler(0x2007, 0x2007, Mapper544_interceptPPUWrite); -} - -void Mapper544_close(void) { - if (CHRRAM) { - FCEU_gfree(CHRRAM); - CHRRAM =NULL; - } + SetWriteHandler(0x2007, 0x2007, interceptPPUWrite); } void Mapper544_Init (CartInfo *info) { - VRC4_init(info, sync, 0x400, 0x800, 1, Mapper544_getPRGBank, NULL, NULL, NULL, Mapper544_externalSelect); - info->Power =Mapper544_power; - info->Close =Mapper544_close; + VRC4_init(info, sync, 0x400, 0x800, 1, getPRGBank, NULL, NULL, NULL, externalSelect); + CartRAM_init(info, 8, 2); + info->Power =power; AddExState(stateRegs, ~0, 0, 0); - - CHRRAMSize =info->CHRRamSize +info->CHRRamSaveSize; - CHRRAM =(uint8*)FCEU_gmalloc(CHRRAMSize); - AddExState(CHRRAM, CHRRAMSize, 0, "CRAM"); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1); } diff --git a/src/boards/545.c b/src/boards/545.c index 5a339e5..bd28342 100644 --- a/src/boards/545.c +++ b/src/boards/545.c @@ -22,7 +22,7 @@ #include "mapinc.h" #include "asic_mmc3.h" -#include "wram.h" +#include "cartram.h" static uint8 reg; diff --git a/src/boards/546.c b/src/boards/546.c index df9e8ef..e388215 100644 --- a/src/boards/546.c +++ b/src/boards/546.c @@ -22,7 +22,7 @@ #include "mapinc.h" #include "asic_mmc1.h" -#include "wram.h" +#include "cartram.h" static uint8 reg; diff --git a/src/boards/548.c b/src/boards/548.c index 013dc7c..01d8e1a 100644 --- a/src/boards/548.c +++ b/src/boards/548.c @@ -21,7 +21,7 @@ */ #include "mapinc.h" -#include "wram.h" +#include "cartram.h" #include "../fds_apu.h" static uint8 reg; diff --git a/src/boards/556.c b/src/boards/556.c index c1806f5..669e804 100644 --- a/src/boards/556.c +++ b/src/boards/556.c @@ -25,7 +25,7 @@ #include "mapinc.h" #include "asic_mmc3.h" #include "asic_vrc2and4.h" -#include "wram.h" +#include "cartram.h" static uint8 reg[4]; static uint8 index; diff --git a/src/boards/557.c b/src/boards/557.c index 4f8dff5..f579467 100644 --- a/src/boards/557.c +++ b/src/boards/557.c @@ -22,7 +22,7 @@ #include "mapinc.h" #include "asic_n118.h" -#include "wram.h" +#include "cartram.h" static void sync() { setprg8r(0x10, 0x6000, 0); diff --git a/src/boards/asic_fme7.c b/src/boards/asic_fme7.c index 124ec5e..3b66263 100644 --- a/src/boards/asic_fme7.c +++ b/src/boards/asic_fme7.c @@ -20,7 +20,6 @@ #include "mapinc.h" #include "asic_FME7.h" -#include "wram.h" static void (*FME7_cbSync)(); static uint8 FME7_index; diff --git a/src/boards/asic_vrc2and4.c b/src/boards/asic_vrc2and4.c index 6dfe81d..be5b4cb 100644 --- a/src/boards/asic_vrc2and4.c +++ b/src/boards/asic_vrc2and4.c @@ -20,7 +20,7 @@ #include "mapinc.h" #include "asic_vrc2and4.h" -#include "wram.h" +#include "cartram.h" static void (*VRC24_cbSync)(); static int VRC24_A0, VRC24_A1; diff --git a/src/boards/asic_vrc6.c b/src/boards/asic_vrc6.c index 95df036..c8cc694 100644 --- a/src/boards/asic_vrc6.c +++ b/src/boards/asic_vrc6.c @@ -20,7 +20,6 @@ #include "mapinc.h" #include "asic_vrc6.h" -#include "wram.h" static void (*VRC6_cbSync)(); static int VRC6_A0, VRC6_A1; diff --git a/src/boards/asic_vrc7.c b/src/boards/asic_vrc7.c index 7c31f02..2461a21 100644 --- a/src/boards/asic_vrc7.c +++ b/src/boards/asic_vrc7.c @@ -19,8 +19,7 @@ */ #include "mapinc.h" -#include "asic_VRC7.h" -#include "wram.h" +#include "asic_vrc7.h" static void (*VRC7_cbSync)(); static int VRC7_A0; diff --git a/src/boards/wram.c b/src/boards/cartram.c similarity index 53% rename from src/boards/wram.c rename to src/boards/cartram.c index 8e3de6b..17e5a6f 100644 --- a/src/boards/wram.c +++ b/src/boards/cartram.c @@ -19,22 +19,27 @@ */ #include "mapinc.h" -#include "wram.h" +#include "cartram.h" +static uint8 *CHRRAMData = NULL; static uint8 *WRAMData = NULL; +uint32 CHRRAMSize = 0; uint32 WRAMSize = 0; -void WRAM_close (void) { +void CartRAM_close (void) { /* Need to combine this in one function to avoid the problem of having to properly cascade two separate Close() functions for WRAM and CHR-RAM each */ if (WRAMData) { FCEU_gfree(WRAMData); WRAMData =NULL; } + if (CHRRAMData) { + FCEU_gfree(CHRRAMData); + CHRRAMData =NULL; + } } -void WRAM_init (CartInfo *info, uint8 defaultWRAMSizeKiB) { +void CartRAM_init (CartInfo *info, uint8 defaultWRAMSizeKiB, uint8 defaultCHRRAMSizeKiB) { WRAMSize =info->iNES2? (info->PRGRamSize +info->PRGRamSaveSize): (defaultWRAMSizeKiB *1024); if (WRAMSize) { - info->Close =WRAM_close; WRAMData =(uint8*)FCEU_gmalloc(WRAMSize); SetupCartPRGMapping(0x10, WRAMData, WRAMSize, 1); AddExState(WRAMData, WRAMSize, 0, "WRAM"); @@ -43,4 +48,24 @@ void WRAM_init (CartInfo *info, uint8 defaultWRAMSizeKiB) { info->SaveGameLen[0] =WRAMSize; } } + CHRRAMSize =info->iNES2? (info->CHRRamSize +info->CHRRamSaveSize): (defaultCHRRAMSizeKiB *1024); + if (ROM_size == 0) CHRRAMSize = 0; /* If there is no CHR-ROM, then any CHR-RAM will not be "extra" and therefore will be handled by ines.c, not here. */ + if (CHRRAMSize) { + CHRRAMData =(uint8*)FCEU_gmalloc(CHRRAMSize); + SetupCartCHRMapping(0x10, CHRRAMData, CHRRAMSize, 1); + AddExState(CHRRAMData, CHRRAMSize, 0, "CRAM"); + if (info->battery) { + info->SaveGame[info->SaveGameLen[0]? 1: 0] =CHRRAMData; + info->SaveGameLen[info->SaveGameLen[0]? 1: 0] =CHRRAMSize; + } + } + if (WRAMSize || CHRRAMSize) info->Close =CartRAM_close; +} + +void CHRRAM_init (CartInfo *info, uint8 defaultCHRRAMSizeKiB) { + CartRAM_init(info, 0, defaultCHRRAMSizeKiB); +} + +void WRAM_init (CartInfo *info, uint8 defaultWRAMSizeKiB) { + CartRAM_init(info, defaultWRAMSizeKiB, 0); } diff --git a/src/boards/wram.h b/src/boards/cartram.h similarity index 84% rename from src/boards/wram.h rename to src/boards/cartram.h index 2544f2d..de46253 100644 --- a/src/boards/wram.h +++ b/src/boards/cartram.h @@ -18,11 +18,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef _WRAM_H -#define _WRAM_H +#ifndef _CARTRAM_H +#define _CARTRAM_H +extern uint32 CHRRAMSize; extern uint32 WRAMSize; +void CartRAM_init (CartInfo *, uint8, uint8); +void CHRRAM_init (CartInfo *, uint8); void WRAM_init (CartInfo *, uint8); -void WRAM_close (); +void CartRAM_close (); #endif From bab8e3fd120004c41779feb93409cb7078c7a97a Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 11:32:19 +0200 Subject: [PATCH 093/109] Mapper 256: Add reset-based menu selection for Power Racer. --- src/boards/onebus.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/boards/onebus.c b/src/boards/onebus.c index c4698bf..a124b33 100644 --- a/src/boards/onebus.c +++ b/src/boards/onebus.c @@ -289,12 +289,14 @@ static DECLFR(UNLOneBusReadAPU40XX) { result = (result & 0x7f) | pcm_irq; } break; + case 0x17: + if (cpu410x[0x0B] == 0x14) result = result &~0x04 | (dipswitch &1? 0x04: 0x00); /* Super Joy III pad */ } return result; } -static DECLFR(readDIP) { - return dipswitch; +static DECLFR(readDIP_FamilyPocket) { + return dipswitch &1? 8: 0; } static void UNLOneBusCpuHook(int a) { @@ -337,7 +339,7 @@ static void UNLOneBusPower(void) { SetReadHandler(0x4000, 0x403f, UNLOneBusReadAPU40XX); SetWriteHandler(0x4000, 0x403f, UNLOneBusWriteAPU40XX); - SetReadHandler(0x412C, 0x412C, readDIP); + SetReadHandler(0x412C, 0x412C, readDIP_FamilyPocket); SetReadHandler(0x6000, 0xFFFF, CartBR); SetWriteHandler(0x6000, 0x7FFF, CartBW); SetWriteHandler(0x2010, 0x201f, UNLOneBusWritePPU201X); @@ -360,7 +362,7 @@ static void UNLOneBusReset(void) { cpu410x[0x0F] =0xFF; cpu410x[0x1C] =submapper ==12 || submapper ==14? 0x40: 0x00; reg4242 =0; - dipswitch ^=8; + dipswitch++; Sync(); } From 81cfd57103ef88a4055468431d46258e375795bd Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 11:57:48 +0200 Subject: [PATCH 094/109] Add mapper 182 (replacing the duplicate of 114). --- src/boards/182.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 2 +- src/ines.h | 1 + 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 src/boards/182.c diff --git a/src/boards/182.c b/src/boards/182.c new file mode 100644 index 0000000..a1cd4ba --- /dev/null +++ b/src/boards/182.c @@ -0,0 +1,75 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg[4]; + +static void sync() { + int prgAND = reg[1] &0x20? 0x1F: 0x0F; + int chrAND = reg[1] &0x40? 0xFF: 0x7F; + int prgOR = (reg[1] &0x02? 0x10: 0x00) | (reg[1] &0x10? 0x020: 0x00); + int chrOR = (reg[1] &0x02? 0x80: 0x00) | (reg[1] &0x10? 0x100: 0x00); + if (reg[0] &0x80) { + if (reg[0] &0x20) + setprg32(0x8000, reg[0] >>1); + else { + setprg16(0x8000, reg[0]); + setprg16(0xC000, reg[0]); + } + } else + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static DECLFW(writeReg) { + if (~reg[1] &0x01) { + reg[A &3] = V; + sync(); + } +} + +static DECLFW(unscramble) { + static const uint16 lutAddress[8] = { 0xA001, 0xA000, 0x8000, 0xC000, 0x8001, 0xC001, 0xE000, 0xE001 }; /* i <5? 4-i: i */ + static const uint8 lutIndex[8] = { 0, 3, 1, 5, 6, 7, 2, 4 }; /* i <6? (i^3)-1: i */ + MMC3_writeReg(lutAddress[A >>12 &6 | A &1], (A &0xE001) == 0xA000? lutIndex[V &7]: V); +} + +static void reset() { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + MMC3_clear(); +} + +static void power() { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + MMC3_power(); + SetWriteHandler(0x8000, 0xFFFF, unscramble); +} + +void Mapper182_Init(CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(reg, 4, 0, "EXPR"); +} diff --git a/src/ines.c b/src/ines.c index 70222f9..149449f 100644 --- a/src/ines.c +++ b/src/ines.c @@ -635,7 +635,7 @@ INES_BOARD_BEGIN() /* INES_BOARD( "", 179, Mapper179_Init ) */ INES_BOARD( "", 180, Mapper180_Init ) INES_BOARD( "", 181, Mapper181_Init ) -/* INES_BOARD( "", 182, Mapper182_Init ) */ /* Deprecated, dupe of Mapper 114 */ + INES_BOARD( "YH-001", 182, Mapper182_Init ) INES_BOARD( "", 183, Mapper183_Init ) INES_BOARD( "", 184, Mapper184_Init ) INES_BOARD( "", 185, Mapper185_Init ) diff --git a/src/ines.h b/src/ines.h index a56fd6b..c58d527 100644 --- a/src/ines.h +++ b/src/ines.h @@ -187,6 +187,7 @@ void Mapper177_Init(CartInfo *); void Mapper178_Init(CartInfo *); void Mapper180_Init(CartInfo *); void Mapper181_Init(CartInfo *); +void Mapper182_Init(CartInfo *); void Mapper183_Init(CartInfo *); void Mapper184_Init(CartInfo *); void Mapper185_Init(CartInfo *); From 2f7bb5134942f36c34971fc4502ed59f92caebd9 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 13:23:26 +0200 Subject: [PATCH 095/109] Add submappers to mapper 396. --- src/boards/396.c | 74 +++++++++++++++++++++++------------------------- src/boards/588.c | 6 ++-- 2 files changed, 39 insertions(+), 41 deletions(-) diff --git a/src/boards/396.c b/src/boards/396.c index a31aee1..4c4d105 100644 --- a/src/boards/396.c +++ b/src/boards/396.c @@ -1,7 +1,7 @@ -/* FCEUmm - NES/Famicom Emulator +/* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2022 + * Copyright (C) 2025 NewRisingSun * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,58 +16,56 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 396 - BMC-830752C - * 1995 Super 8-in-1 (JY-050 rev0) - * Super 8-in-1 Gold Card Series (JY-085) - * Super 8-in-1 Gold Card Series (JY-086) - * 2-in-1 (GN-51) */ #include "mapinc.h" +static uint8 submapper; static uint8 reg[2]; -static void Sync (void) { - setprg16(0x8000, reg[1] << 3 | reg[0] & 7); - setprg16(0xC000, reg[1] << 3 | 7); +static void sync () { + setprg16(0x8000, reg[0] <<3 | reg[1] &0x07); + setprg16(0xC000, reg[0] <<3 | 0x07); setchr8(0); - setmirror(reg[1] & 0x60 ? 0 : 1); + switch(submapper) { + case 1: /* J.Y. YY850437C */ + setmirror(reg[0] &0x40? MI_H: MI_V); + break; + case 2: /* Realtec GN-51 */ + case 3: /* Realtec 8030 */ + setmirror(reg[0] &0x20? MI_H: MI_V); + break; + default: + setmirror(reg[0] &0x60? MI_H: MI_V); + break; + } } -static DECLFW(M396WriteInnerBank) { - reg[0] = V; - Sync(); +static DECLFW (writeReg) { + reg[(A &0xE000) == 0xA000? 0: 1] = V; + sync(); } -static DECLFW(M396WriteOuterBank) { - reg[1] = V; - Sync(); +static DECLFW (writeReg_submapper3) { + reg[A >>14 &1] = V; + sync(); } -static void M396Reset(void) { - reg[0] = 0x00; - reg[1] = 0x00; - Sync(); +static void power () { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, submapper == 3? writeReg_submapper3: writeReg); + reg[0] = reg[1] = 0; + sync(); } -static void StateRestore(int version) { - Sync(); +static void stateRestore (int version) { + sync(); } -static void M396Power(void) { - reg[0] = 0x00; - reg[1] = 0x00; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0x9FFF, M396WriteInnerBank); - SetWriteHandler(0xA000, 0xBFFF, M396WriteOuterBank); - SetWriteHandler(0xC000, 0xFFFF, M396WriteInnerBank); -} - -void Mapper396_Init(CartInfo *info) { - info->Power = M396Power; - info->Reset = M396Reset; - GameStateRestore = StateRestore; +void Mapper396_Init (CartInfo *info) { + submapper = info->submapper; + info->Power = power; + info->Reset = submapper == 3? sync: power; + GameStateRestore = stateRestore; AddExState(reg, 2, 0, "REGS"); } diff --git a/src/boards/588.c b/src/boards/588.c index 4021269..4a7802e 100644 --- a/src/boards/588.c +++ b/src/boards/588.c @@ -29,19 +29,19 @@ static void sync () { setmirror(reg[0] &0x80? MI_H: MI_V); } -static DECLFW(writeReg) { +static DECLFW (writeReg) { reg[A >>12 &1] = V; sync(); } -static void power() { +static void power () { SetReadHandler(0x6000, 0xFFFF, CartBR); SetWriteHandler(0xE000, 0xFFFF, writeReg); reg[0] = reg[1] = 0; sync(); } -static void stateRestore(int version) { +static void stateRestore (int version) { sync(); } From 675d2ab6dd9e5099ae3d18cee7483902563dfd92 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 13:36:12 +0200 Subject: [PATCH 096/109] Cleanly separate mappers 361 and 366. --- src/boards/361.c | 54 +++++++++++++++++++++++++++++++++++++++++++ src/boards/366.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ src/boards/mmc3.c | 4 ++-- src/ines.c | 4 ++-- src/ines.h | 4 ++-- 5 files changed, 119 insertions(+), 6 deletions(-) create mode 100644 src/boards/361.c create mode 100644 src/boards/366.c diff --git a/src/boards/361.c b/src/boards/361.c new file mode 100644 index 0000000..6d0f6f9 --- /dev/null +++ b/src/boards/361.c @@ -0,0 +1,54 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync () { + MMC3_syncPRG(0x0F, reg &~0x0F); + MMC3_syncCHR(0x7F, reg <<3 &~0x7F); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + reg = V; + sync(); +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +void Mapper361_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/366.c b/src/boards/366.c new file mode 100644 index 0000000..4307bd1 --- /dev/null +++ b/src/boards/366.c @@ -0,0 +1,59 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" +#include "cartram.h" + +static uint8 reg; + +static void sync () { + MMC3_syncWRAM(0); + MMC3_syncPRG(0x0F, reg &~0x0F); + MMC3_syncCHR(0x7F, reg <<3 &~0x7F); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + if (~reg &0x80) { + reg = A &0xFF; + sync(); + } +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +void Mapper366_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + WRAM_init(info, 8); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/mmc3.c b/src/boards/mmc3.c index de88f2d..978b57e 100644 --- a/src/boards/mmc3.c +++ b/src/boards/mmc3.c @@ -1311,12 +1311,12 @@ void Mapper367_Init(CartInfo *info) { /* Mapper 361 and 366, previously assigned as Mapper 205 */ static void GN45PW(uint32 A, uint8 V) { /* GN-30A - \ED\E0\F7\E0\EB\FC\ED\E0\FF \EC\E0\F1\EA\E0 \E4\EE\EB\E6\ED\E0 \E1\FB\F2\FC 1F + \E0\EF\EF\E0\F0\E0\F2\ED\FB\E9 \EF\E5\F0\E5\EA\EB\FE\F7\E0\F2\E5\EB\FC \ED\E0 \F8\E8\ED\E5 \E0\E4\F0\E5\F1\E0 */ - setprg8(A, (V & 0x0f) | EXPREGS[0]); + setprg8(A, (V & 0x0f) | EXPREGS[0] &~0x0F); } static void GN45CW(uint32 A, uint8 V) { /* GN-30A - \ED\E0\F7\E0\EB\FC\ED\E0\FF \EC\E0\F1\EA\E0 \E4\EE\EB\E6\ED\E0 \E1\FB\F2\FC FF */ - setchr1(A, (V & 0x7F) | (EXPREGS[0] << 3)); + setchr1(A, (V & 0x7F) | (EXPREGS[0] << 3 &~0x7F)); } static DECLFW(GN45Write0) { diff --git a/src/ines.c b/src/ines.c index 149449f..566864b 100644 --- a/src/ines.c +++ b/src/ines.c @@ -805,11 +805,11 @@ INES_BOARD_BEGIN() INES_BOARD( "YY860606C", 358, Mapper358_Init ) INES_BOARD( "SB-5013/GCL8050/841242C", 359, Mapper359_Init ) INES_BOARD( "Bitcorp 31-in-1", 360, Mapper360_Init ) - INES_BOARD( "OK-411", 361, GN45_Init ) /* OK-411 is emulated together with GN-45 */ + INES_BOARD( "OK-411", 361, Mapper361_Init ) INES_BOARD( "830506C", 362, Mapper362_Init ) INES_BOARD( "5069", 363, Mapper363_Init ) INES_BOARD( "JY830832C", 364, Mapper364_Init ) - INES_BOARD( "GN-45", 366, GN45_Init ) + INES_BOARD( "GN-45", 366, Mapper366_Init ) INES_BOARD( "JC-016-2 variant", 367, Mapper367_Init ) INES_BOARD( "Yung-08", 368, Mapper368_Init ) INES_BOARD( "N49C-300", 369, Mapper369_Init ) diff --git a/src/ines.h b/src/ines.h index c58d527..67fb359 100644 --- a/src/ines.h +++ b/src/ines.h @@ -251,8 +251,6 @@ void Mapper252_Init(CartInfo *); void Mapper253_Init(CartInfo *); void Mapper254_Init(CartInfo *); void Mapper255_Init(CartInfo *); - -void GN45_Init(CartInfo *info); /* m361, m366 */ void Mapper270_Init(CartInfo *); void Mapper272_Init(CartInfo *); void Mapper273_Init(CartInfo *); @@ -290,9 +288,11 @@ void Mapper357_Init(CartInfo *); void Mapper358_Init(CartInfo *); void Mapper359_Init(CartInfo *); void Mapper360_Init(CartInfo *); +void Mapper361_Init(CartInfo *); void Mapper362_Init(CartInfo *); void Mapper363_Init(CartInfo *); void Mapper364_Init(CartInfo *); +void Mapper366_Init(CartInfo *); void Mapper367_Init(CartInfo *); void Mapper368_Init(CartInfo *); void Mapper369_Init(CartInfo *); From 3b05920d4bf00869bfb8f65a36344d504cc75ec3 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 13:39:26 +0200 Subject: [PATCH 097/109] Mapper 464: Reset to menu from Galaxian. --- src/boards/addrlatch.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c index ea3c0ed..040af3e 100644 --- a/src/boards/addrlatch.c +++ b/src/boards/addrlatch.c @@ -846,8 +846,15 @@ static void M464Sync(void) { setmirror(latche &0x20? MI_H: MI_V); } +void Mapper464_reset () { + RAM[0x133] = 0; + latche = 0; + M464Sync(); +} + void Mapper464_Init(CartInfo *info) { Latch_Init(info, M464Sync, NULL, 0x0000, 0x8000, 0xFFFF, 1); + info->Reset = Mapper464_reset; } /*------------------ Map 488 ---------------------------*/ From 2731fdc56bba802f50bf6fed99fd439479fce45a Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 13:55:05 +0200 Subject: [PATCH 098/109] Mapper 280: UNROM-after-reset needs vertical mirroring. --- src/boards/280.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/boards/280.c b/src/boards/280.c index b831be7..afd7d21 100644 --- a/src/boards/280.c +++ b/src/boards/280.c @@ -41,6 +41,7 @@ static void Sync(void) { setprg16(0x8000, 0x20 | latchData &0x07); setprg16(0xC000, 0x27); } + setmirror(MI_V); } else { if (latchAddr &0x01) setprg32(0x8000, latchAddr >>3 &0x0F); @@ -49,10 +50,10 @@ static void Sync(void) { setprg16(0xC000, latchAddr >>2 &0x1F); } if (~latchAddr &0x80) setprg16(0xC000, 0); + setmirror(latchAddr &0x02? MI_H: MI_V); } SetupCartCHRMapping(0, CHRptr[0], 0x2000, ~mode &0x01 && latchAddr &0x80? 0: 1); setchr8(0); - setmirror(latchAddr &0x02? MI_H: MI_V); } static DECLFW(M280Write) { From 7e774f4f5af4de2fd3d342451511ccd95058075c Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 14:05:59 +0200 Subject: [PATCH 099/109] Revise mapper 455. --- src/boards/455.c | 79 +++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/src/boards/455.c b/src/boards/455.c index 55c8bdf..c76eced 100644 --- a/src/boards/455.c +++ b/src/boards/455.c @@ -1,7 +1,7 @@ /* FCEUmm - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2022 + * Copyright (C) 2020 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,62 +16,57 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * */ -/* N625836 PCB */ - #include "mapinc.h" -#include "mmc3.h" +#include "asic_mmc3.h" -static void Mapper455_PRGWrap(uint32 A, uint8 V) { - int prgAND =EXPREGS[1] &0x01? 0x1F: 0x0F; - int prgOR =EXPREGS[0] >>2 &0x07 | EXPREGS[1] <<1 &0x08 | EXPREGS[0] >>2 &0x10; - if (EXPREGS[0] &0x01) { - if (EXPREGS[0] &0x02) { - setprg32(0x8000, prgOR >>1); - } else { - setprg16(0x8000, prgOR); - setprg16(0xC000, prgOR); +static uint8 reg[2]; + +static void sync () { + if (reg[0] &0x01) { + if (reg[0] &0x02) + setprg32(0x8000, reg[0] >>3); + else { + setprg16(0x8000, reg[0] >>2); + setprg16(0xC000, reg[0] >>2); } + MMC3_syncCHR(0xFF, 0x00); } else { - prgOR <<=1; - setprg8(A, V &prgAND | prgOR &~prgAND); + int prgAND = 0x1F; + int chrAND = reg[1] &0x02? 0x7F: 0xFF; + int prgOR = reg[0] >>1; + int chrOR = reg[1] <<6; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); } + MMC3_syncMirror(); } -static void Mapper455_CHRWrap(uint32 A, uint8 V) { - int chrAND =EXPREGS[1] &0x02? 0xFF: 0x7F; - int chrOR =(EXPREGS[0] >>2 &0x07 | EXPREGS[1] <<1 &0x08 | EXPREGS[0] >>2 &0x10) <<4; - setchr1(A, V &chrAND | chrOR &~chrAND); -} - -static DECLFW(Mapper455_Write) { +static DECLFW (writeReg) { if (A &0x100) { - EXPREGS[0] =V; - EXPREGS[1] =A &0xFF; - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); + reg[0] = V; + reg[1] = A &0xFF; + sync(); } } -static void Mapper455_Reset(void) { - EXPREGS[0] =1; - EXPREGS[1] =0; - MMC3RegReset(); +static void reset () { + reg[0] = reg[1] = 0; + MMC3_clear(); } -static void Mapper455_Power(void) { - EXPREGS[0] =1; - EXPREGS[1] =0; - GenMMC3Power(); - SetWriteHandler(0x4100, 0x5FFF, Mapper455_Write); +static void power () { + reg[0] = reg[1] = 0; + MMC3_power(); + SetWriteHandler(0x4020, 0x5FFF, writeReg); } -void Mapper455_Init(CartInfo *info) { - GenMMC3_Init(info, 256, 256, 0, 0); - cwrap = Mapper455_CHRWrap; - pwrap = Mapper455_PRGWrap; - info->Power = Mapper455_Power; - info->Reset = Mapper455_Reset; - AddExState(EXPREGS, 2, 0, "EXPR"); +void Mapper455_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, NULL); + info->Power = power; + info->Reset = reset; + AddExState(reg, 2, 0, "EXPR"); } From b84b48566905640d4602e505cade71bce1cb3b2c Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 14:40:27 +0200 Subject: [PATCH 100/109] OneBus: use all eight bits of the IRQ reload value. --- src/boards/onebus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boards/onebus.c b/src/boards/onebus.c index a124b33..534a749 100644 --- a/src/boards/onebus.c +++ b/src/boards/onebus.c @@ -230,7 +230,7 @@ static DECLFW(UNLOneBusWriteMMC3) { break; } case 0xa000: mirror = V; Sync(); break; - case 0xc000: IRQLatch = V & 0xfe; break; + case 0xc000: IRQLatch = V; break; case 0xc001: IRQReload = 1; break; case 0xe000: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; break; case 0xe001: IRQa = 1; break; From 7c05fe472354a176426ec3a44804e0f6cae61c23 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 15:00:54 +0200 Subject: [PATCH 101/109] Mapper 458: Add submapper 1. --- src/boards/458.c | 77 +++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/src/boards/458.c b/src/boards/458.c index cb7ba5b..5a67d82 100644 --- a/src/boards/458.c +++ b/src/boards/458.c @@ -1,7 +1,7 @@ /* FCEUmm - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2023 + * Copyright (C) 2020 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,58 +16,55 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * */ #include "mapinc.h" -#include "mmc3.h" +#include "asic_mmc3.h" -static void M458CW(uint32 A, uint8 V) { - setchr1(A, ((EXPREGS[0] << 4) & ~0x7F) | (V & 0x7F)); +static uint8 submapper; +static uint8 reg; +static uint8 pad; + +static DECLFR (readPad) { + return CartBR(A &~0xF | pad &0xF); } -static void M458PW(uint32 A, uint8 V) { - if (EXPREGS[0] & 0x10) { - setprg32(0x8000, EXPREGS[0] >> 1); - } else { - setprg16(0x8000, EXPREGS[0]); - setprg16(0xC000, EXPREGS[0]); +static void sync () { + if (reg &(submapper == 1? 0x08: 0x10)) + setprg32(0x8000, reg >>1); + else { + setprg16(0x8000, reg); + setprg16(0xC000, reg); } + MMC3_syncCHR(0x7F, reg <<4 &~0x7F); + MMC3_syncMirror(); + SetReadHandler(0x8000, 0xFFFF, reg &(submapper == 1? 0x80: 0x20)? readPad: CartBR); } -static DECLFR(M458Read) { - if ((EXPREGS[0] & 0x20) && (EXPREGS[1] & 3)) { - return CartBR((A & ~3) | (EXPREGS[1] & 3)); - } - return CartBR(A); +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); } -static DECLFW(M458Write) { - if (MMC3CanWriteToWRAM()) { - EXPREGS[0] = A & 0xFF; - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); - } +static void reset () { + reg = 0; + pad++; + MMC3_clear(); } -static void M458Reset(void) { - EXPREGS[0] = 0; - EXPREGS[1]++; - MMC3RegReset(); +static void power () { + reg = 0; + pad = 0; + MMC3_power(); } -static void M458Power(void) { - EXPREGS[0] = 0; - EXPREGS[1] = 0; - GenMMC3Power(); - SetReadHandler(0x8000, 0xFFFF, M458Read); - SetWriteHandler(0x6000, 0x7FFF, M458Write); -} - -void Mapper458_Init(CartInfo *info) { - GenMMC3_Init(info, 256, 256, 0, 0); - cwrap = M458CW; - pwrap = M458PW; - info->Reset = M458Reset; - info->Power = M458Power; - AddExState(EXPREGS, 2, 0, "EXPR"); +void Mapper458_Init (CartInfo *info) { + submapper = info->submapper; + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); + AddExState(&pad, 1, 0, "DIPS"); } From e9a0242248358e403a6dbd4ce41e9deff0bb86c2 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 19:58:52 +0200 Subject: [PATCH 102/109] Add mapper 594 with expansion sound. --- src/boards/594.c | 133 +++++++++++++++++++++++++++++++++++++++++++ src/boards/fifo.c | 43 ++++++++++++++ src/boards/fifo.h | 19 +++++++ src/boards/msm6585.c | 101 ++++++++++++++++++++++++++++++++ src/boards/msm6585.h | 19 +++++++ src/ines.c | 1 + src/ines.h | 1 + 7 files changed, 317 insertions(+) create mode 100644 src/boards/594.c create mode 100644 src/boards/fifo.c create mode 100644 src/boards/fifo.h create mode 100644 src/boards/msm6585.c create mode 100644 src/boards/msm6585.h diff --git a/src/boards/594.c b/src/boards/594.c new file mode 100644 index 0000000..1db75f9 --- /dev/null +++ b/src/boards/594.c @@ -0,0 +1,133 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" +#include "fifo.h" +#include "msm6585.h" +#include + +static uint8 reg[4]; +static FIFO fifo; +static MSM6585 adpcm; +static int32 soundOffset = 0; + +static void sync () { + int prgAND = 0x3F; + int chrAND = reg[2] &0xC0? 0x0FF: 0x1FF; + int prgOR = (reg[2] &0x40? 0x0C0: 0x000) | (reg[2] &0x80? 0x100: 0x000); + int chrOR = (reg[2] &0x40? 0x200: 0x000) | (reg[2] &0x80? 0x300: 0x000); + setprg8(0x6000, reg[0] | prgOR); + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static int getCHRBank (uint8 bank) { + return MMC3_getCHRBank(bank) | bank <<6 &0x100; +} + +static DECLFR (readADPCM) { + return FIFO_halfFull(&fifo)? 0x00: 0x40; +} + +static DECLFW (writeADPCM) { + if (A &1) { + MSM6585_setRate(&adpcm, V >>6); + FIFO_reset(&fifo); + } else + FIFO_add(&fifo, V); +} + +static int serveADPCM (void) { + return FIFO_retrieve(&fifo); +} + +static DECLFW (writeReg) { + reg[A >>12 &2 | A &1] = V; + sync(); +} + +static void reset () { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + MMC3_clear(); + FIFO_reset(&fifo); + MSM6585_reset(&adpcm); +} + +static void power () { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + MMC3_power(); + FIFO_reset(&fifo); + MSM6585_reset(&adpcm); + SetReadHandler(0x5000, 0x5FFF, readADPCM); + SetWriteHandler(0x5000, 0x5FFF, writeADPCM); + SetWriteHandler(0x9000, 0x9FFF, writeReg); + SetWriteHandler(0xB000, 0xBFFF, writeReg); +} + +static void mapperSound_fillBufferLow (int count) { + int i; + int end = (SOUNDTS <<16) /soundtsinc; + for (i = soundOffset; i < end; i++) { + MSM6585_run(&adpcm); + Wave[i >>4] += MSM6585_getOutput(&adpcm) >>1; + } + soundOffset = count; +} + +static void mapperSound_fillBufferHigh () { + int i; + for (i = soundOffset; i < SOUNDTS; i++) { + MSM6585_run(&adpcm); + WaveHi[i] += MSM6585_getOutput(&adpcm)*8 +16384; + } + soundOffset = SOUNDTS; +} + +static void mapperSound_setSoundOffset(int32 newSoundOffset) { + soundOffset = newSoundOffset; +} + +static void mapperSound_init (void) { + if (FSettings.SndRate) { + GameExpSound.Fill = mapperSound_fillBufferLow; + GameExpSound.HiFill = mapperSound_fillBufferHigh; + GameExpSound.HiSync = mapperSound_setSoundOffset; + GameExpSound.RChange = mapperSound_init; + } + MSM6585_init(&adpcm, FSettings.soundq >=1? 1789773: FSettings.SndRate*16, serveADPCM); +} + +static void close() { + FIFO_close(&fifo); +} + +void Mapper594_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, getCHRBank, NULL, NULL); + FIFO_init(&fifo, 1024); + info->Power = power; + info->Reset = reset; + info->Close = close; + mapperSound_init(); + AddExState(reg, 4, 0, "EXPR"); +} diff --git a/src/boards/fifo.c b/src/boards/fifo.c new file mode 100644 index 0000000..cb25f64 --- /dev/null +++ b/src/boards/fifo.c @@ -0,0 +1,43 @@ +#include "mapinc.h" +#include +#include +#include "fifo.h" + +size_t FIFO_size (FIFO *fifo) { + fifo->front %= fifo->capacity; + fifo->back %= fifo->capacity; + return (fifo->back -fifo->front +fifo->capacity) %fifo->capacity; +} + +uint8 FIFO_halfFull (FIFO *fifo) { + return FIFO_size(fifo) >= fifo->capacity /2; +} + +int FIFO_retrieve (FIFO *fifo) { + fifo->front %= fifo->capacity; + return FIFO_size(fifo)? fifo->data[fifo->front++]: 0; +} + +void FIFO_add (FIFO *fifo, uint8 value) { + fifo->back %= fifo->capacity; + if (FIFO_size(fifo) capacity) fifo->data[fifo->back++] = value; +} + +void FIFO_reset (FIFO *fifo) { + fifo->front = fifo->back = 0; +} + +void FIFO_init (FIFO *fifo, size_t newCapacity) { + fifo->capacity = newCapacity; + fifo->data = (uint8*)FCEU_gmalloc(newCapacity); + AddExState(fifo->data, fifo->capacity, 0, "FIFD"); + AddExState(&fifo->front, 2, 0, "FIFF"); + AddExState(&fifo->back, 2, 0, "FIFB"); +} + +void FIFO_close (FIFO *fifo) { + if (fifo->data) { + free(fifo->data); + fifo->data = NULL; + } +} diff --git a/src/boards/fifo.h b/src/boards/fifo.h new file mode 100644 index 0000000..377452c --- /dev/null +++ b/src/boards/fifo.h @@ -0,0 +1,19 @@ +#ifndef _FIFO_H +#define _FIFO_H + +typedef struct { + size_t capacity; + uint8 *data; + int16 front; + int16 back; +} FIFO; + +size_t FIFO_size (FIFO *); +uint8 FIFO_halfFull (FIFO *); +int FIFO_retrieve (FIFO *); +void FIFO_add (FIFO *, uint8); +void FIFO_reset (FIFO *); +void FIFO_init (FIFO *, size_t); +void FIFO_close (FIFO *); + +#endif diff --git a/src/boards/msm6585.c b/src/boards/msm6585.c new file mode 100644 index 0000000..c103a31 --- /dev/null +++ b/src/boards/msm6585.c @@ -0,0 +1,101 @@ +#include "mapinc.h" +#include "msm6585.h" + +static const int16_t diff_lookup[49*16] = { + 2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30, + 2, 6, 10, 14, 19, 23, 27, 31, -2, -6, -10, -14, -19, -23, -27, -31, + 2, 6, 11, 15, 21, 25, 30, 34, -2, -6, -11, -15, -21, -25, -30, -34, + 2, 7, 12, 17, 23, 28, 33, 38, -2, -7, -12, -17, -23, -28, -33, -38, + 2, 7, 13, 18, 25, 30, 36, 41, -2, -7, -13, -18, -25, -30, -36, -41, + 3, 9, 15, 21, 28, 34, 40, 46, -3, -9, -15, -21, -28, -34, -40, -46, + 3, 10, 17, 24, 31, 38, 45, 52, -3, -10, -17, -24, -31, -38, -45, -52, + 3, 10, 18, 25, 34, 41, 49, 56, -3, -10, -18, -25, -34, -41, -49, -56, + 4, 12, 21, 29, 38, 46, 55, 63, -4, -12, -21, -29, -38, -46, -55, -63, + 4, 13, 22, 31, 41, 50, 59, 68, -4, -13, -22, -31, -41, -50, -59, -68, + 5, 15, 25, 35, 46, 56, 66, 76, -5, -15, -25, -35, -46, -56, -66, -76, + 5, 16, 27, 38, 50, 61, 72, 83, -5, -16, -27, -38, -50, -61, -72, -83, + 6, 18, 31, 43, 56, 68, 81, 93, -6, -18, -31, -43, -56, -68, -81, -93, + 6, 19, 33, 46, 61, 74, 88, 101, -6, -19, -33, -46, -61, -74, -88, -101, + 7, 22, 37, 52, 67, 82, 97, 112, -7, -22, -37, -52, -67, -82, -97, -112, + 8, 24, 41, 57, 74, 90, 107, 123, -8, -24, -41, -57, -74, -90, -107, -123, + 9, 27, 45, 63, 82, 100, 118, 136, -9, -27, -45, -63, -82, -100, -118, -136, + 10, 30, 50, 70, 90, 110, 130, 150, -10, -30, -50, -70, -90, -110, -130, -150, + 11, 33, 55, 77, 99, 121, 143, 165, -11, -33, -55, -77, -99, -121, -143, -165, + 12, 36, 60, 84, 109, 133, 157, 181, -12, -36, -60, -84, -109, -133, -157, -181, + 13, 39, 66, 92, 120, 146, 173, 199, -13, -39, -66, -92, -120, -146, -173, -199, + 14, 43, 73, 102, 132, 161, 191, 220, -14, -43, -73, -102, -132, -161, -191, -220, + 16, 48, 81, 113, 146, 178, 211, 243, -16, -48, -81, -113, -146, -178, -211, -243, + 17, 52, 88, 123, 160, 195, 231, 266, -17, -52, -88, -123, -160, -195, -231, -266, + 19, 58, 97, 136, 176, 215, 254, 293, -19, -58, -97, -136, -176, -215, -254, -293, + 21, 64, 107, 150, 194, 237, 280, 323, -21, -64, -107, -150, -194, -237, -280, -323, + 23, 70, 118, 165, 213, 260, 308, 355, -23, -70, -118, -165, -213, -260, -308, -355, + 26, 78, 130, 182, 235, 287, 339, 391, -26, -78, -130, -182, -235, -287, -339, -391, + 28, 85, 143, 200, 258, 315, 373, 430, -28, -85, -143, -200, -258, -315, -373, -430, + 31, 94, 157, 220, 284, 347, 410, 473, -31, -94, -157, -220, -284, -347, -410, -473, + 34, 103, 173, 242, 313, 382, 452, 521, -34, -103, -173, -242, -313, -382, -452, -521, + 38, 114, 191, 267, 345, 421, 498, 574, -38, -114, -191, -267, -345, -421, -498, -574, + 42, 126, 210, 294, 379, 463, 547, 631, -42, -126, -210, -294, -379, -463, -547, -631, + 46, 138, 231, 323, 417, 509, 602, 694, -46, -138, -231, -323, -417, -509, -602, -694, + 51, 153, 255, 357, 459, 561, 663, 765, -51, -153, -255, -357, -459, -561, -663, -765, + 56, 168, 280, 392, 505, 617, 729, 841, -56, -168, -280, -392, -505, -617, -729, -841, + 61, 184, 308, 431, 555, 678, 802, 925, -61, -184, -308, -431, -555, -678, -802, -925, + 68, 204, 340, 476, 612, 748, 884, 1020, -68, -204, -340, -476, -612, -748, -884, -1020, + 74, 223, 373, 522, 672, 821, 971, 1120, -74, -223, -373, -522, -672, -821, -971, -1120, + 82, 246, 411, 575, 740, 904, 1069, 1233, -82, -246, -411, -575, -740, -904, -1069, -1233, + 90, 271, 452, 633, 814, 995, 1176, 1357, -90, -271, -452, -633, -814, -995, -1176, -1357, + 99, 298, 497, 696, 895, 1094, 1293, 1492, -99, -298, -497, -696, -895, -1094, -1293, -1492, + 109, 328, 547, 766, 985, 1204, 1423, 1642, -109, -328, -547, -766, -985, -1204, -1423, -1642, + 120, 360, 601, 841, 1083, 1323, 1564, 1804, -120, -360, -601, -841, -1083, -1323, -1564, -1804, + 132, 397, 662, 927, 1192, 1457, 1722, 1987, -132, -397, -662, -927, -1192, -1457, -1722, -1987, + 145, 436, 728, 1019, 1311, 1602, 1894, 2185, -145, -436, -728, -1019, -1311, -1602, -1894, -2185, + 160, 480, 801, 1121, 1442, 1762, 2083, 2403, -160, -480, -801, -1121, -1442, -1762, -2083, -2403, + 176, 528, 881, 1233, 1587, 1939, 2292, 2644, -176, -528, -881, -1233, -1587, -1939, -2292, -2644, + 194, 582, 970, 1358, 1746, 2134, 2522, 2910, -194, -582, -970, -1358, -1746, -2134, -2522, -2910 +}; +static const int16_t index_shift[8] = { -1, -1, -1, -1, 2, 4, 6, 8 }; + +void MSM6585_init (MSM6585* chip, int32 newHostClock, int (*newGetInput)(void)) { + chip->hostClock = newHostClock; + chip->getInput = newGetInput; + AddExState(&chip->whichNibble, 1, 0, "MSMW"); + AddExState(&chip->input, 1, 0, "MSMI"); + AddExState(&chip->signal, 2, 0, "MSMO"); + AddExState(&chip->count, 4, 0, "MSMC"); + AddExState(&chip->rate, 4, 0, "MSMR"); + AddExState(&chip->step, 2, 0, "MSMS"); +} + +void MSM6585_reset (MSM6585* chip) { + chip->count = 0; + chip->step = 0; + chip->signal = -2; +} + +void MSM6585_setRate (MSM6585* chip, uint8 rateByte) { + chip->rate = 4000 <<(rateByte &3); +} + +void MSM6585_run (MSM6585* chip) { + chip->count += chip->rate; + while (chip->count >= chip->hostClock) { + chip->count -= chip->hostClock; + uint8_t nibble; + if (chip->whichNibble) + nibble = chip->input &0x0F; + else { + chip->input = chip->getInput(); + nibble = chip->input >>4; + } + chip->whichNibble = !chip->whichNibble; + chip->signal += diff_lookup[chip->step *16 +nibble]; + if (chip->signal > 2047) chip->signal = 2047; + if (chip->signal <-2048) chip->signal =-2048; + chip->step += index_shift[nibble &7]; + if (chip->step > 48) chip->step = 48; + if (chip->step < 0) chip->step = 0; + } +} + +int32_t MSM6585_getOutput (MSM6585* chip) { + return chip->signal; +} diff --git a/src/boards/msm6585.h b/src/boards/msm6585.h new file mode 100644 index 0000000..ce50d04 --- /dev/null +++ b/src/boards/msm6585.h @@ -0,0 +1,19 @@ +#ifndef _MSM6585_H +#define _MSM6585_H +typedef struct { + uint8 whichNibble; + uint8 input; + int16 signal; + int32 count; + int32 hostClock; + int32 rate; + int16 step; + int (*getInput)(void); +} MSM6585; + +void MSM6585_init (MSM6585*, int32, int (*)(void)); +void MSM6585_reset (MSM6585*); +void MSM6585_setRate (MSM6585*, uint8); +void MSM6585_run (MSM6585*); +int32_t MSM6585_getOutput (MSM6585*); +#endif diff --git a/src/ines.c b/src/ines.c index 566864b..bf558b4 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1015,6 +1015,7 @@ INES_BOARD_BEGIN() INES_BOARD( "810430", 590, Mapper590_Init ) INES_BOARD( "07027/810543", 591, Mapper591_Init ) INES_BOARD( "8-in-1 1991", 592, Mapper592_Init ) + INES_BOARD( "Rinco FSG2", 594, Mapper594_Init ) INES_BOARD_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index 67fb359..396164c 100644 --- a/src/ines.h +++ b/src/ines.h @@ -482,6 +482,7 @@ void Mapper589_Init(CartInfo *); void Mapper590_Init(CartInfo *); void Mapper591_Init(CartInfo *); void Mapper592_Init(CartInfo *); +void Mapper594_Init(CartInfo *); void FFE_Init(CartInfo *); From 19e357c0406951d132287fa7b4db67e0e278d72d Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 21:59:11 +0200 Subject: [PATCH 103/109] Add mapper 595. --- src/boards/595.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 72 insertions(+) create mode 100644 src/boards/595.c diff --git a/src/boards/595.c b/src/boards/595.c new file mode 100644 index 0000000..b98267f --- /dev/null +++ b/src/boards/595.c @@ -0,0 +1,70 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "cartram.h" +#include "flashrom.h" + +static uint8 reg; + +static void sync () { + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, reg &0x1F); + setprg16(0xC000, 0xFF); + setchr8(0); +} + +static DECLFW (writeFlash) { + flashrom_write(A &0x3FFF | (Page[A >>11] +A -PRGptr[0]) &~0x3FFF, V); +} + +static DECLFW (writeReg) { + reg = reg >>1 | V <<4 &0x10; + sync(); +} + +static void power () { + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetReadHandler(0x8000, 0xFFFF, flashrom_read); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0xBFFF, writeFlash); + SetWriteHandler(0xC000, 0xFFFF, writeReg); + reg = 0; + sync(); +} + +static void stateRestore (int version) { + sync(); +} + +void Mapper595_Init (CartInfo *info) { + WRAM_init(info, 8); + flashrom_init (0xBF, 0xB4, 4096, 0x5555, 0x2AAA, 0x7FFF); + info->Reset = power; + info->Power = power; + MapIRQHook =flashrom_cpuCycle; + GameStateRestore = stateRestore; + AddExState(®, 1, 0, "REGS"); + if (info->battery) { + info->SaveGame[0] = ROM; + info->SaveGameLen[0] = PRGsize[0]; + AddExState(ROM, PRGsize[0], 0, "FLAS"); + } +} diff --git a/src/ines.c b/src/ines.c index bf558b4..0d0b35f 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1016,6 +1016,7 @@ INES_BOARD_BEGIN() INES_BOARD( "07027/810543", 591, Mapper591_Init ) INES_BOARD( "8-in-1 1991", 592, Mapper592_Init ) INES_BOARD( "Rinco FSG2", 594, Mapper594_Init ) + INES_BOARD( "4MROM-512", 595, Mapper595_Init ) INES_BOARD_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index 396164c..2caf764 100644 --- a/src/ines.h +++ b/src/ines.h @@ -483,6 +483,7 @@ void Mapper590_Init(CartInfo *); void Mapper591_Init(CartInfo *); void Mapper592_Init(CartInfo *); void Mapper594_Init(CartInfo *); +void Mapper595_Init(CartInfo *); void FFE_Init(CartInfo *); From db279aa3389dadb6caf143bea06c70b8b95d32e0 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 21:59:27 +0200 Subject: [PATCH 104/109] Overall cleanup. --- src/boards/116.c | 2 +- src/boards/14.c | 2 +- src/boards/182.c | 12 ++-- src/boards/183.c | 12 ++-- src/boards/222.c | 42 +++++++------- src/boards/252_253.c | 34 ++++++------ src/boards/266.c | 16 +++--- src/boards/273.c | 4 +- src/boards/280.c | 6 +- src/boards/285.c | 4 +- src/boards/308.c | 16 +++--- src/boards/351.c | 39 ++++++------- src/boards/362.c | 14 ++--- src/boards/384.c | 20 +++---- src/boards/398.c | 22 ++++---- src/boards/432.c | 18 +++--- src/boards/445.c | 4 +- src/boards/446.c | 16 +++--- src/boards/447.c | 32 +++++------ src/boards/448.c | 24 ++++---- src/boards/449.c | 11 ++-- src/boards/450.c | 10 ++-- src/boards/458.c | 2 +- src/boards/460.c | 15 +---- src/boards/468.c | 22 ++++---- src/boards/483.c | 3 +- src/boards/490.c | 22 ++++---- src/boards/494.c | 6 +- src/boards/495.c | 4 +- src/boards/503.c | 14 ++--- src/boards/504.c | 14 ++--- src/boards/505.c | 2 +- src/boards/506.c | 16 +++--- src/boards/512.c | 4 +- src/boards/524.c | 16 +++--- src/boards/525.c | 4 +- src/boards/529.c | 12 ++-- src/boards/530.c | 14 ++--- src/boards/542.c | 8 +-- src/boards/544.c | 2 +- src/boards/548.c | 8 +-- src/boards/556.c | 4 +- src/boards/557.c | 4 +- src/boards/559.c | 14 ++--- src/boards/563.c | 8 +-- src/boards/565.c | 4 +- src/boards/567.c | 16 +++--- src/boards/569.c | 14 ++--- src/boards/570.c | 14 ++--- src/boards/572.c | 16 +++--- src/boards/577.c | 6 +- src/boards/578.c | 12 ++-- src/boards/584.c | 6 +- src/boards/585.c | 6 +- src/boards/587.c | 6 +- src/boards/594.c | 7 +-- src/boards/asic_fme7.c | 8 +-- src/boards/asic_fme7.h | 7 ++- src/boards/asic_h3001.c | 14 ++--- src/boards/asic_h3001.h | 1 + src/boards/asic_latch.c | 2 +- src/boards/asic_mmc1.c | 10 ++-- src/boards/asic_mmc2and4.c | 4 +- src/boards/asic_mmc2and4.h | 1 + src/boards/asic_mmc3.c | 4 +- src/boards/asic_n118.c | 2 +- src/boards/asic_pt8154.c | 6 +- src/boards/asic_pt8154.h | 1 + src/boards/asic_qj.c | 4 +- src/boards/asic_qj.h | 1 + src/boards/asic_tc3294.c | 8 +-- src/boards/asic_tc3294.h | 3 +- src/boards/asic_vrc1.c | 6 +- src/boards/asic_vrc1.h | 3 +- src/boards/asic_vrc2and4.c | 16 +++--- src/boards/asic_vrc2and4.h | 1 + src/boards/asic_vrc3.c | 4 +- src/boards/asic_vrc3.h | 1 + src/boards/asic_vrc6.c | 8 +-- src/boards/asic_vrc6.h | 1 + src/boards/asic_vrc7.c | 8 +-- src/boards/asic_vrc7.h | 1 + src/boards/bmck3006.c | 2 +- src/boards/cartram.c | 26 ++++----- src/boards/fifo.c | 4 +- src/boards/msm6585.c | 110 ++++++++++++++++++------------------- 86 files changed, 476 insertions(+), 476 deletions(-) diff --git a/src/boards/116.c b/src/boards/116.c index 465efb4..151b8b7 100644 --- a/src/boards/116.c +++ b/src/boards/116.c @@ -100,7 +100,7 @@ static void applyMode (uint8 clear) { } } -static DECLFW(writeReg) { +static DECLFW (writeReg) { if (A &0x100) { uint8 previousReg = reg; reg = V; diff --git a/src/boards/14.c b/src/boards/14.c index ad47557..6e223e2 100644 --- a/src/boards/14.c +++ b/src/boards/14.c @@ -52,7 +52,7 @@ int getCHRBank_VRC2 (uint8 bank) { return VRC24_getCHRBank(bank) | reg <<(~bank &4? 5: ~bank &2? 3: 1) &0x100; } -static DECLFW(writeReg) { +static DECLFW (writeReg) { uint8 previousReg = reg; reg = V; if ((previousReg ^V) &2) diff --git a/src/boards/182.c b/src/boards/182.c index a1cd4ba..c4edcf2 100644 --- a/src/boards/182.c +++ b/src/boards/182.c @@ -25,7 +25,7 @@ static uint8 reg[4]; -static void sync() { +static void sync () { int prgAND = reg[1] &0x20? 0x1F: 0x0F; int chrAND = reg[1] &0x40? 0xFF: 0x7F; int prgOR = (reg[1] &0x02? 0x10: 0x00) | (reg[1] &0x10? 0x020: 0x00); @@ -43,31 +43,31 @@ static void sync() { MMC3_syncMirror(); } -static DECLFW(writeReg) { +static DECLFW (writeReg) { if (~reg[1] &0x01) { reg[A &3] = V; sync(); } } -static DECLFW(unscramble) { +static DECLFW (unscramble) { static const uint16 lutAddress[8] = { 0xA001, 0xA000, 0x8000, 0xC000, 0x8001, 0xC001, 0xE000, 0xE001 }; /* i <5? 4-i: i */ static const uint8 lutIndex[8] = { 0, 3, 1, 5, 6, 7, 2, 4 }; /* i <6? (i^3)-1: i */ MMC3_writeReg(lutAddress[A >>12 &6 | A &1], (A &0xE001) == 0xA000? lutIndex[V &7]: V); } -static void reset() { +static void reset () { reg[0] = reg[1] = reg[2] = reg[3] = 0; MMC3_clear(); } -static void power() { +static void power () { reg[0] = reg[1] = reg[2] = reg[3] = 0; MMC3_power(); SetWriteHandler(0x8000, 0xFFFF, unscramble); } -void Mapper182_Init(CartInfo *info) { +void Mapper182_Init (CartInfo *info) { MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); info->Power = power; info->Reset = reset; diff --git a/src/boards/183.c b/src/boards/183.c index c494dcf..ef21817 100644 --- a/src/boards/183.c +++ b/src/boards/183.c @@ -23,7 +23,7 @@ static uint8 prg; -static SFORMAT Mapper183_stateRegs[] ={ +static SFORMAT stateRegs[] ={ { &prg, 1, "PRG6" }, { 0 } }; @@ -35,18 +35,18 @@ static void sync () { VRC24_syncMirror(); } -DECLFW(Mapper183_writePRG) { +static DECLFW (writePRG) { prg =A &0xFF; sync(); } -void Mapper183_power(void) { +static void power(void) { prg =0; VRC24_power(); } void Mapper183_Init (CartInfo *info) { - VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, CartBR, Mapper183_writePRG, NULL); - AddExState(Mapper183_stateRegs, ~0, 0, 0); - info->Power =Mapper183_power; + VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, CartBR, writePRG, NULL); + AddExState(stateRegs, ~0, 0, 0); + info->Power =power; } diff --git a/src/boards/222.c b/src/boards/222.c index 832d3d4..38b8554 100644 --- a/src/boards/222.c +++ b/src/boards/222.c @@ -27,7 +27,7 @@ static uint8 counter1; static uint8 counter2; static uint8 prescaler; -static SFORMAT Mapper222_stateRegs[] ={ +static SFORMAT stateRegs[] = { { &clockMode, 1, "CLKM" }, { &pending, 1, "PEND" }, { &counter1, 1, "CNT1" }, @@ -42,39 +42,39 @@ static void sync () { VRC24_syncMirror(); } -DECLFW(Mapper222_nibblizeCHR) { +static DECLFW (nibblizeCHR) { if (~A &1) { VRC24_writeReg(A, V); VRC24_writeReg(A |1, V >>4); } } -DECLFW(Mapper222_writeIRQ) { +static DECLFW (writeIRQ) { switch(A &3) { - case 0: clockMode =0; + case 0: clockMode = 0; break; - case 1: pending =false; + case 1: pending = 0; if (!clockMode) { - counter1 =V &0xF; - counter2 =V >>4; + counter1 = V &0xF; + counter2 = V >>4; } break; - case 2: clockMode =1; + case 2: clockMode = 1; break; } } -void FP_FASTAPASS(1) Mapper222_cpuCycle(int a) { +static void FP_FASTAPASS(1) cpuCycle (int a) { while (a--) { - uint8 previousPrescaler =prescaler; + uint8 previousPrescaler = prescaler; if (pending) - prescaler =0; + prescaler = 0; else prescaler++; if (clockMode && ~previousPrescaler &0x40 && prescaler &0x40) { - if (++counter1 ==0xF && ++counter2 ==0xF) pending =1; - counter1 &=0xF; - counter2 &=0xF; + if (++counter1 == 0xF && ++counter2 == 0xF) pending = 1; + counter1 &= 0xF; + counter2 &= 0xF; } if (pending) X6502_IRQBegin(FCEU_IQEXT); @@ -83,16 +83,16 @@ void FP_FASTAPASS(1) Mapper222_cpuCycle(int a) { } } -void Mapper222_power(void) { - clockMode =pending =counter1 =counter2 =prescaler =0; +static void power (void) { + clockMode = pending = counter1 = counter2 = prescaler = 0; VRC24_power(); - SetWriteHandler(0xB000, 0xEFFF, Mapper222_nibblizeCHR); - SetWriteHandler(0xF000, 0xFFFF, Mapper222_writeIRQ); + SetWriteHandler(0xB000, 0xEFFF, nibblizeCHR); + SetWriteHandler(0xF000, 0xFFFF, writeIRQ); } void Mapper222_Init (CartInfo *info) { VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); - AddExState(Mapper222_stateRegs, ~0, 0, 0); - info->Power =Mapper222_power; - MapIRQHook =Mapper222_cpuCycle; + AddExState(stateRegs, ~0, 0, 0); + info->Power =power; + MapIRQHook = cpuCycle; } diff --git a/src/boards/252_253.c b/src/boards/252_253.c index f087149..61e7116 100644 --- a/src/boards/252_253.c +++ b/src/boards/252_253.c @@ -28,7 +28,7 @@ static uint8 compare; extern uint32 RefreshAddr; static writefunc writePPU; -static SFORMAT stateRegs[] ={ +static SFORMAT stateRegs[] = { { &mask, 1, "CHRM" }, { &compare, 1, "CHRC" }, { 0 } @@ -38,48 +38,48 @@ static void sync () { int bank; VRC24_syncWRAM(0); VRC24_syncPRG(0x01F, 0x000); - for (bank =0; bank <8; bank++) setchr1r((VRC24_getCHRBank(bank) &mask) ==compare? 0x10: 0x00, bank <<10, VRC24_getCHRBank(bank)); + for (bank = 0; bank < 8; bank++) setchr1r((VRC24_getCHRBank(bank) &mask) == compare? 0x10: 0x00, bank <<10, VRC24_getCHRBank(bank)); VRC24_syncMirror(); } -static DECLFW(Mapper252_253_interceptPPUWrite) { +static DECLFW (Mapper252_253_interceptPPUWrite) { if (~RefreshAddr &0x2000) { - int bank =VRC24_getCHRBank(RefreshAddr >>10 &7); + int bank = VRC24_getCHRBank(RefreshAddr >>10 &7); switch(bank) { - case 0x88: mask =0xFC; compare =0x4C; sync(); break; - case 0xC2: mask =0xFE; compare =0x7C; sync(); break; - case 0xC8: mask =0xFE; compare =0x04; sync(); break; + case 0x88: mask = 0xFC; compare = 0x4C; sync(); break; + case 0xC2: mask = 0xFE; compare = 0x7C; sync(); break; + case 0xC8: mask = 0xFE; compare = 0x04; sync(); break; } } writePPU(A, V); } -void Mapper252_power (void) { - mask =0xFE; - compare =0x06; +static void Mapper252_power (void) { + mask = 0xFE; + compare = 0x06; VRC24_power(); - writePPU =GetWriteHandler(0x2007); + writePPU = GetWriteHandler(0x2007); SetWriteHandler(0x2007, 0x2007, Mapper252_253_interceptPPUWrite); } -void Mapper253_power (void) { - mask =0xFE; /* There are two board revisions, the earlier one with a non-switchable mask/compare FE/04 and a later switchable one that starts with FC/28 */ - compare =0x04; +static void Mapper253_power (void) { + mask = 0xFE; /* There are two board revisions, the earlier one with a non-switchable mask/compare FE/04 and a later switchable one that starts with FC/28 */ + compare = 0x04; VRC24_power(); - writePPU =GetWriteHandler(0x2007); + writePPU = GetWriteHandler(0x2007); SetWriteHandler(0x2007, 0x2007, Mapper252_253_interceptPPUWrite); } void Mapper252_Init (CartInfo *info) { VRC4_init(info, sync, 0x4, 0x8, 1, NULL, NULL, NULL, NULL, NULL); CartRAM_init(info, 8, 2); - info->Power =Mapper252_power; + info->Power = Mapper252_power; AddExState(stateRegs, ~0, 0, 0); } void Mapper253_Init (CartInfo *info) { VRC4_init(info, sync, 0x4, 0x8, 1, NULL, NULL, NULL, NULL, NULL); CartRAM_init(info, 8, 2); - info->Power =Mapper253_power; + info->Power = Mapper253_power; AddExState(stateRegs, ~0, 0, 0); } diff --git a/src/boards/266.c b/src/boards/266.c index 5a0e2ec..cc59614 100644 --- a/src/boards/266.c +++ b/src/boards/266.c @@ -23,7 +23,7 @@ static uint8 prg; -static SFORMAT UNLCITYFIGHT_stateRegs[] ={ +static SFORMAT stateRegs[] ={ { &prg, 1, "PRG8" }, { 0 } }; @@ -34,7 +34,7 @@ static void sync () { VRC24_syncMirror(); } -DECLFW(UNLCITYFIGHT_externalSelect) { +static DECLFW (externalSelect) { if (A &0x800) (GetWriteHandler(0x4011))(0x4011, V <<3 &0x78); else { @@ -43,18 +43,18 @@ DECLFW(UNLCITYFIGHT_externalSelect) { } } -DECLFW(UNLCITYFIGHT_unscrambleAddress) { +static DECLFW (unscrambleAddress) { VRC24_writeReg(A &~0x6000 | A <<1 &0x4000 | A >>1 &0x2000, V); } -void UNLCITYFIGHT_power(void) { +static void power (void) { prg =0; VRC24_power(); - SetWriteHandler(0x8000, 0xFFFF, UNLCITYFIGHT_unscrambleAddress); + SetWriteHandler(0x8000, 0xFFFF, unscrambleAddress); } void UNLCITYFIGHT_Init (CartInfo *info) { - VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, NULL, NULL, UNLCITYFIGHT_externalSelect); - AddExState(UNLCITYFIGHT_stateRegs, ~0, 0, 0); - info->Power =UNLCITYFIGHT_power; + VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, NULL, NULL, externalSelect); + AddExState(stateRegs, ~0, 0, 0); + info->Power =power; } diff --git a/src/boards/273.c b/src/boards/273.c index 5310d1f..23df59a 100644 --- a/src/boards/273.c +++ b/src/boards/273.c @@ -40,7 +40,7 @@ static void sync () { VRC24_syncMirror(); } -static DECLFW(writeIRQ) { +static DECLFW (writeIRQ) { switch(A &8) { case 0: irqCounter = V; @@ -69,7 +69,7 @@ static void FP_FASTAPASS(1) cpuCycle (int a) { } } -static void power(void) { +static void power (void) { irqEnabled = irqCounter = irqPrescaler = irqMask = 0; VRC24_power(); SetWriteHandler(0xF000, 0xFFFF, writeIRQ); diff --git a/src/boards/280.c b/src/boards/280.c index afd7d21..9241cb7 100644 --- a/src/boards/280.c +++ b/src/boards/280.c @@ -21,9 +21,9 @@ #include "mapinc.h" static uint16 latchAddr; -static uint8 latchData; -static uint8 mode; -static uint8 submapper; +static uint8 latchData; +static uint8 mode; +static uint8 submapper; static SFORMAT StateRegs[] = { { &latchAddr, 2 | FCEUSTATE_RLSB, "LATC" }, diff --git a/src/boards/285.c b/src/boards/285.c index 9c90393..8a10f35 100644 --- a/src/boards/285.c +++ b/src/boards/285.c @@ -59,13 +59,13 @@ static DECLFR (readPad) { return pad >= 8? 0: pad &7; } -static void power() { +static void power () { pad = 0; Latch_power(); SetReadHandler(0x5000, 0x5FFF, readPad); } -static void reset() { +static void reset () { pad = ++pad %24; Latch_clear(); } diff --git a/src/boards/308.c b/src/boards/308.c index 0c636f8..1e15832 100644 --- a/src/boards/308.c +++ b/src/boards/308.c @@ -25,7 +25,7 @@ static uint8 irqEnabled; static uint16 irqCounterLow; static uint8 irqCounterHigh; -static SFORMAT UNLTH21311_stateRegs[] ={ +static SFORMAT stateRegs[] ={ { &irqEnabled, 1, "IRQE" }, { &irqCounterLow, 2 | FCEUSTATE_RLSB, "CNTL" }, { &irqCounterHigh, 1, "CNTH" }, @@ -38,7 +38,7 @@ static void sync () { VRC24_syncMirror(); } -DECLFW(UNLTH21311_writeIRQ) { +static DECLFW (writeIRQ) { switch(A &3) { case 0: X6502_IRQEnd(FCEU_IQEXT); irqEnabled =0; @@ -51,22 +51,22 @@ DECLFW(UNLTH21311_writeIRQ) { } } -void FP_FASTAPASS(1) UNLTH21311_cpuCycle(int a) { +static void FP_FASTAPASS(1) cpuCycle (int a) { while (a--) if (irqEnabled) { if ((++irqCounterLow &4095) ==2048) irqCounterHigh--; if (!irqCounterHigh && (irqCounterLow &4095) <2048) X6502_IRQBegin(FCEU_IQEXT); } } -void UNLTH21311_power(void) { +static void power (void) { irqEnabled =irqCounterLow =irqCounterHigh =0; VRC24_power(); - SetWriteHandler(0xF000, 0xFFFF, UNLTH21311_writeIRQ); + SetWriteHandler(0xF000, 0xFFFF, writeIRQ); } void UNLTH21311_Init (CartInfo *info) { VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); - AddExState(UNLTH21311_stateRegs, ~0, 0, 0); - info->Power =UNLTH21311_power; - MapIRQHook =UNLTH21311_cpuCycle; + AddExState(stateRegs, ~0, 0, 0); + info->Power =power; + MapIRQHook =cpuCycle; } diff --git a/src/boards/351.c b/src/boards/351.c index 606361c..24de00d 100644 --- a/src/boards/351.c +++ b/src/boards/351.c @@ -40,7 +40,7 @@ static void sync () { int chrAND = reg[2] &0x40? 0x00: reg[2] &0x20? 0x7F: reg[2] &0x10? 0x1F: 0xFF; /* No inner bank in (C)NROM mode, 128K or 256K for others */ int prgOR = reg[1] >>1 &(reg[2] &0x01 && CHRRAM? prgMask_CHRRAM: prgMask_CHRROM) &~prgAND; int chrOR = reg[0] <<1 &~chrAND; - + if (reg[2] &0x10) { /* NROM mode */ if (reg[2] &0x08) { /* NROM-64 */ setprg8(0x8000, prgOR); @@ -61,7 +61,7 @@ static void sync () { VRC24_syncPRG(prgAND, prgOR); else MMC1_syncPRG(prgAND >>1, prgOR >>1); - + if (reg[2] &0x01 && CHRRAM) setchr8r(0x10, 0); else @@ -75,7 +75,7 @@ static void sync () { VRC24_syncCHR(chrAND, chrOR); else MMC1_syncCHR(chrAND >>2, chrOR >>2); - + if (~reg[0] &0x02) MMC3_syncMirror(); else @@ -85,7 +85,7 @@ static void sync () { MMC1_syncMirror(); } -DECLFW(VRC24_trapWriteReg) { /* When A11 is set, VRC4's A0 and A1 are swapped */ +DECLFW (VRC24_trapWriteReg) { /* When A11 is set, VRC4's A0 and A1 are swapped */ if (A &0x800) A = A &~0xF | A >>1 &0x5 | A <<1 &0xA; VRC24_writeReg(A, V); } @@ -107,25 +107,25 @@ static void applyMode (uint8 clear) { MMC1_activate(clear, sync, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL); } -static void Mapper351_restore (int version) { +static void restore (int version) { applyMode(0); sync(); } -static DECLFR(readDIP) { +static DECLFR (readDIP) { return dip; } -static DECLFW(writeReg) { +static DECLFW (writeReg) { reg[A &3] = V; applyMode(A == 2); } -static DECLFW(writeFDSMirroring) { +static DECLFW (writeFDSMirroring) { MMC3_writeReg(0xA000, V >>3 &1); } -static void Mapper351_power(void) { +static void power (void) { reg[0] = reg[1] = reg[2] = reg[3] = 0; dip = 0; SetReadHandler(0x5000, 0x5FFF, readDIP); @@ -135,13 +135,13 @@ static void Mapper351_power(void) { applyMode(1); } -static void Mapper351_reset (void) { +static void reset (void) { reg[0] = reg[1] = reg[2] = reg[3] = 0; dip++; applyMode(1); } -static void Mapper351_close(void) { +static void close (void) { if (CHRRAM) FCEU_gfree(CHRRAM); if (PRGCHR) FCEU_gfree(PRGCHR); CHRRAM = NULL; @@ -153,20 +153,21 @@ void Mapper351_Init (CartInfo *info) { MMC1_addExState(); MMC3_addExState(); VRC24_addExState(); - info->Reset = Mapper351_reset; - info->Power = Mapper351_power; - info->Close = Mapper351_close; - GameStateRestore = Mapper351_restore; - AddExState(stateRegs, ~0, 0, 0); + info->Reset = reset; + info->Power = power; + info->Close = close; + GameStateRestore = restore; + AddExState(stateRegs, ~0, 0, 0); /* When CHR-RAM is enabled, CHR-ROM becomes part of PRG-ROM address space. */ prgMask_CHRROM = prgMask_CHRRAM = PRGsize[0] /8192 -1; if (CHRRAMSIZE) { + uint8* newROM; CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); - prgMask_CHRRAM = (PRGsize[0] +CHRsize[0]) /8192 -1; - uint8* newROM = (uint8*)FCEU_gmalloc(PRGsize[0] +CHRsize[0]); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); + prgMask_CHRRAM = (PRGsize[0] +CHRsize[0]) /8192 -1; + newROM = (uint8*)FCEU_gmalloc(PRGsize[0] +CHRsize[0]); memcpy(newROM, ROM, info->PRGRomSize); memcpy(newROM +PRGsize[0], VROM, info->CHRRomSize); FCEU_gfree(ROM); diff --git a/src/boards/362.c b/src/boards/362.c index 187050d..e6d75b7 100644 --- a/src/boards/362.c +++ b/src/boards/362.c @@ -23,7 +23,7 @@ static uint8 game; -static SFORMAT Mapper362_stateRegs[] ={ +static SFORMAT stateRegs[] ={ { &game, 1, "GAME" }, { 0 } }; @@ -40,21 +40,21 @@ static void sync () { } } -void Mapper362_power(void) { +static void power (void) { game =0; VRC24_power(); } -void Mapper362_reset(void) { +static void reset (void) { game ^=1; - sync(); + VRC24_clear(); } void Mapper362_Init (CartInfo *info) { VRC4_init(info, sync, 0x01, 0x02, 0, NULL, NULL, NULL, NULL, NULL); - info->Power =Mapper362_power; + info->Power = power; if (PRGsize[0] >512*1024) { - info->Reset =Mapper362_reset; - AddExState(Mapper362_stateRegs, ~0, 0, 0); + info->Reset = reset; + AddExState(stateRegs, ~0, 0, 0); } } diff --git a/src/boards/384.c b/src/boards/384.c index 07f5dd1..02d7803 100644 --- a/src/boards/384.c +++ b/src/boards/384.c @@ -24,7 +24,7 @@ static uint8 reg; -static SFORMAT Mapper384_stateRegs[] ={ +static SFORMAT stateRegs[] ={ { ®, 1, "EXP0" }, { 0 } }; @@ -36,7 +36,7 @@ static void sync () { VRC24_syncWRAM(0); } -DECLFW(Mapper384_writeReg) { +static DECLFW (writeReg) { if (A &0x800 && ~reg &0x08) { reg =V; sync(); @@ -44,20 +44,20 @@ DECLFW(Mapper384_writeReg) { CartBW(A, V); } -void Mapper384_power(void) { +static void power (void) { reg =0; VRC24_power(); } -void Mapper384_reset(void) { +static void reset (void) { reg =0; - sync(); -} + VRC24_clear(); +} void Mapper384_Init (CartInfo *info) { - VRC4_init(info, sync, 0x04, 0x08, 0, NULL, NULL, NULL, Mapper384_writeReg, NULL); + VRC4_init(info, sync, 0x04, 0x08, 0, NULL, NULL, NULL, writeReg, NULL); WRAM_init(info, 2); - info->Power =Mapper384_power; - info->Reset =Mapper384_reset; - AddExState(Mapper384_stateRegs, ~0, 0, 0); + info->Power =power; + info->Reset =reset; + AddExState(stateRegs, ~0, 0, 0); } diff --git a/src/boards/398.c b/src/boards/398.c index d0785ff..ce1e630 100644 --- a/src/boards/398.c +++ b/src/boards/398.c @@ -23,7 +23,7 @@ static uint8 reg; -static SFORMAT Mapper398_stateRegs[] ={ +static SFORMAT stateRegs[] ={ { ®, 1, "EXP0" }, { 0 } }; @@ -39,25 +39,25 @@ static void sync () { VRC24_syncMirror(); } -DECLFW(Mapper398_writeReg) { +static DECLFW (writeReg) { reg =A &0xFF; VRC24_writeReg(A, V); } -void Mapper398_power(void) { - reg =0xC0; +static void power (void) { + reg = 0xC0; VRC24_power(); - SetWriteHandler(0x8000, 0xFFFF, Mapper398_writeReg); + SetWriteHandler(0x8000, 0xFFFF, writeReg); } -void Mapper398_reset(void) { - reg =0xC0; - sync(); +static void reset (void) { + reg = 0xC0; + VRC24_clear(); } void Mapper398_Init (CartInfo *info) { VRC4_init(info, sync, 0x01, 0x02, 1, NULL, NULL, NULL, NULL, NULL); - info->Power =Mapper398_power; - info->Reset =Mapper398_reset; - AddExState(Mapper398_stateRegs, ~0, 0, 0); + info->Power = power; + info->Reset = reset; + AddExState(stateRegs, ~0, 0, 0); } diff --git a/src/boards/432.c b/src/boards/432.c index c17c897..b93fe3c 100644 --- a/src/boards/432.c +++ b/src/boards/432.c @@ -27,11 +27,11 @@ static uint8 submapper; static uint8 reg[2]; static uint8 pad; -static DECLFR(readPad) { +static DECLFR (readPad) { return pad; } -static void sync() { +static void sync () { int prgAND = reg[1] &0x02? 0x0F: 0x1F; int chrAND = reg[1] &0x20 && submapper == 3? 0x1FF: reg[1] &0x04? 0x7F: 0xFF; int prgOR = reg[1] <<4 &0x10 | reg[1] <<1 &0x60; @@ -42,7 +42,7 @@ static void sync() { SetReadHandler(0x8000, 0xFFFF, submapper == 1 && reg[1] &0x20 || submapper != 1 && reg[0] &0x01? readPad: CartBR); } -static int getPRGBank(uint8 bank) { +static int getPRGBank (uint8 bank) { if (reg[1] &0x40) { int mask = reg[1] &(submapper == 2? 0x20: 0x80)? 3: 1; return MMC3_getPRGBank(bank &1) &~mask | bank &mask; @@ -50,14 +50,14 @@ static int getPRGBank(uint8 bank) { return MMC3_getPRGBank(bank); } -static int getCHRBank(uint8 bank) { +static int getCHRBank (uint8 bank) { if (reg[1] &0x20 && submapper == 3) return MMC3_getCHRBank(bank &6 | bank >>1 &1) <<1 | bank &1; else return MMC3_getCHRBank(bank); } -static DECLFW(writeReg) { +static DECLFW (writeReg) { if (submapper == 3 && reg[1] &0x80) ; else { @@ -66,19 +66,19 @@ static DECLFW(writeReg) { } } -static void reset() { +static void reset () { reg[0] = reg[1] = 0; ++pad; - sync(); + MMC3_clear(); } -static void power() { +static void power () { reg[0] = reg[1] = 0; pad = 0; MMC3_power(); } -void Mapper432_Init(CartInfo *info) { +void Mapper432_Init (CartInfo *info) { submapper =info->submapper; MMC3_init(info, sync, MMC3_TYPE_AX5202P, getPRGBank, getCHRBank, NULL, writeReg); info->Power = power; diff --git a/src/boards/445.c b/src/boards/445.c index 80bc5ac..0c5a77e 100644 --- a/src/boards/445.c +++ b/src/boards/445.c @@ -66,7 +66,7 @@ static void sync () { SetReadHandler(0x8000, 0xFFFF, reg[0] &0xC0 && (reg[0] &0xC0) == dip? NULL: CartBR); } -static void applyMode(uint8 clear) { +static void applyMode (uint8 clear) { if ((reg[2] >>3 &7) >= 5) Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); else @@ -84,7 +84,7 @@ static void Mapper445_restore (int version) { sync(); } -static DECLFW(writeReg) { +static DECLFW (writeReg) { if (~reg[3] &0x20) { reg[A &3] = V; if ((A &3) == 3) applyMode(1); diff --git a/src/boards/446.c b/src/boards/446.c index b2ef936..f2eaf91 100644 --- a/src/boards/446.c +++ b/src/boards/446.c @@ -165,7 +165,7 @@ static void sync_QJ (int prgAND, int prgOR, int chrAND, int chrOR) { QJ_syncCHR(chrAND, chrOR &~chrAND); QJ_syncMirror(); } -static void sync_TC3294(int prgAND, int prgOR, int chrAND, int chrOR) { +static void sync_TC3294 (int prgAND, int prgOR, int chrAND, int chrOR) { TC3294_syncWRAM(reg[5]); TC3294_syncPRG(prgAND, prgOR &~prgAND); setchr8(0); @@ -240,19 +240,19 @@ static void sync_supervisor (int prgAND, int prgOR, int chrAND, int chrOR) { setmirror(reg[4] &0x01? MI_V: MI_H); } -static DECLFW(writeFlash) { +static DECLFW (writeFlash) { flashrom_write(A &0x1FFF | (Page[A >>11] +A -PRGptr[0]) &~0x1FFF, V); } -static int SUROM_getPRGBank(uint8 bank) { +static int SUROM_getPRGBank (uint8 bank) { return MMC1_getPRGBank(bank) | MMC1_getCHRBank(0) &0x10; } -static int Mapper22_getCHRBank(uint8 bank) { +static int Mapper22_getCHRBank (uint8 bank) { return VRC24_getCHRBank(bank &7) >>1; } -static DECLFW(writeReg) { +static DECLFW (writeReg) { reg[A &7] = V; if ((A &7) == 0) applyMode(1); @@ -388,17 +388,17 @@ static void applyMode (uint8 clear) { } } -static void power() { +static void power () { reg[0] = reg[1] = reg[2] = reg[3] = reg[4] = reg[5] = reg[6] = reg[7] = 0; applyMode(1); SetReadHandler(0x8000, 0xFFFF, CartBR); } -static void stateRestore(int version) { +static void stateRestore (int version) { applyMode(0); } -void Mapper446_Init(CartInfo *info) { +void Mapper446_Init (CartInfo *info) { submapper =info->submapper; H3001_addExState(); Latch_addExState(); diff --git a/src/boards/447.c b/src/boards/447.c index 352d8d6..a5d23cd 100644 --- a/src/boards/447.c +++ b/src/boards/447.c @@ -25,7 +25,7 @@ static uint8 reg; static uint8 dip; -static SFORMAT Mapper447_stateRegs[] ={ +static SFORMAT stateRegs[] = { { ®, 1, "EXP0" }, { &dip, 1, "DIPS" }, { 0 } @@ -38,7 +38,7 @@ static void sync () { VRC24_syncWRAM(0); } -static int Mapper447_getPRGBank(uint8 bank) { +static int getPRGBank (uint8 bank) { if (reg &4) { if (~reg &2) return VRC24_getPRGBank(bank &1) &~2 | bank &2; @@ -48,35 +48,35 @@ static int Mapper447_getPRGBank(uint8 bank) { return VRC24_getPRGBank(bank); } -DECLFR(Mapper447_readPRG) { +static DECLFR (readPRG) { return CartBR(reg &8? (A &~3 | dip &3): A); } -DECLFW(Mapper447_writeReg) { +static DECLFW (writeReg) { if (~reg &1) { - reg =A &0xFF; + reg = A &0xFF; sync(); } CartBW(A, V); } -void Mapper447_power(void) { - reg =0; - dip =0; +static void power (void) { + reg = 0; + dip = 0; VRC24_power(); - SetReadHandler(0x8000, 0xFFFF, Mapper447_readPRG); + SetReadHandler(0x8000, 0xFFFF, readPRG); } -void Mapper447_reset(void) { - reg =0; +static void reset (void) { + reg = 0; dip++; sync(); -} +} void Mapper447_Init (CartInfo *info) { - VRC4_init(info, sync, 0x04, 0x08, 0, Mapper447_getPRGBank, NULL, NULL, Mapper447_writeReg, NULL ); + VRC4_init(info, sync, 0x04, 0x08, 0, getPRGBank, NULL, NULL, writeReg, NULL ); WRAM_init(info, 2); - info->Power =Mapper447_power; - info->Reset =Mapper447_reset; - AddExState(Mapper447_stateRegs, ~0, 0, 0); + info->Power = power; + info->Reset = reset; + AddExState(stateRegs, ~0, 0, 0); } diff --git a/src/boards/448.c b/src/boards/448.c index e31396e..04576ee 100644 --- a/src/boards/448.c +++ b/src/boards/448.c @@ -24,7 +24,7 @@ static uint8 reg; -static SFORMAT Mapper448_stateRegs[] ={ +static SFORMAT stateRegs[] ={ { ®, 1, "EXP0" }, { 0 } }; @@ -46,31 +46,31 @@ static void sync () { setchr8(0); } -DECLFW(Mapper448_writeReg) { +static DECLFW (writeReg) { reg =A &0xFF; sync(); CartBW(A, V); } -DECLFW(Mapper448_writePRG) { +static DECLFW (writePRG) { VRC24_writeReg(reg &8? 0x8000: A, V); } -void Mapper448_power(void) { +static void power (void) { reg =0; VRC24_power(); - SetWriteHandler(0x8000, 0xFFFF, Mapper448_writePRG); + SetWriteHandler(0x8000, 0xFFFF, writePRG); } -void Mapper448_reset(void) { +static void reset (void) { reg =0; - sync(); -} + VRC24_clear(); +} void Mapper448_Init (CartInfo *info) { - VRC4_init(info, sync, 0x04, 0x08, 0, NULL, NULL, NULL, Mapper448_writeReg, NULL); + VRC4_init(info, sync, 0x04, 0x08, 0, NULL, NULL, NULL, writeReg, NULL); WRAM_init(info, 2); - info->Power =Mapper448_power; - info->Reset =Mapper448_reset; - AddExState(Mapper448_stateRegs, ~0, 0, 0); + info->Power =power; + info->Reset =reset; + AddExState(stateRegs, ~0, 0, 0); } diff --git a/src/boards/449.c b/src/boards/449.c index 6fcefc2..c1fea0a 100644 --- a/src/boards/449.c +++ b/src/boards/449.c @@ -25,15 +25,15 @@ uint8 submapper; uint8 pad; uint8 padSelect; -static DECLFR(readPad_submapper0) { +static DECLFR (readPad_submapper0) { return CartBR(A &~0xF | pad &0xF); } -static DECLFR(readPad_submapper1) { +static DECLFR (readPad_submapper1) { return pad; } -static DECLFR(readPad_submapper2) { +static DECLFR (readPad_submapper2) { return CartBR(A &~0x3 | pad &0x3); } @@ -57,7 +57,7 @@ static void sync () { SetReadHandler(0x8000, 0xFFFF, submapper == 0 && Latch_address &0x200? readPad_submapper0: submapper == 2 && padSelect &1? readPad_submapper2: CartBR); } -static DECLFW(writePad_submapper2) { +static DECLFW (writePad_submapper2) { padSelect = V; sync(); } @@ -75,8 +75,7 @@ static void power () { static void reset () { pad++; padSelect = 0; - Latch_address = 0; - sync(); + Latch_clear(); } void Mapper449_Init (CartInfo *info) { diff --git a/src/boards/450.c b/src/boards/450.c index f0432d8..f2da501 100644 --- a/src/boards/450.c +++ b/src/boards/450.c @@ -27,12 +27,12 @@ static void sync () { VRC24_syncMirror(); } -void Mapper450_reset(void) { - VRC2_pins =0; - sync(); -} +static void reset(void) { + VRC2_pins = 0; + VRC24_clear(); +} void Mapper450_Init (CartInfo *info) { VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); - info->Reset =Mapper450_reset; + info->Reset = reset; } diff --git a/src/boards/458.c b/src/boards/458.c index 5a67d82..5ae5b05 100644 --- a/src/boards/458.c +++ b/src/boards/458.c @@ -1,7 +1,7 @@ /* FCEUmm - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2020 + * Copyright (C) 2025 NewRisingSun * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/boards/460.c b/src/boards/460.c index f09ae7e..1345e28 100644 --- a/src/boards/460.c +++ b/src/boards/460.c @@ -22,11 +22,11 @@ #include "mapinc.h" #include "asic_mmc3.h" +#include "cartram.h" static uint8 submapper; static uint8 reg; static uint8 pad; -static uint8 *CHRRAM = NULL; static DECLFR (readPad) { return CartBR(A &~3 | pad &3); @@ -74,23 +74,12 @@ static void power () { MMC3_power(); } -static void close () { - if (CHRRAM) { - FCEU_gfree(CHRRAM); - CHRRAM = NULL; - } -} - void Mapper460_Init (CartInfo *info) { submapper = info->submapper; MMC3_init(info, sync, MMC3_TYPE_SHARP, getPRGBank, getCHRBank, NULL, writeReg); + CHRRAM_init(info, 8); info->Power = power; info->Reset = reset; - info->Close = close; AddExState(®, 1, 0, "EXPR"); AddExState(®, 1, 0, "DIPS"); - - CHRRAM = (uint8 *)FCEU_gmalloc(8192); - SetupCartCHRMapping(0x10, CHRRAM, 8192, 1); - AddExState(CHRRAM, 8192, 0, "CRAM"); } diff --git a/src/boards/468.c b/src/boards/468.c index 48958ac..70110c8 100644 --- a/src/boards/468.c +++ b/src/boards/468.c @@ -67,7 +67,7 @@ static const uint16 lut509[512] = { /* Look-up table, used only by Legendary Gam 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 512, 513, 514, 515, 516, 517 }; -void setPins(uint8 select, uint8 newClock, uint8 newData) { /* Serial EEPROM */ +static void setPins(uint8 select, uint8 newClock, uint8 newData) { /* Serial EEPROM */ if (select) state = 0; else @@ -145,7 +145,7 @@ static void sync_IF12 (int prgOR) { setmirror(Custom_reg[0] &0x01? MI_H: MI_V); } -static DECLFW(IF12_writeReg) { +static DECLFW (IF12_writeReg) { Custom_reg[A >>14 &1] = V; sync(); } @@ -160,7 +160,7 @@ static void sync_LF36 (int prgOR) { setmirror(reg[0] &0x04? MI_H: MI_V); } -void FP_FASTAPASS(1) LF36_cpuCycle (int a) { +static void FP_FASTAPASS(1) LF36_cpuCycle (int a) { while (a--) { if (Custom_reg[1] &1) { if (!++Custom_reg[2]) ++Custom_reg[3]; @@ -201,7 +201,7 @@ static void sync_Misc (int prgOR) { setmirror(Custom_reg[1] &0x10? MI_1: MI_0); } -static DECLFW(Misc_writeReg) { +static DECLFW (Misc_writeReg) { switch(A >>12 &7) { case 0: case 2: case 3: Custom_reg[0] = V; @@ -232,7 +232,7 @@ static void Nanjing_scanline (void) { setchr8(0); } -static DECLFW(Nanjing_writeReg) { +static DECLFW (Nanjing_writeReg) { Custom_reg[A >>8 &3] = V; sync(); } @@ -259,7 +259,7 @@ static void sync_SUROM (int prgOR) { MMC1_syncMirror(); } -static int SUROM_getPRGBank(uint8 bank) { +static int SUROM_getPRGBank (uint8 bank) { return MMC1_getPRGBank(bank) | MMC1_getCHRBank(0) &0x10; } @@ -348,7 +348,7 @@ static void sync_VRC7 (int prgOR) { } /* Supervisor */ -static DECLFR(readReg) { +static DECLFR (readReg) { switch(A) { case 0x5301: case 0x5601: return output? 0x80: 0x00; @@ -357,7 +357,7 @@ static DECLFR(readReg) { } } -static DECLFW(writeReg) { +static DECLFW (writeReg) { switch(A) { case 0x5301: if (submapper == 0) setPins(!!(V &0x04), !!(V &0x02), !!(V &0x01)); @@ -500,7 +500,7 @@ static void applyMode (uint8 clear) { } } -static void power() { +static void power () { reg[0] = 0x0F; reg[1] = 0xFF; reg[2] = submapper == 1? 0x10: 0x00; @@ -511,11 +511,11 @@ static void power() { } -static void stateRestore(int version) { +static void stateRestore (int version) { applyMode(0); } -void Mapper468_Init(CartInfo *info) { +void Mapper468_Init (CartInfo *info) { submapper = info->submapper; FME7_addExState(); Latch_addExState(); diff --git a/src/boards/483.c b/src/boards/483.c index d033363..8bd4387 100644 --- a/src/boards/483.c +++ b/src/boards/483.c @@ -66,9 +66,10 @@ static void power () { applyMode(1); } -static void stateRestore(int version) { +static void stateRestore (int version) { applyMode(0); } + void Mapper483_Init (CartInfo *info) { AddExState(&game, 1, 0, "GAME"); Latch_addExState(); diff --git a/src/boards/490.c b/src/boards/490.c index 2403ed9..30c7fce 100644 --- a/src/boards/490.c +++ b/src/boards/490.c @@ -26,11 +26,11 @@ static uint8 reg; static uint8 pad; -static DECLFR(readPad) { +static DECLFR (readPad) { return CartBR(A &~0xF | pad &0xF); } -static void sync() { +static void sync () { if (reg &0x20) setprg32(0x8000, reg >>1); else { @@ -42,24 +42,24 @@ static void sync() { SetReadHandler(0x8000, 0xFFFF, reg &0x80? readPad: CartBR); } -static DECLFW(writeReg) { +static DECLFW (writeReg) { reg = A &0xFF; sync(); } -static void reset() { - reg = 0; - ++pad; - sync(); -} - -static void power() { +static void power () { reg = 0; pad = 0; MMC3_power(); } -void Mapper490_Init(CartInfo *info) { +static void reset () { + reg = 0; + ++pad; + MMC3_clear(); +} + +void Mapper490_Init (CartInfo *info) { MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); info->Power = power; info->Reset = reset; diff --git a/src/boards/494.c b/src/boards/494.c index 7820751..f7b1dbb 100644 --- a/src/boards/494.c +++ b/src/boards/494.c @@ -23,7 +23,7 @@ static uint8 pad; -static DECLFR(readOB) { +static DECLFR (readOB) { return X.DB; } @@ -43,12 +43,12 @@ static void sync () { SetReadHandler(0x8000, 0xFFFF, ~Latch_address &0x100 && Latch_address &0x001 &pad? readOB: CartBR); } -static void power() { +static void power () { pad = 0; Latch_power(); } -static void reset() { +static void reset () { pad++; Latch_clear(); } diff --git a/src/boards/495.c b/src/boards/495.c index 0867fae..65568ec 100644 --- a/src/boards/495.c +++ b/src/boards/495.c @@ -31,7 +31,7 @@ static SFORMAT stateRegs[] = { { 0 } }; -static void sync() { +static void sync () { setprg8(0x8000, prg[0]); setprg8(0xA000, prg[1]); setprg8(0xC000, prg[2]); @@ -53,7 +53,7 @@ static void FP_FASTAPASS(1) trapPPUAddressChange (uint32 A) { } } -static DECLFW(writeReg) { +static DECLFW (writeReg) { if (A <0xE000) prg[A >>13 &3] = V; else diff --git a/src/boards/503.c b/src/boards/503.c index 83bc127..04f944d 100644 --- a/src/boards/503.c +++ b/src/boards/503.c @@ -26,11 +26,11 @@ static uint8 reg; static uint8 pad; -static DECLFR(readPad) { +static DECLFR (readPad) { return CartBR(A &~3 | pad &3); } -static void sync() { +static void sync () { if (reg &0x10) setprg32(0x8000, reg >>1); else { @@ -42,24 +42,24 @@ static void sync() { SetReadHandler(0x8000, 0xFFFF, reg &0x20? readPad: CartBR); } -static DECLFW(writeReg) { +static DECLFW (writeReg) { reg = A &0xFF; sync(); } -static void reset() { +static void reset () { reg = 0; ++pad; - sync(); + MMC3_clear(); } -static void power() { +static void power () { reg = 0; pad = 0; MMC3_power(); } -void Mapper503_Init(CartInfo *info) { +void Mapper503_Init (CartInfo *info) { MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); info->Power = power; info->Reset = reset; diff --git a/src/boards/504.c b/src/boards/504.c index 1d4b777..93e1a32 100644 --- a/src/boards/504.c +++ b/src/boards/504.c @@ -25,7 +25,7 @@ static uint8 reg; -static void sync() { +static void sync () { int prgAND = reg &0x02? 0x0F: 0x1F; int chrAND = reg &0x02? 0x7F: 0xFF; int prgOR = reg <<4; @@ -35,29 +35,29 @@ static void sync() { MMC3_syncMirror(); } -static int getPRGBank(uint8 bank) { +static int getPRGBank (uint8 bank) { if ((reg &0x03) == 0x03 && ~reg &0x08) return MMC3_getPRGBank(bank &1) &~1 | bank &1; else return MMC3_getPRGBank(bank); } -static DECLFW(writeReg) { +static DECLFW (writeReg) { reg = A &0xFF; sync(); } -static void reset() { +static void reset () { reg = 0; - sync(); + MMC3_clear(); } -static void power() { +static void power () { reg = 0; MMC3_power(); } -void Mapper504_Init(CartInfo *info) { +void Mapper504_Init (CartInfo *info) { MMC3_init(info, sync, MMC3_TYPE_AX5202P, getPRGBank, NULL, NULL, writeReg); info->Power = power; info->Reset = reset; diff --git a/src/boards/505.c b/src/boards/505.c index 82027eb..24b4555 100644 --- a/src/boards/505.c +++ b/src/boards/505.c @@ -60,6 +60,6 @@ void Mapper505_Init (CartInfo *info) { MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, readPad, writeReg); info->Power = power; info->Reset = reset; - AddExState(®, 2, 0, "EXPR"); + AddExState(®, 2 | FCEUSTATE_RLSB, 0, "EXPR"); AddExState(&pad, 1, 0, "DIPS"); } diff --git a/src/boards/506.c b/src/boards/506.c index 69d049e..aac7e49 100644 --- a/src/boards/506.c +++ b/src/boards/506.c @@ -25,32 +25,32 @@ static uint8 reg; -static void sync() { +static void sync () { int prgAND =~reg &3? 0x0F: 0x1F; int chrAND = reg &3? 0x7F: 0xFF; - int prgOR = reg <<5 &0x20 | reg <<3 &0x10; - int chrOR = reg <<7 &0x100 |~reg <<7 &0x80; + int prgOR = reg <<5 &0x20 | reg <<3 &0x10; + int chrOR = reg <<7 &0x100 |~reg <<7 &0x80; MMC3_syncPRG(prgAND, prgOR &~prgAND); MMC3_syncCHR(chrAND, chrOR &~chrAND); MMC3_syncMirror(); } -static DECLFW(writeReg) { +static DECLFW (writeReg) { reg = A &0xFF; sync(); } -static void reset() { +static void reset () { reg = 0; - sync(); + MMC3_clear(); } -static void power() { +static void power () { reg = 0; MMC3_power(); } -void Mapper506_Init(CartInfo *info) { +void Mapper506_Init (CartInfo *info) { MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); info->Power = power; info->Reset = reset; diff --git a/src/boards/512.c b/src/boards/512.c index 9563843..c332e75 100644 --- a/src/boards/512.c +++ b/src/boards/512.c @@ -29,13 +29,13 @@ static uint8 reg; static void sync () { MMC3_syncPRG(0x3F, 0x00); MMC3_syncWRAM(0); - + if (reg &0x02) { setchr4r(0x10, 0x0000, 0); setchr4r(0x10, 0x1000, 0); } else MMC3_syncCHR(0xFF, 0x000); - + if (reg == 1) { /* The game uses six nametables - the two console-internal ones, plus four occupying the second half of 8 KiB CHR-RAM.*/ setntamem(CHRptr[0x10] +0x1000, 1, 0); setntamem(CHRptr[0x10] +0x1400, 1, 1); diff --git a/src/boards/524.c b/src/boards/524.c index 5e8d0af..2658bdd 100644 --- a/src/boards/524.c +++ b/src/boards/524.c @@ -24,7 +24,7 @@ static uint8 irqEnabled; static uint16 irqCounter; -static SFORMAT BTL900218_stateRegs[] ={ +static SFORMAT stateRegs[] ={ { &irqEnabled, 1, "IRQE" }, { &irqCounter, 2 | FCEUSTATE_RLSB, "CNTL" }, { 0 } @@ -36,7 +36,7 @@ static void sync () { VRC24_syncMirror(); } -DECLFW(BTL900218_writeIRQ) { +static DECLFW (writeIRQ) { if (A &8) { if (A &4) { irqEnabled =0; @@ -47,19 +47,19 @@ DECLFW(BTL900218_writeIRQ) { } } -void FP_FASTAPASS(1) BTL900218_cpuCycle(int a) { +static void FP_FASTAPASS(1) cpuCycle (int a) { while (a--) if (irqEnabled && ++irqCounter &1024) X6502_IRQBegin(FCEU_IQEXT); } -void BTL900218_power(void) { +static void power (void) { irqEnabled =irqCounter =0; VRC24_power(); - SetWriteHandler(0xF000, 0xFFFF, BTL900218_writeIRQ); + SetWriteHandler(0xF000, 0xFFFF, writeIRQ); } void BTL900218_Init (CartInfo *info) { VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); - AddExState(BTL900218_stateRegs, ~0, 0, 0); - info->Power =BTL900218_power; - MapIRQHook =BTL900218_cpuCycle; + AddExState(stateRegs, ~0, 0, 0); + info->Power =power; + MapIRQHook =cpuCycle; } diff --git a/src/boards/525.c b/src/boards/525.c index f398a2f..97a9316 100644 --- a/src/boards/525.c +++ b/src/boards/525.c @@ -27,7 +27,7 @@ static void sync () { VRC24_syncMirror(); } -DECLFW(UNLKS7021A_writeCHR) { +DECLFW (UNLKS7021A_writeCHR) { VRC24_writeReg(0xB000 +(A <<11 &0x3000 | A <<1 &0x0002), V &0x0F); VRC24_writeReg(0xB001 +(A <<11 &0x3000 | A <<1 &0x0002), V >>4); } @@ -39,5 +39,5 @@ void UNLKS7021A_power (void) { void UNLKS7021A_Init (CartInfo *info) { VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); - info->Power =UNLKS7021A_power; + info->Power = UNLKS7021A_power; } diff --git a/src/boards/529.c b/src/boards/529.c index ff5c7a0..af9e17b 100644 --- a/src/boards/529.c +++ b/src/boards/529.c @@ -36,25 +36,25 @@ static void sync () { VRC24_syncMirror(); } -DECLFR(UNLT230_readEEPROM) { +static DECLFR (readEEPROM) { return eeprom_93Cx6_read()? 0x01: 0x00; } -DECLFW(UNLT230_writeEEPROM) { +static DECLFW (writeEEPROM) { eeprom_93Cx6_write(A &0x04, A &0x02, A &0x01); } -void UNLT230_power (void) { +static void power (void) { VRC24_power(); eeprom_93Cx6_init(256, 16); - SetReadHandler(0x5000, 0x5FFF, UNLT230_readEEPROM); - SetWriteHandler(0xF800, 0xFFFF, UNLT230_writeEEPROM); + SetReadHandler(0x5000, 0x5FFF, readEEPROM); + SetWriteHandler(0xF800, 0xFFFF, writeEEPROM); } void UNLT230_Init (CartInfo *info) { VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, NULL, NULL, NULL); if (info->PRGRamSaveSize) { - info->Power =UNLT230_power; + info->Power =power; AddExState(stateRegs, ~0, 0, 0); eeprom_93Cx6_storage = eeprom_data; info->battery = 1; diff --git a/src/boards/530.c b/src/boards/530.c index 9a2e780..66924e8 100644 --- a/src/boards/530.c +++ b/src/boards/530.c @@ -27,26 +27,26 @@ static void sync () { VRC24_syncMirror(); } -int UNLAX5705_getPRGBank(uint8 bank) { +static int getPRGBank (uint8 bank) { int result =VRC24_getPRGBank(bank); return result <<2 &0x8 | result >>2 &0x2 | result &~0xA; } -int UNLAX5705_getCHRBank(uint8 bank) { +static int getCHRBank (uint8 bank) { int result =VRC24_getCHRBank(bank); return result <<1 &0x40 | result >>1 &0x20 | result &~0x60; } -DECLFW(UNLAX5705_unscrambleAddress) { +static DECLFW (unscrambleAddress) { VRC24_writeReg(A &~0x1000 | A <<9 &0x1000, V); } -void UNLAX5705_power (void) { +static void power (void) { VRC24_power(); - SetWriteHandler(0x8000, 0xFFFF, UNLAX5705_unscrambleAddress); + SetWriteHandler(0x8000, 0xFFFF, unscrambleAddress); } void UNLAX5705_Init (CartInfo *info) { - VRC4_init(info, sync, 0x01, 0x02, 1, UNLAX5705_getPRGBank, UNLAX5705_getCHRBank, NULL, NULL, NULL); - info->Power =UNLAX5705_power; + VRC4_init(info, sync, 0x01, 0x02, 1, getPRGBank, getCHRBank, NULL, NULL, NULL); + info->Power =power; } diff --git a/src/boards/542.c b/src/boards/542.c index 3dcb258..6d4a23a 100644 --- a/src/boards/542.c +++ b/src/boards/542.c @@ -36,7 +36,7 @@ static void sync () { if (reg &1) setchr1r(0x10, 0x0C00, 1); } -DECLFW(Mapper542_writeExtra) { +DECLFW (writeExtra) { if (A &0x800) { reg =A >>12; sync(); @@ -45,16 +45,16 @@ DECLFW(Mapper542_writeExtra) { } -void Mapper542_power (void) { +void power (void) { reg =0; VRC24_power(); SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0xD000, 0xEFFF, Mapper542_writeExtra); + SetWriteHandler(0xD000, 0xEFFF, writeExtra); } void Mapper542_Init (CartInfo *info) { VRC4_init(info, sync, 0x01, 0x02, 1, NULL, NULL, NULL, NULL, NULL); - info->Power =Mapper542_power; + info->Power =power; AddExState(stateRegs, ~0, 0, 0); SetupCartCHRMapping(0x10, NTARAM, 0x200, 1); } diff --git a/src/boards/544.c b/src/boards/544.c index 0918bc5..ae9ca8c 100644 --- a/src/boards/544.c +++ b/src/boards/544.c @@ -78,7 +78,7 @@ static DECLFW (externalSelect) { } -void power (void) { +static void power (void) { mask =0xFC; compare =0x28; nt[0] =nt[1] =0xE0; diff --git a/src/boards/548.c b/src/boards/548.c index 01d8e1a..ca82a20 100644 --- a/src/boards/548.c +++ b/src/boards/548.c @@ -33,7 +33,7 @@ static SFORMAT stateRegs[] ={ { ®, 1, "REGM" }, { &latch, 1, "LATC" }, { &counting, 1, "IRQA" }, - { &counter, 2, "IRQC" }, + { &counter, 2 | FCEUSTATE_RLSB, "IRQC" }, { 0 } }; @@ -72,7 +72,7 @@ static void FP_FASTAPASS(1) cpuCycle (int a) { } } -static void reset() { +static void reset () { FDSSoundReset(); X6502_IRQEnd(FCEU_IQEXT); latch = 0x07; @@ -82,7 +82,7 @@ static void reset() { sync(); } -static void power() { +static void power () { FDSSoundPower(); SetReadHandler(0x6000, 0xFFFF, CartBR); SetWriteHandler(0x4800, 0x4FFF, writeLatch); @@ -91,7 +91,7 @@ static void power() { reset(); } -static void stateRestore(int version) { +static void stateRestore (int version) { sync(); } diff --git a/src/boards/556.c b/src/boards/556.c index 669e804..b13bbed 100644 --- a/src/boards/556.c +++ b/src/boards/556.c @@ -31,8 +31,8 @@ static uint8 reg[4]; static uint8 index; static SFORMAT StateRegs[] = { - { reg, 5, "REGS" }, - { &index, 1, "INDX" }, + { reg, 4, "REGS" }, + { &index, 1, "INDX" }, { 0 }, }; diff --git a/src/boards/557.c b/src/boards/557.c index f579467..498bfea 100644 --- a/src/boards/557.c +++ b/src/boards/557.c @@ -24,14 +24,14 @@ #include "asic_n118.h" #include "cartram.h" -static void sync() { +static void sync () { setprg8r(0x10, 0x6000, 0); N118_syncPRG(0x0F, 0x00); setchr8(0); setmirror(N118_getCHRBank(7) &0x20? MI_H: MI_V); } -void Mapper557_Init(CartInfo *info) { +void Mapper557_Init (CartInfo *info) { N118_init(info, sync, NULL, NULL); WRAM_init(info, 8); } diff --git a/src/boards/559.c b/src/boards/559.c index 9b725a3..5baeaff 100644 --- a/src/boards/559.c +++ b/src/boards/559.c @@ -38,11 +38,11 @@ static void sync () { setmirrorw(nt[0] &1, nt[1] &1, nt[2] &1, nt[3] &1); } -int Mapper559_getPRGBank(uint8 bank) { +static int getPRGBank (uint8 bank) { return bank ==2? prg: VRC24_getPRGBank(bank); } -DECLFW(Mapper559_externalSelect) { +static DECLFW (externalSelect) { if (A &4) nt[A &3] =V; else @@ -50,20 +50,20 @@ DECLFW(Mapper559_externalSelect) { sync(); } -DECLFW(Mapper559_nibblizeData) { +static DECLFW (nibblizeData) { VRC24_writeReg(A, V >>(A &0x400? 4: 0)); } -void Mapper559_power (void) { +static void power (void) { nt[0] =nt[1] =0xE0; nt[2] =nt[3] =0xE1; prg =0xFE; VRC24_power(); - SetWriteHandler(0xB000, 0xFFFF, Mapper559_nibblizeData); + SetWriteHandler(0xB000, 0xFFFF, nibblizeData); } void Mapper559_Init (CartInfo *info) { - VRC4_init(info, sync, 0x400, 0x800, 1, Mapper559_getPRGBank, NULL, NULL, NULL, Mapper559_externalSelect); - info->Power =Mapper559_power; + VRC4_init(info, sync, 0x400, 0x800, 1, getPRGBank, NULL, NULL, NULL, externalSelect); + info->Power =power; AddExState(stateRegs, ~0, 0, 0); } diff --git a/src/boards/563.c b/src/boards/563.c index 9605464..1db54d4 100644 --- a/src/boards/563.c +++ b/src/boards/563.c @@ -36,7 +36,7 @@ static void sync () { VRC24_syncMirror(); } -static DECLFW(Mapper563_writeIRQ) { +static DECLFW (Mapper563_writeIRQ) { X6502_IRQEnd(FCEU_IQEXT); switch(A &0x1C) { case 0x0C: irqEnabled =0; break; @@ -49,8 +49,8 @@ static void Mapper563_scanline (void) { /* Actually, a sixteen-stage counter tri if (!(++irqCounter &1) && irqEnabled) X6502_IRQBegin(FCEU_IQEXT); } -static void Mapper563_power(void) { - irqEnabled =irqCounter =0; +static void Mapper563_power (void) { + irqEnabled = irqCounter =0; VRC24_power(); SetWriteHandler(0xF000, 0xFFFF, Mapper563_writeIRQ); } @@ -58,6 +58,6 @@ static void Mapper563_power(void) { void Mapper563_Init (CartInfo *info) { VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); AddExState(Mapper563_stateRegs, ~0, 0, 0); - info->Power =Mapper563_power; + info->Power = Mapper563_power; GameHBIRQHook = Mapper563_scanline; } diff --git a/src/boards/565.c b/src/boards/565.c index 722cf17..ff526d7 100644 --- a/src/boards/565.c +++ b/src/boards/565.c @@ -38,7 +38,7 @@ static void sync () { VRC24_syncMirror(); } -static DECLFW(writeIRQ) { +static DECLFW (writeIRQ) { switch(A &0x0C) { case 0: irqCounter = V; @@ -64,7 +64,7 @@ static void FP_FASTAPASS(1) cpuCycle (int a) { } } -static void power(void) { +static void power (void) { irqEnabled = irqCounter = irqPrescaler = 0; VRC24_power(); SetWriteHandler(0xF000, 0xFFFF, writeIRQ); diff --git a/src/boards/567.c b/src/boards/567.c index e62cd33..431c54a 100644 --- a/src/boards/567.c +++ b/src/boards/567.c @@ -25,7 +25,7 @@ static uint8 reg; -static void sync() { +static void sync () { MMC3_syncPRG(0x0F, reg <<4); if (reg == 0x0F) MMC3_syncCHR(0x1FF, 0x400); @@ -34,36 +34,36 @@ static void sync() { MMC3_syncMirror(); } -static int getPRGBank(uint8 bank) { +static int getPRGBank (uint8 bank) { if (reg == 0x08) { return MMC3_getPRGBank(bank &1) &~3 | bank &3; } else return MMC3_getPRGBank(bank); } -static int getCHRBank(uint8 bank) { +static int getCHRBank (uint8 bank) { if (reg == 0x0F) return MMC3_getCHRBank(bank &6 | bank >>1 &1) <<1 | bank &1; else return MMC3_getCHRBank(bank); } -static DECLFW(writeReg) { +static DECLFW (writeReg) { reg = A &0xFF; sync(); } -static void reset() { +static void reset () { reg = 0; - sync(); + MMC3_clear(); } -static void power() { +static void power () { reg = 0; MMC3_power(); } -void Mapper567_Init(CartInfo *info) { +void Mapper567_Init (CartInfo *info) { MMC3_init(info, sync, MMC3_TYPE_SHARP, getPRGBank, getCHRBank, NULL, writeReg); info->Power = power; info->Reset = reset; diff --git a/src/boards/569.c b/src/boards/569.c index 6d21d4e..a6f0dd5 100644 --- a/src/boards/569.c +++ b/src/boards/569.c @@ -25,7 +25,7 @@ static uint8 reg; -static void sync() { +static void sync () { int chrAND = reg &0x04? 0x1FF: reg &0x02? 0xFF: 0x7F; int chrOR = reg <<7; MMC3_syncPRG(0x0F, reg <<4 &~0x0F); @@ -33,36 +33,36 @@ static void sync() { MMC3_syncMirror(); } -static int getPRGBank(uint8 bank) { +static int getPRGBank (uint8 bank) { if (reg &0x08) { return MMC3_getPRGBank(0) &~3 | bank &3; } else return MMC3_getPRGBank(bank); } -static int getCHRBank(uint8 bank) { +static int getCHRBank (uint8 bank) { if (reg &0x04) return MMC3_getCHRBank(bank &6 | bank >>1 &1) <<1 | bank &1; else return MMC3_getCHRBank(bank); } -static DECLFW(writeReg) { +static DECLFW (writeReg) { reg = A &0xFF; sync(); } -static void reset() { +static void reset () { reg = 0; MMC3_clear(); } -static void power() { +static void power () { reg = 0; MMC3_power(); } -void Mapper569_Init(CartInfo *info) { +void Mapper569_Init (CartInfo *info) { MMC3_init(info, sync, MMC3_TYPE_SHARP, getPRGBank, getCHRBank, NULL, writeReg); info->Power = power; info->Reset = reset; diff --git a/src/boards/570.c b/src/boards/570.c index a30a5cc..baaa7cc 100644 --- a/src/boards/570.c +++ b/src/boards/570.c @@ -25,27 +25,27 @@ static uint8 reg; -static void sync() { +static void sync () { int prgAND = 0x0F; int chrAND = reg &0x03? 0x0FF: 0x1FF; - int prgOR = reg <<4; - int chrOR = !!(reg &0x03)*0x200 | !!(reg &0x02)*0x100; + int prgOR = reg <<4; + int chrOR = !!(reg &0x03)*0x200 | !!(reg &0x02)*0x100; VRC24_syncPRG(prgAND, prgOR &~prgAND); VRC24_syncCHR(chrAND, chrOR &~chrAND); VRC24_syncMirror(); } -static DECLFW(writeReg) { +static DECLFW (writeReg) { reg = A &0xFF; sync(); } -static void reset() { +static void reset () { reg = 0; - sync(); + VRC24_clear(); } -static void power() { +static void power () { reg = 0; VRC24_power(); SetWriteHandler(0x5000, 0x5FFF, writeReg); diff --git a/src/boards/572.c b/src/boards/572.c index ce59940..44ccb6c 100644 --- a/src/boards/572.c +++ b/src/boards/572.c @@ -25,34 +25,34 @@ static uint8 reg; -static void sync() { +static void sync () { int prgAND = 0x1F; int chrAND = 0x7F; - int prgOR = reg <<5; - int chrOR = reg <<7; + int prgOR = reg <<5; + int chrOR = reg <<7; MMC3_syncPRG(prgAND, prgOR &~prgAND); MMC3_syncCHR(chrAND, chrOR &~chrAND); MMC3_syncMirror(); } -static DECLFW(writeReg) { +static DECLFW (writeReg) { if (~reg &0x08) { reg = A &0xFF; sync(); } } -static void reset() { +static void reset () { reg = 0; - sync(); + MMC3_clear(); } -static void power() { +static void power () { reg = 0; MMC3_power(); } -void Mapper572_Init(CartInfo *info) { +void Mapper572_Init (CartInfo *info) { MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); info->Power = power; info->Reset = reset; diff --git a/src/boards/577.c b/src/boards/577.c index b2e0502..a969163 100644 --- a/src/boards/577.c +++ b/src/boards/577.c @@ -23,7 +23,7 @@ static uint8 pad; -static DECLFR(readOB) { +static DECLFR (readOB) { return X.DB; } @@ -34,12 +34,12 @@ static void sync () { setchr8(Latch_address >>1); } -static void power() { +static void power () { pad = 0; Latch_power(); } -static void reset() { +static void reset () { pad += 0x10; Latch_clear(); } diff --git a/src/boards/578.c b/src/boards/578.c index a45954e..298b516 100644 --- a/src/boards/578.c +++ b/src/boards/578.c @@ -25,7 +25,7 @@ static uint8 reg; -static void sync() { +static void sync () { int prgAND = reg &0x02 && reg &0x04? 0x1F: 0x0F; int chrAND = reg &0x02 && reg &0x04? 0xFF: 0x7F; int prgOR = reg <<4; @@ -35,24 +35,24 @@ static void sync() { MMC3_syncMirror(); } -static DECLFW(writeReg) { +static DECLFW (writeReg) { reg = V; sync(); } -static void reset() { +static void reset () { reg = 0; MMC3_clear(); } -static void power() { +static void power () { int i; reg = 0; MMC3_power(); - for (int i = 0x8000; i < 0xFFFF; i +=4) SetWriteHandler(i |2, i |3, writeReg); + for (i = 0x8000; i < 0xFFFF; i +=4) SetWriteHandler(i |2, i |3, writeReg); } -void Mapper578_Init(CartInfo *info) { +void Mapper578_Init (CartInfo *info) { MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); info->Power = power; info->Reset = reset; diff --git a/src/boards/584.c b/src/boards/584.c index 45519aa..295cbde 100644 --- a/src/boards/584.c +++ b/src/boards/584.c @@ -33,21 +33,21 @@ static void sync () { setmirror(reg[1] &0x20? MI_V: MI_H); } -static DECLFW(writeReg) { +static DECLFW (writeReg) { if (A &0x100) { reg[A >>13 &1] = V; sync(); } } -static void power() { +static void power () { SetReadHandler(0x6000, 0xFFFF, CartBR); SetWriteHandler(0x4020, 0x7FFF, writeReg); reg[0] = reg[1] = 0; sync(); } -static void stateRestore(int version) { +static void stateRestore (int version) { sync(); } diff --git a/src/boards/585.c b/src/boards/585.c index 0e60577..60c3761 100644 --- a/src/boards/585.c +++ b/src/boards/585.c @@ -23,7 +23,7 @@ static uint8 pad; -static DECLFR(readOB) { +static DECLFR (readOB) { return X.DB; } @@ -39,12 +39,12 @@ static void sync () { setmirror(Latch_address &0x10? MI_V: MI_H); } -static void power() { +static void power () { pad = 0; Latch_power(); } -static void reset() { +static void reset () { pad += 0x20; Latch_clear(); } diff --git a/src/boards/587.c b/src/boards/587.c index 91fe1b9..4c6c251 100644 --- a/src/boards/587.c +++ b/src/boards/587.c @@ -41,19 +41,19 @@ static void sync () { setmirror(reg[0] &0x01? MI_H: MI_V); } -static DECLFW(writeReg) { +static DECLFW (writeReg) { reg[reg[0] &0x80? 1: 0] = V; sync(); } -static void power() { +static void power () { SetReadHandler(0x6000, 0xFFFF, CartBR); SetWriteHandler(0x8000, 0xFFFF, writeReg); reg[0] = reg[1] = 0; sync(); } -static void stateRestore(int version) { +static void stateRestore (int version) { sync(); } diff --git a/src/boards/594.c b/src/boards/594.c index 1db75f9..be0c8a7 100644 --- a/src/boards/594.c +++ b/src/boards/594.c @@ -1,7 +1,7 @@ /* FCEUmm - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2020 + * Copyright (C) 2025 NewRisingSun * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,7 +24,6 @@ #include "asic_mmc3.h" #include "fifo.h" #include "msm6585.h" -#include static uint8 reg[4]; static FIFO fifo; @@ -104,7 +103,7 @@ static void mapperSound_fillBufferHigh () { soundOffset = SOUNDTS; } -static void mapperSound_setSoundOffset(int32 newSoundOffset) { +static void mapperSound_setSoundOffset (int32 newSoundOffset) { soundOffset = newSoundOffset; } @@ -118,7 +117,7 @@ static void mapperSound_init (void) { MSM6585_init(&adpcm, FSettings.soundq >=1? 1789773: FSettings.SndRate*16, serveADPCM); } -static void close() { +static void close () { FIFO_close(&fifo); } diff --git a/src/boards/asic_fme7.c b/src/boards/asic_fme7.c index 3b66263..6be1d20 100644 --- a/src/boards/asic_fme7.c +++ b/src/boards/asic_fme7.c @@ -58,15 +58,15 @@ void FME7_syncMirror () { setmirror(FME7_reg[12] &2? (FME7_reg[12] &1? MI_1: MI_0): FME7_reg[12] &1? MI_H: MI_V); } -DECLFR(FME7_readWRAM) { +DECLFR (FME7_readWRAM) { return ~FME7_reg[8] &0x40 || FME7_reg[8] &0x80? CartBR(A): A >>8; } -DECLFW(FME7_writeWRAM) { +DECLFW (FME7_writeWRAM) { if (FME7_reg[8] &0x80) CartBW(A, V); } -DECLFW(FME7_writeReg) { +DECLFW (FME7_writeReg) { if (A &0x2000) { FME7_reg[FME7_index &0xF] = V; if ((FME7_index &0xF) == 13) X6502_IRQEnd(FCEU_IQEXT); @@ -84,7 +84,7 @@ void FP_FASTAPASS(1) FME7_cpuCycle (int a) { } } -static void FME7_clear () { +void FME7_clear () { int i; for (i = 0; i < 16; i++) FME7_reg[i] = 0; FME7_cbSync(); diff --git a/src/boards/asic_fme7.h b/src/boards/asic_fme7.h index 1528e9f..06994d3 100644 --- a/src/boards/asic_fme7.h +++ b/src/boards/asic_fme7.h @@ -25,10 +25,11 @@ void FME7_syncWRAM (int); void FME7_syncPRG (int, int); void FME7_syncCHR (int, int); void FME7_syncMirror (); -DECLFR(FME7_readWRAM); -DECLFW(MMC3_writeWRAM); -DECLFW(FME7_writeReg); +DECLFR (FME7_readWRAM); +DECLFW (FME7_writeWRAM); +DECLFW (FME7_writeReg); void FP_FASTAPASS(1) FME7_cpuCycle (int); +void FME7_clear (); void FME7_activate (uint8, void (*)()); void FME7_addExState (); void FME7_restore (int); diff --git a/src/boards/asic_h3001.c b/src/boards/asic_h3001.c index 308b45b..77c7554 100644 --- a/src/boards/asic_h3001.c +++ b/src/boards/asic_h3001.c @@ -33,11 +33,11 @@ static uint16 H3001_count; static SFORMAT H3001_state[] = { { H3001_prg, 2, "H31P" }, { H3001_chr, 8, "H31C" }, - {&H3001_layout, 4, "H31L" }, - {&H3001_nt, 4, "H31M" }, - {&H3001_irq, 4, "H31N" }, - {&H3001_reload, 2, "H31R" }, - {&H3001_count, 2, "H31T" }, + {&H3001_layout, 1, "H31L" }, + {&H3001_nt, 1, "H31M" }, + {&H3001_irq, 1, "H31N" }, + {&H3001_reload, 2 | FCEUSTATE_RLSB, "H31R" }, + {&H3001_count, 2 | FCEUSTATE_RLSB, "H31T" }, { 0 } }; @@ -68,7 +68,7 @@ void H3001_syncMirror () { setmirror(H3001_nt &0x40? (H3001_nt &0x80? MI_1: MI_0): H3001_nt &0x80? MI_H: MI_V); } -DECLFW(H3001_write) { +DECLFW (H3001_write) { switch(A >>12 &7) { case 0: case 2: H3001_prg[A >>13 &1] = V; @@ -114,7 +114,7 @@ void FP_FASTAPASS(1) H3001_cpuCycle (int a) { } } -static void H3001_clear () { +void H3001_clear () { int i; for (i = 0; i < 2; i++) H3001_prg[i] = i; for (i = 0; i < 8; i++) H3001_chr[i] = i; diff --git a/src/boards/asic_h3001.h b/src/boards/asic_h3001.h index 97dfd58..1c5122e 100644 --- a/src/boards/asic_h3001.h +++ b/src/boards/asic_h3001.h @@ -25,6 +25,7 @@ void H3001_syncPRG (int, int); void H3001_syncCHR (int, int); void H3001_syncMirror (); DECLFW (H3001_write); +void H3001_clear (); void H3001_activate (uint8, void (*)()); void H3001_addExState (); void H3001_restore (int); diff --git a/src/boards/asic_latch.c b/src/boards/asic_latch.c index 538ccd0..579de14 100644 --- a/src/boards/asic_latch.c +++ b/src/boards/asic_latch.c @@ -33,7 +33,7 @@ static SFORMAT Latch_state[] = { { 0 } }; -DECLFW(Latch_write) { +DECLFW (Latch_write) { uint16 newAddress = A &0xFFFF; if (Latch_cbWrite) Latch_cbWrite(&newAddress, &V, CartBR(A)); Latch_address = newAddress; diff --git a/src/boards/asic_mmc1.c b/src/boards/asic_mmc1.c index 42fdc6a..1c5a5de 100644 --- a/src/boards/asic_mmc1.c +++ b/src/boards/asic_mmc1.c @@ -64,14 +64,14 @@ int MMC1_getCHRBank (uint8 bank) { return MMC1_reg[1] &~1 |bank; } -DECLFR(MMC1_readWRAM) { +DECLFR (MMC1_readWRAM) { if (MMC1_type == MMC1_TYPE_MMC1A || ~MMC1_reg[3] &0x10) return MMC1_cbReadWRAM? MMC1_cbReadWRAM(A): CartBR(A); else return A >>8; } -DECLFW(MMC1_writeWRAM) { +DECLFW (MMC1_writeWRAM) { if (MMC1_type == MMC1_TYPE_MMC1A || ~MMC1_reg[3] &0x10) { CartBW(A, V); if (MMC1_cbWriteWRAM) MMC1_cbWriteWRAM(A, V); @@ -92,11 +92,11 @@ void MMC1_syncMirror () { setmirror(MMC1_reg[0] &2? (MMC1_reg[0] &1? MI_H: MI_V): (MMC1_reg[0] &1? MI_1: MI_0)); } -void FP_FASTAPASS(1) MMC1_cpuCycle(int a) { +void FP_FASTAPASS(1) MMC1_cpuCycle (int a) { while (a--) if (MMC1_filter) MMC1_filter--; } -DECLFW(MMC1_writeReg) { +DECLFW (MMC1_writeReg) { if (V &0x80) { MMC1_reg[0] |= 0x0C; MMC1_shift = 0; @@ -115,7 +115,7 @@ DECLFW(MMC1_writeReg) { MMC1_filter = 2; } -void MMC1_clear() { +void MMC1_clear () { MMC1_reg[0] = 0x0C; MMC1_reg[1] = 0; MMC1_reg[2] = 0; MMC1_reg[3] = 0; /* "Bad News Baseball" is sensitive to the initial CHR bank register content. 0/0 seems to work. */ MMC1_bits = 0; MMC1_shift = 0; MMC1_filter = 0; MMC1_cbSync(); diff --git a/src/boards/asic_mmc2and4.c b/src/boards/asic_mmc2and4.c index 9be02c3..fd6c5f2 100644 --- a/src/boards/asic_mmc2and4.c +++ b/src/boards/asic_mmc2and4.c @@ -65,12 +65,12 @@ static void FP_FASTAPASS(1) MMC24_trapPPUAddressChange (uint32 A) { } } -DECLFW(MMC24_write) { +DECLFW (MMC24_write) { MMC24_reg[(A >>12) -0xA] = V; MMC24_cbSync(); } -static void MMC24_clear () { +void MMC24_clear () { MMC24_reg[0] = 0; MMC24_reg[1] = 0; MMC24_reg[2] = 2; MMC24_reg[3] = 0; MMC24_reg[4] = 0; MMC24_reg[5] = 0; MMC24_latch[0] = 0; MMC24_latch[1] = 0; MMC24_cbSync(); diff --git a/src/boards/asic_mmc2and4.h b/src/boards/asic_mmc2and4.h index 176890c..5c408a3 100644 --- a/src/boards/asic_mmc2and4.h +++ b/src/boards/asic_mmc2and4.h @@ -27,6 +27,7 @@ void MMC4_syncPRG (int, int); void MMC24_syncCHR (int, int); void MMC24_syncMirror (); DECLFW (MMC24_write); +void MMC24_clear (); void MMC24_power (); void MMC24_restore (int); void MMC24_addExState (); diff --git a/src/boards/asic_mmc3.c b/src/boards/asic_mmc3.c index d7267ce..330ba74 100644 --- a/src/boards/asic_mmc3.c +++ b/src/boards/asic_mmc3.c @@ -66,14 +66,14 @@ uint8 MMC3_getMirroring (void) { return MMC3_mirroring; } -DECLFR(MMC3_readWRAM) { +DECLFR (MMC3_readWRAM) { if (MMC3_wramControl &0x80 || MMC3_type == MMC3_TYPE_AX5202P || MMC3_type == MMC3_TYPE_MMC6) return MMC3_cbReadWRAM? MMC3_cbReadWRAM(A): CartBR(A); else return A >>8; } -DECLFW(MMC3_writeWRAM) { +DECLFW (MMC3_writeWRAM) { if ((MMC3_wramControl &0x80 || MMC3_type == MMC3_TYPE_AX5202P) && ~MMC3_wramControl &0x40 || MMC3_type == MMC3_TYPE_MMC6) { CartBW(A, V); if (MMC3_cbWriteWRAM) MMC3_cbWriteWRAM(A, V); diff --git a/src/boards/asic_n118.c b/src/boards/asic_n118.c index 757875a..4ef93d3 100644 --- a/src/boards/asic_n118.c +++ b/src/boards/asic_n118.c @@ -51,7 +51,7 @@ void N118_syncCHR (int AND, int OR) { for (bank = 0; bank < 8; bank++) setchr1(bank <<10, N118_cbGetCHRBank(bank) &AND |OR); } -DECLFW(N118_writeReg) { +DECLFW (N118_writeReg) { if (A &1) { N118_reg[N118_index &7] = V; N118_cbSync(); diff --git a/src/boards/asic_pt8154.c b/src/boards/asic_pt8154.c index cdcda37..16ac8a2 100644 --- a/src/boards/asic_pt8154.c +++ b/src/boards/asic_pt8154.c @@ -44,19 +44,19 @@ void PT8154_syncMirror () { MMC3_syncMirror(); } -DECLFW(PT8154_writeExtra) { +DECLFW (PT8154_writeExtra) { if (A &0x100) { PT8154_reg = V >>4; PT8154_cbSync(); } } -DECLFW(PT8154_writeWRAM) { +DECLFW (PT8154_writeWRAM) { PT8154_reg = A; PT8154_cbSync(); } -static void PT8154_clear () { +void PT8154_clear () { PT8154_reg = 0; PT8154_cbSync(); } diff --git a/src/boards/asic_pt8154.h b/src/boards/asic_pt8154.h index f5c9dda..1991d25 100644 --- a/src/boards/asic_pt8154.h +++ b/src/boards/asic_pt8154.h @@ -26,6 +26,7 @@ void PT8154_syncCHR (int, int); void PT8154_syncMirror (); DECLFW (PT8154_writeExtra); DECLFW (PT8154_writeWRAM); +void PT8154_clear (); void PT8154_activate (uint8, void (*)()); void PT8154_addExState (); void PT8154_restore (int); diff --git a/src/boards/asic_qj.c b/src/boards/asic_qj.c index 7c72557..5ad8b44 100644 --- a/src/boards/asic_qj.c +++ b/src/boards/asic_qj.c @@ -42,12 +42,12 @@ void QJ_syncMirror () { MMC3_syncMirror(); } -DECLFW(QJ_writeWRAM) { +DECLFW (QJ_writeWRAM) { QJ_reg = V; QJ_cbSync(); } -static void QJ_clear () { +void QJ_clear () { QJ_reg = 0; QJ_cbSync(); } diff --git a/src/boards/asic_qj.h b/src/boards/asic_qj.h index 0e8eddc..28ecd9e 100644 --- a/src/boards/asic_qj.h +++ b/src/boards/asic_qj.h @@ -26,6 +26,7 @@ void QJ_syncPRG (int, int); void QJ_syncCHR (int, int); void QJ_syncMirror (); DECLFW (QJ_write); +void QJ_clear (); void QJ_activate (uint8, void (*)()); void QJ_addExState (); void QJ_restore (int); diff --git a/src/boards/asic_tc3294.c b/src/boards/asic_tc3294.c index 04ccc41..a22de7b 100644 --- a/src/boards/asic_tc3294.c +++ b/src/boards/asic_tc3294.c @@ -52,14 +52,14 @@ void TC3294_syncMirror () { MMC3_syncMirror(); } -DECLFW(TC3294_write) { +DECLFW(TC3294_writeReg) { if (~TC3294_reg[3] &0x40) { TC3294_reg[TC3294_index++ &3] = V; TC3294_cbSync(); } } -static void TC3294_clear () { +void TC3294_clear () { TC3294_reg[0] = 0x00; TC3294_reg[1] = 0x00; TC3294_reg[2] = 0x0F; TC3294_reg[3] = 0x00; TC3294_index = 0; TC3294_cbSync(); @@ -73,7 +73,7 @@ static void TC3294_configure (void (*sync)()) { } void TC3294_activate (uint8 clear, void (*sync)()) { - MMC3_activate(clear, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, TC3294_write); + MMC3_activate(clear, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, TC3294_writeReg); TC3294_configure(sync); TC3294_setHandlers(); if (clear) @@ -97,7 +97,7 @@ void TC3294_power () { } void TC3294_init (CartInfo *info, void (*sync)()) { - MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, TC3294_write); + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, TC3294_writeReg); TC3294_addExState(); TC3294_configure(sync); info->Power = TC3294_power; diff --git a/src/boards/asic_tc3294.h b/src/boards/asic_tc3294.h index 1be126c..a1ba78b 100644 --- a/src/boards/asic_tc3294.h +++ b/src/boards/asic_tc3294.h @@ -26,7 +26,8 @@ void TC3294_syncWRAM (int); void TC3294_syncPRG (int, int); void TC3294_syncCHR (int, int); void TC3294_syncMirror (); -DECLFW (TC3294_write); +DECLFW (TC3294_writeReg); +void TC3294_clear (); void TC3294_activate (uint8, void (*)()); void TC3294_addExState (); void TC3294_restore (int); diff --git a/src/boards/asic_vrc1.c b/src/boards/asic_vrc1.c index 63ece13..c25ef2c 100644 --- a/src/boards/asic_vrc1.c +++ b/src/boards/asic_vrc1.c @@ -45,19 +45,19 @@ void VRC1_syncMirror () { setmirror(VRC1_reg[1] &0x01? MI_H: MI_V); } -DECLFW(VRC1_write) { +DECLFW (VRC1_writeReg) { VRC1_reg[A >>12 &7] = V; VRC1_cbSync(); } -static void VRC1_clear () { +void VRC1_clear () { VRC1_reg[0] = 0x00; VRC1_reg[1] = 0; VRC1_reg[2] = 2; VRC1_reg[3] = 0;VRC1_reg[4] = 0x00; VRC1_reg[5] = 0; VRC1_reg[6] = 2; VRC1_reg[7] = 0; VRC1_cbSync(); } static void VRC1_setHandlers () { SetReadHandler (0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, VRC1_write); + SetWriteHandler(0x8000, 0xFFFF, VRC1_writeReg); } static void VRC1_configure (void (*sync)()) { diff --git a/src/boards/asic_vrc1.h b/src/boards/asic_vrc1.h index 040c2b0..ed44fd6 100644 --- a/src/boards/asic_vrc1.h +++ b/src/boards/asic_vrc1.h @@ -24,7 +24,8 @@ void VRC1_syncPRG (int, int); void VRC1_syncCHR (int, int); void VRC1_syncMirror (); -DECLFW (VRC1_write); +DECLFW (VRC1_writeReg); +void VRC1_clear (); void VRC1_activate (uint8, void (*)()); void VRC1_addExState (); void VRC1_restore (int); diff --git a/src/boards/asic_vrc2and4.c b/src/boards/asic_vrc2and4.c index be5b4cb..3e0cc22 100644 --- a/src/boards/asic_vrc2and4.c +++ b/src/boards/asic_vrc2and4.c @@ -29,13 +29,13 @@ static int (*VRC24_cbGetCHRBank)(uint8); static DECLFR((*VRC24_cbReadWRAM)); static DECLFW((*VRC24_cbWriteWRAM)); static DECLFW((*VRC24_cbExternalSelect)); -static uint8 VRC24_isVRC4; /* VRC2 or VRC4? VRC2 has no single-screen mirroring, no PRG A14 swap and no IRQ counter */ +static uint8 VRC24_isVRC4; /* VRC2 or VRC4? VRC2 has no single-screen mirroring, no PRG A14 swap and no IRQ counter */ static uint8 VRC24_useRepeatBit; /* Some VRC4 clones ignore the "repeat" bit in the IRQ Mode register */ static uint8 VRC24_prg[2]; static uint16 VRC24_chr[8]; static uint8 VRC24_mirroring; static uint8 VRC24_misc; -uint8 VRC2_pins; /* EEPROM interface */ +uint8 VRC2_pins; /* EEPROM interface */ static uint8 VRC4_latch; static uint8 VRC4_mode; static uint8 VRC4_count; @@ -103,11 +103,11 @@ void VRC24_syncMirror () { setmirror(VRC24_isVRC4 && VRC24_mirroring &2? (VRC24_mirroring &1? MI_1: MI_0): (VRC24_mirroring &1? MI_H: MI_V)); } -DECLFR(VRC2_readMicrowire) { +DECLFR (VRC2_readMicrowire) { return VRC2_pins; } -DECLFR(VRC24_readWRAM) { +DECLFR (VRC24_readWRAM) { if (VRC24_misc &1 || !VRC24_isVRC4) { if (VRC24_cbReadWRAM) return VRC24_cbReadWRAM(A); @@ -120,12 +120,12 @@ DECLFR(VRC24_readWRAM) { return A >>8; } -DECLFW(VRC2_writeMicrowire) { +DECLFW (VRC2_writeMicrowire) { VRC2_pins = V; VRC24_cbSync(); } -DECLFW(VRC24_writeWRAM) { +DECLFW (VRC24_writeWRAM) { if (VRC24_misc &1 || !VRC24_isVRC4) { if (WRAMSize) CartBW(((A -0x6000) &(WRAMSize -1)) +0x6000, V); @@ -134,7 +134,7 @@ DECLFW(VRC24_writeWRAM) { } } -DECLFW(VRC24_writeReg) { +DECLFW (VRC24_writeReg) { unsigned int index, addr; addr = A &0xF000 | (A &VRC24_A0? 1: 0) | (A &VRC24_A1? 2: 0); /* address as the chip sees it */ switch (addr &0xF000) { @@ -194,7 +194,7 @@ void FP_FASTAPASS(1) VRC4_cpuCycle (int a) { } } -static void VRC24_clear() { +void VRC24_clear () { VRC24_prg[0] = 0; VRC24_prg[1] = 0; VRC24_chr[0] = 0; VRC24_chr[1] = 1; VRC24_chr[2] = 2; VRC24_chr[3] = 3; VRC24_chr[4] = 4; VRC24_chr[5] = 5; VRC24_chr[6] = 6; VRC24_chr[7] = 7; VRC24_mirroring = VRC2_pins = VRC4_latch = VRC4_mode = VRC4_count = VRC4_cycles = 0; diff --git a/src/boards/asic_vrc2and4.h b/src/boards/asic_vrc2and4.h index ed82969..0dcc8f7 100644 --- a/src/boards/asic_vrc2and4.h +++ b/src/boards/asic_vrc2and4.h @@ -38,6 +38,7 @@ DECLFW(VRC24_writeReg); void FP_FASTAPASS(1) VRC4_cpuCycle(int); void VRC24_reconfigure (int, int); +void VRC24_clear (); void VRC2_activate (uint8, void (*)(), int, int, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*))); void VRC4_activate (uint8, void (*)(), int, int, uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*)), DECLFW((*))); void VRC2_addExState (); diff --git a/src/boards/asic_vrc3.c b/src/boards/asic_vrc3.c index 717ad5b..ec43c0b 100644 --- a/src/boards/asic_vrc3.c +++ b/src/boards/asic_vrc3.c @@ -48,7 +48,7 @@ void VRC3_syncCHR (int AND, int OR) { setchr8(OR); } -DECLFW(VRC3_write) { +DECLFW (VRC3_write) { int shift; switch (A >>12 &7) { case 0: case 1: case 2: case 3: @@ -81,7 +81,7 @@ void FP_FASTAPASS(1) VRC3_cpuCycle (int a) { } } -static void VRC3_clear () { +void VRC3_clear () { VRC3_prg = VRC3_irq = VRC3_count = VRC3_reload = 0; X6502_IRQEnd(FCEU_IQEXT); VRC3_cbSync(); diff --git a/src/boards/asic_vrc3.h b/src/boards/asic_vrc3.h index 28147bb..2c73fd5 100644 --- a/src/boards/asic_vrc3.h +++ b/src/boards/asic_vrc3.h @@ -25,6 +25,7 @@ void VRC3_syncWRAM (int); void VRC3_syncPRG (int, int); void VRC3_syncCHR (int, int); DECLFW (VRC3_write); +void VRC3_clear (); void VRC3_activate (uint8, void (*)()); void VRC3_addExState (); void VRC3_restore (int); diff --git a/src/boards/asic_vrc6.c b/src/boards/asic_vrc6.c index c8cc694..3748322 100644 --- a/src/boards/asic_vrc6.c +++ b/src/boards/asic_vrc6.c @@ -83,21 +83,21 @@ int VRC6_getCHRBank (uint8 bank) { /* Only emulates features used by known games return VRC6_chr[bank &7]; } -DECLFR(VRC6_readWRAM) { +DECLFR (VRC6_readWRAM) { if (VRC6_misc &0x80) return VRC6_cbReadWRAM? VRC6_cbReadWRAM(A): CartBR(A); else return A >>8; } -DECLFW(VRC6_writeWRAM) { +DECLFW (VRC6_writeWRAM) { if (VRC6_misc &0x80) { CartBW(A, V); if (VRC6_cbWriteWRAM) VRC6_cbWriteWRAM(A, V); } } -DECLFW(VRC6_writeReg) { +DECLFW (VRC6_writeReg) { unsigned int index; index = (A &VRC6_A0? 1: 0) | (A &VRC6_A1? 2: 0); switch (A >>12 &7) { @@ -151,7 +151,7 @@ void FP_FASTAPASS(1) VRC6_cpuCycle (int a) { } } -static void VRC6_clear () { +void VRC6_clear () { VRC6_prg[0] = 0; VRC6_prg[1] = 0xFE; VRC6_chr[0] = 0; VRC6_chr[1] = 1; VRC6_chr[2] = 2; VRC6_chr[3] = 3; VRC6_chr[4] = 4; VRC6_chr[5] = 5; VRC6_chr[6] = 6; VRC6_chr[7] = 7; VRC6_misc = VRC6_latch = VRC6_mode = VRC6_count = VRC6_cycles = 0; diff --git a/src/boards/asic_vrc6.h b/src/boards/asic_vrc6.h index ae5cbf0..4d3fe8b 100644 --- a/src/boards/asic_vrc6.h +++ b/src/boards/asic_vrc6.h @@ -31,6 +31,7 @@ DECLFR(VRC6_readWRAM); DECLFW(MMC3_writeWRAM); DECLFW(VRC6_writeReg); void FP_FASTAPASS(1) VRC6_cpuCycle (int); +void VRC6_clear (); void VRC6_activate (uint8, void (*)(), int, int, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*))); void VRC6_addExState (); void VRC6_restore (int); diff --git a/src/boards/asic_vrc7.c b/src/boards/asic_vrc7.c index 2461a21..54ee04b 100644 --- a/src/boards/asic_vrc7.c +++ b/src/boards/asic_vrc7.c @@ -68,15 +68,15 @@ void VRC7_syncMirror () { setmirror(VRC7_misc &2? (VRC7_misc &1? MI_1: MI_0): VRC7_misc &1? MI_H: MI_V); } -DECLFR(VRC7_readWRAM) { +DECLFR (VRC7_readWRAM) { return VRC7_misc &0x80? CartBR(A): A >>8; } -DECLFW(VRC7_writeWRAM) { +DECLFW (VRC7_writeWRAM) { if (VRC7_misc &0x80) CartBW(A, V); } -DECLFW(VRC7_writeReg) { +DECLFW (VRC7_writeReg) { unsigned int index; index = A &VRC7_A0? 1: 0; switch (A >>12 &7) { @@ -128,7 +128,7 @@ void FP_FASTAPASS(1) VRC7_cpuCycle (int a) { } } -static void VRC7_clear () { +void VRC7_clear () { VRC7_prg[0] = 0; VRC7_prg[1] = 1; VRC7_prg[2] = 0xFE; VRC7_chr[0] = 0; VRC7_chr[1] = 1; VRC7_chr[2] = 2; VRC7_chr[3] = 3; VRC7_chr[4] = 4; VRC7_chr[5] = 5; VRC7_chr[6] = 6; VRC7_chr[7] = 7; VRC7_misc = VRC7_latch = VRC7_mode = VRC7_count = VRC7_cycles = 0; diff --git a/src/boards/asic_vrc7.h b/src/boards/asic_vrc7.h index 8320468..3431774 100644 --- a/src/boards/asic_vrc7.h +++ b/src/boards/asic_vrc7.h @@ -29,6 +29,7 @@ DECLFR(VRC7_readWRAM); DECLFW(MMC3_writeWRAM); DECLFW(VRC7_writeReg); void FP_FASTAPASS(1) VRC7_cpuCycle (int); +void VRC7_clear (); void VRC7_activate (uint8, void (*)(), int); void VRC7_addExState (); void VRC7_restore (int); diff --git a/src/boards/bmck3006.c b/src/boards/bmck3006.c index f4deed0..7b5ca30 100644 --- a/src/boards/bmck3006.c +++ b/src/boards/bmck3006.c @@ -26,7 +26,7 @@ #include "mapinc.h" #include "mmc3.h" -static uint8 submapper; // 0: K-3006, 1: unmarked, 2: TL 8058, 3: K-3091/GN-16 +static uint8 submapper; /* 0: K-3006, 1: unmarked, 2: TL 8058, 3: K-3091/GN-16 */ static DECLFR (readPad) { return CartBR(A &~3 | EXPREGS[2] &3); diff --git a/src/boards/cartram.c b/src/boards/cartram.c index 17e5a6f..02d04de 100644 --- a/src/boards/cartram.c +++ b/src/boards/cartram.c @@ -29,37 +29,37 @@ uint32 WRAMSize = 0; void CartRAM_close (void) { /* Need to combine this in one function to avoid the problem of having to properly cascade two separate Close() functions for WRAM and CHR-RAM each */ if (WRAMData) { FCEU_gfree(WRAMData); - WRAMData =NULL; + WRAMData = NULL; } if (CHRRAMData) { FCEU_gfree(CHRRAMData); - CHRRAMData =NULL; + CHRRAMData = NULL; } } void CartRAM_init (CartInfo *info, uint8 defaultWRAMSizeKiB, uint8 defaultCHRRAMSizeKiB) { - WRAMSize =info->iNES2? (info->PRGRamSize +info->PRGRamSaveSize): (defaultWRAMSizeKiB *1024); + WRAMSize = info->iNES2? (info->PRGRamSize +info->PRGRamSaveSize): (defaultWRAMSizeKiB *1024); if (WRAMSize) { - WRAMData =(uint8*)FCEU_gmalloc(WRAMSize); + WRAMData = (uint8*)FCEU_gmalloc(WRAMSize); SetupCartPRGMapping(0x10, WRAMData, WRAMSize, 1); AddExState(WRAMData, WRAMSize, 0, "WRAM"); - if (info->battery) { - info->SaveGame[0] =WRAMData; - info->SaveGameLen[0] =WRAMSize; + if (info->battery && (info->PRGRamSaveSize || !info->iNES2)) { + info->SaveGame[0] = WRAMData; + info->SaveGameLen[0] = info->iNES2? info->PRGRamSaveSize: WRAMSize; } } - CHRRAMSize =info->iNES2? (info->CHRRamSize +info->CHRRamSaveSize): (defaultCHRRAMSizeKiB *1024); + CHRRAMSize = info->iNES2? (info->CHRRamSize +info->CHRRamSaveSize): (defaultCHRRAMSizeKiB *1024); if (ROM_size == 0) CHRRAMSize = 0; /* If there is no CHR-ROM, then any CHR-RAM will not be "extra" and therefore will be handled by ines.c, not here. */ if (CHRRAMSize) { - CHRRAMData =(uint8*)FCEU_gmalloc(CHRRAMSize); + CHRRAMData = (uint8*)FCEU_gmalloc(CHRRAMSize); SetupCartCHRMapping(0x10, CHRRAMData, CHRRAMSize, 1); AddExState(CHRRAMData, CHRRAMSize, 0, "CRAM"); - if (info->battery) { - info->SaveGame[info->SaveGameLen[0]? 1: 0] =CHRRAMData; - info->SaveGameLen[info->SaveGameLen[0]? 1: 0] =CHRRAMSize; + if (info->battery && (info->CHRRamSaveSize || !info->iNES2)) { + info->SaveGame[info->SaveGameLen[0]? 1: 0] = CHRRAMData; + info->SaveGameLen[info->SaveGameLen[0]? 1: 0] = info->iNES2? info->CHRRamSaveSize: CHRRAMSize; } } - if (WRAMSize || CHRRAMSize) info->Close =CartRAM_close; + if (WRAMSize || CHRRAMSize) info->Close = CartRAM_close; } void CHRRAM_init (CartInfo *info, uint8 defaultCHRRAMSizeKiB) { diff --git a/src/boards/fifo.c b/src/boards/fifo.c index cb25f64..542671c 100644 --- a/src/boards/fifo.c +++ b/src/boards/fifo.c @@ -31,8 +31,8 @@ void FIFO_init (FIFO *fifo, size_t newCapacity) { fifo->capacity = newCapacity; fifo->data = (uint8*)FCEU_gmalloc(newCapacity); AddExState(fifo->data, fifo->capacity, 0, "FIFD"); - AddExState(&fifo->front, 2, 0, "FIFF"); - AddExState(&fifo->back, 2, 0, "FIFB"); + AddExState(&fifo->front, 2 | FCEUSTATE_RLSB, 0, "FIFF"); + AddExState(&fifo->back, 2 | FCEUSTATE_RLSB, 0, "FIFB"); } void FIFO_close (FIFO *fifo) { diff --git a/src/boards/msm6585.c b/src/boards/msm6585.c index c103a31..bf1a702 100644 --- a/src/boards/msm6585.c +++ b/src/boards/msm6585.c @@ -2,54 +2,54 @@ #include "msm6585.h" static const int16_t diff_lookup[49*16] = { - 2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30, - 2, 6, 10, 14, 19, 23, 27, 31, -2, -6, -10, -14, -19, -23, -27, -31, - 2, 6, 11, 15, 21, 25, 30, 34, -2, -6, -11, -15, -21, -25, -30, -34, - 2, 7, 12, 17, 23, 28, 33, 38, -2, -7, -12, -17, -23, -28, -33, -38, - 2, 7, 13, 18, 25, 30, 36, 41, -2, -7, -13, -18, -25, -30, -36, -41, - 3, 9, 15, 21, 28, 34, 40, 46, -3, -9, -15, -21, -28, -34, -40, -46, - 3, 10, 17, 24, 31, 38, 45, 52, -3, -10, -17, -24, -31, -38, -45, -52, - 3, 10, 18, 25, 34, 41, 49, 56, -3, -10, -18, -25, -34, -41, -49, -56, - 4, 12, 21, 29, 38, 46, 55, 63, -4, -12, -21, -29, -38, -46, -55, -63, - 4, 13, 22, 31, 41, 50, 59, 68, -4, -13, -22, -31, -41, -50, -59, -68, - 5, 15, 25, 35, 46, 56, 66, 76, -5, -15, -25, -35, -46, -56, -66, -76, - 5, 16, 27, 38, 50, 61, 72, 83, -5, -16, -27, -38, -50, -61, -72, -83, - 6, 18, 31, 43, 56, 68, 81, 93, -6, -18, -31, -43, -56, -68, -81, -93, - 6, 19, 33, 46, 61, 74, 88, 101, -6, -19, -33, -46, -61, -74, -88, -101, - 7, 22, 37, 52, 67, 82, 97, 112, -7, -22, -37, -52, -67, -82, -97, -112, - 8, 24, 41, 57, 74, 90, 107, 123, -8, -24, -41, -57, -74, -90, -107, -123, - 9, 27, 45, 63, 82, 100, 118, 136, -9, -27, -45, -63, -82, -100, -118, -136, - 10, 30, 50, 70, 90, 110, 130, 150, -10, -30, -50, -70, -90, -110, -130, -150, - 11, 33, 55, 77, 99, 121, 143, 165, -11, -33, -55, -77, -99, -121, -143, -165, - 12, 36, 60, 84, 109, 133, 157, 181, -12, -36, -60, -84, -109, -133, -157, -181, - 13, 39, 66, 92, 120, 146, 173, 199, -13, -39, -66, -92, -120, -146, -173, -199, - 14, 43, 73, 102, 132, 161, 191, 220, -14, -43, -73, -102, -132, -161, -191, -220, - 16, 48, 81, 113, 146, 178, 211, 243, -16, -48, -81, -113, -146, -178, -211, -243, - 17, 52, 88, 123, 160, 195, 231, 266, -17, -52, -88, -123, -160, -195, -231, -266, - 19, 58, 97, 136, 176, 215, 254, 293, -19, -58, -97, -136, -176, -215, -254, -293, - 21, 64, 107, 150, 194, 237, 280, 323, -21, -64, -107, -150, -194, -237, -280, -323, - 23, 70, 118, 165, 213, 260, 308, 355, -23, -70, -118, -165, -213, -260, -308, -355, - 26, 78, 130, 182, 235, 287, 339, 391, -26, -78, -130, -182, -235, -287, -339, -391, - 28, 85, 143, 200, 258, 315, 373, 430, -28, -85, -143, -200, -258, -315, -373, -430, - 31, 94, 157, 220, 284, 347, 410, 473, -31, -94, -157, -220, -284, -347, -410, -473, - 34, 103, 173, 242, 313, 382, 452, 521, -34, -103, -173, -242, -313, -382, -452, -521, - 38, 114, 191, 267, 345, 421, 498, 574, -38, -114, -191, -267, -345, -421, -498, -574, - 42, 126, 210, 294, 379, 463, 547, 631, -42, -126, -210, -294, -379, -463, -547, -631, - 46, 138, 231, 323, 417, 509, 602, 694, -46, -138, -231, -323, -417, -509, -602, -694, - 51, 153, 255, 357, 459, 561, 663, 765, -51, -153, -255, -357, -459, -561, -663, -765, - 56, 168, 280, 392, 505, 617, 729, 841, -56, -168, -280, -392, -505, -617, -729, -841, - 61, 184, 308, 431, 555, 678, 802, 925, -61, -184, -308, -431, -555, -678, -802, -925, - 68, 204, 340, 476, 612, 748, 884, 1020, -68, -204, -340, -476, -612, -748, -884, -1020, - 74, 223, 373, 522, 672, 821, 971, 1120, -74, -223, -373, -522, -672, -821, -971, -1120, - 82, 246, 411, 575, 740, 904, 1069, 1233, -82, -246, -411, -575, -740, -904, -1069, -1233, - 90, 271, 452, 633, 814, 995, 1176, 1357, -90, -271, -452, -633, -814, -995, -1176, -1357, - 99, 298, 497, 696, 895, 1094, 1293, 1492, -99, -298, -497, -696, -895, -1094, -1293, -1492, - 109, 328, 547, 766, 985, 1204, 1423, 1642, -109, -328, -547, -766, -985, -1204, -1423, -1642, - 120, 360, 601, 841, 1083, 1323, 1564, 1804, -120, -360, -601, -841, -1083, -1323, -1564, -1804, - 132, 397, 662, 927, 1192, 1457, 1722, 1987, -132, -397, -662, -927, -1192, -1457, -1722, -1987, - 145, 436, 728, 1019, 1311, 1602, 1894, 2185, -145, -436, -728, -1019, -1311, -1602, -1894, -2185, - 160, 480, 801, 1121, 1442, 1762, 2083, 2403, -160, -480, -801, -1121, -1442, -1762, -2083, -2403, - 176, 528, 881, 1233, 1587, 1939, 2292, 2644, -176, -528, -881, -1233, -1587, -1939, -2292, -2644, + 2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30, + 2, 6, 10, 14, 19, 23, 27, 31, -2, -6, -10, -14, -19, -23, -27, -31, + 2, 6, 11, 15, 21, 25, 30, 34, -2, -6, -11, -15, -21, -25, -30, -34, + 2, 7, 12, 17, 23, 28, 33, 38, -2, -7, -12, -17, -23, -28, -33, -38, + 2, 7, 13, 18, 25, 30, 36, 41, -2, -7, -13, -18, -25, -30, -36, -41, + 3, 9, 15, 21, 28, 34, 40, 46, -3, -9, -15, -21, -28, -34, -40, -46, + 3, 10, 17, 24, 31, 38, 45, 52, -3, -10, -17, -24, -31, -38, -45, -52, + 3, 10, 18, 25, 34, 41, 49, 56, -3, -10, -18, -25, -34, -41, -49, -56, + 4, 12, 21, 29, 38, 46, 55, 63, -4, -12, -21, -29, -38, -46, -55, -63, + 4, 13, 22, 31, 41, 50, 59, 68, -4, -13, -22, -31, -41, -50, -59, -68, + 5, 15, 25, 35, 46, 56, 66, 76, -5, -15, -25, -35, -46, -56, -66, -76, + 5, 16, 27, 38, 50, 61, 72, 83, -5, -16, -27, -38, -50, -61, -72, -83, + 6, 18, 31, 43, 56, 68, 81, 93, -6, -18, -31, -43, -56, -68, -81, -93, + 6, 19, 33, 46, 61, 74, 88, 101, -6, -19, -33, -46, -61, -74, -88, -101, + 7, 22, 37, 52, 67, 82, 97, 112, -7, -22, -37, -52, -67, -82, -97, -112, + 8, 24, 41, 57, 74, 90, 107, 123, -8, -24, -41, -57, -74, -90, -107, -123, + 9, 27, 45, 63, 82, 100, 118, 136, -9, -27, -45, -63, -82, -100, -118, -136, + 10, 30, 50, 70, 90, 110, 130, 150, -10, -30, -50, -70, -90, -110, -130, -150, + 11, 33, 55, 77, 99, 121, 143, 165, -11, -33, -55, -77, -99, -121, -143, -165, + 12, 36, 60, 84, 109, 133, 157, 181, -12, -36, -60, -84, -109, -133, -157, -181, + 13, 39, 66, 92, 120, 146, 173, 199, -13, -39, -66, -92, -120, -146, -173, -199, + 14, 43, 73, 102, 132, 161, 191, 220, -14, -43, -73, -102, -132, -161, -191, -220, + 16, 48, 81, 113, 146, 178, 211, 243, -16, -48, -81, -113, -146, -178, -211, -243, + 17, 52, 88, 123, 160, 195, 231, 266, -17, -52, -88, -123, -160, -195, -231, -266, + 19, 58, 97, 136, 176, 215, 254, 293, -19, -58, -97, -136, -176, -215, -254, -293, + 21, 64, 107, 150, 194, 237, 280, 323, -21, -64, -107, -150, -194, -237, -280, -323, + 23, 70, 118, 165, 213, 260, 308, 355, -23, -70, -118, -165, -213, -260, -308, -355, + 26, 78, 130, 182, 235, 287, 339, 391, -26, -78, -130, -182, -235, -287, -339, -391, + 28, 85, 143, 200, 258, 315, 373, 430, -28, -85, -143, -200, -258, -315, -373, -430, + 31, 94, 157, 220, 284, 347, 410, 473, -31, -94, -157, -220, -284, -347, -410, -473, + 34, 103, 173, 242, 313, 382, 452, 521, -34, -103, -173, -242, -313, -382, -452, -521, + 38, 114, 191, 267, 345, 421, 498, 574, -38, -114, -191, -267, -345, -421, -498, -574, + 42, 126, 210, 294, 379, 463, 547, 631, -42, -126, -210, -294, -379, -463, -547, -631, + 46, 138, 231, 323, 417, 509, 602, 694, -46, -138, -231, -323, -417, -509, -602, -694, + 51, 153, 255, 357, 459, 561, 663, 765, -51, -153, -255, -357, -459, -561, -663, -765, + 56, 168, 280, 392, 505, 617, 729, 841, -56, -168, -280, -392, -505, -617, -729, -841, + 61, 184, 308, 431, 555, 678, 802, 925, -61, -184, -308, -431, -555, -678, -802, -925, + 68, 204, 340, 476, 612, 748, 884, 1020, -68, -204, -340, -476, -612, -748, -884, -1020, + 74, 223, 373, 522, 672, 821, 971, 1120, -74, -223, -373, -522, -672, -821, -971, -1120, + 82, 246, 411, 575, 740, 904, 1069, 1233, -82, -246, -411, -575, -740, -904, -1069, -1233, + 90, 271, 452, 633, 814, 995, 1176, 1357, -90, -271, -452, -633, -814, -995, -1176, -1357, + 99, 298, 497, 696, 895, 1094, 1293, 1492, -99, -298, -497, -696, -895, -1094, -1293, -1492, + 109, 328, 547, 766, 985, 1204, 1423, 1642, -109, -328, -547, -766, -985, -1204, -1423, -1642, + 120, 360, 601, 841, 1083, 1323, 1564, 1804, -120, -360, -601, -841, -1083, -1323, -1564, -1804, + 132, 397, 662, 927, 1192, 1457, 1722, 1987, -132, -397, -662, -927, -1192, -1457, -1722, -1987, + 145, 436, 728, 1019, 1311, 1602, 1894, 2185, -145, -436, -728, -1019, -1311, -1602, -1894, -2185, + 160, 480, 801, 1121, 1442, 1762, 2083, 2403, -160, -480, -801, -1121, -1442, -1762, -2083, -2403, + 176, 528, 881, 1233, 1587, 1939, 2292, 2644, -176, -528, -881, -1233, -1587, -1939, -2292, -2644, 194, 582, 970, 1358, 1746, 2134, 2522, 2910, -194, -582, -970, -1358, -1746, -2134, -2522, -2910 }; static const int16_t index_shift[8] = { -1, -1, -1, -1, 2, 4, 6, 8 }; @@ -59,16 +59,16 @@ void MSM6585_init (MSM6585* chip, int32 newHostClock, int (*newGetInput)(void)) chip->getInput = newGetInput; AddExState(&chip->whichNibble, 1, 0, "MSMW"); AddExState(&chip->input, 1, 0, "MSMI"); - AddExState(&chip->signal, 2, 0, "MSMO"); - AddExState(&chip->count, 4, 0, "MSMC"); - AddExState(&chip->rate, 4, 0, "MSMR"); - AddExState(&chip->step, 2, 0, "MSMS"); + AddExState(&chip->signal, 2 | FCEUSTATE_RLSB, 0, "MSMO"); + AddExState(&chip->count, 4 | FCEUSTATE_RLSB, 0, "MSMC"); + AddExState(&chip->rate, 4 | FCEUSTATE_RLSB, 0, "MSMR"); + AddExState(&chip->step, 2 | FCEUSTATE_RLSB, 0, "MSMS"); } void MSM6585_reset (MSM6585* chip) { chip->count = 0; chip->step = 0; - chip->signal = -2; + chip->signal = -2; } void MSM6585_setRate (MSM6585* chip, uint8 rateByte) { @@ -78,8 +78,8 @@ void MSM6585_setRate (MSM6585* chip, uint8 rateByte) { void MSM6585_run (MSM6585* chip) { chip->count += chip->rate; while (chip->count >= chip->hostClock) { + uint8_t nibble; chip->count -= chip->hostClock; - uint8_t nibble; if (chip->whichNibble) nibble = chip->input &0x0F; else { @@ -92,7 +92,7 @@ void MSM6585_run (MSM6585* chip) { if (chip->signal <-2048) chip->signal =-2048; chip->step += index_shift[nibble &7]; if (chip->step > 48) chip->step = 48; - if (chip->step < 0) chip->step = 0; + if (chip->step < 0) chip->step = 0; } } From 2df4fac549999c769f97b8e95d6e448ddc9f8397 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 22:18:38 +0200 Subject: [PATCH 105/109] Add UNIF MAPRs for some of the newly-added mappers. --- src/unif.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/unif.c b/src/unif.c index 7260b1e..6667abf 100644 --- a/src/unif.c +++ b/src/unif.c @@ -626,7 +626,15 @@ static BMAPPING bmap[] = { { "K86B", 439, Mapper439_Init, 0 }, { "COOLGIRL", 342, COOLGIRL_Init, BMCFLAG_256KCHRR }, { "S-2009", 434, Mapper434_Init, 0 }, - + { "Yhc-Unrom-Cart", 500, Mapper500_Init, 0 }, + { "Yhc-Axrom-Cart", 501, Mapper501_Init, 0 }, + { "Yhc-A/B/Uxrom-Cart", 502, Mapper502_Init, 0 }, + { "JY4M4", 537, Mapper537_Init, 0 }, + { "82112C", 540, Mapper540_Init, 0 }, + { "KN-20", 577, Mapper577_Init, 0 }, + { "820436-C", 579, Mapper579_Init, 0 }, + { "8203", 585, Mapper585_Init, 0 }, + { "K-3057", 587, Mapper587_Init, 0 }, { NULL, NO_INES, NULL, 0 } }; From 5c6dc553cb7fb5832ff846590c683f7f698fe1a4 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 22:32:41 +0200 Subject: [PATCH 106/109] Change a variable name to resolve name conflict with PS2 driver. --- src/boards/556.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/boards/556.c b/src/boards/556.c index b13bbed..3e6dd7f 100644 --- a/src/boards/556.c +++ b/src/boards/556.c @@ -28,11 +28,11 @@ #include "cartram.h" static uint8 reg[4]; -static uint8 index; +static uint8 rIdx; static SFORMAT StateRegs[] = { { reg, 4, "REGS" }, - { &index, 1, "INDX" }, + { &rIdx, 1, "INDX" }, { 0 }, }; @@ -63,8 +63,8 @@ static void applyMode (uint8 clear) { static DECLFW(writeReg) { if (~reg[3] &0x80) { - reg[index++ &3] = V; - if (index == 3) + reg[rIdx++ &3] = V; + if (rIdx == 3) applyMode(1); else sync(); @@ -74,14 +74,14 @@ static DECLFW(writeReg) { static void reset (void) { reg[0] = reg[1] = reg[3] = 0; reg[2] = 0x0F; - index = 0; + rIdx = 0; applyMode(1); } static void power (void) { reg[0] = reg[1] = reg[3] = 0; reg[2] = 0x0F; - index = 0; + rIdx = 0; SetReadHandler(0x6000, 0xFFFF, CartBR); SetWriteHandler(0x5000, 0x5FFF, writeReg); applyMode(1); From 7d13d3aa054467099f5ba3c56041bad86ff6a0a2 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 22:34:53 +0200 Subject: [PATCH 107/109] Correct for case sensitive filename. --- src/boards/asic_fme7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boards/asic_fme7.c b/src/boards/asic_fme7.c index 6be1d20..2cb4a09 100644 --- a/src/boards/asic_fme7.c +++ b/src/boards/asic_fme7.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "asic_FME7.h" +#include "asic_fme7.h" static void (*FME7_cbSync)(); static uint8 FME7_index; From 04726b827ed4f82a79d715930afcf61474bb6994 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 22:36:58 +0200 Subject: [PATCH 108/109] Correct incompatible pointer type. --- src/boards/asic_h3001.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boards/asic_h3001.c b/src/boards/asic_h3001.c index 77c7554..e4dd57c 100644 --- a/src/boards/asic_h3001.c +++ b/src/boards/asic_h3001.c @@ -161,5 +161,5 @@ void H3001_init (CartInfo *info, void (*sync)()) { H3001_configure(sync); info->Power = H3001_power; info->Reset = H3001_cbSync; - GameStateRestore = H3001_cbSync; + GameStateRestore = H3001_restore; } From 825ce0c0a6816133b85ec0dcba29a2230fdb5d1a Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 12 Sep 2025 22:38:42 +0200 Subject: [PATCH 109/109] More case sensitive filename corrections. --- src/boards/asic_pt8154.c | 2 +- src/boards/asic_qj.c | 2 +- src/boards/asic_vrc3.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/boards/asic_pt8154.c b/src/boards/asic_pt8154.c index 16ac8a2..9a80a1d 100644 --- a/src/boards/asic_pt8154.c +++ b/src/boards/asic_pt8154.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "asic_PT8154.h" +#include "asic_pt8154.h" #include "asic_mmc3.h" static void (*PT8154_cbSync)(); diff --git a/src/boards/asic_qj.c b/src/boards/asic_qj.c index 5ad8b44..1562d73 100644 --- a/src/boards/asic_qj.c +++ b/src/boards/asic_qj.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "asic_QJ.h" +#include "asic_qj.h" #include "asic_mmc3.h" static void (*QJ_cbSync)(); diff --git a/src/boards/asic_vrc3.c b/src/boards/asic_vrc3.c index ec43c0b..2f46e4e 100644 --- a/src/boards/asic_vrc3.c +++ b/src/boards/asic_vrc3.c @@ -19,7 +19,7 @@ */ #include "mapinc.h" -#include "asic_VRC3.h" +#include "asic_vrc3.h" static void (*VRC3_cbSync)(); static uint8 VRC3_prg;