From 00034c1ece976d18304a217daae76b267139f689 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 31 Oct 2020 22:06:09 +0000 Subject: [PATCH] Implement API to terminate current emulator session from within main emulator thread (ie soft power off). --- src/386_dynarec.c | 2 +- src/ibm.h | 2 ++ src/pc.c | 2 ++ src/piix_pm.c | 5 ++++- src/wx-app.cc | 11 +++++++++++ src/wx-app.h | 2 ++ src/wx-sdl2.c | 8 ++++++++ src/wx-utils.cc | 7 +++++++ src/wx-utils.h | 1 + src/x86.h | 1 + 10 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/386_dynarec.c b/src/386_dynarec.c index da47b20..895c745 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -566,7 +566,7 @@ static inline void exec_recompiler(void) } -static int cycles_main = 0; +int cycles_main = 0; void exec386_dynarec(int cycs) { uint8_t temp; diff --git a/src/ibm.h b/src/ibm.h index 90f24cb..a7925c3 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -444,3 +444,5 @@ void saveconfig_global_only(); #define MIN(a, b) ((a) < (b) ? (a) : (b)) void ide_padstr(char *str, const char *src, int len); + +void stop_emulation_now(void); diff --git a/src/pc.c b/src/pc.c index 4779266..49c43af 100644 --- a/src/pc.c +++ b/src/pc.c @@ -489,6 +489,8 @@ void resetpchard() sound_update_buf_length(); cpu_set_turbo(1); + + cycles = cycles_main = 0; } char romsets[17][40]={"IBM PC","IBM XT","Generic Turbo XT","Euro PC","Tandy 1000","Amstrad PC1512","Sinclair PC200","Amstrad PC1640","IBM AT","AMI 286 clone","Dell System 200","Misc 286","IBM AT 386","Misc 386","386 clone","486 clone","486 clone 2"}; diff --git a/src/piix_pm.c b/src/piix_pm.c index ac62dec..a3947b7 100644 --- a/src/piix_pm.c +++ b/src/piix_pm.c @@ -79,7 +79,10 @@ static void piix_pm_write(uint16_t port, uint8_t val, void *p) { pclog("PIIX transition to power state %i\n", (val >> 2) & 7); if (val == 0x20) - fatal("Power off\n"); + { + pclog("Power off\n"); + stop_emulation_now(); + } } piix->pm.pmcntrl = (piix->pm.pmcntrl & ~0xff00) | ((val & 0x1c) << 8); break; diff --git a/src/wx-app.cc b/src/wx-app.cc index ca70c16..cbe4f17 100644 --- a/src/wx-app.cc +++ b/src/wx-app.cc @@ -33,6 +33,7 @@ extern void InitXmlResource(); wxDEFINE_EVENT(WX_CALLBACK_EVENT, CallbackEvent); wxDEFINE_EVENT(WX_EXIT_EVENT, wxCommandEvent); wxDEFINE_EVENT(WX_STOP_EMULATION_EVENT, wxCommandEvent); +wxDEFINE_EVENT(WX_STOP_EMULATION_NOW_EVENT, wxCommandEvent); wxDEFINE_EVENT(WX_EXIT_COMPLETE_EVENT, wxCommandEvent); wxDEFINE_EVENT(WX_SHOW_WINDOW_EVENT, wxCommandEvent); wxDEFINE_EVENT(WX_POPUP_MENU_EVENT, PopupMenuEvent); @@ -89,6 +90,7 @@ Frame::Frame(App* app, const wxString& title, const wxPoint& pos, Bind(WX_EXIT_EVENT, &Frame::OnExitEvent, this); Bind(WX_EXIT_COMPLETE_EVENT, &Frame::OnExitCompleteEvent, this); Bind(WX_STOP_EMULATION_EVENT, &Frame::OnStopEmulationEvent, this); + Bind(WX_STOP_EMULATION_NOW_EVENT, &Frame::OnStopEmulationNowEvent, this); Bind(WX_CALLBACK_EVENT, &Frame::OnCallbackEvent, this); #ifdef _WIN32 Bind(WX_WIN_SEND_MESSAGE_EVENT, &Frame::OnWinSendMessageEvent, this); @@ -151,6 +153,15 @@ void Frame::OnStopEmulationEvent(wxCommandEvent& event) } } +void Frame::OnStopEmulationNowEvent(wxCommandEvent& event) +{ + stop_emulation(); + if (!config_override) + ShowConfigSelection(); + else + Quit(1); +} + void Frame::OnShowWindowEvent(wxCommandEvent& event) { wxWindow* window = (wxWindow*)event.GetEventObject(); diff --git a/src/wx-app.h b/src/wx-app.h index 803f5d1..4c6d29a 100644 --- a/src/wx-app.h +++ b/src/wx-app.h @@ -14,6 +14,7 @@ class PopupMenuEvent; wxDECLARE_EVENT(WX_CALLBACK_EVENT, CallbackEvent); wxDECLARE_EVENT(WX_EXIT_EVENT, wxCommandEvent); wxDECLARE_EVENT(WX_STOP_EMULATION_EVENT, wxCommandEvent); +wxDECLARE_EVENT(WX_STOP_EMULATION_NOW_EVENT, wxCommandEvent); wxDECLARE_EVENT(WX_EXIT_COMPLETE_EVENT, wxCommandEvent); wxDECLARE_EVENT(WX_SHOW_WINDOW_EVENT, wxCommandEvent); wxDECLARE_EVENT(WX_POPUP_MENU_EVENT, PopupMenuEvent); @@ -155,6 +156,7 @@ private: void OnExitEvent(wxCommandEvent& event); void OnExitCompleteEvent(wxCommandEvent& event); void OnStopEmulationEvent(wxCommandEvent& event); + void OnStopEmulationNowEvent(wxCommandEvent& event); void OnShowWindowEvent(wxCommandEvent& event); void OnPopupMenuEvent(PopupMenuEvent& event); void OnCallbackEvent(CallbackEvent& event); diff --git a/src/wx-sdl2.c b/src/wx-sdl2.c index 3ff93fb..0813929 100644 --- a/src/wx-sdl2.c +++ b/src/wx-sdl2.c @@ -223,6 +223,14 @@ int mainthread(void* param) return TRUE; } +void stop_emulation_now(void) +{ + /*Deduct a sufficiently large number of cycles that no instructions will + run before the main thread is terminated*/ + cycles -= 99999999; + wx_stop_emulation_now(ghwnd); +} + int dir_exists(char* path) { return wx_dir_exists(path); diff --git a/src/wx-utils.cc b/src/wx-utils.cc index 819475e..f62a8ec 100644 --- a/src/wx-utils.cc +++ b/src/wx-utils.cc @@ -449,6 +449,13 @@ void wx_stop_emulation(void* window) wxQueueEvent((wxWindow*)window, event); } +void wx_stop_emulation_now(void* window) +{ + wxCommandEvent* event = new wxCommandEvent(WX_STOP_EMULATION_NOW_EVENT, wxID_ANY); + event->SetEventObject((wxWindow*)window); + wxQueueEvent((wxWindow*)window, event); +} + int wx_yield() { return wxYield(); diff --git a/src/wx-utils.h b/src/wx-utils.h index 631f6d1..0b12970 100644 --- a/src/wx-utils.h +++ b/src/wx-utils.h @@ -52,6 +52,7 @@ extern "C" { void wx_exit(void* window, int value); void wx_stop_emulation(void* window); + void wx_stop_emulation_now(void* window); void* wx_createtimer(void (*fn)()); void wx_starttimer(void* timer, int milliseconds, int once); diff --git a/src/x86.h b/src/x86.h index 9c0d328..12125e4 100644 --- a/src/x86.h +++ b/src/x86.h @@ -126,6 +126,7 @@ struct #define cpu_state_offset(MEMBER) ((uintptr_t)&cpu_state.MEMBER - (uintptr_t)&cpu_state - 128) #define cycles cpu_state._cycles +extern int cycles_main; #define cr0 cpu_state.CR0.l #define msw cpu_state.CR0.w