mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-11-03 12:33:16 +02:00
Two things the 60 fps work needed, and one ceiling it found. Rectangle blit: a strip frame with stretch 1 has one source row per screen row, so the source advances by 1280 bits and a group of rows inside one fragment is contiguous -- one PIXBLT with SPTCH = 1280 copies the group. Measured on the tile path, a blit call costs ~0.45 ms in MAME regardless of size (1,200 tile calls accepted 9 frames where 128 strip calls accepted 73 for the same pixels), so call count, not word count, is what a frame is charged for. paint_rect() takes the stretch-1 frame 9 rows at a time and falls back to the per-row path if a row straddles a datagram. Ring depth: vidsrc still said RING_DATAGRAMS = 16 and capped a strip frame at 144 rows, which stopped being true when the receive ring was deepened to 32 for the dictionary upload. It is 32 now, the encoder may send up to the header's 255 rows, and the three tests that encoded the old ceiling were updated to it. The ceiling this found: a picture-as-strips full frame is 29 datagrams, i.e. 1,740 datagrams/s at 60 fps, while the emulated LANCE delivers ~450/s (1,935 datagrams over 4.3 s, measured). So keyframes cannot be sent as whole strips at 60 fps in MAME whatever the decoder does -- the datagram rate binds first. The tile delta (about one datagram a frame) remains the right transport; what costs is its blit-call count. Verified: modes rx, draw and tiles still PASS (draw and tiles with their pixel checkers); 155 unit tests pass.
126 lines
4.9 KiB
NASM
126 lines
4.9 KiB
NASM
; 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
|