From 634eb688c13d747e9c055fcc8ce530401cf3034e Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Fri, 28 Jun 2019 19:25:35 +0800 Subject: [PATCH] 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); }