F18A Mode — Registers

A.C. Wright 6502 BIOS
F18A mode · Pico9918
Unlocking
Write $1C to VR57. Twice, consecutively. Register 57 is register 1 on a stock TMS9918A, which only looks at the low three bits of a register number. $1C written to register 1 means 4 KB of VRAM, display blanked, interrupts off, both mode bits set at once — an illegal combination that makes the chip useless. No working program would write it once, let alone twice in a row. Any other register write between the two cancels it. On a stock card those two writes land in register 1 and blank the screen. Set register 1 back to something sane immediately afterwards, whether or not the unlock took.
Writing a register. Value to $9C01, then the register number with bit 7 set. Registers 0–7 always; 8–63 only once unlocked.
Which card is this? Status register 1 reads $E0 on a real F18A and $E8 on a Pico9918. Select it with VR15, read $9C01, then put VR15 back to 0.
Bit order. D7 is the most significant bit here. Hagerty’s own documents number the most significant bit as 0, so his tables read mirrored against these.
Display modes
Graphics IM1 0 · M2 0 · M3 0 · M4 0
Graphics IIM1 0 · M2 0 · M3 1 · M4 0
MulticolorM1 0 · M2 1 · M3 0 · M4 0
Text, 40 columnM1 1 · M2 0 · M3 0 · M4 0
Text, 80 columnM1 1 · M2 0 · M3 0 · M4 1
Registers 0–7 (always available)
VR0 $00 / ctrl $80 — Mode control 1
D7-D5Reserved, write 0
D4IE1Horizontal interrupt enable — pairs with register 19 (needs unlocking)
D3M5Extended row mode (Pico9918)
D2M480-column text mode (needs unlocking)
D1M3Graphics II mode
D0EVDExternal video enable
VR1 $01 / ctrl $81 — Mode control 2
D7RAMVRAM size — 0 = 4 KB, 1 = 16 KB
D6BLDisplay — 0 = blanked, 1 = active
D5IE0Vertical interrupt enable
D4M1Text mode
D3M2Multicolor mode
D2Reserved, write 0
D1SIZESprite size — 0 = 8×8, 1 = 16×16
D0MAGSprite magnification — 0 = 1×, 1 = 2×
VR2 $02 / ctrl $82 — Name table base address
D7-D4Reserved, write 0
D3-D0A13-A10Name table base
VR3 $03 / ctrl $83 — Color table base address
On a 64-byte boundary. Becomes the tile attribute table in the enhanced color modes.
VR4 $04 / ctrl $84 — Pattern generator base address
On a 2 KB boundary. Shared by both tile layers.
VR5 $05 / ctrl $85 — Sprite attribute table base address
On a 128-byte boundary. 32 sprites, four bytes each.
VR6 $06 / ctrl $86 — Sprite pattern generator base address
On a 2 KB boundary. 4 KB in 2-bit color, 6 KB in 3-bit color.
VR7 $07 / ctrl $87 — Foreground / background color
Text color in the high nibble, backdrop in the low nibble.
Registers 10–34 (unlocked only)
VR10 $0A / ctrl $8A — Name table 2 base address
D7-D4Reserved, write 0
D3-D0A13-A10Tile layer 2 name table base
VR11 $0B / ctrl $8B — Color table 2 base address
Tile layer 2's color / attribute table, same format and same rules as register 3.
VR15 $0F / ctrl $8F — Status register select and counter control
D7Reserved, write 0
D6CNT_RSTReset the counter
D5CNT_SNAPLatch the counter so it can be read, without stopping it
D4CNT_START1 = run, 0 = stop
D3-D0SR_SELStatus register 0-15 the next status read returns
VR19 $13 / ctrl $93 — Horizontal interrupt scan line
Raise an interrupt when the beam reaches this line. 0 disables it.
VR24 $18 / ctrl $98 — Palette select
D7-D6Reserved, write 0
D5-D4SPSSprite palette select, 0-3
D3-D2T2PSTile layer 2 palette select, 0-3
D1-D0T1PSTile layer 1 palette select, 0-3
VR25 $19 / ctrl $99 — Tile layer 2 horizontal scroll
D7-D3HTOHorizontal tile offset, 0-31
D2-D0HPOHorizontal pixel offset, 0-7
VR26 $1A / ctrl $9A — Tile layer 2 vertical scroll
0-255 pixels, added straight to the Y position. Past the bottom of the display it wraps, or swaps page if vertical paging is on.
VR27 $1B / ctrl $9B — Tile layer 1 horizontal scroll
D7-D3HTOHorizontal tile offset, 0-31
D2-D0HPOHorizontal pixel offset, 0-7
VR28 $1C / ctrl $9C — Tile layer 1 vertical scroll
Same as register 26, for the main tile layer.
VR29 $1D / ctrl $9D — Page sizes and pattern plane spacing
D7-D6SPGSSprite pattern plane spacing — 00 = 2 KB, 01 = 1 KB, 10 = 512 B, 11 = 256 B
D5HPSIZE2Tile layer 2 horizontal pages — 0 = one, 1 = two (64 tiles wide)
D4VPSIZE2Tile layer 2 vertical pages
D3-D2TPGSTile pattern plane spacing, same encoding as SPGS
D1HPSIZE1Tile layer 1 horizontal pages
D0VPSIZE1Tile layer 1 vertical pages
VR30 $1E / ctrl $9E — Maximum sprites per scan line
D7-D5Reserved, write 0
D4-D0SPRTMAXSprites per scan line
VR31 $1F / ctrl $9F — Bitmap layer control
D7BML_ENEnable the bitmap layer
D6BML_PRI0 = below the tile layers, 1 = above them
D5BML_TRANSTreat pixel value 0 as transparent
D4BML_FAT0 = 1×1 pixels, four colors; 1 = 2×1 pixels, sixteen colors
D3-D0BML_PALPalette select — shifted up two bits and combined with the pixel value
VR32 $20 / ctrl $A0 — Bitmap layer base address
Where the bitmap lives in VRAM. Address = VR32 << 6, so a 64-byte boundary.
VR33 $21 / ctrl $A1 — Bitmap layer X position
0-255. The bitmap moves independently of everything else, and scroll registers do not touch it.
VR34 $22 / ctrl $A2 — Bitmap layer Y position
The first scan line the bitmap is drawn on. Nothing above it.

