SAZDFsdff
This commit is contained in:
@@ -96,7 +96,54 @@ u32 Interpreter::Step() {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Interpreter::CacheBlock(u32 addr) {
|
bool Interpreter::DetectIdleLoop(const std::array<Instruction, MAX_INSTR_PER_BLOCK> &code, u32 len, u32 blockAddr) {
|
||||||
|
if (!Core::GetInstance().idleSkip)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
u32 lastInstructionIndex = len - 1;
|
||||||
|
auto delay = code[lastInstructionIndex];
|
||||||
|
|
||||||
|
if (len == 2) {
|
||||||
|
// branch or jump to itself
|
||||||
|
// _nop
|
||||||
|
|
||||||
|
auto branch = code[lastInstructionIndex - 1];
|
||||||
|
return ((branch.IsBranch() && branch.offset() == -4) || (branch.target() == ((blockAddr >> 2) & 0x3FFFFFF))) &&
|
||||||
|
delay.instr.raw == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 3) {
|
||||||
|
// load reg1, [some location]
|
||||||
|
// bcond reg2
|
||||||
|
// _andi reg2, reg1, immediate
|
||||||
|
|
||||||
|
auto branch = code[lastInstructionIndex - 1];
|
||||||
|
auto load = code[lastInstructionIndex - 2]; // load
|
||||||
|
|
||||||
|
return (load.opcode() == Instruction::LW || load.opcode() == Instruction::LWU) &&
|
||||||
|
delay.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -8 &&
|
||||||
|
load.rt() == delay.rs() && delay.rt() == branch.rs();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 4) {
|
||||||
|
// load reg2, [reg1(offset)]
|
||||||
|
// andi reg3, reg2, immediate
|
||||||
|
// bcond reg3, reg4
|
||||||
|
// _nop
|
||||||
|
|
||||||
|
auto branch = code[lastInstructionIndex - 1];
|
||||||
|
auto andi = code[lastInstructionIndex - 2]; // andi
|
||||||
|
auto load = code[lastInstructionIndex - 3]; // load
|
||||||
|
|
||||||
|
return (load.opcode() == Instruction::LW || load.opcode() == Instruction::LWU) &&
|
||||||
|
andi.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -12 &&
|
||||||
|
load.rt() == andi.rs() && andi.rt() == branch.rs();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 Interpreter::CacheBlock(u64 addr) {
|
||||||
u32 blockAddr = addr;
|
u32 blockAddr = addr;
|
||||||
|
|
||||||
CachedLine<Instruction> line;
|
CachedLine<Instruction> line;
|
||||||
@@ -104,7 +151,9 @@ u32 Interpreter::CacheBlock(u32 addr) {
|
|||||||
bool fetchDelaySlot = false;
|
bool fetchDelaySlot = false;
|
||||||
|
|
||||||
for (i = 0; i < MAX_INSTR_PER_BLOCK; i++) {
|
for (i = 0; i < MAX_INSTR_PER_BLOCK; i++) {
|
||||||
Instruction instr = mem.Read<u32>(addr);
|
Instruction instr;
|
||||||
|
if (!Fetch(instr, addr))
|
||||||
|
return i + 1;
|
||||||
|
|
||||||
addr += 4;
|
addr += 4;
|
||||||
line.code[i] = instr;
|
line.code[i] = instr;
|
||||||
@@ -127,46 +176,7 @@ u32 Interpreter::CacheBlock(u32 addr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Core::GetInstance().idleSkip) {
|
line.idleSkip = DetectIdleLoop(line.code, i, blockAddr);
|
||||||
auto delay = line.code[i - 1];
|
|
||||||
|
|
||||||
if (i == 2) {
|
|
||||||
// branch to itself
|
|
||||||
// _nop
|
|
||||||
|
|
||||||
auto branch = line.code[i - 2];
|
|
||||||
line.idleSkip = branch.IsBranch() && branch.offset() == -4 && delay.instr.raw == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == 3) {
|
|
||||||
// load reg1, [some location]
|
|
||||||
// bcond reg2
|
|
||||||
// _andi reg2, reg1, immediate
|
|
||||||
|
|
||||||
auto branch = line.code[i - 2];
|
|
||||||
auto load = line.code[i - 3]; // load
|
|
||||||
|
|
||||||
line.idleSkip = (load.opcode() == Instruction::LW || load.opcode() == Instruction::LWU) &&
|
|
||||||
delay.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -8 &&
|
|
||||||
load.rt() == delay.rs() && delay.rt() == branch.rs();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == 4) {
|
|
||||||
// load reg2, [reg1(offset)]
|
|
||||||
// andi reg3, reg2, immediate
|
|
||||||
// bcond reg3, reg4
|
|
||||||
// _nop
|
|
||||||
|
|
||||||
auto branch = line.code[i - 2];
|
|
||||||
auto andi = line.code[i - 3]; // andi
|
|
||||||
auto load = line.code[i - 4]; // load
|
|
||||||
|
|
||||||
line.idleSkip = (load.opcode() == Instruction::LW || load.opcode() == Instruction::LWU) &&
|
|
||||||
andi.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -12 &&
|
|
||||||
load.rt() == andi.rs() && andi.rt() == branch.rs();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
line.cycles = i;
|
line.cycles = i;
|
||||||
line.len = i;
|
line.len = i;
|
||||||
cachedState.blocks[CACHE_GET_BLOCK(blockAddr)]->lines[CACHE_GET_LINE(blockAddr)] = new CachedLine(line);
|
cachedState.blocks[CACHE_GET_BLOCK(blockAddr)]->lines[CACHE_GET_LINE(blockAddr)] = new CachedLine(line);
|
||||||
@@ -175,21 +185,15 @@ u32 Interpreter::CacheBlock(u32 addr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32 Interpreter::ExecuteCached() {
|
u32 Interpreter::ExecuteCached() {
|
||||||
u32 addr;
|
u64 addr = regs.pc;
|
||||||
auto &blocks = cachedState.blocks;
|
auto &blocks = cachedState.blocks;
|
||||||
|
|
||||||
if (!regs.cop0.MapVAddr(Cop0::LOAD, regs.pc, addr)) {
|
if (!blocks[CACHE_GET_BLOCK((u32)addr)]) {
|
||||||
regs.cop0.HandleTLBException(regs.pc);
|
blocks[CACHE_GET_BLOCK((u32)addr)] = new CachedBlock<Instruction>(cachedState.MAX_LINES / 4);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.pc);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!blocks[CACHE_GET_BLOCK(addr)]) {
|
|
||||||
blocks[CACHE_GET_BLOCK(addr)] = new CachedBlock<Instruction>(cachedState.MAX_LINES / 4);
|
|
||||||
return CacheBlock(addr);
|
return CacheBlock(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto line = blocks[CACHE_GET_BLOCK(addr)]->lines[CACHE_GET_LINE(addr)];
|
const auto line = blocks[CACHE_GET_BLOCK((u32)addr)]->lines[CACHE_GET_LINE((u32)addr)];
|
||||||
if (line) {
|
if (line) {
|
||||||
cachedState.exception = false;
|
cachedState.exception = false;
|
||||||
// i copy the block cycles here in case the block evicts itself when executing which would set the cycles to
|
// i copy the block cycles here in case the block evicts itself when executing which would set the cycles to
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ struct Interpreter final {
|
|||||||
u32 ExecuteCached();
|
u32 ExecuteCached();
|
||||||
bool FetchThenMaybeAdvance(Instruction &);
|
bool FetchThenMaybeAdvance(Instruction &);
|
||||||
bool MaybeAdvance();
|
bool MaybeAdvance();
|
||||||
u32 CacheBlock(u32 addr);
|
u32 CacheBlock(u64 addr);
|
||||||
|
bool DetectIdleLoop(const std::array<Instruction, MAX_INSTR_PER_BLOCK> &, u32, u32);
|
||||||
|
|
||||||
void SignalException(u32 addr) { cachedState.exception = true; }
|
void SignalException(u32 addr) { cachedState.exception = true; }
|
||||||
|
|
||||||
|
|||||||
@@ -278,7 +278,6 @@ void Mem::Write<u8>(u32 paddr, u32 val) {
|
|||||||
|
|
||||||
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
|
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
|
||||||
mmio.rdp.WriteRDRAM<u8>(paddr, val);
|
mmio.rdp.WriteRDRAM<u8>(paddr, val);
|
||||||
Core::GetInstance().interpreter.cachedState.EvictCachedBlock(paddr);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
|
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
|
||||||
@@ -325,7 +324,6 @@ void Mem::Write<u16>(u32 paddr, u32 val) {
|
|||||||
|
|
||||||
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
|
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
|
||||||
mmio.rdp.WriteRDRAM<u16>(paddr, val);
|
mmio.rdp.WriteRDRAM<u16>(paddr, val);
|
||||||
Core::GetInstance().interpreter.cachedState.EvictCachedBlock(paddr);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
|
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
|
||||||
@@ -372,7 +370,6 @@ void Mem::Write<u32>(const u32 paddr, const u32 val) {
|
|||||||
|
|
||||||
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
|
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
|
||||||
mmio.rdp.WriteRDRAM<u32>(paddr, val);
|
mmio.rdp.WriteRDRAM<u32>(paddr, val);
|
||||||
Core::GetInstance().interpreter.cachedState.EvictCachedBlock(paddr);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
|
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
|
||||||
@@ -416,7 +413,6 @@ void Mem::Write(const u32 paddr, u64 val) {
|
|||||||
|
|
||||||
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
|
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
|
||||||
mmio.rdp.WriteRDRAM<u64>(paddr, val);
|
mmio.rdp.WriteRDRAM<u64>(paddr, val);
|
||||||
Core::GetInstance().interpreter.cachedState.EvictCachedBlock(paddr);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
|
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
|
||||||
|
|||||||
@@ -117,7 +117,6 @@ void RSP::DMA<true>() {
|
|||||||
for (u32 j = 0; j < length; j++) {
|
for (u32 j = 0; j < length; j++) {
|
||||||
mem.mmio.rdp.WriteRDRAM<u8>(BYTE_ADDRESS(dram_address + j), src[(mem_address + j) & DMEM_DSIZE]);
|
mem.mmio.rdp.WriteRDRAM<u8>(BYTE_ADDRESS(dram_address + j), src[(mem_address + j) & DMEM_DSIZE]);
|
||||||
}
|
}
|
||||||
Core::GetInstance().interpreter.cachedState.EvictCachedBlocksRange(dram_address, dram_address + length);
|
|
||||||
|
|
||||||
const int skip = i == spDMALen.count ? 0 : spDMALen.skip;
|
const int skip = i == spDMALen.count ? 0 : spDMALen.skip;
|
||||||
|
|
||||||
|
|||||||
@@ -1310,6 +1310,7 @@ void Cop1::swc1(const Instruction instr) {
|
|||||||
regs.cop0.HandleTLBException(addr);
|
regs.cop0.HandleTLBException(addr);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
||||||
} else {
|
} else {
|
||||||
|
Core::GetInstance().interpreter.cachedState.EvictCachedBlock(addr);
|
||||||
mem.Write<u32>(physical, FGR_T<u32>(regs.cop0.status, instr.ft()));
|
mem.Write<u32>(physical, FGR_T<u32>(regs.cop0.status, instr.ft()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1337,6 +1338,7 @@ void Cop1::sdc1(const Instruction instr) {
|
|||||||
regs.cop0.HandleTLBException(addr);
|
regs.cop0.HandleTLBException(addr);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
||||||
} else {
|
} else {
|
||||||
|
Core::GetInstance().interpreter.cachedState.EvictCachedBlock(addr);
|
||||||
mem.Write(physical, FGR_T<u64>(regs.cop0.status, instr.ft()));
|
mem.Write(physical, FGR_T<u64>(regs.cop0.status, instr.ft()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -409,6 +409,7 @@ void Interpreter::sb(const Instruction instr) {
|
|||||||
regs.cop0.HandleTLBException(address);
|
regs.cop0.HandleTLBException(address);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
||||||
} else {
|
} else {
|
||||||
|
cachedState.EvictCachedBlock(address);
|
||||||
mem.Write<u8>(paddr, regs.Read<s64>(instr.rt()));
|
mem.Write<u8>(paddr, regs.Read<s64>(instr.rt()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -432,6 +433,7 @@ void Interpreter::sc(const Instruction instr) {
|
|||||||
regs.cop0.HandleTLBException(address);
|
regs.cop0.HandleTLBException(address);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
||||||
} else {
|
} else {
|
||||||
|
cachedState.EvictCachedBlock(address);
|
||||||
mem.Write<u32>(paddr, regs.Read<s64>(instr.rt()));
|
mem.Write<u32>(paddr, regs.Read<s64>(instr.rt()));
|
||||||
regs.Write(instr.rt(), 1);
|
regs.Write(instr.rt(), 1);
|
||||||
}
|
}
|
||||||
@@ -464,6 +466,7 @@ void Interpreter::scd(const Instruction instr) {
|
|||||||
regs.cop0.HandleTLBException(address);
|
regs.cop0.HandleTLBException(address);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
||||||
} else {
|
} else {
|
||||||
|
cachedState.EvictCachedBlock(address);
|
||||||
mem.Write<u32>(paddr, regs.Read<s64>(instr.rt()));
|
mem.Write<u32>(paddr, regs.Read<s64>(instr.rt()));
|
||||||
regs.Write(instr.rt(), 1);
|
regs.Write(instr.rt(), 1);
|
||||||
}
|
}
|
||||||
@@ -480,6 +483,7 @@ void Interpreter::sh(const Instruction instr) {
|
|||||||
regs.cop0.HandleTLBException(address);
|
regs.cop0.HandleTLBException(address);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
||||||
} else {
|
} else {
|
||||||
|
cachedState.EvictCachedBlock(address);
|
||||||
mem.Write<u16>(physical, regs.Read<s64>(instr.rt()));
|
mem.Write<u16>(physical, regs.Read<s64>(instr.rt()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -498,6 +502,7 @@ void Interpreter::sw(const Instruction instr) {
|
|||||||
regs.cop0.HandleTLBException(address);
|
regs.cop0.HandleTLBException(address);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
||||||
} else {
|
} else {
|
||||||
|
cachedState.EvictCachedBlock(address);
|
||||||
mem.Write<u32>(physical, regs.Read<s64>(instr.rt()));
|
mem.Write<u32>(physical, regs.Read<s64>(instr.rt()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -515,6 +520,7 @@ void Interpreter::sd(const Instruction instr) {
|
|||||||
regs.cop0.HandleTLBException(address);
|
regs.cop0.HandleTLBException(address);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
||||||
} else {
|
} else {
|
||||||
|
cachedState.EvictCachedBlock(address);
|
||||||
mem.Write(physical, regs.Read<s64>(instr.rt()));
|
mem.Write(physical, regs.Read<s64>(instr.rt()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -531,6 +537,7 @@ void Interpreter::sdl(const Instruction instr) {
|
|||||||
const u64 data = mem.Read<u64>(paddr & ~7);
|
const u64 data = mem.Read<u64>(paddr & ~7);
|
||||||
const u64 rt = regs.Read<s64>(instr.rt());
|
const u64 rt = regs.Read<s64>(instr.rt());
|
||||||
mem.Write(paddr & ~7, (data & ~mask) | (rt >> shift));
|
mem.Write(paddr & ~7, (data & ~mask) | (rt >> shift));
|
||||||
|
cachedState.EvictCachedBlock(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,6 +553,7 @@ void Interpreter::sdr(const Instruction instr) {
|
|||||||
const u64 data = mem.Read<u64>(paddr & ~7);
|
const u64 data = mem.Read<u64>(paddr & ~7);
|
||||||
const u64 rt = regs.Read<s64>(instr.rt());
|
const u64 rt = regs.Read<s64>(instr.rt());
|
||||||
mem.Write(paddr & ~7, (data & ~mask) | (rt << shift));
|
mem.Write(paddr & ~7, (data & ~mask) | (rt << shift));
|
||||||
|
cachedState.EvictCachedBlock(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,6 +569,7 @@ void Interpreter::swl(const Instruction instr) {
|
|||||||
const u32 data = mem.Read<u32>(paddr & ~3);
|
const u32 data = mem.Read<u32>(paddr & ~3);
|
||||||
const u32 rt = regs.Read<s64>(instr.rt());
|
const u32 rt = regs.Read<s64>(instr.rt());
|
||||||
mem.Write<u32>(paddr & ~3, (data & ~mask) | (rt >> shift));
|
mem.Write<u32>(paddr & ~3, (data & ~mask) | (rt >> shift));
|
||||||
|
cachedState.EvictCachedBlock(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,6 +585,7 @@ void Interpreter::swr(const Instruction instr) {
|
|||||||
const u32 data = mem.Read<u32>(paddr & ~3);
|
const u32 data = mem.Read<u32>(paddr & ~3);
|
||||||
const u32 rt = regs.Read<s64>(instr.rt());
|
const u32 rt = regs.Read<s64>(instr.rt());
|
||||||
mem.Write<u32>(paddr & ~3, (data & ~mask) | (rt << shift));
|
mem.Write<u32>(paddr & ~3, (data & ~mask) | (rt << shift));
|
||||||
|
cachedState.EvictCachedBlock(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -507,6 +507,9 @@ 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);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
BusWrite<u8, true>(cartAddr + i, mem.mmio.rdp.ReadRDRAM<u8>(dramAddr + i));
|
BusWrite<u8, true>(cartAddr + i, mem.mmio.rdp.ReadRDRAM<u8>(dramAddr + i));
|
||||||
@@ -539,7 +542,7 @@ void PI::DMA<true>() {
|
|||||||
for (u32 i = 0; i < len; i++) {
|
for (u32 i = 0; i < len; i++) {
|
||||||
mem.mmio.rdp.WriteRDRAM<u8>(dramAddr + i, BusRead<u8, true>(cartAddr + i));
|
mem.mmio.rdp.WriteRDRAM<u8>(dramAddr + i, BusRead<u8, true>(cartAddr + i));
|
||||||
}
|
}
|
||||||
Core::GetInstance().interpreter.cachedState.EvictCachedBlocksRange(dramAddr, dramAddr + len);
|
|
||||||
dramAddr += len;
|
dramAddr += len;
|
||||||
dramAddr = (dramAddr + 7) & ~7;
|
dramAddr = (dramAddr + 7) & ~7;
|
||||||
cartAddr += len;
|
cartAddr += len;
|
||||||
|
|||||||
@@ -218,19 +218,27 @@ void PIF::ConfigureJoyBusFrame() {
|
|||||||
case 6:
|
case 6:
|
||||||
res[0] = 0x00;
|
res[0] = 0x00;
|
||||||
res[1] = 0x10;
|
res[1] = 0x10;
|
||||||
res[2] = 0x80;
|
res[2] = 0x00;
|
||||||
break;
|
break;
|
||||||
case 7: {
|
case 7:
|
||||||
|
{
|
||||||
const u8 commandStart = packet[COMMAND_START];
|
const u8 commandStart = packet[COMMAND_START];
|
||||||
switch (commandStart) {
|
switch (commandStart) {
|
||||||
case 0:
|
case 0:
|
||||||
|
memset(res, 0, 8);
|
||||||
|
res[1] = 0x06;
|
||||||
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
|
memset(res, 0, 8);
|
||||||
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
|
memset(res, 0, 8);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
auto now = std::time(nullptr);
|
auto now = std::time(nullptr);
|
||||||
const auto *gmtm = gmtime(&now);
|
const auto *gmtm = gmtime(&now);
|
||||||
|
|
||||||
res[0] = BCD_ENCODE(gmtm->tm_sec);
|
res[0] = BCD_ENCODE(gmtm->tm_sec);
|
||||||
res[1] = BCD_ENCODE(gmtm->tm_min);
|
res[1] = BCD_ENCODE(gmtm->tm_min);
|
||||||
res[2] = BCD_ENCODE(gmtm->tm_hour) + 0x80;
|
res[2] = BCD_ENCODE(gmtm->tm_hour) + 0x80;
|
||||||
@@ -239,15 +247,15 @@ void PIF::ConfigureJoyBusFrame() {
|
|||||||
res[5] = BCD_ENCODE(gmtm->tm_mon);
|
res[5] = BCD_ENCODE(gmtm->tm_mon);
|
||||||
res[6] = BCD_ENCODE(gmtm->tm_year);
|
res[6] = BCD_ENCODE(gmtm->tm_year);
|
||||||
res[7] = (gmtm->tm_year - 1900) >= 100 ? 1 : 0;
|
res[7] = (gmtm->tm_year - 1900) >= 100 ? 1 : 0;
|
||||||
res[8] = 0x80;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("Invalid read RTC block {}", commandStart);
|
panic("Invalid read RTC block {}", commandStart);
|
||||||
}
|
}
|
||||||
} break;
|
}
|
||||||
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
res[0] = 0x00;
|
memset(res, 0, 8);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("Invalid PIF command: {:X}", commandIndex);
|
panic("Invalid PIF command: {:X}", commandIndex);
|
||||||
@@ -294,6 +302,8 @@ void PIF::MempakRead(const u8 *cmd, u8 *res) {
|
|||||||
case ACCESSORY_MEMPACK:
|
case ACCESSORY_MEMPACK:
|
||||||
if (offset <= MEMPAK_SIZE - 0x20) {
|
if (offset <= MEMPAK_SIZE - 0x20) {
|
||||||
std::copy_n(mempak.begin() + offset, 32, res);
|
std::copy_n(mempak.begin() + offset, 32, res);
|
||||||
|
} else {
|
||||||
|
memset(res, 0, 32);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ACCESSORY_RUMBLE_PACK:
|
case ACCESSORY_RUMBLE_PACK:
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ void SI::Write(u32 addr, u32 val) {
|
|||||||
status.dmaBusy = true;
|
status.dmaBusy = true;
|
||||||
toDram = true;
|
toDram = true;
|
||||||
Scheduler::GetInstance().EnqueueRelative(SI_DMA_DELAY, SI_DMA);
|
Scheduler::GetInstance().EnqueueRelative(SI_DMA_DELAY, SI_DMA);
|
||||||
Core::GetInstance().interpreter.cachedState.EvictCachedBlocksRange(dramAddr, dramAddr + 64);
|
|
||||||
break;
|
break;
|
||||||
case 0x04800010:
|
case 0x04800010:
|
||||||
pifAddr = val & 0x1FFFFFFF;
|
pifAddr = val & 0x1FFFFFFF;
|
||||||
|
|||||||
Reference in New Issue
Block a user