; ********************************************** ; ** ** ; ** 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+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 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+1 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 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 $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 # $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