mirror of https://github.com/stella-emu/stella.git
added command line options to include (coarse) ARM cycles into system cycles
This commit is contained in:
parent
c02fc531aa
commit
0c511805c7
|
@ -3541,6 +3541,16 @@
|
|||
fatal errors are simply logged, and emulation continues. Do not use this
|
||||
unless you know exactly what you're doing, as it changes the behaviour as
|
||||
compared to real hardware.</td>
|
||||
</tr><tr>
|
||||
<td><pre>-dev.thumb.incycles <1|0></pre></td>
|
||||
<td>When enabled, ARM emulation cycles are added to system cycles. This
|
||||
allows detecting timer overruns.</br>
|
||||
Note: The ARM emulation cycles are only a coarse approximation.
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><pre>-dev.thumb.cyclefactor <float></pre></td>
|
||||
<td>Adjust ARM emulation cycles by a factor (1.25 = default).
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td><pre>-<plr.|dev.>eepromaccess <1|0></pre></td>
|
||||
<td>When enabled, each read or write access to the AtariVox/SaveKey EEPROM is
|
||||
|
|
|
@ -72,9 +72,12 @@ CartridgeBUS::CartridgeBUS(const ByteBuffer& image, size_t size,
|
|||
0x00000808,
|
||||
0x40001FDC,
|
||||
devSettings ? settings.getBool("dev.thumb.trapfatal") : false,
|
||||
devSettings ? settings.getFloat("dev.thumb.cyclefactor") : 1.0,
|
||||
Thumbulator::ConfigureFor::BUS,
|
||||
this);
|
||||
|
||||
myIncCycles = devSettings ? settings.getBool("dev.thumb.inccycles") : false,
|
||||
|
||||
setInitialState();
|
||||
}
|
||||
|
||||
|
@ -167,10 +170,12 @@ inline void CartridgeBUS::callFunction(uInt8 value)
|
|||
// time for Stella as ARM code "runs in zero 6507 cycles".
|
||||
case 255: // call without IRQ driven audio
|
||||
try {
|
||||
Int32 cycles = Int32(mySystem->cycles() - myARMCycles);
|
||||
myARMCycles = mySystem->cycles();
|
||||
uInt32 cycles = uInt32(mySystem->cycles() - myARMCycles);
|
||||
|
||||
myARMCycles = mySystem->cycles();
|
||||
myThumbEmulator->run(cycles);
|
||||
if(myIncCycles)
|
||||
mySystem->incrementCycles(cycles);
|
||||
}
|
||||
catch(const runtime_error& e) {
|
||||
if(!mySystem->autodetectMode())
|
||||
|
|
|
@ -299,6 +299,9 @@ class CartridgeBUS : public Cartridge
|
|||
|
||||
uInt8 myFastJumpActive{false};
|
||||
|
||||
// ARM code increases 6507 cycles
|
||||
bool myIncCycles{false};
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
CartridgeBUS() = delete;
|
||||
|
|
|
@ -108,9 +108,12 @@ CartridgeCDF::CartridgeCDF(const ByteBuffer& image, size_t size,
|
|||
static_cast<uInt32>(mySize),
|
||||
cBase, cStart, cStack,
|
||||
devSettings ? settings.getBool("dev.thumb.trapfatal") : false,
|
||||
devSettings ? settings.getFloat("dev.thumb.cyclefactor") : 1.0,
|
||||
thumulatorConfiguration(myCDFSubtype),
|
||||
this);
|
||||
|
||||
myIncCycles = devSettings ? settings.getBool("dev.thumb.inccycles") : false,
|
||||
|
||||
setInitialState();
|
||||
}
|
||||
|
||||
|
@ -195,10 +198,12 @@ inline void CartridgeCDF::callFunction(uInt8 value)
|
|||
// time for Stella as ARM code "runs in zero 6507 cycles".
|
||||
case 255: // call without IRQ driven audio
|
||||
try {
|
||||
Int32 cycles = Int32(mySystem->cycles() - myARMCycles);
|
||||
myARMCycles = mySystem->cycles();
|
||||
uInt32 cycles = uInt32(mySystem->cycles() - myARMCycles);
|
||||
|
||||
myARMCycles = mySystem->cycles();
|
||||
myThumbEmulator->run(cycles);
|
||||
if(myIncCycles)
|
||||
mySystem->incrementCycles(cycles); // * ~1.79 is the limit for ZEVIOUZ title screen
|
||||
}
|
||||
catch(const runtime_error& e) {
|
||||
if(!mySystem->autodetectMode())
|
||||
|
|
|
@ -369,6 +369,9 @@ class CartridgeCDF : public Cartridge
|
|||
// CDF subtype
|
||||
CDFSubtype myCDFSubtype{CDFSubtype::CDF0};
|
||||
|
||||
// ARM code increases 6507 cycles
|
||||
bool myIncCycles{false};
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
CartridgeCDF() = delete;
|
||||
|
|
|
@ -58,6 +58,7 @@ CartridgeDPCPlus::CartridgeDPCPlus(const ByteBuffer& image, size_t size,
|
|||
0x00000C08,
|
||||
0x40001FDC,
|
||||
devSettings ? settings.getBool("dev.thumb.trapfatal") : false,
|
||||
devSettings ? settings.getFloat("dev.thumb.cyclefactor") : 1.0,
|
||||
Thumbulator::ConfigureFor::DPCplus,
|
||||
this);
|
||||
|
||||
|
@ -77,6 +78,8 @@ CartridgeDPCPlus::CartridgeDPCPlus(const ByteBuffer& image, size_t size,
|
|||
myDriverMD5 == "8dd73b44fd11c488326ce507cbeb19d1" )
|
||||
myFractionalLowMask = 0x0F0000;
|
||||
|
||||
myIncCycles = devSettings ? settings.getBool("dev.thumb.inccycles") : false,
|
||||
|
||||
setInitialState();
|
||||
}
|
||||
|
||||
|
@ -200,10 +203,12 @@ inline void CartridgeDPCPlus::callFunction(uInt8 value)
|
|||
// time for Stella as ARM code "runs in zero 6507 cycles".
|
||||
case 255: // call without IRQ driven audio
|
||||
try {
|
||||
Int32 cycles = Int32(mySystem->cycles() - myARMCycles);
|
||||
myARMCycles = mySystem->cycles();
|
||||
uInt32 cycles = uInt32(mySystem->cycles() - myARMCycles);
|
||||
|
||||
myARMCycles = mySystem->cycles();
|
||||
myThumbEmulator->run(cycles);
|
||||
if(myIncCycles)
|
||||
mySystem->incrementCycles(cycles);
|
||||
}
|
||||
catch(const runtime_error& e) {
|
||||
if(!mySystem->autodetectMode())
|
||||
|
|
|
@ -312,6 +312,9 @@ class CartridgeDPCPlus : public Cartridge
|
|||
// For current versions, this is 0x0F00FF; older versions need 0x0F0000
|
||||
uInt32 myFractionalLowMask{0x0F00FF};
|
||||
|
||||
// ARM code increases 6507 cycles
|
||||
bool myIncCycles{false};
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
CartridgeDPCPlus() = delete;
|
||||
|
|
|
@ -242,10 +242,12 @@ Settings::Settings()
|
|||
setPermanent("dev.tm.uncompressed", 600);
|
||||
setPermanent("dev.tm.interval", "1f"); // = 1 frame
|
||||
setPermanent("dev.tm.horizon", "30s"); // = ~30 seconds
|
||||
// Thumb ARM emulation options
|
||||
setPermanent("dev.thumb.trapfatal", "true");
|
||||
setPermanent("dev.detectedinfo", "true");
|
||||
setPermanent("dev.eepromaccess", "true");
|
||||
// Thumb ARM emulation options
|
||||
setPermanent("dev.thumb.trapfatal", "true");
|
||||
setPermanent("dev.thumb.inccycles", "true");
|
||||
setPermanent("dev.thumb.cyclefactor", "1.25");
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -683,6 +685,8 @@ void Settings::usage() const
|
|||
#endif
|
||||
<< " -dev.thumb.trapfatal <1|0> Determines whether errors in ARM emulation\n"
|
||||
<< " throw an exception\n"
|
||||
<< " -dev.thumb.inccycles <1|0> Determines whether ARM emulation cycles\n"
|
||||
<< " increase system cycles\n"
|
||||
<< " -dev.eepromaccess <1|0> Enable messages for AtariVox/SaveKey access\n"
|
||||
<< " messages\n"
|
||||
<< " -dev.tia.type <standard|custom| Selects a TIA type\n"
|
||||
|
|
|
@ -52,10 +52,13 @@ using Common::Base;
|
|||
#define CONV_RAMROM(d) (d)
|
||||
#endif
|
||||
|
||||
#define CYCLE_FACTOR 1.25 // coarse ARM cycle multiplier
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Thumbulator::Thumbulator(const uInt16* rom_ptr, uInt16* ram_ptr, uInt32 rom_size,
|
||||
const uInt32 c_base, const uInt32 c_start, const uInt32 c_stack,
|
||||
bool traponfatal, Thumbulator::ConfigureFor configurefor,
|
||||
bool traponfatal, double cyclefactor,
|
||||
Thumbulator::ConfigureFor configurefor,
|
||||
Cartridge* cartridge)
|
||||
: rom{rom_ptr},
|
||||
romSize{rom_size},
|
||||
|
@ -73,12 +76,15 @@ Thumbulator::Thumbulator(const uInt16* rom_ptr, uInt16* ram_ptr, uInt32 rom_size
|
|||
setConsoleTiming(ConsoleTiming::ntsc);
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
trapFatalErrors(traponfatal);
|
||||
#endif
|
||||
#ifndef NO_THUMB_STATS
|
||||
cycleFactor(cyclefactor);
|
||||
#endif
|
||||
reset();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string Thumbulator::run()
|
||||
string Thumbulator::doRun(uInt32& cycles)
|
||||
{
|
||||
reset();
|
||||
for(;;)
|
||||
|
@ -89,6 +95,11 @@ string Thumbulator::run()
|
|||
throw runtime_error("instructions > 500000");
|
||||
#endif
|
||||
}
|
||||
#ifndef NO_THUMB_STATS
|
||||
cycles = uInt32((_stats.fetches + _stats.reads + _stats.writes) * arm_cycle_factor / timing_factor);
|
||||
#else
|
||||
cycles = 0;
|
||||
#endif
|
||||
#if defined(THUMB_DISS) || defined(THUMB_DBUG)
|
||||
dump_counters();
|
||||
cout << statusMsg.str() << endl;
|
||||
|
@ -119,15 +130,19 @@ void Thumbulator::setConsoleTiming(ConsoleTiming timing)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Thumbulator::updateTimer(uInt32 cycles)
|
||||
{
|
||||
#ifdef TIMER_0
|
||||
if(T0TCR & 1) // bit 0 controls timer on/off
|
||||
T0TC += uInt32(cycles * timing_factor);
|
||||
#endif
|
||||
if (T1TCR & 1) // bit 0 controls timer on/off
|
||||
T1TC += uInt32(cycles * timing_factor);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string Thumbulator::run(uInt32 cycles)
|
||||
string Thumbulator::run(uInt32& cycles)
|
||||
{
|
||||
updateTimer(cycles);
|
||||
return run();
|
||||
return doRun(cycles);
|
||||
}
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
|
@ -289,7 +304,15 @@ void Thumbulator::write32(uInt32 addr, uInt32 data)
|
|||
DO_DISS(statusMsg << "uart: [" << char(data&0xFF) << "]" << endl);
|
||||
break;
|
||||
#endif
|
||||
#ifdef TIMER_0
|
||||
case 0xE0004004: // T0TCR - Timer 0 Control Register
|
||||
T0TCR = data;
|
||||
break;
|
||||
|
||||
case 0xE0004008: // T0TC - Timer 0 Counter
|
||||
T0TC = data;
|
||||
break;
|
||||
#endif
|
||||
case 0xE0008004: // T1TCR - Timer 1 Control Register
|
||||
T1TCR = data;
|
||||
break;
|
||||
|
@ -467,6 +490,15 @@ uInt32 Thumbulator::read32(uInt32 addr)
|
|||
{
|
||||
switch(addr)
|
||||
{
|
||||
#ifdef TIMER_0
|
||||
case 0xE0004004: // T0TCR - Timer 0 Control Register
|
||||
data = T0TCR;
|
||||
return data;
|
||||
|
||||
case 0xE0004008: // T0TC - Timer 0 Counter
|
||||
data = T0TC;
|
||||
break;
|
||||
#endif
|
||||
case 0xE0008004: // T1TCR - Timer 1 Control Register
|
||||
data = T1TCR;
|
||||
return data;
|
||||
|
@ -2560,4 +2592,5 @@ int Thumbulator::reset()
|
|||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Thumbulator::trapOnFatal = true;
|
||||
double Thumbulator::arm_cycle_factor = 1.25;
|
||||
#endif
|
||||
|
|
|
@ -46,6 +46,8 @@ class Cartridge;
|
|||
#define CPSR_C (1u<<29)
|
||||
#define CPSR_V (1u<<28)
|
||||
|
||||
//#define TIMER_0 // enable timer 0 support
|
||||
|
||||
class Thumbulator
|
||||
{
|
||||
public:
|
||||
|
@ -68,7 +70,8 @@ class Thumbulator
|
|||
|
||||
Thumbulator(const uInt16* rom_ptr, uInt16* ram_ptr, uInt32 rom_size,
|
||||
const uInt32 c_base, const uInt32 c_start, const uInt32 c_stack,
|
||||
bool traponfatal, Thumbulator::ConfigureFor configurefor,
|
||||
bool traponfatal, double cyclefactor,
|
||||
Thumbulator::ConfigureFor configurefor,
|
||||
Cartridge* cartridge);
|
||||
|
||||
/**
|
||||
|
@ -79,8 +82,8 @@ class Thumbulator
|
|||
@return The results of any debugging output (if enabled),
|
||||
otherwise an empty string
|
||||
*/
|
||||
string run();
|
||||
string run(uInt32 cycles);
|
||||
string doRun(uInt32& cycles);
|
||||
string run(uInt32& cycles);
|
||||
const Stats& stats() const { return _stats; }
|
||||
const Stats& prevStats() const { return _prevStats; }
|
||||
|
||||
|
@ -99,6 +102,9 @@ class Thumbulator
|
|||
*/
|
||||
static void trapFatalErrors(bool enable) { trapOnFatal = enable; }
|
||||
#endif
|
||||
#ifndef NO_THUMB_STATS
|
||||
static void cycleFactor(double factor) { arm_cycle_factor = factor; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
Inform the Thumbulator class about the console currently in use,
|
||||
|
@ -215,6 +221,10 @@ class Thumbulator
|
|||
// For emulation of LPC2103's timer 1, used for NTSC/PAL/SECAM detection.
|
||||
// Register names from documentation:
|
||||
// http://www.nxp.com/documents/user_manual/UM10161.pdf
|
||||
#ifdef TIMER_0
|
||||
uInt32 T0TCR{0}; // Timer 0 Timer Control Register
|
||||
uInt32 T0TC{0}; // Timer 0 Timer Counter
|
||||
#endif
|
||||
uInt32 T1TCR{0}; // Timer 1 Timer Control Register
|
||||
uInt32 T1TC{0}; // Timer 1 Timer Counter
|
||||
double timing_factor{0.0};
|
||||
|
@ -224,6 +234,9 @@ class Thumbulator
|
|||
|
||||
static bool trapOnFatal;
|
||||
#endif
|
||||
#ifndef NO_THUMB_STATS
|
||||
static double arm_cycle_factor;
|
||||
#endif
|
||||
|
||||
ConfigureFor configuration;
|
||||
|
||||
|
|
Loading…
Reference in New Issue