WeeGUI/painting.s

607 lines
11 KiB
ArmAsm

;
; painting.s
; Rendering routines for 80 column text elements
;
; Created by Quinn Dunki on 8/15/14.
; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGClearScreen
; Clears the text screen (assumes 80 cols)
; Side effects: Clobbers BASL,BASH
;
WGClearScreen:
SAVE_AXY
SETSWITCH PAGE2OFF
ldx #23
WGClearScreen_lineLoop:
lda TEXTLINES_L,x ; Compute video memory address of line
sta BASL
lda TEXTLINES_H,x
sta BASH
ldy #39
lda #' ' + $80
WGClearScreen_charLoop:
sta (BASL),y
SETSWITCH PAGE2ON
sta (BASL),y
SETSWITCH PAGE2OFF
dey
bpl WGClearScreen_charLoop
dex
bpl WGClearScreen_lineLoop
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGFillRect
; Fills a rectangle (assumes 80 cols)
; PARAM0: Left edge
; PARAM1: Top edge
; PARAM2: Width
; PARAM3: Height
; X: Character to fill
; Side effects: Clobbers BASL,BASH
;
WGFillRect:
SAVE_AXY
SAVE_ZPS
stx SCRATCH0
clc ; Compute bottom edge
lda PARAM1
adc PARAM3
tax
WGFillRect_vertLoop:
phx ; We'll need X back for now, but save the line number
lda TEXTLINES_L,x ; Compute video memory address of left edge of rect
sta BASL
lda TEXTLINES_H,x
sta BASH
lda PARAM0
lsr
clc
adc BASL
sta BASL
lda #$0
adc BASH
sta BASH
lda PARAM0 ; Left edge even?
and #$01
bne WGFillRect_horzLoopOdd
; CASE 1: Left edge even-aligned, even width
SETSWITCH PAGE2OFF
lda PARAM2
lsr
tay ; Iterate w/2
dey
phy ; We'll reuse this calculation for the odd columns
WGFillRect_horzLoopEvenAligned0: ; Draw even columns
lda SCRATCH0 ; Plot the character
sta (BASL),y
dey
bpl WGFillRect_horzLoopEvenAligned0 ; Loop for w/2
SETSWITCH PAGE2ON ; Prepare for odd columns
ply ; Iterate w/2 again
WGFillRect_horzLoopEvenAligned1: ; Draw odd columns
lda SCRATCH0 ; Plot the character
sta (BASL),y
dey
bpl WGFillRect_horzLoopEvenAligned1 ; Loop for w/2
lda PARAM2 ; Is width even?
and #$01
beq WGFillRect_horzLoopEvenAlignedEvenWidth
; CASE 1a: Left edge even aligned, odd width
lda PARAM2 ; Fill in extra last column
lsr
tay
lda SCRATCH0 ; Plot the character
sta (BASL),y
WGFillRect_horzLoopEvenAlignedEvenWidth:
plx ; Prepare for next row
dex
cpx PARAM1
bcs WGFillRect_vertLoop
jmp WGFillRect_done
WGFillRect_horzLoopOdd:
; CASE 2: Left edge odd-aligned, even width
SETSWITCH PAGE2ON
lda PARAM2
lsr
tay ; Iterate w/2
phy ; We'll reuse this calculation for the even columns
WGFillRect_horzLoopOddAligned0: ; Draw even columns
lda SCRATCH0 ; Plot the character
sta (BASL),y
dey
bne WGFillRect_horzLoopOddAligned0 ; Loop for w/2
SETSWITCH PAGE2OFF ; Prepare for odd columns
ply ; Iterate w/2 again, shift left 1
dey
WGFillRect_horzLoopOddAligned1: ; Draw even columns
lda SCRATCH0 ; Plot the character
sta (BASL),y
dey
bpl WGFillRect_horzLoopOddAligned1 ; Loop for w/2
lda PARAM2 ; Is width even?
and #$01
beq WGFillRect_horzLoopOddAlignedEvenWidth
; CASE 2a: Left edge odd aligned, odd width
lda PARAM2 ; Fill in extra last column
lsr
tay
lda SCRATCH0 ; Plot the character
sta (BASL),y
WGFillRect_horzLoopOddAlignedEvenWidth:
plx ; Prepare for next row
dex
cpx PARAM1
bcs WGFillRect_vertLoopJmp
jmp WGFillRect_done
WGFillRect_vertLoopJmp:
jmp WGFillRect_vertLoop
WGFillRect_done:
RESTORE_ZPS
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGStrokeRect
; Strokes a rectangle (assumes 80 cols)
; PARAM0: Left edge
; PARAM1: Top edge
; PARAM2: Width
; PARAM3: Height
; Side effects: Clobbers BASL,BASH
;
CH_TOP = '_'+$80
CH_BOTTOM = 'L';'_'+$80
CH_LEFT = 'Z';'_'+$80
CH_RIGHT = '_'
CH_BOTTOMLEFT = 'L'
CH_BOTTOMRIGHT = '_'+$80
WGStrokeRect:
SAVE_AXY
SAVE_ZPS
; Top and bottom edges
;
ldx PARAM1 ; Start with top edge
dex
lda #CH_TOP
sta SCRATCH0
WGStrokeRect_horzEdge:
lda TEXTLINES_L,x ; Compute video memory address of left edge of rect
sta BASL
lda TEXTLINES_H,x
sta BASH
lda PARAM0
lsr
clc
adc BASL
sta BASL
lda #$0
adc BASH
sta BASH
lda PARAM0 ; Left edge even?
and #$01
bne WGStrokeRect_horzLoopOdd
; CASE 1: Left edge even-aligned, even width
SETSWITCH PAGE2OFF
lda PARAM2
lsr
tay ; Start at right edge
dey
phy ; We'll reuse this calculation for the odd columns
WGStrokeRect_horzLoopEvenAligned0: ; Draw even columns
lda SCRATCH0 ; Plot the character
sta (BASL),y
dey
bpl WGStrokeRect_horzLoopEvenAligned0 ; Loop for w/2
SETSWITCH PAGE2ON ; Prepare for odd columns
ply ; Start at right edge again
WGStrokeRect_horzLoopEvenAligned1: ; Draw odd columns
lda SCRATCH0 ; Plot the character
sta (BASL),y
dey
bpl WGStrokeRect_horzLoopEvenAligned1 ; Loop for w/2
lda PARAM2 ; Is width even?
and #$01
beq WGStrokeRect_horzLoopEvenAlignedEvenWidth
; CASE 1a: Left edge even aligned, odd width
;SETSWITCH PAGE2OFF
lda PARAM2 ; Fill in extra last column
lsr
tay
lda SCRATCH0 ; Plot the character
sta (BASL),y
WGStrokeRect_horzLoopEvenAlignedEvenWidth:
inx
cpx PARAM1
bne WGStrokeRect_vertEdge
clc ; Prepare for bottom edge
lda PARAM1
adc PARAM3
tax
lda #CH_BOTTOM
sta SCRATCH0
jmp WGStrokeRect_horzEdge
WGStrokeRect_horzLoopOdd:
; CASE 2: Left edge odd-aligned, even width
SETSWITCH PAGE2ON
lda PARAM2
lsr
tay ; Iterate w/2
phy ; We'll reuse this calculation for the even columns
WGStrokeRect_horzLoopOddAligned0: ; Draw even columns
lda SCRATCH0 ; Plot the character
sta (BASL),y
dey
bne WGStrokeRect_horzLoopOddAligned0 ; Loop for w/2
SETSWITCH PAGE2OFF ; Prepare for odd columns
ply ; Iterate w/2 again, shift left 1
dey
WGStrokeRect_horzLoopOddAligned1: ; Draw even columns
lda SCRATCH0 ; Plot the character
sta (BASL),y
dey
bpl WGStrokeRect_horzLoopOddAligned1 ; Loop for w/2
lda PARAM2 ; Is width even?
and #$01
beq WGStrokeRect_horzLoopOddAlignedEvenWidth
; CASE 2a: Left edge odd aligned, odd width
lda PARAM2 ; Fill in extra last column
dec
lsr
tay
lda SCRATCH0 ; Plot the character
sta (BASL),y
WGStrokeRect_horzLoopOddAlignedEvenWidth:
inx
cpx PARAM1
bne WGStrokeRect_vertEdge
clc ; Prepare for bottom edge
lda PARAM1
adc PARAM3
tax
lda #CH_BOTTOM
sta SCRATCH0
jmp WGStrokeRect_horzEdge
WGStrokeRect_vertEdge:
; Left and right edges
;
clc
lda PARAM1 ; Compute bottom edge
adc PARAM3
sta SCRATCH0
ldx PARAM1 ; Start with top edge
WGStrokeRect_vertLoop:
phx ; We'll need X back for now, but save the line number
lda TEXTLINES_L,x ; Compute video memory address of left edge of rect
sta BASL
lda TEXTLINES_H,x
sta BASH
lda PARAM0
dec
lsr
clc
adc BASL
sta BASL
lda #$0
adc BASH
sta BASH
lda PARAM0 ; Left edge even?
dec
and #$01
bne WGStrokeRect_vertLoopOdd
; CASE 1: Left edge even-aligned, even width
SETSWITCH PAGE2ON
ldy #$0
lda #CH_LEFT ; Plot the left edge
sta (BASL),y
lda PARAM2 ; Is width even?
inc
inc
and #$01
bne WGStrokeRect_vertLoopEvenAlignedOddWidth
lda PARAM2 ; Calculate right edge
inc
inc
lsr
dec
tay
SETSWITCH PAGE2OFF
lda #CH_RIGHT ; Plot the right edge
sta (BASL),y
jmp WGStrokeRect_vertLoopEvenAlignedNextRow
WGStrokeRect_vertLoopEvenAlignedOddWidth:
; CASE 1a: Left edge even-aligned, odd width
SETSWITCH PAGE2ON
lda PARAM2 ; Calculate right edge
inc
inc
lsr
tay
lda #CH_RIGHT ; Plot the right edge
sta (BASL),y
WGStrokeRect_vertLoopEvenAlignedNextRow:
plx ; Prepare for next row
inx
cpx SCRATCH0
bne WGStrokeRect_vertLoop
jmp WGStrokeRect_done
WGStrokeRect_vertLoopOdd:
; CASE 2: Left edge odd-aligned, even width
SETSWITCH PAGE2OFF
ldy #$0
lda #CH_LEFT ; Plot the left edge
sta (BASL),y
lda PARAM2 ; Is width even?
inc
inc
and #$01
bne WGStrokeRect_vertLoopOddAlignedOddWidth
lda PARAM2 ; Calculate right edge
inc
inc
lsr
tay
SETSWITCH PAGE2ON
lda #CH_RIGHT ; Plot the right edge
sta (BASL),y
jmp WGStrokeRect_vertLoopOddAlignedNextRow
WGStrokeRect_vertLoopOddAlignedOddWidth:
; CASE 2a: Left edge odd-aligned, odd width
SETSWITCH PAGE2OFF
lda PARAM2 ; Calculate right edge
inc
inc
lsr
tay
lda #CH_RIGHT ; Plot the right edge
sta (BASL),y
WGStrokeRect_vertLoopOddAlignedNextRow:
plx ; Prepare for next row
inx
cpx SCRATCH0
bne WGStrokeRect_vertLoopJmp
jmp WGStrokeRect_done
WGStrokeRect_vertLoopJmp:
jmp WGStrokeRect_vertLoop
WGStrokeRect_done:
RESTORE_ZPS
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGPlot
; Plots a character at current cursor position (assumes 80 cols)
; A: Character to plot
; Side effects: Clobbers SCRATCH0,BASL,BASH
;
WGPlot:
sta SCRATCH0
SAVE_AXY
SAVE_ZPS
ldx WG_CURSORY
lda TEXTLINES_L,x ; Compute video memory address of point
sta BASL
lda TEXTLINES_H,x
sta BASH
lda WG_CURSORX
lsr
clc
adc BASL
sta BASL
lda #$0
adc BASH
sta BASH
lda WG_CURSORX ; X even?
and #$01
bne WGPlot_xOdd
SETSWITCH PAGE2ON ; Plot the character
ldy #$0
lda SCRATCH0
sta (BASL),y
jmp WGPlot_done
WGPlot_xOdd:
SETSWITCH PAGE2OFF ; Plot the character
ldy #$0
lda SCRATCH0
sta (BASL),y
WGPlot_done:
RESTORE_ZPS
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGPrintASCII
; Prints a null-terminated ASCII string at the current view's
; cursor position. Clips to current view
; PARAM0: String pointer, LSB
; PARAM1: String pointer, MSB
; Side effects: Clobbers BASL,BASH
;
WGPrintASCII:
SAVE_AXY
SAVE_ZPS
jsr WGSyncGlobalCursor
LDY_ACTIVEVIEW
iny ; Clip to upper extent
lda WG_CURSORY
cmp WG_VIEWRECORDS,y
bcc WGPrintASCII_done
lda WG_VIEWRECORDS,y ; Clip to lower extent
iny
iny
clc
adc WG_VIEWRECORDS,y
dec
cmp WG_CURSORY
bcc WGPrintASCII_done
jsr WGStrLen ; We'll need the length of the string to clip horizontally
sta SCRATCH0
dey ; Clip left/right extents
dey
dey
lda WG_CURSORX ; startIndex = -(globalX - windowStartX)
sec
sbc WG_VIEWRECORDS,y
eor #$ff
inc
bmi WGPrintASCII_leftEdgeStart
cmp SCRATCH0
bcs WGPrintASCII_done ; Entire string is left of window
tax ; Starting mid-string on the left
lda WG_VIEWRECORDS,y
sta WG_CURSORX
txa
bra WGPrintASCII_findRightEdge
WGPrintASCII_leftEdgeStart:
lda #0
WGPrintASCII_findRightEdge:
pha ; Stash start index
lda WG_VIEWRECORDS,y
iny
iny
clc
adc WG_VIEWRECORDS,y
tax
dex
ply ; End cursor in X, start index in Y
WGPrintASCII_loop:
cpx WG_CURSORX
bcc WGPrintASCII_done ; Hit the right edge of the window
lda (PARAM0),y
beq WGPrintASCII_done ; Hit the end of the string
ora #$80
jsr WGPlot
iny
clc
lda #1
adc WG_CURSORX
sta WG_CURSORX
lda #0
adc WG_CURSORY
sta WG_CURSORY
jmp WGPrintASCII_loop
WGPrintASCII_done:
RESTORE_ZPS
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGPrint
; Prints a null-terminated Apple string at the current view's
; cursor position. Clips to current view.
; PARAM0: String pointer, LSB
; PARAM1: String pointer, MSB
; Side effects: Clobbers BASL,BASH
;
WGPrint:
SAVE_AXY
SAVE_ZPS
WGPrint_done:
RESTORE_ZPS
RESTORE_AXY
rts