From 83b2f99527e5b4cd46259fa686c598e1926243c5 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Thu, 27 Jun 2019 12:22:07 +0800 Subject: [PATCH 1/5] Mapper134: Update and add support for UNL-T4A54A unif board --- src/boards/mmc3.c | 15 +++++++++++---- src/unif.c | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/boards/mmc3.c b/src/boards/mmc3.c index 083aa4e..b783b67 100644 --- a/src/boards/mmc3.c +++ b/src/boards/mmc3.c @@ -905,13 +905,19 @@ void Mapper119_Init(CartInfo *info) { } /* ---------------------------- Mapper 134 ------------------------------ */ +/* ---------------------------- UNL-T4A54A ------------------------------ */ + +/* UNL-T4A54A, functionally the same as mapper 134. + * Writes @ $6801. Menu @ prg $20000, chr $00000 */ static void M134PW(uint32 A, uint8 V) { - setprg8(A, (V & 0x1F) | ((EXPREGS[0] & 2) << 4)); + uint8 mask = (EXPREGS[0] & 0x04) ? 0x0F : 0x1F; + setprg8r(PRGptr[1] ? (EXPREGS[0] & 3) : 0, A, (V & mask) | ((EXPREGS[0] & 3) << 4)); } static void M134CW(uint32 A, uint8 V) { - setchr1(A, (V & 0xFF) | ((EXPREGS[0] & 0x20) << 3)); + uint8 mask = (EXPREGS[0] & 0x04) ? 0x7F : 0xFF; + setchr1r(PRGptr[1] ? (EXPREGS[0] & 0x30) >> 4 : 0, A, (V & mask) | ((EXPREGS[0] & 0x30) << 3)); } static DECLFW(M134Write) { @@ -921,13 +927,14 @@ static DECLFW(M134Write) { } static void M134Power(void) { - EXPREGS[0] = 0; + EXPREGS[0] = 0x01; GenMMC3Power(); SetWriteHandler(0x6001, 0x6001, M134Write); + SetWriteHandler(0x6801, 0x6801, M134Write); } static void M134Reset(void) { - EXPREGS[0] = 0; + EXPREGS[0] = 0x01; MMC3RegReset(); } diff --git a/src/unif.c b/src/unif.c index 567ba59..504a2b8 100644 --- a/src/unif.c +++ b/src/unif.c @@ -504,6 +504,7 @@ static BMAPPING bmap[] = { { "K-3033", BMCK3033_Init, 0 }, { "830134C", BMC830134C_Init, 0 }, { "GN-26", BMCGN26_Init, 0 }, + { "T4A54A", Mapper134_Init, 0 }, #ifdef COPYFAMI { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, From 634eb688c13d747e9c055fcc8ce530401cf3034e Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Fri, 28 Jun 2019 19:25:35 +0800 Subject: [PATCH 2/5] UNIF: Fix potential crash when accessing non-existing rom banks - As stated, prevent a potential crash on some certain roms using split rom banks. This is done by counting the number of prg/chr banks loaded and using this as limit count during mapper bank switching. - Update related boards. --- src/boards/8157.c | 14 +++++++------- src/boards/ax40g.c | 5 ----- src/boards/bmcgamecard.c | 2 +- src/boards/bmck3088.c | 29 ++++++++++++++++++----------- src/boards/gn26.c | 2 +- src/boards/mmc3.c | 32 ++++++++++++++++++++++++-------- src/boards/resettxrom.c | 16 ++++++++++++++-- src/boards/t-262.c | 7 +++++-- src/cart.c | 5 +++++ src/cart.h | 3 +++ src/unif.c | 14 +++++++++++++- 11 files changed, 91 insertions(+), 38 deletions(-) diff --git a/src/boards/8157.c b/src/boards/8157.c index f62cb8f..1d72957 100644 --- a/src/boards/8157.c +++ b/src/boards/8157.c @@ -23,6 +23,7 @@ #include "mapinc.h" +static uint8 chip; static uint16 cmdreg; static uint8 reset; static SFORMAT StateRegs[] = @@ -36,13 +37,12 @@ static void Sync(void) { uint32 base = ((cmdreg & 0x060) | ((cmdreg & 0x100) >> 1)) >> 2; uint32 bank = (cmdreg & 0x01C) >> 2; uint32 lbank = (cmdreg & 0x200) ? 7 : ((cmdreg & 0x80) ? bank : 0); - /* this fails to load at least one game, which probably has invalid PRG size in header - * (rom is only 512KB but reported as having 3 prg banks with 128k each) */ - /*if (PRGptr[1]) { - setprg16r(base >> 3, 0x8000, bank); // for versions with split ROMs - setprg16r(base >> 3, 0xC000, lbank); - } else*/ - { + if (PRGptr[1]) { + chip = base >> 3; + if (chip > PRGchip_max) chip &= PRGchip_max; + setprg16r(chip, 0x8000, bank); /* for versions with split ROMs */ + setprg16r(chip, 0xC000, lbank); + } else { setprg16(0x8000, base | bank); setprg16(0xC000, base | lbank); } diff --git a/src/boards/ax40g.c b/src/boards/ax40g.c index f3fe1d1..b372574 100644 --- a/src/boards/ax40g.c +++ b/src/boards/ax40g.c @@ -88,8 +88,3 @@ void UNLAX40G_Init(CartInfo *info) { GameStateRestore = StateRestore; AddExState(&StateRegs, ~0, 0, 0); } - -/*void UNLAX40G_Init(CartInfo *info); // m527 -{ "AX-40G", UNLAX40G_Init, 0 }, -{ "JC-016-2", Mapper205_Init, 0 }, -*/ diff --git a/src/boards/bmcgamecard.c b/src/boards/bmcgamecard.c index e634abd..0cc58af 100644 --- a/src/boards/bmcgamecard.c +++ b/src/boards/bmcgamecard.c @@ -41,7 +41,7 @@ static SFORMAT StateRegs[] = static void Sync(void) { uint8 mirroring = m350 ? ((latche >> 7) & 1) : ((latche >> 5) & 1); uint8 mode = m350 ? ((latche >> 5) & 0x03) : ((latche >> 6) & 0x03); - uint8 chip = m350 ? ((mode & 2) ? ((latche >> 5) & 1) : 0) : 0; + uint8 chip = m350 ? ((latche & 0x40) ? ((latche & 0x20) >> 5) : 0) : 0; setchr8(0); setprg8(0x6000, 1); diff --git a/src/boards/bmck3088.c b/src/boards/bmck3088.c index e59c38c..588a65a 100644 --- a/src/boards/bmck3088.c +++ b/src/boards/bmck3088.c @@ -24,24 +24,31 @@ #include "mapinc.h" #include "mmc3.h" +static uint8 chip; + static void BMCK3088CW(uint32 A, uint8 V) { - if (CHRptr[EXPREGS[0] & 7]) - setchr1r(EXPREGS[0] & 7, A, V); - else + if (CHRptr[1]) { + chip = EXPREGS[0] & 7; + if (chip > CHRchip_max) chip &= CHRchip_max; + setchr1r(chip, A, V); + } else setchr1(A, V | ((EXPREGS[0] & 3) << 7)); } static void BMCK3088PW(uint32 A, uint8 V) { - if (PRGptr[EXPREGS[0] & 7]) { - uint8 chip = EXPREGS[0] & 7; - if (EXPREGS[0] & 8) - setprg32r(chip, 0x8000, ((EXPREGS[0] >> 4) & 3)); - else + if (PRGptr[1]) { + chip = EXPREGS[0] & 7; + if (chip > PRGchip_max) chip &= PRGchip_max; + if (EXPREGS[0] & 8) { + if (A == 0x8000) + setprg32r(chip, A, ((EXPREGS[0] >> 4) & 3)); + } else setprg8r(chip, A, (V & 0x0F)); } else { - if (EXPREGS[0] & 8) - setprg32(0x8000, ((EXPREGS[0] >> 4) & 3) | (0x0C)); - else + if (EXPREGS[0] & 8) { + if (A == 0x8000) + setprg32(A, ((EXPREGS[0] >> 4) & 3) | (0x0C)); + } else setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 3) << 4)); } } diff --git a/src/boards/gn26.c b/src/boards/gn26.c index a712cc2..b55967d 100644 --- a/src/boards/gn26.c +++ b/src/boards/gn26.c @@ -1,7 +1,7 @@ /* FCEUmm - NES/Famicom Emulator * * Copyright notice for this file: - * + * Copyright (C) 2019 Libretro Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/boards/mmc3.c b/src/boards/mmc3.c index b783b67..93d36b6 100644 --- a/src/boards/mmc3.c +++ b/src/boards/mmc3.c @@ -44,6 +44,8 @@ uint8 mmc3opts = 0; uint8 IRQCount, IRQLatch, IRQa; uint8 IRQReload; +static uint8 chip; + static SFORMAT MMC3_StateRegs[] = { { DRegBuf, 8, "REGS" }, @@ -912,12 +914,22 @@ void Mapper119_Init(CartInfo *info) { static void M134PW(uint32 A, uint8 V) { uint8 mask = (EXPREGS[0] & 0x04) ? 0x0F : 0x1F; - setprg8r(PRGptr[1] ? (EXPREGS[0] & 3) : 0, A, (V & mask) | ((EXPREGS[0] & 3) << 4)); + if (PRGptr[1]) { + chip = (EXPREGS[0] & 3); + if (chip > PRGchip_max) chip &= PRGchip_max; + setprg8r(chip, A, (V & mask)); + } else + setprg8(A, (V & mask) | ((EXPREGS[0] & 3) << 4)); } static void M134CW(uint32 A, uint8 V) { uint8 mask = (EXPREGS[0] & 0x04) ? 0x7F : 0xFF; - setchr1r(PRGptr[1] ? (EXPREGS[0] & 0x30) >> 4 : 0, A, (V & mask) | ((EXPREGS[0] & 0x30) << 3)); + if (CHRptr[1]) { + chip = (EXPREGS[0] & 0x30) >> 4; + if (chip > CHRchip_max) chip &= CHRchip_max; + setchr1r(chip, A, (V & mask)); + } else + setchr1(A, (V & mask) | ((EXPREGS[0] & 0x30) << 3)); } static DECLFW(M134Write) { @@ -1200,17 +1212,21 @@ static uint8 block[] = {0, 0, 1, 2}; static void M205PW(uint32 A, uint8 V) { uint8 bank = V & ((EXPREGS[0] & 0x02) ? 0x0F : 0x1F); - if (PRGptr[1]) - setprg8r(block[EXPREGS[0]], A, bank); - else + if (PRGptr[1]) { + chip = block[EXPREGS[0]]; + if (chip > PRGchip_max) chip &= PRGchip_max; + setprg8r(chip, A, bank); + } else setprg8(A, EXPREGS[0] << 4 | bank); } static void M205CW(uint32 A, uint8 V) { uint8 bank = V & ((EXPREGS[0] & 0x02) ? 0x7F : 0xFF); - if (PRGptr[1]) - setchr1r(block[EXPREGS[0]], A, bank); - else + if (CHRptr[1]) { + chip = block[EXPREGS[0]]; + if (chip > CHRchip_max) chip &= CHRchip_max; + setchr1r(chip, A, bank); + } else setchr1(A, (EXPREGS[0] << 7) | bank); } diff --git a/src/boards/resettxrom.c b/src/boards/resettxrom.c index e4bced0..039b5c8 100644 --- a/src/boards/resettxrom.c +++ b/src/boards/resettxrom.c @@ -27,12 +27,24 @@ #include "mapinc.h" #include "mmc3.h" +static uint8 chip; + static void M313CW(uint32 A, uint8 V) { - setchr1r(CHRptr[1] ? EXPREGS[0] : 0, A, (EXPREGS[0] << 7) | (V & 0x7F)); + if (CHRptr[1]) { + chip = EXPREGS[0]; + if (chip > CHRchip_max) chip &= CHRchip_max; + setchr1r(chip, A, (V & 0x7F)); + } else + setchr1(A, (EXPREGS[0] << 7) | (V & 0x7F)); } static void M313PW(uint32 A, uint8 V) { - setprg8r(PRGptr[1] ? EXPREGS[0] : 0, A, (EXPREGS[0] << 4) | (V & 0x0F)); + if (PRGptr[1]) { + chip = EXPREGS[0]; + if (chip > PRGchip_max) chip &= PRGchip_max; + setprg8r(chip, A, (V & 0x0F)); + } else + setprg8(A, (EXPREGS[0] << 4) | (V & 0x0F)); } static void M313Reset(void) { diff --git a/src/boards/t-262.c b/src/boards/t-262.c index d887ef6..7806d56 100644 --- a/src/boards/t-262.c +++ b/src/boards/t-262.c @@ -20,6 +20,7 @@ #include "mapinc.h" +static uint8 chip; static uint8 bank, base, lock, mirr, mode; static SFORMAT StateRegs[] = { @@ -34,8 +35,10 @@ static SFORMAT StateRegs[] = static void Sync(void) { setchr8(0); if (PRGptr[1]) { - setprg16r(base >> 3, 0x8000, bank); - setprg16r(base >> 3, 0xC000, (mode ? bank : 7)); + chip = base >> 3; + if (chip > PRGchip_max) chip &= PRGchip_max; + setprg16r(chip, 0x8000, bank); + setprg16r(chip, 0xC000, (mode ? bank : 7)); } else { setprg16(0x8000, base | bank); setprg16(0xC000, base | (mode ? bank : 7)); diff --git a/src/cart.c b/src/cart.c index 911cb0c..d0b7cd1 100644 --- a/src/cart.c +++ b/src/cart.c @@ -53,6 +53,9 @@ static int PRGram[32]; uint8 *PRGptr[32]; uint8 *CHRptr[32]; +uint32 PRGchip_max; +uint32 CHRchip_max; + uint32 PRGsize[32]; uint32 CHRsize[32]; @@ -104,6 +107,8 @@ void ResetCartMapping(void) { for (x = 0; x < 8; x++) { MMC5SPRVPage[x] = MMC5BGVPage[x] = VPageR[x] = nothing - 0x400 * x; } + PRGchip_max = 0; + CHRchip_max = 0; } void SetupCartPRGMapping(int chip, uint8 *p, uint32 size, int ram) { diff --git a/src/cart.h b/src/cart.h index 37eca2c..fbac352 100644 --- a/src/cart.h +++ b/src/cart.h @@ -40,6 +40,9 @@ DECLFW(CartBW); extern uint8 *PRGptr[32]; extern uint8 *CHRptr[32]; +extern uint32 PRGchip_max; +extern uint32 CHRchip_max; + extern uint32 PRGsize[32]; extern uint32 CHRsize[32]; diff --git a/src/unif.c b/src/unif.c index 504a2b8..a7c252b 100644 --- a/src/unif.c +++ b/src/unif.c @@ -73,6 +73,9 @@ static UNIF_HEADER uchead; static uint8 *malloced[32]; static uint32 mallocedsizes[32]; +static uint32 prg_chip_count; +static uint32 chr_chip_count; + static int FixRomSize(uint32 size, uint32 minimum) { uint32 x = 1; @@ -107,6 +110,8 @@ static void ResetUNIF(void) { mirrortodo = 0; memset(&UNIFCart, 0, sizeof(UNIFCart)); UNIFchrrama = 0; + prg_chip_count = 0; + chr_chip_count = 0; } static uint8 exntar[2048]; @@ -272,6 +277,7 @@ static int LoadPRG(FCEUFILE *fp) { FCEU_printf("\n"); */ SetupCartPRGMapping(z, malloced[z], t, 0); + prg_chip_count++; return(1); } @@ -307,6 +313,7 @@ static int LoadCHR(FCEUFILE *fp) { FCEU_printf("\n"); */ SetupCartCHRMapping(z, malloced[16 + z], t, 0); + chr_chip_count++; return(1); } @@ -584,12 +591,17 @@ static int InitializeBoard(void) { if (bmap[x].flags & BMCFLAG_FORCE4) mirrortodo = 4; MooMirroring(); + + PRGchip_max = prg_chip_count - 1; + if (chr_chip_count) + CHRchip_max = chr_chip_count - 1; + bmap[x].init(&UNIFCart); return(1); } x++; } - FCEU_PrintError("Board type not supported.", boardname); + FCEU_PrintError("Board type not supported, '%s'.", boardname); return(0); } From dce349932cce7b7a9aa629382b6b586ed8828306 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sat, 29 Jun 2019 16:09:44 +0800 Subject: [PATCH 3/5] BMC-411120-C/K-3088: Update PRG banking. Combine both boards - Both are functionally the same, only dipswitch is different. - These boards are assigned as NES 2.0 287 mapper in wiki --- src/boards/411120-c.c | 50 +++++++++++++++++++++++---- src/boards/bmck3088.c | 79 ------------------------------------------- 2 files changed, 44 insertions(+), 85 deletions(-) delete mode 100644 src/boards/bmck3088.c diff --git a/src/boards/411120-c.c b/src/boards/411120-c.c index a4c30e0..706f192 100644 --- a/src/boards/411120-c.c +++ b/src/boards/411120-c.c @@ -2,6 +2,7 @@ * * Copyright notice for this file: * Copyright (C) 2008 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 @@ -18,25 +19,51 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* actually cart ID is 811120-C, sorry ;) K-3094 - another ID */ +/* NES 2.0 Mapper 287 + * BMC-411120-C, actually cart ID is 811120-C, sorry ;) K-3094 - another ID + * - 4-in-1 (411120-C) + * - 4-in-1 (811120-C,411120-C) [p4][U] + * + * BMC-K-3088, similar to BMC-411120-C but without jumper or dipswitch + * - 19-in-1(K-3088)(810849-C)(Unl) + */ #include "mapinc.h" #include "mmc3.h" static uint8 reset_flag = 0; +static uint8 chip, isK3088; static void BMC411120CCW(uint32 A, uint8 V) { - setchr1(A, V | ((EXPREGS[0] & 3) << 7)); + if (CHRptr[1]) { + chip = EXPREGS[0] & 7; + if (chip > CHRchip_max) chip &= CHRchip_max; + setchr1r(chip, A, V); + } else + setchr1(A, V | ((EXPREGS[0] & 3) << 7)); } static void BMC411120CPW(uint32 A, uint8 V) { - if (EXPREGS[0] & (8 | reset_flag)) - setprg32(0x8000, ((EXPREGS[0] >> 4) & 3) | (0x0C)); - else - setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 3) << 4)); + if (PRGptr[1]) { + chip = EXPREGS[0] & 7; + if (chip > PRGchip_max) chip &= PRGchip_max; + if (EXPREGS[0] & (isK3088 ? 8 : (8 | reset_flag))) { /* 32K Mode */ + if (A == 0x8000) + setprg32r(chip, A, ((EXPREGS[0] >> 4) & 3)); + } else /* MMC3 Mode */ + setprg8r(chip, A, (V & 0x0F)); + } else { + if (EXPREGS[0] & (isK3088 ? 8 : (8 | reset_flag))) { /* 32K Mode */ + if (A == 0x8000) + /* bit 0-1 of register should be used as outer bank regardless of banking modes */ + setprg32(A, ((EXPREGS[0] >> 4) & 3) | ((EXPREGS[0] & 3) << 2)); + } else /* MMC3 Mode */ + setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 3) << 4)); + } } static DECLFW(BMC411120CLoWrite) { +/* printf("Wr: A:%04x V:%02x\n", A, V); */ EXPREGS[0] = A; FixMMC3PRG(MMC3_cmd); FixMMC3CHR(MMC3_cmd); @@ -55,6 +82,17 @@ static void BMC411120CPower(void) { } void BMC411120C_Init(CartInfo *info) { + isK3088 = 0; + GenMMC3_Init(info, 128, 128, 8, 0); + pwrap = BMC411120CPW; + cwrap = BMC411120CCW; + info->Power = BMC411120CPower; + info->Reset = BMC411120CReset; + AddExState(EXPREGS, 1, 0, "EXPR"); +} + +void BMCK3088_Init(CartInfo *info) { + isK3088 = 1; GenMMC3_Init(info, 128, 128, 8, 0); pwrap = BMC411120CPW; cwrap = BMC411120CCW; diff --git a/src/boards/bmck3088.c b/src/boards/bmck3088.c deleted file mode 100644 index 588a65a..0000000 --- a/src/boards/bmck3088.c +++ /dev/null @@ -1,79 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2019 Libretro Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 287 - * similar to BMC-411120-C but without jumper or dipswitch */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 chip; - -static void BMCK3088CW(uint32 A, uint8 V) { - if (CHRptr[1]) { - chip = EXPREGS[0] & 7; - if (chip > CHRchip_max) chip &= CHRchip_max; - setchr1r(chip, A, V); - } else - setchr1(A, V | ((EXPREGS[0] & 3) << 7)); -} - -static void BMCK3088PW(uint32 A, uint8 V) { - if (PRGptr[1]) { - chip = EXPREGS[0] & 7; - if (chip > PRGchip_max) chip &= PRGchip_max; - if (EXPREGS[0] & 8) { - if (A == 0x8000) - setprg32r(chip, A, ((EXPREGS[0] >> 4) & 3)); - } else - setprg8r(chip, A, (V & 0x0F)); - } else { - if (EXPREGS[0] & 8) { - if (A == 0x8000) - setprg32(A, ((EXPREGS[0] >> 4) & 3) | (0x0C)); - } else - setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 3) << 4)); - } -} - -static DECLFW(BMCK3088LoWrite) { - EXPREGS[0] = A; - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); -} - -static void BMCK3088Reset(void) { - EXPREGS[0] = 0; - MMC3RegReset(); -} - -static void BMCK3088Power(void) { - GenMMC3Power(); - SetWriteHandler(0x6000, 0x7FFF, BMCK3088LoWrite); -} - -void BMCK3088_Init(CartInfo *info) { - GenMMC3_Init(info, 128, 128, 8, 0); - pwrap = BMCK3088PW; - cwrap = BMCK3088CW; - info->Power = BMCK3088Power; - info->Reset = BMCK3088Reset; - AddExState(EXPREGS, 1, 0, "EXPR"); -} From 06c99179be2623f00c60086dc78420afeb84e8b2 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sun, 30 Jun 2019 16:41:17 +0800 Subject: [PATCH 4/5] Add support for Mapper 237 (Teletubies Y2K multicart) --- Makefile.common | 2 +- src/boards/237.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++ src/ines-correct.h | 1 + src/ines.c | 2 +- 4 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 src/boards/237.c diff --git a/Makefile.common b/Makefile.common index 88a46ff..4012987 100644 --- a/Makefile.common +++ b/Makefile.common @@ -11,7 +11,7 @@ COREDEFINES += -DPSS_STYLE=1 endif ifeq ($(TUP_CWD),) -FCEU_SRC_DIRS := $(CORE_DIR)/boards $(CORE_DIR)/input +FCEU_SRC_DIRS := $(CORE_DIR)/boards $(CORE_DIR)/input $(CORE_DIR)/mappers SOURCES_C := $(foreach dir,$(FCEU_SRC_DIRS),$(wildcard $(dir)/*.c)) else SOURCES_C = $(CORE_DIR)/boards/*.c $(CORE_DIR)/input/*.c diff --git a/src/boards/237.c b/src/boards/237.c new file mode 100644 index 0000000..e2b784a --- /dev/null +++ b/src/boards/237.c @@ -0,0 +1,91 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mapper 237 - "Teletubbies / Y2K" 420-in-1 pirate multicart. + * Dipswitch settings: + * 0: 42-in-1 + * 1: 5,000-in-1 + * 2: 420-in-1 + * 3: 10,000,000-in-1 (lol) + */ + +#include "mapinc.h" + +static uint8 reg[2]; +static uint8 dipswitch; + +static SFORMAT StateRegs[] = +{ + { ®[0], 1, "REG0" }, + { ®[1], 1, "REG1" }, + { &dipswitch, 1, "DPSW" }, + { 0 } +}; + +static void Sync(void) { + uint8 bank = (reg[1] & 0x07); + uint8 base = (reg[1] & 0x18) | ((reg[0] & 0x04) << 3); + uint8 mode = (reg[1] & 0xC0) >> 6; + + setchr8(0); + setprg16(0x8000, base | (bank & ~(mode & 1))); + setprg16(0xC000, base | ((mode & 0x02) ? (bank | (mode & 0x01)) : 0x07)); + setmirror(((reg[1] & 0x20) >> 5) ^ 1); +} + +static DECLFW(M237Write) { + if (!(reg[0] & 0x02)) { + reg[0] = A & 0x0F; + reg[1] = (reg[1] & 0x07) | (V & 0xF8); + } + reg[1] = (reg[1] & 0xF8) | (V & 0x07); + Sync(); +} + +static DECLFR(M237Read) { + if (!(reg[0] & 0x02) && (reg[0] & 0x01)) + return dipswitch; + return CartBR(A); +} + +static void M237Power(void) { + Sync(); + SetReadHandler (0x8000, 0xFFFF, M237Read); + SetWriteHandler(0x8000, 0xFFFF, M237Write); +} + +static void M237Reset(void) { + reg[0] = reg[1] = 0; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper237_Init(CartInfo *info) { + dipswitch = 0; + if ((info->CRC32) == 0x272709b9) /* Teletubbies Y2K (420-in-1) */ + dipswitch = 2; + info->Power = M237Power; + info->Reset = M237Reset; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/ines-correct.h b/src/ines-correct.h index e26aa65..85a8dbe 100644 --- a/src/ines-correct.h +++ b/src/ines-correct.h @@ -353,6 +353,7 @@ {0x071e4ee8, 114, 0}, /* m114,submapper 1 test rom */ {0xfe3e03a1, 197, -1}, /* Mortal Kombat III Special (YY-030) (Ch) [!] */ {0x9151d311, 197, -1}, /* Mortal Kombat III 28 Peoples (NT-328) (Ch) [!] */ + {0x272709b9, 237, -1}, /* Teletubbies Y2K (420-in-1) */ /* ines mappers that uses iNes 2.0 numbers */ diff --git a/src/ines.c b/src/ines.c index 8edac57..656337a 100644 --- a/src/ines.c +++ b/src/ines.c @@ -629,7 +629,7 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"BMC MAXI", 234, Mapper234_Init}, {(uint8_t*)"", 235, Mapper235_Init}, /* {(uint8_t*)"", 236, Mapper236_Init}, */ -/* {(uint8_t*)"", 237, Mapper237_Init}, */ + {(uint8_t*)"Teletubbies / Y2K", 237, Mapper237_Init}, {(uint8_t*)"UNL6035052", 238, UNL6035052_Init}, /* {(uint8_t*)"", 239, Mapper239_Init}, */ {(uint8_t*)"", 240, Mapper240_Init}, From 7e9b3b146d233fd09b2ab1b99dbb7819f1784621 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Tue, 2 Jul 2019 19:34:55 +0800 Subject: [PATCH 5/5] UNIF: Initial implementation of game overrides (move exiting ones out of mapper code) --- src/boards/datalatch.c | 60 +++++++++++++++++++++-------------- src/boards/resetnromxin1.c | 15 ++------- src/cart.h | 1 + src/unif.c | 65 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 37 deletions(-) diff --git a/src/boards/datalatch.c b/src/boards/datalatch.c index 1846bb7..c221310 100644 --- a/src/boards/datalatch.c +++ b/src/boards/datalatch.c @@ -153,27 +153,29 @@ static void CNROMSync(void) { } void CNROM_Init(CartInfo *info) { + unsigned _no_busc, _busc; + + _busc = 1; /* by default, CNROM is set to emulate bus conflicts to all games */ + _no_busc = 0; + + if (GameInfo->cspecial == 1) + _no_busc = 1; + /* TODO: move these to extended database when implemented. */ - int _busc, x; - uint64 partialmd5 = 0; - _busc = 1; - for (x = 0; x < 8; x++) - partialmd5 |= (uint64)info->MD5[15 - x] << (x * 8); - if (partialmd5 == 0x117181328eb1ad23LL) /* 75 Bingo (Sachen-English) [U].unf */ - _busc = 0; - else - switch (info->CRC32) { - case 0xf283cf58: /* Colorful Dragon (Asia) (PAL) (Unl).nes */ - case 0x2915faf0: /* Incantation (Asia) (Unl).nes */ - case 0xebd0644d: /* Dao Shuai (Asia) (Unl).nes */ - case 0x8f154a0d: /* Pu Ke Jing Ling (China) (Unl).nes */ - case 0xd04a40e6: /* Bingo 75 (Asia) (Unl).nes */ - case 0xe41b440f: /* Sidewinder (Joy Van) */ - case 0xb0c871c5: /* Wei Lai Xiao Zi (Joy Van) */ - case 0xb3be2f71: /* Yanshan Chess (Unl) */ - _busc = 0; - break; + switch (info->CRC32) { + case 0xf283cf58: /* Colorful Dragon (Asia) (PAL) (Unl).nes */ + case 0x2915faf0: /* Incantation (Asia) (Unl).nes */ + case 0xebd0644d: /* Dao Shuai (Asia) (Unl).nes */ + case 0x8f154a0d: /* Pu Ke Jing Ling (China) (Unl).nes */ + case 0xd04a40e6: /* Bingo 75 (Asia) (Unl).nes */ + case 0xe41b440f: /* Sidewinder (Joy Van) */ + case 0xb0c871c5: /* Wei Lai Xiao Zi (Joy Van) */ + case 0xb3be2f71: /* Yanshan Chess (Unl) */ + _no_busc = 1; + break; } + + if (_no_busc == 1) _busc = 0; Latch_Init(info, CNROMSync, 0, 0x8000, 0xFFFF, 1, _busc); } @@ -495,22 +497,32 @@ void Mapper241_Init(CartInfo *info) { * 16 bankswitching mode and normal mirroring... But there is no any * correlations between modes and they can be used in one mapper code. */ - +static int A65ASsubmapper; static void BMCA65ASSync(void) { if (latche & 0x40) setprg32(0x8000, (latche >> 1) & 0x0F); else { - setprg16(0x8000, ((latche & 0x30) >> 1) | (latche & 7)); - setprg16(0xC000, ((latche & 0x30) >> 1) | 7); + if (A65ASsubmapper == 1) { + setprg16(0x8000, ((latche & 0x38) >> 0) | (latche & 7)); + setprg16(0xC000, ((latche & 0x38) >> 0) | 7); + } else { + setprg16(0x8000, ((latche & 0x30) >> 1) | (latche & 7)); + setprg16(0xC000, ((latche & 0x30) >> 1) | 7); + } } setchr8(0); if (latche & 0x80) setmirror(MI_0 + (((latche >> 5) & 1))); - else - setmirror(((latche >> 3) & 1) ^ 1); + else { + if (A65ASsubmapper == 1) /* added as workaround since games for this cart uses vertical mirroring */ + setmirror(MI_V); + else + setmirror(((latche >> 3) & 1) ^ 1); + } } void BMCA65AS_Init(CartInfo *info) { + A65ASsubmapper = info->submapper; /* not a real submapper */ Latch_Init(info, BMCA65ASSync, 0, 0x8000, 0xFFFF, 0, 0); } diff --git a/src/boards/resetnromxin1.c b/src/boards/resetnromxin1.c index d17bc81..76c6e84 100644 --- a/src/boards/resetnromxin1.c +++ b/src/boards/resetnromxin1.c @@ -18,7 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* BMC-RESETNROM-XIN1 +/* NES 2.0 Mapper 343 + * BMC-RESETNROM-XIN1 * - Sheng Tian 2-in-1(Unl,ResetBase)[p1] - Kung Fu (Spartan X), Super Mario Bros (alt) * - Sheng Tian 2-in-1(Unl,ResetBase)[p2] - B-Wings, Twin-bee * @@ -58,18 +59,6 @@ static void StateRestore(int version) { } void BMCRESETNROMXIN1_Init(CartInfo *info) { - uint8 x; - uint64 partialmd5 = 0; - - for (x = 0; x < 8; x++) - partialmd5 |= (uint64)info->MD5[15 - x] << (x * 8); - - /* Mirroring override - these boards have incorrect mirroring for some reasons in their headers */ - if (partialmd5 == 0x616851e56946893bLL) /* Sheng Tian 2-in-1(Unl,ResetBase)[p1].unf */ - SetupCartMirroring(1, 1, NULL); - else if (partialmd5 == 0x4cd729b5ae23a3cfLL) /* Sheng Tian 2-in-1(Unl,ResetBase)[p2].unf */ - SetupCartMirroring(0, 1, NULL); - limit = 0x01; info->Power = BMCRESETNROMXIN1Power; info->Reset = BMCRESETNROMXIN1Reset; diff --git a/src/cart.h b/src/cart.h index fbac352..16ab243 100644 --- a/src/cart.h +++ b/src/cart.h @@ -11,6 +11,7 @@ typedef struct { /* Set by iNES/UNIF loading code. */ int mapper; /* mapper used */ + int submapper; /* submapper used */ /* TODO: */ int mirror; /* As set in the header or chunk. * iNES/UNIF specific. Intended * to help support games like "Karnov" diff --git a/src/unif.c b/src/unif.c index a7c252b..6072129 100644 --- a/src/unif.c +++ b/src/unif.c @@ -60,6 +60,8 @@ CartInfo UNIFCart; static int vramo; static int mirrortodo; +static int submapper; +static int cspecial; static uint8 *boardname; static uint8 *sboardname; @@ -317,6 +319,65 @@ static int LoadCHR(FCEUFILE *fp) { return(1); } +#define NO_BUSC 1 + +struct _unif_db { + uint64 partialMD5; + char *boardname; + int submapper; + int mirroring; + int special; /* TODO: for bus conflicts, set 1 for no bus_conflict */ +}; + +static struct _unif_db unif_db[] = { + { 0x8ebad077d08e6c78ULL, "A65AS", 1, -1 }, /* 3-in-1 (N080) [p1][U][!], not a real submapper */ + { 0x117181328eb1ad23ULL, "CNROM", 0, MI_H, NO_BUSC }, /* 75 Bingo (Sachen-English) [U] */ + { 0x616851e56946893bULL, "RESETNROM-XIN1", 0, MI_V }, /* Sheng Tian 2-in-1(Unl,ResetBase)[p1].unf */ + { 0x4cd729b5ae23a3cfULL, "RESETNROM-XIN1", 0, MI_H }, /* Sheng Tian 2-in-1(Unl,ResetBase)[p2].unf */ + + { 0, NULL, -1, -1, -1 } /* end of the line */ +}; + +static void CheckHashInfo(void) { + unsigned x = 0; + uint64 partialMD5 = 0; + + for (x = 0; x < 8; x++) + partialMD5 |= (uint64)UNIFCart.MD5[15 - x] << (x * 8); + + x = 0; + do { + if (partialMD5 == unif_db[x].partialMD5) { + FCEU_printf("\n"); + FCEU_PrintError(" The UNIF header contains incorrect information.\n"); + FCEU_PrintError(" For now, the information will be corrected in RAM.\n"); + if (unif_db[x].boardname != NULL && strcmp((char*)unif_db[x].boardname, (char*)sboardname) != 0) { + FCEU_printf(" Boardname should be set to %s\n", unif_db[x].boardname); + sboardname = unif_db[x].boardname; + } + if (unif_db[x].submapper >= 0 && unif_db[x].submapper != submapper) { + FCEU_PrintError(" Submapper should be set to %d\n", unif_db[x].submapper); + submapper = unif_db[x].submapper; + } + if (unif_db[x].mirroring >= 0 && unif_db[x].mirroring != mirrortodo) { + static char *stuffo[6] = { "Horizontal", "Vertical", "$2000", "$2400", "\"Four-screen\"", "Controlled by Mapper Hardware" }; + FCEU_PrintError(" Mirroring should be set to %s\n", stuffo[unif_db[x].mirroring]); + mirrortodo = unif_db[x].mirroring; + } + if (unif_db[x].special >= 0 && unif_db[x].special != cspecial) { + if (!(strcmp((char*)sboardname, "CNROM"))) { + FCEU_PrintError(" Special flags applied, No bus conflict.\n"); + cspecial = unif_db[x].special; + } + } + /* todo special case aka, dipswitches, busc-like in fk23c/a, etc */ + FCEU_printf("\n"); + } + x++; + } while (unif_db[x].partialMD5 > 0); + +} + #define BMCFLAG_FORCE4 0x01 #define BMCFLAG_16KCHRR 0x02 #define BMCFLAG_32KCHRR 0x04 @@ -595,6 +656,8 @@ static int InitializeBoard(void) { PRGchip_max = prg_chip_count - 1; if (chr_chip_count) CHRchip_max = chr_chip_count - 1; + UNIFCart.submapper = submapper; + GameInfo->cspecial = cspecial; bmap[x].init(&UNIFCart); return(1); @@ -655,6 +718,8 @@ int UNIFLoad(const char *name, FCEUFILE *fp) { memcpy(GameInfo->MD5, UNIFCart.MD5, sizeof(UNIFCart.MD5)); } + CheckHashInfo(); + if (!InitializeBoard()) goto aborto;