Merge pull request #276 from retro-wertz/unif

add new UNIF boards and some fixes/updates to existing ones
This commit is contained in:
hizzlekizzle
2019-06-26 12:53:37 -05:00
committed by GitHub
26 changed files with 890 additions and 89 deletions

72
src/boards/830134C.c Normal file
View File

@@ -0,0 +1,72 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* 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
*/
/* NES 2.0 Mapper 315
* BMC-830134C
* Used for multicarts using 820732C- and 830134C-numbered PCBs such as 4-in-1 Street Blaster 5
* http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_315
*/
#include "mapinc.h"
#include "mmc3.h"
static void BMC830134CCW(uint32 A, uint8 V) {
uint32 chip = (EXPREGS[0] & 0x03) & ~((EXPREGS[0] & 0x02) >> 1);
setchr1r(chip, A, (V & 0xFF) | ((EXPREGS[0] & 0x01) << 8) | ((EXPREGS[0] & 0x02) << 6) | ((EXPREGS[0] & 0x08) << 3));
}
static void BMC830134CPW(uint32 A, uint8 V) {
uint32 chip = (EXPREGS[0] & 0x06) >> 1;
if ((EXPREGS[0] & 0x06) == 0x06) {
if (A == 0x8000) {
setprg8r(chip, A, (V & 0x0F) | ((EXPREGS[0] & 0x06) << 3));
setprg8r(chip, 0xC000, (V & 0x0F) | 0x32);
} else if (A == 0xA000) {
setprg8r(chip, A, (V & 0x0F) | ((EXPREGS[0] & 0x06) << 3));
setprg8r(chip, 0xE000, (V & 0x0F) | 0x32);
}
} else
setprg8r(chip, A, (V & 0x0F) | ((EXPREGS[0] & 0x06) << 3));
}
static DECLFW(BMC830134CWrite) {
EXPREGS[0] = V;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
}
static void BMC830134CReset(void) {
EXPREGS[0] = 0;
MMC3RegReset();
}
static void BMC830134CPower(void) {
GenMMC3Power();
SetWriteHandler(0x6800, 0x68FF, BMC830134CWrite);
}
void BMC830134C_Init(CartInfo *info) {
GenMMC3_Init(info, 128, 256, 1, 0);
pwrap = BMC830134CPW;
cwrap = BMC830134CCW;
info->Power = BMC830134CPower;
info->Reset = BMC830134CReset;
AddExState(EXPREGS, 1, 0, "EXPR");
}

View File

