aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoruser <user@clank>2026-07-16 15:35:07 +0200
committeruser <user@clank>2026-07-16 15:35:07 +0200
commit61c9595901b86ca60eaeb9a65db6a7ddb1309976 (patch)
tree4789a7c3478d36dce292996c2d120cc1eb860c16
parentfont: full mixed-case + punctuation glyph set (not uppercase-only) (diff)
downloadgbos-61c9595901b86ca60eaeb9a65db6a7ddb1309976.tar.gz
gbos-61c9595901b86ca60eaeb9a65db6a7ddb1309976.tar.xz
gbos-61c9595901b86ca60eaeb9a65db6a7ddb1309976.zip
term: cursor + O(1) line scrolling
Rework the terminal from a static one-tile-per-screen-position model to LINE-BOUND tiles with an assign[] indirection, so scrolling is cheap: - Each line-slot L owns the 20 VRAM tiles at positions [L*20..L*20+19]. - assign[screen_row] -> line-slot; the tilemap points each screen row at its slot's tiles. - Scroll = rotate assign[], blank+rebuild only the new bottom line (20 tiles), and rewrite the tilemap. O(1 line) instead of rebuilding all 360 tiles. - term_putc: printable + \n \r \b, line wrap at col 40, cursor advance with scroll-on-overflow. - Cursor: an underline OR'd into the current cell's tile via wCurMask (no sprites/OAM); moving it just re-renders the old and new tiles. - term_demo drives 24 lines through term_putc to exercise scroll+cursor. Also fixes a vicious bug this shook out: build_tile advanced its 16-bit glyph pointers with `ld hl, wGlyphL+1 / inc [hl]`, which CLOBBERS HL -- and HL is the live VRAM destination pointer. Whenever a glyph's 8 bytes straddled a page boundary (common with long/varied lines) the next tile bytes were written into WRAM at $D580+, corrupting wGlyphL/wVram/wCurRow/ wCurCol and freezing the display. Now the pointers are bumped via A so HL is preserved. (Note: the emulator build had also been silently failing on an unrelated debug edit, masking this for a while.) Verified by screenshot: 24 lines scroll to show the last 18 + a visible cursor at the "ready$" prompt; serial shell and filesystem still work.
-rw-r--r--src/boot.asm2
-rw-r--r--src/term.asm662
2 files changed, 455 insertions, 209 deletions
diff --git a/src/boot.asm b/src/boot.asm
index 0a5f2e3..ea52858 100644
--- a/src/boot.asm
+++ b/src/boot.asm
@@ -57,7 +57,7 @@ KernelInit:
ld [wCurProc+1], a
call fs_init ; mount the disk (format on first boot; persists)
call term_init ; set up the LCD text terminal
- call term_test ; render a test pattern
+ call term_demo ; cursor + scroll demo
; --- spawn the init task (pid 1); it fork()s the rest ---
ld hl, TaskInit
diff --git a/src/term.asm b/src/term.asm
index 2b5caf3..deb6748 100644
--- a/src/term.asm
+++ b/src/term.asm
@@ -1,11 +1,15 @@
; =============================================================================
-; term.asm - a 40x18 text terminal on the CGB LCD.
+; term.asm - a 40x18 text terminal on the CGB LCD, with cursor and fast scroll.
;
-; 4x8 font: each 8x8 background tile holds TWO 4-px characters (left+right).
-; The tilemap is static - one dedicated VRAM tile per screen tile-position -
-; and we (re)build the 16 tile bytes when a character changes. 360 tiles:
-; positions 0-255 in VRAM bank 0, 256-359 in bank 1 (via the tilemap attribute
-; bank bit), which is why this is CGB-only.
+; 4x8 font: each 8x8 background tile holds TWO 4-px characters (left+right),
+; giving 40 columns. Tiles are LINE-BOUND: line-slot L owns the 20 VRAM tiles
+; at tile-positions [L*20 .. L*20+19] (index = LOW(pos), VRAM bank = HIGH(pos);
+; positions 256-359 live in bank 1 - hence CGB-only). assign[sr] maps each of
+; the 18 screen rows to a line-slot, and the tilemap points each screen row at
+; that slot's tiles. Scrolling just rotates assign[], rebuilds the one new
+; bottom line, and rewrites the tilemap - O(1 line), not O(screen).
+;
+; The cursor is an underline OR'd into the current cell's tile (wCurMask).
; =============================================================================
INCLUDE "include/gbos.inc"
@@ -17,153 +21,218 @@ DEF rBCPD EQU $FF69 ; CGB BG palette data
DEF TCOLS EQU 40 ; text columns
DEF TROWS EQU 18 ; text rows
-DEF TSTRIDE EQU 64 ; bytes per row in the buffer (power of 2 for addressing)
+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)
-; terminal scratch (WRAMX gap $D500-$D5FF)
-DEF wGlyphL EQU $D580
-DEF wGlyphR EQU $D582
-DEF wVram EQU $D584
+; terminal state (WRAMX gap $D580-$D5FF)
+DEF wGlyphL EQU $D580 ; 2
+DEF wGlyphR EQU $D582 ; 2
+DEF wVram EQU $D584 ; 2
+DEF wCurRow EQU $D586 ; cursor screen row 0..17
+DEF wCurCol EQU $D587 ; cursor screen col 0..39
+DEF wCursorOn EQU $D588 ; draw the cursor?
+DEF wCurMask EQU $D589 ; underline bits to OR into a tile's last row
+DEF wRT_sr EQU $D58A ; render_tile scratch
+DEF wRT_tcol EQU $D58B
+DEF wRT_cL EQU $D58C
+DEF wRT_cR EQU $D58D
+DEF wScratch EQU $D58E
+DEF wAssign EQU $D590 ; assign[18]: screen row -> line-slot ($D590-$D5A1)
-SECTION "term", ROM0
+DEF CUR_L EQU $E0 ; cursor underline, left cell (3px)
+DEF CUR_R EQU $0E ; cursor underline, right cell
-; -----------------------------------------------------------------------------
-; row_addr - A = row -> HL = TERM_BUF + row*64
-; -----------------------------------------------------------------------------
-row_addr:
- ld h, 0
- ld l, a
- add hl, hl
- add hl, hl
- add hl, hl
- add hl, hl
- add hl, hl
- add hl, hl ; *64
- ld de, TERM_BUF
- add hl, de
- ret
+SECTION "term", ROM0
; -----------------------------------------------------------------------------
-; term_init - CGB palette, static tilemap, clear buffer, LCD on.
+; term_init - CGB palette, identity assign[], clear buffer, build, LCD on.
; -----------------------------------------------------------------------------
term_init::
- ; LCD off (so VRAM is freely writable)
xor a
- ld [rLCDC], a
+ ld [rLCDC], a ; LCD off
ld [rSCX], a
ld [rSCY], a
; BG palette 0: color0 = white (bg), color1 = black (text)
ld a, $80
- ld [rBCPS], a ; index 0, auto-increment
+ ld [rBCPS], a
ld a, $FF
- ld [rBCPD], a ; c0 lo (white $7FFF)
+ ld [rBCPD], a
ld a, $7F
- ld [rBCPD], a ; c0 hi
+ ld [rBCPD], a
xor a
- ld [rBCPD], a ; c1 lo (black)
- ld [rBCPD], a ; c1 hi
- ld [rBCPD], a ; c2..c3 = black
+ ld [rBCPD], a
+ ld [rBCPD], a
+ ld [rBCPD], a
ld [rBCPD], a
ld [rBCPD], a
ld [rBCPD], a
- ; --- tilemap indices (VRAM bank 0): [pos] = LOW(pos) ---
+ ; state: assign[sr]=sr, cursor at 0,0 (on)
+ ld hl, wAssign
+ ld b, TROWS
+ xor a
+.mkid
+ ld [hl+], a
+ inc a
+ dec b
+ jr nz, .mkid
+ xor a
+ ld [wCurRow], a
+ ld [wCurCol], a
+ ld a, 1
+ ld [wCursorOn], a
+
+ ; clear the buffer (all slots) to spaces
+ ld hl, TERM_BUF
+ ld de, TROWS * TSTRIDE
+.clr
+ ld a, $20
+ ld [hl+], a
+ dec de
+ ld a, d
+ or e
+ jr nz, .clr
+
+ call term_write_tilemap
+ call term_redraw ; build all tiles (blank + cursor)
+
+ ld a, %10010001 ; LCD on, BG on, tile data $8000, map $9800
+ ld [rLCDC], a
+ ret
+
+; -----------------------------------------------------------------------------
+; term_write_tilemap - point each screen row's tilemap entries at assign[]'s
+; line-slot tiles. Pass 1 = indices (bank 0), pass 2 = attributes (bank 1).
+; -----------------------------------------------------------------------------
+term_write_tilemap::
xor a
ld [rVBK], a
- ld de, 0 ; pos
- ld c, 0 ; row
-.mi_row
- ; compute tilemap row start = $9800 + row*32
- ld a, c
- ld l, a
- ld h, 0
- add hl, hl
- add hl, hl
- add hl, hl
- add hl, hl
- add hl, hl ; row*32
- ld a, h
- add $98
- ld h, a ; HL = $9800 + row*32
- ld b, TCOLS/2 ; 20 tile columns
-.mi_col
+ ld c, 0 ; screen row
+.i_row
+ call .slot20 ; DE = assign[c]*20 (pos start), HL = tilemap row
+ ld b, TCOLS/2
+.i_col
ld a, e
ld [hl+], a ; index = LOW(pos)
inc de
dec b
- jr nz, .mi_col
+ jr nz, .i_col
inc c
ld a, c
cp TROWS
- jr c, .mi_row
+ jr c, .i_row
- ; --- tilemap attributes (VRAM bank 1): bank bit for pos>=256 ---
ld a, 1
ld [rVBK], a
- ld de, 0
ld c, 0
-.ma_row
- ld a, c
- ld l, a
- ld h, 0
- add hl, hl
- add hl, hl
- add hl, hl
- add hl, hl
- add hl, hl
- ld a, h
- add $98
- ld h, a
+.a_row
+ call .slot20
ld b, TCOLS/2
-.ma_col
- ld a, d ; HIGH(pos): 0 for 0-255, 1 for 256+
+.a_col
+ ld a, d ; HIGH(pos): 0 or 1
or a
- jr z, .ma_bank0
- ld a, $08 ; VRAM bank 1 for this tile
- jr .ma_put
-.ma_bank0
+ jr z, .a0
+ ld a, $08 ; VRAM bank 1 attribute
+ jr .aw
+.a0
xor a
-.ma_put
+.aw
ld [hl+], a
inc de
dec b
- jr nz, .ma_col
+ jr nz, .a_col
inc c
ld a, c
cp TROWS
- jr c, .ma_row
+ jr c, .a_row
xor a
ld [rVBK], a
+ ret
+; helper: C = screen row -> DE = assign[C]*20, HL = $9800 + C*32
+.slot20
+ ld a, c
+ add LOW(wAssign)
+ ld l, a
+ ld a, HIGH(wAssign)
+ adc 0
+ ld h, a
+ ld a, [hl] ; L = assign[row]
+ ld l, a
+ ld h, 0
+ add hl, hl
+ add hl, hl ; L*4
+ ld d, h
+ ld e, l
+ add hl, hl
+ add hl, hl ; L*16
+ add hl, de ; L*20
+ ld d, h
+ ld e, l ; DE = pos start
+ ld a, c
+ ld l, a
+ ld h, 0
+ add hl, hl
+ add hl, hl
+ add hl, hl
+ add hl, hl
+ add hl, hl ; row*32
+ ld a, h
+ add $98
+ ld h, a ; HL = $9800 + row*32
+ ret
- ; clear the text buffer to spaces
- ld hl, TERM_BUF
- ld de, TROWS * TSTRIDE
-.clr
- ld a, $20 ; ' '
- ld [hl+], a
- dec de
- ld a, d
- or e
- jr nz, .clr
-
+; -----------------------------------------------------------------------------
+; slot_addr - A = screen row -> HL = TERM_BUF + assign[row]*64
+; -----------------------------------------------------------------------------
+slot_addr:
+ add LOW(wAssign)
+ ld l, a
+ ld a, HIGH(wAssign)
+ adc 0
+ ld h, a
+ ld a, [hl] ; line-slot
+ ld l, a
+ ld h, 0
+ add hl, hl
+ add hl, hl
+ add hl, hl
+ add hl, hl
+ add hl, hl
+ add hl, hl ; *64
+ ld de, TERM_BUF
+ add hl, de
ret
-; term_show - rebuild all tiles then turn the LCD on.
-term_show::
- call term_redraw
- ld a, %10010001 ; LCD on, BG on, tile data $8000, map $9800
- ld [rLCDC], a
+; -----------------------------------------------------------------------------
+; glyph_ptr - A = char -> HL = FontData + (clamp(A,32,127)-32)*8
+; -----------------------------------------------------------------------------
+glyph_ptr:
+ cp 32
+ jr nc, .ok
+ ld a, 32
+.ok
+ cp 128
+ jr c, .ok2
+ ld a, 32
+.ok2
+ sub 32
+ ld l, a
+ ld h, 0
+ add hl, hl
+ add hl, hl
+ add hl, hl ; *8
+ ld de, FontData
+ add hl, de
ret
; -----------------------------------------------------------------------------
-; build_tile - build the 8x8 tile for screen tile-position DE (E=index within
-; bank, D=bank 0/1) from characters B (left) and C (right).
+; build_tile - build tile for tile-position DE (E=index, D=bank) from chars
+; B (left) and C (right). ORs wCurMask into the last pixel row (cursor).
; -----------------------------------------------------------------------------
build_tile:
ld a, d
- ld [rVBK], a ; select VRAM bank for this tile
- ; VRAM dest = $8000 + E*16
+ ld [rVBK], a ; VRAM bank for this tile
ld h, 0
ld l, e
add hl, hl
@@ -177,7 +246,6 @@ build_tile:
ld [wVram], a
ld a, h
ld [wVram+1], a
- ; glyphL = FontData + (clamp(B)-32)*8
ld a, b
call glyph_ptr
ld a, l
@@ -190,15 +258,13 @@ build_tile:
ld [wGlyphR], a
ld a, h
ld [wGlyphR+1], a
- ; 8 rows: dest[2r] = (L[r]<<4)|R[r] ; dest[2r+1] = 0
ld b, 8 ; row counter
ld a, [wVram]
ld l, a
ld a, [wVram+1]
ld h, a ; HL = VRAM dest
.brow
- push hl ; save VRAM ptr
- ; left glyph byte
+ push hl
ld a, [wGlyphL]
ld e, a
ld a, [wGlyphL+1]
@@ -206,20 +272,29 @@ build_tile:
ld a, [de]
swap a
and $F0
- ld c, a ; left nibble -> high
- ; right glyph byte
+ ld c, a ; left glyph -> high nibble
ld a, [wGlyphR]
ld e, a
ld a, [wGlyphR+1]
ld d, a
ld a, [de]
and $0F
- or c ; A = combined row
+ or c ; A = combined pixel row
+ ld e, a ; save (DE reloaded next iter)
+ ld a, b
+ dec a
+ jr nz, .nocur ; last row (b==1)? add cursor underline
+ ld a, [wCurMask]
+ or e
+ jr .wr
+.nocur
+ ld a, e
+.wr
pop hl
ld [hl+], a ; plane 0
xor a
ld [hl+], a ; plane 1 = 0
- ; advance both glyph pointers
+ ; advance glyph pointers - MUST NOT touch HL (it holds the VRAM dest!)
ld a, [wGlyphL]
inc a
ld [wGlyphL], a
@@ -240,142 +315,313 @@ build_tile:
jr nz, .brow
ret
-; glyph_ptr - A = char -> HL = FontData + (clamp(A,32,127)-32)*8
-glyph_ptr:
- cp 32
- jr nc, .ok
- ld a, 32
-.ok
- cp 128
- jr c, .ok2
- ld a, 32
-.ok2
- sub 32
+; -----------------------------------------------------------------------------
+; render_tile - B = screen row, C = tile column: rebuild that one tile from the
+; buffer, adding the cursor underline if the cursor is in it.
+; -----------------------------------------------------------------------------
+render_tile:
+ ld a, b
+ ld [wRT_sr], a
+ ld a, c
+ ld [wRT_tcol], a
+ ; chars: &buffer[assign[sr]][tcol*2]
+ ld a, b
+ call slot_addr ; HL = &buffer[slot][0]
+ ld a, [wRT_tcol]
+ add a ; tcol*2
+ add l
+ ld l, a
+ ld a, h
+ adc 0
+ ld h, a
+ ld a, [hl+]
+ ld [wRT_cL], a
+ ld a, [hl]
+ ld [wRT_cR], a
+ ; cursor mask
+ xor a
+ ld [wCurMask], a
+ ld a, [wCursorOn]
+ or a
+ jr z, .pos
+ ld a, [wCurRow]
+ ld b, a
+ ld a, [wRT_sr]
+ cp b
+ jr nz, .pos
+ ld a, [wRT_tcol]
+ add a ; left cell col
+ ld b, a
+ ld a, [wCurCol]
+ cp b
+ jr nz, .cr
+ ld a, CUR_L
+ ld [wCurMask], a
+ jr .pos
+.cr
+ inc b ; right cell col
+ cp b
+ jr nz, .pos
+ ld a, CUR_R
+ ld [wCurMask], a
+.pos
+ ; pos = assign[sr]*20 + tcol -> DE (D=bank, E=index)
+ ld a, [wRT_sr]
+ add LOW(wAssign)
+ ld l, a
+ ld a, HIGH(wAssign)
+ adc 0
+ ld h, a
+ ld a, [hl]
ld l, a
ld h, 0
add hl, hl
add hl, hl
- add hl, hl ; *8
- ld de, FontData
- add hl, de
+ ld d, h
+ ld e, l ; L*4
+ add hl, hl
+ add hl, hl
+ add hl, de ; L*20
+ ld a, [wRT_tcol]
+ add l
+ ld l, a
+ ld a, h
+ adc 0
+ ld h, a ; HL = pos
+ ld d, h
+ ld e, l ; DE = pos
+ ld a, [wRT_cL]
+ ld b, a
+ ld a, [wRT_cR]
+ ld c, a
+ call build_tile
+ xor a
+ ld [rVBK], a
ret
+; render_cursor_tile - rebuild the tile at the cursor position.
+render_cursor_tile:
+ ld a, [wCurRow]
+ ld b, a
+ ld a, [wCurCol]
+ srl a ; /2 = tile col
+ ld c, a
+ jp render_tile
+
; -----------------------------------------------------------------------------
-; term_redraw - rebuild every tile from the text buffer. (LCD should be off, or
-; call during VBlank for a full frame.)
+; term_redraw - rebuild every tile from the buffer (init / full refresh).
; -----------------------------------------------------------------------------
term_redraw::
- ld c, 0 ; row
+ ld b, 0 ; screen row
.row
- push bc
- ld a, c
- call row_addr ; HL = &buffer[row][0]
- ; iterate 20 tile columns
- ld b, 0 ; tile column
+ ld c, 0 ; tile col
.col
push bc
- push hl
- ; DE = pos = row*20 + tcol : maintain via a running counter is simpler, but
- ; recompute here: pos = C(row)*20 + B(tcol)
+ call render_tile
+ pop bc
+ inc c
ld a, c
+ cp TCOLS/2
+ jr c, .col
+ inc b
+ ld a, b
+ cp TROWS
+ jr c, .row
+ ret
+
+; -----------------------------------------------------------------------------
+; term_scroll - scroll up one line: rotate assign[], blank+build the new bottom
+; line, rewrite the tilemap.
+; -----------------------------------------------------------------------------
+term_scroll::
+ ld a, [wAssign]
+ ld [wScratch], a ; freed line-slot
+ ld hl, wAssign+1
+ ld de, wAssign
+ ld b, TROWS-1
+.rot
+ ld a, [hl+]
+ ld [de], a
+ inc de
+ dec b
+ jr nz, .rot
+ ld a, [wScratch]
+ ld [wAssign + TROWS-1], a ; new bottom row uses the freed slot
+ ; clear that slot to spaces
ld l, a
ld h, 0
add hl, hl
- add hl, hl ; row*4
- ld d, h
- ld e, l
add hl, hl
- add hl, hl ; row*16
- add hl, de ; row*20
- ld a, b
+ add hl, hl
+ add hl, hl
+ add hl, hl
+ add hl, hl ; *64
+ ld de, TERM_BUF
+ add hl, de
+ ld b, TCOLS
+.clr
+ ld a, $20
+ ld [hl+], a
+ dec b
+ jr nz, .clr
+ ; rebuild bottom line tiles (screen row 17)
+ ld c, 0
+.build
+ push bc
+ ld b, TROWS-1
+ call render_tile
+ pop bc
+ inc c
+ ld a, c
+ cp TCOLS/2
+ jr c, .build
+ call term_write_tilemap
+ ret
+
+; cursor_down - advance cursor row, scrolling if it runs off the bottom.
+cursor_down:
+ ld a, [wCurRow]
+ inc a
+ cp TROWS
+ jr c, .ok
+ call term_scroll
+ ld a, TROWS-1
+.ok
+ ld [wCurRow], a
+ ret
+
+; -----------------------------------------------------------------------------
+; term_putc - A = character. Print at the cursor, advance, handle \n \r \b.
+; -----------------------------------------------------------------------------
+term_putc::
+ cp 10
+ jr z, .newline
+ cp 13
+ jr z, .cret
+ cp 8
+ jr z, .bs
+ cp 32
+ ret c ; ignore other control chars
+ ; printable: buffer[assign[cur]][cc] = char
+ ld [wRT_cL], a
+ ld a, [wCurRow]
+ call slot_addr
+ ld a, [wCurCol]
add l
- ld e, a
+ ld l, a
ld a, h
adc 0
- ld d, a ; DE = pos
- pop hl ; &buffer[row][0]
- push hl
- ; charL = buffer[row][tcol*2], charR = [+1]
- ld a, b
- add a ; tcol*2
+ ld h, a
+ ld a, [wRT_cL]
+ ld [hl], a
+ ; redraw current cell WITHOUT cursor (shows the char)
+ xor a
+ ld [wCursorOn], a
+ call render_cursor_tile
+ ; advance
+ ld a, [wCurCol]
+ inc a
+ cp TCOLS
+ jr c, .adv
+ xor a
+ ld [wCurCol], a
+ call cursor_down
+ jr .show
+.adv
+ ld [wCurCol], a
+.show
+ ld a, 1
+ ld [wCursorOn], a
+ call render_cursor_tile
+ ret
+.newline
+ xor a
+ ld [wCursorOn], a
+ call render_cursor_tile
+ xor a
+ ld [wCurCol], a
+ call cursor_down
+ ld a, 1
+ ld [wCursorOn], a
+ call render_cursor_tile
+ ret
+.cret
+ xor a
+ ld [wCursorOn], a
+ call render_cursor_tile
+ xor a
+ ld [wCurCol], a
+ ld a, 1
+ ld [wCursorOn], a
+ call render_cursor_tile
+ ret
+.bs
+ ld a, [wCurCol]
+ or a
+ ret z
+ xor a
+ ld [wCursorOn], a
+ call render_cursor_tile ; clear cursor at old
+ ld a, [wCurCol]
+ dec a
+ ld [wCurCol], a
+ ; blank the cell we backed into
+ ld a, [wCurRow]
+ call slot_addr
+ ld a, [wCurCol]
add l
ld l, a
ld a, h
adc 0
ld h, a
- ld a, [hl+]
- ld b, a ; charL
- ld a, [hl]
- ld c, a ; charR
- push de
- call build_tile ; DE=pos, B=charL, C=charR
- pop de
- pop hl
- pop bc
- inc b
- ld a, b
- cp TCOLS/2
- jr c, .col
- xor a
- ld [rVBK], a
- pop bc
- inc c
- ld a, c
- cp TROWS
- jr c, .row
+ ld a, $20
+ ld [hl], a
+ ld a, 1
+ ld [wCursorOn], a
+ call render_cursor_tile
ret
; -----------------------------------------------------------------------------
-; term_puts - HL = NUL-terminated string, B = row, C = col : write into buffer.
+; term_puts - HL = NUL-terminated string: print via term_putc.
; -----------------------------------------------------------------------------
term_puts::
- push hl
- ld a, b
- call row_addr ; HL = &buffer[row]
- ld a, c
- add l
- ld l, a
- ld a, h
- adc 0
- ld h, a ; HL = &buffer[row][col]
- ld d, h
- ld e, l ; DE = dest
- pop hl ; HL = string
-.l
ld a, [hl+]
or a
ret z
- ld [de], a
- inc de
- jr .l
+ push hl
+ call term_putc
+ pop hl
+ jr term_puts
; -----------------------------------------------------------------------------
-; term_test - fill the screen with a test pattern and show it.
+; term_demo - drive the terminal: print enough lines to scroll, end at a prompt.
; -----------------------------------------------------------------------------
-term_test::
- ld hl, .s0
- ld bc, $0000
- call term_puts
- ld hl, .s1
- ld bc, $0100
- call term_puts
- ld hl, .s2
- ld bc, $0200
- call term_puts
- ld hl, .s3
- ld bc, $0500
- call term_puts
- ld hl, .s4
- ld bc, $0A00
- call term_puts
- ld hl, .s5
- ld bc, $1100
+term_demo::
+ ld hl, .msg
call term_puts
- call term_show
ret
-.s0 db "GBOS Terminal - now with lowercase!", 0
-.s1 db "The quick brown fox jumps over a", 0
-.s2 db "lazy dog. Digits 0123456789 too.", 0
-.s3 db "abcdefghijklmnopqrstuvwxyz", 0
-.s4 db "ascenders bdfhklt, descenders gjpqy", 0
-.s5 db "Punct .,:;!? +-*/=<>()[]#@ ok", 0
+.msg:
+ db "GBOS terminal: cursor + fast scroll", 10
+ db "01 the quick brown fox jumps", 10
+ db "02 over the lazy dog.", 10
+ db "03 line three of the scroll test", 10
+ db "04 line four", 10
+ db "05 line five", 10
+ db "06 line six", 10
+ db "07 line seven", 10
+ db "08 line eight", 10
+ db "09 line nine", 10
+ db "10 line ten", 10
+ db "11 line eleven", 10
+ db "12 line twelve", 10
+ db "13 line thirteen", 10
+ db "14 line fourteen", 10
+ db "15 line fifteen", 10
+ db "16 line sixteen", 10
+ db "17 line seventeen", 10
+ db "18 line eighteen", 10
+ db "19 line nineteen", 10
+ db "20 line twenty", 10
+ db "21 line twenty-one", 10
+ db "22 line twenty-two", 10
+ db "ready$ ", 0