From 91509603264ca2f39b8c6cfd217272996b3a04e3 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Sat, 1 Feb 2020 09:33:44 +0800 Subject: [PATCH 01/13] Add mappers 360, 533 --- src/boards/360.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ src/boards/533.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 2 ++ src/ines.h | 2 ++ 4 files changed, 137 insertions(+) create mode 100644 src/boards/360.c create mode 100644 src/boards/533.c diff --git a/src/boards/360.c b/src/boards/360.c new file mode 100644 index 0000000..2c6609c --- /dev/null +++ b/src/boards/360.c @@ -0,0 +1,67 @@ +/* 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 360 - Bit Corp's 31-in-1 multicart (3150) */ + +#include "mapinc.h" + +static uint8 dipswitch; + +static SFORMAT StateRegs[] = +{ + { &dipswitch, 1, "DPSW" }, + { 0 } +}; + +static void Sync(void) { + /* dip 0 and 1 is the same game SMB) */ + if (dipswitch < 2) + setprg32(0x8000, dipswitch >> 1); + else { + setprg16(0x8000, dipswitch); + setprg16(0xC000, dipswitch); + } + setchr8(dipswitch); + setmirror(((dipswitch & 0x10) >> 4) ^ 1); +} + +static void M360Power(void) { + dipswitch = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0XFFFF, CartBW); +} + +static void M360Reset(void) { + dipswitch = (dipswitch + 1) & 31; + Sync(); + FCEU_printf("dipswitch = %d\n", dipswitch); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper360_Init(CartInfo *info) { + info->Reset = M360Reset; + info->Power = M360Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/533.c b/src/boards/533.c new file mode 100644 index 0000000..664b547 --- /dev/null +++ b/src/boards/533.c @@ -0,0 +1,66 @@ +/* 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 533 is used for the Sachen 3014 board, used for the game + * 動動腦 II: 國中英文(一) (Dòngdòngnǎo II: Guózhōng Yīngwén (I), + * also known as Middle School English II, SA-003). + * It's a CNROM-like board with the added ability to read back + * the latch content for protection purposes. + */ + +#include "mapinc.h" + +static uint8 latche; + +static SFORMAT StateRegs[] = { + { &latche, 1, "LATC" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, 0); + setchr8((latche >> 4) & 1); +} + +static DECLFR(M533Read) { + return ((PRGptr[0][A] & 0xF0) | (latche >> 4)); +} + +static DECLFW(M533Write) { + latche = (V & CartBR(A)); + Sync(); +} + +static void M533Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBROB); + SetReadHandler(0xE000, 0xEFFF, M533Read); + SetWriteHandler(0x8000, 0xFFFF, M533Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper533_Init(CartInfo* info) { + info->Power = M533Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/ines.c b/src/ines.c index d3d9ae7..3917ba5 100644 --- a/src/ines.c +++ b/src/ines.c @@ -671,6 +671,8 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"8-in-1 JY-119", 267, Mapper267_Init }, {(uint8_t*)"MMC3 BMC PIRATE", 294, Bs5652_Init}, /* nesdev redirects this as mapper 134 */ {(uint8_t*)"TXC 01-22110-000", 297, Mapper297_Init}, + {(uint8_t*)"Bitcorp 31-in-1", 360, Mapper360_Init}, + {(uint8_t*)"Sachen 3014", 533, Mapper533_Init}, /* UNIF to NES 2.0 BOARDS */ diff --git a/src/ines.h b/src/ines.h index 871216d..a9c5942 100644 --- a/src/ines.h +++ b/src/ines.h @@ -247,10 +247,12 @@ void Mapper267_Init(CartInfo *); void Mapper288_Init(CartInfo *); void Mapper297_Init(CartInfo *); void Mapper357_Init(CartInfo *); +void Mapper360_Init(CartInfo *); void Mapper372_Init(CartInfo *); void Mapper374_Init(CartInfo *); void Mapper381_Init(CartInfo *); void Mapper390_Init(CartInfo *); +void Mapper533_Init(CartInfo *); void Mapper538_Init(CartInfo *); void Mapper541_Init(CartInfo *); From 3f1544c129b9e59527c2f3b9539b2fc3daefecd7 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Sat, 1 Feb 2020 23:41:28 +0800 Subject: [PATCH 02/13] Update mapper 45 - fix starting register value - fix memory write range to 0x6000-0xffff --- src/boards/mmc3.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/boards/mmc3.c b/src/boards/mmc3.c index 5c498fc..b2d06dd 100644 --- a/src/boards/mmc3.c +++ b/src/boards/mmc3.c @@ -540,7 +540,8 @@ static DECLFR(M45Read) { } static void M45Reset(void) { - EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = EXPREGS[4] = 0; + EXPREGS[0] = EXPREGS[1] = EXPREGS[3] = EXPREGS[4] = 0; + EXPREGS[2] = 0x0F; EXPREGS[5]++; EXPREGS[5] &= 7; MMC3RegReset(); @@ -548,8 +549,9 @@ static void M45Reset(void) { static void M45Power(void) { GenMMC3Power(); - EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = EXPREGS[4] = EXPREGS[5] = 0; - SetWriteHandler(0x5000, 0x7FFF, M45Write); + EXPREGS[0] = EXPREGS[1] = EXPREGS[3] = EXPREGS[4] = EXPREGS[5] = 0; + EXPREGS[2] = 0x0F; + SetWriteHandler(0x6000, 0x7FFF, M45Write); SetReadHandler(0x5000, 0x5FFF, M45Read); } From 43ca4755bb072057049d873dbe5fe857bd252bce Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Mon, 3 Feb 2020 15:35:24 +0800 Subject: [PATCH 03/13] Update mapper 150/243 (unif UNL-Sachen-74LS374N) --- src/boards/sachen.c | 92 +++++++++++++++++++++++++++++++++++++++++++-- src/ines.c | 4 +- src/unif.c | 2 +- 3 files changed, 92 insertions(+), 6 deletions(-) diff --git a/src/boards/sachen.c b/src/boards/sachen.c index db5e63d..bc79786 100644 --- a/src/boards/sachen.c +++ b/src/boards/sachen.c @@ -2,6 +2,7 @@ * * Copyright notice for this file: * Copyright (C) 2002 Xodnizel + * 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 @@ -18,10 +19,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +/* 2020-2-3 - updated mapper 150/243 */ + #include "mapinc.h" static uint8 cmd, dip; static uint8 latch[8]; +static uint8 mapperNum; static void S74LS374MSync(uint8 mirr) { switch (mirr & 3) { @@ -32,7 +36,8 @@ static void S74LS374MSync(uint8 mirr) { } } -static void S74LS374NSynco(void) { +/* old mapper 150 and 243 */ +/* static void S74LS374NSynco(void) { setprg32(0x8000, latch[0]); setchr8(latch[1] | latch[3] | latch[4]); S74LS374MSync(latch[2]); @@ -57,7 +62,7 @@ static DECLFW(S74LS374NWrite) { static DECLFR(S74LS374NRead) { uint8 ret; if ((A & 0x4100) == 0x4100) -/* ret=(X.DB&0xC0)|((~cmd)&0x3F); */ +// ret=(X.DB&0xC0)|((~cmd)&0x3F); ret = ((~cmd) & 0x3F) ^ dip; else ret = X.DB; @@ -128,7 +133,7 @@ void S74LS374NA_Init(CartInfo *info) { GameStateRestore = S74LS374NRestore; AddExState(latch, 5, 0, "LATC"); AddExState(&cmd, 1, 0, "CMD"); -} +}*/ static int type; static void S8259Synco(void) { @@ -407,3 +412,84 @@ void TCA01_Init(CartInfo *info) { info->Power = TCA01Power; } +/* ------------------ Mapper 150 --------------------- */ +/* ------------------ Mapper 243 --------------------- */ + +/* Mapper 150 - SA-015 / SA-630 / Unif UNL-Sachen-74LS374N */ +/* Mapper 243 - SA-020A */ + +static void S74LS374NSynco(void) { + uint32 chrBank; + if (mapperNum == 150) + chrBank = (latch[6] & 3) | ((latch[4] << 2) & 4) | (latch[2] << 3); + else + chrBank = (latch[2] & 1) | ((latch[4] << 1) & 2) | (latch[6] << 2); + + setprg32(0x8000, (latch[2] & 1) | latch[5]); + setchr8(chrBank); + + switch ((latch[7] >> 1) & 3) { + case 0: setmirrorw(0, 1, 1, 1); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_V); break; + case 3: setmirror(MI_0); break; + } +} + +static DECLFR(S74LS374NRead) { + uint8 ret; + if ((A & 0xC101) == 0x4101) { + if (dip & 1) + ret = (latch[cmd] & 3) | (X.DB & 0xFC); + else + ret = (latch[cmd] & 7) | (X.DB & 0xF8); + } else { + ret = X.DB; + } + return ret; +} + +static DECLFW(S74LS374NWrite) { + if (dip & 1) + V |= 4; + switch (A & 0xC101) { + case 0x4100: + cmd = V & 7; + break; + case 0x4101: + latch[cmd] = V & 7; + S74LS374NSynco(); + break; + } +} + +static void S74LS374NRestore(int version) { + S74LS374NSynco(); +} + +static void S74LS374NReset(void) { + dip ^= 1; + latch[0] = latch[1] = latch[2] = latch[3] = 0; + latch[4] = latch[5] = latch[6] = latch[7] = 0; + S74LS374NSynco(); +} + +static void S74LS374NPower(void) { + dip = 0; + latch[0] = latch[1] = latch[2] = latch[3] = 0; + latch[4] = latch[5] = latch[6] = latch[7] = 0; + S74LS374NSynco(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x4100, 0x7FFF, S74LS374NWrite); + if (mapperNum == 150) + SetReadHandler(0x4100, 0x7FFF, S74LS374NRead); +} + +void S74LS374N_Init(CartInfo *info) { + mapperNum = info->mapper; + info->Power = S74LS374NPower; + info->Reset = S74LS374NReset; + GameStateRestore = S74LS374NRestore; + AddExState(latch, 8, 0, "LATC"); + AddExState(&cmd, 1, 0, "CMD"); +} diff --git a/src/ines.c b/src/ines.c index 3917ba5..aa552ee 100644 --- a/src/ines.c +++ b/src/ines.c @@ -545,7 +545,7 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"TCU01", 147, TCU01_Init}, {(uint8_t*)"SA0037", 148, SA0037_Init}, {(uint8_t*)"SA0036", 149, SA0036_Init}, - {(uint8_t*)"S74LS374N", 150, S74LS374N_Init}, + {(uint8_t*)"SA-015/SA-630", 150, S74LS374N_Init}, {(uint8_t*)"", 151, Mapper151_Init}, {(uint8_t*)"", 152, Mapper152_Init}, {(uint8_t*)"BANDAI SRAM", 153, Mapper153_Init}, /* Bandai board 16 with SRAM instead of EEPROM */ @@ -638,7 +638,7 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"", 240, Mapper240_Init}, {(uint8_t*)"", 241, Mapper241_Init}, {(uint8_t*)"", 242, Mapper242_Init}, - {(uint8_t*)"S74LS374NA", 243, S74LS374NA_Init}, + {(uint8_t*)"SA-020A", 243, S74LS374N_Init}, {(uint8_t*)"DECATHLON", 244, Mapper244_Init}, {(uint8_t*)"", 245, Mapper245_Init}, {(uint8_t*)"FONG SHEN BANG", 246, Mapper246_Init}, diff --git a/src/unif.c b/src/unif.c index 6d5e666..37917e0 100644 --- a/src/unif.c +++ b/src/unif.c @@ -520,7 +520,7 @@ static BMAPPING bmap[] = { { "SSS-NROM-256", NO_INES, SSSNROM_Init, 0 }, { "SUNSOFT_UNROM", 93, SUNSOFT_UNROM_Init, 0 }, /* fix me, real pcb name, real pcb type */ { "Sachen-74LS374N", 150, S74LS374N_Init, 0 }, - { "Sachen-74LS374NA", 243, S74LS374NA_Init, 0 }, /* seems to be custom mapper */ + { "Sachen-74LS374NA", 243, S74LS374N_Init, 0 }, /* seems to be custom mapper */ { "Sachen-8259A", 141, S8259A_Init, 0 }, { "Sachen-8259B", 138, S8259B_Init, 0 }, { "Sachen-8259C", 139, S8259C_Init, 0 }, From 7ba33509005ca8066a105be185519a7772e98fcb Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Wed, 5 Feb 2020 12:00:54 +0800 Subject: [PATCH 04/13] Add mappers 382, 534, 539 --- src/boards/382.c | 98 +++++++++++++++++++++++++++++++++++++++++++++ src/boards/534.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++ src/boards/539.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 7 +++- src/ines.h | 3 ++ 5 files changed, 306 insertions(+), 2 deletions(-) create mode 100644 src/boards/382.c create mode 100644 src/boards/534.c create mode 100644 src/boards/539.c diff --git a/src/boards/382.c b/src/boards/382.c new file mode 100644 index 0000000..b0db885 --- /dev/null +++ b/src/boards/382.c @@ -0,0 +1,98 @@ +/* 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 382 - denotes the 830928C circuit board, + * used on a 512 KiB 5-in-1 and a 1 MiB 9-in-1 multicart containing + * the BNROM game Journey to the West and Capcom/Konami UNROM games. + */ + +#include "mapinc.h" + +static uint8 preg[2]; +static uint8 mode; +static uint8 mirr; +static uint8 lock; + +static SFORMAT StateRegs[] = { + { &preg[0], 1, "PRG0" }, + { &preg[1], 1, "PRG1" }, + { &mode, 1, "MODE" }, + { &mirr, 1, "MIRR" }, + { &lock, 1, "LOCK" }, + { 0 } +}; + +static void Sync(void) { + switch (mode) { + case 1: + /* bnrom */ + setprg32(0x8000, (preg[1] << 2) | (preg[0] & 3)); + break; + default: + /* unrom */ + setprg16(0x8000, (preg[1] << 3) | (preg[0] & 7)); + setprg16(0xC000, (preg[1] << 3) | 7); + break; + } + setchr8(0); + setmirror(mirr ^ 1); + /* FCEU_printf("inB[0]:%02x outB[1]:%02x mode:%02x mirr:%02x lock:%02x\n", preg[0], preg[1], mode, mirr, lock); */ +} + +static DECLFW(M382Write) { + if (!lock) { + preg[1] = (A & 0x07); + mode = (A & 0x08) >> 3; + mirr = (A & 0x10) >> 4; + lock = (A & 0x20) >> 5; + } + /* inner bank subject to bus conflicts */ + preg[0] = V & CartBR(A); + Sync(); +} + +static void M382Power(void) { + preg[0] = preg[1] = 0; + mode = 0; + mirr = 0; + lock = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M382Write); +} + +static void M382Reset(void) { + preg[1] = 0; + mode = 0; + mirr = 0; + lock = 0; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper382_Init(CartInfo* info) { + info->Power = M382Power; + info->Reset = M382Reset; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/534.c b/src/boards/534.c new file mode 100644 index 0000000..08e9096 --- /dev/null +++ b/src/boards/534.c @@ -0,0 +1,99 @@ +/* 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 DECLFR(M534Read) { + if (EXPREGS[1] & 0x01) + return (EXPREGS[4] | (X.DB & ~0x03)); + else + return CartBR(A); +} + +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(); +} +static void M534Close(void) { +} + +void Mapper534_Init(CartInfo *info) { + GenMMC3_Init(info, 512, 512, 0, 0); + pwrap = M534PW; + cwrap = M534CW; + info->Power = M534Power; + info->Reset = M534Reset; + info->Close = M534Close; + AddExState(EXPREGS, 5, 0, "EXPR"); +} diff --git a/src/boards/539.c b/src/boards/539.c new file mode 100644 index 0000000..09edd7f --- /dev/null +++ b/src/boards/539.c @@ -0,0 +1,101 @@ +/* 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. + */ + +#include "mapinc.h" + +static uint8 preg; +static uint8 mirr; +static uint8 WRAM[8192]; + +static SFORMAT StateRegs[] = +{ + { &preg, 1, "PREG" }, + { &mirr, 1, "MIRR" } +}; + +static uint32 GetWRAMAddress(uint32 A) { + return ((A & 0x1FFF) | + ((A < 0xC000) ? 0x1000 : 0x0000) | + ((A < 0x8000) ? 0x0800 : 0x000)); +} + +static void Sync(void) { + setprg8(0x6000, 13); + setprg8(0x8000, 12); + setprg8(0xA000, preg); + setprg8(0xC000, 14); + setprg8(0xE000, 15); + setchr8(0); + setmirror(((mirr & 8) >> 3) ^ 1); +} + +static DECLFR(M539Read) { + switch (A >> 8) { + case 0x60: case 0x62: case 0x64: case 0x65: case 0x82: case 0xC0: case 0xC1: case 0xC2: + case 0xC3: case 0xC4: case 0xC5: case 0xC6: case 0xC7: case 0xC8: case 0xC9: case 0xCA: + case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF: case 0xD0: case 0xD1: case 0xDF: + return WRAM[GetWRAMAddress(A)]; + default: + return CartBR(A); + } +} + +static DECLFW(M539Write) { + switch (A >> 8) { + case 0x60: case 0x62: case 0x64: case 0x65: case 0x82: case 0xC0: case 0xC1: case 0xC2: + case 0xC3: case 0xC4: case 0xC5: case 0xC6: case 0xC7: case 0xC8: case 0xC9: case 0xCA: + case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF: case 0xD0: case 0xD1: case 0xDF: + WRAM[GetWRAMAddress(A)] = V; + break; + default: + switch (A & 0xF000) { + case 0xA000: + preg = V; + Sync(); + break; + case 0xF000: + if ((A & 0x25) == 0x25) { + mirr = V; + Sync(); + } + break; + } + break; + } +} + +static void M539Power(void) { + preg = 0; + mirr = 0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, M539Read); + SetWriteHandler(0x6000, 0xFFFF, M539Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper539_Init(CartInfo *info) { + info->Power = M539Power; + GameStateRestore = StateRestore; + AddExState(WRAM, 8192, 0, "WRAM"); + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/ines.c b/src/ines.c index aa552ee..f0b8b07 100644 --- a/src/ines.c +++ b/src/ines.c @@ -668,11 +668,14 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"Realtec 8031", 390, Mapper390_Init }, {(uint8_t*)"60-1064-16L (FDS)", 538, Mapper538_Init }, {(uint8_t*)"LittleCom 160-in-1", 541, Mapper541_Init }, - {(uint8_t*)"8-in-1 JY-119", 267, Mapper267_Init }, + {(uint8_t*)"8-in-1 JY-119", 267, Mapper267_Init }, {(uint8_t*)"MMC3 BMC PIRATE", 294, Bs5652_Init}, /* nesdev redirects this as mapper 134 */ {(uint8_t*)"TXC 01-22110-000", 297, Mapper297_Init}, {(uint8_t*)"Bitcorp 31-in-1", 360, Mapper360_Init}, - {(uint8_t*)"Sachen 3014", 533, Mapper533_Init}, + {(uint8_t*)"Sachen 3014", 533, Mapper533_Init}, + {(uint8_t*)"830928C", 382, Mapper382_Init}, + {(uint8_t*)"NJ064", 534, Mapper534_Init}, + {(uint8_t*)"Kid Ikarus (FDS)", 539, Mapper539_Init}, /* UNIF to NES 2.0 BOARDS */ diff --git a/src/ines.h b/src/ines.h index a9c5942..997a8ef 100644 --- a/src/ines.h +++ b/src/ines.h @@ -250,10 +250,13 @@ void Mapper357_Init(CartInfo *); void Mapper360_Init(CartInfo *); void Mapper372_Init(CartInfo *); void Mapper374_Init(CartInfo *); +void Mapper382_Init(CartInfo *); void Mapper381_Init(CartInfo *); void Mapper390_Init(CartInfo *); void Mapper533_Init(CartInfo *); +void Mapper534_Init(CartInfo *); void Mapper538_Init(CartInfo *); +void Mapper539_Init(CartInfo *); void Mapper541_Init(CartInfo *); #endif From cfe11b9b95f049d12b20ee72500404e7970ed9b3 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Thu, 6 Feb 2020 12:53:26 +0800 Subject: [PATCH 05/13] MMC1: Better work ram and battery saves support for size greater than 8K --- src/boards/mmc1.c | 123 +++++++++++++++++++++++++++------------------- src/ines.c | 1 + src/ines.h | 1 + 3 files changed, 75 insertions(+), 50 deletions(-) diff --git a/src/boards/mmc1.c b/src/boards/mmc1.c index a3f670d..48752c0 100644 --- a/src/boards/mmc1.c +++ b/src/boards/mmc1.c @@ -22,12 +22,17 @@ #include "mapinc.h" static void GenMMC1Power(void); -static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery); +static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int saveram); static uint8 DRegs[4]; static uint8 Buffer, BufferShift; -static int mmc1opts; +static uint32 WRAMSIZE = 0; + + /* size of non-battery-backed portion of WRAM */ + /* serves as starting offset for actual save ram from total wram size */ + /* returns 0 if entire work ram is battery backed ram */ +static uint32 NONSaveRAMSIZE = 0; static void (*MMC1CHRHook4)(uint32 A, uint8 V); static void (*MMC1PRGHook16)(uint32 A, uint8 V); @@ -52,9 +57,9 @@ static DECLFR(MAWRAM) { } static void MMC1CHR(void) { - if (mmc1opts & 4) { - if (DRegs[0] & 0x10) - setprg8r(0x10, 0x6000, (DRegs[1] >> 4) & 1); + if (WRAMSIZE > 8192) { + if (WRAMSIZE > 16384) + setprg8r(0x10, 0x6000, (DRegs[1] >> 2) & 3); else setprg8r(0x10, 0x6000, (DRegs[1] >> 3) & 1); } @@ -183,24 +188,44 @@ static void MMC1CMReset(void) { MMC1PRG(); } -static int DetectMMC1WRAMSize(uint32 crc32) { - switch (crc32) { - case 0xc6182024: /* Romance of the 3 Kingdoms */ - case 0x2225c20f: /* Genghis Khan */ - case 0x4642dda6: /* Nobunaga's Ambition */ - case 0x29449ba9: /* "" "" (J) */ - case 0x2b11e0b0: /* "" "" (J) */ - case 0xb8747abf: /* Best Play Pro Yakyuu Special (J) */ - case 0xc9556b36: /* Final Fantasy I & II (J) [!] */ - FCEU_printf(" >8KB external WRAM present. Use UNIF if you hack the ROM image.\n"); - return(16); +static int DetectMMC1WRAMSize(CartInfo *info, int *saveRAM) { + int workRAM = 8; + switch (info->CRC32) { + case 0xc6182024: /* Romance of the 3 Kingdoms */ + case 0xabbf7217: /* "" "" (J) (PRG0) */ + case 0xccf35c02: /* "" "" (J) (PRG1) */ + case 0x2225c20f: /* Genghis Khan */ + case 0xfb69743a: /* "" "" (J) */ + case 0x4642dda6: /* Nobunaga's Ambition */ + case 0x3f7ad415: /* "" "" (J) (PRG0) */ + case 0x2b11e0b0: /* "" "" (J) (PRG1) */ + *saveRAM = 8; + workRAM = 16; + break; + case 0xb8747abf: /* Best Play Pro Yakyuu Special (J) (PRG0) */ + case 0xc3de7c69: /* "" "" (J) (PRG1) */ + case 0xc9556b36: /* Final Fantasy I & II (J) [!] */ + *saveRAM = 32; + workRAM = 32; + break; + default: + if (info->iNES2) { + workRAM = (info->prgRam + info->prgRam_battery) / 1024; + *saveRAM = info->prgRam_battery / 1024; + /* we only support sizes between 8K and 32K */ + if (workRAM > 0 && workRAM < 8) + workRAM = 8; + if (workRAM > 32) + workRAM = 32; + if (*saveRAM > workRAM) + *saveRAM = workRAM; + } break; - case 0xd1e50064: /* Dezaemon */ - FCEU_printf(" >8KB external WRAM present. Use UNIF if you hack the ROM image.\n"); - return(32); - break; - default: return(8); - } + } + if (workRAM > 8) + FCEU_printf(" >8KB external WRAM present. Use NES 2.0 if you hack the ROM image.\n"); + + return workRAM; } static uint32 NWCIRQCount; @@ -258,17 +283,16 @@ void Mapper105_Init(CartInfo *info) { static void GenMMC1Power(void) { lreset = 0; - if (mmc1opts & 1) { - FCEU_CheatAddRAM(8, 0x6000, WRAM); - if (mmc1opts & 4) - FCEU_dwmemset(WRAM, 0, 8192) - else if (!(mmc1opts & 2)) - FCEU_dwmemset(WRAM, 0, 8192); - } SetWriteHandler(0x8000, 0xFFFF, MMC1_write); SetReadHandler(0x8000, 0xFFFF, CartBR); - if (mmc1opts & 1) { + if (WRAMSIZE) { + FCEU_CheatAddRAM(8, 0x6000, WRAM); + + /* clear non-battery-backed portion of WRAM */ + if (NONSaveRAMSIZE) + FCEU_dwmemset(WRAM, 0, NONSaveRAMSIZE); + SetReadHandler(0x6000, 0x7FFF, MAWRAM); SetWriteHandler(0x6000, 0x7FFF, MBWRAM); setprg8r(0x10, 0x6000, 0); @@ -285,26 +309,24 @@ static void GenMMC1Close(void) { CHRRAM = WRAM = NULL; } -static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery) { +static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int saveram) { is155 = 0; info->Close = GenMMC1Close; MMC1PRGHook16 = MMC1CHRHook4 = 0; - mmc1opts = 0; + WRAMSIZE = wram * 1024; + NONSaveRAMSIZE = (wram - saveram) * 1024; PRGmask16[0] &= (prg >> 14) - 1; CHRmask4[0] &= (chr >> 12) - 1; CHRmask8[0] &= (chr >> 13) - 1; - if (wram) { - WRAM = (uint8*)FCEU_gmalloc(wram * 1024); - mmc1opts |= 1; - if (wram > 8) mmc1opts |= 4; - SetupCartPRGMapping(0x10, WRAM, wram * 1024, 1); - AddExState(WRAM, wram * 1024, 0, "WRAM"); - if (battery) { - mmc1opts |= 2; - info->SaveGame[0] = WRAM + ((mmc1opts & 4) ? 8192 : 0); - info->SaveGameLen[0] = 8192; + if (WRAMSIZE) { + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (saveram) { + info->SaveGame[0] = WRAM + NONSaveRAMSIZE; + info->SaveGameLen[0] = saveram * 1024; } } if (!chr) { @@ -322,13 +344,14 @@ static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery) } void Mapper1_Init(CartInfo *info) { - int ws = DetectMMC1WRAMSize(info->CRC32); - GenMMC1Init(info, 512, 256, ws, info->battery); + int bs = info->battery ? 8 : 0; + int ws = DetectMMC1WRAMSize(info, &bs); + GenMMC1Init(info, 512, 256, ws, bs); } /* Same as mapper 1, without respect for WRAM enable bit. */ void Mapper155_Init(CartInfo *info) { - GenMMC1Init(info, 512, 256, 8, info->battery); + GenMMC1Init(info, 512, 256, 8, info->battery ? 8 : 0); is155 = 1; } @@ -340,7 +363,7 @@ void Mapper171_Init(CartInfo *info) { } void SAROM_Init(CartInfo *info) { - GenMMC1Init(info, 128, 64, 8, info->battery); + GenMMC1Init(info, 128, 64, 8, info->battery ? 8 : 0); } void SBROM_Init(CartInfo *info) { @@ -360,7 +383,7 @@ void SGROM_Init(CartInfo *info) { } void SKROM_Init(CartInfo *info) { - GenMMC1Init(info, 256, 64, 8, info->battery); + GenMMC1Init(info, 256, 64, 8, info->battery ? 8 : 0); } void SLROM_Init(CartInfo *info) { @@ -392,11 +415,11 @@ void SHROM_Init(CartInfo *info) { /* */ void SNROM_Init(CartInfo *info) { - GenMMC1Init(info, 256, 0, 8, info->battery); + GenMMC1Init(info, 256, 0, 8, info->battery ? 8 : 0); } void SOROM_Init(CartInfo *info) { - GenMMC1Init(info, 256, 0, 16, info->battery); + GenMMC1Init(info, 256, 0, 16, info->battery ? 8 : 0); } /* ----------------------- FARID_SLROM_8-IN-1 -----------------------*/ @@ -490,7 +513,7 @@ static void Sync(void) { MMC1PRG(); MMC1CHR(); MMC1MIRROR(); - } else { + } else { /* Mapper 70 */ setprg16(0x8000, ((mode & 2) << 1) | ((latch >> 4) & 3)); setprg16(0xC000, ((mode & 2) << 1) | 3); diff --git a/src/ines.c b/src/ines.c index f0b8b07..0ae0367 100644 --- a/src/ines.c +++ b/src/ines.c @@ -676,6 +676,7 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"830928C", 382, Mapper382_Init}, {(uint8_t*)"NJ064", 534, Mapper534_Init}, {(uint8_t*)"Kid Ikarus (FDS)", 539, Mapper539_Init}, +/* {(uint8_t*)"5-in-1 (CH-501)", 543, Mapper543_Init}, */ /* UNIF to NES 2.0 BOARDS */ diff --git a/src/ines.h b/src/ines.h index 997a8ef..1a498d9 100644 --- a/src/ines.h +++ b/src/ines.h @@ -258,5 +258,6 @@ void Mapper534_Init(CartInfo *); void Mapper538_Init(CartInfo *); void Mapper539_Init(CartInfo *); void Mapper541_Init(CartInfo *); +void Mapper543_Init(CartInfo *); #endif From 310b75964f1cd4a0cc6cff47946af4c217c166e2 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Thu, 6 Feb 2020 20:02:32 +0800 Subject: [PATCH 06/13] Add mapper 543, 550, 516 --- src/boards/516.c | 58 ++++++++++++++++++ src/boards/mmc1.c | 150 +++++++++++++++++++++++++++++++++++++++++++++- src/ines.c | 5 +- src/ines.h | 2 + 4 files changed, 212 insertions(+), 3 deletions(-) create mode 100644 src/boards/516.c diff --git a/src/boards/516.c b/src/boards/516.c new file mode 100644 index 0000000..ad783a0 --- /dev/null +++ b/src/boards/516.c @@ -0,0 +1,58 @@ +/* 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 516 - Brilliant Com Cocoma Pack */ + +#include "mapinc.h" +#include "mmc3.h" + +static void M516CW(uint32 A, uint8 V) { +/* FCEU_printf("CHR: A:%04x V:%02x R0:%02x\n", A, V, EXPREGS[0]); */ + setchr1(A, (V & 0x7F) | ((EXPREGS[0] << 5) & 0x180)); +} + +static void M516PW(uint32 A, uint8 V) { +/* FCEU_printf("PRG: A:%04x V:%02x R0:%02x\n", A, V, EXPREGS[0]); */ + setprg8(A, (V & 0x0F) | ((EXPREGS[0] << 4) & 0x30)); +} + +static DECLFW(M516Write) { +/* FCEU_printf("Wr: A:%04x V:%02x R0:%02x\n", A, V, EXPREGS[0]); */ + if (A & 0x10) { + EXPREGS[0] = A & 0xF; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } + MMC3_CMDWrite(A, V); +} + +static void M516Power(void) { + EXPREGS[0] = 0; + GenMMC3Power(); + SetWriteHandler(0x8000, 0xFFFF, M516Write); +} + +void Mapper516_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 128, 0, 0); + cwrap = M516CW; + pwrap = M516PW; + info->Power = M516Power; + AddExState(EXPREGS, 4, 0, "EXPR"); +} diff --git a/src/boards/mmc1.c b/src/boards/mmc1.c index 48752c0..669399d 100644 --- a/src/boards/mmc1.c +++ b/src/boards/mmc1.c @@ -36,11 +36,21 @@ static uint32 NONSaveRAMSIZE = 0; static void (*MMC1CHRHook4)(uint32 A, uint8 V); static void (*MMC1PRGHook16)(uint32 A, uint8 V); +/* Used to override default wram behavior */ +/* NULL uses default MMC1 wram. Set after GenMMC1Init() is called to override */ +static void (*MMC1WRAMHook8)(void); static uint8 *WRAM = NULL; static uint8 *CHRRAM = NULL; static int is155, is171; +static uint32 MMC1GetCHRBank (uint32 bank) { + if (DRegs[0] & 0x10) /* 4 KiB mode */ + return (DRegs[1 + bank]); + else /* 8 KiB mode */ + return ((DRegs[1] & ~1) | bank); +} + static uint8 MMC1WRAMEnabled(void) { return !(DRegs[3] & 0x10); } @@ -56,14 +66,26 @@ static DECLFR(MAWRAM) { return(Page[A >> 11][A]); } -static void MMC1CHR(void) { +static void MMC1WRAM(void) { if (WRAMSIZE > 8192) { if (WRAMSIZE > 16384) setprg8r(0x10, 0x6000, (DRegs[1] >> 2) & 3); else setprg8r(0x10, 0x6000, (DRegs[1] >> 3) & 1); } +} +static void MMC1CHR(void) { + if (MMC1WRAMHook8) /* Use custom wram hook, currently used for M543 */ + MMC1WRAMHook8(); + else { /* Use default MMC1 wram behavior */ + if (WRAMSIZE > 8192) { + if (WRAMSIZE > 16384) + setprg8r(0x10, 0x6000, (DRegs[1] >> 2) & 3); + else + setprg8r(0x10, 0x6000, (DRegs[1] >> 3) & 1); + } + } if (MMC1CHRHook4) { if (DRegs[0] & 0x10) { MMC1CHRHook4(0x0000, DRegs[1]); @@ -313,7 +335,7 @@ static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int saveram) is155 = 0; info->Close = GenMMC1Close; - MMC1PRGHook16 = MMC1CHRHook4 = 0; + MMC1PRGHook16 = MMC1CHRHook4 = MMC1WRAMHook8 = 0; WRAMSIZE = wram * 1024; NONSaveRAMSIZE = (wram - saveram) * 1024; PRGmask16[0] &= (prg >> 14) - 1; @@ -555,3 +577,127 @@ void Mapper297_Init(CartInfo *info) { AddExState(&latch, 1, 0, "LATC"); AddExState(&mode, 1, 0, "MODE"); } + +/* ---------------------------- Mapper 543 -------------------------------- */ + +/* NES 2.0 Mapper 543 - 1996 無敵智カ卡 5-in-1 (CH-501) */ + +static uint8_t outerBank; +static uint8_t bits; +static uint8_t shift; + +static void M543PRG16(uint32 A, uint8 V) { + setprg16(A, (V & 0x0F) | (outerBank << 4)); +} + +static void M543CHR4(uint32 A, uint8 V) { + setchr4(A, (V & 7)); +} + +static void M543WRAM8(void) { + uint32 wramBank; + if (outerBank & 2) + wramBank = 4 | ((outerBank >> 1) & 2) | (outerBank & 1) ; + else + wramBank = ((outerBank << 1) & 2) | ((MMC1GetCHRBank(0) >> 3) & 1); + setprg8r(0x10, 0x6000, wramBank); +} + +static DECLFW(M543Write) { + bits |= ((V >> 3) & 1) << shift++; + if (shift == 4) { + outerBank = bits; + bits = shift = 0; + MMC1PRG(); + MMC1CHR(); + } +} + +static void M543Reset(void) { + bits = 0; + shift = 0; + outerBank = 0; + MMC1CMReset(); +} + +static void M543Power(void) { + bits = 0; + shift = 0; + outerBank = 0; + GenMMC1Power(); + SetWriteHandler(0x5000, 0x5FFF, M543Write); +} + +void Mapper543_Init(CartInfo *info) { + /* M543 has 32K CHR RAM but only uses 8K, so its safe to set this chr to 0 */ + GenMMC1Init(info, 2048, 32, 64, info->battery ? 64 : 0); + info->Power = M543Power; + info->Reset = M543Reset; + MMC1CHRHook4 = M543CHR4; + MMC1PRGHook16 = M543PRG16; + MMC1WRAMHook8 = M543WRAM8; + AddExState(&bits, 1, 0, "BITS"); + AddExState(&shift, 1, 0, "SHFT"); + AddExState(&outerBank, 1, 0, "BANK"); +} + +/* ---------------------------- Mapper 550 -------------------------------- */ + +/* NES 2.0 Mapper 550 - 7-in-1 1993 Chess Series (JY-015) */ + +static uint8_t latch; +static uint8_t outerBank; + +static void M550PRG16(uint32 A, uint8 V) { + if ((outerBank & 6) == 6) + setprg16(A, (V & 7) | (outerBank << 2)); + else + setprg32(0x8000, (latch >> 4) | (outerBank << 1)); +} + +static void M550CHR4(uint32 A, uint8 V) { + if ((outerBank & 6) == 6) + setchr4(A, (V & 7) | ((outerBank << 2) & 0x18)); + else + setchr8((latch & 3) | ((outerBank << 1) & 0x0C)); +} + +static DECLFW(M550Write7) { + if (!(outerBank & 8)) { + outerBank = A & 15; + MMC1PRG(); + MMC1CHR(); + } +} + +static DECLFW(M550Write8) { + latch = V; + if ((outerBank & 6) == 6) + MMC1_write(A, V); + MMC1PRG(); + MMC1CHR(); +} + +static void M550Reset(void) { + latch = 0; + outerBank = 0; + MMC1CMReset(); +} + +static void M550Power(void) { + latch = 0; + outerBank = 0; + GenMMC1Power(); + SetWriteHandler(0x7000, 0x7FFF, M550Write7); + SetWriteHandler(0x8000, 0xFFFF, M550Write8); +} + +void Mapper550_Init(CartInfo *info) { + GenMMC1Init(info, 512, 128, 8, 0); + info->Power = M550Power; + info->Reset = M550Reset; + MMC1CHRHook4 = M550CHR4; + MMC1PRGHook16 = M550PRG16; + AddExState(&latch, 1, 0, "LATC"); + AddExState(&outerBank, 1, 0, "BANK"); +} diff --git a/src/ines.c b/src/ines.c index 0ae0367..124e9ad 100644 --- a/src/ines.c +++ b/src/ines.c @@ -676,7 +676,9 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"830928C", 382, Mapper382_Init}, {(uint8_t*)"NJ064", 534, Mapper534_Init}, {(uint8_t*)"Kid Ikarus (FDS)", 539, Mapper539_Init}, -/* {(uint8_t*)"5-in-1 (CH-501)", 543, Mapper543_Init}, */ + {(uint8_t*)"5-in-1 (CH-501)", 543, Mapper543_Init}, + {(uint8_t*)"", 550, Mapper550_Init}, + {(uint8_t*)"Brilliant Com Cocoma Pack", 516, Mapper516_Init}, /* UNIF to NES 2.0 BOARDS */ @@ -1042,6 +1044,7 @@ static int iNES_Init(int num) { SetupCartCHRMapping(0, VROM, CHRRAMSize, 1); AddExState(VROM, CHRRAMSize, 0, "CHRR"); } + FCEU_printf(" CHR-RAM: %3d KiB\n", CHRRAMSize / 1024); } if (head.ROM_type & 8) AddExState(ExtraNTARAM, 2048, 0, "EXNR"); diff --git a/src/ines.h b/src/ines.h index 1a498d9..d04e641 100644 --- a/src/ines.h +++ b/src/ines.h @@ -253,11 +253,13 @@ void Mapper374_Init(CartInfo *); void Mapper382_Init(CartInfo *); void Mapper381_Init(CartInfo *); void Mapper390_Init(CartInfo *); +void Mapper516_Init(CartInfo *); void Mapper533_Init(CartInfo *); void Mapper534_Init(CartInfo *); void Mapper538_Init(CartInfo *); void Mapper539_Init(CartInfo *); void Mapper541_Init(CartInfo *); void Mapper543_Init(CartInfo *); +void Mapper550_Init(CartInfo *); #endif From 0b4b5421dcac1b270dbdbada1531310aec272876 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Fri, 14 Feb 2020 10:44:51 +0800 Subject: [PATCH 07/13] Add BMC-SB-5013 (m359) and UNL-82112C (m540) --- src/boards/359.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++ src/ines.c | 2 + src/ines.h | 2 + src/unif.c | 2 + 4 files changed, 199 insertions(+) create mode 100644 src/boards/359.c diff --git a/src/boards/359.c b/src/boards/359.c new file mode 100644 index 0000000..35a533d --- /dev/null +++ b/src/boards/359.c @@ -0,0 +1,193 @@ +/* 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 359 - BMC-SB-5013 + * NES 2.0 Mapper 540 - UNL-82112C + */ + +#include "mapinc.h" + +static uint8 mapperNum; +static uint8 preg[4]; +static uint8 creg[8]; +static uint8 exRegs[4]; +static uint8 IRQReload; +static uint8 IRQa; +static uint8 irqPA12; +static uint8 IRQAutoEnable; +static uint8 IRQLatch; +static uint8 IRQCount; +static int16 IRQCount16; + +static SFORMAT StateRegs[] = { + { preg, 4, "PREG" }, + { creg, 8, "CREG" }, + { exRegs, 4, "EXPR" }, + { &IRQReload, 1, "IRQL" }, + { &IRQa, 1, "IRQa" }, + { &irqPA12, 1, "IRQp" }, + { &IRQAutoEnable, 1, "IRQe" }, + { &IRQLatch, 1, "IRQl" }, + { &IRQCount, 1, "IRQ8" }, + { &IRQCount16, 2 | FCEUSTATE_RLSB, "IRQC" }, + { 0 } +}; + +static void Sync(void) { + uint32 prgMask = 0x3F; + uint32 prgOuterBank = (exRegs[0] & 0x38) << 1; + + switch (exRegs[1] & 3) { + case 0: prgMask = 0x3F; break; + case 1: prgMask = 0x1F; break; + case 2: prgMask = 0x2F; break; + case 3: prgMask = 0x0F; break; + } + + setprg8(0x6000, (preg[3] & prgMask) | prgOuterBank); + setprg8(0x8000, (preg[0] & prgMask) | prgOuterBank); + setprg8(0xA000, (preg[1] & prgMask) | prgOuterBank); + setprg8(0xC000, (preg[2] & prgMask) | prgOuterBank); + setprg8(0xE000, ( ~0 & prgMask) | prgOuterBank); + + if (!UNIFchrrama) { + switch (mapperNum) { + case 359: { + uint32 chrMask = (exRegs[1] & 0x40) ? 0xFF : 0x7F; + uint32 chrOuterBank = (exRegs[3] << 7); + uint32 i; + for (i = 0; i < 8; i++) + setchr1(i << 10, (creg[i] & chrMask) | chrOuterBank); + } break; + case 540: + setchr2(0x0000, creg[0]); + setchr2(0x0800, creg[1]); + setchr2(0x1000, creg[6]); + setchr2(0x1800, creg[7]); + break; + } + } else + setchr8(0); + + if (exRegs[2] & 2) + setmirror(MI_0 + (exRegs[2] & 1)); + else + setmirror((exRegs[2] & 1) ^ 1); +} + +static DECLFW(M359WriteIRQ) { + switch (A & 0xF003) { + case 0xC000: + if (IRQAutoEnable) IRQa = 0; + IRQCount16 &= 0xFF00; + IRQCount16 |= V; + IRQReload = 1; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xC001: + if (IRQAutoEnable) IRQa = 1; + IRQCount16 &= 0x00FF; + IRQCount16 |= (V << 8); + IRQLatch = V; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xC002: + IRQa = (V & 1); + irqPA12 = (V & 2) >> 1; + IRQAutoEnable = (V & 4) >> 2; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xC003: + IRQa = (V & 1); + X6502_IRQEnd(FCEU_IQEXT); + break; + } +} + +static DECLFW(M359WritePRG) { + uint32 i = A & 3; + preg[i] = V; + Sync(); +} + +static DECLFW(M359WriteCHR) { + uint32 i = ((A >> 10) & 4) | (A & 3); + creg[i] = V; + Sync(); +} + +static DECLFW(M359WriteEx) { + uint32 i = A & 3; + exRegs[i] = V; + Sync(); +} + +static void M359Power(void) { + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0x8FFF, M359WritePRG); + SetWriteHandler(0x9000, 0x9FFF, M359WriteEx); + SetWriteHandler(0xA000, 0xBFFF, M359WriteCHR); + SetWriteHandler(0xC000, 0xCFFF, M359WriteIRQ); +} + +static void FP_FASTAPASS(1) M359CPUHook(int a) { + if (!irqPA12) { + if (IRQa && IRQCount16) { + IRQCount16 -= a; + if (IRQCount16 <= 0) + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void M359IRQHook(void) { + if (irqPA12) { + if (!IRQCount || IRQReload) { + IRQCount = IRQLatch; + IRQReload = 0; + } else + IRQCount--; + if (!IRQCount && IRQa) + X6502_IRQBegin(FCEU_IQEXT); + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper359_Init(CartInfo* info) { + mapperNum = 359; + info->Power = M359Power; + MapIRQHook = M359CPUHook; + GameHBIRQHook = M359IRQHook; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +void Mapper540_Init(CartInfo* info) { + mapperNum = 540; + info->Power = M359Power; + MapIRQHook = M359CPUHook; + GameHBIRQHook = M359IRQHook; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/ines.c b/src/ines.c index 124e9ad..cfb9258 100644 --- a/src/ines.c +++ b/src/ines.c @@ -679,6 +679,8 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"5-in-1 (CH-501)", 543, Mapper543_Init}, {(uint8_t*)"", 550, Mapper550_Init}, {(uint8_t*)"Brilliant Com Cocoma Pack", 516, Mapper516_Init}, + {(uint8_t*)"SB-5013/GCL8050/841242C", 359, Mapper359_Init}, + {(uint8_t*)"82112C", 540, Mapper540_Init}, /* UNIF to NES 2.0 BOARDS */ diff --git a/src/ines.h b/src/ines.h index d04e641..f818021 100644 --- a/src/ines.h +++ b/src/ines.h @@ -247,6 +247,7 @@ void Mapper267_Init(CartInfo *); void Mapper288_Init(CartInfo *); void Mapper297_Init(CartInfo *); void Mapper357_Init(CartInfo *); +void Mapper359_Init(CartInfo *); void Mapper360_Init(CartInfo *); void Mapper372_Init(CartInfo *); void Mapper374_Init(CartInfo *); @@ -258,6 +259,7 @@ void Mapper533_Init(CartInfo *); void Mapper534_Init(CartInfo *); void Mapper538_Init(CartInfo *); void Mapper539_Init(CartInfo *); +void Mapper540_Init(CartInfo *); void Mapper541_Init(CartInfo *); void Mapper543_Init(CartInfo *); void Mapper550_Init(CartInfo *); diff --git a/src/unif.c b/src/unif.c index 37917e0..82d91f0 100644 --- a/src/unif.c +++ b/src/unif.c @@ -605,6 +605,8 @@ static BMAPPING bmap[] = { { "GN-26", 344, BMCGN26_Init, 0 }, { "KG256", NO_INES,KG256_Init, 0 }, { "T4A54A", 134, Bs5652_Init, 0 }, + { "SB-5013", 359, Mapper359_Init, 0 }, + { "82112C", 540, Mapper540_Init, 0 }, #ifdef COPYFAMI { "COPYFAMI_MMC3", NO_INES, MapperCopyFamiMMC3_Init, 0 }, From b7050cb55d0d77c7b645fb40d91f460c90849e85 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Fri, 14 Feb 2020 11:39:54 +0800 Subject: [PATCH 08/13] Add mappers 111, 356, 269, 353 - backport mapper 111 (Cheapocabra or GTROM) from fceux --- src/boards/269.c | 89 +++++++++++++ src/boards/353.c | 130 +++++++++++++++++++ src/boards/356.c | 103 +++++++++++++++ src/boards/cheapocabra.c | 269 +++++++++++++++++++++++++++++++++++++++ src/ines.c | 5 +- src/ines.h | 4 + 6 files changed, 599 insertions(+), 1 deletion(-) create mode 100644 src/boards/269.c create mode 100644 src/boards/353.c create mode 100644 src/boards/356.c create mode 100644 src/boards/cheapocabra.c diff --git a/src/boards/269.c b/src/boards/269.c new file mode 100644 index 0000000..f638b9c --- /dev/null +++ b/src/boards/269.c @@ -0,0 +1,89 @@ +/* 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 269 + * Games Xplosion 121-in-1 + * 15000-in-1 + * 18000-in-1 + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 *CHRROM; +static uint32 CHRROMSIZE; + +static void M269CW(uint32 A, uint8 V) { + uint32 NV = V; + if (EXPREGS[2] & 8) + NV &= (1 << ((EXPREGS[2] & 7) + 1)) - 1; + NV |= EXPREGS[0] | ((EXPREGS[2] & 0xF0) << 4); + setchr1(A, NV); +} + +static void M269PW(uint32 A, uint8 V) { + uint32 MV = V & ((EXPREGS[3] & 0x3F) ^ 0x3F); + MV |= EXPREGS[1]; + MV |= ((EXPREGS[3] & 0x40) << 2); + setprg8(A, MV); +} + +static DECLFW(M269Write5) { + if (!(EXPREGS[3] & 0x80)) { + EXPREGS[EXPREGS[4]] = V; + EXPREGS[4] = (EXPREGS[4] + 1) & 3; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } +} + +static void M269Reset(void) { + EXPREGS[0] = EXPREGS[1] = EXPREGS[3] = EXPREGS[4] = 0; + EXPREGS[2] = 0x0F; + MMC3RegReset(); +} + +static void M269Power(void) { + uint32 i; + EXPREGS[0] = EXPREGS[1] = EXPREGS[3] = EXPREGS[4] = 0; + EXPREGS[2] = 0x0F; + GenMMC3Power(); + SetWriteHandler(0x5000, 0x5FFF, M269Write5); + + CHRROMSIZE = PRGsize[0]; + CHRROM = (uint8*)FCEU_gmalloc(CHRROMSIZE); + /* Decrypt CHR data */ + for (i = 0; i < CHRROMSIZE; i++) { + uint8_t Val = PRGptr[0][i]; + Val = ((Val & 1) << 6) | ((Val & 2) << 3) | ((Val & 4) << 0) | ((Val & 8) >> 3) | ((Val & 16) >> 3) | ((Val & 32) >> 2) | ((Val & 64) >> 1) | ((Val & 128) << 0); + CHRROM[i] = Val; + } + SetupCartCHRMapping(0, CHRROM, CHRROMSIZE, 0); + AddExState(CHRROM, CHRROMSIZE, 0, "_CHR"); +} + +void Mapper269_Init(CartInfo *info) { + GenMMC3_Init(info, 512, 0, 8, 0); + cwrap = M269CW; + pwrap = M269PW; + info->Power = M269Power; + info->Reset = M269Reset; + AddExState(EXPREGS, 5, 0, "EXPR"); +} diff --git a/src/boards/353.c b/src/boards/353.c new file mode 100644 index 0000000..94e644f --- /dev/null +++ b/src/boards/353.c @@ -0,0 +1,130 @@ +/* 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 353 is used for the 92 Super Mario Family multicart, + * consisting of an MMC3 clone ASIC together with a PAL. + * The PCB code is 81-03-05-C. + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8* CHRRAM = NULL; +static uint32 CHRRAMSIZE; +static uint8 PPUCHRBus; +static uint8 MIR[8]; + +static void M353PPU(uint32 A) { + A &= 0x1FFF; + A >>= 10; + PPUCHRBus = A; + if (EXPREGS[0] == 0) + setmirror(MI_0 + MIR[A]); +} + +static void M353PW(uint32 A, uint8 V) { + uint32 bank = V; + + if (EXPREGS[0] == 2) { + bank &= 0x0F; + bank |= (DRegBuf[0] & 0x80) ? 0x10 : 0x00; + bank |= (EXPREGS[0] << 5); + } else { + if ((EXPREGS[0] == 3) && !(DRegBuf[0] & 0x80)) { + switch (A & 0xF000) { + case 0xC000: + case 0xE000: + bank = DRegBuf[6 + ((A >> 13) & 1)] | 0x70; + break; + } + } else { + bank &= 0x1F; + bank |= (EXPREGS[0] << 5); + } + } + + setprg8(A, bank); +} + +static void M353CW(uint32 A, uint8 V) { + if ((EXPREGS[0] == 2) && (DRegBuf[0] & 0x80)) + setchr8r(0x10, 0); + else + setchr1(A, (V & 0x7F) | ((EXPREGS[0]) << 7)); + + MIR[A >> 10] = V >> 7; + if ((EXPREGS[0] == 0) && (PPUCHRBus == (A >> 10))) + setmirror(MI_0 + (V >> 7)); +} + +static void M353MW(uint8 V) { + if (EXPREGS[0] != 0) { + A000B = V; + setmirror((V & 1) ^ 1); + } +} + +static DECLFW(M353Write) { + if (A & 0x80) { + EXPREGS[0] = (A >> 13) & 0x03; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } else { + if (A < 0xC000) { + MMC3_CMDWrite(A, V); + FixMMC3PRG(MMC3_cmd); + } else + MMC3_IRQWrite(A, V); + } +} + +static void M353Power(void) { + EXPREGS[0] = 0; + GenMMC3Power(); + SetWriteHandler(0x8000, 0xFFFF, M353Write); +} + +static void M353Reset(void) { + EXPREGS[0] = 0; + MMC3RegReset(); +} + +static void M353Close(void) { + if (CHRRAM) + FCEU_gfree(CHRRAM); + CHRRAM = NULL; +} + +void Mapper353_Init(CartInfo* info) { + GenMMC3_Init(info, 256, 128, 8, info->battery); + cwrap = M353CW; + pwrap = M353PW; + mwrap = M353MW; + PPU_hook = M353PPU; + info->Power = M353Power; + info->Close = M353Close; + info->Reset = M353Reset; + AddExState(EXPREGS, 1, 0, "EXPR"); + + CHRRAMSIZE = 8192; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +} diff --git a/src/boards/356.c b/src/boards/356.c new file mode 100644 index 0000000..c5dc93f --- /dev/null +++ b/src/boards/356.c @@ -0,0 +1,103 @@ +/* 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 356 - J.Y. Company's 7-in-1 Rockman (JY-208) + * All registers work as INES Mapper 045, except $6000 sequential register 2 (third write): + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8* CHRRAM = NULL; +static uint32 CHRRAMSIZE = 0; + +static void M356CW(uint32 A, uint8 V) { + if (EXPREGS[2] & 0x20) { + uint32 NV = V; + if (EXPREGS[2] & 8) + NV &= (1 << ((EXPREGS[2] & 7) + 1)) - 1; + else + if (EXPREGS[2]) + NV &= 0; /* hack ;( don't know exactly how it should be */ + NV |= EXPREGS[0] | ((EXPREGS[2] & 0xF0) << 4); + setchr1(A, NV); + } else + setchr8r(0x10, 0); +} + +static void M356PW(uint32 A, uint8 V) { + uint32 MV = V & ((EXPREGS[3] & 0x3F) ^ 0x3F); + MV |= EXPREGS[1]; + if (UNIFchrrama) + MV |= ((EXPREGS[2] & 0x40) << 2); + setprg8(A, MV); +} + +static void M356MW(uint8 V) { + if (EXPREGS[2] & 0x40) + SetupCartMirroring(4, 1, CHRRAM); + else + setmirror((V & 1) ^ 1); +} + +static DECLFW(M356Write) { + if (!(EXPREGS[3] & 0x40)) { + EXPREGS[EXPREGS[4]] = V; + EXPREGS[4] = (EXPREGS[4] + 1) & 3; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } +} + +static void M356Close(void) { + if (CHRRAM) + FCEU_free(CHRRAM); + CHRRAM = NULL; +} + +static void M356Reset(void) { + EXPREGS[0] = EXPREGS[1] = EXPREGS[3] = EXPREGS[4] = 0; + EXPREGS[2] = 0x0F; + MMC3RegReset(); +} + +static void M356Power(void) { + EXPREGS[4] = 0; + EXPREGS[0] = EXPREGS[1] = EXPREGS[3] = EXPREGS[4] = 0; + EXPREGS[2] = 0x0F; + GenMMC3Power(); + SetWriteHandler(0x6000, 0x7FFF, M356Write); +} + +void Mapper356_Init(CartInfo* info) { + GenMMC3_Init(info, 128, 128, 0, 0); + cwrap = M356CW; + pwrap = M356PW; + mwrap = M356MW; + info->Reset = M356Reset; + info->Power = M356Power; + info->Close = M356Close; + AddExState(EXPREGS, 5, 0, "EXPR"); + + CHRRAMSIZE = 8192; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +} diff --git a/src/boards/cheapocabra.c b/src/boards/cheapocabra.c new file mode 100644 index 0000000..7730941 --- /dev/null +++ b/src/boards/cheapocabra.c @@ -0,0 +1,269 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * + * 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 111 - Cheapocabra board by Memblers + * http://forums.nesdev.com/viewtopic.php?p=146039 + * + * 512k PRG-ROM in 32k pages (flashable if battery backed is specified) + * 32k CHR-RAM used as: + * 2 x 8k pattern pages + * 2 x 8k nametable pages + * + * Notes: + * - CHR-RAM for nametables maps to $3000-3FFF as well, but FCEUX internally mirrors to 4k? + */ + +#include "mapinc.h" +#include "../ines.h" + +static uint8 reg; +static uint8 *CHRRAM = NULL; +static uint32 CHRRAMSIZE; + +static uint8 flash = 0; +static uint8 flash_mode; +static uint8 flash_sequence; +static uint8 flash_id; +static uint8 *FLASHROM = NULL; +static uint32 FLASHROMSIZE; + +static SFORMAT StateRegs[] = { + { ®, 1, "REG" }, + { 0 } +}; + +static SFORMAT FlashRegs[] = { + { &flash_mode, 1, "FMOD" }, + { &flash_sequence, 1, "FSEQ" }, + { &flash_id, 1, "FMID" }, + { 0 } +}; + +static void Sync(void) { + /* bit 7 controls green LED */ + /* bit 6 controls red LED */ + uint32 prg_chip = flash ? 0x10 : 0; + int nt = (reg & 0x20) ? 8192 : 0; /* bit 5 controls 8k nametable page */ + int chr = (reg & 0x10) ? 1 : 0; /* bit 4 selects 8k CHR page */ + int prg = (reg & 0x0F); /* bits 0-3 select 32k PRG page */ + int n = 0; + + nt += (16 * 1024); + for (n = 0; n < 4; ++n) { + setntamem(CHRRAM + nt + (1024 * n), 1, n); + } + setchr8r(0x10, chr); + setprg32r(prg_chip, 0x8000, prg); +} + +static DECLFW(M111Write) { + if ((A >= 0x5000 && A <= 0x5FFF) || (A >= 0x7000 && A <= 0x7FFF)) { + reg = V; + Sync(); + } +} + +static DECLFR(M111FlashID) { + /* Software ID mode is undefined by the datasheet for all but the lowest 2 addressable bytes, + * but some tests of the chip currently being used found it repeats in 512-byte patterns. + * http://forums.nesdev.com/viewtopic.php?p=178728#p178728 + */ + + uint32 aid = A & 0x1FF; + switch (aid) { + case 0: + return 0xBF; + case 1: + return 0xB7; + default: + return 0xFF; + } +} + +void M111FlashIDEnter() { + if (flash_id) + return; + flash_id = 1; + SetReadHandler(0x8000, 0xFFFF, M111FlashID); +} + +void M111FlashIDExit() { + if (!flash_id) + return; + flash_id = 0; + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +enum { + FLASH_MODE_READY = 0, + FLASH_MODE_COMMAND, + FLASH_MODE_BYTE_WRITE, + FLASH_MODE_ERASE, +}; + +static DECLFW(M111Flash) { + uint32 flash_addr = 0; + uint32 command_addr = 0; + + if (A < 0x8000 || A > 0xFFFF) + return; + + flash_addr = ((reg & 0x0F) << 15) | (A & 0x7FFF); + command_addr = flash_addr & 0x7FFF; + + switch (flash_mode) { + default: + case FLASH_MODE_READY: + if (command_addr == 0x5555 && V == 0xAA) { + flash_mode = FLASH_MODE_COMMAND; + flash_sequence = 0; + } else if (V == 0xF0) { + M111FlashIDExit(); + } + break; + case FLASH_MODE_COMMAND: + if (flash_sequence == 0) { + if (command_addr == 0x2AAA && V == 0x55) + flash_sequence = 1; + else + flash_mode = FLASH_MODE_READY; + } else if (flash_sequence == 1) { + if (command_addr == 0x5555) { + flash_sequence = 0; + switch (V) { + default: + flash_mode = FLASH_MODE_READY; + break; + case 0xA0: + flash_mode = FLASH_MODE_BYTE_WRITE; + break; + case 0x80: + flash_mode = FLASH_MODE_ERASE; + break; + case 0x90: + M111FlashIDEnter(); + flash_mode = FLASH_MODE_READY; + break; + case 0xF0: + M111FlashIDExit(); + flash_mode = FLASH_MODE_READY; + break; + } + } else + flash_mode = FLASH_MODE_READY; + } else + flash_mode = FLASH_MODE_READY; /* should be unreachable */ + break; + case FLASH_MODE_BYTE_WRITE: + FLASHROM[flash_addr] &= V; + flash_mode = FLASH_MODE_READY; + break; + case FLASH_MODE_ERASE: + if (flash_sequence == 0) { + if (command_addr == 0x5555 && V == 0xAA) + flash_sequence = 1; + else + flash_mode = FLASH_MODE_READY; + } else if (flash_sequence == 1) { + if (command_addr == 0x2AAA && V == 0x55) + flash_sequence = 2; + else + flash_mode = FLASH_MODE_READY; + } else if (flash_sequence == 2) { + if (command_addr == 0x5555 && V == 0x10) /* erase chip */ + { + memset(FLASHROM, 0xFF, FLASHROMSIZE); + } else if (V == 0x30) /* erase 4k sector */ + { + uint32 sector = flash_addr & 0x7F000; + memset(FLASHROM + sector, 0xFF, 1024 * 4); + } + flash_mode = FLASH_MODE_READY; + } else + flash_mode = FLASH_MODE_READY; /* should be unreachable */ + break; + } +} + +static void M111Power(void) { + reg = 0xFF; + Sync(); + SetReadHandler(0x8000, 0xffff, CartBR); + SetWriteHandler(0x5000, 0x5fff, M111Write); + SetWriteHandler(0x7000, 0x7fff, M111Write); + + if (flash) { + flash_mode = 0; + flash_sequence = 0; + flash_id = 0; + SetWriteHandler(0x8000, 0xFFFF, M111Flash); + } +} + +static void M111Close(void) { + if (CHRRAM) + FCEU_gfree(CHRRAM); + CHRRAM = NULL; + + if (FLASHROM) + FCEU_gfree(FLASHROM); + FLASHROM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper111_Init(CartInfo* info) { + info->Power = M111Power; + info->Close = M111Close; + + CHRRAMSIZE = 1024 * 32; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); + + flash = (info->battery != 0); + if (flash) { + uint32 PRGSIZE = 0; + uint32 w = 0; + uint32 r = 0; + + FLASHROMSIZE = 1024 * 512; + FLASHROM = (uint8*)FCEU_gmalloc(FLASHROMSIZE); + info->SaveGame[0] = FLASHROM; + info->SaveGameLen[0] = FLASHROMSIZE; + AddExState(FLASHROM, FLASHROMSIZE, 0, "FROM"); + AddExState(&FlashRegs, ~0, 0, 0); + + /* copy PRG ROM into FLASHROM, use it instead of PRG ROM */ + PRGSIZE = ROM_size * 16 * 1024; + for (w = 0, r = 0; w < FLASHROMSIZE; ++w) { + FLASHROM[w] = ROM[r]; + ++r; + if (r >= PRGSIZE) + r = 0; + } + SetupCartPRGMapping(0x10, FLASHROM, FLASHROMSIZE, 0); + } +} diff --git a/src/ines.c b/src/ines.c index cfb9258..7b24030 100644 --- a/src/ines.c +++ b/src/ines.c @@ -505,7 +505,7 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"FDS UNROM BOARD", 108, Mapper108_Init}, /* {(uint8_t*)"", 109, Mapper109_Init}, */ /* {(uint8_t*)"", 110, Mapper110_Init}, */ -/* {(uint8_t*)"", 111, Mapper111_Init}, */ + {(uint8_t*)"Cheapocabra", 111, Mapper111_Init}, {(uint8_t*)"ASDER/NTDEC BOARD", 112, Mapper112_Init}, {(uint8_t*)"HACKER/SACHEN BOARD", 113, Mapper113_Init}, {(uint8_t*)"MMC3 SG PROT. A", 114, Mapper114_Init}, @@ -681,6 +681,9 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"Brilliant Com Cocoma Pack", 516, Mapper516_Init}, {(uint8_t*)"SB-5013/GCL8050/841242C", 359, Mapper359_Init}, {(uint8_t*)"82112C", 540, Mapper540_Init}, + {(uint8_t*)"7-in-1 Rockman (JY-208)", 356, Mapper356_Init}, + {(uint8_t*)"Games Xplosion 121-in-1", 269, Mapper269_Init}, + {(uint8_t*)"Super Mario Family", 353, Mapper353_Init}, /* UNIF to NES 2.0 BOARDS */ diff --git a/src/ines.h b/src/ines.h index f818021..d54c8b1 100644 --- a/src/ines.h +++ b/src/ines.h @@ -136,6 +136,7 @@ void Mapper105_Init(CartInfo *); void Mapper106_Init(CartInfo *); void Mapper107_Init(CartInfo *); void Mapper108_Init(CartInfo *); +void Mapper111_Init(CartInfo *); void Mapper112_Init(CartInfo *); void Mapper113_Init(CartInfo *); void Mapper114_Init(CartInfo *); @@ -244,8 +245,11 @@ void NC7000M_Init(CartInfo *); void J2282_Init(CartInfo *); void Mapper267_Init(CartInfo *); +void Mapper269_Init(CartInfo *); void Mapper288_Init(CartInfo *); void Mapper297_Init(CartInfo *); +void Mapper353_Init(CartInfo *); +void Mapper356_Init(CartInfo *); void Mapper357_Init(CartInfo *); void Mapper359_Init(CartInfo *); void Mapper360_Init(CartInfo *); From cfaee1217fdd010134522e00c09cc65eeab31a75 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Sun, 16 Feb 2020 01:10:28 +0800 Subject: [PATCH 09/13] Update mapper 91 --- src/boards/91.c | 58 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/src/boards/91.c b/src/boards/91.c index da9177f..5a2a7f1 100644 --- a/src/boards/91.c +++ b/src/boards/91.c @@ -2,6 +2,7 @@ * * Copyright notice for this file: * Copyright (C) 2012 CaH4e3 + * 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 @@ -18,10 +19,20 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +/* added 2020-2-15 + * Street Fighter 3, Mortal Kombat II, Dragon Ball Z 2, Mario & Sonic 2 (JY-016) + * 1995 Super HIK 4-in-1 (JY-016), 1995 Super HiK 4-in-1 (JY-017) + * submapper 1 - Super Fighter III + * NOTE: nesdev's notes for IRQ is different that whats implemented here + */ + #include "mapinc.h" static uint8 cregs[4], pregs[2]; static uint8 IRQCount, IRQa; +static uint8 submapper; +static uint8 outerbank; +static uint8 mirr; static SFORMAT StateRegs[] = { @@ -29,23 +40,36 @@ static SFORMAT StateRegs[] = { pregs, 2, "PREG" }, { &IRQa, 1, "IRQA" }, { &IRQCount, 1, "IRQC" }, + { &outerbank, 1, "BLOK" }, + { &mirr, 1, "MIRR" }, { 0 } }; static void Sync(void) { - setprg8(0x8000, pregs[0]); - setprg8(0xa000, pregs[1]); - setprg8(0xc000, ~1); - setprg8(0xe000, ~0); - setchr2(0x0000, cregs[0]); - setchr2(0x0800, cregs[1]); - setchr2(0x1000, cregs[2]); - setchr2(0x1800, cregs[3]); +/* FCEU_printf("P0:%02x P1:%02x outerbank:%02x\n", pregs[0], pregs[1], outerbank);*/ + setprg8(0x8000, pregs[0] | (outerbank & 6) << 3); + setprg8(0xa000, pregs[1] | (outerbank & 6) << 3); + setprg8(0xc000, 0xE | (outerbank & 6) << 3); + setprg8(0xe000, 0xF | (outerbank & 6) << 3); + setchr2(0x0000, cregs[0] | (outerbank & 1) << 8); + setchr2(0x0800, cregs[1] | (outerbank & 1) << 8); + setchr2(0x1000, cregs[2] | (outerbank & 1) << 8); + setchr2(0x1800, cregs[3] | (outerbank & 1) << 8); + + if (submapper == 1) + setmirror(mirr ^ 1); } static DECLFW(M91Write0) { - cregs[A & 3] = V; - Sync(); + switch (A & 7) { + case 0: + case 1: + case 2: + case 3: cregs[A & 3] = V; Sync(); break; + case 4: + case 5: mirr = V & 1; Sync(); break; + default: /*FCEU_printf("A:%04x V:%02x\n", A, V);*/ break; + } } static DECLFW(M91Write1) { @@ -57,11 +81,17 @@ static DECLFW(M91Write1) { } } +static DECLFW(M91Write2) { + outerbank = A & 7; + Sync(); +} + static void M91Power(void) { Sync(); + SetReadHandler(0x8000, 0xffff, CartBR); SetWriteHandler(0x6000, 0x6fff, M91Write0); SetWriteHandler(0x7000, 0x7fff, M91Write1); - SetReadHandler(0x8000, 0xffff, CartBR); + SetWriteHandler(0x8000, 0x9fff, M91Write2); } static void M91IRQHook(void) { @@ -78,6 +108,12 @@ static void StateRestore(int version) { } void Mapper91_Init(CartInfo *info) { + submapper = 0; + if (info->CRC32 == 0x082778e6) /* Super Fighter III */ + submapper = 1; + else if (info->iNES2) + submapper = info->submapper; + info->Power = M91Power; GameHBIRQHook = M91IRQHook; GameStateRestore = StateRestore; From 6e7d5abaab58b77db307cc09530a55d5a3e1685f Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Sun, 16 Feb 2020 19:18:02 +0800 Subject: [PATCH 10/13] Update implementation of some unlicensed mappers --- src/boards/01-222.c | 111 ------------ src/boards/36.c | 91 ---------- src/boards/sachen.c | 67 ------- src/boards/txcchip.c | 407 +++++++++++++++++++++++++++++++++++++++++++ src/ines-correct.h | 8 + src/ines.c | 10 +- src/ines.h | 3 + src/unif.c | 6 +- src/unif.h | 2 - 9 files changed, 426 insertions(+), 279 deletions(-) delete mode 100644 src/boards/01-222.c delete mode 100644 src/boards/36.c create mode 100644 src/boards/txcchip.c diff --git a/src/boards/01-222.c b/src/boards/01-222.c deleted file mode 100644 index 22eea70..0000000 --- a/src/boards/01-222.c +++ /dev/null @@ -1,111 +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 - * - * TXC mappers, originally much complex banksitching - * - * 01-22111-000 (05-00002-010) (132, 22211) - MGC-001 Qi Wang - * 01-22110-000 (52S ) - MGC-002 2-in-1 Gun - * 01-22111-100 (02-00002-010) (173 ) - MGC-008 Mahjong Block - * (079 ) - MGC-012 Poke Block - * 01-22110-200 (05-00002-010) (036 ) - MGC-014 Strike Wolf - * 01-22000-400 (05-00002-010) (036 ) - MGC-015 Policeman - * 01-22017-000 (05-PT017-080) (189 ) - MGC-017 Thunder Warrior - * 01-11160-000 (04-02310-000) ( , 11160) - MGC-023 6-in-1 - * 01-22270-000 (05-00002-010) (132, 22211) - MGC-xxx Creatom - * 01-22200-400 (------------) (079 ) - ET.03 F-15 City War - * (172 ) - 1991 Du Ma Racing - * - */ - -#include "mapinc.h" - -static uint8 reg[4], cmd, is172, is173; -static SFORMAT StateRegs[] = -{ - { reg, 4, "REGS" }, - { &cmd, 1, "CMD" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, (reg[2] >> 2) & 1); - if (is172) - setchr8((((cmd ^ reg[2]) >> 3) & 2) | (((cmd ^ reg[2]) >> 5) & 1)); /* 1991 DU MA Racing probably CHR bank sequence is WRONG, so it is possible to - * rearrange CHR banks for normal UNIF board and mapper 172 is unneccessary */ - else - setchr8(reg[2] & 3); -} - -static DECLFW(UNL22211WriteLo) { -/* FCEU_printf("bs %04x %02x\n",A,V); */ - reg[A & 3] = V; -} - -static DECLFW(UNL22211WriteHi) { -/* FCEU_printf("bs %04x %02x\n",A,V); */ - cmd = V; - Sync(); -} - -static DECLFR(UNL22211ReadLo) { - return (reg[1] ^ reg[2]) | (is173 ? 0x01 : 0x40); -#if 0 - if(reg[3]) - return reg[2]; - else - return X.DB; -#endif -} - -static void UNL22211Power(void) { - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetReadHandler(0x4100, 0x4100, UNL22211ReadLo); - SetWriteHandler(0x4100, 0x4103, UNL22211WriteLo); - SetWriteHandler(0x8000, 0xFFFF, UNL22211WriteHi); -} - -static void StateRestore(int version) { - Sync(); -} - -void UNL22211_Init(CartInfo *info) { - is172 = 0; - is173 = 0; - info->Power = UNL22211Power; - GameStateRestore = StateRestore; - AddExState(&StateRegs, ~0, 0, 0); -} - -void Mapper172_Init(CartInfo *info) { - is172 = 1; - is173 = 0; - info->Power = UNL22211Power; - GameStateRestore = StateRestore; - AddExState(&StateRegs, ~0, 0, 0); -} - -void Mapper173_Init(CartInfo *info) { - is172 = 0; - is173 = 1; - info->Power = UNL22211Power; - GameStateRestore = StateRestore; - AddExState(&StateRegs, ~0, 0, 0); -} - diff --git a/src/boards/36.c b/src/boards/36.c deleted file mode 100644 index afc1c87..0000000 --- a/src/boards/36.c +++ /dev/null @@ -1,91 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * 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 - * - * TXC/Micro Genius simplified mapper - * updated 06-2019 http://wiki.nesdev.com/w/index.php/INES_Mapper_036 - * - * Known games: - * - Strike Wolf (Asia) (Unl) - * - Policeman (Gluk Video) (unl) - * - F-15 City War (Spain) (Gluk Video) (Unl) - */ - -#include "mapinc.h" - -static uint8 regs[5]; - -static SFORMAT StateRegs[] = -{ - { regs, 5, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, regs[0] >> 4); - setchr8(regs[4] & 0x0F); -} - -static DECLFW(M36Write4100) { - switch(A & 0xE103) { - case 0x4100: - if(regs[3] & 0x10) - regs[0]++; - else - regs[0] = regs[2]; - break; - case 0x4101: - case 0x4102: - case 0x4103: - regs[A & 0x03] = V; - break; - } -} - -static DECLFW(M36Write4200) { - regs[4] = V; - Sync(); -} - -static DECLFW(M36WriteHi) { - Sync(); -} - -static DECLFR(M36Read) { - return ((X.DB & 0xCF) | (regs[0] & 0x30)); -} - -static void M36Power(void) { - Sync(); - SetReadHandler(0x4100, 0x4100, M36Read); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x4100, 0x4103, M36Write4100); - SetWriteHandler(0x4200, 0x4200, M36Write4200); - SetWriteHandler(0x8000, 0xFFFF, M36WriteHi); -} - -static void M36Restore(int version) { - Sync(); -} - -void Mapper36_Init(CartInfo *info) { - info->Power = M36Power; - GameStateRestore = M36Restore; - AddExState(StateRegs, ~0, 0, 0); -} diff --git a/src/boards/sachen.c b/src/boards/sachen.c index bc79786..fdfd7aa 100644 --- a/src/boards/sachen.c +++ b/src/boards/sachen.c @@ -322,73 +322,6 @@ void SA0037_Init(CartInfo *info) { AddExState(&latch[0], 1, 0, "LATC"); } -/* ----------------------------------------------- */ - -static void TCU01Synco() { - setprg32(0x8000, ((latch[0] & 0x80) >> 6) | ((latch[0] >> 2) & 1)); - setchr8((latch[0] >> 3) & 0xF); -} - -static DECLFW(TCU01Write) { - if ((A & 0x103) == 0x102) { - latch[0] = V; - TCU01Synco(); - } -} - -static void TCU01Power(void) { - latch[0] = 0; - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x4100, 0xFFFF, TCU01Write); - TCU01Synco(); -} - -static void TCU01Restore(int version) { - TCU01Synco(); -} - -void TCU01_Init(CartInfo *info) { - GameStateRestore = TCU01Restore; - info->Power = TCU01Power; - AddExState(&latch[0], 1, 0, "LATC"); -} - -/* ----------------------------------------------- */ - -static void TCU02Synco() { - setprg32(0x8000, 0); - setchr8(latch[0] & 3); -} - -static DECLFW(TCU02Write) { - if ((A & 0x103) == 0x102) { - latch[0] = V + 3; - TCU02Synco(); - } -} - -static DECLFR(TCU02Read) { - return (latch[0] & 0x3F) | (X.DB & 0xC0); -} - -static void TCU02Power(void) { - latch[0] = 0; - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetReadHandler(0x4100, 0x4100, TCU02Read); - SetWriteHandler(0x4100, 0xFFFF, TCU02Write); - TCU02Synco(); -} - -static void TCU02Restore(int version) { - TCU02Synco(); -} - -void TCU02_Init(CartInfo *info) { - GameStateRestore = TCU02Restore; - info->Power = TCU02Power; - AddExState(&latch[0], 1, 0, "LATC"); -} - /* --------------------------------------------- */ static DECLFR(TCA01Read) { diff --git a/src/boards/txcchip.c b/src/boards/txcchip.c new file mode 100644 index 0000000..d2c0ab8 --- /dev/null +++ b/src/boards/txcchip.c @@ -0,0 +1,407 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2019 Libretro Team + * 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 + * + * TXC/Micro Genius simplified mapper + * updated 06-2019 http://wiki.nesdev.com/w/index.php/INES_Mapper_036 + * + * Known games: + * - Strike Wolf (Asia) (Unl) + * - Policeman (Gluk Video) (unl) + * - F-15 City War (Spain) (Gluk Video) (Unl) + * + * TXC mappers, originally much complex banksitching + * + * 01-22111-000 (05-00002-010) (132, 22211) - MGC-001 Qi Wang + * 01-22110-000 (52S ) - MGC-002 2-in-1 Gun + * 01-22111-100 (02-00002-010) (173 ) - MGC-008 Mahjong Block + * (079 ) - MGC-012 Poke Block + * 01-22110-200 (05-00002-010) (036 ) - MGC-014 Strike Wolf + * 01-22000-400 (05-00002-010) (036 ) - MGC-015 Policeman + * 01-22017-000 (05-PT017-080) (189 ) - MGC-017 Thunder Warrior + * 01-11160-000 (04-02310-000) ( , 11160) - MGC-023 6-in-1 + * 01-22270-000 (05-00002-010) (132, 22211) - MGC-xxx Creatom + * 01-22200-400 (------------) (079 ) - ET.03 F-15 City War + * (172 ) - 1991 Du Ma Racing + * + */ + +/* added 2020-2-16 + * Updated based on latest source + * Mappers 36, 132, 173 + * Mappers 136, 147, 172 + */ + +#include "mapinc.h" + +typedef struct { + uint8 mask; + uint8 isJV001; + uint8 accumulator; + uint8 inverter; + uint8 staging; + uint8 output; + uint8 increase; + uint8 Y; + uint8 invert; +} TXC; + +static TXC txc; + +static void (*WSync)(void); + +static SFORMAT StateRegs[] = +{ + { &txc.accumulator, 1, "ACC0" }, + { &txc.inverter, 1, "INVR" }, + { &txc.staging, 1, "STG0" }, + { &txc.output, 1, "OUT0" }, + { &txc.increase, 1, "INC0" }, + { &txc.Y, 1, "YFLG" }, + { &txc.invert, 1, "INVT" }, + { 0 } +}; + +static uint8 TXC_CMDRead(void) { + uint8 ret = ((txc.accumulator & txc.mask) | ((txc.inverter ^ txc.invert) & ~txc.mask)); + txc.Y = !txc.invert || ((ret & 0x10) != 0); + WSync(); + return ret; +} + +static DECLFW(TXC_CMDWrite) { + if (A & 0x8000) { + if (txc.isJV001) + txc.output = (txc.accumulator & 0x0F) | (txc.inverter & 0xF0); + else + txc.output = (txc.accumulator & 0x0F) | ((txc.inverter << 1) & 0x10); + } else { + switch (A & 0x103) { + case 0x100: + if (txc.increase) + txc.accumulator++; + else + txc.accumulator = ((txc.accumulator & ~txc.mask) | (txc.staging ^ txc.invert) & txc.mask); + break; + case 0x101: + txc.invert = (V & 0x01) ? 0xFF : 0x00; + break; + case 0x102: + txc.staging = V & txc.mask; + txc.inverter = V & ~txc.mask; + break; + case 0x103: + txc.increase = ((V & 0x01) != 0); + break; + } + } + txc.Y = !txc.invert || ((V & 0x10) != 0); + WSync(); +} + +static void TXCRegReset(void) { + txc.output = 0; + txc.accumulator = 0; + txc.inverter = 0; + txc.staging = 0; + txc.increase = 0; + txc.Y = 0; + txc.mask = txc.isJV001 ? 0x0F : 0x07; + txc.invert = txc.isJV001 ? 0xFF : 0x00; + + WSync(); +} + +static void GenTXCPower(void) { + TXCRegReset(); +} + +static void TXCClose(void) { +} + +static void StateRestore(int version) { + WSync(); +} + +static void GenTXC_Init(CartInfo *info, void (*proc)(void), uint32 jv001) { + txc.isJV001 = jv001; + WSync = proc; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, 0); +} + +static int CheckHash(CartInfo *info) { + int x, i = 0; + uint64 partialmd5 = 0; + + /* These carts do not work with new mapper implementation. + * This is a hack to use previous mapper implementation for such carts. */ + for (x = 0; x < 8; x++) + partialmd5 |= (uint64)info->MD5[15 - x] << (x * 8); + switch (partialmd5) { + case 0x2dd8f958850f21f4LL: /* Jin Gwok Sei Chuen Saang (Ch) [U][!] */ + FCEU_printf(" WARNING: Using alternate mapper implementation.\n"); + UNL22211_Init(info); + return 1; + } + return 0; +} + +/* --------------- Mapper 36 --------------- */ + +static uint8 creg = 0; + +static void M36Sync(void) { + setprg32(0x8000, txc.output & 0x03); + setchr8(creg & 0x0F); +} + +static DECLFW(M36Write) { + if ((A & 0xF200) == 0x4200) creg = V; + TXC_CMDWrite(A, (V >> 4) & 0x03); +} + +static DECLFR(M36Read) { + uint8 ret = X.DB; + if ((A & 0x103) == 0x100) + ret = (X.DB & 0xCF) | ((TXC_CMDRead() << 4) & 0x30); + return ret; +} + +static void M36Power(void) { + creg = 0; + GenTXCPower(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4100, 0x5FFF, M36Read); + SetWriteHandler(0x4100, 0xFFFF, M36Write); +} + +void Mapper36_Init(CartInfo *info) { + GenTXC_Init(info, M36Sync, 0); + info->Power = M36Power; + AddExState(&creg, 1, 0, "CREG"); +} + +/* --------------- Mapper 132 --------------- */ + +static void M132Sync(void) { + setprg32(0x8000, (txc.output >> 2) & 0x01); + setchr8(txc.output & 0x03); +} + +static DECLFW(M132Write) { + TXC_CMDWrite(A, V & 0x0F); +} + +static DECLFR(M132Read) { + uint8 ret = X.DB; + if ((A & 0x103) == 0x100) + ret = ((X.DB & 0xF0) | (TXC_CMDRead() & 0x0F)); + return ret; +} + +static void M132Power(void) { + GenTXCPower(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4100, 0x5FFF, M132Read); + SetWriteHandler(0x4100, 0xFFFF, M132Write); +} + +void Mapper132_Init(CartInfo *info) { + if (CheckHash(info) != 0) return; + GenTXC_Init(info, M132Sync, 0); + info->Power = M132Power; +} + +/* --------------- Mapper 173 --------------- */ + +static void M173Sync(void) { + setprg32(0x8000, 0); + if (CHRsize[0] > 0x2000) + setchr8(((txc.output & 0x01) | (txc.Y ? 0x02 : 0x00) | ((txc.output & 2) << 0x01))); + else + setchr8(0); +} + +void Mapper173_Init(CartInfo *info) { + GenTXC_Init(info, M173Sync, 0); + info->Power = M132Power; +} + +/* ---------------- Joy/Van ----------------- */ + +/* --------------- Mapper 136 --------------- */ + +static void M136Sync(void) { + setprg32(0x8000, (txc.output >> 4) & 0x01); + setchr8(txc.output & 0x07); +} + +static DECLFW(M136Write) { + TXC_CMDWrite(A, V & 0x3F); +} + +static DECLFR(M136Read) { + uint8 ret = X.DB; + if ((A & 0x103) == 0x100) + ret = ((X.DB & 0xC0) | (TXC_CMDRead() & 0x3F)); + return ret; +} + +static void M136Power(void) { + GenTXCPower(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4100, 0x5FFF, M136Read); + SetWriteHandler(0x4100, 0xFFFF, M136Write); +} + +void Mapper136_Init(CartInfo *info) { + GenTXC_Init(info, M136Sync, 1); + info->Power = M136Power; +} + +/* --------------- Mapper 147 --------------- */ + +static void M147Sync(void) { + setprg32(0x8000, ((txc.output >> 4) & 0x02) | (txc.output & 0x01)); + setchr8((txc.output >> 1) & 0x0F); +} + +static DECLFW(M147Write) { + TXC_CMDWrite(A, ((V >> 2) & 0x3F) | ((V << 6) & 0xC0)); +} + +static DECLFR(M147Read) { + uint8 ret = X.DB; + if ((A & 0x103) == 0x100) { + uint8 value = TXC_CMDRead(); + ret = ((value << 2) & 0xFC) | ((value >> 6) & 0x03); + } + return ret; +} + +static void M147Power(void) { + GenTXCPower(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4100, 0x5FFF, M147Read); + SetWriteHandler(0x4100, 0xFFFF, M147Write); +} + +void Mapper147_Init(CartInfo *info) { + GenTXC_Init(info, M147Sync, 1); + info->Power = M147Power; +} + +/* --------------- Mapper 172 --------------- */ + +static void M172Sync(void) { + setprg32(0x8000, 0); + setchr8(txc.output); + setmirror(txc.invert ? 1 : 0); +} + +static uint8 GetValue(uint8 value) { + return (((value << 5) & 0x20) | ((value << 3) & 0x10) | ((value << 1) & 0x08) | + ((value >> 1) & 0x04) | ((value >> 3) & 0x02) | ((value >> 5) & 0x01)); +} + +static DECLFW(M172Write) { + TXC_CMDWrite(A, GetValue(V)); +} + +static DECLFR(M172Read) { + uint8 ret = X.DB; + if ((A & 0x103) == 0x100) + ret = (X.DB & 0xC0) | GetValue(TXC_CMDRead()); + return ret; +} + +static void M172Power(void) { + GenTXCPower(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4100, 0x5FFF, M172Read); + SetWriteHandler(0x4100, 0xFFFF, M172Write); +} + +void Mapper172_Init(CartInfo *info) { + GenTXC_Init(info, M172Sync, 1); + info->Power = M172Power; +} + +/* === LEGACY MAPPER IMPLEMENTATION === */ + +static uint8 reg[4], cmd, is172, is173; + +static SFORMAT UNL22211StateRegs[] = +{ + { reg, 4, "REGS" }, + { &cmd, 1, "CMD" }, + { 0 } +}; + +static void UNL22211Sync(void) { + setprg32(0x8000, (reg[2] >> 2) & 1); + if (is172) + setchr8((((cmd ^ reg[2]) >> 3) & 2) | (((cmd ^ reg[2]) >> 5) & 1)); /* 1991 DU MA Racing probably CHR bank sequence is WRONG, so it is possible to + * rearrange CHR banks for normal UNIF board and mapper 172 is unneccessary */ + else + setchr8(reg[2] & 3); +} + +static DECLFW(UNL22211WriteLo) { +/* FCEU_printf("bs %04x %02x\n",A,V); */ + reg[A & 3] = V; +} + +static DECLFW(UNL22211WriteHi) { +/* FCEU_printf("bs %04x %02x\n",A,V); */ + cmd = V; + UNL22211Sync(); +} + +static DECLFR(UNL22211ReadLo) { + return (reg[1] ^ reg[2]) | (is173 ? 0x01 : 0x40); +#if 0 + if(reg[3]) + return reg[2]; + else + return X.DB; +#endif +} + +static void UNL22211Power(void) { + UNL22211Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4100, 0x4100, UNL22211ReadLo); + SetWriteHandler(0x4100, 0x4103, UNL22211WriteLo); + SetWriteHandler(0x8000, 0xFFFF, UNL22211WriteHi); +} + +static void UNL22211StateRestore(int version) { + UNL22211Sync(); +} + +void UNL22211_Init(CartInfo *info) { + is172 = 0; + is173 = 0; + info->Power = UNL22211Power; + GameStateRestore = UNL22211StateRestore; + AddExState(&UNL22211StateRegs, ~0, 0, 0); +} diff --git a/src/ines-correct.h b/src/ines-correct.h index b18c35f..f2d4cb2 100644 --- a/src/ines-correct.h +++ b/src/ines-correct.h @@ -359,6 +359,14 @@ {0xa3ac0095, 189, -1}, /* Street Fighter II - The World Warrior (Unl) [a2].nes */ {0xeced5899, 121, -1}, /* Ultimate Mortal Kombat 4 (Unl) [!].nes */ + /* TXC / Sachen / JoyVan */ + + /* This cart does not work anymore with latest mapper implementation. + * This will be run using alternate mapper using override in m132 */ + {0x2a5f4c5a, 132, -1}, /* /Zhan Guo Si Chuan Sheng (C&E) (Unl).nes */ + + {0x0acfc3cd, 132, -1}, /* Mahjong Block (MGC-008) (Unl) [!].nes */ + /* ines mappers that uses iNes 2.0 numbers */ {0xf6bd8e31, 281, 0}, /* 1997 Super HIK 4-in-1 (JY-052) [p1][!] */ diff --git a/src/ines.c b/src/ines.c index 7b24030..061f5f6 100644 --- a/src/ines.c +++ b/src/ines.c @@ -526,12 +526,12 @@ static BMAPPINGLocal bmap[] = { /* {(uint8_t*)"", 129, Mapper129_Init}, */ /* {(uint8_t*)"", 130, Mapper130_Init}, */ /* {(uint8_t*)"", 131, Mapper131_Init}, */ - {(uint8_t*)"TXC/MGENIUS 22111", 132, UNL22211_Init}, + {(uint8_t*)"TXC/UNL-22211", 132, Mapper132_Init}, {(uint8_t*)"SA72008", 133, SA72008_Init}, /* {(uint8_t*)"MMC3 BMC PIRATE", 134, Mapper134_Init}, */ {(uint8_t*)"MMC3 BMC PIRATE", 134, Bs5652_Init}, /* {(uint8_t*)"", 135, Mapper135_Init}, */ - {(uint8_t*)"TCU02", 136, TCU02_Init}, + {(uint8_t*)"Sachen 3011", 136, Mapper136_Init}, {(uint8_t*)"S8259D", 137, S8259D_Init}, {(uint8_t*)"S8259B", 138, S8259B_Init}, {(uint8_t*)"S8259C", 139, S8259C_Init}, @@ -542,7 +542,7 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"AGCI 50282", 144, Mapper144_Init}, {(uint8_t*)"SA72007", 145, SA72007_Init}, {(uint8_t*)"SA0161M", 146, SA0161M_Init}, - {(uint8_t*)"TCU01", 147, TCU01_Init}, + {(uint8_t*)"Sachen 3018 board", 147, Mapper147_Init}, {(uint8_t*)"SA0037", 148, SA0037_Init}, {(uint8_t*)"SA0036", 149, SA0036_Init}, {(uint8_t*)"SA-015/SA-630", 150, S74LS374N_Init}, @@ -567,8 +567,8 @@ static BMAPPINGLocal bmap[] = { /* {(uint8_t*)"", 169, Mapper169_Init}, */ {(uint8_t*)"", 170, Mapper170_Init}, {(uint8_t*)"", 171, Mapper171_Init}, - {(uint8_t*)"", 172, Mapper172_Init}, - {(uint8_t*)"", 173, Mapper173_Init}, + {(uint8_t*)"Super Mega P-4070", 172, Mapper172_Init}, + {(uint8_t*)"Idea-Tek ET.xx", 173, Mapper173_Init}, /* {(uint8_t*)"", 174, Mapper174_Init}, */ {(uint8_t*)"", 175, Mapper175_Init}, {(uint8_t*)"BMCFK23C", 176, BMCFK23C_Init}, /* zero 26-may-2012 - well, i have some WXN junk games that use 176 for instance ????. i dont know what game uses this BMCFK23C as mapper 176. we'll have to make a note when we find it. */ diff --git a/src/ines.h b/src/ines.h index d54c8b1..6f37f89 100644 --- a/src/ines.h +++ b/src/ines.h @@ -148,9 +148,12 @@ void Mapper120_Init(CartInfo *); void Mapper121_Init(CartInfo *); void Mapper125_Init(CartInfo *); void Mapper126_Init(CartInfo *); +void Mapper132_Init(CartInfo *); void Mapper134_Init(CartInfo *); +void Mapper136_Init(CartInfo *); void Mapper140_Init(CartInfo *); void Mapper144_Init(CartInfo *); +void Mapper147_Init(CartInfo *); void Mapper151_Init(CartInfo *); void Mapper152_Init(CartInfo *); void Mapper153_Init(CartInfo *); diff --git a/src/unif.c b/src/unif.c index 82d91f0..674d240 100644 --- a/src/unif.c +++ b/src/unif.c @@ -418,7 +418,7 @@ static BMAPPING bmap[] = { { "12-IN-1", 331, BMC12IN1_Init, 0 }, { "13in1JY110", 295, BMC13in1JY110_Init, 0 }, { "190in1", 300, BMC190in1_Init, 0 }, - { "22211", 132, UNL22211_Init, 0 }, + { "22211", 132, Mapper132_Init, 0 }, { "3D-BLOCK", 355, UNL3DBlock_Init, 0 }, { "411120-C", 287, BMC411120C_Init, 0 }, { "42in1ResetSwitch", 233, Mapper233_Init, 0 }, @@ -493,7 +493,7 @@ static BMAPPING bmap[] = { { "PEC-586", NO_INES, UNLPEC586Init, 0 }, { "RROM", 0, NROM_Init, 0 }, { "RROM-128", 0, NROM_Init, 0 }, - { "SA-002", 136, TCU02_Init, 0 }, + { "SA-002", 136, Mapper136_Init, 0 }, { "SA-0036", 149, SA0036_Init, 0 }, { "SA-0037", 148, SA0037_Init, 0 }, { "SA-009", 160, SA009_Init, 0 }, @@ -532,7 +532,7 @@ static BMAPPING bmap[] = { { "T-230", 529, UNLT230_Init, 0 }, { "T-262", 265, BMCT262_Init, 0 }, { "TBROM", 4, TBROM_Init, 0 }, - { "TC-U01-1.5M", 147, TCU01_Init, 0 }, + { "TC-U01-1.5M", 147, Mapper147_Init, 0 }, { "TEK90", 90, Mapper90_Init, 0 }, { "TEROM", 4, TEROM_Init, 0 }, { "TF1201", 298, UNLTF1201_Init, 0 }, diff --git a/src/unif.h b/src/unif.h index b7dce10..bc2b4da 100644 --- a/src/unif.h +++ b/src/unif.h @@ -94,8 +94,6 @@ void Super24_Init(CartInfo *info); void Supervision16_Init(CartInfo *info); void TBROM_Init(CartInfo *info); void TCA01_Init(CartInfo *info); -void TCU01_Init(CartInfo *info); -void TCU02_Init(CartInfo *info); void TEROM_Init(CartInfo *info); void TFROM_Init(CartInfo *info); void TGROM_Init(CartInfo *info); From 86aad39c3d38ebb5a703857b78ac49d1daa42936 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Mon, 17 Feb 2020 01:16:11 +0800 Subject: [PATCH 11/13] Buildfix --- src/boards/mmc1.c | 4 ++-- src/unif.c | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/boards/mmc1.c b/src/boards/mmc1.c index 669399d..c93fdb4 100644 --- a/src/boards/mmc1.c +++ b/src/boards/mmc1.c @@ -232,8 +232,8 @@ static int DetectMMC1WRAMSize(CartInfo *info, int *saveRAM) { break; default: if (info->iNES2) { - workRAM = (info->prgRam + info->prgRam_battery) / 1024; - *saveRAM = info->prgRam_battery / 1024; + workRAM = (info->PRGRamSize + info->PRGRamSaveSize) / 1024; + *saveRAM = info->PRGRamSaveSize / 1024; /* we only support sizes between 8K and 32K */ if (workRAM > 0 && workRAM < 8) workRAM = 8; diff --git a/src/unif.c b/src/unif.c index 674d240..3ee42ce 100644 --- a/src/unif.c +++ b/src/unif.c @@ -39,6 +39,7 @@ #include "fceu-memory.h" #include "input.h" #include "md5.h" +#include "crc32.h" #include "string/stdstring.h" @@ -799,8 +800,8 @@ int UNIFLoad(const char *name, FCEUFILE *fp) { if (UNIFCart.mapper) FCEU_printf(" [Unif] Mapper: %d\n", UNIFCart.mapper); FCEU_printf(" [Unif] SubMapper: %d\n", UNIFCart.submapper); - FCEU_printf(" [Unif] PRG ROM: %ull KiB\n", UNIF_PRGROMSize / 1024); - FCEU_printf(" [Unif] CHR ROM: %ull KiB\n", UNIF_CHRROMSize / 1024); + FCEU_printf(" [Unif] PRG ROM: %u KiB\n", UNIF_PRGROMSize / 1024); + FCEU_printf(" [Unif] CHR ROM: %u KiB\n", UNIF_CHRROMSize / 1024); GameInterface = UNIFGI; return 1; From ddb1fe786a0f45b03e278054e35ba0542b041286 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Mon, 17 Feb 2020 01:55:28 +0800 Subject: [PATCH 12/13] Add UNIF BMC-WX-KB4K (m134) to supported boards --- src/unif.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/unif.c b/src/unif.c index 3ee42ce..abb829a 100644 --- a/src/unif.c +++ b/src/unif.c @@ -606,6 +606,7 @@ static BMAPPING bmap[] = { { "GN-26", 344, BMCGN26_Init, 0 }, { "KG256", NO_INES,KG256_Init, 0 }, { "T4A54A", 134, Bs5652_Init, 0 }, + { "WX-KB4K", 134, Bs5652_Init, 0 }, { "SB-5013", 359, Mapper359_Init, 0 }, { "82112C", 540, Mapper540_Init, 0 }, From f9fb33d8e820ffdb5b379ab8fe511e4f970de4dd Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Mon, 17 Feb 2020 10:11:55 +0800 Subject: [PATCH 13/13] Silence warnings and fixes - Silence warning [-Wmaybe-uninitialized] - m359: Fix value overflow - m534: Silence warnings - mmc1: Silence warnings - Silence more warnings --- src/boards/28.c | 4 ++-- src/boards/359.c | 2 +- src/boards/534.c | 15 ++++----------- src/boards/bmc60311c.c | 2 ++ src/boards/mmc1.c | 9 +++++---- src/boards/txcchip.c | 7 ++----- src/drivers/libretro/libretro.c | 3 +-- src/fceu.c | 2 +- src/unif.c | 2 +- 9 files changed, 19 insertions(+), 27 deletions(-) diff --git a/src/boards/28.c b/src/boards/28.c index 4fdd088..0daf2f3 100644 --- a/src/boards/28.c +++ b/src/boards/28.c @@ -56,8 +56,8 @@ void Mirror(uint8 value) static void Sync() { - uint8 prglo; - uint8 prghi; + uint8 prglo = 0; + uint8 prghi = 0; uint8 outb = outer << 1; diff --git a/src/boards/359.c b/src/boards/359.c index 35a533d..535be26 100644 --- a/src/boards/359.c +++ b/src/boards/359.c @@ -24,7 +24,7 @@ #include "mapinc.h" -static uint8 mapperNum; +static uint32 mapperNum; static uint8 preg[4]; static uint8 creg[8]; static uint8 exRegs[4]; diff --git a/src/boards/534.c b/src/boards/534.c index 08e9096..3c5d247 100644 --- a/src/boards/534.c +++ b/src/boards/534.c @@ -30,10 +30,10 @@ static uint32 GetPRGBank(uint32 bank) } 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); + 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) { @@ -47,13 +47,6 @@ static void M534CW(uint32 A, uint8 V) { setchr1(A, (V & 0xFF) | ((EXPREGS[2] & 0x0F) << 3) | ((EXPREGS[0] & 0x18) << 4)); } -static DECLFR(M534Read) { - if (EXPREGS[1] & 0x01) - return (EXPREGS[4] | (X.DB & ~0x03)); - else - return CartBR(A); -} - static DECLFW(M534IRQWrite) { MMC3_IRQWrite(0xC000 | (A & 1), V ^ 0xFF); } diff --git a/src/boards/bmc60311c.c b/src/boards/bmc60311c.c index 03eaf11..9ea71fa 100644 --- a/src/boards/bmc60311c.c +++ b/src/boards/bmc60311c.c @@ -52,6 +52,8 @@ static void Sync(void) { */ preg[0] = bank; + preg[1] = 0; + switch (mode & 3) { case 0x00: case 0x01: diff --git a/src/boards/mmc1.c b/src/boards/mmc1.c index c93fdb4..b9698c6 100644 --- a/src/boards/mmc1.c +++ b/src/boards/mmc1.c @@ -335,7 +335,8 @@ static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int saveram) is155 = 0; info->Close = GenMMC1Close; - MMC1PRGHook16 = MMC1CHRHook4 = MMC1WRAMHook8 = 0; + MMC1PRGHook16 = MMC1CHRHook4 = 0; + MMC1WRAMHook8 = 0; WRAMSIZE = wram * 1024; NONSaveRAMSIZE = (wram - saveram) * 1024; PRGmask16[0] &= (prg >> 14) - 1; @@ -597,9 +598,9 @@ static void M543CHR4(uint32 A, uint8 V) { static void M543WRAM8(void) { uint32 wramBank; if (outerBank & 2) - wramBank = 4 | ((outerBank >> 1) & 2) | (outerBank & 1) ; - else - wramBank = ((outerBank << 1) & 2) | ((MMC1GetCHRBank(0) >> 3) & 1); + wramBank = 4 | ((outerBank >> 1) & 2) | (outerBank & 1) ; + else + wramBank = ((outerBank << 1) & 2) | ((MMC1GetCHRBank(0) >> 3) & 1); setprg8r(0x10, 0x6000, wramBank); } diff --git a/src/boards/txcchip.c b/src/boards/txcchip.c index d2c0ab8..c494c21 100644 --- a/src/boards/txcchip.c +++ b/src/boards/txcchip.c @@ -98,7 +98,7 @@ static DECLFW(TXC_CMDWrite) { if (txc.increase) txc.accumulator++; else - txc.accumulator = ((txc.accumulator & ~txc.mask) | (txc.staging ^ txc.invert) & txc.mask); + txc.accumulator = ((txc.accumulator & ~txc.mask) | ((txc.staging ^ txc.invert) & txc.mask)); break; case 0x101: txc.invert = (V & 0x01) ? 0xFF : 0x00; @@ -133,9 +133,6 @@ static void GenTXCPower(void) { TXCRegReset(); } -static void TXCClose(void) { -} - static void StateRestore(int version) { WSync(); } @@ -148,7 +145,7 @@ static void GenTXC_Init(CartInfo *info, void (*proc)(void), uint32 jv001) { } static int CheckHash(CartInfo *info) { - int x, i = 0; + int x = 0; uint64 partialmd5 = 0; /* These carts do not work with new mapper implementation. diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 7a77e88..85d0c99 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -81,7 +81,6 @@ static unsigned turbo_delay = 0; static unsigned input_type[MAX_PLAYERS + 1] = {0}; /* 4-players + famicom expansion */ enum RetroZapperInputModes{RetroLightgun, RetroMouse, RetroPointer}; static enum RetroZapperInputModes zappermode = RetroLightgun; -static unsigned show_advance_sound_options; /* emulator-specific variables */ @@ -2215,7 +2214,7 @@ bool retro_load_game(const struct retro_game_info *game) FCEU_printf(" Loading custom palette: %s%cnes.pal\n", dir, slash); /* Save region and dendy mode for region-auto detect */ - systemRegion = (dendy << 1) | retro_get_region() & 1; + systemRegion = (dendy << 1) | (retro_get_region() & 1); retro_set_custom_palette(); FCEUD_SoundToggle(); diff --git a/src/fceu.c b/src/fceu.c index b3cc164..de3f21b 100644 --- a/src/fceu.c +++ b/src/fceu.c @@ -396,7 +396,7 @@ void FCEU_MemoryRand(uint8 *ptr, uint32 size) *ptr = (x & 1) ? 0x55 : 0xAA; /* F-15 Sity War HISCORE is screwed... */ /* 1942 SCORE/HISCORE is screwed... */ #endif - uint8_t v; + uint8_t v = 0; switch (option_ramstate) { case 0: v = 0xff; break; diff --git a/src/unif.c b/src/unif.c index abb829a..18acb84 100644 --- a/src/unif.c +++ b/src/unif.c @@ -312,7 +312,7 @@ static int SetBoardName(FCEUFILE *fp) { FCEU_fread(boardname, 1, uchead.info, fp); boardname[uchead.info] = 0; /* strip whitespaces */ - boardname = string_trim_whitespace(boardname); + boardname = string_trim_whitespace((char const*)boardname); FCEU_printf(" Board name: %s\n", boardname); sboardname = boardname; if (!memcmp(boardname, "NES-", 4) || !memcmp(boardname, "UNL-", 4) ||