@@ -130,13 +130,13 @@ static void tekprom(void) {
case 0x00:
if (tkcom[0] & 0x80)
setprg8(0x6000, (((prgb[3] << 2) + 3) & 0x3F) | bankmode);
setprg32(0x8000, last_bank & prgmask | bankmode);
setprg32(0x8000, (last_bank & prgmask) | bankmode);
break;
case 0x01:
if (tkcom[0] & 0x80)
setprg8(0x6000, (((prgb[3] << 1) + 1) & 0x3F) | bankmode);
setprg16(0x8000, (prgb[1] & prgmask) | bankmode);
setprg16(0xC000, last_bank & prgmask | bankmode);
setprg16(0xC000, (last_bank & prgmask) | bankmode);
break;
case 0x02:
case 0x03:

View File

@@ -23,7 +23,7 @@
#include "mapinc.h"
static uint8 reg, mirr;
static uint8 latche, reg, mirr;
static int32 IRQa, IRQCount, IRQLatch;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
@@ -35,6 +35,7 @@ static SFORMAT StateRegs[] =
{ &IRQa, 4, "IRQA" },
{ &IRQCount, 4, "IRQC" },
{ &IRQLatch, 4, "IRQL" },
{ &latche, 1, "LATC" },
{ 0 }
};
@@ -47,8 +48,9 @@ static void Sync(void) {
static DECLFW(UNLKS7017Write) {
/* FCEU_printf("bs %04x %02x\n",A,V); */
if ((A & 0xFF00) == 0x4A00) {
reg = ((A >> 2) & 3) | ((A >> 4) & 4);
latche = ((A >> 2) & 3) | ((A >> 4) & 4);
} else if ((A & 0xFF00) == 0x5100) {
reg = latche;
Sync();
} else if (A == 0x4020) {
X6502_IRQEnd(FCEU_IQEXT);

View File

@@ -553,7 +553,7 @@ static void BMCTJ03Sync(void) {
setchr8(bank);
if (bank == 3) mirr ^= 1; /* Twin Bee has incorrect mirroring */
SetupCartMirroring(mirr, 1, NULL);
setmirror(mirr);
}
void BMCTJ03_Init(CartInfo *info) {
@@ -568,7 +568,7 @@ static void BMCSA005ASync(void) {
setprg16(0x8000, latche & 0x0F);
setprg16(0xC000, latche & 0x0F);
setchr8(latche & 0x0F);
SetupCartMirroring((latche >> 3) & 1, 1, NULL);
setmirror((latche >> 3) & 1);
}
void BMCSA005A_Init(CartInfo *info) {

95
src/boards/ax40g.c Normal file
View File

@@ -0,0 +1,95 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* 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
*/
/* NES 2.0 Mapper 527 is used for a bootleg version of
* Taito's 不動明王伝 (Fudō Myōō Den).
* Its UNIF board name is UNL-AX-40G. The original INES Mapper 207 is
* replaced with a VRC2 clone (A0/A1, i.e. VRC2b) while retaining
* Mapper 207's extended mirroring.
*/
#include "mapinc.h"
static uint8 preg[2], creg[8], NT[2];
static SFORMAT StateRegs[] =
{
{ preg, 2, "PREG" },
{ creg, 8, "CREG" },
{ NT, 2, "NMT" },
{ 0 }
};
static void Sync(void) {
uint8 i;
setprg8(0x8000, preg[0]);
setprg8(0xA000, preg[1]);
setprg8(0xC000, 0x1E);
setprg8(0xE000, 0x1F);
for (i = 0; i < 8; i++)
setchr1(i << 10, creg[i]);
setmirrorw(NT[0], NT[0], NT[1], NT[1]);
}
static DECLFW(UNLAX40GWrite8) {
A &= 0xF003;
preg[0] = V & 0x1F;
Sync();
}
static DECLFW(UNLAX40GWriteA) {
A &= 0xF003;
preg[1] = V & 0x1F;
Sync();
}
static DECLFW(UNLAX40GWriteB) {
uint16 i, shift;
A &= 0xF003;
i = ((A >> 1) & 1) | ((A - 0xB000) >> 11);
shift = ((A & 1) << 2);
creg[i] = (creg[i] & (0xF0 >> shift)) | ((V & 0xF) << shift);
if (i < 2)
NT[i] = (creg[i] & 0x80) >> 7;
Sync();
}
static void UNLAX40GPower(void) {
Sync();
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x8000, 0x8FFF, UNLAX40GWrite8);
SetWriteHandler(0xA000, 0xAFFF, UNLAX40GWriteA);
SetWriteHandler(0xB000, 0xEFFF, UNLAX40GWriteB);
}
static void StateRestore(int version) {
Sync();
}
void UNLAX40G_Init(CartInfo *info) {
info->Power = UNLAX40GPower;
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
}
/*void UNLAX40G_Init(CartInfo *info); // m527
{ "AX-40G", UNLAX40G_Init, 0 },
{ "JC-016-2", Mapper205_Init, 0 },
*/

119
src/boards/bj56.c Normal file
View File

@@ -0,0 +1,119 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* 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
*/
/* NES 2.0 Mapper 526 is used for a bootleg version of Namco's 三国志: 中原の覇者 (Sangokushi: Chūgen no Hasha).
* Its UNIF board name is UNL-BJ-56.
* Mirroring seems to be hard-wired (to vertical).
* https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_526
*/
#include "mapinc.h"
static uint8 preg[4], creg[8];
static uint32 IRQCount;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static SFORMAT StateRegs[] =
{
{ preg, 4, "PREG" },
{ creg, 8, "CREG" },
{ &IRQCount, 4, "IRQC" },
{ 0 }
};
static void Sync(void) {
uint8 i;
setprg8r(0x10, 0x6000, 0);
setprg8(0x8000, preg[0]);
setprg8(0xA000, preg[1]);
setprg8(0xC000, preg[2]);
setprg8(0xE000, preg[3]);
for (i = 0; i < 8; i++)
setchr1((i << 10), creg[i]);
setmirror(MI_V);
}
static DECLFW(UNLBJ56Write) {
/* FCEU_printf("Wr: A:%04x V:%02x\n", A, V); */
A &= 0xF00F;
if (A <= 0x8007) {
creg[A & 0x07] = V;
Sync();
} else if (A <= 0x800B) {
preg[A & 0x03] = V;
Sync();
} else {
switch (A & 0x0F) {
case 0x0D:
case 0x0F:
/* One of these two acknowledges a pending IRQ, and the other
* resets to IRQ counter to zero. Because they are always written
* to one after the other, it's not clear which one does which. */
X6502_IRQEnd(FCEU_IQEXT);
IRQCount = 0;
break;
}
}
}
static void FP_FASTAPASS(1) UNLBJ56IRQHook(int a) {
IRQCount += a;
if (IRQCount & 4096)
X6502_IRQBegin(FCEU_IQEXT);
}
static void UNLBJ56Close(void) {
if (WRAM)
FCEU_gfree(WRAM);
WRAM = NULL;
}
static void UNLBJ56Power(void) {
preg[0] = ~3;
preg[1] = ~2;
preg[2] = ~1;
preg[3] = ~0;
Sync();
SetReadHandler(0x6000, 0xFFFF, CartBR);
SetWriteHandler(0x6000, 0x7FFF, CartBW);
SetWriteHandler(0x8000, 0x800F, UNLBJ56Write);
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
}
static void StateRestore(int version) {
Sync();
}
void UNLBJ56_Init(CartInfo *info) {
info->Power = UNLBJ56Power;
info->Close = UNLBJ56Close;
MapIRQHook = UNLBJ56IRQHook;
GameStateRestore = StateRestore;
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");
AddExState(&StateRegs, ~0, 0, 0);
}

View File

@@ -66,7 +66,7 @@ static void Sync(void) {
setchr8(0);
setprg16(0x8000, preg[0]);
setprg16(0xC000, preg[1]);
SetupCartMirroring(((mode & 8) >> 3) ^ 1, 1, NULL);
setmirror(((mode & 8) >> 3) ^ 1);
}
static DECLFW(Write0) {

View File

@@ -35,11 +35,11 @@ static SFORMAT StateRegs[] =
static void Sync(void) {
if (mode & 0x02)
setprg16(0x8000, regs[0] & 0x0F | regs[1] & 0x70);
setprg16(0x8000, (regs[0] & 0x0F) | (regs[1] & 0x70));
else
setprg16r(1, 0x8000, regs[0] & 0x03);
setprg16(0xC000, regs[1]);
SetupCartMirroring(((regs[0] >> 4) & 1) ^ 1, 1, NULL);
setmirror(((regs[0] >> 4) & 1) ^ 1);
}
static DECLFW(BMC80013BWrite) {

View File

@@ -26,66 +26,46 @@
#include "mapinc.h"
static uint8 regs[2];
static uint8 isMermaid = 0;
static uint8 bank_size;
static uint8 inner_bank;
static uint8 outer_bank;
static SFORMAT StateRegs[] =
{
{ regs, 2, "REGS" },
{ &isMermaid, 1, "MERM" },
{ &inner_bank, 1, "INNB" },
{ &outer_bank, 1, "OUTB" },
{ &bank_size, 1, "SIZE" },
{ 0 }
};
static void Sync(void) {
uint8 bank_size = (regs[0] & 0x80) ? 0x07: 0x0F;
uint8 outer_bank = !isMermaid ? (regs[0] & 0x78) : 0x04;
uint8 inner_bank = regs[1];
uint8 game_block = regs[0] & 0x78;
/* TODO: Hacky and forced mapping of outer banks(game block)... */
if (!isMermaid) {
switch(game_block) {
case 0x00: /* botb outerbank=0 */
case 0x10: /* rocketeer outerbank=1 */
case 0x20: /* contra outerbank=2 */
case 0x28: /* ducktales outerbank=3 */
case 0x38: /* school fight outerbank=5 */
outer_bank = (game_block >> 4) + ((game_block & 0x08) ? 0x01 : 0x00);
outer_bank |= (game_block >> 3) & 1;
break;
case 0x30:
/* Mermaid game block is tricky (to me at least). Aim here is
* when this register is selected, ignore any other outer bank reg changes */
isMermaid = 1;
outer_bank = 0x04;
break;
}
}
setprg16r(outer_bank, 0x8000, (inner_bank & bank_size));
setprg16r(outer_bank, 0xC000, bank_size);
setchr8(0);
}
static DECLFW(M320Write) {
if ((A & 0xF0E0) == 0xF0E0) {
regs[0] = (A & 0x1F) << 3;
const uint8 chip[] = { 0, 0, 1, 0, 2, 3, 4, 5 };
/* address mask is inconsistent with that is in the wiki. Mask should be
* 0xFFE0 or Mermaid game will not work. */
if ((A & 0xFFE0) == 0xF0E0) {
outer_bank = chip[(A & 0x0F)];
bank_size = (A & 0x10) ? 0x07 : 0x0F;
}
regs[1] = V & 0x0F;
inner_bank = (V & 0x0F);
Sync();
}
static void M320Power(void) {
regs[0] = regs[1] = 0;
isMermaid = 0;
bank_size = 0x0F;
Sync();
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x8000, 0xFFFF, M320Write);
}
static void M320Reset(void) {
regs[0] = regs[1] = 0;
isMermaid = 0;
inner_bank = outer_bank = 0;
bank_size = 0x0F;
Sync();
}

View File

@@ -43,7 +43,7 @@ static void Sync(void) {
setprg32(0x8000, regs[PRG] & 0x07);
setchr8(regs[CHR] & 0x0F);
SetupCartMirroring(((regs[PRG] >> 5) & 1) ^ 1, 1, NULL);
setmirror(((regs[PRG] >> 5) & 1) ^ 1);
}
static DECLFW(WritePRG) {

95
src/boards/bmcgamecard.c Normal file
View File

@@ -0,0 +1,95 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* 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
*/
/* NES 2.0 Mapper 337 - BMC-CTC-12IN1
* 12-in-1 Game Card multicart
* https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_337
* NES 2.0 Mapper 350 - BMC-891227
* Super 15-in-1 Game Card
* https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_350
*/
#include "mapinc.h"
static uint8 latche, m350;
static SFORMAT StateRegs[] =
{
{ &latche, 1, "LATC" },
{ &m350, 1, "M350" },
{ 0 }
};
static void Sync(void) {
uint8 mirroring = m350 ? ((latche >> 7) & 1) : ((latche >> 5) & 1);
uint8 mode = m350 ? ((latche >> 5) & 0x03) : ((latche >> 6) & 0x03);
uint8 chip = m350 ? ((mode & 2) ? ((latche >> 5) & 1) : 0) : 0;
setchr8(0);
setprg8(0x6000, 1);
setprg16r(PRGptr[1] ? chip : 0, 0x8000, (latche & 0x1F));
setprg16r(PRGptr[1] ? chip : 0, 0xC000, (latche & 0x1F) | ((mode & 2) ? 0x07 : (mode & 1)));
setmirror(mirroring ^ 1);
}
static DECLFW(BMCCTC12IN1Write8) {
latche = (latche & 7) | (V & ~7);
Sync();
}
static DECLFW(BMCCTC12IN1WriteC) {
latche = (latche & ~7) | (V & 7);
Sync();
}
static void BMCCTC12IN1Power(void) {
Sync();
SetReadHandler(0x6000, 0xFFFF, CartBR);
SetWriteHandler(0x8000, 0xBFFF, BMCCTC12IN1Write8);
SetWriteHandler(0xC000, 0xFFFF, BMCCTC12IN1WriteC);
}
static void BMCCTC12IN1Reset(void) {
latche = 0;
Sync();
}
static void StateRestore(int version) {
Sync();
}
/* Mapper 337 - BMC-CTC-12IN1 */
void BMCCTC12IN1_Init(CartInfo *info) {
m350 = 0;
info->Power = BMCCTC12IN1Power;
info->Reset = BMCCTC12IN1Reset;
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
}
/* Mapper 350 - BMC-891227 */
void BMC891227_Init(CartInfo *info) {
m350 = 1;
info->Power = BMCCTC12IN1Power;
info->Reset = BMCCTC12IN1Reset;
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
}

89
src/boards/bmck3033.c Normal file
View File

@@ -0,0 +1,89 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* 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
*/
/* NES 2.0 Mapper 322
* BMC-K-3033
* 35-in-1 (K-3033)
* http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_322
*/
#include "mapinc.h"
#include "mmc3.h"
static void BMCK3033CW(uint32 A, uint8 V) {
if (EXPREGS[2]) {
if (EXPREGS[3]) { // MMC3-256
setchr1r(EXPREGS[1] & ~0x01, A, (V & 0xFF));
} else { // MMC3-128
setchr1r(EXPREGS[1], A, (V & 0x7F));
}
} else { // NROM
setchr1r(EXPREGS[1], A, (V & 0x7F));
}
}
static void BMCK3033PW(uint32 A, uint8 V) {
if (EXPREGS[2]) {
if (EXPREGS[3] ) {
/* FCEU_printf("MMC3-256 A:%04x V:%02x chip:%02x\n", A, V, EXPREGS[1] & ~0x01); */
setprg8r((EXPREGS[1] & ~0x01), A, (V & 0x1F));
} else {
/* FCEU_printf("MMC3-128 A:%04x V:%02x chip:%02x\n", A, V, EXPREGS[1]); */
setprg8r(EXPREGS[1], A, (V & 0x0F));
}
} else {
if (EXPREGS[0] & 0x03) {
/* FCEU_printf("NROM-256 base:%02x chip:%02x\n", EXPREGS[0] >> 1, EXPREGS[1]); */
setprg32r(EXPREGS[1], 0x8000, EXPREGS[0] >> 1);
} else {
/* FCEU_printf("NROM-128 base:%02x chip:%02x\n", EXPREGS[0], EXPREGS[1]); */
setprg16r(EXPREGS[1], 0x8000, EXPREGS[0]);
setprg16r(EXPREGS[1], 0xC000, EXPREGS[0]);
}
}
}
static DECLFW(BMCK3033Write) {
EXPREGS[0] = (A & 0x07);
EXPREGS[1] = ((A & 0x18) >> 3) | ((A & 0x40) >> 4);
EXPREGS[2] = (A & 0x20);
EXPREGS[3] = (A & 0x80);
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
}
static void BMCK3033Power(void) {
GenMMC3Power();
SetWriteHandler(0x6000, 0x7FFF, BMCK3033Write);
}
static void BMCK3033Reset(void) {
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
MMC3RegReset();
}
void BMCK3033_Init(CartInfo *info) {
GenMMC3_Init(info, 256, 256, 1, 0);
pwrap = BMCK3033PW;
cwrap = BMCK3033CW;
info->Power = BMCK3033Power;
info->Reset = BMCK3033Reset;
AddExState(EXPREGS, 4, 0, "EXPR");
}

View File

@@ -26,40 +26,44 @@
#include "mapinc.h"
static uint8 regs[2];
static uint8 regs[2], mirr, mode;
static SFORMAT StateRegs[] =
{
{ regs, 2, "REGS" },
{ regs, 2, "REGS" },
{ &mode, 1, "MODE" },
{ &mirr, 1, "MIRR" },
{ 0 }
};
static void Sync(void) {
if (regs[0] & 0x20) { /* NROM-128 */
setprg16(0x8000, regs[0] & 0x1F);
setprg16(0xC000, regs[0] & 0x1F);
if (mode) { /* NROM-128 */
setprg16(0x8000, regs[0]);
setprg16(0xC000, regs[0]);
} else { /* UNROM */
setprg16(0x8000, regs[0] & 0x1F | regs[1] & 0x07);
setprg16(0xC000, regs[0] & 0x1F | 0x07);
setprg16(0x8000, regs[0] | regs[1]);
setprg16(0xC000, regs[0] | 0x07);
}
setchr8(0);
SetupCartMirroring(((regs[0] & 0x25) == 0x25 ? MI_H : MI_V), 1, NULL);
setmirror(mirr);
}
static DECLFW(M340Write) {
regs[0] = A & 0xFF;
regs[1] = V & 0xFF;
regs[0] = A & 0x1F;
regs[1] = V & 0x07;
mode = A & 0x20;
mirr = ((A & 0x25) == 0x25) ? 0 : 1;
Sync();
}
static void BMCK3036Power(void) {
Sync();
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x8000, 0xBFFF, M340Write);
SetWriteHandler(0x8000, 0xFFFF, M340Write);
}
static void BMCK3036Reset(void) {
regs[0] = regs[1] = 0;
regs[0] = regs[1] = mode = mirr = 0;
Sync();
}

72
src/boards/bmck3088.c Normal file
View File

@@ -0,0 +1,72 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* 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
*/
/* NES 2.0 Mapper 287
* similar to BMC-411120-C but without jumper or dipswitch */
#include "mapinc.h"
#include "mmc3.h"
static void BMCK3088CW(uint32 A, uint8 V) {
if (CHRptr[EXPREGS[0] & 7])
setchr1r(EXPREGS[0] & 7, A, V);
else
setchr1(A, V | ((EXPREGS[0] & 3) << 7));
}
static void BMCK3088PW(uint32 A, uint8 V) {
if (PRGptr[EXPREGS[0] & 7]) {
uint8 chip = EXPREGS[0] & 7;
if (EXPREGS[0] & 8)
setprg32r(chip, 0x8000, ((EXPREGS[0] >> 4) & 3));
else
setprg8r(chip, A, (V & 0x0F));
} else {
if (EXPREGS[0] & 8)
setprg32(0x8000, ((EXPREGS[0] >> 4) & 3) | (0x0C));
else
setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 3) << 4));
}
}
static DECLFW(BMCK3088LoWrite) {
EXPREGS[0] = A;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
}
static void BMCK3088Reset(void) {
EXPREGS[0] = 0;
MMC3RegReset();
}
static void BMCK3088Power(void) {
GenMMC3Power();
SetWriteHandler(0x6000, 0x7FFF, BMCK3088LoWrite);
}
void BMCK3088_Init(CartInfo *info) {
GenMMC3_Init(info, 128, 128, 8, 0);
pwrap = BMCK3088PW;
cwrap = BMCK3088CW;
info->Power = BMCK3088Power;
info->Reset = BMCK3088Reset;
AddExState(EXPREGS, 1, 0, "EXPR");
}

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

@@ -0,0 +1,74 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* 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
*/
/* NES 2.0 Mapper 345
* BMC-L6IN1
* New Star 6-in-1 Game Cartridge
* https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_345
*/
#include "mapinc.h"
#include "mmc3.h"
static void BMCL6IN1CW(uint32 A, uint8 V) {
setchr8(V);
}
static void BMCL6IN1PW(uint32 A, uint8 V) {
if (EXPREGS[0] & 0x0C)
setprg8(A, (V & 0x0F) | (EXPREGS[0] & 0xC0) >> 2);
else
setprg32(0x8000, ((EXPREGS[0] & 0xC0) >> 4) | (EXPREGS[0] & 0x03));
}
static void BMCL6IN1MW(uint8 V) {
if (EXPREGS[0] & 0x20)
setmirror(MI_0 + ((EXPREGS[0] & 0x10) >> 1));
else {
A000B = V;
setmirror((V & 1) ^ 1);
}
}
static DECLFW(BMCL6IN1Write) {
EXPREGS[0] = V;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
}
static void BMCL6IN1Reset(void) {
EXPREGS[0] = 0;
MMC3RegReset();
}
static void BMCL6IN1Power(void) {
GenMMC3Power();
SetWriteHandler(0x6000, 0x7FFF, BMCL6IN1Write);
}
void BMCL6IN1_Init(CartInfo *info) {
GenMMC3_Init(info, 512, 0, 1, 0);
pwrap = BMCL6IN1PW;
cwrap = BMCL6IN1CW;
mwrap = BMCL6IN1MW;
info->Power = BMCL6IN1Power;
info->Reset = BMCL6IN1Reset;
AddExState(EXPREGS, 1, 0, "EXPR");
}

View File

@@ -18,36 +18,40 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* Updated 6-27-19 */
#include "mapinc.h"
static uint16 addrlatch;
static uint8 datalatch, hw_mode;
static uint8 datalatch, addrlatch, lock, hw_mode;
static SFORMAT StateRegs[] =
{
{ &addrlatch, 2, "ADRL" },
{ &addrlatch, 1, "ADRL" },
{ &datalatch, 1, "DATL" },
{ &hw_mode, 1, "HWMO" },
{ &hw_mode, 1, "HWMO" },
{ &lock, 1, "LOCK" },
{ 0 }
};
static void Sync(void) {
uint8 prg = (addrlatch & 7);
uint8 prg = (addrlatch & 0x3F);
setchr8(datalatch);
if(addrlatch & 0x80) {
if (addrlatch & 0x80) {
setprg16(0x8000,prg);
setprg16(0xC000,prg);
} else {
setprg32(0x8000,prg >> 1);
}
setmirror(MI_V);
setmirror(((datalatch >> 7) & 1) ^ 1);
}
static DECLFW(EH8813AWrite) {
if((addrlatch & 0x100) == 0) {
addrlatch = A & 0x1FF;
datalatch = V & 0xF;
if (lock == 0) {
addrlatch = A & 0xFF;
datalatch = V & 0xFC;
lock = (A & 0x100) >> 8;
}
datalatch = (datalatch & ~0x03) | (V & 0x03);
Sync();
}
@@ -56,16 +60,16 @@ static DECLFR(EH8813ARead) {
A= (A & 0xFFF0) + hw_mode;
return CartBR(A);
}
static void EH8813APower(void) {
addrlatch = datalatch = hw_mode = 0;
addrlatch = datalatch = hw_mode = lock = 0;
Sync();
SetReadHandler(0x8000, 0xFFFF, EH8813ARead);
SetWriteHandler(0x8000, 0xFFFF, EH8813AWrite);
}
static void EH8813AReset(void) {
addrlatch = datalatch = 0;
addrlatch = datalatch = lock = 0;
hw_mode = (hw_mode + 1) & 0xF;
FCEU_printf("Hardware Switch is %01X\n", hw_mode);
Sync();

70
src/boards/faridunrom.c Normal file
View File

@@ -0,0 +1,70 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* 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
*/
/* NES 2.0 Mapper 324
* FARID_UNROM_8-IN-1
* https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_324
*/
#include "mapinc.h"
static uint8 latch;
static SFORMAT StateRegs[] =
{
{ &latch, 1, "LATC" },
{ 0 }
};
static void Sync(void) {
setchr8(0);
setprg16(0x8000, ((latch & 0x70) >> 1) | (latch & 0x07));
setprg16(0xC000, ((latch & 0x70) >> 1) | 0x07 );
}
static DECLFW(FARIDUNROMWrite) {
V &= CartBR(A);
if ((V & 0x80) && !(latch & 0x80) && !(latch & 0x08))
latch = (latch & 0x87) | (V & 0x78);
latch = (latch & 0x78) | (V & 0x87);
Sync();
}
static void FARIDUNROMPower(void) {
Sync();
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x8000, 0xFFFF, FARIDUNROMWrite);
}
static void FARIDUNROMReset(void) {
latch &= ~0x78;
Sync();
}
static void StateRestore(int version) {
Sync();
}
void FARIDUNROM_Init(CartInfo *info) {
info->Power = FARIDUNROMPower;
info->Reset = FARIDUNROMReset;
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
}

68
src/boards/gn26.c Normal file
View File

@@ -0,0 +1,68 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
*
*
* 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
*/
/* NES 2.0 Mapper 344
* BMC-GN-26
* Kuai Da Jin Ka Zhong Ji Tiao Zhan 3-in-1 (3-in-1,6-in-1,Unl)
*/
#include "mapinc.h"
#include "mmc3.h"
static void BMCGN26CW(uint32 A, uint8 V) {
uint32 chip = (EXPREGS[0] & 0x03);
if (chip) chip -= 1;
setchr1r(chip, A, (V & 0xFF));
}
static void BMCGN26PW(uint32 A, uint8 V) {
uint32 chip = (EXPREGS[0] & 0x03);
if (chip) chip -= 1; /* Re-ordered -> 0:SF4 1:Contra Force 2:Revolution Hero */
if (EXPREGS[0] & 4) {
if (A == 0x8000)
setprg32r(chip, 0x8000, (V >> 2));
} else
setprg8r(chip, A, (V & 0x0F));
}
static DECLFW(BMCGN26Write) {
EXPREGS[0] = A & 0x0F;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
}
static void BMCGN26Reset(void) {
EXPREGS[0] = 0;
MMC3RegReset();
}
static void BMCGN26Power(void) {
GenMMC3Power();
SetWriteHandler(0x6800, 0x68FF, BMCGN26Write);
}
void BMCGN26_Init(CartInfo *info) {
GenMMC3_Init(info, 128, 256, 1, 0);
pwrap = BMCGN26PW;
cwrap = BMCGN26CW;
info->Power = BMCGN26Power;
info->Reset = BMCGN26Reset;
AddExState(EXPREGS, 1, 0, "EXPR");
}

View File

@@ -440,6 +440,6 @@ void FARIDSLROM8IN1_Init(CartInfo *info) {
MMC1PRGHook16 = FARIDSLROM8IN1PRGHook;
info->Power = FARIDSLROM8IN1Power;
info->Reset = FARIDSLROM8IN1Reset;
AddExState(lock, 1, 0, "LOCK");
AddExState(reg, 1, 0, "REG6");
AddExState(&lock, 1, 0, "LOCK");
AddExState(&reg, 1, 0, "REG6");
}

View File

@@ -599,6 +599,12 @@ void Mapper47_Init(CartInfo *info) {
}
/* ---------------------------- Mapper 49 ------------------------------- */
/* -------------------- BMC-STREETFIGTER-GAME4IN1 ----------------------- */
/* added 6-24-19:
* BMC-STREETFIGTER-GAME4IN1 - Sic. $6000 set to $41 rather than $00 on power-up.
*/
static uint8 isUNIF = 0;
static void M49PW(uint32 A, uint8 V) {
if (EXPREGS[0] & 1) {
@@ -625,11 +631,12 @@ static DECLFW(M49Write) {
}
static void M49Reset(void) {
EXPREGS[0] = 0;
EXPREGS[0] = isUNIF ? 0x41 : 0;
MMC3RegReset();
}
static void M49Power(void) {
EXPREGS[0] = isUNIF ? 0x41 : 0;
M49Reset();
GenMMC3Power();
SetWriteHandler(0x6000, 0x7FFF, M49Write);
@@ -637,6 +644,7 @@ static void M49Power(void) {
}
void Mapper49_Init(CartInfo *info) {
isUNIF = 0;
GenMMC3_Init(info, 512, 256, 0, 0);
cwrap = M49CW;
pwrap = M49PW;
@@ -645,6 +653,16 @@ void Mapper49_Init(CartInfo *info) {
AddExState(EXPREGS, 1, 0, "EXPR");
}
void BMCSFGAME4IN1_Init(CartInfo *info) {
isUNIF = 1;
GenMMC3_Init(info, 512, 512, 0, 0);
cwrap = M49CW;
pwrap = M49PW;
info->Reset = M49Reset;
info->Power = M49Power;
AddExState(EXPREGS, 1, 0, "EXPR");
}
/* ---------------------------- Mapper 52 ------------------------------- */
static void M52PW(uint32 A, uint8 V) {
uint32 mask = 0x1F ^ ((EXPREGS[0] & 8) << 1);
@@ -1169,20 +1187,29 @@ void Mapper198_Init(CartInfo *info) {
}
/* ---------------------------- Mapper 205 ------------------------------ */
/* https://wiki.nesdev.com/w/index.php/INES_Mapper_205 */
/* UNIF boardname BMC-JC-016-2
https://wiki.nesdev.com/w/index.php/INES_Mapper_205 */
static uint8 block[] = {0, 0, 1, 2};
static void M205PW(uint32 A, uint8 V) {
setprg8(A, EXPREGS[0] & 0x30 | (V & (!(EXPREGS[0] & 0xC0) ? 0x1F : 0x0F)));
uint8 bank = V & ((EXPREGS[0] & 0x02) ? 0x0F : 0x1F);
if (PRGptr[1])
setprg8r(block[EXPREGS[0]], A, bank);
else
setprg8(A, EXPREGS[0] << 4 | bank);
}
static void M205CW(uint32 A, uint8 V) {
uint16 reg = (uint16)EXPREGS[0] & 0x30;
setchr1(A, (reg << 3) | V);
uint8 bank = V & ((EXPREGS[0] & 0x02) ? 0x7F : 0xFF);
if (PRGptr[1])
setchr1r(block[EXPREGS[0]], A, bank);
else
setchr1(A, (EXPREGS[0] << 7) | bank);
}
static DECLFW(M205Write0) {
if (EXPREGS[1] == 0) {
EXPREGS[0] = (V << 4) & 0x30;
EXPREGS[0] = V & 0x03;
EXPREGS[1] = A & 0x80;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
@@ -1212,7 +1239,7 @@ static void M205Power(void) {
}
void Mapper205_Init(CartInfo *info) {
GenMMC3_Init(info, 128, 128, 8, 0);
GenMMC3_Init(info, 256, 128, 8, 0);
pwrap = M205PW;
cwrap = M205CW;
info->Power = M205Power;

View File

@@ -59,7 +59,7 @@ static void StateRestore(int version) {
void BMCRESETNROMXIN1_Init(CartInfo *info) {
uint8 x;
uint64 partialmd5;
uint64 partialmd5 = 0;
for (x = 0; x < 8; x++)
partialmd5 |= (uint64)info->MD5[15 - x] << (x * 8);

View File

@@ -28,11 +28,11 @@
#include "mmc3.h"
static void M313CW(uint32 A, uint8 V) {
setchr1r(EXPREGS[0], A, V & 0x7F);
setchr1r(CHRptr[1] ? EXPREGS[0] : 0, A, (EXPREGS[0] << 7) | (V & 0x7F));
}
static void M313PW(uint32 A, uint8 V) {
setprg8r(EXPREGS[0], A, V & 0x0F);
setprg8r(PRGptr[1] ? EXPREGS[0] : 0, A, (EXPREGS[0] << 4) | (V & 0x0F));
}
static void M313Reset(void) {
@@ -48,7 +48,7 @@ static void M313Power(void) {
/* NES 2.0 313, UNIF BMC-RESET-TXROM */
void BMCRESETTXROM_Init(CartInfo *info) {
GenMMC3_Init(info, 512, 256, 0, 0);
GenMMC3_Init(info, 128, 128, 0, 0);
cwrap = M313CW;
pwrap = M313PW;
info->Power = M313Power;

View File

@@ -33,8 +33,13 @@ static SFORMAT StateRegs[] =
static void Sync(void) {
setchr8(0);
setprg16(0x8000, base | bank);
setprg16(0xC000, base | (mode ? bank : 7));
if (PRGptr[1]) {
setprg16r(base >> 3, 0x8000, bank);
setprg16r(base >> 3, 0xC000, (mode ? bank : 7));
} else {
setprg16(0x8000, base | bank);
setprg16(0xC000, base | (mode ? bank : 7));
}
setmirror(mirr);
}

View File

@@ -113,7 +113,8 @@ static uint8 exntar[2048];
static void MooMirroring(void) {
if (mirrortodo < 0x4)
SetupCartMirroring(mirrortodo, 1, 0);
/* 06-22-19 Allow override when using vertical/horizontal mirroring. */
SetupCartMirroring(mirrortodo, (mirrortodo >> 1) & 1, 0);
else if (mirrortodo == 0x4) {
SetupCartMirroring(4, 1, exntar);
AddExState(exntar, 2048, 0, "EXNR");
@@ -472,13 +473,12 @@ static BMAPPING bmap[] = {
{ "WAIXING-FW01", Mapper227_Init, 0 }, /* https://wiki.nesdev.com/w/index.php/Talk:INES_Mapper_242 */
{ "WAIXING-FS005", BMCFK23C_Init, 0 }, /* https://wiki.nesdev.com/w/index.php/INES_Mapper_176 */
{ "80013-B", BMC80013B_Init, 0 },
{ "TH2131-1", UNLTH21311_Init, 0 },
{ "LH51", LH51_Init, 0 },
{ "RESETNROM-XIN1", BMCRESETNROMXIN1_Init, 0 },
{ " BMC-RESET-TXROM", BMCRESETTXROM_Init, 0 },
{ "RESET-TXROM", BMCRESETTXROM_Init, 0 },
{ "K-3088", BMC411120C_Init, 0 },
{ "K-3088", BMCK3088_Init, 0 },
{ "FARID_SLROM_8-IN-1", FARIDSLROM8IN1_Init, 0 },
{ "830425C-4391T", BMC830425C4391T_Init, 0 },
{ "TJ-03", BMCTJ03_Init, 0 },
@@ -491,6 +491,19 @@ static BMAPPING bmap[] = {
{ "KS7021A", UNLKS7021A_Init, 0 },
{ "KS106C", BMCKS106C_Init, 0 },
{ "900218", BTL900218_Init, 0 },
{ "JC-016-2", Mapper205_Init, 0 },
{ "AX-40G", UNLAX40G_Init, 0 },
{ " BMC-STREETFIGTER-GAME4IN1", BMCSFGAME4IN1_Init, 0 },
{ "G631", BMCGhostbusters63in1_Init, 0 },
{ "BJ-56", UNLBJ56_Init, 0 },
{ "L6IN1", BMCL6IN1_Init, 0 },
{ "CTC-12IN1", BMCCTC12IN1_Init, 0 },
{ "891227", BMC891227_Init, 0 },
{ "NEWSTAR-GRM070-8IN1", BMC8IN1_Init, 0 },
{ "FARID_UNROM_8-IN-1", FARIDUNROM_Init, 0 },
{ "K-3033", BMCK3033_Init, 0 },
{ "830134C", BMC830134C_Init, 0 },
{ "GN-26", BMCGN26_Init, 0 },
#ifdef COPYFAMI
{ "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 },

View File

@@ -179,6 +179,18 @@ void BMCK3036_Init(CartInfo *info); /* m340 */
void MINDKIDS_Init(CartInfo *info); /* m268 */
void UNLKS7021A_Init(CartInfo *info); /* m525 */
void BTL900218_Init(CartInfo *info); /* m524 */
void UNLAX40G_Init(CartInfo *info); /* m527 */
void BMCK3088_Init(CartInfo *info); /* m287 */
void BMCSFGAME4IN1_Init(CartInfo *info); /* m049 */
void UNLBJ56_Init(CartInfo *info); /* m526 */
void BMCL6IN1_Init(CartInfo *info); /* m345 */
void BMCCTC12IN1_Init(CartInfo *info); /* m337 */
void BMC891227_Init(CartInfo *info); /* m350 */
void FARIDUNROM_Init(CartInfo *info); /* m324 */
void BMCK3033_Init(CartInfo *info); /* mm22 */
void BMC830134C_Init(CartInfo *info); /* m315 */
void BMCGN26_Init(CartInfo *info); /* m344 */
#ifdef COPYFAMI
void MapperCopyFamiMMC3_Init(CartInfo *info);