@@ 0,0 1,311 @@
+W = 80 ; Maximum width of the text display in characters.
+H = 60 ; Maximum height of the text display in characters.
+FONTHEIGHT = 8 ; Display font height, in pixels.
+FONTWIDTH = 256 ; Display font width, in bytes.
+
+FW = FONTWIDTH
+FH = FONTHEIGHT
+
+FBSIZE = W * H * FONTHEIGHT ; Size, in bytes, of the frame buffer bitmap.
+FRAMEBUF = $FE0000 ; Base address of the frame buffer.
+
+
+;;;; console_init
+;;
+;; SYNOPSIS
+;; JSR console_init
+;;
+;; DESCRIPTION
+;; Private function.
+;;
+;; Initializes the console output state to reset conditions.
+;; Note that this does NOT clear the framebuffer; however,
+;; the cursor is located in the upper-lefthand corner of the
+;; screen.
+;;
+;; The cursor is assumed to be in the erased state, and turned
+;; off.
+;;
+;; This function is assumed to be called by the BIOS start-up
+;; code, not by application software. Thus, it is invoked with
+;; JSR, not JSL.
+;;
+
+console_init:
+ .al
+ .xl
+.(
+ php
+
+ lda #$00
+ sta cursorOffset ; zero cursor offset, implying X=Y=0
+ sta frameBuffer ; set low word of pointer
+ _AS
+ sta cursorX
+ sta cursorY
+ sta cursorDrawn
+ _AL
+ lda #$FE
+ sta frameBuffer+2 ; set high byte of pointer
+ lda #$01
+ sta offCounter ; Cursor is assumed off
+
+ plp
+ rts
+.)
+
+
+;;;; console_mv_cursor_right
+;;
+;; SYNOPSIS
+;; JSR console_mv_cursor_right
+;;
+;; DESCRIPTION
+;; Private function.
+;;
+;; Moves the cursor to the right one character position.
+;;
+;; PRECONDITION
+;; 0 <= cursorX < W-1
+;; 0 <= cursorOffset < FBSIZE-1
+;;
+;; POSTCONDITION
+;; 0 < cursorX < W
+;; 0 < cursorOffset < FBSIZE
+;;
+
+console_mv_cursor_right:
+ .al
+ .xl
+.(
+ php
+
+ ; 0 <= cursorX < W-1 implies 0 <= cursorX < W
+ ; 0 < cursorX+1 <= W-1
+
+ _AS
+ inc cursorX
+ _AL
+ inc cursorOffset
+
+ ; 0 < cursorX <= W-1, still implying 0 < cursorX < W
+
+ plp
+ rts
+.)
+
+;;;; console_mv_cursor_down
+;;
+;; SYNOPSIS
+;; JSR console_mv_cursor_down
+;;
+;; DESCRIPTION
+;; Private function.
+;;
+;; Moves the cursor down one character position.
+;;
+;; PRECONDITION
+;; 0 <= cursorY < H-1
+;; 0 <= cursorOffset < FBSIZE
+;;
+;; POSTCONDITION
+;; 0 < cursorY < H
+;; 0 < cursorOffset < FBSIZE-W
+;;
+
+console_mv_cursor_down:
+ .al
+ .xl
+.(
+ php
+ pha
+
+ ; 0 <= cursorY < H-1 => 0 <= cursorY < H
+ ; 0 < cursorY+1 < H-1 => 0 <= cursorY+1 < H
+ _AS
+ inc cursorY
+ _AL
+ clc
+ lda #W
+ adc cursorOffset
+ sta cursorOffset
+
+ ; 0 < cursorY < H-1 => 0 <= cursorY < H
+
+ pla
+ plp
+ rts
+.)
+
+
+;;;; console_mv_cursor_up
+;;
+;; SYNOPSIS
+;; JSR console_mv_cursor_up
+;;
+;; DESCRIPTION
+;; Private function.
+;;
+;; Moves the cursor up one character position.
+;;
+;; PRECONDITION
+;; 0 < cursorY <= H-1
+;; 0 < cursorOffset <= FBSIZE-1
+;;
+;; POSTCONDITION
+;; 0 <= cursorY < H-1
+;; 0 <= cursorOffset < FBSIZE-W
+;;
+
+console_mv_cursor_up:
+ .al
+ .xl
+.(
+ php
+ pha
+
+ ; 0 < cursorY <= H-1
+ ; 0 <= cursorY-1 < H-1
+
+ _AS
+ dec cursorY
+ _AL
+ lda cursorOffset
+ sec
+ sbc #W
+ sta cursorOffset
+
+ ; 0 <= cursorY < H-1
+
+ pla
+ plp
+ rts
+.)
+
+;;;; console_constrain_pt
+;;
+;; SYNOPSIS
+;; PEA y
+;; PEA x
+;; JSR console_constrain_pt
+;; PLA
+;; STA constrained_x
+;; PLA
+;; STA constrained_y
+;;
+;; DESCRIPTION
+;; Constrain a coordinate to the visible portion of the screen.
+;;
+;; For example, negative ordinates are set to zero. Ordinates that
+;; exceed the width or height of the screen will be limited to the
+;; width or height minus one.
+;;
+console_constrain_pt:
+ .al
+ .xl
+.(
+s_y = 7
+s_x = 5
+s_pc = 3
+s_A = 1
+
+ pha
+
+ ; constrain X first
+
+ lda s_x,s
+ bpl x_is_positive
+ lda #0
+ sta s_x,s
+
+x_is_positive:
+ cmp #W
+ blt x_is_in_range
+ lda #W-1
+ sta s_x,s
+
+ ; constrain Y next
+
+x_is_in_range:
+
+ lda s_y,s
+ bpl y_is_positive
+ lda #0
+ sta s_y,s
+
+y_is_positive:
+ cmp #H
+ blt y_is_in_range
+ lda #H-1
+ sta s_y,s
+
+ pla
+ rts
+.)
+
+;;;; console_set_cursor_xy
+;;
+;; SYNOPSIS
+;; PEA y
+;; PEA x
+;; JSR console_set_cursor_xy
+;; PLA
+;; PLA
+console_set_cursor_xy:
+ .al
+ .xl
+.(
+s_y = 5
+s_x = 3
+s_pc = 1
+
+ ; Constrain new cursor position.
+
+ lda s_y,s
+ pha
+ lda s_x,s
+ pha
+ jsr console_constrain_pt
+ pla
+ sta s_x,s
+ pla
+ sta s_y,s
+
+ ; Let delta be the (signed) difference from the new column to the current column.
+ ; Add delta to cursorX and to cursorOffset.
+
+ lda s_x,s
+ sec
+ sbc cursorX ; cursorOffset+(newX-cursorX) = newOffset
+ clc
+ adc cursorOffset
+ sta cursorOffset ; cursorOffset = newOffset
+
+ lda s_x,s
+ sta cursorX ; cursorX = newX
+
+ ; While new row lies below the current row, do
+ ; Move cursor down by 1.
+ ; end
+
+down_again:
+ lda cursorY
+ cmp s_y,s
+ bge try_up
+ jsr console_mv_cursor_down
+ jmp down_again
+
+ ; While new row lies above the current row, do
+ ; Move cursor up by 1.
+ ; end
+
+try_up: lda cursorY
+ cmp s_y,s
+ blt done
+ beq done
+ jsr console_mv_cursor_up
+ jmp try_up
+
+done: rts
+.)
+
@@ 38,7 38,14 @@ Thread1Context = $0300
Thread2Context = Thread1Context+th_sizeof
alterbuf = Thread2Context+th_sizeof
conbuf = alterbuf+conbuf_sizeof
-BIOS = conbuf+conbuf_sizeof ; JML xx yy zz (total 4 bytes)
+BIOS = conbuf+conbuf_sizeof ; JML xx yy zz (total 4 bytes)
+; BIOS state
+frameBuffer = BIOS+4 ; pointer
+cursorOffset = frameBuffer+4 ; u16
+offCounter = cursorOffset+2 ; u16
+cursorX = offCounter+2 ; u8
+cursorY = cursorX+1
+cursorDrawn = cursorY+1 ; bool
; IM/F Re-entry Causes