2014-06-14 15:27:55 +00:00
|
|
|
#pragma once
|
|
|
|
|
2014-06-14 14:12:10 +00:00
|
|
|
#include "stdafx.h"
|
2014-06-26 01:52:37 +00:00
|
|
|
#include "Snapshotable.h"
|
2014-06-16 01:45:36 +00:00
|
|
|
#include "MemoryManager.h"
|
2014-06-19 21:06:00 +00:00
|
|
|
#include "IVideoDevice.h"
|
2014-06-14 14:12:10 +00:00
|
|
|
|
|
|
|
enum PPURegisters
|
|
|
|
{
|
|
|
|
Control = 0x00,
|
2014-06-22 04:37:45 +00:00
|
|
|
Mask = 0x01,
|
2014-06-14 14:12:10 +00:00
|
|
|
Status = 0x02,
|
|
|
|
SpriteAddr = 0x03,
|
|
|
|
SpriteData = 0x04,
|
|
|
|
ScrollOffsets = 0x05,
|
|
|
|
VideoMemoryAddr = 0x06,
|
2014-06-21 01:48:55 +00:00
|
|
|
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;
|
2014-06-22 04:37:45 +00:00
|
|
|
uint8_t Mask;
|
2014-06-14 14:12:10 +00:00
|
|
|
uint8_t Status;
|
2014-06-21 01:48:55 +00:00
|
|
|
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;
|
2014-06-19 02:54:23 +00:00
|
|
|
|
|
|
|
uint16_t HighBitShift;
|
|
|
|
uint16_t LowBitShift;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct TileInfo
|
2014-06-21 16:42:40 +00:00
|
|
|
{
|
|
|
|
uint8_t LowByte;
|
|
|
|
uint8_t HighByte;
|
2014-06-22 20:22:10 +00:00
|
|
|
uint32_t PaletteOffset;
|
2014-06-21 16:42:40 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct SpriteInfo
|
2014-06-19 02:54:23 +00:00
|
|
|
{
|
|
|
|
uint8_t LowByte;
|
|
|
|
uint8_t HighByte;
|
2014-06-22 20:22:10 +00:00
|
|
|
uint32_t PaletteOffset;
|
2014-06-21 01:48:55 +00:00
|
|
|
bool HorizontalMirror;
|
2014-06-21 16:42:40 +00:00
|
|
|
bool BackgroundPriority;
|
2014-06-14 14:12:10 +00:00
|
|
|
};
|
|
|
|
|
2014-06-26 01:52:37 +00:00
|
|
|
class PPU : public IMemoryHandler, public Snapshotable
|
2014-06-14 14:12:10 +00:00
|
|
|
{
|
2014-06-14 15:27:55 +00:00
|
|
|
private:
|
2014-06-25 21:30:35 +00:00
|
|
|
static PPU* Instance;
|
2014-06-19 21:06:00 +00:00
|
|
|
static IVideoDevice *VideoDevice;
|
2014-06-19 02:54:23 +00:00
|
|
|
|
2014-06-16 01:45:36 +00:00
|
|
|
MemoryManager *_memoryManager;
|
|
|
|
|
2014-06-14 15:27:55 +00:00
|
|
|
PPUState _state;
|
2014-06-19 21:06:00 +00:00
|
|
|
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
|
|
|
|
2014-06-21 02:31:48 +00:00
|
|
|
uint8_t _paletteRAM[0x100];
|
|
|
|
|
2014-06-15 15:25:29 +00:00
|
|
|
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-19 21:06:00 +00:00
|
|
|
|
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;
|
|
|
|
|
2014-06-19 02:54:23 +00:00
|
|
|
TileInfo _currentTile;
|
|
|
|
TileInfo _nextTile;
|
2014-06-19 23:58:15 +00:00
|
|
|
TileInfo _previousTile;
|
2014-06-21 01:48:55 +00:00
|
|
|
|
|
|
|
int32_t _spriteX[8];
|
2014-06-21 16:42:40 +00:00
|
|
|
SpriteInfo _spriteTiles[8];
|
2014-06-22 05:54:35 +00:00
|
|
|
uint32_t _spriteCount = 0;
|
|
|
|
uint32_t _secondaryOAMAddr = 0;
|
2014-06-21 16:42:40 +00:00
|
|
|
bool _sprite0Visible = false;
|
2014-06-19 02:54:23 +00:00
|
|
|
|
2014-06-17 22:16:49 +00:00
|
|
|
void UpdateStatusFlag();
|
|
|
|
|
2014-06-22 04:37:45 +00:00
|
|
|
void SetControlRegister(uint8_t value);
|
|
|
|
void SetMaskRegister(uint8_t value);
|
2014-06-17 22:16:49 +00:00
|
|
|
bool CheckFlag(PPUControlFlags flag);
|
|
|
|
|
|
|
|
bool IsRenderingEnabled();
|
|
|
|
|
2014-06-22 04:37:45 +00:00
|
|
|
void UpdateVideoRamAddr();
|
2014-06-17 22:16:49 +00:00
|
|
|
void IncVerticalScrolling();
|
|
|
|
void IncHorizontalScrolling();
|
2014-06-19 23:58:15 +00:00
|
|
|
uint16_t GetNameTableAddr();
|
2014-06-17 22:16:49 +00:00
|
|
|
uint16_t GetAttributeAddr();
|
|
|
|
|
2014-06-21 01:48:55 +00:00
|
|
|
void ProcessPreVBlankScanline();
|
2014-06-17 22:16:49 +00:00
|
|
|
void ProcessPrerenderScanline();
|
|
|
|
void ProcessVisibleScanline();
|
2014-06-14 22:20:56 +00:00
|
|
|
|
2014-06-21 01:48:55 +00:00
|
|
|
void CopyOAMData();
|
|
|
|
|
2014-06-17 22:16:49 +00:00
|
|
|
void BeginVBlank();
|
|
|
|
void EndVBlank();
|
2014-06-14 22:20:56 +00:00
|
|
|
|
2014-06-22 20:22:10 +00:00
|
|
|
uint32_t GetBGPaletteEntry(uint32_t paletteOffset, uint32_t pixel);
|
|
|
|
uint32_t GetSpritePaletteEntry(uint32_t paletteOffset, uint32_t pixel);
|
2014-06-19 02:54:23 +00:00
|
|
|
|
2014-06-21 02:31:48 +00:00
|
|
|
uint8_t ReadPaletteRAM(uint16_t addr);
|
|
|
|
void WritePaletteRAM(uint16_t addr, uint8_t value);
|
|
|
|
|
2014-06-19 02:54:23 +00:00
|
|
|
void LoadTileInfo();
|
2014-06-21 01:48:55 +00:00
|
|
|
void LoadSpriteTileInfo(uint8_t spriteIndex);
|
2014-06-19 23:58:15 +00:00
|
|
|
void ShiftTileRegisters();
|
|
|
|
void InitializeShiftRegisters();
|
|
|
|
void LoadNextTile();
|
2014-06-19 02:54:23 +00:00
|
|
|
void DrawPixel();
|
|
|
|
|
|
|
|
void CopyFrame();
|
|
|
|
|
2014-06-14 15:27:55 +00:00
|
|
|
PPURegisters GetRegisterID(uint16_t addr)
|
|
|
|
{
|
2014-06-21 01:48:55 +00:00
|
|
|
if(addr == 0x4014) {
|
|
|
|
return PPURegisters::SpriteDMA;
|
|
|
|
} else {
|
|
|
|
return (PPURegisters)(addr & 0x07);
|
|
|
|
}
|
2014-06-14 14:12:10 +00:00
|
|
|
}
|
|
|
|
|
2014-06-26 01:52:37 +00:00
|
|
|
protected:
|
|
|
|
void StreamState(bool saving);
|
|
|
|
|
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-23 17:52:53 +00:00
|
|
|
void Reset();
|
|
|
|
|
2014-06-25 16:22:48 +00:00
|
|
|
void GetMemoryRanges(MemoryRanges &ranges)
|
2014-06-16 01:45:36 +00:00
|
|
|
{
|
2014-06-25 16:22:48 +00:00
|
|
|
ranges.AddHandler(MemoryType::RAM, MemoryOperation::Read, 0x2000, 0x3FFF);
|
|
|
|
ranges.AddHandler(MemoryType::RAM, MemoryOperation::Read, 0x4014);
|
|
|
|
ranges.AddHandler(MemoryType::RAM, MemoryOperation::Write, 0x2000, 0x3FFF);
|
|
|
|
ranges.AddHandler(MemoryType::RAM, MemoryOperation::Write, 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();
|
2014-06-19 02:54:23 +00:00
|
|
|
|
2014-06-19 21:06:00 +00:00
|
|
|
static void RegisterVideoDevice(IVideoDevice *videoDevice)
|
|
|
|
{
|
|
|
|
PPU::VideoDevice = videoDevice;
|
|
|
|
}
|
2014-06-19 02:54:23 +00:00
|
|
|
|
2014-06-22 12:38:42 +00:00
|
|
|
uint8_t* GetFrameBuffer()
|
|
|
|
{
|
|
|
|
return _outputBuffer;
|
|
|
|
}
|
|
|
|
|
2014-06-19 02:54:23 +00:00
|
|
|
uint32_t GetFrameCount()
|
|
|
|
{
|
|
|
|
return _frameCount;
|
|
|
|
}
|
2014-06-25 21:30:35 +00:00
|
|
|
|
|
|
|
static uint32_t GetCurrentCycle()
|
|
|
|
{
|
|
|
|
return PPU::Instance->_cycle;
|
|
|
|
}
|
2014-06-19 02:54:23 +00:00
|
|
|
};
|