Merge pull request #266 from retro-wertz/mappers

Mappers
This commit is contained in:
Twinaphex
2019-05-27 17:12:35 +02:00
committed by GitHub
16 changed files with 879 additions and 42 deletions

79
src/boards/255.c Normal file
View File

@@ -0,0 +1,79 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright (C) 2019 Libretro Team
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* added 2019-5-23
* Mapper 255
* https://wiki.nesdev.com/w/index.php/INES_Mapper_225
* 115-in-1 [p1][!] CRC32 0xb39d30b4
* Seems to handle up to last game in the multicarts than m225 but causes
* graphics garbage past it, else games works fine */
#include "mapinc.h"
static uint8 preg, creg, mode, mirr;
static SFORMAT StateRegs[] =
{
{ &preg, 1, "PRG0" },
{ &creg, 1, "CHR0" },
{ &mode, 1, "MODE" },
{ &mirr, 1, "MIRR" },
{ 0 }
};
static void Sync(void) {
setprg16(0x8000, preg & ~mode);
setprg16(0xC000, preg | mode);
setchr8(creg);
setmirror(mirr ^ 1);
}
static DECLFW(M255Write) {
uint32 bank = (A >> 8 & 0x40);
preg = bank | ((A >> 6) & 0x3F);
creg = bank | (A & 0x3F);
mirr = (A >> 13) & 1;
mode = ((~A) >> 12 & 1);
Sync();
}
static void M255Power(void) {
preg = 0;
mode = 1;
Sync();
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x8000, 0xFFFF, M255Write);
}
static void M255Reset(void) {
preg = 0;
mode = 1;
Sync();
}
static void StateRestore(int version) {
Sync();
}
void Mapper255_Init(CartInfo *info) {
info->Reset = M255Reset;
info->Power = M255Power;
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
}

187
src/boards/28.c Normal file
View File

@@ -0,0 +1,187 @@
/*
* Copyright (C) 2012-2017 FCEUX team
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
/* added 2019-5-23
* Mapper 28 - Action 53
* http://wiki.nesdev.com/w/index.php/INES_Mapper_028 */
#include "mapinc.h"
static uint8 prg_mask_16k;
static uint8 reg, chr, prg, mode, outer;
static SFORMAT StateRegs[] = {
{&reg, 1, "REG"},
{&chr, 1, "CHR"},
{&prg, 1, "PRG"},
{&mode, 1, "MODE"},
{&outer, 1, "OUTR"},
{0}
};
void SyncMirror() {
switch (mode & 3) {
case 0: setmirror(MI_0); break;
case 1: setmirror(MI_1); break;
case 2: setmirror(MI_V); break;
case 3: setmirror(MI_H); break;
}
}
void Mirror(uint8 value)
{
if ((mode & 2) == 0) {
mode &= 0xfe;
mode |= value >> 4 & 1;
}
SyncMirror();
}
static void Sync() {
uint8 prglo;
uint8 prghi;
uint8 outb = outer << 1;
/* this can probably be rolled up, but i have no motivation to do so
* until it's been tested */
switch (mode & 0x3c) {
/* 32K modes */
case 0x00:
case 0x04:
prglo = outb;
prghi = outb | 1;
break;
case 0x10:
case 0x14:
prglo = outb & ~2 | prg << 1 & 2;
prghi = outb & ~2 | prg << 1 & 2 | 1;
break;
case 0x20:
case 0x24:
prglo = outb & ~6 | prg << 1 & 6;
prghi = outb & ~6 | prg << 1 & 6 | 1;
break;
case 0x30:
case 0x34:
prglo = outb & ~14 | prg << 1 & 14;
prghi = outb & ~14 | prg << 1 & 14 | 1;
break;
/* bottom fixed modes */
case 0x08:
prglo = outb;
prghi = outb | prg & 1;
break;
case 0x18:
prglo = outb;
prghi = outb & ~2 | prg & 3;
break;
case 0x28:
prglo = outb;
prghi = outb & ~6 | prg & 7;
break;
case 0x38:
prglo = outb;
prghi = outb & ~14 | prg & 15;
break;
/* top fixed modes */
case 0x0c:
prglo = outb | prg & 1;
prghi = outb | 1;
break;
case 0x1c:
prglo = outb & ~2 | prg & 3;
prghi = outb | 1;
break;
case 0x2c:
prglo = outb & ~6 | prg & 7;
prghi = outb | 1;
break;
case 0x3c:
prglo = outb & ~14 | prg & 15;
prghi = outb | 1;
break;
}
prglo &= prg_mask_16k;
prghi &= prg_mask_16k;
setprg16(0x8000, prglo);
setprg16(0xC000, prghi);
setchr8(chr);
}
static DECLFW(WriteEXP) {
reg = V & 0x81;
}
static DECLFW(WritePRG) {
switch (reg) {
case 0x00:
chr = V & 3;
Mirror(V);
Sync();
break;
case 0x01:
prg = V & 15;
Mirror(V);
Sync();
break;
case 0x80:
mode = V & 63;
SyncMirror();
Sync();
break;
case 0x81:
outer = V & 63;
Sync();
break;
}
}
static void M28Power(void) {
outer = 63;
prg = 15;
Sync();
prg_mask_16k = PRGsize[0] - 1;
SetWriteHandler(0x5000,0x5FFF,WriteEXP);
SetWriteHandler(0x8000,0xFFFF,WritePRG);
SetReadHandler(0x8000,0xFFFF,CartBR);
SetReadHandler(0x6000,0x7FFF,CartBR);
SetWriteHandler(0x6000,0x7FFF,CartBW);
}
static void M28Reset(void) {
outer = 63;
prg = 15;
Sync();
}
static void StateRestore(int version) {
Sync();
}
void Mapper28_Init(CartInfo* info) {
info->Power=M28Power;
info->Reset=M28Reset;
GameStateRestore=StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
}

