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
