WeeGUI/weegui.lst
Quinn Dunki 421835ce66 Polish & Docs
- Removed &NRML and &IVER (not needed)
- WeeGUI's memory pages are now reserved in ProDOS's page allocation scheme, to protect us from file operations and such
- Renamed various files to be more friendly
- Cleaned up the disk image
- First draft of documentation
2015-01-02 16:01:38 -08:00

4905 lines
206 KiB
Plaintext

ca65 V2.13.3 - (C) Copyright 1998-2012 Ullrich von Bassewitz
Main file : weegui.s
Current file: weegui.s
000000r 1 ;
000000r 1 ; gui.s
000000r 1 ; Top level management routines
000000r 1 ;
000000r 1 ; Created by Quinn Dunki on 8/15/14.
000000r 1 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved.
000000r 1 ;
000000r 1
000000r 1
000000r 1 .org $7e00
007E00 1
007E00 1 ; Common definitions
007E00 1
007E00 1 .include "zeropage.s"
007E00 2 ;
007E00 2 ; zeropage.s
007E00 2 ; Zero page information
007E00 2 ;
007E00 2 ; Created by Quinn Dunki on 8/15/14.
007E00 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved.
007E00 2 ;
007E00 2
007E00 2
007E00 2 ; Reserved locations
007E00 2
007E00 2 INVERSE = $32 ; Text output state
007E00 2 CH = $24 ; Cursor X pos
007E00 2 CV = $25 ; Cursor Y pos
007E00 2 BASL = $28 ; Current video memory line
007E00 2 BASH = $29 ; Current video memory line
007E00 2
007E00 2 ; Zero page locations we use (unused by Monitor, Applesoft, or ProDOS)
007E00 2 PARAM0 = $06
007E00 2 PARAM1 = $07
007E00 2 PARAM2 = $08
007E00 2 PARAM3 = $09
007E00 2 SCRATCH0 = $19
007E00 2 SCRATCH1 = $1a
007E00 2
007E00 1 .include "switches.s"
007E00 2 ;
007E00 2 ; switches.s
007E00 2 ; Softswitches for Apple ][
007E00 2 ;
007E00 2 ; Created by Quinn Dunki on 8/15/14.
007E00 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved.
007E00 2 ;
007E00 2
007E00 2
007E00 2 PAGE2 = $c01c ; Read bit 7
007E00 2 PAGE2OFF = $c054 ; Read/Write
007E00 2 PAGE2ON = $c055 ; Read/Write
007E00 2
007E00 2 COL80 = $c01f ; Read bit 7
007E00 2 COL80OFF = $c00c ; Write
007E00 2 COL80ON = $c00d ; Write
007E00 2
007E00 2 STORE80 = $c018 ; Read bit 7
007E00 2 STORE80OFF = $c000 ; Write
007E00 2 STORE80ON = $c001 ; Write
007E00 2
007E00 2 TEXT = $c01a ; Read bit 7
007E00 2 TEXTOFF = $c050 ; Read/Write
007E00 2 TEXTON = $C051 ; Read/Write
007E00 2
007E00 2 KBD = $c000 ; Read
007E00 2 KBDSTRB = $c010 ; Read/Write
007E00 2
007E00 2 RDVBLBAR = $C019 ; Read bit 7 (active low)
007E00 2
007E00 2 OURCH = $057b ; 80 col cursor position (H)
007E00 2 OURCV = $05fb ; 80 col cursor position (V)
007E00 2
007E00 1 .include "macros.s"
007E00 2 ;
007E00 2 ; macros.s
007E00 2 ; Generally useful macros for 6502 code
007E00 2 ;
007E00 2 ; Created by Quinn Dunki on 8/15/14.
007E00 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved.
007E00 2 ;
007E00 2
007E00 2
007E00 2 ; Macros
007E00 2
007E00 2 .macro SETSWITCH name ; Sets the named softswitch (assumes write method)
007E00 2 sta name
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 .macro SAVE_AXY ; Saves all registers
007E00 2 pha
007E00 2 phx
007E00 2 phy
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 .macro RESTORE_AXY ; Restores all registers
007E00 2 ply
007E00 2 plx
007E00 2 pla
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 .macro SAVE_AY ; Saves accumulator and Y index
007E00 2 pha
007E00 2 phy
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 .macro RESTORE_AY ; Restores accumulator and Y index
007E00 2 ply
007E00 2 pla
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 .macro SAVE_AX ; Saves accumulator and X index
007E00 2 pha
007E00 2 phx
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 .macro RESTORE_AX ; Restores accumulator and X index
007E00 2 plx
007E00 2 pla
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 .macro SAVE_XY ; Saves X and Y index
007E00 2 phx
007E00 2 phy
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 .macro RESTORE_XY ; Restores X and Y index
007E00 2 ply
007E00 2 plx
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 .macro SAVE_ZPP ; Saves Zero Page locations we use for parameters
007E00 2 lda PARAM0
007E00 2 pha
007E00 2 lda PARAM1
007E00 2 pha
007E00 2 lda PARAM2
007E00 2 pha
007E00 2 lda PARAM3
007E00 2 pha
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 .macro RESTORE_ZPP ; Restores Zero Page locations we use for parameters
007E00 2 pla
007E00 2 sta PARAM3
007E00 2 pla
007E00 2 sta PARAM2
007E00 2 pla
007E00 2 sta PARAM1
007E00 2 pla
007E00 2 sta PARAM0
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 .macro SAVE_ZPS ; Saves Zero Page locations we use for scratch
007E00 2 lda SCRATCH0
007E00 2 pha
007E00 2 lda SCRATCH1
007E00 2 pha
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 .macro RESTORE_ZPS ; Restores Zero Page locations we use for scratch
007E00 2 pla
007E00 2 sta SCRATCH1
007E00 2 pla
007E00 2 sta SCRATCH0
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 .macro PARAM16 addr
007E00 2 lda #<addr
007E00 2 sta PARAM0
007E00 2 lda #>addr
007E00 2 sta PARAM1
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 .macro CALL16 func,addr
007E00 2 PARAM16 addr
007E00 2 jsr func
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
007E00 2 ; Rendering macros
007E00 2 ;
007E00 2
007E00 2
007E00 2 .macro LDY_AVIEW
007E00 2 asl ; Find our new view record
007E00 2 asl
007E00 2 asl
007E00 2 asl ; Records are 16 bytes wide
007E00 2 tay
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 .macro LDY_ACTIVEVIEW
007E00 2 lda WG_ACTIVEVIEW ; Find our new view record
007E00 2 LDY_AVIEW
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 .macro LDX_ACTIVEVIEW
007E00 2 lda WG_ACTIVEVIEW ; Find our new view record
007E00 2 asl
007E00 2 asl
007E00 2 asl
007E00 2 asl ; Records are 16 bytes wide
007E00 2 tax
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 .macro LDY_FOCUSVIEW
007E00 2 lda WG_FOCUSVIEW ; Find our new view record
007E00 2 LDY_AVIEW
007E00 2 .endmacro
007E00 2
007E00 2
007E00 2 .macro VBL_SYNC ; Synchronize with vertical blanking
007E00 2 lda #$80
007E00 2 ;macroWaitVBLToFinish:
007E00 2 ; bit RDVBLBAR
007E00 2 ; bmi macroWaitVBLToFinish
007E00 2 @macroWaitVBLToStart:
007E00 2 ; bit RDVBLBAR
007E00 2 ; bpl @macroWaitVBLToStart
007E00 2 .endmacro
007E00 2
007E00 1
007E00 1
007E00 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
007E00 1 ; Main entry point. BRUN will land here.
007E00 1 main:
007E00 1 20 49 7E jsr WGInit
007E03 1 60 rts ; Don't add any bytes here!
007E04 1
007E04 1
007E04 1 ; This is the non-negotiable entry point used by applications Don't move it!
007E04 1 ; $7e04
007E04 1
007E04 1
007E04 1
007E04 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
007E04 1 ; WGDispatch
007E04 1 ; The dispatcher for calling the assembly-language API from assembly programs
007E04 1 ; X: API call number
007E04 1 ; P0-3,Y: Parameters to call, as needed
007E04 1 WGDispatch:
007E04 1 7C 07 7E jmp (WGEntryPointTable,x)
007E07 1
007E07 1 ; Entry point jump table
007E07 1 WGEntryPointTable:
007E07 1 FF 7E .addr WGClearScreen
007E09 1 29 7F .addr WGDesktop
007E0B 1 4F 89 .addr WGSetCursor
007E0D 1 5C 89 .addr WGSetGlobalCursor
007E0F 1 69 89 .addr WGSyncGlobalCursor
007E11 1 55 7F .addr WGPlot
007E13 1 90 7F .addr WGPrint
007E15 1 98 80 .addr WGFillRect
007E17 1 24 81 .addr WGStrokeRect
007E19 1 15 83 .addr WGFancyRect
007E1B 1 B6 85 .addr WGPaintView
007E1D 1 3A 8A .addr WGViewPaintAll
007E1F 1 16 87 .addr WGEraseViewContents
007E21 1 B9 84 .addr WGCreateView
007E23 1 0F 85 .addr WGCreateCheckbox
007E25 1 5E 85 .addr WGCreateButton
007E27 1 21 89 .addr WGViewSetTitle
007E29 1 38 89 .addr WGViewSetAction
007E2B 1 57 87 .addr WGSelectView
007E2D 1 5D 8A .addr WGViewFromPoint
007E2F 1 64 87 .addr WGViewFocus
007E31 1 77 87 .addr WGViewUnfocus
007E33 1 82 87 .addr WGViewFocusNext
007E35 1 B3 87 .addr WGViewFocusPrev
007E37 1 2D 88 .addr WGViewFocusAction
007E39 1 97 88 .addr WGPendingViewAction
007E3B 1 1D 89 .addr WGPendingView
007E3D 1 92 89 .addr WGScrollX
007E3F 1 A5 89 .addr WGScrollXBy
007E41 1 E6 89 .addr WGScrollY
007E43 1 F9 89 .addr WGScrollYBy
007E45 1 62 8B .addr WGEnableMouse
007E47 1 BE 8B .addr WGDisableMouse
007E49 1
007E49 1
007E49 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
007E49 1 ; WGInit
007E49 1 ; Initialization. Should be called once at app startup
007E49 1 WGInit:
007E49 1 48 DA 5A SAVE_AXY
007E4C 1
007E4C 1 ; Reserve our memory in the ProDOS allocator bitmap
007E4C 1 ;
007E4C 1 ; See section 5.1.4 in the ProDOS 8 Technical Reference Manual
007E4C 1 ; for an explanation of these values. We're reserving memory
007E4C 1 ; pages $7e-$95 so that ProDOS won't use our memory for file
007E4C 1 ; buffers, or allow Applesoft to step on us
007E4C 1 ;
007E4C 1 ; Byte in System Bitmap : Bit within byte
007E4C 1 ; 0f:001
007E4C 1 ; 0f:000
007E4C 1 ; 10:111 .. 10:000
007E4C 1 ; 11:111 .. 11:000
007E4C 1 ; 12:111
007E4C 1 ; 12:110
007E4C 1 ; 12:101
007E4C 1 ; 12:100
007E4C 1 ; 12:011
007E4C 1 ; 12:010
007E4C 1 A9 03 lda #%00000011
007E4E 1 0C 67 BF tsb MEMBITMAP + $0f
007E51 1 A9 FF lda #$ff
007E53 1 0C 68 BF tsb MEMBITMAP + $10
007E56 1 0C 69 BF tsb MEMBITMAP + $11
007E59 1 A9 FC lda #%11111100
007E5B 1 0C 6A BF tsb MEMBITMAP + $12
007E5E 1
007E5E 1 20 80 7E jsr WG80 ; Enter 80-col text mode
007E61 1 20 C6 8D jsr WGInitApplesoft ; Set up Applesoft API
007E64 1
007E64 1 A0 0F ldy #15 ; Clear our block allocators
007E66 1 WGInit_clearMemLoop:
007E66 1 98 tya
007E67 1 0A asl
007E68 1 0A asl
007E69 1 0A asl
007E6A 1 0A asl
007E6B 1 AA tax
007E6C 1 A9 00 lda #0
007E6E 1 9D D6 93 sta WG_STRINGS,x
007E71 1 88 dey
007E72 1 10 F2 bpl WGInit_clearMemLoop
007E74 1
007E74 1 A9 FF lda #$ff
007E76 1 8D CF 92 sta WG_PENDINGACTIONVIEW
007E79 1 8D CE 92 sta WG_FOCUSVIEW
007E7C 1
007E7C 1 7A FA 68 RESTORE_AXY
007E7F 1 60 rts
007E80 1
007E80 1
007E80 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
007E80 1 ; WG80
007E80 1 ; Enables 80 column mode (and enhanced video firmware)
007E80 1 WG80:
007E80 1 48 pha
007E81 1
007E81 1 A9 A0 lda #$a0
007E83 1 20 00 C3 jsr $c300
007E86 1
007E86 1 8D 51 C0 SETSWITCH TEXTON
007E89 1 8D 54 C0 SETSWITCH PAGE2OFF
007E8C 1 8D 0D C0 SETSWITCH COL80ON
007E8F 1 8D 01 C0 SETSWITCH STORE80ON
007E92 1
007E92 1 68 pla
007E93 1 60 rts
007E94 1
007E94 1
007E94 1 ; Code modules
007E94 1 .include "utility.s"
007E94 2 ;
007E94 2 ; utility.s
007E94 2 ; General utilities for 6502
007E94 2 ;
007E94 2 ; Created by Quinn Dunki on 8/15/14.
007E94 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved.
007E94 2 ;
007E94 2
007E94 2
007E94 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
007E94 2 ; delayShort
007E94 2 ; Sleeps for ~1/30th second
007E94 2 ;
007E94 2 delayShort:
007E94 2 48 DA 5A SAVE_AXY
007E97 2
007E97 2 A0 06 ldy #$06 ; Loop a bit
007E99 2 delayShortOuter:
007E99 2 A2 FF ldx #$ff
007E9B 2 delayShortInner:
007E9B 2 EA nop
007E9C 2 EA nop
007E9D 2 EA nop
007E9E 2 EA nop
007E9F 2 EA nop
007EA0 2 EA nop
007EA1 2 EA nop
007EA2 2 CA dex
007EA3 2 D0 F6 bne delayShortInner
007EA5 2 88 dey
007EA6 2 D0 F1 bne delayShortOuter
007EA8 2
007EA8 2 7A FA 68 RESTORE_AXY
007EAB 2 60 rts
007EAC 2
007EAC 2 .if 0
007EAC 2 ;;;;;;;;;;;;;;;;;;;;;;;
007EAC 2 ; scanHexDigit
007EAC 2 ; Scans a 4 bit hex value from an ASCII character
007EAC 2 ; A: ASCII character
007EAC 2 ; Out A: Hex value
007EAC 2 ;
007EAC 2 scanHexDigit:
007EAC 2 cmp #'a'
007EAC 2 bcs scanHexDigitLowCase
007EAC 2 cmp #'A'
007EAC 2 bcs scanHexDigitLetter
007EAC 2 sec
007EAC 2 sbc #'0'
007EAC 2 jmp scanHexDigitDone
007EAC 2
007EAC 2 scanHexDigitLowCase:
007EAC 2 sec
007EAC 2 sbc #32
007EAC 2
007EAC 2 scanHexDigitLetter:
007EAC 2 sec
007EAC 2 sbc #55
007EAC 2
007EAC 2 scanHexDigitDone:
007EAC 2 rts
007EAC 2
007EAC 2
007EAC 2 ;;;;;;;;;;;;;;;;;;;;;;;
007EAC 2 ; scanHex8
007EAC 2 ; Scans an 8 bit hex value from a string
007EAC 2 ; PARAM0: Pointer to string (LSB)
007EAC 2 ; PARAM1: Pointer to string (MSB)
007EAC 2 ; Y: Offset into string
007EAC 2 ; Out A: 8-bit hex value
007EAC 2 ; Y: One past what we scanned
007EAC 2 ; Side effects: Clobbers S0
007EAC 2 ;
007EAC 2 scanHex8:
007EAC 2 lda (PARAM0),y
007EAC 2 jsr scanHexDigit
007EAC 2 asl
007EAC 2 asl
007EAC 2 asl
007EAC 2 asl
007EAC 2 sta SCRATCH0 ; Stash first digit for later
007EAC 2
007EAC 2 iny
007EAC 2 lda (PARAM0),y
007EAC 2 jsr scanHexDigit
007EAC 2 ora SCRATCH0
007EAC 2 iny ; Be nice and advance Y to end
007EAC 2 rts
007EAC 2 .endif
007EAC 2
007EAC 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
007EAC 2 ; WGStrLen
007EAC 2 ; Finds the length of a null-terminated string
007EAC 2 ; PARAM0: String pointer, LSB
007EAC 2 ; PARAM1: String pointer, MSB
007EAC 2 ; Return: A: String length, not including null
007EAC 2 ;
007EAC 2 WGStrLen:
007EAC 2 5A phy
007EAD 2
007EAD 2 A0 00 ldy #0
007EAF 2 WGStrLen_loop:
007EAF 2 B1 06 lda (PARAM0),y
007EB1 2 F0 03 beq WGStrLen_done
007EB3 2 C8 iny
007EB4 2 80 F9 bra WGStrLen_loop
007EB6 2
007EB6 2 WGStrLen_done:
007EB6 2 98 tya
007EB7 2 7A ply
007EB8 2 60 rts
007EB9 2
007EB9 2
007EB9 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
007EB9 2 ; WGStoreStr
007EB9 2 ; Finds room in our block allocator and copies the given string.
007EB9 2 ; A: Terminator character
007EB9 2 ; PARAM0: String pointer, LSB
007EB9 2 ; PARAM1: String pointer, MSB
007EB9 2 ; Return: PARAM0: Stored string, LSB
007EB9 2 ; PARAM1: Stored string, MSB
007EB9 2 ; Side Effects: Clobbers SA
007EB9 2 ;
007EB9 2 WGStoreStr:
007EB9 2 8D D6 94 sta WG_SCRATCHA
007EBC 2 48 DA 5A SAVE_AXY
007EBF 2
007EBF 2 A2 00 ldx #0
007EC1 2 A0 00 ldy #0
007EC3 2
007EC3 2 WGStoreStr_findEmptyLoop:
007EC3 2 BD D6 93 lda WG_STRINGS,x
007EC6 2 F0 11 beq WGStoreStr_copy
007EC8 2 8A txa
007EC9 2 18 clc
007ECA 2 69 10 adc #16 ; String blocks are 16 bytes wide
007ECC 2 B0 03 bcs WGStoreStr_noRoom
007ECE 2 AA tax
007ECF 2 80 F2 bra WGStoreStr_findEmptyLoop
007ED1 2
007ED1 2 WGStoreStr_noRoom:
007ED1 2 A9 00 lda #0
007ED3 2 85 06 sta PARAM0
007ED5 2 85 07 sta PARAM1
007ED7 2 80 22 bra WGStoreStr_done
007ED9 2
007ED9 2 WGStoreStr_copy:
007ED9 2 DA phx ; Remember the start of our string
007EDA 2
007EDA 2 WGStoreStr_copyLoop:
007EDA 2 B1 06 lda (PARAM0),y
007EDC 2 CD D6 94 cmp WG_SCRATCHA
007EDF 2 F0 09 beq WGStoreStr_terminate
007EE1 2 9D D6 93 sta WG_STRINGS,x
007EE4 2 E8 inx
007EE5 2 C8 iny
007EE6 2 C0 0F cpy #15 ; Clip string to maximum block size
007EE8 2 D0 F0 bne WGStoreStr_copyLoop
007EEA 2
007EEA 2 WGStoreStr_terminate:
007EEA 2 A9 00 lda #0 ; Terminate the stored string
007EEC 2 9D D6 93 sta WG_STRINGS,x
007EEF 2
007EEF 2 68 pla ; Return pointer to the start of the block
007EF0 2 18 clc
007EF1 2 69 D6 adc #<WG_STRINGS
007EF3 2 85 06 sta PARAM0
007EF5 2 A9 00 lda #0
007EF7 2 69 93 adc #>WG_STRINGS
007EF9 2 85 07 sta PARAM1
007EFB 2
007EFB 2 WGStoreStr_done:
007EFB 2 7A FA 68 RESTORE_AXY
007EFE 2 60 rts
007EFF 2
007EFF 1 .include "painting.s"
007EFF 2 ;
007EFF 2 ; painting.s
007EFF 2 ; General rendering routines for 80 column text elements
007EFF 2 ;
007EFF 2 ; Created by Quinn Dunki on 8/15/14.
007EFF 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved.
007EFF 2 ;
007EFF 2
007EFF 2
007EFF 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
007EFF 2 ; WGClearScreen
007EFF 2 ; Clears the text screen (assumes 80 cols)
007EFF 2 ; Side effects: Clobbers BASL,BASH
007EFF 2 ;
007EFF 2 WGClearScreen:
007EFF 2
007EFF 2 48 DA 5A SAVE_AXY
007F02 2 8D 54 C0 SETSWITCH PAGE2OFF
007F05 2 A2 17 ldx #23
007F07 2
007F07 2 WGClearScreen_lineLoop:
007F07 2
007F07 2 BD EF 94 lda TEXTLINES_L,x ; Compute video memory address of line
007F0A 2 85 28 sta BASL
007F0C 2 BD D7 94 lda TEXTLINES_H,x
007F0F 2 85 29 sta BASH
007F11 2
007F11 2 A0 27 ldy #39
007F13 2 A9 A0 lda #' ' + $80
007F15 2
007F15 2 WGClearScreen_charLoop:
007F15 2 91 28 sta (BASL),y
007F17 2 8D 55 C0 SETSWITCH PAGE2ON
007F1A 2 91 28 sta (BASL),y
007F1C 2 8D 54 C0 SETSWITCH PAGE2OFF
007F1F 2 88 dey
007F20 2 10 F3 bpl WGClearScreen_charLoop
007F22 2
007F22 2 CA dex
007F23 2 10 E2 bpl WGClearScreen_lineLoop
007F25 2
007F25 2 7A FA 68 RESTORE_AXY
007F28 2 60 rts
007F29 2
007F29 2
007F29 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
007F29 2 ; WGDesktop
007F29 2 ; Paints the desktop pattern (assumes 80 cols)
007F29 2 ; Side effects: Clobbers BASL,BASH
007F29 2 ;
007F29 2 WGDesktop:
007F29 2
007F29 2 48 DA 5A SAVE_AXY
007F2C 2 8D 54 C0 SETSWITCH PAGE2OFF
007F2F 2 A2 17 ldx #23
007F31 2
007F31 2 WGDesktop_lineLoop:
007F31 2 BD EF 94 lda TEXTLINES_L,x ; Compute video memory address of line
007F34 2 85 28 sta BASL
007F36 2 BD D7 94 lda TEXTLINES_H,x
007F39 2 85 29 sta BASH
007F3B 2
007F3B 2 A0 27 ldy #39
007F3D 2
007F3D 2 WGDesktop_charLoop:
007F3D 2 A9 57 lda #'W'
007F3F 2 91 28 sta (BASL),y
007F41 2 8D 55 C0 SETSWITCH PAGE2ON
007F44 2 A9 56 lda #'V'
007F46 2 91 28 sta (BASL),y
007F48 2 8D 54 C0 SETSWITCH PAGE2OFF
007F4B 2 88 dey
007F4C 2 10 EF bpl WGDesktop_charLoop
007F4E 2
007F4E 2 CA dex
007F4F 2 10 E0 bpl WGDesktop_lineLoop
007F51 2
007F51 2 7A FA 68 RESTORE_AXY
007F54 2 60 rts
007F55 2
007F55 2
007F55 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
007F55 2 ; WGPlot
007F55 2 ; Plots a character at global cursor position (assumes 80 cols)
007F55 2 ; A: Character to plot (Apple format)
007F55 2 ; Side effects: Clobbers BASL,BASH
007F55 2 ;
007F55 2 WGPlot:
007F55 2 DA 5A SAVE_XY
007F57 2 48 pha
007F58 2
007F58 2 AE CA 92 ldx WG_CURSORY
007F5B 2 BD EF 94 lda TEXTLINES_L,x ; Compute video memory address of point
007F5E 2 85 28 sta BASL
007F60 2 BD D7 94 lda TEXTLINES_H,x
007F63 2 85 29 sta BASH
007F65 2
007F65 2 AD C9 92 lda WG_CURSORX
007F68 2 4A lsr
007F69 2 18 clc
007F6A 2 65 28 adc BASL
007F6C 2 85 28 sta BASL
007F6E 2 A9 00 lda #$0
007F70 2 65 29 adc BASH
007F72 2 85 29 sta BASH
007F74 2
007F74 2 AD C9 92 lda WG_CURSORX ; X even?
007F77 2 29 01 and #$01
007F79 2 D0 09 bne WGPlot_xOdd
007F7B 2
007F7B 2 8D 55 C0 SETSWITCH PAGE2ON ; Plot the character
007F7E 2 68 pla
007F7F 2 92 28 sta (BASL)
007F81 2 4C 8A 7F jmp WGPlot_done
007F84 2
007F84 2 WGPlot_xOdd:
007F84 2 8D 54 C0 SETSWITCH PAGE2OFF ; Plot the character
007F87 2 68 pla
007F88 2 92 28 sta (BASL)
007F8A 2
007F8A 2 WGPlot_done:
007F8A 2 8D 54 C0 SETSWITCH PAGE2OFF
007F8D 2 7A FA RESTORE_XY
007F8F 2 60 rts
007F90 2
007F90 2
007F90 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
007F90 2 ; WGPrint
007F90 2 ; Prints a null-terminated ASCII string at the current view's
007F90 2 ; cursor position. Clips to current view.
007F90 2 ; PARAM0: String pointer, LSB
007F90 2 ; PARAM1: String pointer, MSB
007F90 2 ; Side effects: Clobbers SA,BASL,BASH
007F90 2 ;
007F90 2 WGPrint:
007F90 2 48 DA 5A SAVE_AXY
007F93 2 A5 19 48 A5 SAVE_ZPS
007F97 2 1A 48
007F99 2
007F99 2 AD CC 92 lda WG_LOCALCURSORY
007F9C 2 CD D4 92 cmp WG_VIEWCLIP+3
007F9F 2 B0 35 bcs WGPrint_leapDone ; Entire string is below the clip box
007FA1 2
007FA1 2 20 AC 7E jsr WGStrLen ; We'll need the length of the string
007FA4 2 85 1A sta SCRATCH1
007FA6 2
007FA6 2 AD CD 92 0A LDX_ACTIVEVIEW ; Cache view width for later
007FAA 2 0A 0A 0A AA
007FAE 2 BD DD 92 lda WG_VIEWRECORDS+7,x
007FB1 2 8D D6 94 sta WG_SCRATCHA
007FB4 2
007FB4 2 A0 00 ldy #0
007FB6 2
007FB6 2 WGPrint_lineLoopFirst: ; Calculating start of first line is slightly different
007FB6 2 AD CC 92 lda WG_LOCALCURSORY
007FB9 2 CD D2 92 cmp WG_VIEWCLIP+1
007FBC 2 90 1A bcc WGPrint_skipToEndFirst ; This line is above the clip box
007FBE 2
007FBE 2 AD CB 92 lda WG_LOCALCURSORX ; Find start of line within clip box
007FC1 2 CD D1 92 cmp WG_VIEWCLIP+0
007FC4 2 B0 54 bcs WGPrint_visibleChars
007FC6 2
007FC6 2 AD D1 92 lda WG_VIEWCLIP+0 ; Line begins before left clip plane
007FC9 2 38 sec ; Advance string index and advance cursor into clip box
007FCA 2 ED CB 92 sbc WG_LOCALCURSORX
007FCD 2 A8 tay
007FCE 2 AD D1 92 lda WG_VIEWCLIP+0
007FD1 2 8D CB 92 sta WG_LOCALCURSORX
007FD4 2 80 44 bra WGPrint_visibleChars
007FD6 2
007FD6 2 WGPrint_leapDone:
007FD6 2 80 6A bra WGPrint_done
007FD8 2
007FD8 2 WGPrint_skipToEndFirst:
007FD8 2 AD D6 94 lda WG_SCRATCHA ; Skip string index ahead by distance to EOL
007FDB 2 38 sec
007FDC 2 ED CB 92 sbc WG_LOCALCURSORX
007FDF 2 C5 1A cmp SCRATCH1
007FE1 2 B0 5F bcs WGPrint_done ; EOL is past the end of the string, so we're done
007FE3 2 A8 tay
007FE4 2
007FE4 2 AD D6 94 lda WG_SCRATCHA ; Skip cursor ahead to EOL
007FE7 2 8D CB 92 sta WG_LOCALCURSORX
007FEA 2 80 6A bra WGPrint_nextLine
007FEC 2
007FEC 2 WGPrint_skipToEnd:
007FEC 2 98 tya ; Skip string index ahead by distance to EOL
007FED 2 18 clc
007FEE 2 6D D6 94 adc WG_SCRATCHA
007FF1 2 C5 1A cmp SCRATCH1
007FF3 2 B0 4D bcs WGPrint_done ; EOL is past the end of the string, so we're done
007FF5 2 A8 tay
007FF6 2
007FF6 2 AD D6 94 lda WG_SCRATCHA ; Skip cursor ahead to EOL
007FF9 2 8D CB 92 sta WG_LOCALCURSORX
007FFC 2 80 58 bra WGPrint_nextLine
007FFE 2
007FFE 2 WGPrint_lineLoop:
007FFE 2 AD CC 92 lda WG_LOCALCURSORY
008001 2 CD D2 92 cmp WG_VIEWCLIP+1
008004 2 90 E6 bcc WGPrint_skipToEnd ; This line is above the clip box
008006 2
008006 2 AD CB 92 lda WG_LOCALCURSORX ; Find start of line within clip box
008009 2 CD D1 92 cmp WG_VIEWCLIP+0
00800C 2 B0 0C bcs WGPrint_visibleChars
00800E 2
00800E 2 98 tya
00800F 2 18 clc
008010 2 6D D1 92 adc WG_VIEWCLIP+0 ; Jump ahead by left span
008013 2 A8 tay
008014 2
008014 2 AD D1 92 lda WG_VIEWCLIP+0 ; Set cursor to left edge of visible area
008017 2 8D CB 92 sta WG_LOCALCURSORX
00801A 2
00801A 2 WGPrint_visibleChars:
00801A 2 20 69 89 jsr WGSyncGlobalCursor
00801D 2
00801D 2 A5 32 lda INVERSE
00801F 2 C9 3F cmp #CHAR_INVERSE
008021 2 F0 4E beq WGPrint_charLoopInverse
008023 2
008023 2 WGPrint_charLoopNormal:
008023 2 B1 06 lda (PARAM0),y ; Draw current character
008025 2 F0 1B beq WGPrint_done
008027 2 09 80 ora #%10000000
008029 2 20 55 7F jsr WGPlot
00802C 2 C8 iny
00802D 2
00802D 2 EE C9 92 inc WG_CURSORX ; Advance cursors
008030 2 EE CB 92 inc WG_LOCALCURSORX
008033 2
008033 2 AD CB 92 lda WG_LOCALCURSORX
008036 2 CD D6 94 cmp WG_SCRATCHA ; Check for wrap boundary
008039 2 F0 1B beq WGPrint_nextLine
00803B 2 CD D3 92 cmp WG_VIEWCLIP+2 ; Check for right clip plane
00803E 2 F0 0C beq WGPrint_endVisible
008040 2 80 E1 bra WGPrint_charLoopNormal
008042 2
008042 2 WGPrint_done: ; This is in the middle here to keep local branches in range
008042 2 68 85 1A 68 RESTORE_ZPS
008046 2 85 19
008048 2 7A FA 68 RESTORE_AXY
00804B 2 60 rts
00804C 2
00804C 2 WGPrint_endVisible:
00804C 2 98 tya
00804D 2 18 clc
00804E 2 6D D5 92 adc WG_VIEWCLIP+4 ; Advance string index by right span
008051 2 C5 1A cmp SCRATCH1
008053 2 B0 ED bcs WGPrint_done
008055 2 A8 tay
008056 2
008056 2 WGPrint_nextLine:
008056 2 EE CC 92 inc WG_LOCALCURSORY ; Advance cursor
008059 2 AD CC 92 lda WG_LOCALCURSORY
00805C 2 CD D4 92 cmp WG_VIEWCLIP+3 ; Check for bottom clip plane
00805F 2 F0 E1 beq WGPrint_done
008061 2 DD DE 92 cmp WG_VIEWRECORDS+8,x ; Check for bottom of view
008064 2 F0 DC beq WGPrint_done
008066 2 B1 06 lda (PARAM0),y ; Check for end string landing exactly at line end
008068 2 F0 D8 beq WGPrint_done
00806A 2
00806A 2 A9 00 lda #0 ; Wrap to next line
00806C 2 8D CB 92 sta WG_LOCALCURSORX
00806F 2 80 8D bra WGPrint_lineLoop
008071 2
008071 2 WGPrint_charLoopInverse:
008071 2 B1 06 lda (PARAM0),y ; Draw current character
008073 2 F0 CD beq WGPrint_done
008075 2 C9 60 cmp #$60
008077 2 90 04 bcc WGPrint_charLoopInverseLow
008079 2 29 7F and #%01111111 ; Inverse lowercase is in alternate character set
00807B 2 80 02 bra WGPrint_charLoopInversePlot
00807D 2
00807D 2 WGPrint_charLoopInverseLow:
00807D 2 29 3F and #%00111111 ; Normal inverse
00807F 2
00807F 2 WGPrint_charLoopInversePlot:
00807F 2 20 55 7F jsr WGPlot
008082 2 C8 iny
008083 2
008083 2 EE C9 92 inc WG_CURSORX ; Advance cursors
008086 2 EE CB 92 inc WG_LOCALCURSORX
008089 2
008089 2 AD CB 92 lda WG_LOCALCURSORX
00808C 2 CD D6 94 cmp WG_SCRATCHA ; Check for wrap boundary
00808F 2 F0 C5 beq WGPrint_nextLine
008091 2 CD D3 92 cmp WG_VIEWCLIP+2 ; Check for right clip plane
008094 2 F0 B6 beq WGPrint_endVisible
008096 2 80 D9 bra WGPrint_charLoopInverse
008098 2
008098 2
008098 1 .include "rects.s"
008098 2 ;
008098 2 ; rects.s
008098 2 ; Rectangle rendering routines for 80 column text elements
008098 2 ;
008098 2 ; Created by Quinn Dunki on 8/15/14.
008098 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved.
008098 2 ;
008098 2
008098 2
008098 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008098 2 ; WGFillRect
008098 2 ; Fills a rectangle (assumes 80 cols)
008098 2 ; PARAM0: Left edge
008098 2 ; PARAM1: Top edge
008098 2 ; PARAM2: Width
008098 2 ; PARAM3: Height
008098 2 ; Y: Character to fill (Apple format)
008098 2 ; Side effects: Clobbers Y,S0,BASL,BASH
008098 2 ;
008098 2 WGFillRect:
008098 2 48 DA SAVE_AX
00809A 2 84 19 sty SCRATCH0
00809C 2
00809C 2 18 clc ; Compute bottom edge
00809D 2 A5 07 lda PARAM1
00809F 2 65 09 adc PARAM3
0080A1 2 3A dec
0080A2 2 AA tax
0080A3 2
0080A3 2 WGFillRect_vertLoop:
0080A3 2 DA phx ; We'll need X back for now, but save the line number
0080A4 2
0080A4 2 BD EF 94 lda TEXTLINES_L,x ; Compute video memory address of left edge of rect
0080A7 2 85 28 sta BASL
0080A9 2 BD D7 94 lda TEXTLINES_H,x
0080AC 2 85 29 sta BASH
0080AE 2
0080AE 2 A5 06 lda PARAM0
0080B0 2 4A lsr
0080B1 2 18 clc
0080B2 2 65 28 adc BASL
0080B4 2 85 28 sta BASL
0080B6 2 A9 00 lda #$0
0080B8 2 65 29 adc BASH
0080BA 2 85 29 sta BASH
0080BC 2
0080BC 2 A5 06 lda PARAM0 ; Left edge even?
0080BE 2 29 01 and #$01
0080C0 2 D0 2F bne WGFillRect_horzLoopOdd
0080C2 2
0080C2 2 ; CASE 1: Left edge even-aligned, even width
0080C2 2 8D 54 C0 SETSWITCH PAGE2OFF
0080C5 2 A5 08 lda PARAM2
0080C7 2 4A lsr
0080C8 2 A8 tay ; Iterate w/2
0080C9 2 88 dey
0080CA 2 5A phy ; We'll reuse this calculation for the odd columns
0080CB 2
0080CB 2 A5 19 lda SCRATCH0 ; Prepare to plot
0080CD 2 WGFillRect_horzLoopEvenAligned0: ; Draw even columns
0080CD 2 91 28 sta (BASL),y ; Plot the character
0080CF 2 88 dey
0080D0 2 10 FB bpl WGFillRect_horzLoopEvenAligned0 ; Loop for w/2
0080D2 2
0080D2 2 8D 55 C0 SETSWITCH PAGE2ON ; Prepare for odd columns
0080D5 2 7A ply ; Iterate w/2 again
0080D6 2
0080D6 2 WGFillRect_horzLoopEvenAligned1: ; Draw odd columns
0080D6 2 91 28 sta (BASL),y ; Plot the character
0080D8 2 88 dey
0080D9 2 10 FB bpl WGFillRect_horzLoopEvenAligned1 ; Loop for w/2
0080DB 2
0080DB 2 A5 08 lda PARAM2 ; Is width even?
0080DD 2 29 01 and #$01
0080DF 2 F0 08 beq WGFillRect_horzLoopEvenAlignedEvenWidth
0080E1 2
0080E1 2 ; CASE 1a: Left edge even aligned, odd width
0080E1 2 A5 08 lda PARAM2 ; Fill in extra last column
0080E3 2 4A lsr
0080E4 2 A8 tay
0080E5 2 A5 19 lda SCRATCH0 ; Plot the character
0080E7 2 91 28 sta (BASL),y
0080E9 2
0080E9 2 WGFillRect_horzLoopEvenAlignedEvenWidth:
0080E9 2 FA plx ; Prepare for next row
0080EA 2 CA dex
0080EB 2 E4 07 cpx PARAM1
0080ED 2 B0 B4 bcs WGFillRect_vertLoop
0080EF 2 80 2D bra WGFillRect_done
0080F1 2
0080F1 2 WGFillRect_horzLoopOdd:
0080F1 2 ; CASE 2: Left edge odd-aligned, even width
0080F1 2 8D 55 C0 SETSWITCH PAGE2ON
0080F4 2 A5 08 lda PARAM2
0080F6 2 4A lsr
0080F7 2 A8 tay ; Iterate w/2
0080F8 2 5A phy ; We'll reuse this calculation for the even columns
0080F9 2
0080F9 2 A5 19 lda SCRATCH0 ; Prepare to plot
0080FB 2 WGFillRect_horzLoopOddAligned0: ; Draw even columns
0080FB 2 91 28 sta (BASL),y ; Plot the character
0080FD 2 88 dey
0080FE 2 D0 FB bne WGFillRect_horzLoopOddAligned0 ; Loop for w/2
008100 2
008100 2 8D 54 C0 SETSWITCH PAGE2OFF ; Prepare for odd columns
008103 2 7A ply ; Iterate w/2 again, shift left 1
008104 2 88 dey
008105 2
008105 2 WGFillRect_horzLoopOddAligned1: ; Draw even columns
008105 2 91 28 sta (BASL),y ; Plot the character
008107 2 88 dey
008108 2 10 FB bpl WGFillRect_horzLoopOddAligned1 ; Loop for w/2
00810A 2
00810A 2 A5 08 lda PARAM2 ; Is width even?
00810C 2 29 01 and #$01
00810E 2 F0 08 beq WGFillRect_horzLoopOddAlignedEvenWidth
008110 2
008110 2 ; CASE 2a: Left edge odd aligned, odd width
008110 2 A5 08 lda PARAM2 ; Fill in extra last column
008112 2 4A lsr
008113 2 A8 tay
008114 2 A5 19 lda SCRATCH0 ; Plot the character
008116 2 91 28 sta (BASL),y
008118 2
008118 2 WGFillRect_horzLoopOddAlignedEvenWidth:
008118 2 FA plx ; Prepare for next row
008119 2 CA dex
00811A 2 E4 07 cpx PARAM1
00811C 2 B0 85 bcs WGFillRect_vertLoop
00811E 2
00811E 2 WGFillRect_done:
00811E 2 8D 54 C0 SETSWITCH PAGE2OFF
008121 2 FA 68 RESTORE_AX
008123 2 60 rts
008124 2
008124 2
008124 2
008124 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008124 2 ; WGStrokeRect
008124 2 ; Strokes a rectangle (assumes 80 cols)
008124 2 ; PARAM0: Left edge
008124 2 ; PARAM1: Top edge
008124 2 ; PARAM2: Width
008124 2 ; PARAM3: Height
008124 2 ; Side effects: Clobbers BASL,BASH
008124 2 ;
008124 2 CH_TOP = '_'+$80
008124 2 CH_BOTTOM = 'L'
008124 2 CH_LEFT = 'Z'
008124 2 CH_RIGHT = '_'
008124 2 CH_DOUBLE = '\'
008124 2
008124 2 .macro PLOTHLINE
008124 2 lda (BASL),y
008124 2 cmp SCRATCH0
008124 2 beq @PLOTHLINE_skip
008124 2 cmp #CH_DOUBLE
008124 2 beq @PLOTHLINE_skip
008124 2 cmp #CH_BOTTOM
008124 2 beq @PLOTHLINE_double
008124 2 cmp #CH_TOP
008124 2 beq @PLOTHLINE_double
008124 2 lda SCRATCH0
008124 2 bra @PLOTHLINE_plot
008124 2 @PLOTHLINE_double:
008124 2 lda #CH_DOUBLE
008124 2 @PLOTHLINE_plot:
008124 2 sta (BASL),y
008124 2 @PLOTHLINE_skip:
008124 2 .endmacro
008124 2
008124 2
008124 2 WGStrokeRect:
008124 2 48 DA 5A SAVE_AXY
008127 2 A5 19 48 A5 SAVE_ZPS
00812B 2 1A 48
00812D 2
00812D 2 ; Top and bottom edges
00812D 2 ;
00812D 2 A6 07 ldx PARAM1 ; Start with top edge
00812F 2 CA dex
008130 2 A9 DF lda #CH_TOP
008132 2 85 19 sta SCRATCH0
008134 2
008134 2 WGStrokeRect_horzEdge:
008134 2 BD EF 94 lda TEXTLINES_L,x ; Compute video memory address of left edge of rect
008137 2 85 28 sta BASL
008139 2 BD D7 94 lda TEXTLINES_H,x
00813C 2 85 29 sta BASH
00813E 2
00813E 2 A5 06 lda PARAM0
008140 2 4A lsr
008141 2 18 clc
008142 2 65 28 adc BASL
008144 2 85 28 sta BASL
008146 2 A9 00 lda #$0
008148 2 65 29 adc BASH
00814A 2 85 29 sta BASH
00814C 2
00814C 2 A5 06 lda PARAM0 ; Left edge even?
00814E 2 29 01 and #$01
008150 2 F0 03 beq WGStrokeRect_horzEdgeEven
008152 2 4C E3 81 jmp WGStrokeRect_horzLoopOdd
008155 2
008155 2 WGStrokeRect_horzEdgeEven:
008155 2 A5 08 lda PARAM2
008157 2 C9 01 cmp #1 ; Width==1 is a special case
008159 2 D0 03 bne WGStrokeRect_horzLoopEvenAlignedNormalWidth
00815B 2 4C DE 81 jmp WGStrokeRect_horzLoopEvenAlignedOneWidth
00815E 2
00815E 2 WGStrokeRect_horzLoopEvenAlignedNormalWidth:
00815E 2 ; CASE 1: Left edge even-aligned, even width
00815E 2 8D 54 C0 SETSWITCH PAGE2OFF
008161 2 A5 08 lda PARAM2
008163 2 4A lsr
008164 2 A8 tay ; Start at right edge
008165 2 88 dey
008166 2 5A phy ; We'll reuse this calculation for the odd columns
008167 2
008167 2 WGStrokeRect_horzLoopEvenAligned0: ; Draw even columns
008167 2 B1 28 C5 19 PLOTHLINE ; Plot the character
00816B 2 F0 14 C9 5C
00816F 2 F0 10 C9 4C
008181 2 88 dey
008182 2 10 E3 bpl WGStrokeRect_horzLoopEvenAligned0 ; Loop for w/2
008184 2
008184 2 8D 55 C0 SETSWITCH PAGE2ON ; Prepare for odd columns
008187 2 7A ply ; Start at right edge again
008188 2
008188 2 WGStrokeRect_horzLoopEvenAligned1: ; Draw odd columns
008188 2 B1 28 C5 19 PLOTHLINE ; Plot the character
00818C 2 F0 14 C9 5C
008190 2 F0 10 C9 4C
0081A2 2 88 dey
0081A3 2 10 E3 bpl WGStrokeRect_horzLoopEvenAligned1 ; Loop for w/2
0081A5 2
0081A5 2 A5 08 lda PARAM2 ; Is width even?
0081A7 2 29 01 and #$01
0081A9 2 F0 1E beq WGStrokeRect_horzLoopEvenAlignedEvenWidth
0081AB 2
0081AB 2 WGStrokeRect_horzLoopEvenAlignedOddWidth:
0081AB 2 ; CASE 1a: Left edge even aligned, odd width
0081AB 2 A5 08 lda PARAM2 ; Fill in extra last column
0081AD 2 4A lsr
0081AE 2 A8 tay
0081AF 2 B1 28 C5 19 PLOTHLINE ; Plot the character
0081B3 2 F0 14 C9 5C
0081B7 2 F0 10 C9 4C
0081C9 2
0081C9 2 WGStrokeRect_horzLoopEvenAlignedEvenWidth:
0081C9 2 E8 inx
0081CA 2 E4 07 cpx PARAM1
0081CC 2 F0 03 beq WGStrokeRect_horzLoopEvenAlignedEvenWidthBottom
0081CE 2 4C 6C 82 jmp WGStrokeRect_vertEdge
0081D1 2
0081D1 2 WGStrokeRect_horzLoopEvenAlignedEvenWidthBottom:
0081D1 2 18 clc ; Prepare for bottom edge
0081D2 2 A5 07 lda PARAM1
0081D4 2 65 09 adc PARAM3
0081D6 2 AA tax
0081D7 2 A9 4C lda #CH_BOTTOM
0081D9 2 85 19 sta SCRATCH0
0081DB 2 4C 34 81 jmp WGStrokeRect_horzEdge
0081DE 2
0081DE 2 WGStrokeRect_horzLoopEvenAlignedOneWidth:
0081DE 2 8D 55 C0 SETSWITCH PAGE2ON
0081E1 2 80 C8 bra WGStrokeRect_horzLoopEvenAlignedOddWidth
0081E3 2
0081E3 2 WGStrokeRect_horzLoopOdd:
0081E3 2 ; CASE 2: Left edge odd-aligned, even width
0081E3 2
0081E3 2 A5 08 lda PARAM2
0081E5 2 C9 01 cmp #1 ; Width==1 is a special case
0081E7 2 F0 7E beq WGStrokeRect_horzLoopOddAlignedOneWidth
0081E9 2
0081E9 2 8D 55 C0 SETSWITCH PAGE2ON
0081EC 2 A5 08 lda PARAM2
0081EE 2 4A lsr
0081EF 2 A8 tay ; Iterate w/2
0081F0 2 5A phy ; We'll reuse this calculation for the even columns
0081F1 2
0081F1 2 WGStrokeRect_horzLoopOddAligned0: ; Draw even columns
0081F1 2 B1 28 C5 19 PLOTHLINE ; Plot the character
0081F5 2 F0 14 C9 5C
0081F9 2 F0 10 C9 4C
00820B 2 88 dey
00820C 2 D0 E3 bne WGStrokeRect_horzLoopOddAligned0 ; Loop for w/2
00820E 2
00820E 2 8D 54 C0 SETSWITCH PAGE2OFF ; Prepare for odd columns
008211 2 7A ply ; Iterate w/2 again, shift left 1
008212 2 88 dey
008213 2
008213 2 WGStrokeRect_horzLoopOddAligned1: ; Draw even columns
008213 2 B1 28 C5 19 PLOTHLINE ; Plot the character
008217 2 F0 14 C9 5C
00821B 2 F0 10 C9 4C
00822D 2 88 dey
00822E 2 10 E3 bpl WGStrokeRect_horzLoopOddAligned1 ; Loop for w/2
008230 2
008230 2 A5 08 lda PARAM2 ; Is width even?
008232 2 29 01 and #$01
008234 2 F0 1F beq WGStrokeRect_horzLoopOddAlignedEvenWidth
008236 2
008236 2 WGStrokeRect_horzLoopOddAlignedOddWidth:
008236 2 ; CASE 2a: Left edge odd aligned, odd width
008236 2 A5 08 lda PARAM2 ; Fill in extra last column
008238 2 3A dec
008239 2 4A lsr
00823A 2 A8 tay
00823B 2 B1 28 C5 19 PLOTHLINE ; Plot the character
00823F 2 F0 14 C9 5C
008243 2 F0 10 C9 4C
008255 2
008255 2 WGStrokeRect_horzLoopOddAlignedEvenWidth:
008255 2 E8 inx
008256 2 E4 07 cpx PARAM1
008258 2 D0 12 bne WGStrokeRect_vertEdge
00825A 2 18 clc ; Prepare for bottom edge
00825B 2 A5 07 lda PARAM1
00825D 2 65 09 adc PARAM3
00825F 2 AA tax
008260 2 A9 4C lda #CH_BOTTOM
008262 2 85 19 sta SCRATCH0
008264 2 4C 34 81 jmp WGStrokeRect_horzEdge
008267 2
008267 2 WGStrokeRect_horzLoopOddAlignedOneWidth:
008267 2 8D 54 C0 SETSWITCH PAGE2OFF
00826A 2 80 CA bra WGStrokeRect_horzLoopOddAlignedOddWidth
00826C 2
00826C 2 WGStrokeRect_vertEdge:
00826C 2 ; Left and right edges
00826C 2 ;
00826C 2 18 clc
00826D 2 A5 07 lda PARAM1 ; Compute bottom edge
00826F 2 65 09 adc PARAM3
008271 2 85 19 sta SCRATCH0
008273 2
008273 2 A6 07 ldx PARAM1 ; Start with top edge
008275 2
008275 2 WGStrokeRect_vertLoop:
008275 2
008275 2 DA phx ; We'll need X back for now, but save the line number
008276 2
008276 2 BD EF 94 lda TEXTLINES_L,x ; Compute video memory address of left edge of rect
008279 2 85 28 sta BASL
00827B 2 BD D7 94 lda TEXTLINES_H,x
00827E 2 85 29 sta BASH
008280 2
008280 2 A5 06 lda PARAM0
008282 2 3A dec
008283 2 4A lsr
008284 2 18 clc
008285 2 65 28 adc BASL
008287 2 85 28 sta BASL
008289 2 A9 00 lda #$0
00828B 2 65 29 adc BASH
00828D 2 85 29 sta BASH
00828F 2
00828F 2 A5 06 lda PARAM0 ; Left edge even?
008291 2 3A dec
008292 2 29 01 and #$01
008294 2 D0 38 bne WGStrokeRect_vertLoopOdd
008296 2
008296 2 ; CASE 1: Left edge even-aligned, even width
008296 2 8D 55 C0 SETSWITCH PAGE2ON
008299 2 A0 00 ldy #$0
00829B 2 A9 5A lda #CH_LEFT ; Plot the left edge
00829D 2 91 28 sta (BASL),y
00829F 2
00829F 2 A5 08 lda PARAM2 ; Is width even?
0082A1 2 1A inc
0082A2 2 1A inc
0082A3 2 29 01 and #$01
0082A5 2 D0 11 bne WGStrokeRect_vertLoopEvenAlignedOddWidth
0082A7 2
0082A7 2 A5 08 lda PARAM2 ; Calculate right edge
0082A9 2 1A inc
0082AA 2 1A inc
0082AB 2 4A lsr
0082AC 2 3A dec
0082AD 2 A8 tay
0082AE 2 8D 54 C0 SETSWITCH PAGE2OFF
0082B1 2 A9 5F lda #CH_RIGHT ; Plot the right edge
0082B3 2 91 28 sta (BASL),y
0082B5 2 4C C5 82 jmp WGStrokeRect_vertLoopEvenAlignedNextRow
0082B8 2
0082B8 2 WGStrokeRect_vertLoopEvenAlignedOddWidth:
0082B8 2 ; CASE 1a: Left edge even-aligned, odd width
0082B8 2 8D 55 C0 SETSWITCH PAGE2ON
0082BB 2 A5 08 lda PARAM2 ; Calculate right edge
0082BD 2 1A inc
0082BE 2 1A inc
0082BF 2 4A lsr
0082C0 2 A8 tay
0082C1 2 A9 5F lda #CH_RIGHT ; Plot the right edge
0082C3 2 91 28 sta (BASL),y
0082C5 2
0082C5 2 WGStrokeRect_vertLoopEvenAlignedNextRow:
0082C5 2 FA plx ; Prepare for next row
0082C6 2 E8 inx
0082C7 2 E4 19 cpx SCRATCH0
0082C9 2 D0 AA bne WGStrokeRect_vertLoop
0082CB 2 4C 08 83 jmp WGStrokeRect_done
0082CE 2
0082CE 2
0082CE 2 WGStrokeRect_vertLoopOdd:
0082CE 2 ; CASE 2: Left edge odd-aligned, even width
0082CE 2 8D 54 C0 SETSWITCH PAGE2OFF
0082D1 2 A0 00 ldy #$0
0082D3 2 A9 5A lda #CH_LEFT ; Plot the left edge
0082D5 2 91 28 sta (BASL),y
0082D7 2
0082D7 2 A5 08 lda PARAM2 ; Is width even?
0082D9 2 1A inc
0082DA 2 1A inc
0082DB 2 29 01 and #$01
0082DD 2 D0 10 bne WGStrokeRect_vertLoopOddAlignedOddWidth
0082DF 2
0082DF 2 A5 08 lda PARAM2 ; Calculate right edge
0082E1 2 1A inc
0082E2 2 1A inc
0082E3 2 4A lsr
0082E4 2 A8 tay
0082E5 2 8D 55 C0 SETSWITCH PAGE2ON
0082E8 2 A9 5F lda #CH_RIGHT ; Plot the right edge
0082EA 2 91 28 sta (BASL),y
0082EC 2 4C FC 82 jmp WGStrokeRect_vertLoopOddAlignedNextRow
0082EF 2
0082EF 2 WGStrokeRect_vertLoopOddAlignedOddWidth:
0082EF 2 ; CASE 2a: Left edge odd-aligned, odd width
0082EF 2 8D 54 C0 SETSWITCH PAGE2OFF
0082F2 2 A5 08 lda PARAM2 ; Calculate right edge
0082F4 2 1A inc
0082F5 2 1A inc
0082F6 2 4A lsr
0082F7 2 A8 tay
0082F8 2 A9 5F lda #CH_RIGHT ; Plot the right edge
0082FA 2 91 28 sta (BASL),y
0082FC 2
0082FC 2 WGStrokeRect_vertLoopOddAlignedNextRow:
0082FC 2 FA plx ; Prepare for next row
0082FD 2 E8 inx
0082FE 2 E4 19 cpx SCRATCH0
008300 2 D0 03 bne WGStrokeRect_vertLoopJmp
008302 2 4C 08 83 jmp WGStrokeRect_done
008305 2 WGStrokeRect_vertLoopJmp:
008305 2 4C 75 82 jmp WGStrokeRect_vertLoop
008308 2
008308 2 WGStrokeRect_done:
008308 2 8D 54 C0 SETSWITCH PAGE2OFF
00830B 2 68 85 1A 68 RESTORE_ZPS
00830F 2 85 19
008311 2 7A FA 68 RESTORE_AXY
008314 2 60 rts
008315 2
008315 2
008315 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008315 2 ; WGFancyRect
008315 2 ; Draws a fancy rectangle (assumes 80 cols)
008315 2 ; PARAM0: Left edge
008315 2 ; PARAM1: Top edge
008315 2 ; PARAM2: Width
008315 2 ; PARAM3: Height
008315 2 ; Side effects: Clobbers BASL,BASH
008315 2 ;
008315 2 FR_TOP = '\'
008315 2 FR_BOTTOM = '_'+$80
008315 2 FR_LEFT = 'Z'
008315 2 FR_RIGHT = 'Z'
008315 2 FR_TOPLEFT = 'Z'
008315 2 FR_TOPRIGHT = '^'
008315 2 FR_TOPRIGHTA = 'R'
008315 2 FR_BOTTOMRIGHT = $7f
008315 2 FR_BOTTOMRIGHTA1 = 'Q'
008315 2 FR_BOTTOMRIGHTA2 = 'P'
008315 2 FR_BOTTOMLEFT = 'Z'
008315 2 FR_BOTTOMLEFTA = 'O'
008315 2
008315 2 WGFancyRect:
008315 2 48 DA 5A SAVE_AXY
008318 2 A5 19 48 A5 SAVE_ZPS
00831C 2 1A 48
00831E 2
00831E 2 ; Top and bottom edges
00831E 2 ;
00831E 2 A6 07 ldx PARAM1 ; Start with top edge
008320 2 CA dex
008321 2 A9 5C lda #FR_TOP
008323 2 85 19 sta SCRATCH0
008325 2
008325 2 WGFancyRect_horzEdge:
008325 2 BD EF 94 lda TEXTLINES_L,x ; Compute video memory address of left edge of rect
008328 2 85 28 sta BASL
00832A 2 BD D7 94 lda TEXTLINES_H,x
00832D 2 85 29 sta BASH
00832F 2
00832F 2 A5 06 lda PARAM0
008331 2 4A lsr
008332 2 18 clc
008333 2 65 28 adc BASL
008335 2 85 28 sta BASL
008337 2 A9 00 lda #$0
008339 2 65 29 adc BASH
00833B 2 85 29 sta BASH
00833D 2
00833D 2 A5 06 lda PARAM0 ; Left edge even?
00833F 2 29 01 and #$01
008341 2 D0 3B bne WGFancyRect_horzLoopOdd
008343 2
008343 2 ; CASE 1: Left edge even-aligned, even width
008343 2 8D 54 C0 SETSWITCH PAGE2OFF
008346 2 A5 08 lda PARAM2
008348 2 4A lsr
008349 2 A8 tay ; Start at right edge
00834A 2 88 dey
00834B 2 5A phy ; We'll reuse this calculation for the odd columns
00834C 2
00834C 2 WGFancyRect_horzLoopEvenAligned0: ; Draw even columns
00834C 2 A5 19 lda SCRATCH0 ; Plot the character
00834E 2 91 28 sta (BASL),y
008350 2 88 dey
008351 2 10 F9 bpl WGFancyRect_horzLoopEvenAligned0 ; Loop for w/2
008353 2
008353 2 8D 55 C0 SETSWITCH PAGE2ON ; Prepare for odd columns
008356 2 7A ply ; Start at right edge again
008357 2
008357 2 WGFancyRect_horzLoopEvenAligned1: ; Draw odd columns
008357 2 A5 19 lda SCRATCH0 ; Plot the character
008359 2 91 28 sta (BASL),y
00835B 2 88 dey
00835C 2 10 F9 bpl WGFancyRect_horzLoopEvenAligned1 ; Loop for w/2
00835E 2
00835E 2 A5 08 lda PARAM2 ; Is width even?
008360 2 29 01 and #$01
008362 2 F0 08 beq WGFancyRect_horzLoopEvenAlignedEvenWidth
008364 2
008364 2 WGFancyRect_horzLoopEvenAlignedOddWidth:
008364 2 ; CASE 1a: Left edge even aligned, odd width
008364 2 A5 08 lda PARAM2 ; Fill in extra last column
008366 2 4A lsr
008367 2 A8 tay
008368 2 A5 19 lda SCRATCH0 ; Plot the character
00836A 2 91 28 sta (BASL),y
00836C 2
00836C 2 WGFancyRect_horzLoopEvenAlignedEvenWidth:
00836C 2 E8 inx
00836D 2 E4 07 cpx PARAM1
00836F 2 D0 49 bne WGFancyRect_vertEdge
008371 2 18 clc ; Prepare for bottom edge
008372 2 A5 07 lda PARAM1
008374 2 65 09 adc PARAM3
008376 2 AA tax
008377 2 A9 DF lda #FR_BOTTOM
008379 2 85 19 sta SCRATCH0
00837B 2 4C 25 83 jmp WGFancyRect_horzEdge
00837E 2
00837E 2 WGFancyRect_horzLoopOdd:
00837E 2 ; CASE 2: Left edge odd-aligned, even width
00837E 2
00837E 2 8D 55 C0 SETSWITCH PAGE2ON
008381 2 A5 08 lda PARAM2
008383 2 4A lsr
008384 2 A8 tay ; Iterate w/2
008385 2 5A phy ; We'll reuse this calculation for the even columns
008386 2
008386 2 WGFancyRect_horzLoopOddAligned0: ; Draw even columns
008386 2 A5 19 lda SCRATCH0 ; Plot the character
008388 2 91 28 sta (BASL),y
00838A 2 88 dey
00838B 2 D0 F9 bne WGFancyRect_horzLoopOddAligned0 ; Loop for w/2
00838D 2
00838D 2 8D 54 C0 SETSWITCH PAGE2OFF ; Prepare for odd columns
008390 2 7A ply ; Iterate w/2 again, shift left 1
008391 2 88 dey
008392 2
008392 2 WGFancyRect_horzLoopOddAligned1: ; Draw even columns
008392 2 A5 19 lda SCRATCH0 ; Plot the character
008394 2 91 28 sta (BASL),y
008396 2 88 dey
008397 2 10 F9 bpl WGFancyRect_horzLoopOddAligned1 ; Loop for w/2
008399 2
008399 2 A5 08 lda PARAM2 ; Is width even?
00839B 2 29 01 and #$01
00839D 2 F0 09 beq WGFancyRect_horzLoopOddAlignedEvenWidth
00839F 2
00839F 2 WGFancyRect_horzLoopOddAlignedOddWidth:
00839F 2 ; CASE 2a: Left edge odd aligned, odd width
00839F 2 A5 08 lda PARAM2 ; Fill in extra last column
0083A1 2 3A dec
0083A2 2 4A lsr
0083A3 2 A8 tay
0083A4 2 A5 19 lda SCRATCH0 ; Plot the character
0083A6 2 91 28 sta (BASL),y
0083A8 2
0083A8 2 WGFancyRect_horzLoopOddAlignedEvenWidth:
0083A8 2 E8 inx
0083A9 2 E4 07 cpx PARAM1
0083AB 2 D0 0D bne WGFancyRect_vertEdge
0083AD 2 18 clc ; Prepare for bottom edge
0083AE 2 A5 07 lda PARAM1
0083B0 2 65 09 adc PARAM3
0083B2 2 AA tax
0083B3 2 A9 DF lda #FR_BOTTOM
0083B5 2 85 19 sta SCRATCH0
0083B7 2 4C 25 83 jmp WGFancyRect_horzEdge
0083BA 2
0083BA 2 WGFancyRect_vertEdge:
0083BA 2 ; Left and right edges
0083BA 2 ;
0083BA 2 18 clc
0083BB 2 A5 07 lda PARAM1 ; Compute bottom edge
0083BD 2 65 09 adc PARAM3
0083BF 2 85 19 sta SCRATCH0
0083C1 2
0083C1 2 A6 07 ldx PARAM1 ; Start with top edge
0083C3 2
0083C3 2 WGFancyRect_vertLoop:
0083C3 2
0083C3 2 DA phx ; We'll need X back for now, but save the line number
0083C4 2
0083C4 2 BD EF 94 lda TEXTLINES_L,x ; Compute video memory address of left edge of rect
0083C7 2 85 28 sta BASL
0083C9 2 BD D7 94 lda TEXTLINES_H,x
0083CC 2 85 29 sta BASH
0083CE 2
0083CE 2 A5 06 lda PARAM0
0083D0 2 3A dec
0083D1 2 4A lsr
0083D2 2 18 clc
0083D3 2 65 28 adc BASL
0083D5 2 85 28 sta BASL
0083D7 2 A9 00 lda #$0
0083D9 2 65 29 adc BASH
0083DB 2 85 29 sta BASH
0083DD 2
0083DD 2 A5 06 lda PARAM0 ; Left edge even?
0083DF 2 3A dec
0083E0 2 29 01 and #$01
0083E2 2 D0 38 bne WGFancyRect_vertLoopOdd
0083E4 2
0083E4 2 ; CASE 1: Left edge even-aligned, even width
0083E4 2 8D 55 C0 SETSWITCH PAGE2ON
0083E7 2 A0 00 ldy #$0
0083E9 2 A9 5A lda #FR_LEFT ; Plot the left edge
0083EB 2 91 28 sta (BASL),y
0083ED 2
0083ED 2 A5 08 lda PARAM2 ; Is width even?
0083EF 2 1A inc
0083F0 2 1A inc
0083F1 2 29 01 and #$01
0083F3 2 D0 11 bne WGFancyRect_vertLoopEvenAlignedOddWidth
0083F5 2
0083F5 2 A5 08 lda PARAM2 ; Calculate right edge
0083F7 2 1A inc
0083F8 2 1A inc
0083F9 2 4A lsr
0083FA 2 3A dec
0083FB 2 A8 tay
0083FC 2 8D 54 C0 SETSWITCH PAGE2OFF
0083FF 2 A9 5A lda #FR_RIGHT ; Plot the right edge
008401 2 91 28 sta (BASL),y
008403 2 4C 13 84 jmp WGFancyRect_vertLoopEvenAlignedNextRow
008406 2
008406 2 WGFancyRect_vertLoopEvenAlignedOddWidth:
008406 2 ; CASE 1a: Left edge even-aligned, odd width
008406 2 8D 55 C0 SETSWITCH PAGE2ON
008409 2 A5 08 lda PARAM2 ; Calculate right edge
00840B 2 1A inc
00840C 2 1A inc
00840D 2 4A lsr
00840E 2 A8 tay
00840F 2 A9 5A lda #FR_RIGHT ; Plot the right edge
008411 2 91 28 sta (BASL),y
008413 2
008413 2 WGFancyRect_vertLoopEvenAlignedNextRow:
008413 2 FA plx ; Prepare for next row
008414 2 E8 inx
008415 2 E4 19 cpx SCRATCH0
008417 2 D0 AA bne WGFancyRect_vertLoop
008419 2 4C 56 84 jmp WGFancyRect_corners
00841C 2
00841C 2
00841C 2 WGFancyRect_vertLoopOdd:
00841C 2 ; CASE 2: Left edge odd-aligned, even width
00841C 2 8D 54 C0 SETSWITCH PAGE2OFF
00841F 2 A0 00 ldy #$0
008421 2 A9 5A lda #FR_LEFT ; Plot the left edge
008423 2 91 28 sta (BASL),y
008425 2
008425 2 A5 08 lda PARAM2 ; Is width even?
008427 2 1A inc
008428 2 1A inc
008429 2 29 01 and #$01
00842B 2 D0 10 bne WGFancyRect_vertLoopOddAlignedOddWidth
00842D 2
00842D 2 A5 08 lda PARAM2 ; Calculate right edge
00842F 2 1A inc
008430 2 1A inc
008431 2 4A lsr
008432 2 A8 tay
008433 2 8D 55 C0 SETSWITCH PAGE2ON
008436 2 A9 5A lda #FR_RIGHT ; Plot the right edge
008438 2 91 28 sta (BASL),y
00843A 2 4C 4A 84 jmp WGFancyRect_vertLoopOddAlignedNextRow
00843D 2
00843D 2 WGFancyRect_vertLoopOddAlignedOddWidth:
00843D 2 ; CASE 2a: Left edge odd-aligned, odd width
00843D 2 8D 54 C0 SETSWITCH PAGE2OFF
008440 2 A5 08 lda PARAM2 ; Calculate right edge
008442 2 1A inc
008443 2 1A inc
008444 2 4A lsr
008445 2 A8 tay
008446 2 A9 5A lda #FR_RIGHT ; Plot the right edge
008448 2 91 28 sta (BASL),y
00844A 2
00844A 2 WGFancyRect_vertLoopOddAlignedNextRow:
00844A 2 FA plx ; Prepare for next row
00844B 2 E8 inx
00844C 2 E4 19 cpx SCRATCH0
00844E 2 D0 03 bne WGFancyRect_vertLoopJmp
008450 2 4C 56 84 jmp WGFancyRect_corners
008453 2 WGFancyRect_vertLoopJmp:
008453 2 4C C3 83 jmp WGFancyRect_vertLoop
008456 2
008456 2 WGFancyRect_corners:
008456 2 A5 06 lda PARAM0 ; Top left corner
008458 2 3A dec
008459 2 8D C9 92 sta WG_CURSORX
00845C 2 A5 07 lda PARAM1
00845E 2 3A dec
00845F 2 8D CA 92 sta WG_CURSORY
008462 2 A9 5A lda #FR_TOPLEFT
008464 2 20 55 7F jsr WGPlot
008467 2
008467 2 A5 06 lda PARAM0 ; Top right corner
008469 2 18 clc
00846A 2 65 08 adc PARAM2
00846C 2 8D C9 92 sta WG_CURSORX
00846F 2 A9 5E lda #FR_TOPRIGHT
008471 2 20 55 7F jsr WGPlot
008474 2
008474 2 EE CA 92 inc WG_CURSORY
008477 2 A9 52 lda #FR_TOPRIGHTA
008479 2 20 55 7F jsr WGPlot
00847C 2
00847C 2 A5 07 lda PARAM1 ; Bottom right corner
00847E 2 3A dec
00847F 2 18 clc
008480 2 65 09 adc PARAM3
008482 2 8D CA 92 sta WG_CURSORY
008485 2 A9 51 lda #FR_BOTTOMRIGHTA1
008487 2 20 55 7F jsr WGPlot
00848A 2
00848A 2 EE CA 92 inc WG_CURSORY
00848D 2 A9 7F lda #FR_BOTTOMRIGHT
00848F 2 20 55 7F jsr WGPlot
008492 2
008492 2 CE C9 92 dec WG_CURSORX
008495 2 A9 50 lda #FR_BOTTOMRIGHTA2
008497 2 20 55 7F jsr WGPlot
00849A 2
00849A 2 A5 06 lda PARAM0 ; Bottom left corner
00849C 2 8D C9 92 sta WG_CURSORX
00849F 2 A9 4F lda #FR_BOTTOMLEFTA
0084A1 2 20 55 7F jsr WGPlot
0084A4 2 CE C9 92 dec WG_CURSORX
0084A7 2 A9 5A lda #FR_BOTTOMLEFT
0084A9 2 20 55 7F jsr WGPlot
0084AC 2
0084AC 2 WGFancyRect_done:
0084AC 2 8D 54 C0 SETSWITCH PAGE2OFF
0084AF 2 68 85 1A 68 RESTORE_ZPS
0084B3 2 85 19
0084B5 2 7A FA 68 RESTORE_AXY
0084B8 2 60 rts
0084B9 2
0084B9 2
0084B9 1 .include "views.s"
0084B9 2 ;
0084B9 2 ; views.s
0084B9 2 ; Management routines for GUI views
0084B9 2 ;
0084B9 2 ; Created by Quinn Dunki on 8/15/14.
0084B9 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved.
0084B9 2 ;
0084B9 2
0084B9 2
0084B9 2 WG_FEATURE_UP = %00010000
0084B9 2 WG_FEATURE_DN = %00100000
0084B9 2 WG_FEATURE_LF = %00110000
0084B9 2 WG_FEATURE_RT = %01000000
0084B9 2
0084B9 2
0084B9 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0084B9 2 ; WGCreateView
0084B9 2 ; Creates and selects a new view
0084B9 2 ; PARAM0: Pointer to configuration struct (LSB)
0084B9 2 ; PARAM1: Pointer to configuration struct (MSB)
0084B9 2 ;
0084B9 2 ; Configuration struct:
0084B9 2 ; ID: View ID (0-f)
0084B9 2 ; ST: Style
0084B9 2 ; XX: Screen X origin
0084B9 2 ; YY: Screen Y origin
0084B9 2 ; SW: Screen width
0084B9 2 ; SH: Screen height
0084B9 2 ; VW: View Width
0084B9 2 ; VH: View Height
0084B9 2 ;
0084B9 2 WGCreateView:
0084B9 2 48 DA 5A SAVE_AXY
0084BC 2
0084BC 2 A0 00 ldy #0
0084BE 2 B1 06 lda (PARAM0),y ; Find our new view record
0084C0 2 48 pha ; Cache view ID so we can select when we're done
0084C1 2
0084C1 2 0A asl
0084C2 2 0A asl
0084C3 2 0A asl
0084C4 2 0A asl ; Records are 8 bytes wide
0084C5 2 AA tax
0084C6 2
0084C6 2 C8 iny
0084C7 2 B1 06 lda (PARAM0),y
0084C9 2 48 pha ; Cache style byte for later
0084CA 2
0084CA 2 C8 iny
0084CB 2 B1 06 lda (PARAM0),y
0084CD 2 9D D6 92 sta WG_VIEWRECORDS+0,x ; Screen X
0084D0 2
0084D0 2 C8 iny
0084D1 2 B1 06 lda (PARAM0),y
0084D3 2 9D D7 92 sta WG_VIEWRECORDS+1,x ; Screen Y
0084D6 2
0084D6 2 C8 iny
0084D7 2 B1 06 lda (PARAM0),y
0084D9 2 9D D8 92 sta WG_VIEWRECORDS+2,x ; Screen Width
0084DC 2
0084DC 2 C8 iny
0084DD 2 B1 06 lda (PARAM0),y
0084DF 2 9D D9 92 sta WG_VIEWRECORDS+3,x ; Screen Height
0084E2 2
0084E2 2 68 pla
0084E3 2 9D DA 92 sta WG_VIEWRECORDS+4,x ; Style
0084E6 2
0084E6 2 9E DB 92 stz WG_VIEWRECORDS+5,x ; Initialize scrolling
0084E9 2 9E DC 92 stz WG_VIEWRECORDS+6,x
0084EC 2
0084EC 2 C8 iny
0084ED 2 B1 06 lda (PARAM0),y
0084EF 2 9D DD 92 sta WG_VIEWRECORDS+7,x ; View Width
0084F2 2
0084F2 2 C8 iny
0084F3 2 B1 06 lda (PARAM0),y
0084F5 2 9D DE 92 sta WG_VIEWRECORDS+8,x ; View Height
0084F8 2
0084F8 2 9E DF 92 stz WG_VIEWRECORDS+9,x ; Initialize state
0084FB 2 9E E0 92 stz WG_VIEWRECORDS+10,x ; Initialize callback
0084FE 2 9E E1 92 stz WG_VIEWRECORDS+11,x
008501 2 9E E2 92 stz WG_VIEWRECORDS+12,x ; Initialize title
008504 2 9E E3 92 stz WG_VIEWRECORDS+13,x
008507 2
008507 2 68 pla
008508 2 20 57 87 jsr WGSelectView ; Leave this as the active view
00850B 2
00850B 2 WGCreateView_done:
00850B 2 7A FA 68 RESTORE_AXY
00850E 2 60 rts
00850F 2
00850F 2
00850F 2
00850F 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
00850F 2 ; WGCreateCheckbox
00850F 2 ; Creates a new checkbox
00850F 2 ; PARAM0: Pointer to configuration struct (LSB)
00850F 2 ; PARAM1: Pointer to configuration struct (MSB)
00850F 2 ;
00850F 2 ; Configuration struct:
00850F 2 ; ID: View ID (0-f)
00850F 2 ; XX: Screen X origin
00850F 2 ; YY: Screen Y origin
00850F 2 ; SL: String pointer (LSB)
00850F 2 ; SH: String pointer (MSB)
00850F 2 ;
00850F 2 WGCreateCheckbox:
00850F 2 48 DA 5A SAVE_AXY
008512 2
008512 2 A0 00 ldy #0
008514 2 B1 06 lda (PARAM0),y ; Find our new view record
008516 2 48 pha ; Cache view ID so we can select when we're done
008517 2
008517 2 0A asl
008518 2 0A asl
008519 2 0A asl
00851A 2 0A asl ; Records are 16 bytes wide
00851B 2 AA tax
00851C 2
00851C 2 C8 iny
00851D 2 B1 06 lda (PARAM0),y
00851F 2 9D D6 92 sta WG_VIEWRECORDS+0,x ; Screen X
008522 2
008522 2 C8 iny
008523 2 B1 06 lda (PARAM0),y
008525 2 9D D7 92 sta WG_VIEWRECORDS+1,x ; Screen Y
008528 2
008528 2 A9 01 lda #1
00852A 2 9D D8 92 sta WG_VIEWRECORDS+2,x ; Initialize screen width
00852D 2 9D D9 92 sta WG_VIEWRECORDS+3,x ; Initialize screen height
008530 2 9D DD 92 sta WG_VIEWRECORDS+7,x ; Initialize view width
008533 2 9D DE 92 sta WG_VIEWRECORDS+8,x ; Initialize view height
008536 2
008536 2 A9 02 lda #VIEW_STYLE_CHECK
008538 2 9D DA 92 sta WG_VIEWRECORDS+4,x ; Style
00853B 2
00853B 2 9E DB 92 stz WG_VIEWRECORDS+5,x ; Initialize scrolling
00853E 2 9E DC 92 stz WG_VIEWRECORDS+6,x
008541 2
008541 2 9E DF 92 stz WG_VIEWRECORDS+9,x ; Initialize state
008544 2 9E E0 92 stz WG_VIEWRECORDS+10,x ; Initialize callback
008547 2 9E E1 92 stz WG_VIEWRECORDS+11,x
00854A 2
00854A 2 C8 iny
00854B 2 B1 06 lda (PARAM0),y
00854D 2 9D E2 92 sta WG_VIEWRECORDS+12,x ; Title
008550 2 C8 iny
008551 2 B1 06 lda (PARAM0),y
008553 2 9D E3 92 sta WG_VIEWRECORDS+13,x
008556 2
008556 2 68 pla
008557 2 20 57 87 jsr WGSelectView ; Leave this as the active view
00855A 2
00855A 2 WGCreateCheckbox_done:
00855A 2 7A FA 68 RESTORE_AXY
00855D 2 60 rts
00855E 2
00855E 2
00855E 2
00855E 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
00855E 2 ; WGCreateButton
00855E 2 ; Creates a new button
00855E 2 ; PARAM0: Pointer to configuration struct (LSB)
00855E 2 ; PARAM1: Pointer to configuration struct (MSB)
00855E 2 ;
00855E 2 ; Configuration struct:
00855E 2 ; ID: View ID (0-f)
00855E 2 ; XX: Screen X origin
00855E 2 ; YY: Screen Y origin
00855E 2 ; BW: Button width
00855E 2 ; PL: Action callback (LSB)
00855E 2 ; PH: Action callback (MSB)
00855E 2 ; SL: Title string pointer (LSB)
00855E 2 ; SH: Title string pointer (MSB)
00855E 2 WGCreateButton:
00855E 2 48 DA 5A SAVE_AXY
008561 2
008561 2 A0 00 ldy #0
008563 2 B1 06 lda (PARAM0),y ; Find our new view record
008565 2 48 pha ; Cache view ID so we can select when we're done
008566 2
008566 2 0A asl
008567 2 0A asl
008568 2 0A asl
008569 2 0A asl ; Records are 16 bytes wide
00856A 2 AA tax
00856B 2
00856B 2 C8 iny
00856C 2 B1 06 lda (PARAM0),y
00856E 2 9D D6 92 sta WG_VIEWRECORDS+0,x ; Screen X
008571 2
008571 2 C8 iny
008572 2 B1 06 lda (PARAM0),y
008574 2 9D D7 92 sta WG_VIEWRECORDS+1,x ; Screen Y
008577 2
008577 2 C8 iny
008578 2 B1 06 lda (PARAM0),y
00857A 2 9D D8 92 sta WG_VIEWRECORDS+2,x ; Screen width
00857D 2 9D DD 92 sta WG_VIEWRECORDS+7,x ; View width
008580 2
008580 2 A9 01 lda #1
008582 2 9D D9 92 sta WG_VIEWRECORDS+3,x ; Initialize screen height
008585 2 9D DE 92 sta WG_VIEWRECORDS+8,x ; Initialize view height
008588 2
008588 2 A9 03 lda #VIEW_STYLE_BUTTON
00858A 2 9D DA 92 sta WG_VIEWRECORDS+4,x ; Style
00858D 2
00858D 2 9E DB 92 stz WG_VIEWRECORDS+5,x ; Initialize scrolling
008590 2 9E DC 92 stz WG_VIEWRECORDS+6,x
008593 2 9E DF 92 stz WG_VIEWRECORDS+9,x ; Initialize state
008596 2
008596 2 C8 iny
008597 2 B1 06 lda (PARAM0),y
008599 2 9D E0 92 sta WG_VIEWRECORDS+10,x ; Callback
00859C 2 C8 iny
00859D 2 B1 06 lda (PARAM0),y
00859F 2 9D E1 92 sta WG_VIEWRECORDS+11,x
0085A2 2
0085A2 2 C8 iny
0085A3 2 B1 06 lda (PARAM0),y
0085A5 2 9D E2 92 sta WG_VIEWRECORDS+12,x ; Title
0085A8 2 C8 iny
0085A9 2 B1 06 lda (PARAM0),y
0085AB 2 9D E3 92 sta WG_VIEWRECORDS+13,x
0085AE 2
0085AE 2 68 pla
0085AF 2 20 57 87 jsr WGSelectView ; Leave this as the active view
0085B2 2
0085B2 2 WGCreateButton_done:
0085B2 2 7A FA 68 RESTORE_AXY
0085B5 2 60 rts
0085B6 2
0085B6 2
0085B6 2
0085B6 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0085B6 2 ; WGPaintView
0085B6 2 ; Paints the current view
0085B6 2 ;
0085B6 2 WGPaintView:
0085B6 2 48 DA 5A SAVE_AXY
0085B9 2 A5 06 48 A5 SAVE_ZPP
0085BD 2 07 48 A5 08
0085C1 2 48 A5 09 48
0085C5 2
0085C5 2 AD CD 92 0A LDY_ACTIVEVIEW
0085C9 2 0A 0A 0A A8
0085CD 2
0085CD 2 B9 DA 92 lda WG_VIEWRECORDS+4,y ; Cache style information
0085D0 2 29 0F and #$f ; Mask off flag bits
0085D2 2 48 pha
0085D3 2
0085D3 2 B9 D6 92 lda WG_VIEWRECORDS+0,y ; Fetch the geometry
0085D6 2 85 06 sta PARAM0
0085D8 2 B9 D7 92 lda WG_VIEWRECORDS+1,y
0085DB 2 85 07 sta PARAM1
0085DD 2 B9 D8 92 lda WG_VIEWRECORDS+2,y
0085E0 2 85 08 sta PARAM2
0085E2 2 B9 D9 92 lda WG_VIEWRECORDS+3,y
0085E5 2 85 09 sta PARAM3
0085E7 2
0085E7 2 68 pla ; Draw outline
0085E8 2 C9 01 cmp #VIEW_STYLE_FANCY
0085EA 2 F0 0D beq WGPaintView_decorated
0085EC 2
0085EC 2 20 24 81 jsr WGStrokeRect
0085EF 2
0085EF 2 C9 02 cmp #VIEW_STYLE_CHECK
0085F1 2 F0 0E beq WGPaintView_check
0085F3 2 C9 03 cmp #VIEW_STYLE_BUTTON
0085F5 2 F0 0F beq WGPaintView_button
0085F7 2 80 10 bra WGPaintView_done
0085F9 2
0085F9 2 WGPaintView_decorated:
0085F9 2 20 15 83 jsr WGFancyRect
0085FC 2 20 DC 86 jsr paintWindowTitle
0085FF 2 80 08 bra WGPaintView_done
008601 2
008601 2 WGPaintView_check:
008601 2 20 19 86 jsr paintCheck
008604 2 80 03 bra WGPaintView_done
008606 2
008606 2 WGPaintView_button:
008606 2 20 71 86 jsr paintButton
008609 2
008609 2 WGPaintView_done:
008609 2 68 85 09 68 RESTORE_ZPP
00860D 2 85 08 68 85
008611 2 07 68 85 06
008615 2 7A FA 68 RESTORE_AXY
008618 2 60 rts
008619 2
008619 2
008619 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008619 2 ; paintCheck
008619 2 ; Paints the contents of a checkbox
008619 2 ; Y: Index into view records of checkbox to paint
008619 2 ; Side effects: Clobbers all registers,P0,P1
008619 2 paintCheck:
008619 2 B9 D6 92 lda WG_VIEWRECORDS+0,y ; Position cursor
00861C 2 8D C9 92 sta WG_CURSORX
00861F 2 B9 D7 92 lda WG_VIEWRECORDS+1,y
008622 2 8D CA 92 sta WG_CURSORY
008625 2
008625 2 B9 DF 92 lda WG_VIEWRECORDS+9,y ; Determine our visual state
008628 2 29 80 and #$80
00862A 2 D0 0F bne paintCheck_selected
00862C 2
00862C 2 B9 DF 92 lda WG_VIEWRECORDS+9,y
00862F 2 29 01 and #$01
008631 2 F0 04 beq paintCheck_unselectedUnchecked
008633 2
008633 2 A9 44 lda #'D'
008635 2 80 11 bra paintCheck_plot
008637 2
008637 2 paintCheck_unselectedUnchecked:
008637 2 A9 A0 lda #' '+$80
008639 2 80 0D bra paintCheck_plot
00863B 2
00863B 2 paintCheck_selected:
00863B 2 B9 DF 92 lda WG_VIEWRECORDS+9,y
00863E 2 29 01 and #$01
008640 2 F0 04 beq paintCheck_selectedUnchecked
008642 2
008642 2 A9 45 lda #'E'
008644 2 80 02 bra paintCheck_plot
008646 2
008646 2 paintCheck_selectedUnchecked:
008646 2 A9 20 lda #' '
008648 2
008648 2 paintCheck_plot: ; Paint our state
008648 2 20 55 7F jsr WGPlot
00864B 2
00864B 2 EE C9 92 inc WG_CURSORX ; Prepare for title
00864E 2 EE C9 92 inc WG_CURSORX
008651 2 A9 FF lda #CHAR_NORMAL
008653 2 85 32 sta INVERSE
008655 2
008655 2 B9 E2 92 lda WG_VIEWRECORDS+12,y
008658 2 85 06 sta PARAM0
00865A 2 B9 E3 92 lda WG_VIEWRECORDS+13,y
00865D 2 85 07 sta PARAM1
00865F 2 A0 00 ldy #0
008661 2
008661 2 paintCheck_titleLoop:
008661 2 B1 06 lda (PARAM0),y
008663 2 F0 0B beq paintCheck_done
008665 2 09 80 ora #$80
008667 2 20 55 7F jsr WGPlot
00866A 2 EE C9 92 inc WG_CURSORX
00866D 2 C8 iny
00866E 2 80 F1 bra paintCheck_titleLoop
008670 2
008670 2 paintCheck_done:
008670 2 60 rts
008671 2
008671 2
008671 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008671 2 ; paintButton
008671 2 ; Paints the contents of a button
008671 2 ; Y: Index into view records of button to paint
008671 2 ; Side effects: Clobbers all registers,P0,P1,S1
008671 2 paintButton:
008671 2 B9 E2 92 lda WG_VIEWRECORDS+12,y ; Prep the title string
008674 2 85 06 sta PARAM0
008676 2 B9 E3 92 lda WG_VIEWRECORDS+13,y
008679 2 85 07 sta PARAM1
00867B 2
00867B 2 20 AC 7E jsr WGStrLen ; Compute centering offset for title
00867E 2 4A lsr
00867F 2 85 1A sta SCRATCH1
008681 2 B9 D8 92 lda WG_VIEWRECORDS+2,y
008684 2 4A lsr
008685 2 38 sec
008686 2 E5 1A sbc SCRATCH1
008688 2 85 1A sta SCRATCH1 ; Cache this for left margin rendering
00868A 2
00868A 2 A9 00 lda #0 ; Position and print title
00868C 2 8D CB 92 sta WG_LOCALCURSORX
00868F 2 A9 00 lda #0
008691 2 8D CC 92 sta WG_LOCALCURSORY
008694 2 20 69 89 jsr WGSyncGlobalCursor
008697 2
008697 2 B9 DF 92 lda WG_VIEWRECORDS+9,y ; Is button highlighted?
00869A 2 29 80 and #$80
00869C 2 D0 08 bne paintButton_titleSelected
00869E 2 A9 FF lda #CHAR_NORMAL
0086A0 2 85 32 sta INVERSE
0086A2 2 A9 A0 lda #' '+$80
0086A4 2 80 06 bra paintButton_titleMarginLeft
0086A6 2
0086A6 2 paintButton_titleSelected:
0086A6 2 A9 3F lda #CHAR_INVERSE
0086A8 2 85 32 sta INVERSE
0086AA 2 A9 20 lda #' '
0086AC 2
0086AC 2 paintButton_titleMarginLeft:
0086AC 2 A2 00 ldx #0
0086AE 2
0086AE 2 paintButton_titleMarginLeftLoop:
0086AE 2 E4 1A cpx SCRATCH1
0086B0 2 B0 0D bcs paintButton_title ; Left margin finished
0086B2 2 20 55 7F jsr WGPlot
0086B5 2 EE C9 92 inc WG_CURSORX
0086B8 2 EE CB 92 inc WG_LOCALCURSORX
0086BB 2 E8 inx
0086BC 2 4C AE 86 jmp paintButton_titleMarginLeftLoop
0086BF 2
0086BF 2 paintButton_title:
0086BF 2 20 90 7F jsr WGPrint
0086C2 2 BE D8 92 ldx WG_VIEWRECORDS+2,y
0086C5 2 86 1A stx SCRATCH1 ; Loop until right edge of button is reached
0086C7 2 AE CB 92 ldx WG_LOCALCURSORX
0086CA 2
0086CA 2 paintButton_titleMarginRightLoop:
0086CA 2 E4 1A cpx SCRATCH1
0086CC 2 B0 0D bcs paintButton_done ; Right margin finished
0086CE 2 20 55 7F jsr WGPlot
0086D1 2 EE C9 92 inc WG_CURSORX
0086D4 2 EE CB 92 inc WG_LOCALCURSORX
0086D7 2 E8 inx
0086D8 2 4C CA 86 jmp paintButton_titleMarginRightLoop
0086DB 2
0086DB 2 paintButton_done:
0086DB 2 60 rts
0086DC 2
0086DC 2
0086DC 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0086DC 2 ; paintWindowTitle
0086DC 2 ; Paints the title of a fancy window
0086DC 2 ; Y: Index into view records of view title to paint
0086DC 2 ; Side effects: Clobbers all registers,P0,P1,S1
0086DC 2 paintWindowTitle:
0086DC 2 B9 E2 92 lda WG_VIEWRECORDS+12,y ; Prep the title string
0086DF 2 85 06 sta PARAM0
0086E1 2 B9 E3 92 lda WG_VIEWRECORDS+13,y
0086E4 2 85 07 sta PARAM1
0086E6 2 D0 04 bne paintWindowTitle_compute
0086E8 2
0086E8 2 paintWindowTitle_checkNull:
0086E8 2 A5 06 lda PARAM0
0086EA 2 F0 29 beq paintWindowTitle_done
0086EC 2
0086EC 2 paintWindowTitle_compute:
0086EC 2 20 AC 7E jsr WGStrLen ; Compute centering offset for title
0086EF 2 4A lsr
0086F0 2 85 1A sta SCRATCH1
0086F2 2 B9 D8 92 lda WG_VIEWRECORDS+2,y
0086F5 2 4A lsr
0086F6 2 38 sec
0086F7 2 E5 1A sbc SCRATCH1
0086F9 2 8D CB 92 sta WG_LOCALCURSORX ; Position cursor
0086FC 2 A9 FF lda #-1
0086FE 2 8D CC 92 sta WG_LOCALCURSORY
008701 2 20 69 89 jsr WGSyncGlobalCursor
008704 2
008704 2 A0 00 ldy #0
008706 2 paintWindowTitleLoop:
008706 2 B1 06 lda (PARAM0),y
008708 2 F0 0B beq paintWindowTitle_done
00870A 2 09 80 ora #%10000000
00870C 2 20 55 7F jsr WGPlot ; Draw the character
00870F 2 C8 iny
008710 2 EE C9 92 inc WG_CURSORX ; Advance cursors
008713 2 80 F1 bra paintWindowTitleLoop
008715 2
008715 2 paintWindowTitle_done:
008715 2 60 rts
008716 2
008716 2
008716 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008716 2 ; WGEraseViewContents
008716 2 ; Erases the contents of the current view (interior contents only)
008716 2 ;
008716 2 WGEraseViewContents:
008716 2 48 5A SAVE_AY
008718 2 A5 06 48 A5 SAVE_ZPP
00871C 2 07 48 A5 08
008720 2 48 A5 09 48
008724 2
008724 2 AD CD 92 0A LDY_ACTIVEVIEW
008728 2 0A 0A 0A A8
00872C 2
00872C 2 B9 D6 92 lda WG_VIEWRECORDS,y ; Fetch the record
00872F 2 85 06 sta PARAM0
008731 2 C8 iny
008732 2 B9 D6 92 lda WG_VIEWRECORDS,y
008735 2 85 07 sta PARAM1
008737 2 C8 iny
008738 2 B9 D6 92 lda WG_VIEWRECORDS,y
00873B 2 85 08 sta PARAM2
00873D 2 C8 iny
00873E 2 B9 D6 92 lda WG_VIEWRECORDS,y
008741 2 85 09 sta PARAM3
008743 2
008743 2 A0 A0 ldy #' '+$80
008745 2 20 98 80 jsr WGFillRect
008748 2
008748 2 WGEraseViewContents_done:
008748 2 68 85 09 68 RESTORE_ZPP
00874C 2 85 08 68 85
008750 2 07 68 85 06
008754 2 7A 68 RESTORE_AY
008756 2 60 rts
008757 2
008757 2
008757 2
008757 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008757 2 ; WGSelectView
008757 2 ; Selects the active view
008757 2 ; A: ID
008757 2 ;
008757 2 WGSelectView:
008757 2 8D CD 92 sta WG_ACTIVEVIEW
00875A 2
00875A 2 ; Initialize cursor to local origin
00875A 2 9C CB 92 stz WG_LOCALCURSORX
00875D 2 9C CC 92 stz WG_LOCALCURSORY
008760 2
008760 2 20 2B 8B jsr cacheClipPlanes ; View changed, so clipping cache is stale
008763 2
008763 2 WGSelectView_done:
008763 2 60 rts
008764 2
008764 2
008764 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008764 2 ; WGViewFocus
008764 2 ; Shifts focus to the selected view
008764 2 ; Side effects: Changes selected view, repaints some views
008764 2 ;
008764 2 WGViewFocus:
008764 2 48 5A SAVE_AY
008766 2
008766 2 AD CD 92 lda WG_ACTIVEVIEW ; Stash current selection
008769 2 48 pha
00876A 2
00876A 2 20 EB 87 jsr unfocusCurrent
00876D 2
00876D 2 68 pla
00876E 2 8D CE 92 sta WG_FOCUSVIEW ; Focus on our current selection
008771 2 20 0A 88 jsr focusCurrent
008774 2
008774 2 7A 68 RESTORE_AY
008776 2 60 rts
008777 2
008777 2
008777 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008777 2 ; WGViewUnfocus
008777 2 ; Unfocuses all views
008777 2 ; Side effects: Changes selected view, repaints some views
008777 2 ;
008777 2 WGViewUnfocus:
008777 2 48 pha
008778 2
008778 2 20 EB 87 jsr unfocusCurrent
00877B 2
00877B 2 A9 FF lda #$ff
00877D 2 8D CE 92 sta WG_FOCUSVIEW
008780 2
008780 2 WGViewUnfocus_done:
008780 2 68 pla
008781 2 60 rts
008782 2
008782 2
008782 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008782 2 ; WGViewFocusNext
008782 2 ; Shifts focus to the next view
008782 2 ; Side effects: Changes selected view, repaints some views
008782 2 ;
008782 2 WGViewFocusNext:
008782 2 48 5A SAVE_AY
008784 2
008784 2 20 EB 87 jsr unfocusCurrent
008787 2
008787 2 WGViewFocusNext_loop:
008787 2 EE CE 92 inc WG_FOCUSVIEW ; Increment and wrap
00878A 2 AD CE 92 0A LDY_FOCUSVIEW
00878E 2 0A 0A 0A A8
008792 2 B9 D8 92 lda WG_VIEWRECORDS+2,y
008795 2 D0 05 bne WGViewFocusNext_wantFocus
008797 2 A9 00 lda #0
008799 2 8D CE 92 sta WG_FOCUSVIEW
00879C 2
00879C 2 WGViewFocusNext_wantFocus: ; Does this view accept focus?
00879C 2 AD CE 92 0A LDY_FOCUSVIEW
0087A0 2 0A 0A 0A A8
0087A4 2 B9 DA 92 lda WG_VIEWRECORDS+4,y
0087A7 2 29 0F and #$f ; Mask off flag bits
0087A9 2 C9 02 cmp #VIEW_STYLE_TAKESFOCUS
0087AB 2 90 DA bcc WGViewFocusNext_loop
0087AD 2
0087AD 2 WGViewFocusNext_focus:
0087AD 2 20 0A 88 jsr focusCurrent
0087B0 2
0087B0 2 7A 68 RESTORE_AY
0087B2 2 60 rts
0087B3 2
0087B3 2
0087B3 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0087B3 2 ; WGViewFocusPrev
0087B3 2 ; Shifts focus to the prev view
0087B3 2 ; Side effects: Changes selected view, repaints some views
0087B3 2 ;
0087B3 2 WGViewFocusPrev:
0087B3 2 48 DA 5A SAVE_AXY
0087B6 2
0087B6 2 20 EB 87 jsr unfocusCurrent
0087B9 2
0087B9 2 WGViewFocusPrev_loop:
0087B9 2 CE CE 92 dec WG_FOCUSVIEW ; Decrement and wrap
0087BC 2 10 15 bpl WGViewFocusPrev_wantFocus
0087BE 2
0087BE 2 WGViewFocusPrev_hadNone:
0087BE 2 A2 0F ldx #$f
0087C0 2 WGViewFocusPrev_findEndLoop:
0087C0 2 8E CE 92 stx WG_FOCUSVIEW
0087C3 2 AD CE 92 0A LDY_FOCUSVIEW
0087C7 2 0A 0A 0A A8
0087CB 2 B9 D8 92 lda WG_VIEWRECORDS+2,y
0087CE 2 D0 03 bne WGViewFocusPrev_wantFocus
0087D0 2 CA dex
0087D1 2 80 ED bra WGViewFocusPrev_findEndLoop
0087D3 2
0087D3 2 WGViewFocusPrev_wantFocus: ; Does this view accept focus?
0087D3 2 AD CE 92 0A LDY_FOCUSVIEW
0087D7 2 0A 0A 0A A8
0087DB 2 B9 DA 92 lda WG_VIEWRECORDS+4,y
0087DE 2 29 0F and #$f ; Mask off flag bits
0087E0 2 C9 02 cmp #VIEW_STYLE_TAKESFOCUS
0087E2 2 90 D5 bcc WGViewFocusPrev_loop
0087E4 2
0087E4 2 WGViewFocusPrev_focus:
0087E4 2 20 0A 88 jsr focusCurrent
0087E7 2
0087E7 2 7A FA 68 RESTORE_AXY
0087EA 2 60 rts
0087EB 2
0087EB 2
0087EB 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0087EB 2 ; unfocusCurrent
0087EB 2 ; Unfocuses current view, if any
0087EB 2 ; Side effects: Clobbers A,
0087EB 2 ; Leaves Y pointed at current focus view record
0087EB 2 ; Changes active view selection
0087EB 2 unfocusCurrent:
0087EB 2 AD CE 92 lda WG_FOCUSVIEW
0087EE 2 30 19 bmi unfocusCurrentDone ; No current focus
0087F0 2
0087F0 2 AD CE 92 0A LDY_FOCUSVIEW ; Unfocus current view
0087F4 2 0A 0A 0A A8
0087F8 2 B9 DF 92 lda WG_VIEWRECORDS+9,y
0087FB 2 29 7F and #%01111111
0087FD 2 99 DF 92 sta WG_VIEWRECORDS+9,y
008800 2
008800 2 AD CE 92 lda WG_FOCUSVIEW
008803 2 20 57 87 jsr WGSelectView
008806 2 20 B6 85 jsr WGPaintView
008809 2
008809 2 unfocusCurrentDone:
008809 2 60 rts
00880A 2
00880A 2
00880A 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
00880A 2 ; focusCurrent
00880A 2 ; Sets focus to desired view, and repaints
00880A 2 ; Side effects: Clobbers A
00880A 2 focusCurrent:
00880A 2 AD CE 92 lda WG_FOCUSVIEW
00880D 2 20 57 87 jsr WGSelectView
008810 2
008810 2 AD CD 92 0A LDY_ACTIVEVIEW
008814 2 0A 0A 0A A8
008818 2
008818 2 B9 DA 92 lda WG_VIEWRECORDS+4,y
00881B 2 29 0F and #$f ; Mask off flag bits
00881D 2 C9 02 cmp #VIEW_STYLE_TAKESFOCUS
00881F 2 90 0B bcc focusCurrent_done
008821 2
008821 2 B9 DF 92 lda WG_VIEWRECORDS+9,y
008824 2 09 80 ora #%10000000
008826 2 99 DF 92 sta WG_VIEWRECORDS+9,y
008829 2
008829 2 20 B6 85 jsr WGPaintView
00882C 2
00882C 2 focusCurrent_done:
00882C 2 60 rts
00882D 2
00882D 2
00882D 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
00882D 2 ; WGViewFocusAction
00882D 2 ; Performs the action of the focused view
00882D 2 ; WG_GOSUB : Set if the caller should perform an Applesoft GOSUB
00882D 2 ; Side effects: Changes selected view, Repaints some views
00882D 2 ;
00882D 2 WGViewFocusAction:
00882D 2 48 5A SAVE_AY
00882F 2
00882F 2 AD CE 92 lda WG_FOCUSVIEW
008832 2 30 60 bmi WGViewFocusAction_done
008834 2
008834 2 AD CE 92 0A LDY_FOCUSVIEW
008838 2 0A 0A 0A A8
00883C 2 B9 DA 92 lda WG_VIEWRECORDS+4,y ; What kind of view is it?
00883F 2 29 0F and #$f ; Mask off flag bits
008841 2
008841 2 C9 02 cmp #VIEW_STYLE_CHECK
008843 2 F0 02 beq WGViewFocusAction_toggleCheckbox
008845 2 80 11 bra WGViewFocusAction_buttonClick ; Everything else treated like a button
008847 2
008847 2 WGViewFocusAction_toggleCheckbox:
008847 2 B9 DF 92 lda WG_VIEWRECORDS+9,y ; Change the checkbox's state and redraw
00884A 2 49 01 eor #%00000001
00884C 2 99 DF 92 sta WG_VIEWRECORDS+9,y
00884F 2 AD CE 92 lda WG_FOCUSVIEW
008852 2 20 57 87 jsr WGSelectView
008855 2 20 B6 85 jsr WGPaintView
008858 2 ; Fall through so checkboxes can have callbacks too
008858 2
008858 2 ; NOTE: Self-modifying code ahead!
008858 2 WGViewFocusAction_buttonClick:
008858 2 B9 DA 92 lda WG_VIEWRECORDS+4,y ; Are we an Applesoft button?
00885B 2 29 80 and #VIEW_STYLE_APPLESOFT
00885D 2 D0 13 bne WGViewFocusAction_buttonClickApplesoft
00885F 2
00885F 2 B9 E1 92 lda WG_VIEWRECORDS+11,y ; Do we have a callback?
008862 2 F0 30 beq WGViewFocusAction_done
008864 2 8D 6F 88 sta WGViewFocusAction_userJSR+2 ; Modify code below so we can JSR to user's code
008867 2 B9 E0 92 lda WG_VIEWRECORDS+10,y
00886A 2 8D 6E 88 sta WGViewFocusAction_userJSR+1
00886D 2
00886D 2 WGViewFocusAction_userJSR:
00886D 2 20 94 88 jsr WGViewFocusAction_done ; Overwritten with user's function pointer
008870 2 80 22 bra WGViewFocusAction_done
008872 2
008872 2 WGViewFocusAction_buttonClickApplesoft:
008872 2 A9 00 lda #0
008874 2 8D D0 92 sta WG_GOSUB
008877 2 B9 E0 92 lda WG_VIEWRECORDS+10,y ; Do we have a callback?
00887A 2 F0 0E beq WGViewFocusAction_mightBeZero
00887C 2
00887C 2 WGViewFocusAction_buttonClickApplesoftNotZero:
00887C 2 85 06 sta PARAM0
00887E 2 B9 E1 92 lda WG_VIEWRECORDS+11,y
008881 2 85 07 sta PARAM1
008883 2
008883 2 WGViewFocusAction_buttonClickApplesoftGosub:
008883 2 ; Caller needs to handle Applesoft Gosub, so signal with a flag and return
008883 2 A9 01 lda #1
008885 2 8D D0 92 sta WG_GOSUB
008888 2 80 0A bra WGViewFocusAction_done
00888A 2
00888A 2 WGViewFocusAction_mightBeZero:
00888A 2 B9 E1 92 lda WG_VIEWRECORDS+11,y
00888D 2 F0 05 beq WGViewFocusAction_done
00888F 2 B9 E0 92 lda WG_VIEWRECORDS+10,y
008892 2 80 E8 bra WGViewFocusAction_buttonClickApplesoftNotZero
008894 2
008894 2 WGViewFocusAction_done:
008894 2 7A 68 RESTORE_AY
008896 2 WGViewFocusAction_knownRTS:
008896 2 60 rts
008897 2
008897 2
008897 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008897 2 ; WGPendingViewAction
008897 2 ; Performs the action of the pending view, if any
008897 2 ; Global flag set if the caller should perform an Applesoft GOSUB
008897 2 ; Side effects: Changes selected view, Repaints some views
008897 2 ;
008897 2 WGPendingViewAction:
008897 2 48 5A SAVE_AY
008899 2
008899 2 AD CF 92 lda WG_PENDINGACTIONVIEW
00889C 2 30 3F bmi WGPendingViewAction_done
00889E 2
00889E 2 29 0F and #$f ; Select view in question
0088A0 2 20 57 87 jsr WGSelectView
0088A3 2 AD CD 92 0A LDY_ACTIVEVIEW
0088A7 2 0A 0A 0A A8
0088AB 2
0088AB 2 B9 DA 92 lda WG_VIEWRECORDS+4,y
0088AE 2 29 0F and #$f
0088B0 2 C9 01 cmp #VIEW_STYLE_FANCY ; Filter out fancy views with high-nybble of 0
0088B2 2 D0 07 bne WGPendingViewAction_chkCallback ; This prevents unnecessary redraws when clicking
0088B4 2 AD CF 92 lda WG_PENDINGACTIONVIEW ; in the content area
0088B7 2 29 F0 and #$f0
0088B9 2 F0 22 beq WGPendingViewAction_done
0088BB 2
0088BB 2 WGPendingViewAction_chkCallback:
0088BB 2 ; lda WG_VIEWRECORDS+10,y ; Optimization- only process things that can be clicked
0088BB 2 ; bne WGPendingViewAction_hasCallback
0088BB 2 ; lda WG_VIEWRECORDS+11,y
0088BB 2 ; beq WGPendingViewAction_done
0088BB 2
0088BB 2 WGPendingViewAction_hasCallback:
0088BB 2 AD CF 92 lda WG_PENDINGACTIONVIEW
0088BE 2 29 F0 and #$f0 ; Check for window features
0088C0 2 F0 4A beq WGPendingViewAction_content
0088C2 2
0088C2 2 C9 10 cmp #WG_FEATURE_UP
0088C4 2 F0 1F beq WGPendingViewAction_up
0088C6 2 C9 20 cmp #WG_FEATURE_DN
0088C8 2 F0 28 beq WGPendingViewAction_down
0088CA 2 C9 30 cmp #WG_FEATURE_LF
0088CC 2 F0 31 beq WGPendingViewAction_left
0088CE 2 C9 40 cmp #WG_FEATURE_RT
0088D0 2 D0 0B bne WGPendingViewAction_done
0088D2 2
0088D2 2 A9 FF lda #-1 ; Right arrow
0088D4 2 20 A5 89 jsr WGScrollXBy
0088D7 2 20 64 87 jsr WGViewFocus
0088DA 2 20 2D 88 jsr WGViewFocusAction ; Trigger application to redraw contents
0088DD 2
0088DD 2 WGPendingViewAction_done: ; Centralized for branch range
0088DD 2 A9 FF lda #$ff
0088DF 2 8D CF 92 sta WG_PENDINGACTIONVIEW
0088E2 2
0088E2 2 7A 68 RESTORE_AY
0088E4 2 60 rts
0088E5 2
0088E5 2 WGPendingViewAction_up:
0088E5 2 A9 01 lda #1 ; Up arrow
0088E7 2 20 F9 89 jsr WGScrollYBy
0088EA 2 20 64 87 jsr WGViewFocus
0088ED 2 20 2D 88 jsr WGViewFocusAction ; Trigger application to redraw contents
0088F0 2 80 EB bra WGPendingViewAction_done
0088F2 2
0088F2 2 WGPendingViewAction_down:
0088F2 2 A9 FF lda #-1 ; Down arrow
0088F4 2 20 F9 89 jsr WGScrollYBy
0088F7 2 20 64 87 jsr WGViewFocus
0088FA 2 20 2D 88 jsr WGViewFocusAction ; Trigger application to redraw contents
0088FD 2 80 DE bra WGPendingViewAction_done
0088FF 2
0088FF 2 WGPendingViewAction_left:
0088FF 2 A9 01 lda #1 ; Left arrow
008901 2 20 A5 89 jsr WGScrollXBy
008904 2 20 64 87 jsr WGViewFocus
008907 2 20 2D 88 jsr WGViewFocusAction ; Trigger application to redraw contents
00890A 2 80 D1 bra WGPendingViewAction_done
00890C 2
00890C 2 WGPendingViewAction_content:
00890C 2 20 64 87 jsr WGViewFocus
00890F 2 20 2D 88 jsr WGViewFocusAction
008912 2 20 94 7E jsr delayShort
008915 2 20 77 87 jsr WGViewUnfocus
008918 2
008918 2 20 14 8D jsr WGPointerDirty ; If we redrew anything, the pointer BG will be stale
00891B 2 80 C0 bra WGPendingViewAction_done
00891D 2
00891D 2
00891D 2
00891D 2
00891D 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
00891D 2 ; WGPendingView
00891D 2 ; Returns the view that is currently pending
00891D 2 ; OUT A : Pending view ID, or $ff if none
00891D 2 ;
00891D 2 WGPendingView:
00891D 2 AD CF 92 lda WG_PENDINGACTIONVIEW
008920 2 60 rts
008921 2
008921 2
008921 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008921 2 ; WGViewSetTitle
008921 2 ; Sets the title of the active view
008921 2 ; PARAM0: Null-terminated string pointer (LSB)
008921 2 ; PARAM1: Null-terminated string pointer (MSB)
008921 2 WGViewSetTitle:
008921 2 48 5A SAVE_AY
008923 2
008923 2 AD CD 92 0A LDY_ACTIVEVIEW
008927 2 0A 0A 0A A8
00892B 2 A5 06 lda PARAM0
00892D 2 99 E2 92 sta WG_VIEWRECORDS+12,y
008930 2 A5 07 lda PARAM1
008932 2 99 E3 92 sta WG_VIEWRECORDS+13,y
008935 2
008935 2 WGViewSetTitle_done:
008935 2 7A 68 RESTORE_AY
008937 2 60 rts
008938 2
008938 2
008938 2
008938 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008938 2 ; WGViewSetAction
008938 2 ; Sets the callback action of the active view
008938 2 ; PARAM0: Null-terminated function pointer (LSB)
008938 2 ; PARAM1: Null-terminated function pointer (MSB)
008938 2 WGViewSetAction:
008938 2 48 5A SAVE_AY
00893A 2
00893A 2 AD CD 92 0A LDY_ACTIVEVIEW
00893E 2 0A 0A 0A A8
008942 2 A5 06 lda PARAM0
008944 2 99 E0 92 sta WG_VIEWRECORDS+10,y
008947 2 A5 07 lda PARAM1
008949 2 99 E1 92 sta WG_VIEWRECORDS+11,y
00894C 2
00894C 2 WGViewSetAction_done:
00894C 2 7A 68 RESTORE_AY
00894E 2 60 rts
00894F 2
00894F 2
00894F 2
00894F 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
00894F 2 ; WGSetCursor
00894F 2 ; Sets the current local view cursor
00894F 2 ; PARAM0: X
00894F 2 ; PARAM1: Y
00894F 2 ;
00894F 2 WGSetCursor:
00894F 2 48 pha
008950 2
008950 2 A5 06 lda PARAM0
008952 2 8D CB 92 sta WG_LOCALCURSORX
008955 2 A5 07 lda PARAM1
008957 2 8D CC 92 sta WG_LOCALCURSORY
00895A 2
00895A 2 68 pla
00895B 2 60 rts
00895C 2
00895C 2
00895C 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
00895C 2 ; WGSetGlobalCursor
00895C 2 ; Sets the current global cursor
00895C 2 ; PARAM0: X
00895C 2 ; PARAM1: Y
00895C 2 ;
00895C 2 WGSetGlobalCursor:
00895C 2 48 pha
00895D 2
00895D 2 A5 06 lda PARAM0
00895F 2 8D C9 92 sta WG_CURSORX
008962 2 A5 07 lda PARAM1
008964 2 8D CA 92 sta WG_CURSORY
008967 2
008967 2 68 pla
008968 2 60 rts
008969 2
008969 2
008969 2
008969 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008969 2 ; WGSyncGlobalCursor
008969 2 ; Synchronizes the global cursor with the current local view's
008969 2 ; cursor
008969 2 ;
008969 2 WGSyncGlobalCursor:
008969 2 48 5A SAVE_AY
00896B 2
00896B 2 AD CD 92 0A LDY_ACTIVEVIEW
00896F 2 0A 0A 0A A8
008973 2
008973 2 ; Sync X
008973 2 18 clc ; Transform to viewspace
008974 2 AD CB 92 lda WG_LOCALCURSORX
008977 2 79 D6 92 adc WG_VIEWRECORDS+0,y
00897A 2
00897A 2 18 clc
00897B 2 79 DB 92 adc WG_VIEWRECORDS+5,y ; Transform to scrollspace
00897E 2 8D C9 92 sta WG_CURSORX
008981 2
008981 2 ; Sync Y
008981 2 18 clc ; Transform to viewspace
008982 2 AD CC 92 lda WG_LOCALCURSORY
008985 2 79 D7 92 adc WG_VIEWRECORDS+1,y
008988 2
008988 2 18 clc
008989 2 79 DC 92 adc WG_VIEWRECORDS+6,y ; Transform to scrollspace
00898C 2 8D CA 92 sta WG_CURSORY
00898F 2
00898F 2 WGSyncGlobalCursor_done:
00898F 2 7A 68 RESTORE_AY
008991 2 60 rts
008992 2
008992 2
008992 2
008992 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008992 2 ; WGScrollX
008992 2 ; Scrolls the current view horizontally
008992 2 ; A: New scroll amount
008992 2 ; Side effects: Clobbers A
008992 2 ;
008992 2 WGScrollX:
008992 2 5A phy
008993 2 48 pha
008994 2
008994 2 AD CD 92 0A LDY_ACTIVEVIEW
008998 2 0A 0A 0A A8
00899C 2 68 pla
00899D 2 99 DB 92 sta WG_VIEWRECORDS+5,y
0089A0 2 20 2B 8B jsr cacheClipPlanes ; Scroll offset changed, so clipping cache is stale
0089A3 2
0089A3 2 WGScrollX_done:
0089A3 2 7A ply
0089A4 2 60 rts
0089A5 2
0089A5 2
0089A5 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0089A5 2 ; WGScrollXBy
0089A5 2 ; Scrolls the current view horizontally by a delta
0089A5 2 ; A: Scroll delta
0089A5 2 ; Side effects: Clobbers A,S0
0089A5 2 ;
0089A5 2 WGScrollXBy:
0089A5 2 DA 5A SAVE_XY
0089A7 2 AA tax
0089A8 2
0089A8 2 AD CD 92 0A LDY_ACTIVEVIEW
0089AC 2 0A 0A 0A A8
0089B0 2
0089B0 2 8A txa
0089B1 2 10 1E bpl WGScrollXBy_contentRight
0089B3 2
0089B3 2 B9 D8 92 lda WG_VIEWRECORDS+2,y ; Compute left limit
0089B6 2 38 sec
0089B7 2 F9 DD 92 sbc WG_VIEWRECORDS+7,y
0089BA 2 85 19 sta SCRATCH0
0089BC 2
0089BC 2 8A txa ; Compute new scroll value
0089BD 2 18 clc
0089BE 2 79 DB 92 adc WG_VIEWRECORDS+5,y
0089C1 2 C5 19 cmp SCRATCH0 ; Clamp if needed
0089C3 2 30 05 bmi WGScrollXBy_clampLeft
0089C5 2 99 DB 92 sta WG_VIEWRECORDS+5,y
0089C8 2 80 19 bra WGScrollXBy_done
0089CA 2
0089CA 2 WGScrollXBy_clampLeft:
0089CA 2 A5 19 lda SCRATCH0
0089CC 2 99 DB 92 sta WG_VIEWRECORDS+5,y
0089CF 2 80 12 bra WGScrollXBy_done
0089D1 2
0089D1 2 WGScrollXBy_contentRight:
0089D1 2 18 clc ; Compute new scroll value
0089D2 2 79 DB 92 adc WG_VIEWRECORDS+5,y
0089D5 2 F0 02 beq @0 ; Clamp if needed
0089D7 2 10 05 bpl WGScrollXBy_clampRight
0089D9 2 99 DB 92 @0: sta WG_VIEWRECORDS+5,y
0089DC 2 80 05 bra WGScrollXBy_done
0089DE 2
0089DE 2 WGScrollXBy_clampRight:
0089DE 2 A9 00 lda #0
0089E0 2 99 DB 92 sta WG_VIEWRECORDS+5,y
0089E3 2
0089E3 2 WGScrollXBy_done:
0089E3 2 7A FA RESTORE_XY
0089E5 2 60 rts
0089E6 2
0089E6 2
0089E6 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0089E6 2 ; WGScrollY
0089E6 2 ; Scrolls the current view vertically
0089E6 2 ; A: New scroll amount
0089E6 2 ; Side effects: Clobbers A
0089E6 2 ;
0089E6 2 WGScrollY:
0089E6 2 5A phy
0089E7 2 48 pha
0089E8 2
0089E8 2 AD CD 92 0A LDY_ACTIVEVIEW
0089EC 2 0A 0A 0A A8
0089F0 2 68 pla
0089F1 2 99 DC 92 sta WG_VIEWRECORDS+6,y
0089F4 2 20 2B 8B jsr cacheClipPlanes ; Scroll offset changed, so clipping cache is stale
0089F7 2
0089F7 2 WGScrollY_done:
0089F7 2 7A ply
0089F8 2 60 rts
0089F9 2
0089F9 2
0089F9 2
0089F9 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0089F9 2 ; WGScrollYBy
0089F9 2 ; Scrolls the current view horizontally by a delta
0089F9 2 ; A: Scroll delta
0089F9 2 ; Side effects: Clobbers A,S0
0089F9 2 ;
0089F9 2 WGScrollYBy:
0089F9 2 DA 5A SAVE_XY
0089FB 2 AA tax
0089FC 2
0089FC 2 AD CD 92 0A LDY_ACTIVEVIEW
008A00 2 0A 0A 0A A8
008A04 2
008A04 2 8A txa
008A05 2 10 1E bpl WGScrollYBy_contentDown
008A07 2
008A07 2 B9 D9 92 lda WG_VIEWRECORDS+3,y ; Compute bottom limit
008A0A 2 38 sec
008A0B 2 F9 DE 92 sbc WG_VIEWRECORDS+8,y
008A0E 2 85 19 sta SCRATCH0
008A10 2
008A10 2 8A txa ; Compute new scroll value
008A11 2 18 clc
008A12 2 79 DC 92 adc WG_VIEWRECORDS+6,y
008A15 2 C5 19 cmp SCRATCH0 ; Clamp if needed
008A17 2 30 05 bmi WGScrollYBy_clampTop
008A19 2 99 DC 92 sta WG_VIEWRECORDS+6,y
008A1C 2 80 19 bra WGScrollYBy_done
008A1E 2
008A1E 2 WGScrollYBy_clampTop:
008A1E 2 A5 19 lda SCRATCH0
008A20 2 99 DC 92 sta WG_VIEWRECORDS+6,y
008A23 2 80 12 bra WGScrollYBy_done
008A25 2
008A25 2 WGScrollYBy_contentDown:
008A25 2 18 clc ; Compute new scroll value
008A26 2 79 DC 92 adc WG_VIEWRECORDS+6,y
008A29 2 F0 02 beq @0 ; Clamp if needed
008A2B 2 10 05 bpl WGScrollYBy_clampBottom
008A2D 2 99 DC 92 @0: sta WG_VIEWRECORDS+6,y
008A30 2 80 05 bra WGScrollYBy_done
008A32 2
008A32 2 WGScrollYBy_clampBottom:
008A32 2 A9 00 lda #0
008A34 2 99 DC 92 sta WG_VIEWRECORDS+6,y
008A37 2
008A37 2 WGScrollYBy_done:
008A37 2 7A FA RESTORE_XY
008A39 2 60 rts
008A3A 2
008A3A 2
008A3A 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008A3A 2 ; WGViewPaintAll
008A3A 2 ; Repaints all views
008A3A 2 ; Side effects: Changes selected view
008A3A 2 ;
008A3A 2 WGViewPaintAll:
008A3A 2 48 DA 5A SAVE_AXY
008A3D 2
008A3D 2 A2 00 ldx #0
008A3F 2
008A3F 2 WGViewPaintAll_loop:
008A3F 2 8A txa
008A40 2 20 57 87 jsr WGSelectView
008A43 2
008A43 2 AD CD 92 0A LDY_ACTIVEVIEW
008A47 2 0A 0A 0A A8
008A4B 2 B9 D8 92 lda WG_VIEWRECORDS+2,y ; Last view?
008A4E 2 F0 09 beq WGViewPaintAll_done
008A50 2
008A50 2 20 16 87 jsr WGEraseViewContents
008A53 2 20 B6 85 jsr WGPaintView
008A56 2 E8 inx
008A57 2 80 E6 bra WGViewPaintAll_loop
008A59 2
008A59 2 WGViewPaintAll_done:
008A59 2 7A FA 68 RESTORE_AXY
008A5C 2 60 rts
008A5D 2
008A5D 2
008A5D 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008A5D 2 ; WGViewFromPoint
008A5D 2 ; Finds a view containing the given point
008A5D 2 ; PARAM0:X
008A5D 2 ; PARAM1:Y
008A5D 2 ; OUT A: View ID (or high bit set if no match)
008A5D 2 ; For Fancy Views, Upper nibble returned indicates feature hit:
008A5D 2 ; 0000 : Content region
008A5D 2 ; 0001 : Scroll arrow up
008A5D 2 ; 0010 : Scroll arrow down
008A5D 2 ; 0011 : Scroll arrow left
008A5D 2 ; 0100 : Scroll arrow right
008A5D 2 WGViewFromPoint:
008A5D 2 DA 5A SAVE_XY
008A5F 2 A5 19 48 A5 SAVE_ZPS
008A63 2 1A 48
008A65 2
008A65 2 A2 0F ldx #$f ; Scan views backwards, because controls are usually at the end
008A67 2
008A67 2 WGViewFromPoint_loop:
008A67 2 8A txa
008A68 2 0A 0A 0A 0A LDY_AVIEW
008A6C 2 A8
008A6D 2
008A6D 2 B9 D8 92 lda WG_VIEWRECORDS+2,y
008A70 2 F0 67 beq WGViewFromPoint_loopNext ; Not an allocated view
008A72 2
008A72 2 B9 DA 92 lda WG_VIEWRECORDS+4,y ; Fancy views are handled differently
008A75 2 29 0F and #$f
008A77 2 C9 01 cmp #VIEW_STYLE_FANCY
008A79 2 F0 0C beq WGViewFromPoint_loopFancy
008A7B 2
008A7B 2 B9 D8 92 lda WG_VIEWRECORDS+2,y
008A7E 2 85 19 sta SCRATCH0
008A80 2 B9 D9 92 lda WG_VIEWRECORDS+3,y
008A83 2 85 1A sta SCRATCH1
008A85 2 80 0C bra WGViewFromPoint_loopCheckBounds
008A87 2
008A87 2 WGViewFromPoint_loopFancy:
008A87 2 B9 D8 92 lda WG_VIEWRECORDS+2,y ; Include scrollbars
008A8A 2 1A inc
008A8B 2 85 19 sta SCRATCH0
008A8D 2 B9 D9 92 lda WG_VIEWRECORDS+3,y
008A90 2 1A inc
008A91 2 85 1A sta SCRATCH1
008A93 2
008A93 2 WGViewFromPoint_loopCheckBounds:
008A93 2 A5 06 lda PARAM0 ; Check left edge
008A95 2 D9 D6 92 cmp WG_VIEWRECORDS+0,y
008A98 2 90 3F bcc WGViewFromPoint_loopNext
008A9A 2
008A9A 2 A5 07 lda PARAM1 ; Check top edge
008A9C 2 D9 D7 92 cmp WG_VIEWRECORDS+1,y
008A9F 2 90 38 bcc WGViewFromPoint_loopNext
008AA1 2
008AA1 2 B9 D6 92 lda WG_VIEWRECORDS+0,y ; Check right edge
008AA4 2 18 clc
008AA5 2 65 19 adc SCRATCH0
008AA7 2 C5 06 cmp PARAM0
008AA9 2 90 2E bcc WGViewFromPoint_loopNext
008AAB 2 F0 2C beq WGViewFromPoint_loopNext
008AAD 2
008AAD 2 B9 D7 92 lda WG_VIEWRECORDS+1,y ; Check bottom edge
008AB0 2 18 clc
008AB1 2 65 1A adc SCRATCH1
008AB3 2 C5 07 cmp PARAM1
008AB5 2 90 22 bcc WGViewFromPoint_loopNext
008AB7 2 F0 20 beq WGViewFromPoint_loopNext
008AB9 2
008AB9 2 ; Found a match (in X)
008AB9 2 B9 DA 92 lda WG_VIEWRECORDS+4,y
008ABC 2 29 0F and #$f ; Mask off flag bits
008ABE 2 C9 01 cmp #VIEW_STYLE_FANCY
008AC0 2 D0 54 bne WGViewFromPoint_matchDone
008AC2 2
008AC2 2 ; For fancy views, check scrollbars as well
008AC2 2 B9 D6 92 lda WG_VIEWRECORDS+0,y ; Right scroll bar?
008AC5 2 18 clc
008AC6 2 65 19 adc SCRATCH0
008AC8 2 3A dec
008AC9 2 C5 06 cmp PARAM0
008ACB 2 D0 22 bne WGViewFromPoint_checkBottomScroll
008ACD 2
008ACD 2 A5 07 lda PARAM1 ; Up arrow?
008ACF 2 D9 D7 92 cmp WG_VIEWRECORDS+1,y
008AD2 2 D0 0A bne WGViewFromPoint_checkDownArrow
008AD4 2 8A txa
008AD5 2 09 10 ora #WG_FEATURE_UP
008AD7 2 80 3C bra WGViewFromPoint_matchFancyDone
008AD9 2
008AD9 2 WGViewFromPoint_loopNext: ; Inserted here for branch range
008AD9 2 CA dex
008ADA 2 30 44 bmi WGViewFromPoint_noMatch
008ADC 2 80 89 bra WGViewFromPoint_loop
008ADE 2
008ADE 2 WGViewFromPoint_checkDownArrow:
008ADE 2 B9 D7 92 lda WG_VIEWRECORDS+1,y ; Down arrow?
008AE1 2 18 clc
008AE2 2 65 1A adc SCRATCH1
008AE4 2 3A dec
008AE5 2 3A dec
008AE6 2 C5 07 cmp PARAM1
008AE8 2 D0 2C bne WGViewFromPoint_matchDone
008AEA 2 8A txa
008AEB 2 09 20 ora #WG_FEATURE_DN
008AED 2 80 26 bra WGViewFromPoint_matchFancyDone
008AEF 2
008AEF 2 WGViewFromPoint_checkBottomScroll:
008AEF 2 B9 D7 92 lda WG_VIEWRECORDS+1,y ; Bottom scroll bar?
008AF2 2 18 clc
008AF3 2 65 1A adc SCRATCH1
008AF5 2 3A dec
008AF6 2 C5 07 cmp PARAM1
008AF8 2 D0 1C bne WGViewFromPoint_matchDone
008AFA 2 A5 06 lda PARAM0 ; Left arrow?
008AFC 2 D9 D6 92 cmp WG_VIEWRECORDS+0,y
008AFF 2 D0 05 bne WGViewFromPoint_checkRightArrow
008B01 2 8A txa
008B02 2 09 30 ora #WG_FEATURE_LF
008B04 2 80 0F bra WGViewFromPoint_matchFancyDone
008B06 2
008B06 2 WGViewFromPoint_checkRightArrow:
008B06 2 B9 D6 92 lda WG_VIEWRECORDS+0,y ; Right arrow?
008B09 2 18 clc
008B0A 2 65 19 adc SCRATCH0
008B0C 2 3A dec
008B0D 2 3A dec
008B0E 2 C5 06 cmp PARAM0
008B10 2 D0 04 bne WGViewFromPoint_matchDone
008B12 2 8A txa
008B13 2 09 40 ora #WG_FEATURE_RT
008B15 2
008B15 2 WGViewFromPoint_matchFancyDone:
008B15 2 AA tax
008B16 2
008B16 2 WGViewFromPoint_matchDone:
008B16 2 68 85 1A 68 RESTORE_ZPS
008B1A 2 85 19
008B1C 2 8A txa
008B1D 2 7A FA RESTORE_XY
008B1F 2 60 rts
008B20 2
008B20 2 WGViewFromPoint_noMatch:
008B20 2 68 85 1A 68 RESTORE_ZPS
008B24 2 85 19
008B26 2 A9 FF lda #$ff
008B28 2 7A FA RESTORE_XY
008B2A 2 60 rts
008B2B 2
008B2B 2
008B2B 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008B2B 2 ; cacheClipPlanes
008B2B 2 ; Internal routine to cache the clipping planes for the view
008B2B 2 ;
008B2B 2 cacheClipPlanes:
008B2B 2 48 5A SAVE_AY
008B2D 2
008B2D 2 ; Compute clip planes in view space
008B2D 2 AD CD 92 0A LDY_ACTIVEVIEW
008B31 2 0A 0A 0A A8
008B35 2
008B35 2 B9 DB 92 lda WG_VIEWRECORDS+5,y ; Left edge
008B38 2 49 FF eor #$ff
008B3A 2 1A inc
008B3B 2 8D D1 92 sta WG_VIEWCLIP+0
008B3E 2
008B3E 2 18 clc
008B3F 2 79 D8 92 adc WG_VIEWRECORDS+2,y ; Right edge
008B42 2 8D D3 92 sta WG_VIEWCLIP+2
008B45 2
008B45 2 B9 DD 92 lda WG_VIEWRECORDS+7,y ; Right span (distance from window edge to view edge, in viewspace
008B48 2 38 sec
008B49 2 ED D3 92 sbc WG_VIEWCLIP+2
008B4C 2 8D D5 92 sta WG_VIEWCLIP+4
008B4F 2
008B4F 2 B9 DC 92 lda WG_VIEWRECORDS+6,y ; Top edge
008B52 2 49 FF eor #$ff
008B54 2 1A inc
008B55 2 8D D2 92 sta WG_VIEWCLIP+1
008B58 2
008B58 2 18 clc
008B59 2 79 D9 92 adc WG_VIEWRECORDS+3,y ; Bottom edge
008B5C 2 8D D4 92 sta WG_VIEWCLIP+3
008B5F 2
008B5F 2 7A 68 RESTORE_AY
008B61 2 60 rts
008B62 2
008B62 2
008B62 2
008B62 1 .include "mouse.s"
008B62 2 ;
008B62 2 ; mouse.s
008B62 2 ; Routines for handling the mouse
008B62 2 ;
008B62 2 ; Created by Quinn Dunki on 8/15/14.
008B62 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved.
008B62 2 ;
008B62 2
008B62 2
008B62 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008B62 2 ; ProDOS ROM entry points and constants
008B62 2 ;
008B62 2 PRODOS_MLI = $bf00
008B62 2
008B62 2 ALLOC_INTERRUPT = $40
008B62 2 DEALLOC_INTERRUPT = $41
008B62 2
008B62 2
008B62 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008B62 2 ; Mouse firmware ROM entry points and constants
008B62 2 ;
008B62 2
008B62 2 ; These mouse firmware entry points are offsets from the firmware
008B62 2 ; entry point of the slot, and also indirect.
008B62 2 SETMOUSE = $12
008B62 2 SERVEMOUSE = $13
008B62 2 READMOUSE = $14
008B62 2 CLEARMOUSE = $15
008B62 2 POSMOUSE = $16
008B62 2 CLAMPMOUSE = $17
008B62 2 HOMEMOUSE = $18
008B62 2 INITMOUSE = $19
008B62 2
008B62 2 MOUSTAT = $0778 ; + Slot Num
008B62 2 MOUSE_XL = $0478 ; + Slot Num
008B62 2 MOUSE_XH = $0578 ; + Slot Num
008B62 2 MOUSE_YL = $04f8 ; + Slot Num
008B62 2 MOUSE_YH = $05f8 ; + Slot Num
008B62 2 MOUSE_CLAMPL = $04f8
008B62 2 MOUSE_CLAMPH = $05f8
008B62 2
008B62 2 MOUSTAT_MASK_BUTTONINT = %00000100
008B62 2 MOUSTAT_MASK_MOVEINT = %00000010
008B62 2 MOUSTAT_MASK_DOWN = %10000000
008B62 2 MOUSTAT_MASK_WASDOWN = %01000000
008B62 2 MOUSTAT_MASK_MOVED = %00100000
008B62 2
008B62 2 MOUSEMODE_OFF = $00 ; Mouse off
008B62 2 MOUSEMODE_PASSIVE = $01 ; Passive mode (polling only)
008B62 2 MOUSEMODE_MOVEINT = $03 ; Interrupts on movement
008B62 2 MOUSEMODE_BUTINT = $05 ; Interrupts on button
008B62 2 MOUSEMODE_COMBINT = $07 ; Interrupts on movement and button
008B62 2
008B62 2
008B62 2 ; Mouse firmware is all indirectly called, because
008B62 2 ; it moved around a lot in different Apple ][ ROM
008B62 2 ; versions. This macro helps abstracts this for us.
008B62 2 .macro CALLMOUSE name
008B62 2 ldx #name
008B62 2 jsr WGCallMouse
008B62 2 .endmacro
008B62 2
008B62 2
008B62 2 CH_MOUSEPOINTER = 'B'
008B62 2
008B62 2
008B62 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008B62 2 ; WGEnableMouse
008B62 2 ; Prepares the mouse for use
008B62 2 ;
008B62 2 WGEnableMouse:
008B62 2 48 pha
008B63 2
008B63 2 8D 54 C0 SETSWITCH PAGE2OFF
008B66 2
008B66 2 ; Find slot number and calculate the various indirections needed
008B66 2 20 FB 8B jsr WGFindMouse
008B69 2 B0 4E bcs WGEnableMouse_Error
008B6B 2
008B6B 2 ; Install our interrupt handler via ProDOS (play nice!)
008B6B 2 20 00 BF jsr PRODOS_MLI
008B6E 2 40 .byte ALLOC_INTERRUPT
008B6F 2 C0 8D .addr WG_PRODOS_ALLOC
008B71 2 D0 46 bne WGEnableMouse_Error ; ProDOS will return here with Z clear on error
008B73 2
008B73 2 ; Initialize the mouse
008B73 2 9C B8 8D stz WG_MOUSEPOS_X
008B76 2 9C B9 8D stz WG_MOUSEPOS_Y
008B79 2 9C BB 8D stz WG_MOUSEBG
008B7C 2
008B7C 2 A2 19 20 E2 CALLMOUSE INITMOUSE
008B80 2 8B
008B81 2 B0 36 bcs WGEnableMouse_Error ; Firmware sets carry if mouse is not available
008B83 2
008B83 2 A2 15 20 E2 CALLMOUSE CLEARMOUSE
008B87 2 8B
008B88 2
008B88 2 A9 07 lda #MOUSEMODE_COMBINT ; Enable combination interrupt mode
008B8A 2 A2 12 20 E2 CALLMOUSE SETMOUSE
008B8E 2 8B
008B8F 2
008B8F 2 ; Scale the mouse's range into something easy to do math with,
008B8F 2 ; while retaining as much range of motion and precision as possible
008B8F 2 A9 80 lda #$80 ; 640 horizontally
008B91 2 8D F8 04 sta MOUSE_CLAMPL
008B94 2 A9 02 lda #$02
008B96 2 8D F8 05 sta MOUSE_CLAMPH
008B99 2 A9 00 lda #0
008B9B 2 A2 17 20 E2 CALLMOUSE CLAMPMOUSE
008B9F 2 8B
008BA0 2
008BA0 2 A9 E0 lda #$e0 ; 736 vertically
008BA2 2 8D F8 04 sta MOUSE_CLAMPL
008BA5 2 A9 02 lda #$02
008BA7 2 8D F8 05 sta MOUSE_CLAMPH
008BAA 2 A9 01 lda #1
008BAC 2 A2 17 20 E2 CALLMOUSE CLAMPMOUSE
008BB0 2 8B
008BB1 2
008BB1 2 A9 01 lda #1
008BB3 2 8D B7 8D sta WG_MOUSEACTIVE
008BB6 2
008BB6 2 58 cli ; Once all setup is done, it's safe to enable interrupts
008BB7 2 80 03 bra WGEnableMouse_done
008BB9 2
008BB9 2 WGEnableMouse_Error:
008BB9 2 9C B7 8D stz WG_MOUSEACTIVE
008BBC 2
008BBC 2 WGEnableMouse_done:
008BBC 2 68 pla
008BBD 2 60 rts
008BBE 2
008BBE 2
008BBE 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008BBE 2 ; WGDisableMouse
008BBE 2 ; Shuts off the mouse when we're done with it
008BBE 2 ;
008BBE 2 WGDisableMouse:
008BBE 2 48 pha
008BBF 2
008BBF 2 8D 54 C0 SETSWITCH PAGE2OFF
008BC2 2
008BC2 2 AD B7 8D lda WG_MOUSEACTIVE ; Never activated the mouse
008BC5 2 F0 19 beq WGDisableMouse_done
008BC7 2
008BC7 2 A5 00 lda MOUSEMODE_OFF
008BC9 2 A2 12 20 E2 CALLMOUSE SETMOUSE
008BCD 2 8B
008BCE 2
008BCE 2 9C B7 8D stz WG_MOUSEACTIVE
008BD1 2
008BD1 2 ; Remove our interrupt handler via ProDOS (done playing nice!)
008BD1 2 AD C1 8D lda WG_PRODOS_ALLOC+1 ; Copy interrupt ID that ProDOS gave us
008BD4 2 8D C5 8D sta WG_PRODOS_DEALLOC+1
008BD7 2
008BD7 2 20 00 BF jsr PRODOS_MLI
008BDA 2 41 .byte DEALLOC_INTERRUPT
008BDB 2 C4 8D .addr WG_PRODOS_DEALLOC
008BDD 2
008BDD 2 20 04 8D jsr WGUndrawPointer ; Be nice if we're disabled during a program
008BE0 2
008BE0 2 WGDisableMouse_done:
008BE0 2 68 pla
008BE1 2 60 rts
008BE2 2
008BE2 2
008BE2 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008BE2 2 ; WGCallMouse
008BE2 2 ; Calls a mouse firmware routine. Here's where we handle all
008BE2 2 ; the layers of indirection needed to call mouse firmware. The
008BE2 2 ; firmware moved in ROM several times over the life of the
008BE2 2 ; Apple ][, so it's kind of a hassle to call it.
008BE2 2 ; X: Name of routine (firmware offset constant)
008BE2 2 ; Side effects: Clobbers all registers
008BE2 2 WGCallMouse:
008BE2 2 8E E6 8B stx WGCallMouse+4 ; Use self-modifying code to smooth out some indirection
008BE5 2
008BE5 2 ; This load address is overwritten by the above code, AND by the mouse set
008BE5 2 ; up code, to make sure we have the right slot entry point and firmware
008BE5 2 ; offset
008BE5 2 AE 00 C4 ldx $c400 ; Self-modifying code!
008BE8 2 8E BC 8D stx WG_MOUSE_JUMPL ; Get low byte of final jump from firmware
008BEB 2
008BEB 2 08 php ; Note that mouse firmware is not re-entrant,
008BEC 2 78 sei ; so we must disable interrupts inside them
008BED 2
008BED 2 20 F2 8B jsr WGCallMouse_redirect
008BF0 2 28 plp ; Restore interrupts to previous state
008BF1 2 60 rts
008BF2 2
008BF2 2 WGCallMouse_redirect:
008BF2 2 AE BD 8D ldx WG_MOUSE_JUMPH
008BF5 2 AC BF 8D ldy WG_MOUSE_SLOTSHIFTED
008BF8 2 6C BC 8D jmp (WG_MOUSE_JUMPL)
008BFB 2
008BFB 2
008BFB 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008BFB 2 ; WGFindMouse
008BFB 2 ; Figures out which slot (//e) or port (//c) the mouse is in.
008BFB 2 ; It moved around a lot over the years. Sets it to 0 if no mouse
008BFB 2 ; could be found
008BFB 2 ; OUT C: Set if no mouse could be found
008BFB 2 WGFindMouse:
008BFB 2 48 DA SAVE_AX
008BFD 2
008BFD 2 A2 07 ldx #7
008BFF 2
008BFF 2 WGFindMouse_loop:
008BFF 2 8A txa ; Compute slot firmware locations for this loop
008C00 2 09 C0 ora #$c0
008C02 2 8D 13 8C sta WGFindMouse_loopModify+2 ; Self-modifying code!
008C05 2 8D 1A 8C sta WGFindMouse_loopModify+9
008C08 2 8D 21 8C sta WGFindMouse_loopModify+16
008C0B 2 8D 28 8C sta WGFindMouse_loopModify+23
008C0E 2 8D 2F 8C sta WGFindMouse_loopModify+30
008C11 2
008C11 2 WGFindMouse_loopModify:
008C11 2 ; Check for the magic 5-byte pattern that gives away the mouse card
008C11 2 AD 05 C0 lda $c005 ; These addresses are modified in place on
008C14 2 C9 38 cmp #$38 ; each loop iteration
008C16 2 D0 1E bne WGFindMouse_nextSlot
008C18 2 AD 07 C0 lda $c007
008C1B 2 C9 18 cmp #$18
008C1D 2 D0 17 bne WGFindMouse_nextSlot
008C1F 2 AD 0B C0 lda $c00b
008C22 2 C9 01 cmp #$01
008C24 2 D0 10 bne WGFindMouse_nextSlot
008C26 2 AD 0C C0 lda $c00c
008C29 2 C9 20 cmp #$20
008C2B 2 D0 09 bne WGFindMouse_nextSlot
008C2D 2 AD FB C0 lda $c0fb
008C30 2 C9 D6 cmp #$d6
008C32 2 D0 02 bne WGFindMouse_nextSlot
008C34 2 80 05 bra WGFindMouse_found
008C36 2
008C36 2 WGFindMouse_nextSlot:
008C36 2 CA dex
008C37 2 30 1B bmi WGFindMouse_none
008C39 2 80 C4 bra WGFindMouse_loop
008C3B 2
008C3B 2 WGFindMouse_found:
008C3B 2 ; Found it! Now configure all our indirection lookups
008C3B 2 8E BE 8D stx WG_MOUSE_SLOT
008C3E 2 A9 C0 lda #$c0
008C40 2 0D BE 8D ora WG_MOUSE_SLOT
008C43 2 8D BD 8D sta WG_MOUSE_JUMPH
008C46 2 8D E7 8B sta WGCallMouse+5 ; Self-modifying code!
008C49 2 8A txa
008C4A 2 0A asl
008C4B 2 0A asl
008C4C 2 0A asl
008C4D 2 0A asl
008C4E 2 8D BF 8D sta WG_MOUSE_SLOTSHIFTED
008C51 2 18 clc
008C52 2 80 04 bra WGFindMouse_done
008C54 2
008C54 2 WGFindMouse_none:
008C54 2 9C BE 8D stz WG_MOUSE_SLOT
008C57 2 38 sec
008C58 2
008C58 2 WGFindMouse_done:
008C58 2 FA 68 RESTORE_AX
008C5A 2 60 rts
008C5B 2
008C5B 2
008C5B 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008C5B 2 ; WGMouseInterruptHandler
008C5B 2 ; Handles interrupts that may be related to the mouse
008C5B 2 ; This is a ProDOS-compliant interrupt handling routine, and
008C5B 2 ; should be installed and removed via ProDOS as needed.
008C5B 2 ;
008C5B 2 ; IMPORTANT: This routine is NOT MLI-reentrant, which means MLI
008C5B 2 ; calls can NOT be made within this handler. See page 108 of the
008C5B 2 ; ProDOS 8 Technical Reference Manual if this feature needs to be
008C5B 2 ; added.
008C5B 2 ;
008C5B 2 WGMouseInterruptHandler:
008C5B 2 D8 cld ; ProDOS interrupt handlers must open with this
008C5C 2 48 DA 5A SAVE_AXY
008C5F 2
008C5F 2 A2 13 20 E2 CALLMOUSE SERVEMOUSE
008C63 2 8B
008C64 2 B0 64 bcs WGMouseInterruptHandler_disregard
008C66 2
008C66 2 78 sei
008C67 2
008C67 2 AD 1C C0 lda PAGE2 ; Need to preserve text bank, because we may interrupt rendering
008C6A 2 48 pha
008C6B 2 8D 54 C0 SETSWITCH PAGE2OFF
008C6E 2
008C6E 2 AE BE 8D ldx WG_MOUSE_SLOT
008C71 2 BD 78 07 lda MOUSTAT,x ; Check interrupt status bits first, because READMOUSE clears them
008C74 2 29 04 and #MOUSTAT_MASK_BUTTONINT
008C76 2 D0 56 bne WGMouseInterruptHandler_button
008C78 2
008C78 2 20 04 8D jsr WGUndrawPointer ; Erase the old mouse pointer
008C7B 2
008C7B 2 ; Read the mouse state. Note that interrupts need to remain
008C7B 2 ; off until after the data is copied.
008C7B 2 A2 14 20 E2 CALLMOUSE READMOUSE
008C7F 2 8B
008C80 2
008C80 2 AE BE 8D ldx WG_MOUSE_SLOT
008C83 2 BD 78 07 lda MOUSTAT,x ; Movement/button status bits are now valid
008C86 2 8D BA 8D sta WG_MOUSE_STAT
008C89 2
008C89 2 ; Read mouse position and transform it into screen space
008C89 2 5E 78 05 lsr MOUSE_XH,x
008C8C 2 7E 78 04 ror MOUSE_XL,x
008C8F 2 5E 78 05 lsr MOUSE_XH,x
008C92 2 7E 78 04 ror MOUSE_XL,x
008C95 2 5E 78 05 lsr MOUSE_XH,x
008C98 2 7E 78 04 ror MOUSE_XL,x
008C9B 2
008C9B 2 BD 78 04 lda MOUSE_XL,x
008C9E 2 8D B8 8D sta WG_MOUSEPOS_X
008CA1 2
008CA1 2 5E F8 05 lsr MOUSE_YH,x
008CA4 2 7E F8 04 ror MOUSE_YL,x
008CA7 2 5E F8 05 lsr MOUSE_YH,x
008CAA 2 7E F8 04 ror MOUSE_YL,x
008CAD 2 5E F8 05 lsr MOUSE_YH,x
008CB0 2 7E F8 04 ror MOUSE_YL,x
008CB3 2 5E F8 05 lsr MOUSE_YH,x
008CB6 2 7E F8 04 ror MOUSE_YL,x
008CB9 2 5E F8 05 lsr MOUSE_YH,x
008CBC 2 7E F8 04 ror MOUSE_YL,x
008CBF 2
008CBF 2 BD F8 04 lda MOUSE_YL,x
008CC2 2 8D B9 8D sta WG_MOUSEPOS_Y
008CC5 2
008CC5 2 20 0C 8D jsr WGDrawPointer ; Redraw the pointer
008CC8 2 80 29 bra WGMouseInterruptHandler_intDone
008CCA 2
008CCA 2 WGMouseInterruptHandler_disregard:
008CCA 2 ; Carry will still be set here, to notify ProDOS that
008CCA 2 ; this interrupt was not ours
008CCA 2 7A FA 68 RESTORE_AXY
008CCD 2 60 rts
008CCE 2
008CCE 2 WGMouseInterruptHandler_button:
008CCE 2 A2 14 20 E2 CALLMOUSE READMOUSE
008CD2 2 8B
008CD3 2 AE BE 8D ldx WG_MOUSE_SLOT
008CD6 2 BD 78 07 lda MOUSTAT,x ; Movement/button status bits are now valid
008CD9 2 8D BA 8D sta WG_MOUSE_STAT
008CDC 2
008CDC 2 2C BA 8D bit WG_MOUSE_STAT ; Check for rising edge of button state
008CDF 2 10 12 bpl WGMouseInterruptHandler_intDone
008CE1 2
008CE1 2 AD B8 8D lda WG_MOUSEPOS_X ; Where did we click?
008CE4 2 85 06 sta PARAM0
008CE6 2 AD B9 8D lda WG_MOUSEPOS_Y
008CE9 2 85 07 sta PARAM1
008CEB 2 20 5D 8A jsr WGViewFromPoint
008CEE 2 30 03 bmi WGMouseInterruptHandler_intDone
008CF0 2
008CF0 2 ; Button was clicked in a view, so make a note of it for later
008CF0 2 8D CF 92 sta WG_PENDINGACTIONVIEW
008CF3 2
008CF3 2 WGMouseInterruptHandler_intDone:
008CF3 2 68 pla ; Restore text bank
008CF4 2 10 05 bpl WGMouseInterruptHandler_intDoneBankOff
008CF6 2 8D 55 C0 SETSWITCH PAGE2ON
008CF9 2 80 03 bra WGMouseInterruptHandler_done
008CFB 2
008CFB 2 WGMouseInterruptHandler_intDoneBankOff:
008CFB 2 8D 54 C0 SETSWITCH PAGE2OFF
008CFE 2
008CFE 2 WGMouseInterruptHandler_done:
008CFE 2 7A FA 68 RESTORE_AXY
008D01 2
008D01 2 58 cli
008D02 2 18 clc ; Notify ProDOS this was our interrupt
008D03 2 60 rts
008D04 2
008D04 2
008D04 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008D04 2 ; WGUndrawPointer
008D04 2 ; Unplots the mouse pointer at current location
008D04 2 ; Side effects: Clobbers BASL,BASH
008D04 2 ;
008D04 2 WGUndrawPointer:
008D04 2 48 pha
008D05 2 A9 80 lda #$80
008D07 2 20 1C 8D jsr renderPointer
008D0A 2 68 pla
008D0B 2 60 rts
008D0C 2
008D0C 2
008D0C 2
008D0C 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008D0C 2 ; WGDrawPointer
008D0C 2 ; Plots the mouse pointer at current location
008D0C 2 ;
008D0C 2 WGDrawPointer:
008D0C 2 48 pha
008D0D 2 A9 00 lda #0
008D0F 2 20 1C 8D jsr renderPointer
008D12 2 68 pla
008D13 2 60 rts
008D14 2
008D14 2
008D14 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008D14 2 ; WGPointerDirty
008D14 2 ; Updates the background behind the mouse pointer without
008D14 2 ; modifying it's current render state. Assumes pointer is not
008D14 2 ; currently visible
008D14 2 ;
008D14 2 WGPointerDirty:
008D14 2 48 pha
008D15 2 A9 C0 lda #%11000000
008D17 2 20 1C 8D jsr renderPointer
008D1A 2 68 pla
008D1B 2 60 rts
008D1C 2
008D1C 2
008D1C 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008D1C 2 ; renderPointer
008D1C 2 ; Performs mouse-pointer-related rendering
008D1C 2 ; A: 0=draw, %10000000=undraw, %11000000=recapture background
008D1C 2 ;
008D1C 2 renderPointer:
008D1C 2 48 DA 5A SAVE_AXY
008D1F 2 8D B6 8D sta renderPointerMode
008D22 2 A5 28 lda BASL ; Need to preserve BAS, because we may interrupt rendering
008D24 2 48 pha
008D25 2 A5 29 lda BASH
008D27 2 48 pha
008D28 2 AD 1C C0 lda PAGE2 ; Need to preserve text bank, because we may interrupt rendering
008D2B 2 48 pha
008D2C 2
008D2C 2 AD B7 8D lda WG_MOUSEACTIVE
008D2F 2 F0 70 beq renderPointer_done ; Mouse not enabled
008D31 2
008D31 2 AE B9 8D ldx WG_MOUSEPOS_Y
008D34 2 E0 18 cpx #24
008D36 2 B0 69 bcs renderPointer_done ; Mouse out of range (vertically)
008D38 2
008D38 2 BD EF 94 lda TEXTLINES_L,x ; Compute video memory address of point
008D3B 2 85 28 sta BASL
008D3D 2 BD D7 94 lda TEXTLINES_H,x
008D40 2 85 29 sta BASH
008D42 2
008D42 2 AD B8 8D lda WG_MOUSEPOS_X
008D45 2 C9 50 cmp #80
008D47 2 B0 58 bcs renderPointer_done ; Mouse out of range (horizontally)
008D49 2
008D49 2 4A lsr
008D4A 2 18 clc
008D4B 2 65 28 adc BASL
008D4D 2 85 28 sta BASL
008D4F 2 A9 00 lda #0
008D51 2 65 29 adc BASH
008D53 2 85 29 sta BASH
008D55 2
008D55 2 AD B8 8D lda WG_MOUSEPOS_X ; X even?
008D58 2 29 01 and #$01
008D5A 2 D0 27 bne renderPointer_xOdd
008D5C 2
008D5C 2 8D 55 C0 SETSWITCH PAGE2ON
008D5F 2
008D5F 2 2C B6 8D bit renderPointerMode ; Draw or undraw?
008D62 2 10 02 bpl renderPointer_draw
008D64 2 50 14 bvc renderPointer_undraw
008D66 2
008D66 2 renderPointer_draw:
008D66 2 B2 28 lda (BASL) ; Save background
008D68 2 C9 42 cmp #CH_MOUSEPOINTER ; Make sure we never capture ourselves and leave a "stamp"
008D6A 2 F0 03 beq renderPointer_drawSaved
008D6C 2 8D BB 8D sta WG_MOUSEBG
008D6F 2
008D6F 2 renderPointer_drawSaved:
008D6F 2 2C B6 8D bit renderPointerMode ; Recapture or draw?
008D72 2 70 2D bvs renderPointer_done
008D74 2
008D74 2 A9 42 lda #CH_MOUSEPOINTER ; Draw the pointer
008D76 2 92 28 sta (BASL)
008D78 2 80 27 bra renderPointer_done
008D7A 2
008D7A 2 renderPointer_undraw:
008D7A 2 AD BB 8D lda WG_MOUSEBG
008D7D 2 F0 22 beq renderPointer_done ; No saved background yet
008D7F 2 92 28 sta (BASL)
008D81 2 80 1E bra renderPointer_done
008D83 2
008D83 2 renderPointer_xOdd:
008D83 2 8D 54 C0 SETSWITCH PAGE2OFF
008D86 2
008D86 2 2C B6 8D bit renderPointerMode ; Draw or undraw?
008D89 2 10 02 bpl renderPointer_drawOdd
008D8B 2 50 ED bvc renderPointer_undraw
008D8D 2
008D8D 2 renderPointer_drawOdd:
008D8D 2 B2 28 lda (BASL) ; Save background
008D8F 2 C9 42 cmp #CH_MOUSEPOINTER ; Make sure we never capture ourselves and leave a "stamp"
008D91 2 F0 03 beq renderPointer_drawOddSaved
008D93 2 8D BB 8D sta WG_MOUSEBG
008D96 2
008D96 2 renderPointer_drawOddSaved:
008D96 2 2C B6 8D bit renderPointerMode ; Recapture or draw?
008D99 2 70 06 bvs renderPointer_done
008D9B 2
008D9B 2 A9 42 lda #CH_MOUSEPOINTER ; Draw the pointer
008D9D 2 92 28 sta (BASL)
008D9F 2 80 00 bra renderPointer_done
008DA1 2
008DA1 2 renderPointer_done:
008DA1 2 68 pla ; Restore text bank
008DA2 2 10 05 bpl renderPointer_doneBankOff
008DA4 2 8D 55 C0 SETSWITCH PAGE2ON
008DA7 2 80 03 bra renderPointer_doneBAS
008DA9 2
008DA9 2 renderPointer_doneBankOff:
008DA9 2 8D 54 C0 SETSWITCH PAGE2OFF
008DAC 2
008DAC 2 renderPointer_doneBAS:
008DAC 2 68 pla ; Restore BAS
008DAD 2 85 29 sta BASH
008DAF 2 68 pla
008DB0 2 85 28 sta BASL
008DB2 2
008DB2 2 7A FA 68 RESTORE_AXY
008DB5 2 60 rts
008DB6 2
008DB6 2 renderPointerMode:
008DB6 2 00 .byte 0
008DB7 2
008DB7 2
008DB7 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008DB7 2 ; Mouse API state
008DB7 2 ;
008DB7 2 WG_MOUSEACTIVE:
008DB7 2 00 .byte 0
008DB8 2
008DB8 2 WG_MOUSEPOS_X:
008DB8 2 27 .byte 39
008DB9 2 WG_MOUSEPOS_Y:
008DB9 2 0B .byte 11
008DBA 2 WG_MOUSE_STAT:
008DBA 2 00 .byte 0
008DBB 2 WG_MOUSEBG:
008DBB 2 00 .byte 0
008DBC 2
008DBC 2 WG_MOUSE_JUMPL:
008DBC 2 00 .byte 0
008DBD 2 WG_MOUSE_JUMPH:
008DBD 2 00 .byte 0
008DBE 2 WG_MOUSE_SLOT:
008DBE 2 00 .byte 0
008DBF 2 WG_MOUSE_SLOTSHIFTED:
008DBF 2 00 .byte 0
008DC0 2
008DC0 2
008DC0 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008DC0 2 ; ProDOS system call parameter blocks
008DC0 2 ;
008DC0 2 WG_PRODOS_ALLOC:
008DC0 2 02 .byte 2
008DC1 2 00 .byte 0 ; ProDOS returns an ID number for the interrupt here
008DC2 2 5B 8C .addr WGMouseInterruptHandler
008DC4 2
008DC4 2 WG_PRODOS_DEALLOC:
008DC4 2 01 .byte 1
008DC5 2 00 .byte 0 ; To be filled with ProDOS ID number
008DC6 2
008DC6 2
008DC6 2
008DC6 1 .include "applesoft.s"
008DC6 2 ;
008DC6 2 ; applesoft.s
008DC6 2 ; Applesoft API via the & extension point
008DC6 2 ;
008DC6 2 ; Created by Quinn Dunki on 8/15/14.
008DC6 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved.
008DC6 2 ;
008DC6 2
008DC6 2
008DC6 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008DC6 2 ; Applesoft ROM entry points and constants
008DC6 2 ;
008DC6 2 LINNUML = $0050 ; Scratch pad for calculating line numbers (LSB)
008DC6 2 LINNUMH = $0051 ; Scratch pad for calculating line numbers (MSB)
008DC6 2 CURLINL = $0075 ; Current line number (LSB)
008DC6 2 CURLINH = $0076 ; Current line number (MSB)
008DC6 2 CHRGET = $00b1 ; Advances text point and gets character in A
008DC6 2 CHRGOT = $00b7 ; Returns character at text pointer in A
008DC6 2 TXTPTRL = $00b8 ; Current location in BASIC listing (LSB)
008DC6 2 TXTPTRH = $00b9 ; Current location in BASIC listing (MSB)
008DC6 2 VARPNT = $0083 ; Return value for PTRGET
008DC6 2
008DC6 2 FAC = $009d ; Floating point accumulator
008DC6 2
008DC6 2 AMPVECTOR = $03f5 ; Ampersand entry vector
008DC6 2 ERROR = $d412 ; Reports error in X
008DC6 2 NEWSTT = $d7d2 ; Advance to next Applesoft statement
008DC6 2 GOTO = $d93e ; Entry point of Applesoft GOTO
008DC6 2 LINGET = $da0c ; Read a line number (16-bit integer) into LINNUM
008DC6 2 FRMNUM = $dd67 ; Evaluate an expression as a number and store in FAC
008DC6 2 CHKCOM = $debe ; Validates current character is a ',', then gets it
008DC6 2 SYNCHR = $dec0 ; Validates current character is what's in A
008DC6 2 AYINT = $e10c ; Convert FAC to 8-bit signed integer
008DC6 2 GETBYT = $e6f8 ; Gets an integer at text pointer, stores in X
008DC6 2 GETNUM = $e746 ; Gets an 8-bit, stores it X, skips past a comma
008DC6 2 PTRGET = $dfe3 ; Finds the Applesoft variable in memory at text pointer
008DC6 2
008DC6 2 TOKEN_GOSUB = $b0 ; Applesoft's token for GOSUB
008DC6 2 TOKEN_HOME = $97 ; Applesoft's token for HOME
008DC6 2 TOKEN_PRINT = $ba ; Applesoft's token for PRINT
008DC6 2 TOKEN_MINUS = $c9 ; Applesoft's token for a minus sign
008DC6 2 TOKEN_DRAW = $94 ; Applesoft's token for DRAW
008DC6 2 TOKEN_PLOT = $8d ; Applesoft's token for PLOT
008DC6 2 TOKEN_GET = $be ; Applesoft's token for GET
008DC6 2
008DC6 2 ERR_UNDEFINEDFUNC = 224
008DC6 2 ERR_SYNTAX = 16
008DC6 2 ERR_ENDOFDATA = 5
008DC6 2 ERR_TOOLONG = 176
008DC6 2
008DC6 2 MAXCMDLEN = 6
008DC6 2
008DC6 2
008DC6 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008DC6 2 ; WGInitApplesoft
008DC6 2 ; Sets up Applesoft API
008DC6 2 ;
008DC6 2 WGInitApplesoft:
008DC6 2 48 pha
008DC7 2
008DC7 2 A9 4C lda #$4c ; Patch in our jump vector for &
008DC9 2 8D F5 03 sta AMPVECTOR
008DCC 2 A9 D8 lda #<WGAmpersand
008DCE 2 8D F6 03 sta AMPVECTOR+1
008DD1 2 A9 8D lda #>WGAmpersand
008DD3 2 8D F7 03 sta AMPVECTOR+2
008DD6 2
008DD6 2 68 pla
008DD7 2 60 rts
008DD8 2
008DD8 2
008DD8 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008DD8 2 ; WGAmpersand
008DD8 2 ; The entry point from Applesoft. Applesoft text pointer
008DD8 2 ; will be positioned two after the '&', and accumulator will
008DD8 2 ; contain first character after the '&'
008DD8 2 ; Side effects: Clobbers All registers,S0
008DD8 2 ;
008DD8 2 WGAmpersand:
008DD8 2 BA tsx ; Start by caching a valid stack state to return to Applesoft,
008DD9 2 8E FF 91 stx WG_STACKPTR ; in case we need to do so in a hurry
008DDC 2
008DDC 2 85 19 sta SCRATCH0
008DDE 2
008DDE 2 A0 00 ldy #0
008DE0 2 A6 19 ldx SCRATCH0
008DE2 2
008DE2 2 WGAmpersand_parseLoop:
008DE2 2 8A txa
008DE3 2 F0 17 beq WGAmpersand_matchStart ; Check for end-of-statement (CHRGET handles : and EOL)
008DE5 2 C9 28 cmp #'('
008DE7 2 F0 13 beq WGAmpersand_matchStart
008DE9 2
008DE9 2 99 DF 91 sta WGAmpersandCommandBuffer,y
008DEC 2
008DEC 2 20 B1 00 jsr CHRGET
008DEF 2 AA tax
008DF0 2
008DF0 2 C8 iny
008DF1 2 C0 07 cpy #MAXCMDLEN+1
008DF3 2 D0 ED bne WGAmpersand_parseLoop
008DF5 2
008DF5 2 WGAmpersand_parseFail:
008DF5 2 A2 E0 ldx #ERR_UNDEFINEDFUNC
008DF7 2 20 12 D4 jsr ERROR
008DFA 2 80 49 bra WGAmpersand_done
008DFC 2
008DFC 2 WGAmpersand_matchStart:
008DFC 2 A9 00 lda #0
008DFE 2 99 DF 91 sta WGAmpersandCommandBuffer,y ; Null terminate the buffer for matching
008E01 2
008E01 2 A0 00 ldy #0
008E03 2 A2 00 ldx #0 ; Command buffer now contains our API call
008E05 2 DA phx ; We stash the current command number on the stack
008E06 2
008E06 2 WGAmpersand_matchLoop:
008E06 2 B9 DF 91 lda WGAmpersandCommandBuffer,y
008E09 2 F0 09 beq WGAmpersand_matchPossible
008E0B 2 DD 01 92 cmp WGAmpersandCommandTable,x
008E0E 2 D0 09 bne WGAmpersand_matchNext ; Not this one
008E10 2
008E10 2 C8 iny
008E11 2 E8 inx
008E12 2 80 F2 bra WGAmpersand_matchLoop
008E14 2
008E14 2 WGAmpersand_matchPossible:
008E14 2 BD 01 92 lda WGAmpersandCommandTable,x
008E17 2 F0 0F beq WGAmpersand_matchFound ; Got one!
008E19 2
008E19 2 WGAmpersand_matchNext:
008E19 2 68 pla ; Advance index to next commmand in table
008E1A 2 1A inc
008E1B 2 48 pha
008E1C 2 0A asl
008E1D 2 0A asl
008E1E 2 0A asl
008E1F 2 AA tax
008E20 2
008E20 2 E0 C8 cpx #WGAmpersandCommandTableEnd-WGAmpersandCommandTable
008E22 2 F0 1B beq WGAmpersand_matchFail ; Hit the end of the table
008E24 2
008E24 2 A0 00 ldy #0
008E26 2 80 DE bra WGAmpersand_matchLoop
008E28 2
008E28 2 WGAmpersand_matchFound:
008E28 2 68 pla ; This is now the matching command number
008E29 2 1A inc
008E2A 2 0A asl
008E2B 2 0A asl
008E2C 2 0A asl
008E2D 2 A8 tay
008E2E 2 B9 FF 91 lda WGAmpersandCommandTable-2,y ; Prepare an indirect JSR to our command
008E31 2 8D 3B 8E sta WGAmpersand_commandJSR+1 ; Self-modifying code!
008E34 2 B9 00 92 lda WGAmpersandCommandTable-1,y
008E37 2 8D 3C 8E sta WGAmpersand_commandJSR+2
008E3A 2
008E3A 2 ; Self-modifying code!
008E3A 2 WGAmpersand_commandJSR:
008E3A 2 20 45 8E jsr WGAmpersand_done ; Address here overwritten with command
008E3D 2 80 06 bra WGAmpersand_done
008E3F 2
008E3F 2 WGAmpersand_matchFail:
008E3F 2 68 pla ; We left command number on the stack while matching
008E40 2 A2 E0 ldx #ERR_UNDEFINEDFUNC
008E42 2 20 12 D4 jsr ERROR
008E45 2
008E45 2 WGAmpersand_done:
008E45 2 60 rts
008E46 2
008E46 2
008E46 2
008E46 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008E46 2 ; WGAmpersandBeginArguments
008E46 2 ; Begins reading an ampersand argument list
008E46 2 ; Side effects: Clobbers all registers
008E46 2 WGAmpersandBeginArguments:
008E46 2 48 pha
008E47 2
008E47 2 A9 28 lda #'('
008E49 2 20 C0 DE jsr SYNCHR ; Expect opening parenthesis
008E4C 2
008E4C 2 68 pla
008E4D 2 60 rts
008E4E 2
008E4E 2
008E4E 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008E4E 2 ; WGAmpersandNextArgument
008E4E 2 ; Prepares for the next argument in the list
008E4E 2 ; Side effects: Clobbers all registers
008E4E 2 WGAmpersandNextArgument:
008E4E 2 20 B7 00 jsr CHRGOT
008E51 2 20 BE DE jsr CHKCOM ; Verify parameter separator
008E54 2 60 rts
008E55 2
008E55 2
008E55 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008E55 2 ; WGAmpersandEndArguments
008E55 2 ; Finishes reading an ampersand argument list
008E55 2 ; Side effects: Clobbers all registers
008E55 2 WGAmpersandEndArguments:
008E55 2 48 pha
008E56 2
008E56 2 A9 29 lda #')'
008E58 2 20 C0 DE jsr SYNCHR ; Expect closing parenthesis
008E5B 2
008E5B 2 68 pla
008E5C 2 60 rts
008E5D 2
008E5D 2
008E5D 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008E5D 2 ; WGAmpersandIntArgument
008E5D 2 ; Reads an integer argument for the current command
008E5D 2 ; OUT A : The argument
008E5D 2 ; Side effects: Clobbers all registers
008E5D 2 WGAmpersandIntArgument:
008E5D 2 20 B7 00 jsr CHRGOT
008E60 2 C9 C9 cmp #TOKEN_MINUS
008E62 2 F0 05 beq WGAmpersandIntArgument_signed
008E64 2
008E64 2 20 F8 E6 jsr GETBYT
008E67 2 8A txa
008E68 2 60 rts
008E69 2
008E69 2 WGAmpersandIntArgument_signed:
008E69 2 20 B1 00 jsr CHRGET
008E6C 2 20 F8 E6 jsr GETBYT
008E6F 2 8A txa
008E70 2 49 FF eor #$ff
008E72 2 1A inc
008E73 2 60 rts
008E74 2
008E74 2
008E74 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008E74 2 ; WGAmpersandAddrArgument
008E74 2 ; Reads a 16-bit pointer (or integer) argument for the current command
008E74 2 ; OUT X : The argument (LSB)
008E74 2 ; OUT Y : The argument (MSB)
008E74 2 ; Side effects: Clobbers all registers
008E74 2 WGAmpersandAddrArgument:
008E74 2 20 B7 00 jsr CHRGOT
008E77 2 20 0C DA jsr LINGET
008E7A 2
008E7A 2 A6 50 ldx LINNUML
008E7C 2 A4 51 ldy LINNUMH
008E7E 2 60 rts
008E7F 2
008E7F 2
008E7F 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008E7F 2 ; WGAmpersandStrArgument
008E7F 2 ; Reads a string argument for the current command in PARAM0/1.
008E7F 2 ; This string is copied into privately allocated memory.
008E7F 2 ; OUT X : Pointer to a stored copy of the string (LSB)
008E7F 2 ; OUT Y : Pointer to a stored copy of the string (MSB)
008E7F 2 ; Side effects: Clobbers P0/P1 and all registers
008E7F 2 WGAmpersandStrArgument:
008E7F 2 A9 22 lda #'"'
008E81 2 20 C0 DE jsr SYNCHR ; Expect opening quote
008E84 2
008E84 2 A5 B8 lda TXTPTRL ; Allocate for, and copy the string at TXTPTR
008E86 2 85 06 sta PARAM0
008E88 2 A5 B9 lda TXTPTRH
008E8A 2 85 07 sta PARAM1
008E8C 2 A9 22 lda #'"' ; Specify quote as our terminator
008E8E 2 20 B9 7E jsr WGStoreStr
008E91 2
008E91 2 WGAmpersandStrArgument_loop:
008E91 2 20 B1 00 jsr CHRGET ; Consume the string for Applesoft
008E94 2 F0 04 beq WGAmpersandStrArgument_done
008E96 2 C9 22 cmp #'"' ; Check for closing quote
008E98 2 D0 F7 bne WGAmpersandStrArgument_loop
008E9A 2
008E9A 2 WGAmpersandStrArgument_done:
008E9A 2 A9 22 lda #'"'
008E9C 2 20 C0 DE jsr SYNCHR ; Expect closing quote
008E9F 2
008E9F 2 A6 06 ldx PARAM0
008EA1 2 A4 07 ldy PARAM1
008EA3 2 60 rts
008EA4 2
008EA4 2
008EA4 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008EA4 2 ; WGAmpersandTempStrArgument
008EA4 2 ; Reads a string argument for the current command in PARAM0/1.
008EA4 2 ; This string is pointed to IN PLACE, and NOT copied.
008EA4 2 ; OUT X : Pointer to a stored copy of the string (LSB)
008EA4 2 ; OUT Y : Pointer to a stored copy of the string (MSB)
008EA4 2 ; OUT A : String length
008EA4 2 ; Side effects: Clobbers P0/P1 and all registers
008EA4 2 WGAmpersandTempStrArgument:
008EA4 2 A9 22 lda #'"'
008EA6 2 20 C0 DE jsr SYNCHR ; Expect opening quote
008EA9 2
008EA9 2 A5 B8 lda TXTPTRL ; Grab current TXTPTR
008EAB 2 85 06 sta PARAM0
008EAD 2 A5 B9 lda TXTPTRH
008EAF 2 85 07 sta PARAM1
008EB1 2
008EB1 2 WGAmpersandTempStrArgument_loop:
008EB1 2 20 B1 00 jsr CHRGET ; Consume the string for Applesoft
008EB4 2 F0 04 beq WGAmpersandTempStrArgument_done
008EB6 2 C9 22 cmp #'"' ; Check for closing quote
008EB8 2 D0 F7 bne WGAmpersandTempStrArgument_loop
008EBA 2
008EBA 2 WGAmpersandTempStrArgument_done:
008EBA 2 A9 22 lda #'"'
008EBC 2 20 C0 DE jsr SYNCHR ; Expect closing quote
008EBF 2
008EBF 2 ; Compute the 8-bit distance TXTPTR moved. Note that we can't simply
008EBF 2 ; count in the above loop, because CHRGET will skip ahead unpredictable
008EBF 2 ; amounts
008EBF 2 38 sec
008EC0 2 A5 B8 lda TXTPTRL
008EC2 2 E5 06 sbc PARAM0
008EC4 2 3A dec
008EC5 2
008EC5 2 A6 06 ldx PARAM0 ; Return results
008EC7 2 A4 07 ldy PARAM1
008EC9 2 ; pla
008EC9 2
008EC9 2 60 rts
008ECA 2
008ECA 2
008ECA 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008ECA 2 ; Ampersand API entry points
008ECA 2 ;
008ECA 2
008ECA 2
008ECA 2
008ECA 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008ECA 2 ; WGAmpersand_HOME
008ECA 2 ; Clears the screen
008ECA 2 ; &HOME
008ECA 2 WGAmpersand_HOME:
008ECA 2 20 FF 7E jsr WGClearScreen
008ECD 2 20 9C 91 jsr WGBottomCursor
008ED0 2
008ED0 2 60 rts
008ED1 2
008ED1 2
008ED1 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008ED1 2 ; WGAmpersand_DESK
008ED1 2 ; Render the desktop
008ED1 2 ; &DESK
008ED1 2 WGAmpersand_DESK:
008ED1 2 20 29 7F jsr WGDesktop
008ED4 2 20 9C 91 jsr WGBottomCursor
008ED7 2 60 rts
008ED8 2
008ED8 2
008ED8 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008ED8 2 ; WGAmpersand_WINDW
008ED8 2 ; Create a view
008ED8 2 ; &WINDW(id,style,x,y,width,height,canvas width,canvas height)
008ED8 2 WGAmpersand_WINDW:
008ED8 2 20 46 8E jsr WGAmpersandBeginArguments
008EDB 2
008EDB 2 20 5D 8E jsr WGAmpersandIntArgument
008EDE 2 8D DF 91 sta WGAmpersandCommandBuffer+0
008EE1 2 20 4E 8E jsr WGAmpersandNextArgument
008EE4 2
008EE4 2 20 5D 8E jsr WGAmpersandIntArgument
008EE7 2 09 80 ora #VIEW_STYLE_APPLESOFT ; Flag this as an Applesoft-created view
008EE9 2 8D E0 91 sta WGAmpersandCommandBuffer+1
008EEC 2 20 4E 8E jsr WGAmpersandNextArgument
008EEF 2
008EEF 2 20 5D 8E jsr WGAmpersandIntArgument
008EF2 2 8D E1 91 sta WGAmpersandCommandBuffer+2
008EF5 2 20 4E 8E jsr WGAmpersandNextArgument
008EF8 2
008EF8 2 20 5D 8E jsr WGAmpersandIntArgument
008EFB 2 8D E2 91 sta WGAmpersandCommandBuffer+3
008EFE 2 20 4E 8E jsr WGAmpersandNextArgument
008F01 2
008F01 2 20 5D 8E jsr WGAmpersandIntArgument
008F04 2 8D E3 91 sta WGAmpersandCommandBuffer+4
008F07 2 20 4E 8E jsr WGAmpersandNextArgument
008F0A 2
008F0A 2 20 5D 8E jsr WGAmpersandIntArgument
008F0D 2 8D E4 91 sta WGAmpersandCommandBuffer+5
008F10 2 20 4E 8E jsr WGAmpersandNextArgument
008F13 2
008F13 2 20 5D 8E jsr WGAmpersandIntArgument
008F16 2 8D E5 91 sta WGAmpersandCommandBuffer+6
008F19 2 20 4E 8E jsr WGAmpersandNextArgument
008F1C 2
008F1C 2 20 5D 8E jsr WGAmpersandIntArgument
008F1F 2 8D E6 91 sta WGAmpersandCommandBuffer+7
008F22 2
008F22 2 20 55 8E jsr WGAmpersandEndArguments
008F25 2
008F25 2 A9 DF 85 06 CALL16 WGCreateView,WGAmpersandCommandBuffer
008F29 2 A9 91 85 07
008F2D 2 20 B9 84
008F30 2
008F30 2 20 16 87 jsr WGEraseViewContents
008F33 2 20 B6 85 jsr WGPaintView
008F36 2 20 9C 91 jsr WGBottomCursor
008F39 2 60 rts
008F3A 2
008F3A 2
008F3A 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008F3A 2 ; WGAmpersand_CHKBX
008F3A 2 ; Create a checkbox
008F3A 2 ; &CHKBX(id,x,y,"title")
008F3A 2 WGAmpersand_CHKBX:
008F3A 2 20 46 8E jsr WGAmpersandBeginArguments
008F3D 2
008F3D 2 20 5D 8E jsr WGAmpersandIntArgument
008F40 2 8D DF 91 sta WGAmpersandCommandBuffer+0
008F43 2 20 4E 8E jsr WGAmpersandNextArgument
008F46 2
008F46 2 20 5D 8E jsr WGAmpersandIntArgument
008F49 2 8D E0 91 sta WGAmpersandCommandBuffer+1
008F4C 2 20 4E 8E jsr WGAmpersandNextArgument
008F4F 2
008F4F 2 20 5D 8E jsr WGAmpersandIntArgument
008F52 2 8D E1 91 sta WGAmpersandCommandBuffer+2
008F55 2 20 4E 8E jsr WGAmpersandNextArgument
008F58 2
008F58 2 20 7F 8E jsr WGAmpersandStrArgument
008F5B 2 8E E2 91 stx WGAmpersandCommandBuffer+3
008F5E 2 8C E3 91 sty WGAmpersandCommandBuffer+4
008F61 2
008F61 2 20 55 8E jsr WGAmpersandEndArguments
008F64 2
008F64 2 A9 DF 85 06 CALL16 WGCreateCheckbox,WGAmpersandCommandBuffer
008F68 2 A9 91 85 07
008F6C 2 20 0F 85
008F6F 2
008F6F 2 AD CD 92 0A LDY_ACTIVEVIEW ; Flag this as an Applesoft-created view
008F73 2 0A 0A 0A A8
008F77 2 A9 80 lda #VIEW_STYLE_APPLESOFT
008F79 2 19 DA 92 ora WG_VIEWRECORDS+4,y
008F7C 2 99 DA 92 sta WG_VIEWRECORDS+4,y
008F7F 2
008F7F 2 20 B6 85 jsr WGPaintView
008F82 2 20 9C 91 jsr WGBottomCursor
008F85 2
008F85 2 60 rts
008F86 2
008F86 2
008F86 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008F86 2 ; WGAmpersand_BUTTN
008F86 2 ; Create a button
008F86 2 ; &BUTTN(id,x,y,width,lineNum,"title")
008F86 2 WGAmpersand_BUTTN:
008F86 2 20 46 8E jsr WGAmpersandBeginArguments
008F89 2
008F89 2 20 5D 8E jsr WGAmpersandIntArgument
008F8C 2 8D DF 91 sta WGAmpersandCommandBuffer+0
008F8F 2 20 4E 8E jsr WGAmpersandNextArgument
008F92 2
008F92 2 20 5D 8E jsr WGAmpersandIntArgument
008F95 2 8D E0 91 sta WGAmpersandCommandBuffer+1
008F98 2 20 4E 8E jsr WGAmpersandNextArgument
008F9B 2
008F9B 2 20 5D 8E jsr WGAmpersandIntArgument
008F9E 2 8D E1 91 sta WGAmpersandCommandBuffer+2
008FA1 2 20 4E 8E jsr WGAmpersandNextArgument
008FA4 2
008FA4 2 20 5D 8E jsr WGAmpersandIntArgument
008FA7 2 8D E2 91 sta WGAmpersandCommandBuffer+3
008FAA 2 20 4E 8E jsr WGAmpersandNextArgument
008FAD 2
008FAD 2 20 74 8E jsr WGAmpersandAddrArgument
008FB0 2 8E E3 91 stx WGAmpersandCommandBuffer+4
008FB3 2 8C E4 91 sty WGAmpersandCommandBuffer+5
008FB6 2 20 4E 8E jsr WGAmpersandNextArgument
008FB9 2
008FB9 2 20 7F 8E jsr WGAmpersandStrArgument
008FBC 2 8E E5 91 stx WGAmpersandCommandBuffer+6
008FBF 2 8C E6 91 sty WGAmpersandCommandBuffer+7
008FC2 2
008FC2 2 20 55 8E jsr WGAmpersandEndArguments
008FC5 2
008FC5 2 A9 DF 85 06 CALL16 WGCreateButton,WGAmpersandCommandBuffer
008FC9 2 A9 91 85 07
008FCD 2 20 5E 85
008FD0 2
008FD0 2 AD CD 92 0A LDY_ACTIVEVIEW ; Flag this as an Applesoft-created view
008FD4 2 0A 0A 0A A8
008FD8 2 A9 80 lda #VIEW_STYLE_APPLESOFT
008FDA 2 19 DA 92 ora WG_VIEWRECORDS+4,y
008FDD 2 99 DA 92 sta WG_VIEWRECORDS+4,y
008FE0 2
008FE0 2 20 B6 85 jsr WGPaintView
008FE3 2 20 9C 91 jsr WGBottomCursor
008FE6 2
008FE6 2 60 rts
008FE7 2
008FE7 2
008FE7 2
008FE7 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008FE7 2 ; WGAmpersand_SEL
008FE7 2 ; Select a view
008FE7 2 ; &SEL(id)
008FE7 2 WGAmpersand_SEL:
008FE7 2 20 46 8E jsr WGAmpersandBeginArguments
008FEA 2 20 5D 8E jsr WGAmpersandIntArgument
008FED 2
008FED 2 20 57 87 jsr WGSelectView
008FF0 2
008FF0 2 20 55 8E jsr WGAmpersandEndArguments
008FF3 2 60 rts
008FF4 2
008FF4 2
008FF4 2
008FF4 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008FF4 2 ; WGAmpersand_FOC
008FF4 2 ; Focuses selected view
008FF4 2 ; &FOC
008FF4 2 WGAmpersand_FOC:
008FF4 2 20 64 87 jsr WGViewFocus
008FF7 2 20 9C 91 jsr WGBottomCursor
008FFA 2 60 rts
008FFB 2
008FFB 2
008FFB 2
008FFB 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
008FFB 2 ; WGAmpersand_FOCN
008FFB 2 ; Focuses next view
008FFB 2 ; &FOCN
008FFB 2 WGAmpersand_FOCN:
008FFB 2 20 82 87 jsr WGViewFocusNext
008FFE 2 20 9C 91 jsr WGBottomCursor
009001 2 60 rts
009002 2
009002 2
009002 2
009002 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
009002 2 ; WGAmpersand_FOCP
009002 2 ; Focuses previous view
009002 2 ; &FOCP
009002 2 WGAmpersand_FOCP:
009002 2 20 B3 87 jsr WGViewFocusPrev
009005 2 20 9C 91 jsr WGBottomCursor
009008 2 60 rts
009009 2
009009 2
009009 2
009009 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
009009 2 ; WGAmpersand_ACT
009009 2 ; Takes action on focused view
009009 2 ; &ACT
009009 2 WGAmpersand_ACT:
009009 2 20 2D 88 jsr WGViewFocusAction
00900C 2 20 9C 91 jsr WGBottomCursor
00900F 2
00900F 2 AD D0 92 lda WG_GOSUB
009012 2 D0 01 bne WGAmpersand_ACTGosub
009014 2 60 rts
009015 2
009015 2 WGAmpersand_ACTGosub:
009015 2 4C B9 91 jmp WGGosub ; No coming back from an Applesoft GOSUB!
009018 2
009018 2
009018 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
009018 2 ; WGAmpersand_STACT
009018 2 ; Sets the callback for the selected view
009018 2 ; &STACT(lineNum)
009018 2 WGAmpersand_STACT:
009018 2 20 46 8E jsr WGAmpersandBeginArguments
00901B 2
00901B 2 20 74 8E jsr WGAmpersandAddrArgument
00901E 2 86 06 stx PARAM0
009020 2 84 07 sty PARAM1
009022 2
009022 2 20 55 8E jsr WGAmpersandEndArguments
009025 2
009025 2 20 38 89 jsr WGViewSetAction
009028 2 60 rts
009029 2
009029 2
009029 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
009029 2 ; WGAmpersand_TITLE
009029 2 ; Sets the title for the selected view
009029 2 ; &TITLE("title")
009029 2 WGAmpersand_TITLE:
009029 2 20 46 8E jsr WGAmpersandBeginArguments
00902C 2
00902C 2 20 7F 8E jsr WGAmpersandStrArgument
00902F 2 86 06 stx PARAM0
009031 2 84 07 sty PARAM1
009033 2
009033 2 20 55 8E jsr WGAmpersandEndArguments
009036 2
009036 2 20 21 89 jsr WGViewSetTitle
009039 2 20 B6 85 jsr WGPaintView
00903C 2
00903C 2 60 rts
00903D 2
00903D 2
00903D 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
00903D 2 ; WGAmpersand_CURSR
00903D 2 ; Sets the cursor position in selected viewspace
00903D 2 ; &CURSR(x,y)
00903D 2 WGAmpersand_CURSR:
00903D 2 20 46 8E jsr WGAmpersandBeginArguments
009040 2
009040 2 20 5D 8E jsr WGAmpersandIntArgument
009043 2 85 06 sta PARAM0
009045 2 20 4E 8E jsr WGAmpersandNextArgument
009048 2
009048 2 20 5D 8E jsr WGAmpersandIntArgument
00904B 2 85 07 sta PARAM1
00904D 2
00904D 2 20 55 8E jsr WGAmpersandEndArguments
009050 2
009050 2 20 4F 89 jsr WGSetCursor
009053 2
009053 2 60 rts
009054 2
009054 2
009054 2
009054 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
009054 2 ; WGAmpersand_PRINT
009054 2 ; Prints a string in the selected view at the local cursor
009054 2 ; &PRINT("string")
009054 2 WGAmpersand_PRINT:
009054 2 20 46 8E jsr WGAmpersandBeginArguments
009057 2
009057 2 20 A4 8E jsr WGAmpersandTempStrArgument
00905A 2 86 06 stx PARAM0
00905C 2 84 07 sty PARAM1
00905E 2 48 pha
00905F 2
00905F 2 20 55 8E jsr WGAmpersandEndArguments
009062 2
009062 2 ; We're pointing to the string directly in the Applesoft
009062 2 ; source, so we need to NULL-terminate it for printing. In
009062 2 ; order to avoid copying the whole thing, we'll do something
009062 2 ; kinda dirty here.
009062 2 68 pla
009063 2 A8 tay
009064 2 B1 06 lda (PARAM0),y ; Cache the byte at the end of the string
009066 2 48 pha
009067 2
009067 2 A9 00 lda #0
009069 2 91 06 sta (PARAM0),y ; Null-terminate the string in-place
00906B 2
00906B 2 20 90 7F jsr WGPrint
00906E 2
00906E 2 68 pla
00906F 2 91 06 sta (PARAM0),y ; Put original byte back
009071 2
009071 2 60 rts
009072 2
009072 2
009072 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
009072 2 ; WGAmpersand_SCR
009072 2 ; Sets scroll position of selected view
009072 2 ; &SCR(x,y)
009072 2 WGAmpersand_SCR:
009072 2 20 46 8E jsr WGAmpersandBeginArguments
009075 2
009075 2 20 5D 8E jsr WGAmpersandIntArgument
009078 2 48 pha
009079 2 20 4E 8E jsr WGAmpersandNextArgument
00907C 2
00907C 2 20 5D 8E jsr WGAmpersandIntArgument
00907F 2 48 pha
009080 2
009080 2 20 55 8E jsr WGAmpersandEndArguments
009083 2
009083 2 68 pla
009084 2 20 E6 89 jsr WGScrollY
009087 2 68 pla
009088 2 20 92 89 jsr WGScrollX
00908B 2
00908B 2 60 rts
00908C 2
00908C 2
00908C 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
00908C 2 ; WGAmpersand_SCRBY
00908C 2 ; Adjusts scroll position of selected view by a delta
00908C 2 ; &SCRBY(x,y)
00908C 2 WGAmpersand_SCRBY:
00908C 2 20 46 8E jsr WGAmpersandBeginArguments
00908F 2
00908F 2 20 5D 8E jsr WGAmpersandIntArgument
009092 2 48 pha
009093 2 20 4E 8E jsr WGAmpersandNextArgument
009096 2
009096 2 20 5D 8E jsr WGAmpersandIntArgument
009099 2 48 pha
00909A 2
00909A 2 20 55 8E jsr WGAmpersandEndArguments
00909D 2
00909D 2 68 pla
00909E 2 20 F9 89 jsr WGScrollYBy
0090A1 2 68 pla
0090A2 2 20 A5 89 jsr WGScrollXBy
0090A5 2
0090A5 2 60 rts
0090A6 2
0090A6 2
0090A6 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0090A6 2 ; WGAmpersand_GOSUB
0090A6 2 ; A custom gosub, because we can. Only for testing at the moment
0090A6 2 ; &GOSUB
0090A6 2 WGAmpersand_GOSUB:
0090A6 2 A9 E8 lda #$e8
0090A8 2 85 06 sta PARAM0
0090AA 2 A9 03 lda #$03
0090AC 2 85 07 sta PARAM1
0090AE 2 4C B9 91 jmp WGGosub
0090B1 2
0090B1 2
0090B1 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0090B1 2 ; WGAmpersand_ERASE
0090B1 2 ; Erases the contents of the selected view
0090B1 2 ; &ERASE
0090B1 2 WGAmpersand_ERASE:
0090B1 2 20 16 87 jsr WGEraseViewContents
0090B4 2 20 9C 91 jsr WGBottomCursor
0090B7 2 60 rts
0090B8 2
0090B8 2
0090B8 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0090B8 2 ; WGAmpersand_FILL
0090B8 2 ; Fills a rectangle with a character
0090B8 2 ; &FILL(x,y,width,height,char)
0090B8 2 WGAmpersand_FILL:
0090B8 2 20 46 8E jsr WGAmpersandBeginArguments
0090BB 2
0090BB 2 20 5D 8E jsr WGAmpersandIntArgument
0090BE 2 85 06 sta PARAM0
0090C0 2 20 4E 8E jsr WGAmpersandNextArgument
0090C3 2
0090C3 2 20 5D 8E jsr WGAmpersandIntArgument
0090C6 2 85 07 sta PARAM1
0090C8 2 20 4E 8E jsr WGAmpersandNextArgument
0090CB 2
0090CB 2 20 5D 8E jsr WGAmpersandIntArgument
0090CE 2 85 08 sta PARAM2
0090D0 2 20 4E 8E jsr WGAmpersandNextArgument
0090D3 2
0090D3 2 20 5D 8E jsr WGAmpersandIntArgument
0090D6 2 85 09 sta PARAM3
0090D8 2 20 4E 8E jsr WGAmpersandNextArgument
0090DB 2
0090DB 2 20 5D 8E jsr WGAmpersandIntArgument
0090DE 2 09 80 ora #$80 ; Convert to Apple format
0090E0 2 48 pha
0090E1 2
0090E1 2 20 55 8E jsr WGAmpersandEndArguments
0090E4 2 7A ply
0090E5 2
0090E5 2 20 98 80 jsr WGFillRect
0090E8 2 20 9C 91 jsr WGBottomCursor
0090EB 2
0090EB 2 60 rts
0090EC 2
0090EC 2
0090EC 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0090EC 2 ; WGAmpersand_DRAW
0090EC 2 ; Strokes a rectangle with a character
0090EC 2 ; &DRAW(x,y,width,height)
0090EC 2 WGAmpersand_DRAW:
0090EC 2 20 46 8E jsr WGAmpersandBeginArguments
0090EF 2
0090EF 2 20 5D 8E jsr WGAmpersandIntArgument
0090F2 2 85 06 sta PARAM0
0090F4 2 20 4E 8E jsr WGAmpersandNextArgument
0090F7 2
0090F7 2 20 5D 8E jsr WGAmpersandIntArgument
0090FA 2 85 07 sta PARAM1
0090FC 2 20 4E 8E jsr WGAmpersandNextArgument
0090FF 2
0090FF 2 20 5D 8E jsr WGAmpersandIntArgument
009102 2 85 08 sta PARAM2
009104 2 20 4E 8E jsr WGAmpersandNextArgument
009107 2
009107 2 20 5D 8E jsr WGAmpersandIntArgument
00910A 2 85 09 sta PARAM3
00910C 2
00910C 2 20 55 8E jsr WGAmpersandEndArguments
00910F 2
00910F 2 20 24 81 jsr WGStrokeRect
009112 2 20 9C 91 jsr WGBottomCursor
009115 2
009115 2 60 rts
009116 2
009116 2
009116 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
009116 2 ; WGAmpersand_PNT
009116 2 ; Repaints the selected view
009116 2 ; &PNT
009116 2 WGAmpersand_PNT:
009116 2 20 B6 85 jsr WGPaintView
009119 2 20 9C 91 jsr WGBottomCursor
00911C 2 60 rts
00911D 2
00911D 2
00911D 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
00911D 2 ; WGAmpersand_PNTA
00911D 2 ; Repaints all views
00911D 2 ; &PNTA
00911D 2 WGAmpersand_PNTA:
00911D 2 20 3A 8A jsr WGViewPaintAll
009120 2 20 9C 91 jsr WGBottomCursor
009123 2 60 rts
009124 2
009124 2
009124 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
009124 2 ; WGAmpersand_PLOT
009124 2 ; Plots a single character (in Apple format)
009124 2 ; &PLOT(x,y,value)
009124 2 WGAmpersand_PLOT:
009124 2 20 46 8E jsr WGAmpersandBeginArguments
009127 2
009127 2 20 5D 8E jsr WGAmpersandIntArgument
00912A 2 8D C9 92 sta WG_CURSORX
00912D 2 20 4E 8E jsr WGAmpersandNextArgument
009130 2
009130 2 20 5D 8E jsr WGAmpersandIntArgument
009133 2 8D CA 92 sta WG_CURSORY
009136 2 20 4E 8E jsr WGAmpersandNextArgument
009139 2
009139 2 20 5D 8E jsr WGAmpersandIntArgument
00913C 2 48 pha
00913D 2
00913D 2 20 55 8E jsr WGAmpersandEndArguments
009140 2
009140 2 68 pla
009141 2 20 55 7F jsr WGPlot
009144 2 20 9C 91 jsr WGBottomCursor
009147 2
009147 2 60 rts
009148 2
009148 2
009148 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
009148 2 ; WGAmpersand_MOUSE
009148 2 ; Enable or disable the mouse
009148 2 ; &MOUSE(enable)
009148 2 WGAmpersand_MOUSE:
009148 2 20 46 8E jsr WGAmpersandBeginArguments
00914B 2 20 5D 8E jsr WGAmpersandIntArgument
00914E 2
00914E 2 48 pha
00914F 2 20 55 8E jsr WGAmpersandEndArguments
009152 2
009152 2 68 pla
009153 2 F0 04 beq WGAmpersand_MOUSEoff
009155 2 20 62 8B jsr WGEnableMouse
009158 2 60 rts
009159 2
009159 2 WGAmpersand_MOUSEoff:
009159 2 20 BE 8B jsr WGDisableMouse
00915C 2 60 rts
00915D 2
00915D 2
00915D 2
00915D 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
00915D 2 ; WGAmpersand_PDACT
00915D 2 ; Performs any pending view action
00915D 2 ; &PDACT
00915D 2 WGAmpersand_PDACT:
00915D 2 AD CF 92 lda WG_PENDINGACTIONVIEW
009160 2 30 06 bmi WGAmpersand_PDACTdone
009162 2
009162 2 20 97 88 jsr WGPendingViewAction
009165 2 20 9C 91 jsr WGBottomCursor
009168 2
009168 2 WGAmpersand_PDACTdone:
009168 2 AD D0 92 lda WG_GOSUB
00916B 2 D0 01 bne WGAmpersand_PDACTGosub
00916D 2 60 rts
00916E 2
00916E 2 WGAmpersand_PDACTGosub:
00916E 2 4C B9 91 jmp WGGosub ; No coming back from an Applesoft GOSUB!
009171 2
009171 2
009171 2
009171 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
009171 2 ; WGAmpersand_GET
009171 2 ; A non-blocking version of Applesoft GET. Returns 0 if no key
009171 2 ; is pending
009171 2 ; &GET(A$)
009171 2
009171 2 WGAmpersand_GET:
009171 2 20 46 8E jsr WGAmpersandBeginArguments
009174 2
009174 2 20 E3 DF jsr PTRGET
009177 2 AD 00 C0 lda KBD
00917A 2 10 07 bpl WGAmpersand_GETnone ; No key pending
00917C 2
00917C 2 8D 10 C0 sta KBDSTRB ; Clear strobe and high bit
00917F 2 29 7F and #%01111111
009181 2 80 02 bra WGAmpersand_GETstore
009183 2
009183 2 WGAmpersand_GETnone:
009183 2 A9 00 lda #0
009185 2
009185 2 WGAmpersand_GETstore:
009185 2 A0 00 ldy #0
009187 2
009187 2 8D 00 92 sta WG_KEYBUFFER ; Store the key
00918A 2 A9 01 lda #1 ; Create an Applesoft string record in the
00918C 2 91 83 sta (VARPNT),y ; variable's location
00918E 2 C8 iny
00918F 2 A9 00 lda #<WG_KEYBUFFER
009191 2 91 83 sta (VARPNT),y
009193 2 C8 iny
009194 2 A9 92 lda #>WG_KEYBUFFER
009196 2 91 83 sta (VARPNT),y
009198 2
009198 2 20 55 8E jsr WGAmpersandEndArguments
00919B 2 60 rts
00919C 2
00919C 2
00919C 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
00919C 2 ; WGBottomCursor
00919C 2 ; Leave the cursor state in a place that Applesoft is happy with
00919C 2 ;
00919C 2 WGBottomCursor:
00919C 2 48 5A SAVE_AY
00919E 2
00919E 2 A9 00 lda #0
0091A0 2 85 24 sta CH
0091A2 2 8D 7B 05 sta OURCH
0091A5 2 A9 17 lda #23
0091A7 2 85 25 sta CV
0091A9 2 8D FB 05 sta OURCV
0091AC 2
0091AC 2 AD EE 94 lda TEXTLINES_H+23
0091AF 2 85 29 sta BASH
0091B1 2 AD 06 95 lda TEXTLINES_L+23
0091B4 2 85 28 sta BASL
0091B6 2
0091B6 2 7A 68 RESTORE_AY
0091B8 2 60 rts
0091B9 2
0091B9 2
0091B9 2
0091B9 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0091B9 2 ; WGGosub
0091B9 2 ; Performs an Applesoft GOSUB to a line number
0091B9 2 ; PARAM0: Line number (LSB)
0091B9 2 ; PARAM1: Line number (MSB)
0091B9 2 ;
0091B9 2 WGGosub:
0091B9 2 A9 00 lda #0
0091BB 2 8D D0 92 sta WG_GOSUB ; Clear the flag
0091BE 2
0091BE 2 ; Can't come back from what we're about to do, so cleanup from the
0091BE 2 ; original Ampersand entry point now! This is some seriously voodoo
0091BE 2 ; shit we're gonna pull here.
0091BE 2 AE FF 91 ldx WG_STACKPTR
0091C1 2 9A txs
0091C2 2
0091C2 2 ; Fake an Applesoft GOSUB by pushing the same stuff it would do
0091C2 2 A5 B9 lda TXTPTRH
0091C4 2 48 pha
0091C5 2 A5 B8 lda TXTPTRL
0091C7 2 48 pha
0091C8 2 A5 76 lda CURLINH
0091CA 2 48 pha
0091CB 2 A5 75 lda CURLINL
0091CD 2 48 pha
0091CE 2 A9 B0 lda #TOKEN_GOSUB
0091D0 2 48 pha
0091D1 2
0091D1 2 ; Here's the tricky bit- we jump into Applesoft's GOTO
0091D1 2 ; just after the part where it reads the line number. This
0091D1 2 ; allows us to piggy back on the hard work of finding the
0091D1 2 ; line number in the Applesoft source code, and storing
0091D1 2 ; it in the TXTPTR (thus performing the jump portion of
0091D1 2 ; a GOSUB). Since GOSUB normally falls through into GOTO,
0091D1 2 ; by faking the setup portion of the GOSUB, then leaving
0091D1 2 ; the state as GOTO expects it, we can fake the entire
0091D1 2 ; process to GOSUB to a line number we specify
0091D1 2 A5 06 lda PARAM0
0091D3 2 85 50 sta LINNUML
0091D5 2 A5 07 lda PARAM1
0091D7 2 85 51 sta LINNUMH
0091D9 2
0091D9 2 20 41 D9 jsr GOTO+3
0091DC 2
0091DC 2 ; The goto has pointed the interpreter at the subroutine,
0091DC 2 ; so now advance to the next statement to continue executing.
0091DC 2 ; We'll never regain control, which is why we had to clean
0091DC 2 ; up from the ampersand entry before we got here.
0091DC 2 4C D2 D7 jmp NEWSTT
0091DF 2
0091DF 2
0091DF 2
0091DF 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0091DF 2 ; Applesoft API state
0091DF 2 ;
0091DF 2
0091DF 2 WGAmpersandCommandBuffer:
0091DF 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0091E3 2 00 00 00 00
0091E7 2 00 00 00 00
0091EF 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0091F3 2 00 00 00 00
0091F7 2 00 00 00 00
0091FE 2 WGAmpersandCommandBufferEnd:
0091FE 2 00 .byte 0 ; Make sure this last byte is always kept as a terminator
0091FF 2
0091FF 2 WG_STACKPTR: ; A place to save the stack pointer for tricky Applesoft manipulation
0091FF 2 00 .byte 0
009200 2
009200 2 WG_KEYBUFFER: ; A phony string buffer for non-blocking GET
009200 2 00 .byte 0
009201 2
009201 2
009201 2 ; Jump table for ampersand commands.
009201 2 ; Each row is 8 bytes (5 for name, NULL terminator, 2 for address)
009201 2 ;
009201 2 ; Note the strange constants in place of some strings- this is because
009201 2 ; all text is tokenized before we receive it, so reserved words may
009201 2 ; be compressed
009201 2 ;
009201 2 WGAmpersandCommandTable:
009201 2
009201 2 97 00 00 00 .byte TOKEN_HOME,0,0,0,0,0
009205 2 00 00
009207 2 CA 8E .addr WGAmpersand_HOME
009209 2
009209 2 44 45 53 4B .byte "DESK",0,0
00920D 2 00 00
00920F 2 D1 8E .addr WGAmpersand_DESK
009211 2
009211 2 57 49 4E 44 .byte "WINDW",0
009215 2 57 00
009217 2 D8 8E .addr WGAmpersand_WINDW
009219 2
009219 2 43 48 4B 42 .byte "CHKBX",0
00921D 2 58 00
00921F 2 3A 8F .addr WGAmpersand_CHKBX
009221 2
009221 2 42 55 54 54 .byte "BUTTN",0
009225 2 4E 00
009227 2 86 8F .addr WGAmpersand_BUTTN
009229 2
009229 2 53 45 4C 00 .byte "SEL",0,0,0
00922D 2 00 00
00922F 2 E7 8F .addr WGAmpersand_SEL
009231 2
009231 2 46 4F 43 00 .byte "FOC",0,0,0
009235 2 00 00
009237 2 F4 8F .addr WGAmpersand_FOC
009239 2
009239 2 46 4F 43 4E .byte "FOCN",0,0
00923D 2 00 00
00923F 2 FB 8F .addr WGAmpersand_FOCN
009241 2
009241 2 46 4F 43 50 .byte "FOCP",0,0
009245 2 00 00
009247 2 02 90 .addr WGAmpersand_FOCP
009249 2
009249 2 41 43 54 00 .byte "ACT",0,0,0
00924D 2 00 00
00924F 2 09 90 .addr WGAmpersand_ACT
009251 2
009251 2 53 54 41 43 .byte "STACT",0
009255 2 54 00
009257 2 18 90 .addr WGAmpersand_STACT
009259 2
009259 2 54 49 54 4C .byte "TITLE",0
00925D 2 45 00
00925F 2 29 90 .addr WGAmpersand_TITLE
009261 2
009261 2 43 55 52 53 .byte "CURSR",0
009265 2 52 00
009267 2 3D 90 .addr WGAmpersand_CURSR
009269 2
009269 2 53 43 52 00 .byte "SCR",0,0,0
00926D 2 00 00
00926F 2 72 90 .addr WGAmpersand_SCR
009271 2
009271 2 53 43 52 42 .byte "SCRBY",0
009275 2 59 00
009277 2 8C 90 .addr WGAmpersand_SCRBY
009279 2
009279 2 45 52 41 53 .byte "ERASE",0
00927D 2 45 00
00927F 2 B1 90 .addr WGAmpersand_ERASE
009281 2
009281 2 BA 00 00 00 .byte TOKEN_PRINT,0,0,0,0,0
009285 2 00 00
009287 2 54 90 .addr WGAmpersand_PRINT
009289 2
009289 2 46 49 4C 4C .byte "FILL",0,0
00928D 2 00 00
00928F 2 B8 90 .addr WGAmpersand_FILL
009291 2
009291 2 94 00 00 00 .byte TOKEN_DRAW,0,0,0,0,0
009295 2 00 00
009297 2 EC 90 .addr WGAmpersand_DRAW
009299 2
009299 2 50 4E 54 00 .byte "PNT",0,0,0
00929D 2 00 00
00929F 2 16 91 .addr WGAmpersand_PNT
0092A1 2
0092A1 2 50 4E 54 41 .byte "PNTA",0,0
0092A5 2 00 00
0092A7 2 1D 91 .addr WGAmpersand_PNTA
0092A9 2
0092A9 2 8D 00 00 00 .byte TOKEN_PLOT,0,0,0,0,0
0092AD 2 00 00
0092AF 2 24 91 .addr WGAmpersand_PLOT
0092B1 2
0092B1 2 4D 4F 55 53 .byte "MOUSE",0
0092B5 2 45 00
0092B7 2 48 91 .addr WGAmpersand_MOUSE
0092B9 2
0092B9 2 50 44 41 43 .byte "PDACT",0
0092BD 2 54 00
0092BF 2 5D 91 .addr WGAmpersand_PDACT
0092C1 2
0092C1 2 BE 00 00 00 .byte TOKEN_GET,0,0,0,0,0
0092C5 2 00 00
0092C7 2 71 91 .addr WGAmpersand_GET
0092C9 2
0092C9 2 ;.byte TOKEN_GOSUB,0,0,0,0,0,0,0,0,0,0,0,0,0 ; For internal testing of the procedural gosub
0092C9 2 ;.addr WGAmpersand_GOSUB
0092C9 2
0092C9 2
0092C9 2 WGAmpersandCommandTableEnd:
0092C9 2
0092C9 2
0092C9 1 .include "memory.s"
0092C9 2 ;
0092C9 2 ; memory.s
0092C9 2 ; Memory mapping information
0092C9 2 ;
0092C9 2 ; Created by Quinn Dunki on 8/15/14.
0092C9 2 ; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved.
0092C9 2 ;
0092C9 2
0092C9 2
0092C9 2 ; Constants
0092C9 2
0092C9 2 CHAR_NORMAL = $ff
0092C9 2 CHAR_INVERSE = $3f
0092C9 2 CHAR_FLASH = $7f
0092C9 2
0092C9 2 VIEW_STYLE_PLAIN = $00
0092C9 2 VIEW_STYLE_FANCY = $01
0092C9 2 VIEW_STYLE_CHECK = $02
0092C9 2 VIEW_STYLE_BUTTON = $03
0092C9 2
0092C9 2 VIEW_STYLE_TAKESFOCUS = $02 ; Styles >= this one are selectable
0092C9 2
0092C9 2 VIEW_STYLE_APPLESOFT = $80 ; High nybble flag bit for views created from Applesoft
0092C9 2
0092C9 2 IRQVECTORL = $03fe
0092C9 2 IRQVECTORH = $03ff
0092C9 2
0092C9 2 MEMBITMAP = $bf58 ; ProDOS 8 system memory allocation bitmap
0092C9 2
0092C9 2 ; ROM entry points
0092C9 2
0092C9 2 COUT = $fded
0092C9 2 BASCALC = $fbc1
0092C9 2 PRBYTE = $fdda
0092C9 2 RDKEY = $fd0c
0092C9 2 BELL = $fbdd
0092C9 2
0092C9 2
0092C9 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0092C9 2 ; System state
0092C9 2 ;
0092C9 2 WG_CURSORX: ; In screenspace
0092C9 2 00 .byte 0
0092CA 2 WG_CURSORY:
0092CA 2 00 .byte 0
0092CB 2
0092CB 2 WG_LOCALCURSORX: ; In current viewspace
0092CB 2 00 .byte 0
0092CC 2 WG_LOCALCURSORY:
0092CC 2 00 .byte 0
0092CD 2
0092CD 2 WG_ACTIVEVIEW:
0092CD 2 00 .byte 0
0092CE 2
0092CE 2 WG_FOCUSVIEW:
0092CE 2 00 .byte 0
0092CF 2
0092CF 2 WG_PENDINGACTIONVIEW:
0092CF 2 00 .byte 0
0092D0 2
0092D0 2 WG_GOSUB: ; Set if an Applesoft gosub was generated by a view action
0092D0 2 00 .byte 0
0092D1 2
0092D1 2 WG_VIEWCLIP:
0092D1 2 ; X0,Y0,X1,Y1. Edges of current window, in view space, right span
0092D1 2 00 00 00 00 .byte 0,0,0,0,0
0092D5 2 00
0092D6 2
0092D6 2 WG_VIEWRECORDS:
0092D6 2 ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13
0092D6 2 ; X, Y, Screen Width, Screen Height, Style, X Offset, Y Offset, View Width, View Height, State, CallbackL, CallbackH, TitleL, TitleH
0092D6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0092DA 2 00 00 00 00
0092DE 2 00 00 00 00
0092E6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0092EA 2 00 00 00 00
0092EE 2 00 00 00 00
0092F6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0092FA 2 00 00 00 00
0092FE 2 00 00 00 00
009306 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00930A 2 00 00 00 00
00930E 2 00 00 00 00
009316 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00931A 2 00 00 00 00
00931E 2 00 00 00 00
009326 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00932A 2 00 00 00 00
00932E 2 00 00 00 00
009336 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00933A 2 00 00 00 00
00933E 2 00 00 00 00
009346 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00934A 2 00 00 00 00
00934E 2 00 00 00 00
009356 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00935A 2 00 00 00 00
00935E 2 00 00 00 00
009366 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00936A 2 00 00 00 00
00936E 2 00 00 00 00
009376 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00937A 2 00 00 00 00
00937E 2 00 00 00 00
009386 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00938A 2 00 00 00 00
00938E 2 00 00 00 00
009396 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00939A 2 00 00 00 00
00939E 2 00 00 00 00
0093A6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0093AA 2 00 00 00 00
0093AE 2 00 00 00 00
0093B6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0093BA 2 00 00 00 00
0093BE 2 00 00 00 00
0093C6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0093CA 2 00 00 00 00
0093CE 2 00 00 00 00
0093D6 2
0093D6 2 WG_STRINGS: ; Fixed-size block allocator for strings (view titles, mainly)
0093D6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0093DA 2 00 00 00 00
0093DE 2 00 00 00 00
0093E6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0093EA 2 00 00 00 00
0093EE 2 00 00 00 00
0093F6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0093FA 2 00 00 00 00
0093FE 2 00 00 00 00
009406 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00940A 2 00 00 00 00
00940E 2 00 00 00 00
009416 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00941A 2 00 00 00 00
00941E 2 00 00 00 00
009426 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00942A 2 00 00 00 00
00942E 2 00 00 00 00
009436 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00943A 2 00 00 00 00
00943E 2 00 00 00 00
009446 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00944A 2 00 00 00 00
00944E 2 00 00 00 00
009456 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00945A 2 00 00 00 00
00945E 2 00 00 00 00
009466 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00946A 2 00 00 00 00
00946E 2 00 00 00 00
009476 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00947A 2 00 00 00 00
00947E 2 00 00 00 00
009486 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00948A 2 00 00 00 00
00948E 2 00 00 00 00
009496 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00949A 2 00 00 00 00
00949E 2 00 00 00 00
0094A6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0094AA 2 00 00 00 00
0094AE 2 00 00 00 00
0094B6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0094BA 2 00 00 00 00
0094BE 2 00 00 00 00
0094C6 2 00 00 00 00 .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0094CA 2 00 00 00 00
0094CE 2 00 00 00 00
0094D6 2
0094D6 2 WG_SCRATCHA:
0094D6 2 00 .byte 0
0094D7 2
0094D7 2
0094D7 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0094D7 2 ; Lookup tables
0094D7 2 ;
0094D7 2
0094D7 2 ; Video memory
0094D7 2 TEXTLINES_H:
0094D7 2 04 .byte $04 ;0
0094D8 2 04 .byte $04 ;1
0094D9 2 05 .byte $05 ;2
0094DA 2 05 .byte $05 ;3
0094DB 2 06 .byte $06 ;4
0094DC 2 06 .byte $06 ;5
0094DD 2 07 .byte $07 ;6
0094DE 2 07 .byte $07 ;7
0094DF 2 04 .byte $04 ;8
0094E0 2 04 .byte $04 ;9
0094E1 2 05 .byte $05 ;10
0094E2 2 05 .byte $05 ;11
0094E3 2 06 .byte $06 ;12
0094E4 2 06 .byte $06 ;13
0094E5 2 07 .byte $07 ;14
0094E6 2 07 .byte $07 ;15
0094E7 2 04 .byte $04 ;16
0094E8 2 04 .byte $04 ;17
0094E9 2 05 .byte $05 ;18
0094EA 2 05 .byte $05 ;19
0094EB 2 06 .byte $06 ;20
0094EC 2 06 .byte $06 ;21
0094ED 2 07 .byte $07 ;22
0094EE 2 07 .byte $07 ;23
0094EF 2
0094EF 2 TEXTLINES_L:
0094EF 2 00 .byte $00 ;0
0094F0 2 80 .byte $80 ;1
0094F1 2 00 .byte $00 ;2
0094F2 2 80 .byte $80 ;3
0094F3 2 00 .byte $00 ;4
0094F4 2 80 .byte $80 ;5
0094F5 2 00 .byte $00 ;6
0094F6 2 80 .byte $80 ;7
0094F7 2 28 .byte $28 ;8
0094F8 2 A8 .byte $a8 ;9
0094F9 2 28 .byte $28 ;10
0094FA 2 A8 .byte $a8 ;11
0094FB 2 28 .byte $28 ;12
0094FC 2 A8 .byte $a8 ;13
0094FD 2 28 .byte $28 ;14
0094FE 2 A8 .byte $a8 ;15
0094FF 2 50 .byte $50 ;16
009500 2 D0 .byte $d0 ;17
009501 2 50 .byte $50 ;18
009502 2 D0 .byte $d0 ;19
009503 2 50 .byte $50 ;20
009504 2 D0 .byte $d0 ;21
009505 2 50 .byte $50 ;22
009506 2 D0 .byte $d0 ;23
009507 2
009507 2
009507 1
009507 1
009507 1
009507 1 ; Suppress some linker warnings - Must be the last thing in the file
009507 1 .SEGMENT "ZPSAVE"
009507 1 .SEGMENT "EXEHDR"
009507 1 .SEGMENT "STARTUP"
009507 1 .SEGMENT "INIT"
009507 1 .SEGMENT "LOWCODE"
009507 1
009507 1