Add mapper 446 using mapper emulation cores that can be included in other multi-ASIC mappers.
This commit is contained in:
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "vrc2and4.h"
|
||||
#include "asic_vrc2and4.h"
|
||||
|
||||
static uint8 prg;
|
||||
|
||||
@@ -37,7 +37,7 @@ static void sync () {
|
||||
|
||||
DECLFW(Mapper183_writePRG) {
|
||||
prg =A &0xFF;
|
||||
VRC24_Sync();
|
||||
sync();
|
||||
}
|
||||
|
||||
void Mapper183_power(void) {
|
||||
@@ -46,9 +46,7 @@ void Mapper183_power(void) {
|
||||
}
|
||||
|
||||
void Mapper183_Init (CartInfo *info) {
|
||||
VRC24_init(info, sync, 0x04, 0x08, 1, 1, 0);
|
||||
VRC24_WRAMRead =CartBR;
|
||||
VRC24_WRAMWrite =Mapper183_writePRG;
|
||||
VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, CartBR, Mapper183_writePRG, NULL);
|
||||
AddExState(Mapper183_stateRegs, ~0, 0, 0);
|
||||
info->Power =Mapper183_power;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "vrc2and4.h"
|
||||
#include "asic_vrc2and4.h"
|
||||
#include "wram.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;
|
||||
@@ -91,7 +91,7 @@ void Mapper222_power(void) {
|
||||
}
|
||||
|
||||
void Mapper222_Init (CartInfo *info) {
|
||||
VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0);
|
||||
VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL);
|
||||
AddExState(Mapper222_stateRegs, ~0, 0, 0);
|
||||
info->Power =Mapper222_power;
|
||||
MapIRQHook =Mapper222_cpuCycle;
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "vrc2and4.h"
|
||||
#include "asic_vrc2and4.h"
|
||||
#include "wram.h"
|
||||
|
||||
static uint8 *CHRRAM;
|
||||
static uint32 CHRRAMSize;
|
||||
@@ -39,17 +40,17 @@ 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) {
|
||||
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);
|
||||
@@ -76,10 +77,12 @@ void Mapper252_253_close(void) {
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM =NULL;
|
||||
}
|
||||
WRAM_close();
|
||||
}
|
||||
|
||||
void Mapper252_Init (CartInfo *info) {
|
||||
VRC24_init(info, sync, 0x4, 0x8, 1, 1, 0);
|
||||
VRC4_init(info, sync, 0x4, 0x8, 1, NULL, NULL, NULL, NULL, NULL);
|
||||
WRAM_init(info, 8);
|
||||
info->Power =Mapper252_power;
|
||||
info->Close =Mapper252_253_close;
|
||||
AddExState(stateRegs, ~0, 0, 0);
|
||||
@@ -91,7 +94,8 @@ void Mapper252_Init (CartInfo *info) {
|
||||
}
|
||||
|
||||
void Mapper253_Init (CartInfo *info) {
|
||||
VRC24_init(info, sync, 0x4, 0x8, 1, 1, 0);
|
||||
VRC4_init(info, sync, 0x4, 0x8, 1, NULL, NULL, NULL, NULL, NULL);
|
||||
WRAM_init(info, 8);
|
||||
info->Power =Mapper253_power;
|
||||
info->Close =Mapper252_253_close;
|
||||
AddExState(stateRegs, ~0, 0, 0);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "vrc2and4.h"
|
||||
#include "asic_vrc2and4.h"
|
||||
|
||||
static uint8 prg;
|
||||
|
||||
@@ -39,7 +39,7 @@ DECLFW(UNLCITYFIGHT_externalSelect) {
|
||||
(GetWriteHandler(0x4011))(0x4011, V <<3 &0x78);
|
||||
else {
|
||||
prg =V >>2;
|
||||
VRC24_Sync();
|
||||
sync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,8 +54,7 @@ void UNLCITYFIGHT_power(void) {
|
||||
}
|
||||
|
||||
void UNLCITYFIGHT_Init (CartInfo *info) {
|
||||
VRC24_init(info, sync, 0x04, 0x08, 1, 1, 0);
|
||||
VRC24_ExternalSelect =UNLCITYFIGHT_externalSelect;
|
||||
VRC4_init(info, sync, 0x04, 0x08, 1, NULL, NULL, NULL, NULL, UNLCITYFIGHT_externalSelect);
|
||||
AddExState(UNLCITYFIGHT_stateRegs, ~0, 0, 0);
|
||||
info->Power =UNLCITYFIGHT_power;
|
||||
}
|
||||
|
||||
@@ -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,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "vrc2and4.h"
|
||||
#include "asic_vrc2and4.h"
|
||||
|
||||
static uint8 irqEnabled;
|
||||
static uint16 irqCounterLow;
|
||||
@@ -65,7 +65,7 @@ void UNLTH21311_power(void) {
|
||||
}
|
||||
|
||||
void UNLTH21311_Init (CartInfo *info) {
|
||||
VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0);
|
||||
VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL);
|
||||
AddExState(UNLTH21311_stateRegs, ~0, 0, 0);
|
||||
info->Power =UNLTH21311_power;
|
||||
MapIRQHook =UNLTH21311_cpuCycle;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "vrc2and4.h"
|
||||
#include "asic_vrc2and4.h"
|
||||
|
||||
static uint8 game;
|
||||
|
||||
@@ -34,8 +34,8 @@ 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();
|
||||
}
|
||||
}
|
||||
@@ -47,11 +47,11 @@ void Mapper362_power(void) {
|
||||
|
||||
void Mapper362_reset(void) {
|
||||
game ^=1;
|
||||
VRC24_Sync();
|
||||
sync();
|
||||
}
|
||||
|
||||
void Mapper362_Init (CartInfo *info) {
|
||||
VRC24_init(info, sync, 0x01, 0x02, 1, 0, 0);
|
||||
VRC4_init(info, sync, 0x01, 0x02, 0, NULL, NULL, NULL, NULL, NULL);
|
||||
info->Power =Mapper362_power;
|
||||
if (PRGsize[0] >512*1024) {
|
||||
info->Reset =Mapper362_reset;
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "vrc2and4.h"
|
||||
#include "asic_vrc2and4.h"
|
||||
#include "wram.h"
|
||||
|
||||
static uint8 reg;
|
||||
|
||||
@@ -38,7 +39,7 @@ static void sync () {
|
||||
DECLFW(Mapper384_writeReg) {
|
||||
if (A &0x800 && ~reg &0x08) {
|
||||
reg =V;
|
||||
VRC24_Sync();
|
||||
sync();
|
||||
}
|
||||
CartBW(A, V);
|
||||
}
|
||||
@@ -50,12 +51,12 @@ void Mapper384_power(void) {
|
||||
|
||||
void Mapper384_reset(void) {
|
||||
reg =0;
|
||||
VRC24_Sync();
|
||||
sync();
|
||||
}
|
||||
|
||||
void Mapper384_Init (CartInfo *info) {
|
||||
VRC24_init(info, sync, 0x04, 0x08, 1, 0, 2);
|
||||
VRC24_WRAMWrite =Mapper384_writeReg;
|
||||
VRC4_init(info, sync, 0x04, 0x08, 0, NULL, NULL, NULL, Mapper384_writeReg, NULL);
|
||||
WRAM_init(info, 2);
|
||||
info->Power =Mapper384_power;
|
||||
info->Reset =Mapper384_reset;
|
||||
AddExState(Mapper384_stateRegs, ~0, 0, 0);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "vrc2and4.h"
|
||||
#include "asic_vrc2and4.h"
|
||||
|
||||
static uint8 reg;
|
||||
|
||||
@@ -30,8 +30,8 @@ static SFORMAT Mapper398_stateRegs[] ={
|
||||
|
||||
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);
|
||||
@@ -41,7 +41,6 @@ static void sync () {
|
||||
|
||||
DECLFW(Mapper398_writeReg) {
|
||||
reg =A &0xFF;
|
||||
VRC24_Sync();
|
||||
VRC24_writeReg(A, V);
|
||||
}
|
||||
|
||||
@@ -53,11 +52,11 @@ void Mapper398_power(void) {
|
||||
|
||||
void Mapper398_reset(void) {
|
||||
reg =0xC0;
|
||||
VRC24_Sync();
|
||||
sync();
|
||||
}
|
||||
|
||||
void Mapper398_Init (CartInfo *info) {
|
||||
VRC24_init(info, sync, 0x01, 0x02, 1, 1, 0);
|
||||
VRC4_init(info, sync, 0x01, 0x02, 1, NULL, NULL, NULL, NULL, NULL);
|
||||
info->Power =Mapper398_power;
|
||||
info->Reset =Mapper398_reset;
|
||||
AddExState(Mapper398_stateRegs, ~0, 0, 0);
|
||||
|
||||
@@ -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;
|
||||
sync();
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
423
src/boards/446.c
Normal file
423
src/boards/446.c
Normal file
@@ -0,0 +1,423 @@
|
||||
/* 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_mmc2.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 "wram.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);
|
||||
MMC2_syncCHR(chrAND, chrOR &~chrAND);
|
||||
MMC2_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_write(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;
|
||||
MMC2_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();
|
||||
MMC2_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,7 +19,8 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "vrc2and4.h"
|
||||
#include "asic_vrc2and4.h"
|
||||
#include "wram.h"
|
||||
|
||||
static uint8 reg;
|
||||
static uint8 dip;
|
||||
@@ -37,7 +38,7 @@ static void sync () {
|
||||
VRC24_syncWRAM(0);
|
||||
}
|
||||
|
||||
static int Mapper447_getPRGBank(int bank) {
|
||||
static int Mapper447_getPRGBank(uint8 bank) {
|
||||
if (reg &4) {
|
||||
if (~reg &2)
|
||||
return VRC24_getPRGBank(bank &1) &~2 | bank &2;
|
||||
@@ -52,9 +53,9 @@ DECLFR(Mapper447_readPRG) {
|
||||
}
|
||||
|
||||
DECLFW(Mapper447_writeReg) {
|
||||
if (VRC24_misc &1 && ~reg &1) {
|
||||
if (~reg &1) {
|
||||
reg =A &0xFF;
|
||||
VRC24_Sync();
|
||||
sync();
|
||||
}
|
||||
CartBW(A, V);
|
||||
}
|
||||
@@ -69,13 +70,12 @@ void Mapper447_power(void) {
|
||||
void Mapper447_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;
|
||||
VRC4_init(info, sync, 0x04, 0x08, 0, Mapper447_getPRGBank, NULL, NULL, Mapper447_writeReg, NULL );
|
||||
WRAM_init(info, 2);
|
||||
info->Power =Mapper447_power;
|
||||
info->Reset =Mapper447_reset;
|
||||
AddExState(Mapper447_stateRegs, ~0, 0, 0);
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "vrc2and4.h"
|
||||
#include "asic_vrc2and4.h"
|
||||
#include "wram.h"
|
||||
|
||||
static uint8 reg;
|
||||
|
||||
@@ -30,15 +31,15 @@ static SFORMAT Mapper448_stateRegs[] ={
|
||||
|
||||
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();
|
||||
}
|
||||
@@ -46,10 +47,8 @@ static void sync () {
|
||||
}
|
||||
|
||||
DECLFW(Mapper448_writeReg) {
|
||||
if (VRC24_misc &1) {
|
||||
reg =A &0xFF;
|
||||
VRC24_Sync();
|
||||
}
|
||||
reg =A &0xFF;
|
||||
sync();
|
||||
CartBW(A, V);
|
||||
}
|
||||
|
||||
@@ -65,12 +64,12 @@ void Mapper448_power(void) {
|
||||
|
||||
void Mapper448_reset(void) {
|
||||
reg =0;
|
||||
VRC24_Sync();
|
||||
sync();
|
||||
}
|
||||
|
||||
void Mapper448_Init (CartInfo *info) {
|
||||
VRC24_init(info, sync, 0x04, 0x08, 1, 0, 2);
|
||||
VRC24_WRAMWrite =Mapper448_writeReg;
|
||||
VRC4_init(info, sync, 0x04, 0x08, 0, NULL, NULL, NULL, Mapper448_writeReg, NULL);
|
||||
WRAM_init(info, 2);
|
||||
info->Power =Mapper448_power;
|
||||
info->Reset =Mapper448_reset;
|
||||
AddExState(Mapper448_stateRegs, ~0, 0, 0);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "vrc2and4.h"
|
||||
#include "asic_vrc2and4.h"
|
||||
|
||||
static void sync () {
|
||||
VRC24_syncPRG(0x0F, VRC2_pins <<4);
|
||||
@@ -29,10 +29,10 @@ static void sync () {
|
||||
|
||||
void Mapper450_reset(void) {
|
||||
VRC2_pins =0;
|
||||
VRC24_Sync();
|
||||
sync();
|
||||
}
|
||||
|
||||
void Mapper450_Init (CartInfo *info) {
|
||||
VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0);
|
||||
VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL);
|
||||
info->Reset =Mapper450_reset;
|
||||
}
|
||||
|
||||
@@ -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,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "vrc2and4.h"
|
||||
#include "asic_vrc2and4.h"
|
||||
|
||||
static uint8 irqEnabled;
|
||||
static uint16 irqCounter;
|
||||
@@ -58,7 +58,7 @@ void BTL900218_power(void) {
|
||||
}
|
||||
|
||||
void BTL900218_Init (CartInfo *info) {
|
||||
VRC24_init(info, sync, 0x01, 0x02, 0, 0, 0);
|
||||
VRC2_init(info, sync, 0x01, 0x02, NULL, NULL, NULL, NULL);
|
||||
AddExState(BTL900218_stateRegs, ~0, 0, 0);
|
||||
info->Power =BTL900218_power;
|
||||
MapIRQHook =BTL900218_cpuCycle;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "vrc2and4.h"
|
||||
#include "asic_vrc2and4.h"
|
||||
|
||||
static void sync () {
|
||||
VRC24_syncPRG(0x01F, 0x000);
|
||||
@@ -28,8 +28,8 @@ static void sync () {
|
||||
}
|
||||
|
||||
DECLFW(UNLKS7021A_writeCHR) {
|
||||
VRC24_chr[A &7] =V;
|
||||
VRC24_Sync();
|
||||
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);
|
||||
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,7 +30,7 @@ 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();
|
||||
@@ -52,7 +52,7 @@ void UNLT230_power (void) {
|
||||
}
|
||||
|
||||
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;
|
||||
AddExState(stateRegs, ~0, 0, 0);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "vrc2and4.h"
|
||||
#include "asic_vrc2and4.h"
|
||||
|
||||
static void sync () {
|
||||
VRC24_syncPRG(0x01F, 0x000);
|
||||
@@ -27,12 +27,12 @@ static void sync () {
|
||||
VRC24_syncMirror();
|
||||
}
|
||||
|
||||
int UNLAX5705_getPRGBank(int bank) {
|
||||
int UNLAX5705_getPRGBank(uint8 bank) {
|
||||
int result =VRC24_getPRGBank(bank);
|
||||
return result <<2 &0x8 | result >>2 &0x2 | result &~0xA;
|
||||
}
|
||||
|
||||
int UNLAX5705_getCHRBank(int bank) {
|
||||
int UNLAX5705_getCHRBank(uint8 bank) {
|
||||
int result =VRC24_getCHRBank(bank);
|
||||
return result <<1 &0x40 | result >>1 &0x20 | result &~0x60;
|
||||
}
|
||||
@@ -47,8 +47,6 @@ void UNLAX5705_power (void) {
|
||||
}
|
||||
|
||||
void UNLAX5705_Init (CartInfo *info) {
|
||||
VRC24_init(info, sync, 0x01, 0x02, 1, 1, 0);
|
||||
VRC4_init(info, sync, 0x01, 0x02, 1, UNLAX5705_getPRGBank, UNLAX5705_getCHRBank, NULL, NULL, NULL);
|
||||
info->Power =UNLAX5705_power;
|
||||
VRC24_GetPRGBank =UNLAX5705_getPRGBank;
|
||||
VRC24_GetCHRBank =UNLAX5705_getCHRBank;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "vrc2and4.h"
|
||||
#include "asic_vrc2and4.h"
|
||||
|
||||
static uint8 reg;
|
||||
|
||||
@@ -39,7 +39,7 @@ static void sync () {
|
||||
DECLFW(Mapper542_writeExtra) {
|
||||
if (A &0x800) {
|
||||
reg =A >>12;
|
||||
VRC24_Sync();
|
||||
sync();
|
||||
} else
|
||||
VRC24_writeReg(A, V);
|
||||
}
|
||||
@@ -53,7 +53,7 @@ void Mapper542_power (void) {
|
||||
}
|
||||
|
||||
void Mapper542_Init (CartInfo *info) {
|
||||
VRC24_init(info, sync, 0x01, 0x02, 1, 1, 0);
|
||||
VRC4_init(info, sync, 0x01, 0x02, 1, NULL, NULL, NULL, NULL, NULL);
|
||||
info->Power =Mapper542_power;
|
||||
AddExState(stateRegs, ~0, 0, 0);
|
||||
SetupCartCHRMapping(0x10, NTARAM, 0x200, 1);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "vrc2and4.h"
|
||||
#include "asic_vrc2and4.h"
|
||||
|
||||
static uint8 *CHRRAM;
|
||||
static uint32 CHRRAMSize;
|
||||
@@ -43,14 +43,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) {
|
||||
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,13 +60,13 @@ static DECLFW(Mapper544_interceptPPUWrite) {
|
||||
mask =bank &0x40? 0xFE: 0xFC;
|
||||
compare =compares[index];
|
||||
}
|
||||
VRC24_Sync();
|
||||
sync();
|
||||
}
|
||||
}
|
||||
writePPU(A, V);
|
||||
}
|
||||
|
||||
int Mapper544_getPRGBank(int bank) {
|
||||
int Mapper544_getPRGBank(uint8 bank) {
|
||||
return bank ==2? prg: VRC24_getPRGBank(bank);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ DECLFW(Mapper544_externalSelect) {
|
||||
nt[A &3] =V;
|
||||
else
|
||||
prg =V;
|
||||
VRC24_Sync();
|
||||
sync();
|
||||
}
|
||||
|
||||
|
||||
@@ -98,11 +98,9 @@ void Mapper544_close(void) {
|
||||
}
|
||||
|
||||
void Mapper544_Init (CartInfo *info) {
|
||||
VRC24_init(info, sync, 0x400, 0x800, 1, 1, 0);
|
||||
VRC4_init(info, sync, 0x400, 0x800, 1, Mapper544_getPRGBank, NULL, NULL, NULL, Mapper544_externalSelect);
|
||||
info->Power =Mapper544_power;
|
||||
info->Close =Mapper544_close;
|
||||
VRC24_GetPRGBank =Mapper544_getPRGBank;
|
||||
VRC24_ExternalSelect =Mapper544_externalSelect;
|
||||
AddExState(stateRegs, ~0, 0, 0);
|
||||
|
||||
CHRRAMSize =info->CHRRamSize +info->CHRRamSaveSize;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "vrc2and4.h"
|
||||
#include "asic_vrc2and4.h"
|
||||
|
||||
static uint8 nt[4];
|
||||
static uint8 prg;
|
||||
@@ -38,7 +38,7 @@ static void sync () {
|
||||
setmirrorw(nt[0] &1, nt[1] &1, nt[2] &1, nt[3] &1);
|
||||
}
|
||||
|
||||
int Mapper559_getPRGBank(int bank) {
|
||||
int Mapper559_getPRGBank(uint8 bank) {
|
||||
return bank ==2? prg: VRC24_getPRGBank(bank);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ DECLFW(Mapper559_externalSelect) {
|
||||
nt[A &3] =V;
|
||||
else
|
||||
prg =V;
|
||||
VRC24_Sync();
|
||||
sync();
|
||||
}
|
||||
|
||||
DECLFW(Mapper559_nibblizeData) {
|
||||
@@ -63,9 +63,7 @@ void Mapper559_power (void) {
|
||||
}
|
||||
|
||||
void Mapper559_Init (CartInfo *info) {
|
||||
VRC24_init(info, sync, 0x400, 0x800, 1, 1, 0);
|
||||
VRC4_init(info, sync, 0x400, 0x800, 1, Mapper559_getPRGBank, NULL, NULL, NULL, Mapper559_externalSelect);
|
||||
info->Power =Mapper559_power;
|
||||
VRC24_GetPRGBank =Mapper559_getPRGBank;
|
||||
VRC24_ExternalSelect =Mapper559_externalSelect;
|
||||
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;
|
||||
@@ -56,7 +56,7 @@ void Mapper563_power(void) {
|
||||
}
|
||||
|
||||
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;
|
||||
GameHBIRQHook = Mapper563_scanline;
|
||||
|
||||
165
src/boards/asic_h3001.c
Normal file
165
src/boards/asic_h3001.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/* 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_h3001.h"
|
||||
|
||||
static void (*H3001_cbSync)();
|
||||
static uint8 H3001_prg[2];
|
||||
static uint8 H3001_chr[8];
|
||||
static uint8 H3001_layout;
|
||||
static uint8 H3001_nt;
|
||||
static uint8 H3001_irq;
|
||||
static uint16 H3001_reload;
|
||||
static uint16 H3001_count;
|
||||
|
||||
static SFORMAT H3001_state[] = {
|
||||
{ H3001_prg, 2, "H31P" },
|
||||
{ H3001_chr, 8, "H31C" },
|
||||
{&H3001_layout, 4, "H31L" },
|
||||
{&H3001_nt, 4, "H31M" },
|
||||
{&H3001_irq, 4, "H31N" },
|
||||
{&H3001_reload, 2, "H31R" },
|
||||
{&H3001_count, 2, "H31T" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static int H3001_getPRGBank (uint8 bank) {
|
||||
if (H3001_layout &0x80 && ~bank &1) bank ^= 2;
|
||||
return bank &2? 0xFE | bank &1: H3001_prg[bank &1];
|
||||
}
|
||||
|
||||
void H3001_syncPRG (int AND, int OR) {
|
||||
setprg8(0x8000, H3001_getPRGBank(0) &AND |OR);
|
||||
setprg8(0xA000, H3001_getPRGBank(1) &AND |OR);
|
||||
setprg8(0xC000, H3001_getPRGBank(2) &AND |OR);
|
||||
setprg8(0xE000, H3001_getPRGBank(3) &AND |OR);
|
||||
}
|
||||
|
||||
void H3001_syncCHR (int AND, int OR) {
|
||||
setchr1(0x0000, H3001_chr[0]);
|
||||
setchr1(0x0400, H3001_chr[1]);
|
||||
setchr1(0x0800, H3001_chr[2]);
|
||||
setchr1(0x0C00, H3001_chr[3]);
|
||||
setchr1(0x1000, H3001_chr[4]);
|
||||
setchr1(0x1400, H3001_chr[5]);
|
||||
setchr1(0x1800, H3001_chr[6]);
|
||||
setchr1(0x1C00, H3001_chr[7]);
|
||||
}
|
||||
|
||||
void H3001_syncMirror () {
|
||||
setmirror(H3001_nt &0x40? (H3001_nt &0x80? MI_1: MI_0): H3001_nt &0x80? MI_H: MI_V);
|
||||
}
|
||||
|
||||
DECLFW(H3001_write) {
|
||||
switch(A >>12 &7) {
|
||||
case 0: case 2:
|
||||
H3001_prg[A >>13 &1] = V;
|
||||
H3001_cbSync();
|
||||
break;
|
||||
case 1:
|
||||
switch(A &7) {
|
||||
case 0:
|
||||
H3001_layout = V;
|
||||
H3001_cbSync();
|
||||
break;
|
||||
case 1:
|
||||
H3001_nt = V;
|
||||
H3001_cbSync();
|
||||
break;
|
||||
case 3:
|
||||
H3001_irq = V;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
case 4:
|
||||
H3001_count = H3001_reload;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
case 5:
|
||||
H3001_reload = H3001_reload &0x00FF | V <<8;
|
||||
break;
|
||||
case 6:
|
||||
H3001_reload = H3001_reload &0xFF00 | V;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
H3001_chr[A &7] = V;
|
||||
H3001_cbSync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FP_FASTAPASS(1) H3001_cpuCycle (int a) {
|
||||
while (a--) if (H3001_irq &0x80 && !--H3001_count) {
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
H3001_irq = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void H3001_clear () {
|
||||
int i;
|
||||
for (i = 0; i < 2; i++) H3001_prg[i] = i;
|
||||
for (i = 0; i < 8; i++) H3001_chr[i] = i;
|
||||
H3001_layout = H3001_nt = H3001_irq = 0;
|
||||
H3001_reload = H3001_count = 0;
|
||||
H3001_cbSync();
|
||||
}
|
||||
|
||||
static void H3001_setHandlers () {
|
||||
SetReadHandler (0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xBFFF, H3001_write);
|
||||
MapIRQHook =H3001_cpuCycle;
|
||||
}
|
||||
|
||||
static void H3001_configure (void (*sync)()) {
|
||||
H3001_cbSync = sync;
|
||||
}
|
||||
|
||||
void H3001_activate (uint8 clear, void (*sync)()) {
|
||||
H3001_configure(sync);
|
||||
H3001_setHandlers();
|
||||
if (clear)
|
||||
H3001_clear();
|
||||
else
|
||||
H3001_cbSync();
|
||||
|
||||
}
|
||||
|
||||
void H3001_addExState () {
|
||||
AddExState(H3001_state, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void H3001_restore (int version) {
|
||||
H3001_cbSync();
|
||||
}
|
||||
|
||||
void H3001_power () {
|
||||
H3001_setHandlers();
|
||||
H3001_clear();
|
||||
}
|
||||
|
||||
void H3001_init (CartInfo *info, void (*sync)()) {
|
||||
H3001_addExState();
|
||||
H3001_configure(sync);
|
||||
info->Power = H3001_power;
|
||||
info->Reset = H3001_cbSync;
|
||||
GameStateRestore = H3001_cbSync;
|
||||
}
|
||||
34
src/boards/asic_h3001.h
Normal file
34
src/boards/asic_h3001.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#ifndef _ASIC_H3001_H
|
||||
#define _ASIC_H3001_H
|
||||
|
||||
void H3001_syncPRG (int, int);
|
||||
void H3001_syncCHR (int, int);
|
||||
void H3001_syncMirror ();
|
||||
DECLFW (H3001_write);
|
||||
void H3001_activate (uint8, void (*)());
|
||||
void H3001_addExState ();
|
||||
void H3001_restore (int);
|
||||
void H3001_power ();
|
||||
void H3001_init (CartInfo *, void (*)());
|
||||
|
||||
#endif
|
||||
89
src/boards/asic_latch.c
Normal file
89
src/boards/asic_latch.c
Normal file
@@ -0,0 +1,89 @@
|
||||
/* 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 (*Latch_cbSync)();
|
||||
static uint16 Latch_from, Latch_to;
|
||||
static void (*Latch_cbWrite)(uint16*, uint8*, uint8);
|
||||
uint16 Latch_address;
|
||||
uint8 Latch_data;
|
||||
|
||||
static SFORMAT Latch_state[] = {
|
||||
{&Latch_address, 2, "LATA" },
|
||||
{&Latch_data, 1, "LATD" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DECLFW(Latch_write) {
|
||||
uint16 newAddress = A &0xFFFF;
|
||||
if (Latch_cbWrite) Latch_cbWrite(&newAddress, &V, CartBR(A));
|
||||
Latch_address = A;
|
||||
Latch_data = V;
|
||||
Latch_cbSync();
|
||||
}
|
||||
|
||||
static void Latch_clear () {
|
||||
Latch_address = 0;
|
||||
Latch_data = 0;
|
||||
Latch_cbSync();
|
||||
}
|
||||
|
||||
static void Latch_setHandlers() {
|
||||
SetWriteHandler(Latch_from, Latch_to, Latch_write);
|
||||
}
|
||||
|
||||
static void Latch_configure (void (*sync)(), uint16 from, uint16 to, void (*write)(uint16*, uint8*, uint8)) {
|
||||
Latch_cbSync = sync;
|
||||
Latch_from = from;
|
||||
Latch_to = to;
|
||||
Latch_cbWrite = write;
|
||||
}
|
||||
|
||||
void Latch_activate (uint8 clear, void (*sync)(), uint16 from, uint16 to, void (*write)(uint16*, uint8*, uint8)) {
|
||||
Latch_configure(sync, from, to, write);
|
||||
Latch_setHandlers();
|
||||
if (clear)
|
||||
Latch_clear();
|
||||
else
|
||||
Latch_cbSync();
|
||||
}
|
||||
|
||||
void Latch_addExState () {
|
||||
AddExState(Latch_state, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void Latch_restore (int version) {
|
||||
Latch_cbSync();
|
||||
}
|
||||
|
||||
void Latch_power () {
|
||||
Latch_setHandlers();
|
||||
Latch_clear();
|
||||
}
|
||||
|
||||
void Latch_init (CartInfo *info, void (*sync)(), uint16 from, uint16 to, void (*write)(uint16*, uint8*, uint8)) {
|
||||
Latch_addExState();
|
||||
Latch_configure(sync, from, to, write);
|
||||
info->Power = Latch_power;
|
||||
info->Reset = Latch_cbSync;
|
||||
GameStateRestore = Latch_restore;
|
||||
}
|
||||
35
src/boards/asic_latch.h
Normal file
35
src/boards/asic_latch.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#ifndef _ASIC_LATCH_H
|
||||
#define _ASIC_LATCH_H
|
||||
|
||||
extern uint16 Latch_address;
|
||||
extern uint8 Latch_data;
|
||||
|
||||
DECLFW (Latch_write);
|
||||
void Latch_addExState ();
|
||||
void Latch_restore (int);
|
||||
void Latch_power ();
|
||||
void Latch_activate (uint8, void (*)(), uint16, uint16, void (*)(uint16*, uint8*, uint8));
|
||||
void Latch6_activate (uint8, void (*)(), uint16, uint16, void (*)(uint16*, uint8*, uint8));
|
||||
void Latch_init (CartInfo *, void (*)(), uint16, uint16, void (*)(uint16*, uint8*, uint8));
|
||||
|
||||
#endif
|
||||
169
src/boards/asic_mmc1.c
Normal file
169
src/boards/asic_mmc1.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/* 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_mmc1.h"
|
||||
|
||||
static void (*MMC1_cbSync)();
|
||||
static int (*MMC1_cbGetPRGBank)(uint8);
|
||||
static int (*MMC1_cbGetCHRBank)(uint8);
|
||||
static DECLFR ((*MMC1_cbReadWRAM));
|
||||
static DECLFW ((*MMC1_cbWriteWRAM));
|
||||
static uint8 MMC1_type;
|
||||
static uint8 MMC1_bits;
|
||||
static uint8 MMC1_shift;
|
||||
static uint8 MMC1_filter;
|
||||
static uint8 MMC1_reg[4];
|
||||
|
||||
static SFORMAT MMC1_state[] = {
|
||||
{ MMC1_reg, 4, "MC1R" },
|
||||
{&MMC1_bits, 1, "MC1B" },
|
||||
{&MMC1_shift, 1, "MC1S" },
|
||||
{&MMC1_filter, 1, "MC1F" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
void MMC1_syncWRAM (int OR) {
|
||||
if (PRGsize[0x10]) setprg8r(0x10, 0x6000, OR);
|
||||
}
|
||||
|
||||
int MMC1_getPRGBank (uint8 bank) {
|
||||
int result;
|
||||
if (MMC1_reg[0] &0x08)
|
||||
result = MMC1_reg[0] &0x04? (MMC1_reg[3] |bank*0xF): (MMC1_reg[3] &bank*0xF);
|
||||
else
|
||||
result = MMC1_reg[3] &~1 |bank;
|
||||
|
||||
if (MMC1_reg[3] &0x10 && MMC1_type == MMC1_TYPE_MMC1A)
|
||||
return result &0x07 | MMC1_reg[3] &0x08;
|
||||
else
|
||||
return result &0x0F;
|
||||
}
|
||||
|
||||
int MMC1_getCHRBank (uint8 bank) {
|
||||
if (MMC1_reg[0] &0x10)
|
||||
return MMC1_reg[1 +bank];
|
||||
else
|
||||
return MMC1_reg[1] &~1 |bank;
|
||||
}
|
||||
|
||||
DECLFR(MMC1_readWRAM) {
|
||||
if (MMC1_type == MMC1_TYPE_MMC1A || ~MMC1_reg[3] &0x10)
|
||||
return MMC1_cbReadWRAM? MMC1_cbReadWRAM(A): CartBR(A);
|
||||
else
|
||||
return A >>8;
|
||||
}
|
||||
|
||||
DECLFW(MMC1_writeWRAM) {
|
||||
if (MMC1_type == MMC1_TYPE_MMC1A || ~MMC1_reg[3] &0x10) {
|
||||
CartBW(A, V);
|
||||
if (MMC1_cbWriteWRAM) MMC1_cbWriteWRAM(A, V);
|
||||
}
|
||||
}
|
||||
|
||||
void MMC1_syncPRG (int AND, int OR) {
|
||||
setprg16(0x8000, MMC1_cbGetPRGBank(0) &AND |OR);
|
||||
setprg16(0xC000, MMC1_cbGetPRGBank(1) &AND |OR);
|
||||
}
|
||||
|
||||
void MMC1_syncCHR (int AND, int OR) {
|
||||
setchr4(0x0000, MMC1_cbGetCHRBank(0) &AND |OR);
|
||||
setchr4(0x1000, MMC1_cbGetCHRBank(1) &AND |OR);
|
||||
}
|
||||
|
||||
void MMC1_syncMirror () {
|
||||
setmirror(MMC1_reg[0] &2? (MMC1_reg[0] &1? MI_H: MI_V): (MMC1_reg[0] &1? MI_1: MI_0));
|
||||
}
|
||||
|
||||
void FP_FASTAPASS(1) MMC1_cpuCycle(int a) {
|
||||
while (a--) if (MMC1_filter) MMC1_filter--;
|
||||
}
|
||||
|
||||
DECLFW(MMC1_write) {
|
||||
if (V &0x80) {
|
||||
MMC1_reg[0] |= 0x0C;
|
||||
MMC1_shift = 0;
|
||||
MMC1_bits = 0;
|
||||
MMC1_cbSync();
|
||||
} else
|
||||
if (!MMC1_filter) {
|
||||
MMC1_shift |= (V &1) <<MMC1_bits++;
|
||||
if (MMC1_bits == 5) {
|
||||
MMC1_reg[A >>13 &3] = MMC1_shift;
|
||||
MMC1_shift = 0;
|
||||
MMC1_bits = 0;
|
||||
MMC1_cbSync();
|
||||
}
|
||||
}
|
||||
MMC1_filter = 2;
|
||||
}
|
||||
|
||||
static void MMC1_clear() {
|
||||
MMC1_reg[0] = 0x0C; MMC1_reg[1] = 0; MMC1_reg[2] = 2; MMC1_reg[3] = 0;
|
||||
MMC1_bits = 0; MMC1_shift = 0; MMC1_filter = 0;
|
||||
MMC1_cbSync();
|
||||
}
|
||||
|
||||
static void MMC1_setHandlers () {
|
||||
SetReadHandler (0x6000, 0x7FFF, MMC1_readWRAM);
|
||||
SetWriteHandler(0x6000, 0x7FFF, MMC1_writeWRAM);
|
||||
SetReadHandler (0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, MMC1_write);
|
||||
MapIRQHook = MMC1_cpuCycle;
|
||||
}
|
||||
|
||||
static void MMC1_configure (void (*sync)(), uint8 type, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) {
|
||||
MMC1_type = type;
|
||||
MMC1_cbSync = sync;
|
||||
MMC1_cbGetPRGBank = prg? prg: MMC1_getPRGBank;
|
||||
MMC1_cbGetCHRBank = chr? chr: MMC1_getCHRBank;
|
||||
MMC1_cbReadWRAM = read;
|
||||
MMC1_cbWriteWRAM = write;
|
||||
}
|
||||
|
||||
void MMC1_activate (uint8 clear, void (*sync)(), uint8 type, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) {
|
||||
MMC1_configure(sync, type, prg, chr, read, write);
|
||||
MMC1_setHandlers();
|
||||
if (clear)
|
||||
MMC1_clear();
|
||||
else
|
||||
MMC1_cbSync();
|
||||
}
|
||||
|
||||
void MMC1_addExState () {
|
||||
AddExState(MMC1_state, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void MMC1_restore (int version) {
|
||||
MMC1_cbSync();
|
||||
}
|
||||
|
||||
void MMC1_power () {
|
||||
MMC1_setHandlers();
|
||||
MMC1_clear();
|
||||
}
|
||||
|
||||
void MMC1_init (CartInfo *info, void (*sync)(), uint8 type, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) {
|
||||
MMC1_addExState();
|
||||
MMC1_configure(sync, type, prg, chr, read, write);
|
||||
info->Power = MMC1_power;
|
||||
info->Reset = MMC1_cbSync;
|
||||
GameStateRestore = MMC1_restore;
|
||||
}
|
||||
41
src/boards/asic_mmc1.h
Normal file
41
src/boards/asic_mmc1.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#ifndef _ASIC_MMC1_H
|
||||
#define _ASIC_MMC1_H
|
||||
|
||||
#define MMC1_TYPE_MMC1A 0
|
||||
#define MMC1_TYPE_MMC1B 1
|
||||
|
||||
void MMC1_syncWRAM (int);
|
||||
int MMC1_getPRGBank (uint8);
|
||||
int MMC1_getCHRBank (uint8);
|
||||
void MMC1_syncPRG (int, int);
|
||||
void MMC1_syncCHR (int, int);
|
||||
void MMC1_syncMirror ();
|
||||
void FP_FASTAPASS(1) MMC1_cpuCycle(int);
|
||||
DECLFW (MMC1_write);
|
||||
void MMC1_addExState ();
|
||||
void MMC1_restore (int);
|
||||
void MMC1_power ();
|
||||
void MMC1_activate (uint8, void (*)(), uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*)));
|
||||
void MMC1_init (CartInfo *, void (*)(), uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*)));
|
||||
|
||||
#endif
|
||||
108
src/boards/asic_mmc2.c
Normal file
108
src/boards/asic_mmc2.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/* 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_mmc2.h"
|
||||
|
||||
static void (*MMC2_cbSync)();
|
||||
static uint8 MMC2_reg[6];
|
||||
static uint8 MMC2_latch[2];
|
||||
|
||||
static SFORMAT MMC2_state[] = {
|
||||
{ MMC2_reg, 6, "MC2R" },
|
||||
{ MMC2_latch, 2, "MC2S" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void (*MMC2_cbSync)();
|
||||
|
||||
void MMC2_syncPRG (int AND, int OR) {
|
||||
setprg8(0x8000, MMC2_reg[0] &AND |OR);
|
||||
setprg8(0xA000, 0xD &AND |OR);
|
||||
setprg8(0xC000, 0xE &AND |OR);
|
||||
setprg8(0xE000, 0xF &AND |OR);
|
||||
}
|
||||
|
||||
void MMC2_syncCHR (int AND, int OR) {
|
||||
setchr4(0x0000, MMC2_reg[1 +MMC2_latch[0]] &AND |OR);
|
||||
setchr4(0x1000, MMC2_reg[3 +MMC2_latch[1]] &AND |OR);
|
||||
}
|
||||
|
||||
void MMC2_syncMirror () {
|
||||
setmirror(MMC2_reg[5] &1? MI_H: MI_V);
|
||||
}
|
||||
|
||||
static void FP_FASTAPASS(1) MMC2_trapPPUAddressChange (uint32 A) {
|
||||
if ((A &0x2FF0) == 0xFD0 || (A &0x2FF0) == 0xFE0) {
|
||||
MMC2_latch[A >>12 &1] = A >>5 &1;
|
||||
MMC2_cbSync();
|
||||
}
|
||||
}
|
||||
|
||||
DECLFW(MMC2_write) {
|
||||
MMC2_reg[(A >>12) -0xA] = V;
|
||||
MMC2_cbSync();
|
||||
}
|
||||
|
||||
static void MMC2_clear () {
|
||||
MMC2_reg[0] = 0; MMC2_reg[1] = 0; MMC2_reg[2] = 2; MMC2_reg[3] = 0; MMC2_reg[4] = 0; MMC2_reg[5] = 0;
|
||||
MMC2_latch[0] = 0; MMC2_latch[1] = 0;
|
||||
MMC2_cbSync();
|
||||
}
|
||||
|
||||
static void MMC2_setHandlers() {
|
||||
SetReadHandler (0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0xA000, 0xFFFF, MMC2_write);
|
||||
PPU_hook = MMC2_trapPPUAddressChange;
|
||||
}
|
||||
|
||||
static void MMC2_configure (void (*sync)()) {
|
||||
MMC2_cbSync = sync;
|
||||
}
|
||||
|
||||
void MMC2_activate (uint8 clear, void (*sync)()) {
|
||||
MMC2_configure(sync);
|
||||
MMC2_setHandlers();
|
||||
if (clear)
|
||||
MMC2_clear();
|
||||
else
|
||||
MMC2_cbSync();
|
||||
}
|
||||
|
||||
void MMC2_addExState () {
|
||||
AddExState(MMC2_state, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void MMC2_restore (int version) {
|
||||
MMC2_cbSync();
|
||||
}
|
||||
|
||||
void MMC2_power () {
|
||||
MMC2_setHandlers();
|
||||
MMC2_clear();
|
||||
}
|
||||
|
||||
void MMC2_init (CartInfo *info, void (*sync)()) {
|
||||
MMC2_addExState();
|
||||
MMC2_configure(sync);
|
||||
info->Power = MMC2_power;
|
||||
info->Reset = MMC2_cbSync;
|
||||
GameStateRestore = MMC2_restore;
|
||||
}
|
||||
34
src/boards/asic_mmc2.h
Normal file
34
src/boards/asic_mmc2.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#ifndef _ASIC_MMC2_H
|
||||
#define _ASIC_MMC2_H
|
||||
|
||||
void MMC2_syncPRG (int, int);
|
||||
void MMC2_syncCHR (int, int);
|
||||
void MMC2_syncMirror ();
|
||||
DECLFW (MMC2_write);
|
||||
void MMC2_power ();
|
||||
void MMC2_restore (int);
|
||||
void MMC2_addExState ();
|
||||
void MMC2_activate (uint8, void (*)());
|
||||
void MMC2_init (CartInfo *, void (*)());
|
||||
|
||||
#endif
|
||||
165
src/boards/asic_mmc3.c
Normal file
165
src/boards/asic_mmc3.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/* 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_mmc3.h"
|
||||
|
||||
static void (*MMC3_cbSync)();
|
||||
static int (*MMC3_cbGetPRGBank)(uint8);
|
||||
static int (*MMC3_cbGetCHRBank)(uint8);
|
||||
static DECLFR ((*MMC3_cbReadWRAM));
|
||||
static DECLFW ((*MMC3_cbWriteWRAM));
|
||||
static uint8 MMC3_type;
|
||||
static uint8 MMC3_index;
|
||||
static uint8 MMC3_reg[8];
|
||||
static uint8 MMC3_mirroring;
|
||||
static uint8 MMC3_wramControl;
|
||||
static uint8 MMC3_reloadValue;
|
||||
static uint8 MMC3_reloadRequest;
|
||||
static uint8 MMC3_irqEnable;
|
||||
static uint8 MMC3_counter;
|
||||
|
||||
static SFORMAT MMC3_state[] = {
|
||||
{ MMC3_reg, 8, "M3GS" },
|
||||
{&MMC3_index, 1, "M3IX" },
|
||||
{&MMC3_mirroring, 1, "M3NT" },
|
||||
{&MMC3_wramControl, 1, "M3WR" },
|
||||
{&MMC3_reloadRequest, 1, "M3IR" },
|
||||
{&MMC3_counter, 1, "M3IC" },
|
||||
{&MMC3_reloadValue, 1, "M3IL" },
|
||||
{&MMC3_irqEnable, 1, "M3IA" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
void MMC3_syncWRAM (int OR) {
|
||||
if (PRGsize[0x10]) setprg8r(0x10, 0x6000, OR);
|
||||
}
|
||||
|
||||
int MMC3_getPRGBank (uint8 bank) {
|
||||
if (MMC3_index &0x40 && ~bank &1) bank ^= 2;
|
||||
return bank &2? 0xFE | bank &1: MMC3_reg[6 | bank &1];
|
||||
}
|
||||
|
||||
int MMC3_getCHRBank (uint8 bank) {
|
||||
if (MMC3_index &0x80) bank ^= 4;
|
||||
return bank &4? MMC3_reg[bank -2]: MMC3_reg[bank >>1] &~1 | bank &1;
|
||||
}
|
||||
|
||||
DECLFR(MMC3_readWRAM) {
|
||||
if (MMC3_wramControl &0x80 || MMC3_type == MMC3_TYPE_AX5202P || MMC3_type == MMC3_TYPE_MMC6)
|
||||
return MMC3_cbReadWRAM? MMC3_cbReadWRAM(A): CartBR(A);
|
||||
else
|
||||
return A >>8;
|
||||
}
|
||||
|
||||
DECLFW(MMC3_writeWRAM) {
|
||||
if ((MMC3_wramControl &0x80 || MMC3_type == MMC3_TYPE_AX5202P) && ~MMC3_wramControl &0x40 || MMC3_type == MMC3_TYPE_MMC6) {
|
||||
CartBW(A, V);
|
||||
if (MMC3_cbWriteWRAM) MMC3_cbWriteWRAM(A, V);
|
||||
}
|
||||
}
|
||||
|
||||
void MMC3_syncPRG (int AND, int OR) {
|
||||
int bank;
|
||||
for (bank = 0; bank < 4; bank++) setprg8(0x8000 | bank <<13, MMC3_cbGetPRGBank(bank) &AND |OR);
|
||||
}
|
||||
|
||||
void MMC3_syncCHR (int AND, int OR) {
|
||||
int bank;
|
||||
for (bank = 0; bank < 8; bank++) setchr1(bank <<10, MMC3_cbGetCHRBank(bank) &AND |OR);
|
||||
}
|
||||
|
||||
void MMC3_syncMirror () {
|
||||
setmirror(MMC3_mirroring &1? MI_H: MI_V);
|
||||
}
|
||||
|
||||
void MMC3_clockCounter () {
|
||||
uint8 prevCounter = MMC3_counter;
|
||||
MMC3_counter = MMC3_reloadRequest || !MMC3_counter? MMC3_reloadValue: --MMC3_counter;
|
||||
if ((prevCounter || MMC3_type != MMC3_TYPE_NEC || MMC3_reloadRequest) && !MMC3_counter && MMC3_irqEnable) X6502_IRQBegin(FCEU_IQEXT);
|
||||
MMC3_reloadRequest = 0;
|
||||
}
|
||||
|
||||
DECLFW(MMC3_write) {
|
||||
switch(A &0xE001) {
|
||||
case 0x8000: MMC3_index = V; break;
|
||||
case 0x8001: MMC3_reg[MMC3_index &7] = V; break;
|
||||
case 0xA000: MMC3_mirroring = V; break;
|
||||
case 0xA001: MMC3_wramControl = V; break;
|
||||
case 0xC000: MMC3_reloadValue = V; break;
|
||||
case 0xC001: MMC3_reloadRequest = 1; MMC3_counter = 0; break;
|
||||
case 0xE000: X6502_IRQEnd(FCEU_IQEXT); /* Fall-through */
|
||||
case 0xE001: MMC3_irqEnable = A &1; break;
|
||||
}
|
||||
if (A <0xC000) MMC3_cbSync();
|
||||
}
|
||||
|
||||
static void MMC3_clear () {
|
||||
MMC3_reg[0] = 0; MMC3_reg[1] = 2; MMC3_reg[2] = 4; MMC3_reg[3] = 5; MMC3_reg[4] = 6; MMC3_reg[5] = 7; MMC3_reg[6] = 0; MMC3_reg[7] = 1;
|
||||
MMC3_index = MMC3_mirroring = MMC3_wramControl = MMC3_reloadValue = MMC3_reloadRequest = MMC3_irqEnable = MMC3_counter = 0;
|
||||
MMC3_cbSync();
|
||||
}
|
||||
|
||||
static void MMC3_setHandlers () {
|
||||
SetReadHandler (0x6000, 0x7FFF, MMC3_readWRAM);
|
||||
SetWriteHandler(0x6000, 0x7FFF, MMC3_writeWRAM);
|
||||
SetReadHandler (0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, MMC3_write);
|
||||
GameHBIRQHook = MMC3_clockCounter;
|
||||
}
|
||||
|
||||
static void MMC3_configure (void (*sync)(), uint8 type, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) {
|
||||
MMC3_type = type;
|
||||
MMC3_cbSync = sync;
|
||||
MMC3_cbGetPRGBank = prg? prg: MMC3_getPRGBank;
|
||||
MMC3_cbGetCHRBank = chr? chr: MMC3_getCHRBank;
|
||||
MMC3_cbReadWRAM = read;
|
||||
MMC3_cbWriteWRAM = write;
|
||||
}
|
||||
|
||||
void MMC3_activate (uint8 clear, void (*sync)(), uint8 type, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) {
|
||||
MMC3_configure(sync, type, prg, chr, read, write);
|
||||
MMC3_setHandlers();
|
||||
if (clear)
|
||||
MMC3_clear();
|
||||
else
|
||||
MMC3_cbSync();
|
||||
}
|
||||
|
||||
void MMC3_addExState () {
|
||||
AddExState(MMC3_state, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void MMC3_restore (int version) {
|
||||
MMC3_cbSync();
|
||||
}
|
||||
|
||||
void MMC3_power () {
|
||||
MMC3_setHandlers();
|
||||
MMC3_clear();
|
||||
}
|
||||
|
||||
void MMC3_init (CartInfo *info, void (*sync)(), uint8 type, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) {
|
||||
MMC3_addExState();
|
||||
MMC3_configure(sync, type, prg, chr, read, write);
|
||||
info->Power = MMC3_power;
|
||||
info->Reset = MMC3_cbSync;
|
||||
GameStateRestore = MMC3_restore;
|
||||
}
|
||||
44
src/boards/asic_mmc3.h
Normal file
44
src/boards/asic_mmc3.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#ifndef _ASIC_MMC3_H
|
||||
#define _ASIC_MMC3_H
|
||||
|
||||
#define MMC3_TYPE_NEC 0 /* C000=00 causes single IRQ */
|
||||
#define MMC3_TYPE_SHARP 1 /* C000=00 causes continuous IRQs */
|
||||
#define MMC3_TYPE_ACCLAIM 2 /* No difference to SHARP with FCEU*'s PPU implementation */
|
||||
#define MMC3_TYPE_AX5202P 3 /* WRAM always enabled */
|
||||
#define MMC3_TYPE_MMC6 4 /* 1 KiB of built-in WRAM */
|
||||
|
||||
void MMC3_syncWRAM (int);
|
||||
int MMC3_getPRGBank (uint8);
|
||||
int MMC3_getCHRBank (uint8);
|
||||
void MMC3_syncPRG (int, int);
|
||||
void MMC3_syncCHR (int, int);
|
||||
void MMC3_syncMirror ();
|
||||
void MMC3_clockCounter ();
|
||||
DECLFW (MMC3_write);
|
||||
void MMC3_activate (uint8, void (*)(), uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*)));
|
||||
void MMC3_addExState();
|
||||
void MMC3_restore (int);
|
||||
void MMC3_power ();
|
||||
void MMC3_init (CartInfo *, void (*)(), uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*)));
|
||||
|
||||
#endif
|
||||
103
src/boards/asic_pt8154.c
Normal file
103
src/boards/asic_pt8154.c
Normal file
@@ -0,0 +1,103 @@
|
||||
/* 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_PT8154.h"
|
||||
#include "asic_mmc3.h"
|
||||
|
||||
static void (*PT8154_cbSync)();
|
||||
static uint8 PT8154_reg;
|
||||
|
||||
static SFORMAT PT8154_state[] = {
|
||||
{&PT8154_reg, 1, "189R" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
void PT8154_syncPRG (int AND, int OR) {
|
||||
AND >>=2;
|
||||
OR >>=2;
|
||||
setprg32(0x8000, PT8154_reg &AND | OR &~AND);
|
||||
}
|
||||
|
||||
void PT8154_syncCHR (int AND, int OR) {
|
||||
MMC3_syncCHR(AND, OR &~AND);
|
||||
}
|
||||
|
||||
void PT8154_syncMirror () {
|
||||
MMC3_syncMirror();
|
||||
}
|
||||
|
||||
DECLFW(PT8154_writeExtra) {
|
||||
if (A &0x100) {
|
||||
PT8154_reg = V >>4;
|
||||
PT8154_cbSync();
|
||||
}
|
||||
}
|
||||
|
||||
DECLFW(PT8154_writeWRAM) {
|
||||
PT8154_reg = A;
|
||||
PT8154_cbSync();
|
||||
}
|
||||
|
||||
static void PT8154_clear () {
|
||||
PT8154_reg = 0;
|
||||
PT8154_cbSync();
|
||||
}
|
||||
|
||||
static void PT8154_setHandlers () {
|
||||
SetWriteHandler(0x4020, 0x5FFF, PT8154_writeExtra);
|
||||
}
|
||||
|
||||
static void PT8154_configure (void (*sync)()) {
|
||||
PT8154_cbSync = sync;
|
||||
}
|
||||
|
||||
void PT8154_activate (uint8 clear, void (*sync)()) {
|
||||
MMC3_activate(clear, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, PT8154_writeWRAM);
|
||||
PT8154_configure(sync);
|
||||
PT8154_setHandlers();
|
||||
if (clear)
|
||||
PT8154_clear();
|
||||
else
|
||||
PT8154_cbSync();
|
||||
}
|
||||
|
||||
void PT8154_addExState () {
|
||||
AddExState(PT8154_state, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void PT8154_restore (int version) {
|
||||
PT8154_cbSync();
|
||||
}
|
||||
|
||||
void PT8154_power () {
|
||||
MMC3_power();
|
||||
PT8154_setHandlers();
|
||||
PT8154_clear();
|
||||
}
|
||||
|
||||
void PT8154_init (CartInfo *info, void (*sync)()) {
|
||||
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, PT8154_writeWRAM);
|
||||
PT8154_addExState();
|
||||
PT8154_configure(PT8154_cbSync);
|
||||
info->Power = PT8154_power;
|
||||
info->Reset = PT8154_cbSync;
|
||||
GameStateRestore = PT8154_restore;
|
||||
}
|
||||
35
src/boards/asic_pt8154.h
Normal file
35
src/boards/asic_pt8154.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#ifndef _ASIC_PT8154_H
|
||||
#define _ASIC_PT8154_H
|
||||
|
||||
void PT8154_syncPRG (int, int);
|
||||
void PT8154_syncCHR (int, int);
|
||||
void PT8154_syncMirror ();
|
||||
DECLFW (PT8154_writeExtra);
|
||||
DECLFW (PT8154_writeWRAM);
|
||||
void PT8154_activate (uint8, void (*)());
|
||||
void PT8154_addExState ();
|
||||
void PT8154_restore (int);
|
||||
void PT8154_power ();
|
||||
void PT8154_init (CartInfo *, void (*)());
|
||||
|
||||
#endif
|
||||
93
src/boards/asic_qj.c
Normal file
93
src/boards/asic_qj.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/* 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_QJ.h"
|
||||
#include "asic_mmc3.h"
|
||||
|
||||
static void (*QJ_cbSync)();
|
||||
static uint8 QJ_reg;
|
||||
|
||||
static SFORMAT QJ_state[] = {
|
||||
{&QJ_reg, 1, "QJRG" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
void QJ_syncPRG (int AND, int OR) {
|
||||
MMC3_syncPRG(0x0F &AND, QJ_reg <<4 &AND | OR &~AND);
|
||||
}
|
||||
|
||||
void QJ_syncCHR (int AND, int OR) {
|
||||
MMC3_syncCHR(0x7F &AND, QJ_reg <<7 &AND | OR &~AND);
|
||||
}
|
||||
|
||||
void QJ_syncMirror () {
|
||||
MMC3_syncMirror();
|
||||
}
|
||||
|
||||
DECLFW(QJ_writeWRAM) {
|
||||
QJ_reg = V;
|
||||
QJ_cbSync();
|
||||
}
|
||||
|
||||
static void QJ_clear () {
|
||||
QJ_reg = 0;
|
||||
QJ_cbSync();
|
||||
}
|
||||
|
||||
static void QJ_setHandlers () {
|
||||
}
|
||||
|
||||
static void QJ_configure (void (*sync)()) {
|
||||
QJ_cbSync = sync;
|
||||
}
|
||||
|
||||
void QJ_activate (uint8 clear, void (*sync)()) {
|
||||
MMC3_activate(clear, sync, MMC3_TYPE_SHARP, NULL, NULL, NULL, QJ_writeWRAM);
|
||||
QJ_configure(sync);
|
||||
QJ_setHandlers();
|
||||
if (clear)
|
||||
QJ_clear();
|
||||
else
|
||||
QJ_cbSync();
|
||||
}
|
||||
|
||||
void QJ_addExState () {
|
||||
AddExState(QJ_state, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void QJ_restore (int version) {
|
||||
QJ_cbSync();
|
||||
}
|
||||
|
||||
void QJ_power () {
|
||||
MMC3_power();
|
||||
QJ_setHandlers();
|
||||
QJ_clear();
|
||||
}
|
||||
|
||||
void QJ_init (CartInfo *info, void (*sync)()) {
|
||||
MMC3_addExState();
|
||||
QJ_addExState();
|
||||
QJ_configure(QJ_cbSync);
|
||||
info->Power = QJ_power;
|
||||
info->Reset = QJ_cbSync;
|
||||
GameStateRestore = QJ_restore;
|
||||
}
|
||||
35
src/boards/asic_qj.h
Normal file
35
src/boards/asic_qj.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#ifndef _ASIC_QJ_H
|
||||
#define _ASIC_QJ_H
|
||||
|
||||
void QJ_syncWRAM (int);
|
||||
void QJ_syncPRG (int, int);
|
||||
void QJ_syncCHR (int, int);
|
||||
void QJ_syncMirror ();
|
||||
DECLFW (QJ_write);
|
||||
void QJ_activate (uint8, void (*)());
|
||||
void QJ_addExState ();
|
||||
void QJ_restore (int);
|
||||
void QJ_power ();
|
||||
void QJ_init (CartInfo *, void (*)());
|
||||
|
||||
#endif
|
||||
106
src/boards/asic_tc3294.c
Normal file
106
src/boards/asic_tc3294.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/* 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_tc3294.h"
|
||||
#include "asic_mmc3.h"
|
||||
|
||||
static void (*TC3294_cbSync)();
|
||||
static uint8 TC3294_index;
|
||||
static uint8 TC3294_reg[4];
|
||||
|
||||
static SFORMAT TC3294_state[] = {
|
||||
{ TC3294_reg, 8, "329S" },
|
||||
{&TC3294_index, 1, "329I" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
void TC3294_syncWRAM (int OR) {
|
||||
MMC3_syncWRAM(OR);
|
||||
}
|
||||
|
||||
void TC3294_syncPRG (int AND, int OR) {
|
||||
int prgAND =~TC3294_reg[3] &0x3F;
|
||||
int prgOR = TC3294_reg[1] | TC3294_reg[2] <<2 &0x300;
|
||||
MMC3_syncPRG(prgAND &AND, prgOR &~prgAND &AND | OR &~AND);
|
||||
}
|
||||
|
||||
void TC3294_syncCHR (int AND, int OR) {
|
||||
int chrAND =0xFF >>(~TC3294_reg[2] &0xF);
|
||||
int chrOR =TC3294_reg[0] | TC3294_reg[2] <<4 &0xF00;
|
||||
MMC3_syncCHR(chrAND &AND, chrOR &~chrAND &AND | OR &~AND);
|
||||
}
|
||||
|
||||
void TC3294_syncMirror () {
|
||||
MMC3_syncMirror();
|
||||
}
|
||||
|
||||
DECLFW(TC3294_write) {
|
||||
if (~TC3294_reg[3] &0x40) {
|
||||
TC3294_reg[TC3294_index++ &3] =V;
|
||||
TC3294_cbSync();
|
||||
}
|
||||
}
|
||||
|
||||
static void TC3294_clear () {
|
||||
TC3294_reg[0] = 0x00; TC3294_reg[1] = 0x00; TC3294_reg[2] = 0x0F; TC3294_reg[3] = 0x00;
|
||||
TC3294_index = 0;
|
||||
TC3294_cbSync();
|
||||
}
|
||||
|
||||
static void TC3294_setHandlers () {
|
||||
}
|
||||
|
||||
static void TC3294_configure (void (*sync)()) {
|
||||
TC3294_cbSync = sync;
|
||||
}
|
||||
|
||||
void TC3294_activate (uint8 clear, void (*sync)()) {
|
||||
MMC3_activate(clear, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, TC3294_write);
|
||||
TC3294_configure(sync);
|
||||
TC3294_setHandlers();
|
||||
if (clear)
|
||||
TC3294_clear();
|
||||
else
|
||||
TC3294_cbSync();
|
||||
}
|
||||
|
||||
void TC3294_addExState () {
|
||||
AddExState(TC3294_state, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void TC3294_restore (int version) {
|
||||
TC3294_cbSync();
|
||||
}
|
||||
|
||||
void TC3294_power () {
|
||||
MMC3_power();
|
||||
TC3294_setHandlers();
|
||||
TC3294_clear();
|
||||
}
|
||||
|
||||
void TC3294_init (CartInfo *info, void (*sync)()) {
|
||||
MMC3_init(info, sync, MMC3_TYPE_AX5202P, NULL, NULL, NULL, TC3294_write);
|
||||
TC3294_addExState();
|
||||
TC3294_configure(TC3294_cbSync);
|
||||
info->Power = TC3294_power;
|
||||
info->Reset = TC3294_cbSync;
|
||||
GameStateRestore = TC3294_restore;
|
||||
}
|
||||
35
src/boards/asic_tc3294.h
Normal file
35
src/boards/asic_tc3294.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#ifndef _ASIC_TC3294_H
|
||||
#define _ASIC_TC3294_H
|
||||
|
||||
void TC3294_syncWRAM (int);
|
||||
void TC3294_syncPRG (int, int);
|
||||
void TC3294_syncCHR (int, int);
|
||||
void TC3294_syncMirror ();
|
||||
DECLFW (TC3294_write);
|
||||
void TC3294_activate (uint8, void (*)());
|
||||
void TC3294_addExState ();
|
||||
void TC3294_restore (int);
|
||||
void TC3294_power ();
|
||||
void TC3294_init (CartInfo *, void (*)());
|
||||
|
||||
#endif
|
||||
95
src/boards/asic_vrc1.c
Normal file
95
src/boards/asic_vrc1.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/* 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_vrc1.h"
|
||||
|
||||
static void (*VRC1_cbSync)();
|
||||
static uint8 VRC1_reg[8];
|
||||
|
||||
static SFORMAT VRC1_state[] = {
|
||||
{ VRC1_reg, 8, "VC1R" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
void VRC1_syncPRG (int AND, int OR) {
|
||||
setprg8(0x8000, VRC1_reg[0] &AND |OR);
|
||||
setprg8(0xA000, VRC1_reg[2] &AND |OR);
|
||||
setprg8(0xC000, VRC1_reg[4] &AND |OR);
|
||||
setprg8(0xE000, 0xFF &AND |OR);
|
||||
}
|
||||
|
||||
void VRC1_syncCHR (int AND, int OR) {
|
||||
setchr4(0x0000, (VRC1_reg[6] &0x0F | VRC1_reg[1] <<3 &0x10) &AND |OR);
|
||||
setchr4(0x1000, (VRC1_reg[7] &0x0F | VRC1_reg[1] <<2 &0x10) &AND |OR);
|
||||
}
|
||||
|
||||
void VRC1_syncMirror () {
|
||||
setmirror(VRC1_reg[1] &0x01? MI_H: MI_V);
|
||||
}
|
||||
|
||||
DECLFW(VRC1_write) {
|
||||
VRC1_reg[A >>12 &7] = V;
|
||||
VRC1_cbSync();
|
||||
}
|
||||
|
||||
static void VRC1_clear () {
|
||||
VRC1_reg[0] = 0x00; VRC1_reg[1] = 0; VRC1_reg[2] = 2; VRC1_reg[3] = 0;VRC1_reg[4] = 0x00; VRC1_reg[5] = 0; VRC1_reg[6] = 2; VRC1_reg[7] = 0;
|
||||
VRC1_cbSync();
|
||||
}
|
||||
|
||||
static void VRC1_setHandlers () {
|
||||
SetReadHandler (0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, VRC1_write);
|
||||
}
|
||||
|
||||
static void VRC1_configure (void (*sync)()) {
|
||||
VRC1_cbSync = sync;
|
||||
}
|
||||
|
||||
void VRC1_activate (uint8 clear, void (*sync)()) {
|
||||
VRC1_configure(sync);
|
||||
VRC1_setHandlers();
|
||||
if (clear)
|
||||
VRC1_clear();
|
||||
else
|
||||
VRC1_cbSync();
|
||||
}
|
||||
|
||||
void VRC1_addExState () {
|
||||
AddExState(VRC1_state, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void VRC1_restore (int version) {
|
||||
VRC1_cbSync();
|
||||
}
|
||||
|
||||
void VRC1_power () {
|
||||
VRC1_setHandlers();
|
||||
VRC1_clear();
|
||||
}
|
||||
|
||||
void VRC1_init (CartInfo *info, void (*sync)()) {
|
||||
VRC1_addExState();
|
||||
VRC1_configure(sync);
|
||||
info->Power = VRC1_power;
|
||||
info->Reset = VRC1_cbSync;
|
||||
GameStateRestore = VRC1_restore;
|
||||
}
|
||||
34
src/boards/asic_vrc1.h
Normal file
34
src/boards/asic_vrc1.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#ifndef _ASIC_VRC1_H
|
||||
#define _ASIC_VRC1_H
|
||||
|
||||
void VRC1_syncPRG (int, int);
|
||||
void VRC1_syncCHR (int, int);
|
||||
void VRC1_syncMirror ();
|
||||
DECLFW (VRC1_write);
|
||||
void VRC1_activate (uint8, void (*)());
|
||||
void VRC1_addExState ();
|
||||
void VRC1_restore (int);
|
||||
void VRC1_power ();
|
||||
void VRC1_init (CartInfo *, void (*)());
|
||||
|
||||
#endif
|
||||
297
src/boards/asic_vrc2and4.c
Normal file
297
src/boards/asic_vrc2and4.c
Normal file
@@ -0,0 +1,297 @@
|
||||
/* 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"
|
||||
#include "wram.h"
|
||||
|
||||
static void (*VRC24_cbSync)();
|
||||
static int VRC24_A0, VRC24_A1;
|
||||
static int (*VRC24_cbGetPRGBank)(uint8);
|
||||
static int (*VRC24_cbGetCHRBank)(uint8);
|
||||
static DECLFR((*VRC24_cbReadWRAM));
|
||||
static DECLFW((*VRC24_cbWriteWRAM));
|
||||
static DECLFW((*VRC24_cbExternalSelect));
|
||||
static uint8 VRC24_isVRC4; /* VRC2 or VRC4? VRC2 has no single-screen mirroring, no PRG A14 swap and no IRQ counter */
|
||||
static uint8 VRC24_useRepeatBit; /* Some VRC4 clones ignore the "repeat" bit in the IRQ Mode register */
|
||||
static uint8 VRC24_prg[2];
|
||||
static uint16 VRC24_chr[8];
|
||||
static uint8 VRC24_mirroring;
|
||||
static uint8 VRC24_misc;
|
||||
uint8 VRC2_pins; /* EEPROM interface */
|
||||
static uint8 VRC4_latch;
|
||||
static uint8 VRC4_mode;
|
||||
static uint8 VRC4_count;
|
||||
static signed short int VRC4_cycles;
|
||||
|
||||
static SFORMAT VRC24_stateRegs[] = {
|
||||
{ VRC24_prg, 2, "PREG" },
|
||||
{ &VRC24_chr[0], 2 | FCEUSTATE_RLSB, "CRH0" },
|
||||
{ &VRC24_chr[1], 2 | FCEUSTATE_RLSB, "CRH1" },
|
||||
{ &VRC24_chr[2], 2 | FCEUSTATE_RLSB, "CRH2" },
|
||||
{ &VRC24_chr[3], 2 | FCEUSTATE_RLSB, "CRH3" },
|
||||
{ &VRC24_chr[4], 2 | FCEUSTATE_RLSB, "CRH4" },
|
||||
{ &VRC24_chr[5], 2 | FCEUSTATE_RLSB, "CRH5" },
|
||||
{ &VRC24_chr[6], 2 | FCEUSTATE_RLSB, "CRH6" },
|
||||
{ &VRC24_chr[7], 2 | FCEUSTATE_RLSB, "CRH7" },
|
||||
{ &VRC24_mirroring, 1, "MIRR" },
|
||||
{ &VRC24_misc, 1, "MISC" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static SFORMAT VRC2_stateRegs[] = {
|
||||
{ &VRC2_pins, 1, "PINS" },
|
||||
};
|
||||
|
||||
static SFORMAT VRC4_stateRegs[] = {
|
||||
{ &VRC4_latch, 1, "LATC" },
|
||||
{ &VRC4_mode, 1, "MODE" },
|
||||
{ &VRC4_count, 1, "COUN" },
|
||||
{ &VRC4_cycles, 2 | FCEUSTATE_RLSB, "CYCL" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
void VRC24_syncPRG (int AND, int OR) {
|
||||
setprg8(0x8000, VRC24_cbGetPRGBank(0) &AND | OR);
|
||||
setprg8(0xA000, VRC24_cbGetPRGBank(1) &AND | OR);
|
||||
setprg8(0xC000, VRC24_cbGetPRGBank(2) &AND | OR);
|
||||
setprg8(0xE000, VRC24_cbGetPRGBank(3) &AND | OR);
|
||||
}
|
||||
|
||||
void VRC24_syncCHR (int AND, int OR) {
|
||||
setchr1(0x0000, VRC24_cbGetCHRBank(0) &AND | OR);
|
||||
setchr1(0x0400, VRC24_cbGetCHRBank(1) &AND | OR);
|
||||
setchr1(0x0800, VRC24_cbGetCHRBank(2) &AND | OR);
|
||||
setchr1(0x0C00, VRC24_cbGetCHRBank(3) &AND | OR);
|
||||
setchr1(0x1000, VRC24_cbGetCHRBank(4) &AND | OR);
|
||||
setchr1(0x1400, VRC24_cbGetCHRBank(5) &AND | OR);
|
||||
setchr1(0x1800, VRC24_cbGetCHRBank(6) &AND | OR);
|
||||
setchr1(0x1C00, VRC24_cbGetCHRBank(7) &AND | OR);
|
||||
}
|
||||
|
||||
void VRC24_syncWRAM (int OR) {
|
||||
if (PRGsize[0x10]) setprg8r(0x10, 0x6000, OR);
|
||||
}
|
||||
|
||||
int VRC24_getPRGBank (uint8 bank) {
|
||||
if (~bank &1 && VRC24_misc &2) bank ^= 2;
|
||||
return bank &2? (0xFE | bank &1): VRC24_prg[bank &1];
|
||||
}
|
||||
|
||||
int VRC24_getCHRBank (uint8 bank) {
|
||||
return VRC24_chr[bank &7];
|
||||
}
|
||||
|
||||
void VRC24_syncMirror () {
|
||||
setmirror(VRC24_isVRC4 && VRC24_mirroring &2? (VRC24_mirroring &1? MI_1: MI_0): (VRC24_mirroring &1? MI_H: MI_V));
|
||||
}
|
||||
|
||||
DECLFR(VRC2_readMicrowire) {
|
||||
return VRC2_pins;
|
||||
}
|
||||
|
||||
DECLFR(VRC24_readWRAM) {
|
||||
if (VRC24_misc &1 || !VRC24_isVRC4) {
|
||||
if (VRC24_cbReadWRAM)
|
||||
return VRC24_cbReadWRAM(A);
|
||||
else
|
||||
if (WRAMSize)
|
||||
CartBR(((A -0x6000) &(WRAMSize -1)) +0x6000);
|
||||
else
|
||||
return A >>8;
|
||||
} else
|
||||
return A >>8;
|
||||
}
|
||||
|
||||
DECLFW(VRC2_writeMicrowire) {
|
||||
VRC2_pins = V;
|
||||
VRC24_cbSync();
|
||||
}
|
||||
|
||||
DECLFW(VRC24_writeWRAM) {
|
||||
if (VRC24_misc &1 || !VRC24_isVRC4) {
|
||||
if (WRAMSize)
|
||||
CartBW(((A -0x6000) &(WRAMSize -1)) +0x6000, V);
|
||||
if (VRC24_cbWriteWRAM)
|
||||
VRC24_cbWriteWRAM(A, V);
|
||||
}
|
||||
}
|
||||
|
||||
DECLFW(VRC24_writeReg) {
|
||||
unsigned int index, addr;
|
||||
addr = A &0xF000 | (A &VRC24_A0? 1: 0) | (A &VRC24_A1? 2: 0); /* address as the chip sees it */
|
||||
switch (addr &0xF000) {
|
||||
case 0x8000: case 0xA000:
|
||||
VRC24_prg[addr >>13 &1] = V;
|
||||
VRC24_cbSync();
|
||||
break;
|
||||
case 0x9000:
|
||||
if (!VRC24_isVRC4 || (addr &3) == 0) {
|
||||
VRC24_mirroring = V;
|
||||
VRC24_cbSync();
|
||||
} else
|
||||
if (VRC24_isVRC4 && (addr &3) == 2) {
|
||||
VRC24_misc = V;
|
||||
VRC24_cbSync();
|
||||
}
|
||||
if (VRC24_isVRC4 && (addr &3) == 3 && VRC24_cbExternalSelect) {
|
||||
VRC24_cbExternalSelect(A, V); /* Provide original address */
|
||||
}
|
||||
break;
|
||||
case 0xF000:
|
||||
if (VRC24_isVRC4) switch (addr &3) {
|
||||
case 0: VRC4_latch = VRC4_latch &0xF0 | V &0x0F; break;
|
||||
case 1: VRC4_latch = VRC4_latch &0x0F | V <<4; break;
|
||||
case 2: VRC4_mode = V;
|
||||
if (VRC4_mode &0x02) {
|
||||
VRC4_count = VRC4_latch;
|
||||
VRC4_cycles = 341;
|
||||
}
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
case 3: if (VRC24_useRepeatBit) VRC4_mode = VRC4_mode &~0x02 | VRC4_mode <<1 &0x02;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
index = (addr -0xB000) >>11 | addr >>1 &1;
|
||||
if (addr &1)
|
||||
VRC24_chr[index] = VRC24_chr[index] & 0x0F | V <<4;
|
||||
else
|
||||
VRC24_chr[index] = VRC24_chr[index] &~0x0F | V &0x0F;
|
||||
VRC24_cbSync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FP_FASTAPASS(1) VRC4_cpuCycle (int a) {
|
||||
while (a--) {
|
||||
if (VRC4_mode &0x02 && (VRC4_mode &0x04 || (VRC4_cycles -= 3) <= 0)) {
|
||||
if (~VRC4_mode &0x04) VRC4_cycles += 341;
|
||||
if (!++VRC4_count) {
|
||||
VRC4_count = VRC4_latch;
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void VRC24_clear() {
|
||||
VRC24_prg[0] = 0; VRC24_prg[1] = 0;
|
||||
VRC24_chr[0] = 0; VRC24_chr[1] = 1; VRC24_chr[2] = 2; VRC24_chr[3] = 3; VRC24_chr[4] = 4; VRC24_chr[5] = 5; VRC24_chr[6] = 6; VRC24_chr[7] = 7;
|
||||
VRC24_mirroring = VRC2_pins = VRC4_latch = VRC4_mode = VRC4_count = VRC4_cycles = 0;
|
||||
VRC24_misc = 1; /* Start with WRAM enabled */
|
||||
VRC24_cbSync();
|
||||
}
|
||||
|
||||
static void VRC24_setHandlers () {
|
||||
if (VRC24_isVRC4 || WRAMSize) {
|
||||
SetReadHandler(0x6000, 0x7FFF, VRC24_readWRAM);
|
||||
SetWriteHandler(0x6000, 0x7FFF, VRC24_writeWRAM);
|
||||
} else {
|
||||
SetReadHandler(0x6000, 0x6FFF, VRC2_readMicrowire);
|
||||
SetWriteHandler(0x6000, 0x6FFF, VRC2_writeMicrowire);
|
||||
}
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, VRC24_writeReg);
|
||||
if (VRC24_isVRC4) MapIRQHook = VRC4_cpuCycle;
|
||||
}
|
||||
|
||||
static void VRC2_configure (void (*sync)(), int A0, int A1, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) {
|
||||
VRC24_cbSync = sync;
|
||||
VRC24_A0 = A0;
|
||||
VRC24_A1 = A1;
|
||||
VRC24_isVRC4 = 0;
|
||||
VRC24_cbGetPRGBank = prg? prg: VRC24_getPRGBank;
|
||||
VRC24_cbGetCHRBank = chr? chr: VRC24_getCHRBank;
|
||||
VRC24_cbReadWRAM = read;
|
||||
VRC24_cbWriteWRAM = write;
|
||||
}
|
||||
|
||||
static void VRC4_configure (void (*sync)(), int A0, int A1, uint8 useRepeatBit, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write)), DECLFW((*externalSelect))) {
|
||||
VRC24_cbSync = sync;
|
||||
VRC24_A0 = A0;
|
||||
VRC24_A1 = A1;
|
||||
VRC24_isVRC4 = 1;
|
||||
VRC24_useRepeatBit = useRepeatBit;
|
||||
VRC24_cbGetPRGBank = prg? prg: VRC24_getPRGBank;
|
||||
VRC24_cbGetCHRBank = chr? chr: VRC24_getCHRBank;
|
||||
VRC24_cbReadWRAM = read;
|
||||
VRC24_cbWriteWRAM = write;
|
||||
VRC24_cbExternalSelect = externalSelect;
|
||||
}
|
||||
|
||||
void VRC2_activate (uint8 clear, void (*sync)(), int A0, int A1, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) {
|
||||
VRC2_configure(sync, A0, A1, prg, chr, read, write);
|
||||
VRC24_setHandlers();
|
||||
if (clear)
|
||||
VRC24_clear();
|
||||
else
|
||||
VRC24_cbSync();
|
||||
}
|
||||
|
||||
void VRC4_activate (uint8 clear, void (*sync)(), int A0, int A1, uint8 useRepeatBit, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write)), DECLFW((*externalSelect))) {
|
||||
VRC4_configure(sync, A0, A1, useRepeatBit, prg, chr, read, write, externalSelect);
|
||||
VRC24_setHandlers();
|
||||
if (clear)
|
||||
VRC24_clear();
|
||||
else
|
||||
VRC24_cbSync();
|
||||
}
|
||||
|
||||
void VRC2_addExState () {
|
||||
AddExState(VRC24_stateRegs, ~0, 0, 0);
|
||||
AddExState(VRC2_stateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void VRC4_addExState () {
|
||||
AddExState(VRC24_stateRegs, ~0, 0, 0);
|
||||
AddExState(VRC4_stateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void VRC24_addExState () {
|
||||
AddExState(VRC24_stateRegs, ~0, 0, 0);
|
||||
AddExState(VRC2_stateRegs, ~0, 0, 0);
|
||||
AddExState(VRC4_stateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void VRC24_restore (int version) {
|
||||
VRC24_cbSync();
|
||||
}
|
||||
|
||||
void VRC24_power () {
|
||||
VRC24_setHandlers();
|
||||
VRC24_clear();
|
||||
}
|
||||
|
||||
void VRC2_init (CartInfo *info, void (*sync)(), int A0, int A1, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) {
|
||||
VRC2_addExState();
|
||||
VRC2_configure(sync, A0, A1, prg, chr, read, write);
|
||||
info->Power = VRC24_power;
|
||||
GameStateRestore = VRC24_cbSync;
|
||||
}
|
||||
|
||||
void VRC4_init (CartInfo *info, void (*sync)(), int A0, int A1, uint8 useRepeatBit, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write)), DECLFW((*externalSelect))) {
|
||||
VRC4_addExState();
|
||||
VRC4_configure(sync, A0, A1, useRepeatBit, prg, chr, read, write, externalSelect);
|
||||
info->Power = VRC24_power;
|
||||
GameStateRestore = VRC24_restore;
|
||||
}
|
||||
50
src/boards/asic_vrc2and4.h
Normal file
50
src/boards/asic_vrc2and4.h
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
|
||||
*/
|
||||
|
||||
#ifndef _VRC2AND4_H
|
||||
#define _VRC2AND4_H
|
||||
|
||||
extern uint8 VRC2_pins;
|
||||
|
||||
DECLFR(VRC2_readMicrowire);
|
||||
DECLFW(VRC2_writeMicrowire);
|
||||
DECLFR(VRC24_readWRAM);
|
||||
DECLFW(VRC24_writeWRAM);
|
||||
|
||||
void VRC24_syncWRAM (int);
|
||||
void VRC24_syncPRG (int, int);
|
||||
void VRC24_syncCHR (int, int);
|
||||
int VRC24_getPRGBank (uint8);
|
||||
int VRC24_getCHRBank (uint8);
|
||||
void VRC24_syncMirror ();
|
||||
DECLFW(VRC24_writeReg);
|
||||
|
||||
void FP_FASTAPASS(1) VRC4_cpuCycle(int);
|
||||
void VRC2_activate (uint8, void (*)(), int, int, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*)));
|
||||
void VRC4_activate (uint8, void (*)(), int, int, uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*)), DECLFW((*)));
|
||||
void VRC2_addExState ();
|
||||
void VRC4_addExState ();
|
||||
void VRC24_addExState ();
|
||||
void VRC24_restore (int);
|
||||
void VRC24_power ();
|
||||
void VRC2_init (CartInfo *, void (*)(), int, int, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*)));
|
||||
void VRC4_init (CartInfo *, void (*)(), int, int, uint8, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*)), DECLFW((*)));
|
||||
|
||||
#endif
|
||||
129
src/boards/asic_vrc3.c
Normal file
129
src/boards/asic_vrc3.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/* 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_VRC3.h"
|
||||
|
||||
static void (*VRC3_cbSync)();
|
||||
static uint8 VRC3_prg;
|
||||
static uint8 VRC3_irq;
|
||||
static uint16 VRC3_count;
|
||||
static uint16 VRC3_reload;
|
||||
|
||||
static SFORMAT VRC3_state[] = {
|
||||
{&VRC3_prg, 1, "VC3P" },
|
||||
{&VRC3_irq, 1, "VC3I" },
|
||||
{&VRC3_count, 1, "VC3C" },
|
||||
{&VRC3_reload, 1, "VC3R" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
void VRC3_syncWRAM (int OR) {
|
||||
if (PRGsize[0x10]) setprg8r(0x10, 0x6000, OR);
|
||||
}
|
||||
|
||||
void VRC3_syncPRG (int AND, int OR) {
|
||||
setprg16(0x8000, VRC3_prg &AND |OR);
|
||||
setprg16(0xC000, 0xFF &AND |OR);
|
||||
}
|
||||
|
||||
void VRC3_syncCHR (int AND, int OR) {
|
||||
setchr8(OR);
|
||||
}
|
||||
|
||||
DECLFW(VRC3_write) {
|
||||
int shift;
|
||||
switch (A >>12 &7) {
|
||||
case 0: case 1: case 2: case 3:
|
||||
V &=0xF;
|
||||
shift = A >>10 &0xC;
|
||||
VRC3_reload = VRC3_reload &~(0xF <<shift) | V <<shift;
|
||||
break;
|
||||
case 4:
|
||||
VRC3_irq = V;
|
||||
if (VRC3_irq &2) VRC3_count = VRC3_reload;
|
||||
break;
|
||||
case 5:
|
||||
VRC3_irq = VRC3_irq &~2 | VRC3_irq <<1 &1;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
case 7:
|
||||
VRC3_prg = V;
|
||||
VRC3_cbSync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FP_FASTAPASS(1) VRC3_cpuCycle (int a) {
|
||||
while (a--) {
|
||||
int mask = VRC3_irq &4? 0xFF: 0xFFFF;
|
||||
if ((VRC3_count++ &mask) == mask) {
|
||||
VRC3_count = VRC3_reload;
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void VRC3_clear () {
|
||||
VRC3_prg = VRC3_irq = VRC3_count = VRC3_reload = 0;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
VRC3_cbSync();
|
||||
}
|
||||
|
||||
static void VRC3_setHandlers () {
|
||||
SetReadHandler (0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetWriteHandler(0x8000, 0xFFFF, VRC3_write);
|
||||
MapIRQHook = VRC3_cpuCycle;
|
||||
}
|
||||
|
||||
static void VRC3_configure (void (*sync)()) {
|
||||
VRC3_cbSync = sync;
|
||||
}
|
||||
|
||||
void VRC3_activate (uint8 clear, void (*sync)()) {
|
||||
VRC3_configure(sync);
|
||||
VRC3_setHandlers();
|
||||
if (clear)
|
||||
VRC3_clear();
|
||||
else
|
||||
VRC3_cbSync();
|
||||
}
|
||||
|
||||
void VRC3_addExState () {
|
||||
AddExState(VRC3_state, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void VRC3_restore (int version) {
|
||||
VRC3_cbSync();
|
||||
}
|
||||
|
||||
void VRC3_power () {
|
||||
VRC3_setHandlers();
|
||||
VRC3_clear();
|
||||
}
|
||||
|
||||
void VRC3_init (CartInfo *info, void (*sync)()) {
|
||||
VRC3_addExState();
|
||||
VRC3_configure(sync);
|
||||
info->Power = VRC3_power;
|
||||
info->Reset = VRC3_cbSync;
|
||||
GameStateRestore = VRC3_restore;
|
||||
}
|
||||
34
src/boards/asic_vrc3.h
Normal file
34
src/boards/asic_vrc3.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#ifndef _ASIC_VRC3_H
|
||||
#define _ASIC_VRC3_H
|
||||
|
||||
void VRC3_syncWRAM (int);
|
||||
void VRC3_syncPRG (int, int);
|
||||
void VRC3_syncCHR (int, int);
|
||||
DECLFW (VRC3_write);
|
||||
void VRC3_activate (uint8, void (*)());
|
||||
void VRC3_addExState ();
|
||||
void VRC3_restore (int);
|
||||
void VRC3_power ();
|
||||
void VRC3_init (CartInfo *, void (*)());
|
||||
|
||||
#endif
|
||||
208
src/boards/asic_vrc6.c
Normal file
208
src/boards/asic_vrc6.c
Normal file
@@ -0,0 +1,208 @@
|
||||
/* 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_vrc6.h"
|
||||
#include "wram.h"
|
||||
|
||||
static void (*VRC6_cbSync)();
|
||||
static int VRC6_A0, VRC6_A1;
|
||||
static int (*VRC6_cbGetPRGBank)(uint8);
|
||||
static int (*VRC6_cbGetCHRBank)(uint8);
|
||||
static DECLFR ((*VRC6_cbReadWRAM));
|
||||
static DECLFW ((*VRC6_cbWriteWRAM));
|
||||
static uint8 VRC6_prg[2];
|
||||
static uint8 VRC6_chr[8];
|
||||
static uint8 VRC6_misc;
|
||||
static uint8 VRC6_latch;
|
||||
static uint8 VRC6_mode;
|
||||
static uint8 VRC6_count;
|
||||
static signed short int VRC6_cycles;
|
||||
|
||||
static SFORMAT VRC6_stateRegs[] = {
|
||||
{ VRC6_prg, 2, "VC6P" },
|
||||
{ VRC6_chr, 6, "VC6C" },
|
||||
{ &VRC6_misc, 1, "VC6M" },
|
||||
{ &VRC6_latch, 1, "LATC" },
|
||||
{ &VRC6_mode, 1, "MODE" },
|
||||
{ &VRC6_count, 1, "COUN" },
|
||||
{ &VRC6_cycles, 2 | FCEUSTATE_RLSB, "CYCL" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
void VRC6_syncWRAM (int OR) {
|
||||
if (PRGsize[0x10]) setprg8r(0x10, 0x6000, OR);
|
||||
}
|
||||
|
||||
void VRC6_syncPRG (int AND, int OR) {
|
||||
setprg8(0x8000, VRC6_cbGetPRGBank(0) &AND | OR);
|
||||
setprg8(0xA000, VRC6_cbGetPRGBank(1) &AND | OR);
|
||||
setprg8(0xC000, VRC6_cbGetPRGBank(2) &AND | OR);
|
||||
setprg8(0xE000, VRC6_cbGetPRGBank(3) &AND | OR);
|
||||
}
|
||||
|
||||
void VRC6_syncCHR (int AND, int OR) {
|
||||
setchr1(0x0000, VRC6_cbGetCHRBank(0) &AND | OR);
|
||||
setchr1(0x0400, VRC6_cbGetCHRBank(1) &AND | OR);
|
||||
setchr1(0x0800, VRC6_cbGetCHRBank(2) &AND | OR);
|
||||
setchr1(0x0C00, VRC6_cbGetCHRBank(3) &AND | OR);
|
||||
setchr1(0x1000, VRC6_cbGetCHRBank(4) &AND | OR);
|
||||
setchr1(0x1400, VRC6_cbGetCHRBank(5) &AND | OR);
|
||||
setchr1(0x1800, VRC6_cbGetCHRBank(6) &AND | OR);
|
||||
setchr1(0x1C00, VRC6_cbGetCHRBank(7) &AND | OR);
|
||||
}
|
||||
|
||||
void VRC6_syncMirror () { /* Only emulates features used by known games, meaning mode 0 with CHR A10 substitution */
|
||||
setmirror(VRC6_misc &8? (VRC6_misc &4? MI_1: MI_0): VRC6_misc &4? MI_H: MI_V);
|
||||
}
|
||||
|
||||
int VRC6_getPRGBank (uint8 bank) {
|
||||
if (bank &2)
|
||||
return bank &1? 0xFF: VRC6_prg[1];
|
||||
else
|
||||
return VRC6_prg[0] <<1 | bank &1;
|
||||
}
|
||||
|
||||
int VRC6_getCHRBank (uint8 bank) { /* Only emulates features used by known games, meaning mode 0 with CHR A10 substitution */
|
||||
return VRC6_chr[bank &7];
|
||||
}
|
||||
|
||||
DECLFR(VRC6_readWRAM) {
|
||||
if (VRC6_misc &0x80)
|
||||
return VRC6_cbReadWRAM? VRC6_cbReadWRAM(A): CartBR(A);
|
||||
else
|
||||
return A >>8;
|
||||
}
|
||||
|
||||
DECLFW(VRC6_writeWRAM) {
|
||||
if (VRC6_misc &0x80) {
|
||||
CartBW(A, V);
|
||||
if (VRC6_cbWriteWRAM) VRC6_cbWriteWRAM(A, V);
|
||||
}
|
||||
}
|
||||
|
||||
DECLFW(VRC6_writeReg) {
|
||||
unsigned int index;
|
||||
index = (A &VRC6_A0? 1: 0) | (A &VRC6_A1? 2: 0);
|
||||
switch (A >>12 &7) {
|
||||
case 0: case 4:
|
||||
VRC6_prg[A >>14 &1] = V;
|
||||
VRC6_cbSync();
|
||||
break;
|
||||
case 1: case 2: /* Sound */
|
||||
break;
|
||||
case 3:
|
||||
if (index == 3) {
|
||||
VRC6_misc = V;
|
||||
VRC6_cbSync();
|
||||
}
|
||||
break;
|
||||
case 5: case 6:
|
||||
VRC6_chr[A >>11 &4 | index] = V;
|
||||
VRC6_cbSync();
|
||||
break;
|
||||
case 7:
|
||||
switch (index) {
|
||||
case 0:
|
||||
VRC6_latch = V;
|
||||
break;
|
||||
case 1:
|
||||
VRC6_mode = V;
|
||||
if (VRC6_mode &0x02) {
|
||||
VRC6_count = VRC6_latch;
|
||||
VRC6_cycles = 341;
|
||||
}
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
case 2:
|
||||
VRC6_mode = VRC6_mode &~0x02 | VRC6_mode <<1 &0x02;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FP_FASTAPASS(1) VRC6_cpuCycle (int a) {
|
||||
while (a--) {
|
||||
if (VRC6_mode &0x02 && (VRC6_mode &0x04 || (VRC6_cycles -= 3) <= 0)) {
|
||||
if (~VRC6_mode &0x04) VRC6_cycles += 341;
|
||||
if (!++VRC6_count) {
|
||||
VRC6_count = VRC6_latch;
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void VRC6_clear () {
|
||||
VRC6_prg[0] = 0; VRC6_prg[1] = 0xFE;
|
||||
VRC6_chr[0] = 0; VRC6_chr[1] = 1; VRC6_chr[2] = 2; VRC6_chr[3] = 3; VRC6_chr[4] = 4; VRC6_chr[5] = 5; VRC6_chr[6] = 6; VRC6_chr[7] = 7;
|
||||
VRC6_misc = VRC6_latch = VRC6_mode = VRC6_count = VRC6_cycles = 0;
|
||||
VRC6_cbSync();
|
||||
}
|
||||
|
||||
static void VRC6_setHandlers () {
|
||||
SetReadHandler(0x6000, 0x7FFF, VRC6_readWRAM);
|
||||
SetWriteHandler(0x6000, 0x7FFF, VRC6_writeWRAM);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, VRC6_writeReg);
|
||||
MapIRQHook =VRC6_cpuCycle;
|
||||
}
|
||||
|
||||
static void VRC6_configure (void (*sync)(), int A0, int A1, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) {
|
||||
VRC6_A0 = A0;
|
||||
VRC6_A1 = A1;
|
||||
VRC6_cbSync = sync;
|
||||
VRC6_cbGetPRGBank = prg? prg: VRC6_getPRGBank;
|
||||
VRC6_cbGetCHRBank = chr? chr: VRC6_getCHRBank;
|
||||
VRC6_cbReadWRAM = read;
|
||||
VRC6_cbWriteWRAM = write;
|
||||
}
|
||||
|
||||
void VRC6_activate (uint8 clear, void (*sync)(), int A0, int A1, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) {
|
||||
VRC6_configure(sync, A0, A1, prg, chr, read, write);
|
||||
VRC6_setHandlers();
|
||||
if (clear)
|
||||
VRC6_clear();
|
||||
else
|
||||
VRC6_cbSync();
|
||||
}
|
||||
|
||||
void VRC6_addExState () {
|
||||
AddExState(VRC6_stateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void VRC6_restore (int version) {
|
||||
VRC6_cbSync();
|
||||
}
|
||||
|
||||
void VRC6_power () {
|
||||
VRC6_setHandlers();
|
||||
VRC6_clear();
|
||||
}
|
||||
|
||||
void VRC6_init (CartInfo *info, void (*sync)(), int A0, int A1, int (*prg)(uint8), int (*chr)(uint8), DECLFR((*read)), DECLFW((*write))) {
|
||||
VRC6_addExState();
|
||||
VRC6_configure(sync, A0, A1, prg, chr, read, write);
|
||||
info->Power = VRC6_power;
|
||||
info->Reset = VRC6_cbSync;
|
||||
GameStateRestore = VRC6_restore;
|
||||
}
|
||||
40
src/boards/asic_vrc6.h
Normal file
40
src/boards/asic_vrc6.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#ifndef _ASIC_VRC6_H
|
||||
#define _ASIC_VRC6_H
|
||||
|
||||
void VRC6_syncWRAM (int);
|
||||
void VRC6_syncPRG (int, int);
|
||||
void VRC6_syncCHR (int, int);
|
||||
void VRC6_syncMirror ();
|
||||
int VRC6_getPRGBank (uint8);
|
||||
int VRC6_getCHRBank (uint8);
|
||||
DECLFR(VRC6_readWRAM);
|
||||
DECLFW(MMC3_writeWRAM);
|
||||
DECLFW(VRC6_writeReg);
|
||||
void FP_FASTAPASS(1) VRC6_cpuCycle (int);
|
||||
void VRC6_activate (uint8, void (*)(), int, int, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*)));
|
||||
void VRC6_addExState ();
|
||||
void VRC6_restore (int);
|
||||
void VRC6_power ();
|
||||
void VRC6_init (CartInfo *, void (*)(), int, int, int (*)(uint8), int (*)(uint8), DECLFR((*)), DECLFW((*)));
|
||||
|
||||
#endif
|
||||
180
src/boards/asic_vrc7.c
Normal file
180
src/boards/asic_vrc7.c
Normal file
@@ -0,0 +1,180 @@
|
||||
/* 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_VRC7.h"
|
||||
#include "wram.h"
|
||||
|
||||
static void (*VRC7_cbSync)();
|
||||
static int VRC7_A0;
|
||||
static uint8 VRC7_prg[3];
|
||||
static uint8 VRC7_chr[8];
|
||||
static uint8 VRC7_misc;
|
||||
static uint8 VRC7_latch;
|
||||
static uint8 VRC7_mode;
|
||||
static uint8 VRC7_count;
|
||||
static signed short int VRC7_cycles;
|
||||
|
||||
static SFORMAT VRC7_stateRegs[] = {
|
||||
{ VRC7_prg, 3, "VC6P" },
|
||||
{ VRC7_chr, 6, "VC6C" },
|
||||
{ &VRC7_misc, 1, "VC6M" },
|
||||
{ &VRC7_latch, 1, "LATC" },
|
||||
{ &VRC7_mode, 1, "MODE" },
|
||||
{ &VRC7_count, 1, "COUN" },
|
||||
{ &VRC7_cycles, 2 | FCEUSTATE_RLSB, "CYCL" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
void VRC7_syncWRAM (int OR) {
|
||||
if (PRGsize[0x10]) setprg8r(0x10, 0x6000, OR);
|
||||
}
|
||||
|
||||
void VRC7_syncPRG (int AND, int OR) {
|
||||
setprg8(0x8000, VRC7_prg[0] &AND | OR);
|
||||
setprg8(0xA000, VRC7_prg[1] &AND | OR);
|
||||
setprg8(0xC000, VRC7_prg[2] &AND | OR);
|
||||
setprg8(0xE000, 0xFF &AND | OR);
|
||||
}
|
||||
|
||||
void VRC7_syncCHR (int AND, int OR) {
|
||||
setchr1(0x0000, VRC7_chr[0] &AND | OR);
|
||||
setchr1(0x0400, VRC7_chr[1] &AND | OR);
|
||||
setchr1(0x0800, VRC7_chr[2] &AND | OR);
|
||||
setchr1(0x0C00, VRC7_chr[3] &AND | OR);
|
||||
setchr1(0x1000, VRC7_chr[4] &AND | OR);
|
||||
setchr1(0x1400, VRC7_chr[5] &AND | OR);
|
||||
setchr1(0x1800, VRC7_chr[6] &AND | OR);
|
||||
setchr1(0x1C00, VRC7_chr[7] &AND | OR);
|
||||
}
|
||||
|
||||
void VRC7_syncMirror () {
|
||||
setmirror(VRC7_misc &2? (VRC7_misc &1? MI_1: MI_0): VRC7_misc &1? MI_H: MI_V);
|
||||
}
|
||||
|
||||
DECLFR(VRC7_readWRAM) {
|
||||
return VRC7_misc &0x80? CartBR(A): A >>8;
|
||||
}
|
||||
|
||||
DECLFW(VRC7_writeWRAM) {
|
||||
if (VRC7_misc &0x80) CartBW(A, V);
|
||||
}
|
||||
|
||||
DECLFW(VRC7_writeReg) {
|
||||
unsigned int index;
|
||||
index = A &VRC7_A0? 1: 0;
|
||||
switch (A >>12 &7) {
|
||||
case 0:
|
||||
VRC7_prg[index &1] = V;
|
||||
VRC7_cbSync();
|
||||
break;
|
||||
case 1:
|
||||
if (!index) {
|
||||
VRC7_prg[2] = V;
|
||||
VRC7_cbSync();
|
||||
}
|
||||
break;
|
||||
case 2: case 3: case 4: case 5:
|
||||
VRC7_chr[(A -0xA000) >>11 &6 | index] = V;
|
||||
VRC7_cbSync();
|
||||
break;
|
||||
case 6: if (!index) {
|
||||
VRC7_misc = V;
|
||||
VRC7_cbSync();
|
||||
} else
|
||||
VRC7_latch = V;
|
||||
break;
|
||||
case 7:
|
||||
if (!index) {
|
||||
VRC7_mode = V;
|
||||
if (VRC7_mode &0x02) {
|
||||
VRC7_count = VRC7_latch;
|
||||
VRC7_cycles = 341;
|
||||
}
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
} else {
|
||||
VRC7_mode = VRC7_mode &~0x02 | VRC7_mode <<1 &0x02;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FP_FASTAPASS(1) VRC7_cpuCycle (int a) {
|
||||
while (a--) {
|
||||
if (VRC7_mode &0x02 && (VRC7_mode &0x04 || (VRC7_cycles -= 3) <= 0)) {
|
||||
if (~VRC7_mode &0x04) VRC7_cycles += 341;
|
||||
if (!++VRC7_count) {
|
||||
VRC7_count = VRC7_latch;
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void VRC7_clear () {
|
||||
VRC7_prg[0] = 0; VRC7_prg[1] = 1; VRC7_prg[2] = 0xFE;
|
||||
VRC7_chr[0] = 0; VRC7_chr[1] = 1; VRC7_chr[2] = 2; VRC7_chr[3] = 3; VRC7_chr[4] = 4; VRC7_chr[5] = 5; VRC7_chr[6] = 6; VRC7_chr[7] = 7;
|
||||
VRC7_misc = VRC7_latch = VRC7_mode = VRC7_count = VRC7_cycles = 0;
|
||||
VRC7_cbSync();
|
||||
}
|
||||
|
||||
static void VRC7_setHandlers () {
|
||||
SetReadHandler(0x6000, 0x7FFF, VRC7_readWRAM);
|
||||
SetWriteHandler(0x6000, 0x7FFF, VRC7_writeWRAM);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, VRC7_writeReg);
|
||||
MapIRQHook =VRC7_cpuCycle;
|
||||
}
|
||||
|
||||
static void VRC7_configure (void (*sync)(), int A0) {
|
||||
VRC7_A0 = A0;
|
||||
VRC7_cbSync = sync;
|
||||
}
|
||||
|
||||
void VRC7_activate (uint8 clear, void (*sync)(), int A0) {
|
||||
VRC7_configure(sync, A0);
|
||||
VRC7_setHandlers();
|
||||
if (clear)
|
||||
VRC7_clear();
|
||||
else
|
||||
VRC7_cbSync();
|
||||
}
|
||||
|
||||
void VRC7_addExState () {
|
||||
AddExState(VRC7_stateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void VRC7_restore (int version) {
|
||||
VRC7_cbSync();
|
||||
}
|
||||
|
||||
void VRC7_power () {
|
||||
VRC7_setHandlers();
|
||||
VRC7_clear();
|
||||
}
|
||||
|
||||
void VRC7_init (CartInfo *info, void (*sync)(), int A0) {
|
||||
VRC7_addExState();
|
||||
VRC7_configure(sync, A0);
|
||||
info->Power = VRC7_power;
|
||||
info->Reset = VRC7_cbSync;
|
||||
GameStateRestore = VRC7_restore;
|
||||
}
|
||||
41
src/boards/asic_vrc7.h
Normal file
41
src/boards/asic_vrc7.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#ifndef _ASIC_VRC7_H
|
||||
#define _ASIC_VRC7_H
|
||||
|
||||
void VRC7_syncWRAM (int);
|
||||
void VRC7_syncPRG (int, int);
|
||||
void VRC7_syncCHR (int, int);
|
||||
void VRC7_syncMirror ();
|
||||
int VRC7_getPRGBank (uint8);
|
||||
int VRC7_getCHRBank (uint8);
|
||||
int VRC7_getNTBank (uint8);
|
||||
DECLFR(VRC7_readWRAM);
|
||||
DECLFW(MMC3_writeWRAM);
|
||||
DECLFW(VRC7_writeReg);
|
||||
void FP_FASTAPASS(1) VRC7_cpuCycle (int);
|
||||
void VRC7_activate (uint8, void (*)(), int);
|
||||
void VRC7_addExState ();
|
||||
void VRC7_restore (int);
|
||||
void VRC7_power ();
|
||||
void VRC7_init (CartInfo *, void (*)(), int);
|
||||
|
||||
#endif
|
||||
@@ -1,242 +0,0 @@
|
||||
/* 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 "vrc2and4.h"
|
||||
|
||||
int VRC24_A0, VRC24_A1; /* What cartridge connector address pins are connected to the chip's A0 and A1 input pins? */
|
||||
uint8 VRC24_isVRC4; /* VRC2 or VRC4? VRC2 has no single-screen mirroring, no PRG A14 swap and no IRQ counter */
|
||||
uint8 VRC24_useRepeatBit; /* VRC4 clones ignore the "repeat" bit in the IRQ Mode register */
|
||||
uint8 VRC24_prg[2];
|
||||
uint16 VRC24_chr[8];
|
||||
uint8 VRC24_mirroring;
|
||||
uint8 VRC24_misc;
|
||||
uint8 VRC2_pins; /* EEPROM interface */
|
||||
uint8 VRC4_latch;
|
||||
uint8 VRC4_mode;
|
||||
uint8 VRC4_count;
|
||||
signed short int VRC4_cycles;
|
||||
|
||||
static uint8 *WRAM;
|
||||
static uint32 WRAMSize;
|
||||
|
||||
int (*VRC24_GetPRGBank)(int);
|
||||
int (*VRC24_GetCHRBank)(int);
|
||||
void (*VRC24_Sync)();
|
||||
DECLFW((*VRC24_ExternalSelect));
|
||||
DECLFR((*VRC24_WRAMRead));
|
||||
DECLFW((*VRC24_WRAMWrite));
|
||||
|
||||
static SFORMAT VRC24_stateRegs[] ={
|
||||
{ VRC24_prg, 2, "PREG" },
|
||||
{ &VRC24_chr[0], 2 | FCEUSTATE_RLSB, "CRH0" },
|
||||
{ &VRC24_chr[1], 2 | FCEUSTATE_RLSB, "CRH1" },
|
||||
{ &VRC24_chr[2], 2 | FCEUSTATE_RLSB, "CRH2" },
|
||||
{ &VRC24_chr[3], 2 | FCEUSTATE_RLSB, "CRH3" },
|
||||
{ &VRC24_chr[4], 2 | FCEUSTATE_RLSB, "CRH4" },
|
||||
{ &VRC24_chr[5], 2 | FCEUSTATE_RLSB, "CRH5" },
|
||||
{ &VRC24_chr[6], 2 | FCEUSTATE_RLSB, "CRH6" },
|
||||
{ &VRC24_chr[7], 2 | FCEUSTATE_RLSB, "CRH7" },
|
||||
{ &VRC24_mirroring, 1, "MIRR" },
|
||||
{ &VRC24_misc, 1, "MISC" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static SFORMAT VRC2_stateRegs[] ={
|
||||
{ &VRC2_pins, 1, "PINS" },
|
||||
};
|
||||
|
||||
static SFORMAT VRC4_stateRegs[] ={
|
||||
{ &VRC4_latch, 1, "LATC" },
|
||||
{ &VRC4_mode, 1, "MODE" },
|
||||
{ &VRC4_count, 1, "COUN" },
|
||||
{ &VRC4_cycles, 2 | FCEUSTATE_RLSB, "CYCL" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
void VRC24_syncPRG(int AND, int OR) {
|
||||
setprg8(0x8000, VRC24_GetPRGBank(0) &AND | OR);
|
||||
setprg8(0xA000, VRC24_GetPRGBank(1) &AND | OR);
|
||||
setprg8(0xC000, VRC24_GetPRGBank(2) &AND | OR);
|
||||
setprg8(0xE000, VRC24_GetPRGBank(3) &AND | OR);
|
||||
}
|
||||
|
||||
void VRC24_syncCHR(int AND, int OR) {
|
||||
setchr1(0x0000, VRC24_GetCHRBank(0) &AND | OR);
|
||||
setchr1(0x0400, VRC24_GetCHRBank(1) &AND | OR);
|
||||
setchr1(0x0800, VRC24_GetCHRBank(2) &AND | OR);
|
||||
setchr1(0x0C00, VRC24_GetCHRBank(3) &AND | OR);
|
||||
setchr1(0x1000, VRC24_GetCHRBank(4) &AND | OR);
|
||||
setchr1(0x1400, VRC24_GetCHRBank(5) &AND | OR);
|
||||
setchr1(0x1800, VRC24_GetCHRBank(6) &AND | OR);
|
||||
setchr1(0x1C00, VRC24_GetCHRBank(7) &AND | OR);
|
||||
}
|
||||
|
||||
void VRC24_syncWRAM(int OR) {
|
||||
setprg8r(0x10, 0x6000, OR);
|
||||
}
|
||||
|
||||
int VRC24_getPRGBank(int bank) {
|
||||
if (~bank &1 && VRC24_misc &2) bank ^=2;
|
||||
return bank &2? (0xFE | bank &1): VRC24_prg[bank &1];
|
||||
}
|
||||
|
||||
int VRC24_getCHRBank(int bank) {
|
||||
return VRC24_chr[bank &7];
|
||||
}
|
||||
|
||||
void VRC24_syncMirror() {
|
||||
setmirror(VRC24_isVRC4 && VRC24_mirroring &2? (VRC24_mirroring &1? MI_1: MI_0): (VRC24_mirroring &1? MI_H: MI_V));
|
||||
}
|
||||
|
||||
DECLFR(VRC24_wramRead) {
|
||||
if (VRC24_WRAMRead)
|
||||
VRC24_WRAMRead(A);
|
||||
else
|
||||
if (WRAMSize)
|
||||
return CartBR(((A -0x6000) &(WRAMSize -1)) +0x6000);
|
||||
else
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
DECLFW(VRC24_wramWrite) {
|
||||
if (WRAMSize)
|
||||
CartBW(((A -0x6000) &(WRAMSize -1)) +0x6000, V);
|
||||
else
|
||||
if (!VRC24_isVRC4) {
|
||||
VRC2_pins =V;
|
||||
VRC24_Sync();
|
||||
}
|
||||
|
||||
if (VRC24_WRAMWrite)
|
||||
VRC24_WRAMWrite(A, V);
|
||||
}
|
||||
|
||||
DECLFW(VRC24_writeReg) {
|
||||
unsigned int index, addr;
|
||||
addr =A &0xF000 | (A &VRC24_A0? 1: 0) | (A &VRC24_A1? 2: 0); /* address as the chip sees it */
|
||||
switch (addr &0xF000) {
|
||||
case 0x8000: case 0xA000:
|
||||
VRC24_prg[addr >>13 &1] =V;
|
||||
VRC24_Sync();
|
||||
break;
|
||||
case 0x9000:
|
||||
if (!VRC24_isVRC4 || (addr &3) ==0) {
|
||||
VRC24_mirroring =V;
|
||||
VRC24_Sync();
|
||||
} else
|
||||
if (VRC24_isVRC4 && (addr &3) ==2) {
|
||||
VRC24_misc =V;
|
||||
VRC24_Sync();
|
||||
}
|
||||
if (VRC24_isVRC4 && (addr &3) ==3 && VRC24_ExternalSelect) {
|
||||
VRC24_ExternalSelect(A, V); /* Provide original address */
|
||||
}
|
||||
break;
|
||||
case 0xF000:
|
||||
if (VRC24_isVRC4) switch (addr &3) {
|
||||
case 0: VRC4_latch =VRC4_latch &0xF0 | V &0x0F; break;
|
||||
case 1: VRC4_latch =VRC4_latch &0x0F | V <<4; break;
|
||||
case 2: VRC4_mode =V;
|
||||
if (VRC4_mode &0x02) {
|
||||
VRC4_count =VRC4_latch;
|
||||
VRC4_cycles =341;
|
||||
}
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
case 3: if (VRC24_useRepeatBit) VRC4_mode =VRC4_mode &~0x02 | VRC4_mode <<1 &0x02;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
index =(addr -0xB000) >>11 | addr >>1 &1;
|
||||
if (addr &1)
|
||||
VRC24_chr[index] =VRC24_chr[index] & 0x0F | V <<4;
|
||||
else
|
||||
VRC24_chr[index] =VRC24_chr[index] &~0x0F | V &0x0F;
|
||||
VRC24_Sync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FP_FASTAPASS(1) VRC4_cpuCycle(int a) {
|
||||
while (a--) {
|
||||
if (VRC4_mode &0x02 && (VRC4_mode &0x04 || (VRC4_cycles -=3) <=0)) {
|
||||
if (~VRC4_mode &0x04) VRC4_cycles +=341;
|
||||
if (!++VRC4_count) {
|
||||
VRC4_count =VRC4_latch;
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VRC24_power(void) {
|
||||
VRC24_prg[0] =0; VRC24_prg[1] =0;
|
||||
VRC24_chr[0] =0; VRC24_chr[1] =1; VRC24_chr[2] =2; VRC24_chr[3] =3; VRC24_chr[4] =4; VRC24_chr[5] =5; VRC24_chr[6] =6; VRC24_chr[7] =7;
|
||||
VRC24_mirroring =VRC24_misc =VRC2_pins =VRC4_latch =VRC4_mode =VRC4_count =VRC4_cycles =0;
|
||||
SetReadHandler(0x6000, 0x7FFF, VRC24_wramRead);
|
||||
SetWriteHandler(0x6000, 0x7FFF, VRC24_wramWrite);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, VRC24_writeReg);
|
||||
VRC24_Sync();
|
||||
}
|
||||
|
||||
void VRC24_close(void) {
|
||||
if (WRAM) {
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM =NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void VRC24_init(CartInfo *info, void (*_sync)(), int _A0, int _A1, uint8 _isVRC4, uint8 _useRepeatBit, uint8 defaultWRAMSizeKiB) {
|
||||
VRC24_Sync =_sync;
|
||||
VRC24_A0 =_A0;
|
||||
VRC24_A1 =_A1;
|
||||
VRC24_isVRC4 =_isVRC4;
|
||||
VRC24_useRepeatBit =_useRepeatBit;
|
||||
VRC24_GetPRGBank =VRC24_getPRGBank;
|
||||
VRC24_GetCHRBank =VRC24_getCHRBank;
|
||||
VRC24_WRAMRead =NULL;
|
||||
VRC24_WRAMWrite =NULL;
|
||||
VRC24_ExternalSelect =NULL;
|
||||
info->Power =VRC24_power;
|
||||
info->Close =VRC24_close;
|
||||
GameStateRestore =_sync;
|
||||
AddExState(VRC24_stateRegs, ~0, 0, 0);
|
||||
if (VRC24_isVRC4) {
|
||||
MapIRQHook =VRC4_cpuCycle;
|
||||
AddExState(VRC4_stateRegs, ~0, 0, 0);
|
||||
} else {
|
||||
AddExState(VRC2_stateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
WRAMSize =info->iNES2? (info->PRGRamSize +info->PRGRamSaveSize): (defaultWRAMSizeKiB *1024);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
#ifndef _VRC2AND4_H
|
||||
#define _VRC2AND4_H
|
||||
|
||||
extern int VRC24_A0, VRC24_A1;
|
||||
extern uint8 VRC24_isVRC4;
|
||||
extern uint8 VRC24_useRepeatBit;
|
||||
extern uint8 VRC24_prg[2];
|
||||
extern uint16 VRC24_chr[8];
|
||||
extern uint8 VRC24_mirroring;
|
||||
extern uint8 VRC24_misc;
|
||||
extern uint8 VRC2_pins;
|
||||
extern uint8 VRC4_latch;
|
||||
extern uint8 VRC4_mode;
|
||||
extern uint8 VRC4_count;
|
||||
extern signed short int VRC4_cycles;
|
||||
|
||||
extern int (*VRC24_GetPRGBank)(int);
|
||||
extern int (*VRC24_GetCHRBank)(int);
|
||||
extern void (*VRC24_Sync)();
|
||||
extern DECLFW((*VRC24_ExternalSelect));
|
||||
extern DECLFR((*VRC24_WRAMRead));
|
||||
extern DECLFW((*VRC24_WRAMWrite));
|
||||
|
||||
void VRC24_syncPRG (int AND, int OR);
|
||||
void VRC24_syncCHR (int AND, int OR);
|
||||
void VRC24_syncWRAM (int OR);
|
||||
int VRC24_getPRGBank (int bank);
|
||||
int VRC24_getCHRBank (int bank);
|
||||
void VRC24_syncMirror ();
|
||||
DECLFW(VRC24_writeReg);
|
||||
|
||||
void VRC24_power(void);
|
||||
void VRC24_close(void);
|
||||
void VRC24_init(CartInfo *info, void (*_sync)(), int _A0, int _A1, uint8 _isVRC4, uint8 _useRepeatBit, uint8 defaultWRAMSizeKiB);
|
||||
|
||||
#endif
|
||||
46
src/boards/wram.c
Normal file
46
src/boards/wram.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/* 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 "wram.h"
|
||||
|
||||
static uint8 *WRAMData = NULL;
|
||||
uint32 WRAMSize = 0;
|
||||
|
||||
void WRAM_close (void) {
|
||||
if (WRAMData) {
|
||||
FCEU_gfree(WRAMData);
|
||||
WRAMData =NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void WRAM_init (CartInfo *info, uint8 defaultWRAMSizeKiB) {
|
||||
WRAMSize =info->iNES2? (info->PRGRamSize +info->PRGRamSaveSize): (defaultWRAMSizeKiB *1024);
|
||||
if (WRAMSize) {
|
||||
info->Close =WRAM_close;
|
||||
WRAMData =(uint8*)FCEU_gmalloc(WRAMSize);
|
||||
SetupCartPRGMapping(0x10, WRAMData, WRAMSize, 1);
|
||||
AddExState(WRAMData, WRAMSize, 0, "WRAM");
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] =WRAMData;
|
||||
info->SaveGameLen[0] =WRAMSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/boards/wram.h
Normal file
28
src/boards/wram.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#ifndef _WRAM_H
|
||||
#define _WRAM_H
|
||||
|
||||
extern uint32 WRAMSize;
|
||||
void WRAM_init (CartInfo *, uint8);
|
||||
void WRAM_close ();
|
||||
|
||||
#endif
|
||||
@@ -869,6 +869,7 @@ INES_BOARD_BEGIN()
|
||||
INES_BOARD( "NC-3000M", 443, Mapper443_Init )
|
||||
INES_BOARD( "NC-7000M/NC-8000M", 444, Mapper444_Init )
|
||||
INES_BOARD( "DG574B", 445, Mapper445_Init )
|
||||
INES_BOARD( "SMD172B_FPGA", 446, Mapper446_Init )
|
||||
INES_BOARD( "KL-06", 447, Mapper447_Init )
|
||||
INES_BOARD( "830768C", 448, Mapper448_Init )
|
||||
INES_BOARD( "22-in-1 King Series", 449, Mapper449_Init )
|
||||
|
||||
@@ -348,6 +348,7 @@ void Mapper441_Init(CartInfo *);
|
||||
void Mapper443_Init(CartInfo *);
|
||||
void Mapper444_Init(CartInfo *);
|
||||
void Mapper445_Init(CartInfo *);
|
||||
void Mapper446_Init(CartInfo *);
|
||||
void Mapper447_Init(CartInfo *);
|
||||
void Mapper448_Init(CartInfo *);
|
||||
void Mapper449_Init(CartInfo *);
|
||||
|
||||
Reference in New Issue
Block a user