diff options
Diffstat (limited to 'src/NDS.cpp')
-rw-r--r-- | src/NDS.cpp | 317 |
1 files changed, 221 insertions, 96 deletions
diff --git a/src/NDS.cpp b/src/NDS.cpp index e809313..966b252 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2021 Arisotura + Copyright 2016-2022 melonDS team This file is part of melonDS. @@ -32,7 +32,6 @@ #include "Wifi.h" #include "AREngine.h" #include "Platform.h" -#include "NDSCart_SRAMManager.h" #include "FreeBIOS.h" #ifdef JIT_ENABLED @@ -42,6 +41,9 @@ #include "DSi.h" #include "DSi_SPI_TSC.h" +#include "DSi_NWifi.h" +#include "DSi_Camera.h" +#include "DSi_DSP.h" namespace NDS @@ -174,6 +176,7 @@ bool RunningGame; void DivDone(u32 param); void SqrtDone(u32 param); void RunTimer(u32 tid, s32 cycles); +void UpdateWifiTimings(); void SetWifiWaitCnt(u16 val); void SetGBASlotTimings(); @@ -200,7 +203,6 @@ bool Init() DMAs[6] = new DMA(1, 2); DMAs[7] = new DMA(1, 3); - if (!NDSCart_SRAMManager::Init()) return false; if (!NDSCart::Init()) return false; if (!GBACart::Init()) return false; if (!GPU::Init()) return false; @@ -228,7 +230,6 @@ void DeInit() for (int i = 0; i < 8; i++) delete DMAs[i]; - NDSCart_SRAMManager::DeInit(); NDSCart::DeInit(); GBACart::DeInit(); GPU::DeInit(); @@ -353,7 +354,28 @@ void InitTimings() // handled later: GBA slot, wifi } -void SetupDirectBoot() +bool NeedsDirectBoot() +{ + if (ConsoleType == 1) + { + // for now, DSi mode requires original BIOS/NAND + return false; + } + else + { + // internal BIOS does not support direct boot + if (!Platform::GetConfigBool(Platform::ExternalBIOSEnable)) + return true; + + // DSi/3DS firmwares aren't bootable + if (SPI_Firmware::GetFirmwareLength() == 0x20000) + return true; + + return false; + } +} + +void SetupDirectBoot(std::string romname) { if (ConsoleType == 1) { @@ -444,6 +466,8 @@ void SetupDirectBoot() ARM9->CP15Write(0x911, 0x00000020); } + NDSCart::SetupDirectBoot(romname); + ARM9->R[12] = NDSCart::Header.ARM9EntryAddress; ARM9->R[13] = 0x03002F7C; ARM9->R[14] = NDSCart::Header.ARM9EntryAddress; @@ -542,7 +566,6 @@ void Reset() if (ConsoleType == 1) { DSi::LoadBIOS(); - DSi::LoadNAND(); ARM9ClockShift = 2; MainRAMMask = 0xFFFFFF; @@ -658,6 +681,11 @@ void Reset() AREngine::Reset(); } +void Start() +{ + Running = true; +} + void Stop() { printf("Stopping: shutdown\n"); @@ -665,6 +693,9 @@ void Stop() Platform::StopEmu(); GPU::Stop(); SPU::Stop(); + + if (ConsoleType == 1) + DSi::Stop(); } bool DoSavestate_Scheduler(Savestate* file) @@ -692,7 +723,14 @@ bool DoSavestate_Scheduler(Savestate* file) DivDone, SqrtDone, - NULL + DSi_SDHost::FinishRX, + DSi_SDHost::FinishTX, + DSi_NWifi::MSTimer, + DSi_CamModule::IRQ, + DSi_CamModule::TransferScanline, + DSi_DSP::DSPCatchUpU32, + + nullptr }; int len = Event_MAX; @@ -702,7 +740,7 @@ bool DoSavestate_Scheduler(Savestate* file) { SchedEvent* evt = &SchedList[i]; - u32 funcid = -1; + u32 funcid = 0xFFFFFFFF; if (evt->Func) { for (int j = 0; eventfuncs[j]; j++) @@ -749,7 +787,7 @@ bool DoSavestate_Scheduler(Savestate* file) evt->Func = eventfuncs[funcid]; } else - evt->Func = NULL; + evt->Func = nullptr; file->Var64(&evt->Timestamp); file->Var32(&evt->Param); @@ -763,15 +801,26 @@ bool DoSavestate(Savestate* file) { file->Section("NDSG"); - // TODO: - // * do something for bool's (sizeof=1) - // * do something for 'loading DSi-mode savestate in DS mode' and vice-versa - // * add IE2/IF2 there + if (file->Saving) + { + u32 console = ConsoleType; + file->Var32(&console); + } + else + { + u32 console; + file->Var32(&console); + if (console != ConsoleType) + return false; + } - file->VarArray(MainRAM, 0x400000); - file->VarArray(SharedWRAM, 0x8000); + file->VarArray(MainRAM, MainRAMMaxSize); + file->VarArray(SharedWRAM, SharedWRAMSize); file->VarArray(ARM7WRAM, ARM7WRAMSize); + //file->VarArray(ARM9BIOS, 0x1000); + //file->VarArray(ARM7BIOS, 0x4000); + file->VarArray(ExMemCnt, 2*sizeof(u16)); file->VarArray(ROMSeed0, 2*8); file->VarArray(ROMSeed1, 2*8); @@ -781,6 +830,8 @@ bool DoSavestate(Savestate* file) file->VarArray(IME, 2*sizeof(u32)); file->VarArray(IE, 2*sizeof(u32)); file->VarArray(IF, 2*sizeof(u32)); + file->Var32(&IE2); + file->Var32(&IF2); file->Var8(&PostFlag9); file->Var8(&PostFlag7); @@ -825,11 +876,8 @@ bool DoSavestate(Savestate* file) file->Var64(&LastSysClockCycles); file->Var64(&FrameStartTimestamp); file->Var32(&NumFrames); - if (file->IsAtleastVersion(7, 1)) - { - file->Var32(&NumLagFrames); - file->Bool32(&LagFrameFlag); - } + file->Var32(&NumLagFrames); + file->Bool32(&LagFrameFlag); // TODO: save KeyInput???? file->Var16(&KeyCnt); @@ -848,9 +896,7 @@ bool DoSavestate(Savestate* file) InitTimings(); SetGBASlotTimings(); - u16 tmp = WifiWaitCnt; - WifiWaitCnt = 0xFFFF; - SetWifiWaitCnt(tmp); // force timing table update + UpdateWifiTimings(); } for (int i = 0; i < 8; i++) @@ -860,16 +906,23 @@ bool DoSavestate(Savestate* file) ARM7->DoSavestate(file); NDSCart::DoSavestate(file); - GBACart::DoSavestate(file); + if (ConsoleType == 0) + GBACart::DoSavestate(file); GPU::DoSavestate(file); SPU::DoSavestate(file); SPI::DoSavestate(file); RTC::DoSavestate(file); Wifi::DoSavestate(file); + if (ConsoleType == 1) + DSi::DoSavestate(file); + if (!file->Saving) { GPU::SetPowerCnt(PowerControl9); + + SPU::SetPowerCnt(PowerControl7 & 0x0001); + Wifi::SetPowerCnt(PowerControl7 & 0x0002); } #ifdef JIT_ENABLED @@ -888,72 +941,58 @@ void SetConsoleType(int type) ConsoleType = type; } -bool LoadROM(const u8* romdata, u32 filelength, const char *sram, bool direct) +bool LoadCart(const u8* romdata, u32 romlen, const u8* savedata, u32 savelen) { - if (NDSCart::LoadROM(romdata, filelength, sram, direct)) - { - Running = true; - return true; - } - else - { - printf("Failed to load ROM from archive\n"); + if (!NDSCart::LoadROM(romdata, romlen)) return false; - } + + if (savedata && savelen) + NDSCart::LoadSave(savedata, savelen); + + return true; } -bool LoadROM(const char* path, const char* sram, bool direct) +void LoadSave(const u8* savedata, u32 savelen) { - if (NDSCart::LoadROM(path, sram, direct)) - { - Running = true; - return true; - } - else - { - printf("Failed to load ROM %s\n", path); - return false; - } + if (savedata && savelen) + NDSCart::LoadSave(savedata, savelen); } -bool LoadGBAROM(const char* path, const char* sram) +void EjectCart() { - if (GBACart::LoadROM(path, sram)) - { - return true; - } - else - { - printf("Failed to load ROM %s\n", path); - return false; - } + NDSCart::EjectCart(); } -bool LoadGBAROM(const u8* romdata, u32 filelength, const char *filename, const char *sram) +bool CartInserted() { - if (GBACart::LoadROM(romdata, filelength, sram)) - { - return true; - } - else - { - printf("Failed to load ROM %s from archive\n", filename); + return NDSCart::CartInserted; +} + +bool LoadGBACart(const u8* romdata, u32 romlen, const u8* savedata, u32 savelen) +{ + if (!GBACart::LoadROM(romdata, romlen)) return false; - } + + if (savedata && savelen) + GBACart::LoadSave(savedata, savelen); + + return true; } -void LoadBIOS() +void LoadGBAAddon(int type) { - Reset(); - Running = true; + GBACart::LoadAddon(type); } -void RelocateSave(const char* path, bool write) +void EjectGBACart() { - printf("SRAM: relocating to %s (write=%s)\n", path, write?"true":"false"); - NDSCart::RelocateSave(path, write); + GBACart::EjectCart(); } +void LoadBIOS() +{ + Reset(); +} u64 NextTarget() @@ -1094,8 +1133,6 @@ u32 RunFrame() GPU3D::Timestamp-SysTimestamp); #endif SPU::TransferOutput(); - - NDSCart::FlushSRAMFile(); } // In the context of TASes, frame count is traditionally the primary measure of emulated time, @@ -1166,6 +1203,25 @@ void ScheduleEvent(u32 id, bool periodic, s32 delay, void (*func)(u32), u32 para Reschedule(evt->Timestamp); } +void ScheduleEvent(u32 id, u64 timestamp, void (*func)(u32), u32 param) +{ + if (SchedListMask & (1<<id)) + { + printf("!! EVENT %d ALREADY SCHEDULED\n", id); + return; + } + + SchedEvent* evt = &SchedList[id]; + + evt->Timestamp = timestamp; + evt->Func = func; + evt->Param = param; + + SchedListMask |= (1<<id); + + Reschedule(evt->Timestamp); +} + void CancelEvent(u32 id) { SchedListMask &= ~(1<<id); @@ -1229,15 +1285,30 @@ void SetLidClosed(bool closed) } } +void CamInputFrame(int cam, u32* data, int width, int height, bool rgb) +{ + // TODO: support things like the GBA-slot camera addon + // whenever these are emulated + + if (ConsoleType == 1) + { + switch (cam) + { + case 0: return DSi_CamModule::Camera0->InputFrame(data, width, height, rgb); + case 1: return DSi_CamModule::Camera1->InputFrame(data, width, height, rgb); + } + } +} + void MicInputFrame(s16* data, int samples) { return SPI_TSC::MicInputFrame(data, samples); } -int ImportSRAM(u8* data, u32 length) +/*int ImportSRAM(u8* data, u32 length) { return NDSCart::ImportSRAM(data, length); -} +}*/ void Halt() @@ -1291,15 +1362,29 @@ void MapSharedWRAM(u8 val) } +void UpdateWifiTimings() +{ + if (PowerControl7 & 0x0002) + { + const int ntimings[4] = {10, 8, 6, 18}; + u16 val = WifiWaitCnt; + + SetARM7RegionTimings(0x04800, 0x04808, Mem7_Wifi0, 16, ntimings[val & 0x3], (val & 0x4) ? 4 : 6); + SetARM7RegionTimings(0x04808, 0x04810, Mem7_Wifi1, 16, ntimings[(val>>3) & 0x3], (val & 0x20) ? 4 : 10); + } + else + { + SetARM7RegionTimings(0x04800, 0x04808, Mem7_Wifi0, 32, 1, 1); + SetARM7RegionTimings(0x04808, 0x04810, Mem7_Wifi1, 32, 1, 1); + } +} + void SetWifiWaitCnt(u16 val) { if (WifiWaitCnt == val) return; WifiWaitCnt = val; - - const int ntimings[4] = {10, 8, 6, 18}; - SetARM7RegionTimings(0x04800, 0x04808, Mem7_Wifi0, 16, ntimings[val & 0x3], (val & 0x4) ? 4 : 6); - SetARM7RegionTimings(0x04808, 0x04810, Mem7_Wifi1, 16, ntimings[(val>>3) & 0x3], (val & 0x20) ? 4 : 10); + UpdateWifiTimings(); } void SetGBASlotTimings() @@ -1909,8 +1994,8 @@ void debug(u32 param) //for (int i = 0; i < 9; i++) // printf("VRAM %c: %02X\n", 'A'+i, GPU::VRAMCNT[i]); - /*FILE* - shit = fopen("debug/construct.bin", "wb"); + FILE* + shit = fopen("debug/inazuma.bin", "wb"); fwrite(ARM9->ITCM, 0x8000, 1, shit); for (u32 i = 0x02000000; i < 0x02400000; i+=4) { @@ -1922,9 +2007,14 @@ void debug(u32 param) u32 val = ARM7Read32(i); fwrite(&val, 4, 1, shit); } - fclose(shit);*/ + for (u32 i = 0x06000000; i < 0x06040000; i+=4) + { + u32 val = ARM7Read32(i); + fwrite(&val, 4, 1, shit); + } + fclose(shit); - FILE* + /*FILE* shit = fopen("debug/directboot9.bin", "wb"); for (u32 i = 0x02000000; i < 0x04000000; i+=4) { @@ -1932,13 +2022,13 @@ void debug(u32 param) fwrite(&val, 4, 1, shit); } fclose(shit); - shit = fopen("debug/directboot7.bin", "wb"); + shit = fopen("debug/camera7.bin", "wb"); for (u32 i = 0x02000000; i < 0x04000000; i+=4) { u32 val = DSi::ARM7Read32(i); fwrite(&val, 4, 1, shit); } - fclose(shit); + fclose(shit);*/ } @@ -2364,6 +2454,7 @@ u8 ARM7Read8(u32 addr) case 0x04800000: if (addr < 0x04810000) { + if (!(PowerControl7 & (1<<1))) return 0; if (addr & 0x1) return Wifi::Read(addr-1) >> 8; return Wifi::Read(addr) & 0xFF; } @@ -2428,6 +2519,7 @@ u16 ARM7Read16(u32 addr) case 0x04800000: if (addr < 0x04810000) { + if (!(PowerControl7 & (1<<1))) return 0; return Wifi::Read(addr); } break; @@ -2491,6 +2583,7 @@ u32 ARM7Read32(u32 addr) case 0x04800000: if (addr < 0x04810000) { + if (!(PowerControl7 & (1<<1))) return 0; return Wifi::Read(addr) | (Wifi::Read(addr+2) << 16); } break; @@ -2582,7 +2675,8 @@ void ARM7Write8(u32 addr, u8 val) return; } - if (ARM7->R[15] > 0x00002F30) // ARM7 BIOS bug + //if (ARM7->R[15] > 0x00002F30) // ARM7 BIOS bug + if (addr >= 0x01000000) printf("unknown arm7 write8 %08X %02X @ %08X\n", addr, val, ARM7->R[15]); } @@ -2630,6 +2724,7 @@ void ARM7Write16(u32 addr, u16 val) case 0x04800000: if (addr < 0x04810000) { + if (!(PowerControl7 & (1<<1))) return; Wifi::Write(addr, val); return; } @@ -2659,7 +2754,8 @@ void ARM7Write16(u32 addr, u16 val) return; } - printf("unknown arm7 write16 %08X %04X @ %08X\n", addr, val, ARM7->R[15]); + if (addr >= 0x01000000) + printf("unknown arm7 write16 %08X %04X @ %08X\n", addr, val, ARM7->R[15]); } void ARM7Write32(u32 addr, u32 val) @@ -2706,6 +2802,7 @@ void ARM7Write32(u32 addr, u32 val) case 0x04800000: if (addr < 0x04810000) { + if (!(PowerControl7 & (1<<1))) return; Wifi::Write(addr, val & 0xFFFF); Wifi::Write(addr+2, val >> 16); return; @@ -2739,7 +2836,8 @@ void ARM7Write32(u32 addr, u32 val) return; } - printf("unknown arm7 write32 %08X %08X @ %08X\n", addr, val, ARM7->R[15]); + if (addr >= 0x01000000) + printf("unknown arm7 write32 %08X %08X @ %08X\n", addr, val, ARM7->R[15]); } bool ARM7GetMemRegion(u32 addr, bool write, MemRegion* region) @@ -2899,7 +2997,8 @@ u8 ARM9IORead8(u32 addr) return (u8)(emuID[idx]); } - printf("unknown ARM9 IO read8 %08X %08X\n", addr, ARM9->R[15]); + if ((addr & 0xFFFFF000) != 0x04004000) + printf("unknown ARM9 IO read8 %08X %08X\n", addr, ARM9->R[15]); return 0; } @@ -3045,7 +3144,8 @@ u16 ARM9IORead16(u32 addr) return GPU3D::Read16(addr); } - printf("unknown ARM9 IO read16 %08X %08X\n", addr, ARM9->R[15]); + if ((addr & 0xFFFFF000) != 0x04004000) + printf("unknown ARM9 IO read16 %08X %08X\n", addr, ARM9->R[15]); return 0; } @@ -3188,7 +3288,8 @@ u32 ARM9IORead32(u32 addr) return GPU3D::Read32(addr); } - printf("unknown ARM9 IO read32 %08X %08X\n", addr, ARM9->R[15]); + if ((addr & 0xFFFFF000) != 0x04004000) + printf("unknown ARM9 IO read32 %08X %08X\n", addr, ARM9->R[15]); return 0; } @@ -3716,6 +3817,7 @@ u8 ARM7IORead8(u32 addr) case 0x04000241: return WRAMCnt; case 0x04000300: return PostFlag7; + case 0x04000304: return PowerControl7; } if (addr >= 0x04000400 && addr < 0x04000520) @@ -3723,7 +3825,8 @@ u8 ARM7IORead8(u32 addr) return SPU::Read8(addr); } - printf("unknown ARM7 IO read8 %08X %08X\n", addr, ARM7->R[15]); + if ((addr & 0xFFFFF000) != 0x04004000) + printf("unknown ARM7 IO read8 %08X %08X\n", addr, ARM7->R[15]); return 0; } @@ -3798,7 +3901,9 @@ u16 ARM7IORead16(u32 addr) case 0x040001C2: return SPI::ReadData(); case 0x04000204: return ExMemCnt[1]; - case 0x04000206: return WifiWaitCnt; + case 0x04000206: + if (!(PowerControl7 & (1<<1))) return 0; + return WifiWaitCnt; case 0x04000208: return IME[1]; case 0x04000210: return IE[1] & 0xFFFF; @@ -3814,7 +3919,8 @@ u16 ARM7IORead16(u32 addr) return SPU::Read16(addr); } - printf("unknown ARM7 IO read16 %08X %08X\n", addr, ARM7->R[15]); + if ((addr & 0xFFFFF000) != 0x04004000) + printf("unknown ARM7 IO read16 %08X %08X\n", addr, ARM7->R[15]); return 0; } @@ -3880,6 +3986,7 @@ u32 ARM7IORead32(u32 addr) case 0x04000210: return IE[1]; case 0x04000214: return IF[1]; + case 0x04000304: return PowerControl7; case 0x04000308: return ARM7BIOSProt; case 0x04100000: @@ -3913,7 +4020,8 @@ u32 ARM7IORead32(u32 addr) return SPU::Read32(addr); } - printf("unknown ARM7 IO read32 %08X %08X\n", addr, ARM7->R[15]); + if ((addr & 0xFFFFF000) != 0x04004000) + printf("unknown ARM7 IO read32 %08X %08X\n", addr, ARM7->R[15]); return 0; } @@ -4108,6 +4216,7 @@ void ARM7IOWrite16(u32 addr, u16 val) return; } case 0x04000206: + if (!(PowerControl7 & (1<<1))) return; SetWifiWaitCnt(val); return; @@ -4123,7 +4232,15 @@ void ARM7IOWrite16(u32 addr, u16 val) PostFlag7 = val & 0x01; return; - case 0x04000304: PowerControl7 = val; return; + case 0x04000304: + { + u16 change = PowerControl7 ^ val; + PowerControl7 = val & 0x0003; + SPU::SetPowerCnt(val & 0x0001); + Wifi::SetPowerCnt(val & 0x0002); + if (change & 0x0002) UpdateWifiTimings(); + } + return; case 0x04000308: if (ARM7BIOSProt == 0) @@ -4245,7 +4362,15 @@ void ARM7IOWrite32(u32 addr, u32 val) case 0x04000210: IE[1] = val; UpdateIRQ(1); return; case 0x04000214: IF[1] &= ~val; UpdateIRQ(1); return; - case 0x04000304: PowerControl7 = val & 0xFFFF; return; + case 0x04000304: + { + u16 change = PowerControl7 ^ val; + PowerControl7 = val & 0x0003; + SPU::SetPowerCnt(val & 0x0001); + Wifi::SetPowerCnt(val & 0x0002); + if (change & 0x0002) UpdateWifiTimings(); + } + return; case 0x04000308: if (ARM7BIOSProt == 0) |