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.
This commit is contained in:
retro-wertz
2019-06-28 19:25:35 +08:00
parent 83b2f99527
commit 634eb688c1
11 changed files with 91 additions and 38 deletions

View File

@@ -23,6 +23,7 @@
#include "mapinc.h" #include "mapinc.h"
static uint8 chip;
static uint16 cmdreg; static uint16 cmdreg;
static uint8 reset; static uint8 reset;
static SFORMAT StateRegs[] = static SFORMAT StateRegs[] =
@@ -36,13 +37,12 @@ static void Sync(void) {
uint32 base = ((cmdreg & 0x060) | ((cmdreg & 0x100) >> 1)) >> 2; uint32 base = ((cmdreg & 0x060) | ((cmdreg & 0x100) >> 1)) >> 2;
uint32 bank = (cmdreg & 0x01C) >> 2; uint32 bank = (cmdreg & 0x01C) >> 2;
uint32 lbank = (cmdreg & 0x200) ? 7 : ((cmdreg & 0x80) ? bank : 0); 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 if (PRGptr[1]) {
* (rom is only 512KB but reported as having 3 prg banks with 128k each) */ chip = base >> 3;
/*if (PRGptr[1]) { if (chip > PRGchip_max) chip &= PRGchip_max;
setprg16r(base >> 3, 0x8000, bank); // for versions with split ROMs setprg16r(chip, 0x8000, bank); /* for versions with split ROMs */
setprg16r(base >> 3, 0xC000, lbank); setprg16r(chip, 0xC000, lbank);
} else*/ } else {
{
setprg16(0x8000, base | bank); setprg16(0x8000, base | bank);
setprg16(0xC000, base | lbank); setprg16(0xC000, base | lbank);
} }

View File

@@ -88,8 +88,3 @@ void UNLAX40G_Init(CartInfo *info) {
GameStateRestore = StateRestore; GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0); AddExState(&StateRegs, ~0, 0, 0);
} }
/*void UNLAX40G_Init(CartInfo *info); // m527
{ "AX-40G", UNLAX40G_Init, 0 },
{ "JC-016-2", Mapper205_Init, 0 },
*/

View File

@@ -41,7 +41,7 @@ static SFORMAT StateRegs[] =
static void Sync(void) { static void Sync(void) {
uint8 mirroring = m350 ? ((latche >> 7) & 1) : ((latche >> 5) & 1); uint8 mirroring = m350 ? ((latche >> 7) & 1) : ((latche >> 5) & 1);
uint8 mode = m350 ? ((latche >> 5) & 0x03) : ((latche >> 6) & 0x03); 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); setchr8(0);
setprg8(0x6000, 1); setprg8(0x6000, 1);

View File

@@ -24,24 +24,31 @@
#include "mapinc.h" #include "mapinc.h"
#include "mmc3.h" #include "mmc3.h"
static uint8 chip;
static void BMCK3088CW(uint32 A, uint8 V) { static void BMCK3088CW(uint32 A, uint8 V) {
if (CHRptr[EXPREGS[0] & 7]) if (CHRptr[1]) {
setchr1r(EXPREGS[0] & 7, A, V); chip = EXPREGS[0] & 7;
else if (chip > CHRchip_max) chip &= CHRchip_max;
setchr1r(chip, A, V);
} else
setchr1(A, V | ((EXPREGS[0] & 3) << 7)); setchr1(A, V | ((EXPREGS[0] & 3) << 7));
} }
static void BMCK3088PW(uint32 A, uint8 V) { static void BMCK3088PW(uint32 A, uint8 V) {
if (PRGptr[EXPREGS[0] & 7]) { if (PRGptr[1]) {
uint8 chip = EXPREGS[0] & 7; chip = EXPREGS[0] & 7;
if (EXPREGS[0] & 8) if (chip > PRGchip_max) chip &= PRGchip_max;
setprg32r(chip, 0x8000, ((EXPREGS[0] >> 4) & 3)); if (EXPREGS[0] & 8) {
else if (A == 0x8000)
setprg32r(chip, A, ((EXPREGS[0] >> 4) & 3));
} else
setprg8r(chip, A, (V & 0x0F)); setprg8r(chip, A, (V & 0x0F));
} else { } else {
if (EXPREGS[0] & 8) if (EXPREGS[0] & 8) {
setprg32(0x8000, ((EXPREGS[0] >> 4) & 3) | (0x0C)); if (A == 0x8000)
else setprg32(A, ((EXPREGS[0] >> 4) & 3) | (0x0C));
} else
setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 3) << 4)); setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 3) << 4));
} }
} }

