diff options
| author | user <user@clank> | 2026-07-18 21:32:16 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-07-18 21:32:16 +0200 |
| commit | 74825c20ada40a3bf1fffb4a35f3063b7844aea6 (patch) | |
| tree | 83986703f68091347ece6baaff8aa39abb5f2da5 /src | |
| parent | docs: drop the link-drop investigation writeup (diff) | |
| download | gbos-74825c20ada40a3bf1fffb4a35f3063b7844aea6.tar.gz gbos-74825c20ada40a3bf1fffb4a35f3063b7844aea6.tar.xz gbos-74825c20ada40a3bf1fffb4a35f3063b7844aea6.zip | |
term: cache tile attrs in COL_BUF's spare stride bytes (3.5x scroll)
term_write_tilemap's attribute pass ran color_setup - the full Fano
palette walk - for all 360 tiles on every scroll. render_tile already
computes the attr when a tile changes, so store it (COL_BUF + slot*64
+ ACACHE + tcol; the stride's 24 spare bytes were free) and the attr
pass becomes a table read. update_cursor_attr reads the cache too.
term_init now redraws before writing the tilemap so the cache is warm.
Measured entry-to-return with the emulator cycle counter, ANSI test
screen content: term_write_tilemap 723k -> 114k T-cycles (6.3x),
term_scroll 857k -> 248k (3.5x) - a scroll drops from ~12 frames of
guest CPU to ~3.5.
Diffstat (limited to '')
| -rw-r--r-- | src/term.asm | 66 |
1 files changed, 38 insertions, 28 deletions
diff --git a/src/term.asm b/src/term.asm index d62310e..aebe7e3 100644 --- a/src/term.asm +++ b/src/term.asm @@ -25,6 +25,13 @@ DEF TSTRIDE EQU 64 ; bytes per line-slot in the buffer (power of 2) DEF TERM_BUF EQU $D600 ; 18*64 = 1152 B (WRAMX, above the FS caches) DEF COL_BUF EQU $DA80 ; per-cell fg color, parallel to TERM_BUF (18*64 = 1152 B) DEF COL_OFF EQU COL_BUF - TERM_BUF ; $0480: add to a char addr -> its color addr +DEF ACACHE EQU 40 ; attr cache in COL_BUF's spare stride bytes: the tile + ; attribute (palette bits) for [slot][tcol] lives at + ; COL_BUF + slot*64 + ACACHE + tcol (tcol 0..19). + ; render_tile writes it; term_write_tilemap and + ; update_cursor_attr read it - so the tilemap attr + ; pass never re-runs the Fano color math (O(1) lookup + ; per tile instead of color_setup per tile per scroll). ; terminal state (WRAMX gap $D580-$D5FF) DEF wGlyphL EQU $D580 ; 2 @@ -112,8 +119,8 @@ term_init:: or e jr nz, .clrc - call term_write_tilemap - call term_redraw ; build all tiles (blank + cursor) + call term_redraw ; build all tiles (also fills the attr cache) + call term_write_tilemap ; ...which the tilemap attr pass reads ld a, %10010001 ; LCD on, BG on, tile data $8000, map $9800 ld [rLCDC], a @@ -149,10 +156,10 @@ term_write_tilemap:: call .slot20 ; DE = pos, HL = tilemap addr, wTMSlot = slot ld b, TCOLS/2 .a_col - ; attribute = palette(from this tile's two cell colors) | bank bit(pos hi). + ; attribute = cached palette bits (render_tile keeps the cache fresh) + ; | bank bit(pos hi). No color math here - just a table read. push hl ; save tilemap write ptr push de ; save pos - ; color addr = COL_BUF + slot*64 + tcol*2 ; tcol = (TCOLS/2) - b ld a, [wTMSlot] ld l, a ld h, 0 @@ -162,31 +169,21 @@ term_write_tilemap:: add hl, hl add hl, hl add hl, hl ; slot*64 + ld de, COL_BUF + ACACHE + add hl, de ld a, TCOLS/2 - sub b - add a ; tcol*2 + sub b ; tcol add l ld l, a ld a, h adc 0 ld h, a - ld de, COL_BUF - add hl, de - ld a, [hl+] - ld d, a ; colL - ld a, [hl] - ld e, a ; colR - call color_setup ; -> wPalAttr (preserves B, C) + ld a, [hl] ; A = cached attr (palette bits) pop de ; restore pos pop hl ; restore tilemap write ptr - ld a, d ; HIGH(pos): 0 or 1 -> VRAM bank bit - or a - jr z, .a0 - ld a, [wPalAttr] + bit 0, d ; HIGH(pos): 0 or 1 -> VRAM bank bit + jr z, .aw or $08 ; VRAM bank 1 tile - jr .aw -.a0 - ld a, [wPalAttr] .aw ld [hl+], a inc de @@ -549,7 +546,22 @@ render_tile: ld e, a ; E = colR ld a, [hl] ld d, a ; D = colL + push hl ; &colL = COL_BUF + slot*64 + tcol*2 call color_setup + ; refresh the attr cache: cache[slot][tcol] = wPalAttr. + ; addr = &colL - tcol + ACACHE (tcol*2 back off, tcol forward) + pop hl + ld a, [wRT_tcol] + ld e, a + ld a, ACACHE + sub e ; ACACHE - tcol (always positive: 21..40) + add l + ld l, a + ld a, h + adc 0 + ld h, a + ld a, [wPalAttr] + ld [hl], a ; cursor mask xor a ld [wCurMask], a @@ -638,7 +650,8 @@ update_cursor_attr: ld h, a ld a, [hl] ld [wTMSlot], a - ; color addr = COL_BUF + slot*64 + (wCurCol & $FE) + ; attr = cache[slot][wCurCol/2] - the cursor tile was just rendered + ; (render_cursor_tile falls through to here), so the cache is fresh. ld l, a ld h, 0 add hl, hl @@ -647,20 +660,17 @@ update_cursor_attr: add hl, hl add hl, hl add hl, hl ; slot*64 + ld de, COL_BUF + ACACHE + add hl, de ld a, [wCurCol] - and $FE ; left cell of the tile + srl a ; tile col add l ld l, a ld a, h adc 0 ld h, a - ld de, COL_BUF - add hl, de - ld a, [hl+] - ld d, a ; colL ld a, [hl] - ld e, a ; colR - call color_setup ; -> wPalAttr (masks recomputed, harmless) + ld [wPalAttr], a ; downstream bank-bit code reads this ; bank bit: pos = slot*20 + (wCurCol/2) ld a, [wTMSlot] ld l, a |
