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()));
_ppu.reset(new Ppu(shared_from_this()));
_spc.reset(new Spc(shared_from_this(), spcRomData));
_controlManager.reset(new ControlManager(shared_from_this()));
_memoryManager.reset(new MemoryManager());
_dmaController.reset(new DmaController(_memoryManager.get()));
_spc.reset(new Spc(shared_from_this(), spcRomData));
_memoryManager->Initialize(shared_from_this());

View file

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

View file

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