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 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 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 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 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