From f21347c918934441a90a2b18a928535e0dc854a9 Mon Sep 17 00:00:00 2001 From: Raphaël Zumer Date: Sun, 8 Dec 2019 12:32:59 -0500 Subject: Fix GBA memory values on deselected CPU Previously, the GBA memory was 0xFF-filled on both CPUs. However, GBATEK reports that the deselected CPU is 0x00-filled, and that some titles depend on this behavior to function properly. --- src/NDS.cpp | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'src/NDS.cpp') diff --git a/src/NDS.cpp b/src/NDS.cpp index ceeeb79..0957ea3 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1610,16 +1610,16 @@ u8 ARM9Read8(u32 addr) case 0x08000000: case 0x09000000: - if (ExMemCnt[0] & (1<<7)) return 0xFF; // TODO: proper open bus + if (ExMemCnt[0] & (1<<7)) return 0x00; // deselected CPU is 00h-filled //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; //printf("GBA read8 %08X\n", addr); // TODO!!! - return 0xFF; + return 0xFF; // TODO: proper open bus case 0x0A000000: - if (ExMemCnt[0] & (1<<7)) return 0xFF; // TODO: proper open bus + if (ExMemCnt[0] & (1<<7)) return 0x00; // deselected CPU is 00h-filled // TODO!!! - return 0xFF; + return 0xFF; // TODO: proper open bus } printf("unknown arm9 read8 %08X\n", addr); @@ -1671,16 +1671,16 @@ u16 ARM9Read16(u32 addr) case 0x08000000: case 0x09000000: - if (ExMemCnt[0] & (1<<7)) return 0xFFFF; // TODO: proper open bus + if (ExMemCnt[0] & (1<<7)) return 0x0000; // deselected CPU is 00h-filled //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; //printf("GBA read8 %08X\n", addr); // TODO!!! - return 0xFFFF; + return 0xFFFF; // TODO: proper open bus case 0x0A000000: - if (ExMemCnt[0] & (1<<7)) return 0xFFFF; // TODO: proper open bus + if (ExMemCnt[0] & (1<<7)) return 0x0000; // deselected CPU is 00h-filled // TODO!!! - return 0xFFFF; + return 0xFFFF; // TODO: proper open bus } //printf("unknown arm9 read16 %08X %08X\n", addr, ARM9->R[15]); @@ -1732,16 +1732,16 @@ u32 ARM9Read32(u32 addr) case 0x08000000: case 0x09000000: - if (ExMemCnt[0] & (1<<7)) return 0xFFFFFFFF; // TODO: proper open bus + if (ExMemCnt[0] & (1<<7)) return 0x00000000; // deselected CPU is 00h-filled //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; //printf("GBA read8 %08X\n", addr); // TODO!!! - return 0xFFFFFFFF; + return 0xFFFFFFFF; // TODO: proper open bus case 0x0A000000: - if (ExMemCnt[0] & (1<<7)) return 0xFFFFFFFF; // TODO: proper open bus + if (ExMemCnt[0] & (1<<7)) return 0x00000000; // deselected CPU is 00h-filled // TODO!!! - return 0xFFFFFFFF; + return 0xFFFFFFFF; // TODO: proper open bus } printf("unknown arm9 read32 %08X | %08X %08X\n", addr, ARM9->R[15], ARM9->R[12]); @@ -1935,16 +1935,16 @@ u8 ARM7Read8(u32 addr) case 0x08000000: case 0x09000000: - if (!(ExMemCnt[0] & (1<<7))) return 0xFF; // TODO: proper open bus + if (!(ExMemCnt[0] & (1<<7))) return 0x00; // deselected CPU is 00h-filled //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; //printf("GBA read8 %08X\n", addr); // TODO!!! - return 0xFF; + return 0xFF; // TODO: proper open bus case 0x0A000000: - if (!(ExMemCnt[0] & (1<<7))) return 0xFF; // TODO: proper open bus + if (!(ExMemCnt[0] & (1<<7))) return 0x00; // deselected CPU is 00h-filled // TODO!!! - return 0xFF; + return 0xFF; // TODO: proper open bus } printf("unknown arm7 read8 %08X %08X %08X/%08X\n", addr, ARM7->R[15], ARM7->R[0], ARM7->R[1]); @@ -1998,16 +1998,16 @@ u16 ARM7Read16(u32 addr) case 0x08000000: case 0x09000000: - if (!(ExMemCnt[0] & (1<<7))) return 0xFFFF; // TODO: proper open bus + if (!(ExMemCnt[0] & (1<<7))) return 0x0000; // deselected CPU is 00h-filled //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; //printf("GBA read8 %08X\n", addr); // TODO!!! - return 0xFFFF; + return 0xFFFF; // TODO: proper open bus case 0x0A000000: - if (!(ExMemCnt[0] & (1<<7))) return 0xFFFF; // TODO: proper open bus + if (!(ExMemCnt[0] & (1<<7))) return 0x0000; // deselected CPU is 00h-filled // TODO!!! - return 0xFFFF; + return 0xFFFF; // TODO: proper open bus } printf("unknown arm7 read16 %08X %08X\n", addr, ARM7->R[15]); @@ -2061,16 +2061,16 @@ u32 ARM7Read32(u32 addr) case 0x08000000: case 0x09000000: - if (!(ExMemCnt[0] & (1<<7))) return 0xFFFFFFFF; // TODO: proper open bus + if (!(ExMemCnt[0] & (1<<7))) return 0x00000000; // deselected CPU is 00h-filled //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; //printf("GBA read8 %08X\n", addr); // TODO!!! - return 0xFFFFFFFF; + return 0xFFFFFFFF; // TODO: proper open bus case 0x0A000000: - if (!(ExMemCnt[0] & (1<<7))) return 0xFFFFFFFF; // TODO: proper open bus + if (!(ExMemCnt[0] & (1<<7))) return 0x00000000; // deselected CPU is 00h-filled // TODO!!! - return 0xFFFFFFFF; + return 0xFFFFFFFF; // TODO: proper open bus } printf("unknown arm7 read32 %08X | %08X\n", addr, ARM7->R[15]); -- cgit v1.2.3 From d86ee1d5bfb76d4efd89f4056beece374926500a Mon Sep 17 00:00:00 2001 From: Raphaël Zumer Date: Sun, 8 Dec 2019 13:46:51 -0500 Subject: Add GBA cart model and allow reading from it --- src/CMakeLists.txt | 1 + src/GBACart.cpp | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/GBACart.h | 52 ++++++++++++++ src/NDS.cpp | 73 +++++++++++++------- 4 files changed, 299 insertions(+), 24 deletions(-) create mode 100644 src/GBACart.cpp create mode 100644 src/GBACart.h (limited to 'src/NDS.cpp') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a1110f1..03a4bfe 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,6 +10,7 @@ add_library(core STATIC CP15.cpp CRC32.cpp DMA.cpp + GBACart.cpp GPU.cpp GPU2D.cpp GPU3D.cpp diff --git a/src/GBACart.cpp b/src/GBACart.cpp new file mode 100644 index 0000000..7c2faad --- /dev/null +++ b/src/GBACart.cpp @@ -0,0 +1,197 @@ +/* + Copyright 2019 Arisotura, Raphaël Zumer + + This file is part of melonDS. + + melonDS 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 3 of the License, or (at your option) + any later version. + + melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include +#include "GBACart.h" +#include "CRC32.h" +#include "Platform.h" + + +namespace GBACart_SRAM +{ + +u8* SRAM; +u32 SRAMLength; + +char SRAMPath[1024]; + + +bool Init() +{ + SRAM = NULL; + return true; +} + +void DeInit() +{ + if (SRAM) delete[] SRAM; +} + +void Reset() +{ + if (SRAM) delete[] SRAM; + SRAM = NULL; +} + +void DoSavestate(Savestate* file) +{ + // TODO? +} + +void LoadSave(const char* path) +{ + if (SRAM) delete[] SRAM; + + strncpy(SRAMPath, path, 1023); + SRAMPath[1023] = '\0'; + + FILE* f = Platform::OpenFile(path, "rb"); + if (f) + { + fseek(f, 0, SEEK_END); + SRAMLength = (u32)ftell(f); + SRAM = new u8[SRAMLength]; + + fseek(f, 0, SEEK_SET); + fread(SRAM, SRAMLength, 1, f); + + fclose(f); + } + else + { + int SRAMLength = 65536; // max GBA SRAM size + + SRAM = new u8[SRAMLength]; + memset(SRAM, 0xFF, SRAMLength); + } +} + +void RelocateSave(const char* path, bool write) +{ + if (!write) + { + LoadSave(path); // lazy + return; + } + + strncpy(SRAMPath, path, 1023); + SRAMPath[1023] = '\0'; + + FILE* f = Platform::OpenFile(path, "wb"); + if (!f) + { + printf("GBACart_SRAM::RelocateSave: failed to create new file. fuck\n"); + return; + } + + fwrite(SRAM, SRAMLength, 1, f); + fclose(f); +} + +} + + +namespace GBACart +{ + +bool CartInserted; +u8* CartROM; +u32 CartROMSize; +u32 CartCRC; +u32 CartID; + + +bool Init() +{ + if (!GBACart_SRAM::Init()) return false; + + CartROM = NULL; + + return true; +} + +void DeInit() +{ + if (CartROM) delete[] CartROM; + + GBACart_SRAM::DeInit(); +} + +void Reset() +{ + CartInserted = false; + if (CartROM) delete[] CartROM; + CartROM = NULL; + CartROMSize = 0; + + GBACart_SRAM::Reset(); +} + +void DoSavestate(Savestate* file) +{ + // TODO? +} + +bool LoadROM(const char* path, const char* sram) +{ + FILE* f = Platform::OpenFile(path, "rb"); + if (!f) + { + return false; + } + + fseek(f, 0, SEEK_END); + u32 len = (u32)ftell(f); + + CartROMSize = 0x200; + while (CartROMSize < len) + CartROMSize <<= 1; + + u32 gamecode; + fseek(f, 0xAC, SEEK_SET); + fread(&gamecode, 4, 1, f); + printf("Game code: %c%c%c%c\n", gamecode&0xFF, (gamecode>>8)&0xFF, (gamecode>>16)&0xFF, gamecode>>24); + + CartROM = new u8[CartROMSize]; + memset(CartROM, 0, CartROMSize); + fseek(f, 0, SEEK_SET); + fread(CartROM, 1, len, f); + + fclose(f); + //CartROM = f; + + CartCRC = CRC32(CartROM, CartROMSize); + printf("ROM CRC32: %08X\n", CartCRC); + + CartInserted = true; + + // save + printf("Save file: %s\n", sram); + GBACart_SRAM::LoadSave(sram); + + return true; +} + +void RelocateSave(const char* path, bool write) +{ + // derp herp + GBACart_SRAM::RelocateSave(path, write); +} + +} diff --git a/src/GBACart.h b/src/GBACart.h new file mode 100644 index 0000000..94da0b2 --- /dev/null +++ b/src/GBACart.h @@ -0,0 +1,52 @@ +/* + Copyright 2019 Arisotura, Raphaël Zumer + + This file is part of melonDS. + + melonDS 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 3 of the License, or (at your option) + any later version. + + melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef GBACART_H +#define GBACART_H + +#include "types.h" +#include "Savestate.h" + + +namespace GBACart_SRAM +{ + +extern u8* SRAM; +extern u32 SRAMLength; + +} + + +namespace GBACart +{ + +extern bool CartInserted; +extern u8* CartROM; +extern u32 CartROMSize; + +bool Init(); +void DeInit(); +void Reset(); + +void DoSavestate(Savestate* file); +bool LoadROM(const char* path, const char* sram); +void RelocateSave(const char* path, bool write); + +} + +#endif // GBACART_H diff --git a/src/NDS.cpp b/src/NDS.cpp index 0957ea3..a16eb1c 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -22,6 +22,7 @@ #include "NDS.h" #include "ARM.h" #include "NDSCart.h" +#include "GBACart.h" #include "DMA.h" #include "FIFO.h" #include "GPU.h" @@ -1611,14 +1612,18 @@ u8 ARM9Read8(u32 addr) case 0x08000000: case 0x09000000: if (ExMemCnt[0] & (1<<7)) return 0x00; // deselected CPU is 00h-filled - //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; - //printf("GBA read8 %08X\n", addr); - // TODO!!! + if (GBACart::CartInserted) + { + return *(u8*)&GBACart::CartROM[addr & (GBACart::CartROMSize-1)]; + } return 0xFF; // TODO: proper open bus case 0x0A000000: if (ExMemCnt[0] & (1<<7)) return 0x00; // deselected CPU is 00h-filled - // TODO!!! + if (GBACart::CartInserted) + { + return *(u8*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + } return 0xFF; // TODO: proper open bus } @@ -1672,14 +1677,18 @@ u16 ARM9Read16(u32 addr) case 0x08000000: case 0x09000000: if (ExMemCnt[0] & (1<<7)) return 0x0000; // deselected CPU is 00h-filled - //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; - //printf("GBA read8 %08X\n", addr); - // TODO!!! + if (GBACart::CartInserted) + { + return *(u16*)&GBACart::CartROM[addr & (GBACart::CartROMSize-1)]; + } return 0xFFFF; // TODO: proper open bus case 0x0A000000: if (ExMemCnt[0] & (1<<7)) return 0x0000; // deselected CPU is 00h-filled - // TODO!!! + if (GBACart::CartInserted) + { + return *(u16*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + } return 0xFFFF; // TODO: proper open bus } @@ -1733,14 +1742,18 @@ u32 ARM9Read32(u32 addr) case 0x08000000: case 0x09000000: if (ExMemCnt[0] & (1<<7)) return 0x00000000; // deselected CPU is 00h-filled - //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; - //printf("GBA read8 %08X\n", addr); - // TODO!!! + if (GBACart::CartInserted) + { + return *(u32*)&GBACart::CartROM[addr & (GBACart::CartROMSize-1)]; + } return 0xFFFFFFFF; // TODO: proper open bus case 0x0A000000: if (ExMemCnt[0] & (1<<7)) return 0x00000000; // deselected CPU is 00h-filled - // TODO!!! + if (GBACart::CartInserted) + { + return *(u32*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + } return 0xFFFFFFFF; // TODO: proper open bus } @@ -1936,14 +1949,18 @@ u8 ARM7Read8(u32 addr) case 0x08000000: case 0x09000000: if (!(ExMemCnt[0] & (1<<7))) return 0x00; // deselected CPU is 00h-filled - //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; - //printf("GBA read8 %08X\n", addr); - // TODO!!! + if (GBACart::CartInserted) + { + return *(u8*)&GBACart::CartROM[addr & (GBACart::CartROMSize-1)]; + } return 0xFF; // TODO: proper open bus case 0x0A000000: if (!(ExMemCnt[0] & (1<<7))) return 0x00; // deselected CPU is 00h-filled - // TODO!!! + if (GBACart::CartInserted) + { + return *(u8*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + } return 0xFF; // TODO: proper open bus } @@ -1999,14 +2016,18 @@ u16 ARM7Read16(u32 addr) case 0x08000000: case 0x09000000: if (!(ExMemCnt[0] & (1<<7))) return 0x0000; // deselected CPU is 00h-filled - //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; - //printf("GBA read8 %08X\n", addr); - // TODO!!! + if (GBACart::CartInserted) + { + return *(u16*)&GBACart::CartROM[addr & (GBACart::CartROMSize-1)]; + } return 0xFFFF; // TODO: proper open bus case 0x0A000000: if (!(ExMemCnt[0] & (1<<7))) return 0x0000; // deselected CPU is 00h-filled - // TODO!!! + if (GBACart::CartInserted) + { + return *(u16*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + } return 0xFFFF; // TODO: proper open bus } @@ -2062,14 +2083,18 @@ u32 ARM7Read32(u32 addr) case 0x08000000: case 0x09000000: if (!(ExMemCnt[0] & (1<<7))) return 0x00000000; // deselected CPU is 00h-filled - //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; - //printf("GBA read8 %08X\n", addr); - // TODO!!! + if (GBACart::CartInserted) + { + return *(u32*)&GBACart::CartROM[addr & (GBACart::CartROMSize-1)]; + } return 0xFFFFFFFF; // TODO: proper open bus case 0x0A000000: if (!(ExMemCnt[0] & (1<<7))) return 0x00000000; // deselected CPU is 00h-filled - // TODO!!! + if (GBACart::CartInserted) + { + return *(u32*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + } return 0xFFFFFFFF; // TODO: proper open bus } -- cgit v1.2.3 From 968768042eae94f6965ecda5beedba8b8cf172e9 Mon Sep 17 00:00:00 2001 From: Raphaël Zumer Date: Sun, 8 Dec 2019 15:30:56 -0500 Subject: Properly init/deinit the GBA slot --- src/NDS.cpp | 17 +++++++++++++++++ src/NDS.h | 1 + 2 files changed, 18 insertions(+) (limited to 'src/NDS.cpp') diff --git a/src/NDS.cpp b/src/NDS.cpp index a16eb1c..da36bdc 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -170,6 +170,7 @@ bool Init() IPCFIFO7 = new FIFO(16); if (!NDSCart::Init()) return false; + if (!GBACart::Init()) return false; if (!GPU::Init()) return false; if (!SPU::Init()) return false; if (!SPI::Init()) return false; @@ -191,6 +192,7 @@ void DeInit() delete IPCFIFO7; NDSCart::DeInit(); + GBACart::DeInit(); GPU::DeInit(); SPU::DeInit(); SPI::DeInit(); @@ -492,6 +494,7 @@ void Reset() RCnt = 0; NDSCart::Reset(); + GBACart::Reset(); GPU::Reset(); SPU::Reset(); SPI::Reset(); @@ -693,6 +696,7 @@ bool DoSavestate(Savestate* file) ARM7->DoSavestate(file); NDSCart::DoSavestate(file); + GBACart::DoSavestate(file); GPU::DoSavestate(file); SPU::DoSavestate(file); SPI::DoSavestate(file); @@ -721,6 +725,19 @@ bool LoadROM(const char* path, const char* sram, bool direct) } } +bool LoadGBAROM(const char* path, const char* sram) +{ + if (GBACart::LoadROM(path, sram)) + { + return true; + } + else + { + printf("Failed to load ROM %s\n", path); + return false; + } +} + void LoadBIOS() { Reset(); diff --git a/src/NDS.h b/src/NDS.h index 3243337..16c42ef 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -135,6 +135,7 @@ void SetARM9RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, void SetARM7RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, int seq); bool LoadROM(const char* path, const char* sram, bool direct); +bool LoadGBAROM(const char* path, const char* sram); void LoadBIOS(); void SetupDirectBoot(); void RelocateSave(const char* path, bool write); -- cgit v1.2.3 From 62b9f51e2329507d5e47b4239259067b5fb66240 Mon Sep 17 00:00:00 2001 From: Raphaël Zumer Date: Sun, 8 Dec 2019 17:56:22 -0500 Subject: Handle GBA cartridge SRAM writes --- src/GBACart.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/GBACart.h | 4 ++++ src/NDS.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) (limited to 'src/NDS.cpp') diff --git a/src/GBACart.cpp b/src/GBACart.cpp index 8ce76ab..10f5106 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -104,6 +104,60 @@ void RelocateSave(const char* path, bool write) fclose(f); } +void Write8(u32 addr, u8 val) +{ + u8 prev = *(u8*)&SRAM[addr]; + + if (prev != val) + { + *(u8*)&SRAM[addr] = val;/* + + FILE* f = Platform::OpenFile(SRAMPath, "r+b"); + if (f) + { + fseek(f, addr, SEEK_SET); + fwrite((u8*)&SRAM[addr], 1, 1, f); + fclose(f); + }*/ + } +} + +void Write16(u32 addr, u16 val) +{ + u16 prev = *(u16*)&SRAM[addr]; + + if (prev != val) + { + *(u16*)&SRAM[addr] = val;/* + + FILE* f = Platform::OpenFile(SRAMPath, "r+b"); + if (f) + { + fseek(f, addr, SEEK_SET); + fwrite((u8*)&SRAM[addr], 2, 1, f); + fclose(f); + }*/ + } +} + +void Write32(u32 addr, u32 val) +{ + u32 prev = *(u32*)&SRAM[addr]; + + if (prev != val) + { + *(u32*)&SRAM[addr] = val;/* + + FILE* f = Platform::OpenFile(SRAMPath, "r+b"); + if (f) + { + fseek(f, addr, SEEK_SET); + fwrite((u8*)&SRAM[addr], 3, 1, f); + fclose(f); + }*/ + } +} + } diff --git a/src/GBACart.h b/src/GBACart.h index 94da0b2..e86ea43 100644 --- a/src/GBACart.h +++ b/src/GBACart.h @@ -29,6 +29,10 @@ namespace GBACart_SRAM extern u8* SRAM; extern u32 SRAMLength; +void Write8(u32 addr, u8 val); +void Write16(u32 addr, u16 val); +void Write32(u32 addr, u32 val); + } diff --git a/src/NDS.cpp b/src/NDS.cpp index da36bdc..fe66814 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1802,6 +1802,14 @@ void ARM9Write8(u32 addr, u8 val) case 0x07000000: // checkme return; + + case 0x0A000000: + if (ExMemCnt[0] & (1<<7)) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + GBACart_SRAM::Write8(addr & (GBACart_SRAM::SRAMLength-1), val); + } + return; } printf("unknown arm9 write8 %08X %02X\n", addr, val); @@ -1845,6 +1853,14 @@ void ARM9Write16(u32 addr, u16 val) if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return; *(u16*)&GPU::OAM[addr & 0x7FF] = val; return; + + case 0x0A000000: + if (ExMemCnt[0] & (1<<7)) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + GBACart_SRAM::Write16(addr & (GBACart_SRAM::SRAMLength-1), val); + } + return; } //printf("unknown arm9 write16 %08X %04X\n", addr, val); @@ -1888,6 +1904,14 @@ void ARM9Write32(u32 addr, u32 val) if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return; *(u32*)&GPU::OAM[addr & 0x7FF] = val; return; + + case 0x0A000000: + if (ExMemCnt[0] & (1<<7)) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + GBACart_SRAM::Write32(addr & (GBACart_SRAM::SRAMLength-1), val); + } + return; } printf("unknown arm9 write32 %08X %08X | %08X\n", addr, val, ARM9->R[15]); @@ -2152,6 +2176,14 @@ void ARM7Write8(u32 addr, u8 val) case 0x06800000: GPU::WriteVRAM_ARM7(addr, val); return; + + case 0x0A000000: + if (!(ExMemCnt[0] & (1<<7))) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + GBACart_SRAM::Write8(addr & (GBACart_SRAM::SRAMLength-1), val); + } + return; } printf("unknown arm7 write8 %08X %02X @ %08X\n", addr, val, ARM7->R[15]); @@ -2198,6 +2230,14 @@ void ARM7Write16(u32 addr, u16 val) case 0x06800000: GPU::WriteVRAM_ARM7(addr, val); return; + + case 0x0A000000: + if (!(ExMemCnt[0] & (1<<7))) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + GBACart_SRAM::Write16(addr & (GBACart_SRAM::SRAMLength-1), val); + } + return; } //printf("unknown arm7 write16 %08X %04X @ %08X\n", addr, val, ARM7->R[15]); @@ -2245,6 +2285,14 @@ void ARM7Write32(u32 addr, u32 val) case 0x06800000: GPU::WriteVRAM_ARM7(addr, val); return; + + case 0x0A000000: + if (!(ExMemCnt[0] & (1<<7))) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + GBACart_SRAM::Write32(addr & (GBACart_SRAM::SRAMLength-1), val); + } + return; } //printf("unknown arm7 write32 %08X %08X @ %08X\n", addr, val, ARM7->R[15]); -- cgit v1.2.3 From 5ad85f15c1858108665329fada39d67edc408b39 Mon Sep 17 00:00:00 2001 From: Raphaël Zumer Date: Mon, 9 Dec 2019 04:53:45 -0500 Subject: Add a framework to support non-SRAM GBA saves The support is not yet there, but at least we should not read or write bogus data. --- src/GBACart.cpp | 191 +++++++++++++++++++++++++++++++++++++++++++++++--------- src/GBACart.h | 4 ++ src/NDS.cpp | 12 ++-- 3 files changed, 170 insertions(+), 37 deletions(-) (limited to 'src/NDS.cpp') diff --git a/src/GBACart.cpp b/src/GBACart.cpp index 10f5106..937958c 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -26,11 +26,40 @@ namespace GBACart_SRAM { + +enum SaveType { + S_NULL, + S_EEPROM4K, + S_EEPROM64K, + S_SRAM256K, + S_FLASH512K, + S_FLASH1M +}; + +struct FlashProperties +{ + u8 state; + u8 cmd; + u8 device; + u8 manufacturer; + u8 bank; +}; + u8* SRAM; u32 SRAMLength; +SaveType SRAMType; +FlashProperties SRAMFlash; char SRAMPath[1024]; +void (*WriteFunc)(u32 addr, u8 val); + + +void Write_Null(u32 addr, u8 val); +void Write_EEPROM(u32 addr, u8 val); +void Write_SRAM(u32 addr, u8 val); +void Write_Flash(u32 addr, u8 val); + bool Init() { @@ -47,6 +76,9 @@ void Reset() { if (SRAM) delete[] SRAM; SRAM = NULL; + SRAMLength = 0; + SRAMType = S_NULL; + SRAMFlash = {}; } void DoSavestate(Savestate* file) @@ -60,6 +92,7 @@ void LoadSave(const char* path) strncpy(SRAMPath, path, 1023); SRAMPath[1023] = '\0'; + SRAMLength = 0; FILE* f = Platform::OpenFile(path, "rb"); if (f) @@ -73,12 +106,48 @@ void LoadSave(const char* path) fclose(f); } - else + + switch (SRAMLength) { - int SRAMLength = 65536; // max GBA SRAM size + case 512: + SRAMType = S_EEPROM4K; + WriteFunc = Write_EEPROM; + break; + case 8192: + SRAMType = S_EEPROM64K; + WriteFunc = Write_EEPROM; + break; + case 32768: + SRAMType = S_SRAM256K; + WriteFunc = Write_SRAM; + break; + case 65536: + SRAMType = S_FLASH512K; + WriteFunc = Write_Flash; + break; + case 128*1024: + SRAMType = S_FLASH1M; + WriteFunc = Write_Flash; + break; + default: + printf("!! BAD SAVE LENGTH %d\n", SRAMLength); + case 0: + SRAMType = S_NULL; + WriteFunc = Write_Null; + break; + } - SRAM = new u8[SRAMLength]; - memset(SRAM, 0xFF, SRAMLength); + if (SRAMType == S_FLASH512K) + { + // Panasonic 64K chip + SRAMFlash.device = 0x1B; + SRAMFlash.manufacturer = 0x32; + } + else if (SRAMType == S_FLASH1M) + { + // Macronix 128K chip + SRAMFlash.device = 0x09; + SRAMFlash.manufacturer = 0xC2; } } @@ -104,21 +173,93 @@ void RelocateSave(const char* path, bool write) fclose(f); } +u8 Read_Flash(u32 addr) +{ + // TODO: pokemen + return 0xFF; +} + +void Write_Null(u32 addr, u8 val) {} + +void Write_EEPROM(u32 addr, u8 val) +{ + // TODO: could be used in homebrew? +} + +void Write_Flash(u32 addr, u8 val) +{ + // TODO: pokemen +} + +void Write_SRAM(u32 addr, u8 val) +{ + *(u8*)&SRAM[addr] = val; + + // bit wasteful to do this for every written byte + FILE* f = Platform::OpenFile(SRAMPath, "r+b"); + if (f) + { + fseek(f, addr, SEEK_SET); + fwrite((u8*)&SRAM[addr], 1, 1, f); + fclose(f); + } +} + +u8 Read8(u32 addr) +{ + if (SRAMType == S_NULL) + { + return 0xFF; + } + + if (SRAMType == S_FLASH512K || SRAMType == S_FLASH1M) + { + return Read_Flash(addr); + } + + return *(u8*)&SRAM[addr]; +} + +u16 Read16(u32 addr) +{ + if (SRAMType == S_NULL) + { + return 0xFFFF; + } + + if (SRAMType == S_FLASH512K || SRAMType == S_FLASH1M) + { + return Read_Flash(addr) & (Read_Flash(addr + 1) << 8); + } + + return *(u16*)&SRAM[addr]; +} + +u32 Read32(u32 addr) +{ + if (SRAMType == S_NULL) + { + return 0xFFFFFFFF; + } + + if (SRAMType == S_FLASH512K || SRAMType == S_FLASH1M) + { + return Read_Flash(addr) & + (Read_Flash(addr + 1) << 8) & + (Read_Flash(addr + 2) << 16) & + (Read_Flash(addr + 3) << 24); + } + + return *(u32*)&SRAM[addr]; +} + void Write8(u32 addr, u8 val) { u8 prev = *(u8*)&SRAM[addr]; if (prev != val) { - *(u8*)&SRAM[addr] = val;/* - - FILE* f = Platform::OpenFile(SRAMPath, "r+b"); - if (f) - { - fseek(f, addr, SEEK_SET); - fwrite((u8*)&SRAM[addr], 1, 1, f); - fclose(f); - }*/ + WriteFunc(addr, val); } } @@ -128,15 +269,8 @@ void Write16(u32 addr, u16 val) if (prev != val) { - *(u16*)&SRAM[addr] = val;/* - - FILE* f = Platform::OpenFile(SRAMPath, "r+b"); - if (f) - { - fseek(f, addr, SEEK_SET); - fwrite((u8*)&SRAM[addr], 2, 1, f); - fclose(f); - }*/ + WriteFunc(addr, val & 0xFF); + WriteFunc(addr + 1, val >> 8 & 0xFF); } } @@ -146,15 +280,10 @@ void Write32(u32 addr, u32 val) if (prev != val) { - *(u32*)&SRAM[addr] = val;/* - - FILE* f = Platform::OpenFile(SRAMPath, "r+b"); - if (f) - { - fseek(f, addr, SEEK_SET); - fwrite((u8*)&SRAM[addr], 3, 1, f); - fclose(f); - }*/ + WriteFunc(addr, val & 0xFF); + WriteFunc(addr + 1, val >> 8 & 0xFF); + WriteFunc(addr + 2, val >> 16 & 0xFF); + WriteFunc(addr + 3, val >> 24 & 0xFF); } } diff --git a/src/GBACart.h b/src/GBACart.h index e86ea43..81fb222 100644 --- a/src/GBACart.h +++ b/src/GBACart.h @@ -29,6 +29,10 @@ namespace GBACart_SRAM extern u8* SRAM; extern u32 SRAMLength; +u8 Read8(u32 addr); +u16 Read16(u32 addr); +u32 Read32(u32 addr); + void Write8(u32 addr, u8 val); void Write16(u32 addr, u16 val); void Write32(u32 addr, u32 val); diff --git a/src/NDS.cpp b/src/NDS.cpp index fe66814..a906fbb 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1639,7 +1639,7 @@ u8 ARM9Read8(u32 addr) if (ExMemCnt[0] & (1<<7)) return 0x00; // deselected CPU is 00h-filled if (GBACart::CartInserted) { - return *(u8*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + return GBACart_SRAM::Read8(addr & (GBACart_SRAM::SRAMLength-1)); } return 0xFF; // TODO: proper open bus } @@ -1704,7 +1704,7 @@ u16 ARM9Read16(u32 addr) if (ExMemCnt[0] & (1<<7)) return 0x0000; // deselected CPU is 00h-filled if (GBACart::CartInserted) { - return *(u16*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + return GBACart_SRAM::Read16(addr & (GBACart_SRAM::SRAMLength-1)); } return 0xFFFF; // TODO: proper open bus } @@ -1769,7 +1769,7 @@ u32 ARM9Read32(u32 addr) if (ExMemCnt[0] & (1<<7)) return 0x00000000; // deselected CPU is 00h-filled if (GBACart::CartInserted) { - return *(u32*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + return GBACart_SRAM::Read32(addr & (GBACart_SRAM::SRAMLength-1)); } return 0xFFFFFFFF; // TODO: proper open bus } @@ -2000,7 +2000,7 @@ u8 ARM7Read8(u32 addr) if (!(ExMemCnt[0] & (1<<7))) return 0x00; // deselected CPU is 00h-filled if (GBACart::CartInserted) { - return *(u8*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + return GBACart_SRAM::Read8(addr & (GBACart_SRAM::SRAMLength-1)); } return 0xFF; // TODO: proper open bus } @@ -2067,7 +2067,7 @@ u16 ARM7Read16(u32 addr) if (!(ExMemCnt[0] & (1<<7))) return 0x0000; // deselected CPU is 00h-filled if (GBACart::CartInserted) { - return *(u16*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + return GBACart_SRAM::Read16(addr & (GBACart_SRAM::SRAMLength-1)); } return 0xFFFF; // TODO: proper open bus } @@ -2134,7 +2134,7 @@ u32 ARM7Read32(u32 addr) if (!(ExMemCnt[0] & (1<<7))) return 0x00000000; // deselected CPU is 00h-filled if (GBACart::CartInserted) { - return *(u32*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + return GBACart_SRAM::Read32(addr & (GBACart_SRAM::SRAMLength-1)); } return 0xFFFFFFFF; // TODO: proper open bus } -- cgit v1.2.3 From f257b007a250e33ecc7a86c7447ccf049964dd8d Mon Sep 17 00:00:00 2001 From: Raphaël Zumer Date: Tue, 10 Dec 2019 18:44:53 -0500 Subject: Properly pass through GBA GPIO writes --- src/GBACart.cpp | 2 ++ src/NDS.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/libui_sdl/main.cpp | 2 ++ 3 files changed, 92 insertions(+) (limited to 'src/NDS.cpp') diff --git a/src/GBACart.cpp b/src/GBACart.cpp index a7ddf9b..7e5e3b5 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -630,8 +630,10 @@ void Process(GBACart::GPIO* gpio) if (gpio->data & 4) return; // Boktai chip select if (gpio->data & 2) // Reset { + u8 prev = LightSample; LightCounter = 0; LightSample = LIGHT_VALUE; + printf("Solar sensor reset (sample: 0x%02X -> 0x%02X)\n", prev, LightSample); } if (gpio->data & 1 && LightEdge) LightCounter++; diff --git a/src/NDS.cpp b/src/NDS.cpp index a906fbb..47f96c9 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1803,6 +1803,19 @@ void ARM9Write8(u32 addr, u8 val) // checkme return; + case 0x08000000: + case 0x09000000: + if (ExMemCnt[0] & (1<<7)) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + if ((addr & 0x00FFFFFF) >= 0xC4 && (addr & 0x00FFFFFF) <= 0xC9) + { + GBACart::WriteGPIO(addr & (GBACart::CartROMSize-1), val); + return; + } + } + break; + case 0x0A000000: if (ExMemCnt[0] & (1<<7)) return; // deselected CPU, skip the write if (GBACart::CartInserted) @@ -1854,6 +1867,21 @@ void ARM9Write16(u32 addr, u16 val) *(u16*)&GPU::OAM[addr & 0x7FF] = val; return; + case 0x08000000: + case 0x09000000: + if (ExMemCnt[0] & (1<<7)) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + // Note: the lower bound is adjusted such that a write starting + // there will hit the first byte of the GPIO region. + if ((addr & 0x00FFFFFF) >= 0xC3 && (addr & 0x00FFFFFF) <= 0xC9) + { + GBACart::WriteGPIO(addr & (GBACart::CartROMSize-1), val); + return; + } + } + break; + case 0x0A000000: if (ExMemCnt[0] & (1<<7)) return; // deselected CPU, skip the write if (GBACart::CartInserted) @@ -1905,6 +1933,22 @@ void ARM9Write32(u32 addr, u32 val) *(u32*)&GPU::OAM[addr & 0x7FF] = val; return; + case 0x08000000: + case 0x09000000: + if (ExMemCnt[0] & (1<<7)) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + // Note: the lower bound is adjusted such that a write starting + // there will hit the first byte of the GPIO region. + if ((addr & 0x00FFFFFF) >= 0xC1 && (addr & 0x00FFFFFF) <= 0xC9) + { + GBACart::WriteGPIO(addr & (GBACart::CartROMSize-1), val & 0xFF); + GBACart::WriteGPIO((addr + 2) & (GBACart::CartROMSize-1), (val >> 16) & 0xFF); + return; + } + } + break; + case 0x0A000000: if (ExMemCnt[0] & (1<<7)) return; // deselected CPU, skip the write if (GBACart::CartInserted) @@ -2177,6 +2221,19 @@ void ARM7Write8(u32 addr, u8 val) GPU::WriteVRAM_ARM7(addr, val); return; + case 0x08000000: + case 0x09000000: + if (!(ExMemCnt[0] & (1<<7))) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + if ((addr & 0x00FFFFFF) >= 0xC4 && (addr & 0x00FFFFFF) <= 0xC9) + { + GBACart::WriteGPIO(addr & (GBACart::CartROMSize-1), val); + return; + } + } + break; + case 0x0A000000: if (!(ExMemCnt[0] & (1<<7))) return; // deselected CPU, skip the write if (GBACart::CartInserted) @@ -2231,6 +2288,21 @@ void ARM7Write16(u32 addr, u16 val) GPU::WriteVRAM_ARM7(addr, val); return; + case 0x08000000: + case 0x09000000: + if (!(ExMemCnt[0] & (1<<7))) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + // Note: the lower bound is adjusted such that a write starting + // there will hit the first byte of the GPIO region. + if ((addr & 0x00FFFFFF) >= 0xC3 && (addr & 0x00FFFFFF) <= 0xC9) + { + GBACart::WriteGPIO(addr & (GBACart::CartROMSize-1), val); + return; + } + } + break; + case 0x0A000000: if (!(ExMemCnt[0] & (1<<7))) return; // deselected CPU, skip the write if (GBACart::CartInserted) @@ -2286,6 +2358,22 @@ void ARM7Write32(u32 addr, u32 val) GPU::WriteVRAM_ARM7(addr, val); return; + case 0x08000000: + case 0x09000000: + if (!(ExMemCnt[0] & (1<<7))) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + // Note: the lower bound is adjusted such that a write starting + // there will hit the first byte of the GPIO region. + if ((addr & 0x00FFFFFF) >= 0xC1 && (addr & 0x00FFFFFF) <= 0xC9) + { + GBACart::WriteGPIO(addr & (GBACart::CartROMSize-1), val & 0xFF); + GBACart::WriteGPIO((addr + 2) & (GBACart::CartROMSize-1), (val >> 16) & 0xFF); + return; + } + } + break; + case 0x0A000000: if (!(ExMemCnt[0] & (1<<7))) return; // deselected CPU, skip the write if (GBACart::CartInserted) diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 1b7cfe6..d2a38f2 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -1297,6 +1297,7 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) if (GBACart::CartInserted && GBACart::HasSolarSensor) { if (GBACart_SolarSensor::LightLevel > 0) GBACart_SolarSensor::LightLevel--; + printf("Solar sensor level set to %d\n", GBACart_SolarSensor::LightLevel); } } else if (evt->Scancode == 0x4D) // Keypad right @@ -1304,6 +1305,7 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) if (GBACart::CartInserted && GBACart::HasSolarSensor) { if (GBACart_SolarSensor::LightLevel < 10) GBACart_SolarSensor::LightLevel++; + printf("Solar sensor level set to %d\n", GBACart_SolarSensor::LightLevel); } } -- cgit v1.2.3