diff --git a/src/boards/126_422_534.c b/src/boards/126_422_534.c index 18f5836..521082e 100644 --- a/src/boards/126_422_534.c +++ b/src/boards/126_422_534.c @@ -29,6 +29,8 @@ Submapper 0: Normal connection Submapper 1: PRG A21 (2 MiB bank) selects between two 1 MiB chips Submapper 2: Register bit 6001.2 (undocumented in data sheet) selects between two 1 MiB chips + Submapper 3: 6000.2 substitutes PRG A14 and CHR A14 with 6000.5 + Submapper 4: LD822 PCB - CHR A20..A18 = PRG A20..A18 Both ASICs invert the register bit that selects PRG A21 (6000.5), hence "EXPREGS[0] ^0x20". */ @@ -51,6 +53,10 @@ static void wrapPRG(uint32 A, uint8 V) { int prgOR =(EXPREGS[0] <<4 &0x70 | (EXPREGS[0] ^0x20) <<3 &0x180) &~prgAND; /* Outer PRG bank */ if (submapper ==1) prgOR =prgOR &0x7F | prgOR >>1 &0x80; /* Submapper 1 uses PRG A21 as a chip select between two 1 MiB chips */ if (submapper ==2) prgOR =prgOR &0x7F | EXPREGS[1] <<5 &0x80; /* Submapper 2 uses 6001.2 (not documented in datasheet) as a chip select between two 1 MiB chips */ + if (submapper ==3 && EXPREGS[0] &0x04) { /* Submapper 3 replace PRG A14 with PRG A21 */ + prgAND &=~0x02; + prgOR |= EXPREGS[0] &0x20? 0x00: 0x02; + } for (A =0; A <4; A++) { /* In UNROM-like mode (CT3=1, CT2=1, CT0=1), MMC3 sees A13=0 and A14=CPU A14 during reads, making register 6 apply from $8000-$BFFF, and the fixed bank from $C000-$FFFF. In NROM-128, NROM-256, ANROM and UNROM modes (CT0=1), MMC3 sees A13=0 and A14=0, making register 6 apply from $8000-$FFFF. */ @@ -77,9 +83,16 @@ static void wrapCHR(uint32 A, uint8 V) { int chrOR; /* outer CHR bank */ if (reverseCHR_A18_A19) /* Mapper 126 swaps CHR A18 and A19 */ chrOR =(EXPREGS[0] <<4 &0x080 | (EXPREGS[0] ^0x20) <<3 &0x100 | EXPREGS[0] <<5 &0x200) &~chrAND; + else + if (submapper == 4) /* LD822 PCB - CHR A20..A18 = PRG A20..A18 */ + chrOR =(EXPREGS[0] <<4 &0x080 | EXPREGS[0] <<7 &0x100 | ~EXPREGS[0] <<4 &0x200 | EXPREGS[0] <<6 &0x400) &~chrAND; else chrOR =((EXPREGS[0] ^0x20) <<4 &0x380 | EXPREGS[0] <<8 &0x400) &~chrAND; + if (submapper ==3 && EXPREGS[0] &0x04) { /* Submapper 3 replace CHR A14 with PRG A21 */ + chrAND &=~0x10; + chrOR |= EXPREGS[0] &0x20? 0x00: 0x10; + } if (EXPREGS[3] &0x10) /* CNROM mode: 8 KiB inner CHR bank comes from outer bank register #2 */ setchr8(EXPREGS[2] &(chrAND >>3) | (chrOR &~chrAND) >>3); else /* MMC3 CHR mode */ diff --git a/src/boards/191.c b/src/boards/191.c new file mode 100644 index 0000000..c3eaf96 --- /dev/null +++ b/src/boards/191.c @@ -0,0 +1,73 @@ +/* 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 "cartram.h" + +static uint8 submapper; +static uint8 reg; + +static void sync () { + int bank; + MMC3_syncWRAM(0); + MMC3_syncPRG(0x3F, 0); + if ((reg &0x03) == 0x03) for (bank = 0; bank < 8; bank++) { + int val = MMC3_getCHRBank(bank); + setchr1r(val &0x80? 0x10: 0x00, bank <<10, val &0x7F); + } else + MMC3_syncCHR(0x7F, 0x80); + MMC3_syncMirror(); +} + +static int getPRGBank (uint8 bank) { + if (bank &2) + return MMC3_getPRGBank(bank) &~6 | reg <<1 &6; + else + return MMC3_getPRGBank(bank); +} + +static DECLFW (writeReg) { + reg = V; + sync(); +} + +static void reset () { + RAM[0x110] =0; + reg = submapper == 1? 0x00: 0x03; + MMC3_clear(); +} + +static void power () { + MMC3_power(); + SetWriteHandler(0x90AA, 0x90AA, writeReg); + reset(); +} + +void Mapper191_Init (CartInfo *info) { + submapper = info->submapper; + MMC3_init(info, sync, MMC3_TYPE_SHARP, getPRGBank, NULL, NULL, NULL); + CartRAM_init(info, 8, 2); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/225.c b/src/boards/225.c index a00b9fd..ae384ed 100644 --- a/src/boards/225.c +++ b/src/boards/225.c @@ -31,6 +31,7 @@ #include "mapinc.h" static uint8 extraRAM[4], prg, mode, chr, mirr; +static uint8 is255; static SFORMAT StateRegs[] = { @@ -56,7 +57,10 @@ static DECLFW(M225Write) { uint8 bank = (A >> 14) & 1; mirr = (A >> 13) & 1; mode = (A >> 12) & 1; - chr = (A & 0x3f) | (bank << 6); + if (is255) + chr = (V & 0x03) | (A & 0x3C) | (bank << 6); + else + chr = (A & 0x3f) | (bank << 6); prg = ((A >> 6) & 0x3f) | (bank << 6); Sync(); } @@ -92,12 +96,14 @@ static void StateRestore(int version) { } void Mapper225_Init(CartInfo *info) { + is255 = 0; info->Reset = M225Reset; info->Power = M225Power; GameStateRestore = StateRestore; AddExState(&StateRegs, ~0, 0, 0); } -void Mapper255_Init(CartInfo *info) { +void Mapper255_Init(CartInfo *info) { Mapper225_Init(info); -} \ No newline at end of file + is255 = 1; +} diff --git a/src/boards/268.c b/src/boards/268.c index 02de195..6723474 100644 --- a/src/boards/268.c +++ b/src/boards/268.c @@ -34,12 +34,13 @@ static void Mapper268_PRGWrap(uint32 A, uint8 V) { ; switch(submapper &~1) { default: /* Original implementation */ - prgMaskGNROM =EXPREGS[3] &0x10? (EXPREGS[1] &0x02? 0x03: 0x01): 0x00; - prgOffset =EXPREGS[3] &0x00E - |EXPREGS[0] <<4 &0x070 - |EXPREGS[1] <<3 &0x080 - |EXPREGS[1] <<6 &0x300 - |EXPREGS[0] <<6 &0xC00; + prgMaskGNROM = EXPREGS[3] &0x10? (EXPREGS[1] &0x02? 0x03: 0x01): 0x00; + prgOffset = EXPREGS[3] &0x000E + | EXPREGS[0] <<4 &0x0070 + | EXPREGS[1] <<3 &0x0080 + | EXPREGS[1] <<6 &0x0300 + | EXPREGS[0] <<6 &0x0C00 + |~EXPREGS[1] <<12 &0x1000; break; case 2: /* Later revision with different arrangement of register 1 */ prgMaskGNROM =EXPREGS[3] &0x10? (EXPREGS[1] &0x10? 0x01: 0x03): 0x00; @@ -66,6 +67,14 @@ static void Mapper268_PRGWrap(uint32 A, uint8 V) { prgOffset &=ROM_size -1; if (EXPREGS[0] &0x80? !!(EXPREGS[0] &0x08): !!(DRegBuf[0] &0x80)) prgOffset |=ROM_size; break; + case 8: /* 2 MiB regular plus extra latch, CHR-RAM protection */ + prgMaskGNROM =EXPREGS[3] &0x10? (EXPREGS[1] &0x02? 0x03: 0x01): 0x00; + prgOffset =EXPREGS[3] &0x00E + |EXPREGS[0] <<4 &0x070 + |EXPREGS[1] <<3 &0x080 + |EXPREGS[6] <<8 &0x300 + |EXPREGS[6] <<6 &0xC00; + break; } prgOffset &=~(prgMaskMMC3 | prgMaskGNROM); setprg8(A, V &prgMaskMMC3 | prgOffset | A >>13 &prgMaskGNROM); @@ -79,7 +88,7 @@ static void Mapper268_CHRWrap(uint32 A, uint8 V) { chrMaskMMC3 =EXPREGS[3] &0x10? 0x00: EXPREGS[0] &0x80? 0x7F: 0xFF; chrMaskGNROM =EXPREGS[3] &0x10? 0x07: 0x00; - chrOffset =EXPREGS[0] <<4 &0x380 | EXPREGS[2] <<3 &0x078; + chrOffset =EXPREGS[0] <<9 &0xC00 | EXPREGS[0] <<4 &0x380 | EXPREGS[2] <<3 &0x078; chrOffset &=~(chrMaskMMC3 | chrMaskGNROM); setchr1r(CHRRAM && EXPREGS[4] &0x01 && (V &0xFE) ==(EXPREGS[4] &0xFE)? 0x10: 0x00, A, V &chrMaskMMC3 | chrOffset | A >>10 &chrMaskGNROM); @@ -108,21 +117,31 @@ static DECLFW(Mapper268_WriteReg) { if (index ==2) { if (EXPREGS[2] &0x80) V =V &0x0F | EXPREGS[2] &~0x0F; V &=~EXPREGS[2] >>3 &0xE |0xF1; - } - EXPREGS[index] =V; - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); - Mapper268_MirrorWrap(A000B); + } + + if ((submapper &~1) == 8 && index == 1 && V &0x04 && V &0x08) { /* Latch clocking another latch */ + EXPREGS[6] = V; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + Mapper268_MirrorWrap(A000B); + } + + if (index <= 5) { + EXPREGS[index] =V; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + Mapper268_MirrorWrap(A000B); + } } } static void Mapper268_Reset(void) { - EXPREGS[0] =EXPREGS[1] =EXPREGS[2] =EXPREGS[3] =EXPREGS[4] =EXPREGS[5] =0; + EXPREGS[0] =EXPREGS[1] =EXPREGS[2] =EXPREGS[3] =EXPREGS[4] =EXPREGS[5] =EXPREGS[6] =0; MMC3RegReset(); } static void Mapper268_Power(void) { - EXPREGS[0] =EXPREGS[1] =EXPREGS[2] =EXPREGS[3] =EXPREGS[4] =EXPREGS[5] =0; + EXPREGS[0] =EXPREGS[1] =EXPREGS[2] =EXPREGS[3] =EXPREGS[4] =EXPREGS[5] =EXPREGS[6] =0; GenMMC3Power(); SetReadHandler(0x6000, 0x7FFF, Mapper268_ReadWRAM); if (submapper &1) { diff --git a/src/boards/277.c b/src/boards/277.c index 4f6549c..e37a5d8 100644 --- a/src/boards/277.c +++ b/src/boards/277.c @@ -22,6 +22,8 @@ #include "mapinc.h" #include "latch.h" +static uint8 inesMirroring; + static void Sync(void) { if (!(latch.data & 1) && (latch.data & 8)) { setprg16(0x8000, latch.data & ~1); @@ -36,7 +38,10 @@ static void Sync(void) { } } setchr8(0); - setmirror(((latch.data >> 4) & 1) ^ 1); + if (latch.data &8) + setmirror(latch.data &0x10? MI_H: MI_V); + else + setmirror(inesMirroring); /* The UNROM game's mirroring is set via solder pad and not via hardware register, so use the mirroring setting from the iNES header. */ } static DECLFW(M277Write) { @@ -58,6 +63,7 @@ static void M277Reset() { } void Mapper277_Init(CartInfo *info) { + inesMirroring = info->mirror; Latch_Init(info, Sync, NULL, 0, 0); info->Power = M277Power; info->Reset = M277Reset; diff --git a/src/boards/280.c b/src/boards/280.c index 9241cb7..d1eefc9 100644 --- a/src/boards/280.c +++ b/src/boards/280.c @@ -63,7 +63,7 @@ static DECLFW(M280Write) { } static void M280Reset(void) { - mode ^=1; + if (ROM_size >32) mode ^=1; latchAddr = 0; latchData = 0; Sync(); diff --git a/src/boards/293.c b/src/boards/293.c index 86348b0..e9f7a12 100644 --- a/src/boards/293.c +++ b/src/boards/293.c @@ -79,6 +79,11 @@ static void M293Power(void) { SetWriteHandler(0xC000, 0xDFFF, M293Write3); } +static void M293Reset(void) { + regs[0] = regs[1] = 0; + Sync(); +} + static void StateRestore(int version) { Sync(); } @@ -86,6 +91,7 @@ static void StateRestore(int version) { /* BMC 12-in-1/76-in-1 (NewStar) (Unl) */ void Mapper293_Init(CartInfo *info) { info->Power = M293Power; + info->Reset = M293Reset; GameStateRestore = StateRestore; AddExState(&StateRegs, ~0, 0, 0); } diff --git a/src/boards/301.c b/src/boards/301.c new file mode 100644 index 0000000..4e73d23 --- /dev/null +++ b/src/boards/301.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" +#include "asic_latch.h" + +static uint8 half; +static uint8 reg; + +static void sync () { + setprg16(0x8000, half <<5 &0x20 | reg <<3 &0x18 | Latch_data &0x07); + setprg16(0xC000, half <<5 &0x20 | reg <<3 &0x18 | 0x07); + setchr8(0); + setmirror(reg &0x04? MI_H: MI_V); +} + +static DECLFW (writeReg) { + reg = V; + sync(); +} + +static void power () { + half = 0; + reg = 0; + Latch_power(); + SetWriteHandler(0x5000, 0x5FFF, writeReg); +} + +static void reset () { + half ^= 1; + reg = 0; + RAM[0x100] =0; + Latch_clear(); +} + +void Mapper301_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; + AddExState(&half, 1, 0, "HALF"); + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/340.c b/src/boards/340.c new file mode 100644 index 0000000..4ca2787 --- /dev/null +++ b/src/boards/340.c @@ -0,0 +1,51 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +/* Submapper 0 - K-3008, K-3032, K-3036 PCBs: H mirroring via A2 in NROM mode, and via A6 in UNROM mdoe. + Submapper 1 - K-3055 PCB: H mirroring via A2 in NROM mode, and via A3=0,A4=1 in UNROM mode (used by Thundercade). +*/ + +static uint8 submapper; +static void sync () { + int prg = Latch_address >>2 &0x20 | Latch_address &0x1F; + if (Latch_address &0x20) { /* NROM mode */ + if (Latch_address &0x01) { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } else + setprg32(0x8000, prg >>1); + setmirror(Latch_address &0x04? MI_H: MI_V); + } else { /* UNROM mode */ + setprg16(0x8000, prg); + setprg16(0xC000, prg | 7); + setmirror(Latch_address &0x40 && submapper != 1 || ~Latch_address &0x08 && Latch_address &0x10 && submapper == 1? MI_H: MI_V); + } + SetupCartCHRMapping(0, CHRptr[0], 0x2000, Latch_address &0x20? 0: 1); + setchr8(0); +} + +void Mapper340_Init (CartInfo *info) { + submapper = info->submapper; + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/341.c b/src/boards/341.c new file mode 100644 index 0000000..c776544 --- /dev/null +++ b/src/boards/341.c @@ -0,0 +1,40 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2026 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" + +uint8 submapper; + +static void sync () { + setprg32(0x8000, Latch_address >>8); + setchr8(Latch_address >>8); + setmirror(Latch_address &(submapper == 1? 0x800: 0x200)? MI_H: MI_V); +} + +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { + if (!((*newAddress &0xF0) == 0xA0)) *newAddress = Latch_address; /* Update address only if new A7..A4 = $A */ +} + +void Mapper341_Init (CartInfo *info) { + submapper = info->submapper; + Latch_init(info, sync, 0x8000, 0xFFFF, submapper == 1? trapLatchWrite: NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/343.c b/src/boards/343.c new file mode 100644 index 0000000..50ec372 --- /dev/null +++ b/src/boards/343.c @@ -0,0 +1,53 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2026 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; + +static void sync () { + setprg32(0x8000, Latch_data); + setchr8(0); + setmirror(reg &0x08? MI_H: MI_V); +} + +static DECLFW (writeReg) { + reg = V; + sync(); +} + +static void reset () { + reg = 0; + Latch_clear(); +} + +static void power () { + reg = 0; + Latch_power(); + SetWriteHandler(0x5000, 0x5FFF, writeReg); +} + +void Mapper343_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "REGS"); +} diff --git a/src/boards/354.c b/src/boards/354.c index 91a7fbe..df82ce8 100644 --- a/src/boards/354.c +++ b/src/boards/354.c @@ -33,7 +33,11 @@ static SFORMAT StateRegs[] = static void Mapper354_Sync(void) { - int prg =latchData &0x3F | latchAddr <<2 &0x40 | latchAddr >>5 &0x80; + int prg; + if (submapper == 1) + prg = latchData &0x3F | latchAddr <<2 &0x40 | latchAddr >>5 &0x80; + else + prg = latchData &0x3F | latchAddr <<4 &0x40; switch(latchAddr &7) { case 0: case 4: diff --git a/src/boards/432.c b/src/boards/432.c index b93fe3c..9cb9681 100644 --- a/src/boards/432.c +++ b/src/boards/432.c @@ -31,6 +31,10 @@ static DECLFR (readPad) { return pad; } +static DECLFR (readOB) { + return X.DB; +} + static void sync () { int prgAND = reg[1] &0x02? 0x0F: 0x1F; int chrAND = reg[1] &0x20 && submapper == 3? 0x1FF: reg[1] &0x04? 0x7F: 0xFF; @@ -39,7 +43,10 @@ static void sync () { 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); + if (submapper == 4) { + SetReadHandler(0x8000, 0xFFFF, reg[0] &0x01 && pad &1? readOB: CartBR); + } else + SetReadHandler(0x8000, 0xFFFF, submapper == 1 && reg[1] &0x20 || submapper != 1 && reg[0] &0x01? readPad: CartBR); } static int getPRGBank (uint8 bank) { diff --git a/src/boards/437.c b/src/boards/437.c index acb4371..77f6b00 100644 --- a/src/boards/437.c +++ b/src/boards/437.c @@ -33,7 +33,7 @@ static void Mapper437_Sync(void) { } static DECLFW(Mapper437_WriteOuterBank) { - latch =latch &7 | A <<3; + latch =latch &7 | V <<3; Mapper437_Sync(); } diff --git a/src/boards/438.c b/src/boards/438.c index b534fb6..ca6063a 100644 --- a/src/boards/438.c +++ b/src/boards/438.c @@ -1,8 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2002 Xodnizel + * 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 @@ -18,50 +17,63 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -/* K-3071 */ - + #include "mapinc.h" +#include "asic_latch.h" +#include "cartram.h" -static uint8 latch[2]; +static uint8 unrom; -static void Mapper438_Sync(void) { - if (latch[0] &1) - setprg32(0x8000, latch[0] >>2); +static void sync0 () { + if (Latch_address &0x01) + setprg32(0x8000, Latch_address >>2); else { - setprg16(0x8000, latch[0] >>1); - setprg16(0xC000, latch[0] >>1); + setprg16(0x8000, Latch_address >>1); + setprg16(0xC000, Latch_address >>1); } - setchr8(latch[1] >>1); - setmirror(latch[1] &1 ^1); - + setchr8(Latch_data >>1); + setmirror(Latch_data &0x01? MI_H: MI_V); } -static DECLFW(Mapper438_WriteLatch) { - latch[0] =A &0xFF; - latch[1] =V; - Mapper438_Sync(); +static void sync1 () { + int mask = ROM_size -9; + if (unrom) { + mask++; + setprg16(0x8000, Latch_data &7 | mask); + setprg16(0xC000, 7 | mask); + setchr8r(0x10, 0); + setmirror(MI_V); + } else { + if (Latch_address &0x01) + setprg32(0x8000, Latch_address >>2 &(mask >>1)); + else { + setprg16(0x8000, Latch_address >>1 &mask); + setprg16(0xC000, Latch_address >>1 &mask); + } + setchr8(Latch_data >>1); + setmirror(Latch_data &0x01? MI_H: MI_V); + } } -static void Mapper438_Reset(void) { - latch[0] =latch[1] =0; - Mapper438_Sync(); +static void power () { + unrom = 0; + Latch_power(); } -static void Mapper438_Power(void) { - latch[0] =latch[1] =0; - Mapper438_Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, Mapper438_WriteLatch); +static void reset () { + unrom = !unrom; + Latch_clear(); } -static void StateRestore(int version) { - Mapper438_Sync(); -} - -void Mapper438_Init(CartInfo *info) { - info->Reset = Mapper438_Reset; - info->Power = Mapper438_Power; - GameStateRestore = StateRestore; - AddExState(&latch, 2, 0, "LATC"); +void Mapper438_Init (CartInfo *info) { + if (info->submapper == 1) { + Latch_init(info, sync1, 0x8000, 0xFFFF, NULL); + CHRRAM_init(info, 8); + info->Power = power; + info->Reset = reset; + AddExState(&unrom, 1, 0, "UNRO"); + } else { + Latch_init(info, sync0, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; + } } diff --git a/src/boards/439.c b/src/boards/439.c index 281c9ad..8874609 100644 --- a/src/boards/439.c +++ b/src/boards/439.c @@ -26,6 +26,7 @@ #include "latch.h" static uint8 reg[2]; +static uint8 pad; static void Sync(void) { @@ -35,6 +36,11 @@ static void Sync(void) setmirror(((latch.data >> 7) & 1) ^ 1); } +static DECLFR(M439ReadPad) +{ + return pad; +} + static DECLFW(M439WriteReg) { reg[A & 1] = V; @@ -52,14 +58,17 @@ static DECLFW(M439WriteLatch) static void M439Reset(void) { + pad++; reg[0] = reg[1] = ~0; LatchHardReset(); } static void M439Power(void) { + pad = 0; reg[0] = reg[1] = ~0; LatchPower(); + SetReadHandler(0x6000, 0x7FFF, M439ReadPad); SetWriteHandler(0x6000, 0x7FFF, M439WriteReg); SetWriteHandler(0x8000, 0xFFFF, M439WriteLatch); } @@ -70,4 +79,5 @@ void Mapper439_Init(CartInfo *info) info->Power = M439Power; info->Reset = M439Reset; AddExState(reg, 2, 0, "REGS"); + AddExState(&pad, 1, 0, "DIPS"); } diff --git a/src/boards/441.c b/src/boards/441.c index c371a92..8589d26 100644 --- a/src/boards/441.c +++ b/src/boards/441.c @@ -18,14 +18,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* 850335C PCB */ +/* 850335C PCB (submapper 0) + 840415C/43-170 PCB (submapper 1) */ #include "mapinc.h" #include "mmc3.h" +static uint8 submapper; + static void Mapper441_PRGWrap(uint32 A, uint8 V) { - int prgAND =EXPREGS[0] &0x08? 0x0F: 0x1F; - int prgOR =EXPREGS[0] <<4 &0x30; + int prgAND = EXPREGS[0] &0x08? 0x0F: 0x1F; + int prgOR = EXPREGS[0] <<4 &0x30; if (EXPREGS[0] &0x04) { if (~A &0x4000) { setprg8(A, ~2 &V &prgAND | prgOR &~prgAND); @@ -36,14 +39,17 @@ static void Mapper441_PRGWrap(uint32 A, uint8 V) { } static void Mapper441_CHRWrap(uint32 A, uint8 V) { - int chrAND =EXPREGS[0] &0x40? 0x7F: 0xFF; - int chrOR =EXPREGS[0] <<3 &0x180; + int chrAND = EXPREGS[0] &0x40? 0x7F: 0xFF; + int chrOR = EXPREGS[0] <<3 &0x180; setchr1(A, V &chrAND | chrOR &~chrAND); } static DECLFW(Mapper441_Write) { if (~EXPREGS[0] &0x80) { - EXPREGS[0] =V; + if (submapper == 1) + EXPREGS[0] = V &~4 | A &4; + else + EXPREGS[0] = V; FixMMC3PRG(MMC3_cmd); FixMMC3CHR(MMC3_cmd); } @@ -51,17 +57,18 @@ static DECLFW(Mapper441_Write) { } static void Mapper441_Reset(void) { - EXPREGS[0] =0; + EXPREGS[0] = 0; MMC3RegReset(); } static void Mapper441_Power(void) { - EXPREGS[0] =0; + EXPREGS[0] = 0; GenMMC3Power(); SetWriteHandler(0x6000, 0x7FFF, Mapper441_Write); } void Mapper441_Init(CartInfo *info) { + submapper = info->submapper; GenMMC3_Init(info, 256, 256, 8, 0); cwrap = Mapper441_CHRWrap; pwrap = Mapper441_PRGWrap; diff --git a/src/boards/446.c b/src/boards/446.c index f2eaf91..da4cdd3 100644 --- a/src/boards/446.c +++ b/src/boards/446.c @@ -264,7 +264,7 @@ 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: + case 0x000: case 0x100: case 0x200: case 0x400: mapperSync = sync_UxROM; Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL); break; @@ -297,7 +297,7 @@ static void applyMode (uint8 clear) { mapperSync = sync_VRC4; VRC2_activate(clear, sync, 0x02, 0x01, NULL, Mapper22_getCHRBank, NULL, NULL); break; - case 0x008: case 0x118: case 0x218: + case 0x008: case 0x118: case 0x218: case 0x403: mapperSync = sync_VRC4; VRC4_activate(clear, sync, 0x05, 0x0A, 1, NULL, NULL, NULL, NULL, NULL); break; @@ -313,7 +313,7 @@ static void applyMode (uint8 clear) { mapperSync = sync_VRC6; VRC6_activate(clear, sync, 0x02, 0x01, NULL, NULL, NULL, NULL); break; - case 0x00C: + case 0x00C: case 0x406: mapperSync = sync_VRC3; VRC3_activate(clear, sync); break; diff --git a/src/boards/447.c b/src/boards/447.c index a5d23cd..79d516d 100644 --- a/src/boards/447.c +++ b/src/boards/447.c @@ -22,14 +22,9 @@ #include "asic_vrc2and4.h" #include "cartram.h" +static uint8 submapper; static uint8 reg; -static uint8 dip; - -static SFORMAT stateRegs[] = { - { ®, 1, "EXP0" }, - { &dip, 1, "DIPS" }, - { 0 } -}; +static uint8 pad; static void sync () { VRC24_syncPRG(0x0F, reg <<4); @@ -39,21 +34,19 @@ static void sync () { } static int getPRGBank (uint8 bank) { - if (reg &4) { - if (~reg &2) - return VRC24_getPRGBank(bank &1) &~2 | bank &2; - else - return VRC24_getPRGBank(bank &1); + if (reg &0x04) { + int mask = reg &(submapper == 0? 0x02: 0x08) ? 1: 3; + return VRC24_getPRGBank(bank &1) &~mask | bank &mask; } else return VRC24_getPRGBank(bank); } static DECLFR (readPRG) { - return CartBR(reg &8? (A &~3 | dip &3): A); + return CartBR(reg &0x08? (A &~0x03 | pad &0x03): A); } static DECLFW (writeReg) { - if (~reg &1) { + if (~reg &0x01) { reg = A &0xFF; sync(); } @@ -62,21 +55,23 @@ static DECLFW (writeReg) { static void power (void) { reg = 0; - dip = 0; + pad = 0; VRC24_power(); - SetReadHandler(0x8000, 0xFFFF, readPRG); + if (submapper == 0) SetReadHandler(0x8000, 0xFFFF, readPRG); } static void reset (void) { reg = 0; - dip++; - sync(); + pad++; + VRC24_clear(); } void Mapper447_Init (CartInfo *info) { + submapper = info->submapper; 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); + AddExState(®, 1, 0, "EXPR"); + if (submapper == 0) AddExState(&pad, 1, 0, "DIPS"); } diff --git a/src/boards/487.c b/src/boards/487.c index ca056f3..07417e2 100644 --- a/src/boards/487.c +++ b/src/boards/487.c @@ -22,6 +22,7 @@ #include "mapinc.h" static uint8 reg[2]; +static uint8 submapper; static SFORMAT StateRegs[] ={ { reg, 2, "REGS" }, @@ -41,7 +42,16 @@ static void Sync(void) { setmirror(reg[1] &0x80? MI_H: MI_V); } -static DECLFW(WriteNINA) { +static DECLFW(WriteNINA_Prototype) { + if (A &0x200) + reg[1] =V; + else + if (A &0x100) + reg[0] =V; + Sync(); +} + +static DECLFW(WriteNINA08) { if (A &0x100) { if (A &0x080) /* Second register is always writable */ reg[1] =V; @@ -65,7 +75,7 @@ static void Power(void) { reg[1] = 0; Sync(); SetWriteHandler(0x8000, 0xFFFF, WriteColorDreams); - SetWriteHandler(0x4100, 0x7FFF, WriteNINA); + SetWriteHandler(0x4100, 0x7FFF, submapper == 1? WriteNINA_Prototype: WriteNINA08); SetReadHandler(0x8000, 0xFFFF, CartBR); } @@ -74,12 +84,14 @@ static void StateRestore(int version) { } static void Reset(void) { + RAM[0x000] =0; /* Bug in Maxivision 30-in-1 1991-12-14 version */ reg[0] = 0; reg[1] = 0; Sync(); } void Mapper487_Init(CartInfo *info) { + submapper = info->submapper; info->Power = Power; info->Reset = Reset; AddExState(&StateRegs, ~0, 0, 0); diff --git a/src/boards/498.c b/src/boards/498.c index 000005a..6befb42 100644 --- a/src/boards/498.c +++ b/src/boards/498.c @@ -27,15 +27,15 @@ static uint8 reg; static void sync () { if (reg &0x20) - MMC1_syncPRG(0x07, reg &~0x07); + MMC1_syncPRG(0x07, reg >>1 &0x20 | reg &0x18); else - if (reg &0x04) + if (reg &0x05) setprg32(0x8000, reg >>1); else { setprg16(0x8000, reg); setprg16(0xC000, reg); } - MMC1_syncCHR(0x1F, reg <<2 &~0x1F); + MMC1_syncCHR(0x1F, reg <<1 &0x80 | reg <<2 &0x60); MMC1_syncMirror(); } diff --git a/src/boards/518.c b/src/boards/518.c new file mode 100644 index 0000000..9a8944c --- /dev/null +++ b/src/boards/518.c @@ -0,0 +1,96 @@ +/* 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 reg[2]; +static uint8 chr; + +static void sync () { + setprg8r(0x10, 0x6000, 0); + if (reg[1] &0x04) + setprg32(0x8000, reg[0]); + else { + setprg16(0x8000, reg[0]); + setprg16(0xC000, 0); + } + setchr4(0x0000, reg[1] &0x02? chr: 0); + setchr4(0x1000, 1); + setmirror(reg[1] &0x01? MI_H: MI_V); +} + +static void FP_FASTAPASS(1) trapPPUAddressChange (uint32 A) { + if (A &0x2000 && (A &0x23C0) < 0x23C0) { + chr = A >>(10 +(reg[1] &0x01? 1: 0)) &1; + setchr4(0x0000, reg[1] &0x02? chr: 0); + } +} + +static DECLFR (readReg) { + switch(A >>8 &7) { + case 3: /* LPC state */ + return 0x8F; + case 6: /* FDC */ + return 0x00; + default: + return X.DB; + } +} + +static DECLFW (writeReg) { + switch(A >>8 &7) { + case 0: case 2: + reg[A >>9 &1] = V; + sync(); + break; + case 3: /* LPC data */ + break; + case 5: /* FDC */ + break; + } +} + +static void reset () { + reg[0] = reg[1] = chr = 0; + sync(); +} + +static void power () { + SetReadHandler(0x5000, 0x5FFF, readReg); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x5000, 0x5FFF, writeReg); + SetWriteHandler(0x6000, 0xFFFF, CartBW); + reset(); +} + +static void restore (int version) { + sync(); +} + +void Mapper518_Init (CartInfo *info) { + WRAM_init(info, 8); + info->Power = power; + info->Reset = reset; + GameStateRestore = restore; + PPU_hook = trapPPUAddressChange; + AddExState(reg, 2, 0, "REGS"); + AddExState(&chr, 1, 0, "CHRB"); +} diff --git a/src/boards/571.c b/src/boards/571.c index c759426..6189f65 100644 --- a/src/boards/571.c +++ b/src/boards/571.c @@ -23,6 +23,7 @@ #include "mapinc.h" #include "asic_vrc2and4.h" +static uint8 submapper; static uint8 reg; static void sync () { @@ -33,7 +34,7 @@ static void sync () { if (reg &0x20) VRC24_syncPRG(prgAND, prgOR &~prgAND); else - if (reg &0x6) + if (submapper == 0 && reg &0x06 || submapper == 1 && reg &0x02 && reg &0x04) setprg32(0x8000, reg >>1); else { setprg16(0x8000, reg); @@ -65,6 +66,7 @@ static void power () { } void Mapper571_Init (CartInfo *info) { + submapper = info->submapper; VRC4_init(info, sync, 4, 8, 1, NULL, NULL, NULL, writeReg, NULL); info->Power = power; info->Reset = reset; diff --git a/src/boards/592.c b/src/boards/592.c index 3c91f35..3185658 100644 --- a/src/boards/592.c +++ b/src/boards/592.c @@ -21,14 +21,21 @@ #include "mapinc.h" #include "asic_latch.h" +static uint8 submapper; + static void sync () { - setprg16(0x8000, Latch_data); - setprg16(0xC000, Latch_data); + if (submapper == 1) + setprg32(0x8000, Latch_data); + else { + setprg16(0x8000, Latch_data); + setprg16(0xC000, Latch_data); + } setchr8(Latch_data); setmirror(Latch_data &0x08? MI_H: MI_V); } void Mapper592_Init (CartInfo *info) { + submapper = info->submapper; Latch_init(info, sync, 0x8000, 0xFFFF, NULL); info->Reset = Latch_clear; } diff --git a/src/boards/596.c b/src/boards/596.c new file mode 100644 index 0000000..d62c447 --- /dev/null +++ b/src/boards/596.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 &0x04? 0x1F: 0x0F; + int chrAND = 0x7F; + int prgOR = reg <<4; + int chrOR = reg <<7; + MMC3_syncWRAM(0); + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + if (~reg &0x08) { + reg = V; + sync(); + } +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +void Mapper596_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/597.c b/src/boards/597.c new file mode 100644 index 0000000..5f2846a --- /dev/null +++ b/src/boards/597.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 = 0x0F; + int chrAND = reg &0x01? 0xFF: 0x7F; + int prgOR = reg <<4; + int chrOR = (reg &0x02? 0x080: 0x000) | (reg &0x01 && ~reg &0x02? 0x100: 0x000); + MMC3_syncPRG(prgAND, prgOR &~prgAND); + MMC3_syncCHR(chrAND, chrOR &~chrAND); + MMC3_syncMirror(); + SetReadHandler(0x8000, 0xFFFF, reg &0x20? readPad: CartBR); +} + +static int getPRGBank (uint8 bank) { + if (reg &0x04) { + int mask = reg &0x10? 1: 3; + 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 Mapper597_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_SHARP, getPRGBank, NULL, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/boards/598.c b/src/boards/598.c new file mode 100644 index 0000000..c109155 --- /dev/null +++ b/src/boards/598.c @@ -0,0 +1,62 @@ +/* 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 () { + setprg16(0x8000, reg[0] &0x18 | reg[1] &0x07); + setprg16(0xC000, reg[0] &0x18 | 0x07); + setchr8(0); + switch(reg[0] &0x03) { + case 0x00: setmirror(MI_0); break; + case 0x01: setmirror(MI_V); break; + case 0x02: setmirror(MI_H); break; + case 0x03: setmirror(MI_1); break; + } +} + +static DECLFW (writeReg) { + reg[A >>14 &1] = V; + sync(); +} + +static void reset () { + reg[0] = reg[1] = 0; + sync(); +} + +static void power () { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, writeReg); + reset(); +} + +static void stateRestore (int version) { + sync(); +} + +void Mapper598_Init (CartInfo *info) { + info->Power = power; + info->Reset = reset; + GameStateRestore = stateRestore; + AddExState(reg, 2, 0, "REGS"); +} diff --git a/src/boards/599.c b/src/boards/599.c new file mode 100644 index 0000000..22857d2 --- /dev/null +++ b/src/boards/599.c @@ -0,0 +1,80 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" +#include "cartram.h" + +static uint8 pad; + +static DECLFR (readOB) { + return X.DB; +} + +static void sync () { + /* There are two PRG-ROM chips, the first can be either 256 KiB or 512 KiB in size, the second is always 128 KiB in size */ + int prgAND, prgOR; + if (ROM_size >=32) { + prgAND = Latch_address &0x400? 0x07: 0x1F; + prgOR = Latch_address &0x400? 0x20: 0x00; + } else { + prgAND = Latch_address &0x400? 0x07: 0x0F; + prgOR = Latch_address &0x400? 0x10: 0x00; + } + if (Latch_address &0x080) { /* NROM mode */ + if (Latch_address &0x001) + setprg32(0x8000,(prgOR | Latch_address >>2 &prgAND) >>1); + else { + setprg16(0x8000, prgOR | Latch_address >>2 &prgAND); + setprg16(0xC000, prgOR | Latch_address >>2 &prgAND); + } + } else { /* Inverse UNROM mode */ + setprg16(0x8000, prgOR | Latch_address >>2 &prgAND); + setprg16(0xC000, prgOR); + } + SetReadHandler(0x8000, 0xFFFF, ROM_size >=32 && Latch_address &0x200 && pad &1? readOB: CartBR); + if (Latch_address &0x400) + setchr8(Latch_address >>6 &~0x03 | Latch_data &0x03); + else + setchr8r(0x10, 0); + setmirror(Latch_address &0x002? MI_H: MI_V); +} + +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { /* Latch address bit 14 is an address lock bit */ + if (Latch_address &0x4000) *newAddress = Latch_address; +} + +static void power () { + pad = 0; + Latch_power(); +} + +static void reset () { + pad++; + Latch_clear(); +} + +void Mapper599_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); + CHRRAM_init(info, 8); + info->Power = power; + info->Reset = reset; + AddExState(&pad, 1, 0, "DIPS"); +} diff --git a/src/boards/603.c b/src/boards/603.c new file mode 100644 index 0000000..f205ed9 --- /dev/null +++ b/src/boards/603.c @@ -0,0 +1,33 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2026 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 >>2); + setprg16(0xC000, Latch_address >>2); + setchr8(Latch_address); +} + +void Mapper603_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/605.c b/src/boards/605.c new file mode 100644 index 0000000..442285b --- /dev/null +++ b/src/boards/605.c @@ -0,0 +1,71 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2026 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 () { + if (reg[3] &0x01) { /* UNROM mode */ + if (reg[2] &0x20) { /* 128 KiB */ + setprg16(0x8000, reg[2] >>3 &~0x07 | reg[1] &0x07); + setprg16(0xC000, reg[2] >>3 &~0x07 | 0x07); + } else { /* 64 KiB */ + setprg16(0x8000, reg[2] >>3 &~0x03 | reg[1] &0x07); + setprg16(0xC000, reg[2] >>3 &~0x03 | reg[1] &0x04 | 0x03); + } + } else { /* NROM */ + setprg16(0x8000, reg[2] >>3 &~0x07 | reg[1] &~1); + setprg16(0xC000, reg[2] >>3 &~0x07 | reg[1] | 1); + } + setchr8(0); + setmirror(reg[0] &0x01? MI_H: MI_V); +} + +static DECLFW (writeReg) { + reg[A >>14 &1] = V; + if (A <0xC000) { + reg[2] = A &0xFF; + reg[3] = A >>8; + } + sync(); +} + +static void reset () { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + sync(); +} + +static void power () { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, writeReg); + reset(); +} + +static void stateRestore (int version) { + sync(); +} + +void Mapper605_Init (CartInfo *info) { + info->Power = power; + info->Reset = reset; + GameStateRestore = stateRestore; + AddExState(reg, 4, 0, "REGS"); +} diff --git a/src/boards/606.c b/src/boards/606.c new file mode 100644 index 0000000..212b129 --- /dev/null +++ b/src/boards/606.c @@ -0,0 +1,61 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2026 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; + +static void sync () { + if (reg &0x80) { /* ANROM mode */ + setprg32(0x8000, reg >>2 &0x08 | reg >>4 &0x04 | Latch_data &0x03); + setmirror(Latch_data &0x10? MI_1: MI_0); + } else { /* UNROM mode */ + setprg16(0x8000, reg >>1 &0x10 | reg >>3 &0x08 | Latch_data &0x07); + setprg16(0xC000, reg >>1 &0x10 | reg >>3 &0x08 | 0x07); + setmirror(Latch_data &0x10? MI_H: MI_V); + } + setchr8(0); +} + +static DECLFW (writeReg) { + if (~reg &0x10) { + reg = V; + sync(); + } +} + +static void reset () { + reg = 0; + Latch_clear(); +} + +static void power () { + Latch_power(); + SetWriteHandler(0x6000, 0x7FFF, writeReg); + reset(); +} + +void Mapper606_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "REGS"); +} diff --git a/src/boards/607.c b/src/boards/607.c new file mode 100644 index 0000000..c623e51 --- /dev/null +++ b/src/boards/607.c @@ -0,0 +1,62 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2026 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; + +static DECLFR (readOB) { + return X.DB; +} + +static void sync () { + if (reg &0x10) { /* UNROM mode */ + setprg16(0x8000, reg <<3 &~0x07 | Latch_data &0x07); + setprg16(0xC000, reg <<3 &~0x07 | 0x07); + } else /* NROM-256 mode */ + setprg32(0x8000, reg <<3 &0x04 | Latch_data >>1 &0x03); + SetReadHandler(0x8000, 0xFFFF, reg &0x0C? readOB: CartBR); /* 6000.2 and 6000.3 seem to select additional UNROM games. Without a cartridge that has them, the exact workings remain unknown for now. */ + setchr8(0); + setmirror(reg &0x20? MI_H: MI_V); +} + +static DECLFW (writeReg) { + reg = V; + sync(); +} + +static void reset () { + reg = 0; + Latch_clear(); +} + +static void power () { + Latch_power(); + SetWriteHandler(0x6000, 0x7FFF, writeReg); + reset(); +} + +void Mapper607_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "REGS"); +} diff --git a/src/boards/608.c b/src/boards/608.c new file mode 100644 index 0000000..f032bfc --- /dev/null +++ b/src/boards/608.c @@ -0,0 +1,38 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2026 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 &0x04? MI_V: MI_H); +} + +static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { /* The address bits are only updated when the new A4=0 and A3=1. */ + if (!(~*newAddress &0x10 && *newAddress &0x08)) *newAddress = Latch_address; +} + +void Mapper608_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite); + info->Reset = Latch_clear; +} diff --git a/src/boards/609.c b/src/boards/609.c new file mode 100644 index 0000000..6883d8d --- /dev/null +++ b/src/boards/609.c @@ -0,0 +1,64 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2026 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; + +static void sync () { + int bank; + for (bank = 0x8000; bank <= 0xF000; bank += 0x2000) { + int val = reg; + if (reg &0x20) val = val &~0x01 | bank >>13 &1; + if (reg &0x40) val = val &~0x02 | bank >>13 &2; + setprg8(bank, val); + } + setchr8(0); + setmirror(reg &0x80? MI_H: MI_V); +} + +static DECLFW (writeReg) { + if (A &0x100) { + reg = V; + sync(); + } +} + +static void reset () { + reg = 0; + sync(); +} + +static void power () { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x4020, 0x5FFF, writeReg); + reset(); +} + +static void stateRestore (int version) { + sync(); +} + +void Mapper609_Init (CartInfo *info) { + info->Power = power; + info->Reset = reset; + GameStateRestore = stateRestore; + AddExState(®, 1, 0, "REGS"); +} diff --git a/src/boards/610.c b/src/boards/610.c new file mode 100644 index 0000000..70f23e1 --- /dev/null +++ b/src/boards/610.c @@ -0,0 +1,57 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2026 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; + +static void sync () { + if (reg &0x10) { /* NROM-128 mode */ + setprg16(0x8000, reg <<1); + setprg16(0xC000, reg <<1); + } else /* NROM-256 mode */ + setprg32(0x8000, reg); + setchr8(reg <<2 | Latch_data &0x03); + setmirror(reg &0x08? MI_H: MI_V); +} + +static DECLFW (writeReg) { + reg = V; + sync(); +} + +static void reset () { + reg = 0; + Latch_clear(); +} + +static void power () { + Latch_power(); + SetWriteHandler(0x5000, 0x5FFF, writeReg); + reset(); +} + +void Mapper610_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "REGS"); +} diff --git a/src/boards/611.c b/src/boards/611.c new file mode 100644 index 0000000..eb0c7aa --- /dev/null +++ b/src/boards/611.c @@ -0,0 +1,37 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2026 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 >>3); + else { + setprg16(0x8000, Latch_address >>2); + setprg16(0xC000, Latch_address >>2); + } + setchr8(Latch_address >>1 &0x04 | Latch_address &0x03); +} + +void Mapper611_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} diff --git a/src/boards/612.c b/src/boards/612.c new file mode 100644 index 0000000..f43cf21 --- /dev/null +++ b/src/boards/612.c @@ -0,0 +1,47 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2026 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; + +static void sync () { + setprg16(0x8000, reg <<3 | Latch_data &0x07); + setprg16(0xC000, reg <<3 | 0x07); + setchr8(0); +} + +static void reset () { + reg++; + Latch_clear(); +} + +static void power () { + reg = 0; + Latch_power(); +} + +void Mapper612_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "REGS"); +} diff --git a/src/boards/613.c b/src/boards/613.c new file mode 100644 index 0000000..c501647 --- /dev/null +++ b/src/boards/613.c @@ -0,0 +1,70 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2026 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" +#include "asic_mmc3.h" + +static uint8 reg; + +static void sync (void) { + if (reg &0x01) { + MMC3_syncPRG(0x0F, reg <<4); + MMC3_syncCHR(0x7F, reg <<7); + MMC3_syncMirror(); + } else { + MMC1_syncPRG(0x07, reg <<3); + MMC1_syncCHR(0x1F, reg <<5); + MMC1_syncMirror(); + } +} + +static void applyMode (uint8 clear) { + PPU_hook = NULL; + MapIRQHook = NULL; + GameHBIRQHook = NULL; + if (reg &0x01) + MMC3_activate(clear, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, NULL); + else + MMC1_activate(clear, sync, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL); +} + +static void reset (void) { + reg++; + applyMode(1); +} + +static void power (void) { + reg = 0; + applyMode(1); +} + +static void restore (int version) { + applyMode(0); +} + +void Mapper613_Init (CartInfo *info) { + MMC1_addExState(); + MMC3_addExState(); + info->Reset = reset; + info->Power = power; + GameStateRestore = restore; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/614.c b/src/boards/614.c new file mode 100644 index 0000000..2d4803c --- /dev/null +++ b/src/boards/614.c @@ -0,0 +1,68 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2026 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[3]; + +static void sync () { + int prg = reg[0] &0x30 | reg[1] <<3 &0x08; + if (reg[0] &0x08) { + if (reg[0] &0x40) + setprg32(0x8000, prg >>1 &0x1C | reg[0] >>1 &0x03); + else { + setprg16(0x8000, prg &0x38 | reg[2] &0x07); + setprg16(0xC000, prg &0x38 | reg[2] &0x07); + } + } else { + setprg16(0x8000, prg &0x38 | reg[2] &0x07); + setprg16(0xC000, prg &0x38 | 0x07); + } + setchr8(0); + setmirror(reg[0] &0x80? MI_H: MI_V); +} + +static DECLFW (writeReg) { + reg[A >>13 &2] = V; + if (~A &0x4000) reg[1] = A &0xFF; + sync(); +} + +static void reset () { + reg[0] = reg[1] = reg[2] = 0; + sync(); +} + +static void power () { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, writeReg); + reset(); +} + +static void stateRestore (int version) { + sync(); +} + +void Mapper614_Init (CartInfo *info) { + info->Power = power; + info->Reset = reset; + GameStateRestore = stateRestore; + AddExState(reg, 3, 0, "REGS"); +} diff --git a/src/boards/615.c b/src/boards/615.c new file mode 100644 index 0000000..da373d1 --- /dev/null +++ b/src/boards/615.c @@ -0,0 +1,70 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2026 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[3]; + +static void sync () { + int prg = reg[0] &0x34 | reg[1] <<3 &0x08; + if (reg[0] &0x08) { + if (reg[0] &0x20 && reg[1] &0x01) { + setprg16(0x8000, prg &0x3C | reg[2] &0x03); + setprg16(0xC000, prg &0x3C | 0x03); + } else { + setprg16(0x8000, prg &0x38 | reg[2] &0x07); + setprg16(0xC000, prg &0x38 | 0x07); + } + } else + setprg32(0x8000, prg >>1 &0x1C | reg[0] >>1 &0x03); + setchr8(0); + setmirror(reg[0] &0x80? MI_H: MI_V); +} + +static DECLFW (writeReg) { + if (A < 0x8000) { + reg[0] = V; + reg[1] = A &0xFF; + } else + reg[2] = V; + sync(); +} + +static void reset () { + reg[0] = reg[1] = reg[2] = 0; + sync(); +} + +static void power () { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0xFFFF, writeReg); + reset(); +} + +static void stateRestore (int version) { + sync(); +} + +void Mapper615_Init (CartInfo *info) { + info->Power = power; + info->Reset = reset; + GameStateRestore = stateRestore; + AddExState(reg, 3, 0, "REGS"); +} diff --git a/src/boards/616.c b/src/boards/616.c new file mode 100644 index 0000000..010e1cc --- /dev/null +++ b/src/boards/616.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_syncPRG(0x0F, reg <<4); + if (reg &0x04) + setchr8r(0x10, 0); + else + MMC3_syncCHR(0x7F, reg <<7); + MMC3_syncMirror(); +} + +static DECLFW (writeReg) { + reg = A &0xFF; + sync(); +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +void Mapper616_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, writeReg); + CHRRAM_init(info, 8); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/617.c b/src/boards/617.c new file mode 100644 index 0000000..a072a3c --- /dev/null +++ b/src/boards/617.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_vrc2and4.h" + +static uint8 reg; + +static void sync () { + int prgAND = reg &0x04? 0x1F: 0x0F; + int chrAND = reg &0x02? 0x7F: 0xFF; + int prgOR = reg <<4; + int chrOR = reg <<7; + VRC24_syncPRG(prgAND, prgOR &~prgAND); + VRC24_syncCHR(chrAND, chrOR &~chrAND); + VRC24_syncMirror(); +} + +static DECLFW (writeReg) { + if (~reg &0x08) { + reg = A &0xFF; + sync(); + } +} + +static void reset () { + reg = 0; + sync(); +} + +static void power () { + reg = 0; + VRC24_power(); +} + +void Mapper617_Init (CartInfo *info) { + VRC4_init(info, sync, 0x05, 0x0A, 1, NULL, NULL, NULL, writeReg, NULL); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/618.c b/src/boards/618.c new file mode 100644 index 0000000..58e143c --- /dev/null +++ b/src/boards/618.c @@ -0,0 +1,68 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2026 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 uint8 reg; + +static void sync () { + if (reg &0x02) + MMC3_syncPRG(0x0F, reg >>1 &0x20 | reg <<2 &0x10); + else + setprg32(0x8000, reg >>3 &0x08 | reg &0x04 | reg >>4 &0x01 | reg <<1 &0x02); + if (reg &0x80) + MMC3_syncCHR(0x1FF, 0x200); + else + MMC3_syncCHR(0x0FF, reg <<6 &0x100); + MMC3_syncMirror(); +} + +static int getCHRBank (uint8 bank) { + if (reg &0x80) + return MMC3_getCHRBank(bank &4 | bank >>1 &1) <<1 | bank &1; + else + return MMC3_getCHRBank(bank); +} + + +static DECLFW (writeReg) { + reg = V; + sync(); +} + +static void reset () { + reg = 0; + MMC3_clear(); +} + +static void power () { + reg = 0; + MMC3_power(); +} + +void Mapper618_Init (CartInfo *info) { + MMC3_init(info, sync, MMC3_TYPE_SHARP, NULL, getCHRBank, NULL, writeReg); + info->Power = power; + info->Reset = reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/boards/8157.c b/src/boards/8157.c deleted file mode 100644 index eb9224f..0000000 --- a/src/boards/8157.c +++ /dev/null @@ -1,81 +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 - * - * GG1 boards, similar to T-262, with no Data latch - * - */ - -#include "mapinc.h" - -static uint16 cmdreg; -static uint8 reset; -static SFORMAT StateRegs[] = -{ - { &reset, 1, "REST" }, - { &cmdreg, 2, "CREG" }, - { 0 } -}; - -static void Sync(void) { - uint32 base = ((cmdreg & 0x060) | ((cmdreg & 0x100) >> 1)) >> 2; - uint32 bank = (cmdreg & 0x01C) >> 2; - uint32 lbank = (cmdreg & 0x200) ? 7 : ((cmdreg & 0x80) ? bank : 0); - - setprg16(0x8000, base | bank); - setprg16(0xC000, base | lbank); - setmirror(((cmdreg & 2) >> 1) ^ 1); -} - -static DECLFR(UNL8157Read) { - if ((cmdreg & 0x100) && (PRGsize[0] < (1024 * 1024))) { - A = (A & 0xFFF0) + reset; - } - return CartBR(A); -} - -static DECLFW(UNL8157Write) { - cmdreg = A; - Sync(); -} - -static void UNL8157Power(void) { - setchr8(0); - SetWriteHandler(0x8000, 0xFFFF, UNL8157Write); - SetReadHandler(0x8000, 0xFFFF, UNL8157Read); - cmdreg = reset = 0; - Sync(); -} - -static void UNL8157Reset(void) { - cmdreg = reset = 0; - reset++; - reset &= 0x1F; - Sync(); -} - -static void UNL8157Restore(int version) { - Sync(); -} - -void UNL8157_Init(CartInfo *info) { - info->Power = UNL8157Power; - info->Reset = UNL8157Reset; - GameStateRestore = UNL8157Restore; - AddExState(&StateRegs, ~0, 0, 0); -} diff --git a/src/boards/83_264.c b/src/boards/83_264.c new file mode 100644 index 0000000..7601869 --- /dev/null +++ b/src/boards/83_264.c @@ -0,0 +1,240 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2026 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 reg[16]; +static uint8 scratch[4]; +static uint8 flags; +static uint8 pad; +static int mapper; +static uint8 submapper; + +static SFORMAT stateRegs[] = { + { reg, 16, "REGS" }, + { scratch, 4, "SCRA" }, + {&flags, 1, "FLAG" }, + {&pad, 1, "DIPS" }, + { 0 } +}; + +static void sync () { + int prgAND = mapper == 264 || submapper == 3? 0x0F: 0x1F; + switch(reg[1] &0x18) { + case 0x00: + setprg16(0x8000, reg[0]); + setprg16(0xC000, reg[0] | prgAND >>1); + break; + case 0x08: + setprg16(0x8000, reg[0]); + setprg16(0xC000, reg[0]); + break; + case 0x10: case 0x18: + setprg8(0x8000, reg[0] <<1 &~prgAND | reg[4] &prgAND); + setprg8(0xA000, reg[0] <<1 &~prgAND | reg[5] &prgAND); + setprg8(0xC000, reg[0] <<1 &~prgAND | reg[6] &prgAND); + setprg8(0xE000, reg[0] <<1 &~prgAND | 0xFF &prgAND); + break; + } + + if (submapper == 2 && PRGsize[0x10]) + setprg8r(0x10, 0x6000, reg[0] >>6); + else + setprg8(0x6000, reg[7]); + + if (submapper == 2 || reg[1] &0x20) { + SetReadHandler (0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + } else { + SetReadHandler (0x6000, 0xFFFF, CartBROB); + SetWriteHandler(0x6000, 0x7FFF, NULL); + } + + switch(mapper == 264? 1: submapper) { + case 0: + setchr1(0x0000, reg[8 | 0]); + setchr1(0x0400, reg[8 | 1]); + setchr1(0x0800, reg[8 | 2]); + setchr1(0x0C00, reg[8 | 3]); + setchr1(0x1000, reg[8 | 4]); + setchr1(0x1400, reg[8 | 5]); + setchr1(0x1800, reg[8 | 6]); + setchr1(0x1C00, reg[8 | 7]); + break; + case 1: + setchr2(0x0000, reg[8 | 0]); + setchr2(0x0800, reg[8 | 1]); + setchr2(0x1000, reg[8 | 6]); + setchr2(0x1800, reg[8 | 7]); + break; + case 2: + setchr1(0x0000, reg[0] <<4 &~0xFF | reg[8 | 0]); + setchr1(0x0400, reg[0] <<4 &~0xFF | reg[8 | 1]); + setchr1(0x0800, reg[0] <<4 &~0xFF | reg[8 | 2]); + setchr1(0x0C00, reg[0] <<4 &~0xFF | reg[8 | 3]); + setchr1(0x1000, reg[0] <<4 &~0xFF | reg[8 | 4]); + setchr1(0x1400, reg[0] <<4 &~0xFF | reg[8 | 5]); + setchr1(0x1800, reg[0] <<4 &~0xFF | reg[8 | 6]); + setchr1(0x1C00, reg[0] <<4 &~0xFF | reg[8 | 7]); + break; + case 3: + setchr1(0x0000, reg[0] <<2 &~0xFF | reg[8 | 0]); + setchr1(0x0400, reg[0] <<2 &~0xFF | reg[8 | 1]); + setchr1(0x0800, reg[0] <<2 &~0xFF | reg[8 | 2]); + setchr1(0x0C00, reg[0] <<2 &~0xFF | reg[8 | 3]); + setchr1(0x1000, reg[0] <<2 &~0xFF | reg[8 | 4]); + setchr1(0x1400, reg[0] <<2 &~0xFF | reg[8 | 5]); + setchr1(0x1800, reg[0] <<2 &~0xFF | reg[8 | 6]); + setchr1(0x1C00, reg[0] <<2 &~0xFF | reg[8 | 7]); + break; + } + switch (reg[1] &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; + } +} + +static DECLFR (readPadScratch) { + if (A &(mapper == 264? 0x400: 0x100)) + return scratch[A &3]; + else + return pad; +} + +static DECLFW (writeScratch) { + scratch[A &3] = V; +} + +static DECLFW (writeReg) { + if (mapper == 264) A = A >>2 &~0x3F | A &0x3F; + switch (A &0x318) { + case 0x000: case 0x008: case 0x010: case 0x018: case 0x100: case 0x108: case 0x110: case 0x118: + reg[A >>8 &1] = V; + sync(); + break; + case 0x200: case 0x208: case 0x210: case 0x218: + reg[2 | A &1] = V; + if (A &1) + flags = flags &~0x80 | reg[1] &0x80; /* Copy "counting" flag from Misc. register to internal flag register */ + else + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0x300: case 0x308: + reg[4 | A &3] = V; + sync(); + break; + case 0x310: + reg[8 | A &7] = V; + sync(); + break; + case 0x318: + flags = flags &~0x40 | V &0x40; + break; + + } +} + +void clockCounter (void) { + uint16 counter = reg[2] | reg[3] <<8; + if (flags &0x80 && counter) { + if (reg[1] &0x40) + counter--; + else + counter++; + if (!counter) { + X6502_IRQBegin(FCEU_IQEXT); + flags &= ~0x80; + } + } + reg[2] = counter &0xFF; + reg[3] = counter >>8 &0xFF; +} + +void FP_FASTAPASS(1) cycleCounter (int a) { + while (a--) if (~flags &0x40) clockCounter(); +} + +void scanlineCounter() { + if (flags &0x40) { + clockCounter(); + clockCounter(); + clockCounter(); + clockCounter(); + clockCounter(); + clockCounter(); + clockCounter(); + clockCounter(); + } +} + +static void reset () { + int i; + for (i = 0; i < 16; i++) reg[i] = 0; + pad++; + X6502_IRQEnd(FCEU_IQEXT); + sync(); +} + +static void power () { + int i; + SetReadHandler(0x5000, 0x5FFF, readPadScratch); + SetWriteHandler(0x5000, 0x5FFF, writeScratch); + SetReadHandler (0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, writeReg); + MapIRQHook = cycleCounter; + GameHBIRQHook = scanlineCounter; + for (i = 0; i < 16; i++) reg[i] = 0; + for (i = 4; i < 4; i++) scratch[i] = 0; + pad = 0; + sync(); +} + +void restore (int version) { + sync(); +} + +void Mapper83_Init (CartInfo *info) { + mapper = 83; + submapper = info->submapper; + if (!info->iNES2) { + if (info->CHRRomSize ==512*1024) submapper = 1; else + if (info->PRGRomSize ==1024*1024) submapper = 2; else + if (info->PRGRomSize ==512*1024) submapper = 3; + } + if (submapper == 2) WRAM_init(info, 32); + info->Power = power; + info->Reset = reset; + GameStateRestore = restore; + AddExState(stateRegs, ~0, 0, 0); +} + +void Mapper264_Init (CartInfo *info) { + mapper = 264; + submapper = info->submapper; + info->Power = power; + info->Reset = reset; + GameStateRestore = restore; + AddExState(stateRegs, ~0, 0, 0); +} diff --git a/src/boards/8in1.c b/src/boards/8in1.c index 4f9db77..6498caf 100644 --- a/src/boards/8in1.c +++ b/src/boards/8in1.c @@ -27,12 +27,14 @@ #include "mapinc.h" #include "mmc3.h" +static uint8 submapper; + static void BMC8IN1CW(uint32 A, uint8 V) { setchr1(A, ((EXPREGS[0] & 0xC) << 5) | (V & 0x7F)); } static void BMC8IN1PW(uint32 A, uint8 V) { - if(EXPREGS[0] & 0x10) { /* MMC3 mode */ + if(EXPREGS[0] & 0x10 || submapper == 1) { /* MMC3 mode */ setprg8(A, ((EXPREGS[0] & 0xC) << 2) | (V & 0xF)); } else { setprg32(0x8000, EXPREGS[0] & 0xF); @@ -65,6 +67,7 @@ static void BMC8IN1Reset(void) { } void BMC8IN1_Init(CartInfo *info) { + submapper = info->submapper; GenMMC3_Init(info, 128, 128, 0, 0); cwrap = BMC8IN1CW; pwrap = BMC8IN1PW; diff --git a/src/boards/a9746.c b/src/boards/a9746.c index d2b1a05..009c7fb 100644 --- a/src/boards/a9746.c +++ b/src/boards/a9746.c @@ -22,18 +22,19 @@ #include "mmc3.h" static void UNLA9746PWrap(uint32 A, uint8 V) { - setprg8(A, EXPREGS[1] <<4 | V &0x0F); + int prgAND = EXPREGS[0] &0x40? 0x0F: 0x1F; + int prgOR = EXPREGS[0] <<4 &0x10 | EXPREGS[1] &0x20; + setprg8(A, V &prgAND | prgOR &~prgAND); } static void UNLA9746CWrap(uint32 A, uint8 V) { - setchr1(A, EXPREGS[1] <<7 | V &0x7F); + int chrAND = EXPREGS[0] &0x80? 0x7F: 0xFF; + int chrOR = EXPREGS[0] <<4 &0x80 | EXPREGS[1] <<3 &0x100; + setchr1(A, V &chrAND | chrOR &~chrAND); } static DECLFW(UNLA9746WriteOuter) { - switch(A &1) { - case 0: EXPREGS[1] =EXPREGS[1] &~1 | V >>3 &1; break; - case 1: EXPREGS[1] =EXPREGS[1] &~2 | V >>4 &2; break; - } + EXPREGS[A &1] = V; FixMMC3PRG(MMC3_cmd); FixMMC3CHR(MMC3_cmd); } @@ -43,7 +44,7 @@ static DECLFW(UNLA9746WriteASIC) { if (A &1) { /* Register data */ - if (~EXPREGS[0] &0x20) + if (~EXPREGS[2] &0x20) { /* Scrambled mode inactive */ MMC3_CMDWrite(A, V); } @@ -75,7 +76,7 @@ static DECLFW(UNLA9746WriteASIC) { else { /* Register index */ MMC3_CMDWrite(A, V); - if (A &2) EXPREGS[0] =V; + if (A &2) EXPREGS[2] =V; } } @@ -83,23 +84,25 @@ static void UNLA9746Power(void) { GenMMC3Power(); SetWriteHandler(0x5000, 0x5FFF, UNLA9746WriteOuter); SetWriteHandler(0x8000, 0xBFFF, UNLA9746WriteASIC); - EXPREGS[0] = 0; - EXPREGS[1] = 3; + EXPREGS[0] = 0x00; + EXPREGS[1] = 0x20; + EXPREGS[2] = 0x00; MMC3RegReset(); } static void UNLA9746Reset(void) { - EXPREGS[0] = 0; - EXPREGS[1] = 3; + EXPREGS[0] = 0x00; + EXPREGS[1] = 0x20; + EXPREGS[2] = 0x00; MMC3RegReset(); } void UNLA9746_Init(CartInfo *info) { - GenMMC3_Init(info, 128, 128, 0, 0); + GenMMC3_Init(info, 256, 256, 0, 0); pwrap = UNLA9746PWrap; cwrap = UNLA9746CWrap; info->Power = UNLA9746Power; info->Reset = UNLA9746Reset; - AddExState(EXPREGS, 2, 0, "EXPR"); + AddExState(EXPREGS, 3, 0, "EXPR"); } diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c index 040af3e..fe9b9fd 100644 --- a/src/boards/addrlatch.c +++ b/src/boards/addrlatch.c @@ -395,10 +395,10 @@ static void M227Sync(void) { } else { if (L) { setprg16(0x8000, p); - setprg16(0xC000, submapper ==3? 0: (p | 7)); + setprg16(0xC000, p | 7); } else { setprg16(0x8000, p); - setprg16(0xC000, submapper ==2? 0: (p & 0x38)); + setprg16(0xC000, submapper ==2? (p & 0x20): (p & 0x38)); } } } @@ -410,7 +410,7 @@ static void M227Sync(void) { setmirror(((latche >> 1) & 1) ^ 1); setchr8(0); - setprg8r(0x10, 0x6000, 0); + if (PRGsize[0x10]) setprg8r(0x10, 0x6000, 0); } static DECLFR(M227Read) { @@ -514,16 +514,15 @@ static void M242Sync(void) { } } } - - if (!hasBattery && (latche & 0x80) == 0x80 && (ROM_size * 16) > 256) - /* CHR-RAM write protect hack, needed for some multicarts */ + + if (latche &0x80 && submapper >0) /* CHR-RAM write protection not used on single-game cartridges (submapper 0) */ SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0); else SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1); setmirror(((latche >> 1) & 1) ^ 1); setchr8(0); - setprg8r(0x10, 0x6000, 0); + if (PRGsize[0x10]) setprg8r(0x10, 0x6000, 0); } static DECLFR(M242Read) { @@ -542,6 +541,7 @@ static void Mapper242_Reset(void) { void Mapper242_Init(CartInfo *info) { dipswitch = 0; + submapper = info->submapper; M242TwoChips = info->PRGRomSize &0x20000 && info->PRGRomSize >0x20000; Latch_Init(info, M242Sync, M242Read, 0x0000, 0x8000, 0xFFFF, info->iNES2 && (info->PRGRamSize || info->PRGRamSaveSize) || info->battery); info->Reset = Mapper242_Reset; @@ -640,8 +640,15 @@ static void BMC810544CA1Sync(void) { setmirror(((latche >> 4) & 1) ^ 1); } +void BMC810544CA1Reset() { + latche =0; + RAM[0x133] =0; + BMC810544CA1Sync(); +} + void BMC810544CA1_Init(CartInfo *info) { Latch_Init(info, BMC810544CA1Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); + info->Reset = BMC810544CA1Reset; } /*-------------- BMCNTD-03 ------------------------*/ @@ -689,23 +696,6 @@ void BMCG146_Init(CartInfo *info) { Latch_Init(info, BMCG146Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); } -/*-------------- BMC-TJ-03 ------------------------*/ -/* NES 2.0 mapper 341 is used for a simple 4-in-1 multicart */ - -static void BMCTJ03Sync(void) { - uint8 mirr = latche &(PRGsize[0] &0x40000? 0x800: 0x200)? MI_H: MI_V; - uint8 bank = latche >> 8; - - setprg32(0x8000, bank); - setchr8(bank); - - setmirror(mirr); -} - -void BMCTJ03_Init(CartInfo *info) { - Latch_Init(info, BMCTJ03Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); -} - /*-------------- BMC-SA005-A ------------------------*/ /* NES 2.0 mapper 338 is used for a 16-in-1 and a 200/300/600/1000-in-1 multicart. * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_338 */ diff --git a/src/boards/asic_mmc3.c b/src/boards/asic_mmc3.c index 330ba74..3c78b02 100644 --- a/src/boards/asic_mmc3.c +++ b/src/boards/asic_mmc3.c @@ -53,11 +53,13 @@ void MMC3_syncWRAM (int OR) { } int MMC3_getPRGBank (uint8 bank) { + bank &= 3; if (MMC3_index &0x40 && ~bank &1) bank ^= 2; return bank &2? 0xFE | bank &1: MMC3_reg[6 | bank &1]; } int MMC3_getCHRBank (uint8 bank) { + bank &= 7; if (MMC3_index &0x80) bank ^= 4; return bank &4? MMC3_reg[bank -2]: MMC3_reg[bank >>1] &~1 | bank &1; } @@ -83,6 +85,15 @@ DECLFW (MMC3_writeWRAM) { void MMC3_syncPRG (int AND, int OR) { int bank; for (bank = 0; bank < 4; bank++) setprg8(0x8000 | bank <<13, MMC3_cbGetPRGBank(bank) &AND |OR); + /* Enable or disable the Kick Master hack on multicarts */ + if (CartBR(0xF885) == 0xA2 && CartBR(0xF886) == 0x08 && CartBR(0xF887) == 0xCA && CartBR(0xF888) == 0xD0 && + CartBR(0xF894) == 0x20 && CartBR(0xF895) == 0xA7 && CartBR(0xF896) == 0xFA && CartBR(0xF897) == 0xAD) { + /* Kick Master is active. If the previous Horizontal Blanking handler was the standard MMC3 handler, switch it to the Kick-Master-specific one. */ + if (GameHBIRQHook == MMC3_clockCounter) GameHBIRQHook = MMC3_clockCounter_KickMaster; + } else { + /* Kick Master is not or no longer active. If the previous handler was the Kick-Master-specific one, switch it to the standard MMC3 one. */ + if (GameHBIRQHook == MMC3_clockCounter_KickMaster) GameHBIRQHook = MMC3_clockCounter; + } } void MMC3_syncCHR (int AND, int OR) { @@ -101,6 +112,11 @@ void MMC3_clockCounter () { MMC3_reloadRequest = 0; } +void MMC3_clockCounter_KickMaster () { + if (scanline == 238) MMC3_clockCounter(); + MMC3_clockCounter(); +} + DECLFW(MMC3_writeReg) { switch(A &0xE001) { case 0x8000: MMC3_index = V; break; diff --git a/src/boards/asic_mmc3.h b/src/boards/asic_mmc3.h index 3e4527b..a782d62 100644 --- a/src/boards/asic_mmc3.h +++ b/src/boards/asic_mmc3.h @@ -35,6 +35,7 @@ void MMC3_syncPRG (int, int); void MMC3_syncCHR (int, int); void MMC3_syncMirror (); void MMC3_clockCounter (); +void MMC3_clockCounter_KickMaster (); DECLFW (MMC3_writeReg); void MMC3_clear (); void MMC3_activate (uint8, void (*)(), uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*))); diff --git a/src/boards/asic_vrc2and4.c b/src/boards/asic_vrc2and4.c index 3e0cc22..e611074 100644 --- a/src/boards/asic_vrc2and4.c +++ b/src/boards/asic_vrc2and4.c @@ -113,7 +113,7 @@ DECLFR (VRC24_readWRAM) { return VRC24_cbReadWRAM(A); else if (WRAMSize) - CartBR(((A -0x6000) &(WRAMSize -1)) +0x6000); + return CartBR(((A -0x6000) &(WRAMSize -1)) +0x6000); else return A >>8; } else @@ -224,6 +224,7 @@ static void VRC2_configure (void (*sync)(), int A0, int A1, int (*prg)(uint8), i VRC24_cbGetCHRBank = chr? chr: VRC24_getCHRBank; VRC24_cbReadWRAM = read; VRC24_cbWriteWRAM = write; + VRC24_cbExternalSelect = NULL; } static void VRC4_configure (void (*sync)(), int A0, int A1, uint8 useRepeatBit, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write)), DECLFW((*externalSelect))) { diff --git a/src/boards/bmc830425C4391t.c b/src/boards/bmc830425C4391t.c index 108425a..475c097 100644 --- a/src/boards/bmc830425C4391t.c +++ b/src/boards/bmc830425C4391t.c @@ -42,6 +42,7 @@ static void Sync(void) { setprg16(0x8000, (outer_bank << 3) | (inner_bank & bank_size)); setprg16(0xC000, (outer_bank << 3) | bank_size); setchr8(0); + setmirror(outer_bank &0x08? MI_H: MI_V); } static DECLFW(M320Write) { diff --git a/src/boards/bmck3006.c b/src/boards/bmck3006.c index 7b5ca30..ba55a0a 100644 --- a/src/boards/bmck3006.c +++ b/src/boards/bmck3006.c @@ -29,7 +29,7 @@ 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); + return CartBR(A &~3 | EXPREGS[1] &3); } static void BMCK3006CW(uint32 A, uint8 V) { @@ -41,9 +41,10 @@ static void BMCK3006PW(uint32 A, uint8 V) { setprg8(A, (V & 0x0F) | (EXPREGS[0] & 0x18) << 1); } else { 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 */ + submapper ==1 && EXPREGS[0] &0x04 || + submapper ==2 && EXPREGS[0] &0x11 || + submapper ==3 && EXPREGS[0] &0x18 || + submapper ==4 && EXPREGS[0] &0x14) { /* NROM-256 */ setprg32(0x8000, (EXPREGS[0] >> 1) & 0x0F); } else { /* NROM-128 */ setprg16(0x8000, EXPREGS[0] & 0x1F); @@ -54,20 +55,19 @@ static void BMCK3006PW(uint32 A, uint8 V) { static DECLFW(BMCK3006Write) { 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] = EXPREGS[1] = 0; - EXPREGS[2]++; + EXPREGS[0] = 0; + EXPREGS[1]++; MMC3RegReset(); } static void BMCK3006Power(void) { - EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = 0; + EXPREGS[0] = EXPREGS[1] = 0; GenMMC3Power(); SetWriteHandler(0x6000, 0x7FFF, BMCK3006Write); } @@ -79,5 +79,5 @@ void BMCK3006_Init(CartInfo *info) { cwrap = BMCK3006CW; info->Power = BMCK3006Power; info->Reset = BMCK3006Reset; - AddExState(EXPREGS, 3, 0, "EXPR"); + AddExState(EXPREGS, 2, 0, "EXPR"); } diff --git a/src/boards/bmck3036.c b/src/boards/bmck3036.c deleted file mode 100644 index 73e03eb..0000000 --- a/src/boards/bmck3036.c +++ /dev/null @@ -1,69 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright (C) 2019 Libretro Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope 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 regs[2]; - -static SFORMAT StateRegs[] = -{ - { regs, 2, "REGS" }, - { 0 } -}; - -static void Sync(void) { - if (regs[0] &0x20) { /* NROM-128 */ - setprg16(0x8000, regs[0] >>2 &0x20 | regs[0] &0x1F); - setprg16(0xC000, regs[0] >>2 &0x20 | regs[0] &0x1F); - } else { /* UNROM */ - setprg16(0x8000, regs[0] >>2 &0x20 | regs[0] | regs[1] &7); - setprg16(0xC000, regs[0] >>2 &0x20 | regs[0] | 7); - } - setchr8(0); - setmirror((regs[0] &0x40 || regs[0] &0x20 && regs[0] &0x04)? MI_H: MI_V); -} - -static DECLFW(M340Write) { - regs[0] = A & 0xFF; - regs[1] = V; - Sync(); -} - -static void BMCK3036Power(void) { - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M340Write); -} - -static void BMCK3036Reset(void) { - regs[0] = regs[1] = 0; - Sync(); -} - -static void StateRestore(int version) { - Sync(); -} - -void BMCK3036_Init(CartInfo *info) { - info->Power = BMCK3036Power; - info->Reset = BMCK3036Reset; - GameStateRestore = StateRestore; - AddExState(&StateRegs, ~0, 0, 0); -} diff --git a/src/boards/dance2000.c b/src/boards/dance2000.c deleted file mode 100644 index a8a90f6..0000000 --- a/src/boards/dance2000.c +++ /dev/null @@ -1,113 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 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 - * - * Dance 2000 12-in-1 - * - */ - -#include "mapinc.h" - -static uint8 prg, mode; -static uint8 *WRAM = NULL; -static uint32 WRAMSIZE; -static uint32 lastnt = 0; - -static SFORMAT StateRegs[] = -{ - { &prg, 1, "REGS" }, - { &mode, 1, "MODE" }, - { &lastnt, 4, "LSNT" }, - { 0 } -}; - -static void Sync(void) { - setmirror((mode ^ 1) & 1); - setprg8r(0x10, 0x6000, 0); - setchr4(0x0000, lastnt); - setchr4(0x1000, 1); - if (mode & 4) - setprg32(0x8000, prg & 7); - else { - setprg16(0x8000, prg & 0x0f); - setprg16(0xC000, 0); - } -} - -static DECLFW(UNLD2000Write) { - switch (A) { - case 0x5000: prg = V; Sync(); break; - case 0x5200: mode = V; if (mode & 4) Sync(); break; - } -} - -static DECLFR(UNLD2000Read) { - if (prg & 0x40) - return X.DB; - else - return CartBR(A); -} - -static void UNLD2000Power(void) { - prg = mode = 0; - Sync(); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetReadHandler(0x8000, 0xFFFF, UNLD2000Read); - SetWriteHandler(0x5000, 0x5FFF, UNLD2000Write); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void FP_FASTAPASS(1) UNL2000Hook(uint32 A) { - if (mode & 2) { - if ((A & 0x3000) == 0x2000) { - uint32 curnt = A & 0x800; - if (curnt != lastnt) { - setchr4(0x0000, curnt >> 11); - lastnt = curnt; - } - } - } else { - lastnt = 0; - setchr4(0x0000, 0); - } -} - -static void UNLD2000Close(void) { - if (WRAM) - FCEU_gfree(WRAM); - WRAM = NULL; -} - -static void StateRestore(int version) { - Sync(); -} - -void UNLD2000_Init(CartInfo *info) { - info->Power = UNLD2000Power; - info->Close = UNLD2000Close; - PPU_hook = UNL2000Hook; - GameStateRestore = StateRestore; - - WRAMSIZE = 8192; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - - AddExState(&StateRegs, ~0, 0, 0); -} diff --git a/src/boards/datalatch.c b/src/boards/datalatch.c index 32d3d92..127de4f 100644 --- a/src/boards/datalatch.c +++ b/src/boards/datalatch.c @@ -558,7 +558,10 @@ void BMCK3046_Init(CartInfo *info) { static void Mapper429_Sync(void) { setprg32(0x8000, latche >>2); - setchr8(latche); + if (submapper == 2) + setchr8(latche &3 | (latche &4 && latche &8? 4: 0)); + else + setchr8(latche); } static void Mapper429_Reset(void) { @@ -567,6 +570,7 @@ static void Mapper429_Reset(void) { } void Mapper429_Init(CartInfo *info) { + submapper = info->submapper; info->Reset = Mapper429_Reset; Latch_Init(info, Mapper429_Sync, 0, 0x8000, 0xFFFF, 0, 0); } diff --git a/src/boards/fifo.c b/src/boards/fifo.c index 542671c..e66419a 100644 --- a/src/boards/fifo.c +++ b/src/boards/fifo.c @@ -1,3 +1,23 @@ +/* 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 #include @@ -37,7 +57,7 @@ void FIFO_init (FIFO *fifo, size_t newCapacity) { void FIFO_close (FIFO *fifo) { if (fifo->data) { - free(fifo->data); + FCEU_gfree(fifo->data); fifo->data = NULL; } } diff --git a/src/boards/gn26.c b/src/boards/gn26.c index ecaf5f9..f5c0ad9 100644 --- a/src/boards/gn26.c +++ b/src/boards/gn26.c @@ -40,21 +40,28 @@ static void BMCGN26PW(uint32 A, uint8 V) { setprg8(A, (EXPREGS[0] << 4) | (V & 0x0F)); } +static DECLFR(readPad) { + return EXPREGS[1] &0x01? X.DB: CartBR(A); +} + static DECLFW(BMCGN26Write) { if (A001B &0x80 && ~A001B &0x40) { EXPREGS[0] = A; FixMMC3PRG(MMC3_cmd); FixMMC3CHR(MMC3_cmd); + SetReadHandler(0x8000, 0xFFFF, EXPREGS[0] &0x08? readPad: CartBR); } } static void BMCGN26Reset(void) { EXPREGS[0] = 0; + EXPREGS[1]++; MMC3RegReset(); } static void BMCGN26Power(void) { GenMMC3Power(); + EXPREGS[1] = 0; SetWriteHandler(0x6000, 0x7FFF, BMCGN26Write); } @@ -64,5 +71,5 @@ void BMCGN26_Init(CartInfo *info) { cwrap = BMCGN26CW; info->Power = BMCGN26Power; info->Reset = BMCGN26Reset; - AddExState(EXPREGS, 1, 0, "EXPR"); + AddExState(EXPREGS, 2, 0, "EXPR"); } diff --git a/src/boards/mmc1.c b/src/boards/mmc1.c index d6b004d..310c4a3 100644 --- a/src/boards/mmc1.c +++ b/src/boards/mmc1.c @@ -24,6 +24,7 @@ static void GenMMC1Power(void); static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int saveram); +static uint8 submapper; static uint8 DRegs[4]; static uint8 Buffer, BufferShift; @@ -42,7 +43,7 @@ static void (*MMC1WRAMHook8)(void); static uint8 *WRAM = NULL; static uint8 *CHRRAM = NULL; -static int is155, is171; +static int is155; static uint32 MMC1GetCHRBank (uint32 bank) { if (DRegs[0] & 0x10) /* 4 KiB mode */ @@ -66,6 +67,10 @@ static DECLFR(MAWRAM) { return(Page[A >> 11][A]); } +static DECLFR(SFEXPROM_readBank) { + return DRegs[3] <<3 &0x70; +} + static void MMC1CHR(void) { if (MMC1WRAMHook8) /* Use custom wram hook, currently used for M543 */ MMC1WRAMHook8(); @@ -132,7 +137,7 @@ static void MMC1PRG(void) { } static void MMC1MIRROR(void) { - if (!is171) + if (submapper != 7) switch (DRegs[0] & 3) { case 2: setmirror(MI_V); break; case 3: setmirror(MI_H); break; @@ -297,7 +302,9 @@ static void GenMMC1Power(void) { SetReadHandler(0x6000, 0x7FFF, MAWRAM); SetWriteHandler(0x6000, 0x7FFF, MBWRAM); setprg8r(0x10, 0x6000, 0); - } + } else + if (submapper == 8) + SetReadHandler(0x6000, 0x6FFF, SFEXPROM_readBank); MMC1CMReset(); } @@ -311,6 +318,7 @@ static void GenMMC1Close(void) { } static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int saveram) { + submapper = info->submapper; is155 = 0; info->Close = GenMMC1Close; @@ -357,13 +365,6 @@ void Mapper155_Init(CartInfo *info) { is155 = 1; } -/* Same as mapper 1, with different (or without) mirroring control. */ -/* Kaiser KS7058 board, KS203 custom chip */ -void Mapper171_Init(CartInfo *info) { - GenMMC1Init(info, 32, 32, 0, 0); - is171 = 1; -} - void SAROM_Init(CartInfo *info) { GenMMC1Init(info, 128, 64, 8, info->battery ? 8 : 0); } diff --git a/src/boards/mmc3.c b/src/boards/mmc3.c index 978b57e..4b2aa4a 100644 --- a/src/boards/mmc3.c +++ b/src/boards/mmc3.c @@ -75,6 +75,8 @@ int MMC3CanWriteToWRAM(void) { return ((A001B & 0x80) && !(A001B & 0x40)); } +static void MMC3_hb (void); +static void MMC3_hb_KickMasterHack (void); void FixMMC3PRG(int V) { if (V & 0x40) { pwrap(0xC000, DRegBuf[6]); @@ -85,6 +87,15 @@ void FixMMC3PRG(int V) { } pwrap(0xA000, DRegBuf[7]); pwrap(0xE000, ~0); + /* Enable or disable the Kick Master hack on multicarts */ + if (CartBR(0xF885) == 0xA2 && CartBR(0xF886) == 0x08 && CartBR(0xF887) == 0xCA && CartBR(0xF888) == 0xD0 && + CartBR(0xF894) == 0x20 && CartBR(0xF895) == 0xA7 && CartBR(0xF896) == 0xFA && CartBR(0xF897) == 0xAD) { + /* Kick Master is active. If the previous Horizontal Blanking handler was the standard MMC3 handler, switch it to the Kick-Master-specific one. */ + if (GameHBIRQHook == MMC3_hb) GameHBIRQHook = MMC3_hb_KickMasterHack; + } else { + /* Kick Master is not or no longer active. If the previous handler was the Kick-Master-specific one, switch it to the standard MMC3 one. */ + if (GameHBIRQHook == MMC3_hb_KickMasterHack) GameHBIRQHook = MMC3_hb; + } } void FixMMC3CHR(int V) { @@ -639,8 +650,6 @@ void Mapper47_Init(CartInfo *info) { * BMC-STREETFIGTER-GAME4IN1 - Sic. $6000 set to $41 rather than $00 on power-up. */ -static uint8 isUNIF = 0; - static void M49PW(uint32 A, uint8 V) { if (EXPREGS[0] & 1) { V &= 0xF; @@ -658,20 +667,19 @@ static void M49CW(uint32 A, uint8 V) { } static DECLFW(M49Write) { - if (A001B & 0x80) { - EXPREGS[0] = V; - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); - } + if (submapper == 1 && A &0x800) V = EXPREGS[0] &0xC1 | V &~0xC1; + EXPREGS[0] = V; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); } static void M49Reset(void) { - EXPREGS[0] = isUNIF ? 0x41 : 0; + EXPREGS[0] = submapper == 1? 0x41 : 0; MMC3RegReset(); } static void M49Power(void) { - EXPREGS[0] = isUNIF ? 0x41 : 0; + EXPREGS[0] = submapper == 1? 0x41 : 0; M49Reset(); GenMMC3Power(); SetWriteHandler(0x6000, 0x7FFF, M49Write); @@ -679,7 +687,7 @@ static void M49Power(void) { } void Mapper49_Init(CartInfo *info) { - isUNIF = 0; + submapper = info->submapper; GenMMC3_Init(info, 512, 256, 0, 0); cwrap = M49CW; pwrap = M49PW; @@ -689,7 +697,7 @@ void Mapper49_Init(CartInfo *info) { } void BMCSFGAME4IN1_Init(CartInfo *info) { - isUNIF = 1; + submapper = 1; GenMMC3_Init(info, 512, 512, 0, 0); cwrap = M49CW; pwrap = M49PW; @@ -1015,21 +1023,6 @@ void Mapper165_Init(CartInfo *info) { AddExState(EXPREGS, 4, 0, "EXPR"); } -/* ---------------------------- Mapper 191 ------------------------------ */ - -static void M191CW(uint32 A, uint8 V) { - setchr1r((V & 0x80) >> 3, A, V); -} - -void Mapper191_Init(CartInfo *info) { - GenMMC3_Init(info, 256, 256, 8, info->battery); - cwrap = M191CW; - CHRRAMSIZE = 2048; - CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); -} - /* ---------------------------- Mapper 192 ------------------------------- */ static void M192CW(uint32 A, uint8 V) { diff --git a/src/boards/msm6585.c b/src/boards/msm6585.c index bf1a702..0d3880d 100644 --- a/src/boards/msm6585.c +++ b/src/boards/msm6585.c @@ -1,3 +1,23 @@ +/* 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 "msm6585.h" diff --git a/src/boards/sachen.c b/src/boards/sachen.c index cc97bc9..4149695 100644 --- a/src/boards/sachen.c +++ b/src/boards/sachen.c @@ -27,15 +27,6 @@ static uint8 cmd, dip; static uint8 latch[8]; static uint8 mapperNum; -static void S74LS374MSync(uint8 mirr) { - switch (mirr & 3) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirrorw(0, 1, 1, 1); break; - case 3: setmirror(MI_0); break; - } -} - static int type; static void S8259Synco(void) { int x; @@ -65,10 +56,15 @@ static void S8259Synco(void) { } } } - if (!(latch[7] & 1)) - S74LS374MSync(latch[7] >> 1); - else + if (latch[7] &1) setmirror(MI_V); + else + switch(latch[7] >>1 &3) { + case 0: setmirror(mapperNum == 137? MI_H: MI_V); break; + case 1: setmirror(mapperNum == 137? MI_V: MI_H); break; + case 2: setmirrorw(0, 1, 1, 1); break; + case 3: setmirror(MI_0); break; + } } static DECLFW(S8259Write) { @@ -98,6 +94,7 @@ static void S8259Restore(int version) { } void S8259A_Init(CartInfo *info) { /* Kevin's Horton 141 mapper */ + mapperNum = info->mapper; info->Power = S8259Reset; GameStateRestore = S8259Restore; AddExState(latch, 8, 0, "LATC"); @@ -106,6 +103,7 @@ void S8259A_Init(CartInfo *info) { /* Kevin's Horton 141 mapper */ } void S8259B_Init(CartInfo *info) { /* Kevin's Horton 138 mapper */ + mapperNum = info->mapper; info->Power = S8259Reset; GameStateRestore = S8259Restore; AddExState(latch, 8, 0, "LATC"); @@ -114,6 +112,7 @@ void S8259B_Init(CartInfo *info) { /* Kevin's Horton 138 mapper */ } void S8259C_Init(CartInfo *info) { /* Kevin's Horton 139 mapper */ + mapperNum = info->mapper; info->Power = S8259Reset; GameStateRestore = S8259Restore; AddExState(latch, 8, 0, "LATC"); @@ -122,6 +121,7 @@ void S8259C_Init(CartInfo *info) { /* Kevin's Horton 139 mapper */ } void S8259D_Init(CartInfo *info) { /* Kevin's Horton 137 mapper */ + mapperNum = info->mapper; info->Power = S8259Reset; GameStateRestore = S8259Restore; AddExState(latch, 8, 0, "LATC"); diff --git a/src/boards/subor.c b/src/boards/subor.c index 4f9a9bb..913bf27 100644 --- a/src/boards/subor.c +++ b/src/boards/subor.c @@ -55,6 +55,7 @@ static void Sync(void) { } } setchr8(0); + setmirror(regs[0] & 0x01? MI_H: MI_V); } static DECLFW(M166Write) { diff --git a/src/boards/yoko.c b/src/boards/yoko.c deleted file mode 100644 index fa43b47..0000000 --- a/src/boards/yoko.c +++ /dev/null @@ -1,248 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2006 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 - * - * YOKO mapper, almost the same as 83, TODO: figure out difference - * Mapper 83 - 30-in-1 mapper, two modes for single game carts, one mode for - * multigame Dragon Ball Z Party - * - * Mortal Kombat 2 YOKO - * N-CXX(M), XX - PRG+CHR, 12 - 128+256, 22 - 256+256, 14 - 128+512 - * - */ - -#include "mapinc.h" - -static uint8 mode, bank, reg[11], low[4], dip, IRQa; -static int32 IRQCount; -static uint8 *WRAM = NULL; -static uint32 WRAMSIZE; - -static uint8 is2kbank, dbzParty, isYoko; - -static SFORMAT StateRegs[] = -{ - { &mode, 1, "MODE" }, - { &bank, 1, "BANK" }, - { &IRQCount, 4, "IRQC" }, - { &IRQa, 1, "IRQA" }, - { reg, 11, "REGS" }, - { low, 4, "LOWR" }, - { &is2kbank, 1, "IS2K" }, - { 0 } -}; - -static void UNLYOKOSync(void) { - setmirror((mode & 1) ^ 1); - setchr2(0x0000, reg[3]); - setchr2(0x0800, reg[4]); - setchr2(0x1000, reg[5]); - setchr2(0x1800, reg[6]); - if (mode & 0x10) { - uint32 base = (bank & 8) << 1; - setprg8(0x8000, (reg[0] & 0x0f) | base); - setprg8(0xA000, (reg[1] & 0x0f) | base); - setprg8(0xC000, (reg[2] & 0x0f) | base); - setprg8(0xE000, 0x0f | base); - } else { - if (mode & 8) - setprg32(0x8000, bank >> 1); - else { - setprg16(0x8000, bank); - setprg16(0xC000, ~0); - } - } -} - -static void M83Sync(void) { - switch (mode & 3) { /* check if it is true */ - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_0); break; - case 3: setmirror(MI_1); break; - } - if (is2kbank) { - setchr2(0x0000, reg[0]); - setchr2(0x0800, reg[1]); - setchr2(0x1000, reg[6]); - setchr2(0x1800, reg[7]); - } else { - int x; - for (x = 0; x < 8; x++) - setchr1(x << 10, reg[x] | ((bank & 0x30) << 4)); - } - setprg8r(0x10, 0x6000, 0); - switch (mode >>3 &3) { - case 0: - setprg16(0x8000, bank); - setprg16(0xC000, bank |0x0F); - break; - case 1: - setprg32(0x8000, bank >>1); - break; - case 2: - case 3: - setprg8(0x8000, bank <<1 &~0x1F | reg[8] &0x1F); - setprg8(0xA000, bank <<1 &~0x1F | reg[9] &0x1F); - setprg8(0xC000, bank <<1 &~0x1F | reg[10]&0x1F); - setprg8(0xE000, bank <<1 &~0x1F | 0x1F); - break; - } -} - -static DECLFW(UNLYOKOWrite) { - switch (A & 0x8C17) { - case 0x8000: bank = V; UNLYOKOSync(); break; - case 0x8400: mode = V; UNLYOKOSync(); break; - case 0x8800: IRQCount &= 0xFF00; IRQCount |= V; X6502_IRQEnd(FCEU_IQEXT); break; - case 0x8801: IRQa = mode & 0x80; IRQCount &= 0xFF; IRQCount |= V << 8; break; - case 0x8c00: reg[0] = V; UNLYOKOSync(); break; - case 0x8c01: reg[1] = V; UNLYOKOSync(); break; - case 0x8c02: reg[2] = V; UNLYOKOSync(); break; - case 0x8c10: reg[3] = V; UNLYOKOSync(); break; - case 0x8c11: reg[4] = V; UNLYOKOSync(); break; - case 0x8c16: reg[5] = V; UNLYOKOSync(); break; - case 0x8c17: reg[6] = V; UNLYOKOSync(); break; - } -} - -static DECLFW(M83Write) { - switch (A &0x31F) { - case 0x000: bank = V; M83Sync(); break; - case 0x100: mode = V; M83Sync(); break; - case 0x200: IRQCount &= 0xFF00; IRQCount |= V; X6502_IRQEnd(FCEU_IQEXT); break; - case 0x201: IRQa = mode & 0x80; IRQCount &= 0xFF; IRQCount |= V << 8; break; - case 0x300: reg[8] = V; mode &= 0xBF; M83Sync(); break; - case 0x301: reg[9] = V; mode &= 0xBF; M83Sync(); break; - case 0x302: reg[10] = V; mode &= 0xBF; M83Sync(); break; - case 0x310: reg[0] = V; M83Sync(); break; - case 0x311: reg[1] = V; M83Sync(); break; - case 0x312: reg[2] = V; M83Sync(); break; - case 0x313: reg[3] = V; M83Sync(); break; - case 0x314: reg[4] = V; M83Sync(); break; - case 0x315: reg[5] = V; M83Sync(); break; - case 0x316: reg[6] = V; M83Sync(); break; - case 0x317: reg[7] = V; M83Sync(); break; - } -} - -static DECLFR(UNLYOKOReadDip) { - return (X.DB & 0xFC) | dip; -} - -static DECLFR(UNLYOKOReadLow) { - return low[A & 3]; -} - -static DECLFW(UNLYOKOWriteLow) { - low[A & 3] = V; -} - -static void UNLYOKOPower(void) { - mode = bank = 0; - dip = 3; - UNLYOKOSync(); - SetReadHandler(0x5000, 0x53FF, UNLYOKOReadDip); - SetReadHandler(0x5400, 0x5FFF, UNLYOKOReadLow); - SetWriteHandler(0x5400, 0x5FFF, UNLYOKOWriteLow); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, UNLYOKOWrite); -} - -static void M83Power(void) { - mode = bank = 0; - dip = 0; - M83Sync(); - SetReadHandler(0x5000, 0x5000, UNLYOKOReadDip); - SetReadHandler(0x5100, 0x5103, UNLYOKOReadLow); - SetWriteHandler(0x5100, 0x5103, UNLYOKOWriteLow); - SetReadHandler(0x6000, 0x7fff, CartBR); - SetWriteHandler(0x6000, 0x7fff, CartBW); - SetReadHandler(0x8000, 0xffff, CartBR); - SetWriteHandler(0x8000, 0xffff, M83Write); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void UNLYOKOReset(void) { - dip = (dip + 1) & 3; - mode = bank = 0; - UNLYOKOSync(); -} - -static void M83Reset(void) { - dip ^= 1; - mode = bank = 0; - M83Sync(); -} - -static void M83Close(void) { - if (WRAM) - FCEU_gfree(WRAM); - WRAM = NULL; -} - -static void FP_FASTAPASS(1) UNLYOKOIRQHook(int a) { - if (IRQa) { - IRQCount -= a; - if (IRQCount < 0) { - X6502_IRQBegin(FCEU_IQEXT); - IRQa = 0; - IRQCount = 0xFFFF; - } - } -} - -static void UNLYOKOStateRestore(int version) { - UNLYOKOSync(); -} - -static void M83StateRestore(int version) { - M83Sync(); -} - -void UNLYOKO_Init(CartInfo *info) { - info->Power = UNLYOKOPower; - info->Reset = UNLYOKOReset; - MapIRQHook = UNLYOKOIRQHook; - GameStateRestore = UNLYOKOStateRestore; - AddExState(&StateRegs, ~0, 0, 0); -} - -void Mapper83_Init(CartInfo *info) { - info->Power = M83Power; - info->Reset = M83Reset; - info->Close = M83Close; - MapIRQHook = UNLYOKOIRQHook; - GameStateRestore = M83StateRestore; - - if (info->iNES2) { - is2kbank =info->submapper ==1; - dbzParty =info->submapper ==2; - } else { - is2kbank = info->CHRRomSize ==512*1024; - dbzParty = info->PRGRomSize ==1024*1024; - } - if (dbzParty) { - WRAMSIZE = 8192; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - } - - AddExState(&StateRegs, ~0, 0, 0); -} diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index ad85bcf..4eda5b0 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -112,6 +112,9 @@ typedef uint16 bpp_t; #define RETRO_DEVICE_FC_HYPERSHOT RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 3) #define RETRO_DEVICE_FC_FTRAINERA RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_KEYBOARD, 2) #define RETRO_DEVICE_FC_FTRAINERB RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_KEYBOARD, 3) +#define RETRO_DEVICE_FC_FKB RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_KEYBOARD, 4) +#define RETRO_DEVICE_FC_SUBORKB RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_KEYBOARD, 5) +#define RETRO_DEVICE_FC_PEC586KB RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_KEYBOARD, 6) #define RETRO_DEVICE_FC_AUTO RETRO_DEVICE_JOYPAD #define NES_WIDTH 256 @@ -192,6 +195,30 @@ static const uint32_t powerpadmap[] = { RETROK_z, RETROK_x, RETROK_c, RETROK_v, }; +static const uint32_t fkbmap[0x48] = { + RETROK_F1,RETROK_F2,RETROK_F3,RETROK_F4,RETROK_F5,RETROK_F6,RETROK_F7,RETROK_F8, + RETROK_1,RETROK_2,RETROK_3,RETROK_4,RETROK_5,RETROK_6,RETROK_7,RETROK_8,RETROK_9,RETROK_0,RETROK_MINUS,RETROK_EQUALS,RETROK_BACKSLASH,RETROK_BACKSPACE, + RETROK_ESCAPE,RETROK_q,RETROK_w,RETROK_e,RETROK_r,RETROK_t,RETROK_y,RETROK_u,RETROK_i,RETROK_o,RETROK_p,RETROK_TILDE,RETROK_LEFTBRACKET,RETROK_RETURN, + RETROK_LCTRL,RETROK_a,RETROK_s,RETROK_d,RETROK_f,RETROK_g,RETROK_h,RETROK_j,RETROK_k,RETROK_l,RETROK_SEMICOLON,RETROK_QUOTE,RETROK_RIGHTBRACKET,RETROK_INSERT, + RETROK_LSHIFT,RETROK_z,RETROK_x,RETROK_c,RETROK_v,RETROK_b,RETROK_n,RETROK_m,RETROK_COMMA,RETROK_PERIOD,RETROK_SLASH,RETROK_RALT,RETROK_RSHIFT,RETROK_LALT,RETROK_SPACE, + RETROK_DELETE,RETROK_END,RETROK_PAGEDOWN, + RETROK_UP,RETROK_LEFT,RETROK_RIGHT,RETROK_DOWN +}; + +static const uint32_t suborkbmap[0x65] = { + RETROK_ESCAPE,RETROK_F1,RETROK_F2,RETROK_F3,RETROK_F4,RETROK_F5,RETROK_F6,RETROK_F7,RETROK_F8,RETROK_F9, + RETROK_F10,RETROK_F11,RETROK_F12,RETROK_NUMLOCK,RETROK_CARET,RETROK_1,RETROK_2,RETROK_3,RETROK_4,RETROK_5, + RETROK_6,RETROK_7,RETROK_8,RETROK_9,RETROK_0,RETROK_MINUS,RETROK_EQUALS,RETROK_BACKSPACE,RETROK_INSERT,RETROK_HOME, + RETROK_PAGEUP,RETROK_PAUSE,RETROK_KP_DIVIDE,RETROK_KP_MULTIPLY,RETROK_KP_MINUS,RETROK_TAB,RETROK_q,RETROK_w,RETROK_e,RETROK_r, + RETROK_t,RETROK_y,RETROK_u,RETROK_i,RETROK_o,RETROK_p,RETROK_LEFTBRACKET,RETROK_RIGHTBRACKET,RETROK_RETURN,RETROK_DELETE, + RETROK_END,RETROK_PAGEDOWN,RETROK_KP7,RETROK_KP8,RETROK_KP9,RETROK_KP_PLUS,RETROK_CAPSLOCK,RETROK_a,RETROK_s,RETROK_d, + RETROK_f,RETROK_g,RETROK_h,RETROK_j,RETROK_k,RETROK_l,RETROK_SEMICOLON,RETROK_QUOTE,RETROK_KP4,RETROK_KP5, + RETROK_KP6,RETROK_LSHIFT,RETROK_z,RETROK_x,RETROK_c,RETROK_v,RETROK_b,RETROK_n,RETROK_m,RETROK_COMMA, + RETROK_PERIOD,RETROK_SLASH,RETROK_BACKSLASH,RETROK_UP,RETROK_KP1,RETROK_KP2,RETROK_KP3,RETROK_LCTRL,RETROK_LALT,RETROK_SPACE, + RETROK_LEFT,RETROK_DOWN,RETROK_RIGHT,RETROK_KP0,RETROK_KP_PERIOD,RETROK_UNKNOWN,RETROK_UNKNOWN,RETROK_UNKNOWN,RETROK_UNKNOWN,RETROK_UNKNOWN, + RETROK_UNKNOWN +}; + typedef struct { bool enable_4player; /* four-score / 4-player adapter used */ @@ -208,6 +235,8 @@ typedef struct { uint32_t MouseData[MAX_PORTS][4]; /* nes mouse data */ uint32_t FamicomData[3]; /* Famicom expansion port data */ uint32_t PowerPadData; + uint8_t FamilyKeyboardData[0x48]; + uint8_t SuborKeyboardData[0x65]; } NES_INPUT_T; static NES_INPUT_T nes_input = { 0 }; @@ -1323,6 +1352,18 @@ static void update_nes_controllers(unsigned port, unsigned device) FCEUI_SetInputFC(SIFC_FTRAINERB, &nes_input.PowerPadData, 0); FCEU_printf(" Famicom Expansion: Family Trainer B\n"); break; + case RETRO_DEVICE_FC_FKB: + FCEUI_SetInputFC(SIFC_FKB, &nes_input.FamilyKeyboardData, 0); + FCEU_printf(" Famicom Expansion: Family BASIC Keyboard\n"); + break; + case RETRO_DEVICE_FC_SUBORKB: + FCEUI_SetInputFC(SIFC_SUBORKB, &nes_input.SuborKeyboardData, 0); + FCEU_printf(" Famicom Expansion: Subor Keyboard\n"); + break; + case RETRO_DEVICE_FC_PEC586KB: + FCEUI_SetInputFC(SIFC_PEC586KB, &nes_input.SuborKeyboardData, 0); + FCEU_printf(" Famicom Expansion: Dongda Keyboard\n"); + break; case RETRO_DEVICE_NONE: default: FCEUI_SetInputFC(SIFC_NONE, &Dummy, 0); @@ -1373,6 +1414,12 @@ static unsigned fc_to_libretro(int d) return RETRO_DEVICE_FC_FTRAINERA; case SIFC_FTRAINERB: return RETRO_DEVICE_FC_FTRAINERB; + case SIFC_FKB: + return RETRO_DEVICE_FC_FKB; + case SIFC_SUBORKB: + return RETRO_DEVICE_FC_SUBORKB; + case SIFC_PEC586KB: + return RETRO_DEVICE_FC_PEC586KB; } return (RETRO_DEVICE_NONE); @@ -2390,8 +2437,7 @@ static void check_variables(bool startup) update_option_visibility(); } -void add_powerpad_input(unsigned port, uint32 variant, uint32_t *ppdata) -{ +void add_powerpad_input(unsigned port, uint32 variant, uint32_t *ppdata) { unsigned k; const uint32_t* map = powerpadmap; for (k = 0 ; k < 12 ; k++) @@ -2399,6 +2445,26 @@ void add_powerpad_input(unsigned port, uint32 variant, uint32_t *ppdata) *ppdata |= (1 << k); } +void add_fkb_input(unsigned port, uint32 variant, uint8_t *fkbkeys) { + unsigned k; + const uint32_t* map = fkbmap; + for (k = 0 ; k < 0x48 ; k++) + if (input_cb(0, RETRO_DEVICE_KEYBOARD, 0, map[k])) + fkbkeys[k]=1; + else + fkbkeys[k]=0; +} + +void add_suborkey_input(unsigned port, uint32 variant, uint8_t *suborkeys) { + unsigned k; + const uint32_t* map = suborkbmap; + for (k = 0 ; k < 0x65 ; k++) + if (input_cb(0, RETRO_DEVICE_KEYBOARD, 0, map[k])) + suborkeys[k]=1; + else + suborkeys[k]=0; +} + static int mzx = 0, mzy = 0; void get_mouse_input(unsigned port, uint32 variant, uint32_t *mousedata) @@ -2763,6 +2829,13 @@ static void FCEUD_UpdateInput(void) case RETRO_DEVICE_FC_FTRAINERA: add_powerpad_input(4, nes_input.type[4], &nes_input.PowerPadData); break; + case RETRO_DEVICE_FC_FKB: + add_fkb_input(4, nes_input.type[4], nes_input.FamilyKeyboardData); + break; + case RETRO_DEVICE_FC_SUBORKB: + case RETRO_DEVICE_FC_PEC586KB: + add_suborkey_input(4, nes_input.type[4], nes_input.SuborKeyboardData); + break; } if (input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2)) diff --git a/src/ines.c b/src/ines.c index 0d0b35f..212b6c6 100644 --- a/src/ines.c +++ b/src/ines.c @@ -624,7 +624,7 @@ INES_BOARD_BEGIN() INES_BOARD( "", 168, Mapper168_Init ) /* INES_BOARD( "", 169, Mapper169_Init ) */ INES_BOARD( "", 170, Mapper170_Init ) - INES_BOARD( "", 171, Mapper171_Init ) +/* INES_BOARD( "", 171, Mapper171_Init )*/ INES_BOARD( "Super Mega P-4070", 172, Mapper172_Init ) INES_BOARD( "Idea-Tek ET.xx", 173, Mapper173_Init ) INES_BOARD( "", 174, Mapper174_Init ) @@ -708,7 +708,7 @@ INES_BOARD_BEGIN() INES_BOARD( "SAN GUO ZHI PIRATE", 252, Mapper252_Init ) INES_BOARD( "DRAGON BALL PIRATE", 253, Mapper253_Init ) INES_BOARD( "", 254, Mapper254_Init ) - INES_BOARD( "", 255, Mapper255_Init ) /* Duplicate of M225? */ + INES_BOARD( "", 255, Mapper255_Init ) /* Variant of M225 */ /* NES 2.0 MAPPERS */ @@ -719,7 +719,7 @@ INES_BOARD_BEGIN() INES_BOARD( "810544-C-A1", 261, BMC810544CA1_Init ) INES_BOARD( "SHERO", 262, UNLSHeroes_Init ) INES_BOARD( "KOF97", 263, UNLKOF97_Init ) - INES_BOARD( "YOKO", 264, UNLYOKO_Init ) + INES_BOARD( "YOKO", 264, Mapper264_Init ) INES_BOARD( "T-262", 265, Mapper265_Init ) INES_BOARD( "CITYFIGHT", 266, UNLCITYFIGHT_Init ) INES_BOARD( "8-in-1 JY-119", 267, Mapper267_Init ) @@ -750,7 +750,7 @@ INES_BOARD_BEGIN() INES_BOARD( "TF1201", 298, UNLTF1201_Init ) INES_BOARD( "11160", 299, BMC11160_Init ) INES_BOARD( "190in1", 300, BMC190in1_Init ) - INES_BOARD( "8157", 301, UNL8157_Init ) + INES_BOARD( "K-3003", 301, Mapper301_Init ) INES_BOARD( "KS7057", 302, UNLKS7057_Init ) INES_BOARD( "KS7017", 303, UNLKS7017_Init ) INES_BOARD( "SMB2J", 304, UNLSMB2J_Init ) @@ -785,9 +785,10 @@ INES_BOARD_BEGIN() INES_BOARD( "CTC-12IN1", 337, BMCCTC12IN1_Init ) INES_BOARD( "SA005-A", 338, BMCSA005A_Init ) INES_BOARD( "K-3006", 339, BMCK3006_Init ) - INES_BOARD( "K-3036", 340, BMCK3036_Init ) - INES_BOARD( "TJ-03", 341, BMCTJ03_Init ) + INES_BOARD( "K-3036", 340, Mapper340_Init ) + INES_BOARD( "TJ-03", 341, Mapper341_Init ) INES_BOARD( "COOLGIRL", 342, COOLGIRL_Init ) + INES_BOARD( "I030", 343, Mapper343_Init ) INES_BOARD( "GN-26", 344, BMCGN26_Init ) INES_BOARD( "L6IN1", 345, BMCL6IN1_Init ) INES_BOARD( "KS7012", 346, UNLKS7012_Init ) @@ -878,7 +879,7 @@ INES_BOARD_BEGIN() 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( "KL-06/GC007", 447, Mapper447_Init ) INES_BOARD( "830768C", 448, Mapper448_Init ) INES_BOARD( "22-in-1 King Series", 449, Mapper449_Init ) INES_BOARD( "晶太 YY841157C", 450, Mapper450_Init ) @@ -944,7 +945,7 @@ INES_BOARD_BEGIN() 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( "Subor SB96", 518, Mapper518_Init ) INES_BOARD( "EH8813A", 519, UNLEH8813A_Init ) INES_BOARD( "YuYuHakusho+DBZ", 520, Mapper520_Init ) INES_BOARD( "DREAMTECH01", 521, DreamTech01_Init ) @@ -1017,6 +1018,25 @@ INES_BOARD_BEGIN() 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( "FC-49", 596, Mapper596_Init ) + INES_BOARD( "GN-27", 597, Mapper597_Init ) + INES_BOARD( "3936", 598, Mapper598_Init ) + INES_BOARD( "ET-133A", 599, Mapper599_Init ) + INES_BOARD( "J-2061", 603, Mapper603_Init ) + INES_BOARD( "New Star TX5/8IN1", 605, Mapper605_Init ) + INES_BOARD( "New Star T4IN1", 606, Mapper606_Init ) + INES_BOARD( "4705", 607, Mapper607_Init ) + INES_BOARD( "A-23", 608, Mapper608_Init ) + INES_BOARD( "63-100", 609, Mapper609_Init ) + INES_BOARD( "J-2042", 610, Mapper610_Init ) + INES_BOARD( "T-124/43-117/831049", 611, Mapper611_Init ) + INES_BOARD( "K-3004", 612, Mapper612_Init ) + INES_BOARD( "S5668 3366", 613, Mapper613_Init ) + INES_BOARD( "New Star 9135", 614, Mapper614_Init ) + INES_BOARD( "LB12in1", 615, Mapper615_Init ) + INES_BOARD( "K-3044", 616, Mapper616_Init ) + INES_BOARD( "AD-301", 617, Mapper617_Init ) + INES_BOARD( "FC 4-in-1 (NS32)", 618, Mapper618_Init ) INES_BOARD_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index 2caf764..ed9e299 100644 --- a/src/ines.h +++ b/src/ines.h @@ -177,7 +177,6 @@ void Mapper166_Init(CartInfo *); void Mapper167_Init(CartInfo *); void Mapper168_Init(CartInfo *); void Mapper170_Init(CartInfo *); -void Mapper171_Init(CartInfo *); void Mapper172_Init(CartInfo *); void Mapper173_Init(CartInfo *); void Mapper174_Init(CartInfo *); @@ -251,6 +250,7 @@ void Mapper252_Init(CartInfo *); void Mapper253_Init(CartInfo *); void Mapper254_Init(CartInfo *); void Mapper255_Init(CartInfo *); +void Mapper264_Init(CartInfo *); void Mapper270_Init(CartInfo *); void Mapper272_Init(CartInfo *); void Mapper273_Init(CartInfo *); @@ -273,12 +273,16 @@ void Mapper288_Init(CartInfo *); void Mapper293_Init(CartInfo *); void Mapper294_Init(CartInfo *); void Mapper297_Init(CartInfo *); +void Mapper301_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 Mapper340_Init(CartInfo *); +void Mapper341_Init(CartInfo *); +void Mapper343_Init(CartInfo *); void Mapper351_Init(CartInfo *); void Mapper352_Init(CartInfo *); void Mapper353_Init(CartInfo *); @@ -424,6 +428,7 @@ void Mapper511_Init(CartInfo *); void Mapper512_Init(CartInfo *); void Mapper514_Init(CartInfo *); void Mapper516_Init(CartInfo *); +void Mapper518_Init(CartInfo *); void Mapper520_Init(CartInfo *); void Mapper523_Init(CartInfo *); void Mapper528_Init(CartInfo *); @@ -484,7 +489,25 @@ void Mapper591_Init(CartInfo *); void Mapper592_Init(CartInfo *); void Mapper594_Init(CartInfo *); void Mapper595_Init(CartInfo *); - +void Mapper596_Init(CartInfo *); +void Mapper597_Init(CartInfo *); +void Mapper598_Init(CartInfo *); +void Mapper599_Init(CartInfo *); +void Mapper603_Init(CartInfo *); +void Mapper605_Init(CartInfo *); +void Mapper606_Init(CartInfo *); +void Mapper607_Init(CartInfo *); +void Mapper608_Init(CartInfo *); +void Mapper609_Init(CartInfo *); +void Mapper610_Init(CartInfo *); +void Mapper611_Init(CartInfo *); +void Mapper612_Init(CartInfo *); +void Mapper613_Init(CartInfo *); +void Mapper614_Init(CartInfo *); +void Mapper615_Init(CartInfo *); +void Mapper616_Init(CartInfo *); +void Mapper617_Init(CartInfo *); +void Mapper618_Init(CartInfo *); void FFE_Init(CartInfo *); #endif diff --git a/src/sound.c b/src/sound.c index dbf1c8a..49efcc4 100644 --- a/src/sound.c +++ b/src/sound.c @@ -1070,7 +1070,7 @@ void FCEUSND_Power(void) { for (x = 0; x < 5; x++) ChannelBC[x] = 0; soundtsoffs = 0; - IRQFrameMode = 0x0; /* Only initialized by power-on reset, not by soft reset */ + IRQFrameMode = 0x1; /* Only initialized by power-on reset, not by soft reset. NRS: don't start with Frame IRQ enabled for greater compatibility. Any game that actually uses frame IRQ will explicitly enable it, anyway. */ LoadDMCPeriod(DMCFormat & 0xF); } diff --git a/src/unif.c b/src/unif.c index 6667abf..4d47250 100644 --- a/src/unif.c +++ b/src/unif.c @@ -430,10 +430,10 @@ static BMAPPING bmap[] = { { "43272", 242, Mapper242_Init, 0 }, { "603-5052", 238, UNL6035052_Init, 0 }, { "64in1NoRepeat", 314, BMC64in1nr_Init, 0 }, - { "70in1", 236, Mapper236_Init, 0 }, + { "70in1", 236, Mapper236_Init, 0 }, { "70in1B", 236, Mapper236_Init, 0 }, { "810544-C-A1", 261, BMC810544CA1_Init, 0 }, - { "8157", 301, UNL8157_Init, 0 }, + { "8157", 242, Mapper242_Init, 0 }, { "8237", 215, UNL8237_Init, 0 }, { "8237A", 215, UNL8237A_Init, 0 }, { "830118C", 348, BMC830118C_Init, 0 }, @@ -456,7 +456,7 @@ static BMAPPING bmap[] = { { "D1038", 59, BMCD1038_Init, 0 }, { "T3H53", 59, BMCD1038_Init, 0 }, { "DANCE", 256, UNLOneBus_Init, 0 }, - { "DANCE2000", 518, UNLD2000_Init, 0 }, + { "DANCE2000", 518, Mapper518_Init, 0 }, { "DREAMTECH01", 521, DreamTech01_Init, 0 }, { "EDU2000", 329, UNLEDU2000_Init, 0 }, { "EKROM", 5, EKROM_Init, 0 }, @@ -563,7 +563,7 @@ static BMAPPING bmap[] = { { "UNROM-512-32", 30, UNROM512_Init, BMCFLAG_32KCHRR }, { "UOROM", 2, UNROM_Init, 0 }, { "VRC7", 85, UNLVRC7_Init, 0 }, - { "YOKO", 264, UNLYOKO_Init, 0 }, + { "YOKO", 264, Mapper264_Init, 0 }, { "COOLBOY", 268, COOLBOY_Init, BMCFLAG_256KCHRR }, { "MINDKIDS", 268, MINDKIDS_Init, BMCFLAG_256KCHRR }, { "158B", 258, UNL8237_Init, 0 }, @@ -590,12 +590,12 @@ static BMAPPING bmap[] = { { "K-3088", 287, BMCK3088_Init, 0 }, { "FARID_SLROM_8-IN-1", 323, FARIDSLROM8IN1_Init, 0 }, { "830425C-4391T", 320, BMC830425C4391T_Init, 0 }, - { "TJ-03", 341, BMCTJ03_Init, 0 }, + { "TJ-03", 341, Mapper341_Init, 0 }, { "CTC-09", 335, BMCCTC09_Init, 0 }, { "K-3046", 336, BMCK3046_Init, 0 }, { "SA005-A", 338, BMCSA005A_Init, 0 }, { "K-3006", 339, BMCK3006_Init, 0 }, - { "K-3036", 340, BMCK3036_Init, 0 }, + { "K-3036", 340, Mapper340_Init, 0 }, { "KS7021A", 525, UNLKS7021A_Init, 0 }, { "KS106C", NO_INES, BMCKS106C_Init, 0 }, /* split roms */ { "900218", 524, BTL900218_Init, 0 }, diff --git a/src/unif.h b/src/unif.h index 4a07fe4..6c96479 100644 --- a/src/unif.h +++ b/src/unif.h @@ -135,7 +135,6 @@ void UNLSMB2J_Init(CartInfo *info); void UNLT230_Init(CartInfo *info); void UNLTF1201_Init(CartInfo *info); void UNLVRC7_Init(CartInfo *info); -void UNLYOKO_Init(CartInfo *info); void UNROM_Init(CartInfo *info); void UNROM512_Init(CartInfo *info); void COOLBOY_Init(CartInfo *info); @@ -159,12 +158,11 @@ void LH51_Init(CartInfo *info); /* m309 */ void BMCRESETTXROM_Init(CartInfo *info); /* m313 */ void FARIDSLROM8IN1_Init(CartInfo *info); /* m323 */ void BMC830425C4391T_Init(CartInfo *info); /* m320 */ -void BMCTJ03_Init(CartInfo *info); /* m341 */ void BMCCTC09_Init(CartInfo *info); /* m335 */ void BMCK3046_Init(CartInfo *info); /* m336 */ void BMCSA005A_Init(CartInfo *info); /* m338 */ void BMCK3006_Init(CartInfo *info); /* m339 */ -void BMCK3036_Init(CartInfo *info); /* m340 */ +void Mapper340_Init(CartInfo *info); /* m340 */ void MINDKIDS_Init(CartInfo *info); /* m268 */ void UNLKS7021A_Init(CartInfo *info); /* m525 */ void BTL900218_Init(CartInfo *info); /* m524 */