diff --git a/src/boards/116.c b/src/boards/116.c index b9c8b2c..151b8b7 100644 --- a/src/boards/116.c +++ b/src/boards/116.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2011 CaH4e3 + * Copyright (C) 2023 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,353 +16,130 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * SL12 Protected 3-in-1 mapper hardware (VRC2, MMC3, MMC1) - * the same as 603-5052 board (TODO: add reading registers, merge) - * SL1632 2-in-1 protected board, similar to SL12 (TODO: find difference) - * - * Known PCB: - * - * Garou Densetsu Special (G0904.PCB, Huang-1, GAL dip: W conf.) - * Kart Fighter (008, Huang-1, GAL dip: W conf.) - * Somari (008, C5052-13, GAL dip: P conf., GK2-P/GK2-V maskroms) - * Somari (008, Huang-1, GAL dip: W conf., GK1-P/GK1-V maskroms) - * AV Mei Shao Nv Zhan Shi (aka AV Pretty Girl Fighting) (SL-12 PCB, Hunag-1, GAL dip: unk conf. SL-11A/SL-11B maskroms) - * Samurai Spirits (Full version) (Huang-1, GAL dip: unk conf. GS-2A/GS-4A maskroms) - * Contra Fighter (603-5052 PCB, C5052-3, GAL dip: unk conf. SC603-A/SCB603-B maskroms) - * */ #include "mapinc.h" +#include "asic_mmc1.h" +#include "asic_mmc3.h" +#include "asic_vrc2and4.h" -static uint8 vrc2_chr[8] = { 0 }; -static uint8 vrc2_prg[2] = { 0 }; -static uint8 vrc2_mirr = 0; +static uint8 submapper; +static uint8 reg; +static uint8 init; /* Games switch between ASICs expecting registers to keep their value, so initialize each ASIC only on the first switch and use this bitfield to track it */ +static uint8 game; -static uint8 mmc3_regs[10] = { 0 }; -static uint8 mmc3_ctrl = 0; -static uint8 mmc3_mirr = 0; - -static uint8 mmc1_regs[4] = { 0 }; -static uint8 mmc1_buffer = 0; -static uint8 mmc1_shift = 0; - -static uint8 IRQCount = 0; -static uint8 IRQLatch = 0; -static uint8 IRQa = 0; -static uint8 IRQReload = 0; -static uint8 mode = 0; - -static uint8 submapper = 0; -static uint8 game = 0; - -extern uint32 ROM_size; -extern uint32 VROM_size; - -static SFORMAT StateRegs[] = -{ - { &mode, 1, "MODE" }, - { vrc2_chr, 8, "VRCC" }, - { vrc2_prg, 2, "VRCP" }, - { &vrc2_mirr, 1, "VRCM" }, - { mmc3_regs, 10, "M3RG" }, - { &mmc3_ctrl, 1, "M3CT" }, - { &mmc3_mirr, 1, "M3MR" }, - { &IRQReload, 1, "IRQR" }, - { &IRQCount, 1, "IRQC" }, - { &IRQLatch, 1, "IRQL" }, - { &IRQa, 1, "IRQA" }, - { mmc1_regs, 4, "M1RG" }, - { &mmc1_buffer, 1, "M1BF" }, - { &mmc1_shift, 1, "M1MR" }, - { &submapper, 1, "SUBM" }, - { &game, 1, "GAME" }, - { 0 } +static SFORMAT stateRegs[] = { + { ®, 1, "MODE" }, + { &init, 1, "INIT" }, + { 0 }, }; -static void SyncPRG(void) { - uint8 mask = (submapper != 3) ? 0x3F : (game ? 0x0F : 0x1F); - uint8 outer = game ? (game + 1) * 0x10 : 0; - switch (mode & 3) { - case 0: - setprg8(0x8000, (outer & ~mask) | (vrc2_prg[0] & mask)); - setprg8(0xA000, (outer & ~mask) | (vrc2_prg[1] & mask)); - setprg8(0xC000, (outer & ~mask) | (~1 & mask)); - setprg8(0xE000, (outer & ~mask) | (~0 & mask)); - break; - case 1: - { - uint32 swap = (mmc3_ctrl >> 5) & 2; - setprg8(0x8000, (outer & ~mask) | (mmc3_regs[6 + swap] & mask)); - setprg8(0xA000, (outer & ~mask) | (mmc3_regs[7] & mask)); - setprg8(0xC000, (outer & ~mask) | (mmc3_regs[6 + (swap ^ 2)] & mask)); - setprg8(0xE000, (outer & ~mask) | (mmc3_regs[9] & mask)); - break; +static SFORMAT stateRegsMulti[] = { + { &game, 1, "GAME" }, + { 0 }, +}; + +static void sync (void) { + int prgAND, chrAND, prgOR, chrOR; + if (submapper == 3) { /* First game is 256K+256K, the others 128K+128K */ + prgAND = game? 0x0F: 0x1F; + chrAND = game? 0x7F: 0xFF; + prgOR = game <<4 &~prgAND; + chrOR = game <<7 &~chrAND; + } else { + prgAND = 0x3F; + chrAND = 0xFF; + prgOR = 0x00 &~prgAND; + chrOR = reg <<6 &0x100 &~chrAND; } - case 2: - case 3: - { - uint8 bank = mmc1_regs[3] & mask; - if (mmc1_regs[0] & 8) { - if (submapper == 2) - bank >>= 1; - if (mmc1_regs[0] & 4) { - setprg16(0x8000, bank); - setprg16(0xC000, 0x0F); - } else { - setprg16(0x8000, 0); - setprg16(0xC000, bank); - } - } else - setprg32(0x8000, ((outer & ~mask) >> 1) | (bank >> 1)); - } - break; + if (reg &0x02) { + prgAND >>= 1; + prgOR >>= 1; + chrAND >>= 2; + chrOR >>= 2; + MMC1_syncPRG(prgAND, prgOR); + MMC1_syncCHR(chrAND, chrOR); + MMC1_syncMirror(); + } else + if (reg &0x01) { + MMC3_syncPRG(prgAND, prgOR); + MMC3_syncCHR(chrAND, chrOR); + MMC3_syncMirror(); + } else { + VRC24_syncPRG(prgAND, prgOR); + VRC24_syncCHR(chrAND, chrOR); + VRC24_syncMirror(); } } -static void SyncCHR(void) { - uint32 mask = game ? 0x7F : 0xFF; - uint32 outer = game ? (game + 1) * 0x80 : 0; - uint32 base = (mode & 4) << 6; - switch (mode & 3) { - case 0: - setchr1(0x0000, ((outer | base) & ~mask) | (vrc2_chr[0] & mask)); - setchr1(0x0400, ((outer | base) & ~mask) | (vrc2_chr[1] & mask)); - setchr1(0x0800, ((outer | base) & ~mask) | (vrc2_chr[2] & mask)); - setchr1(0x0c00, ((outer | base) & ~mask) | (vrc2_chr[3] & mask)); - setchr1(0x1000, ((outer | base) & ~mask) | (vrc2_chr[4] & mask)); - setchr1(0x1400, ((outer | base) & ~mask) | (vrc2_chr[5] & mask)); - setchr1(0x1800, ((outer | base) & ~mask) | (vrc2_chr[6] & mask)); - setchr1(0x1c00, ((outer | base) & ~mask) | (vrc2_chr[7] & mask)); - break; - case 1: { - uint32 swap = (mmc3_ctrl & 0x80) << 5; - setchr1(0x0000 ^ swap, ((outer | base) & ~mask) | ((mmc3_regs[0] & 0xFE) & mask)); - setchr1(0x0400 ^ swap, ((outer | base) & ~mask) | ((mmc3_regs[0] | 1) & mask)); - setchr1(0x0800 ^ swap, ((outer | base) & ~mask) | ((mmc3_regs[1] & 0xFE) & mask)); - setchr1(0x0c00 ^ swap, ((outer | base) & ~mask) | ((mmc3_regs[1] | 1) & mask)); - setchr1(0x1000 ^ swap, ((outer | base) & ~mask) | (mmc3_regs[2] & mask)); - setchr1(0x1400 ^ swap, ((outer | base) & ~mask) | (mmc3_regs[3] & mask)); - setchr1(0x1800 ^ swap, ((outer | base) & ~mask) | (mmc3_regs[4] & mask)); - setchr1(0x1c00 ^ swap, ((outer | base) & ~mask) | (mmc3_regs[5] & mask)); - break; - } - case 2: - case 3: - if (mmc1_regs[0] & 0x10) { - setchr4(0x0000, (outer & ~mask) | (mmc1_regs[1] & mask)); - setchr4(0x1000, (outer & ~mask) | (mmc1_regs[2] & mask)); - } else - setchr8(((outer & ~mask) >> 1) | (mmc1_regs[1] & mask) >> 1); - break; - } +int Huang2_getPRGBank (uint8 bank) { + return MMC1_getPRGBank(bank) >>1; } -static void SyncMIR(void) { - switch (mode & 3) { - case 0: { - setmirror((vrc2_mirr & 1) ^ 1); - break; - } - case 1: { - setmirror((mmc3_mirr & 1) ^ 1); - break; - } - case 2: - case 3: { - switch (mmc1_regs[0] & 3) { - case 0: setmirror(MI_0); break; - case 1: setmirror(MI_1); break; - case 2: setmirror(MI_V); break; - case 3: setmirror(MI_H); break; - } - break; - } - } -} - -static void Sync(void) { - SyncPRG(); - SyncCHR(); - SyncMIR(); -} - -static DECLFW(UNLSL12ModeWrite) { - if (A & 0x100) { - mode = V; - if (A & 1) { /* hacky hacky, there are two configuration modes on SOMARI HUANG-1 PCBs - * Solder pads with P1/P2 shorted called SOMARI P, - * Solder pads with W1/W2 shorted called SOMARI W - * Both identical 3-in-1 but W wanted MMC1 registers - * to be reset when switch to MMC1 mode P one - doesn't - * There is issue with W version of Somari at starting copyrights - */ - mmc1_regs[0] = 0xc; - mmc1_regs[3] = 0; - mmc1_buffer = 0; - mmc1_shift = 0; - } - Sync(); - } -} - -static DECLFW(UNLSL12Write) { -/* FCEU_printf("%04X:%02X\n",A,V); */ - switch (mode & 3) { - case 0: { - if ((A >= 0xB000) && (A <= 0xE003)) { - int32 ind = ((((A & 2) | (A >> 10)) >> 1) + 2) & 7; - int32 sar = ((A & 1) << 2); - vrc2_chr[ind] = (vrc2_chr[ind] & (0xF0 >> sar)) | ((V & 0x0F) << sar); - SyncCHR(); - } else - switch (A & 0xF000) { - case 0x8000: vrc2_prg[0] = V; SyncPRG(); break; - case 0xA000: vrc2_prg[1] = V; SyncPRG(); break; - case 0x9000: vrc2_mirr = V; SyncMIR(); break; - } - break; - } - case 1: { - switch (A & 0xE001) { - case 0x8000: { - uint8 old_ctrl = mmc3_ctrl; - mmc3_ctrl = V; - if ((old_ctrl & 0x40) != (mmc3_ctrl & 0x40)) - SyncPRG(); - if ((old_ctrl & 0x80) != (mmc3_ctrl & 0x80)) - SyncCHR(); - break; - } - case 0x8001: - mmc3_regs[mmc3_ctrl & 7] = V; - if ((mmc3_ctrl & 7) < 6) - SyncCHR(); - else - SyncPRG(); - break; - case 0xA000: - mmc3_mirr = V; - SyncMIR(); - break; - case 0xC000: - IRQLatch = V; - break; - case 0xC001: - IRQReload = 1; - break; - case 0xE000: - X6502_IRQEnd(FCEU_IQEXT); - IRQa = 0; - break; - case 0xE001: - IRQa = 1; - break; - } - break; - } - case 2: - case 3: { - if (V & 0x80) { - mmc1_regs[0] |= 0xc; - mmc1_buffer = mmc1_shift = 0; - SyncPRG(); - } else { - uint8 n = (A >> 13) - 4; - mmc1_buffer |= (V & 1) << (mmc1_shift++); - if (mmc1_shift == 5) { - mmc1_regs[n] = mmc1_buffer; - mmc1_buffer = mmc1_shift = 0; - switch (n) { - case 0: SyncMIR(); break; - case 2: SyncCHR(); break; - case 3: - case 1: SyncPRG(); break; - } - } - } - break; - } - } -} - -static void UNLSL12HBIRQ(void) { - if ((mode & 3) == 1) { - int32 count = IRQCount; - if (!count || IRQReload) { - IRQCount = IRQLatch; - IRQReload = 0; - } else - IRQCount--; - if (!IRQCount) { - if (IRQa) - X6502_IRQBegin(FCEU_IQEXT); +static void applyMode (uint8 clear) { + PPU_hook = NULL; + MapIRQHook = NULL; + GameHBIRQHook = NULL; + if (reg &0x02) { + MMC1_activate(clear && init &1, sync, MMC1_TYPE_MMC1B, submapper == 2? Huang2_getPRGBank: NULL, NULL, NULL, NULL); + if (submapper != 1) MMC1_writeReg(0x8000, 0x80); + init &= ~1; + } else + if (reg &0x01) { + MMC3_activate(clear && init &2, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, NULL); + init &= ~2; + } else { + VRC2_activate(clear && init &4, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); + if (init &4) { /* The earlier version of Somari needs specific VRC2 CHR register initialization */ + VRC24_writeReg(0xB000, 0xFF); VRC24_writeReg(0xB001, 0xFF); VRC24_writeReg(0xB002, 0xFF); VRC24_writeReg(0xB003, 0xFF); + VRC24_writeReg(0xC000, 0xFF); VRC24_writeReg(0xC001, 0xFF); VRC24_writeReg(0xC002, 0xFF); VRC24_writeReg(0xC003, 0xFF); + VRC24_writeReg(0xD000, 0xFF); VRC24_writeReg(0xD001, 0xFF); VRC24_writeReg(0xD002, 0xFF); VRC24_writeReg(0xD003, 0xFF); + VRC24_writeReg(0xE000, 0xFF); VRC24_writeReg(0xE001, 0xFF); VRC24_writeReg(0xE002, 0xFF); VRC24_writeReg(0xE003, 0xFF); + init &= ~4; } } } -static void StateRestore(int version) { - Sync(); -} - -static void UNLSL12Reset(void) { - /* this is suppose to increment during power cycle */ - /* but we dont have a way to do that, so increment on reset instead. */ - if (submapper == 3) { - game = game + 1; - if (game > 4) - game = 0; +static DECLFW (writeReg) { + if (A &0x100) { + uint8 previousReg = reg; + reg = V; + if ((previousReg ^V) &3) + applyMode(1); + else + sync(); } - Sync(); } -static void UNLSL12Power(void) { - game = (submapper == 3) ? 4 : 0; - mode = 1; - vrc2_chr[0] = ~0; - vrc2_chr[1] = ~0; - vrc2_chr[2] = ~0; - vrc2_chr[3] = ~0; /* W conf. of Somari wanted CHR3 has to be set to BB bank (or similar), but doesn't do that directly */ - vrc2_chr[4] = 4; - vrc2_chr[5] = 5; - vrc2_chr[6] = 6; - vrc2_chr[7] = 7; - vrc2_prg[0] = 0; - vrc2_prg[1] = 1; - vrc2_mirr = 0; - mmc3_regs[0] = 0; - mmc3_regs[1] = 2; - mmc3_regs[2] = 4; - mmc3_regs[3] = 5; - mmc3_regs[4] = 6; - mmc3_regs[5] = 7; - mmc3_regs[6] = ~3; - mmc3_regs[7] = ~2; - mmc3_regs[8] = ~1; - mmc3_regs[9] = ~0; - mmc3_ctrl = mmc3_mirr = IRQCount = IRQLatch = IRQa = 0; - mmc1_regs[0] = 0xc; - mmc1_regs[1] = 0; - mmc1_regs[2] = 0; - mmc1_regs[3] = 0; - mmc1_buffer = 0; - mmc1_shift = 0; - Sync(); +static void reset (void) { + reg = 1; + init = 7; + if (++game == 1) ++game; /* First game is twice as large */ + if (game >= ROM_size /8) game = 0; + applyMode(1); +} + +static void power (void) { + reg = 1; + init = 7; + game = 0; SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x4100, 0x5FFF, UNLSL12ModeWrite); - SetWriteHandler(0x8000, 0xFFFF, UNLSL12Write); + SetWriteHandler(0x4020, 0x5FFF, writeReg); + applyMode(1); } -void UNLSL12_Init(CartInfo *info) { - info->Power = UNLSL12Power; - info->Reset = UNLSL12Reset; - GameHBIRQHook = UNLSL12HBIRQ; - GameStateRestore = StateRestore; - AddExState(&StateRegs, ~0, 0, 0); - submapper = info->submapper; - if (submapper == 0) { - /* PRG 128K and CHR 128K is Huang-2 (submapper 2) */ - if (ROM_size == 8 && VROM_size == 16) - submapper = 2; - } +static void restore (int version) { + applyMode(0); +} + +void UNLSL12_Init (CartInfo *info) { + submapper = info->submapper; + MMC1_addExState(); + MMC3_addExState(); + VRC24_addExState(); + info->Reset = reset; + info->Power = power; + GameStateRestore = restore; + AddExState(stateRegs, ~0, 0, 0); + if (submapper == 3) AddExState(stateRegsMulti, ~0, 0, 0); } diff --git a/src/boards/122.c b/src/boards/122.c new file mode 100644 index 0000000..9021045 --- /dev/null +++ b/src/boards/122.c @@ -0,0 +1,56 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[2]; + +static void sync () { + setprg32(0x8000, 0); + setchr4(0x0000, reg[0]); + setchr4(0x1000, reg[1]); +} + +static DECLFW (writeReg) { + reg[A &1] = V; + sync(); +} + +static void reset () { + reg[0] = reg[1] = 0; + sync(); +} + +static void power () { + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, writeReg); + reset(); +} + +static void stateRestore (int version) { + sync(); +} + +void Mapper122_Init (CartInfo *info) { + info->Reset = reset; + info->Power = power; + GameStateRestore = stateRestore; + AddExState(reg, 2, 0, "REGS"); +} diff --git a/src/boards/14.c b/src/boards/14.c new file mode 100644 index 0000000..6e223e2 --- /dev/null +++ b/src/boards/14.c @@ -0,0 +1,101 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_mmc3.h" +#include "asic_vrc2and4.h" + +static uint8 reg; +static uint8 init; /* Games switch between ASICs expecting registers to keep their value, so initialize each ASIC only on the first switch and use this bitfield to track it */ +static void applyMode (uint8); + +static SFORMAT StateRegs[] = { + { ®, 1, "MODE" }, + { &init, 1, "INIT" }, + { 0 }, +}; + +static void sync (void) { + if (reg &0x02) { + MMC3_syncPRG(0x3F, 0x00); + MMC3_syncCHR(0x1FF, 0x00); + MMC3_syncMirror(); + } else { + VRC24_syncPRG(0x3F, 0x00); + VRC24_syncCHR(0x1FF, 0x00); + VRC24_syncMirror(); + } +} + +int getCHRBank_MMC3 (uint8 bank) { + return MMC3_getCHRBank(bank) | reg <<(~bank &4? 5: ~bank &2? 3: 1) &0x100; +} + +int getCHRBank_VRC2 (uint8 bank) { + return VRC24_getCHRBank(bank) | reg <<(~bank &4? 5: ~bank &2? 3: 1) &0x100; +} + +static DECLFW (writeReg) { + uint8 previousReg = reg; + reg = V; + if ((previousReg ^V) &2) + applyMode(1); + else + sync(); +} + +static void applyMode (uint8 clear) { + PPU_hook = NULL; + MapIRQHook = NULL; + GameHBIRQHook = NULL; + if (reg &0x02) { + MMC3_activate(clear && init &1, sync, MMC3_TYPE_AX5202P, NULL, getCHRBank_MMC3, NULL, NULL); + init &= ~1; + } else { + VRC2_activate(clear && init &2, sync, 0x01, 0x02, NULL, getCHRBank_VRC2, NULL, NULL); + init &= ~2; + } + SetWriteHandler(0xA131, 0xA131, writeReg); +} + +static void reset (void) { + reg = 0; + init = 3; + applyMode(1); +} + +static void power (void) { + reg = 0; + init = 3; + applyMode(1); +} + +static void restore (int version) { + applyMode(0); +} + +void UNLSL1632_Init (CartInfo *info) { + MMC3_addExState(); + VRC24_addExState(); + info->Reset = reset; + info->Power = power; + GameStateRestore = restore; + AddExState(StateRegs, ~0, 0, 0); +} diff --git a/src/boards/178.c b/src/boards/178.c index 87187cc..60fedf8 100644 --- a/src/boards/178.c +++ b/src/boards/178.c @@ -27,7 +27,9 @@ #include "mapinc.h" +static uint8 submapper; static uint8 reg[4]; +static uint8 pad[2]; static uint8 *WRAM = NULL; static uint32 WRAMSIZE; @@ -79,6 +81,10 @@ static uint8 decode(uint8 code) { return (acc >> 8) & 0xff; } +static DECLFR(readPad) { + return CartBR(A &~3 | pad[1] &3); +} + static void M178Sync(void) { uint32 sbank = reg[1] & 0x7; uint32 bbank = reg[2]; @@ -100,6 +106,7 @@ static void M178Sync(void) { } setmirror((reg[0] & 1) ^ 1); + if (submapper == 3) SetReadHandler(0x8000, 0xffff, pad[0] &1? readPad: CartBR); } static void M551Sync(void) { @@ -152,6 +159,11 @@ static DECLFR(M178ReadSnd) { return X.DB; } +static DECLFW(writePad) { + pad[0] = V; + M178Sync(); +} + static void M551Power(void) { reg[0] = reg[1] = reg[2] = reg[3] = 0; M551Sync(); @@ -159,9 +171,9 @@ static void M551Power(void) { SetWriteHandler(0x4800, 0x4fff, M551Write); SetWriteHandler(0x5800, 0x5fff, M178WriteSnd); SetReadHandler(0x5800, 0x5fff, M178ReadSnd); + SetReadHandler(0x8000, 0xffff, CartBR); SetReadHandler(0x6000, 0x7fff, CartBR); SetWriteHandler(0x6000, 0x7fff, CartBW); - SetReadHandler(0x8000, 0xffff, CartBR); FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); } @@ -172,10 +184,15 @@ static void M178Power(void) { SetWriteHandler(0x4800, 0x4fff, M178Write); SetWriteHandler(0x5800, 0x5fff, M178WriteSnd); SetReadHandler(0x5800, 0x5fff, M178ReadSnd); - SetReadHandler(0x6000, 0x7fff, CartBR); - SetWriteHandler(0x6000, 0x7fff, CartBW); SetReadHandler(0x8000, 0xffff, CartBR); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + if (submapper == 3) + SetWriteHandler(0x6000, 0x7fff, writePad); + else { + SetReadHandler(0x6000, 0x7fff, CartBR); + SetWriteHandler(0x6000, 0x7fff, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + } + pad[0] = pad[1] = 0; } static void M551Reset(void) { @@ -189,6 +206,8 @@ static void M178Reset(void) /* Always reset to menu */ reg[0] = reg[1] = reg[2] = reg[3] = 0; M178Sync(); + pad[0] = 0; + pad[1]++; } static void M178SndClk(int a) @@ -217,6 +236,7 @@ static void M178StateRestore(int version) { } void Mapper178_Init(CartInfo *info) { + submapper = info->submapper; info->Power = M178Power; info->Reset = M178Reset; info->Close = M178Close; @@ -225,14 +245,18 @@ void Mapper178_Init(CartInfo *info) { jedi_table_init(); - WRAMSIZE = 32768; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; + if (submapper == 3) + AddExState(pad, 2, 0, "DIPS"); + else { + WRAMSIZE = 32768; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); } - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); AddExState(&StateRegs, ~0, 0, 0); diff --git a/src/boards/182.c b/src/boards/182.c new file mode 100644 index 0000000..c4edcf2 --- /dev/null +++ b/src/boards/182.c @@ -0,0 +1,75 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg[4]; + +static void sync () { + int prgAND = reg[1] &0x20? 0x1F: 0x0F; + int chrAND = reg[1] &0x40? 0xFF: 0x7F; + int prgOR = (reg[1] &0x02? 0x10: 0x00) | (reg[1] &0x10? 0x020: 0x00); + int chrOR = (reg[1] &0x02? 0x80: 0x00) | (reg[1] &0x10? 0x100: 0x00); + if (reg[0] &0x80) { + if (reg[0] &0x20) + setprg32(0x8000, reg[0] >>1); + else { + setprg16(0x8000, reg[0]); + setprg16(0xC000, reg[0]); + } + } else + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + if (~reg[1] &0x01) { + reg[A &3] = V; + sync(); + } +} + +static DECLFW (unscramble) { + static const uint16 lutAddress[8] = { 0xA001, 0xA000, 0x8000, 0xC000, 0x8001, 0xC001, 0xE000, 0xE001 }; /* i <5? 4-i: i */ + static const uint8 lutIndex[8] = { 0, 3, 1, 5, 6, 7, 2, 4 }; /* i <6? (i^3)-1: i */ + MMC3_writeReg(lutAddress[A >>12 &6 | A &1], (A &0xE001) == 0xA000? lutIndex[V &7]: V); +} + +static void reset () { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + MMC3_clear(); +} + +static void power () { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + MMC3_power(); + SetWriteHandler(0x8000, 0xFFFF, unscramble); +} + +void Mapper182_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(reg, 4, 0, "EXPR"); +} diff --git a/src/boards/183.c b/src/boards/183.c index 85a9822..ef21817 100644 --- a/src/boards/183.c +++ b/src/boards/183.c @@ -19,11 +19,11 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static uint8 prg; -static SFORMAT Mapper183_stateRegs[] ={ +static SFORMAT stateRegs[] ={ { &prg, 1, "PRG6" }, { 0 } }; @@ -35,20 +35,18 @@ static void sync () { VRC24_syncMirror(); } -DECLFW(Mapper183_writePRG) { +static DECLFW (writePRG) { prg =A &0xFF; - VRC24_Sync(); + sync(); } -void Mapper183_power(void) { +static void power(void) { prg =0; VRC24_power(); } void Mapper183_Init (CartInfo *info) { - VRC24_init(info, sync, 0x04, 0x08, 1, 1, 0); - VRC24_WRAMRead =CartBR; - VRC24_WRAMWrite =Mapper183_writePRG; - AddExState(Mapper183_stateRegs, ~0, 0, 0); - info->Power =Mapper183_power; + VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, CartBR, writePRG, NULL); + AddExState(stateRegs, ~0, 0, 0); + info->Power =power; } diff --git a/src/boards/213.c b/src/boards/213.c new file mode 100644 index 0000000..ac48393 --- /dev/null +++ b/src/boards/213.c @@ -0,0 +1,37 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_address &0x08) { + setprg16(0x8000, Latch_address >>1 &~1 | Latch_address &1); + setprg16(0xC000, Latch_address >>1 &~1 | Latch_address &1); + } else + setprg32(0x8000, Latch_address >>2); + setchr8(Latch_address >>1 &~1 | Latch_address &1); + setmirror(Latch_address &0x02? MI_H: MI_V); +} + +void Mapper213_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/21_22_23_25.c b/src/boards/21_22_23_25.c index da73aa8..ea66dc9 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 "cartram.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..38b8554 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; @@ -27,7 +27,7 @@ static uint8 counter1; static uint8 counter2; static uint8 prescaler; -static SFORMAT Mapper222_stateRegs[] ={ +static SFORMAT stateRegs[] = { { &clockMode, 1, "CLKM" }, { &pending, 1, "PEND" }, { &counter1, 1, "CNT1" }, @@ -42,39 +42,39 @@ static void sync () { VRC24_syncMirror(); } -DECLFW(Mapper222_nibblizeCHR) { +static DECLFW (nibblizeCHR) { if (~A &1) { VRC24_writeReg(A, V); VRC24_writeReg(A |1, V >>4); } } -DECLFW(Mapper222_writeIRQ) { +static DECLFW (writeIRQ) { switch(A &3) { - case 0: clockMode =0; + case 0: clockMode = 0; break; - case 1: pending =false; + case 1: pending = 0; if (!clockMode) { - counter1 =V &0xF; - counter2 =V >>4; + counter1 = V &0xF; + counter2 = V >>4; } break; - case 2: clockMode =1; + case 2: clockMode = 1; break; } } -void FP_FASTAPASS(1) Mapper222_cpuCycle(int a) { +static void FP_FASTAPASS(1) cpuCycle (int a) { while (a--) { - uint8 previousPrescaler =prescaler; + uint8 previousPrescaler = prescaler; if (pending) - prescaler =0; + prescaler = 0; else prescaler++; if (clockMode && ~previousPrescaler &0x40 && prescaler &0x40) { - if (++counter1 ==0xF && ++counter2 ==0xF) pending =1; - counter1 &=0xF; - counter2 &=0xF; + if (++counter1 == 0xF && ++counter2 == 0xF) pending = 1; + counter1 &= 0xF; + counter2 &= 0xF; } if (pending) X6502_IRQBegin(FCEU_IQEXT); @@ -83,16 +83,16 @@ void FP_FASTAPASS(1) Mapper222_cpuCycle(int a) { } } -void Mapper222_power(void) { - clockMode =pending =counter1 =counter2 =prescaler =0; +static void power (void) { + clockMode = pending = counter1 = counter2 = prescaler = 0; VRC24_power(); - SetWriteHandler(0xB000, 0xEFFF, Mapper222_nibblizeCHR); - SetWriteHandler(0xF000, 0xFFFF, Mapper222_writeIRQ); + SetWriteHandler(0xB000, 0xEFFF, nibblizeCHR); + SetWriteHandler(0xF000, 0xFFFF, writeIRQ); } void Mapper222_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0); - AddExState(Mapper222_stateRegs, ~0, 0, 0); - info->Power =Mapper222_power; - MapIRQHook =Mapper222_cpuCycle; + VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); + AddExState(stateRegs, ~0, 0, 0); + info->Power =power; + MapIRQHook = cpuCycle; } diff --git a/src/boards/239.c b/src/boards/239.c new file mode 100644 index 0000000..72e1192 --- /dev/null +++ b/src/boards/239.c @@ -0,0 +1,38 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_address &0x04) + setprg32(0x8000, Latch_address >>1); + else { + setprg16(0x8000, Latch_address); + setprg16(0xC000, Latch_address); + } + setchr8(Latch_address); + setmirror(Latch_address &0x10? MI_H: MI_V); +} + +void Mapper239_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/252_253.c b/src/boards/252_253.c index 06d3133..61e7116 100644 --- a/src/boards/252_253.c +++ b/src/boards/252_253.c @@ -19,17 +19,16 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" +#include "cartram.h" -static uint8 *CHRRAM; -static uint32 CHRRAMSize; static uint8 mask; static uint8 compare; extern uint32 RefreshAddr; static writefunc writePPU; -static SFORMAT stateRegs[] ={ +static SFORMAT stateRegs[] = { { &mask, 1, "CHRM" }, { &compare, 1, "CHRC" }, { 0 } @@ -39,65 +38,48 @@ 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) { +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); } -void Mapper252_power (void) { - mask =0xFE; - compare =0x06; +static void Mapper252_power (void) { + mask = 0xFE; + compare = 0x06; VRC24_power(); - writePPU =GetWriteHandler(0x2007); + writePPU = GetWriteHandler(0x2007); SetWriteHandler(0x2007, 0x2007, Mapper252_253_interceptPPUWrite); } -void Mapper253_power (void) { - mask =0xFE; /* There are two board revisions, the earlier one with a non-switchable mask/compare FE/04 and a later switchable one that starts with FC/28 */ - compare =0x04; +static void Mapper253_power (void) { + mask = 0xFE; /* There are two board revisions, the earlier one with a non-switchable mask/compare FE/04 and a later switchable one that starts with FC/28 */ + compare = 0x04; VRC24_power(); - writePPU =GetWriteHandler(0x2007); + writePPU = GetWriteHandler(0x2007); SetWriteHandler(0x2007, 0x2007, Mapper252_253_interceptPPUWrite); } -void Mapper252_253_close(void) { - if (CHRRAM) { - FCEU_gfree(CHRRAM); - CHRRAM =NULL; - } -} - void Mapper252_Init (CartInfo *info) { - VRC24_init(info, sync, 0x4, 0x8, 1, 1, 0); - info->Power =Mapper252_power; - info->Close =Mapper252_253_close; + VRC4_init(info, sync, 0x4, 0x8, 1, NULL, NULL, NULL, NULL, NULL); + CartRAM_init(info, 8, 2); + info->Power = Mapper252_power; AddExState(stateRegs, ~0, 0, 0); - - CHRRAMSize =info->iNES2? (info->CHRRamSize +info->CHRRamSaveSize): 2048; - CHRRAM =(uint8*)FCEU_gmalloc(CHRRAMSize); - AddExState(CHRRAM, CHRRAMSize, 0, "CRAM"); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1); } void Mapper253_Init (CartInfo *info) { - VRC24_init(info, sync, 0x4, 0x8, 1, 1, 0); - info->Power =Mapper253_power; - info->Close =Mapper252_253_close; + VRC4_init(info, sync, 0x4, 0x8, 1, NULL, NULL, NULL, NULL, NULL); + CartRAM_init(info, 8, 2); + info->Power = Mapper253_power; AddExState(stateRegs, ~0, 0, 0); - - CHRRAMSize =info->iNES2? (info->CHRRamSize +info->CHRRamSaveSize): 2048; - CHRRAM =(uint8*)FCEU_gmalloc(CHRRAMSize); - AddExState(CHRRAM, CHRRAMSize, 0, "CRAM"); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1); } diff --git a/src/boards/266.c b/src/boards/266.c index 64e405a..cc59614 100644 --- a/src/boards/266.c +++ b/src/boards/266.c @@ -19,11 +19,11 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static uint8 prg; -static SFORMAT UNLCITYFIGHT_stateRegs[] ={ +static SFORMAT stateRegs[] ={ { &prg, 1, "PRG8" }, { 0 } }; @@ -34,28 +34,27 @@ static void sync () { VRC24_syncMirror(); } -DECLFW(UNLCITYFIGHT_externalSelect) { +static DECLFW (externalSelect) { if (A &0x800) (GetWriteHandler(0x4011))(0x4011, V <<3 &0x78); else { prg =V >>2; - VRC24_Sync(); + sync(); } } -DECLFW(UNLCITYFIGHT_unscrambleAddress) { +static DECLFW (unscrambleAddress) { VRC24_writeReg(A &~0x6000 | A <<1 &0x4000 | A >>1 &0x2000, V); } -void UNLCITYFIGHT_power(void) { +static void power (void) { prg =0; VRC24_power(); - SetWriteHandler(0x8000, 0xFFFF, UNLCITYFIGHT_unscrambleAddress); + SetWriteHandler(0x8000, 0xFFFF, unscrambleAddress); } void UNLCITYFIGHT_Init (CartInfo *info) { - VRC24_init(info, sync, 0x04, 0x08, 1, 1, 0); - VRC24_ExternalSelect =UNLCITYFIGHT_externalSelect; - AddExState(UNLCITYFIGHT_stateRegs, ~0, 0, 0); - info->Power =UNLCITYFIGHT_power; + VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, NULL, NULL, externalSelect); + AddExState(stateRegs, ~0, 0, 0); + info->Power =power; } diff --git a/src/boards/273.c b/src/boards/273.c new file mode 100644 index 0000000..23df59a --- /dev/null +++ b/src/boards/273.c @@ -0,0 +1,83 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_vrc2and4.h" + +static uint8 irqEnabled; +static uint8 irqCounter; +static uint8 irqPrescaler; +static uint8 irqMask; + +static SFORMAT stateRegs[] ={ + { &irqEnabled, 1, "IRQE" }, + { &irqCounter, 1, "CNTR" }, + { &irqPrescaler, 1, "IRQP" }, + { &irqMask, 1, "IRQM" }, + { 0 } +}; + +static void sync () { + VRC24_syncPRG(0x01F, 0x000); + VRC24_syncCHR(0x1FF, 0x000); + VRC24_syncMirror(); +} + +static DECLFW (writeIRQ) { + switch(A &8) { + case 0: + irqCounter = V; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 8: + irqEnabled = V; + if (~irqEnabled &1) { + irqPrescaler = 0; + irqMask = 0x7F; + X6502_IRQEnd(FCEU_IQEXT); + } + break; + } +} + +static void FP_FASTAPASS(1) cpuCycle (int a) { + while (a--) { + if (irqEnabled &1 && !(++irqPrescaler &irqMask)) { + irqMask = 0xFF; + if (!++irqCounter) + X6502_IRQBegin(FCEU_IQEXT); + else + X6502_IRQEnd(FCEU_IQEXT); + } + } +} + +static void power (void) { + irqEnabled = irqCounter = irqPrescaler = irqMask = 0; + VRC24_power(); + SetWriteHandler(0xF000, 0xFFFF, writeIRQ); +} + +void Mapper273_Init (CartInfo *info) { + VRC2_init(info, sync, 0x04, 0x08, NULL, NULL, NULL, NULL); + AddExState(stateRegs, ~0, 0, 0); + info->Power = power; + MapIRQHook = cpuCycle; +} diff --git a/src/boards/280.c b/src/boards/280.c index 07deac1..9241cb7 100644 --- a/src/boards/280.c +++ b/src/boards/280.c @@ -21,8 +21,9 @@ #include "mapinc.h" static uint16 latchAddr; -static uint8 latchData; -static uint8 mode; +static uint8 latchData; +static uint8 mode; +static uint8 submapper; static SFORMAT StateRegs[] = { { &latchAddr, 2 | FCEUSTATE_RLSB, "LATC" }, @@ -33,8 +34,14 @@ static SFORMAT StateRegs[] = { static void Sync(void) { if (mode &1) { - setprg16(0x8000, 0x20 | latchData &0x07); - setprg16(0xC000, 0x27); + if (submapper == 1) { + setprg16(0x8000, latchAddr >>2 &7 |0x20); + setprg16(0xC000, 0x27); + } else { + setprg16(0x8000, 0x20 | latchData &0x07); + setprg16(0xC000, 0x27); + } + setmirror(MI_V); } else { if (latchAddr &0x01) setprg32(0x8000, latchAddr >>3 &0x0F); @@ -43,10 +50,10 @@ static void Sync(void) { setprg16(0xC000, latchAddr >>2 &0x1F); } if (~latchAddr &0x80) setprg16(0xC000, 0); + setmirror(latchAddr &0x02? MI_H: MI_V); } SetupCartCHRMapping(0, CHRptr[0], 0x2000, ~mode &0x01 && latchAddr &0x80? 0: 1); setchr8(0); - setmirror(latchAddr &0x02? MI_H: MI_V); } static DECLFW(M280Write) { @@ -76,6 +83,7 @@ static void StateRestore(int version) { } void Mapper280_Init(CartInfo *info) { + submapper = info->submapper; info->Power = M280Power; info->Reset = M280Reset; GameStateRestore = StateRestore; diff --git a/src/boards/285.c b/src/boards/285.c new file mode 100644 index 0000000..8a10f35 --- /dev/null +++ b/src/boards/285.c @@ -0,0 +1,78 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static uint8 pad; + +static void sync_submapper0 () { + if (Latch_data &0x40) + setprg32(0x8000, Latch_data >>1); + else { + setprg16(0x8000, Latch_data); + setprg16(0xC000, Latch_data |7); + } + setchr8(0); + if (Latch_data &0x80) + setmirror(Latch_data &0x20? MI_1: MI_0); + else + setmirror(Latch_data &0x20? MI_H: MI_V); +} + +static void sync_submapper1 () { + if (Latch_data &0x40) + setprg32(0x8000, Latch_data >>1 &0x03 | Latch_data >>2 &~0x03); + else { + setprg16(0x8000, Latch_data >>1 &~0x07 | Latch_data &0x07); + setprg16(0xC000, Latch_data >>1 | 0x07); + } + setchr8(0); + if (Latch_data &0x80) + setmirror(Latch_data &0x20? MI_1: MI_0); + else + setmirror(Latch_data &0x08? MI_H: MI_V); +} + +static DECLFR (readPad) { + if (A &0x80) return pad >= 20? (4 | pad % 20): 0; else + if (A &0x40) return pad >= 16? (4 | pad % 16): 0; else + if (A &0x20) return pad >= 12? (4 | pad % 12): 0; else + if (A &0x10) return pad >= 8? (4 | pad % 8): 0; else + return pad >= 8? 0: pad &7; +} + +static void power () { + pad = 0; + Latch_power(); + SetReadHandler(0x5000, 0x5FFF, readPad); +} + +static void reset () { + pad = ++pad %24; + Latch_clear(); +} + +void Mapper285_Init (CartInfo *info) { + Latch_init(info, info->submapper ==1? sync_submapper1: sync_submapper0, 0x8000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/boards/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..1e15832 100644 --- a/src/boards/308.c +++ b/src/boards/308.c @@ -19,13 +19,13 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static uint8 irqEnabled; static uint16 irqCounterLow; static uint8 irqCounterHigh; -static SFORMAT UNLTH21311_stateRegs[] ={ +static SFORMAT stateRegs[] ={ { &irqEnabled, 1, "IRQE" }, { &irqCounterLow, 2 | FCEUSTATE_RLSB, "CNTL" }, { &irqCounterHigh, 1, "CNTH" }, @@ -38,7 +38,7 @@ static void sync () { VRC24_syncMirror(); } -DECLFW(UNLTH21311_writeIRQ) { +static DECLFW (writeIRQ) { switch(A &3) { case 0: X6502_IRQEnd(FCEU_IQEXT); irqEnabled =0; @@ -51,22 +51,22 @@ DECLFW(UNLTH21311_writeIRQ) { } } -void FP_FASTAPASS(1) UNLTH21311_cpuCycle(int a) { +static void FP_FASTAPASS(1) cpuCycle (int a) { while (a--) if (irqEnabled) { if ((++irqCounterLow &4095) ==2048) irqCounterHigh--; if (!irqCounterHigh && (irqCounterLow &4095) <2048) X6502_IRQBegin(FCEU_IQEXT); } } -void UNLTH21311_power(void) { +static void power (void) { irqEnabled =irqCounterLow =irqCounterHigh =0; VRC24_power(); - SetWriteHandler(0xF000, 0xFFFF, UNLTH21311_writeIRQ); + SetWriteHandler(0xF000, 0xFFFF, writeIRQ); } void UNLTH21311_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0); - AddExState(UNLTH21311_stateRegs, ~0, 0, 0); - info->Power =UNLTH21311_power; - MapIRQHook =UNLTH21311_cpuCycle; + VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); + AddExState(stateRegs, ~0, 0, 0); + info->Power =power; + MapIRQHook =cpuCycle; } diff --git a/src/boards/321.c b/src/boards/321.c new file mode 100644 index 0000000..8b5f0a0 --- /dev/null +++ b/src/boards/321.c @@ -0,0 +1,57 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync () { + if (reg &0x08) + setprg32(0x8000, reg &0x04 | reg >>4 &0x03); + else + MMC3_syncPRG(0x0F, reg <<2 &~0x0F); + MMC3_syncCHR(0x7F, reg <<5 &~0x7F); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + reg = V; + sync(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +void Mapper321_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/351.c b/src/boards/351.c index be65643..24de00d 100644 --- a/src/boards/351.c +++ b/src/boards/351.c @@ -19,322 +19,160 @@ */ #include "mapinc.h" +#include "asic_mmc1.h" +#include "asic_mmc3.h" +#include "asic_vrc2and4.h" static uint8 reg[4], dip; -static uint8 MMC1_reg[4], MMC1_shift, MMC1_count, MMC1_filter; -static uint8 MMC3_reg[8], MMC3_index, MMC3_mirroring, MMC3_wram, MMC3_reload, MMC3_count, MMC3_irq; -static uint8 VRC4_prg[2]; -static uint8 VRC4_mirroring; -static uint8 VRC4_misc; -static uint16 VRC4_chr[8]; -static uint8 VRCIRQ_latch; -static uint8 VRCIRQ_mode; -static uint8 VRCIRQ_count; -static signed short int VRCIRQ_cycles; -static uint8 *CHRRAM =NULL; -static uint8 *PRGCHR =NULL; +static uint8 *CHRRAM = NULL; +static uint8 *PRGCHR = NULL; +static int prgMask_CHRROM; /* PRG-ROM bank mask when CHR-ROM is active (outside of PRG address space */ +static int prgMask_CHRRAM; /* PRG-ROM bank mask when CHR-RAM is active (CHR-ROM becomes part of PRG address space) */ static SFORMAT stateRegs[] = { - { reg, 4, "REGS" }, - { &dip, 1, "DIPS" }, - { MMC1_reg, 4, "MMC1" }, - { &MMC1_shift, 1, "M1SH" }, - { &MMC1_count, 1, "M1CN" }, - { &MMC1_filter, 1, "M1FI" }, - { MMC3_reg, 1, "MMC3" }, - { &MMC3_index, 1, "M3IX" }, - { &MMC3_mirroring, 1, "M3MI" }, - { &MMC3_wram, 1, "M3WR" }, - { &MMC3_reload, 1, "M3RL" }, - { &MMC3_count, 1, "M3CN" }, - { &MMC3_irq, 1, "M3IQ" }, - { VRC4_prg, 2, "V4PR" }, - { &VRC4_mirroring, 1, "V4MI" }, - { &VRC4_misc, 1, "V4MS" }, - { VRC4_chr, 16, "V4CH" }, - { &VRCIRQ_latch, 1, "VILA" }, - { &VRCIRQ_mode, 1, "VIMO" }, - { &VRCIRQ_count, 1, "VICO" }, - { &VRCIRQ_cycles, 2, "VICY" }, + { reg, 4, "REGS" }, + { &dip, 1, "DIPS" }, { 0 } }; - static void sync () { - int chrAND; - int chrOR; - int prgAND =reg[2] &0x04? 0x0F: 0x1F; - int prgOR =reg[1] >>1; - int chip =reg[2] &0x01 && CHRRAM? 0x10: 0x00; - + int prgAND = reg[2] &0x10? 0x00: reg[2] &0x04? 0x0F: 0x1F; /* No inner bank in NROM mode, 128K or 256K for others */ + int chrAND = reg[2] &0x40? 0x00: reg[2] &0x20? 0x7F: reg[2] &0x10? 0x1F: 0xFF; /* No inner bank in (C)NROM mode, 128K or 256K for others */ + int prgOR = reg[1] >>1 &(reg[2] &0x01 && CHRRAM? prgMask_CHRRAM: prgMask_CHRROM) &~prgAND; + int chrOR = reg[0] <<1 &~chrAND; + if (reg[2] &0x10) { /* NROM mode */ if (reg[2] &0x08) { /* NROM-64 */ - setprg8r(chip, 0x8000, prgOR); - setprg8r(chip, 0xA000, prgOR); - setprg8r(chip, 0xC000, prgOR); - setprg8r(chip, 0xE000, prgOR); + setprg8(0x8000, prgOR); + setprg8(0xA000, prgOR); + setprg8(0xC000, prgOR); + setprg8(0xE000, prgOR); } else if (reg[2] &0x04) { /* NROM-128 */ - setprg16r(chip, 0x8000, prgOR >>1); - setprg16r(chip, 0xC000, prgOR >>1); + setprg16(0x8000, prgOR >>1); + setprg16(0xC000, prgOR >>1); } else /* NROM-256 */ - setprg32r(chip, 0x8000, prgOR >>2); + setprg32(0x8000, prgOR >>2); } else - if (~reg[0] &0x02) { /* MMC3 mode */ - setprg8r(chip, 0x8000 ^(MMC3_index <<8 &0x4000), MMC3_reg[6] &prgAND | prgOR &~prgAND); - setprg8r(chip, 0xA000, MMC3_reg[7] &prgAND | prgOR &~prgAND); - setprg8r(chip, 0xC000 ^(MMC3_index <<8 &0x4000), 0xFE &prgAND | prgOR &~prgAND); - setprg8r(chip, 0xE000, 0xFF &prgAND | prgOR &~prgAND); - } else - if (reg[0] &0x01) { /* VRC4 mode */ - setprg8r(chip, 0x8000 ^(VRC4_misc <<13 &0x4000), VRC4_prg[0] &prgAND | prgOR &~prgAND); - setprg8r(chip, 0xA000, VRC4_prg[1] &prgAND | prgOR &~prgAND); - setprg8r(chip, 0xC000 ^(VRC4_misc <<13 &0x4000), 0xFE &prgAND | prgOR &~prgAND); - setprg8r(chip, 0xE000, 0xFF &prgAND | prgOR &~prgAND); - } else { /* MMC1 mode */ - prgAND >>=1; - prgOR >>=1; - if (MMC1_reg[0] &0x8) { /* 16 KiB mode */ - if (MMC1_reg[0] &0x04) { /* OR logic */ - setprg16r(chip, 0x8000, MMC1_reg[3] &prgAND | prgOR &~prgAND); - setprg16r(chip, 0xC000, 0xFF &prgAND | prgOR &~prgAND); - } else { /* AND logic */ - setprg16r(chip, 0x8000, 0x00 &prgAND | prgOR &~prgAND); - setprg16r(chip, 0xC000, MMC1_reg[3] &prgAND | prgOR &~prgAND); - } - } else - setprg32(0x8000, (MMC1_reg[3] &prgAND | prgOR &~prgAND) >>1); - } - - chrAND =reg[2] &0x10 && ~reg[2] &0x20? 0x1F: reg[2] &0x20? 0x7F: 0xFF; - chrOR =reg[0] <<1; - if (reg[2] &0x01) /* CHR RAM mode */ + if (~reg[0] &0x02) + MMC3_syncPRG(prgAND, prgOR); + else + if (reg[0] &0x01) + VRC24_syncPRG(prgAND, prgOR); + else + MMC1_syncPRG(prgAND >>1, prgOR >>1); + + if (reg[2] &0x01 && CHRRAM) setchr8r(0x10, 0); else - if (reg[2] &0x40) /* CNROM mode */ + if (reg[2] &0x40) setchr8(chrOR >>3); else - if (~reg[0] &0x02) { /* MMC3 mode */ - setchr1(0x0000 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] &0xFE)&chrAND | chrOR &~chrAND); - setchr1(0x0400 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] |0x01)&chrAND | chrOR &~chrAND); - setchr1(0x0800 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] &0xFE)&chrAND | chrOR &~chrAND); - setchr1(0x0C00 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] |0x01)&chrAND | chrOR &~chrAND); - setchr1(0x1000 ^(MMC3_index <<5 &0x1000), MMC3_reg[2] &chrAND | chrOR &~chrAND); - setchr1(0x1400 ^(MMC3_index <<5 &0x1000), MMC3_reg[3] &chrAND | chrOR &~chrAND); - setchr1(0x1800 ^(MMC3_index <<5 &0x1000), MMC3_reg[4] &chrAND | chrOR &~chrAND); - setchr1(0x1C00 ^(MMC3_index <<5 &0x1000), MMC3_reg[5] &chrAND | chrOR &~chrAND); - } else - if (reg[0] &0x01) { /* VRC4 mode */ - setchr1(0x0000, VRC4_chr[0] &chrAND | chrOR &~chrAND); - setchr1(0x0400, VRC4_chr[1] &chrAND | chrOR &~chrAND); - setchr1(0x0800, VRC4_chr[2] &chrAND | chrOR &~chrAND); - setchr1(0x0C00, VRC4_chr[3] &chrAND | chrOR &~chrAND); - setchr1(0x1000, VRC4_chr[4] &chrAND | chrOR &~chrAND); - setchr1(0x1400, VRC4_chr[5] &chrAND | chrOR &~chrAND); - setchr1(0x1800, VRC4_chr[6] &chrAND | chrOR &~chrAND); - setchr1(0x1C00, VRC4_chr[7] &chrAND | chrOR &~chrAND); - } else { /* MMC1 mode */ - chrAND >>=2; - chrOR >>=2; - if (MMC1_reg[0] &0x10) { /* 4 KiB mode */ - setchr4(0x0000, MMC1_reg[1] &chrAND | chrOR &~chrAND); - setchr4(0x1000, MMC1_reg[2] &chrAND | chrOR &~chrAND); - } else /* 8 KiB mode */ - setchr8((MMC1_reg[1] &chrAND |chrOR &~chrAND) >>1); - } - - if (~reg[0] &0x02) /* MMC3 mode */ - setmirror(MMC3_mirroring &1 ^1); + if (~reg[0] &0x02) + MMC3_syncCHR(chrAND, chrOR); else - if ( reg[0] &0x01) /* VRC4 mode */ - setmirror(VRC4_mirroring &3 ^(VRC4_mirroring &2? 0: 1)); - else /* MMC1 mode */ - setmirror(MMC1_reg[0] &3 ^3); + if (reg[0] &0x01) + VRC24_syncCHR(chrAND, chrOR); + else + MMC1_syncCHR(chrAND >>2, chrOR >>2); + + if (~reg[0] &0x02) + MMC3_syncMirror(); + else + if (reg[0] &0x01) + VRC24_syncMirror(); + else + MMC1_syncMirror(); } -static DECLFW(writeMMC3) { - switch(A &0xE001) { - case 0x8000: MMC3_index =V; sync(); break; - case 0x8001: MMC3_reg[MMC3_index &7] =V; sync(); break; - case 0xA000: MMC3_mirroring =V; sync(); break; - case 0xA001: MMC3_wram =V; sync(); break; - case 0xC000: MMC3_reload =V; break; - case 0xC001: MMC3_count =0; break; - case 0xE000: MMC3_irq =0; X6502_IRQEnd(FCEU_IQEXT); break; - case 0xE001: MMC3_irq =1; break; - } +DECLFW (VRC24_trapWriteReg) { /* When A11 is set, VRC4's A0 and A1 are swapped */ + if (A &0x800) A = A &~0xF | A >>1 &0x5 | A <<1 &0xA; + VRC24_writeReg(A, V); } -static DECLFW(writeMMC1) { - if (V &0x80) { - MMC1_shift =MMC1_count =0; - MMC1_reg[0] |=0x0C; - sync(); +static void applyMode (uint8 clear) { + PPU_hook = NULL; + MapIRQHook = NULL; + GameHBIRQHook = NULL; + if (~reg[0] &0x02) + MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, NULL); + else + if (reg[0] &0x01) { + if (reg[2] &0x04) + VRC4_activate(clear, sync, 0x05, 0x0A, 1, NULL, NULL, NULL, NULL, NULL); + else + VRC4_activate(clear, sync, 0x02, 0x04, 1, NULL, NULL, NULL, NULL, NULL); + SetWriteHandler(0x8000, 0xFFFF, VRC24_trapWriteReg); } else - if (!MMC1_filter) { - MMC1_shift |=(V &1) <>13 &3] =MMC1_shift; - MMC1_count =0; - MMC1_shift =0; - sync(); - } - } - MMC1_filter =2; + MMC1_activate(clear, sync, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL); } -static DECLFW(writeVRC4) { - uint8 index; - if (~reg[2] &4) A =A &0xF800 | A >>1 &0x3FF; /* A2,A1 -> A1,A0 if 5002.2=1 */ - A |=A >>2 &3; /* A3,A2 -> A1,A0 */ - if (A &0x800) A =A >>1 &1 | A <<1 &2 | A &~3; /* A8==1 => Swap A1,A0 */ - switch (A &0xF000) { - case 0x8000: case 0xA000: - VRC4_prg[A >>13 &1] =V; - sync(); - break; - case 0x9000: - if (~A &2) - VRC4_mirroring =V; - else - if (~A &1) - VRC4_misc =V; - sync(); - break; - case 0xF000: - switch (A &3) { - case 0: VRCIRQ_latch =VRCIRQ_latch &0xF0 | V &0x0F; break; - case 1: VRCIRQ_latch =VRCIRQ_latch &0x0F | V <<4; break; - case 2: VRCIRQ_mode =V; - if (VRCIRQ_mode &0x02) { - VRCIRQ_count =VRCIRQ_latch; - VRCIRQ_cycles =341; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 3: VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02; - X6502_IRQEnd(FCEU_IQEXT); - break; - } - break; - default: - index =(A -0xB000) >>11 &~1 | A >>1 &1; - if (A &1) - VRC4_chr[index] =VRC4_chr[index] & 0x0F | V <<4; - else - VRC4_chr[index] =VRC4_chr[index] &~0x0F | V &0x0F; - sync(); - break; - } -} - -static void FP_FASTAPASS(1) cpuCycle(int a) { - if ((reg[0] &3) ==3) while (a--) { /* VRC4 mode */ - if (VRCIRQ_mode &0x02 && (VRCIRQ_mode &0x04 || (VRCIRQ_cycles -=3) <=0)) { - if (~VRCIRQ_mode &0x04) VRCIRQ_cycles +=341; - if (!++VRCIRQ_count) { - VRCIRQ_count =VRCIRQ_latch; - X6502_IRQBegin(FCEU_IQEXT); - } - } - } - if (MMC1_filter) MMC1_filter--; -} - -static void horizontalBlanking(void) { - if (~reg[0] &2) { /* MMC3 mode */ - MMC3_count =!MMC3_count? MMC3_reload: --MMC3_count; - if (!MMC3_count && MMC3_irq) X6502_IRQBegin(FCEU_IQEXT); - } -} - -static void applyMode() { - switch (reg[0] &3) { - case 0: - case 1: SetWriteHandler(0x8000, 0xFFFF, writeMMC3); break; - case 2: SetWriteHandler(0x8000, 0xFFFF, writeMMC1); break; - case 3: SetWriteHandler(0x8000, 0xFFFF, writeVRC4); break; - } -} - -static void Mapper351_restore (int version) { - applyMode(); +static void restore (int version) { + applyMode(0); sync(); } -static DECLFR(readDIP) { +static DECLFR (readDIP) { return dip; } -static DECLFW(writeReg) { - uint8 previousMode =reg[0] &3; - reg[A &3] =V; - if ((reg[0] &3) !=previousMode) applyMode(); - sync(); +static DECLFW (writeReg) { + reg[A &3] = V; + applyMode(A == 2); } -static DECLFW(writeFDSMirroring) { - MMC3_mirroring =V >>3 &1; - sync(); +static DECLFW (writeFDSMirroring) { + MMC3_writeReg(0xA000, V >>3 &1); } -static void Mapper351_power(void) { - int i; - for (i =0; i <4; i++) reg[i] =0; - for (i =0; i <4; i++) MMC1_reg[i] =0; - for (i =0; i <8; i++) MMC3_reg[i] =0; - for (i =0; i <2; i++) VRC4_prg[i] =0; - for (i =0; i <8; i++) VRC4_chr[i] =0; - MMC1_shift =MMC1_count =MMC1_filter =0; - MMC1_reg[0] =0x0C; - MMC3_index =MMC3_mirroring =MMC3_wram =MMC3_reload =MMC3_count =MMC3_irq =0; - VRC4_mirroring =VRC4_misc =VRCIRQ_latch =VRCIRQ_mode =VRCIRQ_count =VRCIRQ_cycles =0; - dip =0; - - SetReadHandler(0x6000, 0xFFFF, CartBR); +static void power (void) { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + dip = 0; SetReadHandler(0x5000, 0x5FFF, readDIP); + SetReadHandler(0x6000, 0xFFFF, CartBR); SetWriteHandler(0x5000, 0x5FFF, writeReg); SetWriteHandler(0x4025, 0x4025, writeFDSMirroring); - applyMode(); - sync(); + applyMode(1); } -static void Mapper351_reset (void) { - int i; - for (i =0; i <4; i++) reg[i] =0; +static void reset (void) { + reg[0] = reg[1] = reg[2] = reg[3] = 0; dip++; - applyMode(); - sync(); + applyMode(1); } -static void Mapper351_close(void) { +static void close (void) { if (CHRRAM) FCEU_gfree(CHRRAM); if (PRGCHR) FCEU_gfree(PRGCHR); - CHRRAM =NULL; - PRGCHR =NULL; + CHRRAM = NULL; + PRGCHR = NULL; } void Mapper351_Init (CartInfo *info) { - int CHRRAMSIZE =info->CHRRamSize + info->CHRRamSaveSize; - - info->Reset = Mapper351_reset; - info->Power = Mapper351_power; - info->Close = Mapper351_close; - MapIRQHook = cpuCycle; - GameHBIRQHook = horizontalBlanking; - GameStateRestore = Mapper351_restore; + int CHRRAMSIZE = info->CHRRamSize + info->CHRRamSaveSize; + MMC1_addExState(); + MMC3_addExState(); + VRC24_addExState(); + info->Reset = reset; + info->Power = power; + info->Close = close; + GameStateRestore = restore; AddExState(stateRegs, ~0, 0, 0); - + + /* When CHR-RAM is enabled, CHR-ROM becomes part of PRG-ROM address space. */ + prgMask_CHRROM = prgMask_CHRRAM = PRGsize[0] /8192 -1; if (CHRRAMSIZE) { - CHRRAM =(uint8 *)FCEU_gmalloc(CHRRAMSIZE); + uint8* newROM; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); - - /* This crazy thing can map CHR-ROM into CPU address space. Allocate a combined PRG+CHR address space and treat it a second "chip". */ - PRGCHR =(uint8 *)FCEU_gmalloc(PRGsize[0] +CHRsize[0]); - memcpy(PRGCHR, PRGptr[0], PRGsize[0]); - memcpy(PRGCHR +PRGsize[0], CHRptr[0], CHRsize[0]); - SetupCartPRGMapping(0x10, PRGCHR, PRGsize[0] +CHRsize[0], 0); + prgMask_CHRRAM = (PRGsize[0] +CHRsize[0]) /8192 -1; + newROM = (uint8*)FCEU_gmalloc(PRGsize[0] +CHRsize[0]); + memcpy(newROM, ROM, info->PRGRomSize); + memcpy(newROM +PRGsize[0], VROM, info->CHRRomSize); + FCEU_gfree(ROM); + ROM = newROM; + SetupCartPRGMapping(0, ROM, PRGsize[0] +CHRsize[0], 0); } } diff --git a/src/boards/352.c b/src/boards/352.c new file mode 100644 index 0000000..10c6986 --- /dev/null +++ b/src/boards/352.c @@ -0,0 +1,50 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 game; + +static void sync () { + setprg32(0x8000, game); + setchr8(game); +} + +static void power() { + SetReadHandler(0x6000, 0xFFFF, CartBR); + game = 0; + sync(); +} + +static void reset() { + if (++game >= ROM_size /2) game = 0; + sync(); +} + +static void stateRestore(int version) { + sync(); +} + +void Mapper352_Init (CartInfo *info) { + info->Power = power; + info->Reset = reset; + GameStateRestore = stateRestore; + AddExState(&game, 1, 0, "GAME"); +} diff --git a/src/boards/356.c b/src/boards/356.c index 666b7aa..60e8e5a 100644 --- a/src/boards/356.c +++ b/src/boards/356.c @@ -3,10 +3,10 @@ * Copyright notice for this file: * Copyright (C) 2020 * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -15,90 +15,44 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* NES 2.0 Mapper 356 - J.Y. Company's 7-in-1 Rockman (JY-208) - * All registers work as INES Mapper 045, except $6000 sequential register 2 (third write): + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * */ #include "mapinc.h" -#include "mmc3.h" +#include "asic_tc3294.h" -static uint8* CHRRAM = NULL; -static uint32 CHRRAMSIZE = 0; +static uint8 *CHRRAM = NULL; +static uint32 CHRRAMSize; -static void M356CW(uint32 A, uint8 V) { - if (EXPREGS[2] & 0x20) { - uint8 NV = V; - if (EXPREGS[2] & 8) - NV &= (1 << ((EXPREGS[2] & 7) + 1)) - 1; - else - if (EXPREGS[2]) - NV &= 0; /* hack ;( don't know exactly how it should be */ - NV |= EXPREGS[0] | ((EXPREGS[2] & 0xF0) << 4); - setchr1(A, NV); - } else - setchr8r(0x10, 0); -} - -static void M356PW(uint32 A, uint8 V) { - uint8 MV = V & ((EXPREGS[3] & 0x3F) ^ 0x3F); - MV |= EXPREGS[1]; - if (UNIFchrrama) - MV |= ((EXPREGS[2] & 0x40) << 2); - setprg8(A, MV); -} - -static void M356MW(uint8 V) { - if (EXPREGS[2] & 0x40) - SetupCartMirroring(4, 1, CHRRAM); +static void sync () { + TC3294_syncPRG(0xFF, 0x00); + if (TC3294_reg[2] &0x20) + TC3294_syncCHR(0x1FF, 0x00); else - setmirror((V & 1) ^ 1); + setchr8r(0x10, 0); + if (TC3294_reg[2] &0x40) { + setntamem(CHRptr[0x10] +0x0000, 1, 0); + setntamem(CHRptr[0x10] +0x0400, 1, 1); + setntamem(CHRptr[0x10] +0x0800, 1, 2); + setntamem(CHRptr[0x10] +0x0C00, 1, 3); + } else + TC3294_syncMirror(); } -static DECLFW(M356Write) { - if (!(EXPREGS[3] & 0x40)) { - EXPREGS[EXPREGS[4]] = V; - EXPREGS[4] = (EXPREGS[4] + 1) & 3; - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); +static void close (void) { + if (CHRRAM) { + FCEU_gfree(CHRRAM); + CHRRAM =NULL; } } -static void M356Close(void) { - GenMMC3Close(); - if (CHRRAM) - FCEU_free(CHRRAM); - CHRRAM = NULL; -} - -static void M356Reset(void) { - EXPREGS[0] = EXPREGS[1] = EXPREGS[3] = EXPREGS[4] = 0; - EXPREGS[2] = 0x0F; - MMC3RegReset(); -} - -static void M356Power(void) { - EXPREGS[4] = 0; - EXPREGS[0] = EXPREGS[1] = EXPREGS[3] = EXPREGS[4] = 0; - EXPREGS[2] = 0x0F; - GenMMC3Power(); - SetWriteHandler(0x6000, 0x7FFF, M356Write); -} - -void Mapper356_Init(CartInfo* info) { - GenMMC3_Init(info, 128, 128, 0, 0); - cwrap = M356CW; - pwrap = M356PW; - mwrap = M356MW; - info->Reset = M356Reset; - info->Power = M356Power; - info->Close = M356Close; - AddExState(EXPREGS, 5, 0, "EXPR"); - - CHRRAMSIZE = 8192; - CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +void Mapper356_Init (CartInfo *info) { + TC3294_init(info, sync); + info->Close = close; + CHRRAMSize = 8192; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize); + AddExState(CHRRAM, CHRRAMSize, 0, "CRAM"); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1); } diff --git a/src/boards/361.c b/src/boards/361.c new file mode 100644 index 0000000..6d0f6f9 --- /dev/null +++ b/src/boards/361.c @@ -0,0 +1,54 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync () { + MMC3_syncPRG(0x0F, reg &~0x0F); + MMC3_syncCHR(0x7F, reg <<3 &~0x7F); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + reg = V; + sync(); +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +void Mapper361_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/362.c b/src/boards/362.c index 6a77c4e..e6d75b7 100644 --- a/src/boards/362.c +++ b/src/boards/362.c @@ -19,11 +19,11 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static uint8 game; -static SFORMAT Mapper362_stateRegs[] ={ +static SFORMAT stateRegs[] ={ { &game, 1, "GAME" }, { 0 } }; @@ -34,27 +34,27 @@ 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(); } } -void Mapper362_power(void) { +static void power (void) { game =0; VRC24_power(); } -void Mapper362_reset(void) { +static void reset (void) { game ^=1; - VRC24_Sync(); + VRC24_clear(); } void Mapper362_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 1, 0, 0); - info->Power =Mapper362_power; + VRC4_init(info, sync, 0x01, 0x02, 0, NULL, NULL, NULL, NULL, NULL); + info->Power = power; if (PRGsize[0] >512*1024) { - info->Reset =Mapper362_reset; - AddExState(Mapper362_stateRegs, ~0, 0, 0); + info->Reset = reset; + AddExState(stateRegs, ~0, 0, 0); } } diff --git a/src/boards/363.c b/src/boards/363.c new file mode 100644 index 0000000..2916e41 --- /dev/null +++ b/src/boards/363.c @@ -0,0 +1,39 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + setprg16(0x8000, Latch_address <<3 | Latch_data &0x07); + setprg16(0xC000, Latch_address <<3 | 0x07); + setchr8(0); + setmirror(Latch_address &0x20? MI_H: MI_V); +} + +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { + if (!(~Latch_address &0x10 && *newAddress &0x10)) *newAddress = Latch_address; /* Address bits only latched on a rising edge of A4 */ + *newValue &= romValue; /* AND-type bus conflicts */ +} + +void Mapper363_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); + info->Reset = Latch_clear; +} diff --git a/src/boards/366.c b/src/boards/366.c new file mode 100644 index 0000000..4307bd1 --- /dev/null +++ b/src/boards/366.c @@ -0,0 +1,59 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" +#include "cartram.h" + +static uint8 reg; + +static void sync () { + MMC3_syncWRAM(0); + MMC3_syncPRG(0x0F, reg &~0x0F); + MMC3_syncCHR(0x7F, reg <<3 &~0x7F); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + if (~reg &0x80) { + reg = A &0xFF; + sync(); + } +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +void Mapper366_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + WRAM_init(info, 8); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/378.c b/src/boards/378.c new file mode 100644 index 0000000..8e595d0 --- /dev/null +++ b/src/boards/378.c @@ -0,0 +1,39 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_data &0x20) { + setprg16(0x8000, 0x10 | Latch_data <<1 &0x0E | Latch_data >>3 &0x01); + setprg16(0xC000, 0x10 | Latch_data <<1 &0x0E | 0x07); + setmirror(Latch_data &0x04? MI_H: MI_V); + } else { + setprg32(0x8000, Latch_data &0x07); + setmirror(Latch_data &0x10? MI_1: MI_0); + } + setchr8(0); +} + +void Mapper378_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/379.c b/src/boards/379.c new file mode 100644 index 0000000..3e798bf --- /dev/null +++ b/src/boards/379.c @@ -0,0 +1,32 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + setprg32(0x8000, Latch_data &0x03); + setchr8(Latch_data >>2); +} + +void Mapper379_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/380.c b/src/boards/380.c index f14ac63..2b53fb1 100644 --- a/src/boards/380.c +++ b/src/boards/380.c @@ -57,7 +57,7 @@ static void Sync(void) static DECLFR(M380Read) { if (latche & 0x100 && !isKN35A) - return CartBR(A | dipswitch); + return CartBR(A &~0x0F | dipswitch); return CartBR(A); } diff --git a/src/boards/384.c b/src/boards/384.c index 9333622..02d7803 100644 --- a/src/boards/384.c +++ b/src/boards/384.c @@ -19,11 +19,12 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" +#include "cartram.h" static uint8 reg; -static SFORMAT Mapper384_stateRegs[] ={ +static SFORMAT stateRegs[] ={ { ®, 1, "EXP0" }, { 0 } }; @@ -35,28 +36,28 @@ static void sync () { VRC24_syncWRAM(0); } -DECLFW(Mapper384_writeReg) { +static DECLFW (writeReg) { if (A &0x800 && ~reg &0x08) { reg =V; - VRC24_Sync(); + sync(); } CartBW(A, V); } -void Mapper384_power(void) { +static void power (void) { reg =0; VRC24_power(); } -void Mapper384_reset(void) { +static void reset (void) { reg =0; - VRC24_Sync(); -} + VRC24_clear(); +} void Mapper384_Init (CartInfo *info) { - VRC24_init(info, sync, 0x04, 0x08, 1, 0, 2); - VRC24_WRAMWrite =Mapper384_writeReg; - info->Power =Mapper384_power; - info->Reset =Mapper384_reset; - AddExState(Mapper384_stateRegs, ~0, 0, 0); + VRC4_init(info, sync, 0x04, 0x08, 0, NULL, NULL, NULL, writeReg, NULL); + WRAM_init(info, 2); + info->Power =power; + info->Reset =reset; + AddExState(stateRegs, ~0, 0, 0); } diff --git a/src/boards/396.c b/src/boards/396.c index a31aee1..4c4d105 100644 --- a/src/boards/396.c +++ b/src/boards/396.c @@ -1,7 +1,7 @@ -/* FCEUmm - NES/Famicom Emulator +/* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2022 + * Copyright (C) 2025 NewRisingSun * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,58 +16,56 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 396 - BMC-830752C - * 1995 Super 8-in-1 (JY-050 rev0) - * Super 8-in-1 Gold Card Series (JY-085) - * Super 8-in-1 Gold Card Series (JY-086) - * 2-in-1 (GN-51) */ #include "mapinc.h" +static uint8 submapper; static uint8 reg[2]; -static void Sync (void) { - setprg16(0x8000, reg[1] << 3 | reg[0] & 7); - setprg16(0xC000, reg[1] << 3 | 7); +static void sync () { + setprg16(0x8000, reg[0] <<3 | reg[1] &0x07); + setprg16(0xC000, reg[0] <<3 | 0x07); setchr8(0); - setmirror(reg[1] & 0x60 ? 0 : 1); + switch(submapper) { + case 1: /* J.Y. YY850437C */ + setmirror(reg[0] &0x40? MI_H: MI_V); + break; + case 2: /* Realtec GN-51 */ + case 3: /* Realtec 8030 */ + setmirror(reg[0] &0x20? MI_H: MI_V); + break; + default: + setmirror(reg[0] &0x60? MI_H: MI_V); + break; + } } -static DECLFW(M396WriteInnerBank) { - reg[0] = V; - Sync(); +static DECLFW (writeReg) { + reg[(A &0xE000) == 0xA000? 0: 1] = V; + sync(); } -static DECLFW(M396WriteOuterBank) { - reg[1] = V; - Sync(); +static DECLFW (writeReg_submapper3) { + reg[A >>14 &1] = V; + sync(); } -static void M396Reset(void) { - reg[0] = 0x00; - reg[1] = 0x00; - Sync(); +static void power () { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, submapper == 3? writeReg_submapper3: writeReg); + reg[0] = reg[1] = 0; + sync(); } -static void StateRestore(int version) { - Sync(); +static void stateRestore (int version) { + sync(); } -static void M396Power(void) { - reg[0] = 0x00; - reg[1] = 0x00; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0x9FFF, M396WriteInnerBank); - SetWriteHandler(0xA000, 0xBFFF, M396WriteOuterBank); - SetWriteHandler(0xC000, 0xFFFF, M396WriteInnerBank); -} - -void Mapper396_Init(CartInfo *info) { - info->Power = M396Power; - info->Reset = M396Reset; - GameStateRestore = StateRestore; +void Mapper396_Init (CartInfo *info) { + submapper = info->submapper; + info->Power = power; + info->Reset = submapper == 3? sync: power; + GameStateRestore = stateRestore; AddExState(reg, 2, 0, "REGS"); } diff --git a/src/boards/398.c b/src/boards/398.c index b0e69e7..ce1e630 100644 --- a/src/boards/398.c +++ b/src/boards/398.c @@ -19,19 +19,19 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static uint8 reg; -static SFORMAT Mapper398_stateRegs[] ={ +static SFORMAT stateRegs[] ={ { ®, 1, "EXP0" }, { 0 } }; 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); @@ -39,26 +39,25 @@ static void sync () { VRC24_syncMirror(); } -DECLFW(Mapper398_writeReg) { +static DECLFW (writeReg) { reg =A &0xFF; - VRC24_Sync(); VRC24_writeReg(A, V); } -void Mapper398_power(void) { - reg =0xC0; +static void power (void) { + reg = 0xC0; VRC24_power(); - SetWriteHandler(0x8000, 0xFFFF, Mapper398_writeReg); + SetWriteHandler(0x8000, 0xFFFF, writeReg); } -void Mapper398_reset(void) { - reg =0xC0; - VRC24_Sync(); +static void reset (void) { + reg = 0xC0; + VRC24_clear(); } void Mapper398_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 1, 1, 0); - info->Power =Mapper398_power; - info->Reset =Mapper398_reset; - AddExState(Mapper398_stateRegs, ~0, 0, 0); + VRC4_init(info, sync, 0x01, 0x02, 1, NULL, NULL, NULL, NULL, NULL); + info->Power = power; + info->Reset = reset; + AddExState(stateRegs, ~0, 0, 0); } diff --git a/src/boards/400.c b/src/boards/400.c new file mode 100644 index 0000000..3965439 --- /dev/null +++ b/src/boards/400.c @@ -0,0 +1,58 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static uint8 reg[4]; + +static void sync () { + setprg16(0x8000, reg[2] &~0x07 | Latch_data &0x07); + setprg16(0xC000, reg[3] &~0x07 | 0x07); + setchr8(Latch_data >>5); + setmirror(reg[3] &0x20? MI_H: MI_V); +} + +static DECLFW (writeReg) { + if (!(A &0x7FF)) { /* Exclude 8 Bit Xmas 2008's writes to second APU (also at 7001-7015) */ + reg[A >>11 &3] = V; + sync(); + } +} + +static void power () { + reg[0] = reg[1] = reg[2] = 0; + reg[3] = 0x80; + Latch_power(); + SetWriteHandler(0x6000, 0x7FFF, writeReg); +} + +static void reset () { + reg[0] = reg[1] = reg[2] = 0; + reg[3] = 0x80; + Latch_clear(); +} + +void Mapper400_Init (CartInfo *info) { + Latch_init(info, sync, 0xC000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; + AddExState(reg, 4, 0, "REGS"); +} diff --git a/src/boards/418.c b/src/boards/418.c new file mode 100644 index 0000000..26a5996 --- /dev/null +++ b/src/boards/418.c @@ -0,0 +1,34 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_n118.h" + +static void sync () { + N118_syncPRG(0x0F, 0x00); + setchr8(0); + setmirror(N118_getCHRBank(7) &0x01? MI_H: MI_V); +} + +void Mapper418_Init (CartInfo *info) { + N118_init(info, sync, NULL, NULL); +} diff --git a/src/boards/432.c b/src/boards/432.c index e006fc9..b93fe3c 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; + MMC3_clear(); } -void Mapper432_Init(CartInfo *info) { +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/445.c b/src/boards/445.c index 19980d8..0c5a77e 100644 --- a/src/boards/445.c +++ b/src/boards/445.c @@ -19,242 +19,100 @@ */ #include "mapinc.h" +#include "asic_latch.h" +#include "asic_mmc3.h" +#include "asic_vrc2and4.h" -static uint8 reg[5], dip; /* Fourth register is the CNROM latch */ -static uint8 MMC3_reg[8], MMC3_index, MMC3_mirroring, MMC3_wram, MMC3_reload, MMC3_count, MMC3_irq; -static uint8 VRC4_prg[2]; -static uint8 VRC4_mirroring; -static uint8 VRC4_misc; -static uint16 VRC4_chr[8]; -static uint8 VRCIRQ_latch; -static uint8 VRCIRQ_mode; -static uint8 VRCIRQ_count; -static signed short int VRCIRQ_cycles; -static uint8 *PRGCHR =NULL; +static uint8 reg[4]; +static uint8 dip; static SFORMAT stateRegs[] = { - { reg, 5, "REGS" }, - { &dip, 1, "DIPS" }, - { MMC3_reg, 1, "MMC3" }, - { &MMC3_index, 1, "M3IX" }, - { &MMC3_mirroring, 1, "M3MI" }, - { &MMC3_wram, 1, "M3WR" }, - { &MMC3_reload, 1, "M3RL" }, - { &MMC3_count, 1, "M3CN" }, - { &MMC3_irq, 1, "M3IQ" }, - { VRC4_prg, 2, "V4PR" }, - { &VRC4_mirroring, 1, "V4MI" }, - { &VRC4_misc, 1, "V4MS" }, - { VRC4_chr, 16, "V4CH" }, - { &VRCIRQ_latch, 1, "VILA" }, - { &VRCIRQ_mode, 1, "VIMO" }, - { &VRCIRQ_count, 1, "VICO" }, - { &VRCIRQ_cycles, 2, "VICY" }, + { reg, 4, "REGS" }, + { &dip, 1, "DIPS" }, { 0 } }; - static void sync () { - int chrAND; - int chrOR; - /*/ 5003.0-2: PRG size (1 MiB->8 KiB, although 1 MiB and 512 KiB are not connected and so function as 256 KiB) and mode (>=64 KiB: MMC3, <64 KiB: NROM-256/128/64) */ - int prgAND =0x7F >>(reg[2] &7) &0x1F; + int prgAND = 0x7F >>(reg[2] &7) &0x1F; /* 5003.0-2: PRG size (1 MiB->8 KiB, although 1 MiB and 512 KiB are not connected and so function as 256 KiB) and mode (>=64 KiB: MMC3, <64 KiB: NROM-256/128/64) */ + int chrAND = 0x3FF >>(reg[2] >>3 &7) &0xFF; /* 5003.3-5: CHR size (1 MiB->8 KiB, though 1 MiB and 512 KiB are not reachable with inner bank registers and so function as 256 KiB) and mode (>=64 KiB: MMC3, <64 KiB: (C)NROM-256/128/64) */ + int prgOR = reg[0] &~prgAND; + int chrOR = reg[1] <<3 &~chrAND; + if (prgAND &0x04) { - if (reg[3] &0x10) { - setprg8(0x8000 ^(VRC4_misc <<13 &0x4000), VRC4_prg[0] &prgAND | reg[0] &~prgAND); - setprg8(0xA000, VRC4_prg[1] &prgAND | reg[0] &~prgAND); - setprg8(0xC000 ^(VRC4_misc <<13 &0x4000), 0xFE &prgAND | reg[0] &~prgAND); - setprg8(0xE000, 0xFF &prgAND | reg[0] &~prgAND); - } else { - setprg8(0x8000 ^(MMC3_index <<8 &0x4000), MMC3_reg[6] &prgAND | reg[0] &~prgAND); - setprg8(0xA000, MMC3_reg[7] &prgAND | reg[0] &~prgAND); - setprg8(0xC000 ^(MMC3_index <<8 &0x4000), 0xFE &prgAND | reg[0] &~prgAND); - setprg8(0xE000, 0xFF &prgAND | reg[0] &~prgAND); - } + if (reg[3] &0x10) + VRC24_syncPRG(prgAND, prgOR); + else + MMC3_syncPRG(prgAND, prgOR); } else { - setprg8(0x8000, 0 &prgAND | reg[0] &~prgAND); - setprg8(0xA000, 1 &prgAND | reg[0] &~prgAND); - setprg8(0xC000, 2 &prgAND | reg[0] &~prgAND); - setprg8(0xE000, 3 &prgAND | reg[0] &~prgAND); + setprg8(0x8000, 0 &prgAND | prgOR); + setprg8(0xA000, 1 &prgAND | prgOR); + setprg8(0xC000, 2 &prgAND | prgOR); + setprg8(0xE000, 3 &prgAND | prgOR); } - - /* // 5003.3-5: CHR size (1 MiB->8 KiB, though 1 MiB and 512 KiB are not reachable with inner bank registers and so function as 256 KiB) and mode (>=64 KiB: MMC3, <64 KiB: (C)NROM-256/128/64) */ - chrAND =0x3FF >>(reg[2] >>3 &7) &0xFF; if (chrAND &0x20) { - if (reg[3] &0x10) { - setchr1(0x0000, VRC4_chr[0] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x0400, VRC4_chr[1] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x0800, VRC4_chr[2] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x0C00, VRC4_chr[3] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x1000, VRC4_chr[4] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x1400, VRC4_chr[5] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x1800, VRC4_chr[6] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x1C00, VRC4_chr[7] &chrAND | (reg[1] <<3) &~chrAND); - } else { - setchr1(0x0000 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] &0xFE)&chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x0400 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] |0x01)&chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x0800 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] &0xFE)&chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x0C00 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] |0x01)&chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x1000 ^(MMC3_index <<5 &0x1000), MMC3_reg[2] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x1400 ^(MMC3_index <<5 &0x1000), MMC3_reg[3] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x1800 ^(MMC3_index <<5 &0x1000), MMC3_reg[4] &chrAND | (reg[1] <<3) &~chrAND); - setchr1(0x1C00 ^(MMC3_index <<5 &0x1000), MMC3_reg[5] &chrAND | (reg[1] <<3) &~chrAND); - } + if (reg[3] &0x10) + VRC24_syncCHR(chrAND, chrOR); + else + MMC3_syncCHR(chrAND, chrOR); } else { - chrAND >>=3; - setchr8(reg[4] &chrAND | reg[1] &~chrAND); + chrAND >>= 3; + chrOR >>= 3; + setchr8(Latch_data &chrAND | chrOR); } - if (reg[3] &0x10) - setmirror(VRC4_mirroring &3 ^(VRC4_mirroring &2? 0: 1)); + VRC24_syncMirror(); else - setmirror(MMC3_mirroring &1 ^1); - - SetReadHandler(0x8000, 0xFFFF, reg[0] &0xC0 && (reg[0] &0xC0) ==dip? NULL: CartBR); + MMC3_syncMirror(); + SetReadHandler(0x8000, 0xFFFF, reg[0] &0xC0 && (reg[0] &0xC0) == dip? NULL: CartBR); } -static DECLFW(writeCNROM) { - reg[4] =V; - sync(); -} - -static DECLFW(writeMMC3) { - switch(A &0xE001) { - case 0x8000: MMC3_index =V; sync(); break; - case 0x8001: MMC3_reg[MMC3_index &7] =V; sync(); break; - case 0xA000: MMC3_mirroring =V; sync(); break; - case 0xA001: MMC3_wram =V; sync(); break; - case 0xC000: MMC3_reload =V; break; - case 0xC001: MMC3_count =0; break; - case 0xE000: MMC3_irq =0; X6502_IRQEnd(FCEU_IQEXT); break; - case 0xE001: MMC3_irq =1; break; - } -} - -static DECLFW(writeVRC4) { - uint8 index; - if (reg[3] &1) - A =(A &0xA? 1: 0) | (A &0x5? 2: 0) | A &0xF000; +static void applyMode (uint8 clear) { + if ((reg[2] >>3 &7) >= 5) + Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); else - A =(A &0x5? 1: 0) | (A &0xA? 2: 0) | A &0xF000; - switch (A &0xF000) { - case 0x8000: case 0xA000: - VRC4_prg[A >>13 &1] =V; - sync(); - break; - case 0x9000: - if (~A &2) - VRC4_mirroring =V; + if (reg[3] &0x10) { + if (reg[3] &0x01) + VRC4_activate(clear, sync, 0x0A, 0x05, 1, NULL, NULL, NULL, NULL, NULL); else - if (~A &1) - VRC4_misc =V; - sync(); - break; - case 0xF000: - switch (A &3) { - case 0: VRCIRQ_latch =VRCIRQ_latch &0xF0 | V &0x0F; break; - case 1: VRCIRQ_latch =VRCIRQ_latch &0x0F | V <<4; break; - case 2: VRCIRQ_mode =V; - if (VRCIRQ_mode &0x02) { - VRCIRQ_count =VRCIRQ_latch; - VRCIRQ_cycles =341; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 3: VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02; - X6502_IRQEnd(FCEU_IQEXT); - break; - } - break; - default: - index =(A -0xB000) >>11 &~1 | A >>1 &1; - if (A &1) - VRC4_chr[index] =VRC4_chr[index] & 0x0F | V <<4; - else - VRC4_chr[index] =VRC4_chr[index] &~0x0F | V &0x0F; - sync(); - break; - } -} - -static void FP_FASTAPASS(1) cpuCycle(int a) { - if ((reg[0] &3) ==3) while (a--) { /* VRC4 mode */ - if (VRCIRQ_mode &0x02 && (VRCIRQ_mode &0x04 || (VRCIRQ_cycles -=3) <=0)) { - if (~VRCIRQ_mode &0x04) VRCIRQ_cycles +=341; - if (!++VRCIRQ_count) { - VRCIRQ_count =VRCIRQ_latch; - X6502_IRQBegin(FCEU_IQEXT); - } - } - } -} - -static void horizontalBlanking(void) { - if (~reg[0] &2) { /* MMC3 mode */ - MMC3_count =!MMC3_count? MMC3_reload: --MMC3_count; - if (!MMC3_count && MMC3_irq) X6502_IRQBegin(FCEU_IQEXT); - } -} - -static void applyMode() { - if ((reg[2] >>3 &7) >=5) - SetWriteHandler(0x8000, 0xFFFF, writeCNROM); - else - if (reg[3] &0x10) - SetWriteHandler(0x8000, 0xFFFF, writeVRC4); - else - SetWriteHandler(0x8000, 0xFFFF, writeMMC3); + VRC4_activate(clear, sync, 0x05, 0x0A, 1, NULL, NULL, NULL, NULL, NULL); + } else + MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, NULL); } static void Mapper445_restore (int version) { - applyMode(); + applyMode(0); sync(); } -static DECLFW(writeReg) { +static DECLFW (writeReg) { if (~reg[3] &0x20) { - reg[A &3] =V; - if ((A &3) ==3) applyMode(); + reg[A &3] = V; + if ((A &3) == 3) applyMode(1); sync(); } } static void Mapper445_power(void) { - int i; - for (i =0; i <4; i++) reg[i] =0; - for (i =0; i <8; i++) MMC3_reg[i] =0; - for (i =0; i <2; i++) VRC4_prg[i] =0; - for (i =0; i <8; i++) VRC4_chr[i] =0; - MMC3_index =MMC3_mirroring =MMC3_wram =MMC3_reload =MMC3_count =MMC3_irq =0; - VRC4_mirroring =VRC4_misc =VRCIRQ_latch =VRCIRQ_mode =VRCIRQ_count =VRCIRQ_cycles =0; + reg[0] = reg[1] = reg[2] = reg[3] = 0; dip =0; - SetReadHandler(0x6000, 0xFFFF, CartBR); SetWriteHandler(0x5000, 0x5FFF, writeReg); - applyMode(); - sync(); + applyMode(1); } static void Mapper445_reset (void) { - int i; - for (i =0; i <5; i++) reg[i] =0; - dip +=0x40; - applyMode(); - sync(); -} - -static void Mapper445_close(void) { - if (PRGCHR) FCEU_gfree(PRGCHR); - PRGCHR =NULL; + reg[0] = reg[1] = reg[2] = reg[3] = 0; + dip += 0x40; + applyMode(1); } void Mapper445_Init (CartInfo *info) { + Latch_addExState(); + MMC3_addExState(); + VRC24_addExState(); info->Reset = Mapper445_reset; info->Power = Mapper445_power; - info->Close = Mapper445_close; - MapIRQHook = cpuCycle; - GameHBIRQHook = horizontalBlanking; GameStateRestore = Mapper445_restore; - AddExState(stateRegs, ~0, 0, 0); + AddExState(stateRegs, ~0, 0, 0); } diff --git a/src/boards/446.c b/src/boards/446.c new file mode 100644 index 0000000..f2eaf91 --- /dev/null +++ b/src/boards/446.c @@ -0,0 +1,422 @@ +/* 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_mmc2and4.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 "cartram.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); + MMC24_syncCHR(chrAND, chrOR &~chrAND); + MMC24_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_writeReg(0xA000, reg[4] &0x04? 0: 1); + break; + case 0x10E: case 0x20E: /* MMC3 with single-screen mirroring. 239-in-1's Goal! Two has a screen where MMC3 scanline counter emulation fails. */ + mapperSync = sync_TxSROM; + 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; + MMC24_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(); + MMC24_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..a5d23cd 100644 --- a/src/boards/447.c +++ b/src/boards/447.c @@ -19,12 +19,13 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" +#include "cartram.h" static uint8 reg; static uint8 dip; -static SFORMAT Mapper447_stateRegs[] ={ +static SFORMAT stateRegs[] = { { ®, 1, "EXP0" }, { &dip, 1, "DIPS" }, { 0 } @@ -37,7 +38,7 @@ static void sync () { VRC24_syncWRAM(0); } -static int Mapper447_getPRGBank(int bank) { +static int getPRGBank (uint8 bank) { if (reg &4) { if (~reg &2) return VRC24_getPRGBank(bank &1) &~2 | bank &2; @@ -47,36 +48,35 @@ static int Mapper447_getPRGBank(int bank) { return VRC24_getPRGBank(bank); } -DECLFR(Mapper447_readPRG) { +static DECLFR (readPRG) { return CartBR(reg &8? (A &~3 | dip &3): A); } -DECLFW(Mapper447_writeReg) { - if (VRC24_misc &1 && ~reg &1) { - reg =A &0xFF; - VRC24_Sync(); +static DECLFW (writeReg) { + if (~reg &1) { + reg = A &0xFF; + sync(); } CartBW(A, V); } -void Mapper447_power(void) { - reg =0; - dip =0; +static void power (void) { + reg = 0; + dip = 0; VRC24_power(); - SetReadHandler(0x8000, 0xFFFF, Mapper447_readPRG); + SetReadHandler(0x8000, 0xFFFF, readPRG); } -void Mapper447_reset(void) { - reg =0; +static void reset (void) { + reg = 0; dip++; - 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; - info->Power =Mapper447_power; - info->Reset =Mapper447_reset; - AddExState(Mapper447_stateRegs, ~0, 0, 0); + VRC4_init(info, sync, 0x04, 0x08, 0, getPRGBank, NULL, NULL, writeReg, NULL ); + WRAM_init(info, 2); + info->Power = power; + info->Reset = reset; + AddExState(stateRegs, ~0, 0, 0); } diff --git a/src/boards/448.c b/src/boards/448.c index 4b4c850..04576ee 100644 --- a/src/boards/448.c +++ b/src/boards/448.c @@ -19,59 +19,58 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" +#include "cartram.h" static uint8 reg; -static SFORMAT Mapper448_stateRegs[] ={ +static SFORMAT stateRegs[] ={ { ®, 1, "EXP0" }, { 0 } }; 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(); } setchr8(0); } -DECLFW(Mapper448_writeReg) { - if (VRC24_misc &1) { - reg =A &0xFF; - VRC24_Sync(); - } +static DECLFW (writeReg) { + reg =A &0xFF; + sync(); CartBW(A, V); } -DECLFW(Mapper448_writePRG) { +static DECLFW (writePRG) { VRC24_writeReg(reg &8? 0x8000: A, V); } -void Mapper448_power(void) { +static void power (void) { reg =0; VRC24_power(); - SetWriteHandler(0x8000, 0xFFFF, Mapper448_writePRG); + SetWriteHandler(0x8000, 0xFFFF, writePRG); } -void Mapper448_reset(void) { +static void reset (void) { reg =0; - VRC24_Sync(); -} + VRC24_clear(); +} void Mapper448_Init (CartInfo *info) { - VRC24_init(info, sync, 0x04, 0x08, 1, 0, 2); - VRC24_WRAMWrite =Mapper448_writeReg; - info->Power =Mapper448_power; - info->Reset =Mapper448_reset; - AddExState(Mapper448_stateRegs, ~0, 0, 0); + VRC4_init(info, sync, 0x04, 0x08, 0, NULL, NULL, NULL, writeReg, NULL); + WRAM_init(info, 2); + info->Power =power; + info->Reset =reset; + AddExState(stateRegs, ~0, 0, 0); } diff --git a/src/boards/449.c b/src/boards/449.c index 72e4b4c..c1fea0a 100644 --- a/src/boards/449.c +++ b/src/boards/449.c @@ -1,7 +1,7 @@ -/* FCEUmm - NES/Famicom Emulator +/* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2022 + * Copyright (C) 2025 NewRisingSun * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,88 +19,70 @@ */ #include "mapinc.h" +#include "asic_latch.h" -static uint16 latchAddr; -static uint8 latchData; -static uint8 dipswitch; -static uint8 dipselect; +uint8 submapper; +uint8 pad; +uint8 padSelect; -static SFORMAT StateRegs[] = -{ - { &latchAddr, 2, "ADDR" }, - { &latchData, 1, "DATA" }, - { &latchData, 1, "DIPS" }, - { &dipselect, 1, "DSEL" }, - { 0 } -}; - -static void Mapper449_Sync(void) -{ - int prg =latchAddr >>2 &0x1F | latchAddr >>3 &0x20; - if (~latchAddr &0x080) - { - setprg16(0x8000, prg); - setprg16(0xC000, prg |7); - } - else - { - if (latchAddr &0x001) - { - setprg32(0x8000, prg >>1); - } - else - { - setprg16(0x8000, prg); - setprg16(0xC000, prg); - } - } - setchr8(latchData); - setmirror(latchAddr &0x002? MI_H: MI_V); +static DECLFR (readPad_submapper0) { + return CartBR(A &~0xF | pad &0xF); } -static DECLFR(Mapper449_Read) -{ - if (dipselect) - return dipswitch &0x3; - else - if (latchAddr &0x200) - return CartBR(A | dipswitch &0xF); - else - return CartBR(A); +static DECLFR (readPad_submapper1) { + return pad; } -static DECLFW(Mapper449_WriteDIPSelect) -{ - dipselect =V &1; +static DECLFR (readPad_submapper2) { + return CartBR(A &~0x3 | pad &0x3); } -static DECLFW(Mapper449_WriteLatch) -{ - latchData =V; - latchAddr =A &0xFFFF; - Mapper449_Sync(); +static void sync () { + int prg = Latch_address >>2 &0x1F | Latch_address >>3 &0x20 | Latch_address >>4 &0x40; + if (Latch_address &0x080) { + if (Latch_address &0x001) + setprg32(0x8000, prg >>1); + else { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } + setmirror(Latch_data &0x10? MI_1: MI_0); + } else { + setprg16(0x8000, prg); + setprg16(0xC000, prg | 7); + } + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], submapper == 0 && Latch_address &0x80? 0: 1); + setchr8(Latch_data); + setmirror(Latch_address &0x002? MI_H: MI_V); + SetReadHandler(0x8000, 0xFFFF, submapper == 0 && Latch_address &0x200? readPad_submapper0: submapper == 2 && padSelect &1? readPad_submapper2: CartBR); } -static void Mapper449_Reset(void) -{ - dipswitch++; - latchAddr =latchData =0; - Mapper449_Sync(); +static DECLFW (writePad_submapper2) { + padSelect = V; + sync(); } -static void Mapper449_Power(void) -{ - dipselect =dipswitch =latchAddr =latchData =0; - Mapper449_Sync(); - SetWriteHandler(0x6000, 0x7FFF, Mapper449_WriteDIPSelect); - SetWriteHandler(0x8000, 0xFFFF, Mapper449_WriteLatch); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetReadHandler(0x8000, 0xFFFF, Mapper449_Read); +static void power () { + pad = padSelect = 0; + Latch_power(); + if (submapper == 1) + SetReadHandler(0x5000, 0x5FFF, readPad_submapper1); + else + if (submapper == 2) + SetWriteHandler(0x6000, 0x7FFF, writePad_submapper2); } -void Mapper449_Init(CartInfo *info) -{ - info->Power = Mapper449_Power; - info->Reset = Mapper449_Reset; - AddExState(StateRegs, ~0, 0, 0); -} \ No newline at end of file +static void reset () { + pad++; + padSelect = 0; + Latch_clear(); +} + +void Mapper449_Init (CartInfo *info) { + submapper = info->submapper; + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; + AddExState(&pad, 1, 0, "DIPS"); + if (submapper == 2) AddExState(&padSelect, 1, 0, "DIPE"); +} diff --git a/src/boards/450.c b/src/boards/450.c index 990c651..f2da501 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); @@ -27,12 +27,12 @@ static void sync () { VRC24_syncMirror(); } -void Mapper450_reset(void) { - VRC2_pins =0; - VRC24_Sync(); -} +static void reset(void) { + VRC2_pins = 0; + VRC24_clear(); +} void Mapper450_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0); - info->Reset =Mapper450_reset; + VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); + info->Reset = reset; } diff --git a/src/boards/455.c b/src/boards/455.c index 55c8bdf..c76eced 100644 --- a/src/boards/455.c +++ b/src/boards/455.c @@ -1,7 +1,7 @@ /* FCEUmm - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2022 + * Copyright (C) 2020 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,62 +16,57 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * */ -/* N625836 PCB */ - #include "mapinc.h" -#include "mmc3.h" +#include "asic_mmc3.h" -static void Mapper455_PRGWrap(uint32 A, uint8 V) { - int prgAND =EXPREGS[1] &0x01? 0x1F: 0x0F; - int prgOR =EXPREGS[0] >>2 &0x07 | EXPREGS[1] <<1 &0x08 | EXPREGS[0] >>2 &0x10; - if (EXPREGS[0] &0x01) { - if (EXPREGS[0] &0x02) { - setprg32(0x8000, prgOR >>1); - } else { - setprg16(0x8000, prgOR); - setprg16(0xC000, prgOR); +static uint8 reg[2]; + +static void sync () { + if (reg[0] &0x01) { + if (reg[0] &0x02) + setprg32(0x8000, reg[0] >>3); + else { + setprg16(0x8000, reg[0] >>2); + setprg16(0xC000, reg[0] >>2); } + MMC3_syncCHR(0xFF, 0x00); } else { - prgOR <<=1; - setprg8(A, V &prgAND | prgOR &~prgAND); + int prgAND = 0x1F; + int chrAND = reg[1] &0x02? 0x7F: 0xFF; + int prgOR = reg[0] >>1; + int chrOR = reg[1] <<6; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); } + MMC3_syncMirror(); } -static void Mapper455_CHRWrap(uint32 A, uint8 V) { - int chrAND =EXPREGS[1] &0x02? 0xFF: 0x7F; - int chrOR =(EXPREGS[0] >>2 &0x07 | EXPREGS[1] <<1 &0x08 | EXPREGS[0] >>2 &0x10) <<4; - setchr1(A, V &chrAND | chrOR &~chrAND); -} - -static DECLFW(Mapper455_Write) { +static DECLFW (writeReg) { if (A &0x100) { - EXPREGS[0] =V; - EXPREGS[1] =A &0xFF; - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); + reg[0] = V; + reg[1] = A &0xFF; + sync(); } } -static void Mapper455_Reset(void) { - EXPREGS[0] =1; - EXPREGS[1] =0; - MMC3RegReset(); +static void reset () { + reg[0] = reg[1] = 0; + MMC3_clear(); } -static void Mapper455_Power(void) { - EXPREGS[0] =1; - EXPREGS[1] =0; - GenMMC3Power(); - SetWriteHandler(0x4100, 0x5FFF, Mapper455_Write); +static void power () { + reg[0] = reg[1] = 0; + MMC3_power(); + SetWriteHandler(0x4020, 0x5FFF, writeReg); } -void Mapper455_Init(CartInfo *info) { - GenMMC3_Init(info, 256, 256, 0, 0); - cwrap = Mapper455_CHRWrap; - pwrap = Mapper455_PRGWrap; - info->Power = Mapper455_Power; - info->Reset = Mapper455_Reset; - AddExState(EXPREGS, 2, 0, "EXPR"); +void Mapper455_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, NULL); + info->Power = power; + info->Reset = reset; + AddExState(reg, 2, 0, "EXPR"); } diff --git a/src/boards/458.c b/src/boards/458.c index cb7ba5b..5ae5b05 100644 --- a/src/boards/458.c +++ b/src/boards/458.c @@ -1,7 +1,7 @@ /* FCEUmm - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2023 + * Copyright (C) 2025 NewRisingSun * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,58 +16,55 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * */ #include "mapinc.h" -#include "mmc3.h" +#include "asic_mmc3.h" -static void M458CW(uint32 A, uint8 V) { - setchr1(A, ((EXPREGS[0] << 4) & ~0x7F) | (V & 0x7F)); +static uint8 submapper; +static uint8 reg; +static uint8 pad; + +static DECLFR (readPad) { + return CartBR(A &~0xF | pad &0xF); } -static void M458PW(uint32 A, uint8 V) { - if (EXPREGS[0] & 0x10) { - setprg32(0x8000, EXPREGS[0] >> 1); - } else { - setprg16(0x8000, EXPREGS[0]); - setprg16(0xC000, EXPREGS[0]); +static void sync () { + if (reg &(submapper == 1? 0x08: 0x10)) + setprg32(0x8000, reg >>1); + else { + setprg16(0x8000, reg); + setprg16(0xC000, reg); } + MMC3_syncCHR(0x7F, reg <<4 &~0x7F); + MMC3_syncMirror(); + SetReadHandler(0x8000, 0xFFFF, reg &(submapper == 1? 0x80: 0x20)? readPad: CartBR); } -static DECLFR(M458Read) { - if ((EXPREGS[0] & 0x20) && (EXPREGS[1] & 3)) { - return CartBR((A & ~3) | (EXPREGS[1] & 3)); - } - return CartBR(A); +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); } -static DECLFW(M458Write) { - if (MMC3CanWriteToWRAM()) { - EXPREGS[0] = A & 0xFF; - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); - } +static void reset () { + reg = 0; + pad++; + MMC3_clear(); } -static void M458Reset(void) { - EXPREGS[0] = 0; - EXPREGS[1]++; - MMC3RegReset(); +static void power () { + reg = 0; + pad = 0; + MMC3_power(); } -static void M458Power(void) { - EXPREGS[0] = 0; - EXPREGS[1] = 0; - GenMMC3Power(); - SetReadHandler(0x8000, 0xFFFF, M458Read); - SetWriteHandler(0x6000, 0x7FFF, M458Write); -} - -void Mapper458_Init(CartInfo *info) { - GenMMC3_Init(info, 256, 256, 0, 0); - cwrap = M458CW; - pwrap = M458PW; - info->Reset = M458Reset; - info->Power = M458Power; - AddExState(EXPREGS, 2, 0, "EXPR"); +void Mapper458_Init (CartInfo *info) { + submapper = info->submapper; + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); + AddExState(&pad, 1, 0, "DIPS"); } diff --git a/src/boards/460.c b/src/boards/460.c index 02d94e0..1345e28 100644 --- a/src/boards/460.c +++ b/src/boards/460.c @@ -1,7 +1,7 @@ /* FCEUmm - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2022 + * Copyright (C) 2020 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,79 +16,70 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * */ + #include "mapinc.h" -#include "mmc3.h" +#include "asic_mmc3.h" +#include "cartram.h" -static uint8 *CHRRAM =NULL; +static uint8 submapper; +static uint8 reg; +static uint8 pad; -static DECLFR(Mapper460_ReadOB) -{ - return X.DB; +static DECLFR (readPad) { + return CartBR(A &~3 | pad &3); } -static void Mapper460_PRGWrap(uint32 A, uint8 V) { - int prgAND =0x0F; - int prgOR =EXPREGS[0] <<4; - if (EXPREGS[0] &0x38) { /* Menu selection by selectively connecting CPU D7 to reg or not */ - if (~A &0x4000) { - setprg8(A, (EXPREGS[0] &0x10? ~2: ~0) &V &prgAND | prgOR &~prgAND); - setprg8(A |0x4000, (EXPREGS[0] &0x10? 2: 0) |V &prgAND | prgOR &~prgAND); - } - } else - setprg8(A, V &prgAND | prgOR &~prgAND); - - /* Menu selection by selectively connecting reg's D7 to PRG /CE or not */ - if (EXPREGS[0] &0x80 && EXPREGS[1] &1) - SetReadHandler(0x8000, 0xFFFF, Mapper460_ReadOB); +static void sync () { + MMC3_syncPRG(0x0F, reg <<4 &~0x0F); + if (reg &0x04) + MMC3_syncCHR(0x1FF, 0x000); else - SetReadHandler(0x8000, 0xFFFF, CartBR); -} - -static void Mapper460_CHRWrap(uint32 A, uint8 V) { - if (EXPREGS[0] &0x04) { - setchr2(0x0000, DRegBuf[0] &0xFE); - setchr2(0x0800, DRegBuf[0] |0x01); - setchr2(0x1000, DRegBuf[2]); - setchr2(0x1800, DRegBuf[5]); - } else setchr8r(0x10, 0); + MMC3_syncMirror(); + SetReadHandler(0x8000, 0xFFFF, submapper == 0 && reg &0x80 || submapper == 1 && reg &0x20? readPad: CartBR); } -static DECLFW(Mapper460_WriteExtra) { - if (A001B &0x80 && ~A001B &0x40) EXPREGS[0] =A &0xFF; - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); +static int getPRGBank (uint8 bank) { + if (reg &0x08) { + int mask = reg &0x10? 3: 1; + return MMC3_getPRGBank(bank &1) &~mask | bank &mask; + } else + return MMC3_getPRGBank(bank); } -static void Mapper460_Reset(void) { - EXPREGS[0] =0; - EXPREGS[1]++; - MMC3RegReset(); +static int getCHRBank (uint8 bank) { + if (reg &0x04) + return MMC3_getCHRBank(bank &6 | bank >>1 &1) <<1 | bank &1; + else + return MMC3_getCHRBank(bank); } -static void Mapper460_Power(void) { - EXPREGS[0] =0; - EXPREGS[1] =0; - GenMMC3Power(); - SetWriteHandler(0x6000, 0x7FFF, Mapper460_WriteExtra); +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); } -static void Mapper460_close(void) { - if (CHRRAM) FCEU_gfree(CHRRAM); - CHRRAM =NULL; +static void reset () { + reg = 0; + pad++; + MMC3_clear(); } -void Mapper460_Init(CartInfo *info) { - GenMMC3_Init(info, 128, 512, 0, 0); - cwrap = Mapper460_CHRWrap; - pwrap = Mapper460_PRGWrap; - info->Power = Mapper460_Power; - info->Reset = Mapper460_Reset; - info->Close = Mapper460_close; - AddExState(EXPREGS, 2, 0, "EXPR"); - - CHRRAM =(uint8 *)FCEU_gmalloc(8192); - SetupCartCHRMapping(0x10, CHRRAM, 8192, 1); - AddExState(CHRRAM, 8192, 0, "CRAM"); +static void power () { + reg = 0; + pad = 0; + MMC3_power(); +} + +void Mapper460_Init (CartInfo *info) { + submapper = info->submapper; + MMC3_init(info, sync, MMC3_TYPE_SHARP, getPRGBank, getCHRBank, NULL, writeReg); + CHRRAM_init(info, 8); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); + AddExState(®, 1, 0, "DIPS"); } diff --git a/src/boards/461.c b/src/boards/461.c new file mode 100644 index 0000000..47d20c8 --- /dev/null +++ b/src/boards/461.c @@ -0,0 +1,60 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc1.h" + +static uint8 reg; + +static void sync () { + if (reg &0x04) { + MMC1_syncPRG(reg &0x08? 0x07: 0x03, reg &0x0C); + MMC1_syncCHR(0x1F, reg <<2 &0x20); + } else { + setprg16(0x8000, reg &0x03); + setprg16(0xC000, reg &0x03); + MMC1_syncCHR(0x07, 0x40); + } + MMC1_syncMirror(); +} + +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset () { + reg = 0; + MMC1_clear(); +} + +static void power () { + reg = 0; + MMC1_power(); +} + +void Mapper461_Init (CartInfo *info) { + MMC1_init(info, sync, MMC1_TYPE_MMC1A, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/468.c b/src/boards/468.c index a6ba217..70110c8 100644 --- a/src/boards/468.c +++ b/src/boards/468.c @@ -7,7 +7,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -18,93 +18,40 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* BlazePro CPLD-based multicarts - - Unsolved issue: how is CHR RAM write-protection triggered? - - Known problems: - - Forever Duo of NES 852-in-1 (rev1): - #A370 Time Lord: Hangs with glitchy status bar on NTSC and PAL but not Dendy - #A133 Galactic Crusader: Wrong mirroring - #A249 Mission Cobra: Wrong mirroring - - Legendary Games of NES 509-in-1: - #189 Huang Di Battle of Zhuolu: Wrong mirroring during intro - #227 Kid Niki Niki 2: Title screen animation flickers and looks strange - #234 Klax: Screen in wrong position during options screen - #365 Rocman X: Graphical garbage in waterfall (middle) level - #403 Star Wars: Blank tiles due to lack of CHR RAM write-protection - #404 The Empire Strikes Back: Blank tiles due to lack of CHR RAM write-protection - #460 Twin Dragons: Wrong mirroring - - Unlicensed Collection 142-in-1: - #59 Huang Di: Wrong mirroring during intro - #84 Ms. Pac-Man: Wrong mirroring - #102 Rocman X: Graphical garbage in waterfall (middle) level - #132 Trolls on Treasure Island: Wrong mirroring during map - - Unreleased Collection 73-in-1 (v1.01): - #38 Holy Diver: Wrong mirroring during first scene -*/ - #include "mapinc.h" -#include "state.h" +#include "asic_fme7.h" +#include "asic_latch.h" +#include "asic_mmc1.h" +#include "asic_mmc2and4.h" +#include "asic_mmc3.h" +#include "asic_vrc1.h" +#include "asic_vrc2and4.h" +#include "asic_vrc3.h" +#include "asic_vrc6.h" +#include "asic_vrc7.h" +#include "cartram.h" static uint8 submapper; -static uint8 eeprom[16], eep_clock, state, command, output; /* Some strange serial EEPROM */ -static uint8 *WRAM; -static uint32 WRAMSIZE; +static uint8 reg[4]; /* Supervisor registers */ +static uint8 Custom_reg[4]; /* Registers for custom mappers */ +static uint8 eeprom[16], eep_clock, state, command, output; /* Serial EEPROM */ -static int prevSFEXINDEX; -extern int SFEXINDEX; -extern SFORMAT SFMDATA[64]; - -static uint8 mapper; /* 5700 MSB >>4 OR'd with submapper <<4 */ -static uint8 mapperFlags; /* 5700 LSB */ -static uint8 misc; /* 5601 */ -static uint8 misc2; /* 5702 */ -static void (*sync)(); - -static uint16 prgOR; -static uint8 prgAND; - -static uint8 regByte[16]; -static int16 regWord[9]; - -#include "468_mmc1.h" -#include "468_mmc24.h" -#include "468_mmc3.h" -#include "468_vrc1.h" -#include "468_vrc24.h" -#include "468_vrc3.h" -#include "468_vrc6.h" -#include "468_vrc7.h" -#include "468_fme7.h" -#include "468_discrete.h" -#include "468_cnrom.h" -#include "468_if12.h" -#include "468_lf36.h" -#include "468_nanjing.h" +static void (*mapperSync)(int) = NULL; +static void applyMode (uint8); static SFORMAT stateRegs[] = { - { &mapper, 1, "SUP0" }, - { &mapperFlags, 1, "SUP1" }, - { &misc, 1, "SUP2" }, - { &misc2, 1, "SUP3" }, - { &prgOR, 2, "SUP4" }, - { &prgAND, 1, "SUP5" }, - { eeprom, 16,"EEPR" }, - { &eep_clock, 1, "EEP0" }, - { &state, 1, "EEP1" }, - { &command, 1, "EEP2" }, - { &output, 1, "EEP3" }, - { regByte, 16,"REGB" }, - { regWord, 16,"REGW" }, + { ®, 4, "REGS" }, + { &Custom_reg, 4, "CURG" }, + { eeprom, 16, "EEPR" }, + { &eep_clock, 1, "EEP0" }, + { &state, 1, "EEP1" }, + { &command, 1, "EEP2" }, + { &output, 1, "EEP3" }, { 0 } }; -static const uint16 lut509[512] ={ /* Strange look-up table, used only by Legendary Games of NES 509-in-1 */ +/* Serial EEPROM */ +static const uint16 lut509[512] = { /* Look-up table, used only by Legendary Games of NES 509-in-1 */ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 0, 1, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 4, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, @@ -120,153 +67,469 @@ static const uint16 lut509[512] ={ /* Strange look-up table, used only by Legend 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 512, 513, 514, 515, 516, 517 }; -void setPins(uint8 select, uint8 newClock, uint8 newData) { /* Serial EEPROM */ +static void setPins(uint8 select, uint8 newClock, uint8 newData) { /* Serial EEPROM */ if (select) - state =0; + state = 0; else if (!eep_clock && !!newClock) { if (state <8) { - command =command <<1 | !!(newData)*1; - if (++state ==8 && (command &0xF0) !=0x50 && (command &0xF0) !=0xA0) state =0; + command = command <<1 | !!(newData)*1; + if (++state == 8 && (command &0xF0) != 0x50 && (command &0xF0) != 0xA0) state = 0; } else { - int mask =1 <<(15 -state); - int address =command &0x0F; - if ((command &0xF0) ==0xA0) { - eeprom[address] =eeprom[address] &~mask | !!(newData)*mask; - /* The "write" command also silently returns the content of a strange lookup table */ - output =!!(lut509[eeprom[0] | eeprom[1] | eeprom[2] <<8 &0x1FF] >>(address &1? 0: 8) &mask); + int mask = 1 <<(15 -state); + int address = command &0x0F; + if ((command &0xF0) == 0xA0) { + eeprom[address] = eeprom[address] &~mask | !!(newData)*mask; + /* The "write" command also silently returns the content of a lookup table */ + output = !!(lut509[eeprom[0] | eeprom[1] | eeprom[2] <<8 &0x1FF] >>(address &1? 0: 8) &mask); } else - if ((command &0xF0) ==0x50) - output =!!(eeprom[address] &mask); - - if (++state ==16) state =0; + if ((command &0xF0) == 0x50) + output = !!(eeprom[address] &mask); + + if (++state == 16) state = 0; } } - eep_clock =newClock; + eep_clock = newClock; } -static DECLFR(readReg); -static DECLFW(writeReg); -static void setMapper(uint8 clearRegs) { - int i; - if (clearRegs) { - for (i =0; i <16; i++) regByte[i] =0; - for (i =0; i < 8; i++) regWord[i] =0; - X6502_IRQEnd(FCEU_IQEXT); +/* Mapper syncs */ +static void sync () { + if (mapperSync) mapperSync(reg[submapper == 1? 2: 3] <<9 &0x2000 | reg[1] <<5 &0x1FE0 | reg[0] <<4 &0x0010); +} + +static void sync_AxROM (int prgOR) { + int prgAND = reg[0] &0x20? 0x0F: reg[0] &0x02? 0x03: 0x07; + setprg32(0x8000, Latch_data &prgAND | prgOR >>2 &~prgAND); + setchr8(0); + setmirror(Latch_data &0x10? MI_1: MI_0); +} + +static void sync_BxROM (int prgOR) { + int prgAND = reg[0] &0x20? 0x0F: reg[0] &0x02? 0x03: 0x07; + setprg32(0x8000, Latch_data &prgAND | prgOR >>2 &~prgAND); + setchr8(0); + setmirror(reg[0] &0x04? MI_H: MI_V); +} + +static void sync_FME7 (int prgOR) { + int prgAND = reg[0] &0x02? 0x0F: 0x1F; + FME7_syncWRAM(0); + FME7_syncPRG(prgAND, prgOR &~prgAND); + FME7_syncCHR(0xFF, 0x00); + FME7_syncMirror(); +} + +static void sync_FxROM (int prgOR) { + int prgAND = reg[0] &0x02? 0x07: 0x0F; + MMC24_syncWRAM(0); + MMC4_syncPRG(prgAND, prgOR >>1 &~prgAND); + MMC24_syncCHR(0xFF, 0x00); + MMC24_syncMirror(); +} + +static void sync_GNROM (int prgOR) { + int prgAND = reg[0] &0x08? 0x01: 0x03; + int value = Latch_data; + if (submapper == 1 && ~reg[0] &0x08 || submapper != 1 && prgOR &0x2000) value = Latch_data >>4 &0x0F | Latch_data <<4 &0xF0; + prgOR = prgOR >>2 | reg[0] >>1 &0x02; + setprg32(0x8000, value &prgAND | prgOR &~prgAND); + setchr8(value >>4); + setmirror(reg[0] &0x10? MI_H: MI_V); +} + +static void sync_IF12 (int prgOR) { + int prgAND = reg[0] &0x02? 0x07: 0x0F; + setprg16(0x8000, Custom_reg[1] &prgAND | prgOR >>1 &~prgAND); + setprg16(0xC000, prgOR >>1 | prgAND); + setchr8(Custom_reg[0] >>1 &0x0F); + setmirror(Custom_reg[0] &0x01? MI_H: MI_V); +} + +static DECLFW (IF12_writeReg) { + Custom_reg[A >>14 &1] = V; + sync(); +} + +static void sync_LF36 (int prgOR) { + prgOR |= reg[0] &0x08; + setprg8(0x8000, 0x04 | prgOR); + setprg8(0xA000, 0x05 | prgOR); + setprg8(0xC000, Custom_reg[0] &0x07 | prgOR); + setprg8(0xE000, 0x07 | prgOR); + setchr8(0); + setmirror(reg[0] &0x04? MI_H: MI_V); +} + +static void FP_FASTAPASS(1) LF36_cpuCycle (int a) { + while (a--) { + if (Custom_reg[1] &1) { + if (!++Custom_reg[2]) ++Custom_reg[3]; + if (Custom_reg[3] &0x10) + X6502_IRQBegin(FCEU_IQEXT); + else + X6502_IRQEnd(FCEU_IQEXT); + } else { + Custom_reg[2] = Custom_reg[3] = 0; + X6502_IRQEnd(FCEU_IQEXT); + } } +} + +static DECLFW(LF36_writeReg) { + switch(A >>13 &3) { + case 0: case 1: + Custom_reg[1] = A >>13 &1; + break; + case 3: + Custom_reg[0] = V; + sync(); + } +} + +static void sync_Misc (int prgOR) { + if (reg[0] &0x02) { + setprg16(0x8000, Custom_reg[2] <<1 &0x0E | reg[0] &0x01 | prgOR >>1 &~0x0F); + setprg16(0xC000, Custom_reg[2] <<1 &0x0E | reg[0] &0x01 | prgOR >>1 &~0x0F); + setchr8(Custom_reg[0] &0x03); + } else { + setprg32(0x8000, Custom_reg[2] &0x07 | prgOR >>2 &~0x07); + setchr8(Custom_reg[0] &0x0F); + } + if (reg[0] &0x08) + setmirror(reg[0] &0x04? MI_H: MI_V); + else + setmirror(Custom_reg[1] &0x10? MI_1: MI_0); +} + +static DECLFW (Misc_writeReg) { + switch(A >>12 &7) { + case 0: case 2: case 3: + Custom_reg[0] = V; + sync(); + break; + case 1: + Custom_reg[reg[0] &0x08? 0: 1] = V; + sync(); + break; + case 6: case 7: + Custom_reg[2] = V; + sync(); + break; + } +} + +static void sync_Nanjing (int prgOR) { + setprg32(0x8000, Custom_reg[2] <<4 &0x30 | Custom_reg[0] &0x0F | (Custom_reg[3] &0x04? 0x00: 0x03) | prgOR >>2); + setchr8(0); + setmirror(reg[0] &0x04? MI_H: MI_V); +} + +static void Nanjing_scanline (void) { + if (Custom_reg[0] &0x80 && scanline <239) { + setchr4(0x0000, scanline >= 127? 1: 0); + setchr4(0x1000, scanline >= 127? 1: 0); + } else + setchr8(0); +} + +static DECLFW (Nanjing_writeReg) { + Custom_reg[A >>8 &3] = V; + sync(); +} + +static void sync_PNROM (int prgOR) { + MMC24_syncWRAM(0); + MMC2_syncPRG(0x0F, prgOR &~0x0F); + MMC24_syncCHR(0xFF, 0x00); + MMC24_syncMirror(); +} + +static void sync_SxROM (int prgOR) { + int prgAND = reg[0] &0x02? (reg[0] &0x08? 0x03: 0x07): 0x0F; + MMC1_syncWRAM(0); + MMC1_syncPRG(prgAND, (prgOR >>1 | reg[0] &0x06) &~prgAND); + MMC1_syncCHR(0x1F, 0x00); + MMC1_syncMirror(); +} + +static void sync_SUROM (int prgOR) { + MMC1_syncWRAM(0); + MMC1_syncPRG(0x1F, prgOR >>1 &~0x1F); + MMC1_syncCHR(0x0F, 0x00); + MMC1_syncMirror(); +} + +static int SUROM_getPRGBank (uint8 bank) { + return MMC1_getPRGBank(bank) | MMC1_getCHRBank(0) &0x10; +} + +static void sync_TxROM (int prgOR) { + int prgAND = reg[0] &0x08? (reg[0] &0x04? (reg[0] &0x02? (reg[2] &0x02? 0x07: 0x0F): 0x1F): 0x3F): 0x7F; + prgOR |= reg[2] &0x01? 0x0C: 0x00; + MMC3_syncWRAM(0); + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(reg[0] &0x10? 0xFF: 0x7F, 0x00); + MMC3_syncMirror(); +} + +static void sync_TxSROM (int prgOR) { + int prgAND = reg[0] &0x08? (reg[0] &0x04? (reg[0] &0x02? (reg[2] &0x02? 0x07: 0x0F): 0x1F): 0x3F): 0x7F; + prgOR |= reg[2] &0x01? 0x0C: 0x00; + MMC3_syncWRAM(0); + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(0x7F, 0x00); + switch(MMC3_getMirroring() &3) { /* Only A000=02 is TxSROM. H/V mirroring is necessary for Ys 1, modified for MMC3. */ + case 0: + setmirror(MI_V); + break; + case 1: + setmirror(MI_H); + break; + case 2: + setmirror(MMC3_getCHRBank(0) &0x80? MI_1: MI_0); + break; + case 3: + setmirror(MI_1); + break; + } +} + +static void sync_UxROM (int prgOR) { + int prgAND = reg[0] &0x02? 0x07: submapper == 1 && ~reg[0] &0x04? 0x1F: 0x0F; + setprg16(0x8000, Latch_data &prgAND | prgOR >>1 &~prgAND); + setprg16(0xC000, prgOR >>1 | prgAND); + setchr8(0); + setmirror(reg[0] &0x04? MI_H: MI_V); +} + +static void sync_UNROM512 (int prgOR) { + setprg16(0x8000, Latch_data &0x1F | prgOR >>1 &~0x1F); + setprg16(0xC000, prgOR >>1 | 0x1F); + setchr8(Latch_data >>5); + setmirror(reg[0] &0x04? MI_H: MI_V); +} + +static void sync_VRC1 (int prgOR) { + int prgAND = reg[0] &0x08? (reg[0] &0x04? (reg[0] &0x02? 0x0F: 0x1F): 0x3F): 0x7F; + VRC1_syncPRG(prgAND, prgOR &~prgAND); + VRC1_syncCHR(0x1F, 0x00); + VRC1_syncMirror(); +} + +static void sync_VRC24 (int prgOR) { + int prgAND = reg[0] &0x02? 0x0F: 0x1F; + VRC24_syncWRAM(0); + VRC24_syncPRG(prgAND, prgOR &~prgAND); + VRC24_syncCHR(0xFF, 0x00); + VRC24_syncMirror(); +} + +static void sync_VRC3 (int prgOR) { + VRC3_syncWRAM(0); + VRC3_syncPRG(0x07, prgOR >>1 &~0x07); + VRC3_syncCHR(0x01, 0x00); + setmirror(reg[0] &0x04? MI_H: MI_V); +} + +static void sync_VRC6 (int prgOR) { + int prgAND = reg[0] &0x02? 0x0F: 0x1F; + VRC6_syncWRAM(0); + VRC6_syncPRG(prgAND, prgOR &~prgAND); + VRC6_syncCHR(0xFF, 0x00); + VRC6_syncMirror(); +} + +static void sync_VRC7 (int prgOR) { + int prgAND = reg[0] &0x08? (reg[0] &0x04? (reg[0] &0x02? 0x0F: 0x1F): 0x3F): 0x7F; + VRC7_syncWRAM(0); + VRC7_syncPRG(prgAND, prgOR &~prgAND); + VRC7_syncCHR(reg[0] &0x10? 0xFF: 0x7F, 0x00); + VRC7_syncMirror(); +} + +/* Supervisor */ +static DECLFR (readReg) { + switch(A) { + case 0x5301: case 0x5601: + return output? 0x80: 0x00; + default: + return 0xFF; + } +} + +static DECLFW (writeReg) { + switch(A) { + case 0x5301: + if (submapper == 0) setPins(!!(V &0x04), !!(V &0x02), !!(V &0x01)); + break; + case 0x5601: + if (submapper == 1) setPins(!!(V &0x10), !!(V &0x02), !!(V &0x01)); + if (~reg[3] &0x80) { + reg[3] = V; + sync(); + } + break; + case 0x5700: + reg[A &3] = V; + applyMode(1); + break; + case 0x5701: case 0x5702: + reg[A &3] = V; + sync(); + break; + } +} + +static void applyMode (uint8 clear) { + uint8 previousMirroring; + MapIRQHook = NULL; + PPU_hook = NULL; + GameHBIRQHook = NULL; SetReadHandler(0x5000, 0x5FFF, readReg); SetReadHandler(0x6000, 0xFFFF, CartBR); SetWriteHandler(0x5000, 0x5FFF, writeReg); SetWriteHandler(0x6000, 0xFFFF, CartBW); - MapIRQHook = NULL; - PPU_hook = NULL; - GameHBIRQHook = NULL; - setprg8r(0x10, 0x6000, 0); - - switch(mapper) { /* 5700 MSB >>4 OR'd with submapper <<4 */ - case 0x00: case 0x01: case 0x32: MMC1_reset(clearRegs); break; - case 0x0A: MMC2_reset(clearRegs); break; - case 0x10: case 0x11: case 0x12: MMC3_reset(clearRegs); break; - case 0x08: MMC4_reset(clearRegs); break; - case 0x40: VRC1_reset(clearRegs); break; - case 0x20: case 0x21: case 0x22: case 0x23: VRC24_reset(clearRegs); break; - case 0x44: VRC3_reset(clearRegs); break; - case 0x30: case 0x31: VRC6_reset(clearRegs); break; - case 0x41: VRC7_reset(clearRegs); break; - case 0x07: LF36_reset(clearRegs); break; - case 0x50: FME7_reset(clearRegs); break; - case 0x0E: case 0x1E: NANJING_reset(clearRegs); break; - case 0x09: case 0x0B: case 0x17: case 0x37: UNROM_IF12_reset(clearRegs); break; - case 0x04: case 0x06: case 0x14: case 0x16: ANROM_BNROM_reset(clearRegs); break; - case 0x05: case 0x15: CNROM_BF9097_reset(clearRegs); break; - case 0x0C: case 0x0D: case 0x1C: case 0x1D: GNROM_reset(clearRegs); break; - default: break; - } - sync(); -} - -static DECLFR(readReg) { - switch(A) { - case 0x5301: case 0x5601: - return output? 0x80: 0x00; - default: - return 0xFF; - } -} - -static DECLFW(writeReg) { - switch(A) { - case 0x5301: - if (submapper ==0) setPins(!!(V &0x04), !!(V &0x02), !!(V &0x01)); - break; - case 0x5601: - if (~misc &0x80) { - misc =V; - if (submapper !=1) { - prgOR =prgOR &~0x2000 | V <<9 &0x2000; + switch(submapper <<8 | reg[0] >>4) { + case 0x000: case 0x302: + mapperSync = sync_SxROM; + MMC1_activate(clear, sync, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL); + break; + case 0x001: + mapperSync = sync_SUROM; + MMC1_activate(clear, sync, MMC1_TYPE_MMC1B, SUROM_getPRGBank, NULL, NULL, NULL); + break; + case 0x004: case 0x006: case 0x104: case 0x106: + mapperSync = reg[0] &0x08? sync_BxROM: sync_AxROM; + Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); + break; + case 0x005: case 0x105: + mapperSync = sync_Misc; /* NROM, CNROM, Fire Hawk */ + SetWriteHandler(0x8000, 0xFFFF, Misc_writeReg); + if (clear) Custom_reg[0] = Custom_reg[1] = Custom_reg[2] = Custom_reg[3] = 0; + sync(); + break; + case 0x007: + mapperSync = sync_LF36; /* SMB2J */ + MapIRQHook = LF36_cpuCycle; + SetWriteHandler(0x8000, 0xFFFF, LF36_writeReg); + if (clear) Custom_reg[0] = Custom_reg[1] = Custom_reg[2] = Custom_reg[3] = 0; + sync(); + break; + case 0x008: + mapperSync = sync_FxROM; + MMC24_activate(clear, sync); + break; + case 0x009: case 0x107: case 0x307: + if (reg[0] &0x08) { + mapperSync = sync_UxROM; + Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); + } else { + mapperSync = sync_IF12; /* Not Irem's actual IF-12 mapper, but something custom by BlazePro */ + SetWriteHandler(0x8000, 0xFFFF, IF12_writeReg); + if (clear) Custom_reg[0] = Custom_reg[1] = Custom_reg[2] = Custom_reg[3] = 0; sync(); } - } - if (submapper ==1) setPins(!!(V &0x10), !!(V &0x02), !!(V &0x01)); - break; - case 0x5700: - mapper =V >>4 | submapper <<4; - mapperFlags =V &0xF; - prgOR =prgOR &~0x0010 | V <<4 &0x0010; - setMapper(1); - break; - case 0x5701: - prgOR =prgOR &~0x1FE0 | V <<5 &0x1FE0; - sync(); - break; - case 0x5702: - if (submapper ==1) { - misc2 =V; - prgOR =prgOR &~0x2000 | V <<9 &0x2000; - setMapper(0); /* The misc2 value is required for prgAND by MMC3 and UNROM */ - } - break; + break; + case 0x00A: + mapperSync = sync_PNROM; + MMC24_activate(clear, sync); + break; + case 0x00B: + mapperSync = sync_UNROM512; + Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); + break; + case 0x00C: case 0x00D: case 0x10C: case 0x10D: + mapperSync = sync_GNROM; + Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); + break; + case 0x00E: case 0x10E: + mapperSync = sync_Nanjing; + GameHBIRQHook = Nanjing_scanline; + SetWriteHandler(0x5000, 0x53FF, Nanjing_writeReg); + if (clear) Custom_reg[0] = Custom_reg[1] = Custom_reg[2] = Custom_reg[3] = 0; + sync(); + break; + case 0x100: case 0x101: + mapperSync = sync_TxROM; + previousMirroring = MMC3_getMirroring(); + MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, NULL); + MMC3_writeReg(0xA000, previousMirroring); + break; + case 0x102: + mapperSync = sync_TxSROM; + MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, NULL); + break; + case 0x200: + mapperSync = sync_VRC24; + VRC2_activate(clear, sync, 0x05, 0x0A, NULL, NULL, NULL, NULL); + break; + case 0x201: + mapperSync = sync_VRC24; + VRC4_activate(clear, sync, 0x05, 0x0A, 1, NULL, NULL, NULL, NULL, NULL); + break; + case 0x202: + mapperSync = sync_VRC24; + VRC2_activate(clear, sync, 0x0A, 0x05, NULL, NULL, NULL, NULL); + break; + case 0x203: + mapperSync = sync_VRC24; + VRC4_activate(clear, sync, 0x0A, 0x05, 1, NULL, NULL, NULL, NULL, NULL); + break; + case 0x300: case 0x301: + mapperSync = sync_VRC6; + VRC6_activate(clear, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); + break; + case 0x400: + mapperSync = sync_VRC1; + VRC1_activate(clear, sync); + break; + case 0x401: + mapperSync = sync_VRC7; + VRC7_activate(clear, sync, 0x18); + break; + case 0x404: + mapperSync = sync_VRC3; + VRC3_activate(clear, sync); + break; + case 0x500: + mapperSync = sync_FME7; + FME7_activate(clear, sync); + break; + default: + break; } } -static void reset(void) { - mapper =submapper <<4; - mapperFlags =0x0F; - misc =0; - misc2 =0; - prgOR =0x7FF0; - eep_clock =command =output =1; - command =state =0; - setMapper(1); +static void power () { + reg[0] = 0x0F; + reg[1] = 0xFF; + reg[2] = submapper == 1? 0x10: 0x00; + reg[3] = 0x00; + eep_clock = command = output = 1; + command = state = 0; + applyMode(1); } -static void power(void) { - int i; - for (i =0; i <16; i++) eeprom[i] =0; - reset(); + +static void stateRestore (int version) { + applyMode(0); } -static void close(void) { - if (WRAM) - FCEU_gfree(WRAM); - WRAM = NULL; -} - -static void stateRestore(int version) { - setMapper(0); -} - -void Mapper468_Init(CartInfo *info) { - submapper =info->submapper; - info->Reset =reset; - info->Power =power; - info->Close =close; - GameStateRestore =stateRestore; - - WRAMSIZE =8192; - WRAM =(uint8*) FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +void Mapper468_Init (CartInfo *info) { + submapper = info->submapper; + FME7_addExState(); + Latch_addExState(); + MMC1_addExState(); + MMC24_addExState(); + MMC3_addExState(); + VRC1_addExState(); + VRC24_addExState(); + VRC3_addExState(); + VRC6_addExState(); + VRC7_addExState(); + WRAM_init(info, 8); + info->Reset = power; + info->Power = power; + GameStateRestore = stateRestore; AddExState(stateRegs, ~0, 0, 0); - prevSFEXINDEX =SFEXINDEX; } diff --git a/src/boards/468_cnrom.h b/src/boards/468_cnrom.h deleted file mode 100644 index 00dc2dc..0000000 --- a/src/boards/468_cnrom.h +++ /dev/null @@ -1,45 +0,0 @@ -#define CNROM_reg regByte - -static void CNROM_sync () { - int OR =prgOR >>1; - if (mapperFlags &2) { - setprg16(0x8000, CNROM_reg[2] <<1 &0xE | mapperFlags &1 | OR &~0xF); - setprg16(0xC000, CNROM_reg[2] <<1 &0xE | mapperFlags &1 | OR &~0xF); - setchr8(CNROM_reg[0] &0x03); - } else { - OR >>=1; - setprg32(0x8000, CNROM_reg[2] &0x7 | OR &~0x7); - setchr8(CNROM_reg[0] &0x0F); - } - if (mapperFlags &8) - setmirror(mapperFlags &0x04? MI_H: MI_V); - else - setmirror(CNROM_reg[1] &0x10? MI_1: MI_0); -} - -static DECLFW(CNROM_writeReg) { - switch(A &0xE000) { - case 0x8000: case 0xA000: - CNROM_reg[0] =V; - break; - case 0xE000: - CNROM_reg[2] =V; - break; - } - sync(); -} - -static DECLFW(BF9097_writeMirroring) { - CNROM_reg[1] =V; - sync(); -} - -void CNROM_BF9097_reset(uint8 clearRegs) { /* This strange mapper is used for both (C)NROM games and FireHawk. What an absurd combination!*/ - sync =CNROM_sync; - SetWriteHandler(0x8000, 0xFFFF, CNROM_writeReg); - if (~mapperFlags &8) - SetWriteHandler(0x9000, 0x9FFF, BF9097_writeMirroring); - sync(); -} - -#undef CNROM_reg diff --git a/src/boards/468_discrete.h b/src/boards/468_discrete.h deleted file mode 100644 index e42c438..0000000 --- a/src/boards/468_discrete.h +++ /dev/null @@ -1,73 +0,0 @@ -#define latch regByte[0] - -static void ANROM_sync () { - int AND =prgAND >>2; - int OR =prgOR >>2; - setprg32(0x8000, latch &AND | OR &~AND); - setchr8(0); - setmirror(latch &0x10? MI_1: MI_0); -} - -static void BNROM_sync () { - int AND =prgAND >>2; - int OR =prgOR >>2; - setprg32(0x8000, latch &AND | OR &~AND); - setchr8(0); - setmirror(mapperFlags &4? MI_H: MI_V); -} - -static void GNROM_sync () { - int AND =prgAND >>2; - int OR =prgOR >>2 | (mapperFlags &4? 2: 0); - setprg32(0x8000, latch >>4 &AND | OR &~AND); - setchr8(latch &0x0F); - setmirror(mapper &1? MI_H: MI_V); -} - -static void UNROM_sync () { - int AND =prgAND >>1; - int OR =prgOR >>1; - setprg16(0x8000, latch &AND | OR &~AND); - setprg16(0xC000, 0xFF &AND | OR &~AND); - setchr8(0); - setmirror(mapperFlags &4? MI_H: MI_V); -} - -static DECLFW(DISCRETE_writeLatch) { - latch =V; - sync(); -} - -static DECLFW(Portopia_writeLatch) { - DISCRETE_writeLatch(A, A ==0xA000 && V ==0x00? 0x06: V); /* Strange hack, needed to get #282 "Portopia Serial Murder Case" on 852-in-1 running */ -} - -static DECLFW(ColorDreams_writeLatch) { - DISCRETE_writeLatch(A, V >>4 &0xF | V <<4 &0xF0); /* Sswap nibbles to mimic GNROM */ -} - - -void ANROM_BNROM_reset(uint8 clearRegs) { - sync =mapperFlags &8? BNROM_sync: ANROM_sync; - prgAND =(mapper ==0x06 || mapper ==0x16)? 0x3F: mapperFlags &2? 0x0F: 0x1F; - SetWriteHandler(0x8000, 0xFFFF, DISCRETE_writeLatch); - latch =0; - sync(); -} - -void GNROM_reset(uint8 clearRegs) { - sync =GNROM_sync; - prgAND =mapperFlags &8? 0x07: 0x0F; - SetWriteHandler(0x8000, 0xFFFF, misc &0x10 && mapper &~0x10? DISCRETE_writeLatch: ColorDreams_writeLatch); - latch =0; - sync(); -} - -void UNROM_reset(uint8 clearRegs) { - sync =UNROM_sync; - prgAND =mapper ==0x0B || misc2 &0x10? 0x3F: mapperFlags &2? 0x0F: 0x1F; - SetWriteHandler(0x8000, 0xFFFF, mapper ==0x09 && mapperFlags ==0xE? Portopia_writeLatch: DISCRETE_writeLatch); - sync(); -} - -#undef latch diff --git a/src/boards/468_fme7.h b/src/boards/468_fme7.h deleted file mode 100644 index 0e3d311..0000000 --- a/src/boards/468_fme7.h +++ /dev/null @@ -1,72 +0,0 @@ -#define FME7_reg regByte -#define FME7_index regByte[15] -#define FME7_counter regWord[0] - -static void FME7_sync() { - int AND =mapperFlags &8? 0xFF: 0x7F; - switch(FME7_reg[8] &0xC0) { - case 0x00: case 0x80: - setprg8(0x6000, FME7_reg[0x8] &prgAND | prgOR &~prgAND); - break; - case 0x40: - /* Open Bus */ - break; - case 0xC0: - setprg8r(0x10, 0x6000, 0); - break; - } - - setprg8(0x8000, FME7_reg[0x9] &prgAND | prgOR &~prgAND); - setprg8(0xA000, FME7_reg[0xA] &prgAND | prgOR &~prgAND); - setprg8(0xC000, FME7_reg[0xB] &prgAND | prgOR &~prgAND); - setprg8(0xE000, prgAND | prgOR &~prgAND); - setchr1(0x0000, FME7_reg[0x0] &AND); - setchr1(0x0400, FME7_reg[0x1] &AND); - setchr1(0x0800, FME7_reg[0x2] &AND); - setchr1(0x0C00, FME7_reg[0x3] &AND); - setchr1(0x1000, FME7_reg[0x4] &AND); - setchr1(0x1400, FME7_reg[0x5] &AND); - setchr1(0x1800, FME7_reg[0x6] &AND); - setchr1(0x1C00, FME7_reg[0x7] &AND); - setmirror(FME7_reg[0xC] &3 ^(FME7_reg[0xC] &2? 0: 1)); -} - -static DECLFW(FME7_writeIndex) { - FME7_index =V &0xF; -} - -static DECLFW(FME7_writeReg) { - switch(FME7_index) { - case 0xE: - FME7_counter =FME7_counter &0xFF00 |V; - break; - case 0xF: - FME7_counter =FME7_counter &0x00FF |V <<8; - break; - case 0xD: - X6502_IRQEnd(FCEU_IQEXT); - /* Falling through */ - default: - FME7_reg[FME7_index] =V; - sync(); - } -} - -static void FP_FASTAPASS(1) FME7_cpuCycle(int a) { - while (a--) { - if (FME7_reg[0xD] &0x80 && !--FME7_counter && FME7_reg[0xD] &0x01) X6502_IRQBegin(FCEU_IQEXT); - } -} - -void FME7_reset(uint8 clearRegs) { - sync =FME7_sync; - prgAND =mapperFlags &2? 0x0F: 0x1F; - MapIRQHook =FME7_cpuCycle; - SetWriteHandler(0x8000, 0x9FFF, FME7_writeIndex); - SetWriteHandler(0xA000, 0xBFFF, FME7_writeReg); - sync(); -} - -#undef FME7_reg -#undef FME7_index -#undef FME7_counter diff --git a/src/boards/468_if12.h b/src/boards/468_if12.h deleted file mode 100644 index 12ec1e7..0000000 --- a/src/boards/468_if12.h +++ /dev/null @@ -1,31 +0,0 @@ -#define IF12_reg regByte - -static void IF12_sync () { - int AND =prgAND >>1; - int OR =prgOR >>1; - setprg16(0x8000, IF12_reg[1] &AND | OR &~AND); - setprg16(0xC000, 0xFF &AND | OR &~AND); - setchr8(IF12_reg[0] >>1 &0xF); - setmirror(IF12_reg[0] &1? MI_H: MI_V); -} - -static DECLFW(IF12_writeReg) { - IF12_reg[A >>14 &1] =V; - sync(); -} - -void IF12_reset(uint8 clearRegs) { - sync =IF12_sync; - prgAND =mapperFlags &2? 0x0F: 0x1F; - SetWriteHandler(0x8000, 0xFFFF, IF12_writeReg); - sync(); -} - -void UNROM_IF12_reset(uint8 clearRegs) { - if (mapperFlags &8) - UNROM_reset(clearRegs); - else - IF12_reset(clearRegs); -} - -#undef IF12_reg diff --git a/src/boards/468_lf36.h b/src/boards/468_lf36.h deleted file mode 100644 index 73f9407..0000000 --- a/src/boards/468_lf36.h +++ /dev/null @@ -1,46 +0,0 @@ -#define LF36_prg regByte[0] -#define LF36_irq regByte[1] -#define LF36_counter regWord[0] - -static void LF36_sync () { - int OR =prgOR | mapperFlags &0x08; - setprg8(0x8000, 0x04 | OR); - setprg8(0xA000, 0x05 | OR); - setprg8(0xC000, LF36_prg &0x07 | OR); - setprg8(0xE000, 0x07 | OR); - setchr8(0); - setmirror(mapperFlags &4? MI_H: MI_V); -} - -static DECLFW(LF36_writeReg) { - switch (A &0xE000) { - case 0x8000: LF36_irq =0; break; - case 0xA000: LF36_irq =1; break; - case 0XE000: LF36_prg =V; sync(); break; - } -} - -static void FP_FASTAPASS(1) LF36_cpuCycle(int a) { - while (a--) { - if (LF36_irq) { - if (++LF36_counter &0x1000) - X6502_IRQBegin(FCEU_IQEXT); - else - X6502_IRQEnd(FCEU_IQEXT); - } else { - X6502_IRQEnd(FCEU_IQEXT); - LF36_counter =0; - } - } -} - -void LF36_reset(uint8 clearRegs) { - sync =LF36_sync; - MapIRQHook =LF36_cpuCycle; - SetWriteHandler(0x8000, 0xFFFF, LF36_writeReg); - sync(); -} - -#undef LF36_prg -#undef LF36_irq -#undef LF36_counter diff --git a/src/boards/468_mmc1.h b/src/boards/468_mmc1.h deleted file mode 100644 index b780ce2..0000000 --- a/src/boards/468_mmc1.h +++ /dev/null @@ -1,72 +0,0 @@ -#define MMC1_reg regByte -#define MMC1_control regByte[0] -#define MMC1_chr0 regByte[1] -#define MMC1_chr1 regByte[2] -#define MMC1_prg regByte[3] -#define MMC1_shift regByte[4] -#define MMC1_count regByte[5] -#define MMC1_filter regByte[6] - -static void MMC1_sync () { - int AND =prgAND >>1; - int OR =prgOR >>1 | (mapper &0x01? (MMC1_chr0 &0x10): (mapperFlags &0x06)); - if (MMC1_control &0x08) { /* 16 KiB mode */ - if (MMC1_control &0x04) { /* OR logic */ - setprg16(0x8000, MMC1_prg &AND | OR &~AND); - setprg16(0xC000, 0xFF &AND | OR &~AND); - } else { /* AND logic */ - setprg16(0x8000, 0 &AND | OR &~AND); - setprg16(0xC000, MMC1_prg &AND | OR &~AND); - } - } else - setprg32(0x8000, (MMC1_prg &AND | OR &~AND) >>1); - - AND =mapper &0x01? 0x0F: 0x1F; /* SUROM needs to have the upper PRG bank bit, which is in the CHR registers, masked off */ - if (MMC1_control &0x10) { /* 4 KiB mode */ - setchr4(0x0000, MMC1_chr0 &AND); - setchr4(0x1000, MMC1_chr1 &AND); - } else /* 8 KiB mode */ - setchr8(MMC1_chr0 >>1 &(AND >>1)); - - setmirror(MMC1_control &2? (MMC1_control &1? MI_H: MI_V): (MMC1_control &1? MI_1: MI_0)); -} - -static DECLFW(MMC1_writeReg) { - if (V &0x80) { - MMC1_shift =MMC1_count =0; - MMC1_control |=0x0C; - sync(); - } else - if (!MMC1_filter) { - MMC1_shift |=(V &1) <>13 &3] =MMC1_shift; - MMC1_count =0; - MMC1_shift =0; - sync(); - } - } - MMC1_filter =2; -} - -static void FP_FASTAPASS(1) MMC1_cpuCycle(int a) { - while (a--) if (MMC1_filter) MMC1_filter--; -} - -void MMC1_reset(uint8 clearRegs) { - sync =MMC1_sync; - MapIRQHook =MMC1_cpuCycle; - prgAND =mapperFlags &2? (mapperFlags &8? 0x07: 0x0F): 0x1F; - SetWriteHandler(0x8000, 0xFFFF, MMC1_writeReg); - if (clearRegs) MMC1_control =0x0C; - sync(); -} - -#undef MMC1_reg -#undef MMC1_control -#undef MMC1_chr0 -#undef MMC1_chr1 -#undef MMC1_prg -#undef MMC1_shift -#undef MMC1_count -#undef MMC1_filter diff --git a/src/boards/468_mmc24.h b/src/boards/468_mmc24.h deleted file mode 100644 index 398fcc0..0000000 --- a/src/boards/468_mmc24.h +++ /dev/null @@ -1,67 +0,0 @@ -#define MMC24_reg regByte - -static void MMC2_sync() { - setprg8(0x8000, MMC24_reg[0] &prgAND | prgOR &~prgAND); - setprg8(0xA000, 0xFD &prgAND | prgOR &~prgAND); - setprg8(0xC000, 0xFE &prgAND | prgOR &~prgAND); - setprg8(0xE000, 0xFF &prgAND | prgOR &~prgAND); - setchr4(0x0000, MMC24_reg[1 +MMC24_reg[6]]); - setchr4(0x1000, MMC24_reg[3 +MMC24_reg[7]]); - setmirror(MMC24_reg[5] &1? MI_H: MI_V); -} - -static void MMC4_sync() { - int AND =prgAND >>1; - int OR =prgOR >>1; - setprg16(0x8000, MMC24_reg[0] &AND | OR &~AND); - setprg16(0xC000, 0xFF &AND | OR &~AND); - setchr4(0x0000, MMC24_reg[1 +MMC24_reg[6]]); - setchr4(0x1000, MMC24_reg[3 +MMC24_reg[7]]); - setmirror(MMC24_reg[5] &1? MI_H: MI_V); -} - -static DECLFW(MMC24_writeReg) { - MMC24_reg[(A >>12) -0xA] =V; - sync(); -} - -static void FP_FASTAPASS(1) MMC24_ppuHook(uint32 A) { - uint8 l, h = A >> 8; - if (h >= 0x20 || ((h & 0xF) != 0xF)) return; - l = A & 0xF0; - if (h < 0x10) { - if (l == 0xD0) { - MMC24_reg[6] =0; - sync(); - } else if (l == 0xE0) { - MMC24_reg[6] =1; - sync(); - } - } else { - if (l == 0xD0) { - MMC24_reg[7] =0; - sync(); - } else if (l == 0xE0) { - MMC24_reg[7] =1; - sync(); - } - } -} - -void MMC2_reset(uint8 clearRegs) { - sync =MMC2_sync; - prgAND =0x0F; - PPU_hook =MMC24_ppuHook; - SetWriteHandler(0xA000, 0xFFFF, MMC24_writeReg); - sync(); -} - -void MMC4_reset(uint8 clearRegs) { - sync =MMC4_sync; - prgAND =mapperFlags &2? 0x0F: 0x1F; - PPU_hook =MMC24_ppuHook; - SetWriteHandler(0xA000, 0xFFFF, MMC24_writeReg); - sync(); -} - -#undef MMC24_reg diff --git a/src/boards/468_mmc3.h b/src/boards/468_mmc3.h deleted file mode 100644 index f46c64d..0000000 --- a/src/boards/468_mmc3.h +++ /dev/null @@ -1,80 +0,0 @@ -#define MMC3_reg regByte -#define MMC3_index regByte[8] -#define MMC3_mirroring regByte[9] -#define MMC3_wram regByte[10] -#define MMC3_reload regByte[11] -#define MMC3_count regByte[12] -#define MMC3_irq regByte[13] -#define MMC3_lastReg regByte[14] - -static void MMC3_sync () { - int chrAND =mapper &0x01? 0xFF: 0x7F; - int OR =prgOR | (misc2 &1? 12: 0); - setprg8(0x8000 ^(MMC3_index <<8 &0x4000), MMC3_reg[6] &prgAND | OR &~prgAND); - setprg8(0xA000, MMC3_reg[7] &prgAND | OR &~prgAND); - setprg8(0xC000 ^(MMC3_index <<8 &0x4000), 0xFE &prgAND | OR &~prgAND); - setprg8(0xE000, 0xFF &prgAND | OR &~prgAND); - setchr1(0x0000 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] &0xFE)&chrAND); - setchr1(0x0400 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] |0x01)&chrAND); - setchr1(0x0800 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] &0xFE)&chrAND); - setchr1(0x0C00 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] |0x01)&chrAND); - setchr1(0x1000 ^(MMC3_index <<5 &0x1000), MMC3_reg[2] &chrAND); - setchr1(0x1400 ^(MMC3_index <<5 &0x1000), MMC3_reg[3] &chrAND); - setchr1(0x1800 ^(MMC3_index <<5 &0x1000), MMC3_reg[4] &chrAND); - setchr1(0x1C00 ^(MMC3_index <<5 &0x1000), MMC3_reg[5] &chrAND); - - if (mapper &2) switch(MMC3_mirroring &3) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MMC3_reg[MMC3_lastReg] &0x80? MI_1: MI_0); break; - case 3: setmirror(MI_1); break; - } else - setmirror(MMC3_mirroring &1? MI_H: MI_V); -} - -static DECLFW(MMC3_writeReg) { - switch(A &0xE001) { - case 0x8000: MMC3_index =V; sync(); break; - case 0x8001: MMC3_reg[MMC3_index &7] =V; sync(); break; - case 0xA000: MMC3_mirroring =V; sync(); break; - case 0xA001: MMC3_wram =V; sync(); break; - case 0xC000: MMC3_reload =V; break; - case 0xC001: MMC3_count =0; break; - case 0xE000: MMC3_irq =0; X6502_IRQEnd(FCEU_IQEXT); break; - case 0xE001: MMC3_irq =1; break; - } -} - -static void MMC3_horizontalBlanking(void) { - MMC3_count =!MMC3_count? MMC3_reload: --MMC3_count; - if (!MMC3_count && MMC3_irq) X6502_IRQBegin(FCEU_IQEXT); -} - -static void FP_FASTAPASS(1) MMC3_ppuHook(uint32 A) { - A &=0x1FFF; - if (MMC3_index &0x80) A ^=0x1000; - if (A <0x1000) - MMC3_lastReg =A >>11; - else - MMC3_lastReg =(A >>10) -2; - if ((MMC3_mirroring &3) ==2) setmirror(MMC3_reg[MMC3_lastReg] &0x80? MI_1: MI_0); -} - -void MMC3_reset(uint8 clearRegs) { - sync =MMC3_sync; - GameHBIRQHook =MMC3_horizontalBlanking; - if (mapper &2) PPU_hook =MMC3_ppuHook; - prgAND =mapperFlags &8? (mapperFlags &4? (mapperFlags &2? (misc2 &2? 0x07: 0x0F): 0x1F): 0x3F): 0x7F; - SetWriteHandler(0x8000, 0xFFFF, MMC3_writeReg); - MMC3_mirroring =1; /* "Legendary Games of NES' 509-in-1"'s menu runs as MMC3 with H mirroring and expects that setting to stay when running a mapper 206 game such as Legend of Valkyrie. */ - sync(); -} - -#undef MMC3_reg -#undef MMC3_index -#undef MMC3_mirroring -#undef MMC3_wram -#undef MMC3_reload -#undef MMC3_count -#undef MMC3_irq -#undef MMC3_lastReg diff --git a/src/boards/468_nanjing.h b/src/boards/468_nanjing.h deleted file mode 100644 index fa5f555..0000000 --- a/src/boards/468_nanjing.h +++ /dev/null @@ -1,29 +0,0 @@ -#define NANJING_reg regByte - -static void NANJING_sync () { - setprg32(0x8000, NANJING_reg[2] <<4 &0x30 | NANJING_reg[0] &0x0F | (NANJING_reg[3] &4? 0x00: 0x03) | prgOR >>2); - setchr8(0); - setmirror(mapperFlags &4? MI_H: MI_V); -} - -static DECLFW(NANJING_writeReg) { - NANJING_reg[A >>8 &3] =V; - sync(); -} - -static void NANJING_horizontalBlanking(void) { - if (NANJING_reg[0] &0x80 && scanline <239) { /* Actual hardware cannot look at the current scanline number, but instead latches PA09 on PA13 rises. This does not seem possible with the current PPU emulation however. */ - setchr4(0x0000, scanline >=127? 1: 0); - setchr4(0x1000, scanline >=127? 1: 0); - } else - setchr8(0); -} - -void NANJING_reset(uint8 clearRegs) { - sync =NANJING_sync; - GameHBIRQHook = NANJING_horizontalBlanking; - SetWriteHandler(0x5000, 0x53FF, NANJING_writeReg); - sync(); -} - -#undef NANJING_reg diff --git a/src/boards/468_vrc1.h b/src/boards/468_vrc1.h deleted file mode 100644 index 087e65e..0000000 --- a/src/boards/468_vrc1.h +++ /dev/null @@ -1,25 +0,0 @@ -#define VRC1_reg regByte - -static void VRC1_sync () { - setprg8(0x8000, VRC1_reg[0] &prgAND | prgOR &~prgAND); - setprg8(0xA000, VRC1_reg[2] &prgAND | prgOR &~prgAND); - setprg8(0xC000, VRC1_reg[4] &prgAND | prgOR &~prgAND); - setprg8(0xE000, 0xFF &prgAND | prgOR &~prgAND); - setchr4(0x0000, VRC1_reg[6] &0x0F | VRC1_reg[1] <<3 &0x10); - setchr4(0x1000, VRC1_reg[7] &0x0F | VRC1_reg[1] <<2 &0x10); - setmirror(VRC1_reg[1] &1? MI_H: MI_V); -} - -static DECLFW(VRC1_writeReg) { - VRC1_reg[A >>12 &7] =V; - sync(); -} - -void VRC1_reset(uint8 clearRegs) { - sync =VRC1_sync; - prgAND =mapperFlags &8? (mapperFlags &4? (mapperFlags &2? 0x0F: 0x1F): 0x3F): 0x7F; - SetWriteHandler(0x8000, 0xFFFF, VRC1_writeReg); - sync(); -} - -#undef VRC1_reg diff --git a/src/boards/468_vrc24.h b/src/boards/468_vrc24.h deleted file mode 100644 index 9916147..0000000 --- a/src/boards/468_vrc24.h +++ /dev/null @@ -1,92 +0,0 @@ -#define VRC24_prg regByte -#define VRC24_mirroring regByte[2] -#define VRC24_misc regByte[3] -#define VRC24_chr regWord -#define VRCIRQ_latch regByte[13] -#define VRCIRQ_mode regByte[14] -#define VRCIRQ_count regByte[15] -#define VRCIRQ_cycles regWord[8] - -static void VRC24_sync() { - setprg8(0x8000 ^(VRC24_misc <<13 &0x4000), VRC24_prg[0] &prgAND | prgOR &~prgAND); - setprg8(0xA000, VRC24_prg[1] &prgAND | prgOR &~prgAND); - setprg8(0xC000 ^(VRC24_misc <<13 &0x4000), 0xFE &prgAND | prgOR &~prgAND); - setprg8(0xE000, 0xFF &prgAND | prgOR &~prgAND); - setchr1(0x0000, VRC24_chr[0]); - setchr1(0x0400, VRC24_chr[1]); - setchr1(0x0800, VRC24_chr[2]); - setchr1(0x0C00, VRC24_chr[3]); - setchr1(0x1000, VRC24_chr[4]); - setchr1(0x1400, VRC24_chr[5]); - setchr1(0x1800, VRC24_chr[6]); - setchr1(0x1C00, VRC24_chr[7]); - setmirror(VRC24_mirroring &3 ^(VRC24_mirroring &2? 0: 1)); -} - -static DECLFW(VRC24_writeReg) { - uint8 index; - A =A &0xF000 | (mapper &2? ((A &0xA? 1: 0) | (A &0x5? 2: 0)): ((A &0x5? 1: 0) | (A &0xA? 2: 0))); - switch (A &0xF000) { - case 0x8000: case 0xA000: - VRC24_prg[A >>13 &1] =V; - sync(); - break; - case 0x9000: - if (~A &2) - VRC24_mirroring =V & (mapper &1? 3: 1); - else - if (~A &1 && mapper &1) - VRC24_misc =V; - sync(); - break; - case 0xF000: - if (mapper &1) switch (A &3) { - case 0: VRCIRQ_latch =VRCIRQ_latch &0xF0 | V &0x0F; break; - case 1: VRCIRQ_latch =VRCIRQ_latch &0x0F | V <<4; break; - case 2: VRCIRQ_mode =V; - if (VRCIRQ_mode &0x02) { - VRCIRQ_count =VRCIRQ_latch; - VRCIRQ_cycles =341; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 3: VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02; - X6502_IRQEnd(FCEU_IQEXT); - break; - } - break; - default: - index =(A -0xB000) >>11 | A >>1 &1; - if (A &1) - VRC24_chr[index] =VRC24_chr[index] & 0x0F | V <<4; - else - VRC24_chr[index] =VRC24_chr[index] &~0x0F | V &0x0F; - sync(); - break; - } -} - -static void FP_FASTAPASS(1) VRCIRQ_cpuCycle(int a) { - while (a--) { - if (VRCIRQ_mode &0x02 && (VRCIRQ_mode &0x04 || (VRCIRQ_cycles -=3) <=0)) { - if (~VRCIRQ_mode &0x04) VRCIRQ_cycles +=341; - if (!++VRCIRQ_count) { - VRCIRQ_count =VRCIRQ_latch; - X6502_IRQBegin(FCEU_IQEXT); - } - } - } -} - -void VRC24_reset(uint8 clearRegs) { - sync =VRC24_sync; - prgAND =mapperFlags &2? 0x0F: 0x1F; - if (mapper &1) MapIRQHook =VRCIRQ_cpuCycle; - SetWriteHandler(0x8000, 0xFFFF, VRC24_writeReg); - sync(); -} - -#undef VRC24_prg -#undef VRC24_mirroring -#undef VRC24_misc -#undef VRC24_chr diff --git a/src/boards/468_vrc3.h b/src/boards/468_vrc3.h deleted file mode 100644 index 5553b23..0000000 --- a/src/boards/468_vrc3.h +++ /dev/null @@ -1,63 +0,0 @@ -#define VRC3_prg regByte[0] -#define VRC3_latch regWord[0] -#define VRC3_mode regByte[1] -#define VRC3_count regWord[1] - -static void VRC3_sync() { - int AND =prgAND >>1; - int OR =prgOR >>1; - setprg16(0x8000, VRC3_prg &AND | OR &~AND); - setprg16(0xC000, AND | OR &~AND); - setchr8(0); - setmirror(mapperFlags &4? MI_H: MI_V); -} - -static DECLFW(VRC3_writeReg) { - int shift; - switch(A &0xF000) { - case 0x8000: case 0x9000: case 0xA000: case 0xB000: - V &=0xF; - shift =A >>10 &0xC; - VRC3_latch =VRC3_latch &~(0xF <>1; - int OR =prgOR >>1; - setprg16(0x8000, VRC6_prg16 & AND | OR & ~AND); - setprg8(0xC000, VRC6_prg8 &prgAND | prgOR &~prgAND); - setprg8(0xE000, prgAND | prgOR &~prgAND); - setchr1(0x0000, VRC6_chr[0]); - setchr1(0x0400, VRC6_chr[1]); - setchr1(0x0800, VRC6_chr[2]); - setchr1(0x0C00, VRC6_chr[3]); - setchr1(0x1000, VRC6_chr[4]); - setchr1(0x1400, VRC6_chr[5]); - setchr1(0x1800, VRC6_chr[6]); - setchr1(0x1C00, VRC6_chr[7]); - setmirror((VRC6_misc &0xC ^(VRC6_misc &0x8? 0: 0x4)) >>2); -} - -static DECLFW(VRC6_writeReg) { - uint8 index; - switch (A &0xF003) { - case 0x8000: case 0x8001: case 0x8002: case 0x8003: - VRC6_prg16 =V; - sync(); - break; - case 0xB003: - VRC6_misc =V; - sync(); - break; - case 0xC000: case 0xC001: case 0xC002: case 0xC003: - VRC6_prg8 =V; - sync(); - break; - case 0xD000: case 0xD001: case 0xD002: case 0xD003: case 0xE000: case 0xE001: case 0xE002: case 0xE003: - index =(A -0xD000) >>10 | A &3; - VRC6_chr[index] =V; - sync(); - break; - case 0xF000: - VRCIRQ_latch =V; - break; - case 0xF001: - VRCIRQ_mode =V; - if (VRCIRQ_mode &0x02) { - VRCIRQ_count =VRCIRQ_latch; - VRCIRQ_cycles =341; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xF002: - VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02; - X6502_IRQEnd(FCEU_IQEXT); - break; - } -} - -void VRC6_reset(uint8 clearRegs) { - sync =VRC6_sync; - prgAND =mapperFlags &2? 0x0F: 0x1F; - MapIRQHook =VRCIRQ_cpuCycle; - SetWriteHandler(0x8000, 0xFFFF, VRC6_writeReg); - sync(); -} - -#undef VRC6_chr -#undef VRC6_prg16 -#undef VRC6_prg8 -#undef VRC6_misc diff --git a/src/boards/468_vrc7.h b/src/boards/468_vrc7.h deleted file mode 100644 index 24e5938..0000000 --- a/src/boards/468_vrc7.h +++ /dev/null @@ -1,82 +0,0 @@ -#define VRC7_chr regByte -#define VRC7_prg0 regByte[8] -#define VRC7_prg1 regByte[9] -#define VRC7_prg2 regByte[10] -#define VRC7_misc regByte[11] - -static void VRC7_sync() { - setprg8(0x8000, VRC7_prg0 &prgAND | prgOR &~prgAND); - setprg8(0xA000, VRC7_prg1 &prgAND | prgOR &~prgAND); - setprg8(0xC000, VRC7_prg2 &prgAND | prgOR &~prgAND); - setprg8(0xE000, prgAND | prgOR &~prgAND); - setchr1(0x0000, VRC7_chr[0]); - setchr1(0x0400, VRC7_chr[1]); - setchr1(0x0800, VRC7_chr[2]); - setchr1(0x0C00, VRC7_chr[3]); - setchr1(0x1000, VRC7_chr[4]); - setchr1(0x1400, VRC7_chr[5]); - setchr1(0x1800, VRC7_chr[6]); - setchr1(0x1C00, VRC7_chr[7]); - setmirror(VRC7_misc &3 ^(VRC7_misc &2? 0: 1)); -} - -static DECLFW(VRC7_writeReg) { - uint8 index; - A =A &0xF000 | (A &0x18? 1: 0) | (A &0x20? 2: 0); - switch (A &0xF003) { - case 0x8000: - VRC7_prg0 =V; - sync(); - break; - case 0x8001: - VRC7_prg1 =V; - sync(); - break; - case 0x9000: - VRC7_prg2 =V; - sync(); - break; - case 0x9001: case 0x9002: - /* sound */ - break; - case 0xA000: case 0xA001: case 0xB000: case 0xB001: case 0xC000: case 0xC001: case 0xD000: case 0xD001: - index =(A -0xA000) >>11 | A &1; - VRC7_chr[index] =V; - sync(); - break; - case 0xE000: - VRC7_misc =V; - sync(); - break; - case 0xE001: - VRCIRQ_latch =V; - break; - case 0xF000: - VRCIRQ_mode =V; - if (VRCIRQ_mode &0x02) { - VRCIRQ_count =VRCIRQ_latch; - VRCIRQ_cycles =341; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xF001: - VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02; - X6502_IRQEnd(FCEU_IQEXT); - break; - } -} - -void VRC7_reset(uint8 clearRegs) { - sync =VRC7_sync; - prgAND =mapperFlags &8? (mapperFlags &4? (mapperFlags &2? 0x0F: 0x1F): 0x3F): 0x7F; - MapIRQHook =VRCIRQ_cpuCycle; - SetWriteHandler(0x8000, 0xFFFF, VRC7_writeReg); - sync(); -} - -#undef VRC7_chr -#undef VRC7_prg0 -#undef VRC7_prg1 -#undef VRC7_prg2 -#undef VRC7_misc - diff --git a/src/boards/483.c b/src/boards/483.c new file mode 100644 index 0000000..8bd4387 --- /dev/null +++ b/src/boards/483.c @@ -0,0 +1,80 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +/* 3927 PCB, reset-based MMC1/CNROM multicart. The common dump with mapper number 3927 has an unrealistic bank order. */ + +#include "mapinc.h" +#include "asic_latch.h" +#include "asic_mmc1.h" + +static uint8 game; + +static void sync_SLROM () { + MMC1_syncPRG(0x07, game <<3); + MMC1_syncCHR(0x1F, game <<5); + MMC1_syncMirror(); +} + +static void sync_CNROM () { + setprg32(0x8000, 0x0C +game -3); + setchr8(0x30 | (game -3) <<2 | Latch_data &0x03); + setmirror(MI_V); +} + +static void sync_SEROM () { + setprg32(0x8000, 0x0F); + MMC1_syncCHR(0x07, 0x78); + MMC1_syncMirror(); +} + +static void applyMode (uint8 clear) { + if (game <= 2) + MMC1_activate(clear, sync_SLROM, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL); + else + if (game <= 5) + Latch_activate(clear, sync_CNROM, 0x8000, 0xFFFF, NULL); + else + MMC1_activate(clear, sync_SEROM, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL); +} + +static void reset () { + if (++game >=7) game = 0; + applyMode(1); +} + +static void power () { + game = 0; + applyMode(1); +} + +static void stateRestore (int version) { + applyMode(0); +} + +void Mapper483_Init (CartInfo *info) { + AddExState(&game, 1, 0, "GAME"); + Latch_addExState(); + MMC1_addExState(); + info->Power = power; + info->Reset = reset; + GameStateRestore = stateRestore; +} diff --git a/src/boards/489.c b/src/boards/489.c new file mode 100644 index 0000000..f84753e --- /dev/null +++ b/src/boards/489.c @@ -0,0 +1,43 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if ((Latch_data &0x1F) == 2) + setprg32(0x8000, Latch_data >>1); + else { + setprg16(0x8000, Latch_data); + setprg16(0xC000, Latch_data); + } + setchr8(Latch_data); + switch(Latch_data >>6) { + case 0: setmirrorw(0, 0, 0, 1); break; + case 1: setmirror(MI_V); break; + case 2: setmirror(MI_H); break; + case 3: setmirror(MI_1); break; + } +} + +void Mapper489_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/490.c b/src/boards/490.c new file mode 100644 index 0000000..30c7fce --- /dev/null +++ b/src/boards/490.c @@ -0,0 +1,68 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; +static uint8 pad; + +static DECLFR (readPad) { + return CartBR(A &~0xF | pad &0xF); +} + +static void sync () { + if (reg &0x20) + setprg32(0x8000, reg >>1); + else { + setprg16(0x8000, reg); + setprg16(0xC000, reg); + } + MMC3_syncCHR(0xFF, reg <<4 &~0xFF); + MMC3_syncMirror(); + SetReadHandler(0x8000, 0xFFFF, reg &0x80? readPad: CartBR); +} + +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); +} + +static void power () { + reg = 0; + pad = 0; + MMC3_power(); +} + +static void reset () { + reg = 0; + ++pad; + MMC3_clear(); +} + +void Mapper490_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/boards/491.c b/src/boards/491.c new file mode 100644 index 0000000..17d2783 --- /dev/null +++ b/src/boards/491.c @@ -0,0 +1,37 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_address &0x08) { + setprg16(0x8000, Latch_address); + setprg16(0xC000, Latch_address); + } else + setprg32(0x8000, Latch_address >>1); + setchr8(Latch_data); + setmirror(Latch_address &0x10? MI_H: MI_V); +} + +void Mapper491_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/492.c b/src/boards/492.c new file mode 100644 index 0000000..6f2b96a --- /dev/null +++ b/src/boards/492.c @@ -0,0 +1,38 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_address &0x20) + setprg32(0x8000, Latch_address >>4); + else { + setprg16(0x8000, Latch_address >>3); + setprg16(0xC000, Latch_address >>3); + } + setchr8(Latch_address >>1 &0x03 | Latch_address >>2 &0x0C); + setmirror(Latch_address &0x01? MI_H: MI_V); +} + +void Mapper492_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/493.c b/src/boards/493.c new file mode 100644 index 0000000..bef0875 --- /dev/null +++ b/src/boards/493.c @@ -0,0 +1,52 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[2]; + +static void sync () { + setprg32(0x8000, reg[0] <<1 | reg[1] &0x01); + setchr8(reg[0] <<3 | reg[1] >>4 &0x07); +} + +static DECLFW (writeReg) { + reg[A >>15 &1] = V; + sync(); +} + +static void power () { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0xFFFF, writeReg); + reg[0] = reg[1] = 0; + RAM[0x07] =0; + sync(); +} + +static void stateRestore (int version) { + sync(); +} + +void Mapper493_Init (CartInfo *info) { + info->Reset = power; + info->Power = power; + GameStateRestore = stateRestore; + AddExState(reg, 2, 0, "REGS"); +} diff --git a/src/boards/494.c b/src/boards/494.c new file mode 100644 index 0000000..f7b1dbb --- /dev/null +++ b/src/boards/494.c @@ -0,0 +1,61 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static uint8 pad; + +static DECLFR (readOB) { + return X.DB; +} + +static void sync () { + if (Latch_address &0x100) { + if (Latch_address &0x001) { + setprg16(0x8000, Latch_address >>2); + setprg16(0xC000, Latch_address >>2); + } else + setprg32(0x8000, Latch_address >>3); + } else { + setprg16(0x8000, Latch_address >>2); + setprg16(0xC000, Latch_address >>2 |7); + } + setchr8(Latch_address >>5 &7 | Latch_address >>1 &8); + setmirror(Latch_address &0x002? MI_H: MI_V); + SetReadHandler(0x8000, 0xFFFF, ~Latch_address &0x100 && Latch_address &0x001 &pad? readOB: CartBR); +} + +static void power () { + pad = 0; + Latch_power(); +} + +static void reset () { + pad++; + Latch_clear(); +} + +void Mapper494_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/boards/495.c b/src/boards/495.c new file mode 100644 index 0000000..65568ec --- /dev/null +++ b/src/boards/495.c @@ -0,0 +1,83 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 prg[3]; +static uint8 chr[4]; +static uint8 latch[2]; + +static SFORMAT stateRegs[] = { + { prg, 3, "PRGR" }, + { chr, 4, "CHRR" }, + { latch, 2, "LATC" }, + { 0 } +}; + +static void sync () { + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg8(0xC000, prg[2]); + setprg8(0xE000, 0xFF); + setchr4(0x0000, chr[0 | latch[0]]); + setchr4(0x1000, chr[2 | latch[1]]); + switch(chr[latch[0]] >>6) { + case 0: setmirrorw(0, 0, 0, 1); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_V); break; + case 3: setmirror(MI_1); break; + } +} + +static void FP_FASTAPASS(1) trapPPUAddressChange (uint32 A) { + if ((A &0x2FF0) == 0xFD0 || (A &0x2FF0) == 0xFE0) { + latch[A >>12 &1] = ~A >>5 &1; + sync(); + } +} + +static DECLFW (writeReg) { + if (A <0xE000) + prg[A >>13 &3] = V; + else + chr[A >>10 &3] = V; + sync(); +} + +static void restore (int version) { + sync(); +} + +static void power () { + prg[0] = prg[1] = prg[2] = 0; + chr[0] = chr[1] = chr[2] = chr[3] = 0; + latch[0] = 0; latch[1] = 0; + sync(); + SetReadHandler (0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, writeReg); + PPU_hook = trapPPUAddressChange; +} + +void Mapper495_Init (CartInfo *info) { + AddExState(stateRegs, ~0, 0, 0); + info->Power = power; + info->Reset = sync; + GameStateRestore = restore; +} diff --git a/src/boards/498.c b/src/boards/498.c new file mode 100644 index 0000000..000005a --- /dev/null +++ b/src/boards/498.c @@ -0,0 +1,62 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc1.h" + +static uint8 reg; + +static void sync () { + if (reg &0x20) + MMC1_syncPRG(0x07, reg &~0x07); + else + if (reg &0x04) + setprg32(0x8000, reg >>1); + else { + setprg16(0x8000, reg); + setprg16(0xC000, reg); + } + MMC1_syncCHR(0x1F, reg <<2 &~0x1F); + MMC1_syncMirror(); +} + +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset () { + reg = 0; + MMC1_clear(); +} + +static void power () { + reg = 0; + MMC1_power(); +} + +void Mapper498_Init (CartInfo *info) { + MMC1_init(info, sync, MMC1_TYPE_MMC1A, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/499.c b/src/boards/499.c new file mode 100644 index 0000000..340c0fd --- /dev/null +++ b/src/boards/499.c @@ -0,0 +1,56 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc1.h" + +static uint8 reg; + +static void sync () { + MMC1_syncPRG(0x07, reg <<3); + MMC1_syncCHR(0x1F, reg <<5); + MMC1_syncMirror(); +} + +static DECLFW (writeReg) { + if (~reg &8) { + reg = A &0xFF; + sync(); + } +} + +static void reset () { + reg = 0; + MMC1_clear(); +} + +static void power () { + reg = 0; + MMC1_power(); +} + +void Mapper499_Init (CartInfo *info) { + MMC1_init(info, sync, MMC1_TYPE_MMC1A, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/503.c b/src/boards/503.c new file mode 100644 index 0000000..04f944d --- /dev/null +++ b/src/boards/503.c @@ -0,0 +1,67 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; +static uint8 pad; + +static DECLFR (readPad) { + return CartBR(A &~3 | pad &3); +} + +static void sync () { + if (reg &0x10) + setprg32(0x8000, reg >>1); + else { + setprg16(0x8000, reg); + setprg16(0xC000, reg); + } + MMC3_syncCHR(0x7F, reg <<4 &~0x7F); + MMC3_syncMirror(); + SetReadHandler(0x8000, 0xFFFF, reg &0x20? readPad: CartBR); +} + +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset () { + reg = 0; + ++pad; + MMC3_clear(); +} + +static void power () { + reg = 0; + pad = 0; + MMC3_power(); +} + +void Mapper503_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/504.c b/src/boards/504.c new file mode 100644 index 0000000..93e1a32 --- /dev/null +++ b/src/boards/504.c @@ -0,0 +1,65 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync () { + int prgAND = reg &0x02? 0x0F: 0x1F; + int chrAND = reg &0x02? 0x7F: 0xFF; + int prgOR = reg <<4; + int chrOR = reg <<7; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static int getPRGBank (uint8 bank) { + if ((reg &0x03) == 0x03 && ~reg &0x08) + return MMC3_getPRGBank(bank &1) &~1 | bank &1; + else + return MMC3_getPRGBank(bank); +} + +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +void Mapper504_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, getPRGBank, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/505.c b/src/boards/505.c new file mode 100644 index 0000000..24b4555 --- /dev/null +++ b/src/boards/505.c @@ -0,0 +1,65 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint16 reg; +static uint8 pad; + +static void sync () { + if (reg &0x01) + MMC3_syncPRG(0x1F, reg &0x60); + else + setprg32(0x8000, reg >>2); + MMC3_syncCHR(reg &0x100? 0x7F: 0xFF, reg >>1 &0x100 | reg &0x080); + MMC3_syncMirror(); +} + +static DECLFR (readPad) { + return pad; +} + +static DECLFW (writeReg) { + reg = A ^0x1C; + sync(); +} + +static void reset () { + reg = 0xFE; + pad++; + MMC3_clear(); +} + +static void power () { + reg = 0xFE; + pad = 0; + MMC3_power(); +} + +void Mapper505_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, readPad, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 2 | FCEUSTATE_RLSB, 0, "EXPR"); + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/boards/506.c b/src/boards/506.c new file mode 100644 index 0000000..aac7e49 --- /dev/null +++ b/src/boards/506.c @@ -0,0 +1,58 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync () { + int prgAND =~reg &3? 0x0F: 0x1F; + int chrAND = reg &3? 0x7F: 0xFF; + int prgOR = reg <<5 &0x20 | reg <<3 &0x10; + int chrOR = reg <<7 &0x100 |~reg <<7 &0x80; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +void Mapper506_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/507.c b/src/boards/507.c new file mode 100644 index 0000000..0c01414 --- /dev/null +++ b/src/boards/507.c @@ -0,0 +1,66 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; +static uint8 pad; + +static void sync () { + int prgAND = reg &0x20? 0x0F: 0x1F; + int chrAND = reg &0x20? 0x7F: 0xFF; + int prgOR = reg; + int chrOR = reg <<3; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static DECLFR (readPad) { + return pad; +} + +static DECLFW (writeReg) { + reg = V; + sync(); +} + +static void reset () { + reg = 0; + pad ^= 0x80; + MMC3_clear(); +} + +static void power () { + reg = 0; + pad = 0; + MMC3_power(); +} + +void Mapper507_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, readPad, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/boards/508.c b/src/boards/508.c new file mode 100644 index 0000000..9a8a16b --- /dev/null +++ b/src/boards/508.c @@ -0,0 +1,70 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; +static uint8 pad; + +static void sync () { + if (reg &0x80) + MMC3_syncPRG(0x1F, reg >>1 &~0x1F); + else + if (reg &0x20) + setprg32(0x8000, (reg &0x0F | reg >>2 &~0x0F) >>1); + else { + setprg16(0x8000, reg &0x0F | reg >>2 &~0x0F); + setprg16(0xC000, reg &0x0F | reg >>2 &~0x0F); + } + setchr8(0); + MMC3_syncMirror(); +} + +static DECLFR (readPad) { + return pad; +} + +static DECLFW (writeReg) { + reg = V; + sync(); +} + +static void reset () { + reg = 0x0F; + pad++; + MMC3_clear(); +} + +static void power () { + reg = 0x0F; + pad = 0; + MMC3_power(); +} + +void Mapper508_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, readPad, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/boards/509.c b/src/boards/509.c new file mode 100644 index 0000000..4e61254 --- /dev/null +++ b/src/boards/509.c @@ -0,0 +1,71 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" +#include "cartram.h" + +static uint8 reg; + +static void sync () { + int prgAND = reg &0x10? 0x1F: 0x0F; + int chrAND = reg &0x10? 0xFF: 0x7F; + int prgOR = reg <<1; + int chrOR = reg <<4; + if (reg &0x20) + MMC3_syncPRG(prgAND, prgOR &~prgAND); + else + if (reg &0x06) + setprg32(0x8000, reg >>1); + else { + setprg16(0x8000, reg); + setprg16(0xC000, reg); + } + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncWRAM(0); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + if (~reg &0x20) { + reg = A &0xFF; + sync(); + } +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +void Mapper509_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + WRAM_init(info, 8); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/510.c b/src/boards/510.c new file mode 100644 index 0000000..b57eabe --- /dev/null +++ b/src/boards/510.c @@ -0,0 +1,63 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" +#include "cartram.h" + +static uint8 reg; + +static void sync () { + int prgAND = reg &0x20? 0x0F: 0x1F; + int chrAND = reg &0x01? 0xFF: 0x7F; + int prgOR = (reg &0x08? 0x020: 0x000) | (reg &0x40? 0x010: 0x000); + int chrOR = (reg &0x04? 0x100: 0x000) | (reg &0x02? 0x080: 0x000); + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncWRAM(0); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + if (reg == 0) { + reg = V; + sync(); + } +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +void Mapper510_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + WRAM_init(info, 8); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/511.c b/src/boards/511.c new file mode 100644 index 0000000..3929975 --- /dev/null +++ b/src/boards/511.c @@ -0,0 +1,75 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; +static uint8 pad; + +static DECLFR (readPad) { + return CartBR(A &~0x3 | pad &0x3); +} + +static void sync () { + int prgAND = 0x0F; + int chrAND = 0xFF; + int prgOR = reg <<4; + int chrOR = reg <<7; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); + SetReadHandler(0x8000, 0xFFFF, reg &0x08? readPad: CartBR); +} + +static int getPRGBank (uint8 bank) { + if (reg &0x04) { + int mask = reg &0x02? 1: 3; + return MMC3_getPRGBank(bank &1) &~mask | bank &mask; + } else + return MMC3_getPRGBank(bank); +} + +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset () { + reg = 0; + pad++; + MMC3_clear(); +} + +static void power () { + reg = 0; + pad = 0; + MMC3_power(); +} + +void Mapper511_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, getPRGBank, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/boards/512.c b/src/boards/512.c new file mode 100644 index 0000000..c332e75 --- /dev/null +++ b/src/boards/512.c @@ -0,0 +1,72 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" +#include "cartram.h" + +static uint8 reg; + +static void sync () { + MMC3_syncPRG(0x3F, 0x00); + MMC3_syncWRAM(0); + + if (reg &0x02) { + setchr4r(0x10, 0x0000, 0); + setchr4r(0x10, 0x1000, 0); + } else + MMC3_syncCHR(0xFF, 0x000); + + if (reg == 1) { /* The game uses six nametables - the two console-internal ones, plus four occupying the second half of 8 KiB CHR-RAM.*/ + setntamem(CHRptr[0x10] +0x1000, 1, 0); + setntamem(CHRptr[0x10] +0x1400, 1, 1); + setntamem(CHRptr[0x10] +0x1800, 1, 2); + setntamem(CHRptr[0x10] +0x1C00, 1, 3); + } else + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + if (A &0x100) { + reg = V; + sync(); + } +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); + SetWriteHandler(0x4020, 0x5FFF, writeReg); +} + +void Mapper512_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, NULL); + CartRAM_init(info, 8, 8); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/514.c b/src/boards/514.c new file mode 100644 index 0000000..292a5cd --- /dev/null +++ b/src/boards/514.c @@ -0,0 +1,48 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" +#include "cartram.h" + +static uint8 chr; + +static void sync () { + setprg8r(0x10, 0x6000, 0); + setprg32(0x8000, Latch_data); + setchr4(0x0000, Latch_data &0x80? chr: 0); + setchr4(0x1000, 1); + setmirror(Latch_data &0x40? MI_H: MI_V); +} + +static void FP_FASTAPASS(1) trapPPUAddressChange (uint32 A) { + if (A &0x2000 && (A &0x23C0) < 0x23C0) { + chr = A >>(10 +(Latch_data &0x40? 1: 0)) &1; + setchr4(0x0000, Latch_data &0x80? chr: 0); + } +} + +void Mapper514_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + WRAM_init(info, 8); + info->Reset = Latch_clear; + PPU_hook = trapPPUAddressChange; + AddExState(&chr, 1, 0, "CHRB"); +} diff --git a/src/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..2658bdd 100644 --- a/src/boards/524.c +++ b/src/boards/524.c @@ -19,12 +19,12 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" static uint8 irqEnabled; static uint16 irqCounter; -static SFORMAT BTL900218_stateRegs[] ={ +static SFORMAT stateRegs[] ={ { &irqEnabled, 1, "IRQE" }, { &irqCounter, 2 | FCEUSTATE_RLSB, "CNTL" }, { 0 } @@ -36,7 +36,7 @@ static void sync () { VRC24_syncMirror(); } -DECLFW(BTL900218_writeIRQ) { +static DECLFW (writeIRQ) { if (A &8) { if (A &4) { irqEnabled =0; @@ -47,19 +47,19 @@ DECLFW(BTL900218_writeIRQ) { } } -void FP_FASTAPASS(1) BTL900218_cpuCycle(int a) { +static void FP_FASTAPASS(1) cpuCycle (int a) { while (a--) if (irqEnabled && ++irqCounter &1024) X6502_IRQBegin(FCEU_IQEXT); } -void BTL900218_power(void) { +static void power (void) { irqEnabled =irqCounter =0; VRC24_power(); - SetWriteHandler(0xF000, 0xFFFF, BTL900218_writeIRQ); + SetWriteHandler(0xF000, 0xFFFF, writeIRQ); } void BTL900218_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0); - AddExState(BTL900218_stateRegs, ~0, 0, 0); - info->Power =BTL900218_power; - MapIRQHook =BTL900218_cpuCycle; + VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); + AddExState(stateRegs, ~0, 0, 0); + info->Power =power; + MapIRQHook =cpuCycle; } diff --git a/src/boards/525.c b/src/boards/525.c index b60948b..97a9316 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); @@ -27,9 +27,9 @@ static void sync () { VRC24_syncMirror(); } -DECLFW(UNLKS7021A_writeCHR) { - VRC24_chr[A &7] =V; - VRC24_Sync(); +DECLFW (UNLKS7021A_writeCHR) { + VRC24_writeReg(0xB000 +(A <<11 &0x3000 | A <<1 &0x0002), V &0x0F); + VRC24_writeReg(0xB001 +(A <<11 &0x3000 | A <<1 &0x0002), V >>4); } 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); - info->Power =UNLKS7021A_power; + 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..af9e17b 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,31 +30,31 @@ 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(); } -DECLFR(UNLT230_readEEPROM) { +static DECLFR (readEEPROM) { return eeprom_93Cx6_read()? 0x01: 0x00; } -DECLFW(UNLT230_writeEEPROM) { +static DECLFW (writeEEPROM) { eeprom_93Cx6_write(A &0x04, A &0x02, A &0x01); } -void UNLT230_power (void) { +static void power (void) { VRC24_power(); eeprom_93Cx6_init(256, 16); - SetReadHandler(0x5000, 0x5FFF, UNLT230_readEEPROM); - SetWriteHandler(0xF800, 0xFFFF, UNLT230_writeEEPROM); + SetReadHandler(0x5000, 0x5FFF, readEEPROM); + SetWriteHandler(0xF800, 0xFFFF, writeEEPROM); } void UNLT230_Init (CartInfo *info) { - 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; + info->Power =power; AddExState(stateRegs, ~0, 0, 0); eeprom_93Cx6_storage = eeprom_data; info->battery = 1; diff --git a/src/boards/530.c b/src/boards/530.c index 2f7dcd6..66924e8 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,28 +27,26 @@ static void sync () { VRC24_syncMirror(); } -int UNLAX5705_getPRGBank(int bank) { +static int getPRGBank (uint8 bank) { int result =VRC24_getPRGBank(bank); return result <<2 &0x8 | result >>2 &0x2 | result &~0xA; } -int UNLAX5705_getCHRBank(int bank) { +static int getCHRBank (uint8 bank) { int result =VRC24_getCHRBank(bank); return result <<1 &0x40 | result >>1 &0x20 | result &~0x60; } -DECLFW(UNLAX5705_unscrambleAddress) { +static DECLFW (unscrambleAddress) { VRC24_writeReg(A &~0x1000 | A <<9 &0x1000, V); } -void UNLAX5705_power (void) { +static void power (void) { VRC24_power(); - SetWriteHandler(0x8000, 0xFFFF, UNLAX5705_unscrambleAddress); + SetWriteHandler(0x8000, 0xFFFF, unscrambleAddress); } void UNLAX5705_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 1, 1, 0); - info->Power =UNLAX5705_power; - VRC24_GetPRGBank =UNLAX5705_getPRGBank; - VRC24_GetCHRBank =UNLAX5705_getCHRBank; + VRC4_init(info, sync, 0x01, 0x02, 1, getPRGBank, getCHRBank, NULL, NULL, NULL); + info->Power =power; } diff --git a/src/boards/536.c b/src/boards/536.c new file mode 100644 index 0000000..935e777 --- /dev/null +++ b/src/boards/536.c @@ -0,0 +1,67 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +/* The UNIF dump of "(JY-103) 3-in-1" (JY4M4 MAPR) has a strange bank order and will not run with this emulation. */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg[2]; + +static void sync () { + int prg = reg[0] &0x1F | reg[0] >>1 &0x20; + if (reg[0] &0x80) + MMC3_syncPRG(0x0F, prg <<2); + else + if (reg[0] &0x20) + setprg32(0x8000, prg >>1); + else { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } + setchr8(0); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + reg[A &1] = V; + sync(); +} + +static void reset () { + reg[0] = 0x60; + reg[1] = 0x00; + MMC3_clear(); +} + +static void power () { + reg[0] = 0x60; + reg[1] = 0x00; + MMC3_power(); +} + +void Mapper536_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(reg, 2, 0, "EXPR"); +} diff --git a/src/boards/537.c b/src/boards/537.c new file mode 100644 index 0000000..e628180 --- /dev/null +++ b/src/boards/537.c @@ -0,0 +1,60 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +/* The UNIF dump of "(JY-103) 3-in-1" (JY4M4 MAPR) has a strange bank order and will not run with this emulation. */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg[2]; + +static void sync () { + int prgAND = reg[0] &0x80? 0x0F: 0x1F; + int chrAND = 0xFF; + int prgOR = reg[0] >>1 &0x20 | reg[1] <<4 &0x10; + int chrOR = reg[0] <<2 &0x100; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + reg[A &1] = V; + sync(); +} + +static void reset () { + reg[0] = reg[1] = 0; + MMC3_clear(); +} + +static void power () { + reg[0] = reg[1] = 0; + MMC3_power(); +} + +void Mapper537_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(reg, 2, 0, "EXPR"); +} diff --git a/src/boards/542.c b/src/boards/542.c index 5e7ed8c..6d4a23a 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; @@ -36,25 +36,25 @@ static void sync () { if (reg &1) setchr1r(0x10, 0x0C00, 1); } -DECLFW(Mapper542_writeExtra) { +DECLFW (writeExtra) { if (A &0x800) { reg =A >>12; - VRC24_Sync(); + sync(); } else VRC24_writeReg(A, V); } -void Mapper542_power (void) { +void power (void) { reg =0; VRC24_power(); SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0xD000, 0xEFFF, Mapper542_writeExtra); + SetWriteHandler(0xD000, 0xEFFF, writeExtra); } void Mapper542_Init (CartInfo *info) { - VRC24_init(info, sync, 0x01, 0x02, 1, 1, 0); - info->Power =Mapper542_power; + VRC4_init(info, sync, 0x01, 0x02, 1, NULL, NULL, NULL, NULL, NULL); + info->Power =power; AddExState(stateRegs, ~0, 0, 0); SetupCartCHRMapping(0x10, NTARAM, 0x200, 1); } diff --git a/src/boards/544.c b/src/boards/544.c index ec9eefe..ae9ca8c 100644 --- a/src/boards/544.c +++ b/src/boards/544.c @@ -19,10 +19,9 @@ */ #include "mapinc.h" -#include "vrc2and4.h" +#include "asic_vrc2and4.h" +#include "cartram.h" -static uint8 *CHRRAM; -static uint32 CHRRAMSize; static uint8 nt[4]; static uint8 prg; static uint8 mask; @@ -43,14 +42,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) { +static DECLFW (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,26 +59,26 @@ static DECLFW(Mapper544_interceptPPUWrite) { mask =bank &0x40? 0xFE: 0xFC; compare =compares[index]; } - VRC24_Sync(); + sync(); } } writePPU(A, V); } -int Mapper544_getPRGBank(int bank) { +static int getPRGBank (uint8 bank) { return bank ==2? prg: VRC24_getPRGBank(bank); } -DECLFW(Mapper544_externalSelect) { +static DECLFW (externalSelect) { if (A &4) nt[A &3] =V; else prg =V; - VRC24_Sync(); + sync(); } -void Mapper544_power (void) { +static void power (void) { mask =0xFC; compare =0x28; nt[0] =nt[1] =0xE0; @@ -87,26 +86,12 @@ void Mapper544_power (void) { prg =0xFE; VRC24_power(); writePPU =GetWriteHandler(0x2007); - SetWriteHandler(0x2007, 0x2007, Mapper544_interceptPPUWrite); -} - -void Mapper544_close(void) { - if (CHRRAM) { - FCEU_gfree(CHRRAM); - CHRRAM =NULL; - } + SetWriteHandler(0x2007, 0x2007, interceptPPUWrite); } void Mapper544_Init (CartInfo *info) { - VRC24_init(info, sync, 0x400, 0x800, 1, 1, 0); - info->Power =Mapper544_power; - info->Close =Mapper544_close; - VRC24_GetPRGBank =Mapper544_getPRGBank; - VRC24_ExternalSelect =Mapper544_externalSelect; + VRC4_init(info, sync, 0x400, 0x800, 1, getPRGBank, NULL, NULL, NULL, externalSelect); + CartRAM_init(info, 8, 2); + info->Power =power; AddExState(stateRegs, ~0, 0, 0); - - CHRRAMSize =info->CHRRamSize +info->CHRRamSaveSize; - CHRRAM =(uint8*)FCEU_gmalloc(CHRRAMSize); - AddExState(CHRRAM, CHRRAMSize, 0, "CRAM"); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1); } diff --git a/src/boards/545.c b/src/boards/545.c new file mode 100644 index 0000000..bd28342 --- /dev/null +++ b/src/boards/545.c @@ -0,0 +1,70 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" +#include "cartram.h" + +static uint8 reg; + +static void sync () { + MMC3_syncWRAM(0); + MMC3_syncPRG(0x7F, 0x00); + MMC3_syncCHR(0x7F, reg <<7 | ~reg <<4 &0x40); + MMC3_syncMirror(); +} + +static int getPRGBank (uint8 bank) { + int result = MMC3_getPRGBank(bank); + if (reg &0x08 && ~result &0x10) + result = 0x40 | result &0x0F; + else + result = reg <<4 &0x30 | result &0x0F; + return result; +} + +static DECLFW (writeReg) { + if (A &0x020 && A &0x100) { + reg = V; + sync(); + } else + MMC3_writeReg(A, V); +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); + SetWriteHandler(0xF000, 0xFFFF, writeReg); +} + +void Mapper545_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, getPRGBank, NULL, NULL, NULL); + WRAM_init(info, 8); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/546.c b/src/boards/546.c new file mode 100644 index 0000000..e388215 --- /dev/null +++ b/src/boards/546.c @@ -0,0 +1,70 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc1.h" +#include "cartram.h" + +static uint8 reg; + +static void sync () { + MMC1_syncWRAM(0); + if (reg &0x10) + MMC1_syncPRG(0x0F, 0x10); + else + if (reg &0x20) + setprg32(0x8000, reg >>1); + else { + setprg16(0x8000, reg); + setprg16(0xC000, reg); + } + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], reg &0x80? 0: 1); + setchr8(0); + MMC1_syncMirror(); +} + +static DECLFW (writeReg) { + if (!(A &0x0F00)) { + reg = A &0xFF; + sync(); + } + MMC1_writeReg(A, V); +} + +static void reset () { + reg = 0; + MMC1_clear(); +} + +static void power () { + reg = 0; + MMC1_power(); + SetWriteHandler(0x8000, 0x9FFF, writeReg); +} + +void Mapper546_Init (CartInfo *info) { + MMC1_init(info, sync, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL); + WRAM_init(info, 8); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/548.c b/src/boards/548.c new file mode 100644 index 0000000..ca82a20 --- /dev/null +++ b/src/boards/548.c @@ -0,0 +1,105 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "cartram.h" +#include "../fds_apu.h" + +static uint8 reg; +static uint8 latch; +static uint8 counting; +static uint16 counter; + +static SFORMAT stateRegs[] ={ + { ®, 1, "REGM" }, + { &latch, 1, "LATC" }, + { &counting, 1, "IRQA" }, + { &counter, 2 | FCEUSTATE_RLSB, "IRQC" }, + { 0 } +}; + +static void sync () { + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, reg); + setprg16(0xC000, 3); + setchr8(0); +} + +static DECLFW (writeLatch) { + latch = A >>2 &0x03 | A >>3 &0x04; + if (A &4) { + counting = 0; + counter = 0; + X6502_IRQEnd(FCEU_IQEXT); + } else + counting = 1; +} + +static DECLFW (writeReg) { + reg = latch ^0x05; + sync(); +} + +static void FP_FASTAPASS(1) cpuCycle (int a) { + while (a--) { + if (counting) { + if (counter == 23680) + X6502_IRQBegin(FCEU_IQEXT); + else + if (counter == 24320) + X6502_IRQEnd(FCEU_IQEXT); + counter++; + } + } +} + +static void reset () { + FDSSoundReset(); + X6502_IRQEnd(FCEU_IQEXT); + latch = 0x07; + reg = latch ^0x05; + counting = 0; + counter = 0; + sync(); +} + +static void power () { + FDSSoundPower(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x4800, 0x4FFF, writeLatch); + SetWriteHandler(0x5000, 0x57FF, writeReg); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + reset(); +} + +static void stateRestore (int version) { + sync(); +} + +void Mapper548_Init (CartInfo *info) { + WRAM_init(info, 8); + info->Power = power; + info->Reset = reset; + MapIRQHook = cpuCycle; + GameStateRestore = stateRestore; + AddExState(stateRegs, ~0, 0, 0); +} diff --git a/src/boards/549.c b/src/boards/549.c new file mode 100644 index 0000000..18cfa13 --- /dev/null +++ b/src/boards/549.c @@ -0,0 +1,45 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" +#include "../fds_apu.h" + +static void sync () { + setprg8(0x6000, Latch_address >>2 | Latch_address >>3 &0x04); + setprg32(0x8000, 2); + setchr8(0); +} + +static void power() { + Latch_power(); + FDSSoundPower(); +} + +static void reset() { + FDSSoundReset(); + Latch_clear(); +} + +void Mapper549_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; +} diff --git a/src/boards/556.c b/src/boards/556.c index 04fa6b3..3e6dd7f 100644 --- a/src/boards/556.c +++ b/src/boards/556.c @@ -19,312 +19,84 @@ */ /* NES 2.0 Mapper 556 - * Used for the for the 超强小新2+瑪莉家族 7-in-1 (JY-215) multicart. + * Used for the for the 餓狼傳說 激鬥篇 HiK 7-in-1 (JY-215) multicart. */ #include "mapinc.h" +#include "asic_mmc3.h" +#include "asic_vrc2and4.h" +#include "cartram.h" -static uint8 reg[5]; -static uint8 mmc3Reg[8]; -static uint8 mmc3Cmd; -static uint8 mmc3Mirr; -static uint8 mmc3Wram; -static uint8 mmc3IRQLatch; -static uint8 mmc3IRQCount; -static uint8 mmc3IRQa; -static uint8 mmc3IRQReload; -static uint8 vrc4Prg[2]; -static uint8 vrc4Mirr; -static uint8 vrc4Misc; -static uint16 vrc4Chr[8]; -static uint8 vrc4IRQLatch; -static uint8 vrc4IRQa; -static uint8 vrc4IRQCount; -static int16 vrc4IRQCycles; -static uint8 *WRAM = NULL; -static uint32 WRAMSIZE = 0; +static uint8 reg[4]; +static uint8 rIdx; static SFORMAT StateRegs[] = { - { reg, 5, "REGS" }, - { mmc3Reg, 8, "MMC3" }, - { &mmc3Cmd, 1, "M3IX" }, - { &mmc3Mirr, 1, "M3MI" }, - { &mmc3Wram, 1, "M3WR" }, - { &mmc3IRQLatch, 1, "M3RL" }, - { &mmc3IRQCount, 1, "M3CN" }, - { &mmc3IRQa, 1, "M3IQ" }, - { &mmc3IRQReload, 1, "M3IR" }, - { vrc4Prg, 2, "V4PR" }, - { &vrc4Mirr, 1, "V4MI" }, - { &vrc4Misc, 1, "V4MS" }, - { vrc4Chr, 16, "V4CH" }, - { &vrc4IRQLatch, 1, "VILA" }, - { &vrc4IRQa, 1, "VIMO" }, - { &vrc4IRQCount, 1, "VICO" }, - { &vrc4IRQCycles, 2, "VICY" }, + { reg, 4, "REGS" }, + { &rIdx, 1, "INDX" }, { 0 }, }; -static void Sync(void) { - uint32 prgmask = ~reg[3] & 0x3F; - uint32 prgbase = ((reg[3] & 0x40) << 2) | reg[1]; - uint32 chrmask = 0xFF >> (~reg[2] & 0x0F); - uint32 chrbase = ((reg[3] & 0x40) << 6) | ((reg[2] & 0xF0) << 4) | reg[0]; - uint32 cbase = 0; /* prg/chr bank flip flag */ - - if (~reg[2] & 0x80) { - /* MMC3 */ - cbase = (mmc3Cmd << 8) & 0x4000; - setprg8(0x8000 ^ cbase, (prgbase & ~prgmask) | (mmc3Reg[6] & prgmask)); - setprg8(0xA000, (prgbase & ~prgmask) | (mmc3Reg[7] & prgmask)); - setprg8(0xC000 ^ cbase, (prgbase & ~prgmask) | (0xFE & prgmask)); - setprg8(0xE000, (prgbase & ~prgmask) | (0xFF & prgmask)); - - cbase = (mmc3Cmd << 5) & 0x1000; - setchr1(0x0000 ^ cbase, (chrbase & ~chrmask) | ((mmc3Reg[0] & 0xFE) & chrmask)); - setchr1(0x0400 ^ cbase, (chrbase & ~chrmask) | ((mmc3Reg[0] | 0x01) & chrmask)); - setchr1(0x0800 ^ cbase, (chrbase & ~chrmask) | ((mmc3Reg[1] & 0xFE) & chrmask)); - setchr1(0x0C00 ^ cbase, (chrbase & ~chrmask) | ((mmc3Reg[1] | 0x01) & chrmask)); - setchr1(0x1000 ^ cbase, (chrbase & ~chrmask) | (mmc3Reg[2] & chrmask)); - setchr1(0x1400 ^ cbase, (chrbase & ~chrmask) | (mmc3Reg[3] & chrmask)); - setchr1(0x1800 ^ cbase, (chrbase & ~chrmask) | (mmc3Reg[4] & chrmask)); - setchr1(0x1C00 ^ cbase, (chrbase & ~chrmask) | (mmc3Reg[5] & chrmask)); - - setmirror((mmc3Mirr & 0x01) ^ 1); +static void sync (void) { + int prgAND = ~reg[3] &0x3F; + int chrAND = 0xFF >>(~reg[2] &0xF); + int prgOR = (reg[1] | reg[3] <<2 &0x100) &~prgAND; + int chrOR = (reg[0] | reg[2] <<4 &0x0F00 | reg[3] <<6 &0x1000) &~chrAND; + if (reg[2] &0x80) { + VRC24_syncWRAM(0); + VRC24_syncPRG(prgAND, prgOR); + VRC24_syncCHR(chrAND, chrOR); + VRC24_syncMirror(); } else { - /* VRC4 mode */ - cbase = (vrc4Misc << 13) & 0x4000; - setprg8(0x8000 ^ cbase, (prgbase & ~prgmask) | (vrc4Prg[0] & prgmask)); - setprg8(0xA000, (prgbase & ~prgmask) | (vrc4Prg[1] & prgmask)); - setprg8(0xC000 ^ cbase, (prgbase & ~prgmask) | (0xFE & prgmask)); - setprg8(0xE000, (prgbase & ~prgmask) | (0xFF & prgmask)); - - setchr1(0x0000, (chrbase & ~chrmask) | (vrc4Chr[0] & chrmask)); - setchr1(0x0400, (chrbase & ~chrmask) | (vrc4Chr[1] & chrmask)); - setchr1(0x0800, (chrbase & ~chrmask) | (vrc4Chr[2] & chrmask)); - setchr1(0x0C00, (chrbase & ~chrmask) | (vrc4Chr[3] & chrmask)); - setchr1(0x1000, (chrbase & ~chrmask) | (vrc4Chr[4] & chrmask)); - setchr1(0x1400, (chrbase & ~chrmask) | (vrc4Chr[5] & chrmask)); - setchr1(0x1800, (chrbase & ~chrmask) | (vrc4Chr[6] & chrmask)); - setchr1(0x1C00, (chrbase & ~chrmask) | (vrc4Chr[7] & chrmask)); - - switch (vrc4Mirr & 0x03) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_0); break; - case 3: setmirror(MI_1); break; - } + MMC3_syncWRAM(0); + MMC3_syncPRG(prgAND, prgOR); + MMC3_syncCHR(chrAND, chrOR); + MMC3_syncMirror(); } } -static DECLFW(writeMMC3) { - switch (A & 0xE001) { - case 0x8000: - mmc3Cmd = V; - Sync(); - break; - case 0x8001: - mmc3Reg[mmc3Cmd & 7] = V; - Sync(); - break; - case 0xA000: - mmc3Mirr = V; - Sync(); - break; - case 0xA001: - mmc3Wram = V; - Sync(); - break; - case 0xC000: - mmc3IRQLatch = V; - break; - case 0xC001: - mmc3IRQReload = 1; - break; - case 0xE000: - mmc3IRQa = 0; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xE001: - mmc3IRQa = 1; - break; +static void applyMode (uint8 clear) { + if (reg[2] &0x80) + VRC4_activate(clear, sync, 0x05, 0x0A, 1, NULL, NULL, NULL, NULL, NULL); + else + MMC3_activate(clear, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, NULL); +} + +static DECLFW(writeReg) { + if (~reg[3] &0x80) { + reg[rIdx++ &3] = V; + if (rIdx == 3) + applyMode(1); + else + sync(); } } -static DECLFW(writeVRC4) { - uint8 index; - A = (A & 0xF000) | ((A >> 2) & 3) | (A & 3); - switch (A & 0xF000) { - case 0x8000: - case 0xA000: - vrc4Prg[(A >> 13) & 1] = V; - Sync(); - break; - case 0x9000: - if (~A & 2) { - vrc4Mirr = V; - } else if (~A & 1) { - vrc4Misc = V; - } - Sync(); - break; - case 0xF000: - switch (A & 3) { - case 0: - vrc4IRQLatch = (vrc4IRQLatch & 0xF0) | (V & 0x0F); - break; - case 1: - vrc4IRQLatch = (vrc4IRQLatch & 0x0F) | (V << 4); - break; - case 2: - vrc4IRQa = V; - if (vrc4IRQa & 0x02) { - vrc4IRQCount = vrc4IRQLatch; - vrc4IRQCycles = 341; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 3: - vrc4IRQa = (vrc4IRQa & ~0x02) | ((vrc4IRQa << 1) & 0x02); - X6502_IRQEnd(FCEU_IQEXT); - break; - } - break; - default: - index = ((A - 0xB000) >> 11) | ((A >> 1) & 1); - if (A & 1) { - vrc4Chr[index] = (vrc4Chr[index] & 0x0F) | (V << 4); - } else { - vrc4Chr[index] = (vrc4Chr[index] & ~0x0F) | (V & 0x0F); - } - Sync(); - break; - } -} - -static DECLFW(M556WriteReg) { - if (~reg[3] & 0x80) { - reg[reg[4] & 3] = V; - reg[4]++; - Sync(); - } -} - -static DECLFW(M556Write) { - if (~reg[2] & 0x80) { - writeMMC3(A, V); - } else { - writeVRC4(A, V); - } -} - -static void FP_FASTAPASS(1) M556CPUHook(int a) { - int count = a; - - if (~reg[2] & 0x80) { - return; - } - - /* VRC4 IRQ mode */ - while (count--) { - if ((vrc4IRQa & 0x02) && ((vrc4IRQa & 0x04) || ((vrc4IRQCycles -= 3) <= 0))) { - if (~vrc4IRQa & 0x04) { - vrc4IRQCycles += 341; - } - if (!++vrc4IRQCount) { - vrc4IRQCount = vrc4IRQLatch; - X6502_IRQBegin(FCEU_IQEXT); - } - } - } -} - -static void M556HBHook(void) { - int count = mmc3IRQCount; - - if (reg[2] & 0x80) { - return; - } - - /* MMC3 IRQ mode */ - if (!count || mmc3IRQReload) { - mmc3IRQCount = mmc3IRQLatch; - } else { - mmc3IRQCount--; - } - if (count && !mmc3IRQCount && mmc3IRQa) { - X6502_IRQBegin(FCEU_IQEXT); - } - mmc3IRQReload = 0; -} - -static void M556Reset(void) { - int i; - for (i = 0; i < 5; i++) { - reg[i] = 0; - } +static void reset (void) { + reg[0] = reg[1] = reg[3] = 0; reg[2] = 0x0F; - Sync(); + rIdx = 0; + applyMode(1); } -static void M556Power(void) { - int i; - for (i = 0; i < 5; i++) { - reg[i] = 0; - } - for (i = 0; i < 8; i++) { - mmc3Reg[i] = 0; - } - for (i = 0; i < 2; i++) { - vrc4Prg[i] = 0; - } - for (i = 0; i < 8; i++) { - vrc4Chr[i] = 0; - } - mmc3Cmd = mmc3Mirr = mmc3Wram = mmc3IRQLatch = mmc3IRQCount = mmc3IRQa = mmc3IRQReload = 0; - vrc4Mirr = vrc4Misc = vrc4IRQLatch = vrc4IRQa = vrc4IRQCount = vrc4IRQCycles = 0; +static void power (void) { + reg[0] = reg[1] = reg[3] = 0; reg[2] = 0x0F; - Sync(); - - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x5000, 0x5FFF, M556WriteReg); - SetWriteHandler(0x8000, 0xFFFF, M556Write); - - if (WRAM) { - setprg8r(0x10, 0x6000, 0); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - } + rIdx = 0; + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x5000, 0x5FFF, writeReg); + applyMode(1); } -static void M556Close(void) { - if (WRAM) { - FCEU_gfree(WRAM); - } - WRAM = NULL; +static void restore (int version) { + applyMode(0); } -static void StateRestore(int version) { - Sync(); -} - -void Mapper556_Init(CartInfo *info) { - info->Reset = M556Reset; - info->Power = M556Power; - info->Close = M556Close; - MapIRQHook = M556CPUHook; - GameHBIRQHook = M556HBHook; - GameStateRestore = StateRestore; +void Mapper556_Init (CartInfo *info) { + MMC3_addExState(); + VRC24_addExState(); + WRAM_init(info, 8); + info->Reset = reset; + info->Power = power; + GameStateRestore = restore; AddExState(StateRegs, ~0, 0, 0); - - WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - } } diff --git a/src/boards/557.c b/src/boards/557.c new file mode 100644 index 0000000..498bfea --- /dev/null +++ b/src/boards/557.c @@ -0,0 +1,37 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_n118.h" +#include "cartram.h" + +static void sync () { + setprg8r(0x10, 0x6000, 0); + N118_syncPRG(0x0F, 0x00); + setchr8(0); + setmirror(N118_getCHRBank(7) &0x20? MI_H: MI_V); +} + +void Mapper557_Init (CartInfo *info) { + N118_init(info, sync, NULL, NULL); + WRAM_init(info, 8); +} diff --git a/src/boards/559.c b/src/boards/559.c index a9a2c15..5baeaff 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,34 +38,32 @@ static void sync () { setmirrorw(nt[0] &1, nt[1] &1, nt[2] &1, nt[3] &1); } -int Mapper559_getPRGBank(int bank) { +static int getPRGBank (uint8 bank) { return bank ==2? prg: VRC24_getPRGBank(bank); } -DECLFW(Mapper559_externalSelect) { +static DECLFW (externalSelect) { if (A &4) nt[A &3] =V; else prg =V; - VRC24_Sync(); + sync(); } -DECLFW(Mapper559_nibblizeData) { +static DECLFW (nibblizeData) { VRC24_writeReg(A, V >>(A &0x400? 4: 0)); } -void Mapper559_power (void) { +static void power (void) { nt[0] =nt[1] =0xE0; nt[2] =nt[3] =0xE1; prg =0xFE; VRC24_power(); - SetWriteHandler(0xB000, 0xFFFF, Mapper559_nibblizeData); + SetWriteHandler(0xB000, 0xFFFF, nibblizeData); } void Mapper559_Init (CartInfo *info) { - VRC24_init(info, sync, 0x400, 0x800, 1, 1, 0); - info->Power =Mapper559_power; - VRC24_GetPRGBank =Mapper559_getPRGBank; - VRC24_ExternalSelect =Mapper559_externalSelect; + VRC4_init(info, sync, 0x400, 0x800, 1, getPRGBank, NULL, NULL, NULL, externalSelect); + info->Power =power; AddExState(stateRegs, ~0, 0, 0); } diff --git a/src/boards/563.c b/src/boards/563.c index a074442..1db54d4 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; @@ -36,7 +36,7 @@ static void sync () { VRC24_syncMirror(); } -DECLFW(Mapper563_writeIRQ) { +static DECLFW (Mapper563_writeIRQ) { X6502_IRQEnd(FCEU_IQEXT); switch(A &0x1C) { case 0x0C: irqEnabled =0; break; @@ -49,15 +49,15 @@ static void Mapper563_scanline (void) { /* Actually, a sixteen-stage counter tri if (!(++irqCounter &1) && irqEnabled) X6502_IRQBegin(FCEU_IQEXT); } -void Mapper563_power(void) { - irqEnabled =irqCounter =0; +static void Mapper563_power (void) { + irqEnabled = irqCounter =0; VRC24_power(); SetWriteHandler(0xF000, 0xFFFF, Mapper563_writeIRQ); } 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; + info->Power = Mapper563_power; GameHBIRQHook = Mapper563_scanline; } diff --git a/src/boards/564.c b/src/boards/564.c new file mode 100644 index 0000000..94fa23c --- /dev/null +++ b/src/boards/564.c @@ -0,0 +1,45 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + setprg32(0x8000, Latch_data); + setchr8(0); + if (Latch_data &0x20) + setmirror(Latch_data &0x10? MI_1: MI_0); + else + setmirror(Latch_data &0x10? MI_H: MI_V); +} + +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { /* After the lock bit is set, only update the (mode-specific) inner bank bits. */ + if (Latch_data &0x20) { + if (Latch_data &0x08) + *newValue = Latch_data &0x28 | *newValue &~0x28; /* AOROM */ + else + *newValue = Latch_data &0x2C | *newValue &~0x2C; /* ANROM */ + } +} + +void Mapper564_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); + info->Reset = Latch_clear; +} diff --git a/src/boards/565.c b/src/boards/565.c new file mode 100644 index 0000000..ff526d7 --- /dev/null +++ b/src/boards/565.c @@ -0,0 +1,78 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_vrc2and4.h" + +static uint8 irqEnabled; +static uint8 irqCounter; +static uint8 irqPrescaler; + +static SFORMAT stateRegs[] ={ + { &irqEnabled, 1, "IRQE" }, + { &irqCounter, 1, "CNTR" }, + { &irqPrescaler, 1, "IRQP" }, + { 0 } +}; + +static void sync () { + VRC24_syncPRG(0x01F, 0x000); + VRC24_syncCHR(0x1FF, 0x000); + VRC24_syncMirror(); +} + +static DECLFW (writeIRQ) { + switch(A &0x0C) { + case 0: + irqCounter = V; + irqPrescaler = 0; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 4: + irqEnabled = V; + break; + } +} + +static void FP_FASTAPASS(1) cpuCycle (int a) { + while (a--) { + if (irqEnabled &1) { + irqPrescaler++; + if (irqPrescaler == 64 && !++irqCounter) X6502_IRQBegin(FCEU_IQEXT); + if (irqPrescaler == 112) irqPrescaler = 0; + } else { + irqPrescaler = 0; + X6502_IRQEnd(FCEU_IQEXT); + } + } +} + +static void power (void) { + irqEnabled = irqCounter = irqPrescaler = 0; + VRC24_power(); + SetWriteHandler(0xF000, 0xFFFF, writeIRQ); +} + +void Mapper565_Init (CartInfo *info) { + VRC2_init(info, sync, 0x08, 0x04, NULL, NULL, NULL, NULL); + AddExState(stateRegs, ~0, 0, 0); + info->Power = power; + MapIRQHook = cpuCycle; +} diff --git a/src/boards/566.c b/src/boards/566.c new file mode 100644 index 0000000..592fd11 --- /dev/null +++ b/src/boards/566.c @@ -0,0 +1,61 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync () { + int prgAND = reg &0x04? 0x0F: 0x1F; + int chrAND = reg &0x02? 0x7F: 0xFF; + int prgOR = reg <<4 &0x10 | reg <<2 &0x20 | reg <<1 &0xC0; + int chrOR = reg <<7 &0x80 | reg <<4 &0x700; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + if (reg &0x80) + setmirror(MMC3_getCHRBank(0) &0x80? MI_1: MI_0); + else + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +void Mapper566_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/567.c b/src/boards/567.c new file mode 100644 index 0000000..431c54a --- /dev/null +++ b/src/boards/567.c @@ -0,0 +1,71 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync () { + MMC3_syncPRG(0x0F, reg <<4); + if (reg == 0x0F) + MMC3_syncCHR(0x1FF, 0x400); + else + MMC3_syncCHR(0x07F, reg <<7 &0x380); + MMC3_syncMirror(); +} + +static int getPRGBank (uint8 bank) { + if (reg == 0x08) { + return MMC3_getPRGBank(bank &1) &~3 | bank &3; + } else + return MMC3_getPRGBank(bank); +} + +static int getCHRBank (uint8 bank) { + if (reg == 0x0F) + return MMC3_getCHRBank(bank &6 | bank >>1 &1) <<1 | bank &1; + else + return MMC3_getCHRBank(bank); +} + +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +void Mapper567_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_SHARP, getPRGBank, getCHRBank, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/568.c b/src/boards/568.c new file mode 100644 index 0000000..bec0ca5 --- /dev/null +++ b/src/boards/568.c @@ -0,0 +1,75 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; +static uint8 pad; + +static DECLFR (readPad) { + return CartBR(A &~0xF | pad &0xF); +} + +static void sync () { + int prgAND = reg &0x20? 0x1F: 0x0F; + int chrAND = reg &0x20? 0xFF: 0x7F; + int prgOR = reg <<1; + int chrOR = reg <<4; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); + SetReadHandler(0x8000, 0xFFFF, reg &0x40? readPad: CartBR); +} + +static int getPRGBank (uint8 bank) { + if (reg &0x02) { + int mask = reg &0x01? 3: 1; + return MMC3_getPRGBank(0) &~mask | bank &mask; + } else + return MMC3_getPRGBank(bank); +} + +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset () { + reg = 0; + pad++; + MMC3_clear(); +} + +static void power () { + reg = 0; + pad = 0; + MMC3_power(); +} + +void Mapper568_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, getPRGBank, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/boards/569.c b/src/boards/569.c new file mode 100644 index 0000000..a6f0dd5 --- /dev/null +++ b/src/boards/569.c @@ -0,0 +1,70 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync () { + int chrAND = reg &0x04? 0x1FF: reg &0x02? 0xFF: 0x7F; + int chrOR = reg <<7; + MMC3_syncPRG(0x0F, reg <<4 &~0x0F); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static int getPRGBank (uint8 bank) { + if (reg &0x08) { + return MMC3_getPRGBank(0) &~3 | bank &3; + } else + return MMC3_getPRGBank(bank); +} + +static int getCHRBank (uint8 bank) { + if (reg &0x04) + return MMC3_getCHRBank(bank &6 | bank >>1 &1) <<1 | bank &1; + else + return MMC3_getCHRBank(bank); +} + +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +void Mapper569_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_SHARP, getPRGBank, getCHRBank, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/570.c b/src/boards/570.c new file mode 100644 index 0000000..baaa7cc --- /dev/null +++ b/src/boards/570.c @@ -0,0 +1,59 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_vrc2and4.h" + +static uint8 reg; + +static void sync () { + int prgAND = 0x0F; + int chrAND = reg &0x03? 0x0FF: 0x1FF; + int prgOR = reg <<4; + int chrOR = !!(reg &0x03)*0x200 | !!(reg &0x02)*0x100; + VRC24_syncPRG(prgAND, prgOR &~prgAND); + VRC24_syncCHR(chrAND, chrOR &~chrAND); + VRC24_syncMirror(); +} + +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset () { + reg = 0; + VRC24_clear(); +} + +static void power () { + reg = 0; + VRC24_power(); + SetWriteHandler(0x5000, 0x5FFF, writeReg); +} + +void Mapper570_Init(CartInfo *info) { + VRC4_init(info, sync, 1, 2, 1, NULL, NULL, NULL, NULL, NULL); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/571.c b/src/boards/571.c new file mode 100644 index 0000000..c759426 --- /dev/null +++ b/src/boards/571.c @@ -0,0 +1,72 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_vrc2and4.h" + +static uint8 reg; + +static void sync () { + int prgAND = reg &0x10? 0x1F: 0x0F; + int chrAND = reg &0x10? 0xFF: 0x7F; + int prgOR = reg <<1; + int chrOR = reg <<4; + if (reg &0x20) + VRC24_syncPRG(prgAND, prgOR &~prgAND); + else + if (reg &0x6) + setprg32(0x8000, reg >>1); + else { + setprg16(0x8000, reg); + setprg16(0xC000, reg); + } + VRC24_syncCHR(chrAND, chrOR &~chrAND); + VRC24_syncMirror(); + if (reg &0x10) + VRC24_reconfigure(8, 4); + else + VRC24_reconfigure(4, 8); +} + +static DECLFW (writeReg) { + if (~reg &0x01) { + reg = A &0xFF; + sync(); + } +} + +static void reset () { + reg = 0; + sync(); +} + +static void power () { + reg = 0; + VRC24_power(); +} + +void Mapper571_Init (CartInfo *info) { + VRC4_init(info, sync, 4, 8, 1, NULL, NULL, NULL, writeReg, NULL); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/572.c b/src/boards/572.c new file mode 100644 index 0000000..44ccb6c --- /dev/null +++ b/src/boards/572.c @@ -0,0 +1,60 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync () { + int prgAND = 0x1F; + int chrAND = 0x7F; + int prgOR = reg <<5; + int chrOR = reg <<7; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + if (~reg &0x08) { + reg = A &0xFF; + sync(); + } +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +void Mapper572_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/573.c b/src/boards/573.c new file mode 100644 index 0000000..9829cce --- /dev/null +++ b/src/boards/573.c @@ -0,0 +1,48 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static DECLFR(readOB) { + return X.DB; +} + +static void sync () { + if (Latch_address &0x02) { + setprg16(0x8000, Latch_address <<3 &0x10 | Latch_data &0x0F); + setprg16(0xC000, Latch_address <<3 &0x10 | 0x0F); + } else { + setprg16(0x8000, Latch_address <<3 &0x18 | Latch_data &0x07); + setprg16(0xC000, Latch_address <<3 &0x18 | 0x07); + } + SetReadHandler(0x8000, 0xFFFF, Latch_address &0x10 && ROM_size >8? readOB: CartBR); + setchr8(0); +} + +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { + if (Latch_address &0x20) *newAddress = Latch_address; /* Once bit 5 is set, only the inner bank bits can be modified. */ + *newValue &= romValue; /* AND-type bus conflicts */ +} + +void Mapper573_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); + info->Reset = Latch_clear; +} diff --git a/src/boards/574.c b/src/boards/574.c new file mode 100644 index 0000000..089a73a --- /dev/null +++ b/src/boards/574.c @@ -0,0 +1,46 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_address &0x40) /* AOROM */ + setprg32(0x8000, Latch_address >>2 &~0x07 | Latch_data &0x07); + else + if (Latch_address &0x20) /* ANROM */ + setprg32(0x8000, Latch_address >>2 &~0x03 | Latch_data &0x03); + else /* NROM-256 */ + setprg32(0x8000, Latch_address >>2 &~0x03 | Latch_address &0x03); + setchr8(0); + if (Latch_address &0x60) /* AxROM */ + setmirror(Latch_data &0x10? MI_1: MI_0); + else + setmirror(Latch_data &0x10? MI_H: MI_V); +} + +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { /* After the lock bit is set, only update the data bits and the lowest two address bits. */ + if (Latch_address &0x80) *newAddress = Latch_address &~0x03 | *newAddress &0x03; +} + +void Mapper574_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); + info->Reset = Latch_clear; +} diff --git a/src/boards/575.c b/src/boards/575.c new file mode 100644 index 0000000..b652f5c --- /dev/null +++ b/src/boards/575.c @@ -0,0 +1,38 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if ((Latch_address &0x06) == 0x06) + setprg32(0x8000, Latch_address >>1); + else { + setprg16(0x8000, Latch_address); + setprg16(0xC000, Latch_address); + } + setchr8(Latch_address); + setmirror(Latch_address &0x08? MI_H: MI_V); +} + +void Mapper575_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/576.c b/src/boards/576.c new file mode 100644 index 0000000..837b822 --- /dev/null +++ b/src/boards/576.c @@ -0,0 +1,37 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_address &0x100) { + setprg16(0x8000, Latch_address >>4); + setprg16(0xC000, Latch_address >>4); + } else + setprg32(0x8000, Latch_address >>5); + setchr8(Latch_address); + setmirror(Latch_address &0x200? MI_H: MI_V); +} + +void Mapper576_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/577.c b/src/boards/577.c new file mode 100644 index 0000000..a969163 --- /dev/null +++ b/src/boards/577.c @@ -0,0 +1,52 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static uint8 pad; + +static DECLFR (readOB) { + return X.DB; +} + +static void sync () { + setprg16(0x8000, Latch_address); + setprg16(0xC000, Latch_address); + SetReadHandler(0x8000, 0xFFFF, Latch_address &pad &0x30? readOB: CartBR); + setchr8(Latch_address >>1); +} + +static void power () { + pad = 0; + Latch_power(); +} + +static void reset () { + pad += 0x10; + Latch_clear(); +} + +void Mapper577_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/boards/578.c b/src/boards/578.c new file mode 100644 index 0000000..298b516 --- /dev/null +++ b/src/boards/578.c @@ -0,0 +1,60 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync () { + int prgAND = reg &0x02 && reg &0x04? 0x1F: 0x0F; + int chrAND = reg &0x02 && reg &0x04? 0xFF: 0x7F; + int prgOR = reg <<4; + int chrOR = reg <<7; + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + reg = V; + sync(); +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + int i; + reg = 0; + MMC3_power(); + for (i = 0x8000; i < 0xFFFF; i +=4) SetWriteHandler(i |2, i |3, writeReg); +} + +void Mapper578_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/579.c b/src/boards/579.c new file mode 100644 index 0000000..2170c21 --- /dev/null +++ b/src/boards/579.c @@ -0,0 +1,49 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + int prg = Latch_address >>2 &0x1F; + if (Latch_address &0x200) { + setprg16(0x8000, prg); + setprg16(0xC000, prg |7); + } else { + if (Latch_address &0x001) + setprg32(0x8000, prg >>1); + else { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } + } + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], Latch_address &0x80? 0: 1); + setchr8(0); + setmirror(Latch_address &0x02? MI_H: MI_V); +} + +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { /* Once bit 9 is set, only the inner bank bits can be modified. */ + if (Latch_address &0x200) *newAddress = *newAddress &0x01C | Latch_address &~0x01C; +} + +void Mapper579_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); + info->Reset = Latch_clear; +} diff --git a/src/boards/580.c b/src/boards/580.c new file mode 100644 index 0000000..724c297 --- /dev/null +++ b/src/boards/580.c @@ -0,0 +1,39 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_address &0x01) { + setprg32(0x8000, Latch_address >>5); + setchr8(Latch_address >>3 &~3 | Latch_address >>2 &3); + } else { + setprg16(0x8000, Latch_address >>4); + setprg16(0xC000, Latch_address >>4); + setchr8(Latch_address >>3 &~1 | Latch_address >>2 &1); + } + setmirror(Latch_address &0x02? MI_H: MI_V); +} + +void Mapper580_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/581.c b/src/boards/581.c new file mode 100644 index 0000000..e35c8ac --- /dev/null +++ b/src/boards/581.c @@ -0,0 +1,48 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + int prg = Latch_address >>1 &0x20 | Latch_address &0x1F; + if (Latch_address &0x20) { + if (Latch_address &0x01) { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } else + setprg32(0x8000, prg >>1); + } else { + setprg16(0x8000, prg); + setprg16(0xC000, prg |7); + } + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], Latch_address &0x20? 0: 1); + setchr8(0); + setmirror(Latch_address &0x80? MI_H: MI_V); +} + +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { /* The upper two address bits are only updated on a falling edge of A5. */ + if (!(Latch_address &0x20 && ~*newAddress &0x20)) *newAddress = *newAddress &~0xC0 | Latch_address &0xC0; +} + +void Mapper581_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); + info->Reset = Latch_clear; +} diff --git a/src/boards/582.c b/src/boards/582.c new file mode 100644 index 0000000..f12ce07 --- /dev/null +++ b/src/boards/582.c @@ -0,0 +1,56 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[4]; + +static void sync () { + setprg16(0x8000, reg[1] <<3 | reg[0] &0x07); + setprg16(0xC000, reg[3] <<3 | reg[2] &0x07); + setchr8(0); +} + +static DECLFW (writeReg) { + reg[A >>13 &3] = V; + sync(); +} + +static void reset () { + reg[0] = reg[1] = reg[2] = reg[3] = 0xFF; + sync(); +} + +static void power () { + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, writeReg); + reset(); +} + +static void stateRestore (int version) { + sync(); +} + +void Mapper582_Init (CartInfo *info) { + info->Reset = reset; + info->Power = power; + GameStateRestore = stateRestore; + AddExState(reg, 4, 0, "REGS"); +} diff --git a/src/boards/583.c b/src/boards/583.c new file mode 100644 index 0000000..37ef1f4 --- /dev/null +++ b/src/boards/583.c @@ -0,0 +1,50 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + int prg = Latch_address &~0xF | Latch_address <<3 &0x08; + if (Latch_address &0x20) { + setprg32(0x8000, prg >>1 &~7 | Latch_data &7); + setmirror(Latch_data &0x10? MI_1: MI_0); + } else { + if (Latch_address &0x10 && Latch_address &0x08) { + setprg16(0x8000, prg &~0x03 | Latch_data &0x03); + setprg16(0xC000, prg | 0x03); + setmirror(MI_H); + } else { + setprg16(0x8000, prg &~0x07 | Latch_data &0x07); + setprg16(0xC000, prg | 0x07); + setmirror(MI_V); + } + } + setchr8(0); +} + +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { /* The address bits are only updated on a rising edge of A7. */ + if (!(~Latch_address &0x80 && *newAddress &0x80)) *newAddress = Latch_address; +} + +void Mapper583_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); + info->Reset = Latch_clear; +} diff --git a/src/boards/584.c b/src/boards/584.c new file mode 100644 index 0000000..295cbde --- /dev/null +++ b/src/boards/584.c @@ -0,0 +1,59 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[2]; + +static void sync () { + if (reg[0] &0x20) + setprg32(0x8000, reg[0] >>1); + else { + setprg16(0x8000, reg[0]); + setprg16(0xC000, reg[0]); + } + setchr8(reg[1]); + setmirror(reg[1] &0x20? MI_V: MI_H); +} + +static DECLFW (writeReg) { + if (A &0x100) { + reg[A >>13 &1] = V; + sync(); + } +} + +static void power () { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x4020, 0x7FFF, writeReg); + reg[0] = reg[1] = 0; + sync(); +} + +static void stateRestore (int version) { + sync(); +} + +void Mapper584_Init (CartInfo *info) { + info->Reset = power; + info->Power = power; + GameStateRestore = stateRestore; + AddExState(reg, 2, 0, "REGS"); +} diff --git a/src/boards/585.c b/src/boards/585.c new file mode 100644 index 0000000..60c3761 --- /dev/null +++ b/src/boards/585.c @@ -0,0 +1,57 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static uint8 pad; + +static DECLFR (readOB) { + return X.DB; +} + +static void sync () { + if (Latch_address &0x01) + setprg32(0x8000, Latch_address >>2); + else { + setprg16(0x8000, Latch_address >>1); + setprg16(0xC000, Latch_address >>1); + } + SetReadHandler(0x8000, 0xFFFF, Latch_address &pad &0x60? readOB: CartBR); + setchr8(Latch_address >>1); + setmirror(Latch_address &0x10? MI_V: MI_H); +} + +static void power () { + pad = 0; + Latch_power(); +} + +static void reset () { + pad += 0x20; + Latch_clear(); +} + +void Mapper585_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/boards/586.c b/src/boards/586.c new file mode 100644 index 0000000..3872a9b --- /dev/null +++ b/src/boards/586.c @@ -0,0 +1,37 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_address &0x08) { + setprg16(0x8000, Latch_address); + setprg16(0xC000, Latch_address); + } else + setprg32(0x8000, Latch_address >>1); + setchr8(Latch_address); + setmirror(Latch_address &0x08? MI_V: MI_H); +} + +void Mapper586_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/587.c b/src/boards/587.c new file mode 100644 index 0000000..4c6c251 --- /dev/null +++ b/src/boards/587.c @@ -0,0 +1,65 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[2]; + +static void sync () { + if (reg[0] &0x02) { + setprg16(0x8000, reg[0] &~0x07 | reg[1] &0x07); + setprg16(0xC000, reg[0] |0x07); + } else { + if (reg[0] &0x80) + setprg32(0x8000, reg[0] >>1 &~0x03 | reg[1] &0x03); + else { + setprg16(0x8000, reg[0] &~0x07 | reg[1] &0x07); + setprg16(0xC000, reg[0] &~0x07 | reg[1] &0x07); + } + } + setchr8(0); + if (reg[0] &0x04) + setmirror(reg[1] &0x10? MI_1: MI_0); + else + setmirror(reg[0] &0x01? MI_H: MI_V); +} + +static DECLFW (writeReg) { + reg[reg[0] &0x80? 1: 0] = V; + sync(); +} + +static void power () { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, writeReg); + reg[0] = reg[1] = 0; + sync(); +} + +static void stateRestore (int version) { + sync(); +} + +void Mapper587_Init (CartInfo *info) { + info->Reset = power; + info->Power = power; + GameStateRestore = stateRestore; + AddExState(reg, 2, 0, "REGS"); +} diff --git a/src/boards/588.c b/src/boards/588.c new file mode 100644 index 0000000..4a7802e --- /dev/null +++ b/src/boards/588.c @@ -0,0 +1,53 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[2]; + +static void sync () { + setprg8(0x6000, reg[1] &0x07 |0x08); + setprg32(0x8000, reg[0] >>4 &0x07); + setchr8(reg[0] &0x0F); + setmirror(reg[0] &0x80? MI_H: MI_V); +} + +static DECLFW (writeReg) { + reg[A >>12 &1] = V; + sync(); +} + +static void power () { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0xE000, 0xFFFF, writeReg); + reg[0] = reg[1] = 0; + sync(); +} + +static void stateRestore (int version) { + sync(); +} + +void Mapper588_Init (CartInfo *info) { + info->Reset = power; + info->Power = power; + GameStateRestore = stateRestore; + AddExState(reg, 2, 0, "REGS"); +} diff --git a/src/boards/589.c b/src/boards/589.c new file mode 100644 index 0000000..6610761 --- /dev/null +++ b/src/boards/589.c @@ -0,0 +1,43 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_address &0x20) { /* First chip: 256 KiB */ + setprg16(0x8000, Latch_address >>1 &0x08 | Latch_data &0x07); + setprg16(0xC000, Latch_address >>1 &0x08 | 0x07); + } else { /* Second chip: 128 KiB (boot) */ + setprg16(0x8000, 0x10 | Latch_address >>1 &0x07); + setprg16(0xC000, 0x10 | Latch_address >>1 &0x07); + } + setchr8(0); + setmirror(Latch_address &1? MI_H: MI_V); +} + +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { /* The address bits are only updated on a falling edge of D3. */ + if (!(Latch_data &0x08 && ~*newValue &0x08)) *newAddress = Latch_address; +} + +void Mapper589_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); + info->Reset = Latch_clear; +} diff --git a/src/boards/590.c b/src/boards/590.c new file mode 100644 index 0000000..2d90cb1 --- /dev/null +++ b/src/boards/590.c @@ -0,0 +1,37 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if (Latch_data &0x08) + setprg32(0x8000, Latch_data >>1); + else { + setprg16(0x8000, Latch_data); + setprg16(0xC000, Latch_data); + } + setchr8(Latch_data); +} + +void Mapper590_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/591.c b/src/boards/591.c new file mode 100644 index 0000000..dc417d2 --- /dev/null +++ b/src/boards/591.c @@ -0,0 +1,38 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + if ((Latch_address &0x0C) == 0x0C) + setprg32(0x8000, Latch_address >>2); + else { + setprg16(0x8000, Latch_address >>1); + setprg16(0xC000, Latch_address >>1); + } + setchr8(Latch_address); + setmirror(Latch_address &0x08? MI_V: MI_H); +} + +void Mapper591_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/592.c b/src/boards/592.c new file mode 100644 index 0000000..3c91f35 --- /dev/null +++ b/src/boards/592.c @@ -0,0 +1,34 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + setprg16(0x8000, Latch_data); + setprg16(0xC000, Latch_data); + setchr8(Latch_data); + setmirror(Latch_data &0x08? MI_H: MI_V); +} + +void Mapper592_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/594.c b/src/boards/594.c new file mode 100644 index 0000000..be0c8a7 --- /dev/null +++ b/src/boards/594.c @@ -0,0 +1,132 @@ +/* FCEUmm - 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" +#include "fifo.h" +#include "msm6585.h" + +static uint8 reg[4]; +static FIFO fifo; +static MSM6585 adpcm; +static int32 soundOffset = 0; + +static void sync () { + int prgAND = 0x3F; + int chrAND = reg[2] &0xC0? 0x0FF: 0x1FF; + int prgOR = (reg[2] &0x40? 0x0C0: 0x000) | (reg[2] &0x80? 0x100: 0x000); + int chrOR = (reg[2] &0x40? 0x200: 0x000) | (reg[2] &0x80? 0x300: 0x000); + setprg8(0x6000, reg[0] | prgOR); + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static int getCHRBank (uint8 bank) { + return MMC3_getCHRBank(bank) | bank <<6 &0x100; +} + +static DECLFR (readADPCM) { + return FIFO_halfFull(&fifo)? 0x00: 0x40; +} + +static DECLFW (writeADPCM) { + if (A &1) { + MSM6585_setRate(&adpcm, V >>6); + FIFO_reset(&fifo); + } else + FIFO_add(&fifo, V); +} + +static int serveADPCM (void) { + return FIFO_retrieve(&fifo); +} + +static DECLFW (writeReg) { + reg[A >>12 &2 | A &1] = V; + sync(); +} + +static void reset () { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + MMC3_clear(); + FIFO_reset(&fifo); + MSM6585_reset(&adpcm); +} + +static void power () { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + MMC3_power(); + FIFO_reset(&fifo); + MSM6585_reset(&adpcm); + SetReadHandler(0x5000, 0x5FFF, readADPCM); + SetWriteHandler(0x5000, 0x5FFF, writeADPCM); + SetWriteHandler(0x9000, 0x9FFF, writeReg); + SetWriteHandler(0xB000, 0xBFFF, writeReg); +} + +static void mapperSound_fillBufferLow (int count) { + int i; + int end = (SOUNDTS <<16) /soundtsinc; + for (i = soundOffset; i < end; i++) { + MSM6585_run(&adpcm); + Wave[i >>4] += MSM6585_getOutput(&adpcm) >>1; + } + soundOffset = count; +} + +static void mapperSound_fillBufferHigh () { + int i; + for (i = soundOffset; i < SOUNDTS; i++) { + MSM6585_run(&adpcm); + WaveHi[i] += MSM6585_getOutput(&adpcm)*8 +16384; + } + soundOffset = SOUNDTS; +} + +static void mapperSound_setSoundOffset (int32 newSoundOffset) { + soundOffset = newSoundOffset; +} + +static void mapperSound_init (void) { + if (FSettings.SndRate) { + GameExpSound.Fill = mapperSound_fillBufferLow; + GameExpSound.HiFill = mapperSound_fillBufferHigh; + GameExpSound.HiSync = mapperSound_setSoundOffset; + GameExpSound.RChange = mapperSound_init; + } + MSM6585_init(&adpcm, FSettings.soundq >=1? 1789773: FSettings.SndRate*16, serveADPCM); +} + +static void close () { + FIFO_close(&fifo); +} + +void Mapper594_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, getCHRBank, NULL, NULL); + FIFO_init(&fifo, 1024); + info->Power = power; + info->Reset = reset; + info->Close = close; + mapperSound_init(); + AddExState(reg, 4, 0, "EXPR"); +} diff --git a/src/boards/595.c b/src/boards/595.c new file mode 100644 index 0000000..b98267f --- /dev/null +++ b/src/boards/595.c @@ -0,0 +1,70 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "cartram.h" +#include "flashrom.h" + +static uint8 reg; + +static void sync () { + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, reg &0x1F); + setprg16(0xC000, 0xFF); + setchr8(0); +} + +static DECLFW (writeFlash) { + flashrom_write(A &0x3FFF | (Page[A >>11] +A -PRGptr[0]) &~0x3FFF, V); +} + +static DECLFW (writeReg) { + reg = reg >>1 | V <<4 &0x10; + sync(); +} + +static void power () { + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetReadHandler(0x8000, 0xFFFF, flashrom_read); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0xBFFF, writeFlash); + SetWriteHandler(0xC000, 0xFFFF, writeReg); + reg = 0; + sync(); +} + +static void stateRestore (int version) { + sync(); +} + +void Mapper595_Init (CartInfo *info) { + WRAM_init(info, 8); + flashrom_init (0xBF, 0xB4, 4096, 0x5555, 0x2AAA, 0x7FFF); + info->Reset = power; + info->Power = power; + MapIRQHook =flashrom_cpuCycle; + GameStateRestore = stateRestore; + AddExState(®, 1, 0, "REGS"); + if (info->battery) { + info->SaveGame[0] = ROM; + info->SaveGameLen[0] = PRGsize[0]; + AddExState(ROM, PRGsize[0], 0, "FLAS"); + } +} diff --git a/src/boards/82.c b/src/boards/82_552.c similarity index 82% rename from src/boards/82.c rename to src/boards/82_552.c index fd71c75..5ed4d6b 100644 --- a/src/boards/82.c +++ b/src/boards/82_552.c @@ -26,6 +26,7 @@ static uint8 regs[9], ctrl; static uint8 *WRAM = NULL; static uint32 WRAMSIZE; +static uint8 is552; static SFORMAT StateRegs[] = { @@ -34,6 +35,13 @@ static SFORMAT StateRegs[] = { 0 } }; +uint8 prgBits (uint8 val) { + if (is552) + return val >>5 &0x01 | val >>3 &0x02 | val >>1 &0x04 | val <<1 &0x08 | val <<3 &0x10 | val <<5 &0x20; + else + return val >>2; +} + static void Sync(void) { uint32 swap = ((ctrl & 2) << 11); setchr2(0x0000 ^ swap, regs[0] >> 1); @@ -43,9 +51,9 @@ static void Sync(void) { setchr1(0x1800 ^ swap, regs[4]); setchr1(0x1c00 ^ swap, regs[5]); setprg8r(0x10, 0x6000, 0); - setprg8(0x8000, regs[6]); - setprg8(0xA000, regs[7]); - setprg8(0xC000, regs[8]); + setprg8(0x8000, prgBits(regs[6])); + setprg8(0xA000, prgBits(regs[7])); + setprg8(0xC000, prgBits(regs[8])); setprg8(0xE000, ~0); setmirror(ctrl & 1); } @@ -56,9 +64,9 @@ static DECLFW(M82Write) { else switch (A) { case 0x7ef6: ctrl = V & 3; break; - case 0x7efa: regs[6] = V >> 2; break; - case 0x7efb: regs[7] = V >> 2; break; - case 0x7efc: regs[8] = V >> 2; break; + case 0x7efa: regs[6] = V; break; + case 0x7efb: regs[7] = V; break; + case 0x7efc: regs[8] = V; break; } Sync(); } @@ -82,6 +90,7 @@ static void StateRestore(int version) { } void Mapper82_Init(CartInfo *info) { + is552 = 0; info->Power = M82Power; info->Close = M82Close; @@ -96,3 +105,8 @@ void Mapper82_Init(CartInfo *info) { GameStateRestore = StateRestore; AddExState(&StateRegs, ~0, 0, 0); } + +void Mapper552_Init(CartInfo *info) { + Mapper82_Init(info); + is552 = 1; +} diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c index 2f581c3..040af3e 100644 --- a/src/boards/addrlatch.c +++ b/src/boards/addrlatch.c @@ -181,7 +181,10 @@ static void M61Sync(void) { setprg16(0xC000, latche <<1 &0x1E | latche >>5 &0x01); } else setprg32(0x8000, latche & 0xF); - setchr8(latche >> 8); + if (submapper == 1) + setchr8(latche >> 7 &~1 | latche >> 6 &1); + else + setchr8(latche >> 8); setmirror(((latche >> 7) & 1) ^ 1); } @@ -193,6 +196,7 @@ void Mapper61_Reset() { } void Mapper61_Init(CartInfo *info) { + submapper = info->submapper; Latch_Init(info, M61Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); info->Reset = Mapper61_Reset; } @@ -342,10 +346,6 @@ void Mapper212_Init(CartInfo *info) { Latch_Init(info, M212Sync, M212Read, 0x0000, 0x8000, 0xFFFF, 0); } -/*------------------ Map 213 ---------------------------*/ - -/* SEE MAPPER 58 */ - /*------------------ Map 214 ---------------------------*/ static void M214Sync(void) { @@ -395,10 +395,10 @@ static void M227Sync(void) { } else { if (L) { setprg16(0x8000, p); - setprg16(0xC000, p | 7); + setprg16(0xC000, submapper ==3? 0: (p | 7)); } else { setprg16(0x8000, p); - setprg16(0xC000, submapper ==2? 0: p & 0x38); + setprg16(0xC000, submapper ==2? 0: (p & 0x38)); } } } @@ -766,6 +766,10 @@ void Mapper409_Init(CartInfo *info) { } /*------------------ Map 435 ---------------------------*/ +static DECLFR(ReadOB) { + return X.DB; +} + static void M435Sync(void) { int p =latche >>2 &0x1F | latche >>3 &0x20 | latche >>4 &0x40; if (latche &0x200) { @@ -787,10 +791,27 @@ static void M435Sync(void) { setmirror(latche &0x002? MI_H: MI_V); setchr8(0); + SetReadHandler(0x8000, 0xFFFF, ~latche &0x200 && latche &(submapper == 1? 0x001: 0x400) && dipswitch &1? ReadOB: CartBR); +} + +void Mapper435_Power() { + LatchPower(); + dipswitch = 0; + M435Sync(); +} + +void Mapper435_Reset() { + latche = 0; + dipswitch++; + M435Sync(); } void Mapper435_Init(CartInfo *info) { + submapper = info->submapper; Latch_Init(info, M435Sync, NULL, 0x0000, 0x8000, 0xFFFF, 1); + info->Power = Mapper435_Power; + info->Reset = Mapper435_Reset; + AddExState(&dipswitch, 1, 0, "DIPSW"); } /*------------------ Map 459 ---------------------------*/ @@ -811,24 +832,6 @@ void Mapper459_Init(CartInfo *info) { Latch_Init(info, M459Sync, NULL, 0x0000, 0x8000, 0xFFFF, 1); } -/*------------------ Map 461 ---------------------------*/ -static void M461Sync(void) { - int p =latche <<1 | latche >>5 &1; - int c =latche >>8; - if (latche &0x10) { - setprg16(0x8000, p); - setprg16(0xC000, p); - } else { - setprg32(0x8000, p >>1); - } - setchr8(c); - setmirror(latche &0x80? MI_H: MI_V); -} - -void Mapper461_Init(CartInfo *info) { - Latch_Init(info, M461Sync, NULL, 0x0000, 0x8000, 0xFFFF, 1); -} - /*------------------ Map 464 ---------------------------*/ static void M464Sync(void) { int p =latche >>7; @@ -843,8 +846,15 @@ static void M464Sync(void) { setmirror(latche &0x20? MI_H: MI_V); } +void Mapper464_reset () { + RAM[0x133] = 0; + latche = 0; + M464Sync(); +} + void Mapper464_Init(CartInfo *info) { Latch_Init(info, M464Sync, NULL, 0x0000, 0x8000, 0xFFFF, 1); + info->Reset = Mapper464_reset; } /*------------------ Map 488 ---------------------------*/ diff --git a/src/boards/asic_fme7.c b/src/boards/asic_fme7.c new file mode 100644 index 0000000..2cb4a09 --- /dev/null +++ b/src/boards/asic_fme7.c @@ -0,0 +1,133 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_fme7.h" + +static void (*FME7_cbSync)(); +static uint8 FME7_index; +static uint8 FME7_reg[16]; + +static SFORMAT FME7_stateRegs[] = { + { &FME7_index, 1, "FM7I" }, + { FME7_reg, 16, "FM7R" }, + { 0 } +}; + +void FME7_syncWRAM (int OR) { + if (PRGsize[0x10] && FME7_reg[8] &0x40) setprg8r(0x10, 0x6000, FME7_reg[8] | OR); +} + +void FME7_syncPRG (int AND, int OR) { + if (~FME7_reg[8] &0x40) setprg8(0x6000, FME7_reg[8] &AND | OR); + setprg8(0x8000, FME7_reg[ 9] &AND | OR); + setprg8(0xA000, FME7_reg[10] &AND | OR); + setprg8(0xC000, FME7_reg[11] &AND | OR); + setprg8(0xE000, 0xFF &AND | OR); +} + +void FME7_syncCHR (int AND, int OR) { + setchr1(0x0000, FME7_reg[0] &AND | OR); + setchr1(0x0400, FME7_reg[1] &AND | OR); + setchr1(0x0800, FME7_reg[2] &AND | OR); + setchr1(0x0C00, FME7_reg[3] &AND | OR); + setchr1(0x1000, FME7_reg[4] &AND | OR); + setchr1(0x1400, FME7_reg[5] &AND | OR); + setchr1(0x1800, FME7_reg[6] &AND | OR); + setchr1(0x1C00, FME7_reg[7] &AND | OR); +} + +void FME7_syncMirror () { + setmirror(FME7_reg[12] &2? (FME7_reg[12] &1? MI_1: MI_0): FME7_reg[12] &1? MI_H: MI_V); +} + +DECLFR (FME7_readWRAM) { + return ~FME7_reg[8] &0x40 || FME7_reg[8] &0x80? CartBR(A): A >>8; +} + +DECLFW (FME7_writeWRAM) { + if (FME7_reg[8] &0x80) CartBW(A, V); +} + +DECLFW (FME7_writeReg) { + if (A &0x2000) { + FME7_reg[FME7_index &0xF] = V; + if ((FME7_index &0xF) == 13) X6502_IRQEnd(FCEU_IQEXT); + FME7_cbSync(); + } else + FME7_index = V; +} + +void FP_FASTAPASS(1) FME7_cpuCycle (int a) { + while (a--) { + int16_t counter = FME7_reg[14] | FME7_reg[15] <<8; + if (FME7_reg[13] &0x80 && !--counter && FME7_reg[13] &0x01) X6502_IRQBegin(FCEU_IQEXT); + FME7_reg[14] = counter &0xFF; + FME7_reg[15] = counter >>8; + } +} + +void FME7_clear () { + int i; + for (i = 0; i < 16; i++) FME7_reg[i] = 0; + FME7_cbSync(); +} + +static void FME7_setHandlers () { + SetReadHandler(0x6000, 0x7FFF, FME7_readWRAM); + SetWriteHandler(0x6000, 0x7FFF, FME7_writeWRAM); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xBFFF, FME7_writeReg); + MapIRQHook = FME7_cpuCycle; +} + +static void FME7_configure (void (*sync)()) { + FME7_cbSync = sync; +} + +void FME7_activate (uint8 clear, void (*sync)()) { + FME7_configure(sync); + FME7_setHandlers(); + if (clear) + FME7_clear(); + else + FME7_cbSync(); +} + +void FME7_addExState () { + AddExState(FME7_stateRegs, ~0, 0, 0); +} + +void FME7_restore (int version) { + FME7_cbSync(); +} + +void FME7_power () { + FME7_setHandlers(); + FME7_clear(); +} + +void FME7_init (CartInfo *info, void (*sync)()) { + FME7_addExState(); + FME7_configure(sync); + info->Power = FME7_power; + info->Reset = FME7_cbSync; + GameStateRestore = FME7_restore; +} diff --git a/src/boards/asic_fme7.h b/src/boards/asic_fme7.h new file mode 100644 index 0000000..06994d3 --- /dev/null +++ b/src/boards/asic_fme7.h @@ -0,0 +1,39 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_FME7_H +#define _ASIC_FME7_H + +void FME7_syncWRAM (int); +void FME7_syncPRG (int, int); +void FME7_syncCHR (int, int); +void FME7_syncMirror (); +DECLFR (FME7_readWRAM); +DECLFW (FME7_writeWRAM); +DECLFW (FME7_writeReg); +void FP_FASTAPASS(1) FME7_cpuCycle (int); +void FME7_clear (); +void FME7_activate (uint8, void (*)()); +void FME7_addExState (); +void FME7_restore (int); +void FME7_power (); +void FME7_init (CartInfo *, void (*)()); + +#endif \ No newline at end of file diff --git a/src/boards/asic_h3001.c b/src/boards/asic_h3001.c new file mode 100644 index 0000000..e4dd57c --- /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, 1, "H31L" }, + {&H3001_nt, 1, "H31M" }, + {&H3001_irq, 1, "H31N" }, + {&H3001_reload, 2 | FCEUSTATE_RLSB, "H31R" }, + {&H3001_count, 2 | FCEUSTATE_RLSB, "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; + } +} + +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_restore; +} diff --git a/src/boards/asic_h3001.h b/src/boards/asic_h3001.h new file mode 100644 index 0000000..1c5122e --- /dev/null +++ b/src/boards/asic_h3001.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_H3001_H +#define _ASIC_H3001_H + +void H3001_syncPRG (int, int); +void H3001_syncCHR (int, int); +void H3001_syncMirror (); +DECLFW (H3001_write); +void H3001_clear (); +void H3001_activate (uint8, void (*)()); +void H3001_addExState (); +void H3001_restore (int); +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..579de14 --- /dev/null +++ b/src/boards/asic_latch.c @@ -0,0 +1,91 @@ +/* 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 = newAddress; + Latch_data = V; + Latch_cbSync(); +} + +void Latch_clear () { + Latch_address = 0; + Latch_data = 0; + Latch_cbSync(); +} + +static void Latch_setHandlers() { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + 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..80c9ef2 --- /dev/null +++ b/src/boards/asic_latch.h @@ -0,0 +1,36 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_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_clear (); +void Latch_power (); +void Latch_activate (uint8, void (*)(), uint16, uint16, void (*)(uint16*, uint8*, uint8)); +void Latch6_activate (uint8, void (*)(), uint16, uint16, void (*)(uint16*, uint8*, uint8)); +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..1c5a5de --- /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_writeReg) { + 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; +} + +void MMC1_clear () { + MMC1_reg[0] = 0x0C; MMC1_reg[1] = 0; MMC1_reg[2] = 0; MMC1_reg[3] = 0; /* "Bad News Baseball" is sensitive to the initial CHR bank register content. 0/0 seems to work. */ + MMC1_bits = 0; MMC1_shift = 0; MMC1_filter = 0; + MMC1_cbSync(); +} + +static void MMC1_setHandlers () { + SetReadHandler (0x6000, 0x7FFF, MMC1_readWRAM); + SetWriteHandler(0x6000, 0x7FFF, MMC1_writeWRAM); + SetReadHandler (0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, MMC1_writeReg); + 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..e72260c --- /dev/null +++ b/src/boards/asic_mmc1.h @@ -0,0 +1,42 @@ +/* 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_writeReg); +void MMC1_clear (); +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_mmc2and4.c b/src/boards/asic_mmc2and4.c new file mode 100644 index 0000000..fd6c5f2 --- /dev/null +++ b/src/boards/asic_mmc2and4.c @@ -0,0 +1,117 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_mmc2and4.h" + +static void (*MMC24_cbSync)(); +static uint8 MMC24_reg[6]; +static uint8 MMC24_latch[2]; + +static SFORMAT MMC24_state[] = { + { MMC24_reg, 6, "MC2R" }, + { MMC24_latch, 2, "MC2S" }, + { 0 } +}; + +static void (*MMC24_cbSync)(); + +void MMC24_syncWRAM (int OR) { + if (PRGsize[0x10]) setprg8r(0x10, 0x6000, OR); +} + +void MMC2_syncPRG (int AND, int OR) { + setprg8(0x8000, MMC24_reg[0] &AND |OR); + setprg8(0xA000, 0xFD &AND |OR); + setprg8(0xC000, 0xFE &AND |OR); + setprg8(0xE000, 0xFF &AND |OR); +} + +void MMC4_syncPRG (int AND, int OR) { + setprg16(0x8000, MMC24_reg[0] &AND |OR); + setprg16(0xC000, 0xFF &AND |OR); +} + +void MMC24_syncCHR (int AND, int OR) { + setchr4(0x0000, MMC24_reg[1 +MMC24_latch[0]] &AND |OR); + setchr4(0x1000, MMC24_reg[3 +MMC24_latch[1]] &AND |OR); +} + +void MMC24_syncMirror () { + setmirror(MMC24_reg[5] &1? MI_H: MI_V); +} + +static void FP_FASTAPASS(1) MMC24_trapPPUAddressChange (uint32 A) { + if ((A &0x2FF0) == 0xFD0 || (A &0x2FF0) == 0xFE0) { + MMC24_latch[A >>12 &1] = A >>5 &1; + MMC24_cbSync(); + } +} + +DECLFW (MMC24_write) { + MMC24_reg[(A >>12) -0xA] = V; + MMC24_cbSync(); +} + +void MMC24_clear () { + MMC24_reg[0] = 0; MMC24_reg[1] = 0; MMC24_reg[2] = 2; MMC24_reg[3] = 0; MMC24_reg[4] = 0; MMC24_reg[5] = 0; + MMC24_latch[0] = 0; MMC24_latch[1] = 0; + MMC24_cbSync(); +} + +static void MMC24_setHandlers() { + SetReadHandler (0x8000, 0xFFFF, CartBR); + SetWriteHandler(0xA000, 0xFFFF, MMC24_write); + PPU_hook = MMC24_trapPPUAddressChange; +} + +static void MMC24_configure (void (*sync)()) { + MMC24_cbSync = sync; +} + +void MMC24_activate (uint8 clear, void (*sync)()) { + MMC24_configure(sync); + MMC24_setHandlers(); + if (clear) + MMC24_clear(); + else + MMC24_cbSync(); +} + +void MMC24_addExState () { + AddExState(MMC24_state, ~0, 0, 0); +} + +void MMC24_restore (int version) { + MMC24_cbSync(); +} + +void MMC24_power () { + MMC24_setHandlers(); + MMC24_clear(); +} + +void MMC24_init (CartInfo *info, void (*sync)()) { + MMC24_addExState(); + MMC24_configure(sync); + info->Power = MMC24_power; + info->Reset = MMC24_cbSync; + GameStateRestore = MMC24_restore; +} diff --git a/src/boards/asic_mmc2and4.h b/src/boards/asic_mmc2and4.h new file mode 100644 index 0000000..5c408a3 --- /dev/null +++ b/src/boards/asic_mmc2and4.h @@ -0,0 +1,37 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_MMC2AND4_H +#define _ASIC_MMC2AND4_H + +void MMC24_syncWRAM (int); +void MMC2_syncPRG (int, int); +void MMC4_syncPRG (int, int); +void MMC24_syncCHR (int, int); +void MMC24_syncMirror (); +DECLFW (MMC24_write); +void MMC24_clear (); +void MMC24_power (); +void MMC24_restore (int); +void MMC24_addExState (); +void MMC24_activate (uint8, void (*)()); +void MMC24_init (CartInfo *, void (*)()); + +#endif diff --git a/src/boards/asic_mmc3.c b/src/boards/asic_mmc3.c new file mode 100644 index 0000000..330ba74 --- /dev/null +++ b/src/boards/asic_mmc3.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_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; +} + +uint8 MMC3_getMirroring (void) { + return MMC3_mirroring; +} + +DECLFR (MMC3_readWRAM) { + if (MMC3_wramControl &0x80 || MMC3_type == MMC3_TYPE_AX5202P || MMC3_type == MMC3_TYPE_MMC6) + return MMC3_cbReadWRAM? MMC3_cbReadWRAM(A): CartBR(A); + 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_writeReg) { + 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(); +} + +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_writeReg); + 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..3e4527b --- /dev/null +++ b/src/boards/asic_mmc3.h @@ -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 + */ + +#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); +uint8 MMC3_getMirroring (void); +void MMC3_syncPRG (int, int); +void MMC3_syncCHR (int, int); +void MMC3_syncMirror (); +void MMC3_clockCounter (); +DECLFW (MMC3_writeReg); +void MMC3_clear (); +void MMC3_activate (uint8, void (*)(), uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*))); +void MMC3_addExState(); +void MMC3_restore (int); +void MMC3_power (); +void MMC3_init (CartInfo *, void (*)(), uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*))); + +#endif diff --git a/src/boards/asic_n118.c b/src/boards/asic_n118.c new file mode 100644 index 0000000..4ef93d3 --- /dev/null +++ b/src/boards/asic_n118.c @@ -0,0 +1,108 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_n118.h" + +static void (*N118_cbSync)(); +static int (*N118_cbGetPRGBank)(uint8); +static int (*N118_cbGetCHRBank)(uint8); +static uint8 N118_index; +static uint8 N118_reg[8]; + +static SFORMAT N118_state[] = { + { N118_reg, 8, "N8RG" }, + {&N118_index, 1, "N8IX" }, + { 0 } +}; + +int N118_getPRGBank (uint8 bank) { + return bank &2? (0xFE | bank &1): N118_reg[6 | bank &1]; +} + +int N118_getCHRBank (uint8 bank) { + return bank &4? N118_reg[bank -2]: (N118_reg[bank >>1] &~1 | bank &1); +} + +void N118_syncPRG (int AND, int OR) { + int bank; + for (bank = 0; bank < 4; bank++) setprg8(0x8000 | bank <<13, N118_cbGetPRGBank(bank) &AND |OR); +} + +void N118_syncCHR (int AND, int OR) { + int bank; + for (bank = 0; bank < 8; bank++) setchr1(bank <<10, N118_cbGetCHRBank(bank) &AND |OR); +} + +DECLFW (N118_writeReg) { + if (A &1) { + N118_reg[N118_index &7] = V; + N118_cbSync(); + } else + N118_index = V; +} + +void N118_clear () { + N118_reg[0] = 0; N118_reg[1] = 2; N118_reg[2] = 4; N118_reg[3] = 5; N118_reg[4] = 6; N118_reg[5] = 7; N118_reg[6] = 0; N118_reg[7] = 1; + N118_index = 0; + N118_cbSync(); +} + +static void N118_setHandlers () { + SetReadHandler (0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0x9FFF, N118_writeReg); +} + +static void N118_configure (void (*sync)(), int (*prg)(uint8), int (*chr)(uint8)) { + N118_cbSync = sync; + N118_cbGetPRGBank = prg? prg: N118_getPRGBank; + N118_cbGetCHRBank = chr? chr: N118_getCHRBank; +} + +void N118_activate (uint8 clear, void (*sync)(), int (*prg)(uint8), int (*chr)(uint8)) { + N118_configure(sync, prg, chr); + N118_setHandlers(); + if (clear) + N118_clear(); + else + N118_cbSync(); +} + +void N118_addExState () { + AddExState(N118_state, ~0, 0, 0); +} + +void N118_restore (int version) { + N118_cbSync(); +} + +void N118_power () { + N118_setHandlers(); + N118_clear(); +} + +void N118_init (CartInfo *info, void (*sync)(), int (*prg)(uint8), int (*chr)(uint8)) { + N118_addExState(); + N118_configure(sync, prg, chr); + info->Power = N118_power; + info->Reset = N118_cbSync; + GameStateRestore = N118_restore; +} diff --git a/src/boards/asic_n118.h b/src/boards/asic_n118.h new file mode 100644 index 0000000..77438ae --- /dev/null +++ b/src/boards/asic_n118.h @@ -0,0 +1,36 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_N118_H +#define _ASIC_N118_H + +int N118_getPRGBank (uint8); +int N118_getCHRBank (uint8); +void N118_syncPRG (int, int); +void N118_syncCHR (int, int); +DECLFW (N118_writeReg); +void N118_clear (); +void N118_activate (uint8, void (*)(), int (*)(uint8), int (*)(uint8)); +void N118_addExState(); +void N118_restore (int); +void N118_power (); +void N118_init (CartInfo *, void (*)(), int (*)(uint8), int (*)(uint8)); + +#endif diff --git a/src/boards/asic_pt8154.c b/src/boards/asic_pt8154.c new file mode 100644 index 0000000..9a80a1d --- /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(); +} + +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..1991d25 --- /dev/null +++ b/src/boards/asic_pt8154.h @@ -0,0 +1,36 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_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_clear (); +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..1562d73 --- /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(); +} + +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..28ecd9e --- /dev/null +++ b/src/boards/asic_qj.h @@ -0,0 +1,36 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_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_clear (); +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..a22de7b --- /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; +uint8 TC3294_reg[4]; + +static SFORMAT TC3294_state[] = { + { TC3294_reg, 4, "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_writeReg) { + if (~TC3294_reg[3] &0x40) { + TC3294_reg[TC3294_index++ &3] = V; + TC3294_cbSync(); + } +} + +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_writeReg); + 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_writeReg); + TC3294_addExState(); + TC3294_configure(sync); + info->Power = TC3294_power; + info->Reset = TC3294_clear; + GameStateRestore = TC3294_restore; +} diff --git a/src/boards/asic_tc3294.h b/src/boards/asic_tc3294.h new file mode 100644 index 0000000..a1ba78b --- /dev/null +++ b/src/boards/asic_tc3294.h @@ -0,0 +1,37 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ASIC_TC3294_H +#define _ASIC_TC3294_H + +extern uint8 TC3294_reg[4]; +void TC3294_syncWRAM (int); +void TC3294_syncPRG (int, int); +void TC3294_syncCHR (int, int); +void TC3294_syncMirror (); +DECLFW (TC3294_writeReg); +void TC3294_clear (); +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..c25ef2c --- /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_writeReg) { + VRC1_reg[A >>12 &7] = V; + VRC1_cbSync(); +} + +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_writeReg); +} + +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..ed44fd6 --- /dev/null +++ b/src/boards/asic_vrc1.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_VRC1_H +#define _ASIC_VRC1_H + +void VRC1_syncPRG (int, int); +void VRC1_syncCHR (int, int); +void VRC1_syncMirror (); +DECLFW (VRC1_writeReg); +void VRC1_clear (); +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..3e0cc22 --- /dev/null +++ b/src/boards/asic_vrc2and4.c @@ -0,0 +1,302 @@ +/* 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 "cartram.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, "VC2P" }, + { &VRC24_chr[0], 2 | FCEUSTATE_RLSB, "V2C0" }, + { &VRC24_chr[1], 2 | FCEUSTATE_RLSB, "V2C1" }, + { &VRC24_chr[2], 2 | FCEUSTATE_RLSB, "V2C2" }, + { &VRC24_chr[3], 2 | FCEUSTATE_RLSB, "V2C3" }, + { &VRC24_chr[4], 2 | FCEUSTATE_RLSB, "V2C4" }, + { &VRC24_chr[5], 2 | FCEUSTATE_RLSB, "V2C5" }, + { &VRC24_chr[6], 2 | FCEUSTATE_RLSB, "V2C6" }, + { &VRC24_chr[7], 2 | FCEUSTATE_RLSB, "V2C7" }, + { &VRC24_mirroring, 1, "VC2N" }, + { &VRC24_misc, 1, "VC4M" }, + { 0 } +}; + +static SFORMAT VRC2_stateRegs[] = { + { &VRC2_pins, 1, "VC2E" }, +}; + +static SFORMAT VRC4_stateRegs[] = { + { &VRC4_latch, 1, "V4LT" }, + { &VRC4_mode, 1, "V4MO" }, + { &VRC4_count, 1, "V4CT" }, + { &VRC4_cycles, 2 | FCEUSTATE_RLSB, "V4CY" }, + { 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); + } + } + } +} + +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 VRC24_reconfigure(int A0, int A1) { + VRC24_A0 = A0; + VRC24_A1 = A1; +} + +void VRC2_activate (uint8 clear, void (*sync)(), int A0, int A1, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) { + VRC2_configure(sync, A0, A1, prg, chr, read, write); + VRC24_setHandlers(); + 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_restore; +} + +void VRC4_init (CartInfo *info, void (*sync)(), int A0, int A1, uint8 useRepeatBit, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write)), DECLFW((*externalSelect))) { + 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..0dcc8f7 --- /dev/null +++ b/src/boards/asic_vrc2and4.h @@ -0,0 +1,52 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#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 VRC24_reconfigure (int, int); +void VRC24_clear (); +void VRC2_activate (uint8, void (*)(), int, int, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*))); +void VRC4_activate (uint8, void (*)(), int, int, uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*)), DECLFW((*))); +void VRC2_addExState (); +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..2f46e4e --- /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..2c73fd5 --- /dev/null +++ b/src/boards/asic_vrc3.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_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_clear (); +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..3748322 --- /dev/null +++ b/src/boards/asic_vrc6.c @@ -0,0 +1,207 @@ +/* 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" + +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, 8, "VC6C" }, + { &VRC6_misc, 1, "VC6M" }, + { &VRC6_latch, 1, "V6LT" }, + { &VRC6_mode, 1, "V6MO" }, + { &VRC6_count, 1, "V6CT" }, + { &VRC6_cycles, 2 | FCEUSTATE_RLSB, "V6CY" }, + { 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); + } + } + } +} + +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..4d3fe8b --- /dev/null +++ b/src/boards/asic_vrc6.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_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_clear (); +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..54ee04b --- /dev/null +++ b/src/boards/asic_vrc7.c @@ -0,0 +1,179 @@ +/* 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" + +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, "VC7P" }, + { VRC7_chr, 8, "VC7C" }, + { &VRC7_misc, 1, "VC7M" }, + { &VRC7_latch, 1, "V7LT" }, + { &VRC7_mode, 1, "V7MO" }, + { &VRC7_count, 1, "V7CT" }, + { &VRC7_cycles, 2 | FCEUSTATE_RLSB, "V7CY" }, + { 0 } +}; + +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); + } + } + } +} + +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..3431774 --- /dev/null +++ b/src/boards/asic_vrc7.h @@ -0,0 +1,39 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#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 (); +DECLFR(VRC7_readWRAM); +DECLFW(MMC3_writeWRAM); +DECLFW(VRC7_writeReg); +void FP_FASTAPASS(1) VRC7_cpuCycle (int); +void VRC7_clear (); +void VRC7_activate (uint8, void (*)(), int); +void VRC7_addExState (); +void VRC7_restore (int); +void VRC7_power (); +void VRC7_init (CartInfo *, void (*)(), int); + +#endif \ No newline at end of file diff --git a/src/boards/bmc64in1nr.c b/src/boards/bmc64in1nr.c index 8a6cdb5..86d2abe 100644 --- a/src/boards/bmc64in1nr.c +++ b/src/boards/bmc64in1nr.c @@ -31,17 +31,17 @@ static SFORMAT StateRegs[] = }; static void Sync(void) { + int prg = regs[0] <<7 &0x80 | regs[1] <<1 &0x7E | regs[1] >>6 &0x01; if (regs[0] & 0x80) { /* NROM mode */ if (regs[1] & 0x80) - setprg32(0x8000, regs[1] & 0x3F); + setprg32(0x8000, prg >>1); else { - int bank = ((regs[1] & 0x3F) << 1) | ((regs[1] >> 6) & 1); - setprg16(0x8000, bank); - setprg16(0xC000, bank); + setprg16(0x8000, prg); + setprg16(0xC000, prg); } } else { /* UNROM mode */ - setprg16(0x8000, regs[1] <<1 | regs[3] &7); - setprg16(0xC000, regs[1] <<1 | 7); + setprg16(0x8000, prg &~7 | regs[3] &7); + setprg16(0xC000, prg | 7); } if (regs[0] & 0x20) setmirror(MI_H); @@ -51,9 +51,7 @@ static void Sync(void) { } static DECLFW(BMC64in1nrWriteLo) { - A &=3; - if (A ==3) A =1; /* K-42001's "Aladdin III" */ - regs[A & 3] = V; + regs[A &(VROM_size? 3: 1)] = V; Sync(); } diff --git a/src/boards/bmck3006.c b/src/boards/bmck3006.c index 0e62d5e..7b5ca30 100644 --- a/src/boards/bmck3006.c +++ b/src/boards/bmck3006.c @@ -26,7 +26,11 @@ #include "mapinc.h" #include "mmc3.h" -static uint8 submapper; +static uint8 submapper; /* 0: K-3006, 1: unmarked, 2: TL 8058, 3: K-3091/GN-16 */ + +static DECLFR (readPad) { + return CartBR(A &~3 | EXPREGS[2] &3); +} static void BMCK3006CW(uint32 A, uint8 V) { setchr1(A, (V & 0x7F) | (EXPREGS[0] & 0x18) << 4); @@ -36,9 +40,12 @@ static void BMCK3006PW(uint32 A, uint8 V) { if (EXPREGS[0] & 0x20) { /* MMC3 mode */ setprg8(A, (V & 0x0F) | (EXPREGS[0] & 0x18) << 1); } else { - if ((EXPREGS[0] & 0x07) == 0x06 && submapper ==0 || EXPREGS[0] &4 && submapper ==1) { /* NROM-256 */ + if (submapper ==0 && (EXPREGS[0] & 0x06) == 0x06 || + submapper ==1 && EXPREGS[0] &4 || + submapper ==2 && (EXPREGS[0] &1 || EXPREGS[1] &1) || + submapper ==3 && EXPREGS[0] &0x18) { /* NROM-256 */ setprg32(0x8000, (EXPREGS[0] >> 1) & 0x0F); - } else { /* NROM-128 */ + } else { /* NROM-128 */ setprg16(0x8000, EXPREGS[0] & 0x1F); setprg16(0xC000, EXPREGS[0] & 0x1F); } @@ -46,18 +53,21 @@ static void BMCK3006PW(uint32 A, uint8 V) { } static DECLFW(BMCK3006Write) { - EXPREGS[0] = A & 0x3F; + EXPREGS[0] = A &0xFF; + EXPREGS[1] = A >>8 &0xFF; FixMMC3PRG(MMC3_cmd); FixMMC3CHR(MMC3_cmd); + if (submapper == 2 || submapper == 3) SetReadHandler(0x8000, 0xFFFF, EXPREGS[0] &0x80? readPad: CartBR); } static void BMCK3006Reset(void) { - EXPREGS[0] = 0; + EXPREGS[0] = EXPREGS[1] = 0; + EXPREGS[2]++; MMC3RegReset(); } static void BMCK3006Power(void) { - EXPREGS[0] = 0; + EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = 0; GenMMC3Power(); SetWriteHandler(0x6000, 0x7FFF, BMCK3006Write); } @@ -69,5 +79,5 @@ void BMCK3006_Init(CartInfo *info) { cwrap = BMCK3006CW; info->Power = BMCK3006Power; info->Reset = BMCK3006Reset; - AddExState(EXPREGS, 1, 0, "EXPR"); + AddExState(EXPREGS, 3, 0, "EXPR"); } diff --git a/src/boards/cartram.c b/src/boards/cartram.c new file mode 100644 index 0000000..02d04de --- /dev/null +++ b/src/boards/cartram.c @@ -0,0 +1,71 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "cartram.h" + +static uint8 *CHRRAMData = NULL; +static uint8 *WRAMData = NULL; +uint32 CHRRAMSize = 0; +uint32 WRAMSize = 0; + +void CartRAM_close (void) { /* Need to combine this in one function to avoid the problem of having to properly cascade two separate Close() functions for WRAM and CHR-RAM each */ + if (WRAMData) { + FCEU_gfree(WRAMData); + WRAMData = NULL; + } + if (CHRRAMData) { + FCEU_gfree(CHRRAMData); + CHRRAMData = NULL; + } +} + +void CartRAM_init (CartInfo *info, uint8 defaultWRAMSizeKiB, uint8 defaultCHRRAMSizeKiB) { + WRAMSize = info->iNES2? (info->PRGRamSize +info->PRGRamSaveSize): (defaultWRAMSizeKiB *1024); + if (WRAMSize) { + WRAMData = (uint8*)FCEU_gmalloc(WRAMSize); + SetupCartPRGMapping(0x10, WRAMData, WRAMSize, 1); + AddExState(WRAMData, WRAMSize, 0, "WRAM"); + if (info->battery && (info->PRGRamSaveSize || !info->iNES2)) { + info->SaveGame[0] = WRAMData; + info->SaveGameLen[0] = info->iNES2? info->PRGRamSaveSize: WRAMSize; + } + } + CHRRAMSize = info->iNES2? (info->CHRRamSize +info->CHRRamSaveSize): (defaultCHRRAMSizeKiB *1024); + if (ROM_size == 0) CHRRAMSize = 0; /* If there is no CHR-ROM, then any CHR-RAM will not be "extra" and therefore will be handled by ines.c, not here. */ + if (CHRRAMSize) { + CHRRAMData = (uint8*)FCEU_gmalloc(CHRRAMSize); + SetupCartCHRMapping(0x10, CHRRAMData, CHRRAMSize, 1); + AddExState(CHRRAMData, CHRRAMSize, 0, "CRAM"); + if (info->battery && (info->CHRRamSaveSize || !info->iNES2)) { + info->SaveGame[info->SaveGameLen[0]? 1: 0] = CHRRAMData; + info->SaveGameLen[info->SaveGameLen[0]? 1: 0] = info->iNES2? info->CHRRamSaveSize: CHRRAMSize; + } + } + if (WRAMSize || CHRRAMSize) info->Close = CartRAM_close; +} + +void CHRRAM_init (CartInfo *info, uint8 defaultCHRRAMSizeKiB) { + CartRAM_init(info, 0, defaultCHRRAMSizeKiB); +} + +void WRAM_init (CartInfo *info, uint8 defaultWRAMSizeKiB) { + CartRAM_init(info, defaultWRAMSizeKiB, 0); +} diff --git a/src/boards/cartram.h b/src/boards/cartram.h new file mode 100644 index 0000000..de46253 --- /dev/null +++ b/src/boards/cartram.h @@ -0,0 +1,31 @@ +/* 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 _CARTRAM_H +#define _CARTRAM_H + +extern uint32 CHRRAMSize; +extern uint32 WRAMSize; +void CartRAM_init (CartInfo *, uint8, uint8); +void CHRRAM_init (CartInfo *, uint8); +void WRAM_init (CartInfo *, uint8); +void CartRAM_close (); + +#endif diff --git a/src/boards/datalatch.c b/src/boards/datalatch.c index 09a0da6..32d3d92 100644 --- a/src/boards/datalatch.c +++ b/src/boards/datalatch.c @@ -507,53 +507,6 @@ void Mapper538_Init(CartInfo *info) { info->Power = M538Power; } -/* ------------------ A65AS --------------------------- */ - -/* actually, there is two cart in one... First have extra mirroring - * mode (one screen) and 32K bankswitching, second one have only - * 16 bankswitching mode and normal mirroring... But there is no any - * correlations between modes and they can be used in one mapper code. - * - * Submapper 0 - 3-in-1 (N068) - * Submapper 0 - 3-in-1 (N080) - * Submapper 1 - 4-in-1 (JY-066) - */ - -static int A65ASsubmapper; -static void BMCA65ASSync(void) { - if (latche & 0x40) - setprg32(0x8000, (latche >> 1) & 0x0F); - else { - if (A65ASsubmapper == 1) { - setprg16(0x8000, ((latche & 0x30) >> 1) | (latche & 7)); - setprg16(0xC000, ((latche & 0x30) >> 1) | 7); - } else { - setprg16(0x8000, latche & 0x0F); - setprg16(0xC000, latche & 0x0F | 7); - } - } - setchr8(0); - if (latche & 0x80) - setmirror(MI_0 + (((latche >> 5) & 1))); - else { - if (A65ASsubmapper == 1) - setmirror(latche &0x08? MI_H: MI_V); - else - setmirror(latche &0x20? MI_H: MI_V); - } -} - -void BMCA65AS_Reset() { - latche =0; - BMCA65ASSync(); -} - -void BMCA65AS_Init(CartInfo *info) { - A65ASsubmapper = info->submapper; - info->Reset = BMCA65AS_Reset; - Latch_Init(info, BMCA65ASSync, 0, 0x8000, 0xFFFF, 0, 0); -} - /*------------------ BMC-11160 ---------------------------*/ /* Simple BMC discrete mapper by TXC */ diff --git a/src/boards/et-100.c b/src/boards/et-100.c index 5e41622..1ad553c 100644 --- a/src/boards/et-100.c +++ b/src/boards/et-100.c @@ -41,6 +41,7 @@ #include "mapinc.h" #include "mmc3.h" +static uint8 submapper; static uint8 *CHRRAM = NULL; static uint32 CHRRAMSize; @@ -58,6 +59,16 @@ static void BMC1024CA1CW(uint32 A, uint8 V) { setchr1(A, V | ((EXPREGS[0] & 7) << 7)); else setchr1(A, (V&0x7F) | ((EXPREGS[0] & 7) << 7)); + + if (submapper == 1 && EXPREGS[0] &0x08) setmirror(DRegBuf[MMC3_cmd &0x80? 2: 0] &0x80? MI_1: MI_0); +} + +static void BMC1024CA1MW(uint8 V) { + A000B = V; + if (EXPREGS[0] &0x08) + setmirror(DRegBuf[MMC3_cmd &0x80? 2: 0] &0x80? MI_1: MI_0); + else + setmirror(V &1? MI_H: MI_V); } static DECLFW(BMC1024CA1Write) { @@ -90,6 +101,7 @@ static void BMC1024CA1Close(void) { } void BMC1024CA1_Init(CartInfo *info) { + submapper = info->submapper; GenMMC3_Init(info, 256, 256, 8, 0); CHRRAMSize = 8192; CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize); @@ -97,6 +109,7 @@ void BMC1024CA1_Init(CartInfo *info) { AddExState(CHRRAM, CHRRAMSize, 0, "CHRR"); pwrap = BMC1024CA1PW; cwrap = BMC1024CA1CW; + if (submapper == 1) mwrap = BMC1024CA1MW; info->Power = BMC1024CA1Power; info->Reset = BMC1024CA1Reset; info->Close = BMC1024CA1Close; diff --git a/src/boards/fifo.c b/src/boards/fifo.c new file mode 100644 index 0000000..542671c --- /dev/null +++ b/src/boards/fifo.c @@ -0,0 +1,43 @@ +#include "mapinc.h" +#include +#include +#include "fifo.h" + +size_t FIFO_size (FIFO *fifo) { + fifo->front %= fifo->capacity; + fifo->back %= fifo->capacity; + return (fifo->back -fifo->front +fifo->capacity) %fifo->capacity; +} + +uint8 FIFO_halfFull (FIFO *fifo) { + return FIFO_size(fifo) >= fifo->capacity /2; +} + +int FIFO_retrieve (FIFO *fifo) { + fifo->front %= fifo->capacity; + return FIFO_size(fifo)? fifo->data[fifo->front++]: 0; +} + +void FIFO_add (FIFO *fifo, uint8 value) { + fifo->back %= fifo->capacity; + if (FIFO_size(fifo) capacity) fifo->data[fifo->back++] = value; +} + +void FIFO_reset (FIFO *fifo) { + fifo->front = fifo->back = 0; +} + +void FIFO_init (FIFO *fifo, size_t newCapacity) { + fifo->capacity = newCapacity; + fifo->data = (uint8*)FCEU_gmalloc(newCapacity); + AddExState(fifo->data, fifo->capacity, 0, "FIFD"); + AddExState(&fifo->front, 2 | FCEUSTATE_RLSB, 0, "FIFF"); + AddExState(&fifo->back, 2 | FCEUSTATE_RLSB, 0, "FIFB"); +} + +void FIFO_close (FIFO *fifo) { + if (fifo->data) { + free(fifo->data); + fifo->data = NULL; + } +} diff --git a/src/boards/fifo.h b/src/boards/fifo.h new file mode 100644 index 0000000..377452c --- /dev/null +++ b/src/boards/fifo.h @@ -0,0 +1,19 @@ +#ifndef _FIFO_H +#define _FIFO_H + +typedef struct { + size_t capacity; + uint8 *data; + int16 front; + int16 back; +} FIFO; + +size_t FIFO_size (FIFO *); +uint8 FIFO_halfFull (FIFO *); +int FIFO_retrieve (FIFO *); +void FIFO_add (FIFO *, uint8); +void FIFO_reset (FIFO *); +void FIFO_init (FIFO *, size_t); +void FIFO_close (FIFO *); + +#endif diff --git a/src/boards/fk23c.c b/src/boards/fk23c.c index ac22b6d..5218f3f 100644 --- a/src/boards/fk23c.c +++ b/src/boards/fk23c.c @@ -107,7 +107,7 @@ static void cwrap(uint32 A, uint32 V) /* some workaround for chr rom / ram access */ if (!VROM_size) bank = 0; - else if (CHRRAMSIZE && fk23_regs[0] & 0x20) + else if (fk23_regs[0] &0x20 && ~fk23_regs[0] &0x40 && CHRRAMSIZE || VROM_size == 0) bank = 0x10; if (CHR_MIXED && V < 8) bank = 0x10; /* first 8K of chr bank is RAM */ @@ -175,7 +175,7 @@ static void SyncPRG(void) switch (subType) { case 1: /* FK-xxx */ - if (PRG_MODE == 0) mask = 0xFF; /* Mode 0 allows the MMC3 to address 2 MiB rather than the usual 512 KiB. */ + if (PRG_MODE == 0 && MMC3_EXTENDED) mask = 0xFF; /* Mode 0 allows the MMC3 to address 2 MiB rather than the usual 512 KiB. */ break; case 2: /* FS005 */ prg_base |= fk23_regs[0] << 4 & 0x080 | fk23_regs[0] << 1 & 0x100 | fk23_regs[2] << 3 & 0x600 | fk23_regs[2] << 6 & 0x800; @@ -394,6 +394,7 @@ static void Reset(void) } fk23_regs[0] = fk23_regs[1] = fk23_regs[2] = fk23_regs[3] = fk23_regs[4] = fk23_regs[5] = fk23_regs[6] = fk23_regs[7] = 0; + if (subType == 1) fk23_regs[1] = 0xFF; mmc3_regs[0] = 0; mmc3_regs[1] = 2; mmc3_regs[2] = 4; @@ -415,6 +416,7 @@ static void Reset(void) static void Power(void) { fk23_regs[0] = fk23_regs[1] = fk23_regs[2] = fk23_regs[3] = fk23_regs[4] = fk23_regs[5] = fk23_regs[6] = fk23_regs[7] = 0; + if (subType == 1) fk23_regs[1] = 0xFF; mmc3_regs[0] = 0; mmc3_regs[1] = 2; mmc3_regs[2] = 4; diff --git a/src/boards/jyasic.c b/src/boards/jyasic.c index 544648b..ef0d708 100644 --- a/src/boards/jyasic.c +++ b/src/boards/jyasic.c @@ -710,7 +710,7 @@ static void Mapper394_PWrap(uint32 A, uint8 V) static void Mapper394_CWrap(uint32 A, uint8 V) { int chrAND =HSK007Reg[3] &0x80? 0xFF: 0x7F; - int chrOR =submapper ==1? (HSK007Reg[3] <<1 &0x080 | HSK007Reg[1] <<8 &0x200 | HSK007Reg[1] <<6 &0x100): (HSK007Reg[3] <<1 &0x080 | HSK007Reg[1] <<8 &0x100); + int chrOR =submapper ==1? (HSK007Reg[3] <<1 &0x080 | HSK007Reg[1] <<8 &0x200 | HSK007Reg[1] <<6 &0x100): (HSK007Reg[3] <<1 &0x080 | HSK007Reg[1] <<8 &0x300); setchr1(A, V &chrAND | chrOR &~chrAND); } static DECLFW(Mapper394_Write) diff --git a/src/boards/mmc3.c b/src/boards/mmc3.c index de88f2d..978b57e 100644 --- a/src/boards/mmc3.c +++ b/src/boards/mmc3.c @@ -1311,12 +1311,12 @@ void Mapper367_Init(CartInfo *info) { /* Mapper 361 and 366, previously assigned as Mapper 205 */ static void GN45PW(uint32 A, uint8 V) { /* GN-30A - \ED\E0\F7\E0\EB\FC\ED\E0\FF \EC\E0\F1\EA\E0 \E4\EE\EB\E6\ED\E0 \E1\FB\F2\FC 1F + \E0\EF\EF\E0\F0\E0\F2\ED\FB\E9 \EF\E5\F0\E5\EA\EB\FE\F7\E0\F2\E5\EB\FC \ED\E0 \F8\E8\ED\E5 \E0\E4\F0\E5\F1\E0 */ - setprg8(A, (V & 0x0f) | EXPREGS[0]); + setprg8(A, (V & 0x0f) | EXPREGS[0] &~0x0F); } static void GN45CW(uint32 A, uint8 V) { /* GN-30A - \ED\E0\F7\E0\EB\FC\ED\E0\FF \EC\E0\F1\EA\E0 \E4\EE\EB\E6\ED\E0 \E1\FB\F2\FC FF */ - setchr1(A, (V & 0x7F) | (EXPREGS[0] << 3)); + setchr1(A, (V & 0x7F) | (EXPREGS[0] << 3 &~0x7F)); } static DECLFW(GN45Write0) { diff --git a/src/boards/msm6585.c b/src/boards/msm6585.c new file mode 100644 index 0000000..bf1a702 --- /dev/null +++ b/src/boards/msm6585.c @@ -0,0 +1,101 @@ +#include "mapinc.h" +#include "msm6585.h" + +static const int16_t diff_lookup[49*16] = { + 2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30, + 2, 6, 10, 14, 19, 23, 27, 31, -2, -6, -10, -14, -19, -23, -27, -31, + 2, 6, 11, 15, 21, 25, 30, 34, -2, -6, -11, -15, -21, -25, -30, -34, + 2, 7, 12, 17, 23, 28, 33, 38, -2, -7, -12, -17, -23, -28, -33, -38, + 2, 7, 13, 18, 25, 30, 36, 41, -2, -7, -13, -18, -25, -30, -36, -41, + 3, 9, 15, 21, 28, 34, 40, 46, -3, -9, -15, -21, -28, -34, -40, -46, + 3, 10, 17, 24, 31, 38, 45, 52, -3, -10, -17, -24, -31, -38, -45, -52, + 3, 10, 18, 25, 34, 41, 49, 56, -3, -10, -18, -25, -34, -41, -49, -56, + 4, 12, 21, 29, 38, 46, 55, 63, -4, -12, -21, -29, -38, -46, -55, -63, + 4, 13, 22, 31, 41, 50, 59, 68, -4, -13, -22, -31, -41, -50, -59, -68, + 5, 15, 25, 35, 46, 56, 66, 76, -5, -15, -25, -35, -46, -56, -66, -76, + 5, 16, 27, 38, 50, 61, 72, 83, -5, -16, -27, -38, -50, -61, -72, -83, + 6, 18, 31, 43, 56, 68, 81, 93, -6, -18, -31, -43, -56, -68, -81, -93, + 6, 19, 33, 46, 61, 74, 88, 101, -6, -19, -33, -46, -61, -74, -88, -101, + 7, 22, 37, 52, 67, 82, 97, 112, -7, -22, -37, -52, -67, -82, -97, -112, + 8, 24, 41, 57, 74, 90, 107, 123, -8, -24, -41, -57, -74, -90, -107, -123, + 9, 27, 45, 63, 82, 100, 118, 136, -9, -27, -45, -63, -82, -100, -118, -136, + 10, 30, 50, 70, 90, 110, 130, 150, -10, -30, -50, -70, -90, -110, -130, -150, + 11, 33, 55, 77, 99, 121, 143, 165, -11, -33, -55, -77, -99, -121, -143, -165, + 12, 36, 60, 84, 109, 133, 157, 181, -12, -36, -60, -84, -109, -133, -157, -181, + 13, 39, 66, 92, 120, 146, 173, 199, -13, -39, -66, -92, -120, -146, -173, -199, + 14, 43, 73, 102, 132, 161, 191, 220, -14, -43, -73, -102, -132, -161, -191, -220, + 16, 48, 81, 113, 146, 178, 211, 243, -16, -48, -81, -113, -146, -178, -211, -243, + 17, 52, 88, 123, 160, 195, 231, 266, -17, -52, -88, -123, -160, -195, -231, -266, + 19, 58, 97, 136, 176, 215, 254, 293, -19, -58, -97, -136, -176, -215, -254, -293, + 21, 64, 107, 150, 194, 237, 280, 323, -21, -64, -107, -150, -194, -237, -280, -323, + 23, 70, 118, 165, 213, 260, 308, 355, -23, -70, -118, -165, -213, -260, -308, -355, + 26, 78, 130, 182, 235, 287, 339, 391, -26, -78, -130, -182, -235, -287, -339, -391, + 28, 85, 143, 200, 258, 315, 373, 430, -28, -85, -143, -200, -258, -315, -373, -430, + 31, 94, 157, 220, 284, 347, 410, 473, -31, -94, -157, -220, -284, -347, -410, -473, + 34, 103, 173, 242, 313, 382, 452, 521, -34, -103, -173, -242, -313, -382, -452, -521, + 38, 114, 191, 267, 345, 421, 498, 574, -38, -114, -191, -267, -345, -421, -498, -574, + 42, 126, 210, 294, 379, 463, 547, 631, -42, -126, -210, -294, -379, -463, -547, -631, + 46, 138, 231, 323, 417, 509, 602, 694, -46, -138, -231, -323, -417, -509, -602, -694, + 51, 153, 255, 357, 459, 561, 663, 765, -51, -153, -255, -357, -459, -561, -663, -765, + 56, 168, 280, 392, 505, 617, 729, 841, -56, -168, -280, -392, -505, -617, -729, -841, + 61, 184, 308, 431, 555, 678, 802, 925, -61, -184, -308, -431, -555, -678, -802, -925, + 68, 204, 340, 476, 612, 748, 884, 1020, -68, -204, -340, -476, -612, -748, -884, -1020, + 74, 223, 373, 522, 672, 821, 971, 1120, -74, -223, -373, -522, -672, -821, -971, -1120, + 82, 246, 411, 575, 740, 904, 1069, 1233, -82, -246, -411, -575, -740, -904, -1069, -1233, + 90, 271, 452, 633, 814, 995, 1176, 1357, -90, -271, -452, -633, -814, -995, -1176, -1357, + 99, 298, 497, 696, 895, 1094, 1293, 1492, -99, -298, -497, -696, -895, -1094, -1293, -1492, + 109, 328, 547, 766, 985, 1204, 1423, 1642, -109, -328, -547, -766, -985, -1204, -1423, -1642, + 120, 360, 601, 841, 1083, 1323, 1564, 1804, -120, -360, -601, -841, -1083, -1323, -1564, -1804, + 132, 397, 662, 927, 1192, 1457, 1722, 1987, -132, -397, -662, -927, -1192, -1457, -1722, -1987, + 145, 436, 728, 1019, 1311, 1602, 1894, 2185, -145, -436, -728, -1019, -1311, -1602, -1894, -2185, + 160, 480, 801, 1121, 1442, 1762, 2083, 2403, -160, -480, -801, -1121, -1442, -1762, -2083, -2403, + 176, 528, 881, 1233, 1587, 1939, 2292, 2644, -176, -528, -881, -1233, -1587, -1939, -2292, -2644, + 194, 582, 970, 1358, 1746, 2134, 2522, 2910, -194, -582, -970, -1358, -1746, -2134, -2522, -2910 +}; +static const int16_t index_shift[8] = { -1, -1, -1, -1, 2, 4, 6, 8 }; + +void MSM6585_init (MSM6585* chip, int32 newHostClock, int (*newGetInput)(void)) { + chip->hostClock = newHostClock; + chip->getInput = newGetInput; + AddExState(&chip->whichNibble, 1, 0, "MSMW"); + AddExState(&chip->input, 1, 0, "MSMI"); + AddExState(&chip->signal, 2 | FCEUSTATE_RLSB, 0, "MSMO"); + AddExState(&chip->count, 4 | FCEUSTATE_RLSB, 0, "MSMC"); + AddExState(&chip->rate, 4 | FCEUSTATE_RLSB, 0, "MSMR"); + AddExState(&chip->step, 2 | FCEUSTATE_RLSB, 0, "MSMS"); +} + +void MSM6585_reset (MSM6585* chip) { + chip->count = 0; + chip->step = 0; + chip->signal = -2; +} + +void MSM6585_setRate (MSM6585* chip, uint8 rateByte) { + chip->rate = 4000 <<(rateByte &3); +} + +void MSM6585_run (MSM6585* chip) { + chip->count += chip->rate; + while (chip->count >= chip->hostClock) { + uint8_t nibble; + chip->count -= chip->hostClock; + if (chip->whichNibble) + nibble = chip->input &0x0F; + else { + chip->input = chip->getInput(); + nibble = chip->input >>4; + } + chip->whichNibble = !chip->whichNibble; + chip->signal += diff_lookup[chip->step *16 +nibble]; + if (chip->signal > 2047) chip->signal = 2047; + if (chip->signal <-2048) chip->signal =-2048; + chip->step += index_shift[nibble &7]; + if (chip->step > 48) chip->step = 48; + if (chip->step < 0) chip->step = 0; + } +} + +int32_t MSM6585_getOutput (MSM6585* chip) { + return chip->signal; +} diff --git a/src/boards/msm6585.h b/src/boards/msm6585.h new file mode 100644 index 0000000..ce50d04 --- /dev/null +++ b/src/boards/msm6585.h @@ -0,0 +1,19 @@ +#ifndef _MSM6585_H +#define _MSM6585_H +typedef struct { + uint8 whichNibble; + uint8 input; + int16 signal; + int32 count; + int32 hostClock; + int32 rate; + int16 step; + int (*getInput)(void); +} MSM6585; + +void MSM6585_init (MSM6585*, int32, int (*)(void)); +void MSM6585_reset (MSM6585*); +void MSM6585_setRate (MSM6585*, uint8); +void MSM6585_run (MSM6585*); +int32_t MSM6585_getOutput (MSM6585*); +#endif diff --git a/src/boards/onebus.c b/src/boards/onebus.c index c4698bf..534a749 100644 --- a/src/boards/onebus.c +++ b/src/boards/onebus.c @@ -230,7 +230,7 @@ static DECLFW(UNLOneBusWriteMMC3) { break; } case 0xa000: mirror = V; Sync(); break; - case 0xc000: IRQLatch = V & 0xfe; break; + case 0xc000: IRQLatch = V; break; case 0xc001: IRQReload = 1; break; case 0xe000: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; break; case 0xe001: IRQa = 1; break; @@ -289,12 +289,14 @@ static DECLFR(UNLOneBusReadAPU40XX) { result = (result & 0x7f) | pcm_irq; } break; + case 0x17: + if (cpu410x[0x0B] == 0x14) result = result &~0x04 | (dipswitch &1? 0x04: 0x00); /* Super Joy III pad */ } return result; } -static DECLFR(readDIP) { - return dipswitch; +static DECLFR(readDIP_FamilyPocket) { + return dipswitch &1? 8: 0; } static void UNLOneBusCpuHook(int a) { @@ -337,7 +339,7 @@ static void UNLOneBusPower(void) { SetReadHandler(0x4000, 0x403f, UNLOneBusReadAPU40XX); SetWriteHandler(0x4000, 0x403f, UNLOneBusWriteAPU40XX); - SetReadHandler(0x412C, 0x412C, readDIP); + SetReadHandler(0x412C, 0x412C, readDIP_FamilyPocket); SetReadHandler(0x6000, 0xFFFF, CartBR); SetWriteHandler(0x6000, 0x7FFF, CartBW); SetWriteHandler(0x2010, 0x201f, UNLOneBusWritePPU201X); @@ -360,7 +362,7 @@ static void UNLOneBusReset(void) { cpu410x[0x0F] =0xFF; cpu410x[0x1C] =submapper ==12 || submapper ==14? 0x40: 0x00; reg4242 =0; - dipswitch ^=8; + dipswitch++; Sync(); } diff --git a/src/boards/sl1632.c b/src/boards/sl1632.c deleted file mode 100644 index 33c38ee..0000000 --- a/src/boards/sl1632.c +++ /dev/null @@ -1,111 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * SL1632 2-in-1 protected board, similar to SL12 - * Samurai Spirits Rex (Full) - * - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 chrcmd[8], prg0, prg1, bbrk, mirr, swap; -static SFORMAT StateRegs[] = -{ - { chrcmd, 8, "CHRC" }, - { &prg0, 1, "PRG0" }, - { &prg1, 1, "PRG1" }, - { &bbrk, 1, "BRK" }, - { &mirr, 1, "MIRR" }, - { &swap, 1, "SWAP" }, - { 0 } -}; - -static void Sync(void) { - int i; - setprg8(0x8000, prg0); - setprg8(0xA000, prg1); - setprg8(0xC000, ~1); - setprg8(0xE000, ~0); - for (i = 0; i < 8; i++) - setchr1(i << 10, chrcmd[i]); - setmirror(mirr ^ 1); -} - -static void UNLSL1632CW(uint32 A, uint8 V) { - int cbase = (MMC3_cmd & 0x80) << 5; - int page0 = (bbrk & 0x08) << 5; - int page1 = (bbrk & 0x20) << 3; - int page2 = (bbrk & 0x80) << 1; - setchr1(cbase ^ 0x0000, page0 | (DRegBuf[0] & (~1))); - setchr1(cbase ^ 0x0400, page0 | DRegBuf[0] | 1); - setchr1(cbase ^ 0x0800, page0 | (DRegBuf[1] & (~1))); - setchr1(cbase ^ 0x0C00, page0 | DRegBuf[1] | 1); - setchr1(cbase ^ 0x1000, page1 | DRegBuf[2]); - setchr1(cbase ^ 0x1400, page1 | DRegBuf[3]); - setchr1(cbase ^ 0x1800, page2 | DRegBuf[4]); - setchr1(cbase ^ 0x1c00, page2 | DRegBuf[5]); -} - -static DECLFW(UNLSL1632CMDWrite) { - if (A == 0xA131) { - bbrk = V; - } - if (bbrk & 2) { - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); - if (A < 0xC000) - MMC3_CMDWrite(A, V); - else - MMC3_IRQWrite(A, V); - } else { - if ((A >= 0xB000) && (A <= 0xE003)) { - int ind = ((((A & 2) | (A >> 10)) >> 1) + 2) & 7; - int sar = ((A & 1) << 2); - chrcmd[ind] = (chrcmd[ind] & (0xF0 >> sar)) | ((V & 0x0F) << sar); - } else - switch (A & 0xF003) { - case 0x8000: prg0 = V; break; - case 0xA000: prg1 = V; break; - case 0x9000: mirr = V & 1; break; - } - Sync(); - } -} - -static void StateRestore(int version) { - if (bbrk & 2) { - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); - } else - Sync(); -} - -static void UNLSL1632Power(void) { - GenMMC3Power(); - SetWriteHandler(0x4100, 0xFFFF, UNLSL1632CMDWrite); -} - -void UNLSL1632_Init(CartInfo *info) { - GenMMC3_Init(info, 256, 512, 0, 0); - cwrap = UNLSL1632CW; - info->Power = UNLSL1632Power; - GameStateRestore = StateRestore; - AddExState(&StateRegs, ~0, 0, 0); -} diff --git a/src/boards/unrom512.c b/src/boards/unrom512.c index ca3f63b..4f136d0 100644 --- a/src/boards/unrom512.c +++ b/src/boards/unrom512.c @@ -43,6 +43,7 @@ static uint8 fceumm_flash_buf[flashdata_size + flash_write_count_size]; static uint32 fceumm_flash_buf_size = sizeof(fceumm_flash_buf); +static uint8 submapper; static uint8 latche, latcheinit, bus_conflict, chrram_mask, software_id=0; static uint16 latcha; static uint8 *flashdata = fceumm_flash_buf + flash_write_count_size; @@ -135,11 +136,11 @@ static void UNROM512LatchPower(void) { latche = latcheinit; WHSync(); SetReadHandler(0x8000, 0xFFFF, UNROM512LatchRead); - if (!flash_save) + if (submapper == 0 && !flash_save || submapper == 2) SetWriteHandler(0x8000, 0xFFFF, UNROM512HLatchWrite); else { - SetWriteHandler(0x8000, 0xBFFF, UNROM512LLatchWrite); + if (submapper != 4) SetWriteHandler(0x8000, 0xBFFF, UNROM512LLatchWrite); SetWriteHandler(0xC000, 0xFFFF, UNROM512HLatchWrite); } } @@ -205,12 +206,15 @@ static void UNROM512HSync(void) { setfprg16(0x8000, flash_bank); setfprg16(0xC000, ~0); setchr8r(0, (latche & chrram_mask) >> 5); - setmirror(MI_0 + (latche >> 7)); + if (submapper == 3) + setmirror(latche &0x80? MI_V: MI_H); + else + setmirror(MI_0 + (latche >> 7)); } void UNROM512_Init(CartInfo *info) { int mirror; - + submapper = info->submapper; memset(fceumm_flash_buf, 0x00, fceumm_flash_buf_size); flash_state = 0; flash_bank = 0; @@ -224,6 +228,9 @@ void UNROM512_Init(CartInfo *info) { chrram_mask = 0x60; mirror = (head.ROM_type & 1) | ((head.ROM_type & 8) >> 2); + if (submapper == 3) /* Mega Man II (30th Anniversary Edition): switchable H/V */ + SetupCartMirroring(MI_V, 0, NULL); + else switch (mirror) { case 0: /* hard horizontal, internal */ SetupCartMirroring(MI_H, 1, NULL); @@ -238,7 +245,7 @@ void UNROM512_Init(CartInfo *info) { SetupCartMirroring(4, 1, VROM + (info->CHRRamSize - 8192)); break; } - bus_conflict = !info->battery; + bus_conflict = submapper == 0 && !info->battery || submapper == 2; latcheinit = 0; WLSync = UNROM512LSync; WHSync = UNROM512HSync; diff --git a/src/boards/vrc2and4.c b/src/boards/vrc2and4.c deleted file mode 100644 index 3994da7..0000000 --- a/src/boards/vrc2and4.c +++ /dev/null @@ -1,246 +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; - } -} - -static void StateRestore(int version) { - VRC24_Sync(); -} - -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 =StateRestore; - 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/ines.c b/src/ines.c index c30942f..0d0b35f 100644 --- a/src/ines.c +++ b/src/ines.c @@ -575,7 +575,7 @@ INES_BOARD_BEGIN() INES_BOARD( "NES-TQROM", 119, Mapper119_Init ) INES_BOARD( "FDS TOBIDASE", 120, Mapper120_Init ) INES_BOARD( "MMC3 PIRATE PROT. A", 121, Mapper121_Init ) -/* INES_BOARD( "", 122, Mapper122_Init ) */ + INES_BOARD( "JY043", 122, Mapper122_Init ) INES_BOARD( "MMC3 PIRATE H2288", 123, UNLH2288_Init ) /* INES_BOARD( "", 124, Mapper124_Init ) */ INES_BOARD( "FDS LH32", 125, LH32_Init ) @@ -635,7 +635,7 @@ INES_BOARD_BEGIN() /* INES_BOARD( "", 179, Mapper179_Init ) */ INES_BOARD( "", 180, Mapper180_Init ) INES_BOARD( "", 181, Mapper181_Init ) -/* INES_BOARD( "", 182, Mapper182_Init ) */ /* Deprecated, dupe of Mapper 114 */ + INES_BOARD( "YH-001", 182, Mapper182_Init ) INES_BOARD( "", 183, Mapper183_Init ) INES_BOARD( "", 184, Mapper184_Init ) INES_BOARD( "", 185, Mapper185_Init ) @@ -666,7 +666,7 @@ INES_BOARD_BEGIN() INES_BOARD( "", 210, Mapper210_Init ) INES_BOARD( "HUMMER/JY BOARD", 211, Mapper211_Init ) INES_BOARD( "", 212, Mapper212_Init ) - INES_BOARD( "", 213, Mapper58_Init ) /* in mapper 58 */ + INES_BOARD( "EJ-3003/820428-C", 213, Mapper213_Init ) INES_BOARD( "", 214, Mapper214_Init ) INES_BOARD( "UNL-8237", 215, UNL8237_Init ) INES_BOARD( "", 216, Mapper216_Init ) @@ -692,7 +692,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Realtec 8031/8155/8099/8106", 236, Mapper236_Init ) INES_BOARD( "Teletubbies / Y2K", 237, Mapper237_Init ) INES_BOARD( "UNL6035052", 238, UNL6035052_Init ) -/* INES_BOARD( "", 239, Mapper239_Init ) */ + INES_BOARD( "OK-043", 239, Mapper239_Init ) INES_BOARD( "", 240, Mapper240_Init ) INES_BOARD( "", 241, Mapper241_Init ) INES_BOARD( "43272", 242, Mapper242_Init ) @@ -728,13 +728,14 @@ INES_BOARD_BEGIN() INES_BOARD( "OneBus+412C Bankswitch", 270, Mapper270_Init ) INES_BOARD( "MGC-026", 271, Mapper271_Init ) INES_BOARD( "Akumajō Special: Boku Dracula-kun", 272, Mapper272_Init ) + INES_BOARD( "J-3?-C", 273, Mapper273_Init ) INES_BOARD( "80013-B", 274, BMC80013B_Init ) INES_BOARD( "", 277, Mapper277_Init ) INES_BOARD( "K-3017", 280, Mapper280_Init ) INES_BOARD( "YY860417C", 281, Mapper281_Init ) INES_BOARD( "860224C", 282, Mapper282_Init ) INES_BOARD( "GS-2004/GS-2013", 283, Mapper283_Init ) - INES_BOARD( "A65AS", 285, BMCA65AS_Init ) + INES_BOARD( "A65AS", 285, Mapper285_Init ) INES_BOARD( "BS-5", 286, BMCBS5_Init ) INES_BOARD( "411120-C, 811120-C", 287, BMC411120C_Init ) INES_BOARD( "GKCX1", 288, Mapper288_Init ) @@ -765,6 +766,7 @@ INES_BOARD_BEGIN() INES_BOARD( "830134C", 315, BMC830134C_Init ) INES_BOARD( "HP898F", 319, Mapper319_Init ) INES_BOARD( "830425C-4391T", 320, BMC830425C4391T_Init ) + INES_BOARD( "820310", 321, Mapper321_Init ) INES_BOARD( "K-3033", 322, BMCK3033_Init ) INES_BOARD( "FARID_SLROM_8-IN-1", 323, FARIDSLROM8IN1_Init ) INES_BOARD( "FARID_UNROM_8-IN-1", 324, FARIDUNROM_Init ) @@ -794,6 +796,7 @@ INES_BOARD_BEGIN() INES_BOARD( "G-146", 349, BMCG146_Init ) INES_BOARD( "891227", 350, BMC891227_Init ) INES_BOARD( "Techline XB", 351, Mapper351_Init ) + INES_BOARD( "Reset-based NROM-256", 352, Mapper352_Init ) INES_BOARD( "Super Mario Family", 353, Mapper353_Init ) INES_BOARD( "FAM250/81-01-39-C/SCHI-24",354, Mapper354_Init ) INES_BOARD( "3D-BLOCK", 355, UNL3DBlock_Init ) @@ -802,10 +805,11 @@ INES_BOARD_BEGIN() INES_BOARD( "YY860606C", 358, Mapper358_Init ) INES_BOARD( "SB-5013/GCL8050/841242C", 359, Mapper359_Init ) INES_BOARD( "Bitcorp 31-in-1", 360, Mapper360_Init ) - INES_BOARD( "OK-411", 361, GN45_Init ) /* OK-411 is emulated together with GN-45 */ + INES_BOARD( "OK-411", 361, Mapper361_Init ) INES_BOARD( "830506C", 362, Mapper362_Init ) + INES_BOARD( "5069", 363, Mapper363_Init ) INES_BOARD( "JY830832C", 364, Mapper364_Init ) - INES_BOARD( "GN-45", 366, GN45_Init ) + INES_BOARD( "GN-45", 366, Mapper366_Init ) INES_BOARD( "JC-016-2 variant", 367, Mapper367_Init ) INES_BOARD( "Yung-08", 368, Mapper368_Init ) INES_BOARD( "N49C-300", 369, Mapper369_Init ) @@ -816,6 +820,8 @@ INES_BOARD_BEGIN() INES_BOARD( "135-in-1", 375, Mapper375_Init ) INES_BOARD( "YY841155C", 376, Mapper376_Init ) INES_BOARD( "JY-111/JY-112", 377, Mapper377_Init ) + INES_BOARD( "8-in-1 AOROM+UNROM", 378, Mapper378_Init ) + INES_BOARD( "35BH-1", 379, Mapper379_Init ) INES_BOARD( "42 to 80,000 (970630C)", 380, Mapper380_Init ) INES_BOARD( "KN-42", 381, Mapper381_Init ) INES_BOARD( "830928C", 382, Mapper382_Init ) @@ -836,6 +842,7 @@ INES_BOARD_BEGIN() INES_BOARD( "YY850439C", 397, Mapper397_Init ) INES_BOARD( "YY840820C", 398, Mapper398_Init ) INES_BOARD( "BATMAP-000", 399, Mapper399_Init ) + INES_BOARD( "8BIT-XMAS", 400, Mapper400_Init ) INES_BOARD( "BMC Super 19-in-1 (VIP19)",401, Mapper401_Init ) INES_BOARD( "831019C J-2282", 402, J2282_Init ) INES_BOARD( "89433", 403, Mapper403_Init ) @@ -850,6 +857,7 @@ INES_BOARD_BEGIN() INES_BOARD( "0353", 415, Mapper415_Init ) INES_BOARD( "4-in-1/N-32", 416, Mapper416_Init ) INES_BOARD( "", 417, Mapper417_Init ) + INES_BOARD( "820106-C/821007C", 418, Mapper418_Init ) INES_BOARD( "A971210", 420, Mapper420_Init ) INES_BOARD( "SC871115C", 421, Mapper421_Init ) INES_BOARD( "BS-400R/BS-4040", 422, Mapper422_Init ) @@ -869,6 +877,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 ) @@ -883,7 +892,7 @@ INES_BOARD_BEGIN() INES_BOARD( "", 458, Mapper458_Init ) INES_BOARD( "8-in-1", 459, Mapper459_Init ) INES_BOARD( "FC-29-40/K-3101", 460, Mapper460_Init ) - INES_BOARD( "0324", 461, Mapper461_Init ) + INES_BOARD( "CM-9309", 461, Mapper461_Init ) INES_BOARD( "BMC-971107-00G", 462, Mapper462_Init ) INES_BOARD( "YH810X1", 463, Mapper463_Init ) INES_BOARD( "NTDEC 9012", 464, Mapper464_Init ) @@ -903,16 +912,38 @@ INES_BOARD_BEGIN() INES_BOARD( "480", 480, Mapper480_Init ) INES_BOARD( "045N", 481, Mapper481_Init ) INES_BOARD( "K-1079", 482, Mapper482_Init ) + INES_BOARD( "3927", 483, Mapper483_Init ) INES_BOARD( "ESTIQUE", 484, Mapper484_Init ) INES_BOARD( "0359", 485, Mapper485_Init ) INES_BOARD( "KS7009", 486, Mapper486_Init ) INES_BOARD( "AVE NINA-08", 487, Mapper487_Init ) INES_BOARD( "HC001", 488, Mapper488_Init ) + INES_BOARD( "N-80", 489, Mapper489_Init ) + INES_BOARD( "K-3101", 490, Mapper490_Init ) + INES_BOARD( "Sane Ting 5-in-1", 491, Mapper491_Init ) + INES_BOARD( "K-3069/12-28", 492, Mapper492_Init ) + INES_BOARD( "AVE-NTDEC 30-in-1", 493, Mapper493_Init ) + INES_BOARD( "CH512K/OK-103", 494, Mapper494_Init ) + INES_BOARD( "N-46", 495, Mapper495_Init ) + INES_BOARD( "K-3011", 498, Mapper498_Init ) + INES_BOARD( "FC-41", 499, Mapper499_Init ) INES_BOARD( "Yhc-000", 500, Mapper500_Init ) INES_BOARD( "Yhc-001", 501, Mapper501_Init ) INES_BOARD( "Yhc-002", 502, Mapper502_Init ) + INES_BOARD( "ET-170", 503, Mapper503_Init ) + INES_BOARD( "K-3054", 504, Mapper504_Init ) + INES_BOARD( "5426757A-Y2-230630", 505, Mapper505_Init ) + INES_BOARD( "GA-009", 506, Mapper506_Init ) + INES_BOARD( "A-018", 507, Mapper507_Init ) + INES_BOARD( "JY-014", 508, Mapper508_Init ) + INES_BOARD( "K-3022", 509, Mapper509_Init ) + INES_BOARD( "FC-53A", 510, Mapper510_Init ) + INES_BOARD( "1n4148", 511, Mapper511_Init ) + INES_BOARD( "Zhonggguo Daheng", 512, Mapper512_Init ) INES_BOARD( "SA-9602B", 513, SA9602B_Init ) - INES_BOARD( "Brilliant Com Cocoma Pack",516, Mapper516_Init ) + INES_BOARD( "Subor Karaoke", 514, Mapper514_Init ) + INES_BOARD( "Brilliant Com Cocoma Pack",516, Mapper516_Init ) + INES_BOARD( "Kkachi-wa Nolae Chingu", 517, UNROM_Init ) /* Microphone input currently not emulated */ INES_BOARD( "DANCE2000", 518, UNLD2000_Init ) INES_BOARD( "EH8813A", 519, UNLEH8813A_Init ) INES_BOARD( "YuYuHakusho+DBZ", 520, Mapper520_Init ) @@ -929,6 +960,8 @@ INES_BOARD_BEGIN() INES_BOARD( "Sachen 3014", 533, Mapper533_Init ) INES_BOARD( "NJ064", 534, Mapper534_Init ) INES_BOARD( "LH53", 535, LH53_Init ) + INES_BOARD( "N42S-2", 536, Mapper536_Init ) + INES_BOARD( "JY4M4", 537, Mapper537_Init ) INES_BOARD( "60-1064-16L (FDS)", 538, Mapper538_Init ) INES_BOARD( "Kid Ikarus (FDS)", 539, Mapper539_Init ) INES_BOARD( "82112C", 540, Mapper540_Init ) @@ -936,17 +969,54 @@ INES_BOARD_BEGIN() INES_BOARD( "JYV610 830626C", 542, Mapper542_Init ) INES_BOARD( "5-in-1 (CH-501)", 543, Mapper543_Init ) INES_BOARD( "WAIXING FS306", 544, Mapper544_Init ) + INES_BOARD( "ST-80", 545, Mapper545_Init ) + INES_BOARD( "03-101", 546, Mapper546_Init ) + INES_BOARD( "CTC-15", 548, Mapper548_Init ) + INES_BOARD( "Kaiser KS-7016B", 549, Mapper549_Init ) + INES_BOARD( "", 550, Mapper550_Init ) INES_BOARD( "", 551, Mapper178_Init ) + INES_BOARD( "TAITO X1-017", 552, Mapper552_Init ) INES_BOARD( "SACHEN 3013", 553, Mapper553_Init ) INES_BOARD( "KS-7010", 554, Mapper554_Init ) INES_BOARD( "", 555, Mapper555_Init ) INES_BOARD( "JY-215", 556, Mapper556_Init ) - INES_BOARD( "", 550, Mapper550_Init ) + INES_BOARD( "NTDEC 2718", 557, Mapper557_Init ) INES_BOARD( "YC-03-09", 558, Mapper558_Init ) INES_BOARD( "Subor Sango II", 559, Mapper559_Init ) INES_BOARD( "Bung Super Game Doctor", 561, Mapper561_562_Init ) INES_BOARD( "Venus Turbo Game Doctor", 562, Mapper561_562_Init ) INES_BOARD( "J-2020", 563, Mapper563_Init ) + INES_BOARD( "bd23.pcb", 564, Mapper564_Init ) + INES_BOARD( "J-33-C", 565, Mapper565_Init ) + INES_BOARD( "ET-149", 566, Mapper566_Init ) + INES_BOARD( "Top Ten Variety (SF III)", 567, Mapper567_Init ) + INES_BOARD( "T-227", 568, Mapper568_Init ) + INES_BOARD( "820315-C", 569, Mapper569_Init ) + INES_BOARD( "9052", 570, Mapper570_Init ) + INES_BOARD( "JC-011", 571, Mapper571_Init ) + INES_BOARD( "F-648", 572, Mapper572_Init ) + INES_BOARD( "5068", 573, Mapper573_Init ) + INES_BOARD( "FC-40", 574, Mapper574_Init ) + INES_BOARD( "W-03", 575, Mapper575_Init ) + INES_BOARD( "J-2096", 576, Mapper576_Init ) + INES_BOARD( "KN-29", 577, Mapper577_Init ) + INES_BOARD( "910610", 578, Mapper578_Init ) + INES_BOARD( "T-215", 579, Mapper579_Init ) + INES_BOARD( "ET-156", 580, Mapper580_Init ) + INES_BOARD( "ET-82", 581, Mapper581_Init ) + INES_BOARD( "A9778", 582, Mapper582_Init ) + INES_BOARD( "8203", 583, Mapper583_Init ) + INES_BOARD( "ST-32", 584, Mapper584_Init ) + INES_BOARD( "FE-01-1", 585, Mapper585_Init ) + INES_BOARD( "HN-02", 586, Mapper586_Init ) + INES_BOARD( "3355", 587, Mapper587_Init ) + INES_BOARD( "ET-81", 588, Mapper588_Init ) + INES_BOARD( "810706", 589, Mapper589_Init ) + INES_BOARD( "810430", 590, Mapper590_Init ) + INES_BOARD( "07027/810543", 591, Mapper591_Init ) + INES_BOARD( "8-in-1 1991", 592, Mapper592_Init ) + INES_BOARD( "Rinco FSG2", 594, Mapper594_Init ) + INES_BOARD( "4MROM-512", 595, Mapper595_Init ) INES_BOARD_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index 07d87fc..2caf764 100644 --- a/src/ines.h +++ b/src/ines.h @@ -150,6 +150,7 @@ void Mapper117_Init(CartInfo *); void Mapper119_Init(CartInfo *); void Mapper120_Init(CartInfo *); void Mapper121_Init(CartInfo *); +void Mapper122_Init(CartInfo *); void Mapper125_Init(CartInfo *); void Mapper126_Init(CartInfo *); void Mapper128_Init(CartInfo *); @@ -186,6 +187,7 @@ void Mapper177_Init(CartInfo *); void Mapper178_Init(CartInfo *); void Mapper180_Init(CartInfo *); void Mapper181_Init(CartInfo *); +void Mapper182_Init(CartInfo *); void Mapper183_Init(CartInfo *); void Mapper184_Init(CartInfo *); void Mapper185_Init(CartInfo *); @@ -236,6 +238,7 @@ void Mapper234_Init(CartInfo *); void Mapper235_Init(CartInfo *); void Mapper236_Init(CartInfo *); void Mapper237_Init(CartInfo *); +void Mapper239_Init(CartInfo *); void Mapper240_Init(CartInfo *); void Mapper241_Init(CartInfo *); void Mapper242_Init(CartInfo *); @@ -248,10 +251,9 @@ void Mapper252_Init(CartInfo *); void Mapper253_Init(CartInfo *); void Mapper254_Init(CartInfo *); void Mapper255_Init(CartInfo *); - -void GN45_Init(CartInfo *info); /* m361, m366 */ void Mapper270_Init(CartInfo *); void Mapper272_Init(CartInfo *); +void Mapper273_Init(CartInfo *); void Mapper277_Init(CartInfo *); void Mapper280_Init(CartInfo *); void Mapper281_Init(CartInfo *); @@ -273,10 +275,12 @@ void Mapper294_Init(CartInfo *); void Mapper297_Init(CartInfo *); void Mapper310_Init(CartInfo *); void Mapper319_Init(CartInfo *); +void Mapper321_Init(CartInfo *); void Mapper326_Init(CartInfo *); void Mapper330_Init(CartInfo *); void Mapper334_Init(CartInfo *); void Mapper351_Init(CartInfo *); +void Mapper352_Init(CartInfo *); void Mapper353_Init(CartInfo *); void Mapper354_Init(CartInfo *); void Mapper356_Init(CartInfo *); @@ -284,8 +288,11 @@ void Mapper357_Init(CartInfo *); void Mapper358_Init(CartInfo *); void Mapper359_Init(CartInfo *); void Mapper360_Init(CartInfo *); +void Mapper361_Init(CartInfo *); void Mapper362_Init(CartInfo *); +void Mapper363_Init(CartInfo *); void Mapper364_Init(CartInfo *); +void Mapper366_Init(CartInfo *); void Mapper367_Init(CartInfo *); void Mapper368_Init(CartInfo *); void Mapper369_Init(CartInfo *); @@ -296,6 +303,8 @@ void Mapper374_Init(CartInfo *); void Mapper375_Init(CartInfo *); void Mapper376_Init(CartInfo *); void Mapper377_Init(CartInfo *); +void Mapper378_Init(CartInfo *); +void Mapper379_Init(CartInfo *); void Mapper380_Init(CartInfo *); void Mapper381_Init(CartInfo *); void Mapper382_Init(CartInfo *); @@ -316,6 +325,7 @@ void Mapper396_Init(CartInfo *); void Mapper397_Init(CartInfo *); void Mapper398_Init(CartInfo *); void Mapper399_Init(CartInfo *); +void Mapper400_Init(CartInfo *); void Mapper401_Init(CartInfo *); void Mapper403_Init(CartInfo *); void Mapper404_Init(CartInfo *); @@ -329,6 +339,7 @@ void Mapper414_Init(CartInfo *); void Mapper415_Init(CartInfo *); void Mapper416_Init(CartInfo *); void Mapper417_Init(CartInfo *); +void Mapper418_Init(CartInfo *); void Mapper420_Init(CartInfo *); void Mapper421_Init(CartInfo *); void Mapper422_Init(CartInfo *); @@ -348,6 +359,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 *); @@ -382,20 +394,43 @@ void Mapper478_Init(CartInfo *); void Mapper480_Init(CartInfo *); void Mapper481_Init(CartInfo *); void Mapper482_Init(CartInfo *); +void Mapper483_Init(CartInfo *); void Mapper484_Init(CartInfo *); void Mapper485_Init(CartInfo *); void Mapper486_Init(CartInfo *); void Mapper487_Init(CartInfo *); void Mapper488_Init(CartInfo *); +void Mapper489_Init(CartInfo *); +void Mapper490_Init(CartInfo *); +void Mapper491_Init(CartInfo *); +void Mapper492_Init(CartInfo *); +void Mapper493_Init(CartInfo *); +void Mapper494_Init(CartInfo *); +void Mapper495_Init(CartInfo *); +void Mapper498_Init(CartInfo *); +void Mapper499_Init(CartInfo *); void Mapper500_Init(CartInfo *); void Mapper501_Init(CartInfo *); void Mapper502_Init(CartInfo *); +void Mapper503_Init(CartInfo *); +void Mapper504_Init(CartInfo *); +void Mapper505_Init(CartInfo *); +void Mapper506_Init(CartInfo *); +void Mapper507_Init(CartInfo *); +void Mapper508_Init(CartInfo *); +void Mapper509_Init(CartInfo *); +void Mapper510_Init(CartInfo *); +void Mapper511_Init(CartInfo *); +void Mapper512_Init(CartInfo *); +void Mapper514_Init(CartInfo *); void Mapper516_Init(CartInfo *); void Mapper520_Init(CartInfo *); void Mapper523_Init(CartInfo *); void Mapper528_Init(CartInfo *); void Mapper533_Init(CartInfo *); void Mapper534_Init(CartInfo *); +void Mapper536_Init(CartInfo *); +void Mapper537_Init(CartInfo *); void Mapper538_Init(CartInfo *); void Mapper539_Init(CartInfo *); void Mapper540_Init(CartInfo *); @@ -403,15 +438,52 @@ void Mapper541_Init(CartInfo *); void Mapper542_Init(CartInfo *); void Mapper543_Init(CartInfo *); void Mapper544_Init(CartInfo *); +void Mapper545_Init(CartInfo *); +void Mapper546_Init(CartInfo *); +void Mapper548_Init(CartInfo *); +void Mapper549_Init(CartInfo *); void Mapper550_Init(CartInfo *); +void Mapper552_Init(CartInfo *); void Mapper553_Init(CartInfo *); void Mapper554_Init(CartInfo *); void Mapper555_Init(CartInfo *); void Mapper556_Init(CartInfo *); +void Mapper557_Init(CartInfo *); void Mapper558_Init(CartInfo *); void Mapper559_Init(CartInfo *); void Mapper561_562_Init(CartInfo *); void Mapper563_Init(CartInfo *); +void Mapper564_Init(CartInfo *); +void Mapper565_Init(CartInfo *); +void Mapper566_Init(CartInfo *); +void Mapper567_Init(CartInfo *); +void Mapper568_Init(CartInfo *); +void Mapper569_Init(CartInfo *); +void Mapper570_Init(CartInfo *); +void Mapper571_Init(CartInfo *); +void Mapper572_Init(CartInfo *); +void Mapper573_Init(CartInfo *); +void Mapper574_Init(CartInfo *); +void Mapper575_Init(CartInfo *); +void Mapper576_Init(CartInfo *); +void Mapper577_Init(CartInfo *); +void Mapper578_Init(CartInfo *); +void Mapper579_Init(CartInfo *); +void Mapper580_Init(CartInfo *); +void Mapper581_Init(CartInfo *); +void Mapper582_Init(CartInfo *); +void Mapper583_Init(CartInfo *); +void Mapper584_Init(CartInfo *); +void Mapper585_Init(CartInfo *); +void Mapper586_Init(CartInfo *); +void Mapper587_Init(CartInfo *); +void Mapper588_Init(CartInfo *); +void Mapper589_Init(CartInfo *); +void Mapper590_Init(CartInfo *); +void Mapper591_Init(CartInfo *); +void Mapper592_Init(CartInfo *); +void Mapper594_Init(CartInfo *); +void Mapper595_Init(CartInfo *); void FFE_Init(CartInfo *); diff --git a/src/unif.c b/src/unif.c index a022ec8..6667abf 100644 --- a/src/unif.c +++ b/src/unif.c @@ -437,7 +437,7 @@ static BMAPPING bmap[] = { { "8237", 215, UNL8237_Init, 0 }, { "8237A", 215, UNL8237A_Init, 0 }, { "830118C", 348, BMC830118C_Init, 0 }, - { "A65AS", 285, BMCA65AS_Init, 0 }, + { "A65AS", 285, Mapper285_Init, 0 }, { "AB-G1L", 428, Mapper428_Init, 0 }, { "WELL-NO-DG450", 428, Mapper428_Init, 0 }, { "TF2740", 428, Mapper428_Init, 0 }, @@ -626,7 +626,15 @@ static BMAPPING bmap[] = { { "K86B", 439, Mapper439_Init, 0 }, { "COOLGIRL", 342, COOLGIRL_Init, BMCFLAG_256KCHRR }, { "S-2009", 434, Mapper434_Init, 0 }, - + { "Yhc-Unrom-Cart", 500, Mapper500_Init, 0 }, + { "Yhc-Axrom-Cart", 501, Mapper501_Init, 0 }, + { "Yhc-A/B/Uxrom-Cart", 502, Mapper502_Init, 0 }, + { "JY4M4", 537, Mapper537_Init, 0 }, + { "82112C", 540, Mapper540_Init, 0 }, + { "KN-20", 577, Mapper577_Init, 0 }, + { "820436-C", 579, Mapper579_Init, 0 }, + { "8203", 585, Mapper585_Init, 0 }, + { "K-3057", 587, Mapper587_Init, 0 }, { NULL, NO_INES, NULL, 0 } }; diff --git a/src/unif.h b/src/unif.h index 353235a..4a07fe4 100644 --- a/src/unif.h +++ b/src/unif.h @@ -30,7 +30,7 @@ void BMC411120C_Init(CartInfo *info); void BMC64in1nr_Init(CartInfo *info); void BMC810544CA1_Init(CartInfo *info); void BMC830118C_Init(CartInfo *info); -void BMCA65AS_Init(CartInfo *info); +void Mapper285_Init(CartInfo *info); void BMCBS5_Init(CartInfo *info); void BMCD1038_Init(CartInfo *info); void BMCFK23CA_Init(CartInfo *info);