Mesen-S/Core/BsxSatellaview.cpp
Sour 6539b92502 SA-1: Fixed timing regressions
Memory handlers did not have the _memoryType value set, which caused some memory accesses to be much faster than expected
2020-03-01 18:24:33 -05:00

140 lines
3.8 KiB
C++

#include "stdafx.h"
#include "BsxSatellaview.h"
#include "Console.h"
#include "MemoryManager.h"
#include "EmuSettings.h"
#include "../Utilities/Serializer.h"
BsxSatellaview::BsxSatellaview(Console* console, IMemoryHandler* bBusHandler) : IMemoryHandler(SnesMemoryType::Register)
{
_console = console;
_memoryManager = console->GetMemoryManager().get();
_customDate = console->GetSettings()->GetEmulationConfig().BsxCustomDate;
_bBusHandler = bBusHandler;
Reset();
}
void BsxSatellaview::Reset()
{
_prevMasterClock = 0;
_streamReg = 0;
_extOutput = 0xFF;
time_t resetDate;
if(_customDate >= 0) {
resetDate = (time_t)_customDate;
} else {
//Use the current date/time as the BS-X date/time
time(&resetDate);
}
_stream[0].Reset(_console, resetDate);
_stream[1].Reset(_console, resetDate);
}
uint8_t BsxSatellaview::Read(uint32_t addr)
{
addr &= 0xFFFF;
if(addr >= 0x2188 && addr <= 0x219F) {
//Handle BS-X $2188-219F registers
ProcessClocks();
switch(addr) {
case 0x2188: return _stream[0].GetChannel() & 0xFF;
case 0x2189: return (_stream[0].GetChannel()) >> 8;
case 0x218A: return _stream[0].GetPrefixCount();
case 0x218B: return _stream[0].GetPrefix();
case 0x218C: return _stream[0].GetData();
case 0x218D: return _stream[0].GetStatus((_streamReg & 0x01) != 0);
case 0x218E: return _stream[1].GetChannel() & 0xFF;
case 0x218F: return (_stream[1].GetChannel()) >> 8;
case 0x2190: return _stream[1].GetPrefixCount();
case 0x2191: return _stream[1].GetPrefix();
case 0x2192: return _stream[1].GetData();
case 0x2193: return _stream[1].GetStatus((_streamReg & 0x01) != 0);
case 0x2194: return _streamReg; //LED and Stream register
case 0x2195: return 0; //Unknown
case 0x2196: return 0x10; //Satellaview status
case 0x2197: return _extOutput; //Soundlink / EXT output
case 0x2198: return 0x80; //Serial IO (Serial number)
case 0x2199: return 0x01; //Serial IO (???)
case 0x219A: return 0x10; //Unknown
}
}
//Use regular B-bus handler for everything else
return _bBusHandler->Read(addr);
}
void BsxSatellaview::Write(uint32_t addr, uint8_t value)
{
addr &= 0xFFFF;
if(addr >= 0x2188 && addr <= 0x219F) {
//Handle BS-X register writes
ProcessClocks();
switch(addr) {
case 0x2188: _stream[0].SetChannelLow(value); break;
case 0x2189: _stream[0].SetChannelHigh(value); break;
case 0x218B: _stream[0].SetPrefixLatch(value); break;
case 0x218C: _stream[0].SetDataLatch(value); break;
case 0x218E: _stream[1].SetChannelLow(value); break;
case 0x218F: _stream[1].SetChannelHigh(value); break;
case 0x2191: _stream[1].SetPrefixLatch(value); break;
case 0x2192: _stream[1].SetDataLatch(value); break;
case 0x2194: _streamReg = value; break;
case 0x2197: _extOutput = value; break;
}
} else {
//Regular B-bus handler
_bBusHandler->Write(addr, value);
}
}
void BsxSatellaview::ProcessClocks()
{
if(_stream[0].NeedUpdate() || _stream[1].NeedUpdate()) {
uint64_t gap = _memoryManager->GetMasterClock() - _prevMasterClock;
uint64_t clocksPerFrame = _console->GetMasterClockRate() / 1000; //1000 frames/sec (224kbits/sec)
while(gap >= clocksPerFrame) {
bool needUpdate = _stream[0].FillQueues() || _stream[1].FillQueues();
if(!needUpdate) {
gap = 0;
break;
}
gap -= clocksPerFrame;
}
_prevMasterClock = _memoryManager->GetMasterClock() - gap;
} else {
_prevMasterClock = _memoryManager->GetMasterClock();
}
}
uint8_t BsxSatellaview::Peek(uint32_t addr)
{
return 0;
}
void BsxSatellaview::PeekBlock(uint32_t addr, uint8_t* output)
{
memset(output, 0, 0x1000);
}
AddressInfo BsxSatellaview::GetAbsoluteAddress(uint32_t address)
{
return { -1, SnesMemoryType::Register };
}
void BsxSatellaview::Serialize(Serializer& s)
{
s.Stream(_extOutput, _streamReg, _customDate, _prevMasterClock);
s.Stream(&_stream[0]);
s.Stream(&_stream[1]);
}