1
0
Fork 0
2019-nes-emulator/Source/PPU/PPU.hpp

165 lines
3.0 KiB
C++

#pragma once
#include <cstdint>
#include <queue>
class NES;
const unsigned int VRAM_SIZE = 2048u;
const unsigned int PALETTE_SIZE = 8u;
const unsigned int OAM_SIZE = 256u;
const unsigned int VIDEO_WIDTH = 256u;
const unsigned int VIDEO_HEIGHT = 240u;
const unsigned int TOTAL_SCANLINES = 262u;
const unsigned int TOTAL_DOTS = 341u;
class PPU
{
public:
PPU();
enum Register
{
PPUCTRL = 0x00,
PPUMASK = 0x01,
PPUSTATUS = 0x02,
OAMADDR = 0x03,
OAMDATA = 0x04,
PPUSCROLL = 0x05,
PPUADDR = 0x06,
PPUDATA = 0x07,
};
void Tick();
void WriteRegister(Register reg, uint8_t value);
uint8_t ReadRegister(Register reg);
void WriteMemory(uint16_t address, uint8_t value);
uint8_t ReadMemory(uint16_t address);
private:
friend class NES;
void FetchNT();
void FetchAT();
void FetchPTLow();
void FetchPTHigh();
void SetVBlank();
void SetTileX();
void SetTileY();
void LoadBackground();
void Draw();
void IncrementTileX();
void IncrementTileY();
void ClearFlags();
enum Event
{
FETCH_NT = 0x1,
FETCH_AT = 0x2,
FETCH_PT_LOW = 0x4,
FETCH_PT_HIGH = 0x8,
LOAD_BACKGROUND = 0x10,
SHIFT_BACKGROUND = 0x20,
SET_VBLANK = 0x40,
SET_TILE_X = 0x80,
SET_TILE_Y = 0x100,
DRAW = 0x200,
INCREMENT_TILE_X = 0x400,
INCREMENT_TILE_Y = 0x800,
CLEAR_FLAGS = 0x1000
};
struct PpuCtrl
{
void SetByte(uint8_t byte);
uint16_t nametableBaseAddr;
uint8_t vramAddrIncrement;
uint8_t spritePatternTableAddr;
uint8_t bgPatternTableAddr;
uint8_t spriteSize;
uint8_t masterSlaveSelect;
uint8_t nmiEnable;
};
struct PpuMask
{
void SetByte(uint8_t byte);
uint8_t grayscale;
uint8_t showBackgroundLeft;
uint8_t showSpritesLeft;
uint8_t showBackground;
uint8_t showSprites;
uint8_t redEmphasis;
uint8_t greenEmphasis;
uint8_t blueEmphasis;
};
struct PpuStatus
{
uint8_t GetByte();
uint8_t vblankStarted;
uint8_t sprite0Hit;
uint8_t spriteOverflow;
uint8_t previousLsb;
};
struct Address
{
uint16_t GetValue();
void SetValue(uint16_t value);
uint8_t scrollFineY;
uint8_t nametableX;
uint8_t nametableY;
uint8_t scrollCoarseX;
uint8_t scrollCoarseY;
};
// External Registersgg
PpuCtrl regPPUCTRL{}; // $2000, W
PpuMask regPPUMASK{}; // $2001, W
PpuStatus regPPUSTATUS{}; // $2002, R
uint8_t regOAMADDR{}; // $2003, W
uint8_t oldByte{};
// Internal Registers
Address currentAddress{};
Address tempAddress{};
uint8_t scrollFineX{};
bool firstWrite{true};
// Timing tracking
uint32_t events[TOTAL_SCANLINES][TOTAL_DOTS]{};
uint16_t currentCycle{};
uint16_t currentScanline{};
// Memory
uint8_t ram[VRAM_SIZE]{};
uint8_t palette[PALETTE_SIZE][4]{};
uint8_t oam[OAM_SIZE]{};
uint32_t video[VIDEO_WIDTH * VIDEO_HEIGHT]{};
uint64_t frameNumber{};
// Shift registers and latches
uint16_t patternTableHighShift{};
uint16_t patternTableLowShift{};
uint8_t atShiftLow{};
uint8_t atShiftHigh{};
uint8_t nametableLatch{};
uint8_t attributeTableLatch{};
uint8_t attribute;
uint8_t patternTableLowLatch{};
uint8_t patternTableHighLatch{};
NES* nes;
void ShiftBG();
};