move controller logic to PIF
This commit is contained in:
@@ -2,7 +2,6 @@
|
|||||||
#include <ParallelRDPWrapper.hpp>
|
#include <ParallelRDPWrapper.hpp>
|
||||||
#include <Window.hpp>
|
#include <Window.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <MupenMovie.hpp>
|
|
||||||
#include <Scheduler.hpp>
|
#include <Scheduler.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
@@ -29,7 +28,7 @@ CartInfo Core::LoadROM(const std::string& rom_) {
|
|||||||
|
|
||||||
CartInfo cartInfo = mem.LoadROM(rom);
|
CartInfo cartInfo = mem.LoadROM(rom);
|
||||||
isPAL = cartInfo.isPAL;
|
isPAL = cartInfo.isPAL;
|
||||||
ExecutePIF(mem, CpuGetRegs(), cartInfo);
|
mem.mmio.si.pif.ExecutePIF(mem, CpuGetRegs(), cartInfo);
|
||||||
|
|
||||||
return cartInfo;
|
return cartInfo;
|
||||||
}
|
}
|
||||||
@@ -87,98 +86,5 @@ void Core::Run(Window& window, float volumeL, float volumeR) {
|
|||||||
UpdateScreenParallelRdpNoGame(*this, window);
|
UpdateScreenParallelRdpNoGame(*this, window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(debugger.enabled)
|
|
||||||
debugger.tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GET_BUTTON(gamepad, i) SDL_GameControllerGetButton(gamepad, i)
|
|
||||||
#define GET_AXIS(gamepad, axis) SDL_GameControllerGetAxis(gamepad, axis)
|
|
||||||
|
|
||||||
void Core::UpdateController(const u8* state) {
|
|
||||||
Controller &controller = mem.mmio.si.controller;
|
|
||||||
s8 xaxis = 0, yaxis = 0;
|
|
||||||
|
|
||||||
if(gamepadConnected) {
|
|
||||||
bool A = GET_BUTTON(gamepad, SDL_CONTROLLER_BUTTON_A);
|
|
||||||
bool B = GET_BUTTON(gamepad, SDL_CONTROLLER_BUTTON_X);
|
|
||||||
bool Z = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_TRIGGERLEFT) == 32767;
|
|
||||||
bool START = GET_BUTTON(gamepad, SDL_CONTROLLER_BUTTON_START);
|
|
||||||
bool DUP = GET_BUTTON(gamepad, SDL_CONTROLLER_BUTTON_DPAD_UP);
|
|
||||||
bool DDOWN = GET_BUTTON(gamepad, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
|
|
||||||
bool DLEFT = GET_BUTTON(gamepad, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
|
|
||||||
bool DRIGHT = GET_BUTTON(gamepad, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
|
|
||||||
bool L = GET_BUTTON(gamepad, SDL_CONTROLLER_BUTTON_LEFTSHOULDER);
|
|
||||||
bool R = GET_BUTTON(gamepad, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
|
|
||||||
bool CUP = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_RIGHTY) <= -128;
|
|
||||||
bool CDOWN = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_RIGHTY) >= 127;
|
|
||||||
bool CLEFT = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_RIGHTX) <= -128;
|
|
||||||
bool CRIGHT = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_RIGHTX) >= 127;
|
|
||||||
|
|
||||||
controller.a = A;
|
|
||||||
controller.b = B;
|
|
||||||
controller.z = Z;
|
|
||||||
controller.start = START;
|
|
||||||
controller.dp_up = DUP;
|
|
||||||
controller.dp_down = DDOWN;
|
|
||||||
controller.dp_left = DLEFT;
|
|
||||||
controller.dp_right = DRIGHT;
|
|
||||||
controller.joy_reset = L && R && START;
|
|
||||||
controller.l = L;
|
|
||||||
controller.r = R;
|
|
||||||
controller.c_up = CUP;
|
|
||||||
controller.c_down = CDOWN;
|
|
||||||
controller.c_left = CLEFT;
|
|
||||||
controller.c_right = CRIGHT;
|
|
||||||
|
|
||||||
xaxis = (s8) std::clamp((GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_LEFTX) >> 8), -86, 86);
|
|
||||||
yaxis = (s8) std::clamp(-(GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_LEFTY) >> 8), -86, 86);
|
|
||||||
|
|
||||||
controller.joy_x = xaxis;
|
|
||||||
controller.joy_y = yaxis;
|
|
||||||
|
|
||||||
if (controller.joy_reset) {
|
|
||||||
controller.start = false;
|
|
||||||
controller.joy_x = 0;
|
|
||||||
controller.joy_y = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
controller.a = state[SDL_SCANCODE_X];
|
|
||||||
controller.b = state[SDL_SCANCODE_C];
|
|
||||||
controller.z = state[SDL_SCANCODE_Z];
|
|
||||||
controller.start = state[SDL_SCANCODE_RETURN];
|
|
||||||
controller.dp_up = state[SDL_SCANCODE_KP_8];
|
|
||||||
controller.dp_down = state[SDL_SCANCODE_KP_5];
|
|
||||||
controller.dp_left = state[SDL_SCANCODE_KP_4];
|
|
||||||
controller.dp_right = state[SDL_SCANCODE_KP_6];
|
|
||||||
controller.joy_reset = state[SDL_SCANCODE_RETURN] && state[SDL_SCANCODE_A] && state[SDL_SCANCODE_S];
|
|
||||||
controller.l = state[SDL_SCANCODE_A];
|
|
||||||
controller.r = state[SDL_SCANCODE_S];
|
|
||||||
controller.c_up = state[SDL_SCANCODE_I];
|
|
||||||
controller.c_down = state[SDL_SCANCODE_J];
|
|
||||||
controller.c_left = state[SDL_SCANCODE_K];
|
|
||||||
controller.c_right = state[SDL_SCANCODE_L];
|
|
||||||
|
|
||||||
if (state[SDL_SCANCODE_LEFT]) {
|
|
||||||
xaxis = -86;
|
|
||||||
} else if (state[SDL_SCANCODE_RIGHT]) {
|
|
||||||
xaxis = 86;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state[SDL_SCANCODE_DOWN]) {
|
|
||||||
yaxis = -86;
|
|
||||||
} else if (state[SDL_SCANCODE_UP]) {
|
|
||||||
yaxis = 86;
|
|
||||||
}
|
|
||||||
|
|
||||||
controller.joy_x = xaxis;
|
|
||||||
controller.joy_y = yaxis;
|
|
||||||
|
|
||||||
if (controller.joy_reset) {
|
|
||||||
controller.start = false;
|
|
||||||
controller.joy_x = 0;
|
|
||||||
controller.joy_y = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,11 +21,10 @@ struct Core {
|
|||||||
void Stop();
|
void Stop();
|
||||||
CartInfo LoadROM(const std::string&);
|
CartInfo LoadROM(const std::string&);
|
||||||
void Run(Window&, float volumeL, float volumeR);
|
void Run(Window&, float volumeL, float volumeR);
|
||||||
void UpdateController(const u8*);
|
|
||||||
void TogglePause() { pause = !pause; }
|
void TogglePause() { pause = !pause; }
|
||||||
VI& GetVI() { return mem.mmio.vi; }
|
VI& GetVI() { return mem.mmio.vi; }
|
||||||
|
|
||||||
void CpuReset() {
|
void CpuReset() const {
|
||||||
switch(cpuType) {
|
switch(cpuType) {
|
||||||
case CpuType::Dynarec: cpuDynarec->Reset(); break;
|
case CpuType::Dynarec: cpuDynarec->Reset(); break;
|
||||||
case CpuType::Interpreter: cpuInterp->Reset(); break;
|
case CpuType::Interpreter: cpuInterp->Reset(); break;
|
||||||
@@ -33,7 +32,7 @@ struct Core {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Registers& CpuGetRegs() {
|
[[nodiscard]] Registers& CpuGetRegs() const {
|
||||||
switch(cpuType) {
|
switch(cpuType) {
|
||||||
case CpuType::Dynarec: return cpuDynarec->regs;
|
case CpuType::Dynarec: return cpuDynarec->regs;
|
||||||
case CpuType::Interpreter: return cpuInterp->regs;
|
case CpuType::Interpreter: return cpuInterp->regs;
|
||||||
@@ -43,13 +42,6 @@ struct Core {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int CpuStep(Core& core) {
|
static int CpuStep(Core& core) {
|
||||||
if (core.debugger.enabled && core.debugger.checkBreakpoint(core.CpuGetRegs().pc)) {
|
|
||||||
core.debugger.breakpointHit();
|
|
||||||
}
|
|
||||||
while (core.debugger.broken) {
|
|
||||||
SDL_Delay(1);
|
|
||||||
core.debugger.tick();
|
|
||||||
}
|
|
||||||
switch(core.cpuType) {
|
switch(core.cpuType) {
|
||||||
case CpuType::Dynarec: return core.cpuDynarec->Step(core.mem);
|
case CpuType::Dynarec: return core.cpuDynarec->Step(core.mem);
|
||||||
case CpuType::Interpreter: core.cpuInterp->Step(core.mem); return 1;
|
case CpuType::Interpreter: core.cpuInterp->Step(core.mem); return 1;
|
||||||
@@ -63,8 +55,6 @@ struct Core {
|
|||||||
bool pause = true;
|
bool pause = true;
|
||||||
bool isPAL = false;
|
bool isPAL = false;
|
||||||
bool romLoaded = false;
|
bool romLoaded = false;
|
||||||
SDL_GameController* gamepad;
|
|
||||||
bool gamepadConnected = false;
|
|
||||||
bool done = false;
|
bool done = false;
|
||||||
std::string rom;
|
std::string rom;
|
||||||
Mem mem;
|
Mem mem;
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ u8 Mem::Read8(n64::Registers ®s, u32 paddr) {
|
|||||||
const auto page = paddr >> 12;
|
const auto page = paddr >> 12;
|
||||||
const auto offset = paddr & 0xFFF;
|
const auto offset = paddr & 0xFFF;
|
||||||
const auto pointer = readPages[page];
|
const auto pointer = readPages[page];
|
||||||
|
SI& si = mmio.si;
|
||||||
|
|
||||||
if(pointer) {
|
if(pointer) {
|
||||||
return ((u8*)pointer)[BYTE_ADDRESS(offset)];
|
return ((u8*)pointer)[BYTE_ADDRESS(offset)];
|
||||||
@@ -95,9 +96,9 @@ u8 Mem::Read8(n64::Registers ®s, u32 paddr) {
|
|||||||
paddr = (paddr + 2) & ~2;
|
paddr = (paddr + 2) & ~2;
|
||||||
return cart[BYTE_ADDRESS(paddr) & romMask];
|
return cart[BYTE_ADDRESS(paddr) & romMask];
|
||||||
case 0x1FC00000 ... 0x1FC007BF:
|
case 0x1FC00000 ... 0x1FC007BF:
|
||||||
return pifBootrom[BYTE_ADDRESS(paddr) - 0x1FC00000];
|
return si.pif.pifBootrom[BYTE_ADDRESS(paddr) - 0x1FC00000];
|
||||||
case PIF_RAM_REGION:
|
case PIF_RAM_REGION:
|
||||||
return pifRam[paddr - PIF_RAM_REGION_START];
|
return si.pif.pifRam[paddr - PIF_RAM_REGION_START];
|
||||||
case 0x00800000 ... 0x03FFFFFF:
|
case 0x00800000 ... 0x03FFFFFF:
|
||||||
case 0x04200000 ... 0x042FFFFF:
|
case 0x04200000 ... 0x042FFFFF:
|
||||||
case 0x04900000 ... 0x0FFFFFFF:
|
case 0x04900000 ... 0x0FFFFFFF:
|
||||||
@@ -113,6 +114,7 @@ u16 Mem::Read16(n64::Registers ®s, u32 paddr) {
|
|||||||
const auto page = paddr >> 12;
|
const auto page = paddr >> 12;
|
||||||
const auto offset = paddr & 0xFFF;
|
const auto offset = paddr & 0xFFF;
|
||||||
const auto pointer = readPages[page];
|
const auto pointer = readPages[page];
|
||||||
|
SI& si = mmio.si;
|
||||||
|
|
||||||
if(pointer) {
|
if(pointer) {
|
||||||
return Util::ReadAccess<u16>((u8*)pointer, HALF_ADDRESS(offset));
|
return Util::ReadAccess<u16>((u8*)pointer, HALF_ADDRESS(offset));
|
||||||
@@ -134,9 +136,9 @@ u16 Mem::Read16(n64::Registers ®s, u32 paddr) {
|
|||||||
paddr = (paddr + 2) & ~3;
|
paddr = (paddr + 2) & ~3;
|
||||||
return Util::ReadAccess<u16>(cart, HALF_ADDRESS(paddr) & romMask);
|
return Util::ReadAccess<u16>(cart, HALF_ADDRESS(paddr) & romMask);
|
||||||
case 0x1FC00000 ... 0x1FC007BF:
|
case 0x1FC00000 ... 0x1FC007BF:
|
||||||
return Util::ReadAccess<u16>(pifBootrom, HALF_ADDRESS(paddr) - 0x1FC00000);
|
return Util::ReadAccess<u16>(si.pif.pifBootrom, HALF_ADDRESS(paddr) - 0x1FC00000);
|
||||||
case PIF_RAM_REGION:
|
case PIF_RAM_REGION:
|
||||||
return be16toh(Util::ReadAccess<u16>(pifRam, paddr - PIF_RAM_REGION_START));
|
return be16toh(Util::ReadAccess<u16>(si.pif.pifRam, paddr - PIF_RAM_REGION_START));
|
||||||
case 0x00800000 ... 0x03FFFFFF:
|
case 0x00800000 ... 0x03FFFFFF:
|
||||||
case 0x04200000 ... 0x042FFFFF:
|
case 0x04200000 ... 0x042FFFFF:
|
||||||
case 0x04900000 ... 0x0FFFFFFF:
|
case 0x04900000 ... 0x0FFFFFFF:
|
||||||
@@ -152,6 +154,7 @@ u32 Mem::Read32(n64::Registers ®s, u32 paddr) {
|
|||||||
const auto page = paddr >> 12;
|
const auto page = paddr >> 12;
|
||||||
const auto offset = paddr & 0xFFF;
|
const auto offset = paddr & 0xFFF;
|
||||||
const auto pointer = readPages[page];
|
const auto pointer = readPages[page];
|
||||||
|
SI& si = mmio.si;
|
||||||
|
|
||||||
if(pointer) {
|
if(pointer) {
|
||||||
return Util::ReadAccess<u32>((u8*)pointer, offset);
|
return Util::ReadAccess<u32>((u8*)pointer, offset);
|
||||||
@@ -170,9 +173,9 @@ u32 Mem::Read32(n64::Registers ®s, u32 paddr) {
|
|||||||
case 0x10000000 ... 0x1FBFFFFF:
|
case 0x10000000 ... 0x1FBFFFFF:
|
||||||
return Util::ReadAccess<u32>(cart, paddr & romMask);
|
return Util::ReadAccess<u32>(cart, paddr & romMask);
|
||||||
case 0x1FC00000 ... 0x1FC007BF:
|
case 0x1FC00000 ... 0x1FC007BF:
|
||||||
return Util::ReadAccess<u32>(pifBootrom, paddr - 0x1FC00000);
|
return Util::ReadAccess<u32>(si.pif.pifBootrom, paddr - 0x1FC00000);
|
||||||
case PIF_RAM_REGION:
|
case PIF_RAM_REGION:
|
||||||
return be32toh(Util::ReadAccess<u32>(pifRam, paddr - PIF_RAM_REGION_START));
|
return be32toh(Util::ReadAccess<u32>(si.pif.pifRam, paddr - PIF_RAM_REGION_START));
|
||||||
case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF:
|
case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF:
|
||||||
case 0x04900000 ... 0x0FFFFFFF: case 0x1FC00800 ... 0xFFFFFFFF: return 0;
|
case 0x04900000 ... 0x0FFFFFFF: case 0x1FC00800 ... 0xFFFFFFFF: return 0;
|
||||||
default:
|
default:
|
||||||
@@ -185,6 +188,7 @@ u64 Mem::Read64(n64::Registers ®s, u32 paddr) {
|
|||||||
const auto page = paddr >> 12;
|
const auto page = paddr >> 12;
|
||||||
const auto offset = paddr & 0xFFF;
|
const auto offset = paddr & 0xFFF;
|
||||||
const auto pointer = readPages[page];
|
const auto pointer = readPages[page];
|
||||||
|
SI& si = mmio.si;
|
||||||
|
|
||||||
if(pointer) {
|
if(pointer) {
|
||||||
return Util::ReadAccess<u64>((u8*)pointer, offset);
|
return Util::ReadAccess<u64>((u8*)pointer, offset);
|
||||||
@@ -205,9 +209,9 @@ u64 Mem::Read64(n64::Registers ®s, u32 paddr) {
|
|||||||
case 0x10000000 ... 0x1FBFFFFF:
|
case 0x10000000 ... 0x1FBFFFFF:
|
||||||
return Util::ReadAccess<u64>(cart, paddr & romMask);
|
return Util::ReadAccess<u64>(cart, paddr & romMask);
|
||||||
case 0x1FC00000 ... 0x1FC007BF:
|
case 0x1FC00000 ... 0x1FC007BF:
|
||||||
return Util::ReadAccess<u64>(pifBootrom, paddr - 0x1FC00000);
|
return Util::ReadAccess<u64>(si.pif.pifBootrom, paddr - 0x1FC00000);
|
||||||
case PIF_RAM_REGION:
|
case PIF_RAM_REGION:
|
||||||
return be64toh(Util::ReadAccess<u64>(pifRam, paddr - PIF_RAM_REGION_START));
|
return be64toh(Util::ReadAccess<u64>(si.pif.pifRam, paddr - PIF_RAM_REGION_START));
|
||||||
case 0x00800000 ... 0x03FFFFFF:
|
case 0x00800000 ... 0x03FFFFFF:
|
||||||
case 0x04200000 ... 0x042FFFFF:
|
case 0x04200000 ... 0x042FFFFF:
|
||||||
case 0x04900000 ... 0x0FFFFFFF:
|
case 0x04900000 ... 0x0FFFFFFF:
|
||||||
@@ -243,6 +247,7 @@ void Mem::Write8(Registers& regs, u32 paddr, u32 val) {
|
|||||||
const auto page = paddr >> 12;
|
const auto page = paddr >> 12;
|
||||||
auto offset = paddr & 0xFFF;
|
auto offset = paddr & 0xFFF;
|
||||||
const auto pointer = writePages[page];
|
const auto pointer = writePages[page];
|
||||||
|
SI& si = mmio.si;
|
||||||
|
|
||||||
if(pointer) {
|
if(pointer) {
|
||||||
((u8*)pointer)[BYTE_ADDRESS(offset)] = val;
|
((u8*)pointer)[BYTE_ADDRESS(offset)] = val;
|
||||||
@@ -269,8 +274,8 @@ void Mem::Write8(Registers& regs, u32 paddr, u32 val) {
|
|||||||
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;
|
||||||
Util::WriteAccess<u32>(pifRam, paddr, htobe32(val));
|
Util::WriteAccess<u32>(si.pif.pifRam, paddr, htobe32(val));
|
||||||
ProcessPIFCommands(pifRam, mmio.si.controller, *this);
|
si.pif.ProcessPIFCommands(*this);
|
||||||
break;
|
break;
|
||||||
case 0x00800000 ... 0x03FFFFFF:
|
case 0x00800000 ... 0x03FFFFFF:
|
||||||
case 0x04200000 ... 0x042FFFFF:
|
case 0x04200000 ... 0x042FFFFF:
|
||||||
@@ -290,6 +295,7 @@ void Mem::Write16(Registers& regs, u32 paddr, u32 val) {
|
|||||||
const auto page = paddr >> 12;
|
const auto page = paddr >> 12;
|
||||||
auto offset = paddr & 0xFFF;
|
auto offset = paddr & 0xFFF;
|
||||||
const auto pointer = writePages[page];
|
const auto pointer = writePages[page];
|
||||||
|
SI& si = mmio.si;
|
||||||
|
|
||||||
if(pointer) {
|
if(pointer) {
|
||||||
Util::WriteAccess<u16>((u8*)pointer, HALF_ADDRESS(offset), val);
|
Util::WriteAccess<u16>((u8*)pointer, HALF_ADDRESS(offset), val);
|
||||||
@@ -316,8 +322,8 @@ void Mem::Write16(Registers& regs, u32 paddr, u32 val) {
|
|||||||
case PIF_RAM_REGION:
|
case PIF_RAM_REGION:
|
||||||
val = val << (16 * !(paddr & 2));
|
val = val << (16 * !(paddr & 2));
|
||||||
paddr &= ~3;
|
paddr &= ~3;
|
||||||
Util::WriteAccess<u32>(pifRam, paddr - PIF_RAM_REGION_START, htobe32(val));
|
Util::WriteAccess<u32>(si.pif.pifRam, paddr - PIF_RAM_REGION_START, htobe32(val));
|
||||||
ProcessPIFCommands(pifRam, mmio.si.controller, *this);
|
si.pif.ProcessPIFCommands(*this);
|
||||||
break;
|
break;
|
||||||
case 0x00800000 ... 0x03FFFFFF:
|
case 0x00800000 ... 0x03FFFFFF:
|
||||||
case 0x04200000 ... 0x042FFFFF:
|
case 0x04200000 ... 0x042FFFFF:
|
||||||
@@ -337,6 +343,7 @@ void Mem::Write32(Registers& regs, u32 paddr, u32 val) {
|
|||||||
const auto page = paddr >> 12;
|
const auto page = paddr >> 12;
|
||||||
auto offset = paddr & 0xFFF;
|
auto offset = paddr & 0xFFF;
|
||||||
const auto pointer = writePages[page];
|
const auto pointer = writePages[page];
|
||||||
|
SI& si = mmio.si;
|
||||||
|
|
||||||
if(pointer) {
|
if(pointer) {
|
||||||
Util::WriteAccess<u32>((u8*)pointer, offset, val);
|
Util::WriteAccess<u32>((u8*)pointer, offset, val);
|
||||||
@@ -367,8 +374,8 @@ void Mem::Write32(Registers& regs, u32 paddr, u32 val) {
|
|||||||
break;
|
break;
|
||||||
case 0x14000000 ... 0x1FBFFFFF: break;
|
case 0x14000000 ... 0x1FBFFFFF: break;
|
||||||
case PIF_RAM_REGION:
|
case PIF_RAM_REGION:
|
||||||
Util::WriteAccess<u32>(pifRam, paddr - PIF_RAM_REGION_START, htobe32(val));
|
Util::WriteAccess<u32>(si.pif.pifRam, paddr - PIF_RAM_REGION_START, htobe32(val));
|
||||||
ProcessPIFCommands(pifRam, mmio.si.controller, *this);
|
si.pif.ProcessPIFCommands(*this);
|
||||||
break;
|
break;
|
||||||
case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF:
|
case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF:
|
||||||
case 0x08000000 ... 0x0FFFFFFF: case 0x04900000 ... 0x07FFFFFF:
|
case 0x08000000 ... 0x0FFFFFFF: case 0x04900000 ... 0x07FFFFFF:
|
||||||
@@ -382,6 +389,7 @@ void Mem::Write64(Registers& regs, u32 paddr, u64 val) {
|
|||||||
const auto page = paddr >> 12;
|
const auto page = paddr >> 12;
|
||||||
auto offset = paddr & 0xFFF;
|
auto offset = paddr & 0xFFF;
|
||||||
const auto pointer = writePages[page];
|
const auto pointer = writePages[page];
|
||||||
|
SI& si = mmio.si;
|
||||||
|
|
||||||
if(pointer) {
|
if(pointer) {
|
||||||
Util::WriteAccess<u64>((u8*)pointer, offset, val);
|
Util::WriteAccess<u64>((u8*)pointer, offset, val);
|
||||||
@@ -405,8 +413,8 @@ void Mem::Write64(Registers& regs, u32 paddr, u64 val) {
|
|||||||
case 0x10000000 ... 0x1FBFFFFF:
|
case 0x10000000 ... 0x1FBFFFFF:
|
||||||
break;
|
break;
|
||||||
case PIF_RAM_REGION:
|
case PIF_RAM_REGION:
|
||||||
Util::WriteAccess<u64>(pifRam, paddr - PIF_RAM_REGION_START, htobe64(val));
|
Util::WriteAccess<u64>(si.pif.pifRam, paddr - PIF_RAM_REGION_START, htobe64(val));
|
||||||
ProcessPIFCommands(pifRam, mmio.si.controller, *this);
|
si.pif.ProcessPIFCommands(*this);
|
||||||
break;
|
break;
|
||||||
case 0x00800000 ... 0x03FFFFFF:
|
case 0x00800000 ... 0x03FFFFFF:
|
||||||
case 0x04200000 ... 0x042FFFFF:
|
case 0x04200000 ... 0x042FFFFF:
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ struct Mem {
|
|||||||
void Write64(Registers&, u32, u64);
|
void Write64(Registers&, u32, u64);
|
||||||
|
|
||||||
MMIO mmio;
|
MMIO mmio;
|
||||||
u8 pifRam[PIF_RAM_SIZE]{};
|
|
||||||
|
|
||||||
inline void DumpRDRAM() const {
|
inline void DumpRDRAM() const {
|
||||||
FILE *fp = fopen("rdram.dump", "wb");
|
FILE *fp = fopen("rdram.dump", "wb");
|
||||||
@@ -83,7 +82,6 @@ private:
|
|||||||
friend struct RSP;
|
friend struct RSP;
|
||||||
friend struct Core;
|
friend struct Core;
|
||||||
u8* sram, *cart;
|
u8* sram, *cart;
|
||||||
u8 pifBootrom[PIF_BOOTROM_SIZE]{};
|
|
||||||
u8 isviewer[ISVIEWER_SIZE]{};
|
u8 isviewer[ISVIEWER_SIZE]{};
|
||||||
size_t romMask = 0;
|
size_t romMask = 0;
|
||||||
|
|
||||||
@@ -119,12 +117,6 @@ private:
|
|||||||
return std::any_of(std::begin(pal_codes), std::end(pal_codes), [this](char a) {
|
return std::any_of(std::begin(pal_codes), std::end(pal_codes), [this](char a) {
|
||||||
return cart[0x3e] == a;
|
return cart[0x3e] == a;
|
||||||
});
|
});
|
||||||
// for (char pal_code : pal_codes) {
|
|
||||||
// if (cart[0x3e] == pal_code) {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return false;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ void RSP::Reset() {
|
|||||||
divInLoaded = false;
|
divInLoaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
inline void logRSP(const RSP& rsp, const u32 instr) {
|
inline void logRSP(const RSP& rsp, const u32 instr) {
|
||||||
Util::print("{:04X} {:08X} ", rsp.oldPC, instr);
|
Util::print("{:04X} {:08X} ", rsp.oldPC, instr);
|
||||||
for (auto gpr : rsp.gpr) {
|
for (auto gpr : rsp.gpr) {
|
||||||
@@ -63,6 +64,7 @@ inline void logRSP(const RSP& rsp, const u32 instr) {
|
|||||||
Util::print(" {:04X} {:04X} {:02X}\n", rsp.GetVCC(), rsp.GetVCO(), rsp.GetVCE());
|
Util::print(" {:04X} {:04X} {:02X}\n", rsp.GetVCC(), rsp.GetVCO(), rsp.GetVCE());
|
||||||
Util::print("DMEM: {:02X}{:02X}\n", rsp.dmem[0x3c4], rsp.dmem[0x3c5]);
|
Util::print("DMEM: {:02X}{:02X}\n", rsp.dmem[0x3c4], rsp.dmem[0x3c5]);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void RSP::Step(Registers& regs, Mem& mem) {
|
void RSP::Step(Registers& regs, Mem& mem) {
|
||||||
gpr[0] = 0;
|
gpr[0] = 0;
|
||||||
|
|||||||
@@ -3,11 +3,12 @@
|
|||||||
#include <core/registers/Registers.hpp>
|
#include <core/registers/Registers.hpp>
|
||||||
#include <log.hpp>
|
#include <log.hpp>
|
||||||
#include <MupenMovie.hpp>
|
#include <MupenMovie.hpp>
|
||||||
|
#include <SDL_keyboard.h>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
static int channel = 0;
|
static int channel = 0;
|
||||||
|
|
||||||
void ProcessPIFCommands(u8* pifRam, Controller& controller, Mem& mem) {
|
void PIF::ProcessPIFCommands(Mem& mem) {
|
||||||
u8 control = pifRam[63];
|
u8 control = pifRam[63];
|
||||||
|
|
||||||
if(control & 1) {
|
if(control & 1) {
|
||||||
@@ -46,6 +47,8 @@ void ProcessPIFCommands(u8* pifRam, Controller& controller, Mem& mem) {
|
|||||||
case 1:
|
case 1:
|
||||||
if(tas_movie_loaded()) {
|
if(tas_movie_loaded()) {
|
||||||
controller = tas_next_inputs();
|
controller = tas_next_inputs();
|
||||||
|
} else {
|
||||||
|
UpdateController();
|
||||||
}
|
}
|
||||||
res[0] = controller.byte1;
|
res[0] = controller.byte1;
|
||||||
res[1] = controller.byte2;
|
res[1] = controller.byte2;
|
||||||
@@ -70,7 +73,97 @@ void ProcessPIFCommands(u8* pifRam, Controller& controller, Mem& mem) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoPIFHLE(Mem& mem, Registers& regs, CartInfo cartInfo) {
|
#define GET_BUTTON(gamepad, i) SDL_GameControllerGetButton(gamepad, i)
|
||||||
|
#define GET_AXIS(gamepad, axis) SDL_GameControllerGetAxis(gamepad, axis)
|
||||||
|
|
||||||
|
void PIF::UpdateController() {
|
||||||
|
const uint8_t* state = SDL_GetKeyboardState(nullptr);
|
||||||
|
s8 xaxis = 0, yaxis = 0;
|
||||||
|
|
||||||
|
if(gamepadConnected) {
|
||||||
|
bool A = GET_BUTTON(gamepad, SDL_CONTROLLER_BUTTON_A);
|
||||||
|
bool B = GET_BUTTON(gamepad, SDL_CONTROLLER_BUTTON_X);
|
||||||
|
bool Z = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_TRIGGERLEFT) == 32767;
|
||||||
|
bool START = GET_BUTTON(gamepad, SDL_CONTROLLER_BUTTON_START);
|
||||||
|
bool DUP = GET_BUTTON(gamepad, SDL_CONTROLLER_BUTTON_DPAD_UP);
|
||||||
|
bool DDOWN = GET_BUTTON(gamepad, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
|
||||||
|
bool DLEFT = GET_BUTTON(gamepad, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
|
||||||
|
bool DRIGHT = GET_BUTTON(gamepad, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
|
||||||
|
bool L = GET_BUTTON(gamepad, SDL_CONTROLLER_BUTTON_LEFTSHOULDER);
|
||||||
|
bool R = GET_BUTTON(gamepad, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
|
||||||
|
bool CUP = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_RIGHTY) <= -128;
|
||||||
|
bool CDOWN = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_RIGHTY) >= 127;
|
||||||
|
bool CLEFT = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_RIGHTX) <= -128;
|
||||||
|
bool CRIGHT = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_RIGHTX) >= 127;
|
||||||
|
|
||||||
|
controller.a = A;
|
||||||
|
controller.b = B;
|
||||||
|
controller.z = Z;
|
||||||
|
controller.start = START;
|
||||||
|
controller.dp_up = DUP;
|
||||||
|
controller.dp_down = DDOWN;
|
||||||
|
controller.dp_left = DLEFT;
|
||||||
|
controller.dp_right = DRIGHT;
|
||||||
|
controller.joy_reset = L && R && START;
|
||||||
|
controller.l = L;
|
||||||
|
controller.r = R;
|
||||||
|
controller.c_up = CUP;
|
||||||
|
controller.c_down = CDOWN;
|
||||||
|
controller.c_left = CLEFT;
|
||||||
|
controller.c_right = CRIGHT;
|
||||||
|
|
||||||
|
xaxis = (s8) std::clamp((GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_LEFTX) >> 8), -86, 86);
|
||||||
|
yaxis = (s8) std::clamp(-(GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_LEFTY) >> 8), -86, 86);
|
||||||
|
|
||||||
|
controller.joy_x = xaxis;
|
||||||
|
controller.joy_y = yaxis;
|
||||||
|
|
||||||
|
if (controller.joy_reset) {
|
||||||
|
controller.start = false;
|
||||||
|
controller.joy_x = 0;
|
||||||
|
controller.joy_y = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
controller.a = state[SDL_SCANCODE_X];
|
||||||
|
controller.b = state[SDL_SCANCODE_C];
|
||||||
|
controller.z = state[SDL_SCANCODE_Z];
|
||||||
|
controller.start = state[SDL_SCANCODE_RETURN];
|
||||||
|
controller.dp_up = state[SDL_SCANCODE_KP_8];
|
||||||
|
controller.dp_down = state[SDL_SCANCODE_KP_5];
|
||||||
|
controller.dp_left = state[SDL_SCANCODE_KP_4];
|
||||||
|
controller.dp_right = state[SDL_SCANCODE_KP_6];
|
||||||
|
controller.joy_reset = state[SDL_SCANCODE_RETURN] && state[SDL_SCANCODE_A] && state[SDL_SCANCODE_S];
|
||||||
|
controller.l = state[SDL_SCANCODE_A];
|
||||||
|
controller.r = state[SDL_SCANCODE_S];
|
||||||
|
controller.c_up = state[SDL_SCANCODE_I];
|
||||||
|
controller.c_down = state[SDL_SCANCODE_J];
|
||||||
|
controller.c_left = state[SDL_SCANCODE_K];
|
||||||
|
controller.c_right = state[SDL_SCANCODE_L];
|
||||||
|
|
||||||
|
if (state[SDL_SCANCODE_LEFT]) {
|
||||||
|
xaxis = -86;
|
||||||
|
} else if (state[SDL_SCANCODE_RIGHT]) {
|
||||||
|
xaxis = 86;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state[SDL_SCANCODE_DOWN]) {
|
||||||
|
yaxis = -86;
|
||||||
|
} else if (state[SDL_SCANCODE_UP]) {
|
||||||
|
yaxis = 86;
|
||||||
|
}
|
||||||
|
|
||||||
|
controller.joy_x = xaxis;
|
||||||
|
controller.joy_y = yaxis;
|
||||||
|
|
||||||
|
if (controller.joy_reset) {
|
||||||
|
controller.start = false;
|
||||||
|
controller.joy_x = 0;
|
||||||
|
controller.joy_y = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PIF::DoPIFHLE(Mem& mem, Registers& regs, CartInfo cartInfo) {
|
||||||
u32 cicType = cartInfo.cicType;
|
u32 cicType = cartInfo.cicType;
|
||||||
bool pal = cartInfo.isPAL;
|
bool pal = cartInfo.isPAL;
|
||||||
mem.Write32(regs, PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]);
|
mem.Write32(regs, PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]);
|
||||||
@@ -336,7 +429,7 @@ void DoPIFHLE(Mem& mem, Registers& regs, CartInfo cartInfo) {
|
|||||||
regs.SetPC32(0xA4000040);
|
regs.SetPC32(0xA4000040);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecutePIF(Mem& mem, Registers& regs, CartInfo cartInfo) {
|
void PIF::ExecutePIF(Mem& mem, Registers& regs, CartInfo cartInfo) {
|
||||||
u32 cicType = cartInfo.cicType;
|
u32 cicType = cartInfo.cicType;
|
||||||
bool pal = cartInfo.isPAL;
|
bool pal = cartInfo.isPAL;
|
||||||
mem.Write32(regs, PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]);
|
mem.Write32(regs, PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <common.hpp>
|
#include <MemoryRegions.hpp>
|
||||||
|
#include <SDL_gamecontroller.h>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
|
|
||||||
@@ -61,6 +62,14 @@ enum CICType {
|
|||||||
|
|
||||||
struct CartInfo;
|
struct CartInfo;
|
||||||
|
|
||||||
void ProcessPIFCommands(u8*, Controller&, Mem&);
|
struct PIF {
|
||||||
void ExecutePIF(Mem& mem, Registers& regs, CartInfo cartInfo);
|
void ProcessPIFCommands(Mem&);
|
||||||
|
void ExecutePIF(Mem& mem, Registers& regs, CartInfo cartInfo);
|
||||||
|
void DoPIFHLE(Mem& mem, Registers& regs, CartInfo cartInfo);
|
||||||
|
void UpdateController();
|
||||||
|
bool gamepadConnected = false;
|
||||||
|
SDL_GameController* gamepad;
|
||||||
|
Controller controller;
|
||||||
|
u8 pifBootrom[PIF_BOOTROM_SIZE]{}, pifRam[PIF_RAM_SIZE];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -33,20 +33,19 @@ auto SI::Read(MI& mi, u32 addr) const -> u32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DMA(Mem& mem, Registers& regs) {
|
void DMA(Mem& mem, Registers& regs) {
|
||||||
MMIO& mmio = mem.mmio;
|
SI& si = mem.mmio.si;
|
||||||
SI& si = mmio.si;
|
|
||||||
si.status.dmaBusy = false;
|
si.status.dmaBusy = false;
|
||||||
if(si.toDram) {
|
if(si.toDram) {
|
||||||
ProcessPIFCommands(mem.pifRam, si.controller, mem);
|
si.pif.ProcessPIFCommands(mem);
|
||||||
for(int i = 0; i < 64; i++) {
|
for(int i = 0; i < 64; i++) {
|
||||||
mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)] = mem.pifRam[i];
|
mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)] = si.pif.pifRam[i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(int i = 0; i < 64; i++) {
|
for(int i = 0; i < 64; i++) {
|
||||||
mem.pifRam[i] = mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)];
|
si.pif.pifRam[i] = mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)];
|
||||||
}
|
}
|
||||||
Util::debug("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})\n", si.pifAddr, si.dramAddr);
|
Util::debug("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})\n", si.pifAddr, si.dramAddr);
|
||||||
ProcessPIFCommands(mem.pifRam, si.controller, mem);
|
si.pif.ProcessPIFCommands(mem);
|
||||||
}
|
}
|
||||||
InterruptRaise(mem.mmio.mi, regs, Interrupt::SI);
|
InterruptRaise(mem.mmio.mi, regs, Interrupt::SI);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ struct SI {
|
|||||||
|
|
||||||
auto Read(MI&, u32) const -> u32;
|
auto Read(MI&, u32) const -> u32;
|
||||||
void Write(Mem&, Registers&, u32, u32);
|
void Write(Mem&, Registers&, u32, u32);
|
||||||
|
PIF pif;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void DMA(Mem& mem, Registers& regs);
|
static void DMA(Mem& mem, Registers& regs);
|
||||||
|
|||||||
@@ -8,12 +8,11 @@ App::App() : window(core) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void App::Run() {
|
void App::Run() {
|
||||||
const u8* state = SDL_GetKeyboardState(nullptr);
|
|
||||||
SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
|
SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
|
||||||
|
n64::SI& si = core.mem.mmio.si;
|
||||||
|
|
||||||
while (!core.done) {
|
while (!core.done) {
|
||||||
core.Run(window, window.settings.GetVolumeL(), window.settings.GetVolumeL());
|
core.Run(window, window.settings.GetVolumeL(), window.settings.GetVolumeL());
|
||||||
core.UpdateController(state);
|
|
||||||
|
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
@@ -27,12 +26,12 @@ void App::Run() {
|
|||||||
break;
|
break;
|
||||||
case SDL_CONTROLLERDEVICEADDED: {
|
case SDL_CONTROLLERDEVICEADDED: {
|
||||||
const int index = event.cdevice.which;
|
const int index = event.cdevice.which;
|
||||||
core.gamepad = SDL_GameControllerOpen(index);
|
si.pif.gamepad = SDL_GameControllerOpen(index);
|
||||||
core.gamepadConnected = true;
|
si.pif.gamepadConnected = true;
|
||||||
} break;
|
} break;
|
||||||
case SDL_CONTROLLERDEVICEREMOVED:
|
case SDL_CONTROLLERDEVICEREMOVED:
|
||||||
SDL_GameControllerClose(core.gamepad);
|
SDL_GameControllerClose(si.pif.gamepad);
|
||||||
core.gamepadConnected = false;
|
si.pif.gamepadConnected = false;
|
||||||
break;
|
break;
|
||||||
case SDL_KEYDOWN:
|
case SDL_KEYDOWN:
|
||||||
switch(event.key.keysym.sym) {
|
switch(event.key.keysym.sym) {
|
||||||
|
|||||||
@@ -67,8 +67,12 @@ Settings::Settings(n64::Core& core) {
|
|||||||
settingsFile.close();
|
settingsFile.close();
|
||||||
|
|
||||||
switch(core.cpuType) {
|
switch(core.cpuType) {
|
||||||
case n64::CpuType::Interpreter: core.cpuInterp = new n64::Interpreter; break;
|
case n64::CpuType::Interpreter:
|
||||||
case n64::CpuType::Dynarec: core.cpuDynarec = new n64::JIT::Dynarec; break;
|
core.cpuInterp = new n64::Interpreter;
|
||||||
|
break;
|
||||||
|
case n64::CpuType::Dynarec:
|
||||||
|
core.cpuDynarec = new n64::JIT::Dynarec;
|
||||||
|
break;
|
||||||
case n64::CpuType::NONE:
|
case n64::CpuType::NONE:
|
||||||
Util::panic("BRUH\n");
|
Util::panic("BRUH\n");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user