Merge pull request #637 from NRS-NewRisingSun/asic_modularize

New Mappers and modularization
This commit is contained in:
LibretroAdmin
2025-09-13 02:57:07 +02:00
committed by GitHub
183 changed files with 9564 additions and 3326 deletions

View File

@@ -1,7 +1,7 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2011 CaH4e3
* Copyright (C) 2023
*
* 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
@@ -16,353 +16,130 @@
* 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
*
* SL12 Protected 3-in-1 mapper hardware (VRC2, MMC3, MMC1)
* the same as 603-5052 board (TODO: add reading registers, merge)
* SL1632 2-in-1 protected board, similar to SL12 (TODO: find difference)
*
* Known PCB:
*
* Garou Densetsu Special (G0904.PCB, Huang-1, GAL dip: W conf.)
* Kart Fighter (008, Huang-1, GAL dip: W conf.)
* Somari (008, C5052-13, GAL dip: P conf., GK2-P/GK2-V maskroms)
* Somari (008, Huang-1, GAL dip: W conf., GK1-P/GK1-V maskroms)
* AV Mei Shao Nv Zhan Shi (aka AV Pretty Girl Fighting) (SL-12 PCB, Hunag-1, GAL dip: unk conf. SL-11A/SL-11B maskroms)
* Samurai Spirits (Full version) (Huang-1, GAL dip: unk conf. GS-2A/GS-4A maskroms)
* Contra Fighter (603-5052 PCB, C5052-3, GAL dip: unk conf. SC603-A/SCB603-B maskroms)
*
*/
#include "mapinc.h"
#include "asic_mmc1.h"
#include "asic_mmc3.h"
#include "asic_vrc2and4.h"
static uint8 vrc2_chr[8] = { 0 };
static uint8 vrc2_prg[2] = { 0 };
static uint8 vrc2_mirr = 0;
static uint8 submapper;
static uint8 reg;
static uint8 init; /* Games switch between ASICs expecting registers to keep their value, so initialize each ASIC only on the first switch and use this bitfield to track it */
static uint8 game;
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 uint8 submapper = 0;
static uint8 game = 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" },
{ &mmc1_buffer, 1, "M1BF" },
{ &mmc1_shift, 1, "M1MR" },
{ &submapper, 1, "SUBM" },
{ &game, 1, "GAME" },
{ 0 }
static SFORMAT stateRegs[] = {
{ &reg, 1, "MODE" },
{ &init, 1, "INIT" },
{ 0 },
};
static void SyncPRG(void) {
uint8 mask = (submapper != 3) ? 0x3F : (game ? 0x0F : 0x1F);
uint8 outer = game ? (game + 1) * 0x10 : 0;
switch (mode & 3) {
case 0:
setprg8(0x8000, (outer & ~mask) | (vrc2_prg[0] & mask));
setprg8(0xA000, (outer & ~mask) | (vrc2_prg[1] & mask));
setprg8(0xC000, (outer & ~mask) | (~1 & mask));
setprg8(0xE000, (outer & ~mask) | (~0 & mask));
break;
case 1:
{
uint32 swap = (mmc3_ctrl >> 5) & 2;
setprg8(0x8000, (outer & ~mask) | (mmc3_regs[6 + swap] & mask));
setprg8(0xA000, (outer & ~mask) | (mmc3_regs[7] & mask));
setprg8(0xC000, (outer & ~mask) | (mmc3_regs[6 + (swap ^ 2)] & mask));
setprg8(0xE000, (outer & ~mask) | (mmc3_regs[9] & mask));
break;
static SFORMAT stateRegsMulti[] = {
{ &game, 1, "GAME" },
{ 0 },
};
static void sync (void) {
int prgAND, chrAND, prgOR, chrOR;
if (submapper == 3) { /* First game is 256K+256K, the others 128K+128K */
prgAND = game? 0x0F: 0x1F;
chrAND = game? 0x7F: 0xFF;
prgOR = game <<4 &~prgAND;
chrOR = game <<7 &~chrAND;
} else {
prgAND = 0x3F;
chrAND = 0xFF;
prgOR = 0x00 &~prgAND;
chrOR = reg <<6 &0x100 &~chrAND;
}
case 2:
case 3:
{
uint8 bank = mmc1_regs[3] & mask;
if (mmc1_regs[0] & 8) {
if (submapper == 2)
bank >>= 1;
if (mmc1_regs[0] & 4) {
setprg16(0x8000, bank);
setprg16(0xC000, 0x0F);
} else {
setprg16(0x8000, 0);
setprg16(0xC000, bank);
}
} else
setprg32(0x8000, ((outer & ~mask) >> 1) | (bank >> 1));
}
break;
if (reg &0x02) {
prgAND >>= 1;
prgOR >>= 1;
chrAND >>= 2;
chrOR >>= 2;
MMC1_syncPRG(prgAND, prgOR);
MMC1_syncCHR(chrAND, chrOR);
MMC1_syncMirror();
} else
if (reg &0x01) {
MMC3_syncPRG(prgAND, prgOR);
MMC3_syncCHR(chrAND, chrOR);
MMC3_syncMirror();
} else {
VRC24_syncPRG(prgAND, prgOR);
VRC24_syncCHR(chrAND, chrOR);
VRC24_syncMirror();
}
}
static void SyncCHR(void) {
uint32 mask = game ? 0x7F : 0xFF;
uint32 outer = game ? (game + 1) * 0x80 : 0;
uint32 base = (mode & 4) << 6;
switch (mode & 3) {
case 0:
setchr1(0x0000, ((outer | base) & ~mask) | (vrc2_chr[0] & mask));
setchr1(0x0400, ((outer | base) & ~mask) | (vrc2_chr[1] & mask));
setchr1(0x0800, ((outer | base) & ~mask) | (vrc2_chr[2] & mask));
setchr1(0x0c00, ((outer | base) & ~mask) | (vrc2_chr[3] & mask));
setchr1(0x1000, ((outer | base) & ~mask) | (vrc2_chr[4] & mask));
setchr1(0x1400, ((outer | base) & ~mask) | (vrc2_chr[5] & mask));
setchr1(0x1800, ((outer | base) & ~mask) | (vrc2_chr[6] & mask));
setchr1(0x1c00, ((outer | base) & ~mask) | (vrc2_chr[7] & mask));
break;
case 1: {
uint32 swap = (mmc3_ctrl & 0x80) << 5;
setchr1(0x0000 ^ swap, ((outer | base) & ~mask) | ((mmc3_regs[0] & 0xFE) & mask));
setchr1(0x0400 ^ swap, ((outer | base) & ~mask) | ((mmc3_regs[0] | 1) & mask));
setchr1(0x0800 ^ swap, ((outer | base) & ~mask) | ((mmc3_regs[1] & 0xFE) & mask));
setchr1(0x0c00 ^ swap, ((outer | base) & ~mask) | ((mmc3_regs[1] | 1) & mask));
setchr1(0x1000 ^ swap, ((outer | base) & ~mask) | (mmc3_regs[2] & mask));
setchr1(0x1400 ^ swap, ((outer | base) & ~mask) | (mmc3_regs[3] & mask));
setchr1(0x1800 ^ swap, ((outer | base) & ~mask) | (mmc3_regs[4] & mask));
setchr1(0x1c00 ^ swap, ((outer | base) & ~mask) | (mmc3_regs[5] & mask));
break;
}
case 2:
case 3:
if (mmc1_regs[0] & 0x10) {
setchr4(0x0000, (outer & ~mask) | (mmc1_regs[1] & mask));
setchr4(0x1000, (outer & ~mask) | (mmc1_regs[2] & mask));
} else
setchr8(((outer & ~mask) >> 1) | (mmc1_regs[1] & mask) >> 1);
break;
}
int Huang2_getPRGBank (uint8 bank) {
return MMC1_getPRGBank(bank) >>1;
}
static void SyncMIR(void) {
switch (mode & 3) {
case 0: {
setmirror((vrc2_mirr & 1) ^ 1);
break;
}
case 1: {
setmirror((mmc3_mirr & 1) ^ 1);
break;
}
case 2:
case 3: {
switch (mmc1_regs[0] & 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;
}
break;
}
}
}
static void Sync(void) {
SyncPRG();
SyncCHR();
SyncMIR();
}
static DECLFW(UNLSL12ModeWrite) {
if (A & 0x100) {
mode = V;
if (A & 1) { /* hacky hacky, there are two configuration modes on SOMARI HUANG-1 PCBs
* Solder pads with P1/P2 shorted called SOMARI P,
* Solder pads with W1/W2 shorted called SOMARI W
* Both identical 3-in-1 but W wanted MMC1 registers
* to be reset when switch to MMC1 mode P one - doesn't
* There is issue with W version of Somari at starting copyrights
*/
mmc1_regs[0] = 0xc;
mmc1_regs[3] = 0;
mmc1_buffer = 0;
mmc1_shift = 0;
}
Sync();
}
}
static DECLFW(UNLSL12Write) {
/* FCEU_printf("%04X:%02X\n",A,V); */
switch (mode & 3) {
case 0: {
if ((A >= 0xB000) && (A <= 0xE003)) {
int32 ind = ((((A & 2) | (A >> 10)) >> 1) + 2) & 7;
int32 sar = ((A & 1) << 2);
vrc2_chr[ind] = (vrc2_chr[ind] & (0xF0 >> sar)) | ((V & 0x0F) << sar);
SyncCHR();
} else
switch (A & 0xF000) {
case 0x8000: vrc2_prg[0] = V; SyncPRG(); break;
case 0xA000: vrc2_prg[1] = V; SyncPRG(); break;
case 0x9000: vrc2_mirr = V; SyncMIR(); break;
}
break;
}
case 1: {
switch (A & 0xE001) {
case 0x8000: {
uint8 old_ctrl = mmc3_ctrl;
mmc3_ctrl = V;
if ((old_ctrl & 0x40) != (mmc3_ctrl & 0x40))
SyncPRG();
if ((old_ctrl & 0x80) != (mmc3_ctrl & 0x80))
SyncCHR();
break;
}
case 0x8001:
mmc3_regs[mmc3_ctrl & 7] = V;
if ((mmc3_ctrl & 7) < 6)
SyncCHR();
else
SyncPRG();
break;
case 0xA000:
mmc3_mirr = V;
SyncMIR();
break;
case 0xC000:
IRQLatch = V;
break;
case 0xC001:
IRQReload = 1;
break;
case 0xE000:
X6502_IRQEnd(FCEU_IQEXT);
IRQa = 0;
break;
case 0xE001:
IRQa = 1;
break;
}
break;
}
case 2:
case 3: {
if (V & 0x80) {
mmc1_regs[0] |= 0xc;
mmc1_buffer = mmc1_shift = 0;
SyncPRG();
} else {
uint8 n = (A >> 13) - 4;
mmc1_buffer |= (V & 1) << (mmc1_shift++);
if (mmc1_shift == 5) {
mmc1_regs[n] = mmc1_buffer;
mmc1_buffer = mmc1_shift = 0;
switch (n) {
case 0: SyncMIR(); break;
case 2: SyncCHR(); break;
case 3:
case 1: SyncPRG(); break;
}
}
}
break;
}
}
}
static void UNLSL12HBIRQ(void) {
if ((mode & 3) == 1) {
int32 count = IRQCount;
if (!count || IRQReload) {
IRQCount = IRQLatch;
IRQReload = 0;
} else
IRQCount--;
if (!IRQCount) {
if (IRQa)
X6502_IRQBegin(FCEU_IQEXT);
static void applyMode (uint8 clear) {
PPU_hook = NULL;
MapIRQHook = NULL;
GameHBIRQHook = NULL;
if (reg &0x02) {
MMC1_activate(clear && init &1, sync, MMC1_TYPE_MMC1B, submapper == 2? Huang2_getPRGBank: NULL, NULL, NULL, NULL);
if (submapper != 1) MMC1_writeReg(0x8000, 0x80);
init &= ~1;
} else
if (reg &0x01) {
MMC3_activate(clear && init &2, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, NULL);
init &= ~2;
} else {
VRC2_activate(clear && init &4, sync, 0x01, 0x02, NULL, NULL, NULL, NULL);
if (init &4) { /* The earlier version of Somari needs specific VRC2 CHR register initialization */
VRC24_writeReg(0xB000, 0xFF); VRC24_writeReg(0xB001, 0xFF); VRC24_writeReg(0xB002, 0xFF); VRC24_writeReg(0xB003, 0xFF);
VRC24_writeReg(0xC000, 0xFF); VRC24_writeReg(0xC001, 0xFF); VRC24_writeReg(0xC002, 0xFF); VRC24_writeReg(0xC003, 0xFF);
VRC24_writeReg(0xD000, 0xFF); VRC24_writeReg(0xD001, 0xFF); VRC24_writeReg(0xD002, 0xFF); VRC24_writeReg(0xD003, 0xFF);
VRC24_writeReg(0xE000, 0xFF); VRC24_writeReg(0xE001, 0xFF); VRC24_writeReg(0xE002, 0xFF); VRC24_writeReg(0xE003, 0xFF);
init &= ~4;
}
}
}
static void StateRestore(int version) {
Sync();
}
static void UNLSL12Reset(void) {
/* this is suppose to increment during power cycle */
/* but we dont have a way to do that, so increment on reset instead. */
if (submapper == 3) {
game = game + 1;
if (game > 4)
game = 0;
static DECLFW (writeReg) {
if (A &0x100) {
uint8 previousReg = reg;
reg = V;
if ((previousReg ^V) &3)
applyMode(1);
else
sync();
}
Sync();
}
static void UNLSL12Power(void) {
game = (submapper == 3) ? 4 : 0;
mode = 1;
vrc2_chr[0] = ~0;
vrc2_chr[1] = ~0;
vrc2_chr[2] = ~0;
vrc2_chr[3] = ~0; /* W conf. of Somari wanted CHR3 has to be set to BB bank (or similar), but doesn't do that directly */
vrc2_chr[4] = 4;
vrc2_chr[5] = 5;
vrc2_chr[6] = 6;
vrc2_chr[7] = 7;
vrc2_prg[0] = 0;
vrc2_prg[1] = 1;
vrc2_mirr = 0;
mmc3_regs[0] = 0;
mmc3_regs[1] = 2;
mmc3_regs[2] = 4;
mmc3_regs[3] = 5;
mmc3_regs[4] = 6;
mmc3_regs[5] = 7;
mmc3_regs[6] = ~3;
mmc3_regs[7] = ~2;
mmc3_regs[8] = ~1;
mmc3_regs[9] = ~0;
mmc3_ctrl = mmc3_mirr = IRQCount = IRQLatch = IRQa = 0;
mmc1_regs[0] = 0xc;
mmc1_regs[1] = 0;
mmc1_regs[2] = 0;
mmc1_regs[3] = 0;
mmc1_buffer = 0;
mmc1_shift = 0;
Sync();
static void reset (void) {
reg = 1;
init = 7;
if (++game == 1) ++game; /* First game is twice as large */
if (game >= ROM_size /8) game = 0;
applyMode(1);
}
static void power (void) {
reg = 1;
init = 7;
game = 0;
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x4100, 0x5FFF, UNLSL12ModeWrite);
SetWriteHandler(0x8000, 0xFFFF, UNLSL12Write);
SetWriteHandler(0x4020, 0x5FFF, writeReg);
applyMode(1);
}
void UNLSL12_Init(CartInfo *info) {
info->Power = UNLSL12Power;
info->Reset = UNLSL12Reset;
GameHBIRQHook = UNLSL12HBIRQ;
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
submapper = info->submapper;
if (submapper == 0) {
/* PRG 128K and CHR 128K is Huang-2 (submapper 2) */
if (ROM_size == 8 && VROM_size == 16)
submapper = 2;
}
static void restore (int version) {
applyMode(0);
}
void UNLSL12_Init (CartInfo *info) {
submapper = info->submapper;
MMC1_addExState();
MMC3_addExState();
VRC24_addExState();
info->Reset = reset;
info->Power = power;
GameStateRestore = restore;
AddExState(stateRegs, ~0, 0, 0);
if (submapper == 3) AddExState(stateRegsMulti, ~0, 0, 0);
}

56
src/boards/122.c Normal file
View File

@@ -0,0 +1,56 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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"
static uint8 reg[2];
static void sync () {
setprg32(0x8000, 0);
setchr4(0x0000, reg[0]);
setchr4(0x1000, reg[1]);
}
static DECLFW (writeReg) {
reg[A &1] = V;
sync();
}
static void reset () {
reg[0] = reg[1] = 0;
sync();
}
static void power () {
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x8000, 0xFFFF, writeReg);
reset();
}
static void stateRestore (int version) {
sync();
}
void Mapper122_Init (CartInfo *info) {
info->Reset = reset;
info->Power = power;
GameStateRestore = stateRestore;
AddExState(reg, 2, 0, "REGS");
}

101
src/boards/14.c Normal file
View File

@@ -0,0 +1,101 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2023
*
* 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 "asic_mmc3.h"
#include "asic_vrc2and4.h"
static uint8 reg;
static uint8 init; /* Games switch between ASICs expecting registers to keep their value, so initialize each ASIC only on the first switch and use this bitfield to track it */
static void applyMode (uint8);
static SFORMAT StateRegs[] = {
{ &reg, 1, "MODE" },
{ &init, 1, "INIT" },
{ 0 },
};
static void sync (void) {
if (reg &0x02) {
MMC3_syncPRG(0x3F, 0x00);
MMC3_syncCHR(0x1FF, 0x00);
MMC3_syncMirror();
} else {
VRC24_syncPRG(0x3F, 0x00);
VRC24_syncCHR(0x1FF, 0x00);
VRC24_syncMirror();
}
}
int getCHRBank_MMC3 (uint8 bank) {
return MMC3_getCHRBank(bank) | reg <<(~bank &4? 5: ~bank &2? 3: 1) &0x100;
}
int getCHRBank_VRC2 (uint8 bank) {
return VRC24_getCHRBank(bank) | reg <<(~bank &4? 5: ~bank &2? 3: 1) &0x100;
}
static DECLFW (writeReg) {
uint8 previousReg = reg;
reg = V;
if ((previousReg ^V) &2)
applyMode(1);
else
sync();
}
static void applyMode (uint8 clear) {
PPU_hook = NULL;
MapIRQHook = NULL;
GameHBIRQHook = NULL;
if (reg &0x02) {
MMC3_activate(clear && init &1, sync, MMC3_TYPE_AX5202P, NULL, getCHRBank_MMC3, NULL, NULL);
init &= ~1;
} else {
VRC2_activate(clear && init &2, sync, 0x01, 0x02, NULL, getCHRBank_VRC2, NULL, NULL);
init &= ~2;
}
SetWriteHandler(0xA131, 0xA131, writeReg);
}
static void reset (void) {
reg = 0;
init = 3;
applyMode(1);
}
static void power (void) {
reg = 0;
init = 3;
applyMode(1);
}
static void restore (int version) {
applyMode(0);
}
void UNLSL1632_Init (CartInfo *info) {
MMC3_addExState();
VRC24_addExState();
info->Reset = reset;
info->Power = power;
GameStateRestore = restore;
AddExState(StateRegs, ~0, 0, 0);
}

View File

@@ -27,7 +27,9 @@
#include "mapinc.h"
static uint8 submapper;
static uint8 reg[4];
static uint8 pad[2];
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
@@ -79,6 +81,10 @@ static uint8 decode(uint8 code) {
return (acc >> 8) & 0xff;
}
static DECLFR(readPad) {
return CartBR(A &~3 | pad[1] &3);
}
static void M178Sync(void) {
uint32 sbank = reg[1] & 0x7;
uint32 bbank = reg[2];
@@ -100,6 +106,7 @@ static void M178Sync(void) {
}
setmirror((reg[0] & 1) ^ 1);
if (submapper == 3) SetReadHandler(0x8000, 0xffff, pad[0] &1? readPad: CartBR);
}
static void M551Sync(void) {
@@ -152,6 +159,11 @@ static DECLFR(M178ReadSnd) {
return X.DB;
}
static DECLFW(writePad) {
pad[0] = V;
M178Sync();
}
static void M551Power(void) {
reg[0] = reg[1] = reg[2] = reg[3] = 0;
M551Sync();
@@ -159,9 +171,9 @@ static void M551Power(void) {
SetWriteHandler(0x4800, 0x4fff, M551Write);
SetWriteHandler(0x5800, 0x5fff, M178WriteSnd);
SetReadHandler(0x5800, 0x5fff, M178ReadSnd);
SetReadHandler(0x8000, 0xffff, CartBR);
SetReadHandler(0x6000, 0x7fff, CartBR);
SetWriteHandler(0x6000, 0x7fff, CartBW);
SetReadHandler(0x8000, 0xffff, CartBR);
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
}
@@ -172,10 +184,15 @@ static void M178Power(void) {
SetWriteHandler(0x4800, 0x4fff, M178Write);
SetWriteHandler(0x5800, 0x5fff, M178WriteSnd);
SetReadHandler(0x5800, 0x5fff, M178ReadSnd);
SetReadHandler(0x6000, 0x7fff, CartBR);
SetWriteHandler(0x6000, 0x7fff, CartBW);
SetReadHandler(0x8000, 0xffff, CartBR);
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
if (submapper == 3)
SetWriteHandler(0x6000, 0x7fff, writePad);
else {
SetReadHandler(0x6000, 0x7fff, CartBR);
SetWriteHandler(0x6000, 0x7fff, CartBW);
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
}
pad[0] = pad[1] = 0;
}
static void M551Reset(void) {
@@ -189,6 +206,8 @@ static void M178Reset(void)
/* Always reset to menu */
reg[0] = reg[1] = reg[2] = reg[3] = 0;
M178Sync();
pad[0] = 0;
pad[1]++;
}
static void M178SndClk(int a)
@@ -217,6 +236,7 @@ static void M178StateRestore(int version) {
}
void Mapper178_Init(CartInfo *info) {
submapper = info->submapper;
info->Power = M178Power;
info->Reset = M178Reset;
info->Close = M178Close;
@@ -225,14 +245,18 @@ void Mapper178_Init(CartInfo *info) {
jedi_table_init();
WRAMSIZE = 32768;
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
if (submapper == 3)
AddExState(pad, 2, 0, "DIPS");
else {
WRAMSIZE = 32768;
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(WRAM, WRAMSIZE, 0, "WRAM");
AddExState(&StateRegs, ~0, 0, 0);

75
src/boards/182.c Normal file
View File

@@ -0,0 +1,75 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc3.h"
static uint8 reg[4];
static void sync () {
int prgAND = reg[1] &0x20? 0x1F: 0x0F;
int chrAND = reg[1] &0x40? 0xFF: 0x7F;
int prgOR = (reg[1] &0x02? 0x10: 0x00) | (reg[1] &0x10? 0x020: 0x00);
int chrOR = (reg[1] &0x02? 0x80: 0x00) | (reg[1] &0x10? 0x100: 0x00);
if (reg[0] &0x80) {
if (reg[0] &0x20)
setprg32(0x8000, reg[0] >>1);
else {
setprg16(0x8000, reg[0]);
setprg16(0xC000, reg[0]);
}
} else
MMC3_syncPRG(prgAND, prgOR &~prgAND);
MMC3_syncCHR(chrAND, chrOR &~chrAND);
MMC3_syncMirror();
}
static DECLFW (writeReg) {
if (~reg[1] &0x01) {
reg[A &3] = V;
sync();
}
}
static DECLFW (unscramble) {
static const uint16 lutAddress[8] = { 0xA001, 0xA000, 0x8000, 0xC000, 0x8001, 0xC001, 0xE000, 0xE001 }; /* i <5? 4-i: i */
static const uint8 lutIndex[8] = { 0, 3, 1, 5, 6, 7, 2, 4 }; /* i <6? (i^3)-1: i */
MMC3_writeReg(lutAddress[A >>12 &6 | A &1], (A &0xE001) == 0xA000? lutIndex[V &7]: V);
}
static void reset () {
reg[0] = reg[1] = reg[2] = reg[3] = 0;
MMC3_clear();
}
static void power () {
reg[0] = reg[1] = reg[2] = reg[3] = 0;
MMC3_power();
SetWriteHandler(0x8000, 0xFFFF, unscramble);
}
void Mapper182_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg);
info->Power = power;
info->Reset = reset;
AddExState(reg, 4, 0, "EXPR");
}

View File

@@ -19,11 +19,11 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
static uint8 prg;
static SFORMAT Mapper183_stateRegs[] ={
static SFORMAT stateRegs[] ={
{ &prg, 1, "PRG6" },
{ 0 }
};
@@ -35,20 +35,18 @@ static void sync () {
VRC24_syncMirror();
}
DECLFW(Mapper183_writePRG) {
static DECLFW (writePRG) {
prg =A &0xFF;
VRC24_Sync();
sync();
}
void Mapper183_power(void) {
static void power(void) {
prg =0;
VRC24_power();
}
void Mapper183_Init (CartInfo *info) {
VRC24_init(info, sync, 0x04, 0x08, 1, 1, 0);
VRC24_WRAMRead =CartBR;
VRC24_WRAMWrite =Mapper183_writePRG;
AddExState(Mapper183_stateRegs, ~0, 0, 0);
info->Power =Mapper183_power;
VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, CartBR, writePRG, NULL);
AddExState(stateRegs, ~0, 0, 0);
info->Power =power;
}

37
src/boards/213.c Normal file
View File

@@ -0,0 +1,37 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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 "asic_latch.h"
static void sync () {
if (Latch_address &0x08) {
setprg16(0x8000, Latch_address >>1 &~1 | Latch_address &1);
setprg16(0xC000, Latch_address >>1 &~1 | Latch_address &1);
} else
setprg32(0x8000, Latch_address >>2);
setchr8(Latch_address >>1 &~1 | Latch_address &1);
setmirror(Latch_address &0x02? MI_H: MI_V);
}
void Mapper213_Init (CartInfo *info) {
Latch_init(info, sync, 0x8000, 0xFFFF, NULL);
info->Reset = Latch_clear;
}

View File

@@ -19,7 +19,8 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
#include "cartram.h"
static void sync () {
VRC24_syncWRAM(0);
@@ -31,41 +32,38 @@ static void sync () {
void Mapper21_Init (CartInfo *info) {
switch(info->submapper) {
case 1: VRC24_init(info, sync, 0x02, 0x04, 1, 1, 8); break;
case 2: VRC24_init(info, sync, 0x40, 0x80, 1, 1, 8); break;
default: VRC24_init(info, sync, 0x42, 0x84, 1, 1, 8); break;
case 1: VRC4_init(info, sync, 0x02, 0x04, 1, NULL, NULL, NULL, NULL, NULL); break;
case 2: VRC4_init(info, sync, 0x40, 0x80, 1, NULL, NULL, NULL, NULL, NULL); break;
default: VRC4_init(info, sync, 0x42, 0x84, 1, NULL, NULL, NULL, NULL, NULL); break;
}
WRAM_init(info, 8);
}
int Mapper22_getCHRBank(int bank) {
return VRC24_chr[bank &7] >>1;
static int Mapper22_getCHRBank(uint8 bank) {
return VRC24_getCHRBank(bank &7) >>1;
}
void Mapper22_Init (CartInfo *info) {
VRC24_init(info, sync, 0x02, 0x01, 0, 0, 8);
VRC24_GetCHRBank =Mapper22_getCHRBank;
}
DECLFR(Mapper23_readProtection) {
return VRC2_pins;
VRC2_init(info, sync, 0x02, 0x01, NULL, Mapper22_getCHRBank, NULL, NULL);
WRAM_init(info, 8);
}
void Mapper23_Init (CartInfo *info) {
switch(info->submapper) {
case 1: VRC24_init(info, sync, 0x01, 0x02, 1, 1, 8); break;
case 2: VRC24_init(info, sync, 0x04, 0x08, 1, 1, 8); break;
case 3: VRC24_init(info, sync, 0x01, 0x02, 0, 0, 8);
VRC24_WRAMRead =Mapper23_readProtection;
break;
default: VRC24_init(info, sync, 0x05, 0x0A, 1, 1, 8); break;
case 1: VRC4_init(info, sync, 0x01, 0x02, 1, NULL, NULL, NULL, NULL, NULL); break;
case 2: VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, NULL, NULL, NULL); break;
case 3: VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL); break;
default: VRC4_init(info, sync, 0x05, 0x0A, 1, NULL, NULL, NULL, NULL, NULL); break;
}
WRAM_init(info, 8);
}
void Mapper25_Init (CartInfo *info) {
switch(info->submapper) {
case 1: VRC24_init(info, sync, 0x02, 0x01, 1, 1, 8); break;
case 2: VRC24_init(info, sync, 0x08, 0x04, 1, 1, 8); break;
case 3: VRC24_init(info, sync, 0x02, 0x01, 0, 0, 8); break;
default: VRC24_init(info, sync, 0x0A, 0x05, 1, 1, 8); break;
case 1: VRC4_init(info, sync, 0x02, 0x01, 1, NULL, NULL, NULL, NULL, NULL); break;
case 2: VRC4_init(info, sync, 0x08, 0x04, 1, NULL, NULL, NULL, NULL, NULL); break;
case 3: VRC2_init(info, sync, 0x02, 0x01, NULL, NULL, NULL, NULL); break;
default: VRC4_init(info, sync, 0x0A, 0x05, 1, NULL, NULL, NULL, NULL, NULL); break;
}
WRAM_init(info, 8);
}

View File

@@ -19,7 +19,7 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
static uint8 clockMode;
static uint8 pending;
@@ -27,7 +27,7 @@ static uint8 counter1;
static uint8 counter2;
static uint8 prescaler;
static SFORMAT Mapper222_stateRegs[] ={
static SFORMAT stateRegs[] = {
{ &clockMode, 1, "CLKM" },
{ &pending, 1, "PEND" },
{ &counter1, 1, "CNT1" },
@@ -42,39 +42,39 @@ static void sync () {
VRC24_syncMirror();
}
DECLFW(Mapper222_nibblizeCHR) {
static DECLFW (nibblizeCHR) {
if (~A &1) {
VRC24_writeReg(A, V);
VRC24_writeReg(A |1, V >>4);
}
}
DECLFW(Mapper222_writeIRQ) {
static DECLFW (writeIRQ) {
switch(A &3) {
case 0: clockMode =0;
case 0: clockMode = 0;
break;
case 1: pending =false;
case 1: pending = 0;
if (!clockMode) {
counter1 =V &0xF;
counter2 =V >>4;
counter1 = V &0xF;
counter2 = V >>4;
}
break;
case 2: clockMode =1;
case 2: clockMode = 1;
break;
}
}
void FP_FASTAPASS(1) Mapper222_cpuCycle(int a) {
static void FP_FASTAPASS(1) cpuCycle (int a) {
while (a--) {
uint8 previousPrescaler =prescaler;
uint8 previousPrescaler = prescaler;
if (pending)
prescaler =0;
prescaler = 0;
else
prescaler++;
if (clockMode && ~previousPrescaler &0x40 && prescaler &0x40) {
if (++counter1 ==0xF && ++counter2 ==0xF) pending =1;
counter1 &=0xF;
counter2 &=0xF;
if (++counter1 == 0xF && ++counter2 == 0xF) pending = 1;
counter1 &= 0xF;
counter2 &= 0xF;
}
if (pending)
X6502_IRQBegin(FCEU_IQEXT);
@@ -83,16 +83,16 @@ void FP_FASTAPASS(1) Mapper222_cpuCycle(int a) {
}
}
void Mapper222_power(void) {
clockMode =pending =counter1 =counter2 =prescaler =0;
static void power (void) {
clockMode = pending = counter1 = counter2 = prescaler = 0;
VRC24_power();
SetWriteHandler(0xB000, 0xEFFF, Mapper222_nibblizeCHR);
SetWriteHandler(0xF000, 0xFFFF, Mapper222_writeIRQ);
SetWriteHandler(0xB000, 0xEFFF, nibblizeCHR);
SetWriteHandler(0xF000, 0xFFFF, writeIRQ);
}
void Mapper222_Init (CartInfo *info) {
VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0);
AddExState(Mapper222_stateRegs, ~0, 0, 0);
info->Power =Mapper222_power;
MapIRQHook =Mapper222_cpuCycle;
VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL);
AddExState(stateRegs, ~0, 0, 0);
info->Power =power;
MapIRQHook = cpuCycle;
}

38
src/boards/239.c Normal file
View File

@@ -0,0 +1,38 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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 "asic_latch.h"
static void sync () {
if (Latch_address &0x04)
setprg32(0x8000, Latch_address >>1);
else {
setprg16(0x8000, Latch_address);
setprg16(0xC000, Latch_address);
}
setchr8(Latch_address);
setmirror(Latch_address &0x10? MI_H: MI_V);
}
void Mapper239_Init (CartInfo *info) {
Latch_init(info, sync, 0x8000, 0xFFFF, NULL);
info->Reset = Latch_clear;
}

View File

@@ -19,17 +19,16 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
#include "cartram.h"
static uint8 *CHRRAM;
static uint32 CHRRAMSize;
static uint8 mask;
static uint8 compare;
extern uint32 RefreshAddr;
static writefunc writePPU;
static SFORMAT stateRegs[] ={
static SFORMAT stateRegs[] = {
{ &mask, 1, "CHRM" },
{ &compare, 1, "CHRC" },
{ 0 }
@@ -39,65 +38,48 @@ static void sync () {
int bank;
VRC24_syncWRAM(0);
VRC24_syncPRG(0x01F, 0x000);
for (bank =0; bank <8; bank++) setchr1r((VRC24_chr[bank] &mask) ==compare? 0x10: 0x00, bank <<10, VRC24_chr[bank]);
for (bank = 0; bank < 8; bank++) setchr1r((VRC24_getCHRBank(bank) &mask) == compare? 0x10: 0x00, bank <<10, VRC24_getCHRBank(bank));
VRC24_syncMirror();
}
static DECLFW(Mapper252_253_interceptPPUWrite) {
static DECLFW (Mapper252_253_interceptPPUWrite) {
if (~RefreshAddr &0x2000) {
int bank =VRC24_chr[RefreshAddr >>10 &7];
int bank = VRC24_getCHRBank(RefreshAddr >>10 &7);
switch(bank) {
case 0x88: mask =0xFC; compare =0x4C; VRC24_Sync(); break;
case 0xC2: mask =0xFE; compare =0x7C; VRC24_Sync(); break;
case 0xC8: mask =0xFE; compare =0x04; VRC24_Sync(); break;
case 0x88: mask = 0xFC; compare = 0x4C; sync(); break;
case 0xC2: mask = 0xFE; compare = 0x7C; sync(); break;
case 0xC8: mask = 0xFE; compare = 0x04; sync(); break;
}
}
writePPU(A, V);
}
void Mapper252_power (void) {
mask =0xFE;
compare =0x06;
static void Mapper252_power (void) {
mask = 0xFE;
compare = 0x06;
VRC24_power();
writePPU =GetWriteHandler(0x2007);
writePPU = GetWriteHandler(0x2007);
SetWriteHandler(0x2007, 0x2007, Mapper252_253_interceptPPUWrite);
}
void Mapper253_power (void) {
mask =0xFE; /* There are two board revisions, the earlier one with a non-switchable mask/compare FE/04 and a later switchable one that starts with FC/28 */
compare =0x04;
static void Mapper253_power (void) {
mask = 0xFE; /* There are two board revisions, the earlier one with a non-switchable mask/compare FE/04 and a later switchable one that starts with FC/28 */
compare = 0x04;
VRC24_power();
writePPU =GetWriteHandler(0x2007);
writePPU = GetWriteHandler(0x2007);
SetWriteHandler(0x2007, 0x2007, Mapper252_253_interceptPPUWrite);
}
void Mapper252_253_close(void) {
if (CHRRAM) {
FCEU_gfree(CHRRAM);
CHRRAM =NULL;
}
}
void Mapper252_Init (CartInfo *info) {
VRC24_init(info, sync, 0x4, 0x8, 1, 1, 0);
info->Power =Mapper252_power;
info->Close =Mapper252_253_close;
VRC4_init(info, sync, 0x4, 0x8, 1, NULL, NULL, NULL, NULL, NULL);
CartRAM_init(info, 8, 2);
info->Power = Mapper252_power;
AddExState(stateRegs, ~0, 0, 0);
CHRRAMSize =info->iNES2? (info->CHRRamSize +info->CHRRamSaveSize): 2048;
CHRRAM =(uint8*)FCEU_gmalloc(CHRRAMSize);
AddExState(CHRRAM, CHRRAMSize, 0, "CRAM");
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
}
void Mapper253_Init (CartInfo *info) {
VRC24_init(info, sync, 0x4, 0x8, 1, 1, 0);
info->Power =Mapper253_power;
info->Close =Mapper252_253_close;
VRC4_init(info, sync, 0x4, 0x8, 1, NULL, NULL, NULL, NULL, NULL);
CartRAM_init(info, 8, 2);
info->Power = Mapper253_power;
AddExState(stateRegs, ~0, 0, 0);
CHRRAMSize =info->iNES2? (info->CHRRamSize +info->CHRRamSaveSize): 2048;
CHRRAM =(uint8*)FCEU_gmalloc(CHRRAMSize);
AddExState(CHRRAM, CHRRAMSize, 0, "CRAM");
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
}

View File

@@ -19,11 +19,11 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
static uint8 prg;
static SFORMAT UNLCITYFIGHT_stateRegs[] ={
static SFORMAT stateRegs[] ={
{ &prg, 1, "PRG8" },
{ 0 }
};
@@ -34,28 +34,27 @@ static void sync () {
VRC24_syncMirror();
}
DECLFW(UNLCITYFIGHT_externalSelect) {
static DECLFW (externalSelect) {
if (A &0x800)
(GetWriteHandler(0x4011))(0x4011, V <<3 &0x78);
else {
prg =V >>2;
VRC24_Sync();
sync();
}
}
DECLFW(UNLCITYFIGHT_unscrambleAddress) {
static DECLFW (unscrambleAddress) {
VRC24_writeReg(A &~0x6000 | A <<1 &0x4000 | A >>1 &0x2000, V);
}
void UNLCITYFIGHT_power(void) {
static void power (void) {
prg =0;
VRC24_power();
SetWriteHandler(0x8000, 0xFFFF, UNLCITYFIGHT_unscrambleAddress);
SetWriteHandler(0x8000, 0xFFFF, unscrambleAddress);
}
void UNLCITYFIGHT_Init (CartInfo *info) {
VRC24_init(info, sync, 0x04, 0x08, 1, 1, 0);
VRC24_ExternalSelect =UNLCITYFIGHT_externalSelect;
AddExState(UNLCITYFIGHT_stateRegs, ~0, 0, 0);
info->Power =UNLCITYFIGHT_power;
VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, NULL, NULL, externalSelect);
AddExState(stateRegs, ~0, 0, 0);
info->Power =power;
}

83
src/boards/273.c Normal file
View File

@@ -0,0 +1,83 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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 "asic_vrc2and4.h"
static uint8 irqEnabled;
static uint8 irqCounter;
static uint8 irqPrescaler;
static uint8 irqMask;
static SFORMAT stateRegs[] ={
{ &irqEnabled, 1, "IRQE" },
{ &irqCounter, 1, "CNTR" },
{ &irqPrescaler, 1, "IRQP" },
{ &irqMask, 1, "IRQM" },
{ 0 }
};
static void sync () {
VRC24_syncPRG(0x01F, 0x000);
VRC24_syncCHR(0x1FF, 0x000);
VRC24_syncMirror();
}
static DECLFW (writeIRQ) {
switch(A &8) {
case 0:
irqCounter = V;
X6502_IRQEnd(FCEU_IQEXT);
break;
case 8:
irqEnabled = V;
if (~irqEnabled &1) {
irqPrescaler = 0;
irqMask = 0x7F;
X6502_IRQEnd(FCEU_IQEXT);
}
break;
}
}
static void FP_FASTAPASS(1) cpuCycle (int a) {
while (a--) {
if (irqEnabled &1 && !(++irqPrescaler &irqMask)) {
irqMask = 0xFF;
if (!++irqCounter)
X6502_IRQBegin(FCEU_IQEXT);
else
X6502_IRQEnd(FCEU_IQEXT);
}
}
}
static void power (void) {
irqEnabled = irqCounter = irqPrescaler = irqMask = 0;
VRC24_power();
SetWriteHandler(0xF000, 0xFFFF, writeIRQ);
}
void Mapper273_Init (CartInfo *info) {
VRC2_init(info, sync, 0x04, 0x08, NULL, NULL, NULL, NULL);
AddExState(stateRegs, ~0, 0, 0);
info->Power = power;
MapIRQHook = cpuCycle;
}

View File

@@ -21,8 +21,9 @@
#include "mapinc.h"
static uint16 latchAddr;
static uint8 latchData;
static uint8 mode;
static uint8 latchData;
static uint8 mode;
static uint8 submapper;
static SFORMAT StateRegs[] = {
{ &latchAddr, 2 | FCEUSTATE_RLSB, "LATC" },
@@ -33,8 +34,14 @@ static SFORMAT StateRegs[] = {
static void Sync(void) {
if (mode &1) {
setprg16(0x8000, 0x20 | latchData &0x07);
setprg16(0xC000, 0x27);
if (submapper == 1) {
setprg16(0x8000, latchAddr >>2 &7 |0x20);
setprg16(0xC000, 0x27);
} else {
setprg16(0x8000, 0x20 | latchData &0x07);
setprg16(0xC000, 0x27);
}
setmirror(MI_V);
} else {
if (latchAddr &0x01)
setprg32(0x8000, latchAddr >>3 &0x0F);
@@ -43,10 +50,10 @@ static void Sync(void) {
setprg16(0xC000, latchAddr >>2 &0x1F);
}
if (~latchAddr &0x80) setprg16(0xC000, 0);
setmirror(latchAddr &0x02? MI_H: MI_V);
}
SetupCartCHRMapping(0, CHRptr[0], 0x2000, ~mode &0x01 && latchAddr &0x80? 0: 1);
setchr8(0);
setmirror(latchAddr &0x02? MI_H: MI_V);
}
static DECLFW(M280Write) {
@@ -76,6 +83,7 @@ static void StateRestore(int version) {
}
void Mapper280_Init(CartInfo *info) {
submapper = info->submapper;
info->Power = M280Power;
info->Reset = M280Reset;
GameStateRestore = StateRestore;

78
src/boards/285.c Normal file
View File

@@ -0,0 +1,78 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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 "asic_latch.h"
static uint8 pad;
static void sync_submapper0 () {
if (Latch_data &0x40)
setprg32(0x8000, Latch_data >>1);
else {
setprg16(0x8000, Latch_data);
setprg16(0xC000, Latch_data |7);
}
setchr8(0);
if (Latch_data &0x80)
setmirror(Latch_data &0x20? MI_1: MI_0);
else
setmirror(Latch_data &0x20? MI_H: MI_V);
}
static void sync_submapper1 () {
if (Latch_data &0x40)
setprg32(0x8000, Latch_data >>1 &0x03 | Latch_data >>2 &~0x03);
else {
setprg16(0x8000, Latch_data >>1 &~0x07 | Latch_data &0x07);
setprg16(0xC000, Latch_data >>1 | 0x07);
}
setchr8(0);
if (Latch_data &0x80)
setmirror(Latch_data &0x20? MI_1: MI_0);
else
setmirror(Latch_data &0x08? MI_H: MI_V);
}
static DECLFR (readPad) {
if (A &0x80) return pad >= 20? (4 | pad % 20): 0; else
if (A &0x40) return pad >= 16? (4 | pad % 16): 0; else
if (A &0x20) return pad >= 12? (4 | pad % 12): 0; else
if (A &0x10) return pad >= 8? (4 | pad % 8): 0; else
return pad >= 8? 0: pad &7;
}
static void power () {
pad = 0;
Latch_power();
SetReadHandler(0x5000, 0x5FFF, readPad);
}
static void reset () {
pad = ++pad %24;
Latch_clear();
}
void Mapper285_Init (CartInfo *info) {
Latch_init(info, info->submapper ==1? sync_submapper1: sync_submapper0, 0x8000, 0xFFFF, NULL);
info->Power = power;
info->Reset = reset;
AddExState(&pad, 1, 0, "DIPS");
}

View File

@@ -19,15 +19,14 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
static void sync () {
VRC24_syncWRAM(0);
VRC24_syncPRG(0x01F, 0x000);
VRC24_syncCHR(0x1FF, 0x000);
VRC24_syncMirror();
}
void UNLTF1201_Init (CartInfo *info) {
VRC24_init(info, sync, 0x02, 0x01, 1, 0, 8);
VRC4_init(info, sync, 0x02, 0x01, 0, NULL, NULL, NULL, NULL, NULL);
}

View File

@@ -19,13 +19,13 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
static uint8 irqEnabled;
static uint16 irqCounterLow;
static uint8 irqCounterHigh;
static SFORMAT UNLTH21311_stateRegs[] ={
static SFORMAT stateRegs[] ={
{ &irqEnabled, 1, "IRQE" },
{ &irqCounterLow, 2 | FCEUSTATE_RLSB, "CNTL" },
{ &irqCounterHigh, 1, "CNTH" },
@@ -38,7 +38,7 @@ static void sync () {
VRC24_syncMirror();
}
DECLFW(UNLTH21311_writeIRQ) {
static DECLFW (writeIRQ) {
switch(A &3) {
case 0: X6502_IRQEnd(FCEU_IQEXT);
irqEnabled =0;
@@ -51,22 +51,22 @@ DECLFW(UNLTH21311_writeIRQ) {
}
}
void FP_FASTAPASS(1) UNLTH21311_cpuCycle(int a) {
static void FP_FASTAPASS(1) cpuCycle (int a) {
while (a--) if (irqEnabled) {
if ((++irqCounterLow &4095) ==2048) irqCounterHigh--;
if (!irqCounterHigh && (irqCounterLow &4095) <2048) X6502_IRQBegin(FCEU_IQEXT);
}
}
void UNLTH21311_power(void) {
static void power (void) {
irqEnabled =irqCounterLow =irqCounterHigh =0;
VRC24_power();
SetWriteHandler(0xF000, 0xFFFF, UNLTH21311_writeIRQ);
SetWriteHandler(0xF000, 0xFFFF, writeIRQ);
}
void UNLTH21311_Init (CartInfo *info) {
VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0);
AddExState(UNLTH21311_stateRegs, ~0, 0, 0);
info->Power =UNLTH21311_power;
MapIRQHook =UNLTH21311_cpuCycle;
VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL);
AddExState(stateRegs, ~0, 0, 0);
info->Power =power;
MapIRQHook =cpuCycle;
}

57
src/boards/321.c Normal file
View File

@@ -0,0 +1,57 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc3.h"
static uint8 reg;
static void sync () {
if (reg &0x08)
setprg32(0x8000, reg &0x04 | reg >>4 &0x03);
else
MMC3_syncPRG(0x0F, reg <<2 &~0x0F);
MMC3_syncCHR(0x7F, reg <<5 &~0x7F);
MMC3_syncMirror();
}
static DECLFW (writeReg) {
reg = V;
sync();
}
static void power () {
reg = 0;
MMC3_power();
}
static void reset () {
reg = 0;
MMC3_clear();
}
void Mapper321_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
}

View File

@@ -19,322 +19,160 @@
*/
#include "mapinc.h"
#include "asic_mmc1.h"
#include "asic_mmc3.h"
#include "asic_vrc2and4.h"
static uint8 reg[4], dip;
static uint8 MMC1_reg[4], MMC1_shift, MMC1_count, MMC1_filter;
static uint8 MMC3_reg[8], MMC3_index, MMC3_mirroring, MMC3_wram, MMC3_reload, MMC3_count, MMC3_irq;
static uint8 VRC4_prg[2];
static uint8 VRC4_mirroring;
static uint8 VRC4_misc;
static uint16 VRC4_chr[8];
static uint8 VRCIRQ_latch;
static uint8 VRCIRQ_mode;
static uint8 VRCIRQ_count;
static signed short int VRCIRQ_cycles;
static uint8 *CHRRAM =NULL;
static uint8 *PRGCHR =NULL;
static uint8 *CHRRAM = NULL;
static uint8 *PRGCHR = NULL;
static int prgMask_CHRROM; /* PRG-ROM bank mask when CHR-ROM is active (outside of PRG address space */
static int prgMask_CHRRAM; /* PRG-ROM bank mask when CHR-RAM is active (CHR-ROM becomes part of PRG address space) */
static SFORMAT stateRegs[] = {
{ reg, 4, "REGS" },
{ &dip, 1, "DIPS" },
{ MMC1_reg, 4, "MMC1" },
{ &MMC1_shift, 1, "M1SH" },
{ &MMC1_count, 1, "M1CN" },
{ &MMC1_filter, 1, "M1FI" },
{ MMC3_reg, 1, "MMC3" },
{ &MMC3_index, 1, "M3IX" },
{ &MMC3_mirroring, 1, "M3MI" },
{ &MMC3_wram, 1, "M3WR" },
{ &MMC3_reload, 1, "M3RL" },
{ &MMC3_count, 1, "M3CN" },
{ &MMC3_irq, 1, "M3IQ" },
{ VRC4_prg, 2, "V4PR" },
{ &VRC4_mirroring, 1, "V4MI" },
{ &VRC4_misc, 1, "V4MS" },
{ VRC4_chr, 16, "V4CH" },
{ &VRCIRQ_latch, 1, "VILA" },
{ &VRCIRQ_mode, 1, "VIMO" },
{ &VRCIRQ_count, 1, "VICO" },
{ &VRCIRQ_cycles, 2, "VICY" },
{ reg, 4, "REGS" },
{ &dip, 1, "DIPS" },
{ 0 }
};
static void sync () {
int chrAND;
int chrOR;
int prgAND =reg[2] &0x04? 0x0F: 0x1F;
int prgOR =reg[1] >>1;
int chip =reg[2] &0x01 && CHRRAM? 0x10: 0x00;
int prgAND = reg[2] &0x10? 0x00: reg[2] &0x04? 0x0F: 0x1F; /* No inner bank in NROM mode, 128K or 256K for others */
int chrAND = reg[2] &0x40? 0x00: reg[2] &0x20? 0x7F: reg[2] &0x10? 0x1F: 0xFF; /* No inner bank in (C)NROM mode, 128K or 256K for others */
int prgOR = reg[1] >>1 &(reg[2] &0x01 && CHRRAM? prgMask_CHRRAM: prgMask_CHRROM) &~prgAND;
int chrOR = reg[0] <<1 &~chrAND;
if (reg[2] &0x10) { /* NROM mode */
if (reg[2] &0x08) { /* NROM-64 */
setprg8r(chip, 0x8000, prgOR);
setprg8r(chip, 0xA000, prgOR);
setprg8r(chip, 0xC000, prgOR);
setprg8r(chip, 0xE000, prgOR);
setprg8(0x8000, prgOR);
setprg8(0xA000, prgOR);
setprg8(0xC000, prgOR);
setprg8(0xE000, prgOR);
} else
if (reg[2] &0x04) { /* NROM-128 */
setprg16r(chip, 0x8000, prgOR >>1);
setprg16r(chip, 0xC000, prgOR >>1);
setprg16(0x8000, prgOR >>1);
setprg16(0xC000, prgOR >>1);
} else /* NROM-256 */
setprg32r(chip, 0x8000, prgOR >>2);
setprg32(0x8000, prgOR >>2);
} else
if (~reg[0] &0x02) { /* MMC3 mode */
setprg8r(chip, 0x8000 ^(MMC3_index <<8 &0x4000), MMC3_reg[6] &prgAND | prgOR &~prgAND);
setprg8r(chip, 0xA000, MMC3_reg[7] &prgAND | prgOR &~prgAND);
setprg8r(chip, 0xC000 ^(MMC3_index <<8 &0x4000), 0xFE &prgAND | prgOR &~prgAND);
setprg8r(chip, 0xE000, 0xFF &prgAND | prgOR &~prgAND);
} else
if (reg[0] &0x01) { /* VRC4 mode */
setprg8r(chip, 0x8000 ^(VRC4_misc <<13 &0x4000), VRC4_prg[0] &prgAND | prgOR &~prgAND);
setprg8r(chip, 0xA000, VRC4_prg[1] &prgAND | prgOR &~prgAND);
setprg8r(chip, 0xC000 ^(VRC4_misc <<13 &0x4000), 0xFE &prgAND | prgOR &~prgAND);
setprg8r(chip, 0xE000, 0xFF &prgAND | prgOR &~prgAND);
} else { /* MMC1 mode */
prgAND >>=1;
prgOR >>=1;
if (MMC1_reg[0] &0x8) { /* 16 KiB mode */
if (MMC1_reg[0] &0x04) { /* OR logic */
setprg16r(chip, 0x8000, MMC1_reg[3] &prgAND | prgOR &~prgAND);
setprg16r(chip, 0xC000, 0xFF &prgAND | prgOR &~prgAND);
} else { /* AND logic */
setprg16r(chip, 0x8000, 0x00 &prgAND | prgOR &~prgAND);
setprg16r(chip, 0xC000, MMC1_reg[3] &prgAND | prgOR &~prgAND);
}
} else
setprg32(0x8000, (MMC1_reg[3] &prgAND | prgOR &~prgAND) >>1);
}
chrAND =reg[2] &0x10 && ~reg[2] &0x20? 0x1F: reg[2] &0x20? 0x7F: 0xFF;
chrOR =reg[0] <<1;
if (reg[2] &0x01) /* CHR RAM mode */
if (~reg[0] &0x02)
MMC3_syncPRG(prgAND, prgOR);
else
if (reg[0] &0x01)
VRC24_syncPRG(prgAND, prgOR);
else
MMC1_syncPRG(prgAND >>1, prgOR >>1);
if (reg[2] &0x01 && CHRRAM)
setchr8r(0x10, 0);
else
if (reg[2] &0x40) /* CNROM mode */
if (reg[2] &0x40)
setchr8(chrOR >>3);
else
if (~reg[0] &0x02) { /* MMC3 mode */
setchr1(0x0000 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] &0xFE)&chrAND | chrOR &~chrAND);
setchr1(0x0400 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] |0x01)&chrAND | chrOR &~chrAND);
setchr1(0x0800 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] &0xFE)&chrAND | chrOR &~chrAND);
setchr1(0x0C00 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] |0x01)&chrAND | chrOR &~chrAND);
setchr1(0x1000 ^(MMC3_index <<5 &0x1000), MMC3_reg[2] &chrAND | chrOR &~chrAND);
setchr1(0x1400 ^(MMC3_index <<5 &0x1000), MMC3_reg[3] &chrAND | chrOR &~chrAND);
setchr1(0x1800 ^(MMC3_index <<5 &0x1000), MMC3_reg[4] &chrAND | chrOR &~chrAND);
setchr1(0x1C00 ^(MMC3_index <<5 &0x1000), MMC3_reg[5] &chrAND | chrOR &~chrAND);
} else
if (reg[0] &0x01) { /* VRC4 mode */
setchr1(0x0000, VRC4_chr[0] &chrAND | chrOR &~chrAND);
setchr1(0x0400, VRC4_chr[1] &chrAND | chrOR &~chrAND);
setchr1(0x0800, VRC4_chr[2] &chrAND | chrOR &~chrAND);
setchr1(0x0C00, VRC4_chr[3] &chrAND | chrOR &~chrAND);
setchr1(0x1000, VRC4_chr[4] &chrAND | chrOR &~chrAND);
setchr1(0x1400, VRC4_chr[5] &chrAND | chrOR &~chrAND);
setchr1(0x1800, VRC4_chr[6] &chrAND | chrOR &~chrAND);
setchr1(0x1C00, VRC4_chr[7] &chrAND | chrOR &~chrAND);
} else { /* MMC1 mode */
chrAND >>=2;
chrOR >>=2;
if (MMC1_reg[0] &0x10) { /* 4 KiB mode */
setchr4(0x0000, MMC1_reg[1] &chrAND | chrOR &~chrAND);
setchr4(0x1000, MMC1_reg[2] &chrAND | chrOR &~chrAND);
} else /* 8 KiB mode */
setchr8((MMC1_reg[1] &chrAND |chrOR &~chrAND) >>1);
}
if (~reg[0] &0x02) /* MMC3 mode */
setmirror(MMC3_mirroring &1 ^1);
if (~reg[0] &0x02)
MMC3_syncCHR(chrAND, chrOR);
else
if ( reg[0] &0x01) /* VRC4 mode */
setmirror(VRC4_mirroring &3 ^(VRC4_mirroring &2? 0: 1));
else /* MMC1 mode */
setmirror(MMC1_reg[0] &3 ^3);
if (reg[0] &0x01)
VRC24_syncCHR(chrAND, chrOR);
else
MMC1_syncCHR(chrAND >>2, chrOR >>2);
if (~reg[0] &0x02)
MMC3_syncMirror();
else
if (reg[0] &0x01)
VRC24_syncMirror();
else
MMC1_syncMirror();
}
static DECLFW(writeMMC3) {
switch(A &0xE001) {
case 0x8000: MMC3_index =V; sync(); break;
case 0x8001: MMC3_reg[MMC3_index &7] =V; sync(); break;
case 0xA000: MMC3_mirroring =V; sync(); break;
case 0xA001: MMC3_wram =V; sync(); break;
case 0xC000: MMC3_reload =V; break;
case 0xC001: MMC3_count =0; break;
case 0xE000: MMC3_irq =0; X6502_IRQEnd(FCEU_IQEXT); break;
case 0xE001: MMC3_irq =1; break;
}
DECLFW (VRC24_trapWriteReg) { /* When A11 is set, VRC4's A0 and A1 are swapped */
if (A &0x800) A = A &~0xF | A >>1 &0x5 | A <<1 &0xA;
VRC24_writeReg(A, V);
}
static DECLFW(writeMMC1) {
if (V &0x80) {
MMC1_shift =MMC1_count =0;
MMC1_reg[0] |=0x0C;
sync();
static void applyMode (uint8 clear) {
PPU_hook = NULL;
MapIRQHook = NULL;
GameHBIRQHook = NULL;
if (~reg[0] &0x02)
MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, NULL);
else
if (reg[0] &0x01) {
if (reg[2] &0x04)
VRC4_activate(clear, sync, 0x05, 0x0A, 1, NULL, NULL, NULL, NULL, NULL);
else
VRC4_activate(clear, sync, 0x02, 0x04, 1, NULL, NULL, NULL, NULL, NULL);
SetWriteHandler(0x8000, 0xFFFF, VRC24_trapWriteReg);
} else
if (!MMC1_filter) {
MMC1_shift |=(V &1) <<MMC1_count++;
if (MMC1_count ==5) {
MMC1_reg[A >>13 &3] =MMC1_shift;
MMC1_count =0;
MMC1_shift =0;
sync();
}
}
MMC1_filter =2;
MMC1_activate(clear, sync, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL);
}
static DECLFW(writeVRC4) {
uint8 index;
if (~reg[2] &4) A =A &0xF800 | A >>1 &0x3FF; /* A2,A1 -> A1,A0 if 5002.2=1 */
A |=A >>2 &3; /* A3,A2 -> A1,A0 */
if (A &0x800) A =A >>1 &1 | A <<1 &2 | A &~3; /* A8==1 => Swap A1,A0 */
switch (A &0xF000) {
case 0x8000: case 0xA000:
VRC4_prg[A >>13 &1] =V;
sync();
break;
case 0x9000:
if (~A &2)
VRC4_mirroring =V;
else
if (~A &1)
VRC4_misc =V;
sync();
break;
case 0xF000:
switch (A &3) {
case 0: VRCIRQ_latch =VRCIRQ_latch &0xF0 | V &0x0F; break;
case 1: VRCIRQ_latch =VRCIRQ_latch &0x0F | V <<4; break;
case 2: VRCIRQ_mode =V;
if (VRCIRQ_mode &0x02) {
VRCIRQ_count =VRCIRQ_latch;
VRCIRQ_cycles =341;
}
X6502_IRQEnd(FCEU_IQEXT);
break;
case 3: VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02;
X6502_IRQEnd(FCEU_IQEXT);
break;
}
break;
default:
index =(A -0xB000) >>11 &~1 | A >>1 &1;
if (A &1)
VRC4_chr[index] =VRC4_chr[index] & 0x0F | V <<4;
else
VRC4_chr[index] =VRC4_chr[index] &~0x0F | V &0x0F;
sync();
break;
}
}
static void FP_FASTAPASS(1) cpuCycle(int a) {
if ((reg[0] &3) ==3) while (a--) { /* VRC4 mode */
if (VRCIRQ_mode &0x02 && (VRCIRQ_mode &0x04 || (VRCIRQ_cycles -=3) <=0)) {
if (~VRCIRQ_mode &0x04) VRCIRQ_cycles +=341;
if (!++VRCIRQ_count) {
VRCIRQ_count =VRCIRQ_latch;
X6502_IRQBegin(FCEU_IQEXT);
}
}
}
if (MMC1_filter) MMC1_filter--;
}
static void horizontalBlanking(void) {
if (~reg[0] &2) { /* MMC3 mode */
MMC3_count =!MMC3_count? MMC3_reload: --MMC3_count;
if (!MMC3_count && MMC3_irq) X6502_IRQBegin(FCEU_IQEXT);
}
}
static void applyMode() {
switch (reg[0] &3) {
case 0:
case 1: SetWriteHandler(0x8000, 0xFFFF, writeMMC3); break;
case 2: SetWriteHandler(0x8000, 0xFFFF, writeMMC1); break;
case 3: SetWriteHandler(0x8000, 0xFFFF, writeVRC4); break;
}
}
static void Mapper351_restore (int version) {
applyMode();
static void restore (int version) {
applyMode(0);
sync();
}
static DECLFR(readDIP) {
static DECLFR (readDIP) {
return dip;
}
static DECLFW(writeReg) {
uint8 previousMode =reg[0] &3;
reg[A &3] =V;
if ((reg[0] &3) !=previousMode) applyMode();
sync();
static DECLFW (writeReg) {
reg[A &3] = V;
applyMode(A == 2);
}
static DECLFW(writeFDSMirroring) {
MMC3_mirroring =V >>3 &1;
sync();
static DECLFW (writeFDSMirroring) {
MMC3_writeReg(0xA000, V >>3 &1);
}
static void Mapper351_power(void) {
int i;
for (i =0; i <4; i++) reg[i] =0;
for (i =0; i <4; i++) MMC1_reg[i] =0;
for (i =0; i <8; i++) MMC3_reg[i] =0;
for (i =0; i <2; i++) VRC4_prg[i] =0;
for (i =0; i <8; i++) VRC4_chr[i] =0;
MMC1_shift =MMC1_count =MMC1_filter =0;
MMC1_reg[0] =0x0C;
MMC3_index =MMC3_mirroring =MMC3_wram =MMC3_reload =MMC3_count =MMC3_irq =0;
VRC4_mirroring =VRC4_misc =VRCIRQ_latch =VRCIRQ_mode =VRCIRQ_count =VRCIRQ_cycles =0;
dip =0;
SetReadHandler(0x6000, 0xFFFF, CartBR);
static void power (void) {
reg[0] = reg[1] = reg[2] = reg[3] = 0;
dip = 0;
SetReadHandler(0x5000, 0x5FFF, readDIP);
SetReadHandler(0x6000, 0xFFFF, CartBR);
SetWriteHandler(0x5000, 0x5FFF, writeReg);
SetWriteHandler(0x4025, 0x4025, writeFDSMirroring);
applyMode();
sync();
applyMode(1);
}
static void Mapper351_reset (void) {
int i;
for (i =0; i <4; i++) reg[i] =0;
static void reset (void) {
reg[0] = reg[1] = reg[2] = reg[3] = 0;
dip++;
applyMode();
sync();
applyMode(1);
}
static void Mapper351_close(void) {
static void close (void) {
if (CHRRAM) FCEU_gfree(CHRRAM);
if (PRGCHR) FCEU_gfree(PRGCHR);
CHRRAM =NULL;
PRGCHR =NULL;
CHRRAM = NULL;
PRGCHR = NULL;
}
void Mapper351_Init (CartInfo *info) {
int CHRRAMSIZE =info->CHRRamSize + info->CHRRamSaveSize;
info->Reset = Mapper351_reset;
info->Power = Mapper351_power;
info->Close = Mapper351_close;
MapIRQHook = cpuCycle;
GameHBIRQHook = horizontalBlanking;
GameStateRestore = Mapper351_restore;
int CHRRAMSIZE = info->CHRRamSize + info->CHRRamSaveSize;
MMC1_addExState();
MMC3_addExState();
VRC24_addExState();
info->Reset = reset;
info->Power = power;
info->Close = close;
GameStateRestore = restore;
AddExState(stateRegs, ~0, 0, 0);
/* When CHR-RAM is enabled, CHR-ROM becomes part of PRG-ROM address space. */
prgMask_CHRROM = prgMask_CHRRAM = PRGsize[0] /8192 -1;
if (CHRRAMSIZE) {
CHRRAM =(uint8 *)FCEU_gmalloc(CHRRAMSIZE);
uint8* newROM;
CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE);
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1);
AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM");
/* This crazy thing can map CHR-ROM into CPU address space. Allocate a combined PRG+CHR address space and treat it a second "chip". */
PRGCHR =(uint8 *)FCEU_gmalloc(PRGsize[0] +CHRsize[0]);
memcpy(PRGCHR, PRGptr[0], PRGsize[0]);
memcpy(PRGCHR +PRGsize[0], CHRptr[0], CHRsize[0]);
SetupCartPRGMapping(0x10, PRGCHR, PRGsize[0] +CHRsize[0], 0);
prgMask_CHRRAM = (PRGsize[0] +CHRsize[0]) /8192 -1;
newROM = (uint8*)FCEU_gmalloc(PRGsize[0] +CHRsize[0]);
memcpy(newROM, ROM, info->PRGRomSize);
memcpy(newROM +PRGsize[0], VROM, info->CHRRomSize);
FCEU_gfree(ROM);
ROM = newROM;
SetupCartPRGMapping(0, ROM, PRGsize[0] +CHRsize[0], 0);
}
}

50
src/boards/352.c Normal file
View File

@@ -0,0 +1,50 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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"
static uint8 game;
static void sync () {
setprg32(0x8000, game);
setchr8(game);
}
static void power() {
SetReadHandler(0x6000, 0xFFFF, CartBR);
game = 0;
sync();
}
static void reset() {
if (++game >= ROM_size /2) game = 0;
sync();
}
static void stateRestore(int version) {
sync();
}
void Mapper352_Init (CartInfo *info) {
info->Power = power;
info->Reset = reset;
GameStateRestore = stateRestore;
AddExState(&game, 1, 0, "GAME");
}

View File

@@ -3,10 +3,10 @@
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 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
@@ -15,90 +15,44 @@
*
* 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 356 - J.Y. Company's 7-in-1 Rockman (JY-208)
* All registers work as INES Mapper 045, except $6000 sequential register 2 (third write):
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*
*/
#include "mapinc.h"
#include "mmc3.h"
#include "asic_tc3294.h"
static uint8* CHRRAM = NULL;
static uint32 CHRRAMSIZE = 0;
static uint8 *CHRRAM = NULL;
static uint32 CHRRAMSize;
static void M356CW(uint32 A, uint8 V) {
if (EXPREGS[2] & 0x20) {
uint8 NV = V;
if (EXPREGS[2] & 8)
NV &= (1 << ((EXPREGS[2] & 7) + 1)) - 1;
else
if (EXPREGS[2])
NV &= 0; /* hack ;( don't know exactly how it should be */
NV |= EXPREGS[0] | ((EXPREGS[2] & 0xF0) << 4);
setchr1(A, NV);
} else
setchr8r(0x10, 0);
}
static void M356PW(uint32 A, uint8 V) {
uint8 MV = V & ((EXPREGS[3] & 0x3F) ^ 0x3F);
MV |= EXPREGS[1];
if (UNIFchrrama)
MV |= ((EXPREGS[2] & 0x40) << 2);
setprg8(A, MV);
}
static void M356MW(uint8 V) {
if (EXPREGS[2] & 0x40)
SetupCartMirroring(4, 1, CHRRAM);
static void sync () {
TC3294_syncPRG(0xFF, 0x00);
if (TC3294_reg[2] &0x20)
TC3294_syncCHR(0x1FF, 0x00);
else
setmirror((V & 1) ^ 1);
setchr8r(0x10, 0);
if (TC3294_reg[2] &0x40) {
setntamem(CHRptr[0x10] +0x0000, 1, 0);
setntamem(CHRptr[0x10] +0x0400, 1, 1);
setntamem(CHRptr[0x10] +0x0800, 1, 2);
setntamem(CHRptr[0x10] +0x0C00, 1, 3);
} else
TC3294_syncMirror();
}
static DECLFW(M356Write) {
if (!(EXPREGS[3] & 0x40)) {
EXPREGS[EXPREGS[4]] = V;
EXPREGS[4] = (EXPREGS[4] + 1) & 3;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
static void close (void) {
if (CHRRAM) {
FCEU_gfree(CHRRAM);
CHRRAM =NULL;
}
}
static void M356Close(void) {
GenMMC3Close();
if (CHRRAM)
FCEU_free(CHRRAM);
CHRRAM = NULL;
}
static void M356Reset(void) {
EXPREGS[0] = EXPREGS[1] = EXPREGS[3] = EXPREGS[4] = 0;
EXPREGS[2] = 0x0F;
MMC3RegReset();
}
static void M356Power(void) {
EXPREGS[4] = 0;
EXPREGS[0] = EXPREGS[1] = EXPREGS[3] = EXPREGS[4] = 0;
EXPREGS[2] = 0x0F;
GenMMC3Power();
SetWriteHandler(0x6000, 0x7FFF, M356Write);
}
void Mapper356_Init(CartInfo* info) {
GenMMC3_Init(info, 128, 128, 0, 0);
cwrap = M356CW;
pwrap = M356PW;
mwrap = M356MW;
info->Reset = M356Reset;
info->Power = M356Power;
info->Close = M356Close;
AddExState(EXPREGS, 5, 0, "EXPR");
CHRRAMSIZE = 8192;
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE);
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1);
AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR");
void Mapper356_Init (CartInfo *info) {
TC3294_init(info, sync);
info->Close = close;
CHRRAMSize = 8192;
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize);
AddExState(CHRRAM, CHRRAMSize, 0, "CRAM");
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
}

54
src/boards/361.c Normal file
View File

@@ -0,0 +1,54 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc3.h"
static uint8 reg;
static void sync () {
MMC3_syncPRG(0x0F, reg &~0x0F);
MMC3_syncCHR(0x7F, reg <<3 &~0x7F);
MMC3_syncMirror();
}
static DECLFW (writeReg) {
reg = V;
sync();
}
static void reset () {
reg = 0;
MMC3_clear();
}
static void power () {
reg = 0;
MMC3_power();
}
void Mapper361_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
}

View File

@@ -19,11 +19,11 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
static uint8 game;
static SFORMAT Mapper362_stateRegs[] ={
static SFORMAT stateRegs[] ={
{ &game, 1, "GAME" },
{ 0 }
};
@@ -34,27 +34,27 @@ static void sync () {
VRC24_syncCHR(0x1FF, 0x200);
VRC24_syncMirror();
} else {
VRC24_syncPRG(0x00F, VRC24_chr[0] >>3 &0x30);
VRC24_syncCHR(0x07F, VRC24_chr[0] &0x180);
VRC24_syncPRG(0x00F, VRC24_getCHRBank(0) >>3 &0x30);
VRC24_syncCHR(0x07F, VRC24_getCHRBank(0) &0x180);
VRC24_syncMirror();
}
}
void Mapper362_power(void) {
static void power (void) {
game =0;
VRC24_power();
}
void Mapper362_reset(void) {
static void reset (void) {
game ^=1;
VRC24_Sync();
VRC24_clear();
}
void Mapper362_Init (CartInfo *info) {
VRC24_init(info, sync, 0x01, 0x02, 1, 0, 0);
info->Power =Mapper362_power;
VRC4_init(info, sync, 0x01, 0x02, 0, NULL, NULL, NULL, NULL, NULL);
info->Power = power;
if (PRGsize[0] >512*1024) {
info->Reset =Mapper362_reset;
AddExState(Mapper362_stateRegs, ~0, 0, 0);
info->Reset = reset;
AddExState(stateRegs, ~0, 0, 0);
}
}

39
src/boards/363.c Normal file
View File

@@ -0,0 +1,39 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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 "asic_latch.h"
static void sync () {
setprg16(0x8000, Latch_address <<3 | Latch_data &0x07);
setprg16(0xC000, Latch_address <<3 | 0x07);
setchr8(0);
setmirror(Latch_address &0x20? MI_H: MI_V);
}
static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) {
if (!(~Latch_address &0x10 && *newAddress &0x10)) *newAddress = Latch_address; /* Address bits only latched on a rising edge of A4 */
*newValue &= romValue; /* AND-type bus conflicts */
}
void Mapper363_Init (CartInfo *info) {
Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite);
info->Reset = Latch_clear;
}

59
src/boards/366.c Normal file
View File

@@ -0,0 +1,59 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc3.h"
#include "cartram.h"
static uint8 reg;
static void sync () {
MMC3_syncWRAM(0);
MMC3_syncPRG(0x0F, reg &~0x0F);
MMC3_syncCHR(0x7F, reg <<3 &~0x7F);
MMC3_syncMirror();
}
static DECLFW (writeReg) {
if (~reg &0x80) {
reg = A &0xFF;
sync();
}
}
static void reset () {
reg = 0;
MMC3_clear();
}
static void power () {
reg = 0;
MMC3_power();
}
void Mapper366_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg);
WRAM_init(info, 8);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
}

39
src/boards/378.c Normal file
View File

@@ -0,0 +1,39 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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 "asic_latch.h"
static void sync () {
if (Latch_data &0x20) {
setprg16(0x8000, 0x10 | Latch_data <<1 &0x0E | Latch_data >>3 &0x01);
setprg16(0xC000, 0x10 | Latch_data <<1 &0x0E | 0x07);
setmirror(Latch_data &0x04? MI_H: MI_V);
} else {
setprg32(0x8000, Latch_data &0x07);
setmirror(Latch_data &0x10? MI_1: MI_0);
}
setchr8(0);
}
void Mapper378_Init (CartInfo *info) {
Latch_init(info, sync, 0x8000, 0xFFFF, NULL);
info->Reset = Latch_clear;
}

32
src/boards/379.c Normal file
View File

@@ -0,0 +1,32 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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 "asic_latch.h"
static void sync () {
setprg32(0x8000, Latch_data &0x03);
setchr8(Latch_data >>2);
}
void Mapper379_Init (CartInfo *info) {
Latch_init(info, sync, 0x8000, 0xFFFF, NULL);
info->Reset = Latch_clear;
}

View File

@@ -57,7 +57,7 @@ static void Sync(void)
static DECLFR(M380Read)
{
if (latche & 0x100 && !isKN35A)
return CartBR(A | dipswitch);
return CartBR(A &~0x0F | dipswitch);
return CartBR(A);
}

View File

@@ -19,11 +19,12 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
#include "cartram.h"
static uint8 reg;
static SFORMAT Mapper384_stateRegs[] ={
static SFORMAT stateRegs[] ={
{ &reg, 1, "EXP0" },
{ 0 }
};
@@ -35,28 +36,28 @@ static void sync () {
VRC24_syncWRAM(0);
}
DECLFW(Mapper384_writeReg) {
static DECLFW (writeReg) {
if (A &0x800 && ~reg &0x08) {
reg =V;
VRC24_Sync();
sync();
}
CartBW(A, V);
}
void Mapper384_power(void) {
static void power (void) {
reg =0;
VRC24_power();
}
void Mapper384_reset(void) {
static void reset (void) {
reg =0;
VRC24_Sync();
}
VRC24_clear();
}
void Mapper384_Init (CartInfo *info) {
VRC24_init(info, sync, 0x04, 0x08, 1, 0, 2);
VRC24_WRAMWrite =Mapper384_writeReg;
info->Power =Mapper384_power;
info->Reset =Mapper384_reset;
AddExState(Mapper384_stateRegs, ~0, 0, 0);
VRC4_init(info, sync, 0x04, 0x08, 0, NULL, NULL, NULL, writeReg, NULL);
WRAM_init(info, 2);
info->Power =power;
info->Reset =reset;
AddExState(stateRegs, ~0, 0, 0);
}

View File

@@ -1,7 +1,7 @@
/* FCEUmm - NES/Famicom Emulator
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2022
* Copyright (C) 2025 NewRisingSun
*
* 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
@@ -16,58 +16,56 @@
* 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 396 - BMC-830752C
* 1995 Super 8-in-1 (JY-050 rev0)
* Super 8-in-1 Gold Card Series (JY-085)
* Super 8-in-1 Gold Card Series (JY-086)
* 2-in-1 (GN-51)
*/
#include "mapinc.h"
static uint8 submapper;
static uint8 reg[2];
static void Sync (void) {
setprg16(0x8000, reg[1] << 3 | reg[0] & 7);
setprg16(0xC000, reg[1] << 3 | 7);
static void sync () {
setprg16(0x8000, reg[0] <<3 | reg[1] &0x07);
setprg16(0xC000, reg[0] <<3 | 0x07);
setchr8(0);
setmirror(reg[1] & 0x60 ? 0 : 1);
switch(submapper) {
case 1: /* J.Y. YY850437C */
setmirror(reg[0] &0x40? MI_H: MI_V);
break;
case 2: /* Realtec GN-51 */
case 3: /* Realtec 8030 */
setmirror(reg[0] &0x20? MI_H: MI_V);
break;
default:
setmirror(reg[0] &0x60? MI_H: MI_V);
break;
}
}
static DECLFW(M396WriteInnerBank) {
reg[0] = V;
Sync();
static DECLFW (writeReg) {
reg[(A &0xE000) == 0xA000? 0: 1] = V;
sync();
}
static DECLFW(M396WriteOuterBank) {
reg[1] = V;
Sync();
static DECLFW (writeReg_submapper3) {
reg[A >>14 &1] = V;
sync();
}
static void M396Reset(void) {
reg[0] = 0x00;
reg[1] = 0x00;
Sync();
static void power () {
SetReadHandler(0x6000, 0xFFFF, CartBR);
SetWriteHandler(0x8000, 0xFFFF, submapper == 3? writeReg_submapper3: writeReg);
reg[0] = reg[1] = 0;
sync();
}
static void StateRestore(int version) {
Sync();
static void stateRestore (int version) {
sync();
}
static void M396Power(void) {
reg[0] = 0x00;
reg[1] = 0x00;
Sync();
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x8000, 0x9FFF, M396WriteInnerBank);
SetWriteHandler(0xA000, 0xBFFF, M396WriteOuterBank);
SetWriteHandler(0xC000, 0xFFFF, M396WriteInnerBank);
}
void Mapper396_Init(CartInfo *info) {
info->Power = M396Power;
info->Reset = M396Reset;
GameStateRestore = StateRestore;
void Mapper396_Init (CartInfo *info) {
submapper = info->submapper;
info->Power = power;
info->Reset = submapper == 3? sync: power;
GameStateRestore = stateRestore;
AddExState(reg, 2, 0, "REGS");
}

View File

@@ -19,19 +19,19 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
static uint8 reg;
static SFORMAT Mapper398_stateRegs[] ={
static SFORMAT stateRegs[] ={
{ &reg, 1, "EXP0" },
{ 0 }
};
static void sync () {
if (reg &0x80) {
setprg32(0x8000, reg >>5 &6 | VRC24_chr[0] >>2 &1);
setchr8(0x40 | reg >>3 &8 | VRC24_chr[0] &7);
setprg32(0x8000, reg >>5 &6 | VRC24_getCHRBank(0) >>2 &1);
setchr8(0x40 | reg >>3 &8 | VRC24_getCHRBank(0) &7);
} else {
VRC24_syncPRG(0x0F, 0x00);
VRC24_syncCHR(0x1FF, 0x000);
@@ -39,26 +39,25 @@ static void sync () {
VRC24_syncMirror();
}
DECLFW(Mapper398_writeReg) {
static DECLFW (writeReg) {
reg =A &0xFF;
VRC24_Sync();
VRC24_writeReg(A, V);
}
void Mapper398_power(void) {
reg =0xC0;
static void power (void) {
reg = 0xC0;
VRC24_power();
SetWriteHandler(0x8000, 0xFFFF, Mapper398_writeReg);
SetWriteHandler(0x8000, 0xFFFF, writeReg);
}
void Mapper398_reset(void) {
reg =0xC0;
VRC24_Sync();
static void reset (void) {
reg = 0xC0;
VRC24_clear();
}
void Mapper398_Init (CartInfo *info) {
VRC24_init(info, sync, 0x01, 0x02, 1, 1, 0);
info->Power =Mapper398_power;
info->Reset =Mapper398_reset;
AddExState(Mapper398_stateRegs, ~0, 0, 0);
VRC4_init(info, sync, 0x01, 0x02, 1, NULL, NULL, NULL, NULL, NULL);
info->Power = power;
info->Reset = reset;
AddExState(stateRegs, ~0, 0, 0);
}

58
src/boards/400.c Normal file
View File

@@ -0,0 +1,58 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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 "asic_latch.h"
static uint8 reg[4];
static void sync () {
setprg16(0x8000, reg[2] &~0x07 | Latch_data &0x07);
setprg16(0xC000, reg[3] &~0x07 | 0x07);
setchr8(Latch_data >>5);
setmirror(reg[3] &0x20? MI_H: MI_V);
}
static DECLFW (writeReg) {
if (!(A &0x7FF)) { /* Exclude 8 Bit Xmas 2008's writes to second APU (also at 7001-7015) */
reg[A >>11 &3] = V;
sync();
}
}
static void power () {
reg[0] = reg[1] = reg[2] = 0;
reg[3] = 0x80;
Latch_power();
SetWriteHandler(0x6000, 0x7FFF, writeReg);
}
static void reset () {
reg[0] = reg[1] = reg[2] = 0;
reg[3] = 0x80;
Latch_clear();
}
void Mapper400_Init (CartInfo *info) {
Latch_init(info, sync, 0xC000, 0xFFFF, NULL);
info->Power = power;
info->Reset = reset;
AddExState(reg, 4, 0, "REGS");
}

34
src/boards/418.c Normal file
View File

@@ -0,0 +1,34 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_n118.h"
static void sync () {
N118_syncPRG(0x0F, 0x00);
setchr8(0);
setmirror(N118_getCHRBank(7) &0x01? MI_H: MI_V);
}
void Mapper418_Init (CartInfo *info) {
N118_init(info, sync, NULL, NULL);
}

View File

@@ -21,56 +21,67 @@
*/
#include "mapinc.h"
#include "mmc3.h"
#include "asic_mmc3.h"
static uint8 submapper;
static uint8 reg[2];
static uint8 pad;
static void M432CW(uint32 A, uint8 V) {
int chrAND = (EXPREGS[1] & 0x04) ? 0x7F : 0xFF;
int chrOR = (EXPREGS[1] << 7) & 0x080 | (EXPREGS[1] << 5) & 0x100 | (EXPREGS[1] << 4) & 0x200;
setchr1(A, (V & chrAND) | (chrOR & ~chrAND));
static DECLFR (readPad) {
return pad;
}
static void M432PW(uint32 A, uint8 V) {
int prgAND = (EXPREGS[1] & 0x02) ? 0x0F : 0x1F;
int prgOR = ((EXPREGS[1] << 4) & 0x10) | (EXPREGS[1] << 1) & 0x60;
if ((A < 0xC000) || (~EXPREGS[1] & 0x40)) setprg8(A, (V & prgAND) | (prgOR & ~prgAND) & (EXPREGS[1] &(submapper ==2? 0x20: 0x80)?~2:~0));
if ((A < 0xC000) && (EXPREGS[1] & 0x40)) setprg8(A | 0x4000, (V & prgAND) | (prgOR & ~prgAND) | (EXPREGS[1] &(submapper ==2? 0x20: 0x80)? 2: 0));
static void sync () {
int prgAND = reg[1] &0x02? 0x0F: 0x1F;
int chrAND = reg[1] &0x20 && submapper == 3? 0x1FF: reg[1] &0x04? 0x7F: 0xFF;
int prgOR = reg[1] <<4 &0x10 | reg[1] <<1 &0x60;
int chrOR = reg[1] <<7 &0x80 | reg[1] <<5 &0x100 | reg[1] <<4 &0x200;
MMC3_syncPRG(prgAND, prgOR &~prgAND);
MMC3_syncCHR(chrAND, chrOR &~chrAND);
MMC3_syncMirror();
SetReadHandler(0x8000, 0xFFFF, submapper == 1 && reg[1] &0x20 || submapper != 1 && reg[0] &0x01? readPad: CartBR);
}
static DECLFR(M432Read) {
if (submapper ==1? !!(EXPREGS[1] &0x20): !!(EXPREGS[0] &0x01)) return EXPREGS[2];
return CartBR(A);
static int getPRGBank (uint8 bank) {
if (reg[1] &0x40) {
int mask = reg[1] &(submapper == 2? 0x20: 0x80)? 3: 1;
return MMC3_getPRGBank(bank &1) &~mask | bank &mask;
} else
return MMC3_getPRGBank(bank);
}
static DECLFW(M432Write) {
EXPREGS[A & 1] = V;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
static int getCHRBank (uint8 bank) {
if (reg[1] &0x20 && submapper == 3)
return MMC3_getCHRBank(bank &6 | bank >>1 &1) <<1 | bank &1;
else
return MMC3_getCHRBank(bank);
}
static void M432Reset(void) {
EXPREGS[0] = 0;
EXPREGS[1] = 0;
EXPREGS[2]++;
MMC3RegReset();
static DECLFW (writeReg) {
if (submapper == 3 && reg[1] &0x80)
;
else {
reg[A &1] = V;
sync();
}
}
static void M432Power(void) {
EXPREGS[0] = 0;
EXPREGS[1] = 0;
EXPREGS[2] = 0;
GenMMC3Power();
SetReadHandler(0x8000, 0xFFFF, M432Read);
SetWriteHandler(0x6000, 0x7FFF, M432Write);
static void reset () {
reg[0] = reg[1] = 0;
++pad;
MMC3_clear();
}
void Mapper432_Init(CartInfo *info) {
static void power () {
reg[0] = reg[1] = 0;
pad = 0;
MMC3_power();
}
void Mapper432_Init (CartInfo *info) {
submapper =info->submapper;
GenMMC3_Init(info, 256, 256, 0, 0);
cwrap = M432CW;
pwrap = M432PW;
info->Power = M432Power;
info->Reset = M432Reset;
AddExState(EXPREGS, 3, 0, "EXPR");
MMC3_init(info, sync, MMC3_TYPE_AX5202P, getPRGBank, getCHRBank, NULL, writeReg);
info->Power = power;
info->Reset = reset;
AddExState(reg, 2, 0, "EXPR");
}

View File

@@ -19,242 +19,100 @@
*/
#include "mapinc.h"
#include "asic_latch.h"
#include "asic_mmc3.h"
#include "asic_vrc2and4.h"
static uint8 reg[5], dip; /* Fourth register is the CNROM latch */
static uint8 MMC3_reg[8], MMC3_index, MMC3_mirroring, MMC3_wram, MMC3_reload, MMC3_count, MMC3_irq;
static uint8 VRC4_prg[2];
static uint8 VRC4_mirroring;
static uint8 VRC4_misc;
static uint16 VRC4_chr[8];
static uint8 VRCIRQ_latch;
static uint8 VRCIRQ_mode;
static uint8 VRCIRQ_count;
static signed short int VRCIRQ_cycles;
static uint8 *PRGCHR =NULL;
static uint8 reg[4];
static uint8 dip;
static SFORMAT stateRegs[] = {
{ reg, 5, "REGS" },
{ &dip, 1, "DIPS" },
{ MMC3_reg, 1, "MMC3" },
{ &MMC3_index, 1, "M3IX" },
{ &MMC3_mirroring, 1, "M3MI" },
{ &MMC3_wram, 1, "M3WR" },
{ &MMC3_reload, 1, "M3RL" },
{ &MMC3_count, 1, "M3CN" },
{ &MMC3_irq, 1, "M3IQ" },
{ VRC4_prg, 2, "V4PR" },
{ &VRC4_mirroring, 1, "V4MI" },
{ &VRC4_misc, 1, "V4MS" },
{ VRC4_chr, 16, "V4CH" },
{ &VRCIRQ_latch, 1, "VILA" },
{ &VRCIRQ_mode, 1, "VIMO" },
{ &VRCIRQ_count, 1, "VICO" },
{ &VRCIRQ_cycles, 2, "VICY" },
{ reg, 4, "REGS" },
{ &dip, 1, "DIPS" },
{ 0 }
};
static void sync () {
int chrAND;
int chrOR;
/*/ 5003.0-2: PRG size (1 MiB->8 KiB, although 1 MiB and 512 KiB are not connected and so function as 256 KiB) and mode (>=64 KiB: MMC3, <64 KiB: NROM-256/128/64) */
int prgAND =0x7F >>(reg[2] &7) &0x1F;
int prgAND = 0x7F >>(reg[2] &7) &0x1F; /* 5003.0-2: PRG size (1 MiB->8 KiB, although 1 MiB and 512 KiB are not connected and so function as 256 KiB) and mode (>=64 KiB: MMC3, <64 KiB: NROM-256/128/64) */
int chrAND = 0x3FF >>(reg[2] >>3 &7) &0xFF; /* 5003.3-5: CHR size (1 MiB->8 KiB, though 1 MiB and 512 KiB are not reachable with inner bank registers and so function as 256 KiB) and mode (>=64 KiB: MMC3, <64 KiB: (C)NROM-256/128/64) */
int prgOR = reg[0] &~prgAND;
int chrOR = reg[1] <<3 &~chrAND;
if (prgAND &0x04) {
if (reg[3] &0x10) {
setprg8(0x8000 ^(VRC4_misc <<13 &0x4000), VRC4_prg[0] &prgAND | reg[0] &~prgAND);
setprg8(0xA000, VRC4_prg[1] &prgAND | reg[0] &~prgAND);
setprg8(0xC000 ^(VRC4_misc <<13 &0x4000), 0xFE &prgAND | reg[0] &~prgAND);
setprg8(0xE000, 0xFF &prgAND | reg[0] &~prgAND);
} else {
setprg8(0x8000 ^(MMC3_index <<8 &0x4000), MMC3_reg[6] &prgAND | reg[0] &~prgAND);
setprg8(0xA000, MMC3_reg[7] &prgAND | reg[0] &~prgAND);
setprg8(0xC000 ^(MMC3_index <<8 &0x4000), 0xFE &prgAND | reg[0] &~prgAND);
setprg8(0xE000, 0xFF &prgAND | reg[0] &~prgAND);
}
if (reg[3] &0x10)
VRC24_syncPRG(prgAND, prgOR);
else
MMC3_syncPRG(prgAND, prgOR);
} else {
setprg8(0x8000, 0 &prgAND | reg[0] &~prgAND);
setprg8(0xA000, 1 &prgAND | reg[0] &~prgAND);
setprg8(0xC000, 2 &prgAND | reg[0] &~prgAND);
setprg8(0xE000, 3 &prgAND | reg[0] &~prgAND);
setprg8(0x8000, 0 &prgAND | prgOR);
setprg8(0xA000, 1 &prgAND | prgOR);
setprg8(0xC000, 2 &prgAND | prgOR);
setprg8(0xE000, 3 &prgAND | prgOR);
}
/* // 5003.3-5: CHR size (1 MiB->8 KiB, though 1 MiB and 512 KiB are not reachable with inner bank registers and so function as 256 KiB) and mode (>=64 KiB: MMC3, <64 KiB: (C)NROM-256/128/64) */
chrAND =0x3FF >>(reg[2] >>3 &7) &0xFF;
if (chrAND &0x20) {
if (reg[3] &0x10) {
setchr1(0x0000, VRC4_chr[0] &chrAND | (reg[1] <<3) &~chrAND);
setchr1(0x0400, VRC4_chr[1] &chrAND | (reg[1] <<3) &~chrAND);
setchr1(0x0800, VRC4_chr[2] &chrAND | (reg[1] <<3) &~chrAND);
setchr1(0x0C00, VRC4_chr[3] &chrAND | (reg[1] <<3) &~chrAND);
setchr1(0x1000, VRC4_chr[4] &chrAND | (reg[1] <<3) &~chrAND);
setchr1(0x1400, VRC4_chr[5] &chrAND | (reg[1] <<3) &~chrAND);
setchr1(0x1800, VRC4_chr[6] &chrAND | (reg[1] <<3) &~chrAND);
setchr1(0x1C00, VRC4_chr[7] &chrAND | (reg[1] <<3) &~chrAND);
} else {
setchr1(0x0000 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] &0xFE)&chrAND | (reg[1] <<3) &~chrAND);
setchr1(0x0400 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] |0x01)&chrAND | (reg[1] <<3) &~chrAND);
setchr1(0x0800 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] &0xFE)&chrAND | (reg[1] <<3) &~chrAND);
setchr1(0x0C00 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] |0x01)&chrAND | (reg[1] <<3) &~chrAND);
setchr1(0x1000 ^(MMC3_index <<5 &0x1000), MMC3_reg[2] &chrAND | (reg[1] <<3) &~chrAND);
setchr1(0x1400 ^(MMC3_index <<5 &0x1000), MMC3_reg[3] &chrAND | (reg[1] <<3) &~chrAND);
setchr1(0x1800 ^(MMC3_index <<5 &0x1000), MMC3_reg[4] &chrAND | (reg[1] <<3) &~chrAND);
setchr1(0x1C00 ^(MMC3_index <<5 &0x1000), MMC3_reg[5] &chrAND | (reg[1] <<3) &~chrAND);
}
if (reg[3] &0x10)
VRC24_syncCHR(chrAND, chrOR);
else
MMC3_syncCHR(chrAND, chrOR);
} else {
chrAND >>=3;
setchr8(reg[4] &chrAND | reg[1] &~chrAND);
chrAND >>= 3;
chrOR >>= 3;
setchr8(Latch_data &chrAND | chrOR);
}
if (reg[3] &0x10)
setmirror(VRC4_mirroring &3 ^(VRC4_mirroring &2? 0: 1));
VRC24_syncMirror();
else
setmirror(MMC3_mirroring &1 ^1);
SetReadHandler(0x8000, 0xFFFF, reg[0] &0xC0 && (reg[0] &0xC0) ==dip? NULL: CartBR);
MMC3_syncMirror();
SetReadHandler(0x8000, 0xFFFF, reg[0] &0xC0 && (reg[0] &0xC0) == dip? NULL: CartBR);
}
static DECLFW(writeCNROM) {
reg[4] =V;
sync();
}
static DECLFW(writeMMC3) {
switch(A &0xE001) {
case 0x8000: MMC3_index =V; sync(); break;
case 0x8001: MMC3_reg[MMC3_index &7] =V; sync(); break;
case 0xA000: MMC3_mirroring =V; sync(); break;
case 0xA001: MMC3_wram =V; sync(); break;
case 0xC000: MMC3_reload =V; break;
case 0xC001: MMC3_count =0; break;
case 0xE000: MMC3_irq =0; X6502_IRQEnd(FCEU_IQEXT); break;
case 0xE001: MMC3_irq =1; break;
}
}
static DECLFW(writeVRC4) {
uint8 index;
if (reg[3] &1)
A =(A &0xA? 1: 0) | (A &0x5? 2: 0) | A &0xF000;
static void applyMode (uint8 clear) {
if ((reg[2] >>3 &7) >= 5)
Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL);
else
A =(A &0x5? 1: 0) | (A &0xA? 2: 0) | A &0xF000;
switch (A &0xF000) {
case 0x8000: case 0xA000:
VRC4_prg[A >>13 &1] =V;
sync();
break;
case 0x9000:
if (~A &2)
VRC4_mirroring =V;
if (reg[3] &0x10) {
if (reg[3] &0x01)
VRC4_activate(clear, sync, 0x0A, 0x05, 1, NULL, NULL, NULL, NULL, NULL);
else
if (~A &1)
VRC4_misc =V;
sync();
break;
case 0xF000:
switch (A &3) {
case 0: VRCIRQ_latch =VRCIRQ_latch &0xF0 | V &0x0F; break;
case 1: VRCIRQ_latch =VRCIRQ_latch &0x0F | V <<4; break;
case 2: VRCIRQ_mode =V;
if (VRCIRQ_mode &0x02) {
VRCIRQ_count =VRCIRQ_latch;
VRCIRQ_cycles =341;
}
X6502_IRQEnd(FCEU_IQEXT);
break;
case 3: VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02;
X6502_IRQEnd(FCEU_IQEXT);
break;
}
break;
default:
index =(A -0xB000) >>11 &~1 | A >>1 &1;
if (A &1)
VRC4_chr[index] =VRC4_chr[index] & 0x0F | V <<4;
else
VRC4_chr[index] =VRC4_chr[index] &~0x0F | V &0x0F;
sync();
break;
}
}
static void FP_FASTAPASS(1) cpuCycle(int a) {
if ((reg[0] &3) ==3) while (a--) { /* VRC4 mode */
if (VRCIRQ_mode &0x02 && (VRCIRQ_mode &0x04 || (VRCIRQ_cycles -=3) <=0)) {
if (~VRCIRQ_mode &0x04) VRCIRQ_cycles +=341;
if (!++VRCIRQ_count) {
VRCIRQ_count =VRCIRQ_latch;
X6502_IRQBegin(FCEU_IQEXT);
}
}
}
}
static void horizontalBlanking(void) {
if (~reg[0] &2) { /* MMC3 mode */
MMC3_count =!MMC3_count? MMC3_reload: --MMC3_count;
if (!MMC3_count && MMC3_irq) X6502_IRQBegin(FCEU_IQEXT);
}
}
static void applyMode() {
if ((reg[2] >>3 &7) >=5)
SetWriteHandler(0x8000, 0xFFFF, writeCNROM);
else
if (reg[3] &0x10)
SetWriteHandler(0x8000, 0xFFFF, writeVRC4);
else
SetWriteHandler(0x8000, 0xFFFF, writeMMC3);
VRC4_activate(clear, sync, 0x05, 0x0A, 1, NULL, NULL, NULL, NULL, NULL);
} else
MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, NULL);
}
static void Mapper445_restore (int version) {
applyMode();
applyMode(0);
sync();
}
static DECLFW(writeReg) {
static DECLFW (writeReg) {
if (~reg[3] &0x20) {
reg[A &3] =V;
if ((A &3) ==3) applyMode();
reg[A &3] = V;
if ((A &3) == 3) applyMode(1);
sync();
}
}
static void Mapper445_power(void) {
int i;
for (i =0; i <4; i++) reg[i] =0;
for (i =0; i <8; i++) MMC3_reg[i] =0;
for (i =0; i <2; i++) VRC4_prg[i] =0;
for (i =0; i <8; i++) VRC4_chr[i] =0;
MMC3_index =MMC3_mirroring =MMC3_wram =MMC3_reload =MMC3_count =MMC3_irq =0;
VRC4_mirroring =VRC4_misc =VRCIRQ_latch =VRCIRQ_mode =VRCIRQ_count =VRCIRQ_cycles =0;
reg[0] = reg[1] = reg[2] = reg[3] = 0;
dip =0;
SetReadHandler(0x6000, 0xFFFF, CartBR);
SetWriteHandler(0x5000, 0x5FFF, writeReg);
applyMode();
sync();
applyMode(1);
}
static void Mapper445_reset (void) {
int i;
for (i =0; i <5; i++) reg[i] =0;
dip +=0x40;
applyMode();
sync();
}
static void Mapper445_close(void) {
if (PRGCHR) FCEU_gfree(PRGCHR);
PRGCHR =NULL;
reg[0] = reg[1] = reg[2] = reg[3] = 0;
dip += 0x40;
applyMode(1);
}
void Mapper445_Init (CartInfo *info) {
Latch_addExState();
MMC3_addExState();
VRC24_addExState();
info->Reset = Mapper445_reset;
info->Power = Mapper445_power;
info->Close = Mapper445_close;
MapIRQHook = cpuCycle;
GameHBIRQHook = horizontalBlanking;
GameStateRestore = Mapper445_restore;
AddExState(stateRegs, ~0, 0, 0);
AddExState(stateRegs, ~0, 0, 0);
}

422
src/boards/446.c Normal file
View File

@@ -0,0 +1,422 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2022 NewRisingSun
*
* 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 "asic_h3001.h"
#include "asic_latch.h"
#include "asic_mmc1.h"
#include "asic_mmc2and4.h"
#include "asic_mmc3.h"
#include "asic_pt8154.h"
#include "asic_qj.h"
#include "asic_tc3294.h"
#include "asic_vrc1.h"
#include "asic_vrc2and4.h"
#include "asic_vrc3.h"
#include "asic_vrc6.h"
#include "asic_vrc7.h"
#include "flashrom.h"
#include "cartram.h"
static uint8 submapper;
static uint8 reg[8];
static void (*mapperSync)(int, int, int, int) = NULL;
static void applyMode (uint8);
static void sync () {
int prgAND = reg[3] ^ (submapper == 2? 0x00: 0xFF);
int prgOR = reg[1] | reg[2] <<8;
int chrAND = reg[4] <<2 &0xE0 ^0xFF;
int chrOR = reg[6];
SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], !(reg[5] &0x04));
if (mapperSync) mapperSync(prgAND, prgOR, chrAND, chrOR);
}
static void sync_152 (int prgAND, int prgOR, int chrAND, int chrOR) {
prgAND >>=1;
chrAND >>=3;
prgOR >>=1;
chrOR >>=3;
setprg16(0x8000, Latch_data >>4 &prgAND | prgOR &~prgAND);
setprg16(0xC000, prgOR | prgAND);
setchr8(Latch_data &chrAND | chrOR &~chrAND);
setmirror(Latch_data &0x80? MI_1: MI_0);
}
static void sync_AxROM (int prgAND, int prgOR, int chrAND, int chrOR) {
prgAND >>=2;
prgOR >>=2;
setprg32(0x8000, Latch_data &prgAND | prgOR &~prgAND);
setchr8(chrOR);
setmirror(Latch_data &0x10? MI_1: MI_0);
}
static void sync_BNROM (int prgAND, int prgOR, int chrAND, int chrOR) {
setprg8(0x8000, (Latch_data <<2 |0) &prgAND |prgOR);
setprg8(0xA000, (Latch_data <<2 |1) &prgAND |prgOR);
setprg8(0xC000, (Latch_data <<2 |2) &prgAND |prgOR);
setprg8(0xE000, (Latch_data <<2 |3) &prgAND |prgOR);
setchr8(chrOR);
setmirror(reg[4] &0x01? MI_V: MI_H);
}
static void sync_CNROM (int prgAND, int prgOR, int chrAND, int chrOR) {
chrAND >>=3;
chrOR >>=3;
setprg8(0x8000, 0 &prgAND |prgOR);
setprg8(0xA000, 1 &prgAND |prgOR);
setprg8(0xC000, 2 &prgAND |prgOR);
setprg8(0xE000, 3 &prgAND |prgOR);
setchr8(Latch_data &(reg[4] &1? 7: 3));
setmirror(reg[4] &0x01? MI_V: MI_H);
}
static void sync_CNROM_Konami (int prgAND, int prgOR, int chrAND, int chrOR) {
chrAND >>=3;
chrOR >>=3;
setprg8(0x8000, 0 &prgAND |prgOR);
setprg8(0xA000, 1 &prgAND |prgOR);
setprg8(0xC000, 2 &prgAND |prgOR);
setprg8(0xE000, 3 &prgAND |prgOR);
setchr8(Latch_data <<1 &2 | Latch_data >>1 &1);
setmirror(reg[4] &0x01? MI_V: MI_H);
}
static void sync_GNROM (int prgAND, int prgOR, int chrAND, int chrOR) {
prgAND >>=2;
chrAND >>=3;
prgOR >>=2;
chrOR >>=3;
setprg32(0x8000, Latch_data >>4 &prgAND | prgOR &~prgAND);
setchr8(Latch_data &3);
setmirror(reg[4] &0x01? MI_V: MI_H);
}
static void sync_H3001 (int prgAND, int prgOR, int chrAND, int chrOR) {
H3001_syncPRG(prgAND, prgOR &~prgAND);
H3001_syncCHR(chrAND, chrOR &~chrAND);
H3001_syncMirror();
}
static void sync_PNROM (int prgAND, int prgOR, int chrAND, int chrOR) {
MMC2_syncPRG(prgAND, prgOR &~prgAND);
MMC24_syncCHR(chrAND, chrOR &~chrAND);
MMC24_syncMirror();
}
static void sync_SKROM (int prgAND, int prgOR, int chrAND, int chrOR) {
prgAND >>=1;
chrAND >>=2;
prgOR >>=1;
chrOR >>=2;
MMC1_syncWRAM(reg[5]);
MMC1_syncPRG(prgAND, prgOR &~prgAND);
MMC1_syncCHR(chrAND, chrOR &~chrAND);
MMC1_syncMirror();
}
static void sync_SNROM (int prgAND, int prgOR, int chrAND, int chrOR) {
prgAND >>=1;
chrAND >>=2;
prgOR >>=1;
chrOR >>=2;
MMC1_syncWRAM(reg[5]);
MMC1_syncPRG(prgAND, prgOR &~prgAND);
MMC1_syncCHR(chrAND, chrOR &~chrAND);
MMC1_syncMirror();
}
static void sync_SUROM (int prgAND, int prgOR, int chrAND, int chrOR) {
prgAND >>=1;
chrAND =chrAND >>2 &0x0F; /* The highest CHR bit switches 256 KiB PRG banks, so don't use that as a CHR bank bit. */
prgOR >>=1;
chrOR >>=2;
MMC1_syncWRAM(reg[5]);
MMC1_syncPRG(prgAND, prgOR &~prgAND);
MMC1_syncCHR(chrAND, chrOR &~chrAND);
MMC1_syncMirror();
}
static void sync_PT8154 (int prgAND, int prgOR, int chrAND, int chrOR) {
PT8154_syncPRG(prgAND, prgOR &~prgAND);
PT8154_syncCHR(chrAND, chrOR &~chrAND);
PT8154_syncMirror();
}
static void sync_QJ (int prgAND, int prgOR, int chrAND, int chrOR) {
QJ_syncPRG(prgAND, prgOR &~prgAND);
QJ_syncCHR(chrAND, chrOR &~chrAND);
QJ_syncMirror();
}
static void sync_TC3294 (int prgAND, int prgOR, int chrAND, int chrOR) {
TC3294_syncWRAM(reg[5]);
TC3294_syncPRG(prgAND, prgOR &~prgAND);
setchr8(0);
TC3294_syncMirror();
}
static void sync_TxROM (int prgAND, int prgOR, int chrAND, int chrOR) {
MMC3_syncWRAM(reg[5]);
MMC3_syncPRG(prgAND, prgOR &~prgAND);
MMC3_syncCHR(chrAND, chrOR &~chrAND);
MMC3_syncMirror();
}
static void sync_TxSROM (int prgAND, int prgOR, int chrAND, int chrOR) {
MMC3_syncWRAM(reg[5]);
MMC3_syncPRG(prgAND, prgOR &~prgAND);
MMC3_syncCHR(chrAND &0x7F, chrOR &~chrAND);
setmirror(MMC3_getCHRBank(0) &0x80? MI_1: MI_0);
}
static void sync_UxROM (int prgAND, int prgOR, int chrAND, int chrOR) {
prgAND >>=1;
prgOR >>=1;
setprg16(0x8000, Latch_data &prgAND | prgOR &~prgAND);
setprg16(0xC000, prgOR | prgAND);
setchr8(chrOR);
setmirror(reg[4] &0x01? MI_V: MI_H);
}
static void sync_VRC1 (int prgAND, int prgOR, int chrAND, int chrOR) {
VRC1_syncPRG(prgAND, prgOR &~prgAND);
VRC1_syncCHR(chrAND, chrOR &~chrAND);
VRC1_syncMirror();
}
static void sync_VRC3 (int prgAND, int prgOR, int chrAND, int chrOR) {
prgAND >>=1;
prgOR >>=1;
VRC3_syncWRAM(reg[5]);
VRC3_syncPRG(prgAND, prgOR &~prgAND);
VRC3_syncCHR(chrAND, chrOR &~chrAND);
setmirror(reg[4] &0x01? MI_V: MI_H);
}
static void sync_VRC4 (int prgAND, int prgOR, int chrAND, int chrOR) {
VRC24_syncWRAM(reg[5]);
VRC24_syncPRG(prgAND, prgOR &~prgAND);
VRC24_syncCHR(chrAND, chrOR &~chrAND);
VRC24_syncMirror();
}
static void sync_VRC6 (int prgAND, int prgOR, int chrAND, int chrOR) {
VRC6_syncWRAM(reg[5]);
VRC6_syncPRG(prgAND, prgOR &~prgAND);
VRC6_syncCHR(chrAND, chrOR &~chrAND);
VRC6_syncMirror();
}
static void sync_VRC7 (int prgAND, int prgOR, int chrAND, int chrOR) {
VRC7_syncWRAM(reg[5]);
VRC7_syncPRG(prgAND, prgOR &~prgAND);
VRC7_syncCHR(chrAND, chrOR &~chrAND);
VRC7_syncMirror();
}
static void sync_supervisor (int prgAND, int prgOR, int chrAND, int chrOR) {
setprg8(0x8000, prgOR);
setprg8(0xA000, prgOR +1);
setprg8(0xC000, submapper == 3? 0x1E: 0x3E);
setprg8(0xE000, submapper == 3? 0x1F: 0x3F);
setchr8(chrOR);
setmirror(reg[4] &0x01? MI_V: MI_H);
}
static DECLFW (writeFlash) {
flashrom_write(A &0x1FFF | (Page[A >>11] +A -PRGptr[0]) &~0x1FFF, V);
}
static int SUROM_getPRGBank (uint8 bank) {
return MMC1_getPRGBank(bank) | MMC1_getCHRBank(0) &0x10;
}
static int Mapper22_getCHRBank (uint8 bank) {
return VRC24_getCHRBank(bank &7) >>1;
}
static DECLFW (writeReg) {
reg[A &7] = V;
if ((A &7) == 0)
applyMode(1);
else
sync();
}
static void applyMode (uint8 clear) {
if (reg[0] &0x80) {
SetWriteHandler(0x5000, 0x5FFF, CartBW);
switch(submapper <<8 | reg[0] &0x1F) {
case 0x000: case 0x100: case 0x200:
mapperSync = sync_UxROM;
Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL);
break;
case 0x001: case 0x105: case 0x205:
mapperSync = sync_SKROM;
MMC1_activate(clear, sync, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL);
break;
case 0x002: case 0x102: case 0x202: /* NROM or BNROM */
mapperSync = sync_BNROM;
Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL);
break;
case 0x003: case 0x103: case 0x203:
mapperSync = sync_CNROM;
Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL);
break;
case 0x004: case 0x101: case 0x201: case 0x209: /* MMC3 or Namco 118 */
mapperSync = sync_TxROM;
MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, NULL);
if (clear) MMC3_writeReg(0xA000, reg[4] &0x04? 0: 1);
break;
case 0x10E: case 0x20E: /* MMC3 with single-screen mirroring. 239-in-1's Goal! Two has a screen where MMC3 scanline counter emulation fails. */
mapperSync = sync_TxSROM;
MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, NULL);
break;
case 0x006:
mapperSync = sync_VRC4;
VRC4_activate(clear, sync, 0x42, 0x84, 1, NULL, NULL, NULL, NULL, NULL);
break;
case 0x007: case 0x112: case 0x212:
mapperSync = sync_VRC4;
VRC2_activate(clear, sync, 0x02, 0x01, NULL, Mapper22_getCHRBank, NULL, NULL);
break;
case 0x008: case 0x118: case 0x218:
mapperSync = sync_VRC4;
VRC4_activate(clear, sync, 0x05, 0x0A, 1, NULL, NULL, NULL, NULL, NULL);
break;
case 0x009: case 0x110:
mapperSync = sync_VRC6;
VRC6_activate(clear, sync, 0x01, 0x02, NULL, NULL, NULL, NULL);
break;
case 0x00A: case 0x115: case 0x215:
mapperSync = sync_VRC4;
VRC4_activate(clear, sync, 0x0A, 0x05, 1, NULL, NULL, NULL, NULL, NULL);
break;
case 0x00B:
mapperSync = sync_VRC6;
VRC6_activate(clear, sync, 0x02, 0x01, NULL, NULL, NULL, NULL);
break;
case 0x00C:
mapperSync = sync_VRC3;
VRC3_activate(clear, sync);
break;
case 0x00D:
mapperSync = sync_VRC7;
VRC7_activate(clear, sync, 0x18);
break;
case 0x00E:
mapperSync = sync_CNROM_Konami;
Latch_activate(clear, sync, 0x6000, 0x7FFF, NULL);
break;
case 0x104: case 0x204:
mapperSync = sync_AxROM;
Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL);
break;
case 0x106: case 0x206:
mapperSync = sync_SNROM;
MMC1_activate(clear, sync, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL);
break;
case 0x107: case 0x208:
mapperSync = sync_SUROM;
MMC1_activate(clear, sync, MMC1_TYPE_MMC1B, SUROM_getPRGBank, NULL, NULL, NULL);
break;
case 0x108:
mapperSync = sync_GNROM;
Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL);
break;
case 0x109:
mapperSync = sync_PNROM;
MMC24_activate(clear, sync);
break;
case 0x10A: case 0x20A:
mapperSync = sync_TxROM;
MMC3_activate(clear, sync, MMC3_TYPE_MMC6, NULL, NULL, NULL, NULL);
break;
case 0x10B: case 0x20B:
mapperSync = sync_152;
Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL);
break;
case 0x10F:
mapperSync = sync_PT8154;
PT8154_activate(clear, sync);
break;
case 0x119:
mapperSync = sync_QJ;
QJ_activate(clear, sync);
break;
case 0x11A: case 0x21A:
mapperSync = sync_VRC1;
VRC1_activate(clear, sync);
break;
case 0x301:
mapperSync = sync_H3001;
H3001_activate(clear, sync);
break;
case 0x401:
mapperSync = sync_TC3294;
TC3294_activate(clear, sync);
break;
default:
break;
}
} else {
SetWriteHandler(0x5000, 0x5FFF, writeReg);
SetReadHandler(0x8000, 0xFFFF, flashrom_read);
SetWriteHandler(0x8000, 0xFFFF, writeFlash);
mapperSync = sync_supervisor;
PPU_hook = NULL;
MapIRQHook = flashrom_cpuCycle;
GameHBIRQHook = NULL;
sync();
}
}
static void power () {
reg[0] = reg[1] = reg[2] = reg[3] = reg[4] = reg[5] = reg[6] = reg[7] = 0;
applyMode(1);
SetReadHandler(0x8000, 0xFFFF, CartBR);
}
static void stateRestore (int version) {
applyMode(0);
}
void Mapper446_Init (CartInfo *info) {
submapper =info->submapper;
H3001_addExState();
Latch_addExState();
MMC1_addExState();
MMC24_addExState();
MMC3_addExState();
VRC1_addExState();
VRC24_addExState();
VRC3_addExState();
VRC6_addExState();
VRC7_addExState();
QJ_addExState();
PT8154_addExState();
TC3294_addExState();
WRAM_init(info, 32);
flashrom_init (0x01, 0x7E, 131072, 0xAAA, 0x555, 0xFFF);
info->Reset =power;
info->Power =power;
GameStateRestore =stateRestore;
AddExState(reg, 8, 0, "REGS");
}

View File

@@ -19,12 +19,13 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
#include "cartram.h"
static uint8 reg;
static uint8 dip;
static SFORMAT Mapper447_stateRegs[] ={
static SFORMAT stateRegs[] = {
{ &reg, 1, "EXP0" },
{ &dip, 1, "DIPS" },
{ 0 }
@@ -37,7 +38,7 @@ static void sync () {
VRC24_syncWRAM(0);
}
static int Mapper447_getPRGBank(int bank) {
static int getPRGBank (uint8 bank) {
if (reg &4) {
if (~reg &2)
return VRC24_getPRGBank(bank &1) &~2 | bank &2;
@@ -47,36 +48,35 @@ static int Mapper447_getPRGBank(int bank) {
return VRC24_getPRGBank(bank);
}
DECLFR(Mapper447_readPRG) {
static DECLFR (readPRG) {
return CartBR(reg &8? (A &~3 | dip &3): A);
}
DECLFW(Mapper447_writeReg) {
if (VRC24_misc &1 && ~reg &1) {
reg =A &0xFF;
VRC24_Sync();
static DECLFW (writeReg) {
if (~reg &1) {
reg = A &0xFF;
sync();
}
CartBW(A, V);
}
void Mapper447_power(void) {
reg =0;
dip =0;
static void power (void) {
reg = 0;
dip = 0;
VRC24_power();
SetReadHandler(0x8000, 0xFFFF, Mapper447_readPRG);
SetReadHandler(0x8000, 0xFFFF, readPRG);
}
void Mapper447_reset(void) {
reg =0;
static void reset (void) {
reg = 0;
dip++;
VRC24_Sync();
}
sync();
}
void Mapper447_Init (CartInfo *info) {
VRC24_init(info, sync, 0x04, 0x08, 1, 0, 2);
VRC24_WRAMWrite =Mapper447_writeReg;
VRC24_GetPRGBank =Mapper447_getPRGBank;
info->Power =Mapper447_power;
info->Reset =Mapper447_reset;
AddExState(Mapper447_stateRegs, ~0, 0, 0);
VRC4_init(info, sync, 0x04, 0x08, 0, getPRGBank, NULL, NULL, writeReg, NULL );
WRAM_init(info, 2);
info->Power = power;
info->Reset = reset;
AddExState(stateRegs, ~0, 0, 0);
}

View File

@@ -19,59 +19,58 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
#include "cartram.h"
static uint8 reg;
static SFORMAT Mapper448_stateRegs[] ={
static SFORMAT stateRegs[] ={
{ &reg, 1, "EXP0" },
{ 0 }
};
static void sync () {
if (reg &8) { /* AOROM */
setprg32(0x8000, VRC24_prg[0] &0x07 | reg <<2 &~0x07);
setmirror(VRC24_prg[0] &0x10? MI_1: MI_0);
setprg32(0x8000, VRC24_getPRGBank(0) &0x07 | reg <<2 &~0x07);
setmirror(VRC24_getPRGBank(0) &0x10? MI_1: MI_0);
} else {
if (reg &4) { /* UOROM */
setprg16(0x8000, VRC24_prg[0] &0xF | reg <<3 &~0xF);
setprg16(0xC000, 0xF | reg <<3 &~0xF);
setprg16(0x8000, VRC24_getPRGBank(0) &0xF | reg <<3 &~0xF);
setprg16(0xC000, 0xF | reg <<3 &~0xF);
} else { /* UNROM */
setprg16(0x8000, VRC24_prg[0] &0x7 | reg <<3 &~0x7);
setprg16(0xC000, 0x7 | reg <<3 &~0x7);
setprg16(0x8000, VRC24_getPRGBank(0) &0x7 | reg <<3 &~0x7);
setprg16(0xC000, 0x7 | reg <<3 &~0x7);
}
VRC24_syncMirror();
}
setchr8(0);
}
DECLFW(Mapper448_writeReg) {
if (VRC24_misc &1) {
reg =A &0xFF;
VRC24_Sync();
}
static DECLFW (writeReg) {
reg =A &0xFF;
sync();
CartBW(A, V);
}
DECLFW(Mapper448_writePRG) {
static DECLFW (writePRG) {
VRC24_writeReg(reg &8? 0x8000: A, V);
}
void Mapper448_power(void) {
static void power (void) {
reg =0;
VRC24_power();
SetWriteHandler(0x8000, 0xFFFF, Mapper448_writePRG);
SetWriteHandler(0x8000, 0xFFFF, writePRG);
}
void Mapper448_reset(void) {
static void reset (void) {
reg =0;
VRC24_Sync();
}
VRC24_clear();
}
void Mapper448_Init (CartInfo *info) {
VRC24_init(info, sync, 0x04, 0x08, 1, 0, 2);
VRC24_WRAMWrite =Mapper448_writeReg;
info->Power =Mapper448_power;
info->Reset =Mapper448_reset;
AddExState(Mapper448_stateRegs, ~0, 0, 0);
VRC4_init(info, sync, 0x04, 0x08, 0, NULL, NULL, NULL, writeReg, NULL);
WRAM_init(info, 2);
info->Power =power;
info->Reset =reset;
AddExState(stateRegs, ~0, 0, 0);
}

View File

@@ -1,7 +1,7 @@
/* FCEUmm - NES/Famicom Emulator
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2022
* Copyright (C) 2025 NewRisingSun
*
* 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
@@ -19,88 +19,70 @@
*/
#include "mapinc.h"
#include "asic_latch.h"
static uint16 latchAddr;
static uint8 latchData;
static uint8 dipswitch;
static uint8 dipselect;
uint8 submapper;
uint8 pad;
uint8 padSelect;
static SFORMAT StateRegs[] =
{
{ &latchAddr, 2, "ADDR" },
{ &latchData, 1, "DATA" },
{ &latchData, 1, "DIPS" },
{ &dipselect, 1, "DSEL" },
{ 0 }
};
static void Mapper449_Sync(void)
{
int prg =latchAddr >>2 &0x1F | latchAddr >>3 &0x20;
if (~latchAddr &0x080)
{
setprg16(0x8000, prg);
setprg16(0xC000, prg |7);
}
else
{
if (latchAddr &0x001)
{
setprg32(0x8000, prg >>1);
}
else
{
setprg16(0x8000, prg);
setprg16(0xC000, prg);
}
}
setchr8(latchData);
setmirror(latchAddr &0x002? MI_H: MI_V);
static DECLFR (readPad_submapper0) {
return CartBR(A &~0xF | pad &0xF);
}
static DECLFR(Mapper449_Read)
{
if (dipselect)
return dipswitch &0x3;
else
if (latchAddr &0x200)
return CartBR(A | dipswitch &0xF);
else
return CartBR(A);
static DECLFR (readPad_submapper1) {
return pad;
}
static DECLFW(Mapper449_WriteDIPSelect)
{
dipselect =V &1;
static DECLFR (readPad_submapper2) {
return CartBR(A &~0x3 | pad &0x3);
}
static DECLFW(Mapper449_WriteLatch)
{
latchData =V;
latchAddr =A &0xFFFF;
Mapper449_Sync();
static void sync () {
int prg = Latch_address >>2 &0x1F | Latch_address >>3 &0x20 | Latch_address >>4 &0x40;
if (Latch_address &0x080) {
if (Latch_address &0x001)
setprg32(0x8000, prg >>1);
else {
setprg16(0x8000, prg);
setprg16(0xC000, prg);
}
setmirror(Latch_data &0x10? MI_1: MI_0);
} else {
setprg16(0x8000, prg);
setprg16(0xC000, prg | 7);
}
SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], submapper == 0 && Latch_address &0x80? 0: 1);
setchr8(Latch_data);
setmirror(Latch_address &0x002? MI_H: MI_V);
SetReadHandler(0x8000, 0xFFFF, submapper == 0 && Latch_address &0x200? readPad_submapper0: submapper == 2 && padSelect &1? readPad_submapper2: CartBR);
}
static void Mapper449_Reset(void)
{
dipswitch++;
latchAddr =latchData =0;
Mapper449_Sync();
static DECLFW (writePad_submapper2) {
padSelect = V;
sync();
}
static void Mapper449_Power(void)
{
dipselect =dipswitch =latchAddr =latchData =0;
Mapper449_Sync();
SetWriteHandler(0x6000, 0x7FFF, Mapper449_WriteDIPSelect);
SetWriteHandler(0x8000, 0xFFFF, Mapper449_WriteLatch);
SetReadHandler(0x6000, 0x7FFF, CartBR);
SetReadHandler(0x8000, 0xFFFF, Mapper449_Read);
static void power () {
pad = padSelect = 0;
Latch_power();
if (submapper == 1)
SetReadHandler(0x5000, 0x5FFF, readPad_submapper1);
else
if (submapper == 2)
SetWriteHandler(0x6000, 0x7FFF, writePad_submapper2);
}
void Mapper449_Init(CartInfo *info)
{
info->Power = Mapper449_Power;
info->Reset = Mapper449_Reset;
AddExState(StateRegs, ~0, 0, 0);
}
static void reset () {
pad++;
padSelect = 0;
Latch_clear();
}
void Mapper449_Init (CartInfo *info) {
submapper = info->submapper;
Latch_init(info, sync, 0x8000, 0xFFFF, NULL);
info->Power = power;
info->Reset = reset;
AddExState(&pad, 1, 0, "DIPS");
if (submapper == 2) AddExState(&padSelect, 1, 0, "DIPE");
}

View File

@@ -19,7 +19,7 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
static void sync () {
VRC24_syncPRG(0x0F, VRC2_pins <<4);
@@ -27,12 +27,12 @@ static void sync () {
VRC24_syncMirror();
}
void Mapper450_reset(void) {
VRC2_pins =0;
VRC24_Sync();
}
static void reset(void) {
VRC2_pins = 0;
VRC24_clear();
}
void Mapper450_Init (CartInfo *info) {
VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0);
info->Reset =Mapper450_reset;
VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL);
info->Reset = reset;
}

View File

@@ -1,7 +1,7 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2022
* Copyright (C) 2020
*
* 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
@@ -16,62 +16,57 @@
* 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
*
*
*/
/* N625836 PCB */
#include "mapinc.h"
#include "mmc3.h"
#include "asic_mmc3.h"
static void Mapper455_PRGWrap(uint32 A, uint8 V) {
int prgAND =EXPREGS[1] &0x01? 0x1F: 0x0F;
int prgOR =EXPREGS[0] >>2 &0x07 | EXPREGS[1] <<1 &0x08 | EXPREGS[0] >>2 &0x10;
if (EXPREGS[0] &0x01) {
if (EXPREGS[0] &0x02) {
setprg32(0x8000, prgOR >>1);
} else {
setprg16(0x8000, prgOR);
setprg16(0xC000, prgOR);
static uint8 reg[2];
static void sync () {
if (reg[0] &0x01) {
if (reg[0] &0x02)
setprg32(0x8000, reg[0] >>3);
else {
setprg16(0x8000, reg[0] >>2);
setprg16(0xC000, reg[0] >>2);
}
MMC3_syncCHR(0xFF, 0x00);
} else {
prgOR <<=1;
setprg8(A, V &prgAND | prgOR &~prgAND);
int prgAND = 0x1F;
int chrAND = reg[1] &0x02? 0x7F: 0xFF;
int prgOR = reg[0] >>1;
int chrOR = reg[1] <<6;
MMC3_syncPRG(prgAND, prgOR &~prgAND);
MMC3_syncCHR(chrAND, chrOR &~chrAND);
}
MMC3_syncMirror();
}
static void Mapper455_CHRWrap(uint32 A, uint8 V) {
int chrAND =EXPREGS[1] &0x02? 0xFF: 0x7F;
int chrOR =(EXPREGS[0] >>2 &0x07 | EXPREGS[1] <<1 &0x08 | EXPREGS[0] >>2 &0x10) <<4;
setchr1(A, V &chrAND | chrOR &~chrAND);
}
static DECLFW(Mapper455_Write) {
static DECLFW (writeReg) {
if (A &0x100) {
EXPREGS[0] =V;
EXPREGS[1] =A &0xFF;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
reg[0] = V;
reg[1] = A &0xFF;
sync();
}
}
static void Mapper455_Reset(void) {
EXPREGS[0] =1;
EXPREGS[1] =0;
MMC3RegReset();
static void reset () {
reg[0] = reg[1] = 0;
MMC3_clear();
}
static void Mapper455_Power(void) {
EXPREGS[0] =1;
EXPREGS[1] =0;
GenMMC3Power();
SetWriteHandler(0x4100, 0x5FFF, Mapper455_Write);
static void power () {
reg[0] = reg[1] = 0;
MMC3_power();
SetWriteHandler(0x4020, 0x5FFF, writeReg);
}
void Mapper455_Init(CartInfo *info) {
GenMMC3_Init(info, 256, 256, 0, 0);
cwrap = Mapper455_CHRWrap;
pwrap = Mapper455_PRGWrap;
info->Power = Mapper455_Power;
info->Reset = Mapper455_Reset;
AddExState(EXPREGS, 2, 0, "EXPR");
void Mapper455_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, NULL);
info->Power = power;
info->Reset = reset;
AddExState(reg, 2, 0, "EXPR");
}

View File

@@ -1,7 +1,7 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2023
* Copyright (C) 2025 NewRisingSun
*
* 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
@@ -16,58 +16,55 @@
* 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 "asic_mmc3.h"
static void M458CW(uint32 A, uint8 V) {
setchr1(A, ((EXPREGS[0] << 4) & ~0x7F) | (V & 0x7F));
static uint8 submapper;
static uint8 reg;
static uint8 pad;
static DECLFR (readPad) {
return CartBR(A &~0xF | pad &0xF);
}
static void M458PW(uint32 A, uint8 V) {
if (EXPREGS[0] & 0x10) {
setprg32(0x8000, EXPREGS[0] >> 1);
} else {
setprg16(0x8000, EXPREGS[0]);
setprg16(0xC000, EXPREGS[0]);
static void sync () {
if (reg &(submapper == 1? 0x08: 0x10))
setprg32(0x8000, reg >>1);
else {
setprg16(0x8000, reg);
setprg16(0xC000, reg);
}
MMC3_syncCHR(0x7F, reg <<4 &~0x7F);
MMC3_syncMirror();
SetReadHandler(0x8000, 0xFFFF, reg &(submapper == 1? 0x80: 0x20)? readPad: CartBR);
}
static DECLFR(M458Read) {
if ((EXPREGS[0] & 0x20) && (EXPREGS[1] & 3)) {
return CartBR((A & ~3) | (EXPREGS[1] & 3));
}
return CartBR(A);
static DECLFW (writeReg) {
reg = A &0xFF;
sync();
}
static DECLFW(M458Write) {
if (MMC3CanWriteToWRAM()) {
EXPREGS[0] = A & 0xFF;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
}
static void reset () {
reg = 0;
pad++;
MMC3_clear();
}
static void M458Reset(void) {
EXPREGS[0] = 0;
EXPREGS[1]++;
MMC3RegReset();
static void power () {
reg = 0;
pad = 0;
MMC3_power();
}
static void M458Power(void) {
EXPREGS[0] = 0;
EXPREGS[1] = 0;
GenMMC3Power();
SetReadHandler(0x8000, 0xFFFF, M458Read);
SetWriteHandler(0x6000, 0x7FFF, M458Write);
}
void Mapper458_Init(CartInfo *info) {
GenMMC3_Init(info, 256, 256, 0, 0);
cwrap = M458CW;
pwrap = M458PW;
info->Reset = M458Reset;
info->Power = M458Power;
AddExState(EXPREGS, 2, 0, "EXPR");
void Mapper458_Init (CartInfo *info) {
submapper = info->submapper;
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
AddExState(&pad, 1, 0, "DIPS");
}

View File

@@ -1,7 +1,7 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2022
* Copyright (C) 2020
*
* 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
@@ -16,79 +16,70 @@
* 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 "asic_mmc3.h"
#include "cartram.h"
static uint8 *CHRRAM =NULL;
static uint8 submapper;
static uint8 reg;
static uint8 pad;
static DECLFR(Mapper460_ReadOB)
{
return X.DB;
static DECLFR (readPad) {
return CartBR(A &~3 | pad &3);
}
static void Mapper460_PRGWrap(uint32 A, uint8 V) {
int prgAND =0x0F;
int prgOR =EXPREGS[0] <<4;
if (EXPREGS[0] &0x38) { /* Menu selection by selectively connecting CPU D7 to reg or not */
if (~A &0x4000) {
setprg8(A, (EXPREGS[0] &0x10? ~2: ~0) &V &prgAND | prgOR &~prgAND);
setprg8(A |0x4000, (EXPREGS[0] &0x10? 2: 0) |V &prgAND | prgOR &~prgAND);
}
} else
setprg8(A, V &prgAND | prgOR &~prgAND);
/* Menu selection by selectively connecting reg's D7 to PRG /CE or not */
if (EXPREGS[0] &0x80 && EXPREGS[1] &1)
SetReadHandler(0x8000, 0xFFFF, Mapper460_ReadOB);
static void sync () {
MMC3_syncPRG(0x0F, reg <<4 &~0x0F);
if (reg &0x04)
MMC3_syncCHR(0x1FF, 0x000);
else
SetReadHandler(0x8000, 0xFFFF, CartBR);
}
static void Mapper460_CHRWrap(uint32 A, uint8 V) {
if (EXPREGS[0] &0x04) {
setchr2(0x0000, DRegBuf[0] &0xFE);
setchr2(0x0800, DRegBuf[0] |0x01);
setchr2(0x1000, DRegBuf[2]);
setchr2(0x1800, DRegBuf[5]);
} else
setchr8r(0x10, 0);
MMC3_syncMirror();
SetReadHandler(0x8000, 0xFFFF, submapper == 0 && reg &0x80 || submapper == 1 && reg &0x20? readPad: CartBR);
}
static DECLFW(Mapper460_WriteExtra) {
if (A001B &0x80 && ~A001B &0x40) EXPREGS[0] =A &0xFF;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
static int getPRGBank (uint8 bank) {
if (reg &0x08) {
int mask = reg &0x10? 3: 1;
return MMC3_getPRGBank(bank &1) &~mask | bank &mask;
} else
return MMC3_getPRGBank(bank);
}
static void Mapper460_Reset(void) {
EXPREGS[0] =0;
EXPREGS[1]++;
MMC3RegReset();
static int getCHRBank (uint8 bank) {
if (reg &0x04)
return MMC3_getCHRBank(bank &6 | bank >>1 &1) <<1 | bank &1;
else
return MMC3_getCHRBank(bank);
}
static void Mapper460_Power(void) {
EXPREGS[0] =0;
EXPREGS[1] =0;
GenMMC3Power();
SetWriteHandler(0x6000, 0x7FFF, Mapper460_WriteExtra);
static DECLFW (writeReg) {
reg = A &0xFF;
sync();
}
static void Mapper460_close(void) {
if (CHRRAM) FCEU_gfree(CHRRAM);
CHRRAM =NULL;
static void reset () {
reg = 0;
pad++;
MMC3_clear();
}
void Mapper460_Init(CartInfo *info) {
GenMMC3_Init(info, 128, 512, 0, 0);
cwrap = Mapper460_CHRWrap;
pwrap = Mapper460_PRGWrap;
info->Power = Mapper460_Power;
info->Reset = Mapper460_Reset;
info->Close = Mapper460_close;
AddExState(EXPREGS, 2, 0, "EXPR");
CHRRAM =(uint8 *)FCEU_gmalloc(8192);
SetupCartCHRMapping(0x10, CHRRAM, 8192, 1);
AddExState(CHRRAM, 8192, 0, "CRAM");
static void power () {
reg = 0;
pad = 0;
MMC3_power();
}
void Mapper460_Init (CartInfo *info) {
submapper = info->submapper;
MMC3_init(info, sync, MMC3_TYPE_SHARP, getPRGBank, getCHRBank, NULL, writeReg);
CHRRAM_init(info, 8);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
AddExState(&reg, 1, 0, "DIPS");
}

60
src/boards/461.c Normal file
View File

@@ -0,0 +1,60 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc1.h"
static uint8 reg;
static void sync () {
if (reg &0x04) {
MMC1_syncPRG(reg &0x08? 0x07: 0x03, reg &0x0C);
MMC1_syncCHR(0x1F, reg <<2 &0x20);
} else {
setprg16(0x8000, reg &0x03);
setprg16(0xC000, reg &0x03);
MMC1_syncCHR(0x07, 0x40);
}
MMC1_syncMirror();
}
static DECLFW (writeReg) {
reg = A &0xFF;
sync();
}
static void reset () {
reg = 0;
MMC1_clear();
}
static void power () {
reg = 0;
MMC1_power();
}
void Mapper461_Init (CartInfo *info) {
MMC1_init(info, sync, MMC1_TYPE_MMC1A, NULL, NULL, NULL, writeReg);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
}

View File

@@ -7,7 +7,7 @@
* 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
@@ -18,93 +18,40 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* BlazePro CPLD-based multicarts
Unsolved issue: how is CHR RAM write-protection triggered?
Known problems:
Forever Duo of NES 852-in-1 (rev1):
#A370 Time Lord: Hangs with glitchy status bar on NTSC and PAL but not Dendy
#A133 Galactic Crusader: Wrong mirroring
#A249 Mission Cobra: Wrong mirroring
Legendary Games of NES 509-in-1:
#189 Huang Di Battle of Zhuolu: Wrong mirroring during intro
#227 Kid Niki Niki 2: Title screen animation flickers and looks strange
#234 Klax: Screen in wrong position during options screen
#365 Rocman X: Graphical garbage in waterfall (middle) level
#403 Star Wars: Blank tiles due to lack of CHR RAM write-protection
#404 The Empire Strikes Back: Blank tiles due to lack of CHR RAM write-protection
#460 Twin Dragons: Wrong mirroring
Unlicensed Collection 142-in-1:
#59 Huang Di: Wrong mirroring during intro
#84 Ms. Pac-Man: Wrong mirroring
#102 Rocman X: Graphical garbage in waterfall (middle) level
#132 Trolls on Treasure Island: Wrong mirroring during map
Unreleased Collection 73-in-1 (v1.01):
#38 Holy Diver: Wrong mirroring during first scene
*/
#include "mapinc.h"
#include "state.h"
#include "asic_fme7.h"
#include "asic_latch.h"
#include "asic_mmc1.h"
#include "asic_mmc2and4.h"
#include "asic_mmc3.h"
#include "asic_vrc1.h"
#include "asic_vrc2and4.h"
#include "asic_vrc3.h"
#include "asic_vrc6.h"
#include "asic_vrc7.h"
#include "cartram.h"
static uint8 submapper;
static uint8 eeprom[16], eep_clock, state, command, output; /* Some strange serial EEPROM */
static uint8 *WRAM;
static uint32 WRAMSIZE;
static uint8 reg[4]; /* Supervisor registers */
static uint8 Custom_reg[4]; /* Registers for custom mappers */
static uint8 eeprom[16], eep_clock, state, command, output; /* Serial EEPROM */
static int prevSFEXINDEX;
extern int SFEXINDEX;
extern SFORMAT SFMDATA[64];
static uint8 mapper; /* 5700 MSB >>4 OR'd with submapper <<4 */
static uint8 mapperFlags; /* 5700 LSB */
static uint8 misc; /* 5601 */
static uint8 misc2; /* 5702 */
static void (*sync)();
static uint16 prgOR;
static uint8 prgAND;
static uint8 regByte[16];
static int16 regWord[9];
#include "468_mmc1.h"
#include "468_mmc24.h"
#include "468_mmc3.h"
#include "468_vrc1.h"
#include "468_vrc24.h"
#include "468_vrc3.h"
#include "468_vrc6.h"
#include "468_vrc7.h"
#include "468_fme7.h"
#include "468_discrete.h"
#include "468_cnrom.h"
#include "468_if12.h"
#include "468_lf36.h"
#include "468_nanjing.h"
static void (*mapperSync)(int) = NULL;
static void applyMode (uint8);
static SFORMAT stateRegs[] = {
{ &mapper, 1, "SUP0" },
{ &mapperFlags, 1, "SUP1" },
{ &misc, 1, "SUP2" },
{ &misc2, 1, "SUP3" },
{ &prgOR, 2, "SUP4" },
{ &prgAND, 1, "SUP5" },
{ eeprom, 16,"EEPR" },
{ &eep_clock, 1, "EEP0" },
{ &state, 1, "EEP1" },
{ &command, 1, "EEP2" },
{ &output, 1, "EEP3" },
{ regByte, 16,"REGB" },
{ regWord, 16,"REGW" },
{ &reg, 4, "REGS" },
{ &Custom_reg, 4, "CURG" },
{ eeprom, 16, "EEPR" },
{ &eep_clock, 1, "EEP0" },
{ &state, 1, "EEP1" },
{ &command, 1, "EEP2" },
{ &output, 1, "EEP3" },
{ 0 }
};
static const uint16 lut509[512] ={ /* Strange look-up table, used only by Legendary Games of NES 509-in-1 */
/* Serial EEPROM */
static const uint16 lut509[512] = { /* Look-up table, used only by Legendary Games of NES 509-in-1 */
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 0, 1, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
85, 86, 87, 88, 89, 90, 4, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
@@ -120,153 +67,469 @@ static const uint16 lut509[512] ={ /* Strange look-up table, used only by Legend
483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 512, 513, 514, 515, 516, 517
};
void setPins(uint8 select, uint8 newClock, uint8 newData) { /* Serial EEPROM */
static void setPins(uint8 select, uint8 newClock, uint8 newData) { /* Serial EEPROM */
if (select)
state =0;
state = 0;
else
if (!eep_clock && !!newClock) {
if (state <8) {
command =command <<1 | !!(newData)*1;
if (++state ==8 && (command &0xF0) !=0x50 && (command &0xF0) !=0xA0) state =0;
command = command <<1 | !!(newData)*1;
if (++state == 8 && (command &0xF0) != 0x50 && (command &0xF0) != 0xA0) state = 0;
} else {
int mask =1 <<(15 -state);
int address =command &0x0F;
if ((command &0xF0) ==0xA0) {
eeprom[address] =eeprom[address] &~mask | !!(newData)*mask;
/* The "write" command also silently returns the content of a strange lookup table */
output =!!(lut509[eeprom[0] | eeprom[1] | eeprom[2] <<8 &0x1FF] >>(address &1? 0: 8) &mask);
int mask = 1 <<(15 -state);
int address = command &0x0F;
if ((command &0xF0) == 0xA0) {
eeprom[address] = eeprom[address] &~mask | !!(newData)*mask;
/* The "write" command also silently returns the content of a lookup table */
output = !!(lut509[eeprom[0] | eeprom[1] | eeprom[2] <<8 &0x1FF] >>(address &1? 0: 8) &mask);
} else
if ((command &0xF0) ==0x50)
output =!!(eeprom[address] &mask);
if (++state ==16) state =0;
if ((command &0xF0) == 0x50)
output = !!(eeprom[address] &mask);
if (++state == 16) state = 0;
}
}
eep_clock =newClock;
eep_clock = newClock;
}
static DECLFR(readReg);
static DECLFW(writeReg);
static void setMapper(uint8 clearRegs) {
int i;
if (clearRegs) {
for (i =0; i <16; i++) regByte[i] =0;
for (i =0; i < 8; i++) regWord[i] =0;
X6502_IRQEnd(FCEU_IQEXT);
/* Mapper syncs */
static void sync () {
if (mapperSync) mapperSync(reg[submapper == 1? 2: 3] <<9 &0x2000 | reg[1] <<5 &0x1FE0 | reg[0] <<4 &0x0010);
}
static void sync_AxROM (int prgOR) {
int prgAND = reg[0] &0x20? 0x0F: reg[0] &0x02? 0x03: 0x07;
setprg32(0x8000, Latch_data &prgAND | prgOR >>2 &~prgAND);
setchr8(0);
setmirror(Latch_data &0x10? MI_1: MI_0);
}
static void sync_BxROM (int prgOR) {
int prgAND = reg[0] &0x20? 0x0F: reg[0] &0x02? 0x03: 0x07;
setprg32(0x8000, Latch_data &prgAND | prgOR >>2 &~prgAND);
setchr8(0);
setmirror(reg[0] &0x04? MI_H: MI_V);
}
static void sync_FME7 (int prgOR) {
int prgAND = reg[0] &0x02? 0x0F: 0x1F;
FME7_syncWRAM(0);
FME7_syncPRG(prgAND, prgOR &~prgAND);
FME7_syncCHR(0xFF, 0x00);
FME7_syncMirror();
}
static void sync_FxROM (int prgOR) {
int prgAND = reg[0] &0x02? 0x07: 0x0F;
MMC24_syncWRAM(0);
MMC4_syncPRG(prgAND, prgOR >>1 &~prgAND);
MMC24_syncCHR(0xFF, 0x00);
MMC24_syncMirror();
}
static void sync_GNROM (int prgOR) {
int prgAND = reg[0] &0x08? 0x01: 0x03;
int value = Latch_data;
if (submapper == 1 && ~reg[0] &0x08 || submapper != 1 && prgOR &0x2000) value = Latch_data >>4 &0x0F | Latch_data <<4 &0xF0;
prgOR = prgOR >>2 | reg[0] >>1 &0x02;
setprg32(0x8000, value &prgAND | prgOR &~prgAND);
setchr8(value >>4);
setmirror(reg[0] &0x10? MI_H: MI_V);
}
static void sync_IF12 (int prgOR) {
int prgAND = reg[0] &0x02? 0x07: 0x0F;
setprg16(0x8000, Custom_reg[1] &prgAND | prgOR >>1 &~prgAND);
setprg16(0xC000, prgOR >>1 | prgAND);
setchr8(Custom_reg[0] >>1 &0x0F);
setmirror(Custom_reg[0] &0x01? MI_H: MI_V);
}
static DECLFW (IF12_writeReg) {
Custom_reg[A >>14 &1] = V;
sync();
}
static void sync_LF36 (int prgOR) {
prgOR |= reg[0] &0x08;
setprg8(0x8000, 0x04 | prgOR);
setprg8(0xA000, 0x05 | prgOR);
setprg8(0xC000, Custom_reg[0] &0x07 | prgOR);
setprg8(0xE000, 0x07 | prgOR);
setchr8(0);
setmirror(reg[0] &0x04? MI_H: MI_V);
}
static void FP_FASTAPASS(1) LF36_cpuCycle (int a) {
while (a--) {
if (Custom_reg[1] &1) {
if (!++Custom_reg[2]) ++Custom_reg[3];
if (Custom_reg[3] &0x10)
X6502_IRQBegin(FCEU_IQEXT);
else
X6502_IRQEnd(FCEU_IQEXT);
} else {
Custom_reg[2] = Custom_reg[3] = 0;
X6502_IRQEnd(FCEU_IQEXT);
}
}
}
static DECLFW(LF36_writeReg) {
switch(A >>13 &3) {
case 0: case 1:
Custom_reg[1] = A >>13 &1;
break;
case 3:
Custom_reg[0] = V;
sync();
}
}
static void sync_Misc (int prgOR) {
if (reg[0] &0x02) {
setprg16(0x8000, Custom_reg[2] <<1 &0x0E | reg[0] &0x01 | prgOR >>1 &~0x0F);
setprg16(0xC000, Custom_reg[2] <<1 &0x0E | reg[0] &0x01 | prgOR >>1 &~0x0F);
setchr8(Custom_reg[0] &0x03);
} else {
setprg32(0x8000, Custom_reg[2] &0x07 | prgOR >>2 &~0x07);
setchr8(Custom_reg[0] &0x0F);
}
if (reg[0] &0x08)
setmirror(reg[0] &0x04? MI_H: MI_V);
else
setmirror(Custom_reg[1] &0x10? MI_1: MI_0);
}
static DECLFW (Misc_writeReg) {
switch(A >>12 &7) {
case 0: case 2: case 3:
Custom_reg[0] = V;
sync();
break;
case 1:
Custom_reg[reg[0] &0x08? 0: 1] = V;
sync();
break;
case 6: case 7:
Custom_reg[2] = V;
sync();
break;
}
}
static void sync_Nanjing (int prgOR) {
setprg32(0x8000, Custom_reg[2] <<4 &0x30 | Custom_reg[0] &0x0F | (Custom_reg[3] &0x04? 0x00: 0x03) | prgOR >>2);
setchr8(0);
setmirror(reg[0] &0x04? MI_H: MI_V);
}
static void Nanjing_scanline (void) {
if (Custom_reg[0] &0x80 && scanline <239) {
setchr4(0x0000, scanline >= 127? 1: 0);
setchr4(0x1000, scanline >= 127? 1: 0);
} else
setchr8(0);
}
static DECLFW (Nanjing_writeReg) {
Custom_reg[A >>8 &3] = V;
sync();
}
static void sync_PNROM (int prgOR) {
MMC24_syncWRAM(0);
MMC2_syncPRG(0x0F, prgOR &~0x0F);
MMC24_syncCHR(0xFF, 0x00);
MMC24_syncMirror();
}
static void sync_SxROM (int prgOR) {
int prgAND = reg[0] &0x02? (reg[0] &0x08? 0x03: 0x07): 0x0F;
MMC1_syncWRAM(0);
MMC1_syncPRG(prgAND, (prgOR >>1 | reg[0] &0x06) &~prgAND);
MMC1_syncCHR(0x1F, 0x00);
MMC1_syncMirror();
}
static void sync_SUROM (int prgOR) {
MMC1_syncWRAM(0);
MMC1_syncPRG(0x1F, prgOR >>1 &~0x1F);
MMC1_syncCHR(0x0F, 0x00);
MMC1_syncMirror();
}
static int SUROM_getPRGBank (uint8 bank) {
return MMC1_getPRGBank(bank) | MMC1_getCHRBank(0) &0x10;
}
static void sync_TxROM (int prgOR) {
int prgAND = reg[0] &0x08? (reg[0] &0x04? (reg[0] &0x02? (reg[2] &0x02? 0x07: 0x0F): 0x1F): 0x3F): 0x7F;
prgOR |= reg[2] &0x01? 0x0C: 0x00;
MMC3_syncWRAM(0);
MMC3_syncPRG(prgAND, prgOR &~prgAND);
MMC3_syncCHR(reg[0] &0x10? 0xFF: 0x7F, 0x00);
MMC3_syncMirror();
}
static void sync_TxSROM (int prgOR) {
int prgAND = reg[0] &0x08? (reg[0] &0x04? (reg[0] &0x02? (reg[2] &0x02? 0x07: 0x0F): 0x1F): 0x3F): 0x7F;
prgOR |= reg[2] &0x01? 0x0C: 0x00;
MMC3_syncWRAM(0);
MMC3_syncPRG(prgAND, prgOR &~prgAND);
MMC3_syncCHR(0x7F, 0x00);
switch(MMC3_getMirroring() &3) { /* Only A000=02 is TxSROM. H/V mirroring is necessary for Ys 1, modified for MMC3. */
case 0:
setmirror(MI_V);
break;
case 1:
setmirror(MI_H);
break;
case 2:
setmirror(MMC3_getCHRBank(0) &0x80? MI_1: MI_0);
break;
case 3:
setmirror(MI_1);
break;
}
}
static void sync_UxROM (int prgOR) {
int prgAND = reg[0] &0x02? 0x07: submapper == 1 && ~reg[0] &0x04? 0x1F: 0x0F;
setprg16(0x8000, Latch_data &prgAND | prgOR >>1 &~prgAND);
setprg16(0xC000, prgOR >>1 | prgAND);
setchr8(0);
setmirror(reg[0] &0x04? MI_H: MI_V);
}
static void sync_UNROM512 (int prgOR) {
setprg16(0x8000, Latch_data &0x1F | prgOR >>1 &~0x1F);
setprg16(0xC000, prgOR >>1 | 0x1F);
setchr8(Latch_data >>5);
setmirror(reg[0] &0x04? MI_H: MI_V);
}
static void sync_VRC1 (int prgOR) {
int prgAND = reg[0] &0x08? (reg[0] &0x04? (reg[0] &0x02? 0x0F: 0x1F): 0x3F): 0x7F;
VRC1_syncPRG(prgAND, prgOR &~prgAND);
VRC1_syncCHR(0x1F, 0x00);
VRC1_syncMirror();
}
static void sync_VRC24 (int prgOR) {
int prgAND = reg[0] &0x02? 0x0F: 0x1F;
VRC24_syncWRAM(0);
VRC24_syncPRG(prgAND, prgOR &~prgAND);
VRC24_syncCHR(0xFF, 0x00);
VRC24_syncMirror();
}
static void sync_VRC3 (int prgOR) {
VRC3_syncWRAM(0);
VRC3_syncPRG(0x07, prgOR >>1 &~0x07);
VRC3_syncCHR(0x01, 0x00);
setmirror(reg[0] &0x04? MI_H: MI_V);
}
static void sync_VRC6 (int prgOR) {
int prgAND = reg[0] &0x02? 0x0F: 0x1F;
VRC6_syncWRAM(0);
VRC6_syncPRG(prgAND, prgOR &~prgAND);
VRC6_syncCHR(0xFF, 0x00);
VRC6_syncMirror();
}
static void sync_VRC7 (int prgOR) {
int prgAND = reg[0] &0x08? (reg[0] &0x04? (reg[0] &0x02? 0x0F: 0x1F): 0x3F): 0x7F;
VRC7_syncWRAM(0);
VRC7_syncPRG(prgAND, prgOR &~prgAND);
VRC7_syncCHR(reg[0] &0x10? 0xFF: 0x7F, 0x00);
VRC7_syncMirror();
}
/* Supervisor */
static DECLFR (readReg) {
switch(A) {
case 0x5301: case 0x5601:
return output? 0x80: 0x00;
default:
return 0xFF;
}
}
static DECLFW (writeReg) {
switch(A) {
case 0x5301:
if (submapper == 0) setPins(!!(V &0x04), !!(V &0x02), !!(V &0x01));
break;
case 0x5601:
if (submapper == 1) setPins(!!(V &0x10), !!(V &0x02), !!(V &0x01));
if (~reg[3] &0x80) {
reg[3] = V;
sync();
}
break;
case 0x5700:
reg[A &3] = V;
applyMode(1);
break;
case 0x5701: case 0x5702:
reg[A &3] = V;
sync();
break;
}
}
static void applyMode (uint8 clear) {
uint8 previousMirroring;
MapIRQHook = NULL;
PPU_hook = NULL;
GameHBIRQHook = NULL;
SetReadHandler(0x5000, 0x5FFF, readReg);
SetReadHandler(0x6000, 0xFFFF, CartBR);
SetWriteHandler(0x5000, 0x5FFF, writeReg);
SetWriteHandler(0x6000, 0xFFFF, CartBW);
MapIRQHook = NULL;
PPU_hook = NULL;
GameHBIRQHook = NULL;
setprg8r(0x10, 0x6000, 0);
switch(mapper) { /* 5700 MSB >>4 OR'd with submapper <<4 */
case 0x00: case 0x01: case 0x32: MMC1_reset(clearRegs); break;
case 0x0A: MMC2_reset(clearRegs); break;
case 0x10: case 0x11: case 0x12: MMC3_reset(clearRegs); break;
case 0x08: MMC4_reset(clearRegs); break;
case 0x40: VRC1_reset(clearRegs); break;
case 0x20: case 0x21: case 0x22: case 0x23: VRC24_reset(clearRegs); break;
case 0x44: VRC3_reset(clearRegs); break;
case 0x30: case 0x31: VRC6_reset(clearRegs); break;
case 0x41: VRC7_reset(clearRegs); break;
case 0x07: LF36_reset(clearRegs); break;
case 0x50: FME7_reset(clearRegs); break;
case 0x0E: case 0x1E: NANJING_reset(clearRegs); break;
case 0x09: case 0x0B: case 0x17: case 0x37: UNROM_IF12_reset(clearRegs); break;
case 0x04: case 0x06: case 0x14: case 0x16: ANROM_BNROM_reset(clearRegs); break;
case 0x05: case 0x15: CNROM_BF9097_reset(clearRegs); break;
case 0x0C: case 0x0D: case 0x1C: case 0x1D: GNROM_reset(clearRegs); break;
default: break;
}
sync();
}
static DECLFR(readReg) {
switch(A) {
case 0x5301: case 0x5601:
return output? 0x80: 0x00;
default:
return 0xFF;
}
}
static DECLFW(writeReg) {
switch(A) {
case 0x5301:
if (submapper ==0) setPins(!!(V &0x04), !!(V &0x02), !!(V &0x01));
break;
case 0x5601:
if (~misc &0x80) {
misc =V;
if (submapper !=1) {
prgOR =prgOR &~0x2000 | V <<9 &0x2000;
switch(submapper <<8 | reg[0] >>4) {
case 0x000: case 0x302:
mapperSync = sync_SxROM;
MMC1_activate(clear, sync, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL);
break;
case 0x001:
mapperSync = sync_SUROM;
MMC1_activate(clear, sync, MMC1_TYPE_MMC1B, SUROM_getPRGBank, NULL, NULL, NULL);
break;
case 0x004: case 0x006: case 0x104: case 0x106:
mapperSync = reg[0] &0x08? sync_BxROM: sync_AxROM;
Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL);
break;
case 0x005: case 0x105:
mapperSync = sync_Misc; /* NROM, CNROM, Fire Hawk */
SetWriteHandler(0x8000, 0xFFFF, Misc_writeReg);
if (clear) Custom_reg[0] = Custom_reg[1] = Custom_reg[2] = Custom_reg[3] = 0;
sync();
break;
case 0x007:
mapperSync = sync_LF36; /* SMB2J */
MapIRQHook = LF36_cpuCycle;
SetWriteHandler(0x8000, 0xFFFF, LF36_writeReg);
if (clear) Custom_reg[0] = Custom_reg[1] = Custom_reg[2] = Custom_reg[3] = 0;
sync();
break;
case 0x008:
mapperSync = sync_FxROM;
MMC24_activate(clear, sync);
break;
case 0x009: case 0x107: case 0x307:
if (reg[0] &0x08) {
mapperSync = sync_UxROM;
Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL);
} else {
mapperSync = sync_IF12; /* Not Irem's actual IF-12 mapper, but something custom by BlazePro */
SetWriteHandler(0x8000, 0xFFFF, IF12_writeReg);
if (clear) Custom_reg[0] = Custom_reg[1] = Custom_reg[2] = Custom_reg[3] = 0;
sync();
}
}
if (submapper ==1) setPins(!!(V &0x10), !!(V &0x02), !!(V &0x01));
break;
case 0x5700:
mapper =V >>4 | submapper <<4;
mapperFlags =V &0xF;
prgOR =prgOR &~0x0010 | V <<4 &0x0010;
setMapper(1);
break;
case 0x5701:
prgOR =prgOR &~0x1FE0 | V <<5 &0x1FE0;
sync();
break;
case 0x5702:
if (submapper ==1) {
misc2 =V;
prgOR =prgOR &~0x2000 | V <<9 &0x2000;
setMapper(0); /* The misc2 value is required for prgAND by MMC3 and UNROM */
}
break;
break;
case 0x00A:
mapperSync = sync_PNROM;
MMC24_activate(clear, sync);
break;
case 0x00B:
mapperSync = sync_UNROM512;
Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL);
break;
case 0x00C: case 0x00D: case 0x10C: case 0x10D:
mapperSync = sync_GNROM;
Latch_activate(clear, sync, 0x8000, 0xFFFF, NULL);
break;
case 0x00E: case 0x10E:
mapperSync = sync_Nanjing;
GameHBIRQHook = Nanjing_scanline;
SetWriteHandler(0x5000, 0x53FF, Nanjing_writeReg);
if (clear) Custom_reg[0] = Custom_reg[1] = Custom_reg[2] = Custom_reg[3] = 0;
sync();
break;
case 0x100: case 0x101:
mapperSync = sync_TxROM;
previousMirroring = MMC3_getMirroring();
MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, NULL);
MMC3_writeReg(0xA000, previousMirroring);
break;
case 0x102:
mapperSync = sync_TxSROM;
MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, NULL);
break;
case 0x200:
mapperSync = sync_VRC24;
VRC2_activate(clear, sync, 0x05, 0x0A, NULL, NULL, NULL, NULL);
break;
case 0x201:
mapperSync = sync_VRC24;
VRC4_activate(clear, sync, 0x05, 0x0A, 1, NULL, NULL, NULL, NULL, NULL);
break;
case 0x202:
mapperSync = sync_VRC24;
VRC2_activate(clear, sync, 0x0A, 0x05, NULL, NULL, NULL, NULL);
break;
case 0x203:
mapperSync = sync_VRC24;
VRC4_activate(clear, sync, 0x0A, 0x05, 1, NULL, NULL, NULL, NULL, NULL);
break;
case 0x300: case 0x301:
mapperSync = sync_VRC6;
VRC6_activate(clear, sync, 0x01, 0x02, NULL, NULL, NULL, NULL);
break;
case 0x400:
mapperSync = sync_VRC1;
VRC1_activate(clear, sync);
break;
case 0x401:
mapperSync = sync_VRC7;
VRC7_activate(clear, sync, 0x18);
break;
case 0x404:
mapperSync = sync_VRC3;
VRC3_activate(clear, sync);
break;
case 0x500:
mapperSync = sync_FME7;
FME7_activate(clear, sync);
break;
default:
break;
}
}
static void reset(void) {
mapper =submapper <<4;
mapperFlags =0x0F;
misc =0;
misc2 =0;
prgOR =0x7FF0;
eep_clock =command =output =1;
command =state =0;
setMapper(1);
static void power () {
reg[0] = 0x0F;
reg[1] = 0xFF;
reg[2] = submapper == 1? 0x10: 0x00;
reg[3] = 0x00;
eep_clock = command = output = 1;
command = state = 0;
applyMode(1);
}
static void power(void) {
int i;
for (i =0; i <16; i++) eeprom[i] =0;
reset();
static void stateRestore (int version) {
applyMode(0);
}
static void close(void) {
if (WRAM)
FCEU_gfree(WRAM);
WRAM = NULL;
}
static void stateRestore(int version) {
setMapper(0);
}
void Mapper468_Init(CartInfo *info) {
submapper =info->submapper;
info->Reset =reset;
info->Power =power;
info->Close =close;
GameStateRestore =stateRestore;
WRAMSIZE =8192;
WRAM =(uint8*) FCEU_gmalloc(WRAMSIZE);
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
void Mapper468_Init (CartInfo *info) {
submapper = info->submapper;
FME7_addExState();
Latch_addExState();
MMC1_addExState();
MMC24_addExState();
MMC3_addExState();
VRC1_addExState();
VRC24_addExState();
VRC3_addExState();
VRC6_addExState();
VRC7_addExState();
WRAM_init(info, 8);
info->Reset = power;
info->Power = power;
GameStateRestore = stateRestore;
AddExState(stateRegs, ~0, 0, 0);
prevSFEXINDEX =SFEXINDEX;
}

View File

@@ -1,45 +0,0 @@
#define CNROM_reg regByte
static void CNROM_sync () {
int OR =prgOR >>1;
if (mapperFlags &2) {
setprg16(0x8000, CNROM_reg[2] <<1 &0xE | mapperFlags &1 | OR &~0xF);
setprg16(0xC000, CNROM_reg[2] <<1 &0xE | mapperFlags &1 | OR &~0xF);
setchr8(CNROM_reg[0] &0x03);
} else {
OR >>=1;
setprg32(0x8000, CNROM_reg[2] &0x7 | OR &~0x7);
setchr8(CNROM_reg[0] &0x0F);
}
if (mapperFlags &8)
setmirror(mapperFlags &0x04? MI_H: MI_V);
else
setmirror(CNROM_reg[1] &0x10? MI_1: MI_0);
}
static DECLFW(CNROM_writeReg) {
switch(A &0xE000) {
case 0x8000: case 0xA000:
CNROM_reg[0] =V;
break;
case 0xE000:
CNROM_reg[2] =V;
break;
}
sync();
}
static DECLFW(BF9097_writeMirroring) {
CNROM_reg[1] =V;
sync();
}
void CNROM_BF9097_reset(uint8 clearRegs) { /* This strange mapper is used for both (C)NROM games and FireHawk. What an absurd combination!*/
sync =CNROM_sync;
SetWriteHandler(0x8000, 0xFFFF, CNROM_writeReg);
if (~mapperFlags &8)
SetWriteHandler(0x9000, 0x9FFF, BF9097_writeMirroring);
sync();
}
#undef CNROM_reg

View File

@@ -1,73 +0,0 @@
#define latch regByte[0]
static void ANROM_sync () {
int AND =prgAND >>2;
int OR =prgOR >>2;
setprg32(0x8000, latch &AND | OR &~AND);
setchr8(0);
setmirror(latch &0x10? MI_1: MI_0);
}
static void BNROM_sync () {
int AND =prgAND >>2;
int OR =prgOR >>2;
setprg32(0x8000, latch &AND | OR &~AND);
setchr8(0);
setmirror(mapperFlags &4? MI_H: MI_V);
}
static void GNROM_sync () {
int AND =prgAND >>2;
int OR =prgOR >>2 | (mapperFlags &4? 2: 0);
setprg32(0x8000, latch >>4 &AND | OR &~AND);
setchr8(latch &0x0F);
setmirror(mapper &1? MI_H: MI_V);
}
static void UNROM_sync () {
int AND =prgAND >>1;
int OR =prgOR >>1;
setprg16(0x8000, latch &AND | OR &~AND);
setprg16(0xC000, 0xFF &AND | OR &~AND);
setchr8(0);
setmirror(mapperFlags &4? MI_H: MI_V);
}
static DECLFW(DISCRETE_writeLatch) {
latch =V;
sync();
}
static DECLFW(Portopia_writeLatch) {
DISCRETE_writeLatch(A, A ==0xA000 && V ==0x00? 0x06: V); /* Strange hack, needed to get #282 "Portopia Serial Murder Case" on 852-in-1 running */
}
static DECLFW(ColorDreams_writeLatch) {
DISCRETE_writeLatch(A, V >>4 &0xF | V <<4 &0xF0); /* Sswap nibbles to mimic GNROM */
}
void ANROM_BNROM_reset(uint8 clearRegs) {
sync =mapperFlags &8? BNROM_sync: ANROM_sync;
prgAND =(mapper ==0x06 || mapper ==0x16)? 0x3F: mapperFlags &2? 0x0F: 0x1F;
SetWriteHandler(0x8000, 0xFFFF, DISCRETE_writeLatch);
latch =0;
sync();
}
void GNROM_reset(uint8 clearRegs) {
sync =GNROM_sync;
prgAND =mapperFlags &8? 0x07: 0x0F;
SetWriteHandler(0x8000, 0xFFFF, misc &0x10 && mapper &~0x10? DISCRETE_writeLatch: ColorDreams_writeLatch);
latch =0;
sync();
}
void UNROM_reset(uint8 clearRegs) {
sync =UNROM_sync;
prgAND =mapper ==0x0B || misc2 &0x10? 0x3F: mapperFlags &2? 0x0F: 0x1F;
SetWriteHandler(0x8000, 0xFFFF, mapper ==0x09 && mapperFlags ==0xE? Portopia_writeLatch: DISCRETE_writeLatch);
sync();
}
#undef latch

View File

@@ -1,72 +0,0 @@
#define FME7_reg regByte
#define FME7_index regByte[15]
#define FME7_counter regWord[0]
static void FME7_sync() {
int AND =mapperFlags &8? 0xFF: 0x7F;
switch(FME7_reg[8] &0xC0) {
case 0x00: case 0x80:
setprg8(0x6000, FME7_reg[0x8] &prgAND | prgOR &~prgAND);
break;
case 0x40:
/* Open Bus */
break;
case 0xC0:
setprg8r(0x10, 0x6000, 0);
break;
}
setprg8(0x8000, FME7_reg[0x9] &prgAND | prgOR &~prgAND);
setprg8(0xA000, FME7_reg[0xA] &prgAND | prgOR &~prgAND);
setprg8(0xC000, FME7_reg[0xB] &prgAND | prgOR &~prgAND);
setprg8(0xE000, prgAND | prgOR &~prgAND);
setchr1(0x0000, FME7_reg[0x0] &AND);
setchr1(0x0400, FME7_reg[0x1] &AND);
setchr1(0x0800, FME7_reg[0x2] &AND);
setchr1(0x0C00, FME7_reg[0x3] &AND);
setchr1(0x1000, FME7_reg[0x4] &AND);
setchr1(0x1400, FME7_reg[0x5] &AND);
setchr1(0x1800, FME7_reg[0x6] &AND);
setchr1(0x1C00, FME7_reg[0x7] &AND);
setmirror(FME7_reg[0xC] &3 ^(FME7_reg[0xC] &2? 0: 1));
}
static DECLFW(FME7_writeIndex) {
FME7_index =V &0xF;
}
static DECLFW(FME7_writeReg) {
switch(FME7_index) {
case 0xE:
FME7_counter =FME7_counter &0xFF00 |V;
break;
case 0xF:
FME7_counter =FME7_counter &0x00FF |V <<8;
break;
case 0xD:
X6502_IRQEnd(FCEU_IQEXT);
/* Falling through */
default:
FME7_reg[FME7_index] =V;
sync();
}
}
static void FP_FASTAPASS(1) FME7_cpuCycle(int a) {
while (a--) {
if (FME7_reg[0xD] &0x80 && !--FME7_counter && FME7_reg[0xD] &0x01) X6502_IRQBegin(FCEU_IQEXT);
}
}
void FME7_reset(uint8 clearRegs) {
sync =FME7_sync;
prgAND =mapperFlags &2? 0x0F: 0x1F;
MapIRQHook =FME7_cpuCycle;
SetWriteHandler(0x8000, 0x9FFF, FME7_writeIndex);
SetWriteHandler(0xA000, 0xBFFF, FME7_writeReg);
sync();
}
#undef FME7_reg
#undef FME7_index
#undef FME7_counter

View File

@@ -1,31 +0,0 @@
#define IF12_reg regByte
static void IF12_sync () {
int AND =prgAND >>1;
int OR =prgOR >>1;
setprg16(0x8000, IF12_reg[1] &AND | OR &~AND);
setprg16(0xC000, 0xFF &AND | OR &~AND);
setchr8(IF12_reg[0] >>1 &0xF);
setmirror(IF12_reg[0] &1? MI_H: MI_V);
}
static DECLFW(IF12_writeReg) {
IF12_reg[A >>14 &1] =V;
sync();
}
void IF12_reset(uint8 clearRegs) {
sync =IF12_sync;
prgAND =mapperFlags &2? 0x0F: 0x1F;
SetWriteHandler(0x8000, 0xFFFF, IF12_writeReg);
sync();
}
void UNROM_IF12_reset(uint8 clearRegs) {
if (mapperFlags &8)
UNROM_reset(clearRegs);
else
IF12_reset(clearRegs);
}
#undef IF12_reg

View File

@@ -1,46 +0,0 @@
#define LF36_prg regByte[0]
#define LF36_irq regByte[1]
#define LF36_counter regWord[0]
static void LF36_sync () {
int OR =prgOR | mapperFlags &0x08;
setprg8(0x8000, 0x04 | OR);
setprg8(0xA000, 0x05 | OR);
setprg8(0xC000, LF36_prg &0x07 | OR);
setprg8(0xE000, 0x07 | OR);
setchr8(0);
setmirror(mapperFlags &4? MI_H: MI_V);
}
static DECLFW(LF36_writeReg) {
switch (A &0xE000) {
case 0x8000: LF36_irq =0; break;
case 0xA000: LF36_irq =1; break;
case 0XE000: LF36_prg =V; sync(); break;
}
}
static void FP_FASTAPASS(1) LF36_cpuCycle(int a) {
while (a--) {
if (LF36_irq) {
if (++LF36_counter &0x1000)
X6502_IRQBegin(FCEU_IQEXT);
else
X6502_IRQEnd(FCEU_IQEXT);
} else {
X6502_IRQEnd(FCEU_IQEXT);
LF36_counter =0;
}
}
}
void LF36_reset(uint8 clearRegs) {
sync =LF36_sync;
MapIRQHook =LF36_cpuCycle;
SetWriteHandler(0x8000, 0xFFFF, LF36_writeReg);
sync();
}
#undef LF36_prg
#undef LF36_irq
#undef LF36_counter

View File

@@ -1,72 +0,0 @@
#define MMC1_reg regByte
#define MMC1_control regByte[0]
#define MMC1_chr0 regByte[1]
#define MMC1_chr1 regByte[2]
#define MMC1_prg regByte[3]
#define MMC1_shift regByte[4]
#define MMC1_count regByte[5]
#define MMC1_filter regByte[6]
static void MMC1_sync () {
int AND =prgAND >>1;
int OR =prgOR >>1 | (mapper &0x01? (MMC1_chr0 &0x10): (mapperFlags &0x06));
if (MMC1_control &0x08) { /* 16 KiB mode */
if (MMC1_control &0x04) { /* OR logic */
setprg16(0x8000, MMC1_prg &AND | OR &~AND);
setprg16(0xC000, 0xFF &AND | OR &~AND);
} else { /* AND logic */
setprg16(0x8000, 0 &AND | OR &~AND);
setprg16(0xC000, MMC1_prg &AND | OR &~AND);
}
} else
setprg32(0x8000, (MMC1_prg &AND | OR &~AND) >>1);
AND =mapper &0x01? 0x0F: 0x1F; /* SUROM needs to have the upper PRG bank bit, which is in the CHR registers, masked off */
if (MMC1_control &0x10) { /* 4 KiB mode */
setchr4(0x0000, MMC1_chr0 &AND);
setchr4(0x1000, MMC1_chr1 &AND);
} else /* 8 KiB mode */
setchr8(MMC1_chr0 >>1 &(AND >>1));
setmirror(MMC1_control &2? (MMC1_control &1? MI_H: MI_V): (MMC1_control &1? MI_1: MI_0));
}
static DECLFW(MMC1_writeReg) {
if (V &0x80) {
MMC1_shift =MMC1_count =0;
MMC1_control |=0x0C;
sync();
} else
if (!MMC1_filter) {
MMC1_shift |=(V &1) <<MMC1_count++;
if (MMC1_count ==5) {
MMC1_reg[A >>13 &3] =MMC1_shift;
MMC1_count =0;
MMC1_shift =0;
sync();
}
}
MMC1_filter =2;
}
static void FP_FASTAPASS(1) MMC1_cpuCycle(int a) {
while (a--) if (MMC1_filter) MMC1_filter--;
}
void MMC1_reset(uint8 clearRegs) {
sync =MMC1_sync;
MapIRQHook =MMC1_cpuCycle;
prgAND =mapperFlags &2? (mapperFlags &8? 0x07: 0x0F): 0x1F;
SetWriteHandler(0x8000, 0xFFFF, MMC1_writeReg);
if (clearRegs) MMC1_control =0x0C;
sync();
}
#undef MMC1_reg
#undef MMC1_control
#undef MMC1_chr0
#undef MMC1_chr1
#undef MMC1_prg
#undef MMC1_shift
#undef MMC1_count
#undef MMC1_filter

View File

@@ -1,67 +0,0 @@
#define MMC24_reg regByte
static void MMC2_sync() {
setprg8(0x8000, MMC24_reg[0] &prgAND | prgOR &~prgAND);
setprg8(0xA000, 0xFD &prgAND | prgOR &~prgAND);
setprg8(0xC000, 0xFE &prgAND | prgOR &~prgAND);
setprg8(0xE000, 0xFF &prgAND | prgOR &~prgAND);
setchr4(0x0000, MMC24_reg[1 +MMC24_reg[6]]);
setchr4(0x1000, MMC24_reg[3 +MMC24_reg[7]]);
setmirror(MMC24_reg[5] &1? MI_H: MI_V);
}
static void MMC4_sync() {
int AND =prgAND >>1;
int OR =prgOR >>1;
setprg16(0x8000, MMC24_reg[0] &AND | OR &~AND);
setprg16(0xC000, 0xFF &AND | OR &~AND);
setchr4(0x0000, MMC24_reg[1 +MMC24_reg[6]]);
setchr4(0x1000, MMC24_reg[3 +MMC24_reg[7]]);
setmirror(MMC24_reg[5] &1? MI_H: MI_V);
}
static DECLFW(MMC24_writeReg) {
MMC24_reg[(A >>12) -0xA] =V;
sync();
}
static void FP_FASTAPASS(1) MMC24_ppuHook(uint32 A) {
uint8 l, h = A >> 8;
if (h >= 0x20 || ((h & 0xF) != 0xF)) return;
l = A & 0xF0;
if (h < 0x10) {
if (l == 0xD0) {
MMC24_reg[6] =0;
sync();
} else if (l == 0xE0) {
MMC24_reg[6] =1;
sync();
}
} else {
if (l == 0xD0) {
MMC24_reg[7] =0;
sync();
} else if (l == 0xE0) {
MMC24_reg[7] =1;
sync();
}
}
}
void MMC2_reset(uint8 clearRegs) {
sync =MMC2_sync;
prgAND =0x0F;
PPU_hook =MMC24_ppuHook;
SetWriteHandler(0xA000, 0xFFFF, MMC24_writeReg);
sync();
}
void MMC4_reset(uint8 clearRegs) {
sync =MMC4_sync;
prgAND =mapperFlags &2? 0x0F: 0x1F;
PPU_hook =MMC24_ppuHook;
SetWriteHandler(0xA000, 0xFFFF, MMC24_writeReg);
sync();
}
#undef MMC24_reg

View File

@@ -1,80 +0,0 @@
#define MMC3_reg regByte
#define MMC3_index regByte[8]
#define MMC3_mirroring regByte[9]
#define MMC3_wram regByte[10]
#define MMC3_reload regByte[11]
#define MMC3_count regByte[12]
#define MMC3_irq regByte[13]
#define MMC3_lastReg regByte[14]
static void MMC3_sync () {
int chrAND =mapper &0x01? 0xFF: 0x7F;
int OR =prgOR | (misc2 &1? 12: 0);
setprg8(0x8000 ^(MMC3_index <<8 &0x4000), MMC3_reg[6] &prgAND | OR &~prgAND);
setprg8(0xA000, MMC3_reg[7] &prgAND | OR &~prgAND);
setprg8(0xC000 ^(MMC3_index <<8 &0x4000), 0xFE &prgAND | OR &~prgAND);
setprg8(0xE000, 0xFF &prgAND | OR &~prgAND);
setchr1(0x0000 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] &0xFE)&chrAND);
setchr1(0x0400 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] |0x01)&chrAND);
setchr1(0x0800 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] &0xFE)&chrAND);
setchr1(0x0C00 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] |0x01)&chrAND);
setchr1(0x1000 ^(MMC3_index <<5 &0x1000), MMC3_reg[2] &chrAND);
setchr1(0x1400 ^(MMC3_index <<5 &0x1000), MMC3_reg[3] &chrAND);
setchr1(0x1800 ^(MMC3_index <<5 &0x1000), MMC3_reg[4] &chrAND);
setchr1(0x1C00 ^(MMC3_index <<5 &0x1000), MMC3_reg[5] &chrAND);
if (mapper &2) switch(MMC3_mirroring &3) {
case 0: setmirror(MI_V); break;
case 1: setmirror(MI_H); break;
case 2: setmirror(MMC3_reg[MMC3_lastReg] &0x80? MI_1: MI_0); break;
case 3: setmirror(MI_1); break;
} else
setmirror(MMC3_mirroring &1? MI_H: MI_V);
}
static DECLFW(MMC3_writeReg) {
switch(A &0xE001) {
case 0x8000: MMC3_index =V; sync(); break;
case 0x8001: MMC3_reg[MMC3_index &7] =V; sync(); break;
case 0xA000: MMC3_mirroring =V; sync(); break;
case 0xA001: MMC3_wram =V; sync(); break;
case 0xC000: MMC3_reload =V; break;
case 0xC001: MMC3_count =0; break;
case 0xE000: MMC3_irq =0; X6502_IRQEnd(FCEU_IQEXT); break;
case 0xE001: MMC3_irq =1; break;
}
}
static void MMC3_horizontalBlanking(void) {
MMC3_count =!MMC3_count? MMC3_reload: --MMC3_count;
if (!MMC3_count && MMC3_irq) X6502_IRQBegin(FCEU_IQEXT);
}
static void FP_FASTAPASS(1) MMC3_ppuHook(uint32 A) {
A &=0x1FFF;
if (MMC3_index &0x80) A ^=0x1000;
if (A <0x1000)
MMC3_lastReg =A >>11;
else
MMC3_lastReg =(A >>10) -2;
if ((MMC3_mirroring &3) ==2) setmirror(MMC3_reg[MMC3_lastReg] &0x80? MI_1: MI_0);
}
void MMC3_reset(uint8 clearRegs) {
sync =MMC3_sync;
GameHBIRQHook =MMC3_horizontalBlanking;
if (mapper &2) PPU_hook =MMC3_ppuHook;
prgAND =mapperFlags &8? (mapperFlags &4? (mapperFlags &2? (misc2 &2? 0x07: 0x0F): 0x1F): 0x3F): 0x7F;
SetWriteHandler(0x8000, 0xFFFF, MMC3_writeReg);
MMC3_mirroring =1; /* "Legendary Games of NES' 509-in-1"'s menu runs as MMC3 with H mirroring and expects that setting to stay when running a mapper 206 game such as Legend of Valkyrie. */
sync();
}
#undef MMC3_reg
#undef MMC3_index
#undef MMC3_mirroring
#undef MMC3_wram
#undef MMC3_reload
#undef MMC3_count
#undef MMC3_irq
#undef MMC3_lastReg

View File

@@ -1,29 +0,0 @@
#define NANJING_reg regByte
static void NANJING_sync () {
setprg32(0x8000, NANJING_reg[2] <<4 &0x30 | NANJING_reg[0] &0x0F | (NANJING_reg[3] &4? 0x00: 0x03) | prgOR >>2);
setchr8(0);
setmirror(mapperFlags &4? MI_H: MI_V);
}
static DECLFW(NANJING_writeReg) {
NANJING_reg[A >>8 &3] =V;
sync();
}
static void NANJING_horizontalBlanking(void) {
if (NANJING_reg[0] &0x80 && scanline <239) { /* Actual hardware cannot look at the current scanline number, but instead latches PA09 on PA13 rises. This does not seem possible with the current PPU emulation however. */
setchr4(0x0000, scanline >=127? 1: 0);
setchr4(0x1000, scanline >=127? 1: 0);
} else
setchr8(0);
}
void NANJING_reset(uint8 clearRegs) {
sync =NANJING_sync;
GameHBIRQHook = NANJING_horizontalBlanking;
SetWriteHandler(0x5000, 0x53FF, NANJING_writeReg);
sync();
}
#undef NANJING_reg

View File

@@ -1,25 +0,0 @@
#define VRC1_reg regByte
static void VRC1_sync () {
setprg8(0x8000, VRC1_reg[0] &prgAND | prgOR &~prgAND);
setprg8(0xA000, VRC1_reg[2] &prgAND | prgOR &~prgAND);
setprg8(0xC000, VRC1_reg[4] &prgAND | prgOR &~prgAND);
setprg8(0xE000, 0xFF &prgAND | prgOR &~prgAND);
setchr4(0x0000, VRC1_reg[6] &0x0F | VRC1_reg[1] <<3 &0x10);
setchr4(0x1000, VRC1_reg[7] &0x0F | VRC1_reg[1] <<2 &0x10);
setmirror(VRC1_reg[1] &1? MI_H: MI_V);
}
static DECLFW(VRC1_writeReg) {
VRC1_reg[A >>12 &7] =V;
sync();
}
void VRC1_reset(uint8 clearRegs) {
sync =VRC1_sync;
prgAND =mapperFlags &8? (mapperFlags &4? (mapperFlags &2? 0x0F: 0x1F): 0x3F): 0x7F;
SetWriteHandler(0x8000, 0xFFFF, VRC1_writeReg);
sync();
}
#undef VRC1_reg

View File

@@ -1,92 +0,0 @@
#define VRC24_prg regByte
#define VRC24_mirroring regByte[2]
#define VRC24_misc regByte[3]
#define VRC24_chr regWord
#define VRCIRQ_latch regByte[13]
#define VRCIRQ_mode regByte[14]
#define VRCIRQ_count regByte[15]
#define VRCIRQ_cycles regWord[8]
static void VRC24_sync() {
setprg8(0x8000 ^(VRC24_misc <<13 &0x4000), VRC24_prg[0] &prgAND | prgOR &~prgAND);
setprg8(0xA000, VRC24_prg[1] &prgAND | prgOR &~prgAND);
setprg8(0xC000 ^(VRC24_misc <<13 &0x4000), 0xFE &prgAND | prgOR &~prgAND);
setprg8(0xE000, 0xFF &prgAND | prgOR &~prgAND);
setchr1(0x0000, VRC24_chr[0]);
setchr1(0x0400, VRC24_chr[1]);
setchr1(0x0800, VRC24_chr[2]);
setchr1(0x0C00, VRC24_chr[3]);
setchr1(0x1000, VRC24_chr[4]);
setchr1(0x1400, VRC24_chr[5]);
setchr1(0x1800, VRC24_chr[6]);
setchr1(0x1C00, VRC24_chr[7]);
setmirror(VRC24_mirroring &3 ^(VRC24_mirroring &2? 0: 1));
}
static DECLFW(VRC24_writeReg) {
uint8 index;
A =A &0xF000 | (mapper &2? ((A &0xA? 1: 0) | (A &0x5? 2: 0)): ((A &0x5? 1: 0) | (A &0xA? 2: 0)));
switch (A &0xF000) {
case 0x8000: case 0xA000:
VRC24_prg[A >>13 &1] =V;
sync();
break;
case 0x9000:
if (~A &2)
VRC24_mirroring =V & (mapper &1? 3: 1);
else
if (~A &1 && mapper &1)
VRC24_misc =V;
sync();
break;
case 0xF000:
if (mapper &1) switch (A &3) {
case 0: VRCIRQ_latch =VRCIRQ_latch &0xF0 | V &0x0F; break;
case 1: VRCIRQ_latch =VRCIRQ_latch &0x0F | V <<4; break;
case 2: VRCIRQ_mode =V;
if (VRCIRQ_mode &0x02) {
VRCIRQ_count =VRCIRQ_latch;
VRCIRQ_cycles =341;
}
X6502_IRQEnd(FCEU_IQEXT);
break;
case 3: VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02;
X6502_IRQEnd(FCEU_IQEXT);
break;
}
break;
default:
index =(A -0xB000) >>11 | A >>1 &1;
if (A &1)
VRC24_chr[index] =VRC24_chr[index] & 0x0F | V <<4;
else
VRC24_chr[index] =VRC24_chr[index] &~0x0F | V &0x0F;
sync();
break;
}
}
static void FP_FASTAPASS(1) VRCIRQ_cpuCycle(int a) {
while (a--) {
if (VRCIRQ_mode &0x02 && (VRCIRQ_mode &0x04 || (VRCIRQ_cycles -=3) <=0)) {
if (~VRCIRQ_mode &0x04) VRCIRQ_cycles +=341;
if (!++VRCIRQ_count) {
VRCIRQ_count =VRCIRQ_latch;
X6502_IRQBegin(FCEU_IQEXT);
}
}
}
}
void VRC24_reset(uint8 clearRegs) {
sync =VRC24_sync;
prgAND =mapperFlags &2? 0x0F: 0x1F;
if (mapper &1) MapIRQHook =VRCIRQ_cpuCycle;
SetWriteHandler(0x8000, 0xFFFF, VRC24_writeReg);
sync();
}
#undef VRC24_prg
#undef VRC24_mirroring
#undef VRC24_misc
#undef VRC24_chr

View File

@@ -1,63 +0,0 @@
#define VRC3_prg regByte[0]
#define VRC3_latch regWord[0]
#define VRC3_mode regByte[1]
#define VRC3_count regWord[1]
static void VRC3_sync() {
int AND =prgAND >>1;
int OR =prgOR >>1;
setprg16(0x8000, VRC3_prg &AND | OR &~AND);
setprg16(0xC000, AND | OR &~AND);
setchr8(0);
setmirror(mapperFlags &4? MI_H: MI_V);
}
static DECLFW(VRC3_writeReg) {
int shift;
switch(A &0xF000) {
case 0x8000: case 0x9000: case 0xA000: case 0xB000:
V &=0xF;
shift =A >>10 &0xC;
VRC3_latch =VRC3_latch &~(0xF <<shift) | V <<shift;
break;
case 0xC000:
VRC3_mode =V;
if (VRC3_mode &0x02) VRC3_count =VRC3_latch;
X6502_IRQEnd(FCEU_IQEXT);
break;
case 0xD000:
VRC3_mode =VRC3_mode &~0x02 | VRC3_mode <<1 &0x02;
X6502_IRQEnd(FCEU_IQEXT);
break;
case 0xF000:
VRC3_prg =V;
sync();
break;
}
}
static void FP_FASTAPASS(1) VRC3_cpuCycle(int a) {
while (a--) {
int mask =VRC3_mode &0x04? 0xFF: 0xFFFF;
if (VRC3_mode &0x02) {
if ((VRC3_count &mask) ==mask) {
VRC3_count =VRC3_latch;
X6502_IRQBegin(FCEU_IQEXT);
} else
++VRC3_count;
}
}
}
void VRC3_reset(uint8 clearRegs) {
sync =VRC3_sync;
prgAND =0x0F;
MapIRQHook =VRC3_cpuCycle;
SetWriteHandler(0x8000, 0xFFFF, VRC3_writeReg);
sync();
}
#undef VRC3_prg
#undef VRC3_latch
#undef VRC3_mode
#undef VRC3_count

View File

@@ -1,72 +0,0 @@
#define VRC6_chr regByte
#define VRC6_prg16 regByte[8]
#define VRC6_prg8 regByte[9]
#define VRC6_misc regByte[10]
static void VRC6_sync() {
int AND =prgAND >>1;
int OR =prgOR >>1;
setprg16(0x8000, VRC6_prg16 & AND | OR & ~AND);
setprg8(0xC000, VRC6_prg8 &prgAND | prgOR &~prgAND);
setprg8(0xE000, prgAND | prgOR &~prgAND);
setchr1(0x0000, VRC6_chr[0]);
setchr1(0x0400, VRC6_chr[1]);
setchr1(0x0800, VRC6_chr[2]);
setchr1(0x0C00, VRC6_chr[3]);
setchr1(0x1000, VRC6_chr[4]);
setchr1(0x1400, VRC6_chr[5]);
setchr1(0x1800, VRC6_chr[6]);
setchr1(0x1C00, VRC6_chr[7]);
setmirror((VRC6_misc &0xC ^(VRC6_misc &0x8? 0: 0x4)) >>2);
}
static DECLFW(VRC6_writeReg) {
uint8 index;
switch (A &0xF003) {
case 0x8000: case 0x8001: case 0x8002: case 0x8003:
VRC6_prg16 =V;
sync();
break;
case 0xB003:
VRC6_misc =V;
sync();
break;
case 0xC000: case 0xC001: case 0xC002: case 0xC003:
VRC6_prg8 =V;
sync();
break;
case 0xD000: case 0xD001: case 0xD002: case 0xD003: case 0xE000: case 0xE001: case 0xE002: case 0xE003:
index =(A -0xD000) >>10 | A &3;
VRC6_chr[index] =V;
sync();
break;
case 0xF000:
VRCIRQ_latch =V;
break;
case 0xF001:
VRCIRQ_mode =V;
if (VRCIRQ_mode &0x02) {
VRCIRQ_count =VRCIRQ_latch;
VRCIRQ_cycles =341;
}
X6502_IRQEnd(FCEU_IQEXT);
break;
case 0xF002:
VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02;
X6502_IRQEnd(FCEU_IQEXT);
break;
}
}
void VRC6_reset(uint8 clearRegs) {
sync =VRC6_sync;
prgAND =mapperFlags &2? 0x0F: 0x1F;
MapIRQHook =VRCIRQ_cpuCycle;
SetWriteHandler(0x8000, 0xFFFF, VRC6_writeReg);
sync();
}
#undef VRC6_chr
#undef VRC6_prg16
#undef VRC6_prg8
#undef VRC6_misc

View File

@@ -1,82 +0,0 @@
#define VRC7_chr regByte
#define VRC7_prg0 regByte[8]
#define VRC7_prg1 regByte[9]
#define VRC7_prg2 regByte[10]
#define VRC7_misc regByte[11]
static void VRC7_sync() {
setprg8(0x8000, VRC7_prg0 &prgAND | prgOR &~prgAND);
setprg8(0xA000, VRC7_prg1 &prgAND | prgOR &~prgAND);
setprg8(0xC000, VRC7_prg2 &prgAND | prgOR &~prgAND);
setprg8(0xE000, prgAND | prgOR &~prgAND);
setchr1(0x0000, VRC7_chr[0]);
setchr1(0x0400, VRC7_chr[1]);
setchr1(0x0800, VRC7_chr[2]);
setchr1(0x0C00, VRC7_chr[3]);
setchr1(0x1000, VRC7_chr[4]);
setchr1(0x1400, VRC7_chr[5]);
setchr1(0x1800, VRC7_chr[6]);
setchr1(0x1C00, VRC7_chr[7]);
setmirror(VRC7_misc &3 ^(VRC7_misc &2? 0: 1));
}
static DECLFW(VRC7_writeReg) {
uint8 index;
A =A &0xF000 | (A &0x18? 1: 0) | (A &0x20? 2: 0);
switch (A &0xF003) {
case 0x8000:
VRC7_prg0 =V;
sync();
break;
case 0x8001:
VRC7_prg1 =V;
sync();
break;
case 0x9000:
VRC7_prg2 =V;
sync();
break;
case 0x9001: case 0x9002:
/* sound */
break;
case 0xA000: case 0xA001: case 0xB000: case 0xB001: case 0xC000: case 0xC001: case 0xD000: case 0xD001:
index =(A -0xA000) >>11 | A &1;
VRC7_chr[index] =V;
sync();
break;
case 0xE000:
VRC7_misc =V;
sync();
break;
case 0xE001:
VRCIRQ_latch =V;
break;
case 0xF000:
VRCIRQ_mode =V;
if (VRCIRQ_mode &0x02) {
VRCIRQ_count =VRCIRQ_latch;
VRCIRQ_cycles =341;
}
X6502_IRQEnd(FCEU_IQEXT);
break;
case 0xF001:
VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02;
X6502_IRQEnd(FCEU_IQEXT);
break;
}
}
void VRC7_reset(uint8 clearRegs) {
sync =VRC7_sync;
prgAND =mapperFlags &8? (mapperFlags &4? (mapperFlags &2? 0x0F: 0x1F): 0x3F): 0x7F;
MapIRQHook =VRCIRQ_cpuCycle;
SetWriteHandler(0x8000, 0xFFFF, VRC7_writeReg);
sync();
}
#undef VRC7_chr
#undef VRC7_prg0
#undef VRC7_prg1
#undef VRC7_prg2
#undef VRC7_misc

80
src/boards/483.c Normal file
View File

@@ -0,0 +1,80 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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
*
*
*/
/* 3927 PCB, reset-based MMC1/CNROM multicart. The common dump with mapper number 3927 has an unrealistic bank order. */
#include "mapinc.h"
#include "asic_latch.h"
#include "asic_mmc1.h"
static uint8 game;
static void sync_SLROM () {
MMC1_syncPRG(0x07, game <<3);
MMC1_syncCHR(0x1F, game <<5);
MMC1_syncMirror();
}
static void sync_CNROM () {
setprg32(0x8000, 0x0C +game -3);
setchr8(0x30 | (game -3) <<2 | Latch_data &0x03);
setmirror(MI_V);
}
static void sync_SEROM () {
setprg32(0x8000, 0x0F);
MMC1_syncCHR(0x07, 0x78);
MMC1_syncMirror();
}
static void applyMode (uint8 clear) {
if (game <= 2)
MMC1_activate(clear, sync_SLROM, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL);
else
if (game <= 5)
Latch_activate(clear, sync_CNROM, 0x8000, 0xFFFF, NULL);
else
MMC1_activate(clear, sync_SEROM, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL);
}
static void reset () {
if (++game >=7) game = 0;
applyMode(1);
}
static void power () {
game = 0;
applyMode(1);
}
static void stateRestore (int version) {
applyMode(0);
}
void Mapper483_Init (CartInfo *info) {
AddExState(&game, 1, 0, "GAME");
Latch_addExState();
MMC1_addExState();
info->Power = power;
info->Reset = reset;
GameStateRestore = stateRestore;
}

43
src/boards/489.c Normal file
View File

@@ -0,0 +1,43 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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 "asic_latch.h"
static void sync () {
if ((Latch_data &0x1F) == 2)
setprg32(0x8000, Latch_data >>1);
else {
setprg16(0x8000, Latch_data);
setprg16(0xC000, Latch_data);
}
setchr8(Latch_data);
switch(Latch_data >>6) {
case 0: setmirrorw(0, 0, 0, 1); break;
case 1: setmirror(MI_V); break;
case 2: setmirror(MI_H); break;
case 3: setmirror(MI_1); break;
}
}
void Mapper489_Init (CartInfo *info) {
Latch_init(info, sync, 0x8000, 0xFFFF, NULL);
info->Reset = Latch_clear;
}

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

@@ -0,0 +1,68 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc3.h"
static uint8 reg;
static uint8 pad;
static DECLFR (readPad) {
return CartBR(A &~0xF | pad &0xF);
}
static void sync () {
if (reg &0x20)
setprg32(0x8000, reg >>1);
else {
setprg16(0x8000, reg);
setprg16(0xC000, reg);
}
MMC3_syncCHR(0xFF, reg <<4 &~0xFF);
MMC3_syncMirror();
SetReadHandler(0x8000, 0xFFFF, reg &0x80? readPad: CartBR);
}
static DECLFW (writeReg) {
reg = A &0xFF;
sync();
}
static void power () {
reg = 0;
pad = 0;
MMC3_power();
}
static void reset () {
reg = 0;
++pad;
MMC3_clear();
}
void Mapper490_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
AddExState(&pad, 1, 0, "DIPS");
}

37
src/boards/491.c Normal file
View File

@@ -0,0 +1,37 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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 "asic_latch.h"
static void sync () {
if (Latch_address &0x08) {
setprg16(0x8000, Latch_address);
setprg16(0xC000, Latch_address);
} else
setprg32(0x8000, Latch_address >>1);
setchr8(Latch_data);
setmirror(Latch_address &0x10? MI_H: MI_V);
}
void Mapper491_Init (CartInfo *info) {
Latch_init(info, sync, 0x8000, 0xFFFF, NULL);
info->Reset = Latch_clear;
}

38
src/boards/492.c Normal file
View File

@@ -0,0 +1,38 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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 "asic_latch.h"
static void sync () {
if (Latch_address &0x20)
setprg32(0x8000, Latch_address >>4);
else {
setprg16(0x8000, Latch_address >>3);
setprg16(0xC000, Latch_address >>3);
}
setchr8(Latch_address >>1 &0x03 | Latch_address >>2 &0x0C);
setmirror(Latch_address &0x01? MI_H: MI_V);
}
void Mapper492_Init (CartInfo *info) {
Latch_init(info, sync, 0x8000, 0xFFFF, NULL);
info->Reset = Latch_clear;
}

52
src/boards/493.c Normal file
View File

@@ -0,0 +1,52 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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"
static uint8 reg[2];
static void sync () {
setprg32(0x8000, reg[0] <<1 | reg[1] &0x01);
setchr8(reg[0] <<3 | reg[1] >>4 &0x07);
}
static DECLFW (writeReg) {
reg[A >>15 &1] = V;
sync();
}
static void power () {
SetReadHandler(0x6000, 0xFFFF, CartBR);
SetWriteHandler(0x6000, 0xFFFF, writeReg);
reg[0] = reg[1] = 0;
RAM[0x07] =0;
sync();
}
static void stateRestore (int version) {
sync();
}
void Mapper493_Init (CartInfo *info) {
info->Reset = power;
info->Power = power;
GameStateRestore = stateRestore;
AddExState(reg, 2, 0, "REGS");
}

61
src/boards/494.c Normal file
View File

@@ -0,0 +1,61 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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 "asic_latch.h"
static uint8 pad;
static DECLFR (readOB) {
return X.DB;
}
static void sync () {
if (Latch_address &0x100) {
if (Latch_address &0x001) {
setprg16(0x8000, Latch_address >>2);
setprg16(0xC000, Latch_address >>2);
} else
setprg32(0x8000, Latch_address >>3);
} else {
setprg16(0x8000, Latch_address >>2);
setprg16(0xC000, Latch_address >>2 |7);
}
setchr8(Latch_address >>5 &7 | Latch_address >>1 &8);
setmirror(Latch_address &0x002? MI_H: MI_V);
SetReadHandler(0x8000, 0xFFFF, ~Latch_address &0x100 && Latch_address &0x001 &pad? readOB: CartBR);
}
static void power () {
pad = 0;
Latch_power();
}
static void reset () {
pad++;
Latch_clear();
}
void Mapper494_Init (CartInfo *info) {
Latch_init(info, sync, 0x8000, 0xFFFF, NULL);
info->Power = power;
info->Reset = reset;
AddExState(&pad, 1, 0, "DIPS");
}

83
src/boards/495.c Normal file
View File

@@ -0,0 +1,83 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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"
static uint8 prg[3];
static uint8 chr[4];
static uint8 latch[2];
static SFORMAT stateRegs[] = {
{ prg, 3, "PRGR" },
{ chr, 4, "CHRR" },
{ latch, 2, "LATC" },
{ 0 }
};
static void sync () {
setprg8(0x8000, prg[0]);
setprg8(0xA000, prg[1]);
setprg8(0xC000, prg[2]);
setprg8(0xE000, 0xFF);
setchr4(0x0000, chr[0 | latch[0]]);
setchr4(0x1000, chr[2 | latch[1]]);
switch(chr[latch[0]] >>6) {
case 0: setmirrorw(0, 0, 0, 1); break;
case 1: setmirror(MI_H); break;
case 2: setmirror(MI_V); break;
case 3: setmirror(MI_1); break;
}
}
static void FP_FASTAPASS(1) trapPPUAddressChange (uint32 A) {
if ((A &0x2FF0) == 0xFD0 || (A &0x2FF0) == 0xFE0) {
latch[A >>12 &1] = ~A >>5 &1;
sync();
}
}
static DECLFW (writeReg) {
if (A <0xE000)
prg[A >>13 &3] = V;
else
chr[A >>10 &3] = V;
sync();
}
static void restore (int version) {
sync();
}
static void power () {
prg[0] = prg[1] = prg[2] = 0;
chr[0] = chr[1] = chr[2] = chr[3] = 0;
latch[0] = 0; latch[1] = 0;
sync();
SetReadHandler (0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x8000, 0xFFFF, writeReg);
PPU_hook = trapPPUAddressChange;
}
void Mapper495_Init (CartInfo *info) {
AddExState(stateRegs, ~0, 0, 0);
info->Power = power;
info->Reset = sync;
GameStateRestore = restore;
}

62
src/boards/498.c Normal file
View File

@@ -0,0 +1,62 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc1.h"
static uint8 reg;
static void sync () {
if (reg &0x20)
MMC1_syncPRG(0x07, reg &~0x07);
else
if (reg &0x04)
setprg32(0x8000, reg >>1);
else {
setprg16(0x8000, reg);
setprg16(0xC000, reg);
}
MMC1_syncCHR(0x1F, reg <<2 &~0x1F);
MMC1_syncMirror();
}
static DECLFW (writeReg) {
reg = A &0xFF;
sync();
}
static void reset () {
reg = 0;
MMC1_clear();
}
static void power () {
reg = 0;
MMC1_power();
}
void Mapper498_Init (CartInfo *info) {
MMC1_init(info, sync, MMC1_TYPE_MMC1A, NULL, NULL, NULL, writeReg);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
}

56
src/boards/499.c Normal file
View File

@@ -0,0 +1,56 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc1.h"
static uint8 reg;
static void sync () {
MMC1_syncPRG(0x07, reg <<3);
MMC1_syncCHR(0x1F, reg <<5);
MMC1_syncMirror();
}
static DECLFW (writeReg) {
if (~reg &8) {
reg = A &0xFF;
sync();
}
}
static void reset () {
reg = 0;
MMC1_clear();
}
static void power () {
reg = 0;
MMC1_power();
}
void Mapper499_Init (CartInfo *info) {
MMC1_init(info, sync, MMC1_TYPE_MMC1A, NULL, NULL, NULL, writeReg);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
}

67
src/boards/503.c Normal file
View File

@@ -0,0 +1,67 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc3.h"
static uint8 reg;
static uint8 pad;
static DECLFR (readPad) {
return CartBR(A &~3 | pad &3);
}
static void sync () {
if (reg &0x10)
setprg32(0x8000, reg >>1);
else {
setprg16(0x8000, reg);
setprg16(0xC000, reg);
}
MMC3_syncCHR(0x7F, reg <<4 &~0x7F);
MMC3_syncMirror();
SetReadHandler(0x8000, 0xFFFF, reg &0x20? readPad: CartBR);
}
static DECLFW (writeReg) {
reg = A &0xFF;
sync();
}
static void reset () {
reg = 0;
++pad;
MMC3_clear();
}
static void power () {
reg = 0;
pad = 0;
MMC3_power();
}
void Mapper503_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
}

65
src/boards/504.c Normal file
View File

@@ -0,0 +1,65 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc3.h"
static uint8 reg;
static void sync () {
int prgAND = reg &0x02? 0x0F: 0x1F;
int chrAND = reg &0x02? 0x7F: 0xFF;
int prgOR = reg <<4;
int chrOR = reg <<7;
MMC3_syncPRG(prgAND, prgOR &~prgAND);
MMC3_syncCHR(chrAND, chrOR &~chrAND);
MMC3_syncMirror();
}
static int getPRGBank (uint8 bank) {
if ((reg &0x03) == 0x03 && ~reg &0x08)
return MMC3_getPRGBank(bank &1) &~1 | bank &1;
else
return MMC3_getPRGBank(bank);
}
static DECLFW (writeReg) {
reg = A &0xFF;
sync();
}
static void reset () {
reg = 0;
MMC3_clear();
}
static void power () {
reg = 0;
MMC3_power();
}
void Mapper504_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, getPRGBank, NULL, NULL, writeReg);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
}

65
src/boards/505.c Normal file
View File

@@ -0,0 +1,65 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc3.h"
static uint16 reg;
static uint8 pad;
static void sync () {
if (reg &0x01)
MMC3_syncPRG(0x1F, reg &0x60);
else
setprg32(0x8000, reg >>2);
MMC3_syncCHR(reg &0x100? 0x7F: 0xFF, reg >>1 &0x100 | reg &0x080);
MMC3_syncMirror();
}
static DECLFR (readPad) {
return pad;
}
static DECLFW (writeReg) {
reg = A ^0x1C;
sync();
}
static void reset () {
reg = 0xFE;
pad++;
MMC3_clear();
}
static void power () {
reg = 0xFE;
pad = 0;
MMC3_power();
}
void Mapper505_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, readPad, writeReg);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 2 | FCEUSTATE_RLSB, 0, "EXPR");
AddExState(&pad, 1, 0, "DIPS");
}

58
src/boards/506.c Normal file
View File

@@ -0,0 +1,58 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc3.h"
static uint8 reg;
static void sync () {
int prgAND =~reg &3? 0x0F: 0x1F;
int chrAND = reg &3? 0x7F: 0xFF;
int prgOR = reg <<5 &0x20 | reg <<3 &0x10;
int chrOR = reg <<7 &0x100 |~reg <<7 &0x80;
MMC3_syncPRG(prgAND, prgOR &~prgAND);
MMC3_syncCHR(chrAND, chrOR &~chrAND);
MMC3_syncMirror();
}
static DECLFW (writeReg) {
reg = A &0xFF;
sync();
}
static void reset () {
reg = 0;
MMC3_clear();
}
static void power () {
reg = 0;
MMC3_power();
}
void Mapper506_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
}

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

@@ -0,0 +1,66 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc3.h"
static uint8 reg;
static uint8 pad;
static void sync () {
int prgAND = reg &0x20? 0x0F: 0x1F;
int chrAND = reg &0x20? 0x7F: 0xFF;
int prgOR = reg;
int chrOR = reg <<3;
MMC3_syncPRG(prgAND, prgOR &~prgAND);
MMC3_syncCHR(chrAND, chrOR &~chrAND);
MMC3_syncMirror();
}
static DECLFR (readPad) {
return pad;
}
static DECLFW (writeReg) {
reg = V;
sync();
}
static void reset () {
reg = 0;
pad ^= 0x80;
MMC3_clear();
}
static void power () {
reg = 0;
pad = 0;
MMC3_power();
}
void Mapper507_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, readPad, writeReg);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
AddExState(&pad, 1, 0, "DIPS");
}

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

@@ -0,0 +1,70 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc3.h"
static uint8 reg;
static uint8 pad;
static void sync () {
if (reg &0x80)
MMC3_syncPRG(0x1F, reg >>1 &~0x1F);
else
if (reg &0x20)
setprg32(0x8000, (reg &0x0F | reg >>2 &~0x0F) >>1);
else {
setprg16(0x8000, reg &0x0F | reg >>2 &~0x0F);
setprg16(0xC000, reg &0x0F | reg >>2 &~0x0F);
}
setchr8(0);
MMC3_syncMirror();
}
static DECLFR (readPad) {
return pad;
}
static DECLFW (writeReg) {
reg = V;
sync();
}
static void reset () {
reg = 0x0F;
pad++;
MMC3_clear();
}
static void power () {
reg = 0x0F;
pad = 0;
MMC3_power();
}
void Mapper508_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, readPad, writeReg);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
AddExState(&pad, 1, 0, "DIPS");
}

71
src/boards/509.c Normal file
View File

@@ -0,0 +1,71 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc3.h"
#include "cartram.h"
static uint8 reg;
static void sync () {
int prgAND = reg &0x10? 0x1F: 0x0F;
int chrAND = reg &0x10? 0xFF: 0x7F;
int prgOR = reg <<1;
int chrOR = reg <<4;
if (reg &0x20)
MMC3_syncPRG(prgAND, prgOR &~prgAND);
else
if (reg &0x06)
setprg32(0x8000, reg >>1);
else {
setprg16(0x8000, reg);
setprg16(0xC000, reg);
}
MMC3_syncCHR(chrAND, chrOR &~chrAND);
MMC3_syncWRAM(0);
MMC3_syncMirror();
}
static DECLFW (writeReg) {
if (~reg &0x20) {
reg = A &0xFF;
sync();
}
}
static void reset () {
reg = 0;
MMC3_clear();
}
static void power () {
reg = 0;
MMC3_power();
}
void Mapper509_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg);
WRAM_init(info, 8);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
}

63
src/boards/510.c Normal file
View File

@@ -0,0 +1,63 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc3.h"
#include "cartram.h"
static uint8 reg;
static void sync () {
int prgAND = reg &0x20? 0x0F: 0x1F;
int chrAND = reg &0x01? 0xFF: 0x7F;
int prgOR = (reg &0x08? 0x020: 0x000) | (reg &0x40? 0x010: 0x000);
int chrOR = (reg &0x04? 0x100: 0x000) | (reg &0x02? 0x080: 0x000);
MMC3_syncPRG(prgAND, prgOR &~prgAND);
MMC3_syncCHR(chrAND, chrOR &~chrAND);
MMC3_syncWRAM(0);
MMC3_syncMirror();
}
static DECLFW (writeReg) {
if (reg == 0) {
reg = V;
sync();
}
}
static void reset () {
reg = 0;
MMC3_clear();
}
static void power () {
reg = 0;
MMC3_power();
}
void Mapper510_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg);
WRAM_init(info, 8);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
}

75
src/boards/511.c Normal file
View File

@@ -0,0 +1,75 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc3.h"
static uint8 reg;
static uint8 pad;
static DECLFR (readPad) {
return CartBR(A &~0x3 | pad &0x3);
}
static void sync () {
int prgAND = 0x0F;
int chrAND = 0xFF;
int prgOR = reg <<4;
int chrOR = reg <<7;
MMC3_syncPRG(prgAND, prgOR &~prgAND);
MMC3_syncCHR(chrAND, chrOR &~chrAND);
MMC3_syncMirror();
SetReadHandler(0x8000, 0xFFFF, reg &0x08? readPad: CartBR);
}
static int getPRGBank (uint8 bank) {
if (reg &0x04) {
int mask = reg &0x02? 1: 3;
return MMC3_getPRGBank(bank &1) &~mask | bank &mask;
} else
return MMC3_getPRGBank(bank);
}
static DECLFW (writeReg) {
reg = A &0xFF;
sync();
}
static void reset () {
reg = 0;
pad++;
MMC3_clear();
}
static void power () {
reg = 0;
pad = 0;
MMC3_power();
}
void Mapper511_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, getPRGBank, NULL, NULL, writeReg);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
AddExState(&pad, 1, 0, "DIPS");
}

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

@@ -0,0 +1,72 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc3.h"
#include "cartram.h"
static uint8 reg;
static void sync () {
MMC3_syncPRG(0x3F, 0x00);
MMC3_syncWRAM(0);
if (reg &0x02) {
setchr4r(0x10, 0x0000, 0);
setchr4r(0x10, 0x1000, 0);
} else
MMC3_syncCHR(0xFF, 0x000);
if (reg == 1) { /* The game uses six nametables - the two console-internal ones, plus four occupying the second half of 8 KiB CHR-RAM.*/
setntamem(CHRptr[0x10] +0x1000, 1, 0);
setntamem(CHRptr[0x10] +0x1400, 1, 1);
setntamem(CHRptr[0x10] +0x1800, 1, 2);
setntamem(CHRptr[0x10] +0x1C00, 1, 3);
} else
MMC3_syncMirror();
}
static DECLFW (writeReg) {
if (A &0x100) {
reg = V;
sync();
}
}
static void reset () {
reg = 0;
MMC3_clear();
}
static void power () {
reg = 0;
MMC3_power();
SetWriteHandler(0x4020, 0x5FFF, writeReg);
}
void Mapper512_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, NULL);
CartRAM_init(info, 8, 8);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
}

48
src/boards/514.c Normal file
View File

@@ -0,0 +1,48 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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 "asic_latch.h"
#include "cartram.h"
static uint8 chr;
static void sync () {
setprg8r(0x10, 0x6000, 0);
setprg32(0x8000, Latch_data);
setchr4(0x0000, Latch_data &0x80? chr: 0);
setchr4(0x1000, 1);
setmirror(Latch_data &0x40? MI_H: MI_V);
}
static void FP_FASTAPASS(1) trapPPUAddressChange (uint32 A) {
if (A &0x2000 && (A &0x23C0) < 0x23C0) {
chr = A >>(10 +(Latch_data &0x40? 1: 0)) &1;
setchr4(0x0000, Latch_data &0x80? chr: 0);
}
}
void Mapper514_Init (CartInfo *info) {
Latch_init(info, sync, 0x8000, 0xFFFF, NULL);
WRAM_init(info, 8);
info->Reset = Latch_clear;
PPU_hook = trapPPUAddressChange;
AddExState(&chr, 1, 0, "CHRB");
}

View File

@@ -19,14 +19,14 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
static void sync () {
VRC24_syncPRG(0x1F, VRC24_chr[0] <<2 &0x20);
VRC24_syncPRG(0x1F, VRC24_getCHRBank(0) <<2 &0x20);
VRC24_syncCHR(0x07, 0x00);
VRC24_syncMirror();
}
void Mapper520_Init (CartInfo *info) {
VRC24_init(info, sync, 0x04, 0x08, 1, 1, 0);
VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, NULL, NULL, NULL);
}

View File

@@ -19,12 +19,12 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
static uint8 irqEnabled;
static uint16 irqCounter;
static SFORMAT BTL900218_stateRegs[] ={
static SFORMAT stateRegs[] ={
{ &irqEnabled, 1, "IRQE" },
{ &irqCounter, 2 | FCEUSTATE_RLSB, "CNTL" },
{ 0 }
@@ -36,7 +36,7 @@ static void sync () {
VRC24_syncMirror();
}
DECLFW(BTL900218_writeIRQ) {
static DECLFW (writeIRQ) {
if (A &8) {
if (A &4) {
irqEnabled =0;
@@ -47,19 +47,19 @@ DECLFW(BTL900218_writeIRQ) {
}
}
void FP_FASTAPASS(1) BTL900218_cpuCycle(int a) {
static void FP_FASTAPASS(1) cpuCycle (int a) {
while (a--) if (irqEnabled && ++irqCounter &1024) X6502_IRQBegin(FCEU_IQEXT);
}
void BTL900218_power(void) {
static void power (void) {
irqEnabled =irqCounter =0;
VRC24_power();
SetWriteHandler(0xF000, 0xFFFF, BTL900218_writeIRQ);
SetWriteHandler(0xF000, 0xFFFF, writeIRQ);
}
void BTL900218_Init (CartInfo *info) {
VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0);
AddExState(BTL900218_stateRegs, ~0, 0, 0);
info->Power =BTL900218_power;
MapIRQHook =BTL900218_cpuCycle;
VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL);
AddExState(stateRegs, ~0, 0, 0);
info->Power =power;
MapIRQHook =cpuCycle;
}

View File

@@ -19,7 +19,7 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
static void sync () {
VRC24_syncPRG(0x01F, 0x000);
@@ -27,9 +27,9 @@ static void sync () {
VRC24_syncMirror();
}
DECLFW(UNLKS7021A_writeCHR) {
VRC24_chr[A &7] =V;
VRC24_Sync();
DECLFW (UNLKS7021A_writeCHR) {
VRC24_writeReg(0xB000 +(A <<11 &0x3000 | A <<1 &0x0002), V &0x0F);
VRC24_writeReg(0xB001 +(A <<11 &0x3000 | A <<1 &0x0002), V >>4);
}
void UNLKS7021A_power (void) {
@@ -38,6 +38,6 @@ void UNLKS7021A_power (void) {
}
void UNLKS7021A_Init (CartInfo *info) {
VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0);
info->Power =UNLKS7021A_power;
VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL);
info->Power = UNLKS7021A_power;
}

View File

@@ -19,14 +19,14 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
static void sync () {
VRC24_syncPRG(0x01F, 0x000);
VRC24_syncCHR(0x1FF, 0x000);
setmirrorw(VRC24_chr[0] >>7, VRC24_chr[0] >>7, VRC24_chr[1] >>7, VRC24_chr[1] >>7);
setmirrorw(VRC24_getCHRBank(0) >>7, VRC24_getCHRBank(0) >>7, VRC24_getCHRBank(1) >>7, VRC24_getCHRBank(1) >>7);
}
void UNLAX40G_Init (CartInfo *info) {
VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0);
VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL);
}

View File

@@ -19,7 +19,7 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
#include "eeprom_93Cx6.h"
static uint8 eeprom_data[256];
@@ -30,31 +30,31 @@ static SFORMAT stateRegs[] ={
};
static void sync () {
setprg16(0x8000, VRC24_prg[1]);
setprg16(0x8000, VRC24_getPRGBank(1));
setprg16(0xC000, 0xFF);
VRC24_syncCHR(0x1FF, 0x000);
VRC24_syncMirror();
}
DECLFR(UNLT230_readEEPROM) {
static DECLFR (readEEPROM) {
return eeprom_93Cx6_read()? 0x01: 0x00;
}
DECLFW(UNLT230_writeEEPROM) {
static DECLFW (writeEEPROM) {
eeprom_93Cx6_write(A &0x04, A &0x02, A &0x01);
}
void UNLT230_power (void) {
static void power (void) {
VRC24_power();
eeprom_93Cx6_init(256, 16);
SetReadHandler(0x5000, 0x5FFF, UNLT230_readEEPROM);
SetWriteHandler(0xF800, 0xFFFF, UNLT230_writeEEPROM);
SetReadHandler(0x5000, 0x5FFF, readEEPROM);
SetWriteHandler(0xF800, 0xFFFF, writeEEPROM);
}
void UNLT230_Init (CartInfo *info) {
VRC24_init(info, sync, 0x04, 0x08, 1, 1, 0);
VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, NULL, NULL, NULL);
if (info->PRGRamSaveSize) {
info->Power =UNLT230_power;
info->Power =power;
AddExState(stateRegs, ~0, 0, 0);
eeprom_93Cx6_storage = eeprom_data;
info->battery = 1;

View File

@@ -19,7 +19,7 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
static void sync () {
VRC24_syncPRG(0x01F, 0x000);
@@ -27,28 +27,26 @@ static void sync () {
VRC24_syncMirror();
}
int UNLAX5705_getPRGBank(int bank) {
static int getPRGBank (uint8 bank) {
int result =VRC24_getPRGBank(bank);
return result <<2 &0x8 | result >>2 &0x2 | result &~0xA;
}
int UNLAX5705_getCHRBank(int bank) {
static int getCHRBank (uint8 bank) {
int result =VRC24_getCHRBank(bank);
return result <<1 &0x40 | result >>1 &0x20 | result &~0x60;
}
DECLFW(UNLAX5705_unscrambleAddress) {
static DECLFW (unscrambleAddress) {
VRC24_writeReg(A &~0x1000 | A <<9 &0x1000, V);
}
void UNLAX5705_power (void) {
static void power (void) {
VRC24_power();
SetWriteHandler(0x8000, 0xFFFF, UNLAX5705_unscrambleAddress);
SetWriteHandler(0x8000, 0xFFFF, unscrambleAddress);
}
void UNLAX5705_Init (CartInfo *info) {
VRC24_init(info, sync, 0x01, 0x02, 1, 1, 0);
info->Power =UNLAX5705_power;
VRC24_GetPRGBank =UNLAX5705_getPRGBank;
VRC24_GetCHRBank =UNLAX5705_getCHRBank;
VRC4_init(info, sync, 0x01, 0x02, 1, getPRGBank, getCHRBank, NULL, NULL, NULL);
info->Power =power;
}

67
src/boards/536.c Normal file
View File

@@ -0,0 +1,67 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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
*
*
*/
/* The UNIF dump of "(JY-103) 3-in-1" (JY4M4 MAPR) has a strange bank order and will not run with this emulation. */
#include "mapinc.h"
#include "asic_mmc3.h"
static uint8 reg[2];
static void sync () {
int prg = reg[0] &0x1F | reg[0] >>1 &0x20;
if (reg[0] &0x80)
MMC3_syncPRG(0x0F, prg <<2);
else
if (reg[0] &0x20)
setprg32(0x8000, prg >>1);
else {
setprg16(0x8000, prg);
setprg16(0xC000, prg);
}
setchr8(0);
MMC3_syncMirror();
}
static DECLFW (writeReg) {
reg[A &1] = V;
sync();
}
static void reset () {
reg[0] = 0x60;
reg[1] = 0x00;
MMC3_clear();
}
static void power () {
reg[0] = 0x60;
reg[1] = 0x00;
MMC3_power();
}
void Mapper536_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg);
info->Power = power;
info->Reset = reset;
AddExState(reg, 2, 0, "EXPR");
}

60
src/boards/537.c Normal file
View File

@@ -0,0 +1,60 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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
*
*
*/
/* The UNIF dump of "(JY-103) 3-in-1" (JY4M4 MAPR) has a strange bank order and will not run with this emulation. */
#include "mapinc.h"
#include "asic_mmc3.h"
static uint8 reg[2];
static void sync () {
int prgAND = reg[0] &0x80? 0x0F: 0x1F;
int chrAND = 0xFF;
int prgOR = reg[0] >>1 &0x20 | reg[1] <<4 &0x10;
int chrOR = reg[0] <<2 &0x100;
MMC3_syncPRG(prgAND, prgOR &~prgAND);
MMC3_syncCHR(chrAND, chrOR &~chrAND);
MMC3_syncMirror();
}
static DECLFW (writeReg) {
reg[A &1] = V;
sync();
}
static void reset () {
reg[0] = reg[1] = 0;
MMC3_clear();
}
static void power () {
reg[0] = reg[1] = 0;
MMC3_power();
}
void Mapper537_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, writeReg);
info->Power = power;
info->Reset = reset;
AddExState(reg, 2, 0, "EXPR");
}

View File

@@ -19,7 +19,7 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
static uint8 reg;
@@ -36,25 +36,25 @@ static void sync () {
if (reg &1) setchr1r(0x10, 0x0C00, 1);
}
DECLFW(Mapper542_writeExtra) {
DECLFW (writeExtra) {
if (A &0x800) {
reg =A >>12;
VRC24_Sync();
sync();
} else
VRC24_writeReg(A, V);
}
void Mapper542_power (void) {
void power (void) {
reg =0;
VRC24_power();
SetReadHandler(0x6000, 0x7FFF, CartBR);
SetWriteHandler(0xD000, 0xEFFF, Mapper542_writeExtra);
SetWriteHandler(0xD000, 0xEFFF, writeExtra);
}
void Mapper542_Init (CartInfo *info) {
VRC24_init(info, sync, 0x01, 0x02, 1, 1, 0);
info->Power =Mapper542_power;
VRC4_init(info, sync, 0x01, 0x02, 1, NULL, NULL, NULL, NULL, NULL);
info->Power =power;
AddExState(stateRegs, ~0, 0, 0);
SetupCartCHRMapping(0x10, NTARAM, 0x200, 1);
}

View File

@@ -19,10 +19,9 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
#include "cartram.h"
static uint8 *CHRRAM;
static uint32 CHRRAMSize;
static uint8 nt[4];
static uint8 prg;
static uint8 mask;
@@ -43,14 +42,14 @@ static void sync () {
int bank;
VRC24_syncWRAM(0);
VRC24_syncPRG(0x01F, 0x000);
for (bank =0; bank <8; bank++) setchr1r((VRC24_chr[bank] &mask) ==compare? 0x10: 0x00, bank <<10, VRC24_chr[bank]);
for (bank =0; bank <8; bank++) setchr1r((VRC24_getCHRBank(bank) &mask) ==compare? 0x10: 0x00, bank <<10, VRC24_getCHRBank(bank));
setmirrorw(nt[0] &1, nt[1] &1, nt[2] &1, nt[3] &1);
}
static const uint8 compares[8] = { 0x28, 0x00, 0x4C, 0x64, 0x46, 0x7C, 0x04, 0xFF };
static DECLFW(Mapper544_interceptPPUWrite) {
static DECLFW (interceptPPUWrite) {
if (~RefreshAddr &0x2000) {
int bank =VRC24_chr[RefreshAddr >>10 &7];
int bank =VRC24_getCHRBank(RefreshAddr >>10 &7);
if (bank &0x80) {
if (bank &0x10) {
mask =0x00;
@@ -60,26 +59,26 @@ static DECLFW(Mapper544_interceptPPUWrite) {
mask =bank &0x40? 0xFE: 0xFC;
compare =compares[index];
}
VRC24_Sync();
sync();
}
}
writePPU(A, V);
}
int Mapper544_getPRGBank(int bank) {
static int getPRGBank (uint8 bank) {
return bank ==2? prg: VRC24_getPRGBank(bank);
}
DECLFW(Mapper544_externalSelect) {
static DECLFW (externalSelect) {
if (A &4)
nt[A &3] =V;
else
prg =V;
VRC24_Sync();
sync();
}
void Mapper544_power (void) {
static void power (void) {
mask =0xFC;
compare =0x28;
nt[0] =nt[1] =0xE0;
@@ -87,26 +86,12 @@ void Mapper544_power (void) {
prg =0xFE;
VRC24_power();
writePPU =GetWriteHandler(0x2007);
SetWriteHandler(0x2007, 0x2007, Mapper544_interceptPPUWrite);
}
void Mapper544_close(void) {
if (CHRRAM) {
FCEU_gfree(CHRRAM);
CHRRAM =NULL;
}
SetWriteHandler(0x2007, 0x2007, interceptPPUWrite);
}
void Mapper544_Init (CartInfo *info) {
VRC24_init(info, sync, 0x400, 0x800, 1, 1, 0);
info->Power =Mapper544_power;
info->Close =Mapper544_close;
VRC24_GetPRGBank =Mapper544_getPRGBank;
VRC24_ExternalSelect =Mapper544_externalSelect;
VRC4_init(info, sync, 0x400, 0x800, 1, getPRGBank, NULL, NULL, NULL, externalSelect);
CartRAM_init(info, 8, 2);
info->Power =power;
AddExState(stateRegs, ~0, 0, 0);
CHRRAMSize =info->CHRRamSize +info->CHRRamSaveSize;
CHRRAM =(uint8*)FCEU_gmalloc(CHRRAMSize);
AddExState(CHRRAM, CHRRAMSize, 0, "CRAM");
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
}

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

@@ -0,0 +1,70 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc3.h"
#include "cartram.h"
static uint8 reg;
static void sync () {
MMC3_syncWRAM(0);
MMC3_syncPRG(0x7F, 0x00);
MMC3_syncCHR(0x7F, reg <<7 | ~reg <<4 &0x40);
MMC3_syncMirror();
}
static int getPRGBank (uint8 bank) {
int result = MMC3_getPRGBank(bank);
if (reg &0x08 && ~result &0x10)
result = 0x40 | result &0x0F;
else
result = reg <<4 &0x30 | result &0x0F;
return result;
}
static DECLFW (writeReg) {
if (A &0x020 && A &0x100) {
reg = V;
sync();
} else
MMC3_writeReg(A, V);
}
static void reset () {
reg = 0;
MMC3_clear();
}
static void power () {
reg = 0;
MMC3_power();
SetWriteHandler(0xF000, 0xFFFF, writeReg);
}
void Mapper545_Init (CartInfo *info) {
MMC3_init(info, sync, MMC3_TYPE_AX5202P, getPRGBank, NULL, NULL, NULL);
WRAM_init(info, 8);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
}

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

@@ -0,0 +1,70 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_mmc1.h"
#include "cartram.h"
static uint8 reg;
static void sync () {
MMC1_syncWRAM(0);
if (reg &0x10)
MMC1_syncPRG(0x0F, 0x10);
else
if (reg &0x20)
setprg32(0x8000, reg >>1);
else {
setprg16(0x8000, reg);
setprg16(0xC000, reg);
}
SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], reg &0x80? 0: 1);
setchr8(0);
MMC1_syncMirror();
}
static DECLFW (writeReg) {
if (!(A &0x0F00)) {
reg = A &0xFF;
sync();
}
MMC1_writeReg(A, V);
}
static void reset () {
reg = 0;
MMC1_clear();
}
static void power () {
reg = 0;
MMC1_power();
SetWriteHandler(0x8000, 0x9FFF, writeReg);
}
void Mapper546_Init (CartInfo *info) {
MMC1_init(info, sync, MMC1_TYPE_MMC1B, NULL, NULL, NULL, NULL);
WRAM_init(info, 8);
info->Power = power;
info->Reset = reset;
AddExState(&reg, 1, 0, "EXPR");
}

105
src/boards/548.c Normal file
View File

@@ -0,0 +1,105 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "cartram.h"
#include "../fds_apu.h"
static uint8 reg;
static uint8 latch;
static uint8 counting;
static uint16 counter;
static SFORMAT stateRegs[] ={
{ &reg, 1, "REGM" },
{ &latch, 1, "LATC" },
{ &counting, 1, "IRQA" },
{ &counter, 2 | FCEUSTATE_RLSB, "IRQC" },
{ 0 }
};
static void sync () {
setprg8r(0x10, 0x6000, 0);
setprg16(0x8000, reg);
setprg16(0xC000, 3);
setchr8(0);
}
static DECLFW (writeLatch) {
latch = A >>2 &0x03 | A >>3 &0x04;
if (A &4) {
counting = 0;
counter = 0;
X6502_IRQEnd(FCEU_IQEXT);
} else
counting = 1;
}
static DECLFW (writeReg) {
reg = latch ^0x05;
sync();
}
static void FP_FASTAPASS(1) cpuCycle (int a) {
while (a--) {
if (counting) {
if (counter == 23680)
X6502_IRQBegin(FCEU_IQEXT);
else
if (counter == 24320)
X6502_IRQEnd(FCEU_IQEXT);
counter++;
}
}
}
static void reset () {
FDSSoundReset();
X6502_IRQEnd(FCEU_IQEXT);
latch = 0x07;
reg = latch ^0x05;
counting = 0;
counter = 0;
sync();
}
static void power () {
FDSSoundPower();
SetReadHandler(0x6000, 0xFFFF, CartBR);
SetWriteHandler(0x4800, 0x4FFF, writeLatch);
SetWriteHandler(0x5000, 0x57FF, writeReg);
SetWriteHandler(0x6000, 0x7FFF, CartBW);
reset();
}
static void stateRestore (int version) {
sync();
}
void Mapper548_Init (CartInfo *info) {
WRAM_init(info, 8);
info->Power = power;
info->Reset = reset;
MapIRQHook = cpuCycle;
GameStateRestore = stateRestore;
AddExState(stateRegs, ~0, 0, 0);
}

45
src/boards/549.c Normal file
View File

@@ -0,0 +1,45 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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 "asic_latch.h"
#include "../fds_apu.h"
static void sync () {
setprg8(0x6000, Latch_address >>2 | Latch_address >>3 &0x04);
setprg32(0x8000, 2);
setchr8(0);
}
static void power() {
Latch_power();
FDSSoundPower();
}
static void reset() {
FDSSoundReset();
Latch_clear();
}
void Mapper549_Init (CartInfo *info) {
Latch_init(info, sync, 0x8000, 0xFFFF, NULL);
info->Power = power;
info->Reset = reset;
}

View File

@@ -19,312 +19,84 @@
*/
/* NES 2.0 Mapper 556
* Used for the for the 超强小æ°2+瑪莉家族 7-in-1 (JY-215) multicart.
* Used for the for the 餓狼傳說 激鬥篇 HiK 7-in-1 (JY-215) multicart.
*/
#include "mapinc.h"
#include "asic_mmc3.h"
#include "asic_vrc2and4.h"
#include "cartram.h"
static uint8 reg[5];
static uint8 mmc3Reg[8];
static uint8 mmc3Cmd;
static uint8 mmc3Mirr;
static uint8 mmc3Wram;
static uint8 mmc3IRQLatch;
static uint8 mmc3IRQCount;
static uint8 mmc3IRQa;
static uint8 mmc3IRQReload;
static uint8 vrc4Prg[2];
static uint8 vrc4Mirr;
static uint8 vrc4Misc;
static uint16 vrc4Chr[8];
static uint8 vrc4IRQLatch;
static uint8 vrc4IRQa;
static uint8 vrc4IRQCount;
static int16 vrc4IRQCycles;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE = 0;
static uint8 reg[4];
static uint8 rIdx;
static SFORMAT StateRegs[] = {
{ reg, 5, "REGS" },
{ mmc3Reg, 8, "MMC3" },
{ &mmc3Cmd, 1, "M3IX" },
{ &mmc3Mirr, 1, "M3MI" },
{ &mmc3Wram, 1, "M3WR" },
{ &mmc3IRQLatch, 1, "M3RL" },
{ &mmc3IRQCount, 1, "M3CN" },
{ &mmc3IRQa, 1, "M3IQ" },
{ &mmc3IRQReload, 1, "M3IR" },
{ vrc4Prg, 2, "V4PR" },
{ &vrc4Mirr, 1, "V4MI" },
{ &vrc4Misc, 1, "V4MS" },
{ vrc4Chr, 16, "V4CH" },
{ &vrc4IRQLatch, 1, "VILA" },
{ &vrc4IRQa, 1, "VIMO" },
{ &vrc4IRQCount, 1, "VICO" },
{ &vrc4IRQCycles, 2, "VICY" },
{ reg, 4, "REGS" },
{ &rIdx, 1, "INDX" },
{ 0 },
};
static void Sync(void) {
uint32 prgmask = ~reg[3] & 0x3F;
uint32 prgbase = ((reg[3] & 0x40) << 2) | reg[1];
uint32 chrmask = 0xFF >> (~reg[2] & 0x0F);
uint32 chrbase = ((reg[3] & 0x40) << 6) | ((reg[2] & 0xF0) << 4) | reg[0];
uint32 cbase = 0; /* prg/chr bank flip flag */
if (~reg[2] & 0x80) {
/* MMC3 */
cbase = (mmc3Cmd << 8) & 0x4000;
setprg8(0x8000 ^ cbase, (prgbase & ~prgmask) | (mmc3Reg[6] & prgmask));
setprg8(0xA000, (prgbase & ~prgmask) | (mmc3Reg[7] & prgmask));
setprg8(0xC000 ^ cbase, (prgbase & ~prgmask) | (0xFE & prgmask));
setprg8(0xE000, (prgbase & ~prgmask) | (0xFF & prgmask));
cbase = (mmc3Cmd << 5) & 0x1000;
setchr1(0x0000 ^ cbase, (chrbase & ~chrmask) | ((mmc3Reg[0] & 0xFE) & chrmask));
setchr1(0x0400 ^ cbase, (chrbase & ~chrmask) | ((mmc3Reg[0] | 0x01) & chrmask));
setchr1(0x0800 ^ cbase, (chrbase & ~chrmask) | ((mmc3Reg[1] & 0xFE) & chrmask));
setchr1(0x0C00 ^ cbase, (chrbase & ~chrmask) | ((mmc3Reg[1] | 0x01) & chrmask));
setchr1(0x1000 ^ cbase, (chrbase & ~chrmask) | (mmc3Reg[2] & chrmask));
setchr1(0x1400 ^ cbase, (chrbase & ~chrmask) | (mmc3Reg[3] & chrmask));
setchr1(0x1800 ^ cbase, (chrbase & ~chrmask) | (mmc3Reg[4] & chrmask));
setchr1(0x1C00 ^ cbase, (chrbase & ~chrmask) | (mmc3Reg[5] & chrmask));
setmirror((mmc3Mirr & 0x01) ^ 1);
static void sync (void) {
int prgAND = ~reg[3] &0x3F;
int chrAND = 0xFF >>(~reg[2] &0xF);
int prgOR = (reg[1] | reg[3] <<2 &0x100) &~prgAND;
int chrOR = (reg[0] | reg[2] <<4 &0x0F00 | reg[3] <<6 &0x1000) &~chrAND;
if (reg[2] &0x80) {
VRC24_syncWRAM(0);
VRC24_syncPRG(prgAND, prgOR);
VRC24_syncCHR(chrAND, chrOR);
VRC24_syncMirror();
} else {
/* VRC4 mode */
cbase = (vrc4Misc << 13) & 0x4000;
setprg8(0x8000 ^ cbase, (prgbase & ~prgmask) | (vrc4Prg[0] & prgmask));
setprg8(0xA000, (prgbase & ~prgmask) | (vrc4Prg[1] & prgmask));
setprg8(0xC000 ^ cbase, (prgbase & ~prgmask) | (0xFE & prgmask));
setprg8(0xE000, (prgbase & ~prgmask) | (0xFF & prgmask));
setchr1(0x0000, (chrbase & ~chrmask) | (vrc4Chr[0] & chrmask));
setchr1(0x0400, (chrbase & ~chrmask) | (vrc4Chr[1] & chrmask));
setchr1(0x0800, (chrbase & ~chrmask) | (vrc4Chr[2] & chrmask));
setchr1(0x0C00, (chrbase & ~chrmask) | (vrc4Chr[3] & chrmask));
setchr1(0x1000, (chrbase & ~chrmask) | (vrc4Chr[4] & chrmask));
setchr1(0x1400, (chrbase & ~chrmask) | (vrc4Chr[5] & chrmask));
setchr1(0x1800, (chrbase & ~chrmask) | (vrc4Chr[6] & chrmask));
setchr1(0x1C00, (chrbase & ~chrmask) | (vrc4Chr[7] & chrmask));
switch (vrc4Mirr & 0x03) {
case 0: setmirror(MI_V); break;
case 1: setmirror(MI_H); break;
case 2: setmirror(MI_0); break;
case 3: setmirror(MI_1); break;
}
MMC3_syncWRAM(0);
MMC3_syncPRG(prgAND, prgOR);
MMC3_syncCHR(chrAND, chrOR);
MMC3_syncMirror();
}
}
static DECLFW(writeMMC3) {
switch (A & 0xE001) {
case 0x8000:
mmc3Cmd = V;
Sync();
break;
case 0x8001:
mmc3Reg[mmc3Cmd & 7] = V;
Sync();
break;
case 0xA000:
mmc3Mirr = V;
Sync();
break;
case 0xA001:
mmc3Wram = V;
Sync();
break;
case 0xC000:
mmc3IRQLatch = V;
break;
case 0xC001:
mmc3IRQReload = 1;
break;
case 0xE000:
mmc3IRQa = 0;
X6502_IRQEnd(FCEU_IQEXT);
break;
case 0xE001:
mmc3IRQa = 1;
break;
static void applyMode (uint8 clear) {
if (reg[2] &0x80)
VRC4_activate(clear, sync, 0x05, 0x0A, 1, NULL, NULL, NULL, NULL, NULL);
else
MMC3_activate(clear, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, NULL);
}
static DECLFW(writeReg) {
if (~reg[3] &0x80) {
reg[rIdx++ &3] = V;
if (rIdx == 3)
applyMode(1);
else
sync();
}
}
static DECLFW(writeVRC4) {
uint8 index;
A = (A & 0xF000) | ((A >> 2) & 3) | (A & 3);
switch (A & 0xF000) {
case 0x8000:
case 0xA000:
vrc4Prg[(A >> 13) & 1] = V;
Sync();
break;
case 0x9000:
if (~A & 2) {
vrc4Mirr = V;
} else if (~A & 1) {
vrc4Misc = V;
}
Sync();
break;
case 0xF000:
switch (A & 3) {
case 0:
vrc4IRQLatch = (vrc4IRQLatch & 0xF0) | (V & 0x0F);
break;
case 1:
vrc4IRQLatch = (vrc4IRQLatch & 0x0F) | (V << 4);
break;
case 2:
vrc4IRQa = V;
if (vrc4IRQa & 0x02) {
vrc4IRQCount = vrc4IRQLatch;
vrc4IRQCycles = 341;
}
X6502_IRQEnd(FCEU_IQEXT);
break;
case 3:
vrc4IRQa = (vrc4IRQa & ~0x02) | ((vrc4IRQa << 1) & 0x02);
X6502_IRQEnd(FCEU_IQEXT);
break;
}
break;
default:
index = ((A - 0xB000) >> 11) | ((A >> 1) & 1);
if (A & 1) {
vrc4Chr[index] = (vrc4Chr[index] & 0x0F) | (V << 4);
} else {
vrc4Chr[index] = (vrc4Chr[index] & ~0x0F) | (V & 0x0F);
}
Sync();
break;
}
}
static DECLFW(M556WriteReg) {
if (~reg[3] & 0x80) {
reg[reg[4] & 3] = V;
reg[4]++;
Sync();
}
}
static DECLFW(M556Write) {
if (~reg[2] & 0x80) {
writeMMC3(A, V);
} else {
writeVRC4(A, V);
}
}
static void FP_FASTAPASS(1) M556CPUHook(int a) {
int count = a;
if (~reg[2] & 0x80) {
return;
}
/* VRC4 IRQ mode */
while (count--) {
if ((vrc4IRQa & 0x02) && ((vrc4IRQa & 0x04) || ((vrc4IRQCycles -= 3) <= 0))) {
if (~vrc4IRQa & 0x04) {
vrc4IRQCycles += 341;
}
if (!++vrc4IRQCount) {
vrc4IRQCount = vrc4IRQLatch;
X6502_IRQBegin(FCEU_IQEXT);
}
}
}
}
static void M556HBHook(void) {
int count = mmc3IRQCount;
if (reg[2] & 0x80) {
return;
}
/* MMC3 IRQ mode */
if (!count || mmc3IRQReload) {
mmc3IRQCount = mmc3IRQLatch;
} else {
mmc3IRQCount--;
}
if (count && !mmc3IRQCount && mmc3IRQa) {
X6502_IRQBegin(FCEU_IQEXT);
}
mmc3IRQReload = 0;
}
static void M556Reset(void) {
int i;
for (i = 0; i < 5; i++) {
reg[i] = 0;
}
static void reset (void) {
reg[0] = reg[1] = reg[3] = 0;
reg[2] = 0x0F;
Sync();
rIdx = 0;
applyMode(1);
}
static void M556Power(void) {
int i;
for (i = 0; i < 5; i++) {
reg[i] = 0;
}
for (i = 0; i < 8; i++) {
mmc3Reg[i] = 0;
}
for (i = 0; i < 2; i++) {
vrc4Prg[i] = 0;
}
for (i = 0; i < 8; i++) {
vrc4Chr[i] = 0;
}
mmc3Cmd = mmc3Mirr = mmc3Wram = mmc3IRQLatch = mmc3IRQCount = mmc3IRQa = mmc3IRQReload = 0;
vrc4Mirr = vrc4Misc = vrc4IRQLatch = vrc4IRQa = vrc4IRQCount = vrc4IRQCycles = 0;
static void power (void) {
reg[0] = reg[1] = reg[3] = 0;
reg[2] = 0x0F;
Sync();
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x5000, 0x5FFF, M556WriteReg);
SetWriteHandler(0x8000, 0xFFFF, M556Write);
if (WRAM) {
setprg8r(0x10, 0x6000, 0);
SetReadHandler(0x6000, 0x7FFF, CartBR);
SetWriteHandler(0x6000, 0x7FFF, CartBW);
}
rIdx = 0;
SetReadHandler(0x6000, 0xFFFF, CartBR);
SetWriteHandler(0x5000, 0x5FFF, writeReg);
applyMode(1);
}
static void M556Close(void) {
if (WRAM) {
FCEU_gfree(WRAM);
}
WRAM = NULL;
static void restore (int version) {
applyMode(0);
}
static void StateRestore(int version) {
Sync();
}
void Mapper556_Init(CartInfo *info) {
info->Reset = M556Reset;
info->Power = M556Power;
info->Close = M556Close;
MapIRQHook = M556CPUHook;
GameHBIRQHook = M556HBHook;
GameStateRestore = StateRestore;
void Mapper556_Init (CartInfo *info) {
MMC3_addExState();
VRC24_addExState();
WRAM_init(info, 8);
info->Reset = reset;
info->Power = power;
GameStateRestore = restore;
AddExState(StateRegs, ~0, 0, 0);
WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize;
if (WRAMSIZE) {
WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE);
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
}
}
}

37
src/boards/557.c Normal file
View File

@@ -0,0 +1,37 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020
*
* 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 "asic_n118.h"
#include "cartram.h"
static void sync () {
setprg8r(0x10, 0x6000, 0);
N118_syncPRG(0x0F, 0x00);
setchr8(0);
setmirror(N118_getCHRBank(7) &0x20? MI_H: MI_V);
}
void Mapper557_Init (CartInfo *info) {
N118_init(info, sync, NULL, NULL);
WRAM_init(info, 8);
}

View File

@@ -19,7 +19,7 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
static uint8 nt[4];
static uint8 prg;
@@ -38,34 +38,32 @@ static void sync () {
setmirrorw(nt[0] &1, nt[1] &1, nt[2] &1, nt[3] &1);
}
int Mapper559_getPRGBank(int bank) {
static int getPRGBank (uint8 bank) {
return bank ==2? prg: VRC24_getPRGBank(bank);
}
DECLFW(Mapper559_externalSelect) {
static DECLFW (externalSelect) {
if (A &4)
nt[A &3] =V;
else
prg =V;
VRC24_Sync();
sync();
}
DECLFW(Mapper559_nibblizeData) {
static DECLFW (nibblizeData) {
VRC24_writeReg(A, V >>(A &0x400? 4: 0));
}
void Mapper559_power (void) {
static void power (void) {
nt[0] =nt[1] =0xE0;
nt[2] =nt[3] =0xE1;
prg =0xFE;
VRC24_power();
SetWriteHandler(0xB000, 0xFFFF, Mapper559_nibblizeData);
SetWriteHandler(0xB000, 0xFFFF, nibblizeData);
}
void Mapper559_Init (CartInfo *info) {
VRC24_init(info, sync, 0x400, 0x800, 1, 1, 0);
info->Power =Mapper559_power;
VRC24_GetPRGBank =Mapper559_getPRGBank;
VRC24_ExternalSelect =Mapper559_externalSelect;
VRC4_init(info, sync, 0x400, 0x800, 1, getPRGBank, NULL, NULL, NULL, externalSelect);
info->Power =power;
AddExState(stateRegs, ~0, 0, 0);
}

View File

@@ -19,7 +19,7 @@
*/
#include "mapinc.h"
#include "vrc2and4.h"
#include "asic_vrc2and4.h"
static uint8 irqEnabled;
static uint8 irqCounter;
@@ -36,7 +36,7 @@ static void sync () {
VRC24_syncMirror();
}
DECLFW(Mapper563_writeIRQ) {
static DECLFW (Mapper563_writeIRQ) {
X6502_IRQEnd(FCEU_IQEXT);
switch(A &0x1C) {
case 0x0C: irqEnabled =0; break;
@@ -49,15 +49,15 @@ static void Mapper563_scanline (void) { /* Actually, a sixteen-stage counter tri
if (!(++irqCounter &1) && irqEnabled) X6502_IRQBegin(FCEU_IQEXT);
}
void Mapper563_power(void) {
irqEnabled =irqCounter =0;
static void Mapper563_power (void) {
irqEnabled = irqCounter =0;
VRC24_power();
SetWriteHandler(0xF000, 0xFFFF, Mapper563_writeIRQ);
}
void Mapper563_Init (CartInfo *info) {
VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0);
VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL);
AddExState(Mapper563_stateRegs, ~0, 0, 0);
info->Power =Mapper563_power;
info->Power = Mapper563_power;
GameHBIRQHook = Mapper563_scanline;
}

45
src/boards/564.c Normal file
View File

@@ -0,0 +1,45 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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 "asic_latch.h"
static void sync () {
setprg32(0x8000, Latch_data);
setchr8(0);
if (Latch_data &0x20)
setmirror(Latch_data &0x10? MI_1: MI_0);
else
setmirror(Latch_data &0x10? MI_H: MI_V);
}
static void trapLatchWrite (uint16 *newAddress, uint8 *newValue, uint8 romValue) { /* After the lock bit is set, only update the (mode-specific) inner bank bits. */
if (Latch_data &0x20) {
if (Latch_data &0x08)
*newValue = Latch_data &0x28 | *newValue &~0x28; /* AOROM */
else
*newValue = Latch_data &0x2C | *newValue &~0x2C; /* ANROM */
}
}
void Mapper564_Init (CartInfo *info) {
Latch_init(info, sync, 0x8000, 0xFFFF, trapLatchWrite);
info->Reset = Latch_clear;
}

78
src/boards/565.c Normal file
View File

@@ -0,0 +1,78 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2025 NewRisingSun
*
* 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 "asic_vrc2and4.h"
static uint8 irqEnabled;
static uint8 irqCounter;
static uint8 irqPrescaler;
static SFORMAT stateRegs[] ={
{ &irqEnabled, 1, "IRQE" },
{ &irqCounter, 1, "CNTR" },
{ &irqPrescaler, 1, "IRQP" },
{ 0 }
};
static void sync () {
VRC24_syncPRG(0x01F, 0x000);
VRC24_syncCHR(0x1FF, 0x000);
VRC24_syncMirror();
}
static DECLFW (writeIRQ) {
switch(A &0x0C) {
case 0:
irqCounter = V;
irqPrescaler = 0;
X6502_IRQEnd(FCEU_IQEXT);
break;
case 4:
irqEnabled = V;
break;
}
}
static void FP_FASTAPASS(1) cpuCycle (int a) {
while (a--) {
if (irqEnabled &1) {
irqPrescaler++;
if (irqPrescaler == 64 && !++irqCounter) X6502_IRQBegin(FCEU_IQEXT);
if (irqPrescaler == 112) irqPrescaler = 0;
} else {
irqPrescaler = 0;
X6502_IRQEnd(FCEU_IQEXT);
}
}
}
static void power (void) {
irqEnabled = irqCounter = irqPrescaler = 0;
VRC24_power();
SetWriteHandler(0xF000, 0xFFFF, writeIRQ);
}
void Mapper565_Init (CartInfo *info) {
VRC2_init(info, sync, 0x08, 0x04, NULL, NULL, NULL, NULL);
AddExState(stateRegs, ~0, 0, 0);
info->Power = power;
MapIRQHook = cpuCycle;
}

Some files were not shown because too many files have changed in this diff Show More