Lay down initial PI bus latch implementation
This commit is contained in:
@@ -2,6 +2,18 @@
|
|||||||
#include <Scheduler.hpp>
|
#include <Scheduler.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
|
u32 extraCycles = 0;
|
||||||
|
|
||||||
|
void CpuStall(u32 cycles) {
|
||||||
|
extraCycles += cycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 PopStalledCycles() {
|
||||||
|
u32 ret = extraCycles;
|
||||||
|
extraCycles = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
Core::Core() {
|
Core::Core() {
|
||||||
if(SDL_GameControllerAddMappingsFromFile("resources/gamecontrollerdb.txt") < 0) {
|
if(SDL_GameControllerAddMappingsFromFile("resources/gamecontrollerdb.txt") < 0) {
|
||||||
Util::warn("Failed to load game controller DB");
|
Util::warn("Failed to load game controller DB");
|
||||||
@@ -46,8 +58,9 @@ void Core::Run(float volumeL, float volumeR) {
|
|||||||
MMIO& mmio = mem.mmio;
|
MMIO& mmio = mem.mmio;
|
||||||
Registers& regs = cpu->regs;
|
Registers& regs = cpu->regs;
|
||||||
|
|
||||||
|
Event event;
|
||||||
for (int field = 0; field < mmio.vi.numFields; field++) {
|
for (int field = 0; field < mmio.vi.numFields; field++) {
|
||||||
int frameCycles = 0;
|
u32 frameCycles = 0;
|
||||||
for (int i = 0; i < mmio.vi.numHalflines; i++) {
|
for (int i = 0; i < mmio.vi.numHalflines; i++) {
|
||||||
mmio.vi.current = (i << 1) + field;
|
mmio.vi.current = (i << 1) + field;
|
||||||
|
|
||||||
@@ -56,8 +69,9 @@ void Core::Run(float volumeL, float volumeR) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(; cycles < mem.mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) {
|
for(; cycles < mem.mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) {
|
||||||
int taken = cpu->Step();
|
u32 taken = cpu->Step();
|
||||||
static int cpuSteps = 0;
|
taken += PopStalledCycles();
|
||||||
|
static u32 cpuSteps = 0;
|
||||||
cpuSteps += taken;
|
cpuSteps += taken;
|
||||||
if(mmio.rsp.spStatus.halt) {
|
if(mmio.rsp.spStatus.halt) {
|
||||||
cpuSteps = 0;
|
cpuSteps = 0;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <SDL2/SDL_timer.h>
|
#include <SDL2/SDL_timer.h>
|
||||||
|
|
||||||
struct Window;
|
struct Window;
|
||||||
|
struct Event;
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
struct Core {
|
struct Core {
|
||||||
@@ -17,13 +18,14 @@ struct Core {
|
|||||||
void Serialize();
|
void Serialize();
|
||||||
void Deserialize();
|
void Deserialize();
|
||||||
void TogglePause() { pause = !pause; }
|
void TogglePause() { pause = !pause; }
|
||||||
|
void HandleEvents(Event*);
|
||||||
[[nodiscard]] VI& GetVI() { return cpu->mem.mmio.vi; }
|
[[nodiscard]] VI& GetVI() { return cpu->mem.mmio.vi; }
|
||||||
|
|
||||||
u32 breakpoint = 0;
|
u32 breakpoint = 0;
|
||||||
|
|
||||||
bool pause = true;
|
bool pause = true;
|
||||||
bool render = true;
|
bool render = true;
|
||||||
int cycles = 0;
|
u32 cycles = 0;
|
||||||
bool romLoaded = false;
|
bool romLoaded = false;
|
||||||
std::string rom;
|
std::string rom;
|
||||||
std::unique_ptr<BaseCPU> cpu;
|
std::unique_ptr<BaseCPU> cpu;
|
||||||
@@ -31,4 +33,8 @@ struct Core {
|
|||||||
int memSize, cpuSize, verSize;
|
int memSize, cpuSize, verSize;
|
||||||
int slot = 0;
|
int slot = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern u32 extraCycles;
|
||||||
|
void CpuStall(u32 cycles);
|
||||||
|
u32 PopStalledCycles();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
#define PI_REGION 0x04600000 ... 0x046FFFFF
|
#define PI_REGION 0x04600000 ... 0x046FFFFF
|
||||||
#define RI_REGION 0x04700000 ... 0x047FFFFF
|
#define RI_REGION 0x04700000 ... 0x047FFFFF
|
||||||
#define SI_REGION 0x04800000 ... 0x048FFFFF
|
#define SI_REGION 0x04800000 ... 0x048FFFFF
|
||||||
#define REGION_CART CART_REGION_START_2_1 ... CART_REGION_END_1_2
|
#define REGION_CART CART_REGION_START_2_1 ... CART_REGION_END_1_2
|
||||||
#define PIF_ROM_REGION PIF_ROM_REGION_START ... PIF_ROM_REGION_END
|
#define PIF_ROM_REGION PIF_ROM_REGION_START ... PIF_ROM_REGION_END
|
||||||
#define PIF_RAM_REGION PIF_RAM_REGION_START ... PIF_RAM_REGION_END
|
#define PIF_RAM_REGION PIF_RAM_REGION_START ... PIF_RAM_REGION_END
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,60 @@
|
|||||||
#include <Scheduler.hpp>
|
#include <Scheduler.hpp>
|
||||||
#include <core/registers/Registers.hpp>
|
#include <core/registers/Registers.hpp>
|
||||||
|
#include <core/Mem.hpp>
|
||||||
|
|
||||||
Scheduler scheduler;
|
Scheduler scheduler;
|
||||||
|
|
||||||
|
void Scheduler::enqueueRelative(u64 t, const EventType type) {
|
||||||
|
enqueueAbsolute(t + ticks, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scheduler::enqueueAbsolute(u64 t, const EventType type) {
|
||||||
|
events.push({t, type});
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 Scheduler::remove(EventType type) {
|
||||||
|
auto copy = events;
|
||||||
|
while(!copy.empty()) {
|
||||||
|
if(copy.top().type == type) {
|
||||||
|
u64 ret = copy.top().time - ticks;
|
||||||
|
copy.pop();
|
||||||
|
events.swap(copy);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
copy.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scheduler::tick(u64 t, n64::Mem& mem, n64::Registers& regs) {
|
||||||
|
ticks += t;
|
||||||
|
n64::MI& mi = mem.mmio.mi;
|
||||||
|
n64::SI& si = mem.mmio.si;
|
||||||
|
n64::PI& pi = mem.mmio.pi;
|
||||||
|
|
||||||
|
while(ticks >= events.top().time) {
|
||||||
|
switch(events.top().type) {
|
||||||
|
case SI_DMA:
|
||||||
|
si.status.dmaBusy = false;
|
||||||
|
si.DMA(mem, regs);
|
||||||
|
InterruptRaise(mi, regs, n64::Interrupt::SI);
|
||||||
|
break;
|
||||||
|
case PI_DMA_COMPLETE:
|
||||||
|
InterruptRaise(mi, regs, n64::Interrupt::PI);
|
||||||
|
pi.dmaBusy = false;
|
||||||
|
break;
|
||||||
|
case PI_BUS_WRITE_COMPLETE:
|
||||||
|
pi.ioBusy = false;
|
||||||
|
break;
|
||||||
|
case NONE:
|
||||||
|
break;
|
||||||
|
case IMPOSSIBLE:
|
||||||
|
Util::panic("Congratulations on keeping the emulator on for about 5 billion years, I guess, nerd.");
|
||||||
|
default:
|
||||||
|
Util::panic("Unknown scheduler event type");
|
||||||
|
}
|
||||||
|
events.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <functional>
|
||||||
#include <log.hpp>
|
#include <log.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
@@ -8,9 +9,17 @@ struct Mem;
|
|||||||
struct Registers;
|
struct Registers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum EventType {
|
||||||
|
NONE,
|
||||||
|
PI_BUS_WRITE_COMPLETE,
|
||||||
|
PI_DMA_COMPLETE,
|
||||||
|
SI_DMA,
|
||||||
|
IMPOSSIBLE
|
||||||
|
};
|
||||||
|
|
||||||
struct Event {
|
struct Event {
|
||||||
u64 time = 0;
|
u64 time;
|
||||||
void(*handler)(n64::Mem&, n64::Registers&) = nullptr;
|
EventType type;
|
||||||
|
|
||||||
friend bool operator<(const Event& rhs, const Event& lhs) {
|
friend bool operator<(const Event& rhs, const Event& lhs) {
|
||||||
return rhs.time < lhs.time;
|
return rhs.time < lhs.time;
|
||||||
@@ -27,26 +36,14 @@ struct Event {
|
|||||||
|
|
||||||
struct Scheduler {
|
struct Scheduler {
|
||||||
Scheduler() {
|
Scheduler() {
|
||||||
enqueueAbsolute(Event{std::numeric_limits<u64>::max(), [](n64::Mem&, n64::Registers&) {
|
enqueueAbsolute(std::numeric_limits<u64>::max(), IMPOSSIBLE);
|
||||||
Util::panic("How the fuck did we get here?!");
|
|
||||||
}});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE void enqueueRelative(const Event& event) {
|
void enqueueRelative(u64, const EventType);
|
||||||
enqueueAbsolute({event.time + ticks, event.handler});
|
void enqueueAbsolute(u64, const EventType);
|
||||||
}
|
u64 remove(const EventType);
|
||||||
|
void tick(u64 t, n64::Mem&, n64::Registers&);
|
||||||
FORCE_INLINE void enqueueAbsolute(const Event& e) {
|
|
||||||
events.push(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCE_INLINE void tick(u64 t, n64::Mem& mem, n64::Registers& regs) {
|
|
||||||
ticks += t;
|
|
||||||
while(ticks >= events.top().time) {
|
|
||||||
events.top().handler(mem, regs);
|
|
||||||
events.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::priority_queue<Event, std::vector<Event>, std::greater<>> events;
|
std::priority_queue<Event, std::vector<Event>, std::greater<>> events;
|
||||||
u64 ticks = 0;
|
u64 ticks = 0;
|
||||||
u8 index = 0;
|
u8 index = 0;
|
||||||
|
|||||||
@@ -363,11 +363,12 @@ void Mem::Write8(Registers& regs, u32 paddr, u32 val) {
|
|||||||
Util::WriteAccess<u32>(mmio.rsp.dmem, mirrAddr, val);
|
Util::WriteAccess<u32>(mmio.rsp.dmem, mirrAddr, val);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case MMIO_REGION:
|
|
||||||
Util::panic("MMIO Write8!");
|
|
||||||
case REGION_CART:
|
case REGION_CART:
|
||||||
|
Util::debug("BusWrite8 @ {:08X} = {:02X}", paddr, val);
|
||||||
mmio.pi.BusWrite8(*this, paddr, val);
|
mmio.pi.BusWrite8(*this, paddr, val);
|
||||||
break;
|
break;
|
||||||
|
case MMIO_REGION:
|
||||||
|
Util::panic("MMIO Write8!");
|
||||||
case PIF_RAM_REGION:
|
case PIF_RAM_REGION:
|
||||||
val = val << (8 * (3 - (paddr & 3)));
|
val = val << (8 * (3 - (paddr & 3)));
|
||||||
paddr = (paddr - PIF_RAM_REGION_START) & ~3;
|
paddr = (paddr - PIF_RAM_REGION_START) & ~3;
|
||||||
@@ -411,6 +412,10 @@ void Mem::Write16(Registers& regs, u32 paddr, u32 val) {
|
|||||||
Util::WriteAccess<u32>(mmio.rsp.dmem, mirrAddr, val);
|
Util::WriteAccess<u32>(mmio.rsp.dmem, mirrAddr, val);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case REGION_CART:
|
||||||
|
Util::debug("BusWrite8 @ {:08X} = {:04X}", paddr, val);
|
||||||
|
mmio.pi.BusWrite16(*this, paddr, val);
|
||||||
|
break;
|
||||||
case MMIO_REGION:
|
case MMIO_REGION:
|
||||||
Util::panic("MMIO Write16!");
|
Util::panic("MMIO Write16!");
|
||||||
case PIF_RAM_REGION:
|
case PIF_RAM_REGION:
|
||||||
@@ -419,9 +424,6 @@ void Mem::Write16(Registers& regs, u32 paddr, u32 val) {
|
|||||||
Util::WriteAccess<u32>(si.pif.ram, paddr - PIF_RAM_REGION_START, htobe32(val));
|
Util::WriteAccess<u32>(si.pif.ram, paddr - PIF_RAM_REGION_START, htobe32(val));
|
||||||
si.pif.ProcessCommands(*this);
|
si.pif.ProcessCommands(*this);
|
||||||
break;
|
break;
|
||||||
case REGION_CART:
|
|
||||||
mmio.pi.BusWrite16(*this, paddr, val);
|
|
||||||
break;
|
|
||||||
case 0x00800000 ... 0x03FFFFFF:
|
case 0x00800000 ... 0x03FFFFFF:
|
||||||
case 0x04200000 ... 0x042FFFFF:
|
case 0x04200000 ... 0x042FFFFF:
|
||||||
case 0x04900000 ... 0x04FFFFFF:
|
case 0x04900000 ... 0x04FFFFFF:
|
||||||
@@ -457,6 +459,10 @@ void Mem::Write32(Registers& regs, u32 paddr, u32 val) {
|
|||||||
Util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
|
Util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case REGION_CART:
|
||||||
|
Util::debug("BusWrite8 @ {:08X} = {:08X}", paddr, val);
|
||||||
|
mmio.pi.BusWrite32(*this, paddr, val);
|
||||||
|
break;
|
||||||
case MMIO_REGION:
|
case MMIO_REGION:
|
||||||
mmio.Write(*this, regs, paddr, val);
|
mmio.Write(*this, regs, paddr, val);
|
||||||
break;
|
break;
|
||||||
@@ -470,9 +476,6 @@ void Mem::Write32(Registers& regs, u32 paddr, u32 val) {
|
|||||||
case PIF_ROM_REGION:
|
case PIF_ROM_REGION:
|
||||||
case 0x1FC00800 ... 0x7FFFFFFF:
|
case 0x1FC00800 ... 0x7FFFFFFF:
|
||||||
case 0x80000000 ... 0xFFFFFFFF: break;
|
case 0x80000000 ... 0xFFFFFFFF: break;
|
||||||
case REGION_CART:
|
|
||||||
mmio.pi.BusWrite32(*this, paddr, val);
|
|
||||||
break;
|
|
||||||
default: Util::panic("Unimplemented 32-bit write at address {:08X} with value {:0X} (PC = {:016X})", paddr, val, (u64)regs.pc);
|
default: Util::panic("Unimplemented 32-bit write at address {:08X} with value {:0X} (PC = {:016X})", paddr, val, (u64)regs.pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -500,15 +503,16 @@ void Mem::Write64(Registers& regs, u32 paddr, u64 val) {
|
|||||||
Util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
|
Util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case REGION_CART:
|
||||||
|
Util::debug("BusWrite8 @ {:08X} = {:016X}", paddr, val);
|
||||||
|
mmio.pi.BusWrite64(*this, paddr, val);
|
||||||
|
break;
|
||||||
case MMIO_REGION:
|
case MMIO_REGION:
|
||||||
Util::panic("MMIO Write64!");
|
Util::panic("MMIO Write64!");
|
||||||
case PIF_RAM_REGION:
|
case PIF_RAM_REGION:
|
||||||
Util::WriteAccess<u64>(si.pif.ram, paddr - PIF_RAM_REGION_START, htobe64(val));
|
Util::WriteAccess<u64>(si.pif.ram, paddr - PIF_RAM_REGION_START, htobe64(val));
|
||||||
si.pif.ProcessCommands(*this);
|
si.pif.ProcessCommands(*this);
|
||||||
break;
|
break;
|
||||||
case REGION_CART:
|
|
||||||
mmio.pi.BusWrite64(*this, paddr, val);
|
|
||||||
break;
|
|
||||||
case 0x00800000 ... 0x03FFFFFF:
|
case 0x00800000 ... 0x03FFFFFF:
|
||||||
case 0x04200000 ... 0x042FFFFF:
|
case 0x04200000 ... 0x042FFFFF:
|
||||||
case 0x04900000 ... 0x04FFFFFF:
|
case 0x04900000 ... 0x04FFFFFF:
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ void AI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AI::Step(Mem& mem, Registers& regs, int cpuCycles, float volumeL, float volumeR) {
|
void AI::Step(Mem& mem, Registers& regs, u32 cpuCycles, float volumeL, float volumeR) {
|
||||||
cycles += cpuCycles;
|
cycles += cpuCycles;
|
||||||
while(cycles > dac.period) {
|
while(cycles > dac.period) {
|
||||||
if (dmaCount == 0) {
|
if (dmaCount == 0) {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ struct AI {
|
|||||||
void Reset();
|
void Reset();
|
||||||
auto Read(u32) const -> u32;
|
auto Read(u32) const -> u32;
|
||||||
void Write(Mem&, Registers&, u32, u32);
|
void Write(Mem&, Registers&, u32, u32);
|
||||||
void Step(Mem&, Registers&, int, float, float);
|
void Step(Mem&, Registers&, u32, float, float);
|
||||||
bool dmaEnable{};
|
bool dmaEnable{};
|
||||||
u16 dacRate{};
|
u16 dacRate{};
|
||||||
u8 bitrate{};
|
u8 bitrate{};
|
||||||
@@ -19,7 +19,7 @@ struct AI {
|
|||||||
u32 dmaLen[2]{};
|
u32 dmaLen[2]{};
|
||||||
u32 dmaAddr[2]{};
|
u32 dmaAddr[2]{};
|
||||||
bool dmaAddrCarry{};
|
bool dmaAddrCarry{};
|
||||||
int cycles{};
|
u32 cycles{};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u32 freq{44100};
|
u32 freq{44100};
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
#include <core/mmio/PI.hpp>
|
#include <core/mmio/PI.hpp>
|
||||||
#include <log.hpp>
|
#include <log.hpp>
|
||||||
#include <core/Mem.hpp>
|
#include <Core.hpp>
|
||||||
#include <core/registers/Registers.hpp>
|
#include <Scheduler.hpp>
|
||||||
#include "Scheduler.hpp"
|
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
PI::PI() {
|
PI::PI() {
|
||||||
@@ -10,23 +9,59 @@ PI::PI() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PI::Reset() {
|
void PI::Reset() {
|
||||||
|
dmaBusy = false;
|
||||||
|
ioBusy = false;
|
||||||
|
latch = 0;
|
||||||
dramAddr = 0;
|
dramAddr = 0;
|
||||||
cartAddr = 0;
|
cartAddr = 0;
|
||||||
|
dramAddrInternal = 0;
|
||||||
|
cartAddrInternal = 0;
|
||||||
rdLen = 0;
|
rdLen = 0;
|
||||||
wrLen = 0;
|
wrLen = 0;
|
||||||
|
pi_bsd_dom1_lat = 0;
|
||||||
|
pi_bsd_dom2_lat = 0;
|
||||||
|
pi_bsd_dom1_pwd = 0;
|
||||||
|
pi_bsd_dom2_pwd = 0;
|
||||||
|
pi_bsd_dom1_pgs = 0;
|
||||||
|
pi_bsd_dom2_pgs = 0;
|
||||||
|
pi_bsd_dom1_rls = 0;
|
||||||
|
pi_bsd_dom2_rls = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PI::BusRead8(Mem& mem, u32 addr) const -> u8 {
|
bool PI::WriteLatch(u32 value) {
|
||||||
// TODO: Latch with CPU stall
|
if (ioBusy) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
ioBusy = true;
|
||||||
|
latch = value;
|
||||||
|
scheduler.enqueueRelative(100, PI_BUS_WRITE_COMPLETE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PI::ReadLatch() {
|
||||||
|
if (ioBusy) [[unlikely]] {
|
||||||
|
ioBusy = false;
|
||||||
|
CpuStall(scheduler.remove(PI_BUS_WRITE_COMPLETE));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PI::BusRead8(Mem& mem, u32 addr) -> u8 {
|
||||||
|
if (!ReadLatch()) [[unlikely]] {
|
||||||
|
return latch >> 24;
|
||||||
|
}
|
||||||
|
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case REGION_PI_UNKNOWN:
|
case REGION_PI_UNKNOWN:
|
||||||
Util::warn("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, returning FF because it is not emulated", addr);
|
//Util::warn("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, returning FF because it is not emulated", addr);
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
case REGION_PI_64DD_REG:
|
case REGION_PI_64DD_REG:
|
||||||
Util::warn("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, returning FF because it is not emulated", addr);
|
//Util::warn("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, returning FF because it is not emulated", addr);
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
case REGION_PI_64DD_ROM:
|
case REGION_PI_64DD_ROM:
|
||||||
Util::warn("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, returning FF because it is not emulated", addr);
|
//Util::warn("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, returning FF because it is not emulated", addr);
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
case REGION_PI_SRAM:
|
case REGION_PI_SRAM:
|
||||||
return mem.BackupRead8(addr - SREGION_PI_SRAM);
|
return mem.BackupRead8(addr - SREGION_PI_SRAM);
|
||||||
@@ -35,7 +70,7 @@ auto PI::BusRead8(Mem& mem, u32 addr) const -> u8 {
|
|||||||
addr = (addr + 2) & ~2;
|
addr = (addr + 2) & ~2;
|
||||||
u32 index = BYTE_ADDRESS(addr) - SREGION_PI_ROM;
|
u32 index = BYTE_ADDRESS(addr) - SREGION_PI_ROM;
|
||||||
if (index > mem.rom.size) {
|
if (index > mem.rom.size) {
|
||||||
Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr, index, index, mem.rom.size, mem.rom.size);
|
//Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr, index, index, mem.rom.size, mem.rom.size);
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
return mem.rom.cart[index];
|
return mem.rom.cart[index];
|
||||||
@@ -46,51 +81,59 @@ auto PI::BusRead8(Mem& mem, u32 addr) const -> u8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PI::BusWrite8(Mem& mem, u32 addr, u32 val) {
|
void PI::BusWrite8(Mem& mem, u32 addr, u32 val) {
|
||||||
|
int latch_shift = 24 - (addr & 1) * 8;
|
||||||
|
|
||||||
|
if (!WriteLatch(val << latch_shift) && addr != 0x05000020) [[unlikely]] {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case REGION_PI_UNKNOWN:
|
case REGION_PI_UNKNOWN:
|
||||||
Util::warn("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
|
//Util::warn("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
|
||||||
return;
|
return;
|
||||||
case REGION_PI_64DD_REG:
|
case REGION_PI_64DD_REG:
|
||||||
if (addr == 0x05000020) {
|
if (addr == 0x05000020) {
|
||||||
fprintf(stderr, "%c", val);
|
fprintf(stderr, "%c", val);
|
||||||
} else {
|
} else {
|
||||||
Util::warn("Writing byte 0x{:02X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", val, addr);
|
//Util::warn("Writing byte 0x{:02X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", val, addr);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case REGION_PI_64DD_ROM:
|
case REGION_PI_64DD_ROM:
|
||||||
Util::warn("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr);
|
//Util::warn("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr);
|
||||||
return;
|
return;
|
||||||
case REGION_PI_SRAM:
|
case REGION_PI_SRAM:
|
||||||
mem.BackupWrite8(addr - SREGION_PI_SRAM, val);
|
mem.BackupWrite8(addr - SREGION_PI_SRAM, val);
|
||||||
return;
|
return;
|
||||||
case REGION_PI_ROM:
|
case REGION_PI_ROM:
|
||||||
Util::warn("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
|
//Util::warn("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr);
|
Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PI::BusRead16(Mem& mem, u32 addr) const -> u16 {
|
auto PI::BusRead16(Mem& mem, u32 addr) -> u16 {
|
||||||
// TODO: Latch with CPU stall
|
if (!ReadLatch()) [[unlikely]] {
|
||||||
|
return latch >> 16;
|
||||||
|
}
|
||||||
|
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case REGION_PI_UNKNOWN:
|
case REGION_PI_UNKNOWN:
|
||||||
Util::warn("Reading half from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, returning FF because it is not emulated", addr);
|
//Util::warn("Reading half from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, returning FF because it is not emulated", addr);
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
case REGION_PI_64DD_REG:
|
case REGION_PI_64DD_REG:
|
||||||
Util::warn("Reading half from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, returning FF because it is not emulated", addr);
|
//Util::warn("Reading half from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, returning FF because it is not emulated", addr);
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
case REGION_PI_64DD_ROM:
|
case REGION_PI_64DD_ROM:
|
||||||
Util::warn("Reading half from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, returning FF because it is not emulated", addr);
|
//Util::warn("Reading half from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, returning FF because it is not emulated", addr);
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
case REGION_PI_SRAM:
|
case REGION_PI_SRAM:
|
||||||
Util::panic("Reading half from address 0x{:08X} in unsupported region: REGION_PI_SRAM", addr);
|
Util::panic("Reading half from address 0x{:08X} in unsupported region: REGION_PI_SRAM", addr);
|
||||||
case REGION_PI_ROM: {
|
case REGION_PI_ROM: {
|
||||||
// round to nearest 4 byte boundary, keeping old LSB
|
|
||||||
addr = (addr + 2) & ~3;
|
addr = (addr + 2) & ~3;
|
||||||
u32 index = HALF_ADDRESS(addr) - SREGION_PI_ROM;
|
u32 index = HALF_ADDRESS(addr) - SREGION_PI_ROM;
|
||||||
if (index > mem.rom.size - 1) {
|
if (index > mem.rom.size - 1) {
|
||||||
Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr, index, index, mem.rom.size, mem.rom.size);
|
//Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr, index, index, mem.rom.size, mem.rom.size);
|
||||||
return 0xFFFF;
|
return 0xFFFF;
|
||||||
}
|
}
|
||||||
return Util::ReadAccess<u16>(mem.rom.cart, index);
|
return Util::ReadAccess<u16>(mem.rom.cart, index);
|
||||||
@@ -101,38 +144,45 @@ auto PI::BusRead16(Mem& mem, u32 addr) const -> u16 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PI::BusWrite16(Mem& mem, u32 addr, u16 val) {
|
void PI::BusWrite16(Mem& mem, u32 addr, u16 val) {
|
||||||
|
if (!WriteLatch(val << 16)) [[unlikely]] {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case REGION_PI_UNKNOWN:
|
case REGION_PI_UNKNOWN:
|
||||||
Util::warn("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
|
//Util::warn("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
|
||||||
return;
|
return;
|
||||||
case REGION_PI_64DD_REG:
|
case REGION_PI_64DD_REG:
|
||||||
Util::warn("Writing half 0x{:04X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", val, addr);
|
//Util::warn("Writing half 0x{:04X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", val, addr);
|
||||||
return;
|
return;
|
||||||
case REGION_PI_64DD_ROM:
|
case REGION_PI_64DD_ROM:
|
||||||
Util::warn("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr);
|
//Util::warn("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr);
|
||||||
return;
|
return;
|
||||||
case REGION_PI_SRAM:
|
case REGION_PI_SRAM:
|
||||||
Util::warn("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_SRAM", val, addr);
|
//Util::warn("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_SRAM", val, addr);
|
||||||
return;
|
return;
|
||||||
case REGION_PI_ROM:
|
case REGION_PI_ROM:
|
||||||
Util::warn("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
|
//Util::warn("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr);
|
Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PI::BusRead32(Mem& mem, u32 addr) const -> u32 {
|
auto PI::BusRead32(Mem& mem, u32 addr) -> u32 {
|
||||||
// TODO: Latch with CPU stall
|
if (!ReadLatch()) [[unlikely]] {
|
||||||
|
return latch;
|
||||||
|
}
|
||||||
|
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case REGION_PI_UNKNOWN:
|
case REGION_PI_UNKNOWN:
|
||||||
Util::warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, returning FF because it is not emulated", addr);
|
//Util::warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, returning FF because it is not emulated", addr);
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
case REGION_PI_64DD_REG:
|
case REGION_PI_64DD_REG:
|
||||||
Util::warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, returning FF because it is not emulated", addr);
|
//Util::warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, returning FF because it is not emulated", addr);
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
case REGION_PI_64DD_ROM:
|
case REGION_PI_64DD_ROM:
|
||||||
Util::warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, returning FF because it is not emulated", addr);
|
//Util::warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, returning FF because it is not emulated", addr);
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
case REGION_PI_SRAM:
|
case REGION_PI_SRAM:
|
||||||
return mem.BackupRead32(addr - SREGION_PI_SRAM);
|
return mem.BackupRead32(addr - SREGION_PI_SRAM);
|
||||||
@@ -145,7 +195,7 @@ auto PI::BusRead32(Mem& mem, u32 addr) const -> u32 {
|
|||||||
case CART_ISVIEWER_FLUSH:
|
case CART_ISVIEWER_FLUSH:
|
||||||
Util::panic("Read from ISViewer flush!");
|
Util::panic("Read from ISViewer flush!");
|
||||||
}
|
}
|
||||||
Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index, index);
|
//Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index, index);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return Util::ReadAccess<u32>(mem.rom.cart, index);
|
return Util::ReadAccess<u32>(mem.rom.cart, index);
|
||||||
@@ -159,15 +209,27 @@ auto PI::BusRead32(Mem& mem, u32 addr) const -> u32 {
|
|||||||
void PI::BusWrite32(Mem& mem, u32 addr, u32 val) {
|
void PI::BusWrite32(Mem& mem, u32 addr, u32 val) {
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case REGION_PI_UNKNOWN:
|
case REGION_PI_UNKNOWN:
|
||||||
Util::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
|
if (!WriteLatch(val)) [[unlikely]] {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//Util::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
|
||||||
return;
|
return;
|
||||||
case REGION_PI_64DD_REG:
|
case REGION_PI_64DD_REG:
|
||||||
Util::warn("Writing word 0x{:08X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", val, addr);
|
if (!WriteLatch(val)) [[unlikely]] {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//Util::warn("Writing word 0x{:08X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", val, addr);
|
||||||
return;
|
return;
|
||||||
case REGION_PI_64DD_ROM:
|
case REGION_PI_64DD_ROM:
|
||||||
Util::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr);
|
if (!WriteLatch(val)) [[unlikely]] {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//Util::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr);
|
||||||
return;
|
return;
|
||||||
case REGION_PI_SRAM:
|
case REGION_PI_SRAM:
|
||||||
|
if (!WriteLatch(val)) [[unlikely]] {
|
||||||
|
return;
|
||||||
|
}
|
||||||
mem.BackupWrite32(addr - SREGION_PI_SRAM, val);
|
mem.BackupWrite32(addr - SREGION_PI_SRAM, val);
|
||||||
return;
|
return;
|
||||||
case REGION_PI_ROM:
|
case REGION_PI_ROM:
|
||||||
@@ -188,7 +250,10 @@ void PI::BusWrite32(Mem& mem, u32 addr, u32 val) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
Util::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
|
if (!WriteLatch(val)) [[unlikely]] {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//Util::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
@@ -196,19 +261,23 @@ void PI::BusWrite32(Mem& mem, u32 addr, u32 val) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PI::BusRead64(Mem& mem, u32 addr) const -> u64 {
|
auto PI::BusRead64(Mem& mem, u32 addr) -> u64 {
|
||||||
|
if (!ReadLatch()) [[unlikely]] {
|
||||||
|
return (u64)latch << 32;
|
||||||
|
}
|
||||||
|
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case REGION_PI_UNKNOWN:
|
case REGION_PI_UNKNOWN:
|
||||||
Util::warn("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", addr);
|
//Util::warn("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", addr);
|
||||||
return 0xFFFFFFFFFFFFFFFF;
|
return 0xFFFFFFFFFFFFFFFF;
|
||||||
case REGION_PI_64DD_REG:
|
case REGION_PI_64DD_REG:
|
||||||
Util::warn("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG", addr);
|
//Util::warn("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG", addr);
|
||||||
return 0xFFFFFFFFFFFFFFFF;
|
return 0xFFFFFFFFFFFFFFFF;
|
||||||
case REGION_PI_64DD_ROM:
|
case REGION_PI_64DD_ROM:
|
||||||
Util::warn("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", addr);
|
//Util::warn("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", addr);
|
||||||
return 0xFFFFFFFFFFFFFFFF;
|
return 0xFFFFFFFFFFFFFFFF;
|
||||||
case REGION_PI_SRAM:
|
case REGION_PI_SRAM:
|
||||||
Util::warn("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_SRAM", addr);
|
//Util::warn("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_SRAM", addr);
|
||||||
return 0xFFFFFFFFFFFFFFFF;
|
return 0xFFFFFFFFFFFFFFFF;
|
||||||
case REGION_PI_ROM: {
|
case REGION_PI_ROM: {
|
||||||
u32 index = addr - SREGION_PI_ROM;
|
u32 index = addr - SREGION_PI_ROM;
|
||||||
@@ -223,6 +292,10 @@ auto PI::BusRead64(Mem& mem, u32 addr) const -> u64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PI::BusWrite64(Mem& mem, u32 addr, u64 val) {
|
void PI::BusWrite64(Mem& mem, u32 addr, u64 val) {
|
||||||
|
if (!WriteLatch(val >> 32)) [[unlikely]] {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case REGION_PI_UNKNOWN:
|
case REGION_PI_UNKNOWN:
|
||||||
Util::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
|
Util::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
|
||||||
@@ -233,7 +306,7 @@ void PI::BusWrite64(Mem& mem, u32 addr, u64 val) {
|
|||||||
case REGION_PI_SRAM:
|
case REGION_PI_SRAM:
|
||||||
Util::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_SRAM", val, addr);
|
Util::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_SRAM", val, addr);
|
||||||
case REGION_PI_ROM:
|
case REGION_PI_ROM:
|
||||||
Util::warn("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
|
//Util::warn("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Util::panic("Should never end up here! Access to address %08X which did not match any PI bus regions!", addr);
|
Util::panic("Should never end up here! Access to address %08X which did not match any PI bus regions!", addr);
|
||||||
@@ -248,8 +321,8 @@ auto PI::Read(MI& mi, u32 addr) const -> u32 {
|
|||||||
case 0x0460000C: return wrLen;
|
case 0x0460000C: return wrLen;
|
||||||
case 0x04600010: {
|
case 0x04600010: {
|
||||||
u32 value = 0;
|
u32 value = 0;
|
||||||
value |= (0 << dmaBusy); // Is PI DMA active? No, because it's instant
|
value |= (dmaBusy << 0); // Is PI DMA active? No, because it's instant
|
||||||
value |= (0 << ioBusy); // Is PI IO busy? No, because it's instant
|
value |= (ioBusy << 1); // Is PI IO busy? No, because it's instant
|
||||||
value |= (0 << 2); // PI IO error?
|
value |= (0 << 2); // PI IO error?
|
||||||
value |= (mi.miIntr.pi << 3); // PI interrupt?
|
value |= (mi.miIntr.pi << 3); // PI interrupt?
|
||||||
return value;
|
return value;
|
||||||
@@ -314,23 +387,6 @@ FORCE_INLINE u32 PIAccessTiming(PI& pi, u8 domain, u32 length) {
|
|||||||
return cycles * 1.5; // Converting RCP clock speed to CPU clock speed
|
return cycles * 1.5; // Converting RCP clock speed to CPU clock speed
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool toCart>
|
|
||||||
FORCE_INLINE void OnDMAComplete(Mem& mem, Registers& regs) {
|
|
||||||
PI& pi = mem.mmio.pi;
|
|
||||||
u32 len;
|
|
||||||
if constexpr (toCart) {
|
|
||||||
len = pi.rdLen;
|
|
||||||
} else {
|
|
||||||
len = pi.wrLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
pi.dramAddr = pi.dramAddrInternal + len;
|
|
||||||
pi.cartAddr = pi.cartAddrInternal + len;
|
|
||||||
pi.dmaBusy = false;
|
|
||||||
pi.ioBusy = false;
|
|
||||||
InterruptRaise(mem.mmio.mi, regs, Interrupt::PI);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
||||||
MI& mi = mem.mmio.mi;
|
MI& mi = mem.mmio.mi;
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
@@ -349,8 +405,8 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
|||||||
}
|
}
|
||||||
Util::trace("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr);
|
Util::trace("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr);
|
||||||
dmaBusy = true;
|
dmaBusy = true;
|
||||||
ioBusy = true;
|
toCart = true;
|
||||||
scheduler.enqueueRelative(Event{PIAccessTiming(*this, PIGetDomain(cartAddr), len), OnDMAComplete<true>});
|
scheduler.enqueueRelative(PIAccessTiming(*this, PIGetDomain(cartAddr), len), PI_DMA_COMPLETE);
|
||||||
} break;
|
} break;
|
||||||
case 0x0460000C: {
|
case 0x0460000C: {
|
||||||
u32 len = (val & 0x00FFFFFF) + 1;
|
u32 len = (val & 0x00FFFFFF) + 1;
|
||||||
@@ -364,9 +420,9 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
|||||||
mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE] = mem.rom.cart[BYTE_ADDRESS(cartAddrInternal + i) & mem.rom.mask];
|
mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE] = mem.rom.cart[BYTE_ADDRESS(cartAddrInternal + i) & mem.rom.mask];
|
||||||
}
|
}
|
||||||
dmaBusy = true;
|
dmaBusy = true;
|
||||||
ioBusy = true;
|
|
||||||
Util::trace("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr);
|
Util::trace("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr);
|
||||||
scheduler.enqueueRelative(Event{PIAccessTiming(*this, PIGetDomain(cartAddr), len), OnDMAComplete<false>});
|
toCart = false;
|
||||||
|
scheduler.enqueueRelative(PIAccessTiming(*this, PIGetDomain(cartAddr), len), PI_DMA_COMPLETE);
|
||||||
} break;
|
} break;
|
||||||
case 0x04600010:
|
case 0x04600010:
|
||||||
if(val & 2) {
|
if(val & 2) {
|
||||||
|
|||||||
@@ -12,15 +12,18 @@ struct PI {
|
|||||||
void Reset();
|
void Reset();
|
||||||
auto Read(MI&, u32) const -> u32;
|
auto Read(MI&, u32) const -> u32;
|
||||||
void Write(Mem&, Registers&, u32, u32);
|
void Write(Mem&, Registers&, u32, u32);
|
||||||
auto BusRead8(Mem&, u32) const -> u8;
|
auto BusRead8(Mem&, u32) -> u8;
|
||||||
void BusWrite8(Mem&, u32, u32);
|
void BusWrite8(Mem&, u32, u32);
|
||||||
auto BusRead16(Mem&, u32) const -> u16;
|
auto BusRead16(Mem&, u32) -> u16;
|
||||||
void BusWrite16(Mem&, u32, u16);
|
void BusWrite16(Mem&, u32, u16);
|
||||||
auto BusRead32(Mem&, u32) const -> u32;
|
auto BusRead32(Mem&, u32) -> u32;
|
||||||
void BusWrite32(Mem&, u32, u32);
|
void BusWrite32(Mem&, u32, u32);
|
||||||
auto BusRead64(Mem&, u32) const -> u64;
|
auto BusRead64(Mem&, u32) -> u64;
|
||||||
void BusWrite64(Mem&, u32, u64);
|
void BusWrite64(Mem&, u32, u64);
|
||||||
bool dmaBusy{}, ioBusy{};
|
bool ReadLatch();
|
||||||
|
bool WriteLatch(u32 val);
|
||||||
|
bool dmaBusy{}, ioBusy{}, toCart{};
|
||||||
|
u32 latch;
|
||||||
u32 dramAddr{}, cartAddr{}, dramAddrInternal{}, cartAddrInternal{};
|
u32 dramAddr{}, cartAddr{}, dramAddrInternal{}, cartAddrInternal{};
|
||||||
u32 rdLen{}, wrLen{};
|
u32 rdLen{}, wrLen{};
|
||||||
u32 pi_bsd_dom1_lat{}, pi_bsd_dom2_lat{};
|
u32 pi_bsd_dom1_lat{}, pi_bsd_dom2_lat{};
|
||||||
|
|||||||
@@ -32,11 +32,10 @@ auto SI::Read(MI& mi, u32 addr) const -> u32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool toDram>
|
void SI::DMA(Mem& mem, Registers& regs) {
|
||||||
FORCE_INLINE void DMA(Mem& mem, Registers& regs) {
|
|
||||||
SI& si = mem.mmio.si;
|
SI& si = mem.mmio.si;
|
||||||
si.status.dmaBusy = false;
|
si.status.dmaBusy = false;
|
||||||
if constexpr(toDram) {
|
if (toDram) {
|
||||||
si.pif.ProcessCommands(mem);
|
si.pif.ProcessCommands(mem);
|
||||||
for(int i = 0; i < 64; i++) {
|
for(int i = 0; i < 64; i++) {
|
||||||
mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)] = si.pif.Read(si.pifAddr + i);
|
mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)] = si.pif.Read(si.pifAddr + i);
|
||||||
@@ -60,12 +59,14 @@ void SI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
|||||||
case 0x04800004: {
|
case 0x04800004: {
|
||||||
pifAddr = val & 0x1FFFFFFF;
|
pifAddr = val & 0x1FFFFFFF;
|
||||||
status.dmaBusy = true;
|
status.dmaBusy = true;
|
||||||
scheduler.enqueueRelative({SI_DMA_DELAY, DMA<true>});
|
toDram = true;
|
||||||
|
scheduler.enqueueRelative(SI_DMA_DELAY, SI_DMA);
|
||||||
} break;
|
} break;
|
||||||
case 0x04800010: {
|
case 0x04800010: {
|
||||||
pifAddr = val & 0x1FFFFFFF;
|
pifAddr = val & 0x1FFFFFFF;
|
||||||
status.dmaBusy = true;
|
status.dmaBusy = true;
|
||||||
scheduler.enqueueRelative({SI_DMA_DELAY, DMA<false>});
|
toDram = false;
|
||||||
|
scheduler.enqueueRelative(SI_DMA_DELAY, SI_DMA);
|
||||||
} break;
|
} break;
|
||||||
case 0x04800018:
|
case 0x04800018:
|
||||||
InterruptLower(mem.mmio.mi, regs, Interrupt::SI);
|
InterruptLower(mem.mmio.mi, regs, Interrupt::SI);
|
||||||
|
|||||||
@@ -26,9 +26,11 @@ struct SI {
|
|||||||
SIStatus status{};
|
SIStatus status{};
|
||||||
u32 dramAddr{};
|
u32 dramAddr{};
|
||||||
u32 pifAddr{};
|
u32 pifAddr{};
|
||||||
|
bool toDram = false;
|
||||||
|
|
||||||
auto Read(MI&, u32) const -> u32;
|
auto Read(MI&, u32) const -> u32;
|
||||||
void Write(Mem&, Registers&, u32, u32);
|
void Write(Mem&, Registers&, u32, u32);
|
||||||
|
void DMA(Mem&, Registers&);
|
||||||
PIF pif;
|
PIF pif;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user