apple2pi/client/BUILD/a2pigs.s

593 lines
9.3 KiB
ArmAsm
Executable File

PTR = $06
PTRL = $06
PTRH = $07
SPINIDX = $07
BASEL = $28
CSWL = $36
CSWH = $37
KSWL = $38
KSWH = $39
RNDL = $4E
RNDH = $4F
MOUROM = $C4
MOUINDEX = $04
MOUSLOT = $40
CEVL = $3CE
CEVH = $3CF
OUTVECT0 = $BE10
OUTVECT3 = $BE16
INVECT0 = $BE20
INVECT3 = $BE26
VECTOUT = $BE30
VECTIN = $BE32
WARMDOS = $BE00
TEXTSCRN = $0400
WAIT = $FCA8
BELL1 = $FBD9
COUT1 = $FDF0
KEYBD = $C000
KBCLR = $C010
ANYKEY = $C010
;---------------------------------------------------------
; Apple IIgs SCC Z8530 registers and constants
;---------------------------------------------------------
GSCMDB = $C038
GSDATAB = $C03A
GSCMDA = $C039
GSDATAA = $C03B
RESETB = %01010001 ; constant to reset Channel B
WR11A = %11010000 ; init wr11 in Ch A
WR11BXTAL = %00000000 ; init wr11 in Ch B - use external clock
WR11BBRG = %01010000 ; init wr11 in Ch B - use baud rate generator
.org $9600
CLD
;
; SLOTS FOR MOUSE AND SERIAL ON IIGS ARE WELL KNOWN
;
;
; RESET ENTRYPOINT
;
ENTRY: CLI
;
; INIT MOUSE
;
INITMOU:
LDY #$19 ; INIT MOUSE
JSR CALLMOU
LDY #$12 ; SET MOUSE
LDA #$01 ; TRANSPARENT MODE
JSR CALLMOU
LDA #$00
STA $478
STA $4F8
LDA #$C0
STA $578
LDA #$3F
STA $5F8
LDY #$17 ; CLAMP MOUSE
LDA #$00 ; X AXIS
JSR CALLMOU
LDY #$17 ; CLAMP MOUSE
LDA #$01 ; Y AXIS
JSR CALLMOU
;
; INIT SCC MODEM PORT FOR 115K BAUD
;
INITSCC:
SEI ; No interruptions here!
LDA GSCMDB ; Hit rr0 once to sync up
LDY #$00
SCCREGS:
LDA SCCTAB,Y
STA GSCMDB
INY
LDA SCCTAB,Y
STA GSCMDB
INY
CPY SCCTABLEN
BNE SCCREGS
CLI ; we're done!
;
; SYNCHRONIZE WITH PI
;
SYNC: LDA #$80
JSR SENDACC
INC SPINIDX
LDA SPINIDX
AND #$03
TAX
LDA SPINNER,X
STA TEXTSCRN
LDA #$FF
JSR WAIT
LDA KEYBD
BPL CHKACK
JMP EXIT
CHKACK: ; Read a byte from SCC
LDA GSCMDB ; dummy read to reset SCC pointer to 0
SYNCLUP:
BIT $C0E0 ; attempt to slow down accelerators by referencing slot 6 ($C080 + $60)
LDA GSCMDB ; read SCC register 0
AND #$01 ; bit 0 means receive available
CMP #$01
BNE SYNC
SYNCRDY:
LDA #$01 ; set pointer to rr1
STA GSCMDB
LDA GSCMDB ; read SCC register 1
AND #$20 ; check for bit 5=rx overrun
BEQ SYNCOK
LDX #$30 ; clear overrun
STX GSCMDB
LDX #$00
STX GSCMDB
SYNCOK: LDA #$08 ; get ready to read rr8 (our SCC byte)
STA GSCMDB
LDA GSCMDB ; read it
CMP #$81
BNE SYNC
LDY #$20 ; Tell 'em about slot 2
STY $301 ; TELL CALLING PROGRAM SYNC OK
LDA #$A0
STA TEXTSCRN ; Clear the spinner out
LDA #$87
JSR BELL1
LDA ANYKEY
STA KEYSTAT
;
; GET COUT/CIN VECTORS
;
JSR $C300
LDA CSWL
STA CHAINOUT+1
LDA CSWH
STA CHAINOUT+2
JSR HOOK
;
; SET VECTOR FOR CHKEVENT
;
; LDX #<CHKEVENT
; STX CEVL
; LDX #>CHKEVENT
; STX CEVH
;
; SET UP RESET VECTOR
;
LDA RESET+1
BNE ISRESET
LDA $3F2
STA RESET
LDA $3F3
STA RESET+1
LDA #<ENTRY
STA $3F2
LDA #>ENTRY
STA $3F3
EOR #$A5
STA $3F4
RTS
ISRESET:
LDX #$FF
TXS
JMP WARMDOS
;
; CHAR OUT HOOK - CHECK ONCE FOR A2PI EVENTS
;
COUTPI: PHP
CLI
PHA
STX SAVEX
STY SAVEY
LDA #$98
JSR SENDACC
PLA
PHA
JSR SENDACC
JSR SENDACC
LDA CHRIN
BNE COUTNXT ; SKIP IF INPUT CHAR PENDING
LDA KEYBD
CMP #$83 ; SKIP CTRL-C
BEQ COUTNXT
CMP #$93 ; SKIP CTRL-S
BEQ COUTNXT
LDA #$01
STA WAITEV
JSR CHKEVENT ; CHECK ON EVENTS
BCC COUTNXT
STA CHRIN
COUTNXT:
PLA
LDY SAVEY
LDX SAVEX
PLP
STA SAVEY
CHAINOUT:
JSR COUT1
;
; SET INPUT/OUTPUT VECTORS
;
HOOK: STX SAVEX
LDX #<COUTPI
STX CSWL
LDX #>COUTPI
STX CSWH
LDX #<CINPI
STX KSWL
LDX #>CINPI
STX KSWH
LDX SAVEX
RTS
;
; CHAR IN HOOK - EVENT LOOP FOR A2PI DAEMON
;
CINPI: STA (BASEL),Y ; RESTORE CURSOR
LDA CHRIN
BNE CINPIEX
STX SAVEX
LDA #$5F ; PRINT _
JSR CHAINOUT
LDA #$88 ; BACKSAPCE
JSR CHAINOUT
PHP
CLI
EVENTLP:
INC RNDL ; UPDATE RND LIKE ANY PROPER RDKEY
BNE EVENTLP1
INC RNDH
EVENTLP1:
JSR CHKEVENT
BCC EVENTLP
PLP ; HAVE CHAR FROM A2PI DAEMON
LDX SAVEX
CINPIEX:
LDY #$00
STY CHRIN
RTS
;
; SEND MODIFIER (OPEN & CLOSED APPLE) KEYS/PADDLE BUTTONS
;
SENDMOD:
LDA $C062
ASL
LDA $C061
ROR
AND #$C0 ; FALL THROUGH
;
; ACIA SEND BYTE IN ACCUMULATOR
;
SENDACC:
STA SAVEY
STX SAVEX
SCCSEND:
LDA GSCMDB
TAX
AND #%00000100 ; test bit 2 (hardware handshaking)
BEQ SCCSEND
TXA
AND #%00100000 ; test bit 5 (ready to send?)
BEQ SCCSEND
LDA SAVEY ; ready... get the byte to send
STA GSDATAB ; send the byte
LDX SAVEX
LDA SAVEY
RTS
;
; SCC RECEIVE BYTE IN ACCUMULATOR
;
RECVACC:
LDA GSCMDB ; dummy read to reset SCC pointer to 0
RECVLUP:
BIT $C0E0 ; attempt to slow down accelerators by referencing slot 6 ($C080 + $60)
LDA GSCMDB ; read SCC register 0
AND #$01 ; bit 0 means receive available
CMP #$01
BNE RECVLUP
RECVRDY:
LDA #$01 ; set pointer to rr1
STA GSCMDB
LDA GSCMDB ; read SCC register 1
AND #$20 ; check for bit 5=rx overrun
BEQ RCVOK
LDX #$30 ; clear overrun
STX GSCMDB
LDX #$00
STX GSCMDB
RCVOK: LDA #$08 ; get ready to read rr8 (our SCC byte)
STA GSCMDB
LDA GSCMDB ; read it
CLC
RTS
;
; CHECK INPUT STATE FOR CHANGE
;
CHKEVENT:
LDA ANYKEY ; CHECK FOR KEY PRESS/RELEASE
CMP KEYSTAT
BNE SENDKEY
LDA GSCMDB
BIT $C0E0
LDA GSCMDB
AND #$01
CMP #$01
BNE CHKMOU ; no data; check for mouse
JSR RECVRDY
JMP HOSTREQ
CHKMOU: DEC WAITEV ; CHECK FOR MOUSE UPDATE
BEQ UPDTMOU
EXEVENT:
CLC
RTS
;
; KEYBOARD EVENT
;
SENDKEY:
TAX
BPL SENDKBEV
LDA #$80 ; DEBOUNCE KEYPRESS
JSR WAIT
LDX ANYKEY
CPX #$FF
BNE SENDKBEV
LDA $C062
BPL SENDKBEV
LDA $C061
BPL SENDKBEV
UNHOOK: JSR EXIT
LDA #$00
STA RESET
STA RESET+1
LDA #$0D
SEC
RTS
SENDKBEV:
STX KEYSTAT
LDA #$82 ; KBEVENT CODE
JSR SENDACC
JSR SENDMOD
TXA
CLC
JMP SENDACC
;
; MOUSE EVENTS
;
UPDTMOU:
LDY #$14 ; READ MOUSE
LDA #$80
JSR CALLMOU
BCC EXMOU
LDY #MOUINDEX
LDA $478,Y
STA MOUXSTAT
LDA $4F8,Y
STA MOUYSTAT
LDA $778,Y
PHA
LDY #$15 ; CLEAR MOUSE
LDA #$80
JSR CALLMOU
LDA MOUXSTAT
ORA MOUYSTAT
BEQ CHKBTTN
LDA #$84 ; SEND MOUSE POSITION
JSR SENDACC
LDA MOUXSTAT
JSR SENDACC
LDA MOUYSTAT
JSR SENDACC
CHKBTTN:
LDY #MOUINDEX
PLA
STA $778,Y ; GS CLEARS THIS IN CLEAR MOUSE CALL
AND #$80
CMP BTTNSTAT
BEQ EXMOU
SENDBTTN:
STA BTTNSTAT
LDA #$86
JSR SENDACC
JSR SENDMOD
LDA BTTNSTAT
JSR SENDACC
EXMOU: CLC
RTS
;
; CALL MOUSE FIRMWARE
;
CALLMOU:
LDX #MOUROM
PHA
LDA PTRL ; SAVE ZERO PAGE LOCATIONS
STA SAVEZP
LDA PTRH
STA SAVEZP+1
LDA #$00
STA PTRL
STX PTRH
LDA (PTR),Y
STA PTRL
PLA
LDX #MOUROM
LDY #MOUSLOT
PHP
SEI
JSR IJMP
PLP
LDA SAVEZP ; RESTORE ZERO PAGE LOCATIONS
STA PTRL
LDA SAVEZP+1
STA PTRH
SEC ; MOUSE PRESENT FLAG
RTS
;
; HOST REQUEST/RESPONSE HANDLING
;
RECVADDR:
JSR SENDACC ; ECHO REQUEST
JSR SENDACC ; DUMMY VALUE
JSR SENDACC ; DUMMY VALUE
JSR RECVACC
STA PTRL
TXA ; ACK
JSR SENDACC
JSR RECVACC
STA PTRH
TXA ; ACK
JMP SENDACC
RECVCNT:
JSR RECVACC
STA CNTL
TXA ; ACK
JSR SENDACC
JSR RECVACC
STA CNTH ; INC FOR LOOP CONTROL
INC CNTH
TXA ; ACK
JMP SENDACC
HOSTREQ:
LDX PTRL ; SAVE ZERO PAGE LOCATIONS
STX SAVEZP
LDX PTRH
STX SAVEZP+1
READREQ:
CMP #$90 ; READ BYTES
BNE WRITEREQ
LDX #$91
JSR RECVADDR
JSR RECVCNT
LDX #$00
READLP: LDA (PTR,X)
JSR SENDACC
INC PTRL
BNE READDEC
INC PTRH
READDEC:
DEC CNTL
BNE READLP
DEC CNTH
BNE READLP
BEQ OKREQ
WRITEREQ:
CMP #$92 ; WRITE BYTES
BNE CALLREQ
SEI ; DISABLE INTERRUPTS
LDX #$93
JSR RECVADDR
JSR RECVCNT
LDX #$00
WRITELP:
JSR RECVACC
STA (PTR,X)
INC PTRL
BNE WRITEDEC
INC PTRH
WRITEDEC:
DEC CNTL
BNE WRITELP
DEC CNTH
BNE WRITELP
BEQ OKREQ
CALLREQ:
CMP #$94
BEQ CALLREQ1
CMP #$9A
BNE CINREQ
CALLREQ1:
TAX
INX
JSR RECVADDR
JSR IJMP
OKREQ: LDX #$9E ; REQ COMPLETE OK
SENDCOMP:
CLI ; ENABLE INTERRUPTS
PHP
PHA
TXA
JSR SENDACC
PLA
JSR SENDACC ; ACCUM VALUE
PLA
JSR SENDACC ; FLAGS VALUE
LDA SAVEZP ; RESTORE ZERO PAGE LOCATIONS
STA PTRL
LDA SAVEZP+1
STA PTRH
EXREQ: CLC
RTS
CINREQ: CMP #$96
BNE RESYNC
LDX #$97
JSR RECVADDR
LDA #$9E ; REQ COMPLETE OK
JSR SENDACC
LDA PTRL
LDX SAVEZP ; RESTORE ZERO PAGE LOCATIONS
STX PTRL
LDX SAVEZP+1
STX PTRH
JSR SENDACC ; ECHO VALUE
JSR SENDACC ; ECHO VALUE
SEC ; RETURN CHAR TO RDKEY
RTS
RESYNC: CMP #$80 ; RESYNC WITH HOST
BNE BADREQ
JSR SENDACC ; ECHO
JSR RECVACC
CMP #$81
BEQ EXREQ
; JMP UNHOOK
BNE RESYNC
BADREQ: LDX #$9F ; REQ BAD
BNE SENDCOMP
;
; CLEANUP
;
EXIT: LDA KBCLR
JSR $C300
LDA RESET+1
BEQ EX1
STA $3F3
EOR #$A5
STA $3F4
LDA RESET
STA $3F2
EX1: LDY #$12 ; SET MOUSE
LDA #$00 ; DISABLE MOUSE
STA RESET
STA RESET+1
JMP CALLMOU
IJMP: JMP (PTR)
MOUXSTAT: .byte 0
MOUYSTAT: .byte 0
BTTNSTAT: .byte 0
KEYSTAT: .byte 0
WAITEV: .byte 0
CNTL: .byte 0
CNTH: .byte 0
RESET: .word 0
SAVEZP: .word 0
SAVEX: .byte 0
SAVEY: .byte 0
CHRIN: .byte 0
SPINNER: .byte $af, $ad, $dc, $fc ; "/-\|" (i.e. rotate clockwise)
SCCTABLEN:
.byte 24 ; Number of bytes to follow
SCCTAB: .byte 9, RESETB
.byte 3, %11000000
.byte 5, %01100010
.byte 14, %00000000
.byte 4, %10000100
.byte 11, WR11BXTAL
.byte 3, %11000001
.byte 5, %01101010
.byte 15, %00000000
.byte 0, %00010000 ; Need this twice
.byte 0, %00010000 ; Need this twice
.byte 1, %00000000