diff --git a/src/boards/126-422-534.c b/src/boards/126-422-534.c new file mode 100644 index 0000000..e8d6610 --- /dev/null +++ b/src/boards/126-422-534.c @@ -0,0 +1,136 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 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 + */ + +/* Mapper 422: "Normal" version of the mapper. Represents UNIF boards BS-400R and BS-4040R. + Mapper 126: Power Joy version of the mapper, connecting CHR A18 and A19 in reverse order. + Mapper 534: Waixing version of the mapper, inverting the reload value of the MMC3 scanline counter. +*/ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reverseCHR_A18_A19; +static uint8 invertC000; +static uint8 dipSwitch; + +static void wrapPRG(uint32 A, uint8 V) { + int prgAND = EXPREGS[0] &0x40? 0x0F: 0x1F; // 128 KiB or 256 KiB inner PRG bank selection + int prgOR =(EXPREGS[0] <<4 &0x70 | EXPREGS[0] <<3 &0x180) &~prgAND; // outer PRG bank + switch(EXPREGS[3] &3) { + case 0: // MMC3 PRG mode + break; + case 1: + case 2: // NROM-128 mode: MMC3 register 6 applies throughout $8000-$FFFF, MMC3 A13 replaced with CPU A13. + V =DRegBuf[6] &~1 | A >>13 &1; + setprg8(A ^0x4000, V &prgAND | prgOR); // wrapPRG is only called with A containing the switchable banks, so we need to manually switch the normally fixed banks in this mode as well. + break; + case 3: // NROM-256 mode: MMC3 register 6 applies throughout $8000-$FFFF, MMC3 A13-14 replaced with CPU A13-14. + V =DRegBuf[6] &~3 | A >>13 &3; + setprg8(A ^0x4000, (V ^2) &prgAND | prgOR); // wrapPRG is only called with A containing the switchable banks, so we need to manually switch the normally fixed banks in this mode as well. + break; + } + setprg8(A, V &prgAND | prgOR); +} + +static void wrapCHR(uint32 A, uint8 V) { + int chrAND = EXPREGS[0] &0x80? 0x7F: 0xFF; // 128 KiB or 256 KiB innter CHR bank selection + int chrOR; // outer CHR bank + if (reverseCHR_A18_A19) // Mapper 126 swaps CHR A18 and A19 + chrOR =(EXPREGS[0] <<4 &0x080 | EXPREGS[0] <<3 &0x100 | EXPREGS[0] <<5 &0x200) &~chrAND; + else + chrOR =EXPREGS[0] <<4 &0x380 &~chrAND; + + if (EXPREGS[3] &0x10) // CNROM mode: 8 KiB inner CHR bank comes from outer bank register #2 + setchr8(EXPREGS[2] &(chrAND >>3) | chrOR >>3); + else // MMC3 CHR mode + setchr1(A, (V & chrAND) | chrOR); +} + +static DECLFW(writeWRAM) { + if (~EXPREGS[3] &0x80) { + // Lock bit clear: Update any outer bank register + EXPREGS[A &3] =V; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } else + if ((A &3) ==2) { + // Lock bit set: Only update the bottom one or two bits of the CNROM bank + int latchMask =EXPREGS[2] &0x10? 1: 3; // 16 or 32 KiB inner CHR bank selection + EXPREGS[2] &=~latchMask; + EXPREGS[2] |= V &latchMask; + FixMMC3CHR(MMC3_cmd); + } + CartBW(A, V); +} + +static DECLFR(readDIP) { + uint8 result =CartBR(A); + if (EXPREGS[1] &1) result =result &~3 | dipSwitch &3; // Replace bottom two bits with solder pad or DIP switch setting if so selected + return result; +} + +static DECLFW(writeIRQ) { + MMC3_IRQWrite(A, V ^0xFF); +} + +static void reset(void) { + dipSwitch++; // Soft-resetting cycles through solder pad or DIP switch settings + EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; + MMC3RegReset(); +} + +static void power(void) { + dipSwitch =0; + EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; + GenMMC3Power(); + SetWriteHandler(0x6000, 0x7FFF, writeWRAM); + SetReadHandler(0x8000, 0xFFFF, readDIP); + if (invertC000) SetWriteHandler(0xC000, 0xDFFF, writeIRQ); // Mapper 534 inverts the MMC3 scanline counter reload value +} + +static void init(CartInfo *info) { + GenMMC3_Init(info, 512, 256, 8, info->battery); + cwrap = wrapCHR; + pwrap = wrapPRG; + + info->Power = power; + info->Reset = reset; + + AddExState(EXPREGS, 4, 0, "EXPR"); + AddExState(&dipSwitch, 1, 0, "DPSW"); +} + +void Mapper126_Init(CartInfo *info) { + reverseCHR_A18_A19 = 1; + invertC000 = 0; + init(info); +} + +void Mapper422_Init(CartInfo *info) { + reverseCHR_A18_A19 = 0; + invertC000 = 0; + init(info); +} + +void Mapper534_Init(CartInfo *info) { + reverseCHR_A18_A19 = 0; + invertC000 = 1; + init(info); +} diff --git a/src/boards/126.c b/src/boards/126.c deleted file mode 100644 index 0a93910..0000000 --- a/src/boards/126.c +++ /dev/null @@ -1,105 +0,0 @@ -/* 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 - */ - -/* Mapper 126, PowerJoy 84-in-1 Multicart (PJ-008*/ -/* reference from nestopia since not available in nesdev */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint16 GetExChrExBank() { - uint16 bank = (uint16)EXPREGS[0]; - return ((~bank << 0 & 0x080 & ((uint16)EXPREGS[2])) | (bank << 4 & 0x080 & bank) | - (bank << 3 & 0x100) | (bank << 5 & 0x200)); -} - -static void UpdateChrBank(void) { - uint16 bank = (uint16)EXPREGS[2] & 0x0F; - bank |= GetExChrExBank() >> 3; - setchr8(bank); -} - -static void M126CW(uint32 A, uint8 V) { - if (!(EXPREGS[3] & 0x10)) { - uint16 bank = (uint16)V & (((uint16)EXPREGS[0] & 0x80) - 1); - bank |= GetExChrExBank(); - setchr1(A, bank); - } -} - -static void M126PW(uint32 A, uint8 V) { - uint16 bank = (uint16)V; - uint16 preg = (uint16)EXPREGS[0]; - bank &= ((~preg >> 2) & 0x10) | 0x0F; - bank |= ((preg & (0x06 | (preg & 0x40) >> 6)) << 4) | ((preg & 0x10) << 3); - if (!(EXPREGS[3] & 0x03)) - setprg8(A, bank); - else if ((A - 0x8000) == ((MMC3_cmd << 8) & 0x4000)) { /* TODO: Clean this */ - if ((EXPREGS[3] & 0x3) == 0x3) - setprg32(0x8000, (bank >> 2)); - else { - setprg16(0x8000, (bank >> 1)); - setprg16(0xc000, (bank >> 1)); - } - } -} - -static DECLFW(M126Write) { - A &= 0x03; - if(A == 0x01 || A == 0x02 || ((A == 0x00 || A == 0x03) && !(EXPREGS[3] & 0x80))) { - if (EXPREGS[A] != V) { - EXPREGS[A] = V; - if (EXPREGS[3] & 0x10) - UpdateChrBank(); - else - FixMMC3CHR(MMC3_cmd); - FixMMC3PRG(MMC3_cmd); - } - } -} - -void M126StateRestore(int v) { - FixMMC3CHR(MMC3_cmd); - FixMMC3PRG(MMC3_cmd); - - if (EXPREGS[3] & 0x10) - UpdateChrBank(); -} - -static void M126Reset(void) { - EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; - MMC3RegReset(); -} - -static void M126Power(void) { - EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; - GenMMC3Power(); - SetWriteHandler(0x6000, 0x7FFF, M126Write); -} - -void Mapper126_Init(CartInfo *info) { - GenMMC3_Init(info, 2048, 1023, 0, 0); - cwrap = M126CW; - pwrap = M126PW; - info->Power = M126Power; - info->Reset = M126Reset; - GameStateRestore = M126StateRestore; - AddExState(EXPREGS, 4, 0, "EXPR"); -} diff --git a/src/boards/534.c b/src/boards/534.c deleted file mode 100644 index 8c8bb9d..0000000 --- a/src/boards/534.c +++ /dev/null @@ -1,89 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2020 negativeExponent - * - * 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 534 - 2-in-1 数独/五子棋 (Sudoku/Gomoku, NJ064) */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint32 GetPRGBank(uint32 bank) -{ - if (~bank & 1 && (MMC3_cmd & 0x40)) bank ^= 2; - return (bank & 2) ? (0xFE | (bank & 1)) : DRegBuf[6 | (bank & 1)]; -} - -void SyncPRG_GNROM(int A14, int AND, int OR) { - setprg8(0x8000, ((GetPRGBank(0) & ~A14) & AND) | OR); - setprg8(0xA000, ((GetPRGBank(1) & ~A14) & AND) | OR); - setprg8(0xC000, ((GetPRGBank(0) | A14) & AND) | OR); - setprg8(0xE000, ((GetPRGBank(1) | A14) & AND) | OR); -} - -static void M534PW(uint32 A, uint8 V) { - if (EXPREGS[0] & 0x40) - SyncPRG_GNROM(EXPREGS[3] & 0x02, 0x0F, ((EXPREGS[0] & 3) << 4)); - else - setprg8(A, (V & 0x1F) | ((EXPREGS[0] & 0x2) << 4)); -} - -static void M534CW(uint32 A, uint8 V) { - setchr1(A, (V & 0xFF) | ((EXPREGS[2] & 0x0F) << 3) | ((EXPREGS[0] & 0x18) << 4)); -} - -static DECLFW(M534IRQWrite) { - MMC3_IRQWrite(0xC000 | (A & 1), V ^ 0xFF); -} - -static DECLFW(M534WriteLo) { - if ((A & 0x800) && (!(EXPREGS[3] & 0x80) || (A & 3) == 2)) { - EXPREGS[A & 3] = V; - FixMMC3CHR(MMC3_cmd); - FixMMC3PRG(MMC3_cmd); - } -} - -static void M534Power(void) { - EXPREGS[0] = 0x00; - EXPREGS[1] = 0x00; - EXPREGS[2] = 0x00; - EXPREGS[3] = 0x00; - GenMMC3Power(); - SetWriteHandler(0x6000, 0x6FFF, M534WriteLo); - SetWriteHandler(0xC000, 0xDFFF, M534IRQWrite); -} - -static void M534Reset(void) { - EXPREGS[0] = 0x00; - EXPREGS[1] = 0x00; - EXPREGS[2] = 0x00; - EXPREGS[3] = 0x00; - EXPREGS[4] = (EXPREGS[4] + 1) & 7; - FCEU_printf("dipswitch = %d\n", EXPREGS[4]); - MMC3RegReset(); -} - -void Mapper534_Init(CartInfo *info) { - GenMMC3_Init(info, 512, 512, 0, 0); - pwrap = M534PW; - cwrap = M534CW; - info->Power = M534Power; - info->Reset = M534Reset; - AddExState(EXPREGS, 5, 0, "EXPR"); -} diff --git a/src/boards/bs4xxxr.c b/src/boards/bs4xxxr.c deleted file mode 100644 index a844007..0000000 --- a/src/boards/bs4xxxr.c +++ /dev/null @@ -1,156 +0,0 @@ -/* FCE Ultra - 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 - */ - -/* originally submitted by dragon2snow - * Known carts: - * UNIF BMC-BS-400R : 700000-in-1 (BS-400R)(Unl), PRG 1024K CHR 1024K CRC 0x5DBDFAA0 - * UNIF BMC-BS-4040R : Double Dragon 310000-in-1 (4040R) PRG 512 CHR 512 CRC 0x3A642F31 - * - * FIXME: Future Kids notes - * Either something is wrong or missing because chr banks for the game is $E8 - EB - * but game uses $EC-EF here. These are chr banks for the next game and does not masked properly - * by mapper code. - * ~ c@2020 - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 pointer; -static uint8 offset; - -static int getPRGBankBS4XXXR(int bank) -{ - if (((~bank) & 1) && (pointer & 0x40)) bank ^= 2; - return ((bank & 2) ? 0xFE | (bank & 1) : DRegBuf[6 | (bank & 1)]); -} - -static void BS4XXXRPW(uint32 A, uint8 V) -{ - if ((EXPREGS[3] >> 4) & 1) { - uint8 prgAND = ((EXPREGS[0] >> 1) & 1) ? 0x0F : 0x0F; - uint8 prgOR = (EXPREGS[0] & 7) << 4; - uint8 bank0 = getPRGBankBS4XXXR(0); - uint8 bank1 = getPRGBankBS4XXXR(1); - /* 16K Mode */ - if (!((EXPREGS[3] >>1 )& 0x1)) { - setprg8(0x8000, (bank0 & prgAND) | prgOR); - setprg8(0xA000, (bank1 & prgAND) | prgOR); - setprg8(0xC000, (bank0 & prgAND) | prgOR); - setprg8(0xE000, (bank1 & prgAND) | prgOR); - } - /* 32K Mode */ - else { - setprg8(0x8000, (bank0 & prgAND) | prgOR); - setprg8(0xA000, (bank1 & prgAND) | prgOR); - setprg8(0xC000, ((bank0 | 2) & prgAND) | prgOR); - setprg8(0xE000, ((bank1 | 2) & prgAND) | prgOR); - } - } - /* Mmc3 Mode */ - else { - uint8 prgAND = ((EXPREGS[0] >> offset) & 1) ? 0x0F : 0x1F; /* 4040R 6,400R 1 */ - uint8 prgOR = (EXPREGS[0] & 7) << 4; - setprg8(A, (V & prgAND) | prgOR); - } -} - -static void BS4XXXRCW(uint32 A, uint8 V) { - if ((EXPREGS[3] >> 4) & 1) { - uint8 chrAND = ((EXPREGS[0] >> 1) & 1) ? 0x0F : 0x0F; - uint8 chrOR = ((EXPREGS[0] >> 3) & 7) << 4; - /* FIXME: Ugly hack for Future Kids */ - if (EXPREGS[4]) { - chrAND = 0x03; - chrOR |= 8; - } - setchr8((EXPREGS[2] & chrAND) | chrOR); - } else { - uint8 chrAND = ((EXPREGS[0] >> 1) & 1) ? 0xFF : 0xFF; - uint16 chrOR = ((EXPREGS[0] >> 3) & 7) << 7; - setchr1(A, (V & chrAND) | chrOR); - } -} - -static DECLFW(BS4XXXRHiWrite) { - /* FCEU_printf("Wr8B: A:%04x V:%02x\n", A, V); */ - if (A == 0x8000) - pointer = MMC3_cmd ^ V; - MMC3_CMDWrite(A, V); -} - -static DECLFW(BS4XXXRLoWrite) { - /* FCEU_printf("WrLo: A:%04x V:%02x\n", A, V); */ - if (A & 0x800) { - /* Future Kids hack */ - if (!EXPREGS[4]) { - if ((((A & 3) == 2) && (V == 0xE8))) - EXPREGS[4] = 1; - } - if (!(EXPREGS[3] & 0x80)) { - EXPREGS[A & 0x03] = V; - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); - } - else if (EXPREGS[3] & 0x10) { - EXPREGS[A & 0x03] = V; - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); - } - } - CartBW(A, V); -} - -static void BS4XXXRReset(void) { - EXPREGS[4] = 0; - EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; - MMC3RegReset(); -} - -static void BS4XXXRPower(void) { - EXPREGS[4] = 0; - EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; - GenMMC3Power(); - SetWriteHandler(0x6000, 0x7FFF, BS4XXXRLoWrite); - SetWriteHandler(0x8000, 0xBFFF, BS4XXXRHiWrite); -} - -void BS4XXXR_Init(CartInfo *info) { - GenMMC3_Init(info, 512, 256, 8, 0); - cwrap = BS4XXXRCW; - pwrap = BS4XXXRPW; - - info->Power = BS4XXXRPower; - info->Reset = BS4XXXRReset; - - AddExState(EXPREGS, 4, 0, "EXPR"); - AddExState(&pointer, 1, 0, "PNTR"); - AddExState(&offset, 1, 0, "OFFS"); -} - -void BS400R_Init(CartInfo *info) { - offset = 1; - BS4XXXR_Init(info); -} - -void BS4040R_Init(CartInfo *info) { - offset = 6; - BS4XXXR_Init(info); -} diff --git a/src/ines.c b/src/ines.c index 69dabaf..231b846 100644 --- a/src/ines.c +++ b/src/ines.c @@ -699,6 +699,7 @@ INES_BOARD_BEGIN() INES_BOARD( "Realtec 8210", 395, Mapper395_Init ) INES_BOARD( "BMC Super 19-in-1 (VIP19)", 401, Mapper401_Init ) INES_BOARD( "A88S-1", 411, Mapper411_Init ) + INES_BOARD( "BS-400R/BS-4040", 422, Mapper422_Init ) INES_BOARD( "Brilliant Com Cocoma Pack", 516, Mapper516_Init ) INES_BOARD( "Sachen 3014", 533, Mapper533_Init ) INES_BOARD( "NJ064", 534, Mapper534_Init ) diff --git a/src/ines.h b/src/ines.h index b1ce41c..99e4756 100644 --- a/src/ines.h +++ b/src/ines.h @@ -271,6 +271,7 @@ void Mapper390_Init(CartInfo *); void Mapper395_Init(CartInfo *); void Mapper401_Init(CartInfo *); void Mapper411_Init(CartInfo *); +void Mapper422_Init(CartInfo *); void Mapper516_Init(CartInfo *); void Mapper533_Init(CartInfo *); void Mapper534_Init(CartInfo *); diff --git a/src/unif.c b/src/unif.c index fd7a642..2d1bfe4 100644 --- a/src/unif.c +++ b/src/unif.c @@ -616,8 +616,8 @@ static BMAPPING bmap[] = { { "82112C", 540, Mapper540_Init, 0 }, { "N49C-300", 369, Mapper369_Init, 0 }, - { "BS-400R", NO_INES, BS400R_Init, 0 }, - { "BS-4040R", NO_INES, BS4040R_Init, 0 }, + { "BS-400R", 422, Mapper422_Init, 0 }, + { "BS-4040R", 422, Mapper422_Init, 0 }, #ifdef COPYFAMI { "COPYFAMI_MMC3", NO_INES, MapperCopyFamiMMC3_Init, 0 }, diff --git a/src/unif.h b/src/unif.h index 3b2cbe3..0dbd4ab 100644 --- a/src/unif.h +++ b/src/unif.h @@ -196,8 +196,7 @@ void AbG1l_Init(CartInfo *info); void KG256_Init(CartInfo *info); void WAIXINGFS005_Init(CartInfo *info); -void BS4040R_Init(CartInfo *info); -void BS400R_Init(CartInfo *info); +void Mapper422_Init(CartInfo *info); #ifdef COPYFAMI void MapperCopyFamiMMC3_Init(CartInfo *info);