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"
|
#include "mapinc.h"
|
||||||
|
|
||||||
static uint8 mode;
|
static uint8 vrc2_chr[8] = { 0 };
|
||||||
static uint8 vrc2_chr[8], vrc2_prg[2], vrc2_mirr;
|
static uint8 vrc2_prg[2] = { 0 };
|
||||||
static uint8 mmc3_regs[10], mmc3_ctrl, mmc3_mirr;
|
static uint8 vrc2_mirr = 0;
|
||||||
static uint8 IRQCount, IRQLatch, IRQa;
|
|
||||||
static uint8 IRQReload;
|
static uint8 mmc3_regs[10] = { 0 };
|
||||||
static uint8 mmc1_regs[4], mmc1_buffer, mmc1_shift;
|
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[] =
|
static SFORMAT StateRegs[] =
|
||||||
{
|
{
|
||||||
{ &mode, 1, "MODE" },
|
{ &mode, 1, "MODE" },
|
||||||
{ vrc2_chr, 8, "VRCC" },
|
{ vrc2_chr, 8, "VRCC" },
|
||||||
{ vrc2_prg, 2, "VRCP" },
|
{ vrc2_prg, 2, "VRCP" },
|
||||||
{ &vrc2_mirr, 1, "VRCM" },
|
{ &vrc2_mirr, 1, "VRCM" },
|
||||||
{ mmc3_regs, 10, "M3RG" },
|
{ mmc3_regs, 10, "M3RG" },
|
||||||
{ &mmc3_ctrl, 1, "M3CT" },
|
{ &mmc3_ctrl, 1, "M3CT" },
|
||||||
{ &mmc3_mirr, 1, "M3MR" },
|
{ &mmc3_mirr, 1, "M3MR" },
|
||||||
{ &IRQReload, 1, "IRQR" },
|
{ &IRQReload, 1, "IRQR" },
|
||||||
{ &IRQCount, 1, "IRQC" },
|
{ &IRQCount, 1, "IRQC" },
|
||||||
{ &IRQLatch, 1, "IRQL" },
|
{ &IRQLatch, 1, "IRQL" },
|
||||||
{ &IRQa, 1, "IRQA" },
|
{ &IRQa, 1, "IRQA" },
|
||||||
{ mmc1_regs, 4, "M1RG" },
|
{ mmc1_regs, 4, "M1RG" },
|
||||||
{ &mmc1_buffer, 1, "M1BF" },
|
{ &mmc1_buffer, 1, "M1BF" },
|
||||||
{ &mmc1_shift, 1, "M1MR" },
|
{ &mmc1_shift, 1, "M1MR" },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -83,6 +99,8 @@ static void SyncPRG(void) {
|
|||||||
{
|
{
|
||||||
uint8 bank = mmc1_regs[3] & 0xF;
|
uint8 bank = mmc1_regs[3] & 0xF;
|
||||||
if (mmc1_regs[0] & 8) {
|
if (mmc1_regs[0] & 8) {
|
||||||
|
if (isHuang2)
|
||||||
|
bank >>= 1;
|
||||||
if (mmc1_regs[0] & 4) {
|
if (mmc1_regs[0] & 4) {
|
||||||
setprg16(0x8000, bank);
|
setprg16(0x8000, bank);
|
||||||
setprg16(0xC000, 0x0F);
|
setprg16(0xC000, 0x0F);
|
||||||
@@ -92,9 +110,9 @@ static void SyncPRG(void) {
|
|||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
setprg32(0x8000, bank >> 1);
|
setprg32(0x8000, bank >> 1);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SyncCHR(void) {
|
static void SyncCHR(void) {
|
||||||
@@ -322,4 +340,7 @@ void UNLSL12_Init(CartInfo *info) {
|
|||||||
GameHBIRQHook = UNLSL12HBIRQ;
|
GameHBIRQHook = UNLSL12HBIRQ;
|
||||||
GameStateRestore = StateRestore;
|
GameStateRestore = StateRestore;
|
||||||
AddExState(&StateRegs, ~0, 0, 0);
|
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(0xC000, preg[2]);
|
||||||
setprg8(0xE000, preg[3]);
|
setprg8(0xE000, preg[3]);
|
||||||
setmirror(((latched >> 6) & 1) ^ 1);
|
setmirror(((latched >> 6) & 1) ^ 1);
|
||||||
|
setchr8(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DECLFW(M15Write) {
|
static DECLFW(M15Write) {
|
||||||
latchea = A;
|
latchea = A;
|
||||||
latched = V;
|
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();
|
Sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ static DECLFW(M71Write) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void M71Power(void) {
|
static void M71Power(void) {
|
||||||
|
preg = 0;
|
||||||
mirr = 0;
|
mirr = 0;
|
||||||
Sync();
|
Sync();
|
||||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||||
|
|||||||
@@ -41,7 +41,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mapinc.h"
|
#include "mapinc.h"
|
||||||
#include "../ines.h"
|
|
||||||
|
|
||||||
static uint8 *WRAM = NULL;
|
static uint8 *WRAM = NULL;
|
||||||
static uint8 *CHRRAM = 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 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) */
|
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[] = {
|
static SFORMAT StateRegs[] = {
|
||||||
{ fk23_regs, 8, "EXPR" },
|
{ fk23_regs, 8, "EXPR" },
|
||||||
{ mmc3_regs, 12, "M3RG" },
|
{ mmc3_regs, 12, "M3RG" },
|
||||||
|
|||||||
@@ -53,34 +53,15 @@ static int is210; /* Lesser mapper. */
|
|||||||
static uint8 PRG[3];
|
static uint8 PRG[3];
|
||||||
static uint8 CHR[8];
|
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[] = {
|
static SFORMAT N106_StateRegs[] = {
|
||||||
{ &PRG[0], 1, "PRG1" },
|
{ PRG, 3, "PRG" },
|
||||||
{ &PRG[1], 1, "PRG2" },
|
{ CHR, 8, "CHR" },
|
||||||
{ &PRG[2], 1, "PRG3" },
|
{ NTAPage, 4, "NTA" },
|
||||||
|
|
||||||
{ &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" },
|
|
||||||
|
|
||||||
{ &IRQCount, 2 | FCEUSTATE_RLSB, "IRQC" },
|
{ &IRQCount, 2 | FCEUSTATE_RLSB, "IRQC" },
|
||||||
{ &IRQa, 1, "IRQA" },
|
{ &IRQa, 1, "IRQA" },
|
||||||
|
|
||||||
{ &dopol, 1, "GORF" },
|
{ &dopol, 1, "GORF" },
|
||||||
{ &gorfus, 1, "DOPO" },
|
{ &gorfus, 1, "DOPO" },
|
||||||
{ &gorko, 1, "GORK" },
|
{ &gorko, 1, "GORK" },
|
||||||
|
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -91,6 +72,15 @@ static void SyncPRG(void) {
|
|||||||
setprg8(0xe000, 0x3F);
|
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) {
|
static void FP_FASTAPASS(1) NamcoIRQHook(int a) {
|
||||||
if (IRQa) {
|
if (IRQa) {
|
||||||
IRQCount += a;
|
IRQCount += a;
|
||||||
@@ -167,7 +157,10 @@ static void FixCache(int a, int V) {
|
|||||||
case 0x02: FreqCache[w] &= ~0x0000FF00; FreqCache[w] |= V << 8; break;
|
case 0x02: FreqCache[w] &= ~0x0000FF00; FreqCache[w] |= V << 8; break;
|
||||||
case 0x04:
|
case 0x04:
|
||||||
FreqCache[w] &= ~0x00030000; FreqCache[w] |= (V & 3) << 16;
|
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;
|
break;
|
||||||
case 0x07: EnvCache[w] = (double)(V & 0xF) * 576716; break;
|
case 0x07: EnvCache[w] = (double)(V & 0xF) * 576716; break;
|
||||||
}
|
}
|
||||||
@@ -206,6 +199,10 @@ static DECLFW(Mapper19_write) {
|
|||||||
gorko = V & 0xC0;
|
gorko = V & 0xC0;
|
||||||
PRG[0] = V & 0x3F;
|
PRG[0] = V & 0x3F;
|
||||||
SyncPRG();
|
SyncPRG();
|
||||||
|
if (is210) {
|
||||||
|
gorko = V >> 6;
|
||||||
|
SyncMirror();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0xE800:
|
case 0xE800:
|
||||||
gorfus = V & 0xC0;
|
gorfus = V & 0xC0;
|
||||||
@@ -378,6 +375,7 @@ static void DoNamcoSound(int32 *Wave, int Count) {
|
|||||||
static void Mapper19_StateRestore(int version) {
|
static void Mapper19_StateRestore(int version) {
|
||||||
int x;
|
int x;
|
||||||
SyncPRG();
|
SyncPRG();
|
||||||
|
SyncMirror();
|
||||||
FixNTAR();
|
FixNTAR();
|
||||||
FixCRR();
|
FixCRR();
|
||||||
for (x = 0x40; x < 0x80; x++)
|
for (x = 0x40; x < 0x80; x++)
|
||||||
|
|||||||
@@ -1116,6 +1116,7 @@ static int iNES_Init(int num) {
|
|||||||
if (!VROM_size) {
|
if (!VROM_size) {
|
||||||
if (iNESCart.iNES2) {
|
if (iNESCart.iNES2) {
|
||||||
CHRRAMSize = iNESCart.CHRRamSize + iNESCart.CHRRamSaveSize;
|
CHRRAMSize = iNESCart.CHRRamSize + iNESCart.CHRRamSaveSize;
|
||||||
|
if (CHRRAMSize == 0) CHRRAMSize = iNESCart.CHRRamSize = 8 * 8192;
|
||||||
} else {
|
} else {
|
||||||
switch (num) { /* FIXME, mapper or game data base with the board parameters and ROM/RAM sizes */
|
switch (num) { /* FIXME, mapper or game data base with the board parameters and ROM/RAM sizes */
|
||||||
case 13: CHRRAMSize = 16 * 1024; break;
|
case 13: CHRRAMSize = 16 * 1024; break;
|
||||||
@@ -1132,7 +1133,7 @@ static int iNES_Init(int num) {
|
|||||||
}
|
}
|
||||||
iNESCart.CHRRamSize = CHRRAMSize;
|
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;
|
if ((VROM = (uint8*)malloc(CHRRAMSize)) == NULL) return 0;
|
||||||
FCEU_MemoryRand(VROM, CHRRAMSize);
|
FCEU_MemoryRand(VROM, CHRRAMSize);
|
||||||
UNIFchrrama = VROM;
|
UNIFchrrama = VROM;
|
||||||
|
|||||||
Reference in New Issue
Block a user