diff --git a/src/frontend/KaizenGui.cpp b/src/frontend/KaizenGui.cpp index fc0dd20..9dd4e7e 100644 --- a/src/frontend/KaizenGui.cpp +++ b/src/frontend/KaizenGui.cpp @@ -8,7 +8,9 @@ using namespace std::chrono_literals; -KaizenGui::KaizenGui() noexcept : window("Kaizen " KAIZEN_VERSION_STR, 1280, 720), settingsWindow(window), emuThread(fpsCounter, settingsWindow), vulkanWidget(window.getHandle(), emuThread.rdramCopy.data()) { +KaizenGui::KaizenGui() noexcept : + window("Kaizen " KAIZEN_VERSION_STR, 1280, 720), settingsWindow(window), emuThread(fpsCounter, settingsWindow), + vulkanWidget(window.getHandle(), emuThread.rdramCopy.data()) { gui::Initialize(n64::Core::GetInstance().parallel.wsi, window.getHandle()); SDL_InitSubSystem(SDL_INIT_GAMEPAD); @@ -36,203 +38,210 @@ void KaizenGui::QueryDevices(const SDL_Event &event) { if (gamepad) SDL_CloseGamepad(gamepad); break; - default: break; + default: + break; } } void KaizenGui::HandleInput(const SDL_Event &event) { - const n64::Core& core = n64::Core::GetInstance(); + const n64::Core &core = n64::Core::GetInstance(); n64::PIF &pif = n64::Core::GetMem().mmio.si.pif; - switch(event.type) { - case SDL_EVENT_GAMEPAD_AXIS_MOTION: - if(!gamepad) - break; - { - 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); + switch (event.type) { + case SDL_EVENT_GAMEPAD_AXIS_MOTION: + if (!gamepad) + break; + { + 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(gamepad, SDL_GAMEPAD_AXIS_LEFTX); - if (xclamped < 0) { - xclamped /= static_cast(std::abs(SDL_JOYSTICK_AXIS_MAX)); - } else { - xclamped /= SDL_JOYSTICK_AXIS_MAX; - } - - xclamped *= 86; - - float yclamped = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_LEFTY); - if (yclamped < 0) { - yclamped /= static_cast(std::abs(SDL_JOYSTICK_AXIS_MIN)); - } else { - yclamped /= SDL_JOYSTICK_AXIS_MAX; - } - - yclamped *= 86; - - pif.UpdateAxis(0, n64::Controller::Axis::Y, static_cast(-yclamped)); - pif.UpdateAxis(0, n64::Controller::Axis::X, static_cast( xclamped)); + float xclamped = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_LEFTX); + if (xclamped < 0) { + xclamped /= static_cast(std::abs(SDL_JOYSTICK_AXIS_MAX)); + } else { + xclamped /= SDL_JOYSTICK_AXIS_MAX; } - break; - case SDL_EVENT_GAMEPAD_BUTTON_DOWN: - 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: - { - const auto keys = SDL_GetKeyboardState(nullptr); - if((keys[SDL_SCANCODE_LCTRL] || keys[SDL_SCANCODE_RCTRL]) && keys[SDL_SCANCODE_O]) { - fileDialogOpen = true; - } - fastForward = keys[SDL_SCANCODE_SPACE]; - if(!unlockFramerate) - core.parallel.SetFramerateUnlocked(fastForward); + xclamped *= 86; - if(core.romLoaded) { - if(keys[SDL_SCANCODE_P]) { - emuThread.TogglePause(); - } - - if(keys[SDL_SCANCODE_R]) { - emuThread.Reset(); - } - - if(keys[SDL_SCANCODE_Q]) { - emuThread.Stop(); - } - } - - if(gamepad) - break; - - pif.UpdateButton(0, n64::Controller::Key::Z, keys[SDL_SCANCODE_Z]); - pif.UpdateButton(0, n64::Controller::Key::CUp, keys[SDL_SCANCODE_HOME]); - pif.UpdateButton(0, n64::Controller::Key::CDown, keys[SDL_SCANCODE_END]); - pif.UpdateButton(0, n64::Controller::Key::CLeft, keys[SDL_SCANCODE_DELETE]); - pif.UpdateButton(0, n64::Controller::Key::CRight, keys[SDL_SCANCODE_PAGEDOWN]); - pif.UpdateButton(0, n64::Controller::Key::A, keys[SDL_SCANCODE_X]); - pif.UpdateButton(0, n64::Controller::Key::B, keys[SDL_SCANCODE_C]); - pif.UpdateButton(0, n64::Controller::Key::Start, keys[SDL_SCANCODE_RETURN]); - pif.UpdateButton(0, n64::Controller::Key::DUp, keys[SDL_SCANCODE_I]); - pif.UpdateButton(0, n64::Controller::Key::DDown, keys[SDL_SCANCODE_K]); - pif.UpdateButton(0, n64::Controller::Key::DLeft, keys[SDL_SCANCODE_J]); - pif.UpdateButton(0, n64::Controller::Key::DRight, keys[SDL_SCANCODE_L]); - pif.UpdateButton(0, n64::Controller::Key::LT, keys[SDL_SCANCODE_A]); - pif.UpdateButton(0, n64::Controller::Key::RT, keys[SDL_SCANCODE_S]); - - float x = 0, y = 0; - - if (keys[SDL_SCANCODE_UP]) y = 86; - if (keys[SDL_SCANCODE_DOWN]) y = -86; - if (keys[SDL_SCANCODE_LEFT]) x = -86; - if (keys[SDL_SCANCODE_RIGHT]) x = 86; - - pif.UpdateAxis(0, n64::Controller::Axis::X, x); - pif.UpdateAxis(0, n64::Controller::Axis::Y, y); + float yclamped = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_LEFTY); + if (yclamped < 0) { + yclamped /= static_cast(std::abs(SDL_JOYSTICK_AXIS_MIN)); + } else { + yclamped /= SDL_JOYSTICK_AXIS_MAX; } + + yclamped *= 86; + + pif.UpdateAxis(0, n64::Controller::Axis::Y, static_cast(-yclamped)); + pif.UpdateAxis(0, n64::Controller::Axis::X, static_cast(xclamped)); + } + break; + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: + case SDL_EVENT_GAMEPAD_BUTTON_UP: + if (!gamepad) break; - default: 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: + { + const auto keys = SDL_GetKeyboardState(nullptr); + if ((keys[SDL_SCANCODE_LCTRL] || keys[SDL_SCANCODE_RCTRL]) && keys[SDL_SCANCODE_O]) { + fileDialogOpen = true; + } + + fastForward = keys[SDL_SCANCODE_SPACE]; + if (!unlockFramerate) + core.parallel.SetFramerateUnlocked(fastForward); + + if (core.romLoaded) { + if (keys[SDL_SCANCODE_P]) { + emuThread.TogglePause(); + } + + if (keys[SDL_SCANCODE_R]) { + emuThread.Reset(); + } + + if (keys[SDL_SCANCODE_Q]) { + emuThread.Stop(); + } + } + + if (gamepad) + break; + + pif.UpdateButton(0, n64::Controller::Key::Z, keys[SDL_SCANCODE_Z]); + pif.UpdateButton(0, n64::Controller::Key::CUp, keys[SDL_SCANCODE_HOME]); + pif.UpdateButton(0, n64::Controller::Key::CDown, keys[SDL_SCANCODE_END]); + pif.UpdateButton(0, n64::Controller::Key::CLeft, keys[SDL_SCANCODE_DELETE]); + pif.UpdateButton(0, n64::Controller::Key::CRight, keys[SDL_SCANCODE_PAGEDOWN]); + pif.UpdateButton(0, n64::Controller::Key::A, keys[SDL_SCANCODE_X]); + pif.UpdateButton(0, n64::Controller::Key::B, keys[SDL_SCANCODE_C]); + pif.UpdateButton(0, n64::Controller::Key::Start, keys[SDL_SCANCODE_RETURN]); + pif.UpdateButton(0, n64::Controller::Key::DUp, keys[SDL_SCANCODE_I]); + pif.UpdateButton(0, n64::Controller::Key::DDown, keys[SDL_SCANCODE_K]); + pif.UpdateButton(0, n64::Controller::Key::DLeft, keys[SDL_SCANCODE_J]); + pif.UpdateButton(0, n64::Controller::Key::DRight, keys[SDL_SCANCODE_L]); + pif.UpdateButton(0, n64::Controller::Key::LT, keys[SDL_SCANCODE_A]); + pif.UpdateButton(0, n64::Controller::Key::RT, keys[SDL_SCANCODE_S]); + + float x = 0, y = 0; + + if (keys[SDL_SCANCODE_UP]) + y = 86; + if (keys[SDL_SCANCODE_DOWN]) + y = -86; + if (keys[SDL_SCANCODE_LEFT]) + x = -86; + if (keys[SDL_SCANCODE_RIGHT]) + x = 86; + + pif.UpdateAxis(0, n64::Controller::Axis::X, x); + pif.UpdateAxis(0, n64::Controller::Axis::Y, y); + } + break; + default: + break; } } std::pair, std::optional> RenderErrorMessageDetails() { auto lastPC = Util::Error::GetLastPC(); - if(lastPC.has_value()) { + if (lastPC.has_value()) { ImGui::Text("%s", std::format("Occurred @ PC = {:016X}", Util::Error::GetLastPC().value()).c_str()); } auto memoryAccess = Util::Error::GetMemoryAccess(); - if(memoryAccess.has_value()) { + if (memoryAccess.has_value()) { const auto [is_write, size, address, written_val] = memoryAccess.value(); - ImGui::Text("%s", std::format("{} {}-bit value @ {:08X}{}", is_write ? "Writing" : "Reading", - static_cast(size), address, - is_write ? std::format(" (value = 0x{:X})", written_val) : "") - .c_str()); + ImGui::Text("%s", + std::format("{} {}-bit value @ {:08X}{}", is_write ? "Writing" : "Reading", static_cast(size), + address, is_write ? std::format(" (value = 0x{:X})", written_val) : "") + .c_str()); } return {lastPC, memoryAccess}; } void KaizenGui::RenderUI() { - n64::Core& core = n64::Core::GetInstance(); + n64::Core &core = n64::Core::GetInstance(); gui::StartFrame(); - if(ImGui::BeginMainMenuBar()) { - if(ImGui::BeginMenu("File")) { - if(ImGui::MenuItem("Open", "Ctrl-O")) { + if (ImGui::BeginMainMenuBar()) { + if (ImGui::BeginMenu("File")) { + if (ImGui::MenuItem("Open", "Ctrl-O")) { fileDialogOpen = true; } - if(ImGui::MenuItem("Exit")) { + if (ImGui::MenuItem("Exit")) { quit = true; emuThread.Stop(); } ImGui::EndMenu(); } - if(ImGui::BeginMenu("Emulation")) { + if (ImGui::BeginMenu("Emulation")) { ImGui::BeginDisabled(!core.romLoaded); - - if(ImGui::MenuItem(core.pause ? "Resume" : "Pause", "P")) { + + if (ImGui::MenuItem(core.pause ? "Resume" : "Pause", "P")) { emuThread.TogglePause(); } - - if(ImGui::MenuItem("Reset", "R")) { + + if (ImGui::MenuItem("Reset", "R")) { emuThread.Reset(); } - - if(ImGui::MenuItem("Stop", "Q")) { + + if (ImGui::MenuItem("Stop", "Q")) { emuThread.Stop(); core.romLoaded = false; } - - if(ImGui::Checkbox("Unlock framerate", &unlockFramerate)) { + + if (ImGui::Checkbox("Unlock framerate", &unlockFramerate)) { core.parallel.SetFramerateUnlocked(unlockFramerate); } - if(ImGui::MenuItem("Open Debugger")) { + if (ImGui::MenuItem("Open Debugger")) { debugger.Open(); } ImGui::EndDisabled(); - if(ImGui::MenuItem("Options")) { + if (ImGui::MenuItem("Options")) { settingsWindow.isOpen = true; } ImGui::EndMenu(); } - if(ImGui::BeginMenu("Help")) { - if(ImGui::MenuItem("About")) { + if (ImGui::BeginMenu("Help")) { + if (ImGui::MenuItem("About")) { aboutOpen = true; } - + ImGui::EndMenu(); } ImGui::EndMainMenuBar(); } - if(!Util::Error::IsHandled()) { + if (!Util::Error::IsHandled()) { ImGui::OpenPopup(Util::Error::GetSeverity().as_c_str()); } - - if(settingsWindow.isOpen) { + + if (settingsWindow.isOpen) { ImGui::OpenPopup("Settings", ImGuiPopupFlags_None); } - if(aboutOpen) { + if (aboutOpen) { ImGui::OpenPopup("About Kaizen"); } @@ -250,11 +259,11 @@ void KaizenGui::RenderUI() { ImGui::Separator(); ImGui::Text("Kaizen %s%s", KAIZEN_USE_HASH ? "dev build " : "", KAIZEN_VERSION_STR); ImGui::Separator(); - if(ImGui::Button("OK")) { + if (ImGui::Button("OK")) { aboutOpen = false; ImGui::CloseCurrentPopup(); } - + ImGui::EndPopup(); } @@ -262,43 +271,48 @@ void KaizenGui::RenderUI() { if (ImGui::BeginPopupModal(Util::Error::GetSeverity().as_c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { emuThread.TogglePause(); - switch(Util::Error::GetSeverity().as_enum) { - case Util::Error::Severity::WARN: { + switch (Util::Error::GetSeverity().as_enum) { + case Util::Error::Severity::WARN: + { ImGui::PushStyleColor(ImGuiCol_TitleBg, 0x8054eae5); ImGui::PushStyleColor(ImGuiCol_Text, 0xff7be4e1); ImGui::Text("Warning of type: %s", Util::Error::GetType().as_c_str()); - ImGui::PopStyleColor(); + ImGui::PopStyleColor(); ImGui::PopStyleColor(); ImGui::Text(R"(Warning message: "%s")", Util::Error::GetError().c_str()); RenderErrorMessageDetails(); - if(n64::Core::GetInstance().romLoaded && !n64::Core::GetInstance().pause) { - const bool ignore = ImGui::Button("Try continuing"); ImGui::SameLine(); - const bool stop = ImGui::Button("Stop emulation"); ImGui::SameLine(); + if (n64::Core::GetInstance().romLoaded && !n64::Core::GetInstance().pause) { + const bool ignore = ImGui::Button("Try continuing"); + ImGui::SameLine(); + const bool stop = ImGui::Button("Stop emulation"); + ImGui::SameLine(); const bool chooseAnother = ImGui::Button("Choose another ROM"); - if(ignore || stop || chooseAnother) { + if (ignore || stop || chooseAnother) { Util::Error::SetHandled(); ImGui::CloseCurrentPopup(); } - if(ignore) { + if (ignore) { emuThread.TogglePause(); } - if(stop || chooseAnother) { + if (stop || chooseAnother) { emuThread.Stop(); } - - if(chooseAnother) { + + if (chooseAnother) { fileDialogOpen = true; } break; } - if(ImGui::Button("OK")) + if (ImGui::Button("OK")) ImGui::CloseCurrentPopup(); - } break; - case Util::Error::Severity::UNRECOVERABLE: { + } + break; + case Util::Error::Severity::UNRECOVERABLE: + { emuThread.Stop(); ImGui::PushStyleColor(ImGuiCol_TitleBg, 0x800000ff); ImGui::PushStyleColor(ImGuiCol_Text, 0xff3b3bbf); @@ -308,10 +322,12 @@ void KaizenGui::RenderUI() { ImGui::PopStyleColor(); ImGui::Text(R"(Error message: "%s")", Util::Error::GetError().c_str()); RenderErrorMessageDetails(); - if(ImGui::Button("OK")) + if (ImGui::Button("OK")) ImGui::CloseCurrentPopup(); - } break; - case Util::Error::Severity::NON_FATAL: { + } + break; + case Util::Error::Severity::NON_FATAL: + { ImGui::PushStyleColor(ImGuiCol_TitleBg, 0x800000ff); ImGui::PushStyleColor(ImGuiCol_Text, 0xff3b3bbf); ImGui::Text("An error has occurred!"); @@ -321,48 +337,54 @@ void KaizenGui::RenderUI() { ImGui::Text(R"(Error message: "%s")", Util::Error::GetError().c_str()); auto [lastPC, memoryAccess] = RenderErrorMessageDetails(); - const bool ignore = ImGui::Button("Try continuing"); ImGui::SameLine(); - const bool stop = ImGui::Button("Stop emulation"); ImGui::SameLine(); + const bool ignore = ImGui::Button("Try continuing"); + ImGui::SameLine(); + const bool stop = ImGui::Button("Stop emulation"); + ImGui::SameLine(); const bool chooseAnother = ImGui::Button("Choose another ROM"); - const bool openInDebugger = lastPC.has_value() ? ImGui::Button("Add breakpoint at this PC and open the debugger") : false; - if(ignore || stop || chooseAnother || openInDebugger) { + const bool openInDebugger = + lastPC.has_value() ? ImGui::Button("Add breakpoint at this PC and open the debugger") : false; + if (ignore || stop || chooseAnother || openInDebugger) { Util::Error::SetHandled(); ImGui::CloseCurrentPopup(); } - if(ignore) { + if (ignore) { emuThread.TogglePause(); } - if(stop || chooseAnother) { + if (stop || chooseAnother) { emuThread.Stop(); } - - if(chooseAnother) { + + if (chooseAnother) { fileDialogOpen = true; } - if(openInDebugger) { - if(!n64::Core::GetInstance().breakpoints.contains(lastPC.value())) + if (openInDebugger) { + if (!n64::Core::GetInstance().breakpoints.contains(lastPC.value())) n64::Core::GetInstance().ToggleBreakpoint(lastPC.value()); - + debugger.Open(); emuThread.Reset(); } - } break; - default: break; + } + break; + default: + break; } - + ImGui::EndPopup(); } - - if(ImGui::BeginMainStatusBar()) { + + if (ImGui::BeginMainStatusBar()) { ImGui::Text("FPS: %.2f", ImGui::GetIO().Framerate); ImGui::EndMainStatusBar(); } if (shouldDisplaySpinner) { - ImGui::SetNextWindowPos({static_cast(width) * 0.5f, static_cast(height) * 0.5f}, 0, ImVec2(0.5f, 0.5f)); + ImGui::SetNextWindowPos({static_cast(width) * 0.5f, static_cast(height) * 0.5f}, 0, + ImVec2(0.5f, 0.5f)); ImGui::PushStyleColor(ImGuiCol_WindowBg, IM_COL32_BLACK_TRANS); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); @@ -387,47 +409,51 @@ void KaizenGui::RenderUI() { ImGui::RenderPlatformWindowsDefault(); } - if(fileDialogOpen) { + if (fileDialogOpen) { fileDialogOpen = false; - constexpr SDL_DialogFileFilter filters[] = {{"All files", "*"}, {"Nintendo 64 executable", "n64;z64;v64"}, {"Nintendo 64 executable archive", "rar;tar;zip;7z"}}; - SDL_ShowOpenFileDialog([](void *userdata, const char * const *filelist, int) { - auto kaizen = static_cast(userdata); - - if (!filelist) { - panic("An error occured: {}", SDL_GetError()); - } + constexpr SDL_DialogFileFilter filters[] = {{"All files", "*"}, + {"Nintendo 64 executable", "n64;z64;v64"}, + {"Nintendo 64 executable archive", "rar;tar;zip;7z"}}; + SDL_ShowOpenFileDialog( + [](void *userdata, const char *const *filelist, int) { + auto kaizen = static_cast(userdata); - if (!*filelist) { - warn("The user did not select any file."); - warn("Most likely, the dialog was canceled."); - return; - } + if (!filelist) { + panic("An error occured: {}", SDL_GetError()); + } - kaizen->fileToLoad = *filelist; - kaizen->shouldDisplaySpinner = true; + if (!*filelist) { + warn("The user did not select any file."); + warn("Most likely, the dialog was canceled."); + return; + } - std::thread fileWorker(&KaizenGui::FileWorker, kaizen); - fileWorker.detach(); - }, this, window.getHandle(), filters, 3, nullptr, false); + kaizen->fileToLoad = *filelist; + kaizen->shouldDisplaySpinner = true; + + std::thread fileWorker(&KaizenGui::FileWorker, kaizen); + fileWorker.detach(); + }, + this, window.getHandle(), filters, 3, nullptr, false); } - if(minimized) + if (minimized) return; - if(core.romLoaded) { + if (core.romLoaded) { std::unique_lock lk(emuThread.presentMutex); - if(emuThread.readyForPresentation.wait_for(lk, 16.6667ms) == std::cv_status::no_timeout) + if (emuThread.readyForPresentation.wait_for(lk, 16.6667ms) == std::cv_status::no_timeout) core.parallel.UpdateScreen(); else core.parallel.UpdateScreen(); return; } - + core.parallel.UpdateScreen(); } void KaizenGui::LoadROM(const std::string &path) noexcept { - n64::Core& core = n64::Core::GetInstance(); + n64::Core &core = n64::Core::GetInstance(); core.LoadROM(path); emuThread.create(); const auto gameNameDB = n64::Core::GetMem().rom.gameNameDB; @@ -435,22 +461,23 @@ void KaizenGui::LoadROM(const std::string &path) noexcept { } void KaizenGui::run() { - while(!quit) { + while (!quit) { SDL_Event e; while (SDL_PollEvent(&e)) { ImGui_ImplSDL3_ProcessEvent(&e); - switch(e.type) { - case SDL_EVENT_QUIT: - quit = true; - emuThread.Stop(); - break; - case SDL_EVENT_WINDOW_MINIMIZED: - minimized = true; - break; - case SDL_EVENT_WINDOW_RESTORED: - minimized = false; - break; - default: + switch (e.type) { + case SDL_EVENT_QUIT: + quit = true; + emuThread.Stop(); + break; + case SDL_EVENT_WINDOW_MINIMIZED: + minimized = true; + break; + case SDL_EVENT_WINDOW_RESTORED: + minimized = false; + break; + default: + break; } QueryDevices(e); HandleInput(e); @@ -461,6 +488,5 @@ void KaizenGui::run() { } } -void KaizenGui::LoadTAS(const std::string &path) noexcept { - n64::Core::GetInstance().LoadTAS(fs::path(path)); -} \ No newline at end of file +void KaizenGui::LoadTAS(const std::string &path) noexcept { n64::Core::GetInstance().LoadTAS(fs::path(path)); } + diff --git a/src/utils/Options.hpp b/src/utils/Options.hpp index 8450a2b..834b8ae 100644 --- a/src/utils/Options.hpp +++ b/src/utils/Options.hpp @@ -1,6 +1,5 @@ #pragma once #include -#include #include #include #include @@ -8,39 +7,41 @@ namespace fs = std::filesystem; struct Options { - Options() : file{"resources/options.ini"} { - auto fileExists = fs::exists("resources/options.ini"); - if(fileExists) { - file.read(structure); - return; - } - - structure["general"]["savePath"] = "saves"; - fs::create_directory("saves"); - structure["audio"]["volumeL"] = "0.5"; - structure["audio"]["volumeR"] = "0.5"; - structure["audio"]["lock"] = "true"; - structure["cpu"]["type"] = "interpreter"; - - if(!file.generate(structure)) - panic("Couldn't generate settings' INI!"); + Options() : file{"resources/options.ini"} { + auto fileExists = fs::exists("resources/options.ini"); + if (fileExists) { + file.read(structure); + return; } - static Options &GetInstance() { - static Options instance; - return instance; - } + structure["general"]["savePath"] = "saves"; + fs::create_directory("saves"); + structure["audio"]["volumeL"] = "0.5"; + structure["audio"]["volumeR"] = "0.5"; + structure["audio"]["lock"] = "true"; + structure["cpu"]["type"] = "interpreter"; - template - void SetValue(const std::string &key, const std::string &field, const T &value); - template - T GetValue(const std::string &key, const std::string &field); + if (!file.generate(structure)) + panic("Couldn't generate settings' INI!"); + } + + static Options &GetInstance() { + static Options instance; + return instance; + } + + template + void SetValue(const std::string &key, const std::string &field, const T &value); + template + T GetValue(const std::string &key, const std::string &field); + + void Apply() { + if (!file.write(structure)) + panic("Could not modify options on disk!"); + } - void Apply() { - if(!file.write(structure)) - panic("Could not modify options on disk!"); - } private: - mINI::INIFile file; - mINI::INIStructure structure; -}; \ No newline at end of file + mINI::INIFile file; + mINI::INIStructure structure; +}; +