diff --git a/source/fceultra/boards/158B.cpp b/source/fceultra/boards/158B.cpp new file mode 100644 index 0000000..765c8fc --- /dev/null +++ b/source/fceultra/boards/158B.cpp @@ -0,0 +1,71 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2015 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 + * + * "Blood Of Jurassic" protected MMC3 based board (GD-98 Cart ID, 158B PCB ID) + * + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 lut[8] = { 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0F, 0x00 }; + +static void UNL158BPW(uint32 A, uint8 V) { + if (EXPREGS[0] & 0x80) { + uint32 bank = EXPREGS[0] & 7; + if(EXPREGS[0] & 0x20) { // 32Kb mode + setprg32(0x8000, bank >> 1); + } else { // 16Kb mode + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } + } else { + setprg8(A, V & 0xF); + } +} + +static DECLFW(UNL158BProtWrite) { + EXPREGS[A & 7] = V; + switch(A & 7) { + case 0: + FixMMC3PRG(MMC3_cmd); + break; + case 7: + FCEU_printf("UNK PROT WRITE\n"); + break; + } + +} + +static DECLFR(UNL158BProtRead) { + return X.DB | lut[A & 7]; +} + +static void UNL158BPower(void) { + GenMMC3Power(); + SetWriteHandler(0x5000, 0x5FFF, UNL158BProtWrite); + SetReadHandler(0x5000, 0x5FFF, UNL158BProtRead); +} + +void UNL158B_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 128, 0, 0); + pwrap = UNL158BPW; + info->Power = UNL158BPower; + AddExState(EXPREGS, 8, 0, "EXPR"); +} diff --git a/source/fceultra/boards/190.cpp b/source/fceultra/boards/190.cpp new file mode 100644 index 0000000..85b4730 --- /dev/null +++ b/source/fceultra/boards/190.cpp @@ -0,0 +1,85 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright (C) 2017 FCEUX Team + * + * 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 + * + * Magic Kid GooGoo + */ + +#include "mapinc.h" + +static uint8 prgr, chrr[4]; +static uint8 *WRAM = NULL; + +static void Mapper190_Sync(void) { + setprg8r(0x10, 0x6000, 0); + + setprg16(0x8000, prgr); + setprg16(0xC000, 0); + setchr2(0x0000, chrr[0]); + setchr2(0x0800, chrr[1]); + setchr2(0x1000, chrr[2]); + setchr2(0x1800, chrr[3]); +} + +static DECLFW(Mapper190_Write89) { prgr = V&7; Mapper190_Sync(); } +static DECLFW(Mapper190_WriteCD) { prgr = 8|(V&7); Mapper190_Sync(); } + +static DECLFW(Mapper190_WriteAB) { + int bank = A&3; + chrr[bank] = V&63; + Mapper190_Sync(); +} + + +static void Mapper190_Power(void) { + FCEU_CheatAddRAM(0x2000 >> 10, 0x6000, WRAM); + + SetReadHandler(0x6000, 0xFFFF, CartBR); + + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0x9FFF, Mapper190_Write89); + SetWriteHandler(0xA000, 0xBFFF, Mapper190_WriteAB); + SetWriteHandler(0xC000, 0xDFFF, Mapper190_WriteCD); + Mapper190_Sync(); + + setmirror(MI_V); +} + +static void Mapper190_Close(void) { + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void Mapper190_Restore(int) { + Mapper190_Sync(); +} + + +void Mapper190_Init(CartInfo *info) { + info->Power = Mapper190_Power; + info->Close = Mapper190_Close; + GameStateRestore = Mapper190_Restore; + + WRAM = (uint8*)FCEU_gmalloc(0x2000); + SetupCartPRGMapping(0x10, WRAM, 0x2000, 1); + + chrr[0] = chrr[1] = chrr[2] = chrr[3] = prgr = 0; + + AddExState(&prgr, 1, 0, "PRGR"); + AddExState(chrr, 4, 0, "CHRR"); + AddExState(WRAM, 0x2000, 0, "WRAM"); +} diff --git a/source/fceultra/boards/80013-B.cpp b/source/fceultra/boards/80013-B.cpp new file mode 100644 index 0000000..1f376ea --- /dev/null +++ b/source/fceultra/boards/80013-B.cpp @@ -0,0 +1,76 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2017 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 uint8 bios_prg, rom_prg, rom_mode, mirror; + +static SFORMAT StateRegs[] = +{ + { &bios_prg, 1, "BREG" }, + { &rom_prg, 1, "RREG" }, + { &rom_mode, 1, "RMODE" }, + { 0 } +}; + +static void Sync(void) { + setchr8(0); + if(rom_mode&2) { + setprg16r(0,0x8000,(bios_prg&0xF)|(rom_prg&0x70)); + } else { + setprg16r(1,0x8000,bios_prg&3); + } + setprg16r(0,0xC000,rom_prg&0x7F); + setmirror(((bios_prg>>4)&1)^1); +} + +static DECLFW(BMC80013BWrite) { + uint8 reg = (A>>13)&3; + if(reg == 0) { + bios_prg = V; + } else { + rom_prg = V; + rom_mode = reg; + } + Sync(); +} + +static void BMC80013BPower(void) { + bios_prg=rom_prg=rom_mode=mirror=0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, BMC80013BWrite); +} + +static void BMC80013BReset(void) { + bios_prg=rom_prg=rom_mode=mirror=0; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void BMC80013B_Init(CartInfo *info) { + info->Reset = BMC80013BReset; + info->Power = BMC80013BPower; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/source/fceultra/boards/8in1.cpp b/source/fceultra/boards/8in1.cpp new file mode 100644 index 0000000..3e2f964 --- /dev/null +++ b/source/fceultra/boards/8in1.cpp @@ -0,0 +1,67 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2016 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 + * + * 8-in-1 Rockin' Kats, Snake, (PCB marked as "8 in 1"), similar to 12IN1, + * but with MMC3 on board, all games are hacked the same, Snake is buggy too! + * + * no reset-citcuit, so selected game can be reset, but to change it you must use power + * + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void BMC8IN1CW(uint32 A, uint8 V) { + setchr1(A, ((EXPREGS[0] & 0xC) << 5) | (V & 0x7F)); +} + +static void BMC8IN1PW(uint32 A, uint8 V) { + if(EXPREGS[0] & 0x10) { // MMC3 mode + setprg8(A, ((EXPREGS[0] & 0xC) << 2) | (V & 0xF)); + } else { + setprg32(0x8000, EXPREGS[0] & 0xF); + } +} + +static DECLFW(BMC8IN1Write) { + if(A & 0x1000) { + EXPREGS[0] = V; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } else { + if(A < 0xC000) + MMC3_CMDWrite(A, V); + else + MMC3_IRQWrite(A, V); + } +} + +static void BMC8IN1Power(void) { + EXPREGS[0] = 0; + GenMMC3Power(); + SetWriteHandler(0x8000, 0xFFFF, BMC8IN1Write); +} + +void BMC8IN1_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 128, 0, 0); + cwrap = BMC8IN1CW; + pwrap = BMC8IN1PW; + info->Power = BMC8IN1Power; + AddExState(EXPREGS, 1, 0, "EXPR"); +} diff --git a/source/fceultra/boards/BMW8544.cpp b/source/fceultra/boards/BMW8544.cpp new file mode 100644 index 0000000..5c1f613 --- /dev/null +++ b/source/fceultra/boards/BMW8544.cpp @@ -0,0 +1,79 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2015 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 + * + * "Dragon Fighter" protected MMC3 based custom mapper board + * mostly hacky implementation, I can't verify if this mapper can read a RAM of the + * console or watches the bus writes somehow. + * + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void UNLBMW8544PW(uint32 A, uint8 V) { + if(A == 0x8000) + setprg8(A,EXPREGS[0] & 0x1F); // the real hardware has this bank overrided with it's own register, + else // but MMC3 prg swap still works and you can actually change bank C000 at the same time if use 0x46 cmd + setprg8(A,V); +} + +static void UNLBMW8544CW(uint32 A, uint8 V) { + if(A == 0x0000) + setchr2(0x0000,(V >> 1) ^ EXPREGS[1]); + else if (A == 0x0800) + setchr2(0x0800,(V >> 1) | ((EXPREGS[2] & 0x40) << 1)); + else if (A == 0x1000) + setchr4(0x1000, EXPREGS[2] & 0x3F); + +} + +static DECLFW(UNLBMW8544ProtWrite) { + if(!(A & 1)) { + EXPREGS[0] = V; + FixMMC3PRG(MMC3_cmd); + } +} + +static DECLFR(UNLBMW8544ProtRead) { + if(!fceuindbg) { + if(!(A & 1)) { + if((EXPREGS[0] & 0xE0) == 0xC0) { + EXPREGS[1] = ARead[0x6a](0x6a); // program can latch some data from the BUS, but I can't say how exactly, + } else { // without more euipment and skills ;) probably here we can try to get any write + EXPREGS[2] = ARead[0xff](0xff); // before the read operation + } + FixMMC3CHR(MMC3_cmd & 0x7F); // there are more different behaviour of the board isn't used by game itself, so unimplemented here and + } // actually will break the current logic ;) + } + return 0; +} + +static void UNLBMW8544Power(void) { + GenMMC3Power(); + SetWriteHandler(0x6000, 0x6FFF, UNLBMW8544ProtWrite); + SetReadHandler(0x6000, 0x6FFF, UNLBMW8544ProtRead); +} + +void UNLBMW8544_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 256, 0, 0); + pwrap = UNLBMW8544PW; + cwrap = UNLBMW8544CW; + info->Power = UNLBMW8544Power; + AddExState(EXPREGS, 3, 0, "EXPR"); +} diff --git a/source/fceultra/boards/F-15.cpp b/source/fceultra/boards/F-15.cpp new file mode 100644 index 0000000..7e18c7b --- /dev/null +++ b/source/fceultra/boards/F-15.cpp @@ -0,0 +1,62 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2015 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 + * + * BMC F-15 PCB (256+266 MMC3 based, with 16/32Kb banking discrete logic) + * 150-in-1 Unchaied Melody FIGHT version with system test (START+SELECT) + * + * CHR - MMC3 stock regs + * PRG - MMC3 regs disabled, area 6000-7FFF used instead + * 011xxxxxxxxxxxxx addr mask, + * ----APPp reg bits mask + * A - higher 128K PRG bank select/32K bank mode override + * PP - bank number in 32K mode + * PPp - bank number in 16K mode + * initial state of extra regs is undefined, A001 enables/disables the 6000 area + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void BMCF15PW(uint32 A, uint8 V) { + uint32 bank = EXPREGS[0] & 0xF; + uint32 mode = (EXPREGS[0] & 8) >> 3; + uint32 mask = ~(mode); + setprg16(0x8000, (bank & mask)); + setprg16(0xC000, (bank & mask) | mode); +} + +static DECLFW(BMCF15Write) { + if (A001B & 0x80) { + EXPREGS[0] = V & 0xF; + FixMMC3PRG(MMC3_cmd); + } +} + +static void BMCF15Power(void) { + GenMMC3Power(); + SetWriteHandler(0x6000, 0x7FFF, BMCF15Write); + SetWriteHandler(0x6000, 0x7FFF, BMCF15Write); +} + +void BMCF15_Init(CartInfo *info) { + GenMMC3_Init(info, 256, 256, 0, 0); + pwrap = BMCF15PW; + info->Power = BMCF15Power; + AddExState(EXPREGS, 1, 0, "EXPR"); +} diff --git a/source/fceultra/boards/cheapocabra.cpp b/source/fceultra/boards/cheapocabra.cpp new file mode 100644 index 0000000..c018fd0 --- /dev/null +++ b/source/fceultra/boards/cheapocabra.cpp @@ -0,0 +1,270 @@ +/* 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 + */ + +// mapper 111 - Cheapocabra board by Memblers +// http://forums.nesdev.com/viewtopic.php?p=146039 +// +// 512k PRG-ROM in 32k pages (flashable if battery backed is specified) +// 32k CHR-ROM used as: +// 2 x 8k pattern pages +// 2 x 8k nametable pages +// +// Notes: +// - CHR-RAM for nametables maps to $3000-3FFF as well, but FCEUX internally mirrors to 4k? + +#include "mapinc.h" +#include "../ines.h" + +static uint8 reg; +static uint8 *CHRRAM = NULL; +const uint32 CHRRAMSIZE = 1024 * 32; + +static bool flash = false; +static uint8 flash_mode; +static uint8 flash_sequence; +static uint8 flash_id; +static uint8 *FLASHROM = NULL; +const uint32 FLASHROMSIZE = 1024 * 512; + + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REG" }, + { 0 } +}; + +static SFORMAT FlashRegs[] = +{ + { &flash_mode, 1, "FMOD" }, + { &flash_sequence, 1, "FSEQ" }, + { &flash_id, 1, "FMID" }, + { 0 } +}; + +static void Sync(void) { + // bit 7 controls green LED + // bit 6 controls red LED + int nt = (reg & 0x20) ? 8192 : 0; // bit 5 controls 8k nametable page + int chr = (reg & 0x10) ? 1 : 0; // bit 4 selects 8k CHR page + int prg = (reg & 0x0F); // bits 0-3 select 32k PRG page + + nt += (16 * 1024); + for (int n=0; n<4; ++n) + { + setntamem(CHRRAM + nt + (1024 * n),1,n); + } + setchr8r(0x10, chr); + + uint32 prg_chip = flash ? 0x10 : 0; + setprg32r(prg_chip,0x8000,prg); +} + +static DECLFW(M111Write) { + if ((A >= 0x5000 && A <= 0x5FFF) || (A >= 0x7000 && A <= 0x7FFF)) + { + reg = V; + Sync(); + } +} + +static DECLFR(M111FlashID) +{ + // Software ID mode is undefined by the datasheet for all but the lowest 2 addressable bytes, + // but some tests of the chip currently being used found it repeats in 512-byte patterns. + // http://forums.nesdev.com/viewtopic.php?p=178728#p178728 + + uint32 aid = A & 0x1FF; + switch (aid) + { + case 0: return 0xBF; + case 1: return 0xB7; + default: return 0xFF; + } +} + +void M111FlashIDEnter() +{ + if (flash_id) return; + flash_id = 1; + SetReadHandler(0x8000,0xFFFF,M111FlashID); +} + +void M111FlashIDExit() +{ + if (!flash_id) return; + flash_id = 0; + SetReadHandler(0x8000,0xFFFF,CartBR); +} + +static DECLFW(M111Flash) { + if (A < 0x8000 || A > 0xFFFF) return; + + uint32 flash_addr = ((reg & 0x0F) << 15) | (A & 0x7FFF); + uint32 command_addr = flash_addr & 0x7FFF; + + enum + { + FLASH_MODE_READY = 0, + FLASH_MODE_COMMAND, + FLASH_MODE_BYTE_WRITE, + FLASH_MODE_ERASE, + }; + + switch (flash_mode) + { + default: + case FLASH_MODE_READY: + if (command_addr == 0x5555 && V == 0xAA) + { + flash_mode = FLASH_MODE_COMMAND; + flash_sequence = 0; + } + else if (V == 0xF0) + { + M111FlashIDExit(); + } + break; + case FLASH_MODE_COMMAND: + if (flash_sequence == 0) + { + if (command_addr == 0x2AAA && V == 0x55) + flash_sequence = 1; + else + flash_mode = FLASH_MODE_READY; + } + else if (flash_sequence == 1) + { + if (command_addr == 0x5555) + { + flash_sequence = 0; + switch (V) + { + default: flash_mode = FLASH_MODE_READY; break; + case 0xA0: flash_mode = FLASH_MODE_BYTE_WRITE; break; + case 0x80: flash_mode = FLASH_MODE_ERASE; break; + case 0x90: M111FlashIDEnter(); flash_mode = FLASH_MODE_READY; break; + case 0xF0: M111FlashIDExit(); flash_mode = FLASH_MODE_READY; break; + } + } + else + flash_mode = FLASH_MODE_READY; + } + else + flash_mode = FLASH_MODE_READY; // should be unreachable + break; + case FLASH_MODE_BYTE_WRITE: + FLASHROM[flash_addr] &= V; + flash_mode = FLASH_MODE_READY; + break; + case FLASH_MODE_ERASE: + if (flash_sequence == 0) + { + if (command_addr == 0x5555 && V == 0xAA) + flash_sequence = 1; + else + flash_mode = FLASH_MODE_READY; + } + else if (flash_sequence == 1) + { + if (command_addr == 0x2AAA && V == 0x55) + flash_sequence = 2; + else + flash_mode = FLASH_MODE_READY; + } + else if (flash_sequence == 2) + { + if (command_addr == 0x5555 && V == 0x10) // erase chip + { + memset(FLASHROM, 0xFF, FLASHROMSIZE); + } + else if (V == 0x30) // erase 4k sector + { + uint32 sector = flash_addr & 0x7F000; + memset(FLASHROM + sector, 0xFF, 1024 * 4); + } + flash_mode = FLASH_MODE_READY; + } + else + flash_mode = FLASH_MODE_READY; // should be unreachable + break; + } +} + +static void M111Power(void) { + reg = 0xFF; + Sync(); + SetReadHandler(0x8000, 0xffff, CartBR); + SetWriteHandler(0x5000, 0x5fff, M111Write); + SetWriteHandler(0x7000, 0x7fff, M111Write); + + if (flash) + { + flash_mode = 0; + flash_sequence = 0; + flash_id = false; + SetWriteHandler(0x8000, 0xFFFF, M111Flash); + } +} + +static void M111Close(void) { + if (CHRRAM) + FCEU_gfree(CHRRAM); + CHRRAM = NULL; + + if (FLASHROM) + FCEU_gfree(FLASHROM); + FLASHROM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper111_Init(CartInfo *info) { + info->Power = M111Power; + info->Close = M111Close; + + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); + + flash = (info->battery != 0); + if (flash) + { + FLASHROM = (uint8*)FCEU_gmalloc(FLASHROMSIZE); + info->SaveGame[0] = FLASHROM; + info->SaveGameLen[0] = FLASHROMSIZE; + AddExState(FLASHROM, FLASHROMSIZE, 0, "FROM"); + AddExState(&FlashRegs, ~0, 0, 0); + + // copy PRG ROM into FLASHROM, use it instead of PRG ROM + const uint32 PRGSIZE = ROM_size * 16 * 1024; + for (uint32 w=0, r=0; w= PRGSIZE) r = 0; + } + SetupCartPRGMapping(0x10, FLASHROM, FLASHROMSIZE, 0); + } +} diff --git a/source/fceultra/boards/eh8813a.cpp b/source/fceultra/boards/eh8813a.cpp new file mode 100644 index 0000000..34f7ce6 --- /dev/null +++ b/source/fceultra/boards/eh8813a.cpp @@ -0,0 +1,83 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2015 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 addrlatch; +static uint8 datalatch, hw_mode; + +static SFORMAT StateRegs[] = +{ + { &addrlatch, 2, "ADRL" }, + { &datalatch, 1, "DATL" }, + { &hw_mode, 1, "HWMO" }, + { 0 } +}; + +static void Sync(void) { + uint8 prg = (addrlatch & 7); + setchr8(datalatch); + if(addrlatch & 0x80) { + setprg16(0x8000,prg); + setprg16(0xC000,prg); + } else { + setprg32(0x8000,prg >> 1); + } + setmirror(MI_V); +} + +static DECLFW(EH8813AWrite) { + if((addrlatch & 0x100) == 0) { + addrlatch = A & 0x1FF; + datalatch = V & 0xF; + } + Sync(); +} + +static DECLFR(EH8813ARead) { + if (addrlatch & 0x40) + A= (A & 0xFFF0) + hw_mode; + return CartBR(A); +} + +static void EH8813APower(void) { + addrlatch = datalatch = hw_mode = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, EH8813ARead); + SetWriteHandler(0x8000, 0xFFFF, EH8813AWrite); +} + +static void EH8813AReset(void) { + addrlatch = datalatch = 0; + hw_mode = (hw_mode + 1) & 0xF; + FCEU_printf("Hardware Switch is %01X\n", hw_mode); + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLEH8813A_Init(CartInfo *info) { + info->Reset = EH8813AReset; + info->Power = EH8813APower; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/source/fceultra/boards/et-100.cpp b/source/fceultra/boards/et-100.cpp new file mode 100644 index 0000000..b3539ce --- /dev/null +++ b/source/fceultra/boards/et-100.cpp @@ -0,0 +1,103 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2015 Cluster + * http://clusterrr.com + * clusterrr@clusterrr.com + * + * 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 + */ + +/* + MMC3-based multicart mapper with CHR RAM, CHR ROM and PRG RAM + + $6000-7FFF: A~[011xxxxx xxMRSBBB] Multicart reg + This register can only be written to if PRG-RAM is enabled and writable (see $A001) + and BBB = 000 (power on state) + + BBB = CHR+PRG block select bits (A19, A18, A17 for both PRG and CHR) + S = PRG block size (0=256k 1=128k) + R = CHR mode (0=CHR ROM 1=CHR RAM) + M = CHR block size (0=256k 1=128k) + ignored when S is 0 for some reason + + Example Game: + -------------------------- + 6 in 1 multicart (SMB3, TMNT2, Contra, Ninja Cat, Ninja Crusaders, Rainbow Islands 2) +*/ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 *CHRRAM; +static uint32 CHRRAMSize; + +static void BMC1024CA1PW(uint32 A, uint8 V) { + if ((EXPREGS[0]>>3)&1) + setprg8(A, (V&0x1F) | ((EXPREGS[0] & 7) << 4)); + else + setprg8(A, (V&0x0F) | ((EXPREGS[0] & 7) << 4)); +} + +static void BMC1024CA1CW(uint32 A, uint8 V) { + if ((EXPREGS[0]>>4)&1) + setchr1r(0x10, A, V); + else if (((EXPREGS[0]>>5)&1) && ((EXPREGS[0]>>3)&1)) + setchr1(A, V | ((EXPREGS[0] & 7) << 7)); + else + setchr1(A, (V&0x7F) | ((EXPREGS[0] & 7) << 7)); +} + +static DECLFW(BMC1024CA1Write) { + if (((A001B & 0xC0) == 0x80) && !(EXPREGS[0] & 7)) + { + EXPREGS[0] = A & 0x3F; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } else { + CartBW(A, V); + } +} + +static void BMC1024CA1Reset(void) { + EXPREGS[0] = 0; + MMC3RegReset(); +} + +static void BMC1024CA1Power(void) { + EXPREGS[0] = 0; + GenMMC3Power(); + SetWriteHandler(0x6000, 0x7FFF, BMC1024CA1Write); +} + +static void BMC1024CA1Close(void) { + if (CHRRAM) + FCEU_gfree(CHRRAM); + CHRRAM = NULL; +} + +void BMC1024CA1_Init(CartInfo *info) { + GenMMC3_Init(info, 256, 256, 8, 0); + CHRRAMSize = 8192; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1); + AddExState(CHRRAM, CHRRAMSize, 0, "CHRR"); + pwrap = BMC1024CA1PW; + cwrap = BMC1024CA1CW; + info->Power = BMC1024CA1Power; + info->Reset = BMC1024CA1Reset; + info->Close = BMC1024CA1Close; + AddExState(EXPREGS, 1, 0, "EXPR"); +} diff --git a/source/fceultra/boards/et-4320.cpp b/source/fceultra/boards/et-4320.cpp new file mode 100644 index 0000000..1904226 --- /dev/null +++ b/source/fceultra/boards/et-4320.cpp @@ -0,0 +1,119 @@ +/* FCE Ultra - NES/Famicom Emulator +* +* Copyright notice for this file: +* Copyright (C) 2016 Cluster +* http://clusterrr.com +* clusterrr@clusterrr.com +* +* 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 +*/ + +/* +MMC3-based multicart mapper with CHR RAM, CHR ROM and PRG RAM + +$6000-7FFF: A~[011xxxxx xxMRSBBB] Multicart reg +This register can only be written to if PRG-RAM is enabled and writable (see $A001) +and BBB = 000 (power on state) + +BBB = CHR+PRG block select bits (A19, A18, A17 for both PRG and CHR) +S = PRG block size & mirroring mode (0=128k with normal MMC3, 1=256k with TxSROM-like single-screen mirroring) +R = CHR mode (0=CHR ROM 1=CHR RAM) +M = CHR block size (0=256k 1=128k) +ignored when S is 0 for some reason + +Example Game: +-------------------------- +7 in 1 multicart (Amarello, TMNT2, Contra, Ninja Cat, Ninja Crusaders, Rainbow Islands 2) +*/ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 *CHRRAM; +static uint32 CHRRAMSize; +static uint8 PPUCHRBus; +static uint8 TKSMIR[8]; + +static void BMC810131C_PW(uint32 A, uint8 V) { + if ((EXPREGS[0] >> 3) & 1) + setprg8(A, (V & 0x1F) | ((EXPREGS[0] & 7) << 4)); + else + setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 7) << 4)); +} + +static void BMC810131C_CW(uint32 A, uint8 V) { + if ((EXPREGS[0] >> 4) & 1) + setchr1r(0x10, A, V); + else if (((EXPREGS[0] >> 5) & 1) && ((EXPREGS[0] >> 3) & 1)) + setchr1(A, V | ((EXPREGS[0] & 7) << 7)); + else + setchr1(A, (V & 0x7F) | ((EXPREGS[0] & 7) << 7)); + + TKSMIR[A >> 10] = V >> 7; + if (((EXPREGS[0] >> 3) & 1) && (PPUCHRBus == (A >> 10))) + setmirror(MI_0 + (V >> 7)); +} + +static DECLFW(BMC810131C_Write) { + if (((A001B & 0xC0) == 0x80) && !(EXPREGS[0] & 7)) + { + EXPREGS[0] = A & 0x3F; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } + else { + CartBW(A, V); + } +} + +static void BMC810131C_Reset(void) { + EXPREGS[0] = 0; + MMC3RegReset(); +} + +static void BMC810131C_Power(void) { + EXPREGS[0] = 0; + GenMMC3Power(); + SetWriteHandler(0x6000, 0x7FFF, BMC810131C_Write); +} + +static void BMC810131C_Close(void) { + if (CHRRAM) + FCEU_gfree(CHRRAM); + CHRRAM = NULL; +} + +static void TKSPPU(uint32 A) { + A &= 0x1FFF; + A >>= 10; + PPUCHRBus = A; + if ((EXPREGS[0] >> 3) & 1) + setmirror(MI_0 + TKSMIR[A]); +} + +void BMC810131C_Init(CartInfo *info) { + GenMMC3_Init(info, 256, 256, 8, 0); + CHRRAMSize = 8192; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1); + AddExState(CHRRAM, CHRRAMSize, 0, "CHRR"); + pwrap = BMC810131C_PW; + cwrap = BMC810131C_CW; + PPU_hook = TKSPPU; + info->Power = BMC810131C_Power; + info->Reset = BMC810131C_Reset; + info->Close = BMC810131C_Close; + AddExState(EXPREGS, 1, 0, "EXPR"); +} diff --git a/source/fceultra/boards/hp10xx_hp20xx.cpp b/source/fceultra/boards/hp10xx_hp20xx.cpp new file mode 100644 index 0000000..76276e9 --- /dev/null +++ b/source/fceultra/boards/hp10xx_hp20xx.cpp @@ -0,0 +1,177 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2017 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 + * + * HP10xx/HP20xx - a simplified version of FK23C mapper with pretty strict and better + * organized banking behaviour. It seems that some 176 mapper assigned game may be + * actually this kind of board instead but in common they aren't compatible at all, + * the games on the regular FK23C boards couldn't run on this mapper and vice versa... + * + */ + +#include "mapinc.h" +#include "mmc3.h" +#include "../ines.h" + +static uint8 unromchr, lock; +static uint32 dipswitch; + +static void BMCHPxxCW(uint32 A, uint8 V) +{ + if(EXPREGS[0]&4) { // custom banking + switch(EXPREGS[0]&3) { + case 0: + case 1: + setchr8(EXPREGS[2]&0x3F); +// FCEU_printf("\tCHR8 %02X\n",EXPREGS[2]&0x3F); + break; + case 2: + setchr8((EXPREGS[2]&0x3E)|(unromchr&1)); +// FCEU_printf("\tCHR8 %02X\n",(EXPREGS[2]&0x3E)|(unromchr&1)); + break; + case 3: + setchr8((EXPREGS[2]&0x3C)|(unromchr&3)); +// FCEU_printf("\tCHR8 %02X\n",(EXPREGS[2]&0x3C)|(unromchr&3)); + break; + } + } else { // mmc3 banking + int base, mask; + if(EXPREGS[0]&1) { // 128K mode + base=EXPREGS[2]&0x30; + mask=0x7F; + } else { // 256K mode + base=EXPREGS[2]&0x20; + mask=0xFF; + } +// FCEU_printf("\tCHR1 %04x:%02X\n",A,(V&mask)|(base<<3)); + setchr1(A,(V&mask)|(base<<3)); + } +} + +//PRG wrapper +static void BMCHPxxPW(uint32 A, uint8 V) +{ + if(EXPREGS[0]&4) { // custom banking + if((EXPREGS[0]&0xF)==4) { // 16K mode +// FCEU_printf("\tPRG16 %02X\n",EXPREGS[1]&0x1F); + setprg16(0x8000,EXPREGS[1]&0x1F); + setprg16(0xC000,EXPREGS[1]&0x1F); + } else { // 32K modes +// FCEU_printf("\tPRG32 %02X\n",(EXPREGS[1]&0x1F)>>1); + setprg32(0x8000,(EXPREGS[1]&0x1F)>>1); + } + } else { // mmc3 banking + int base, mask; + if(EXPREGS[0]&2) { // 128K mode + base=EXPREGS[1]&0x18; + mask=0x0F; + } else { // 256K mode + base=EXPREGS[1]&0x10; + mask=0x1F; + } +// FCEU_printf("\tPRG8 %02X\n",(V&mask)|(base<<1)); + setprg8(A,(V&mask)|(base<<1)); + setprg8r(0x10,0x6000,A001B&3); + } +} + +//MIRROR wrapper +static void BMCHPxxMW(uint8 V) { + if(EXPREGS[0]&4) { // custom banking +// FCEU_printf("CUSTOM MIRR: %d\n",(unromchr>>2)&1); + setmirror(((unromchr>>2)&1)^1); + } else { // mmc3 banking +// FCEU_printf("MMC3 MIRR: %d\n",(V&1)^1); + A000B = V; + setmirror((A000B & 1) ^ 1); + } +} + +//PRG handler ($8000-$FFFF) +static DECLFW(BMCHPxxHiWrite) +{ +// FCEU_printf("HI WRITE %04X:%02X\n",A,V); + if(EXPREGS[0]&4) { // custom banking +// FCEU_printf("CUSTOM\n"); + unromchr=V; + FixMMC3CHR(MMC3_cmd); + } else { // mmc3 banking +// FCEU_printf("MMC3\n"); + if(A<0xC000) { + MMC3_CMDWrite(A,V); + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } else { + MMC3_IRQWrite(A,V); + } + } +} + +//EXP handler ($5000-$5FFF) +static DECLFW(BMCHPxxWrite) +{ + if(!lock) { +// FCEU_printf("LO WRITE %04X:%02X\n",A,V); + EXPREGS[A&3]=V; + lock=V&0x80; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } +} + +static DECLFR(BMCHPxxRead) { + return dipswitch; +} + +static void BMCHPxxReset(void) +{ + dipswitch++; + dipswitch&=0xF; + lock=0; +// FCEU_printf("BMCHPxx dipswitch set to %d\n",dipswitch); + EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0; + MMC3RegReset(); + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void BMCHPxxPower(void) +{ + GenMMC3Power(); + dipswitch=lock=0; + EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + SetReadHandler(0x5000,0x5fff,BMCHPxxRead); + SetWriteHandler(0x5000,0x5fff,BMCHPxxWrite); + SetWriteHandler(0x8000,0xffff,BMCHPxxHiWrite); +} + +void BMCHPxx_Init(CartInfo *info) +{ + GenMMC3_Init(info, 256, 256, 8, 0); + cwrap=BMCHPxxCW; + pwrap=BMCHPxxPW; + mwrap=BMCHPxxMW; + info->Power=BMCHPxxPower; + info->Reset=BMCHPxxReset; + AddExState(EXPREGS, 8, 0, "EXPR"); + AddExState(&unromchr, 1, 0, "UCHR"); + AddExState(&dipswitch, 1, 0, "DPSW"); + AddExState(&lock, 1, 0, "LOCK"); +} diff --git a/source/fceultra/boards/hp898f.cpp b/source/fceultra/boards/hp898f.cpp new file mode 100644 index 0000000..b0471bb --- /dev/null +++ b/source/fceultra/boards/hp898f.cpp @@ -0,0 +1,69 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2015 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 uint8 regs[2]; + +static SFORMAT StateRegs[] = +{ + { regs, 2, "REGS" }, + { 0 } +}; + +static void Sync(void) { + uint8 chr = (regs[0] >> 4) & 7; + uint8 prg = (regs[1] >> 3) & 7; + uint8 dec = (regs[1] >> 4) & 4; + setchr8(chr & (~(((regs[0] & 1) << 2) | (regs[0] & 2)))); + setprg16(0x8000,prg & (~dec)); + setprg16(0xC000,prg | dec); + setmirror(regs[1] >> 7); +} + +static DECLFW(HP898FWrite) { + if((A & 0x6000) == 0x6000) { + regs[(A & 4) >> 2] = V; + Sync(); + } +} + +static void HP898FPower(void) { + regs[0] = regs[1] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0xFFFF, HP898FWrite); +} + +static void HP898FReset(void) { + regs[0] = regs[1] = 0; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void BMCHP898F_Init(CartInfo *info) { + info->Reset = HP898FReset; + info->Power = HP898FPower; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/source/fceultra/boards/ks7016.cpp b/source/fceultra/boards/ks7016.cpp new file mode 100644 index 0000000..3e85620 --- /dev/null +++ b/source/fceultra/boards/ks7016.cpp @@ -0,0 +1,85 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2016 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 + * + * FDS Conversion (Exciting Basket), weird banking addressing, seems because + * of used addressing scheme, made to disable the lower system banks from 6000 + * but the kaiser mapper chip and PCB are the same as usual + * probably need a hard eprom dump to verify actual banks layout + * + */ + +#include "mapinc.h" + +static uint8 preg; + +static SFORMAT StateRegs[] = +{ + { &preg, 1, "PREG" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x6000, preg); + setprg8(0x8000, 0xC); + setprg8(0xA000, 0xD); + setprg8(0xC000, 0xE); + setprg8(0xE000, 0xF); + setchr8(0); +} + +static DECLFW(UNLKS7016Write) { + u16 mask = (A & 0x30); + switch(A & 0xD943) { + case 0xD943: { + if(mask == 0x30) { + preg = 8 | 3; // or A, or no bus (all FF) + } else { + preg = (A >> 2) & 0xF; // can be anything but C-F + } + Sync(); + break; + } + case 0xD903: { // this case isn't usedby the game, but addressing does this as a side effect + if(mask == 0x30) { + preg = 8 | ((A >> 2) & 3); // also masked C-F from output + } else { + preg = 8 | 3; + } + Sync(); + break; + } + } +} + +static void UNLKS7016Power(void) { + preg = 8; + Sync(); + SetReadHandler(0x6000, 0xffff, CartBR); + SetWriteHandler(0x8000, 0xffff, UNLKS7016Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLKS7016_Init(CartInfo *info) { + info->Power = UNLKS7016Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/source/fceultra/boards/rt-01.cpp b/source/fceultra/boards/rt-01.cpp new file mode 100644 index 0000000..b636379 --- /dev/null +++ b/source/fceultra/boards/rt-01.cpp @@ -0,0 +1,55 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2016 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 + * + * Test Ver. 1.01 Dlya Proverki TV Pristavok (RT-01, by SS aka Snake) + * A simple board with 16K PRG ROM + 2K CHR ROM with no mapper, hardwired mirroring + * PRG EPROM has copy protected areas with "weak bits", which is tested at some + * points of the program. Trying to simalate "weak bits" behaviour + * + */ + +#include "mapinc.h" + +extern u64 xoroshiro128plus_next(); // deterministic random + +static DECLFR(UNLRT01Read) { +// u16 i, prot_areas[2][2] = { +// { 0x8E80, 0x8EFF }, +// { 0xFE80, 0xFEFF }, +// }; + if(((A >= 0xCE80) && (A < 0xCF00)) || + ((A >= 0xFE80) && (A < 0xFF00))) { + return 0xF2 | (xoroshiro128plus_next() & 0x0D); + } else + return CartBR(A); +} + +static void UNLRT01Power(void) { + setprg16(0x8000, 0); + setprg16(0xC000, 0); + setchr2(0x0000,0); + setchr2(0x0800,0); + setchr2(0x1000,0); + setchr2(0x1800,0); + SetReadHandler(0x8000, 0xFFFF, UNLRT01Read); +} + +void UNLRT01_Init(CartInfo *info) { + info->Power = UNLRT01Power; +} diff --git a/source/fceultra/input/snesmouse.cpp b/source/fceultra/input/snesmouse.cpp new file mode 100644 index 0000000..782a45a --- /dev/null +++ b/source/fceultra/input/snesmouse.cpp @@ -0,0 +1,115 @@ +/* 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 +#include +#include "share.h" + +typedef struct { + bool strobe; + uint32 latch; // latched data (read when strobe goes high to low) + uint32 sensitivity; // reading while strobe is high cycles sensitivity 0,1,2 + int32 dx, dy; // relative position to communicate + int32 mb; // current buttons +} SNES_MOUSE; + +static SNES_MOUSE SNESMouse; + +static uint8 ReadSNESMouse(int w) +{ + if (SNESMouse.strobe) + { + SNESMouse.sensitivity += 1; + if (SNESMouse.sensitivity > 2) SNESMouse.sensitivity = 0; + } + + uint8 result = (SNESMouse.latch & 0x80000000) >> 31; + SNESMouse.latch = (SNESMouse.latch << 1); + + return result; +} + +static void WriteSNESMouse(uint8 v) +{ + bool strobing = v & 1; + + if (SNESMouse.strobe && !strobing) + { + int dx = SNESMouse.dx; + int dy = SNESMouse.dy; + SNESMouse.dx = 0; + SNESMouse.dy = 0; + + // convert to sign and magnitude + bool sx = (dx < 0); + bool sy = (dy < 0); + if (dx < 0) dx = -dx; + if (dy < 0) dy = -dy; + + // apply sensitivity + dx += dx >> (2 - SNESMouse.sensitivity); + dx += dx >> (2 - SNESMouse.sensitivity); + + // clamp + if (dx > 127) dx = 127; + if (dy > 127) dy = 127; + + //FCEU_printf("SNES Mouse: %1d %3d, %1d %3d %1d x%1d\n",sx,dx,sy,dy,SNESMouse.mb,SNESMouse.sensitivity); + + uint8 byte0 = 0x00; + uint8 byte1 = + 0x1 | // signature + ((SNESMouse.sensitivity & 3) << 4) | // sensitivity + ((SNESMouse.mb & 3) << 6); // buttons + uint8 byte2 = uint8(dy) | (sy ? 0x80 : 0x00); + uint8 byte3 = uint8(dx) | (sx ? 0x80 : 0x00); + + SNESMouse.latch = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | (byte3 << 0); + } + + SNESMouse.strobe = strobing; +} + +static void UpdateSNESMouse(int w, void *data, int arg) +{ + int32 *ptr=(int32*)data; + + SNESMouse.dx += ptr[0]; ptr[0] = 0; + SNESMouse.dy += ptr[1]; ptr[1] = 0; + SNESMouse.mb = ptr[2] & 3; // bit 0 = left button, bit 1 = right button +} + +static INPUTC SNES_MOUSEC = +{ + ReadSNESMouse, // Read + WriteSNESMouse, // Write + 0, // Strobe (handled by Write) + UpdateSNESMouse, // Update + 0, // SLHook + 0, // Draw + 0, // Log + 0, // Load +}; + +INPUTC *FCEU_InitSNESMouse(int w) +{ + memset(&SNESMouse,0,sizeof(SNESMouse)); + return(&SNES_MOUSEC); +}