diff --git a/src/boards/112.cpp b/src/boards/112.cpp index f0aeff3f..f0ee7aca 100644 --- a/src/boards/112.cpp +++ b/src/boards/112.cpp @@ -1,90 +1,90 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 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 - * - * NTDEC, ASDER games - * - */ - -#include "mapinc.h" - -static uint8 reg[8]; -static uint8 mirror, cmd, bank; -static uint8 *WRAM = NULL; - -static SFORMAT StateRegs[] = -{ - { &cmd, 1, "CMD" }, - { &mirror, 1, "MIRR" }, - { &bank, 1, "BANK" }, - { reg, 8, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setmirror(mirror ^ 1); - setprg8(0x8000, reg[0]); - setprg8(0xA000, reg[1]); - setchr2(0x0000, (reg[2] >> 1)); - setchr2(0x0800, (reg[3] >> 1)); - setchr1(0x1000, ((bank & 0x10) << 4) | reg[4]); - setchr1(0x1400, ((bank & 0x20) << 3) | reg[5]); - setchr1(0x1800, ((bank & 0x40) << 2) | reg[6]); - setchr1(0x1C00, ((bank & 0x80) << 1) | reg[7]); -} - -static DECLFW(M112Write) { - switch (A) { - case 0xe000: mirror = V & 1; Sync();; break; - case 0x8000: cmd = V & 7; break; - case 0xa000: reg[cmd] = V; Sync(); break; - case 0xc000: bank = V; Sync(); break; - } -} - -static void M112Close(void) { - if (WRAM) - FCEU_gfree(WRAM); - WRAM = NULL; -} - -static void M112Power(void) { - bank = 0; - setprg16(0xC000, ~0); - setprg8r(0x10, 0x6000, 0); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M112Write); - SetWriteHandler(0x4020, 0x5FFF, M112Write); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 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 + * + * NTDEC, ASDER games + * + */ + +#include "mapinc.h" + +static uint8 reg[8]; +static uint8 mirror, cmd, bank; +static uint8 *WRAM = NULL; + +static SFORMAT StateRegs[] = +{ + { &cmd, 1, "CMD" }, + { &mirror, 1, "MIRR" }, + { &bank, 1, "BANK" }, + { reg, 8, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setmirror(mirror ^ 1); + setprg8(0x8000, reg[0]); + setprg8(0xA000, reg[1]); + setchr2(0x0000, (reg[2] >> 1)); + setchr2(0x0800, (reg[3] >> 1)); + setchr1(0x1000, ((bank & 0x10) << 4) | reg[4]); + setchr1(0x1400, ((bank & 0x20) << 3) | reg[5]); + setchr1(0x1800, ((bank & 0x40) << 2) | reg[6]); + setchr1(0x1C00, ((bank & 0x80) << 1) | reg[7]); +} + +static DECLFW(M112Write) { + switch (A) { + case 0xe000: mirror = V & 1; Sync();; break; + case 0x8000: cmd = V & 7; break; + case 0xa000: reg[cmd] = V; Sync(); break; + case 0xc000: bank = V; Sync(); break; + } +} + +static void M112Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void M112Power(void) { + bank = 0; + setprg16(0xC000, ~0); + setprg8r(0x10, 0x6000, 0); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M112Write); + SetWriteHandler(0x4020, 0x5FFF, M112Write); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); FCEU_CheatAddRAM(8, 0x6000, WRAM); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper112_Init(CartInfo *info) { - info->Power = M112Power; - info->Close = M112Close; - GameStateRestore = StateRestore; - WRAM = (uint8*)FCEU_gmalloc(8192); - SetupCartPRGMapping(0x10, WRAM, 8192, 1); - AddExState(WRAM, 8192, 0, "WRAM"); - AddExState(&StateRegs, ~0, 0, 0); -} +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper112_Init(CartInfo *info) { + info->Power = M112Power; + info->Close = M112Close; + GameStateRestore = StateRestore; + WRAM = (uint8*)FCEU_gmalloc(8192); + SetupCartPRGMapping(0x10, WRAM, 8192, 1); + AddExState(WRAM, 8192, 0, "WRAM"); + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/164.cpp b/src/boards/164.cpp index 37b04396..6eb963bf 100644 --- a/src/boards/164.cpp +++ b/src/boards/164.cpp @@ -1,232 +1,232 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel 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 - * - * It seems that 162/163/164 mappers are the same mapper with just different - * mapper modes enabled or disabled in software or hardware, need more nanjing - * carts - */ - -#include "mapinc.h" - -static uint8 laststrobe, trigger; -static uint8 reg[8]; -static uint8 *WRAM = NULL; -static uint32 WRAMSIZE; - -static writefunc pcmwrite; - -static void (*WSync)(void); - -static SFORMAT StateRegs[] = -{ - { &laststrobe, 1, "STB" }, - { &trigger, 1, "TRG" }, - { reg, 8, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - setprg32(0x8000, (reg[0] << 4) | (reg[1] & 0xF)); - setchr8(0); -} - -static void StateRestore(int version) { - WSync(); -} - -static DECLFR(ReadLow) { - switch (A & 0x7700) { - case 0x5100: return reg[2] | reg[0] | reg[1] | reg[3] ^ 0xff; break; - case 0x5500: - if (trigger) - return reg[2] | reg[1]; // Lei Dian Huang Bi Ka Qiu Chuan Shuo (NJ046) may broke other games - else - return 0; - } - return 4; -} - -static void M163HB(void) { - if (reg[1] & 0x80) { - if (scanline == 239) { - setchr4(0x0000, 0); - setchr4(0x1000, 0); - } else if (scanline == 127) { - setchr4(0x0000, 1); - setchr4(0x1000, 1); - } -/* - if(scanline>=127) // Hu Lu Jin Gang (NJ039) (Ch) [!] don't like it - { - setchr4(0x0000,1); - setchr4(0x1000,1); - } - else - { - setchr4(0x0000,0); - setchr4(0x1000,0); - } -*/ - } -} - -static DECLFW(Write) { - switch (A & 0x7300) { - case 0x5100: reg[0] = V; WSync(); break; - case 0x5000: reg[1] = V; WSync(); break; - case 0x5300: reg[2] = V; break; - case 0x5200: reg[3] = V; WSync(); break; - } -} - -static void Power(void) { - memset(reg, 0, 8); - reg[1] = 0xFF; - SetWriteHandler(0x5000, 0x5FFF, Write); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel 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 + * + * It seems that 162/163/164 mappers are the same mapper with just different + * mapper modes enabled or disabled in software or hardware, need more nanjing + * carts + */ + +#include "mapinc.h" + +static uint8 laststrobe, trigger; +static uint8 reg[8]; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static writefunc pcmwrite; + +static void (*WSync)(void); + +static SFORMAT StateRegs[] = +{ + { &laststrobe, 1, "STB" }, + { &trigger, 1, "TRG" }, + { reg, 8, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg32(0x8000, (reg[0] << 4) | (reg[1] & 0xF)); + setchr8(0); +} + +static void StateRestore(int version) { + WSync(); +} + +static DECLFR(ReadLow) { + switch (A & 0x7700) { + case 0x5100: return reg[2] | reg[0] | reg[1] | reg[3] ^ 0xff; break; + case 0x5500: + if (trigger) + return reg[2] | reg[1]; // Lei Dian Huang Bi Ka Qiu Chuan Shuo (NJ046) may broke other games + else + return 0; + } + return 4; +} + +static void M163HB(void) { + if (reg[1] & 0x80) { + if (scanline == 239) { + setchr4(0x0000, 0); + setchr4(0x1000, 0); + } else if (scanline == 127) { + setchr4(0x0000, 1); + setchr4(0x1000, 1); + } +/* + if(scanline>=127) // Hu Lu Jin Gang (NJ039) (Ch) [!] don't like it + { + setchr4(0x0000,1); + setchr4(0x1000,1); + } + else + { + setchr4(0x0000,0); + setchr4(0x1000,0); + } +*/ + } +} + +static DECLFW(Write) { + switch (A & 0x7300) { + case 0x5100: reg[0] = V; WSync(); break; + case 0x5000: reg[1] = V; WSync(); break; + case 0x5300: reg[2] = V; break; + case 0x5200: reg[3] = V; WSync(); break; + } +} + +static void Power(void) { + memset(reg, 0, 8); + reg[1] = 0xFF; + SetWriteHandler(0x5000, 0x5FFF, Write); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - WSync(); -} - -static void Close(void) { - if (WRAM) - FCEU_gfree(WRAM); - WRAM = NULL; -} - -void Mapper164_Init(CartInfo *info) { - info->Power = Power; - info->Close = Close; - WSync = Sync; - - WRAMSIZE = 8192; - 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; - } - - GameStateRestore = StateRestore; - AddExState(&StateRegs, ~0, 0, 0); -} - -static DECLFW(Write2) { - if (A == 0x5101) { - if (laststrobe && !V) { - trigger ^= 1; - } - laststrobe = V; - } else if (A == 0x5100 && V == 6) //damn thoose protected games - setprg32(0x8000, 3); - else - switch (A & 0x7300) { - case 0x5200: reg[0] = V; WSync(); break; - case 0x5000: reg[1] = V; WSync(); if (!(reg[1] & 0x80) && (scanline < 128)) setchr8(0); /* setchr8(0); */ break; - case 0x5300: reg[2] = V; break; - case 0x5100: reg[3] = V; WSync(); break; - } -} - -static void Power2(void) { - memset(reg, 0, 8); - laststrobe = 1; - pcmwrite = GetWriteHandler(0x4011); - SetReadHandler(0x5000, 0x5FFF, ReadLow); - SetWriteHandler(0x5000, 0x5FFF, Write2); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); + WSync(); +} + +static void Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +void Mapper164_Init(CartInfo *info) { + info->Power = Power; + info->Close = Close; + WSync = Sync; + + WRAMSIZE = 8192; + 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; + } + + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +static DECLFW(Write2) { + if (A == 0x5101) { + if (laststrobe && !V) { + trigger ^= 1; + } + laststrobe = V; + } else if (A == 0x5100 && V == 6) //damn thoose protected games + setprg32(0x8000, 3); + else + switch (A & 0x7300) { + case 0x5200: reg[0] = V; WSync(); break; + case 0x5000: reg[1] = V; WSync(); if (!(reg[1] & 0x80) && (scanline < 128)) setchr8(0); /* setchr8(0); */ break; + case 0x5300: reg[2] = V; break; + case 0x5100: reg[3] = V; WSync(); break; + } +} + +static void Power2(void) { + memset(reg, 0, 8); + laststrobe = 1; + pcmwrite = GetWriteHandler(0x4011); + SetReadHandler(0x5000, 0x5FFF, ReadLow); + SetWriteHandler(0x5000, 0x5FFF, Write2); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - WSync(); -} - -void Mapper163_Init(CartInfo *info) { - info->Power = Power2; - info->Close = Close; - WSync = Sync; - GameHBIRQHook = M163HB; - - WRAMSIZE = 8192; - 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; - } - GameStateRestore = StateRestore; - AddExState(&StateRegs, ~0, 0, 0); -} - -static void Sync3(void) { - setchr8(0); - setprg8r(0x10, 0x6000, 0); - switch (reg[3] & 7) { - case 0: - case 2: setprg32(0x8000, (reg[0] & 0xc) | (reg[1] & 2) | ((reg[2] & 0xf) << 4)); break; - case 1: - case 3: setprg32(0x8000, (reg[0] & 0xc) | (reg[2] & 0xf) << 4); break; - case 4: - case 6: setprg32(0x8000, (reg[0] & 0xe) | ((reg[1] >> 1) & 1) | ((reg[2] & 0xf) << 4)); break; - case 5: - case 7: setprg32(0x8000, (reg[0] & 0xf) | ((reg[2] & 0xf) << 4)); break; - } -} - -static DECLFW(Write3) { -// FCEU_printf("bs %04x %02x\n",A,V); - reg[(A >> 8) & 3] = V; - WSync(); -} - -static void Power3(void) { - reg[0] = 3; - reg[1] = 0; - reg[2] = 0; - reg[3] = 7; - SetWriteHandler(0x5000, 0x5FFF, Write3); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); + WSync(); +} + +void Mapper163_Init(CartInfo *info) { + info->Power = Power2; + info->Close = Close; + WSync = Sync; + GameHBIRQHook = M163HB; + + WRAMSIZE = 8192; + 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; + } + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +static void Sync3(void) { + setchr8(0); + setprg8r(0x10, 0x6000, 0); + switch (reg[3] & 7) { + case 0: + case 2: setprg32(0x8000, (reg[0] & 0xc) | (reg[1] & 2) | ((reg[2] & 0xf) << 4)); break; + case 1: + case 3: setprg32(0x8000, (reg[0] & 0xc) | (reg[2] & 0xf) << 4); break; + case 4: + case 6: setprg32(0x8000, (reg[0] & 0xe) | ((reg[1] >> 1) & 1) | ((reg[2] & 0xf) << 4)); break; + case 5: + case 7: setprg32(0x8000, (reg[0] & 0xf) | ((reg[2] & 0xf) << 4)); break; + } +} + +static DECLFW(Write3) { +// FCEU_printf("bs %04x %02x\n",A,V); + reg[(A >> 8) & 3] = V; + WSync(); +} + +static void Power3(void) { + reg[0] = 3; + reg[1] = 0; + reg[2] = 0; + reg[3] = 7; + SetWriteHandler(0x5000, 0x5FFF, Write3); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - WSync(); -} - -void UNLFS304_Init(CartInfo *info) { - info->Power = Power3; - info->Close = Close; - WSync = Sync3; - - WRAMSIZE = 8192; - 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; - } - - GameStateRestore = StateRestore; - AddExState(&StateRegs, ~0, 0, 0); -} + WSync(); +} + +void UNLFS304_Init(CartInfo *info) { + info->Power = Power3; + info->Close = Close; + WSync = Sync3; + + WRAMSIZE = 8192; + 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; + } + + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/datalatch.cpp b/src/boards/datalatch.cpp index 260b9ff4..c9e9c985 100644 --- a/src/boards/datalatch.cpp +++ b/src/boards/datalatch.cpp @@ -1,543 +1,543 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * - * 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 "../ines.h" - -static uint8 latche, latcheinit, bus_conflict; -static uint16 addrreg0, addrreg1; -static uint8 *WRAM = NULL; -static uint32 WRAMSIZE; -static void (*WSync)(void); - -static DECLFW(LatchWrite) { -// FCEU_printf("bs %04x %02x\n",A,V); - if (bus_conflict) +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * + * 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 "../ines.h" + +static uint8 latche, latcheinit, bus_conflict; +static uint16 addrreg0, addrreg1; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; +static void (*WSync)(void); + +static DECLFW(LatchWrite) { +// FCEU_printf("bs %04x %02x\n",A,V); + if (bus_conflict) latche = V & CartBR(A); - else - latche = V; - 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(0x8000, 0xFFFF, CartBR); - } - 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), uint8 init, uint16 adr0, uint16 adr1, uint8 wram, uint8 busc) { - bus_conflict = busc; - latcheinit = init; - addrreg0 = adr0; - addrreg1 = adr1; - WSync = proc; - info->Power = LatchPower; - info->Close = LatchClose; - GameStateRestore = StateRestore; - if(info->ines2) - if(info->battery_wram_size + info->wram_size > 0) - wram = 1; - if (wram) - { - if(info->ines2) - { - //I would like to do it in this way, but FCEUX is woefully inadequate - //for instance if WRAMSIZE is large, the cheat pointers may get overwritten. and it's just a giant mess. - //WRAMSIZE = info->battery_wram_size + info->wram_size; - //WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - //if(!info->wram_size && !info->battery_wram_size) {} - //else if(info->wram_size && !info->battery_wram_size) - // SetupCartPRGMapping(0x10, WRAM, info->wram_size, 1); - //else if(!info->wram_size && info->battery_wram_size) - //{ - // SetupCartPRGMapping(0x10, WRAM, info->battery_wram_size, 1); - // info->SaveGame[0] = WRAM; - // info->SaveGameLen[0] = info->battery_wram_size; - //} else { - // //well, this is annoying - // SetupCartPRGMapping(0x10, WRAM, info->wram_size, 1); - // SetupCartPRGMapping(0x11, WRAM, info->battery_wram_size, 1); //? ? ? there probably isnt even a way to select this - // info->SaveGame[0] = WRAM + info->wram_size; - // info->SaveGameLen[0] = info->battery_wram_size; - //} - - //this is more likely the only practical scenario - WRAMSIZE = 8192; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - setprg8r(0x10, 0x6000, 0); - if(info->battery_wram_size) - { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = 8192; - } - } - else - { - WRAMSIZE = 8192; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - } - - } - AddExState(&latche, 1, 0, "LATC"); -} - -//------------------ Map 0 --------------------------- - -#ifdef DEBUG_MAPPER -static DECLFW(NROMWrite) { - FCEU_printf("bs %04x %02x\n", A, V); - CartBW(A, V); -} -#endif - -static void NROMPower(void) { - setprg8r(0x10, 0x6000, 0); // Famili BASIC (v3.0) need it (uses only 4KB), FP-BASIC uses 8KB - setprg16(0x8000, ~1); - setprg16(0xC000, ~0); - setchr8(0); - - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetReadHandler(0x8000, 0xFFFF, CartBR); - + else + latche = V; + 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(0x8000, 0xFFFF, CartBR); + } + 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), uint8 init, uint16 adr0, uint16 adr1, uint8 wram, uint8 busc) { + bus_conflict = busc; + latcheinit = init; + addrreg0 = adr0; + addrreg1 = adr1; + WSync = proc; + info->Power = LatchPower; + info->Close = LatchClose; + GameStateRestore = StateRestore; + if(info->ines2) + if(info->battery_wram_size + info->wram_size > 0) + wram = 1; + if (wram) + { + if(info->ines2) + { + //I would like to do it in this way, but FCEUX is woefully inadequate + //for instance if WRAMSIZE is large, the cheat pointers may get overwritten. and it's just a giant mess. + //WRAMSIZE = info->battery_wram_size + info->wram_size; + //WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + //if(!info->wram_size && !info->battery_wram_size) {} + //else if(info->wram_size && !info->battery_wram_size) + // SetupCartPRGMapping(0x10, WRAM, info->wram_size, 1); + //else if(!info->wram_size && info->battery_wram_size) + //{ + // SetupCartPRGMapping(0x10, WRAM, info->battery_wram_size, 1); + // info->SaveGame[0] = WRAM; + // info->SaveGameLen[0] = info->battery_wram_size; + //} else { + // //well, this is annoying + // SetupCartPRGMapping(0x10, WRAM, info->wram_size, 1); + // SetupCartPRGMapping(0x11, WRAM, info->battery_wram_size, 1); //? ? ? there probably isnt even a way to select this + // info->SaveGame[0] = WRAM + info->wram_size; + // info->SaveGameLen[0] = info->battery_wram_size; + //} + + //this is more likely the only practical scenario + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + setprg8r(0x10, 0x6000, 0); + if(info->battery_wram_size) + { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = 8192; + } + } + else + { + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + } + + } + AddExState(&latche, 1, 0, "LATC"); +} + +//------------------ Map 0 --------------------------- + +#ifdef DEBUG_MAPPER +static DECLFW(NROMWrite) { + FCEU_printf("bs %04x %02x\n", A, V); + CartBW(A, V); +} +#endif + +static void NROMPower(void) { + setprg8r(0x10, 0x6000, 0); // Famili BASIC (v3.0) need it (uses only 4KB), FP-BASIC uses 8KB + setprg16(0x8000, ~1); + setprg16(0xC000, ~0); + setchr8(0); + + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - -#ifdef DEBUG_MAPPER - SetWriteHandler(0x4020, 0xFFFF, NROMWrite); - #endif -} - -void NROM_Init(CartInfo *info) { - info->Power = NROMPower; - info->Close = LatchClose; - - WRAMSIZE = 8192; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); -} - -//------------------ Map 2 --------------------------- - -static void UNROMSync(void) { -// static uint32 mirror_in_use = 0; -// if (PRGsize[0] <= 128 * 1024) { -// setprg16(0x8000, latche & 0x7); -// if (latche & 8) mirror_in_use = 1; -// if (mirror_in_use) -// setmirror(((latche >> 3) & 1) ^ 1); // Higway Star Hacked mapper, disabled till new mapper defined -// } else - setprg16(0x8000, latche); - setprg16(0xc000, ~0); - setchr8(0); -} - -void UNROM_Init(CartInfo *info) { - Latch_Init(info, UNROMSync, 0, 0x8000, 0xFFFF, 0, 1); -} - -//------------------ Map 3 --------------------------- - -static void CNROMSync(void) { - setchr8(latche); - setprg32(0x8000, 0); - setprg8r(0x10, 0x6000, 0); // Hayauchy IGO uses 2Kb or RAM -} - -void CNROM_Init(CartInfo *info) { - Latch_Init(info, CNROMSync, 0, 0x8000, 0xFFFF, 1, 1); -} - -//------------------ Map 7 --------------------------- - -static void ANROMSync() { - setprg32(0x8000, latche & 0xF); - setmirror(MI_0 + ((latche >> 4) & 1)); - setchr8(0); -} - -void ANROM_Init(CartInfo *info) { - Latch_Init(info, ANROMSync, 0, 0x4020, 0xFFFF, 0, 0); -} - -//------------------ Map 8 --------------------------- - -static void M8Sync() { - setprg16(0x8000, latche >> 3); - setprg16(0xc000, 1); - setchr8(latche & 3); -} - -void Mapper8_Init(CartInfo *info) { - Latch_Init(info, M8Sync, 0, 0x8000, 0xFFFF, 0, 0); -} - -//------------------ Map 11 --------------------------- - -static void M11Sync(void) { - setprg32(0x8000, latche & 0xF); - setchr8(latche >> 4); -} - -void Mapper11_Init(CartInfo *info) { - Latch_Init(info, M11Sync, 0, 0x8000, 0xFFFF, 0, 0); -} - -void Mapper144_Init(CartInfo *info) { - Latch_Init(info, M11Sync, 0, 0x8001, 0xFFFF, 0, 0); -} - -//------------------ Map 13 --------------------------- - -static void CPROMSync(void) { - setchr4(0x0000, 0); - setchr4(0x1000, latche & 3); - setprg32(0x8000, 0); -} - -void CPROM_Init(CartInfo *info) { - Latch_Init(info, CPROMSync, 0, 0x8000, 0xFFFF, 0, 0); -} - -//------------------ Map 29 --------------------------- //Used by Glider, http://www.retrousb.com/product_info.php?cPath=30&products_id=58 - -static void M29Sync() { - setprg16(0x8000, (latche & 0x1C) >> 2); - setprg16(0xc000, ~0); - setchr8r(0, latche & 3); - setprg8r(0x10, 0x6000, 0); -} - -void Mapper29_Init(CartInfo *info) { - Latch_Init(info, M29Sync, 0, 0x8000, 0xFFFF, 1, 0); -} - - -//------------------ Map 38 --------------------------- - -static void M38Sync(void) { - setprg32(0x8000, latche & 3); - setchr8(latche >> 2); -} - -void Mapper38_Init(CartInfo *info) { - Latch_Init(info, M38Sync, 0, 0x7000, 0x7FFF, 0, 0); -} - -//------------------ Map 66 --------------------------- - -static void MHROMSync(void) { - setprg32(0x8000, latche >> 4); - setchr8(latche & 0xF); -} - -void MHROM_Init(CartInfo *info) { - Latch_Init(info, MHROMSync, 0, 0x8000, 0xFFFF, 0, 0); -} - -//------------------ Map 70 --------------------------- - -static void M70Sync() { - setprg16(0x8000, latche >> 4); - setprg16(0xc000, ~0); - setchr8(latche & 0xf); -} - -void Mapper70_Init(CartInfo *info) { - Latch_Init(info, M70Sync, 0, 0x8000, 0xFFFF, 0, 0); -} - -//------------------ Map 78 --------------------------- -/* Should be two separate emulation functions for this "mapper". Sigh. URGE TO KILL RISING. */ -static void M78Sync() { - setprg16(0x8000, (latche & 7)); - setprg16(0xc000, ~0); - setchr8(latche >> 4); - setmirror(MI_0 + ((latche >> 3) & 1)); -} - -void Mapper78_Init(CartInfo *info) { - Latch_Init(info, M78Sync, 0, 0x8000, 0xFFFF, 0, 0); -} - -//------------------ Map 86 --------------------------- - -static void M86Sync(void) { - setprg32(0x8000, (latche >> 4) & 3); - setchr8((latche & 3) | ((latche >> 4) & 4)); -} - -void Mapper86_Init(CartInfo *info) { - Latch_Init(info, M86Sync, ~0, 0x6000, 0x6FFF, 0, 0); -} - -//------------------ Map 87 --------------------------- - -static void M87Sync(void) { - setprg32(0x8000, 0); - setchr8(((latche >> 1) & 1) | ((latche << 1) & 2)); -} - -void Mapper87_Init(CartInfo *info) { - Latch_Init(info, M87Sync, ~0, 0x6000, 0xFFFF, 0, 0); -} - -//------------------ Map 89 --------------------------- - -static void M89Sync(void) { - setprg16(0x8000, (latche >> 4) & 7); - setprg16(0xc000, ~0); - setchr8((latche & 7) | ((latche >> 4) & 8)); - setmirror(MI_0 + ((latche >> 3) & 1)); -} - -void Mapper89_Init(CartInfo *info) { - Latch_Init(info, M89Sync, 0, 0x8000, 0xFFFF, 0, 0); -} - -//------------------ Map 93 --------------------------- - -static void SSUNROMSync(void) { - setprg16(0x8000, latche >> 4); - setprg16(0xc000, ~0); - setchr8(0); -} - -void SUNSOFT_UNROM_Init(CartInfo *info) { - Latch_Init(info, SSUNROMSync, 0, 0x8000, 0xFFFF, 0, 0); -} - -//------------------ Map 94 --------------------------- - -static void M94Sync(void) { - setprg16(0x8000, latche >> 2); - setprg16(0xc000, ~0); - setchr8(0); -} - -void Mapper94_Init(CartInfo *info) { - Latch_Init(info, M94Sync, 0, 0x8000, 0xFFFF, 0, 0); -} - -//------------------ Map 97 --------------------------- - -static void M97Sync(void) { - setchr8(0); - setprg16(0x8000, ~0); - setprg16(0xc000, latche & 15); - switch (latche >> 6) { - case 0: break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_V); break; - case 3: break; - } - setchr8(((latche >> 1) & 1) | ((latche << 1) & 2)); -} - -void Mapper97_Init(CartInfo *info) { - Latch_Init(info, M97Sync, ~0, 0x8000, 0xFFFF, 0, 0); -} - -//------------------ Map 101 --------------------------- - -static void M101Sync(void) { - setprg32(0x8000, 0); - setchr8(latche); -} - -void Mapper101_Init(CartInfo *info) { - Latch_Init(info, M101Sync, ~0, 0x6000, 0x7FFF, 0, 0); -} - -//------------------ Map 107 --------------------------- - -static void M107Sync(void) { - setprg32(0x8000, (latche >> 1) & 3); - setchr8(latche & 7); -} - -void Mapper107_Init(CartInfo *info) { - Latch_Init(info, M107Sync, ~0, 0x8000, 0xFFFF, 0, 0); -} - -//------------------ Map 113 --------------------------- - -static void M113Sync(void) { - setprg32(0x8000, (latche >> 3) & 7); - setchr8(((latche >> 3) & 8) | (latche & 7)); -// setmirror(latche>>7); // only for HES 6in1 -} - -void Mapper113_Init(CartInfo *info) { - Latch_Init(info, M113Sync, 0, 0x4100, 0x7FFF, 0, 0); -} - -//------------------ Map 140 --------------------------- - -void Mapper140_Init(CartInfo *info) { - Latch_Init(info, MHROMSync, 0, 0x6000, 0x7FFF, 0, 0); -} - -//------------------ Map 152 --------------------------- - -static void M152Sync() { - setprg16(0x8000, (latche >> 4) & 7); - setprg16(0xc000, ~0); - setchr8(latche & 0xf); - setmirror(MI_0 + ((latche >> 7) & 1)); /* Saint Seiya...hmm. */ -} - -void Mapper152_Init(CartInfo *info) { - Latch_Init(info, M152Sync, 0, 0x8000, 0xFFFF, 0, 0); -} - -//------------------ Map 180 --------------------------- - -static void M180Sync(void) { - setprg16(0x8000, 0); - setprg16(0xc000, latche); - setchr8(0); -} - -void Mapper180_Init(CartInfo *info) { - Latch_Init(info, M180Sync, 0, 0x8000, 0xFFFF, 0, 0); -} - -//------------------ Map 184 --------------------------- - -static void M184Sync(void) { - setchr4(0x0000, latche); - setchr4(0x1000, latche >> 4); - setprg32(0x8000, 0); -} - -void Mapper184_Init(CartInfo *info) { - Latch_Init(info, M184Sync, 0, 0x6000, 0x7FFF, 0, 0); -} - -//------------------ Map 203 --------------------------- - -static void M203Sync(void) { - setprg16(0x8000, (latche >> 2) & 3); - setprg16(0xC000, (latche >> 2) & 3); - setchr8(latche & 3); -} - -void Mapper203_Init(CartInfo *info) { - Latch_Init(info, M203Sync, 0, 0x8000, 0xFFFF, 0, 0); -} - -//------------------ Map 240 --------------------------- - -static void M240Sync(void) { - setprg8r(0x10, 0x6000, 0); - setprg32(0x8000, latche >> 4); - setchr8(latche & 0xF); -} - -void Mapper240_Init(CartInfo *info) { - Latch_Init(info, M240Sync, 0, 0x4020, 0x5FFF, 1, 0); -} - -//------------------ Map 241 --------------------------- -// Mapper 7 mostly, but with SRAM or maybe prot circuit -// figure out, which games do need 5xxx area reading - -static void M241Sync(void) { - setchr8(0); - setprg8r(0x10, 0x6000, 0); - if (latche & 0x80) - setprg32(0x8000, latche | 8); // no 241 actually, but why not afterall? - else - setprg32(0x8000, latche); -} - -void Mapper241_Init(CartInfo *info) { - Latch_Init(info, M241Sync, 0, 0x8000, 0xFFFF, 1, 0); -} - -//------------------ A65AS --------------------------- - -// actually, there is two cart in one... First have extra mirroring -// mode (one screen) and 32K bankswitching, second one have only -// 16 bankswitching mode and normal mirroring... But there is no any -// correlations between modes and they can be used in one mapper code. - -static void BMCA65ASSync(void) { - if (latche & 0x40) - setprg32(0x8000, (latche >> 1) & 0x0F); - else { - setprg16(0x8000, ((latche & 0x30) >> 1) | (latche & 7)); - setprg16(0xC000, ((latche & 0x30) >> 1) | 7); - } - setchr8(0); - if (latche & 0x80) - setmirror(MI_0 + (((latche >> 5) & 1))); - else - setmirror(((latche >> 3) & 1) ^ 1); -} - -void BMCA65AS_Init(CartInfo *info) { - Latch_Init(info, BMCA65ASSync, 0, 0x8000, 0xFFFF, 0, 0); -} - -//------------------ BMC-11160 --------------------------- -// Simple BMC discrete mapper by TXC - -static void BMC11160Sync(void) { - uint32 bank = (latche >> 4) & 7; - setprg32(0x8000, bank); - setchr8((bank << 2) | (latche & 3)); - setmirror((latche >> 7) & 1); -} - -void BMC11160_Init(CartInfo *info) { - Latch_Init(info, BMC11160Sync, 0, 0x8000, 0xFFFF, 0, 0); -} + +#ifdef DEBUG_MAPPER + SetWriteHandler(0x4020, 0xFFFF, NROMWrite); + #endif +} + +void NROM_Init(CartInfo *info) { + info->Power = NROMPower; + info->Close = LatchClose; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} + +//------------------ Map 2 --------------------------- + +static void UNROMSync(void) { +// static uint32 mirror_in_use = 0; +// if (PRGsize[0] <= 128 * 1024) { +// setprg16(0x8000, latche & 0x7); +// if (latche & 8) mirror_in_use = 1; +// if (mirror_in_use) +// setmirror(((latche >> 3) & 1) ^ 1); // Higway Star Hacked mapper, disabled till new mapper defined +// } else + setprg16(0x8000, latche); + setprg16(0xc000, ~0); + setchr8(0); +} + +void UNROM_Init(CartInfo *info) { + Latch_Init(info, UNROMSync, 0, 0x8000, 0xFFFF, 0, 1); +} + +//------------------ Map 3 --------------------------- + +static void CNROMSync(void) { + setchr8(latche); + setprg32(0x8000, 0); + setprg8r(0x10, 0x6000, 0); // Hayauchy IGO uses 2Kb or RAM +} + +void CNROM_Init(CartInfo *info) { + Latch_Init(info, CNROMSync, 0, 0x8000, 0xFFFF, 1, 1); +} + +//------------------ Map 7 --------------------------- + +static void ANROMSync() { + setprg32(0x8000, latche & 0xF); + setmirror(MI_0 + ((latche >> 4) & 1)); + setchr8(0); +} + +void ANROM_Init(CartInfo *info) { + Latch_Init(info, ANROMSync, 0, 0x4020, 0xFFFF, 0, 0); +} + +//------------------ Map 8 --------------------------- + +static void M8Sync() { + setprg16(0x8000, latche >> 3); + setprg16(0xc000, 1); + setchr8(latche & 3); +} + +void Mapper8_Init(CartInfo *info) { + Latch_Init(info, M8Sync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ Map 11 --------------------------- + +static void M11Sync(void) { + setprg32(0x8000, latche & 0xF); + setchr8(latche >> 4); +} + +void Mapper11_Init(CartInfo *info) { + Latch_Init(info, M11Sync, 0, 0x8000, 0xFFFF, 0, 0); +} + +void Mapper144_Init(CartInfo *info) { + Latch_Init(info, M11Sync, 0, 0x8001, 0xFFFF, 0, 0); +} + +//------------------ Map 13 --------------------------- + +static void CPROMSync(void) { + setchr4(0x0000, 0); + setchr4(0x1000, latche & 3); + setprg32(0x8000, 0); +} + +void CPROM_Init(CartInfo *info) { + Latch_Init(info, CPROMSync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ Map 29 --------------------------- //Used by Glider, http://www.retrousb.com/product_info.php?cPath=30&products_id=58 + +static void M29Sync() { + setprg16(0x8000, (latche & 0x1C) >> 2); + setprg16(0xc000, ~0); + setchr8r(0, latche & 3); + setprg8r(0x10, 0x6000, 0); +} + +void Mapper29_Init(CartInfo *info) { + Latch_Init(info, M29Sync, 0, 0x8000, 0xFFFF, 1, 0); +} + + +//------------------ Map 38 --------------------------- + +static void M38Sync(void) { + setprg32(0x8000, latche & 3); + setchr8(latche >> 2); +} + +void Mapper38_Init(CartInfo *info) { + Latch_Init(info, M38Sync, 0, 0x7000, 0x7FFF, 0, 0); +} + +//------------------ Map 66 --------------------------- + +static void MHROMSync(void) { + setprg32(0x8000, latche >> 4); + setchr8(latche & 0xF); +} + +void MHROM_Init(CartInfo *info) { + Latch_Init(info, MHROMSync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ Map 70 --------------------------- + +static void M70Sync() { + setprg16(0x8000, latche >> 4); + setprg16(0xc000, ~0); + setchr8(latche & 0xf); +} + +void Mapper70_Init(CartInfo *info) { + Latch_Init(info, M70Sync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ Map 78 --------------------------- +/* Should be two separate emulation functions for this "mapper". Sigh. URGE TO KILL RISING. */ +static void M78Sync() { + setprg16(0x8000, (latche & 7)); + setprg16(0xc000, ~0); + setchr8(latche >> 4); + setmirror(MI_0 + ((latche >> 3) & 1)); +} + +void Mapper78_Init(CartInfo *info) { + Latch_Init(info, M78Sync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ Map 86 --------------------------- + +static void M86Sync(void) { + setprg32(0x8000, (latche >> 4) & 3); + setchr8((latche & 3) | ((latche >> 4) & 4)); +} + +void Mapper86_Init(CartInfo *info) { + Latch_Init(info, M86Sync, ~0, 0x6000, 0x6FFF, 0, 0); +} + +//------------------ Map 87 --------------------------- + +static void M87Sync(void) { + setprg32(0x8000, 0); + setchr8(((latche >> 1) & 1) | ((latche << 1) & 2)); +} + +void Mapper87_Init(CartInfo *info) { + Latch_Init(info, M87Sync, ~0, 0x6000, 0xFFFF, 0, 0); +} + +//------------------ Map 89 --------------------------- + +static void M89Sync(void) { + setprg16(0x8000, (latche >> 4) & 7); + setprg16(0xc000, ~0); + setchr8((latche & 7) | ((latche >> 4) & 8)); + setmirror(MI_0 + ((latche >> 3) & 1)); +} + +void Mapper89_Init(CartInfo *info) { + Latch_Init(info, M89Sync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ Map 93 --------------------------- + +static void SSUNROMSync(void) { + setprg16(0x8000, latche >> 4); + setprg16(0xc000, ~0); + setchr8(0); +} + +void SUNSOFT_UNROM_Init(CartInfo *info) { + Latch_Init(info, SSUNROMSync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ Map 94 --------------------------- + +static void M94Sync(void) { + setprg16(0x8000, latche >> 2); + setprg16(0xc000, ~0); + setchr8(0); +} + +void Mapper94_Init(CartInfo *info) { + Latch_Init(info, M94Sync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ Map 97 --------------------------- + +static void M97Sync(void) { + setchr8(0); + setprg16(0x8000, ~0); + setprg16(0xc000, latche & 15); + switch (latche >> 6) { + case 0: break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_V); break; + case 3: break; + } + setchr8(((latche >> 1) & 1) | ((latche << 1) & 2)); +} + +void Mapper97_Init(CartInfo *info) { + Latch_Init(info, M97Sync, ~0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ Map 101 --------------------------- + +static void M101Sync(void) { + setprg32(0x8000, 0); + setchr8(latche); +} + +void Mapper101_Init(CartInfo *info) { + Latch_Init(info, M101Sync, ~0, 0x6000, 0x7FFF, 0, 0); +} + +//------------------ Map 107 --------------------------- + +static void M107Sync(void) { + setprg32(0x8000, (latche >> 1) & 3); + setchr8(latche & 7); +} + +void Mapper107_Init(CartInfo *info) { + Latch_Init(info, M107Sync, ~0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ Map 113 --------------------------- + +static void M113Sync(void) { + setprg32(0x8000, (latche >> 3) & 7); + setchr8(((latche >> 3) & 8) | (latche & 7)); +// setmirror(latche>>7); // only for HES 6in1 +} + +void Mapper113_Init(CartInfo *info) { + Latch_Init(info, M113Sync, 0, 0x4100, 0x7FFF, 0, 0); +} + +//------------------ Map 140 --------------------------- + +void Mapper140_Init(CartInfo *info) { + Latch_Init(info, MHROMSync, 0, 0x6000, 0x7FFF, 0, 0); +} + +//------------------ Map 152 --------------------------- + +static void M152Sync() { + setprg16(0x8000, (latche >> 4) & 7); + setprg16(0xc000, ~0); + setchr8(latche & 0xf); + setmirror(MI_0 + ((latche >> 7) & 1)); /* Saint Seiya...hmm. */ +} + +void Mapper152_Init(CartInfo *info) { + Latch_Init(info, M152Sync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ Map 180 --------------------------- + +static void M180Sync(void) { + setprg16(0x8000, 0); + setprg16(0xc000, latche); + setchr8(0); +} + +void Mapper180_Init(CartInfo *info) { + Latch_Init(info, M180Sync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ Map 184 --------------------------- + +static void M184Sync(void) { + setchr4(0x0000, latche); + setchr4(0x1000, latche >> 4); + setprg32(0x8000, 0); +} + +void Mapper184_Init(CartInfo *info) { + Latch_Init(info, M184Sync, 0, 0x6000, 0x7FFF, 0, 0); +} + +//------------------ Map 203 --------------------------- + +static void M203Sync(void) { + setprg16(0x8000, (latche >> 2) & 3); + setprg16(0xC000, (latche >> 2) & 3); + setchr8(latche & 3); +} + +void Mapper203_Init(CartInfo *info) { + Latch_Init(info, M203Sync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ Map 240 --------------------------- + +static void M240Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg32(0x8000, latche >> 4); + setchr8(latche & 0xF); +} + +void Mapper240_Init(CartInfo *info) { + Latch_Init(info, M240Sync, 0, 0x4020, 0x5FFF, 1, 0); +} + +//------------------ Map 241 --------------------------- +// Mapper 7 mostly, but with SRAM or maybe prot circuit +// figure out, which games do need 5xxx area reading + +static void M241Sync(void) { + setchr8(0); + setprg8r(0x10, 0x6000, 0); + if (latche & 0x80) + setprg32(0x8000, latche | 8); // no 241 actually, but why not afterall? + else + setprg32(0x8000, latche); +} + +void Mapper241_Init(CartInfo *info) { + Latch_Init(info, M241Sync, 0, 0x8000, 0xFFFF, 1, 0); +} + +//------------------ A65AS --------------------------- + +// actually, there is two cart in one... First have extra mirroring +// mode (one screen) and 32K bankswitching, second one have only +// 16 bankswitching mode and normal mirroring... But there is no any +// correlations between modes and they can be used in one mapper code. + +static void BMCA65ASSync(void) { + if (latche & 0x40) + setprg32(0x8000, (latche >> 1) & 0x0F); + else { + setprg16(0x8000, ((latche & 0x30) >> 1) | (latche & 7)); + setprg16(0xC000, ((latche & 0x30) >> 1) | 7); + } + setchr8(0); + if (latche & 0x80) + setmirror(MI_0 + (((latche >> 5) & 1))); + else + setmirror(((latche >> 3) & 1) ^ 1); +} + +void BMCA65AS_Init(CartInfo *info) { + Latch_Init(info, BMCA65ASSync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ BMC-11160 --------------------------- +// Simple BMC discrete mapper by TXC + +static void BMC11160Sync(void) { + uint32 bank = (latche >> 4) & 7; + setprg32(0x8000, bank); + setchr8((bank << 2) | (latche & 3)); + setmirror((latche >> 7) & 1); +} + +void BMC11160_Init(CartInfo *info) { + Latch_Init(info, BMC11160Sync, 0, 0x8000, 0xFFFF, 0, 0); +} diff --git a/src/boards/pec-586.cpp b/src/boards/pec-586.cpp index 0eac60ce..b7559c5f 100644 --- a/src/boards/pec-586.cpp +++ b/src/boards/pec-586.cpp @@ -16,6 +16,9 @@ * 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 + * + * PEC-586 FC based computer series by DUNDA + * */ #include "mapinc.h" diff --git a/src/boards/vrc5.cpp b/src/boards/vrc5.cpp index eb5d7e39..6bdecc0f 100644 --- a/src/boards/vrc5.cpp +++ b/src/boards/vrc5.cpp @@ -17,20 +17,24 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * VRC-5 (CAI Shogakko no Sansu) + * VRC-V (CAI Shogakko no Sansu) * */ #include "mapinc.h" -#define CAI_DEBUG +//#define CAI_DEBUG -static writefunc old2006wrap; -static writefunc old2007wrap; -static uint8 QTAINTRAM[2048]; -static uint16 qtaintramofs; +// main tiles RAM is 8K in size, but unless other non-CHR ROM type carts, +// this one accesses the $0000 and $1000 pages based on extra NT RAM on board +// which is similar to MMC5 but much simpler because there are no additional +// bankings here. +// extra NT RAM handling is in PPU code now. static uint16 CHRSIZE = 8192; +// there are two separate WRAMs 8K each, on main system cartridge (not battery +// backed), and one on the daughter cart (with battery). both are accessed +// via the same registers with additional selector flags. static uint16 WRAMSIZE = 8192 + 8192; static uint8 *CHRRAM = NULL; static uint8 *WRAM = NULL; @@ -38,72 +42,91 @@ static uint8 *WRAM = NULL; static uint8 IRQa, K4IRQ; static uint32 IRQLatch, IRQCount; -static uint8 conv_tbl[128][4] = { - { 0x40, 0x40, 0x40, 0x40 }, - { 0x41, 0x41, 0x41, 0x41 }, - { 0x42, 0x42, 0x42, 0x42 }, - { 0x43, 0x43, 0x43, 0x43 }, - { 0x44, 0x44, 0x44, 0x44 }, - { 0x45, 0x45, 0x45, 0x45 }, - { 0x46, 0x46, 0x46, 0x46 }, - { 0x47, 0x47, 0x47, 0x47 }, - { 0x40, 0x40, 0x40, 0x40 }, - { 0x41, 0x41, 0x41, 0x41 }, - { 0x42, 0x42, 0x42, 0x42 }, - { 0x43, 0x43, 0x43, 0x43 }, - { 0x44, 0x44, 0x44, 0x44 }, - { 0x45, 0x45, 0x45, 0x45 }, - { 0x46, 0x46, 0x46, 0x46 }, - { 0x47, 0x47, 0x47, 0x47 }, - { 0x40, 0x40, 0x48, 0x44 }, - { 0x41, 0x41, 0x49, 0x45 }, - { 0x42, 0x42, 0x4A, 0x46 }, - { 0x43, 0x43, 0x4B, 0x47 }, - { 0x44, 0x40, 0x48, 0x44 }, - { 0x45, 0x41, 0x49, 0x45 }, - { 0x46, 0x42, 0x4A, 0x46 }, - { 0x47, 0x43, 0x4B, 0x47 }, - { 0x40, 0x50, 0x58, 0x60 }, - { 0x41, 0x51, 0x59, 0x61 }, - { 0x42, 0x52, 0x5A, 0x62 }, - { 0x43, 0x53, 0x5B, 0x63 }, - { 0x44, 0x54, 0x5C, 0x64 }, - { 0x45, 0x55, 0x5D, 0x65 }, - { 0x46, 0x56, 0x5E, 0x66 }, - { 0x47, 0x57, 0x5F, 0x67 }, - { 0x40, 0x68, 0x70, 0x78 }, - { 0x41, 0x69, 0x71, 0x79 }, - { 0x42, 0x6A, 0x72, 0x7A }, - { 0x43, 0x6B, 0x73, 0x7B }, - { 0x44, 0x6C, 0x74, 0x7C }, - { 0x45, 0x6D, 0x75, 0x7D }, - { 0x46, 0x6E, 0x76, 0x7E }, - { 0x47, 0x6F, 0x77, 0x7F }, - { 0x40, 0x40, 0x48, 0x50 }, - { 0x41, 0x41, 0x49, 0x51 }, - { 0x42, 0x42, 0x4A, 0x52 }, - { 0x43, 0x43, 0x4B, 0x53 }, - { 0x44, 0x44, 0x4C, 0x54 }, - { 0x45, 0x45, 0x4D, 0x55 }, - { 0x46, 0x46, 0x4E, 0x56 }, - { 0x47, 0x47, 0x4F, 0x57 }, - { 0x40, 0x58, 0x60, 0x68 }, - { 0x41, 0x59, 0x61, 0x69 }, - { 0x42, 0x5A, 0x62, 0x6A }, - { 0x43, 0x5B, 0x63, 0x6B }, - { 0x44, 0x5C, 0x64, 0x6C }, - { 0x45, 0x5D, 0x65, 0x6D }, - { 0x46, 0x5E, 0x66, 0x6E }, - { 0x47, 0x5F, 0x67, 0x6F }, - { 0x40, 0x70, 0x78, 0x74 }, - { 0x41, 0x71, 0x79, 0x75 }, - { 0x42, 0x72, 0x7A, 0x76 }, - { 0x43, 0x73, 0x7B, 0x77 }, - { 0x44, 0x74, 0x7C, 0x74 }, - { 0x45, 0x75, 0x7D, 0x75 }, - { 0x46, 0x76, 0x7E, 0x76 }, - { 0x47, 0x77, 0x7F, 0x77 }, +// some kind of 16-bit text encoding (actually 14-bit) used in game resources +// may be converted by the hardware into the tile indexes for internal CHR ROM +// not sure whey they made it hardware, because most of calculations are just +// bit shifting. the main purpose of this table is to calculate actual CHR ROM +// bank for every character. there is a some kind of regularity, so this table +// may be calculated in software easily. + +// table read out from hardware registers as is + +///* +static uint8 conv_tbl[4][8] = { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x40, 0x10, 0x28, 0x00, 0x18, 0x30 }, + { 0x00, 0x00, 0x48, 0x18, 0x30, 0x08, 0x20, 0x38 }, + { 0x00, 0x00, 0x80, 0x20, 0x38, 0x10, 0x28, 0xB0 } }; +//*/ +/* +static uint8 conv_tbl[64][4] = { + { 0x40, 0x40, 0x40, 0x40 }, // 00 | A - 40 41 42 43 44 45 46 47 + { 0x41, 0x41, 0x41, 0x41 }, // 02 | B - 48 49 4A 4B 4C 4D 4E 4F + { 0x42, 0x42, 0x42, 0x42 }, // 04 | C - 50 51 52 53 54 55 56 57 + { 0x43, 0x43, 0x43, 0x43 }, // 06 | D - 58 59 5A 5B 5C 5D 5E 5F + { 0x44, 0x44, 0x44, 0x44 }, // 08 | E - 60 61 62 63 64 65 66 67 + { 0x45, 0x45, 0x45, 0x45 }, // 0A | F - 68 69 6A 6B 6C 6D 6E 6F + { 0x46, 0x46, 0x46, 0x46 }, // 0C | G - 70 71 72 73 74 75 76 77 + { 0x47, 0x47, 0x47, 0x47 }, // 0E | H - 78 79 7A 7B 7C 7D 7E 7F + { 0x40, 0x40, 0x40, 0x40 }, // 10 | + { 0x41, 0x41, 0x41, 0x41 }, // 12 +---------------------------- + { 0x42, 0x42, 0x42, 0x42 }, // 14 | A A A A + { 0x43, 0x43, 0x43, 0x43 }, // 16 | A A A A + { 0x44, 0x44, 0x44, 0x44 }, // 18 | A A' B' A" + { 0x45, 0x45, 0x45, 0x45 }, // 1A | A C D E + { 0x46, 0x46, 0x46, 0x46 }, // 1C | A F G H + { 0x47, 0x47, 0x47, 0x47 }, // 1E | A A B C + { 0x40, 0x40, 0x48, 0x44 }, // 20 | A D E F + { 0x41, 0x41, 0x49, 0x45 }, // 22 | A G H G" + { 0x42, 0x42, 0x4A, 0x46 }, // 24 +---------------------------- + { 0x43, 0x43, 0x4B, 0x47 }, // 26 | A' - 40 41 42 43 40 41 42 43 + { 0x44, 0x40, 0x48, 0x44 }, // 28 | A" - 44 45 46 47 44 45 46 47 + { 0x45, 0x41, 0x49, 0x45 }, // 2A | B' - 48 49 4A 4B 48 49 4A 4B + { 0x46, 0x42, 0x4A, 0x46 }, // 2C | G" - 74 75 76 77 74 75 76 77 + { 0x47, 0x43, 0x4B, 0x47 }, // 2E + { 0x40, 0x50, 0x58, 0x60 }, // 30 + { 0x41, 0x51, 0x59, 0x61 }, // 32 + { 0x42, 0x52, 0x5A, 0x62 }, // 34 + { 0x43, 0x53, 0x5B, 0x63 }, // 36 + { 0x44, 0x54, 0x5C, 0x64 }, // 38 + { 0x45, 0x55, 0x5D, 0x65 }, // 3A + { 0x46, 0x56, 0x5E, 0x66 }, // 3C + { 0x47, 0x57, 0x5F, 0x67 }, // 3E + { 0x40, 0x68, 0x70, 0x78 }, // 40 + { 0x41, 0x69, 0x71, 0x79 }, // 42 + { 0x42, 0x6A, 0x72, 0x7A }, // 44 + { 0x43, 0x6B, 0x73, 0x7B }, // 46 + { 0x44, 0x6C, 0x74, 0x7C }, // 48 + { 0x45, 0x6D, 0x75, 0x7D }, // 4A + { 0x46, 0x6E, 0x76, 0x7E }, // 4C + { 0x47, 0x6F, 0x77, 0x7F }, // 4E + { 0x40, 0x40, 0x48, 0x50 }, // 50 + { 0x41, 0x41, 0x49, 0x51 }, // 52 + { 0x42, 0x42, 0x4A, 0x52 }, // 54 + { 0x43, 0x43, 0x4B, 0x53 }, // 56 + { 0x44, 0x44, 0x4C, 0x54 }, // 58 + { 0x45, 0x45, 0x4D, 0x55 }, // 5A + { 0x46, 0x46, 0x4E, 0x56 }, // 5C + { 0x47, 0x47, 0x4F, 0x57 }, // 5E + { 0x40, 0x58, 0x60, 0x68 }, // 60 + { 0x41, 0x59, 0x61, 0x69 }, // 62 + { 0x42, 0x5A, 0x62, 0x6A }, // 64 + { 0x43, 0x5B, 0x63, 0x6B }, // 66 + { 0x44, 0x5C, 0x64, 0x6C }, // 68 + { 0x45, 0x5D, 0x65, 0x6D }, // 6A + { 0x46, 0x5E, 0x66, 0x6E }, // 6C + { 0x47, 0x5F, 0x67, 0x6F }, // 6E + { 0x40, 0x70, 0x78, 0x74 }, // 70 + { 0x41, 0x71, 0x79, 0x75 }, // 72 + { 0x42, 0x72, 0x7A, 0x76 }, // 74 + { 0x43, 0x73, 0x7B, 0x77 }, // 76 + { 0x44, 0x74, 0x7C, 0x74 }, // 78 + { 0x45, 0x75, 0x7D, 0x75 }, // 7A + { 0x46, 0x76, 0x7E, 0x76 }, // 7C + { 0x47, 0x77, 0x7F, 0x77 }, // 7E +}; +*/ static uint8 regs[16]; static SFORMAT StateRegs[] = @@ -118,88 +141,65 @@ static SFORMAT StateRegs[] = static void chrSync(void) { setchr4r(0x10, 0x0000, regs[5] & 1); -// one more hack to make visible some screens in common. will be replaced with proper code later - setchr4r(0x10, 0x1000, QTAINTRAM[0] & 1); -// setchr4r(0x10, 0x1000, 1); + // 30.06.19 CaH4e3 there is much more complicated behaviour with second banking register, you may actually + // view the content of the internal character CHR rom via this window, but it is useless because hardware + // does not use this area to access the internal ROM. not sure why they did this, but I see no need to + // emulate this behaviour carefully, unless I find something that I missed... + setchr4r(0x10, 0x1000, 1); } static void Sync(void) { chrSync(); - setprg4r(0x10, 0x6000, (regs[0] & 1) | (regs[0] >> 2)); - setprg4r(0x10, 0x7000, (regs[1] & 1) | (regs[1] >> 2)); -#ifdef CAI_DEBUG - setprg8(0x8000, regs[2]); - setprg8(0xA000, regs[3]); - setprg8(0xC000, regs[4]); - setprg8(0xE000, ~0); -#else - setprg8r((regs[2] >> 6) & 1, 0x8000, (regs[2] & 0x3F)); - setprg8r((regs[3] >> 6) & 1, 0xA000, (regs[3] & 0x3F)); - setprg8r((regs[4] >> 6) & 1, 0xC000, (regs[4] & 0x3F)); - setprg8r(1, 0xE000, ~0); -#endif + setprg4r(0x10, 0x6000, (regs[0] & 1) | (regs[0] >> 2)); // two 4K banks are identical, either internal or excernal + setprg4r(0x10, 0x7000, (regs[1] & 1) | (regs[1] >> 2)); // SRAMs may be mapped in any bank independently + if (PRGsize[0] == 1024 * 1024) {// hacky hacky way to run it as iNES rom for debugging purposes + setprg8(0x8000, regs[2]); + setprg8(0xA000, regs[3]); + setprg8(0xC000, regs[4]); + setprg8(0xE000, ~0); + } else { + setprg8r((regs[2] >> 6) & 1, 0x8000, (regs[2] & 0x3F)); + setprg8r((regs[3] >> 6) & 1, 0xA000, (regs[3] & 0x3F)); + setprg8r((regs[4] >> 6) & 1, 0xC000, (regs[4] & 0x3F)); + setprg8r(1, 0xE000, ~0); // always sees the last bank of the external cart, so can't be booted without it. + } setmirror(((regs[0xA]&2)>>1)^1); } static DECLFW(QTAiWrite) { - regs[(A & 0x0F00) >> 8] = V; + regs[(A & 0x0F00) >> 8] = V; // IRQ pretty the same as in other VRC mappers by Konami switch (A) { - case 0xd600: { - IRQLatch &= 0xFF00; - IRQLatch |= V; -#ifdef CAI_DEBUG - FCEU_printf("irq latch lo=%02x\n", V); -#endif - break; - } - case 0xd700: { - IRQLatch &= 0x00FF; - IRQLatch |= V << 8; -#ifdef CAI_DEBUG - FCEU_printf("irq latch hi=%02x\n", V); -#endif - break; - } - case 0xd900: { - IRQCount = IRQLatch; - IRQa = V & 2; - K4IRQ = V & 1; - X6502_IRQEnd(FCEU_IQEXT); -#ifdef CAI_DEBUG - FCEU_printf("irq reload\n", V); -#endif - break; - } - case 0xd800: { - IRQa = K4IRQ; - X6502_IRQEnd(FCEU_IQEXT); -#ifdef CAI_DEBUG - FCEU_printf("irq stop\n", V); -#endif - break; - } - default: -#ifdef CAI_DEBUG - FCEU_printf("write %04x:%04x %d, %d\n", A, V, scanline, timestamp); -#endif + case 0xd600: IRQLatch &= 0xFF00; IRQLatch |= V; break; + case 0xd700: IRQLatch &= 0x00FF; IRQLatch |= V << 8; break; + case 0xd900: IRQCount = IRQLatch; IRQa = V & 2; K4IRQ = V & 1; X6502_IRQEnd(FCEU_IQEXT); break; + case 0xd800: IRQa = K4IRQ; X6502_IRQEnd(FCEU_IQEXT); break; + case 0xda00: qtaintramreg = regs[0xA] & 3; break; // register shadow to share it with ppu } Sync(); } -#ifdef CAI_DEBUG -static DECLFR(DebugExtNT) { - return QTAINTRAM[A & 0x07FF]; -} -#endif - static DECLFR(QTAiRead) { - // OH = conv_tbl[DD00 >> 1][DC00 >> 6] - // OL = ((DC00 & 0x3F) << 2) + DB00 - if (A == 0xDD00) - return conv_tbl[regs[0xD] >> 1][regs[0xC] >> 6]; - else if (A == 0xDC00) - return ((regs[0xC] & 0x3F) << 2) + regs[0xB]; - else + +// uint8 res1 = conv_tbl[(regs[0xD] & 0x7F) >> 1][(regs[0xC] >> 5) & 3]; +// uint8 res2 = ((regs[0xD] & 1) << 7) | ((regs[0xC] & 0x1F) << 2) | (regs[0xB] & 3); + + uint8 tabl = conv_tbl[(regs[0xC] >> 5) & 3][(regs[0xD] & 0x7F) >> 4]; + uint8 res1 = 0x40 | (tabl & 0x3F) | ((regs[0xD] >> 1) & 7); + uint8 res2 = ((regs[0xD] & 1) << 7) | ((regs[0xC] & 0x1F) << 2) | (regs[0xB] & 3); + + if (tabl & 0x40) + res1 &= 0xFB; + else if (tabl & 0x80) + res1 |= 0x04; + + if (A == 0xDD00) { + return res1; + } else if (A == 0xDC00) { +#ifdef CAI_DEBUG + FCEU_printf("%02x:%02x+%d -> %02x:%02x\n", regs[0xD], regs[0xC], regs[0xB], res1, res2); +#endif + return res2; + } else return 0; } @@ -213,38 +213,7 @@ static void VRC5IRQ(int a) { } } -// debug hack. mapper does not track ppu address himseld, instead the regular ppu offset is used -// these handlers must be moved in ppu code in order to be emulated properly. -// -static DECLFW(QTAi2006Wrap) { - if (regs[0xA] & 1) - qtaintramofs = (qtaintramofs << 8) | V; - else - old2006wrap(0x2006, V); -} - -static DECLFW(QTAi2007Wrap) { - if (regs[0xA] & 1) { - QTAINTRAM[qtaintramofs & 0x07FF] = V; - qtaintramofs++; - } else - old2007wrap(0x2007, V); -} - static void QTAiPower(void) { - - QTAIHack = 1; - qtaintramofs = 0; - - old2006wrap = GetWriteHandler(0x2006); - old2007wrap = GetWriteHandler(0x2007); - SetWriteHandler(0x2006, 0x2006, QTAi2006Wrap); - SetWriteHandler(0x2007, 0x2007, QTAi2007Wrap); - -#ifdef CAI_DEBUG - SetReadHandler(0x5000, 0x5FFF, DebugExtNT); -#endif - SetReadHandler(0x6000, 0xFFFF, CartBR); SetWriteHandler(0x6000, 0x7FFF, CartBW); SetWriteHandler(0x8000, 0xFFFF, QTAiWrite); @@ -268,6 +237,8 @@ static void StateRestore(int version) { } void QTAi_Init(CartInfo *info) { + QTAIHack = 1; + info->Power = QTAiPower; info->Close = QTAiClose; GameStateRestore = StateRestore; @@ -284,7 +255,10 @@ void QTAi_Init(CartInfo *info) { if (info->battery) { info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE - 4096; + // note, only extrnal cart's SRAM is battery backed, the the part on the main cartridge is just + // an additional work ram. so we may save only half here, but I forgot what part is saved lol, will + // find out later. + info->SaveGameLen[0] = WRAMSIZE; } AddExState(&StateRegs, ~0, 0, 0); diff --git a/src/fceu.h b/src/fceu.h index f8277f5f..a15da070 100644 --- a/src/fceu.h +++ b/src/fceu.h @@ -46,9 +46,11 @@ void FCEUI_RewindToLastAutosave(void); char *FCEUI_GetAboutString(); extern uint64 timestampbase; + +// MMC5 external shared buffers/vars +extern int MMC5Hack; extern uint32 MMC5HackVROMMask; extern uint8 *MMC5HackExNTARAMPtr; -extern int MMC5Hack, PEC586Hack, QTAIHack; extern uint8 *MMC5HackVROMPTR; extern uint8 MMC5HackCHRMode; extern uint8 MMC5HackSPMode; @@ -56,6 +58,12 @@ extern uint8 MMC50x5130; extern uint8 MMC5HackSPScroll; extern uint8 MMC5HackSPPage; +extern int PEC586Hack; + +// VRCV extarnal shared buffers/vars +extern int QTAIHack; +extern uint8 QTAINTRAM[2048]; +extern uint8 qtaintramreg; #define GAME_MEM_BLOCK_SIZE 131072 diff --git a/src/ppu.cpp b/src/ppu.cpp index 49bf1e54..1e56098c 100644 --- a/src/ppu.cpp +++ b/src/ppu.cpp @@ -330,7 +330,7 @@ int fceuindbg = 0; //0xFF shall indicate to use palette[0] uint8 gNoBGFillColor = 0xFF; -int MMC5Hack = 0, PEC586Hack = 0, QTAIHack = 0; +int MMC5Hack = 0; uint32 MMC5HackVROMMask = 0; uint8 *MMC5HackExNTARAMPtr = 0; uint8 *MMC5HackVROMPTR = 0; @@ -340,6 +340,12 @@ uint8 MMC50x5130 = 0; uint8 MMC5HackSPScroll = 0; uint8 MMC5HackSPPage = 0; +int PEC586Hack = 0; + +int QTAIHack = 0; +uint8 QTAINTRAM[2048]; +uint8 qtaintramreg; + uint8 VRAMBuffer = 0, PPUGenLatch = 0; uint8 *vnapage[4]; uint8 PPUNTARAM = 0; @@ -426,8 +432,12 @@ inline void FFCEUX_PPUWrite_Default(uint32 A, uint8 V) { if (PPUCHRRAM & (1 << (tmp >> 10))) VPage[tmp >> 10][tmp] = V; } else if (tmp < 0x3F00) { - if (PPUNTARAM & (1 << ((tmp & 0xF00) >> 10))) - vnapage[((tmp & 0xF00) >> 10)][tmp & 0x3FF] = V; + if (QTAIHack && (qtaintramreg & 1)) { + QTAINTRAM[((((tmp & 0xF00) >> 10) >> ((qtaintramreg >> 1)) & 1) << 10) | (tmp & 0x3FF)] = V; + } else { + if (PPUNTARAM & (1 << ((tmp & 0xF00) >> 10))) + vnapage[((tmp & 0xF00) >> 10)][tmp & 0x3FF] = V; + } } else { if (!(tmp & 3)) { if (!(tmp & 0xC)) { @@ -955,8 +965,12 @@ static DECLFW(B2007) { if (PPUCHRRAM & (1 << (tmp >> 10))) VPage[tmp >> 10][tmp] = V; } else if (tmp < 0x3F00) { - if (PPUNTARAM & (1 << ((tmp & 0xF00) >> 10))) - vnapage[((tmp & 0xF00) >> 10)][tmp & 0x3FF] = V; + if (QTAIHack && (qtaintramreg & 1)) { + QTAINTRAM[((((tmp & 0xF00) >> 10) >> ((qtaintramreg >> 1)) & 1) << 10) | (tmp & 0x3FF)] = V; + } else { + if (PPUNTARAM & (1 << ((tmp & 0xF00) >> 10))) + vnapage[((tmp & 0xF00) >> 10)][tmp & 0x3FF] = V; + } } else { if (!(tmp & 3)) { if (!(tmp & 0xC)) @@ -1196,6 +1210,12 @@ static void RefreshLine(int lastpixel) { #include "pputile.inc" } #undef PPU_BGFETCH + } if (QTAIHack) { + #define PPU_VRC5FETCH + for (X1 = firsttile; X1 < lasttile; X1++) { + #include "pputile.inc" + } + #undef PPU_VRC5FETCH } else { for (X1 = firsttile; X1 < lasttile; X1++) { #include "pputile.inc" @@ -1959,12 +1979,16 @@ void runppu(int x) { //todo - consider making this a 3 or 4 slot fifo to keep from touching so much memory struct BGData { struct Record { - uint8 nt, pecnt, at, pt[2]; + uint8 nt, pecnt, at, pt[2], qtnt; INLINE void Read() { NTRefreshAddr = RefreshAddr = ppur.get_ntread(); if (PEC586Hack) ppur.s = (RefreshAddr & 0x200) >> 9; + else if (QTAIHack) { + qtnt = QTAINTRAM[((((RefreshAddr >> 10) & 3) >> ((qtaintramreg >> 1)) & 1) << 10) | (RefreshAddr & 0x3FF)]; + ppur.s = qtnt & 0x3F; + } pecnt = (RefreshAddr & 1) << 3; nt = CALL_PPUREAD(RefreshAddr); runppu(kFetchTime); @@ -1990,12 +2014,16 @@ struct BGData { ppur.par = nt; RefreshAddr = ppur.get_ptread(); if (PEC586Hack) { - if (ScreenON) - RENDER_LOG(RefreshAddr | pecnt); pt[0] = CALL_PPUREAD(RefreshAddr | pecnt); runppu(kFetchTime); pt[1] = CALL_PPUREAD(RefreshAddr | pecnt); runppu(kFetchTime); + } else if (QTAIHack && (qtnt & 0x40)) { + pt[0] = *(CHRptr[0] + RefreshAddr); + runppu(kFetchTime); + RefreshAddr |= 8; + pt[1] = *(CHRptr[0] + RefreshAddr); + runppu(kFetchTime); } else { if (ScreenON) RENDER_LOG(RefreshAddr); diff --git a/src/pputile.inc b/src/pputile.inc index fc6d04a5..c4f5431f 100644 --- a/src/pputile.inc +++ b/src/pputile.inc @@ -1,6 +1,9 @@ uint8 *C; register uint8 cc; uint32 vadr; +#ifdef PPU_VRC5FETCH +uint8 tmpd; +#endif #ifndef PPUT_MMC5SP register uint8 zz; @@ -42,7 +45,11 @@ if (X1 >= 2) { #else zz = RefreshAddr & 0x1F; C = vnapage[(RefreshAddr >> 10) & 3]; - vadr = (C[RefreshAddr & 0x3ff] << 4) + vofs; // Fetch name table byte. +#ifdef PPU_VRC5FETCH + tmpd = QTAINTRAM[((((RefreshAddr >> 10) & 3) >> ((qtaintramreg >> 1)) & 1) << 10) | (RefreshAddr & 0x3FF)]; + vofs = ((tmpd & 0x3F) << 12) | ((RefreshAddr >> 12) & 7); // recalculate VROM offset +#endif + vadr = (C[RefreshAddr & 0x3ff] << 4) + vofs; // Fetch name table byte. #endif #ifdef PPUT_HOOK @@ -78,7 +85,16 @@ pshift[1] <<= 8; #elif defined(PPUT_MMC5) C = MMC5BGVRAMADR(vadr); #else + + #ifdef PPU_VRC5FETCH + if(tmpd & 0x40) + C = CHRptr[0] + vadr; + else C = VRAMADR(vadr); + #else + C = VRAMADR(vadr); +#endif + #endif #endif