66
src/boards/31.c Normal file
View File

@@ -0,0 +1,66 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright (C) 2019 Libretro Team
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* added 2019-5-23
* Mapper 31 - custom mapper by infiniteneslives
* https://wiki.nesdev.com/w/index.php/INES_Mapper_031 */
#include "mapinc.h"
static uint8 preg[8];
static SFORMAT StateRegs[] =
{
{ preg, 8, "PREG" },
{ 0 }
};
static void Sync(void) {
setprg4(0x8000, preg[0]);
setprg4(0x9000, preg[1]);
setprg4(0xA000, preg[2]);
setprg4(0xB000, preg[3]);
setprg4(0xC000, preg[4]);
setprg4(0xD000, preg[5]);
setprg4(0xE000, preg[6]);
setprg4(0xF000, preg[7]);
setchr8(0);
}
static DECLFW(M31Write) {
preg[A & 7] = V;
Sync();
}
static void M31Power(void) {
preg[7] = ~0;
Sync();
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x5000, 0x5FFF, M31Write);
}
static void StateRestore(int version) {
Sync();
}
void Mapper31_Init(CartInfo *info) {
info->Power = M31Power;
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
}

View File

@@ -36,10 +36,13 @@ static void Sync(void) {
uint32 base = ((cmdreg & 0x060) | ((cmdreg & 0x100) >> 1)) >> 2;
uint32 bank = (cmdreg & 0x01C) >> 2;
uint32 lbank = (cmdreg & 0x200) ? 7 : ((cmdreg & 0x80) ? bank : 0);
if (PRGptr[1]) {
setprg16r(base >> 3, 0x8000, bank); /* for versions with split ROMs */
/* this fails to load at least one game, which probably has invalid PRG size in header
* (rom is only 512KB but reported as having 3 prg banks with 128k each) */
/*if (PRGptr[1]) {
setprg16r(base >> 3, 0x8000, bank); // for versions with split ROMs
setprg16r(base >> 3, 0xC000, lbank);
} else {
} else*/
{
setprg16(0x8000, base | bank);
setprg16(0xC000, base | lbank);
}

View File

@@ -2,6 +2,7 @@
*
* Copyright notice for this file:
* Copyright (C) 2007 CaH4e3
* Copyright (C) 2019 Libretro Team
*
* 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
@@ -21,43 +22,99 @@
*
*/
/* added 2019-5-23
* - Mapper 56 - UNL KS202
* FDS Conversion: Super Mario Bros. 3 (Pirate, Alt)
* similar to M142 but use WRAM instead? $D000 additional IRQ trigger
* - fix IRQ counter, noticeable in status bars of both SMB2J(KS7032) and SMB3J(KS202)
*/
#include "mapinc.h"
static uint8 reg[8], cmd, IRQa = 0, isirqused = 0;
static int32 IRQCount;
static uint8 reg[8], creg[8], mirr, cmd, IRQa = 0, isirqused = 0;
static int32 IRQCount, IRQLatch;
static uint8 KS7032;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static SFORMAT StateRegs[] =
static SFORMAT StateRegsKS7032[] =
{
{ &cmd, 1, "CMD" },
{ reg, 8, "REGS" },
{ &IRQa, 1, "IRQA" },
{ &IRQCount, 4, "IRQC" },
{ &IRQCount, 4 | FCEUSTATE_RLSB, "IRQC" },
{ 0 }
};
static SFORMAT StateRegsKS202[] =
{
{ creg, 8, "CREG" },
{ &mirr, 1, "MIRR" },
{ 0 }
};
static void Sync(void) {
setprg8(0x6000, reg[4]);
setprg8(0x8000, reg[1]);
setprg8(0xA000, reg[2]);
setprg8(0xC000, reg[3]);
setprg8(0x8000, reg[0]);
setprg8(0xA000, reg[1]);
setprg8(0xC000, reg[2]);
setprg8(0xE000, ~0);
setchr8(0);
if (KS7032)
setprg8(0x6000, reg[3]);
else {
setprg8r(0x10, 0x6000, 0);
setchr1(0x0000, creg[0]);
setchr1(0x0400, creg[1]);
setchr1(0x0800, creg[2]);
setchr1(0x0C00, creg[3]);
setchr1(0x1000, creg[4]);
setchr1(0x1400, creg[5]);
setchr1(0x1800, creg[6]);
setchr1(0x1C00, creg[7]);
setmirror(mirr);
}
}
static DECLFW(UNLKS7032Write) {
/* FCEU_printf("bs %04x %02x\n",A,V); */
switch (A & 0xF000) {
/* case 0x8FFF: reg[4]=V; Sync(); break; */
case 0x8000: X6502_IRQEnd(FCEU_IQEXT); IRQCount = (IRQCount & 0x000F) | (V & 0x0F); isirqused = 1; break;
case 0x9000: X6502_IRQEnd(FCEU_IQEXT); IRQCount = (IRQCount & 0x00F0) | ((V & 0x0F) << 4); isirqused = 1; break;
case 0xA000: X6502_IRQEnd(FCEU_IQEXT); IRQCount = (IRQCount & 0x0F00) | ((V & 0x0F) << 8); isirqused = 1; break;
case 0xB000: X6502_IRQEnd(FCEU_IQEXT); IRQCount = (IRQCount & 0xF000) | (V << 12); isirqused = 1; break;
case 0xC000: if (isirqused) {
X6502_IRQEnd(FCEU_IQEXT); IRQa = 1;
}
break;
case 0x8000: IRQLatch = (IRQLatch & 0xFFF0) | (V & 0x0F); break;
case 0x9000: IRQLatch = (IRQLatch & 0xFF0F) | ((V & 0x0F) << 4); break;
case 0xA000: IRQLatch = (IRQLatch & 0xF0FF) | ((V & 0x0F) << 8); break;
case 0xB000: IRQLatch = (IRQLatch & 0x0FFF) | (V << 12); break;
case 0xC000:
IRQa = (V & 0xF);
if (IRQa)
IRQCount = IRQLatch;
X6502_IRQEnd(FCEU_IQEXT); break;
case 0xD000: X6502_IRQEnd(FCEU_IQEXT); break;
case 0xE000: cmd = V & 7; break;
case 0xF000: reg[cmd] = V; Sync(); break;
case 0xF000: {
uint8 bank = (cmd - 1);
if (bank < 3)
reg[bank] = reg[bank] & 0x10 | V & 0x0F;
else if (bank < 4)
reg[bank] = V;
Sync();
switch (A & 0xFC00) {
case 0xF000:
A &= 3;
if (A < 3)
reg[bank] = reg[bank] & 0x0F | V & 0x10;
Sync();
break;
case 0xF800:
mirr = (V & 1);
Sync();
break;
case 0xFC00:
creg[A & 7] = V;
Sync();
break;
}
}
break;
}
}
@@ -65,8 +122,7 @@ static void FP_FASTAPASS(1) UNLSMB2JIRQHook(int a) {
if (IRQa) {
IRQCount += a;
if (IRQCount >= 0xFFFF) {
IRQa = 0;
IRQCount = 0;
IRQCount = IRQLatch;
X6502_IRQBegin(FCEU_IQEXT);
}
}
@@ -77,6 +133,10 @@ static void UNLKS7032Power(void) {
SetReadHandler(0x6000, 0x7FFF, CartBR);
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x4020, 0xFFFF, UNLKS7032Write);
if (!KS7032) {
SetWriteHandler(0x6000, 0x7FFF, CartBW);
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
}
}
static void StateRestore(int version) {
@@ -84,8 +144,27 @@ static void StateRestore(int version) {
}
void UNLKS7032_Init(CartInfo *info) {
KS7032 = 1;
info->Power = UNLKS7032Power;
MapIRQHook = UNLSMB2JIRQHook;
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
AddExState(&StateRegsKS7032, ~0, 0, 0);
}
void UNLKS202_Init(CartInfo *info) {
KS7032 = 0;
info->Power = UNLKS7032Power;
MapIRQHook = UNLSMB2JIRQHook;
GameStateRestore = StateRestore;
AddExState(&StateRegsKS7032, ~0, 0, 0);
AddExState(&StateRegsKS202, ~0, 0, 0);
WRAMSIZE = 8192;
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
}
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
}

View File

@@ -195,6 +195,37 @@ void Mapper61_Init(CartInfo *info) {
Latch_Init(info, M61Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0);
}
/*------------------ Map 063 ---------------------------*/
/* added 2019-5-23
* Mapper 63 NTDEC-Multicart
* http://wiki.nesdev.com/w/index.php/INES_Mapper_063
* - Powerful 250-in-1
* - Hello Kitty 255-in-1 */
static DECLFR(M63Read) {
if (latche & 0x0300)
return X.DB;
return CartBR(A);
}
static void M63Sync(void) {
uint16 mode = latche & 2;
uint16 prg_bank = (latche & 0x3F8) >> 1;
uint16 prg16 = (latche & 4) >> 1;
setprg8(0x8000, (prg_bank | (mode ? 0 : prg16 | 0)));
setprg8(0xA000, (prg_bank | (mode ? 1 : prg16 | 1)));
setprg8(0xC000, (prg_bank | (mode ? 2 : prg16 | 0)));
setprg8(0xE000, ((latche & 0x800) ? ((latche & 0x7C) | ((latche & 6) ? 3 : 1)) :
(prg_bank | (mode ? 3 : (prg16 | 1)))));
setchr8(0);
setmirror((latche & 1) ^ 1);
}
void Mapper63_Init(CartInfo *info) {
Latch_Init(info, M63Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0);
}
/*------------------ Map 092 ---------------------------*/
/* Another two-in-one mapper, two Jaleco carts uses similar
* hardware, but with different wiring.

110
src/boards/bmc60311c.c Normal file
View File

@@ -0,0 +1,110 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright (C) 2019 Libretro Team
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* added 2019-5-23
* UNIF: BMC-60311C:
* https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_289
*/
#include "mapinc.h"
static uint8 inner_bank, outer_bank, mode;
static SFORMAT StateRegs[] =
{
{ &inner_bank, 1, "INB0" },
{ &outer_bank, 1, "OUTB" },
{ &mode, 1, "MODE" },
{ 0 }
};
static void Sync(void) {
uint8 bbank = (mode & 4) ? 0 : (inner_bank & 7);
uint8 bank = outer_bank | bbank;
uint8 preg[2];
/* 0: NROM-128: Same inner/outer 16 KiB bank at CPU $8000-$BFFF
* and $C000-$FFFF
* 1: NROM-256: 32 kiB bank at CPU $8000-$FFFF (Selected inner/outer bank SHR 1)
* 2: UNROM: Inner/outer bank at CPU $8000-BFFF,
* fixed inner bank 7 within outer bank at $C000-$FFFF
* 3: Unknown
*
* The combined inner/outer bank is simply the inner bank, selected by the
* latch at $8000-$FFFF (or 0 if the latch is disabled) ORed with the
* outer bank selected by $6001, without any bit shifting.
*/
preg[0] = bank;
switch (mode & 3) {
case 0x00:
case 0x01:
preg[1] = bank | ((mode & 1) ? 1 : 0);
break;
case 0x02:
preg[1] = outer_bank | 7;
case 0x03:
break;
}
setchr8(0);
setprg16(0x8000, preg[0]);
setprg16(0xC000, preg[1]);
SetupCartMirroring(((mode & 8) >> 3) ^ 1, 1, NULL);
}
static DECLFW(Write0) {
mode = V;
Sync();
}
static DECLFW(Write1) {
outer_bank = V;
Sync();
}
static DECLFW(Write8) {
inner_bank = V;
Sync();
}
static void BMC60311CPower(void) {
inner_bank = outer_bank = mode = 0;
Sync();
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x6000, 0x6000, Write0);
SetWriteHandler(0x6001, 0x6001, Write1);
SetWriteHandler(0x8000, 0xFFFF, Write8);
}
static void BMC60311CReset(void) {
inner_bank = outer_bank = mode = 0;
Sync();
}
static void BMC60311CRestore(int version) {
Sync();
}
void BMC60311C_Init(CartInfo *info) {
info->Power = BMC60311CPower;
info->Reset = BMC60311CReset;
GameStateRestore = BMC60311CRestore;
AddExState(&StateRegs, ~0, 0, 0);
}

View File

@@ -225,6 +225,22 @@ void CPROM_Init(CartInfo *info) {
Latch_Init(info, CPROMSync, 0, 0x8000, 0xFFFF, 0, 0);
}
/*------------------ Map 29 ---------------------------*/
/* added 2019-5-23
* Mapper 28, used by homebrew game Glider
* https://wiki.nesdev.com/w/index.php/INES_Mapper_029 */
static void M29Sync(void) {
setprg16(0x8000, (latche >> 2) & 7);
setprg16(0xc000, ~0);
setchr8r(0, latche & 3);
setprg8r(0x10, 0x6000, 0);
}
void Mapper29_Init(CartInfo *info) {
Latch_Init(info, M29Sync, 0x0000, 0x6000, 0xFFFF, 1, 0);
}
/*------------------ Map 38 ---------------------------*/
static void M38Sync(void) {

171
src/boards/hp10xx_hp20xx.c Normal file
View File

@@ -0,0 +1,171 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2017 CaH4e3
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "mapinc.h"
#include "mmc3.h"
#include "../ines.h"
/* added on 2019-5-23 - NES 2.0 Mapper 260
* HP10xx/HP20xx - a simplified version of FK23C mapper with pretty strict and better
* organized banking behaviour. It seems that some 176 mapper assigned game may be
* actually this kind of board instead but in common they aren't compatible at all,
* the games on the regular FK23C boards couldn't run on this mapper and vice versa...
*/
static uint8 unromchr, lock;
static uint32 dipswitch;
static void BMCHPxxCW(uint32 A, uint8 V) {
if (EXPREGS[0] & 4) { /* custom banking */
switch(EXPREGS[0] & 3) {
case 0:
case 1:
setchr8(EXPREGS[2] & 0x3F);
/* FCEU_printf("\tCHR8 %02X\n",EXPREGS[2]&0x3F); */
break;
case 2:
setchr8((EXPREGS[2] & 0x3E) | (unromchr & 1));
/* FCEU_printf("\tCHR8 %02X\n",(EXPREGS[2]&0x3E)|(unromchr&1)); */
break;
case 3:
setchr8((EXPREGS[2] & 0x3C) | (unromchr & 3));
/* FCEU_printf("\tCHR8 %02X\n",(EXPREGS[2]&0x3C)|(unromchr&3)); */
break;
}
} else { /* mmc3 banking */
int base, mask;
if(EXPREGS[0] & 1) { /* 128K mode */
base = EXPREGS[2] & 0x30;
mask = 0x7F;
} else { /* 256K mode */
base = EXPREGS[2] & 0x20;
mask = 0xFF;
}
/* FCEU_printf("\tCHR1 %04x:%02X\n",A,(V&mask)|(base<<3)); */
setchr1(A, (V & mask) | (base << 3));
}
}
/* PRG wrapper */
static void BMCHPxxPW(uint32 A, uint8 V) {
if(EXPREGS[0] & 4) { /* custom banking */
if((EXPREGS[0] & 0xF) == 4) { /* 16K mode */
/* FCEU_printf("\tPRG16 %02X\n",EXPREGS[1]&0x1F); */
setprg16(0x8000, EXPREGS[1] & 0x1F);
setprg16(0xC000, EXPREGS[1] & 0x1F);
} else { /* 32K modes */
/* FCEU_printf("\tPRG32 %02X\n",(EXPREGS[1]&0x1F)>>1); */
setprg32(0x8000, (EXPREGS[1] & 0x1F) >> 1);
}
} else { /* mmc3 banking */
uint8 base, mask;
if(EXPREGS[0] & 2) { /* 128K mode */
base = EXPREGS[1] & 0x18;
mask = 0x0F;
} else { /* 256K mode */
base = EXPREGS[1] & 0x10;
mask = 0x1F;
}
/* FCEU_printf("\tPRG8 %02X\n",(V&mask)|(base<<1)); */
setprg8(A, (V & mask) | (base << 1));
setprg8r(0x10, 0x6000, A001B & 3);
}
}
/* MIRROR wrapper */
static void BMCHPxxMW(uint8 V) {
if(EXPREGS[0] & 4) { /* custom banking */
/* FCEU_printf("CUSTOM MIRR: %d\n",(unromchr>>2)&1); */
setmirror(((unromchr >> 2) & 1) ^ 1);
} else { /* mmc3 banking */
/* FCEU_printf("MMC3 MIRR: %d\n",(V&1)^1); */
A000B = V;
setmirror((A000B & 1) ^ 1);
}
}
/* PRG handler ($8000-$FFFF) */
static DECLFW(BMCHPxxHiWrite) {
/* FCEU_printf("HI WRITE %04X:%02X\n",A,V); */
if(EXPREGS[0] & 4) { /* custom banking */
/* FCEU_printf("CUSTOM\n"); */
unromchr = V;
FixMMC3CHR(MMC3_cmd);
} else { /* mmc3 banking */
/* FCEU_printf("MMC3\n"); */
if(A<0xC000) {
MMC3_CMDWrite(A, V);
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
} else {
MMC3_IRQWrite(A, V);
}
}
}
/* EXP handler ($5000-$5FFF) */
static DECLFW(BMCHPxxWrite) {
if (!lock) {
/* FCEU_printf("LO WRITE %04X:%02X\n",A,V); */
EXPREGS[A & 3] = V;
lock = V & 0x80;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
}
}
static DECLFR(BMCHPxxRead) {
return dipswitch;
}
static void BMCHPxxReset(void) {
dipswitch++;
dipswitch &= 0xF;
lock = 0;
/* FCEU_printf("BMCHPxx dipswitch set to %d\n",dipswitch); */
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
MMC3RegReset();
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
}
static void BMCHPxxPower(void) {
GenMMC3Power();
dipswitch = lock = 0;
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
SetReadHandler(0x5000, 0x5fff, BMCHPxxRead);
SetWriteHandler(0x5000, 0x5fff, BMCHPxxWrite);
SetWriteHandler(0x8000, 0xffff, BMCHPxxHiWrite);
}
void BMCHPxx_Init(CartInfo *info) {
GenMMC3_Init(info, 256, 256, 8, 0);
cwrap = BMCHPxxCW;
pwrap = BMCHPxxPW;
mwrap = BMCHPxxMW;
info->Power = BMCHPxxPower;
info->Reset = BMCHPxxReset;
AddExState(EXPREGS, 8, 0, "EXPR");
AddExState(&unromchr, 1, 0, "UCHR");
AddExState(&dipswitch, 1, 0, "DPSW");
AddExState(&lock, 1, 0, "LOCK");
}

74
src/boards/super40in1.c Normal file
View File

@@ -0,0 +1,74 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright (C) 2019 Libretro Team
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* added 2019-5-23
* BMC-WS Used for Super 40-in-1 multicart
* https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_332 */
#include "mapinc.h"
static uint8 preg, creg;
static SFORMAT StateRegs[] =
{
{ &preg, 1, "PREG" },
{ &creg, 1, "CREG" },
{ 0 }
};
static void Sync(void) {
if (preg & 8) {
setprg16(0x8000, preg & 7);
setprg16(0xc000, preg & 7);
}
else
setprg32(0x8000, (preg & 6) >> 1);
setchr8(creg);
setmirror(((preg >> 4) & 1) ^ 1);
}
static DECLFW(BMCWSWrite) {
if (preg & 0x20)
return;
switch (A & 1) {
case 0: preg = V; Sync(); break;
case 1: creg = V; Sync(); break;
}
}
static void MBMCWSPower(void) {
Sync();
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x6000, 0x6001, BMCWSWrite);
}
static void BMCWSReset(void) {
}
static void StateRestore(int version) {
Sync();
}
void BMCWS_Init(CartInfo *info) {
info->Reset = BMCWSReset;
info->Power = MBMCWSPower;
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
}

View File

@@ -317,7 +317,7 @@
{0x6bea1235, 245, -1}, /* MMC3 cart, but with nobanking applied to CHR-RAM, so let it be there */
{0x345ee51a, 245, -1}, /* DQ4c */
{0x57514c6c, 245, -1}, /* Yong Zhe Dou E Long - Dragon Quest VI (Ch) */
{0xdb9d71b7, 114, -1}, /* Super Donkey Kong (Unl) [o1] */
{0x00000000, -1, -1}
#endif

View File

@@ -417,10 +417,10 @@ static BMAPPINGLocal bmap[] = {
{(uint8_t*)"Konami VRC2/VRC4 D", 25, Mapper25_Init},
{(uint8_t*)"Konami VRC6 Rev. B", 26, Mapper26_Init},
{(uint8_t*)"CC-21 MI HUN CHE", 27, UNLCC21_Init}, /* Former dupe for VRC2/VRC4 mapper, redefined with crc to mihunche boards */
/* {(uint8_t*)"", 28, Mapper28_Init}, */ /* Custom Multidiscrete mapper for PDs */
/* {(uint8_t*)"", 29, Mapper29_Init}, */
{(uint8_t*)"Action 53", 28, Mapper28_Init},
{(uint8_t*)"", 29, Mapper29_Init},
{(uint8_t*)"UNROM 512", 30, UNROM512_Init},
/* {(uint8_t*)"", 31, Mapper31_Init}, */
{(uint8_t*)"infineteNesLives-NSF", 31, Mapper31_Init},
{(uint8_t*)"IREM G-101", 32, Mapper32_Init},
{(uint8_t*)"TC0190FMC/TC0350FMR", 33, Mapper33_Init},
{(uint8_t*)"IREM I-IM/BNROM", 34, Mapper34_Init},
@@ -445,14 +445,14 @@ static BMAPPINGLocal bmap[] = {
{(uint8_t*)"SUPERVISION 16-in-1", 53, Supervision16_Init},
/* {(uint8_t*)"", 54, Mapper54_Init}, */
/* {(uint8_t*)"", 55, Mapper55_Init}, */
/* {(uint8_t*)"", 56, Mapper56_Init}, */
{(uint8_t*)"UNLKS202", 56, UNLKS202_Init},
{(uint8_t*)"SIMBPLE BMC PIRATE A", 57, Mapper57_Init},
{(uint8_t*)"SIMBPLE BMC PIRATE B", 58, BMCGK192_Init},
{(uint8_t*)"", 59, Mapper59_Init}, /* Check this out */
{(uint8_t*)"SIMBPLE BMC PIRATE C", 60, BMCD1038_Init},
{(uint8_t*)"20-in-1 KAISER Rev. A",61, Mapper61_Init},
{(uint8_t*)"700-in-1", 62, Mapper62_Init},
/* {(uint8_t*)"", 63, Mapper63_Init}, */
{(uint8_t*)"", 63, Mapper63_Init},
{(uint8_t*)"TENGEN RAMBO1", 64, Mapper64_Init},
{(uint8_t*)"IREM-H3001", 65, Mapper65_Init},
{(uint8_t*)"MHROM", 66, MHROM_Init},
@@ -571,7 +571,7 @@ static BMAPPINGLocal bmap[] = {
/* {(uint8_t*)"", 179, Mapper179_Init}, */
{(uint8_t*)"", 180, Mapper180_Init},
{(uint8_t*)"", 181, Mapper181_Init},
/* {(uint8_t*)"", 182, Mapper182_Init}, */ /* Deprecated, dupe */
/* {(uint8_t*)"", 182, Mapper182_Init}, */ /* Deprecated, dupe of Mapper 114 */
{(uint8_t*)"", 183, Mapper183_Init},
{(uint8_t*)"", 184, Mapper184_Init},
{(uint8_t*)"", 185, Mapper185_Init},
@@ -644,7 +644,8 @@ static BMAPPINGLocal bmap[] = {
{(uint8_t*)"SAN GUO ZHI PIRATE", 252, Mapper252_Init},
{(uint8_t*)"DRAGON BALL PIRATE", 253, Mapper253_Init},
{(uint8_t*)"", 254, Mapper254_Init},
/* {(uint8_t*)"", 255, Mapper255_Init}, */ /* No good dumps for this mapper */
{(uint8_t*)"", 255, Mapper255_Init}, /* Duplicate of M225? */
{(uint8_t*)"", 0, NULL}
};
@@ -742,10 +743,6 @@ int iNESLoad(const char *name, FCEUFILE *fp) {
iNESCart.CRC32 = iNESGameCRC32;
FCEU_printf(" PRG ROM: %3d x 16KiB\n", head.ROM_size ? head.ROM_size : 256);
FCEU_printf(" CHR ROM: %3d x 8KiB\n", head.VROM_size);
FCEU_printf(" ROM CRC32: 0x%08lx\n", iNESGameCRC32);
FCEU_printf(" ROM MD5: 0x%s\n", md5_asciistr(iNESCart.MD5));
mappername = "Not Listed";
for (mappertest = 0; mappertest < (sizeof bmap / sizeof bmap[0]) - 1; mappertest++) {
@@ -755,12 +752,6 @@ int iNESLoad(const char *name, FCEUFILE *fp) {
}
}
FCEU_printf(" Mapper #: %d\n", MapperNo);
FCEU_printf(" Mapper name: %s\n", mappername);
FCEU_printf(" Mirroring: %s\n", Mirroring == 2 ? "None (Four-screen)" : Mirroring ? "Vertical" : "Horizontal");
FCEU_printf(" Battery-backed: %s\n", (head.ROM_type & 2) ? "Yes" : "No");
FCEU_printf(" Trained: %s\n", (head.ROM_type & 4) ? "Yes" : "No");
SetInput();
CheckHInfo();
{
@@ -790,10 +781,22 @@ int iNESLoad(const char *name, FCEUFILE *fp) {
iNESCart.battery = (head.ROM_type & 2) ? 1 : 0;
iNESCart.mirror = Mirroring;
FCEU_printf(" ROM CRC32: 0x%08lx\n", iNESGameCRC32);
FCEU_printf(" ROM MD5: 0x%s\n", md5_asciistr(iNESCart.MD5));
FCEU_printf(" PRG ROM: %3d x 16KiB\n", head.ROM_size ? head.ROM_size : 256);
FCEU_printf(" CHR ROM: %3d x 8KiB\n", head.VROM_size);
if (!iNES_Init(MapperNo))
FCEU_PrintError("iNES mapper #%d is not supported at all.", MapperNo);
iNESCart.mapper = MapperNo;
FCEU_printf(" \n");
FCEU_printf(" Mapper #: %3d\n", MapperNo);
FCEU_printf(" Mapper name: %s\n", mappername);
FCEU_printf(" Mirroring: %s\n", Mirroring == 2 ? "None (Four-screen)" : Mirroring ? "Vertical" : "Horizontal");
FCEU_printf(" Battery-backed: %s\n", (head.ROM_type & 2) ? "Yes" : "No");
FCEU_printf(" Trained: %s\n", (head.ROM_type & 4) ? "Yes" : "No");
GameInterface = iNESGI;
FCEU_printf("\n");
@@ -831,6 +834,8 @@ static int iNES_Init(int num) {
switch (num) { /* FIXME, mapper or game data base with the board parameters and ROM/RAM sizes */
case 13: CHRRAMSize = 16 * 1024; break;
case 6:
case 28:
case 29:
case 30:
case 45:
case 96: CHRRAMSize = 32 * 1024; break;
@@ -843,6 +848,7 @@ static int iNES_Init(int num) {
UNIFchrrama = VROM;
SetupCartCHRMapping(0, VROM, CHRRAMSize, 1);
AddExState(VROM, CHRRAMSize, 0, "CHRR");
FCEU_printf(" CHR RAM: %3d x 1KiB\n", CHRRAMSize / 1024);
}
if (head.ROM_type & 8)
AddExState(ExtraNTARAM, 2048, 0, "EXNR");

View File

@@ -63,7 +63,9 @@ void Mapper23_Init(CartInfo *);
void Mapper24_Init(CartInfo *);
void Mapper25_Init(CartInfo *);
void Mapper26_Init(CartInfo *);
void UNROM512_Init(CartInfo *); /* Mapper #30 */
void Mapper28_Init(CartInfo *);
void Mapper29_Init(CartInfo *);
void Mapper31_Init(CartInfo *);
void Mapper32_Init(CartInfo *);
void Mapper33_Init(CartInfo *);
void Mapper34_Init(CartInfo *);
@@ -87,6 +89,7 @@ void Mapper57_Init(CartInfo *);
void Mapper59_Init(CartInfo *);
void Mapper61_Init(CartInfo *);
void Mapper62_Init(CartInfo *);
void Mapper63_Init(CartInfo *);
void Mapper64_Init(CartInfo *);
void Mapper65_Init(CartInfo *);
void Mapper67_Init(CartInfo *);
@@ -222,5 +225,6 @@ void Mapper250_Init(CartInfo *);
void Mapper252_Init(CartInfo *);
void Mapper253_Init(CartInfo *);
void Mapper254_Init(CartInfo *);
void Mapper255_Init(CartInfo *);
#endif

View File

@@ -463,6 +463,10 @@ static BMAPPING bmap[] = {
{ "RT-01", UNLRT01_Init, 0 },
{ "81-01-31-C", BMC810131C_Init, 0 },
{ "8-IN-1", BMC8IN1_Init, 0 },
{ "RET-CUFROM", Mapper29_Init, BMCFLAG_32KCHRR },
{ "60311C", BMC60311C_Init, 0 },
{ "WS", BMCWS_Init, 0 },
{ "HPxx", BMCHPxx_Init, 0 },
#ifdef COPYFAMI
{ "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 },
@@ -609,6 +613,7 @@ int UNIFLoad(const char *name, FCEUFILE *fp) {
aborto:
FCEU_printf(" Failed to initialize board %s\n", boardname);
FreeUNIF();
ResetUNIF();
return 0;

View File

@@ -158,6 +158,12 @@ void UNLRT01_Init(CartInfo *info);
void BMC810131C_Init(CartInfo *info);
void BMC8IN1_Init(CartInfo *info);
/* additional boards */
void BMC60311C_Init(CartInfo *info); /* m289 */
void BMCWS_Init(CartInfo *info); /* m332 */
void UNLKS202_Init(CartInfo *info); /* m056 */
void BMCHPxx_Init(CartInfo *info); /* m260 */
#ifdef COPYFAMI
void MapperCopyFamiMMC3_Init(CartInfo *info);
void MapperCopyFami_Init(CartInfo *info);