View File

@@ -1,7 +1,7 @@
/* FCEUmm - NES/Famicom Emulator /* FCEUmm - NES/Famicom Emulator
* *
* Copyright notice for this file: * Copyright notice for this file:
* * Copyright (C) 2019 Libretro Team
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@@ -44,6 +44,8 @@ uint8 mmc3opts = 0;
uint8 IRQCount, IRQLatch, IRQa; uint8 IRQCount, IRQLatch, IRQa;
uint8 IRQReload; uint8 IRQReload;
static uint8 chip;
static SFORMAT MMC3_StateRegs[] = static SFORMAT MMC3_StateRegs[] =
{ {
{ DRegBuf, 8, "REGS" }, { DRegBuf, 8, "REGS" },
@@ -912,12 +914,22 @@ void Mapper119_Init(CartInfo *info) {
static void M134PW(uint32 A, uint8 V) { static void M134PW(uint32 A, uint8 V) {
uint8 mask = (EXPREGS[0] & 0x04) ? 0x0F : 0x1F; 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) { static void M134CW(uint32 A, uint8 V) {
uint8 mask = (EXPREGS[0] & 0x04) ? 0x7F : 0xFF; 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) { static DECLFW(M134Write) {
@@ -1200,17 +1212,21 @@ static uint8 block[] = {0, 0, 1, 2};
static void M205PW(uint32 A, uint8 V) { static void M205PW(uint32 A, uint8 V) {
uint8 bank = V & ((EXPREGS[0] & 0x02) ? 0x0F : 0x1F); uint8 bank = V & ((EXPREGS[0] & 0x02) ? 0x0F : 0x1F);
if (PRGptr[1]) if (PRGptr[1]) {
setprg8r(block[EXPREGS[0]], A, bank); chip = block[EXPREGS[0]];
else if (chip > PRGchip_max) chip &= PRGchip_max;
setprg8r(chip, A, bank);
} else
setprg8(A, EXPREGS[0] << 4 | bank); setprg8(A, EXPREGS[0] << 4 | bank);
} }
static void M205CW(uint32 A, uint8 V) { static void M205CW(uint32 A, uint8 V) {
uint8 bank = V & ((EXPREGS[0] & 0x02) ? 0x7F : 0xFF); uint8 bank = V & ((EXPREGS[0] & 0x02) ? 0x7F : 0xFF);
if (PRGptr[1]) if (CHRptr[1]) {
setchr1r(block[EXPREGS[0]], A, bank); chip = block[EXPREGS[0]];
else if (chip > CHRchip_max) chip &= CHRchip_max;
setchr1r(chip, A, bank);
} else
setchr1(A, (EXPREGS[0] << 7) | bank); setchr1(A, (EXPREGS[0] << 7) | bank);
} }

View File

@@ -27,12 +27,24 @@
#include "mapinc.h" #include "mapinc.h"
#include "mmc3.h" #include "mmc3.h"
static uint8 chip;
static void M313CW(uint32 A, uint8 V) { 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) { 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) { static void M313Reset(void) {

View File

@@ -20,6 +20,7 @@
#include "mapinc.h" #include "mapinc.h"
static uint8 chip;
static uint8 bank, base, lock, mirr, mode; static uint8 bank, base, lock, mirr, mode;
static SFORMAT StateRegs[] = static SFORMAT StateRegs[] =
{ {
@@ -34,8 +35,10 @@ static SFORMAT StateRegs[] =
static void Sync(void) { static void Sync(void) {
setchr8(0); setchr8(0);
if (PRGptr[1]) { if (PRGptr[1]) {
setprg16r(base >> 3, 0x8000, bank); chip = base >> 3;
setprg16r(base >> 3, 0xC000, (mode ? bank : 7)); if (chip > PRGchip_max) chip &= PRGchip_max;
setprg16r(chip, 0x8000, bank);
setprg16r(chip, 0xC000, (mode ? bank : 7));
} else { } else {
setprg16(0x8000, base | bank); setprg16(0x8000, base | bank);
setprg16(0xC000, base | (mode ? bank : 7)); setprg16(0xC000, base | (mode ? bank : 7));

View File

@@ -53,6 +53,9 @@ static int PRGram[32];
uint8 *PRGptr[32]; uint8 *PRGptr[32];
uint8 *CHRptr[32]; uint8 *CHRptr[32];
uint32 PRGchip_max;
uint32 CHRchip_max;
uint32 PRGsize[32]; uint32 PRGsize[32];
uint32 CHRsize[32]; uint32 CHRsize[32];
@@ -104,6 +107,8 @@ void ResetCartMapping(void) {
for (x = 0; x < 8; x++) { for (x = 0; x < 8; x++) {
MMC5SPRVPage[x] = MMC5BGVPage[x] = VPageR[x] = nothing - 0x400 * 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) { void SetupCartPRGMapping(int chip, uint8 *p, uint32 size, int ram) {

View File

@@ -40,6 +40,9 @@ DECLFW(CartBW);
extern uint8 *PRGptr[32]; extern uint8 *PRGptr[32];
extern uint8 *CHRptr[32]; extern uint8 *CHRptr[32];
extern uint32 PRGchip_max;
extern uint32 CHRchip_max;
extern uint32 PRGsize[32]; extern uint32 PRGsize[32];
extern uint32 CHRsize[32]; extern uint32 CHRsize[32];

View File

@@ -73,6 +73,9 @@ static UNIF_HEADER uchead;
static uint8 *malloced[32]; static uint8 *malloced[32];
static uint32 mallocedsizes[32]; static uint32 mallocedsizes[32];
static uint32 prg_chip_count;
static uint32 chr_chip_count;
static int FixRomSize(uint32 size, uint32 minimum) { static int FixRomSize(uint32 size, uint32 minimum) {
uint32 x = 1; uint32 x = 1;
@@ -107,6 +110,8 @@ static void ResetUNIF(void) {
mirrortodo = 0; mirrortodo = 0;
memset(&UNIFCart, 0, sizeof(UNIFCart)); memset(&UNIFCart, 0, sizeof(UNIFCart));
UNIFchrrama = 0; UNIFchrrama = 0;
prg_chip_count = 0;
chr_chip_count = 0;
} }
static uint8 exntar[2048]; static uint8 exntar[2048];
@@ -272,6 +277,7 @@ static int LoadPRG(FCEUFILE *fp) {
FCEU_printf("\n"); */ FCEU_printf("\n"); */
SetupCartPRGMapping(z, malloced[z], t, 0); SetupCartPRGMapping(z, malloced[z], t, 0);
prg_chip_count++;
return(1); return(1);
} }
@@ -307,6 +313,7 @@ static int LoadCHR(FCEUFILE *fp) {
FCEU_printf("\n"); */ FCEU_printf("\n"); */
SetupCartCHRMapping(z, malloced[16 + z], t, 0); SetupCartCHRMapping(z, malloced[16 + z], t, 0);
chr_chip_count++;
return(1); return(1);
} }
@@ -584,12 +591,17 @@ static int InitializeBoard(void) {
if (bmap[x].flags & BMCFLAG_FORCE4) if (bmap[x].flags & BMCFLAG_FORCE4)
mirrortodo = 4; mirrortodo = 4;
MooMirroring(); MooMirroring();
PRGchip_max = prg_chip_count - 1;
if (chr_chip_count)
CHRchip_max = chr_chip_count - 1;
bmap[x].init(&UNIFCart); bmap[x].init(&UNIFCart);
return(1); return(1);
} }
x++; x++;
} }
FCEU_PrintError("Board type not supported.", boardname); FCEU_PrintError("Board type not supported, '%s'.", boardname);
return(0); return(0);
} }