GGPO fixes
Memwatchers weren't properly reset after a ggpo session. Race condition when stopping if GGPO restarts the cpu for a new frame. The emu thread might still run some rollback frames before stopping, so the emu state must be updated only after ggpo is stopped. Fixes MINIDUMP-6P Don't autosavestate when GGPO is on Really disable renderer during GGPO advance frame Don't stop the sh4 after render (single threaded) when GGPO is on android: Don't restart when unpaused if online
This commit is contained in:
parent
5875eda4d0
commit
6b2063b06f
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -215,8 +215,6 @@ inline static void protect()
|
|||
|
||||
inline static void unprotect()
|
||||
{
|
||||
if (!config::GGPOEnable)
|
||||
return;
|
||||
vramWatcher.unprotect();
|
||||
ramWatcher.unprotect();
|
||||
aramWatcher.unprotect();
|
||||
|
|
|
@ -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 <mutex>
|
||||
#include <deque>
|
||||
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -86,6 +86,9 @@ void flycast_term()
|
|||
|
||||
void dc_savestate(int index)
|
||||
{
|
||||
if (settings.network.online)
|
||||
return;
|
||||
|
||||
Serializer ser;
|
||||
dc_serialize(ser);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -301,7 +301,6 @@ struct settings_t
|
|||
u8 vmu[16];
|
||||
} md5;
|
||||
} network;
|
||||
bool disableRenderer;
|
||||
};
|
||||
|
||||
extern settings_t settings;
|
||||
|
|
|
@ -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 *)
|
||||
|
|
Loading…
Reference in New Issue