; 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 ; vram_blit_ -- copy a 1-bpp rectangle from RAM to VRAM with PIXBLT L,XY. ; The manual has no L,L variant; the destination is XY so the hardware forms ; the address from OFFSET + y*CONVDP + x (rom:07ee9db6 does the same with ; MOVI 0x4000000,B4). ; ; _blit_src linear source address (bit address, 1 bpp, SPTCH apart) ; _blit_sptch source pitch in bits; 0 makes every row read the same address ; _blit_daddr destination XY: (y << 16) | x ; _blit_dydx dimensions XY: (rows << 16) | columns .globl _vram_blit_ .ref _blit_src .ref _blit_sptch .ref _blit_daddr .ref _blit_dydx _vram_blit_: setf 32, 0, 1 move b0, -*sp, 1 move b1, -*sp, 1 move b2, -*sp, 1 move b3, -*sp, 1 move b4, -*sp, 1 move b7, -*sp, 1 move @_blit_src, b0, 1 ; SADDR move @_blit_sptch, b1, 1 ; SPTCH move @_blit_daddr, b2, 1 ; DADDR (XY) movi 800h, b3 ; DPTCH = 256 bytes movi 04000000h, b4 ; OFFSET = VRAM base move @_blit_dydx, b7, 1 ; DYDX (rows, columns) movi 1, a1 move a1, @0C0000150h, 0 ; PSIZE = 1 movi 14h, a1 move a1, @0C0000130h, 0 ; CONVSP = pitch code for 0x800 bits move a1, @0C0000140h, 0 ; CONVDP clr a1 move a1, @0C0000160h, 0 ; PMASK = 0 move a1, @0C0000170h, 0 move @0C00000B0h, a1, 0 ; CONTROL: keep CD/RM/RR, raster op = 0 andi 0801Fh, a1 move a1, @0C00000B0h, 0 move @0C00000B0h, a1, 0 ; read back (pipelined I/O) pixblt l, xy move *sp+, b7, 1 move *sp+, b4, 1 move *sp+, b3, 1 move *sp+, b2, 1 move *sp+, b1, 1 move *sp+, b0, 1 rets .end