idle skipping works!

This commit is contained in:
2026-05-22 00:20:17 +02:00
parent 5fbda03ceb
commit c9a0307878
8 changed files with 26 additions and 41 deletions
+10 -30
View File
@@ -96,49 +96,37 @@ void Core::StepRSP(const u32 cpuCycles) {
} }
} }
void Core::MaybeIdleSkip() {
if (GetRegs().nextPC == GetRegs().pc)
Scheduler::GetInstance().SkipToNext();
}
void Core::Run(const float volumeL, const float volumeR) { void Core::Run(const float volumeL, const float volumeR) {
MMIO &mmio = mem->mmio; MMIO &mmio = mem->mmio;
bool broken = false; bool broken = false;
for (int field = 0; field < mmio.vi.numFields; field++) { for (int field = 0; field < mmio.vi.numFields; field++) {
Scheduler::GetInstance().HandleEvents();
u32 frameCycles = 0; u32 frameCycles = 0;
for (int i = 0; i < mmio.vi.numHalflines; i++) { for (int halfline = 0; halfline < mmio.vi.numHalflines; halfline++) {
mmio.vi.current = (i << 1) + field; mmio.vi.current = (halfline << 1) + field;
if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) { if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) {
mmio.mi.InterruptRaise(MI::Interrupt::VI); mmio.mi.InterruptRaise(MI::Interrupt::VI);
} }
while (cycles < mem->mmio.vi.cyclesPerHalfline) { for (int cycles = 0; cycles < mem->mmio.vi.cyclesPerHalfline;) {
if (IsAnythingSkippable()) { Scheduler::GetInstance().HandleEvents();
const u32 taken = Scheduler::GetInstance().events.top().time - Scheduler::GetInstance().ticks;
cycles += taken;
frameCycles += taken;
Scheduler::GetInstance().Tick(taken);
isReadingAnyIO = false;
continue;
}
const u32 taken = StepCPU(); const u32 taken = StepCPU();
cycles += taken; cycles += taken;
if ((broken = breakpoints.contains(regs.nextPC)))
break;
StepRSP(taken); StepRSP(taken);
frameCycles += taken; frameCycles += taken;
Scheduler::GetInstance().Tick(taken); Scheduler::GetInstance().Tick(taken);
} }
if (broken)
break;
cycles -= mmio.vi.cyclesPerHalfline;
} }
if (broken)
break;
if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) { if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) {
mmio.mi.InterruptRaise(MI::Interrupt::VI); mmio.mi.InterruptRaise(MI::Interrupt::VI);
} }
@@ -146,13 +134,5 @@ void Core::Run(const float volumeL, const float volumeR) {
mmio.ai.Step(frameCycles, volumeL, volumeR); mmio.ai.Step(frameCycles, volumeL, volumeR);
Scheduler::GetInstance().Tick(frameCycles); Scheduler::GetInstance().Tick(frameCycles);
} }
if (broken)
pause = true;
}
bool Core::IsAnythingSkippable() {
MMIO &mmio = mem->mmio;
return (mmio.si.status.dmaBusy || mmio.pi.dmaBusy || mmio.pi.ioBusy) && isReadingAnyIO;
} }
} // namespace n64 } // namespace n64
+1 -6
View File
@@ -19,8 +19,7 @@ struct Core {
return instance; return instance;
} }
static void SetIdleSkippingStatus(bool v) { GetInstance().isReadingAnyIO = v; } static void MaybeIdleSkip();
static Registers &GetRegs() { return GetInstance().regs; } static Registers &GetRegs() { return GetInstance().regs; }
static Mem &GetMem() { return *GetInstance().mem; } static Mem &GetMem() { return *GetInstance().mem; }
@@ -45,7 +44,6 @@ struct Core {
bool pause = true; bool pause = true;
bool romLoaded = false; bool romLoaded = false;
int slot = 0; int slot = 0;
u32 cycles = 0;
size_t memSize{}, cpuSize{}, verSize{}; size_t memSize{}, cpuSize{}, verSize{};
std::string rom; std::string rom;
std::set<s64> breakpoints{}; std::set<s64> breakpoints{};
@@ -59,8 +57,5 @@ struct Core {
#endif #endif
Interpreter interpreter; Interpreter interpreter;
ParallelRDP parallel; ParallelRDP parallel;
bool isReadingAnyIO = false;
bool IsAnythingSkippable();
}; };
} // namespace n64 } // namespace n64
+8 -1
View File
@@ -27,9 +27,16 @@ u64 Scheduler::Remove(const EventType eventType) const {
return ret; return ret;
} }
void Scheduler::SkipToNext() {
ticks = events.top().time;
}
void Scheduler::Tick(const u64 t) { void Scheduler::Tick(const u64 t) {
n64::Mem &mem = n64::Core::GetMem();
ticks += t; ticks += t;
}
void Scheduler::HandleEvents() {
n64::Mem &mem = n64::Core::GetMem();
n64::MI &mi = mem.mmio.mi; n64::MI &mi = mem.mmio.mi;
n64::SI &si = mem.mmio.si; n64::SI &si = mem.mmio.si;
n64::PI &pi = mem.mmio.pi; n64::PI &pi = mem.mmio.pi;
+2
View File
@@ -35,11 +35,13 @@ struct Scheduler {
return instance; return instance;
} }
void HandleEvents();
void EnqueueRelative(u64, EventType); void EnqueueRelative(u64, EventType);
void EnqueueAbsolute(u64, EventType); void EnqueueAbsolute(u64, EventType);
[[nodiscard]] u64 Remove(EventType) const; [[nodiscard]] u64 Remove(EventType) const;
[[nodiscard]] Event *Find(EventType) const; [[nodiscard]] Event *Find(EventType) const;
void Tick(u64 t); void Tick(u64 t);
void SkipToNext();
u8 index = 0; u8 index = 0;
u64 ticks = 0; u64 ticks = 0;
@@ -140,6 +140,7 @@ void Interpreter::branch(const bool cond, const s64 address) {
regs.delaySlot = true; regs.delaySlot = true;
if (cond) { if (cond) {
regs.nextPC = address; regs.nextPC = address;
Core::MaybeIdleSkip();
} }
} }
@@ -147,6 +148,7 @@ void Interpreter::branch_likely(const bool cond, const s64 address) {
if (cond) { if (cond) {
regs.delaySlot = true; regs.delaySlot = true;
regs.nextPC = address; regs.nextPC = address;
Core::MaybeIdleSkip();
} else { } else {
regs.SetPC64(regs.nextPC); regs.SetPC64(regs.nextPC);
} }
+1 -1
View File
@@ -425,7 +425,6 @@ auto PI::Read(u32 addr) const -> u32 {
return wrLen; return wrLen;
case 0x04600010: case 0x04600010:
{ {
Core::SetIdleSkippingStatus(true);
u32 value = 0; u32 value = 0;
value |= (dmaBusy << 0); // Is PI DMA active? value |= (dmaBusy << 0); // Is PI DMA active?
value |= (ioBusy << 1); // Is PI IO busy? value |= (ioBusy << 1); // Is PI IO busy?
@@ -433,6 +432,7 @@ auto PI::Read(u32 addr) const -> u32 {
value |= (mem.mmio.mi.intr.pi << 3); // PI interrupt? value |= (mem.mmio.mi.intr.pi << 3); // PI interrupt?
return value; return value;
} }
case 0x04600034:
case 0x04600014: case 0x04600014:
return piBsdDom1Lat; return piBsdDom1Lat;
case 0x04600018: case 0x04600018:
-1
View File
@@ -24,7 +24,6 @@ auto SI::Read(u32 addr) const -> u32 {
return 0; return 0;
case 0x04800018: case 0x04800018:
{ {
Core::SetIdleSkippingStatus(true);
u32 val = 0; u32 val = 0;
val |= status.dmaBusy; val |= status.dmaBusy;
val |= (0 << 1); val |= (0 << 1);
+1 -1
View File
@@ -442,7 +442,7 @@ void KaizenGui::run() {
case SDL_EVENT_WINDOW_RESTORED: case SDL_EVENT_WINDOW_RESTORED:
minimized = false; minimized = false;
break; break;
default: default: break;
} }
QueryDevices(e); QueryDevices(e);
HandleInput(e); HandleInput(e);