From f0bd82026457adc78fe5a64cb1f6433128f51552 Mon Sep 17 00:00:00 2001 From: Sour Date: Wed, 13 Feb 2019 23:03:01 -0500 Subject: [PATCH] PPU: Added barebones implementation of PPU/DMA to allow test roms to display their result on screen --- Core/Ppu.cpp | 82 +++++++++++++++++++++++++++++++++++++++++++++++----- Core/Ppu.h | 6 +++- 2 files changed, 80 insertions(+), 8 deletions(-) diff --git a/Core/Ppu.cpp b/Core/Ppu.cpp index 5537d1f..7eecd9f 100644 --- a/Core/Ppu.cpp +++ b/Core/Ppu.cpp @@ -1,7 +1,9 @@ #include "stdafx.h" #include "Ppu.h" #include "Console.h" +#include "MemoryManager.h" #include "Cpu.h" +#include "VideoDecoder.h" Ppu::Ppu(shared_ptr console) { @@ -64,12 +66,35 @@ void Ppu::Exec() void Ppu::SendFrame() { - for(int i = 0; i < 256 * 224; i++) { - _currentBuffer[i] = i; - } - _currentBuffer = _currentBuffer == _outputBuffers[0] ? _outputBuffers[1] : _outputBuffers[0]; + uint16_t tilemapAddr = _layerConfig[0].TilemapAddress; + uint16_t chrAddr = _layerConfig[0].ChrAddress; + + 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; - //_console->GetVideoDecoder()->SendFrame(_currentBuffer); + uint16_t tileStart = chrAddr + tileIndex * 8 * 2; + 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); + color >>= 1; + } + + uint16_t paletteColor = _cgram[(palette * 4 + color) * 2] | (_cgram[(palette * 4 + color) * 2 + 1] << 8); + _currentBuffer[(y * 8 + i) * 256 + x * 8 + j] = paletteColor; + } + } + } + } + + _currentBuffer = _currentBuffer == _outputBuffers[0] ? _outputBuffers[1] : _outputBuffers[0]; + _console->GetVideoDecoder()->UpdateFrame(_currentBuffer, _frameCount); } uint8_t Ppu::Read(uint16_t addr) @@ -95,7 +120,7 @@ void Ppu::Write(uint32_t addr, uint8_t value) switch(addr) { 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) << 8; + _layerConfig[addr - 0x2107].TilemapAddress = (value & 0xFC) << 9; _layerConfig[addr - 0x2107].HorizontalMirrorring = (value & 0x01) != 0; _layerConfig[addr - 0x2107].VerticalMirrorring = (value & 0x02) != 0; break; @@ -147,16 +172,59 @@ void Ppu::Write(uint32_t addr, uint8_t value) case 0x2121: //CGRAM Address(CGADD) - _cgramAddress = value; + _cgramAddress = value * 2; break; case 0x2122: //CGRAM Data write (CGDATA) _cgram[_cgramAddress] = value; + _cgramAddress++; break; case 0x4200: _enableNmi = (value & 0x80) != 0; break; + + case 0x420B: + //MDMAEN - DMA Enable + if(value & 0x01) { + for(int i = 0; i < _dmaSize; i++) { + uint8_t valToWrite = _console->GetMemoryManager()->Read(_dmaSource, MemoryOperationType::Read); + _console->GetMemoryManager()->Write(0x2100 | _dmaDest, valToWrite, MemoryOperationType::Write); + _dmaSource++; + } + } + break; + + case 0x4300: + //DMAPx - DMA Control for Channel x + break; + + case 0x4301: + //BBADx - DMA Destination Register for Channel x + _dmaDest = value; + break; + + case 0x4305: + //DASxL - DMA Size / HDMA Indirect Address low byte(x = 0 - 7) + _dmaSize = (_dmaSize & 0xFF00) | value; + break; + + case 0x4306: + //DASxL - DMA Size / HDMA Indirect Address low byte(x = 0 - 7) + _dmaSize = (_dmaSize & 0xFF) | (value << 8); + break; + + case 0x4302: + _dmaSource = (_dmaSource & 0xFFFF00) | value; + break; + + case 0x4303: + _dmaSource = (_dmaSource & 0xFF00FF) | (value << 8); + break; + + case 0x4304: + _dmaSource = (_dmaSource & 0x00FFFF) | (value << 16); + break; } } diff --git a/Core/Ppu.h b/Core/Ppu.h index 4d21022..6902713 100644 --- a/Core/Ppu.h +++ b/Core/Ppu.h @@ -22,13 +22,17 @@ private: bool _vramAddrIncrementOnSecondReg; uint16_t _cgramAddress; - uint16_t _cgram[256]; + uint8_t _cgram[512]; uint16_t *_outputBuffers[2]; uint16_t *_currentBuffer; LayerConfig _layerConfig[4]; + uint8_t _dmaDest = 0; + uint32_t _dmaSource = 0; + uint16_t _dmaSize = 0; + public: Ppu(shared_ptr console);