Skip to main content

GfxVGA programming guide

Outline #

The GfxVGA video display processor was developed as general purpose display system for use with the Y Ddraig computer. Designed to be capable of being used in many situations from text based OS, graphics user interfaces or as a games system.

The video card supports both 640x480 60hz 65536 colour display or 320x240 by doubling the pixel output. There is 2MB of Video RAM that is used for the bitmap mode as a framebuffer or used by the tile and sprite modes for storing data.

Display Modes #

There are 3 display modes supported. Text, bitmap and tile based modes.

Text Mode #

The following display modes are supported

  • 80x30 character mode (8x16 font)
  • 80x60 character mode (8x8 font)
  • Hardware cursor
  • hardware controlled text blinking
  • 16 total colours from a user defined palette
  • 16/8 background colours, only 8 colours available if blink mode is enabled, otherwise uses the full 16
  • Custom 8x16 or 8x8 fonts

Palette support #

There is a 1024 item palette that is used by the bitmap, tiles, sprite and text modes that can each select between several palette banks within the full palette range.

Bitmap mode #

  • 640x480 and 320x240 resolutions supported
  • RGB-565 mode
  • 8-bpp 256 palette mode
  • Sprites can be used along with bitmap modes
  • Framebuffer pointer to allow for double buffering

Tile Mode #

There are 4 tile layers that support either 16x16 or 8x8 tiles. Each tile uses 16 colours from a palette with index 0 always transparent. Tiles can use 8 different palettes for 128 colours (120 unique with transparent colours).

  • Two 16x16 layers
  • Two 8x8 layers
  • Independent enable per layer
  • 2048 tiles per layer
  • Tile map are is 512x512 pixels
    • 32x32 tiles for 16 pixel tiles
    • 64x64 tiles for 8 pixel tiles
  • Each tile layer supports independent X/Y per pixel scrolling
  • Palette selected from 8 16-colour palettes
  • Selectable palette bank per tile layer from 8 palette banks
  • Flipping on both X and Y axis
  • Layer priority is linear, layers 1-4 will draw in order

Sprites #

  • 256 sprites available
  • 48 visible sprites per line
  • Flipping on X and Y axis
  • Sprite priority handling between sprites and tile layers
  • 16 colours per sprite, index 0 always transparent
  • 16 palette banks for 256 sprite colours
  • Sprites can be displayed on bitmap modes, limited to 320x240 resolution and screen space

Hardware accelerated drawing #

There are hardware accelerated drawing functions that work in 640x480 and 320x240 bitmap modes but only in RGB-565 format for now, not in palette mode.

  • Filled rectangle
  • Line drawing
    • Fast horizontal
    • Fast vertical
  • Filled triangle

An extension to the drawing functions to allow some fast memory operations.

  • Memory fill
  • Linear memory copy
  • 2D memory copy

Registers #

The register interface uses 16-bit accesses on even addresses. The CPU register address bus is split into a register group in bits 6:3 and a register index in bits 2:0, so each group contains up to 8 registers.

Unless otherwise noted:

  • Registers are 16-bit
  • Address values below are byte addresses
  • Multi-word pointers are 20-bit values split into low and high registers
  • Memory data/index registers commonly auto-increment after access

Register map #

Range Group Purpose
0x00-0x0E Control Global control, status, interrupts, SRAM page
0x10-0x1E Bitmap Framebuffer base and line-scroll data pointer
0x20-0x2E Text/Palette Text RAM, cursor, palette RAM, palette bank control
0x30-0x3E Drawing Drawing engine command, colours, mode, base pointer
0x40-0x4E Draw Params Drawing engine parameter registers
0x50-0x5E Tile Layer 1 Tile layer 1 control, pointers, scrolling
0x60-0x6E Tile Layer 2 Tile layer 2 control, pointers, scrolling
0x70-0x7E Tile Layer 3 Tile layer 3 control, pointers, scrolling
0x80-0x8E Tile Layer 4 Tile layer 4 control, pointers, scrolling
0x90-0x9E Sprites Sprite data pointer and indexed sprite attribute access
0xA0-0xAE Misc Font RAM, pattern RAM, line interrupt
0xB0-0xBE Cursor Hardware cursor sprite control, position, data, colours
0xF0-0xFE ID Board version and board ID

Control registers #

Addr Name R/W Description
0x00 Status R/W Device status on read, interrupt clear bits on write
0x02 Control R/W Global display mode and presentation control
0x04 Interrupt control/status R/W Interrupt enable register
0x06 SRAM page control R/W CPU-visible SRAM page select

0x00 Status register #

Read returns current device status. Writing to this register clears interrupt flags through bits 4:2.

