diff --git a/core/emulator.cpp b/core/emulator.cpp index d6d1537a5..28feefee7 100644 --- a/core/emulator.cpp +++ b/core/emulator.cpp @@ -365,8 +365,8 @@ void dc_reset(bool hard) NetworkHandshake::term(); if (hard) { - _vmem_unprotect_vram(0, VRAM_SIZE); - memwatch::elanWatcher.unprotectMem(0, 0xffffffff); + memwatch::unprotect(); + memwatch::reset(); } sh4_sched_reset(hard); pvr::reset(hard); @@ -656,9 +656,14 @@ void Emulator::term() } } -void Emulator::stop() { +void Emulator::stop() +{ if (state != Running) return; + // Avoid race condition with GGPO restarting the sh4 for a new frame + if (config::GGPOEnable) + NetworkHandshake::term(); + // must be updated after GGPO is stopped since it may run some rollback frames state = Loaded; sh4_cpu.Stop(); if (config::ThreadedRendering) @@ -686,6 +691,8 @@ void Emulator::stop() { void Emulator::requestReset() { resetRequested = true; + if (config::GGPOEnable) + NetworkHandshake::term(); sh4_cpu.Stop(); } diff --git a/core/hw/mem/mem_watch.h b/core/hw/mem/mem_watch.h index c102617e3..c47b710dd 100644 --- a/core/hw/mem/mem_watch.h +++ b/core/hw/mem/mem_watch.h @@ -215,8 +215,6 @@ inline static void protect() inline static void unprotect() { - if (!config::GGPOEnable) - return; vramWatcher.unprotect(); ramWatcher.unprotect(); aramWatcher.unprotect(); diff --git a/core/hw/pvr/Renderer_if.cpp b/core/hw/pvr/Renderer_if.cpp index 3ad998fa9..afd9cd035 100644 --- a/core/hw/pvr/Renderer_if.cpp +++ b/core/hw/pvr/Renderer_if.cpp @@ -8,6 +8,7 @@ #include "hw/holly/holly_intc.h" #include "hw/sh4/sh4_if.h" #include "profiler/fc_profiler.h" +#include "network/ggpo.h" #include #include @@ -32,6 +33,7 @@ u32 fb_watch_addr_end; bool fb_dirty; static bool pend_rend; +static bool rendererEnabled = true; TA_context* _pvrrc; @@ -230,7 +232,7 @@ private: if (renderer->Present()) { presented = true; - if (!config::ThreadedRendering) + if (!config::ThreadedRendering && !ggpo::active()) sh4_cpu.Stop(); #ifdef LIBRETRO retro_rend_present(); @@ -311,6 +313,7 @@ static void rend_create_renderer() bool rend_init_renderer() { + rendererEnabled = true; if (renderer == nullptr) rend_create_renderer(); bool success = renderer->Init(); @@ -340,6 +343,7 @@ void rend_reset() FrameCount = 1; fb_w_cur = 1; pvrQueue.reset(); + rendererEnabled = true; } void rend_start_render() @@ -426,12 +430,15 @@ void rend_vblank() if (config::EmulateFramebuffer || (!render_called && fb_dirty && FB_R_CTRL.fb_enable)) { - FramebufferInfo fbInfo; - fbInfo.update(); - pvrQueue.enqueue(PvrMessageQueue::RenderFramebuffer, fbInfo); - pvrQueue.enqueue(PvrMessageQueue::Present); - if (!config::EmulateFramebuffer) - DEBUG_LOG(PVR, "Direct framebuffer write detected"); + if (rend_is_enabled()) + { + FramebufferInfo fbInfo; + fbInfo.update(); + pvrQueue.enqueue(PvrMessageQueue::RenderFramebuffer, fbInfo); + pvrQueue.enqueue(PvrMessageQueue::Present); + if (!config::EmulateFramebuffer) + DEBUG_LOG(PVR, "Direct framebuffer write detected"); + } fb_dirty = false; } render_called = false; @@ -470,7 +477,7 @@ void rend_set_fb_write_addr(u32 fb_w_sof1) void rend_swap_frame(u32 fb_r_sof) { - if (!config::EmulateFramebuffer && fb_r_sof == fb_w_cur) + if (!config::EmulateFramebuffer && fb_r_sof == fb_w_cur && rend_is_enabled()) pvrQueue.enqueue(PvrMessageQueue::Present); } @@ -490,6 +497,14 @@ void rend_start_rollback() vramRollback.Wait(); } +void rend_enable_renderer(bool enabled) { + rendererEnabled = enabled; +} + +bool rend_is_enabled() { + return rendererEnabled; +} + void rend_serialize(Serializer& ser) { ser << fb_w_cur; diff --git a/core/hw/pvr/Renderer_if.h b/core/hw/pvr/Renderer_if.h index 009da803c..e1ee747f3 100644 --- a/core/hw/pvr/Renderer_if.h +++ b/core/hw/pvr/Renderer_if.h @@ -17,6 +17,8 @@ void rend_reset(); void rend_disable_rollback(); void rend_start_rollback(); void rend_allow_rollback(); +void rend_enable_renderer(bool enabled); +bool rend_is_enabled(); void rend_serialize(Serializer& ser); void rend_deserialize(Deserializer& deser); diff --git a/core/hw/pvr/ta_ctx.cpp b/core/hw/pvr/ta_ctx.cpp index bf98848e8..152c6678f 100644 --- a/core/hw/pvr/ta_ctx.cpp +++ b/core/hw/pvr/ta_ctx.cpp @@ -50,7 +50,7 @@ bool QueueRender(TA_context* ctx) { verify(ctx != 0); - bool skipFrame = settings.disableRenderer; + bool skipFrame = !rend_is_enabled(); if (!skipFrame) { RenderCount++; @@ -67,7 +67,7 @@ bool QueueRender(TA_context* ctx) if (skipFrame || rqueue) { tactx_Recycle(ctx); - if (!settings.disableRenderer) + if (rend_is_enabled()) fskip++; return false; } diff --git a/core/network/ggpo.cpp b/core/network/ggpo.cpp index 76b90169a..a3020f861 100644 --- a/core/network/ggpo.cpp +++ b/core/network/ggpo.cpp @@ -255,14 +255,14 @@ static bool advance_frame(int) { INFO_LOG(NETWORK, "advance_frame"); settings.aica.muteAudio = true; - settings.disableRenderer = true; + rend_enable_renderer(false); inRollback = true; emu.run(); ggpo_advance_frame(ggpoSession); settings.aica.muteAudio = false; - settings.disableRenderer = false; + rend_enable_renderer(true); inRollback = false; _endOfFrame = false; @@ -597,6 +597,8 @@ void stopSession() ggpoSession = nullptr; miniupnp.Term(); emu.setNetworkState(false); + memwatch::unprotect(); + memwatch::reset(); } void getInput(MapleInputState inputState[4]) diff --git a/core/nullDC.cpp b/core/nullDC.cpp index 12fa24baf..f2bae9f42 100644 --- a/core/nullDC.cpp +++ b/core/nullDC.cpp @@ -86,6 +86,9 @@ void flycast_term() void dc_savestate(int index) { + if (settings.network.online) + return; + Serializer ser; dc_serialize(ser); diff --git a/core/rend/gui.cpp b/core/rend/gui.cpp index 3f6a229cc..fec896c08 100644 --- a/core/rend/gui.cpp +++ b/core/rend/gui.cpp @@ -2591,20 +2591,11 @@ static void gui_network_start() ImGui::Text("Starting..."); try { if (networkStatus.get()) - { gui_state = GuiState::Closed; - } else - { - emu.unloadGame(); - gui_state = GuiState::Main; - } + gui_stop_game(); } catch (const FlycastException& e) { - if (NetworkHandshake::instance != nullptr) - NetworkHandshake::instance->stop(); - emu.unloadGame(); - gui_error(e.what()); - gui_state = GuiState::Main; + gui_stop_game(e.what()); } } else @@ -2626,8 +2617,7 @@ static void gui_network_start() } catch (const FlycastException& e) { } - emu.unloadGame(); - gui_state = GuiState::Main; + gui_stop_game(); } ImGui::PopStyleVar(); @@ -2685,12 +2675,10 @@ static void gui_display_loadscreen() } } catch (const FlycastException& ex) { ERROR_LOG(BOOT, "%s", ex.what()); - gui_error(ex.what()); #ifdef TEST_AUTOMATION die("Game load failed"); #endif - emu.unloadGame(); - gui_state = GuiState::Main; + gui_stop_game(ex.what()); } ImGui::PopStyleVar(); diff --git a/core/rend/vulkan/vulkan_context.h b/core/rend/vulkan/vulkan_context.h index d3f864918..620632f08 100644 --- a/core/rend/vulkan/vulkan_context.h +++ b/core/rend/vulkan/vulkan_context.h @@ -122,7 +122,7 @@ public: nameInfo.objectType = objectType; nameInfo.object = object; nameInfo.pObjectName = name.c_str(); - vkDebugMarkerSetObjectNameEXT((VkDevice)*device, &nameInfo); + VULKAN_HPP_DEFAULT_DISPATCHER.vkDebugMarkerSetObjectNameEXT((VkDevice)*device, &nameInfo); } #endif constexpr static int VENDOR_AMD = 0x1022; diff --git a/core/types.h b/core/types.h index 99d6af47e..26668ade9 100644 --- a/core/types.h +++ b/core/types.h @@ -301,7 +301,6 @@ struct settings_t u8 vmu[16]; } md5; } network; - bool disableRenderer; }; extern settings_t settings; diff --git a/shell/android-studio/flycast/src/main/jni/src/Android.cpp b/shell/android-studio/flycast/src/main/jni/src/Android.cpp index 170994738..48ad3a814 100644 --- a/shell/android-studio/flycast/src/main/jni/src/Android.cpp +++ b/shell/android-studio/flycast/src/main/jni/src/Android.cpp @@ -341,14 +341,19 @@ extern "C" JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_setupMic(J extern "C" JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_pause(JNIEnv *env,jobject obj) { - if (emu.running()) - { - stopEmu(); - game_started = true; // restart when resumed - if (config::AutoSaveState) - dc_savestate(config::SavestateSlot); - } - gui_save(); + if (config::GGPOEnable) + { + stopEmu(); + gui_stop_game(); + } + else if (emu.running()) + { + stopEmu(); + game_started = true; // restart when resumed + if (config::AutoSaveState) + dc_savestate(config::SavestateSlot); + } + gui_save(); } extern "C" JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_resume(JNIEnv *env,jobject obj) @@ -359,10 +364,8 @@ extern "C" JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_resume(JNI extern "C" JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_stop(JNIEnv *env,jobject obj) { - stopEmu(); - emu.unloadGame(); - gui_state = GuiState::Main; - game_started = false; + stopEmu(); + gui_stop_game(); } static void *render_thread_func(void *)