SPC: Fixed potential overflow problem when running for a very long time

This commit is contained in:
Sour 2019-03-29 22:13:22 -04:00
parent 75150cb133
commit 7e4a141b7b
3 changed files with 12 additions and 6 deletions

View file

@ -230,10 +230,10 @@ bool Console::LoadRom(VirtualFile romFile, VirtualFile patchFile, bool stopRom)
_internalRegisters.reset(new InternalRegisters(shared_from_this())); _internalRegisters.reset(new InternalRegisters(shared_from_this()));
_ppu.reset(new Ppu(shared_from_this())); _ppu.reset(new Ppu(shared_from_this()));
_spc.reset(new Spc(shared_from_this(), spcRomData));
_controlManager.reset(new ControlManager(shared_from_this())); _controlManager.reset(new ControlManager(shared_from_this()));
_memoryManager.reset(new MemoryManager()); _memoryManager.reset(new MemoryManager());
_dmaController.reset(new DmaController(_memoryManager.get())); _dmaController.reset(new DmaController(_memoryManager.get()));
_spc.reset(new Spc(shared_from_this(), spcRomData));
_memoryManager->Initialize(shared_from_this()); _memoryManager->Initialize(shared_from_this());

View file

@ -9,6 +9,7 @@
Spc::Spc(shared_ptr<Console> console, vector<uint8_t> &spcRomData) Spc::Spc(shared_ptr<Console> console, vector<uint8_t> &spcRomData)
{ {
_console = console; _console = console;
_memoryManager = console->GetMemoryManager();
_soundBuffer = new int16_t[Spc::SampleBufferSize]; _soundBuffer = new int16_t[Spc::SampleBufferSize];
_immediateMode = false; _immediateMode = false;
_operandA = 0; _operandA = 0;
@ -28,6 +29,8 @@ Spc::Spc(shared_ptr<Console> console, vector<uint8_t> &spcRomData)
_state.RomEnabled = true; _state.RomEnabled = true;
_state.SP = 0xFF; _state.SP = 0xFF;
_state.PC = ReadWord(Spc::ResetVector); _state.PC = ReadWord(Spc::ResetVector);
_clockRatio = (double)2048000 / _console->GetMasterClockRate();
} }
Spc::~Spc() Spc::~Spc()
@ -202,9 +205,7 @@ void Spc::CpuWriteRegister(uint32_t addr, uint8_t value)
void Spc::Run() void Spc::Run()
{ {
int64_t masterClock = _console->GetMemoryManager()->GetMasterClock(); uint64_t targetCycle = (uint64_t)(_memoryManager->GetMasterClock() * _clockRatio);
//TODO: This will overflow after 100+ hours, needs to be fixed
uint64_t targetCycle = (masterClock * (uint64_t)1024000 / (uint64_t)_console->GetMasterClockRate()) * 2;
while(_state.Cycle < targetCycle) { while(_state.Cycle < targetCycle) {
Exec(); Exec();
} }
@ -214,6 +215,8 @@ void Spc::ProcessEndFrame()
{ {
Run(); Run();
_clockRatio = (double)2048000 / _console->GetMasterClockRate();
int sampleCount = _dsp->sample_count(); int sampleCount = _dsp->sample_count();
if(sampleCount != 0) { if(sampleCount != 0) {
_console->GetSoundMixer()->PlayAudioBuffer(_soundBuffer, sampleCount / 2); _console->GetSoundMixer()->PlayAudioBuffer(_soundBuffer, sampleCount / 2);
@ -233,14 +236,14 @@ void Spc::Serialize(Serializer &s)
s.Stream(_state.OutputReg[0], _state.OutputReg[1], _state.OutputReg[2], _state.OutputReg[3]); s.Stream(_state.OutputReg[0], _state.OutputReg[1], _state.OutputReg[2], _state.OutputReg[3]);
s.Stream(_state.RamReg[0], _state.RamReg[1]); s.Stream(_state.RamReg[0], _state.RamReg[1]);
s.Stream(_state.ExternalSpeed, _state.InternalSpeed, _state.WriteEnabled, _state.TimersEnabled); s.Stream(_state.ExternalSpeed, _state.InternalSpeed, _state.WriteEnabled, _state.TimersEnabled);
s.Stream(_state.DspReg, _state.RomEnabled); s.Stream(_state.DspReg, _state.RomEnabled, _clockRatio);
_state.Timer0.Serialize(s); _state.Timer0.Serialize(s);
_state.Timer1.Serialize(s); _state.Timer1.Serialize(s);
_state.Timer2.Serialize(s); _state.Timer2.Serialize(s);
ArrayInfo<uint8_t> ram { _ram, Spc::SpcRamSize }; ArrayInfo<uint8_t> ram { _ram, Spc::SpcRamSize };
s.Stream(ram, _state.DspReg, _state.RomEnabled); s.Stream(ram);
uint8_t dspState[SPC_DSP::state_size]; uint8_t dspState[SPC_DSP::state_size];
memset(dspState, 0, SPC_DSP::state_size); memset(dspState, 0, SPC_DSP::state_size);

View file

@ -6,6 +6,7 @@
#include "../Utilities/ISerializable.h" #include "../Utilities/ISerializable.h"
class Console; class Console;
class MemoryManager;
class SPC_DSP; class SPC_DSP;
class Spc : public ISerializable class Spc : public ISerializable
@ -18,11 +19,13 @@ private:
static constexpr uint16_t ResetVector = 0xFFFE; static constexpr uint16_t ResetVector = 0xFFFE;
shared_ptr<Console> _console; shared_ptr<Console> _console;
shared_ptr<MemoryManager> _memoryManager;
unique_ptr<SPC_DSP> _dsp; unique_ptr<SPC_DSP> _dsp;
bool _immediateMode; bool _immediateMode;
uint16_t _operandA; uint16_t _operandA;
uint16_t _operandB; uint16_t _operandB;
double _clockRatio;
SpcState _state; SpcState _state;
uint8_t _ram[Spc::SpcRamSize]; uint8_t _ram[Spc::SpcRamSize];