Controller + avoid disassembling if in Release build + minor things

This commit is contained in:
CocoSimone
2022-08-18 18:21:35 +02:00
parent 066b1ace17
commit 02636d38b6
10 changed files with 155 additions and 20 deletions

View File

@@ -4,6 +4,7 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED true)
add_compile_definitions(VULKAN_DEBUG)
file(COPY ${CMAKE_SOURCE_DIR}/../resources DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
add_subdirectory(n64)
add_subdirectory(frontend)

View File

@@ -5,6 +5,7 @@
void App::Run() {
// Main loop
bool done = false;
const u8* state = SDL_GetKeyboardState(nullptr);
while (!done) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
@@ -14,6 +15,15 @@ void App::Run() {
case SDL_WINDOWEVENT:
done = window.gotClosed(event);
break;
case SDL_CONTROLLERDEVICEADDED: {
const int index = event.cdevice.which;
core.gamepad = SDL_GameControllerOpen(index);
core.gamepadConnected = true;
} break;
case SDL_CONTROLLERDEVICEREMOVED:
SDL_GameControllerClose(core.gamepad);
core.gamepadConnected = false;
break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym) {
case SDLK_o: {
@@ -28,7 +38,7 @@ void App::Run() {
} break;
}
core.PollInputs(event);
core.UpdateController(state);
}
core.Run(window);

View File

@@ -3,6 +3,7 @@
struct App {
App() : window(core) {};
~App() = default;
void Run();
inline void LoadROM(const std::string& path) {
core.LoadROM(path);

View File

@@ -174,6 +174,9 @@ Window::~Window() {
vkDestroyDescriptorPool(device, descriptorPool, nullptr);
vkDestroyDevice(device, nullptr);
vkDestroyInstance(instance, nullptr);
SDL_DestroyWindow(window);
SDL_DestroyWindow(g_Window);
SDL_Quit();
}
ImDrawData* Window::Present(n64::Core& core) {

View File

@@ -1,6 +1,8 @@
#include <Core.hpp>
#include <ParallelRDPWrapper.hpp>
#include <Window.hpp>
#include <algorithm>
#include <util.hpp>
namespace n64 {
Core::Core() {
@@ -21,14 +23,24 @@ void Core::LoadROM(const std::string& rom) {
void Core::Run(Window& window) {
MMIO& mmio = mem.mmio;
for(mmio.vi.current = 0; mmio.vi.current < 262; mmio.vi.current++) {
int cycles = 0;
for(int field = 0; field < mmio.vi.numFields; field++) {
if(romLoaded) {
for (int i = 0; i < 6000; i++) {
cpu.Step(mem);
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);
//timerInstructions.Start();
for (int i = 0; i < mmio.vi.numHalflines; i++) {
if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) {
InterruptRaise(mmio.mi, cpu.regs, Interrupt::VI);
}
for(;cycles <= mmio.vi.cyclesPerHalfline; cycles++) {
cpu.Step(mem);
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);
}
cycles -= mmio.vi.cyclesPerHalfline;
}
if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) {
@@ -42,7 +54,85 @@ void Core::Run(Window& window) {
}
}
void Core::PollInputs(SDL_Event e) {
#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;
if(gamepadConnected) {
controller.b1 = 0;
controller.b2 = 0;
controller.b3 = 0;
controller.b4 = 0;
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) == 32767;
bool CDOWN = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_RIGHTY) == -32768;
bool CLEFT = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_RIGHTX) == -32768;
bool CRIGHT = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_RIGHTX) == 32767;
controller.b1 = (A << 7) | (B << 6) | (Z << 5) | (START << 4) |
(DUP << 3) | (DDOWN << 2) | (DLEFT << 1) | DRIGHT;
controller.b2 = ((START && L && R) << 7) | (0 << 6) | (L << 5) | (R << 4) |
(CUP << 3) | (CDOWN << 2) | (CLEFT << 1) | CRIGHT;
s8 xaxis = (s8)std::clamp((GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_LEFTX) >> 8), -127, 127);
s8 yaxis = (s8)std::clamp(-(GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_LEFTY) >> 8), -127, 127);
controller.b3 = xaxis;
controller.b4 = yaxis;
if((controller.b2 >> 7) & 1) {
controller.b1 &= ~0x10;
controller.b3 = 0;
controller.b4 = 0;
}
} else {
controller.b1 = 0;
controller.b2 = 0;
controller.b3 = 0;
controller.b4 = 0;
controller.b1 =
(state[SDL_SCANCODE_X] << 7) |
(state[SDL_SCANCODE_C] << 6) |
(state[SDL_SCANCODE_Z] << 5) |
(state[SDL_SCANCODE_RETURN] << 4) |
(state[SDL_SCANCODE_KP_8] << 3) |
(state[SDL_SCANCODE_KP_5] << 2) |
(state[SDL_SCANCODE_KP_4] << 1) |
(state[SDL_SCANCODE_KP_6]);
controller.b2 =
((state[SDL_SCANCODE_RETURN] && state[SDL_SCANCODE_A] && state[SDL_SCANCODE_S]) << 7) |
(0 << 6) |
(state[SDL_SCANCODE_A] << 5) |
(state[SDL_SCANCODE_S] << 4) |
(state[SDL_SCANCODE_I] << 3) |
(state[SDL_SCANCODE_J] << 2) |
(state[SDL_SCANCODE_K] << 1) |
(state[SDL_SCANCODE_L]);
s8 xaxis = state[SDL_SCANCODE_LEFT] ? -128 : (state[SDL_SCANCODE_RIGHT] ? 127 : 0);
s8 yaxis = state[SDL_SCANCODE_DOWN] ? -128 : (state[SDL_SCANCODE_UP] ? 127 : 0);
controller.b3 = xaxis;
controller.b4 = yaxis;
if((controller.b2 >> 7) & 1) {
controller.b1 &= ~0x10;
controller.b3 = 0;
controller.b4 = 0;
}
}
}
}

View File

@@ -12,9 +12,11 @@ struct Core {
void Reset();
void LoadROM(const std::string&);
void Run(Window&);
void PollInputs(SDL_Event);
void UpdateController(const u8*);
VI& GetVI() { return mem.mmio.vi; }
bool romLoaded = false;
SDL_GameController* gamepad;
bool gamepadConnected = false;
private:
friend struct ::Window;
Mem mem;

View File

@@ -99,7 +99,9 @@ inline void HandleInterrupt(Registers& regs) {
}
void Cpu::LogInstruction(u32 instruction) {
#ifndef NDEBUG
count = cs_disasm(handle, reinterpret_cast<u8*>(&instruction), 4, regs.pc, 0, &insn);
#endif
if (count > 0) {
for(auto j = 0; j < count; j++) {
@@ -113,13 +115,14 @@ void Cpu::LogInstruction(u32 instruction) {
void Cpu::Step(Mem& mem) {
regs.gpr[0] = 0;
regs.prevDelaySlot = regs.delaySlot;
regs.delaySlot = false;
CheckCompareInterrupt(mem.mmio.mi, regs);
u32 instruction = mem.Read<u32>(regs, regs.pc, regs.pc);
LogInstruction(instruction);
//LogInstruction(instruction);
HandleInterrupt(regs);

View File

@@ -20,7 +20,7 @@ inline void special(RSP& rsp, u32 instr) {
//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 %d %d\n", (mask >> 3) & 7, mask & 7);
default: util::panic("Unhandled RSP special instruction {} {}\n", (mask >> 3) & 7, mask & 7);
}
}
@@ -29,7 +29,7 @@ inline void regimm(RSP& rsp, u32 instr) {
switch(mask) {
//case 0x00: rsp.b(instr, (s32)rsp.gpr[RS(instr)] < 0); break;
//case 0x01: rsp.b(instr, (s32)rsp.gpr[RS(instr)] >= 0); break;
default: util::panic("Unhandled RSP regimm instruction %d %d\n", (mask >> 3) & 3, mask & 7);
default: util::panic("Unhandled RSP regimm instruction {} {}\n", (mask >> 3) & 3, mask & 7);
}
}
@@ -37,7 +37,7 @@ inline void lwc2(RSP& rsp, u32 instr) {
u8 mask = (instr >> 11) & 0x1F;
switch(mask) {
//case 0x04: rsp.lqv(instr); break;
default: util::panic("Unhandled RSP LWC2 %d %d\n", (mask >> 3) & 3, mask & 7);
default: util::panic("Unhandled RSP LWC2 {} {}\n", (mask >> 3) & 3, mask & 7);
}
}
@@ -45,7 +45,7 @@ inline void swc2(RSP& rsp, u32 instr) {
u8 mask = (instr >> 11) & 0x1F;
switch(mask) {
//case 0x04: rsp.sqv(instr); break;
default: util::panic("Unhandled RSP SWC2 %d %d\n", (mask >> 3) & 3, mask & 7);
default: util::panic("Unhandled RSP SWC2 {} {}\n", (mask >> 3) & 3, mask & 7);
}
}
@@ -56,7 +56,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 %d %d\n", (mask_sub >> 3) & 3, mask_sub & 3);
default: util::panic("Unhandled RSP COP2 sub {} {}\n", (mask_sub >> 3) & 3, mask_sub & 3);
}
break;
//case 0x13: rsp.vabs(instr); break;
@@ -64,7 +64,7 @@ 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 %d %d\n", (mask >> 3) & 7, mask & 7);
default: util::panic("Unhandled RSP COP2 {} {}\n", (mask >> 3) & 7, mask & 7);
}
}
@@ -73,7 +73,7 @@ inline void cop0(MI& mi, Registers& regs, RSP& rsp, RDP& rdp, u32 instr) {
switch(mask) {
//case 0x00: rsp.mfc0(rdp, instr); break;
//case 0x04: rsp.mtc0(mi, regs, rdp, instr); break;
default: util::panic("Unhandled RSP COP0 %d %d\n", (mask >> 3) & 3, mask & 7);
default: util::panic("Unhandled RSP COP0 {} {}\n", (mask >> 3) & 3, mask & 7);
}
}
@@ -100,7 +100,7 @@ void RSP::Exec(MI &mi, Registers &regs, RDP &rdp, u32 instr) {
//case 0x2B: sw(instr); break;
//case 0x32: lwc2(*this, instr); break;
//case 0x3A: swc2(*this, instr); break;
default: util::panic("Unhandled RSP instruction %d %d\n", (mask >> 3) & 7, mask & 7);
default: util::panic("Unhandled RSP instruction {} {}\n", (mask >> 3) & 7, mask & 7);
}
}
}

View File

@@ -6,8 +6,13 @@
#include <fstream>
#include <vector>
#include <array>
#include <chrono>
namespace util {
using SteadyClock = std::chrono::steady_clock;
using DurationMillis = std::chrono::duration<double, std::milli>;
using TimePoint = std::chrono::time_point<SteadyClock, DurationMillis>;
enum MessageType : u8 {
Info, Warn, Error
};
@@ -46,6 +51,25 @@ constexpr void logdebug(const std::string& fmt, Args... args) {
#endif
}
#define TIMER(name) \
struct Timer##name { \
util::TimePoint start, end; \
Timer##name() {} \
~Timer##name() {} \
void Start() { \
start = util::SteadyClock::now(); \
} \
\
void End() { \
end = util::SteadyClock::now(); \
} \
\
void PrintDuration() { \
auto diff = end - start; \
util::info(#name + std::string(" took {:.3f}ms to run\n"), diff.count()); \
} \
}
template <typename T, bool HToBE = false>
[[maybe_unused]] auto GetSwapFunc(T num) -> T {
static_assert(sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "GetSwapFunc used with invalid size!");