diff --git a/client/client.bin b/client/client.bin index e1bdde6..b6b3ed0 100644 Binary files a/client/client.bin and b/client/client.bin differ diff --git a/client/client.list b/client/client.list index 6a6ad01..c62d7d4 100644 --- a/client/client.list +++ b/client/client.list @@ -9,7 +9,7 @@ Current file: client.s 000000r 1 ;;;------------------------------------------------------------------- 000000r 1 000000r 1 PADDLE_SUPPORT = 1 -000000r 1 ;;; MOUSE_SUPPORT = 1 +000000r 1 MOUSE_SUPPORT = 1 000000r 1 000000r 1 .include "apple2.inc" 000000r 2 @@ -127,8 +127,6 @@ Current file: client.s 000000r 1 000000r 1 MAX_SLOT := 7 ; Maximum slot # on an Apple II 000000r 1 -000000r 1 ZP_PTR := $FA ; Write cursor location on zero page -000000r 1 000000r 1 ;;;------------------------------------------------------------------- 000000r 1 ;;; Protocol: 000000r 1 ;;;------------------------------------------------------------------- @@ -157,7 +155,7 @@ Current file: client.s 000000r 1 ;;;------------------------------------------------------------------- 000000r 1 000000r 1 .org $6000 -006000 1 4C 5B 60 jmp AppEntry +006000 1 4C 8A 61 jmp AppEntry 006003 1 006003 1 .include "ssc.inc" 006003 2 ;;;------------------------------------------------------------------- @@ -205,7 +203,7 @@ Current file: client.s 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 58 60 ldy PSPEED ; Control register: look up by baud rate (8 data bits, 1 stop bit) +006013 2 AC 87 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 3C 60 stx MOD_UADATA_1 ; Modify references to @@ -281,292 +279,604 @@ Current file: client.s 006058 1 006058 1 .ifdef MOUSE_SUPPORT 006058 1 .include "mouse.inc" -006058 1 .endif -006058 1 -006058 1 -006058 1 ;;;------------------------------------------------------------------- -006058 1 ;;; Variables -006058 1 ;;;------------------------------------------------------------------- -006058 1 -006058 1 ;;; Application configuration -006058 1 03 PSPEED: .byte SSC::BPS_115k ; Hardcoded for Apple IIc (TODO: Allow configuration) -006059 1 02 PSLOT: .byte 2 ; Hardcoded for Apple IIc (TODO: Allow configuration) -00605A 1 00 PEXIT: .byte 0 ; Set when it's time to exit (Not Yet Implemented) -00605B 1 -00605B 1 -00605B 1 ;;;--------------------------------------------------------- -00605B 1 ;;; Initialize the application, and enter the main loop -00605B 1 -00605B 1 .proc AppEntry -00605B 1 AD 59 60 lda PSLOT ; Use slot 2 -00605E 1 20 07 60 jsr SSC::Init ; Initialize Super Serial Card -006061 1 20 2B 61 jsr InitHires ; Initialize Hi-Res graphics -006064 1 20 A5 60 jsr InitInput ; Initialize input devices -006067 1 20 74 60 jsr MainLoop -00606A 1 ;; fall through -00606A 1 .endproc -00606A 1 -00606A 1 ;;;--------------------------------------------------------- -00606A 1 ;;; Clean up and exit app -00606A 1 -00606A 1 .proc AppExit -00606A 1 20 54 60 jsr SSC::Reset -00606D 1 8D 54 C0 sta LOWSCR -006070 1 8D 51 C0 sta TXTSET -006073 1 60 rts -006074 1 .endproc -006074 1 -006074 1 ;;;------------------------------------------------------------------- -006074 1 ;;; -006074 1 ;;; Main loop functionality -006074 1 ;;; -006074 1 ;;;------------------------------------------------------------------- -006074 1 -006074 1 -006074 1 ;;;--------------------------------------------------------- -006074 1 .proc MainLoop -006074 1 -006074 1 ;;; TODO: Sort out the protocol - should be able to send -006074 1 ;;; input state without receiving data -006074 1 ;;; jsr SSC::HasData ; Anything to read? -006074 1 ;;; bne :+ ; Nope -006074 1 -006074 1 20 7E 60 : jsr ReceivePage -006077 1 ;; Input is sent every 256 bytes (32 times per page) -006077 1 20 42 61 jsr FlipHires -00607A 1 -00607A 1 4C 74 60 jmp :- ; TODO: define an exit trigger -00607D 1 60 rts -00607E 1 .endproc -00607E 1 -00607E 1 -00607E 1 ;;;--------------------------------------------------------- -00607E 1 ;;; Pull a hi-res page down over serial -00607E 1 ;;; -00607E 1 ;;; Protocol is: -00607E 1 ;;; * Recieve 256 bytes (graphic data) -00607E 1 ;;; * Send 1 byte (input state) -00607E 1 -00607E 1 .proc ReceivePage -00607E 1 A9 80 lda #Protocol::Screen -006080 1 20 30 60 jsr SSC::Put -006083 1 A9 00 lda #0 ; data size -006085 1 20 30 60 jsr SSC::Put -006088 1 -006088 1 -006088 1 A9 00 lda #0 ; set up write pointer -00608A 1 85 FA sta ZP_PTR -00608C 1 A5 E6 lda PAGE -00608E 1 85 FB sta ZP_PTR+1 -006090 1 A2 20 ldx #PAGESIZE ; plan to receive this many pages -006092 1 A0 00 ldy #0 -006094 1 -006094 1 20 3F 60 : jsr SSC::Get -006097 1 91 FA sta (ZP_PTR),Y -006099 1 C8 iny -00609A 1 D0 F8 bne :- ; Do a full page... -00609C 1 -00609C 1 ;; Interleave to maintain responsiveness -00609C 1 20 A6 60 jsr SendInputState -00609F 1 -00609F 1 E6 FB inc ZP_PTR+1 -0060A1 1 CA dex -0060A2 1 D0 F0 bne :- ; ...as many pages as we need -0060A4 1 60 rts -0060A5 1 .endproc -0060A5 1 -0060A5 1 -0060A5 1 ;;;------------------------------------------------------------------- -0060A5 1 ;;; -0060A5 1 ;;; Input device routines -0060A5 1 ;;; -0060A5 1 ;;;------------------------------------------------------------------- -0060A5 1 -0060A5 1 ;;;--------------------------------------------------------- -0060A5 1 ;;; Initialize input devices and storage for detecting -0060A5 1 ;;; state transitions -0060A5 1 -0060A5 1 .proc InitInput -0060A5 1 -0060A5 1 .ifdef MOUSE_SUPPORT -0060A5 1 jsr Mouse::FindMouse -0060A5 1 .endif -0060A5 1 -0060A5 1 60 rts -0060A6 1 .endproc -0060A6 1 -0060A6 1 -0060A6 1 ;;;--------------------------------------------------------- -0060A6 1 ;;; Send a full set of input state updates. -0060A6 1 -0060A6 1 ;;; Assumes time to transmit is roughly comparable to time -0060A6 1 ;;; to measure input state, therefore only sending changes is -0060A6 1 ;;; not worthwhile in most cases. -0060A6 1 -0060A6 1 .proc SendInputState -0060A6 1 20 B0 60 jsr MaybeSendKeyboard -0060A9 1 20 E3 60 jsr SendButtons -0060AC 1 -0060AC 1 .ifdef PADDLE_SUPPORT -0060AC 1 20 04 61 jsr SendPaddles -0060AF 1 .endif -0060AF 1 -0060AF 1 .ifdef MOUSE_SUPPORT -0060AF 1 jsr SendMouse -0060AF 1 .endif -0060AF 1 -0060AF 1 .endproc -0060AF 1 -0060AF 1 -0060AF 1 ;;;------------------------------------------------------------ -0060AF 1 ;;; Keyboard -0060AF 1 -0060AF 1 ;;; NOTE: Can't use KBDSTRB to detect key up -> key down transition -0060AF 1 ;;; since the msb can change before the key code. Instead, consider -0060AF 1 ;;; these cases: -0060AF 1 ;;; -0060AF 1 ;;; OLD STATE KBD KBDSTRB RESULT -0060AF 1 ;;; Up Up - No-op -0060AF 1 ;;; Up Down - Save and send key down -0060AF 1 ;;; Down - Up Save and send key up -0060AF 1 ;;; Down - Down Save and send key ONLY if different -0060AF 1 ;;; -0060AF 1 -0060AF 1 00 last_kb: .byte 0 -0060B0 1 -0060B0 1 .proc MaybeSendKeyboard -0060B0 1 AD AF 60 lda last_kb -0060B3 1 D0 08 bne key_was_down -0060B5 1 -0060B5 1 key_was_up: -0060B5 1 ;; Key was up - send only if now down. -0060B5 1 AD 00 C0 lda KBD ; Read keyboard -0060B8 1 10 28 bpl done ; Do nothing if it is still up. -0060BA 1 4C CF 60 jmp send ; Otherwise send. -0060BD 1 -0060BD 1 key_was_down: -0060BD 1 ;; Key was down - strobe should match -0060BD 1 ;; unless the key changed or was released. -0060BD 1 AD 10 C0 lda KBDSTRB -0060C0 1 30 05 bmi kbdstrb_down -0060C2 1 -0060C2 1 kbdstrb_up: -0060C2 1 A9 00 lda #0 ; Now released -0060C4 1 4C CF 60 jmp send -0060C7 1 -0060C7 1 kbdstrb_down: -0060C7 1 CD AF 60 cmp last_kb ; Same key as last time? -0060CA 1 F0 16 beq done ; - no change, don't send. -0060CC 1 4C CF 60 jmp send -0060CF 1 -0060CF 1 8D AF 60 send: sta last_kb -0060D2 1 A5 00 lda Protocol::Keyboard -0060D4 1 20 30 60 jsr SSC::Put -0060D7 1 A9 01 lda #1 ; Data size -0060D9 1 20 30 60 jsr SSC::Put -0060DC 1 AD AF 60 lda last_kb -0060DF 1 20 30 60 jsr SSC::Put -0060E2 1 -0060E2 1 60 done: rts -0060E3 1 .endproc -0060E3 1 -0060E3 1 ;;;------------------------------------------------------------ -0060E3 1 ;;; Buttons -0060E3 1 -0060E3 1 .proc SendButtons -0060E3 1 -0060E3 1 A5 10 lda Protocol::Button0 -0060E5 1 20 30 60 jsr SSC::Put -0060E8 1 A9 01 lda #1 ; Data size -0060EA 1 20 30 60 jsr SSC::Put -0060ED 1 AD 61 C0 lda BUTN0 -0060F0 1 20 30 60 jsr SSC::Put -0060F3 1 -0060F3 1 A5 11 lda Protocol::Button1 -0060F5 1 20 30 60 jsr SSC::Put -0060F8 1 A9 01 lda #1 ; Data size -0060FA 1 20 30 60 jsr SSC::Put -0060FD 1 AD 62 C0 lda BUTN1 -006100 1 20 30 60 jsr SSC::Put -006103 1 -006103 1 60 rts -006104 1 .endproc -006104 1 -006104 1 ;;;------------------------------------------------------------ -006104 1 ;;; Paddles -006104 1 -006104 1 .ifdef PADDLE_SUPPORT -006104 1 .proc SendPaddles -006104 1 -006104 1 A5 20 lda Protocol::Paddle0 -006106 1 20 30 60 jsr SSC::Put -006109 1 A9 01 lda #1 ; Data size -00610B 1 20 30 60 jsr SSC::Put -00610E 1 -00610E 1 A2 00 ldx #0 -006110 1 20 1E FB jsr PREAD -006113 1 98 tya -006114 1 20 30 60 jsr SSC::Put -006117 1 -006117 1 ;; Assumes at least 11 cycles to send, so -006117 1 ;; timer has a chance to reset. -006117 1 -006117 1 A5 21 lda Protocol::Paddle1 -006119 1 20 30 60 jsr SSC::Put -00611C 1 A9 01 lda #1 ; Data size -00611E 1 20 30 60 jsr SSC::Put -006121 1 -006121 1 A2 01 ldx #1 -006123 1 20 1E FB jsr PREAD -006126 1 98 tya -006127 1 20 30 60 jsr SSC::Put -00612A 1 -00612A 1 60 rts -00612B 1 .endproc -00612B 1 .endif -00612B 1 -00612B 1 ;;;------------------------------------------------------------------- -00612B 1 ;;; -00612B 1 ;;; Hi-res graphics routines -00612B 1 ;;; -00612B 1 ;;;------------------------------------------------------------------- -00612B 1 -00612B 1 ;;;--------------------------------------------------------- -00612B 1 ;;; Set up the graphics display and pointers -00612B 1 -00612B 1 .proc InitHires -00612B 1 A9 20 lda #PAGE1 ; clear page 1 -00612D 1 85 E6 sta PAGE -00612F 1 20 F2 F3 jsr HCLR -006132 1 -006132 1 20 42 61 jsr FlipHires ; then show it and flip to 2 -006135 1 8D 57 C0 sta HIRES -006138 1 8D 50 C0 sta TXTCLR -00613B 1 8D 52 C0 sta MIXCLR -00613E 1 8D 54 C0 sta LOWSCR -006141 1 -006141 1 60 rts -006142 1 .endproc -006142 1 -006142 1 -006142 1 ;;;--------------------------------------------------------- -006142 1 ;;; Call when done with the current plotting page -006142 1 ;;; (selected in PAGE) and it will be shown and the -006142 1 ;;; other page will be shown. -006142 1 -006142 1 .proc FlipHires -006142 1 A5 E6 lda PAGE ; plotting on which page? -006144 1 C9 20 cmp #PAGE1 -006146 1 F0 08 beq :+ -006148 1 -006148 1 8D 55 C0 sta HISCR ; page 2 - so show it -00614B 1 A9 20 lda #PAGE1 ; and plot on page 1 -00614D 1 85 E6 sta PAGE -00614F 1 60 rts -006150 1 -006150 1 8D 54 C0 : sta LOWSCR ; page 1 - so show it -006153 1 A9 40 lda #PAGE2 ; and plot on page 2 -006155 1 85 E6 sta PAGE -006157 1 60 rts -006158 1 .endproc -006158 1 +006058 2 ;;;------------------------------------------------------------------- +006058 2 ;;; +006058 2 ;;; Mouse +006058 2 ;;; +006058 2 ;;;------------------------------------------------------------------- +006058 2 ;; .error "Mouse support not fully implemented" +006058 2 +006058 2 .proc Mouse +006058 2 +006058 2 ;;;-------------------------------------------------- +006058 2 ;;; Mouse Screen Holes +006058 2 ;;;-------------------------------------------------- +006058 2 +006058 2 ;;; For ReadMouse and PosMouse +006058 2 +006058 2 MOUSE_X_LSB := $0478 ; + slot Low byte of X coordinate +006058 2 MOUSE_Y_LSB := $04F8 ; + slot Low byte of Y coordinate +006058 2 MOUSE_X_MSB := $0578 ; + slot High byte of X coordinate +006058 2 MOUSE_Y_MSB := $05F8 ; + slot High byte of Y coordinate +006058 2 MOUSE_RSV1 := $0678 ; + slot Reserved +006058 2 MOUSE_RSV2 := $06F8 ; + slot Reserved +006058 2 MOUSE_STATUS := $0778 ; + slot Status byte +006058 2 ;; 7 Button down +006058 2 ;; 6 Button was down on last read and still down +006058 2 ;; 5 Movement since last read +006058 2 ;; 4 Reserved +006058 2 ;; 3 Interrupt from VBlInt +006058 2 ;; 2 Interrupt from button +006058 2 ;; 1 Interrupt from movement +006058 2 ;; 0 Reserved +006058 2 MOUSE_MODE := $07F8 ; + slot Mode byte +006058 2 ;; 7-4 Reserved +006058 2 ;; 3 VBlInt active +006058 2 ;; 2 VBL interrupt on button +006058 2 ;; 1 VBL interrupt on movement +006058 2 ;; 0 Mouse active +006058 2 +006058 2 ;;; Scratch area for ClampMouse: +006058 2 +006058 2 MOUSE_CMIN_LSB := $0478 ; Low byte of clamping minimum +006058 2 MOUSE_CMAX_LSB := $04F8 ; Low byte of clamping maximum +006058 2 MOUSE_CMIN_MSB := $0578 ; High byte of clamping minimum +006058 2 MOUSE_CMAX_MSB := $05F8 ; High byte of clamping maximum +006058 2 +006058 2 ;;;-------------------------------------------------- +006058 2 ;;; Mouse Constants +006058 2 ;;;-------------------------------------------------- +006058 2 +006058 2 MOUSE_CLAMP_X := 0 ; Value for A when setting X clamp with ClampMouse +006058 2 MOUSE_CLAMP_Y := 1 ; Value for A when setting X clamp with ClampMouse +006058 2 +006058 2 ;;; Mouse ID bytes +006058 2 MOUSEID_MAX := 4 +006058 2 05 07 0B 0C MOUSEID_ADDR: .byte $05, $07, $0b, $0c, $fb +00605C 2 FB +00605D 2 38 18 01 20 MOUSEID_VAL: .byte $38, $18, $01, $20, $d6 +006061 2 D6 +006062 2 +006062 2 SLOT_BASE := $C000 +006062 2 +006062 2 ;;;-------------------------------------------------- +006062 2 ;;; Mouse firmware routine +006062 2 ;;;-------------------------------------------------- +006062 2 +006062 2 SetMouse := $12 ; A=mode; C=0 on success +006062 2 ServeMouse := $13 ; C=0 mouse interrupt, C=1 other +006062 2 ReadMouse := $14 +006062 2 ClearMouse := $15 +006062 2 PosMouse := $16 +006062 2 ClampMouse := $17 +006062 2 HomeMouse := $18 +006062 2 InitMouse := $19 +006062 2 +006062 2 .macro MOUSE_CALL routine +006062 2 ldy routine +006062 2 jmp CallMouse +006062 2 .endmacro +006062 2 +006062 2 ;;;-------------------------------------------------- +006062 2 ;;; Data +006062 2 ;;;-------------------------------------------------- +006062 2 +006062 2 ;;; Mouse +006062 2 00 mouse_slot: .byte 0 ; mouse slot, or 0 if none +006063 2 00 mouse_fw_hi: .byte 0 ; mouse slot as $Cn +006064 2 00 mouse_op: .byte 0 ; mouse slot as $n0 +006065 2 +006065 2 mouse_ptr := $EB ; Zero page location +006065 2 +006065 2 ;;;-------------------------------------------------- +006065 2 ;;; Routines +006065 2 ;;;-------------------------------------------------- +006065 2 +006065 2 +006065 2 MOUSE_CLAMP_MIN := $10 +006065 2 MOUSE_CLAMP_MAX := $1F +006065 2 MOUSE_CENTER := $17 +006065 2 MOUSE_POS_MASK := $0F +006065 2 +006065 2 +006065 2 ;;;-------------------------------------------------- +006065 2 ;;; Macros for common mouse operations +006065 2 ;;;-------------------------------------------------- +006065 2 +006065 2 ;;;---------------------------------------- +006065 2 .macro DoClampMouse axis, min, max +006065 2 ;;;---------------------------------------- +006065 2 ;;; axis: MOUSE_CLAMP_X or MOUSE_CLAMP_Y +006065 2 ;;; min: minimum value (2 byte) +006065 2 ;;; max: maximum value (2 byte) +006065 2 ;;;---------------------------------------- +006065 2 lda #min +006065 2 sta MOUSE_CMIN_MSB +006065 2 lda #max +006065 2 sta MOUSE_CMAX_MSB +006065 2 lda #axis +006065 2 MOUSE_CALL ClampMouse +006065 2 .endmacro +006065 2 +006065 2 ;;;---------------------------------------- +006065 2 .macro DoPosMouse px, py +006065 2 ;;;---------------------------------------- +006065 2 ldx mouse_slot +006065 2 lda #px +006065 2 sta MOUSE_X_MSB,x +006065 2 lda #py +006065 2 sta MOUSE_Y_MSB,x +006065 2 MOUSE_CALL PosMouse +006065 2 .endmacro +006065 2 +006065 2 ;;;---------------------------------------- +006065 2 .macro DoSetMouse mode +006065 2 ;;;---------------------------------------- +006065 2 lda #mode +006065 2 MOUSE_CALL SetMouse +006065 2 .endmacro +006065 2 +006065 2 +006065 2 ;;;--------------------------------------------------------- +006065 2 ;;; Find and initialize the mouse port +006065 2 +006065 2 .proc FindMouse +006065 2 +006065 2 ;;; Reference: http://home.swbell.net/rubywand/R034MOUSEPRG.TXT +006065 2 +006065 2 78 sei ; No interrupts while we're getting set up +006066 2 +006066 2 ;; Find mouse card by scanning slots for ID bytes +006066 2 +006066 2 A0 07 ldy #MAX_SLOT ; Start search in slot 7 +006068 2 +006068 2 slot_loop: +006068 2 8C 62 60 sty mouse_slot ; Save for later +00606B 2 98 tya +00606C 2 18 clc +00606D 2 69 C0 adc #>SLOT_BASE ; Firmware is $Cn +00606F 2 8D 7C 60 sta slot_addr + 1 ; Update msb of signature test +006072 2 A2 04 ldx #MOUSEID_MAX ; This many signature bytes +006074 2 +006074 2 BD 58 60 : lda MOUSEID_ADDR,x +006077 2 8D 7B 60 sta slot_addr ; Update lsb of signature test +00607A 2 +00607A 2 slot_addr := *+1 +00607A 2 AD 00 C0 lda SLOT_BASE ; Self-modified +00607D 2 DD 5D 60 cmp MOUSEID_VAL,x ; Does it match the signature? +006080 2 D0 06 bne no_match ; Nope - try the next slot +006082 2 CA dex ; Yes! Keep testing +006083 2 10 EF bpl :- ; Fall through if all done +006085 2 4C 8F 60 jmp found +006088 2 +006088 2 no_match: +006088 2 88 dey ; Didn't match +006089 2 D0 DD bne slot_loop ; Keep looking until slot 0 +00608B 2 8C 62 60 sty mouse_slot ; Oops, no mouse - make a note +00608E 2 60 rts ; and bail +00608F 2 +00608F 2 ;; Store results needed for call ($Cn and $n0) +00608F 2 +00608F 2 98 found: tya ; Slot is in y +006090 2 09 C0 ora #>SLOT_BASE ; Compute $Cn - needed for calls +006092 2 8D 63 60 sta mouse_fw_hi +006095 2 +006095 2 98 tya +006096 2 0A asl ; Compute $n0 - needed for calls +006097 2 0A asl +006098 2 0A asl +006099 2 0A asl +00609A 2 8D 64 60 sta mouse_op +00609D 2 +00609D 2 ;; Initialize and configure mouse card +00609D 2 +00609D 2 A4 19 4C FD MOUSE_CALL InitMouse ; reset, clamp to 0-1023 x/y +0060A1 2 60 +0060A2 2 +0060A2 2 A9 01 A4 12 DoSetMouse $01 ; mouse on, no interrupts +0060A6 2 4C FD 60 +0060A9 2 ; TODO: test carry bit result (set = error) +0060A9 2 +0060A9 2 ;; Clamp for deltas +0060A9 2 A9 10 8D 78 DoClampMouse MOUSE_CLAMP_X, MOUSE_CLAMP_MIN, MOUSE_CLAMP_MAX +0060AD 2 04 A9 00 8D +0060B1 2 78 05 A9 1F +0060B5 2 8D F8 04 A9 +0060B9 2 00 8D F8 05 +0060BD 2 A9 00 A4 17 +0060C1 2 4C FD 60 +0060C4 2 A9 10 8D 78 DoClampMouse MOUSE_CLAMP_Y, MOUSE_CLAMP_MIN, MOUSE_CLAMP_MAX +0060C8 2 04 A9 00 8D +0060CC 2 78 05 A9 1F +0060D0 2 8D F8 04 A9 +0060D4 2 00 8D F8 05 +0060D8 2 A9 01 A4 17 +0060DC 2 4C FD 60 +0060DF 2 +0060DF 2 AE 62 60 A9 DoPosMouse MOUSE_CENTER, MOUSE_CENTER +0060E3 2 17 9D 78 04 +0060E7 2 A9 00 9D 78 +0060EB 2 05 A9 17 9D +0060EF 2 F8 04 A9 00 +0060F3 2 9D F8 05 A4 +0060F7 2 16 4C FD 60 +0060FB 2 +0060FB 2 58 cli ; Enable interrupts so mouse can function +0060FC 2 +0060FC 2 60 rts +0060FD 2 .endproc +0060FD 2 +0060FD 2 ;;;-------------------------------------------------- +0060FD 2 ;;; Call mouse firmware, param in A, routine in Y +0060FD 2 +0060FD 2 .proc CallMouse +0060FD 2 48 pha ; Save A (param) +0060FE 2 AE 63 60 ldx mouse_fw_hi ; $Cn +006101 2 86 EC stx mouse_ptr+1 +006103 2 A9 00 lda #0 +006105 2 85 EB sta mouse_ptr +006107 2 B1 EB lda (mouse_ptr),y ; Look up routine offset +006109 2 85 EB sta mouse_ptr +00610B 2 +00610B 2 68 pla ; param in A +00610C 2 AC 64 60 ldy mouse_op ; $n0 in Y +00610F 2 +00610F 2 08 php +006110 2 78 sei +006111 2 20 16 61 jsr call +006114 2 28 plp +006115 2 60 rts +006116 2 +006116 2 6C EB 00 call: jmp (mouse_ptr) +006119 2 .endproc +006119 2 +006119 2 ;;;-------------------------------------------------- +006119 2 ;;; Read mouse pos, send deltas, and recenter +006119 2 +006119 2 .proc SendMouse +006119 2 48 8A 48 98 SaveRegisters +00611D 2 48 +00611E 2 AD 62 60 lda mouse_slot +006121 2 F0 5E beq done +006123 2 +006123 2 A4 14 4C FD MOUSE_CALL ReadMouse +006127 2 60 +006128 2 +006128 2 A5 30 lda Protocol::MouseX +00612A 2 20 30 60 jsr SSC::Put +00612D 2 A9 01 lda #1 ; Data size +00612F 2 20 30 60 jsr SSC::Put +006132 2 AE 62 60 ldx mouse_slot +006135 2 BD 78 04 lda MOUSE_X_LSB,x +006138 2 05 0F ora MOUSE_POS_MASK +00613A 2 20 30 60 jsr SSC::Put +00613D 2 +00613D 2 A5 31 lda Protocol::MouseY +00613F 2 20 30 60 jsr SSC::Put +006142 2 A9 01 lda #1 ; Data size +006144 2 20 30 60 jsr SSC::Put +006147 2 AE 62 60 ldx mouse_slot +00614A 2 BD F8 04 lda MOUSE_Y_LSB,x +00614D 2 05 0F ora MOUSE_POS_MASK +00614F 2 20 30 60 jsr SSC::Put +006152 2 +006152 2 A5 32 lda Protocol::MouseBtn +006154 2 20 30 60 jsr SSC::Put +006157 2 A9 01 lda #1 ; Data size +006159 2 20 30 60 jsr SSC::Put +00615C 2 AE 62 60 ldx mouse_slot +00615F 2 BD 78 07 lda MOUSE_STATUS,x +006162 2 20 30 60 jsr SSC::Put +006165 2 +006165 2 AE 62 60 A9 DoPosMouse MOUSE_CENTER, MOUSE_CENTER +006169 2 17 9D 78 04 +00616D 2 A9 00 9D 78 +006171 2 05 A9 17 9D +006175 2 F8 04 A9 00 +006179 2 9D F8 05 A4 +00617D 2 16 4C FD 60 +006181 2 +006181 2 68 A8 68 AA done: RestoreRegisters +006185 2 68 +006186 2 60 rts +006187 2 .endproc +006187 2 +006187 2 .endproc +006187 2 +006187 1 .endif +006187 1 +006187 1 +006187 1 ;;;------------------------------------------------------------------- +006187 1 ;;; Variables +006187 1 ;;;------------------------------------------------------------------- +006187 1 +006187 1 ;;; Application configuration +006187 1 03 PSPEED: .byte SSC::BPS_115k ; Hardcoded for Apple IIc (TODO: Allow configuration) +006188 1 02 PSLOT: .byte 2 ; Hardcoded for Apple IIc (TODO: Allow configuration) +006189 1 00 PEXIT: .byte 0 ; Set when it's time to exit (Not Yet Implemented) +00618A 1 +00618A 1 +00618A 1 ;;;--------------------------------------------------------- +00618A 1 ;;; Initialize the application, and enter the main loop +00618A 1 +00618A 1 .proc AppEntry +00618A 1 AD 88 61 lda PSLOT ; Use slot 2 +00618D 1 20 07 60 jsr SSC::Init ; Initialize Super Serial Card +006190 1 20 60 62 jsr InitHires ; Initialize Hi-Res graphics +006193 1 20 D4 61 jsr InitInput ; Initialize input devices +006196 1 20 A3 61 jsr MainLoop +006199 1 ;; fall through +006199 1 .endproc +006199 1 +006199 1 ;;;--------------------------------------------------------- +006199 1 ;;; Clean up and exit app +006199 1 +006199 1 .proc AppExit +006199 1 20 54 60 jsr SSC::Reset +00619C 1 8D 54 C0 sta LOWSCR +00619F 1 8D 51 C0 sta TXTSET +0061A2 1 60 rts +0061A3 1 .endproc +0061A3 1 +0061A3 1 ;;;------------------------------------------------------------------- +0061A3 1 ;;; +0061A3 1 ;;; Main loop functionality +0061A3 1 ;;; +0061A3 1 ;;;------------------------------------------------------------------- +0061A3 1 +0061A3 1 +0061A3 1 ;;;--------------------------------------------------------- +0061A3 1 .proc MainLoop +0061A3 1 +0061A3 1 ;;; TODO: Sort out the protocol - should be able to send +0061A3 1 ;;; input state without receiving data +0061A3 1 ;;; jsr SSC::HasData ; Anything to read? +0061A3 1 ;;; bne :+ ; Nope +0061A3 1 +0061A3 1 20 AD 61 : jsr ReceivePage +0061A6 1 ;; Input is sent every 256 bytes (32 times per page) +0061A6 1 20 77 62 jsr FlipHires +0061A9 1 +0061A9 1 4C A3 61 jmp :- ; TODO: define an exit trigger +0061AC 1 60 rts +0061AD 1 .endproc +0061AD 1 +0061AD 1 +0061AD 1 ;;;--------------------------------------------------------- +0061AD 1 ;;; Request a hires page, sending input state along every +0061AD 1 ;;; 256 bytes. +0061AD 1 ;;; +0061AD 1 +0061AD 1 .proc ReceivePage +0061AD 1 +0061AD 1 ptr := $FA +0061AD 1 +0061AD 1 A9 80 lda #Protocol::Screen +0061AF 1 20 30 60 jsr SSC::Put +0061B2 1 A9 00 lda #0 ; data size +0061B4 1 20 30 60 jsr SSC::Put +0061B7 1 +0061B7 1 +0061B7 1 A9 00 lda #0 ; set up write pointer +0061B9 1 85 FA sta ptr +0061BB 1 A5 E6 lda PAGE +0061BD 1 85 FB sta ptr+1 +0061BF 1 A2 20 ldx #PAGESIZE ; plan to receive this many pages +0061C1 1 A0 00 ldy #0 +0061C3 1 +0061C3 1 20 3F 60 : jsr SSC::Get +0061C6 1 91 FA sta (ptr),Y +0061C8 1 C8 iny +0061C9 1 D0 F8 bne :- ; Do a full page... +0061CB 1 +0061CB 1 ;; Interleave to maintain responsiveness +0061CB 1 20 D8 61 jsr SendInputState +0061CE 1 +0061CE 1 E6 FB inc ptr+1 +0061D0 1 CA dex +0061D1 1 D0 F0 bne :- ; ...as many pages as we need +0061D3 1 60 rts +0061D4 1 .endproc +0061D4 1 +0061D4 1 +0061D4 1 ;;;------------------------------------------------------------------- +0061D4 1 ;;; +0061D4 1 ;;; Input device routines +0061D4 1 ;;; +0061D4 1 ;;;------------------------------------------------------------------- +0061D4 1 +0061D4 1 ;;;--------------------------------------------------------- +0061D4 1 ;;; Initialize input devices and storage for detecting +0061D4 1 ;;; state transitions +0061D4 1 +0061D4 1 .proc InitInput +0061D4 1 +0061D4 1 .ifdef MOUSE_SUPPORT +0061D4 1 20 65 60 jsr Mouse::FindMouse +0061D7 1 .endif +0061D7 1 +0061D7 1 60 rts +0061D8 1 .endproc +0061D8 1 +0061D8 1 +0061D8 1 ;;;--------------------------------------------------------- +0061D8 1 ;;; Send a full set of input state updates. +0061D8 1 +0061D8 1 ;;; Assumes time to transmit is roughly comparable to time +0061D8 1 ;;; to measure input state, therefore only sending changes is +0061D8 1 ;;; not worthwhile in most cases. +0061D8 1 +0061D8 1 .proc SendInputState +0061D8 1 20 E5 61 jsr MaybeSendKeyboard +0061DB 1 20 18 62 jsr SendButtons +0061DE 1 +0061DE 1 .ifdef PADDLE_SUPPORT +0061DE 1 20 39 62 jsr SendPaddles +0061E1 1 .endif +0061E1 1 +0061E1 1 .ifdef MOUSE_SUPPORT +0061E1 1 20 19 61 jsr Mouse::SendMouse +0061E4 1 .endif +0061E4 1 +0061E4 1 .endproc +0061E4 1 +0061E4 1 +0061E4 1 ;;;------------------------------------------------------------ +0061E4 1 ;;; Keyboard +0061E4 1 +0061E4 1 ;;; NOTE: Can't use KBDSTRB to detect key up -> key down transition +0061E4 1 ;;; since the msb can change before the key code. Instead, consider +0061E4 1 ;;; these cases: +0061E4 1 ;;; +0061E4 1 ;;; OLD STATE KBD KBDSTRB RESULT +0061E4 1 ;;; Up Up - No-op +0061E4 1 ;;; Up Down - Save and send key down +0061E4 1 ;;; Down - Up Save and send key up +0061E4 1 ;;; Down - Down Save and send key ONLY if different +0061E4 1 ;;; +0061E4 1 +0061E4 1 00 last_kb: .byte 0 +0061E5 1 +0061E5 1 .proc MaybeSendKeyboard +0061E5 1 AD E4 61 lda last_kb +0061E8 1 D0 08 bne key_was_down +0061EA 1 +0061EA 1 key_was_up: +0061EA 1 ;; Key was up - send only if now down. +0061EA 1 AD 00 C0 lda KBD ; Read keyboard +0061ED 1 10 28 bpl done ; Do nothing if it is still up. +0061EF 1 4C 04 62 jmp send ; Otherwise send. +0061F2 1 +0061F2 1 key_was_down: +0061F2 1 ;; Key was down - strobe should match +0061F2 1 ;; unless the key changed or was released. +0061F2 1 AD 10 C0 lda KBDSTRB +0061F5 1 30 05 bmi kbdstrb_down +0061F7 1 +0061F7 1 kbdstrb_up: +0061F7 1 A9 00 lda #0 ; Now released +0061F9 1 4C 04 62 jmp send +0061FC 1 +0061FC 1 kbdstrb_down: +0061FC 1 CD E4 61 cmp last_kb ; Same key as last time? +0061FF 1 F0 16 beq done ; - no change, don't send. +006201 1 4C 04 62 jmp send +006204 1 +006204 1 8D E4 61 send: sta last_kb +006207 1 A5 00 lda Protocol::Keyboard +006209 1 20 30 60 jsr SSC::Put +00620C 1 A9 01 lda #1 ; Data size +00620E 1 20 30 60 jsr SSC::Put +006211 1 AD E4 61 lda last_kb +006214 1 20 30 60 jsr SSC::Put +006217 1 +006217 1 60 done: rts +006218 1 .endproc +006218 1 +006218 1 ;;;------------------------------------------------------------ +006218 1 ;;; Buttons +006218 1 +006218 1 .proc SendButtons +006218 1 +006218 1 A5 10 lda Protocol::Button0 +00621A 1 20 30 60 jsr SSC::Put +00621D 1 A9 01 lda #1 ; Data size +00621F 1 20 30 60 jsr SSC::Put +006222 1 AD 61 C0 lda BUTN0 +006225 1 20 30 60 jsr SSC::Put +006228 1 +006228 1 A5 11 lda Protocol::Button1 +00622A 1 20 30 60 jsr SSC::Put +00622D 1 A9 01 lda #1 ; Data size +00622F 1 20 30 60 jsr SSC::Put +006232 1 AD 62 C0 lda BUTN1 +006235 1 20 30 60 jsr SSC::Put +006238 1 +006238 1 60 rts +006239 1 .endproc +006239 1 +006239 1 ;;;------------------------------------------------------------ +006239 1 ;;; Paddles +006239 1 +006239 1 .ifdef PADDLE_SUPPORT +006239 1 .proc SendPaddles +006239 1 +006239 1 A5 20 lda Protocol::Paddle0 +00623B 1 20 30 60 jsr SSC::Put +00623E 1 A9 01 lda #1 ; Data size +006240 1 20 30 60 jsr SSC::Put +006243 1 +006243 1 A2 00 ldx #0 +006245 1 20 1E FB jsr PREAD +006248 1 98 tya +006249 1 20 30 60 jsr SSC::Put +00624C 1 +00624C 1 ;; Need to wait 3ms between reads. +00624C 1 +00624C 1 A5 21 lda Protocol::Paddle1 +00624E 1 20 30 60 jsr SSC::Put +006251 1 A9 01 lda #1 ; Data size +006253 1 20 30 60 jsr SSC::Put +006256 1 +006256 1 A2 01 ldx #1 +006258 1 20 1E FB jsr PREAD +00625B 1 98 tya +00625C 1 20 30 60 jsr SSC::Put +00625F 1 +00625F 1 60 rts +006260 1 .endproc +006260 1 .endif +006260 1 +006260 1 ;;;------------------------------------------------------------------- +006260 1 ;;; +006260 1 ;;; Hi-res graphics routines +006260 1 ;;; +006260 1 ;;;------------------------------------------------------------------- +006260 1 +006260 1 ;;;--------------------------------------------------------- +006260 1 ;;; Set up the graphics display and pointers +006260 1 +006260 1 .proc InitHires +006260 1 A9 20 lda #PAGE1 ; clear page 1 +006262 1 85 E6 sta PAGE +006264 1 20 F2 F3 jsr HCLR +006267 1 +006267 1 20 77 62 jsr FlipHires ; then show it and flip to 2 +00626A 1 8D 57 C0 sta HIRES +00626D 1 8D 50 C0 sta TXTCLR +006270 1 8D 52 C0 sta MIXCLR +006273 1 8D 54 C0 sta LOWSCR +006276 1 +006276 1 60 rts +006277 1 .endproc +006277 1 +006277 1 +006277 1 ;;;--------------------------------------------------------- +006277 1 ;;; Call when done with the current plotting page +006277 1 ;;; (selected in PAGE) and it will be shown and the +006277 1 ;;; other page will be shown. +006277 1 +006277 1 .proc FlipHires +006277 1 A5 E6 lda PAGE ; plotting on which page? +006279 1 C9 20 cmp #PAGE1 +00627B 1 F0 08 beq :+ +00627D 1 +00627D 1 8D 55 C0 sta HISCR ; page 2 - so show it +006280 1 A9 20 lda #PAGE1 ; and plot on page 1 +006282 1 85 E6 sta PAGE +006284 1 60 rts +006285 1 +006285 1 8D 54 C0 : sta LOWSCR ; page 1 - so show it +006288 1 A9 40 lda #PAGE2 ; and plot on page 2 +00628A 1 85 E6 sta PAGE +00628C 1 60 rts +00628D 1 .endproc +00628D 1 diff --git a/client/client.s b/client/client.s index 03c9596..da101be 100644 --- a/client/client.s +++ b/client/client.s @@ -5,7 +5,7 @@ ;;;------------------------------------------------------------------- PADDLE_SUPPORT = 1 -;;; MOUSE_SUPPORT = 1 + MOUSE_SUPPORT = 1 .include "apple2.inc" @@ -36,8 +36,6 @@ HCLR := $F3F2 ; Clear current hires screen to black MAX_SLOT := 7 ; Maximum slot # on an Apple II -ZP_PTR := $FA ; Write cursor location on zero page - ;;;------------------------------------------------------------------- ;;; Protocol: ;;;------------------------------------------------------------------- @@ -132,13 +130,14 @@ PEXIT: .byte 0 ; Set when it's time to exit (Not Yet Implemente ;;;--------------------------------------------------------- -;;; Pull a hi-res page down over serial +;;; Request a hires page, sending input state along every +;;; 256 bytes. ;;; -;;; Protocol is: -;;; * Recieve 256 bytes (graphic data) -;;; * Send 1 byte (input state) .proc ReceivePage + +ptr := $FA + lda #Protocol::Screen jsr SSC::Put lda #0 ; data size @@ -146,21 +145,21 @@ PEXIT: .byte 0 ; Set when it's time to exit (Not Yet Implemente lda #0 ; set up write pointer - sta ZP_PTR + sta ptr lda PAGE - sta ZP_PTR+1 + sta ptr+1 ldx #PAGESIZE ; plan to receive this many pages ldy #0 : jsr SSC::Get - sta (ZP_PTR),Y + sta (ptr),Y iny bne :- ; Do a full page... ;; Interleave to maintain responsiveness jsr SendInputState - inc ZP_PTR+1 + inc ptr+1 dex bne :- ; ...as many pages as we need rts @@ -203,7 +202,7 @@ PEXIT: .byte 0 ; Set when it's time to exit (Not Yet Implemente .endif .ifdef MOUSE_SUPPORT - jsr SendMouse + jsr Mouse::SendMouse .endif .endproc @@ -299,8 +298,7 @@ done: rts tya jsr SSC::Put - ;; Assumes at least 11 cycles to send, so - ;; timer has a chance to reset. + ;; Need to wait 3ms between reads. lda Protocol::Paddle1 jsr SSC::Put diff --git a/client/mouse.inc b/client/mouse.inc index 772c291..be8b629 100644 --- a/client/mouse.inc +++ b/client/mouse.inc @@ -3,34 +3,51 @@ ;;; Mouse ;;; ;;;------------------------------------------------------------------- - .error "Mouse support not fully implemented" + ;; .error "Mouse support not fully implemented" .proc Mouse ;;;-------------------------------------------------- -;;; Locations and constants +;;; Mouse Screen Holes ;;;-------------------------------------------------- -;;; For READMOUSE and POSMOUSE +;;; For ReadMouse and PosMouse -MOUSE_X_LSB := $0478 ; + slot Low byte of absolute X position -MOUSE_X_MSB := $0578 ; + slot High byte of absolute X position -MOUSE_Y_LSB := $04F8 ; + slot Low byte of absolute Y position -MOUSE_Y_MSB := $05F8 ; + slot High byte of absolute Y position -MOUSE_RSV1 := $0678 ; + slot Reserved and used by the firmware -MOUSE_RSV2 := $06F8 ; + slot Reserved and used by the firmware -MOUSE_BTN := $0778 ; + slot Button 0/1 interrupt status byte +MOUSE_X_LSB := $0478 ; + slot Low byte of X coordinate +MOUSE_Y_LSB := $04F8 ; + slot Low byte of Y coordinate +MOUSE_X_MSB := $0578 ; + slot High byte of X coordinate +MOUSE_Y_MSB := $05F8 ; + slot High byte of Y coordinate +MOUSE_RSV1 := $0678 ; + slot Reserved +MOUSE_RSV2 := $06F8 ; + slot Reserved +MOUSE_STATUS := $0778 ; + slot Status byte + ;; 7 Button down + ;; 6 Button was down on last read and still down + ;; 5 Movement since last read + ;; 4 Reserved + ;; 3 Interrupt from VBlInt + ;; 2 Interrupt from button + ;; 1 Interrupt from movement + ;; 0 Reserved MOUSE_MODE := $07F8 ; + slot Mode byte + ;; 7-4 Reserved + ;; 3 VBlInt active + ;; 2 VBL interrupt on button + ;; 1 VBL interrupt on movement + ;; 0 Mouse active -;;; For CLAMPMOUSE: +;;; Scratch area for ClampMouse: -MOUSE_CMIN_LSB := $0478 ; low byte of low clamp -MOUSE_CMIN_MSB := $0578 ; high byte of low clamp -MOUSE_CMAX_LSB := $04F8 ; low byte of high clamp -MOUSE_CMAX_MSB := $05F8 ; high byte of high clamp +MOUSE_CMIN_LSB := $0478 ; Low byte of clamping minimum +MOUSE_CMAX_LSB := $04F8 ; Low byte of clamping maximum +MOUSE_CMIN_MSB := $0578 ; High byte of clamping minimum +MOUSE_CMAX_MSB := $05F8 ; High byte of clamping maximum -MOUSE_CLAMP_X := 0 ; Value for A when setting X clamp with CLAMPMOUSE -MOUSE_CLAMP_Y := 1 ; Value for A when setting X clamp with CLAMPMOUSE +;;;-------------------------------------------------- +;;; Mouse Constants +;;;-------------------------------------------------- + +MOUSE_CLAMP_X := 0 ; Value for A when setting X clamp with ClampMouse +MOUSE_CLAMP_Y := 1 ; Value for A when setting X clamp with ClampMouse ;;; Mouse ID bytes MOUSEID_MAX := 4 @@ -39,28 +56,44 @@ MOUSEID_VAL: .byte $38, $18, $01, $20, $d6 SLOT_BASE := $C000 +;;;-------------------------------------------------- +;;; Mouse firmware routine +;;;-------------------------------------------------- + +SetMouse := $12 ; A=mode; C=0 on success +ServeMouse := $13 ; C=0 mouse interrupt, C=1 other +ReadMouse := $14 +ClearMouse := $15 +PosMouse := $16 +ClampMouse := $17 +HomeMouse := $18 +InitMouse := $19 + +.macro MOUSE_CALL routine + ldy routine + jmp CallMouse +.endmacro + ;;;-------------------------------------------------- ;;; Data ;;;-------------------------------------------------- ;;; Mouse -MOUSE_SLOT: .byte 0 ; mouse slot, or 0 if none -LAST_MX: .byte $7f -LAST_MY: .byte $7f +mouse_slot: .byte 0 ; mouse slot, or 0 if none +mouse_fw_hi: .byte 0 ; mouse slot as $Cn +mouse_op: .byte 0 ; mouse slot as $n0 +mouse_ptr := $EB ; Zero page location ;;;-------------------------------------------------- ;;; Routines ;;;-------------------------------------------------- -MOUSEPTR := $EB ; Zero page location -MOUSE_MIN_X := $10 -MOUSE_MAX_X := $1f -MOUSE_CENTER_X := $17 -MOUSE_MIN_Y := $20 -MOUSE_MAX_Y := $2f -MOUSE_CENTER_Y := $2f +MOUSE_CLAMP_MIN := $10 +MOUSE_CLAMP_MAX := $1F +MOUSE_CENTER := $17 +MOUSE_POS_MASK := $0F ;;;-------------------------------------------------- @@ -68,7 +101,7 @@ MOUSE_CENTER_Y := $2f ;;;-------------------------------------------------- ;;;---------------------------------------- -.macro ClampMouse axis, min, max +.macro DoClampMouse axis, min, max ;;;---------------------------------------- ;;; axis: MOUSE_CLAMP_X or MOUSE_CLAMP_Y ;;; min: minimum value (2 byte) @@ -83,22 +116,29 @@ MOUSE_CENTER_Y := $2f lda #>max sta MOUSE_CMAX_MSB lda #axis - jsr CLAMPMOUSE + MOUSE_CALL ClampMouse .endmacro ;;;---------------------------------------- -.macro PosMouse px, py +.macro DoPosMouse px, py ;;;---------------------------------------- - ldx MOUSE_SLOT + ldx mouse_slot lda #px - sta MOUSE_X_MSB,X + sta MOUSE_X_MSB,x lda #py - sta MOUSE_Y_MSB,X - jsr POSMOUSE + sta MOUSE_Y_MSB,x + MOUSE_CALL PosMouse +.endmacro + +;;;---------------------------------------- +.macro DoSetMouse mode +;;;---------------------------------------- + lda #mode + MOUSE_CALL SetMouse .endmacro @@ -110,183 +150,131 @@ MOUSE_CENTER_Y := $2f ;;; Reference: http://home.swbell.net/rubywand/R034MOUSEPRG.TXT sei ; No interrupts while we're getting set up - ; -;;; Step 1: Find the mouse card by scanning slots for ID bytes - ; + + ;; Find mouse card by scanning slots for ID bytes ldy #MAX_SLOT ; Start search in slot 7 -TESTSLOT: - sty MOUSE_SLOT ; Save for later +slot_loop: + sty mouse_slot ; Save for later tya clc - adc #>SLOT_BASE ; Firmware is $c0 + slot + adc #>SLOT_BASE ; Firmware is $Cn sta slot_addr + 1 ; Update msb of signature test ldx #MOUSEID_MAX ; This many signature bytes -TESTID: - lda MOUSEID_ADDR,x - sta MOD_MOUSE_ID + 1 ; Update lsb of signature test +: lda MOUSEID_ADDR,x + sta slot_addr ; Update lsb of signature test + slot_addr := *+1 lda SLOT_BASE ; Self-modified cmp MOUSEID_VAL,x ; Does it match the signature? - bne NOMATCH ; Nope - try the next slot + bne no_match ; Nope - try the next slot dex ; Yes! Keep testing - bpl TESTID ; Fall through if all done - jmp FOUND_MOUSE + bpl :- ; Fall through if all done + jmp found -NOMATCH: +no_match: dey ; Didn't match - bne TESTSLOT ; Keep looking until slot 0 - sty MOUSE_SLOT ; Oops, no mouse - make a note + bne slot_loop ; Keep looking until slot 0 + sty mouse_slot ; Oops, no mouse - make a note rts ; and bail - ; -;;; Step 2: Set up indirect calling routines - ; + ;; Store results needed for call ($Cn and $n0) -FOUND_MOUSE: - ; Slot is in y +found: tya ; Slot is in y + ora #>SLOT_BASE ; Compute $Cn - needed for calls + sta mouse_fw_hi tya - ora #>SLOT_BASE ; Compute $Cn - needed for - sta MOUSEPTR+1 ; MSB of MOUSEPTR ($Cn00) - sta TOMOUSE_Cn ; X register before firmware calls - sta TOMOUSE_msb ; MSB of firmware calls - - lda #0 - sta MOUSEPTR ; LSB of MOUSEPTR ($Cn00) - - tya - asl ; Compute $n0 - needed for + asl ; Compute $n0 - needed for calls asl asl asl - sta TOMOUSE_n0 ; Y register before firmware calls + sta mouse_op - ; -;;; Step 3: Configure the mouse card - ; + ;; Initialize and configure mouse card -;;; Initialize the mouse for use - jsr INITMOUSE ; reset, clamp to 0-1023 x/y - lda #1 ; mouse on, no interrupts - jsr SETMOUSE ; TODO: test carry bit result (set = error) - ; -;;; Since we want deltas, clamp and center - ; - ClampMouse MOUSE_CLAMP_X, MOUSE_MIN_X, MOUSE_MAX_X - ClampMouse MOUSE_CLAMP_Y, MOUSE_MIN_Y, MOUSE_MAX_Y - PosMouse MOUSE_CENTER_X, MOUSE_CENTER_Y + MOUSE_CALL InitMouse ; reset, clamp to 0-1023 x/y + + DoSetMouse $01 ; mouse on, no interrupts + ; TODO: test carry bit result (set = error) + + ;; Clamp for deltas + DoClampMouse MOUSE_CLAMP_X, MOUSE_CLAMP_MIN, MOUSE_CLAMP_MAX + DoClampMouse MOUSE_CLAMP_Y, MOUSE_CLAMP_MIN, MOUSE_CLAMP_MAX + + DoPosMouse MOUSE_CENTER, MOUSE_CENTER cli ; Enable interrupts so mouse can function rts - .endproc - -;;;-------------------------------------------------- -;;; Indirect jump table for mouse firmware routines ;;;-------------------------------------------------- +;;; Call mouse firmware, param in A, routine in Y -SETMOUSE: ldy #$12 - jmp GoMouse -SERVEMOUSE: ldy #$13 - jmp GoMouse -READMOUSE: ldy #$14 - jmp GoMouse -CLEARMOUSE: ldy #$15 - jmp GoMouse -POSMOUSE: ldy #$16 - jmp GoMouse -CLAMPMOUSE: ldy #$17 - jmp GoMouse -HOMEMOUSE: ldy #$18 - jmp GoMouse -INITMOUSE: ldy #$19 - jmp GoMouse +.proc CallMouse + pha ; Save A (param) + ldx mouse_fw_hi ; $Cn + stx mouse_ptr+1 + lda #0 + sta mouse_ptr + lda (mouse_ptr),y ; Look up routine offset + sta mouse_ptr -;;;-------------------------------------------------- + pla ; param in A + ldy mouse_op ; $n0 in Y -.proc GoMouse - tax ; Preserve the value in A - lda (MOUSEPTR),Y ; Get the routine entry point - sta TOMOUSE_lsb ; Patch the JMP instruction - txa ; Restore the value in A - -;;; The following operand bytes must be patched by the -;;; initialization code which detects the mouse. - -BANK := $C054 - -TOMOUSE: -TOMOUSE_Cn := *+1 - ldx #$C1 ; Set up slot in $Cn form in X -TOMOUSE_n0 := *+1 - ldy #$10 ; Set up slot in $n0 form in Y - php ; Save interrupt state - sei ; No interrupts while calling - bit BANK -TOMOUSE_slot := *+1 - jsr 0 ; Go to the mouse routine - plp ; Restore interrupt state + php + sei + jsr call + plp rts + +call: jmp (mouse_ptr) .endproc -TOMOUSE_Cn := GoMouse::TOMOUSE_Cn -TOMOUSE_n0 := GoMouse::TOMOUSE_n0 -TOMOUSE_lsb := GoMouse::TOMOUSE_slot -TOMOUSE_msb := GoMouse::TOMOUSE_slot+1 - - -;;; TODO: Turn this into a proper delta-sending routine - ;;;-------------------------------------------------- -.proc FOOMOUSE +;;; Read mouse pos, send deltas, and recenter - txa ; save x - pha - tya ; save y - pha +.proc SendMouse + SaveRegisters + lda mouse_slot + beq done - jsr READMOUSE - - jmp DONE - - ldx MOUSE_SLOT + MOUSE_CALL ReadMouse + lda Protocol::MouseX + jsr SSC::Put + lda #1 ; Data size + jsr SSC::Put + ldx mouse_slot lda MOUSE_X_LSB,x - sta LAST_MX + ora MOUSE_POS_MASK + jsr SSC::Put + lda Protocol::MouseY + jsr SSC::Put + lda #1 ; Data size + jsr SSC::Put + ldx mouse_slot lda MOUSE_Y_LSB,x - sta LAST_MY - - lda LAST_MX - cmp #MOUSE_CENTER_X - bne SEND - - lda LAST_MY - cmp #MOUSE_CENTER_Y - beq DONE - -SEND: - lda LAST_MX - ora #SIS_MX - jsr SSC::Put - lda LAST_MY - ora #SIS_MY + ora MOUSE_POS_MASK jsr SSC::Put - PosMouse MOUSE_CENTER_X, MOUSE_CENTER_Y + lda Protocol::MouseBtn + jsr SSC::Put + lda #1 ; Data size + jsr SSC::Put + ldx mouse_slot + lda MOUSE_STATUS,x + jsr SSC::Put -DONE: - pla ; restore y - tay - pla ; restore x - tax + DoPosMouse MOUSE_CENTER, MOUSE_CENTER + +done: RestoreRegisters rts - .endproc .endproc