mapper-related updates and fixes (#491)

* m116: Fix support for Huang-2 chip

* Provide 8K CHR ram if no CHR rom/ram is provided due to bad headers

* m15: Implement CHR write-protect

* Update Namco 106

- Cleanup save state struct
- Implement nametable mirroring
- fix sound issue (fceux)

Co-authored-by: negativeExponent <negativeExponent@users.noreply.github.com>
This commit is contained in:
negativeExponent
2022-02-01 15:14:16 +08:00
committed by GitHub
parent e0200b03c8
commit 85ace685b9
6 changed files with 76 additions and 45 deletions

View File

@@ -35,29 +35,45 @@
#include "mapinc.h"
static uint8 mode;
static uint8 vrc2_chr[8], vrc2_prg[2], vrc2_mirr;
static uint8 mmc3_regs[10], mmc3_ctrl, mmc3_mirr;
static uint8 IRQCount, IRQLatch, IRQa;
static uint8 IRQReload;
static uint8 mmc1_regs[4], mmc1_buffer, mmc1_shift;
static uint8 vrc2_chr[8] = { 0 };
static uint8 vrc2_prg[2] = { 0 };
static uint8 vrc2_mirr = 0;
static uint8 mmc3_regs[10] = { 0 };
static uint8 mmc3_ctrl = 0;
static uint8 mmc3_mirr = 0;
static uint8 mmc1_regs[4] = { 0 };
static uint8 mmc1_buffer = 0;
static uint8 mmc1_shift = 0;
static uint8 IRQCount = 0;
static uint8 IRQLatch = 0;
static uint8 IRQa = 0;
static uint8 IRQReload = 0;
static uint8 mode = 0;
static uint32 isHuang2 = 0;
extern uint32 ROM_size;
extern uint32 VROM_size;
static SFORMAT StateRegs[] =
{
{ &mode, 1, "MODE" },
{ vrc2_chr, 8, "VRCC" },
{ vrc2_prg, 2, "VRCP" },
{ &vrc2_mirr, 1, "VRCM" },
{ mmc3_regs, 10, "M3RG" },
{ &mmc3_ctrl, 1, "M3CT" },
{ &mmc3_mirr, 1, "M3MR" },
{ &IRQReload, 1, "IRQR" },
{ &IRQCount, 1, "IRQC" },
{ &IRQLatch, 1, "IRQL" },
{ &IRQa, 1, "IRQA" },
{ mmc1_regs, 4, "M1RG" },
{ &mode, 1, "MODE" },
{ vrc2_chr, 8, "VRCC" },
{ vrc2_prg, 2, "VRCP" },
{ &vrc2_mirr, 1, "VRCM" },
{ mmc3_regs, 10, "M3RG" },
{ &mmc3_ctrl, 1, "M3CT" },
{ &mmc3_mirr, 1, "M3MR" },
{ &IRQReload, 1, "IRQR" },
{ &IRQCount, 1, "IRQC" },
{ &IRQLatch, 1, "IRQL" },
{ &IRQa, 1, "IRQA" },
{ mmc1_regs, 4, "M1RG" },
{ &mmc1_buffer, 1, "M1BF" },
{ &mmc1_shift, 1, "M1MR" },
{ &mmc1_shift, 1, "M1MR" },
{ 0 }
};
@@ -83,6 +99,8 @@ static void SyncPRG(void) {
{
uint8 bank = mmc1_regs[3] & 0xF;
if (mmc1_regs[0] & 8) {
if (isHuang2)
bank >>= 1;
if (mmc1_regs[0] & 4) {
setprg16(0x8000, bank);
setprg16(0xC000, 0x0F);
@@ -92,9 +110,9 @@ static void SyncPRG(void) {
}
} else
setprg32(0x8000, bank >> 1);
}
break;
}
}
}
static void SyncCHR(void) {
@@ -322,4 +340,7 @@ void UNLSL12_Init(CartInfo *info) {
GameHBIRQHook = UNLSL12HBIRQ;
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
/* PRG 128K and CHR 128K is Huang-2 */
if (ROM_size == 8 && VROM_size == 16)
isHuang2 = 1;
}

View File

@@ -63,11 +63,19 @@ static void Sync(void) {
setprg8(0xC000, preg[2]);
setprg8(0xE000, preg[3]);
setmirror(((latched >> 6) & 1) ^ 1);
setchr8(0);
}
static DECLFW(M15Write) {
latchea = A;
latched = V;
/* cah4e3 02.10.19 once again, there may be either two similar mapper 15 exist. the one for 110in1 or 168in1 carts with complex multi game features.
and another implified version for subor/waixing chinese originals and hacks with no different modes, working only in mode 0 and which does not
expect there is any CHR write protection. protecting CHR writes only for mode 3 fixes the problem, all roms may be run on the same source again. */
if((latchea & 3) == 3)
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0);
else
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1);
Sync();
}

View File

