From 960904c40134f68d1f13515137332932a3884fc1 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Mon, 23 Jul 2018 19:47:24 +0200 Subject: [PATCH 1/6] Exit cleanly in desktop platforms Lighter and cleaner version of the previous PR --- core/hw/pvr/Renderer_if.cpp | 11 ++++++++++- core/linux-dist/evdev.cpp | 4 +++- core/linux-dist/main.cpp | 19 +++++++++++++++++- core/linux-dist/x11.cpp | 37 +++++++++++++++++++++++++++++++----- core/linux-dist/x11.h | 2 ++ core/nullDC.cpp | 5 +++++ core/rec-ARM/ngen_arm.S | 6 ++++++ core/rec-cpp/rec_cpp.cpp | 2 +- core/rec-x64/rec_x64.cpp | 4 ++-- core/rec-x86/rec_x86_asm.cpp | 6 +++--- core/sdl/sdl.cpp | 7 ++----- core/windows/winmain.cpp | 6 ++++-- 12 files changed, 88 insertions(+), 21 deletions(-) diff --git a/core/hw/pvr/Renderer_if.cpp b/core/hw/pvr/Renderer_if.cpp index cc34362cf..174d4493f 100644 --- a/core/hw/pvr/Renderer_if.cpp +++ b/core/hw/pvr/Renderer_if.cpp @@ -76,6 +76,7 @@ u32 VertexCount=0; u32 FrameCount=1; Renderer* renderer; +bool renderer_enabled = true; // Signals the renderer thread to exit #if !defined(TARGET_NO_THREADS) cResetEvent rs(false,true); @@ -217,6 +218,9 @@ bool rend_single_frame() #if !defined(TARGET_NO_THREADS) rs.Wait(); #endif + if (!renderer_enabled) + return false; + _pvrrc = DequeueRender(); } while (!_pvrrc); @@ -269,11 +273,13 @@ void* rend_thread(void* p) //we don't know if this is true, so let's not speculate here //renderer->Resize(640, 480); - for(;;) + while (renderer_enabled) { if (rend_single_frame()) renderer->Present(); } + + return NULL; } #if !defined(TARGET_NO_THREADS) @@ -490,6 +496,9 @@ bool rend_init() void rend_term() { + renderer_enabled = false; + rs.Set(); + if (fCheckFrames) fclose(fCheckFrames); diff --git a/core/linux-dist/evdev.cpp b/core/linux-dist/evdev.cpp index d13ecdbdf..24b9b0739 100644 --- a/core/linux-dist/evdev.cpp +++ b/core/linux-dist/evdev.cpp @@ -16,6 +16,8 @@ libevdev_func1_t libevdev_event_code_from_name; libevdev_func2_t libevdev_event_code_get_name; + void dc_stop(void); + void load_libevdev() { if (libevdev_tried) @@ -353,7 +355,7 @@ } else if (ie.code == controller->mapping->Btn_Start) { SET_FLAG(kcode[port], DC_BTN_START, ie.value); } else if (ie.code == controller->mapping->Btn_Escape) { - die("death by escape key"); + dc_stop(); } else if (ie.code == controller->mapping->Btn_DPad_Left) { SET_FLAG(kcode[port], DC_DPAD_LEFT, ie.value); } else if (ie.code == controller->mapping->Btn_DPad_Right) { diff --git a/core/linux-dist/main.cpp b/core/linux-dist/main.cpp index a6ef7679c..167fee852 100755 --- a/core/linux-dist/main.cpp +++ b/core/linux-dist/main.cpp @@ -222,6 +222,7 @@ void os_DoEvents() { #if defined(SUPPORT_X11) input_x11_handle(); + event_x11_handle(); #endif } @@ -252,6 +253,7 @@ void os_CreateWindow() void common_linux_setup(); int dc_init(int argc,wchar* argv[]); void dc_run(); +void dc_term(); #ifdef TARGET_PANDORA void gl_term(); @@ -475,11 +477,26 @@ int main(int argc, wchar* argv[]) emscripten_set_main_loop(&dc_run, 100, false); #endif - #ifdef TARGET_PANDORA clean_exit(0); #endif + dc_term(); + + #if defined(USE_EVDEV) + for (int port = 0; port < 4 ; port++) + { + if(evdev_controllers[port].fd >= 0) + { + close(evdev_controllers[port].fd); + } + } + #endif + + #if defined(SUPPORT_X11) + x11_window_destroy(); + #endif + return 0; } #endif diff --git a/core/linux-dist/x11.cpp b/core/linux-dist/x11.cpp index 4f3b9b211..5fa99ffcd 100644 --- a/core/linux-dist/x11.cpp +++ b/core/linux-dist/x11.cpp @@ -35,11 +35,14 @@ int x11_width; int x11_height; int ndcid = 0; -void* x11_glc; +void* x11_glc = NULL; bool x11_fullscreen = false; +Atom wmDeleteMessage; void* x11_vis; +void dc_stop(void); + enum { _NET_WM_STATE_REMOVE =0, @@ -64,6 +67,20 @@ void x11_window_set_fullscreen(bool fullscreen) XSendEvent((Display*)x11_disp, DefaultRootWindow((Display*)x11_disp), False, SubstructureNotifyMask, &xev); } +void event_x11_handle() +{ + XEvent event; + + while(XPending((Display *)x11_disp)) + { + XNextEvent((Display *)x11_disp, &event); + + if (event.type == ClientMessage && + event.xclient.data.l[0] == wmDeleteMessage) + dc_stop(); + } +} + void input_x11_handle() { if (x11_win && x11_keyboard_input) @@ -79,7 +96,7 @@ void input_x11_handle() case KeyRelease: if (e.type == KeyRelease && e.xkey.keycode == KEY_ESC) { - die("X11: death by escape key"); + dc_stop(); } #if FEAT_HAS_NIXPROF else if (e.type == KeyRelease && e.xkey.keycode == KEY_F10) @@ -244,7 +261,7 @@ void x11_window_create() // Get a visual XVisualInfo *vi = glXGetVisualFromFBConfig(x11Display, bestFbc); - printf("Chosen visual ID = 0x%x\n", vi->visualid); + printf("Chosen visual ID = 0x%lx\n", vi->visualid); depth = vi->depth; @@ -283,6 +300,10 @@ void x11_window_create() x11Window = XCreateWindow(x11Display, RootWindow(x11Display, x11Screen), (ndcid%3)*640, (ndcid/3)*480, x11_width, x11_height, 0, depth, InputOutput, x11Visual->visual, ui32Mask, &sWA); + // Capture the close window event + wmDeleteMessage = XInternAtom(x11Display, "WM_DELETE_WINDOW", False); + XSetWMProtocols(x11Display, x11Window, &wmDeleteMessage, 1); + if(x11_fullscreen) { @@ -354,12 +375,18 @@ void x11_window_destroy() if (x11_win) { XDestroyWindow((Display*)x11_disp, (Window)x11_win); - x11_win = 0; + x11_win = NULL; } if (x11_disp) { + if (x11_glc) + { + glXMakeCurrent((Display*)x11_disp, None, NULL); + glXDestroyContext((Display*)x11_disp, (GLXContext)x11_glc); + x11_glc = NULL; + } XCloseDisplay((Display*)x11_disp); - x11_disp = 0; + x11_disp = NULL; } } #endif diff --git a/core/linux-dist/x11.h b/core/linux-dist/x11.h index df042cd97..678899063 100644 --- a/core/linux-dist/x11.h +++ b/core/linux-dist/x11.h @@ -3,8 +3,10 @@ extern void* x11_glc; extern void input_x11_init(); extern void input_x11_handle(); +extern void event_x11_handle(); extern void x11_window_create(); extern void x11_window_set_text(const char* text); +extern void x11_window_destroy(); // numbers const int KEY_1 = 10; diff --git a/core/nullDC.cpp b/core/nullDC.cpp index 0a21d95f8..d5deeeaf0 100755 --- a/core/nullDC.cpp +++ b/core/nullDC.cpp @@ -227,6 +227,11 @@ void dc_term() SaveRomFiles(get_writable_data_path("/data/")); } +void dc_stop() +{ + sh4_cpu.Stop(); +} + void LoadSettings() { #ifndef _ANDROID diff --git a/core/rec-ARM/ngen_arm.S b/core/rec-ARM/ngen_arm.S index b6c74dfbf..81294e7e5 100644 --- a/core/rec-ARM/ngen_arm.S +++ b/core/rec-ARM/ngen_arm.S @@ -173,6 +173,10 @@ do_iter: HIDDEN(no_update) CSYM(no_update): @ next_pc _MUST_ be on r4 *R4 NOT R0 anymore* + ldr r0,[r8,#-156] @load CpuRunning + cmp r0,#0 + beq CSYM(cleanup) + #if DC_PLATFORM == DC_PLATFORM_NAOMI sub r2,r8,#0x4100000 ubfx r1,r4,#1,#24 @@ -185,6 +189,8 @@ CSYM(no_update): @ next_pc _MUST_ be on r4 *R4 NOT R0 anymore* @bic r1,r4,#0xFF000000 @ldr pc,[r2,r1,lsl #1] +HIDDEN(cleanup) +CSYM(cleanup): pop {r4-r12,lr} bx lr diff --git a/core/rec-cpp/rec_cpp.cpp b/core/rec-cpp/rec_cpp.cpp index 25108ebd4..b3a3d0527 100644 --- a/core/rec-cpp/rec_cpp.cpp +++ b/core/rec-cpp/rec_cpp.cpp @@ -53,7 +53,7 @@ void ngen_mainloop(void* v_cntx) cycle_counter = 0; #if !defined(TARGET_BOUNDED_EXECUTION) - for (;;) { + for (sh4_int_bCpuRun) { #else for (int i=0; i<10000; i++) { #endif diff --git a/core/rec-x64/rec_x64.cpp b/core/rec-x64/rec_x64.cpp index 51011dd50..c4e7a5986 100644 --- a/core/rec-x64/rec_x64.cpp +++ b/core/rec-x64/rec_x64.cpp @@ -44,7 +44,7 @@ void ngen_mainloop(void* v_cntx) cycle_counter = 0; - for (;;) { + while (sh4_int_bCpuRun) { cycle_counter = SH4_TIMESLICE; do { DynarecCodeEntryPtr rcb = bm_GetCode(ctx->cntx.pc); @@ -511,4 +511,4 @@ void ngen_CC_Finish(shil_opcode* op) { } -#endif \ No newline at end of file +#endif diff --git a/core/rec-x86/rec_x86_asm.cpp b/core/rec-x86/rec_x86_asm.cpp index 505ceb820..db2975af3 100644 --- a/core/rec-x86/rec_x86_asm.cpp +++ b/core/rec-x86/rec_x86_asm.cpp @@ -93,8 +93,8 @@ do_iter: pop ecx; call rdv_DoInterrupts; mov ecx,eax; -// cmp byte ptr [sh4_int_bCpuRun],0; - // jz cleanup; + cmp byte ptr [sh4_int_bCpuRun],0; + jz cleanup; jmp no_update; cleanup: @@ -130,4 +130,4 @@ naked void DYNACALL ngen_blockcheckfail2(u32 addr) u32 gas_offs=offsetof(Sh4RCB,cntx.jdyn); void (*ngen_FailedToFindBlock)()=&ngen_FailedToFindBlock_; #endif -#endif \ No newline at end of file +#endif diff --git a/core/sdl/sdl.cpp b/core/sdl/sdl.cpp index af84ef354..aa97c26e0 100644 --- a/core/sdl/sdl.cpp +++ b/core/sdl/sdl.cpp @@ -21,7 +21,7 @@ static SDL_GLContext glcontext; static SDL_Joystick* JoySDL = 0; extern bool FrameSkipping; -extern void dc_term(); +extern void dc_stop(); extern bool KillTex; #ifdef TARGET_PANDORA @@ -374,10 +374,7 @@ void input_sdl_handle(u32 port) if (keys[12]){ kcode[port] &= ~DC_BTN_START; } if (keys[9]) { - dc_term(); - - // is there a proper way to exit? dc_term() doesn't end the dc_run() loop it seems - die("death by escape key"); + dc_stop(); } if (keys[10]) { diff --git a/core/windows/winmain.cpp b/core/windows/winmain.cpp index bba32de7e..3c01f4617 100644 --- a/core/windows/winmain.cpp +++ b/core/windows/winmain.cpp @@ -102,7 +102,7 @@ PCHAR* return argv; } - +void dc_stop(void); bool VramLockedWrite(u8* address); bool ngen_Rewrite(unat& addr,unat retadr,unat acc); @@ -247,6 +247,8 @@ void UpdateInputState(u32 port) if (GetAsyncKeyState(VK_F10)) DiscSwap(); + if (GetAsyncKeyState(VK_ESCAPE)) + dc_stop(); } void UpdateController(u32 port) @@ -734,7 +736,7 @@ void os_DoEvents() // If the message is WM_QUIT, exit the while loop if (msg.message == WM_QUIT) { - sh4_cpu.Stop(); + dc_stop(); } // Translate the message and dispatch it to WindowProc() From 3d2de4a0dc276ca815058c551508d3a037ceda1b Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Mon, 23 Jul 2018 20:26:12 +0200 Subject: [PATCH 2/6] tentative fix for rec x86/win --- core/rec-x86/rec_x86_asm.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/rec-x86/rec_x86_asm.cpp b/core/rec-x86/rec_x86_asm.cpp index db2975af3..6f53589d7 100644 --- a/core/rec-x86/rec_x86_asm.cpp +++ b/core/rec-x86/rec_x86_asm.cpp @@ -59,6 +59,8 @@ naked void ngen_FailedToFindBlock_() } } +const u32 cpurun_offset=offsetof(Sh4RCB,cntx.CpuRunning); + void (*ngen_FailedToFindBlock)()=&ngen_FailedToFindBlock_; naked void ngen_mainloop(void* cntx) { @@ -93,7 +95,9 @@ do_iter: pop ecx; call rdv_DoInterrupts; mov ecx,eax; - cmp byte ptr [sh4_int_bCpuRun],0; + mov edx,[p_sh4rcb]; + add edx,[cpu_run_offset]; + cmp dword ptr [edx],0; jz cleanup; jmp no_update; From 8dab514b2a13536d31dae7461d9c70784f5789d2 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Mon, 23 Jul 2018 20:38:31 +0200 Subject: [PATCH 3/6] yet another tentative asm fix --- core/rec-x86/rec_x86_asm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/rec-x86/rec_x86_asm.cpp b/core/rec-x86/rec_x86_asm.cpp index 6f53589d7..d2e479ef2 100644 --- a/core/rec-x86/rec_x86_asm.cpp +++ b/core/rec-x86/rec_x86_asm.cpp @@ -96,7 +96,7 @@ do_iter: call rdv_DoInterrupts; mov ecx,eax; mov edx,[p_sh4rcb]; - add edx,[cpu_run_offset]; + add edx,[cpurun_offset]; cmp dword ptr [edx],0; jz cleanup; jmp no_update; From 45d4abb64d371d9126468d6dc3524231d21c88b5 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Mon, 23 Jul 2018 20:44:35 +0200 Subject: [PATCH 4/6] "for" should be a "while" --- core/rec-cpp/rec_cpp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/rec-cpp/rec_cpp.cpp b/core/rec-cpp/rec_cpp.cpp index b3a3d0527..4732489fd 100644 --- a/core/rec-cpp/rec_cpp.cpp +++ b/core/rec-cpp/rec_cpp.cpp @@ -53,7 +53,7 @@ void ngen_mainloop(void* v_cntx) cycle_counter = 0; #if !defined(TARGET_BOUNDED_EXECUTION) - for (sh4_int_bCpuRun) { + while (sh4_int_bCpuRun) { #else for (int i=0; i<10000; i++) { #endif From 20de593a886ae7c919ce8baa2ac08f9d4c73e8b9 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Tue, 24 Jul 2018 14:27:58 +0200 Subject: [PATCH 5/6] Clean exit on OS X. Minor changes. --- core/hw/pvr/Renderer_if.cpp | 2 ++ core/nullDC.cpp | 2 ++ .../apple/emulator-osx/emulator-osx/AppDelegate.swift | 8 ++++---- shell/apple/emulator-osx/emulator-osx/EmuGLView.swift | 10 +++++++++- .../emulator-osx/emulator-osx-Bridging-Header.h | 1 + shell/apple/emulator-osx/emulator-osx/osx-main.mm | 11 +++++++++++ 6 files changed, 29 insertions(+), 5 deletions(-) diff --git a/core/hw/pvr/Renderer_if.cpp b/core/hw/pvr/Renderer_if.cpp index 174d4493f..223fe4027 100644 --- a/core/hw/pvr/Renderer_if.cpp +++ b/core/hw/pvr/Renderer_if.cpp @@ -497,7 +497,9 @@ bool rend_init() void rend_term() { renderer_enabled = false; +#if !defined(TARGET_NO_THREADS) rs.Set(); +#endif if (fCheckFrames) fclose(fCheckFrames); diff --git a/core/nullDC.cpp b/core/nullDC.cpp index d5deeeaf0..c2bdcdc8c 100755 --- a/core/nullDC.cpp +++ b/core/nullDC.cpp @@ -225,6 +225,8 @@ void dc_term() SaveSettings(); #endif SaveRomFiles(get_writable_data_path("/data/")); + + TermAudio(); } void dc_stop() diff --git a/shell/apple/emulator-osx/emulator-osx/AppDelegate.swift b/shell/apple/emulator-osx/emulator-osx/AppDelegate.swift index 0119a128b..0cee0a3f3 100644 --- a/shell/apple/emulator-osx/emulator-osx/AppDelegate.swift +++ b/shell/apple/emulator-osx/emulator-osx/AppDelegate.swift @@ -15,15 +15,15 @@ class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ aNotification: Notification) { - // Insert code here to initialize your application emu_main(); } func applicationWillTerminate(_ aNotification: Notification) { - // Insert code here to tear down your application + emu_dc_stop() } - - + func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } } diff --git a/shell/apple/emulator-osx/emulator-osx/EmuGLView.swift b/shell/apple/emulator-osx/emulator-osx/EmuGLView.swift index c7a171012..7f9ac942b 100644 --- a/shell/apple/emulator-osx/emulator-osx/EmuGLView.swift +++ b/shell/apple/emulator-osx/emulator-osx/EmuGLView.swift @@ -8,7 +8,7 @@ import Cocoa -class EmuGLView: NSOpenGLView { +class EmuGLView: NSOpenGLView , NSWindowDelegate { override var acceptsFirstResponder: Bool { return true; @@ -71,4 +71,12 @@ class EmuGLView: NSOpenGLView { emu_key_input(e.characters!, 0); } + override func viewDidMoveToWindow() { + super.viewDidMoveToWindow() + self.window!.delegate = self + } + + func windowWillClose(_ notification: Notification) { + emu_dc_stop() + } } diff --git a/shell/apple/emulator-osx/emulator-osx/emulator-osx-Bridging-Header.h b/shell/apple/emulator-osx/emulator-osx/emulator-osx-Bridging-Header.h index 6183158b7..b6fce55e4 100644 --- a/shell/apple/emulator-osx/emulator-osx/emulator-osx-Bridging-Header.h +++ b/shell/apple/emulator-osx/emulator-osx/emulator-osx-Bridging-Header.h @@ -10,6 +10,7 @@ #define emulator_osx_osx_main_Bridging_Header_h void emu_main(); +void emu_dc_stop(); int emu_single_frame(int w, int h); void emu_gles_init(); void emu_key_input(const char* key, int state); diff --git a/shell/apple/emulator-osx/emulator-osx/osx-main.mm b/shell/apple/emulator-osx/emulator-osx/osx-main.mm index a50798401..caca6dcc6 100644 --- a/shell/apple/emulator-osx/emulator-osx/osx-main.mm +++ b/shell/apple/emulator-osx/emulator-osx/osx-main.mm @@ -90,6 +90,8 @@ void gl_swap() { int dc_init(int argc,wchar* argv[]); void dc_run(); +void dc_term(); +void dc_stop(); bool has_init = false; void* emuthread(void*) { @@ -115,9 +117,18 @@ void* emuthread(void*) { dc_run(); + has_init = false; + + dc_term(); + return 0; } +extern "C" void emu_dc_stop() +{ + dc_stop(); +} + pthread_t emu_thread; extern "C" void emu_main() { pthread_create(&emu_thread, 0, &emuthread, 0); From 5960450e765a9f5611b858a48c5e63471b9f60d8 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Tue, 24 Jul 2018 17:24:56 +0200 Subject: [PATCH 6/6] Linux x86 fix. Wait for renderer thread to end. --- core/hw/pvr/Renderer_if.cpp | 4 ++++ core/rec-x86/rec_lin86_asm.S | 6 ++++-- core/rec-x86/rec_x86_asm.cpp | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/core/hw/pvr/Renderer_if.cpp b/core/hw/pvr/Renderer_if.cpp index 223fe4027..5af14df8c 100644 --- a/core/hw/pvr/Renderer_if.cpp +++ b/core/hw/pvr/Renderer_if.cpp @@ -506,6 +506,10 @@ void rend_term() if (fLogFrames) fclose(fLogFrames); + +#if !defined(TARGET_NO_THREADS) + rthd.WaitToEnd(); +#endif } void rend_vblank() diff --git a/core/rec-x86/rec_lin86_asm.S b/core/rec-x86/rec_lin86_asm.S index 2a2df3479..d57ce3c5b 100644 --- a/core/rec-x86/rec_lin86_asm.S +++ b/core/rec-x86/rec_lin86_asm.S @@ -120,8 +120,10 @@ do_iter: pop ecx call rdv_DoInterrupts mov ecx,eax -# cmp byte ptr [sh4_int_bCpuRun],0 -# jz cleanup + mov edx,[p_sh4rcb]; + add edx,[cpurun_offset]; + cmp dword ptr [edx],0; + jz cleanup; jmp no_update cleanup: diff --git a/core/rec-x86/rec_x86_asm.cpp b/core/rec-x86/rec_x86_asm.cpp index d2e479ef2..a780b94b4 100644 --- a/core/rec-x86/rec_x86_asm.cpp +++ b/core/rec-x86/rec_x86_asm.cpp @@ -132,6 +132,7 @@ naked void DYNACALL ngen_blockcheckfail2(u32 addr) } #else u32 gas_offs=offsetof(Sh4RCB,cntx.jdyn); + u32 cpurun_offset=offsetof(Sh4RCB,cntx.CpuRunning); void (*ngen_FailedToFindBlock)()=&ngen_FailedToFindBlock_; #endif #endif