mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-11-01 12:14:56 +02:00
The tile pipeline packed every row MSB first: pixel i -> bit 7 - i % 8. The
encoder and tile_check.py shared that convention, so every MAME replay check
passed while a display showed each group of eight pixels mirrored.
Evidence, from the real clip's own replay dump (vram-replay-200.bin, frame 200
of Bad Apple, 1,228,800 pixels):
decoded MSB first 1,215 mismatched <- what the pipeline produced
decoded LSB first 3,113 mismatched <- the mirrored picture, a sawtooth
and both the real unit and MAME decode LSB first: dwt/screenshot.py --real
("LSB-first bits", measured on live VRAM) and vt1200.cpp's
(vram[bit >> 4] >> (bit & 15)) & 1. A zoomed edge of that dump showed the
comb of triangles; after this change the same edge is a smooth curve.
vidsrc.Rows.pack_row now sets bit i % 8 of byte i // 8. The test that pins it
was written first and watched fail: it decodes the packed row with the
hardware's rule, which no MSB-first packer can pass. The two older tests that
asserted MSB first were rewritten -- they were asserting the bug -- and the
synthetic clip now packs through a bit-reversal table, so the committed cache
is regenerated (PSNR 29.47 -> 31.30 dB). The layout claims in tilecost.py,
vram_tile.asm and make_tiles.load_clip are corrected so the clip format states
the order instead of leaving it to whoever writes the frames.
Separately, MAME's renderer reads 128-byte rows while a payload targeting the
real unit writes 256-byte rows (vram_tile.asm DPTCH=0x800; c-hello/README.md:
"a payload writing at row*2048 bits lands on scanline row"). VT1200_VRAM_REAL=1
now draws the framebuffer at 2048 bits / 1280 px from x=0. Off by default: the
Level-1 error text is only legible at the derived 128-byte pitch, and that is
what the faithful boot needs. The branch only touches the bitmap, so the
regression baseline is unmoved (PROG_FRAMES=200 -> PC=3FDCE400, samples=198,
3 distinct PCs), and the default frame-3000 render of the Terminal Manager is
unchanged.
Verified end to end on the 3,292-frame Bad Apple clip: RX_OK=3196, TILES_DROP=0,
3292/3292 frames dumped and matched by tile_check.py, and the dumps decode to
1,379 / 4,125 mismatched pixels of 1,228,800 (quantisation) under the hardware
rule versus 3,101 / 9,793 under MSB. MAME's own frame dumps with
VT1200_VRAM_REAL=1 show the clip unsheared.
Revert note for the driver: delete the m_render_real branch and its getenv and
vt1200.cpp returns to the measured 128-byte renderer byte for byte. No second
reader reviewed that citation; it is quoted in the comment for the next one.
115 lines
4.7 KiB
NASM
115 lines
4.7 KiB
NASM
; 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. All inputs are reloaded on
|
|
; every call: PIXBLT leaves SADDR/DADDR and the B registers it advanced in a
|
|
; half-consumed state, so a caller that "saved" them would save that.
|
|
;
|
|
; 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
|
|
.globl _tile_blit_
|
|
_tile_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 b8, -*sp, 1
|
|
move b9, -*sp, 1
|
|
|
|
move @_tile_src, b0, 1 ; SADDR: dictionary entry, index << 10 bits
|
|
movi 020h, b1 ; SPTCH = 32 bits = four bytes a tile row
|
|
move @_tile_daddr, b2, 1 ; DADDR (XY): (ty*32 << 16) | tx*32
|
|
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)
|
|
|
|
; --- 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
|
|
|
|
.end
|