Files
vt1200/harness/udpstream/vram.asm
T
arti d99a9cdb6c udpstream: hardware FILL L makes full-screen writes 70x faster (30.6 fps on the unit)
Byte stores to VRAM measure 2284 ms per 1280x1024 frame on the real unit
(0.44 fps) -- about a scanline period per byte, i.e. almost no access through
the arbiter.  vram.asm now drives the GSP's array engine instead: FILL L with
DADDR/DPTCH/DYDX/COLOR1 (B2/B3/B7/B9), PSIZE=1, PMASK=0 and PPOP=0, per the
TMS34010 User's Guide's implied-operand table, with CONTROL read-modify-written
so CD/RM/RR survive.

Measured: 32.7 ms/frame, 30.6 fps on the unit; 27.1 ms in MAME (74x over byte
stores there, 70x on hardware).  2,508,224 destination words/s = 0.40 us/word.

Consequence for video: a full uncompressed frame is wire-limited at 8 fps
(163840 B at 1.27 MB/s); a small source expanded on the device is limited by
the ~33 ms transfer, i.e. ~30 fps full screen if the expansion uses PIXBLT.

build-lance.sh assembles vram.asm and links VRAM.obj; MARK moved to 0x01A00000
because .text had come within 146 bytes of it.
2026-10-30 17:32:59 +02:00

60 lines
2.1 KiB
NASM

; vram.asm -- hardware framebuffer fill for the VT1200 payload.
;
; The C loop in lance_cmd.c writes the screen one byte at a time and measures
; ~2.0 s per 1280x1024 frame (0.5 fps). FILL L does the same job in the GSP's
; array engine: the manual's Table 13-6 gives (1 + N*G)L states for a long row,
; with G=2 for "replace, no plane masking", N=80 words/row and L=1024 rows --
; about 165k states, i.e. ~16 ms at a 10 MHz state, roughly 120x faster.
;
; Implied operands of FILL L (TMS34010 User's Guide, instruction reference):
; DADDR = B2 linear address of the first pixel of the array
; DPTCH = B3 pitch between rows, in bits
; DYDX = B7 dimensions in XY form: (rows << 16) | columns
; COLOR1 = B9 fill colour / 16-bit pattern
; CONTROL (0C00000B0h) bits 10-14 PPOP = 0 -> replace (S -> D)
; PSIZE (0C0000150h) 1 -> one bit per pixel
; PMASK (0C0000160h) 0 -> no plane protected, all bits writable
;
; DADDR and DYDX are modified by the instruction, so they are reloaded on every
; call. The pattern is read from the C global _vram_pattern (a .bss word) so
; no calling-convention assumption is needed.
.ref _vram_pattern
.text
.globl _vram_fill_
_vram_fill_:
setf 32, 0, 1
move b2, -*sp, 1
move b3, -*sp, 1
move b7, -*sp, 1
move b9, -*sp, 1
; --- destination array -------------------------------------------------
movi 04000000h, b2 ; VRAM base, bit address
movi 800h, b3 ; 2048 bits = 256-byte row pitch
movi 04000500h, b7 ; DY=1024 (0400h), DX=1280 (0500h)
move @_vram_pattern, b9, 1 ; fill pattern
; --- pixel format ------------------------------------------------------
movi 1, a1
move a1, @0C0000150h, 0 ; PSIZE = 1
clr a1
move a1, @0C0000160h, 0 ; PMASK = 0 (all planes writable)
move a1, @0C0000170h, 0 ; upper half, for forward compatibility
; --- graphics operation: replace, no transparency, no window ----------
move @0C00000B0h, a1, 0 ; CONTROL
andi 0801Fh, a1 ; keep CD (15) and RM/RR (2-4) only
move a1, @0C00000B0h, 0
move @0C00000B0h, a1, 0 ; read back: I/O writes are pipelined
fill l
move *sp+, b9, 1
move *sp+, b7, 1
move *sp+, b3, 1
move *sp+, b2, 1
rets
.end