b15b14b13b12b11b10b9b8 b7b6b5b4b3b2b1b0
VBLANK HBLANK UNUSED LINEINT VBLANKINT DRAWRDY
  • DRAWRDY: 1 when the drawing engine is idle and can accept a command
  • VBLANKINT: vertical blank interrupt pending
  • LINEINT: line interrupt pending
  • HBLANK: currently in horizontal blank
  • VBLANK: currently in vertical blank
  • Write b4:b2 to clear pending interrupt sources

0x02 Control register #

The control register selects the active display mode and several global presentation features.

b15b14b13b12b11b10b9b8 b7b6b5b4b3b2b1b0
UNUSED TEXTOVL SCANLINE SPRITEEN TEXT60 BLINK CURSOR DEPTH MODE

Scanline mode only applies to 320x240 style output modes and can be used to simulate a CRT-like scanline effect.

MODE `000` Text mode
`001` 320x240 bitmap mode
`010` 640x480 bitmap mode
`011` 320x240 tilemap mode
Other values reserved
DEPTH `000` RGB 5:6:5
`001` 8-bpp paletted
Other values reserved
CURSOR`1` enables the text cursor
BLINK`1` enables text blink attributes
TEXT60`0` = 80x30 text mode, `1` = 80x60 text mode
SPRITEEN`1` enables sprite display
TEXTOVL`1` overlays the text layer on top of bitmap or tile output
SCANLINE `00` no scanlines
`01` black scanlines
`10` grey scanlines
`11` colour scanlines

0x04 Interrupt control/status #

Controls which interrupt sources are enabled.

b15b14b13b12b11b10b9b8 b7b6b5b4b3b2b1b0
UNUSED UNUSED LINEEN VBLEN
  • VBLEN: vertical blank interrupt enable
  • LINEEN: line interrupt enable
  • b2: currently unused in the interrupt generation path
  • Other bits are unused on write and read back as zero

0x06 SRAM page control #

Selects the CPU-visible SRAM page.

b15b14b13b12b11b10b9b8 b7b6b5b4b3b2b1b0
UNUSED PAGE
  • PAGE: SRAM page select

Bitmap registers #

These registers control the framebuffer base address and the line-scroll table base address.

Addr Name R/W Description
0x10 Framebuffer base low R/W Low 16 bits of framebuffer pointer
0x12 Framebuffer base high R/W High 4 bits of framebuffer pointer in b3:b0
0x18 Line-scroll base low R/W Low 16 bits of line-scroll pointer
0x1A Line-scroll base high R/W High 4 bits of line-scroll pointer in b3:b0

Notes:

  • Both pointers are 20-bit SRAM addresses
  • 0x14, 0x16, 0x1C, and 0x1E are currently unused in this block

Text and palette registers #

These registers give indexed access to text RAM and palette RAM, plus cursor and palette bank configuration.

Addr Name R/W Description
0x20 Text address R/W 13-bit text RAM index
0x22 Text data R/W Text RAM data at current index, auto-increments index
0x24 Cursor position R/W Cursor position in text memory
0x26 Cursor size R/W Cursor start/end scanline control
0x28 Palette address R/W 10-bit palette index
0x2A Palette data R/W Palette entry at current index, write auto-increments index
0x2C Palette control 0 R/W Text/bitmap palette bank control
0x2E Palette control 1 R/W Tile/sprite palette bank control

Text address and data #

  • 0x20 uses b12:b0 for the text RAM index
  • 0x22 accesses the current text RAM word
  • Writing 0x22 increments the text index
  • Reading 0x22 also increments the text index

Cursor registers #

The register block exposes:

  • 0x24 cursor position
  • 0x26 cursor size

The reset value for cursor size is 0x0E0D.

0x24 cursor position:

b15b14b13b12b11b10b9b8 b7b6b5b4b3b2b1b0
CURSOR Y CURSOR X

0x26 cursor size:

b15b14b13b12b11b10b9b8 b7b6b5b4b3b2b1b0
UNUSED END UNUSED START

Current implementation in the text generator decodes:

  • cursor_pos[7:0]: cursor X character position
  • cursor_pos[15:8]: cursor Y character position
  • cursor_size[3:0]: cursor start scanline
  • cursor_size[11:8]: cursor end scanline

With the reset value 0x0E0D, the default cursor spans scanlines 13 through 14.

Palette address and data #

  • 0x28 uses b9:b0 for the palette index
  • 0x2A accesses one 16-bit palette entry
  • Writing 0x2A increments the palette index
  • Reads from 0x2A use the current palette index without incrementing it

Palette control registers #

These registers are consumed by the display pipeline as follows:

0x2C palette control 0:

b15b14b13b12b11b10b9b8 b7b6b5b4b3b2b1b0
UNUSED TEXT PAL BANK BITMAP PAL BANK

0x2E palette control 1:

