From 2b2a722e4605756b41462c40da134a4f2da0c0a8 Mon Sep 17 00:00:00 2001 From: David Schmidt Date: Sun, 22 Feb 2015 17:07:12 -0500 Subject: [PATCH] Initial GS implementation - blurts random text on the GS at first --- client/BUILD/a2pigs.s | 592 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 592 insertions(+) create mode 100755 client/BUILD/a2pigs.s diff --git a/client/BUILD/a2pigs.s b/client/BUILD/a2pigs.s new file mode 100755 index 0000000..c416019 --- /dev/null +++ b/client/BUILD/a2pigs.s @@ -0,0 +1,592 @@ +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 CEVH +; +; SET UP RESET VECTOR +; + LDA RESET+1 + BNE ISRESET + LDA $3F2 + STA RESET + LDA $3F3 + STA RESET+1 + 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 CSWH + 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