vnIIc/client/client.list

941 lines
46 KiB
Plaintext

ca65 V2.18 - Git 93b6efcb
Main file : client.s
Current file: client.s
000000r 1 ;;;-------------------------------------------------------------------
000000r 1 ;;;
000000r 1 ;;; vnIIc Client Application
000000r 1 ;;;
000000r 1 ;;;-------------------------------------------------------------------
000000r 1
000000r 1 PADDLE_SUPPORT = 0
000000r 1 MOUSE_SUPPORT = 0
000000r 1
000000r 1 .include "apple2.inc"
000000r 2
000000r 2 ;-----------------------------------------------------------------------------
000000r 2 ; Zero page stuff
000000r 2
000000r 2 WNDLFT := $20 ; Text window left
000000r 2 WNDWDTH := $21 ; Text window width
000000r 2 WNDTOP := $22 ; Text window top
000000r 2 WNDBTM := $23 ; Text window bottom+1
000000r 2 CH := $24 ; Cursor horizontal position
000000r 2 CV := $25 ; Cursor vertical position
000000r 2 BASL := $28 ; Text base address low
000000r 2 BASH := $29 ; Text base address high
000000r 2 INVFLG := $32 ; Normal/inverse(/flash)
000000r 2 PROMPT := $33 ; Used by GETLN
000000r 2 RNDL := $4E ; Random counter low
000000r 2 RNDH := $4F ; Random counter high
000000r 2 HIMEM := $73 ; Highest available memory address+1
000000r 2
000000r 2 ;-----------------------------------------------------------------------------
000000r 2 ; Vectors
000000r 2
000000r 2 DOSWARM := $03D0 ; DOS warmstart vector
000000r 2 BRKVec := $03F0 ; Break vector
000000r 2 SOFTEV := $03F2 ; Vector for warm start
000000r 2 PWREDUP := $03F4 ; This must be = EOR #$A5 of SOFTEV+1
000000r 2
000000r 2 ;-----------------------------------------------------------------------------
000000r 2 ; Hardware
000000r 2
000000r 2 ; Keyboard input
000000r 2 KBD := $C000 ; Read keyboard
000000r 2 KBDSTRB := $C010 ; Clear keyboard strobe
000000r 2
000000r 2 ; 80 column video switches
000000r 2 CLR80COL:= $C000 ; Disable 80 column store
000000r 2 SET80COL:= $C001 ; Enable 80 column store
000000r 2 RD80COL := $C018 ; >127 if 80 column store enabled
000000r 2 RD80VID := $C01F ; >127 if 80 column video enabled
000000r 2
000000r 2 ; Character set switches
000000r 2 CLRALTCHAR := $C00E ; Normal Apple II char set
000000r 2 SETALTCHAR := $C00F ; Norm/inv LC, no flash
000000r 2 ALTCHARSET := $C01E ; >127 if alt charset switched in
000000r 2
000000r 2 ; Language card switches
000000r 2 RDLCBNK2:= $C011 ; >127 if LC bank 2 in use
000000r 2 RDLCRAM := $C012 ; >127 if LC is read enabled
000000r 2 ROMIN := $C081 ; Swap in D000-FFFF ROM
000000r 2 LCBANK2 := $C083 ; Swap in LC bank 2
000000r 2 LCBANK1 := $C08B ; Swap in LC bank 1
000000r 2
000000r 2 ; Video mode switches
000000r 2 TXTCLR := $C050 ; Display graphics
000000r 2 TXTSET := $C051 ; Display text
000000r 2 MIXCLR := $C052 ; Disable 4 lines of text
000000r 2 MIXSET := $C053 ; Enable 4 lines of text
000000r 2 LOWSCR := $C054 ; Page 1
000000r 2 HISCR := $C055 ; Page 2
000000r 2 LORES := $C056 ; Lores graphics
000000r 2 HIRES := $C057 ; Hires graphics
000000r 2
000000r 2 ; Game controller
000000r 2 BUTN0 := $C061 ; Open-Apple Key
000000r 2 BUTN1 := $C062 ; Closed-Apple Key
000000r 2
000000r 1
000000r 1 .include "macros.inc"
000000r 2 ;;;---------------------------------------------------------
000000r 2 ;;;
000000r 2 ;;; Generic Macros
000000r 2 ;;;
000000r 2 ;;;---------------------------------------------------------
000000r 2
000000r 2 .macro SaveRegisters
000000r 2 pha
000000r 2 txa
000000r 2 pha
000000r 2 tya
000000r 2 pha
000000r 2 .endmacro
000000r 2
000000r 2 .macro RestoreRegisters
000000r 2 pla
000000r 2 tay
000000r 2 pla
000000r 2 tax
000000r 2 pla
000000r 2 .endmacro
000000r 2
000000r 1
000000r 1 ;;;---------------------------------------------------------
000000r 1 ;;; Hi-res graphics constants/locations
000000r 1 ;;;---------------------------------------------------------
000000r 1
000000r 1 PAGE := $E6 ; Active hires plotting page (Applesoft)
000000r 1 PAGE1 := $20
000000r 1 PAGE2 := $40
000000r 1
000000r 1 PAGESIZE := $20 ; Size of hi-res screen in pages
000000r 1
000000r 1 ;;;---------------------------------------------------------
000000r 1 ;;; I/O
000000r 1 ;;;---------------------------------------------------------
000000r 1
000000r 1 PADDL0 := $C064
000000r 1 PTRIG := $C070
000000r 1
000000r 1 ;;;---------------------------------------------------------
000000r 1 ;;; ROM routines
000000r 1 ;;;---------------------------------------------------------
000000r 1
000000r 1 HCLR := $F3F2 ; Clear current hires screen to black
000000r 1
000000r 1
000000r 1 ;;;---------------------------------------------------------
000000r 1 ;;; Other
000000r 1 ;;;---------------------------------------------------------
000000r 1
000000r 1 MAX_SLOT := 7 ; Maximum slot # on an Apple II
000000r 1
000000r 1 ;;;-------------------------------------------------------------------
000000r 1 ;;; Protocol:
000000r 1 ;;;-------------------------------------------------------------------
000000r 1
000000r 1 .proc Protocol
000000r 1 Keyboard := $00
000000r 1
000000r 1 Button0 := $10
000000r 1 Button1 := $11
000000r 1
000000r 1 Paddle0 := $20
000000r 1 Paddle1 := $21
000000r 1
000000r 1 MouseX := $30
000000r 1 MouseY := $31
000000r 1 MouseBtn := $32
000000r 1
000000r 1 Screen := $80
000000r 1 .endproc
000000r 1
000000r 1
000000r 1 ;;;-------------------------------------------------------------------
000000r 1 ;;;
000000r 1 ;;; Client Code
000000r 1 ;;;
000000r 1 ;;;-------------------------------------------------------------------
000000r 1
000000r 1 .org $6000
006000 1 4C 86 61 jmp AppEntry
006003 1
006003 1 .include "ssc.inc"
006003 2 ;;;-------------------------------------------------------------------
006003 2 ;;;
006003 2 ;;; Serial port routines
006003 2 ;;;
006003 2 ;;; (based on ADTPro)
006003 2 ;;;
006003 2 ;;;-------------------------------------------------------------------
006003 2
006003 2 .proc SSC
006003 2
006003 2 ;;;---------------------------------------------------------
006003 2 ;;; Super Serial constants/locations
006003 2 ;;;---------------------------------------------------------
006003 2
006003 2 ;;; These get incremented by the slot where they appear
006003 2 UACTRL = $C08B ; Control Register
006003 2 UACMND = $C08A ; Command Register
006003 2 UASTAT = $C089 ; Status Register
006003 2 UADATA = $C088 ; Data Register - incoming and outgoing data
006003 2
006003 2 ;;; Lookup table for UACTRL register, by baud rate
006003 2
006003 2 16 1E 1F 10 BPSCTRL: .byte $16,$1E,$1F,$10 ; 300, 9600, 19200, 115k (with 8 data bits, 1 stop bit, no echo)
006007 2 .enum
006007 2 BPS_300
006007 2 BPS_9600
006007 2 BPS_19200
006007 2 BPS_115k
006007 2 .endenum
006007 2
006007 2 CMND_NRDI = $0B ; Command: no parity, RTS on, DTR on, no interrupts
006007 2
006007 2
006007 2 ;;;---------------------------------------------------------
006007 2 ;;; Initialize the SSC; slot passed in A
006007 2
006007 2 .proc Init
006007 2 0A asl ; Slot passed in A
006008 2 0A asl
006009 2 0A asl
00600A 2 0A asl ; Now $S0
00600B 2 69 88 adc #$88 ; Low byte of UADATA
00600D 2 AA tax
00600E 2 A9 0B lda #CMND_NRDI ; Command register: no parity, RTS on, DTR on, no interrupts
006010 2 9D 02 C0 sta $C002,X
006013 2 AC 83 61 ldy PSPEED ; Control register: look up by baud rate (8 data bits, 1 stop bit)
006016 2 B9 03 60 lda BPSCTRL,Y
006019 2 9D 03 C0 sta $C003,X
00601C 2 8E 3A 60 stx MOD_UADATA_1 ; Modify references to
00601F 2 8E 45 60 stx MOD_UADATA_2 ; UADATA to point at
006022 2 8E 51 60 stx MOD_UADATA_3 ; correct slot (UADATA+S0)
006025 2 E8 inx
006026 2 8E 32 60 stx MOD_UASTAT_1 ; Modify reference to
006029 2 8E 3E 60 stx MOD_UASTAT_2 ; UASTAT to point at
00602C 2 8E 49 60 stx MOD_UASTAT_3 ; correct slot (UASTAT+S0)
00602F 2 60 rts
006030 2 .endproc
006030 2
006030 2
006030 2 ;;;---------------------------------------------------------
006030 2 ;;; Send accumulator out the serial port
006030 2
006030 2 .proc Put
006030 2 48 pha ; Push A onto the stack
006031 2 MOD_UASTAT_1 := *+1
006031 2 AD 89 C0 : lda UASTAT ; Check status bits
006034 2 29 10 and #$10
006036 2 F0 F9 beq :- ; Output register is full, so loop
006038 2 68 pla
006039 2 MOD_UADATA_1 := *+1
006039 2 8D 88 C0 sta UADATA ; Put character
00603C 2 60 rts
00603D 2 .endproc
00603D 2 MOD_UASTAT_1 := Put::MOD_UASTAT_1
00603D 2 MOD_UADATA_1 := Put::MOD_UADATA_1
00603D 2
00603D 2 ;;;---------------------------------------------------------
00603D 2 ;;; Read a character from the serial port to the accumulator
00603D 2
00603D 2 .proc Get
00603D 2 MOD_UASTAT_2 := *+1
00603D 2 AD 89 C0 lda UASTAT ; Check status bits
006040 2 29 08 and #$8
006042 2 F0 F9 beq Get ; Input register empty, loop
006044 2 MOD_UADATA_2 := *+1
006044 2 AD 88 C0 lda UADATA ; Get character
006047 2 60 rts
006048 2 .endproc
006048 2 MOD_UASTAT_2 := Get::MOD_UASTAT_2
006048 2 MOD_UADATA_2 := Get::MOD_UADATA_2
006048 2
006048 2 ;;;---------------------------------------------------------
006048 2 ;;; Check if the serial port has pending data
006048 2
006048 2 .proc HasData
006048 2 MOD_UASTAT_3 := *+1
006048 2 AD 89 C0 lda UASTAT ; Check status bits
00604B 2 29 68 and #$68
00604D 2 C9 08 cmp #$8
00604F 2 60 rts
006050 2 .endproc
006050 2 MOD_UASTAT_3 := HasData::MOD_UASTAT_3
006050 2
006050 2
006050 2 ;;;---------------------------------------------------------
006050 2 ;;; Clean up serial port
006050 2
006050 2 .proc Reset
006050 2 MOD_UADATA_3 := *+1
006050 2 2C 88 C0 bit UADATA
006053 2 60 rts
006054 2 .endproc
006054 2 MOD_UADATA_3 := Reset::MOD_UADATA_3
006054 2
006054 2 .endproc
006054 2
006054 1
006054 1 .ifdef MOUSE_SUPPORT
006054 1 .include "mouse.inc"
006054 2 ;;;-------------------------------------------------------------------
006054 2 ;;;
006054 2 ;;; Mouse
006054 2 ;;;
006054 2 ;;;-------------------------------------------------------------------
006054 2 ;; .error "Mouse support not fully implemented"
006054 2
006054 2 .proc Mouse
006054 2
006054 2 ;;;--------------------------------------------------
006054 2 ;;; Mouse Screen Holes
006054 2 ;;;--------------------------------------------------
006054 2
006054 2 ;;; For ReadMouse and PosMouse
006054 2
006054 2 MOUSE_X_LSB := $0478 ; + slot Low byte of X coordinate
006054 2 MOUSE_Y_LSB := $04F8 ; + slot Low byte of Y coordinate
006054 2 MOUSE_X_MSB := $0578 ; + slot High byte of X coordinate
006054 2 MOUSE_Y_MSB := $05F8 ; + slot High byte of Y coordinate
006054 2 MOUSE_RSV1 := $0678 ; + slot Reserved
006054 2 MOUSE_RSV2 := $06F8 ; + slot Reserved
006054 2 MOUSE_STATUS := $0778 ; + slot Status byte
006054 2 ;; 7 Button down
006054 2 ;; 6 Button was down on last read and still down
006054 2 ;; 5 Movement since last read
006054 2 ;; 4 Reserved
006054 2 ;; 3 Interrupt from VBlInt
006054 2 ;; 2 Interrupt from button
006054 2 ;; 1 Interrupt from movement
006054 2 ;; 0 Reserved
006054 2 MOUSE_MODE := $07F8 ; + slot Mode byte
006054 2 ;; 7-4 Reserved
006054 2 ;; 3 VBlInt active
006054 2 ;; 2 VBL interrupt on button
006054 2 ;; 1 VBL interrupt on movement
006054 2 ;; 0 Mouse active
006054 2
006054 2 ;;; Scratch area for ClampMouse:
006054 2
006054 2 MOUSE_CMIN_LSB := $0478 ; Low byte of clamping minimum
006054 2 MOUSE_CMAX_LSB := $04F8 ; Low byte of clamping maximum
006054 2 MOUSE_CMIN_MSB := $0578 ; High byte of clamping minimum
006054 2 MOUSE_CMAX_MSB := $05F8 ; High byte of clamping maximum
006054 2
006054 2 ;;;--------------------------------------------------
006054 2 ;;; Mouse Constants
006054 2 ;;;--------------------------------------------------
006054 2
006054 2 MOUSE_CLAMP_X := 0 ; Value for A when setting X clamp with ClampMouse
006054 2 MOUSE_CLAMP_Y := 1 ; Value for A when setting X clamp with ClampMouse
006054 2
006054 2 ;;; Mouse ID bytes
006054 2 MOUSEID_MAX := 4
006054 2 05 07 0B 0C MOUSEID_ADDR: .byte $05, $07, $0b, $0c, $fb
006058 2 FB
006059 2 38 18 01 20 MOUSEID_VAL: .byte $38, $18, $01, $20, $d6
00605D 2 D6
00605E 2
00605E 2 SLOT_BASE := $C000
00605E 2
00605E 2 ;;;--------------------------------------------------
00605E 2 ;;; Mouse firmware routine
00605E 2 ;;;--------------------------------------------------
00605E 2
00605E 2 SetMouse := $12 ; A=mode; C=0 on success
00605E 2 ServeMouse := $13 ; C=0 mouse interrupt, C=1 other
00605E 2 ReadMouse := $14
00605E 2 ClearMouse := $15
00605E 2 PosMouse := $16
00605E 2 ClampMouse := $17
00605E 2 HomeMouse := $18
00605E 2 InitMouse := $19
00605E 2
00605E 2 .macro MOUSE_CALL routine
00605E 2 ldy routine
00605E 2 jmp CallMouse
00605E 2 .endmacro
00605E 2
00605E 2 ;;;--------------------------------------------------
00605E 2 ;;; Data
00605E 2 ;;;--------------------------------------------------
00605E 2
00605E 2 ;;; Mouse
00605E 2 00 mouse_slot: .byte 0 ; mouse slot, or 0 if none
00605F 2 00 mouse_fw_hi: .byte 0 ; mouse slot as $Cn
006060 2 00 mouse_op: .byte 0 ; mouse slot as $n0
006061 2
006061 2 mouse_ptr := $EB ; Zero page location
006061 2
006061 2 ;;;--------------------------------------------------
006061 2 ;;; Routines
006061 2 ;;;--------------------------------------------------
006061 2
006061 2
006061 2 MOUSE_CLAMP_MIN := $10
006061 2 MOUSE_CLAMP_MAX := $1F
006061 2 MOUSE_CENTER := $17
006061 2 MOUSE_POS_MASK := $0F
006061 2
006061 2
006061 2 ;;;--------------------------------------------------
006061 2 ;;; Macros for common mouse operations
006061 2 ;;;--------------------------------------------------
006061 2
006061 2 ;;;----------------------------------------
006061 2 .macro DoClampMouse axis, min, max
006061 2 ;;;----------------------------------------
006061 2 ;;; axis: MOUSE_CLAMP_X or MOUSE_CLAMP_Y
006061 2 ;;; min: minimum value (2 byte)
006061 2 ;;; max: maximum value (2 byte)
006061 2 ;;;----------------------------------------
006061 2 lda #<min
006061 2 sta MOUSE_CMIN_LSB
006061 2 lda #>min
006061 2 sta MOUSE_CMIN_MSB
006061 2 lda #<max
006061 2 sta MOUSE_CMAX_LSB
006061 2 lda #>max
006061 2 sta MOUSE_CMAX_MSB
006061 2 lda #axis
006061 2 MOUSE_CALL ClampMouse
006061 2 .endmacro
006061 2
006061 2 ;;;----------------------------------------
006061 2 .macro DoPosMouse px, py
006061 2 ;;;----------------------------------------
006061 2 ldx mouse_slot
006061 2 lda #<px
006061 2 sta MOUSE_X_LSB,x
006061 2 lda #>px
006061 2 sta MOUSE_X_MSB,x
006061 2 lda #<py
006061 2 sta MOUSE_Y_LSB,x
006061 2 lda #>py
006061 2 sta MOUSE_Y_MSB,x
006061 2 MOUSE_CALL PosMouse
006061 2 .endmacro
006061 2
006061 2 ;;;----------------------------------------
006061 2 .macro DoSetMouse mode
006061 2 ;;;----------------------------------------
006061 2 lda #mode
006061 2 MOUSE_CALL SetMouse
006061 2 .endmacro
006061 2
006061 2
006061 2 ;;;---------------------------------------------------------
006061 2 ;;; Find and initialize the mouse port
006061 2
006061 2 .proc FindMouse
006061 2
006061 2 ;;; Reference: http://home.swbell.net/rubywand/R034MOUSEPRG.TXT
006061 2
006061 2 78 sei ; No interrupts while we're getting set up
006062 2
006062 2 ;; Find mouse card by scanning slots for ID bytes
006062 2
006062 2 A0 07 ldy #MAX_SLOT ; Start search in slot 7
006064 2
006064 2 slot_loop:
006064 2 8C 5E 60 sty mouse_slot ; Save for later
006067 2 98 tya
006068 2 18 clc
006069 2 69 C0 adc #>SLOT_BASE ; Firmware is $Cn
00606B 2 8D 78 60 sta slot_addr + 1 ; Update msb of signature test
00606E 2 A2 04 ldx #MOUSEID_MAX ; This many signature bytes
006070 2
006070 2 BD 54 60 : lda MOUSEID_ADDR,x
006073 2 8D 77 60 sta slot_addr ; Update lsb of signature test
006076 2
006076 2 slot_addr := *+1
006076 2 AD 00 C0 lda SLOT_BASE ; Self-modified
006079 2 DD 59 60 cmp MOUSEID_VAL,x ; Does it match the signature?
00607C 2 D0 06 bne no_match ; Nope - try the next slot
00607E 2 CA dex ; Yes! Keep testing
00607F 2 10 EF bpl :- ; Fall through if all done
006081 2 4C 8B 60 jmp found
006084 2
006084 2 no_match:
006084 2 88 dey ; Didn't match
006085 2 D0 DD bne slot_loop ; Keep looking until slot 0
006087 2 8C 5E 60 sty mouse_slot ; Oops, no mouse - make a note
00608A 2 60 rts ; and bail
00608B 2
00608B 2 ;; Store results needed for call ($Cn and $n0)
00608B 2
00608B 2 98 found: tya ; Slot is in y
00608C 2 09 C0 ora #>SLOT_BASE ; Compute $Cn - needed for calls
00608E 2 8D 5F 60 sta mouse_fw_hi
006091 2
006091 2 98 tya
006092 2 0A asl ; Compute $n0 - needed for calls
006093 2 0A asl
006094 2 0A asl
006095 2 0A asl
006096 2 8D 60 60 sta mouse_op
006099 2
006099 2 ;; Initialize and configure mouse card
006099 2
006099 2 A4 19 4C F9 MOUSE_CALL InitMouse ; reset, clamp to 0-1023 x/y
00609D 2 60
00609E 2
00609E 2 A9 01 A4 12 DoSetMouse $01 ; mouse on, no interrupts
0060A2 2 4C F9 60
0060A5 2 ; TODO: test carry bit result (set = error)
0060A5 2
0060A5 2 ;; Clamp for deltas
0060A5 2 A9 10 8D 78 DoClampMouse MOUSE_CLAMP_X, MOUSE_CLAMP_MIN, MOUSE_CLAMP_MAX
0060A9 2 04 A9 00 8D
0060AD 2 78 05 A9 1F
0060B1 2 8D F8 04 A9
0060B5 2 00 8D F8 05
0060B9 2 A9 00 A4 17
0060BD 2 4C F9 60
0060C0 2 A9 10 8D 78 DoClampMouse MOUSE_CLAMP_Y, MOUSE_CLAMP_MIN, MOUSE_CLAMP_MAX
0060C4 2 04 A9 00 8D
0060C8 2 78 05 A9 1F
0060CC 2 8D F8 04 A9
0060D0 2 00 8D F8 05
0060D4 2 A9 01 A4 17
0060D8 2 4C F9 60
0060DB 2
0060DB 2 AE 5E 60 A9 DoPosMouse MOUSE_CENTER, MOUSE_CENTER
0060DF 2 17 9D 78 04
0060E3 2 A9 00 9D 78
0060E7 2 05 A9 17 9D
0060EB 2 F8 04 A9 00
0060EF 2 9D F8 05 A4
0060F3 2 16 4C F9 60
0060F7 2
0060F7 2 58 cli ; Enable interrupts so mouse can function
0060F8 2
0060F8 2 60 rts
0060F9 2 .endproc
0060F9 2
0060F9 2 ;;;--------------------------------------------------
0060F9 2 ;;; Call mouse firmware, param in A, routine in Y
0060F9 2
0060F9 2 .proc CallMouse
0060F9 2 48 pha ; Save A (param)
0060FA 2 AE 5F 60 ldx mouse_fw_hi ; $Cn
0060FD 2 86 EC stx mouse_ptr+1
0060FF 2 A9 00 lda #0
006101 2 85 EB sta mouse_ptr
006103 2 B1 EB lda (mouse_ptr),y ; Look up routine offset
006105 2 85 EB sta mouse_ptr
006107 2
006107 2 68 pla ; param in A
006108 2 AC 60 60 ldy mouse_op ; $n0 in Y
00610B 2
00610B 2 08 php
00610C 2 78 sei
00610D 2 20 12 61 jsr call
006110 2 28 plp
006111 2 60 rts
006112 2
006112 2 6C EB 00 call: jmp (mouse_ptr)
006115 2 .endproc
006115 2
006115 2 ;;;--------------------------------------------------
006115 2 ;;; Read mouse pos, send deltas, and recenter
006115 2
006115 2 .proc SendMouse
006115 2 48 8A 48 98 SaveRegisters
006119 2 48
00611A 2 AD 5E 60 lda mouse_slot
00611D 2 F0 5E beq done
00611F 2
00611F 2 A4 14 4C F9 MOUSE_CALL ReadMouse
006123 2 60
006124 2
006124 2 A5 30 lda Protocol::MouseX
006126 2 20 30 60 jsr SSC::Put
006129 2 A9 01 lda #1 ; Data size
00612B 2 20 30 60 jsr SSC::Put
00612E 2 AE 5E 60 ldx mouse_slot
006131 2 BD 78 04 lda MOUSE_X_LSB,x
006134 2 05 0F ora MOUSE_POS_MASK
006136 2 20 30 60 jsr SSC::Put
006139 2
006139 2 A5 31 lda Protocol::MouseY
00613B 2 20 30 60 jsr SSC::Put
00613E 2 A9 01 lda #1 ; Data size
006140 2 20 30 60 jsr SSC::Put
006143 2 AE 5E 60 ldx mouse_slot
006146 2 BD F8 04 lda MOUSE_Y_LSB,x
006149 2 05 0F ora MOUSE_POS_MASK
00614B 2 20 30 60 jsr SSC::Put
00614E 2
00614E 2 A5 32 lda Protocol::MouseBtn
006150 2 20 30 60 jsr SSC::Put
006153 2 A9 01 lda #1 ; Data size
006155 2 20 30 60 jsr SSC::Put
006158 2 AE 5E 60 ldx mouse_slot
00615B 2 BD 78 07 lda MOUSE_STATUS,x
00615E 2 20 30 60 jsr SSC::Put
006161 2
006161 2 AE 5E 60 A9 DoPosMouse MOUSE_CENTER, MOUSE_CENTER
006165 2 17 9D 78 04
006169 2 A9 00 9D 78
00616D 2 05 A9 17 9D
006171 2 F8 04 A9 00
006175 2 9D F8 05 A4
006179 2 16 4C F9 60
00617D 2
00617D 2 68 A8 68 AA done: RestoreRegisters
006181 2 68
006182 2 60 rts
006183 2 .endproc
006183 2
006183 2 .endproc
006183 2
006183 1 .endif
006183 1
006183 1
006183 1 ;;;-------------------------------------------------------------------
006183 1 ;;; Variables
006183 1 ;;;-------------------------------------------------------------------
006183 1
006183 1 ;;; Application configuration
006183 1 03 PSPEED: .byte SSC::BPS_115k ; Hardcoded for Apple IIc (TODO: Allow configuration)
006184 1 02 PSLOT: .byte 2 ; Hardcoded for Apple IIc (TODO: Allow configuration)
006185 1 00 PEXIT: .byte 0 ; Set when it's time to exit (Not Yet Implemented)
006186 1
006186 1
006186 1 ;;;---------------------------------------------------------
006186 1 ;;; Initialize the application, and enter the main loop
006186 1
006186 1 .proc AppEntry
006186 1 AD 84 61 lda PSLOT ; Use slot 2
006189 1 20 07 60 jsr SSC::Init ; Initialize Super Serial Card
00618C 1 20 8E 62 jsr InitHires ; Initialize Hi-Res graphics
00618F 1 20 ED 61 jsr InitInput ; Initialize input devices
006192 1 20 9F 61 jsr MainLoop
006195 1 ;; fall through
006195 1 .endproc
006195 1
006195 1 ;;;---------------------------------------------------------
006195 1 ;;; Clean up and exit app
006195 1
006195 1 .proc AppExit
006195 1 20 50 60 jsr SSC::Reset
006198 1 8D 54 C0 sta LOWSCR
00619B 1 8D 51 C0 sta TXTSET
00619E 1 60 rts
00619F 1 .endproc
00619F 1
00619F 1 ;;;-------------------------------------------------------------------
00619F 1 ;;;
00619F 1 ;;; Main loop functionality
00619F 1 ;;;
00619F 1 ;;;-------------------------------------------------------------------
00619F 1
00619F 1
00619F 1 ;;;---------------------------------------------------------
00619F 1 .proc MainLoop
00619F 1
00619F 1 ;; Handle splash image - sent without preamble
00619F 1 20 AF 61 jsr ReceivePage
0061A2 1 20 A6 62 jsr FlipHires
0061A5 1
0061A5 1
0061A5 1 ;;; TODO: Sort out the protocol - should be able to send
0061A5 1 ;;; input state without receiving data
0061A5 1 ;;; jsr SSC::HasData ; Anything to read?
0061A5 1 ;;; bne :+ ; Nope
0061A5 1
0061A5 1 20 C9 61 : jsr RequestPage
0061A8 1 20 A6 62 jsr FlipHires
0061AB 1
0061AB 1 4C A5 61 jmp :- ; TODO: define an exit trigger
0061AE 1 60 rts
0061AF 1 .endproc
0061AF 1
0061AF 1
0061AF 1 ;;;---------------------------------------------------------
0061AF 1 ;;; Receive a hires page; no input sent.
0061AF 1 ;;;
0061AF 1
0061AF 1 .proc ReceivePage
0061AF 1
0061AF 1 ptr := $FA
0061AF 1
0061AF 1 A9 00 lda #0 ; set up write pointer
0061B1 1 85 FA sta ptr
0061B3 1 A5 E6 lda PAGE
0061B5 1 85 FB sta ptr+1
0061B7 1 A2 20 ldx #PAGESIZE ; plan to receive this many pages
0061B9 1 A0 00 ldy #0
0061BB 1
0061BB 1 20 3D 60 : jsr SSC::Get
0061BE 1 91 FA sta (ptr),Y
0061C0 1
0061C0 1 C8 iny
0061C1 1 D0 F8 bne :- ; Do a full page...
0061C3 1
0061C3 1 E6 FB inc ptr+1
0061C5 1 CA dex
0061C6 1 D0 F3 bne :- ; ...as many pages as we need
0061C8 1 60 rts
0061C9 1 .endproc
0061C9 1
0061C9 1 ;;;---------------------------------------------------------
0061C9 1 ;;; Request a hires page, sending input state along every
0061C9 1 ;;; 256 bytes.
0061C9 1 ;;;
0061C9 1
0061C9 1 .proc RequestPage
0061C9 1
0061C9 1 ptr := $FA
0061C9 1
0061C9 1 A9 80 lda #Protocol::Screen
0061CB 1 20 30 60 jsr SSC::Put
0061CE 1 A9 00 lda #0 ; data size
0061D0 1 20 30 60 jsr SSC::Put
0061D3 1
0061D3 1 A9 00 lda #0 ; set up write pointer
0061D5 1 85 FA sta ptr
0061D7 1 A5 E6 lda PAGE
0061D9 1 85 FB sta ptr+1
0061DB 1 A2 20 ldx #PAGESIZE ; plan to receive this many pages
0061DD 1 A0 00 ldy #0
0061DF 1
0061DF 1 20 3D 60 : jsr SSC::Get
0061E2 1 91 FA sta (ptr),Y
0061E4 1
0061E4 1 C8 iny
0061E5 1 D0 F8 bne :- ; Do a full page...
0061E7 1
0061E7 1 ;; Interleave to maintain responsiveness
0061E7 1 .if 0
0061E7 1 jsr SendInputState
0061E7 1 .endif
0061E7 1
0061E7 1 E6 FB inc ptr+1
0061E9 1 CA dex
0061EA 1 D0 F3 bne :- ; ...as many pages as we need
0061EC 1 60 rts
0061ED 1 .endproc
0061ED 1
0061ED 1
0061ED 1 ;;;-------------------------------------------------------------------
0061ED 1 ;;;
0061ED 1 ;;; Input device routines
0061ED 1 ;;;
0061ED 1 ;;;-------------------------------------------------------------------
0061ED 1
0061ED 1 ;;;---------------------------------------------------------
0061ED 1 ;;; Initialize input devices and storage for detecting
0061ED 1 ;;; state transitions
0061ED 1
0061ED 1 .proc InitInput
0061ED 1
0061ED 1 .ifdef MOUSE_SUPPORT
0061ED 1 20 61 60 jsr Mouse::FindMouse
0061F0 1 .endif
0061F0 1
0061F0 1 60 rts
0061F1 1 .endproc
0061F1 1
0061F1 1
0061F1 1 ;;;---------------------------------------------------------
0061F1 1 ;;; Send a full set of input state updates.
0061F1 1
0061F1 1 ;;; Assumes time to transmit is roughly comparable to time
0061F1 1 ;;; to measure input state, therefore only sending changes is
0061F1 1 ;;; not worthwhile in most cases.
0061F1 1
0061F1 1 .proc SendInputState
0061F1 1 20 FE 61 jsr MaybeSendKeyboard
0061F4 1 20 31 62 jsr SendButtons
0061F7 1
0061F7 1 .ifdef PADDLE_SUPPORT
0061F7 1 20 52 62 jsr SendPaddles
0061FA 1 .endif
0061FA 1
0061FA 1 .ifdef MOUSE_SUPPORT
0061FA 1 20 15 61 jsr Mouse::SendMouse
0061FD 1 .endif
0061FD 1
0061FD 1 .endproc
0061FD 1
0061FD 1
0061FD 1 ;;;------------------------------------------------------------
0061FD 1 ;;; Keyboard
0061FD 1
0061FD 1 ;;; NOTE: Can't use KBDSTRB to detect key up -> key down transition
0061FD 1 ;;; since the msb can change before the key code. Instead, consider
0061FD 1 ;;; these cases:
0061FD 1 ;;;
0061FD 1 ;;; OLD STATE KBD KBDSTRB RESULT
0061FD 1 ;;; Up Up - No-op
0061FD 1 ;;; Up Down - Save and send key down
0061FD 1 ;;; Down - Up Save and send key up
0061FD 1 ;;; Down - Down Save and send key ONLY if different
0061FD 1 ;;;
0061FD 1
0061FD 1 00 last_kb: .byte 0
0061FE 1
0061FE 1 .proc MaybeSendKeyboard
0061FE 1 AD FD 61 lda last_kb
006201 1 D0 08 bne key_was_down
006203 1
006203 1 key_was_up:
006203 1 ;; Key was up - send only if now down.
006203 1 AD 00 C0 lda KBD ; Read keyboard
006206 1 10 28 bpl done ; Do nothing if it is still up.
006208 1 4C 1D 62 jmp send ; Otherwise send.
00620B 1
00620B 1 key_was_down:
00620B 1 ;; Key was down - strobe should match
00620B 1 ;; unless the key changed or was released.
00620B 1 AD 10 C0 lda KBDSTRB
00620E 1 30 05 bmi kbdstrb_down
006210 1
006210 1 kbdstrb_up:
006210 1 A9 00 lda #0 ; Now released
006212 1 4C 1D 62 jmp send
006215 1
006215 1 kbdstrb_down:
006215 1 CD FD 61 cmp last_kb ; Same key as last time?
006218 1 F0 16 beq done ; - no change, don't send.
00621A 1 4C 1D 62 jmp send
00621D 1
00621D 1 8D FD 61 send: sta last_kb
006220 1 A5 00 lda Protocol::Keyboard
006222 1 20 30 60 jsr SSC::Put
006225 1 A9 01 lda #1 ; Data size
006227 1 20 30 60 jsr SSC::Put
00622A 1 AD FD 61 lda last_kb
00622D 1 20 30 60 jsr SSC::Put
006230 1
006230 1 60 done: rts
006231 1 .endproc
006231 1
006231 1 ;;;------------------------------------------------------------
006231 1 ;;; Buttons
006231 1
006231 1 .proc SendButtons
006231 1
006231 1 A5 10 lda Protocol::Button0
006233 1 20 30 60 jsr SSC::Put
006236 1 A9 01 lda #1 ; Data size
006238 1 20 30 60 jsr SSC::Put
00623B 1 AD 61 C0 lda BUTN0
00623E 1 20 30 60 jsr SSC::Put
006241 1
006241 1 A5 11 lda Protocol::Button1
006243 1 20 30 60 jsr SSC::Put
006246 1 A9 01 lda #1 ; Data size
006248 1 20 30 60 jsr SSC::Put
00624B 1 AD 62 C0 lda BUTN1
00624E 1 20 30 60 jsr SSC::Put
006251 1
006251 1 60 rts
006252 1 .endproc
006252 1
006252 1 ;;;------------------------------------------------------------
006252 1 ;;; Paddles
006252 1
006252 1 .ifdef PADDLE_SUPPORT
006252 1 .proc SendPaddles
006252 1
006252 1 A5 20 lda Protocol::Paddle0
006254 1 20 30 60 jsr SSC::Put
006257 1 A9 01 lda #1 ; Data size
006259 1 20 30 60 jsr SSC::Put
00625C 1
00625C 1 A2 00 ldx #0
00625E 1 20 79 62 jsr pread
006261 1 98 tya
006262 1 20 30 60 jsr SSC::Put
006265 1
006265 1 ;; Need to wait 3ms between reads.
006265 1
006265 1 A5 21 lda Protocol::Paddle1
006267 1 20 30 60 jsr SSC::Put
00626A 1 A9 01 lda #1 ; Data size
00626C 1 20 30 60 jsr SSC::Put
00626F 1
00626F 1 A2 01 ldx #1
006271 1 20 79 62 jsr pread
006274 1 98 tya
006275 1 20 30 60 jsr SSC::Put
006278 1
006278 1 60 rts
006279 1
006279 1 .proc pread
006279 1 ;; Let any previous timer reset
006279 1 BD 64 C0 : lda PADDL0,x
00627C 1 30 FB bmi :-
00627E 1
00627E 1 ;; Read paddle
00627E 1 AD 70 C0 lda PTRIG
006281 1 A0 00 ldy #0
006283 1 EA nop
006284 1 EA nop
006285 1 BD 64 C0 : lda PADDL0,X
006288 1 10 03 bpl done
00628A 1 C8 iny
00628B 1 D0 F8 bne :-
00628D 1 60 done: rts
00628E 1 .endproc
00628E 1
00628E 1 .endproc
00628E 1 .endif
00628E 1
00628E 1 ;;;-------------------------------------------------------------------
00628E 1 ;;;
00628E 1 ;;; Hi-res graphics routines
00628E 1 ;;;
00628E 1 ;;;-------------------------------------------------------------------
00628E 1
00628E 1 ;;;---------------------------------------------------------
00628E 1 ;;; Set up the graphics display and pointers
00628E 1
00628E 1 .proc InitHires
00628E 1 A9 20 lda #PAGE1 ; clear page 1
006290 1 85 E6 sta PAGE
006292 1 20 F2 F3 jsr HCLR
006295 1
006295 1 ;; Show page 1
006295 1 8D 57 C0 sta HIRES
006298 1 8D 50 C0 sta TXTCLR
00629B 1 8D 52 C0 sta MIXCLR
00629E 1 8D 54 C0 sta LOWSCR
0062A1 1
0062A1 1 ;; And set up writing to page 2
0062A1 1 A9 40 lda #PAGE2
0062A3 1 85 E6 sta PAGE
0062A5 1
0062A5 1 60 rts
0062A6 1 .endproc
0062A6 1
0062A6 1
0062A6 1 ;;;---------------------------------------------------------
0062A6 1 ;;; Call when done with the current plotting page
0062A6 1 ;;; (selected in PAGE) and it will be shown and the
0062A6 1 ;;; other page will be shown.
0062A6 1
0062A6 1 .proc FlipHires
0062A6 1 A5 E6 lda PAGE ; plotting on which page?
0062A8 1 C9 20 cmp #PAGE1
0062AA 1 F0 08 beq :+
0062AC 1
0062AC 1 8D 55 C0 sta HISCR ; page 2 - so show it
0062AF 1 A9 20 lda #PAGE1 ; and plot on page 1
0062B1 1 85 E6 sta PAGE
0062B3 1 60 rts
0062B4 1
0062B4 1 8D 54 C0 : sta LOWSCR ; page 1 - so show it
0062B7 1 A9 40 lda #PAGE2 ; and plot on page 2
0062B9 1 85 E6 sta PAGE
0062BB 1 60 rts
0062BC 1 .endproc
0062BC 1