mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-10-31 12:05:05 +02:00
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.
60 lines
2.1 KiB
NASM
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
|