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++; _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 tilemapAddr = config.TilemapAddress;
uint16_t chrAddr = config.ChrAddress; uint16_t chrAddr = config.ChrAddress;
@ -116,10 +123,11 @@ void Ppu::RenderTilemap(LayerConfig &config, uint8_t bpp)
color >>= 1; color >>= 1;
} }
uint16_t paletteRamOffset = color == 0 ? 0 : ((palette * (1 << bpp) + color) * 2); if(color > 0) {
uint16_t paletteRamOffset = (palette * (1 << bpp) + color) * 2;
uint16_t paletteColor = _cgram[paletteRamOffset] | (_cgram[paletteRamOffset + 1] << 8); uint16_t paletteColor = _cgram[paletteRamOffset] | (_cgram[paletteRamOffset + 1] << 8);
_currentBuffer[(y * 8 + i) * 256 + x * 8 + j] = paletteColor; _currentBuffer[(y * 8 + i) * 256 + x * 8 + j] = paletteColor;
}
} }
} }
addr+=2; addr+=2;
@ -129,42 +137,58 @@ void Ppu::RenderTilemap(LayerConfig &config, uint8_t bpp)
void Ppu::SendFrame() void Ppu::SendFrame()
{ {
uint16_t bgColor = _cgram[0] | (_cgram[1]);
for(int i = 0; i < 256 * 224; i++) {
_currentBuffer[i] = bgColor;
}
switch(_bgMode) { switch(_bgMode) {
case 0: case 0:
RenderTilemap(_layerConfig[3], 2); RenderTilemap(3, 2);
RenderTilemap(_layerConfig[2], 2); RenderTilemap(2, 2);
RenderTilemap(_layerConfig[1], 2); RenderTilemap(1, 2);
RenderTilemap(_layerConfig[0], 2); RenderTilemap(0, 2);
break; break;
case 1: case 1:
RenderTilemap(_layerConfig[2], 2); RenderTilemap(2, 2);
RenderTilemap(_layerConfig[1], 4); RenderTilemap(1, 4);
RenderTilemap(_layerConfig[0], 4); RenderTilemap(0, 4);
break; break;
case 2: case 2:
RenderTilemap(_layerConfig[1], 4); RenderTilemap(1, 4);
RenderTilemap(_layerConfig[0], 4); RenderTilemap(0, 4);
break; break;
case 3: case 3:
RenderTilemap(_layerConfig[1], 4); RenderTilemap(1, 4);
RenderTilemap(_layerConfig[0], 8); RenderTilemap(0, 8);
break; break;
case 5: case 5:
RenderTilemap(_layerConfig[1], 2); RenderTilemap(1, 2);
RenderTilemap(_layerConfig[0], 4); RenderTilemap(0, 4);
break; break;
case 6: case 6:
RenderTilemap(_layerConfig[0], 8); RenderTilemap(0, 8);
break; break;
} }
//Draw sprites //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]; uint8_t y = _oamRam[i + 1];
if(y >= 225) { if(y >= 225) {
continue; 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() uint8_t* Ppu::GetVideoRam()
@ -307,8 +327,8 @@ void Ppu::Write(uint32_t addr, uint8_t value)
case 0x210B: case 0x210C: case 0x210B: case 0x210C:
//BG1+2 / BG3+4 Chr Address (BG12NBA / BG34NBA) //BG1+2 / BG3+4 Chr Address (BG12NBA / BG34NBA)
_layerConfig[addr - 0x210B].ChrAddress = (value & 0x0F) << 12; _layerConfig[(addr - 0x210B) * 2].ChrAddress = (value & 0x0F) << 12;
_layerConfig[addr - 0x210B + 1].ChrAddress = (value & 0xF0) << 8; _layerConfig[(addr - 0x210B) * 2 + 1].ChrAddress = (value & 0xF0) << 8;
break; break;
case 0x2115: case 0x2115:
@ -361,6 +381,11 @@ void Ppu::Write(uint32_t addr, uint8_t value)
_cgramAddress = (_cgramAddress + 1) & (Ppu::CgRamSize - 1); _cgramAddress = (_cgramAddress + 1) & (Ppu::CgRamSize - 1);
break; break;
case 0x212C:
//TM - Main Screen Designation
_mainScreenLayers = value & 0x1F;
break;
default: default:
MessageManager::DisplayMessage("Debug", "Unimplemented register write: " + HexUtilities::ToHex(addr)); MessageManager::DisplayMessage("Debug", "Unimplemented register write: " + HexUtilities::ToHex(addr));
break; break;

View file

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