diff --git a/.gitignore b/.gitignore index 48a84ca3..56e2663b 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ disasm.txt CMakeSettings.json compile_commands.json *.diagsession +tests/ \ No newline at end of file diff --git a/external/parallel-rdp/ParallelRDPWrapper.cpp b/external/parallel-rdp/ParallelRDPWrapper.cpp index d701efaa..20c78c0b 100644 --- a/external/parallel-rdp/ParallelRDPWrapper.cpp +++ b/external/parallel-rdp/ParallelRDPWrapper.cpp @@ -1,8 +1,7 @@ #include -#include +#include #include #include -#include #include #include #include @@ -159,10 +158,7 @@ void ParallelRDP::DrawFullscreenTexturedQuad(Util::IntrusivePtr image, cmd->draw(3, 1); } -std::mutex coreM; - void ParallelRDP::UpdateScreen(Util::IntrusivePtr image) const { - std::lock_guard coreLock(coreM); wsi->begin_frame(); if (!image) { @@ -188,16 +184,15 @@ void ParallelRDP::UpdateScreen(Util::IntrusivePtr image) const { cmd->begin_render_pass(wsi->get_device().get_swapchain_render_pass(SwapchainRenderPass::ColorOnly)); DrawFullscreenTexturedQuad(image, cmd); - auto drawData = ImGui::GetDrawData(); - if(drawData) - ImGui_ImplVulkan_RenderDrawData(drawData, cmd->get_command_buffer()); + ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd->get_command_buffer()); cmd->end_render_pass(); wsi->get_device().submit(cmd); wsi->end_frame(); } -void ParallelRDP::UpdateScreen(const n64::VI &vi, bool playing) const { +void ParallelRDP::UpdateScreen(n64::Core &core, bool playing) const { if(playing) { + n64::VI& vi = core.GetVI(); command_processor->set_vi_register(VIRegister::Control, vi.status.raw); command_processor->set_vi_register(VIRegister::Origin, vi.origin); command_processor->set_vi_register(VIRegister::Width, vi.width); diff --git a/external/parallel-rdp/ParallelRDPWrapper.hpp b/external/parallel-rdp/ParallelRDPWrapper.hpp index 9ea8f064..f0fd5bc0 100644 --- a/external/parallel-rdp/ParallelRDPWrapper.hpp +++ b/external/parallel-rdp/ParallelRDPWrapper.hpp @@ -4,7 +4,7 @@ #include namespace n64 { -struct VI; +struct Core; } class ParallelRDP { @@ -23,7 +23,7 @@ public: const std::shared_ptr &, const u8 *); ParallelRDP() = default; - void UpdateScreen(const n64::VI &, bool = true) const; + void UpdateScreen(n64::Core &, bool = true) const; void EnqueueCommand(int, const u32 *) const; void OnFullSync() const; bool IsFramerateUnlocked() const; diff --git a/src/backend/Core.cpp b/src/backend/Core.cpp index 6151fd44..2ba8455a 100644 --- a/src/backend/Core.cpp +++ b/src/backend/Core.cpp @@ -6,7 +6,6 @@ namespace n64 { Core::Core() : cpu(std::make_unique(parallel)) {} void Core::Stop() { - render = false; pause = true; romLoaded = false; cpu->Reset(); @@ -38,7 +37,6 @@ void Core::LoadROM(const std::string &rom_) { cpu->GetMem().LoadSRAM(cpu->GetMem().saveType, rom); cpu->GetMem().mmio.si.pif.Execute(); pause = false; - render = true; } void Core::Run(float volumeL, float volumeR) { diff --git a/src/backend/Core.hpp b/src/backend/Core.hpp index 545707a1..7c50c1c7 100644 --- a/src/backend/Core.hpp +++ b/src/backend/Core.hpp @@ -19,7 +19,6 @@ struct Core { u32 breakpoint = 0; bool pause = true; - bool render = false; u32 cycles = 0; bool romLoaded = false; std::string rom; diff --git a/src/frontend/EmuThread.cpp b/src/frontend/EmuThread.cpp index 1175a4c3..bdff2139 100644 --- a/src/frontend/EmuThread.cpp +++ b/src/frontend/EmuThread.cpp @@ -6,46 +6,39 @@ EmuThread::EmuThread(const std::shared_ptr &core, double &fps, Render SettingsWindow &settings) noexcept : renderWidget(renderWidget), core(core), settings(settings), fps(fps) {} -void EmuThread::start() noexcept { - thread = std::thread([&]() { - isRunning = true; +void EmuThread::run() noexcept { + isRunning = true; - auto lastSample = std::chrono::high_resolution_clock::now(); - auto avgFps = 16.667; - auto sampledFps = 0; - static bool oneSecondPassed = false; - - fps = 1000.0 / avgFps; - - while (!interruptionRequested) { - const auto startFrameTime = std::chrono::high_resolution_clock::now(); - if (!core->pause) { - core->Run(settings.getVolumeL(), settings.getVolumeR()); - } - - const auto endFrameTime = std::chrono::high_resolution_clock::now(); - using namespace std::chrono_literals; - const auto frameTimeMs = std::chrono::duration(endFrameTime - startFrameTime) / 1ms; - avgFps += frameTimeMs; - - sampledFps++; - - if (const auto elapsedSinceLastSample = std::chrono::duration(endFrameTime - lastSample) / 1s; - elapsedSinceLastSample >= 1.0) { - if (!oneSecondPassed) { - oneSecondPassed = true; - continue; - } - lastSample = endFrameTime; - avgFps /= sampledFps; - sampledFps = 0; - fps = 1000.0 / avgFps; - } + auto lastSample = std::chrono::high_resolution_clock::now(); + auto avgFps = 16.667; + auto sampledFps = 0; + static bool oneSecondPassed = false; + + fps = 1000.0 / avgFps; + + const auto startFrameTime = std::chrono::high_resolution_clock::now(); + if (!core->pause) { + core->Run(settings.getVolumeL(), settings.getVolumeR()); + } + + const auto endFrameTime = std::chrono::high_resolution_clock::now(); + using namespace std::chrono_literals; + const auto frameTimeMs = std::chrono::duration(endFrameTime - startFrameTime) / 1ms; + avgFps += frameTimeMs; + + sampledFps++; + + if (const auto elapsedSinceLastSample = std::chrono::duration(endFrameTime - lastSample) / 1s; + elapsedSinceLastSample >= 1.0) { + if (!oneSecondPassed) { + oneSecondPassed = true; + return; } - SetRender(false); - Stop(); - isRunning = false; - }); + lastSample = endFrameTime; + avgFps /= sampledFps; + sampledFps = 0; + fps = 1000.0 / avgFps; + } } void EmuThread::TogglePause() const noexcept { @@ -55,8 +48,6 @@ void EmuThread::TogglePause() const noexcept { core->cpu->GetMem().mmio.si.pif.movie.GetFilename()); } -void EmuThread::SetRender(const bool v) const noexcept { core->render = v; } - void EmuThread::Reset() const noexcept { core->pause = true; core->Stop(); diff --git a/src/frontend/EmuThread.hpp b/src/frontend/EmuThread.hpp index 84bdcd9c..8b0eebfe 100644 --- a/src/frontend/EmuThread.hpp +++ b/src/frontend/EmuThread.hpp @@ -14,9 +14,8 @@ class EmuThread final { public: explicit EmuThread(const std::shared_ptr &, double &, RenderWidget &, SettingsWindow &) noexcept; - void start() noexcept; + void run() noexcept; void TogglePause() const noexcept; - void SetRender(bool v) const noexcept; void Reset() const noexcept; void Stop() const noexcept; void requestInterruption() { interruptionRequested = true; } @@ -25,5 +24,4 @@ public: std::shared_ptr core; SettingsWindow &settings; double& fps; - std::thread thread; }; diff --git a/src/frontend/ImGuiImpl/GUI.hpp b/src/frontend/ImGuiImpl/GUI.hpp index a72d944b..96571f17 100644 --- a/src/frontend/ImGuiImpl/GUI.hpp +++ b/src/frontend/ImGuiImpl/GUI.hpp @@ -150,6 +150,5 @@ namespace gui { } inline void EndFrame() { - ImGui::Render(); } } \ No newline at end of file diff --git a/src/frontend/KaizenGui.cpp b/src/frontend/KaizenGui.cpp index feafbfad..244bdbee 100644 --- a/src/frontend/KaizenGui.cpp +++ b/src/frontend/KaizenGui.cpp @@ -52,9 +52,12 @@ KaizenGui::KaizenGui() noexcept : window("Kaizen", 800, 600), core(std::make_sha {"Open", [&]() { NFD::Guard guard; NFD::UniquePath path; - nfdfilteritem_t filterItem = {"Nintendo 64 roms", "n64,z64,v64,N64,Z64,V64"}; + static const std::vector filterItems = { + {"Nintendo 64 rom archive", "rar,RAR,tar,TAR,zip,ZIP,7z,7Z"}, + {"Nintendo 64 rom", "n64,z64,v64,N64,Z64,V64"} + }; - auto result = NFD::OpenDialog(path, &filterItem, 1); + auto result = NFD::OpenDialog(path, filterItems.data(), filterItems.size()); if(result == NFD_CANCEL) return; if(result == NFD_ERROR) Util::panic("Error: {}", NFD::GetError()); @@ -88,20 +91,24 @@ void KaizenGui::RenderUI() { menuBar.render(); settingsWindow.render(); about.render(); - gui::EndFrame(); - - if (core->render) { - core->parallel.UpdateScreen(core->cpu->GetMem().mmio.vi); - } else { - core->parallel.UpdateScreen(core->cpu->GetMem().mmio.vi, false); + ImGui::Render(); + if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable){ + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); } + + if(!core->pause) { + core->parallel.UpdateScreen(*core.get()); + return; + } + + core->parallel.UpdateScreen(*core.get(), false); } void KaizenGui::LoadROM(const std::string &path) noexcept { actionPause.setEnabled(true); actionReset.setEnabled(true); actionStop.setEnabled(true); - emuThread.start(); emuThread.core->LoadROM(path); const auto gameNameDB = emuThread.core->cpu->GetMem().rom.gameNameDB; Util::RPC::GetInstance().Update(Util::RPC::Playing, gameNameDB); @@ -114,6 +121,7 @@ int KaizenGui::run() { } RenderUI(); + emuThread.run(); } return 0;