Class R2C02

Nested Relationships

Nested Types

Inheritance Relationships

Base Type

Class Documentation

class R2C02 : public Component

NES PPU emulation. Both foreground and background cycle-accurate rendering implemented, sprite 0 bug and other quirks are also emulated.

Ports: data “ppuBus” to control a communication on the PPU’s own bus; signal “INT” to send interrupts to the CPU (normally connected to the NMI). Connectors: data “cpuBus” to connect to the CPU, signal “CLK” to clock the PPU (standard rate is 21.477272 MHz ÷ 4).

Public Functions

R2C02()

Default constructor. Reset PPU status and rendering.

~R2C02() = default

Default destructor.

virtual void init()

Reset the PPU.

void clock()

Proceed one clock further in emulation. Works as a physical CLK input. 1 PPU cycle = 186 ns

void OAMDMA(uint8_t addr, uint8_t data)

PPU OAM DMA. Used to write to the OAM during DMA proccess.

Parameters
  • addr – OAM address.

  • data – Data to write.

std::vector<RGBPixel> getPalette(uint8_t paletteId)
uint8_t *getPaletteRAM()
std::vector<std::vector<RGBPixel>> getPatternTable(uint8_t colorType, uint8_t paletteId, uint8_t index, bool applyEffects = false)

Get a pattern table.

std::vector<RGBPixel> getScreen()

Get a NES screen.

bool scanlineFinished() const

Is a scanline finished?

Returns

true if clock index >= 341

bool frameFinished() const

Is a frame finished?

Returns

true if scanline index >= 261

virtual std::vector<EmulatorWindow> getGUIs() override

Get GUI windows: metadata and rendering functions.

Note

For Component developer: If the component have a debugger or other GUI, return an arbitrary count of windows, they will be rendered on a load of a system which contains the component.

Returns

A vector of windows to be rendered.

Public Members

uint8_t primaryOAM[256]
uint8_t secondaryOAM[32]
uint8_t attrLatch[8]
uint8_t x[8]
uint8_t shiftLo[8]

8 pairs of 8 bit shifters Pattern table data for up to 8 sprites to be rendered on the current scanline.

uint8_t shiftHi[8]
uint8_t allowShift[8]
uint8_t secondarySpriteId
uint8_t feedY
uint16_t feedTileAddress
uint8_t feedIndex
uint8_t ntByte
uint8_t atByte
uint16_t tileData
uint16_t shiftTileLo
uint16_t shiftTileHi
uint16_t shiftAttrLo
uint16_t shiftAttrHi

Protected Functions

void verticalIncrement()
void horizontalIncrement()
void verticalTransfer()
void horizontalTransfer()
void fetchNT()
void fetchAT()
void fetchTileLo()
void fetchTileHi()
void feedShifters()
void shiftShifters()
void evaluateSprites()
void fetchSprite(uint8_t offset)
uint8_t ppuBusRead(uint16_t addr)

Read from the internal bus.

Parameters

addr – Address to read from.

Returns

Data.

void ppuBusWrite(uint16_t addr, uint8_t data)

Write to the internal bus.

Parameters
  • addr – Address to write to.

  • data – Data to write.

RGBPixel getPixelColor(uint8_t paletteId, uint8_t pixel)
RGBPixel getColorFromPalette(uint8_t bgFg, uint8_t paletteNumber, uint8_t pixelValue)
RGBPixel applyPixelEffects(RGBPixel pixel) const

Protected Attributes

uint8_t m_dataBuffer = 0x00

Data lines sometimes act as a buffer because of their capacitance.

struct R2C02::internalRegisters_t m_internalRegisters
struct R2C02::[anonymous] m_spriteData
struct R2C02::[anonymous] m_backgroundData
struct R2C02::registers_t m_registers
bool m_scanlineReady = false
bool m_frameReady = false
bool m_oddScan = false

True if the odd field of the frame is being rendered (see interlaced video).

bool m_settingsEnableForeground = true

Foreground pixel placement enabled.

bool m_settingsEnableBackground = true

Background pixel placement enabled.

bool m_blockNMI = false

Suppress NMI generation and NMI flag setting. Used by a special case during reading NMI flag near the clock 1 of the scanline 241, which is when the NMI is supposed to generate. See read method for more information.

const RGBPixel m_colors2C02[64]

Default 2C02 color pallete.

const RGBPixel *m_colors = m_colors2C02
uint8_t m_palettes[32]

