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"
|
2016-02-06 04:14:27 +00:00
|
|
|
#include "EmulationSettings.h"
|
2017-04-01 02:14:16 +00:00
|
|
|
#include "Types.h"
|
|
|
|
#include "DebuggerTypes.h"
|
|
|
|
#include "IMemoryHandler.h"
|
2014-06-14 14:12:10 +00:00
|
|
|
|
2015-07-22 03:05:27 +00:00
|
|
|
enum class NesModel;
|
|
|
|
|
2017-04-01 02:14:16 +00:00
|
|
|
class BaseMapper;
|
|
|
|
|
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-26 01:52:37 +00:00
|
|
|
class PPU : public IMemoryHandler, public Snapshotable
|
2014-06-14 14:12:10 +00:00
|
|
|
{
|
2015-08-15 01:50:14 +00:00
|
|
|
protected:
|
2014-06-25 21:30:35 +00:00
|
|
|
static PPU* Instance;
|
2016-12-16 12:13:33 +00:00
|
|
|
|
2017-04-01 02:14:16 +00:00
|
|
|
BaseMapper *_mapper;
|
2014-06-16 01:45:36 +00:00
|
|
|
|
2014-06-14 15:27:55 +00:00
|
|
|
PPUState _state;
|
2015-07-22 03:05:27 +00:00
|
|
|
int32_t _scanline;
|
|
|
|
uint32_t _cycle;
|
2016-01-03 01:36:22 +00:00
|
|
|
uint32_t _frameCount;
|
2015-07-22 03:05:27 +00:00
|
|
|
uint8_t _memoryReadBuffer;
|
|
|
|
|
2015-08-06 01:43:53 +00:00
|
|
|
uint8_t _paletteRAM[0x20];
|
2014-06-21 02:31:48 +00:00
|
|
|
|
2014-06-15 15:25:29 +00:00
|
|
|
uint8_t _spriteRAM[0x100];
|
2014-06-21 13:00:10 +00:00
|
|
|
uint8_t _secondarySpriteRAM[0x20];
|
2017-04-02 21:41:24 +00:00
|
|
|
bool _hasSprite[257];
|
2014-06-14 15:27:55 +00:00
|
|
|
|
2015-08-31 01:04:21 +00:00
|
|
|
uint16_t *_currentOutputBuffer;
|
|
|
|
uint16_t *_outputBuffers[2];
|
2015-07-21 22:18:20 +00:00
|
|
|
|
2015-07-22 03:05:27 +00:00
|
|
|
NesModel _nesModel;
|
|
|
|
uint16_t _vblankEnd;
|
2016-06-21 22:58:22 +00:00
|
|
|
uint16_t _nmiScanline;
|
2015-07-22 03:05:27 +00:00
|
|
|
|
2014-06-15 13:35:17 +00:00
|
|
|
PPUControlFlags _flags;
|
|
|
|
PPUStatusFlags _statusFlags;
|
2014-06-14 22:20:56 +00:00
|
|
|
|
2015-07-23 02:08:28 +00:00
|
|
|
uint16_t _intensifyColorBits;
|
|
|
|
uint8_t _paletteRamMask;
|
|
|
|
|
2015-08-15 01:50:14 +00:00
|
|
|
SpriteInfo *_lastSprite; //used by HD ppu
|
|
|
|
|
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
|
|
|
|
2016-01-15 03:20:50 +00:00
|
|
|
SpriteInfo _spriteTiles[64];
|
2016-12-16 12:13:33 +00:00
|
|
|
uint32_t _spriteCount;
|
|
|
|
uint32_t _secondaryOAMAddr;
|
|
|
|
bool _sprite0Visible;
|
2014-07-01 22:05:54 +00:00
|
|
|
|
2016-12-16 12:13:33 +00:00
|
|
|
uint32_t _overflowSpriteAddr;
|
|
|
|
uint32_t _spriteIndex;
|
2015-12-29 18:23:38 +00:00
|
|
|
|
2016-12-16 12:13:33 +00:00
|
|
|
uint8_t _openBus;
|
2016-01-03 01:36:22 +00:00
|
|
|
int32_t _openBusDecayStamp[8];
|
2016-12-16 12:13:33 +00:00
|
|
|
uint32_t _ignoreVramRead;
|
2016-01-03 01:36:22 +00:00
|
|
|
|
2014-07-01 22:05:54 +00:00
|
|
|
uint8_t _oamCopybuffer;
|
2016-01-03 16:44:20 +00:00
|
|
|
bool _spriteInRange;
|
2014-07-01 22:05:54 +00:00
|
|
|
bool _sprite0Added;
|
2016-01-03 16:44:20 +00:00
|
|
|
uint8_t _spriteAddrH;
|
|
|
|
uint8_t _spriteAddrL;
|
|
|
|
bool _oamCopyDone;
|
2017-03-11 02:29:48 +00:00
|
|
|
uint8_t _overflowBugCounter;
|
2016-01-11 22:18:01 +00:00
|
|
|
|
|
|
|
bool _renderingEnabled;
|
2016-02-14 18:57:47 +00:00
|
|
|
bool _prevRenderingEnabled;
|
2016-05-31 21:12:43 +00:00
|
|
|
|
2016-06-12 22:11:31 +00:00
|
|
|
double _cyclesNeeded;
|
|
|
|
|
2017-03-11 03:21:14 +00:00
|
|
|
uint16_t _updateVramAddr;
|
|
|
|
uint8_t _updateVramAddrDelay;
|
2016-10-23 17:29:37 +00:00
|
|
|
|
|
|
|
uint32_t _minimumDrawBgCycle;
|
|
|
|
uint32_t _minimumDrawSpriteCycle;
|
|
|
|
uint32_t _minimumDrawSpriteStandardCycle;
|
2016-01-03 16:44:20 +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 IsRenderingEnabled();
|
|
|
|
|
2016-01-03 01:36:22 +00:00
|
|
|
void SetOpenBus(uint8_t mask, uint8_t value);
|
|
|
|
uint8_t ApplyOpenBus(uint8_t mask, uint8_t value);
|
|
|
|
|
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();
|
|
|
|
|
2017-04-01 02:14:16 +00:00
|
|
|
__forceinline void ProcessScanline();
|
2016-06-07 03:09:22 +00:00
|
|
|
__forceinline void CopyOAMData();
|
2014-06-21 01:48:55 +00:00
|
|
|
|
2014-06-17 22:16:49 +00:00
|
|
|
void BeginVBlank();
|
2016-01-31 00:33:32 +00:00
|
|
|
void TriggerNmi();
|
2014-06-14 22:20:56 +00:00
|
|
|
|
2016-01-04 00:39:41 +00:00
|
|
|
void LoadTileInfo();
|
2016-01-15 03:20:50 +00:00
|
|
|
void LoadSprite(uint8_t spriteY, uint8_t tileIndex, uint8_t attributes, uint8_t spriteX, bool extraSprite);
|
2015-12-29 18:23:38 +00:00
|
|
|
void LoadSpriteTileInfo();
|
2016-01-15 03:20:50 +00:00
|
|
|
void LoadExtraSprites();
|
2017-04-01 02:14:16 +00:00
|
|
|
__forceinline void ShiftTileRegisters();
|
2014-06-19 23:58:15 +00:00
|
|
|
void InitializeShiftRegisters();
|
|
|
|
void LoadNextTile();
|
2014-06-19 02:54:23 +00:00
|
|
|
|
2016-10-23 17:29:37 +00:00
|
|
|
void UpdateMinimumDrawCycles();
|
|
|
|
|
2017-04-01 02:14:16 +00:00
|
|
|
__forceinline uint32_t GetPixelColor();
|
2016-06-07 03:09:22 +00:00
|
|
|
__forceinline virtual void DrawPixel();
|
2015-08-15 01:50:14 +00:00
|
|
|
virtual void SendFrame();
|
2014-06-19 02:54:23 +00:00
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2016-12-18 04:14:47 +00:00
|
|
|
void StreamState(bool saving) override;
|
2014-06-26 01:52:37 +00:00
|
|
|
|
2014-06-14 15:27:55 +00:00
|
|
|
public:
|
2015-07-24 03:16:31 +00:00
|
|
|
static const uint32_t ScreenWidth = 256;
|
|
|
|
static const uint32_t ScreenHeight = 240;
|
|
|
|
static const uint32_t PixelCount = 256*240;
|
|
|
|
static const uint32_t OutputBufferSize = 256*240*2;
|
|
|
|
|
2017-04-01 02:14:16 +00:00
|
|
|
PPU(BaseMapper *mapper);
|
2015-08-15 01:50:14 +00:00
|
|
|
virtual ~PPU();
|
2014-06-14 22:20:56 +00:00
|
|
|
|
2014-06-23 17:52:53 +00:00
|
|
|
void Reset();
|
|
|
|
|
2016-06-05 14:26:05 +00:00
|
|
|
void DebugSendFrame();
|
2015-07-02 03:17:14 +00:00
|
|
|
PPUDebugState GetState();
|
2016-11-26 22:48:11 +00:00
|
|
|
void SetState(PPUDebugState state);
|
2015-07-02 03:17:14 +00:00
|
|
|
|
2016-12-18 04:14:47 +00:00
|
|
|
void GetMemoryRanges(MemoryRanges &ranges) override
|
2014-06-16 01:45:36 +00:00
|
|
|
{
|
2015-07-30 02:10:34 +00:00
|
|
|
ranges.AddHandler(MemoryOperation::Read, 0x2000, 0x3FFF);
|
|
|
|
ranges.AddHandler(MemoryOperation::Write, 0x2000, 0x3FFF);
|
|
|
|
ranges.AddHandler(MemoryOperation::Write, 0x4014);
|
2014-06-14 15:27:55 +00:00
|
|
|
}
|
2014-06-14 14:12:10 +00:00
|
|
|
|
2017-04-01 02:14:16 +00:00
|
|
|
__forceinline uint8_t ReadPaletteRAM(uint16_t addr);
|
2016-09-05 13:05:34 +00:00
|
|
|
void WritePaletteRAM(uint16_t addr, uint8_t value);
|
2015-08-06 01:43:53 +00:00
|
|
|
|
2016-12-18 04:14:47 +00:00
|
|
|
uint8_t ReadRAM(uint16_t addr) override;
|
|
|
|
void WriteRAM(uint16_t addr, uint8_t value) override;
|
2014-06-14 22:20:56 +00:00
|
|
|
|
2015-07-22 03:05:27 +00:00
|
|
|
void SetNesModel(NesModel model);
|
2015-12-26 22:11:00 +00:00
|
|
|
|
2015-07-05 02:21:14 +00:00
|
|
|
void Exec();
|
2015-07-21 22:18:20 +00:00
|
|
|
static void ExecStatic();
|
2014-06-19 02:54:23 +00:00
|
|
|
|
2015-07-11 01:07:24 +00:00
|
|
|
static uint32_t GetFrameCount()
|
2014-06-19 02:54:23 +00:00
|
|
|
{
|
2015-07-11 01:07:24 +00:00
|
|
|
return PPU::Instance->_frameCount;
|
2014-06-19 02:54:23 +00:00
|
|
|
}
|
2014-06-25 21:30:35 +00:00
|
|
|
|
2014-06-26 20:41:07 +00:00
|
|
|
static uint32_t GetFrameCycle()
|
|
|
|
{
|
|
|
|
return ((PPU::Instance->_scanline + 1) * 341) + PPU::Instance->_cycle;
|
|
|
|
}
|
|
|
|
|
2015-07-30 02:10:34 +00:00
|
|
|
static PPUControlFlags GetControlFlags()
|
|
|
|
{
|
|
|
|
return PPU::Instance->_flags;
|
|
|
|
}
|
|
|
|
|
2014-06-25 21:30:35 +00:00
|
|
|
static uint32_t GetCurrentCycle()
|
|
|
|
{
|
|
|
|
return PPU::Instance->_cycle;
|
|
|
|
}
|
2014-06-26 20:41:07 +00:00
|
|
|
|
2016-01-25 02:35:43 +00:00
|
|
|
static int32_t GetCurrentScanline()
|
2014-06-26 20:41:07 +00:00
|
|
|
{
|
|
|
|
return PPU::Instance->_scanline;
|
|
|
|
}
|
2015-08-06 01:43:53 +00:00
|
|
|
|
2015-08-06 00:40:10 +00:00
|
|
|
uint8_t* GetSpriteRam()
|
|
|
|
{
|
|
|
|
return _spriteRAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t* GetSecondarySpriteRam()
|
|
|
|
{
|
|
|
|
return _secondarySpriteRAM;
|
|
|
|
}
|
2016-02-06 04:14:27 +00:00
|
|
|
|
|
|
|
static uint32_t GetPixelBrightness(uint8_t x, uint8_t y)
|
|
|
|
{
|
|
|
|
//Used by Zapper, gives a rough approximation of the brightness level of the specific pixel
|
|
|
|
uint16_t pixelData = PPU::Instance->_currentOutputBuffer[y << 8 | x];
|
|
|
|
uint32_t argbColor = EmulationSettings::GetRgbPalette()[pixelData & 0x3F];
|
|
|
|
return (argbColor & 0xFF) + ((argbColor >> 8) & 0xFF) + ((argbColor >> 16) & 0xFF);
|
|
|
|
}
|
2014-06-19 02:54:23 +00:00
|
|
|
};
|