SGB: Improved logic to select row/bank to write pixels to

Uses hblank/vblank (when mode changes) to move to the next row/reset to the top of the screen
This commit is contained in:
Sour 2025-03-02 13:23:07 +09:00
parent 53f17745d7
commit e9a0e7aaa5
3 changed files with 29 additions and 19 deletions

View file

@ -179,6 +179,9 @@ void GbPpu::ExecCycle()
//Mode turns to hblank on the same cycle as the last pixel is output
_state.Mode = PpuMode::HBlank;
_state.IrqMode = PpuMode::HBlank;
if(_gameboy->IsSgb()) {
_gameboy->GetSgb()->ProcessHBlank();
}
_state.IdleCycles = 456 - _state.Cycle - 1;
_oamReadBlocked = false;
@ -219,6 +222,9 @@ void GbPpu::ProcessVblankScanline()
if(_state.Scanline == 144) {
_state.Mode = PpuMode::VBlank;
_state.IrqMode = PpuMode::VBlank;
if(_gameboy->IsSgb()) {
_gameboy->GetSgb()->ProcessVBlank();
}
_windowCounter = -1;
_memoryManager->RequestIrq(GbIrqSource::VerticalBlank);
SendFrame();

View file

@ -96,7 +96,7 @@ uint8_t SuperGameboy::Read(uint32_t addr)
return data;
} else {
switch(addr & 0xFFFF) {
case 0x6000: return (GetLcdRow() << 3) | GetLcdBufferRow();
case 0x6000: return (_row & ~0x07) | _bank;
case 0x6002: return _packetReady;
case 0x600F: return 0x21; //or 0x61
}
@ -240,24 +240,22 @@ void SuperGameboy::LogPacket()
_emu->DebugLog(log);
}
void SuperGameboy::ProcessHBlank()
{
_row++;
if((_row & 0x07) == 0) {
_bank = (_bank + 1) & 0x03;
}
}
void SuperGameboy::ProcessVBlank()
{
_row = 0;
}
void SuperGameboy::WriteLcdColor(uint8_t scanline, uint8_t pixel, uint8_t color)
{
_lcdBuffer[GetLcdBufferRow()][(scanline & 0x07) * 160 + pixel] = color;
}
uint8_t SuperGameboy::GetLcdRow()
{
uint8_t scanline = _ppu->GetScanline();
uint8_t row = scanline / 8;
if(row >= 18) {
row = 0;
}
return row;
}
uint8_t SuperGameboy::GetLcdBufferRow()
{
return (_ppu->GetFrameCount() * 18 + GetLcdRow()) & 0x03;
_lcdBuffer[_bank][(_row & 0x07) * 160 + pixel] = color;
}
uint8_t SuperGameboy::GetPlayerCount()
@ -364,6 +362,8 @@ void SuperGameboy::Serialize(Serializer& s)
{
SV(_control); SV(_resetClock); SV(_input[0]); SV(_input[1]); SV(_input[2]); SV(_input[3]); SV(_inputIndex); SV(_listeningForPacket); SV(_packetReady);
SV(_inputWriteClock); SV(_inputValue); SV(_packetByte); SV(_packetBit); SV(_lcdRowSelect); SV(_readPosition); SV(_waitForHigh); SV(_clockRatio);
SV(_row);
SV(_bank);
SVArray(_packetData, 16);
SVArray(_lcdBuffer[0], 1280);

View file

@ -30,6 +30,9 @@ private:
double _clockRatio = 0;
double _effectiveClockRate = 0;
uint64_t _clockOffset = 0;
uint8_t _row = 0;
uint8_t _bank = 0;
uint8_t _input[4] = {};
uint8_t _inputIndex = 0;
@ -49,8 +52,6 @@ private:
HermiteResampler _resampler;
uint8_t GetLcdRow();
uint8_t GetLcdBufferRow();
uint8_t GetPlayerCount();
void SetInputIndex(uint8_t index);
@ -71,6 +72,9 @@ public:
void LogPacket();
void ProcessHBlank();
void ProcessVBlank();
void WriteLcdColor(uint8_t scanline, uint8_t pixel, uint8_t color);
void MixAudio(int16_t* out, uint32_t sampleCount, uint32_t sampleRate) override;