diff --git a/core/hw/pvr/Renderer_if.cpp b/core/hw/pvr/Renderer_if.cpp index cc34362cf..5af14df8c 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,11 +496,20 @@ bool rend_init() void rend_term() { + renderer_enabled = false; +#if !defined(TARGET_NO_THREADS) + rs.Set(); +#endif + if (fCheckFrames) fclose(fCheckFrames); if (fLogFrames) fclose(fLogFrames); + +#if !defined(TARGET_NO_THREADS) + rthd.WaitToEnd(); +#endif } void rend_vblank() 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..c2bdcdc8c 100755 --- a/core/nullDC.cpp +++ b/core/nullDC.cpp @@ -225,6 +225,13 @@ void dc_term() SaveSettings(); #endif SaveRomFiles(get_writable_data_path("/data/")); + + TermAudio(); +} + +void dc_stop() +{ + sh4_cpu.Stop(); } void LoadSettings() 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..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 (;;) { + while (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_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 505ceb820..a780b94b4 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,8 +95,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: @@ -128,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 \ 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() 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);