diff options
| author | user <user@clank> | 2026-09-23 16:29:47 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-09-23 16:29:47 +0200 |
| commit | 364ecdd32f0cecb83983ca3e4a2acaac4c3251c7 (patch) | |
| tree | 137d746f1f6a53db600a1321285f1eb64acbef77 | |
| parent | usr: ircd - an IRC server running on the Game Boy (diff) | |
| download | gbos-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.asm | 71 |
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 |
