From 399daf7a61b25490118ce144d99d03786493c2d2 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sat, 6 Sep 2025 13:12:15 +0200 Subject: [PATCH] Mapper 14: use the modularized ASIC cores. Mapper 116: Add multicart variant. --- src/boards/116.c | 47 +++++++++++++------ src/boards/14.c | 101 ++++++++++++++++++++++++++++++++++++++++ src/boards/sl1632.c | 111 -------------------------------------------- 3 files changed, 133 insertions(+), 126 deletions(-) create mode 100644 src/boards/14.c delete mode 100644 src/boards/sl1632.c diff --git a/src/boards/116.c b/src/boards/116.c index f9052d4..d8ded64 100644 --- a/src/boards/116.c +++ b/src/boards/116.c @@ -18,10 +18,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* NES 2.0 Mapper 556 - * Used for the for the 餓狼傳說 激鬥篇 HiK 7-in-1 (JY-215) multicart. - */ - #include "mapinc.h" #include "asic_mmc1.h" #include "asic_mmc3.h" @@ -29,19 +25,33 @@ static uint8 submapper; static uint8 reg; -static uint8 init; +static uint8 init; /* Games switch between ASICs expecting registers to keep their value, so initialize each ASIC only on the first switch and use this bitfield */ +static uint8 game; -static SFORMAT StateRegs[] = { +static SFORMAT stateRegs[] = { { ®, 1, "MODE" }, { &init, 1, "INIT" }, { 0 }, }; +static SFORMAT stateRegsMulti[] = { + { &game, 1, "GAME" }, + { 0 }, +}; + static void sync (void) { - int prgAND = 0x3F; - int chrAND = 0xFF; - int prgOR = 0x00 &~prgAND; - int chrOR = reg <<6 &0x100 &~chrAND; + int prgAND, chrAND, prgOR, chrOR; + if (submapper == 3) { /* First game is 256K+256K, the others 128K+128K */ + prgAND = game? 0x0F: 0x1F; + chrAND = game? 0x7F: 0xFF; + prgOR = game <<4 &~prgAND; + chrOR = game <<7 &~chrAND; + } else { + prgAND = 0x3F; + chrAND = 0xFF; + prgOR = 0x00 &~prgAND; + chrOR = reg <<6 &0x100 &~chrAND; + } if (reg &0x02) { prgAND >>= 1; prgOR >>= 1; @@ -67,9 +77,12 @@ int Huang2_getPRGBank (uint8 bank) { } static void applyMode (uint8 clear) { + PPU_hook = NULL; + MapIRQHook = NULL; + GameHBIRQHook = NULL; if (reg &0x02) { MMC1_activate(clear && init &1, sync, MMC1_TYPE_MMC1B, submapper == 2? Huang2_getPRGBank: NULL, NULL, NULL, NULL); - MMC1_writeReg(0x8000, 0x80); + if (submapper != 1) MMC1_writeReg(0x8000, 0x80); init &= ~1; } else if (reg &0x01) { @@ -77,7 +90,7 @@ static void applyMode (uint8 clear) { init &= ~2; } else { VRC2_activate(clear && init &4, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); - if (init &4) { + if (init &4) { /* The earlier version of Somari needs specific VRC2 CHR register initialization */ VRC24_writeReg(0xB000, 0xFF); VRC24_writeReg(0xB001, 0xFF); VRC24_writeReg(0xB002, 0xFF); VRC24_writeReg(0xB003, 0xFF); VRC24_writeReg(0xC000, 0xFF); VRC24_writeReg(0xC001, 0xFF); VRC24_writeReg(0xC002, 0xFF); VRC24_writeReg(0xC003, 0xFF); VRC24_writeReg(0xD000, 0xFF); VRC24_writeReg(0xD001, 0xFF); VRC24_writeReg(0xD002, 0xFF); VRC24_writeReg(0xD003, 0xFF); @@ -99,14 +112,17 @@ static DECLFW(writeReg) { } static void reset (void) { - reg = 0; + reg = 1; init = 7; + if (++game == 1) ++game; /* First game is twice as large */ + if (game >= ROM_size /8) game = 0; applyMode(1); } static void power (void) { - reg = 0; + reg = 1; init = 7; + game = 0; SetReadHandler(0x8000, 0xFFFF, CartBR); SetWriteHandler(0x4020, 0x5FFF, writeReg); applyMode(1); @@ -124,5 +140,6 @@ void UNLSL12_Init (CartInfo *info) { info->Reset = reset; info->Power = power; GameStateRestore = restore; - AddExState(StateRegs, ~0, 0, 0); + AddExState(stateRegs, ~0, 0, 0); + if (submapper == 3) AddExState(stateRegsMulti, ~0, 0, 0); } diff --git a/src/boards/14.c b/src/boards/14.c new file mode 100644 index 0000000..1c974c3 --- /dev/null +++ b/src/boards/14.c @@ -0,0 +1,101 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_mmc3.h" +#include "asic_vrc2and4.h" + +static uint8 reg; +static uint8 init; /* Games switch between ASICs expecting registers to keep their value, so initialize each ASIC only on the first switch and use this bitfield */ +static void applyMode (uint8); + +static SFORMAT StateRegs[] = { + { ®, 1, "MODE" }, + { &init, 1, "INIT" }, + { 0 }, +}; + +static void sync (void) { + if (reg &0x02) { + MMC3_syncPRG(0x3F, 0x00); + MMC3_syncCHR(0x1FF, 0x00); + MMC3_syncMirror(); + } else { + VRC24_syncPRG(0x3F, 0x00); + VRC24_syncCHR(0x1FF, 0x00); + VRC24_syncMirror(); + } +} + +int getCHRBank_MMC3 (uint8 bank) { + return MMC3_getCHRBank(bank) | reg <<(~bank &4? 5: ~bank &2? 3: 1) &0x100; +} + +int getCHRBank_VRC2 (uint8 bank) { + return VRC24_getCHRBank(bank) | reg <<(~bank &4? 5: ~bank &2? 3: 1) &0x100; +} + +static DECLFW(writeReg) { + uint8 previousReg = reg; + reg = V; + if ((previousReg ^V) &2) + applyMode(1); + else + sync(); +} + +static void applyMode (uint8 clear) { + PPU_hook = NULL; + MapIRQHook = NULL; + GameHBIRQHook = NULL; + if (reg &0x02) { + MMC3_activate(clear && init &1, sync, MMC3_TYPE_AX5202P, NULL, getCHRBank_MMC3, NULL, NULL); + init &= ~1; + } else { + VRC2_activate(clear && init &2, sync, 0x01, 0x02, NULL, getCHRBank_VRC2, NULL, NULL); + init &= ~2; + } + SetWriteHandler(0xA131, 0xA131, writeReg); +} + +static void reset (void) { + reg = 0; + init = 3; + applyMode(1); +} + +static void power (void) { + reg = 0; + init = 3; + applyMode(1); +} + +static void restore (int version) { + applyMode(0); +} + +void UNLSL1632_Init (CartInfo *info) { + MMC3_addExState(); + VRC24_addExState(); + info->Reset = reset; + info->Power = power; + GameStateRestore = restore; + AddExState(StateRegs, ~0, 0, 0); +} diff --git a/src/boards/sl1632.c b/src/boards/sl1632.c deleted file mode 100644 index 33c38ee..0000000 --- a/src/boards/sl1632.c +++ /dev/null @@ -1,111 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * SL1632 2-in-1 protected board, similar to SL12 - * Samurai Spirits Rex (Full) - * - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 chrcmd[8], prg0, prg1, bbrk, mirr, swap; -static SFORMAT StateRegs[] = -{ - { chrcmd, 8, "CHRC" }, - { &prg0, 1, "PRG0" }, - { &prg1, 1, "PRG1" }, - { &bbrk, 1, "BRK" }, - { &mirr, 1, "MIRR" }, - { &swap, 1, "SWAP" }, - { 0 } -}; - -static void Sync(void) { - int i; - setprg8(0x8000, prg0); - setprg8(0xA000, prg1); - setprg8(0xC000, ~1); - setprg8(0xE000, ~0); - for (i = 0; i < 8; i++) - setchr1(i << 10, chrcmd[i]); - setmirror(mirr ^ 1); -} - -static void UNLSL1632CW(uint32 A, uint8 V) { - int cbase = (MMC3_cmd & 0x80) << 5; - int page0 = (bbrk & 0x08) << 5; - int page1 = (bbrk & 0x20) << 3; - int page2 = (bbrk & 0x80) << 1; - setchr1(cbase ^ 0x0000, page0 | (DRegBuf[0] & (~1))); - setchr1(cbase ^ 0x0400, page0 | DRegBuf[0] | 1); - setchr1(cbase ^ 0x0800, page0 | (DRegBuf[1] & (~1))); - setchr1(cbase ^ 0x0C00, page0 | DRegBuf[1] | 1); - setchr1(cbase ^ 0x1000, page1 | DRegBuf[2]); - setchr1(cbase ^ 0x1400, page1 | DRegBuf[3]); - setchr1(cbase ^ 0x1800, page2 | DRegBuf[4]); - setchr1(cbase ^ 0x1c00, page2 | DRegBuf[5]); -} - -static DECLFW(UNLSL1632CMDWrite) { - if (A == 0xA131) { - bbrk = V; - } - if (bbrk & 2) { - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); - if (A < 0xC000) - MMC3_CMDWrite(A, V); - else - MMC3_IRQWrite(A, V); - } else { - if ((A >= 0xB000) && (A <= 0xE003)) { - int ind = ((((A & 2) | (A >> 10)) >> 1) + 2) & 7; - int sar = ((A & 1) << 2); - chrcmd[ind] = (chrcmd[ind] & (0xF0 >> sar)) | ((V & 0x0F) << sar); - } else - switch (A & 0xF003) { - case 0x8000: prg0 = V; break; - case 0xA000: prg1 = V; break; - case 0x9000: mirr = V & 1; break; - } - Sync(); - } -} - -static void StateRestore(int version) { - if (bbrk & 2) { - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); - } else - Sync(); -} - -static void UNLSL1632Power(void) { - GenMMC3Power(); - SetWriteHandler(0x4100, 0xFFFF, UNLSL1632CMDWrite); -} - -void UNLSL1632_Init(CartInfo *info) { - GenMMC3_Init(info, 256, 512, 0, 0); - cwrap = UNLSL1632CW; - info->Power = UNLSL1632Power; - GameStateRestore = StateRestore; - AddExState(&StateRegs, ~0, 0, 0); -}