mirror of https://github.com/stella-emu/stella.git
Refactor System::myCycles to be 64-bit instead of 32-bit.
- The cycles counter is now essentially monotonically increasing (ie, we never need to worry about it going backwards and giving a negative difference, simplifying a lot of code - There are now reset() methods in all places that keep track of system cycles, but they are used for a full reset only; not called each frame like before (which had to be done to prevent overflow).
This commit is contained in:
parent
fc104c3b4a
commit
ebb8725126
|
@ -56,14 +56,6 @@ class SoundNull : public Sound
|
|||
*/
|
||||
void setEnabled(bool enable) override { }
|
||||
|
||||
/**
|
||||
The system cycle counter is being adjusting by the specified amount. Any
|
||||
members using the system cycle counter should be adjusted as needed.
|
||||
|
||||
@param amount The amount the cycle counter is being adjusted by
|
||||
*/
|
||||
void adjustCycleCounter(Int32 amount) override { }
|
||||
|
||||
/**
|
||||
Sets the number of channels (mono or stereo sound).
|
||||
|
||||
|
@ -110,7 +102,7 @@ class SoundNull : public Sound
|
|||
@param value The value to save into the register
|
||||
@param cycle The system cycle at which the register is being updated
|
||||
*/
|
||||
void set(uInt16 addr, uInt8 value, Int32 cycle) override { }
|
||||
void set(uInt16 addr, uInt8 value, uInt64 cycle) override { }
|
||||
|
||||
/**
|
||||
Sets the volume of the sound device to the specified level. The
|
||||
|
|
|
@ -226,12 +226,6 @@ void SoundSDL2::adjustVolume(Int8 direction)
|
|||
myOSystem.frameBuffer().showMessage(message);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL2::adjustCycleCounter(Int32 amount)
|
||||
{
|
||||
myLastRegisterSetCycle += amount;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL2::setChannels(uInt32 channels)
|
||||
{
|
||||
|
@ -249,7 +243,7 @@ void SoundSDL2::setFrameRate(float framerate)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL2::set(uInt16 addr, uInt8 value, Int32 cycle)
|
||||
void SoundSDL2::set(uInt16 addr, uInt8 value, uInt64 cycle)
|
||||
{
|
||||
SDL_LockAudio();
|
||||
|
||||
|
@ -386,7 +380,7 @@ bool SoundSDL2::save(Serializer& out) const
|
|||
for(int i = 0; i < 6; ++i)
|
||||
out.putByte(0);
|
||||
|
||||
out.putInt(myLastRegisterSetCycle);
|
||||
out.putLong(myLastRegisterSetCycle);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -423,7 +417,7 @@ bool SoundSDL2::load(Serializer& in)
|
|||
for(int i = 0; i < 6; ++i)
|
||||
in.getByte();
|
||||
|
||||
myLastRegisterSetCycle = in.getInt();
|
||||
myLastRegisterSetCycle = in.getLong();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
|
|
@ -55,14 +55,6 @@ class SoundSDL2 : public Sound
|
|||
*/
|
||||
void setEnabled(bool state) override;
|
||||
|
||||
/**
|
||||
The system cycle counter is being adjusting by the specified amount. Any
|
||||
members using the system cycle counter should be adjusted as needed.
|
||||
|
||||
@param amount The amount the cycle counter is being adjusted by
|
||||
*/
|
||||
void adjustCycleCounter(Int32 amount) override;
|
||||
|
||||
/**
|
||||
Sets the number of channels (mono or stereo sound). Note that this
|
||||
determines how the emulation should 'mix' the channels of the TIA sound
|
||||
|
@ -113,7 +105,7 @@ class SoundSDL2 : public Sound
|
|||
@param value The value to save into the register
|
||||
@param cycle The system cycle at which the register is being updated
|
||||
*/
|
||||
void set(uInt16 addr, uInt8 value, Int32 cycle) override;
|
||||
void set(uInt16 addr, uInt8 value, uInt64 cycle) override;
|
||||
|
||||
/**
|
||||
Sets the volume of the sound device to the specified level. The
|
||||
|
@ -258,7 +250,7 @@ class SoundSDL2 : public Sound
|
|||
bool myIsInitializedFlag;
|
||||
|
||||
// Indicates the cycle when a sound register was last set
|
||||
Int32 myLastRegisterSetCycle;
|
||||
uInt64 myLastRegisterSetCycle;
|
||||
|
||||
// Indicates the number of channels (mono or stereo)
|
||||
uInt32 myNumChannels;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
#include "StateManager.hxx"
|
||||
|
||||
#define STATE_HEADER "05000300state"
|
||||
#define STATE_HEADER "05000301state"
|
||||
#define MOVIE_HEADER "03030000movie"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -99,6 +99,7 @@ static const char* const pseudo_registers[][2] = {
|
|||
{ "_rwport", "Address at which a read from a write port occurred" },
|
||||
{ "_scan", "Current scanline count" },
|
||||
{ "_fcount", "Number of frames since emulation started" },
|
||||
//FIXME { "_fcycles", "Number of cycles since frame started" },
|
||||
{ "_cclocks", "Color clocks on current scanline" },
|
||||
{ "_vsync", "Whether vertical sync is enabled (1 or 0)" },
|
||||
{ "_vblank", "Whether vertical blank is enabled (1 or 0)" },
|
||||
|
@ -302,13 +303,13 @@ int Debugger::step()
|
|||
saveOldState();
|
||||
mySystem.clearDirtyPages();
|
||||
|
||||
int cyc = mySystem.cycles();
|
||||
uInt64 startCycle = mySystem.cycles();
|
||||
|
||||
unlockBankswitchState();
|
||||
myOSystem.console().tia().updateScanlineByStep().flushLineCache();
|
||||
lockBankswitchState();
|
||||
|
||||
return mySystem.cycles() - cyc;
|
||||
return int(mySystem.cycles() - startCycle);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -330,14 +331,14 @@ int Debugger::trace()
|
|||
saveOldState();
|
||||
mySystem.clearDirtyPages();
|
||||
|
||||
int cyc = mySystem.cycles();
|
||||
uInt64 startCycle = mySystem.cycles();
|
||||
int targetPC = myCpuDebug->pc() + 3; // return address
|
||||
|
||||
unlockBankswitchState();
|
||||
myOSystem.console().tia().updateScanlineByTrace(targetPC).flushLineCache();
|
||||
lockBankswitchState();
|
||||
|
||||
return mySystem.cycles() - cyc;
|
||||
return int(mySystem.cycles() - startCycle);
|
||||
}
|
||||
else
|
||||
return step();
|
||||
|
|
|
@ -153,11 +153,6 @@ class Debugger : public DialogContainer
|
|||
*/
|
||||
const string run(const string& command);
|
||||
|
||||
/**
|
||||
The current cycle count of the System.
|
||||
*/
|
||||
int cycles() const { return int(mySystem.cycles()); }
|
||||
|
||||
string autoExec();
|
||||
|
||||
string showWatches();
|
||||
|
|
|
@ -694,6 +694,12 @@ int TIADebug::frameCount() const
|
|||
return myTIA.myFrameManager.frameCount();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int TIADebug::frameCycles() const
|
||||
{
|
||||
return myTIA.frameCycles();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int TIADebug::scanlines() const
|
||||
{
|
||||
|
|
|
@ -159,6 +159,7 @@ class TIADebug : public DebuggerSystem
|
|||
int scanlines() const;
|
||||
int scanlinesLastFrame() const;
|
||||
int frameCount() const;
|
||||
int frameCycles() const;
|
||||
int clocksThisLine() const;
|
||||
bool vsync() const;
|
||||
bool vblank() const;
|
||||
|
|
|
@ -129,7 +129,7 @@ void TiaInfoWidget::loadConfig()
|
|||
TIADebug& tia = dbg.tiaDebug();
|
||||
|
||||
myFrameCount->setText(Common::Base::toString(tia.frameCount(), Common::Base::F_10));
|
||||
myFrameCycles->setText(Common::Base::toString(dbg.cycles(), Common::Base::F_10));
|
||||
myFrameCycles->setText(Common::Base::toString(tia.frameCycles(), Common::Base::F_10));
|
||||
|
||||
myVSync->setState(tia.vsync());
|
||||
myVBlank->setState(tia.vblank());
|
||||
|
|
|
@ -99,13 +99,12 @@ void AtariVox::write(DigitalPin pin, bool value)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void AtariVox::clockDataIn(bool value)
|
||||
{
|
||||
uInt32 cycle = mySystem.cycles();
|
||||
|
||||
if(value && (myShiftCount == 0))
|
||||
return;
|
||||
|
||||
// If this is the first write this frame, or if it's been a long time
|
||||
// since the last write, start a new data byte.
|
||||
uInt64 cycle = mySystem.cycles();
|
||||
if((cycle < myLastDataWriteCycle) || (cycle > myLastDataWriteCycle + 1000))
|
||||
{
|
||||
myShiftRegister = 0;
|
||||
|
@ -138,6 +137,13 @@ void AtariVox::clockDataIn(bool value)
|
|||
myLastDataWriteCycle = cycle;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void AtariVox::reset()
|
||||
{
|
||||
myLastDataWriteCycle = mySystem.cycles();
|
||||
myEEPROM->systemReset();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void AtariVox::close()
|
||||
{
|
||||
|
@ -145,16 +151,6 @@ void AtariVox::close()
|
|||
myEEPROM.reset();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void AtariVox::systemCyclesReset()
|
||||
{
|
||||
myLastDataWriteCycle -= mySystem.cycles();
|
||||
|
||||
// The EEPROM keeps track of cycle counts, and needs to know when the
|
||||
// cycles are reset
|
||||
myEEPROM->systemCyclesReset();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string AtariVox::about() const
|
||||
{
|
||||
|
|
|
@ -79,6 +79,13 @@ class AtariVox : public Controller
|
|||
*/
|
||||
void update() override { }
|
||||
|
||||
/**
|
||||
Notification method invoked by the system after its reset method has
|
||||
been called. It may be necessary to override this method for
|
||||
controllers that need to know a reset has occurred.
|
||||
*/
|
||||
void reset() override;
|
||||
|
||||
/**
|
||||
Notification method invoked by the system indicating that the
|
||||
console is about to be destroyed. It may be necessary to override
|
||||
|
@ -86,13 +93,6 @@ class AtariVox : public Controller
|
|||
*/
|
||||
void close() override;
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
void systemCyclesReset() override;
|
||||
|
||||
string about() const override;
|
||||
|
||||
private:
|
||||
|
@ -121,7 +121,7 @@ class AtariVox : public Controller
|
|||
// The real SpeakJet chip reads data at 19200 bits/sec. Alex's
|
||||
// driver code sends data at 62 CPU cycles per bit, which is
|
||||
// "close enough".
|
||||
uInt32 myLastDataWriteCycle;
|
||||
uInt64 myLastDataWriteCycle;
|
||||
|
||||
// Holds information concerning serial port usage
|
||||
string myAboutString;
|
||||
|
|
|
@ -26,7 +26,6 @@ CartridgeAR::CartridgeAR(const BytePtr& image, uInt32 size,
|
|||
mySize(std::max(size, 8448u)),
|
||||
myWriteEnabled(false),
|
||||
myPower(true),
|
||||
myPowerRomCycle(0),
|
||||
myDataHoldRegister(0),
|
||||
myNumberOfDistinctAccesses(0),
|
||||
myWritePending(false),
|
||||
|
@ -64,7 +63,6 @@ void CartridgeAR::reset()
|
|||
|
||||
myWriteEnabled = false;
|
||||
myPower = true;
|
||||
myPowerRomCycle = mySystem->cycles();
|
||||
|
||||
myDataHoldRegister = 0;
|
||||
myNumberOfDistinctAccesses = 0;
|
||||
|
@ -74,13 +72,6 @@ void CartridgeAR::reset()
|
|||
bankConfiguration(0);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeAR::systemCyclesReset()
|
||||
{
|
||||
// Adjust cycle values
|
||||
myPowerRomCycle -= mySystem->cycles();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeAR::install(System& system)
|
||||
{
|
||||
|
@ -243,11 +234,6 @@ bool CartridgeAR::bankConfiguration(uInt8 configuration)
|
|||
// Handle ROM power configuration
|
||||
myPower = !(configuration & 0x01);
|
||||
|
||||
if(myPower)
|
||||
{
|
||||
myPowerRomCycle = mySystem->cycles();
|
||||
}
|
||||
|
||||
myWriteEnabled = configuration & 0x02;
|
||||
|
||||
switch((configuration >> 2) & 0x07)
|
||||
|
@ -474,9 +460,6 @@ bool CartridgeAR::save(Serializer& out) const
|
|||
// Indicates if the ROM's power is on or off
|
||||
out.putBool(myPower);
|
||||
|
||||
// Indicates when the power was last turned on
|
||||
out.putInt(myPowerRomCycle);
|
||||
|
||||
// Data hold register used for writing
|
||||
out.putByte(myDataHoldRegister);
|
||||
|
||||
|
@ -525,9 +508,6 @@ bool CartridgeAR::load(Serializer& in)
|
|||
// Indicates if the ROM's power is on or off
|
||||
myPower = in.getBool();
|
||||
|
||||
// Indicates when the power was last turned on
|
||||
myPowerRomCycle = in.getInt();
|
||||
|
||||
// Data hold register used for writing
|
||||
myDataHoldRegister = in.getByte();
|
||||
|
||||
|
|
|
@ -60,13 +60,6 @@ class CartridgeAR : public Cartridge
|
|||
*/
|
||||
void reset() override;
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
void systemCyclesReset() override;
|
||||
|
||||
/**
|
||||
Install cartridge in the specified system. Invoked by the system
|
||||
when the cartridge is attached to it.
|
||||
|
@ -208,9 +201,6 @@ class CartridgeAR : public Cartridge
|
|||
// Indicates if the ROM's power is on or off
|
||||
bool myPower;
|
||||
|
||||
// Indicates when the power was last turned on
|
||||
Int32 myPowerRomCycle;
|
||||
|
||||
// Data hold register used for writing
|
||||
uInt8 myDataHoldRegister;
|
||||
|
||||
|
|
|
@ -112,14 +112,6 @@ void CartridgeBUS::consoleChanged(ConsoleTiming timing)
|
|||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeBUS::systemCyclesReset()
|
||||
{
|
||||
// Adjust the cycle counter so that it reflects the new value
|
||||
mySystemCycles -= mySystem->cycles();
|
||||
myARMCycles -= mySystem->cycles();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeBUS::install(System& system)
|
||||
{
|
||||
|
@ -143,7 +135,7 @@ void CartridgeBUS::install(System& system)
|
|||
inline void CartridgeBUS::updateMusicModeDataFetchers()
|
||||
{
|
||||
// Calculate the number of cycles since the last update
|
||||
Int32 cycles = mySystem->cycles() - mySystemCycles;
|
||||
Int32 cycles = Int32(mySystem->cycles() - mySystemCycles);
|
||||
mySystemCycles = mySystem->cycles();
|
||||
|
||||
// Calculate the number of BUS OSC clocks since the last update
|
||||
|
@ -170,7 +162,7 @@ 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 = mySystem->cycles() - myARMCycles;
|
||||
Int32 cycles = Int32(mySystem->cycles() - myARMCycles);
|
||||
myARMCycles = mySystem->cycles();
|
||||
|
||||
myThumbEmulator->run(cycles);
|
||||
|
@ -570,9 +562,9 @@ bool CartridgeBUS::save(Serializer& out) const
|
|||
out.putShort(myJMPoperandAddress);
|
||||
|
||||
// Save cycles and clocks
|
||||
out.putInt(mySystemCycles);
|
||||
out.putLong(mySystemCycles);
|
||||
out.putInt((uInt32)(myFractionalClocks * 100000000.0));
|
||||
out.putInt(myARMCycles);
|
||||
out.putLong(myARMCycles);
|
||||
|
||||
// Audio info
|
||||
out.putIntArray(myMusicCounters, 3);
|
||||
|
@ -614,9 +606,9 @@ bool CartridgeBUS::load(Serializer& in)
|
|||
myJMPoperandAddress = in.getShort();
|
||||
|
||||
// Get system cycles and fractional clocks
|
||||
mySystemCycles = (Int32)in.getInt();
|
||||
mySystemCycles = in.getLong();
|
||||
myFractionalClocks = (double)in.getInt() / 100000000.0;
|
||||
myARMCycles = (Int32)in.getInt();
|
||||
myARMCycles = in.getLong();
|
||||
|
||||
// Audio info
|
||||
in.getIntArray(myMusicCounters, 3);
|
||||
|
|
|
@ -73,13 +73,6 @@ class CartridgeBUS : public Cartridge
|
|||
*/
|
||||
void consoleChanged(ConsoleTiming timing) override;
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
void systemCyclesReset() override;
|
||||
|
||||
/**
|
||||
Install cartridge in the specified system. Invoked by the system
|
||||
when the cartridge is attached to it.
|
||||
|
@ -252,10 +245,10 @@ class CartridgeBUS : public Cartridge
|
|||
uInt16 myJMPoperandAddress;
|
||||
|
||||
// System cycle count when the last update to music data fetchers occurred
|
||||
Int32 mySystemCycles;
|
||||
uInt64 mySystemCycles;
|
||||
|
||||
// ARM cycle count from when the last callFunction() occurred
|
||||
Int32 myARMCycles;
|
||||
uInt64 myARMCycles;
|
||||
|
||||
// The music mode counters
|
||||
uInt32 myMusicCounters[3];
|
||||
|
|
|
@ -119,14 +119,6 @@ void CartridgeCDF::consoleChanged(ConsoleTiming timing)
|
|||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeCDF::systemCyclesReset()
|
||||
{
|
||||
// Adjust the cycle counter so that it reflects the new value
|
||||
myAudioCycles -= mySystem->cycles();
|
||||
myARMCycles -= mySystem->cycles();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeCDF::install(System& system)
|
||||
{
|
||||
|
@ -145,7 +137,7 @@ void CartridgeCDF::install(System& system)
|
|||
inline void CartridgeCDF::updateMusicModeDataFetchers()
|
||||
{
|
||||
// Calculate the number of cycles since the last update
|
||||
Int32 cycles = mySystem->cycles() - myAudioCycles;
|
||||
Int32 cycles = Int32(mySystem->cycles() - myAudioCycles);
|
||||
myAudioCycles = mySystem->cycles();
|
||||
|
||||
// Calculate the number of CDF OSC clocks since the last update
|
||||
|
@ -172,7 +164,7 @@ 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 = mySystem->cycles() - myARMCycles;
|
||||
Int32 cycles = Int32(mySystem->cycles() - myARMCycles);
|
||||
myARMCycles = mySystem->cycles();
|
||||
|
||||
myThumbEmulator->run(cycles);
|
||||
|
@ -519,9 +511,9 @@ bool CartridgeCDF::save(Serializer& out) const
|
|||
out.putByteArray(myMusicWaveformSize, 3);
|
||||
|
||||
// Save cycles and clocks
|
||||
out.putInt(myAudioCycles);
|
||||
out.putLong(myAudioCycles);
|
||||
out.putInt((uInt32)(myFractionalClocks * 100000000.0));
|
||||
out.putInt(myARMCycles);
|
||||
out.putLong(myARMCycles);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -562,9 +554,9 @@ bool CartridgeCDF::load(Serializer& in)
|
|||
in.getByteArray(myMusicWaveformSize, 3);
|
||||
|
||||
// Get cycles and clocks
|
||||
myAudioCycles = (Int32)in.getInt();
|
||||
myAudioCycles = in.getLong();
|
||||
myFractionalClocks = (double)in.getInt() / 100000000.0;
|
||||
myARMCycles = (Int32)in.getInt();
|
||||
myARMCycles = in.getLong();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
|
|
@ -73,13 +73,6 @@ class CartridgeCDF : public Cartridge
|
|||
*/
|
||||
void consoleChanged(ConsoleTiming timing) override;
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
void systemCyclesReset() override;
|
||||
|
||||
/**
|
||||
Install cartridge in the specified system. Invoked by the system
|
||||
when the cartridge is attached to it.
|
||||
|
@ -239,10 +232,10 @@ class CartridgeCDF : public Cartridge
|
|||
uInt16 myBankOffset;
|
||||
|
||||
// System cycle count from when the last update to music data fetchers occurred
|
||||
Int32 myAudioCycles;
|
||||
uInt64 myAudioCycles;
|
||||
|
||||
// ARM cycle count from when the last callFunction() occurred
|
||||
Int32 myARMCycles;
|
||||
uInt64 myARMCycles;
|
||||
|
||||
// The audio routines in the driver run in 32-bit mode and take advantage
|
||||
// of the FIQ Shadow Registers which are not accessible to 16-bit thumb
|
||||
|
|
|
@ -61,13 +61,6 @@ void CartridgeCTY::reset()
|
|||
bank(myStartBank);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeCTY::systemCyclesReset()
|
||||
{
|
||||
// Adjust the cycle counter so that it reflects the new value
|
||||
mySystemCycles -= mySystem->cycles();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeCTY::install(System& system)
|
||||
{
|
||||
|
@ -296,7 +289,7 @@ bool CartridgeCTY::save(Serializer& out) const
|
|||
out.putShort(myCounter);
|
||||
out.putBool(myLDAimmediate);
|
||||
out.putInt(myRandomNumber);
|
||||
out.putInt(mySystemCycles);
|
||||
out.putLong(mySystemCycles);
|
||||
out.putInt(uInt32(myFractionalClocks * 100000000.0));
|
||||
|
||||
}
|
||||
|
@ -325,7 +318,7 @@ bool CartridgeCTY::load(Serializer& in)
|
|||
myCounter = in.getShort();
|
||||
myLDAimmediate = in.getBool();
|
||||
myRandomNumber = in.getInt();
|
||||
mySystemCycles = in.getInt();
|
||||
mySystemCycles = in.getLong();
|
||||
myFractionalClocks = double(in.getInt()) / 100000000.0;
|
||||
}
|
||||
catch(...)
|
||||
|
@ -513,7 +506,7 @@ void CartridgeCTY::wipeAllScores()
|
|||
inline void CartridgeCTY::updateMusicModeDataFetchers()
|
||||
{
|
||||
// Calculate the number of cycles since the last update
|
||||
Int32 cycles = mySystem->cycles() - mySystemCycles;
|
||||
Int32 cycles = Int32(mySystem->cycles() - mySystemCycles);
|
||||
mySystemCycles = mySystem->cycles();
|
||||
|
||||
// Calculate the number of DPC OSC clocks since the last update
|
||||
|
|
|
@ -130,13 +130,6 @@ class CartridgeCTY : public Cartridge
|
|||
*/
|
||||
void reset() override;
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
void systemCyclesReset() override;
|
||||
|
||||
/**
|
||||
Install cartridge in the specified system. Invoked by the system
|
||||
when the cartridge is attached to it.
|
||||
|
@ -300,7 +293,7 @@ class CartridgeCTY : public Cartridge
|
|||
string myEEPROMFile;
|
||||
|
||||
// System cycle count when the last update to music data fetchers occurred
|
||||
Int32 mySystemCycles;
|
||||
uInt64 mySystemCycles;
|
||||
|
||||
// Fractional DPC music OSC clocks unused during the last update
|
||||
double myFractionalClocks;
|
||||
|
|
|
@ -62,13 +62,6 @@ void CartridgeDPC::reset()
|
|||
bank(myStartBank);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeDPC::systemCyclesReset()
|
||||
{
|
||||
// Adjust the cycle counter so that it reflects the new value
|
||||
mySystemCycles -= mySystem->cycles();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeDPC::install(System& system)
|
||||
{
|
||||
|
@ -105,7 +98,7 @@ inline void CartridgeDPC::clockRandomNumberGenerator()
|
|||
inline void CartridgeDPC::updateMusicModeDataFetchers()
|
||||
{
|
||||
// Calculate the number of cycles since the last update
|
||||
Int32 cycles = mySystem->cycles() - mySystemCycles;
|
||||
Int32 cycles = Int32(mySystem->cycles() - mySystemCycles);
|
||||
mySystemCycles = mySystem->cycles();
|
||||
|
||||
// Calculate the number of DPC OSC clocks since the last update
|
||||
|
@ -481,7 +474,7 @@ bool CartridgeDPC::save(Serializer& out) const
|
|||
// The random number generator register
|
||||
out.putByte(myRandomNumber);
|
||||
|
||||
out.putInt(mySystemCycles);
|
||||
out.putLong(mySystemCycles);
|
||||
out.putInt(uInt32(myFractionalClocks * 100000000.0));
|
||||
}
|
||||
catch(...)
|
||||
|
@ -524,7 +517,7 @@ bool CartridgeDPC::load(Serializer& in)
|
|||
myRandomNumber = in.getByte();
|
||||
|
||||
// Get system cycles and fractional clocks
|
||||
mySystemCycles = Int32(in.getInt());
|
||||
mySystemCycles = in.getLong();
|
||||
myFractionalClocks = double(in.getInt()) / 100000000.0;
|
||||
}
|
||||
catch(...)
|
||||
|
|
|
@ -58,13 +58,6 @@ class CartridgeDPC : public Cartridge
|
|||
*/
|
||||
void reset() override;
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
void systemCyclesReset() override;
|
||||
|
||||
/**
|
||||
Install cartridge in the specified system. Invoked by the system
|
||||
when the cartridge is attached to it.
|
||||
|
@ -203,7 +196,7 @@ class CartridgeDPC : public Cartridge
|
|||
uInt8 myRandomNumber;
|
||||
|
||||
// System cycle count when the last update to music data fetchers occurred
|
||||
Int32 mySystemCycles;
|
||||
uInt64 mySystemCycles;
|
||||
|
||||
// Fractional DPC music OSC clocks unused during the last update
|
||||
double myFractionalClocks;
|
||||
|
|
|
@ -110,14 +110,6 @@ void CartridgeDPCPlus::consoleChanged(ConsoleTiming timing)
|
|||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeDPCPlus::systemCyclesReset()
|
||||
{
|
||||
// Adjust the cycle counter so that it reflects the new value
|
||||
mySystemCycles -= mySystem->cycles();
|
||||
myARMCycles -= mySystem->cycles();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeDPCPlus::install(System& system)
|
||||
{
|
||||
|
@ -153,7 +145,7 @@ inline void CartridgeDPCPlus::priorClockRandomNumberGenerator()
|
|||
inline void CartridgeDPCPlus::updateMusicModeDataFetchers()
|
||||
{
|
||||
// Calculate the number of cycles since the last update
|
||||
Int32 cycles = mySystem->cycles() - mySystemCycles;
|
||||
Int32 cycles = Int32(mySystem->cycles() - mySystemCycles);
|
||||
mySystemCycles = mySystem->cycles();
|
||||
|
||||
// Calculate the number of DPC OSC clocks since the last update
|
||||
|
@ -195,7 +187,7 @@ 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 = mySystem->cycles() - myARMCycles;
|
||||
Int32 cycles = Int32(mySystem->cycles() - myARMCycles);
|
||||
myARMCycles = mySystem->cycles();
|
||||
|
||||
myThumbEmulator->run(cycles);
|
||||
|
@ -690,11 +682,11 @@ bool CartridgeDPCPlus::save(Serializer& out) const
|
|||
out.putInt(myRandomNumber);
|
||||
|
||||
// Get system cycles and fractional clocks
|
||||
out.putInt(mySystemCycles);
|
||||
out.putLong(mySystemCycles);
|
||||
out.putInt(uInt32(myFractionalClocks * 100000000.0));
|
||||
|
||||
// Clock info for Thumbulator
|
||||
out.putInt(myARMCycles);
|
||||
out.putLong(myARMCycles);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -754,11 +746,11 @@ bool CartridgeDPCPlus::load(Serializer& in)
|
|||
myRandomNumber = in.getInt();
|
||||
|
||||
// Get system cycles and fractional clocks
|
||||
mySystemCycles = in.getInt();
|
||||
mySystemCycles = in.getLong();
|
||||
myFractionalClocks = double(in.getInt()) / 100000000.0;
|
||||
|
||||
// Clock info for Thumbulator
|
||||
myARMCycles = in.getInt();
|
||||
myARMCycles = in.getLong();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
|
|
@ -74,13 +74,6 @@ class CartridgeDPCPlus : public Cartridge
|
|||
*/
|
||||
void consoleChanged(ConsoleTiming timing) override;
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
void systemCyclesReset() override;
|
||||
|
||||
/**
|
||||
Install cartridge in the specified system. Invoked by the system
|
||||
when the cartridge is attached to it.
|
||||
|
@ -267,13 +260,13 @@ class CartridgeDPCPlus : public Cartridge
|
|||
uInt32 myRandomNumber;
|
||||
|
||||
// System cycle count when the last update to music data fetchers occurred
|
||||
Int32 mySystemCycles;
|
||||
uInt64 mySystemCycles;
|
||||
|
||||
// Fractional DPC music OSC clocks unused during the last update
|
||||
double myFractionalClocks;
|
||||
|
||||
// System cycle count when the last Thumbulator::run() occurred
|
||||
Int32 myARMCycles;
|
||||
uInt64 myARMCycles;
|
||||
|
||||
// Indicates the offset into the ROM image (aligns to current bank)
|
||||
uInt16 myBankOffset;
|
||||
|
|
|
@ -275,7 +275,7 @@ bool CartridgeWD::save(Serializer& out) const
|
|||
out.putString(name());
|
||||
out.putShort(myCurrentBank);
|
||||
out.putByteArray(myRAM, 64);
|
||||
out.putInt(myCyclesAtBankswitchInit);
|
||||
out.putLong(myCyclesAtBankswitchInit);
|
||||
out.putShort(myPendingBank);
|
||||
}
|
||||
catch(...)
|
||||
|
@ -297,7 +297,7 @@ bool CartridgeWD::load(Serializer& in)
|
|||
|
||||
myCurrentBank = in.getShort();
|
||||
in.getByteArray(myRAM, 64);
|
||||
myCyclesAtBankswitchInit = in.getInt();
|
||||
myCyclesAtBankswitchInit = in.getLong();
|
||||
myPendingBank = in.getShort();
|
||||
|
||||
bank(myCurrentBank);
|
||||
|
|
|
@ -224,7 +224,7 @@ class CartridgeWD : public Cartridge
|
|||
uInt16 myOffset[4];
|
||||
|
||||
// Indicates the cycle at which a bankswitch was initiated
|
||||
uInt32 myCyclesAtBankswitchInit;
|
||||
uInt64 myCyclesAtBankswitchInit;
|
||||
|
||||
// Indicates the bank we wish to switch to in the future
|
||||
uInt16 myPendingBank;
|
||||
|
|
|
@ -171,6 +171,13 @@ class Controller : public Serializable
|
|||
*/
|
||||
virtual void update() = 0;
|
||||
|
||||
/**
|
||||
Notification method invoked by the system after its reset method has
|
||||
been called. It may be necessary to override this method for
|
||||
controllers that need to know a reset has occurred.
|
||||
*/
|
||||
virtual void reset() { }
|
||||
|
||||
/**
|
||||
Notification method invoked by the system indicating that the
|
||||
console is about to be destroyed. It may be necessary to override
|
||||
|
@ -178,13 +185,6 @@ class Controller : public Serializable
|
|||
*/
|
||||
virtual void close() { };
|
||||
|
||||
/**
|
||||
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 controllers that remember cycle counts.
|
||||
*/
|
||||
virtual void systemCyclesReset() { }
|
||||
|
||||
/**
|
||||
Determines how this controller will treat values received from the
|
||||
X/Y axis and left/right buttons of the mouse. Since not all controllers
|
||||
|
|
|
@ -55,13 +55,6 @@ class Device : public Serializable
|
|||
*/
|
||||
virtual void consoleChanged(ConsoleTiming timing) { }
|
||||
|
||||
/**
|
||||
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() { }
|
||||
|
||||
/**
|
||||
Install device in the specified system. Invoked by the system
|
||||
when the device is attached to it.
|
||||
|
|
|
@ -68,19 +68,10 @@ void M6532::reset()
|
|||
|
||||
// Edge-detect set to negative (high to low)
|
||||
myEdgeDetectPositive = false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void M6532::systemCyclesReset()
|
||||
{
|
||||
// System cycles are being reset to zero so we need to adjust
|
||||
// the cycle count we remembered when the timer was last set
|
||||
myLastCycle -= mySystem->cycles();
|
||||
mySetTimerCycle -= mySystem->cycles();
|
||||
|
||||
// We should also inform any 'smart' controllers as well
|
||||
myConsole.leftController().systemCyclesReset();
|
||||
myConsole.rightController().systemCyclesReset();
|
||||
// Let the controllers know about the reset
|
||||
myConsole.leftController().reset();
|
||||
myConsole.rightController().reset();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -109,7 +100,7 @@ void M6532::update()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void M6532::updateEmulation()
|
||||
{
|
||||
uInt32 cycles = mySystem->cycles() - myLastCycle;
|
||||
uInt32 cycles = uInt32(mySystem->cycles() - myLastCycle);
|
||||
uInt32 subTimer = mySubTimer;
|
||||
|
||||
// Guard against further state changes if the debugger alread forwarded emulation
|
||||
|
@ -361,8 +352,8 @@ bool M6532::save(Serializer& out) const
|
|||
out.putInt(myDivider);
|
||||
out.putBool(myTimerWrapped);
|
||||
out.putBool(myWrappedThisCycle);
|
||||
out.putInt(myLastCycle);
|
||||
out.putInt(mySetTimerCycle);
|
||||
out.putLong(myLastCycle);
|
||||
out.putLong(mySetTimerCycle);
|
||||
|
||||
out.putByte(myDDRA);
|
||||
out.putByte(myDDRB);
|
||||
|
@ -397,8 +388,8 @@ bool M6532::load(Serializer& in)
|
|||
myDivider = in.getInt();
|
||||
myTimerWrapped = in.getBool();
|
||||
myWrappedThisCycle = in.getBool();
|
||||
myLastCycle = in.getInt();
|
||||
mySetTimerCycle = in.getInt();
|
||||
myLastCycle = in.getLong();
|
||||
mySetTimerCycle = in.getLong();
|
||||
|
||||
myDDRA = in.getByte();
|
||||
myDDRB = in.getByte();
|
||||
|
@ -449,5 +440,5 @@ Int32 M6532::intimClocks()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 M6532::timerClocks() const
|
||||
{
|
||||
return mySystem->cycles() - mySetTimerCycle;
|
||||
return uInt32(mySystem->cycles() - mySetTimerCycle);
|
||||
}
|
||||
|
|
|
@ -60,13 +60,6 @@ class M6532 : public Device
|
|||
*/
|
||||
void reset() override;
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
void systemCyclesReset() override;
|
||||
|
||||
/**
|
||||
Update the entire digital and analog pin state of ports A and B.
|
||||
*/
|
||||
|
@ -178,7 +171,7 @@ class M6532 : public Device
|
|||
bool myWrappedThisCycle;
|
||||
|
||||
// Cycle when the timer set. Debugging only.
|
||||
Int32 mySetTimerCycle;
|
||||
uInt64 mySetTimerCycle;
|
||||
|
||||
// Last cycle considered in emu updates
|
||||
Int32 myLastCycle;
|
||||
|
|
|
@ -144,6 +144,13 @@ void MT24LC256::update()
|
|||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void MT24LC256::systemReset()
|
||||
{
|
||||
myCyclesWhenSDASet = myCyclesWhenSCLSet = myCyclesWhenTimerSet =
|
||||
mySystem.cycles();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void MT24LC256::erase()
|
||||
{
|
||||
|
@ -151,17 +158,6 @@ void MT24LC256::erase()
|
|||
myDataChanged = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void MT24LC256::systemCyclesReset()
|
||||
{
|
||||
// System cycles are being reset to zero so we need to adjust
|
||||
// the cycle counts we remembered
|
||||
uInt32 cycles = mySystem.cycles();
|
||||
myCyclesWhenSDASet -= cycles;
|
||||
myCyclesWhenSCLSet -= cycles;
|
||||
myCyclesWhenTimerSet -= cycles;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void MT24LC256::jpee_init()
|
||||
{
|
||||
|
@ -366,7 +362,7 @@ bool MT24LC256::jpee_timercheck(int mode)
|
|||
{
|
||||
if(myTimerActive)
|
||||
{
|
||||
uInt32 elapsed = mySystem.cycles() - myCyclesWhenTimerSet;
|
||||
uInt32 elapsed = uInt32(mySystem.cycles() - myCyclesWhenTimerSet);
|
||||
myTimerActive = elapsed < uInt32(5000000.0 / 838.0);
|
||||
}
|
||||
return myTimerActive;
|
||||
|
|
|
@ -50,16 +50,12 @@ class MT24LC256
|
|||
void writeSDA(bool state);
|
||||
void writeSCL(bool state);
|
||||
|
||||
/** Called when the system is being reset */
|
||||
void systemReset();
|
||||
|
||||
/** Erase entire EEPROM to known state ($FF) */
|
||||
void erase();
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
void systemCyclesReset();
|
||||
|
||||
private:
|
||||
// I2C access code provided by Supercat
|
||||
void jpee_init();
|
||||
|
@ -85,10 +81,10 @@ class MT24LC256
|
|||
bool myTimerActive;
|
||||
|
||||
// Indicates when the timer was set
|
||||
uInt32 myCyclesWhenTimerSet;
|
||||
uInt64 myCyclesWhenTimerSet;
|
||||
|
||||
// Indicates when the SDA and SCL pins were set/written
|
||||
uInt32 myCyclesWhenSDASet, myCyclesWhenSCLSet;
|
||||
uInt64 myCyclesWhenSDASet, myCyclesWhenSCLSet;
|
||||
|
||||
// The file containing the EEPROM data
|
||||
string myDataFile;
|
||||
|
|
|
@ -72,17 +72,15 @@ void SaveKey::write(DigitalPin pin, bool value)
|
|||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SaveKey::reset()
|
||||
{
|
||||
myEEPROM->systemReset();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SaveKey::close()
|
||||
{
|
||||
// Force the EEPROM object to cleanup
|
||||
myEEPROM.reset();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SaveKey::systemCyclesReset()
|
||||
{
|
||||
// The EEPROM keeps track of cycle counts, and needs to know when the
|
||||
// cycles are reset
|
||||
myEEPROM->systemCyclesReset();
|
||||
}
|
||||
|
|
|
@ -74,6 +74,13 @@ class SaveKey : public Controller
|
|||
*/
|
||||
void update() override { }
|
||||
|
||||
/**
|
||||
Notification method invoked by the system after its reset method has
|
||||
been called. It may be necessary to override this method for
|
||||
controllers that need to know a reset has occurred.
|
||||
*/
|
||||
void reset() override;
|
||||
|
||||
/**
|
||||
Notification method invoked by the system indicating that the
|
||||
console is about to be destroyed. It may be necessary to override
|
||||
|
@ -81,13 +88,6 @@ class SaveKey : public Controller
|
|||
*/
|
||||
void close() override;
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
void systemCyclesReset() override;
|
||||
|
||||
private:
|
||||
// The EEPROM used in the SaveKey
|
||||
unique_ptr<MT24LC256> myEEPROM;
|
||||
|
|
|
@ -133,6 +133,15 @@ void Serializer::getIntArray(uInt32* array, uInt32 size) const
|
|||
myStream->read(reinterpret_cast<char*>(array), sizeof(uInt32)*size);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt64 Serializer::getLong() const
|
||||
{
|
||||
uInt64 val = 0;
|
||||
myStream->read(reinterpret_cast<char*>(&val), sizeof(uInt64));
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
double Serializer::getDouble() const
|
||||
{
|
||||
|
@ -195,6 +204,12 @@ void Serializer::putIntArray(const uInt32* array, uInt32 size)
|
|||
myStream->write(reinterpret_cast<const char*>(array), sizeof(uInt32)*size);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Serializer::putLong(uInt64 value)
|
||||
{
|
||||
myStream->write(reinterpret_cast<char*>(&value), sizeof(uInt64));
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Serializer::putDouble(double value)
|
||||
{
|
||||
|
|
|
@ -27,12 +27,9 @@
|
|||
stream can be either an actual file, or an in-memory structure.
|
||||
|
||||
Bytes are written as characters, shorts as 2 characters (16-bits),
|
||||
integers as 4 characters (32-bits), strings are written as characters
|
||||
prepended by the length of the string, boolean values are written using
|
||||
a special character pattern.
|
||||
|
||||
All bytes, shorts and ints should be cast to their appropriate data type upon
|
||||
method return.
|
||||
integers as 4 characters (32-bits), long integers as 8 bytes (64-bits),
|
||||
strings are written as characters prepended by the length of the string,
|
||||
boolean values are written using a special character pattern.
|
||||
|
||||
@author Stephen Anthony
|
||||
*/
|
||||
|
@ -110,6 +107,13 @@ class Serializer
|
|||
*/
|
||||
void getIntArray(uInt32* array, uInt32 size) const;
|
||||
|
||||
/**
|
||||
Reads a long int value (unsigned 64-bit) from the current input stream.
|
||||
|
||||
@result The long int value which has been read from the stream.
|
||||
*/
|
||||
uInt64 getLong() const;
|
||||
|
||||
/**
|
||||
Reads a double value (signed 64-bit) from the current input stream.
|
||||
|
||||
|
@ -176,6 +180,13 @@ class Serializer
|
|||
*/
|
||||
void putIntArray(const uInt32* array, uInt32 size);
|
||||
|
||||
/**
|
||||
Writes a long int value (unsigned 64-bit) to the current output stream.
|
||||
|
||||
@param value The long int value to write to the output stream.
|
||||
*/
|
||||
void putLong(uInt64 value);
|
||||
|
||||
/**
|
||||
Writes a double value (signed 64-bit) to the current output stream.
|
||||
|
||||
|
|
|
@ -47,14 +47,6 @@ class Sound : public Serializable
|
|||
*/
|
||||
virtual void setEnabled(bool enable) = 0;
|
||||
|
||||
/**
|
||||
The system cycle counter is being adjusting by the specified amount. Any
|
||||
members using the system cycle counter should be adjusted as needed.
|
||||
|
||||
@param amount The amount the cycle counter is being adjusted by
|
||||
*/
|
||||
virtual void adjustCycleCounter(Int32 amount) = 0;
|
||||
|
||||
/**
|
||||
Sets the number of channels (mono or stereo sound).
|
||||
|
||||
|
@ -101,7 +93,7 @@ class Sound : public Serializable
|
|||
@param value The value to save into the register
|
||||
@param cycle The system cycle at which the register is being updated
|
||||
*/
|
||||
virtual void set(uInt16 addr, uInt8 value, Int32 cycle) = 0;
|
||||
virtual void set(uInt16 addr, uInt8 value, uInt64 cycle) = 0;
|
||||
|
||||
/**
|
||||
Sets the volume of the sound device to the specified level. The
|
||||
|
|
|
@ -69,10 +69,8 @@ void System::reset(bool autodetect)
|
|||
// Provide hint to devices that autodetection is active (or not)
|
||||
mySystemInAutodetect = autodetect;
|
||||
|
||||
// Reset system cycle counter
|
||||
resetCycles();
|
||||
|
||||
// Reset all devices
|
||||
myCycles = 0; // Must be done first (the reset() methods use its value)
|
||||
myM6532.reset();
|
||||
myTIA.reset();
|
||||
myCart.reset();
|
||||
|
@ -82,18 +80,6 @@ void System::reset(bool autodetect)
|
|||
clearDirtyPages();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void System::resetCycles()
|
||||
{
|
||||
// First we let all of the device attached to me know about the reset
|
||||
myM6532.systemCyclesReset();
|
||||
myTIA.systemCyclesReset();
|
||||
myCart.systemCyclesReset();
|
||||
|
||||
// Now, we reset cycle count to zero
|
||||
myCycles = 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void System::consoleChanged(ConsoleTiming timing)
|
||||
{
|
||||
|
@ -209,7 +195,7 @@ bool System::save(Serializer& out) const
|
|||
try
|
||||
{
|
||||
out.putString(name());
|
||||
out.putInt(myCycles);
|
||||
out.putLong(myCycles);
|
||||
out.putByte(myDataBusState);
|
||||
|
||||
// Save the state of each device
|
||||
|
@ -241,7 +227,7 @@ bool System::load(Serializer& in)
|
|||
if(in.getString() != name())
|
||||
return false;
|
||||
|
||||
myCycles = in.getInt();
|
||||
myCycles = in.getLong();
|
||||
myDataBusState = in.getByte();
|
||||
|
||||
// Load the state of each device
|
||||
|
|
|
@ -126,12 +126,12 @@ class System : public Serializable
|
|||
|
||||
public:
|
||||
/**
|
||||
Get the number of system cycles which have passed since the last
|
||||
time cycles were reset or the system was reset.
|
||||
Get the number of system cycles which have passed since the
|
||||
system was created.
|
||||
|
||||
@return The number of system cycles which have passed
|
||||
*/
|
||||
uInt32 cycles() const { return myCycles; }
|
||||
uInt64 cycles() const { return myCycles; }
|
||||
|
||||
/**
|
||||
Increment the system cycles by the specified number of cycles.
|
||||
|
@ -140,14 +140,6 @@ class System : public Serializable
|
|||
*/
|
||||
void incrementCycles(uInt32 amount) { myCycles += amount; }
|
||||
|
||||
/**
|
||||
Reset the system cycle count to zero. The first thing that
|
||||
happens is that all devices are notified of the reset by invoking
|
||||
their systemCyclesReset method then the system cycle count is
|
||||
reset to zero.
|
||||
*/
|
||||
void resetCycles();
|
||||
|
||||
/**
|
||||
Informs all attached devices that the console type has changed.
|
||||
*/
|
||||
|
@ -396,8 +388,8 @@ class System : public Serializable
|
|||
// Cartridge device attached to the system
|
||||
Cartridge& myCart;
|
||||
|
||||
// Number of system cycles executed since the last reset
|
||||
uInt32 myCycles;
|
||||
// Number of system cycles executed since instantiation
|
||||
uInt64 myCycles;
|
||||
|
||||
// Null device to use for page which are not installed
|
||||
NullDevice myNullDevice;
|
||||
|
|
|
@ -145,6 +145,8 @@ void TIA::reset()
|
|||
myDelayQueue.reset();
|
||||
myFrameManager.reset();
|
||||
|
||||
myCyclesAtFrameStart = 0;
|
||||
|
||||
frameReset(); // Recalculate the size of the display
|
||||
|
||||
// Must be done last, after all other items have reset
|
||||
|
@ -160,16 +162,6 @@ void TIA::frameReset()
|
|||
enableColorLoss(mySettings.getBool("colorloss"));
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIA::systemCyclesReset()
|
||||
{
|
||||
const uInt32 cycles = mySystem->cycles();
|
||||
|
||||
myLastCycle -= cycles;
|
||||
|
||||
mySound.adjustCycleCounter(-1 * cycles);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIA::install(System& system)
|
||||
{
|
||||
|
@ -243,7 +235,7 @@ bool TIA::save(Serializer& out) const
|
|||
out.putInt(int(myPriority));
|
||||
|
||||
out.putByte(mySubClock);
|
||||
out.putInt(myLastCycle);
|
||||
out.putLong(myLastCycle);
|
||||
|
||||
out.putByte(mySpriteEnabledBits);
|
||||
out.putByte(myCollisionsEnabledBits);
|
||||
|
@ -255,6 +247,8 @@ bool TIA::save(Serializer& out) const
|
|||
out.putBool(myAutoFrameEnabled);
|
||||
|
||||
out.putByteArray(myShadowRegisters, 64);
|
||||
|
||||
out.putLong(myCyclesAtFrameStart);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -312,7 +306,7 @@ bool TIA::load(Serializer& in)
|
|||
myPriority = Priority(in.getInt());
|
||||
|
||||
mySubClock = in.getByte();
|
||||
myLastCycle = in.getInt();
|
||||
myLastCycle = in.getLong();
|
||||
|
||||
mySpriteEnabledBits = in.getByte();
|
||||
myCollisionsEnabledBits = in.getByte();
|
||||
|
@ -324,6 +318,8 @@ bool TIA::load(Serializer& in)
|
|||
myAutoFrameEnabled = in.getBool();
|
||||
|
||||
in.getByteArray(myShadowRegisters, 64);
|
||||
|
||||
myCyclesAtFrameStart = in.getLong();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -811,6 +807,12 @@ bool TIA::enableColorLoss(bool enabled)
|
|||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 TIA::frameCycles() const
|
||||
{
|
||||
return uInt32(mySystem->cycles() - myCyclesAtFrameStart);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool TIA::electronBeamPos(uInt32& x, uInt32& y) const
|
||||
{
|
||||
|
@ -1055,12 +1057,12 @@ uInt8 TIA::registerValue(uInt8 reg) const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIA::updateEmulation()
|
||||
{
|
||||
const uInt32 systemCycles = mySystem->cycles();
|
||||
const uInt64 systemCycles = mySystem->cycles();
|
||||
|
||||
if (mySubClock > 2)
|
||||
throw runtime_error("subclock exceeds range");
|
||||
|
||||
const uInt32 cyclesToRun = 3 * (systemCycles - myLastCycle) + mySubClock;
|
||||
const uInt32 cyclesToRun = 3 * uInt32(systemCycles - myLastCycle) + mySubClock;
|
||||
|
||||
mySubClock = 0;
|
||||
myLastCycle = systemCycles;
|
||||
|
@ -1103,7 +1105,7 @@ void TIA::onRenderingStart()
|
|||
void TIA::onFrameComplete()
|
||||
{
|
||||
mySystem->m6502().stop();
|
||||
mySystem->resetCycles();
|
||||
myCyclesAtFrameStart = mySystem->cycles();
|
||||
|
||||
if (myXAtRenderingStart > 0)
|
||||
memset(myFramebuffer, 0, myXAtRenderingStart);
|
||||
|
|
|
@ -112,12 +112,6 @@ class TIA : public Device
|
|||
*/
|
||||
void frameReset();
|
||||
|
||||
/**
|
||||
Notification method invoked by the system right before the
|
||||
system resets its cycle counter to zero.
|
||||
*/
|
||||
void systemCyclesReset() override;
|
||||
|
||||
/**
|
||||
Install TIA in the specified system. Invoked by the system
|
||||
when the TIA is attached to it.
|
||||
|
@ -264,6 +258,11 @@ class TIA : public Device
|
|||
*/
|
||||
uInt32 scanlinesLastFrame() const { return myFrameManager.scanlinesLastFrame(); }
|
||||
|
||||
/**
|
||||
Answers the system cycles from the start of the current frame.
|
||||
*/
|
||||
uInt32 frameCycles() const;
|
||||
|
||||
/**
|
||||
Answers whether the TIA is currently in being rendered
|
||||
(we're in between the start and end of drawing a frame).
|
||||
|
@ -707,6 +706,11 @@ class TIA : public Device
|
|||
bool myColorLossEnabled;
|
||||
bool myColorLossActive;
|
||||
|
||||
/**
|
||||
* System cycles at the end of the previous frame / beginning of next frame
|
||||
*/
|
||||
uInt64 myCyclesAtFrameStart;
|
||||
|
||||
private:
|
||||
TIA() = delete;
|
||||
TIA(const TIA&) = delete;
|
||||
|
|
Loading…
Reference in New Issue