From 005eb7bdc31345f05977d2e85e10a5e1ad54c806 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Fri, 24 May 2019 06:59:26 +0800 Subject: [PATCH 1/3] Implement mappers 28, 29, 31, 56, 63, 255, BMC-60311C, BMC-WS, BMC-HPxx - Added a few mappers to the list. Tested with roms from goodnes set and some demos - Fix IRQ for Kaiser7032/202 - Issue noticeable with SMB2/3's status status bar --- src/boards/255.c | 79 +++++++++++++ src/boards/28.c | 187 ++++++++++++++++++++++++++++++ src/boards/31.c | 66 +++++++++++ src/boards/{ks7016.c => KS7016.c} | 0 src/boards/KS7032.c | 119 +++++++++++++++---- src/boards/addrlatch.c | 31 +++++ src/boards/bmc60311c.c | 110 ++++++++++++++++++ src/boards/datalatch.c | 16 +++ src/boards/hp10xx_hp20xx.c | 171 +++++++++++++++++++++++++++ src/boards/super40in1.c | 74 ++++++++++++ src/ines-correct.h | 1 - src/ines.c | 40 ++++--- src/ines.h | 6 +- src/unif.c | 5 + src/unif.h | 6 + 15 files changed, 872 insertions(+), 39 deletions(-) create mode 100644 src/boards/255.c create mode 100644 src/boards/28.c create mode 100644 src/boards/31.c rename src/boards/{ks7016.c => KS7016.c} (100%) create mode 100644 src/boards/bmc60311c.c create mode 100644 src/boards/hp10xx_hp20xx.c create mode 100644 src/boards/super40in1.c diff --git a/src/boards/255.c b/src/boards/255.c new file mode 100644 index 0000000..fc7f28c --- /dev/null +++ b/src/boards/255.c @@ -0,0 +1,79 @@ +/* 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 + */ + +/* added 2019-5-23 + * Mapper 255 + * https://wiki.nesdev.com/w/index.php/INES_Mapper_225 + * 115-in-1 [p1][!] CRC32 0xb39d30b4 + * Seems to handle up to last game in the multicarts than m225 but causes + * graphics garbage past it, else games works fine */ + +#include "mapinc.h" + +static uint8 preg, creg, mode, mirr; + +static SFORMAT StateRegs[] = +{ + { &preg, 1, "PRG0" }, + { &creg, 1, "CHR0" }, + { &mode, 1, "MODE" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setprg16(0x8000, preg & ~mode); + setprg16(0xC000, preg | mode); + setchr8(creg); + setmirror(mirr ^ 1); +} + +static DECLFW(M255Write) { + uint32 bank = (A >> 8 & 0x40); + preg = bank | ((A >> 6) & 0x3F); + creg = bank | (A & 0x3F); + mirr = (A >> 13) & 1; + mode = ((~A) >> 12 & 1); + Sync(); +} + +static void M255Power(void) { + preg = 0; + mode = 1; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M255Write); +} + +static void M255Reset(void) { + preg = 0; + mode = 1; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper255_Init(CartInfo *info) { + info->Reset = M255Reset; + info->Power = M255Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/28.c b/src/boards/28.c new file mode 100644 index 0000000..2cb95f0 --- /dev/null +++ b/src/boards/28.c @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2012-2017 FCEUX 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. + * + */ + +/* added 2019-5-23 + * Mapper 28 - Action 53 + * http://wiki.nesdev.com/w/index.php/INES_Mapper_028 */ + +#include "mapinc.h" + +static uint8 prg_mask_16k; +static uint8 reg, chr, prg, mode, outer; + +static SFORMAT StateRegs[] = { + {®, 1, "REG"}, + {&chr, 1, "CHR"}, + {&prg, 1, "PRG"}, + {&mode, 1, "MODE"}, + {&outer, 1, "OUTR"}, + {0} +}; + +void SyncMirror() { + switch (mode & 3) { + case 0: setmirror(MI_0); break; + case 1: setmirror(MI_1); break; + case 2: setmirror(MI_V); break; + case 3: setmirror(MI_H); break; + } +} + +void Mirror(uint8 value) +{ + if ((mode & 2) == 0) { + mode &= 0xfe; + mode |= value >> 4 & 1; + } + SyncMirror(); +} + + +static void Sync() { + uint8 prglo; + uint8 prghi; + + uint8 outb = outer << 1; + + /* this can probably be rolled up, but i have no motivation to do so + * until it's been tested */ + switch (mode & 0x3c) { + /* 32K modes */ + case 0x00: + case 0x04: + prglo = outb; + prghi = outb | 1; + break; + case 0x10: + case 0x14: + prglo = outb & ~2 | prg << 1 & 2; + prghi = outb & ~2 | prg << 1 & 2 | 1; + break; + case 0x20: + case 0x24: + prglo = outb & ~6 | prg << 1 & 6; + prghi = outb & ~6 | prg << 1 & 6 | 1; + break; + case 0x30: + case 0x34: + prglo = outb & ~14 | prg << 1 & 14; + prghi = outb & ~14 | prg << 1 & 14 | 1; + break; + /* bottom fixed modes */ + case 0x08: + prglo = outb; + prghi = outb | prg & 1; + break; + case 0x18: + prglo = outb; + prghi = outb & ~2 | prg & 3; + break; + case 0x28: + prglo = outb; + prghi = outb & ~6 | prg & 7; + break; + case 0x38: + prglo = outb; + prghi = outb & ~14 | prg & 15; + break; + /* top fixed modes */ + case 0x0c: + prglo = outb | prg & 1; + prghi = outb | 1; + break; + case 0x1c: + prglo = outb & ~2 | prg & 3; + prghi = outb | 1; + break; + case 0x2c: + prglo = outb & ~6 | prg & 7; + prghi = outb | 1; + break; + case 0x3c: + prglo = outb & ~14 | prg & 15; + prghi = outb | 1; + break; + } + + prglo &= prg_mask_16k; + prghi &= prg_mask_16k; + + setprg16(0x8000, prglo); + setprg16(0xC000, prghi); + setchr8(chr); +} + +static DECLFW(WriteEXP) { + reg = V & 0x81; +} + +static DECLFW(WritePRG) { + switch (reg) { + case 0x00: + chr = V & 3; + Mirror(V); + Sync(); + break; + case 0x01: + prg = V & 15; + Mirror(V); + Sync(); + break; + case 0x80: + mode = V & 63; + SyncMirror(); + Sync(); + break; + case 0x81: + outer = V & 63; + Sync(); + break; + } +} + +static void M28Power(void) { + outer = 63; + prg = 15; + Sync(); + prg_mask_16k = PRGsize[0] - 1; + SetWriteHandler(0x5000,0x5FFF,WriteEXP); + SetWriteHandler(0x8000,0xFFFF,WritePRG); + SetReadHandler(0x8000,0xFFFF,CartBR); + SetReadHandler(0x6000,0x7FFF,CartBR); + SetWriteHandler(0x6000,0x7FFF,CartBW); +} + +static void M28Reset(void) { + outer = 63; + prg = 15; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper28_Init(CartInfo* info) { + info->Power=M28Power; + info->Reset=M28Reset; + GameStateRestore=StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/31.c b/src/boards/31.c new file mode 100644 index 0000000..17777ab --- /dev/null +++ b/src/boards/31.c @@ -0,0 +1,66 @@ +/* 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 + */ + +/* added 2019-5-23 + * Mapper 31 - custom mapper by infiniteneslives + * https://wiki.nesdev.com/w/index.php/INES_Mapper_031 */ + +#include "mapinc.h" + +static uint8 preg[8]; + +static SFORMAT StateRegs[] = +{ + { preg, 8, "PREG" }, + { 0 } +}; + +static void Sync(void) { + setprg4(0x8000, preg[0]); + setprg4(0x9000, preg[1]); + setprg4(0xA000, preg[2]); + setprg4(0xB000, preg[3]); + setprg4(0xC000, preg[4]); + setprg4(0xD000, preg[5]); + setprg4(0xE000, preg[6]); + setprg4(0xF000, preg[7]); + setchr8(0); +} + +static DECLFW(M31Write) { + preg[A & 7] = V; + Sync(); +} + +static void M31Power(void) { + preg[7] = ~0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x5000, 0x5FFF, M31Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper31_Init(CartInfo *info) { + info->Power = M31Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/ks7016.c b/src/boards/KS7016.c similarity index 100% rename from src/boards/ks7016.c rename to src/boards/KS7016.c diff --git a/src/boards/KS7032.c b/src/boards/KS7032.c index 7958a0c..5a5bd53 100644 --- a/src/boards/KS7032.c +++ b/src/boards/KS7032.c @@ -2,6 +2,7 @@ * * Copyright notice for this file: * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2019 Libretro Team (IRQ Update) * * 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 @@ -21,43 +22,99 @@ * */ +/* added 2019-5-23 + * - Mapper 56 - UNL KS202 + * FDS Conversion: Super Mario Bros. 3 (Pirate, Alt) + * similar to M142 but use WRAM instead? $D000 additional IRQ trigger + * - fix IRQ counter, noticeable in status bars of both SMB2J(KS7032) and SMB3J(KS202) + */ + #include "mapinc.h" -static uint8 reg[8], cmd, IRQa = 0, isirqused = 0; -static int32 IRQCount; +static uint8 reg[8], creg[8], mirr, cmd, IRQa = 0, isirqused = 0; +static int32 IRQCount, IRQLatch; +static uint8 KS7032; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; -static SFORMAT StateRegs[] = +static SFORMAT StateRegsKS7032[] = { { &cmd, 1, "CMD" }, { reg, 8, "REGS" }, { &IRQa, 1, "IRQA" }, - { &IRQCount, 4, "IRQC" }, + { &IRQCount, 4 | FCEUSTATE_RLSB, "IRQC" }, + { 0 } +}; + +static SFORMAT StateRegsKS202[] = +{ + { creg, 8, "CREG" }, + { &mirr, 1, "MIRR" }, { 0 } }; static void Sync(void) { - setprg8(0x6000, reg[4]); - setprg8(0x8000, reg[1]); - setprg8(0xA000, reg[2]); - setprg8(0xC000, reg[3]); + setprg8(0x8000, reg[0]); + setprg8(0xA000, reg[1]); + setprg8(0xC000, reg[2]); setprg8(0xE000, ~0); setchr8(0); + if (KS7032) + setprg8(0x6000, reg[3]); + else { + setprg8r(0x10, 0x6000, 0); + setchr1(0x0000, creg[0]); + setchr1(0x0400, creg[1]); + setchr1(0x0800, creg[2]); + setchr1(0x0C00, creg[3]); + setchr1(0x1000, creg[4]); + setchr1(0x1400, creg[5]); + setchr1(0x1800, creg[6]); + setchr1(0x1C00, creg[7]); + setmirror(mirr); + } } static DECLFW(UNLKS7032Write) { /* FCEU_printf("bs %04x %02x\n",A,V); */ switch (A & 0xF000) { /* case 0x8FFF: reg[4]=V; Sync(); break; */ - case 0x8000: X6502_IRQEnd(FCEU_IQEXT); IRQCount = (IRQCount & 0x000F) | (V & 0x0F); isirqused = 1; break; - case 0x9000: X6502_IRQEnd(FCEU_IQEXT); IRQCount = (IRQCount & 0x00F0) | ((V & 0x0F) << 4); isirqused = 1; break; - case 0xA000: X6502_IRQEnd(FCEU_IQEXT); IRQCount = (IRQCount & 0x0F00) | ((V & 0x0F) << 8); isirqused = 1; break; - case 0xB000: X6502_IRQEnd(FCEU_IQEXT); IRQCount = (IRQCount & 0xF000) | (V << 12); isirqused = 1; break; - case 0xC000: if (isirqused) { - X6502_IRQEnd(FCEU_IQEXT); IRQa = 1; - } - break; + case 0x8000: IRQLatch = (IRQLatch & 0xFFF0) | (V & 0x0F); break; + case 0x9000: IRQLatch = (IRQLatch & 0xFF0F) | ((V & 0x0F) << 4); break; + case 0xA000: IRQLatch = (IRQLatch & 0xF0FF) | ((V & 0x0F) << 8); break; + case 0xB000: IRQLatch = (IRQLatch & 0x0FFF) | (V << 12); break; + case 0xC000: + IRQa = (V & 0xF); + if (IRQa) + IRQCount = IRQLatch; + X6502_IRQEnd(FCEU_IQEXT); break; + case 0xD000: X6502_IRQEnd(FCEU_IQEXT); break; case 0xE000: cmd = V & 7; break; - case 0xF000: reg[cmd] = V; Sync(); break; + case 0xF000: { + uint8 bank = (cmd - 1); + if (bank < 3) + reg[bank] = reg[bank] & 0x10 | V & 0x0F; + else if (bank < 4) + reg[bank] = V; + Sync(); + switch (A & 0xFC00) { + case 0xF000: + A &= 3; + if (A < 3) + reg[bank] = reg[bank] & 0x0F | V & 0x10; + Sync(); + break; + case 0xF800: + mirr = (V & 1); + Sync(); + break; + case 0xFC00: + creg[A & 7] = V; + Sync(); + break; + } + } + break; } } @@ -65,8 +122,7 @@ static void FP_FASTAPASS(1) UNLSMB2JIRQHook(int a) { if (IRQa) { IRQCount += a; if (IRQCount >= 0xFFFF) { - IRQa = 0; - IRQCount = 0; + IRQCount = IRQLatch; X6502_IRQBegin(FCEU_IQEXT); } } @@ -77,6 +133,10 @@ static void UNLKS7032Power(void) { SetReadHandler(0x6000, 0x7FFF, CartBR); SetReadHandler(0x8000, 0xFFFF, CartBR); SetWriteHandler(0x4020, 0xFFFF, UNLKS7032Write); + if (!KS7032) { + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + } } static void StateRestore(int version) { @@ -84,8 +144,27 @@ static void StateRestore(int version) { } void UNLKS7032_Init(CartInfo *info) { + KS7032 = 1; info->Power = UNLKS7032Power; MapIRQHook = UNLSMB2JIRQHook; GameStateRestore = StateRestore; - AddExState(&StateRegs, ~0, 0, 0); + AddExState(&StateRegsKS7032, ~0, 0, 0); +} + +void UNLKS202_Init(CartInfo *info) { + KS7032 = 0; + info->Power = UNLKS7032Power; + MapIRQHook = UNLSMB2JIRQHook; + GameStateRestore = StateRestore; + AddExState(&StateRegsKS7032, ~0, 0, 0); + AddExState(&StateRegsKS202, ~0, 0, 0); + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); } diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c index b9efe6d..ec1a3f1 100644 --- a/src/boards/addrlatch.c +++ b/src/boards/addrlatch.c @@ -195,6 +195,37 @@ void Mapper61_Init(CartInfo *info) { Latch_Init(info, M61Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); } +/*------------------ Map 063 ---------------------------*/ +/* added 2019-5-23 + * Mapper 63 NTDEC-Multicart + * http://wiki.nesdev.com/w/index.php/INES_Mapper_063 + * - Powerful 250-in-1 + * - Hello Kitty 255-in-1 */ + +static DECLFR(M63Read) { + if (latche & 0x0300) + return X.DB; + return CartBR(A); +} + +static void M63Sync(void) { + uint16 mode = latche & 2; + uint16 prg_bank = (latche & 0x3F8) >> 1; + uint16 prg16 = (latche & 4) >> 1; + + setprg8(0x8000, (prg_bank | (mode ? 0 : prg16 | 0))); + setprg8(0xA000, (prg_bank | (mode ? 1 : prg16 | 1))); + setprg8(0xC000, (prg_bank | (mode ? 2 : prg16 | 0))); + setprg8(0xE000, ((latche & 0x800) ? ((latche & 0x7C) | ((latche & 6) ? 3 : 1)) : + (prg_bank | (mode ? 3 : (prg16 | 1))))); + setchr8(0); + setmirror((latche & 1) ^ 1); +} + +void Mapper63_Init(CartInfo *info) { + Latch_Init(info, M63Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); +} + /*------------------ Map 092 ---------------------------*/ /* Another two-in-one mapper, two Jaleco carts uses similar * hardware, but with different wiring. diff --git a/src/boards/bmc60311c.c b/src/boards/bmc60311c.c new file mode 100644 index 0000000..8f313ee --- /dev/null +++ b/src/boards/bmc60311c.c @@ -0,0 +1,110 @@ +/* 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 + */ + +/* added 2019-5-23 + * UNIF: BMC-60311C: + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_289 + */ + +#include "mapinc.h" + +static uint8 inner_bank, outer_bank, mode; + +static SFORMAT StateRegs[] = +{ + { &inner_bank, 1, "INB0" }, + { &outer_bank, 1, "OUTB" }, + { &mode, 1, "MODE" }, + { 0 } +}; + +static void Sync(void) { + uint8 bbank = (mode & 4) ? 0 : (inner_bank & 7); + uint8 bank = outer_bank | bbank; + uint8 preg[2]; + + /* 0: NROM-128: Same inner/outer 16 KiB bank at CPU $8000-$BFFF + * and $C000-$FFFF + * 1: NROM-256: 32 kiB bank at CPU $8000-$FFFF (Selected inner/outer bank SHR 1) + * 2: UNROM: Inner/outer bank at CPU $8000-BFFF, + * fixed inner bank 7 within outer bank at $C000-$FFFF + * 3: Unknown + * + * The combined inner/outer bank is simply the inner bank, selected by the + * latch at $8000-$FFFF (or 0 if the latch is disabled) ORed with the + * outer bank selected by $6001, without any bit shifting. + */ + + preg[0] = bank; + switch (mode & 3) { + case 0x00: + case 0x01: + preg[1] = bank | ((mode & 1) ? 1 : 0); + break; + case 0x02: + preg[1] = outer_bank | 7; + case 0x03: + break; + } + + setchr8(0); + setprg16(0x8000, preg[0]); + setprg16(0xC000, preg[1]); + SetupCartMirroring(((mode & 8) >> 3) ^ 1, 1, NULL); +} + +static DECLFW(Write0) { + mode = V; + Sync(); +} + +static DECLFW(Write1) { + outer_bank = V; + Sync(); +} + +static DECLFW(Write8) { + inner_bank = V; + Sync(); +} + +static void BMC60311CPower(void) { + inner_bank = outer_bank = mode = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x6000, Write0); + SetWriteHandler(0x6001, 0x6001, Write1); + SetWriteHandler(0x8000, 0xFFFF, Write8); +} + +static void BMC60311CReset(void) { + inner_bank = outer_bank = mode = 0; + Sync(); +} + +static void BMC60311CRestore(int version) { + Sync(); +} + +void BMC60311C_Init(CartInfo *info) { + info->Power = BMC60311CPower; + info->Reset = BMC60311CReset; + GameStateRestore = BMC60311CRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/datalatch.c b/src/boards/datalatch.c index 3ed37be..c13454b 100644 --- a/src/boards/datalatch.c +++ b/src/boards/datalatch.c @@ -225,6 +225,22 @@ void CPROM_Init(CartInfo *info) { Latch_Init(info, CPROMSync, 0, 0x8000, 0xFFFF, 0, 0); } +/*------------------ Map 29 ---------------------------*/ +/* added 2019-5-23 + * Mapper 28, used by homebrew game Glider + * https://wiki.nesdev.com/w/index.php/INES_Mapper_029 */ + +static void M29Sync(void) { + setprg16(0x8000, (latche >> 2) & 7); + setprg16(0xc000, ~0); + setchr8r(0, latche & 3); + setprg8r(0x10, 0x6000, 0); +} + +void Mapper29_Init(CartInfo *info) { + Latch_Init(info, M29Sync, 0x0000, 0x6000, 0xFFFF, 1, 0); +} + /*------------------ Map 38 ---------------------------*/ static void M38Sync(void) { diff --git a/src/boards/hp10xx_hp20xx.c b/src/boards/hp10xx_hp20xx.c new file mode 100644 index 0000000..c18c9d1 --- /dev/null +++ b/src/boards/hp10xx_hp20xx.c @@ -0,0 +1,171 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2017 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 + */ + +#include "mapinc.h" +#include "mmc3.h" +#include "../ines.h" + +/* added on 2019-5-23 - NES 2.0 Mapper 260 + * HP10xx/HP20xx - a simplified version of FK23C mapper with pretty strict and better + * organized banking behaviour. It seems that some 176 mapper assigned game may be + * actually this kind of board instead but in common they aren't compatible at all, + * the games on the regular FK23C boards couldn't run on this mapper and vice versa... + */ + +static uint8 unromchr, lock; +static uint32 dipswitch; + +static void BMCHPxxCW(uint32 A, uint8 V) { + if (EXPREGS[0] & 4) { /* custom banking */ + switch(EXPREGS[0] & 3) { + case 0: + case 1: + setchr8(EXPREGS[2] & 0x3F); +/* FCEU_printf("\tCHR8 %02X\n",EXPREGS[2]&0x3F); */ + break; + case 2: + setchr8((EXPREGS[2] & 0x3E) | (unromchr & 1)); +/* FCEU_printf("\tCHR8 %02X\n",(EXPREGS[2]&0x3E)|(unromchr&1)); */ + break; + case 3: + setchr8((EXPREGS[2] & 0x3C) | (unromchr & 3)); +/* FCEU_printf("\tCHR8 %02X\n",(EXPREGS[2]&0x3C)|(unromchr&3)); */ + break; + } + } else { /* mmc3 banking */ + int base, mask; + if(EXPREGS[0] & 1) { /* 128K mode */ + base = EXPREGS[2] & 0x30; + mask = 0x7F; + } else { /* 256K mode */ + base = EXPREGS[2] & 0x20; + mask = 0xFF; + } +/* FCEU_printf("\tCHR1 %04x:%02X\n",A,(V&mask)|(base<<3)); */ + setchr1(A, (V & mask) | (base << 3)); + } +} + +/* PRG wrapper */ +static void BMCHPxxPW(uint32 A, uint8 V) { + if(EXPREGS[0] & 4) { /* custom banking */ + if((EXPREGS[0] & 0xF) == 4) { /* 16K mode */ +/* FCEU_printf("\tPRG16 %02X\n",EXPREGS[1]&0x1F); */ + setprg16(0x8000, EXPREGS[1] & 0x1F); + setprg16(0xC000, EXPREGS[1] & 0x1F); + } else { /* 32K modes */ +/* FCEU_printf("\tPRG32 %02X\n",(EXPREGS[1]&0x1F)>>1); */ + setprg32(0x8000, (EXPREGS[1] & 0x1F) >> 1); + } + } else { /* mmc3 banking */ + uint8 base, mask; + if(EXPREGS[0] & 2) { /* 128K mode */ + base = EXPREGS[1] & 0x18; + mask = 0x0F; + } else { /* 256K mode */ + base = EXPREGS[1] & 0x10; + mask = 0x1F; + } +/* FCEU_printf("\tPRG8 %02X\n",(V&mask)|(base<<1)); */ + setprg8(A, (V & mask) | (base << 1)); + setprg8r(0x10, 0x6000, A001B & 3); + } +} + +/* MIRROR wrapper */ +static void BMCHPxxMW(uint8 V) { + if(EXPREGS[0] & 4) { /* custom banking */ +/* FCEU_printf("CUSTOM MIRR: %d\n",(unromchr>>2)&1); */ + setmirror(((unromchr >> 2) & 1) ^ 1); + } else { /* mmc3 banking */ +/* FCEU_printf("MMC3 MIRR: %d\n",(V&1)^1); */ + A000B = V; + setmirror((A000B & 1) ^ 1); + } +} + +/* PRG handler ($8000-$FFFF) */ +static DECLFW(BMCHPxxHiWrite) { +/* FCEU_printf("HI WRITE %04X:%02X\n",A,V); */ + if(EXPREGS[0] & 4) { /* custom banking */ +/* FCEU_printf("CUSTOM\n"); */ + unromchr = V; + FixMMC3CHR(MMC3_cmd); + } else { /* mmc3 banking */ +/* FCEU_printf("MMC3\n"); */ + if(A<0xC000) { + MMC3_CMDWrite(A, V); + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } else { + MMC3_IRQWrite(A, V); + } + } +} + +/* EXP handler ($5000-$5FFF) */ +static DECLFW(BMCHPxxWrite) { + if (!lock) { +/* FCEU_printf("LO WRITE %04X:%02X\n",A,V); */ + EXPREGS[A & 3] = V; + lock = V & 0x80; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } +} + +static DECLFR(BMCHPxxRead) { + return dipswitch; +} + +static void BMCHPxxReset(void) { + dipswitch++; + dipswitch &= 0xF; + lock = 0; +/* FCEU_printf("BMCHPxx dipswitch set to %d\n",dipswitch); */ + EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; + MMC3RegReset(); + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void BMCHPxxPower(void) { + GenMMC3Power(); + dipswitch = lock = 0; + EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + SetReadHandler(0x5000, 0x5fff, BMCHPxxRead); + SetWriteHandler(0x5000, 0x5fff, BMCHPxxWrite); + SetWriteHandler(0x8000, 0xffff, BMCHPxxHiWrite); +} + +void BMCHPxx_Init(CartInfo *info) { + GenMMC3_Init(info, 256, 256, 8, 0); + cwrap = BMCHPxxCW; + pwrap = BMCHPxxPW; + mwrap = BMCHPxxMW; + info->Power = BMCHPxxPower; + info->Reset = BMCHPxxReset; + AddExState(EXPREGS, 8, 0, "EXPR"); + AddExState(&unromchr, 1, 0, "UCHR"); + AddExState(&dipswitch, 1, 0, "DPSW"); + AddExState(&lock, 1, 0, "LOCK"); +} diff --git a/src/boards/super40in1.c b/src/boards/super40in1.c new file mode 100644 index 0000000..ef5a5e1 --- /dev/null +++ b/src/boards/super40in1.c @@ -0,0 +1,74 @@ +/* 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 + */ + +/* added 2019-5-23 + * BMC-WS Used for Super 40-in-1 multicart + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_332 */ + +#include "mapinc.h" + +static uint8 preg, creg; + +static SFORMAT StateRegs[] = +{ + { &preg, 1, "PREG" }, + { &creg, 1, "CREG" }, + { 0 } +}; + +static void Sync(void) { + if (preg & 8) { + setprg16(0x8000, preg & 7); + setprg16(0xc000, preg & 7); + } + else + setprg32(0x8000, (preg & 6) >> 1); + setchr8(creg); + setmirror(((preg >> 4) & 1) ^ 1); +} + +static DECLFW(BMCWSWrite) { + if (preg & 0x20) + return; + + switch (A & 1) { + case 0: preg = V; Sync(); break; + case 1: creg = V; Sync(); break; + } +} + +static void MBMCWSPower(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x6001, BMCWSWrite); +} + +static void BMCWSReset(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void BMCWS_Init(CartInfo *info) { + info->Reset = BMCWSReset; + info->Power = MBMCWSPower; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/ines-correct.h b/src/ines-correct.h index 359c7e9..fde6d54 100644 --- a/src/ines-correct.h +++ b/src/ines-correct.h @@ -317,7 +317,6 @@ {0x6bea1235, 245, -1}, /* MMC3 cart, but with nobanking applied to CHR-RAM, so let it be there */ {0x345ee51a, 245, -1}, /* DQ4c */ {0x57514c6c, 245, -1}, /* Yong Zhe Dou E Long - Dragon Quest VI (Ch) */ - {0x00000000, -1, -1} #endif diff --git a/src/ines.c b/src/ines.c index 83591df..acec60f 100644 --- a/src/ines.c +++ b/src/ines.c @@ -417,10 +417,10 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"Konami VRC2/VRC4 D", 25, Mapper25_Init}, {(uint8_t*)"Konami VRC6 Rev. B", 26, Mapper26_Init}, {(uint8_t*)"CC-21 MI HUN CHE", 27, UNLCC21_Init}, /* Former dupe for VRC2/VRC4 mapper, redefined with crc to mihunche boards */ -/* {(uint8_t*)"", 28, Mapper28_Init}, */ /* Custom Multidiscrete mapper for PDs */ -/* {(uint8_t*)"", 29, Mapper29_Init}, */ + {(uint8_t*)"Action 53", 28, Mapper28_Init}, + {(uint8_t*)"", 29, Mapper29_Init}, {(uint8_t*)"UNROM 512", 30, UNROM512_Init}, -/* {(uint8_t*)"", 31, Mapper31_Init}, */ + {(uint8_t*)"infineteNesLives-NSF", 31, Mapper31_Init}, {(uint8_t*)"IREM G-101", 32, Mapper32_Init}, {(uint8_t*)"TC0190FMC/TC0350FMR", 33, Mapper33_Init}, {(uint8_t*)"IREM I-IM/BNROM", 34, Mapper34_Init}, @@ -445,14 +445,14 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"SUPERVISION 16-in-1", 53, Supervision16_Init}, /* {(uint8_t*)"", 54, Mapper54_Init}, */ /* {(uint8_t*)"", 55, Mapper55_Init}, */ -/* {(uint8_t*)"", 56, Mapper56_Init}, */ + {(uint8_t*)"UNLKS202", 56, UNLKS202_Init}, {(uint8_t*)"SIMBPLE BMC PIRATE A", 57, Mapper57_Init}, {(uint8_t*)"SIMBPLE BMC PIRATE B", 58, BMCGK192_Init}, {(uint8_t*)"", 59, Mapper59_Init}, /* Check this out */ {(uint8_t*)"SIMBPLE BMC PIRATE C", 60, BMCD1038_Init}, {(uint8_t*)"20-in-1 KAISER Rev. A",61, Mapper61_Init}, {(uint8_t*)"700-in-1", 62, Mapper62_Init}, -/* {(uint8_t*)"", 63, Mapper63_Init}, */ + {(uint8_t*)"", 63, Mapper63_Init}, {(uint8_t*)"TENGEN RAMBO1", 64, Mapper64_Init}, {(uint8_t*)"IREM-H3001", 65, Mapper65_Init}, {(uint8_t*)"MHROM", 66, MHROM_Init}, @@ -571,7 +571,7 @@ static BMAPPINGLocal bmap[] = { /* {(uint8_t*)"", 179, Mapper179_Init}, */ {(uint8_t*)"", 180, Mapper180_Init}, {(uint8_t*)"", 181, Mapper181_Init}, -/* {(uint8_t*)"", 182, Mapper182_Init}, */ /* Deprecated, dupe */ +/* {(uint8_t*)"", 182, Mapper182_Init}, */ /* Deprecated, dupe of Mapper 114 */ {(uint8_t*)"", 183, Mapper183_Init}, {(uint8_t*)"", 184, Mapper184_Init}, {(uint8_t*)"", 185, Mapper185_Init}, @@ -644,7 +644,8 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"SAN GUO ZHI PIRATE", 252, Mapper252_Init}, {(uint8_t*)"DRAGON BALL PIRATE", 253, Mapper253_Init}, {(uint8_t*)"", 254, Mapper254_Init}, -/* {(uint8_t*)"", 255, Mapper255_Init}, */ /* No good dumps for this mapper */ + {(uint8_t*)"", 255, Mapper255_Init}, /* Duplicate of M225? */ + {(uint8_t*)"", 0, NULL} }; @@ -742,10 +743,6 @@ int iNESLoad(const char *name, FCEUFILE *fp) { iNESCart.CRC32 = iNESGameCRC32; - FCEU_printf(" PRG ROM: %3d x 16KiB\n", head.ROM_size ? head.ROM_size : 256); - FCEU_printf(" CHR ROM: %3d x 8KiB\n", head.VROM_size); - FCEU_printf(" ROM CRC32: 0x%08lx\n", iNESGameCRC32); - FCEU_printf(" ROM MD5: 0x%s\n", md5_asciistr(iNESCart.MD5)); mappername = "Not Listed"; for (mappertest = 0; mappertest < (sizeof bmap / sizeof bmap[0]) - 1; mappertest++) { @@ -755,12 +752,6 @@ int iNESLoad(const char *name, FCEUFILE *fp) { } } - FCEU_printf(" Mapper #: %d\n", MapperNo); - FCEU_printf(" Mapper name: %s\n", mappername); - FCEU_printf(" Mirroring: %s\n", Mirroring == 2 ? "None (Four-screen)" : Mirroring ? "Vertical" : "Horizontal"); - FCEU_printf(" Battery-backed: %s\n", (head.ROM_type & 2) ? "Yes" : "No"); - FCEU_printf(" Trained: %s\n", (head.ROM_type & 4) ? "Yes" : "No"); - SetInput(); CheckHInfo(); { @@ -790,10 +781,22 @@ int iNESLoad(const char *name, FCEUFILE *fp) { iNESCart.battery = (head.ROM_type & 2) ? 1 : 0; iNESCart.mirror = Mirroring; + FCEU_printf(" ROM CRC32: 0x%08lx\n", iNESGameCRC32); + FCEU_printf(" ROM MD5: 0x%s\n", md5_asciistr(iNESCart.MD5)); + FCEU_printf(" PRG ROM: %3d x 16KiB\n", head.ROM_size ? head.ROM_size : 256); + FCEU_printf(" CHR ROM: %3d x 8KiB\n", head.VROM_size); + if (!iNES_Init(MapperNo)) FCEU_PrintError("iNES mapper #%d is not supported at all.", MapperNo); iNESCart.mapper = MapperNo; + FCEU_printf(" \n"); + FCEU_printf(" Mapper #: %3d\n", MapperNo); + FCEU_printf(" Mapper name: %s\n", mappername); + FCEU_printf(" Mirroring: %s\n", Mirroring == 2 ? "None (Four-screen)" : Mirroring ? "Vertical" : "Horizontal"); + FCEU_printf(" Battery-backed: %s\n", (head.ROM_type & 2) ? "Yes" : "No"); + FCEU_printf(" Trained: %s\n", (head.ROM_type & 4) ? "Yes" : "No"); + GameInterface = iNESGI; FCEU_printf("\n"); @@ -831,6 +834,8 @@ static int iNES_Init(int num) { switch (num) { /* FIXME, mapper or game data base with the board parameters and ROM/RAM sizes */ case 13: CHRRAMSize = 16 * 1024; break; case 6: + case 28: + case 29: case 30: case 45: case 96: CHRRAMSize = 32 * 1024; break; @@ -843,6 +848,7 @@ static int iNES_Init(int num) { UNIFchrrama = VROM; SetupCartCHRMapping(0, VROM, CHRRAMSize, 1); AddExState(VROM, CHRRAMSize, 0, "CHRR"); + FCEU_printf(" CHR RAM: %3d x 1KiB\n", CHRRAMSize / 1024); } if (head.ROM_type & 8) AddExState(ExtraNTARAM, 2048, 0, "EXNR"); diff --git a/src/ines.h b/src/ines.h index b3d07ba..61402c2 100644 --- a/src/ines.h +++ b/src/ines.h @@ -63,7 +63,9 @@ void Mapper23_Init(CartInfo *); void Mapper24_Init(CartInfo *); void Mapper25_Init(CartInfo *); void Mapper26_Init(CartInfo *); -void UNROM512_Init(CartInfo *); /* Mapper #30 */ +void Mapper28_Init(CartInfo *); +void Mapper29_Init(CartInfo *); +void Mapper31_Init(CartInfo *); void Mapper32_Init(CartInfo *); void Mapper33_Init(CartInfo *); void Mapper34_Init(CartInfo *); @@ -87,6 +89,7 @@ void Mapper57_Init(CartInfo *); void Mapper59_Init(CartInfo *); void Mapper61_Init(CartInfo *); void Mapper62_Init(CartInfo *); +void Mapper63_Init(CartInfo *); void Mapper64_Init(CartInfo *); void Mapper65_Init(CartInfo *); void Mapper67_Init(CartInfo *); @@ -222,5 +225,6 @@ void Mapper250_Init(CartInfo *); void Mapper252_Init(CartInfo *); void Mapper253_Init(CartInfo *); void Mapper254_Init(CartInfo *); +void Mapper255_Init(CartInfo *); #endif diff --git a/src/unif.c b/src/unif.c index 4622f3a..e0f961b 100644 --- a/src/unif.c +++ b/src/unif.c @@ -463,6 +463,10 @@ static BMAPPING bmap[] = { { "RT-01", UNLRT01_Init, 0 }, { "81-01-31-C", BMC810131C_Init, 0 }, { "8-IN-1", BMC8IN1_Init, 0 }, + { "RET-CUFROM", Mapper29_Init, BMCFLAG_32KCHRR }, + { "60311C", BMC60311C_Init, 0 }, + { "WS", BMCWS_Init, 0 }, + { "HPxx", BMCHPxx_Init, 0 }, #ifdef COPYFAMI { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, @@ -609,6 +613,7 @@ int UNIFLoad(const char *name, FCEUFILE *fp) { aborto: + FCEU_printf(" Failed to initialize board %s\n", boardname); FreeUNIF(); ResetUNIF(); return 0; diff --git a/src/unif.h b/src/unif.h index f7df71d..8e58113 100644 --- a/src/unif.h +++ b/src/unif.h @@ -158,6 +158,12 @@ void UNLRT01_Init(CartInfo *info); void BMC810131C_Init(CartInfo *info); void BMC8IN1_Init(CartInfo *info); +/* additional boards */ +void BMC60311C_Init(CartInfo *info); /* m289 */ +void BMCWS_Init(CartInfo *info); /* m332 */ +void UNLKS202_Init(CartInfo *info); /* m056 */ +void BMCHPxx_Init(CartInfo *info); /* m260 */ + #ifdef COPYFAMI void MapperCopyFamiMMC3_Init(CartInfo *info); void MapperCopyFami_Init(CartInfo *info); From 6fd12ed6bf9899f81e96b45f273dce4f1e4b8862 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Mon, 27 May 2019 21:35:12 +0800 Subject: [PATCH 2/3] BMC-8157: ignore prg mapping for split rom types - fixes 1 of only 2 CK-001 4-in-1 carts i found so far --- src/boards/8157.c | 9 ++++++--- src/boards/KS7032.c | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/boards/8157.c b/src/boards/8157.c index 8a95353..f62cb8f 100644 --- a/src/boards/8157.c +++ b/src/boards/8157.c @@ -36,10 +36,13 @@ 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); - if (PRGptr[1]) { - setprg16r(base >> 3, 0x8000, bank); /* for versions with split ROMs */ + /* this fails to load at least one game, which probably has invalid PRG size in header + * (rom is only 512KB but reported as having 3 prg banks with 128k each) */ + /*if (PRGptr[1]) { + setprg16r(base >> 3, 0x8000, bank); // for versions with split ROMs setprg16r(base >> 3, 0xC000, lbank); - } else { + } else*/ + { setprg16(0x8000, base | bank); setprg16(0xC000, base | lbank); } diff --git a/src/boards/KS7032.c b/src/boards/KS7032.c index 5a5bd53..7a8bdfc 100644 --- a/src/boards/KS7032.c +++ b/src/boards/KS7032.c @@ -2,7 +2,7 @@ * * Copyright notice for this file: * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2019 Libretro Team (IRQ Update) + * 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 From ffef1743d86ea0da149998e4e91d71928bfe7c7c Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Mon, 27 May 2019 21:39:27 +0800 Subject: [PATCH 3/3] Add Super Donkey Kong (Unl) [o1] to ines-correct --- src/ines-correct.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ines-correct.h b/src/ines-correct.h index fde6d54..3c0a31a 100644 --- a/src/ines-correct.h +++ b/src/ines-correct.h @@ -317,6 +317,7 @@ {0x6bea1235, 245, -1}, /* MMC3 cart, but with nobanking applied to CHR-RAM, so let it be there */ {0x345ee51a, 245, -1}, /* DQ4c */ {0x57514c6c, 245, -1}, /* Yong Zhe Dou E Long - Dragon Quest VI (Ch) */ + {0xdb9d71b7, 114, -1}, /* Super Donkey Kong (Unl) [o1] */ {0x00000000, -1, -1} #endif