; vram_b.asm -- PIXBLT B,XY: a packed 1-bpp RAM row straight to the screen. ; ; Task 5's blit primitive. PIXBLT's B source form reads the source as packed ; 1-bit pixels from a LINEAR bit address and writes an XY destination, which is ; exactly the strip decoder's shape: a 1280-pixel row (160 bytes) in the slot, ; painted down `stretch` screen rows. ; ; The vertical stretch is one instruction, not a loop over screen rows: SPTCH ; = 0 makes every source row read the SAME source address, so a PIXBLT whose ; DYDX names `stretch` rows paints the one row `stretch` times. ; ; DESCRIPTION-register assignments for PIXBLT B,XY (TMS34010 User's Guide, ; instruction reference; vram.asm already uses the same values for L,XY): ; SADDR = B0 source bit address (1 bpp, packed) ; SPTCH = B1 source pitch in bits; 0 = do not advance the source ; 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: COLOR0 and COLOR1 are implied B-register ; operands of every graphics instruction (vram.asm's FILL passes its pattern in ; B9 for the same reason). They are explicit here because a PIXBLT B expands ; a packed 1-bpp source into pixel values, so whatever the resident OS left in ; B9 becomes the colour of every set pixel -- measured: the first draw run ; painted every row it blitted black because nothing had set B9 (the padding ; past column 1280, which the blit does not write, kept the OS's old bytes). ; ; 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 ; ; _blit_sptch: the source pitch in bits. Zero is the stretch form (every ; source row reads the same address); 1280 is the rectangle form, where each ; source row is one screen row of the picture -- one PIXBLT then copies a whole ; group of rows, which is what makes a full frame ~32 calls instead of ~1,200. ; ; Entry points. The TMS34010 C compiler passes arguments in its own frame- ; pointer scheme, and no hand-written assembly in this repository has ever ; DECODED that frame: the ROM thunks in entry.asm forward the caller's stack ; frame through `calla` without touching it, and the two array primitives in ; vram.asm take their inputs from published words in .bss with a no-argument ; entry (called by lance_cmd.c, measured on the unit). This primitive follows ; the vram.asm form, so the three interface values named in the plan live in ; blit_src / blit_daddr / blit_dydx (blit_sptch only exists for vram.asm and is ; ignored: this primitive always sets SPTCH = 0). The C side wraps them in ; blit_row() so the call reads as blit_row(src, daddr_xy, dydx). ; ; All inputs are reloaded on every call: PIXBLT leaves SADDR/DADDR advanced, so ; a caller that "saves" them saves a half-consumed rectangle. ; ; _vid_dint_ / _vid_eint_ -- interrupts off/on. The C compiler cannot emit ; DINT/EINT, and spec section 8.9 wants the OS masked for the whole burst so a ; resident repaint cannot tear the picture. .ref _blit_src .ref _blit_sptch .ref _blit_daddr .ref _blit_dydx .text .globl _vram_blit_b_ _vram_blit_b_: 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 b8, -*sp, 1 move b9, -*sp, 1 move @_blit_src, b0, 1 ; SADDR: packed 1-bpp source row move @_blit_sptch, b1, 1 ; SPTCH: 0 = stretch, 1280 = rectangle move @_blit_daddr, b2, 1 ; DADDR (XY) movi 800h, b3 ; DPTCH = 2048 bits = 256-byte row pitch movi 04000000h, b4 ; OFFSET = VRAM base move @_blit_dydx, b7, 1 ; DYDX (rows, columns) clr b8 ; COLOR0 = 0 (black) movi 0FFFFh, b9 ; COLOR1 = all planes set (white) ; --- pixel format ------------------------------------------------------ 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 ; --- 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 pixblt b, xy move *sp+, b9, 1 move *sp+, b8, 1 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 .globl _vid_dint_ _vid_dint_: dint rets .globl _vid_eint_ _vid_eint_: eint rets .end