diff options
Diffstat (limited to 'src/NDS.h')
-rw-r--r-- | src/NDS.h | 425 |
1 files changed, 253 insertions, 172 deletions
@@ -29,6 +29,14 @@ #include "types.h" #include "NDSCart.h" #include "GBACart.h" +#include "SPU.h" +#include "SPI.h" +#include "RTC.h" +#include "Wifi.h" +#include "AREngine.h" +#include "GPU.h" +#include "ARMJIT.h" +#include "DMA.h" // when touching the main loop/timing code, pls test a lot of shit // with this enabled, to make sure it doesn't desync @@ -36,17 +44,6 @@ namespace melonDS { -class SPU; -class SPIHost; -class RTC; -class Wifi; - -class AREngine; -class GPU; -class ARMJIT; - -namespace NDS -{ enum { @@ -75,7 +72,13 @@ enum typedef std::function<void(u32)> EventFunc; #define MemberEventFunc(cls,func) std::bind(&cls::func,this,std::placeholders::_1) - +struct SchedEvent +{ + std::map<u32, EventFunc> Funcs; + u64 Timestamp; + u32 FuncID; + u32 Param; +}; enum { IRQ_VBlank = 0, @@ -197,196 +200,274 @@ enum // TODO: add DSi regions! }; -struct MemRegion -{ - u8* Mem; - u32 Mask; -}; - // supported GBA slot addon types enum { GBAAddon_RAMExpansion = 1, }; -#ifdef JIT_ENABLED -extern bool EnableJIT; -#endif -extern int ConsoleType; -extern int CurCPU; - -extern u8 ARM9MemTimings[0x40000][8]; -extern u32 ARM9Regions[0x40000]; -extern u8 ARM7MemTimings[0x20000][4]; -extern u32 ARM7Regions[0x20000]; - -extern u32 NumFrames; -extern u32 NumLagFrames; -extern bool LagFrameFlag; - -extern u64 ARM9Timestamp, ARM9Target; -extern u64 ARM7Timestamp, ARM7Target; -extern u32 ARM9ClockShift; - -extern u32 IME[2]; -extern u32 IE[2]; -extern u32 IF[2]; -extern u32 IE2; -extern u32 IF2; -extern Timer Timers[8]; - -extern u32 CPUStop; - -extern u16 PowerControl9; - -extern u16 ExMemCnt[2]; -extern u8 ROMSeed0[2*8]; -extern u8 ROMSeed1[2*8]; - -extern u8 ARM9BIOS[0x1000]; -extern u8 ARM7BIOS[0x4000]; -extern u16 ARM7BIOSProt; - -extern u8* MainRAM; -extern u32 MainRAMMask; - -const u32 MainRAMMaxSize = 0x1000000; - -const u32 SharedWRAMSize = 0x8000; -extern u8* SharedWRAM; - -extern MemRegion SWRAM_ARM9; -extern MemRegion SWRAM_ARM7; - -extern u32 KeyInput; -extern u16 RCnt; - -extern class SPU* SPU; -extern class SPIHost* SPI; -extern class RTC* RTC; -extern class Wifi* Wifi; -extern std::unique_ptr<NDSCart::NDSCartSlot> NDSCartSlot; -extern std::unique_ptr<GBACart::GBACartSlot> GBACartSlot; -extern std::unique_ptr<GPU> GPU; -extern std::unique_ptr<ARMJIT> JIT; -extern class AREngine* AREngine; - -const u32 ARM7WRAMSize = 0x10000; -extern u8* ARM7WRAM; - -bool Init(); -void DeInit(); -void Reset(); -void Start(); - -/// Stop the emulator. -void Stop(Platform::StopReason reason = Platform::StopReason::External); - -bool DoSavestate(Savestate* file); - -void SetARM9RegionTimings(u32 addrstart, u32 addrend, u32 region, int buswidth, int nonseq, int seq); -void SetARM7RegionTimings(u32 addrstart, u32 addrend, u32 region, int buswidth, int nonseq, int seq); - -// 0=DS 1=DSi -void SetConsoleType(int type); - -void LoadBIOS(); -bool IsLoadedARM9BIOSBuiltIn(); -bool IsLoadedARM7BIOSBuiltIn(); +class SPU; +class SPIHost; +class RTC; +class Wifi; -bool LoadCart(const u8* romdata, u32 romlen, const u8* savedata, u32 savelen); -void LoadSave(const u8* savedata, u32 savelen); -void EjectCart(); -bool CartInserted(); +class AREngine; +class GPU; +class ARMJIT; -bool NeedsDirectBoot(); -void SetupDirectBoot(const std::string& romname); +class NDS +{ +public: -bool LoadGBACart(const u8* romdata, u32 romlen, const u8* savedata, u32 savelen); -void LoadGBAAddon(int type); -void EjectGBACart(); +#ifdef JIT_ENABLED + bool EnableJIT; +#endif + int ConsoleType; + int CurCPU; -u32 RunFrame(); + SchedEvent SchedList[Event_MAX] {}; + u8 ARM9MemTimings[0x40000][8]; + u32 ARM9Regions[0x40000]; + u8 ARM7MemTimings[0x20000][4]; + u32 ARM7Regions[0x20000]; -void TouchScreen(u16 x, u16 y); -void ReleaseScreen(); + u32 NumFrames; + u32 NumLagFrames; + bool LagFrameFlag; -void SetKeyMask(u32 mask); + // no need to worry about those overflowing, they can keep going for atleast 4350 years + u64 ARM9Timestamp, ARM9Target; + u64 ARM7Timestamp, ARM7Target; + u32 ARM9ClockShift; -bool IsLidClosed(); -void SetLidClosed(bool closed); + u32 IME[2]; + u32 IE[2]; + u32 IF[2]; + u32 IE2; + u32 IF2; + Timer Timers[8]; -void CamInputFrame(int cam, u32* data, int width, int height, bool rgb); -void MicInputFrame(s16* data, int samples); + u32 CPUStop; -void RegisterEventFunc(u32 id, u32 funcid, EventFunc func); -void UnregisterEventFunc(u32 id, u32 funcid); -void ScheduleEvent(u32 id, bool periodic, s32 delay, u32 funcid, u32 param); -void CancelEvent(u32 id); + u16 PowerControl9; -void debug(u32 p); + u16 ExMemCnt[2]; + u8 ROMSeed0[2*8]; + u8 ROMSeed1[2*8]; -void Halt(); + u8 ARM9BIOS[0x1000]; + u8 ARM7BIOS[0x4000]; + u16 ARM7BIOSProt; -void MapSharedWRAM(u8 val); + u8* MainRAM; + u32 MainRAMMask; -void UpdateIRQ(u32 cpu); -void SetIRQ(u32 cpu, u32 irq); -void ClearIRQ(u32 cpu, u32 irq); -void SetIRQ2(u32 irq); -void ClearIRQ2(u32 irq); -bool HaltInterrupted(u32 cpu); -void StopCPU(u32 cpu, u32 mask); -void ResumeCPU(u32 cpu, u32 mask); -void GXFIFOStall(); -void GXFIFOUnstall(); + const u32 MainRAMMaxSize = 0x1000000; -u32 GetPC(u32 cpu); -u64 GetSysClockCycles(int num); -void NocashPrint(u32 cpu, u32 addr); + const u32 SharedWRAMSize = 0x8000; + u8* SharedWRAM; -void MonitorARM9Jump(u32 addr); + MemRegion SWRAM_ARM9; + MemRegion SWRAM_ARM7; -bool DMAsInMode(u32 cpu, u32 mode); -bool DMAsRunning(u32 cpu); -void CheckDMAs(u32 cpu, u32 mode); -void StopDMAs(u32 cpu, u32 mode); + u32 KeyInput; + u16 RCnt; -void RunTimers(u32 cpu); + // JIT MUST be declared before all other component objects, + // as they'll need the memory that it allocates in its constructor! + // (Reminder: C++ fields are initialized in the order they're declared, + // regardless of what the constructor's initializer list says.) + melonDS::ARMJIT JIT; + ARMv5 ARM9; + ARMv4 ARM7; + melonDS::SPU SPU; + SPIHost SPI; + melonDS::RTC RTC; + melonDS::Wifi Wifi; + NDSCart::NDSCartSlot NDSCartSlot; + GBACart::GBACartSlot GBACartSlot; + melonDS::GPU GPU; + melonDS::AREngine AREngine; -u8 ARM9Read8(u32 addr); -u16 ARM9Read16(u32 addr); -u32 ARM9Read32(u32 addr); -void ARM9Write8(u32 addr, u8 val); -void ARM9Write16(u32 addr, u16 val); -void ARM9Write32(u32 addr, u32 val); + const u32 ARM7WRAMSize = 0x10000; + u8* ARM7WRAM; -bool ARM9GetMemRegion(u32 addr, bool write, MemRegion* region); + virtual void Reset(); + void Start(); -u8 ARM7Read8(u32 addr); -u16 ARM7Read16(u32 addr); -u32 ARM7Read32(u32 addr); -void ARM7Write8(u32 addr, u8 val); -void ARM7Write16(u32 addr, u16 val); -void ARM7Write32(u32 addr, u32 val); + /// Stop the emulator. + virtual void Stop(Platform::StopReason reason = Platform::StopReason::External); -bool ARM7GetMemRegion(u32 addr, bool write, MemRegion* region); + bool DoSavestate(Savestate* file); -u8 ARM9IORead8(u32 addr); -u16 ARM9IORead16(u32 addr); -u32 ARM9IORead32(u32 addr); -void ARM9IOWrite8(u32 addr, u8 val); -void ARM9IOWrite16(u32 addr, u16 val); -void ARM9IOWrite32(u32 addr, u32 val); + void SetARM9RegionTimings(u32 addrstart, u32 addrend, u32 region, int buswidth, int nonseq, int seq); + void SetARM7RegionTimings(u32 addrstart, u32 addrend, u32 region, int buswidth, int nonseq, int seq); -u8 ARM7IORead8(u32 addr); -u16 ARM7IORead16(u32 addr); -u32 ARM7IORead32(u32 addr); -void ARM7IOWrite8(u32 addr, u8 val); -void ARM7IOWrite16(u32 addr, u16 val); -void ARM7IOWrite32(u32 addr, u32 val); + // 0=DS 1=DSi + void SetConsoleType(int type); -} + void LoadBIOS(); + bool IsLoadedARM9BIOSBuiltIn(); + bool IsLoadedARM7BIOSBuiltIn(); + + virtual bool LoadCart(const u8* romdata, u32 romlen, const u8* savedata, u32 savelen); + void LoadSave(const u8* savedata, u32 savelen); + virtual void EjectCart(); + bool CartInserted(); + + virtual bool NeedsDirectBoot(); + void SetupDirectBoot(const std::string& romname); + virtual void SetupDirectBoot(); + + bool LoadGBACart(const u8* romdata, u32 romlen, const u8* savedata, u32 savelen); + void LoadGBAAddon(int type); + void EjectGBACart(); + + u32 RunFrame(); + + bool IsRunning() const noexcept { return Running; } + + void TouchScreen(u16 x, u16 y); + void ReleaseScreen(); + + void SetKeyMask(u32 mask); + + bool IsLidClosed(); + void SetLidClosed(bool closed); + + virtual void CamInputFrame(int cam, u32* data, int width, int height, bool rgb) {} + void MicInputFrame(s16* data, int samples); + + void RegisterEventFunc(u32 id, u32 funcid, EventFunc func); + void UnregisterEventFunc(u32 id, u32 funcid); + void ScheduleEvent(u32 id, bool periodic, s32 delay, u32 funcid, u32 param); + void CancelEvent(u32 id); + + void debug(u32 p); + + void Halt(); + + void MapSharedWRAM(u8 val); + + void UpdateIRQ(u32 cpu); + void SetIRQ(u32 cpu, u32 irq); + void ClearIRQ(u32 cpu, u32 irq); + void SetIRQ2(u32 irq); + void ClearIRQ2(u32 irq); + bool HaltInterrupted(u32 cpu); + void StopCPU(u32 cpu, u32 mask); + void ResumeCPU(u32 cpu, u32 mask); + void GXFIFOStall(); + void GXFIFOUnstall(); + + u32 GetPC(u32 cpu); + u64 GetSysClockCycles(int num); + void NocashPrint(u32 cpu, u32 addr); + + void MonitorARM9Jump(u32 addr); + + virtual bool DMAsInMode(u32 cpu, u32 mode); + virtual bool DMAsRunning(u32 cpu); + virtual void CheckDMAs(u32 cpu, u32 mode); + virtual void StopDMAs(u32 cpu, u32 mode); + + void RunTimers(u32 cpu); + + virtual u8 ARM9Read8(u32 addr); + virtual u16 ARM9Read16(u32 addr); + virtual u32 ARM9Read32(u32 addr); + virtual void ARM9Write8(u32 addr, u8 val); + virtual void ARM9Write16(u32 addr, u16 val); + virtual void ARM9Write32(u32 addr, u32 val); + + virtual bool ARM9GetMemRegion(u32 addr, bool write, MemRegion* region); + + virtual u8 ARM7Read8(u32 addr); + virtual u16 ARM7Read16(u32 addr); + virtual u32 ARM7Read32(u32 addr); + virtual void ARM7Write8(u32 addr, u8 val); + virtual void ARM7Write16(u32 addr, u16 val); + virtual void ARM7Write32(u32 addr, u32 val); + + virtual bool ARM7GetMemRegion(u32 addr, bool write, MemRegion* region); + + virtual u8 ARM9IORead8(u32 addr); + virtual u16 ARM9IORead16(u32 addr); + virtual u32 ARM9IORead32(u32 addr); + virtual void ARM9IOWrite8(u32 addr, u8 val); + virtual void ARM9IOWrite16(u32 addr, u16 val); + virtual void ARM9IOWrite32(u32 addr, u32 val); + + virtual u8 ARM7IORead8(u32 addr); + virtual u16 ARM7IORead16(u32 addr); + virtual u32 ARM7IORead32(u32 addr); + virtual void ARM7IOWrite8(u32 addr, u8 val); + virtual void ARM7IOWrite16(u32 addr, u16 val); + virtual void ARM7IOWrite32(u32 addr, u32 val); + +private: + void InitTimings(); + u32 SchedListMask; + u64 SysTimestamp; + u8 WRAMCnt; + u8 PostFlag9; + u8 PostFlag7; + u16 PowerControl7; + u16 WifiWaitCnt; + u8 TimerCheckMask[2]; + u64 TimerTimestamp[2]; + DMA DMAs[8]; + u32 DMA9Fill[4]; + u16 IPCSync9, IPCSync7; + u16 IPCFIFOCnt9, IPCFIFOCnt7; + FIFO<u32, 16> IPCFIFO9; // FIFO in which the ARM9 writes + FIFO<u32, 16> IPCFIFO7; + u16 DivCnt; + u32 DivNumerator[2]; + u32 DivDenominator[2]; + u32 DivQuotient[2]; + u32 DivRemainder[2]; + u16 SqrtCnt; + u32 SqrtVal[2]; + u32 SqrtRes; + u16 KeyCnt[2]; + bool Running; + bool RunningGame; + u64 LastSysClockCycles; + u64 FrameStartTimestamp; + u64 NextTarget(); + u64 NextTargetSleep(); + void CheckKeyIRQ(u32 cpu, u32 oldkey, u32 newkey); + void Reschedule(u64 target); + void RunSystemSleep(u64 timestamp); + void RunSystem(u64 timestamp); + void HandleTimerOverflow(u32 tid); + u16 TimerGetCounter(u32 timer); + void TimerStart(u32 id, u16 cnt); + void StartDiv(); + void DivDone(u32 param); + void SqrtDone(u32 param); + void StartSqrt(); + void RunTimer(u32 tid, s32 cycles); + void UpdateWifiTimings(); + void SetWifiWaitCnt(u16 val); + void SetGBASlotTimings(); + void EnterSleepMode(); + template <bool EnableJIT> + u32 RunFrame(); +public: + NDS() noexcept : NDS(0) {} + virtual ~NDS() noexcept; + NDS(const NDS&) = delete; + NDS& operator=(const NDS&) = delete; + NDS(NDS&&) = delete; + NDS& operator=(NDS&&) = delete; + // The frontend should set and unset this manually after creating and destroying the NDS object. + [[deprecated("Temporary workaround until JIT code generation is revised to accommodate multiple NDS objects.")]] static NDS* Current; +protected: + explicit NDS(int type) noexcept; + virtual void DoSavestateExtra(Savestate* file) {} +}; } #endif // NDS_H |