From 69cf69fa6fcb822d809e70a1b8dc2f9ce4c13ce1 Mon Sep 17 00:00:00 2001 From: Sour Date: Wed, 13 Feb 2019 18:44:39 -0500 Subject: [PATCH] PPU: Implement some of the registers --- Core/Console.cpp | 7 +- Core/Console.h | 1 + Core/Core.vcxproj | 1 + Core/Core.vcxproj.filters | 3 + Core/MemoryManager.h | 7 +- Core/Ppu.cpp | 162 ++++++++++++++++++++++++++++++++++++++ Core/Ppu.h | 72 ++++++----------- Core/PpuTypes.h | 9 +++ 8 files changed, 212 insertions(+), 50 deletions(-) create mode 100644 Core/Ppu.cpp diff --git a/Core/Console.cpp b/Core/Console.cpp index e127fcd..abfe6fc 100644 --- a/Core/Console.cpp +++ b/Core/Console.cpp @@ -43,13 +43,18 @@ void Console::LoadRom(VirtualFile romFile, VirtualFile patchFile) shared_ptr cart = BaseCartridge::CreateCartridge(romFile, patchFile); if(cart) { - _ppu.reset(new Ppu()); + _ppu.reset(new Ppu(shared_from_this())); _memoryManager.reset(new MemoryManager(cart, shared_from_this())); _cpu.reset(new Cpu(_memoryManager)); _debugger.reset(new Debugger(_cpu, _ppu, _memoryManager)); } } +shared_ptr Console::GetCpu() +{ + return _cpu; +} + shared_ptr Console::GetPpu() { return _ppu; diff --git a/Core/Console.h b/Core/Console.h index 2650943..51a08f0 100644 --- a/Core/Console.h +++ b/Core/Console.h @@ -26,6 +26,7 @@ public: void LoadRom(VirtualFile romFile, VirtualFile patchFile); + shared_ptr GetCpu(); shared_ptr GetPpu(); shared_ptr GetDebugger(bool allowStart = true); diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 7d28bb2..d6d66c4 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -75,6 +75,7 @@ + Create Create diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 2275cae..29d593c 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -95,6 +95,9 @@ SNES + + SNES + diff --git a/Core/MemoryManager.h b/Core/MemoryManager.h index 9f8f860..639d736 100644 --- a/Core/MemoryManager.h +++ b/Core/MemoryManager.h @@ -130,8 +130,11 @@ public: } for(int i = 0; i <= 0x3F; i++) { - RegisterHandler((i << 16) | 0x4000, (i << 16) | 0x5FFF, _cpuRegisterHandler.get()); - RegisterHandler(((i | 0x80) << 16) | 0x4000, ((i | 0x80) << 16) | 0x5FFF, _cpuRegisterHandler.get()); + RegisterHandler((i << 16) | 0x2000, (i << 16) | 0x2FFF, _cpuRegisterHandler.get()); + RegisterHandler(((i | 0x80) << 16) | 0x2000, ((i | 0x80) << 16) | 0x2FFF, _cpuRegisterHandler.get()); + + RegisterHandler((i << 16) | 0x4000, (i << 16) | 0x4FFF, _cpuRegisterHandler.get()); + RegisterHandler(((i | 0x80) << 16) | 0x4000, ((i | 0x80) << 16) | 0x4FFF, _cpuRegisterHandler.get()); } RegisterHandler(0x0000, 0x0FFF, _workRamHandlers[0].get()); diff --git a/Core/Ppu.cpp b/Core/Ppu.cpp new file mode 100644 index 0000000..5537d1f --- /dev/null +++ b/Core/Ppu.cpp @@ -0,0 +1,162 @@ +#include "stdafx.h" +#include "Ppu.h" +#include "Console.h" +#include "Cpu.h" + +Ppu::Ppu(shared_ptr console) +{ + _console = console; + + _vram = new uint8_t[0x10000]; + memset(_vram, 0, 0x10000); + + _layerConfig[0] = {}; + _layerConfig[1] = {}; + _layerConfig[2] = {}; + _layerConfig[3] = {}; + + _outputBuffers[0] = new uint16_t[256 * 224]; + _outputBuffers[1] = new uint16_t[256 * 224]; + + _currentBuffer = _outputBuffers[0]; + + _cgramAddress = 0; + + _vramAddress = 0; + _vramIncrementValue = 1; + _vramAddressRemapping = 0; + _vramAddrIncrementOnSecondReg = false; +} + +PpuState Ppu::GetState() +{ + return { + _cycle, + _scanline, + _frameCount + }; +} + +void Ppu::Exec() +{ + if(_cycle == 340) { + _cycle = 0; + _scanline++; + + if(_scanline == 225) { + _nmiFlag = true; + SendFrame(); + + if(_enableNmi) { + _console->GetCpu()->SetNmiFlag(); + } + } + + if(_scanline == 260) { + _nmiFlag = false; + _scanline = 0; + _frameCount++; + } + } + + _cycle++; +} + +void Ppu::SendFrame() +{ + for(int i = 0; i < 256 * 224; i++) { + _currentBuffer[i] = i; + } + _currentBuffer = _currentBuffer == _outputBuffers[0] ? _outputBuffers[1] : _outputBuffers[0]; + + //_console->GetVideoDecoder()->SendFrame(_currentBuffer); +} + +uint8_t Ppu::Read(uint16_t addr) +{ + switch(addr) { + case 0x4210: + return _nmiFlag ? 0x80 : 0; + break; + + case 0x4212: + return ( + (_scanline >= 225 ? 0x80 : 0) || + ((_cycle >= 0x121 || _cycle <= 0x15) ? 0x40 : 0) + ); + break; + } + + return 0; +} + +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].HorizontalMirrorring = (value & 0x01) != 0; + _layerConfig[addr - 0x2107].VerticalMirrorring = (value & 0x02) != 0; + break; + + 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; + break; + + case 0x2115: + //VMAIN - Video Port Control + switch(value & 0x03) { + case 0: _vramIncrementValue = 1; break; + case 1: _vramIncrementValue = 32; break; + + case 2: + case 3: _vramIncrementValue = 128; break; + } + _vramAddressRemapping = (value & 0x0C) >> 2; + _vramAddrIncrementOnSecondReg = (value & 0x80) != 0; + break; + + case 0x2116: + //VMADDL - VRAM Address low byte + _vramAddress = (_vramAddress & 0xFF00) | value; + break; + + case 0x2117: + //VMADDH - VRAM Address high byte + _vramAddress = (_vramAddress & 0x00FF) | (value << 8); + break; + + case 0x2118: + //VMDATAL - VRAM Data Write low byte + _vram[_vramAddress << 1] = value; + if(!_vramAddrIncrementOnSecondReg) { + _vramAddress += _vramIncrementValue; + } + break; + + case 0x2119: + //VMDATAH - VRAM Data Write high byte + _vram[(_vramAddress << 1) + 1] = value; + if(_vramAddrIncrementOnSecondReg) { + _vramAddress += _vramIncrementValue; + } + break; + + case 0x2121: + //CGRAM Address(CGADD) + _cgramAddress = value; + break; + + case 0x2122: + //CGRAM Data write (CGDATA) + _cgram[_cgramAddress] = value; + break; + + case 0x4200: + _enableNmi = (value & 0x80) != 0; + break; + } +} diff --git a/Core/Ppu.h b/Core/Ppu.h index cc16bb3..4d21022 100644 --- a/Core/Ppu.h +++ b/Core/Ppu.h @@ -2,64 +2,42 @@ #include "stdafx.h" #include "PpuTypes.h" +class Console; + class Ppu { private: + shared_ptr _console; + uint16_t _cycle = 0; uint16_t _scanline = 0; uint32_t _frameCount = 0; bool _nmiFlag = false; + bool _enableNmi = false; + + uint8_t *_vram; + uint16_t _vramAddress; + uint8_t _vramIncrementValue; + uint8_t _vramAddressRemapping; + bool _vramAddrIncrementOnSecondReg; + + uint16_t _cgramAddress; + uint16_t _cgram[256]; + + uint16_t *_outputBuffers[2]; + uint16_t *_currentBuffer; + + LayerConfig _layerConfig[4]; public: - PpuState GetState() - { - return { - _cycle, - _scanline, - _frameCount - }; - } + Ppu(shared_ptr console); - void Exec() - { - if(_cycle == 340) { - _cycle = 0; - _scanline++; + PpuState GetState(); - if(_scanline == 225) { - _nmiFlag = true; - } + void Exec(); - if(_scanline == 260) { - _nmiFlag = false; - _scanline = 0; - _frameCount++; - } - } + void SendFrame(); - _cycle++; - } - - uint8_t Read(uint16_t addr) - { - switch(addr) { - case 0x4210: - return _nmiFlag ? 0x80 : 0; - break; - - case 0x4212: - return ( - (_scanline >= 225 ? 0x80 : 0) || - ((_cycle >= 0x121 || _cycle <= 0x15) ? 0x40 : 0) - ); - break; - } - - return 0; - } - - void Write(uint32_t addr, uint8_t value) - { - - } + uint8_t Read(uint16_t addr); + void Write(uint32_t addr, uint8_t value); }; \ No newline at end of file diff --git a/Core/PpuTypes.h b/Core/PpuTypes.h index 5305c51..964b331 100644 --- a/Core/PpuTypes.h +++ b/Core/PpuTypes.h @@ -7,3 +7,12 @@ struct PpuState uint16_t Scanline; uint32_t FrameCount; }; + +struct LayerConfig +{ + uint16_t TilemapAddress; + uint16_t ChrAddress; + + bool HorizontalMirrorring; + bool VerticalMirrorring; +}; \ No newline at end of file