diff --git a/src/common/ThreadDebugging.cxx b/src/common/ThreadDebugging.cxx index 542b29e3e..d46e83a5f 100644 --- a/src/common/ThreadDebugging.cxx +++ b/src/common/ThreadDebugging.cxx @@ -15,16 +15,14 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include -#include - #include "ThreadDebugging.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ThreadDebuggingHelper::ThreadDebuggingHelper() : myMainThreadIdConfigured(false) {} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ThreadDebuggingHelper& ThreadDebuggingHelper::instance() { static ThreadDebuggingHelper instance; @@ -33,16 +31,14 @@ ThreadDebuggingHelper& ThreadDebuggingHelper::instance() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ThreadDebuggingHelper::fail(std::string message) +void ThreadDebuggingHelper::fail(const string& message) { - std::cerr << message << std::endl; + cerr << message << endl; - throw std::runtime_error(message); + throw runtime_error(message); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void ThreadDebuggingHelper::setMainThread() { if (myMainThreadIdConfigured) fail("main thread already configured"); @@ -52,7 +48,6 @@ void ThreadDebuggingHelper::setMainThread() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void ThreadDebuggingHelper::assertMainThread() { if (!myMainThreadIdConfigured) fail("main thread not configured"); diff --git a/src/common/ThreadDebugging.hxx b/src/common/ThreadDebugging.hxx index 7b451e352..5da4ce083 100644 --- a/src/common/ThreadDebugging.hxx +++ b/src/common/ThreadDebugging.hxx @@ -15,8 +15,13 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#ifndef THREADING_DEBUGGER_HXX +#define THREADING_DEBUGGER_HXX + #include +#include "bspf.hxx" + #ifdef DEBUG_BUILD #define SET_MAIN_THREAD ThreadDebuggingHelper::instance().setMainThread(); @@ -41,7 +46,7 @@ class ThreadDebuggingHelper { private: - void fail(std::string message); + void fail(const string& message); ThreadDebuggingHelper(); @@ -56,3 +61,5 @@ class ThreadDebuggingHelper { ThreadDebuggingHelper& operator=(const ThreadDebuggingHelper&) = delete; ThreadDebuggingHelper& operator=(ThreadDebuggingHelper&&) = delete; }; + +#endif // THREADING_DEBUGGER_HXX diff --git a/src/emucore/CartBUS.cxx b/src/emucore/CartBUS.cxx index 9fb3c0744..36585931a 100644 --- a/src/emucore/CartBUS.cxx +++ b/src/emucore/CartBUS.cxx @@ -25,6 +25,7 @@ #include "TIA.hxx" #include "Thumbulator.hxx" #include "CartBUS.hxx" +#include "exception/FatalEmulationError.hxx" // Location of data within the RAM copy of the BUS Driver. #define DSxPTR 0x06D8 @@ -171,11 +172,7 @@ inline void CartridgeBUS::callFunction(uInt8 value) catch(const runtime_error& e) { if(!mySystem->autodetectMode()) { - #ifdef DEBUGGER_SUPPORT - Debugger::debugger().startWithFatalError(e.what()); - #else - cout << e.what() << endl; - #endif + FatalEmulationError::raise(e.what()); } } break; diff --git a/src/emucore/CartCDF.cxx b/src/emucore/CartCDF.cxx index f4c4a1025..1aee02f95 100644 --- a/src/emucore/CartCDF.cxx +++ b/src/emucore/CartCDF.cxx @@ -25,6 +25,7 @@ #include "Thumbulator.hxx" #include "CartCDF.hxx" #include "TIA.hxx" +#include "exception/FatalEmulationError.hxx" // Location of data within the RAM copy of the CDF Driver. // Version 0 1 @@ -166,11 +167,7 @@ inline void CartridgeCDF::callFunction(uInt8 value) catch(const runtime_error& e) { if(!mySystem->autodetectMode()) { -#ifdef DEBUGGER_SUPPORT - Debugger::debugger().startWithFatalError(e.what()); -#else - cout << e.what() << endl; -#endif + FatalEmulationError::raise(e.what()); } } break; diff --git a/src/emucore/CartDPCPlus.cxx b/src/emucore/CartDPCPlus.cxx index 131fe6679..706312f6a 100644 --- a/src/emucore/CartDPCPlus.cxx +++ b/src/emucore/CartDPCPlus.cxx @@ -22,6 +22,7 @@ #include "Thumbulator.hxx" #include "CartDPCPlus.hxx" #include "TIA.hxx" +#include "exception/FatalEmulationError.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeDPCPlus::CartridgeDPCPlus(const BytePtr& image, uInt32 size, @@ -191,11 +192,7 @@ inline void CartridgeDPCPlus::callFunction(uInt8 value) catch(const runtime_error& e) { if(!mySystem->autodetectMode()) { - #ifdef DEBUGGER_SUPPORT - Debugger::debugger().startWithFatalError(e.what()); - #else - cout << e.what() << endl; - #endif + FatalEmulationError::raise(e.what()); } } break; diff --git a/src/emucore/DispatchResult.cxx b/src/emucore/DispatchResult.cxx index 31900d9ae..5b15a50c0 100644 --- a/src/emucore/DispatchResult.cxx +++ b/src/emucore/DispatchResult.cxx @@ -53,3 +53,9 @@ void DispatchResult::setFatal(uInt64 cycles) myStatus = Status::fatal; } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void DispatchResult::setMessage(const string& message) +{ + myMessage = message; +} diff --git a/src/emucore/DispatchResult.hxx b/src/emucore/DispatchResult.hxx index 08b3dba08..99f25ad23 100644 --- a/src/emucore/DispatchResult.hxx +++ b/src/emucore/DispatchResult.hxx @@ -34,7 +34,7 @@ class DispatchResult uInt64 getCycles() const { return myCycles; } - const string& getMessage() const { assertStatus(Status::debugger); return myMessage; } + const string& getMessage() const { assertStatus(Status::debugger, Status::fatal); return myMessage; } int getAddress() const { assertStatus(Status::debugger); return myAddress; } @@ -48,10 +48,19 @@ class DispatchResult void setFatal(uInt64 cycles); + void setMessage(const string& message); + private: void assertStatus(Status status) const; + template void assertStatus(Status status, Ts... more) const + { + if (myStatus == status) return; + + assertStatus(more...); + } + private: Status myStatus; diff --git a/src/emucore/M6502.cxx b/src/emucore/M6502.cxx index 05a5e539b..a332f8091 100644 --- a/src/emucore/M6502.cxx +++ b/src/emucore/M6502.cxx @@ -48,6 +48,7 @@ #include "System.hxx" #include "M6502.hxx" #include "DispatchResult.hxx" +#include "exception/FatalEmulationError.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - M6502::M6502(const Settings& settings) @@ -306,19 +307,24 @@ inline void M6502::_execute(uInt64 cycles, DispatchResult& result) // Reset the peek/poke address pointers myLastPeekAddress = myLastPokeAddress = myDataAddressForPoke = 0; - icycles = 0; - // Fetch instruction at the program counter - IR = peek(PC++, DISASM_CODE); // This address represents a code section + try { + icycles = 0; - // Call code to execute the instruction - switch(IR) - { - // 6502 instruction emulation is generated by an M4 macro file - #include "M6502.ins" + // Fetch instruction at the program counter + IR = peek(PC++, DISASM_CODE); // This address represents a code section - default: - // Oops, illegal instruction executed so set fatal error flag - myExecutionStatus |= FatalErrorBit; + // Call code to execute the instruction + switch(IR) + { + // 6502 instruction emulation is generated by an M4 macro file + #include "M6502.ins" + + default: + FatalEmulationError::raise("invalid instruction"); + } + } catch (FatalEmulationError& e) { + myExecutionStatus |= FatalErrorBit; + result.setMessage(e.what()); } currentCycles = (mySystem->cycles() - previousCycles); @@ -343,6 +349,15 @@ inline void M6502::_execute(uInt64 cycles, DispatchResult& result) interruptHandler(); } + // See if a fatal error has occured + if(myExecutionStatus & FatalErrorBit) + { + // Yes, so answer that something when wrong. The message has already been set when + // the exception was handled. + result.setFatal(currentCycles); + return; + } + // See if execution has been stopped if(myExecutionStatus & StopExecutionBit) { @@ -351,18 +366,7 @@ inline void M6502::_execute(uInt64 cycles, DispatchResult& result) return; } - // See if a fatal error has occured - if(myExecutionStatus & FatalErrorBit) - { - // Yes, so answer that something when wrong - result.setFatal(currentCycles + icycles); - return; - } - - // See if we've executed the specified number of instructions - if (currentCycles >= cycles * SYSTEM_CYCLES_PER_CPU) - { - // Yes, so answer that everything finished fine + if (currentCycles >= cycles * SYSTEM_CYCLES_PER_CPU) { result.setOk(currentCycles); return; } diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index 61b2dafd8..730352c04 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -626,14 +626,34 @@ double OSystem::dispatchEmulation(EmulationWorker& emulationWorker) // Stop the worker and wait until it has finished uInt64 totalCycles = emulationWorker.stop(); -#ifdef DEBUGGER_SUPPORT - // Break or trap? -> start debugger - if (dispatchResult.getStatus() == DispatchResult::Status::debugger) myDebugger->start( - dispatchResult.getMessage(), - dispatchResult.getAddress(), - dispatchResult.wasReadTrap() - ); -#endif + // Handle the dispatch result + switch (dispatchResult.getStatus()) { + case DispatchResult::Status::ok: + break; + + case DispatchResult::Status::debugger: + #ifdef DEBUGGER_SUPPORT + myDebugger->start( + dispatchResult.getMessage(), + dispatchResult.getAddress(), + dispatchResult.wasReadTrap() + ); + #endif + + break; + + case DispatchResult::Status::fatal: + #ifdef DEBUGGER_SUPPORT + myDebugger->startWithFatalError(dispatchResult.getMessage()); + #else + throw runtime_error(dispatchResult.getMessage()); + #endif + + break; + + default: + throw runtime_error("invalid emulation dispatch result"); + } // Handle frying if (dispatchResult.getStatus() == DispatchResult::Status::ok && myEventHandler->frying()) diff --git a/src/emucore/exception/FatalEmulationError.cxx b/src/emucore/exception/FatalEmulationError.cxx new file mode 100644 index 000000000..c75b0fe6b --- /dev/null +++ b/src/emucore/exception/FatalEmulationError.cxx @@ -0,0 +1,35 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include "FatalEmulationError.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +FatalEmulationError::FatalEmulationError(const string& message) + : myMessage(message) +{} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const char* FatalEmulationError::what() const throw() +{ + return myMessage.c_str(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FatalEmulationError::raise(const string& message) +{ + throw FatalEmulationError(message); +} diff --git a/src/emucore/exception/FatalEmulationError.hxx b/src/emucore/exception/FatalEmulationError.hxx new file mode 100644 index 000000000..8c092b8b2 --- /dev/null +++ b/src/emucore/exception/FatalEmulationError.hxx @@ -0,0 +1,39 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#ifndef FATAL_EMULATION_ERROR_HXX +#define FATAL_EMULATION_ERROR_HXX + +#include "bspf.hxx" + +class FatalEmulationError: public std::exception { + + public: + + FatalEmulationError(const string& message); + + virtual const char* what() const throw(); + + static void raise(const string& message); + + private: + + const string myMessage; + +}; + +#endif // FATAL_EMULATION_ERROR_HXX diff --git a/src/emucore/module.mk b/src/emucore/module.mk index 778b747b1..3ea4ba691 100644 --- a/src/emucore/module.mk +++ b/src/emucore/module.mk @@ -80,7 +80,8 @@ MODULE_OBJS := \ src/emucore/Switches.o \ src/emucore/System.o \ src/emucore/TIASurface.o \ - src/emucore/Thumbulator.o + src/emucore/Thumbulator.o \ + src/emucore/exception/FatalEmulationError.o MODULE_DIRS += \ src/emucore