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-07-11 23:30:40 -04:00
|
|
|
#include "../Utilities/Timer.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-07-19 19:39:38 -04:00
|
|
|
class Spc;
|
|
|
|
class EmuSettings;
|
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-07-12 23:34:19 -04:00
|
|
|
Console* _console;
|
|
|
|
InternalRegisters* _regs;
|
|
|
|
MemoryManager* _memoryManager;
|
2019-07-19 19:39:38 -04:00
|
|
|
Spc* _spc;
|
|
|
|
EmuSettings* _settings;
|
2019-02-13 18:44:39 -05:00
|
|
|
|
2019-07-08 15:24:43 -04:00
|
|
|
//Temporary data used for the tilemap/tile fetching
|
2019-07-13 13:43:56 -04:00
|
|
|
LayerData _layerData[4] = {};
|
2019-07-07 18:18:20 -04:00
|
|
|
uint16_t _hOffset = 0;
|
|
|
|
uint16_t _vOffset = 0;
|
2019-07-10 22:50:12 -04:00
|
|
|
uint16_t _fetchBgStart = 0;
|
|
|
|
uint16_t _fetchBgEnd = 0;
|
2019-07-07 18:18:20 -04:00
|
|
|
|
2019-07-08 15:24:43 -04:00
|
|
|
//Temporary data used by the sprite evaluation/fetching
|
2019-07-10 22:50:12 -04:00
|
|
|
SpriteInfo _currentSprite = {};
|
|
|
|
uint8_t _oamEvaluationIndex = 0;
|
|
|
|
uint8_t _oamTimeIndex = 0;
|
|
|
|
uint16_t _fetchSpriteStart = 0;
|
|
|
|
uint16_t _fetchSpriteEnd = 0;
|
|
|
|
uint16_t _spriteEvalStart = 0;
|
|
|
|
uint16_t _spriteEvalEnd = 0;
|
|
|
|
bool _spriteFetchingDone = false;
|
|
|
|
uint8_t _spriteIndexes[32] = {};
|
|
|
|
uint8_t _spriteCount = 0;
|
|
|
|
uint8_t _spriteTileCount = 0;
|
2019-07-12 23:53:47 -04:00
|
|
|
bool _hasSpritePriority[4] = {};
|
2019-07-08 15:24:43 -04:00
|
|
|
|
2019-02-13 13:32:21 -05:00
|
|
|
uint16_t _scanline = 0;
|
|
|
|
uint32_t _frameCount = 0;
|
2019-07-19 19:39:38 -04:00
|
|
|
|
|
|
|
uint16_t _vblankStartScanline;
|
|
|
|
uint16_t _vblankEndScanline;
|
|
|
|
uint16_t _baseVblankEndScanline;
|
|
|
|
uint16_t _adjustedVblankEndScanline;
|
|
|
|
uint16_t _nmiScanline;
|
|
|
|
bool _overclockEnabled;
|
|
|
|
|
2019-04-08 10:16:12 -04:00
|
|
|
uint8_t _oddFrame = 0;
|
2019-03-04 17:49:14 -05:00
|
|
|
|
2019-10-10 23:54:38 -04:00
|
|
|
PpuState _state;
|
|
|
|
|
2019-03-07 20:13:44 -05:00
|
|
|
uint16_t _drawStartX = 0;
|
|
|
|
uint16_t _drawEndX = 0;
|
2021-03-10 11:13:28 -05:00
|
|
|
|
|
|
|
uint16_t *_vram = nullptr;
|
2019-07-11 17:37:01 -04:00
|
|
|
uint16_t _cgram[Ppu::CgRamSize >> 1] = {};
|
2019-10-10 23:54:38 -04:00
|
|
|
uint8_t _oamRam[Ppu::SpriteRamSize] = {};
|
2019-02-15 21:33:13 -05:00
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
uint16_t *_outputBuffers[2] = {};
|
|
|
|
uint16_t *_currentBuffer = nullptr;
|
2019-07-06 14:03:27 -04:00
|
|
|
bool _useHighResOutput = false;
|
2019-11-02 22:55:56 -04:00
|
|
|
bool _interlacedFrame = false;
|
2020-02-29 19:36:17 -05:00
|
|
|
bool _overscanFrame = false;
|
2019-02-19 23:35:43 -05:00
|
|
|
|
2020-01-11 17:40:42 -05:00
|
|
|
uint8_t _mainScreenFlags[256] = {};
|
2019-06-29 09:16:53 -04:00
|
|
|
uint16_t _mainScreenBuffer[256] = {};
|
2019-02-13 13:32:21 -05:00
|
|
|
|
2020-01-11 17:40:42 -05:00
|
|
|
uint8_t _subScreenPriority[256] = {};
|
2019-06-29 09:16:53 -04:00
|
|
|
uint16_t _subScreenBuffer[256] = {};
|
2019-02-19 01:26:48 -05:00
|
|
|
|
2019-07-08 23:46:31 -04:00
|
|
|
uint32_t _mosaicColor[4] = {};
|
2020-01-11 17:40:42 -05:00
|
|
|
uint32_t _mosaicPriority[4] = {};
|
2019-07-11 21:45:56 -04:00
|
|
|
uint16_t _mosaicScanlineCounter = 0;
|
2021-03-10 11:13:28 -05:00
|
|
|
|
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-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-08-09 20:47:12 -04:00
|
|
|
bool _latchRequest = false;
|
|
|
|
uint16_t _latchRequestX = 0;
|
|
|
|
uint16_t _latchRequestY = 0;
|
2019-02-21 07:27:47 -05:00
|
|
|
|
2019-07-11 23:30:40 -04:00
|
|
|
Timer _frameSkipTimer;
|
|
|
|
bool _skipRender = false;
|
2019-05-20 15:35:09 -04:00
|
|
|
uint8_t _configVisibleLayers = 0xFF;
|
2019-04-10 22:32:28 -04:00
|
|
|
|
2019-07-10 22:50:12 -04:00
|
|
|
uint8_t _spritePriority[256] = {};
|
|
|
|
uint8_t _spritePalette[256] = {};
|
|
|
|
uint8_t _spriteColors[256] = {};
|
|
|
|
uint8_t _spritePriorityCopy[256] = {};
|
|
|
|
uint8_t _spritePaletteCopy[256] = {};
|
|
|
|
uint8_t _spriteColorsCopy[256] = {};
|
|
|
|
|
2020-01-11 17:40:42 -05:00
|
|
|
void RenderSprites(const uint8_t priorities[4]);
|
2019-02-22 18:41:43 -05:00
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
template<bool hiResMode>
|
2019-07-07 18:18:20 -04:00
|
|
|
void GetTilemapData(uint8_t layerIndex, uint8_t columnIndex);
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
template<bool hiResMode, uint8_t bpp, bool secondTile = false>
|
2019-07-07 18:18:20 -04:00
|
|
|
void GetChrData(uint8_t layerIndex, uint8_t column, uint8_t plane);
|
|
|
|
|
|
|
|
void GetHorizontalOffsetByte(uint8_t columnIndex);
|
|
|
|
void GetVerticalOffsetByte(uint8_t columnIndex);
|
|
|
|
void FetchTileData();
|
|
|
|
|
2019-07-12 23:53:47 -04:00
|
|
|
void RenderMode0();
|
|
|
|
void RenderMode1();
|
|
|
|
void RenderMode2();
|
|
|
|
void RenderMode3();
|
|
|
|
void RenderMode4();
|
|
|
|
void RenderMode5();
|
|
|
|
void RenderMode6();
|
|
|
|
void RenderMode7();
|
2019-02-22 18:41:43 -05:00
|
|
|
|
2019-02-24 01:11:26 -05:00
|
|
|
void RenderBgColor();
|
2019-02-23 21:39:35 -05:00
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
template<uint8_t layerIndex, uint8_t bpp, uint8_t normalPriority, uint8_t highPriority, uint16_t basePaletteOffset = 0>
|
2019-02-24 01:11:26 -05:00
|
|
|
__forceinline void RenderTilemap();
|
2021-03-10 11:13:28 -05:00
|
|
|
|
|
|
|
template<uint8_t layerIndex, uint8_t bpp, uint8_t normalPriority, uint8_t highPriority, uint16_t basePaletteOffset, bool hiResMode>
|
2019-02-24 01:11:26 -05:00
|
|
|
__forceinline void RenderTilemap();
|
2019-02-22 22:35:53 -05:00
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
template<uint8_t layerIndex, uint8_t bpp, uint8_t normalPriority, uint8_t highPriority, uint16_t basePaletteOffset, bool hiResMode, bool applyMosaic>
|
2019-02-24 01:11:26 -05:00
|
|
|
__forceinline void RenderTilemap();
|
2019-02-22 22:35:53 -05:00
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
template<uint8_t layerIndex, uint8_t bpp, uint8_t normalPriority, uint8_t highPriority, uint16_t basePaletteOffset, bool hiResMode, bool applyMosaic, bool directColorMode>
|
2019-02-22 22:35:53 -05:00
|
|
|
void RenderTilemap();
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
template<uint8_t bpp, bool directColorMode, uint8_t basePaletteOffset>
|
2019-07-12 23:53:47 -04:00
|
|
|
__forceinline uint16_t GetRgbColor(uint8_t paletteIndex, uint8_t colorIndex);
|
|
|
|
|
2019-02-24 01:30:55 -05:00
|
|
|
__forceinline bool IsRenderRequired(uint8_t layerIndex);
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
template<uint8_t bpp>
|
2019-07-08 15:24:43 -04:00
|
|
|
__forceinline uint8_t GetTilePixelColor(const uint16_t chrData[4], const uint8_t shift);
|
2019-02-24 01:30:55 -05:00
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
template<uint8_t layerIndex, uint8_t normalPriority, uint8_t highPriority>
|
2019-02-24 01:11:26 -05:00
|
|
|
__forceinline void RenderTilemapMode7();
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
template<uint8_t layerIndex, uint8_t normalPriority, uint8_t highPriority, bool applyMosaic>
|
2019-02-24 01:11:26 -05:00
|
|
|
__forceinline void RenderTilemapMode7();
|
2019-02-23 01:28:41 -05:00
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
template<uint8_t layerIndex, uint8_t normalPriority, uint8_t highPriority, 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);
|
2020-01-11 17:40:42 -05:00
|
|
|
__forceinline void DrawSubPixel(uint8_t x, uint16_t color, uint8_t priority);
|
2019-02-23 15:40:32 -05:00
|
|
|
|
2019-02-19 01:26:48 -05:00
|
|
|
void ApplyColorMath();
|
2021-03-10 11:13:28 -05:00
|
|
|
void ApplyColorMathToPixel(uint16_t &pixelA, uint16_t pixelB, int x, bool isInsideWindow);
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
template<uint8_t layerIndex>
|
2019-02-22 20:15:55 -05:00
|
|
|
bool ProcessMaskWindow(uint8_t activeWindowCount, int x);
|
2019-07-12 23:53:47 -04:00
|
|
|
|
2019-02-22 20:15:55 -05:00
|
|
|
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-07-13 00:02:36 -04:00
|
|
|
void EvaluateNextLineSprites();
|
|
|
|
void FetchSpriteData();
|
2019-08-10 10:56:39 -04:00
|
|
|
__forceinline void FetchSpritePosition(uint16_t oamAddress);
|
2019-07-13 00:02:36 -04:00
|
|
|
void FetchSpriteAttributes(uint16_t oamAddress);
|
|
|
|
void FetchSpriteTile(bool secondCycle);
|
|
|
|
|
|
|
|
void UpdateOamAddress();
|
|
|
|
uint16_t GetOamAddress();
|
2021-03-10 11:13:28 -05:00
|
|
|
|
2019-12-11 21:44:42 -05:00
|
|
|
void RandomizeState();
|
2019-07-13 00:02:36 -04:00
|
|
|
|
2019-02-13 18:44:39 -05:00
|
|
|
public:
|
2019-07-12 23:34:19 -04:00
|
|
|
Ppu(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 RenderScanline();
|
|
|
|
|
2019-02-17 19:54:29 -05:00
|
|
|
uint32_t GetFrameCount();
|
2019-07-19 19:39:38 -04:00
|
|
|
uint16_t GetRealScanline();
|
2019-10-08 21:04:32 -04:00
|
|
|
uint16_t GetVblankEndScanline();
|
2019-03-07 20:12:32 -05:00
|
|
|
uint16_t GetScanline();
|
|
|
|
uint16_t GetCycle();
|
2019-07-19 19:39:38 -04:00
|
|
|
uint16_t GetNmiScanline();
|
2019-04-10 16:04:55 -04:00
|
|
|
uint16_t GetVblankStart();
|
|
|
|
|
2019-02-13 18:44:39 -05:00
|
|
|
PpuState GetState();
|
2021-03-10 11:13:28 -05:00
|
|
|
void GetState(PpuState &state, bool returnPartialState);
|
2019-02-13 13:32:21 -05:00
|
|
|
|
2019-04-20 11:46:51 -04:00
|
|
|
bool ProcessEndOfScanline(uint16_t hClock);
|
2019-07-19 19:39:38 -04:00
|
|
|
void UpdateSpcState();
|
|
|
|
void UpdateNmiScanline();
|
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-10-18 19:34:55 -04:00
|
|
|
uint16_t* GetPreviousScreenBuffer();
|
2019-02-15 21:33:13 -05:00
|
|
|
uint8_t* GetVideoRam();
|
|
|
|
uint8_t* GetCgRam();
|
|
|
|
uint8_t* GetSpriteRam();
|
|
|
|
|
2019-08-09 20:47:12 -04:00
|
|
|
void SetLocationLatchRequest(uint16_t x, uint16_t y);
|
|
|
|
void ProcessLocationLatchRequest();
|
2019-02-21 07:27:47 -05:00
|
|
|
void LatchLocationValues();
|
2021-03-10 11:13:28 -05:00
|
|
|
|
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
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
void Serialize(Serializer &s) override;
|
|
|
|
};
|