2C02 bus components: 0x0000 - 0x1FFF Pattern memory (CHR ROM) - on cartridge (sprites) 0x2000 - 0x3EFF Nametable memory (VRAM) - on cartridge or built-in (sprite locations) 0x3F00 - 0x3FFF Palette memory - built-in (colors)

int m_clock
int m_scanline
std::vector<std::vector<RGBPixel>> m_screen = {OUTPUT_BITMAP_HEIGHT, {OUTPUT_BITMAP_WIDTH, {0, 0, 0}}}
DataPort m_ppuBus
SignalPort m_INT

Protected Static Functions

static uint8_t saturate(uint8_t x, uint8_t y)
static uint8_t desaturate(uint8_t x, uint8_t y)

Protected Static Attributes

static constexpr AddressRange ADDR_PATTERN_TABLES = {0x0000, 0x1FFF}

Frame rendering: 256 341 xxxxxxxxxxxxxxx <- scanline -1 @@@@@@@&mdash; @@@@@@@&mdash; @@@@@@@&mdash;

static constexpr AddressRange ADDR_NAMETABLES = {0x2000, 0x2FFF}
static constexpr AddressRange ADDR_PALETTE_RAM = {0x3F00, 0x3FFF}
static const uint16_t OUTPUT_BITMAP_WIDTH = 256
static const uint16_t OUTPUT_BITMAP_HEIGHT = 240
static const uint16_t PATTERN_TABLE_TILE_ROW_COUNT = 16
static const uint16_t PATTERN_TABLE_TILE_COLUMN_COUNT = 16
static const uint16_t PATTERN_TABLE_PLANE_SIZE = 8
struct internalRegisters_t

Internal registers of the PPU for the rendering purposes. These are not exposed.

Public Members

uint16_t coarseX
uint16_t coarseY
uint16_t nameX
uint16_t nameY
uint16_t fineY
uint16_t padding
struct R2C02::internalRegisters_t::[anonymous]::STR bits
uint16_t data
union R2C02::internalRegisters_t::[anonymous] v

v = current VRAM address t = temporary VRAM address

union R2C02::internalRegisters_t::[anonymous] t
uint8_t x

Fine X scroll. 3 bits.

bool w

First or second write toggle. Shared by 0x2005 and 0x2006 register. 1 bit.

struct registers_t

“Public” registers accessible by the CPU.

Public Members

uint8_t nameX

Base nametable address, scroll X coordinate MSB. (1 = add 256)

uint8_t nameY

Base nametable address, scroll Y coordinate MSB. (1 = add 240)

uint8_t incMode

VRAM address increment per CPU R/W of PPUDATA. (0 = add 1, 1 = add 32).

uint8_t spriteAddress

Sprite pattern table address for 8x8 sprites.

uint8_t backgroundAddress

Background pattern table address.

uint8_t spriteSize

Sprite size (8x8, 8x16).

uint8_t masterSlave

PPU master/slave.

uint8_t nmi

Generate NMI on vblank.

struct R2C02::registers_t::[anonymous]::[anonymous] bits
uint8_t data
union R2C02::registers_t::[anonymous] ppuctrl

Controller (0x2000) - PPUCTRL Access: write Controls PPU operation.

uint8_t grayscale

Enable grayscale.

uint8_t showBackgroundLeft

Show background in leftmost 8 pixels.

uint8_t showSpritesLeft

Show sprites in leftmost 8 pixels.

uint8_t showBackground

Show bg.

uint8_t showSprites

Show sprites.

uint8_t eRed

Enhance red. (Green on PAL/Dendy.)

uint8_t eGreen

Enhance green. (Red on PAL/Dendy.)

uint8_t eBlue

Enhance blue.

struct R2C02::registers_t::[anonymous]::[anonymous] bits
union R2C02::registers_t::[anonymous] ppumask

Mask register (0x2001) - PPUMASK Access: write Controls the rendering of sprites and backgrounds and color effects.

uint8_t padding

Least sig. bits of previous value written to PPU register. Some Vs. systems return a constant that game checks.

uint8_t spriteOverflow

Buggy detection of the existence of more than 8 sprites on a scanline.

uint8_t spriteZeroHit

Nonzero pixel of sprite 0 overlaps nonzero background.

uint8_t vBlank

True if vblank started, cleared after reading this register.

struct R2C02::registers_t::[anonymous]::[anonymous] bits
union R2C02::registers_t::[anonymous] ppustatus

Status register (0x2002) - PPUSTATUS Access: read Reflects the state of the PPU.

uint8_t byte
uint8_t index
struct R2C02::registers_t::[anonymous]::[anonymous] bits
union R2C02::registers_t::[anonymous] oamAddress