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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ static DECLFW(M71Write) {
|
||||
}
|
||||
|
||||
static void M71Power(void) {
|
||||
preg = 0;
|
||||
mirr = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
|
||||
@@ -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" },
|
||||
|
||||
@@ -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++)
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user