Skip to content

PPU: Notes

Carl Blomqvist edited this page Feb 14, 2020 · 4 revisions

Pattern Memory : 0x000 - 0x1FFF

Delat i två delar, 16x16 tiles - varje tile 8x8 pixlar - adresseras genom mapper.

En tile

4 färger - 2 bytes. - lagras som 8 LSB, följt av 4 MSB Läs en tile genom att läsa 16 bytes.

Name Table Memory : 0x2000 - 0x3EFF

32x32 av bytes - varje byte är ett ID i Pattern Memory (1kb) Scroll Register anger offset i nametable. 2 name tables bredvid varandra 2 st mirrored nametables.

Horizontal Mirroring

[ ][m] [ ][m]

Vertical Mirroring

[ ][ ] [m][m]

Nametable Offset

y * width + x NTy, NTx, coarse y, coarse x 1 1 5 5 - bits fine y, fine x (offset inom 32x32 blocken) fine x > 7 => coarse_x++ när vår scanline går över gränsen för nästa nametable flippar vi NTx/NTy biten

Sista två raderna används för Attribute Memory

Varje byte representerar en 4x4 grid i name tablet Varje 4x4 grid delas upp i 4st 2x2 grids - 2 bits per grid Exempel byte: 01 00 10 11 Adresserad genom LSB (typ…): [11][10] [00][01] coarse y och coarse x: 5 -> 3 bits - ger oss adress för attribute memory. De två bitarna vi “kastat bort” ger oss våra 2 bitar inom byten för tilen

Palette Memory : 0x3F00 - 0x3FFF

X $3F00 [] <- Byte

Background Palette

0 $3F01 [][][][X] <- Fjärde oanvänd 1 $3F05 [][][.] 2 $3F09 3 $3F0D

Foreground Palette

4 $3F11 5 $3F15 6 $3F19 7 $3F1D Exempel: Palette 1 + Pixel 3 => (1 x 4) + 3 = 7 ($3F07)

PPU Register

$2000 - CTRL

struct {
    nametable_x,
    nametable_y,
    increment_mode, -- bestämmer vilket "håll" dataregistret ökar åt
    pattern_sprite,
    pattern_background,
    sprite_size,
    slave_mode,
    enable_nmi
}
** $2001 - MASK
struct {
    grayscale,
    render_background_left,
    render_sprites_left,
    render_background,
    render_sprites,
    enhance_red,
    enhance_green,
    enhance_blue
}

$2002 - STATUS

struct {
    5 unused,
    sprite_overflow,
    sprite_zero_hit,
    vertical_blank
}

vertical_blank återställs vid läsning från registret

$2003 - OAM ADDR

$2004 - OAM DATA

$2005 - SCROLL

$2006 - ADDR

16-bitar: Skrivs i två delar

$2007 - DATA

1 cycle delay - utom från Palette Memory (> 0x3F00) Auto-increment vid läsning och skrivning (control.increment_mode ? 32 : 1)

$4014 - DMA (Direct Memory Access)

Stannar CPUn och kopierar en page från CPU-minnet till PPU-minnet (512 cykler)

Scanlines

resolution: 256 x 240 scanlines : 341 x 261 PPU kan generera NMI när vi går in i vertical_blank. wiki.nesdev.com/w/images/4/4f/Ppu.svg

Loopy Register

struct {
    coarse_x,
    coarse_y,
    nametable_x,
    nametable_y,
    fine_y,
    unused
}

vram + tram

Clock

wiki.nesdev.com/w/images/4/4f/Ppu.svg Beroende på vilken cykel vi är på ska vi läsa olika saker från minnet. “Förberedande” inläsning av next_tile, next_tile_attribute, next_tile_lsb, next_tile_msb

Shift Registers

16-bit register pattern_LSB pattern_MSB attribute_LSB attribute_MSB indexera i byten med fine_x Vi laddar in next_tile-variablerna i nedre delen av dessa register

Controllers

CPU Skriver -> Kontroll sparar state -> CPU läser 8 ggr från shift register $4016 $4017

Object Attribute Memory (OAM) - 256 bytes

64 Sprites

struct {
    y,
    id,
    attribute,
    x
}

Drawing a sprite

  1. End of scanline, search OAM for max of 8 sprites visible on next scanline
  2. as scanline scans, reduce sprites x coord (måste ju gå att göra bättre?)
  3. if x coord == 0, start to draw sprites
  4. resolve priority of sprite pixel (0 har högst prio, 63 lägst)

2 x 8 shift register för sprites (LSB/MSB)