; vram_tile.asm -- PIXBLT B,XY: one 32x32 1-bpp dictionary tile to the screen. ; ; Task 4's tile primitive. A dictionary entry is 32 rows of FOUR bytes (32 px ; is two 16-bit words) = 128 bytes = 1024 bits, row-major, LSB first within each ; byte (bit 0 is the leftmost pixel -- the scanout order) -- tilecost.py's ; layout. PIXBLT's B source form reads packed 1-bit ; pixels from a linear bit address and writes an XY destination, so one tile is ; ; SADDR = dict_base + index * 1024 (128 bytes a tile: index << 10) ; SPTCH = 32 (4 bytes a source row) ; DADDR = (ty*32 << 16) | (tx*32) (XY destination) ; DYDX = (32 << 16) | 32 (32 rows, 32 pixels) ; ; DESCRIPTION-register assignments for PIXBLT B,XY (TMS34010 User's Guide, ; instruction reference; vram.asm already uses the same values for L,XY and ; vram_b.asm for B,XY): ; SADDR = B0 source bit address (1 bpp, packed) ; SPTCH = B1 source pitch in bits (4 bytes = 32 bits a row) ; DADDR = B2 destination XY: (y << 16) | x ; DPTCH = B3 destination pitch in bits (0x800 = 256-byte screen row) ; OFFSET = B4 VRAM base bit address ; DYDX = B7 dimensions in XY form: (rows << 16) | columns ; ; COLOR0 = B8 pixel value for a clear source bit (0 = black) ; COLOR1 = B9 pixel value for a set source bit (0xFFFF = white) ; ; B8/B9 are NOT I/O registers: they are implied operands of every graphics ; instruction, and a PIXBLT B expands a packed 1-bpp source into pixel values. ; They are set explicitly because the resident OS leaves them arbitrary -- ; measured in the strip work: the first draw run painted every row black ; because nothing had set B9. vram_b.asm's comment records the same finding. ; ; PSIZE (0C0000150h) 1 one bit per destination pixel ; CONVSP (0C0000130h) 14h 0x800-bit pitch code (1 << (~0x14 & 0x1F) = 2048) ; CONVDP (0C0000140h) 14h same, for the XY destination ; PMASK (0C0000160h) 0 every plane writable ; CONTROL (0C00000B0h) raster op 0 (replace), CD/RM/RR preserved ; ; Entry point / calling form (ruling R13). The TMS34010 C compiler's argument ; frame is not decoded by any hand-written assembly in this repository; the ; published-word form of vram.asm and vram_b.asm is used instead. This symbol ; takes NO arguments: the two values a caller can change live in .bss words ; ; tile_src the source tile's bit address ; tile_daddr the destination XY word ; ; and the C wrapper tile_blit(src, tx, ty) is the only entry point. B7 (DYDX) ; is the constant 32x32 this primitive exists for. ; ; Two entry points, split by what changes: tile_init_() programs the constants ; (pitch, offset, dimensions, colours, PSIZE/CONVSP/CONVDP/PMASK/CONTROL) once ; per frame, and tile_blit_() then only reloads SADDR and DADDR -- the two ; registers PIXBLT destroys -- before executing it. ; ; Revert note: this file is new in Task 4 and nothing else calls it. To ; revert, delete it, the VRAMTILE entries in build-stream.sh and the ; tile_blit/paint_tiles code in vidstream.c; the strip path (vram_b.asm) does ; not reference any symbol defined here and is unaffected. The disassembly ; this copies is vram_b.asm's, and its value table is quoted above from ; vram_b.asm rather than re-derived. ; ; This file does NOT define _vid_dint_/_vid_eint_: they live in vram_b.asm and ; both objects are linked, so a second definition would be a duplicate symbol. .ref _tile_src .ref _tile_daddr .text ; _tile_init_ -- program everything that does not vary between tiles. ; ; Spec 8.3's hoist, and it is worth real time in MAME: measured per-tile cost ; was ~0.36 ms against the unit's ~40 us, and the call did 11 I/O-register ; accesses plus 8 push/pop pairs for constants that never change. The registers ; this sets -- PSIZE, CONVSP, CONVDP, PMASK, CONTROL and B1 (SPTCH), B3 (DPTCH), ; B4 (OFFSET), B7 (DYDX), B8 (COLOR0), B9 (COLOR1) -- survive PIXBLT (the ; user's guide marks only SADDR/DADDR and B10-B14 as changed), so once per ; frame is enough. ; ; B8/B9 are NOT I/O registers: they are implied operands of every graphics ; instruction, and the resident OS leaves them arbitrary -- measured in the ; strip work: the first draw run painted every row black because nothing had ; set B9. .globl _tile_init_ _tile_init_: setf 32, 0, 1 movi 020h, b1 ; SPTCH = 32 bits = four bytes a tile row movi 800h, b3 ; DPTCH = 2048 bits = 256-byte screen row movi 04000000h, b4 ; OFFSET = VRAM base movi 0200020h, b7 ; DYDX = (32 rows << 16) | 32 pixels clr b8 ; COLOR0 = 0 (black) movi 0FFFFh, b9 ; COLOR1 = all planes set (white) 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 (all planes writable) move a1, @0C0000170h, 0 ; upper half, for forward compatibility ; raster op 0 (replace), CD/RM/RR preserved move @0C00000B0h, a1, 0 ; CONTROL andi 0801Fh, a1 move a1, @0C00000B0h, 0 move @0C00000B0h, a1, 0 ; read back: I/O writes are pipelined rets ; _tile_blit_ -- one 32x32 tile, everything already programmed. ; ; Only B0 (SADDR) and B2 (DADDR) vary, and PIXBLT destroys both, so those two ; are the only registers this saves and reloads. tile_init_() must have run. ; ; Revert note: this file is new in Task 4 and nothing else calls it. To ; revert, delete it, the VRAMTILE entries in build-stream.sh and the ; tile_blit/paint_tiles code in vidstream.c; the strip path (vram_b.asm) does ; not reference any symbol defined here and is unaffected. .globl _tile_blit_ _tile_blit_: setf 32, 0, 1 move b0, -*sp, 1 move b2, -*sp, 1 move @_tile_src, b0, 1 ; SADDR: dictionary entry, index << 10 bits move @_tile_daddr, b2, 1 ; DADDR (XY): (ty*32 << 16) | tx*32 pixblt b, xy move *sp+, b2, 1 move *sp+, b0, 1 rets .end