mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-27 00:00:07 -06:00
start refining sleep mode. code still kinda sucks.
This commit is contained in:
@ -959,10 +959,10 @@ void RunNDMAs(u32 cpu)
|
|||||||
{
|
{
|
||||||
if (NDS::ARM9Timestamp >= NDS::ARM9Target) return;
|
if (NDS::ARM9Timestamp >= NDS::ARM9Target) return;
|
||||||
|
|
||||||
if (!(NDS::CPUStop & 0x80000000)) NDMAs[0]->Run();
|
if (!(NDS::CPUStop & NDS::CPUStop_GXStall)) NDMAs[0]->Run();
|
||||||
if (!(NDS::CPUStop & 0x80000000)) NDMAs[1]->Run();
|
if (!(NDS::CPUStop & NDS::CPUStop_GXStall)) NDMAs[1]->Run();
|
||||||
if (!(NDS::CPUStop & 0x80000000)) NDMAs[2]->Run();
|
if (!(NDS::CPUStop & NDS::CPUStop_GXStall)) NDMAs[2]->Run();
|
||||||
if (!(NDS::CPUStop & 0x80000000)) NDMAs[3]->Run();
|
if (!(NDS::CPUStop & NDS::CPUStop_GXStall)) NDMAs[3]->Run();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
150
src/NDS.cpp
150
src/NDS.cpp
@ -1060,19 +1060,115 @@ void RunSystem(u64 timestamp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 NextTargetSleep()
|
||||||
|
{
|
||||||
|
u64 minEvent = UINT64_MAX;
|
||||||
|
|
||||||
|
u32 mask = SchedListMask;
|
||||||
|
for (int i = 0; i < Event_MAX; i++)
|
||||||
|
{
|
||||||
|
if (!mask) break;
|
||||||
|
if (i == Event_SPU || i == Event_RTC)
|
||||||
|
{
|
||||||
|
if (mask & 0x1)
|
||||||
|
{
|
||||||
|
if (SchedList[i].Timestamp < minEvent)
|
||||||
|
minEvent = SchedList[i].Timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return minEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunSystemSleep(u64 timestamp)
|
||||||
|
{
|
||||||
|
u64 offset = timestamp - SysTimestamp;
|
||||||
|
SysTimestamp = timestamp;
|
||||||
|
|
||||||
|
u32 mask = SchedListMask;
|
||||||
|
for (int i = 0; i < Event_MAX; i++)
|
||||||
|
{
|
||||||
|
if (!mask) break;
|
||||||
|
if (i == Event_SPU || i == Event_RTC)
|
||||||
|
{
|
||||||
|
if (mask & 0x1)
|
||||||
|
{
|
||||||
|
if (SchedList[i].Timestamp <= SysTimestamp)
|
||||||
|
{
|
||||||
|
SchedListMask &= ~(1<<i);
|
||||||
|
|
||||||
|
u32 param;
|
||||||
|
if (i == Event_SPU)
|
||||||
|
param = 1;
|
||||||
|
else
|
||||||
|
param = SchedList[i].Param;
|
||||||
|
|
||||||
|
SchedList[i].Func(param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mask & 0x1)
|
||||||
|
{
|
||||||
|
if (SchedList[i].Timestamp <= SysTimestamp)
|
||||||
|
{
|
||||||
|
SchedList[i].Timestamp += offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <bool EnableJIT, int ConsoleType>
|
template <bool EnableJIT, int ConsoleType>
|
||||||
u32 RunFrame()
|
u32 RunFrame()
|
||||||
{
|
{
|
||||||
FrameStartTimestamp = SysTimestamp;
|
FrameStartTimestamp = SysTimestamp;
|
||||||
|
|
||||||
LagFrameFlag = true;
|
LagFrameFlag = true;
|
||||||
bool runFrame = Running && !(CPUStop & 0x40000000);
|
bool runFrame = Running && !(CPUStop & CPUStop_Sleep);
|
||||||
if (runFrame)
|
while (Running)
|
||||||
|
{
|
||||||
|
u64 frametarget = SysTimestamp + 560190;
|
||||||
|
|
||||||
|
if (CPUStop & CPUStop_Sleep)
|
||||||
|
{
|
||||||
|
// we are running in sleep mode
|
||||||
|
// we still need to run the RTC during this mode
|
||||||
|
// we also keep outputting audio, so that frontends using audio sync don't skyrocket to 1000+FPS
|
||||||
|
|
||||||
|
while (Running && (SysTimestamp < frametarget))
|
||||||
|
{
|
||||||
|
u64 target = NextTargetSleep();
|
||||||
|
if (target > frametarget)
|
||||||
|
target = frametarget;
|
||||||
|
|
||||||
|
ARM9Timestamp = target << ARM9ClockShift;
|
||||||
|
ARM7Timestamp = target;
|
||||||
|
TimerTimestamp[0] = target;
|
||||||
|
TimerTimestamp[1] = target;
|
||||||
|
GPU3D::Timestamp = target;
|
||||||
|
RunSystemSleep(target);
|
||||||
|
|
||||||
|
if (!(CPUStop & CPUStop_Sleep))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SysTimestamp >= frametarget)
|
||||||
|
GPU::TotalScanlines = 263;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ARM9->CheckGdbIncoming();
|
ARM9->CheckGdbIncoming();
|
||||||
ARM7->CheckGdbIncoming();
|
ARM7->CheckGdbIncoming();
|
||||||
|
|
||||||
|
if (!(CPUStop & CPUStop_Wakeup))
|
||||||
|
{
|
||||||
GPU::StartFrame();
|
GPU::StartFrame();
|
||||||
|
}
|
||||||
|
CPUStop &= ~CPUStop_Wakeup;
|
||||||
|
|
||||||
while (Running && GPU::TotalScanlines==0)
|
while (Running && GPU::TotalScanlines==0)
|
||||||
{
|
{
|
||||||
@ -1080,19 +1176,19 @@ u32 RunFrame()
|
|||||||
ARM9Target = target << ARM9ClockShift;
|
ARM9Target = target << ARM9ClockShift;
|
||||||
CurCPU = 0;
|
CurCPU = 0;
|
||||||
|
|
||||||
if (CPUStop & 0x80000000)
|
if (CPUStop & CPUStop_GXStall)
|
||||||
{
|
{
|
||||||
// GXFIFO stall
|
// GXFIFO stall
|
||||||
s32 cycles = GPU3D::CyclesToRunFor();
|
s32 cycles = GPU3D::CyclesToRunFor();
|
||||||
|
|
||||||
ARM9Timestamp = std::min(ARM9Target, ARM9Timestamp+(cycles<<ARM9ClockShift));
|
ARM9Timestamp = std::min(ARM9Target, ARM9Timestamp+(cycles<<ARM9ClockShift));
|
||||||
}
|
}
|
||||||
else if (CPUStop & 0x0FFF)
|
else if (CPUStop & CPUStop_DMA9)
|
||||||
{
|
{
|
||||||
DMAs[0]->Run<ConsoleType>();
|
DMAs[0]->Run<ConsoleType>();
|
||||||
if (!(CPUStop & 0x80000000)) DMAs[1]->Run<ConsoleType>();
|
if (!(CPUStop & CPUStop_GXStall)) DMAs[1]->Run<ConsoleType>();
|
||||||
if (!(CPUStop & 0x80000000)) DMAs[2]->Run<ConsoleType>();
|
if (!(CPUStop & CPUStop_GXStall)) DMAs[2]->Run<ConsoleType>();
|
||||||
if (!(CPUStop & 0x80000000)) DMAs[3]->Run<ConsoleType>();
|
if (!(CPUStop & CPUStop_GXStall)) DMAs[3]->Run<ConsoleType>();
|
||||||
if (ConsoleType == 1) DSi::RunNDMAs(0);
|
if (ConsoleType == 1) DSi::RunNDMAs(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1115,7 +1211,7 @@ u32 RunFrame()
|
|||||||
{
|
{
|
||||||
ARM7Target = target; // might be changed by a reschedule
|
ARM7Target = target; // might be changed by a reschedule
|
||||||
|
|
||||||
if (CPUStop & 0x0FFF0000)
|
if (CPUStop & CPUStop_DMA7)
|
||||||
{
|
{
|
||||||
DMAs[4]->Run<ConsoleType>();
|
DMAs[4]->Run<ConsoleType>();
|
||||||
DMAs[5]->Run<ConsoleType>();
|
DMAs[5]->Run<ConsoleType>();
|
||||||
@ -1138,14 +1234,18 @@ u32 RunFrame()
|
|||||||
|
|
||||||
RunSystem(target);
|
RunSystem(target);
|
||||||
|
|
||||||
if (CPUStop & 0x40000000)
|
if (CPUStop & CPUStop_Sleep)
|
||||||
{
|
{
|
||||||
// checkme: when is sleep mode effective?
|
// checkme: when is sleep mode effective?
|
||||||
CancelEvent(Event_LCD);
|
//CancelEvent(Event_LCD);
|
||||||
GPU::TotalScanlines = 263;
|
//GPU::TotalScanlines = 263;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GPU::TotalScanlines == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
#ifdef DEBUG_CHECK_DESYNC
|
#ifdef DEBUG_CHECK_DESYNC
|
||||||
Log(LogLevel::Debug, "[%08X%08X] ARM9=%ld, ARM7=%ld, GPU=%ld\n",
|
Log(LogLevel::Debug, "[%08X%08X] ARM9=%ld, ARM7=%ld, GPU=%ld\n",
|
||||||
@ -1155,15 +1255,17 @@ u32 RunFrame()
|
|||||||
GPU3D::Timestamp-SysTimestamp);
|
GPU3D::Timestamp-SysTimestamp);
|
||||||
#endif
|
#endif
|
||||||
SPU::TransferOutput();
|
SPU::TransferOutput();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("FRAME %08X %d %016llX\n", CPUStop, GPU::TotalScanlines, SysTimestamp-FrameStartTimestamp);
|
||||||
// In the context of TASes, frame count is traditionally the primary measure of emulated time,
|
// In the context of TASes, frame count is traditionally the primary measure of emulated time,
|
||||||
// so it needs to be tracked even if NDS is powered off.
|
// so it needs to be tracked even if NDS is powered off.
|
||||||
NumFrames++;
|
NumFrames++;
|
||||||
if (LagFrameFlag)
|
if (LagFrameFlag)
|
||||||
NumLagFrames++;
|
NumLagFrames++;
|
||||||
|
|
||||||
if (runFrame)
|
if (Running)
|
||||||
return GPU::TotalScanlines;
|
return GPU::TotalScanlines;
|
||||||
else
|
else
|
||||||
return 263;
|
return 263;
|
||||||
@ -1302,8 +1404,6 @@ void SetLidClosed(bool closed)
|
|||||||
{
|
{
|
||||||
KeyInput &= ~(1<<23);
|
KeyInput &= ~(1<<23);
|
||||||
SetIRQ(1, IRQ_LidOpen);
|
SetIRQ(1, IRQ_LidOpen);
|
||||||
CPUStop &= ~0x40000000;
|
|
||||||
GPU3D::RestartFrame();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1468,6 +1568,16 @@ void SetIRQ(u32 cpu, u32 irq)
|
|||||||
{
|
{
|
||||||
IF[cpu] |= (1 << irq);
|
IF[cpu] |= (1 << irq);
|
||||||
UpdateIRQ(cpu);
|
UpdateIRQ(cpu);
|
||||||
|
|
||||||
|
if ((cpu == 1) && (CPUStop & CPUStop_Sleep))
|
||||||
|
{
|
||||||
|
if (IE[1] & (1 << irq))
|
||||||
|
{
|
||||||
|
CPUStop &= ~CPUStop_Sleep;
|
||||||
|
CPUStop |= CPUStop_Wakeup;
|
||||||
|
GPU3D::RestartFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearIRQ(u32 cpu, u32 irq)
|
void ClearIRQ(u32 cpu, u32 irq)
|
||||||
@ -1527,9 +1637,9 @@ void ResumeCPU(u32 cpu, u32 mask)
|
|||||||
|
|
||||||
void GXFIFOStall()
|
void GXFIFOStall()
|
||||||
{
|
{
|
||||||
if (CPUStop & 0x80000000) return;
|
if (CPUStop & CPUStop_GXStall) return;
|
||||||
|
|
||||||
CPUStop |= 0x80000000;
|
CPUStop |= CPUStop_GXStall;
|
||||||
|
|
||||||
if (CurCPU == 1) ARM9->Halt(2);
|
if (CurCPU == 1) ARM9->Halt(2);
|
||||||
else
|
else
|
||||||
@ -1544,14 +1654,14 @@ void GXFIFOStall()
|
|||||||
|
|
||||||
void GXFIFOUnstall()
|
void GXFIFOUnstall()
|
||||||
{
|
{
|
||||||
CPUStop &= ~0x80000000;
|
CPUStop &= ~CPUStop_GXStall;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnterSleepMode()
|
void EnterSleepMode()
|
||||||
{
|
{
|
||||||
if (CPUStop & 0x40000000) return;
|
if (CPUStop & CPUStop_Sleep) return;
|
||||||
|
|
||||||
CPUStop |= 0x40000000;
|
CPUStop |= CPUStop_Sleep;
|
||||||
ARM7->Halt(2);
|
ARM7->Halt(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2018,7 +2128,7 @@ void debug(u32 param)
|
|||||||
// printf("VRAM %c: %02X\n", 'A'+i, GPU::VRAMCNT[i]);
|
// printf("VRAM %c: %02X\n", 'A'+i, GPU::VRAMCNT[i]);
|
||||||
|
|
||||||
FILE*
|
FILE*
|
||||||
shit = fopen("debug/crayon.bin", "wb");
|
shit = fopen("debug/DSfirmware.bin", "wb");
|
||||||
fwrite(ARM9->ITCM, 0x8000, 1, shit);
|
fwrite(ARM9->ITCM, 0x8000, 1, shit);
|
||||||
for (u32 i = 0x02000000; i < 0x02400000; i+=4)
|
for (u32 i = 0x02000000; i < 0x02400000; i+=4)
|
||||||
{
|
{
|
||||||
|
27
src/NDS.h
27
src/NDS.h
@ -123,6 +123,33 @@ enum
|
|||||||
IRQ2_DSi_MicExt
|
IRQ2_DSi_MicExt
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CPUStop_DMA9_0 = (1<<0),
|
||||||
|
CPUStop_DMA9_1 = (1<<1),
|
||||||
|
CPUStop_DMA9_2 = (1<<2),
|
||||||
|
CPUStop_DMA9_3 = (1<<3),
|
||||||
|
CPUStop_NDMA9_0 = (1<<4),
|
||||||
|
CPUStop_NDMA9_1 = (1<<5),
|
||||||
|
CPUStop_NDMA9_2 = (1<<6),
|
||||||
|
CPUStop_NDMA9_3 = (1<<7),
|
||||||
|
CPUStop_DMA9 = 0xFFF,
|
||||||
|
|
||||||
|
CPUStop_DMA7_0 = (1<<16),
|
||||||
|
CPUStop_DMA7_1 = (1<<17),
|
||||||
|
CPUStop_DMA7_2 = (1<<18),
|
||||||
|
CPUStop_DMA7_3 = (1<<19),
|
||||||
|
CPUStop_NDMA7_0 = (1<<20),
|
||||||
|
CPUStop_NDMA7_1 = (1<<21),
|
||||||
|
CPUStop_NDMA7_2 = (1<<22),
|
||||||
|
CPUStop_NDMA7_3 = (1<<23),
|
||||||
|
CPUStop_DMA7 = (0xFFF<<16),
|
||||||
|
|
||||||
|
CPUStop_Wakeup = (1<<29),
|
||||||
|
CPUStop_Sleep = (1<<30),
|
||||||
|
CPUStop_GXStall = (1<<31),
|
||||||
|
};
|
||||||
|
|
||||||
struct Timer
|
struct Timer
|
||||||
{
|
{
|
||||||
u16 Reload;
|
u16 Reload;
|
||||||
|
@ -726,7 +726,7 @@ void Mix(u32 dummy)
|
|||||||
s32 left = 0, right = 0;
|
s32 left = 0, right = 0;
|
||||||
s32 leftoutput = 0, rightoutput = 0;
|
s32 leftoutput = 0, rightoutput = 0;
|
||||||
|
|
||||||
if (Cnt & (1<<15))
|
if ((Cnt & (1<<15)) && (!dummy))
|
||||||
{
|
{
|
||||||
s32 ch0 = Channels[0]->DoRun();
|
s32 ch0 = Channels[0]->DoRun();
|
||||||
s32 ch1 = Channels[1]->DoRun();
|
s32 ch1 = Channels[1]->DoRun();
|
||||||
|
Reference in New Issue
Block a user