diff --git a/src/boards/406.c b/src/boards/406.c new file mode 100644 index 0000000..49c1703 --- /dev/null +++ b/src/boards/406.c @@ -0,0 +1,55 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2025 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" +#include "flashrom.h" + +uint8 submapper; + +static DECLFW(Write) { + flashrom_write(A &0x1FFF | (Page[A >>11] +A -PRGptr[0]) &~0x1FFF, V); + + if (submapper ==1) + A =A <0xA000 || A >=0xE000? (A ^0x6000): A; + else + A =A &0xE000 | A >>1 &0x0001; + + if (A &0x4000) + MMC3_IRQWrite(A, V); + else + MMC3_CMDWrite(A, V); +} + +static void Power(void) { + GenMMC3Power(); + SetReadHandler(0x8000, 0xFFFF, flashrom_read); + SetWriteHandler(0x8000, 0xFFFF, Write); +} + +void Mapper406_Init(CartInfo *info) { + submapper =info->submapper; + GenMMC3_Init(info, 512, 256, 0, 0); + flashrom_init (submapper ==1? 0x01: 0xC2, 0xA4, 65536, 0x5555, 0x2AAA, 0x7FFF); /* Macronix MX29F040 (0)/AMD AM29F040 (1) */ + info->Power =Power; + info->SaveGame[0] =PRGptr[0]; + info->SaveGameLen[0] =PRGsize[0]; + MapIRQHook =flashrom_cpuCycle; +} diff --git a/src/boards/flashrom.c b/src/boards/flashrom.c new file mode 100644 index 0000000..175b5c1 --- /dev/null +++ b/src/boards/flashrom.c @@ -0,0 +1,60 @@ +#include "flashrom.h" +void flashrom_init (uint8 manufacturerID, uint8 modelID, uint32 sectorSize, uint32 magicAddr1, uint32 magicAddr2, uint32 magicMask) { + flashrom_manufacturerID =manufacturerID; + flashrom_modelID =modelID; + flashrom_sectorSize =sectorSize; + flashrom_magicAddr1 =magicAddr1; + flashrom_magicAddr2 =magicAddr2; + flashrom_magicMask =magicMask; +} + +uint8 flashrom_read (uint32 A) { + if (flashrom_state ==0x90) /* software ID */ + return A &1? flashrom_modelID: flashrom_manufacturerID; + else + if (flashrom_timeOut) + return (CartBR(A) ^(flashrom_timeOut &1? 0x40: 0x00)) &~0x88; + else + return CartBR(A); +} + +void flashrom_write (uint32 fullAddress, uint8 V) { + uint32 i; + uint8* sector =NULL; + uint32 compare =fullAddress &flashrom_magicMask; + fullAddress &=PRGsize[0] -1; + switch (flashrom_state) { + /* command start */ + default: if (compare ==flashrom_magicAddr1 && V ==0xAA) flashrom_state++; break; + case 0x01: if (compare ==flashrom_magicAddr2 && V ==0x55) flashrom_state++; break; + case 0x02: if (compare ==flashrom_magicAddr1) flashrom_state =V; break; + /* sector or chip erase */ + case 0x80: if (compare ==flashrom_magicAddr1 && V ==0xAA) flashrom_state++; break; + case 0x81: if (compare ==flashrom_magicAddr2 && V ==0x55) flashrom_state++; break; + case 0x82: if (V ==0x30) { /* sector erase */ + /* Determine the actual sector start by masking with the sector size */ + fullAddress &=~(flashrom_sectorSize -1); + sector =PRGptr[0] +fullAddress; + for (i =0; i