diff --git a/core/coresignal.h b/core/coresignal.h index 5caae1a..198180f 100644 --- a/core/coresignal.h +++ b/core/coresignal.h @@ -58,6 +58,14 @@ public: } } + void disconnect(int id) { + _slots.erase(id); + } + + void disconnect_all() { + _slots.clear(); + } + private: mutable std::map> _slots; mutable unsigned int _current_id { 0 }; diff --git a/core/hostevents.h b/core/hostevents.h index 2092f33..4aeeff9 100644 --- a/core/hostevents.h +++ b/core/hostevents.h @@ -94,6 +94,13 @@ public: _post_signal.connect_method(inst, func); } + void disconnect_handlers() { + _window_signal.disconnect_all(); + _mouse_signal.disconnect_all(); + _keyboard_signal.disconnect_all(); + _post_signal.disconnect_all(); + } + private: static EventManager* event_manager; EventManager() {}; // private constructor to implement a singleton diff --git a/cpu/ppc/ppcemu.h b/cpu/ppc/ppcemu.h index 0895a7a..acb468e 100644 --- a/cpu/ppc/ppcemu.h +++ b/cpu/ppc/ppcemu.h @@ -322,6 +322,8 @@ enum Po_Cause : int { po_starting_up, po_shut_down, po_shutting_down, + po_restarting, + po_restart, po_disassemble_on, po_disassemble_off, po_enter_debugger, diff --git a/debugger/debugger.cpp b/debugger/debugger.cpp index e9cd6d6..0f392fe 100644 --- a/debugger/debugger.cpp +++ b/debugger/debugger.cpp @@ -458,6 +458,10 @@ void enter_debugger() { power_off_reason = po_shutting_down; break; } + if (power_off_reason == po_restart) { + power_off_reason = po_restarting; + break; + } power_on = true; if (power_off_reason == po_starting_up) { diff --git a/devices/common/viacuda.cpp b/devices/common/viacuda.cpp index 78eebc9..796705a 100644 --- a/devices/common/viacuda.cpp +++ b/devices/common/viacuda.cpp @@ -25,6 +25,7 @@ along with this program. If not, see . #include #include #include +#include #include #include #include @@ -654,10 +655,14 @@ void ViaCuda::pseudo_command(int cmd, int data_count) { LOG_F(INFO, "Cuda: send %d to PB0", (int)(this->in_buf[2])); response_header(CUDA_PKT_PSEUDO, 0); break; + case CUDA_RESTART_SYSTEM: + LOG_F(INFO, "Cuda: system restart"); + power_on = false; + power_off_reason = po_restart; + break; case CUDA_WARM_START: case CUDA_POWER_DOWN: case CUDA_MONO_STABLE_RESET: - case CUDA_RESTART_SYSTEM: /* really kludge temp code */ LOG_F(INFO, "Cuda: Restart/Shutdown signal sent with command 0x%x!", cmd); //exit(0); diff --git a/main.cpp b/main.cpp index 784af16..53ecd2e 100644 --- a/main.cpp +++ b/main.cpp @@ -61,6 +61,8 @@ static string appDescription = string( "\n" ); +void run_machine(std::string machine_str, std::string bootrom_path, uint32_t execution_mode); + int main(int argc, char** argv) { uint32_t execution_mode = interpreter; @@ -166,10 +168,6 @@ int main(int argc, char** argv) { // initialize global profiler object gProfilerObj.reset(new Profiler()); - if (MachineFactory::create_machine_for_id(machine_str, bootrom_path) < 0) { - goto bail; - } - // graceful handling of fatal errors loguru::set_fatal_handler([](const loguru::Message& message) { // Make sure the reason for the failure is visible (it may have been @@ -187,9 +185,29 @@ int main(int argc, char** argv) { // redirect SIGABRT to our own handler signal(SIGABRT, sigabrt_handler); + while (true) { + run_machine(machine_str, bootrom_path, execution_mode); + if (power_off_reason == po_restarting) { + LOG_F(INFO, "Restarting..."); + power_on = true; + continue; + } + break; + } + + cleanup(); + + return 0; +} + +void run_machine(std::string machine_str, std::string bootrom_path, uint32_t execution_mode) { + if (MachineFactory::create_machine_for_id(machine_str, bootrom_path) < 0) { + return; + } + // set up system wide event polling using // default Macintosh polling rate of 11 ms - TimerManager::get_instance()->add_cyclic_timer(MSECS_TO_NSECS(11), [] { + uint32_t event_timer = TimerManager::get_instance()->add_cyclic_timer(MSECS_TO_NSECS(11), [] { EventManager::get_instance()->poll_events(); }); @@ -204,15 +222,11 @@ int main(int argc, char** argv) { break; default: LOG_F(ERROR, "Invalid EXECUTION MODE"); - return 1; + return; } -bail: LOG_F(INFO, "Cleaning up..."); - + TimerManager::get_instance()->cancel_timer(event_timer); + EventManager::get_instance()->disconnect_handlers(); delete gMachineObj.release(); - - cleanup(); - - return 0; }