aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoruser <user@clank>2026-09-23 16:29:47 +0200
committeruser <user@clank>2026-09-23 16:29:47 +0200
commit364ecdd32f0cecb83983ca3e4a2acaac4c3251c7 (patch)
tree137d746f1f6a53db600a1321285f1eb64acbef77
parentusr: ircd - an IRC server running on the Game Boy (diff)
downloadgbos-364ecdd32f0cecb83983ca3e4a2acaac4c3251c7.tar.gz
gbos-364ecdd32f0cecb83983ca3e4a2acaac4c3251c7.tar.xz
gbos-364ecdd32f0cecb83983ca3e4a2acaac4c3251c7.zip
term: write the palette attribute for every re-rendered tile, not just the cursor's
Reported as "the nickname w00t renders with its first and last letter a different colour". It was neither the nick hash nor the Fano palette tables: the colour buffer was right, the tile pixels were right, and the tilemap ATTRIBUTE - which selects the palette - was stale. render_tile writes pixels and refreshes the attr cache, but only update_cursor_attr ever pushed an attribute into the tilemap, for the tile under the cursor. A batched write (sys_write, i.e. every puts()) renders its whole dirty span through render_tile and then updates exactly one attribute, so the rest of the line kept whatever palette its row was created with - palette 0, whose colours are white, red and cyan. Hence: ordinary white text was always fine, red and cyan were fine by luck, and green/yellow/blue/ magenta silently rendered as red or cyan. In "<w00t>" the brackets are putc'd (attribute written, w and t correct) while the nick is puts'd, so the middle "00" kept the stale palette and came out red. update_tile_attr now does that work for any (row, tile col) and term_write_end calls it for every tile it renders. update_cursor_attr is a thin wrapper. NB the wrapper MUST stay immediately after render_cursor_tile: that path falls through rather than calling, and render_tile clobbers B/C, so the row/column have to be re-read from wCurRow/wCurCol. Putting update_tile_attr there first had it inherit garbage and scribble attributes over unrelated rows - visible as yellow text in the boot log. Verified by decoding recorded frames (control-socket "record", which needs a display run - --headless produces no frames): ansi(1)'s word line now renders red/green/yellow/blue/magenta/cyan/white instead of red/red/cyan/red/cyan/ cyan/white, the per-character bar and RAINBOW! still cycle correctly, and <w00t> is uniformly blue between white brackets (was blue/red/red/blue). Pre-existing: the same capture reproduces on c9f61fc, before this session.
-rw-r--r--src/term.asm71
1 files changed, 46 insertions, 25 deletions
diff --git a/src/term.asm b/src/term.asm
index a3bfe19..1ad120f 100644
--- a/src/term.asm
+++ b/src/term.asm
@@ -764,14 +764,37 @@ render_cursor_tile:
; (possibly just-recolored) cells.
; -----------------------------------------------------------------------------
-; update_cursor_attr - rewrite the tilemap palette attribute for the tile under
-; the cursor, from that tile's two cell colors. The cursor line is always fully
-; on-screen (compute_offset guarantees it), so its physical row = wCurRow minus
-; the view offset with no clamping. Bank bit follows the tile's VRAM position.
+; update_cursor_attr - the cursor tile's attribute (render_cursor_tile falls
+; through to HERE, so this must stay the first routine after it: render_tile
+; clobbers B and C, so the row/col have to be re-read from wCurRow/wCurCol
+; rather than inherited. Its cache entry is fresh.)
; -----------------------------------------------------------------------------
update_cursor_attr:
- ; slot = assign[wCurRow]
ld a, [wCurRow]
+ ld b, a
+ ld a, [wCurCol]
+ srl a ; tile col
+ ld c, a
+ jp update_tile_attr
+
+; -----------------------------------------------------------------------------
+; update_tile_attr - B = screen row, C = tile col: write that tile's palette
+; attribute into the tilemap, taken from the attr cache render_tile just
+; refreshed. Bank bit follows the tile's VRAM position. Preserves B, C, D, E
+; (term_write_end's flush loop holds the row, the column and the dirty span).
+;
+; Every path that re-renders a tile MUST come through here. render_tile only
+; writes pixels + the cache, so a tile whose attribute is never written keeps
+; whatever palette the row was created with - blank rows are palette 0, whose
+; colors are white/red/cyan. That is exactly why coloured text looked right
+; only in those three: batched writes (puts(), i.e. most output) updated the
+; pixels and left the palette behind, so green came out red and yellow cyan.
+; -----------------------------------------------------------------------------
+update_tile_attr:
+ push bc
+ push de
+ ; slot = assign[row]
+ ld a, b
add LOW(wAssign)
ld l, a
ld a, HIGH(wAssign)
@@ -779,8 +802,7 @@ update_cursor_attr:
ld h, a
ld a, [hl]
ld [wTMSlot], a
- ; attr = cache[slot][wCurCol/2] - the cursor tile was just rendered
- ; (render_cursor_tile falls through to here), so the cache is fresh.
+ ; attr = cache[slot][tcol] = COL_BUF + slot*64 + ACACHE + tcol
ld l, a
ld h, 0
add hl, hl
@@ -791,16 +813,15 @@ update_cursor_attr:
add hl, hl ; slot*64
ld de, COL_BUF + ACACHE
add hl, de
- ld a, [wCurCol]
- srl a ; tile col
+ ld a, c
add l
ld l, a
ld a, h
adc 0
ld h, a
ld a, [hl]
- ld [wPalAttr], a ; downstream bank-bit code reads this
- ; bank bit: pos = slot*20 + (wCurCol/2)
+ ld [wPalAttr], a
+ ; pos = slot*20 + tcol; pos >= 256 -> the tile lives in VRAM bank 1
ld a, [wTMSlot]
ld l, a
ld h, 0
@@ -811,26 +832,24 @@ update_cursor_attr:
add hl, hl
add hl, hl ; *16
add hl, de ; *20
- ld a, [wCurCol]
- srl a
+ ld a, c
add l
ld l, a
ld a, h
adc 0
ld h, a ; HL = pos
ld a, [wPalAttr]
- bit 0, h ; pos >= 256 -> VRAM bank 1
- jr z, .noattr_bank
+ bit 0, h
+ jr z, .nobank
or $08
-.noattr_bank
- ld c, a ; C = attribute byte
- ; ring row = (wMapTop + wCurRow) & 31 - the cursor's map row is fixed by
- ; its logical row; the view offset only moves SCY, never the map.
- ld a, [wCurRow]
+.nobank
+ ld e, a ; E = attribute byte
+ ; ring row = (wMapTop + row) & 31 - the map row is fixed by the logical
+ ; row; the view offset only moves SCY, never the map.
+ ld a, b
ld hl, wMapTop
add [hl]
and 31
- ; tilemap attr addr = $9800 + ringrow*32 + (wCurCol/2), VRAM bank 1
ld l, a
ld h, 0
add hl, hl
@@ -840,9 +859,8 @@ update_cursor_attr:
add hl, hl ; *32
ld a, h
add $98
- ld h, a
- ld a, [wCurCol]
- srl a
+ ld h, a ; HL = $9800 + ringrow*32
+ ld a, c
add l
ld l, a
ld a, h
@@ -850,10 +868,12 @@ update_cursor_attr:
ld h, a
ld a, 1
ld [rVBK], a
- ld a, c
+ ld a, e
ld [hl], a
xor a
ld [rVBK], a
+ pop de
+ pop bc
ret
; -----------------------------------------------------------------------------
@@ -1043,6 +1063,7 @@ term_write_end::
call render_tile ; B = row, C = tile col
pop de
pop bc
+ call update_tile_attr ; ...and sync that tile's palette attribute
inc c
ld a, d
cp c