Idle skipping... maybe?

This commit is contained in:
2026-05-21 17:16:43 +02:00
parent 609fa2fb08
commit 366637aba3
7 changed files with 604 additions and 580 deletions
File diff suppressed because it is too large Load Diff
+25 -25
View File
@@ -3,35 +3,35 @@
namespace n64 {
struct PI {
PI();
void Reset();
[[nodiscard]] auto Read(u32) const -> u32;
void Write(u32, u32);
PI();
void Reset();
[[nodiscard]] auto Read(u32) const -> u32;
void Write(u32, u32);
template <typename T, bool isDma>
void BusWrite(u32, u32);
template <bool isDma>
void BusWrite(u32, u64);
template <typename T, bool isDma>
void BusWrite(u32, u32);
template <bool isDma>
void BusWrite(u32, u64);
template <typename T, bool isDma>
auto BusRead(u32) -> T;
template <typename T, bool isDma>
auto BusRead(u32) -> T;
bool ReadLatch();
bool WriteLatch(u32 val);
bool ReadLatch();
bool WriteLatch(u32 val);
static u8 GetDomain(u32 address);
[[nodiscard]] u32 AccessTiming(u8 domain, u32 length) const;
bool dmaBusy{}, ioBusy{};
u32 latch{};
u32 dramAddr{}, cartAddr{};
u32 rdLen{}, wrLen{};
u32 piBsdDom1Lat{}, piBsdDom2Lat{};
u32 piBsdDom1Pwd{}, piBsdDom2Pwd{};
u32 piBsdDom1Pgs{}, piBsdDom2Pgs{};
u32 piBsdDom1Rls{}, piBsdDom2Rls{};
static u8 GetDomain(u32 address);
[[nodiscard]] u32 AccessTiming(u8 domain, u32 length) const;
bool dmaBusy{}, ioBusy{};
u32 latch{};
u32 dramAddr{}, cartAddr{};
u32 rdLen{}, wrLen{};
u32 piBsdDom1Lat{}, piBsdDom2Lat{};
u32 piBsdDom1Pwd{}, piBsdDom2Pwd{};
u32 piBsdDom1Pgs{}, piBsdDom2Pgs{};
u32 piBsdDom1Rls{}, piBsdDom2Rls{};
private:
template <bool toDram>
void DMA();
private:
template <bool toDram>
void DMA();
};
} // namespace n64
+67 -66
View File
@@ -5,91 +5,92 @@ namespace n64 {
SI::SI() { Reset(); }
void SI::Reset() {
status.raw = 0;
dramAddr = 0;
pifAddr = 0;
toDram = false;
pif.Reset();
status.raw = 0;
dramAddr = 0;
pifAddr = 0;
toDram = false;
pif.Reset();
}
auto SI::Read(u32 addr) const -> u32 {
n64::Mem& mem = n64::Core::GetMem();
switch (addr) {
case 0x04800000:
return dramAddr;
case 0x04800004:
case 0x04800010:
return pifAddr;
case 0x0480000C:
return 0;
case 0x04800018:
{
u32 val = 0;
val |= status.dmaBusy;
val |= (0 << 1);
val |= (0 << 3);
val |= (mem.mmio.mi.intr.si << 12);
return val;
n64::Mem &mem = n64::Core::GetMem();
switch (addr) {
case 0x04800000:
return dramAddr;
case 0x04800004:
case 0x04800010:
return pifAddr;
case 0x0480000C:
return 0;
case 0x04800018:
{
Core::SetIdleSkippingStatus(true);
u32 val = 0;
val |= status.dmaBusy;
val |= (0 << 1);
val |= (0 << 3);
val |= (mem.mmio.mi.intr.si << 12);
return val;
}
default:
panic("Unhandled SI[{:08X}] read", addr);
}
default:
panic("Unhandled SI[{:08X}] read", addr);
}
}
// pif -> rdram
template <>
void SI::DMA<true>() {
n64::Mem& mem = n64::Core::GetMem();
pif.ProcessCommands();
for (int i = 0; i < 64; i++) {
mem.mmio.rdp.WriteRDRAM<u8>(dramAddr + i, pif.Read(pifAddr + i));
}
trace("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})", pifAddr, dramAddr);
n64::Mem &mem = n64::Core::GetMem();
pif.ProcessCommands();
for (int i = 0; i < 64; i++) {
mem.mmio.rdp.WriteRDRAM<u8>(dramAddr + i, pif.Read(pifAddr + i));
}
trace("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})", pifAddr, dramAddr);
}
// rdram -> pif
template <>
void SI::DMA<false>() {
n64::Mem& mem = n64::Core::GetMem();
for (int i = 0; i < 64; i++) {
pif.Write(pifAddr + i, mem.mmio.rdp.ReadRDRAM<u8>(dramAddr + i));
}
trace("SI DMA from RDRAM to PIF RAM ({:08X} to {:08X})", dramAddr, pifAddr);
n64::Mem &mem = n64::Core::GetMem();
for (int i = 0; i < 64; i++) {
pif.Write(pifAddr + i, mem.mmio.rdp.ReadRDRAM<u8>(dramAddr + i));
}
trace("SI DMA from RDRAM to PIF RAM ({:08X} to {:08X})", dramAddr, pifAddr);
}
void SI::DMA() {
n64::Mem& mem = n64::Core::GetMem();
status.dmaBusy = false;
if (toDram)
DMA<true>();
else
DMA<false>();
mem.mmio.mi.InterruptRaise(MI::Interrupt::SI);
n64::Mem &mem = n64::Core::GetMem();
status.dmaBusy = false;
if (toDram)
DMA<true>();
else
DMA<false>();
mem.mmio.mi.InterruptRaise(MI::Interrupt::SI);
}
void SI::Write(u32 addr, u32 val) {
n64::Mem& mem = n64::Core::GetMem();
switch (addr) {
case 0x04800000:
dramAddr = val & RDRAM_DSIZE;
break;
case 0x04800004:
pifAddr = val & 0x1FFFFFFF;
status.dmaBusy = true;
toDram = true;
Scheduler::GetInstance().EnqueueRelative(SI_DMA_DELAY, SI_DMA);
break;
case 0x04800010:
pifAddr = val & 0x1FFFFFFF;
status.dmaBusy = true;
toDram = false;
Scheduler::GetInstance().EnqueueRelative(SI_DMA_DELAY, SI_DMA);
break;
case 0x04800018:
mem.mmio.mi.InterruptLower(MI::Interrupt::SI);
break;
default:
panic("Unhandled SI[{:08X}] write ({:08X})", addr, val);
}
n64::Mem &mem = n64::Core::GetMem();
switch (addr) {
case 0x04800000:
dramAddr = val & RDRAM_DSIZE;
break;
case 0x04800004:
pifAddr = val & 0x1FFFFFFF;
status.dmaBusy = true;
toDram = true;
Scheduler::GetInstance().EnqueueRelative(SI_DMA_DELAY, SI_DMA);
break;
case 0x04800010:
pifAddr = val & 0x1FFFFFFF;
status.dmaBusy = true;
toDram = false;
Scheduler::GetInstance().EnqueueRelative(SI_DMA_DELAY, SI_DMA);
break;
case 0x04800018:
mem.mmio.mi.InterruptLower(MI::Interrupt::SI);
break;
default:
panic("Unhandled SI[{:08X}] write ({:08X})", addr, val);
}
}
} // namespace n64
+24 -25
View File
@@ -4,33 +4,32 @@
#include <core/mmio/PIF.hpp>
namespace n64 {
struct SI {
SI();
void Reset();
[[nodiscard]] auto Read(u32) const -> u32;
void Write(u32, u32);
template <bool toDram>
void DMA();
void DMA();
union SIStatus {
u32 raw{};
struct {
unsigned dmaBusy : 1;
unsigned ioBusy : 1;
unsigned reserved : 1;
unsigned dmaErr : 1;
unsigned : 8;
unsigned intr : 1;
};
};
union Status {
u32 raw{};
struct {
unsigned dmaBusy : 1;
unsigned ioBusy : 1;
unsigned reserved : 1;
unsigned dmaErr : 1;
unsigned : 8;
unsigned intr : 1;
};
};
struct SI {
SI();
void Reset();
[[nodiscard]] auto Read(u32) const -> u32;
void Write(u32, u32);
template <bool toDram>
void DMA();
void DMA();
bool toDram = false;
SIStatus status{};
u32 dramAddr{};
u32 pifAddr{};
PIF pif;
bool toDram = false;
Status status{};
u32 dramAddr{};
u32 pifAddr{};
PIF pif;
};
#define SI_DMA_DELAY (65536 * 2)