PPU: Fixed tile CHR address for layers 1/3 + implemented "layer/oam enabled" flag

This commit is contained in:
Sour 2019-02-17 23:26:49 -05:00
parent 20059ae975
commit 7ccfc99a62
2 changed files with 55 additions and 27 deletions

View file

@ -95,8 +95,15 @@ void Ppu::Exec()
_cycle++;
}
void Ppu::RenderTilemap(LayerConfig &config, uint8_t bpp)
void Ppu::RenderTilemap(uint8_t layerIndex, uint8_t bpp)
{
if(((_mainScreenLayers >> layerIndex) & 0x01) == 0) {
//This screen is disabled
return;
}
LayerConfig &config = _layerConfig[layerIndex];
uint16_t tilemapAddr = config.TilemapAddress;
uint16_t chrAddr = config.ChrAddress;
@ -116,10 +123,11 @@ void Ppu::RenderTilemap(LayerConfig &config, uint8_t bpp)
color >>= 1;
}
uint16_t paletteRamOffset = color == 0 ? 0 : ((palette * (1 << bpp) + color) * 2);
uint16_t paletteColor = _cgram[paletteRamOffset] | (_cgram[paletteRamOffset + 1] << 8);
_currentBuffer[(y * 8 + i) * 256 + x * 8 + j] = paletteColor;
if(color > 0) {
uint16_t paletteRamOffset = (palette * (1 << bpp) + color) * 2;
uint16_t paletteColor = _cgram[paletteRamOffset] | (_cgram[paletteRamOffset + 1] << 8);
_currentBuffer[(y * 8 + i) * 256 + x * 8 + j] = paletteColor;
}
}
}
addr+=2;
@ -129,42 +137,58 @@ void Ppu::RenderTilemap(LayerConfig &config, uint8_t bpp)
void Ppu::SendFrame()
{
uint16_t bgColor = _cgram[0] | (_cgram[1]);
for(int i = 0; i < 256 * 224; i++) {
_currentBuffer[i] = bgColor;
}
switch(_bgMode) {
case 0:
RenderTilemap(_layerConfig[3], 2);
RenderTilemap(_layerConfig[2], 2);
RenderTilemap(_layerConfig[1], 2);
RenderTilemap(_layerConfig[0], 2);
RenderTilemap(3, 2);
RenderTilemap(2, 2);
RenderTilemap(1, 2);
RenderTilemap(0, 2);
break;
case 1:
RenderTilemap(_layerConfig[2], 2);
RenderTilemap(_layerConfig[1], 4);
RenderTilemap(_layerConfig[0], 4);
RenderTilemap(2, 2);
RenderTilemap(1, 4);
RenderTilemap(0, 4);
break;
case 2:
RenderTilemap(_layerConfig[1], 4);
RenderTilemap(_layerConfig[0], 4);
RenderTilemap(1, 4);
RenderTilemap(0, 4);
break;
case 3:
RenderTilemap(_layerConfig[1], 4);
RenderTilemap(_layerConfig[0], 8);
RenderTilemap(1, 4);
RenderTilemap(0, 8);
break;
case 5:
RenderTilemap(_layerConfig[1], 2);
RenderTilemap(_layerConfig[0], 4);
RenderTilemap(1, 2);
RenderTilemap(0, 4);
break;
case 6:
RenderTilemap(_layerConfig[0], 8);
RenderTilemap(0, 8);
break;
}
//Draw sprites
for(int i = 0; i < 512; i+=4) {
if(_mainScreenLayers & 0x10) {
DrawSprites();
}
_console->GetNotificationManager()->SendNotification(ConsoleNotificationType::PpuFrameDone);
_currentBuffer = _currentBuffer == _outputBuffers[0] ? _outputBuffers[1] : _outputBuffers[0];
_console->GetVideoDecoder()->UpdateFrame(_currentBuffer, _frameCount);
}
void Ppu::DrawSprites()
{
for(int i = 0; i < 512; i += 4) {
uint8_t y = _oamRam[i + 1];
if(y >= 225) {
continue;
@ -219,10 +243,6 @@ void Ppu::SendFrame()
}
}
}
_console->GetNotificationManager()->SendNotification(ConsoleNotificationType::PpuFrameDone);
_currentBuffer = _currentBuffer == _outputBuffers[0] ? _outputBuffers[1] : _outputBuffers[0];
_console->GetVideoDecoder()->UpdateFrame(_currentBuffer, _frameCount);
}
uint8_t* Ppu::GetVideoRam()
@ -307,8 +327,8 @@ void Ppu::Write(uint32_t addr, uint8_t value)
case 0x210B: case 0x210C:
//BG1+2 / BG3+4 Chr Address (BG12NBA / BG34NBA)
_layerConfig[addr - 0x210B].ChrAddress = (value & 0x0F) << 12;
_layerConfig[addr - 0x210B + 1].ChrAddress = (value & 0xF0) << 8;
_layerConfig[(addr - 0x210B) * 2].ChrAddress = (value & 0x0F) << 12;
_layerConfig[(addr - 0x210B) * 2 + 1].ChrAddress = (value & 0xF0) << 8;
break;
case 0x2115:
@ -361,6 +381,11 @@ void Ppu::Write(uint32_t addr, uint8_t value)
_cgramAddress = (_cgramAddress + 1) & (Ppu::CgRamSize - 1);
break;
case 0x212C:
//TM - Main Screen Designation
_mainScreenLayers = value & 0x1F;
break;
default:
MessageManager::DisplayMessage("Debug", "Unimplemented register write: " + HexUtilities::ToHex(addr));
break;

View file

@ -32,6 +32,8 @@ private:
uint32_t _frameCount = 0;
uint8_t _bgMode = 0;
uint8_t _mainScreenLayers = 0;
LayerConfig _layerConfig[4];
uint8_t *_vram;
@ -57,7 +59,8 @@ private:
uint16_t _internalOamAddress = 0;
uint8_t _oamWriteBuffer = 0;
void RenderTilemap(LayerConfig &config, uint8_t bpp);
void RenderTilemap(uint8_t layerIndex, uint8_t bpp);
void DrawSprites();
public:
Ppu(shared_ptr<Console> console);