Updated Thumb ARM emulation to log its output instead of printing to the

console (which doesn't exist on every platform).  Also use proper C++
stringstreams instead of C-style arrays (which are evil).  If an exception
is thrown, start the debugger with a fatal error message.  Currently, this
message is simply printed in the debugger info window.  Still TODO is add
a dialog to show the entire input from within the UI, as well as a way
to exit the ROM when a fatal error occurs.

Cleaned up the API a little, adding explicit declarations for when a method
can throw an exception.  Also merged some empty classes directly into their
header files.

Added functionality to the System class for querying whether it has 
been reset while in 'autodetect' mode.  Autodect mode is defined as
when Stella starts and temporarily runs to autoconfigure itself.
Some classes (such as Thumb ARM emulation) need to know this, and
suppress debugging output/throwing exceptions when not running in
normal emulation mode.

I hope to have a new release done by the end of this week, or the end
of the month at the latest.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2232 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2011-05-24 16:04:48 +00:00
parent 4e6d4cb1c6
commit 5025a21d92
29 changed files with 301 additions and 253 deletions

View File

@ -120,7 +120,7 @@ class Array
return _data[idx];
}
Array<T>& operator =(const Array<T>& array)
Array<T>& operator =(const Array<T>& array)
{
if (_data)
delete [] _data;

View File

@ -37,6 +37,7 @@ PNGLibrary::~PNGLibrary()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PNGLibrary::readImage(const FrameBuffer& fb, FBSurface& surface)
throw(const char*)
{
#define readImageERROR(s) { err_message = s; goto done; }

View File

@ -51,7 +51,7 @@ class PNGLibrary
@return On success, the FBSurface containing image data and a
result of true, otherwise an exception is thrown.
*/
bool readImage(const FrameBuffer& fb, FBSurface& surface);
bool readImage(const FrameBuffer& fb, FBSurface& surface) throw(const char*);
private:
/**

View File

@ -67,6 +67,7 @@
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <cstring>
#include <cctype>
using namespace std;
@ -110,6 +111,11 @@ using namespace std;
#define BSPF_ARCH "NOARCH"
#endif
// Used for stringstreams
#define HEX8 uppercase << hex << setw(8) << setfill('0')
#define HEX4 uppercase << hex << setw(4) << setfill('0')
#define HEX2 uppercase << hex << setw(2) << setfill('0')
// Some convenience functions
template<typename T> inline void BSPF_swap(T& a, T& b) { T tmp = a; a = b; b = tmp; }
template<typename T> inline T BSPF_abs (T x) { return (x>=0) ? x : -x; }
@ -151,8 +157,4 @@ inline size_t BSPF_findIgnoreCase(const string& s1, const string& s2)
static const string EmptyString("");
#ifdef _WIN32_WCE
#include "missing.h"
#endif
#endif

View File

@ -84,6 +84,8 @@ int stellaMain(int argc, char* argv[])
int main(int argc, char* argv[])
#endif
{
ios_base::sync_with_stdio(false);
// Create the parent OSystem object and settings
#if defined(UNIX)
theOSystem = new OSystemUNIX();

View File

@ -48,9 +48,6 @@ class ButtonWidget;
#include "Stack.hxx"
#include "bspf.hxx"
#define HEX4 uppercase << hex << setw(4) << setfill('0')
#define HEX2 uppercase << hex << setw(2) << setfill('0')
typedef map<string,Expression*> FunctionMap;
typedef map<string,string> FunctionDefMap;

View File

@ -64,7 +64,7 @@ class AtariVox : public Controller
@param pin The pin of the controller jack to read
@return The state of the pin
*/
virtual bool read(DigitalPin pin);
bool read(DigitalPin pin);
/**
Write the given value to the specified digital pin for this
@ -74,20 +74,20 @@ class AtariVox : public Controller
@param pin The pin of the controller jack to write to
@param value The value to write to the pin
*/
virtual void write(DigitalPin pin, bool value);
void write(DigitalPin pin, bool value);
/**
Update the entire digital and analog pin state according to the
events currently set.
*/
virtual void update() { }
void update() { }
/**
Notification method invoked by the system right before the
system resets its cycle counter to zero. It may be necessary
to override this method for devices that remember cycle counts.
*/
virtual void systemCyclesReset();
void systemCyclesReset();
virtual string about() const;

View File

@ -53,7 +53,7 @@ class BoosterGrip : public Controller
Update the entire digital and analog pin state according to the
events currently set.
*/
virtual void update();
void update();
private:
// Pre-compute the events we care about based on given port

View File

@ -208,11 +208,14 @@ inline void CartridgeDPCPlus::callFunction(uInt8 value)
try {
myThumbEmulator->run();
}
catch(const char* msg) {
cerr << msg << endl;
#ifdef DEBUGGER_SUPPORT
Debugger::debugger().startWithFatalError(msg);
#endif
catch(const string& error) {
if(!mySystem->autodectMode())
{
cerr << error << endl;
#ifdef DEBUGGER_SUPPORT
Debugger::debugger().startWithFatalError(error);
#endif
}
}
break;
#endif

View File

@ -132,7 +132,7 @@ Console::Console(OSystem* osystem, Cartridge* cart, const Properties& props)
// The 'fastscbios' option must be changed before the system is reset
bool fastscbios = myOSystem->settings().getBool("fastscbios");
myOSystem->settings().setBool("fastscbios", true);
mySystem->reset();
mySystem->reset(true); // autodetect in reset enabled
int palCount = 0;
for(int i = 0; i < 60; ++i)
{

View File

@ -1,37 +0,0 @@
//============================================================================
//
// MM MM 6666 555555 0000 2222
// MMMM MMMM 66 66 55 00 00 22 22
// MM MMM MM 66 55 00 00 22
// MM M MM 66666 55555 00 00 22222 -- "A 6502 Microprocessor Emulator"
// MM MM 66 66 55 00 00 22
// MM MM 66 66 55 55 00 00 22
// MM MM 6666 5555 0000 222222
//
// Copyright (c) 1995-2011 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.
//
// $Id$
//============================================================================
#include "Device.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Device::Device()
: mySystem(0)
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Device::~Device()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Device::systemCyclesReset()
{
// By default I do nothing when my system resets its cycle counter
}

View File

@ -38,12 +38,12 @@ class Device : public Serializable
/**
Create a new device
*/
Device();
Device() : mySystem(0) { }
/**
Destructor
*/
virtual ~Device();
virtual ~Device() { }
public:
/**
@ -60,7 +60,7 @@ class Device : public Serializable
system resets its cycle counter to zero. It may be necessary
to override this method for devices that remember cycle counts.
*/
virtual void systemCyclesReset();
virtual void systemCyclesReset() { }
/**
Install device in the specified system. Invoked by the system

View File

@ -53,7 +53,7 @@ class Driving : public Controller
Update the entire digital and analog pin state according to the
events currently set.
*/
virtual void update();
void update();
private:
// Counter to iterate through the gray codes

View File

@ -55,7 +55,7 @@ class Genesis : public Controller
Update the entire digital and analog pin state according to the
events currently set.
*/
virtual void update();
void update();
private:
// Pre-compute the events we care about based on given port

View File

@ -52,7 +52,7 @@ class Joystick : public Controller
Update the entire digital and analog pin state according to the
events currently set.
*/
virtual void update();
void update();
/**
Sets the deadzone amount for real analog joysticks.

View File

@ -56,13 +56,13 @@ class Keyboard : public Controller
@param pin The pin of the controller jack to write to
@param value The value to write to the pin
*/
virtual void write(DigitalPin pin, bool value);
void write(DigitalPin pin, bool value);
/**
Update the entire digital and analog pin state according to the
events currently set.
*/
virtual void update();
void update();
private:
// State of the output pins

View File

@ -59,7 +59,7 @@ class Paddles : public Controller
Update the entire digital and analog pin state according to the
events currently set.
*/
virtual void update();
void update();
/**
Sets the sensitivity for digital emulation of paddle movement.

View File

@ -60,7 +60,7 @@ class SaveKey : public Controller
@param pin The pin of the controller jack to read
@return The state of the pin
*/
virtual bool read(DigitalPin pin);
bool read(DigitalPin pin);
/**
Write the given value to the specified digital pin for this
@ -70,20 +70,20 @@ class SaveKey : public Controller
@param pin The pin of the controller jack to write to
@param value The value to write to the pin
*/
virtual void write(DigitalPin pin, bool value);
void write(DigitalPin pin, bool value);
/**
Update the entire digital and analog pin state according to the
events currently set.
*/
virtual void update() { }
void update() { }
/**
Notification method invoked by the system right before the
system resets its cycle counter to zero. It may be necessary
to override this method for devices that remember cycle counts.
*/
virtual void systemCyclesReset();
void systemCyclesReset();
private:
// The EEPROM used in the SaveKey

View File

@ -37,7 +37,8 @@ System::System(uInt16 n, uInt16 m)
myTIA(0),
myCycles(0),
myDataBusState(0),
myDataBusLocked(false)
myDataBusLocked(false),
mySystemInAutodetect(false)
{
// Make sure the arguments are reasonable
assert((1 <= m) && (m <= n) && (n <= 16));
@ -85,22 +86,21 @@ System::~System()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::reset()
void System::reset(bool autodetect)
{
// Provide hint to devices that autodetection is active (or not)
mySystemInAutodetect = autodetect;
// Reset system cycle counter
resetCycles();
// First we reset the devices attached to myself
for(uInt32 i = 0; i < myNumberOfDevices; ++i)
{
myDevices[i]->reset();
}
// Now we reset the processor if it exists
if(myM6502 != 0)
{
myM6502->reset();
}
// There are no dirty pages upon startup
clearDirtyPages();

View File

@ -66,8 +66,15 @@ class System : public Serializable
/**
Reset the system cycle counter, the attached devices, and the
attached processor of the system.
@param autodetect A hint to devices that the system is currently
in autodetect mode. That is, the system is being
run to autodetect certain device settings before
actual emulation will begin. Certain devices may
use this hint to act differently under those
circumstances.
*/
void reset();
void reset(bool autodetect = false);
/**
Attach the specified device and claim ownership of it. The device
@ -204,6 +211,11 @@ class System : public Serializable
*/
void resetCycles();
/**
Answers whether the system is currently in device autodetect mode.
*/
bool autodectMode() const { return mySystemInAutodetect; }
public:
/**
Get the current state of the data bus in the system. The current
@ -472,6 +484,11 @@ class System : public Serializable
// debugger is active.
bool myDataBusLocked;
// Whether autodetection is currently running (ie, the emulation
// core is attempting to autodetect display settings, cart modes, etc)
// Some parts of the codebase need to act differently in such a case
bool mySystemInAutodetect;
private:
// Copy constructor isn't supported by this class so make it private
System(const System&);

File diff suppressed because it is too large Load Diff

View File

@ -65,7 +65,15 @@ class Thumbulator
Thumbulator(uInt16* rom, uInt16* ram);
~Thumbulator();
int run();
/**
Run the ARM code, and return when finished. An exception is thrown
in case of any fatal errors/aborts, containing the actual error,
and the contents of the registers at that point in time.
@return The results of any debugging output (if enabled),
otherwise an empty string
*/
string run() throw(const string&);
private:
uInt32 read_register ( uInt32 reg );
@ -85,7 +93,10 @@ class Thumbulator
void do_cflag_bit ( uInt32 x );
void do_vflag_bit ( uInt32 x );
int fatalError(const char* opcode, uInt32 v1, const char* msg) throw(const string&);
int fatalError(const char* opcode, uInt32 v1, uInt32 v2, const char* msg) throw(const string&);
void dump_counters ( void );
void dump_regs( void );
int execute ( void );
int reset ( void );
@ -111,7 +122,7 @@ class Thumbulator
Int32 DBUG; // dump detailed execution trace
Int32 DISS; // dump Thumb instruction trace
char errorMsg[100];
ostringstream statusMsg;
};
#endif

View File

@ -68,8 +68,8 @@ bool TrackBall::read(DigitalPin pin)
// Only update the controller pins when an SWCHA read is actually
// different from a previous one
// This is done since Stella tends to read several pins consecutively
// in the same processor 'cycle', and it would be inefficient/incorrect
// to do this work multiple times per processor cycle
// in the same processor 'cycle', and it would be incorrect to do this
// work multiple times per processor cycle
if(myCyclesWhenSWCHARead != mySystem.cycles())
{
int scanline = ((System&)mySystem).tia().scanlines();

View File

@ -63,20 +63,20 @@ class TrackBall : public Controller
@param pin The pin of the controller jack to read
@return The state of the pin
*/
virtual bool read(DigitalPin pin);
bool read(DigitalPin pin);
/**
Update the entire digital and analog pin state according to the
events currently set.
*/
virtual void update();
void update();
/**
Notification method invoked by the system right before the
system resets its cycle counter to zero. It may be necessary
to override this method for devices that remember cycle counts.
*/
virtual void systemCyclesReset();
void systemCyclesReset();
private:
// Counter to iterate through the gray codes

View File

@ -33,7 +33,6 @@ MODULE_OBJS := \
src/emucore/CartX07.o \
src/emucore/Console.o \
src/emucore/Control.o \
src/emucore/Device.o \
src/emucore/Driving.o \
src/emucore/EventHandler.o \
src/emucore/FrameBuffer.o \

View File

@ -301,7 +301,6 @@
DCAD60A81152F8BD00BC4184 /* CartDPCPlus.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCAD60A61152F8BD00BC4184 /* CartDPCPlus.cxx */; };
DCAD60A91152F8BD00BC4184 /* CartDPCPlus.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCAD60A71152F8BD00BC4184 /* CartDPCPlus.hxx */; };
DCB9DA5F0FCD527000B192F6 /* GLShaderProgs.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCB9DA5E0FCD527000B192F6 /* GLShaderProgs.hxx */; };
DCC527D010B9DA19005E1287 /* Device.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCC527C810B9DA19005E1287 /* Device.cxx */; };
DCC527D110B9DA19005E1287 /* Device.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCC527C910B9DA19005E1287 /* Device.hxx */; };
DCC527D210B9DA19005E1287 /* M6502.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCC527CA10B9DA19005E1287 /* M6502.cxx */; };
DCC527D310B9DA19005E1287 /* M6502.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCC527CB10B9DA19005E1287 /* M6502.hxx */; };
@ -708,7 +707,6 @@
DCAD60A71152F8BD00BC4184 /* CartDPCPlus.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = CartDPCPlus.hxx; path = ../emucore/CartDPCPlus.hxx; sourceTree = SOURCE_ROOT; };
DCB9DA5E0FCD527000B192F6 /* GLShaderProgs.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = GLShaderProgs.hxx; path = ../common/GLShaderProgs.hxx; sourceTree = SOURCE_ROOT; };
DCBA710010DED62E0077193B /* Stella.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Stella.app; sourceTree = BUILT_PRODUCTS_DIR; };
DCC527C810B9DA19005E1287 /* Device.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Device.cxx; path = ../emucore/Device.cxx; sourceTree = SOURCE_ROOT; };
DCC527C910B9DA19005E1287 /* Device.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Device.hxx; path = ../emucore/Device.hxx; sourceTree = SOURCE_ROOT; };
DCC527CA10B9DA19005E1287 /* M6502.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = M6502.cxx; path = ../emucore/M6502.cxx; sourceTree = SOURCE_ROOT; };
DCC527CB10B9DA19005E1287 /* M6502.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = M6502.hxx; path = ../emucore/M6502.hxx; sourceTree = SOURCE_ROOT; };
@ -1038,7 +1036,6 @@
2DE2DF3A0627AE07006BEC99 /* Control.cxx */,
2DE2DF3B0627AE07006BEC99 /* Control.hxx */,
DC932D3F0F278A5200FEFEFC /* DefProps.hxx */,
DCC527C810B9DA19005E1287 /* Device.cxx */,
DCC527C910B9DA19005E1287 /* Device.hxx */,
2DE2DF3E0627AE07006BEC99 /* Driving.cxx */,
2DE2DF3F0627AE07006BEC99 /* Driving.hxx */,
@ -1704,7 +1701,6 @@
DCF467C40F939A1400B25D7A /* CartEFSC.cxx in Sources */,
DCF7B0DD10A762FC007A2870 /* CartF0.cxx in Sources */,
DCF7B0DF10A762FC007A2870 /* CartFA.cxx in Sources */,
DCC527D010B9DA19005E1287 /* Device.cxx in Sources */,
DCC527D210B9DA19005E1287 /* M6502.cxx in Sources */,
DCC527D410B9DA19005E1287 /* NullDev.cxx in Sources */,
DCC527D610B9DA19005E1287 /* System.cxx in Sources */,

View File

@ -256,7 +256,6 @@ SDLmain.lib
<ClCompile Include="..\emucore\CartX07.cxx" />
<ClCompile Include="..\emucore\Console.cxx" />
<ClCompile Include="..\emucore\Control.cxx" />
<ClCompile Include="..\emucore\Device.cxx" />
<ClCompile Include="..\emucore\Driving.cxx" />
<ClCompile Include="..\emucore\EventHandler.cxx" />
<ClCompile Include="..\emucore\FrameBuffer.cxx" />

View File

@ -186,9 +186,6 @@
<ClCompile Include="..\emucore\Control.cxx">
<Filter>Source Files\emucore</Filter>
</ClCompile>
<ClCompile Include="..\emucore\Device.cxx">
<Filter>Source Files\emucore</Filter>
</ClCompile>
<ClCompile Include="..\emucore\Driving.cxx">
<Filter>Source Files\emucore</Filter>
</ClCompile>

View File

@ -368,10 +368,6 @@
RelativePath="..\emucore\Control.cxx"
>
</File>
<File
RelativePath="..\emucore\Device.cxx"
>
</File>
<File
RelativePath="..\emucore\Driving.cxx"
>