Merge pull request #1236 from reicast/clean-exit-light
Exit cleanly in desktop platforms
This commit is contained in:
commit
9beb87ef64
|
@ -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()
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -225,6 +225,13 @@ void dc_term()
|
|||
SaveSettings();
|
||||
#endif
|
||||
SaveRomFiles(get_writable_data_path("/data/"));
|
||||
|
||||
TermAudio();
|
||||
}
|
||||
|
||||
void dc_stop()
|
||||
{
|
||||
sh4_cpu.Stop();
|
||||
}
|
||||
|
||||
void LoadSettings()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
#endif
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
#endif
|
||||
|
|
|
@ -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])
|
||||
{
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue