Files
ci-libretro-fceumm/src/boards/addrlatch.c
2023-03-27 21:24:28 +02:00

847 lines
20 KiB
C

/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2006 CaH4e3
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "mapinc.h"
static uint16 latche, latcheinit;
static uint16 addrreg0, addrreg1;
static uint8 dipswitch;
static void (*WSync)(void);
static readfunc defread;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 hasBattery;
static uint32 submapper = 0;
static DECLFW(LatchWrite) {
latche = A;
WSync();
}
static void LatchReset(void) {
latche = latcheinit;
WSync();
}
static void LatchPower(void) {
latche = latcheinit;
WSync();
if (WRAM) {
SetReadHandler(0x6000, 0xFFFF, CartBR);
SetWriteHandler(0x6000, 0x7FFF, CartBW);
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
} else
SetReadHandler(0x6000, 0xFFFF, defread);
SetWriteHandler(addrreg0, addrreg1, LatchWrite);
}
static void LatchClose(void) {
if (WRAM)
FCEU_gfree(WRAM);
WRAM = NULL;
}
static void StateRestore(int version) {
WSync();
}
static void Latch_Init(CartInfo *info, void (*proc)(void), readfunc func, uint16 linit, uint16 adr0, uint16 adr1, uint8 wram) {
latcheinit = linit;
addrreg0 = adr0;
addrreg1 = adr1;
WSync = proc;
hasBattery = 0;
if (func != NULL)
defread = func;
else
defread = CartBROB;
info->Power = LatchPower;
info->Reset = LatchReset;
info->Close = LatchClose;
if (wram) {
WRAMSIZE = 8192;
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
if (info->battery) {
hasBattery = 1;
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
}
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
}
GameStateRestore = StateRestore;
AddExState(&latche, 2, 0, "LATC");
}
/*------------------ BMCD1038 ---------------------------*/
static void BMCD1038Sync(void) {
if (latche & 0x80) {
setprg16(0x8000, (latche & 0x70) >> 4);
setprg16(0xC000, (latche & 0x70) >> 4);
} else
setprg32(0x8000, (latche & 0x60) >> 5);
setchr8(latche & 7);
setmirror(((latche & 8) >> 3) ^ 1);
}
static DECLFR(BMCD1038Read) {
if (latche & 0x100)
return dipswitch;
else
return CartBR(A);
}
static DECLFW(BMCD1038Write) {
/* Only recognize the latch write if the lock bit has not been set. Needed for NT-234 "Road Fighter" */
if (~latche & 0x200)
LatchWrite(A, V);
}
static void BMCD1038Reset(void) {
dipswitch++;
dipswitch &= 3;
/* Always reset to menu */
latche = 0;
BMCD1038Sync();
}
static void BMCD1038Power(void) {
LatchPower();
/* Trap latch writes to enforce the "Lock" bit */
SetWriteHandler(0x8000, 0xFFFF, BMCD1038Write);
}
void BMCD1038_Init(CartInfo *info) {
Latch_Init(info, BMCD1038Sync, BMCD1038Read, 0x0000, 0x8000, 0xFFFF, 0);
info->Reset = BMCD1038Reset;
info->Power = BMCD1038Power;
AddExState(&dipswitch, 1, 0, "DIPSW");
}
/*------------------ Map 058 ---------------------------*/
static void M58Sync(void) {
if (latche & 0x40) {
setprg16(0x8000, latche & 7);
setprg16(0xC000, latche & 7);
} else
setprg32(0x8000, (latche >> 1) & 3);
setchr8((latche >> 3) & 7);
setmirror(((latche & 0x80) >> 7) ^ 1);
}
void Mapper58_Init(CartInfo *info) {
Latch_Init(info, M58Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0);
}
/*------------------ Map 059 ---------------------------*/
/* One more forgotten mapper */
/* Formerly, an incorrect implementation of BMC-T3H53 */
/*static void M59Sync(void) {
setprg32(0x8000, (latche >> 4) & 7);
setchr8(latche & 0x7);
setmirror((latche >> 3) & 1);
}
static DECLFR(M59Read) {
if (latche & 0x100)
return 0;
else
return CartBR(A);
}
void Mapper59_Init(CartInfo *info) {
Latch_Init(info, M59Sync, M59Read, 0x0000, 0x8000, 0xFFFF, 0);
}*/
/*------------------ Map 061 ---------------------------*/
static void M61Sync(void) {
if (((latche & 0x10) << 1) ^ (latche & 0x20)) {
setprg16(0x8000, ((latche & 0xF) << 1) | (((latche & 0x20) >> 4)));
setprg16(0xC000, ((latche & 0xF) << 1) | (((latche & 0x20) >> 4)));
} else
setprg32(0x8000, latche & 0xF);
setchr8(0);
setmirror(((latche >> 7) & 1) ^ 1);
}
void Mapper61_Init(CartInfo *info) {
Latch_Init(info, M61Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0);
}
/*------------------ Map 063 ---------------------------*/
/* added 2019-5-23
* Mapper 63 NTDEC-Multicart
* http://wiki.nesdev.com/w/index.php/INES_Mapper_063
* - Powerful 250-in-1
* - Hello Kitty 255-in-1
* Submapper 1:
* - NTDEC 82-in-1 */
static uint16 openBus;
static DECLFR(M63Read) {
if (openBus)
return X.DB;
return CartBR(A);
}
static void M63Sync(void) {
uint16 prg =latche >>2 &(submapper ==1? 0x7F: 0xFF);
if (latche &2)
setprg32(0x8000, prg >>1);
else {
setprg16(0x8000, prg);
setprg16(0xC000, prg);
}
openBus =prg >=ROM_size;
SetupCartCHRMapping(0, CHRptr[0], 0x2000, latche &(submapper ==1? 0x200: 0x400)? 0: 1);
setchr8(0);
setmirror(latche &1? MI_H: MI_V);
}
void Mapper63_Init(CartInfo *info) {
submapper = info->submapper;
Latch_Init(info, M63Sync, M63Read, 0x0000, 0x8000, 0xFFFF, 0);
}
/*------------------ Map 092 ---------------------------*/
/* Another two-in-one mapper, two Jaleco carts uses similar
* hardware, but with different wiring.
* Original code provided by LULU
* Additionally, PCB contains DSP extra sound chip, used for voice samples (unemulated)
*/
static void M92Sync(void) {
uint8 reg = latche & 0xF0;
setprg16(0x8000, 0);
if (latche >= 0x9000) {
switch (reg) {
case 0xD0: setprg16(0xc000, latche & 15); break;
case 0xE0: setchr8(latche & 15); break;
}
} else {
switch (reg) {
case 0xB0: setprg16(0xc000, latche & 15); break;
case 0x70: setchr8(latche & 15); break;
}
}
}
void Mapper92_Init(CartInfo *info) {
Latch_Init(info, M92Sync, NULL, 0x80B0, 0x8000, 0xFFFF, 0);
}
/*------------------ Map 200 ---------------------------*/
static void M200Sync(void) {
setprg16(0x8000, latche);
setprg16(0xC000, latche);
setchr8(latche);
setmirror(latche &(submapper ==1? 4: 8)? MI_H: MI_V);
}
void Mapper200_Init(CartInfo *info) {
submapper = info->submapper;
Latch_Init(info, M200Sync, NULL, 0xFFFF, 0x8000, 0xFFFF, 0);
}
/*------------------ Map 201 ---------------------------*/
/* 2020-3-6 - Support for 21-in-1 (CF-043) (2006-V) (Unl) [p1].nes which has mixed mirroring
* found at the time labeled as submapper 15
* 0x05658DED 128K PRG, 32K CHR */
static void M201Sync(void) {
if (latche & 8 || submapper == 15) {
setprg32(0x8000, latche & 3);
setchr8(latche & 3);
} else {
setprg32(0x8000, 0);
setchr8(0);
}
if (submapper == 15)
setmirror(((latche & 0x07) == 0x07) ? MI_V : MI_H);
}
void Mapper201_Init(CartInfo *info) {
submapper = info->submapper;
Latch_Init(info, M201Sync, NULL, 0xFFFF, 0x8000, 0xFFFF, 0);
}
/*------------------ Map 202 ---------------------------*/
static void M202Sync(void) {
/* According to more carefull hardware tests and PCB study */
int32 mirror = latche & 1;
int32 bank = (latche >> 1) & 0x7;
int32 select = (mirror & (bank >> 2));
setprg16(0x8000, select ? (bank & 6) | 0 : bank);
setprg16(0xc000, select ? (bank & 6) | 1 : bank);
setmirror(mirror ^ 1);
setchr8(bank);
}
void Mapper202_Init(CartInfo *info) {
Latch_Init(info, M202Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0);
}
/*------------------ Map 204 ---------------------------*/
static void M204Sync(void) {
int32 tmp2 = latche & 0x6;
int32 tmp1 = tmp2 + ((tmp2 == 0x6) ? 0 : (latche & 1));
setprg16(0x8000, tmp1);
setprg16(0xc000, tmp2 + ((tmp2 == 0x6) ? 1 : (latche & 1)));
setchr8(tmp1);
setmirror(((latche >> 4) & 1) ^ 1);
}
void Mapper204_Init(CartInfo *info) {
Latch_Init(info, M204Sync, NULL, 0xFFFF, 0x8000, 0xFFFF, 0);
}
/*------------------ Map 212 ---------------------------*/
static DECLFR(M212Read) {
uint8 ret = CartBROB(A);
if ((A & 0xE010) == 0x6000)
ret |= 0x80;
return ret;
}
static void M212Sync(void) {
if (latche & 0x4000) {
setprg32(0x8000, (latche >> 1) & 3);
} else {
setprg16(0x8000, latche & 7);
setprg16(0xC000, latche & 7);
}
setchr8(latche & 7);
setmirror(((latche >> 3) & 1) ^ 1);
}
void Mapper212_Init(CartInfo *info) {
Latch_Init(info, M212Sync, M212Read, 0x0000, 0x8000, 0xFFFF, 0);
}
/*------------------ Map 213 ---------------------------*/
/* SEE MAPPER 58 */
/*------------------ Map 214 ---------------------------*/
static void M214Sync(void) {
setprg16(0x8000, (latche >> 2) & 3);
setprg16(0xC000, (latche >> 2) & 3);
setchr8(latche & 3);
}
void Mapper214_Init(CartInfo *info) {
Latch_Init(info, M214Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0);
}
/*------------------ Map 217 ---------------------------*/
static void M217Sync(void) {
setprg32(0x8000, (latche >> 2) & 0x03);
setchr8(latche & 0x0F);
}
void Mapper217_Init(CartInfo *info) {
Latch_Init(info, M217Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0);
}
/*------------------ Map 227 ---------------------------*/
static void M227Sync(void) {
uint32 S = latche & 1;
uint32 p = ((latche >> 2) & 0x1F) + ((latche & 0x100) >> 3);
uint32 L = (latche >> 9) & 1;
if ((latche >> 7) & 1) {
if (S) {
setprg32(0x8000, p >> 1);
} else {
setprg16(0x8000, p);
setprg16(0xC000, p);
}
} else {
if (S) {
if (L) {
setprg16(0x8000, p & 0x3E);
setprg16(0xC000, p | 7);
} else {
setprg16(0x8000, p & 0x3E);
setprg16(0xC000, p & 0x38);
}
} else {
if (L) {
setprg16(0x8000, p);
setprg16(0xC000, p | 7);
} else {
setprg16(0x8000, p);
setprg16(0xC000, submapper ==2? 0: p & 0x38);
}
}
}
if (!hasBattery && (latche & 0x80) == 0x80)
/* CHR-RAM write protect hack, needed for some multicarts */
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0);
else
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1);
setmirror(((latche >> 1) & 1) ^ 1);
setchr8(0);
setprg8r(0x10, 0x6000, 0);
}
static DECLFR(M227Read) {
if (latche &0x0400)
return CartBR(A | dipswitch);
else
return CartBR(A);
}
static void Mapper227_Reset(void) {
dipswitch++;
dipswitch &= 15;
latche = 0;
M227Sync();
}
void Mapper227_Init(CartInfo *info) {
submapper =info->submapper;
Latch_Init(info, M227Sync, M227Read, 0x0000, 0x8000, 0xFFFF, info->iNES2 && (info->PRGRamSize || info->PRGRamSaveSize) || info->battery);
info->Reset = Mapper227_Reset;
AddExState(&dipswitch, 1, 0, "DIPSW");
}
/*------------------ Map 229 ---------------------------*/
static void M229Sync(void) {
setchr8(latche);
if (!(latche & 0x1e))
setprg32(0x8000, 0);
else {
setprg16(0x8000, latche & 0x1F);
setprg16(0xC000, latche & 0x1F);
}
setmirror(((latche >> 5) & 1) ^ 1);
}
void Mapper229_Init(CartInfo *info) {
Latch_Init(info, M229Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0);
}
/*------------------ Map 231 ---------------------------*/
static void M231Sync(void) {
setchr8(0);
if (latche & 0x20)
setprg32(0x8000, (latche >> 1) & 0x0F);
else {
setprg16(0x8000, latche & 0x1E);
setprg16(0xC000, latche & 0x1E);
}
setmirror(((latche >> 7) & 1) ^ 1);
}
void Mapper231_Init(CartInfo *info) {
Latch_Init(info, M231Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0);
}
/*------------------ Map 242 ---------------------------*/
static uint8 M242TwoChips;
static void M242Sync(void) {
uint32 S = latche & 1;
uint32 p = (latche >> 2) & 0x1F;
uint32 L = (latche >> 9) & 1;
if (M242TwoChips) {
if (latche &0x600)
{ /* First chip */
p &= 0x1F;
}
else
{ /* Second chip */
p &= 0x07;
p += 0x20;
}
}
if ((latche >> 7) & 1) {
if (S) {
setprg32(0x8000, p >> 1);
} else {
setprg16(0x8000, p);
setprg16(0xC000, p);
}
} else {
if (S) {
if (L) {
setprg16(0x8000, p & 0x3E);
setprg16(0xC000, p | 7);
} else {
setprg16(0x8000, p & 0x3E);
setprg16(0xC000, p & 0x38);
}
} else {
if (L) {
setprg16(0x8000, p);
setprg16(0xC000, p | 7);
} else {
setprg16(0x8000, p);
setprg16(0xC000, p & 0x38);
}
}
}
if (!hasBattery && (latche & 0x80) == 0x80 && (ROM_size * 16) > 256)
/* CHR-RAM write protect hack, needed for some multicarts */
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0);
else
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1);
setmirror(((latche >> 1) & 1) ^ 1);
setchr8(0);
setprg8r(0x10, 0x6000, 0);
}
static DECLFR(M242Read) {
if (latche &0x0100)
return CartBR(A | dipswitch);
else
return CartBR(A);
}
static void Mapper242_Reset(void) {
dipswitch++;
dipswitch &= 31;
latche = 0;
M242Sync();
}
void Mapper242_Init(CartInfo *info) {
M242TwoChips = info->PRGRomSize &0x20000 && info->PRGRomSize >0x20000;
Latch_Init(info, M242Sync, M242Read, 0x0000, 0x8000, 0xFFFF, info->iNES2 && (info->PRGRamSize || info->PRGRamSaveSize) || info->battery);
info->Reset = Mapper242_Reset;
AddExState(&dipswitch, 1, 0, "DIPSW");
}
/*------------------ Map 288 ---------------------------*/
/* NES 2.0 Mapper 288 is used for two GKCX1 21-in-1 multicarts
* - 21-in-1 (GA-003)
* - 64-in-1 (CF-015)
*/
static void M288Sync(void) {
setchr8(latche & 7);
setprg32(0x8000, (latche >> 3) & 3);
}
static DECLFR(M288Read) {
uint8 ret = CartBR(A);
if (latche & 0x20)
ret |= (dipswitch << 2);
return ret;
}
static void M288Reset(void) {
dipswitch++;
dipswitch &= 3;
M288Sync();
}
void Mapper288_Init(CartInfo *info) {
dipswitch = 0;
Latch_Init(info, M288Sync, M288Read, 0x0000, 0x8000, 0xFFFF, 0);
info->Reset = M288Reset;
AddExState(&dipswitch, 1, 0, "DIPSW");
}
/*------------------ Map 385 ---------------------------*/
static void M385Sync(void) {
int32 mirror = latche & 1;
int32 bank = (latche >> 1) & 0x7;
setprg16(0x8000, bank);
setprg16(0xc000, bank);
setmirror(mirror ^ 1);
setchr8(0);
}
void Mapper385_Init(CartInfo *info) {
Latch_Init(info, M385Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0);
}
/*------------------ Map 541 ---------------------------*/
/* LittleCom 160-in-1 multicart */
static void M541Sync(void) {
if (latche & 2) {
/* NROM-128 */
setprg16(0x8000, latche >> 2);
setprg16(0xC000, latche >> 2);
} else {
/* NROM=256 */
setprg32(0x8000, latche >> 3);
}
setchr8(0);
setmirror(latche & 1);
}
void Mapper541_Init(CartInfo *info) {
Latch_Init(info, M541Sync, NULL, 0x0000, 0xC000, 0xFFFF, 0);
}
/*------------------ 190in1 ---------------------------*/
static void BMC190in1Sync(void) {
setprg16(0x8000, (latche >> 2) & 7);
setprg16(0xC000, (latche >> 2) & 7);
setchr8((latche >> 2) & 7);
setmirror((latche & 1) ^ 1);
}
void BMC190in1_Init(CartInfo *info) {
Latch_Init(info, BMC190in1Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0);
}
/*-------------- BMC810544-C-A1 ------------------------*/
static void BMC810544CA1Sync(void) {
uint32 bank = latche >> 7;
if (latche & 0x40)
setprg32(0x8000, bank);
else {
setprg16(0x8000, (bank << 1) | ((latche >> 5) & 1));
setprg16(0xC000, (bank << 1) | ((latche >> 5) & 1));
}
setchr8(latche & 0x0f);
setmirror(((latche >> 4) & 1) ^ 1);
}
void BMC810544CA1_Init(CartInfo *info) {
Latch_Init(info, BMC810544CA1Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0);
}
/*-------------- BMCNTD-03 ------------------------*/
static void BMCNTD03Sync(void) {
/* 1PPP Pmcc spxx xccc
* 1000 0000 0000 0000 v
* 1001 1100 0000 0100 h
* 1011 1010 1100 0100
*/
uint32 prg = ((latche >> 10) & 0x1e);
uint32 chr = ((latche & 0x0300) >> 5) | (latche & 7);
if (latche & 0x80) {
setprg16(0x8000, prg | ((latche >> 6) & 1));
setprg16(0xC000, prg | ((latche >> 6) & 1));
} else
setprg32(0x8000, prg >> 1);
setchr8(chr);
setmirror(((latche >> 10) & 1) ^ 1);
}
void BMCNTD03_Init(CartInfo *info) {
Latch_Init(info, BMCNTD03Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0);
}
/*-------------- BMCG-146 ------------------------*/
static void BMCG146Sync(void) {
setchr8(0);
if (latche & 0x800) { /* UNROM mode */
setprg16(0x8000, (latche & 0x1F) | (latche & ((latche & 0x40) >> 6)));
setprg16(0xC000, (latche & 0x18) | 7);
} else {
if (latche & 0x40) { /* 16K mode */
setprg16(0x8000, latche & 0x1F);
setprg16(0xC000, latche & 0x1F);
} else {
setprg32(0x8000, (latche >> 1) & 0x0F);
}
}
setmirror(((latche & 0x80) >> 7) ^ 1);
}
void BMCG146_Init(CartInfo *info) {
Latch_Init(info, BMCG146Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0);
}
/*-------------- BMC-TJ-03 ------------------------*/
/* NES 2.0 mapper 341 is used for a simple 4-in-1 multicart */
static void BMCTJ03Sync(void) {
uint8 mirr = latche &(PRGsize[0] &0x40000? 0x800: 0x200)? MI_H: MI_V;
uint8 bank = latche >> 8;
setprg32(0x8000, bank);
setchr8(bank);
setmirror(mirr);
}
void BMCTJ03_Init(CartInfo *info) {
Latch_Init(info, BMCTJ03Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0);
}
/*-------------- BMC-SA005-A ------------------------*/
/* NES 2.0 mapper 338 is used for a 16-in-1 and a 200/300/600/1000-in-1 multicart.
* http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_338 */
static void BMCSA005ASync(void) {
setprg16(0x8000, latche & 0x0F);
setprg16(0xC000, latche & 0x0F);
setchr8(latche & 0x0F);
setmirror((latche >> 3) & 1);
}
void BMCSA005A_Init(CartInfo *info) {
Latch_Init(info, BMCSA005ASync, NULL, 0x0000, 0x8000, 0xFFFF, 0);
}
/* -------------- 831019C J-2282 ------------------------ */
static void J2282Sync(void)
{
setchr8(0);
if ((latche & 0x40)) {
uint8 bank = (latche >> 0) & 0x1F;
setprg16(0x8000, bank);
setprg16(0xC000, bank);
}
else
{
uint8 bank;
if (latche & 0x800)
{
setprg8(0x6000, ((latche << 1) & 0x3F) | 3);
}
bank = (latche >> 1) & 0x1F;
setprg32(0x8000, bank);
}
if (latche & 0x80)
setmirror(0);
else
setmirror(1);
}
void J2282_Init(CartInfo *info)
{
Latch_Init(info, J2282Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0);
}
/* -------------- Mapper 409 ------------------------ */
static void M409Sync(void) {
setprg16(0x8000, latche);
setprg16(0xC000, ~0);
setchr8(0);
}
void Mapper409_Init(CartInfo *info) {
Latch_Init(info, M409Sync, NULL, 0x0000, 0xC000, 0xCFFF, 0);
}
/*------------------ Map 435 ---------------------------*/
static void M435Sync(void) {
int p =latche >>2 &0x1F | latche >>3 &0x20 | latche >>4 &0x40;
if (latche &0x200) {
if (latche &0x001) {
setprg16(0x8000, p);
setprg16(0xC000, p);
} else {
setprg32(0x8000, p >> 1);
}
} else {
setprg16(0x8000, p);
setprg16(0xC000, p | 7);
}
if (latche &0x200)
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0);
else
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1);
setmirror(latche &0x002? MI_H: MI_V);
setchr8(0);
}
void Mapper435_Init(CartInfo *info) {
Latch_Init(info, M435Sync, NULL, 0x0000, 0x8000, 0xFFFF, 1);
}
/*------------------ Map 459 ---------------------------*/
static void M459Sync(void) {
int p =latche >>5;
int c =latche &0x03 | latche >>2 &0x04 | latche >>4 &0x08;
if (latche &0x04) {
setprg32(0x8000, p);
} else {
setprg16(0x8000, p <<1);
setprg16(0xC000, p <<1 |7);
}
setchr8(c &(latche &0x08? 0x0F: 0x08));
setmirror(latche &0x100? MI_H: MI_V);
}
void Mapper459_Init(CartInfo *info) {
Latch_Init(info, M459Sync, NULL, 0x0000, 0x8000, 0xFFFF, 1);
}
/*------------------ Map 461 ---------------------------*/
static void M461Sync(void) {
int p =latche <<1 | latche >>5 &1;
int c =latche >>8;
if (latche &0x10) {
setprg16(0x8000, p);
setprg16(0xC000, p);
} else {
setprg32(0x8000, p >>1);
}
setchr8(c);
setmirror(latche &0x80? MI_H: MI_V);
}
void Mapper461_Init(CartInfo *info) {
Latch_Init(info, M461Sync, NULL, 0x0000, 0x8000, 0xFFFF, 1);
}
/*------------------ Map 464 ---------------------------*/
static void M464Sync(void) {
int p =latche >>7;
int c =latche &0x1F;
if (latche &0x40) {
setprg32(0x8000, p >> 1);
} else {
setprg16(0x8000, p);
setprg16(0xC000, p);
}
setchr8(c);
setmirror(latche &0x20? MI_H: MI_V);
}
void Mapper464_Init(CartInfo *info) {
Latch_Init(info, M464Sync, NULL, 0x0000, 0x8000, 0xFFFF, 1);
}