From b414ad217688ad2ec124ca3703cb0976c891d68f Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Tue, 18 Jun 2019 11:04:27 +0800 Subject: [PATCH] Add UNIF boards... - Add UNL-TH2131-1, UNL-LH51, BMC-RESETNROM-XIN1, BMC-RESET-TXROM - Add FARID_SLROM_8-IN-1, BMC-830425C-4391T, BMC-TJ-03, BMC-CTC-09 - Add BMC-K-3046, BMC-SA005-A, BMC-K-3006, BMC-K-3036, MINDKIDS - Add UNL-KS7021A, KS106C, BTL-900218 - Cleanup VRC2and4 (unify power function) --- src/boards/addrlatch.c | 33 +++++++++ src/boards/bcmk3006.c | 70 +++++++++++++++++++ src/boards/bmc830425C4391t.c | 101 +++++++++++++++++++++++++++ src/boards/bmcctc09.c | 74 ++++++++++++++++++++ src/boards/bmck3036.c | 75 ++++++++++++++++++++ src/boards/coolboy.c | 28 +++++++- src/boards/datalatch.c | 14 ++++ src/boards/lh51.c | 87 ++++++++++++++++++++++++ src/boards/mmc1.c | 51 +++++++++++++- src/boards/resetnromxin1.c | 86 +++++++++++++++++++++++ src/boards/resettxrom.c | 57 ++++++++++++++++ src/boards/vrc2and4.c | 128 +++++++++++++++++++++++++++++------ src/unif.c | 19 ++++++ src/unif.h | 19 +++++- 14 files changed, 816 insertions(+), 26 deletions(-) create mode 100644 src/boards/bcmk3006.c create mode 100644 src/boards/bmc830425C4391t.c create mode 100644 src/boards/bmcctc09.c create mode 100644 src/boards/bmck3036.c create mode 100644 src/boards/lh51.c create mode 100644 src/boards/resetnromxin1.c create mode 100644 src/boards/resettxrom.c diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c index 7bda0c1..ee18af9 100644 --- a/src/boards/addrlatch.c +++ b/src/boards/addrlatch.c @@ -541,3 +541,36 @@ static void BMCG146Sync(void) { 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 >> 1) & 1) ^ 1; + uint8 bank = (latche >> 8) & 7; + + setprg32(0x8000, bank); + setchr8(bank); + + if (bank == 3) mirr ^= 1; /* Twin Bee has incorrect mirroring */ + SetupCartMirroring(mirr, 1, NULL); +} + +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 */ + +static void BMCSA005ASync(void) { + setprg16(0x8000, latche & 0x0F); + setprg16(0xC000, latche & 0x0F); + setchr8(latche & 0x0F); + SetupCartMirroring((latche >> 3) & 1, 1, NULL); +} + +void BMCSA005A_Init(CartInfo *info) { + Latch_Init(info, BMCSA005ASync, NULL, 0x0000, 0x8000, 0xFFFF, 0); +} diff --git a/src/boards/bcmk3006.c b/src/boards/bcmk3006.c new file mode 100644 index 0000000..ab3e539 --- /dev/null +++ b/src/boards/bcmk3006.c @@ -0,0 +1,70 @@ +/* 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 + * + */ + +/* NES 2.0 mapper 339 is used for a 21-in-1 multicart. + * Its UNIF board name is BMC-K-3006. + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_339 + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void BMCK3006CW(uint32 A, uint8 V) { + setchr1(A, (V & 0x7F) | (EXPREGS[0] & 0x18) << 4); +} + +static void BMCK3006PW(uint32 A, uint8 V) { + if (EXPREGS[0] & 0x20) { /* MMC3 mode */ + setprg8(A, (V & 0x0F) | (EXPREGS[0] & 0x18) << 1); + } else { + if ((EXPREGS[0] & 0x07) == 0x06) { /* NROM-256 */ + setprg32(0x8000, (EXPREGS[0] >> 1) & 0x0F); + } else { /* NROM-128 */ + setprg16(0x8000, EXPREGS[0] & 0x1F); + setprg16(0xC000, EXPREGS[0] & 0x1F); + } + } +} + +static DECLFW(BMCK3006Write) { + EXPREGS[0] = A & 0x3F; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void BMCK3006Reset(void) { + EXPREGS[0] = 0; + MMC3RegReset(); +} + +static void BMCK3006Power(void) { + EXPREGS[0] = 0; + GenMMC3Power(); + SetWriteHandler(0x6000, 0x7FFF, BMCK3006Write); +} + +void BMCK3006_Init(CartInfo *info) { + GenMMC3_Init(info, 512, 512, 8, 0); + pwrap = BMCK3006PW; + cwrap = BMCK3006CW; + info->Power = BMCK3006Power; + info->Reset = BMCK3006Reset; + AddExState(EXPREGS, 1, 0, "EXPR"); +} diff --git a/src/boards/bmc830425C4391t.c b/src/boards/bmc830425C4391t.c new file mode 100644 index 0000000..db18618 --- /dev/null +++ b/src/boards/bmc830425C4391t.c @@ -0,0 +1,101 @@ +/* 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 + * + */ + +/* NES 2.0 Mapper 320 is used for the Super HiK 6-in-1 A-030 multicart. + * Basically UxROM with an address-latch-based outer bank register. + * UNIF board name is BMC-830425C-4391T. Mirroring is hard-wired. + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_320 + */ + +#include "mapinc.h" + +static uint8 regs[2]; +static uint8 isMermaid = 0; + +static SFORMAT StateRegs[] = +{ + { regs, 2, "REGS" }, + { &isMermaid, 1, "MERM" }, + { 0 } +}; + +static void Sync(void) { + uint8 bank_size = (regs[0] & 0x80) ? 0x07: 0x0F; + uint8 outer_bank = !isMermaid ? (regs[0] & 0x78) : 0x04; + uint8 inner_bank = regs[1]; + uint8 game_block = regs[0] & 0x78; + + /* TODO: Hacky and forced mapping of outer banks(game block)... */ + if (!isMermaid) { + switch(game_block) { + case 0x00: /* botb outerbank=0 */ + case 0x10: /* rocketeer outerbank=1 */ + case 0x20: /* contra outerbank=2 */ + case 0x28: /* ducktales outerbank=3 */ + case 0x38: /* school fight outerbank=5 */ + outer_bank = (game_block >> 4) + ((game_block & 0x08) ? 0x01 : 0x00); + outer_bank |= (game_block >> 3) & 1; + break; + case 0x30: + /* Mermaid game block is tricky (to me at least). Aim here is + * when this register is selected, ignore any other outer bank reg changes */ + isMermaid = 1; + outer_bank = 0x04; + break; + } + } + + setprg16r(outer_bank, 0x8000, (inner_bank & bank_size)); + setprg16r(outer_bank, 0xC000, bank_size); + setchr8(0); +} + +static DECLFW(M320Write) { + if ((A & 0xF0E0) == 0xF0E0) { + regs[0] = (A & 0x1F) << 3; + } + regs[1] = V & 0x0F; + Sync(); +} + +static void M320Power(void) { + regs[0] = regs[1] = 0; + isMermaid = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M320Write); +} + +static void M320Reset(void) { + regs[0] = regs[1] = 0; + isMermaid = 0; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void BMC830425C4391T_Init(CartInfo *info) { + info->Power = M320Power; + info->Reset = M320Reset; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/bmcctc09.c b/src/boards/bmcctc09.c new file mode 100644 index 0000000..185576c --- /dev/null +++ b/src/boards/bmcctc09.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 + * + */ + +/* NES 2.0 mapper 335 is used for a 10-in-1 multicart. + * Its UNIF board name is BMC-CTC-09. + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_335 */ + +#include "mapinc.h" + +#define PRG 0 +#define CHR 1 + +static uint8 regs[2]; + +static SFORMAT StateRegs[] = +{ + { regs, 2, "REGS" }, + { 0 } +}; + +static void Sync(void) { + if (regs[PRG] & 0x10) { + setprg16(0x8000, ((regs[PRG] & 0x07) << 1) | ((regs[PRG] >> 3) & 1)); + setprg16(0xC000, ((regs[PRG] & 0x07) << 1) | ((regs[PRG] >> 3) & 1)); + } else + setprg32(0x8000, regs[PRG] & 0x07); + + setchr8(regs[CHR] & 0x0F); + SetupCartMirroring(((regs[PRG] >> 5) & 1) ^ 1, 1, NULL); +} + +static DECLFW(WritePRG) { + regs[PRG] = V; + Sync(); +} + +static DECLFW(WriteCHR) { + regs[CHR] = V; + Sync(); +} + +static void BMCCTC09Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xBFFF, WriteCHR); + SetWriteHandler(0xC000, 0xFFFF, WritePRG); +} + +static void StateRestore(int version) { + Sync(); +} + +void BMCCTC09_Init(CartInfo *info) { + info->Power = BMCCTC09Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/bmck3036.c b/src/boards/bmck3036.c new file mode 100644 index 0000000..2e716e0 --- /dev/null +++ b/src/boards/bmck3036.c @@ -0,0 +1,75 @@ +/* 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 + * + */ + +/* NES 2.0 mapper 340 is used for a 35-in-1 multicart. + * Its UNIF board name is BMC-K-3036. + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_340 + * TODO: Some games are not working... + */ + +#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] & 0x1F); + setprg16(0xC000, regs[0] & 0x1F); + } else { /* UNROM */ + setprg16(0x8000, regs[0] & 0x1F | regs[1] & 0x07); + setprg16(0xC000, regs[0] & 0x1F | 0x07); + } + setchr8(0); + SetupCartMirroring(((regs[0] & 0x25) == 0x25 ? MI_H : MI_V), 1, NULL); +} + +static DECLFW(M340Write) { + regs[0] = A & 0xFF; + regs[1] = V & 0xFF; + Sync(); +} + +static void BMCK3036Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xBFFF, M340Write); +} + +static void BMCK3036Reset(void) { + regs[0] = regs[1] = 0; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void BMCK3036_Init(CartInfo *info) { + info->Power = BMCK3036Power; + info->Reset = BMCK3036Reset; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/coolboy.c b/src/boards/coolboy.c index b0f8649..5482550 100644 --- a/src/boards/coolboy.c +++ b/src/boards/coolboy.c @@ -42,7 +42,7 @@ static void COOLBOYCW(uint32 A, uint8 V) { } } /* Highest bit goes from MMC3 registers when EXPREGS[3]&0x80==0 or from EXPREGS[0]&0x08 otherwise */ - setchr1(A, + setchr1(A, (V & 0x80 & mask) | ((((EXPREGS[0] & 0x08) << 4) & ~mask)) /* 7th bit */ | ((EXPREGS[2] & 0x0F) << 3) /* 6-3 bits */ | ((A >> 10) & 7) /* 2-0 bits */ @@ -107,7 +107,7 @@ static DECLFW(COOLBOYWrite) { CartBW(A,V); /* Deny any further writes when 7th bit is 1 AND 4th is 0 */ - if ((EXPREGS[3] & 0x90) != 0x80) { + if ((EXPREGS[3] & 0x90) != 0x80) { EXPREGS[A & 3] = V; FixMMC3PRG(MMC3_cmd); FixMMC3CHR(MMC3_cmd); @@ -150,3 +150,27 @@ void COOLBOY_Init(CartInfo *info) { info->Reset = COOLBOYReset; AddExState(EXPREGS, 4, 0, "EXPR"); } + +/*------------------ MINDKIDS ---------------------------*/ +/* A COOLBOY variant that works identically but puts the outer bank registers + * in the $5xxx range instead of the $6xxx range. + * The UNIF board name is MINDKIDS (submapper 1). + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_268 + */ + +static void MINDKIDSPower(void) { + GenMMC3Power(); + EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + SetWriteHandler(0x5000, 0x5fff, COOLBOYWrite); +} + +void MINDKIDS_Init(CartInfo *info) { + GenMMC3_Init(info, 2048, 256, 8, info->battery); + pwrap = COOLBOYPW; + cwrap = COOLBOYCW; + info->Power = MINDKIDSPower; + info->Reset = COOLBOYReset; + AddExState(EXPREGS, 4, 0, "EXPR"); +} diff --git a/src/boards/datalatch.c b/src/boards/datalatch.c index 4a563f3..1846bb7 100644 --- a/src/boards/datalatch.c +++ b/src/boards/datalatch.c @@ -527,3 +527,17 @@ static void BMC11160Sync(void) { void BMC11160_Init(CartInfo *info) { Latch_Init(info, BMC11160Sync, 0, 0x8000, 0xFFFF, 0, 0); } + +/*------------------ BMC-K-3046 ---------------------------*/ +/* NES 2.0 mapper 336 is used for an 11-in-1 multicart + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_336 */ + +static void BMCK3046Sync(void) { + setprg16(0x8000, latche); + setprg16(0xC000, latche | 0x07); + setchr8(0); +} + +void BMCK3046_Init(CartInfo *info) { + Latch_Init(info, BMCK3046Sync, 0, 0x8000, 0xFFFF, 0, 0); +} diff --git a/src/boards/lh51.c b/src/boards/lh51.c new file mode 100644 index 0000000..3236485 --- /dev/null +++ b/src/boards/lh51.c @@ -0,0 +1,87 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * 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 + */ + +/* FDS Conversion + * NES 2.0 Mapper 309 is used for Whirlwind Manu's ROM cartridge conversion + * of game 愛戦士ニコル (Ai Senshi Nicol, cartridge code LH51). + * Its UNIF board name is UNL-LH51. + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_309 + */ + +#include "mapinc.h" + +static uint8 reg, mirr; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REG" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setchr8(0); + setprg8r(0x10, 0x6000, 0); + setprg8(0x8000, reg & 0x0F); + setprg8(0xA000, 13); + setprg8(0xC000, 14); + setprg8(0xE000, 15); + setmirror(((mirr >> 3) & 1) ^ 1); +} + +static DECLFW(LH51Write) { + switch (A & 0xF000) { + case 0x8000: reg = V; Sync(); break; + case 0xF000: mirr = V; Sync(); break; + } +} + +static void LH51Power(void) { + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0xFFFF, LH51Write); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void LH51Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void LH51_Init(CartInfo *info) { + info->Power = LH51Power; + info->Close = LH51Close; + 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/mmc1.c b/src/boards/mmc1.c index 5a4d343..4dc4f69 100644 --- a/src/boards/mmc1.c +++ b/src/boards/mmc1.c @@ -36,13 +36,17 @@ static uint8 *WRAM = NULL; static uint8 *CHRRAM = NULL; static int is155, is171; +static uint8 MMC1WRAMEnabled(void) { + return !(DRegs[3] & 0x10); +} + static DECLFW(MBWRAM) { - if (!(DRegs[3] & 0x10) || is155) + if (MMC1WRAMEnabled() || is155) Page[A >> 11][A] = V; /* WRAM is enabled. */ } static DECLFR(MAWRAM) { - if ((DRegs[3] & 0x10) && !is155) + if (!MMC1WRAMEnabled() && !is155) return X.DB; /* WRAM is disabled */ return(Page[A >> 11][A]); } @@ -395,4 +399,47 @@ void SOROM_Init(CartInfo *info) { GenMMC1Init(info, 256, 0, 16, info->battery); } +/* ----------------------- FARID_SLROM_8-IN-1 -----------------------*/ +/* NES 2.0 Mapper 323 - UNIF FARID_SLROM_8-IN-1 */ + +static uint8 reg, lock; + +static void FARIDSLROM8IN1PRGHook(uint32 A, uint8 V) { + setprg16(A, (V & 0x07) | (reg << 3)); +} + +static void FARIDSLROM8IN1CHRHook(uint32 A, uint8 V) { + setchr4(A, (V & 0x1F) | (reg << 5)); +} + +static DECLFW(FARIDSLROM8IN1Write) { + if (MMC1WRAMEnabled() && !lock) { + lock = (V & 0x08) >> 3; + reg = (V & 0xF0) >> 4; + MMC1MIRROR(); + MMC1CHR(); + MMC1PRG(); + } +} + +static void FARIDSLROM8IN1Power(void) { + reg = lock = 0; + GenMMC1Power(); + SetWriteHandler(0x6000, 0x7FFF, FARIDSLROM8IN1Write); +} + +static void FARIDSLROM8IN1Reset(void) { + reg = lock = 0; + MMC1CMReset(); +} + +void FARIDSLROM8IN1_Init(CartInfo *info) { + GenMMC1Init(info, 1024, 256, 8, 0); + MMC1CHRHook4 = FARIDSLROM8IN1CHRHook; + MMC1PRGHook16 = FARIDSLROM8IN1PRGHook; + info->Power = FARIDSLROM8IN1Power; + info->Reset = FARIDSLROM8IN1Reset; + AddExState(lock, 1, 0, "LOCK"); + AddExState(reg, 1, 0, "REG6"); +} diff --git a/src/boards/resetnromxin1.c b/src/boards/resetnromxin1.c new file mode 100644 index 0000000..c97837d --- /dev/null +++ b/src/boards/resetnromxin1.c @@ -0,0 +1,86 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * 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 + */ + +/* BMC-RESETNROM-XIN1 + * - Sheng Tian 2-in-1(Unl,ResetBase)[p1] - Kung Fu (Spartan X), Super Mario Bros (alt) + * - Sheng Tian 2-in-1(Unl,ResetBase)[p2] - B-Wings, Twin-bee + * + * BMC-KS106C + * - Kaiser 4-in-1(Unl,KS106C)[p1] - B-Wings, Kung Fu, 1942, SMB1 (wrong mirroring) + */ + +#include "mapinc.h" + +static uint8 gameblock, limit; + +static SFORMAT StateRegs[] = +{ + { &gameblock, 1, "GAME" }, + { 0 } +}; + +static void Sync(void) { + setchr8r(gameblock, 0); + setprg32r(gameblock, 0x8000, 0); +} + +static void BMCRESETNROMXIN1Power(void) { + gameblock = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void BMCRESETNROMXIN1Reset(void) { + gameblock++; + gameblock &= limit; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void BMCRESETNROMXIN1_Init(CartInfo *info) { + uint8 x; + uint64 partialmd5; + + for (x = 0; x < 8; x++) + partialmd5 |= (uint64)info->MD5[15 - x] << (x * 8); + + /* Mirroring override - these boards have incorrect mirroring for some reasons in their headers */ + if (partialmd5 == 0x616851e56946893bLL) /* Sheng Tian 2-in-1(Unl,ResetBase)[p1].unf */ + SetupCartMirroring(1, 1, NULL); + else if (partialmd5 == 0x4cd729b5ae23a3cfLL) /* Sheng Tian 2-in-1(Unl,ResetBase)[p2].unf */ + SetupCartMirroring(0, 1, NULL); + + limit = 0x01; + info->Power = BMCRESETNROMXIN1Power; + info->Reset = BMCRESETNROMXIN1Reset; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +void BMCKS106C_Init(CartInfo *info) { + limit = 0x03; + info->Power = BMCRESETNROMXIN1Power; + info->Reset = BMCRESETNROMXIN1Reset; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/resettxrom.c b/src/boards/resettxrom.c new file mode 100644 index 0000000..fdf1d1b --- /dev/null +++ b/src/boards/resettxrom.c @@ -0,0 +1,57 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * 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 + */ + +/* NES 2.0 Mapper 313 is used for MMC3-based multicarts that switch + * between 128 KiB PRG-ROM/128 KiB CHR-ROM-sized games on each reset and + * thus require no additional registers. + * Its UNIF board name is BMC-RESET-TXROM. + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void M313CW(uint32 A, uint8 V) { + setchr1r(EXPREGS[0], A, V & 0x7F); +} + +static void M313PW(uint32 A, uint8 V) { + setprg8r(EXPREGS[0], A, V & 0x0F); +} + +static void M313Reset(void) { + EXPREGS[0]++; + EXPREGS[0] &= 0x03; + MMC3RegReset(); +} + +static void M313Power(void) { + EXPREGS[0] = 0; + GenMMC3Power(); +} + +/* NES 2.0 313, UNIF BMC-RESET-TXROM */ +void BMCRESETTXROM_Init(CartInfo *info) { + GenMMC3_Init(info, 512, 256, 0, 0); + cwrap = M313CW; + pwrap = M313PW; + info->Power = M313Power; + info->Reset = M313Reset; + AddExState(EXPREGS, 1, 0, "EXPR"); +} diff --git a/src/boards/vrc2and4.c b/src/boards/vrc2and4.c index 7ff7ce7..b26d804 100644 --- a/src/boards/vrc2and4.c +++ b/src/boards/vrc2and4.c @@ -158,14 +158,20 @@ static DECLFW(M23Write) { VRC24Write(A, V); } -static void M21Power(void) { +static void VRC24PowerCommon(void (*WRITEFUNC)(uint32 A, uint8 V)) { Sync(); - setprg8r(0x10, 0x6000, 0); + setprg8r(0x10, 0x6000, 0); /* Only two Goemon games are have battery backed RAM, three more shooters + * (Parodius Da!, Gradius 2 and Crisis Force uses 2k or SRAM at 6000-67FF only + */ SetReadHandler(0x6000, 0x7FFF, CartBR); SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M21Write); + SetWriteHandler(0x8000, 0xFFFF, WRITEFUNC); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M21Power(void) { + VRC24PowerCommon(M21Write); } static void M22Power(void) { @@ -176,26 +182,12 @@ static void M22Power(void) { static void M23Power(void) { big_bank = 0x20; - Sync(); - setprg8r(0x10, 0x6000, 0); /* Only two Goemon games are have battery backed RAM, three more shooters - * (Parodius Da!, Gradius 2 and Crisis Force uses 2k or SRAM at 6000-67FF only - */ - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M23Write); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + VRC24PowerCommon(M23Write); } static void M25Power(void) { big_bank = 0x20; - Sync(); - setprg8r(0x10, 0x6000, 0); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M22Write); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + VRC24PowerCommon(M22Write); } void FP_FASTAPASS(1) VRC24IRQHook(int a) { @@ -279,3 +271,99 @@ void UNLT230_Init(CartInfo *info) { info->Power = M23Power; VRC24_Init(info); } + +/* -------------------- UNL-TH2131-1 -------------------- */ +/* https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_308 + * NES 2.0 Mapper 308 is used for a bootleg version of the Sunsoft game Batman + * similar to Mapper 23 Submapper 3) with custom IRQ functionality. + * UNIF board name is UNL-TH2131-1. + */ + +static DECLFW(TH2131Write) { + switch (A & 0xF003) { + case 0xF000: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; IRQCount = 0; break; + case 0xF001: IRQa = 1; break; + case 0xF003: IRQLatch = (V & 0xF0) >> 4; break; + } +} + +void FP_FASTAPASS(1) TH2131IRQHook(int a) { + int count; + + if (!IRQa) + return; + + for (count = 0; count < a; count++) { + IRQCount++; + if ((IRQCount & 0x0FFF) == 2048) + IRQLatch--; + if (!IRQLatch && (IRQCount & 0x0FFF) < 2048) + X6502_IRQBegin(FCEU_IQEXT); + } +} + +static void TH2131Power(void) { + VRC24PowerCommon(VRC24Write); + SetWriteHandler(0xF000, 0xFFFF, TH2131Write); +} + +void UNLTH21311_Init(CartInfo *info) { + info->Power = TH2131Power; + VRC24_Init(info); + MapIRQHook = TH2131IRQHook; +} + +/* -------------------- UNL-KS7021A -------------------- */ +/* http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_525 + * NES 2.0 Mapper 525 is used for a bootleg version of versions of Contra and 月風魔伝 (Getsu Fūma Den). + * Its similar to Mapper 23 Submapper 3) with non-nibblized CHR-ROM bank registers. + */ + +static DECLFW(KS7021AWrite) { + switch (A & 0xB000) { + case 0xB000: chrreg[A & 0x07] = V; Sync(); break; + } +} + +static void KS7021APower(void) { + VRC24PowerCommon(VRC24Write); + SetWriteHandler(0xB000, 0xBFFF, KS7021AWrite); +} + +void UNLKS7021A_Init(CartInfo *info) { + info->Power = KS7021APower; + VRC24_Init(info); +} + +/* -------------------- BTL-900218 -------------------- */ +/* http://wiki.nesdev.com/w/index.php/UNIF/900218 + * NES 2.0 Mapper 524 describes the PCB used for the pirate port Lord of King or Axe of Fight. + * UNIF board name is BTL-900218. + */ + +static DECLFW(BTL900218Write) { + switch (A & 0xF00C) { + case 0xF008: IRQa = 1; break; + case 0xF00C: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; IRQCount = 0; break; + } +} + +void FP_FASTAPASS(1) BTL900218IRQHook(int a) { + if (!IRQa) + return; + + IRQCount += a; + if (IRQCount & 1024) + X6502_IRQBegin(FCEU_IQEXT); +} + +static void BTL900218Power(void) { + VRC24PowerCommon(VRC24Write); + SetWriteHandler(0xF000, 0xFFFF, BTL900218Write); +} + +void BTL900218_Init(CartInfo *info) { + info->Power = BTL900218Power; + VRC24_Init(info); + MapIRQHook = BTL900218IRQHook; +} diff --git a/src/unif.c b/src/unif.c index 8288a1e..2ff053e 100644 --- a/src/unif.c +++ b/src/unif.c @@ -473,6 +473,25 @@ static BMAPPING bmap[] = { { "WAIXING-FS005", BMCFK23C_Init, 0 }, /* https://wiki.nesdev.com/w/index.php/INES_Mapper_176 */ { "80013-B", BMC80013B_Init, 0 }, + { "TH2131-1", UNLTH21311_Init, 0 }, + { "LH51", LH51_Init, 0 }, + { "RESETNROM-XIN1", BMCRESETNROMXIN1_Init, 0 }, + { " BMC-RESET-TXROM", BMCRESETTXROM_Init, 0 }, + { "RESET-TXROM", BMCRESETTXROM_Init, 0 }, + { "K-3088", BMC411120C_Init, 0 }, + { "FARID_SLROM_8-IN-1", FARIDSLROM8IN1_Init, 0 }, + { "830425C-4391T", BMC830425C4391T_Init, 0 }, + { "TJ-03", BMCTJ03_Init, 0 }, + { "CTC-09", BMCCTC09_Init, 0 }, + { "K-3046", BMCK3046_Init, 0 }, + { "SA005-A", BMCSA005A_Init, 0 }, + { "K-3006", BMCK3006_Init, 0 }, + { "K-3036", BMCK3036_Init, 0 }, + { "MINDKIDS", MINDKIDS_Init, BMCFLAG_256KCHRR }, + { "KS7021A", UNLKS7021A_Init, 0 }, + { "KS106C", BMCKS106C_Init, 0 }, + { "900218", BTL900218_Init, 0 }, + #ifdef COPYFAMI { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, { "COPYFAMI", MapperCopyFami_Init, 0 }, diff --git a/src/unif.h b/src/unif.h index 5bb8a52..93b3df8 100644 --- a/src/unif.h +++ b/src/unif.h @@ -158,13 +158,28 @@ void UNLRT01_Init(CartInfo *info); void BMC810131C_Init(CartInfo *info); void BMC8IN1_Init(CartInfo *info); void BMC80013B_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 */ +void BMCRESETNROMXIN1_Init(CartInfo *info); +void BMCKS106C_Init(CartInfo *info); +void UNLTH21311_Init(CartInfo *info); /* m308 */ +void LH51_Init(CartInfo *info); /* m309 */ +void BMCRESETTXROM_Init(CartInfo *info); /* m313 */ +void FARIDSLROM8IN1_Init(CartInfo *info); /* m323 */ +void BMC830425C4391T_Init(CartInfo *info); /* m320 */ +void BMCTJ03_Init(CartInfo *info); /* m341 */ +void BMCCTC09_Init(CartInfo *info); /* m335 */ +void BMCK3046_Init(CartInfo *info); /* m336 */ +void BMCSA005A_Init(CartInfo *info); /* m338 */ +void BMCK3006_Init(CartInfo *info); /* m339 */ +void BMCK3036_Init(CartInfo *info); /* m340 */ +void MINDKIDS_Init(CartInfo *info); /* m268 */ +void UNLKS7021A_Init(CartInfo *info); /* m525 */ +void BTL900218_Init(CartInfo *info); /* m524 */ + #ifdef COPYFAMI void MapperCopyFamiMMC3_Init(CartInfo *info); void MapperCopyFami_Init(CartInfo *info);