PPU: Implement some of the registers
This commit is contained in:
parent
ca95636c37
commit
69cf69fa6f
8 changed files with 212 additions and 50 deletions
|
@ -43,13 +43,18 @@ void Console::LoadRom(VirtualFile romFile, VirtualFile patchFile)
|
||||||
|
|
||||||
shared_ptr<BaseCartridge> cart = BaseCartridge::CreateCartridge(romFile, patchFile);
|
shared_ptr<BaseCartridge> cart = BaseCartridge::CreateCartridge(romFile, patchFile);
|
||||||
if(cart) {
|
if(cart) {
|
||||||
_ppu.reset(new Ppu());
|
_ppu.reset(new Ppu(shared_from_this()));
|
||||||
_memoryManager.reset(new MemoryManager(cart, shared_from_this()));
|
_memoryManager.reset(new MemoryManager(cart, shared_from_this()));
|
||||||
_cpu.reset(new Cpu(_memoryManager));
|
_cpu.reset(new Cpu(_memoryManager));
|
||||||
_debugger.reset(new Debugger(_cpu, _ppu, _memoryManager));
|
_debugger.reset(new Debugger(_cpu, _ppu, _memoryManager));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shared_ptr<Cpu> Console::GetCpu()
|
||||||
|
{
|
||||||
|
return _cpu;
|
||||||
|
}
|
||||||
|
|
||||||
shared_ptr<Ppu> Console::GetPpu()
|
shared_ptr<Ppu> Console::GetPpu()
|
||||||
{
|
{
|
||||||
return _ppu;
|
return _ppu;
|
||||||
|
|
|
@ -26,6 +26,7 @@ public:
|
||||||
|
|
||||||
void LoadRom(VirtualFile romFile, VirtualFile patchFile);
|
void LoadRom(VirtualFile romFile, VirtualFile patchFile);
|
||||||
|
|
||||||
|
shared_ptr<Cpu> GetCpu();
|
||||||
shared_ptr<Ppu> GetPpu();
|
shared_ptr<Ppu> GetPpu();
|
||||||
shared_ptr<Debugger> GetDebugger(bool allowStart = true);
|
shared_ptr<Debugger> GetDebugger(bool allowStart = true);
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,7 @@
|
||||||
<ClCompile Include="DisassemblyInfo.cpp" />
|
<ClCompile Include="DisassemblyInfo.cpp" />
|
||||||
<ClCompile Include="KeyManager.cpp" />
|
<ClCompile Include="KeyManager.cpp" />
|
||||||
<ClCompile Include="MessageManager.cpp" />
|
<ClCompile Include="MessageManager.cpp" />
|
||||||
|
<ClCompile Include="Ppu.cpp" />
|
||||||
<ClCompile Include="stdafx.cpp">
|
<ClCompile Include="stdafx.cpp">
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='PGO Profile|Win32'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='PGO Profile|Win32'">Create</PrecompiledHeader>
|
||||||
|
|
|
@ -95,6 +95,9 @@
|
||||||
<ClCompile Include="Cpu.Instructions.cpp">
|
<ClCompile Include="Cpu.Instructions.cpp">
|
||||||
<Filter>SNES</Filter>
|
<Filter>SNES</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Ppu.cpp">
|
||||||
|
<Filter>SNES</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="SNES">
|
<Filter Include="SNES">
|
||||||
|
|
|
@ -130,8 +130,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i <= 0x3F; i++) {
|
for(int i = 0; i <= 0x3F; i++) {
|
||||||
RegisterHandler((i << 16) | 0x4000, (i << 16) | 0x5FFF, _cpuRegisterHandler.get());
|
RegisterHandler((i << 16) | 0x2000, (i << 16) | 0x2FFF, _cpuRegisterHandler.get());
|
||||||
RegisterHandler(((i | 0x80) << 16) | 0x4000, ((i | 0x80) << 16) | 0x5FFF, _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());
|
RegisterHandler(0x0000, 0x0FFF, _workRamHandlers[0].get());
|
||||||
|
|
162
Core/Ppu.cpp
Normal file
162
Core/Ppu.cpp
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Ppu.h"
|
||||||
|
#include "Console.h"
|
||||||
|
#include "Cpu.h"
|
||||||
|
|
||||||
|
Ppu::Ppu(shared_ptr<Console> 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;
|
||||||
|
}
|
||||||
|
}
|
72
Core/Ppu.h
72
Core/Ppu.h
|
@ -2,64 +2,42 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "PpuTypes.h"
|
#include "PpuTypes.h"
|
||||||
|
|
||||||
|
class Console;
|
||||||
|
|
||||||
class Ppu
|
class Ppu
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
shared_ptr<Console> _console;
|
||||||
|
|
||||||
uint16_t _cycle = 0;
|
uint16_t _cycle = 0;
|
||||||
uint16_t _scanline = 0;
|
uint16_t _scanline = 0;
|
||||||
uint32_t _frameCount = 0;
|
uint32_t _frameCount = 0;
|
||||||
bool _nmiFlag = false;
|
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:
|
public:
|
||||||
PpuState GetState()
|
Ppu(shared_ptr<Console> console);
|
||||||
{
|
|
||||||
return {
|
|
||||||
_cycle,
|
|
||||||
_scanline,
|
|
||||||
_frameCount
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void Exec()
|
PpuState GetState();
|
||||||
{
|
|
||||||
if(_cycle == 340) {
|
|
||||||
_cycle = 0;
|
|
||||||
_scanline++;
|
|
||||||
|
|
||||||
if(_scanline == 225) {
|
void Exec();
|
||||||
_nmiFlag = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(_scanline == 260) {
|
void SendFrame();
|
||||||
_nmiFlag = false;
|
|
||||||
_scanline = 0;
|
|
||||||
_frameCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_cycle++;
|
uint8_t Read(uint16_t addr);
|
||||||
}
|
void Write(uint32_t addr, uint8_t value);
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
};
|
|
@ -7,3 +7,12 @@ struct PpuState
|
||||||
uint16_t Scanline;
|
uint16_t Scanline;
|
||||||
uint32_t FrameCount;
|
uint32_t FrameCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LayerConfig
|
||||||
|
{
|
||||||
|
uint16_t TilemapAddress;
|
||||||
|
uint16_t ChrAddress;
|
||||||
|
|
||||||
|
bool HorizontalMirrorring;
|
||||||
|
bool VerticalMirrorring;
|
||||||
|
};
|
Loading…
Add table
Reference in a new issue