fix pads, start RSP
This commit is contained in:
@@ -6,6 +6,9 @@ void App::Run() {
|
||||
// Main loop
|
||||
const u8* state = SDL_GetKeyboardState(nullptr);
|
||||
while (!core.done) {
|
||||
core.Run(window);
|
||||
core.UpdateController(state);
|
||||
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||
@@ -36,10 +39,6 @@ void App::Run() {
|
||||
} break;
|
||||
} break;
|
||||
}
|
||||
|
||||
core.UpdateController(state);
|
||||
}
|
||||
|
||||
core.Run(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <nfd.hpp>
|
||||
#include <Core.hpp>
|
||||
#include <utility>
|
||||
#include <Audio.hpp>
|
||||
|
||||
VkInstance instance{};
|
||||
|
||||
@@ -20,6 +21,8 @@ Window::Window(n64::Core& core) {
|
||||
|
||||
void Window::InitSDL() {
|
||||
SDL_Init(SDL_INIT_EVERYTHING);
|
||||
n64::InitAudio();
|
||||
|
||||
window = SDL_CreateWindow(
|
||||
"natsukashii",
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
|
||||
@@ -38,6 +38,7 @@ void Core::LoadROM(const std::string& rom_) {
|
||||
|
||||
void Core::Run(Window& window) {
|
||||
MMIO& mmio = mem.mmio;
|
||||
Controller& controller = mmio.si.controller;
|
||||
int cycles = 0;
|
||||
for(int field = 0; field < mmio.vi.numFields; field++) {
|
||||
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.ai.Step(mem, cpu.regs, 1);
|
||||
mmio.ai.Step(mem, cpu.regs, 1);
|
||||
}
|
||||
|
||||
cycles -= mmio.vi.cyclesPerHalfline;
|
||||
@@ -69,7 +70,7 @@ void Core::Run(Window& window) {
|
||||
UpdateScreenParallelRdp(*this, window, GetVI());
|
||||
|
||||
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) {
|
||||
UpdateScreenParallelRdp(*this, window, GetVI());
|
||||
} else if(pause && !romLoaded) {
|
||||
|
||||
@@ -12,7 +12,7 @@ static SDL_AudioStream* audioStream = nullptr;
|
||||
SDL_mutex* audioStreamMutex;
|
||||
SDL_AudioSpec audioSpec;
|
||||
SDL_AudioSpec request;
|
||||
SDL_AudioDeviceID audioDev;
|
||||
SDL_AudioDeviceID audioDev{};
|
||||
|
||||
#define LockAudioMutex() SDL_LockMutex(audioStreamMutex)
|
||||
#define UnlockAudioMutex() SDL_UnlockMutex(audioStreamMutex)
|
||||
@@ -48,7 +48,9 @@ void InitAudio() {
|
||||
request.callback = audioCallback;
|
||||
request.userdata = nullptr;
|
||||
|
||||
if(!audioDev) {
|
||||
audioDev = SDL_OpenAudioDevice(nullptr, 0, &request, &audioSpec, 0);
|
||||
}
|
||||
|
||||
if(!audioDev) {
|
||||
util::panic("Failed to initialize SDL Audio: {}", SDL_GetError());
|
||||
|
||||
@@ -59,8 +59,12 @@ void FireException(Registers& regs, ExceptionCode code, int cop, s64 pc) {
|
||||
util::panic("BEV bit set!\n");
|
||||
} else {
|
||||
switch(code) {
|
||||
case Interrupt ... TLBModification:
|
||||
case AddressErrorLoad ... Trap:
|
||||
case Interrupt: case TLBModification:
|
||||
case AddressErrorLoad: case AddressErrorStore:
|
||||
case InstructionBusError: case DataBusError:
|
||||
case Syscall: case Breakpoint:
|
||||
case ReservedInstruction: case CoprocessorUnusable:
|
||||
case Overflow: case Trap:
|
||||
case FloatingPointError: case Watch:
|
||||
regs.SetPC(s64(s32(0x80000180)));
|
||||
break;
|
||||
|
||||
@@ -7,16 +7,16 @@
|
||||
namespace n64 {
|
||||
struct Cpu {
|
||||
Cpu() {
|
||||
log = fopen("disasm.txt", "w");
|
||||
if(cs_open(CS_ARCH_MIPS, CS_MODE_MIPS64, &handle) != CS_ERR_OK) {
|
||||
util::panic("Could not initialize capstone!\n");
|
||||
}
|
||||
//log = fopen("disasm.txt", "w");
|
||||
//if(cs_open(CS_ARCH_MIPS, CS_MODE_MIPS64, &handle) != CS_ERR_OK) {
|
||||
// util::panic("Could not initialize capstone!\n");
|
||||
//}
|
||||
Reset();
|
||||
}
|
||||
|
||||
~Cpu() {
|
||||
fclose(log);
|
||||
cs_close(&handle);
|
||||
//fclose(log);
|
||||
//cs_close(&handle);
|
||||
}
|
||||
void Reset();
|
||||
void Step(Mem&);
|
||||
|
||||
@@ -33,8 +33,8 @@ void RSP::Step(MI& mi, Registers& regs, RDP& rdp) {
|
||||
if(!spStatus.halt) {
|
||||
gpr[0] = 0;
|
||||
u32 instr = util::ReadAccess<u32>(imem, pc & IMEM_DSIZE);
|
||||
oldPC = pc & 0xFFF;
|
||||
pc = nextPC & 0xFFF;
|
||||
oldPC = pc & 0xFFC;
|
||||
pc = nextPC & 0xFFC;
|
||||
nextPC += 4;
|
||||
Exec(mi, regs, rdp, instr);
|
||||
}
|
||||
@@ -120,7 +120,7 @@ void RSP::Write(Mem& mem, Registers& regs, u32 addr, u32 value) {
|
||||
if(spStatus.halt) {
|
||||
oldPC = pc;
|
||||
pc = nextPC;
|
||||
nextPC = value & 0xFFF;
|
||||
nextPC = value & 0xFFC;
|
||||
} break;
|
||||
default: util::panic("Unimplemented SP register write {:08X}, val: {:08X}\n", addr, value);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
#include <n64/core/RDP.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 {
|
||||
union SPStatus {
|
||||
u32 raw;
|
||||
@@ -154,6 +160,30 @@ struct RSP {
|
||||
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 addi(u32 instr);
|
||||
void and_(u32 instr);
|
||||
|
||||
@@ -11,9 +11,7 @@ Cop0::Cop0() {
|
||||
void Cop0::Reset() {
|
||||
cause.raw = 0xB000007C;
|
||||
status.raw = 0x241000E0;
|
||||
wired = 64;
|
||||
index = 64;
|
||||
PRId = 0x00000B00;
|
||||
PRId = 0x00000B22;
|
||||
Config = 0x7006E463;
|
||||
EPC = 0xFFFFFFFFFFFFFFFF;
|
||||
ErrorEPC = 0xFFFFFFFFFFFFFFFF;
|
||||
|
||||
@@ -72,8 +72,8 @@ void AI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
||||
}
|
||||
}
|
||||
|
||||
void AI::Step(Mem& mem, Registers& regs, int) {
|
||||
cycles += cycles;
|
||||
void AI::Step(Mem& mem, Registers& regs, int cpuCycles) {
|
||||
cycles += cpuCycles;
|
||||
while(cycles > dac.period) {
|
||||
if (dmaCount == 0) {
|
||||
return;
|
||||
|
||||
@@ -59,7 +59,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
||||
cartAddr = cart_addr + len;
|
||||
InterruptRaise(mi, regs, Interrupt::PI);
|
||||
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;
|
||||
case 0x0460000C: {
|
||||
u32 len = (val & 0x00FFFFFF) + 1;
|
||||
@@ -76,7 +76,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
||||
cartAddr = cart_addr + len;
|
||||
InterruptRaise(mi, regs, Interrupt::PI);
|
||||
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;
|
||||
case 0x04600010:
|
||||
if(val & 2) {
|
||||
|
||||
@@ -65,7 +65,7 @@ void ProcessPIFCommands(u8* pifRam, Controller& controller, Mem& mem) {
|
||||
pifRam[63] = 128;
|
||||
}
|
||||
|
||||
//mem->pif_ram[63] &= ~1;
|
||||
//pifRam[63] &= ~1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,23 +34,29 @@ void SI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
||||
dramAddr = val;
|
||||
break;
|
||||
case 0x04800004: {
|
||||
// if(!(status.raw & 3)) {
|
||||
if(!(status.raw & 3)) {
|
||||
ProcessPIFCommands(mem.pifRam, controller, mem);
|
||||
|
||||
u8 pifAddr = (val & 0x7FC) & PIF_RAM_DSIZE;
|
||||
memcpy(&mem.mmio.rdp.dram[dramAddr & RDRAM_DSIZE],
|
||||
&mem.pifRam[pifAddr], 64);
|
||||
pifAddr = (val & 0x7FC) & PIF_RAM_DSIZE;
|
||||
for(int i = 0; i < 64; i++) {
|
||||
mem.mmio.rdp.dram[BYTE_ADDRESS(dramAddr + i) & RDRAM_DSIZE] = mem.pifRam[pifAddr + i];
|
||||
}
|
||||
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;
|
||||
case 0x04800010: {
|
||||
//if(!(status.raw & 3)) {
|
||||
u8 pifAddr = (val & 0x7FC) & PIF_RAM_DSIZE;
|
||||
memcpy(&mem.pifRam[pifAddr],
|
||||
&mem.mmio.rdp.dram[dramAddr & RDRAM_DSIZE], 64);
|
||||
if(!(status.raw & 3)) {
|
||||
pifAddr = (val & 0x7FC) & PIF_RAM_DSIZE;
|
||||
for(int i = 0; i < 64; i++) {
|
||||
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);
|
||||
status.intr = 1;
|
||||
//util::logdebug("SI DMA from RDP RAM to PIF RAM ({:08X} to {:08X})\n", dramAddr, pifAddr);
|
||||
}
|
||||
} break;
|
||||
case 0x04800018:
|
||||
InterruptLower(mem.mmio.mi, regs, Interrupt::SI);
|
||||
|
||||
@@ -25,6 +25,7 @@ struct SI {
|
||||
void Reset();
|
||||
SIStatus status{};
|
||||
u32 dramAddr{};
|
||||
u32 pifAddr{};
|
||||
Controller controller{};
|
||||
|
||||
auto Read(MI&, u32) const -> u32;
|
||||
|
||||
@@ -1,26 +1,30 @@
|
||||
#include <n64/core/RSP.hpp>
|
||||
#include <util.hpp>
|
||||
#include <n64/core/cpu/Registers.hpp>
|
||||
#include <Interrupt.hpp>
|
||||
|
||||
namespace n64 {
|
||||
inline void special(RSP& rsp, u32 instr) {
|
||||
inline void special(MI& mi, Registers& regs, RSP& rsp, u32 instr) {
|
||||
u8 mask = instr & 0x3f;
|
||||
switch(mask) {
|
||||
//case 0x00: rsp.sll(instr); break;
|
||||
//case 0x04: rsp.sllv(instr); break;
|
||||
case 0x00: rsp.sll(instr); break;
|
||||
case 0x04: rsp.sllv(instr); break;
|
||||
//case 0x08: rsp.jr(instr); break;
|
||||
//case 0x0C:
|
||||
//case 0x0D:
|
||||
// rsp.spStatus.halt = true;
|
||||
// rsp.spStatus.broke = true;
|
||||
// break;
|
||||
case 0x0C:
|
||||
case 0x0D:
|
||||
rsp.spStatus.halt = true;
|
||||
rsp.spStatus.broke = true;
|
||||
if(rsp.spStatus.interruptOnBreak) {
|
||||
InterruptRaise(mi, regs, Interrupt::SP);
|
||||
}
|
||||
break;
|
||||
//case 0x20: case 0x21:
|
||||
// rsp.add(instr);
|
||||
// break;
|
||||
//case 0x24: rsp.and_(instr); break;
|
||||
//case 0x25: rsp.or_(instr); break;
|
||||
case 0x24: rsp.and_(instr); break;
|
||||
case 0x25: rsp.or_(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:
|
||||
switch(mask_sub) {
|
||||
//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;
|
||||
//case 0x13: rsp.vabs(instr); break;
|
||||
@@ -64,40 +68,40 @@ inline void cop2(RSP& rsp, u32 instr) {
|
||||
//case 0x21: rsp.veq(instr); break;
|
||||
//case 0x22: rsp.vne(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) {
|
||||
u8 mask = (instr >> 21) & 0x1F;
|
||||
switch(mask) {
|
||||
//case 0x00: rsp.mfc0(rdp, instr); break;
|
||||
//case 0x04: rsp.mtc0(mi, regs, rdp, instr); break;
|
||||
default: util::panic("Unhandled RSP COP0 {} {}\n", (mask >> 3) & 3, mask & 7);
|
||||
case 0x00: rsp.mfc0(rdp, instr); break;
|
||||
case 0x04: rsp.mtc0(mi, regs, rdp, instr); break;
|
||||
default: util::panic("Unhandled RSP COP0 ({:06b})\n", mask);
|
||||
}
|
||||
}
|
||||
|
||||
void RSP::Exec(MI &mi, Registers ®s, RDP &rdp, u32 instr) {
|
||||
u8 mask = (instr >> 26) & 0x3F;
|
||||
switch(mask) {
|
||||
//case 0x00: special(*this, instr); break;
|
||||
case 0x00: special(mi, regs, *this, instr); break;
|
||||
case 0x01: regimm(*this, instr); break;
|
||||
case 0x02: j(instr); break;
|
||||
//case 0x03: jal(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 0x07: b(instr, gpr[RS(instr)] > 0); break;
|
||||
case 0x03: jal(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 0x07: b(instr, gpr[RS(instr)] > 0); break;
|
||||
case 0x08: case 0x09: addi(instr); break;
|
||||
//case 0x0C: andi(instr); break;
|
||||
case 0x0C: andi(instr); break;
|
||||
case 0x0D: ori(instr); break;
|
||||
//case 0x0F: lui(instr); break;
|
||||
//case 0x10: cop0(mi, regs, *this, rdp, instr); break;
|
||||
case 0x0F: lui(instr); break;
|
||||
case 0x10: cop0(mi, regs, *this, rdp, instr); break;
|
||||
//case 0x12: cop2(*this, instr); break;
|
||||
//case 0x21: lh(instr); break;
|
||||
//case 0x23: lw(instr); break;
|
||||
case 0x23: lw(instr); break;
|
||||
//case 0x28: sb(instr); break;
|
||||
//case 0x29: sh(instr); break;
|
||||
//case 0x2B: sw(instr); break;
|
||||
case 0x2B: sw(instr); break;
|
||||
//case 0x32: lwc2(*this, instr); break;
|
||||
//case 0x3A: swc2(*this, instr); break;
|
||||
default: util::panic("Unhandled RSP instruction ({:06b})\n", mask);
|
||||
|
||||
@@ -98,11 +98,11 @@ void RSP::addi(u32 instr) {
|
||||
}
|
||||
|
||||
void RSP::and_(u32 instr) {
|
||||
|
||||
gpr[RD(instr)] = gpr[RT(instr)] & gpr[RS(instr)];
|
||||
}
|
||||
|
||||
void RSP::andi(u32 instr) {
|
||||
|
||||
gpr[RT(instr)] = gpr[RS(instr)] & (u16)instr;
|
||||
}
|
||||
|
||||
void RSP::cfc2(u32 instr) {
|
||||
@@ -119,11 +119,13 @@ void RSP::lh(u32 instr) {
|
||||
}
|
||||
|
||||
void RSP::lw(u32 instr) {
|
||||
|
||||
u32 address = gpr[BASE(instr)] + (s16)instr;
|
||||
gpr[RT(instr)] = ReadWord(address);
|
||||
}
|
||||
|
||||
void RSP::lui(u32 instr) {
|
||||
|
||||
u32 imm = ((u16)instr) << 16;
|
||||
gpr[RT(instr)] = imm;
|
||||
}
|
||||
|
||||
void RSP::lqv(u32 instr) {
|
||||
@@ -136,7 +138,8 @@ void RSP::j(u32 instr) {
|
||||
}
|
||||
|
||||
void RSP::jal(u32 instr) {
|
||||
|
||||
gpr[31] = nextPC;
|
||||
j(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) {
|
||||
s16 imm = 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) {
|
||||
|
||||
}
|
||||
@@ -165,7 +168,8 @@ void RSP::sh(u32 instr) {
|
||||
}
|
||||
|
||||
void RSP::sw(u32 instr) {
|
||||
|
||||
u32 address = gpr[BASE(instr)] + (s16)instr;
|
||||
WriteWord(address, gpr[RT(instr)]);
|
||||
}
|
||||
|
||||
void RSP::sqv(u32 instr) {
|
||||
@@ -178,7 +182,8 @@ void RSP::sllv(u32 instr) {
|
||||
}
|
||||
|
||||
void RSP::sll(u32 instr) {
|
||||
|
||||
u8 sa = (instr >> 6) & 0x1f;
|
||||
gpr[RD(instr)] = gpr[RT(instr)] << sa;
|
||||
}
|
||||
|
||||
void RSP::vabs(u32 instr) {
|
||||
|
||||
Reference in New Issue
Block a user