@@ -46,6 +46,7 @@ static DECLFW(M71Write) {
}
static void M71Power(void) {
preg = 0;
mirr = 0;
Sync();
SetReadHandler(0x8000, 0xFFFF, CartBR);

View File

@@ -41,7 +41,6 @@
*/
#include "mapinc.h"
#include "../ines.h"
static uint8 *WRAM = NULL;
static uint8 *CHRRAM = NULL;
@@ -64,6 +63,9 @@ static uint8 jncota523 = 0; /* Jncota board with unusual wiring that turn
static uint8 dipsw_enable = 0; /* Change the address mask on every reset? */
static uint8 after_power = 0; /* Used for detecting whether a DIP switch is used or not (see above) */
extern uint32 ROM_size;
extern uint32 VROM_size;
static SFORMAT StateRegs[] = {
{ fk23_regs, 8, "EXPR" },
{ mmc3_regs, 12, "M3RG" },

View File

@@ -53,34 +53,15 @@ static int is210; /* Lesser mapper. */
static uint8 PRG[3];
static uint8 CHR[8];
/* TODO: Clean this up. State variables are expanded for
* big-endian compatibility when saving and loading states */
static SFORMAT N106_StateRegs[] = {
{ &PRG[0], 1, "PRG1" },
{ &PRG[1], 1, "PRG2" },
{ &PRG[2], 1, "PRG3" },
{ &CHR[0], 1, "CHR1" },
{ &CHR[1], 1, "CHR2" },
{ &CHR[2], 1, "CHR3" },
{ &CHR[3], 1, "CHR4" },
{ &CHR[4], 1, "CHR5" },
{ &CHR[5], 1, "CHR6" },
{ &CHR[6], 1, "CHR7" },
{ &CHR[7], 1, "CHR8" },
{ &NTAPage[0], 1, "NTA1" },
{ &NTAPage[1], 1, "NTA2" },
{ &NTAPage[2], 1, "NTA3" },
{ &NTAPage[3], 1, "NTA4" },
{ PRG, 3, "PRG" },
{ CHR, 8, "CHR" },
{ NTAPage, 4, "NTA" },
{ &IRQCount, 2 | FCEUSTATE_RLSB, "IRQC" },
{ &IRQa, 1, "IRQA" },
{ &dopol, 1, "GORF" },
{ &gorfus, 1, "DOPO" },
{ &gorko, 1, "GORK" },
{ 0 }
};
@@ -91,6 +72,15 @@ static void SyncPRG(void) {
setprg8(0xe000, 0x3F);
}
static void SyncMirror() {
switch(gorko) {
case 0: setmirror(MI_0); break;
case 1: setmirror(MI_V); break;
case 2: setmirror(MI_H); break;
case 3: setmirror(MI_0); break;
}
}
static void FP_FASTAPASS(1) NamcoIRQHook(int a) {
if (IRQa) {
IRQCount += a;
@@ -167,7 +157,10 @@ static void FixCache(int a, int V) {
case 0x02: FreqCache[w] &= ~0x0000FF00; FreqCache[w] |= V << 8; break;
case 0x04:
FreqCache[w] &= ~0x00030000; FreqCache[w] |= (V & 3) << 16;
LengthCache[w] = (8 - ((V >> 2) & 7)) << 2;
/* something wrong here http://www.romhacking.net/forum/index.php?topic=21907.msg306903#msg306903 */
/* LengthCache[w] = (8 - ((V >> 2) & 7)) << 2; */
/* fix be like in https://github.com/SourMesen/Mesen/blob/cda0a0bdcb5525480784f4b8c71de6fc7273b570/Core/Namco163Audio.h#L61 */
LengthCache[w] = 256 - (V & 0xFC);
break;
case 0x07: EnvCache[w] = (double)(V & 0xF) * 576716; break;
}
@@ -206,6 +199,10 @@ static DECLFW(Mapper19_write) {
gorko = V & 0xC0;
PRG[0] = V & 0x3F;
SyncPRG();
if (is210) {
gorko = V >> 6;
SyncMirror();
}
break;
case 0xE800:
gorfus = V & 0xC0;
@@ -378,6 +375,7 @@ static void DoNamcoSound(int32 *Wave, int Count) {
static void Mapper19_StateRestore(int version) {
int x;
SyncPRG();
SyncMirror();
FixNTAR();
FixCRR();
for (x = 0x40; x < 0x80; x++)

View File

@@ -1116,6 +1116,7 @@ static int iNES_Init(int num) {
if (!VROM_size) {
if (iNESCart.iNES2) {
CHRRAMSize = iNESCart.CHRRamSize + iNESCart.CHRRamSaveSize;
if (CHRRAMSize == 0) CHRRAMSize = iNESCart.CHRRamSize = 8 * 8192;
} else {
switch (num) { /* FIXME, mapper or game data base with the board parameters and ROM/RAM sizes */
case 13: CHRRAMSize = 16 * 1024; break;
@@ -1132,7 +1133,7 @@ static int iNES_Init(int num) {
}
iNESCart.CHRRamSize = CHRRAMSize;
}
if (CHRRAMSize) { /* TODO: CHR-RAM are sometimes handled in mappers e.g. MMC1 using submapper 1/2/4 and CHR-RAM can be zero here */
if (CHRRAMSize > 0) { /* TODO: CHR-RAM are sometimes handled in mappers e.g. MMC1 using submapper 1/2/4 and CHR-RAM can be zero here */
if ((VROM = (uint8*)malloc(CHRRAMSize)) == NULL) return 0;
FCEU_MemoryRand(VROM, CHRRAMSize);
UNIFchrrama = VROM;