2019-02-13 13:32:21 -05:00
|
|
|
#pragma once
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "PpuTypes.h"
|
2019-03-12 09:15:57 -04:00
|
|
|
#include "../Utilities/ISerializable.h"
|
2019-02-13 13:32:21 -05:00
|
|
|
|
2019-02-13 18:44:39 -05:00
|
|
|
class Console;
|
2019-02-17 15:37:31 -05:00
|
|
|
class InternalRegisters;
|
2019-04-20 11:46:51 -04:00
|
|
|
class MemoryManager;
|
2019-02-13 18:44:39 -05:00
|
|
|
|
2019-03-12 09:15:57 -04:00
|
|
|
class Ppu : public ISerializable
|
2019-02-13 13:32:21 -05:00
|
|
|
{
|
2019-02-15 21:33:13 -05:00
|
|
|
public:
|
|
|
|
constexpr static uint32_t SpriteRamSize = 544;
|
|
|
|
constexpr static uint32_t CgRamSize = 512;
|
|
|
|
constexpr static uint32_t VideoRamSize = 0x10000;
|
|
|
|
|
2019-02-13 13:32:21 -05:00
|
|
|
private:
|
2019-02-22 20:15:55 -05:00
|
|
|
constexpr static int SpriteLayerIndex = 4;
|
2019-02-22 22:19:20 -05:00
|
|
|
constexpr static int ColorWindowIndex = 5;
|
2019-02-22 20:15:55 -05:00
|
|
|
|
2019-02-13 18:44:39 -05:00
|
|
|
shared_ptr<Console> _console;
|
2019-02-17 15:37:31 -05:00
|
|
|
shared_ptr<InternalRegisters> _regs;
|
2019-04-20 11:46:51 -04:00
|
|
|
shared_ptr<MemoryManager> _memoryManager;
|
2019-02-13 18:44:39 -05:00
|
|
|
|
2019-07-07 18:18:20 -04:00
|
|
|
LayerData _layerData[4];
|
|
|
|
uint16_t _hOffset = 0;
|
|
|
|
uint16_t _vOffset = 0;
|
|
|
|
uint16_t _fetchStartX = 0;
|
|
|
|
uint16_t _fetchEndX = 0;
|
|
|
|
|
2019-02-19 18:01:27 -05:00
|
|
|
bool _forcedVblank = false;
|
|
|
|
uint8_t _screenBrightness = 0;
|
|
|
|
|
2019-02-13 13:32:21 -05:00
|
|
|
uint16_t _scanline = 0;
|
|
|
|
uint32_t _frameCount = 0;
|
2019-04-10 16:04:55 -04:00
|
|
|
uint16_t _vblankStart;
|
2019-04-08 10:16:12 -04:00
|
|
|
uint8_t _oddFrame = 0;
|
2019-03-04 17:49:14 -05:00
|
|
|
|
2019-03-07 20:13:44 -05:00
|
|
|
uint16_t _drawStartX = 0;
|
|
|
|
uint16_t _drawEndX = 0;
|
2019-02-17 01:09:47 -05:00
|
|
|
|
2019-02-17 00:32:41 -05:00
|
|
|
uint8_t _bgMode = 0;
|
2019-02-19 01:26:48 -05:00
|
|
|
bool _mode1Bg3Priority = false;
|
2019-02-17 23:26:49 -05:00
|
|
|
|
|
|
|
uint8_t _mainScreenLayers = 0;
|
2019-02-19 01:26:48 -05:00
|
|
|
uint8_t _subScreenLayers = 0;
|
2019-06-29 09:16:53 -04:00
|
|
|
LayerConfig _layerConfig[4] = {};
|
2019-02-22 20:15:55 -05:00
|
|
|
|
2019-06-29 09:16:53 -04:00
|
|
|
WindowConfig _window[2] = {};
|
|
|
|
WindowMaskLogic _maskLogic[6] = {};
|
|
|
|
bool _windowMaskMain[5] = {};
|
|
|
|
bool _windowMaskSub[5] = {};
|
2019-02-23 15:40:32 -05:00
|
|
|
|
2019-06-29 09:16:53 -04:00
|
|
|
Mode7Config _mode7 = {};
|
2019-02-17 00:32:41 -05:00
|
|
|
|
2019-06-29 09:16:53 -04:00
|
|
|
uint8_t *_vram = nullptr;
|
|
|
|
uint16_t _vramAddress = 0;
|
|
|
|
uint8_t _vramIncrementValue = 0;
|
|
|
|
uint8_t _vramAddressRemapping = 0;
|
|
|
|
bool _vramAddrIncrementOnSecondReg = 0;
|
2019-02-24 09:38:22 -05:00
|
|
|
uint16_t _vramReadBuffer = 0;
|
2019-02-13 18:44:39 -05:00
|
|
|
|
2019-03-09 10:29:19 -05:00
|
|
|
uint8_t _ppu1OpenBus = 0;
|
|
|
|
uint8_t _ppu2OpenBus = 0;
|
|
|
|
|
2019-06-29 09:16:53 -04:00
|
|
|
uint16_t _cgramAddress = 0;
|
|
|
|
uint8_t _cgramWriteBuffer = 0;
|
|
|
|
uint8_t _cgram[Ppu::CgRamSize] = {};
|
2019-02-15 21:33:13 -05:00
|
|
|
|
2019-06-29 09:16:53 -04:00
|
|
|
uint16_t *_outputBuffers[2] = {};
|
|
|
|
uint16_t *_currentBuffer = nullptr;
|
2019-07-06 14:03:27 -04:00
|
|
|
bool _useHighResOutput = false;
|
2019-02-19 23:35:43 -05:00
|
|
|
|
2019-03-02 00:11:42 -05:00
|
|
|
SpriteInfo _sprites[33] = {};
|
2019-02-19 23:37:27 -05:00
|
|
|
uint8_t _spriteCount = 0;
|
|
|
|
uint8_t _spritePriority[256] = {};
|
|
|
|
uint8_t _spritePalette[256] = {};
|
|
|
|
uint16_t _spritePixels[256] = {};
|
|
|
|
|
2019-02-21 22:40:08 -05:00
|
|
|
uint16_t _pixelsDrawn = 0;
|
|
|
|
uint16_t _subPixelsDrawn = 0;
|
|
|
|
|
2019-06-29 09:16:53 -04:00
|
|
|
uint8_t _rowPixelFlags[256] = {};
|
|
|
|
uint16_t _mainScreenBuffer[256] = {};
|
2019-02-13 13:32:21 -05:00
|
|
|
|
2019-06-29 09:16:53 -04:00
|
|
|
bool _subScreenFilled[256] = {};
|
|
|
|
uint16_t _subScreenBuffer[256] = {};
|
2019-02-19 01:26:48 -05:00
|
|
|
|
2019-07-08 09:13:08 -04:00
|
|
|
uint8_t _mosaicColor[4] = {};
|
2019-02-20 17:39:14 -05:00
|
|
|
uint8_t _mosaicSize = 0;
|
|
|
|
uint8_t _mosaicEnabled = 0;
|
|
|
|
uint16_t _mosaicStartScanline = 0;
|
|
|
|
|
2019-02-17 21:09:33 -05:00
|
|
|
uint8_t _oamMode = 0;
|
2019-02-17 22:44:57 -05:00
|
|
|
uint16_t _oamBaseAddress = 0;
|
|
|
|
uint16_t _oamAddressOffset = 0;
|
2019-02-17 21:09:33 -05:00
|
|
|
|
2019-06-29 09:16:53 -04:00
|
|
|
uint8_t _oamRam[Ppu::SpriteRamSize] = {};
|
2019-02-17 21:09:33 -05:00
|
|
|
uint16_t _oamRamAddress = 0;
|
|
|
|
bool _enableOamPriority = false;
|
|
|
|
|
2019-04-04 20:46:29 -04:00
|
|
|
uint16_t _oamRenderAddress = 0;
|
2019-02-17 21:09:33 -05:00
|
|
|
uint16_t _internalOamAddress = 0;
|
|
|
|
uint8_t _oamWriteBuffer = 0;
|
|
|
|
|
2019-02-19 18:01:27 -05:00
|
|
|
bool _timeOver = false;
|
|
|
|
bool _rangeOver = false;
|
|
|
|
|
2019-02-24 11:14:24 -05:00
|
|
|
bool _hiResMode = false;
|
2019-02-23 21:39:35 -05:00
|
|
|
bool _screenInterlace = false;
|
2019-02-24 19:21:19 -05:00
|
|
|
bool _objInterlace = false;
|
2019-02-23 21:39:35 -05:00
|
|
|
bool _overscanMode = false;
|
2019-02-18 22:27:22 -05:00
|
|
|
bool _directColorMode = false;
|
|
|
|
|
2019-02-22 22:19:20 -05:00
|
|
|
ColorWindowMode _colorMathClipMode = ColorWindowMode::Never;
|
|
|
|
ColorWindowMode _colorMathPreventMode = ColorWindowMode::Never;
|
2019-02-17 23:53:19 -05:00
|
|
|
bool _colorMathAddSubscreen = false;
|
|
|
|
uint8_t _colorMathEnabled = 0;
|
|
|
|
bool _colorMathSubstractMode = false;
|
|
|
|
bool _colorMathHalveResult = false;
|
2019-02-19 23:35:43 -05:00
|
|
|
uint16_t _fixedColor = 0;
|
2019-02-17 23:53:19 -05:00
|
|
|
|
2019-02-19 17:23:21 -05:00
|
|
|
uint8_t _hvScrollLatchValue = 0;
|
|
|
|
uint8_t _hScrollLatchValue = 0;
|
|
|
|
|
2019-02-21 07:27:47 -05:00
|
|
|
uint16_t _horizontalLocation = 0;
|
|
|
|
bool _horizontalLocToggle = false;
|
|
|
|
uint16_t _verticalLocation = 0;
|
|
|
|
bool _verticalLocationToggle = false;
|
2019-02-21 18:11:31 -05:00
|
|
|
bool _locationLatched = false;
|
2019-02-21 07:27:47 -05:00
|
|
|
|
2019-04-10 22:32:28 -04:00
|
|
|
bool _allowFrameSkip = false;
|
2019-05-20 15:35:09 -04:00
|
|
|
uint8_t _configVisibleLayers = 0xFF;
|
2019-04-10 22:32:28 -04:00
|
|
|
|
2019-02-19 01:26:48 -05:00
|
|
|
template<uint8_t priority, bool forMainScreen>
|
2019-02-22 18:41:43 -05:00
|
|
|
void RenderSprites();
|
|
|
|
|
2019-07-07 18:18:20 -04:00
|
|
|
template<bool hiResMode>
|
|
|
|
void GetTilemapData(uint8_t layerIndex, uint8_t columnIndex);
|
|
|
|
|
|
|
|
template<bool hiResMode, uint8_t bpp, bool secondTile = false>
|
|
|
|
void GetChrData(uint8_t layerIndex, uint8_t column, uint8_t plane);
|
|
|
|
|
|
|
|
void GetHorizontalOffsetByte(uint8_t columnIndex);
|
|
|
|
void GetVerticalOffsetByte(uint8_t columnIndex);
|
|
|
|
void FetchTileData();
|
|
|
|
|
2019-02-24 01:11:26 -05:00
|
|
|
template<bool forMainScreen> void RenderMode0();
|
|
|
|
template<bool forMainScreen> void RenderMode1();
|
|
|
|
template<bool forMainScreen> void RenderMode2();
|
|
|
|
template<bool forMainScreen> void RenderMode3();
|
|
|
|
template<bool forMainScreen> void RenderMode4();
|
|
|
|
template<bool forMainScreen> void RenderMode5();
|
2019-02-24 10:30:19 -05:00
|
|
|
template<bool forMainScreen> void RenderMode6();
|
2019-02-24 01:11:26 -05:00
|
|
|
template<bool forMainScreen> void RenderMode7();
|
2019-02-22 18:41:43 -05:00
|
|
|
|
2019-02-23 21:39:35 -05:00
|
|
|
template<bool forMainScreen>
|
2019-02-24 01:11:26 -05:00
|
|
|
void RenderBgColor();
|
2019-02-23 21:39:35 -05:00
|
|
|
|
2019-02-24 01:11:26 -05:00
|
|
|
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, uint16_t basePaletteOffset = 0>
|
|
|
|
__forceinline void RenderTilemap();
|
2019-02-24 11:14:24 -05:00
|
|
|
|
|
|
|
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, uint16_t basePaletteOffset, bool hiResMode>
|
|
|
|
__forceinline void RenderTilemap();
|
2019-02-23 15:40:32 -05:00
|
|
|
|
2019-07-07 18:18:20 -04:00
|
|
|
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, uint16_t basePaletteOffset, bool hiResMode, uint8_t activeWindowCount>
|
2019-02-24 01:11:26 -05:00
|
|
|
__forceinline void RenderTilemap();
|
2019-02-22 22:35:53 -05:00
|
|
|
|
2019-07-07 18:18:20 -04:00
|
|
|
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, uint16_t basePaletteOffset, bool hiResMode, uint8_t activeWindowCount, bool applyMosaic>
|
2019-02-24 01:11:26 -05:00
|
|
|
__forceinline void RenderTilemap();
|
2019-02-22 22:35:53 -05:00
|
|
|
|
2019-07-07 18:18:20 -04:00
|
|
|
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, uint16_t basePaletteOffset, bool hiResMode, uint8_t activeWindowCount, bool applyMosaic, bool directColorMode>
|
2019-02-22 22:35:53 -05:00
|
|
|
void RenderTilemap();
|
|
|
|
|
2019-02-24 01:30:55 -05:00
|
|
|
template<bool forMainScreen>
|
|
|
|
__forceinline bool IsRenderRequired(uint8_t layerIndex);
|
|
|
|
|
2019-07-07 18:18:20 -04:00
|
|
|
template<uint8_t bpp>
|
|
|
|
uint8_t GetTilePixelColor(const uint16_t chrData[4], const uint8_t shift);
|
|
|
|
|
2019-02-24 01:30:55 -05:00
|
|
|
template<uint8_t bpp>
|
|
|
|
__forceinline uint16_t GetTilePixelColor(const uint16_t pixelStart, const uint8_t shift);
|
|
|
|
|
2019-02-24 01:11:26 -05:00
|
|
|
template<uint8_t layerIndex, bool forMainScreen, bool processHighPriority>
|
|
|
|
__forceinline void RenderTilemapMode7();
|
|
|
|
|
|
|
|
template<uint8_t layerIndex, bool forMainScreen, bool processHighPriority, bool applyMosaic>
|
|
|
|
__forceinline void RenderTilemapMode7();
|
2019-02-23 01:28:41 -05:00
|
|
|
|
2019-02-24 01:11:26 -05:00
|
|
|
template<uint8_t layerIndex, bool forMainScreen, bool processHighPriority, bool applyMosaic, bool directColorMode>
|
2019-02-23 15:40:32 -05:00
|
|
|
void RenderTilemapMode7();
|
|
|
|
|
2019-02-24 01:11:26 -05:00
|
|
|
__forceinline void DrawMainPixel(uint8_t x, uint16_t color, uint8_t flags);
|
|
|
|
__forceinline void DrawSubPixel(uint8_t x, uint16_t color);
|
2019-02-23 15:40:32 -05:00
|
|
|
|
2019-02-19 01:26:48 -05:00
|
|
|
void ApplyColorMath();
|
2019-04-02 23:44:00 -04:00
|
|
|
void ApplyColorMathToPixel(uint16_t &pixelA, uint16_t pixelB, int x, bool isInsideWindow);
|
2019-02-23 21:39:35 -05:00
|
|
|
|
|
|
|
template<bool forMainScreen>
|
2019-02-22 22:31:20 -05:00
|
|
|
void ApplyBrightness();
|
2019-02-22 20:15:55 -05:00
|
|
|
|
2019-07-06 14:03:27 -04:00
|
|
|
void ConvertToHiRes();
|
2019-02-23 21:39:35 -05:00
|
|
|
void ApplyHiResMode();
|
|
|
|
|
2019-02-22 20:15:55 -05:00
|
|
|
template<uint8_t layerIndex>
|
|
|
|
bool ProcessMaskWindow(uint8_t activeWindowCount, int x);
|
|
|
|
void ProcessWindowMaskSettings(uint8_t value, uint8_t offset);
|
|
|
|
|
2019-02-24 09:38:22 -05:00
|
|
|
void UpdateVramReadBuffer();
|
2019-03-01 22:24:18 -05:00
|
|
|
uint16_t GetVramAddress();
|
2019-02-24 09:38:22 -05:00
|
|
|
|
2019-02-19 01:26:48 -05:00
|
|
|
void SendFrame();
|
|
|
|
|
2019-03-02 18:00:27 -05:00
|
|
|
bool IsDoubleHeight();
|
|
|
|
bool IsDoubleWidth();
|
|
|
|
|
2019-02-13 18:44:39 -05:00
|
|
|
public:
|
|
|
|
Ppu(shared_ptr<Console> console);
|
2019-03-31 14:50:12 -04:00
|
|
|
virtual ~Ppu();
|
2019-02-13 13:32:21 -05:00
|
|
|
|
2019-04-10 16:04:55 -04:00
|
|
|
void PowerOn();
|
2019-03-16 12:20:18 -04:00
|
|
|
void Reset();
|
|
|
|
|
2019-04-20 11:46:51 -04:00
|
|
|
void EvaluateNextLineSprites();
|
|
|
|
void RenderScanline();
|
|
|
|
|
2019-02-17 19:54:29 -05:00
|
|
|
uint32_t GetFrameCount();
|
2019-03-07 20:12:32 -05:00
|
|
|
uint16_t GetScanline();
|
|
|
|
uint16_t GetCycle();
|
2019-04-10 16:04:55 -04:00
|
|
|
uint16_t GetVblankStart();
|
|
|
|
|
2019-02-13 18:44:39 -05:00
|
|
|
PpuState GetState();
|
2019-02-13 13:32:21 -05:00
|
|
|
|
2019-04-20 11:46:51 -04:00
|
|
|
bool ProcessEndOfScanline(uint16_t hClock);
|
2019-04-14 15:22:34 -04:00
|
|
|
uint16_t GetLastScanline();
|
2019-02-13 13:32:21 -05:00
|
|
|
|
2019-07-06 14:03:27 -04:00
|
|
|
bool IsHighResOutput();
|
2019-03-07 20:12:32 -05:00
|
|
|
uint16_t* GetScreenBuffer();
|
2019-02-15 21:33:13 -05:00
|
|
|
uint8_t* GetVideoRam();
|
|
|
|
uint8_t* GetCgRam();
|
|
|
|
uint8_t* GetSpriteRam();
|
|
|
|
|
2019-02-21 07:27:47 -05:00
|
|
|
void LatchLocationValues();
|
|
|
|
|
2019-02-13 18:44:39 -05:00
|
|
|
uint8_t Read(uint16_t addr);
|
|
|
|
void Write(uint32_t addr, uint8_t value);
|
2019-03-12 09:15:57 -04:00
|
|
|
|
|
|
|
void Serialize(Serializer &s) override;
|
2019-02-13 13:32:21 -05:00
|
|
|
};
|