fix pads, start RSP

This commit is contained in:
CocoSimone
2022-09-10 01:05:46 +02:00
parent 0b5a9ba0e7
commit 645a20931a
16 changed files with 131 additions and 78 deletions

View File

@@ -6,6 +6,9 @@ void App::Run() {
// Main loop // Main loop
const u8* state = SDL_GetKeyboardState(nullptr); const u8* state = SDL_GetKeyboardState(nullptr);
while (!core.done) { while (!core.done) {
core.Run(window);
core.UpdateController(state);
SDL_Event event; SDL_Event event;
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
ImGui_ImplSDL2_ProcessEvent(&event); ImGui_ImplSDL2_ProcessEvent(&event);
@@ -36,10 +39,6 @@ void App::Run() {
} break; } break;
} break; } break;
} }
core.UpdateController(state);
} }
core.Run(window);
} }
} }

View File

@@ -3,6 +3,7 @@
#include <nfd.hpp> #include <nfd.hpp>
#include <Core.hpp> #include <Core.hpp>
#include <utility> #include <utility>
#include <Audio.hpp>
VkInstance instance{}; VkInstance instance{};
@@ -20,6 +21,8 @@ Window::Window(n64::Core& core) {
void Window::InitSDL() { void Window::InitSDL() {
SDL_Init(SDL_INIT_EVERYTHING); SDL_Init(SDL_INIT_EVERYTHING);
n64::InitAudio();
window = SDL_CreateWindow( window = SDL_CreateWindow(
"natsukashii", "natsukashii",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,

View File

@@ -38,6 +38,7 @@ void Core::LoadROM(const std::string& rom_) {
void Core::Run(Window& window) { void Core::Run(Window& window) {
MMIO& mmio = mem.mmio; MMIO& mmio = mem.mmio;
Controller& controller = mmio.si.controller;
int cycles = 0; int cycles = 0;
for(int field = 0; field < mmio.vi.numFields; field++) { for(int field = 0; field < mmio.vi.numFields; field++) {
int frameCycles = 0; int frameCycles = 0;
@@ -56,7 +57,7 @@ void Core::Run(Window& window) {
mmio.rsp.Step(mmio.mi, cpu.regs, mmio.rdp); mmio.rsp.Step(mmio.mi, cpu.regs, mmio.rdp);
mmio.rsp.Step(mmio.mi, cpu.regs, mmio.rdp); mmio.rsp.Step(mmio.mi, cpu.regs, mmio.rdp);
//mmio.ai.Step(mem, cpu.regs, 1); mmio.ai.Step(mem, cpu.regs, 1);
} }
cycles -= mmio.vi.cyclesPerHalfline; cycles -= mmio.vi.cyclesPerHalfline;
@@ -69,7 +70,7 @@ void Core::Run(Window& window) {
UpdateScreenParallelRdp(*this, window, GetVI()); UpdateScreenParallelRdp(*this, window, GetVI());
int missedCycles = N64_CYCLES_PER_FRAME - frameCycles; int missedCycles = N64_CYCLES_PER_FRAME - frameCycles;
//mmio.ai.Step(mem, cpu.regs, missedCycles); mmio.ai.Step(mem, cpu.regs, missedCycles);
} else if(pause && romLoaded) { } else if(pause && romLoaded) {
UpdateScreenParallelRdp(*this, window, GetVI()); UpdateScreenParallelRdp(*this, window, GetVI());
} else if(pause && !romLoaded) { } else if(pause && !romLoaded) {

View File

@@ -12,7 +12,7 @@ static SDL_AudioStream* audioStream = nullptr;
SDL_mutex* audioStreamMutex; SDL_mutex* audioStreamMutex;
SDL_AudioSpec audioSpec; SDL_AudioSpec audioSpec;
SDL_AudioSpec request; SDL_AudioSpec request;
SDL_AudioDeviceID audioDev; SDL_AudioDeviceID audioDev{};
#define LockAudioMutex() SDL_LockMutex(audioStreamMutex) #define LockAudioMutex() SDL_LockMutex(audioStreamMutex)
#define UnlockAudioMutex() SDL_UnlockMutex(audioStreamMutex) #define UnlockAudioMutex() SDL_UnlockMutex(audioStreamMutex)
@@ -48,7 +48,9 @@ void InitAudio() {
request.callback = audioCallback; request.callback = audioCallback;
request.userdata = nullptr; request.userdata = nullptr;
audioDev = SDL_OpenAudioDevice(nullptr, 0, &request, &audioSpec, 0); if(!audioDev) {
audioDev = SDL_OpenAudioDevice(nullptr, 0, &request, &audioSpec, 0);
}
if(!audioDev) { if(!audioDev) {
util::panic("Failed to initialize SDL Audio: {}", SDL_GetError()); util::panic("Failed to initialize SDL Audio: {}", SDL_GetError());

View File

@@ -59,8 +59,12 @@ void FireException(Registers& regs, ExceptionCode code, int cop, s64 pc) {
util::panic("BEV bit set!\n"); util::panic("BEV bit set!\n");
} else { } else {
switch(code) { switch(code) {
case Interrupt ... TLBModification: case Interrupt: case TLBModification:
case AddressErrorLoad ... Trap: case AddressErrorLoad: case AddressErrorStore:
case InstructionBusError: case DataBusError:
case Syscall: case Breakpoint:
case ReservedInstruction: case CoprocessorUnusable:
case Overflow: case Trap:
case FloatingPointError: case Watch: case FloatingPointError: case Watch:
regs.SetPC(s64(s32(0x80000180))); regs.SetPC(s64(s32(0x80000180)));
break; break;

View File

@@ -7,16 +7,16 @@
namespace n64 { namespace n64 {
struct Cpu { struct Cpu {
Cpu() { Cpu() {
log = fopen("disasm.txt", "w"); //log = fopen("disasm.txt", "w");
if(cs_open(CS_ARCH_MIPS, CS_MODE_MIPS64, &handle) != CS_ERR_OK) { //if(cs_open(CS_ARCH_MIPS, CS_MODE_MIPS64, &handle) != CS_ERR_OK) {
util::panic("Could not initialize capstone!\n"); // util::panic("Could not initialize capstone!\n");
} //}
Reset(); Reset();
} }
~Cpu() { ~Cpu() {
fclose(log); //fclose(log);
cs_close(&handle); //cs_close(&handle);
} }
void Reset(); void Reset();
void Step(Mem&); void Step(Mem&);

View File

@@ -33,8 +33,8 @@ void RSP::Step(MI& mi, Registers& regs, RDP& rdp) {
if(!spStatus.halt) { if(!spStatus.halt) {
gpr[0] = 0; gpr[0] = 0;
u32 instr = util::ReadAccess<u32>(imem, pc & IMEM_DSIZE); u32 instr = util::ReadAccess<u32>(imem, pc & IMEM_DSIZE);
oldPC = pc & 0xFFF; oldPC = pc & 0xFFC;
pc = nextPC & 0xFFF; pc = nextPC & 0xFFC;
nextPC += 4; nextPC += 4;
Exec(mi, regs, rdp, instr); Exec(mi, regs, rdp, instr);
} }
@@ -120,7 +120,7 @@ void RSP::Write(Mem& mem, Registers& regs, u32 addr, u32 value) {
if(spStatus.halt) { if(spStatus.halt) {
oldPC = pc; oldPC = pc;
pc = nextPC; pc = nextPC;
nextPC = value & 0xFFF; nextPC = value & 0xFFC;
} break; } break;
default: util::panic("Unimplemented SP register write {:08X}, val: {:08X}\n", addr, value); default: util::panic("Unimplemented SP register write {:08X}, val: {:08X}\n", addr, value);
} }

View File

@@ -3,6 +3,12 @@
#include <n64/core/RDP.hpp> #include <n64/core/RDP.hpp>
#include <n64/memory_regions.hpp> #include <n64/memory_regions.hpp>
#define RSP_BYTE(addr) (dmem[BYTE_ADDRESS(addr) & 0xfff])
#define GET_RSP_HALF(addr) ((RSP_BYTE(addr) << 8) | RSP_BYTE((addr) + 1))
#define SET_RSP_HALF(addr, value) do { RSP_BYTE(addr) = ((value) >> 8) & 0xFF; RSP_BYTE((addr) + 1) = (value) & 0xFF;} while(0)
#define GET_RSP_WORD(addr) ((GET_RSP_HALF(addr) << 16) | GET_RSP_HALF((addr) + 2))
#define SET_RSP_WORD(addr, value) do { SET_RSP_HALF(addr, ((value) >> 16) & 0xFFFF); SET_RSP_HALF((addr) + 2, (value) & 0xFFFF);} while(0)
namespace n64 { namespace n64 {
union SPStatus { union SPStatus {
u32 raw; u32 raw;
@@ -154,6 +160,30 @@ struct RSP {
return val; return val;
} }
inline u32 ReadWord(u32 addr) {
return GET_RSP_WORD(addr);
}
inline void WriteWord(u32 addr, u32 val) {
SET_RSP_WORD(addr, val);
}
inline u16 ReadHalf(u32 addr) {
return GET_RSP_HALF(addr);
}
inline void WriteHalf(u32 addr, u16 val) {
SET_RSP_HALF(addr, val);
}
inline u8 ReadByte(u32 addr) {
return GET_RSP_WORD(addr);
}
inline void WriteByte(u32 addr, u8 val) {
SET_RSP_WORD(addr, val);
}
void add(u32 instr); void add(u32 instr);
void addi(u32 instr); void addi(u32 instr);
void and_(u32 instr); void and_(u32 instr);

View File

@@ -11,9 +11,7 @@ Cop0::Cop0() {
void Cop0::Reset() { void Cop0::Reset() {
cause.raw = 0xB000007C; cause.raw = 0xB000007C;
status.raw = 0x241000E0; status.raw = 0x241000E0;
wired = 64; PRId = 0x00000B22;
index = 64;
PRId = 0x00000B00;
Config = 0x7006E463; Config = 0x7006E463;
EPC = 0xFFFFFFFFFFFFFFFF; EPC = 0xFFFFFFFFFFFFFFFF;
ErrorEPC = 0xFFFFFFFFFFFFFFFF; ErrorEPC = 0xFFFFFFFFFFFFFFFF;

View File

@@ -72,8 +72,8 @@ void AI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
} }
} }
void AI::Step(Mem& mem, Registers& regs, int) { void AI::Step(Mem& mem, Registers& regs, int cpuCycles) {
cycles += cycles; cycles += cpuCycles;
while(cycles > dac.period) { while(cycles > dac.period) {
if (dmaCount == 0) { if (dmaCount == 0) {
return; return;

View File

@@ -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 rdram to cart (size: {:.2f} MiB)\n", (float)len / 1048576); //util::logdebug("PI DMA from RDP RAM 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 cart to rdram (size: {:.2f} MiB)\n", (float)len / 1048576); //util::logdebug("PI DMA from CARTRIDGE to RDP RAM (size: {} KiB, {:08X} to {:08X})\n", len, cartAddr, dramAddr);
} break; } break;
case 0x04600010: case 0x04600010:
if(val & 2) { if(val & 2) {

View File

@@ -65,7 +65,7 @@ void ProcessPIFCommands(u8* pifRam, Controller& controller, Mem& mem) {
pifRam[63] = 128; pifRam[63] = 128;
} }
//mem->pif_ram[63] &= ~1; //pifRam[63] &= ~1;
} }
} }

View File

@@ -34,23 +34,29 @@ void SI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
dramAddr = val; dramAddr = val;
break; break;
case 0x04800004: { case 0x04800004: {
// if(!(status.raw & 3)) { if(!(status.raw & 3)) {
ProcessPIFCommands(mem.pifRam, controller, mem); ProcessPIFCommands(mem.pifRam, controller, mem);
u8 pifAddr = (val & 0x7FC) & PIF_RAM_DSIZE; pifAddr = (val & 0x7FC) & PIF_RAM_DSIZE;
memcpy(&mem.mmio.rdp.dram[dramAddr & RDRAM_DSIZE], for(int i = 0; i < 64; i++) {
&mem.pifRam[pifAddr], 64); mem.mmio.rdp.dram[BYTE_ADDRESS(dramAddr + i) & RDRAM_DSIZE] = mem.pifRam[pifAddr + i];
InterruptRaise(mem.mmio.mi, regs, Interrupt::SI); }
status.intr = 1; InterruptRaise(mem.mmio.mi, regs, Interrupt::SI);
status.intr = 1;
//util::logdebug("SI DMA from PIF RAM to RDP RAM ({:08X} to {:08X})\n", pifAddr, dramAddr);
}
} break; } break;
case 0x04800010: { case 0x04800010: {
//if(!(status.raw & 3)) { if(!(status.raw & 3)) {
u8 pifAddr = (val & 0x7FC) & PIF_RAM_DSIZE; pifAddr = (val & 0x7FC) & PIF_RAM_DSIZE;
memcpy(&mem.pifRam[pifAddr], for(int i = 0; i < 64; i++) {
&mem.mmio.rdp.dram[dramAddr & RDRAM_DSIZE], 64); mem.pifRam[pifAddr + i] = mem.mmio.rdp.dram[BYTE_ADDRESS(dramAddr + i) & RDRAM_DSIZE];
ProcessPIFCommands(mem.pifRam, controller, mem); }
InterruptRaise(mem.mmio.mi, regs, Interrupt::SI); ProcessPIFCommands(mem.pifRam, controller, mem);
status.intr = 1; InterruptRaise(mem.mmio.mi, regs, Interrupt::SI);
status.intr = 1;
//util::logdebug("SI DMA from RDP RAM to PIF RAM ({:08X} to {:08X})\n", dramAddr, pifAddr);
}
} break; } break;
case 0x04800018: case 0x04800018:
InterruptLower(mem.mmio.mi, regs, Interrupt::SI); InterruptLower(mem.mmio.mi, regs, Interrupt::SI);

View File

@@ -25,6 +25,7 @@ struct SI {
void Reset(); void Reset();
SIStatus status{}; SIStatus status{};
u32 dramAddr{}; u32 dramAddr{};
u32 pifAddr{};
Controller controller{}; Controller controller{};
auto Read(MI&, u32) const -> u32; auto Read(MI&, u32) const -> u32;

View File

@@ -1,26 +1,30 @@
#include <n64/core/RSP.hpp> #include <n64/core/RSP.hpp>
#include <util.hpp> #include <util.hpp>
#include <n64/core/cpu/Registers.hpp> #include <n64/core/cpu/Registers.hpp>
#include <Interrupt.hpp>
namespace n64 { namespace n64 {
inline void special(RSP& rsp, u32 instr) { inline void special(MI& mi, Registers& regs, RSP& rsp, u32 instr) {
u8 mask = instr & 0x3f; u8 mask = instr & 0x3f;
switch(mask) { switch(mask) {
//case 0x00: rsp.sll(instr); break; case 0x00: rsp.sll(instr); break;
//case 0x04: rsp.sllv(instr); break; case 0x04: rsp.sllv(instr); break;
//case 0x08: rsp.jr(instr); break; //case 0x08: rsp.jr(instr); break;
//case 0x0C: case 0x0C:
//case 0x0D: case 0x0D:
// rsp.spStatus.halt = true; rsp.spStatus.halt = true;
// rsp.spStatus.broke = true; rsp.spStatus.broke = true;
// break; if(rsp.spStatus.interruptOnBreak) {
InterruptRaise(mi, regs, Interrupt::SP);
}
break;
//case 0x20: case 0x21: //case 0x20: case 0x21:
// rsp.add(instr); // rsp.add(instr);
// break; // break;
//case 0x24: rsp.and_(instr); break; case 0x24: rsp.and_(instr); break;
//case 0x25: rsp.or_(instr); break; case 0x25: rsp.or_(instr); break;
//case 0x27: rsp.nor(instr); break; //case 0x27: rsp.nor(instr); break;
default: util::panic("Unhandled RSP special instruction {} {}\n", (mask >> 3) & 7, mask & 7); default: util::panic("Unhandled RSP special instruction ({:06b})\n", mask);
} }
} }
@@ -56,7 +60,7 @@ inline void cop2(RSP& rsp, u32 instr) {
case 0x00: case 0x00:
switch(mask_sub) { switch(mask_sub) {
//case 0x02: rsp.cfc2(instr); break; //case 0x02: rsp.cfc2(instr); break;
default: util::panic("Unhandled RSP COP2 sub {} {}\n", (mask_sub >> 3) & 3, mask_sub & 3); default: util::panic("Unhandled RSP COP2 sub ({:06b})\n", mask_sub);
} }
break; break;
//case 0x13: rsp.vabs(instr); break; //case 0x13: rsp.vabs(instr); break;
@@ -64,40 +68,40 @@ inline void cop2(RSP& rsp, u32 instr) {
//case 0x21: rsp.veq(instr); break; //case 0x21: rsp.veq(instr); break;
//case 0x22: rsp.vne(instr); break; //case 0x22: rsp.vne(instr); break;
//case 0x33: rsp.vmov(instr); break; //case 0x33: rsp.vmov(instr); break;
default: util::panic("Unhandled RSP COP2 {} {}\n", (mask >> 3) & 7, mask & 7); default: util::panic("Unhandled RSP COP2 ({:06b})\n", mask);
} }
} }
inline void cop0(MI& mi, Registers& regs, RSP& rsp, RDP& rdp, u32 instr) { inline void cop0(MI& mi, Registers& regs, RSP& rsp, RDP& rdp, u32 instr) {
u8 mask = (instr >> 21) & 0x1F; u8 mask = (instr >> 21) & 0x1F;
switch(mask) { switch(mask) {
//case 0x00: rsp.mfc0(rdp, instr); break; case 0x00: rsp.mfc0(rdp, instr); break;
//case 0x04: rsp.mtc0(mi, regs, rdp, instr); break; case 0x04: rsp.mtc0(mi, regs, rdp, instr); break;
default: util::panic("Unhandled RSP COP0 {} {}\n", (mask >> 3) & 3, mask & 7); default: util::panic("Unhandled RSP COP0 ({:06b})\n", mask);
} }
} }
void RSP::Exec(MI &mi, Registers &regs, RDP &rdp, u32 instr) { void RSP::Exec(MI &mi, Registers &regs, RDP &rdp, u32 instr) {
u8 mask = (instr >> 26) & 0x3F; u8 mask = (instr >> 26) & 0x3F;
switch(mask) { switch(mask) {
//case 0x00: special(*this, instr); break; case 0x00: special(mi, regs, *this, instr); break;
case 0x01: regimm(*this, instr); break; case 0x01: regimm(*this, instr); break;
case 0x02: j(instr); break; case 0x02: j(instr); break;
//case 0x03: jal(instr); break; case 0x03: jal(instr); break;
//case 0x04: b(instr, gpr[RT(instr)] == gpr[RS(instr)]); break; case 0x04: b(instr, gpr[RT(instr)] == gpr[RS(instr)]); break;
//case 0x05: b(instr, gpr[RT(instr)] != gpr[RS(instr)]); break; case 0x05: b(instr, gpr[RT(instr)] != gpr[RS(instr)]); break;
//case 0x07: b(instr, gpr[RS(instr)] > 0); break; case 0x07: b(instr, gpr[RS(instr)] > 0); break;
case 0x08: case 0x09: addi(instr); break; case 0x08: case 0x09: addi(instr); break;
//case 0x0C: andi(instr); break; case 0x0C: andi(instr); break;
case 0x0D: ori(instr); break; case 0x0D: ori(instr); break;
//case 0x0F: lui(instr); break; case 0x0F: lui(instr); break;
//case 0x10: cop0(mi, regs, *this, rdp, instr); break; case 0x10: cop0(mi, regs, *this, rdp, instr); break;
//case 0x12: cop2(*this, instr); break; //case 0x12: cop2(*this, instr); break;
//case 0x21: lh(instr); break; //case 0x21: lh(instr); break;
//case 0x23: lw(instr); break; case 0x23: lw(instr); break;
//case 0x28: sb(instr); break; //case 0x28: sb(instr); break;
//case 0x29: sh(instr); break; //case 0x29: sh(instr); break;
//case 0x2B: sw(instr); break; case 0x2B: sw(instr); break;
//case 0x32: lwc2(*this, instr); break; //case 0x32: lwc2(*this, instr); break;
//case 0x3A: swc2(*this, instr); break; //case 0x3A: swc2(*this, instr); break;
default: util::panic("Unhandled RSP instruction ({:06b})\n", mask); default: util::panic("Unhandled RSP instruction ({:06b})\n", mask);

View File

@@ -98,11 +98,11 @@ void RSP::addi(u32 instr) {
} }
void RSP::and_(u32 instr) { void RSP::and_(u32 instr) {
gpr[RD(instr)] = gpr[RT(instr)] & gpr[RS(instr)];
} }
void RSP::andi(u32 instr) { void RSP::andi(u32 instr) {
gpr[RT(instr)] = gpr[RS(instr)] & (u16)instr;
} }
void RSP::cfc2(u32 instr) { void RSP::cfc2(u32 instr) {
@@ -119,11 +119,13 @@ void RSP::lh(u32 instr) {
} }
void RSP::lw(u32 instr) { void RSP::lw(u32 instr) {
u32 address = gpr[BASE(instr)] + (s16)instr;
gpr[RT(instr)] = ReadWord(address);
} }
void RSP::lui(u32 instr) { void RSP::lui(u32 instr) {
u32 imm = ((u16)instr) << 16;
gpr[RT(instr)] = imm;
} }
void RSP::lqv(u32 instr) { void RSP::lqv(u32 instr) {
@@ -136,7 +138,8 @@ void RSP::j(u32 instr) {
} }
void RSP::jal(u32 instr) { void RSP::jal(u32 instr) {
gpr[31] = nextPC;
j(instr);
} }
void RSP::jr(u32 instr) { void RSP::jr(u32 instr) {
@@ -147,15 +150,15 @@ void RSP::nor(u32 instr) {
} }
void RSP::or_(u32 instr) {
}
void RSP::ori(u32 instr) { void RSP::ori(u32 instr) {
s16 imm = instr; s16 imm = instr;
gpr[RT(instr)] = imm | gpr[RS(instr)]; gpr[RT(instr)] = imm | gpr[RS(instr)];
} }
void RSP::or_(u32 instr) {
gpr[RD(instr)] = gpr[RT(instr)] | gpr[RS(instr)];
}
void RSP::sb(u32 instr) { void RSP::sb(u32 instr) {
} }
@@ -165,7 +168,8 @@ void RSP::sh(u32 instr) {
} }
void RSP::sw(u32 instr) { void RSP::sw(u32 instr) {
u32 address = gpr[BASE(instr)] + (s16)instr;
WriteWord(address, gpr[RT(instr)]);
} }
void RSP::sqv(u32 instr) { void RSP::sqv(u32 instr) {
@@ -178,7 +182,8 @@ void RSP::sllv(u32 instr) {
} }
void RSP::sll(u32 instr) { void RSP::sll(u32 instr) {
u8 sa = (instr >> 6) & 0x1f;
gpr[RD(instr)] = gpr[RT(instr)] << sa;
} }
void RSP::vabs(u32 instr) { void RSP::vabs(u32 instr) {