b15b14b13b12b11b10b9b8 b7b6b5b4b3b2b1b0
UNUSED SPR TILE4 TILE3 TILE2 TILE1
  • TEXT PAL BANK: text palette bank select
  • BITMAP PAL BANK: bitmap palette bank select
  • TILE1..TILE4: tile layer palette bank selects
  • SPR: sprite palette bank select

Drawing registers #

The drawing engine is split into command/control registers and parameter registers.

Command/control block #

Addr Name R/W Description
0x30 Draw command R/W Command code in b6:b0; write starts command processing
0x32 Draw base low R/W Low 16 bits of drawing target base address
0x34 Draw base high R/W High 4 bits of drawing target base address
0x36 Draw colour 0 R/W Primary colour/pattern input
0x38 Draw colour 1 R/W Secondary colour input
0x3A Draw mode R/W Draw operation mode in b2:b0
0x3C Draw pattern R/W 16-bit pattern register

Implemented command values:

  • 0x00: none
  • 0x01: filled rectangle
  • 0x02: line
  • 0x03: vertical line
  • 0x04: horizontal line
  • 0x05: filled triangle
  • 0x06: linear memory copy
  • 0x07: 2D memory copy
  • 0x08: linear memory fill

Implemented draw modes:

  • 0: solid
  • 1: XOR
  • 2: transparent
  • 3: reverse transparent

The current parameter usage is implementation-defined but stable enough to document.

Parameter block #

Addr Name R/W Description
0x40 Draw param 0 R/W Command parameter 0
0x42 Draw param 1 R/W Command parameter 1
0x44 Draw param 2 R/W Command parameter 2
0x46 Draw param 3 R/W Command parameter 3
0x48 Draw param 4 R/W Command parameter 4
0x4A Draw param 5 R/W Command parameter 5
0x4C Draw param 6 R/W Command parameter 6

Current parameter usage by command #

Command Param 0 Param 1 Param 2 Param 3 Param 4 Param 5 Param 6
Filled rectangle X0 Y0 X1 Y1 unused unused unused
Line X0 Y0 X1 Y1 unused unused unused
Horizontal line X0 Y0 X1 unused unused unused unused
Vertical line X0 Y0 unused Y1 unused unused unused
Filled triangle X0 Y0 X1 Y1 X2 Y2 unused
Linear memory copy source low source high dest low dest high word count unused unused
2D memory copy source low source high dest low dest high width in words height in lines stride in words, 0 = tightly packed
Linear memory fill dest low dest high word count fill value unused unused unused

Notes:

  • Coordinates are clamped internally to the active display area before drawing starts
  • Pointer pairs use a 20-bit address split as low 16 bits plus high 4 bits
  • Rectangle coordinates are normalized internally so X0/X1 and Y0/Y1 may be supplied in either order
  • draw_pattern is used by rectangle and line operations

Tile layer registers #

There are four identical tile layer register banks:

  • Layer 1: 0x50-0x5E
  • Layer 2: 0x60-0x6E
  • Layer 3: 0x70-0x7E
  • Layer 4: 0x80-0x8E

Each bank contains the following registers:

Offset Name R/W Description
+0x0 Tile control R/W Layer control bits in b2:b0
+0x2 Tile data low R/W Low 16 bits of tile graphics base pointer
+0x4 Tile data high R/W High 4 bits of tile graphics base pointer
+0x6 Tile map low R/W Low 16 bits of tile map base pointer
+0x8 Tile map high R/W High 4 bits of tile map base pointer
+0xA Scroll X R/W Horizontal scroll
+0xC Scroll Y R/W Vertical scroll

For each layer:

  • Tile data and tile map pointers are 20-bit SRAM addresses
  • Scroll registers are 16-bit values
  • Control uses only b2:b0

Tile control register:

b15b14b13b12b11b10b9b8 b7b6b5b4b3b2b1b0
UNUSED LINE SCR ENABLE
  • ENABLE: layer enable
  • LINE SCR:
    • 00: disabled
    • 01: shared line-scroll table
    • 10: per-layer line-scroll table
    • 11: reserved

Sprite registers #

This block contains a sprite graphics base pointer plus indexed access to one sprite descriptor at a time.

Addr Name R/W Description
0x90 Sprite data low R/W Low 16 bits of sprite graphics base pointer
0x92 Sprite data high R/W High 4 bits of sprite graphics base pointer
0x94 Sprite index R/W Selects sprite descriptor entry
0x96 Sprite X position R/W 10-bit X position
0x98 Sprite Y position R/W 10-bit Y position
0x9A Sprite tile R/W 11-bit tile index
0x9C Sprite attributes R/W Enable, priority, flip, palette

Sprite index #

  • 0x94 uses b7:b0 for the sprite number
  • Selecting a sprite triggers an internal descriptor fetch into a latch

Sprite attribute layout #

On write to 0x9C:

