Skip to content

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.

  • Fills and lines — screen clear, rectangles (fill_rect, draw_rect), horizontal and vertical lines, arbitrary Bresenham lines.
  • Pixelsput_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_FF flag: bytes #FF are skipped by the hardware during output, giving “holey” sprites without per-pixel checks.
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 — success

Walkthrough: 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 targetGFX_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).

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.

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:

  1. draw the frame into GFX_TARGET_BACK;
  2. call gfx_swap_buffers — the hidden buffer becomes visible;
  3. 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 2

The 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.

  • 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_buffers and gfx_fade_step from the main loop.
  • Do not print through the DSS console while mode #81 is active — it corrupts the picture (see the overview).
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