GFX320 — 2D graphics at 320×256×256
GFX320.DLL is a 2D graphics library for Sprinter in DSS mode #81
(320×256 pixels, 256 colours). It gives ready-made graphics functions to
programs written in assembly, C or Pascal: the application does not program
the video controller, VRAM pages, palette or blitter — it simply calls
functions by number. Internally the library uses the Sprinter hardware
accelerator, but that is an implementation detail, not part of the interface.
The shared rules for loading DLLs and passing arguments are described in the libraries overview.
What it can do
Section titled “What it can do”- Fills and lines — screen clear, rectangles (
fill_rect,draw_rect), horizontal and vertical lines, arbitrary Bresenham lines. - Pixels —
put_pixel/get_pixel. - Double buffering — copying rectangles and whole buffers, switching the
visible screen (
swap_buffers), moving and scrolling regions, restoring the background from a mirror kept in ordinary memory. - Palette — loading all 256 RGB colours, a range, or a single colour.
- Fade — smooth fade-out and fade-in across 33 brightness levels; the library performs one step per call, the pace is up to the application (typically once per frame).
- 16×16 tiles — drawing single tiles, spans, lists, whole tilemaps and metatiles from memory pages prepared by the application.
- Transparency — the
GFX_KEY_FFflag: bytes#FFare skipped by the hardware during output, giving “holey” sprites without per-pixel checks.
Quick start (assembly)
Section titled “Quick start (assembly)” include "gfx320.inc"
ld bc,#0050 ; DSS SETVMOD ld a,#81 ; we select mode 320x256x256 ourselves rst #10
ld hl,libname ; "GFX320.DLL",0 ld a,3 ; load the DLL into window WIN3 call LIBMAN.l_load jp c,load_error ld (handle),hl
; clear the visible screen with colour 0 ld hl,(handle) ld a,0 ; colour ld e,GFX_TARGET_FRONT ld b,GFX_CLEAR ; function number from gfx320.inc call LIBMAN.l_call jp c,dispatch_error ; libman error or a jp nz,gfx_error ; GFX320 status: 0 — successWalkthrough: the application enables mode #81 itself (the library never
touches the video mode), loads the DLL through libman and calls GFX_CLEAR.
Arguments travel in registers A, DE, IX, IY; here E selects the
target — GFX_TARGET_FRONT (the visible screen) or GFX_TARGET_BACK
(the hidden buffer). The status comes back in A: zero means success,
#10..#17 are the GFX_ERR_* codes (bad argument, off-screen coordinates
and so on).
Quick start (C, SDCC)
Section titled “Quick start (C, SDCC)”The package includes an SDCC binding — the gfx320.h header and a wrapper
library:
#include "gfx320.h"
/* handle — from the application's libman loader */gfx_u8 draw(gfx_u8 handle) { gfx320_rect_t panel = { 16, 16, 288, 48, /* x, y, width, height */ 4, /* colour */ GFX_TARGET_FRONT, /* where to draw */ {0, 0, 0} /* internal fields */ }; gfx_u8 status;
gfx320_bind(handle); /* attach wrappers to the DLL */ status = gfx320_clear(0, GFX_TARGET_FRONT); if (status) return status; status = gfx320_fill_rect(&panel); /* a 288x48 panel in colour 4 */ if (status) return status; return gfx320_hline(16, 80, 288, 15, GFX_TARGET_FRONT);}The wrappers mirror the register ABI one-to-one: each function returns the
same status that would arrive in register A. Larger arguments (rectangles,
tile descriptors) are plain structures — in assembly they correspond to
packed descriptors whose field offsets are listed in gfx320.inc.
Double buffering and the mirror
Section titled “Double buffering and the mirror”In mode #81 Sprinter has two screen buffers; a bit in the RGMOD register
decides which one is visible. The classic game loop with GFX320:
- draw the frame into
GFX_TARGET_BACK; - call
gfx_swap_buffers— the hidden buffer becomes visible; - repeat.
Besides VRAM, the library keeps a mirror of the screen in ordinary
memory. It is what makes get_pixel, the copy operations and restore_rect
work — the latter quickly restores the background under a sprite without
redrawing the scene. The GFX_VRAM_ONLY flag draws past the mirror (faster),
but the mirror never “sees” such pixels — they cannot be read back or used
as a copy source.
A tile is a 16×16-pixel image (256 bytes). Tiles live in 16-KB memory pages,
64 per page; the application allocates the pages (DSS #3D), queries their
physical numbers (BIOS #C5) and passes the table to gfx_set_page_table
once. From then on any tile is addressed by a “page + slot” pair.
You don’t have to build the pages by hand — the package includes a packer that slices an indexed PNG/BMP into tiles:
python3 gfx320/tools/tilepack.py assets.png build/tiles \ --keyed --transparent-index 0 \ --metatile-width 2 --metatile-height 2The output is ready-made 16-KB pageNN.bin files, a palette and a JSON
manifest with slot numbers. The --keyed flag turns the chosen colour into
the transparent byte #FF for drawing with GFX_KEY_FF.
Limitations
Section titled “Limitations”- During tile operations the source page is mapped into window WIN0 with interrupts disabled, so the code, the stack and the DLL itself must stay out of WIN0.
- The library is not reentrant: do not call its functions from an interrupt
handler. Set a frame flag in the ISR and call
gfx_swap_buffersandgfx_fade_stepfrom the main loop. - Do not print through the DSS console while mode
#81is active — it corrupts the picture (see the overview).
Package contents
Section titled “Package contents”| File | Purpose |
|---|---|
GFX320.DLL |
the library — the only file an application needs |
gfx320.inc |
constants and descriptor offsets for sjasmplus |
bindings/sdcc/ |
header and library for C (SDCC) |
bindings/tpascal/ |
include for Turbo Pascal |
tools/tilepack.py |
tile packer for PNG/BMP |
GFX320.EXE |
visual test; applications do not need it |