; **********************************************
; ** **
; ** OPERATING SYSTEM ROM PART 2: E400-FFFF **
; ** **
; **********************************************
.org $E400
.segment "E400FFFF"
.include "atari.inc"
.include "gtia.inc"
.include "antic.inc"
.include "pokey.inc"
.include "pia.inc"
.import C02C,C2AA,C018,C000,C0CE
.import CHARSET1,CHARSET2
.import C7E4,CB56,CA29,C90C
.import C745,C9AA,C9A5,C9A0
.import C99B,C996,C991
.import SLFTST,COLDS,WARMS,INTIN,VBLKD
.import VBLKI,SETVBL,SIO,DISKIN,DISKI
.export EDITRV,SCRENV ,KEYBDV,PRINTV,CASETV
.export DISKIV,DISKINV,CIOV ,SIOV ,SETVBV,SYSVBV,XITVBV
.export SIOINV,SENDEV ,INTINV,CIOINV,SELFSV,WARMSV,COLDSV
.export RBLOKV,CSOPIV ,PUPDIV,SLFTSV,PENTV ,PHUNLV,PHINIV
.export GPDVV
.export KIR
.export VFR,VSR
.export E40C,E41C,E42C,E43C,E44C
.export E49B,E510,E55C,E716,E7DE,E89E,E971
.export ISRODN,ISRTD,ISRSIR
.export PHR
.export SELFS
; E000-E3FF 1024 character set 1
; E400-E44F 80 device handlers:
; -> E400 editor E:
; -> E410 screen S:
; -> E420 keyboard K:
; -> E430 printer P:
; -> E440 cassette C:
; E450-E48E 63 jump vectors (21)
; E48F-E49E 16 device handler for parallel bus
; E49F-E4C0 34 unused (zero, followed by RTS)
; E4C1-E738 632 CIO code
; E739-E95B 547 peripheral handler code
; E95C-EE1C 1217 SIO code
; EE1D-EEBB 159 tables (presumably for screen handler)
; EEBC-EF6D 176 peripheral handler code (special CIO case)
; EF6C-FCDA 3439 screen/editor/keyboard handler
; FCDB-FE98 446 cassette handler
; FE99-FF72 218 printer handler
; FF73-FFEA 120 rom checksum routine
; FFEB-FFED 3 unused (zero) bytes
; FFEE-FFF9 12 ROM identification bytes
; FFFA-FFFF 6 6502 exception handler vectors
; ***********************
; ** **
; ** DEVICE HANDLERS **
; ** **
; ***********************
; Device Handler "E:"
EDITRV: .word EF94-1 ; Open E:
.word F22E-1 ; Close E:
.word F24A-1 ; Get E:
.word F2B0-1 ; Put E:
.word F21E-1 ; Status E:
.word F22D-1 ; Special E: [RTS]
E40C: jmp SIN ; Init E:
.byte 0
; Device Handler "S:"
SCRENV: .word EF8E-1 ; Open S:
.word F22E-1 ; Close S:
.word F180-1 ; Get S:
.word F1A4-1 ; Put S:
.word F21E-1 ; Status S:
.word F9AF-1 ; Special S:
E41C: jmp SIN ; Init S:
.byte 0
; Device Handler "K:"
KEYBDV: .word F21E-1 ; Open K:
.word F21E-1 ; Close K:
E424: .word F2FD-1 ; Get K:
.word F22D-1 ; Put K: [RTS]
.word F21E-1 ; Get K:
.word F22D-1 ; Special K: [RTS]
E42C: jmp SIN ; Init K:
.byte 0
; Device Handler "P:"
PRINTV: .word FEC2-1 ; Open P:
.word FF07-1 ; Close P:
.word FEC1-1 ; Get P: [RTS]
.word FECB-1 ; Put P:
.word FEA3-1 ; Status P:
.word FEC1-1 ; Special P: [RTS]
E43C: jmp PIN ; Init P:
.byte 0
; Device Handler "C:"
CASETV: .word FCE6-1 ; Open C:
.word FDCF-1 ; Close C:
.word FD7A-1 ; Get C:
.word FDB4-1 ; Put C:
.word FDCC-1 ; Status C:
.word FCE5-1 ; Special C: [RTS]
E44C: jmp CIN ; Init C: !!! Patched by XL-IT! !!!
.byte 0
; ********************
; ** **
; ** Jump Vectors **
; ** **
; ********************
DISKIV: jmp DISKI
DISKINV: jmp DISKIN
CIOV: jmp CIO ; Central I/O
SIOV: jmp SIO ; Serial I/O
SETVBV: jmp SETVBL
SYSVBV: jmp VBLKI
XITVBV: jmp VBLKD
SIOINV: jmp SIOINT
SENDEV: jmp SENDEN
INTINV: jmp INTIN
CIOINV: jmp ICIO
SELFSV: jmp SELFS
WARMSV: jmp WARMS
COLDSV: jmp COLDS
RBLOKV: jmp RBLOK
CSOPIV: jmp CSOPI
PUPDIV: jmp SELFS
SLFTSV: jmp SLFTST
PENTV: jmp PHE
PHUNLV: jmp PHUNL
PHINIV: jmp PHINI
; Device Handler Parallel Bus
GPDVV: .word C991-1
.word C996-1
.word C99B-1
.word C9A0-1
.word C9A5-1
.word C9AA-1
E49B: jmp C90C
.byte 0
; Weird stuff
.byte 0,0,0,0,0,0,0,0,0,0,0 ; 33 bytes wasted
.byte 0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0
rts ; 1 byte wasted
; ************************
; ** **
; ** INIT CENTRAL I/O **
; ** **
; ************************
; CIO initialization (called by monitor at power up)
ICIO: ldx #0
@1: lda #$FF ; set all IOCB's to free
sta ICHID,X ; by setting handler ID's=$FF
lda #<(IIN-1)
sta ICPTL,X ; point PUT to error routine
lda #>(IIN-1)
sta ICPTH,X
txa
clc
adc #$10 ; bump index by size
tax
cmp #$80 ; done?
bcc @1 ; no
rts ; yes, return
; error routine for illegal PUT
IIN: ldy #133 ; IOCB not open
rts
; *******************************
; ** **
; ** CENTRAL I/O (602 bytes) **
; ** **
; *******************************
; CIO interfaces between user and input/output device
CIO: sta ICAX6Z ; save possible output character
stx ICAX5Z ; save IOCB number * N
; check for legal IOCB
txa
and #%00001111 ; is IOCB multiple of 16?
bne @1 ; no, error
cpx #$80 ; is index too large?
bcc @2 ; no
; invalid IOCB number -- return error
@1: ldy #134 ; error code
jmp E670 ; return
; move user IOCB to zero page
@2: ldy #0
@3: lda IOCB,X ; user IOCB
sta ZIOCB,Y ; to zero page
inx
iny
cpy #12 ; 12 bytes
bcc @3
; new stuff...
lda ICHIDZ
cmp #$7F
bne L6
lda ICCOMZ ; Handler Index Number == $7F
cmp #12
beq CICLOS ; Close command?
lda HNDLOD
bne L5 ; Should we do a peripheral command?
E510: ldy #130 ; ERROR: Nonexistent Device
L4: jmp E670
L5: jsr CA29 ; Do peripheral command
bmi L4
; Compute CIO internal vector for command
L6: ldy #132 ; assume invalid code
lda ICCOMZ ; command code to index
cmp #3 ; is command legal?
bcc E670_2 ; no
tay
; move command to zero base for index
cpy #14 ; is command special?
bcc @7 ; no
ldy #14 ; yes, set special offset index
@7: sty ICCOMT ; save command for vector
lda COMTAB-3,Y ; get vector offset from table
beq CIOPEN ; go if OPEN command
cmp #2 ; is it CLOSE?
beq CICLOS ; yes
cmp #8 ; is it STATUS or SPECIAL?
bcs CISTSP ; yes
cmp #4 ; is it READ?
beq CIREAD ; yes
jmp CIWRIT ; else, must be WRITE
; OPEN command
; find device handler in handler address table
CIOPEN: lda ICHIDZ ; get handler ID
cmp #$FF ; is this IOCB closed?
beq W1 ; yes
; error -- IOCB already open
ldy #129 ; error code
E670_2: jmp E670 ; return
; new stuff...
W1: lda HNDLOD
bne W2
; go find device
jsr DEVSRC ; call device search
bcs W2 ; go if device not found
; device found, initialize IOCB for open
lda #0 ; reserve 0 bytes
sta DVSTAT
sta DVSTAT+1
; compute handler entry point
E55C: jsr COMENT
bcs E670_2 ; go if error in compute
; go to handler for initialization
jsr GOHAND ; use indirect jump
; store PUT BYTE address-1 into IOCB
lda #11 ; simulate put character
sta ICCOMT
jsr COMENT ; compute entry point
lda ICAX3Z ; move computed value
sta ICPTLZ ; to PUT BYTE address
lda ICAX4Z
sta ICPTHZ
jmp E672 ; return to user
; new stuff...
W2: jsr EEF9
jmp E670
; CLOSE command
CICLOS: ldy #1 ; assume good CLOSE
sty ICSTAZ
jsr COMENT ; compute handler entry point
bcs @1 ; go if error in compute
jsr GOHAND ; go to handler to close device
@1: lda #$FF ; get IOCB "free" value
sta ICHIDZ ; set handler ID
lda #>(IIN-1)
sta ICPTHZ ; set PUT BYTE to point to error
lda #<(IIN-1)
sta ICPTLZ
jmp E672 ; return
; STATUS and SPECIAL requests
; do implied open if necessary and go to device
CISTSP: lda ICHIDZ ; is there a handler ID?
cmp #$FF
bne @1 ; yes
; IOCB is free, do implied open
jsr DEVSRC ; find device in table
bcs E670_2 ; go if error in compute
; compute and go to entry point in handler
@1: jsr COMENT ; compute handler entry vector
jsr GOHAND ; go to handler
; restore handler index (do implied close)
ldx ICAX5Z ; IOCB index
lda ICHID,X ; get original handler ID
sta ICHIDZ ; restore zero page
jmp E672 ; return
; read -- do GET commands
CIREAD: lda ICCOMZ ; get command byte
and ICAX1Z ; is this read legal?
bne rlegal ; yes
; illegal read -- IOCB opened for write only
ldy #131 ; error code
E670_3: jmp E670 ; return
; compute and check entry point
rlegal: jsr COMENT ; compute entry point
bcs E670_3 ; go if error in compute
; get record or characters
lda ICBLLZ
ora ICBLHZ ; is buffer length zero?
bne @2 ; no
jsr GOHAND
sta ICAX6Z
jmp E672
; loop to fill buffer or end record
@2: jsr GOHAND ; go to handler to get byte
sta ICAX6Z ; save byte
bmi @6 ; end transfer if error
ldy #0
sta (ICBALZ),Y ; put byte in user buffer
jsr INCBFP ; increment buffer pointer
lda ICCOMZ ; get command code
and #2 ; is it GET RECORD?
bne @3 ; no
; check for EOL on text records
lda ICAX6Z ; get byte
cmp #$9B ; is it an EOL?
bne @3 ; no
jsr DECBFL ; yes, decrement buffer length
jmp @6 ; end transfer
; check buffer full
@3: jsr DECBFL ; decrement buffer length
bne @2 ; continue if non zero
; buffer full, record not ended
; discard bytes until end of record
lda ICCOMZ ; get command byte
and #2 ; is it GET CHARACTER?
bne @6 ; yes, end transfer
; loop to wait for EOL
@4: jsr GOHAND ; get byte from handler
sta ICAX6Z ; save character
bmi @5 ; go if error
; text record, wait for EOL
lda ICAX6Z ; get got byte
cmp #$9B ; is it EOL?
bne @4 ; no, continue
; end of record, buffer full -- send truncated record message
lda #137 ; ERROR: truncated record
sta ICSTAZ ; store in IOCB
; new stuff...
@5: jsr DECBFA
ldy #0
lda #$9B
sta (ICBALZ),Y
jsr INCBFP
; transfer done
@6: jsr SUBBFL ; set final buffer length
jmp E672 ; return
; write -- do PUT commands
CIWRIT: lda ICCOMZ ; get command byte
and ICAX1Z ; is this write legal?
bne Z1 ; yes
; illegal write -- device opened for read only
ldy #135 ; error code
E670_4: jmp E670 ; return
; compute and check entry point
Z1: jsr COMENT ; compute handler entry point
bcs E670_4 ; go if error in compute
; put record or characters
lda ICBLLZ
ora ICBLHZ ; is buffer length zero?
bne @2 ; no
lda ICAX6Z ; get character
inc ICBLLZ ; set buffer length=1
bne @3 ; then just transfer one byte
; loop to transfer bytes from buffer to handler
@2: ldy #0
lda (ICBALZ),Y ; get byte from buffer
sta ICAX6Z ; save
@3: jsr GOHAND ; go put byte
; new stuff...
php ; save N flag
jsr INCBFP ; increment buffer pointer
jsr DECBFL ; decrement buffer length
plp ; restore N flag
bmi @5 ; end if error
lda ICCOMZ ; get command byte
and #2 ; is it PUT RECORD?
bne @4 ; no
; text record -- check for EOL transfer
lda ICAX6Z ; get last character
cmp #$9B ; is it an EOL?
beq @5 ; no
; new stuff..
@4: lda ICBLLZ
ora ICBLHZ ; check buffer length
bne @2 ; continue if non-zero
; buffer empty, record not filled
; check type of transfer
lda ICCOMZ ; get command code
and #2 ; is it PUT CHARACTER?
bne @5 ; yes, end transfer
; put record (text), buffer empty, send EOL
lda #$9B
jsr GOHAND ; go to handler
; end PUT transfer
@5: jsr SUBBFL ; set actual PUT buffer length
jmp E672 ; return
; CIO returns
; returns with Y=status
E670: sty ICSTAZ
; returns with status stored in ICSTAZ
; move IOCB in zero page back to user area
E672: ldy ICAX5Z ; get IOCB index
lda ICBAL,Y
sta ICBALZ ; restore user buffer pointer
lda ICBAH,Y
sta ICBAHZ
ldx #0 ; loop count and index
stx HNDLOD
@1: lda ZIOCB,X ; zero page
sta ICHID,Y ; to user area
inx
iny
cpx #12 ; 12 bytes
bcc @1
; restore A, X & Y
lda ICAX6Z ; get last character
ldx ICAX5Z ; IOCB index
ldy ICSTAZ ; get STATUS and set flags
rts ; return to user
; ***********************
; ** CIO SUBROUTINES **
; ***********************
; COMENT -- check and compute handler entry point
COMENT: ldy ICHIDZ ; get handler index
cpy #34 ; is it a legal index?
bcc @1 ; yes
; illegal handler index means device not open for operation
ldy #133 ; error code
bcs @2 ; return
; use handler address table and command table to get vector
@1: lda HATABS+1,Y ; get low byte of address
sta ICAX3Z ; and save in pointer
lda HATABS+2,Y ; get hi byte of address
sta ICAX4Z
ldy ICCOMT ; get command code
lda COMTAB-3,Y ; get command offset
tay
lda (ICAX3Z),Y ; get low byte of vector from
tax ; handler itself and save
iny
lda (ICAX3Z),Y ; get hi byte of vector
sta ICAX4Z
stx ICAX3Z ; set lo byte
clc ; show no error
@2: rts
; DECBFL -- decrement buffer length double byte
; Z-flag = 0 on return if length = 0 after decrement
DECBFL: lda ICBLLZ ; will low byte go below?
bne @1 ; no
dec ICBLHZ ; decrement hi byte
@1: dec ICBLLZ ; decrement low byte
lda ICBLLZ
ora ICBLHZ ; set Z if both are zero
rts
; DECBFA -- decrement buffer address diuble byte
DECBFA: lda ICBALZ ; will low byte go below?
bne @1 ; no
dec ICBAHZ ; decrement hi byte
@1: dec ICBALZ ; decrement lo byte
rts
; INCBFP -- increment working buffer pointer
INCBFP: inc ICBALZ ; bump low byte
bne @1 ; go if not zero
inc ICBAHZ ; else, bump hi byte
@1: rts
; SUBBFL -- set buffer length = buffer length - working byte count
SUBBFL: ldx ICAX5Z ; get IOCB index
sec
lda $348,X ; get low byte of initial length
sbc ICBLLZ ; subtract final low byte
sta ICBLLZ ; and save back
lda $349,X ; get hi byte
sbc ICBLHZ
sta ICBLHZ
rts
; GOHAND -- go indirect to a device handler
; Y = status on return, N flag=1 if error on return
GOHAND: ldy #146 ; "no function" status for handler RTS
jsr @1 ; use the indirect jump
sty ICSTAZ ; save status
cpy #0 ; and set N flag
rts
; indirect jump to handler by Paul's method
@1: tax ; save A
lda ICAX4Z ; get jump address hi byte
pha ; put on stack
lda ICAX3Z ; get jump address lo byte
pha ; put on stack
txa ; restore A
ldx ICAX5Z ; get IOCB index
rts ; go to handler indirectly
; DEVSRC -- device search, find device in handler address table
; set ICDNO
DEVSRC: SEC
ldy #1
lda (ICBALZ),Y ; get device number (drive number)
sbc #'1' ; subtract ASCII one
bmi @1
cmp #9 ; is number in range?
bcc @2 ; yes
@1: lda #0 ; no, default to one
@2: sta ICDNOZ ; save device number+1
inc ICDNOZ
; loop to find device
ldy #0 ; get device name from user
lda (ICBALZ),Y
E716: beq @4
ldy #33 ; initial compare index
@3: cmp HATABS,Y ; is this the device?
beq @5 ; yes
dey
dey ; else, point to next device
dey
bpl @3 ; continue for all devices
; no device found, declare non-existent device error
@4: ldy #130 ; error code
sec ; show error
rts ; and return
; found device, set ICHID
@5: tya
sta ICHIDZ ; save handler index
clc ; show no error
rts ; return
COMTAB: .byte 0,4,4,4,4,6,6,6,6,2,8,10
; ********************************
; ** **
; ** PERIPHERAL HANDLER LOADER **
; ** **
; ********************************
PHR: lda WARMST
beq @2
lda #<$3E9 ; ZCHAIN = $3E9
sta ZCHAIN
lda #>$3E9
sta ZCHAIN+1
@1: ldy #$12
clc
lda (ZCHAIN),Y
tax
iny
adc (ZCHAIN),Y
beq @4 ; RTS
lda (ZCHAIN),Y
sta ZCHAIN+1
stx ZCHAIN
jsr CB56
bne @4 ; RTS
jsr E894
bcs @4 ; RTS
bcc @1
@2: lda #0
sta CHLINK
sta CHLINK+1
lda #$4F
bne @7
@3: lda #0
tay
jsr E7BE
bpl @5
@4: rts
@5: clc
lda MEMLO ; HIMEM>=(MEMLO+DVSTAT) ?
adc DVSTAT
sta TEMP1
lda MEMLO+1
adc DVSTAT+1
sta TEMP1+1
sec
lda HIMEM
sbc TEMP1
lda HIMEM+1
sbc TEMP1+1
bcs @8
@6: lda #$4E
@7: tay
jsr E7BE
jmp @3
@8: lda DVSTAT+2 ; device SIO address used for loading
ldx MEMLO
stx DVSTAT+2
ldx MEMLO+1
stx DVSTAT+3
jsr E7DE
bmi @6
sec
jsr E89E
bcs @6
bcc @3
E7BE: pha
ldx #$9
@1: lda E7D4,X
sta $300,X
dex
bpl @1
sty DAUX2
pla
sta DAUX1
jmp SIOV
; a table area
E7D4: .byte $4F ; DDEVIC
.byte 1 ; DUNIT
.byte $40 ; DCOMND
.byte %01000000 ; DSTATS
.word $2EA ; DBUFLO/HI
.byte 30 ; DTIMLO
.byte 0 ; DUNUSE
.word 4 ; DBYTLO/HI
E7DE: sta TEMP2
ldx #0
stx TEMP1
dex
stx TEMP3
lda $2EC
ror A
bcc @1
inc $2EC
bne @1
inc $2ED
@1: lda DVSTAT+2
sta LOADAD
lda DVSTAT+3
sta LOADAD+1
lda #<E816
sta GBYTEA
lda #>E816
sta GBYTEA+1
lda #$80
sta $2D3
jmp C745
E816: ldx TEMP3
inx
stx TEMP3
beq @2
@1: ldx TEMP3
lda $37D,X
clc
rts
@2: lda #$80
sta TEMP3
jsr E833
bpl @1
sec
rts
E833: ldx #11
@1: lda E851,X
sta $300,X
dex
bpl @1
ldx TEMP1
stx DAUX1
inx
stx TEMP1
lda TEMP2
sta DDEVIC
jmp SIOV
; Device Control Block
E851: .byte 0 ; DDEVIC
.byte 1 ; DUNIT
.byte $26 ; DCOMND
.byte %01000000 ; DSTATS
.word CASBUF ; DBUFLO/HI
.byte 30 ; DTIMLO
.byte 0 ; DUNUSE
.word $80 ; DBYTLO/HI
.word 0 ; DAUX1/2
E85D: sty TEMP1
sta TEMP1+1
lda #<$3E9 ; ZCHAIN = $3E9
sta ZCHAIN
lda #>$3E9
sta ZCHAIN+1
@1: ldy #$12
lda (ZCHAIN),Y
tax
iny
lda (ZCHAIN),Y
cmp TEMP1+1
bne @2
cpx TEMP1
bne @2
clc
rts
@2: cmp #0
bne @4
cpx #0
bne @4
@3: sec
rts
@4: stx ZCHAIN
sta ZCHAIN+1
jsr CB56
bne @3
beq @1
E894: sec
php
bcs E8C0 ; JMP E8C0
PHINI: sta $2ED
sty $2EC
E89E: php
lda #0
tay
jsr E85D
bcs E8CE
ldy #$12
lda $2EC
sta (ZCHAIN),Y
tax
iny
lda $2ED
sta (ZCHAIN),Y
stx ZCHAIN
sta ZCHAIN+1
lda #0
sta (ZCHAIN),Y
dey
sta (ZCHAIN),Y
E8C0: jsr E900
bcc E8D1
lda $2ED
ldy $2EC
jsr PHUNL
E8CE: plp
sec
rts
E8D1: plp
bcs E8DD
lda #0
ldy #$10
sta (ZCHAIN),Y
iny
sta (ZCHAIN),Y
E8DD: clc
ldy #$10
lda MEMLO
adc (ZCHAIN),Y
sta MEMLO
iny
lda MEMLO+1
adc (ZCHAIN),Y
sta MEMLO+1
ldy #15
lda #0
sta (ZCHAIN),Y
jsr CB56
ldy #15
sta (ZCHAIN),Y
clc
rts
E900: clc
lda ZCHAIN
adc #12
sta TEMP1
lda $4B
adc #0
sta TEMP1+1
jmp (TEMP1)
jmp SETVBL
PHUNL: jsr E85D
bcs @3
tay
lda ZCHAIN
pha
lda ZCHAIN+1
pha
stx ZCHAIN
sty ZCHAIN+1
lda COLDST
bne @1
ldy #$10
clc
lda (ZCHAIN),Y
iny
adc (ZCHAIN),Y
bne @2
jsr CB56
bne @2
@1: ldy #18
lda (ZCHAIN),Y
tax
iny
lda (ZCHAIN),Y
tay
pla
sta ZCHAIN+1
pla
sta ZCHAIN
tya
ldy #19
sta (ZCHAIN),Y
dey
txa
sta (ZCHAIN),Y
clc
rts
@2: pla
pla
@3: sec
rts
; weird stuff...
.byte 0,0
jmp SIO
; ****************************************
; ** **
; ** END OF: PERIPHERAL HANDLER LOADER **
; ** **
; ****************************************
; **********************
; ** **
; ** SERIAL I/O INIT **
; ** **
; **********************
; SIO initialization subroutine
SIOINT: lda #%00111100
sta PACTL ; turn off motor
lda #%00111100
sta PBCTL ; raise not command line
lda #3
sta $232 ; get POKEY out of initialize mode
sta SOUNDR ; init poke address for quiet I/O
sta SKCTL
rts
; ***********************
; ** **
; ** SIO MAIN ROUTINE **
; ** **
; ***********************
E971: tsx
stx STACKP ; save stack pointer
lda #1
sta CRITIC
lda DDEVIC
cmp #$60
bne @1 ; branch if not cassette
jmp CASENT ; otherwise jump to cassette enter
; all devices except cassette are intelligent
@1: lda #0
sta CASFLG ; init cassette flag to no cassette
lda #1 ; set number of device retries
sta DRETRY
@2: lda #13 ; set number of command frame retries
sta CRETRY
; send a command frame
@3: lda #$28 ; set baud rate to 19200
sta $D204
lda #0
sta $D206
clc ; set up command buffer
lda DDEVIC
adc DUNIT
adc #$FF ; subtract 1
sta CDEVIC ; set bus ID number
lda DCOMND ; set bus command
sta CCOMND
lda DAUX1 ; store command frame aux bytes 1 and 2
sta CAUX1
lda DAUX2
sta CAUX2 ; done setting up command buffer
clc ; set buffer pointer to cmd frame buf
lda #$3A
sta BUFRLO ; and buffer end address
adc #4
sta BFENLO
lda #2
sta BUFRHI
sta BFENHI ; done setting up buffer pointer
lda #%00110100 ; lower not command line
sta PBCTL
jsr SENDIN ; send command frame to a smart device
lda ERRFLG
bne @4 ; branch if an error received
tya
bne @5 ; branch if ACK received
@4: dec CRETRY ; NACK or TIME OUT occured
bpl @3 ; so branch if any retries left
jmp @10 ; otherwise, jump to return section
@5: lda DSTATS ; new stuff...
bpl @6
; send a data frame to a peripheral
lda #13 ; set number of retries
sta CRETRY
jsr LDPNTR ; load buffer pointer with DCB info
jsr SENDIN ; send data frame to smart device
beq @10 ; branch if bad
; wait for complete signal from peripheral
@6: jsr STTMOT ; set device time out values in Y,X
lda #0
sta ERRFLG ; clear error flag
jsr WAITER ; set up timer and wait
beq @8 ; branch if time out
; device did not time out
bit DSTATS
bvs @7 ; branch if more data follows
lda ERRFLG
bne @10 ; branch if an error occured
beq EA2A ; otherwise return
; receive a data frame from peripheral
@7: jsr LDPNTR ; load buffer pointer with DCB info
jsr RECEIV ; go receive a data frame
@8: lda ERRFLG
beq @9 ; branch if no error preceeded data
lda TSTAT ; get temp status
sta STATUS ; store in real status
@9: lda STATUS
cmp #1
beq EA2A ; branch if completely successful
@10: dec DRETRY
bmi EA2A ; branch if out of device retries
jmp @2 ; otherwise, one more time
EA2A: jsr SENDDS ; disable POKEY interrupts
lda #0
sta CRITIC
ldy STATUS ; return status in Y
sty DSTATS ; and the DCB status word
rts
; wait subroutine
; waits for COMPLETE or ACK
; returns Y=$FF if successfull, Y=$00 if not
WAIT: lda #0
sta ERRFLG ; clear error flag
clc ; load buffer pointer with address
lda #$3E ; of temporary RAM cell
sta BUFRLO
adc #1
sta BFENLO ; also set buffer end +1 address
lda #2
sta BUFRHI
sta BFENHI ; done loading pointer
lda #$FF
sta NOCKSM ; set no checksum follows data flag
jsr RECEIV ; go receive a byte
ldy #$FF ; assume success
lda STATUS
cmp #1
bne @2 ; branch if it did not work ok
lda TEMP ; make sure the byte successfully rec'd
cmp #'A' ; was actually an ACK or COMPLETE
beq @4
cmp #'C'
beq @4
cmp #'E' ; branch if device did not send back
bne @1
lda #144
sta STATUS ; set device error status
bne @2
@1: lda #139 ; otherwise set NACK status
sta STATUS
@2: lda STATUS
cmp #138
beq @3 ; branch if time out
lda #$FF
sta ERRFLG ; set some error flag
bne @4 ; return with out setting Y = 0
@3: ldy #0
@4: lda STATUS
sta TSTAT
rts ; return
; send subroutine
; sends a buffer of bytes out over the serial bus
SEND: lda #1 ; assume success
sta STATUS
jsr SENDEN ; enable sending
ldy #0
sty CHKSUM ; clear check sum
sty CHKSNT ; checksum sent flag
sty XMTDON ; transmission done flag
lda (BUFRLO),Y ; put first byte from buffer
sta SEROUT ; into the serial output register
sta CHKSUM ; put it in checksum
@1: lda BRKKEY
bne @2
jmp BROKE ; jump if break key pressed
@2: lda XMTDON ; loop until transmission done
beq @1
jsr SENDDS ; disable sending
rts ; return
; output data needed interrupt service routine
ISRODN: tya
pha ; save Y reg on stack
inc BUFRLO ; increment buffer pointer
bne @1
inc BUFRHI
@1: lda BUFRLO ; check if past end buffer
cmp BFENLO
lda BUFRHI ; high part
sbc BFENHI
bcc @4 ; branch if not pas end of buffer
lda CHKSNT
bne @2
lda CHKSUM
sta SEROUT ; send check sum
lda #$FF
sta CHKSNT ; set checksum sent flag
bne @3
@2: lda POKMSK ; enable transmit done interrupt
ora #%00001000
sta POKMSK
sta IRQEN
@3: pla
tay ; restore Y reg
pla ; return from interrupt
rti
@4: ldy #0
lda (BUFRLO),Y ; put next byte from buffer
sta SEROUT ; into the serial output register
clc
adc CHKSUM ; add it to checksum
adc #0
sta CHKSUM
jmp @3 ; go return
; transmit done interrupt service routine
ISRTD: lda CHKSNT
beq @1 ; branch if checksum not yet sent
sta XMTDON ; otherwise set transmission done flag
lda POKMSK ; disable transmit done interrupt
and #%11110111
sta POKMSK
sta IRQEN
@1: pla ; return from interrupt
rti
RECEIV: lda #0
ldy CASFLG ; branch if cassette
bne @1
sta CHKSUM ; clear checksum
@1: sta BUFRFL ; buffer full flag
sta RECVDN ; receive done flag
lda #1
sta STATUS ; set good status for default case
jsr RECVEN ; do receive enable
lda #%00111100 ; command frame hi command
sta PBCTL ; store in PIA
@2: lda BRKKEY
bne @3
jmp BROKE ; jump if break key pressed
@3: lda TIMFLG ; no,
beq TOUT ; if timeout, go set error status
lda RECVDN
beq @2 ; done?
rts
TOUT: lda #138 ; yes,
sta STATUS ; set timeout status
rts
ISRSIR: tya
pha ; save Y reg on stack
lda SKSTAT
sta SKRES ; reset status register
bmi @1 ; branch if no framing error
ldy #140
sty STATUS ; set frame error status
@1: and #%00100000
bne @2 ; branch if no overrun error
ldy #142
sty STATUS ; set overrun error status
@2: lda BUFRFL
beq @5 ; branch if buffer was not yet filled
lda SERIN ; this input byte is the checksum
cmp CHKSUM
beq @3 ; branch if checksums match
ldy #143
sty STATUS ; set checksum error status
@3: lda #$FF
sta RECVDN ; set receive done flag
@4: pla
tay ; restore Y reg
pla ; return from interrupt
rti
@5: lda SERIN
ldy #0
sta (BUFRLO),Y ; store input register into buffer
clc ; add it to checksum
adc CHKSUM
adc #0
sta CHKSUM
inc BUFRLO ; increment buffer pointer
bne @6
inc BUFRHI
@6: lda BUFRLO
cmp BFENLO
lda BUFRHI
sbc BFENHI
bcc @4 ; branch if new bufadr is in buffer L
lda NOCKSM
beq @7 ; branch if a checksum will follow data
lda #0
sta NOCKSM ; clear no checksum flag
beq @3 ; go return and set receive done flag
@7: lda #$FF
sta BUFRFL ; set buffer full flag
bne @4 ; go return
; load buffer pointer subroutine
; load DCB buffer pointer with DCB buffer information
LDPNTR: clc
lda DBUFLO
sta BUFRLO
adc DBYTLO
sta BFENLO ; also set buffer end + 1 address
lda DBUFHI
sta BUFRHI
adc DBYTHI
sta BFENHI
rts ; return
; cassette handling code
CASENT: lda DSTATS
bpl @3 ; branch if input from cassette
lda #<1484 ; set baud rate to 600
sta AUDF3
lda #>1484
sta AUDF4
jsr SENDEN ; turn on POKEY mark tone
ldx PALNTS
ldy EE11+4,X ; load short write interrecord gap time
lda DAUX2
bmi @1 ; branch if short gap is desired
ldy EE11,X
@1: ldx #0 ; set write IRG time
jsr SETVBX
lda #%00110100
sta PACTL ; turn on motor
@2: lda TIMFLG ; loop until done
bne @2
jsr LDPNTR ; load buffer pointer with DCB info
jsr SEND ; send a buffer
jmp @6 ; go return
; receive a record
@3: lda #$FF
sta CASFLG ; set cassette flag
ldx PALNTS
ldy EE11+6,X ; load short read interrecord gap time
lda DAUX2
bmi @4 ; branch if short gap is desired
ldy EE11+2,X
@4: ldx #0
jsr SETVBX
lda #%00110100
sta PACTL ; turn on motor
@5: lda TIMFLG ; loop until done
bne @5
jsr LDPNTR ; load buffer pointer with DCB info
jsr STTMOT ; set device time out in Y,X
jsr SETVBX
jsr BEGIN ; set initial baud rate
jsr RECEIV ; go receive a block
@6: lda DAUX2
bmi @7 ; branch if doing short IRG's
lda #%00111100
sta PACTL ; turn off motor
@7: jmp EA2A
JTIMER: lda #0
sta TIMFLG ; set time out flag
rts
; send enable subroutine
SENDEN: lda #%00000111 ; mask off prev serial bus control bits
and SSKCTL
ora #%00100000 ; set transmit mode
ldy DDEVIC
cpy #$60
bne @1 ; branch if not cassette
ora #%00001000 ; set the FSK output bit
ldy #7 ; set FSK tome frequencies
sty AUDF2
ldy #5
sty AUDF1
@1: sta SSKCTL ; store new value to system mask
sta SKCTL ; store to actual register
lda #%11000111 ; mask off prev serial bus intr bits
and POKMSK
ora #%00010000 ; enable output data needed interrupt
jmp EC56 ; continue in receive enable subroutine
; receive enable subroutine
RECVEN: lda #%00000111 ; mask off prev serial bus control bits
and SSKCTL
ora #%00010000 ; set receive mode asynchronous
sta SSKCTL ; store new value to system mask
sta SKCTL ; store to actual register
sta SKRES ; reset serial port/keyboard status reg
lda #%11000111 ; mask off prev serial bus intr bits
and POKMSK
ora #%00100000 ; enable receive interrupt
EC56: sta POKMSK ; store new value to system mask
sta IRQEN ; store to actual register
lda #%00101000 ; clock CH@3 with 1@79 MHz
sta AUDCTL ; clock CH@4 with CH@3
ldx #6 ; set pure tones, no volume
lda #%10101000
ldy SOUNDR ; test quiet I/O flag
bne @1 ; NE is normal (noisy)
lda #%10100000
@1: sta AUDC1,X
dex
dex
bpl @1
lda #%10100000
sta AUDC3 ; turn off sound on channel 3
ldy DDEVIC
cpy #$60
beq @2 ; branch if cassette is desired
sta AUDC1 ; otherwise turn off channels 1 and 2
sta AUDC2
@2: rts ; return
SENDDS: nop ; ?huh?
lda #%11000111 ; mask off serial bus interrupts
and POKMSK
sta POKMSK ; store new value to system mask
sta IRQEN ; store to actual register
ldx #6
lda #0
@1: sta AUDC1,X
dex
dex
bpl @1 ; turn off audio volume
rts ; return
; set ddevice time out values in Y,X subroutine
STTMOT: lda DTIMLO ; get device time out in 1 second incr
ror A ; put 6 hi bits in X, lo 2 bits in Y
ror A
tay ; temp save
and #%00111111 ; mask off hi 2 bits
tax ; this is hi byte of time out
tya
ror A
and #%11000000 ; mask off all but 2 hi bits
tay ; this is lo byte of time out
rts
; these are called INTTBL in the OS source, but are not used!
.word ISRSIR ; serial input ready
.word ISRODN ; output data needed
.word ISRTD ; transmission done
; send a data frame to an intelligent peripheral subroutine
SENDIN: ldx #1 ; wait a short time...
@1: ldy #$FF
@2: dey
bne @2
dex
bne @1
jsr SEND ; go send the data frame
ldy #2 ; set ack time out
ldx #0
WAITER: jsr SETVBX
jsr WAIT ; wait for ack
tya ; if Y=0, a TIME OUT or NACK occured
rts ; return
; compute value for POKEY freq regs for the baud rate as
; measured by an interval of the 'VCOUNT' timer.
COMPUT: sta TIMER2
sty TIMER2+1 ; save final timer value
jsr ADJUST ; adjust VCOUNT value
sta TIMER2 ; save adjusted value
lda TIMER1
jsr ADJUST ; adjust
sta TIMER1 ; save adjusted TIMER1 value
lda TIMER2
sec
sbc TIMER1
sta TEMP1 ; find VCOUNT difference
lda TIMER2+1
sec
sbc TIMER1+1
tay ; find VBLANK count difference
ldx PALNTS
lda #0
sec
sbc EE11+8,X
@1: clc
adc EE11+8,X ; accumulate multiplication
dey
bpl @1 ; done?
clc
adc TEMP1 ; total VCOUNT difference
tay ; save accum
lsr A
lsr A
lsr A
asl A
sec
sbc #22 ; adjust table index
tax ; div interval by 4 to get table index
tya ; restore accum
and #%00000111
tay ; pull off 3 lo bits of interval
lda #$F5 ; -11
@2: clc
adc #11 ; accumulate interpolation constant
dey
bpl @2 ; interp constant computation done?
ldy #0
sec
sbc #7 ; adjust interpolation constant
bpl @3
dey
@3: clc
adc POKTAB,X ; add constant to lo byte table value
sta CBAUDL
tya
adc POKTAB+1,X ; add carry to hi byte table value
sta CBAUDH
rts
ADJUST: cmp #$7C
bmi @1 ; larger than '7C' ?
sec ; yes
sbc #$7C
rts
@1: clc
ldx PALNTS
adc EE11+10,X
rts
; initial baud rate measurement -- used to set the
; baud rate at the start of a record
; it is assumed that the first two bytes of every record are 'AA' hex
BEGIN: lda BRKKEY
bne @1
jmp BROKE ; jump if break key pressed
@1: sei
lda TIMFLG
bne @2 ; branch if not timed out
beq @4 ; branch if time out
@2: lda SKSTAT
and #%00010000 ; read serial port
bne BEGIN ; start bit?
sta SAVIO ; save ser. data in
ldx VCOUNT ; read vertical line counter
ldy RTCLOK+2 ; read lo byte of VBLANK counter
stx TIMER1
sty TIMER1+1 ; save initial timer value
ldx #1 ; set mode flag
stx TEMP3
ldy #10 ; set bit counter for 10 bits
@3: lda BRKKEY
beq BROKE ; branch if break key pressed
lda TIMFLG
bne @5 ; branch if not timed out
@4: cli
jmp TOUT ; branch if time out
@5: lda SKSTAT
and #%00010000 ; read serial port
cmp SAVIO ; data in changed yet?
beq @3
sta SAVIO ; yes, save ser. data in
dey ; decr. bit counter
bne @3 ; done?
dec TEMP3 ; yes,
bmi @6 ; done with both modes?
lda VCOUNT
ldy RTCLOK+2 ; read timer lo & hi bytes
jsr COMPUT ; no, compute baud rate
ldy #9 ; set bit counter for 9 bits
bne @3
@6: lda CBAUDL
sta AUDF3
lda CBAUDH
sta AUDF4 ; set POKEY freq regs for baud rate
lda #0
sta SKCTL
lda SSKCTL
sta SKCTL ; init POKEY serial port
lda #%01010101
sta (BUFRLO),Y ; store '$55' as first rcv. buffer
iny
sta (BUFRLO),Y
lda #%10101010
sta CHKSUM ; store checksum for 2 bytes of '$AA'
clc
lda BUFRLO
adc #2
sta BUFRLO
lda BUFRHI
adc #0
sta BUFRHI ; incr. buffer pointer by 1
cli
rts
BROKE: jsr SENDDS ; break key was pressed, so prepare
lda #%00111100 ; to return
sta PACTL ; turn off motor
lda #%00111100
sta PBCTL ; raise not command line
lda #128
sta STATUS ; store break abort status code
ldx STACKP
txs ; restore stack pointer
dec BRKKEY ; set break key flag to nonzero
cli ; allow IRQ's
jmp EA2A ; go return
SETVBX: lda #<JTIMER ; store time out routine address
sta CDTMA1
lda #>JTIMER
sta CDTMA1+1
lda #1 ; set for timer 1
sei ; the SETVBL needs this to cut short
jsr SETVBV ; any VBLANKs that occur
lda #1 ; set for timer 2
sta TIMFLG ; set flag to not timed out
cli
rts
; 'VCOUNT' interval timer measurement -- TO -- POKEY freq reg value
; conversion table
; The values stored in the table are 'AUDF+7'
; The followinf formulas were used to determine the table values:
; F OUT = F IN/(2*(AUDF+M)) , where F IN=1@78979 MHz & M=7
; From this was derived a formula used to compute the table values
; based on a measurement of the period by an interval of the VCOUNT
; timer.
; AUDF+7=(11@365167)*T OUT, where T OUT=# of counts
; (127 usec. resolution) of VCOUNT for 1 character time
; (10 bit times).
; AUDF+7 BAUD RATE VCOUNT INTERVAL
; ------ ----------- ----------------
POKTAB: .word $3E8 ; 895 88
.word $443 ; 820 96
.word $49E ; 757 104
.word $4F9 ; 703 112
.word $554 ; 656 120
.word $5AF ; 615 128
.word $60A ; 579 136
.word $665 ; 547 144
.word $6C0 ; 518 152
.word $71A ; 492 160
.word $775 ; 469 168
.word $7D0 ; 447 176
; PAL / NTSC timing values
EE11: .byte $B4,$96
.byte $78,$64
.byte $0F,$0D
.byte $0A,$08
.byte $83,$9C
.byte $07,$20
; *********************
; ** SIO ENDS HERE **
; *********************
EE1D: .byte $18,$10,$0A,$0A,$10,$1C,$34,$64
.byte $C4,$C4,$C4,$C4,$1C,$10,$64,$C4
EE2D: .byte $17,$17,$0B,$17,$2F,$2F,$5F,$5F
.byte $61,$61,$61,$61,$17,$0B,$BF,$61
.byte $13,$13,$09,$13,$27,$27,$4F,$4F
.byte $41,$41,$41,$41,$13,$09,$9F,$41
EE4D: .byte $02,$06,$07,$08,$09,$0A,$0B,$0D
.byte $0F,$0F,$0F,$0F,$04,$05,$0C,$0E
EE5D: .byte $00,$00,$00,$00,$00,$00,$00,$01
.byte $01,$01,$01,$01,$00,$00,$01,$01
EE6D: .byte $03,$02,$02,$01,$01,$02,$02,$03
.byte $03,$03,$03,$03,$03,$03,$02,$03
EE7D: .byte $28,$14,$14,$28,$50,$50,$A0,$A0
.byte $40,$50,$50,$50,$28,$28,$A0,$A0
EE8D: .byte $18,$18,$0C,$18,$30,$30,$60,$60
.byte $C0,$C0,$C0,$C0,$18,$0C,$C0,$C0
EE9D: .byte $00,$00,$00,$02,$03,$02,$03,$02
.byte $03,$01,$01,$01,$00,$00,$03,$02
EEAD: .byte $FF,$F0,$0F,$C0,$30,$0C,$03
EEB4: .byte %10000000 ; yet another barrel shifter!
.byte %01000000
.byte %00100000
.byte %00010000
.byte %00001000
.byte %00000100
.byte %00000010
.byte %00000001
PHE: pha ; peripheral handler entry
tya
pha
txa
ldx #0
@1: cmp HATABS,X
beq @3
inx
inx
inx
cpx #$22
bmi @1
ldx #0
tay
lda #0
@2: cmp HATABS,X
beq @4
inx
inx
inx
cpx #$22
bmi @2
pla
pla
ldy #$FF
sec
rts
@3: pla
tay
pla
inx
sec
rts
@4: tya
sta HATABS,X
pla
sta HATABS+1,X
pla
sta HATABS+2,X
clc
rts
EEF9: ldy #0
lda (ICBALZ),Y
ldy ICDNOZ
jsr E7BE
bpl EF07
ldy #130
rts
EF07: lda #$7F
sta ICHIDZ
lda #<(EF26-1)
sta ICPTLZ
lda #>(EF26-1)
sta ICPTHZ
lda $2EC
.byte $AE ; absolute addr. mode for LDX ICAX5Z
.word ICAX5Z
sta $34D,X
ldy #0
lda (ICBALZ),Y
sta $34C,X
ldy #1
rts
EF26: pha
txa
pha
and #%00001111
bne EF3D
cpx #$80
bpl EF3D
lda HNDLOD
bne EF41
ldy #$82
EF38: pla
pla
cpy #0
rts
EF3D: ldy #134
bmi EF38
EF41: .byte $8E ; absolute addr. mode for STX ICAX5Z
.word ICAX5Z
ldy #0
EF46: lda IOCB,X
sta ZIOCB,Y
inx
iny
cpy #12
bmi EF46
jsr CA29
bmi EF38
pla
tax
pla
tay
lda ICPTHZ
pha
lda ICPTLZ
pha
tya
ldy #146
rts
.byte 0,0,0,0,0,0
jmp FD05
; ***************************************************************
; ** **
; ** Device Handler Initialisation Code for devices E: S: K: **
; ** **
; ***************************************************************
SIN: lda #$FF
sta CH
lda RAMSIZ
sta RAMTOP
lda #$40
sta $2BE
lda #<KEYMAP
sta KEYDEF
lda #>KEYMAP
sta KEYDEF+1
lda #<FKYMAP
sta FKDEF
lda #>FKYMAP
sta FKDEF+1
rts
; ***************
; ** **
; ** Open S: **
; ** **
; ***************
EF8E: lda ICAX2Z ; perform screen OPEN
and #%00001111
bne EF9C
; ***************
; ** **
; ** Open E: **
; ** **
; ***************
EF94: lda ICAX1Z ; perform editor OPEN
and #%00001111
sta ICAX1Z
lda #0
EF9C: sta $57 ; complete OPEN command
cmp #$10
bcc EFA7
lda #$91
jmp F154
EFA7: lda #>CHARSET1
sta CHBAS
lda #>CHARSET2
sta CHSALT
lda #2
sta CHACT
sta SDMCTL
lda #1
sta $4C
lda #%11000000
ora POKMSK
sta POKMSK
sta IRQEN
lda #%01000000
sta NMIEN
bit $26E
bpl EFDC
lda #<FCC4 ; gimme a DLI!
sta VDSLST
lda #>FCC4
sta VDSLST+1
lda #%11000000
EFDC: sta NMIEN
lda #0
sta TINDEX
sta ADRESS
sta $7B
sta CRSINH
ldy #14
lda #1
EFEF: sta TABMAP,Y
dey
bpl EFEF
ldx #4 ; init color 0-3
EFF7: lda FB08,X
sta $2C4,X
dex
bpl EFF7
ldy RAMTOP
dey
sty TXTMSC+1
lda #$60
sta TXTMSC
ldx $57
lda EE4D,X
sta $51
lda RAMTOP
sta ADRESS+1
ldy EE1D,X
F019: lda #$28
jsr F57A
dey
bne F019
lda GPRIOR
and #%00111111
sta $67
tay
cpx #8
bcc F04C
cpx #15
beq F03E
cpx #12
bcs F04C
txa
ror A
ror A
ror A
and #%11000000
ora $67
tay
F03E: lda #$10
jsr F57A
cpx #11
bne F04C
lda #6 ; gray
sta COLOR4
F04C: sty GPRIOR
lda ADRESS
sta $58
lda ADRESS+1
sta $59
F057: lda $D40B
cmp #$7A
bne F057
jsr F578
lda EE5D,X
beq F06C
lda #$FF
sta ADRESS
dec ADRESS+1
F06C: jsr F565
lda ADRESS
sta $68
lda ADRESS+1
sta $69
lda #$41
jsr F570
stx $66
lda #$18
sta $2BF
lda $57
cmp #12
bcs F08D
cmp #9
bcs F0C6
F08D: lda ICAX1Z
and #%00010000
beq F0C6
lda #4
sta $2BF
ldx #2
lda $26E
beq F0A2
jsr F5A0
F0A2: lda #2
jsr F569
dex
bpl F0A2
ldy RAMTOP
dey
tya
jsr F570
lda #$60
jsr F570
lda #$42
jsr F569
clc
lda #$10
adc $66
tay
ldx EE2D,Y
bne F0DB
F0C6: ldy $66
ldx EE2D,Y
lda $57
bne F0DB
lda $26E
beq F0DB
jsr F5A0
lda #$22
sta $51
F0DB: lda $51
jsr F570
dex
bne F0DB
lda $57
cmp #8
bcc F10F
cmp #15
beq F0F1
cmp #12
bcs F10F
F0F1: ldx #$5D
lda RAMTOP
sec
sbc #$10
jsr F570
lda #0
jsr F570
lda $51
ora #$40
jsr F570
F107: lda $51
jsr F570
dex
bne F107
F10F: lda $59
jsr F570
lda $58
jsr F570
lda $51
ora #$40
jsr F570
lda #$70
jsr F570
lda #$70
jsr F570
lda ADRESS
sta SDLSTL
lda ADRESS+1
sta SDLSTH
lda #$70
jsr F570
lda ADRESS
sta HIMEM
lda ADRESS+1
sta HIMEM+1
ldy #1
lda SDLSTL
sta ($68),Y
iny
lda SDLSTH
sta ($68),Y
lda $4C
bpl F164
F154: sta DERRF
jsr EF94
lda DERRF
ldy #0
sty DERRF
tay
rts
F164: lda ICAX1Z
and #%00100000
bne F175
jsr F420
sta TXTROW
lda LMARGN
sta TXTCOL
F175: lda #%00100010
ora SDMCTL
sta SDMCTL
jmp F20B
; *******************
; ** **
; ** Get Byte S: **
; ** **
; *******************
F180: jsr F6CA ; screen get-byte routine
jsr F18F
jsr F76A
jsr F60A
jmp F21E
F18F: jsr F5AC ; get data under cursor
lda (ADRESS),Y
and $2A0
F197: lsr $6F
bcs F19E
lsr A
bpl F197
F19E: sta $2FA
cmp #0
F1A3: rts
; *******************
; ** **
; ** Put Byte S: **
; ** **
; *******************
F1A4: sta $2FB
cmp #$7D
bne F1B1
jsr F420
jmp F20B
F1B1: jsr F6CA
F1B4: lda $2FB
cmp #$9B
bne F1C1
jsr F661
jmp F20B
F1C1: jsr F1CA
jsr F60E
jmp F20B
F1CA: lda SSFLAG ; plot point
bne F1CA
ldx #2
F1D1: lda $54,X
sta $5A,X
dex
bpl F1D1
lda $2FB
tay
rol A
rol A
rol A
rol A
and #$3
tax
tya
and #$9F
ora FB49,X
F1E9: sta $2FA ; display
jsr F5AC
lda $2FA
F1F2: lsr $6F
bcs F1FA
asl A
jmp F1F2
F1FA: and $2A0
sta $50
lda $2A0
eor #$FF
and (ADRESS),Y
ora $50
sta (ADRESS),Y
rts
F20B: jsr F18F
sta $5D
ldx $57
bne F21E
ldx CRSINH
bne F21E
eor #$80
jsr F1E9
; ********************************************
; ** **
; ** Open K: Close K: Get Status E: S: K: **
; ** **
; ********************************************
F21E: ldy $4C
jmp F226
SELFS: jmp $C8FC
F226: lda #1
sta $4C
lda $2FB
; *********************************
; ** **
; ** Special E: K: Put Byte K: **
; ** **
; *********************************
F22D: rts
; *******************
; ** **
; ** Close E: S: **
; ** **
; *******************
F22E: bit $26E
bpl F21E
lda #$40
sta NMIEN
lda #0
sta $26E
lda #<C0CE
sta $200
lda #>C0CE
sta $201
jmp EF94
; *******************
; ** **
; ** Get Byte E: **
; ** **
; *******************
F24A: jsr F962
jsr F6BC
lda $6B
bne F288
lda $54
sta $6C
lda $55
sta $6D
F25C: jsr F2FD
sty $4C
lda $2FB
cmp #$9B
beq F27A
jsr F2BE
jsr F962
lda $63
cmp #$71
bne F277
jsr F556
F277: jmp F25C
F27A: jsr F718
jsr F8B1
lda $6C
sta $54
lda $6D
sta $55
F288: lda $6B
beq F29D
F28C: dec $6B
beq F29D
lda $4C
bmi F28C
jsr F180
sta $2FB
jmp F962
F29D: jsr F661
lda #$9B
sta $2FB
jsr F20B
sty $4C
jmp F962
F2AD: jmp (ADRESS)
; ******************
; ** **
; ** Put Byte E: **
; ** **
; ******************
F2B0: sta $2FB
jsr F962
jsr F6BC
lda #0
sta SUPERF
F2BE: jsr F718
jsr F93C
beq F2CF
F2C6: asl ESCFLG
jsr F1B4
jmp F962
F2CF: lda $2FE
ora ESCFLG
bne F2C6
asl ESCFLG
inx
lda SUPERF
beq F2E5
txa
clc
adc #$2D
tax
F2E5: lda FB0D,X
sta ADRESS
lda FB0E,X
sta ADRESS+1
jsr F2AD ; JSR (ADRESS)
jsr F20B
jmp F962
F2F8: lda #$FF
sta CH
; *******************
; ** **
; ** Get Byte K: **
; ** **
; *******************
F2FD: lda #0
sta SUPERF
lda ICAX1Z
lsr A
bcs @10
lda #$80
ldx BRKKEY
beq @9
lda CH
cmp #$FF
beq F2FD
sta $7C
ldx #$FF
stx CH
ldx $2DB
bne @1
jsr F983
@1: tay
cpy #$C0
bcs F2F8
lda ($79),Y
@2: sta $2FB
tax
bmi @3
jmp @16
@3: cmp #$80
beq F2F8
cmp #$81
bne @4
lda $2B6
eor #$80
sta $2B6
bcs F2F8
@4: cmp #$82
bne @5
lda $2BE
beq @6
lda #0
sta $2BE
beq F2F8
@5: cmp #$83
bne @7
@6: lda #$40
sta $2BE
bne F2F8
@7: cmp #$84
bne @8
lda #$80
sta $2BE
jmp F2F8
@8: cmp #$85
bne @11
lda #$88
@9: sta $4C
sta BRKKEY
@10: lda #$9B
jmp @18
@11: cmp #$89
bne @13
lda $2DB
eor #$FF
sta $2DB
bne @12 ; JMP $F2F8
jsr F983
@12: jmp F2F8
@13: cmp #$8E
bcs @15
cmp #$8A
bcc @12
sbc #$8A
asl $7C
bpl @14
ora #4
@14: tay
lda (FKDEF),Y
jmp @2
@15: cmp #$92
bcs @16
cmp #$8E
bcc @12 ; JMP $F2F8
sbc #$72
inc SUPERF
bne @18
@16: lda $7C
cmp #$40
bcs @17
lda $2FB
cmp #$61
bcc @17
cmp #$7B
bcs @17
lda $2BE
beq @17
ora $7C
jmp @1
@17: jsr F93C
beq @19 ; JMP $F21E
lda $2FB
eor $2B6
@18: sta $2FB
@19: jmp F21E
; *******************************
; ** KEYBOARD HANDLER ROUTINES **
; *******************************
F3E0: lda #$80 ; keyboard handler 27
sta ESCFLG
rts
F3E6: dec $54 ; keyboard handler 28
bpl F3F0
ldx $2BF
dex
F3EE: stx $54
F3F0: jmp F90C
F3F3: inc $54 ; keyboard handler 29
lda $54
cmp $2BF
bcc F3F0
ldx #0
beq F3EE
F400: dec $55 ; keyboard handler $1E
lda $55
bmi F40A
cmp LMARGN
bcs F40E
F40A: lda RMARGN ; keyboard handler $1F
F40C: sta $55
F40E: jmp F88E
F411: inc $55 ; keyboard handler $1F
lda $55
cmp RMARGN
bcc F40E
beq F40E
F41B: lda LMARGN ; keyboard handler $1E
jmp F40C
F420: jsr F9A6 ; keyboard handler $7D
ldy ADRESS
lda #0
sta ADRESS
F429: sta (ADRESS),Y
iny
bne F429
inc ADRESS+1
ldx ADRESS+1
cpx RAMTOP
bcc F429
lda #$FF
F438: sta $2B2,Y
iny
cpy #4
bcc F438
F440: jsr F997 ; keyboard handler $1C
sta $63
sta $6D
lda #0
sta $54
sta $56
sta $6C
rts
F450: lda $63 ; keyboard handler $7E
cmp LMARGN
beq F477
lda $55
cmp LMARGN
bne F45F
jsr F923
F45F: jsr F400
lda $55
cmp RMARGN
bne F46F
lda $54
beq F46F
jsr F3E6
F46F: lda #$20
sta $2FB
jsr F1CA
F477: jmp F88E
F47A: jsr F411 ; keyboard handler $7F
lda $55
cmp LMARGN
bne F48B
jsr F665
jsr F758
bcs F492
F48B: lda $63
jsr F75D
bcc F47A
F492: jmp F88E
F495: lda $63 ; keyboard handler $9F
jmp F73E
F49A: lda $63 ; keyboard handler $9E
jmp F74A
F49F: jsr F94C ; keyboard handler $FF
jsr F18F
sta $7D
lda #0
sta $2BB
F4AC: jsr F1E9
lda $63
pha
jsr F612
pla
cmp $63
bcs F4C6
lda $7D
pha
jsr F18F
sta $7D
pla
jmp F4AC
F4C6: jsr F957
F4C9: dec $2BB
bmi F4D2
dec $54
bne F4C9
F4D2: jmp F88E
F4D5: jsr F94C ; keyboard handler $FE
F4D8: jsr F5AC
lda ADRESS
sta $68
lda ADRESS+1
sta $69
lda $63
pha
jsr F60A
pla
cmp $63
bcs F4FE
lda $54
cmp $2BF
bcs F4FE
jsr F18F
ldy #0
sta ($68),Y
beq F4D8
F4FE: ldy #0
tya
sta ($68),Y
jsr F918
jsr F957
jmp F88E
F50C: sec ; keyboard handler $9D
F50D: jsr F7C2
lda LMARGN
sta $55
jsr F5AC
jsr F78E
jsr F7E2
jmp F88E
F520: jsr F88E ; keyboard handler $9C
ldy $51
sty $54
F527: ldy $54
F529: tya
sec
jsr F75B
php
tya
clc
adc #$78
plp
jsr F73C
iny
cpy #$18
bne F529
lda $2B4
ora #1
sta $2B4
lda #0
sta $55
jsr F5AC
jsr F82A
jsr F758
bcc F527
jmp F41B
F556: ldy #$20 ; keyboard handler $FD
F558: jsr F983
dey
bpl F558
rts
F55F: jsr F440 ; keyboard handler $1D
jmp F3E6
F565: lda #2
bne F57A
F569: ldy $26E
beq F570
ora #$20
F570: ldy $4C
bmi F59F
ldy #0
sta (ADRESS),Y
F578: lda #1
F57A: sta $29E
lda $4C
bmi F59F
lda ADRESS
sec
sbc $29E
sta ADRESS
bcs F58D
dec ADRESS+1
F58D: lda APPMHI+1
cmp ADRESS+1
bcc F59F
bne F59B
lda APPMHI
cmp ADRESS
bcc F59F
F59B: lda #$93
sta $4C
F59F: rts
F5A0: lda #2
jsr F570
lda #$A2
jsr F570
dex
rts
F5AC: ldx #1
stx $66
dex
stx ADRESS+1
lda $54
asl A
rol ADRESS+1
asl A
rol ADRESS+1
adc $54
sta ADRESS
bcc F5C3
inc ADRESS+1
F5C3: ldy $57
ldx EE6D,Y
F5C8: asl ADRESS
rol ADRESS+1
dex
bne F5C8
lda $56
lsr A
lda $55
ldx EE9D,Y
beq F5DF
F5D9: ror A
asl $66
dex
bne F5D9
F5DF: adc ADRESS
bcc F5E5
inc ADRESS+1
F5E5: clc
adc $58
sta ADRESS
sta $5E
lda ADRESS+1
adc $59
sta ADRESS+1
sta $5F
ldx EE9D,Y
lda FB04,X
and $55
adc $66
tay
lda EEAD-1,Y
sta $2A0
sta $6F
ldy #0
F609: rts
F60A: lda #0
beq F610
F60E: lda #$9B
F610: sta $7D
F612: inc $63
inc $55
bne F61A
inc $56
F61A: lda $55
ldx $57
cmp EE7D,X
beq F62D
cpx #0
bne F609
cmp RMARGN
beq F609
bcc F609
F62D: cpx #8
bne F635
lda $56
beq F609
F635: lda $57
bne F665
lda $63
cmp #$51
bcc F649
lda $7D
beq F665
jsr F661
jmp F6AB
F649: jsr F665
lda $54
clc
adc #$78
jsr F75D
bcc F65E
lda $7D
beq F65E
clc
jsr F50D
F65E: jmp F88E
F661: lda #$9B ; keyboard handler $9B
sta $7D
F665: jsr F997
lda #0
sta $56
inc $54
ldx $57
ldy #$18
bit $7B
bpl F67B
ldy #4
tya
bne F67E
F67B: lda EE8D,X
F67E: cmp $54
bne F6AB
sty $29D
txa
bne F6AB
lda $7D
beq F6AB
cmp #$9B
beq F691
clc
F691: jsr F7F7
inc $2BB
dec $6C
bpl F69D
inc $6C
F69D: dec $29D
lda $2B2
sec
bpl F691
lda $29D
sta $54
F6AB: jmp F88E
F6AE: sec
lda $70,X
sbc $74
sta $70,X
lda $71,X
sbc $75
sta $71,X
rts
F6BC: lda $2BF
cmp #4
beq F6CA
lda $57
beq F6CA
jsr EF94
F6CA: lda #39 ; column 39 ?
cmp RMARGN
bcs F6D2
sta RMARGN
F6D2: ldx $57
lda EE8D,X
cmp $54
bcc F705
beq F705
cpx #8
bne F6EB
lda $56
beq F6F8
cmp #1
bne F705
beq F6EF
F6EB: lda $56
bne F705
F6EF: lda EE7D,X
cmp $55
bcc F705
beq F705
F6F8: lda #1
sta $4C
lda #$80
ldx BRKKEY
sta BRKKEY
beq F70A
rts
F705: jsr F440
lda #$8D
F70A: sta $4C
pla
pla
lda $7B
bpl F715
jmp F962
F715: jmp F21E
F718: ldy #0
lda $5F
beq F722
lda $5D
sta ($5E),Y
F722: rts
F723: pha
and #%00000111
tax
lda EEB4,X
sta $6E
pla
lsr A
lsr A
lsr A
tax
rts
F732: rol $2B4
rol $2B3
rol $2B2
rts
F73C: bcc F74A
F73E: jsr F723
lda TABMAP,X
ora $6E
sta TABMAP,X
rts
F74A: jsr F723
lda $6E
eor #$FF
and TABMAP,X
sta TABMAP,X
rts
F758: lda $54
F75A: clc
F75B: adc #$78
F75D: jsr F723
clc
lda TABMAP,X
and $6E
beq F769
sec
F769: rts
F76A: lda $2FA
ldy $57
cpy #14
bcs F78A
cpy #12
bcs F77B
cpy #3
bcs F78A
F77B: rol A
rol A
rol A
rol A
and #3
tax
lda $2FA
and #$9F
ora FB4D,X
F78A: sta $2FB
F78D: rts
F78E: ldx RAMTOP
dex
stx $69
stx $67
lda #$B0
sta $68
lda #$D8
sta $66
ldx $54
F79F: inx
cpx $2BF
beq F78D
ldy #$27
F7A7: lda ($68),Y
sta ($66),Y
dey
bpl F7A7
sec
lda $68
sta $66
sbc #$28
sta $68
lda $69
sta $67
sbc #0
sta $69
jmp F79F
F7C2: php
ldy #$16
F7C5: tya
jsr F75A
php
tya
clc
adc #$79
plp
jsr F73C
dey
bmi F7D9
cpy $54
bcs F7C5
F7D9: lda $54
clc
adc #$78
plp
jmp F73C
F7E2: lda LMARGN
sta $55
jsr F5AC
sec
lda RMARGN
sbc LMARGN
tay
lda #0
F7F1: sta (ADRESS),Y
dey
bpl F7F1
rts
F7F7: jsr F732
lda $26E
beq F827
F7FF: lda VSFLAG ; busy waiting (fine scroll)
bne F7FF
lda #8
sta VSFLAG
F809: lda VSFLAG ; busy waiting (fine scroll)
cmp #1
bne F809
F810: lda $D40B
cmp #$40
bcs F810 ; busy waiting
ldx #$D
lda $2BF
cmp #4
bne F822
ldx #$70
F822: cpx $D40B
bcs F822
F827: jsr F9A6
F82A: lda ADRESS
ldx ADRESS+1
F82E: inx
cpx RAMTOP
beq F839
sec
sbc #$10
jmp F82E
F839: adc #39
bne F847
ldx ADRESS+1
inx
cpx RAMTOP
beq F87C
clc
adc #$10
F847: tay
sta $7E
sec
lda ADRESS
sbc $7E
sta ADRESS
bcs F855
dec ADRESS+1
F855: lda ADRESS
clc
adc #40
sta $7E
lda ADRESS+1
adc #0
sta $7F
F862: lda ($7E),Y
sta (ADRESS),Y
iny
bne F862
ldy #$10
lda ADRESS
cmp #$D8
beq F87C
clc
adc #240
sta ADRESS
bcc F855
inc ADRESS+1
bne F855
F87C: ldx RAMTOP
dex
stx $7F
ldx #$D8
stx $7E
lda #0
ldy #$27
F889: sta ($7E),Y
dey
bpl F889
F88E: lda #0
sta $63
lda $54
sta $51
F896: lda $51
jsr F75A
bcs F8A9
lda $63
clc
adc #$28
sta $63
dec $51
jmp F896
F8A9: clc
lda $63
adc $55
sta $63
rts
F8B1: jsr F94C
lda $63
pha
lda $6C
sta $54
lda $6D
sta $55
lda #1
sta $6B
F8C3: ldx #$17
lda $7B
bpl F8CB
ldx #3
F8CB: cpx $54
bne F8DA
lda $55
cmp RMARGN
bne F8DA
inc $6B
jmp F8EA
F8DA: jsr F60A
inc $6B
lda $63
cmp LMARGN
bne F8C3
dec $54
jsr F400
F8EA: jsr F18F
bne F906
dec $6B
lda $63
cmp LMARGN
beq F906
jsr F400
lda $55
cmp RMARGN
bne F902
dec $54
F902: lda $6B
bne F8EA
F906: pla
sta $63
jmp F957
F90C: jsr F88E
lda $51
sta $6C
lda LMARGN
sta $6D
F917: rts
F918: lda $63
cmp LMARGN
bne F920
dec $54
F920: jsr F88E
F923: lda $63
cmp LMARGN
beq F917
jsr F5AC
lda RMARGN
sec
sbc LMARGN
tay
F932: lda (ADRESS),Y
bne F917
dey
bpl F932
jmp F527
F93C: ldx #$2D
F93E: lda FB0D,X
cmp $2FB
beq F94B
dex
dex
dex
bpl F93E
F94B: rts
F94C: ldx #2
F94E: lda $54,X
sta $2B8,X
dex
bpl F94E
rts
F957: ldx #2
F959: lda $2B8,X
sta $54,X
dex
bpl F959
rts
F962: lda $2BF
cmp #$18
beq F980 ; BEQ F21E
ldx #11 ; swap $54.@5F with $290.@29B
F96B: lda $54,X
pha
lda $290,X
sta $54,X
pla
sta $290,X
dex
bpl F96B
lda $7B
eor #$FF
sta $7B
F980: jmp F21E
F983: ldx #$7E
pha
F986: stx CONSOL
lda $D40B
F98C: cmp $D40B ; busy waiting
beq F98C
dex
dex
bpl F986
pla
rts
F997: lda #0
ldx $7B
bne F9A1
ldx $57
bne F9A3
F9A1: lda LMARGN
F9A3: sta $55
rts
F9A6: lda $58
sta ADRESS
lda $59
sta ADRESS+1
F9AE: rts
; ******************
; ** **
; ** Special S: **
; ** **
; ******************
F9AF: ldx #0
lda ICCOMZ
cmp #17
beq @2
cmp #18
beq @1
ldy #132 ; ERROR: Invalid Handler Command
rts
@1: inx
@2: stx $2B7
lda $54
sta $2F5
lda $55
sta $2F6
lda $56
sta $2F7
lda #1
sta $2F8
sta $2F9
sec
lda $2F5
sbc $5A
sta $76
bcs @3
lda #$FF
sta $2F8
lda $76
eor #$FF
clc
adc #1
sta $76
@3: sec
lda $2F6
sbc $5B
sta $77
lda $2F7
sbc $5C
sta $78
bcs @4
lda #$FF
sta $2F9
lda $77
eor #$FF
sta $77
lda $78
eor #$FF
sta $78
inc $77
bne @4
inc $78
@4: ldx #2
ldy #0
sty $73
@5: tya
sta $70,X
lda $5A,X
sta $54,X
dex
bpl @5
lda $77
inx
tay
lda $78
sta $7F
sta $75
bne @6
lda $77
cmp $76
bcs @6
lda $76
ldx #2
tay
@6: tya
sta $7E
sta $74
pha
lda $75
lsr A
pla
ror A
sta $70,X
@7: lda $7E
ora $7F
bne @8
jmp @19 ; JMP $F21E
@8: clc
lda $70
adc $76
sta $70
bcc @9
inc $71
@9: lda $71
cmp $75
bcc @11
bne @10
lda $70
cmp $74
bcc @11
@10: clc
lda $54
adc $2F8
sta $54
ldx #0
jsr F6AE
@11: clc
lda $72
adc $77
sta $72
lda $73
adc $78
sta $73
cmp $75
bcc @15
bne @12
lda $72
cmp $74
bcc @15
@12: bit $2F9
bpl @13
dec $55
lda $55
cmp #$FF
bne @14
lda $56
beq @14
dec $56
bpl @14
@13: inc $55
bne @14
inc $56
@14: ldx #2
jsr F6AE
@15: jsr F6CA
jsr F1CA
lda $2B7
beq @18
jsr F94C
lda $2FB
sta $2BC
@16: lda $54
pha
jsr F612
pla
sta $54
jsr F6CA
jsr F18F
bne @17
lda $2FD
sta $2FB
jsr F1CA
jmp @16
@17: lda $2BC
sta $2FB
jsr F957
@18: sec
lda $7E
sbc #1
sta $7E
lda $7F
sbc #0
sta $7F
bmi @19 ; JMP $F21E
jmp @7
@19: jmp F21E
; some tables
FB04: .byte 0,1,3,7
FB08: .byte $28,$CA,$94,$46,$00 ; Default colors 0-4
FB0D: .byte $1B
FB0E: .word F3E0
.byte $1C
.word F3E6
.byte $1D
.word F3F3
.byte $1E
.word F400
.byte $1F
.word F411
.byte $7D
.word F420
.byte $7E
.word F450
.byte $7F
.word F47A
.byte $9B
.word F661
.byte $9C
.word F520
.byte $9D
.word F50C
.byte $9E
.word F49A
.byte $9F
.word F495
.byte $FD
.word F556
.byte $FE
.word F4D5
.byte $FF
.word F49F
.byte $1C
.word F440
.byte $1D
.word F55F
.byte $1E
.word F41B
.byte $1F
.word F40A
FB49: .byte $40,$00,$20,$60
FB4D: .byte $20,$40,$00,$60
KEYMAP: .byte $6C,$6A,$3B,$8A,$8B,$6B,$2B,$2A
.byte $6F,$80,$70,$75,$9B,$69,$2D,$3D
.byte $76,$80,$63,$8C,$8D,$62,$78,$7A
.byte $34,$80,$33,$36,$1B,$35,$32,$31
.byte $2C,$20,$2E,$6E,$80,$6D,$2F,$81
.byte $72,$80,$65,$79,$7F,$74,$77,$71
.byte $39,$80,$30,$37,$7E,$38,$3C,$3E
.byte $66,$68,$64,$80,$82,$67,$73,$61
.byte $4C,$4A,$3A,$8A,$8B,$4B,$5C,$5E
.byte $4F,$80,$50,$55,$9B,$49,$5F,$7C
.byte $56,$80,$43,$8C,$8D,$42,$58,$5A
.byte $24,$80,$23,$26,$1B,$25,$22,$21
.byte $5B,$20,$5D,$4E,$80,$4D,$3F,$81
.byte $52,$80,$45,$59,$9F,$54,$57,$51
.byte $28,$80,$29,$27,$9C,$40,$7D,$9D
.byte $46,$48,$44,$80,$83,$47,$53,$41
.byte $0C,$0A,$7B,$80,$80,$0B,$1E,$1F
.byte $0F,$80,$10,$15,$9B,$09,$1C,$1D
.byte $16,$80,$03,$89,$80,$02,$18,$1A
.byte $80,$80,$85,$80,$1B,$80,$FD,$80
.byte $00,$20,$60,$0E,$80,$0D,$80,$81
.byte $12,$80,$05,$19,$9E,$14,$17,$11
.byte $80,$80,$80,$80,$FE,$80,$7D,$FF
.byte $06,$08,$04,$80,$84,$07,$13,$01
FKYMAP: .byte $1C,$1D,$1E,$1F,$8E,$8F,$90,$91
; **********************************
; ** **
; ** KEYBOARD INTERRUPT ROUTINE **
; ** **
; **********************************
KIR: txa
pha
tya
pha
ldy PORTB
lda KBCODE
cmp CH1
bne @1
ldx KEYDEL
bne @8
@1: ldx KEYDIS
cmp #$83
bne @4
txa
eor #$FF
sta KEYDIS
bne @2
tya
ora #%00000100
bne @3
@2: tya
and #%11111011
@3: tay
bcs @7
@4: txa
bne @9
lda KBCODE
tax
cmp #$9F
bne @5
lda SSFLAG
eor #%11111111
sta SSFLAG
bcs @7
@5: and #%00111111
cmp #17
bne @10
stx $2DC
beq @7
@6: stx CH
stx CH1
@7: lda #3
sta KEYDEL
lda #0
sta ATRACT
@8: lda KRPDEL
sta SRTIMR
lda SDMCTL
bne @9
lda DMASAV
sta SDMCTL
@9: sty PORTB
pla
tay
pla
tax
pla
rti
@10: cpx #$84
beq @12
cpx #$94
bne @6
lda $2F4
ldx $26B
sta $26B
stx $2F4
cpx #>CHARSET2
beq @11
tya
ora #%00001000
tay
bne @7
@11: tya
and #%11110111
tay
jmp @7
@12: lda SDMCTL
beq @9
sta DMASAV
lda #0
sta SDMCTL
beq @9
; smooth scroll DLI
FCC4: pha
lda COLOR2
.byte $4D ; force absolute addressing mode for EOR $4F
.word $4F
.byte $2D ; force absolute addressing mode for AND $4E
.word $4E
sta WSYNC
sta COLPF1
pla
rti
.byte 0,0 ; waste 2 bytes
jmp F983 ; waste 3 bytes
; ********************************************************
; ** **
; ** Device Handler Initialization Code for device C: **
; ** **
; ********************************************************
CIN: lda #<1484 ; 1484 <--> 600 baud
sta CBAUDL
lda #>1484
sta CBAUDH
; *****************
; ** **
; ** Special C: **
; ** **
; *****************
FCE5: rts ; patched by XL-IT!
; ***************
; ** **
; ** Open C: **
; ** **
; ***************
FCE6: lda ICAX2Z ; patched by XL-IT!
sta $3E
lda ICAX1Z
and #12
cmp #4
beq CSOPI
cmp #8
beq FD34
rts
CSOPI: lda #0
sta WMODE ; 'read'
sta $3F
lda #1
jsr FDFC
bmi FD2E
FD05: lda #$34
sta PACTL
ldx PALNTS
ldy FE93,X
lda FE91,X
tax
lda #3
sta $22A
jsr SETVBV
FD1B: lda $22A
bne FD1B
lda #$80
sta $3D
sta $28A
jmp FD77
FD2A: ldy #$80
dec BRKKEY
FD2E: lda #0 ; 'read'
sta WMODE
rts
FD34: lda #$80 ; 'write'
sta WMODE
lda #2
jsr FDFC
bmi FD2E
lda #<1484 ; set baudrate
sta $D204
lda #>1484
sta $D206
lda #$60
sta DDEVIC
jsr SENDEV
lda #$34
sta PACTL
ldx PALNTS
ldy FE8F,X
lda FE8D,X
tax
lda #3
jsr SETVBV
lda #$FF
sta $22A
FD6A: lda BRKKEY
beq FD2A
lda $22A
bne FD6A
lda #0
sta $3D
FD77: ldy #1
FD79: rts
; **************
; ** **
; ** Get C: **
; ** **
; **************
FD7A: lda $3F ; PATCHED BY XL-IT!
bmi FDB1 ; LDY #136; RTS
ldx $3D
cpx $28A
beq RBLOK
lda $400,X
inc $3D
ldy #1
FD8C: rts
RBLOK: lda #'R' ; read command
jsr FE3F
tya
bmi FD8C
lda #0
sta $3D
ldx #$80
lda $3FF
cmp #$FE
beq @2
cmp #$FA
bne @1
ldx $47F
@1: stx $28A
jmp FD7A
@2: dec $3F
FDB1: ldy #$88
rts
; **************
; ** **
; ** Put C: **
; ** **
; **************
FDB4: ldx $3D ; PATCHED BY XL-IT!
sta $400,X
inc $3D
ldy #1
cpx #$7F
beq @1
rts
@1: lda #$FC
jsr FE7C
lda #0
sta $3D
rts
; ****************
; ** **
; ** Status C: **
; ** **
; ****************
FDCC: ldy #1 ; PATCHED BY XL-IT!
FDCE: rts
; ****************
; ** **
; ** Close C: **
; ** **
; ****************
FDCF: lda $289 ; PATCHED BY XL-IT!
bmi FDDC
ldy #1
FDD6: lda #%00111100
sta PACTL
rts
FDDC: ldx $3D
beq @1
stx $47F
lda #$FA
jsr FE7C
bmi FDD6
@1: ldx #$7F
lda #0
@2: sta $400,X
dex
bpl @2
lda #$FE
jsr FE7C
jmp FDD6
FDFC: sta $40
@1: lda $14
clc
ldx PALNTS
adc FE95,X
tax
@2: lda #$FF
sta CONSOL
lda #0
ldy #$F0 ; wait a bit ...
@3: dey
bne @3
sta CONSOL
ldy #$F0 ; wait a bit ...
@4: dey
bne @4
cpx $14
bne @2
dec $40
beq @6
txa
clc
ldx PALNTS
adc FE97,X
tax
@5: cpx $14 ; busy waiting
bne @5
beq @1
@6: jsr @7
tya
rts
@7: lda E424+1 ; JMP ($E424)+1 --> JMP $F2FD.
pha
lda E424
pha
rts
FE3F: sta DCOMND
lda #>131 ; 131 bytes per record
sta DBYTHI
lda #<131
sta DBYTLO
lda #>CASBUF ; cassette buffer
sta DBUFHI
lda #<CASBUF
sta DBUFLO
lda #$60
sta DDEVIC
lda #0
sta DUNIT
lda #$23
sta DTIMLO
lda DCOMND
ldy #$40
cmp #$52
beq @1
ldy #$80
@1: sty DSTATS
lda $3E
sta DAUX2
jsr SIOV
rts
FE7C: sta $3FF
lda #%01010101 ; bit pattern!
sta CASBUF
sta CASBUF+1
lda #'W' ; write command
jsr FE3F
rts
; Timing stuff
FE8D: .byte $04,$03
FE8F: .byte $80,$C0
FE91: .byte $02,$01
FE93: .byte $40,$E0
FE95: .byte $1E,$19
FE97: .byte $0A,$08
; ********************************************************
; ** **
; ** Device Handler Initialisation Code for device P: **
; ** **
; ********************************************************
PIN: lda #30
sta PTIMOT
rts
FE9F: .word $2EA
FEA1: .word $3C0
; status P:
FEA3: lda #4
sta $2DF
ldx FE9F
ldy FE9F+1
lda #'S' ; status
sta DCOMND
sta DAUX1
jsr FF14
jsr SIOV
bmi FEC1
jsr FF44
FEC1: rts
; open P:
FEC2: jsr FEA3
lda #0
sta PBPNT
FECA: rts
; put P:
FECB: pha
lda ICDNO,X
sta ICDNOZ
jsr FF4B
ldx PBPNT
pla
sta $3C0,X
inx
cpx PBUFSZ
beq FEF6
stx PBPNT
cmp #$9B
beq FEEB
ldy #1
rts
FEEB: lda #$20
FEED: sta $3C0,X
inx
cpx PBUFSZ
bne FEED
FEF6: lda #0
sta PBPNT
ldx FEA1
ldy FEA1+1
jsr FF14
jmp SIOV
; close P:
FF07: jsr FF4B
lda #$9B
ldx PBPNT
bne FEED
ldy #1
rts
FF14: stx DBUFLO
sty DBUFHI
lda #$40 ; printer 1 ID
sta DDEVIC
lda ICDNOZ
sta DUNIT
lda #$80
ldx DCOMND
cpx #'S' ; COMMAND == STATUS ?
bne @1
lda #$40 ; yes!
@1: sta DSTATS
lda PBUFSZ
sta DBYTLO
lda #0
sta DBYTHI
lda PTIMOT
sta DTIMLO
rts
FF44: lda DVSTAT+2
sta PTIMOT
rts
FF4B: ldy #'W'
lda ICAX2Z
@1: cmp #'N'
bne @2
ldx #'('
bne @4
@2: cmp #'D'
bne @3
ldx #$14
bne @4
@3: cmp #'S'
bne @5
ldx #29
@4: stx PBUFSZ
sty DCOMND
sta DAUX1
rts
@5: lda #$4E
bne @1
; **********************
; ** **
; ** Checksum Stuff **
; ** **
; **********************
VFR: ldx #0 ; clear checksum value
stx $8B
stx $8C
@1: jsr FFA9 ; calculate checksum of 1st 8K ROM:
cpx #12 ; C000-CFFF + 5000-57FF + D800-DFFF
bne @1
lda C000 ; checksum of first ROM
ldx C000+1
; patched by XL-IT! to: CLC/RTS
FF86: cmp $8B ; carry = ( A==$8B && X==$8C )
bne @1
cpx $8C
bne @1
clc ; clear carry means OK
rts
@1: sec ; set carry means ERROR
rts
VSR: ldx #0 ; clear checksum value
stx $8B
stx $8C
ldx #12
jsr FFA9 ; calculate checksum of 2nd 8K ROM:
jsr FFA9 ; E000-FFF7 + FFFA-FFFF
lda FFF8
ldx FFF8+1
jmp FF86 ; carry = ( A==$8B && X==$8C )
FFA9: ldy #0 ; copy 4 checksum-specifier bytes -> $9E..$9A1
@1: lda FFD7,X
sta $9E,Y
inx ; advance to next checksum
iny
cpy #4
bne @1
ldy #0 ; add ($9E) -> $8B
@2: clc
lda ($9E),Y
adc $8B
sta $8B
bcc @3
inc $8C ; advance ($9E)
@3: inc $9E
bne @4
inc $9F
@4: lda $9E
cmp $A0 ; repeat until $9E-ptr == $A0-ptr
bne @2
lda $9F
cmp $A1
bne @2
rts ; return
; checksums
FFD7: .word $C002,$D000
.word $5000,$5800
.word $D800,$E000
.word $E000,$FFF8
.word $FFFA,$0000
.byte 0,0,0
; ROM identification
.byte $10,$05,$83 ; revision date: October 5th, 1983
.byte $02 ; option byte
.byte 'B','B',0,0,1 ; part number: BB001
.byte $02 ; revision number
FFF8: .word $6C8C ; checksum
; ***************************************
; ** **
; ** 6502 HARDWARE INTERRUPT VECTORS **
; ** **
; ***************************************
FFFA: .word C018 ; address of 6502 Non-Maskable Interrupt (NMI) handler
FFFC: .word C2AA ; address of 6502 Reset (RST) handler
FFFE: .word C02C ; address of 6502 Interrupt Request (IRQ) handler
; **********************************
; ** **
; ** END OF OPERATING SYSTEM ROM **
; ** **
; **********************************
.end