Mesen/Core/PPU.h

188 lines
3.4 KiB
C
Raw Normal View History

2014-06-14 15:27:55 +00:00
#pragma once
2014-06-14 14:12:10 +00:00
#include "stdafx.h"
2014-06-16 01:45:36 +00:00
#include "MemoryManager.h"
#include "IVideoDevice.h"
2014-06-14 14:12:10 +00:00
enum PPURegisters
{
Control = 0x00,
Mask = 0x01,
2014-06-14 14:12:10 +00:00
Status = 0x02,
SpriteAddr = 0x03,
SpriteData = 0x04,
ScrollOffsets = 0x05,
VideoMemoryAddr = 0x06,
VideoMemoryData = 0x07,
SpriteDMA = 0x4014,
2014-06-14 14:12:10 +00:00
};
2014-06-14 22:20:56 +00:00
struct PPUControlFlags
{
bool VerticalWrite;
uint16_t SpritePatternAddr;
uint16_t BackgroundPatternAddr;
bool LargeSprites;
bool VBlank;
bool Grayscale;
bool BackgroundMask;
bool SpriteMask;
bool BackgroundEnabled;
bool SpritesEnabled;
bool IntensifyRed;
bool IntensifyGreen;
bool IntensifyBlue;
};
struct PPUStatusFlags
{
bool SpriteOverflow;
bool Sprite0Hit;
bool VerticalBlank;
};
2014-06-14 14:12:10 +00:00
struct PPUState
{
2014-06-14 22:20:56 +00:00
uint8_t Control;
uint8_t Mask;
2014-06-14 14:12:10 +00:00
uint8_t Status;
uint32_t SpriteRamAddr;
2014-06-14 14:12:10 +00:00
uint16_t VideoRamAddr;
2014-06-17 22:16:49 +00:00
uint8_t XScroll;
uint16_t TmpVideoRamAddr;
bool WriteToggle;
uint16_t HighBitShift;
uint16_t LowBitShift;
};
struct TileInfo
{
uint8_t LowByte;
uint8_t HighByte;
uint8_t PaletteOffset;
};
struct SpriteInfo
{
uint8_t LowByte;
uint8_t HighByte;
uint8_t PaletteOffset;
bool HorizontalMirror;
bool BackgroundPriority;
2014-06-14 14:12:10 +00:00
};
class PPU : public IMemoryHandler
{
2014-06-14 15:27:55 +00:00
private:
static IVideoDevice *VideoDevice;
2014-06-16 01:45:36 +00:00
MemoryManager *_memoryManager;
2014-06-14 15:27:55 +00:00
PPUState _state;
int32_t _scanline = 0;
uint32_t _cycle = 0;
uint32_t _frameCount = 0;
uint64_t _cycleCount = 0;
uint8_t _memoryReadBuffer = 0;
2014-06-14 22:20:56 +00:00
uint8_t _paletteRAM[0x100];
uint8_t _spriteRAM[0x100];
2014-06-21 13:00:10 +00:00
uint8_t _secondarySpriteRAM[0x20];
2014-06-14 15:27:55 +00:00
2014-06-14 22:20:56 +00:00
uint8_t *_outputBuffer;
2014-06-15 13:35:17 +00:00
PPUControlFlags _flags;
PPUStatusFlags _statusFlags;
2014-06-14 22:20:56 +00:00
2014-06-21 04:37:27 +00:00
bool _doNotSetVBFlag = false;
TileInfo _currentTile;
TileInfo _nextTile;
TileInfo _previousTile;
int32_t _spriteX[8];
SpriteInfo _spriteTiles[8];
uint32_t _spriteCount = 0;
uint32_t _secondaryOAMAddr = 0;
bool _sprite0Visible = false;
2014-06-17 22:16:49 +00:00
void UpdateStatusFlag();
void SetControlRegister(uint8_t value);
void SetMaskRegister(uint8_t value);
2014-06-17 22:16:49 +00:00
bool CheckFlag(PPUControlFlags flag);
bool IsRenderingEnabled();
void UpdateVideoRamAddr();
2014-06-17 22:16:49 +00:00
void IncVerticalScrolling();
void IncHorizontalScrolling();
uint16_t GetNameTableAddr();
2014-06-17 22:16:49 +00:00
uint16_t GetAttributeAddr();
void ProcessPreVBlankScanline();
2014-06-17 22:16:49 +00:00
void ProcessPrerenderScanline();
void ProcessVisibleScanline();
2014-06-14 22:20:56 +00:00
void CopyOAMData();
2014-06-17 22:16:49 +00:00
void BeginVBlank();
void EndVBlank();
2014-06-14 22:20:56 +00:00
uint8_t GetBGPaletteEntry(uint8_t paletteOffset, uint8_t pixel);
uint8_t GetSpritePaletteEntry(uint8_t paletteOffset, uint8_t pixel);
uint8_t ReadPaletteRAM(uint16_t addr);
void WritePaletteRAM(uint16_t addr, uint8_t value);
void LoadTileInfo();
void LoadSpriteTileInfo(uint8_t spriteIndex);
void ShiftTileRegisters();
void InitializeShiftRegisters();
void LoadNextTile();
void DrawPixel();
void CopyFrame();
2014-06-14 15:27:55 +00:00
PPURegisters GetRegisterID(uint16_t addr)
{
if(addr == 0x4014) {
return PPURegisters::SpriteDMA;
} else {
return (PPURegisters)(addr & 0x07);
}
2014-06-14 14:12:10 +00:00
}
2014-06-14 15:27:55 +00:00
public:
2014-06-16 01:45:36 +00:00
PPU(MemoryManager *memoryManager);
2014-06-14 22:20:56 +00:00
~PPU();
2014-06-16 01:45:36 +00:00
vector<std::array<uint16_t, 2>> GetRAMAddresses()
{
return{ { { 0x2000, 0x3FFF } }, { {0x4014, 0x4014 } } };
2014-06-14 15:27:55 +00:00
}
2014-06-14 14:12:10 +00:00
2014-06-16 01:45:36 +00:00
uint8_t ReadRAM(uint16_t addr);
void WriteRAM(uint16_t addr, uint8_t value);
2014-06-14 22:20:56 +00:00
void Exec();
static void RegisterVideoDevice(IVideoDevice *videoDevice)
{
PPU::VideoDevice = videoDevice;
}
2014-06-22 12:38:42 +00:00
uint8_t* GetFrameBuffer()
{
return _outputBuffer;
}
uint32_t GetFrameCount()
{
return _frameCount;
}
};