From 1be357e607a9e4a5bee3f7a552c469e365e3efa4 Mon Sep 17 00:00:00 2001 From: SimoZ64 Date: Fri, 27 Jun 2025 12:18:44 +0200 Subject: [PATCH] gamepad works now finally. Ready for merge in dev --- external/parallel-rdp/ParallelRDPWrapper.hpp | 3 +- src/backend/MemoryRegions.hpp | 32 +++--- src/backend/core/mmio/Audio.cpp | 7 -- src/backend/core/mmio/Audio.hpp | 1 - src/frontend/KaizenGui.cpp | 107 ++++++++----------- src/frontend/KaizenGui.hpp | 14 ++- 6 files changed, 73 insertions(+), 91 deletions(-) diff --git a/external/parallel-rdp/ParallelRDPWrapper.hpp b/external/parallel-rdp/ParallelRDPWrapper.hpp index f0fd5bc0..a7c18e73 100644 --- a/external/parallel-rdp/ParallelRDPWrapper.hpp +++ b/external/parallel-rdp/ParallelRDPWrapper.hpp @@ -21,8 +21,7 @@ public: void Init(const std::shared_ptr &, const std::shared_ptr &, const u8 *); - ParallelRDP() = default; - + void UpdateScreen(n64::Core &, bool = true) const; void EnqueueCommand(int, const u32 *) const; void OnFullSync() const; diff --git a/src/backend/MemoryRegions.hpp b/src/backend/MemoryRegions.hpp index d82ff612..6ce3be62 100644 --- a/src/backend/MemoryRegions.hpp +++ b/src/backend/MemoryRegions.hpp @@ -37,8 +37,8 @@ #define CART_REGION_END_2_1 0x05FFFFFF #define CART_REGION_END_2_2 0x0FFFFFFF -#define RDRAM_REGION RDRAM_REGION_START... RDRAM_REGION_END -#define RSP_MEM_REGION DMEM_REGION_START... 0x0403FFFF +#define RDRAM_REGION RDRAM_REGION_START ... RDRAM_REGION_END +#define RSP_MEM_REGION DMEM_REGION_START ... 0x0403FFFF #define MMIO_REGION 0x04040000 ... 0x041FFFFF : case 0x04300000 ... 0x048FFFFF #define SP_REGION 0x04040000 ... 0x040FFFFF #define DP_CMD_REGION 0x04100000 ... 0x041FFFFF @@ -51,9 +51,9 @@ #define PI_REGION 0x04600000 ... 0x046FFFFF #define RI_REGION 0x04700000 ... 0x047FFFFF #define SI_REGION 0x04800000 ... 0x048FFFFF -#define REGION_CART CART_REGION_START_2_1... CART_REGION_END_1_2 -#define PIF_ROM_REGION PIF_ROM_REGION_START... PIF_ROM_REGION_END -#define PIF_RAM_REGION PIF_RAM_REGION_START... PIF_RAM_REGION_END +#define REGION_CART CART_REGION_START_2_1 ... CART_REGION_END_1_2 +#define PIF_ROM_REGION PIF_ROM_REGION_START ... PIF_ROM_REGION_END +#define PIF_RAM_REGION PIF_RAM_REGION_START ... PIF_RAM_REGION_END #define START_VREGION_KUSEG 0x00000000 #define START_VREGION_KSEG0 0x80000000 @@ -67,11 +67,11 @@ #define END_VREGION_KSSEG 0xDFFFFFFF #define END_VREGION_KSEG3 0xFFFFFFFF -#define VREGION_KUSEG START_VREGION_KUSEG... END_VREGION_KUSEG -#define VREGION_KSEG0 START_VREGION_KSEG0... END_VREGION_KSEG0 -#define VREGION_KSEG1 START_VREGION_KSEG1... END_VREGION_KSEG1 -#define VREGION_KSSEG START_VREGION_KSSEG... END_VREGION_KSSEG -#define VREGION_KSEG3 START_VREGION_KSEG3... END_VREGION_KSEG3 +#define VREGION_KUSEG START_VREGION_KUSEG ... END_VREGION_KUSEG +#define VREGION_KSEG0 START_VREGION_KSEG0 ... END_VREGION_KSEG0 +#define VREGION_KSEG1 START_VREGION_KSEG1 ... END_VREGION_KSEG1 +#define VREGION_KSSEG START_VREGION_KSSEG ... END_VREGION_KSSEG +#define VREGION_KSEG3 START_VREGION_KSEG3 ... END_VREGION_KSEG3 #define DIRECT_MAP_MASK 0x1FFFFFFF @@ -99,17 +99,17 @@ #define EREGION_PI_SRAM 0x0FFFFFFF #define EREGION_PI_ROM 0xFFFFFFFF -#define REGION_PI_UNKNOWN SREGION_PI_UNKNOWN... EREGION_PI_UNKNOWN -#define REGION_PI_64DD_REG SREGION_PI_64DD_REG... EREGION_PI_64DD_REG -#define REGION_PI_64DD_ROM SREGION_PI_64DD_ROM... EREGION_PI_64DD_ROM -#define REGION_PI_SRAM SREGION_PI_SRAM... EREGION_PI_SRAM -#define REGION_PI_ROM SREGION_PI_ROM... EREGION_PI_ROM +#define REGION_PI_UNKNOWN SREGION_PI_UNKNOWN ... EREGION_PI_UNKNOWN +#define REGION_PI_64DD_REG SREGION_PI_64DD_REG ... EREGION_PI_64DD_REG +#define REGION_PI_64DD_ROM SREGION_PI_64DD_ROM ... EREGION_PI_64DD_ROM +#define REGION_PI_SRAM SREGION_PI_SRAM ... EREGION_PI_SRAM +#define REGION_PI_ROM SREGION_PI_ROM ... EREGION_PI_ROM #define CART_ISVIEWER_FLUSH 0x13FF0014 #define SREGION_CART_ISVIEWER_BUFFER 0x13FF0020 #define EREGION_CART_ISVIEWER_BUFFER 0x13FFFFFF #define CART_ISVIEWER_SIZE (EREGION_CART_ISVIEWER_BUFFER - SREGION_CART_ISVIEWER_BUFFER) -#define REGION_CART_ISVIEWER_BUFFER SREGION_CART_ISVIEWER_BUFFER... EREGION_CART_ISVIEWER_BUFFER +#define REGION_CART_ISVIEWER_BUFFER SREGION_CART_ISVIEWER_BUFFER ... EREGION_CART_ISVIEWER_BUFFER constexpr u64 operator""_kb(unsigned long long int x) { return 1024ULL * x; } diff --git a/src/backend/core/mmio/Audio.cpp b/src/backend/core/mmio/Audio.cpp index 55829055..c3dbc692 100644 --- a/src/backend/core/mmio/Audio.cpp +++ b/src/backend/core/mmio/Audio.cpp @@ -8,13 +8,6 @@ namespace n64 { #define SYSTEM_SAMPLE_SIZE 4 #define BYTES_PER_HALF_SECOND (((float)AUDIO_SAMPLE_RATE / 2) * SYSTEM_SAMPLE_SIZE) -AudioDevice::~AudioDevice() { - LockMutex(); - SDL_DestroyAudioStream(GetStream()); - UnlockMutex(); - SDL_DestroyMutex(audioStreamMutex); -} - AudioDevice::AudioDevice() { audioStreamMutex = SDL_CreateMutex(); if (!audioStreamMutex) { diff --git a/src/backend/core/mmio/Audio.hpp b/src/backend/core/mmio/Audio.hpp index a2bc8301..7d5cb8e0 100644 --- a/src/backend/core/mmio/Audio.hpp +++ b/src/backend/core/mmio/Audio.hpp @@ -5,7 +5,6 @@ namespace n64 { struct AudioDevice { AudioDevice(); - ~AudioDevice(); void Reset() { running = false; } diff --git a/src/frontend/KaizenGui.cpp b/src/frontend/KaizenGui.cpp index 77338fbf..75048837 100644 --- a/src/frontend/KaizenGui.cpp +++ b/src/frontend/KaizenGui.cpp @@ -5,15 +5,11 @@ #include #include -bool HandleInput(void *userdata, SDL_Event *event); -bool QueryDevices(void *userdata, SDL_Event *event); - KaizenGui::KaizenGui() noexcept : window("Kaizen", 800, 600), core(std::make_shared()), vulkanWidget(core, window.getHandle()), emuThread(core, fpsCounter, vulkanWidget, settingsWindow) { gui::Initialize(core->parallel.wsi, window.getHandle()); + SDL_InitSubSystem(SDL_INIT_GAMEPAD); SDL_AddGamepadMapping(gamecontrollerdb_str); - SDL_AddEventWatch(HandleInput, this); - SDL_AddEventWatch(QueryDevices, this); actionPause.setFunc([&]() { if(ImGui::IsItemClicked()) { @@ -43,8 +39,11 @@ KaizenGui::KaizenGui() noexcept : window("Kaizen", 800, 600), core(std::make_sha }); statusBar.setFunc([&]() { + /* TODO: for when I'll separate the GUI and the Core in two threads again ImGui::Text("GUI FPS: %.2f, Emulation FPS: %s", ImGui::GetIO().Framerate, fmt::format(fpsCounter > 0 ? fmt::runtime("{0:.2f}") : fmt::runtime("{1}"), fpsCounter, "Not playing").c_str()); + */ + ImGui::Text("FPS: %.2f", ImGui::GetIO().Framerate); }); menuBar.addMenu({"File", @@ -91,51 +90,40 @@ KaizenGui::KaizenGui() noexcept : window("Kaizen", 800, 600), core(std::make_sha KaizenGui::~KaizenGui() { gui::Cleanup(); - SDL_RemoveEventWatch(HandleInput, this); - SDL_RemoveEventWatch(QueryDevices, this); SDL_Quit(); } -bool QueryDevices(void *userdata, SDL_Event *event) { - auto _this = (KaizenGui*)userdata; - switch (event->type) { +void KaizenGui::QueryDevices(SDL_Event event) { + switch (event.type) { case SDL_EVENT_GAMEPAD_ADDED: { - const auto index = event->gdevice.which; + const auto index = event.gdevice.which; - auto gamepad = SDL_OpenGamepad(index); + gamepad = SDL_OpenGamepad(index); Util::info("Found controller!"); - const auto serial = SDL_GetGamepadSerial(gamepad); - const auto name = SDL_GetGamepadName(gamepad); - const auto path = SDL_GetGamepadPath(gamepad); - - _this->gamepad = gamepad; } - return true; + break; case SDL_EVENT_GAMEPAD_REMOVED: - SDL_CloseGamepad(_this->gamepad); - return true; - default: - return false; + SDL_CloseGamepad(gamepad); + break; + default: break; } } -bool HandleInput(void *userdata, SDL_Event *event) { - auto _this = (KaizenGui*)userdata; - n64::PIF &pif = _this->core->cpu->GetMem().mmio.si.pif; - switch(event->type) { +void KaizenGui::HandleInput(SDL_Event event) { + n64::PIF &pif = core->cpu->GetMem().mmio.si.pif; + switch(event.type) { case SDL_EVENT_GAMEPAD_AXIS_MOTION: - if(!_this->gamepad) - return false; + if(!gamepad) + break; { - _this->core->pause = true; - pif.UpdateButton(0, n64::Controller::Key::Z, SDL_GetGamepadAxis(_this->gamepad, SDL_GAMEPAD_AXIS_LEFT_TRIGGER) == SDL_JOYSTICK_AXIS_MAX); - pif.UpdateButton(0, n64::Controller::Key::CUp, SDL_GetGamepadAxis(_this->gamepad, SDL_GAMEPAD_AXIS_RIGHTY) <= -127); - pif.UpdateButton(0, n64::Controller::Key::CDown, SDL_GetGamepadAxis(_this->gamepad, SDL_GAMEPAD_AXIS_RIGHTY) >= 127); - pif.UpdateButton(0, n64::Controller::Key::CLeft, SDL_GetGamepadAxis(_this->gamepad, SDL_GAMEPAD_AXIS_RIGHTX) <= -127); - pif.UpdateButton(0, n64::Controller::Key::CRight, SDL_GetGamepadAxis(_this->gamepad, SDL_GAMEPAD_AXIS_RIGHTX) >= 127); + pif.UpdateButton(0, n64::Controller::Key::Z, SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_LEFT_TRIGGER) == SDL_JOYSTICK_AXIS_MAX); + pif.UpdateButton(0, n64::Controller::Key::CUp, SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_RIGHTY) <= -127); + pif.UpdateButton(0, n64::Controller::Key::CDown, SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_RIGHTY) >= 127); + pif.UpdateButton(0, n64::Controller::Key::CLeft, SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_RIGHTX) <= -127); + pif.UpdateButton(0, n64::Controller::Key::CRight, SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_RIGHTX) >= 127); - float xclamped = SDL_GetGamepadAxis(_this->gamepad, SDL_GAMEPAD_AXIS_LEFTX); + float xclamped = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_LEFTX); if (xclamped < 0) { xclamped /= float(std::abs(SDL_JOYSTICK_AXIS_MAX)); } else { @@ -144,7 +132,7 @@ bool HandleInput(void *userdata, SDL_Event *event) { xclamped *= 86; - float yclamped = SDL_GetGamepadAxis(_this->gamepad, SDL_GAMEPAD_AXIS_LEFTY); + float yclamped = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_LEFTY); if (yclamped < 0) { yclamped /= float(std::abs(SDL_JOYSTICK_AXIS_MIN)); } else { @@ -155,32 +143,28 @@ bool HandleInput(void *userdata, SDL_Event *event) { pif.UpdateAxis(0, n64::Controller::Axis::Y, -yclamped); pif.UpdateAxis(0, n64::Controller::Axis::X, xclamped); - _this->core->pause = false; } - return true; + break; case SDL_EVENT_GAMEPAD_BUTTON_DOWN: - if(!_this->gamepad) - return false; - { - _this->core->pause = true; - pif.UpdateButton(0, n64::Controller::Key::A, SDL_GetGamepadButton(_this->gamepad, SDL_GAMEPAD_BUTTON_SOUTH)); - pif.UpdateButton(0, n64::Controller::Key::B, SDL_GetGamepadButton(_this->gamepad, SDL_GAMEPAD_BUTTON_WEST)); - pif.UpdateButton(0, n64::Controller::Key::Start, SDL_GetGamepadButton(_this->gamepad, SDL_GAMEPAD_BUTTON_START)); - pif.UpdateButton(0, n64::Controller::Key::DUp, SDL_GetGamepadButton(_this->gamepad, SDL_GAMEPAD_BUTTON_DPAD_UP)); - pif.UpdateButton(0, n64::Controller::Key::DDown, SDL_GetGamepadButton(_this->gamepad, SDL_GAMEPAD_BUTTON_DPAD_DOWN)); - pif.UpdateButton(0, n64::Controller::Key::DLeft, SDL_GetGamepadButton(_this->gamepad, SDL_GAMEPAD_BUTTON_DPAD_LEFT)); - pif.UpdateButton(0, n64::Controller::Key::DRight, SDL_GetGamepadButton(_this->gamepad, SDL_GAMEPAD_BUTTON_DPAD_RIGHT)); - pif.UpdateButton(0, n64::Controller::Key::LT, SDL_GetGamepadButton(_this->gamepad, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER)); - pif.UpdateButton(0, n64::Controller::Key::RT, SDL_GetGamepadButton(_this->gamepad, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER)); - _this->core->pause = false; - } - return true; + case SDL_EVENT_GAMEPAD_BUTTON_UP: + if(!gamepad) + break; + + pif.UpdateButton(0, n64::Controller::Key::A, SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_SOUTH)); + pif.UpdateButton(0, n64::Controller::Key::B, SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_WEST)); + pif.UpdateButton(0, n64::Controller::Key::Start, SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_START)); + pif.UpdateButton(0, n64::Controller::Key::DUp, SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_DPAD_UP)); + pif.UpdateButton(0, n64::Controller::Key::DDown, SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_DPAD_DOWN)); + pif.UpdateButton(0, n64::Controller::Key::DLeft, SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_DPAD_LEFT)); + pif.UpdateButton(0, n64::Controller::Key::DRight, SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_DPAD_RIGHT)); + pif.UpdateButton(0, n64::Controller::Key::LT, SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER)); + pif.UpdateButton(0, n64::Controller::Key::RT, SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER)); + break; case SDL_EVENT_KEY_DOWN: case SDL_EVENT_KEY_UP: - if(_this->gamepad) - return false; + if(gamepad) + break; { - _this->core->pause = true; auto keys = SDL_GetKeyboardState(nullptr); pif.UpdateButton(0, n64::Controller::Key::Z, keys[SDL_SCANCODE_Z]); pif.UpdateButton(0, n64::Controller::Key::CUp, keys[SDL_SCANCODE_HOME]); @@ -198,10 +182,9 @@ bool HandleInput(void *userdata, SDL_Event *event) { pif.UpdateButton(0, n64::Controller::Key::RT, keys[SDL_SCANCODE_S]); pif.UpdateAxis(0, n64::Controller::Axis::Y, keys[SDL_SCANCODE_UP] ? 86 : keys[SDL_SCANCODE_DOWN] ? -86 : 0); pif.UpdateAxis(0, n64::Controller::Axis::X, keys[SDL_SCANCODE_LEFT] ? -86 : keys[SDL_SCANCODE_RIGHT] ? 86 : 0); - _this->core->pause = false; } - return true; - default: return false; + break; + default: break; } } @@ -217,7 +200,7 @@ void KaizenGui::RenderUI() { ImGui::RenderPlatformWindowsDefault(); } - if(!core->pause) { + if(!core->pause && core->romLoaded) { core->parallel.UpdateScreen(*core.get()); return; } @@ -245,6 +228,8 @@ void KaizenGui::run() { emuThread.Stop(); break; } + QueryDevices(e); + HandleInput(e); } emuThread.run(); diff --git a/src/frontend/KaizenGui.hpp b/src/frontend/KaizenGui.hpp index 9a4587ed..ba58e62e 100644 --- a/src/frontend/KaizenGui.hpp +++ b/src/frontend/KaizenGui.hpp @@ -13,15 +13,19 @@ class KaizenGui final { public: explicit KaizenGui() noexcept; ~KaizenGui(); + double fpsCounter = -1.0; + gui::MenuBar menuBar; gui::MenuItem actionPause{"Pause", nullptr, false}, actionStop{"Stop", nullptr, false}, actionReset{"Reset", nullptr, false}; - SettingsWindow settingsWindow; - std::shared_ptr core; - RenderWidget vulkanWidget; - EmuThread emuThread; gui::PopupWindow about{"About Kaizen"}; gui::StatusBar statusBar{}; + + std::shared_ptr core; + RenderWidget vulkanWidget; + SettingsWindow settingsWindow; + EmuThread emuThread; + SDL_Gamepad* gamepad = nullptr; void run(); @@ -31,4 +35,6 @@ private: bool quit = false; std::function emuExitFunc; void RenderUI(); + void HandleInput(SDL_Event event); + void QueryDevices(SDL_Event event); };