Minor performance improvements (5-15%)

This commit is contained in:
Sour 2020-06-24 18:43:49 -04:00
parent 4ac7b21878
commit 884aa1abcc
2 changed files with 118 additions and 99 deletions

View file

@ -48,13 +48,6 @@ void MemoryManager::Initialize(Console *console)
_workRam
));
memset(_hasEvent, 0, sizeof(_hasEvent));
_hasEvent[276 * 4] = true;
_hasEvent[285 * 4] = true;
_hasEvent[1360] = true;
_hasEvent[1364] = true;
_hasEvent[1368] = true;
for(uint32_t i = 0; i < 128 * 1024; i += 0x1000) {
_workRamHandlers.push_back(unique_ptr<RamHandler>(new RamHandler(_workRam, i, MemoryManager::WorkRamSize, SnesMemoryType::WorkRam)));
}
@ -75,7 +68,7 @@ void MemoryManager::Initialize(Console *console)
_cart->Init(_mappings);
GenerateMasterClockTable();
UpdateEvents();
Reset();
}
MemoryManager::~MemoryManager()
@ -87,47 +80,47 @@ void MemoryManager::Reset()
{
_masterClock = 0;
_hClock = 0;
UpdateEvents();
_dramRefreshPosition = 538 - (_masterClock & 0x07);
_nextEventClock = _dramRefreshPosition;
_nextEvent = SnesEventType::DramRefresh;
}
void MemoryManager::GenerateMasterClockTable()
{
for(int j = 0; j < 2; j++) {
for(int i = 0; i < 0x10000; i++) {
uint8_t bank = (i & 0xFF00) >> 8;
if(bank >= 0x40 && bank <= 0x7F) {
for(int i = 0; i < 0x800; i++) {
uint8_t bank = (i & 0x300) >> 8;
if(bank == 1) {
//Banks $40-$7F - Slow
_masterClockTable[i] = 8;
} else if(bank == 3) {
//Banks $C0-$FF
//Slow or fast (depending on register)
_masterClockTable[i] = (i >= 0x400) ? 6 : 8;
} else {
//Banks $00-$3F and $80-$BF
uint8_t page = (i & 0xFF);
if(page <= 0x1F) {
//Slow
_masterClockTable[j][i] = 8;
} else if(bank >= 0xC0) {
//Banks $C0-$FF
//Slow or fast (depending on register)
_masterClockTable[j][i] = j == 1 ? 6 : 8;
_masterClockTable[i] = 8;
} else if(page >= 0x20 && page <= 0x3F) {
//Fast
_masterClockTable[i] = 6;
} else if(page == 0x40 || page == 0x41) {
//Extra slow
_masterClockTable[i] = 12;
} else if(page >= 0x42 && page <= 0x5F) {
//Fast
_masterClockTable[i] = 6;
} else if(page >= 0x60 && page <= 0x7F) {
//Slow
_masterClockTable[i] = 8;
} else if(bank == 0) {
//Slow
_masterClockTable[i] = 8;
} else {
//Banks $00-$3F and $80-$BF
uint8_t page = (i & 0xFF);
if(page <= 0x1F) {
//Slow
_masterClockTable[j][i] = 8;
} else if(page >= 0x20 && page <= 0x3F) {
//Fast
_masterClockTable[j][i] = 6;
} else if(page == 0x40 || page == 0x41) {
//Extra slow
_masterClockTable[j][i] = 12;
} else if(page >= 0x42 && page <= 0x5F) {
//Fast
_masterClockTable[j][i] = 6;
} else if(page >= 0x60 && page <= 0x7F) {
//Slow
_masterClockTable[j][i] = 8;
} else if(bank <= 0x3F) {
//Slow
_masterClockTable[j][i] = 8;
} else {
//page >= $80
//Slow or fast (depending on register)
_masterClockTable[j][i] = j == 1 ? 6 : 8;
}
//page >= $80
//Slow or fast (depending on register)
_masterClockTable[i] = (i >= 0x400) ? 6 : 8;
}
}
}
@ -181,49 +174,16 @@ void MemoryManager::IncrementMasterClockValue(uint16_t cyclesToRun)
}
}
void MemoryManager::UpdateEvents()
{
_hasEvent[_hdmaInitPosition] = false;
_hasEvent[_dramRefreshPosition] = false;
if(_ppu->GetScanline() == 0) {
_hdmaInitPosition = 12 + (_masterClock & 0x07);
_hasEvent[_hdmaInitPosition] = true;
}
_dramRefreshPosition = 538 - (_masterClock & 0x07);
_hasEvent[_dramRefreshPosition] = true;
}
void MemoryManager::Exec()
{
_masterClock += 2;
_hClock += 2;
if(_hasEvent[_hClock]) {
if(_hClock >= 1360 && _ppu->ProcessEndOfScanline(_hClock)) {
_hClock = 0;
UpdateEvents();
}
if((_hClock & 0x03) == 0) {
_console->ProcessPpuCycle<CpuType::Cpu>();
_regs->ProcessIrqCounters();
if(_hClock == 276 * 4 && _ppu->GetScanline() < _ppu->GetVblankStart()) {
_console->GetDmaController()->BeginHdmaTransfer();
}
}
if(_hClock == _hdmaInitPosition && _ppu->GetScanline() == 0) {
_console->GetDmaController()->BeginHdmaInit();
}
if(_hClock == _dramRefreshPosition) {
IncMasterClock40();
_cpu->IncreaseCycleCount<5>();
}
} else if((_hClock & 0x03) == 0) {
if(_hClock == _nextEventClock) {
ProcessEvent();
}
if((_hClock & 0x03) == 0) {
_console->ProcessPpuCycle<CpuType::Cpu>();
_regs->ProcessIrqCounters();
}
@ -231,6 +191,53 @@ void MemoryManager::Exec()
_cart->SyncCoprocessors();
}
void MemoryManager::ProcessEvent()
{
switch(_nextEvent) {
case SnesEventType::HdmaInit:
_console->GetDmaController()->BeginHdmaInit();
_nextEvent = SnesEventType::DramRefresh;
_nextEventClock = _dramRefreshPosition;
break;
case SnesEventType::DramRefresh:
IncMasterClock40();
_cpu->IncreaseCycleCount<5>();
if(_ppu->GetScanline() < _ppu->GetVblankStart()) {
_nextEvent = SnesEventType::HdmaStart;
_nextEventClock = 276 * 4;
} else {
_nextEvent = SnesEventType::EndOfScanline;
_nextEventClock = 1360;
}
break;
case SnesEventType::HdmaStart:
_console->GetDmaController()->BeginHdmaTransfer();
_nextEvent = SnesEventType::EndOfScanline;
_nextEventClock = 1360;
break;
case SnesEventType::EndOfScanline:
if(_ppu->ProcessEndOfScanline(_hClock)) {
_hClock = 0;
if(_ppu->GetScanline() == 0) {
_nextEvent = SnesEventType::HdmaInit;
_nextEventClock = 12 + (_masterClock & 0x07);
} else {
_dramRefreshPosition = 538 - (_masterClock & 0x07);
_nextEvent = SnesEventType::DramRefresh;
_nextEventClock = _dramRefreshPosition;
}
} else {
_nextEventClock += 2;
}
break;
}
}
uint8_t MemoryManager::Read(uint32_t addr, MemoryOperationType type)
{
IncrementMasterClockValue(_cpuSpeed - 4);
@ -373,7 +380,7 @@ MemoryMappings* MemoryManager::GetMemoryMappings()
uint8_t MemoryManager::GetCpuSpeed(uint32_t addr)
{
return _masterClockTable[(uint8_t)_regs->IsFastRomEnabled()][addr >> 8];
return _masterClockTable[(_regs->IsFastRomEnabled() << 10) | ((addr & 0xC00000) >> 14) | ((addr & 0xFF00) >> 8)];
}
uint8_t MemoryManager::GetCpuSpeed()
@ -405,8 +412,13 @@ bool MemoryManager::IsWorkRam(uint32_t cpuAddress)
void MemoryManager::Serialize(Serializer &s)
{
s.Stream(_masterClock, _openBus, _cpuSpeed, _hClock, _dramRefreshPosition, _hdmaInitPosition);
s.Stream(_masterClock, _openBus, _cpuSpeed, _hClock, _dramRefreshPosition);
s.StreamArray(_workRam, MemoryManager::WorkRamSize);
s.StreamArray(_hasEvent, sizeof(_hasEvent));
if(s.GetVersion() < 8) {
bool unusedHasEvent[1369];
s.StreamArray(unusedHasEvent, sizeof(unusedHasEvent));
}
s.Stream(_registerHandlerB.get());
}

View file

@ -16,6 +16,14 @@ class Cpu;
class CheatManager;
enum class MemoryOperationType;
enum class SnesEventType : uint8_t
{
HdmaInit,
DramRefresh,
HdmaStart,
EndOfScanline
};
class MemoryManager : public ISerializable
{
public:
@ -32,26 +40,26 @@ private:
Cpu* _cpu;
BaseCartridge* _cart;
CheatManager* _cheatManager;
uint8_t *_workRam;
uint64_t _masterClock = 0;
uint16_t _hClock = 0;
uint16_t _nextEventClock = 0;
uint16_t _dramRefreshPosition = 0;
SnesEventType _nextEvent = SnesEventType::DramRefresh;
SnesMemoryType _memTypeBusA = SnesMemoryType::PrgRom;
uint8_t _cpuSpeed = 8;
uint8_t _openBus = 0;
MemoryMappings _mappings;
vector<unique_ptr<IMemoryHandler>> _workRamHandlers;
uint8_t _masterClockTable[0x800];
uint8_t *_workRam;
uint64_t _masterClock = 0;
uint16_t _hClock = 0;
uint16_t _dramRefreshPosition = 0;
uint16_t _hdmaInitPosition = 0;
uint8_t _openBus = 0;
uint8_t _cpuSpeed = 8;
SnesMemoryType _memTypeBusA = SnesMemoryType::PrgRom;
bool _hasEvent[1369];
uint8_t _masterClockTable[2][0x10000];
void UpdateEvents();
__forceinline void SyncCoprocessors();
void Exec();
void ProcessEvent();
public:
void Initialize(Console* console);
virtual ~MemoryManager();
@ -91,7 +99,6 @@ public:
bool IsRegister(uint32_t cpuAddress);
bool IsWorkRam(uint32_t cpuAddress);
int GetRelativeAddress(AddressInfo &address, uint8_t startBank = 0);
void Serialize(Serializer &s) override;
};