********************************************************************************
* Apple II SSC Firmware *
* *
* By Larry Kenyon *
* -January 1981- *
* *
* (C) Copyright 1981 by Apple Computer, Inc. *
********************************************************************************
* This is a disassembly of the Super Serial Card (SSC) ROM, based on the *
* listing in _Super Serial Card Installation and Operating Manual_ (starting *
* on page 58). The ROM binary is from AppleWin's "SSC.rom", which puts the *
* $C200 code at the end rather than the start. *
********************************************************************************
* Project created by Andy McFadden, using 6502bench SourceGen v1.7.4. *
* Last updated 2021/06/11 *
********************************************************************************
* Notes on declarations... *
* *
* *** SSC Card Addresses *** *
* *
* Bit-> B7 B6 B5 B4 B3 B2 B1 B0 *
* +----------------------------+ *
* DIPSW1 S1 S2 S3 S4 Z Z S5 S6 (left dipswitch) *
* *
* (S1-S4 used for baud rate, S5-S6 for firmware mode) *
* *
* DIPSW2 S1 Z S2 Z S3 S4 S5 CTS (right dipswitch) *
* *
* STREG INT DSR DCD TDR RDR OVR FE PE *
* *
* CTLREG STB << WL >> CK << BAUD RATE >> *
* *
* CMDREG <<PARITY >> ECH <<XMIT>> RE DTR *
* *
* *
* *** Screen Variables: PPC and SIC modes *** *
* STATEFLG ($578-$C0): *
* B7=CR gen enb flag B6=after LC input flg *
* B2-B0=command interpreter states *
* 0 0 0 idle *
* 0 0 1 cmd char received *
* 0 1 0 collect <N> until char then do command *
* 0 1 1 skip until space, then goto state 4 *
* 1 0 0 E/D commands *
* 1 0 1 unused *
* 1 1 0 wait until CR then set state to zero *
* 1 1 1 wait until CR then do proc indicated by parm *
* *
* (B4-B0 determine enquire char for P8A mode) *
* *
* CIC mode: *
* B7=terminal mode flag *
* B3-B5=chain slot *
* *
* DELAYFLG ($478-$C0): *
* B7-B6=screen translation options *
* 0 0 LC->UC *
* 0 1 no translation *
* 1 0 LC->UC inverse *
* 1 1 LC->UC, UC->UC inverse *
* (1-3 will allow LC chars to pass thru monitor) *
* *
* B5-B4=CR delay 0 0 = no delay *
* B3-B2=LF delay 0 1 = 32 millisec *
* B1-B0=FF delay 1 0 = 1/4 sec *
* 1 1 = 2 sec *
* *
* MISCFLG ($7f8-$C0): *
* B7=echo bit B6=tabbing option enable *
* B5=linefeed eat B4=Pascal/BASIC flag *
* B3=XOFF enb flag B2=keyboard enb *
* B1=PPC/CIC mode B0=LF generate enb *
* *
* CIC mode: B6=term mode shift enb *
********************************************************************************
PARAMETER .eq $0438 {const} ;accumulator for cmd parameter
CHNBYTE .eq $0638 {const} ;current output screen ($CN00 entry)
BUFBYTE .eq $06b8 {const} ;buffer for one input byte
MON_CH .eq $24 ;cursor horizontal displacement
SLOT16 .eq $26 ;save $NO to free up Y-reg
CHARACTER .eq $27 ;output, screen and input chars
MON_BASL .eq $28 ;base address for text output (lo)
ZPTMP1 .eq $2a ;when ZPTEMP isn't enough
ZPTMP2 .eq $2b ;temporaries, temporaries!
ZPTEMP .eq $35 ;workhorse temporary
MON_CSWL .eq $36 ;character output hook (lo)
MON_CSWH .eq $37 ;character output hook (hi)
MON_KSWL .eq $38 ;character input hook (lo)
MON_KSWH .eq $39 ;character input hook (hi)
MON_A1L .eq $3c ;general purpose
MON_RNDL .eq $4e ;low byte of KEYIN "random" value
MON_RNDH .eq $4f ;high byte of KEYIN "random" value
STACK .eq $0100 {addr/256} ;system stack block
INBUFF .eq $0200 {addr/256} ;system input buffer
DELAYFLG .eq $03b8 ;(see notes)
HANDSHKE .eq $0438 ;SIC P8A char counter for ETX/ACK
STATEFLG .eq $04b8 ;(see notes)
CMDBYTE .eq $0538 ;holds command character (PPC & CIC)
STSBYTE .eq $05b8 ;status/ioresult/input byte
PWDBYTE .eq $0638 ;printer (format) width
COLBYTE .eq $06b8 ;column position counter
MISCFLG .eq $0738 ;(see notes)
MSLOT .eq $07f8 ;buffer for hi slot addr ($CN)
KBD .eq $c000 ;R last key pressed + 128
KBDSTRB .eq $c010 ;RW keyboard strobe
DIPSW1 .eq $c081 ;(+$NO) dipswitch block 1
DIPSW2 .eq $c082 ;(+$NO) dipswitch block 2
RDREG .eq $c088 ;(+$NO) read data reg (read)
RESET .eq $c089 ;(+$NO) software reset (write)
STREG .eq $c089 ;(+$NO) status register (read)
CMDREG .eq $c08a ;(+$NO) command register (R/W)
CTLREG .eq $c08b ;(+$NO) control register (R/W)
CLRROM .eq $cfff ;disable slot C8 ROM
MON_NXTA1 .eq $fcba ;increment A1; set carry if A1 >= A2 before inc
MON_COUT .eq $fded ;print Acc to output device via $36-37
MON_COUTZ .eq $fdf6
MON_SETKBD .eq $fe89 ;reset char input handler to ROM
MON_SETVID .eq $fe93 ;reset char output handler to ROM
MON_IORTS .eq $ff58 ;JSR here to find out where one is
.org $c800
********************************************************************************
* *
* C800 space: high level stuff. *
* *
********************************************************************************
c800: 20 9b c9 PASCALINIT jsr PENTRY ;Pascal 1.0 initialization entry
c803: a9 16 lda #$16 ;no XOFF, echo, LF eat, or LF gen
c805: 48 INIT1 pha ;goes to MISCFLG after modification
c806: a9 00 lda #$00
c808: 9d b8 04 sta STATEFLG,x
c80b: 9d b8 03 sta DELAYFLG,x
c80e: 9d 38 04 sta HANDSHKE,x
c811: 9d b8 05 sta STSBYTE,x
c814: 9d 38 06 sta PWDBYTE,x
c817: 9d b8 06 sta COLBYTE,x
c81a: b9 82 c0 lda DIPSW2,y ;set LF gen option from D2-S5
c81d: 85 2b sta ZPTMP2 ;save for later
c81f: 4a lsr A ;S5-> carry
c820: 4a lsr A ;if S5=on=0 then leave MISCFLG alone
c821: 90 04 bcc INIT1A
c823: 68 pla ;otherwise, make sure LF gen
c824: 29 fe and #$fe ; enable is reset
c826: 48 pha
c827: b8 INIT1A clv ;V will be clear for CIC mode
c828: b9 81 c0 lda DIPSW1,y
c82b: 4a lsr A ;SIC modes set carry
c82c: b0 07 bcs INIT2 ;branch for SIC modes
c82e: 4a lsr A
c82f: b0 0e bcs INIT2B ;PPC mode branch
c831: a9 01 lda #$01 ;Ctl-A
c833: d0 3d bne INIT5 ;<always> CIC mode branch
c835: 4a INIT2 lsr A ;set carry for P8A
c836: a9 03 lda #$03 ;set ETX as default inquiry char
c838: b0 02 bcs INIT2A ;branch for P8A
c83a: a9 80 lda #$80 ;for P8 set auto CR gen
c83c: 9d b8 04 INIT2A sta STATEFLG,x
c83f: 2c 58 ff INIT2B bit MON_IORTS ;set V-flag for PPC, SIC modes
c842: a5 2b lda ZPTMP2
c844: 29 20 and #$20 ;set CR delay
c846: 49 20 eor #$20 ;SO 1=ENB, 0=DISABLE
c848: 9d b8 03 sta DELAYFLG,x ; from D2-S2
;
c84b: 70 0a bvs INIT3 ;<always> branch around Pascal
;
; Pascal 1.0 read entry (must be at $C84D).
;
c84d: 20 9b c8 jsr PASCALREAD ;do Pascal 1.1 read
c850: ae f8 07 ldx MSLOT ;modify for 1.0
c853: 9d b8 05 sta STSBYTE,x ;character read
c856: 60 rts
;
; Now where were we?
;
c857: a5 2b INIT3 lda ZPTMP2 ;PPC, SIC modes use switches
c859: 4a lsr A ; to set pwidth, CR delay
c85a: 4a lsr A
c85b: 29 03 and #$03
c85d: a8 tay
c85e: f0 04 beq INIT4
;
c860: 68 pla ;reset video enable for pwidth#40
c861: 29 7f and #$7f
c863: 48 pha
;
c864: b9 a6 c9 INIT4 lda PWDTBL,y
c867: 9d 38 06 sta PWDBYTE,x
c86a: a4 26 ldy SLOT16
;
c86c: 68 pla ;clear CIC bit in future MISCFLG
c86d: 29 95 and #$95 ; (and tabbing, XOFF and LF eat bits)
c86f: 48 pha
c870: a9 09 lda #$09 ;Ctl-I
;
c872: 9d 38 05 INIT5 sta CMDBYTE,x ;cmd ESC char (ignored for SIC modes)
c875: 68 pla
c876: 9d 38 07 sta MISCFLG,x ;set MISCFLG flags
;
; Now for the ACIA initialization routine.
;
c879: a5 2b INITACIA lda ZPTMP2 ;DIPSW2
c87b: 48 pha
c87c: 29 a0 and #$a0 ;data bit options for CIC mode
c87e: 50 02 bvc INITACIA1 ;branch for CIC mode
c880: 29 80 and #$80 ;8 data, 1 or 2 stop for SIC, PPC
c882: 20 a1 cd INITACIA1 jsr DATACMD1 ;set control reg
c885: 20 81 cd jsr BAUDCMD1 ;set dipswitch baud rate
c888: 68 pla
c889: 29 0c and #$0c ;parity options for CIC mode
c88b: 50 02 bvc INITACIA2 ;branch for CIC mode
c88d: a9 00 lda #$00 ;disable parity for SIC, PPC modes
c88f: 0a INITACIA2 asl A
c890: 0a asl A
c891: 0a asl A
c892: 09 0b ora #$0b
c894: 99 8a c0 sta CMDREG,y
c897: b9 88 c0 lda RDREG,y ;throw out the strange stuff
c89a: 60 rts
;
; Pascal read routine.
;
c89b: 20 9b c9 PASCALREAD jsr PENTRY ;shared by both Pascal versions
c89e: 20 aa c8 jsr GETCHAR ;get ACIA/KBD data
c8a1: 29 7f and #$7f ;clear high bit for Pascal
c8a3: ac f8 07 PASEXIT ldy MSLOT
c8a6: be b8 05 ldx STSBYTE,y ;error status-> X-reg
c8a9: 60 rts
;
; GETCHAR routine waits for the next char from either the ACIA or keyboard (if
; enabled). Used by Pascal read routine, XON wait, and ACK wait. Data is
; returned in the A-register.
;
c8aa: 20 ff ca GETCHAR jsr INPUT ;ACIA data?
c8ad: b0 05 bcs GETCHAR1
c8af: 20 2c cc jsr CKKBD ;keyboard input?
c8b2: 90 f6 bcc GETCHAR
c8b4: 60 GETCHAR1 rts ;exit when we have something
;
; CIC exit routine.
;
c8b5: 20 1e ca CICEXIT jsr CHECKTERM ;see if we've entered terminal mode
;
; BASIC exit routine.
;
c8b8: 68 BASICEXIT pla
c8b9: a8 tay
c8ba: 68 pla
c8bb: aa tax
c8bc: a5 27 lda CHARACTER
c8be: 60 rts
;
; BASIC input routine.
;
c8bf: f0 29 BINPUT beq BINACIA ;branch if not CIC mode
c8c1: bd b8 06 lda COLBYTE,x ;input buffer full?
c8c4: 10 05 bpl BINKBD
c8c6: 5e b8 06 lsr COLBYTE,x ;reset buffer full
c8c9: d0 24 bne BINACIA1 ;<always>
c8cb: 20 3e cc BINKBD jsr GETKBD ;keyboard data?
c8ce: 90 1a bcc BINACIA
;
;
c8d0: bd b8 03 BINEND lda DELAYFLG,x
c8d3: 29 c0 and #$c0 ;translate lowercase to uppercase?
c8d5: f0 0e beq BINEND1 ;if so, let the monitor do it
c8d7: a5 27 lda CHARACTER ;if not, set flag if
c8d9: c9 e0 cmp #$e0 ; this is a lowercase char
c8db: 90 08 bcc BINEND1 ; for input buffer correction
c8dd: bd b8 04 lda STATEFLG,x ; (circumvent Apple monitor)
c8e0: 09 40 ora #$40
c8e2: 9d b8 04 sta STATEFLG,x
;
c8e5: 28 BINEND1 plp
c8e6: f0 d0 beq BASICEXIT ;branch if not CIC mode
c8e8: d0 cb bne CICEXIT ;<always> check to see if we entered term mode (via kybd escape)
c8ea: 20 ff ca BINACIA jsr INPUT ;ACIA data?
c8ed: 90 dc bcc BINKBD
c8ef: 20 11 cc BINACIA1 jsr RESTORE ;do BASIC cursed duty
c8f2: 28 plp
c8f3: 08 php ;get CIC mode indicator
c8f4: f0 da beq BINEND ;skip if not CIC mode
c8f6: 20 d1 c9 jsr CKINPUT ;look for input stream special chars
c8f9: 4c d0 c8 LC8F9 jmp BINEND
;
; SIC, PPC BASIC output routine.
;
c8fc: 20 1a cb SEROUT jsr CMDSEQCK ;check for a command sequence
c8ff: b0 b7 bcs BASICEXIT ;branch if we were in command mode
c901: a5 27 lda CHARACTER ;save char on stack
c903: 48 pha
c904: bd 38 07 lda MISCFLG,x ;if video or tabbing enabled,
c907: 29 c0 and #$c0 ; don't mess with the cursor
c909: d0 16 bne TABCHECK
;
c90b: a5 24 lda MON_CH ;check for comma tabbing
c90d: f0 42 beq NOTAB ;if CH=0, there was no tab or comma
c90f: c9 08 cmp #8 ;Integer BASIC comma?
c911: f0 04 beq COMMA
c913: c9 10 cmp #16 ;Applesoft comma?
c915: d0 0a bne TABCHECK
c917: 09 f0 COMMA ora #$f0
c919: 3d b8 06 and COLBYTE,x ;set col to previous tab
c91c: 18 clc
c91d: 65 24 adc MON_CH ;then increment to next tab
c91f: 85 24 sta MON_CH
;
c921: bd b8 06 TABCHECK lda COLBYTE,x
c924: c5 24 cmp MON_CH ;is tabbing needed?
c926: f0 29 beq NOTAB ;if equal then no tab needed
c928: a9 a0 lda #$a0 ;space for forward tab
c92a: 90 08 bcc TAB1
c92c: bd 38 07 lda MISCFLG,x ;don't backspace unless tabbing
c92f: 0a asl A ; option is enabled
c930: 10 1f bpl NOTAB
c932: a9 88 lda #$88 ;backspace for backtab
c934: 85 27 TAB1 sta CHARACTER
c936: 2c 58 ff bit MON_IORTS ;set V=1 to indicate tabbing
c939: 08 php ;save tabbing indicator
c93a: 70 0c bvs TAB2 ;<always> around batch move entry
c93c: ea nop
;
; Short batch move: locate at $C93D for compatibility with SIC P8 block move.
;
c93d: 2c 58 ff BATCHIN bit MON_IORTS ;[known $60; always sets V-flag]
c940: 50 bvc ▼ LC8F9+1 ;dummy BVC
c941: b8 BATCHOUT clv ;V=0 for output entry
c942: ae f8 07 ldx MSLOT
c945: 4c ef c9 jmp BATCHIO
;
; Burp . . .
;
c948: 20 b5 c9 TAB2 jsr ADJUST ;adjust column count
c94b: 20 6b cb jsr OUTPUT2 ;don't go to screen when tabbing
c94e: 4c 68 c9 jmp FORCECR ;share some code. . .
c951: 68 NOTAB pla
c952: b8 clv
c953: 08 php ;save 'no tab' indication
c954: 85 27 NOTAB1 sta CHARACTER ;(force CR reentry)
c956: 48 pha
c957: 20 68 cb jsr OUTPUT1 ;enter after cmd seq check
c95a: 20 b5 c9 jsr ADJUST
c95d: 68 pla
c95e: 49 8d eor #$8d ;was it a CR?
c960: 0a asl A
c961: d0 05 bne FORCECR
c963: 9d b8 06 sta COLBYTE,x ;if so, reset column to 0
c966: 85 24 sta MON_CH
;
c968: bd b8 04 FORCECR lda STATEFLG,x ;force CR disabled?
c96b: 10 0d bpl SEREND
c96d: bd 38 06 lda PWDBYTE,x ;force CR if limit reached
c970: f0 08 beq SEREND ;(for P8 poke compatibility)
c972: 18 clc
c973: fd b8 06 sbc COLBYTE,x
c976: a9 8d lda #$8d
c978: 90 da bcc NOTAB1 ;branch to force CR
;
c97a: 28 SEREND plp
c97b: 70 a4 bvs TABCHECK ;branch if tabbing
;
c97d: bd 38 07 lda MISCFLG,x ;don't mess with cursor
c980: 30 16 bmi SEREND2 ; when video is on
c982: bc b8 06 ldy COLBYTE,x
c985: 0a asl A
c986: 30 0e bmi SETCH ;set CH to value of col for tabbing
c988: 98 tya
c989: a0 00 ldy #0
c98b: 38 sec
c98c: fd 38 06 sbc PWDBYTE,x
c98f: c9 f8 cmp #$f8 ;within 8 chars of pwidth?
c991: 90 03 bcc SETCH
c993: 69 27 adc #$27 ;if so, adjust to within 8 of 40
c995: a8 tay
c996: 84 24 SETCH sty MON_CH
;
c998: 4c b8 c8 SEREND2 jmp BASICEXIT ;that's all
;
; Pascal entry routine.
;
c99b: 8e f8 07 PENTRY stx MSLOT
c99e: 84 26 sty SLOT16
c9a0: a9 00 lda #0
c9a2: 9d b8 05 sta STSBYTE,x
c9a5: 60 rts
;
; SIC mode printer width table.
;
c9a6: 29 PWDTBL .dd1 $29 ;40 columns
c9a7: 48 .dd1 $48 ;72 columns
c9a8: 50 .dd1 $50 ;80 columns
c9a9: 84 .dd1 $84 ;132 columns
;
; Pascal write routine (doubles as Pascal 1.0 entry point)
; - must be at $C9AA -
;
c9aa: 85 27 PASCALWRITE sta CHARACTER
c9ac: 20 9b c9 jsr PENTRY
c9af: 20 63 cb jsr OUTPUT
c9b2: 4c a3 c8 jmp PASEXIT ;load X-reg with error byte & RTS
;
; Column adjust routine (PPC, SIC modes only).
;
c9b5: a5 27 ADJUST lda CHARACTER
c9b7: 49 08 eor #$08 ;backspace?
c9b9: 0a asl A
c9ba: f0 04 beq DECRCOL ;if so, decrement column
c9bc: 49 ee eor #$ee ;delete? ($ff, rub)
c9be: d0 09 bne CTRLTST
c9c0: de b8 06 DECRCOL dec COLBYTE,x ;decrement column count
c9c3: 10 03 bpl ADJRTS
c9c5: 9d b8 06 sta COLBYTE,x ;don't allow to go below 0
c9c8: 60 ADJRTS rts
c9c9: c9 c0 CTRLTST cmp #$c0 ;don't increment column count for
c9cb: b0 fb bcs ADJRTS ; control characters
c9cd: fe b8 06 inc COLBYTE,x
c9d0: 60 rts
;
; Routine to process special input chars.
;
c9d1: bd 38 07 CKINPUT lda MISCFLG,x
c9d4: 29 08 and #$08 ;input ctl chars enabled?
c9d6: f0 16 beq CIEND
;
c9d8: bd b8 04 lda STATEFLG,x
c9db: a4 27 ldy CHARACTER
c9dd: c0 94 cpy #$94 ;Ctl-T?
c9df: d0 04 bne CKINPUT1
c9e1: 09 80 ora #$80 ;set terminal mode
c9e3: d0 06 bne CKINPUT2 ;<always>
c9e5: c0 92 CKINPUT1 cpy #$92 ;Control-R?
c9e7: d0 05 bne CIEND
c9e9: 29 7f and #$7f ;reset terminal mode
c9eb: 9d b8 04 CKINPUT2 sta STATEFLG,x
c9ee: 60 CIEND rts
;
; Short block move.
;
c9ef: 8a BATCHIO txa
c9f0: 0a asl A
c9f1: 0a asl A
c9f2: 0a asl A
c9f3: 0a asl A
c9f4: 85 26 sta SLOT16
c9f6: a9 00 lda #0
c9f8: 9d b8 05 sta STSBYTE,x ;zero error indication
c9fb: 70 0f bvs MOVIN
;
c9fd: a0 00 MOVOUT ldy #$00
c9ff: b1 3c lda (MON_A1L),y ;get buffer data
ca01: 85 27 sta CHARACTER
ca03: 20 02 cc jsr ACIAOUT ;send it out the ACIA
ca06: 20 ba fc jsr MON_NXTA1
ca09: 90 f2 bcc MOVOUT
ca0b: 60 rts
ca0c: 20 d2 ca MOVIN jsr SRIN
ca0f: 90 fb bcc MOVIN
ca11: b9 88 c0 lda RDREG,y
ca14: a0 00 ldy #0
ca16: 91 3c sta (MON_A1L),y ;put ACIA data into buffer
ca18: 20 ba fc jsr MON_NXTA1
ca1b: 90 ef bcc MOVIN
ca1d: 60 rts
********************************************************************************
* *
* Terminal mode routines. *
* *
********************************************************************************
ca1e: bd b8 04 CHECKTERM lda STATEFLG,x ;have we entered terminal mode?
ca21: 10 31 bpl TERMRTS ;if not, a simple RTS will do. . .
;
; We enter the world of terminal mode.
;
ca23: a9 02 lda #$02 ;start in shift-lock state
ca25: 48 pha ;shift state is saved on stack
ca26: a9 7f lda #$7f
ca28: 20 e2 cd jsr KCMD1 ;reset echo (default to full dup)
;
ca2b: a4 24 TERMNEXT ldy MON_CH
ca2d: b1 28 lda (MON_BASL),y
ca2f: 85 27 sta CHARACTER ;save screen character
ca31: a9 07 TERMNEXT1 lda #$07 ;implement a flashing underline
ca33: 25 4f and MON_RNDH ; for a cursor
ca35: d0 10 bne TERMNEXT3
ca37: a4 24 ldy MON_CH
ca39: a9 df lda #$df
ca3b: d1 28 cmp (MON_BASL),y ;is underline on the screen?
ca3d: d0 02 bne TERMNEXT2 ;if not, put it there
ca3f: a5 27 lda CHARACTER ;otherwise use true screen char
ca41: 91 28 TERMNEXT2 sta (MON_BASL),y
ca43: e6 4f inc MON_RNDH ;make it flash, but
ca45: e6 4f inc MON_RNDH ;not too slow and not too fast
;
ca47: bd b8 04 TERMNEXT3 lda STATEFLG,x ;are we still in term mode?
ca4a: 30 09 bmi TERMACIAIN ;if so, go check ACIA
;
ca4c: 20 11 cc jsr RESTORE ;always replace our cursor
ca4f: 68 pla ;clean up the stack
ca50: a9 8d lda #$8d ;return a <CR> to cover up
ca52: 85 27 sta CHARACTER
ca54: 60 TERMRTS rts
ca55: 20 ff ca TERMACIAIN jsr INPUT ;ACIA input?
ca58: 90 0c bcc TERMKBDIN ;if not, go check keyboard
ca5a: 20 11 cc jsr RESTORE ;restore cursor, input->character
ca5d: 20 d1 c9 jsr CKINPUT ;check for Ctl-T, Ctl-R
ca60: 20 a3 cc jsr SCREENOUT1 ;input->screen always
ca63: 4c 2b ca jmp TERMNEXT
ca66: 20 3e cc TERMKBDIN jsr GETKBD ;keypress?
ca69: 90 c6 bcc TERMNEXT1 ;skip if not
ca6b: 70 be bvs TERMNEXT ;branch if we did a kbd escape seq.
ca6d: bd 38 07 lda MISCFLG,x ;shifting enabled?
ca70: 0a asl A
ca71: 10 22 bpl TERMSEND1
ca73: 68 pla ;recover termstate
ca74: a8 tay
ca75: a5 27 lda CHARACTER
ca77: c0 01 cpy #1 ;1 = shift letters, xlate numbers
ca79: f0 20 beq TERMCAP
ca7b: b0 34 bcs TERMLOCK ;2 means caps lock mode
;
ca7d: c9 9b TERMNORM cmp #$9b ;ESC?
ca7f: d0 06 bne TERMLETTER
;
ca81: c8 TERMINC iny ;increment status
ca82: 98 TERMINC1 tya
ca83: 48 pha ;put back on stack
ca84: 4c 2b ca jmp TERMNEXT
ca87: c9 c1 TERMLETTER cmp #$c1 ;<A?
ca89: 90 08 bcc TERMSEND
ca8b: c9 db cmp #$db ;>Z?
ca8d: b0 04 bcs TERMSEND
ca8f: 09 20 ora #$20 ;it's a letter so translate to LC
ca91: 85 27 sta CHARACTER
;
ca93: 98 TERMSEND tya
ca94: 48 pha ;put state back on stack
ca95: 20 68 cb TERMSEND1 jsr OUTPUT1 ;go output
ca98: 4c 2b ca jmp TERMNEXT
ca9b: c9 9b TERMCAP cmp #$9b ;two escapes?
ca9d: f0 e2 beq TERMINC
ca9f: c9 b0 cmp #$b0 ;<0?
caa1: 90 0a bcc TERMCAP1
caa3: c9 bb cmp #$bb ;>colon?
caa5: b0 06 bcs TERMCAP1
;
; ESC <number> so translate into missing ASCII char.
;
caa7: a8 tay
caa8: b9 09 ca lda TRANSLATE-176,y
caab: 85 27 sta CHARACTER
caad: a0 00 TERMCAP1 ldy #0 ;back to state 0
caaf: f0 e2 beq TERMSEND ;<always>
cab1: c9 9b TERMLOCK cmp #$9b ;ESC?
cab3: d0 de bne TERMSEND
cab5: a0 00 ldy #0
cab7: f0 c9 beq TERMINC1 ;<always>
;
; Translate table.
;
cab9: 9b TRANSLATE .dd1 $9b ;ESC
caba: 9c .dd1 $9c ;FS
cabb: 9f .dd1 $9f ;US
cabc: db .dd1 $db ;left bracket
cabd: dc .dd1 $dc ;left slash
cabe: df .dd1 $df ;underscore
cabf: fb .dd1 $fb ;left enclose
cac0: fc .dd1 $fc ;vertical bar
cac1: fd .dd1 $fd ;right enclose
cac2: fe .dd1 $fe ;tilde
cac3: ff .dd1 $ff ;rub
;
; General purpose wait routine.
;
; WAITMS wait for [A-reg] milliseconds (256 if A-reg=0).
;
cac4: a2 ca WAITMS ldx #202
cac6: ca WAITMS1 dex ;<don't let this loop cross a page>
cac7: d0 fd bne WAITMS1 ;5 microsecond loop
cac9: 38 sec
caca: e9 01 sbc #$01
cacc: d0 f6 bne WAITMS
cace: ae f8 07 ldx MSLOT
cad1: 60 rts
;
; ACIA status register read routines.
;
cad2: a4 26 SRIN ldy SLOT16 ;SLOT16=$NO
cad4: b9 89 c0 lda STREG,y
cad7: 48 pha
cad8: 29 20 and #$20 ;DCD?
cada: 4a lsr A ;an error if not
cadb: 4a lsr A
cadc: 85 35 sta ZPTEMP
cade: 68 pla
cadf: 29 0f and #$0f
cae1: c9 08 cmp #$08 ;set carry if RDR full, else clear
cae3: 90 04 bcc SRIN1
cae5: 29 07 and #$07 ;PE, FE, OVR valid only when RDR=1
cae7: b0 02 bcs SRIN2 ;<always>
cae9: a5 35 SRIN1 lda ZPTEMP
caeb: 05 35 SRIN2 ora ZPTEMP ;get CDC error bit
caed: f0 05 beq SRIN3 ;branch if no errors found
caef: 09 20 ora #$20 ;else set bit 5 to offset for Pascal
caf1: 9d b8 05 sta STSBYTE,x ;and save in status temp
caf4: 60 SRIN3 rts ;CY=1 means data is available
;
; SROUT checks if TDR is empty + hardware handshake is OK.
;
caf5: a4 26 SROUT ldy SLOT16
caf7: b9 89 c0 lda STREG,y
cafa: 29 70 and #$70
cafc: c9 10 cmp #$10 ;equ if TDR empty, DCD, DSR, & CTS
cafe: 60 rts
;
; General input routine.
;
caff: 20 d2 ca INPUT jsr SRIN
cb02: 90 15 bcc NOINPUT1
;
cb04: b9 88 c0 lda RDREG,y ;get the ACIA input
cb07: 09 80 ora #$80 ;set hi bit for BASIC
cb09: c9 8a cmp #$8a ;linefeed?
cb0b: d0 09 bne INPUT2
;
cb0d: a8 tay
cb0e: bd 38 07 lda MISCFLG,x ;see if we should eat it
cb11: 29 20 and #$20
cb13: d0 03 bne NOINPUT ;if so, just keep it a secret
cb15: 98 tya
;
cb16: 38 INPUT2 sec ;indicate data
cb17: 60 rts
cb18: 18 NOINPUT clc ;carry clear for no input
cb19: 60 NOINPUT1 rts
;
; General output routine.
;
; Start of command check routine.
;
cb1a: a4 26 CMDSEQCK ldy SLOT16
cb1c: b9 81 c0 lda DIPSW1,y
cb1f: 4a lsr A
cb20: b0 36 bcs NOCMD ;don't worry about cmd seq for SIC
cb22: bd b8 04 lda STATEFLG,x
cb25: 29 07 and #$07 ;are we in a command sequence?
cb27: f0 05 beq ESCCHECK
cb29: 20 fc cd jsr CMDPROC ;if so, goto command central
cb2c: 38 sec ;indicate command
cb2d: 60 rts
cb2e: a5 27 ESCCHECK lda CHARACTER
cb30: 29 7f and #$7f ;ignore high bit
cb32: dd 38 05 cmp CMDBYTE,x ;is this beginning of a cmd seq?
cb35: d0 05 bne XOFFCK
cb37: fe b8 04 inc STATEFLG,x ;start up command modes
cb3a: 38 sec ;indicate command
cb3b: 60 rts
cb3c: bd 38 07 XOFFCK lda MISCFLG,x ;is XON enabled?
cb3f: 29 08 and #$08
cb41: f0 15 beq NOCMD ;skip this if not
;
cb43: 20 ff ca jsr INPUT ;any input?
cb46: 90 10 bcc NOCMD ;if not, go output
cb48: c9 93 cmp #$93 ;is it an XOFF?
cb4a: f0 0e beq XONWAIT ;if so, go wait for another input
cb4c: 48 pha
cb4d: bd 38 07 lda MISCFLG,x ;CIC mode?
cb50: 4a lsr A
cb51: 4a lsr A
cb52: 68 pla
cb53: 90 04 bcc ANRTS
cb55: 9d b8 06 sta BUFBYTE,x ;if so, we have a buffer
cb58: 18 NOCMD clc ;indicate not a cmd seq
cb59: 60 ANRTS rts
cb5a: 20 aa c8 XONWAIT jsr GETCHAR ;get ACIA/kbd data
cb5d: c9 91 cmp #$91 ;is it an XON?
cb5f: d0 f9 bne XONWAIT ;if not, wait
cb61: 18 clc ;otherwise, indicate not a cmd seq
cb62: 60 rts ; and return
;
; Now the output routine you've been waiting for.
;
cb63: 20 1a cb OUTPUT jsr CMDSEQCK
cb66: b0 f1 bcs ANRTS ;don't output command sequences
;
cb68: 20 9e cc OUTPUT1 jsr SCREENOUT
;
cb6b: a4 26 OUTPUT2 ldy SLOT16
cb6d: b9 81 c0 lda DIPSW1,y
cb70: 4a lsr A
cb71: 90 4e bcc OUTPUT3 ;skip ETX/ACK for native modes
cb73: 4a lsr A
cb74: 90 4b bcc OUTPUT3 ;branch if not P8A emulation
;
; P8A ETX/ACK stuff.
;
; After 148 characters but not within an escape sequence of up to 5 characters,
; the handshake is performed (will delay until 'not ESC' and then 4 more chars
; or until an 'ESC').
;
cb76: a5 27 P8AOUT1 lda CHARACTER ;save char on stack
cb78: 48 pha
cb79: bd 38 04 lda HANDSHKE,x ;char count for buffer full
cb7c: c9 67 cmp #103 ;if <103 then 153 chars in buffer
cb7e: 90 10 bcc ETX
cb80: c9 6c cmp #108 ;if >=108 then less than 149 chars
cb82: b0 22 bcs P8AOUT2 ; so no handshake is needed yet
cb84: c9 6b cmp #107 ;sets carry if 107 (149 sent)
cb86: 68 pla
cb87: 48 pha
cb88: 49 9b eor #$9b ;ESC?
cb8a: 29 7f and #$7f ;ignore hi-bit
cb8c: d0 18 bne P8AOUT2 ;count as 1 of 5 if not 'ESC'
cb8e: b0 19 bcs P8AOUT3 ;don't count if 149th char is 'ESC'
;
cb90: bd b8 04 ETX lda STATEFLG,x ;send query char to printer
cb93: 29 1f and #$1f ;(default is ETX)
cb95: 09 80 ora #$80
cb97: 85 27 sta CHARACTER
cb99: 20 02 cc jsr ACIAOUT
cb9c: 20 aa c8 ACK jsr GETCHAR ;get ACIA/kbd data
cb9f: 49 86 eor #$86 ;ACK?
cba1: d0 ed bne ETX ;if not ACK, repeat handshake
cba3: 9d 38 04 sta HANDSHKE,x ;init char count to 255
;
cba6: de 38 04 P8AOUT2 dec HANDSHKE,x
cba9: 68 P8AOUT3 pla ;get real char to output
cbaa: 85 27 sta CHARACTER
cbac: 49 8d eor #$8d ;if CR and CR delay mode
cbae: 0a asl A
cbaf: d0 0a bne P8AOUT4 ; then fake char count to less than
cbb1: bd b8 03 lda DELAYFLG,x ; 48 to force handshake on next
cbb4: 29 30 and #$30 ; character out
cbb6: f0 03 beq P8AOUT4
cbb8: 9d 38 04 sta HANDSHKE,x
;
cbbb: 20 02 cc P8AOUT4 jsr ACIAOUT
cbbe: 4c ea cb jmp LFGEN ;(skip delays)
;
; And back to normal output.
;
cbc1: 20 02 cc OUTPUT3 jsr ACIAOUT
;
; Now check for CR, LF, and FF delays.
;
cbc4: 0a asl A
cbc5: a8 tay
cbc6: bd b8 03 lda DELAYFLG,x ;get delay flags
cbc9: c0 18 cpy #$18 ;form feed?
cbcb: f0 0c beq OUTDLY1
cbcd: 4a lsr A
cbce: 4a lsr A ;right justify LF delay
cbcf: c0 14 cpy #$14 ;line feed?
cbd1: f0 06 beq OUTDLY1
cbd3: 4a lsr A
cbd4: 4a lsr A ;right justify CR delay
cbd5: c0 1a cpy #$1a ;carriage return?
cbd7: d0 25 bne OUTPUTEND
cbd9: 29 03 OUTDLY1 and #$03 ;just want lowest 2 bits
cbdb: f0 0d beq LFGEN ;no delay indicated
cbdd: a8 tay
cbde: b9 fe cb lda DLYTBL-1,y
cbe1: a8 tay ;delay in 32 msec increments
cbe2: a9 20 OUTDLYLP lda #32
cbe4: 20 c4 ca jsr WAITMS
cbe7: 88 dey
cbe8: d0 f8 bne OUTDLYLP
;
; Check on LF generation option.
;
cbea: a5 27 LFGEN lda CHARACTER
cbec: 0a asl A
cbed: c9 1a cmp #$1a ;carriage return?
cbef: d0 0d bne OUTPUTEND
cbf1: bd 38 07 lda MISCFLG,x ;is LF generate enabled?
cbf4: 6a ror A
cbf5: 90 07 bcc OUTPUTEND
cbf7: a9 8a lda #$8a
cbf9: 85 27 sta CHARACTER ;line feed
cbfb: 4c 6b cb jmp OUTPUT2 ;(don't echo it)
cbfe: 60 OUTPUTEND rts
cbff: 01 DLYTBL .dd1 $01 ;32 msec
cc00: 08 .dd1 $08 ;1/4 sec
cc01: 40 .dd1 $40 ; 2 sec
;
; ACIA output routine.
;
cc02: 20 f5 ca ACIAOUT jsr SROUT ;ready for output?
cc05: d0 fb bne ACIAOUT
cc07: 98 tya
cc08: 09 89 ora #$89 ;prepare to address ACIA,
cc0a: a8 tay ; causing 6502 false read to occur
cc0b: a5 27 lda CHARACTER ; on page $BF (avoiding RDR read)
cc0d: 99 ff bf sta $bfff,y ;here you are ACIA
cc10: 60 rts
;
; Restore cursor (not for Pascal)
; (A-reg should contain new char)
;
cc11: 48 RESTORE pha ;save new character
cc12: a4 24 ldy MON_CH
cc14: a5 27 lda CHARACTER ;old character
cc16: 91 28 sta (MON_BASL),y
cc18: 68 pla
;
cc19: c9 95 cmp #$95 ;screen pick?
cc1b: d0 0c bne RESTOREND
cc1d: a5 27 lda CHARACTER ;if so, use screen char
cc1f: c9 20 cmp #$20 ;inverse?
cc21: b0 06 bcs RESTOREND
cc23: 20 df cc jsr GETXLATE ;reverse the translation
cc26: 59 db cc eor REVMASK,y
cc29: 85 27 RESTOREND sta CHARACTER
cc2b: 60 rts
;
; Pascal-BASIC keyboard fetch.
;
cc2c: 18 CKKBD clc ;return carry clear for no data
cc2d: bd 38 07 lda MISCFLG,x
cc30: 29 04 and #$04 ;answer no if keyboard is disabled
cc32: f0 09 beq CKKBDXIT
;
cc34: ad 00 c0 CKKBD1 lda KBD
cc37: 10 04 bpl CKKBDXIT
cc39: 8d 10 c0 sta KBDSTRB
cc3c: 38 sec ;indicate data
cc3d: 60 CKKBDXIT rts
;
; Get a char from keyboard for BASIC only.
;
cc3e: e6 4e GETKBD inc MON_RNDL ;mix up random # seed
cc40: d0 02 bne GETKBD1 ; for BASIC
cc42: e6 4f inc MON_RNDH
cc44: 20 2c cc GETKBD1 jsr CKKBD ;keyboard fetch routine
cc47: b8 clv ;indicate no escape sequence
cc48: 90 f3 bcc CKKBDXIT ;exit if no key press
cc4a: 20 11 cc jsr RESTORE ;do BASIC cursed duty
cc4d: 29 7f and #$7f
cc4f: dd 38 05 cmp CMDBYTE,x ;is is the start of a command?
cc52: d0 3d bne GETKBDONE ;if not, exit indicating data
cc54: a4 26 ldy SLOT16
cc56: b9 81 c0 lda DIPSW1,y ;only do cmd esc for PPC, SIC modes
cc59: 4a lsr A
cc5a: b0 35 bcs GETKBDONE
;
; Keyboard escape handler.
;
cc5c: a0 0a KBDESC ldy #$0a ;first print a prompt
cc5e: b9 93 cc PROMPTLOOP lda PROMPTBL,y
cc61: 85 27 sta CHARACTER
cc63: 98 tya
cc64: 48 pha
cc65: 20 a3 cc jsr SCREENOUT1 ;always send to screen
cc68: 68 pla
cc69: a8 tay
cc6a: 88 dey
cc6b: 10 f1 bpl PROMPTLOOP
;
cc6d: a9 01 lda #1 ;start out in command state 1
cc6f: 20 7b ce jsr SETOSTATE
;
cc72: 20 34 cc GETCMD jsr CKKBD1 ;wait for keyboard character
cc75: 10 fb bpl GETCMD
cc77: c9 88 cmp #$88 ;backspace?
cc79: f0 e1 beq KBDESC ;if so, then start over
cc7b: 85 27 sta CHARACTER
;
cc7d: 20 a3 cc jsr SCREENOUT1
cc80: 20 1a cb jsr CMDSEQCK ;pump thru cmd interpreter
;
cc83: bd b8 04 lda STATEFLG,x ;are we done?
cc86: 29 07 and #$07
cc88: d0 e8 bne GETCMD ;if not, go again
;
cc8a: a9 8d lda #$8d ;force back a carriage return
cc8c: 85 27 sta CHARACTER
cc8e: 2c 58 ff bit MON_IORTS ;indicate that a cmd seq has occurred
cc91: 38 GETKBDONE sec ;indicate success
cc92: 60 rts
cc93: ba c3 d3 d3+ PROMPTBL .str “:CSS ELPPA”,$8d
;
; Routine to print a character on the current display.
;
cc9e: bd 38 07 SCREENOUT lda MISCFLG,x
cca1: 10 13 bpl NOOUT ;if screen disabled
;
cca3: bd 38 07 SCREENOUT1 lda MISCFLG,x ;entry after echo check
cca6: 29 02 and #$02 ;if it isn't CIC mode,
cca8: f0 0d beq ASCREEN ;always use the Apple screen
ccaa: bd b8 04 lda STATEFLG,x ;current screen = Apple screen?
ccad: 29 38 and #$38
ccaf: f0 06 beq ASCREEN ;slot 0= Apple screen
;
ccb1: 8a txa ;jump to CN00 space
ccb2: 48 pha
ccb3: a9 af lda #<SENDCD-1 ; to vector to the peripheral
ccb5: 48 pha ; in the chain slot
ccb6: 60 NOOUT rts
;
; Apple 40-col screen driver.
;
ccb7: 20 df cc ASCREEN jsr GETXLATE ;get the translate options
ccba: 09 80 ora #$80 ;set high bit of char
ccbc: c9 e0 cmp #$e0 ;lowercase?
ccbe: 90 06 bcc TESTLETTER
ccc0: 59 d3 cc eor LCMASK,y ;do lowercase trip
ccc3: 4c f6 fd TOSCREEN jmp MON_COUTZ ;all regs are preserved
;
; If uppercase, we only map letters.
;
ccc6: c9 c1 TESTLETTER cmp #$c1 ;<A?
ccc8: 90 f9 bcc TOSCREEN
ccca: c9 db cmp #$db ;>Z?
cccc: b0 f5 bcs TOSCREEN
ccce: 59 d7 cc eor UCMASK,y
ccd1: 90 f0 bcc TOSCREEN ;<always>
;
; Masks for case translation.
;
ccd3: 20 00 e0 20 LCMASK .bulk $20,$00,$e0,$20
ccd7: 00 00 00 c0 UCMASK .bulk $00,$00,$00,$c0
ccdb: 00 00 e0 c0 REVMASK .bulk $00,$00,$e0,$c0
ccdf: bd b8 03 GETXLATE lda DELAYFLG,x ;translate options in B6-B7
cce2: 2a rol A
cce3: 2a rol A
cce4: 2a rol A
cce5: 29 03 and #$03
cce7: a8 tay
cce8: a5 27 lda CHARACTER
ccea: 60 rts
;
; SSC command processor.
;
; Command table (used by command processer[sic] routine).
;
cceb: 42 CMDTBL .dd1 $42 ;B(reak)
ccec: 67 .dd1 $67 ;CIC PAS NS=7
cced: c0 .dd1 <BREAKCMD-1
ccee: 54 .dd1 $54 ;T(erminal)
ccef: 47 .dd1 $47 ;CIC NS=7
ccf0: a6 .dd1 <TERMCMD-1
ccf1: 43 .dd1 $43 ;C(R generate)
ccf2: 87 .dd1 $87 ; PPC NS=7
ccf3: a6 .dd1 <TERMCMD-1
ccf4: 51 .dd1 $51 ;Q(uit)
ccf5: 47 .dd1 $47 ;CIC NS=7
ccf6: b8 .dd1 <QUITCMD-1
ccf7: 52 .dd1 $52 ;R(eset)
ccf8: c7 .dd1 $c7 ;CIC PPC NS=7
ccf9: ac .dd1 <RESETCMD-1
ccfa: 5a .dd1 $5a ;Z command
ccfb: e7 .dd1 $e7 ;CIC PPC PAS NS=7
ccfc: f3 .dd1 <ZCMD-1
ccfd: 49 .dd1 $49 ;I command
ccfe: 90 .dd1 $90 ; PPC NS=0
ccff: d3 .dd1 <ICMD-1
cd00: 4b .dd1 $4b ;K command
cd01: 90 .dd1 $90 ; PPC NS=0
cd02: df .dd1 <KCMD-1
;
cd03: 45 .dd1 $45 ;E(cho)
cd04: 43 .dd1 $43 ;CIC NS=3
cd05: 80 .dd1 $80
cd06: 46 .dd1 $46 ;F(romkybd)
cd07: e3 .dd1 $e3 ;CIC PPC PAS NS=3
cd08: 04 .dd1 $04
cd09: 4c .dd1 $4c ;L(F generate)
cd0a: e3 .dd1 $e3 ;CIC PPC PAS NS=3
cd0b: 01 .dd1 $01
cd0c: 58 .dd1 $58 ;X(off)
cd0d: e3 .dd1 $e3 ;CIC PPC PAS NS=3
cd0e: 08 .dd1 $08
cd0f: 54 .dd1 $54 ;T(abbing)
cd10: 83 .dd1 $83 ; PPC NS=3
cd11: 40 .dd1 $40
cd12: 53 .dd1 $53 ;S(hifting)
cd13: 43 .dd1 $43 ;CIC NS=3
cd14: 40 .dd1 $40
cd15: 4d .dd1 $4d ;M(unch LF)
cd16: e3 .dd1 $e3 ;CIC PPC PAS NS=3
cd17: 20 .dd1 $20
;
cd18: 00 .dd1 $00 ;end of first part marker
;
cd19: 42 CMDTBL1 .dd1 $42 ;B(aud)
cd1a: f6 .dd1 $f6 ;CIC PPC PAS NS=6
cd1b: 7c .dd1 <BAUDCMD-1
cd1c: 50 .dd1 $50 ;P(arity)
cd1d: f6 .dd1 $f6 ;CIC PPC PAS NS=6
cd1e: 9a .dd1 <PARITYCMD-1
cd1f: 44 .dd1 $44 ;D(ata)
cd20: f6 .dd1 $f6 ;CIC PPC PAS NS=6
cd21: 9b .dd1 <DATACMD-1
cd22: 46 .dd1 $46 ;F(f delay)
cd23: f6 .dd1 $f6 ;CIC PPC PAS NS=6
cd24: 46 .dd1 <FFCMD-1
cd25: 4c .dd1 $4c ;L(F delay)
cd26: f6 .dd1 $f6 ;CIC PPC PAS NS=6
cd27: 40 .dd1 <LFCMD-1
cd28: 43 .dd1 $43 ;C(R delay)
cd29: f6 .dd1 $f6 ;CIC PPC PAS NS=6
cd2a: 3a .dd1 <CRCMD-1
cd2b: 54 .dd1 $54 ;T(ranslate)
cd2c: d6 .dd1 $d6 ;CIC PPC NS=6
cd2d: 34 .dd1 <TRANCMD-1
cd2e: 4e .dd1 $4e ;N command
cd2f: 90 .dd1 $90 ; PPC NS=0
cd30: e8 .dd1 <NCMD-1
cd31: 53 .dd1 $53 ;S(creenslot)
cd32: 56 .dd1 $56 ;CIC NS=6
cd33: 60 .dd1 <SSLOTCMD-1
;
cd34: 00 .dd1 $00 ;end of table marker
;
; Command routines (called by parser). (Must start in page $CD . . .)
;
cd35: a9 3f TRANCMD lda #$3f ;set screen translate options
cd37: a0 07 ldy #$07
cd39: d0 10 bne DELAYSET ;<always>
cd3b: a9 cf CRCMD lda #$cf ;set CR delay
cd3d: a0 05 ldy #$05
cd3f: d0 0a bne DELAYSET ;<always>
cd41: a9 f3 LFCMD lda #$f3 ;set LF delay
cd43: a0 03 ldy #$03
cd45: d0 04 bne DELAYSET ;<always>
cd47: a9 fc FFCMD lda #$fc ;set FF delay
cd49: a0 01 ldy #$01
cd4b: 3d b8 03 DELAYSET and DELAYFLG,x ;don't disturb the other flags
cd4e: 85 2a sta ZPTMP1
cd50: bd 38 04 lda PARAMETER,x
cd53: 29 03 and #$03 ;just use two bits
cd55: 18 clc
cd56: 6a ror A ;once for fun
cd57: 2a ROTATE rol A ;change directions
cd58: 88 dey
cd59: d0 fc bne ROTATE ;prepare it to OR into the flags
;
cd5b: 05 2a ora ZPTMP1
cd5d: 9d b8 03 sta DELAYFLG,x
cd60: 60 rts
cd61: 29 07 SSLOTCMD and #$07 ;set slot command
cd63: 0a asl A
cd64: 0a asl A
cd65: 0a asl A
cd66: 85 2a sta ZPTMP1
cd68: 0a asl A
cd69: c5 26 cmp SLOT16 ;make sure we don't set it
cd6b: f0 0f beq SSLOTCMD1 ; to our own slot
cd6d: bd b8 04 lda STATEFLG,x
cd70: 29 c7 and #$c7 ;put new slot number in bits 3-5
cd72: 05 2a ora ZPTMP1 ; of CMDBYTE,X
cd74: 9d b8 04 sta STATEFLG,x
cd77: a9 00 lda #0 ;store zero into
cd79: 9d 38 06 sta CHNBYTE,x ;slot offset (set to CN00 entry)
cd7c: 60 SSLOTCMD1 rts
cd7d: 29 0f BAUDCMD and #$0f ;set new baud rate
cd7f: d0 07 bne BAUDCMD2
cd81: b9 81 c0 BAUDCMD1 lda DIPSW1,y ;zero parm = reload from switches
cd84: 4a lsr A
cd85: 4a lsr A
cd86: 4a lsr A
cd87: 4a lsr A
cd88: 09 10 BAUDCMD2 ora #$10 ;set int. baud rate generator
cd8a: 85 2a sta ZPTMP1
cd8c: a9 e0 lda #$e0
cd8e: 85 2b CTLREGSET sta ZPTMP2
cd90: b9 8b c0 lda CTLREG,y
cd93: 25 2b and ZPTMP2
cd95: 05 2a ora ZPTMP1
cd97: 99 8b c0 sta CTLREG,y
cd9a: 60 rts
cd9b: 88 PARITYCMD dey ;trick: so CTLREG,Y actually addresses the command reg
;
cd9c: 0a DATACMD asl A ;set new # of data bits
cd9d: 0a asl A
cd9e: 0a asl A
cd9f: 0a asl A
cda0: 0a asl A
cda1: 85 2a DATACMD1 sta ZPTMP1
cda3: a9 1f lda #$1f
cda5: d0 e7 bne CTLREGSET ;<always>
cda7: 1e b8 04 TERMCMD asl STATEFLG,x ;set terminal mode
cdaa: 38 sec
cdab: b0 10 bcs QCMD1 ;<always>
cdad: 99 89 c0 RESETCMD sta RESET,y ;drop RTS, DTR
cdb0: 20 93 fe jsr MON_SETVID ;PR#0
cdb3: 20 89 fe jsr MON_SETKBD ;IN#0
cdb6: ae f8 07 ldx MSLOT
cdb9: 1e b8 04 QUITCMD asl STATEFLG,x ;clear terminal mode
cdbc: 18 clc
cdbd: 7e b8 04 QCMD1 ror STATEFLG,x
cdc0: 60 rts
cdc1: b9 8a c0 BREAKCMD lda CMDREG,y ;send break signal
cdc4: 48 pha ; for 233 milliseconds
cdc5: 09 0c ora #$0c
cdc7: 99 8a c0 sta CMDREG,y
cdca: a9 e9 lda #233 ;delay for 233 microsec.[sic]
cdcc: 20 c4 ca jsr WAITMS
cdcf: 68 pla ;restore old command reg contents
cdd0: 99 8a c0 sta CMDREG,y
cdd3: 60 rts
cdd4: a9 28 ICMD lda #$28
cdd6: 9d 38 06 sta PWDBYTE,x ;set printer width to 40
cdd9: a9 80 lda #$80
cddb: 1d 38 07 ora MISCFLG,x ;set screen echo
cdde: d0 05 bne KCMD2 ;<always>
;
cde0: a9 fe KCMD lda #$fe ;reset the LF generate flag
cde2: 3d 38 07 KCMD1 and MISCFLG,x
cde5: 9d 38 07 KCMD2 sta MISCFLG,x
cde8: 60 rts
cde9: c9 28 NCMD cmp #40 ;>=40?
cdeb: 90 0e bcc ZCMDRTS ;if not, just exit
cded: 9d 38 06 sta PWDBYTE,x ;set new printer width
cdf0: a9 3f lda #$3f ;disable screen, set listing mode
cdf2: d0 ee bne KCMD1 ;<always>
cdf4: 1e 38 05 ZCMD asl CMDBYTE,x ;disable command recognition
cdf7: 38 sec
cdf8: 7e 38 05 ror CMDBYTE,x
cdfb: 60 ZCMDRTS rts
;
; Vector according to command state.
;
cdfc: a8 CMDPROC tay ;A-reg=command state
cdfd: a5 27 lda CHARACTER
cdff: 29 7f and #$7f
;
ce01: c9 20 cmp #$20 ;skip spaces for all modes
ce03: d0 09 bne CMDPROC2
ce05: c0 03 cpy #$03 ;except mode 3
ce07: f0 01 beq CMDPROC1
ce09: 60 rts
ce0a: a9 04 CMDPROC1 lda #$04
ce0c: d0 6d bne SETOSTATE ;<always>
ce0e: c9 0d CMDPROC2 cmp #$0d ;carriage return?
ce10: d0 12 bne CMDPROC4
ce12: 20 79 ce jsr ZEROSTATE ;abort for states 0-5, exit for 6,7
ce15: c0 07 cpy #$07 ;in state 7 we vector to the proc
ce17: f0 01 beq CMDPROC3
ce19: 60 rts ;otherwise, just exit
ce1a: a9 cd CMDPROC3 lda #$cd ;all procs must start in page $CD
ce1c: 48 pha
ce1d: bd 38 04 lda PARAMETER,x
ce20: 48 pha
ce21: a4 26 ldy SLOT16 ;needed by break cmd
ce23: 60 rts
ce24: 85 35 CMDPROC4 sta ZPTEMP
ce26: a9 ce lda #$ce ;all routines must start
ce28: 48 pha ; in page $CE
ce29: b9 30 ce lda STATETBL,y
ce2c: 48 pha
ce2d: a5 35 lda ZPTEMP
ce2f: 60 rts ;RTS to command procedure
;
; Now the state routines.
;
; State branch table.
;
ce30: a7 STATETBL .dd1 <STATERR-1 ;bad state
ce31: 37 .dd1 <CSTATE1-1 ;<cmd< seen
ce32: 61 .dd1 <CSTATE2-1 ;accumulate parameter
ce33: 89 .dd1 <CDONE-1 ;skip until space
ce34: 8a .dd1 <CSTATE4-1 ;E/D something
ce35: a7 .dd1 <STATERR-1 ;illegal state
ce36: 89 .dd1 <CDONE-1 ;skip until CR
ce37: 89 .dd1 <CDONE-1 ;skip until CR then do cmd
;
; Command state 1.
;
ce38: dd 38 05 CSTATE1 cmp CMDBYTE,x ;is it <cmd>?
ce3b: d0 06 bne CSTATE1A
ce3d: de b8 04 dec STATEFLG,x ;set state back to zero
ce40: 4c 02 cc jmp ACIAOUT ;output <cmd> if so
ce43: c9 30 CSTATE1A cmp #$30 ;>=0?
ce45: 90 0d bcc CSTATE1B
ce47: c9 3a cmp #$3a ;<=9?
ce49: b0 09 bcs CSTATE1B
ce4b: 29 0f and #$0f ;it's a number
ce4d: 9d 38 04 sta PARAMETER,x
ce50: a9 02 lda #2
ce52: d0 27 bne SETOSTATE ;<always> set mode 2 and return
ce54: c9 20 CSTATE1B cmp #$20 ;is it a control char?
ce56: b0 06 bcs CSTATE1C
ce58: 9d 38 05 sta CMDBYTE,x ;set new command character
ce5b: 4c 79 ce jmp ZEROSTATE ;reset state to zero
ce5e: a0 00 CSTATE1C ldy #$00 ;use command table
ce60: f0 4d beq CMDSEARCH ;<always>
;
; Command state 2: accumulate parameter.
;
ce62: 49 30 CSTATE2 eor #$30 ;convert $30-$39 to 0-9
ce64: c9 0a cmp #$0a ;0-9?
ce66: b0 0d bcs CSTATE2A
ce68: a0 0a ldy #$0a ;it's a number, so add
ce6a: 7d 38 04 ACCLOOP adc PARAMETER,x ; it to 10*parameter
ce6d: 88 dey
ce6e: d0 fa bne ACCLOOP
ce70: 9d 38 04 sta PARAMETER,x
ce73: f0 15 beq CDONE ;<always>
ce75: a0 2e CSTATE2A ldy #$2e ;use command table [LDY #CMDTBL1-CMDTBL]
ce77: d0 36 bne CMDSEARCH ;<always>
;
; Set command state.
;
ce79: a9 00 ZEROSTATE lda #0
ce7b: 85 2a SETOSTATE sta ZPTMP1
ce7d: ae f8 07 ldx MSLOT
ce80: bd b8 04 lda STATEFLG,x
ce83: 29 f8 and #$f8
ce85: 05 2a ora ZPTMP1
ce87: 9d b8 04 sta STATEFLG,x
ce8a: 60 CDONE rts
;
; Command state 4 (E/D).
;
ce8b: a8 CSTATE4 tay ;E/D -> Y-reg
ce8c: bd 38 04 lda PARAMETER,x
ce8f: c0 44 cpy #$44 ;D(isable)?
ce91: f0 09 beq CSTATE4A
ce93: c0 45 cpy #$45 ;E(nable)?
ce95: d0 11 bne STATERR ;if not, ignore this command
ce97: 1d 38 07 ora MISCFLG,x ;set flag
ce9a: d0 05 bne CSTATE4B ;<always>
ce9c: 49 ff CSTATE4A eor #$ff ;invert for disable
ce9e: 3d 38 07 and MISCFLG,x ;reset flag
cea1: 9d 38 07 CSTATE4B sta MISCFLG,x
;
; Escape to state 6.
;
cea4: a9 06 SETSTATE6 lda #6
cea6: d0 d3 bne SETOSTATE ;<always>
cea8: a9 20 STATERR lda #32 ;code for bad command
ceaa: 9d b8 05 sta STSBYTE,x
cead: d0 f5 bne SETSTATE6 ;<always>
;
; Table driven command processor.
;
ceaf: b9 eb cc CMDSEARCH lda CMDTBL,y ;get candidate character
ceb2: f0 f4 beq STATERR ;a zero marks the end of a subtable
ceb4: c5 35 cmp ZPTEMP ;match?
ceb6: f0 05 beq CMDMATCH
ceb8: c8 iny
ceb9: c8 CMDSEARCH1 iny ;reentry for wrong modes
ceba: c8 iny ;entry length = 3
cebb: d0 f2 bne CMDSEARCH ;<always>
cebd: c8 CMDMATCH iny
cebe: b9 eb cc lda CMDTBL,y
cec1: 85 2a sta ZPTMP1
cec3: 29 20 and #$20 ;check Pascal enable
cec5: d0 07 bne CMDMATCH1 ;it's on so don't check P-bit
cec7: bd 38 07 lda MISCFLG,x ;off so make sure
ceca: 29 10 and #$10 ; that we aren't in Pascal
cecc: d0 eb bne CMDSEARCH1 ;branch if we are
;
cece: bd 38 07 CMDMATCH1 lda MISCFLG,x ;get CIC/PPC bit
ced1: 4a lsr A ;shift CIC/PPC mode bit to carry
ced2: 4a lsr A
ced3: 24 2a bit ZPTMP1 ;PPC->N CIC->V
ced5: b0 04 bcs CMDMATCH2 ;branch if CIC mode
ced7: 10 e0 bpl CMDSEARCH1 ;not OK for PPC
ced9: 30 02 bmi CMDEXEC ;and OK
cedb: 50 dc CMDMATCH2 bvc CMDSEARCH1 ;not OK for CIC
;
cedd: a5 2a CMDEXEC lda ZPTMP1 ;retrieve table mode byte
cedf: 48 pha
cee0: 29 07 and #$07
cee2: 20 7b ce jsr SETOSTATE ;set next state
cee5: c8 iny
cee6: 68 pla
cee7: 29 10 and #$10
cee9: d0 07 bne CMDEXEC1 ;if bit 4 is set, vector to routine
ceeb: b9 eb cc lda CMDTBL,y
ceee: 9d 38 04 sta PARAMETER,x
cef1: 60 rts
cef2: a9 cd CMDEXEC1 lda #$cd ;routines must be in page $CD
cef4: 48 pha
cef5: b9 eb cc lda CMDTBL,y
cef8: 48 pha
cef9: a4 26 ldy SLOT16
cefb: bd 38 04 lda PARAMETER,x ;lot of routines need this
cefe: 60 rts
ceff: c2 .dd1 $c2 ;[DFB $00 in original; checksum byte?]
.org $c200
********************************************************************************
* *
* CN00 space code *
* *
* [Serial cards are installed in slot 2 by convention, so this is disassembled *
* at $C200. The original listing showed this at $C700.] *
* *
********************************************************************************
c200: 2c 58 ff BINIT bit MON_IORTS ;set the V-flag
c203: 70 0c bvs BENTRY ;<always>
c205: 38 IENTRY sec ;BASIC input entry
c206: 90 bcc ▼ LC21E+2 ;opcode for BCC
c207: 18 OENTRY clc ;BASIC output entry
c208: b8 clv
c209: 50 06 bvc BENTRY ;<always> skip around Pascal 1.1 entry
c20b: 01 .dd1 $01 ;generic signature byte
c20c: 31 .dd1 $31 ;device signature byte
c20d: 8e .dd1 <PINIT
c20e: 94 .dd1 <PREAD
c20f: 97 .dd1 <PWRITE
c210: 9a .dd1 <PSTATUS
c211: 85 27 BENTRY sta CHARACTER
c213: 86 35 stx ZPTEMP ;input buffer index
c215: 8a txa ;save X and Y regs on stack
c216: 48 pha
c217: 98 tya
c218: 48 pha
c219: 08 php ;save entry flags
c21a: 78 sei ;no rupts during slot determination
c21b: 8d ff cf sta CLRROM ;switch out other $C800 ROMs
c21e: 20 58 ff LC21E jsr MON_IORTS
c221: ba tsx
c222: bd 00 01 lda STACK,x ;recover $CN
c225: 8d f8 07 sta MSLOT
c228: aa tax ;X-reg will generally be $CN
c229: 0a asl A
c22a: 0a asl A ;determine $NO
c22b: 0a asl A
c22c: 0a asl A
c22d: 85 26 sta SLOT16
c22f: a8 tay ;Y-reg will generally be $NO
c230: 28 plp ;restore rupts
c231: 50 29 bvc NORMIO
;
; BASIC initialization.
;
c233: 1e 38 05 asl CMDBYTE,x ;always enable commands
c236: 5e 38 05 lsr CMDBYTE,x
c239: b9 8a c0 lda CMDREG,y ;just had a power-on or program reset?
c23c: 29 1f and #$1f
c23e: d0 05 bne BINIT1
c240: a9 ef lda #$ef ;if so, go join init in progress
c242: 20 05 c8 jsr INIT1
;
c245: e4 37 BINIT1 cpx MON_CSWH
c247: d0 0b bne FROMIN
c249: a9 07 lda #<OENTRY
c24b: c5 36 cmp MON_CSWL ;if CSW is already pointing to OENTRY,
c24d: f0 05 beq FROMIN ; then we must have come from KSW
c24f: 85 36 sta MON_CSWL ;otherwise, set CSW to OENTRY
c251: 18 FROMOUT clc ;indicate we are called for output
c252: 90 08 bcc NORMIO ;<always>
c254: e4 39 FROMIN cpx MON_KSWH ;make sure KSW points here
c256: d0 f9 bne FROMOUT
c258: a9 05 lda #$05
c25a: 85 38 sta MON_KSWL ;set up KSW (note carry set from CPX)
;
; Branch to appropriate BASIC I/O routine.
;
c25c: bd 38 07 NORMIO lda MISCFLG,x ;separate CIC mode from others
c25f: 29 02 and #$02 ;not zero for CIC mode
c261: 08 php ;save CIC mode indication
c262: 90 03 bcc BOUTPUT
c264: 4c bf c8 jmp BINPUT
c267: bd b8 04 BOUTPUT lda STATEFLG,x ;check for after lowercase input
c26a: 48 pha
c26b: 0a asl A
c26c: 10 0e bpl BOUTPUT1 ;skip if not
c26e: a6 35 ldx ZPTEMP
c270: a5 27 lda CHARACTER
c272: 09 20 ora #$20
c274: 9d 00 02 sta INBUFF,x ;restore lowercase in buffer
c277: 85 27 sta CHARACTER ;and for output echo
c279: ae f8 07 ldx MSLOT
c27c: 68 BOUTPUT1 pla
c27d: 29 bf and #$bf ;zero the flag
c27f: 9d b8 04 sta STATEFLG,x
c282: 28 plp ;retrieve CIC mode indication
c283: f0 06 beq BOUTPUT2 ;branch for PPC, SIC modes
c285: 20 63 cb jsr OUTPUT ;CIC mode output
c288: 4c b5 c8 jmp CICEXIT ;finish by checking for term mode
c28b: 4c fc c8 BOUTPUT2 jmp SEROUT
********************************************************************************
* *
* New Pascal interface entries. *
* *
********************************************************************************
c28e: 20 00 c8 PINIT jsr PASCALINIT
c291: a2 00 ldx #0 ;no error possible
c293: 60 rts
c294: 4c 9b c8 PREAD jmp PASCALREAD
c297: 4c aa c9 PWRITE jmp PASCALWRITE
;
; New Pascal status request.
;
; A-reg=0 -> ready for output?
; A-reg=1 -> has input been received?
;
c29a: 4a PSTATUS lsr A ;save request type in carry
c29b: 20 9b c9 jsr PENTRY ;(preserves carry)
c29e: b0 08 bcs PSTATIN
c2a0: 20 f5 ca jsr SROUT ;ready for output?
c2a3: f0 06 beq PSTATUS2
c2a5: 18 clc
c2a6: 90 03 bcc PSTATUS2 ;carry clear for not ready
c2a8: 20 d2 ca PSTATIN jsr SRIN ;sets carry correctly
c2ab: bd b8 05 PSTATUS2 lda STSBYTE,x ;get error flags
c2ae: aa tax
c2af: 60 rts
;
; Routine to send a character to another card.
;
c2b0: a2 03 SENDCD ldx #3
c2b2: b5 36 SAVEHOOK lda MON_CSWL,x
c2b4: 48 pha
c2b5: ca dex
c2b6: 10 fa bpl SAVEHOOK
;
; Now put card address in hook.
;
c2b8: ae f8 07 ldx MSLOT
c2bb: bd 38 06 lda PWDBYTE,x
c2be: 85 36 sta MON_CSWL
c2c0: bd b8 04 lda STATEFLG,x ;get slot #
c2c3: 29 38 and #$38
c2c5: 4a lsr A
c2c6: 4a lsr A
c2c7: 4a lsr A
c2c8: 09 c0 ora #$c0 ;form $CN
c2ca: 85 37 sta MON_CSWH
;
; Output to the peripheral.
;
c2cc: 8a txa ;save $CN
c2cd: 48 pha
c2ce: a5 27 lda CHARACTER
c2d0: 48 pha
c2d1: 09 80 ora #$80 ;80 col boards want hi-bit on
c2d3: 20 ed fd jsr MON_COUT
;
; Now restore everything the other card may have clobbered.
;
c2d6: 68 pla
c2d7: 85 27 sta CHARACTER
c2d9: 68 pla
c2da: 8d f8 07 sta MSLOT
c2dd: aa tax
c2de: 0a asl A
c2df: 0a asl A
c2e0: 0a asl A
c2e1: 0a asl A
c2e2: 85 26 sta SLOT16
c2e4: 8d ff cf sta CLRROM
;
; Put back CSWL into CHNBYTE.
;
c2e7: a5 36 lda MON_CSWL
c2e9: 9d 38 06 sta PWDBYTE,x
;
c2ec: a2 00 ldx #0
c2ee: 68 RESTORHOOK pla
c2ef: 95 36 sta MON_CSWL,x
c2f1: e8 inx
c2f2: e0 04 cpx #4
c2f4: 90 f8 bcc RESTORHOOK
c2f6: ae f8 07 ldx MSLOT
c2f9: 60 rts
;
c2fa: c1 d0 d0 cc+ .str “APPLE”
c2ff: 08 .dd1 $08