Merge pull request #637 from NRS-NewRisingSun/asic_modularize
New Mappers and modularization
This commit is contained in:
431
src/boards/116.c
431
src/boards/116.c
@@ -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[] = {
|
||||
{ ®, 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
56
src/boards/122.c
Normal 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
101
src/boards/14.c
Normal 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[] = {
|
||||
{ ®, 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);
|
||||
}
|
||||
@@ -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
75
src/boards/182.c
Normal 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");
|
||||
}
|
||||
@@ -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
37
src/boards/213.c
Normal 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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
38
src/boards/239.c
Normal 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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
83
src/boards/273.c
Normal 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;
|
||||
}
|
||||
@@ -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
78
src/boards/285.c
Normal 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");
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
57
src/boards/321.c
Normal 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(®, 1, 0, "EXPR");
|
||||
}
|
||||
364
src/boards/351.c
364
src/boards/351.c
@@ -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
50
src/boards/352.c
Normal 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");
|
||||
}
|
||||
112
src/boards/356.c
112
src/boards/356.c
@@ -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
54
src/boards/361.c
Normal 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(®, 1, 0, "EXPR");
|
||||
}
|
||||
@@ -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
39
src/boards/363.c
Normal 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
59
src/boards/366.c
Normal 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(®, 1, 0, "EXPR");
|
||||
}
|
||||
39
src/boards/378.c
Normal file
39
src/boards/378.c
Normal 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
32
src/boards/379.c
Normal 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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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[] ={
|
||||
{ ®, 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);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -19,19 +19,19 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "vrc2and4.h"
|
||||
#include "asic_vrc2and4.h"
|
||||
|
||||
static uint8 reg;
|
||||
|
||||
static SFORMAT Mapper398_stateRegs[] ={
|
||||
static SFORMAT stateRegs[] ={
|
||||
{ ®, 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
58
src/boards/400.c
Normal 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
34
src/boards/418.c
Normal 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);
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
246
src/boards/445.c
246
src/boards/445.c
@@ -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
422
src/boards/446.c
Normal 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");
|
||||
}
|
||||
@@ -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[] = {
|
||||
{ ®, 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);
|
||||
}
|
||||
|
||||
@@ -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[] ={
|
||||
{ ®, 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);
|
||||
}
|
||||
|
||||
128
src/boards/449.c
128
src/boards/449.c
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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(®, 1, 0, "EXPR");
|
||||
AddExState(&pad, 1, 0, "DIPS");
|
||||
}
|
||||
|
||||
107
src/boards/460.c
107
src/boards/460.c
@@ -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(®, 1, 0, "EXPR");
|
||||
AddExState(®, 1, 0, "DIPS");
|
||||
}
|
||||
|
||||
60
src/boards/461.c
Normal file
60
src/boards/461.c
Normal 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(®, 1, 0, "EXPR");
|
||||
}
|
||||
669
src/boards/468.c
669
src/boards/468.c
@@ -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" },
|
||||
{ ®, 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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
80
src/boards/483.c
Normal 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
43
src/boards/489.c
Normal 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
68
src/boards/490.c
Normal 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(®, 1, 0, "EXPR");
|
||||
AddExState(&pad, 1, 0, "DIPS");
|
||||
}
|
||||
37
src/boards/491.c
Normal file
37
src/boards/491.c
Normal 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
38
src/boards/492.c
Normal 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
52
src/boards/493.c
Normal 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
61
src/boards/494.c
Normal 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
83
src/boards/495.c
Normal 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
62
src/boards/498.c
Normal 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(®, 1, 0, "EXPR");
|
||||
}
|
||||
56
src/boards/499.c
Normal file
56
src/boards/499.c
Normal 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(®, 1, 0, "EXPR");
|
||||
}
|
||||
67
src/boards/503.c
Normal file
67
src/boards/503.c
Normal 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(®, 1, 0, "EXPR");
|
||||
}
|
||||
65
src/boards/504.c
Normal file
65
src/boards/504.c
Normal 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(®, 1, 0, "EXPR");
|
||||
}
|
||||
65
src/boards/505.c
Normal file
65
src/boards/505.c
Normal 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(®, 2 | FCEUSTATE_RLSB, 0, "EXPR");
|
||||
AddExState(&pad, 1, 0, "DIPS");
|
||||
}
|
||||
58
src/boards/506.c
Normal file
58
src/boards/506.c
Normal 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(®, 1, 0, "EXPR");
|
||||
}
|
||||
66
src/boards/507.c
Normal file
66
src/boards/507.c
Normal 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(®, 1, 0, "EXPR");
|
||||
AddExState(&pad, 1, 0, "DIPS");
|
||||
}
|
||||
70
src/boards/508.c
Normal file
70
src/boards/508.c
Normal 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(®, 1, 0, "EXPR");
|
||||
AddExState(&pad, 1, 0, "DIPS");
|
||||
}
|
||||
71
src/boards/509.c
Normal file
71
src/boards/509.c
Normal 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(®, 1, 0, "EXPR");
|
||||
}
|
||||
63
src/boards/510.c
Normal file
63
src/boards/510.c
Normal 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(®, 1, 0, "EXPR");
|
||||
}
|
||||
75
src/boards/511.c
Normal file
75
src/boards/511.c
Normal 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(®, 1, 0, "EXPR");
|
||||
AddExState(&pad, 1, 0, "DIPS");
|
||||
}
|
||||
72
src/boards/512.c
Normal file
72
src/boards/512.c
Normal 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(®, 1, 0, "EXPR");
|
||||
}
|
||||
48
src/boards/514.c
Normal file
48
src/boards/514.c
Normal 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");
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
67
src/boards/536.c
Normal 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
60
src/boards/537.c
Normal 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");
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
70
src/boards/545.c
Normal 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(®, 1, 0, "EXPR");
|
||||
}
|
||||
70
src/boards/546.c
Normal file
70
src/boards/546.c
Normal 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(®, 1, 0, "EXPR");
|
||||
}
|
||||
105
src/boards/548.c
Normal file
105
src/boards/548.c
Normal 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[] ={
|
||||
{ ®, 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
45
src/boards/549.c
Normal 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;
|
||||
}
|
||||
338
src/boards/556.c
338
src/boards/556.c
@@ -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
37
src/boards/557.c
Normal 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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
45
src/boards/564.c
Normal 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
78
src/boards/565.c
Normal 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
Reference in New Issue
Block a user