diff --git a/src/frontend/App.cpp b/src/frontend/App.cpp index ff61bad1..29fa7463 100644 --- a/src/frontend/App.cpp +++ b/src/frontend/App.cpp @@ -4,16 +4,15 @@ void App::Run() { // Main loop - bool done = false; const u8* state = SDL_GetKeyboardState(nullptr); - while (!done) { + while (!core.done) { SDL_Event event; while (SDL_PollEvent(&event)) { ImGui_ImplSDL2_ProcessEvent(&event); switch(event.type) { - case SDL_QUIT: done = true; break; + case SDL_QUIT: core.done = true; break; case SDL_WINDOWEVENT: - done = window.gotClosed(event); + core.done = window.gotClosed(event); break; case SDL_CONTROLLERDEVICEADDED: { const int index = event.cdevice.which; diff --git a/src/frontend/imgui/Window.cpp b/src/frontend/imgui/Window.cpp index dcfceaa5..3dc247d0 100644 --- a/src/frontend/imgui/Window.cpp +++ b/src/frontend/imgui/Window.cpp @@ -28,6 +28,8 @@ void Window::InitSDL() { SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI ); + windowID = SDL_GetWindowID(window); + if(volkInitialize() != VK_SUCCESS) { util::panic("Failed to load Volk!"); } @@ -187,7 +189,7 @@ ImDrawData* Window::Present(n64::Core& core) { ImGui_ImplVulkan_NewFrame(); ImGui_ImplSDL2_NewFrame(window); ImGui::NewFrame(); -// + Render(core); ImGui::Render(); @@ -195,31 +197,35 @@ ImDrawData* Window::Present(n64::Core& core) { } void Window::Render(n64::Core& core) { - ImGui::BeginMainMenuBar(); - if(ImGui::BeginMenu("File")) { - if(ImGui::BeginMenu("Open")) { - if(ImGui::MenuItem("Nintendo 64")) { - nfdchar_t* outpath; - const nfdu8filteritem_t filter {"Nintendo 64 roms", "n64,z64,v64,N64,Z64,V64"}; + if(windowID == SDL_GetWindowID(SDL_GetMouseFocus())) { + ImGui::BeginMainMenuBar(); + if (ImGui::BeginMenu("File")) { + if (ImGui::MenuItem("Open", "O")) { + nfdchar_t *outpath; + const nfdu8filteritem_t filter{"Nintendo 64 roms", "n64,z64,v64,N64,Z64,V64"}; nfdresult_t result = NFD_OpenDialog(&outpath, &filter, 1, nullptr); - if(result == NFD_OKAY) { + if (result == NFD_OKAY) { core.LoadROM(outpath); NFD_FreePath(outpath); } } - if(ImGui::MenuItem("Game Boy")) { - if(ImGui::BeginPopup("##unimplemented_Core")) { - ImGui::TextColored({1.0, 0.0, 0.0, 0.7}, "Unimplemented core 'Game Boy'!"); - ImGui::EndPopup(); - } + if (ImGui::MenuItem("Exit")) { + core.done = true; } ImGui::EndMenu(); } - if(ImGui::BeginMenu("Exit")) { - + if (ImGui::BeginMenu("Emulation")) { + if (ImGui::MenuItem("Reset")) { + core.Reset(); + } + if (ImGui::MenuItem("Stop")) { + core.Stop(); + } + if (ImGui::MenuItem(core.pause ? "Resume" : "Pause", nullptr, false, core.romLoaded)) { + core.TogglePause(); + } ImGui::EndMenu(); } - ImGui::EndMenu(); + ImGui::EndMainMenuBar(); } - ImGui::EndMainMenuBar(); } diff --git a/src/frontend/imgui/Window.hpp b/src/frontend/imgui/Window.hpp index a8cb7a03..605dfbd5 100644 --- a/src/frontend/imgui/Window.hpp +++ b/src/frontend/imgui/Window.hpp @@ -15,6 +15,7 @@ struct Window { [[nodiscard]] bool gotClosed(SDL_Event event); private: SDL_Window* window; + u32 windowID; void InitSDL(); void InitImgui(); void Render(n64::Core& core); diff --git a/src/n64/Core.cpp b/src/n64/Core.cpp index 465c4580..030f13d5 100644 --- a/src/n64/Core.cpp +++ b/src/n64/Core.cpp @@ -6,18 +6,31 @@ namespace n64 { Core::Core() { - Reset(); + Stop(); +} + +void Core::Stop() { + cpu.Reset(); + mem.Reset(); + pause = true; + romLoaded = false; + rom.clear(); } void Core::Reset() { cpu.Reset(); mem.Reset(); + pause = true; romLoaded = false; + if(!rom.empty()) { + LoadROM(rom); + } } -void Core::LoadROM(const std::string& rom) { - Reset(); +void Core::LoadROM(const std::string& rom_) { + rom = rom_; mem.LoadROM(rom); + pause = false; romLoaded = true; } @@ -25,8 +38,7 @@ void Core::Run(Window& window) { MMIO& mmio = mem.mmio; int cycles = 0; for(int field = 0; field < mmio.vi.numFields; field++) { - if(romLoaded) { - //timerInstructions.Start(); + if(!pause && romLoaded) { for (int i = 0; i < mmio.vi.numHalflines; i++) { if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) { InterruptRaise(mmio.mi, cpu.regs, Interrupt::VI); @@ -48,7 +60,9 @@ void Core::Run(Window& window) { } UpdateScreenParallelRdp(*this, window, GetVI()); - } else { + } else if(pause && romLoaded) { + UpdateScreenParallelRdp(*this, window, GetVI()); + } else if(pause && !romLoaded) { UpdateScreenParallelRdpNoGame(*this, window); } } diff --git a/src/n64/Core.hpp b/src/n64/Core.hpp index 96f27601..47d4ed79 100644 --- a/src/n64/Core.hpp +++ b/src/n64/Core.hpp @@ -9,14 +9,19 @@ namespace n64 { struct Core { ~Core() = default; Core(); + void Stop(); void Reset(); void LoadROM(const std::string&); void Run(Window&); void UpdateController(const u8*); + void TogglePause() { pause = !pause; } VI& GetVI() { return mem.mmio.vi; } + bool pause = true; bool romLoaded = false; SDL_GameController* gamepad; bool gamepadConnected = false; + bool done = false; + std::string rom; private: friend struct ::Window; Mem mem;