mirror of https://github.com/stella-emu/stella.git
Reverted TIA changes that affect late NUSIZx changes. More work is needed
in this area. Added commandline argument 'thumb.trapfatal', which causes fatal errors in the Thumb ARM emulation to really be treated as fatal (ie, the emulation stops and throws an exception). This is enabled by default (as it always should be). When disabled, fatal errors simply log the error and continue with emulation. This was added because the current HarmonyCart ARM code isn't always exactly compatible with the emulation in Stella, and there is a lagtime from when Harmony implements something to when the same functionality is added to Stella. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2279 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
1d5ea6a9eb
commit
bb63ea3dd1
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include <cstdlib>
|
||||
|
||||
#define STELLA_VERSION "3.5_svn_test1"
|
||||
#define STELLA_VERSION "3.5_svn_test2"
|
||||
#define STELLA_BUILD atoi("$Rev$" + 6)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -68,7 +68,8 @@ CartridgeDPCPlus::CartridgeDPCPlus(const uInt8* image, uInt32 size,
|
|||
#ifdef THUMB_SUPPORT
|
||||
// Create Thumbulator ARM emulator
|
||||
myThumbEmulator = new Thumbulator((uInt16*)(myProgramImage-0xC00),
|
||||
(uInt16*)myDPCRAM);
|
||||
(uInt16*)myDPCRAM,
|
||||
settings.getBool("thumb.trapfatal"));
|
||||
#endif
|
||||
|
||||
// Copy DPC display data to Harmony RAM
|
||||
|
|
|
@ -137,6 +137,9 @@ Settings::Settings(OSystem* osystem)
|
|||
setInternal("resolvedata", "auto");
|
||||
setInternal("gfxformat", "2");
|
||||
setInternal("showaddr", "true");
|
||||
|
||||
// Thumb ARM emulation options
|
||||
setInternal("thumb.trapfatal", "true");
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -620,8 +620,8 @@ const Int16 TIATables::PokeDelay[64] = {
|
|||
1, // VBLANK (0) / 1
|
||||
0, // WSYNC
|
||||
0, // RSYNC
|
||||
0, // NUSIZ0 (0) / 8 TODO - calculate this instead of hardcoding
|
||||
0, // NUSIZ1 (0) / 8 TODO - calculate this instead of hardcoding
|
||||
8, // NUSIZ0 (0) / 8 TODO - calculate this instead of hardcoding
|
||||
8, // NUSIZ1 (0) / 8 TODO - calculate this instead of hardcoding
|
||||
0, // COLUP0
|
||||
0, // COLUP1
|
||||
0, // COLUPF
|
||||
|
|
|
@ -31,13 +31,14 @@
|
|||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Thumbulator::Thumbulator(uInt16* rom_ptr, uInt16* ram_ptr)
|
||||
Thumbulator::Thumbulator(uInt16* rom_ptr, uInt16* ram_ptr, bool traponfatal)
|
||||
: rom(rom_ptr),
|
||||
ram(ram_ptr),
|
||||
copydata(0),
|
||||
DBUG(0), // dump detailed execution trace
|
||||
DISS(0) // dump Thumb instruction trace
|
||||
{
|
||||
trapFatalErrors(traponfatal);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -74,7 +75,9 @@ inline int Thumbulator::fatalError(const char* opcode, uInt32 v1, const char* ms
|
|||
statusMsg << "Thumb ARM emulation fatal error: " << endl
|
||||
<< opcode << "(" << HEX8 << v1 << "), " << msg << endl;
|
||||
dump_regs();
|
||||
throw statusMsg.str();
|
||||
if(trapOnFatal)
|
||||
throw statusMsg.str();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -84,7 +87,9 @@ inline int Thumbulator::fatalError(const char* opcode, uInt32 v1, uInt32 v2,
|
|||
statusMsg << "Thumb ARM emulation fatal error: " << endl
|
||||
<< opcode << "(" << HEX8 << v1 << "," << v2 << "), " << msg << endl;
|
||||
dump_regs();
|
||||
throw statusMsg.str();
|
||||
if(trapOnFatal)
|
||||
throw statusMsg.str();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -116,13 +121,9 @@ void Thumbulator::dump_regs( void )
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 Thumbulator::fetch16 ( uInt32 addr )
|
||||
{
|
||||
uInt32 data;
|
||||
|
||||
fetches++;
|
||||
|
||||
if(DBUG)
|
||||
statusMsg << "fetch16(" << HEX8 << addr << ")=";
|
||||
|
||||
uInt32 data;
|
||||
switch(addr&0xF0000000)
|
||||
{
|
||||
case 0x00000000: //ROM
|
||||
|
@ -137,7 +138,7 @@ uInt32 Thumbulator::fetch16 ( uInt32 addr )
|
|||
data=rom[addr];
|
||||
#endif
|
||||
if(DBUG)
|
||||
statusMsg << HEX4 << data << endl;
|
||||
statusMsg << "fetch16(" << HEX8 << addr << ")=" << HEX4 << data << endl;
|
||||
return(data);
|
||||
|
||||
case 0x40000000: //RAM
|
||||
|
@ -149,7 +150,7 @@ uInt32 Thumbulator::fetch16 ( uInt32 addr )
|
|||
data=ram[addr];
|
||||
#endif
|
||||
if(DBUG)
|
||||
statusMsg << HEX4 << data << endl;
|
||||
statusMsg << "fetch16(" << HEX8 << addr << ")=" << HEX4 << data << endl;
|
||||
return(data);
|
||||
}
|
||||
return fatalError("fetch16", addr, "abort");
|
||||
|
@ -159,10 +160,6 @@ uInt32 Thumbulator::fetch16 ( uInt32 addr )
|
|||
uInt32 Thumbulator::fetch32 ( uInt32 addr )
|
||||
{
|
||||
uInt32 data;
|
||||
|
||||
if(DBUG)
|
||||
statusMsg << "fetch32(" << HEX8 << addr << ")=";
|
||||
|
||||
switch(addr&0xF0000000)
|
||||
{
|
||||
case 0x00000000: //ROM
|
||||
|
@ -170,7 +167,7 @@ uInt32 Thumbulator::fetch32 ( uInt32 addr )
|
|||
{
|
||||
data=read32(addr);
|
||||
if(DBUG)
|
||||
statusMsg << HEX8 << data << endl;
|
||||
statusMsg << "fetch32(" << HEX8 << addr << ")=" << HEX8 << data << endl;
|
||||
if(addr==0x00000000) return(data);
|
||||
if(addr==0x00000004) return(data);
|
||||
fatalError("fetch32", addr, "abort");
|
||||
|
@ -181,7 +178,7 @@ uInt32 Thumbulator::fetch32 ( uInt32 addr )
|
|||
data<<=16;
|
||||
data|=fetch16(addr+0);
|
||||
if(DBUG)
|
||||
statusMsg << HEX8 << data << endl;;
|
||||
statusMsg << "fetch32(" << HEX8 << addr << ")=" << HEX8 << data << endl;;
|
||||
return(data);
|
||||
}
|
||||
return fatalError("fetch32", addr, "abort");
|
||||
|
@ -217,6 +214,8 @@ void Thumbulator::write16 ( uInt32 addr, uInt32 data )
|
|||
case 0xE0000000: //MAMCR
|
||||
if(addr == 0xE01FC000)
|
||||
{
|
||||
if(DBUG)
|
||||
statusMsg << "write16(" << HEX8 << "MAMCR" << "," << HEX8 << data << ") *" << endl;
|
||||
mamcr = data;
|
||||
return;
|
||||
}
|
||||
|
@ -277,9 +276,6 @@ uInt32 Thumbulator::read16 ( uInt32 addr )
|
|||
|
||||
reads++;
|
||||
|
||||
if(DBUG)
|
||||
statusMsg << "read16(" << HEX8 << addr << ")=";
|
||||
|
||||
switch(addr&0xF0000000)
|
||||
{
|
||||
case 0x00000000: //ROM
|
||||
|
@ -291,7 +287,7 @@ uInt32 Thumbulator::read16 ( uInt32 addr )
|
|||
data=rom[addr];
|
||||
#endif
|
||||
if(DBUG)
|
||||
statusMsg << HEX4 << data << endl;
|
||||
statusMsg << "read16(" << HEX8 << addr << ")=" << HEX4 << data << endl;
|
||||
return(data);
|
||||
|
||||
case 0x40000000: //RAM
|
||||
|
@ -303,12 +299,16 @@ uInt32 Thumbulator::read16 ( uInt32 addr )
|
|||
data=ram[addr];
|
||||
#endif
|
||||
if(DBUG)
|
||||
statusMsg << HEX4 << data << endl;
|
||||
statusMsg << "read16(" << HEX8 << addr << ")=" << HEX4 << data << endl;
|
||||
return(data);
|
||||
|
||||
case 0xE0000000: //MAMCR
|
||||
if(addr == 0xE01FC000)
|
||||
{
|
||||
if(DBUG)
|
||||
statusMsg << "read16(" << "MAMCR" << addr << ")=" << mamcr << " *";
|
||||
return mamcr;
|
||||
}
|
||||
}
|
||||
return fatalError("read16", addr, "abort");
|
||||
}
|
||||
|
@ -319,9 +319,6 @@ uInt32 Thumbulator::read32 ( uInt32 addr )
|
|||
if(addr&3)
|
||||
fatalError("read32", addr, "abort - misaligned");
|
||||
|
||||
if(DBUG)
|
||||
statusMsg << "read32(" << HEX8 << addr << ")=";
|
||||
|
||||
uInt32 data;
|
||||
switch(addr&0xF0000000)
|
||||
{
|
||||
|
@ -331,7 +328,7 @@ uInt32 Thumbulator::read32 ( uInt32 addr )
|
|||
data<<=16;
|
||||
data|=read16(addr+0);
|
||||
if(DBUG)
|
||||
statusMsg << HEX8 << data << endl;
|
||||
statusMsg << "read32(" << HEX8 << addr << ")=" << HEX8 << data << endl;
|
||||
return(data);
|
||||
}
|
||||
return fatalError("read32", addr, "abort");
|
||||
|
@ -340,12 +337,9 @@ uInt32 Thumbulator::read32 ( uInt32 addr )
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 Thumbulator::read_register ( uInt32 reg )
|
||||
{
|
||||
uInt32 data;
|
||||
|
||||
reg&=0xF;
|
||||
if(DBUG)
|
||||
statusMsg << "read_register(" << dec << reg << ")=";
|
||||
|
||||
uInt32 data;
|
||||
switch(cpsr&0x1F)
|
||||
{
|
||||
case MODE_SVC:
|
||||
|
@ -355,7 +349,7 @@ uInt32 Thumbulator::read_register ( uInt32 reg )
|
|||
case 13: case 14: data=reg_svc[reg]; break;
|
||||
}
|
||||
if(DBUG)
|
||||
statusMsg << HEX8 << data << endl;
|
||||
statusMsg << "read_register(" << dec << reg << ")=" << HEX8 << data << endl;
|
||||
return(data);
|
||||
}
|
||||
return fatalError("read_register", cpsr, "invalid cpsr mode");
|
||||
|
@ -369,7 +363,6 @@ uInt32 Thumbulator::write_register ( uInt32 reg, uInt32 data )
|
|||
if(DBUG)
|
||||
statusMsg << "write_register(" << dec << reg << ","
|
||||
<< HEX8 << data << ")" << endl;
|
||||
|
||||
switch(cpsr&0x1F)
|
||||
{
|
||||
case MODE_SVC:
|
||||
|
@ -2096,4 +2089,7 @@ int Thumbulator::reset ( void )
|
|||
return(0);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Thumbulator::trapOnFatal = true;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -62,19 +62,33 @@
|
|||
class Thumbulator
|
||||
{
|
||||
public:
|
||||
Thumbulator(uInt16* rom, uInt16* ram);
|
||||
Thumbulator(uInt16* rom, uInt16* ram, bool traponfatal);
|
||||
~Thumbulator();
|
||||
|
||||
/**
|
||||
Run the ARM code, and return when finished. A string 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.
|
||||
thrown in case of any fatal errors/aborts (if enabled), 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();
|
||||
|
||||
/**
|
||||
Normally when a fatal error is encountered, the ARM emulation
|
||||
immediately throws an exception and exits. This method allows execution
|
||||
to continue, and simply log the error.
|
||||
|
||||
Note that this is meant for developers only, and should normally be
|
||||
always enabled. It can be used to temporarily ignore illegal reads
|
||||
and writes, but a ROM which consistently performs these operations
|
||||
should be fixed, as it can cause crashes on real hardware.
|
||||
|
||||
@param enable Enable (the default) or disable exceptions on fatal errors
|
||||
*/
|
||||
static void trapFatalErrors(bool enable) { trapOnFatal = enable; }
|
||||
|
||||
private:
|
||||
uInt32 read_register ( uInt32 reg );
|
||||
uInt32 write_register ( uInt32 reg, uInt32 data );
|
||||
|
@ -128,6 +142,8 @@ class Thumbulator
|
|||
Int32 DBUG; // dump detailed execution trace
|
||||
Int32 DISS; // dump Thumb instruction trace
|
||||
ostringstream statusMsg;
|
||||
|
||||
static bool trapOnFatal;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue