Mapper 268, submappers 8,9

This commit is contained in:
Alexey 'Cluster' Avdyukhin 2022-12-06 17:59:26 +04:00
parent a70bc4c72c
commit b6bf83db7f
1 changed files with 91 additions and 48 deletions

View File

@ -55,15 +55,16 @@
* $xxx3 * $xxx3
* 7 bit 0 * 7 bit 0
* ---- ---- * ---- ----
* NPxP QQRx * NPZP QQRx
* || | ||| * |||| |||
* || | +++--- PRG offset for GNROM mode (PRG A16, A15, A14) * |||| +++--- PRG offset for GNROM mode (PRG A16, A15, A14)
* || +------- 1: GNROM mode; 0: MMC3 mode * |||+------- 1: GNROM mode; 0: MMC3 mode
* || | (1: PRG A16...13 from QQ, L, R, CPU A14, A13 + CHR A16...10 from MMMM, PPU A12...10; * |||| (1: PRG A16...13 from QQ, L, R, CPU A14, A13 + CHR A16...10 from MMMM, PPU A12...10;
* || | 0: PRG A16...13 from MMC3 + CHR A16...A10 from MMC3 ) * |||| 0: PRG A16...13 from MMC3 + CHR A16...A10 from MMC3 )
* ||+-------- 1: Also enable PRG RAM in $5000-$5FFF
* |+-+------- Banking mode * |+-+------- Banking mode
* |+--------- "Weird MMC3 mode" * |+--------- "Weird MMC3 mode"
* +---------- Lockout (prevent further writes to these four registers, only works in MMC3 mode) * +---------- Lockout (prevent further writes to all registers but the one at $xxx2, only works in MMC3 mode)
* *
* Also some new cartridges from MINDKIDS have /WE and /OE pins connected to mapper, * Also some new cartridges from MINDKIDS have /WE and /OE pins connected to mapper,
* which allows you to rewrite flash memory without soldering. * which allows you to rewrite flash memory without soldering.
@ -95,6 +96,7 @@ static uint8 cfi_mode = 0;
static uint8 flag23 = 0; static uint8 flag23 = 0;
static uint8 flag45 = 0; static uint8 flag45 = 0;
static uint8 flag89 = 0;
// Macronix 256-mbit memory CFI data // Macronix 256-mbit memory CFI data
const uint8 cfi_data[] = const uint8 cfi_data[] =
@ -118,9 +120,9 @@ const uint8 cfi_data[] =
}; };
static void COOLBOYCW(uint32 A, uint8 V) { static void COOLBOYCW(uint32 A, uint8 V) {
uint32 mask = 0xFF ^ (EXPREGS[0] & 0x80); uint32 mask = 0xFF ^ (EXPREGS[0] & 0b10000000);
if (EXPREGS[3] & 0x10) { if (EXPREGS[3] & 0b00010000) {
if (EXPREGS[3] & 0x40) { // Weird mode if (EXPREGS[3] & 0b01000000) { // Weird mode
int cbase = (MMC3_cmd & 0x80) << 5; int cbase = (MMC3_cmd & 0x80) << 5;
switch (cbase ^ A) { // Don't even try do understand switch (cbase ^ A) { // Don't even try do understand
case 0x0400: case 0x0400:
@ -129,13 +131,13 @@ static void COOLBOYCW(uint32 A, uint8 V) {
} }
// Highest bit goes from MMC3 registers when EXPREGS[0]&0x80==0 or from EXPREGS[0]&0x08 otherwise // Highest bit goes from MMC3 registers when EXPREGS[0]&0x80==0 or from EXPREGS[0]&0x08 otherwise
setchr1(A, setchr1(A,
(V & 0x80 & mask) | ((((EXPREGS[0] & 0x08) << 4) & ~mask)) // 7th bit (V & 0x80 & mask) | ((((EXPREGS[0] & 0b00001000) << 4) & ~mask)) // 7th bit
| ((EXPREGS[2] & 0x0F) << 3) // 6-3 bits | ((EXPREGS[2] & 0x0F) << 3) // 6-3 bits
| ((A >> 10) & 7) // 2-0 bits | ((A >> 10) & 7) // 2-0 bits
); );
} }
else { else {
if (EXPREGS[3] & 0x40) { // Weird mode, again if (EXPREGS[3] & 0b01000000) { // Weird mode, again
int cbase = (MMC3_cmd & 0x80) << 5; int cbase = (MMC3_cmd & 0x80) << 5;
switch (cbase ^ A) { // Don't even try do understand switch (cbase ^ A) { // Don't even try do understand
case 0x0000: V = DRegBuf[0]; break; case 0x0000: V = DRegBuf[0]; break;
@ -152,16 +154,72 @@ static void COOLBOYCW(uint32 A, uint8 V) {
static void COOLBOYPW(uint32 A, uint8 V) { static void COOLBOYPW(uint32 A, uint8 V) {
uint8 CREGS[] = {EXPREGS[0], EXPREGS[1], EXPREGS[2], EXPREGS[3]}; uint8 CREGS[] = {EXPREGS[0], EXPREGS[1], EXPREGS[2], EXPREGS[3]};
// Submappers has scrambled bits
if (flag23) { if (flag23) {
CREGS[1] = (CREGS[1] & 0b11100000) | ((CREGS[1] & 0b11100) >> 1) | (((CREGS[1] & 0b10) ^ 0b10) << 3); /*
$xxx1
7 bit 0
---- ----
GHIL JKKx
|||| |||
|||| +++--- PRG offset (in order: PRG A20, A22, A21)
|||+------- GNROM mode bank PRG size (0: 32 KiB bank, PRG A14=CPU A14; 1: 16 KiB bank, PRG A14=offset A14)
||+-------- PRG mask (PRG A20 from 0: offset; 1: MMC3)
|+--------- PRG mask (PRG A19 from 0: offset; 1: MMC3)
+---------- PRG mask (PRG A18 from 0: MMC3; 1: offset)
*/
CREGS[1] = (CREGS[1] & 0b11100000)
| ((CREGS[1] & 0b00001110) << 1) // PRG A20, A22, A21
| (((CREGS[1] & 0b00010000) ^ 0b00010000) >> 3); // GNROM mode bank PRG size
} }
if (flag45) { if (flag45) {
CREGS[1] = (CREGS[1] & 0b11101011) | ((CREGS[0] & 0b00100000) >> 3) | (CREGS[0] & 0b00010000); /*
CREGS[0] &= 0b11001111; $xxx0
7 bit 0
---- ----
ABCC DEEE
|||| ||||
|||| |+++-- PRG offset (PRG A19, A18, A17)
|||| +----- Alternate CHR A17
||++------- PRG offset (PRG A21, A20)
|+--------- PRG mask (PRG A17 from 0: MMC3; 1: offset)
+---------- CHR mask (CHR A17 from 0: MMC3; 1: alternate)
$xxx1
7 bit 0
---- ----
GHIx xxLx
||| |
||| +--- GNROM mode bank PRG size (1: 32 KiB bank, PRG A14=CPU A14; 0: 16 KiB bank, PRG A14=offset A14)
||+-------- PRG mask (PRG A20 from 0: offset; 1: MMC3)
|+--------- PRG mask (PRG A19 from 0: offset; 1: MMC3)
+---------- PRG mask (PRG A18 from 0: MMC3; 1: offset)
*/
CREGS[1] = (CREGS[1] & 0b11101011)
| ((CREGS[0] & 0b00100000) >> 3) // PRG A21
| (CREGS[0] & 0b00010000); // PRG A20
}
if (flag89) {
/*
$xxx1
7 bit 0
---- ----
GHIL JKKx
|||| |||
|||| +++--- PRG offset (in order: A20, A21, A22)
|||+------- GNROM mode bank PRG size (0: 32 KiB bank, PRG A14=CPU A14; 1: 16 KiB bank, PRG A14=offset A14)
||+-------- PRG mask (PRG A20 from 0: offset; 1: MMC3)
|+--------- PRG mask (PRG A19 from 0: offset; 1: MMC3)
+---------- PRG mask (PRG A18 from 0: MMC3; 1: offset)
*/
CREGS[1] = (CREGS[1] & 0b11100101)
| ((CREGS[1] & 0b00001000) << 1) // PRG A20
| ((CREGS[1] & 0b00000010) << 2) // PRG A22
| ((((CREGS[1] ^ 0b00010000) & 0b00010000) >> 3)); // GNROM mode bank PRG size
} }
uint32 mask = ((0x3F | (CREGS[1] & 0x40) | ((CREGS[1] & 0x20) << 2)) ^ ((CREGS[0] & 0x40) >> 2)) ^ ((CREGS[1] & 0x80) >> 2); uint32 mask = ((0b00111111 | (CREGS[1] & 0b01000000) | ((CREGS[1] & 0b00100000) << 2)) ^ ((CREGS[0] & 0b01000000) >> 2)) ^ ((CREGS[1] & 0b10000000) >> 2);
uint32 base = ((CREGS[0] & 0x07) >> 0) | ((CREGS[1] & 0x10) >> 1) | ((CREGS[1] & 0x0C) << 2) | ((CREGS[0] & 0x30) << 2); uint32 base = ((CREGS[0] & 0b00000111) >> 0) | ((CREGS[1] & 0b00010000) >> 1) | ((CREGS[1] & 0b00001100) << 2) | ((CREGS[0] & 0b00110000) << 2);
FCEU_printf("mask=%04x base=%04x r0=%02x r1=%02x r2=%02x r3=%02x\n", mask, base, CREGS[0], CREGS[1], CREGS[2], CREGS[3]);
if (flash_save && cfi_mode) { if (flash_save && cfi_mode) {
setprg32r(CFI_CHIP, 0x8000, 0); setprg32r(CFI_CHIP, 0x8000, 0);
@ -172,7 +230,7 @@ static void COOLBOYPW(uint32 A, uint8 V) {
// Very weird mode // Very weird mode
// Last banks are first in this mode, ignored when MMC3_cmd&0x40 // Last banks are first in this mode, ignored when MMC3_cmd&0x40
if ((CREGS[3] & 0x40) && (V >= 0xFE) && !((MMC3_cmd & 0x40) != 0)) { if ((CREGS[3] & 0b01000000) && (V >= 0xFE) && !((MMC3_cmd & 0x40) != 0)) {
switch (A & 0xE000) { switch (A & 0xE000) {
case 0xC000: case 0xC000:
case 0xE000: case 0xE000:
@ -189,11 +247,11 @@ static void COOLBOYPW(uint32 A, uint8 V) {
// NROM mode // NROM mode
mask &= 0xF0; mask &= 0xF0;
uint8 emask; uint8 emask;
if ((((CREGS[1] & 2) != 0))) // 32kb mode if (CREGS[1] & 0b00000010) // 32kb mode
emask = (CREGS[3] & 0x0C) | ((A & 0x4000) >> 13); emask = (CREGS[3] & 0b00001100) | ((A & 0x4000) >> 13);
else // 16kb mode else // 16kb mode
emask = CREGS[3] & 0x0E; emask = CREGS[3] & 0b00001110;
setprg8r(chip, A, ((base << 4) & ~mask) // 7-4 bits are from base (see below) setprg8r(chip, A, ((base << 4) & ~mask) // 7-4 bits are from base
| (V & mask) // ... or from MM3 internal regs, depends on mask | (V & mask) // ... or from MM3 internal regs, depends on mask
| emask // 3-1 (or 3-2 when (EXPREGS[3]&0x0C is set) from EXPREGS[3] | emask // 3-1 (or 3-2 when (EXPREGS[3]&0x0C is set) from EXPREGS[3]
| ((A & 0x2000) >> 13)); // 0th just as is | ((A & 0x2000) >> 13)); // 0th just as is
@ -207,10 +265,10 @@ static DECLFW(COOLBOYWrite) {
// Deny any further writes when 7th bit is 1 AND 4th is 0 // Deny any further writes when 7th bit is 1 AND 4th is 0
if ((EXPREGS[3] & 0x90) != 0x80) { if ((EXPREGS[3] & 0x90) != 0x80) {
EXPREGS[A & 3] = V; EXPREGS[A & 3] = V;
}
FixMMC3PRG(MMC3_cmd); FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd); FixMMC3CHR(MMC3_cmd);
} }
}
static DECLFW(MINDKIDSWrite) { static DECLFW(MINDKIDSWrite) {
if (A >= 0x6000) { if (A >= 0x6000) {
@ -222,10 +280,10 @@ static DECLFW(MINDKIDSWrite) {
// Deny any further writes when 7th bit is 1 AND 4th is 0 // Deny any further writes when 7th bit is 1 AND 4th is 0
if ((EXPREGS[3] & 0x90) != 0x80) { if ((EXPREGS[3] & 0x90) != 0x80) {
EXPREGS[A & 3] = V; EXPREGS[A & 3] = V;
}
FixMMC3PRG(MMC3_cmd); FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd); FixMMC3CHR(MMC3_cmd);
} }
}
static DECLFR(COOLBOYFlashRead) { static DECLFR(COOLBOYFlashRead) {
return CartBR(A); return CartBR(A);
@ -359,38 +417,23 @@ void CommonInit(CartInfo* info, int submapper)
switch (submapper) switch (submapper)
{ {
case 0: case 0:
case 2:
case 4:
case 8:
info->Power = COOLBOYPower; info->Power = COOLBOYPower;
flag23 = 0;
flag45 = 0;
break; break;
case 1: case 1:
info->Power = MINDKIDSPower;
flag23 = 0;
flag45 = 0;
break;
case 2:
info->Power = COOLBOYPower;
flag23 = 1;
flag45 = 0;
break;
case 3: case 3:
info->Power = MINDKIDSPower;
flag23 = 1;
flag45 = 0;
break;
case 4:
info->Power = COOLBOYPower;
flag23 = 0;
flag45 = 1;
break;
case 5: case 5:
case 9:
info->Power = MINDKIDSPower; info->Power = MINDKIDSPower;
flag23 = 0;
flag45 = 1;
break; break;
default: default:
FCEU_PrintError("Submapper #%d is not supported", submapper); FCEU_PrintError("Submapper #%d is not supported", submapper);
} }
flag23 = (submapper == 2) || (submapper == 3);
flag45 = (submapper == 4) || (submapper == 5);
flag89 = (submapper == 8) || (submapper == 9);
info->Reset = CommonReset; info->Reset = CommonReset;
info->Close = CommonClose; info->Close = CommonClose;