b15b14b13b12b11b10b9b8 b7b6b5b4b3b2b1b0
EN UNUSED PRIORITY FLIPY FLIPX PALETTE
  • EN: sprite enable
  • PRIORITY: sprite priority field
  • FLIPY: vertical flip
  • FLIPX: horizontal flip
  • PALETTE: palette select

Current sprite format and priority behaviour #

The current sprite pipeline uses:

  • 16x16 pixels per sprite
  • 4-bpp tile data format
  • 16-colour per-sprite palettes with index 0 transparent
  • up to 48 visible sprites per line

Within the sprite renderer:

  • lower numeric sprite priority wins over higher numeric sprite priority
  • if two sprites overlap, the lower priority value overwrites the higher one in the sprite line buffer

At final composition against tile layers:

  • sprite priorities 0 and 1 are above all tile layers
  • priorities 2 and 3 are between tile layer 4 and tile layer 3
  • priorities 4 and 5 are between tile layer 3 and tile layer 2
  • priorities 6 and 7 are between tile layer 2 and tile layer 1
  • priority 8 is behind all tile layers
  • priorities 9 to 15 are also treated as furthest back by the compositor

Hardware cursor registers #

This block controls the hardware cursor sprite overlay and its pattern RAM.

Addr Name R/W Description
0xB0 Cursor control R/W b0 enables the hardware cursor
0xB2 Cursor X R/W 10-bit cursor X position
0xB4 Cursor Y R/W 10-bit cursor Y position
0xB6 Cursor data address R/W 7-bit cursor pattern word address
0xB8 Cursor data W Writes one 16-bit cursor pattern word and auto-increments address
0xBA Cursor colour 1 R/W RGB565 cursor colour 1
0xBC Cursor colour 2 R/W RGB565 cursor colour 2
0xBE Cursor colour 3 R/W RGB565 cursor colour 3

Notes:

  • Cursor X and Y use b9:b0
  • Cursor pattern address uses b6:b0
  • Writing 0xB8 increments the cursor pattern address
  • The current register block does not provide readback for cursor pattern data, only for the address and colour/control registers

0xB0 cursor control:

b15b14b13b12b11b10b9b8 b7b6b5b4b3b2b1b0
UNUSED ENABLE

0xB2 cursor X and 0xB4 cursor Y:

b15b14b13b12b11b10b9b8 b7b6b5b4b3b2b1b0
UNUSED POSITION

0xB6 cursor data address:

b15b14b13b12b11b10b9b8 b7b6b5b4b3b2b1b0
UNUSED ADDR

Miscellaneous registers #

Addr Name R/W Description
0xA0 Font address R/W 13-bit font RAM index
0xA2 Font data R/W 8-bit font RAM data, auto-increments index
0xA4 Pattern address R/W 10-bit pattern RAM index
0xA6 Pattern data R/W 16-bit pattern RAM data, auto-increments index
0xA8 Line interrupt Y R/W Scanline for line interrupt

Details:

  • Font data uses only b7:b0
  • Reading or writing font data auto-increments the font index
  • Reading or writing pattern data auto-increments the pattern index
  • 0xA8 uses b9:b0 for the interrupt line

Line interrupt timing #

The line interrupt compare runs from the VGA-domain timing path and is edge-qualified so the same line does not retrigger repeatedly.

Current behaviour:

  • In bitmap and tilemap modes, the compare is performed against the logical 320x240 line number, derived from the VGA line number by dividing by 2
  • In text mode, the compare is performed against the full VGA line number
  • The compare happens around hblank_start, using the upcoming line value from the timing pipeline
  • Vertical blank resets the one-shot tracking used to prevent duplicate triggers on the same line

Software should therefore treat the line interrupt value as:

  • logical line coordinates in 320x240 bitmap/tile modes
  • full 640x480 line coordinates in text mode

Identification registers #

Addr Name R/W Description
0xFC Board version Read Returns major version in high byte and minor version in low byte
0xFE Board ID Read Returns board type ID duplicated in both bytes

For the current source:

  • Board version = 1.0
  • Board type ID = 0x13

Notes for software #

  • Reads are pipelined in the register controller, so software should honour the bus handshake rather than assume a purely combinational register read
  • Text, font, pattern, and some palette accesses use indexed data ports rather than flat address-mapped RAM windows
  • Several registers are implemented here as raw control fields, while their detailed meaning is defined by the downstream rendering blocks

Bus access pattern #

The register file is handshake-based rather than purely timing-based.

Typical software access pattern:

  1. Present register address and data with the correct read/write direction.
  2. Assert the register request.
  3. Wait for register acknowledge.
  4. On reads, sample returned data when acknowledge is asserted.
  5. Deassert the request before starting the next access.

This matters most for:

  • all reads, because they are pipelined through the register controller
  • indexed text/font/pattern/palette accesses, where the address register and data register are separate operations