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 *);