;------------------------------------------------------------------------------ ; ; 1541 with 8 bits IDE interface, JiffyDOS version V0.4 ; ; - images ; - directory for images ; ; ; Remark: the main idea is to use only 8 of the 16 bits of the interface. ; This means that only half of the capacity of the drive is used. But ; IMHO even then an old 20 GB harddisk can store all available ; programs that ever have been programmed for all the Commodores with ; an IEC bus. ; Using only 8 bits also solves the problem what to do with the 512 ; bytes sized sectors. Saving a 256 bytes sized C= sector on a 512 ; bytes one would mean we first have to load it because we HAVE to ; write 512 bytes and thus have to preserve the other C= sector first. ; Unfortunately the parameters of the HD cannot be read with an 8 bits ; interface as half of the information will be discarded. The disk ; parameters have to be provided in another way or the disk has to be ; pre-formatted by a PC. ; ; ; ;------------------------------------------------------------------------------ ; Changes so far in original routines: ; 00- skip ROM test ; 02- initialization of the added I/O ; 04- read header of sector ; 06- read sector ; 08- write sector ; 10- verify data ; 11- step head ; 12- format track ; 16- Start up text ; 19- new commands .eq JOBSzp = $00 .eq JOBSab = $0000 .eq TRASECzp = $06 ; track/sector for job .eq TRASECab = $0006 ; free 012 .. 017 .eq HDRTRK = $18 ; track number .eq HDRSEC = $19 ; sector number ; Free 01A .. 01B .eq WPSW0 = $1C ; write protect drive 0 ; Free 01D .. 01F .eq DRVST = $20 ; disk drive status (drive 0) 1/0 ; bit 4 = shut down drive motor y/n ; bit 5 = drive motor on/off ; bit 6 = head stepping on/off ; bit 7 = drive ready no/yes ; Free 021 .eq DRVTRK = $22 ; current track under head (drive 0) .eq VIC20mode = $23 ; VIC-20 / C64 mode ; Free 024 .. 025 .eq SAVPNT = $2E ; temporary savepoint .eq BUFPNT = $30 ; pointer to currently active buffer .eq J_BUFPNT = $0030 .eq HDRPNT = $32 ; pointer to active values in hdr table ; Free 034 .. 03D .eq CURDRV = $3E ; current drive ($FF is none) .eq JOBN = $3F ; position of last job in queue (0-5) .eq TRACC = $40 ; byte counter for GCR/binary convers. .eq NXTJOB = $41 ; position of next job in queue (0-5) ; Free 042 .eq SECCNT = $43 ; sector counter for format routine .eq WORK = $44 ; temporary workspace .eq JOB = $45 ; temporary storage of job code ; Free 046 .. 048 .eq SAVSP = $49 ; temporary save of stackpointer ; Free 04A .eq TMP = $4B ; temporary storage .eq CSECT = $4C ; last sector read .eq NEXTS = $4D ; next sector to service ; Free 04E .. 050 .eq FTNUM = $51 ; current track to be formatted ; Free 052 .. 064 .eq VNMI = $65 ; pointer to NMI routine .eq J_VNMI = $0065 .eq NMIFLG = $67 ; indicator if NMI in progress ; Free 068 .. 06A .eq USRJMP = $6B ; LB user jump .eq BMPNT = $6D ; pointer to start of bitmap ($0400) .eq TEMP0 = $6F .eq J_TEMP0 = $006F .eq TEMP1 = $70 .eq TEMP2 = $71 .eq TEMP3 = $72 .eq TEMP4 = $73 .eq TEMP5 = $74 .eq IP = $75 ; indirect pointer variable .eq J_IP = $0075 .eq LSNADR = $77 .eq TLKADR = $78 .eq LSNACT = $79 ; active listener flag .eq TLKACT = $7A ; active talker flag .eq ATNPND = $7C ; ATN pending .eq ATNMOD = $7D ; 6502 in attention mode .eq LastTrack = $7E ; last used track ; Free 07F .eq TRACK = $80 ; current track number .eq SECTOR = $81 ; current sector number .eq CURCHN = $82 ; current channel .eq SA = $83 ; secundair address .eq ORGSA = $84 ; original secundair address .eq DATA = $85 ; temporary databyte .eq R0 = $86 ; temporary result .eq R1 = $87 .eq R2 = $88 .eq J_R2 = $0088 .eq R3 = $89 .eq R4 = $8A .eq RESULT0 = $8B ; result area .eq RESULT1 = $8C .eq RESULT2 = $8D .eq RESULT3 = $8E .eq ACCUM0 = $8F ; accumulator .eq ACCUM1 = $90 .eq ACCUM2 = $91 .eq ACCUM3 = $92 .eq ACCUM4 = $93 .eq DIRBUF = $94 ; directory buffer ($0205) .eq CONT = $98 ; bit counter for serial .eq BUFTABzp = $99 ; $99..A2 pointer to buffer0..4 ; normally: $0300..$0700 .eq BUFTABab = $0099 .eq INPPTR = $A3 ; pointer to inputbuffer $0200 .eq ERRPTR = $A5 ; pointer to errorbuffer $02D5 .eq BUF0CH1zp = $A7 .eq BUF0CH1ab = $00A7 .eq BUF0CH5 = $AB .eq BUF0CH6 = $AC .eq BUF0CH7 = $AD .eq BUF1CH1zp = $AE .eq BUF1CH1ab = $00AE .eq BUF1CH7 = $B4 .eq RECL = $B5 .eq RECH = $BB .eq WRIPNTab = $00C1 ; Write pointer .eq WRIPNT = $C1 ; Write pointer .eq RecLength = $C7 ; $C7..CC Rec length for every buffer .eq SIDSECzp = $CD .eq SIDSECab = $00CD .eq CHNNUM = $D3 .eq CHNNUM1 = $D4 ; $D4..7 Channel numbers .eq CHNNUM2 = $D5 .eq CHNNUM3 = $D6 .eq CHNNUM4 = $D7 .eq DIRSECP = $D8 ; $D8..C pointer directory sectors .eq BUFPTR = $DD ; $DD..E1 bufferpointers .eq DRVNUM = $E2 ; $E2..6 drive numbers .eq COMFLG = $E7 ; $E7..A used for marking comma's .eq DIACFLab = $00EC ; Flag for direct access .eq DIACFLzp = $EC .eq REWRFLab = $00F2 ; read/write flag .eq REWRFLzp = $F2 .eq WRFLAG = $F6 ; Write-flag .eq RDFLAG = $F7 ; Read-flag .eq EOIFLG = $F8 .eq JOBNUM = $F9 ; job number .eq LRUTBLzp = $FA ; least recently used table .eq LRUTBLab = $00FA .eq A_0101 = $0101 .eq A_0104 = $0104 .eq LBAfrom = $01F0 .eq LBAto = $01F3 .eq IDEtmp0 = $01F6 .eq IDEtmp1 = $01F7 .eq IDEtmp2 = $01F8 .eq IDEtmp3 = $01F9 .eq IDEtmp4 = $01FA .eq IDEtmp5 = $01FB .eq ImageLBA = $01FC ; actual choosen image .eq CMDBUF = $0200 .eq INSTRU = $022A ; instruction number .eq LINTAB = $022B .eq CH4WFL = $023A ; Write-flag channel 4 .eq CH5WFL = $023B ; Write-flag channel 5 .eq A_023C = $023C .eq A_023D = $023D .eq OUTREG = $023E ; output registers .eq ENDPNT = $0244 .eq TYPE = $024A ; active file type .eq STRSIZ = $024B ; length of string .eq TEMPSA = $024C ; temporary secondary address .eq CMD = $024D ; temporary job command .eq BSTSEC = $024E ; best sector to do ; The original ROM uses BUFUSEL and BUFUSEH to note whether a buffer is used or ; not. BUFUSEH is an inheritance of the old IEEE drives which had more then ; eight buffers. BUFUSEH is ommited in this version. .eq BUFUSEL = $024F ; .eq BUFUSEH = $0250 ; Free 0250 .eq MDIRTY = $0251 ; <> 0 means: BAM changed flag (dr 0) ; $0252 = same for drive 1 .eq ENTFND = $0253 ; directory entry found flag .eq DIRLST = $0254 ; directory listing flag .eq CMDWAT = $0255 ; command waiting flag .eq LINUSE = $0256 ; LINDX use word .eq LBUSED = $0257 ; last buffer used .eq RECSIZ = $0258 ; record size (directory routine) .eq TRKSS = $0259 ; side sector track .eq SECSS = $025A ; side sector sector .eq LSTJOB = $025B ; last job / drive number .eq DSEC = $0260 ; sector of directory entry by buffer .eq DIND = $0266 ; index of directory entry by buffer .eq ERWORD = $026C ; error word .eq DISKID1 = $026D .eq DISKID2 = $026E .eq PRGSEC = $026F ; last program sector .eq WLINDX = $0270 ; write LINDX .eq NBTEMP0 = $0272 .eq NBTEMP1 = $0273 .eq CMDSIZ = $0274 ; size of command string .eq CHAR = $0275 ; character under parser .eq LIMIT = $0276 ; PTR limit in comparison .eq F1CNT = $0277 ; file stream 1 count .eq F2CNT = $0278 ; file stream 2 count / number of drives .eq F2PTR = $0279 ; file stream 2 pointer .eq FILTBL = $027A ; table of filename pointers .eq FILTRK = $0280 ; first file link (track) .eq FILSEC = $0285 ; first file link (sector) .eq PATFLG = $028A ; pattern present flag .eq IMAGE = $028B ; file stream image / flag syntax check .eq LBAimage = $028C ; Byte 1, 2, and 3 of LBA of momentary ; ... $028E image. 03 00 00 = root .eq FOUND = $028F ; found flag in directory searches .eq DIRSEC = $0290 ; directory sector .eq DELSEC = $0291 ; sector of first available entry .eq DELIND = $0292 ; index of first available entry .eq LSTBUF = $0293 ; O if last block .eq INDEX = $0294 ; current index in buffer .eq FILCNT = $0295 ; counter of file entries .eq TYPFLG = $0296 ; match by type of flag .eq MODE = $0297 ; active file mode (R,W) .eq JOBRTN = $0298 ; job return flag .eq EPTR = $0299 ; pointer for recovery .eq TOFF = $029A ; total track offset .eq UBAM = $029B ; last BAM update pointer ; free 029C .eq TBAM = $029D ; track # of BAM image .eq BAMima = $02A1 ; BAM images .eq NameBuffer = $02B1 ; directory output buffer .eq ERRBUF = $02D5 ; error message output buffer .eq WBAM = $02F9 ; 'don't write BAM'-flag. set at start .eq NDBL = $02FA ; # of disk blocks free (lo byte 0/1) ; free 02FB .eq NDBH = $02FC ; # of disk blocks free (hi byte 0/1) ; free 02FD..02FF .eq BUF0 = $0300 .eq A_0345 = $0345 .eq BUF2 = $0500 .eq BUF3 = $0600 .eq ErrorCount = $0620 ;+------+-----+-----+---+---+---+----------------+---------------+ ;| Addr | CS0 | CS1 |A2 |A1 |A0 | Read (-IOR) | Write (-IOW) | ;+------+-----+-----+---+---+---+----------------+---------------+-----------+ ;| | 0 | 0 | X | X | X | ILLEGAL | ILLEGAL | | ;+------+-----+-----+---+---+---+----------------+---------------+-----------+ ;| 1000 | 0 | 1 | 0 | 0 | 0 | Data Port | Data Port | <--+ | ;| 1001 | 0 | 1 | 0 | 0 | 1 | Error Register | Precomp | | | ;| 1002 | 0 | 1 | 0 | 1 | 0 | Sector Count | Sector Count | Command | ;| 1003 | 0 | 1 | 0 | 1 | 1 | Sector Number | Sector Number | Block | ;| 1004 | 0 | 1 | 1 | 0 | 0 | Cylinder Low | Cylinder Low | Registers | ;| 1005 | 0 | 1 | 1 | 0 | 1 | Cylinder High | Cylinder High | | | ;| 1006 | 0 | 1 | 1 | 1 | 0 | Drive / Head | Drive / Head | | | ;| 1007 | 0 | 1 | 1 | 1 | 1 | Status | Command | <--+ | ;+------+-----+-----+---+---+---+----------------+---------------+-----------+ ;| 1008 | 1 | 0 | 0 | 0 | 0 | High Impedance | Not Used | Control | ;| ... | 1 | 0 | ... | High Impedance | Not Used | Block | ;| 100D | 1 | 0 | 1 | 0 | 1 | High Impedance | Not Used | Registers | ;| 100E | 1 | 0 | 1 | 1 | 0 | Altern Status | Device Control| | | ;| 100F | 1 | 0 | 1 | 1 | 1 | Drive Address | Not Used | <--+ | ;+------+-----+-----+---+---+---+----------------+---------------+-----------+ ;| | 1 | 1 | X | X | X | High Impedance | Not Used | | ;+------+-----+-----+---+---+---+----------------+---------------+-----------+ .eq IDEcs0 = $1000 ; CS0 .eq IDEdata = IDEcs0 + 0 .eq IDEerror = IDEcs0 + 1 .eq IDEnumSec = IDEcs0 + 2 ; number of sectors .eq IDElba0 = IDEcs0 + 3 ; starts counting from ONE !!! .eq IDElba1 = IDEcs0 + 4 .eq IDElba2 = IDEcs0 + 5 .eq IDElba3 = IDEcs0 + 6 .eq IDEstatus = IDEcs0 + 7 ; when reading .eq IDEcommand = IDEcs0 + 7 ; when writing .eq IDEcs1 = IDEcs0 + 8 ; CS1 .eq IDEcontrol = IDEcs0 + 14 ; Register Designation Function ; 0 ORA or IRB Output or input register B ; 1 ORA or IRA Output or input register A ; 2 DDRB Data direction register B ; 3 DDRA Data direction register A ; 4 T1C-L T1 low-byte latch or T1 low-byte counter ; 5 T1C-H T1 high-byte counter ; 6 T1L-L T1 low-byte latch ; 7 T1L-H T1 high-byte latch ; 8 T2C-L T2 low-byte latch or T2 low-byte counter ; 9 T2C-H T2 high-byte counter ; 10 SR Shift Register ; 11 ACR Auxiliary Control Register ; 12 PCR Peripheral Control Register ; 13 IFR Interrupt Flag Register ; 14 IER Interrupt Enable Register ; 15 ORA or IRA Identical to offset 1 but no handshake .eq PortB1 = $1800 ; bit 0 = DATA in ; bit 1 = DATA out ; bit 2 = CLOCK in ; bit 3 = CLOCK out ; bit 4 = ATN out ; bit 5 = device number bit 0 ; bit 6 = device number bit 1 ; bit 7 = ATN in .eq PortA1 = $1801 ; not used .eq DDRB1 = $1802 .eq DDRA1 = $1803 .eq T1CL1 = $1804 .eq T1CH1 = $1805 .eq T1LL1 = $1806 .eq T1LH1 = $1807 .eq T2CL1 = $1808 .eq T2CH1 = $1809 .eq SR1 = $180A .eq ACR1 = $180B .eq PCR1 = $180C .eq IFR1 = $180D .eq IER1 = $180E .eq IRA1 = $180F .eq PortB2 = $1C00 ; bit 0 = stepping motor bit 0 ; bit 1 = stepping motor bit 1 ; bit 2 = motor ON/OFF ; bit 3 = drive 0 LED ; bit 4 = write protect sense ; bit 5 = density select 0 ; bit 6 = density select 1 ; bit 7 = SYNC detect line .eq PortA2 = $1C01 ; GCR data I/O to diskette .eq DDRB2 = $1C02 .eq DDRA2 = $1C03 .eq T1CL2 = $1C04 .eq T1CH2 = $1C05 .eq T1LL2 = $1C06 .eq T1LH2 = $1C07 .eq T2CL2 = $1C08 .eq T2CH2 = $1C09 .eq SR2 = $1C0A .eq ACR2 = $1C0B .eq PCR2 = $1C0C .eq IFR2 = $1C0D .eq IER2 = $1C0E .eq IRA2 = $1C0F .eq POSTcode = PortA1 .eq POSTcode2 = $1400 .eq POSTcode3 = $1401 ; Constants .eq NewStack = $80 ;============================================================================== .ba $C000 ; This table simplifies the conversion from D64 track to the lineair sector ; numbering used by the harddisk ; Sector Track Tracktable .wo 1 ; 1 .wo 22 ; 2 .wo 43 ; 3 .wo 64 ; 4 .wo 85 ; 5 .wo 106 ; 6 .wo 127 ; 7 .wo 148 ; 8 .wo 169 ; 9 .wo 190 ; 10 .wo 211 ; 11 .wo 232 ; 12 .wo 253 ; 13 .wo 274 ; 14 .wo 295 ; 15 .wo 316 ; 16 .wo 337 ; 17 .wo 358 ; 18 .wo 377 ; 19 .wo 396 ; 20 .wo 415 ; 21 .wo 434 ; 22 .wo 453 ; 23 .wo 472 ; 24 .wo 491 ; 25 .wo 509 ; 26 .wo 527 ; 27 .wo 545 ; 28 .wo 563 ; 29 .wo 581 ; 30 .wo 599 ; 31 .wo 616 ; 32 .wo 633 ; 33 .wo 650 ; 34 .wo 667 ; 35 .wo 684 ; 36 .wo 701 ; 37 .wo 718 ; 38 .wo 735 ; 39 .wo 752 ; 40 TrackSector .by 20 ; 1 .by 20 ; 2 .by 20 ; 3 .by 20 ; 4 .by 20 ; 5 .by 20 ; 6 .by 20 ; 7 .by 20 ; 8 .by 20 ; 9 .by 20 ; 10 .by 20 ; 11 .by 20 ; 12 .by 20 ; 13 .by 20 ; 14 .by 20 ; 15 .by 20 ; 16 .by 20 ; 17 .by 18 ; 18 .by 18 ; 19 .by 18 ; 20 .by 18 ; 21 .by 18 ; 22 .by 18 ; 23 .by 18 ; 24 .by 17 ; 25 .by 17 ; 26 .by 17 ; 27 .by 17 ; 28 .by 17 ; 29 .by 17 ; 30 .by 16 ; 31 .by 16 ; 32 .by 16 ; 33 .by 16 ; 34 .by 16 ; 35 .by 16 ; 36 .by 16 ; 37 .by 16 ; 38 .by 16 ; 39 .by 16 ; 40 ;** Turn LED on with checking drive ; in: - ; out: - ; used: A LedOn ; [C100] sei LedOn2 lda PortB2 ora #$08 ; LED on sta PortB2 cli rts ;** Clear error flags ; in: - ; out: - ; used: A ClrErrorFlags ; [C123] lda #$00 sta ERWORD rts ;** Prepare for LED flash after error ; in: - ; out: - ; used: A PrepLedFlash ; [C12C] sei lda #$50 sta ERWORD jmp LedOn2 ;** Interprete command from computer ; in: - ; out: - ; used: A X Y InterprCmnd ; [C146] lda #$00 sta WBAM jsr OK2Buffer ; OK message in buffer [E6BC] lda ORGSA ; secundair address bpl L_C160 and #$0F cmp #$0F ; 15, command-channel ? beq L_C160 ; yes, -> jmp OPEN_N15 ; OPEN command [D7B4] L_C160 jsr ChkLineLength ; [C2B3] lda (INPPTR),Y ; get first char sta CHAR ; mark it ; &&&19 First check for new commands lda (INPPTR),Y ; get first char cmp #'C' ; CI or CP? beq t_C166 ; yes, -> cmp #'F' ; FCD = Format Complete Disk? bne t_C169 ; no, -> iny lda (INPPTR),Y ; get second char cmp #'C' bne t_C168 ; no, -> iny lda (INPPTR),Y ; get third char dey cmp #'D' bne t_C168 ; no, -> jmp FormatCDisk t_C166 iny lda (INPPTR),Y ; get second char cmp #'I' ; CI? bne t_C167 ; no, -> maybe CP dey ldx #14 ; CI bne L_C17A ; always -> t_C167 cmp #'P' ; CP? bne t_C168 ; no, -> original routine dey ldx #13 ; CP bne L_C17A ; always -> t_C168 dey ; restore Y t_C169 ldx #11 ; number of commands + 1 L_C16A lda TblCommands,X ; compare commands cmp CHAR ; with char beq L_C17A ; found, -> dex bpl L_C16A jmp Error31 ; 31, 'syntax error' L_C17A stx INSTRU cpx #10 ; commandnumber < 11 ? bcc L_C184 ; yes -> jsr ChkSyntax ; test for R, S or N [C1EE] L_C184 ldx INSTRU ; X = commandnumber lda CmdAddrLB,X sta TEMP0 lda CmdAddrHB,X sta TEMP1 jmp (TEMP0) ; jump to command ;** Table of command words TblCommands ; [FE89] .by "V" ; Validate .by "I" ; Initialize .by "D" ; D (back up, not used) .by "M" ; Memory .by "B" ; Block .by "U" ; User .by "P" ; Position .by "&" ; USR execute .by "C" ; Copy .by "R" ; Rename .by "S" ; Scratch .by "N" ; New (Format) ;** Low byte of command addresses CmdAddrLB ; [FE95] .by <(Validate) .by <(Initialize) .by <(Error31) .by <(Memory) .by <(Block) .by <(User) .by <(Position) .by <(USRexec) .by <(Copy) .by <(Rename) .by <(Scratch) .by <(New) .by $FF .by <(ChangeImage) .by <(CopyImage) ;** High byte of command addresses CmdAddrHB ; [FEA1] .by >(Validate) .by >(Initialize) .by >(Error31) .by >(Memory) .by >(Block) .by >(User) .by >(Position) .by >(USRexec) .by >(Copy) .by >(Rename) .by >(Scratch) .by >(New) .by $FF .by >(ChangeImage) .by >(CopyImage) ;** Prepare error msg after executing command ; in: - ; out: - ; used: A X Y Out_Err_msg ; [C194] lda #$00 sta WBAM J_C199 lda ERWORD ; flag set? bne OutputErrorMsg ; yes, -> ldy #$00 tya sty TRACK J_C1A3 sty SECTOR sty INPPTR jsr Errmsg2buf ; OK-message [E6C7] jsr ClrErrorFlags ; [C123] J_C1AD lda #$00 tax sta $FF jsr EraseInputBuf ; clear inputbuffer [C1BD] jmp Close17_18 ; close internal channel [D4DA] ;** Erase input buffer ; in: - ; out: - ; used: A Y EraseInputBuf ; [C1BD] ldy #$28 lda #$00 L_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 [E645] ;** Check input line ChkInputLine ; [C1D1] ldx #$00 stx FILTBL ; pointer to drivenumber lda #":" jsr SearchInputBuf ; Check line until : or end [C268] beq B_C1E2 ; not found, -> dey dey sty FILTBL ; points to drivenumber for : B_C1E2 jmp Get_Drv_Num ; [C368] ;** Check for a colon in the line ChkForColon ; [C1E5] ldy #$00 ldx #$00 lda #":" jmp SearchInputBuf ; [C268] ;** 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 Error34 lda #$34 jmp OutputErrorMsg ; 34, 'Syntax error' [C1C8] Chk4DrvNum ; [C1F8] dey dey sty FILTBL ; points to drivenumber for : txa ; found ',' for ':' ? bne Error34 ; yes, -> 'Syntax error' [C1F3] ChkWildcard ; [C200] lda #"=" jsr SearchInputBuf ; [C268] txa ; found ',' ? beq L_C20A ; no, -> lda #$40 ; set bit 6 ... L_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 tya ; found '=' ? beq L_C254 ; no, -> sta FILTBL,X lda F1CNT ; number of ',' for '=' sign sta F2PTR lda #$8D ; shift CR jsr SearchInputBuf ; [C268] inx ; increment ',' counter stx F2CNT ; mark number of ',' dex lda PATFLG ; found wildcard? beq L_C245 ; no, -> lda #$08 ; set bit 3 L_C245 cpx F1CNT ; ',' after '=' ? beq L_C24C ; no, -> ora #$04 ; set bit 2 L_C24C ora #$03 ; set bit 0 and 1 eor IMAGE sta IMAGE ; flag syntax test L_C254 lda IMAGE ldx INSTRU and TblSyntax-8,X ; combine with checkbyte bne L_C260 ; faulty syntax, -> rts L_C260 sta ERWORD ; set error flag Error30 lda #$30 jmp OutputErrorMsg ; 30, 'Syntax error' [C1C8] ;** Bytes for syntax check TblSyntax ; [FEAD] .by $51, $DD, $1C, $9E, $1C, $DE, $9E ; ; ^ ^ ^ ^ ; | | | | ; | | | +------- Copy Image ; | | | ; | | +------------ Change image ; | | ; | +----------------- Directory ; | ; +---------------------- NEW ;** Search character in input buffer SearchInputBuf ; [C268] sta CHAR ; mark char L_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 inc PATFLG ; set wildcardflag L_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 inx ; increment ',' counter cpx #$04 ; alread 4 comma's? bcc L_C26B ; no, continue -> L_C29E ldy #$00 L_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 tya rts ;** Check line length ptr 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 iny ; reset to old value L_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 ; [C1C8] ;** Clear flag for command input CLR_Flg_inp ; [C2DC] ldy #$00 tya ; A := 0 sta INPPTR sta RECSIZ sta TYPE sta TYPFLG sta CHNNUM sta F2PTR sta F1CNT sta F2CNT sta PATFLG sta ERWORD ldx #$05 L_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 lda #$01 sta F2CNT ; only ONE drive sta F2PTR GetDrvNum2 ; [C320] ldx #$00 L_C325 stx CHNNUM lda FILTBL,X ; place of ':' ; subroutine embedded ------> L_C33D tax lda #":" cmp CMDBUF+1,X bne x_C344 ; no, -> inx jmp x_C34C x_C344 cmp CMDBUF,X ; this place? beq x_C34C ; yes, -> lda #$80 ; set bit 7, not sure of drive bne L_C34F ; always -> x_C34C inx lda #0 L_C34F tay txa ; <--------------------------- 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 L_C361 lda #$80 ; set bit 7, not sure of drive bne L_C34F ; always -> ;** Get drive number ; used: AY Get_Drv_Num ; [C368] lda #$00 sta IMAGE ; clear syntax flag ldy FILTBL ; place in commandline B_C370 lda (INPPTR),Y ; get char jsr ChkDriveNum ; Number is sure? [C3BD] bpl L_C388 ; yes, -> iny ; increment pointer cpy CMDSIZ ; end of line? bcs L_C383 ldy CMDSIZ dey bne B_C370 L_C383 dec IMAGE L_C388 jmp LedOn ; [C100] ;** Check filetype ; used: AY Chk_Filetype ; [C398] ldy #$00 lda F1CNT ; found '=' sign cmp F2CNT beq L_C3B8 ; no, -> dec F2CNT ; get pointer ldy F2CNT lda FILTBL,Y tay lda (INPPTR),Y ; get char behind '=' ldy #15 L_C3B0 cmp TblFiletype,Y ; compare with 'S', 'P', 'U', 'R' beq L_C3B8 ; same, -> dey bne L_C3B0 ; if not found, filetype 'DEL' is assumed L_C3B8 tya sta TYPFLG ; note file type (1-4) rts ;** Check drive number ChkDriveNum ; [C3BD] cmp #"0" bcc x_C3C5 cmp #"9"+1 bcc L_C3C7 x_C3C5 ora #$80 ; set bit 7 = type not sure L_C3C7 and #$80 rts ;** Verify drive number Verify_Drv_Num ; [C3CA] jsr InitDrive beq L_C439 ; no error, -> L_C41B lda #$74 jmp OutputErrorMsg ; 74, 'drive not ready' [C1C8] L_C439 jmp LedOn ; [C100] ;** Search for file in directory Srch_File_Dir ; [C44F] jsr Verify_Drv_Num L_C452 lda #$00 sta DELIND jsr RD_1st_Dir_Blk ; read first directory block [C5AC] bne L_C475 ; found something, -> rts L_C470 jsr Nxt_File_Dir ; [C617] beq L_C485 ; not found, -> L_C475 jsr Tst_Input_Dir ; [C4D8] lda FOUND beq L_C47E ; more files, -> rts L_C47E lda ENTFND ; file found? bmi L_C470 ; no, -> bpl L_C475 ; yes, -> L_C485 lda FOUND rts ;** Search next file in directory SrchNxtFileDir ; [C48B] jsr RD_Nxt_Dir_Blk beq L_C4AA ; not found, -> bne L_C4BA ; found, -> SrchDirEntry ; [C49D] lda #$00 sta DELIND jsr RD_1st_Dir_Blk ; [C5AC] bne L_C4BA ; if found, -> sta FOUND L_C4AA lda FOUND rts ;** Search next directory item SrchNxtDirEnt ; [C4B5] jsr Nxt_File_Dir beq L_C4AA ; not found, -> L_C4BA jsr Tst_Input_Dir ; [C4D8] ldx ENTFND ; found file? bpl L_C4C9 ; yes, -> lda FOUND beq SrchNxtDirEnt ; no, -> bne L_C4D7 ; no, ready -> RTS L_C4C9 lda TYPFLG ; DEL? beq L_C4D7 ; yes, ready -> RTS lda COMFLG,X ; filetype and #15 cmp TYPFLG ; like wanted type? bne SrchNxtDirEnt L_C4D7 rts ;** Check input in directory Tst_Input_Dir ; [C4D8] ldx #$FF stx ENTFND ; flag file found inx stx PATFLG ; erses joker flag jsr Set_Ptr_to_File ; [C589] beq L_C4EC L_C4E6 rts L_C4E7 jsr Ptr_to_Nxt_File ; [C594] bne L_C4E6 ; no file, ready -> ;#### kan weg IMHO L_C4EC lda DRVNUM,X lsr bcc L_C4FE ; bit 0 was 0, -> and #$40 ; standard drive? beq L_C4E7 ; yes, -> ;#### L_C4FE lda FILTBL,X ; check next file name tax jsr Get_Length_Name ; get length filename [C6A6] ldy #$03 jmp L_C51D L_C50A lda CMDBUF,X ; get char from instruction cmp (DIRBUF),Y ; same char in directory? beq L_C51B ; yes, -> cmp #"?" ; wildcard? bne L_C4E7 ; no, next file -> lda (DIRBUF),Y cmp #$A0 ; shift space beq L_C4E7 ; no, next file -> L_C51B inx ; increment pointer iny L_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 cpy #$13 ; end of name bcs L_C535 ; yes, -> lda (DIRBUF),Y cmp #$A0 ; shift space bne L_C4E7 ; no, name is longer -> ;** Found file L_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 ; file open -> ora #$20 ; set bit 5 L_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 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 RECSIZ ; do we have length of record? bne Set_Ptr_to_File ; yes, -> ;* Get length of record ldy #$15 lda (DIRBUF),Y sta RECSIZ ;** Set pointer to file Set_Ptr_to_File ; [C589] lda #$FF sta FOUND lda F2CNT sta F2PTR Ptr_to_Nxt_File dec F2PTR ; [C594] bpl L_C59A rts L_C59A ldx F2PTR lda COMFLG,X ; wildcard-flag is set? bmi L_C5A6 ; yes, -> lda FILTRK,X ; track number is set? bne Ptr_to_Nxt_File ; yes, -> L_C5A6 lda #$00 sta FOUND rts ;** Read first directory Block RD_1st_Dir_Blk ; [C5AC] ldy #$00 sty DELSEC dey sty ENTFND lda DirTrack ; track with directory sta TRACK lda #$01 sta SECTOR sta LSTBUF jsr ReadSeqFile ; [D475] J_C5C4 lda LSTBUF ; last sector? bne L_C5CA ; no, -> rts L_C5CA lda #$07 sta FILCNT ; number of dir entries (-1) lda #$00 jsr GetAthByte ; get byte from buffer [D4F6] sta LSTBUF ; mark as track J_C5D7 jsr SetBufPointer ; [D4E8] dec FILCNT ; decrement entry counter ldy #$00 lda (DIRBUF),Y ; first byte of directory = filetype bne L_C5FB lda DELSEC bne Nxt_File_Dir jsr GetTrackSector ; [DE3B] lda SECTOR sta DELSEC lda DIRBUF ; bufferpointer ldx DELIND sta DELIND beq Nxt_File_Dir rts L_C5FB ldx #$01 cpx DELIND ; bufferpointer = 1 ? bne L_C62F ; no, -> beq Nxt_File_Dir ; yes, always -> ;** Read next directory Block RD_Nxt_Dir_Blk ; [C604] lda DirTrack sta TRACK lda DIRSEC sta SECTOR jsr ReadSeqFile ; [D475] lda INDEX jsr SetBufPointer3 ; [D4C8] ;** Search for next file in directory Nxt_File_Dir ; [C617] lda #$FF sta ENTFND ; erase flag "found file" lda FILCNT ; searched all dir-entries? bmi L_C629 ; yes, -> lda #$20 jsr IncBufPointer ; [D1C6] jmp J_C5D7 L_C629 jsr RdNxtBlock ; set pointer [D44D] jmp J_C5C4 ; read next block L_C62F lda DIRBUF sta INDEX jsr GetTrackSector ; [DE3B] lda SECTOR sta DIRSEC ; mark sector rts ;** Test and initialize drive InitDrive ; [C63D] lsr WPSW0 ; disk changed? bcc B_C669 ; no, then done -> lda #$FF sta JOBRTN ; set errorflag jsr ReadDirTrack ; read directorytrack [D00E] ; #### IMHO not needed anymore ldy #$FF ; $FF = error cmp #$02 ; 20 'read error' ? beq B_C65F ; yes, -> cmp #$03 ; 21 'read error' ? beq B_C65F ; yes, -> cmp #$0F ; 74 'drive not ready' ? beq B_C65F ; yes, -> ; <--- ldy #$00 ; no error B_C65F ldx #0 ; drive number tya ; error? sta $FF ; save errorcode bne B_C669 ; if error, -> jsr LoadBAM ; load BAM [D042] B_C669 ldx #0 ; drive number lda $FF ; load errorcode rts ;** Name of file in directory buffer ; in: ; A = maximum length ; X points to start of the name in CMDBUF NamFil2DirBuf ; [C66E] pha ; Accu contains maximum length jsr Get_Length_Name ; [C6A6] ;** 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 B_C697 lda CMDBUF,X ; get character from buffer sta (DIRBUF),Y iny beq B_C6A5 ; buffer full -> inx cpx LIMIT ; check with maximum bcc B_C697 B_C6A5 pla sec sbc STRSIZ ; compare length with maximum length tax ; store difference in X beq B_C687 ; = 0, -> bcc B_C687 ; greater then maximum, -> ;** Add $A0 (shifted space) to end of name until maximum lda #$A0 B_C681 sta (DIRBUF),Y iny dex bne B_C681 B_C687 rts ;** Search for end of name in command Get_length_name ; [C6A6] lda #$00 sta STRSIZ txa ; save X pha B_C6AD lda CMDBUF,X cmp #"," beq B_C6C8 ; end search -> cmp #"=" beq B_C6C8 ; end search -> inc STRSIZ inx lda #$0F ; 15 = (maximum length of name) - 1 cmp STRSIZ ; found 16 characters, -> bcc B_C6C8 ; no, -> next char cpx CMDSIZ ; compare with length of input bcc B_C6AD ; smaller, search on -> B_C6C8 stx LIMIT pla tax ; restore X rts ;** Directory entry in buffer GetDirEntry ; [C6CE] lda SA pha lda CURCHN pha jsr GetDirEntry2 ; [C6DE] pla sta CURCHN pla sta SA rts ;** Create directory entry in buffer GetDirEntry2 ; [C6DE] lda #$11 sta SA jsr OpenChan4Read ; [D0EB] jsr SetBufPointer ; [D4E8] lda ENTFND ; found entry? bpl B_C71B ; yes, -> jsr BlocksFree ; [C806] clc 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. ; #### alles fixeren op: xxxxx "NAAM " PRG ? B_C71B ldx #$18 ; length of entry ldy #$1D ; position HB number of blocks lda (DIRBUF),Y sta NBTEMP1 beq B_C728 ldx #$16 B_C728 dey lda (DIRBUF),Y sta NBTEMP0 cpx #$16 beq B_C73C cmp #$0A ; number of blocks? bcc B_C73C ; <10 , -> dex cmp #$64 ; <100 , -> bcc B_C73C dex B_C73C jsr ClrNameBuf ; [C7AC] lda (DIRBUF),Y ; A = filetype pha asl A ; bit 7 in Carry / write protection? bpl B_C74A ; no, -> lda #"<" sta NameBuffer+1,X B_C74A pla ; filetype and #$0F ; isolate bit 0..3 tay ; and use as index lda TblFiletype+32,Y ; 3rd char of filetype sta NameBuffer,X dex lda TblFiletype+16,Y ; 2nd char of filetype sta NameBuffer,X dex lda TblFiletype,Y ; 1st char of filetype sta NameBuffer,X dex dex bcs B_C76B ; file closed, -> lda #"*" ; file open mark sta NameBuffer+1,X B_C76B lda #$A0 ; fill with shifted space sta NameBuffer,X dex ; Copy the file name ldy #$12 B_C773 lda (DIRBUF),Y sta NameBuffer,X dex dey cpy #$03 bcs B_C773 lda #'"' ; " before file name sta NameBuffer,X ; Replace shifted space with normal space by cleraing bit 7 B_C783 inx cpx #$20 ; ???? bcs B_C793 lda NameBuffer,X cmp #'"' beq B_C793 cmp #$A0 ; shifted space? bne B_C783 ; no, -> B_C793 lda #'"' ; yes, replace sta NameBuffer,X B_C798 inx cpx #$20 bcs B_C7A7 lda #$7F and NameBuffer,X ; erase bit 7 sta NameBuffer,X ; in remaining chars bpl B_C798 ; always -> B_C7A7 jsr SrchNxtDirEnt ; [C4B5] sec rts ;** Clear the reserved space for the name of the disk ClrNameBuf ; [C7AC] ldy #$1B ; total length lda #" " B_C7B0 sta NameBuffer-1,Y dey bne B_C7B0 rts ;** Create header with disk name DirHeader ; [C7B7] jsr GetBufNumBAM jsr ReadBAM ; [F0DF] jsr ClrNameBuf ; [C7AC] lda #$FF sta TEMP0 ; ??? where used ??? ; Output the drive number in front of the disk label lda #$00 sta NBTEMP1 sta NBTEMP0 ldx JOBNUM lda BufferAddress,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 B_C7ED ; no, -> lda #"1" .by $2C ; dummy BIT opcode B_C7E5 lda (DIRBUF),Y cmp #$A0 ; shifted space? bne B_C7ED ; no, -> lda #" " B_C7ED sta NameBuffer+2,Y dey bpl B_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 B_C80B lda TxtBlocksFree,Y sta NameBuffer,Y dey bpl B_C80B jmp NumBlocksFree ; [EF4D] TxtBlocksFree ; [C817] .tx "BLOCKS FREE." ;** S - Scratch command Scratch ; [C823] jsr Chk_Filetype jsr GetDrvNum2 ; [C320] jsr Verify_Drv_Num ; [C3CA] lda #$00 sta R0 ; counter erased files jsr SrchDirEntry ; [C49D] bmi B_C872 ; not found, -> B_C835 jsr IsFileOpen ; [DDB7] bcc B_C86D ; yes, -> ldy #$00 lda (DIRBUF),Y ; filetype and #$40 ; LOCK-bit set? bne B_C86D ; yes, -> ;@@10 jsr DelDirEntry ; delete entry [C8B6] ldy #$13 lda (DIRBUF),Y ; tracknumber of first side-sector beq B_C855 ; does not exist, -> sta TRACK iny lda (DIRBUF),Y ; sector number sta SECTOR jsr DelSectorChain ; delete all side-sectors [C87D] B_C855 ldx ENTFND ; file number lda #$20 and COMFLG,X ; file closed? bne B_C86B ; no, -> lda FILTRK,X sta TRACK lda FILSEC,X sta SECTOR jsr DelSectorChain ; delete file [C87D] B_C86B inc R0 ; increase number of erased files B_C86D jsr SrchNxtFileDir ; another file? [C48B] bpl B_C835 ; yes, -> B_C872 lda R0 sta TRACK lda #$01 ldy #$00 jmp J_C1A3 ; message "FILES SCRATCHED" ;** Erase file DelSectorChain ; [C87D] jsr FreeSector ; free block in BAM jsr ReadSeqFile ; [D475] jsr GetBufNumBAM ; get buffer number in BAM [F119] lda BUF0CH1zp,X cmp #$FF ; buffer not used? beq J_C894 ; yes, -> lda WBAM ora #$40 sta WBAM J_C894 lda #$00 jsr SetBufPointer3 ; buffer pointer to zero [D4C8] jsr RdNxtBlock2 ; get track [D156] sta TRACK jsr RdNxtBlock2 ; get sector [D156] sta SECTOR lda TRACK ; track number bne B_C8AD ; not equal to zero jsr WriteBam ; write BAM [EEF4] jmp CloseChannel ; close channel [D227] B_C8AD jsr FreeSector ; free block in BAM [EF5F] ;==> Jiffy jsr P_FB64 cli ; Jiffy <== jmp J_C894 ; and continue ;** Erase dir entry DelDirEntry ; [C8B6] ldy #$00 tya UpdateDirEntry sta (DIRBUF),Y ; set file type to zero jsr WriteSector3 ; write block [DE5E] jmp VerifyExec ; and check [D599] ;** D - Backup command (UNUSED) Error31 lda #$31 jmp OutputErrorMsg ; 31, 'syntax error' [C1C8] ;** 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 [D6D3] lda #$E0 ; command code for formatting sta JOBSzp+3 ; transmit B_C8E0 lda JOBSzp+3 bmi B_C8E0 ; wait until formatting done cmp #$02 bcc B_C8EF ; smaller than two, then ok lda #$03 ldx #$00 jmp PrepErrMsg ; 21, 'read error' [E60A] B_C8EF rts ;** C - Copy command Copy ; [C8F0] lda #$E0 sta BUFUSEL jsr ClearTBAM ; [F0D1] jsr GetBufNumBAM ; get buffer number of BAM [F119] lda #$FF sta BUF0CH1zp,X lda #$0F sta LINUSE jsr ChkForColon ; check input line [C1E5] bne B_C90C jmp Error31 ; 31, 'syntax error' B_C90C jsr Chk4DrvNum ; check input [C1F8] jsr GetDrvNum2 ; test drive number [C320] lda IMAGE ; flag for syntax check and #$55 ; normal copy? bne B_C928 ; yes, -> ldx FILTBL lda CMDBUF,X ; character of the command cmp #'*' ; * ? bne B_C928 ; no, -> B_C923 jmp Error30 ; 30, 'syntax error' B_C928 lda IMAGE ; syntax flag and #$D9 bne B_C923 ; 30, 'syntax error' J_C952 jsr Srch_File_Dir ; search for file in directory [C44F] lda F2CNT ; number of filenames in command cmp #$03 ; smaller than three? bcc B_C9A1 ; yes, -> lda DRVNUM ; first drive number cmp DRVNUM+1 ; second drive number bne B_C9A1 ; not on same drive? lda BUFPTR ; directory block of the 1st file cmp BUFPTR+1 ; same directory block as second file? bne B_C9A1 ; no, -> lda DIRSECP ; directory sector of first file cmp DIRSECP+1 ; same directory sector as second file? bne B_C9A1 ; no, -> jsr IsFilePresent ; is file present? [CACC] ; yes lda #$01 sta F2PTR jsr ReadDirSec ; [C9FA] jsr CheckREL ; get data type, REL? [D125] beq B_C982 ; yes, -> cmp #$02 ; prg-file? bne B_C987 ; no, -> B_C982 jmp Error64 ; 64, 'file type mismatch' B_C987 lda #$12 ; 18 sta SA ; secondary address lda A_023C sta A_023D lda #$FF sta A_023C jsr Prep4Append ; prepare append [DA2A] ldx #$02 jsr CopyFile2 ; copy file [C9B9] jmp Out_Err_Msg ; done [C194] B_C9A1 jsr CopyFile1 ; copy file [C9A7] jmp Out_Err_Msg ; done [C194] ;** CopyFile1 ; [C9A7] jsr Chk2Filenames ; [CAE7] ;** Allocate new block lda #$12 ; 18 sta SA ; secondary address jsr AllocNewSec ; allocate new block [DCDA] jsr CreDirEntry ; enter file in directory [D6E4] ldx F1CNT ;** CopyFile2 ; [C9B9] stx F2PTR jsr ReadDirSec ; [C9FA] lda #$11 ; 17 sta SA jsr OpenChan4Read ; [D0EB] jsr CheckREL ; get data type [D125] bne B_C9CE ; REL file? no, -> jsr P_CA53 B_C9CE lda #$08 sta EOIFLG bne J_C9D8 ; always -> B_C9D5 jsr WrData2Buffer ; write byte in buffer [CF9B] J_C9D8 jsr OpenChnGetByt ; and get byte [CA35] lda #$80 jsr ChkChanBit ; test bit 7 [DDA6] beq B_C9D5 ; not set? jsr CheckREL ; check file type [D125] beq B_C9EA ; REL file? yes, -> jsr WrData2Buffer ; get data byte in buffer [CF9B] B_C9EA ldx F2PTR inx cpx F2CNT bcc CopyFile2 lda #$12 ; 18 sta SA jmp CloseFile ; close channel [DB02] ;** Open an internal channel for reading a directory block/file ReadDirSec ; [C9FA] ldx F2PTR lda DirTrack ; 18, directory track sta TRACK ; save lda DIRSECP,X ; directory sector sta SECTOR jsr ReadSeqFile ; read block [D475] ldx F2PTR lda BUFPTR,X ; pointer in block jsr SetBufPointer3 ; set buffer pointer [D4C8] ldx F2PTR lda COMFLG,X ; file type and #15 ; isolate sta TYPE ; and save lda #$00 sta RECSIZ jsr OpenFile4Read ; get parameters for REL file [D9A0] ldy #$01 jsr CheckREL ; get file type [D125] beq B_CA31 ; REL file? yes, -> iny B_CA31 tya jmp SetBufPointer3 ; set buffer pointer [D4C8] OpenChnGetByt ; [CA35] lda #$11 ; 11 sta SA ; open channel and get byte OpenChnGetByt2 ; [CA39] jsr P_D39B sta DATA ldx CURCHN ; channel number lda REWRFLzp,X and #$08 ; isolate end marker sta EOIFLG bne B_CA52 ; not set? jsr CheckREL ; REL file? [D125] beq B_CA52 ; no, -> lda #$80 jsr SetFlags ; set bit 7 = last record [DD97] B_CA52 rts P_CA53 jsr GetDrvNum3 ; set drive number [D1D3] jsr SetPar2LstRec ; [E1CB] lda CHNNUM3 pha lda CHNNUM2 pha lda #$12 ; 18 sta SA jsr OpenChan4Write ; open write channel [D107] jsr GetDrvNum3 ; set drive number [D1D3] jsr SetPar2LstRec ; [E1CB] jsr Record2Buffer ; [E29C] lda CHNNUM3 sta R1 lda CHNNUM2 sta R0 lda #$00 sta R2 sta CHNNUM1 sta CHNNUM4 pla sta CHNNUM2 pla sta CHNNUM3 jmp J_E33B ;** R - Rename command Rename ; [CA88] jsr GetDrvNum2 ; get drive number from command line lda #0 sta DRVNUM+1 ; 2nd drive number B_CA97 sta DRVNUM jsr Srch_File_Dir ; search for file in directory [C44F] jsr Chk2Filenames ; does name exist? [CAE7] lda DIRSECP+1 sta SECTOR ; sector number jsr ReadSector2 ; read block from directory [DE57] jsr VerifyExec ; ok? [D599] lda BUFPTR+1 ; pointer to directory entry clc adc #$03 ; pointer plus 3 to file name jsr SetBufPointer3 ; set buffer pointer [D4C8] jsr GetBufNumber ; get buffer number [DF93] tay ldx FILTBL lda #$10 ; 16 characters jsr NamFil2DirBuf ; write name in buffer [C66E] jsr WriteSector3 ; write block to directory [DE5E] jsr VerifyExec ; ok? [D599] jmp Out_Err_Msg ; done, prepare disk status [C194] ;** Check if file present IsFilePresent ; [CACC] lda COMFLG+1 ; file type and #15 sta TYPE ; save ldx F2CNT B_CAD6 dex cpx F1CNT ; file present? bcc B_CAE6 ; yes, -> lda FILTRK,X ; track number bne B_CAD6 ; not zero? Error62 lda #$62 jmp OutputErrorMsg ; 62, 'file not found' [C1C8] B_CAE6 rts ;** Check if two file names are the same Chk2Filenames ; [CAE7] jsr IsFilePresent ; does file exist with old name? B_CAEA lda FILTRK,X ; track number of new file beq B_CAF4 ; file erased? Error63 lda #$63 jmp OutputErrorMsg ; 63, 'file exists' [C1C8] B_CAF4 dex bpl B_CAEA rts ;** M - Memory command Memory ; [CAF8] lda CMDBUF+1 ; 2nd character from buffer cmp #'-' bne B_CB4B 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' beq B_CB20 ; to memory read jsr P_F258 ; (RTS) cmp #'W' beq B_CB50 ; to memory write cmp #'E' bne B_CB4B jmp (J_TEMP0) ; memory-execute ;** M-R memory read B_CB20 lda (TEMP0),Y ; read byte sta DATA lda CMDSIZ ; length of command line cmp #$06 ; less than 6? bcc B_CB45 ; yes, -> ldx CMDBUF+5 ; number dex beq B_CB45 ; only one byte? 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 J_D443 ; byte out B_CB45 jsr OpenChan4Read ; open read channel [D0EB] jmp J_D43A ; byte out B_CB4B jmp Error31 ; 31, 'syntax error' ;** M-W momory write B_CB50 lda CMDBUF+6,Y ; read character sta (TEMP0),Y ; and save iny cpy CMDBUF+5 ; number of characters bcc B_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 jsr P_CB72 jmp Out_Err_Msg ; done, prepare error message [C194] P_CB72 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 J_CB84 lda SA ; channel number pha jsr InitDrive ; check drive and initialize [C63D] pla sta SA ldx CMDSIZ ; length of filename dex bne B_CBA5 ; greater than one? lda #$01 jsr FindRdChanBuf ; layout buffer and channel [D1E2] jmp J_CBF1 ; set flags, done B_CBA0 jmp Error70 ; 70, 'no channel' B_CBA5 ldy #$01 jsr GetCmdParms2 ; get buffer number [CC7C] ldx FILSEC ; buffer number cpx #$05 ; bigger than 5? bcs B_CBA0 ; 70, 'no channel' lda PowersOf2,X eor #$FF ; invert bits and BUFUSEL ; buffer free? bne B_CBA0 ; no, -> lda PowersOf2,X ora BUFUSEL sta BUFUSEL ; allocate buffer lda #$00 jsr FindRdChanBuf ; search channel [D1E2] ldx CURCHN ; channel number lda FILSEC ; buffer number sta BUF0CH1zp,X tax lda #0 ; drive number sta JOBSzp,X sta LSTJOB,X J_CBF1 ldx SA ; secondary address lda LINTAB,X ora #$40 ; set READ and WRITE flags 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 [C194] ;** B - Block command Block ; [CC1B] ldy #$00 ldx #$00 lda #'-' jsr SearchInputBuf ; search for minus sign [C268] bne B_CC30 ; found? B_CC26 jmp Error31 ; 31, 'syntax error' B_CC2B jmp Error30 ; 30, 'syntax error' B_CC30 txa bne B_CC2B ; comma, then error ldx #$05 lda CMDBUF,Y ; char from buffer B_CC38 cmp Afrwep,X ; compare with 'AFRWEP' beq B_CC42 ; found? dex bpl B_CC38 ; compare with all characters bmi B_CC26 ; not found, error B_CC42 txa ora #$80 ; command number, set bit 7 sta INSTRU jsr GetCmdParms ; get parameters [CC6F] 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 AFRWEP ; [CC5D] .tx "AFRWEP" ;** Addresses of block commands CmdAFRWEP ; [CC63] .WO L_CD03 ;** B-A .WO E_CCF5 ;** B-F .WO E_CD56 ;** B-R .WO E_CD73 ;** B-W .WO E_CDA3 ;** B-E .WO E_CDBD ;** 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 [C268] bne GetCmdParms2 ; found? ldy #$03 ; no, begin at 4th character GetCmdParms2 ; [CC7C] lda CMDBUF,Y ; search for separating char cmp #' ' beq B_CC8B cmp #$1D ; cursor right beq B_CC8B cmp #',' bne B_CC92 B_CC8B iny cpy CMDSIZ ; line end? bcc GetCmdParms2 rts B_CC92 jsr P_CCA1 ; preserve next parameter inc F1CNT ; increment parameter counter ldy F2PTR cpx #$04 ; compare with maximum number bcc B_CC8B bcs B_CC2B ; 30, 'syntax error' P_CCA1 lda #$00 sta TEMP0 sta TEMP1 ; erase storage area for decimal numbers sta TEMP3 ldx #$FF B_CCAB lda CMDBUF,Y ; get characters from input buffer cmp #$40 bcs B_CCCA ; no digits? cmp #'0' bcc B_CCCA ; no digits? and #$0F ; convert ASCII digits to hex pha ; and save 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 ; line end reached bcc B_CCAB ; no, -> B_CCCA sty F2PTR ; save pointer clc lda #$00 B_CCD0 inx cpx #$03 bcs B_CCE4 ; convert hex digits to one byte ldy TEMP0,X B_CCD7 dey bmi B_CCD0 adc Decimal,X ; add decimal value bcc B_CCD7 clc inc TEMP3 bne B_CCD7 B_CCE4 pha ldx F1CNT ; counter for paramaters lda TEMP3 sta FILTRK,X ; lo byte pla sta FILSEC,X ; hi byte rts ;** Decimal values Decimal ; [CCF2] .by 1, 10, 100 ;** B-F block free E_CCF5 jsr P_CDF5 ; get track, sector and drive number jsr FreeSector ; free block [EF5F] jmp Out_Err_Msg ; done, prepare error message [C194] ;** B-A block allocate E_CCFE lda #$01 sta WBAM L_CD03 jsr P_CDF5 ; get track, sector and drive number lda SECTOR ; sector pha ; save jsr P_F1FA ; find block in BAM beq B_CD19 ; block allocated? pla ; desired sector cmp SECTOR ; = next free sector? bne B_CD2C ; no, -> jsr AllocSector ; allocate block in BAM [EF90] jmp Out_Err_Msg ; done [C194] B_CD19 pla B_CD1A lda #$00 sta SECTOR ; sector 0 inc TRACK ; next track lda TRACK ; track number cmp A_FED7 ; 36, last track number + 1 bcs B_CD31 ; >=, then 'no block' jsr P_F1FA ; find free block in next track beq B_CD1A ; not found, check next track B_CD2C lda #$65 jmp CreErrorMsg ; 65, 'no block' next free block[E645] B_CD31 lda #$65 jmp OutputErrorMsg ; 65, 'no block' no more free blocks ; [C1C8] ;** OpenChanRdSec ; [CD36] jsr OpenChannel2 ; open channel, set parameters jmp ReadSector ; read block from disk [D460] ;** Get byte from buffer P_CD3C 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 [D4C8] jsr P_CD3C ; get a byte from the buffer sta ENDPNT,Y lda #$89 ; set read and write flag sta REWRFLab,Y rts ;** B-R block read E_CD56 jsr Readsector3 ; read block from disk [CD42] jsr PrepbyteBuf ; prepare byte from buffer [D3EC] jmp Out_Err_Msg ; prepare error message [C194] ;** U1 substitute for block read E_CD5F jsr GetCmdParms ; get parameters of the command [CC6F] jsr Readsector3 ; read block from disk [CD42] lda ENDPNT,Y ; end pointer sta OUTREG,Y ; save as data byte lda #$FF sta ENDPNT,Y ; end pointer to $FF jmp Out_Err_Msg ; done, prepare error message [C194] ;** B-W block write E_CD73 jsr OpenChannel2 ; open channel [CDF2] jsr SetBufPointer ; set buffer pointer [D4E8] tay dey cmp #$02 ; buffer pointer lo less than 2? bcs B_CD81 ; no, -> ldy #$01 B_CD81 lda #$00 jsr SetBufPointer3 ; buffer pointer to zero [D4C8] tya jsr Write2Buf ; write byte in buffer [CFF1] txa pha jsr WriteSector ; write block to disk [D464] pla tax jsr GetByteBuf ; get byte from buffer [D3EE] jmp Out_Err_Msg ; done, error message [C194] ;** U2 substitute for block write E_CD97 jsr GetCmdParms ; get command parameters [CC6F] X_CD9A jsr OpenChannel2 ; open channel [CDF2] jsr WriteSector ; and write block to disk [D464] jmp Out_Err_Msg ; done [C194] ;** B-E block execute E_CDA3 jsr P_F258 ; (RTS) jsr OpenChanRdSec ; open channel and read block [CD36] lda #$00 sta TEMP0 ; address low ldx JOBNUM lda BufferAddress,X ; buffer address high sta TEMP1 jsr P_CDBA ; execute routine jmp Out_Err_Msg ; done [C194] P_CDBA jmp (J_TEMP0) ; jump to routine ;** B-P block pointer E_CDBD jsr OpenChannel ; open channel, get buffer number ; [CDD2] lda JOBNUM 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 [D3EE] jmp Out_Err_Msg ; done [C194] ;** Open channel OpenChannel ; [CDD2] ldx CHNNUM inc CHNNUM lda FILSEC,X ; buffer number tay dey dey cpy #$0C ; buffer number smaller than 14? bcc B_CDE5 ; yes, -> B_CDE0 jmp Error70 ; 70, 'no channel' B_CDE5 sta SA ; secondary address jsr OpenChan4Read ; open channel [D0EB] bcs B_CDE0 ; already allocated, 'no channel' jsr GetBufNumber ; buffer number [DF93] sta JOBNUM ; set rts ;** Check buffer number and open channel OpenChannel2 ; [CDF2] jsr OpenChannel ; check buffer number and open channel P_CDF5 ldx CHNNUM ; channel number lda FILSEC+2,X sta SECTOR ; sector lda FILSEC+1,X sta TRACK ; track jsr ChkTraSec3 ; track and sector ok? [D55F] jmp LedOn ; turn LED on [C100] ;** Set pointer for REL file SetPtrRelFil ; [CE0E] jsr P_CE2C ; record number * record length jsr P_CE6E ; divide by 254 lda ACCUM1 ; remainder = pointer in data block sta CHNNUM4 ; data pointer jsr P_CE71 ; divide by 120 = side-sector number inc CHNNUM4 inc CHNNUM4 ; data pointer + 2 (track/sector ; pointer!) lda RESULT0 ; result of division sta CHNNUM2 ; equals side-sector number lda ACCUM1 ; remainder asl A ; times 2 clc adc #$10 ; plus 16 sta CHNNUM3 ; =pointer in side-sector to data block rts ;** record number * record length P_CE2C jsr ClearResult ; erase work storage [CED9] sta ACCUM3 ldx CURCHN ; channel number lda RECL,X ; record number lo sta ACCUM1 lda RECH,X ; record number hi sta ACCUM2 bne B_CE41 lda ACCUM1 beq B_CE4C ; record number not zero? B_CE41 lda ACCUM1 sec sbc #$01 ; then subtract one sta ACCUM1 bcs B_CE4C dec ACCUM2 B_CE4C lda RecLength,X ; record length sta TEMP0 B_CE50 lsr TEMP0 bcc B_CE57 jsr P_CEED ; record number * record length B_CE57 jsr LshiftAccum ; shift register left [CEE5] lda TEMP0 bne B_CE50 lda CHNNUM1 clc adc RESULT0 sta RESULT0 bcc B_CE6D ; result in $8B/$8C/$8D inc RESULT1 bne B_CE6D inc RESULT2 B_CE6D rts ;** Divide by 254 P_CE6E lda #$FE ; 254 .by $2C ; dummy BIT opcode ;** Divide by 120 P_CE71 lda #$78 sta TEMP0 ; divisor ldx #$03 B_CE77 lda ACCUM0,X pha lda R4,X sta ACCUM0,X pla sta R4,X dex bne B_CE77 jsr ClearResult ; erase work storage [CED9] B_CE87 ldx #$00 B_CE89 lda ACCUM1,X sta ACCUM0,X inx cpx #$04 bcc B_CE89 lda #$00 sta ACCUM3 bit TEMP0 bmi B_CEA3 asl ACCUM0 php lsr ACCUM0 plp jsr LshiftAccum2 ; shift register 1 left [CEE6] B_CEA3 jsr P_CEED ; add register 0 to register 1 jsr LshiftAccum ; shift register 1 left [CEE5] bit TEMP0 bmi B_CEB0 jsr LshiftAccumX2 ; left-shift register 1 twice [CEE2] B_CEB0 lda ACCUM0 clc adc ACCUM1 sta ACCUM1 bcc B_CEBF inc ACCUM2 bne B_CEBF inc ACCUM3 B_CEBF lda ACCUM3 ora ACCUM2 bne B_CE87 lda ACCUM1 sec sbc TEMP0 ; quotient in $8B/$8C/$8D bcc B_CED8 inc RESULT0 bne B_CED6 inc RESULT1 bne B_CED6 inc RESULT2 B_CED6 sta ACCUM1 ; remainder in $90 B_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 ;** P_CEED clc ldx #$FD B_CEF0 lda RESULT3,X ; register $90/$91/$92 adc ACCUM4,X ; add to register $8B/$8C/$8D sta RESULT3,X inx bne B_CEF0 rts ;** Initialize least recently used table InitLastTable ; [CEFA] ldx #$00 B_CEFC txa ; store 0,1,2,3,6 .... sta LRUTBLzp,X ; .... $FA/B/C/D/E inx cpx #$04 bne B_CEFC lda #$06 sta LRUTBLzp,X rts ;** UpdateTbl ; [CF09] ldy #$04 ldx CURCHN ; channel number J_CF0D lda LRUTBLab,Y stx LRUTBLzp,Y cmp CURCHN ; channel number beq B_CF1D dey bmi InitLastTable tax jmp J_CF0D B_CF1D rts ; [CE1E] ChangeBuffer2 ; [CF1E] jsr UpdateTbl jsr ChkBufferOK ; [DFB7] bne B_CF6C ; no, -> jsr GetDrvNum3 ; set drive number [D1D3] jsr GetBuffer ; [D28E] bmi B_CF76 jsr DeactivateBuf ; [DFC2] lda TRACK ; track pha lda SECTOR ; sector pha lda #$01 jsr GetAthByte ; get byte 1 from buffer [D4F6] sta SECTOR ; sector lda #$00 jsr GetAthByte ; get byte 0 from buffer [D4F6] sta TRACK ; last sector? beq B_CF66 ; yes, -> jsr CheckREL ; REL file? [D125] beq B_CF57 ; yes, -> jsr Chk4Write ; [DDAB] bne B_CF57 jsr ChangeBuffer ; [CF8C] jmp J_CF5D B_CF57 jsr ChangeBuffer ; [CF8C] jsr ReadSector2 ; [DE57] J_CF5D pla sta SECTOR ; get sector pla sta TRACK ; and track number jmp J_CF6F B_CF66 pla sta SECTOR ; get back sector pla sta TRACK ; and track number B_CF6C jsr ChangeBuffer ; [CF8C] J_CF6F jsr GetBufNumber ; [DF93] tax jmp VerifyExec ; and verify [D599] B_CF76 jmp Error70 ; 70, 'no channel' ;** Look for a free buffer Look4FreeBuf ; [CF7B] jsr UpdateTbl jsr ChkBufferOK ; [DFB7] bne B_CF8B jsr GetBuffer ; [D28E] bmi B_CF76 jsr DeactivateBuf ; [DFC2] B_CF8B rts ;** Change buffer ChangeBuffer ; [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 [D107] jsr LedOn ; turn LED on [C100] jsr CheckREL ; check file type [D125] bcc B_CFAF ; no REL file lda #$20 jsr DeleteFlags ; change buffer [DD9D] B_CFAF lda SA ; secondary address cmp #$0F ; 15? beq B_CFD8 ; yes, -> bne B_CFBF ; no, -> P_CFB7 lda ORGSA ; secondary address and #$8F cmp #$0F ; greater than 15? bcs B_CFD8 ; then input buffer B_CFBF jsr CheckREL ; check file type [D125] bcs B_CFC9 ; REL file or direct access? lda DATA ; data byte jmp J_D19D ; write in buffer B_CFC9 bne B_CFCE ; direct access file? jmp J_E0AB ; write data byte in REL file B_CFCE lda DATA jsr Write2Buf ; write data byte in buffer [CFF1] ldy CURCHN ; channel number jmp GetByteBuf ; prepare next byte for output [D3EE] B_CFD8 lda #$04 ; channel 4 sta CURCHN ; corresponding input buffer jsr SetBufPointer ; set buffer pointer [D4E8] cmp #$2A ; 40 beq B_CFE8 ; buffer end? lda DATA jsr Write2Buf ; write data byte in buffer [CFF1] B_CFE8 lda EOIFLG ; end flag set? beq B_CFED ; yes, -> rts B_CFED inc CMDWAT ; set command flag rts ;** Write data byte in buffer Write2Buf ; [CFF1] pha ; save data byte jsr GetBufNumber ; get buffer number [DF93] bpl J_CFFD ; associated buffer? pla lda #$61 jmp OutputErrorMsg ; 61, 'file not open' [C1C8] J_CFFD 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 [D042] jmp Out_Err_Msg ; prepare disk status [C194] ;** 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 B_D02C ; yes, -> pha jsr GetBuffer ; [D28E] tax ; buffer available? bpl B_D024 ; yes, -> lda #$70 jsr CreErrorMsg2 ; 70, 'no channel' [E648] B_D024 pla tay txa ora #$80 ; inactive sta BUF0CH1ab,Y B_D02C txa and #$0F sta JOBNUM ldx #$00 stx SECTOR ; sector 0 ldx DirTrack ; 18 stx TRACK ; track 18 jsr Par2DiskCtrl2 ; transmit parameter to disk controller ; [D6D3] lda #$B0 ; command code 'read block header' jmp J_D58C ; transmit to disk controller ;** Load BAM LoadBAM ; [D042] jsr ClearTBAM jsr ReadDirTrack ; read block [D00E] ldx #0 ; drive number lda #$00 sta MDIRTY ; reset flag for "BAM changed' jsr DskReadBlock ; [D586] lda JOBNUM ; buffer number asl A tax lda #$02 ; buffer pointer to $200 sta BUFTABzp,X lda (BUFTABzp,X) ; get character from buffer sta A_0101 ; Load the Disk ID lda #162 ; buffer pointer to $200 sta BUFTABzp,X lda (BUFTABzp,X) ; get character from buffer sta DISKID1 lda #163 ; buffer pointer to $200 sta BUFTABzp,X lda (BUFTABzp,X) ; get character from buffer sta DISKID2 ldx #0 ; drive number lda #$00 sta WPSW0 ; no disk change sta $FF ; flag for read error ;** Calculate blocks free J_D075 jsr SetBufPtrBAM ; buffer address to $6D/$6E [EF3A] ldy #$04 ; begin at position 4 lda #$00 tax B_D07D clc adc (BMPNT),Y ; add number of free blocks per track bcc B_D083 inx ; X as hi-byte B_D083 iny iny ; plus 4 iny iny cpy #$48 ; track 18? beq B_D083 ; then skip cpy #$90 ; last track number? bne B_D07D ; no, -> pha ; lo-byte txa ; hi-byte ldx #0 ; drive number sta NDBH ; hi-byte to $2FC pla ; lo-byte sta NDBL ; to $2FA rts ;** Read a sector into the buffer ReadBlk2Buf ; [D09B] jsr Par2DiskCtrl ; parameters to disk controller jsr ReadBlock ; read block [D0C3] jsr VerifyExec ; ok? [D599] P_D0A4 jsr GetByteFromBuf ; get byte from buffer [D137] sta TRACK ; track jsr GetByteFromBuf ; next byte from buffer [D137] sta SECTOR ; sector rts J_D0AF jsr ReadBlk2Buf ; [D09B] lda TRACK ; track bne B_D0B7 rts B_D0B7 jsr ChangeBuffer2 ; change buffer [CF1E] jsr Par2DiskCtrl ; parameters to disk controller [D6D0] jsr ReadBlock ; read block [D0C3] jmp ChangeBuffer2 ; change buffer [CF1E] ;** Read Block ReadBlock ; [D0C3] lda #$80 ; code for 'read' bne B_D0C9 ;** Write Block WriteBlock ; [D0C7] lda #$90 ; code for 'write' B_D0C9 sta CMD ; save jsr GetBufNumber ; get buffer number [DF93] tax jsr ChkTrackSector ; get track/sector, read/write block ; [D506] P_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 [D125] cmp #$04 ; REL file or direct access? bcs B_D0E8 ; yes, -> inc RECL,X bne B_D0E8 ; increment block counter inc RECH,X B_D0E8 pla tax rts ;** Open channel for reading OpenChan4Read ; [D0EB] lda SA ; secondary address cmp #$13 ; 19 bcc B_D0F3 ; smaller? and #$0F B_D0F3 cmp #$0F bne B_D0F9 lda #$10 ; 16 B_D0F9 tax sec lda LINTAB,X ; already in use? bmi B_D106 ; yes, -> and #$0F sta CURCHN tax clc ; flag for ok B_D106 rts ;** Open channel for writing OpenChan4Write ; [D107] lda SA ; secondary address cmp #$13 ; 19 bcc B_D10F ; smaller? and #$0F B_D10F tax lda LINTAB,X ; channel number tay asl A bcc B_D121 bmi B_D123 B_D119 tya and #$0F sta CURCHN tax clc ; flag for ok rts B_D121 bmi B_D119 B_D123 sec ; flag for channel allocated rts ;** Check for file type REL CheckREL ; [D125] ldx CURCHN lda DIACFLzp,X lsr A and #$07 cmp #$04 ; '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 ; end pointer beq B_D151 lda (BUFTABzp,X) ; get byte from buffer pha lda BUFTABzp,X ; buffer pointer cmp ENDPNT,Y ; equal end pointer? bne B_D14D ; no, -> lda #$FF sta BUFTABzp,X ; buffer pointer to -1 B_D14D pla ; data byte inc BUFTABzp,X ; increment buffer pointer rts ;** Get byte and read next block B_D151 lda (BUFTABzp,X) ; get character from buffer inc BUFTABzp,X ; increment buffer pointer rts ; [D156] RdNxtBlock2 ; [D156] jsr GetByteFromBuf ; get byte from buffer bne B_D191 ; not last character? sta DATA ; save data byte lda ENDPNT,Y ; end pointer beq B_D16A ; yes, -> P_D162 lda #$80 sta REWRFLab,Y ; READ-flag lda DATA ; data byte rts B_D16A jsr ChangeBuffer2 ; change buffer and read next block ; [CF1E] lda #$00 jsr SetBufPointer3 ; set buffer pointer to zero [D4C8] jsr GetByteFromBuf ; get first byte from buffer [D137] cmp #$00 ; track number zero beq B_D192 ; yes, then last block sta TRACK ; save last track number jsr GetByteFromBuf ; get next byte [D137] sta SECTOR ; save as following track jsr ChangeBuffer2 ; change buffer and read next block ; [CF1E] jsr GetDrvNum3 ; save drive number [D1D3] jsr Par2DiskCtrl ; parameter to disk controller [D6D0] jsr ReadBlock ; transmit read command [D0C3] jsr ChangeBuffer2 ; change buffer and read block [CF1E] lda DATA ; get data byte B_D191 rts ;** Write byte in buffer and block B_D192 jsr GetByteFromBuf ; get next byte from buffer [D137] ldy CURCHN sta ENDPNT,Y ; save as end pointer lda DATA ; get data byte back rts J_D19D jsr Write2Buf ; byte in buffer [CFF1] beq Buffer2Disk ; buffer full? rts ;** Write the contents of the buffer to disk Buffer2Disk ; [D1A3] jsr GetDrvNum3 ; get drive number jsr P_F11E ; find free block in BAM P_D1A9 lda #$00 jsr SetBufPointer3 ; buffer pointer to zero [D4C8] lda TRACK jsr Write2Buf ; track number as first byte [CFF1] lda SECTOR jsr Write2Buf ; sector number as second byte [CFF1] jsr WriteBlock ; write block [D0C7] jsr ChangeBuffer2 ; change buffer [CF1E] jsr Par2DiskCtrl ; parameter to disk controller [D6D0] lda #$02 jmp SetBufPointer3 ; buffer pointer to 2 [D4C8] ;** Increment buffer pointer with value in A IncBufPointer ; [D1C6] sta TEMP0 jsr SetBufPointer ; get buffer pointer [D4E8] clc adc TEMP0 sta BUFTABzp,X ; and increment sta DIRBUF rts ;** Get drive number GetDrvNum3 ; [D1D3] jsr GetBufNumber ; get drive number tax lda #0 ; isolate drive number rts ;** Find write channel and buffer FindWrChanBuf ; [D1DF] sec ; flag for writing bcs B_D1E3 ;** Find read channel and buffer FindRdChanBuf ; [D1E2] clc ; flag for reading B_D1E3 php ; save sta TEMP0 ; buffer number, AFAIK 0 or 1 jsr CloseChannel ; close channel [D227] jsr P_D37F ; allocate free channel sta CURCHN ; channel number ldx SA ; secondary address plp ; read channel? bcc B_D1F5 ; yes, -> ora #$80 ; flag for writing B_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 B_D226 ; done already? jsr GetBuffer ; find buffer [D28E] bpl B_D217 ; found? ;** No channel available NoChannel jsr FreeBuffer ; erase flags in table [D25A] Error70 lda #$70 jmp OutputErrorMsg ; 70, 'no channel' [C1C8] B_D217 sta BUF0CH1ab,Y ; buffer number in table dec TEMP0 ; buffer number bmi B_D226 ; already done? jsr GetBuffer ; find buffer [D28E] bmi NoChannel ; not found? sta BUF1CH1ab,Y ; buffer number in table B_D226 rts ;** Close channel ; in: - ; out: - ; used: A X Y CloseChannel ; [D227] lda SA ; secondary address cmp #$0F ; 15? bne B_D22E ; no, -> rts ; else done already B_D22E ldx SA lda LINTAB,X ; channel number cmp #$FF ; not associated? beq B_D259 ; then done and #$3F sta CURCHN ; channel number lda #$FF sta LINTAB,X ; erase association in table ldx CURCHN lda #$00 sta REWRFLzp,X ; erase READ and WRITE flag jsr FreeBuffer ; [D25A] ldx CURCHN ; channel number lda #$01 ; set bit 0 B_D24D dex bmi B_D253 ; shift to correct position asl A bne B_D24D B_D253 ora LINUSE ; free in allocation register sta LINUSE B_D259 rts ;** Free buffer ; in: - ; out: - ; used: A X Y FreeBuffer ; [D25A] ldx CURCHN ; channel number lda BUF0CH1zp,X ; buffer number cmp #$FF beq B_D26B ; not associated? pha lda #$FF sta BUF0CH1zp,X ; erase buffer association pla jsr ClrAllocReg ; clr buffer alloc register [D2F3] B_D26B ldx CURCHN ; channel number lda BUF1CH1zp,X cmp #$FF ; associated in second table? beq B_D27C ; no, -> pha lda #$FF sta BUF1CH1zp,X ; erase association pla jsr ClrAllocReg ; clr buffer alloc register [D2F3] B_D27C ldx CURCHN ; channel number lda SIDSECzp,X cmp #$FF ; associated in 3rd table? beq B_D28D ; no, -> pha lda #$FF sta SIDSECzp,X ; erase association pla jsr ClrAllocReg ; clr buffer alloc register [D2F3] B_D28D rts ;** Get a free buffer GetBuffer ; [D28E] tya pha ;** Find a free buffer ; in: Y ; out : N flag ; FindBuffer ; [D2BA] ldx #$07 B_D2BC lda BUFUSEL and PowersOf2,X ; buffer used? beq B_D2C8 ; no, -> dex ; all buffers checked? bpl B_D2BC ; no, -> rts B_D2C8 lda BUFUSEL eor PowersOf2,X ; toggle bit sta BUFUSEL txa ; set N-flag ; <---------------- bpl B_D2A3 ; found one, -> jsr StealBuffer ; [D339] tax ; success? bmi B_D2B6 ; no, -> B_D2A3 lda JOBSzp,X ; job is completed? bmi B_D2A3 ; no, wait -> ;* clear jobqueue lda #0 sta JOBSzp,X sta LSTJOB,X txa asl A tay lda #$02 sta BUFTABab,Y B_D2B6 pla tay txa rts ;** Check if a buffer is free ChkBufFree ; [D2DA] ldx CURCHN lda BUF0CH1zp,X ; buffer free? bmi B_D2E9 ; yes, -> txa clc adc #$07 ; alternative buffer tax lda BUF0CH1zp,X ; free? bmi B_D2E9 ; yes, -> x_D2D9 rts B_D2E9 cmp #$FF ; free? beq x_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 ClrAllocReg ; [D2F3] and #7 tax ClrAllocReg2 ; [D2F6] lda PowersOf2,X eor #$FF ; invert bit and BUFUSEL sta BUFUSEL rts ;** Close all channels CloseAllChan ; [D307] lda #$0E ; 14 sta SA ; secondary address B_D30B jsr CloseChannel ; close channel [D227] dec SA ; next secondary address bne B_D30B rts ;** Steal the less recently used inactive buffer StealBuffer ; [D339] lda TEMP0 pha ldy #$00 B_D33E ldx LRUTBLzp,Y lda BUF0CH1zp,X ; buffer is active? bpl B_D348 ; yes, -> cmp #$FF ; buffer is used? bne B_D35E ; no, -> ;* check alternative buffer B_D348 txa clc adc #$07 tax lda BUF0CH1zp,X ; buffer active as well? bpl B_D355 ; yes, -> cmp #$FF ; buffer is used? bne B_D35E ; no, -> B_D355 iny ; next channel cpy #$05 bcc B_D33E ldx #$FF ; no buffer found bne B_D37A ; always -> B_D35E stx TEMP0 and #$3F tax B_D363 lda JOBSzp,X ; used by job now? bmi B_D363 ; wait for completion of job, -> cmp #$02 ; job ended in error? bcc B_D373 ; no, steal buffer -> ldx TEMP0 cpx #$07 ; alternative buffers left to check? bcc B_D348 ; yes, -> bcs B_D355 ; always -> B_D373 ldy TEMP0 lda #$FF sta BUF0CH1ab,Y ; make buffer "unused" B_D37A pla sta TEMP0 txa rts ;** Find channel and allocate P_D37F ldy #$00 lda #$01 ; set bit 0 B_D383 bit LINUSE ; channel free? bne B_D391 ; yes, -> iny asl A ; rotate bit to left bne B_D383 ; all channels checked? jmp Error70 ; 70, 'no channel' B_D391 eor #$FF ; rotate bit model and LINUSE ; erase bit sta LINUSE ; allocate channel tya rts ;** Get byte for output P_D39B jsr OpenChan4Read ; open channel for reading [D0EB] jsr LedOn ; turn LED on [C100] jsr NxtByteFile ; get byte in output register [D3AA] ldx CURCHN ; channel number lda OUTREG,X ; get byte rts ; get byte in output register [D3AA] NxtByteFile ; [D3AA] ldx CURCHN ; channel number jsr CheckREL ; check file type [D125] bne B_D3B4 ; no REL file? jmp J_E120 ; get byte from REL file B_D3B4 lda SA ; secondary address cmp #$0F ; 15 beq B_D414 ; yes, read error channel lda REWRFLzp,X and #$08 ; end flag set? bne B_D3D3 ; no, -> jsr CheckREL ; check file type [D125] cmp #$07 ; direct access file? bne B_D3CE ; no, -> lda #$89 ; set READ and WRITE flag sta REWRFLzp,X jmp J_D3DE B_D3CE lda #$00 sta REWRFLzp,X ; erase READ and WRITE flag rts B_D3D3 lda SA ; secondary address beq B_D409 ; zero, LOAD? jsr CheckREL ; check file type [D125] cmp #$04 ; REL file or direct access? bcc B_D400 ; no, -> J_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 B_D3FF ; no, -> lda #$81 sta REWRFLab,Y ; set flags B_D3FF rts B_D400 jsr RdNxtBlock2 ; get byte from buffer [D156] J_D403 ldx CURCHN ; channel number sta OUTREG,X ; byte in output register rts B_D409 lda DIRLST ; flag for directory? beq B_D400 ; no, -> jsr P_ED67 ; create directory line jmp J_D403 B_D414 jsr SetBufPointer ; set buffer pointer [D4E8] cmp #$D4 ; error buffer? bne B_D433 ; no, -> lda DIRBUF+1 cmp #$02 ; error buffer? bne B_D433 ; no, -> lda #$0D ; CR sta DATA ; in output register jsr ClrErrorFlags ; erase error flags [C123] jsr OK2Buffer2 ; create 'ok' message [E6C1] dec ERRPTR ; set buffer pointer back lda #$80 ; set READ flag bne B_D445 ; always -> B_D433 jsr GetByteFromBuf ; get byte from buffer [D137] sta DATA ; into output register bne J_D443 J_D43A lda #$D4 jsr SetBufPointer3 ; set buffer pointer in front of error ; [D4C8] ; pointer lda #$02 sta BUFTABzp+1,X ; hi-address J_D443 lda #$88 ; set READ flag B_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 B_D45F ; no block following? dec BUFTABzp,X ; buffer pointer to -1 jmp RdNxtBlock2 ; read next block [D156] B_D45F rts ;** Read block ReadSector ; [D460] lda #$80 ; command code for reading bne B_D466 ;** Write block WriteSector ; [D464] lda #$90 ; command code for writing B_D466 sta CMD ; save code lda JOBNUM jsr Par2DiskCtrl2 ; parameter to disk controller [D6D3] ldx JOBNUM jmp J_D593 ; 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[DC46] lda #$02 jmp SetBufPointer3 ; buffer pointer to 2 [D4C8] ;** Write dir block WrDirSector ; [D48D] jsr GetTrackSector ; get track and sector number lda #$01 sta TEMP0 ; a block jsr P_F12D ; find free block in BAM lda #$00 jsr SetBufPointer3 ; buffer pointer to zero [D4C8] lda TRACK jsr Write2Buf ; track number in buffer [CFF1] lda SECTOR jsr Write2Buf ; sector number in buffer [CFF1] jsr WriteBlock ; write block to disk [D0C7] jsr VerifyExec ; and verify [D599] lda #$00 jsr SetBufPointer3 ; buffer pointer to zero [D4C8] B_D4BB jsr Write2Buf ; fill buffer with zeroes [CFF1] bne B_D4BB jsr Write2Buf ; zero as following track [CFF1] lda #$FF jmp Write2Buf ; $FF as number of bytes [CFF1] ;** Set buffer pointer SetBufPointer3 ; [D4C8] sta TEMP0 ; save pointer jsr GetBufNumber ; get buffer number [DF93] asl A ; times 2 tax lda BUFTABzp+1,X ; buffer pointer hi sta DIRBUF+1 lda TEMP0 sta BUFTABzp,X ; buffer pointer lo, new value sta DIRBUF rts ;** Close internal channel Close17_18 ; [D4DA] lda #$11 ; 17 sta SA jsr CloseChannel ; close channel [D227] lda #$12 ; 18 sta SA jmp CloseChannel ; close channel [D227] ;** 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 first byte from buffer GetAthByte ; [D4F6] sta TEMP2 ; pointer lo jsr GetBufNumber ; get buffer number [DF93] tax lda BufferAddress,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 P_D50E pha ; save stx JOBNUM ; buffer number txa asl A ; times 2 tax lda TRASECzp+1,X ; sector sta CMD ; save lda TRASECzp,X ; track beq B_D54A ; track 0 not allowed, -> cmp A_FED7 ; 36, highest track number + 1 bcs B_D54A ; track number too big, -> tax pla ; command code pha and #$F0 cmp #$90 ; code for writing? bne B_D57A ; no, -> lda A_0101 B_D538 beq B_D53F cmp A_FED5 ; 'A', format marker bne B_D572 ; 73, 'cbm dos v2.6 1541' B_D53F txa ; track number jsr MaxSectors ; get maximum sector number [F24B] cmp CMD ; compare with sector number beq B_D54A ; equal, then error bcs B_D57A ; smaller? B_D54A jsr GetTrackSect2 ; [D552] Error66 B_D54D lda #$66 jmp CreErrorMsg ; 66, 'illegal track or sector' [E645] ;** Get track and sector numbers GetTrackSect2 ; [D552] lda JOBNUM ; buffer number asl A ; *2 tax ; as index lda TRASECzp,X sta TRACK ; track lda TRASECzp+1,X sta SECTOR ; sector rts ;** Check for valid track and sector numbers ChkTraSec3 ; [D55F] lda TRACK ; track beq B_D54D ; zero, then error cmp A_FED7 ; 36, maximum track number + 1 bcs B_D54D ; 66, 'illegal track and sector number' jsr MaxSectors ; get maximum sector number [F24B] cmp SECTOR ; sector beq B_D54D bcc B_D54D ; error rts B_D572 jsr GetTrackSect2 ; [D552] lda #$73 jmp CreErrorMsg ; 73, 'cbm dos v2.6 1541' [E645] B_D57A ldx JOBNUM ; buffer number pla 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 ;** Write block DskWriteBlock ; [D58A] lda #$90 ; code for write J_D58C ldx JOBNUM ; buffer number P_D590 sta CMD J_D593 lda CMD ; command code jsr P_D50E ; check track and sector ;** Verify execution VerifyExec ; [D599] jsr P_D5A6 ; verify execution bcs VerifyExec ; wait for end pha lda #$00 sta JOBRTN ; erase error flag pla rts P_D5A6 lda JOBSzp,X ; command code (bit 7) in register? bmi B_D5C4 ; yes, -> cmp #$02 bcc B_D5C2 ; error-free execution cmp #$08 ; 8 beq B_D5BA ; write protect cmp #$0B ; 11 beq B_D5BA ; ID mismatch B_D5BA bit JOBRTN bmi B_D5C2 jmp J_D63F ; create error message B_D5C2 clc ; execution ended rts B_D5C4 sec ; execution not yet ended rts B_D635 pla ; command code cmp #$90 ; for writing? bne J_D63F ; no, -> sta LSTJOB,X ; command code in table J_D63F lda JOBSzp,X ; return message jmp PrepErrMsg ; set error message [E60A] B_D644 pla bit JOBRTN bmi J_D66D pha lda #$C0 ; command code for head positioning sta JOBSzp,X ; in command register B_D651 lda JOBSzp,X bmi B_D651 ; wait for execution jsr RetryExec ; attempt command execution again ; [D6A6] cmp #$02 ; return message bcs B_D635 ; incorrect? B_D65C pla cmp #$90 ; command code for writing bne J_D66D ; no, -> sta LSTJOB,X ; in table jsr RetryExec ; attempt execution again [D6A6] cmp #$02 ; return message bcs J_D63F ; error? J_D66D pla pla tay lda JOBSzp,X ; error code clc ; end-of-execution flag rts ;** Attempt command execution multiple times RetryExec ; [D6A6] lda #8 ; bit for LED eor PortB2 sta PortB2 lda LSTJOB,X ; command sta JOBSzp,X ; transmit to disk controller B_D6B9 lda JOBSzp,X ; and return message bmi B_D6B9 ; wait B_D6C4 pha lda #8 ora PortB2 ; LED off sta PortB2 pla rts ;** Transmit param to disk controller 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 ldx #0 ; drive number * 2 rts ;** Enter file in dir 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 [DE3B] lda TYPE ; file type pha ; save ldx JOBNUM ; buffer number lda LSTJOB,X lsr A bcc B_D715 ; equal drive number? ldx #$01 stx DELIND ; pointer in directory jsr Rd_1st_Dir_Blk ; load dir and find first entry [C5AC] beq B_D730 ; if not found -> new sector bne J_D73D ; always -> B_D715 lda DELSEC ; sector number in directory beq B_D726 ; equal zero cmp SECTOR ; equal sector number? beq J_D73D ; yes, -> sta SECTOR ; save sector number jsr ReadSector ; read block [D460] jmp J_D73D B_D726 lda #$01 sta DELIND ; pointer to one jsr Nxt_File_Dir ; find next entry in directory [C617] bne J_D73D ; found? ; write entry B_D730 jsr WrDirSector ; write directory block [D48D] lda SECTOR ; sector number sta DELSEC lda #$02 sta DELIND ; pointer to 2 J_D73D lda DELIND jsr SetBufPointer3 ; set buffer pointer [D4C8] pla sta TYPE ; file type cmp #$04 ; REL file? bne B_D74D ; no, -> ora #$80 ; set bit 7 B_D74D jsr Write2Buf ; and write in buffer [CFF1] pla sta FILTRK ; following track jsr Write2Buf ; in buffer [CFF1] pla sta FILSEC ; following sector jsr Write2Buf ; in buffer [CFF1] jsr GetBufNumber ; get buffer number [DF93] tay lda FILTBL tax lda #$10 ; 16, length of filename jsr NamFil2DirBuf ; write filename in buffer [C66E] ldy #$10 lda #$00 B_D76F sta (DIRBUF),Y ; fill with zeroes at position 16 iny cpy #$1B ; position 27 already? bcc B_D76F ; no, -> lda TYPE ; file type cmp #$04 ; REL file? bne B_D790 ; no, -> ldy #$10 lda TRKSS ; track sta (DIRBUF),Y iny lda SECSS ; and sector sta (DIRBUF),Y ; the side-sectors in directory entry iny lda RECSIZ ; record length sta (DIRBUF),Y ; in directory B_D790 jsr WriteSector ; write block [D464] 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 #0 ; 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 [C2B3] stx INSTRU ldx CMDBUF ; first character from buffer lda TEMPSA ; secondary address = 0 (LOAD)? bne B_D7F3 ; no, -> cpx #'*' bne B_D7F3 lda LastTrack ; last track number beq B_D81C sta TRACK ; track number lda #0 ; last drive number sta DRVNUM lda #$02 sta COMFLG ; set data type to program lda PRGSEC ; last sector number sta SECTOR ; sector jsr LedOn ; turn LED on [C100] jsr RdBlkAllocBuf ; allocate buffer, read block [DC46] lda #$04 ; file type PRG (*2) J_D7EB ldx CURCHN ; channel number sta DIACFLab,Y ; set flag jmp Out_Err_Msg ; done [C194] B_D7F3 cpx #'$' ; directory bne B_D815 ; no, -> lda TEMPSA ; secondary address bne B_D7FF ; not equal to zero? jmp J_DA55 ; OPEN $ ;** Treat directory as SEQ file B_D7FF jsr ChkInputLine ; analyze line to end [C1D1] lda DirTrack ; 18, directory track sta TRACK ; track lda #$00 sta SECTOR ; sector 0 jsr RdBlkAllocBuf ; allocate buffer, read block [DC46] lda #$02 ; file type SEQ (*2) jmp J_D7EB ; continue as above B_D815 cpx #"#" bne B_D82B jmp J_CB84 ; open direct access file B_D81C lda #$02 sta TYPFLG ; file type program jsr LoadBAM ; load BAM [D042] B_D82B jsr ChkForColon ; analyze line, colon found? [C1E5] bne B_D834 ; no, -> ldx #$00 beq B_D840 ; always -> B_D834 txa ; comma found? beq B_D83C ; no, -> jmp Error30 ; 30, 'syntax error' B_D83C dey beq B_D840 dey B_D840 sty FILTBL ; pointer to drive number lda #$8D ; shift CR jsr SearchInputBuf ; analyze line to end [C268] inx stx F2CNT ; comma counter jsr GetDrvNum ; get drive number [C312] jsr Verify_Drv_Num ; check drive number [C3CA] jsr SrchDirEntry ; find file entry in directory [C49D] ldx #$00 ; default values stx RECSIZ ; record length stx MODE stx TYPE ; file type inx cpx F1CNT ; comma before equal sign? bcs B_D876 ; no, -> jsr ChkTypeMode ; get file type and control mode[DA09] inx cpx F1CNT ; additional comma? bcs B_D876 ; no, -> cpy #$04 ; REL file? beq B_D8B1 ; yes, -> jsr ChkTypeMode ; get file type and control method ; [DA09] B_D876 ldx TEMPSA stx SA ; secondary address cpx #$02 ; greater than 2? bcs B_D891 ; yes, -> stx MODE ; 0 or 1 (LOAD or SAVE) lda #$40 sta WBAM lda TYPE ; DEL type? bne B_D8A7 ; no, -> lda #$02 ; PRG sta TYPE ; as file type B_D891 lda TYPE bne B_D8A7 lda COMFLG and #15 ; get file type and command line sta TYPE lda FILTRK ; track number bne B_D8A7 ; not equal zero? lda #$01 sta TYPE ; file type sequential B_D8A7 lda MODE ; control method cmp #$01 ; Write? beq B_D8C6 ; yes, -> jmp J_D940 B_D8B1 ldy FILTBL,X ; pointer behind second comma lda CMDBUF,Y ; get value sta RECSIZ ; record length lda FILTRK ; track number, used? bne B_D876 ; yes, -> lda #$01 ; 'W' sta MODE ; as second method bne B_D876 ; always -> B_D8C6 lda COMFLG ; file type and #$80 ; isolate wildcard flag tax ; wildcard in name? bne B_D8E1 ; yes, -> lda #$20 bit COMFLG ; was file closed? beq B_D8D9 ; yes, -> jsr DelDirEntry ; byte 0 in buffer and write block ; [C8B6] jmp OpenFile4Write ; [D9E3] B_D8D9 lda FILTRK ; track number of the first block bne B_D8E1 ; already existing jmp OpenFile4Write ; [D9E3] B_D8E1 lda CMDBUF ; first character from input buffer cmp #'@' ; replace? beq B_D8F5 ; yes, -> txa ; file exists? bne B_D8F0 ; no, -> jmp Error63 ; 63, 'file exists' B_D8F0 jmp Error33 ; 33, 'syntax error' ;** Open a file with overwriting B_D8F5 lda COMFLG ; file type and #15 ; isolate cmp TYPE bne B_D965 ; file type different? cmp #$04 ; REL file? beq B_D965 ; 64, 'file type mismatch' jsr AllocNewSec ; [DCDA] lda CURCHN sta WLINDX ; save channel number lda #$11 sta SA jsr OpenChan4Read ; open read channel [D0EB] lda INDEX jsr SetBufPointer3 ; set buffer pointer for directory ; [D4C8] 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 [DE3B] jsr WriteSector ; write block [D464] jmp J_D9EF ; prepare track, sector, and drive ; number J_D940 lda FILTRK ; file erased? bne B_D94A ; no, -> jmp Error62 ; 62, 'file not found' B_D94A lda MODE ; control mode cmp #$03 ; Merge? beq B_D95C ; yes, then no test of unclosed file lda #$20 bit COMFLG ; file closed? beq B_D95C ; yes, ok -> lda #$60 jmp OutputErrorMsg ; [C1C8] B_D95C lda COMFLG and #15 ; isolate file type cmp TYPE ; same file type? beq B_D96A ; yes, -> B_D965 jmp Error64 ; 64, 'file type mismatch' B_D96A ldy #$00 sty F2PTR ldx MODE ; control mode cpx #$02 ; Append? bne B_D990 ; no, -> cmp #$04 ; REL file? beq B_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 [DE3B] jsr WriteSector ; write block [D464] pla sta SA ; get channel number back B_D990 jsr OpenFile4Read ; [D9A0] lda MODE ; control mode cmp #$02 bne J_D9EF jsr Prep4Append ; [DA2A] jmp Out_Err_Msg ; done [C194] ;** Open file for reading OpenFile4Read ; [D9A0] ldy #$13 lda (DIRBUF),Y ; track sta TRKSS iny lda (DIRBUF),Y sta SECSS iny lda (DIRBUF),Y ; record length ldx RECSIZ ; last record len sta RECSIZ txa ; length 0 ? beq B_D9C3 ; yes, -> cmp RECSIZ ; same length? beq B_D9C3 ; yes, -> Error50 lda #$50 jmp OutputErrorMsg ; 50, 'record not present' [C1C8] B_D9C3 ldx F2PTR lda FILTRK,X ; track sta TRACK lda FILSEC,X ; sector sta SECTOR jsr RdBlkAllocBuf ; [DC46] ldy CURCHN ldx F2PTR lda DIRSECP,X sta DSEC,Y lda BUFPTR,X sta DIND,Y rts ;** Open file for writing OpenFile4Write ; [D9E3] jsr AllocNewSec ; [DCDA] jsr CreDirEntry ; [D6E4] J_D9EF lda SA ; channel number cmp #$02 bcs B_DA06 jsr GetSector2 ; [DE3E] lda TRACK sta LastTrack lda SECTOR sta PRGSEC B_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 ldy #$04 B_DA11 dey bmi B_DA1C cmp A_FEB2,Y ; control modes 'R', 'W', 'A', 'M' bne B_DA11 sty MODE ; save B_DA1C ldy #$05 B_DA1E dey bmi B_DA29 cmp A_FEB6,Y ; file types 'D','S','P','U','L' bne B_DA1E sty TYPE ; save B_DA29 rts ;** preparation for append Prep4Append ; [DA2A] jsr OpenChnGetByt2 ; open channel to read, get byte lda #$80 jsr ChkChanBit ; last byte? [DDA6] beq Prep4Append ; no, -> jsr GetNxtSector ; get track and sector number [DE95] ldx SECTOR ; sector number inx txa bne B_DA42 ; not $FF? jsr Buffer2Disk ; close buffer, write block [D1A3] lda #$02 B_DA42 jsr SetBufPointer3 ; buffer pointer to 2 [D4C8] 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 lda #$0C ; command number 12 sta INSTRU lda #$00 ; default only drive 0 ldx CMDSIZ dex ; only "$" ? beq B_DA6D ; yes, -> dex bne B_DA86 lda CMDBUF+1 ; second character cmp #'$' bne x_DA68 jmp ShowImages x_DA68 jsr ChkDriveNum ; check drive number, 0 <= drive <= 9 ; [C3BD] bmi B_DA86 ; no, -> B_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 B_DA9E ; always -> B_DA86 jsr ChkForColon ; test input line for ":" [C1E5] bne B_DA90 ; not found, -> jsr CLR_Flg_inp ; erase flags [C2DC] ldy #$03 B_DA90 dey dey sty FILTBL ; pointer to drive number in command jsr ChkWildcard ; analyze line [C200] jsr Chk_Filetype ; ascertain file type [C398] jsr GetDrvNum2 ; get drive number [C320] B_DA9E jsr Verify_Drv_Num ; initialize drive if necessary [C3CA] jsr DirHeader ; prepare disk title [C7B7] jsr SrchDirEntry ; load directory [C49D] jsr P_EC9E ; create and prepare directory x_DAAA jsr GetByteFromBuf ; get byte from buffer [D137] ldx CURCHN ; channel number sta OUTREG,X ; byte in output register lda #$04 sta DIACFLzp,X ; PRG-flag lda #$00 sta INPPTR ; set pointer back in input buffer rts ;** Close routine Close ; [DAC0] lda #$00 sta WBAM lda SA ; secondary address bne B_DAD4 ; not zero? lda #$00 ; secondary address 0, LOAD sta DIRLST jsr CloseChannel ; close channel [D227] B_DAD1 jmp Close17_18 ; close internal channels 17 & 18 ; [D4DA] B_DAD4 cmp #$0F ; 15 beq B_DAEC ; yes, close all channels jsr CloseFile ; close file [DB02] lda SA ; secondary address cmp #$02 bcc B_DAD1 ; smaller than 2? lda ERWORD bne B_DAE9 jmp Out_Err_Msg ; termination [C194] B_DAE9 jmp J_C1AD ;** Close file B_DAEC lda #$0E ; 14 sta SA ; secondary address B_DAF0 jsr CloseFile ; close file [DB02] dec SA ; next secondary address bpl B_DAF0 lda ERWORD bne B_DAFF jmp Out_Err_Msg ; termination [C194] B_DAFF jmp J_C1AD ;** Close file CloseFile ; [DB02] ldx SA ; secondary address lda LINTAB,X ; get channel number cmp #$FF ; no channel associated? bne B_DB0C rts ; no, then none B_DB0C and #$0F ; isolate channel number sta CURCHN jsr CheckREL ; check data type [D125] cmp #$07 ; direct access? beq B_DB26 ; yes, -> cmp #$04 ; REL file? beq B_DB2C ; yes, -> jsr OpenChan4Write ; channel for writing open [D107] bcs B_DB29 ; no file for writing? jsr WriteLastSec ; write last block [DB62] jsr WriteDirEntry ; write entry in directory and block ; [DBA5] B_DB26 jsr WriteBam ; write BAM [EEF4] B_DB29 jmp CloseChannel ; close channel [D227] B_DB2C jsr GetBufWrSec ; get buffer number, write block[DDF1] jsr ChangeBuffer2 ; change buffer [CF1E] jsr SetPar2LstRec ; get last side-sector [E1CB] ldx CHNNUM2 ; side-sector number stx TEMP4 inc TEMP4 lda #$00 sta TEMP1 sta TEMP2 lda CHNNUM3 sec sbc #$0E ; minus 14 for pointer sta TEMP3 jsr CalcSecPtrREL ; calculate block number of file[DF51] ldx CURCHN ; channel number lda TEMP1 sta RECL,X ; record number lo lda TEMP2 sta RECH,X ; record number hi lda #$40 jsr ChkChanBit ; bit 6 set? [DDA6] beq B_DB5F ; no, -> jsr WriteDirEntry ; enter in directory [DBA5] B_DB5F jmp CloseChannel ; close channel [D227] ;** Write last block WriteLastSec ; [DB62] ldx CURCHN ; channel number lda RECL,X ; record number lo ora RECH,X ; record number hi bne B_DB76 ; not zero? jsr SetBufPointer ; set buffer pointer [D4E8] cmp #$02 bne B_DB76 ; not 2 lda #$0D ; CR jsr Write2Buf ; in buffer [CFF1] B_DB76 jsr SetBufPointer ; set buffer pointer [D4E8] cmp #$02 ; now equal to 2? bne B_DB8C ; no, -> jsr ChangeBuffer2 ; change buffer [CF1E] ldx CURCHN ; channel number lda RECL,X ; record number lo bne B_DB88 dec RECH,X ; decrement block number hi B_DB88 dec RECL,X ; and block number lo lda #$00 B_DB8C sec sbc #$01 ; set pointer pha lda #$00 jsr SetBufPointer3 ; buffer pointer to zero [D4C8] jsr Write2Buf ; write zero in buffer [CFF1] pla ; second byte = pointer to end jsr Write2Buf ; write in buffer [CFF1] jsr WriteBlock ; write block to disk [D0C7] jsr VerifyExec ; and verify [D599] jmp ChangeBuffer2 ; change buffer [CF1E] ;** 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 DirTrack ; 18, directory track sta TRACK ; set jsr GetBufNumber ; [DF93] pha sta JOBNUM jsr ReadSector ; read directory block [D460] ldy #$00 lda BufferAddress,X ; buffer address sta R1 lda INDEX ; buffer pointer sta R0 lda (R0),Y ; file type and #$20 ; file closed? beq B_DC21 ; yes, -> jsr CheckREL ; check file type [D125] 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 bne B_DC06 ; set? sta TRACK ; set track number pla sta SECTOR ; sector number lda #$67 jmp CreErrorMsg ; 67, 'illegal track or sector' [E645] B_DC06 pha lda #$00 sta (R0),Y ; erase track number iny sta (R0),Y ; and sector number of the ; substitute file pla ldy TEMP2 sta (R0),Y iny ; set track & sector number of the new ; file lda (R0),Y sta SECTOR pla sta (R0),Y jsr DelSectorChain ; erase all files [C87D] jmp J_DC29 B_DC21 lda (R0),Y ; get file type and #$0F ; isolate bits 0-3 ora #$80 ; set bit 7 for closed file sta (R0),Y J_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 'writing' jsr P_D590 ; write block pla sta SA ; secondary address jmp OpenChan4Write ; open channel for writing [D107] ;** Read block, allocate buffer RdBlkAllocBuf ; [DC46] lda #$01 jsr FindRdChanBuf ; find channel and buffer for read ; [D1E2] jsr ResetPointer ; set pointer [DCB6] lda TYPE ; file type pha ; save asl A sta DIACFLzp,X jsr ReadBlk2Buf ; read block in buffer [D09B] ldx CURCHN ; channel number lda TRACK ; track bne B_DC65 ; following track? lda SECTOR ; sector sta ENDPNT,X ; as end pointer B_DC65 pla ; file type cmp #$04 ; REL file? bne B_DCA9 ; no, -> ldy SA ; secondary address lda LINTAB,Y ; channel number ora #$40 sta LINTAB,Y ; set flag for READ and WRITE lda RECSIZ ; record length sta RecLength,X jsr GetBuffer ; find buffer for side-sector [D28E] bpl B_DC81 ; found? jmp NoChannel ; 70, 'no channel' [D20F] B_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 ; [D6D3] jsr ReadSector4 ; read side sector [DE73] jsr VerifyExec ; and verify [D599] J_DC98 ldx CURCHN ; channel number lda #$02 sta WRIPNT,X ; pointer for writing lda #$00 jsr SetBufPointer3 ; buffer pointer to zero [D4C8] jsr NxtByte2Out ; find next record [E153] jmp GetSector2 ; get track and sector number [DE3E] B_DCA9 jsr RdNxtBlock2 ; get byte from buffer [D156] 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 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 [D1DF] jsr Par2DiskCtrl ; transmit parameter to disk controller ; [D6D0] jsr ResetPointer ; reset pointer [DCB6] ldx CURCHN ; channel number lda TYPE ; file type pha asl A sta DIACFLzp,X ; save as flag pla cmp #$04 ; REL file? beq B_DCFD ; yes, -> lda #$01 sta REWRFLzp,X ; set WRITE flag rts B_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 RECSIZ ; record length sta RecLength,X ; in table jsr GetBuffer ; find buffer [D28E] bpl B_DD16 ; found? jmp NoChannel ; 70, 'no channel' [D20F] B_DD16 ldx CURCHN ; channel number sta SIDSECzp,X ; buffer number for side-sector jsr EraseBuffer ; erase buffer [DEC1] jsr P_F11E ; 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 ; [D6D3] lda #$00 jsr SetBufPtrSS2 ; buffer pointer to zero [DEE9] lda #$00 jsr WrBytSidSec ; [DD8D] lda #$11 ; 17 jsr WrBytSidSec ; as end pointer in buffer [DD8D] lda #$00 ; zero jsr WrBytSidSec ; as side-sector number in buffer ; [DD8D] lda RECSIZ ; record length jsr WrBytSidSec ; in buffer [DD8D] lda TRACK ; track number of this block jsr WrBytSidSec ; in buffer [DD8D] lda SECTOR ; sector number jsr WrBytSidSec ; in buffer [DD8D] lda #$10 ; 16 jsr SetBufPtrSS2 ; buffer pointer to 16 [DEE9] jsr GetSector2 ; get track and sector number [DE3E] lda TRACK ; track number of the first data block jsr WrBytSidSec ; in buffer [DD8D] lda SECTOR ; sector number of the first data block jsr WrBytSidSec ; in buffer [DD8D] jsr WriteSector4 ; write block to disk [DE6C] jsr VerifyExec ; and check [D599] lda #$02 jsr SetBufPointer3 ; buffer pointer to 2 [D4C8] ldx CURCHN ; channel number sec lda #$00 sbc RecLength,X ; record length sta WRIPNT,X ; pointer for writing jsr CreateRecords ; [E2E2] jsr SetLinkLstRec ; write link bytes in buffer [DE19] jsr WriteSector3 ; write block to disk [DE5E] jsr VerifyExec ; and check [D599] jsr WriteBam ; write BAM [EEF4] 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 J_CFFD ; write byte in buffer ;** Manipulate flags E_DD95 bcc DeleteFlags ; [DD97] SetFlags ; [DD97] ldx CURCHN ; channel number ora DIACFLzp,X ; set flag bne B_DDA3 ; (IMHO) always -> ; [DD9D] DeleteFlags ; [DD9D] ldx CURCHN ; channel number eor #$FF and DIACFLzp,X ; erase flag B_DDA3 sta DIACFLzp,X rts ChkChanBit ; [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 B_DDB9 stx TEMP2 ; counter for secondary address lda LINTAB,X ; get channel number from table cmp #$FF bne B_DDCA ; file open? B_DDC2 ldx TEMP2 inx ; increment counter cpx #$10 ; smaller than 16? bcc B_DDB9 rts B_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 B_DDC2 ; no, -> lda DSEC,Y ; sector number in directory cmp DIRSECP,X ; same as file? bne B_DDC2 ; no, -> lda DIND,Y cmp BUFPTR,X ; pointer same? bne B_DDC2 ; no, -> clc rts ;** Write a block of a REL file GetBufWrSec ; [DDF1] jsr GetBufNumber2 ; get buffer number bvc B_DDFC ; no REL file? jsr WriteSector3 ; write block [DE5E] jsr VerifyExec ; and verify [D599] B_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 [E105] ;** Get following 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 linker 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 ;** 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 JOBNUM ; 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 ;** P_DE50 lda #$90 ; command code for writing sta CMD bne B_DE7F ; always -> ;** ReadSector2 ; [DE57] lda #$80 ; command code for reading sta CMD bne B_DE7F ; always -> ;** WriteSector3 ; [DE5E] lda #$90 ; command code for writing sta CMD bne B_DE8B ; always -> ;??? used ??? lda #$80 ; command code for reading sta CMD bne B_DE8B ;** WriteSector4 ; [DE6C] lda #$90 ; command code for writing sta CMD bne B_DE75 ;** ReadSector4 ; [DE73] lda #$80 ; command code for reading B_DE75 sta CMD ldx CURCHN ; channel number lda SIDSECzp,X ; side-sector buffer number tax ; buffer associated? bpl B_DE92 ; yes,-> B_DE7F jsr Par2DiskCtrl ; generate header for disk controller ; [D6D0] jsr GetBufNumber ; get buffer number [DF93] tax lda #0 ; drive number sta LSTJOB,X B_DE8B jsr P_E115 ; buffer number jsr GetBufNumber ; get buffer number [DF93] tax B_DE92 jmp ChkTrackSector ; write block [D506] ;** Get following track and sector from buffer GetNxtSector ; [DE95] lda #$00 jsr SetBufPointer3 ; buffer pointer to zero [D4C8] jsr GetByteFromBuf ; get byte [D137] sta TRACK ; save as track jsr GetByteFromBuf ; get byte [D137] sta SECTOR ; as sector rts ;** Coppy buffer contents CopyBuffer ; [DEA5] pha lda #$00 sta TEMP0 sta TEMP2 lda BufferAddress,Y ; buffer address Y, hi sta TEMP1 lda BufferAddress,X ; buffer address X, lo sta TEMP3 pla tay dey B_DEB9 lda (TEMP0),Y sta (TEMP2),Y dey bpl B_DEB9 rts ;** Erase the buffer EraseBuffer ; [DEC1] tay ; buffer number lda BufferAddress,Y ; get hi-address sta TEMP1 lda #$00 ; lo-address sta TEMP0 tay B_DECC sta (TEMP0),Y ; erase buffer iny bne B_DECC rts ;** Get side-sector number GetNumSideSec ; [DED2] lda #$00 jsr SetBufPtrSS ; buffer pointer to zero [DEDC] ldy #$02 lda (DIRBUF),Y ; byte 2 contains the side-sector number rts ;** Set buffer pointer to side-sector SetBufPtrSS ; [DEDC] sta DIRBUF ; printer lo ldx CURCHN ; channel number lda SIDSECzp,X ; buffer number tax lda BufferAddress,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 [DEDC] 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 B_DF0B ; no, -> bvc B_DF12 ; ok ldx CURCHN ; channel number lda SIDSECzp,X ; buffer number jsr ReadSideSec ; read side-sector [DF1B] jsr IsSidSecInBuf ; and check if in buffer [DF66] bpl B_DF12 ; yes? B_DF0B jsr SetPar2LstRec ; get last side-sector [E1CB] bit A_FECD+1 ; set V bit rts B_DF12 lda CHNNUM3 ; side-sector and pointer jsr SetBufPtrSS2 ; set pointer in side-sector [DEE9] bit A_FECD ; erase V bit rts ;** Read side-sector ReadSideSec ; [DF1B] sta JOBNUM ; buffer number lda #$80 ; command code for reading bne B_DF25 ; always -> ;** Write side-sector ; !!! not used IMHO ==> sta JOBNUM ; buffer number lda #$90 ; command code for writing ; <== B_DF25 sta CMD ; save lda (DIRBUF),Y ; track number sta TRACK iny lda (DIRBUF),Y ; sector number sta SECTOR lda JOBNUM ; buffer number jsr Par2DiskCtrl2 ; transmit parameter to disk controller ; [D6D3] ldx JOBNUM ; buffer number jmp J_D593 ; 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 [D4EB] ;** Calculate number of blocks in a REL file B_DF4C lda #$78 ; 120 block pointers per side-sector jsr IncSidSecPtr ; add to $70/$71 [DF5C] ;** CalcSecPtrREL ; [DF51] dex ; next side-sector? bpl B_DF4C ; yes, -> lda TEMP3 ; pointer value in last block lsr A ; divided by 2 jsr IncSidSecPtr ; add to previous sum [DF5C] lda TEMP4 ; number of the side-sector block ;** IncSidSecPtr ; [DF5C] clc adc TEMP1 sta TEMP1 ; add bcc B_DF65 inc TEMP2 B_DF65 rts ;** Verify side-sector in buffer IsSidSecInBuf ; [DF66] jsr GetNumSideSec ; get side-sector number cmp CHNNUM2 ; = number of necessary block? bne B_DF7B ; no, -> ldy CHNNUM3 ; pointer in side-sector lda (DIRBUF),Y ; track number beq B_DF77 bit A_FECD ; erase bits rts B_DF77 bit A_FECD+2 ; set N-bit rts B_DF7B lda CHNNUM2 ; side-sector number cmp #$06 ; 6 or greater? bcs B_DF8B ; yes, -> asl A tay lda #$04 sta DIRBUF lda (DIRBUF),Y ; track number bne B_DF8F B_DF8B bit A_FECD+3 ; set N and V bits rts B_DF8F bit A_FECD+1 ; set V bit rts ;** Get buffer number GetBufNumber ; [DF93] ldx CURCHN ; channel number lda BUF0CH1zp,X ; buffer number bpl B_DF9B lda BUF1CH1zp,X ; buffer number from second table B_DF9B and #$BF ; erase V bit rts ;** Get buffer number GetBufNumber2 ; [DF9E] ldx CURCHN ; channel number stx LBUSED ; save lda BUF0CH1zp,X ; get buffer number bpl B_DFB0 ; buffer allocated txa clc adc #$07 ; increment number by 7 sta LBUSED ; and save lda BUF1CH1zp,X ; buffer number from table 2 B_DFB0 sta TEMP1 and #$1F ; erase the highest 3 bits bit TEMP1 rts ChkBufferOK ; [DFB7] ldx CURCHN ; channel number lda BUF0CH1zp,X ; buffer number bmi B_DFBF ; buffer free? lda BUF1CH1zp,X ; buffer number from table 2 B_DFBF cmp #$FF ; free? rts ;** DeactivateBuf ; [DFC2] ldx CURCHN ora #$80 ldy BUF0CH1zp,X bpl B_DFCD sta BUF0CH1zp,X rts B_DFCD sta BUF1CH1zp,X rts ;** Get next record in REL file GetNxtRelRec ; [DFD0] lda #$20 jsr DeleteFlags ; erase bit 5 [DD9D] lda #$80 jsr ChkChanBit ; test bit 7 [DDA6] bne B_E01D ; set? ldx CURCHN ; channel number inc RECL,X ; increment record number bne B_DFE4 inc RECH,X ; record number hi B_DFE4 ldx CURCHN ; channel number lda WRIPNT,X ; write pointer beq B_E018 ; zero? jsr SetBufPointer ; set buffer pointer [D4E8] ldx CURCHN ; channel number cmp WRIPNT,X ; buffer pointer smaller than write ; pointer bcc B_DFF6 ; yes, -> jsr WrRdSector ; write block, read next block [E03C] B_DFF6 ldx CURCHN ; channel number lda WRIPNT,X ; write pointer jsr SetBufPointer3 ; set buffer pointer = write pointer ; [D4C8] lda (BUFTABzp,X) ; byte from buffer sta DATA ; put in output register lda #$20 jsr DeleteFlags ; erase bit 5 [DD9D] jsr SetPtr2NxtRec ; add record length to write pointer ; [E304] P_E009 pha ; and save bcc B_E034 ; not yet in last block? lda #$00 jsr GetAthByte ; get track number [D4F6] bne B_E034 ; does block exist? pla ; pointer cmp #$02 ; = 2 beq B_E02A ; yes, -> B_E018 lda #$80 jsr SetFlags ; set bit 7 [DD97] B_E01D jsr GetBufChanNum ; get byte from buffer [D12F] lda BUFTABzp,X ; buffer pointer sta ENDPNT,Y ; as end pointer lda #$0D ; CR sta DATA ; in output register rts B_E02A jsr Ptr2LastChar ; [E035] ldx CURCHN ; channel number lda #$00 sta WRIPNT,X ; write pointer to zero rts B_E034 pla ;** Set the pointer to the last character Ptr2LastChar ; [E035] ldx CURCHN ; channel number sta WRIPNT,X ; set write pointer jmp J_E16E ; continue -> ;** Write block and read next block WrRdSector ; [E03C] jsr GetDrvNum3 ; get drive number jsr GetNxtSector ; get track and sector number [DE95] jsr GetBufNumber2 ; get bufer number [DF9E] bvc B_E05D ; no REL file? jsr WriteSector3 ; write block [DE5E] jsr ChangeBuffer2 ; change buffer [CF1E] lda #$02 jsr SetBufPointer3 ; buffer pointer to 2 [D4C8] jsr Chk4Write ; command code for writing? [DDAB] bne B_E07B ; no, -> jsr ReadSector2 ; read block [DE57] jmp VerifyExec ; and verify [D599] B_E05D jsr ChangeBuffer2 ; change buffer [CF1E] jsr Chk4Write ; command code for writing? [DDAB] bne B_E06B ; no, -> jsr ReadSector2 ; read block [DE57] jsr VerifyExec ; and verify [D599] B_E06B jsr GetNxtSector ; get track and sector number [DE95] lda TRACK ; track beq B_E07B ; no following track jsr ChangeBuffer2 ; change buffer [CF1E] jsr ReadSector2 ; read block [DE57] jsr ChangeBuffer2 ; change buffer [CF1E] B_E07B rts ;** Write a byte in a record WrByte2Record ; [E07C] jsr WrBufNum2Tbl jsr GetBufNumber ; get buffer number [DF93] asl A ; times 2 tax lda DATA ; data byte sta (BUFTABzp,X) ; write in buffer ldy BUFTABzp,X ; buffer pointer iny ; increment bne B_E096 ; not equal zero? ldy CURCHN ; channel number lda WRIPNTab,Y ; write pointer beq B_E09E ; equal zero? ldy #$02 ; buffer pointer to 2 B_E096 tya ldy CURCHN ; channel number cmp WRIPNTab,Y ; buffer pointer = write pointer? bne B_E0A3 ; no, -> B_E09E lda #$20 jmp SetFlags ; set bit 5 [DD97] B_E0A3 inc BUFTABzp,X ; increment buffer pointer bne B_E0AA ; not zero? jsr WrRdSector ; else write block, read next one ; [E03C] B_E0AA rts ;** Write byte in REL file J_E0AB lda #$A0 jsr ChkChanBit ; test bits 6 & 7 [DDA6] bne B_E0D9 ; set? J_E0B2 lda DATA ; data byte jsr WrByte2Record ; write in record [E07C] lda EOIFLG ; end? beq B_E0C8 ; yes, -> rts B_E0BC lda #$20 jsr ChkChanBit ; test bit 5 [DDA6] beq B_E0C8 ; not set lda #$51 ; 51, 'overflow in record' sta ERWORD ; set error flag B_E0C8 jsr P_E0F3 ; fill remainder with zeroes jsr NxtByte2Out ; [E153] lda ERWORD ; error flag set? beq B_E0D6 ; no, -> jmp OutputErrorMsg ; set error message [C1C8] B_E0D6 jmp OK2Buffer ; error free execution [E6BC] B_E0D9 and #$80 ; bit 7 set? bne B_E0E2 ; yes, -> lda EOIFLG beq B_E0BC ; end? rts B_E0E2 lda DATA ; data byte pha jsr ExpandSidSec ; expand side-sector [E31C] pla sta DATA lda #$80 jsr DeleteFlags ; erase bit 7 [DD9D] jmp J_E0B2 ; write byte in file ;** Fill record with 0s P_E0F3 lda #$20 jsr ChkChanBit ; test bit 5 [DDA6] bne B_E104 ; set? lda #$00 sta DATA ; zero as data byte jsr WrByte2Record ; write in record [E07C] jmp P_E0F3 ; until record full B_E104 rts ;** Write buffer number in table WrBufNum2Tbl ; [E105] lda #$40 jsr SetFlags ; set bit 6 [DD97] jsr GetBufNumber2 ; get buffer number [DF9E] ora #$40 ; set bit 6 ldx LBUSED ; channel number + 7 sta BUF0CH1zp,X ; write in table rts P_E115 jsr GetBufNumber2 ; get buffer number [DF9E] and #$BF ; erase bit 6 ldx LBUSED ; channel number sta BUF0CH1zp,X ; write in table rts ;** Get byte from REL file J_E120 lda #$80 jsr ChkChanBit ; test bit 7 [DDA6] bne NoRecord ; set? jsr GetBufChanNum ; get byte from buffer [D12F] lda BUFTABzp,X ; buffer pointer cmp ENDPNT,Y ; compare to end pointer beq NxtByte2Out ; equal? inc BUFTABzp,X ; increment buffer pointer bne B_E13B ; not zero? jsr WrRdSector ; write block, read next one [E03C] J_E138 jsr GetBufChanNum ; get byte from buffer [D12F] B_E13B lda (BUFTABzp,X) J_E13D sta OUTREG,Y ; in output register lda #$89 sta REWRFLab,Y ; set READ and WRITE flag lda BUFTABzp,X ; buffer pointer cmp ENDPNT,Y ; compare to end pointer beq B_E14D ; same? rts B_E14D lda #$81 sta REWRFLab,Y ; set flag for end rts ; [E153] NxtByte2Out ; [E153] jsr GetNxtRelRec ; find next record jsr GetBufChanNum ; get buffer and channel number [D12F] lda DATA ; data byte jmp J_E13D ; into output register ;** Message "No record present" NoRecord ; [E15E] ldx CURCHN ; channel number lda #$0D ; CR sta OUTREG,X ; into output register lda #$81 sta REWRFLzp,X ; set flag for end jmp Error50 ; 50, 'record not present' J_E16E ldx CURCHN ; channel number lda WRIPNT,X ; write pointer sta R1 ; save dec R1 cmp #$02 ; equal 2? bne B_E17E ; no, -> lda #$FF sta R1 B_E17E lda RecLength,X ; record length sta R2 jsr SetBufPointer ; set buffer pointer [D4E8] ldx CURCHN ; channel number cmp R1 ; buffer pointer > write pointer? bcc B_E1A4 beq B_E1A4 ; no, -> jsr ChangeBuffer2 ; change buffer [CF1E] jsr LastCharNot0 ; [E1B2] bcc B_E19D ldx CURCHN ; channel number sta ENDPNT,X jmp ChangeBuffer2 ; change buffer [CF1E] B_E19D jsr ChangeBuffer2 ; change buffer [CF1E] lda #$FF sta R1 B_E1A4 jsr LastCharNot0 ; [E1B2] bcs B_E1AC jsr SetBufPointer ; set buffer pointer [D4E8] B_E1AC ldx CURCHN ; channel number sta ENDPNT,X ; end pointer rts ;** Find the last char of the record <> 0 LastCharNot0 ; [E1B2] jsr SetBufPtrZero ; buffer pointer to zero ldy R1 B_E1B7 lda (DIRBUF),Y ; byte from buffer bne B_E1C8 ; not zero? dey cpy #$02 bcc B_E1C4 dec R2 bne B_E1B7 B_E1C4 dec R2 clc rts B_E1C8 tya sec rts ;** Get last side-sector SetPar2LstRec ; [E1CB] jsr GetNumSideSec ; get number of the side-sector sta CHNNUM2 ; save lda #$04 sta DIRBUF ; pointer to side-sectors ldy #$0A bne B_E1DC B_E1D8 dey dey bmi Error67 B_E1DC lda (DIRBUF),Y ; track number of the previous block beq B_E1D8 tya lsr A ; divide by 2 cmp CHNNUM2 ; = number of the actual block? beq B_E1EF ; yes, -> sta CHNNUM2 ; else save all numbers ldx CURCHN ; channel number lda SIDSECzp,X ; buffer number jsr ReadSideSec ; read block [DF1B] B_E1EF ldy #$00 sty DIRBUF ; buffer pointer lda (DIRBUF),Y ; track number bne Error67 ; another block? iny lda (DIRBUF),Y ; sector number = end pointer tay dey sty CHNNUM3 ; save end pointer tya jmp SetBufPtrSS2 ; set buffer pointer [DEE9] ;** Error67 ; [E202] lda #$67 jmp CreErrorMsg ; 67, 'illegal track or sector' [E645] ;** P - Position command Position ; [E207] jsr ChkLineLength ; verify lines lda CMDBUF+1 ; secondary address sta SA jsr OpenChan4Read ; find channel number [D0EB] bcc B_E219 ; found? jmp Error70 ; 70, 'no block' B_E219 lda #$A0 jsr DeleteFlags ; erase bits 6 & 7 [DD9D] jsr CheckREL ; verify if 'REL'-file [D125] beq B_E228 ; yes, -> Error64 lda #$64 jmp OutputErrorMsg ; 64, 'file type mismatch' [C1C8] B_E228 lda CMDBUF+2 ; record number lo sta RECL,X lda CMDBUF+3 ; record number hi sta RECH,X ldx CURCHN ; channel number lda #$89 sta REWRFLzp,X ; READ and WRITE flag lda CMDBUF+4 ; byte-pointer beq B_E253 ; zero? sec sbc #$01 beq B_E253 cmp RecLength,X ; compare with record length bcc B_E253 lda #$51 sta ERWORD ; 51, 'overflow in record' lda #$00 B_E253 sta CHNNUM1 jsr SetPtrRelFil ; calculate pointer in REL file [CE0E] jsr GetSideSector ; and read appropriate side-sector ; [DEF8] bvc B_E265 ; does block exist? lda #$80 jsr SetFlags ; set bit 7 [DD97] jmp NoRecord ; and 50, 'record not present' [E15E] B_E265 jsr P_E275 lda #$80 jsr ChkChanBit ; test bit 7 [DDA6] beq B_E272 ; not set jmp NoRecord ; 50, 'record not present' [E15E] B_E272 jmp Out_Err_Msg ; done [C194] P_E275 jsr Record2Buffer ; [E29C] lda CHNNUM4 ; pointer in REL file jsr SetBufPointer3 ; set buffer pointer [D4C8] ldx CURCHN ; channel number lda RecLength,X ; record length sec sbc CHNNUM1 ; minus position bcs B_E289 ; positive? jmp Error67 ; 67, 'illegal track or sector' [E202] B_E289 clc adc CHNNUM4 ; add pointer in data block bcc B_E291 ; no overflow adc #$01 ; plus 2 sec B_E291 jsr P_E009 ; set pointer jmp J_E138 ; get byte from buffer E_E297 lda #$51 jmp OutputErrorMsg ; 51, 'overflow in record' [C1C8] ;** Write record into the buffer Record2Buffer ; [E29C] lda DIRBUF ; buffer pointer lo sta R3 lda DIRBUF+1 ; buffer pointer hi sta R4 jsr CompTraSec ; compare track and sector [E2D0] bne B_E2AA ; not equal? rts B_E2AA jsr GetBufWrSec ; [DDF1] jsr GetNxtTraSec ; [DE0C] lda TRACK ; track beq B_E2C2 ; no block following? jsr CompTraSec2 ; compare track and sector number ; [E2D3] bne B_E2BF ; not equal? jsr ChangeBuffer2 ; change buffer [CF1E] jmp ChkBufFree ; [D2DA] B_E2BF jsr ChkBufFree ; [D2DA] B_E2C2 ldy #$00 lda (R3),Y ; track sta TRACK iny lda (R3),Y ; and sector of the next block sta SECTOR jmp J_D0AF ; read block ;** Comp sectors CompTraSec ; [E2D0] jsr GetSector2 CompTraSec2 ; [E2D3] ldy #$00 lda (R3),Y ; track number cmp TRACK ; compare beq B_E2DC rts B_E2DC iny lda (R3),Y ; sector number cmp SECTOR ; compare rts ;** Divide data blocks into records CreateRecords ; [E2E2] jsr SetBufPtrZero ; set buffer pointer ldy #$02 lda #$00 B_E2E9 sta (DIRBUF),Y ; erase buffer iny bne B_E2E9 jsr SetPtr2NxtRec ; set pointer to next record [E304] B_E2F1 sta WRIPNT,X tay lda #$FF sta (DIRBUF),Y ; $FF as 1st character in record jsr SetPtr2NxtRec ; set pointer to next record [E304] bcc B_E2F1 ; done in this block? L_E2FD bne B_E303 ; block full? [E2FD] lda #$00 sta WRIPNT,X ; write pointer to zero B_E303 rts ;** Set pointer to next record SetPtr2NxtRec ; [E304] ldx CURCHN ; channel number lda WRIPNT,X ; write pointer sec beq B_E318 ; equal zero? clc adc RecLength,X ; add record length bcc B_E31B ; smaller than 256? bne B_E318 ; equal 256? lda #$02 bit x_E31C ; set the Zero flag, needed at L_E2FD rts B_E318 adc #$01 ; add two, 1 + C sec B_E31B rts ;** For setting the Zero flag, see routine at x_E31C .by $00 ;** Expand side-sector ExpandSidSec ; [E31C] jsr GetDrvNum3 ; get drive number jsr SetPar2LstRec ; get last side-sector [E1CB] jsr Record2Buffer ; [E29C] jsr Look4FreeBuf ; [CF7B] lda CHNNUM3 sta R1 lda CHNNUM2 ; side-sector number sta R0 lda #$00 sta R2 sta CHNNUM1 jsr SetPtrRelFil ; calculate side-sector number and ; pointer [CE0E] J_E33B jsr NumBlocksFree ; number of free blocks [EF4D] ldy CURCHN ; channel number ldx RecLength,Y ; record length dex txa clc adc CHNNUM4 ; plus pointer in data block bcc B_E355 inc CHNNUM3 inc CHNNUM3 ; increment pointer to end by 2 bne B_E355 inc CHNNUM2 ; increment side-sector number lda #$10 sta CHNNUM3 ; set pointer to 16 B_E355 lda R1 clc adc #$02 jsr SetBufPtrSS2 ; set buffer pointer for side-sector ; [DEE9] lda CHNNUM2 ; side-sector number cmp #$06 bcc B_E368 ; smaller than 6? B_E363 lda #$52 jmp OutputErrorMsg ; 52, 'file too large' [C1C8] B_E368 lda CHNNUM3 ; end pointer sec sbc R1 ; minus last end pointer bcs B_E372 sbc #$0F ; minus 16 clc B_E372 sta TEMP3 lda CHNNUM2 ; side-sector number sbc R0 ; minus last side-sector number sta TEMP4 ; save ldx #$00 stx TEMP1 ; erase sum for calculation stx TEMP2 tax jsr CalcSecPtrREL ; calculate block # of REL file [DF51] lda TEMP2 bne B_E38F ldx TEMP1 dex bne B_E38F inc R2 B_E38F cmp NBTEMP1 ; block number of REL file bcc B_E39D ; greater than free blocks on disk? bne B_E363 ; 52, 'file too large' lda NBTEMP0 cmp TEMP1 bcc B_E363 ; 52, 'file too large' B_E39D lda #$01 jsr GetAthByte ; get byte from buffer [D4F6] clc adc #$01 ; plus 1 ldx CURCHN sta WRIPNT,X ; as write pointer jsr P_F11E ; find free block in BAM jsr WrNxtSecBuf ; track and sector in buffer [DDFD] lda R2 bne B_E3C8 ; only one block needed? jsr WriteSector3 ; write block [DE5E] B_E3B6 jsr ChangeBuffer2 ; change buffer [CF1E] jsr Par2DiskCtrl ; transmit parameter to disk controller ; [D6D0] jsr P_F11E ; find free block in BAM jsr WrNxtSecBuf ; track and sector in buffer [DDFD] jsr CreateRecords ; [E2E2] jmp J_E3D4 B_E3C8 jsr ChangeBuffer2 ; change buffer [CF1E] jsr Par2DiskCtrl ; transmit parameter to disk controller ; [D6D0] jsr CreateRecords ; [E2E2] jsr SetLinkLstRec ; zero byte and end pointer in buffer ; [DE19] J_E3D4 jsr WriteSector3 ; write block [DE5E] jsr GetNxtTraSec ; get track and sector [DE0C] lda TRACK ; track pha lda SECTOR ; and sector pha ; save jsr GetSector2 ; get track and sector from disk[DE3E] lda SECTOR ; controller pha lda TRACK ; save track and sector pha jsr SetPtrSidSec ; set buffer pointer for side-sector ; [DF45] tax bne B_E3F9 ; pointer not zero? jsr P_E44E ; write side-sector lda #$10 jsr SetBufPtrSS2 ; buffer pointer to 16 [DEE9] inc R0 ; increment side-sector number B_E3F9 pla jsr WrBytSidSec ; track in side-sector [DD8D] pla jsr WrBytSidSec ; sector in side-sector [DD8D] pla sta SECTOR ; sector pla sta TRACK ; and get track back beq B_E418 ; no more blocks? lda R0 ; side-sector number cmp CHNNUM2 ; changed? bne B_E3B6 ; yes, -> jsr SetPtrSidSec ; set buffer pointer in side-sector ; [DF45] cmp CHNNUM3 ; end pointer bcc B_E3B6 ; smaller? beq B_E3C8 ; same B_E418 jsr SetPtrSidSec ; set buffer pointer in side-sector ; [DF45] pha lda #$00 jsr SetBufPtrSS ; buffer pointer to zero [DEDC] lda #$00 tay sta (DIRBUF),Y ; zero as track number iny pla ; end pointer sec sbc #$01 ; minus one sta (DIRBUF),Y ; as sector jsr WriteSector4 ; write block [DE6C] jsr VerifyExec ; and verify [D599] jsr WriteBam ; update BAM [EEF4] jsr SetPtrRelFil ; update pointer for REL file [CE0E] jsr ChangeBuffer2 ; change buffer [CF1E] jsr GetSideSector ; right side-sector? [DEF8] bvs B_E444 ; no, -> jmp P_E275 B_E444 lda #$80 jsr SetFlags ; set bit 7 [DD97] jmp Error50 ; 50, 'record not present' ;** Write side-sector and allocate new [E44E P_E44E jsr P_F11E ; find free block in BAM jsr ChangeBuffer2 ; change buffer [CF1E] jsr GetBufWrSec ; write block [DDF1] jsr GetBufNumber ; get buffer number [DF93] pha jsr EraseBuffer ; erase buffer [DEC1] ldx CURCHN ; channel number lda SIDSECzp,X ; buffer number tay pla tax lda #$10 ; 16 bytes of the side-sector jsr CopyBuffer ; copy in buffer [DEA5] lda #$00 jsr SetBufPtrSS ; buffer pointer to 0, old side-sector ; [DEDC] ldy #$02 lda (DIRBUF),Y ; side-sector number pha lda #$00 jsr SetBufPointer3 ; buffer pointer to 0, new side-sector ; [D4C8] pla clc adc #$01 ; increment side-sector number sta (DIRBUF),Y ; and in buffer asl A ; times 2 adc #$04 ; plus 4 sta R3 tay sec sbc #$02 ; minus 2 sta R4 ; same pointer to old side-sector lda TRACK ; track sta R1 sta (DIRBUF),Y ; in buffer iny lda SECTOR ; sector sta R2 sta (DIRBUF),Y ; in buffer ldy #$00 tya sta (DIRBUF),Y ; zero in buffer iny lda #$11 ; 17 sta (DIRBUF),Y ; number of bytes in block lda #$10 ; 16 jsr SetBufPointer3 ; buffer pointer to 16 [D4C8] jsr P_DE50 ; write block jsr VerifyExec ; and verify [D599] ldx CURCHN ; channel number lda SIDSECzp,X ; buffer number of the side-sector pha jsr GetBufNumber2 ; get buffer number [DF9E] ldx CURCHN ; channel number sta SIDSECzp,X ; write in table pla ldx LBUSED ; channel number + 7 sta BUF0CH1zp,X ; in table lda #$00 jsr SetBufPointer3 ; buffer pointer to zero [D4C8] ldy #$00 lda TRACK ; track sta (DIRBUF),Y ; in buffer iny lda SECTOR ; sector sta (DIRBUF),Y ; in buffer jmp J_E4DE B_E4D1 jsr GetBufNumber ; get buffer number [DF93] ldx CURCHN ; channel number jsr ReadSideSec ; read block [DF1B] lda #$00 jsr SetBufPointer3 ; buffer pointer to zero [D4C8] J_E4DE dec R4 dec R4 ; counter for side-sector blocks ldy R3 lda R1 ; track number sta (DIRBUF),Y ; in buffer iny lda R2 ; sector number sta (DIRBUF),Y ; in buffer jsr WriteSector3 ; write block [DE5E] jsr VerifyExec ; and verify [D599] ldy R4 ; counter for side-sector blocks cpy #$03 bcs B_E4D1 ; greater than or equal to 3? jmp ChangeBuffer2 ; change buffer [CF1E] ;** Table of error messages ;** Format: error numbers ;** description ;** (with start and end letters +$80) ;** If value less than $10 ;** Then look up text in pointer ;** Table. ErrorMessages ; [E4FC] ;** Ok .by $00 ; 00 .by $A0,$4F,$CB ; ' oK' ;** Read eroor .by $20,$21,$22,$23,$24,$27 ; error numbers of 'read error' .by $D2,$45,$41,$44 ; 'Read' .by $89 ; pointer to 'error' ;** File too large .by $52 ; 52 .by $83 ; pointer to 'file' .by $20,$54,$4F,$4F ; ' too ' .by $20,$4C,$41,$52,$47,$C5 ; 'largE' ;** Record not present .by $50 ; 50 .by $8B ; pointer to 'record' and 'not' .by $06 ; pointer to 'record' and 'not' .by $20,$50,$52,$45,$53,$45,$4E,$D4 ; ' presenT' ;** Overflow in record .by $51 ; 51 .by $CF,$56,$45,$52,$46,$4C,$4F,$57 ; 'Overflow' .by $20,$49,$4E ; ' in' .by $8B ; pointer to 'record' ;** Write error .by $25,$28 ; error numbers of 'write error' .by $8A ; pointers to 'write' and 'error' .by $89 ; pointers to 'write' and 'error' ;** Write protect on .by $26 ; 26 .by $8A ; pointer to 'write' .by $20,$50,$52,$4F,$54,$45,$43,$54 ; ' protect' .by $20,$4F,$CE ; ' oN' ;** Disk id mismatch .by $29 ; 29 .by $88 ; pointer to 'disk' .by $20,$49,$44 ; ' id' .by $85 ; pointer to 'mismatch' ;** Syntax error .by $30,$31,$32,$33,$34 ; error numbers for 'syntax error' .by $D3,$59,$4E,$54,$41,$58 ; 'Syntax' .by $89 ; pointer to 'error' ;** Write file open .by $60 ; 60 .by $8A ; pointers to 'write', 'file' and 'open' .by $03 ; pointers to 'write', 'file' and 'open' .by $84 ; pointers to 'write', 'file' and 'open' ;** File exists .by $63 ; 63 .by $83 ; pointer to 'file' .by $20,$45,$58,$49,$53,$54,$D3 ; ' existS' ;** File type mismatch .by $64 ; 64 .by $83 ; pointer to 'file' .by $20,$54,$59,$50,$45 ; ' type' .by $85 ; pointer to 'mismatch' ;** No block .by $65 ; 65 .by $CE,$4F ; 'No' .by $20,$42,$4C,$4F,$43,$CB ; ' block' ;** Illegal track or sector .by $66,$67 ; error numbers for .by $C9,$4C,$4C,$45,$47,$41,$4C ; 'Illegal' .by $20,$54,$52,$41,$43,$4B ; ' track' .by $20,$4F,$52 ; ' or' .by $20,$53,$45,$43,$54,$4F,$D2 ; ' sectoR' ;** File not open .by $61 ; 61 .by $83 ; pointer to 'file' .by $06 ; pointer to 'not' .by $84 ; pointer to 'open' ;** File not found .by $39,$62 ; error numbers for 'file not found' .by $83 ; pointers to 'file' .by $06 ; pointers to 'not' .by $87 ; pointers to 'found' ;** Files scratched .by $01 ; 01 .by $83 ; pointer to 'files' .by $53,$20,$53 ; 's s' .by $43,$52,$41,$54,$43,$48,$45,$C4 ; 'cratcheD' ;** No channel .by $70 ; 70 .by $CE,$4F ; 'No' .by $20,$43,$48,$41,$4E,$4E,$45,$CC ; 'channeL' ;** Dir error .by $71 ; 71 .by $C4,$49,$52 ; 'Dir' .by $89 ; pointer to 'error' ;** Disk full .by $72 ; 72 .by $88 ; pointer to 'disk' .by $20,$46,$55,$4C,$CC ; ' fulL' ;** Cbm dos v2.6 1541 .by $73 ; 73 .by 'C' + $80 .tx 'BM IDE-JD8 V0.4' ; CBM IDE-JD8 V0.4 &&&16 .BY ' ' + $80 ;** Drive not ready .by $74 ; 74 .by $C4,$52,$49,$56,$45 ; 'Drive' .by $06 ; pointer to 'not' .by $20,$52,$45,$41,$44,$D9 ; ' readY' ;** Indexed words ;** Format: index number ;** description .by $09 ; ' readY' .by $C5,$52,$52,$4F,$D2 ; 'ErroR' .by $0A .by $D7,$52,$49,$54,$C5 ; 'WritE' .by $03 .by $C6,$49,$4C,$C5 ; 'FilE' .by $04 .by $CF,$50,$45,$CE ; 'OpeN' .by $05 .by $CD,$49,$53,$4D,$41,$54,$43,$C8 ; 'MismatcH' .by $06 .by $CE,$4F,$D4 ; 'NoT' .by $07 .by $C6,$4F,$55,$4E,$C4 ; 'FounD' .by $08 .by $C4,$49,$53,$CB ; 'DisK' .by $0B .by $D2,$45,$43,$4F,$52,$C4 ; 'RecorD' ;** prepare error number and message PrepErrMsg ; [E60A] pha ; save error code stx JOBNUM ; buffer number txa asl A ; times 2 tax ; as pointer lda TRASECzp,X sta TRACK ; get track lda TRASECzp+1,X sta SECTOR ; and sector number pla ; get error code back and #$0F ; isolate bits 0-3 beq B_E625 ; zero, then 24, 'read error' cmp #$0F ; 15? bne B_E627 lda #$74 ; 74, 'drive not ready' bne B_E62D ; 6 B_E625 lda #$06 ; add $20 B_E627 ora #$20 tax dex dex ; subtract two txa B_E62D pha ; save error number lda INSTRU ; number of the disk command ; ????? cmp #$00 ; OPEN or VALIDATE? bne B_E644 ; no, -> lda #$FF sta INSTRU pla ; get error number back jsr Errmsg2buf ; generate error message [E6C7] jsr LoadBAM ; load BAM [D042] jmp CreErrorMsg2 ; set error message [E648] B_E644 pla CreErrorMsg ; [E645] jsr Errmsg2buf ; set error message CreErrorMsg2 ; [E648] jsr EraseInputBuf ; erase input buffer lda #$00 sta WBAM ; erase error flag jsr PrepLedFlash ; turn LED off [C12C] jsr Close17_18 ; close channels 17 and 18 [D4DA] lda #$00 sta INPPTR ; input buffer pointer to zero ldx #NewStack txs ; initialize stack pointer lda ORGSA ; secondary address and #$0F sta SA cmp #$0F ; 15? beq B_E698 ; yes, command channel sei lda LSNACT ; LISTEN active? bne B_E688 ; yes, -> lda TLKACT ; TALK active? bne B_E680 ; yes, -> ldx SA ; channel number lda LINTAB,X ; open channel to this secondary addr cmp #$FF beq B_E698 ; no, -> and #$0F sta CURCHN ; channel jmp J_E68E ;** TALK B_E680 jsr OpenChan4Read ; open channel for reading [D0EB] nop ; accept byte nop nop bne J_E68E ;** LISTEN B_E688 jsr OpenChan4Write ; open channel for writing [D107] nop ; accept byte nop nop J_E68E jsr CheckREL ; verify file type [D125] cmp #$04 ; file type REL? bcs B_E698 ; yes, -> jsr CloseChannel ; close channel [D227] B_E698 jmp WaitLoop1 ; [EBE7] ;** Convert hex to decimal (2 bytes) ; in: A Y ; out: - ; used: A X Y Bcd2Ascii ; [E69B] tax lda #$00 sed J_E69F cpx #$00 beq B_E6AA ; convert hex to BCD clc adc #$01 dex jmp J_E69F B_E6AA cld ;** Divide BCD number into two bytes Hex2Ascii ; [E6AB] tax lsr A lsr A ; shift hi-nibble down lsr A lsr A jsr P_E6B4 ; convert to ASCII txa P_E6B4 and #$0F ; erase top 4 bits ora #$30 ; add '0' sta (ERRPTR),Y ; write in buffer iny ; increment buffer pointer rts ;** Write OK in buffer ; in: - ; out: - ; used: A X Y OK2Buffer ; [E6BC] jsr ClrErrorFlags ; erase error flag, A := 0 ; in: A ; out: - ; used: A X Y OK2Buffer2 ; [E6C1] ldy #$00 sty TRACK ; track 0 sty SECTOR ; sector 0 ;** Error message in buffer (number in A) ; in: A TRACK SECTOR ; out: - ; used: A X Y Errmsg2buf ; [E6C7] ldy #$00 ; buffer pointer ldx #<(ERRBUF) stx ERRPTR ldx #>(ERRBUF) stx ERRPTR+1 ; pointer $A5/$A6 to $02D5 jsr Hex2Ascii ; error number to ASCII and in buffer ; [E6AB] lda #',' sta (ERRPTR),Y ; write in buffer iny ; increment buffer pointer lda ERRBUF ; first digit of the disk status sta OUTREG+5 ; in output register txa ; error number in accumulator jsr Message2Buffer ; error message in buffer [E706] lda #',' sta (ERRPTR),Y ; write in buffer iny ; and increment buffer pointer lda TRACK ; track number jsr Bcd2Ascii ; to ASCII and in buffer [E69B] lda #',' sta (ERRPTR),Y ; write in buffer iny ; increment buffer pointer lda SECTOR ; sector jsr Bcd2Ascii ; convert to ASCII and in buffer[E69B] dey tya clc adc #$D5 sta ENDPNT+5 ; end pointer inc ERRPTR lda #$88 ; set READ flag sta RDFLAG rts ;** Write error message to buffer ; in: A ; out: - ; used: A X Y Message2Buffer ; [E706] tax ; error code to X lda R0 pha ; preserve pointer $86/$87 lda R1 pha lda #<(ErrorMessages) sta R0 lda #>(ErrorMessages) sta R1 ; $E4FC - start of the error messages txa ; error number in accumulator ldx #$00 J_E718 cmp (R0,X) ; compare with error number in table beq B_E73D pha jsr IncPointer ; bit 7 into carry and erase [E775] bcc B_E727 ; not set? B_E722 jsr IncPointer ; bit 7 into carry [E775] bcc B_E722 ; wait for character with bit 7 set B_E727 lda R1 cmp #>(PrepErrMsg) bcc B_E735 ; check for end of table bne B_E739 lda #<(PrepErrMsg) cmp R0 bcc B_E739 B_E735 pla jmp J_E718 ; no, continue B_E739 pla jmp J_E74D ; done B_E73D jsr GetChar ; get a character, bit 7 in carry ; [E767] bcc B_E73D ; wait for character with bit 7 set B_E742 jsr WrChar2Buf ; and write in buffer [E754] jsr GetChar ; get next character [E767] bcc B_E742 ; wait for character with bit 7 set jsr WrChar2Buf ; put character in buffer [E754] J_E74D pla sta R1 pla ; get pointer $86/$87 back sta R0 rts ;** Write character into buffer ; in: A Y ; out: Y ; used: A X Y WrChar2Buf ; [E754] cmp #' ' bcs B_E763 ; greater, then write in buffer tax ; save code lda #$20 ; blank sta (ERRPTR),Y ; write in buffer iny ; increment buffer pointer txa ; code in accumulator jsr Message2Buffer ; output previous text [E706] rts ;** Get a char of the error message B_E763 sta (ERRPTR),Y ; write character in buffer iny ; and increment pointer rts ;** GetChar ; [E767] inc R0 bne Bit7Carry ; increment pointer inc R1 ;** ; in: X ; out: A C ; used: A Bit7Carry ; [E76D] lda (R0,X) ; get character asl A ; bit 7 into carry lda (R0,X) ; get character again and #$7F ; erase bit 7 rts ;** Increment pointer ; in: X ; out: A C ; used: A IncPointer ; [E775] jsr Bit7Carry ; bit 7 into carry inc R0 bne B_E77E ; increment pointer inc R1 B_E77E S_E77F rts ;==> Jiffy J_E781 jsr DelayX ; $FEF6 asl A bpl A_E78A jmp J_FF2D ; $FF2D A_E78A jsr CheckREL ; $E78A , $D125 [D125] tax beq A_E79C cmp #$03 bcs A_E79C lda DIRLST ; directory listen? bne A_E79C ; yes, -> jmp J_FB33 ; $FB33 A_E79C sec ror CONT jmp J_FB3B ; $FB3B ; Jiffy <== ;** & - USR file execute command USRexec ; [E7A3] lda #$8D jsr SearchInputBuf ; check command line to end [C268] jsr P_F258 ; RTS lda F2CNT ; number of file names pha ; save lda #$01 sta F2CNT ; file name lda #$FF sta R0 jsr Srch_File_Dir ; find file [C44F] lda FILTRK bne B_E7C5 ; found? lda #$39 jmp OutputErrorMsg ; 39, 'file not found' [C1C8] B_E7C5 pla sta F2CNT ; get number of file names back lda FILTRK sta TRACK ; track lda FILSEC sta SECTOR ; and sector lda #$03 ; file type 'USR' jsr ReadXxxFile ; buffer allocated, read 1st block ; [D477] B_E7D8 lda #$00 sta R1 ; erase checksum jsr GetBytFromFil ; get byte from file [E839] sta R2 ; save as start address lo jsr GenChecksum ; from checksum [E84B] jsr GetBytFromFil ; get byte from file [E839] sta R3 ; as start address hi jsr GenChecksum ; form checksum [E84B] lda R0 beq B_E7FA lda R2 pha ; save program start address lda R3 pha lda #$00 sta R0 B_E7FA jsr GetBytFromFil ; get byte from file [E839] sta R4 ; save as counter jsr GenChecksum ; form checksum [E84B] B_E802 jsr GetBytFromFil ; get byte from file [E839] ldy #$00 sta (R2),Y ; save as program bytes jsr GenChecksum ; form checksum [E84B] lda R2 clc adc #$01 sta R2 ; increment $88/$89 bcc B_E817 inc R3 B_E817 dec R4 ; decrement pointer bne B_E802 jsr OpenChnGetByt ; get next byte [CA35] lda DATA ; data byte cmp R1 ; equal to checksum? beq B_E82C ; yes, -> jsr GetSector2 ; transmit parameter to disk controller ; [DE3E] lda #$50 jsr CreErrorMsg ; 50, 'record not present' [E645] B_E82C lda EOIFLG ; end? bne B_E7D8 ; no, next data block pla sta R3 pla ; get program start address back sta R2 jmp (J_R2) ; and execute program ;** GetBytFromFil ; [E839] jsr OpenChnGetByt ; get byte from file lda EOIFLG ; end? bne B_E848 ; no, -> jsr GetSector2 ; transmit parameter to disk controller ; [DE3E] lda #$51 jsr CreErrorMsg ; 51, 'overflow in record' [E645] B_E848 lda DATA ; data byte rts ;** Generate checksum GenChecksum ; [E84B] clc adc R1 adc #$00 sta R1 rts ;** IRQ routine for serial bus P_E853 lda PortA1 ; read port A, erase IRQ flag lda #$01 sta ATNPND ; set flag for 'ATN received' rts ;** Service the serial bus ;==> Jiffy SerialBus ; [E85B] sei lda #$00 sta CONT sta LSNACT sta TLKACT sta ATNPND ldx #NewStack txs bit PortB1 ; ATN active? bpl J_E8CA ; no, -> ldy #$80 sty EOIFLG sty ATNMOD lda #$12 sta PortB1 jsr DelayX A_E87C jsr GetByteFromBus ; [E9C9] bne A_E883 sta CONT A_E883 cmp #$3F beq A_E891 cmp #$5F beq A_E89B cmp TLKADR bne A_E895 sty TLKACT A_E891 stx LSNACT beq A_E8C5 A_E895 cmp LSNADR bne A_E89F sty LSNACT A_E89B stx TLKACT beq A_E8C5 A_E89F cmp #$61 bne A_E8AB ldx TLKACT beq A_E8AB lda #$60 sta CONT A_E8AB tax and #$60 cmp #$60 bne A_E8EC stx ORGSA txa and #$0F sta SA txa and #$F0 cmp #$E0 bne A_E8F7 cli jsr Close ; [DAC0] sei A_E8C5 lda PortB1 bmi A_E87C J_E8CA ldx #$00 stx ATNMOD and #$EF sta PortB1 lda LSNACT beq A_E8DD jsr ReceiveData ; [EA2E] jmp WaitLoop1 ; $EBE7 [EBE7] A_E8DD lda TLKACT beq A_E8E9 lda #$08 sta PortB1 jsr P_E909 ; $E909 A_E8E9 jmp WaitLoop0 ; $E8E9 , $EA4E [EA4E] A_E8EC lda LSNACT ora TLKACT bne A_E8F7 lda #$10 sta PortB1 A_E8F7 lda PortB1 bpl J_E8CA bmi A_E8F7 J_E8FE jsr P_F910 jmp J_F418 ; $F418 ; needed by JiffyDOS A_E904 .by $0A, $0A, $0B, $0C, $F9 P_E909 sei jsr OpenChan4Read ; $D0EB [D0EB] bcs A_E96C J_E90F lda CONT beq J_E918 ldx #$46 jmp J_E781 ; $E781 J_E918 ldx CURCHN ldy REWRFLzp,X bpl A_E96C lda PortB1 and #$F7 sta PortB1 lsr A bcc A_E931 jsr P_E96D ; $E96D tya and #$08 bne A_E934 A_E931 jsr P_E966 ; $E931 , $E966 A_E934 jsr ClkOut_H ; [E9AE] jsr P_E96D ; $E96D ldy #$08 A_E93C ldx CURCHN ror OUTREG,X jsr DataOut_L ; [E99C] bcs A_E948 ora #$02 A_E948 jsr P_E9A1 ; $E948 , $E9A1 jsr P_E9BA ; $E9BA ldx #$0B A_E950 dex bne A_E950 ora #$08 jsr P_E99F ; $E99F dey bne A_E93C jsr P_E966 ; $E966 cli jsr NxtByteFile ; [D3AA] sei jmp J_E918 ; $E918 P_E966 jsr Check4EOI ; $E966 , $EA59 [EA59] ror A bcc P_E966 A_E96C rts P_E96D jsr Check4EOI ; $E96D , $EA59 [EA59] ror A bcs P_E96D rts P_E974 lda (BUFTABzp,X) sta TRACK inc BUFTABzp,X lda (BUFTABzp,X) sta SECTOR jsr P_FB64 ; $FB64 jsr P_D0D3 ; $D0D3 jsr P_D0A4 ; $D0A4 B_E987 ldx TRACK bne A_E98E sta OUTREG+6,Y A_E98E rts ; Jiffy <== ;** DATA OUT lo DataOut_L ; [E99C] lda PortB1 P_E99F and #$FD ; output bit '1' P_E9A1 sta PortB1 rts ;** DATA OUT hi DataOut_H ; [E9A5] lda PortB1 ora #$02 ; output bit '0' sta PortB1 rts ;** CLOCK OUT hi ClkOut_H ; [E9AE] lda PortB1 ora #$08 ; set bit 3 sta PortB1 rts ;** CLOCK OUT lo ClkOut_L ; [E9B7] lda PortB1 P_E9BA and #$F7 ; erase bit 3 sta PortB1 rts ;** Read IEC port ReadIecPort ; [E9C0] lda PortB1 ; read port cmp PortB1 ; wait for constants bne ReadIecPort rts ;** Get data byte from bus ; ==> Jiffydos GetByteFromBus ; [E9C9] lda #$08 sta TMP A_E9CD jsr P_EA17 ; $E9CD , $EA17 bne A_E9CD jsr DataOut_L ; [E99C] jsr PATCH2 ; $FF20 [FF20] ldx #$90 A_E9DA jsr P_EA17 ; $E9DA , $EA17 bne A_E9EC dex bmi A_E9DA jsr P_F683 ; $F683 stx EOIFLG A_E9E7 jsr P_EA17 ; $E9E7 , $EA17 beq A_E9E7 A_E9EC ldx #$0C A_E9EE lda PortB1 sta WORK and #$04 beq A_E9FF dex bne A_E9EE jsr P_F674 ; $F674 beq A_E9EE A_E9FF lda WORK eor #$01 lsr A ror DATA A_EA06 jsr P_EA17 ; $EA06 , $EA17 beq A_EA06 dec TMP bne A_E9EC jsr DataOut_H ; [E9A5] ldx #$00 lda DATA rts P_EA17 jsr Check4EOI ; [EA59] and #$04 rts A_EA1D .by $0F, $07, $0D, $05, $0B, $03, $09 .by $01, $0E, $06, $0C, $04, $0A, $02 .by $08, $00, $60 ; Jiffydos <== ;** Accept data from serial bus ReceiveData ; [EA2E] sei jsr OpenChan4Write ; open channel for writing [D107] bcs B_EA39 ; channel not active? lda REWRFLzp,X ; WRITE flag ror A bcs B_EA44 ; not set? B_EA39 lda ORGSA ; secondary address and #$F0 cmp #$F0 ; OPEN command? beq B_EA44 ; yes, -> jmp WaitLoop0 ; to wait loop [EA4E] ; ==> Jiffydos B_EA44 jsr P_FBC1 ; $EA44 , $FBC1 nop jsr P_F769 ; $F769 ; Jiffydos <== jmp ReceiveData ; to loop beginning [EA2E] ;** WaitLoop0 ; [EA4E] lda #$00 sta PortB1 ; reset IEEE port jmp WaitLoop1 ; to wait loop [EBE7] S_EA56 jmp SerialBus ; [E85B] ;** Test for EOI Check4EOI ; [EA59] lda ATNMOD ; EOI received? beq B_EA63 ; yes, -> lda PortB1 ; IEEE port bpl B_EA6B B_EA62 rts B_EA63 lda PortB1 ; IEC port bpl B_EA62 jmp SerialBus ; to serial bus main loop [E85B] ; ==> Jiffydos B_EA6B jmp J_E8CA ; Jiffydos <== ;** Flash LED for hardware defects, self-test ; if X=$FD, then continue flashing BlinkOnce ; [EA6E] ldx #$00 ; blink once for ZeroPage .by $2C ; dummy BIT opcode BlinkX ; [EA71] ldx TEMP0 ; blink X+1 times for RAM/ROM err txs ; use Stackreg. as extra register L_EA74 tsx L_EA75 lda #$08 ; LED on ora PortB2 jmp PATCH3 ; [FEEA] J_EA7D tya ; delay L_EA7E clc L_EA7F adc #$01 bne L_EA7F dey bne L_EA7E lda PortB2 and #$F7 ; turn LED off sta PortB2 ; LED off L_EA8E tya ; delay L_EA8F clc L_EA90 adc #$01 bne L_EA90 ; delay loop dey bne L_EA8F dex ; all flashes? bpl L_EA75 ; no, -> cpx #$FC bne L_EA8E ; no, extra pause beq L_EA74 ; always, -> start again flashing ;** RESET routine RESET ; [EAA0] sei cld ldx #$FF jmp PATCH1 ; port A to output [FF10] ;** Test ZP-RAM L_EAA7 inx ; Why ???, see R_EAAA ldy #$00 R_EAAA ldx #$00 ;** Fill ZP with ascending pattern L_EAAC txa ; Store 1, 2, 3 etc. sta JOBSzp,X ; .... on address 1, 2, 3 etc. inx bne L_EAAC L_EAB2 txa cmp JOBSzp,X ; check contents bne BlinkOnce ; no, then to error display (blink) L_EAB7 inc JOBSzp,X ; loop to add 256 iny bne L_EAB7 cmp JOBSzp,X ; result must be the same bne BlinkOnce ; error sty JOBSzp,X ; Y=0 lda JOBSzp,X ; A=0 ? bne BlinkOnce ; no, error -> inx bne L_EAB2 ;** Test both ROMs L_EAC9 inc TEMP0 ; number of LED-flashes stx IP+1 ; HB lda #$00 sta IP ; IP=0 tay ; &&&00 Skip ROM test for the moment ;-- ldx #$20 ; 8 KByte ;-- clc jmp CheckRAM ; &&& L_EAD5 dec IP+1 ; next page L_EAD7 adc (IP),Y ; add byte iny bne L_EAD7 dex ; all 8 KB bne L_EAD5 ; no -> adc #$00 ; add Carry tax cmp IP+1 ; A=$E0/C0 ? bne L_EB1F ; no, error -> cpx #$C0 ; $C000-$DFFF checked? bne L_EAC9 ; no, next 8 KB ;** Check RAM CheckRAM lda #$01 sta IP+1 ; start with page 1 inc TEMP0 ldx #$07 ; 7 pages L_EAF2 tya clc adc IP+1 sta (IP),Y iny bne L_EAF2 inc IP+1 dex ; next page bne L_EAF2 ldx #$07 ; 7 pages L_EB02 dec IP+1 L_EB04 dey tya clc adc IP+1 cmp (IP),Y bne L_EB1F ; RAM-error -> eor #$FF sta (IP),Y eor (IP),Y sta (IP),Y bne L_EB1F ; RAM-error -> tya bne L_EB04 ; next byte dex bne L_EB02 ; next page beq InitStack ; always -> L_EB1F jmp BlinkX ; to error display [EA71] ;** Initialize stackpointer InitStack ; [EB22] ; Set root image ldx #0 stx LBAimage+2 ; X = 0 stx LBAimage+1 stx ImageLBA stx ImageLBA+1 stx ImageLBA+2 InitLBAima ldx #3 ; Root image starts at sector 768 stx LBAimage InitStack2 ; start here after changing image ; &&&02 Init the IDE drive ldx #NewStack txs ldx #$FF stx POSTcode+2 ; init data direction stx POSTcode2+2 ; init data direction stx POSTcode3+2 ; init data direction ldx #$C3 stx POSTcode ; output C3 stx POSTcode2 ; output C3 stx POSTcode3 ; output C3 ; init LED lda #8 sta DDRB2 sta PortB2 ; Check if drive is ready InitIde010 lda IDEstatus ; ready? bmi InitIde010 ; if not, -> wait ; <-- &&02 lda PortB2 ; de-activate LED and #$F7 ; turn LED off sta PortB2 lda #$01 ; trigger CA1 (ATN IN) sta PCR1 ; on positive edge lda #$82 ; enable interrupt via ATN IN sta IFR1 ; interrupt possible through ATN IN sta IER1 ;** Read device number out of bit 5/6 of Port B1 lda PortB1 ; read port B and #$60 ; isolate bits 5 & 6 (device number) asl rol rol ; rotate to bit positions 0 & 1 rol ora #$48 ; dev. number for talk sta TLKADR ; device number for TALK (send) eor #$60 ; dev. number for listen sta LSNADR ; device number + $20 for LISTEN ;** Initialize pointers to buffers 0..4 ldx #$00 ldy #$00 L_EB4F lda #$00 sta BUFTABzp,X ; Low Byte = 0 inx lda BufferAddress,Y ; Load HB from tabel sta BUFTABzp,X ; save inx iny cpy #$05 bne L_EB4F ;** Let $A3/$A4 point to $0200 lda #<(CMDBUF) sta BUFTABzp,X inx ; pointer $A3/$A4 to $200, input buffer lda #>(CMDBUF) sta BUFTABzp,X inx ;** Buffer errormessage ERRBUF in $A5/$A6 lda #<(ERRBUF) sta BUFTABzp,X inx ; pointer $A5/$A6 to $2D5, error lda #>(ERRBUF) ; message pointer sta BUFTABzp,X ;** Fill channel table with $FF (= not used) lda #$FF ldx #$12 L_EB76 sta LINTAB,X ; fill channel table with $FF dex bpl L_EB76 ldx #$05 L_EB7E sta BUF0CH1zp,X ; erase buffer tables sta BUF1CH1zp,X sta SIDSECzp,X ; erase side-sector table dex bpl L_EB7E lda #$05 ; buffer 5 sta BUF0CH5 ; for channel 4 lda #$06 ; buffer 6 sta BUF0CH6 ; for channel 5 lda #$FF sta BUF0CH7 sta BUF1CH7 lda #$05 sta CH5WFL ; reset WRITE-flag channel 5 lda #$84 sta CH4WFL ; set WRITE-flag channel 4 lda #$0F ; initialize channel allocation register sta LINUSE ; mark all channels as free lda #$01 sta WRFLAG ; WRITE flag lda #$88 sta RDFLAG ; READ flag lda #$E0 ; 5 buffers free sta BUFUSEL ; 5 buffers free (bit = 0) lda #$01 ; disk has changed sta WPSW0 jsr SetVectorU0 ; set vector for U0 [CB63] jsr InitLastTable ; initialize channel table [CEFA] jsr InitDiskCntrlr ; initialize disk-controler [F259] ;** Initialize NMI-vector lda #<(InitStack) sta VNMI lda #>(InitStack) ; pointer $65/$66 to $EB22 sta VNMI+1 lda #$73 ; initialize error message jsr OK2Buffer2 ; 73, 'cbm dos v2.6 1541' [E6C1] ; init 1st 6522, port B lda #$1A ; bit 1, 3 & 4 to output sta DDRB1 ldx #$00 stx PortB1 ; new POSTcode = ROM version ldx #$04 stx POSTcode ; output C3 ;** WaitLoop1 ; [EBE7] cli lda PortB1 and #$E5 ; reset serial port sta PortB1 lda CMDWAT ; command flag? beq WaitLoop2 ; no, -> lda #$00 ; reset command flag sta CMDWAT ; reset command flag sta NMIFLG jsr InterprCmnd ; analyse and execute instruction ; [C146] ;** Wait loop WaitLoop2 ; [EBFF] cli lda ATNPND ; ATN pending? beq L_EC07 ; no, -> jmp SerialBus ; to IEEE routine [E85B] L_EC07 cli lda #$0E ; 14 sta TEMP3 ; secundair address lda #$00 sta TEMP0 ; job counter sta TEMP1 L_EC12 ldx TEMP3 lda LINTAB,X ; secondary address cmp #$FF ; channel added ? beq L_EC2B ; no -> and #$3F sta CURCHN ; channel number jsr GetBufNumber ; get buffer # [DF93] tax lda LSTJOB,X ; get drive # and #$01 tax inc TEMP0,X ; increment job counter L_EC2B dec TEMP3 ; decrement secundair address bpl L_EC12 ; >= 0, -> ldy #$04 ; buffer counter L_EC31 lda JOBSab,Y ; does disk controler work? bpl L_EC3B ; no, -> and #$01 ; isolate drive # tax inc TEMP0,X ; incr. job counter L_EC3B dey ; next buffer? bpl L_EC31 ; yes, -> sei lda PortB2 and #$F7 ; LED bit off pha lda TEMP0 ; job for drive 0? beq L_EC5C ; no, -> L_EC58 pla ora #$08 ; LED bit on pha L_EC5C pla ; bit for LED ldx ERWORD ; IRQ-counter for blinking LED beq L_EC98 ; no blinking, -> lda PortB2 cpx #$80 ; old error? bne L_EC81 ; yes, -> jmp L_EC8B ; no, new error -> L_EC81 ldx T1CH1 ; still timing? bmi L_EC98 ; yes -> ldx #$A0 ; no, new 8 msec cycle stx T1CH1 ; set timer L_EC8B dec ERWORD ; time is up? bne L_EC98 ; no -> eor #8 ; toggle LED ldx #$10 stx ERWORD ; reset counter L_EC98 sta PortB2 ; LED on/off jmp WaitLoop2 ; start loop all over again [EBFF] ;** Load dir P_EC9E lda #$00 sta SA ; secondary address 0 lda #$01 jsr FindRdChanBuf ; find channel and buffer [D1E2] lda #$00 jsr SetBufPointer3 ; initialize buffer pointer [D4C8] ldx CURCHN ; channel number lda #$00 sta ENDPNT,X ; pointer to end = zero jsr GetBufNumber ; get buffer number [DF93] tax lda #0 ; drive number sta LSTJOB,X ; bring in table ; write start address $0401 in buffer lda #$01 jsr Write2Buf ; [CFF1] lda #$04 jsr Write2Buf ; [CFF1] lda #$01 ; 2 times 1 jsr Write2Buf ; [CFF1] jsr Write2Buf ; write in buffer as link address ; [CFF1] lda ImageLBA ; image number lo jsr Write2Buf ; write in buffer as line number[CFF1] lda ImageLBA+1 ; image number hi jsr Write2Buf ; in buffer [CFF1] jsr DirLine2Buf ; directory entry in buffer [ED59] jsr GetBufNumber ; get buffer number [DF93] asl A tax dec BUFTABzp,X ; decrement buffer pointer dec BUFTABzp,X lda #$00 jsr Write2Buf ; 0 as line end in buffer [CFF1] P_ECEA lda #$01 jsr Write2Buf ; 2 times 1 as link address [CFF1] jsr Write2Buf ; [CFF1] jsr GetDirEntry ; directory entry in buffer [C6CE] bcc B_ED23 ; another entry? lda NBTEMP0 ; block number lo jsr Write2Buf ; in buffer [CFF1] lda NBTEMP1 ; block number hi jsr Write2Buf ; in buffer [CFF1] jsr DirLine2Buf ; directory entry in buffer [ED59] lda #$00 ; zero as end marker in buffer jsr Write2Buf ; buffer full? [CFF1] bne P_ECEA ; no, -> J_ED0D jsr GetBufNumber ; get buffer number [DF93] asl A tax lda #$00 sta BUFTABzp,X ; buffer pointer to zero lda #$88 ; set READ flag ldy CURCHN ; channel number sta DIRLST sta REWRFLab,Y ; flag for channel lda DATA ; data byte rts B_ED23 lda NBTEMP0 ; block number lo jsr Write2Buf ; write in buffer [CFF1] lda NBTEMP1 ; block number hi jsr Write2Buf ; in buffer [CFF1] jsr DirLine2Buf ; 'blocks free.' in buffer [ED59] jsr GetBufNumber ; get buffer number [DF93] asl A tax dec BUFTABzp,X dec BUFTABzp,X ; buffer pointer minus 2 lda #$00 jsr Write2Buf ; [CFF1] jsr Write2Buf ; [CFF1] jsr Write2Buf ; three zeroes as program end [CFF1] jsr GetBufNumber ; get buffer number [DF93] asl A ; times 2 tay lda BUFTABab,Y ; buffer pointer ldx CURCHN sta ENDPNT,X ; as end marker dec ENDPNT,X jmp J_ED0D ;** Write dir line into buffer DirLine2Buf ; [ED59] ldy #$00 B_ED5B lda NameBuffer,Y ; character from buffer jsr Write2Buf ; write in output buffer [CFF1] iny cpy #$1B ; 27 characters? bne B_ED5B rts ;** Get byte from buffer P_ED67 jsr GetByteFromBuf ; get byte [D137] beq B_ED6D ; buffer pointer zero? rts B_ED6D sta DATA ; save data byte ldy CURCHN ; channel number lda ENDPNT,Y ; set end marker beq B_ED7E ; zero (LOAD $)? lda #$80 sta REWRFLab,Y ; set READ flag lda DATA ; data byte rts B_ED7E pha lda DIRLST cmp #$89 ; directory of images? beq x_ED80 ; yes, -> jsr P_ECEA ; create directory line in buffer pla rts x_ED80 jsr t_ECEA ; create image line in buffer pla rts ;** V - Validate command Validate ; [ED84] jsr ChkInputLine ; find drive number in input line jsr LoadBAM ; load BAM [D042] lda #$40 sta WBAM jsr CreateBam ; create new BAM in buffer [EEB7] lda #$00 sta DELIND jsr Rd_1st_Dir_Blk ; load directory, find 1st flag [C5AC] bne B_EDD9 ; found? B_ED9C lda #$00 sta SECTOR ; sector 0 lda DirTrack ; 18 sta TRACK ; track 18 for BAM jsr AllocateFile ; mark directory blocks as allocated ; [EDE5] lda #$00 sta WBAM jsr WriteBam2 ; write BAM back to disk [EEFF] jmp Out_Err_Msg ; done, prepare disk status [C194] B_EDB3 iny lda (DIRBUF),Y ; save track pha iny lda (DIRBUF),Y ; and sector pha ldy #$13 ; pointer to side-sector block lda (DIRBUF),Y beq B_EDCB ; no track following? sta TRACK ; track and iny lda (DIRBUF),Y sta SECTOR ; sector of 1st side-sector block jsr AllocateFile ; mark side-sector block as [EDE5] B_EDCB pla ; allocated sta SECTOR pla ; get track and sector back sta TRACK jsr AllocateFile ; mark blocks of file as allocated ; [EDE5] J_EDD4 jsr Rd_Nxt_Dir_Blk ; read next entry in directory [C604] beq B_ED9C ; end of directory? B_EDD9 ldy #$00 lda (DIRBUF),Y ; file type bmi B_EDB3 ; bit 7 set, file closed? jsr DelDirEntry ; file type to zero and write BAM ; [C8B6] jmp J_EDD4 ;** Allocate file blocks in BAM AllocateFile ; [EDE5] jsr ChkTraSec3 ; check track and sector number jsr AllocSector ; allocate block in BAM [EF90] jsr ReadSeqFile ; read next block [D475] J_EDEE lda #$00 jsr SetBufPointer3 ; buffer pointer zero [D4C8] ; ==> Jiffydos jsr P_D0A4 ; $D0A4 lda TRACK bne A_EDFD jmp CloseChannel ; $D227 [D227] A_EDFD jsr AllocSector ; $EDFD , $EF90 [EF90] sei jsr P_FB64 ; $FB64 cli jmp J_EDEE ; $EDEE ; Jiffydos <== ;** N - New (Format) command New ; [EE0D] jsr GetDrvNum ; get drive number lda DRVNUM ; drive number OK? bpl B_EE19 ; yes, -> Error33 lda #$33 jmp OutputErrorMsg ; 33, 'syntax error' [C1C8] B_EE19 jsr LedOn ; turn LED on [C100] ldx #0 ; drive number * 2 ldy FILTBL+1 ; comma position cpy CMDSIZ ; compare with end name beq B_EE46 ; format without ID lda CMDBUF,Y ; first character of ID sta DISKID1 ; save lda CMDBUF+1,Y ; second character sta DISKID2 jsr CloseAllChan ; close all channels [D307] lda #$01 sta TRACK ; track 1 jsr FormatFloppy ; format disk [C8C6] jsr EraseBamBuf ; erase buffer [F005] jmp J_EE56 ; continue as below B_EE46 jsr LoadBAM ; load BAM [D042] ldx #0 ; drive number lda A_0101 cmp A_FED5 ; 'A', marker for 1541 format beq J_EE56 ; ok jmp B_D572 ; 73, 'cbm dos v2.6 1541' J_EE56 jsr CreateBam ; create BAM [EEB7] lda JOBNUM ; buffer number tay asl A tax lda LengthBAM ; $90, start of disk name sta BUFTABzp,X ; buffer pointer to name ldx FILTBL lda #$1B ; 27 jsr NamFil2DirBuf ; write filenames in buffer [C66E] ldy #$12 ; position 18 ldx #0 ; drive number lda A_FED5 ; 'A', 1541 format sta A_0101 txa asl A ; times 2 tax lda DISKID1 ; ID, first character sta (DIRBUF),Y ; in buffer iny lda DISKID2 ; and second character sta (DIRBUF),Y ; in buffer ; store 'IDE' in BAM iny lda #'I' sta (DIRBUF),Y ; in buffer iny lda #'D' sta (DIRBUF),Y ; in buffer iny lda #'E' sta (DIRBUF),Y ; in buffer ldy #$02 lda A_FED5 ; 'A', 1541 format sta (BMPNT),Y ; and at position 2 ; allocate BAM lda DirTrack ; 18 sta TRACK ; track number jsr AllocSector2 ; mark block as allocated [EF93] lda #$01 ; 1 sta SECTOR ; sector number jsr AllocSector2 ; mark block as allocated [EF93] jsr WriteBam2 ; write BAM [EEFF] jsr EraseBamBuf ; [F005] ldy #$01 lda #$FF sta (BMPNT),Y ; all 256 bytes of this sector used jsr WriteSector ; write Directory [D464] dec SECTOR ; decrement sector number, 0 ;** update image directory lda ImageLBA sta IDEtmp0 lda ImageLBA+1 sta IDEtmp1 lda ImageLBA+2 sta IDEtmp2 lda #0 sta IDEtmp3 ; pointer within sector ; divide by 16 (16 image headers / sector) ldx #4 x_EE68 lsr IDEtmp2 ror IDEtmp1 ror IDEtmp0 ror IDEtmp3 dex bne x_EE68 ; add 1 because IDE starts with sector 1 clc lda IDEtmp0 adc #1 sta IDEtmp0 bcc x_EE70 inc IDEtmp1 bne x_EE70 inc IDEtmp2 ; read sector x_EE70 lda IDEtmp0 sta IDElba0 lda IDEtmp1 sta IDElba1 lda IDEtmp2 sta IDElba2 lda #$E0 sta IDElba3 lda #1 sta IDEnumsec lda #$20 ; read sector jsr SendCommand ldy #0 x_EE74 lda IDEdata sta (BMPNT),Y iny bne x_EE74 x_EE76 lda IDEstatus ; ready? bmi x_EE76 ; if not, -> wait ; change header lda #16 sta IDEtmp4 ; counter ldx FILTBL ldy IDEtmp3 x_EE78 lda CMDBUF,x cpx LIMIT ; end of string? bcc x_EE7A ; no, -> lda #' ' ; fill with spaces x_EE7A sta (BMPNT),Y inx iny dec IDEtmp4 ; 16 chars? bne x_EE78 ; store sector x_EE7B lda #$30 ; write sector jsr SendCommand ldy #0 x_EE7C lda (BMPNT),Y sta IDEdata iny bne x_EE7C x_EE7E lda IDEstatus ; ready? bmi x_EE7E ; if not, -> wait ; rest of original routine jsr ReadSector ; read block [D460] jmp Out_Err_Msg ; prepare disk status [C194] ;** Create BAM CreateBam ; [EEB7] jsr ClearTBAM ldy #$00 lda #$12 ; 18 sta (BMPNT),Y ; pointer to directory track iny tya ; 1 sta (BMPNT),Y ; pointer to directory sector iny iny iny B_EEC7 lda #$00 sta TEMP0 sta TEMP1 ; 3 bytes = 24 bits for sectors sta TEMP2 tya ; byte position lsr A lsr A ; divided by 4 = track number jsr MaxSectors ; get number of sectors [F24B] sta (BMPNT),Y ; and in BAM iny tax B_EED9 sec rol TEMP0 rol TEMP1 ; create bit model rol TEMP2 dex bne B_EED9 B_EEE3 lda TEMP0,X ; 3 bytes sta (BMPNT),Y ; the BAM in buffer iny inx cpx #$03 bcc B_EEE3 cpy #$90 ; position 144? bcc B_EEC7 ; no, next track jmp J_D075 ; calculate number of free blocks ;** Write BAM if needed WriteBam ; [EEF4] jsr GetBufNumber ; get buffer number tax ; [EEFF] WriteBam2 ; [EEFF] ldy #0 lda MDIRTY ; BAM-changed flag set? bne B_EF07 ; yes, -> rts B_EF07 lda #$00 sta MDIRTY ; reset BAM-changed flag jsr SetBufPtrBAM ; set buffer pointer for BAM [EF3A] lda #0 ; drive number pha jsr VerifyBamEntry ; verify BAM entry [F0A5] pla clc adc #$01 ; increment drive number jsr VerifyBamEntry ; verify BAM entry [F0A5] lda TRACK ; track pha lda #$01 ; track 1 sta TRACK B_EF24 asl A ; times 4 asl A sta BMPNT ; bytes/track jsr P_F220 ; verify BAM inc TRACK ; increment track number lda TRACK cmp A_FED7 ; and compare with max val + 1 = 36 bcc B_EF24 ; ok, next track pla sta TRACK ; get track number back jmp DskWriteBlock ; write BAM to disk [D58A] ;** Set buffer pointer for BAM SetBufPtrBAM ; [EF3A] jsr GetBufNumBAM2 ; get 13 for drive 0 [F10F] tax jsr ReadBAM ; allocate buffer [F0DF] ldx JOBNUM ; buffer number lda BufferAddress,X ; buffer address, hi byte sta BMPNT+1 lda #$00 ; lo byte sta BMPNT ; pointer to $6D/$6E rts ;** Get number of free blocks for dir NumBlocksFree ; [EF4D] ldx #0 ; drive number lda NDBL ; number of blocks, lo sta NBTEMP0 lda NDBH ; number of blocks, hi sta NBTEMP1 ; in buffer for directory rts S_EF5C jsr P_EFF1 ; set buffer pointer ;** Mark block as free FreeSector ; [EF5F] jsr GetBitBAM ; get state of bit for sector in BAM ; ==> Jiffydos bne A_EF85 lda (BMPNT),Y ; bit model of BAM ora PowersOf2,X ; set bit X, marker for free sta (BMPNT),Y jsr P_EF88 ; set flag for BAM changed ldy TEMP0 clc lda (BMPNT),Y adc #$01 ; increment number of free blocks/track sta (BMPNT),Y lda TRACK ; track cmp #$12 ; equal to 18? beq B_EFBA ; then skip inc NDBL,X ; increment number of free blocks in ; disk bne A_EF85 inc NDBH,X ; increment number of blocks hi A_EF85 rts ; jmp J_F7D9 ; $EF85 , $F7D9 ; Jiffydos <== ;** Set flag for BAM changed P_EF88 ldx #0 ; drive number lda #$01 sta MDIRTY ; flag = 1 rts ;** Mark block as allocated AllocSector ; [EF90] jsr P_EFF1 ; set buffer pointer AllocSector2 ; [EF93] jsr GetBitBAM ; erase bit for sector in BAM beq B_EFCE ; already allocated, then done lda (BMPNT),Y eor PowersOf2,X ; erase bit for block sta (BMPNT),Y jsr P_EF88 ; set flag for BAM changed ldy TEMP0 lda (BMPNT),Y sec sbc #$01 ; decrement number of blocks per track sta (BMPNT),Y lda TRACK ; track cmp DirTrack ; 18? beq B_EFBD lda NDBL,X ; number of free blocks lo bne B_EFBA dec NDBH,X ; decrement number of free blocks B_EFBA dec NDBL,X B_EFBD lda NDBH,X ; number of free blocks hi bne B_EFCE ; more than 255 blocks free? lda NDBL,X ; free blocks lo cmp #$03 bcs B_EFCE ; smaller than 3? lda #$72 jsr Errmsg2buf ; 72, 'disk full' [E6C7] B_EFCE rts ;** Get state of bit for sector in BAM entry GetBitBAM ; [EFCF] jsr P_F011 ; find BAM field for this track tya sta TEMP0 P_EFD5 lda SECTOR ; sector lsr A lsr A ; divide by 8 lsr A sec adc TEMP0 tay ; byte number in BAM entry lda SECTOR ; sector number and #$07 tax ; bit number in BAM entry lda (BMPNT),Y ; byte in BAM and PowersOf2,X ; get state rts ;** Powers of 2 PowersOf2 ; [EFE9] .by $01, $02, $04, $08, $10, $20, $40, $80 ;** Write BAM after change P_EFF1 lda #$FF bit WBAM beq B_F004 bpl B_F004 bvs B_F004 lda #$00 sta WBAM ; reset flag jmp DskWriteBlock ; write block [D58A] B_F004 rts ;** Erase BAM buffer EraseBamBuf ; [F005] jsr SetBufPtrBAM ; pointer $6D/$6E to BAM buffer [EF3A] ldy #$00 tya B_F00B sta (BMPNT),Y ; erase BAM buffer iny bne B_F00B rts P_F011 lda TEMP0 pha lda TEMP1 pha jsr GetBufNumBAM2 ; drive 0: A=13, drive 1: A=6 [F10F] sta TEMP0 ; channel lda #0 ; drive number sta TEMP1 tax lda TRACK ; track cmp TBAM beq B_F03E inx ; altenative channel stx TEMP1 cmp TBAM,X beq B_F03E jsr P_F05B B_F03E lda TEMP1 ldx #0 ; drive number sta UBAM asl A asl A ; times 4 clc adc #<(BAMima) sta BMPNT lda #>(BAMima) adc #$00 sta BMPNT+1 ldy #$00 pla sta TEMP1 pla sta TEMP0 rts P_F05B ldx TEMP0 ; channel = 13 jsr ReadBAM ; [F0DF] ldx #0 ; drive number lda UBAM eor #$01 and #$03 sta TEMP1 jsr VerifyBamEntry ; [F0A5] lda JOBNUM ; buffer number asl A tax lda TRACK ; track asl A asl A ; times 4 sta BUFTABzp,X ; equal pointer in BAM field lda TEMP1 asl A asl A tay B_F07F lda (BUFTABzp,X) sta BAMima,Y lda #$00 sta (BUFTABzp,X) ; zero in buffer inc BUFTABzp,X ; increment buffer pointer iny tya and #$03 bne B_F07F ldx TEMP1 lda TRACK ; track sta TBAM,X lda WBAM bne B_F09F jmp DskWriteBlock ; write block [D58A] B_F09F ora #$80 sta WBAM rts ;** Verify the BAM entry VerifyBamEntry ; [F0A5] tay lda TBAM,Y ; BAM in memory? beq B_F0D0 ; no, -> pha ; save track lda #$00 ; ???? sta TBAM,Y lda JOBNUM ; buffer number asl A ; times 2 tax pla ; restore track asl A asl A ; * 4 sta BUFTABzp,X tya ; drive asl A asl A ; * 4 (why ???) tay B_F0BE lda BAMima,Y sta (BUFTABzp,X) ; write in buffer lda #$00 sta BAMima,Y inc BUFTABzp,X ; increment buffer pointer iny tya and #$03 bne B_F0BE B_F0D0 rts ;** Clear the variable TBAM (+1) ClearTBAM ; [F0D1] ldx #0 ; drive number * 2 lda #$00 sta TBAM inx sta TBAM rts ;** Read BAM into page 7 if not loaded yet ReadBAM ; [F0DF] lda BUF0CH1zp,X cmp #$FF ; BAM loaded? bne B_F10A ; yes, -> txa pha jsr GetBuffer ; [D28E] tax bpl B_F0F2 jmp Error70 ; 70, 'no channel' B_F0F2 stx JOBNUM pla tay txa ora #$80 sta BUF0CH1ab,Y asl A tax lda DirTrack ; 18, directory track sta TRASECzp,X ; save lda #$00 ; 0 sta TRASECzp+1,X ; as sector jmp DskReadBlock ; read block [D586] B_F10A and #$0F sta JOBNUM ; buffer number rts ;** Get buffer number for BAM GetBufNumBAM2 ; [F10F] lda #13 ; Drive 0 -> 13 ldx #0 ; drive number B_F118 rts ;** Get buffer number for BAM GetBufNumBAM ; [F119] jsr GetBufNumBAM2 ; get buffer number tax rts ;** Find and allocate free block P_F11E jsr GetSector2 ; get track and sector number [DE3E] lda #$03 sta TEMP0 ; counter lda #$01 ora WBAM sta WBAM ; ==> Jiffydos P_F12D jsr P_F011 ; find BAM field for TRACK lda (BMPNT),Y ; number of free blocks in track bne A_F173 ; still free sectors, -> lda SECTOR sta SECTOR ; ??? ; &&&21 ldx #$12 ; ldx DirTrackM ; <--- cpx TRACK ; track 18 beq A_F15A ; yes, -> disk full bcs A_F151 inc TRACK lda TRACK cmp #$24 bne P_F12D dex A_F149 stx TRACK dec TEMP0 bne P_F12D beq A_F15A ; always -> A_F151 dec TRACK bne P_F12D inx bne A_F149 ; disk full Error72 A_F15A lda #$72 jmp OutputErrorMsg ; $C1C8 [C1C8] A_F173 lda #1 clc adc SECTOR sta SECTOR lda TRACK jsr MaxSectors ; [F24B] sta BSTSEC sta CMD cmp SECTOR bcs B_F195 sec lda SECTOR sbc BSTSEC sta SECTOR nop ; Jiffydos <== B_F195 jsr P_F1FA ; check BAM, find free sector beq B_F19D ; not found? B_F19A jmp AllocSector ; allocate block in BAM [EF90] B_F19D lda #$00 sta SECTOR ; sector zero jsr P_F1FA ; find free sector bne B_F19A ; found? jmp J_F1F5 ; no, 'dir sector' ;** Find free sector and allocate ; #### start from track 1 upwards FreeSecAlloc ; [F1A9] lda #$01 ora WBAM sta WBAM ; don't write to the BAM lda R0 pha lda #$01 ; track counter sta R0 B_F1B8 lda DirTrack ; 18, directory track sec sbc R0 ; minus counter sta TRACK ; save as track number bcc B_F1CB ; result <= zero? beq B_F1CB ; then try top half of directory jsr P_F011 ; find BAM field for this track lda (BMPNT),Y ; number of free blocks in this track bne B_F1E6 ; free blocks exist B_F1CB lda DirTrack ; 18, directory track clc adc R0 ; plus counter sta TRACK ; save as track number inc R0 ; increment counter cmp A_FED7 ; 36, max track number plus one bcc B_F1DF ; smaller, then ok lda #$67 jsr CreErrorMsg ; 67, 'illegal track or sector' [E645] B_F1DF jsr P_F011 ; find BAM field for this track lda (BMPNT),Y ; number of free blocks? beq B_F1B8 ; no more free blocks? B_F1E6 pla sta R0 lda #$00 sta SECTOR ; sector 0 jsr P_F1FA ; find free sector beq J_F1F5 ; not found? jmp AllocSector ; allocate block in BAM [EF90] J_F1F5 lda #$71 jsr CreErrorMsg ; 71, 'dir error' [E645] ;** Find free sectors in current track P_F1FA jsr P_F011 ; find BAM field for this track tya ; point to number of free blocks pha jsr P_F220 ; verify BAM lda TRACK ; track jsr MaxSectors ; get max number of sectors of the track ; [F24B] sta BSTSEC ; save pla sta TEMP0 ; save pointer B_F20D lda SECTOR ; compare sector cmp BSTSEC ; with maximum number bcs B_F21D ; greater than or equal to? jsr P_EFD5 ; get bit number of sector bne B_F21F ; sector free? inc SECTOR ; increment sector number bne B_F20D ; and check if free B_F21D lda #$00 ; no sectors free B_F21F rts ;** Verify number of free blocks in BAM P_F220 lda TEMP0 pha lda #$00 sta TEMP0 ; counter to zero ldy #4 ; 4, number of bytes per track in BAM dey B_F22B ldx #$07 B_F22D lda (BMPNT),Y and PowersOf2,X ; isolate bit beq B_F236 inc TEMP0 ; increment counter of free sectors B_F236 dex bpl B_F22D dey bne B_F22B lda (BMPNT),Y ; compare with number on diskette cmp TEMP0 bne B_F246 ; not equal, then error pla sta TEMP0 rts B_F246 lda #$71 jsr CreErrorMsg ; 71, 'dir error' [E645] ; Although it is a JSR, the routine resets the stack pointer and ends up ; in WaitLoop1. ;** Establish number of sectors per track MaxSectors ; [F24B] ldx A_FED6 ; 4 different values B_F24E cmp A_FED6,X ; track number dex bcs B_F24E ; not greater? lda A_FED1,X ; get number of sectors rts ;#### WHY ???? P_F258 rts ;** Initialize disk controller InitDiskCntrlr ; [F259] lda #$6F ; bit 4 (write protect) and 7 (SYNC) sta DDRB2 ; as input and #$F0 sta PortB2 ; port B, control port lda PCR2 ; PCR, control register and #$FE ora #$0E ora #$E0 sta PCR2 lda #$41 ; neg. edge latch, CA2 (H), sta ACR2 ; CB1 input, CB2 = R/W control lda #$00 ; 20 msec between IRQs sta T1LL2 ; timer 1 lo latch lda #$3A sta T1LH2 ; timer 1 hi latch sta T1CH2 ; timer 1 hi lda #$7F sta IER2 ; clear IRQs lda #$C0 ; only timer 1 sta IFR2 sta IER2 ; enable IRQs lda #$FF sta CURDRV sta FTNUM ; track counter for formatting ;** IRQ routine for disk controller IRQdiskCntrllr ; [F2B0] tsx stx SAVSP ; save stackpointer lda T1CL2 ; erase flag of timer lda PCR2 and #$FD sta PCR2 ; disable "Byte Ready" / SO J_F2BE ldy #$05 B_F2C0 lda JOBSab,Y ; command for buffer Y bpl B_F2F3 ; no, -> cmp #$D0 ; execute PRG in buffer? bne B_F2CD ; no, -> tya jmp ExecBufPRG_2 ; execute program in buffer [F370] B_F2CD lda #0 ; isolate drive number tax cmp CURDRV ; motor running? beq B_F2E9 ; yes, -> ;** Turn drive motor on ; !&&&18 Turn motor on? MotorOn ; [F97E] lda #$A0 sta DRVST lda #0 sta CURDRV ; set flag jmp LoopDiskCntrl ; to job loop [F99C] B_F2E9 lda DRVST ; ?? where initialised ?? bmi B_F2F0 asl A ; head transport programmed? bpl B_F2F9 ; yes, -> B_F2F0 jmp LoopDiskCntrl ; to job loop [F99C] B_F2F3 dey bpl B_F2C0 ; check next buffer jmp LoopDiskCntrl ; to job loop [F99C] ;** Head transport B_F2F9 lda #$20 sta DRVST ; program motor on ldy #$05 sty JOBN B_F301 jsr InitPntr2Buf ; set pointer in buffer [F393] bmi B_F320 ; command for buffer? J_F306 dec JOBN ; decrement counter bpl B_F301 ; check next buffer ldy NXTJOB ; buffer number jsr InitPntr2Buf2 ; set pointer in buffer [F395] lda #$60 ; set flag for head transport sta DRVST lda (HDRPNT),Y ; get track number from buffer sta DRVTRK jmp LoopDiskCntrl ; to job loop [F99C] B_F320 lda DRVTRK ; last track number beq B_F33C ; equal zero? sec sbc (HDRPNT),Y ; equal track number of this job? beq B_F33C ; yes, -> lda JOBN sta NXTJOB ; ==> Jiffydos jmp J_F381 ; Jiffydos <== B_F33C ldx #$04 lda (HDRPNT),Y ; track number of the job sta TRACC ; save B_F342 cmp A_FED6,X ; compare with maximum track number dex bcs B_F342 ; greater? lda A_FED1,X ; get number of sectors per track sta SECCNT ; and save ;** Create value for density for PB5/PB6 txa asl A asl A asl A asl A asl A sta WORK ; gives 0, 32, 64, 96 lda PortB2 and #$9F ora WORK ; generate control byte for motor ; ==> Jiffydos jsr P_FAE4 ; $FAE4 ; Jiffydos <== ldx #0 ; drive number lda JOB ; command code cmp #$40 ; position head? beq B_F37C ; yes, -> cmp #$60 ; command code for program execution? beq ExecBufPRG ; yes, -> jmp ReadHeader ; read block header [F3B1] ;** Execute program in buffer ExecBufPRG ; [F36E] lda JOBN ExecBufPRG_2 ; [F370] clc adc #$03 ; plus 3 sta BUFPNT+1 lda #$00 ; equals address of buffer sta BUFPNT jmp (J_BUFPNT) ; execute program in buffer ;** Bump, find track 1 (head at stop) ; ==> Jiffydos B_F37C jsr P_FAD3 ; $F37C , $FAD3 bne A_F390 J_F381 lda #$13 sta T1LH2 jmp J_F306 ; $F306 ; Jiffydos <== A_F390 jmp P_F969 ; ok ;** Initialize pointer in buffer InitPntr2Buf ; [F393] ldy JOBN InitPntr2Buf2 ; [F395] lda JOBSab,Y ; command code pha ; save bpl B_F3AB and #$78 ; erase bits 0,1,2, and 7 sta JOB tya ; buffer number asl A ; times two adc #$06 ; plus 6 sta HDRPNT ; equals pointer to actual buffer tya ; buffer number clc adc #$03 ; plus 3 sta BUFPNT+1 ; equals buffer address hi B_F3AB ldy #$00 sty BUFPNT ; buffer address lo pla ; get command code back rts ;** Read block header ReadHeader ; [F3B1] jsr FindSector2 ; <-- &&04 L_F3E6 ldx CURDRV ; drive number lda HDRTRK ; track number of header sta DRVTRK,X ; use as actual track number lda JOB cmp #$30 ; code for 'preserve header'? beq J_F418 ; yes, -> ldy #0 ; drive number jmp JobOptimal ; [F423] J_F418 lda #$01 ; ok jmp P_F969 ; done ;** Job optimisation JobOptimal ; [F423] lda #$7F sta CSECT lda HDRSEC clc adc #$02 cmp SECCNT ; max. sectors/track bcc B_F432 sbc SECCNT B_F432 sta NEXTS ldx #$05 stx JOBN ldx #$FF B_F43A jsr InitPntr2Buf ; set buffer pointer for disk controller ; [F393] bpl B_F483 ; no job, -> sta WORK ; save job code and #$01 cmp CURDRV ; momentary drive? bne B_F483 ; no, -> ldy #$00 lda (HDRPNT),Y ; get track # cmp TRACC ; same as from momentary job? bne B_F483 ; no, -> lda JOB ; command code cmp #$60 ; execute program in buffer? beq B_F461 ; yes, -> ldy #$01 sec lda (HDRPNT),Y ; get sector # sbc NEXTS bpl B_F461 clc adc SECCNT B_F461 cmp CSECT bcs B_F483 B_F473 sta CSECT lda JOBN tax adc #$03 sta BUFPNT+1 bne B_F483 B_F47E pla cmp #$06 bcc B_F473 B_F483 dec JOBN bpl B_F43A txa bpl B_F48D jmp LoopDiskCntrl ; to job loop [F99C] B_F48D stx JOBN jsr InitPntr2Buf ; get buffer number [F393] lda JOB ; command code ;** Test command code further J_F4CA cmp #$00 ; command code for 'read'? beq J_F4D1 ; yes, -> jmp J_F56E ; continue checking command ;** Read sector ; !&&&06 IDE replacement for reading data from disk J_F4D1 jsr FindSector ; [F510] jsr LedOnn jsr SetTSparms lda #$20 ; read sector jsr SendCommand ldy #0 JobReadSec lda IDEdata sta (BUFPNT),Y iny bne JobReadSec x_F4E0 lda IDEstatus ; ready? bmi x_F4E0 ; if not, -> wait jsr LedOff ; <-- &&06 B_F505 lda #$01 ; ok jmp P_F969 ; prepare error message ;** Read block header FindSector ; [F510] ldx #0 ; drive number FindSector2 ldy #$00 lda (HDRPNT),Y ; get track and sta HDRTRK iny lda (HDRPNT),Y ; sector number from buffer sta HDRSEC ;** At this point the track and sector to be searched for are stored rts ;** Test command code further J_F56E cmp #$10 ; command code for 'write' beq J_F575 ; yes, -> jmp J_F691 ; continue checking command code ;** Write data block to disk ; !&&&08 IDE replacement for writing data to disk J_F575 jsr FindSector ; [F510] jsr SetTSparms lda #$30 ; write sector jsr SendCommand ldy #0 sty BUFPNT JobWrSector20 lda (BUFPNT),Y sta IDEdata iny bne JobWrSector20 x_F5D0 lda IDEstatus ; ready? bmi x_F5D0 ; if not, -> wait ; <-- &&08 l_F5DC ldy JOBN ; &&&09 lda JOBSab,Y eor #$30 ; convert command code 'write' to ; 'verify' sta JOBSab,Y jmp ReadHeader ; [F3B1] ; ==> Jiffydos P_F674 lda DATA lsr A cmp LSNADR beq A_F67F cmp TLKADR bne A_F68C A_F67F inc CONT ldx #$0F P_F683 jsr DataOut_H ; [E9A5] A_F686 dex bne A_F686 jsr DataOut_L ; [E99C] A_F68C ldx #$00 rts ; Jiffydos <== ;** Test command code further J_F691 cmp #$20 ; command code for 'verify'? beq J_F698 ; yes, -> jmp J_F6CA ; continue checking command code ;** Compare written data with data on disk ; !&&&10 IDE replacement for verifying data on the disk J_F698 jsr FindSector ; [F510] jsr LedOnn jsr SetTSparms lda #$20 ; read sector jsr SendCommand ldx #0 ; no errors found yet ldy #0 JobVerify20 lda IDEdata eor (BUFPNT),Y ; compare beq JobVerify40 ; OK, -> JobVerify30 inx ; error found beq JobVerify30 ; make sure it stays <> 0 JobVerify40 iny ; 256 bytes? bne JobVerify20 ; no, -> jsr LedOff ldy #$FD txa ; Error? bne B_F6C5 ; yes, -> error jmp J_F418 ; OK ; <-- &&10 B_F6C5 Error25 lda #$07 jmp P_F969 ; 25, 'write error' ;** Command code for find sector J_F6CA jsr FindSector ; read block header [F510] jmp J_F418 ; done ; ==> JiffyDOS P_F769 lda ORGSA cmp #$6F bcs A_F774 jsr CheckREL ; $D125 [D125] bcc A_F778 A_F774 cli jmp P_CFB7 ; $CFB7 A_F778 lda DATA jmp J_FE3A ; $FE3A /* J_F7D9 pla cmp #$AF bne A_F7E4 jsr P_FB64 cli lda #$93 A_F7E4 pha rts */ ; <== JiffyDOS ;** ======================================================================== ;** turn LED off LedOff lda #$F7 and PortB2 sta PortB2 rts ;** turn LED on (without SEI and CLI) LedOnn lda #8 ora PortB2 sta PortB2 rts ;** Send command to IDE ;- in: A contains command ;- out: A contains error code SendCommand sta IDEcommand SendCommand10 lda IDEstatus ; ready? bmi SendCommand10 ; if not, -> wait and #1 ; error? rts ;** Set track and sector SetTSparms lda HDRTRK ; track # SetTSparms2 asl ; * 2 tax clc lda HDRSEC SetTSparms3 adc TrackTable-2,X ; relative number sta IDElba0 lda TrackTable-1,X adc LBAimage sta IDElba1 lda #0 adc LBAimage+1 sta IDElba2 lda #$E0 adc LBAimage+2 sta IDElba3 lda #1 sta IDEnumsec rts ; ==> Jiffydos P_F910 tsx lda A_0104,X ldx JOBN ldy #$01 sec sbc #$FB bne A_F900 sty JOBSzp,X ldx SAVSP txs jmp J_FABE ; $FABE A_F900 rts ; Jiffydos <== ;** Error entry disk controller P_F969 ldy JOBN sta JOBSab,Y B_F975 lda DRVST ora #$10 ; turn drive motor off sta DRVST ldx SAVSP ; get stack pointer back txs jmp J_F2BE ;** Job loop disk controller LoopDiskCntrl ; [F99C] lda T1LH2 sta T1CH2 B_F9B1 ldx #0 ; drive number active? lda DRVST tay cmp #$20 ; drivemotor on? bne B_F9D9 ; no, -> B_F9D6 jmp J_FABE B_F9D9 tya ; A = DRVST bpl B_F9E4 ; drive already marked ready, -> and #$7F ; mark ready sta DRVST B_F9E4 and #$10 ; shut down drive motor ? beq B_F9FA ; no, -> lda #$FF sta CURDRV lda #$00 sta DRVST beq B_F9D6 ; always -> B_F9FA tya and #$40 ; activate steppermotor? bne B_FA02 ; yes, -> jmp J_FABE B_FA02 ; jmp (NXTSTab) ; StepHead [FA05] ;** Step the head ; !&&&11 Stepping the head. ; For regular operations nothing has to be done. But a problem occurs ; when someone steps the head and starts reading the passing sectors ; not using the normal procedure. We'll see..... StepHead ; [FA05] ; <-- &&11 L_FA52 lda DRVST and #$BF ; erase bit 6 sta DRVST jmp J_FABE J_FABE lda PCR2 and #$FD ; erase bit 1 sta PCR2 ; disable "Byte ready" rts ;** Formatting E_FAC7 lda FTNUM ; track number ; ==> Jiffydos bpl A_FAF0 jsr P_FAD3 ; $FAD3 sta FTNUM sta DRVTRK jmp LoopDiskCntrl ; $F99C [F99C] P_FAD3 lda #$60 sta DRVST lda #$01 sta DRVTRK lda PortB2 and #$FC P_FAE4 sta PortB2 lda #$3A sta T1LH2 lda #$01 A_FAEE rts A_FAF0 ldy #$00 sta (HDRPNT),Y cmp (HDRPNT),Y beq A_FAFB sta (HDRPNT),Y jmp LoopDiskCntrl ; $F99C [F99C] A_FAFB lda #2 sta ErrorCount ; !&&&12 Format one track by filling all sectors with $00 ; As there is no need to lowformat a track on the IDE disk, all according ; routines are skipped. ;- in: FTNUM = track ;- out: X = 0 A_FB0C ldx FTNUM ; track # x_FB0C stx HDRTRK stx POSTcode lda TrackSector-1,X tay ; Y := last sector ; Fill sector with zeros FormatTrack01 sty HDRSEC FT015 jsr SetTSparms lda #$30 ; write sector jsr SendCommand lda #0 tax FormatTrack02 sta IDEdata inx bne FormatTrack02 FT03 lda IDEstatus ; ready? bmi FT03 ; if not, -> wait and #1 ; error? bne FT015 ; yes, -> dey ; last sector? bpl FormatTrack01 ; no, -> ldx FTNUM cpx #$23 ; last track? bcs x_FB0E ; no, -> inx stx FTNUM bne x_FB0C x_FB0E jmp L_FD8B ; <-- &&12 A_FB0F ldx CONT bmi A_FB5C ldy CURCHN lda (BUFTABzp,X) sta OUTREG,Y lda OUTREG+6,Y beq A_FB2C sec sbc BUFTABzp,X bne A_FB2C sta BUFTABzp,X jsr P_D162 ; $D162 jmp J_FB3B ; $FB3B A_FB2C inc BUFTABzp,X bne J_FB3B jsr P_E974 ; $E974 J_FB33 jsr ChkBufFree ; $FB33 , $D2DA [D2DA] jsr GetBufChanNum ; $D12F [D12F] stx CONT J_FB3B ldx CURCHN lda PortB1 and #$6D sta WORK and #$61 sta TLKACT lda REWRFLzp,X bmi x_FBCC rts x_FBCC and #$08 jsr P_FF79 ; $FF79 and #$02 beq A_FB0F lda TLKACT ora #$0D jsr P_FFDB ; $FFDB A_FB5C cli jsr NxtByteFile ; [D3AA] sei jmp J_FB3B ; $FB3B P_FB64 sei jsr Par2DiskCtrl ; $D6D0 [D6D0] tya lsr A tax lda #$80 jsr P_D50E ; $D50E .by $2C ; dummy BIT opcode P_FB71 lda #$90 P_FB73 pha txa asl A tay lda TRASECab,Y cmp DRVTRK beq A_FB83 lda #$B0 jsr P_FBA4 ; $FBA4 A_FB83 pla pha sta JOBSzp,X stx JOBN lda PCR2 ora #$0E sta PCR2 jsr InitPntr2Buf ; $F393 [F393] txa pha lda JOBSzp,X jsr P_FBAD ; $FBAD pla tax lda JOBSzp,X cmp #$02 pla bcc A_FBAC P_FBA4 jsr P_D50E ; $FBA4 , $D50E cli jsr VerifyExec ; $D599 [D599] sei A_FBAC rts P_FBAD tsx stx SAVSP and #$30 bne A_FBB7 jmp J_F4D1 ; read sector A_FBB7 and #$20 bne A_FBBE jmp J_F575 ; write sector A_FBBE jmp J_F698 ; verify sector P_FBC1 lda CONT bne A_FBC8 A_FBC5 jmp GetByteFromBus ; [E9C9] A_FBC8 lda PortB1 and #$04 sta PortB1 A_FBD0 bit PortB1 bne A_FBD0 pha pla lda PortB1 asl A pha pla ora PortB1 and #$0F tax ldy TLKACT lda PortB1 asl A pha pla ora PortB1 and #$0F ora A_FC08,X sta DATA lda PortB1 ora #$02 sta PortB1 bmi A_FBC5 and #$04 bne A_FC05 sty EOIFLG A_FC05 lda DATA rts A_FC08 .by $00, $80, $20, $A0, $40, $C0, $60 ; .. .@.` .by $E0, $10, $90, $30, $B0, $50, $D0 ; ...0.P. .by $70, $F0 ; p. ; <== JiffyDOS L_FD8B inc FTNUM ; increment track number lda FTNUM cmp #$24 ; compare with 36, highest track ; number + 1 bcs B_FD96 ; greater, then formatting done jmp LoopDiskCntrl ; continue [F99C] B_FD96 lda #$FF sta FTNUM ; track number to $FF lda #$01 jmp P_F969 ; ok ;** Attempt counter for formatting J_FDD3 dec ErrorCount ; decrement number of attempts beq J_FDDB ; zero, then error jmp LoopDiskCntrl ; continue [F99C] J_FDDB ldy #$FF sty FTNUM ; flag for end of formatting iny ; #### still needed ??? jmp P_F969 ; error termination ; ==> Jiffydos J_FE3A jsr Write2Buf ; [CFF1] bne A_FE66 jsr ChkBufferOK ; [DFB7] bne A_FE49 cli jsr Look4FreeBuf ; [CF7B] sei A_FE49 and #$07 tax lda JOBSzp,X bpl A_FE53 jsr P_FB73 ; $FB73 A_FE53 cli jsr P_F11E ; $F11E sei jsr P_D1A9 ; $D1A9 ldx JOBNUM jsr P_FB71 ; $FB71 ldx JOBNUM lda #$A0 sta JOBSzp,X A_FE66 rts ; Jiffydos <== ;** Interrupt routine IRQ ; [FE67] pha txa pha ; save registers tya pha lda IFR1 ; interrupt from serial bus? and #$02 beq B_FE76 ; no, -> jsr P_E853 ; serve serial bus B_FE76 lda IFR2 ; interrupt from timer 1? asl A bpl B_FE7F ; no, -> jsr IRQdiskCntrllr ; IRQ routine for disk controller ; [F2B0] B_FE7F pla tay pla ; get registers back tax pla rti ;** Constands for disk format ; &&&20 &&&21 DirTrack ; [FE85] .by $12 ;** directory track ; <--- .by $04 ;** start of bam .by $04 ;** length of bam per track LengthBAM ; [FE88] .by $90 ;** end of bam ;** File control methods A_FEB2 .tx "RWAM" ;** File types A_FEB6 .tx "DSPUL" ;** Names of file types TblFiletype ; [FEBB] .tx "DSPURDBTE " ;** 1st char .tx "EERSEIIXX " ;** 2nd char .tx "LQGRLRNTE " ;** 3rd char ;** Masks for bit command A_FECD .by $3F,$7F,$BF,$FF ;** Number of sectors per track A_FED1 .by $11,$12,$13,$15 ;** Constands for disk format A_FED5 .by $41 ;** A marker for 1541 format A_FED6 .by $04 ;** 4 track ranges A_FED7 .by $24 ;** number of tracks .by $1F,$19,$12 ;** tracks on which sector numbers ; change ;** High byte addresses of buffers BufferAddress ; [FEE0] .by $03,$04,$05,$06,$07,$07 L_FEE7 jmp (J_VNMI) ;** Patch for diagnostic routine, from $EA7A PATCH3 ; [FEEA] sta PortB2 ; turn LED on sta DDRB2 ; port to output jmp J_EA7D ; back to diagnostic routine ;** Delay loop for serial bus in 1541 mode from $E97D DelayC64 ; [FEF3] txa ldx #$05 DelayX dex ; about 40 microseconds bne DelayX tax rts ;** Patch for data output to serial bus from $E980 P_FEFB jsr ClkOut_H ; CLOCK OUT hi [E9AE] jmp DataOut_L ; DATA OUT lo [E99C] ;** U9 vector, switch 1540/1541 NMI lda CMDBUF+2 cmp #'-' beq B_FF0D ; if parameter is '+', then at B_FF0D result is 0 sec sbc #'+' bne L_FEE7 ; indirect jump over ($0065) B_FF0D sta VIC20mode rts ;** Patch for reset routine, from $EAA4 PATCH1 ; [FF10] stx DDRA1 lda #$02 sta PortB1 lda #$1A sta DDRB1 jmp L_EAA7 ;** Patch for listen to serial bus from $E9DC PATCH2 ; [FF20] lda PortB1 and #$01 bne PATCH2 lda #$01 sta T1CH1 ; ==> Jiffydos rts J_FF2D lda BUFPNT+1 pha jsr P_E96D ; $E96D lda #$04 A_FF35 pha ldy #$01 lda (BUFPNT),Y sta SECTOR tax dey lda (BUFPNT),Y sta TRACK bne A_FF50 pla clc sbc SECTOR inx stx BUFPNT beq A_FF4F dec BUFPNT+1 A_FF4F pha A_FF50 pla tay jsr P_FF8D ; $FF8D lda TRACK beq A_FF60 jsr P_FB64 ; $FB64 lda #$02 bne A_FF35 A_FF60 sta BUFPNT pla sta BUFPNT+1 jsr P_FF6E ; $FF6E jsr P_FF6E ; $FF6E jsr ClkOut_H ; [E9AE] P_FF6E ldx #$14 A_FF70 dex bne A_FF70 jmp ClkOut_L ; $E9B7 [E9B7] A_FF76 jmp SerialBus ; $FF76 , $E85B [E85B] P_FF79 bne A_FF81 lda TLKACT ora #$03 sta WORK A_FF81 lda OUTREG,X ldx TLKACT ldy #$FF stx PortB1 bne A_FFA5 P_FF8D lda PortB1 and #$60 sta TLKACT ora #$0D sta WORK jsr DataOut_H ; [E9A5] eor #$0D sta PortB1 jsr DelayC64 ; $FEF3 [FEF3] A_FFA3 lda (BUFPNT),Y A_FFA5 tax lsr A lsr A lsr A lsr A sta TMP txa and #$0F tax lda A_EA1D,X ldx TLKACT stx PortB1 A_FFB8 cpx PortB1 beq A_FFB8 sta PortB1 asl A and #$0F nop sta PortB1 ldx TMP lda A_EA1D,X sta PortB1 asl A and #$0F iny sta PortB1 bne A_FFA3 nop lda WORK P_FFDB sta PortB1 A_FFDE cmp PortB1 bcc A_FF76 bne A_FFDE rts ; Jiffydos <== ;** Change image ; Multiply number in IDEtmp0..2 with register Y ImaAdd lda #0 sta IDEtmp3 sta IDEtmp4 sta IDEtmp5 ImaAdd02 clc lda IDEtmp3 adc IDEtmp0 sta IDEtmp3 lda IDEtmp4 adc IDEtmp1 sta IDEtmp4 lda IDEtmp5 adc IDEtmp2 sta IDEtmp5 dey bne ImaAdd02 lda IDEtmp3 sta IDEtmp0 lda IDEtmp4 sta IDEtmp1 lda IDEtmp5 sta IDEtmp2 rts ; change the "floppy" ChangeImage jsr GetDrvNum ; get drive number [C312] lda DRVNUM ; drive number OK? bpl SubIma010 ; yes, -> jmp Error33 ; 33, 'syntax error' SubIma010 jsr LedOn ; turn LED on sec lda CMDSIZ sbc FILTBL cmp #1 ; check size of number > 0 bcs SubIma020 ; yes, -> jmp Error34 SubIma020 ; #### needed? ldx FILTBL lda #16 ; max. 16 characters jsr Get_Length_Name ; [C6A6] lda #0 sta IDEtmp0 sta IDEtmp1 sta IDEtmp2 ldx FILTBL SubIma030 lda CMDBUF,X and #15 clc adc IDEtmp0 sta IDEtmp0 bcc SubIma025 inc IDEtmp1 bne SubIma025 inc IDEtmp2 bne SubIma025 SubIma025 inx cpx LIMIT ; last number? bcs SubIma050 ; yes, -> ldy #10 jsr ImaAdd ; multiply with 10 jmp SubIma030 ; copy given number to ImageLBA SubIma050 lda IDEtmp2 cmp CSubima+2 bcc SubIma52 ; < is OK, -> bne SubIma60 ; > is error, -> lda IDEtmp1 cmp CSubima+1 bcc SubIma52 ; < is OK, -> bne SubIma60 ; > is error, -> lda IDEtmp0 cmp CSubima bcs SubIma60 ; >= is error, -> SubIma52 lda IDEtmp0 sta ImageLBA lda IDEtmp1 sta ImageLBA+1 lda IDEtmp2 sta ImageLBA+2 ; multiply with 3 and store in LBAimage ldy #3 jsr ImaAdd clc lda IDEtmp0 adc InitLBAima+1 ; add offset for image directory sta LBAimage lda IDEtmp1 adc #0 sta LBAimage+1 lda IDEtmp2 adc #0 sta LBAimage+2 lda #1 sta WPSW0 jmp InitDrive SubIma60 jmp Error66 CSubIma .by $F0, $2F, 0 ; ((3 * 256) - 1) * 16 ;** Format all BAM sectors and image directory FormatCDisk ; start with image directory ldy #0 sty Idetmp1 iny sty Idetmp0 FoIma1 lda IDEtmp0 sta IDElba0 lda IDEtmp1 sta IDElba1 lda #0 sta IDElba2 lda #$E0 sta IDElba3 lda #1 sta IDEnumsec lda #$30 ; write sector jsr SendCommand ldx #0 txa FoIma2 sta IDEdata inx bne FoIma2 FoIma3 lda IDEstatus ; ready? bmi FoIma3 ; next sector inc IDEtmp0 bne FoIma1 inc IDEtmp1 lda IDEtmp1 cmp InitLBAima+1 bcc FoIma1 ; Clear all BAM tables, start with first possible image lda InitLBAima+1 sta LBAimage ; point to first image ldy #0 sty LBAimage+1 sty LBAimage+2 sty HDRSEC ; BAM sector 0 lda #18 sta HDRTRK ; BAM track 18 jsr LedOnn ; look for BAM of current image FoIma10 jsr SetTSparms lda #$70 ; seek sector jsr SendCommand bne FoIma40 lda #$30 ; write sector jsr SendCommand ldy #0 tya FoIma20 sta IDEdata iny bne FoIma20 FoIma22 lda IDEstatus ; ready? bmi FoIma22 ; if not, -> wait and #1 ; error ? sector not found) bne FoIma40 ; yes, -> clc lda LBAimage adc #3 sta LBAimage bcc FoIma10 inc LBAimage+1 bne FoIma10 inc LBAimage+2 bne FoIma10 ; always -> FoIma40 lda #1 sta WPSW0 jmp InitDrive ;** Show available images stored in first x * 768 sectors TxtAvImages .by $12 .tx '"AVAILABLE IMAGES" X-IDE' ShowImages jsr Verify_Drv_Num ; initialize drive if necessary [C3CA] ; Store text AVAILABLE IMAGES in buffer jsr ClrNameBuf ; [C7AC] ldy #24 ShIma10 lda TxtAvImages,Y sta NameBuffer,Y dey bpl ShIma10 jsr SrchDirEntry ; load directory [C49D] lda DIRBUF+1 jsr t_EC9E ; create and prepare directory jmp x_DAAA ; rest of original routine ;** Load dir t_EC9E lda #$00 sta SA ; secondary address 0 ; start with first sector - 1 sta IDEtmp0 ; 1st LBA byte for harddisk sector sta IDEtmp1 ; 2nd LBA byte for harddisk sector lda #240 ; 0 - 16 sta IDEtmp2 ; pointer inside sector lda #$01 jsr FindRdChanBuf ; find channel and buffer [D1E2] lda #$00 jsr SetBufPointer3 ; initialize buffer pointer [D4C8] ldx CURCHN ; channel number lda #$00 sta ENDPNT,X ; pointer to end = zero jsr GetBufNumber ; get buffer number [DF93] tax lda #0 ; drive number sta LSTJOB,X ; bring in table ; write start address $0401 in buffer lda #$01 jsr Write2Buf ; [CFF1] lda #$04 jsr Write2Buf ; [CFF1] lda #$01 ; 2 times 1 jsr Write2Buf ; [CFF1] jsr Write2Buf ; write in buffer as link address ; [CFF1] lda #0 jsr Write2Buf ; write in buffer [CFF1] jsr Write2Buf ; as line number [CFF1] jsr DirLine2Buf ; directory entry in buffer [ED59] jsr GetBufNumber ; get buffer number [DF93] asl A tax dec BUFTABzp,X ; decrement buffer pointer dec BUFTABzp,X lda #$00 jsr Write2Buf ; 0 as line end in buffer [CFF1] ; image counter sta IDEtmp4 sta IDEtmp5 ; start with image 0 lda #$FF sta NBTEMP0 sta NBTEMP1 t_ECEA lda #$01 jsr Write2Buf ; 2 times 1 as link address [CFF1] jsr Write2Buf ; [CFF1] ; jsr GetDirEntry ; directory entry in buffer [C6CE] lda SA pha lda CURCHN pha ; jsr GetDirEntry2 ; [C6DE] lda #$11 sta SA jsr OpenChan4Read ; [D0EB] jsr SetBufPointer ; [D4E8] jsr RdImageSec lda ENTFND ; found entry? bpl t_C71B ; yes, -> ; display END OD LIST text jsr ClrNameBuf ; [C7AC] ldy #23 ShIma90 lda TxtEndOfList,Y sta NameBuffer,Y dey bpl ShIma90 clc jmp z_C7AA TxtEndOfList .tx ' ' .by $12 .tx '"IMAGES FOUND "' .by 0 t_C71B ldx #$19 ; length of entry ldy #$1D ; position HB number of blocks ; check for 10.000 lda NBTEMP1 cmp #$27 bcc t_C720 ; < 10.000, -> beq t_C71E ; > 10.000 t_C71D ldx #$15 bne t_C73C ; always -> t_C71E lda NBTEMP0 cmp #$10 ; >= $2710 = 10.000 ? bcs t_C71D ; yes, -> ; no, < 10.000 lda NBTEMP1 t_C720 cmp #3 bcc t_C726 ; < 1000, -> beq t_C724 ; > 1000 t_C722 ldx #$16 bne t_C73C ; always -> t_C724 lda NBTEMP0 cmp #$E8 ; >= $03E8 = 1000 ? bcs t_C722 ; yes, -> ; no, < 1000 t_C726 lda NBTEMP1 beq t_C728 ldx #$17 t_C728 dey lda NBTEMP0 cpx #$17 beq t_C73C cmp #$0A ; number of blocks? bcc t_C73C ; <10 , -> dex cmp #$64 ; <100 , -> bcc t_C73C dex t_C73C jsr ClrNameBuf ; [C7AC] lda (DIRBUF),Y ; A = filetype and #$0F ; isolate bit 0..3 tay ; and use as index lda #'4' ; 3rd char of filetype sta NameBuffer,X dex lda #'6' ; 2nd char of filetype sta NameBuffer,X dex lda #'D' ; 1st char of filetype sta NameBuffer,X dex lda #' ' sta NameBuffer,X dex lda #'"' ; last quote sta NameBuffer,X dex lda IDEtmp2 sta DIRBUF ; Copy the file name ldy #15 t_C773 lda (DIRBUF),Y sta NameBuffer,X dex dey bpl t_C773 lda #'"' ; " before file name sta NameBuffer,X ; increment image counter inc IDEtmp4 bne z_C7A9 inc IDEtmp5 z_C7A9 sec z_C7AA pla sta CURCHN pla sta SA bcc t_ED23 ; another entry? no, -> lda NBTEMP0 ; block number lo jsr Write2Buf ; in buffer [CFF1] lda NBTEMP1 ; block number hi jsr Write2Buf ; in buffer [CFF1] jsr DirLine2Buf ; directory entry in buffer [ED59] lda #$00 ; zero as end marker in buffer jsr Write2Buf ; buffer full? [CFF1] beq t_ED0D ; yes, -> jmp t_ECEA ; no, -> t_ED0D jsr GetBufNumber ; get buffer number [DF93] asl A tax lda #$00 sta BUFTABzp,X ; buffer pointer to zero lda #$88 ; set READ flag ldy CURCHN ; channel number sta REWRFLab,Y ; flag for channel lda #$89 sta DIRLST lda DATA ; data byte rts t_ED23 lda IDEtmp4 jsr Write2Buf ; [CFF1] lda IDEtmp5 jsr Write2Buf ; [CFF1] jsr DirLine2Buf ; [ED59] jsr GetBufNumber ; get buffer number [DF93] asl A tax dec BUFTABzp,X dec BUFTABzp,X ; buffer pointer minus 2 lda #$00 jsr Write2Buf ; [CFF1] jsr Write2Buf ; [CFF1] jsr Write2Buf ; three zeroes as program end [CFF1] jsr GetBufNumber ; get buffer number [DF93] asl A ; times 2 tay lda BUFTABab,Y ; buffer pointer ldx CURCHN sta ENDPNT,X ; as end marker dec ENDPNT,X jmp t_ED0D ;** Read sector with image info RdImageSec inc NBTEMP0 ; image counter bne RdImS16 inc NBTEMP1 RdImS16 clc lda IDEtmp2 adc #16 sta IDEtmp2 ; sector done? bne RdImS18 ; no, -> RdImS17 inc IDEtmp0 bne RdImS18 ; next sector -> inc IDEtmp1 lda IDEtmp1 cmp InitLBAima+1 ; end of image directory? bcc RdImS18 ; no, -> next sector RdImS19 lda #$F0 sta ENTFND ; no entry found yet rts RdImS18 lda #0 sta IDElba2 sta DIRBUF lda IDEtmp0 sta IDElba0 lda IDEtmp1 sta IDElba1 lda #$E0 sta IDElba3 sta ENTFND ; no entry found yet lda #1 sta IDEnumsec lda #$20 ; read sector jsr SendCommand ldy #0 RdImS1 lda IDEdata sta (DIRBUF),Y iny bne RdImS1 RdImS2 lda IDEstatus ; ready? bmi RdImS2 ; if not, -> wait ; Check every entry RdImS10 lda #0 sta DIRBUF RdImS12 ldy IDEtmp2 lda (DIRBUF),Y ; valid entry? bne RdImS20 ; yes, -> inc NBTEMP0 ; image counter bne RdImS13 inc NBTEMP1 RdImS13 clc tya adc #16 sta IDEtmp2 ; sector done? bne RdImS12 ; no, -> beq RdImS17 ; always -> next sector ; Entry found RdImS20 lda #0 sta ENTFND rts ;** Copy an image over another image ; Read number from command buffer CoIReadNumber lda #0 sta IDEtmp0 sta IDEtmp1 sta IDEtmp2 CoI030 lda CMDBUF,X and #15 clc adc IDEtmp0 sta IDEtmp0 bcc CoI025 inc IDEtmp1 bne CoI025 inc IDEtmp2 bne CoI025 CoI025 inx cpx TEMP0 ; last number? bcc CoI050 ; no, -> ; check given number lda IDEtmp1 sta POSTcode3 lda IDEtmp0 sta POSTcode lda IDEtmp2 sta POSTcode2 cmp CSubIma+2 bcc CoI52 ; < is OK, -> bne CoI60 ; > is error, -> lda IDEtmp1 cmp CSubIma+1 bcc CoI52 ; < is OK, -> bne CoI60 ; > is error, -> lda IDEtmp0 cmp CSubIma bcs CoI60 ; >= is error, -> ; multiply with 3 CoI52 ldy #3 jsr ImaAdd clc rts CoI050 ldy #10 jsr ImaAdd ; multiply with 10 jmp CoI030 CoI60 jmp Error66 CopyImage jsr LedOn ; turn LED on [C100] ldx FILTBL+1 ; position behind comma cpx CMDSIZ ; exists? bne CoI010 ; yes, -> CoI005 jmp Error33 ; Found at least the "to" number, now check size. Should be 3 at least: x,x CoI010 lda CMDSIZ sta TEMP0 cmp #6 ; check total size of command > 6 bcc CoI005 ; no, -> error ldx FILTBL+1 cpx CMDSIZ ; smaller then CMDSIZ? bcs CoI005 ; no, -> error ; Read "to" number jsr CoIReadNumber ; Store in LBAto lda IDEtmp0 adc InitLBAima+1 ; add offset for image directory sta LBAto lda IDEtmp1 adc #0 sta LBAto+1 lda IDEtmp2 adc #0 sta LBAto+2 ; Read "from" number ldx FILTBL+1 dex stx TEMP0 ldx #3 jsr CoIReadNumber ; Store in LBAfrom lda IDEtmp0 adc InitLBAima+1 ; add offset for image directory sta LBAfrom lda IDEtmp1 adc #0 sta LBAfrom+1 lda IDEtmp2 adc #0 sta LBAfrom+2 ; Prepare a buffer for copying the data jsr GetBuffer ; free buffer bpl COI100 ; yes, -> jmp Error70 ; 70, 'no channel' COI100 tax lda BufferAddress,X ; buffer address high sta TEMP1 lda #$00 sta TEMP0 ; address low tax ; sector counter tay lda #3 ; 3 * 256 sectors sta TEMP2 ; Prepare reading COI110 stx IDElba0 stx POSTcode lda LBAfrom sta IDElba1 sta POSTcode3 lda LBAfrom+1 sta IDElba2 clc lda #$E0 adc LBAfrom+2 sta IDElba3 lda #1 sta IDEnumsec ; Read data lda #$20 ; read sector jsr SendCommand COI200 lda IDEdata sta (TEMP0),Y iny bne COI200 COI210 lda IDEstatus ; ready? bmi COI210 ; if not, -> wait ; Prepare writing COI260 stx IDElba0 lda LBAto sta IDElba1 sta POSTcode2 lda LBAto+1 sta IDElba2 clc lda #$E0 adc LBAto+2 sta IDElba3 lda #1 sta IDEnumsec ; Write data lda #$30 ; write sector jsr SendCommand COI300 lda (TEMP0),Y sta IDEdata iny bne COI300 COI310 lda IDEstatus ; ready? bmi COI310 ; if not, -> wait inx ; 256 sectors? bne COI110 ; no, -> ; next 256 sectors inc LBAfrom bne COI320 inc LBAfrom+1 bne COI320 inc LBAfrom+2 COI320 inc LBAto bne COI330 inc LBAto+1 bne COI330 inc LBAto+2 COI330 dec TEMP2 ; all 768 sectors? beq COI340 ; yes, -> jmp COI110 ; no, -> COI340 lda #1 sta WPSW0 jmp InitDrive .ba $FFEA ;** USER vectors UserVectors ; [FFEA] .WO E_CD5F ;** UA, U1 .WO E_CD97 ;** UB, U2 .WO BUF2+0 ;** UC, U3 .WO BUF2+3 ;** UD, U4 .WO BUF2+6 ;** UE, U5 .WO BUF2+9 ;** UF, U6 .WO BUF2+12 ;** UG, U7 .WO BUF2+15 ;** UH, U8 ;** Hardware vectors .WO NMI ;** UI, U9 .WO RESET ;** RESET .WO IRQ ;** IRQ .en