From 29a0caf61b7e1cc3fe5edc91b67a4fb6b2909fd6 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sat, 13 Sep 2025 11:27:38 +0200 Subject: [PATCH 01/66] Add keyboard input. --- src/drivers/libretro/libretro.c | 77 ++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) 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)) From 5d88968cf9d6911fb82d38e4f64921265a6064df Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sat, 13 Sep 2025 12:31:58 +0200 Subject: [PATCH 02/66] Adding software-selectable mirroring to mapper 166/167. Rewrite mapper 518. --- src/boards/518.c | 95 ++++++++++++++++++++++++++++++++++ src/boards/dance2000.c | 113 ----------------------------------------- src/boards/subor.c | 1 + src/ines.c | 2 +- src/ines.h | 1 + src/unif.c | 2 +- 6 files changed, 99 insertions(+), 115 deletions(-) create mode 100644 src/boards/518.c delete mode 100644 src/boards/dance2000.c diff --git a/src/boards/518.c b/src/boards/518.c new file mode 100644 index 0000000..369c48b --- /dev/null +++ b/src/boards/518.c @@ -0,0 +1,95 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "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(&chr, 1, 0, "CHRB"); +} 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/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/ines.c b/src/ines.c index 0d0b35f..d704063 100644 --- a/src/ines.c +++ b/src/ines.c @@ -944,7 +944,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 ) diff --git a/src/ines.h b/src/ines.h index 2caf764..c90ef0a 100644 --- a/src/ines.h +++ b/src/ines.h @@ -424,6 +424,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 *); diff --git a/src/unif.c b/src/unif.c index 6667abf..2332e14 100644 --- a/src/unif.c +++ b/src/unif.c @@ -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 }, From fc9d69430d4d03f2cd10716d2ede655ddd47db76 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Wed, 17 Sep 2025 19:20:54 +0200 Subject: [PATCH 03/66] Slight fixes; add GNU preamble. --- src/boards/518.c | 1 + src/boards/fifo.c | 22 +++++++++++++++++++++- src/boards/msm6585.c | 20 ++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/boards/518.c b/src/boards/518.c index 369c48b..9a8944c 100644 --- a/src/boards/518.c +++ b/src/boards/518.c @@ -91,5 +91,6 @@ void Mapper518_Init (CartInfo *info) { info->Reset = reset; GameStateRestore = restore; PPU_hook = trapPPUAddressChange; + AddExState(reg, 2, 0, "REGS"); AddExState(&chr, 1, 0, "CHRB"); } 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/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" From 1ac2f351ee9afb682fc4d29ca266bdc60fe9dc05 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Wed, 17 Sep 2025 19:46:40 +0200 Subject: [PATCH 04/66] Add mapper 422.3. Correct multicart registers of mapper 219. --- src/boards/126_422_534.c | 8 ++++++++ src/boards/a9746.c | 31 +++++++++++++++++-------------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/boards/126_422_534.c b/src/boards/126_422_534.c index 18f5836..2ae880d 100644 --- a/src/boards/126_422_534.c +++ b/src/boards/126_422_534.c @@ -51,6 +51,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. */ @@ -80,6 +84,10 @@ static void wrapCHR(uint32 A, uint8 V) { 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/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"); } From 3969360227c2542e2fd0cf662410f07636b65329 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Wed, 17 Sep 2025 20:25:14 +0200 Subject: [PATCH 05/66] Rewrite mapper 340. --- src/boards/340.c | 43 +++++++++++++++++++++++++++ src/boards/bmck3036.c | 69 ------------------------------------------- src/ines.c | 2 +- src/ines.h | 1 + src/unif.c | 2 +- src/unif.h | 2 +- 6 files changed, 47 insertions(+), 72 deletions(-) create mode 100644 src/boards/340.c delete mode 100644 src/boards/bmck3036.c diff --git a/src/boards/340.c b/src/boards/340.c new file mode 100644 index 0000000..3444c48 --- /dev/null +++ b/src/boards/340.c @@ -0,0 +1,43 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "asic_latch.h" + +static void sync () { + int prg = Latch_address >>2 &0x20 | Latch_address &0x1F; + if (Latch_address &0x20) { + if (Latch_address &0x01) { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } else + setprg32(0x8000, prg >>1); + } else { + setprg16(0x8000, prg); + setprg16(0xC000, prg | 7); + } + setchr8(0); + setmirror(Latch_address &0x040 || (Latch_address &0x025) == 0x025 || (Latch_address &0x118) == 0x010? MI_H: MI_V); +} + +void Mapper340_Init (CartInfo *info) { + Latch_init(info, sync, 0x8000, 0xFFFF, NULL); + info->Reset = Latch_clear; +} 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/ines.c b/src/ines.c index d704063..ba9338c 100644 --- a/src/ines.c +++ b/src/ines.c @@ -785,7 +785,7 @@ 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( "K-3036", 340, Mapper340_Init ) INES_BOARD( "TJ-03", 341, BMCTJ03_Init ) INES_BOARD( "COOLGIRL", 342, COOLGIRL_Init ) INES_BOARD( "GN-26", 344, BMCGN26_Init ) diff --git a/src/ines.h b/src/ines.h index c90ef0a..1c48ffd 100644 --- a/src/ines.h +++ b/src/ines.h @@ -279,6 +279,7 @@ void Mapper321_Init(CartInfo *); void Mapper326_Init(CartInfo *); void Mapper330_Init(CartInfo *); void Mapper334_Init(CartInfo *); +void Mapper340_Init(CartInfo *); void Mapper351_Init(CartInfo *); void Mapper352_Init(CartInfo *); void Mapper353_Init(CartInfo *); diff --git a/src/unif.c b/src/unif.c index 2332e14..9a91a53 100644 --- a/src/unif.c +++ b/src/unif.c @@ -595,7 +595,7 @@ static BMAPPING bmap[] = { { "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..2caf553 100644 --- a/src/unif.h +++ b/src/unif.h @@ -164,7 +164,7 @@ 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 */ From 2c1ca2c179bbcb18e6e6c1413f0c6d3fdd3aa752 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Thu, 18 Sep 2025 11:05:33 +0200 Subject: [PATCH 06/66] Power on with frame IRQ disabled. This already matches the behavior of some famiclones, increases compatibility with several known titles, while any game that makes use of Frame IRQ explicitly enables it anyway. --- src/sound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); } From 76bcada1bef0fc941b47d3345ec8e57c178e5d70 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Thu, 18 Sep 2025 12:22:21 +0200 Subject: [PATCH 07/66] Add mapper 596; update mappers 268.4 and 268.8 for larger ROM sizes --- src/boards/268.c | 34 ++++++++++++++++++++------ src/boards/596.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 4 files changed, 91 insertions(+), 8 deletions(-) create mode 100644 src/boards/596.c diff --git a/src/boards/268.c b/src/boards/268.c index 02de195..be2895e 100644 --- a/src/boards/268.c +++ b/src/boards/268.c @@ -66,6 +66,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 +87,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 +116,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/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/ines.c b/src/ines.c index ba9338c..f8ef459 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1017,6 +1017,7 @@ 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_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index 1c48ffd..d9f9c62 100644 --- a/src/ines.h +++ b/src/ines.h @@ -486,6 +486,7 @@ void Mapper591_Init(CartInfo *); void Mapper592_Init(CartInfo *); void Mapper594_Init(CartInfo *); void Mapper595_Init(CartInfo *); +void Mapper596_Init(CartInfo *); void FFE_Init(CartInfo *); From a75f70b3ffdb629540bc95d01dbb360311a8ef82 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Thu, 18 Sep 2025 12:52:33 +0200 Subject: [PATCH 08/66] Add mapper 339.4. --- src/boards/bmck3006.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/boards/bmck3006.c b/src/boards/bmck3006.c index 7b5ca30..6ee7fc0 100644 --- a/src/boards/bmck3006.c +++ b/src/boards/bmck3006.c @@ -43,7 +43,8 @@ static void BMCK3006PW(uint32 A, uint8 V) { 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 ==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); From 7e75e786ebe89446069b794f013cdbc73070421a Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 19 Sep 2025 23:39:59 +0200 Subject: [PATCH 09/66] Mapper 339: Simplify submapper 2 and reduce the number of EXPREGS accordingly. --- src/boards/bmck3006.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/boards/bmck3006.c b/src/boards/bmck3006.c index 6ee7fc0..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,8 +41,8 @@ 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 ==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); @@ -55,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); } @@ -80,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"); } From 1e15064ec5ee3ed462593eb77daa203478e1ce45 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 21 Sep 2025 22:02:30 +0200 Subject: [PATCH 10/66] Add mappers 597 and 598. --- src/boards/597.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++ src/boards/598.c | 63 ++++++++++++++++++++++++++++++++++++++++ src/ines.c | 2 ++ src/ines.h | 2 ++ 4 files changed, 142 insertions(+) create mode 100644 src/boards/597.c create mode 100644 src/boards/598.c 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..63c0274 --- /dev/null +++ b/src/boards/598.c @@ -0,0 +1,63 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[4]; + +static void sync () { + int prg = reg[3] <<3 | reg[1] &0x07; + if (reg[3] &0x08) + setprg32(0x8000, prg >>1); + else { + setprg16(0x8000, prg); + setprg16(0xC000, prg |7); + } + setchr4(0x0000, reg[3] <<5 | reg[1] >>3 &0x1F); + setchr4(0x1000, reg[3] <<5 | reg[2] >>3 &0x1F); + setmirror(reg[3] &0x04? MI_H: MI_V); +} + +static DECLFW (writeReg) { + reg[A >>13 &3] = V; + 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 Mapper598_Init (CartInfo *info) { + info->Power = power; + info->Reset = reset; + GameStateRestore = stateRestore; + AddExState(reg, 4, 0, "REGS"); +} diff --git a/src/ines.c b/src/ines.c index f8ef459..a99c4c8 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1018,6 +1018,8 @@ INES_BOARD_BEGIN() 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( "New Star 21-in-1", 598, Mapper598_Init ) INES_BOARD_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index d9f9c62..83f3ce2 100644 --- a/src/ines.h +++ b/src/ines.h @@ -487,6 +487,8 @@ 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 FFE_Init(CartInfo *); From 2b29c778bf330983a717f52ca16029109f96dbd9 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Thu, 25 Sep 2025 12:51:42 +0200 Subject: [PATCH 11/66] Revise mapper 354.0 to support 650-in-1. --- src/boards/354.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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: From 0e365ada5eef32b81cb222f660e44966ce742fee Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 28 Sep 2025 20:59:17 +0200 Subject: [PATCH 12/66] Mapper 320: Add mirroring switch for a cartridge that uses it. --- src/boards/bmc830425C4391t.c | 1 + 1 file changed, 1 insertion(+) 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) { From 76f40218d05385e4f804e2f25adbd71c5f1aba84 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Mon, 29 Sep 2025 23:09:42 +0200 Subject: [PATCH 13/66] Mapper 498: Add 1MiB+1MiB variant. --- src/boards/498.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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(); } From dfdbd645265d1072abd2406e07c63dcfd493dd04 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 30 Sep 2025 20:32:09 +0200 Subject: [PATCH 14/66] Mapper 438: add reset-based Contra variant --- src/boards/438.c | 82 +++++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 35 deletions(-) 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; + } } From 430b59cd9287ac869e7f6cd0f32ed0b7ad25a108 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 3 Oct 2025 12:54:14 +0200 Subject: [PATCH 15/66] Add mapper 447 submapper 1. --- src/boards/447.c | 33 ++++++++++++++------------------- src/ines.c | 2 +- 2 files changed, 15 insertions(+), 20 deletions(-) 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/ines.c b/src/ines.c index a99c4c8..dbc499e 100644 --- a/src/ines.c +++ b/src/ines.c @@ -878,7 +878,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 ) From a2aefa199067c21d7965366b7fb5cc8341c4a869 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 3 Oct 2025 17:55:55 +0200 Subject: [PATCH 16/66] Remove mapper 598, as it is a duplicate of 331. --- src/ines.c | 1 - src/ines.h | 1 - 2 files changed, 2 deletions(-) diff --git a/src/ines.c b/src/ines.c index dbc499e..2fde992 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1019,7 +1019,6 @@ INES_BOARD_BEGIN() INES_BOARD( "4MROM-512", 595, Mapper595_Init ) INES_BOARD( "FC-49", 596, Mapper596_Init ) INES_BOARD( "GN-27", 597, Mapper597_Init ) - INES_BOARD( "New Star 21-in-1", 598, Mapper598_Init ) INES_BOARD_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index 83f3ce2..429b8dc 100644 --- a/src/ines.h +++ b/src/ines.h @@ -488,7 +488,6 @@ void Mapper594_Init(CartInfo *); void Mapper595_Init(CartInfo *); void Mapper596_Init(CartInfo *); void Mapper597_Init(CartInfo *); -void Mapper598_Init(CartInfo *); void FFE_Init(CartInfo *); From dc3b3842f1daac0fde5f45874696e3dbe81980fa Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 3 Oct 2025 18:02:44 +0200 Subject: [PATCH 17/66] Mapper 293: reset to menu --- src/boards/293.c | 6 ++++++ 1 file changed, 6 insertions(+) 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); } From 0d3b44c99cf40e50a420016d8907ba06eecf34bb Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Mon, 20 Oct 2025 21:28:45 +0200 Subject: [PATCH 18/66] Mapper 277: The UNROM game must take its mirroring from the NES header. --- src/boards/277.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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; From f452da1c89377cda67baf72290d4cc245b868759 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sat, 25 Oct 2025 13:47:06 +0200 Subject: [PATCH 19/66] Mapper 280: Don't switch modes when there are only 512 KiB of PRG-ROM. --- src/boards/280.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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(); From 0a4c82155b32d2f552f657514e4ac74f1354ef6b Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sat, 25 Oct 2025 13:49:24 +0200 Subject: [PATCH 20/66] Mapper 227: Correct the behavior of submapper 2. Remove submapper 3, as it's actually just mapper 280 without the reset-based UNROM game spot populated. --- src/boards/addrlatch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c index 040af3e..fd75151 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)); } } } From 65cf86e1482b8fa6753da2885d3d07ea86af4a29 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sat, 25 Oct 2025 13:59:36 +0200 Subject: [PATCH 21/66] Mapper 301: This is a duplicate of 242, so make the UNIF 8127 board run as mapper 242, and reassign iNES mapper #301 to new K-3003. --- src/boards/301.c | 59 ++++++++++++++++++++++++++++++++++ src/boards/8157.c | 81 ----------------------------------------------- src/ines.c | 2 +- src/ines.h | 1 + src/unif.c | 4 +-- 5 files changed, 63 insertions(+), 84 deletions(-) create mode 100644 src/boards/301.c delete mode 100644 src/boards/8157.c 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/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/ines.c b/src/ines.c index 2fde992..c59a7ab 100644 --- a/src/ines.c +++ b/src/ines.c @@ -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 ) diff --git a/src/ines.h b/src/ines.h index 429b8dc..b8f3d6f 100644 --- a/src/ines.h +++ b/src/ines.h @@ -273,6 +273,7 @@ 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 *); diff --git a/src/unif.c b/src/unif.c index 9a91a53..0600839 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 }, From 4070514256875f83edecbedc6d52eac58d87bc60 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 2 Nov 2025 10:46:56 +0100 Subject: [PATCH 22/66] Mapper 191: Rewrite to add multicart functionality; add submapper 1. --- src/boards/191.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++ src/boards/mmc3.c | 15 ---------- 2 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 src/boards/191.c 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/mmc3.c b/src/boards/mmc3.c index 978b57e..356ce56 100644 --- a/src/boards/mmc3.c +++ b/src/boards/mmc3.c @@ -1015,21 +1015,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) { From aabeaf1d03b0218e2e22913fae36149ea7f0e0c1 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 28 Nov 2025 12:08:57 +0100 Subject: [PATCH 23/66] Remove mapper 171, add mapper 1 submappers 7 and 8. --- src/boards/mmc1.c | 21 +++++++++++---------- src/ines.c | 2 +- src/ines.h | 1 - 3 files changed, 12 insertions(+), 12 deletions(-) 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/ines.c b/src/ines.c index c59a7ab..699cda9 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 ) diff --git a/src/ines.h b/src/ines.h index b8f3d6f..78674eb 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 *); From d0c3023e142abacfec8bbc28f07b982596951f27 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 28 Nov 2025 12:25:24 +0100 Subject: [PATCH 24/66] Add mapper 422submapper 4. --- src/boards/126_422_534.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/boards/126_422_534.c b/src/boards/126_422_534.c index 2ae880d..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". */ @@ -81,6 +83,9 @@ 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; From 78b9d810e1b818cbfd9b2c14aab6bef6c3a6b3dc Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sat, 13 Dec 2025 02:28:38 +0100 Subject: [PATCH 25/66] Mapper 268.0/1: Add 64 MiB variant (YH2018A PCB). --- src/boards/268.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/boards/268.c b/src/boards/268.c index be2895e..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; From 0caa46219089fe243e72a2daca5570ae78a30065 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 14 Dec 2025 17:26:03 +0100 Subject: [PATCH 26/66] Added mapper 441 submapper 1. --- src/boards/441.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) 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; From 9a4beeadfada4f95038cfcbd09d17adaed36412e Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Thu, 25 Dec 2025 03:35:55 +0100 Subject: [PATCH 27/66] VRC2/4: added a missing return statement --- src/boards/asic_vrc2and4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boards/asic_vrc2and4.c b/src/boards/asic_vrc2and4.c index 3e0cc22..a0472e7 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 From db5855b9516bb54c4e40434994c221dcea43064f Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 1 Feb 2026 11:25:21 +0100 Subject: [PATCH 28/66] Add mapper 429 submapper 2. --- src/boards/datalatch.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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); } From ae870894cfd31fd3b3e071782bd30231ec373509 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Mon, 2 Feb 2026 14:32:04 +0100 Subject: [PATCH 29/66] Added mapper 432 submapper 4. --- src/boards/432.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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) { From febdbaca0893ceafd2f6b7f6bc2c9457b7be8319 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Wed, 4 Feb 2026 15:10:35 +0100 Subject: [PATCH 30/66] Mapper 242: Use submapper 1 to denote multicart variant that allows write-protecting CHR-RAM in NROM mode. Mappers 227/242: Prevent crashes when accessing PRG-RAM with PRG-RAM being present. --- src/boards/addrlatch.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c index fd75151..69eb1a1 100644 --- a/src/boards/addrlatch.c +++ b/src/boards/addrlatch.c @@ -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; From d74d4c18b64f3c2a35f1f40acc0d7280de47b816 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Wed, 4 Feb 2026 16:03:00 +0100 Subject: [PATCH 31/66] Mapper 340: Add submapper 1. Add CHR-RAM write protection in NROM mode, needed for B-Wings. --- src/boards/340.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/boards/340.c b/src/boards/340.c index 3444c48..4ca2787 100644 --- a/src/boards/340.c +++ b/src/boards/340.c @@ -21,23 +21,31 @@ #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) { + if (Latch_address &0x20) { /* NROM mode */ if (Latch_address &0x01) { setprg16(0x8000, prg); setprg16(0xC000, prg); } else setprg32(0x8000, prg >>1); - } else { + 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); - setmirror(Latch_address &0x040 || (Latch_address &0x025) == 0x025 || (Latch_address &0x118) == 0x010? MI_H: MI_V); } void Mapper340_Init (CartInfo *info) { + submapper = info->submapper; Latch_init(info, sync, 0x8000, 0xFFFF, NULL); info->Reset = Latch_clear; } From ed6b26bb52cd8f480f6b71cb0fab295090fa4e05 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 6 Feb 2026 14:56:06 +0100 Subject: [PATCH 32/66] Add mapper 598. --- src/boards/598.c | 25 ++++++++++++------------- src/ines.c | 1 + src/ines.h | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/boards/598.c b/src/boards/598.c index 63c0274..c109155 100644 --- a/src/boards/598.c +++ b/src/boards/598.c @@ -20,28 +20,27 @@ #include "mapinc.h" -static uint8 reg[4]; +static uint8 reg[2]; static void sync () { - int prg = reg[3] <<3 | reg[1] &0x07; - if (reg[3] &0x08) - setprg32(0x8000, prg >>1); - else { - setprg16(0x8000, prg); - setprg16(0xC000, prg |7); + 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; } - setchr4(0x0000, reg[3] <<5 | reg[1] >>3 &0x1F); - setchr4(0x1000, reg[3] <<5 | reg[2] >>3 &0x1F); - setmirror(reg[3] &0x04? MI_H: MI_V); } static DECLFW (writeReg) { - reg[A >>13 &3] = V; + reg[A >>14 &1] = V; sync(); } static void reset () { - reg[0] = reg[1] = reg[2] = reg[3] = 0; + reg[0] = reg[1] = 0; sync(); } @@ -59,5 +58,5 @@ void Mapper598_Init (CartInfo *info) { info->Power = power; info->Reset = reset; GameStateRestore = stateRestore; - AddExState(reg, 4, 0, "REGS"); + AddExState(reg, 2, 0, "REGS"); } diff --git a/src/ines.c b/src/ines.c index 699cda9..1a9b070 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1019,6 +1019,7 @@ INES_BOARD_BEGIN() 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_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index 78674eb..b5adf55 100644 --- a/src/ines.h +++ b/src/ines.h @@ -488,7 +488,7 @@ void Mapper594_Init(CartInfo *); void Mapper595_Init(CartInfo *); void Mapper596_Init(CartInfo *); void Mapper597_Init(CartInfo *); - +void Mapper598_Init(CartInfo *); void FFE_Init(CartInfo *); #endif From d171ad39930f4730bfb160b4f24a4875708e4c3f Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 6 Feb 2026 16:01:38 +0100 Subject: [PATCH 33/66] Add mapper 599. --- src/boards/599.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 82 insertions(+) create mode 100644 src/boards/599.c 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/ines.c b/src/ines.c index 1a9b070..ba47aaf 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1020,6 +1020,7 @@ INES_BOARD_BEGIN() 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_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index b5adf55..93cd0d8 100644 --- a/src/ines.h +++ b/src/ines.h @@ -489,6 +489,7 @@ void Mapper595_Init(CartInfo *); void Mapper596_Init(CartInfo *); void Mapper597_Init(CartInfo *); void Mapper598_Init(CartInfo *); +void Mapper599_Init(CartInfo *); void FFE_Init(CartInfo *); #endif From 02f8077408024862a61c3b1c862e2e818b675759 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 8 Feb 2026 11:42:37 +0100 Subject: [PATCH 34/66] Add mapper 571 submapper 1. --- src/boards/571.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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; From 602236f48289ad1ebd0284efe9367f72ee90bb1f Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 8 Feb 2026 11:53:02 +0100 Subject: [PATCH 35/66] Add mapper 603. --- src/boards/603.c | 33 +++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 35 insertions(+) create mode 100644 src/boards/603.c 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/ines.c b/src/ines.c index ba47aaf..c4807ab 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1021,6 +1021,7 @@ INES_BOARD_BEGIN() 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_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index 93cd0d8..bbd73f7 100644 --- a/src/ines.h +++ b/src/ines.h @@ -490,6 +490,7 @@ void Mapper596_Init(CartInfo *); void Mapper597_Init(CartInfo *); void Mapper598_Init(CartInfo *); void Mapper599_Init(CartInfo *); +void Mapper603_Init(CartInfo *); void FFE_Init(CartInfo *); #endif From 45a440bb1ae669394eff0f7df9209a7ff6d5cd02 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 8 Feb 2026 12:01:20 +0100 Subject: [PATCH 36/66] Added mapper 605. --- src/boards/605.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 73 insertions(+) create mode 100644 src/boards/605.c 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/ines.c b/src/ines.c index c4807ab..9c9d21d 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1022,6 +1022,7 @@ INES_BOARD_BEGIN() 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_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index bbd73f7..8234dc8 100644 --- a/src/ines.h +++ b/src/ines.h @@ -491,6 +491,7 @@ void Mapper597_Init(CartInfo *); void Mapper598_Init(CartInfo *); void Mapper599_Init(CartInfo *); void Mapper603_Init(CartInfo *); +void Mapper605_Init(CartInfo *); void FFE_Init(CartInfo *); #endif From caafd50a96be5d1da2bdbb31c1c1a09a98bf09f3 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 8 Feb 2026 12:09:43 +0100 Subject: [PATCH 37/66] Added mapper 606. --- src/boards/606.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 63 insertions(+) create mode 100644 src/boards/606.c 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/ines.c b/src/ines.c index 9c9d21d..765ad71 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1023,6 +1023,7 @@ INES_BOARD_BEGIN() 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_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index 8234dc8..8fc9f6d 100644 --- a/src/ines.h +++ b/src/ines.h @@ -492,6 +492,7 @@ void Mapper598_Init(CartInfo *); void Mapper599_Init(CartInfo *); void Mapper603_Init(CartInfo *); void Mapper605_Init(CartInfo *); +void Mapper606_Init(CartInfo *); void FFE_Init(CartInfo *); #endif From c0025a327b4ac7bc38f565cc3ce9af2e02a366bf Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 8 Feb 2026 12:17:53 +0100 Subject: [PATCH 38/66] Added mapper 607. --- src/boards/607.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 64 insertions(+) create mode 100644 src/boards/607.c diff --git a/src/boards/607.c b/src/boards/607.c new file mode 100644 index 0000000..f56f705 --- /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 &0x08 | Latch_data &0x07); + setprg16(0xC000, reg <<3 &0x08 | 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/ines.c b/src/ines.c index 765ad71..eb384e8 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1024,6 +1024,7 @@ INES_BOARD_BEGIN() 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_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index 8fc9f6d..e902f0f 100644 --- a/src/ines.h +++ b/src/ines.h @@ -493,6 +493,7 @@ void Mapper599_Init(CartInfo *); void Mapper603_Init(CartInfo *); void Mapper605_Init(CartInfo *); void Mapper606_Init(CartInfo *); +void Mapper607_Init(CartInfo *); void FFE_Init(CartInfo *); #endif From 912d524c3543ff22421a5616e6e189c15431c1ce Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 8 Feb 2026 12:29:38 +0100 Subject: [PATCH 39/66] Added mapper 608. --- src/boards/608.c | 38 ++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 40 insertions(+) create mode 100644 src/boards/608.c 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/ines.c b/src/ines.c index eb384e8..c352fe5 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1025,6 +1025,7 @@ INES_BOARD_BEGIN() 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_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index e902f0f..a09cdb2 100644 --- a/src/ines.h +++ b/src/ines.h @@ -494,6 +494,7 @@ void Mapper603_Init(CartInfo *); void Mapper605_Init(CartInfo *); void Mapper606_Init(CartInfo *); void Mapper607_Init(CartInfo *); +void Mapper608_Init(CartInfo *); void FFE_Init(CartInfo *); #endif From 1d876ffec444b04c81681e1f8f3417cc262a2208 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 8 Feb 2026 12:34:44 +0100 Subject: [PATCH 40/66] Added mapper 609. --- src/boards/609.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 66 insertions(+) create mode 100644 src/boards/609.c 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/ines.c b/src/ines.c index c352fe5..b22f501 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1026,6 +1026,7 @@ INES_BOARD_BEGIN() 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_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index a09cdb2..44067a4 100644 --- a/src/ines.h +++ b/src/ines.h @@ -495,6 +495,7 @@ void Mapper605_Init(CartInfo *); void Mapper606_Init(CartInfo *); void Mapper607_Init(CartInfo *); void Mapper608_Init(CartInfo *); +void Mapper609_Init(CartInfo *); void FFE_Init(CartInfo *); #endif From 84126a581c3176993ec91599c08f6438e3abedd3 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 8 Feb 2026 12:40:47 +0100 Subject: [PATCH 41/66] Added mapper 610. --- src/boards/610.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 59 insertions(+) create mode 100644 src/boards/610.c 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/ines.c b/src/ines.c index b22f501..932c7e2 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1027,6 +1027,7 @@ INES_BOARD_BEGIN() 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_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index 44067a4..aa070f3 100644 --- a/src/ines.h +++ b/src/ines.h @@ -496,6 +496,7 @@ void Mapper606_Init(CartInfo *); void Mapper607_Init(CartInfo *); void Mapper608_Init(CartInfo *); void Mapper609_Init(CartInfo *); +void Mapper610_Init(CartInfo *); void FFE_Init(CartInfo *); #endif From 306afa9778fcf62424e516fde57742d862ab2408 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 8 Feb 2026 12:43:40 +0100 Subject: [PATCH 42/66] Added mapper 611. --- src/boards/611.c | 37 +++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 39 insertions(+) create mode 100644 src/boards/611.c 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/ines.c b/src/ines.c index 932c7e2..fa0127a 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1028,6 +1028,7 @@ INES_BOARD_BEGIN() 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_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index aa070f3..c8204bb 100644 --- a/src/ines.h +++ b/src/ines.h @@ -497,6 +497,7 @@ void Mapper607_Init(CartInfo *); void Mapper608_Init(CartInfo *); void Mapper609_Init(CartInfo *); void Mapper610_Init(CartInfo *); +void Mapper611_Init(CartInfo *); void FFE_Init(CartInfo *); #endif From 214ca7072704e046825340384490d7aa67844e18 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 10 Mar 2026 15:55:01 +0100 Subject: [PATCH 43/66] MMC3: Make the Kick Master hack work on multicarts as well. --- src/boards/asic_mmc3.c | 14 ++++++++++++++ src/boards/asic_mmc3.h | 1 + src/boards/mmc3.c | 11 +++++++++++ 3 files changed, 26 insertions(+) diff --git a/src/boards/asic_mmc3.c b/src/boards/asic_mmc3.c index 330ba74..717ac0e 100644 --- a/src/boards/asic_mmc3.c +++ b/src/boards/asic_mmc3.c @@ -83,6 +83,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 +110,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/mmc3.c b/src/boards/mmc3.c index 356ce56..78a179d 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) { From f9ab64ae0d966eb8c47f12bfd08e082fbe816abe Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 10 Mar 2026 16:38:09 +0100 Subject: [PATCH 44/66] ASIC MMC3: guard against possible bounds violation --- src/boards/asic_mmc3.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/boards/asic_mmc3.c b/src/boards/asic_mmc3.c index 717ac0e..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; } From 40b4c4a70d3dbff2225c6377f6c2ba8d2ed2a8da Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 10 Mar 2026 17:30:56 +0100 Subject: [PATCH 45/66] Add Mapper 333 submapper 1. --- src/boards/8in1.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/boards/8in1.c b/src/boards/8in1.c index 4f9db77..68b8af1 100644 --- a/src/boards/8in1.c +++ b/src/boards/8in1.c @@ -27,12 +27,14 @@ #include "mapinc.h" #include "mmc3.h" +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; From 585b66ca89a02861d76f8e577a04fc34bcc5fc32 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 10 Mar 2026 17:35:20 +0100 Subject: [PATCH 46/66] Add Mapper 616. --- src/boards/616.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 61 insertions(+) create mode 100644 src/boards/616.c 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/ines.c b/src/ines.c index fa0127a..596c200 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1029,6 +1029,7 @@ INES_BOARD_BEGIN() 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-3044", 616, Mapper616_Init ) INES_BOARD_END() static uint32 iNES_get_mapper_id(void) diff --git a/src/ines.h b/src/ines.h index c8204bb..1e0570d 100644 --- a/src/ines.h +++ b/src/ines.h @@ -498,6 +498,7 @@ void Mapper608_Init(CartInfo *); void Mapper609_Init(CartInfo *); void Mapper610_Init(CartInfo *); void Mapper611_Init(CartInfo *); +void Mapper616_Init(CartInfo *); void FFE_Init(CartInfo *); #endif From 726d7157f859c118ecd8d08b0b387d955225d999 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 10 Mar 2026 17:46:33 +0100 Subject: [PATCH 47/66] Add mapper 613. --- src/boards/613.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 72 insertions(+) create mode 100644 src/boards/613.c 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/ines.c b/src/ines.c index 596c200..8fe523c 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1029,6 +1029,7 @@ INES_BOARD_BEGIN() 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( "S5668 3366", 613, Mapper613_Init ) INES_BOARD( "K-3044", 616, Mapper616_Init ) INES_BOARD_END() diff --git a/src/ines.h b/src/ines.h index 1e0570d..e22a48f 100644 --- a/src/ines.h +++ b/src/ines.h @@ -498,6 +498,7 @@ void Mapper608_Init(CartInfo *); void Mapper609_Init(CartInfo *); void Mapper610_Init(CartInfo *); void Mapper611_Init(CartInfo *); +void Mapper613_Init(CartInfo *); void Mapper616_Init(CartInfo *); void FFE_Init(CartInfo *); From ba9f10a805134053ac89c3c7df12384bdb5d206c Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 10 Mar 2026 17:49:36 +0100 Subject: [PATCH 48/66] Mapper 446.4: Add more fusemaps. --- src/boards/446.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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; From 7143a2730a205b06a91881672db6261715947576 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 10 Mar 2026 17:54:22 +0100 Subject: [PATCH 49/66] Add mapper 592 submapper 1. Add 'static' keybword to mapper 333. --- src/boards/592.c | 11 +++++++++-- src/boards/8in1.c | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) 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/8in1.c b/src/boards/8in1.c index 68b8af1..6498caf 100644 --- a/src/boards/8in1.c +++ b/src/boards/8in1.c @@ -27,7 +27,7 @@ #include "mapinc.h" #include "mmc3.h" -uint8 submapper; +static uint8 submapper; static void BMC8IN1CW(uint32 A, uint8 V) { setchr1(A, ((EXPREGS[0] & 0xC) << 5) | (V & 0x7F)); From eb6df7680aceb8212d9b4f3e38574c92800f0a62 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 10 Mar 2026 19:25:49 +0100 Subject: [PATCH 50/66] Add mapper 612. --- src/boards/612.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 49 insertions(+) create mode 100644 src/boards/612.c 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/ines.c b/src/ines.c index 8fe523c..a8ca546 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1029,6 +1029,7 @@ INES_BOARD_BEGIN() 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( "K-3044", 616, Mapper616_Init ) INES_BOARD_END() diff --git a/src/ines.h b/src/ines.h index e22a48f..ba4afbb 100644 --- a/src/ines.h +++ b/src/ines.h @@ -498,6 +498,7 @@ 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 Mapper616_Init(CartInfo *); void FFE_Init(CartInfo *); From 58007df8bcdb41f1be96097396e73fab97f19eed Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 10 Mar 2026 19:31:40 +0100 Subject: [PATCH 51/66] Add mapper 614. --- src/boards/614.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 70 insertions(+) create mode 100644 src/boards/614.c 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/ines.c b/src/ines.c index a8ca546..beeb6e0 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1031,6 +1031,7 @@ INES_BOARD_BEGIN() 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( "K-3044", 616, Mapper616_Init ) INES_BOARD_END() diff --git a/src/ines.h b/src/ines.h index ba4afbb..9b7fafa 100644 --- a/src/ines.h +++ b/src/ines.h @@ -500,6 +500,7 @@ void Mapper610_Init(CartInfo *); void Mapper611_Init(CartInfo *); void Mapper612_Init(CartInfo *); void Mapper613_Init(CartInfo *); +void Mapper614_Init(CartInfo *); void Mapper616_Init(CartInfo *); void FFE_Init(CartInfo *); From a5df7359bc861131853259175373555a6feb1db3 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 10 Mar 2026 19:37:22 +0100 Subject: [PATCH 52/66] Add mapper 615. --- src/boards/615.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 72 insertions(+) create mode 100644 src/boards/615.c 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/ines.c b/src/ines.c index beeb6e0..dd417a0 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1032,6 +1032,7 @@ INES_BOARD_BEGIN() 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_END() diff --git a/src/ines.h b/src/ines.h index 9b7fafa..d1fe952 100644 --- a/src/ines.h +++ b/src/ines.h @@ -501,6 +501,7 @@ 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 FFE_Init(CartInfo *); From 1d9c0d739a6b47980f0bfa5427ec333344e5ce36 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 10 Mar 2026 19:40:58 +0100 Subject: [PATCH 53/66] Mapper 437: Use value instead of address. --- src/boards/437.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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(); } From d180d7c7ad414bd6f073388efc141aa3d273adcd Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 10 Mar 2026 19:44:12 +0100 Subject: [PATCH 54/66] Mapper 439: Add solder pad. --- src/boards/439.c | 10 ++++++++++ 1 file changed, 10 insertions(+) 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"); } From b60fc16d152c62fadf8475238952a565156bc95f Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 13 Mar 2026 10:41:02 +0100 Subject: [PATCH 55/66] Add mapper 49.1, resembling the UNIF MAPR BMC-STREETFIGTER-GAME4IN1. --- src/boards/mmc3.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/boards/mmc3.c b/src/boards/mmc3.c index 78a179d..4b2aa4a 100644 --- a/src/boards/mmc3.c +++ b/src/boards/mmc3.c @@ -650,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; @@ -669,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); @@ -690,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; @@ -700,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; From bf2a9ad3d5fca5997047925bd8d28c350c708c6f Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Fri, 13 Mar 2026 10:41:23 +0100 Subject: [PATCH 56/66] Add mapper 255 as a variant, rather than a duplicate, of mapper 225. --- src/boards/225.c | 12 +++++++++--- src/ines.c | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) 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/ines.c b/src/ines.c index dd417a0..07505f6 100644 --- a/src/ines.c +++ b/src/ines.c @@ -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 */ From bcd85e6cf3e686c165b1cab107344dceaeea9d55 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 31 Mar 2026 23:06:05 +0200 Subject: [PATCH 57/66] Mapper 137: Correct mirroring for The Great Wall. --- src/boards/sachen.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) 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"); From ee613aec52d0ef8e371a12157a42bc1b26254d9f Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 31 Mar 2026 23:08:26 +0200 Subject: [PATCH 58/66] Mapper 607: Correct for multiple UNROM games. --- src/boards/607.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/boards/607.c b/src/boards/607.c index f56f705..c623e51 100644 --- a/src/boards/607.c +++ b/src/boards/607.c @@ -29,8 +29,8 @@ static DECLFR (readOB) { static void sync () { if (reg &0x10) { /* UNROM mode */ - setprg16(0x8000, reg <<3 &0x08 | Latch_data &0x07); - setprg16(0xC000, reg <<3 &0x08 | 0x07); + 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. */ From 93300cbf077ef17a0160b1736be044f2a175eb28 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 31 Mar 2026 23:20:10 +0200 Subject: [PATCH 59/66] Add mapper 618. --- src/boards/618.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 70 insertions(+) create mode 100644 src/boards/618.c 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/ines.c b/src/ines.c index 07505f6..29e4282 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1034,6 +1034,7 @@ INES_BOARD_BEGIN() INES_BOARD( "New Star 9135", 614, Mapper614_Init ) INES_BOARD( "LB12in1", 615, Mapper615_Init ) INES_BOARD( "K-3044", 616, Mapper616_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 d1fe952..c5f02d9 100644 --- a/src/ines.h +++ b/src/ines.h @@ -503,6 +503,7 @@ void Mapper613_Init(CartInfo *); void Mapper614_Init(CartInfo *); void Mapper615_Init(CartInfo *); void Mapper616_Init(CartInfo *); +void Mapper618_Init(CartInfo *); void FFE_Init(CartInfo *); #endif From d20e1cf637ebc9ed8c2ec28deb3228d4ecead34f Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Tue, 31 Mar 2026 23:27:40 +0200 Subject: [PATCH 60/66] Add mapper 617. --- src/boards/617.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 62 insertions(+) create mode 100644 src/boards/617.c 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/ines.c b/src/ines.c index 29e4282..69f907a 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1034,6 +1034,7 @@ INES_BOARD_BEGIN() 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() diff --git a/src/ines.h b/src/ines.h index c5f02d9..a9b1215 100644 --- a/src/ines.h +++ b/src/ines.h @@ -503,6 +503,7 @@ 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 *); From e81b5e0370b307553ff200f87cfd7034192c2bce Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Wed, 1 Apr 2026 00:26:20 +0200 Subject: [PATCH 61/66] Add mapper 487 submapper 1. --- src/boards/487.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) 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); From ba25f9107b0dd1c7e180ad0a42a125c01741057b Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 5 Apr 2026 02:24:19 +0200 Subject: [PATCH 62/66] Mappers 83/264: Added submapper 3, rewrote to incorporate new findings --- src/boards/83_264.c | 240 +++++++++++++++++++++++++++++++++++ src/boards/asic_vrc2and4.c | 1 + src/boards/yoko.c | 248 ------------------------------------- src/ines.c | 2 +- src/ines.h | 1 + src/unif.c | 2 +- src/unif.h | 1 - 7 files changed, 244 insertions(+), 251 deletions(-) create mode 100644 src/boards/83_264.c delete mode 100644 src/boards/yoko.c diff --git a/src/boards/83_264.c b/src/boards/83_264.c new file mode 100644 index 0000000..00d05ad --- /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 (int 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 (int i = 0; i < 16; i++) reg[i] = 0; + for (int 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/asic_vrc2and4.c b/src/boards/asic_vrc2and4.c index a0472e7..e611074 100644 --- a/src/boards/asic_vrc2and4.c +++ b/src/boards/asic_vrc2and4.c @@ -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/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/ines.c b/src/ines.c index 69f907a..bec4026 100644 --- a/src/ines.c +++ b/src/ines.c @@ -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 ) diff --git a/src/ines.h b/src/ines.h index a9b1215..d1579df 100644 --- a/src/ines.h +++ b/src/ines.h @@ -250,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 *); diff --git a/src/unif.c b/src/unif.c index 0600839..d60ba50 100644 --- a/src/unif.c +++ b/src/unif.c @@ -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 }, diff --git a/src/unif.h b/src/unif.h index 2caf553..558d5cc 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); From 6657dc502ffa4810da7827f178321a6be5d4e032 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 5 Apr 2026 02:30:30 +0200 Subject: [PATCH 63/66] Mappers 344: Add solder pad --- src/boards/gn26.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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"); } From 13f16f05ca721bc38cd43ee202bcf6ee5be9d61d Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 5 Apr 2026 02:40:15 +0200 Subject: [PATCH 64/66] Mappers 261: Reset to menu from Galaxian --- src/boards/addrlatch.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c index 69eb1a1..bb3fe6c 100644 --- a/src/boards/addrlatch.c +++ b/src/boards/addrlatch.c @@ -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 ------------------------*/ From 37e23ac075704fe845ef54ef7f58385d44157f5a Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 5 Apr 2026 02:46:56 +0200 Subject: [PATCH 65/66] Cleanup --- src/boards/83_264.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/boards/83_264.c b/src/boards/83_264.c index 00d05ad..7601869 100644 --- a/src/boards/83_264.c +++ b/src/boards/83_264.c @@ -191,7 +191,7 @@ void scanlineCounter() { static void reset () { int i; - for (int i = 0; i < 16; i++) reg[i] = 0; + for (i = 0; i < 16; i++) reg[i] = 0; pad++; X6502_IRQEnd(FCEU_IQEXT); sync(); @@ -205,8 +205,8 @@ static void power () { SetWriteHandler(0x8000, 0xFFFF, writeReg); MapIRQHook = cycleCounter; GameHBIRQHook = scanlineCounter; - for (int i = 0; i < 16; i++) reg[i] = 0; - for (int i = 4; i < 4; i++) scratch[i] = 0; + for (i = 0; i < 16; i++) reg[i] = 0; + for (i = 4; i < 4; i++) scratch[i] = 0; pad = 0; sync(); } From 147eb59b6bc4c0fe81a7a1225aa7cc1a10ee50a4 Mon Sep 17 00:00:00 2001 From: NewRisingSun <8vytz1+dhp372pv94ebg@sharklasers.com> Date: Sun, 5 Apr 2026 11:05:29 +0200 Subject: [PATCH 66/66] Add mappers 341.1 and 343. --- src/boards/341.c | 40 +++++++++++++++++++++++++++++++ src/boards/343.c | 53 ++++++++++++++++++++++++++++++++++++++++++ src/boards/addrlatch.c | 17 -------------- src/ines.c | 3 ++- src/ines.h | 2 ++ src/unif.c | 2 +- src/unif.h | 1 - 7 files changed, 98 insertions(+), 20 deletions(-) create mode 100644 src/boards/341.c create mode 100644 src/boards/343.c 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/addrlatch.c b/src/boards/addrlatch.c index bb3fe6c..fe9b9fd 100644 --- a/src/boards/addrlatch.c +++ b/src/boards/addrlatch.c @@ -696,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/ines.c b/src/ines.c index bec4026..212b6c6 100644 --- a/src/ines.c +++ b/src/ines.c @@ -786,8 +786,9 @@ INES_BOARD_BEGIN() INES_BOARD( "SA005-A", 338, BMCSA005A_Init ) INES_BOARD( "K-3006", 339, BMCK3006_Init ) INES_BOARD( "K-3036", 340, Mapper340_Init ) - INES_BOARD( "TJ-03", 341, BMCTJ03_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 ) diff --git a/src/ines.h b/src/ines.h index d1579df..ed9e299 100644 --- a/src/ines.h +++ b/src/ines.h @@ -281,6 +281,8 @@ 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 *); diff --git a/src/unif.c b/src/unif.c index d60ba50..4d47250 100644 --- a/src/unif.c +++ b/src/unif.c @@ -590,7 +590,7 @@ 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 }, diff --git a/src/unif.h b/src/unif.h index 558d5cc..6c96479 100644 --- a/src/unif.h +++ b/src/unif.h @@ -158,7 +158,6 @@ 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 */