F18A Mode — Registers

A.C. Wright 6502 BIOS
F18A mode · Pico9918
Registers 35–63 (unlocked only)
VR35 $23 / ctrl $A3 — Bitmap layer width
Width of one bitmap row, in bytes. Every byte is four pixels wide whichever pixel format is selected.
VR36 $24 / ctrl $A4 — Bitmap layer height
How many rows are drawn, starting from the row in register 34.
VR47 $2F / ctrl $AF — Palette control and data-port mode
D7DPMData port mode — 0 = writes go to VRAM, 1 = writes go to the palette
D6AUTOStep to the next palette entry after each complete entry
D5-D0PAL_IDXPalette entry, 0-63
VR48 $30 / ctrl $B0 — VRAM address increment
Signed byte added to the VRAM address after every read or write. Default 1.
VR49 $31 / ctrl $B1 — Enhanced color modes and display options
D7T2_ENEnable tile layer 2
D6ROW300 = 24 rows, 1 = 30 rows (240 lines)
D5-D4ECMTTile color mode — 0 = original, 1 / 2 / 3 = one, two or three bits per pixel
D3Y_REALSprite Y is the real coordinate rather than the stock chip's off-by-one
D2Reserved, write 0
D1-D0ECMSSprite color mode, same encoding as ECMT
VR50 $32 / ctrl $B2 — General control and GPU triggers
D7VR_RSTReset — relocks the card and restores register defaults; the palette survives
D6GPU_HTRIGRun the GPU at the start of every scan line
D5GPU_VTRIGRun the GPU once per frame
D4TL1_OFFTurn off tile layer 1 — sprites, the bitmap layer and tile layer 2 carry on
D3RPT_MAX0 = report the fifth sprite the stock way, 1 = report against register 30's limit
D2SCANLINESDim every other line for a CRT look
D1POS_ATTR0 = attributes per pattern name, 1 = attributes per screen position
D0T2_PRI0 = tile layer 2 always on top, 1 = tile layer 2 obeys per-tile priority
VR51 $33 / ctrl $B3 — Maximum sprites per frame
D7-D6Reserved, write 0
D5-D0STOPSPRTSprites processed per frame
VR54 $36 / ctrl $B6 — GPU program counter, high byte
Default $40, which points at the GPU's own RAM.
VR55 $37 / ctrl $B7 — GPU program counter, low byte
Writing this loads the program counter and starts the GPU running. It is the trigger, not just the low byte.
VR56 $38 / ctrl $B8 — GPU control and status
D7-D1Reserved, write 0
D0GPU OPWrite: 0 = reset and load the PC, 1 = run. Read: 1 = running
VR57 $39 / ctrl $B9 — Unlock
Write $1C twice in a row to unlock. Any write to it once unlocked locks it again.
VR58 $3A / ctrl $BA — Configuration option index (Pico9918)
Selects a card configuration option. Writing it also mirrors that option's current value into status register 12.
VR59 $3B / ctrl $BB — Configuration option value (Pico9918)
Writes the option selected by register 58. Options below index 8 are read-only hardware facts and refuse writes.
VR63 $3F / ctrl $BF — Firmware update control (Pico9918)
D7EXECPerform the operation
D6OP0 = verify, 1 = write
D5-D0PAGE256-byte page
Status registers
SR0The stock TMS9918A status byte, and the only one a locked card will give you.
SR1What the card is, and whether the horizontal interrupt fired.
SR2D7 is set while the GPU is running. D6-D0 are seven bits the GPU program can set for the 6502 to read.
SR3Where the beam is. 0 outside the active display.
SR40-999. Not documented for the Pico9918. (F18A only)
SR5The top two bits of the nanosecond count. (F18A only)
SR60-999.
SR7The top two bits.
SR80-999.
SR9The top two bits.
SR100-65535.
SR11The high byte of the second count.
SR12The value of whichever option register 58 last selected. (Pico9918)
SR13The Pico's core temperature, four counts per degree C. Updated every 64 frames. (Pico9918)
SR14Major and minor version, a nibble each. An ACE reads $1A.
SR15Reads back the status register selection written to register 15.
Enhanced color modes
Original2 colors per tile, 1 per sprite · 1 plane · 2 KB pattern table · 4 of 16 palettes
ECM12 colors per tile, 1 per sprite · 1 plane · 2 KB pattern table · 32 of 2 palettes
ECM24 colors per tile, 3 per sprite · 2 planes · 4 KB pattern table · 16 of 4 palettes
ECM38 colors per tile, 7 per sprite · 3 planes · 6 KB pattern table · 8 of 8 palettes
Sprite attribute byte, card unlocked
D7ECEarly clock, unchanged
D6FLIP XMirror the sprite horizontally
D5FLIP YMirror it vertically
D4SIZEPer-sprite size — 0 takes register 1's global setting, 1 forces 16×16
D3-D0PSColor, or palette select in the enhanced color modes
The sources disagree. The Pico9918 reference calls D4 an opaque-sprite flag in 16×16 mode rather than a size override. Both documents agree the bit is new and that it concerns 16×16 sprites; they do not agree on what it does.
Tile attribute byte, enhanced color modes
D7PRIThis tile draws over sprites
D6FLIP XMirror the tile horizontally
D5FLIP YMirror it vertically
D4TRANSColor index 0 is transparent rather than a color
D3-D0PSPalette select
Before you trust this
It cannot be checked here. F18A mode exists on hardware only. Everything on this card is transcribed from Matthew Hagerty’s F18A register sheet and the Pico9918 reference; where those two disagree, the guide says so and this card follows the guide.