clamping logic + sdr fix + rsp.status gets written the same way as RSP::Write on RSP::MTC0
This commit is contained in:
1
external/parallel-rdp/CMakeLists.txt
vendored
1
external/parallel-rdp/CMakeLists.txt
vendored
@@ -61,6 +61,7 @@ target_include_directories(parallel-rdp PUBLIC
|
|||||||
parallel-rdp-standalone/util
|
parallel-rdp-standalone/util
|
||||||
../../src/n64
|
../../src/n64
|
||||||
../../src/n64/core/
|
../../src/n64/core/
|
||||||
|
../../src/n64/core/mmio
|
||||||
../../src/n64/core/cpu/
|
../../src/n64/core/cpu/
|
||||||
../../src/n64/core/cpu/registers
|
../../src/n64/core/cpu/registers
|
||||||
parallel-rdp-standalone
|
parallel-rdp-standalone
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ void App::Run() {
|
|||||||
char* droppedDir = event.drop.file;
|
char* droppedDir = event.drop.file;
|
||||||
if(droppedDir) {
|
if(droppedDir) {
|
||||||
LoadROM(droppedDir);
|
LoadROM(droppedDir);
|
||||||
|
free(droppedDir);
|
||||||
}
|
}
|
||||||
free(droppedDir);
|
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,14 +126,14 @@ void Core::UpdateController(const u8* state) {
|
|||||||
|
|
||||||
s8 xaxis = 0;
|
s8 xaxis = 0;
|
||||||
if(state[SDL_SCANCODE_LEFT]) {
|
if(state[SDL_SCANCODE_LEFT]) {
|
||||||
xaxis = -128;
|
xaxis = -127;
|
||||||
} else if(state[SDL_SCANCODE_RIGHT]) {
|
} else if(state[SDL_SCANCODE_RIGHT]) {
|
||||||
xaxis = 127;
|
xaxis = 127;
|
||||||
}
|
}
|
||||||
|
|
||||||
s8 yaxis = 0;
|
s8 yaxis = 0;
|
||||||
if(state[SDL_SCANCODE_DOWN]) {
|
if(state[SDL_SCANCODE_DOWN]) {
|
||||||
yaxis = -128;
|
yaxis = -127;
|
||||||
} else if(state[SDL_SCANCODE_UP]) {
|
} else if(state[SDL_SCANCODE_UP]) {
|
||||||
yaxis = 127;
|
yaxis = 127;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,28 +34,23 @@ inline void HandleInterrupt(Registers& regs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void Cpu::disassembly(u32 instr) {
|
inline void Cpu::disassembly(u32 instr) {
|
||||||
auto found = std::find(instructionsLogged.begin(), instructionsLogged.end(), instr);
|
size_t count;
|
||||||
|
cs_insn *insn;
|
||||||
|
|
||||||
if(found == instructionsLogged.end()) {
|
u8 code[4];
|
||||||
instructionsLogged.push_back(instr);
|
memcpy(code, &instr, 4);
|
||||||
size_t count;
|
|
||||||
cs_insn *insn;
|
|
||||||
|
|
||||||
u8 code[4];
|
count = cs_disasm(handle, code, 4, regs.pc, 0, &insn);
|
||||||
memcpy(code, &instr, 4);
|
|
||||||
|
|
||||||
count = cs_disasm(handle, code, 4, regs.pc, 0, &insn);
|
if (count > 0) {
|
||||||
|
size_t j;
|
||||||
|
for (j = 0; j < count; j++) {
|
||||||
|
fmt::print("0x{:016X}:\t{}\t\t{}\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
|
||||||
|
}
|
||||||
|
|
||||||
if (count > 0) {
|
cs_free(insn, count);
|
||||||
size_t j;
|
} else
|
||||||
for (j = 0; j < count; j++) {
|
printf("ERROR: Failed to disassemble given code!\n");
|
||||||
fmt::print("0x{:016X}:\t{}\t\t{}\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
cs_free(insn, count);
|
|
||||||
} else
|
|
||||||
printf("ERROR: Failed to disassemble given code!\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::Step(Mem& mem) {
|
void Cpu::Step(Mem& mem) {
|
||||||
|
|||||||
@@ -26,8 +26,6 @@ private:
|
|||||||
void disassembly(u32 instr);
|
void disassembly(u32 instr);
|
||||||
friend struct Cop1;
|
friend struct Cop1;
|
||||||
|
|
||||||
std::vector<u32> instructionsLogged;
|
|
||||||
|
|
||||||
void special(Mem&, u32);
|
void special(Mem&, u32);
|
||||||
void regimm(u32);
|
void regimm(u32);
|
||||||
void Exec(Mem&, u32);
|
void Exec(Mem&, u32);
|
||||||
|
|||||||
@@ -67,25 +67,7 @@ void RSP::Write(Mem& mem, Registers& regs, u32 addr, u32 value) {
|
|||||||
spDMALen.raw = value;
|
spDMALen.raw = value;
|
||||||
DMA<true>(spDMALen, mem.GetRDRAM(), *this, spDMASPAddr.bank);
|
DMA<true>(spDMALen, mem.GetRDRAM(), *this, spDMASPAddr.bank);
|
||||||
} break;
|
} break;
|
||||||
case 0x04040010: {
|
case 0x04040010: WriteStatus(mi, regs, value); break;
|
||||||
auto write = SPStatusWrite{.raw = value};
|
|
||||||
CLEAR_SET(spStatus.halt, write.clearHalt, write.setHalt);
|
|
||||||
if(write.clearBroke) spStatus.broke = false;
|
|
||||||
if(write.clearIntr && !write.setIntr)
|
|
||||||
InterruptLower(mi, regs, Interrupt::SP);
|
|
||||||
if(write.setIntr && !write.clearIntr)
|
|
||||||
InterruptRaise(mi, regs, Interrupt::SP);
|
|
||||||
CLEAR_SET(spStatus.singleStep, write.clearSstep, write.setSstep);
|
|
||||||
CLEAR_SET(spStatus.interruptOnBreak, write.clearIntrOnBreak, write.setIntrOnBreak);
|
|
||||||
CLEAR_SET(spStatus.signal0Set, write.clearSignal0, write.setSignal0);
|
|
||||||
CLEAR_SET(spStatus.signal1Set, write.clearSignal1, write.setSignal1);
|
|
||||||
CLEAR_SET(spStatus.signal2Set, write.clearSignal2, write.setSignal2);
|
|
||||||
CLEAR_SET(spStatus.signal3Set, write.clearSignal3, write.setSignal3);
|
|
||||||
CLEAR_SET(spStatus.signal4Set, write.clearSignal4, write.setSignal4);
|
|
||||||
CLEAR_SET(spStatus.signal5Set, write.clearSignal5, write.setSignal5);
|
|
||||||
CLEAR_SET(spStatus.signal6Set, write.clearSignal6, write.setSignal6);
|
|
||||||
CLEAR_SET(spStatus.signal7Set, write.clearSignal7, write.setSignal7);
|
|
||||||
} break;
|
|
||||||
case 0x0404001C: ReleaseSemaphore(); break;
|
case 0x0404001C: ReleaseSemaphore(); break;
|
||||||
case 0x04080000:
|
case 0x04080000:
|
||||||
if(spStatus.halt) {
|
if(spStatus.halt) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <n64/core/mmio/MI.hpp>
|
#include <n64/core/mmio/MI.hpp>
|
||||||
#include <n64/core/RDP.hpp>
|
#include <n64/core/RDP.hpp>
|
||||||
#include <n64/memory_regions.hpp>
|
#include <n64/memory_regions.hpp>
|
||||||
|
#include <Interrupt.hpp>
|
||||||
|
|
||||||
#define RSP_BYTE(addr, buf) (buf[BYTE_ADDRESS(addr) & 0xFFF])
|
#define RSP_BYTE(addr, buf) (buf[BYTE_ADDRESS(addr) & 0xFFF])
|
||||||
#define GET_RSP_HALF(addr, buf) ((RSP_BYTE(addr, buf) << 8) | RSP_BYTE((addr) + 1, buf))
|
#define GET_RSP_HALF(addr, buf) ((RSP_BYTE(addr, buf) << 8) | RSP_BYTE((addr) + 1, buf))
|
||||||
@@ -22,14 +23,14 @@ union SPStatus {
|
|||||||
unsigned ioFull:1;
|
unsigned ioFull:1;
|
||||||
unsigned singleStep:1;
|
unsigned singleStep:1;
|
||||||
unsigned interruptOnBreak:1;
|
unsigned interruptOnBreak:1;
|
||||||
unsigned signal0Set:1;
|
unsigned signal0:1;
|
||||||
unsigned signal1Set:1;
|
unsigned signal1:1;
|
||||||
unsigned signal2Set:1;
|
unsigned signal2:1;
|
||||||
unsigned signal3Set:1;
|
unsigned signal3:1;
|
||||||
unsigned signal4Set:1;
|
unsigned signal4:1;
|
||||||
unsigned signal5Set:1;
|
unsigned signal5:1;
|
||||||
unsigned signal6Set:1;
|
unsigned signal6:1;
|
||||||
unsigned signal7Set:1;
|
unsigned signal7:1;
|
||||||
unsigned:17;
|
unsigned:17;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -169,6 +170,26 @@ struct RSP {
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void WriteStatus(MI& mi, Registers& regs, u32 value) {
|
||||||
|
auto write = SPStatusWrite{.raw = value};
|
||||||
|
CLEAR_SET(spStatus.halt, write.clearHalt, write.setHalt);
|
||||||
|
if(write.clearBroke) spStatus.broke = false;
|
||||||
|
if(write.clearIntr && !write.setIntr)
|
||||||
|
InterruptLower(mi, regs, Interrupt::SP);
|
||||||
|
if(write.setIntr && !write.clearIntr)
|
||||||
|
InterruptRaise(mi, regs, Interrupt::SP);
|
||||||
|
CLEAR_SET(spStatus.singleStep, write.clearSstep, write.setSstep);
|
||||||
|
CLEAR_SET(spStatus.interruptOnBreak, write.clearIntrOnBreak, write.setIntrOnBreak);
|
||||||
|
CLEAR_SET(spStatus.signal0, write.clearSignal0, write.setSignal0);
|
||||||
|
CLEAR_SET(spStatus.signal1, write.clearSignal1, write.setSignal1);
|
||||||
|
CLEAR_SET(spStatus.signal2, write.clearSignal2, write.setSignal2);
|
||||||
|
CLEAR_SET(spStatus.signal3, write.clearSignal3, write.setSignal3);
|
||||||
|
CLEAR_SET(spStatus.signal4, write.clearSignal4, write.setSignal4);
|
||||||
|
CLEAR_SET(spStatus.signal5, write.clearSignal5, write.setSignal5);
|
||||||
|
CLEAR_SET(spStatus.signal6, write.clearSignal6, write.setSignal6);
|
||||||
|
CLEAR_SET(spStatus.signal7, write.clearSignal7, write.setSignal7);
|
||||||
|
}
|
||||||
|
|
||||||
inline u16 VCCasU16() {
|
inline u16 VCCasU16() {
|
||||||
u16 val = 0;
|
u16 val = 0;
|
||||||
for(int i = 0; i < 8; i++) {
|
for(int i = 0; i < 8; i++) {
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ void Cpu::lwl(Mem& mem, u32 instr) {
|
|||||||
u32 shift = 8 * ((address ^ 0) & 3);
|
u32 shift = 8 * ((address ^ 0) & 3);
|
||||||
u32 mask = 0xFFFFFFFF << shift;
|
u32 mask = 0xFFFFFFFF << shift;
|
||||||
u32 data = mem.Read32<false>(regs, paddr & ~3, regs.oldPC);
|
u32 data = mem.Read32<false>(regs, paddr & ~3, regs.oldPC);
|
||||||
s32 result = (s32) ((regs.gpr[RT(instr)] & ~mask) | (data << shift));
|
s32 result = s32((regs.gpr[RT(instr)] & ~mask) | (data << shift));
|
||||||
regs.gpr[RT(instr)] = result;
|
regs.gpr[RT(instr)] = result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -257,7 +257,7 @@ void Cpu::lwr(Mem& mem, u32 instr) {
|
|||||||
u32 shift = 8 * ((address ^ 3) & 3);
|
u32 shift = 8 * ((address ^ 3) & 3);
|
||||||
u32 mask = 0xFFFFFFFF >> shift;
|
u32 mask = 0xFFFFFFFF >> shift;
|
||||||
u32 data = mem.Read32<false>(regs, paddr & ~3, regs.oldPC);
|
u32 data = mem.Read32<false>(regs, paddr & ~3, regs.oldPC);
|
||||||
s32 result = (s32) ((regs.gpr[RT(instr)] & ~mask) | (data >> shift));
|
s32 result = s32((regs.gpr[RT(instr)] & ~mask) | (data >> shift));
|
||||||
regs.gpr[RT(instr)] = result;
|
regs.gpr[RT(instr)] = result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -420,7 +420,7 @@ void Cpu::sdl(Mem& mem, u32 instr) {
|
|||||||
s32 shift = 8 * ((address ^ 0) & 7);
|
s32 shift = 8 * ((address ^ 0) & 7);
|
||||||
u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
|
u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
|
||||||
u64 data = mem.Read64<false>(regs, paddr & ~7, regs.oldPC);
|
u64 data = mem.Read64<false>(regs, paddr & ~7, regs.oldPC);
|
||||||
s64 rt = regs.gpr[RT(instr)];
|
u64 rt = regs.gpr[RT(instr)];
|
||||||
mem.Write64<false>(regs, paddr & ~7, (data & ~mask) | (rt >> shift), regs.oldPC);
|
mem.Write64<false>(regs, paddr & ~7, (data & ~mask) | (rt >> shift), regs.oldPC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -435,7 +435,7 @@ void Cpu::sdr(Mem& mem, u32 instr) {
|
|||||||
s32 shift = 8 * ((address ^ 7) & 7);
|
s32 shift = 8 * ((address ^ 7) & 7);
|
||||||
u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
|
u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
|
||||||
u64 data = mem.Read64<false>(regs, paddr & ~7, regs.oldPC);
|
u64 data = mem.Read64<false>(regs, paddr & ~7, regs.oldPC);
|
||||||
s64 rt = regs.gpr[RT(instr)];
|
u64 rt = regs.gpr[RT(instr)];
|
||||||
mem.Write64<false>(regs, paddr & ~7, (data & ~mask) | (rt << shift), regs.oldPC);
|
mem.Write64<false>(regs, paddr & ~7, (data & ~mask) | (rt << shift), regs.oldPC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
|||||||
cartAddr = cart_addr + len;
|
cartAddr = cart_addr + len;
|
||||||
InterruptRaise(mi, regs, Interrupt::PI);
|
InterruptRaise(mi, regs, Interrupt::PI);
|
||||||
status &= 0xFFFFFFFE;
|
status &= 0xFFFFFFFE;
|
||||||
//util::logdebug("PI DMA from RDP RAM to CARTRIDGE (size: {} KiB, {:08X} to {:08X})\n", len, dramAddr, cartAddr);
|
util::logdebug("PI DMA from RDRAM to CARTRIDGE (size: {} KiB, {:08X} to {:08X})\n", len, dramAddr, cartAddr);
|
||||||
} break;
|
} break;
|
||||||
case 0x0460000C: {
|
case 0x0460000C: {
|
||||||
u32 len = (val & 0x00FFFFFF) + 1;
|
u32 len = (val & 0x00FFFFFF) + 1;
|
||||||
@@ -76,7 +76,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
|||||||
cartAddr = cart_addr + len;
|
cartAddr = cart_addr + len;
|
||||||
InterruptRaise(mi, regs, Interrupt::PI);
|
InterruptRaise(mi, regs, Interrupt::PI);
|
||||||
status &= 0xFFFFFFFE;
|
status &= 0xFFFFFFFE;
|
||||||
//util::logdebug("PI DMA from CARTRIDGE to RDP RAM (size: {} KiB, {:08X} to {:08X})\n", len, cartAddr, dramAddr);
|
util::logdebug("PI DMA from CARTRIDGE to RDRAM (size: {} KiB, {:08X} to {:08X})\n", len, cart_addr, dram_addr);
|
||||||
} break;
|
} break;
|
||||||
case 0x04600010:
|
case 0x04600010:
|
||||||
if(val & 2) {
|
if(val & 2) {
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ inline void special(MI& mi, Registers& regs, RSP& rsp, u32 instr) {
|
|||||||
case 0x07: rsp.srav(instr); break;
|
case 0x07: rsp.srav(instr); break;
|
||||||
case 0x08: rsp.jr(instr); break;
|
case 0x08: rsp.jr(instr); break;
|
||||||
case 0x09: rsp.jalr(instr); break;
|
case 0x09: rsp.jalr(instr); break;
|
||||||
case 0x0C:
|
|
||||||
case 0x0D:
|
case 0x0D:
|
||||||
rsp.spStatus.halt = true;
|
rsp.spStatus.halt = true;
|
||||||
rsp.spStatus.broke = true;
|
rsp.spStatus.broke = true;
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ inline void SetCop0Reg(Registers& regs, Mem& mem, u8 index, u32 val) {
|
|||||||
rsp.spDMALen.raw = val;
|
rsp.spDMALen.raw = val;
|
||||||
rsp.DMA<true>(rsp.spDMALen, mem.GetRDRAM(), rsp, rsp.spDMASPAddr.bank);
|
rsp.DMA<true>(rsp.spDMALen, mem.GetRDRAM(), rsp, rsp.spDMASPAddr.bank);
|
||||||
break;
|
break;
|
||||||
case 4: rsp.spStatus.raw = val; break;
|
case 4: rsp.WriteStatus(mi, regs, val); break;
|
||||||
case 7:
|
case 7:
|
||||||
if(val == 0) {
|
if(val == 0) {
|
||||||
ReleaseSemaphore(rsp);
|
ReleaseSemaphore(rsp);
|
||||||
@@ -337,7 +337,7 @@ void RSP::srlv(u32 instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RSP::srav(u32 instr) {
|
void RSP::srav(u32 instr) {
|
||||||
u8 sa = (gpr[RS(instr)]) & 0x1F;
|
u8 sa = gpr[RS(instr)] & 0x1F;
|
||||||
s32 rt = gpr[RT(instr)];
|
s32 rt = gpr[RT(instr)];
|
||||||
s32 result = rt >> sa;
|
s32 result = rt >> sa;
|
||||||
gpr[RD(instr)] = result;
|
gpr[RD(instr)] = result;
|
||||||
|
|||||||
Reference in New Issue
Block a user