Idle skipping... maybe?
This commit is contained in:
@@ -20,6 +20,7 @@ vgcore.*
|
|||||||
*.data
|
*.data
|
||||||
disasm.txt
|
disasm.txt
|
||||||
*log*.txt
|
*log*.txt
|
||||||
|
*.log
|
||||||
CMakeSettings.json
|
CMakeSettings.json
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
*.diagsession
|
*.diagsession
|
||||||
|
|||||||
@@ -110,6 +110,15 @@ void Core::Run(const float volumeL, const float volumeR) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (cycles < mem->mmio.vi.cyclesPerHalfline) {
|
while (cycles < mem->mmio.vi.cyclesPerHalfline) {
|
||||||
|
if (IsAnythingSkippable()) {
|
||||||
|
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;
|
||||||
|
|
||||||
@@ -141,4 +150,9 @@ void Core::Run(const float volumeL, const float volumeR) {
|
|||||||
if (broken)
|
if (broken)
|
||||||
pause = true;
|
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
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ struct Core {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SetIdleSkippingStatus(bool v) { GetInstance().isReadingAnyIO = v; }
|
||||||
|
|
||||||
static Registers &GetRegs() { return GetInstance().regs; }
|
static Registers &GetRegs() { return GetInstance().regs; }
|
||||||
|
|
||||||
static Mem &GetMem() { return *GetInstance().mem; }
|
static Mem &GetMem() { return *GetInstance().mem; }
|
||||||
@@ -57,5 +59,8 @@ struct Core {
|
|||||||
#endif
|
#endif
|
||||||
Interpreter interpreter;
|
Interpreter interpreter;
|
||||||
ParallelRDP parallel;
|
ParallelRDP parallel;
|
||||||
|
|
||||||
|
bool isReadingAnyIO = false;
|
||||||
|
bool IsAnythingSkippable();
|
||||||
};
|
};
|
||||||
} // namespace n64
|
} // namespace n64
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ bool PI::WriteLatch(u32 value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PI::ReadLatch() {
|
bool PI::ReadLatch() {
|
||||||
n64::Registers& regs = n64::Core::GetRegs();
|
n64::Registers ®s = n64::Core::GetRegs();
|
||||||
if (ioBusy) [[unlikely]] {
|
if (ioBusy) [[unlikely]] {
|
||||||
ioBusy = false;
|
ioBusy = false;
|
||||||
regs.CpuStall(Scheduler::GetInstance().Remove(PI_BUS_WRITE_COMPLETE));
|
regs.CpuStall(Scheduler::GetInstance().Remove(PI_BUS_WRITE_COMPLETE));
|
||||||
@@ -48,7 +48,7 @@ bool PI::ReadLatch() {
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
auto PI::BusRead<u8, true>(u32 addr) -> u8 {
|
auto PI::BusRead<u8, true>(u32 addr) -> u8 {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case REGION_PI_UNKNOWN:
|
case REGION_PI_UNKNOWN:
|
||||||
panic("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, "
|
panic("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, "
|
||||||
@@ -83,7 +83,7 @@ auto PI::BusRead<u8, true>(u32 addr) -> u8 {
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
auto PI::BusRead<u8, false>(u32 addr) -> u8 {
|
auto PI::BusRead<u8, false>(u32 addr) -> u8 {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
if (!ReadLatch()) [[unlikely]] {
|
if (!ReadLatch()) [[unlikely]] {
|
||||||
return latch >> 24;
|
return latch >> 24;
|
||||||
}
|
}
|
||||||
@@ -123,7 +123,7 @@ auto PI::BusRead<u8, false>(u32 addr) -> u8 {
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
void PI::BusWrite<u8, true>(u32 addr, u32 val) {
|
void PI::BusWrite<u8, true>(u32 addr, u32 val) {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case REGION_PI_UNKNOWN:
|
case REGION_PI_UNKNOWN:
|
||||||
panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
|
panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
|
||||||
@@ -161,7 +161,7 @@ void PI::BusWrite<u8, false>(u32 addr, u32 val) {
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
auto PI::BusRead<u16, false>(u32 addr) -> u16 {
|
auto PI::BusRead<u16, false>(u32 addr) -> u16 {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
if (!ReadLatch()) [[unlikely]] {
|
if (!ReadLatch()) [[unlikely]] {
|
||||||
return latch >> 16;
|
return latch >> 16;
|
||||||
}
|
}
|
||||||
@@ -186,7 +186,8 @@ auto PI::BusRead<u16, false>(u32 addr) -> u16 {
|
|||||||
addr = (addr + 2) & ~3;
|
addr = (addr + 2) & ~3;
|
||||||
const u32 index = HALF_ADDRESS(addr) - SREGION_PI_ROM;
|
const u32 index = HALF_ADDRESS(addr) - SREGION_PI_ROM;
|
||||||
if (index > mem.rom.cart.size() - 1) {
|
if (index > mem.rom.cart.size() - 1) {
|
||||||
panic("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index, index);
|
panic("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index,
|
||||||
|
index);
|
||||||
}
|
}
|
||||||
return ircolib::ReadAccess<u16>(mem.rom.cart, index);
|
return ircolib::ReadAccess<u16>(mem.rom.cart, index);
|
||||||
}
|
}
|
||||||
@@ -231,7 +232,7 @@ void PI::BusWrite<u16, true>(u32 addr, u32 val) {
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
auto PI::BusRead<u32, false>(u32 addr) -> u32 {
|
auto PI::BusRead<u32, false>(u32 addr) -> u32 {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
if (!ReadLatch()) [[unlikely]] {
|
if (!ReadLatch()) [[unlikely]] {
|
||||||
return latch;
|
return latch;
|
||||||
}
|
}
|
||||||
@@ -260,7 +261,8 @@ auto PI::BusRead<u32, false>(u32 addr) -> u32 {
|
|||||||
if (index > mem.rom.cart.size() - 3) { // -3 because we're reading an entire word
|
if (index > mem.rom.cart.size() - 3) { // -3 because we're reading an entire word
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case REGION_CART_ISVIEWER_BUFFER:
|
case REGION_CART_ISVIEWER_BUFFER:
|
||||||
return std::byteswap<u32>(ircolib::ReadAccess<u32>(mem.isviewer, addr - SREGION_CART_ISVIEWER_BUFFER));
|
return std::byteswap<u32>(
|
||||||
|
ircolib::ReadAccess<u32>(mem.isviewer, addr - SREGION_CART_ISVIEWER_BUFFER));
|
||||||
case CART_ISVIEWER_FLUSH:
|
case CART_ISVIEWER_FLUSH:
|
||||||
panic("Read from ISViewer flush!");
|
panic("Read from ISViewer flush!");
|
||||||
default:
|
default:
|
||||||
@@ -284,7 +286,7 @@ auto PI::BusRead<u32, true>(u32 addr) -> u32 {
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
void PI::BusWrite<u32, false>(u32 addr, u32 val) {
|
void PI::BusWrite<u32, false>(u32 addr, u32 val) {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case REGION_PI_UNKNOWN:
|
case REGION_PI_UNKNOWN:
|
||||||
if (!WriteLatch(val)) [[unlikely]] {
|
if (!WriteLatch(val)) [[unlikely]] {
|
||||||
@@ -349,7 +351,7 @@ void PI::BusWrite<u32, true>(u32 addr, u32 val) {
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
auto PI::BusRead<u64, false>(u32 addr) -> u64 {
|
auto PI::BusRead<u64, false>(u32 addr) -> u64 {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
if (!ReadLatch()) [[unlikely]] {
|
if (!ReadLatch()) [[unlikely]] {
|
||||||
return static_cast<u64>(latch) << 32;
|
return static_cast<u64>(latch) << 32;
|
||||||
}
|
}
|
||||||
@@ -367,7 +369,8 @@ auto PI::BusRead<u64, false>(u32 addr) -> u64 {
|
|||||||
{
|
{
|
||||||
const u32 index = addr - SREGION_PI_ROM;
|
const u32 index = addr - SREGION_PI_ROM;
|
||||||
if (index > mem.rom.cart.size() - 7) { // -7 because we're reading an entire dword
|
if (index > mem.rom.cart.size() - 7) { // -7 because we're reading an entire dword
|
||||||
panic("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index, index);
|
panic("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index,
|
||||||
|
index);
|
||||||
}
|
}
|
||||||
return ircolib::ReadAccess<u64>(mem.rom.cart, index);
|
return ircolib::ReadAccess<u64>(mem.rom.cart, index);
|
||||||
}
|
}
|
||||||
@@ -410,7 +413,7 @@ void PI::BusWrite<true>(u32 addr, u64 val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto PI::Read(u32 addr) const -> u32 {
|
auto PI::Read(u32 addr) const -> u32 {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case 0x04600000:
|
case 0x04600000:
|
||||||
return dramAddr & 0x00FFFFFE;
|
return dramAddr & 0x00FFFFFE;
|
||||||
@@ -422,6 +425,7 @@ 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?
|
||||||
@@ -499,7 +503,7 @@ u32 PI::AccessTiming(const u8 domain, const u32 length) const {
|
|||||||
// rdram -> cart
|
// rdram -> cart
|
||||||
template <>
|
template <>
|
||||||
void PI::DMA<false>() {
|
void PI::DMA<false>() {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
const s32 len = rdLen + 1;
|
const s32 len = rdLen + 1;
|
||||||
trace("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr);
|
trace("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr);
|
||||||
|
|
||||||
@@ -523,12 +527,12 @@ void PI::DMA<false>() {
|
|||||||
// cart -> rdram
|
// cart -> rdram
|
||||||
template <>
|
template <>
|
||||||
void PI::DMA<true>() {
|
void PI::DMA<true>() {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
const s32 len = wrLen + 1;
|
const s32 len = wrLen + 1;
|
||||||
trace("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr);
|
trace("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr);
|
||||||
|
|
||||||
if (mem.saveType == SAVE_FLASH_1m && cartAddr >= SREGION_PI_SRAM && cartAddr < (CART_REGION_START_2_2 + 1_mb)) {
|
if (mem.saveType == SAVE_FLASH_1m && cartAddr >= SREGION_PI_SRAM && cartAddr < (CART_REGION_START_2_2 + 1_mb)) {
|
||||||
cartAddr = SREGION_PI_SRAM | ((cartAddr & (1_mb-1)) << 1);
|
cartAddr = SREGION_PI_SRAM | ((cartAddr & (1_mb - 1)) << 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < len; i++) {
|
for (u32 i = 0; i < len; i++) {
|
||||||
@@ -547,7 +551,7 @@ void PI::DMA<true>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PI::Write(u32 addr, u32 val) {
|
void PI::Write(u32 addr, u32 val) {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
MI &mi = mem.mmio.mi;
|
MI &mi = mem.mmio.mi;
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case 0x04600000:
|
case 0x04600000:
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ struct PI {
|
|||||||
u32 piBsdDom1Pgs{}, piBsdDom2Pgs{};
|
u32 piBsdDom1Pgs{}, piBsdDom2Pgs{};
|
||||||
u32 piBsdDom1Rls{}, piBsdDom2Rls{};
|
u32 piBsdDom1Rls{}, piBsdDom2Rls{};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <bool toDram>
|
template <bool toDram>
|
||||||
void DMA();
|
void DMA();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ void SI::Reset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto SI::Read(u32 addr) const -> u32 {
|
auto SI::Read(u32 addr) const -> u32 {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case 0x04800000:
|
case 0x04800000:
|
||||||
return dramAddr;
|
return dramAddr;
|
||||||
@@ -24,6 +24,7 @@ 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);
|
||||||
@@ -39,7 +40,7 @@ auto SI::Read(u32 addr) const -> u32 {
|
|||||||
// pif -> rdram
|
// pif -> rdram
|
||||||
template <>
|
template <>
|
||||||
void SI::DMA<true>() {
|
void SI::DMA<true>() {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
pif.ProcessCommands();
|
pif.ProcessCommands();
|
||||||
for (int i = 0; i < 64; i++) {
|
for (int i = 0; i < 64; i++) {
|
||||||
mem.mmio.rdp.WriteRDRAM<u8>(dramAddr + i, pif.Read(pifAddr + i));
|
mem.mmio.rdp.WriteRDRAM<u8>(dramAddr + i, pif.Read(pifAddr + i));
|
||||||
@@ -50,7 +51,7 @@ void SI::DMA<true>() {
|
|||||||
// rdram -> pif
|
// rdram -> pif
|
||||||
template <>
|
template <>
|
||||||
void SI::DMA<false>() {
|
void SI::DMA<false>() {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
for (int i = 0; i < 64; i++) {
|
for (int i = 0; i < 64; i++) {
|
||||||
pif.Write(pifAddr + i, mem.mmio.rdp.ReadRDRAM<u8>(dramAddr + i));
|
pif.Write(pifAddr + i, mem.mmio.rdp.ReadRDRAM<u8>(dramAddr + i));
|
||||||
}
|
}
|
||||||
@@ -58,7 +59,7 @@ void SI::DMA<false>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SI::DMA() {
|
void SI::DMA() {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
status.dmaBusy = false;
|
status.dmaBusy = false;
|
||||||
if (toDram)
|
if (toDram)
|
||||||
DMA<true>();
|
DMA<true>();
|
||||||
@@ -68,7 +69,7 @@ void SI::DMA() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SI::Write(u32 addr, u32 val) {
|
void SI::Write(u32 addr, u32 val) {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case 0x04800000:
|
case 0x04800000:
|
||||||
dramAddr = val & RDRAM_DSIZE;
|
dramAddr = val & RDRAM_DSIZE;
|
||||||
|
|||||||
@@ -4,19 +4,6 @@
|
|||||||
#include <core/mmio/PIF.hpp>
|
#include <core/mmio/PIF.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
|
|
||||||
union SIStatus {
|
|
||||||
u32 raw{};
|
|
||||||
struct {
|
|
||||||
unsigned dmaBusy : 1;
|
|
||||||
unsigned ioBusy : 1;
|
|
||||||
unsigned reserved : 1;
|
|
||||||
unsigned dmaErr : 1;
|
|
||||||
unsigned : 8;
|
|
||||||
unsigned intr : 1;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SI {
|
struct SI {
|
||||||
SI();
|
SI();
|
||||||
void Reset();
|
void Reset();
|
||||||
@@ -26,8 +13,20 @@ struct SI {
|
|||||||
void DMA();
|
void DMA();
|
||||||
void DMA();
|
void DMA();
|
||||||
|
|
||||||
|
union Status {
|
||||||
|
u32 raw{};
|
||||||
|
struct {
|
||||||
|
unsigned dmaBusy : 1;
|
||||||
|
unsigned ioBusy : 1;
|
||||||
|
unsigned reserved : 1;
|
||||||
|
unsigned dmaErr : 1;
|
||||||
|
unsigned : 8;
|
||||||
|
unsigned intr : 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
bool toDram = false;
|
bool toDram = false;
|
||||||
SIStatus status{};
|
Status status{};
|
||||||
u32 dramAddr{};
|
u32 dramAddr{};
|
||||||
u32 pifAddr{};
|
u32 pifAddr{};
|
||||||
PIF pif;
|
PIF pif;
|
||||||
|
|||||||
Reference in New Issue
Block a user