aboutsummaryrefslogtreecommitdiff
path: root/src/NDS.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/NDS.cpp')
-rw-r--r--src/NDS.cpp317
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)