165 lines
3.0 KiB
C++
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();
|
|
};
|