From f92ef31fe4ec37fdd9db78e6d65391a3417d1554 Mon Sep 17 00:00:00 2001 From: Joshua Bell Date: Sun, 28 Oct 2018 19:49:17 -0700 Subject: [PATCH] snapshot --- client/client.bin | Bin 462 -> 465 bytes client/client.list | 1407 ++++++++++++++++++-------------------------- client/client.s | 802 +++++++------------------ client/mouse.inc | 293 +++++++++ client/ssc.inc | 100 ++++ 5 files changed, 1164 insertions(+), 1438 deletions(-) create mode 100644 client/mouse.inc create mode 100644 client/ssc.inc diff --git a/client/client.bin b/client/client.bin index c74512b7e994b041434a089ea0b2f73cd41d76b9..3ab452710ddc6cae2f997b4dc9708898c2fbdfc4 100644 GIT binary patch literal 465 zcmYL_u}i~16voq}Lt{ZQi7xdv5sG9Kbm$^P>Cj5W^*yIJ6x;+CT?$pWfFRhVAcaD& zn8nTQ7NIFkdw)d`r{G|vS-fj)^DXZ_zTdqEU%3WrQkTs>%eQs@8sPf}whiv>gLed8 z6+XQ^@D9N{25|g)zIzo|V(QW+2j$!#C#HUCps3zMBnFT>Bu_x9w^We0cO@D-9 z-PgFaBUw^}@(ubHxAXJA3m=X!Hq#WjZ81FzG2W7!7YNHJZ?3$5p`dIyR?v6}8Oob0 z-_b}RX`M)!b~sVV3idLt{ZQiCyXkf+BRtPYAda>7b&Bi`?fFH~j@pg(_UYt%wCFRC>jm zI*5xN4%)Om$gc?E6dbHHi+8PU-sQXZ-sir9mwzB!Ae0eY0!0EZNDlirf+9n1{hmuio&s(DF+xA)#e$(GTK`U&rda!lS2&+=TKIAYvEf4 zl#<4dlI6&ePDcOaSE_#a-O4ODS4z#v`Nm82z1Q)&9$`?6;22dc^hnTMLHC6!i?pKv z;ygVRIw$IexoW1ZF{7h9OLSpBWJ&3)-erZRDIVYP`3;*{;Xk0?L;n>&{X6u#=s&6M h_?6f?5A1O4(Yheoc|krL^VE>CI key down transition -006064 1 ; since the msb can change before the key code. Instead, consider -006064 1 ; these cases: -006064 1 ; -006064 1 ; OLD STATE KEYBD STROBE RESULT -006064 1 ; Up Up - No-op -006064 1 ; Up Down - Save and send key down -006064 1 ; Down - Up Save and send key up -006064 1 ; Down - Down Save and send key ONLY if different -006064 1 ; -006064 1 -006064 1 AD C9 61 lda LASTKB -006067 1 D0 0E bne KEY_WAS_DOWN -006069 1 -006069 1 KEY_WAS_UP: -006069 1 AD 00 C0 lda KEYBD ; Read keyboard -00606C 1 10 27 bpl END_KEY ; - still up -00606E 1 8D C9 61 sta LASTKB ; Down, so save it -006071 1 20 9A 61 jsr SSCPUT ; and send it -006074 1 4C 26 61 jmp DONE +000000r 1 .org $6000 +006000 1 4C 54 60 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 .proc Init +006003 2 ;;;--------------------------------------------------------- +006003 2 ;;; Initialize the SSC; slot passed in A +006003 2 ;;;--------------------------------------------------------- +006003 2 0A asl ; Slot passed in A +006004 2 0A asl +006005 2 0A asl +006006 2 0A asl ; Now $S0 +006007 2 69 88 adc #$88 ; Low byte of UADATA +006009 2 AA tax +00600A 2 A9 0B lda #CMND_NRDI ; Command register: no parity, RTS on, DTR on, no interrupts +00600C 2 9D 02 C0 sta $C002,X +00600F 2 AC C9 61 ldy PSPEED ; Control register: look up by baud rate (8 data bits, 1 stop bit) +006012 2 B9 C5 61 lda BPSCTRL,Y +006015 2 9D 03 C0 sta $C003,X +006018 2 8E 38 60 stx MOD_UADATA_1+1 ; Modify references to +00601B 2 8E 45 60 stx MOD_UADATA_2+1 ; UADATA to point at +00601E 2 8E 51 60 stx MOD_UADATA_3+1 ; correct slot (UADATA+S0) +006021 2 E8 inx +006022 2 8E 2E 60 stx MOD_UASTAT_1+1 ; Modify reference to +006025 2 8E 3C 60 stx MOD_UASTAT_2+1 ; UASTAT to point at +006028 2 8E 49 60 stx MOD_UASTAT_3+1 ; correct slot (UASTAT+S0) +00602B 2 60 rts +00602C 2 +00602C 2 .endproc +00602C 2 +00602C 2 +00602C 2 ;;;--------------------------------------------------------- +00602C 2 .proc Put +00602C 2 ;;;--------------------------------------------------------- +00602C 2 ;;; Send accumulator out the serial port +00602C 2 ;;;--------------------------------------------------------- +00602C 2 48 pha ; Push A onto the stack +00602D 2 MOD_UASTAT_1: +00602D 2 AD 89 C0 : lda UASTAT ; Check status bits +006030 2 29 70 and #$70 +006032 2 C9 10 cmp #$10 +006034 2 D0 F7 bne :- ; Output register is full, so loop +006036 2 68 pla +006037 2 MOD_UADATA_1: +006037 2 8D 88 C0 sta UADATA ; Put character +00603A 2 60 rts +00603B 2 .endproc +00603B 2 MOD_UASTAT_1 := Put::MOD_UASTAT_1 +00603B 2 MOD_UADATA_1 := Put::MOD_UADATA_1 +00603B 2 +00603B 2 ;;;--------------------------------------------------------- +00603B 2 .proc Get +00603B 2 ;;;--------------------------------------------------------- +00603B 2 ;;; Read a character from the serial port to the accumulator +00603B 2 ;;;--------------------------------------------------------- +00603B 2 MOD_UASTAT_2: +00603B 2 AD 89 C0 lda UASTAT ; Check status bits +00603E 2 29 68 and #$68 +006040 2 C9 08 cmp #$8 +006042 2 D0 F7 bne Get ; Input register empty, loop +006044 2 MOD_UADATA_2: +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 .proc HasData +006048 2 ;;;--------------------------------------------------------- +006048 2 ;;; Read a character from the serial port to the accumulator +006048 2 ;;;--------------------------------------------------------- +006048 2 MOD_UASTAT_3: +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 .proc Reset +006050 2 ;;;--------------------------------------------------------- +006050 2 ;;; Clean up serial port +006050 2 ;;;--------------------------------------------------------- +006050 2 MOD_UADATA_3: +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 1 .endif ; MOUSE_SUPPORT +006054 1 +006054 1 +006054 1 ;;;--------------------------------------------------------- +006054 1 .proc AppEntry +006054 1 ;;;--------------------------------------------------------- +006054 1 ;;; Initialize the application, and enter the main loop +006054 1 ;;;--------------------------------------------------------- +006054 1 AD CA 61 lda PSLOT ; Use slot 2 +006057 1 20 03 60 jsr SSC::Init ; Initialize Super Serial Card +00605A 1 20 80 61 jsr InitHires ; Initialize Hi-Res graphics +00605D 1 20 94 60 jsr InitInput ; Initialize input devices +006060 1 20 6D 60 jsr MainLoop +006063 1 +006063 1 ; fall through +006063 1 .endproc +006063 1 +006063 1 ;;;--------------------------------------------------------- +006063 1 .proc AppExit +006063 1 ;;;--------------------------------------------------------- +006063 1 ;;; Clean up and exit app +006063 1 ;;;--------------------------------------------------------- +006063 1 20 50 60 jsr SSC::Reset +006066 1 8D 54 C0 sta PAGE1 +006069 1 8D 51 C0 sta SETTEXT +00606C 1 60 rts +00606D 1 .endproc +00606D 1 +00606D 1 +00606D 1 ;;;------------------------------------------------------------------- +00606D 1 ; +00606D 1 ;;; Main loop functionality +00606D 1 ; +00606D 1 ;;;------------------------------------------------------------------- +00606D 1 +00606D 1 +00606D 1 ;;;--------------------------------------------------------- +00606D 1 .proc MainLoop +00606D 1 ;;;--------------------------------------------------------- +00606D 1 +00606D 1 ;;; TODO: Sort out the protocol - should be able to send +00606D 1 ;;; input state without receiving data +00606D 1 ;;; jsr SSCHasData ; Anything to read? +00606D 1 ;;; bne :+ ; Nope +00606D 1 +00606D 1 20 77 60 : jsr ReceivePage +006070 1 20 97 61 jsr FlipHires +006073 1 4C 6D 60 jmp :- ; TODO: define an exit trigger +006076 1 60 rts +006077 1 .endproc 006077 1 -006077 1 KEY_WAS_DOWN: -006077 1 ; key was down - strobe should match -006077 1 ; unless the key changed or was released -006077 1 AD 10 C0 lda STROBE -00607A 1 30 0B bmi STROBE_DOWN -00607C 1 STROBE_UP: -00607C 1 A9 00 lda #SIS_KBUP ; Key was released -00607E 1 8D C9 61 sta LASTKB ; so save it -006081 1 20 9A 61 jsr SSCPUT ; and send it -006084 1 4C 26 61 jmp DONE -006087 1 STROBE_DOWN: -006087 1 CD C9 61 cmp LASTKB ; Same key as last time? -00608A 1 F0 09 beq END_KEY ; - no change -00608C 1 8D C9 61 sta LASTKB ; New key, so save it -00608F 1 20 9A 61 jsr SSCPUT ; and send it -006092 1 4C 26 61 jmp DONE -006095 1 -006095 1 END_KEY: -006095 1 -006095 1 ;-------------------------------------- -006095 1 ; Send Open Apple state, if it changed -006095 1 -006095 1 ; TODO: Can simplify this code if we make the high bits the same -006095 1 ; for both OA states and bit = 0 down: lda OPNAPPLE ; ROL ; LDA #0 ; ROL ; ORA #signature -006095 1 -006095 1 TEST_OA: -006095 1 AD 61 C0 lda OPNAPPLE ; Test Open Apple state -006098 1 30 10 bmi OA_IS_DOWN -00609A 1 OA_IS_UP: -00609A 1 A9 02 lda #SIS_OAUP -00609C 1 CD CA 61 cmp LASTOA ; Changed? -00609F 1 F0 19 beq END_OA ; Nope -0060A1 1 8D CA 61 sta LASTOA ; Yes, save it / send it! -0060A4 1 20 9A 61 jsr SSCPUT -0060A7 1 4C 26 61 jmp DONE -0060AA 1 OA_IS_DOWN: -0060AA 1 A9 01 lda #SIS_OADOWN -0060AC 1 CD CA 61 cmp LASTOA ; Changed? -0060AF 1 F0 09 beq END_OA ; Nope -0060B1 1 8D CA 61 sta LASTOA ; Yes, save it / send it! -0060B4 1 20 9A 61 jsr SSCPUT -0060B7 1 4C 26 61 jmp DONE -0060BA 1 -0060BA 1 END_OA: -0060BA 1 -0060BA 1 ;-------------------------------------- -0060BA 1 ; Send Closed Apple state, if it changed -0060BA 1 -0060BA 1 TEST_CA: -0060BA 1 AD 62 C0 lda CLSAPPLE ; Has the Open Apple/Button 1 value changed? -0060BD 1 30 10 bmi CA_IS_DOWN -0060BF 1 CA_IS_UP: -0060BF 1 A9 04 lda #SIS_CAUP -0060C1 1 CD CB 61 cmp LASTCA ; Changed? -0060C4 1 F0 19 beq END_CA ; Nope -0060C6 1 8D CB 61 sta LASTCA ; Yes, save it -0060C9 1 20 9A 61 jsr SSCPUT ; and send it -0060CC 1 4C 26 61 jmp DONE -0060CF 1 CA_IS_DOWN: -0060CF 1 A9 03 lda #SIS_CADOWN -0060D1 1 CD CB 61 cmp LASTCA ; Changed? -0060D4 1 F0 09 beq END_CA ; Nope -0060D6 1 8D CB 61 sta LASTCA ; Yes, save it -0060D9 1 20 9A 61 jsr SSCPUT ; and send it -0060DC 1 4C 26 61 jmp DONE -0060DF 1 -0060DF 1 END_CA: -0060DF 1 -0060DF 1 .ifdef PADDLE_SUPPORT -0060DF 1 -0060DF 1 ;-------------------------------------- -0060DF 1 ; Send Paddle 0 state, if it changed -0060DF 1 TEST_PDL0: -0060DF 1 A2 00 ldx #0 -0060E1 1 20 1E FB jsr PREAD -0060E4 1 98 tya -0060E5 1 4A lsr ; Shift to low nibble -0060E6 1 4A lsr -0060E7 1 4A lsr -0060E8 1 4A lsr -0060E9 1 09 30 ora #SIS_PDL0 ; And mark it with the signature -0060EB 1 CD CC 61 cmp LASTP0 ; Change? -0060EE 1 F0 09 beq END_PDL0 ; Nope -0060F0 1 8D CC 61 sta LASTP0 ; Yes, save it -0060F3 1 20 9A 61 jsr SSCPUT ; and send it -0060F6 1 4C 26 61 jmp DONE -0060F9 1 END_PDL0: -0060F9 1 ; Chew up time so next paddle read will be correct -0060F9 1 ; TODO: Replace this with a "read both" strobes -0060F9 1 ; routine -0060F9 1 EA EA EA EA : .repeat 11 ; By experiment, need 11 NOPs. -0060FD 1 EA EA EA EA -006101 1 EA EA EA -006104 1 nop -006104 1 .endrep -006104 1 C8 iny -006105 1 D0 F2 bne :- -006107 1 -006107 1 ;-------------------------------------- -006107 1 ; Send Paddle 1 state, if it changed -006107 1 TEST_PDL1: -006107 1 A2 01 ldx #1 -006109 1 20 1E FB jsr PREAD -00610C 1 98 tya -00610D 1 4A lsr ; Shift to low nibble -00610E 1 4A lsr -00610F 1 4A lsr -006110 1 4A lsr -006111 1 09 40 ora #SIS_PDL1 ; And mark it with the signature -006113 1 CD CD 61 cmp LASTP1 ; Change? -006116 1 F0 09 beq END_PDL1 ; Nope -006118 1 8D CD 61 sta LASTP1 ; Yes, save it -00611B 1 20 9A 61 jsr SSCPUT ; and send it -00611E 1 4C 26 61 jmp DONE -006121 1 END_PDL1: -006121 1 ; NOTE: No need to chew time like PDL0 -006121 1 ; since data receive will make up for it; if we -006121 1 ; loop in SENDINPUTSTATE need to add it here -006121 1 -006121 1 .endif -006121 1 -006121 1 -006121 1 ;-------------------------------------- -006121 1 .ifdef MOUSE_SUPPORT -006121 1 .error "Mouse support not fully implemented" -006121 1 .endif -006121 1 -006121 1 ;-------------------------------------- -006121 1 ; No state changes so send sync byte -006121 1 -006121 1 A9 7F lda #SIS_SYNC -006123 1 20 9A 61 jsr SSCPUT -006126 1 -006126 1 DONE: -006126 1 68 A8 68 AA RestoreRegisters -00612A 1 68 -00612B 1 60 rts -00612C 1 -00612C 1 .endproc -00612C 1 -00612C 1 -00612C 1 ;------------------------------------------------------------------- -00612C 1 ; -00612C 1 ; Hi-res graphics routines -00612C 1 ; -00612C 1 ;------------------------------------------------------------------- -00612C 1 -00612C 1 ;--------------------------------------------------------- -00612C 1 .proc INITHIRES -00612C 1 ;--------------------------------------------------------- -00612C 1 ; Set up the graphics display and pointers -00612C 1 ;--------------------------------------------------------- -00612C 1 A9 20 lda #PLOTPAGE1 ; clear page 1 -00612E 1 85 E6 sta PLOTPAGE -006130 1 20 59 61 jsr CLEARHIRES +006077 1 +006077 1 ;;;--------------------------------------------------------- +006077 1 .proc ReceivePage +006077 1 ;;;--------------------------------------------------------- +006077 1 ;;; Pull a hi-res page down over serial +006077 1 ; +006077 1 ;;; Protocol is: +006077 1 ;;; * Recieve 256 bytes (graphic data) +006077 1 ;;; * Send 1 byte (input state) +006077 1 ;;;--------------------------------------------------------- +006077 1 +006077 1 A9 00 lda #0 ; set up write pointer +006079 1 85 FA sta ZP +00607B 1 A5 E6 lda PLOTPAGE +00607D 1 85 FB sta ZP+1 +00607F 1 A2 20 ldx #PAGESIZE ; plan to receive this many pages +006081 1 A0 00 ldy #0 +006083 1 +006083 1 20 3B 60 : jsr SSC::Get ; TODO: look for escape codes in the sequence +006086 1 91 FA sta (ZP),Y +006088 1 C8 iny +006089 1 D0 F8 bne :- ; Do a full page... +00608B 1 +00608B 1 20 B2 60 jsr SendInputState ; brief moment to send data back upstream +00608E 1 +00608E 1 E6 FB inc ZP+1 +006090 1 CA dex +006091 1 D0 F0 bne :- ; ...as many pages as we need +006093 1 60 rts +006094 1 .endproc +006094 1 +006094 1 +006094 1 ;;;------------------------------------------------------------------- +006094 1 ; +006094 1 ;;; Input device routines +006094 1 ; +006094 1 ;;;------------------------------------------------------------------- +006094 1 ;;; Protocol: +006094 1 ;;; $7f - $ff - key down, ASCII code + $80 +006094 1 ;;; otherwise, a transition: +006094 1 ; +006094 1 SIS_KBUP = $00 ; Key up +006094 1 SIS_OADOWN = $01 ; Open Apple transitioned to down +006094 1 SIS_OAUP = $02 ; Open Apple transitioned to up +006094 1 SIS_CADOWN = $03 ; Closed Apple transitioned to down +006094 1 SIS_CAUP = $04 ; Closed Apple transitioned to up +006094 1 ; +006094 1 ;;; $05 - $0f : reserved +006094 1 ; +006094 1 SIS_MX = $10 ; Mouse X high nibble +006094 1 SIS_MY = $20 ; Mouse Y high nibble +006094 1 SIS_PDL0 = $30 ; Paddle 0 high nibble +006094 1 SIS_PDL1 = $40 ; Paddle 1 high nibble +006094 1 ; +006094 1 ;;; $50 - $7e : reserved +006094 1 ; +006094 1 SIS_SYNC = $7f +006094 1 +006094 1 ;;;--------------------------------------------------------- +006094 1 .proc InitInput +006094 1 ;;;--------------------------------------------------------- +006094 1 ;;; Initialize input devices and storage for detecting +006094 1 ;;; state transitions +006094 1 ;;;--------------------------------------------------------- +006094 1 +006094 1 ;;; Init keyboard state +006094 1 A9 00 lda #SIS_KBUP +006096 1 8D CC 61 sta LASTKB +006099 1 +006099 1 ;;; Init Open/Closed Apple states +006099 1 A9 02 lda #SIS_OAUP ; NOTE: Don't store OA state as it fluctuates +00609B 1 8D CD 61 sta LASTOA +00609E 1 A9 04 lda #SIS_CAUP ; NOTE: Don't store CA state as it fluctuates +0060A0 1 8D CE 61 sta LASTCA +0060A3 1 +0060A3 1 .ifdef PADDLE_SUPPORT +0060A3 1 ;;; Init Paddle state +0060A3 1 A9 30 lda #SIS_PDL0 +0060A5 1 09 08 ora #8 ; Middle of range 0...15 +0060A7 1 8D CF 61 sta LASTP0 +0060AA 1 A9 40 lda #SIS_PDL1 +0060AC 1 09 08 ora #8 ; Middle of range 0...15 +0060AE 1 8D D0 61 sta LASTP1 +0060B1 1 .endif +0060B1 1 +0060B1 1 .ifdef MOUSE_SUPPORT +0060B1 1 jsr Mouse::FindMouse +0060B1 1 .endif +0060B1 1 +0060B1 1 60 rts +0060B2 1 .endproc +0060B2 1 +0060B2 1 +0060B2 1 ;;;--------------------------------------------------------- +0060B2 1 .proc SendInputState +0060B2 1 ;;;--------------------------------------------------------- +0060B2 1 ;;; Send keyboard joystick and/or mouse state over the +0060B2 1 ;;; serial port +0060B2 1 ; +0060B2 1 ;;; Algorithm: +0060B2 1 ;;; - Send key state (if it changed) +0060B2 1 ;;; - otherwise send open-apple state (if it changed) +0060B2 1 ;;; - otherwise send closed-apple state (if it changed) +0060B2 1 ;;; - otherwise send paddle 0 state (if it changed) +0060B2 1 ;;; - (TODO: Mouse state) +0060B2 1 ;;; - otherwise send sync byte +0060B2 1 ;;;--------------------------------------------------------- +0060B2 1 +0060B2 1 48 8A 48 98 SaveRegisters ; Store registers +0060B6 1 48 +0060B7 1 18 clc +0060B8 1 +0060B8 1 ;;;-------------------------------------- +0060B8 1 ;;; Send key state, if it changed +0060B8 1 +0060B8 1 ;;; NOTE: Can't use STROBE to detect key up -> key down transition +0060B8 1 ;;; since the msb can change before the key code. Instead, consider +0060B8 1 ;;; these cases: +0060B8 1 ; +0060B8 1 ;;; OLD STATE KEYBD STROBE RESULT +0060B8 1 ;;; Up Up - No-op +0060B8 1 ;;; Up Down - Save and send key down +0060B8 1 ;;; Down - Up Save and send key up +0060B8 1 ;;; Down - Down Save and send key ONLY if different +0060B8 1 ; +0060B8 1 +0060B8 1 AD CC 61 lda LASTKB +0060BB 1 D0 0E bne KEY_WAS_DOWN +0060BD 1 +0060BD 1 KEY_WAS_UP: +0060BD 1 AD 00 C0 lda KEYBD ; Read keyboard +0060C0 1 10 27 bpl END_KEY ; - still up +0060C2 1 8D CC 61 sta LASTKB ; Down, so save it +0060C5 1 20 2C 60 jsr SSC::Put ; and send it +0060C8 1 4C 7A 61 jmp DONE +0060CB 1 +0060CB 1 KEY_WAS_DOWN: +0060CB 1 ; key was down - strobe should match +0060CB 1 ; unless the key changed or was released +0060CB 1 AD 10 C0 lda STROBE +0060CE 1 30 0B bmi STROBE_DOWN +0060D0 1 STROBE_UP: +0060D0 1 A9 00 lda #SIS_KBUP ; Key was released +0060D2 1 8D CC 61 sta LASTKB ; so save it +0060D5 1 20 2C 60 jsr SSC::Put ; and send it +0060D8 1 4C 7A 61 jmp DONE +0060DB 1 STROBE_DOWN: +0060DB 1 CD CC 61 cmp LASTKB ; Same key as last time? +0060DE 1 F0 09 beq END_KEY ; - no change +0060E0 1 8D CC 61 sta LASTKB ; New key, so save it +0060E3 1 20 2C 60 jsr SSC::Put ; and send it +0060E6 1 4C 7A 61 jmp DONE +0060E9 1 +0060E9 1 END_KEY: +0060E9 1 +0060E9 1 ;;;-------------------------------------- +0060E9 1 ;;; Send Open Apple state, if it changed +0060E9 1 +0060E9 1 ;;; TODO: Can simplify this code if we make the high bits the same +0060E9 1 ;;; for both OA states and bit = 0 down: lda OPNAPPLE ; ROL ; LDA #0 ; ROL ; ORA #signature +0060E9 1 +0060E9 1 TEST_OA: +0060E9 1 AD 61 C0 lda OPNAPPLE ; Test Open Apple state +0060EC 1 30 10 bmi OA_IS_DOWN +0060EE 1 OA_IS_UP: +0060EE 1 A9 02 lda #SIS_OAUP +0060F0 1 CD CD 61 cmp LASTOA ; Changed? +0060F3 1 F0 19 beq END_OA ; Nope +0060F5 1 8D CD 61 sta LASTOA ; Yes, save it / send it! +0060F8 1 20 2C 60 jsr SSC::Put +0060FB 1 4C 7A 61 jmp DONE +0060FE 1 OA_IS_DOWN: +0060FE 1 A9 01 lda #SIS_OADOWN +006100 1 CD CD 61 cmp LASTOA ; Changed? +006103 1 F0 09 beq END_OA ; Nope +006105 1 8D CD 61 sta LASTOA ; Yes, save it / send it! +006108 1 20 2C 60 jsr SSC::Put +00610B 1 4C 7A 61 jmp DONE +00610E 1 +00610E 1 END_OA: +00610E 1 +00610E 1 ;;;-------------------------------------- +00610E 1 ;;; Send Closed Apple state, if it changed +00610E 1 +00610E 1 TEST_CA: +00610E 1 AD 62 C0 lda CLSAPPLE ; Has the Open Apple/Button 1 value changed? +006111 1 30 10 bmi CA_IS_DOWN +006113 1 CA_IS_UP: +006113 1 A9 04 lda #SIS_CAUP +006115 1 CD CE 61 cmp LASTCA ; Changed? +006118 1 F0 19 beq END_CA ; Nope +00611A 1 8D CE 61 sta LASTCA ; Yes, save it +00611D 1 20 2C 60 jsr SSC::Put ; and send it +006120 1 4C 7A 61 jmp DONE +006123 1 CA_IS_DOWN: +006123 1 A9 03 lda #SIS_CADOWN +006125 1 CD CE 61 cmp LASTCA ; Changed? +006128 1 F0 09 beq END_CA ; Nope +00612A 1 8D CE 61 sta LASTCA ; Yes, save it +00612D 1 20 2C 60 jsr SSC::Put ; and send it +006130 1 4C 7A 61 jmp DONE 006133 1 -006133 1 20 43 61 jsr FLIPHIRES ; then show it and flip to 2 -006136 1 8D 57 C0 sta SETHIRES -006139 1 8D 50 C0 sta CLRTEXT -00613C 1 8D 52 C0 sta CLRMIXED -00613F 1 8D 54 C0 sta PAGE1 -006142 1 -006142 1 60 rts -006143 1 .endproc -006143 1 -006143 1 -006143 1 ;--------------------------------------------------------- -006143 1 .proc FLIPHIRES -006143 1 ;--------------------------------------------------------- -006143 1 ; Call when done with the current plotting page -006143 1 ; (selected in PLOTPAGE) and it will be shown and the -006143 1 ; other page will be shown. -006143 1 ;--------------------------------------------------------- -006143 1 A5 E6 lda PLOTPAGE ; plotting on which page? -006145 1 C9 20 cmp #PLOTPAGE1 -006147 1 F0 08 beq :+ -006149 1 -006149 1 8D 55 C0 sta PAGE2 ; page 2 - so show it -00614C 1 A9 20 lda #PLOTPAGE1 ; and plot on page 1 -00614E 1 85 E6 sta PLOTPAGE -006150 1 60 rts -006151 1 -006151 1 8D 54 C0 : sta PAGE1 ; page 1 - so show it -006154 1 A9 40 lda #PLOTPAGE2 ; and plot on page 2 -006156 1 85 E6 sta PLOTPAGE -006158 1 60 rts -006159 1 .endproc -006159 1 -006159 1 -006159 1 ;--------------------------------------------------------- -006159 1 .proc CLEARHIRES -006159 1 ;--------------------------------------------------------- -006159 1 ; Clear hires plotting page (selected in PLOTPAGE) to -006159 1 ; black uses ZP; not terribly efficient -006159 1 ;--------------------------------------------------------- -006159 1 A9 00 lda #0 ; Set up ZP as a pointer into the hires page -00615B 1 85 FA sta ZP -00615D 1 A5 E6 lda PLOTPAGE -00615F 1 85 FB sta ZP+1 -006161 1 A2 20 ldx #PAGESIZE ; Clear this many pages -006163 1 A9 00 lda #0 ; with black! -006165 1 A8 tay -006166 1 91 FA : sta (ZP),Y -006168 1 C8 iny -006169 1 D0 FB bne :- -00616B 1 E6 FB inc ZP+1 -00616D 1 CA dex -00616E 1 D0 F6 bne :- -006170 1 60 rts -006171 1 .endproc -006171 1 -006171 1 -006171 1 -006171 1 ;------------------------------------------------------------------- -006171 1 ; -006171 1 ; Serial port routines -006171 1 ; -006171 1 ;------------------------------------------------------------------- -006171 1 -006171 1 -006171 1 ;--------------------------------------------------------- -006171 1 .proc INITSSC -006171 1 ;--------------------------------------------------------- -006171 1 ; Initialize the SSC; slot passed in A -006171 1 ; [based on ADTPro] -006171 1 ;--------------------------------------------------------- -006171 1 0A asl ; Slot passed in A -006172 1 0A asl -006173 1 0A asl -006174 1 0A asl ; Now $S0 -006175 1 69 88 adc #$88 ; Low byte of UADATA -006177 1 AA tax -006178 1 A9 0B lda #CMND_NRDI ; Command register: no parity, RTS on, DTR on, no interrupts -00617A 1 9D 02 C0 sta $C002,X -00617D 1 AC C6 61 ldy PSPEED ; Control register: look up by baud rate (8 data bits, 1 stop bit) -006180 1 B9 C2 61 lda BPSCTRL,Y -006183 1 9D 03 C0 sta $C003,X -006186 1 8E A6 61 stx MOD_UADATA_1+1 ; Modify references to -006189 1 8E B3 61 stx MOD_UADATA_2+1 ; UADATA to point at -00618C 1 8E BF 61 stx MOD_UADATA_3+1 ; correct slot (UADATA+S0) -00618F 1 E8 inx -006190 1 8E 9C 61 stx MOD_UASTAT_1+1 ; Modify reference to -006193 1 8E AA 61 stx MOD_UASTAT_2+1 ; UASTAT to point at -006196 1 8E B7 61 stx MOD_UASTAT_3+1 ; correct slot (UASTAT+S0) -006199 1 60 rts -00619A 1 -00619A 1 .endproc -00619A 1 -00619A 1 -00619A 1 ;--------------------------------------------------------- -00619A 1 SSCPUT: -00619A 1 ;--------------------------------------------------------- -00619A 1 ; Send accumulator out the serial port -00619A 1 ; (this is a blocking call) -00619A 1 ; [based on ADTPro] -00619A 1 ;--------------------------------------------------------- -00619A 1 48 pha ; Push A onto the stack -00619B 1 MOD_UASTAT_1: -00619B 1 AD 89 C0 : lda UASTAT ; Check status bits -00619E 1 29 70 and #$70 -0061A0 1 C9 10 cmp #$10 -0061A2 1 D0 F7 bne :- ; Output register is full, so loop -0061A4 1 68 pla -0061A5 1 MOD_UADATA_1: -0061A5 1 8D 88 C0 sta UADATA ; Put character -0061A8 1 60 rts -0061A9 1 -0061A9 1 -0061A9 1 ;--------------------------------------------------------- -0061A9 1 SSCGET: -0061A9 1 ;--------------------------------------------------------- -0061A9 1 ; Read a character from the serial port to the accumulator -0061A9 1 ; (this is a blocking call) -0061A9 1 ; [based on ADTPro] -0061A9 1 ;--------------------------------------------------------- -0061A9 1 MOD_UASTAT_2: -0061A9 1 AD 89 C0 lda UASTAT ; Check status bits -0061AC 1 29 68 and #$68 -0061AE 1 C9 08 cmp #$8 -0061B0 1 D0 F7 bne SSCGET ; Input register empty, loop -0061B2 1 MOD_UADATA_2: -0061B2 1 AD 88 C0 lda UADATA ; Get character -0061B5 1 60 rts -0061B6 1 -0061B6 1 -0061B6 1 ;--------------------------------------------------------- -0061B6 1 SSCHASDATA: -0061B6 1 ;--------------------------------------------------------- -0061B6 1 ; Read a character from the serial port to the accumulator -0061B6 1 ; (this is a blocking call) -0061B6 1 ; [based on ADTPro] -0061B6 1 ;--------------------------------------------------------- -0061B6 1 MOD_UASTAT_3: -0061B6 1 AD 89 C0 lda UASTAT ; Check status bits -0061B9 1 29 68 and #$68 -0061BB 1 C9 08 cmp #$8 -0061BD 1 60 rts -0061BE 1 -0061BE 1 -0061BE 1 ;--------------------------------------------------------- -0061BE 1 RESETSSC: -0061BE 1 ;--------------------------------------------------------- -0061BE 1 ; Clean up serial port -0061BE 1 ; [based on ADTPro] -0061BE 1 ;--------------------------------------------------------- -0061BE 1 MOD_UADATA_3: -0061BE 1 2C 88 C0 bit UADATA -0061C1 1 60 rts -0061C2 1 -0061C2 1 -0061C2 1 -0061C2 1 .ifdef MOUSE_SUPPORT -0061C2 1 ;------------------------------------------------------------------- -0061C2 1 ; -0061C2 1 ; Mouse routines -0061C2 1 ; -0061C2 1 ;------------------------------------------------------------------- -0061C2 1 -0061C2 1 MOUSEPTR = $EB ; Zero page location -0061C2 1 -0061C2 1 MOUSE_MIN_X = $10 -0061C2 1 MOUSE_MAX_X = $1f -0061C2 1 MOUSE_CENTER_X = $17 -0061C2 1 MOUSE_MIN_Y = $20 -0061C2 1 MOUSE_MAX_Y = $2f -0061C2 1 MOUSE_CENTER_Y = $2f -0061C2 1 -0061C2 1 -0061C2 1 ;-------------------------------------------------- -0061C2 1 ; Macros for common mouse operations -0061C2 1 ;-------------------------------------------------- -0061C2 1 -0061C2 1 ;---------------------------------------- -0061C2 1 .macro ClampMouse axis, min, max -0061C2 1 ;---------------------------------------- -0061C2 1 ; axis: MOUSE_CLAMP_X or MOUSE_CLAMP_Y -0061C2 1 ; min: minimum value (2 byte) -0061C2 1 ; max: maximum value (2 byte) -0061C2 1 ;---------------------------------------- -0061C2 1 ; Clamp X to 0...255 -0061C2 1 lda #min -0061C2 1 sta MOUSE_CMIN_MSB -0061C2 1 lda #max -0061C2 1 sta MOUSE_CMAX_MSB -0061C2 1 lda #axis -0061C2 1 jsr CLAMPMOUSE -0061C2 1 .endmacro -0061C2 1 -0061C2 1 ;---------------------------------------- -0061C2 1 .macro PosMouse px, py -0061C2 1 ;---------------------------------------- -0061C2 1 ldx MOUSE_SLOT -0061C2 1 lda #px -0061C2 1 sta MOUSE_X_MSB,X -0061C2 1 lda #py -0061C2 1 sta MOUSE_Y_MSB,X -0061C2 1 jsr POSMOUSE -0061C2 1 .endmacro -0061C2 1 -0061C2 1 -0061C2 1 ;--------------------------------------------------------- -0061C2 1 .proc FINDMOUSE -0061C2 1 ;--------------------------------------------------------- -0061C2 1 ; Find and initialize the mouse port -0061C2 1 ;--------------------------------------------------------- -0061C2 1 -0061C2 1 ; Reference: http://home.swbell.net/rubywand/R034MOUSEPRG.TXT -0061C2 1 -0061C2 1 sei ; No interrupts while we're getting set up -0061C2 1 ; -0061C2 1 ; Step 1: Find the mouse card by scanning slots for ID bytes -0061C2 1 ; -0061C2 1 -0061C2 1 ldy #MAX_SLOT ; Start search in slot 7 -0061C2 1 -0061C2 1 TESTSLOT: -0061C2 1 sty MOUSE_SLOT ; Save for later -0061C2 1 tya -0061C2 1 clc -0061C2 1 adc #>SLOT_BASE ; Firmware is $c0 + slot -0061C2 1 sta MOD_MOUSE_ID + 2 ; Update msb of signature test -0061C2 1 ldx #MOUSEID_MAX ; This many signature bytes -0061C2 1 -0061C2 1 TESTID: -0061C2 1 lda MOUSEID_ADDR,x -0061C2 1 sta MOD_MOUSE_ID + 1 ; Update lsb of signature test -0061C2 1 MOD_MOUSE_ID: -0061C2 1 lda SLOT_BASE -0061C2 1 cmp MOUSEID_VAL,x ; Does it match the signature? -0061C2 1 bne NOMATCH ; Nope - try the next slot -0061C2 1 dex ; Yes! Keep testing -0061C2 1 bpl TESTID ; Fall through if all done -0061C2 1 jmp FOUND_MOUSE -0061C2 1 -0061C2 1 NOMATCH: -0061C2 1 dey ; Didn't match -0061C2 1 bne TESTSLOT ; Keep looking until slot 0 -0061C2 1 sty MOUSE_SLOT ; Oops, no mouse - make a note -0061C2 1 rts ; and bail -0061C2 1 -0061C2 1 ; -0061C2 1 ; Step 2: Set up indirect calling routines -0061C2 1 ; -0061C2 1 -0061C2 1 FOUND_MOUSE: -0061C2 1 ; Slot is in y -0061C2 1 -0061C2 1 tya -0061C2 1 ora #>SLOT_BASE ; Compute $Cn - needed for -0061C2 1 sta MOUSEPTR+1 ; MSB of MOUSEPTR ($Cn00) -0061C2 1 sta TOMOUSE_Cn ; X register before firmware calls -0061C2 1 sta TOMOUSE_msb ; MSB of firmware calls -0061C2 1 -0061C2 1 lda #0 -0061C2 1 sta MOUSEPTR ; LSB of MOUSEPTR ($Cn00) -0061C2 1 -0061C2 1 tya -0061C2 1 asl ; Compute $n0 - needed for -0061C2 1 asl -0061C2 1 asl -0061C2 1 asl -0061C2 1 sta TOMOUSE_n0 ; Y register before firmware calls -0061C2 1 -0061C2 1 ; -0061C2 1 ; Step 3: Configure the mouse card -0061C2 1 ; -0061C2 1 -0061C2 1 ; Initialize the mouse for use -0061C2 1 jsr INITMOUSE ; reset, clamp to 0-1023 x/y -0061C2 1 lda #1 ; mouse on, no interrupts -0061C2 1 jsr SETMOUSE ; TODO: test carry bit result (set = error) -0061C2 1 ; -0061C2 1 ; Since we want deltas, clamp and center -0061C2 1 ; -0061C2 1 ClampMouse MOUSE_CLAMP_X, MOUSE_MIN_X, MOUSE_MAX_X -0061C2 1 ClampMouse MOUSE_CLAMP_Y, MOUSE_MIN_Y, MOUSE_MAX_Y -0061C2 1 PosMouse MOUSE_CENTER_X, MOUSE_CENTER_Y -0061C2 1 -0061C2 1 cli ; Enable interrupts so mouse can function -0061C2 1 -0061C2 1 rts -0061C2 1 -0061C2 1 .endproc -0061C2 1 -0061C2 1 -0061C2 1 ;-------------------------------------------------- -0061C2 1 ; Indirect jump table for mouse firmware routines -0061C2 1 ;-------------------------------------------------- -0061C2 1 -0061C2 1 SETMOUSE: ldy #$12 -0061C2 1 jmp GOMOUSE -0061C2 1 SERVEMOUSE: ldy #$13 -0061C2 1 jmp GOMOUSE -0061C2 1 READMOUSE: ldy #$14 -0061C2 1 jmp GOMOUSE -0061C2 1 CLEARMOUSE: ldy #$15 -0061C2 1 jmp GOMOUSE -0061C2 1 POSMOUSE: ldy #$16 -0061C2 1 jmp GOMOUSE -0061C2 1 CLAMPMOUSE: ldy #$17 -0061C2 1 jmp GOMOUSE -0061C2 1 HOMEMOUSE: ldy #$18 -0061C2 1 jmp GOMOUSE -0061C2 1 INITMOUSE: ldy #$19 -0061C2 1 jmp GOMOUSE -0061C2 1 -0061C2 1 ;-------------------------------------------------- -0061C2 1 .proc GOMOUSE -0061C2 1 ;-------------------------------------------------- -0061C2 1 tax ; Preserve the value in A -0061C2 1 lda (MOUSEPTR),Y ; Get the routine entry point -0061C2 1 sta TOMOUSE_lsb ; Patch the JMP instruction -0061C2 1 txa ; Restore the value in A -0061C2 1 .endproc -0061C2 1 ; fall through -0061C2 1 -0061C2 1 ; The following operand bytes must be patched by the -0061C2 1 ; initialization code which detects the mouse. -0061C2 1 -0061C2 1 BANK = $C054 -0061C2 1 -0061C2 1 TOMOUSE: -0061C2 1 ldx #$C1 ; Set up slot in $Cn form in X -0061C2 1 ldy #$10 ; Set up slot in $n0 form in Y -0061C2 1 php ; Save interrupt state -0061C2 1 sei ; No interrupts while calling -0061C2 1 bit BANK -0061C2 1 jsr SLOT_BASE ; Go to the mouse routine -0061C2 1 plp ; Restore interrupt state -0061C2 1 rts -0061C2 1 -0061C2 1 TOMOUSE_Cn = TOMOUSE + 1 -0061C2 1 TOMOUSE_n0 = TOMOUSE + 3 -0061C2 1 TOMOUSE_lsb = TOMOUSE + 10 -0061C2 1 TOMOUSE_msb = TOMOUSE + 11 -0061C2 1 -0061C2 1 -0061C2 1 ; TODO: Turn this into a proper delta-sending routine -0061C2 1 -0061C2 1 ;-------------------------------------------------- -0061C2 1 .proc FOOMOUSE -0061C2 1 ;-------------------------------------------------- -0061C2 1 ; -0061C2 1 ;-------------------------------------------------- -0061C2 1 txa ; save x -0061C2 1 pha -0061C2 1 tya ; save y -0061C2 1 pha -0061C2 1 -0061C2 1 jsr READMOUSE -0061C2 1 -0061C2 1 jmp DONE -0061C2 1 -0061C2 1 ldx MOUSE_SLOT -0061C2 1 -0061C2 1 lda MOUSE_X_LSB,x -0061C2 1 sta LAST_MX -0061C2 1 -0061C2 1 lda MOUSE_Y_LSB,x -0061C2 1 sta LAST_MY -0061C2 1 -0061C2 1 lda LAST_MX -0061C2 1 cmp #MOUSE_CENTER_X -0061C2 1 bne SEND -0061C2 1 -0061C2 1 lda LAST_MY -0061C2 1 cmp #MOUSE_CENTER_Y -0061C2 1 beq DONE -0061C2 1 -0061C2 1 SEND: -0061C2 1 lda LAST_MX -0061C2 1 ora #SIS_MX -0061C2 1 jsr SSCPUT -0061C2 1 lda LAST_MY -0061C2 1 ora #SIS_MY -0061C2 1 jsr SSCPUT -0061C2 1 -0061C2 1 PosMouse MOUSE_CENTER_X, MOUSE_CENTER_Y -0061C2 1 -0061C2 1 DONE: -0061C2 1 pla ; restore y -0061C2 1 tay -0061C2 1 pla ; restore x -0061C2 1 tax -0061C2 1 rts -0061C2 1 -0061C2 1 .endproc -0061C2 1 -0061C2 1 .endif ; MOUSE_SUPPORT -0061C2 1 -0061C2 1 -0061C2 1 ;------------------------------------------------------------------- -0061C2 1 ; -0061C2 1 ; Lookup Tables and Variable Storage -0061C2 1 ; -0061C2 1 ;------------------------------------------------------------------- -0061C2 1 -0061C2 1 ; Lookup table for UACTRL register, by baud rate -0061C2 1 -0061C2 1 16 1E 1F 10 BPSCTRL: .byte $16,$1E,$1F,$10 ; 300, 9600, 19200, 115k (with 8 data bits, 1 stop bit, no echo) -0061C6 1 .enum -0061C6 1 BPS_300 -0061C6 1 BPS_9600 -0061C6 1 BPS_19200 -0061C6 1 BPS_115k -0061C6 1 .endenum -0061C6 1 CMND_NRDI = $0B ; Command: no parity, RTS on, DTR on, no interrupts -0061C6 1 -0061C6 1 -0061C6 1 ; Application configuration -0061C6 1 03 PSPEED: .byte BPS_115k ; Hardcoded for Apple IIc (TODO: Allow configuration) -0061C7 1 02 PSLOT: .byte 2 ; Hardcoded for Apple IIc (TODO: Allow configuration) -0061C8 1 00 PEXIT: .byte 0 ; Set when it's time to exit (Not Yet Implemented) +006133 1 END_CA: +006133 1 +006133 1 .ifdef PADDLE_SUPPORT +006133 1 +006133 1 ;;;-------------------------------------- +006133 1 ;;; Send Paddle 0 state, if it changed +006133 1 TEST_PDL0: +006133 1 A2 00 ldx #0 +006135 1 20 1E FB jsr PREAD +006138 1 98 tya +006139 1 4A lsr ; Shift to low nibble +00613A 1 4A lsr +00613B 1 4A lsr +00613C 1 4A lsr +00613D 1 09 30 ora #SIS_PDL0 ; And mark it with the signature +00613F 1 CD CF 61 cmp LASTP0 ; Change? +006142 1 F0 09 beq END_PDL0 ; Nope +006144 1 8D CF 61 sta LASTP0 ; Yes, save it +006147 1 20 2C 60 jsr SSC::Put ; and send it +00614A 1 4C 7A 61 jmp DONE +00614D 1 END_PDL0: +00614D 1 ; Chew up time so next paddle read will be correct +00614D 1 ; TODO: Replace this with a "read both" strobes +00614D 1 ; routine +00614D 1 EA EA EA EA : .repeat 11 ; By experiment, need 11 NOPs. +006151 1 EA EA EA EA +006155 1 EA EA EA +006158 1 nop +006158 1 .endrep +006158 1 C8 iny +006159 1 D0 F2 bne :- +00615B 1 +00615B 1 ;;;-------------------------------------- +00615B 1 ;;; Send Paddle 1 state, if it changed +00615B 1 TEST_PDL1: +00615B 1 A2 01 ldx #1 +00615D 1 20 1E FB jsr PREAD +006160 1 98 tya +006161 1 4A lsr ; Shift to low nibble +006162 1 4A lsr +006163 1 4A lsr +006164 1 4A lsr +006165 1 09 40 ora #SIS_PDL1 ; And mark it with the signature +006167 1 CD D0 61 cmp LASTP1 ; Change? +00616A 1 F0 09 beq END_PDL1 ; Nope +00616C 1 8D D0 61 sta LASTP1 ; Yes, save it +00616F 1 20 2C 60 jsr SSC::Put ; and send it +006172 1 4C 7A 61 jmp DONE +006175 1 END_PDL1: +006175 1 ; NOTE: No need to chew time like PDL0 +006175 1 ; since data receive will make up for it; if we +006175 1 ; loop in SendInputState need to add it here +006175 1 +006175 1 .endif +006175 1 +006175 1 +006175 1 ;;;-------------------------------------- +006175 1 ;;; No state changes so send sync byte +006175 1 +006175 1 A9 7F lda #SIS_SYNC +006177 1 20 2C 60 jsr SSC::Put +00617A 1 +00617A 1 DONE: +00617A 1 68 A8 68 AA RestoreRegisters +00617E 1 68 +00617F 1 60 rts +006180 1 +006180 1 .endproc +006180 1 +006180 1 +006180 1 ;;;------------------------------------------------------------------- +006180 1 ; +006180 1 ;;; Hi-res graphics routines +006180 1 ; +006180 1 ;;;------------------------------------------------------------------- +006180 1 +006180 1 ;;;--------------------------------------------------------- +006180 1 .proc InitHires +006180 1 ;;;--------------------------------------------------------- +006180 1 ;;; Set up the graphics display and pointers +006180 1 ;;;--------------------------------------------------------- +006180 1 A9 20 lda #PLOTPAGE1 ; clear page 1 +006182 1 85 E6 sta PLOTPAGE +006184 1 20 AD 61 jsr ClearHires +006187 1 +006187 1 20 97 61 jsr FlipHires ; then show it and flip to 2 +00618A 1 8D 57 C0 sta SETHIRES +00618D 1 8D 50 C0 sta CLRTEXT +006190 1 8D 52 C0 sta CLRMIXED +006193 1 8D 54 C0 sta PAGE1 +006196 1 +006196 1 60 rts +006197 1 .endproc +006197 1 +006197 1 +006197 1 ;;;--------------------------------------------------------- +006197 1 .proc FlipHires +006197 1 ;;;--------------------------------------------------------- +006197 1 ;;; Call when done with the current plotting page +006197 1 ;;; (selected in PLOTPAGE) and it will be shown and the +006197 1 ;;; other page will be shown. +006197 1 ;;;--------------------------------------------------------- +006197 1 A5 E6 lda PLOTPAGE ; plotting on which page? +006199 1 C9 20 cmp #PLOTPAGE1 +00619B 1 F0 08 beq :+ +00619D 1 +00619D 1 8D 55 C0 sta PAGE2 ; page 2 - so show it +0061A0 1 A9 20 lda #PLOTPAGE1 ; and plot on page 1 +0061A2 1 85 E6 sta PLOTPAGE +0061A4 1 60 rts +0061A5 1 +0061A5 1 8D 54 C0 : sta PAGE1 ; page 1 - so show it +0061A8 1 A9 40 lda #PLOTPAGE2 ; and plot on page 2 +0061AA 1 85 E6 sta PLOTPAGE +0061AC 1 60 rts +0061AD 1 .endproc +0061AD 1 +0061AD 1 +0061AD 1 ;;;--------------------------------------------------------- +0061AD 1 .proc ClearHires +0061AD 1 ;;;--------------------------------------------------------- +0061AD 1 ;;; Clear hires plotting page (selected in PLOTPAGE) to +0061AD 1 ;;; black uses ZP; not terribly efficient +0061AD 1 ;;;--------------------------------------------------------- +0061AD 1 A9 00 lda #0 ; Set up ZP as a pointer into the hires page +0061AF 1 85 FA sta ZP +0061B1 1 A5 E6 lda PLOTPAGE +0061B3 1 85 FB sta ZP+1 +0061B5 1 A2 20 ldx #PAGESIZE ; Clear this many pages +0061B7 1 A9 00 lda #0 ; with black! +0061B9 1 A8 tay +0061BA 1 91 FA : sta (ZP),Y +0061BC 1 C8 iny +0061BD 1 D0 FB bne :- +0061BF 1 E6 FB inc ZP+1 +0061C1 1 CA dex +0061C2 1 D0 F6 bne :- +0061C4 1 60 rts +0061C5 1 .endproc +0061C5 1 +0061C5 1 +0061C5 1 +0061C5 1 +0061C5 1 ;;;------------------------------------------------------------------- +0061C5 1 ; +0061C5 1 ;;; Lookup Tables and Variable Storage +0061C5 1 ; +0061C5 1 ;;;------------------------------------------------------------------- +0061C5 1 +0061C5 1 ;;; Lookup table for UACTRL register, by baud rate +0061C5 1 +0061C5 1 16 1E 1F 10 BPSCTRL: .byte $16,$1E,$1F,$10 ; 300, 9600, 19200, 115k (with 8 data bits, 1 stop bit, no echo) +0061C9 1 .enum +0061C9 1 BPS_300 +0061C9 1 BPS_9600 +0061C9 1 BPS_19200 +0061C9 1 BPS_115k +0061C9 1 .endenum +0061C9 1 CMND_NRDI = $0B ; Command: no parity, RTS on, DTR on, no interrupts 0061C9 1 0061C9 1 -0061C9 1 ; Keyboard state -0061C9 1 00 LASTKB: .byte 0 -0061CA 1 00 LASTOA: .byte 0 -0061CB 1 00 LASTCA: .byte 0 +0061C9 1 ;;; Application configuration +0061C9 1 03 PSPEED: .byte BPS_115k ; Hardcoded for Apple IIc (TODO: Allow configuration) +0061CA 1 02 PSLOT: .byte 2 ; Hardcoded for Apple IIc (TODO: Allow configuration) +0061CB 1 00 PEXIT: .byte 0 ; Set when it's time to exit (Not Yet Implemented) 0061CC 1 -0061CC 1 .ifdef PADDLE_SUPPORT 0061CC 1 -0061CC 1 ; Paddle state -0061CC 1 00 LASTP0: .byte 0 -0061CD 1 00 LASTP1: .byte 0 -0061CE 1 -0061CE 1 .endif ; PADDLE_SUPPORT -0061CE 1 -0061CE 1 -0061CE 1 .ifdef MOUSE_SUPPORT -0061CE 1 -0061CE 1 ; Mouse -0061CE 1 MOUSE_SLOT: .byte 0 ; mouse slot, or 0 if none -0061CE 1 LAST_MX: .byte $7f -0061CE 1 LAST_MY: .byte $7f -0061CE 1 -0061CE 1 ; Mouse ID bytes -0061CE 1 MOUSEID_MAX = 4 -0061CE 1 MOUSEID_ADDR: .byte $05, $07, $0b, $0c, $fb -0061CE 1 MOUSEID_VAL: .byte $38, $18, $01, $20, $d6 -0061CE 1 -0061CE 1 .endif ; MOUSE_SUPPORT -0061CE 1 -0061CE 1 +0061CC 1 ;;; Keyboard state +0061CC 1 00 LASTKB: .byte 0 +0061CD 1 00 LASTOA: .byte 0 +0061CE 1 00 LASTCA: .byte 0 +0061CF 1 +0061CF 1 .ifdef PADDLE_SUPPORT +0061CF 1 +0061CF 1 ;;; Paddle state +0061CF 1 00 LASTP0: .byte 0 +0061D0 1 00 LASTP1: .byte 0 +0061D1 1 +0061D1 1 .endif ; PADDLE_SUPPORT +0061D1 1 diff --git a/client/client.s b/client/client.s index 092b2f2..640a1b9 100644 --- a/client/client.s +++ b/client/client.s @@ -1,21 +1,20 @@ - PADDLE_SUPPORT = 1 -;MOUSE_SUPPORT = 1 ; NOTE: tests for ifdef +;;; MOUSE_SUPPORT = 1 -;--------------------------------------------------------- -; Super Serial constants/locations -;--------------------------------------------------------- +;;;--------------------------------------------------------- +;;; Super Serial constants/locations +;;;--------------------------------------------------------- -; These get incremented by the slot where they appear +;;; These get incremented by the slot where they appear UACTRL = $C08B ; Control Register UACMND = $C08A ; Command Register UASTAT = $C089 ; Status Register UADATA = $C088 ; Data Register - incoming and outgoing data -;--------------------------------------------------------- -; Hi-res graphics constants/locations -;--------------------------------------------------------- +;;;--------------------------------------------------------- +;;; Hi-res graphics constants/locations +;;;--------------------------------------------------------- PLOTPAGE = $E6 ; Active hires plotting page (Applesoft) PLOTPAGE1 = $20 @@ -30,64 +29,39 @@ SETMIXED = $C053 ;enable graphics/text mixed mode PAGE1 = $C054 ;select text/graphics page1 PAGE2 = $C055 ;select text/graphics page2 CLRHIRES = $C056 ;select Lo-res -SETHIRES = $C057 ;select Hi-res +SETHIRES = $C057 ;select Hi-res -;--------------------------------------------------------- -; Keyboard input constants/locations -;--------------------------------------------------------- +;;;--------------------------------------------------------- +;;; Keyboard input constants/locations +;;;--------------------------------------------------------- KEYBD = $C000 ; key down in bit 7; key code in lower bits STROBE = $C010 ; write to clear key down state OPNAPPLE = $C061 ; open apple (command) key data (read) CLSAPPLE = $C062 ; closed apple (option) key data (read) -PB2 = $C063 ; Paddle button 2 (read) -PB3 = $C060 ; Paddle button 3 (read) +PB2 = $C063 ; Paddle button 2 (read) +PB3 = $C060 ; Paddle button 3 (read) -;--------------------------------------------------------- -; Paddle/Joystick constants/locations/routines -;--------------------------------------------------------- +;;;--------------------------------------------------------- +;;; Paddle/Joystick constants/locations/routines +;;;--------------------------------------------------------- -PADDLE0 = $C064 ; bit 7 = status of pdl-0 timer (read) +PADDLE0 = $C064 ; bit 7 = status of pdl-0 timer (read) PADDLE1 = $C065 ; bit 7 = status of pdl-1 timer (read) PADDLE2 = $C066 ; bit 7 = status of pdl-2 timer (read) PADDLE3 = $C067 ; bit 7 = status of pdl-3 timer (read) -PDLTRIG = $C070 ; trigger paddles +PDLTRIG = $C070 ; trigger paddles PREAD = $FB1E ; Monitor paddle reading routine, call ; with paddle # in X, returns value in Y -;-------------------------------------------------- -; Mouse locations and constants -;-------------------------------------------------- -; 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_MODE = $07F8 ; + slot Mode byte - -; 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_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 - - -;--------------------------------------------------------- -; Other -;--------------------------------------------------------- +;;;--------------------------------------------------------- +;;; Other +;;;--------------------------------------------------------- SLOT_CASE = $c000 ; Firmware for slots are at $cx00 MAX_SLOT = 7 ; Maximum slot # on an Apple II @@ -97,13 +71,13 @@ ESCAPE = $80 ; Unused image data byte (all black2) ESCAPE2 = $FF ; Unused image data byte (all white2) -;--------------------------------------------------------- -; Generic Macros -;--------------------------------------------------------- +;;;--------------------------------------------------------- +;;; Generic Macros +;;;--------------------------------------------------------- -;---------------------------------------- +;;;---------------------------------------- .macro SaveRegisters -;---------------------------------------- +;;;---------------------------------------- pha txa pha @@ -111,9 +85,9 @@ ESCAPE2 = $FF ; Unused image data byte (all white2) pha .endmacro -;---------------------------------------- +;;;---------------------------------------- .macro RestoreRegisters -;---------------------------------------- +;;;---------------------------------------- pla tay pla @@ -122,87 +96,95 @@ ESCAPE2 = $FF ; Unused image data byte (all white2) .endmacro -;------------------------------------------------------------------- -; -; Application-level logic +;;;------------------------------------------------------------------- ; -;------------------------------------------------------------------- +;;; Application-level logic +; +;;;------------------------------------------------------------------- -.ORG $6000 +.org $6000 + jmp AppEntry -;--------------------------------------------------------- -.proc APP_ENTRY -;--------------------------------------------------------- -; Initialize the application, and enter the main loop -;--------------------------------------------------------- +.include "ssc.inc" + +.ifdef MOUSE_SUPPORT + .include "mouse.inc" +.endif ; MOUSE_SUPPORT + + +;;;--------------------------------------------------------- +.proc AppEntry +;;;--------------------------------------------------------- +;;; Initialize the application, and enter the main loop +;;;--------------------------------------------------------- lda PSLOT ; Use slot 2 - jsr INITSSC ; Initialize Super Serial Card - jsr INITHIRES ; Initialize Hi-Res graphics - jsr INITINPUT ; Initialize input devices - jsr MAINLOOP + jsr SSC::Init ; Initialize Super Serial Card + jsr InitHires ; Initialize Hi-Res graphics + jsr InitInput ; Initialize input devices + jsr MainLoop ; fall through .endproc - -;--------------------------------------------------------- -.proc APP_EXIT -;--------------------------------------------------------- -; Clean up and exit app -;--------------------------------------------------------- - jsr RESETSSC + +;;;--------------------------------------------------------- +.proc AppExit +;;;--------------------------------------------------------- +;;; Clean up and exit app +;;;--------------------------------------------------------- + jsr SSC::Reset sta PAGE1 sta SETTEXT rts .endproc -;------------------------------------------------------------------- -; -; Main loop functionality +;;;------------------------------------------------------------------- ; -;------------------------------------------------------------------- +;;; Main loop functionality +; +;;;------------------------------------------------------------------- -;--------------------------------------------------------- -.proc MAINLOOP -;--------------------------------------------------------- +;;;--------------------------------------------------------- +.proc MainLoop +;;;--------------------------------------------------------- -; TODO: Sort out the protocol - should be able to send -; input state without receiving data -; jsr SSCHASDATA ; Anything to read? -; bne :+ ; Nope +;;; TODO: Sort out the protocol - should be able to send +;;; input state without receiving data +;;; jsr SSCHasData ; Anything to read? +;;; bne :+ ; Nope -: jsr RECEIVEPAGE - jsr FLIPHIRES +: jsr ReceivePage + jsr FlipHires jmp :- ; TODO: define an exit trigger rts .endproc - -;--------------------------------------------------------- -.proc RECEIVEPAGE -;--------------------------------------------------------- -; Pull a hi-res page down over serial + +;;;--------------------------------------------------------- +.proc ReceivePage +;;;--------------------------------------------------------- +;;; Pull a hi-res page down over serial ; -; Protocol is: -; * Recieve 256 bytes (graphic data) -; * Send 1 byte (input state) -;--------------------------------------------------------- - +;;; Protocol is: +;;; * Recieve 256 bytes (graphic data) +;;; * Send 1 byte (input state) +;;;--------------------------------------------------------- + lda #0 ; set up write pointer sta ZP lda PLOTPAGE sta ZP+1 ldx #PAGESIZE ; plan to receive this many pages ldy #0 - -: jsr SSCGET ; TODO: look for escape codes in the sequence + +: jsr SSC::Get ; TODO: look for escape codes in the sequence sta (ZP),Y iny bne :- ; Do a full page... - jsr SENDINPUTSTATE ; brief moment to send data back upstream + jsr SendInputState ; brief moment to send data back upstream inc ZP+1 dex @@ -211,51 +193,51 @@ ESCAPE2 = $FF ; Unused image data byte (all white2) .endproc -;------------------------------------------------------------------- -; -; Input device routines +;;;------------------------------------------------------------------- ; -;------------------------------------------------------------------- -; Protocol: -; $7f - $ff - key down, ASCII code + $80 -; otherwise, a transition: +;;; Input device routines +; +;;;------------------------------------------------------------------- +;;; Protocol: +;;; $7f - $ff - key down, ASCII code + $80 +;;; otherwise, a transition: ; SIS_KBUP = $00 ; Key up SIS_OADOWN = $01 ; Open Apple transitioned to down SIS_OAUP = $02 ; Open Apple transitioned to up SIS_CADOWN = $03 ; Closed Apple transitioned to down SIS_CAUP = $04 ; Closed Apple transitioned to up -; -; $05 - $0f : reserved +; +;;; $05 - $0f : reserved ; SIS_MX = $10 ; Mouse X high nibble SIS_MY = $20 ; Mouse Y high nibble SIS_PDL0 = $30 ; Paddle 0 high nibble SIS_PDL1 = $40 ; Paddle 1 high nibble -; -; $50 - $7e : reserved +; +;;; $50 - $7e : reserved ; SIS_SYNC = $7f -;--------------------------------------------------------- -.proc INITINPUT -;--------------------------------------------------------- -; Initialize input devices and storage for detecting -; state transitions -;--------------------------------------------------------- +;;;--------------------------------------------------------- +.proc InitInput +;;;--------------------------------------------------------- +;;; Initialize input devices and storage for detecting +;;; state transitions +;;;--------------------------------------------------------- -; Init keyboard state +;;; Init keyboard state lda #SIS_KBUP sta LASTKB -; Init Open/Closed Apple states +;;; Init Open/Closed Apple states lda #SIS_OAUP ; NOTE: Don't store OA state as it fluctuates sta LASTOA lda #SIS_CAUP ; NOTE: Don't store CA state as it fluctuates sta LASTCA .ifdef PADDLE_SUPPORT -; Init Paddle state +;;; Init Paddle state lda #SIS_PDL0 ora #8 ; Middle of range 0...15 sta LASTP0 @@ -265,43 +247,43 @@ ESCAPE2 = $FF ; Unused image data byte (all white2) .endif .ifdef MOUSE_SUPPORT - jsr FINDMOUSE -.endif + jsr Mouse::FindMouse +.endif rts .endproc -;--------------------------------------------------------- -.proc SENDINPUTSTATE -;--------------------------------------------------------- -; Send keyboard joystick and/or mouse state over the -; serial port +;;;--------------------------------------------------------- +.proc SendInputState +;;;--------------------------------------------------------- +;;; Send keyboard joystick and/or mouse state over the +;;; serial port ; -; Algorithm: -; - Send key state (if it changed) -; - otherwise send open-apple state (if it changed) -; - otherwise send closed-apple state (if it changed) -; - otherwise send paddle 0 state (if it changed) -; - (TODO: Mouse state) -; - otherwise send sync byte -;--------------------------------------------------------- +;;; Algorithm: +;;; - Send key state (if it changed) +;;; - otherwise send open-apple state (if it changed) +;;; - otherwise send closed-apple state (if it changed) +;;; - otherwise send paddle 0 state (if it changed) +;;; - (TODO: Mouse state) +;;; - otherwise send sync byte +;;;--------------------------------------------------------- SaveRegisters ; Store registers clc - -;-------------------------------------- -; Send key state, if it changed -; NOTE: Can't use STROBE to detect key up -> key down transition -; since the msb can change before the key code. Instead, consider -; these cases: +;;;-------------------------------------- +;;; Send key state, if it changed + +;;; NOTE: Can't use STROBE to detect key up -> key down transition +;;; since the msb can change before the key code. Instead, consider +;;; these cases: ; -; OLD STATE KEYBD STROBE RESULT -; Up Up - No-op -; Up Down - Save and send key down -; Down - Up Save and send key up -; Down - Down Save and send key ONLY if different +;;; OLD STATE KEYBD STROBE RESULT +;;; Up Up - No-op +;;; Up Down - Save and send key down +;;; Down - Up Save and send key up +;;; Down - Down Save and send key ONLY if different ; lda LASTKB @@ -309,11 +291,11 @@ ESCAPE2 = $FF ; Unused image data byte (all white2) KEY_WAS_UP: lda KEYBD ; Read keyboard - bpl END_KEY ; - still up + bpl END_KEY ; - still up sta LASTKB ; Down, so save it - jsr SSCPUT ; and send it + jsr SSC::Put ; and send it jmp DONE - + KEY_WAS_DOWN: ; key was down - strobe should match ; unless the key changed or was released @@ -322,70 +304,70 @@ KEY_WAS_DOWN: STROBE_UP: lda #SIS_KBUP ; Key was released sta LASTKB ; so save it - jsr SSCPUT ; and send it + jsr SSC::Put ; and send it jmp DONE -STROBE_DOWN: +STROBE_DOWN: cmp LASTKB ; Same key as last time? beq END_KEY ; - no change sta LASTKB ; New key, so save it - jsr SSCPUT ; and send it + jsr SSC::Put ; and send it jmp DONE - + END_KEY: -;-------------------------------------- -; Send Open Apple state, if it changed +;;;-------------------------------------- +;;; Send Open Apple state, if it changed -; TODO: Can simplify this code if we make the high bits the same -; for both OA states and bit = 0 down: lda OPNAPPLE ; ROL ; LDA #0 ; ROL ; ORA #signature +;;; TODO: Can simplify this code if we make the high bits the same +;;; for both OA states and bit = 0 down: lda OPNAPPLE ; ROL ; LDA #0 ; ROL ; ORA #signature -TEST_OA: +TEST_OA: lda OPNAPPLE ; Test Open Apple state bmi OA_IS_DOWN -OA_IS_UP: - lda #SIS_OAUP +OA_IS_UP: + lda #SIS_OAUP cmp LASTOA ; Changed? beq END_OA ; Nope sta LASTOA ; Yes, save it / send it! - jsr SSCPUT + jsr SSC::Put jmp DONE OA_IS_DOWN: lda #SIS_OADOWN cmp LASTOA ; Changed? beq END_OA ; Nope sta LASTOA ; Yes, save it / send it! - jsr SSCPUT + jsr SSC::Put jmp DONE END_OA: -;-------------------------------------- -; Send Closed Apple state, if it changed +;;;-------------------------------------- +;;; Send Closed Apple state, if it changed -TEST_CA: +TEST_CA: lda CLSAPPLE ; Has the Open Apple/Button 1 value changed? bmi CA_IS_DOWN -CA_IS_UP: +CA_IS_UP: lda #SIS_CAUP cmp LASTCA ; Changed? beq END_CA ; Nope sta LASTCA ; Yes, save it - jsr SSCPUT ; and send it + jsr SSC::Put ; and send it jmp DONE CA_IS_DOWN: lda #SIS_CADOWN cmp LASTCA ; Changed? beq END_CA ; Nope sta LASTCA ; Yes, save it - jsr SSCPUT ; and send it + jsr SSC::Put ; and send it jmp DONE END_CA: .ifdef PADDLE_SUPPORT -;-------------------------------------- -; Send Paddle 0 state, if it changed +;;;-------------------------------------- +;;; Send Paddle 0 state, if it changed TEST_PDL0: ldx #0 jsr PREAD @@ -398,20 +380,20 @@ TEST_PDL0: cmp LASTP0 ; Change? beq END_PDL0 ; Nope sta LASTP0 ; Yes, save it - jsr SSCPUT ; and send it + jsr SSC::Put ; and send it jmp DONE -END_PDL0: +END_PDL0: ; Chew up time so next paddle read will be correct ; TODO: Replace this with a "read both" strobes ; routine -: .repeat 11 ; By experiment, need 11 NOPs. +: .repeat 11 ; By experiment, need 11 NOPs. nop .endrep iny bne :- -;-------------------------------------- -; Send Paddle 1 state, if it changed +;;;-------------------------------------- +;;; Send Paddle 1 state, if it changed TEST_PDL1: ldx #1 jsr PREAD @@ -424,66 +406,61 @@ TEST_PDL1: cmp LASTP1 ; Change? beq END_PDL1 ; Nope sta LASTP1 ; Yes, save it - jsr SSCPUT ; and send it + jsr SSC::Put ; and send it jmp DONE -END_PDL1: - ; NOTE: No need to chew time like PDL0 +END_PDL1: + ; NOTE: No need to chew time like PDL0 ; since data receive will make up for it; if we - ; loop in SENDINPUTSTATE need to add it here - -.endif + ; loop in SendInputState need to add it here - -;-------------------------------------- -.ifdef MOUSE_SUPPORT - .error "Mouse support not fully implemented" .endif -;-------------------------------------- -; No state changes so send sync byte + +;;;-------------------------------------- +;;; No state changes so send sync byte lda #SIS_SYNC - jsr SSCPUT + jsr SSC::Put DONE: RestoreRegisters rts - + .endproc -;------------------------------------------------------------------- -; -; Hi-res graphics routines +;;;------------------------------------------------------------------- ; -;------------------------------------------------------------------- +;;; Hi-res graphics routines +; +;;;------------------------------------------------------------------- -;--------------------------------------------------------- -.proc INITHIRES -;--------------------------------------------------------- -; Set up the graphics display and pointers -;--------------------------------------------------------- +;;;--------------------------------------------------------- +.proc InitHires +;;;--------------------------------------------------------- +;;; Set up the graphics display and pointers +;;;--------------------------------------------------------- lda #PLOTPAGE1 ; clear page 1 sta PLOTPAGE - jsr CLEARHIRES + jsr ClearHires - jsr FLIPHIRES ; then show it and flip to 2 + jsr FlipHires ; then show it and flip to 2 sta SETHIRES - sta CLRTEXT - sta CLRMIXED - sta PAGE1 + sta CLRTEXT + sta CLRMIXED + sta PAGE1 rts .endproc -;--------------------------------------------------------- -.proc FLIPHIRES -;--------------------------------------------------------- -; Call when done with the current plotting page -; (selected in PLOTPAGE) and it will be shown and the -; other page will be shown. -;--------------------------------------------------------- +;;;--------------------------------------------------------- +.proc FlipHires +;;;--------------------------------------------------------- +;;; Call when done with the current plotting page +;;; (selected in PLOTPAGE) and it will be shown and the +;;; other page will be shown. +;;;--------------------------------------------------------- lda PLOTPAGE ; plotting on which page? cmp #PLOTPAGE1 beq :+ @@ -498,14 +475,14 @@ DONE: sta PLOTPAGE rts .endproc - -;--------------------------------------------------------- -.proc CLEARHIRES -;--------------------------------------------------------- -; Clear hires plotting page (selected in PLOTPAGE) to -; black uses ZP; not terribly efficient -;--------------------------------------------------------- + +;;;--------------------------------------------------------- +.proc ClearHires +;;;--------------------------------------------------------- +;;; Clear hires plotting page (selected in PLOTPAGE) to +;;; black uses ZP; not terribly efficient +;;;--------------------------------------------------------- lda #0 ; Set up ZP as a pointer into the hires page sta ZP lda PLOTPAGE @@ -513,412 +490,51 @@ DONE: ldx #PAGESIZE ; Clear this many pages lda #0 ; with black! tay -: sta (ZP),Y +: sta (ZP),Y iny bne :- inc ZP+1 dex bne :- - rts + rts .endproc -;------------------------------------------------------------------- -; -; Serial port routines + +;;;------------------------------------------------------------------- ; -;------------------------------------------------------------------- - - -;--------------------------------------------------------- -.proc INITSSC -;--------------------------------------------------------- -; Initialize the SSC; slot passed in A -; [based on ADTPro] -;--------------------------------------------------------- - asl ; Slot passed in A - asl - asl - asl ; Now $S0 - adc #$88 ; Low byte of UADATA - tax - lda #CMND_NRDI ; Command register: no parity, RTS on, DTR on, no interrupts - sta $C002,X - ldy PSPEED ; Control register: look up by baud rate (8 data bits, 1 stop bit) - lda BPSCTRL,Y - sta $C003,X - stx MOD_UADATA_1+1 ; Modify references to - stx MOD_UADATA_2+1 ; UADATA to point at - stx MOD_UADATA_3+1 ; correct slot (UADATA+S0) - inx - stx MOD_UASTAT_1+1 ; Modify reference to - stx MOD_UASTAT_2+1 ; UASTAT to point at - stx MOD_UASTAT_3+1 ; correct slot (UASTAT+S0) - rts - -.endproc - - -;--------------------------------------------------------- -SSCPUT: -;--------------------------------------------------------- -; Send accumulator out the serial port -; (this is a blocking call) -; [based on ADTPro] -;--------------------------------------------------------- - pha ; Push A onto the stack -MOD_UASTAT_1: -: lda UASTAT ; Check status bits - and #$70 - cmp #$10 - bne :- ; Output register is full, so loop - pla -MOD_UADATA_1: - sta UADATA ; Put character - rts - - -;--------------------------------------------------------- -SSCGET: -;--------------------------------------------------------- -; Read a character from the serial port to the accumulator -; (this is a blocking call) -; [based on ADTPro] -;--------------------------------------------------------- -MOD_UASTAT_2: - lda UASTAT ; Check status bits - and #$68 - cmp #$8 - bne SSCGET ; Input register empty, loop -MOD_UADATA_2: - lda UADATA ; Get character - rts - - -;--------------------------------------------------------- -SSCHASDATA: -;--------------------------------------------------------- -; Read a character from the serial port to the accumulator -; (this is a blocking call) -; [based on ADTPro] -;--------------------------------------------------------- -MOD_UASTAT_3: - lda UASTAT ; Check status bits - and #$68 - cmp #$8 - rts - - -;--------------------------------------------------------- -RESETSSC: -;--------------------------------------------------------- -; Clean up serial port -; [based on ADTPro] -;--------------------------------------------------------- -MOD_UADATA_3: - bit UADATA - rts - - - -.ifdef MOUSE_SUPPORT -;------------------------------------------------------------------- -; -; Mouse routines +;;; Lookup Tables and Variable Storage ; -;------------------------------------------------------------------- +;;;------------------------------------------------------------------- -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 - - -;-------------------------------------------------- -; Macros for common mouse operations -;-------------------------------------------------- - -;---------------------------------------- -.macro ClampMouse axis, min, max -;---------------------------------------- -; axis: MOUSE_CLAMP_X or MOUSE_CLAMP_Y -; min: minimum value (2 byte) -; max: maximum value (2 byte) -;---------------------------------------- - ; Clamp X to 0...255 - lda #min - sta MOUSE_CMIN_MSB - lda #max - sta MOUSE_CMAX_MSB - lda #axis - jsr CLAMPMOUSE -.endmacro - -;---------------------------------------- -.macro PosMouse px, py -;---------------------------------------- - ldx MOUSE_SLOT - lda #px - sta MOUSE_X_MSB,X - lda #py - sta MOUSE_Y_MSB,X - jsr POSMOUSE -.endmacro - - -;--------------------------------------------------------- -.proc FINDMOUSE -;--------------------------------------------------------- -; Find and initialize the mouse port -;--------------------------------------------------------- - -; 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 -; - - ldy #MAX_SLOT ; Start search in slot 7 - -TESTSLOT: - sty MOUSE_SLOT ; Save for later - tya - clc - adc #>SLOT_BASE ; Firmware is $c0 + slot - sta MOD_MOUSE_ID + 2 ; 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 -MOD_MOUSE_ID: - lda SLOT_BASE - cmp MOUSEID_VAL,x ; Does it match the signature? - bne NOMATCH ; Nope - try the next slot - dex ; Yes! Keep testing - bpl TESTID ; Fall through if all done - jmp FOUND_MOUSE - -NOMATCH: - dey ; Didn't match - bne TESTSLOT ; Keep looking until slot 0 - sty MOUSE_SLOT ; Oops, no mouse - make a note - rts ; and bail - -; -; Step 2: Set up indirect calling routines -; - -FOUND_MOUSE: - ; Slot is in y - - 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 - asl - asl - sta TOMOUSE_n0 ; Y register before firmware calls - -; -; Step 3: Configure the 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 - - cli ; Enable interrupts so mouse can function - - rts - -.endproc - - -;-------------------------------------------------- -; Indirect jump table for mouse firmware routines -;-------------------------------------------------- - -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 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 -.endproc - ; fall through - -; The following operand bytes must be patched by the -; initialization code which detects the mouse. - -BANK = $C054 - -TOMOUSE: - ldx #$C1 ; Set up slot in $Cn form in X - ldy #$10 ; Set up slot in $n0 form in Y - php ; Save interrupt state - sei ; No interrupts while calling - bit BANK - jsr SLOT_BASE ; Go to the mouse routine - plp ; Restore interrupt state - rts - -TOMOUSE_Cn = TOMOUSE + 1 -TOMOUSE_n0 = TOMOUSE + 3 -TOMOUSE_lsb = TOMOUSE + 10 -TOMOUSE_msb = TOMOUSE + 11 - - -; TODO: Turn this into a proper delta-sending routine - -;-------------------------------------------------- -.proc FOOMOUSE -;-------------------------------------------------- -; -;-------------------------------------------------- - txa ; save x - pha - tya ; save y - pha - - jsr READMOUSE - - jmp DONE - - ldx MOUSE_SLOT - - lda MOUSE_X_LSB,x - sta LAST_MX - - 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 SSCPUT - lda LAST_MY - ora #SIS_MY - jsr SSCPUT - - PosMouse MOUSE_CENTER_X, MOUSE_CENTER_Y - -DONE: - pla ; restore y - tay - pla ; restore x - tax - rts - -.endproc - -.endif ; MOUSE_SUPPORT - - -;------------------------------------------------------------------- -; -; Lookup Tables and Variable Storage -; -;------------------------------------------------------------------- - -; Lookup table for UACTRL register, by baud rate +;;; Lookup table for UACTRL register, by baud rate BPSCTRL: .byte $16,$1E,$1F,$10 ; 300, 9600, 19200, 115k (with 8 data bits, 1 stop bit, no echo) .enum - BPS_300 - BPS_9600 + BPS_300 + BPS_9600 BPS_19200 - BPS_115k + BPS_115k .endenum CMND_NRDI = $0B ; Command: no parity, RTS on, DTR on, no interrupts -; Application configuration +;;; Application configuration PSPEED: .byte BPS_115k ; Hardcoded for Apple IIc (TODO: Allow configuration) PSLOT: .byte 2 ; Hardcoded for Apple IIc (TODO: Allow configuration) PEXIT: .byte 0 ; Set when it's time to exit (Not Yet Implemented) -; Keyboard state +;;; Keyboard state LASTKB: .byte 0 LASTOA: .byte 0 LASTCA: .byte 0 .ifdef PADDLE_SUPPORT -; Paddle state +;;; Paddle state LASTP0: .byte 0 LASTP1: .byte 0 .endif ; PADDLE_SUPPORT - - -.ifdef MOUSE_SUPPORT - -; Mouse -MOUSE_SLOT: .byte 0 ; mouse slot, or 0 if none -LAST_MX: .byte $7f -LAST_MY: .byte $7f - -; Mouse ID bytes -MOUSEID_MAX = 4 -MOUSEID_ADDR: .byte $05, $07, $0b, $0c, $fb -MOUSEID_VAL: .byte $38, $18, $01, $20, $d6 - -.endif ; MOUSE_SUPPORT - diff --git a/client/mouse.inc b/client/mouse.inc new file mode 100644 index 0000000..a13d574 --- /dev/null +++ b/client/mouse.inc @@ -0,0 +1,293 @@ +;;;------------------------------------------------------------------- +;;; +;;; Mouse +;;; +;;;------------------------------------------------------------------- + +.error "Mouse support not fully implemented" + +.proc Mouse + +;;;-------------------------------------------------- +;;; Locations and constants +;;;-------------------------------------------------- + +;;; 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_MODE = $07F8 ; + slot Mode byte + +;;; 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_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 +MOUSEID_ADDR: .byte $05, $07, $0b, $0c, $fb +MOUSEID_VAL: .byte $38, $18, $01, $20, $d6 + +;;;-------------------------------------------------- +;;; Data +;;;-------------------------------------------------- + +;;; Mouse +MOUSE_SLOT: .byte 0 ; mouse slot, or 0 if none +LAST_MX: .byte $7f +LAST_MY: .byte $7f + + +;;;-------------------------------------------------- +;;; 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 + + +;;;-------------------------------------------------- +;;; Macros for common mouse operations +;;;-------------------------------------------------- + +;;;---------------------------------------- +.macro ClampMouse axis, min, max +;;;---------------------------------------- +;;; axis: MOUSE_CLAMP_X or MOUSE_CLAMP_Y +;;; min: minimum value (2 byte) +;;; max: maximum value (2 byte) +;;;---------------------------------------- + ; Clamp X to 0...255 + lda #min + sta MOUSE_CMIN_MSB + lda #max + sta MOUSE_CMAX_MSB + lda #axis + jsr CLAMPMOUSE +.endmacro + +;;;---------------------------------------- +.macro PosMouse px, py +;;;---------------------------------------- + ldx MOUSE_SLOT + lda #px + sta MOUSE_X_MSB,X + lda #py + sta MOUSE_Y_MSB,X + jsr POSMOUSE +.endmacro + + +;;;--------------------------------------------------------- +.proc FindMouse +;;;--------------------------------------------------------- +;;; Find and initialize the mouse port +;;;--------------------------------------------------------- + +;;; 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 +; + + ldy #MAX_SLOT ; Start search in slot 7 + +TESTSLOT: + sty MOUSE_SLOT ; Save for later + tya + clc + adc #>SLOT_BASE ; Firmware is $c0 + slot + sta MOD_MOUSE_ID + 2 ; 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 +MOD_MOUSE_ID: + lda SLOT_BASE + cmp MOUSEID_VAL,x ; Does it match the signature? + bne NOMATCH ; Nope - try the next slot + dex ; Yes! Keep testing + bpl TESTID ; Fall through if all done + jmp FOUND_MOUSE + +NOMATCH: + dey ; Didn't match + bne TESTSLOT ; Keep looking until slot 0 + sty MOUSE_SLOT ; Oops, no mouse - make a note + rts ; and bail + +; +;;; Step 2: Set up indirect calling routines +; + +FOUND_MOUSE: + ; Slot is in y + + 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 + asl + asl + sta TOMOUSE_n0 ; Y register before firmware calls + +; +;;; Step 3: Configure the 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 + + cli ; Enable interrupts so mouse can function + + rts + +.endproc + + +;;;-------------------------------------------------- +;;; Indirect jump table for mouse firmware routines +;;;-------------------------------------------------- + +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 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 +.endproc + ; fall through + +;;; The following operand bytes must be patched by the +;;; initialization code which detects the mouse. + +BANK = $C054 + +TOMOUSE: + ldx #$C1 ; Set up slot in $Cn form in X + ldy #$10 ; Set up slot in $n0 form in Y + php ; Save interrupt state + sei ; No interrupts while calling + bit BANK + jsr SLOT_BASE ; Go to the mouse routine + plp ; Restore interrupt state + rts + +TOMOUSE_Cn = TOMOUSE + 1 +TOMOUSE_n0 = TOMOUSE + 3 +TOMOUSE_lsb = TOMOUSE + 10 +TOMOUSE_msb = TOMOUSE + 11 + + +;;; TODO: Turn this into a proper delta-sending routine + +;;;-------------------------------------------------- +.proc FOOMOUSE +;;;-------------------------------------------------- +; +;;;-------------------------------------------------- + txa ; save x + pha + tya ; save y + pha + + jsr READMOUSE + + jmp DONE + + ldx MOUSE_SLOT + + lda MOUSE_X_LSB,x + sta LAST_MX + + 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 + jsr SSC::Put + + PosMouse MOUSE_CENTER_X, MOUSE_CENTER_Y + +DONE: + pla ; restore y + tay + pla ; restore x + tax + rts + +.endproc + +.endproc \ No newline at end of file diff --git a/client/ssc.inc b/client/ssc.inc new file mode 100644 index 0000000..f3f7b88 --- /dev/null +++ b/client/ssc.inc @@ -0,0 +1,100 @@ +;;;------------------------------------------------------------------- +;;; +;;; Serial port routines +;;; +;;; (based on ADTPro) +;;; +;;;------------------------------------------------------------------- + +.proc SSC + +;;;--------------------------------------------------------- +.proc Init +;;;--------------------------------------------------------- +;;; Initialize the SSC; slot passed in A +;;;--------------------------------------------------------- + asl ; Slot passed in A + asl + asl + asl ; Now $S0 + adc #$88 ; Low byte of UADATA + tax + lda #CMND_NRDI ; Command register: no parity, RTS on, DTR on, no interrupts + sta $C002,X + ldy PSPEED ; Control register: look up by baud rate (8 data bits, 1 stop bit) + lda BPSCTRL,Y + sta $C003,X + stx MOD_UADATA_1+1 ; Modify references to + stx MOD_UADATA_2+1 ; UADATA to point at + stx MOD_UADATA_3+1 ; correct slot (UADATA+S0) + inx + stx MOD_UASTAT_1+1 ; Modify reference to + stx MOD_UASTAT_2+1 ; UASTAT to point at + stx MOD_UASTAT_3+1 ; correct slot (UASTAT+S0) + rts + +.endproc + + +;;;--------------------------------------------------------- +.proc Put +;;;--------------------------------------------------------- +;;; Send accumulator out the serial port +;;;--------------------------------------------------------- + pha ; Push A onto the stack +MOD_UASTAT_1: +: lda UASTAT ; Check status bits + and #$70 + cmp #$10 + bne :- ; Output register is full, so loop + pla +MOD_UADATA_1: + sta UADATA ; Put character + rts +.endproc + MOD_UASTAT_1 := Put::MOD_UASTAT_1 + MOD_UADATA_1 := Put::MOD_UADATA_1 + +;;;--------------------------------------------------------- +.proc Get +;;;--------------------------------------------------------- +;;; Read a character from the serial port to the accumulator +;;;--------------------------------------------------------- +MOD_UASTAT_2: + lda UASTAT ; Check status bits + and #$68 + cmp #$8 + bne Get ; Input register empty, loop +MOD_UADATA_2: + lda UADATA ; Get character + rts +.endproc + MOD_UASTAT_2 := Get::MOD_UASTAT_2 + MOD_UADATA_2 := Get::MOD_UADATA_2 + +;;;--------------------------------------------------------- +.proc HasData +;;;--------------------------------------------------------- +;;; Read a character from the serial port to the accumulator +;;;--------------------------------------------------------- +MOD_UASTAT_3: + lda UASTAT ; Check status bits + and #$68 + cmp #$8 + rts +.endproc + MOD_UASTAT_3 := HasData::MOD_UASTAT_3 + + +;;;--------------------------------------------------------- +.proc Reset +;;;--------------------------------------------------------- +;;; Clean up serial port +;;;--------------------------------------------------------- +MOD_UADATA_3: + bit UADATA + rts +.endproc + MOD_UADATA_3 := Reset::MOD_UADATA_3 + +.endproc