From 06814198419570cecb5430e96d4ba5b9ac63d03c Mon Sep 17 00:00:00 2001 From: Sour Date: Sun, 17 Feb 2019 00:32:41 -0500 Subject: [PATCH] PPU: Added very basic support for other display modes --- Core/Ppu.cpp | 72 ++++++++++++++++++++++++++++++++++++++++--------- Core/Ppu.h | 8 +++--- Core/PpuTypes.h | 2 ++ 3 files changed, 66 insertions(+), 16 deletions(-) diff --git a/Core/Ppu.cpp b/Core/Ppu.cpp index 079f888..868b30a 100644 --- a/Core/Ppu.cpp +++ b/Core/Ppu.cpp @@ -74,37 +74,74 @@ void Ppu::Exec() _cycle++; } -void Ppu::SendFrame() +void Ppu::RenderTilemap(LayerConfig &config, uint8_t bpp) { - uint16_t tilemapAddr = _layerConfig[0].TilemapAddress; - uint16_t chrAddr = _layerConfig[0].ChrAddress; + uint16_t tilemapAddr = config.TilemapAddress; + uint16_t chrAddr = config.ChrAddress; + uint32_t addr = tilemapAddr; for(int y = 0; y < 28; y++) { for(int x = 0; x < 32; x++) { - uint8_t byte1 = _vram[tilemapAddr + (y * 32 + x) * 2]; - uint8_t byte2 = _vram[tilemapAddr + (y * 32 + x) * 2 + 1]; - - uint8_t palette = (byte2 >> 2) & 0x07; - uint16_t tileIndex = ((byte2 & 0x03) << 8) | byte1; + uint8_t palette = (_vram[addr + 1] >> 2) & 0x07; + uint16_t tileIndex = ((_vram[addr + 1] & 0x03) << 8) | _vram[addr]; - uint16_t tileStart = chrAddr + tileIndex * 8 * 2; + uint16_t tileStart = chrAddr + tileIndex * 8 * bpp; for(int i = 0; i < 8; i++) { for(int j = 0; j < 8; j++) { - uint8_t color = 0; - for(int plane = 0; plane < 2; plane++) { - color |= (((_vram[tileStart + i * 2 + plane] >> (7 - j)) & 0x01) << 2); + uint16_t color = 0; + for(int plane = 0; plane < bpp; plane++) { + uint8_t offset = (plane >> 1) * 16; + color |= (((_vram[tileStart + i * 2 + offset + (plane & 0x01)] >> (7 - j)) & 0x01) << bpp); color >>= 1; } - uint16_t paletteRamOffset = color == 0 ? 0 : ((palette * 4 + color) * 2); + 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; } } + addr+=2; } } +} +void Ppu::SendFrame() +{ + switch(_bgMode) { + case 0: + RenderTilemap(_layerConfig[3], 2); + RenderTilemap(_layerConfig[2], 2); + RenderTilemap(_layerConfig[1], 2); + RenderTilemap(_layerConfig[0], 2); + break; + + case 1: + RenderTilemap(_layerConfig[2], 2); + RenderTilemap(_layerConfig[1], 4); + RenderTilemap(_layerConfig[0], 4); + break; + + case 2: + RenderTilemap(_layerConfig[1], 4); + RenderTilemap(_layerConfig[0], 4); + break; + + case 3: + RenderTilemap(_layerConfig[1], 4); + RenderTilemap(_layerConfig[0], 8); + break; + + case 5: + RenderTilemap(_layerConfig[1], 2); + RenderTilemap(_layerConfig[0], 4); + break; + + case 6: + RenderTilemap(_layerConfig[0], 8); + break; + } + _console->GetNotificationManager()->SendNotification(ConsoleNotificationType::PpuFrameDone); _currentBuffer = _currentBuffer == _outputBuffers[0] ? _outputBuffers[1] : _outputBuffers[0]; _console->GetVideoDecoder()->UpdateFrame(_currentBuffer, _frameCount); @@ -145,6 +182,15 @@ uint8_t Ppu::Read(uint16_t addr) void Ppu::Write(uint32_t addr, uint8_t value) { switch(addr) { + case 0x2105: + _bgMode = value & 0x07; + //_mode1Bg3Priority = (value & 0x08) != 0; + _layerConfig[0].LargeTiles = (value & 0x10) != 0; + _layerConfig[1].LargeTiles = (value & 0x20) != 0; + _layerConfig[2].LargeTiles = (value & 0x30) != 0; + _layerConfig[3].LargeTiles = (value & 0x40) != 0; + break; + case 0x2107: case 0x2108: case 0x2109: case 0x210A: //BG 1-4 Tilemap Address and Size (BG1SC, BG2SC, BG3SC, BG4SC) _layerConfig[addr - 0x2107].TilemapAddress = (value & 0xFC) << 9; diff --git a/Core/Ppu.h b/Core/Ppu.h index 3d729f0..2f637b9 100644 --- a/Core/Ppu.h +++ b/Core/Ppu.h @@ -19,7 +19,10 @@ private: uint32_t _frameCount = 0; bool _nmiFlag = false; bool _enableNmi = false; - + + uint8_t _bgMode = 0; + LayerConfig _layerConfig[4]; + uint8_t *_vram; uint16_t _vramAddress; uint8_t _vramIncrementValue; @@ -34,8 +37,7 @@ private: uint16_t *_outputBuffers[2]; uint16_t *_currentBuffer; - LayerConfig _layerConfig[4]; - + void RenderTilemap(LayerConfig & config, uint8_t bpp); public: Ppu(shared_ptr console); diff --git a/Core/PpuTypes.h b/Core/PpuTypes.h index 964b331..a0fa719 100644 --- a/Core/PpuTypes.h +++ b/Core/PpuTypes.h @@ -15,4 +15,6 @@ struct LayerConfig bool HorizontalMirrorring; bool VerticalMirrorring; + + bool LargeTiles; }; \ No newline at end of file