;****************************************************************************** ; ; 1540 / 1541 ; ; This source code generates the ROM for the 1540 and 1541 in the address ; range $C000-$DFFF with the Commodore code 325302-01. ; ; .ba $C000 .by $97 .fb $AA, 255 ;****************************************************************************** ; ;** Turn LED on with checking drive ; in: - ; out: - ; used: A LedOn: ; [C100] sei lda #$F7 and PortB2 ; LED out pha lda DRVNMB ; drive 0? beq L_C110 ; yes -> pla ; no, LED out ora #$00 ; used to be LED drive 1 bne L_C113 L_C110: ; [C110] pla ora #$08 ; LED on L_C113: ; [C113] sta PortB2 cli rts ;****************************************************************************** ; ;** NOT USED ----> ;** Turn LED on [C118] sei lda #$08 ora PortB2 sta PortB2 cli rts ; <---- ;****************************************************************************** ; ;** Clear error flags ; in: - ; out: - ; used: A ClrErrorFlags: ; [C123] lda #$00 sta ERWORD sta ERLED rts ;****************************************************************************** ; ;** Prepare for LED flash after error ; in: - ; out: - ; used: A PrepLedFlash: ; [C12C] sei txa pha ; save X lda #$50 sta ERWORD ldx #$00 ; drive number lda A_FECA,X ; in this case value 8 sta ERLED ora PortB2 sta PortB2 ; LED on pla tax ; restore X cli rts ;****************************************************************************** ; ;** Interprete command from computer ; in: - ; out: - ; used: A X Y InterprCmnd: ; [C146] lda #$00 sta WBAM lda LSTDRV ; last drive number sta DRVNMB jsr OK2Buffer ; OK message in buffer lda ORGSA ; secundair address bpl L_C160 and #$0F cmp #$0F ; 15, command-channel ? beq L_C160 ; yes, -> jmp OPEN_N15 ; OPEN command L_C160: ; [C160] jsr ChkLineLength lda (INPPTR),Y ; get first char sta CHAR ; mark it ldx #$0B L_C16A: ; [C16A] lda TblCommands,X ; compare commands cmp CHAR ; with char beq L_C17A ; found, -> dex bpl L_C16A lda #$31 ; NOT found jmp OutputErrorMsg ; 31, 'syntax error' L_C17A: ; [C17A] stx INSTRU cpx #$09 ; commandnumber < 9 ? bcc L_C184 ; yes -> jsr ChkSyntax ; test for R, S or N L_C184: ; [C184] ldx INSTRU ; X = commandnumber lda CmdAddrLB,X sta TEMP0 lda CmdAddrHB,X sta TEMP1 jmp (TEMP0) ; jump to command ;****************************************************************************** ; ;** Prepare error msg after executing command ; in: - ; out: - ; used: A X Y Out_Err_msg: ; [C194] lda #$00 sta WBAM J_C199: ; [C199] lda ERWORD ; flag set? bne OutputErrorMsg ; yes, -> ldy #$00 tya sty TRACK OutputErrMsg2: sty SECTOR sty INPPTR jsr ErrMsg2Buf ; OK-message jsr ClrErrorFlags J_C1AD: ; [C1AD] lda DRVNMB sta LSTDRV ; mark as last drive tax lda #$00 sta $FF,X jsr EraseInputBuf ; clear inputbuffer jmp Close17_18 ; close internal channel ;****************************************************************************** ; ;** Erase input buffer ; in: - ; out: - ; used: A Y EraseInputBuf: ; [C1BD] ldy #$28 lda #$00 L_C1C1: ; [C1C1] sta CMDBUF,Y ; fill $0200 - $0228 with 0 dey bpl L_C1C1 rts ;****************************************************************************** ; ;** Output error msg (track and sector 0) OutputErrorMsg: ; [C1C8] ldy #$00 sty TRACK sty SECTOR jmp CreErrorMsg ; Accu contains errornumber ;****************************************************************************** ; ;** Check input line ChkInputLine: ; [C1D1] ldx #$00 stx FILTBL ; pointer to drivenumber lda #":" jsr SearchInputBuf ; Check line until : or end beq A_C1E2 ; not found, -> dey dey sty FILTBL ; points to drivenumber for : A_C1E2: ; [C1E2] jmp Get_Drv_Num ;****************************************************************************** ; ;** Check for a colon in the line ChkForColon: ; [C1E5] ldy #$00 ldx #$00 lda #":" jmp SearchInputBuf ;****************************************************************************** ; ;** Check the syntax of the line ; ; Settings of IMAGE ($028B) after check: ; ; bit meaning ; --- ------------------------- ; 7 found wildcard (Y=1) \ ; 6 more then one file implied (Y=1) | file #1 ; 5 Drive # specified | ; 4 filename given / ; 3 found wildcard (Y=1) \ ; 2 more then one file implied (Y=1) | file #2 ; 1 Drive # specified | ; 0 filename given / ChkSyntax: ; [C1EE] jsr ChkForColon bne Chk4DrvNum A_C1F3: ; [C1F3] lda #$34 jmp OutputErrorMsg ; 34, 'Syntax error' Chk4DrvNum: ; [C1F8] dey dey sty FILTBL ; points to drivenumber for : txa ; found ',' for ':' ? bne A_C1F3 ; yes, -> 'Syntax error' ChkWildcard: ; [C200] lda #"=" jsr SearchInputBuf txa ; found ',' ? beq L_C20A ; no, -> lda #$40 ; set bit 6 ... L_C20A: ; [C20A] ora #$21 ; ... and 0 and 5 sta IMAGE inx stx F1CNT stx F2CNT lda PATFLG ; found wildcard? beq L_C228 ; no, -> lda #$80 ora IMAGE sta IMAGE ; set bit 7 lda #$00 sta PATFLG ; reset wildcardflag L_C228: ; [C228] tya ; found '=' ? beq L_C254 ; no, -> sta FILTBL,X lda F1CNT ; number of ',' for '=' sign sta F2PTR lda #$8D ; shift CR jsr SearchInputBuf inx ; increment ',' counter stx F2CNT ; mark number of ',' dex lda PATFLG ; found wildcard? beq L_C245 ; no, -> lda #$08 ; set bit 3 L_C245: ; [C245] cpx F1CNT ; ',' after '=' ? beq L_C24C ; no, -> ora #$04 ; set bit 2 L_C24C: ; [C24C] ora #$03 ; set bit 0 and 1 eor IMAGE sta IMAGE ; flag syntax test L_C254: ; [C254] lda IMAGE ldx INSTRU and TblSyntax-8,X ; combine with checkbyte bne L_C260 ; faulty syntax, -> rts L_C260: ; [C260] sta ERWORD ; set error flag lda #$30 jmp OutputErrorMsg ; 30, 'Syntax error' ;****************************************************************************** ; ;** Search character in input buffer SearchInputBuf: ; [C268] sta CHAR ; mark char L_C26B: ; [C26B] cpy CMDSIZ ; end of line? bcs L_C29E ; yes, -> lda (INPPTR),Y ; get char from buffer iny cmp CHAR ; compare with char searched for beq L_C2A0 ; found, -> cmp #"*" beq L_C280 cmp #"?" bne L_C283 L_C280: ; [C280] inc PATFLG ; set wildcardflag L_C283: ; [C283] cmp #"," bne L_C26B ; no, -> tya sta FILTBL+1,X ; mark place of ',' lda PATFLG and #$7F ; wildcard? beq L_C299 ; no, -> lda #$80 sta COMFLG,X ; mark flag sta PATFLG ; mark as wildcard L_C299: ; [C299] inx ; increment ',' counter cpx #$04 ; alread 4 comma's? bcc L_C26B ; no, -> continue L_C29E: ; [C29E] ldy #$00 L_C2A0: ; [C2A0] lda CMDSIZ sta FILTBL+1,X ; set flag end-of-line lda PATFLG and #$7F ; wildcard? beq L_C2B1 ; no, -> lda #$80 sta COMFLG,X ; set flag L_C2B1: ; [C2B1] tya rts ;****************************************************************************** ; ;** Check line length pointer in command ChkLineLength: ; [C2B3] ldy INPPTR ; 0 ? beq L_C2CB dey ; 1 ? beq L_C2CA lda CMDBUF,Y ; get char from inputbuffer cmp #$0D ; 'CR' beq L_C2CB ; yes, -> end-of-line dey lda CMDBUF,Y ; get previous char cmp #$0D ; 'CR' beq L_C2CB ; yes, -> iny L_C2CA: ; [C2CA] iny ; reset to old value L_C2CB: ; [C2CB] sty CMDSIZ cpy #$2A ; check length instruction ldy #$FF bcc CLR_Flg_inp ; < 42 = OK, -> sty INSTRU lda #$32 jmp OutputErrorMsg ; 32, 'syntax error' = line too long ;****************************************************************************** ; ;** Clear flag for command input CLR_Flg_inp: ; [C2DC] ldy #$00 tya ; A := 0 sta INPPTR sta RecordSize sta TYPE sta TYPFLG sta CHNNUM sta F2PTR sta F1CNT sta F2CNT sta PATFLG sta ERWORD ldx #$05 L_C2FD: ; [C2FD] sta F2PTR,X ; flag line analyse sta DIRSECP-1,X sta BUFPTR-1,X sta DRVNUM-1,X sta COMFLG-1,X ; wildcard flags sta FILTRK-1,X sta FILSEC-1,X dex bne L_C2FD rts ;****************************************************************************** ; ;** Get drive number GetDrvNum: ; [C312] lda F2CNT ; number of comma's sta F1CNT ; mark R_C318: ; [C318] lda #$01 sta F2CNT ; only ONE drive sta F2PTR GetDrvNum2: ; [C320] ldy LSTDRV ldx #$00 L_C325: ; [C325] stx CHNNUM lda FILTBL,X ; place of ':' jsr Search_DrvNum ; get drive number for : ldx CHNNUM sta FILTBL,X ; store exact place tya sta DRVNUM,X ; store drive number inx cpx F2CNT ; done for every drive? bcc L_C325 ; no, -> (in fact never: R_C318) rts ;****************************************************************************** ; ;** Search for drive number ;- out: Y contains drivenumber Search_DrvNum: ; [C33C] tax ; mark R_C33D: ; [C33D] ldy #$00 lda #":" cmp CMDBUF+1,X ; this place? beq L_C352 ; yes, -> cmp CMDBUF,X ; this place? bne L_C361 ; no, -> inx L_C34C: ; [C34C] tya ; A := 0 (R_C33D) L_C34D: ; [C34D] and #$01 ; filter drive number L_C34F: ; [C34F] tay txa rts L_C352: ; [C352] lda CMDBUF,X ; get drive number inx inx cmp #"0" beq L_C34D cmp #"1" beq L_C34D bne L_C34C ; use last drive, always -> L_C361: ; [C361] tya ora #$80 ; set bit 7, not sure of drive and #$81 ; clear bit 1..6 bne L_C34F ; always -> ;****************************************************************************** ; ;** Get drive number Get_Drv_Num: ; [C368] lda #$00 sta IMAGE ; clear syntax flag ldy FILTBL ; place in commandline A_C370: ; [C370] lda (INPPTR),Y ; get char jsr ChkDriveNum ; Number is sure? bpl L_C388 ; yes, -> iny ; increment pointer cpy CMDSIZ ; end of line? bcs L_C383 ; yes, -> ldy CMDSIZ dey ; only one character? bne A_C370 ; no, -> L_C383: ; [C383] dec IMAGE lda #$00 L_C388: ; [C388] and #$01 sta DRVNMB jmp LedOn ;****************************************************************************** ; ;** Reverse drive number ReverseDriveNum: ; [C38F] lda DRVNMB eor #$01 and #$01 sta DRVNMB rts ;****************************************************************************** ; ;** Check filetype ChkFileType: ; [C398] ldy #$00 lda F1CNT ; found '=' sign cmp F2CNT beq L_C3B8 ; no, -> dec F2CNT ldy F2CNT ; get pointer lda FILTBL,Y tay lda (INPPTR),Y ; get char behind '=' ldy #$04 L_C3B0: ; [C3B0] cmp TblFileTyp,Y ; compare with 'S', 'P', 'U', 'R' beq L_C3B8 ; same, -> dey ; all possible types? bne L_C3B0 ; no, -> ; if not found, filetype 'DEL' is assumed L_C3B8: ; [C3B8] tya sta TYPFLG ; note file type (0-4) rts ;****************************************************************************** ; ;** Check drive number ChkDriveNum: ; [C3BD] cmp #"0" beq L_C3C7 cmp #"1" beq L_C3C7 ora #$80 ; set bit 7 = type not sure L_C3C7: ; [C3C7] and #$81 rts ;****************************************************************************** ; ;** Verify drive number VerifyDrvNum: ; [C3CA] lda #$00 sta TEMP0 sta DRVFLG pha ldx F2CNT ; number of drives (1541: 1) L_C3D5: ; [C3D5] pla ora TEMP0 pha ; 0, lda #$01 sta TEMP0 dex ; next drive bmi L_C3EF lda DRVNUM,X bpl L_C3E8 ; >= 0, -> asl TEMP0 ; TEMP0 := 2 asl TEMP0 ; TEMP0 := 4 L_C3E8: ; [C3E8] lsr bcc L_C3D5 ; bit 0 was 0, -> asl TEMP0 ; TEMP0 := 2 / 8 bne L_C3D5 ; always -> L_C3EF: ; [C3EF] pla tax lda FlagDrvTest-1,X ; get syntax flag pha and #$03 sta DRVCNT pla asl bpl L_C43C lda DRVNUM L_C400: ; [C400] and #$01 sta DRVNMB lda DRVCNT beq L_C434 jsr InitDrive beq L_C420 ; no error, -> jsr ReverseDriveNum ; go to other drive lda #$00 sta DRVCNT jsr InitDrive beq L_C439 ; no error, -> L_C41B: ; [C41B] lda #$74 jsr OutputErrorMsg ; 74, 'drive not ready' L_C420: ; [C420] jsr ReverseDriveNum jsr InitDrive php ; save state jsr ReverseDriveNum plp beq L_C439 ; no error, -> lda #$00 sta DRVCNT beq L_C439 ; always -> L_C434: ; [C434] jsr InitDrive bne L_C41B ; if error, -> L_C439: ; [C439] jmp LedOn L_C43C: ; [C43C] rol ; drivenumber from carry to bit 0 jmp L_C400 ;****************************************************************************** ; ;** Flags for drive check FlagDrvTest: ; [C440] .by $00, $80, $41, $01, $01, $01, $01, $81 .by $81, $81, $81, $42, $42, $42, $42 ;****************************************************************************** ; ;** Search for file in directory SrchFileDir: ; [C44F] jsr VerifyDrvNum L_C452: ; [C452] lda #$00 sta DELIND jsr Read1stDirBlk ; read first directory block bne L_C475 ; found something, -> L_C45C: ; [C45C] dec DRVCNT ; more drives? bpl L_C462 ; yes, -> rts L_C462: ; [C462] lda #$01 ; go for other drive sta DRVFLG jsr ReverseDriveNum jsr LedOn jmp L_C452 L_C470: ; [C470] jsr NxtFileInDir beq L_C485 ; not found, -> L_C475: ; [C475] jsr TstInputDir lda FOUND beq L_C47E ; more files, -> rts L_C47E: ; [C47E] lda ENTFND ; file found? bmi L_C470 ; no, -> bpl L_C475 ; yes, -> L_C485: ; [C485] lda FOUND beq L_C45C ; file found, -> rts ;****************************************************************************** ; ;** Search next file in directory SrchNxtFileDir: ; [C48B] jsr ReadNxtDirBlk beq L_C4AA ; not found, -> bne L_C4BA ; found, -> L_C492: ; [C492] lda #$01 sta DRVFLG jsr ReverseDriveNum jsr LedOn SrchDirEntry: ; [C49D] lda #$00 sta DELIND jsr Read1stDirBlk bne L_C4BA ; if found, -> sta FOUND L_C4AA: ; [C4AA] lda FOUND bne L_C4D7 ; found, -> RTS dec DRVCNT bpl L_C492 ; try other drive, -> rts ;****************************************************************************** ; ;** Search next directory item SrchNxtDirEnt: ; [C4B5] jsr NxtFileInDir beq L_C4AA ; not found, -> L_C4BA: ; [C4BA] jsr TstInputDir ldx ENTFND ; found file? bpl L_C4C9 ; yes, -> lda FOUND beq SrchNxtDirEnt ; no, -> bne L_C4D7 ; yes, ready -> RTS L_C4C9: ; [C4C9] lda TYPFLG ; DEL? beq L_C4D7 ; yes, ready -> RTS lda COMFLG,X ; filetype and #$07 cmp TYPFLG ; like wanted type? bne SrchNxtDirEnt ; no, -> L_C4D7: ; [C4D7] rts ;****************************************************************************** ; ;** Check input in directory TstInputDir: ; [C4D8] ldx #$FF stx ENTFND ; flag file found inx stx PATFLG ; erase joker flag jsr SetPtrToFile ; any file found? beq L_C4EC ; yes, -> L_C4E6: ; [C4E6] rts L_C4E7: ; [C4E7] jsr PtrToNxtFile bne L_C4E6 ; no file, ready -> L_C4EC: ; [C4EC] lda DRVNMB eor DRVNUM,X lsr bcc L_C4FE ; if bit 0 was 0, -> and #$40 ; standard drive? beq L_C4E7 ; yes, -> lda #$02 cmp DRVCNT ; search on both drives beq L_C4E7 ; yes, -> L_C4FE: ; [C4FE] lda FILTBL,X ; check next file name tax jsr GetLengthName ; get length filename ldy #$03 jmp L_C51D L_C50A: ; [C50A] lda CMDBUF,X ; get char from instruction buffer cmp (DIRBUF),Y ; same char in directory? beq L_C51B ; yes, -> cmp #"?" ; wildcard? bne L_C4E7 ; no, -> next file lda (DIRBUF),Y cmp #$A0 ; shifted space beq L_C4E7 ; no, -> next file L_C51B: ; [C51B] inx ; increment pointer iny L_C51D: ; [C51D] cpx LIMIT ; end of name in instruction? bcs L_C52B ; yes, -> lda CMDBUF,X cmp #"*" ; wildcard? beq L_C535 ; yes, -> found file bne L_C50A ; no, continue search, always -> L_C52B: ; [C52B] cpy #$13 ; CR = end of name? bcs L_C535 ; yes, -> lda (DIRBUF),Y cmp #$A0 ; shifted space bne L_C4E7 ; no, name is longer -> ;****************************************************************************** ; ;** Found file L_C535: ; [C535] ldx F2PTR ; position of the found file stx ENTFND lda COMFLG,X ; filetype and #$80 sta PATFLG lda INDEX sta BUFPTR,X lda SECTOR ; sectornumber of directory sta DIRSECP,X ; in tabels ldy #$00 lda (DIRBUF),Y ; filetype iny pha and #$40 ; isolate lock-bit ... sta TEMP0 ; ... and save pla and #$DF ; clear bit 5 bmi L_C55C ; if file open -> ora #$20 ; set bit 5 L_C55C: ; [C55C] and #$27 ; clear bit 3, 4 end 7 ora TEMP0 ; restore lock-bit sta TEMP0 lda #$80 and COMFLG,X ; isolate wildcard-flag ora TEMP0 sta COMFLG,X lda DRVNUM,X and #$80 ora DRVNMB sta DRVNUM,X lda (DIRBUF),Y ; first track of file sta FILTRK,X iny lda (DIRBUF),Y ; first sector of file sta FILSEC,X lda RecordSize ; do we have length of record? bne SetPtrToFile ; yes, -> ;* Get length of record ldy #$15 lda (DIRBUF),Y sta RecordSize ;****************************************************************************** ; ;** Set pointer to file SetPtrToFile: ; [C589] lda #$FF sta FOUND lda F2CNT sta F2PTR PtrToNxtFile: dec F2PTR ; [C594] bpl L_C59A rts L_C59A: ; [C59A] ldx F2PTR lda COMFLG,X ; wildcard-flag is set? bmi L_C5A6 ; yes, -> lda FILTRK,X ; track number is set? bne PtrToNxtFile ; yes, -> L_C5A6: ; [C5A6] lda #$00 sta FOUND rts ;****************************************************************************** ; ;** Read first directory Block Read1stDirBlk: ; [C5AC] ldy #$00 sty DELSEC dey sty ENTFND lda DirTrack ; track with directory sta TRACK lda #$01 sta SECTOR sta LSTBUF jsr ReadSeqFile J_C5C4: ; [C5C4] lda LSTBUF ; last sector? bne L_C5CA ; no, -> rts L_C5CA: ; [C5CA] lda #$07 sta FILCNT ; number of dir entries (-1) lda #$00 jsr GetAthByte ; get byte from buffer sta LSTBUF ; mark as track J_C5D7: ; [C5D7] jsr SetBufPointer dec FILCNT ; decrement entry counter ldy #$00 lda (DIRBUF),Y ; first byte of directory = filetype bne L_C5FB ; if not deleted, -> lda DELSEC bne NxtFileInDir jsr GetTrackSector lda SECTOR sta DELSEC lda DIRBUF ; bufferpointer ldx DELIND sta DELIND beq NxtFileInDir rts L_C5FB: ; [C5FB] ldx #$01 cpx DELIND ; bufferpointer = 1 ? bne L_C62F ; no, -> beq NxtFileInDir ; yes, always -> ;****************************************************************************** ; ;** Read next directory Block ReadNxtDirBlk: ; [C604] lda DirTrack sta TRACK lda DIRSEC sta SECTOR jsr ReadSeqFile lda INDEX jsr SetBufPointer3 ;****************************************************************************** ; ;** Search for next file in directory NxtFileInDir: ; [C617] lda #$FF sta ENTFND ; erase flag "found file" lda FILCNT ; searched all dir-entries? bmi L_C629 ; yes, -> lda #$20 jsr IncBufPointer jmp J_C5D7 L_C629: ; [C629] jsr RdNxtBlock ; set pointer jmp J_C5C4 ; read dir next block L_C62F: ; [C62F] lda DIRBUF sta INDEX jsr GetTrackSector lda SECTOR sta DIRSEC ; mark sector rts ;****************************************************************************** ; ;** Test and initialize drive InitDrive: ; [C63D] lda AUTOFG ; auto-initialization (= read BAM) ? bne A_C669 ; no, -> ldx DRVNMB lsr WPSW0,X ; disk changed? bcc A_C669 ; no, -> done lda #$FF sta JOBRTN ; set errorflag jsr ReadDirTrack ; read directorytrack ldy #$FF ; $FF = error cmp #$02 ; 20 'read error' ? beq A_C65F ; yes, -> cmp #$03 ; 21 'read error' ? beq A_C65F ; yes, -> cmp #$0F ; 74 'drive not ready' ? beq A_C65F ; yes, -> ldy #$00 ; no error A_C65F: ; [C65F] ldx DRVNMB tya ; error? sta $FF,X ; save error code bne A_C669 ; if error, -> jsr LoadBAM ; load BAM A_C669: ; [C669] ldx DRVNMB lda $FF,X ; load error code rts ;****************************************************************************** ; ;** Name of file in directory buffer ; in: ; A = maximum length ; X points to start of the name in CMDBUF FilNam2DirBuf: ; [C66E] pha ; Accu contains maximum length jsr GetLengthName jsr FilNam2Buf ; write filename in buffer pla sec sbc STRSIZ ; compare length with maximum length tax ; store difference in X beq A_C687 ; = 0, -> bcc A_C687 ; greater then maximum, -> ;* Add $A0 (shifted space) to end of name until maximum lda #$A0 A_C681: ; [C681] sta (DIRBUF),Y iny dex bne A_C681 A_C687: ; [C687] rts ;****************************************************************************** ; ;** Next subroutine is only called at $C672 FilNam2Buf: ; [C688] tya ; buffernumber asl A ; *2 => pointer tay lda BUFTABab,Y sta DIRBUF lda BUFTABab+1,Y sta DIRBUF+1 ldy #$00 A_C697: ; [C697] lda CMDBUF,X ; get character from buffer sta (DIRBUF),Y ; store in directory entry iny ; buffer full? beq A_C6A5 ; yes, -> inx cpx LIMIT ; check with maximum bcc A_C697 A_C6A5: ; [C6A5] rts ;****************************************************************************** ; ;** Search for end of name in command GetLengthName: ; [C6A6] lda #$00 sta STRSIZ txa ; save X pha A_C6AD: ; [C6AD] lda CMDBUF,X cmp #"," beq A_C6C8 ; end search -> cmp #"=" beq A_C6C8 ; end search -> inc STRSIZ inx lda #$0F ; 15 = (maximum length of name) - 1 cmp STRSIZ bcc A_C6C8 ; found 16 characters, -> cpx CMDSIZ ; compare with length of input bcc A_C6AD ; smaller, -> search on A_C6C8: ; [C6C8] stx LIMIT pla tax ; restore X rts ;****************************************************************************** ; ;** Directory entry in buffer GetDirEntry: ; [C6CE] lda SA pha lda CURCHN pha jsr GetDirEntry2 pla sta CURCHN pla sta SA rts ;****************************************************************************** ; ;** Create directory entry in buffer GetDirEntry2: ; [C6DE] lda #$11 sta SA jsr OpenChan4Read jsr SetBufPointer lda ENTFND ; found entry? bpl A_C6F7 ; yes, -> lda DRVFLG ; drive 1? bne A_C6FC ; yes, -> jsr BlocksFree clc rts A_C6F7: ; [C6F7] lda DRVFLG beq A_C71B A_C6FC: ; [C6FC] dec DRVFLG bne A_C70E dec DRVFLG jsr ReverseDriveNum jsr BlocksFree sec jmp ReverseDriveNum A_C70E: ; [C70E] lda #$00 sta NBTEMP1 ; HB number of blocks sta DRVFLG jsr DirHeader sec rts ; IMHO this routine roughly calculates the length of the number of blocks ; of a file and thus where the name, file type, etc. should be placed. A_C71B: ; [C71B] ldx #$18 ; length of entry ldy #$1D ; position HB number of blocks lda (DIRBUF),Y sta NBTEMP1 beq A_C728 ldx #$16 A_C728: ; [C728] dey ; position LB number of blocks lda (DIRBUF),Y sta NBTEMP0 cpx #$16 beq A_C73C cmp #10 ; number of blocks? bcc A_C73C ; <10 , -> dex cmp #100 ; <100 ? bcc A_C73C ; yes, -> dex A_C73C: ; [C73C] jsr ClrNameBuf lda (DIRBUF),Y ; A = filetype pha asl A ; lock bit set? bpl A_C74A ; no, -> lda #"<" sta NameBuffer+1,X A_C74A: ; [C74A] pla ; filetype and #$0F ; isolate bit 0..3 tay ; and use as index lda TblFileTyp+10,Y ; 3rd char of filetype sta NameBuffer,X dex lda TblFileTyp+5,Y ; 2nd char of filetype sta NameBuffer,X dex lda TblFileTyp,Y ; 1st char of filetype sta NameBuffer,X dex dex bcs A_C76B ; file closed, -> lda #"*" ; file open mark sta NameBuffer+1,X A_C76B: ; [C76B] lda #$A0 ; fill with shifted space sta NameBuffer,X dex ; Copy the file name ldy #$12 A_C773: ; [C773] lda (DIRBUF),Y sta NameBuffer,X dex dey cpy #$03 bcs A_C773 lda #'"' ; " before file name sta NameBuffer,X ; Replace shifted space with normal space by cleraing bit 7 A_C783: ; [C783] inx cpx #$20 ; ???? bcs A_C793 lda NameBuffer,X cmp #'"' beq A_C793 cmp #$A0 ; shifted space? bne A_C783 ; no, -> A_C793: ; [C793] lda #'"' ; yes, replace sta NameBuffer,X A_C798: ; [C798] inx cpx #$20 bcs A_C7A7 lda #$7F and NameBuffer,X ; erase bit 7 sta NameBuffer,X ; in remaining chars bpl A_C798 ; always -> A_C7A7: ; [C7A7] jsr SrchNxtDirEnt sec rts ;****************************************************************************** ; ;** Clear the reserved space for the name of the disk ClrNameBuf: ; [C7AC] ldy #$1B ; total length lda #' ' A_C7B0: ; [C7B0] sta NameBuffer-1,Y dey bne A_C7B0 rts ;****************************************************************************** ; ;** Create header with disk name DirHeader: ; [C7B7] jsr GetBufNumBAM jsr ReadBAM jsr ClrNameBuf lda #$FF sta TEMP0 ; ??? where used ??? ; Output the drive number in front of the disk label ldx DRVNMB stx NBTEMP0 lda #$00 sta NBTEMP1 ldx ActBufNum lda BufAddrHB,X sta DIRBUF+1 lda LengthBAM ; $90, position of disk name sta DIRBUF ldy #$16 lda (DIRBUF),Y ; read char of disk name cmp #$A0 ; shifted space? bne A_C7ED ; no, -> lda #"1" .by $2C ; dummy BIT opcode A_C7E5: ; [C7E5] lda (DIRBUF),Y cmp #$A0 ; shifted space? bne A_C7ED ; no, -> lda #' ' A_C7ED: ; [C7ED] sta NameBuffer+2,Y dey bpl A_C7E5 lda #$12 ; Reverse ON sta NameBuffer lda #'"' sta NameBuffer+1 ; write " before and ... sta NameBuffer+18 ; ... behind disk name lda #' ' sta NameBuffer+19 ; add space rts ;****************************************************************************** ; ;** Create last line = ... BLOCKS FREE BlocksFree: ; [C806] jsr ClrNameBuf ldy #$0B A_C80B: ; [C80B] lda TxtBlocksFree,Y sta NameBuffer,Y dey bpl A_C80B jmp NumBlocksFree TxtBlocksFree: ; [C817] .tx "BLOCKS FREE." ;****************************************************************************** ; ;** S - Scratch command Scratch: ; [C823] jsr ChkFileType jsr GetDrvNum2 jsr VerifyDrvNum lda #$00 sta R0 ; counter erased files jsr SrchDirEntry bmi A_C872 ; not found, -> A_C835: ; [C835] jsr IsFileOpen bcc A_C86D ; yes, -> ldy #$00 lda (DIRBUF),Y ; filetype and #$40 ; LOCK-bit set? bne A_C86D ; yes, -> jsr DelDirEntry ; delete entry ldy #$13 lda (DIRBUF),Y ; tracknumber of first side-sector beq A_C855 ; does not exist, -> sta TRACK iny lda (DIRBUF),Y ; sector number sta SECTOR jsr DelSectorChain ; delete all side-sectors A_C855: ; [C855] ldx ENTFND ; file number lda #$20 and COMFLG,X ; file closed? bne A_C86B ; no, -> lda FILTRK,X sta TRACK lda FILSEC,X sta SECTOR jsr DelSectorChain ; delete file A_C86B: ; [C86B] inc R0 ; increase number of erased files A_C86D: ; [C86D] jsr SrchNxtFileDir ; another file? bpl A_C835 ; yes, -> A_C872: ; [C872] lda R0 sta TRACK lda #$01 ldy #$00 jmp OutputErrMsg2 ; message "FILES SCRATCHED" ;****************************************************************************** ; ;** Erase file DelSectorChain: ; [C87D] jsr FreeSector ; free block in BAM jsr ReadSeqFile jsr GetBufNumBAM ; get buffer number in BAM lda BUF0CH1zp,X cmp #$FF ; buffer not used? beq J_C894 ; yes, -> lda WBAM ora #$40 sta WBAM J_C894: ; [C894] lda #$00 jsr SetBufPointer3 ; buffer pointer to zero jsr ReadBuffer2A ; get track sta TRACK jsr ReadBuffer2A ; get sector sta SECTOR lda TRACK ; last sector? bne A_C8AD ; no, -> jsr WriteBam ; write BAM jmp CloseChannel ; close channel A_C8AD: ; [C8AD] jsr FreeSector ; free block in BAM jsr RdNxtBlock ; read next block jmp J_C894 ; and continue ;****************************************************************************** ; ;** Erase dir entry DelDirEntry: ; [C8B6] ldy #$00 tya sta (DIRBUF),Y ; set file type to zero jsr WriteSector3 ; write block jmp VerifyExec ; and check ;****************************************************************************** ; ;** D - Backup command (UNUSED) SyntaxError: ; [C8C1] lda #$31 jmp OutputErrorMsg ; 31, 'syntax error' ;****************************************************************************** ; ;** Format disk FormatFloppy: ; [C8C6] lda #$4C ; JMP-command sta BUF3 lda #<(E_FAC7) sta BUF3+1 lda #>(E_FAC7) sta BUF3+2 ; "JMP $FAC7" in $600 ... $602 lda #$03 jsr Par2DiskCtrl2 ; set parameters lda DRVNMB ; drive number ora #$E0 ; command code for formatting sta JOBSzp+3 ; transmit A_C8E0: ; [C8E0] lda JOBSzp+3 bmi A_C8E0 ; wait until formatting done cmp #$02 bcc A_C8EF ; smaller than two, then ok lda #$03 ldx #$00 jmp PrepErrMsg ; 21, 'read error' A_C8EF: ; [C8EF] rts ;****************************************************************************** ; ;** C - Copy command Copy: ; [C8F0] lda #$E0 sta BUFUSEL jsr ClearTBAM jsr GetBufNumBAM ; get buffer number of BAM lda #$FF sta BUF0CH1zp,X lda #$0F sta LINUSE jsr ChkForColon ; disk involved? bne A_C90C ; no, -> jmp SyntaxError ; 31, 'syntax error' A_C90C: ; [C90C] jsr Chk4DrvNum ; check input jsr GetDrvNum2 ; test drive number lda IMAGE ; flag for syntax check and #$55 ; normal copy? bne A_C928 ; yes, -> ldx FILTBL lda CMDBUF,X ; character of the command cmp #'*' ; all files? bne A_C928 ; no, -> A_C923: ; [C923] lda #$30 jmp OutputErrorMsg ; 30, 'syntax error' A_C928: ; [C928] lda IMAGE ; syntax flag and #$D9 bne A_C923 ; 30, 'syntax error' jmp J_C952 ;****************************************************************************** ; ;** Parameters for copying a whole disk. Not used in a 1541 E_C932: ; [C932] lda #$00 sta RecordSize sta DRVCNT ; number of drives sta FILTRK ; track number in directory sta FILTRK+1 lda DRVNUM+1 and #$01 sta DRVNMB ; drive number ora #$01 sta DELSEC ; sector number lda FILTBL+1 sta FILTBL rts J_C952: ; [C952] jsr SrchFileDir ; search for file in directory lda F2CNT ; number of filenames in command cmp #$03 ; smaller than three? bcc A_C9A1 ; yes, -> lda DRVNUM ; first drive number cmp DRVNUM+1 ; second drive number bne A_C9A1 ; not on same drive? lda BUFPTR ; directory block of the 1st file cmp BUFPTR+1 ; same directory block as second file? bne A_C9A1 ; no, -> lda DIRSECP ; directory sector of first file cmp DIRSECP+1 ; same directory sector as second file? bne A_C9A1 ; no, -> jsr IsFilePresent ; is file present? lda #$01 sta F2PTR jsr ReadDirSec jsr CheckREL ; get data type beq A_C982 ; REL file? yes cmp #$02 ; prg-file? bne A_C987 ; no, -> A_C982: ; [C982] lda #$64 jsr OutputErrorMsg ; 64, 'file type mismatch' A_C987: ; [C987] lda #$12 ; 18 sta SA ; secondary address lda LINTAB+17 sta LINTAB+18 lda #$FF sta LINTAB+17 jsr Prep4Append ; prepare append ldx #$02 jsr CopyFile2 ; copy file jmp Out_Err_Msg ; done A_C9A1: ; [C9A1] jsr CopyFile1 ; copy file jmp Out_Err_Msg ; done ;** CopyFile1: ; [C9A7] jsr Chk2Filenames lda DRVNUM ; drive number of first file and #$01 sta DRVNMB ; drive number jsr OpenWrChannel jsr CreDirEntry ; enter file in directory ldx F1CNT ;** CopyFile2: ; [C9B9] stx F2PTR jsr ReadDirSec lda #$11 ; 17 sta SA jsr OpenChan4Read jsr CheckREL ; get data type bne A_C9CE ; no REL file? jsr InitSideSec A_C9CE: ; [C9CE] lda #$08 sta EOIFLG jmp J_C9D8 A_C9D5: ; [C9D5] jsr WrData2Buffer ; write byte in buffer J_C9D8: ; [C9D8] jsr OpenChnGetByt ; and get byte lda #$80 jsr ChkFTypeBit ; test bit 7 beq A_C9D5 ; not set? jsr CheckREL ; check file type beq A_C9EA ; REL file? jsr WrData2Buffer ; get data byte in buffer A_C9EA: ; [C9EA] ldx F2PTR inx cpx F2CNT bcc CopyFile2 lda #$12 ; 18 sta SA jmp CloseFile ; close channel ;****************************************************************************** ; ;** Open an internal channel for reading a directory block/file ReadDirSec: ; [C9FA] ldx F2PTR lda DRVNUM,X ; drive number and #$01 sta DRVNMB ; save lda DirTrack ; 18, directory track sta TRACK ; save lda DIRSECP,X ; directory sector sta SECTOR jsr ReadSeqFile ; read block ldx F2PTR lda BUFPTR,X ; pointer in block jsr SetBufPointer3 ; set buffer pointer ldx F2PTR lda COMFLG,X ; file type and #$07 ; isolate sta TYPE ; and save lda #$00 sta RecordSize jsr Open1stSidSec ; get parameters for REL file ldy #$01 jsr CheckREL ; get file type beq A_CA31 ; REL file? iny A_CA31: ; [CA31] tya jmp SetBufPointer3 ; set buffer pointer ;****************************************************************************** ; ;** Open channel 17 and get a byte OpenChnGetByt: ; [CA35] lda #$11 ; 11 sta SA ; open channel and get byte OpenChnGetByt2: ; [CA39] jsr GetByte sta DATA ldx CURCHN ; channel number lda REWRFLzp,X and #$08 ; isolate end marker sta EOIFLG bne A_CA52 ; not set? jsr CheckREL ; REL file? beq A_CA52 ; no, -> lda #$80 jsr SetFlags ; set bit 7 = last record A_CA52: ; [CA52] rts InitSideSec: jsr GetDrvNum3 ; set drive number jsr SetPar2LstSSec lda PtrSideSec pha lda NumSidSec pha lda #$12 ; 18 sta SA jsr OpenChan4Write ; open write channel jsr GetDrvNum3 ; set drive number jsr SetPar2LstSSec jsr Record2Buffer lda PtrSideSec sta R1 lda NumSidSec sta R0 lda #$00 sta R2 sta RecordPos sta RelPointer pla sta NumSidSec pla sta PtrSideSec jmp J_E33B ;****************************************************************************** ; ;** R - Rename command Rename: ; [CA88] jsr GetDrvNum2 ; get drive number from command line lda DRVNUM+1 and #$01 sta DRVNUM+1 ; 2nd drive number cmp DRVNUM ; compare with 1st drive number beq A_CA97 ; same? ora #$80 A_CA97: ; [CA97] sta DRVNUM jsr SrchFileDir ; search for file in directory jsr Chk2Filenames ; does name exist? lda DRVNUM+1 and #$01 sta DRVNMB ; drive number lda DIRSECP+1 sta SECTOR ; sector number jsr ReadSector2 ; read block from directory jsr VerifyExec ; ok? lda BUFPTR+1 ; pointer to directory entry clc adc #$03 ; pointer plus 3 to file name jsr SetBufPointer3 ; set buffer pointer jsr GetBufNumber ; get buffer number tay ldx FILTBL lda #$10 ; 16 characters jsr FilNam2DirBuf ; write name in buffer jsr WriteSector3 ; write block to directory jsr VerifyExec ; ok? jmp Out_Err_Msg ; done, prepare disk status ;****************************************************************************** ; ;** Check if file present IsFilePresent: ; [CACC] lda COMFLG+1 ; file type and #$07 sta TYPE ; save ldx F2CNT A_CAD6: ; [CAD6] dex cpx F1CNT bcc A_CAE6 lda FILTRK,X ; track number of new file, erased? bne A_CAD6 ; no, -> lda #$62 jmp OutputErrorMsg ; 62, 'file not found' A_CAE6: ; [CAE6] rts ;****************************************************************************** ; ;** Check if two file names are the same Chk2Filenames: ; [CAE7] jsr IsFilePresent ; does file exist with old name? A_CAEA: ; [CAEA] lda FILTRK,X ; track number of new file, erased? beq A_CAF4 ; yes, -> lda #$63 jmp OutputErrorMsg ; 63, 'file exists' A_CAF4: ; [CAF4] dex bpl A_CAEA rts ;****************************************************************************** ; ;** M - Memory command Memory: ; [CAF8] lda CMDBUF+1 ; 2nd character from buffer cmp #'-' ; is '-'? (should be) bne A_CB4B ; no, -> error lda CMDBUF+3 sta TEMP0 ; address in $6F/$70 lda CMDBUF+4 sta TEMP1 ldy #$00 lda CMDBUF+2 ; 3rd character from buffer cmp #'R' ; M-R ? beq A_CB20 ; yes, -> jsr P_F258 ; (RTS) cmp #'W' beq A_CB50 ; to memory write cmp #'E' bne A_CB4B jmp (J_TEMP0) ; memory-execute ;****************************************************************************** ; ;** M-R memory read A_CB20: ; [CB20] lda (TEMP0),Y ; read byte sta DATA lda CMDSIZ ; length of command line cmp #$06 ; less than 6? bcc A_CB45 ; yes, -> ldx CMDBUF+5 ; number dex ; only one byte? beq A_CB45 ; yes, -> txa ; number of bytes clc adc TEMP0 ; plus start address inc TEMP0 sta ENDPNT+5 ; end pointer lda TEMP0 sta ERRPTR ; buffer pointer for error message lda TEMP1 ; set to start address for 'M-R' sta ERRPTR+1 jmp Byte2ErrChan ; byte out A_CB45: ; [CB45] jsr OpenChan4Read ; open read channel jmp J_D43A ; byte out A_CB4B: ; [CB4B] lda #$31 jmp OutputErrorMsg ; 31, 'syntax error' ;****************************************************************************** ; ;** M-W momory write A_CB50: ; [CB50] lda CMDBUF+6,Y ; read character sta (TEMP0),Y ; and save iny cpy CMDBUF+5 ; number of characters bcc A_CB50 ; all characters? rts ;****************************************************************************** ; ;** U - User command User: ; [CB5C] ldy CMDBUF+1 ; second char cpy #'0' bne E_CB6C ; no, -> ;****************************************************************************** ; ;** Initial setup USER JUMP vectortable SetVectorU0: ; [CB63] lda #<(UserVectors) sta USRJMP ; pointer to table of user-addresses lda #>(UserVectors) ; $FFEA sta USRJMP+1 rts E_CB6C: ; [CB6C] jsr UserExec jmp Out_Err_Msg ; done, prepare error message UserExec: dey tya and #$0F ; number asl A ; times 2 tay lda (USRJMP),Y ; as pointer in table sta IP iny ; address at $75/$76 lda (USRJMP),Y sta IP+1 jmp (J_IP) ; execute function ;****************************************************************************** ; ;** Open direct access channel, number OpenBlock: lda LSTDRV ; last drive number sta DRVNMB ; drive number lda SA ; channel number pha jsr InitDrive ; check drive and initialize pla sta SA ldx CMDSIZ ; length of filename dex bne A_CBA5 ; greater than one? lda #$01 jsr FindRdChanBuf ; layout buffer and channel jmp J_CBF1 ; set flags, done A_CBA0: ; [CBA0] lda #$70 jmp OutputErrorMsg ; 70, 'no channel' A_CBA5: ; [CBA5] ldy #$01 jsr GetCmdParms2 ; get buffer number ldx FILSEC ; buffer number cpx #$05 ; bigger than 4? bcs A_CBA0 ; yes, -> 'no channel' lda #$00 sta TEMP0 sta TEMP1 ;* Look for buffer and allocate it sec A_CBB8: ; [CBB8] rol TEMP0 rol TEMP1 dex bpl A_CBB8 lda TEMP0 and BUFUSEL ; found a free buffer? bne A_CBA0 ; no, -> lda TEMP1 and BUFUSEH ; found a free buffer? bne A_CBA0 ; no, -> lda TEMP0 ora BUFUSEL ; allocate it sta BUFUSEL lda TEMP1 ora BUFUSEH ; allocate it sta BUFUSEH lda #$00 jsr FindRdChanBuf ; search channel ldx CURCHN ; channel number lda FILSEC ; buffer number sta BUF0CH1zp,X tax lda DRVNMB ; drive number sta JOBSzp,X sta LSTJOB,X J_CBF1: ; [CBF1] ldx SA ; secondary address lda LINTAB,X ora #$40 sta LINTAB,X ldy CURCHN ; channel number lda #$FF sta ENDPNT,Y ; end pointer lda #$89 sta REWRFLab,Y ; set READ and WRITE flags lda BUF0CH1ab,Y ; buffer number sta OUTREG,Y asl A ; times 2 tax lda #$01 sta BUFTABzp,X ; buffer pointer to one lda #$0E sta DIACFLab,Y ; flag for direct access jmp Out_Err_Msg ; done ;****************************************************************************** ; ;** B - Block command Block: ; [CC1B] ldy #$00 ldx #$00 lda #'-' jsr SearchInputBuf ; search for minus sign, found? bne A_CC30 ; yes, -> A_CC26: ; [CC26] lda #$31 jmp OutputErrorMsg ; 31, 'syntax error' A_CC2B: ; [CC2B] lda #$30 jmp OutputErrorMsg ; 30, 'syntax error' A_CC30: ; [CC30] txa ; comma? bne A_CC2B ; yes, -> error ldx #$05 lda CMDBUF,Y ; char from buffer A_CC38: ; [CC38] cmp TxtAFRWEP,X ; compare with 'AFRWEP', found? beq A_CC42 ; yes, -> dex bpl A_CC38 ; compare with all characters bmi A_CC26 ; not found, error A_CC42: ; [CC42] txa ora #$80 ; command number, set bit 7 sta INSTRU jsr GetCmdParms ; get parameters lda INSTRU asl A ; number times 2 tax ; as index lda CmdAFRWEP+1,X ; address of command hi sta TEMP1 lda CmdAFRWEP,X ; address lo sta TEMP0 jmp (J_TEMP0) ; jump to command TxtAFRWEP: ; [CC5D] .tx "AFRWEP" ;****************************************************************************** ; ;** Addresses of block commands CmdAFRWEP: ; [CC63] .wo BlockAlloc ;** B-A .wo BlockFree ;** B-F .wo BlockRead ;** B-R .wo BlockWrite ;** B-W .wo BlockExec ;** B-E .wo BlockPoint ;** B-P ;****************************************************************************** ; ;** Get parameters from block commands ; parameters will look like: [:] channel#; unit; track; sector GetCmdParms: ; [CC6F] ldy #$00 ldx #$00 lda #':' jsr SearchInputBuf ; test line to colon bne GetCmdParms2 ; found? ldy #$03 ; no, begin at 4th character GetCmdParms2: ; [CC7C] lda CMDBUF,Y ; search for separating char cmp #' ' ; space found? beq A_CC8B ; yes, -> cmp #$1D ; cursor right? beq A_CC8B ; yes, -> cmp #',' ; comma? bne A_CC92 ; no, -> A_CC8B: ; [CC8B] iny cpy CMDSIZ ; line end? bcc GetCmdParms2 ; no, -> more rts A_CC92: ; [CC92] jsr Ascii2Dec ; preserve next parameter inc F1CNT ; increment parameter counter ldy F2PTR cpx #$04 ; compare with maximum number, smaller? bcc A_CC8B ; yes, -> OK bcs A_CC2B ; no, -> 30, 'syntax error' ;* Convert read ASCII character into decimal value Ascii2Dec: lda #$00 sta TEMP0 sta TEMP1 ; erase storage area decimal numbers sta TEMP3 ldx #$FF A_CCAB: ; [CCAB] lda CMDBUF,Y ; get characters from input buffer cmp #'@' ; number? bcs A_CCCA ; no, -> cmp #'0' ; number? bcc A_CCCA ; no, -> and #$0F ; convert ASCII digits to hex pha ; and save ; shift read values lda TEMP1 sta TEMP2 ; move digits one further lda TEMP0 sta TEMP1 pla sta TEMP0 ; note read number iny ; increment pointer in input buffer cpy CMDSIZ ; end of line reached? bcc A_CCAB ; no, -> A_CCCA: ; [CCCA] sty F2PTR ; save pointer clc lda #$00 A_CCD0: ; [CCD0] inx cpx #$03 bcs A_CCE4 ; convert hex digits to one byte ldy TEMP0,X A_CCD7: ; [CCD7] dey bmi A_CCD0 adc Decimal,X ; add decimal value bcc A_CCD7 clc inc TEMP3 bne A_CCD7 A_CCE4: ; [CCE4] pha ldx F1CNT ; counter for paramaters lda TEMP3 sta FILTRK,X ; track link table pla sta FILSEC,X ; sector link table rts ;****************************************************************************** ; ;** Decimal values Decimal: ; [CCF2] .by 1, 10, 100 ;****************************************************************************** ; ;** B-F block free BlockFree: jsr GetTrkSecDrv ; get track, sector and drive number jsr FreeSector ; free block jmp Out_Err_Msg ; done, prepare error message ;****************************************************************************** ; ;** B-A block allocate E_CCFE: ; [CCFE] lda #$01 sta WBAM BlockAlloc: jsr GetTrkSecDrv ; get track, sector and drive number lda SECTOR ; sector pha ; save jsr FindSecInBAM ; find block in BAM beq A_CD19 ; block allocated? pla ; desired sector cmp SECTOR ; = next free sector? bne A_CD2C ; no, -> jsr AllocSector ; allocate block in BAM jmp Out_Err_Msg ; done A_CD19: ; [CD19] pla A_CD1A: ; [CD1A] lda #$00 sta SECTOR ; sector 0 inc TRACK ; next track lda TRACK ; track number cmp A_FED7 ; 36, last track number + 1 bcs A_CD31 ; >=, then 'no block' jsr FindSecInBAM ; find free block in next track beq A_CD1A ; not found, check next track A_CD2C: ; [CD2C] lda #$65 jsr CreErrorMsg ; 65, 'no block' next free block A_CD31: ; [CD31] lda #$65 jsr OutputErrorMsg ; 65, 'no block' no more free blocks ;** OpenChanRdSec: ; [CD36] jsr OpenChannel2 ; open channel, set parameters jmp ReadSector ; read block from disk ;****************************************************************************** ; ;** Get byte from buffer GetByteBuf2: jsr GetBufChanNum ; set pointer to buffer [D12F] lda (BUFTABzp,X) ; get byte rts ;****************************************************************************** ; ;** Read block from disk Readsector3: ; [CD42] jsr OpenChanRdSec ; open channel, read block lda #$00 jsr SetBufPointer3 ; set buffer pointer to zero jsr GetByteBuf2 ; get a byte from the buffer sta ENDPNT,Y lda #$89 ; set read and write flag sta REWRFLab,Y rts ;****************************************************************************** ; ;** B-R block read BlockRead: jsr Readsector3 ; read block from disk jsr PrepbyteBuf ; prepare byte from buffer jmp Out_Err_Msg ; prepare error message ;****************************************************************************** ; ;** U1 substitute for block read UA_U1: jsr GetCmdParms ; get parameters of the command jsr Readsector3 ; read block from disk lda ENDPNT,Y ; end pointer sta OUTREG,Y ; save as data byte lda #$FF sta ENDPNT,Y ; set end pointer to $FF jmp Out_Err_Msg ; done, prepare error message ;****************************************************************************** ; ;** B-W block write BlockWrite: jsr OpenChannel2 ; open channel jsr SetBufPointer ; set buffer pointer tay dey cmp #$02 ; buffer pointer lo less than 2? bcs A_CD81 ; no, -> ldy #$01 A_CD81: ; [CD81] lda #$00 jsr SetBufPointer3 ; buffer pointer to zero tya jsr Write2Buf ; write byte in buffer txa pha jsr WriteSector ; write block to disk pla tax jsr GetByteBuf ; get byte from buffer jmp Out_Err_Msg ; done, error message ;****************************************************************************** ; ;** U2 substitute for block write UA_U2: jsr GetCmdParms ; get command parameters jsr OpenChannel2 ; open channel jsr WriteSector ; and write block to disk jmp Out_Err_Msg ; done ;****************************************************************************** ; ;** B-E block execute BlockExec: jsr P_F258 ; (RTS) jsr OpenChanRdSec ; open channel and read block lda #$00 sta TEMP0 ; address low ldx ActBufNum lda BufAddrHB,X ; buffer address high sta TEMP1 jsr ExecBlock ; execute routine jmp Out_Err_Msg ; done ExecBlock: jmp (J_TEMP0) ; jump to routine ;****************************************************************************** ; ;** B-P block pointer BlockPoint: jsr OpenChannel ; open channel, get buffer number lda ActBufNum asl A ; * 2 tax ; as index lda FILSEC+1 ; pointer value sta BUFTABzp,X ; save as buffer pointer jsr GetBufChanNum ; prepare a byte in buffer [D12F] jsr GetByteBuf ; for output jmp Out_Err_Msg ; done ;****************************************************************************** ; ;** Check buffer number and open channel OpenChannel: ; [CDD2] ldx CHNNUM inc CHNNUM lda FILSEC,X ; buffer number tay dey dey cpy #$0C ; buffer number smaller than 14? bcc A_CDE5 ; yes, -> A_CDE0: ; [CDE0] lda #$70 jmp OutputErrorMsg ; 70, 'no channel' A_CDE5: ; [CDE5] sta SA ; secondary address jsr OpenChan4Read ; open channel, already allocated? bcs A_CDE0 ; yes, -> 'no channel' jsr GetBufNumber ; buffer number sta ActBufNum ; set rts ;****************************************************************************** ; ;** Open channel OpenChannel2: ; [CDF2] jsr OpenChannel ; check buffer number and open channel GetTrkSecDrv: ldx CHNNUM ; channel number lda FILSEC,X ; buffer address and #$01 sta DRVNMB ; drive number lda FILSEC+2,X sta SECTOR ; sector lda FILSEC+1,X sta TRACK ; track jsr ChkTraSec3 ; track and sector OK? jmp LedOn ; turn LED on ;****************************************************************************** ; ;** Set pointer for REL file SetPtrRelFile: ; [CE0E] jsr RecNumXrecLen ; record number * record length jsr DivideBy254 lda ACCUM1 ; remainder = pointer in data block sta RelPointer ; data pointer jsr DivideBy120 ; divide by 120 = side-sector number inc RelPointer inc RelPointer ; data pointer + 2 (track/sector ; pointer!) lda RESULT0 ; result of division sta NumSidSec ; equals side-sector number lda ACCUM1 ; remainder asl A ; times 2 clc adc #$10 ; plus 16 sta PtrSideSec ; =pointer in side-sector to data block rts ;****************************************************************************** ; ;** record number * record length RecNumXrecLen: jsr ClearResult ; erase work storage sta ACCUM3 ldx CURCHN ; channel number lda RECL,X ; record number lo sta ACCUM1 lda RECH,X ; record number hi sta ACCUM2 ; zero? bne A_CE41 ; no, -> lda ACCUM1 ; record number zero? beq A_CE4C ; yes, -> ; not zero A_CE41: ; [CE41] lda ACCUM1 sec sbc #$01 ; then subtract one sta ACCUM1 bcs A_CE4C dec ACCUM2 A_CE4C: ; [CE4C] lda RecLength,X ; record length sta TEMP0 A_CE50: ; [CE50] lsr TEMP0 ; bit 1 = 0 ? bcc A_CE57 ; yes, -> jsr RecNumXrecLen2 ; record number * record length A_CE57: ; [CE57] jsr LshiftAccum ; shift register left lda TEMP0 bne A_CE50 lda RecordPos clc adc RESULT0 sta RESULT0 bcc A_CE6D ; result in $8B/$8C/$8D inc RESULT1 bne A_CE6D inc RESULT2 A_CE6D: ; [CE6D] rts ;****************************************************************************** ; ;** Divide by 254 DivideBy254: lda #$FE ; 254 .by $2C ; dummy BIT opcode ;****************************************************************************** ; ;** Divide by 120 DivideBy120: lda #$78 sta TEMP0 ; divisor ldx #$03 A_CE77: ; [CE77] lda ACCUM0,X pha lda R4,X sta ACCUM0,X pla sta R4,X dex bne A_CE77 jsr ClearResult ; erase work storage A_CE87: ; [CE87] ldx #$00 A_CE89: ; [CE89] lda ACCUM1,X sta ACCUM0,X inx cpx #$04 bcc A_CE89 lda #$00 sta ACCUM3 bit TEMP0 bmi A_CEA3 asl ACCUM0 php lsr ACCUM0 plp jsr LshiftAccum2 ; shift register 1 left A_CEA3: ; [CEA3] jsr RecNumXrecLen2 ; add register 0 to register 1 jsr LshiftAccum ; shift register 1 left bit TEMP0 bmi A_CEB0 jsr LshiftAccumX2 ; left-shift register 1 twice A_CEB0: ; [CEB0] lda ACCUM0 clc adc ACCUM1 sta ACCUM1 bcc A_CEBF inc ACCUM2 bne A_CEBF inc ACCUM3 A_CEBF: ; [CEBF] lda ACCUM3 ora ACCUM2 bne A_CE87 lda ACCUM1 sec sbc TEMP0 ; quotient in $8B/$8C/$8D bcc A_CED8 inc RESULT0 bne A_CED6 inc RESULT1 bne A_CED6 inc RESULT2 A_CED6: ; [CED6] sta ACCUM1 ; remainder in $90 A_CED8: ; [CED8] rts ;****************************************************************************** ; ;** Erase work storage ClearResult: ; [CED9] lda #$00 sta RESULT0 sta RESULT1 sta RESULT2 rts ;****************************************************************************** ; ;** Left shift 3-byte register twice LshiftAccumX2: ; [CEE2] jsr LshiftAccum ;****************************************************************************** ; ;** Left shift 3-byte register once LshiftAccum: ; [CEE5] clc LshiftAccum2: ; [CEE6] rol ACCUM1 rol ACCUM2 rol ACCUM3 rts ;** RecNumXrecLen2: clc ldx #$FD A_CEF0: ; [CEF0] lda RESULT3,X ; register $90/$91/$92 adc ACCUM4,X ; add to register $8B/$8C/$8D sta RESULT3,X inx bne A_CEF0 rts ;****************************************************************************** ; ;** Initialize least recently used table InitLastTable: ; [CEFA] ldx #$00 A_CEFC: ; [CEFC] txa ; store 0,1,2,3,6 .... sta LRUTBLzp,X ; .... $FA/B/C/D/E inx cpx #$04 bne A_CEFC lda #$06 sta LRUTBLzp,X rts ;** UpdateTbl: ; [CF09] ldy #$04 ldx CURCHN ; channel number J_CF0D: ; [CF0D] lda LRUTBLab,Y stx LRUTBLzp,Y cmp CURCHN ; channel number beq A_CF1D dey bmi InitLastTable tax jmp J_CF0D A_CF1D: ; [CF1D] rts ; [CE1E] SwapBuffers2: ; [CF1E] jsr UpdateTbl jsr ChkBufferFree bne A_CF6C ; no, -> jsr GetDrvNum3 ; set drive number jsr GetBuffer bmi A_CF76 jsr DeactivateBuf lda TRACK ; track pha lda SECTOR ; sector pha lda #$01 jsr GetAthByte ; get byte 1 from buffer sta SECTOR ; sector lda #$00 jsr GetAthByte ; get byte 0 from buffer sta TRACK ; last sector? beq A_CF66 ; yes, -> jsr CheckREL ; REL file? beq A_CF57 ; yes, -> jsr Chk4Write bne A_CF57 jsr SwapBuffers jmp J_CF5D A_CF57: ; [CF57] jsr SwapBuffers jsr ReadSector2 J_CF5D: ; [CF5D] pla sta SECTOR ; get sector pla sta TRACK ; and track number jmp J_CF6F A_CF66: ; [CF66] pla sta SECTOR ; get back sector pla sta TRACK ; and track number A_CF6C: ; [CF6C] jsr SwapBuffers J_CF6F: ; [CF6F] jsr GetBufNumber tax jmp VerifyExec ; and verify A_CF76: ; [CF76] lda #$70 jmp OutputErrorMsg ; 70, 'no channel' ;****************************************************************************** ; ;** Look for a free buffer Look4FreeBuf: ; [CF7B] jsr UpdateTbl jsr ChkBufferFree bne A_CF8B jsr GetBuffer bmi A_CF76 jsr DeactivateBuf A_CF8B: ; [CF8B] rts ;****************************************************************************** ; ;** Swap buffers SwapBuffers: ; [CF8C] ldx CURCHN ; channel number lda BUF0CH1zp,X eor #$80 ; toggle bit 7 in table sta BUF0CH1zp,X lda BUF1CH1zp,X eor #$80 ; toggle bit 7 in table sta BUF1CH1zp,X rts ;****************************************************************************** ; ;** Write data in buffer WrData2Buffer: ; [CF9B] ldx #$12 ; channel 18 stx SA jsr OpenChan4Write ; open write channel jsr LedOn ; turn LED on jsr CheckREL ; check file type bcc A_CFAF ; no REL file lda #$20 jsr DeleteFlags ; change buffer A_CFAF: ; [CFAF] lda SA ; secondary address cmp #$0F ; command channel? beq A_CFD8 ; yes, -> bne A_CFBF ; no, -> P_CFB7: ; [CFB7] lda ORGSA ; secondary address and #$8F cmp #$0F ; greater than 15? bcs A_CFD8 ; then input buffer A_CFBF: ; [CFBF] jsr CheckREL ; check file type bcs A_CFC9 ; REL file or direct access? lda DATA ; data byte jmp J_D19D ; write in buffer A_CFC9: ; [CFC9] bne A_CFCE ; if direct access file, -> jmp WrByte2REL ; write data byte in REL file A_CFCE: ; [CFCE] lda DATA jsr Write2Buf ; write data byte in buffer ldy CURCHN ; channel number jmp GetByteBuf ; prepare next byte for output A_CFD8: ; [CFD8] lda #$04 ; channel 4 sta CURCHN ; corresponding input buffer jsr SetBufPointer ; set buffer pointer cmp #$2A ; 40 beq A_CFE8 ; buffer end? lda DATA jsr Write2Buf ; write data byte in buffer A_CFE8: ; [CFE8] lda EOIFLG ; end flag set? beq A_CFED ; yes, -> rts A_CFED: ; [CFED] inc CMDWAT ; set command flag rts ;****************************************************************************** ; ;** Write data byte in buffer Write2Buf: ; [CFF1] pha ; save data byte jsr GetBufNumber ; get buffer number bpl Write2Buf2 ; associated buffer? pla lda #$61 jmp OutputErrorMsg ; 61, 'file not open' Write2Buf2: asl A ; buffer number times 2 tax ; as index pla ; data byte sta (BUFTABzp,X) ; write in buffer inc BUFTABzp,X ; increment buffer pointer rts ;****************************************************************************** ; ;** I - Initialize command Initialize: ; [D005] jsr ChkInputLine ; find drive number jsr LoadBAM ; load BAM jmp Out_Err_Msg ; prepare disk status ;****************************************************************************** ; ;** Read header of BAM Sector ReadDirTrack: ; [D00E] jsr GetBufNumBAM2 ; drive 0: A=13, 1: A=6 tay ldx BUF0CH1zp,Y cpx #$FF ; buffer available? bne A_D02C ; no, -> pha jsr GetBuffer tax ; buffer available? bpl A_D024 ; yes, -> lda #$70 jsr CreErrorMsg2 ; 70, 'no channel' A_D024: ; [D024] pla tay txa ora #$80 ; inactive sta BUF0CH1ab,Y A_D02C: ; [D02C] txa and #$0F sta ActBufNum ldx #$00 stx SECTOR ; sector 0 ldx DirTrack ; 18 stx TRACK ; track 18 jsr Par2DiskCtrl2 ; transmit parameter to disk controller lda #$B0 ; command code 'read block header' jmp J_D58C ; transmit to disk controller ;****************************************************************************** ; ;** Load BAM LoadBAM: ; [D042] jsr ClearTBAM jsr ClsChanThisDrv jsr ReadDirTrack ; read block ldx DRVNMB ; drive number lda #$00 sta MDIRTY,X ; reset flag for "BAM changed" txa asl A tax lda HDR1IDzp sta DISKIDzp,X lda HDR2ID ; save ID sta IMDIIDzp,X jsr DskReadBlock lda ActBufNum ; buffer number asl A tax lda #$02 ; buffer pointer to $0x02 sta BUFTABzp,X lda (BUFTABzp,X) ; get character from buffer ldx DRVNMB ; drive number sta TypeChk,X lda #$00 sta WPSW0,X ; no disk change sta $FF,X ; flag for read error ;****************************************************************************** ; ;** Calculate free blocks CalcFreeBlks: ; [D075] jsr SetBufPtrBAM ; buffer address to $6D/$6E ldy #$04 ; begin at position 4 lda #$00 tax A_D07D: ; [D07D] clc adc (BMPNT),Y ; add number of free blocks per track bcc A_D083 inx ; X as hi-byte A_D083: ; [D083] iny iny ; plus 4 iny iny cpy #$48 ; track 18? beq A_D083 ; then skip cpy #$90 ; last track number? bne A_D07D ; no, -> pha ; lo-byte txa ; hi-byte ldx DRVNMB ; drive number sta NDBH,X ; hi-byte to $2FC pla ; lo-byte sta NDBL,X ; to $2FA rts ;****************************************************************************** ; ;** Read a sector into the buffer ReadBlk2Buf: ; [D09B] jsr Par2DiskCtrl ; parameters to disk controller jsr ReadBlock ; read block jsr VerifyExec ; ok? ReadBlk2Buf2: ; [D0A4] jsr GetByteFromBuf ; get byte from buffer sta TRACK ; track jsr GetByteFromBuf ; next byte from buffer sta SECTOR ; sector rts J_D0AF: ; [D0AF] jsr ReadBlk2Buf lda TRACK ; last sector? bne A_D0B7 ; no, -> rts ;* Next sector in second buffer A_D0B7: ; [D0B7] jsr SwapBuffers2 ; change buffer jsr Par2DiskCtrl ; parameters to disk controller jsr ReadBlock ; read block jmp SwapBuffers2 ; change buffer ;****************************************************************************** ; ;** Read Block ReadBlock: ; [D0C3] lda #$80 ; code for 'read' bne A_D0C9 ;****************************************************************************** ; ;** Write Block WriteBlock: ; [D0C7] lda #$90 ; code for 'write' A_D0C9: ; [D0C9] sta CMD ; save jsr GetBufNumber ; get buffer number tax jsr ChkTrackSector ; get track/sector, read/write block WriteBlock2: ; [D0D3] txa pha asl A ; buffer pointer times 2 tax lda #$00 sta BUFTABzp,X ; pointer in buffer to zero jsr CheckREL ; get file type cmp #$04 ; REL file or direct access? bcs A_D0E8 ; yes, -> inc RECL,X bne A_D0E8 ; increment block counter inc RECH,X A_D0E8: ; [D0E8] pla tax rts ;****************************************************************************** ; ;** Open channel for reading OpenChan4Read: ; [D0EB] lda SA ; secondary address cmp #$13 ; 19 bcc A_D0F3 ; smaller? and #$0F A_D0F3: ; [D0F3] cmp #15 ; command channel? bne A_D0F9 ; no, -> lda #$10 ; 16 A_D0F9: ; [D0F9] tax sec ; flag for channel already allocated lda LINTAB,X ; already in use? bmi A_D106 ; no, -> and #$0F sta CURCHN tax clc ; flag for ok A_D106: ; [D106] rts ;****************************************************************************** ; ;** Open channel for writing OpenChan4Write: ; [D107] lda SA ; secondary address cmp #$13 ; 19 bcc A_D10F ; smaller? and #$0F A_D10F: ; [D10F] tax lda LINTAB,X ; channel number tay asl A bcc A_D121 bmi A_D123 A_D119: ; [D119] tya and #$0F sta CURCHN tax clc ; flag for ok rts A_D121: ; [D121] bmi A_D119 A_D123: ; [D123] sec ; flag for channel already allocated rts ;****************************************************************************** ; ;** Check for file type REL CheckREL: ; [D125] ldx CURCHN lda DIACFLzp,X lsr A and #7 cmp #4 ; 'REL'? rts ;****************************************************************************** ; ;** Get buffer and channel numbers GetBufChanNum: ; [D12F] jsr GetBufNumber ; get buffer number asl A tax ldy CURCHN rts ;****************************************************************************** ; ;** Get a byte from buffer GetByteFromBuf: jsr GetBufChanNum ; get buffer and channel number [D12F] lda ENDPNT,Y ; pointer did roll over? beq A_D151 ; yes, -> next block lda (BUFTABzp,X) ; get byte from buffer pha lda BUFTABzp,X ; buffer pointer cmp ENDPNT,Y ; equal end pointer? bne A_D14D ; no, -> lda #$FF sta BUFTABzp,X ; buffer pointer to -1 A_D14D: ; [D14D] pla ; data byte inc BUFTABzp,X ; increment buffer pointer rts ;* Get byte and read next block A_D151: ; [D151] lda (BUFTABzp,X) ; get character from buffer inc BUFTABzp,X ; increment buffer pointer rts ;****************************************************************************** ; ;** Read byte from buffer into variable Data ReadBuffer2A: ; [D156] jsr GetByteFromBuf ; get byte from buffer, last char? bne A_D191 ; no, -> RTS sta DATA ; save data byte lda ENDPNT,Y ; end pointer? beq A_D16A ; yes, -> ReadBuffer2B: ; [D162] lda #$80 sta REWRFLab,Y ; READ-flag lda DATA ; data byte rts A_D16A: ; [D16A] jsr SwapBuffers2 ; change buffer and read next block lda #$00 jsr SetBufPointer3 ; set buffer pointer to zero jsr GetByteFromBuf ; get first byte from buffer cmp #0 ; last sector? beq A_D192 ; yes, -> sta TRACK ; save last track number jsr GetByteFromBuf ; get next byte sta SECTOR ; save as following track jsr SwapBuffers2 ; change buffer and read next block jsr GetDrvNum3 ; save drive number jsr Par2DiskCtrl ; parameter to disk controller jsr ReadBlock ; transmit read command jsr SwapBuffers2 ; change buffer and read block lda DATA ; get data byte A_D191: ; [D191] rts ;* Write byte in buffer and block A_D192: ; [D192] jsr GetByteFromBuf ; get next byte from buffer ldy CURCHN sta ENDPNT,Y ; save as end pointer lda DATA ; get data byte back rts J_D19D: ; [D19D] jsr Write2Buf ; byte in buffer, buffer full? beq Buffer2Disk rts ;****************************************************************************** ; ;** Write the contents of the buffer to disk Buffer2Disk: ; [D1A3] jsr GetDrvNum3 ; get drive number jsr FindAllocSec ; find free block in BAM Buffer2Disk2: ; [D1A9] lda #$00 jsr SetBufPointer3 ; buffer pointer to zero lda TRACK jsr Write2Buf ; track number as first byte lda SECTOR jsr Write2Buf ; sector number as second byte jsr WriteBlock ; write block jsr SwapBuffers2 ; change buffer jsr Par2DiskCtrl ; parameter to disk controller lda #$02 jmp SetBufPointer3 ; buffer pointer to 2 ;****************************************************************************** ; ;** Increment buffer pointer with value in A IncBufPointer: ; [D1C6] sta TEMP0 jsr SetBufPointer ; get buffer pointer clc adc TEMP0 sta BUFTABzp,X ; and increment sta DIRBUF rts ;****************************************************************************** ; ;** Get drive number GetDrvNum3: ; [D1D3] jsr GetBufNumber ; get drive number tax lda LSTJOB,X and #$01 ; isolate drive number sta DRVNMB ; and save rts ;****************************************************************************** ; ;** Find write channel and buffer FindWrChanBuf: ; [D1DF] sec ; flag for writing bcs A_D1E3 ; always -> ;****************************************************************************** ; ;** Find read channel and buffer FindRdChanBuf: ; [D1E2] clc ; flag for reading A_D1E3: ; [D1E3] php ; save sta TEMP0 ; buffer number, AFAIK 0 or 1 jsr CloseChannel ; close channel jsr AllocFreeChan ; allocate free channel sta CURCHN ; channel number ldx SA ; secondary address plp ; read channel? bcc A_D1F5 ; yes, -> ora #$80 ; flag for writing A_D1F5: ; [D1F5] sta LINTAB,X ; set and #$3F tay lda #$FF ; default value sta BUF0CH1ab,Y sta BUF1CH1ab,Y ; write in associated table sta SIDSECab,Y dec TEMP0 ; decrement buffer number bmi A_D226 ; done already? jsr GetBuffer ; find buffer, found? bpl A_D217 ; yes, -> ;****************************************************************************** ; ;** No channel available NoChannel: jsr FreeBuffer ; erase flags in table [D25A] lda #$70 jmp OutputErrorMsg ; 70, 'no channel' A_D217: ; [D217] sta BUF0CH1ab,Y ; buffer number in table dec TEMP0 ; buffer number bmi A_D226 ; already done? jsr GetBuffer ; find buffer bmi NoChannel ; not found? sta BUF1CH1ab,Y ; buffer number in table A_D226: ; [D226] rts ;****************************************************************************** ; ;** Close channel ; in: - ; out: - ; used: A X Y CloseChannel: ; [D227] lda SA ; secondary address cmp #15 ; command channel? bne A_D22E ; no, -> rts ; ready A_D22E: ; [D22E] ldx SA lda LINTAB,X ; channel number cmp #$FF ; allocated? beq A_D259 ; no, -> ready and #$3F sta CURCHN ; channel number lda #$FF sta LINTAB,X ; close it ldx CURCHN lda #$00 sta REWRFLzp,X ; erase READ and WRITE flag jsr FreeBuffer ; [D25A] ;* Set right bit in register ldx CURCHN ; channel number lda #$01 ; set bit 0 A_D24D: ; [D24D] dex ; count down ready? bmi A_D253 ; yes, -> asl A ; shift A bne A_D24D ; always -> A_D253: ; [D253] ora LINUSE ; set bit in register sta LINUSE A_D259: ; [D259] rts ;****************************************************************************** ; ;** Free buffer ; in: - ; out: - ; used: A X Y FreeBuffer: ; [D25A] ldx CURCHN ; channel number lda BUF0CH1zp,X ; buffer number cmp #$FF ; allocated? beq A_D26B ; no, -> pha lda #$FF sta BUF0CH1zp,X ; erase buffer association pla jsr ClrAllocReg ; clr buffer alloc register [D2F3] A_D26B: ; [D26B] ldx CURCHN ; channel number lda BUF1CH1zp,X cmp #$FF ; associated in second table? beq A_D27C ; no, -> pha lda #$FF sta BUF1CH1zp,X ; erase allocation pla jsr ClrAllocReg ; clr buffer alloc register [D2F3] A_D27C: ; [D27C] ldx CURCHN ; channel number lda SIDSECzp,X cmp #$FF ; allocated in side sector table? beq A_D28D ; no, -> pha lda #$FF sta SIDSECzp,X ; erase allocation pla jsr ClrAllocReg ; clr buffer alloc register [D2F3] A_D28D: ; [D28D] rts ;****************************************************************************** ; ;** Get a free buffer GetBuffer: ; [D28E] tya pha ldy #$01 jsr FindBuffer bpl A_D2A3 ; found one, -> dey jsr FindBuffer bpl A_D2A3 ; found one, -> jsr StealBuffer tax ; success? bmi A_D2B6 ; no, -> A_D2A3: ; [D2A3] lda JOBSzp,X ; job is completed? bmi A_D2A3 ; no, wait -> ;* clear jobqueue lda DRVNMB ; = 0 sta JOBSzp,X sta LSTJOB,X txa asl A tay lda #$02 sta BUFTABab,Y A_D2B6: ; [D2B6] pla tay txa rts ;****************************************************************************** ; ;** Find a free buffer ; in: Y ; out : N flag FindBuffer: ; [D2BA] ldx #$07 A_D2BC: ; [D2BC] lda BUFUSEL,Y and PowersOf2,X ; buffer used? beq A_D2C8 ; no, -> dex ; all buffers checked? bpl A_D2BC ; no, -> rts A_D2C8: ; [D2C8] lda BUFUSEL,Y eor PowersOf2,X ; toggle bit sta BUFUSEL,Y txa ; buffer number dey bmi A_D2D8 clc adc #$08 A_D2D8: ; [D2D8] tax ; buffer number A_D2D9: ; [D2D9] rts ;****************************************************************************** ; ;** Check if a buffer is free ChkBufFree: ; [D2DA] ldx CURCHN lda BUF0CH1zp,X ; buffer free? bmi A_D2E9 ; yes, -> txa clc adc #$07 ; alternative buffer tax lda BUF0CH1zp,X ; free? bpl A_D2D9 ; no, -> A_D2E9: ; [D2E9] cmp #$FF ; free? beq A_D2D9 ; yes, -> pha lda #$FF sta BUF0CH1zp,X ; mark as free pla ;****************************************************************************** ; ;** Clear allocation register of the freed buffer ; in: A ; out: - ; used: A X Y ClrAllocReg: ; [D2F3] and #$0F tay ; buffer number iny ldx #$10 ; 16 A_D2F9: ; [D2F9] ror BUFUSEH ror BUFUSEL ; rotate 16-bit allocation register dey bne A_D303 clc ; erase bit for buffer A_D303: ; [D303] dex ; rotation completed? bpl A_D2F9 ; no, -> rts ;****************************************************************************** ; ;** Close all channels CloseAllChan: ; [D307] lda #14 ; number of channels sta SA ; secondary address A_D30B: ; [D30B] jsr CloseChannel ; close channel dec SA ; all channels done? bne A_D30B ; no, -> more rts ;****************************************************************************** ; ;** Close all channels of this drive ClsChanThisDrv: ; [D313] lda #$0E ; 14 sta SA ; secondary address A_D317: ; [D317] ldx SA lda LINTAB,X ; association table cmp #$FF ; channel associated? beq A_D334 ; no, -> and #$3F sta CURCHN ; channel number jsr GetBufNumber ; get buffer number tax lda LSTJOB,X ; drive number and #$01 ; isolate cmp DRVNMB ; equal to actual drive number bne A_D334 ; no, -> jsr CloseChannel ; close channel A_D334: ; [D334] dec SA ; next channel bpl A_D317 rts ;****************************************************************************** ; ;** Steal the less recently used inactive buffer StealBuffer: ; [D339] lda TEMP0 pha ldy #$00 A_D33E: ; [D33E] ldx LRUTBLzp,Y lda BUF0CH1zp,X ; buffer is active? bpl A_D348 ; yes, -> cmp #$FF ; buffer is used? bne A_D35E ; no, -> ;* check alternative buffer A_D348: ; [D348] txa clc adc #$07 tax lda BUF0CH1zp,X ; buffer active as well? bpl A_D355 ; yes, -> cmp #$FF ; buffer is used? bne A_D35E ; no, -> A_D355: ; [D355] iny ; next channel cpy #$05 bcc A_D33E ldx #$FF ; no buffer found bne A_D37A ; always -> A_D35E: ; [D35E] stx TEMP0 and #$3F tax A_D363: ; [D363] lda JOBSzp,X ; used by job now? bmi A_D363 ; wait for completion of job, -> cmp #$02 ; job ended in error? bcc A_D373 ; no, steal buffer -> ldx TEMP0 cpx #$07 ; alternative buffers left to check? bcc A_D348 ; yes, -> bcs A_D355 ; always -> A_D373: ; [D373] ldy TEMP0 lda #$FF sta BUF0CH1ab,Y ; make buffer "unused" A_D37A: ; [D37A] pla sta TEMP0 txa rts ;****************************************************************************** ; ;** Find channel and allocate AllocFreeChan: ldy #$00 lda #$01 ; set bit 0 A_D383: ; [D383] bit LINUSE ; channel free? bne A_D391 ; yes, -> iny asl A ; more channels to check? bne A_D383 ; yes, -> lda #$70 jmp OutputErrorMsg ; 70, 'no channel' A_D391: ; [D391] eor #$FF ; exor bit model and LINUSE ; erase bit (= set channel) sta LINUSE ; allocate channel tya rts ;****************************************************************************** ; ;** Open read channel, get byte GetByte: jsr OpenChan4Read ; open channel for reading jsr LedOn ; turn LED on jsr GetByte2 ; get byte in output register ldx CURCHN ; channel number lda OUTREG,X ; get byte rts ;** GetByte2: ; [D3AA] ldx CURCHN ; channel number jsr CheckREL ; check file type bne A_D3B4 ; no REL file? jmp GetByteREL ; get byte from REL file A_D3B4: ; [D3B4] lda SA ; secondary address cmp #15 ; command channel? beq A_D414 ; yes, -> read error channel lda REWRFLzp,X and #$08 ; end flag set? bne A_D3D3 ; no, -> jsr CheckREL ; check file type cmp #$07 ; direct access file? bne A_D3CE ; no, -> lda #$89 ; set READ and WRITE flag sta REWRFLzp,X jmp A_D3DE A_D3CE: ; [D3CE] lda #$00 sta REWRFLzp,X ; erase READ and WRITE flag rts A_D3D3: ; [D3D3] lda SA ; zero = LOAD? beq A_D409 ; yes, -> jsr CheckREL ; check file type cmp #4 ; REL file or direct access? bcc A_D400 ; no, -> A_D3DE: ; [D3DE] jsr GetBufChanNum ; get buffer and channel number [D12F] lda BUFTABzp,X ; buffer pointer cmp ENDPNT,Y ; equal end pointer? bne PrepByteBuf ; no, -> lda #$00 sta BUFTABzp,X ; buffer pointer to zero ;** PrepByteBuf: ; [D3EC] inc BUFTABzp,X ; increment buffer pointer ;** GetByteBuf: ; [D3EE] lda (BUFTABzp,X) ; get byte from buffer sta OUTREG,Y ; into output register lda BUFTABzp,X ; buffer pointer cmp ENDPNT,Y ; equal end pointer? bne A_D3FF ; no, -> lda #$81 sta REWRFLab,Y ; set flags A_D3FF: ; [D3FF] rts A_D400: ; [D400] jsr ReadBuffer2A ; get byte from buffer A_D403: ; [D403] ldx CURCHN ; channel number sta OUTREG,X ; byte in output register rts A_D409: ; [D409] lda DIRLST ; flag for directory? beq A_D400 ; no, -> jsr CreateDirLine ; create directory line jmp A_D403 A_D414: ; [D414] jsr SetBufPointer ; set buffer pointer cmp #<(ERRBUF)-1 ; error buffer? bne A_D433 ; no, -> lda DIRBUF+1 cmp #>(ERRBUF) ; error buffer? bne A_D433 ; no, -> lda #$0D ; CR sta DATA ; in output register jsr ClrErrorFlags ; erase error flags lda #$00 jsr ErrMsgTS00 ; create 'OK' message dec ERRPTR ; set buffer pointer back lda #$80 ; set READ flag bne A_D445 ; always -> A_D433: ; [D433] jsr GetByteFromBuf ; get byte from buffer sta DATA ; into output register bne Byte2ErrChan J_D43A: ; [D43A] lda #<(ERRBUF)-1 jsr SetBufPointer3 lda #>(ERRBUF) sta BUFTABzp+1,X ;****************************************************************************** ; ;** Send a byte to the error channel Byte2ErrChan: lda #$88 ; set READ and EOI flag A_D445: ; [D445] sta RDFLAG lda DATA ; data byte sta OUTREG+5 ; into output register rts ;****************************************************************************** ; ;** Read next block RdNxtBlock: ; [D44D] jsr GetBufNumber ; get buffer number asl A ; times 2 tax lda #$00 sta BUFTABzp,X ; buffer pointer to zero lda (BUFTABzp,X) ; get first byte from buffer beq A_D45F ; no block following? dec BUFTABzp,X ; buffer pointer to -1 jmp ReadBuffer2A ; read next block A_D45F: ; [D45F] rts ;****************************************************************************** ; ;** Read block ReadSector: ; [D460] lda #$80 ; command code for reading bne A_D466 ;****************************************************************************** ; ;** Write block WriteSector: ; [D464] lda #$90 ; command code for writing A_D466: ; [D466] ora DRVNMB ; drive number sta CMD ; save code lda ActBufNum jsr Par2DiskCtrl2 ; parameter to disk controller ldx ActBufNum jmp ExecCommand ; execute command ;****************************************************************************** ; ;** Allocate buffer and read block ReadSeqFile: ; [D475] lda #$01 ; file type to sequential ReadXxxFile: ; [D477] sta TYPE lda #$11 ; 17 sta SA ; secondary address jsr RdBlkAllocBuf ; allocate buffer and read block lda #$02 jmp SetBufPointer3 ; buffer pointer to 2 ;****************************************************************************** ; ;** Allocate new block OpenWrChannel: lda #$12 ; 18 sta SA ; secondary address jmp AllocNewSec ; allocate new block ;****************************************************************************** ; ;** Write directory sector WrDirSector: ; [D48D] jsr GetTrackSector ; get track and sector number lda #$01 sta TEMP0 ; a block lda SECINC ; save original interleave pha lda #$03 ; temporary interleave sta SECINC jsr FindAllocSec2 ; find free block in BAM pla sta SECINC ; restore original interleave lda #$00 jsr SetBufPointer3 ; buffer pointer to zero lda TRACK jsr Write2Buf ; track number in buffer lda SECTOR jsr Write2Buf ; sector number in buffer jsr WriteBlock ; write block to disk jsr VerifyExec ; and verify lda #$00 jsr SetBufPointer3 ; buffer pointer to zero A_D4BB: ; [D4BB] jsr Write2Buf ; fill buffer with zeroes bne A_D4BB jsr Write2Buf ; zero as following track lda #$FF jmp Write2Buf ; $FF as number of bytes ;****************************************************************************** ; ;** Set buffer pointer SetBufPointer3: ; [D4C8] sta TEMP0 ; save pointer jsr GetBufNumber ; get buffer number asl A ; times 2 tax lda BUFTABzp+1,X ; buffer pointer hi sta DIRBUF+1 lda TEMP0 ; restore pointer sta BUFTABzp,X ; buffer pointer lo, new value sta DIRBUF rts ;****************************************************************************** ; ;** Close internal channels 17 and 18 Close17_18: ; [D4DA] lda #17 sta SA jsr CloseChannel ; close channel lda #18 sta SA jmp CloseChannel ; close channel ;****************************************************************************** ; ;** Set buffer pointer SetBufPointer: ; [D4E8] jsr GetBufNumber ; get buffer number SetBufPointer2: ; [D4EB] asl A tax lda BUFTABzp+1,X ; buffer pointer hi sta DIRBUF+1 lda BUFTABzp,X ; buffer pointer lo sta DIRBUF rts ;****************************************************************************** ; ;** Get byte from buffer at position A GetAthByte: ; [D4F6] sta TEMP2 ; pointer lo jsr GetBufNumber ; get buffer number tax lda BufAddrHB,X ; hi-byte buffer address sta TEMP3 ; pointer hi ldy #$00 lda (TEMP2),Y ; get byte from buffer rts ;****************************************************************************** ; ;** Check track and sector numbers ChkTrackSector: ; [D506] lda LSTJOB,X ; command code for disk controller and #$01 ; drive number ora CMD ; plus command code SetJoA__: pha ; save stx ActBufNum ; buffer number txa asl A ; times 2 tax lda TRASECzp+1,X ; sector sta CMD ; save lda TRASECzp,X ; track beq A_D54A ; track 0 not allowed, -> cmp A_FED7 ; 36, highest track number + 1 bcs A_D54A ; track number too big, -> tax pla ; command code pha and #$F0 cmp #$90 ; code for writing? bne A_D57A ; no, -> pla ; command code pha lsr A ; drive 1? bcs A_D535 ; yes, -> lda TypeChk bcc A_D538 ; always -> A_D535: ; [D535] lda TypeChk+1 A_D538: ; [D538] beq A_D53F cmp A_FED5 ; 'A', format marker bne A_D572 ; 73, 'cbm dos v2.6 1541' A_D53F: ; [D53F] txa ; track number jsr GetMaxSectors ; get maximum sector number cmp CMD ; compare with sector number beq A_D54A ; if equal, -> error bcs A_D57A ; if smaller, -> OK A_D54A: ; [D54A] jsr GetTrackSect2 A_D54D: ; [D54D] lda #$66 jmp CreErrorMsg ; 66, 'illegal track or sector' ;****************************************************************************** ; ;** Get track and sector numbers GetTrackSect2: ; [D552] lda ActBufNum ; buffer number asl A ; *2 tax ; as index lda TRASECzp,X sta TRACK lda TRASECzp+1,X sta SECTOR rts ;****************************************************************************** ; ;** Check for valid track and sector numbers ChkTraSec3: ; [D55F] lda TRACK ; track beq A_D54D ; zero, then error cmp A_FED7 ; 36, maximum track number + 1 bcs A_D54D ; 66, 'illegal track and sector number' jsr GetMaxSectors ; get maximum sector number cmp SECTOR ; sector beq A_D54D bcc A_D54D ; error rts ;* Output message with DOS version A_D572: ; [D572] jsr GetTrackSect2 lda #$73 jmp CreErrorMsg ; 73, 'cbm dos v2.6 1541' A_D57A: ; [D57A] ldx ActBufNum ; buffer number pla ; restore ... sta CMD ; command code for disk controller sta JOBSzp,X ; in command register sta LSTJOB,X ; and write in table rts ;****************************************************************************** ; ;** Read block DskReadBlock: ; [D586] lda #$80 ; code for read bne J_D58C ; always -> ;****************************************************************************** ; ;** Write block DskWriteBlock: ; [D58A] lda #$90 ; code for write J_D58C: ; [D58C] ora DRVNMB ; drive number ldx ActBufNum ; buffer number ExecCommand2: sta CMD ExecCommand: lda CMD ; command code jsr SetJoA__ ; check track and sector ;****************************************************************************** ; ;** Verify execution VerifyExec: ; [D599] jsr VerifyExec2 ; verify execution bcs VerifyExec ; wait for end pha lda #$00 sta JOBRTN ; erase error flag pla rts VerifyExec2: lda JOBSzp,X ; still busy? bmi A_D5C4 ; yes, -> wait cmp #$02 ; error-free execution? bcc A_D5C2 ; yes, -> cmp #$08 ; write protect error? beq A_D5BA ; yes, -> cmp #$0B ; ID mismatch? beq A_D5BA ; yes, -> cmp #$0F ; drive not ready? bne A_D5C6 ; no, -> A_D5BA: ; [D5BA] bit JOBRTN bmi A_D5C2 jmp J_D63F ; create error message A_D5C2: ; [D5C2] clc ; execution ended rts A_D5C4: ; [D5C4] sec ; execution not yet ended rts ;* Additional attempts for read errors A_D5C6: ; [D5C6] tya pha lda DRVNMB ; drive number pha lda LSTJOB,X and #$01 ; drive number sta DRVNMB tay lda A_FECA,Y ; bit model for drive sta ERLED jsr RetryExec ; read attempt cmp #$02 bcs A_D5E3 ; not ok? jmp ExecOK ; done A_D5E3: ; [D5E3] lda LSTJOB,X ; command code and #$F0 ; isolate pha cmp #$90 ; code for write bne A_D5F4 ; no, -> lda DRVNMB ; drive number ora #$B8 sta LSTJOB,X A_D5F4: ; [D5F4] bit REVCNT ; position head? bvs A_D631 ; yes, -> lda #$00 sta EPTR ; counter for searches next to track sta TOFF A_D600: ; [D600] ldy EPTR ; counter lda TOFF sec sbc ReadAttempts,Y ; constants for read attempts sta TOFF lda ReadAttempts,Y jsr MovHeadHalfTrk ; position head next to track inc EPTR ; increment counter jsr RetryExec ; read attempt cmp #$02 ; execution OK? bcc A_D625 ; yes, -> ldy EPTR ; load counter lda ReadAttempts,Y ; another try? bne A_D600 ; yes, -> A_D625: ; [D625] lda TOFF jsr MovHeadHalfTrk ; position head lda JOBSzp,X cmp #$02 ; execution OK? bcc A_D65C ; yes, -> A_D631: ; [D631] bit REVCNT bpl A_D644 A_D635: ; [D635] pla ; command code cmp #$90 ; for writing? bne J_D63F ; no, -> ora DRVNMB ; drive number sta LSTJOB,X ; command code in table J_D63F: ; [D63F] lda JOBSzp,X ; return message jsr PrepErrMsg ; set error message A_D644: ; [D644] pla bit JOBRTN ; still busy? bmi ExecOK ; yes, -> pha lda #$C0 ; command code for head positioning ora DRVNMB ; drive number sta JOBSzp,X ; in command register A_D651: ; [D651] lda JOBSzp,X bmi A_D651 ; wait for execution jsr RetryExec ; attempt command execution again cmp #$02 ; return message bcs A_D635 ; incorrect? A_D65C: ; [D65C] pla cmp #$90 ; command code for writing bne ExecOK ; no, -> ora DRVNMB ; drive number sta LSTJOB,X ; in table jsr RetryExec ; attempt execution again cmp #$02 ; return message bcs J_D63F ; error? ExecOK: ; [ecOK] pla sta DRVNMB ; get drive number back pla tay lda JOBSzp,X ; error code clc ; end-of-execution flag rts ;****************************************************************************** ; ;** Move head by half a track MovHeadHalfTrk: cmp #$00 ; move at all? beq A_D692 ; no, -> finished bmi A_D688 ; move outward, -> ;* Move head to center of disk A_D67C: ; [D67C] ldy #$01 jsr MoveHead1Trk ; transmit data for head position sec sbc #$01 ; another move? bne A_D67C ; yes, -> more beq A_D692 ; no, -> done (why not RTS?) A_D688: ; [D688] ldy #$FF jsr MoveHead1Trk ; transmit data for head position clc adc #$01 ; another move? bne A_D688 ; yes, -> more A_D692: ; [D692] rts ;****************************************************************************** ; ;** Move head one track in or out ; Y = direction MoveHead1Trk: pha tya ldy DRVNMB ; drive number sta PHASE,Y A_D69A: ; [D69A] cmp PHASE,Y ; head has been moved? beq A_D69A ; no, -> lda #$00 sta PHASE,Y pla rts ;****************************************************************************** ; ;** Attempt command execution multiple times RetryExec: ; [D6A6] lda REVCNT ; maximum number of retries and #$3F tay A_D6AB: ; [D6AB] lda ERLED ; bit for LED eor PortB2 sta PortB2 lda LSTJOB,X ; command sta JOBSzp,X ; transmit to disk controller A_D6B9: ; [D6B9] lda JOBSzp,X ; and return message bmi A_D6B9 ; wait cmp #$02 ; ok? bcc A_D6C4 ; yes, -> dey ; decrement counter bne A_D6AB ; attempt again A_D6C4: ; [D6C4] pha lda ERLED ora PortB2 ; LED on sta PortB2 pla ; error code rts ;****************************************************************************** ; ;** Transmit parameters to disk controller = track, sector and ID Par2DiskCtrl: ; [D6D0] jsr GetBufNumber ; get buffer number Par2DiskCtrl2: ; [D6D3] asl A tay lda TRACK ; track number sta TRASECab,Y ; transmit lda SECTOR ; sector number sta TRASECab+1,Y ; transmit lda DRVNMB ; drive number asl A ; times 2 tax rts ;****************************************************************************** ; ;** Create file entry in directory CreDirEntry: ; [D6E4] lda SA ; secondary address pha lda CURCHN ; channel number pha lda SECTOR ; sector number pha lda TRACK ; track number pha ; save lda #$11 sta SA ; secondary address 17 jsr GetTrackSector ; get track and sector number lda TYPE ; file type pha ; save lda DRVNUM ; drive number and #$01 sta DRVNMB ; set ldx ActBufNum ; buffer number eor LSTJOB,X lsr A ; equal drive number? bcc A_D715 ; yes, -> ldx #$01 stx DELIND ; pointer in directory jsr Read1stDirBlk ; find first entry, free? beq A_D730 ; yes, -> bne J_D73D ; no, always -> A_D715: ; [D715] lda DELSEC ; sector free? beq A_D726 ; yes, -> cmp SECTOR ; equal sector number? beq J_D73D ; yes, -> sta SECTOR ; save sector number jsr ReadSector ; read block jmp J_D73D A_D726: ; [D726] lda #$01 sta DELIND ; pointer to one jsr NxtFileInDir ; next entry in directory free? bne J_D73D ; no, -> ; write entry A_D730: ; [D730] jsr WrDirSector ; write directory block lda SECTOR ; sector number sta DELSEC lda #$02 sta DELIND ; pointer to 2 J_D73D: ; [D73D] lda DELIND jsr SetBufPointer3 ; set buffer pointer pla sta TYPE ; file type cmp #$04 ; REL file? bne A_D74D ; no, -> ora #$80 ; set bit 7 A_D74D: ; [D74D] jsr Write2Buf ; and write in buffer pla sta FILTRK ; following track jsr Write2Buf ; in buffer pla sta FILSEC ; following sector jsr Write2Buf ; in buffer jsr GetBufNumber ; get buffer number tay lda FILTBL tax lda #16 ; length of filename jsr FilNam2DirBuf ; write filename in buffer ;* Fill entry wit zeros from offset 16 until 27 ldy #$10 lda #$00 A_D76F: ; [D76F] sta (DIRBUF),Y ; fill with zeroes at position 16 iny cpy #$1B ; position 27 already? bcc A_D76F ; no, -> lda TYPE ; file type cmp #$04 ; REL file? bne A_D790 ; no, -> ; enter variables for REL file ldy #$10 lda TRKSS ; track sta (DIRBUF),Y iny lda SECSS ; and sector sta (DIRBUF),Y ; the side-sectors in directory entry iny lda RecordSize ; record length sta (DIRBUF),Y ; in directory A_D790: ; [D790] jsr WriteSector ; write block pla sta CURCHN ; channel number tax pla sta SA ; secondary address lda DELSEC sta DIRSECP sta DSEC,X lda DELIND sta BUFPTR sta DIND,X lda TYPE ; file type sta COMFLG lda DRVNMB ; drive number sta DRVNUM rts ;****************************************************************************** ; ;** OPEN command, secondary addres <> 15 OPEN_N15: ; [D7B4] lda SA ; secondary address sta TEMPSA jsr ChkLineLength ; get line length, erase flags stx INSTRU ldx CMDBUF ; first character from buffer lda TEMPSA ; secondary address bne A_D7F3 ; not equal 0 (LOAD)? cpx #'*' ; load first file? bne A_D7F3 ; no, -> lda LastTrack ; load last used file? beq A_D81C ; no, -> sta TRACK ; track number lda PRGDRV ; last drive number sta DRVNMB ; drive number sta DRVNUM lda #$02 sta COMFLG ; set data type to PRG lda PRGSEC ; last used sector sta SECTOR ; sector jsr LedOn ; turn LED on jsr RdBlkAllocBuf ; allocate buffer, read block lda #4 ; file type PRG (*2) ora DRVNMB ; drive number J_D7EB: ; [D7EB] ldx CURCHN ; channel number sta DIACFLab,Y ; set flag jmp Out_Err_Msg ; done A_D7F3: ; [D7F3] cpx #'$' ; directory? bne A_D815 ; no, -> lda TEMPSA ; '$',0 ? bne A_D7FF ; no, -> jmp J_DA55 ; OPEN $ ;****************************************************************************** ; ;** Treat directory as SEQ file A_D7FF: ; [D7FF] jsr ChkInputLine ; analyze line to end ;* Read first block of directory lda DirTrack ; 18, directory track sta TRACK ; track lda #$00 sta SECTOR ; sector 0 jsr RdBlkAllocBuf ; allocate buffer, read block lda DRVNMB ; drive number ora #$02 ; file type SEQ (*2) jmp J_D7EB ; continue as above A_D815: ; [D815] cpx #"#" ; direct access? bne A_D82B ; no, -> jmp OpenBlock ; open direct access file A_D81C: ; [D81C] lda #$02 sta TYPFLG ; file type program lda #$00 sta DRVNMB ; drive 0 sta LSTDRV jsr LoadBAM ; load BAM A_D82B: ; [D82B] jsr ChkForColon ; analyze line, colon found? bne A_D834 ; no, -> ldx #$00 beq A_D840 ; always -> A_D834: ; [D834] txa ; comma found? beq A_D83C ; no, -> lda #$30 jmp OutputErrorMsg ; 30, 'syntax error' A_D83C: ; [D83C] dey beq A_D840 dey A_D840: ; [D840] sty FILTBL ; pointer to drive number lda #$8D ; shift CR jsr SearchInputBuf ; analyze line to end inx stx F2CNT ; comma counter jsr GetDrvNum ; get drive number jsr VerifyDrvNum ; check drive number jsr SrchDirEntry ; find file entry in directory ldx #$00 ; default values stx RecordSize ; record length stx MODE stx TYPE ; file type inx ; X := 1 cpx F1CNT ; comma before equal sign? bcs A_D876 ; no, -> jsr ChkTypeMode ; get file type and control mode inx cpx F1CNT ; additional comma? bcs A_D876 ; no, -> cpy #$04 ; REL file? beq A_D8B1 ; yes, -> jsr ChkTypeMode ; get file type and control method A_D876: ; [D876] ldx TEMPSA stx SA ; secondary address cpx #$02 ; greater than 1? bcs A_D891 ; yes, -> stx MODE ; 0 or 1 (LOAD or SAVE) lda #$40 sta WBAM lda TYPE ; DEL type? bne A_D8A7 ; no, -> lda #$02 ; PRG sta TYPE ; as file type A_D891: ; [D891] lda TYPE bne A_D8A7 lda COMFLG and #$07 ; isolate file type sta TYPE lda FILTRK ; track number bne A_D8A7 ; not equal zero? lda #$01 sta TYPE ; file type sequential A_D8A7: ; [D8A7] lda MODE ; control method cmp #$01 ; Write? beq A_D8C6 ; yes, -> jmp J_D940 A_D8B1: ; [D8B1] ldy FILTBL,X ; pointer behind second comma lda CMDBUF,Y ; get value sta RecordSize ; record length lda FILTRK ; number of parameters, 0 or 1 bne A_D876 ; 1, -> lda #$01 ; 'W' sta MODE ; as second method bne A_D876 ; always -> A_D8C6: ; [D8C6] lda COMFLG ; file type and #$80 ; isolate wildcard flag tax ; wildcard in name? bne A_D8E1 ; yes, -> lda #$20 bit COMFLG ; was file closed? beq A_D8D9 ; yes, -> jsr DelDirEntry ; byte 0 in buffer and write block jmp OpenFile4Write A_D8D9: ; [D8D9] lda FILTRK ; track number of the first block bne A_D8E1 ; already existing jmp OpenFile4Write A_D8E1: ; [D8E1] lda CMDBUF ; first character from input buffer cmp #'@' ; replace? beq A_D8F5 ; yes, -> txa ; file exists? bne A_D8F0 ; no, -> lda #$63 jmp OutputErrorMsg ; 63, 'file exists' A_D8F0: ; [D8F0] lda #$33 jmp OutputErrorMsg ; 33, 'syntax error' ;* Open a file with overwriting A_D8F5: ; [D8F5] lda COMFLG ; file type and #$07 ; isolate cmp TYPE bne A_D965 ; file type different? cmp #$04 ; REL file? beq A_D965 ; 64, 'file type mismatch' jsr AllocNewSec lda CURCHN sta WLINDX ; save channel number lda #$11 sta SA jsr OpenChan4Read ; open read channel lda INDEX jsr SetBufPointer3 ; set buffer pointer for directory ldy #$00 lda (DIRBUF),Y ; file type ora #$20 ; set bit 5, open file sta (DIRBUF),Y ldy #$1A lda TRACK ; track sta (DIRBUF),Y iny lda SECTOR ; and sector sta (DIRBUF),Y ; for open with at-sign ldx WLINDX ; channel number lda DIRSECP sta DSEC,X ; pointer to directory block lda BUFPTR sta DIND,X jsr GetTrackSector ; get track and sector number jsr WriteSector ; write block jmp J_D9EF ; prepare track, sector, and drive ; number ;* Open file for read (and load) J_D940: ; [D940] lda FILTRK ; file erased? bne A_D94A ; no, -> lda #$62 jmp OutputErrorMsg ; 62, 'file not found' A_D94A: ; [D94A] lda MODE ; control mode cmp #$03 ; Merge? beq A_D95C ; yes, then no test of unclosed file lda #$20 bit COMFLG ; file closed? beq A_D95C ; yes, ok -> lda #$60 jmp OutputErrorMsg A_D95C: ; [D95C] lda COMFLG and #$07 ; isolate file type cmp TYPE ; same file type? beq A_D96A ; yes, -> A_D965: ; [D965] lda #$64 jmp OutputErrorMsg ; 64, 'file type mismatch' A_D96A: ; [D96A] ldy #$00 sty F2PTR ldx MODE ; control mode cpx #$02 ; Append? bne A_D990 ; no, -> cmp #$04 ; REL file? beq A_D965 ; yes, -> lda (DIRBUF),Y and #$4F ; mark file as open sta (DIRBUF),Y lda SA pha lda #$11 ; READ sta SA ; channel 17 jsr GetTrackSector ; get track and sector number jsr WriteSector ; write block pla sta SA ; get channel number back A_D990: ; [D990] jsr Open1stSidSec lda MODE ; control mode cmp #$02 ; Append? bne J_D9EF ; no, -> jsr Prep4Append jmp Out_Err_Msg ; done ;****************************************************************************** ; ;** Get first side sector from directory Open1stSidSec: ; [D9A0] ldy #$13 lda (DIRBUF),Y ; track sta TRKSS iny lda (DIRBUF),Y sta SECSS iny lda (DIRBUF),Y ; record length ldx RecordSize ; save last record length sta RecordSize txa ; last record length 0 ? beq A_D9C3 ; yes, -> cmp RecordSize ; same length? beq A_D9C3 ; yes, -> lda #$50 jsr OutputErrorMsg ; 50, 'record not present' A_D9C3: ; [D9C3] ldx F2PTR lda FILTRK,X ; track sta TRACK lda FILSEC,X ; sector sta SECTOR jsr RdBlkAllocBuf ldy CURCHN ldx F2PTR lda DIRSECP,X sta DSEC,Y lda BUFPTR,X sta DIND,Y rts ;****************************************************************************** ; ;** Open file for writing OpenFile4Write: ; [D9E3] lda DRVNUM ; drive number and #$01 sta DRVNMB jsr AllocNewSec jsr CreDirEntry J_D9EF: ; [D9EF] lda SA ; channel number cmp #$02 ; LOAD or SAVE? bcs A_DA06 ; no, -> jsr GetSector2 ;* Adjust parameters for last used drive and file lda TRACK sta LastTrack lda DRVNMB sta PRGDRV lda SECTOR sta PRGSEC A_DA06: ; [DA06] jmp J_C199 ;****************************************************************************** ; ;** Check file type and control mode ; in: X = place behind comma ChkTypeMode: ; [DA09] ldy FILTBL,X ; pointer in command line lda CMDBUF,Y ; get characters from line ;* Check mode: Read, Write, Append, Merge ldy #$04 A_DA11: ; [DA11] dey ; more modes to check? bmi A_DA1C ; no, -> cmp TblRWAM,Y ; control modes 'R', 'W', 'A', 'M'? bne A_DA11 ; no, -> sty MODE ; save ;* Check file type: Deleted, Sequential, Program, User, reLational A_DA1C: ; [DA1C] ldy #$05 A_DA1E: ; [DA1E] dey ; more file types to check? bmi A_DA29 cmp TblDSPUL,Y ; file types 'D','S','P','U','L'? bne A_DA1E ; no, -> sty TYPE ; save A_DA29: ; [DA29] rts ;****************************************************************************** ; ;** preparation for append Prep4Append: ; [DA2A] jsr OpenChnGetByt2 ; open channel to read, get byte lda #$80 jsr ChkFTypeBit ; last byte? beq Prep4Append ; no, -> jsr GetNxtSector ; get track and sector number ldx SECTOR ; sector number inx txa bne A_DA42 ; not $FF? jsr Buffer2Disk ; close buffer, write block lda #$02 A_DA42: ; [DA42] jsr SetBufPointer3 ; buffer pointer to 2 ldx CURCHN ; channel number lda #$01 sta REWRFLzp,X ; set flag for WRITE lda #$80 ora CURCHN ldx SA sta LINTAB,X ; channel number in table rts ;****************************************************************************** ; ;** Load directory J_DA55: ; [DA55] lda #$0C ; command number 12 sta INSTRU lda #$00 ; default only drive 0 ldx CMDSIZ dex ; only "$" ? beq A_DA6D ; yes, -> dex bne A_DA86 lda CMDBUF+1 ; second character jsr ChkDriveNum ; check drive number bmi A_DA86 ; not 0 or 1? A_DA6D: ; [DA6D] sta DRVNUM ; save drivenumber inc F1CNT ; number of ',' for '=' sign inc F2CNT ; total number of ',' inc FILTBL lda #$80 sta COMFLG ; set wildcard flag lda #'*' sta CMDBUF ; as file name in command buffer sta CMDBUF+1 bne A_DA9E ; always -> A_DA86: ; [DA86] jsr ChkForColon ; test input line for ":" bne A_DA90 ; not found, -> jsr CLR_Flg_inp ; erase flags ldy #$03 A_DA90: ; [DA90] dey dey sty FILTBL ; pointer to drive number in command jsr ChkWildcard ; analyze line jsr ChkFileType ; ascertain file type jsr GetDrvNum2 ; get drive number A_DA9E: ; [DA9E] jsr VerifyDrvNum ; initialize drive if necessary jsr DirHeader ; prepare disk title jsr SrchDirEntry ; load directory jsr CreDirectory ; create and prepare directory jsr GetByteFromBuf ; get byte from buffer ldx CURCHN ; channel number sta OUTREG,X ; byte in output register lda DRVNMB ; drive number sta LSTDRV ; save as last drive number ora #$04 sta DIACFLzp,X ; PRG-flag lda #$00 sta INPPTR ; set pointer back in input buffer rts ;****************************************************************************** ; ;** Close file with actual sec. address CloseFileSA: ; [DAC0] lda #$00 sta WBAM lda SA ; secondary address bne A_DAD4 ; not zero? lda #$00 ; ## why? A is already zero sta DIRLST jsr CloseChannel ; close channel A_DAD1: ; [DAD1] jmp Close17_18 ; close internal channels 17 & 18 A_DAD4: ; [DAD4] cmp #15 ; command channel beq A_DAEC ; yes, -> close all channels jsr CloseFile ; close file lda SA ; secondary address cmp #$02 ; LOAD or SAVE? bcc A_DAD1 ; yes, -> lda ERWORD bne A_DAE9 jmp Out_Err_Msg ; termination A_DAE9: ; [DAE9] jmp J_C1AD ;* Close all channels A_DAEC: ; [DAEC] lda #$0E ; 14 sta SA ; secondary address A_DAF0: ; [DAF0] jsr CloseFile ; close file dec SA ; next secondary address? bpl A_DAF0 ; yes, -> lda ERWORD bne A_DAFF jmp Out_Err_Msg ; termination A_DAFF: ; [DAFF] jmp J_C1AD ;****************************************************************************** ; ;** Close file CloseFile: ; [DB02] ldx SA ; secondary address lda LINTAB,X ; get channel number cmp #$FF ; channel associated? bne A_DB0C ; yes, -> rts ; no, then none A_DB0C: ; [DB0C] and #$0F ; isolate channel number sta CURCHN jsr CheckREL ; check data type cmp #$07 ; direct access? beq A_DB26 ; yes, -> cmp #$04 ; REL file? beq A_DB2C ; yes, -> jsr OpenChan4Write ; channel for writing open bcs A_DB29 ; no file for writing? jsr WriteLastSec ; write last block jsr WriteDirEntry ; write entry in directory and block A_DB26: ; [DB26] jsr WriteBam ; write BAM A_DB29: ; [DB29] jmp CloseChannel ; close channel A_DB2C: ; [DB2C] jsr GetBufWrSec ; get buffer number, write block jsr SwapBuffers2 ; change buffer jsr SetPar2LstSSec ; get last side-sector ldx NumSidSec ; side-sector number stx TEMP4 inc TEMP4 lda #$00 sta TEMP1 sta TEMP2 lda PtrSideSec sec sbc #$0E ; minus 14 for pointer sta TEMP3 jsr CalcSecPtrREL ; calculate block number of file ldx CURCHN ; channel number lda TEMP1 sta RECL,X ; record number lo lda TEMP2 sta RECH,X ; record number hi lda #$40 jsr ChkFTypeBit ; bit 6 set? beq A_DB5F ; no, -> jsr WriteDirEntry ; enter in directory A_DB5F: ; [DB5F] jmp CloseChannel ; close channel ;****************************************************************************** ; ;** Write last block WriteLastSec: ; [DB62] ldx CURCHN ; channel number lda RECL,X ora RECH,X ; number of records = 0? bne A_DB76 ; no, -> jsr SetBufPointer ; set buffer pointer cmp #$02 ; set at 1st byte after link? bne A_DB76 ; no, -> lda #$0D ; CR jsr Write2Buf ; in buffer A_DB76: ; [DB76] jsr SetBufPointer ; set buffer pointer cmp #$02 ; now set at 1st byte after link? bne A_DB8C ; no, -> jsr SwapBuffers2 ; change buffer ;* Decrement number of records ldx CURCHN ; channel number lda RECL,X ; record number lo bne A_DB88 dec RECH,X ; decrement block number hi A_DB88: ; [DB88] dec RECL,X ; and block number lo lda #$00 A_DB8C: ; [DB8C] sec sbc #$01 ; set pointer pha ; number of bytes on last sector lda #$00 jsr SetBufPointer3 ; buffer pointer to zero jsr Write2Buf ; write zero in buffer = last sector pla ; number of bytes on last sector jsr Write2Buf ; write in buffer jsr WriteBlock ; write block to disk jsr VerifyExec ; and verify jmp SwapBuffers2 ; change buffer ;****************************************************************************** ; ;** Directory entry WriteDirEntry: ; [DBA5] ldx CURCHN ; channel number stx WLINDX ; save lda SA ; secondary address pha ; save lda DSEC,X ; sector number in directory sta SECTOR ; set lda DIND,X ; pointer in directory sta INDEX lda DIACFLzp,X and #$01 sta DRVNMB ; drive number lda DirTrack ; 18, directory track sta TRACK ; set jsr GetBufNumber ; increment buffer number pha sta ActBufNum jsr ReadSector ; read directory block ldy #$00 lda BufAddrHB,X ; buffer address sta R1 lda INDEX ; buffer pointer sta R0 lda (R0),Y ; file type and #$20 ; file should be closed? beq A_DC21 ; yes, -> jsr CheckREL ; check file type cmp #$04 ; REL file? beq J_DC29 ; yes, -> lda (R0),Y and #$8F ; erase bits 4,5, and 6 sta (R0),Y ; in file type iny lda (R0),Y ; track number sta TRACK sty TEMP2 ldy #$1B lda (R0),Y ; sector number of the file for pha ; overwriting dey lda (R0),Y ; track number for overwriting set? bne A_DC06 ; yes, -> sta TRACK ; set track number pla sta SECTOR ; sector number lda #$67 jsr CreErrorMsg ; 67, 'illegal track or sector' A_DC06: ; [DC06] pha ;* Erase track number and sector number of the substitute file lda #$00 sta (R0),Y iny sta (R0),Y pla ldy TEMP2 sta (R0),Y ;* Set track & sector number of the new file iny lda (R0),Y sta SECTOR pla sta (R0),Y jsr DelSectorChain jmp J_DC29 A_DC21: ; [DC21] lda (R0),Y ; get file type and #$0F ; isolate bits 0-3 ora #$80 ; set bit 7 for closed file sta (R0),Y ;* Set number of blocks J_DC29: ; [DC29] ldx WLINDX ; channel number ldy #$1C lda RECL,X ; block number lo sta (R0),Y ; in directory entry iny lda RECH,X ; and block number hi sta (R0),Y ; write pla ; buffer number tax lda #$90 ; code for 'write' ora DRVNMB jsr ExecCommand2 ; write block pla sta SA ; secondary address jmp OpenChan4Write ; open channel for writing ;****************************************************************************** ; ;** Read block, allocate buffer RdBlkAllocBuf: ; [DC46] lda #$01 jsr FindRdChanBuf ; find channel and buffer for read jsr ResetPointer lda TYPE ; file type pha ; save asl A ora DRVNMB ; drive number sta DIACFLzp,X jsr ReadBlk2Buf ; read block in buffer ldx CURCHN ; channel number lda TRACK ; last sector? bne A_DC65 ; no, -> lda SECTOR ; sector sta ENDPNT,X ; as end pointer A_DC65: ; [DC65] pla ; file type cmp #$04 ; REL file? bne A_DCA9 ; no, -> ldy SA ; secondary address lda LINTAB,Y ; channel number ora #$40 ; set flag for READ and WRITE sta LINTAB,Y lda RecordSize ; record length sta RecLength,X jsr GetBuffer ; buffer for side-sector found? bpl A_DC81 ; yes, -> jmp NoChannel ; 70, 'no channel' A_DC81: ; [DC81] ldx CURCHN ; channel number sta SIDSECzp,X ldy TRKSS sty TRACK ; track for side-sector ldy SECSS sty SECTOR ; sector for side-sector jsr Par2DiskCtrl2 ; transmit parameters to disk controller jsr ReadSector4 ; read side sector jsr VerifyExec ; and verify J_DC98: ; [DC98] ldx CURCHN ; channel number lda #$02 sta WRIPNT,X ; pointer for writing lda #$00 jsr SetBufPointer3 ; buffer pointer to zero jsr NxtByte2Out ; find next record jmp GetSector2 ; get track and sector number A_DCA9: ; [DCA9] jsr ReadBuffer2A ; get byte from buffer ldx CURCHN ; channel number sta OUTREG,X ; byte in output register lda #$88 ; set flag for READ sta REWRFLzp,X rts ;****************************************************************************** ; ;** Reset pointer ResetPointer: ; [DCB6] ldx CURCHN ; channel number lda BUF0CH1zp,X ; buffer number asl A ; times 2 tay lda #$02 sta BUFTABab,Y ; buffer pointer lo lda BUF1CH1zp,X ora #$80 ; set bit 7 sta BUF1CH1zp,X asl A tay lda #$02 sta BUFTABab,Y ; buffer pointer lo ; reset number of blocks lda #$00 sta RECL,X ; block number lo sta RECH,X ; block number hi lda #$00 sta ENDPNT,X ; end pointer rts ;****************************************************************************** ; ;** Construct a new block AllocNewSec: ; [DCDA] jsr FreeSecAlloc ; find free sector in BAM lda #$01 jsr FindWrChanBuf ; open channel jsr Par2DiskCtrl ; transmit parameter to disk controller jsr ResetPointer ; reset pointer ldx CURCHN ; channel number lda TYPE ; file type pha asl A ora DRVNMB ; drive number sta DIACFLzp,X ; save as flag pla cmp #$04 ; REL file? beq A_DCFD ; yes, -> lda #$01 sta REWRFLzp,X ; set WRITE flag rts A_DCFD: ; [DCFD] ldy SA ; secondary address lda LINTAB,Y ; channel number in table and #$3F ; erase the top two bits ora #$40 ; set bit 6 sta LINTAB,Y ; READ and WRITE flag lda RecordSize ; record length sta RecLength,X ; in table jsr GetBuffer ; buffer found? bpl A_DD16 ; yes, -> jmp NoChannel ; 70, 'no channel' A_DD16: ; [DD16] ldx CURCHN ; channel number sta SIDSECzp,X ; buffer number for side-sector jsr EraseBuffer ; erase buffer jsr FindAllocSec ; find free block in BAM lda TRACK ; track sta TRKSS ; for side-sector lda SECTOR ; sector sta SECSS ; for side-sector ldx CURCHN ; channel number lda SIDSECzp,X ; buffer number jsr Par2DiskCtrl2 ; transmit parameter to disk controller lda #$00 jsr SetBufPtrSS2 ; buffer pointer to zero lda #$00 jsr WrBytSidSec lda #$11 ; 17 jsr WrBytSidSec ; as end pointer in buffer lda #$00 ; zero jsr WrBytSidSec ; as side-sector number in buffer lda RecordSize ; record length jsr WrBytSidSec ; in buffer lda TRACK ; track number of this block jsr WrBytSidSec ; in buffer lda SECTOR ; sector number jsr WrBytSidSec ; in buffer lda #$10 ; 16 jsr SetBufPtrSS2 ; buffer pointer to 16 jsr GetSector2 ; get track and sector number lda TRACK ; track number of the first data block jsr WrBytSidSec ; in buffer lda SECTOR ; sector number of the first data block jsr WrBytSidSec ; in buffer jsr WriteSector4 ; write block to disk jsr VerifyExec ; and check lda #$02 jsr SetBufPointer3 ; buffer pointer to 2 ldx CURCHN ; channel number sec lda #$00 sbc RecLength,X ; record length sta WRIPNT,X ; pointer for writing jsr CreateRecords jsr SetLinkLstRec ; write link bytes in buffer jsr WriteSector3 ; write block to disk jsr VerifyExec ; and check jsr WriteBam ; write BAM jmp J_DC98 ; and done ;****************************************************************************** ; ;** Write byte in side-sector block WrBytSidSec: ; [DD8D] pha ; save byte ldx CURCHN ; channel number lda SIDSECzp,X ; buffer number of the side-sector jmp Write2Buf2 ; write byte in buffer ;****************************************************************************** ; ;** Manipulate flags ## used where ??? E_DD95: ; [DD95] bcc DeleteFlags ; [DD97] SetFlags: ; [DD97] ldx CURCHN ; channel number ora DIACFLzp,X ; set flag bne A_DDA3 ; (IMHO) always -> ; [DD9D] DeleteFlags: ; [DD9D] ldx CURCHN ; channel number eor #$FF and DIACFLzp,X ; erase flag A_DDA3: ; [DDA3] sta DIACFLzp,X rts ;****************************************************************************** ; ;** Check file type bit(s) ChkFTypeBit: ; [DDA6] ldx CURCHN ; channel number and DIACFLzp,X ; test flag rts ;****************************************************************************** ; ;** Verify command code for writing Chk4Write: ; [DDAB] jsr GetBufNumber ; get buffer number tax lda LSTJOB,X and #$F0 ; isolate command code cmp #$90 ; code for writing? rts ;****************************************************************************** ; ;** Check if the file is open IsFileOpen: ; [DDB7] ldx #$00 A_DDB9: ; [DDB9] stx TEMP2 ; counter for secondary address lda LINTAB,X ; get channel number from table cmp #$FF bne A_DDCA ; file open? A_DDC2: ; [DDC2] ldx TEMP2 inx ; increment counter cpx #$10 ; smaller than 16? bcc A_DDB9 rts A_DDCA: ; [DDCA] stx TEMP2 and #$3F ; isolate channel number tay lda DIACFLab,Y and #$01 ; isolate drive number sta TEMP1 ldx ENTFND lda DRVNUM,X and #$01 ; isolate drive number cmp TEMP1 ; same drive? bne A_DDC2 ; no, -> lda DSEC,Y ; sector number in directory cmp DIRSECP,X ; same as file? bne A_DDC2 ; no, -> lda DIND,Y cmp BUFPTR,X ; same pointer? bne A_DDC2 ; no, -> clc rts ;****************************************************************************** ; ;** write BAM sector ??? GetBufWrSec: ; [DDF1] jsr GetBufNumber2 ; dirty flag set? bvc A_DDFC ; no, -> no write needed jsr WriteSector3 ; write block jsr VerifyExec ; and verify A_DDFC: ; [DDFC] rts ;****************************************************************************** ; ;** Write bytes for following track WrNxtSecBuf: ; [DDFD] jsr SetBufPtrZero ; set buffer pointer lda TRACK ; track number sta (DIRBUF),Y ; in buffer iny lda SECTOR ; sector number sta (DIRBUF),Y ; in buffer jmp WrBufNum2Tbl ; set rel-flag ;****************************************************************************** ; ;** Get next track and sector numbers GetNxtTraSec: ; [DE0C] jsr SetBufPtrZero ; set buffer pointer lda (DIRBUF),Y ; following track number sta TRACK iny lda (DIRBUF),Y ; and get sector number sta SECTOR rts ;****************************************************************************** ; ;** Set link for last block of record SetLinkLstRec: ; [DE19] jsr SetBufPtrZero ; set buffer pointer lda #$00 ; zero sta (DIRBUF),Y ; as track number iny ldx CURCHN ; channel number lda WRIPNT,X ; pointer in block tax dex ; minus 1 txa sta (DIRBUF),Y ; as pointer in block rts ;****************************************************************************** ; ;** Set buffer pointer to zero SetBufPtrZero: ; [DE2B] jsr GetBufNumber ; get buffer number asl A ; times 2 tax lda BUFTABzp+1,X ; buffer pointer hi sta DIRBUF+1 lda #$00 sta DIRBUF ; buffer pointer lo ldy #$00 rts ;****************************************************************************** ; ;** Get track and Sector GetTrackSector: ; [DE3B] jsr OpenChan4Read ; get channel number GetSector2: ; [DE3E] jsr GetBufNumber ; get buffer number sta ActBufNum ; save asl A ; times 2 tay lda TRASECab,Y ; get track sta TRACK lda TRASECab+1,Y ; and sector number from disk controller sta SECTOR rts ;** WriteSector2: lda #$90 ; command code for writing sta CMD bne A_DE7F ; always -> ;** ReadSector2: ; [DE57] lda #$80 ; command code for reading sta CMD bne A_DE7F ; always -> ;** WriteSector3: ; [DE5E] lda #$90 ; command code for writing sta CMD bne A_DE8B ; always -> ;??? used ??? lda #$80 ; command code for reading sta CMD bne A_DE8B ;** WriteSector4: ; [DE6C] lda #$90 ; command code for writing sta CMD bne A_DE75 ;** ReadSector4: ; [DE73] lda #$80 ; command code for reading A_DE75: ; [DE75] sta CMD ldx CURCHN ; channel number lda SIDSECzp,X ; side-sector buffer number tax ; buffer associated? bpl A_DE92 ; yes,-> A_DE7F: ; [DE7F] jsr Par2DiskCtrl ; generate header for disk controller jsr GetBufNumber ; get buffer number tax lda DRVNMB ; drive number sta LSTJOB,X A_DE8B: ; [DE8B] jsr ClrDirtyFlg jsr GetBufNumber ; get buffer number tax A_DE92: ; [DE92] jmp ChkTrackSector ; write block ;****************************************************************************** ; ;** Get next track and sector from buffer GetNxtSector: ; [DE95] lda #$00 jsr SetBufPointer3 ; buffer pointer to zero jsr GetByteFromBuf ; get byte sta TRACK ; save as track jsr GetByteFromBuf ; get byte sta SECTOR ; as sector rts ;****************************************************************************** ; ;** Coppy buffer contents ; A = starting point ; X = 'from' buffer ; Y = 'to' buffer CopyBuffer: ; [DEA5] pha lda #$00 sta TEMP0 sta TEMP2 lda BufAddrHB,Y sta TEMP1 lda BufAddrHB,X sta TEMP3 pla tay dey A_DEB9: ; [DEB9] lda (TEMP0),Y sta (TEMP2),Y dey bpl A_DEB9 rts ;****************************************************************************** ; ;** Erase the buffer EraseBuffer: ; [DEC1] tay ; buffer number lda BufAddrHB,Y ; get hi-address sta TEMP1 lda #$00 ; set lo-address sta TEMP0 tay A_DECC: ; [DECC] sta (TEMP0),Y ; erase buffer iny bne A_DECC rts ;****************************************************************************** ; ;** Get side-sector number GetNumSideSec: ; [DED2] lda #$00 jsr SetBufPtrSS ; buffer pointer to zero ldy #$02 lda (DIRBUF),Y ; byte 2 contains side-sector number rts ;****************************************************************************** ; ;** Set buffer pointer to side-sector SetBufPtrSS: ; [DEDC] sta DIRBUF ldx CURCHN ; channel number lda SIDSECzp,X ; buffer number tax lda BufAddrHB,X ; buffer address hi sta DIRBUF+1 ; set rts ;****************************************************************************** ; ;** Buffer pointer for side-sector SetBufPtrSS2: ; [DEE9] pha ; pointer in side-sector jsr SetBufPtrSS ; set buffer pointer pha txa ; buffer number asl A ; times 2 tax pla sta BUFTABzp+1,X ; buffer pointer hi pla sta BUFTABzp,X ; buffer pointer lo rts ;****************************************************************************** ; ;** Get side sector and buffer pointer GetSideSector: ; [DEF8] jsr IsSidSecInBuf ; is side-sector in buffer? bmi A_DF0B ; no, -> bvc A_DF12 ; ok ldx CURCHN ; channel number lda SIDSECzp,X ; buffer number jsr ReadSideSec ; read side-sector jsr IsSidSecInBuf ; and check if in buffer bpl A_DF12 ; yes, -> A_DF0B: ; [DF0B] jsr SetPar2LstSSec ; get last side-sector bit MaskBits+1 ; set V bit rts A_DF12: ; [DF12] lda PtrSideSec ; side-sector and pointer jsr SetBufPtrSS2 ; set pointer in side-sector bit MaskBits ; erase V bit rts ;****************************************************************************** ; ;** Read side-sector ReadSideSec: ; [DF1B] sta ActBufNum ; buffer number lda #$80 ; command code for reading bne A_DF25 ; always -> ;****************************************************************************** ; ;** Write side-sector ; !!! not used IMHO ==> sta ActBufNum ; buffer number lda #$90 ; command code for writing ; <== A_DF25: ; [DF25] pha lda DIACFLzp,X and #$01 ; isolate drive number sta DRVNMB pla ora DRVNMB ; command code plus drive number sta CMD ; save lda (DIRBUF),Y ; track number sta TRACK iny lda (DIRBUF),Y ; sector number sta SECTOR lda ActBufNum ; buffer number jsr Par2DiskCtrl2 ; transmit parameter to disk controller ldx ActBufNum ; buffer number jmp ExecCommand ; transmit command to disk controller ;****************************************************************************** ; ;** Set buffer pointer in side-sector SetPtrSidSec: ; [DF45] ldx CURCHN ; channel number lda SIDSECzp,X ; buffer number jmp SetBufPointer2 ; set buffer pointer ;****************************************************************************** ; ;** Calculate number of blocks in a REL file A_DF4C: ; [DF4C] lda #120 ; 120 block pointers per side-sector jsr IncSidSecPtr ; add to TEMP1/TEMP2 CalcSecPtrREL: ; [DF51] dex ; next side-sector? bpl A_DF4C ; yes, -> lda TEMP3 ; pointer value in last block lsr A ; divided by 2 jsr IncSidSecPtr ; add to previous sum lda TEMP4 ; number of the side-sector block IncSidSecPtr: ; [DF5C] clc adc TEMP1 sta TEMP1 ; add bcc A_DF65 inc TEMP2 A_DF65: ; [DF65] rts ;****************************************************************************** ; ;** Verify side-sector in buffer IsSidSecInBuf: ; [DF66] jsr GetNumSideSec ; get side-sector number cmp NumSidSec ; = number of necessary block? bne A_DF7B ; no, -> ldy PtrSideSec ; pointer in side-sector lda (DIRBUF),Y ; track number, last sector? beq A_DF77 ; yes, -> bit MaskBits ; erase bits rts A_DF77: ; [DF77] bit MaskBits+2 ; set N-bit rts A_DF7B: ; [DF7B] lda NumSidSec ; side-sector number cmp #$06 ; 6 or greater? bcs A_DF8B ; yes, -> asl A tay lda #$04 sta DIRBUF lda (DIRBUF),Y ; track number bne A_DF8F A_DF8B: ; [DF8B] bit MaskBits+3 ; set N and V bits rts A_DF8F: ; [DF8F] bit MaskBits+1 ; set V bit rts ;****************************************************************************** ; ;** Get buffer number GetBufNumber: ; [DF93] ldx CURCHN ; channel number lda BUF0CH1zp,X ; buffer number bpl A_DF9B lda BUF1CH1zp,X ; buffer number from second table A_DF9B: ; [DF9B] and #$BF ; erase V bit rts ;****************************************************************************** ; ;** Get buffer number GetBufNumber2: ; [DF9E] ldx CURCHN ; channel number stx LstUsedBuf ; save lda BUF0CH1zp,X ; get buffer number bpl A_DFB0 ; buffer allocated txa clc adc #$07 ; increment number by 7 sta LstUsedBuf ; and save lda BUF1CH1zp,X ; buffer number from table 2 A_DFB0: ; [DFB0] sta TEMP1 and #$1F ; erase the highest 3 bits bit TEMP1 rts ;****************************************************************************** ; ;** Check if the buffer for the current channel is free ChkBufferFree: ; [DFB7] ldx CURCHN ; channel number lda BUF0CH1zp,X ; buffer number bmi A_DFBF ; buffer free? lda BUF1CH1zp,X ; buffer number from table 2 A_DFBF: ; [DFBF] cmp #$FF ; free? rts ;** DeactivateBuf: ; [DFC2] ldx CURCHN ora #$80 ldy BUF0CH1zp,X bpl A_DFCD sta BUF0CH1zp,X rts A_DFCD: ; [DFCD] sta BUF1CH1zp,X rts ;****************************************************************************** ; ;** Get next record in REL file GetNxtRelRec: ; [DFD0] lda #$20 jsr DeleteFlags ; erase bit 5 lda #$80 jsr ChkFTypeBit ; bit 7 set? bne A_E01D ; yes, -> ldx CURCHN ; channel number inc RECL,X ; increment record number bne A_DFE4 inc RECH,X ; record number hi A_DFE4: ; [DFE4] ldx CURCHN ; channel number lda WRIPNT,X ; write pointer beq A_E018 ; zero? jsr SetBufPointer ; set buffer pointer ldx CURCHN ; channel number cmp WRIPNT,X ; buffer pointer smaller than write ; pointer bcc A_DFF6 ; yes, -> jsr WrSecRdNxtSec ; write block, read next block A_DFF6: ; [DFF6] ldx CURCHN ; channel number lda WRIPNT,X ; write pointer jsr SetBufPointer3 ; set buffer pointer = write pointer lda (BUFTABzp,X) ; byte from buffer .by $85 ; sta DATA ; put in output register