;------------------------------------------------------------------------------ ; ; 1541 with IDE interface, using my own filesystem V0.1 ; ; for the moment only 8 bits interface ; ; ; - uses 4 bytes as pointer to the next sector (LSB first) ; - as bit 4..7 of the 4th byte aren't used they have another meaning: ; - bit 7 = set : last sector ; - bit 6 (not used yet) ; - bit 5 (not used yet) ; - bit 4 (not used yet) ; - if last sector, first byte is the number of used bytes ; ; ;------------------------------------------------------------------------------ /* Remarks: - 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. */ ; To do or to take care of: ; Wait until writing BAM until change of BAM sector or drive is idle. ;** Memory .eq JOBSZP = $00 .eq JOBS = $0000 .eq TraSecLBA = $06 ; org TRASEC for buffer 0 ; ... $1D ; Free 1E-22 .eq VIC20mode = $23 ; VIC-20 / C64 mode .eq IDEtmp0 = $24 ; temporary .eq IDEtmp1 = IDEtmp0+1 .eq IDEtmp2 = IDEtmp0+2 .eq IDEtmp3 = IDEtmp0+3 .eq IDEtmp4 = IDEtmp0+4 .eq IDEtmp5 = IDEtmp0+5 .eq IDEtmp6 = IDEtmp0+6 .eq IDEtmp7 = IDEtmp0+7 .eq IDEtmp8 = IDEtmp0+8 .eq IDEtmp9 = IDEtmp0+9 .eq BUFPNT = $30 ; pointer to currently active buffer .eq J_BUFPNT = $0030 .eq DiskParms = $32 ; copy of disk parameters in RAM ; ... $35 .eq DirParms = $36 ; start of directory ; ... $39 .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) .eq NXTTRK = $42 ; next track to move head to .eq SECCNT = $43 ; sector counter for format routine .eq SaveX = $44 ; temporary storage for register X .eq JOB = $45 ; temporary storage of job code ; Free 047 .eq ACLTIM = $48 ; timer for acceleration of head .eq SAVSP = $49 ; temporary save of stackpointer .eq DelSecLBA = $4A ; LBA replacement of DELSEC .eq DirSecLBA = $4E ; LBA replacement of DIRSEC .eq PrgLba = $52 ; IDE equivalent of PrgTrack and PRGSEC .eq UseLba = $56 ; IDE equivalent of TRACK and SECTOR .eq DirLba = $5A ; start of momentary (sub-) directory .eq R5 = $5E .eq R6 = $5F .eq MBAM0 = $60 ; momentary BAM sector in buffer ; ... $63 ; MBAM0+3 <> 0 means not valid ; Free 064 .eq VNMI = $65 ; pointer to NMI routine .eq J_VNMI = $0065 .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 (user jump) .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 ; Free 07E - 081 .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 ; record # .eq RECH = $BB .eq WRIPNT = $C1 ; Write pointer .eq WRIPNTab = $00C1 ; 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 SidSecLBA = $E2 ; LBA replacement of TRKSS/SECSS ; Free 0E6 .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 DIRSECP0 = $0100 ; LBA replacement of DIRSECP .eq DIRSECP1 = DIRSECP0+4 .eq DIRSECP2 = DIRSECP0+8 .eq DIRSECP3 = DIRSECP0+12 .eq DIRSECP4 = DIRSECP0+16 .eq DSecLBA = DIRSECP0+24 ; LBA replacement of DSEC .eq FilLBA = DSecLBA+24 ; LBA replacement of FILTRK/FILSEC ; +24 .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 ; Free 023c ; Free 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 .eq BUFUSEL = $024F ; Free 250 - 252 .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) ; Free 259 - 25A .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 ; Free 26D - 26E .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 ; Free 280 - 289 .eq PATFLG = $028A ; pattern present flag .eq IMAGE = $028B ; file stream image / flag syntax check ; Free 28C - 28E .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 29C .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 ; Free 02F9 .eq NumFrBlk = $02FA ; # of free disk blocks ; Free 2FE .eq BUF0 = $0300 .eq BUF2 = $0500 .eq BUF3 = $0600 ;+------+-----+-----+---+---+---+----------------+---------------+ ;| 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 /* 3BC,378 = Printerdata 3BD,379 = Printerstatus bit 0 = not used bit 1 = not used bit 2 = not used bit 3 = error (15) bit 4 = select (13) bit 5 = paper end (12) bit 6 = acknowledge (10) bit 7 = busy (11) 3BE,37A = Printercontrol bit 0 = strobe (1) - inverted bit 1 = autofeed (14) - inverted bit 2 = Initialize (16) bit 3 = select in (17) - inverted bit 4 = enable IRQ7 bit 5 = bi-directional mode bit 6 = not used bit 7 = not used Control after reset: $CC Commands: */ ; 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 = ; bit 1 = ; bit 2 = ; bit 3 = drive 0 LED ; bit 4 = ; bit 5 = ; bit 6 = ; bit 7 = .eq PortA2 = $1C01 ; Used for displaying POST codes .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 ;** Constants ; Directory entry ; filetype 1 byte ; pointer 4 bytes ; name 16 bytes ; sideSector 4 bytes ; recordsize 1 byte ; pointer to replacement file 4 bytes ; number of Sectors 2 bytes ; future 4 bytes ; -- + ; 36 bytes .eq DirNumSecs = 32 ; offset of number of sectors of file ; in dir entry .eq DirSideSec = 21 ; offset side sectors in dir entry .eq DirReplace = 26 ; offset replacement LBA in dir entry .eq LengthEntry = 36 ; length of a directory entry .eq NumEntries = 7 ; number of dir entries / sector .eq NewStack = $FE ; start of Stack .ba $C000 ;** Block containing text and other forms of data HDidentity .tx "1541-IDEN8 FS00" ; 8 bits interface HDversion .tx "00.00.01 " HDheader .tx "IDE41" HDinitName .tx "(C) R.BALTISSEN " ;** Table of original 1541 command words TblCommands .by "V" ; Validate .by "I" ; Initialize .by "D" ; D (back up) .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 .BY <(Validate) .BY <(Initialize) .BY <(Error31) .BY <(Memory) .BY <(Block) .BY <(User) .BY <(Position) .BY <(USRexec) .BY <(Copy) .BY <(Rename) .BY <(Scratch) .BY <(New) ;** High byte of command addresses CmdAddrHB .BY >(Validate) .BY >(Initialize) .BY >(Error31) .BY >(Memory) .BY >(Block) .BY >(User) .BY >(Position) .BY >(USRexec) .BY >(Copy) .BY >(Rename) .BY >(Scratch) .BY >(New) ;** Table of command words TblCommands2 .by "C" ; Change directory .by "D" ; Deltree .by "M" ; Make directory .by "P" ; Prepare harddisk .by "R" ; Remove directory ;** Low byte of command addresses CmdAddrLB2 .by <(CmdC) .by <(CmdD) .by <(CmdM) .by <(CmdP) .by <(CmdR) .by <(Error31) ;** High byte of command addresses CmdAddrHB2 .by >(CmdC) .by >(CmdD) .by >(CmdM) .by >(CmdP) .by >(CmdR) .by >(Error31) ;** Names of file types, used for directory FileTypes .tx "DSPURDBTE " ;** 1st char .tx "EERSEIIXX " ;** 2nd char .tx "LQGRLRNTE " ;** 3rd char ;** File types, used for OPEN command FileTypes2 .tx "DSPUL" ;** Number of bits net set par nibble NibbleBits .by 4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0 ;** Powers of 2 PowersOf2 .by $01, $02, $04, $08, $10, $20, $40, $80 ;** File control methods RWAM .tx "RWAM" ;** Bytes for syntax check TblChkSyntax .by $51, $DD, $1C, $9E, $1C ; ; ^ ^ ; | | ; +-------------------+---- why are these here? ;============================================================================= CmdC CmdD CmdM rts ;** Prepare harddisk ; - determine size of harddisk ; - initialise first sector ; First sector ; identifier 16 bytes ; version 16 bytes ; disk parameters 4 bytes ; directory parameters 4 bytes ; name of disk 16 bytes ; ID is not supported .eq DDiskParms = 32 .eq DDi3Parms = 36 .eq DiskName = 40 ; offset of the diskname in sector 1 CmdP jsr ClearBUF2 ; [AX] ; Copy 32 bytes of the signature + version to the buffer ldx #31 CmdP010 lda HDidentity,X sta BUF2,X dex ; all characters copied? bpl CmdP010 ; no, -> ; copy the disk and directory parameters to disk ldx #7 CmdP020 lda DiskParms,X sta BUF2+DDiskParms,X dex ; all data copied? bpl CmdP020 ; no, -> ; copy the initial name of the disk ldx #15 CmdP030 lda HDinitName,X sta BUF2+DiskName,X dex ; all data copied? bpl CmdP030 ; no, -> ; write the sector lda #$E0 sta IDElba3 ldx #2 stx IDElba0 ; first BAM sector dex stx IDEnumSec ; number of sectors dex stx IDElba1 stx IDElba2 jmp WriteIdeSector ; create the first directory sector, quick and dirty jsr ClearBUF2 ; [AX] lda #$FF sta BUF2 lda #$80 sta BUF2+3 ldx #3 CmdP040 lda DirParms,X sta IDElba0,X dex bpl CmdP040 jmp WriteIdeSector CmdR rts ;** Clear $05xx ; used: AX ClearBUF2 ldx #0 txa clrb010 sta BUF2,X inx bne clrb010 rts ;** Copy the contents of a buffer to the sector pointer UseLBA ; in: Y ; used: AY DirBuf2UseLBA lda (DIRBUF),Y ; and get sector number sta UseLBA iny lda (DIRBUF),Y sta UseLBA+1 iny lda (DIRBUF),Y sta UseLBA+2 iny lda (DIRBUF),Y sta UseLBA+3 rts ;** Copy the directory parameters to the sector pointer UseLBA ; used: AX DirPar2UseLba ldx #3 B_DPU00 lda DirParms,X sta UseLBA,X dex bpl B_DPU00 rts ;** Copy the File link parameters to the sector pointer UseLBA ; in: X ; used: A FilLBA2UseLBA2 lda FilLBA,X sta UseLBA lda FilLBA+1,X sta UseLBA+1 lda FilLBA+2,X sta UseLBA+2 lda FilLBA+3,X sta UseLBA+3 rts ;** Find the BAM sector for sector stored in UseLBA ; in: UseLBA ; out: UseLBA ; IDEtmp5 = original UseLBA+1 ; used: AX FindBamSec2 lda UseLBA+1 ; "divide" by 256 sta IDEtmp5 ; save for future use sta UseLBA lda UseLBA+2 sta UseLBA+1 lda UseLBA+3 sta UseLBA+2 ldx #3 ; divide by 8 L_FBS01 lsr UseLBA+2 ror UseLBA+1 ror UseLBA dex bne L_FBS01 stx UseLBA+3 ; := 0 ; add 3 because actual BAM starts at sector 3 clc lda #3 adc UseLBA sta UseLBA lda #0 adc UseLBA+1 sta UseLBA+1 lda #0 adc UseLBA+2 sta UseLBA+2 ; no need to increase UseLBA+3 L_FBS02 rts ;** Find the exact byte and bit in the BAM sector for sector stored partly ; in UseLBA ; in: UseLBA ; out: IDEtmp4 = pointer within buffer ; IDEtmp5 = affected bit ; UseLBA ; used: AX FindBamSec lda UseLBA sta IDEtmp4 ; save for future use pha jsr FindBamSec2 ; [AX] ; Which byte within the secor is affected? ldx #3 L_FBS11 lsr IDEtmp5 ror IDEtmp4 dex bne L_FBS11 ; IDEtmp4 now contains the pointer to the byte in the sector pla and #7 tax lda PowersOf2,X sta IDEtmp5 rts ;** Set UseLBA to point to first BAM sector FirstBamSec lda #2 sta UseLBA lda #0 sta UseLBA+1 sta UseLBA+2 sta UseLBA+3 rts ;** Find free sector and allocate ; out: UseLBA contains found free sector ; Used: IDEtmp, to preserve UseLBA during BAM actions ; AXY FreeSecAlloc ; set DIRBUF ldx JOBNUM lda BufferAddress,X sta DIRBUF+1 lda #0 sta DIRBUF ; start with root directory jsr DirPar2UseLba ; [AX] B_FFS02 jsr GetBitBAM ; sector is allocated? [AXY] bne B_FFS15 ; no, -> ; check next sector .... B_FFS07 inc UseLBA bne B_FFS08 inc UseLBA+1 bne B_FFS08 inc UseLBA+2 bne B_FFS08 inc UseLBA+3 ; last sector? B_FFS08 lda UseLBA+3 cmp DiskParms+3 bne B_FFS09 ; no, -> lda UseLBA+2 cmp DiskParms+2 bne B_FFS09 ; no, -> lda UseLBA+1 cmp DiskParms+1 bne B_FFS09 ; no, -> lda UseLBA cmp DiskParms beq B_FFS10 ; yes, -> ; .... and increment bit counter B_FFS09 inx cpx #8 ; checked all bits of BAM byte? bcs B_FFS092 ; no, -> B_FFS091 ldy IDEtmp4 lda (DIRBUF),Y ; read byte containing "sector" and PowersOf2,X ; sector free? bne B_FFS20 ; yes, -> beq B_FFS07 ; always -> B_FFS092 ldx #0 ; reset bit counter inc IDEtmp4 ; next BAM byte or finished? bne B_FFS091 ; next one, -> jsr UseLBA2IDEtmp bmi B_FFS02 ; always -> next BAM sector ; Disk is full B_FFS10 lda #$72 jmp OutputErrorMsg ; 72, 'disk full' ; Allocate this sector B_FFS15 ldx IDEtmp5 ; bit counter B_FFS20 lda PowersOf2,X ; allocate sector eor #$FF ; invert and (DIRBUF),Y ; read byte containing "sector" sta (DIRBUF),Y ; store byte containing "sector" jsr FindBamSec ; UseLBA -> BAM location [AX] jsr WriteBAM ; [AXY] ; restore original UseLBA and finish jmp IDEtmp2UseLba ; used: AXY GetByt2UseLba jsr GetByteFromBuf ; get byte [AXY] sta UseLBA jsr GetByteFromBuf ; get byte [AXY] sta UseLBA+1 jsr GetByteFromBuf ; get byte [AXY] sta UseLBA+2 jsr GetByteFromBuf ; get byte [AXY] sta UseLBA+3 rts ;** Convert hexidecimal value in IDEtmp to ASCII ; in: Y = pointer for (ERRPTR) ; used: AX Hex2Dec lda #0 sta IDEtmp0+4 ; 0 = not displayed sta IDEtmp0+5 ; decimal counter ldx #32 ; pointer in DECIMAL table L_xb000 lda IDEtmp0+3 cmp Decimal,X ; smaller? bcc L_xb010 ; yes, -> lda IDEtmp0+2 cmp Decimal+1,X ; smaller? bcc L_xb010 ; yes, -> lda IDEtmp0+1 cmp Decimal+2,X ; smaller? bcc L_xb010 ; yes, -> lda IDEtmp0 cmp Decimal+3,X ; smaller? bcc L_xb010 ; yes, -> sec lda IDEtmp0 sbc Decimal+3,X sta IDEtmp0 lda IDEtmp0+1 sbc Decimal+2,X sta IDEtmp0+1 lda IDEtmp0+2 sbc Decimal+1,X sta IDEtmp0+2 lda IDEtmp0+3 sbc Decimal,X sta IDEtmp0+3 inc IDEtmp0+5 bne L_xb000 ; always -> L_xb010 lda IDEtmp0+5 ; > 0 ? beq l_xb020 ; no, -> jsr PutCharERRPTR dex dex dex dex ; > 9 done? beq L_xb030 ; yes, -> l_xb020 lda #0 sta IDEtmp0+5 ; reset counter beq L_xb000 ; always -> ; last digit L_xb030 lda IDEtmp0 jmp PutCharERRPTR IDEtmp2UseLba ldx #3 B_I2U lda IDEtmp0,X sta UseLBA,X dex bne B_I2U rts ;** Turn LED of LedOff sei lda PortB2 and #$F7 ; LED off sta PortB2 cli rts ;** Turn LED on LedOn sei lda PortB2 ora #$08 ; LED on sta PortB2 cli rts PutCharERRPTR clc adc #"0" sta (ERRPTR),Y iny sty IDEtmp0+4 ; display 0 rts ;** Copy the contents of (R0) to UseLBA R0_UseLBa lda (R0),Y sta UseLBA iny lda (R0),Y sta UseLBA+1 iny lda (R0),Y sta UseLBA+2 iny lda (R0),Y sta UseLBA+3 rts ;** Read an IDE sector ReadIdeSector lda #$20 bne SendCommand ;** Write an IDE sector WriteIdeSector lda #$30 bne SendCommand ;** Seek a sector on drive 0 ;- in: LBA data in IDElbaX SeekSector lda #$77 ; Seek ;** Send command to IDE ;- in: A contains command ;- out: A contains error code SendCommand sta IDEcommand SendCommand010 lda IDEstatus ; ready? bmi SendCommand010 ; if not, -> wait rts ; in: X = offset TraSec2UseLBA lda TraSecLBA,X sta UseLba lda TraSecLBA+1,X sta UseLba+1 lda TraSecLBA+2,X sta UseLba+2 lda TraSecLBA+3,X sta UseLba+3 rts UseLBA2Buf lda UseLBA jsr Write2Buf ; [AX] lda UseLBA+1 jsr Write2Buf ; [AX] lda UseLBA+2 jsr Write2Buf ; [AX] lda UseLBA+3 jmp Write2Buf ; [AX] UseLBA2DelSec lda UseLba sta DelSecLBA lda UseLba+1 sta DelSecLBA+1 lda UseLba+2 sta DelSecLBA+2 lda UseLba+3 sta DelSecLBA+3 rts UseLBA2DirBuf lda UseLBA sta (DIRBUF),Y iny lda UseLBA+1 sta (DIRBUF),Y iny lda UseLBA+2 sta (DIRBUF),Y iny lda UseLBA+3 sta (DIRBUF),Y rts UseLBA2IDElba stx SaveX ldx #3 B_ulil lda UseLBA,X sta IDElba0,x dex bpl B_ulil ldx SaveX rts UseLBA2IDEtmp ldx #3 B_ulit lda UseLBA,X sta IDEtmp0,x dex bpl B_ulit rts UseLBA2WrBSS lda UseLBA jsr WrBytSidSec ; in buffer [X] lda UseLBA+1 jsr WrBytSidSec ; in buffer [X] lda UseLBA+2 jsr WrBytSidSec ; in buffer [X] lda UseLBA+3 jmp WrBytSidSec ; in buffer [X] ;============================================================================== ;** Clear error flags [C123] ClrErrorFlags lda #$00 sta ERWORD rts ;** Prepare for LED flash after error [C12C] PrepLedFlash sei lda #$50 sta ERWORD lda #8 ora PortB2 sta PortB2 ; LED on cli rts ;** Interpret command from computer [C146] InterprCmnd lda #$10 sta PortA2 ; output code 10 jsr OK2Buffer ; OK message in buffer [AXY] lda ORGSA ; secundair address bpl L_C160 and #$0F cmp #$0F ; 15, command-channel ? beq L_C160 ; yes, -> jmp OPEN_N15 ; OPEN command L_C160 lda #$15 sta PortA2 ; output code 15 jsr ChkLineLength ; [AXY] lda (INPPTR),Y ; get first char sta CHAR ; mark it ; First check for new commands cmp #"!" bne L_C168 ; original routine lda CMDBUF+1 ; 2nd character from buffer sta CHAR ldx #(CmdAddrLB2-TblCommands2-1) NewCommands20 lda TblCommands2,X ; compare commands cmp CHAR ; with char beq NewCommands30 ; found, -> dex bpl NewCommands20 ; NOT found jmp Error31 NewCommands30 stx INSTRU lda CmdAddrLB2,X sta TEMP0 lda CmdAddrHB2,X sta TEMP1 lda #$11 sta PortA2 ; output code 11 jmp (TEMP0) ; jump to command ; original commands L_C168 ldx #$0B L_C16A lda TblCommands,X ; compare commands cmp CHAR ; with char beq L_C17A ; found, -> dex bpl L_C16A ; NOT found jmp Error31 L_C17A stx INSTRU cpx #$09 ; commandnumber >= 9 ? bcs ChkSyntax ; test for R, S or N L_C184 ldx INSTRU ; X = commandnumber lda CmdAddrLB,X sta TEMP0 lda CmdAddrHB,X sta TEMP1 jmp (TEMP0) ; jump to command ;** Prepare error msg after executing command Out_Err_msg J_C199 lda ERWORD ; flag set? bne OutputErrorMsg ; yes, -> ldy #$00 tya sty UseLba sty UseLba+1 sty UseLba+2 sty UseLba+3 J_C1A3 sty INPPTR jsr ErrMsg2buf jsr ClrErrorFlags ; [A] J_C1AD jsr EraseInputBuf ; clear inputbuffer [AY] jmp Close17_18 ; close internal channel [AX] ;** Erase input buffer [C1BD] ; used: AY EraseInputBuf ldy #$28 lda #$00 L_C1C1 sta CMDBUF,Y ; fill $0200 - $0228 with 0 dey bpl L_C1C1 rts ;** Output error msg (sector 0) OutputErrorMsg ldy #$00 sty UseLba sty UseLba+1 sty UseLba+2 sty UseLba+3 jmp CreErrorMsg ; Accu contains errornumber [AXY] ;** Check input line ; used: AXY ChkInputLine ldx #$00 stx FILTBL ; pointer to drivenumber lda #":" jsr SearchInputBuf ; Check line until : or end [AXY] beq B_C1E2 ; not found, -> dey dey sty FILTBL ; points to drivenumber for : B_C1E2 jmp Get_Drv_Num ; [AY] ;** Check for a colon in the line ; used: AXY ChkForColon ldy #$00 ldx #$00 lda #":" jmp SearchInputBuf ; [AXY] ;** Check input 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 / ; used: AXY ChkSyntax jsr ChkForColon ; [AXY] bne Chk4DrvNum B_C1F3 lda #$34 jmp OutputErrorMsg ; 34, 'Syntax error' Chk4DrvNum dey dey sty FILTBL ; points to drivenumber for : txa ; found ',' for ':' ? bne B_C1F3 ; yes, -> 'Syntax error' ChkWildcard lda #"=" jsr SearchInputBuf ; [AXY] 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 ; [AXY] 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 CmdAddrHB+4,X ; combine with checkbyte bne L_C260 ; faulty syntax, -> rts L_C260 sta ERWORD ; set error flag Error30 lda #$30 ; 30, 'Syntax error' jmp OutputErrorMsg ;** Search character in input buffer ; in: AX ; used: AXY SearchInputBuf 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 pointer in command ; used: AXY ChkLineLength 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 ;** Clear flag for command input ; used: AXY CLR_Flg_inp 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 #4 L_C2FD lda #0 sta F2PTR+1,X ; flag line analyse sta BUFPTR,X sta COMFLG,X ; wildcard flags ; copy parms of momentary subdirectory to DIRSECP lda DirLba,X sta DIRSECP0,X sta DIRSECP1,X sta DIRSECP2,X sta DIRSECP3,X sta DIRSECP4,X dex bpl L_C2FD inx rts ;** Get drive number [C312] ; out: A = drive number ; used: AXY ; actual drive number before colon is ignored GetDrvNum lda F2CNT ; number of comma's sta F1CNT ; mark R_C318 lda #1 sta F2CNT ; one drive only sta F2PTR GetDrvNum2 ldx #$00 L_C325 stx CHNNUM lda FILTBL,X ; place of ':' tax ; mark ; subroutine embedded ------> L_C33D lda #":" cmp CMDBUF+1,X bne L_xx02 ; no, -> inx inx lda #0 ; get drive number beq L_C34F ; always -> L_xx02 cmp CMDBUF,X ; this place? beq L_xx03 ; yes, -> lda #$80 ; set bit 7, not sure of drive bne L_C34F ; always -> L_xx03 inx lda #0 L_C34F tay txa ; <--------------------------- L_C32D ldx CHNNUM sta FILTBL,X ; store exact place inx tya ; drive number rts ;** Get drive number ; used: AY Get_Drv_Num lda #$00 sta IMAGE ; clear syntax flag ldy FILTBL ; place in commandline B_C370 lda (INPPTR),Y ; get char jsr ChkDriveNum ; Number is OK? [A] 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 ;** Check filetype [C389] ; used: AY ChkFileType 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 #$04 L_C3B0 cmp FileTypes,Y ; compare with 'S', 'P', 'U', etc. beq L_C3B8 ; same, -> dey bne L_C3B0 ;* if not found, filetype 'DEL' is assumed L_C3B8 tya sta TYPFLG ; note file type rts ;** Check drive number [C3BD] ; in: A ; out: A = drive number (always 0) ; used: A ChkDriveNum cmp #"0" beq L_C3C7 cmp #"1" beq L_C3C7 ora #$80 ; set bit 7 = type not sure L_C3C7 and #$80 rts ;** Search for file in directory [C3CA] ; used: AXY Srch_File_Dir jsr LedOn lda #$00 sta DELIND jsr RD_1st_Dir_Blk ; read first directory block [AXY] bne L_C475 ; found something, -> rts L_C470 jsr Nxt_File_Dir ; [AXY] beq L_C485 ; not found, -> L_C475 jsr Tst_Input_Dir ; [AXY] lda FOUND beq L_C47E ; more files, -> rts L_C47E lda ENTFND ; file found? bmi L_C470 ; no, -> bpl L_C475 ; yes, -> L_C485 rts ;** Search next file ; used: AXY SrchNxtFileDir jsr RD_Nxt_Dir_Blk ; [AXY] beq L_C4AA ; not found, -> bne L_C4BA ; (found) always -> SrchDirEntry lda #$00 sta DELIND jsr RD_1st_Dir_Blk ; [AXY] bne L_C4BA ; if found, -> sta FOUND L_C4AA lda FOUND rts ;** Search next directory item ; used: AXY SrchNxtDirEnt jsr Nxt_File_Dir ; [AXY] beq L_C4AA ; not found, -> L_C4BA jsr Tst_Input_Dir ; [AXY] [AXY] ldx ENTFND ; found file? bpl L_C4C9 ; yes, -> lda FOUND beq SrchNxtDirEnt ; no, -> rts L_C4C9 lda TYPFLG ; DEL? beq L_C4D7 ; yes, ready -> RTS lda COMFLG,X ; filetype and #$07 cmp TYPFLG ; like wanted type? bne SrchNxtDirEnt L_C4D7 rts ;** Check input in directory ; used: AXY Tst_Input_Dir ldx #$FF stx ENTFND ; flag file found inx stx PATFLG jsr Set_Ptr_to_File ; [AX] beq L_C4EC L_C4E6 rts L_C4E7 jsr Ptr_to_Nxt_File ; [AX] bne L_C4E6 ; no file, ready -> L_C4EC lda FILTBL,X ; check next file name tax jsr Get_Length_Name ; get length filename [A] ldy #$03 bne L_C51D ; always -> 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 txa asl asl ; *4 tay lda UseLba ; sector number of directory sta DIRSECP0,Y ; in tabels lda UseLba+1 sta DIRSECP0+1,Y lda UseLba+2 sta DIRSECP0+2,Y lda UseLba+3 sta DIRSECP0+3,Y 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 txa asl A asl A tax lda (DIRBUF),Y ; first track of file sta FilLba,X iny lda (DIRBUF),Y sta FilLba+1,X iny lda (DIRBUF),Y sta FilLba+2,X iny lda (DIRBUF),Y sta FilLba+3,X lda RECSIZ ; do we have length of record? bne Set_Ptr_to_File ; yes, -> ;* Get length of record ldy #25 lda (DIRBUF),Y sta RECSIZ ;** Set pointer to file ; used: AX Set_Ptr_to_File lda #$FF sta FOUND lda F2CNT sta F2PTR Ptr_to_Nxt_File dec F2PTR bpl L_C59A rts L_C59A ldx F2PTR lda COMFLG,X ; wildcard-flag is set? bmi L_C5A6 ; yes, -> txa asl asl tax lda FilLBA,X ; track number is set? bpl Ptr_to_Nxt_File ; yes, -> L_C5A6 lda #$00 sta FOUND rts ;** Read first directory block ; in: - ; out: ; used: AXY RD_1st_Dir_Blk ldy #$FF sty DelSecLBA+3 sty ENTFND ; Point to first sector of the momentary (sub) directory ldx #3 stx LSTBUF ; not the last sector yet L_C5B0 lda DirLba,X sta UseLba,X dex bpl L_C5B0 jsr ReadSeqFile ; [AXY] J_C5C4 lda LSTBUF ; last sector? bpl L_C5CA ; no, -> rts L_C5CA lda #NumEntries ; number of dir entries (-1) sta FILCNT ; 7 * 36 + 4 = 256 lda #4 jsr GetAthByte ; get byte from buffer [AXY] sta LSTBUF ; HB LBA of next sector J_C5D7 jsr SetBufPointer ; [AX] dec FILCNT ; decrement entry counter ldy #$00 lda (DIRBUF),Y ; first byte of directory = filetype bne L_C5FB lda DElSecLBA+3 ; empty? bpl Nxt_File_Dir ; no, -> jsr GetSector ; [AXY] jsr UseLBA2DelSec 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 [C604] ; used: AXY RD_Nxt_Dir_Blk lda DirSecLBA sta UseLBA lda DirSecLBA+1 sta UseLBA+1 lda DirSecLBA+2 sta UseLBA+2 lda DirSecLBA+3 sta UseLBA+3 jsr ReadSeqFile ; [AXY] lda INDEX jsr SetBufPointer3 ; [AX] ;** Search for next file in directory [C617] ; used: AXY Nxt_File_Dir lda #$FF sta ENTFND ; erase flag "found file" lda FILCNT ; searched all dir-entries? bmi L_C629 ; yes, -> lda #LengthEntry ; IDE entry is now 36 bytes long !!! jsr IncBufPointer ; [AX] jmp J_C5D7 L_C629 jsr RdNxtBlock ; set pointer [AXY] jmp J_C5C4 ; read next block L_C62F lda DIRBUF sta INDEX jsr GetSector ; [AXY] lda UseLba sta DirSecLBA lda UseLba+1 sta DirSecLBA+1 lda UseLba+2 sta DirSecLBA+2 lda UseLba+3 sta DirSecLBA+3 rts ;** Name of file in directory buffer [C66E] ; in: ; A = maximum length ; X points to start of the name in CMDBUF ; Y buffernumber ; used: AXY NamFil2DirBuf pha ; Accu contains maximum length jsr Get_Length_Name ; [A] jsr FilNam2Buf ; write filename in buffer [AXY] pla sec sbc STRSIZ ; compare length with maximum length tax ; store difference in X beq B_C687 ; = 0, -> bcc B_C687 ; greater then maximum, -> end ; 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 ;** Next subroutine is only called at $C672 [C688] ; in: X, Y ; out: Y ; used: AXY FilNam2Buf 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 rts ;** Search for end of name in command ; in: X = offset of name in command buffer ; used: A Get_length_name 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 bcc B_C6C8 ; found 16 characters, -> cpx CMDSIZ ; compare with length of input bcc B_C6AD ; smaller, search on -> B_C6C8 stx LIMIT pla tax ; restore X rts ;** Create directory entry in buffer ; used: AXY GetDirEntry lda #$11 sta SA jsr OpenChan4Read ; [AX] jsr SetBufPointer ; [AX] lda ENTFND ; found entry? bpl B_C71B ; yes, -> jsr BlocksFree ; [AXY] clc rts B_C71B ldx #$18 ldy #DirNumSecs+1 ; 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 ; [AY] 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 FileTypes+32,Y ; 3rd char of filetype sta NameBuffer,X dex lda FileTypes+16,Y ; 2nd char of filetype sta NameBuffer,X dex lda FileTypes,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 ldy #$12 B_C773 lda (DIRBUF),Y ; copy file name sta NameBuffer,X dex dey cpy #$03 bcs B_C773 lda #'"' ; " before filename 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_C798 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 ; [AXY] sec rts ;** Clear the reserved space for the name of the disk [C7AC] ; out: Y=0 ; used: AY ClrNameBuf ldy #$1B lda #" " B_C7B0 sta NameBuffer-1,Y dey bne B_C7B0 rts ;** Create header with disk name [C7B7] ; used: AXY DirHeader jsr FirstBamSec ; [A] jsr ReadBAM ; [AXY] jsr ClrNameBuf ; [AY] lda #$FF sta TEMP0 ; ??? where used ??? inx stx NBTEMP0 stx NBTEMP1 ldx JOBNUM lda BufferAddress,X sta DIRBUF+1 lda #DiskName ; 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 ; used: AXY BlocksFree jsr ClrNameBuf ; Y := 0 [AY] ; Copy calculated number to IDEtmp ldx #3 B_C800 lda NumFrBlk,X sta IDEtmp0,X dex bpl B_C800 lda #<(NameBuffer) sta ERRPTR lda #>(NameBuffer) sta ERRPTR+1 jsr Hex2Dec ; display "BLOCKS FREE." ldx #0 stx NBTEMP0 stx NBTEMP1 B_C80B lda TxtBlocksFree,X sta NameBuffer,Y iny inx cpx #$0D ; whole text has been copied ? bcc B_C80B ; no, -> rts TxtBlocksFree .tx " BLOCKS FREE." ;** Get number of free blocks for dir ; used: A NumBlocksFree lda NumFrBlk+3 bne L_NBF08 lda NumFrBlk+2 bne L_NBF08 lda NumFrBlk+1 sta NBTEMP1 lda NumFrBlk sta NBTEMP0 rts L_NBF08 lda #$FF sta NBTEMP0 sta NBTEMP1 rts ;** S - Scratch command Scratch jsr ChkFileType ; [AY] jsr GetDrvNum2 ; [AXY] jsr LedOn lda #$00 sta R0 ; counter erased files sta R1 sta R2 sta R3 jsr SrchDirEntry ; [AXY] bmi B_C872 ; not found, -> B_C835 jsr IsFileOpen ; [AXY] bcc B_C86D ; yes, -> ldy #$00 lda (DIRBUF),Y ; filetype and #$40 ; LOCK-bit set? bne B_C86D ; yes, -> jsr DelDirEntry ; delete entry [AXY] ldy #DirSideSec+3 lda (DIRBUF),Y ; tracknumber of first side-sector bmi B_C855 ; does not exist, -> ldy #DirSideSec jsr DirBuf2UseLba ; [AY] jsr DelSectorChain ; delete all side-sectors [AXY] B_C855 ldx ENTFND ; file number lda #$20 and COMFLG,X ; file closed? bne B_C86B ; no, -> txa asl asl tax jsr FilLBA2UseLBA2 jsr DelSectorChain ; delete file [AXY] B_C86B inc R0 ; increase number of erased files bne B_C86D inc R1 bne B_C86D inc R2 bne B_C86D inc R3 B_C86D jsr SrchNxtFileDir ; another file? [AXY] bpl B_C835 ; yes, -> B_C872 ldx #3 B_C874 lda R0,X sta UseLBA,X dex bpl B_C874 lda #$01 ldy #$00 jmp J_C1A3 ; message "FILES SCRATCHED" ;** Erase file [C87D] ; used: AXY DelSectorChain jsr FreeSector ; free block in BAM [AXY] jsr ReadSeqFile ; [AXY] J_C894 lda #$00 jsr SetBufPointer3 ; buffer pointer to zero [AX] jsr RdNxtBlock2 ; [AXY] sta UseLBA jsr RdNxtBlock2 ; [AXY] sta UseLBA+1 jsr RdNxtBlock2 ; [AXY] sta UseLBA+2 jsr RdNxtBlock2 ; [AXY] sta UseLBA+3 ; last sector? bpl B_C8AD ; no, -> jmp CloseChannel ; close channel [AX] B_C8AD jsr FreeSector ; free block in BAM [AXY] jsr RdNxtBlock ; read next block [AXY] jmp J_C894 ; and continue ;** Erase dir entry [C8B6] ; used: AXY DelDirEntry ldy #$00 tya sta (DIRBUF),Y ; set file type to zero jsr WriteSector3 ; write block [AX] jmp VerifyExec ; and check [AX] ;** D - Backup command (UNUSED) [C8C1] Error31 lda #$31 jmp OutputErrorMsg ; 31, 'syntax error' ;** C - Copy command [C8F0] Copy lda #$E0 sta BUFUSEL ldx #13 ; get buffer number of BAM lda #$FF sta BUF0CH1zp,X lda #$0F sta LINUSE jsr ChkForColon ; check input line for colon [AXY] bne B_C90C ; found, -> jmp Error31 ; 31, 'syntax error' B_C90C jsr Chk4DrvNum ; check input [AXY] jsr GetDrvNum2 ; test drive number [AXY] 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 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 [AXY] lda F2CNT ; number of filenames in command cmp #$03 ; smaller than three? bcc B_C9A1 ; yes, -> lda BUFPTR ; directory block of the 1st file cmp BUFPTR+1 ; same directory block as second file? bne B_C9A1 ; no, -> lda DIRSECP0 ; directory sector of first file cmp DIRSECP1 ; same directory sector as second file? bne B_C9A1 ; no, -> lda DIRSECP0+1 cmp DIRSECP1+1 bne B_C9A1 ; no, -> lda DIRSECP0+2 cmp DIRSECP1+2 bne B_C9A1 ; no, -> lda DIRSECP0+3 cmp DIRSECP1+3 bne B_C9A1 ; no, -> jsr IsFilePresent ; is file present? [AX] lda #$01 sta F2PTR jsr ReadDirSec ; [AXY] jsr CheckREL ; get data type [AX] beq B_C982 ; REL file? 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 jsr Prep4Append ; prepare append [AXY] ldx #$02 jsr CopyFile2 ; copy file [AXY] jmp Out_Err_Msg ; done B_C9A1 jsr CopyFile1 ; copy file jmp Out_Err_Msg ; done CopyFile1 jsr Chk2Filenames ; [AX] jsr AllocNewSecWR ; [AXY] jsr CreDirEntry ; enter file in directory [AXY] ldx F1CNT CopyFile2 stx F2PTR jsr ReadDirSec ; [AXY] lda #$11 ; 17 sta SA jsr OpenChan4Read ; [AX] jsr CheckREL ; get data type [AX] bne B_C9CE ; no REL file? jsr CopyRelFile ; [AXY] B_C9CE lda #8 sta EOIFLG bne B_C9D8 ; always -> B_C9D5 jsr WrData2Buffer ; write byte in buffer [AXY] B_C9D8 jsr OpenChnGetByt ; and get byte [AXY] lda #$80 jsr ChkChanBit ; test bit 7 [A] beq B_C9D5 ; not set? jsr CheckREL ; check file type [AX] beq B_C9EA ; REL file? jsr WrData2Buffer ; get data byte in buffer [AXY] B_C9EA ldx F2PTR inx cpx F2CNT bcc CopyFile2 lda #$12 ; 18 sta SA jmp CloseFile ; close channel [AXY] ;** Open an internal channel for reading a directory block/file [C9FA] ; used: AXY ReadDirSec lda F2PTR asl asl tax lda DirSecP0,X sta UseLBA lda DirSecP0+1,X sta UseLBA+1 lda DirSecP0+2,X sta UseLBA+2 lda DirSecP0+3,X sta UseLBA+3 jsr ReadSeqFile ; read block [AXY] ldx F2PTR lda BUFPTR,X ; pointer in block jsr SetBufPointer3 ; set buffer pointer [AX] ldx F2PTR lda COMFLG,X ; file type and #$07 ; isolate sta TYPE ; and save lda #$00 sta RECSIZ jsr OpenFile4Read ; get parameters for REL file [AXY] ldy #$01 jsr CheckREL ; get file type [AX] beq B_CA31 ; REL file, -> iny B_CA31 tya jmp SetBufPointer3 ; set buffer pointer [AX] ; open channel and get byte [CA35] ; used: AX OpenChnGetByt lda #$11 ; 11 sta SA ;** [CA39] ; used: AXY OpenChnGetByt2 jsr OpenChan4Read ; open channel for reading [AX] jsr LedOn ; turn LED on jsr NxtByteFile ; get byte in output register [AXY] ldx CURCHN ; channel number lda OUTREG,X ; get byte 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? [AX] beq B_CA52 ; no, -> lda #$80 jsr SetFlags ; set bit 7 = last record [AX] B_CA52 rts ;** Copy a REL file [CA53] ; used: AXY CopyRelFile jsr GetDrvNum3 ; set drive number [AX] jsr SetPar2LstRec ; [AX] lda CHNNUM3 pha lda CHNNUM2 pha lda #$12 ; 18 sta SA jsr OpenChan4Write ; open write channel [AXY] jsr GetDrvNum3 ; set drive number [AX] jsr SetPar2LstRec ; [AX] jsr Record2Buffer ; [AXY] 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 [CA88] Rename jsr GetDrvNum2 ; get drive number from command line ; [AXY] B_CA97 jsr Srch_File_Dir ; search for file in directory [AXY] jsr Chk2Filenames ; does name exist? [AX] ldx #3 B_CA9F lda DIRSECP1,X sta UseLBA,X dex bpl B_CA9F jsr ReadSector2 ; read block from directory [AX] jsr VerifyExec ; ok? [AX] lda BUFPTR+1 ; pointer to directory entry clc adc #$03 ; pointer plus 3 to file name jsr SetBufPointer3 ; set buffer pointer [AX] jsr GetBufNumber ; get buffer number [AX] tay ldx FILTBL lda #$10 ; 16 characters jsr NamFil2DirBuf ; write name in buffer [AXY] jsr WriteSector3 ; write block to directory [AX] jsr VerifyExec ; ok? [AX] jmp Out_Err_Msg ; done, prepare disk status ;** Check if file present [CACC] ; out: X ; used: AX IsFilePresent lda COMFLG+1 ; file type and #$07 sta TYPE ; save ldx F2CNT B_CAD6 dex cpx F1CNT bcc B_CAE6 txa pha ; save X asl asl tax lda FilLBA,X ; sector in use? bmi B_CAD6 ; yes, -> pla tax ; restore X jmp B_CAD6 B_CAE1 pla ; remove saved X Error62 lda #$62 jmp OutputErrorMsg ; 62, 'file not found' B_CAE6 rts ;** Check if two file names are the same [CAE7] ; used: AX Chk2Filenames jsr IsFilePresent ; does file exist with old name? [AX] B_CAEA txa pha asl asl tax lda FilLBA,X ; file erased? bmi B_CAF4 ; yes, -> pla Error63 lda #$63 jmp OutputErrorMsg ; 63, 'file exists' B_CAF4 pla tax dex bpl B_CAEA rts ;** M - Memory command Memory lda CMDBUF+1 ; 2nd character from buffer cmp #'-' bne B_CB4B ; no, -> syntax error lda CMDBUF+3 sta TEMP0 lda CMDBUF+4 sta TEMP1 ldy #$00 lda CMDBUF+2 ; 3rd character from buffer cmp #'R' beq B_CB20 ; yes, -> memory read cmp #'W' beq B_CB50 ; yes, -> memory write cmp #'E' bne B_CB4B ; no, -> syntax error 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, -> finished reading 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 [AX] jmp J_D43A ; byte out B_CB4B jmp Error31 ;** 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 ldy CMDBUF+1 ; second char cpy #'0' bne E_CB6C ; no, -> ; Initial setup USER JUMP vectortable SetVectorU0 lda #<(UserVectors) sta USRJMP lda #>(UserVectors) sta USRJMP+1 rts E_CB6C jsr P_CB72 jmp Out_Err_Msg ; done, prepare error message 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 ; used: AXY J_CB84 ldx CMDSIZ ; length of filename dex ; greater than one? bne B_CBA5 ; yes, -> lda #$01 jsr FindRdChanBuf ; layout buffer and channel [AXY] jmp J_CBF1 ; set flags, done B_CBA0 jmp ErrNoChannel ; 70, 'no channel' B_CBA5 ldy #$01 jsr GetCmdParms2 ; get buffer number [AXY] ldx FilLba ; buffer number cpx #$05 ; bigger than 5? bcs B_CBA0 ; 70, 'no channel' lda #$00 sta TEMP0 sec B_CBB8 rol TEMP0 dex bpl B_CBB8 lda TEMP0 and BUFUSEL bne B_CBA0 sta BUFUSEL lda #$00 jsr FindRdChanBuf ; search channel [AXY] ldx CURCHN ; channel number lda FilLba ; buffer number sta BUF0CH1zp,X tax lda #0 ; drive 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 ;** B - Block command Block ldy #$00 ldx #$00 lda #'-' jsr SearchInputBuf ; search for minus sign [AXY] bne B_CC30 ; if found, -> B_CC26 jmp Error31 B_CC2B jmp Error30 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 ; if 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 [AXY] 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 .tx "AFRWEP" ;** Addresses of block commands [CC63] CmdAFRWEP .WO E_CCFE ;** 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 [CC6F] ; parameters will look like: [:] channel#; unit; sector ; used: AXY GetCmdParms ldy #$00 ; ^ ldx #$00 ; | lda #':' ; --+ jsr SearchInputBuf ; test line to colon [AXY] bne GetCmdParms2 ; if found, -> ldy #$03 ; not found, begin with 4th character GetCmdParms2 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 ldx #8 lda #0 B_CC96 sta IDEtmp0,X ; erase storage area for decimal numbers dex bpl B_CC96 ; X = $FF B_CCAB stx IDEtmp9 ; save X lda CMDBUF,Y ; get characters from input buffer cmp #'@' ; >= '@' ? bcs B_CCCA ; yes, -> cmp #'0' ; digits? bcc B_CCCA ; no, -> and #$0F ; convert ASCII digits to hex pha ; and save ; move digits one further ldx #7 B_CCC0 lda IDEtmp0,X sta IDEtmp1,X dex bpl B_CCC0 pla sta IDEtmp0 ; store read number iny ; increment pointer in input buffer cpy CMDSIZ ; line end reached bcc B_CCAB ; no, -> B_CCCA sty F2PTR ; save pointer clc ; clear result storage ldx #3 lda #$00 B_CCCC sta TEMP0,X dex bpl B_CCCC ldx IDEtmp9 ; restore X B_CCD0 inx cpx #9 ; done all possible 9 digits? bcs B_CCE4 ; yes, -> ; convert digit -> hex ldy IDEtmp0,X B_CCD7 stx IDEtmp9 ; save X dey bmi B_CCD0 ; X := X * 4 txa asl asl tax clc lda Temp0 adc Decimal,X ; add decimal value sta Temp0 inx lda Temp1 adc Decimal,X ; add decimal value sta Temp1 inx lda Temp2 adc Decimal,X ; add decimal value sta Temp2 inx lda Temp3 adc Decimal,X ; add decimal value sta Temp3 jmp B_CCD7 B_CCE4 lda F1CNT ; counter for paramaters asl asl tax lda TEMP0 sta FilLBA,X inx lda TEMP1 sta FilLBA,X inx lda TEMP2 sta FilLBA,X inx lda TEMP3 sta FilLBA,X inc F1CNT ; increment parameter counter ldy F2PTR cpx #3 ; compare with maximum number bcc B_CCEC ; smaller, -> jmp B_CC2B ; always -> 30, 'syntax error' B_CCEC jmp B_CC8B ;** Decimal values Decimal .dw 1, 10, 100, 1000, 10000, 100000, 1000000 .dw 10000000, 100000000 ;** B-F block free [CCF5] E_CCF5 jsr FilLba2UseLba ; get track, sector and drive number jsr FreeSector ; free block [AXY] jmp Out_Err_Msg ; done, prepare error message ;** B-A block allocate [CCFE] E_CCFE jsr FilLba2UseLba ; get track, sector and drive number jsr GetBitBAM ; sector is allocated? [AXY] beq B_CD2C ; yes, -> jsr AllocSector ; allocate block in BAM [AXY] jmp Out_Err_Msg ; done B_CD2C lda #$65 jmp CreErrorMsg ; 65, 'no block' next free block [AXY] B_CD31 lda #$65 jmp OutputErrorMsg ; 65, 'no block' no more free blocks ;** [CD36] OpenChanRdSec jsr OpenChannel2 ; open channel, set parameters [AXY] jmp ReadSector ; read block from disk [AX] ;** Read block from disk [CD42] ; used: AXY Readsector3 jsr OpenChanRdSec ; open channel, read block [AXY] lda #$00 jsr SetBufPointer3 ; set buffer pointer to zero [AX] ; Get byte from buffer [CD3C] L_CD3C jsr GetBufChanNum ; set pointer to buffer [AXY] lda (BUFTABzp,X) ; get byte 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 [AXY] jsr PrepByteBuf ; prepare byte from buffer [A] jmp Out_Err_Msg ; prepare error message ;** U1 substitute for block read E_CD5F jsr GetCmdParms ; get parameters of command [AXY] jsr Readsector3 ; read block from disk [AXY] 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 ;** B-W block write E_CD73 jsr OpenChannel2 ; open channel [AXY] jsr SetBufPointer ; set buffer pointer [AX] 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 [AX] tya jsr Write2Buf ; write byte in buffer [AX] txa pha jsr WriteSector ; write block to disk [AX] pla tax jsr GetByteBuf ; get byte from buffer [A] jmp Out_Err_Msg ; done, error message ;** U2 substitute for block write E_CD97 jsr GetCmdParms ; get command parameters [AXY] jsr OpenChannel2 ; open channel [AXY] jsr WriteSector ; and write block to disk [AX] jmp Out_Err_Msg ; done ;** B-E block execute E_CDA3 jsr OpenChanRdSec ; open channel and read block [AXY] 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 P_CDBA jmp (J_TEMP0) ; jump to routine ;** B-P block pointer E_CDBD jsr OpenChannel ; open channel, get buffer number [AXY] lda JOBNUM asl A ; * 2 tax ; as index lda FilLba+4 ; pointer value sta BUFTABzp,X ; save as buffer pointer jsr GetBufChanNum ; prepare a byte in buffer [AXY] jsr GetByteBuf ; for output [A] jmp Out_Err_Msg ; done ;** Open channel [CDD2] ; used: AXY OpenChannel lda CHNNUM asl asl tax inc CHNNUM lda FilLba,X ; buffer number tay dey dey cpy #$0C ; buffer number smaller than 14? bcc B_CDE5 ; yes, -> B_CDE0 jmp ErrNoChannel ; 70, 'no channel' B_CDE5 sta SA ; secondary address jsr OpenChan4Read ; open channel [AX] bcs B_CDE0 ; already allocated, 'no channel' jsr GetBufNumber ; buffer number [AX] sta JOBNUM ; set rts ;** Check buffer number and open channel [CDF2] ; used: AXY OpenChannel2 jsr OpenChannel ; check buffer number and open channel ; data is stored as 'channel#, unit, sector' [CDF5] FilLba2UseLba ldx CHNNUM ; channel number inx inx ; X + 2 -> sector LBA txa asl asl tax jsr FilLBA2UseLBA2 jsr ChkSector3 ; sector ok? [A] jmp LedOn ; turn LED on ;** Set pointer for REL file [CE0E] ; used: AX SetPtrRelFil jsr P_CE2C ; record number * record length [AX] jsr DivideBy252 ; divide by 252 [AX] lda ACCUM1 ; remainder = pointer in data block sta CHNNUM4 ; data pointer jsr DivideBy60 ; divide by 60 = sidsec number [AX] 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 [CE2C] ; used: AX P_CE2C jsr ClearResult ; erase work storage [A] sta ACCUM3 ; A = 0 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 [AX] B_CE57 jsr LshiftAccum ; shift register left [A] 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 252 [CE6E] ; used: AX DivideBy252 lda #252 .by $2C ; dummy BIT opcode ;** Divide by 60 [CE71] ; used: AX DivideBy60 lda #60 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 [A] 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 [A] B_CEA3 jsr P_CEED ; add register 0 to register 1 [AX] jsr LshiftAccum ; shift register 1 left [A] bit TEMP0 bmi B_CEB0 jsr LshiftAccumX2 ; left-shift register 1 twice [A] 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 [CED9] ; used: A ClearResult lda #$00 sta RESULT0 sta RESULT1 sta RESULT2 rts ;** Left shift 3-byte register twice [CEE2] ; used: A LshiftAccumX2 jsr LshiftAccum ; [A] ;** Left shift 3-byte register once [CEE5] ; used: A LshiftAccum clc LshiftAccum2 rol ACCUM1 rol ACCUM2 rol ACCUM3 rts ;** Add ACCUMx to RESULTx [CEED] ; used: AX P_CEED clc ldx #$FD B_CEF0 lda RESULT3,X adc ACCUM4,X sta RESULT3,X inx bne B_CEF0 rts ;** Initialize least recently used table ; used: AX InitLastTable 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 ; used: AXY UpdateTbl 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 ; used: AXY ChangeBuffer2 jsr UpdateTbl ; [AXY] jsr ChkBufferFree ; buffer free? [AX] bne B_CF6C ; no, -> jsr GetDrvNum3 ; set drive number [AX] jsr GetBuffer ; [AXY] bmi B_CF76 jsr DeactivateBuf ; [AXY] lda UseLBA+3 pha lda UseLBA+2 pha lda UseLBA+1 pha lda UseLBA pha lda #0 jsr GetAthByte ; get byte 1 from buffer [AXY] sta UseLBA lda #1 jsr GetAthByte ; get byte 0 from buffer [AXY] sta UseLBA+1 lda #2 jsr GetAthByte ; get byte 0 from buffer [AXY] sta UseLBA+2 lda #3 jsr GetAthByte ; get byte 0 from buffer [AXY] sta UseLBA+3 ; last sector? bmi B_CF66 ; yes, -> jsr CheckREL ; REL file? [AX] beq B_CF57 ; yes, -> jsr Chk4Write ; write job? [AX] bne B_CF57 ; no, -> jsr ChangeBuffer ; [AX] jmp J_CF5D B_CF57 jsr ChangeBuffer ; [AX] jsr ReadSector2 ; [AX] J_CF5D pla sta UseLBA pla sta UseLBA+1 pla sta UseLBA+2 pla sta UseLBA+3 jmp J_CF6F B_CF66 pla sta UseLBA pla sta UseLBA+1 pla sta UseLBA+2 pla sta UseLBA+3 B_CF6C jsr ChangeBuffer ; [AX] J_CF6F jsr GetBufNumber ; [AX] tax jmp VerifyExec ; and verify [AX] B_CF76 jmp ErrNoChannel ; 70, 'no channel' ;** Look for a free buffer [CF7B] ; used: AXY Look4FreeBuf jsr UpdateTbl ; [AXY] jsr ChkBufferFree ; [AX] bne B_CF8B ; no, -> jsr GetBuffer ; [AXY] bmi B_CF76 jsr DeactivateBuf ; [AXY] B_CF8B rts ;** Change Buffer ; used: AX ChangeBuffer ldx CURCHN ; channel number lda BUF0CH1zp,X eor #$80 sta BUF0CH1zp,X lda BUF1CH1zp,X ; rotate bit 7 in table eor #$80 sta BUF1CH1zp,X rts ;** Write data in buffer [CF9B] ; used: AXY WrData2Buffer ldx #$12 ; channel 18 stx SA jsr OpenChan4Write ; open write channel [AXY] jsr LedOn ; turn LED on jsr CheckREL ; check file type [AX] bcc B_CFAF ; no REL file lda #$20 jsr DeleteFlags ; [AX] B_CFAF lda SA ; secondary address cmp #$0F ; 15? beq B_CFD8 ; yes, -> bne B_CFBF ; no, -> ;** [CFB7] ; used: AXY WrData2Buf2 lda ORGSA ; secondary address and #$8F cmp #$0F ; greater than 15? bcs B_CFD8 ; then input buffer B_CFBF jsr CheckREL ; check file type [AX] bcs B_CFC9 ; REL file or direct access? lda DATA ; data byte jmp J_D19D ; write in buffer [AXY] 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 [AX] ldy CURCHN ; channel number jmp GetByteBuf ; prepare next byte for output B_CFD8 lda #$04 ; channel 4 sta CURCHN ; corresponding input buffer jsr SetBufPointer ; set buffer pointer [AX] cmp #$2A ; 40 beq B_CFE8 ; buffer end? lda DATA jsr Write2Buf ; write data byte in buffer [AX] 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 [CFF1] ; used: AX Write2Buf pha ; save data byte jsr GetBufNumber ; get buffer number [AX] bpl B_CFFD ; associated buffer? pla lda #$61 jmp OutputErrorMsg ; 61, 'file not open' ;** Write byte in side-sector block ; used: X WrBytSidSec pha ; save byte ldx CURCHN ; channel number lda SIDSECzp,X ; buffer number of the side-sector B_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 [D005] Initialize jsr ChkInputLine ; find drive number [AXY] jsr LoadBAM ; load BAM [AXY] jmp Out_Err_Msg ; prepare disk status ;** Load BAM [D042] ; used: AXY LoadBAM lda JOBNUM ; buffer number asl A tax lda #$02 sta BUFTABzp,X ;** Calculate blocks free [D075] J_D075 jsr SetBufPtrBAM ; buffer address to BMPNT(+1) [AXY] ; Clear counter lda #0 sta NumFrBlk,X sta NumFrBlk+1,X sta NumFrBlk+2,X sta NumFrBlk+3,X lda JOBNUM ; buffer number asl A asl A pha tax ; First BAM sector with sector information is found at LBA $0003 lda #3 sta TraSecLBA,X lda #$00 sta TraSecLBA+1,X sta TraSecLBA+2,X sta TraSecLBA+3,X ; Load the sector in memory L_xx70 jsr DskReadBlock ; read block [AX] ldy #0 L_xx72 lda (BMPNT),Y ; get most significant nibble (MSN) lsr lsr lsr lsr ; calculate number of set sectors tax lda NibbleBits,X sta IDEtmp0 ; get least significant nibble lda (BMPNT),Y and #$0F ; calculate number of set sectors tax lda NibbleBits,X clc adc IDEtmp0 ; add set sectors MSN adc NumFrBlk sta NumFrBlk ; result > 255 ? bcc L_xx76 ; no, -> inc NumFrBlk+1 bne L_xx76 inc NumFrBlk+2 bne L_xx76 inc NumFrBlk+3 bne L_xx76 L_xx76 iny ; next byte? bne L_xx72 ; yes, -> lda TraSecLBA+3,X cmp DirParms+3 bne L_xx78 lda TraSecLBA+2,X cmp DirParms+2 bne L_xx78 lda TraSecLBA+1,X cmp DirParms+1 bne L_xx78 lda TraSecLBA,X cmp DirParms bcs L_xx80 ; if >=, -> L_xx78 pla pha tax inc TraSecLBA bne L_xx70 inc TraSecLBA+1 bne L_xx70 inc TraSecLBA+2 bne L_xx70 inc TraSecLBA+3 bne L_xx70 ; All culculations done, result in NumFrBlk+0..3 l_xx80 rts ;** Read a sector into a buffer ; used: AXY ReadSec2Buf jsr Par2DiskCtrl ; parameters to disk controller [AX] jsr ReadBlock ; read block [AX] jsr VerifyExec ; ok? [AX] jmp GetByt2UseLba ; [AXY] ;** Read Block ; used: AX ReadBlock lda #$80 ; code for 'read' bne B_D0C9 ;** Write Block ; used: AX WriteBlock lda #$90 ; code for 'write' B_D0C9 sta CMD ; save jsr GetBufNumber ; get buffer number [AX] tax jsr ChkSector ; [AX] txa pha asl A ; buffer pointer times 2 tax lda #$00 sta BUFTABzp,X ; pointer in buffer to zero jsr CheckREL ; get file type [AX] 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 ; out: X = channel ; used: AX OpenChan4Read 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 lda LINTAB,X ; already in use? bmi B_D123 ; yes, -> J_D100 and #$0F sta CURCHN tax clc ; flag for ok rts ;** Open channel for writing ; out: Y = status of channel ? ; used: AXY OpenChan4Write 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 ; original bit 6 = (H), -> B_D119 tya jmp J_D100 B_D121 bmi B_D119 B_D123 sec ; flag for channel allocated rts ;** Check for file type REL ; out: ZF, 1 = file is REL type ; used: AX CheckREL ldx CURCHN lda DIACFLzp,X lsr A and #$07 cmp #$04 ; 'REL'? rts ;** Get buffer and channel numbers ; out: Y ; used: AXY GetBufChanNum jsr GetBufNumber ; get buffer number [AX] asl A tax ldy CURCHN rts ;** Get a byte from buffer ; used: AXY GetByteFromBuf jsr GetBufChanNum ; get buffer and channel number [AXY] 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 ; moved ----> ;** Read next block [D44D] ; out: A = data ; used: AXY RdNxtBlock jsr GetBufNumber ; get buffer number [AX] asl A ; times 2 tax lda #3 sta BUFTABzp,X ; load HB LBA of next sector lda (BUFTABzp,X) ; block following? bmi B_D169 ; no, -> lda #$FF sta BUFTABzp,X ; buffer pointer to -1 ; <---- ; [D156] RdNxtBlock2 jsr GetByteFromBuf ; get byte from buffer [AXY] bne B_D191 ; not last character? sta DATA ; save data byte lda ENDPNT,Y ; end pointer? beq B_D16A ; yes, -> lda #$80 sta REWRFLab,Y ; READ-flag lda DATA ; data byte B_D169 rts B_D16A jsr ChangeBuffer2 ; change buffer and read next block ; [AXY] lda #3 jsr SetBufPointer3 ; set buffer pointer to 3 [AX] jsr GetByteFromBuf ; get first byte from buffer [AXY] cmp #$80 ; last sector? bcs B_D192 ; yes, then last block sta UseLBA+3 lda #0 jsr SetBufPointer3 ; set buffer pointer to 0 [AX] jsr GetByt2UseLba ; [AXY] jsr ChangeBuffer2 ; change buffer and read next block ; [AXY] jsr GetDrvNum3 ; save drive number [AX] jsr Par2DiskCtrl ; parameter to disk controller [AX] jsr ReadBlock ; transmit read command [AX] jsr ChangeBuffer2 ; change buffer and read block [AXY] lda DATA ; get data byte B_D191 rts ;** Write byte in buffer and block B_D192 jsr GetByteFromBuf ; get next byte from buffer [AXY] ldy CURCHN sta ENDPNT,Y ; save as end pointer lda DATA ; get data byte back rts J_D19D jsr Write2Buf ; byte in buffer [AX] beq Buffer2Disk ; buffer full? [AXY] rts ;** Write the contents of the buffer to disk [D1A3] ; used: AXY Buffer2Disk jsr GetDrvNum3 ; get drive number [AX] jsr FreeSecAlloc ; find free block in BAM [AXY] lda #$00 jsr SetBufPointer3 ; buffer pointer to zero [AX] jsr UseLBA2Buf jsr WriteBlock ; write block [AX] jsr ChangeBuffer2 ; change buffer [AXY] jsr Par2DiskCtrl ; parameter to disk controller [AX] lda #$02 jmp SetBufPointer3 ; buffer pointer to 2 [AX] ;** Increment buffer pointer with value in A ; in: A ; used: AX IncBufPointer sta TEMP0 jsr SetBufPointer ; get buffer pointer [AX] clc adc TEMP0 sta BUFTABzp,X ; and increment sta DIRBUF rts ;** Get drive number ; used: AX GetDrvNum3 jsr GetBufNumber ; get number of buffer [AX] tax rts ;** Find write channel and buffer ; used: AXY FindWrChanBuf sec ; flag for writing bcs B_D1E3 ; always -> ;** Find read channel and buffer ; in: A ; used: AXY FindRdChanBuf clc ; flag for reading B_D1E3 php ; save sta TEMP0 ; number of buffers, AFAIK 0 or 1 jsr CloseChannel ; close channel [AX] ; Find channel and allocate 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 ErrNoChannel ; 70, 'no channel' B_D391 eor #$FF ; rotate bit model and LINUSE ; erase bit sta LINUSE ; allocate channel tya 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 [AXY] bpl B_D217 ; found? NoChannel jsr FreeBuffer ; erase flags in table [AX] ErrNoChannel lda #$70 jmp OutputErrorMsg ; 70, 'no channel' B_D217 sta BUF0CH1ab,Y ; buffer number in table dec TEMP0 ; buffer number bmi B_D226 ; already done? jsr GetBuffer ; find buffer [AXY] bmi NoChannel ; not found? sta BUF1CH1ab,Y ; buffer number in table B_D226 rts ;** Close channel [D227] ; used: AX CloseChannel lda SA ; secondary address cmp #$0F ; 15? beq B_D259 ; yes, ready -> B_D22E ldx SA lda LINTAB,X ; channel number cmp #$FF ; associated? beq B_D259 ; no, -> 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 ; free Buffer [AX] 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 [D25A] ; used: AX FreeBuffer 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 ; erase buffer allocation register 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 ; erase buffer in allocation register 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 ; erase buffer in allocation register B_D28D rts ;** Get a free buffer [D28B] ; used: AX GetBuffer tya ; save Y pha jsr FindBuffer ; [AXY] bpl B_D2A3 ; found one, -> jsr StealBuffer ; [AXY] 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 ; restore Y txa rts ;** Find a free buffer [D2BA] ; out: N flag ; X = buffernumber ; used: AXY FindBuffer 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 ; reset N flag B_D2D9 rts ;** Check if a buffer is free [D2DA] ; used: AX ChkBufFree ldx CURCHN lda BUF0CH1zp,X ; buffer free? bmi B_D2E9 ; yes, -> txa clc adc #$07 ; alternative buffer tax lda BUF0CH1zp,X ; free? bpl B_D2D9 ; no, -> B_D2E9 cmp #$FF ; free? beq B_D2D9 ; yes, -> pha lda #$FF sta BUF0CH1zp,X ; mark as free pla ;** Clear allocation register of the freed buffer [D2F3] ; in: A = buffer number ; out: - ; used: AX ClrAllocReg and #7 tax lda PowersOf2,X eor #$FF ; invert bits and BUFUSEL sta BUFUSEL rts ;** Steal the less recently used inactive buffer [D339] ; used: AXY StealBuffer lda TEMP0 pha ; ??? needed to save TEMP0 ??? 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 ; get byte in output register [D3AA] ; used: AXY NxtByteFile ldx CURCHN ; channel number jsr CheckREL ; check file type [AX] 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 [AX] 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 [AX] cmp #$04 ; REL file or direct access? bcc B_D400 ; no, -> J_D3DE jsr GetBufChanNum ; get buffer and channel number [AXY] lda BUFTABzp,X ; buffer pointer cmp ENDPNT,Y ; equal end pointer? bne PrepByteBuf ; no, -> lda #$00 sta BUFTABzp,X ; buffer pointer to zero ;** [D3EC] ; used: A PrepByteBuf inc BUFTABzp,X ; increment buffer pointer ;** [D3EE] GetByteBuf 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 [AXY] 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 [AXY] jmp J_D403 B_D414 jsr SetBufPointer ; set buffer pointer [AX] 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 [A] lda #$00 jsr OK2Buffer2 ; create 'ok' message [AXY] dec ERRPTR ; set buffer pointer back lda #$80 ; set READ flag bne B_D445 ; always -> B_D433 jsr GetByteFromBuf ; get byte from buffer [AXY] sta DATA ; into output register bne J_D443 ; Byte out J_D43A lda #$D4 ; error buffer jsr SetBufPointer3 ; set buffer pointer in front of error ; 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 B_D44A rts ;** Read block ; used: AX ReadSector lda #$80 ; command code for reading bne B_D466 ;** Write block WriteSector lda #$90 ; command code for writing B_D466 sta CMD ; save code lda JOBNUM jsr Par2DiskCtrl2 ; parameter to disk controller [AX] ldx JOBNUM jmp J_D593 ; execute command ;** Write dir block ; used: AXY WrDirSector jsr GetSector ; get track and sector number [AXY] lda #$01 sta TEMP0 ; a block jsr FreeSecAlloc ; find free block in BAM [AXY] lda #$00 jsr SetBufPointer3 ; buffer pointer to zero [AX] jsr UseLBA2Buf jsr WriteBlock ; write block to disk [AX] jsr VerifyExec ; and verify [AX] lda #$00 jsr SetBufPointer3 ; buffer pointer to zero [AX] B_D4BB jsr Write2Buf ; fill buffer with zeroes [AX] bne B_D4BB lda #$FF jsr Write2Buf ; $FF as number of bytes [AX] jsr Write2Buf ; dummy [AX] jsr Write2Buf ; dummy [AX] jmp Write2Buf ; last track [AX] ;** Allocate buffer and read block ; used: AXY ReadSeqFile lda #$01 ; file type to sequential ReadXxxFile sta TYPE lda #$11 ; 17 sta SA ; secondary address jsr RdBlkAllocBuf ; alloc buffer and read block [AXY] lda #$04 ; data starts at byte 4 ;** Set buffer pointer [D4C8] ; in: A ; used: AX SetBufPointer3 sta TEMP0 ; save pointer jsr GetBufNumber ; get buffer number [AX] 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 [D4DA] Close17_18 lda #$11 ; 17 sta SA jsr CloseChannel ; close channel [AX] lda #$12 ; 18 sta SA jmp CloseChannel ; close channel [AX] ;** Set buffer pointer [D4E8] ; used: AX SetBufPointer jsr GetBufNumber ; get buffer number [AX] SetBufPointer2 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 [D4F6] ; in: A, offset inside buffer ; out: A = data byte ; used: AXY GetAthByte sta TEMP2 ; pointer lo jsr GetBufNumber ; get buffer number [AX] tax lda BufferAddress,X ; hi-byte buffer address sta TEMP3 ; pointer hi ldy #$00 lda (TEMP2),Y ; get byte from buffer rts ;** Check sector number ; in: X = buffer number ; out: A = command code ; used: A,X ChkSector lda CMD ; plus command code ChkSector2 pha ; save stx JOBNUM ; buffer number txa asl A ; times 2 asl A ; times 2 tax ; #### what about checking the sector using the SEEK command? ; jsr SeekSector ; beq xxxx ; sector exists, -> ; check if sector = 0 lda TraSecLBA,X bne L_xx06 lda TraSecLBA+1,X bne L_xx06 lda TraSecLBA+2,X bne L_xx06 lda TraSecLBA+3,X beq B_D54A ; sector 0 not allowed, -> ; Check if sector number is not too big L_xx06 lda TraSecLBA+3,X cmp DiskParms+3 bne L_xx07 lda TraSecLBA+2,X cmp DiskParms+2 bne L_xx07 lda TraSecLBA+1,X cmp DiskParms+1 bne L_xx07 lda TraSecLBA,X cmp DiskParms beq B_D57A L_xx07 bcs B_D54A ; sector number too big, -> ; Sector = OK 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 ; Wrong sector number B_D54A jsr TraSec2UseLBA B_D54D lda #$66 jmp CreErrorMsg ; 66, 'illegal sector' [AXY] ;** Check for valid track and sector numbers [D55F] ; #### what about checking the sector using the SEEK command? ; check if sector = 0 ChkSector3 lda UseLBA bne B_D566 lda UseLBA+1 bne B_D566 lda UseLBA+2 bne B_D566 lda UseLBA+3 beq B_D54D ; sector 0 not allowed, -> ; Check if sector number is not too big B_D566 lda UseLBA+3 cmp DiskParms+3 bne B_D567 lda UseLBA+2 cmp DiskParms+2 bne B_D567 lda UseLBA+1 cmp DiskParms+1 bne B_D567 lda UseLBA cmp DiskParms beq B_D569 B_D567 bcs B_D54D ; sector number too big, -> ; Sector = OK B_D569 rts ;** Read block ; used: AX DskReadBlock lda #$80 ; code for read bne J_D58C ;** Write block ; used: AX DskWriteBlock lda #$90 ; code for write J_D58C ldx JOBNUM ; buffer number P_D590 sta CMD J_D593 lda CMD ; command code jsr ChkSector2 ; check track and sector [AX] ;** Verify execution [D598] ; used: AX VerifyExec lda JOBSZP,X ; command code (bit 7) in register? bmi VerifyExec ; yes, wait -> cmp #$02 bcc B_D5C2 ; > 2 = error-free execution, -> B_D5BA bit JOBRTN bmi B_D5C2 lda JOBSZP,X ; return message jmp PrepErrMsg ; set error message [AX] B_D5C2 clc ; execution ended ldx #$00 stx JOBRTN ; erase error flag rts ;** Transmit param to disk controller [D6CF] ; used: AX Par2DiskCtrl jsr GetBufNumber ; get buffer number [AX] Par2DiskCtrl2 asl A asl A tax lda UseLba sta TraSecLBA,X lda UseLba+1 sta TraSecLBA+1,X lda UseLba+2 sta TraSecLBA+2,X lda UseLba+3 sta TraSecLBA+3,X rts ;** Enter file in dir [D6E4] ; used: AXY CreDirEntry lda SA ; secondary address pha lda CURCHN ; channel number pha lda UseLBA pha lda UseLBA+1 pha lda UseLBA+2 pha lda UseLBA+3 pha lda #$11 sta SA ; secondary address 17 jsr GetSector ; get track and sector number [AXY] lda TYPE ; file type pha ; save B_D715 lda DelSecLBA+3 ; sector number in directory bmi B_D726 ; if not used, -> cmp UseLBA+3 ; equal sector number? bne B_D71E lda DelSecLBA+2 cmp UseLBA+2 bne B_D71E lda DelSecLBA+1 cmp UseLBA+1 bne B_D71E lda DelSecLBA cmp UseLBA beq J_D73D ; yes, -> B_D71E lda DelSecLBA+3 sta UseLBA+3 lda DelSecLBA+2 sta UseLBA+2 lda DelSecLBA+1 sta UseLBA+1 lda DelSecLBA sta UseLBA jsr ReadSector ; read block [AX] jmp J_D73D B_D726 lda #$01 sta DELIND ; pointer to one jsr Nxt_File_Dir ; find next entry in directory [AXY] bne J_D73D ; found? B_D730 jsr WrDirSector ; write directory block [AXY] jsr UseLBA2DelSec lda #4 sta DELIND ; pointer to 4 J_D73D lda DELIND jsr SetBufPointer3 ; set buffer pointer [AX] 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 [AX] pla sta FilLBA+3 jsr Write2Buf ; in buffer [AX] pla sta FilLBA+2 jsr Write2Buf ; in buffer [AX] pla sta FilLBA+1 jsr Write2Buf ; in buffer [AX] pla sta FilLBA jsr Write2Buf ; in buffer [AX] jsr GetBufNumber ; get buffer number [AX] tay lda FILTBL tax lda #$10 ; 16, length of filename jsr NamFil2DirBuf ; write filename in buffer [AXY] ldy #$10 lda #$00 B_D76F sta (DIRBUF),Y ; fill with zeroes at position 16 iny cpy #29 ; position 29 already? bcc B_D76F ; no, -> lda TYPE ; file type cmp #$04 ; REL file? bne B_D790 ; no, -> ; store the side sector in directory entry ldy #$10 lda SidSecLBA sta (DIRBUF),Y iny lda SidSecLBA+1 sta (DIRBUF),Y iny lda SidSecLBA+2 sta (DIRBUF),Y iny lda SidSecLBA+3 sta (DIRBUF),Y iny lda RECSIZ ; record length sta (DIRBUF),Y ; in directory B_D790 jsr WriteSector ; write block [AX] pla sta CURCHN ; channel number tax pla sta SA ; secondary address ; X := X * 4 txa pha ; save original value asl asl tax lda DelSecLBA sta DIRSECP0 sta DSecLBA,X lda DelSecLBA+1 sta DIRSECP0+1 sta DSecLBA+1,X lda DelSecLBA+2 sta DIRSECP0+2 sta DSecLBA+2,X lda DelSecLBA+3 sta DIRSECP0+3 sta DSecLBA+3,X pla tax ; restor X lda DELIND sta BUFPTR sta DIND,X lda TYPE ; file type sta COMFLG rts ;** OPEN command, secondary addres <> 15 OPEN_N15 lda #$11 sta PortA2 ; output code 11 lda SA ; secondary address sta TEMPSA jsr ChkLineLength ; get line length, erase flags [AXY] stx INSTRU ldx CMDBUF ; first character from buffer lda TEMPSA ; secondary address bne B_D7F3 ; not equal 0 (LOAD)? cpx #'*' bne B_D7F3 lda PrgLBA+3 ; already program loaded before? bmi B_D81C ; no, -> lda #$02 sta COMFLG ; set data type to PRG ldx #3 L_D7E0 lda PrgLba,X ; last used sector sta UseLba,X dex bpl L_D7E0 jsr LedOn ; turn LED on jsr RdBlkAllocBuf ; allocate buffer, read block [AXY] lda #$04 ; file type PRG (*2) J_D7EB ldx CURCHN ; channel number sta DIACFLab,Y ; set flag jmp Out_Err_Msg ; done B_D7F3 cpx #'$' ; directory? bne B_D815 ; no, -> lda #$12 sta PortA2 ; output code 12 lda TEMPSA ; secondary address bne B_D7FF ; not equal to zero? jmp J_DA55 ; OPEN $ ;** Treat directory as SEQ file B_D7FF lda #$13 sta PortA2 ; output code 13 jsr ChkInputLine ; analyze line to end [AXY] lda DirLBA sta UseLBA lda DirLBA+1 sta UseLBA+1 lda DirLBA+2 sta UseLBA+2 lda DirLBA+3 sta UseLBA+3 jsr RdBlkAllocBuf ; allocate buffer, read block [AXY] lda #$02 ; file type SEQ (*2) jmp J_D7EB ; continue as above B_D815 lda #$14 sta PortA2 ; output code 14 cpx #"#" ; buffer reservation? bne B_D81C ; no, -> jmp J_CB84 B_D81C lda #$02 sta TYPFLG ; file type PRG ; #### needed? jsr LoadBAM ; load BAM [AXY] B_D82B jsr ChkForColon ; analyze line, colon found? [AXY] bne B_D834 ; no, -> ldx #$00 beq B_D840 ; always -> B_D834 txa ; comma found? beq B_D83C ; no, -> jmp Error30 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 [AXY] inx stx F2CNT ; comma counter jsr GetDrvNum ; get drive number [AXY] jsr LedOn jsr SrchDirEntry ; find file entry in directory [AXY] 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 [AY] inx cpx F1CNT ; additional comma? bcs B_D876 ; no, -> cpy #$04 ; REL file? beq B_D8B1 ; yes, -> jsr ChkTypeMode ; get file type and control mode [AY] 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 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 #$07 ; get file type and command line sta TYPE lda FilLBA+3 ; last sector? bpl B_D8A7 ; no, -> 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 FilLBA+3 ; used? bpl 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 jmp OpenFile4Write ; [AXY] B_D8D9 lda FilLBA+3 ; first block used? bpl B_D8E1 ; already existing, -> jmp OpenFile4Write ; [AXY] 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 #$07 ; isolate cmp TYPE bne B_D965 ; file type different? cmp #$04 ; REL file? beq B_D965 ; 64, 'file type mismatch' jsr AllocNewSec ; [AXY] lda CURCHN sta WLINDX ; save channel number lda #$11 sta SA jsr OpenChan4Read ; open read channel [AX] lda INDEX jsr SetBufPointer3 ; set buffer pointer for directory [AX] ldy #$00 lda (DIRBUF),Y ; file type ora #$20 ; set bit 5, open file sta (DIRBUF),Y ldy #$1A jsr UseLBA2DirBuf lda WLINDX ; channel number asl asl tax ; X := X * 4 lda DIRSECP0 sta DSecLBA,X lda DIRSECP0+1 sta DSecLBA+1,X lda DIRSECP0+2 sta DSecLBA+2,X lda DIRSECP0+3 sta DSecLBA+3,X ldx WLINDX ; channel number lda BUFPTR sta DIND,X jsr GetSector ; get track and sector number [AXY] jsr WriteSector ; write block [AX] jmp J_D9EF ; prepare track, sector, and drive ; number J_D940 lda FilLBA+3 ; file erased? bpl 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 B_D95C lda COMFLG and #$07 ; 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 ; file type and #$4F ; mark file as open sta (DIRBUF),Y lda SA pha lda #$11 ; READ sta SA ; channel 17 jsr GetSector ; get track and sector number [AXY] jsr WriteSector ; write block [AX] pla sta SA ; get channel number back B_D990 jsr OpenFile4Read ; [AXY] lda MODE ; control mode cmp #$02 bne J_D9EF jsr Prep4Append ; [AXY] jmp Out_Err_Msg ; done ;** Open file for reading ; used: AXY OpenFile4Read ldy #DirSideSec B_D9A2 lda (DIRBUF),Y ; track sta SidSecLBA-DirSideSec,Y iny cpy #DirSideSec+4 bne B_D9A2 iny lda (DIRBUF),Y ; record length ldx RECSIZ ; last record length 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' B_D9C3 ldx F2PTR txa asl asl tax jsr FilLBA2UseLBA2 jsr RdBlkAllocBuf ; [AXY] ldy CURCHN ldx F2PTR lda BUFPTR,X sta DIND,Y tya asl asl tay txa asl asl tax lda DIRSECP0,X sta DSecLBA,Y lda DIRSECP0+1,X sta DSecLBA+1,Y lda DIRSECP0+2,X sta DSecLBA+2,Y lda DIRSECP0+3,X sta DSecLBA+3,Y rts ;** Open file for writing ; used: AXY OpenFile4Write jsr AllocNewSec ; [AXY] jsr CreDirEntry ; [AXY] J_D9EF lda SA ; channel number cmp #$02 bcs B_DA06 jsr GetSector2 ; [AXY] lda UseLBA sta PrgLBA lda UseLBA+1 sta PrgLBA+1 lda UseLBA+2 sta PrgLBA+2 lda UseLBA+3 sta PrgLBA+3 B_DA06 jmp Out_Err_Msg ;** Check file type and control mode ; in: X = place behind comma ; used: AY ChkTypeMode ldy FILTBL,X ; pointer in command line lda CMDBUF,Y ; get characters from line ldy #$04 B_DA11 dey bmi B_DA1C cmp RWAM,Y ; control modes 'R', 'W', 'A', 'M' bne B_DA11 sty MODE ; save B_DA1C ldy #$05 B_DA1E dey bmi B_DA29 cmp FileTypes2,Y ; file types 'D','S','P','U','L' bne B_DA1E sty TYPE ; save B_DA29 rts ;** Preparation for append [DA2A] ; used: AXY Prep4Append jsr OpenChnGetByt2 ; open chan to read, get byte [AXY] lda #$80 jsr ChkChanBit ; last byte? [A] beq Prep4Append ; no, -> jsr GetNxtSector ; get track and sector number [AXY] ldx UseLBA ; sector number inx txa bne B_DA42 ; not $FF? jsr Buffer2Disk ; close buffer, write block [AXY] lda #$02 ; #### 4? B_DA42 jsr SetBufPointer3 ; buffer pointer to 2 [AX] 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 [DA55] J_DA55 lda #$0C ; command number 12 sta INSTRU ldx CMDSIZ dex ; only "$" ? beq B_DA6D ; yes, -> dex bne B_DA86 lda CMDBUF+1 ; second character jsr ChkDriveNum ; check drive number [A] bmi B_DA86 ; not 0 or 1? B_DA6D 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 ":" [AXY] bne B_DA90 ; not found, -> jsr CLR_Flg_inp ; erase flags [AXY] ldy #$03 B_DA90 dey dey sty FILTBL ; pointer to drive number in command jsr ChkWildcard ; analyze line [AXY] jsr ChkFileType ; [AY] jsr GetDrvNum2 ; get drive number [AXY] B_DA9E jsr LedOn jsr DirHeader ; [AXY] jsr SrchDirEntry ; load directory [AXY] jsr LoadDir ; [AXY] jsr GetByteFromBuf ; get byte from buffer [AXY] 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 [DAC0] ; used: AXY Close lda SA ; secondary address bne B_DAD4 ; not zero? lda #$00 ; secondary address 0, LOAD sta DIRLST jsr CloseChannel ; close channel [AX] B_DAD1 jmp Close17_18 ; close intern channels 17 & 18 [AX] B_DAD4 cmp #$0F ; 15 beq B_DAEC ; yes, close all channels jsr CloseFile ; close file [AXY] lda SA ; secondary address cmp #$02 bcc B_DAD1 ; smaller than 2? lda ERWORD bne B_DAE9 jmp Out_Err_Msg ; termination B_DAE9 jmp J_C1AD ; Close file B_DAEC lda #$0E ; 14 sta SA ; secondary address B_DAF0 jsr CloseFile ; close file [AXY] dec SA ; next secondary address bpl B_DAF0 lda ERWORD bne B_DAFF jmp Out_Err_Msg ; termination B_DAFF jmp J_C1AD ;** Close file [DB02] ; used: AXY CloseFile 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 [AX] cmp #$07 ; direct access? beq B_DB26 ; yes, -> cmp #$04 ; REL file? beq B_DB2C ; yes, -> jsr OpenChan4Write ; channel for writing open [AXY] bcs B_DB29 ; no file for writing? jsr WriteLastSec ; write last block [AXY] jsr WriteDirEntry ; write entry in directory and block ; [AXY] B_DB26 jsr WriteBam ; write BAM [AXY] B_DB29 jmp CloseChannel ; close channel [AX] B_DB2C jsr GetBufWrSec ; get buffer number, write block [AX] jsr ChangeBuffer2 ; change buffer [AXY] jsr SetPar2LstRec ; get last side-sector [AX] 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 # of file [AX] 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? [A] beq B_DB5F ; no, -> jsr WriteDirEntry ; enter in directory [AXY] B_DB5F jmp CloseChannel ; close channel [AX] ;** Write last block [DB62] ; used: AXY] WriteLastSec 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 [AX] cmp #$02 bne B_DB76 ; not 2 lda #$0D ; CR jsr Write2Buf ; in buffer [AX] B_DB76 jsr SetBufPointer ; set buffer pointer [AX] cmp #$02 ; now equal to 2? bne B_DB8C ; no, -> jsr ChangeBuffer2 ; change buffer [AXY] 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 [AX] jsr Write2Buf ; write zero in buffer [AX] pla ; second byte = pointer to end jsr Write2Buf ; write in buffer [AX] jsr WriteBlock ; write block to disk [AX] jsr VerifyExec ; and verify [AX] jmp ChangeBuffer2 ; change buffer [AXY] ;** Directory entry [DBA5] ; in: Y ; used: AXY WriteDirEntry lda CURCHN ; channel number sta WLINDX ; save asl asl tax lda SA ; secondary address pha ; save lda DSecLBA,X ; sector number in directory sta UseLBA lda DSecLBA+1,X sta UseLBA+1 lda DSecLBA+2,X sta UseLBA+2 lda DSecLBA+3,X sta UseLBA+3 ldx CURCHN lda DIND,X ; pointer in directory sta INDEX jsr GetBufNumber ; increment buffer number [AX] pha sta JOBNUM jsr ReadSector ; read directory block [AX] 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 [AX] cmp #$04 ; REL file? beq J_DC29 ; yes, -> pha lda (R0),Y and #$8F ; erase bits 4,5, and 6 sta (R0),Y ; in file type iny jsr R0_UseLBA ; [AY] sty TEMP2 ldy #DirReplace+3 lda (R0),Y ; sector number of the file for ; overwriting is valid? bmi B_DC06 ; yes, -> ldy #DirReplace+3 jsr R0_UseLBA ; [AY] jmp Error67 ; 67, 'illegal sector' [AXY] B_DC06 sta IDEtmp3 dey lda (R0),Y sta IDEtmp2 dey lda (R0),Y sta IDEtmp1 dey lda (R0),Y sta IDEtmp0 ; erase sector number of substitute file lda #$00 sta (R0),Y iny sta (R0),Y iny sta (R0),Y iny sta (R0),Y ; set track & sector number of the new file ldy TEMP2 lda IDEtmp3 sta (R0),Y dey lda IDEtmp2 sta (R0),Y dey lda IDEtmp1 sta (R0),Y dey lda IDEtmp0 sta (R0),Y jsr DelSectorChain ; erase all files [AXY] 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 #DirNumSecs 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 [AX] pla sta SA ; secondary address jmp OpenChan4Write ; open channel for writing [AXY] ;** Read block, allocate buffer ; used: AXY RdBlkAllocBuf lda #$01 jsr FindRdChanBuf ; find chan + buffer for read [AXY] jsr ResetPointer ; set pointer [AXY] lda TYPE ; file type pha ; save asl A sta DIACFLzp,X jsr ReadSec2Buf ; read block in buffer [AXY] ldx CURCHN ; channel number lda UseLba+3 ; last track? bpl B_DC65 ; no, -> lda UseLba ; number of used bytes on 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 [AXY] bpl B_DC81 ; found? jmp NoChannel ; 70, 'no channel' B_DC81 ldx CURCHN ; channel number sta SIDSECzp,X ldy #3 B_DC87 lda SidSecLBA,Y sta UseLBA,Y dey bpl B_DC87 jsr Par2DiskCtrl2 ; parameters to disk controller [AX] jsr ReadSector4 ; read side sector [AX] jsr VerifyExec ; and verify [AX] J_DC98 ldx CURCHN ; channel number lda #$02 sta WRIPNT,X ; pointer for writing lda #$00 jsr SetBufPointer3 ; buffer pointer to zero [AX] jsr NxtByte2Out ; find next record [AXY] jmp GetSector2 ; get track and sector number [AXY] B_DCA9 jsr RdNxtBlock2 ; get byte from buffer [AXY] ldx CURCHN ; channel number sta OUTREG,X ; byte in output register lda #$88 ; set flag for READ sta REWRFLzp,X rts ;** Reset pointer ; used: AXY ResetPointer 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 ;** Allocate new block for writing [moved from D486] ; used: AXY AllocNewSecWR lda #$12 ; 18 (WRITE) sta SA ; secondary address ;** Construct a new block [DCDA] ; used: AXY AllocNewSec jsr FreeSecAlloc ; find free sector in BAM [AXY] lda #$01 jsr FindWrChanBuf ; open channel [AXY] jsr Par2DiskCtrl ; parameter to disk controllerr [AX] jsr ResetPointer ; reset pointer [AXY] 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 [AXY] bpl B_DD16 ; found? jmp NoChannel ; 70, 'no channel' B_DD16 ldx CURCHN ; channel number sta SIDSECzp,X ; buffer number for side-sector jsr EraseBuffer ; erase buffer [AY] jsr FreeSecAlloc ; find free block in BAM [AXY] ldx #3 L_dd010 lda UseLBA,X sta SidSecLBA,X dex bne L_dd010 ldx CURCHN ; channel number lda SIDSECzp,X ; buffer number jsr Par2DiskCtrl2 ; parameter to disk controller [AX] lda #$00 jsr SetBufPtrSS2 ; buffer pointer to zero [X] lda #$11 ; 17, number of used bytes #### jsr WrBytSidSec ; [X] lda #$00 jsr WrBytSidSec ; [X] lda #$00 jsr WrBytSidSec ; [X] lda #$80 ; last sector jsr WrBytSidSec ; [X] lda #$00 ; zero jsr WrBytSidSec ; as side-sector number in buffer [X] lda RECSIZ ; record length jsr WrBytSidSec ; in buffer [X] ; write actual sector into buffer jsr UseLBA2WrBSS lda #$10 ; 16 #### jsr SetBufPtrSS2 ; buffer pointer to 16 [X] jsr GetSector2 ; get track and sector number [AXY] ; write sector of first data block into buffer jsr UseLBA2WrBSS jsr WriteSector4 ; write block to disk [AX] jsr VerifyExec ; and check [AX] lda #$02 jsr SetBufPointer3 ; buffer pointer to 2 [AX] ldx CURCHN ; channel number sec lda #$00 sbc RecLength,X ; record length sta WRIPNT,X ; pointer for writing jsr CreateRecords ; [AXY] jsr SetLinkLstRec ; write link bytes in buffer [AXY] jsr WriteSector3 ; write block to disk [AX] jsr VerifyExec ; and check [AX] jsr WriteBam ; write BAM [AXY] jmp J_DC98 ; and done ;** Manipulate flags ; in: A ; used: AX SetFlags ldx CURCHN ; channel number ora DIACFLzp,X ; set flag bne B_DDA3 ; in: A ; used: AX DeleteFlags ldx CURCHN ; channel number eor #$FF and DIACFLzp,X ; erase flag B_DDA3 sta DIACFLzp,X rts ; in: A ; used: A ChkChanBit ldx CURCHN ; channel number and DIACFLzp,X ; test flag rts ;** Verify command code for writing [DDAB] ; out: ZF, set = write command ; used: AX Chk4Write jsr GetBufNumber ; get buffer number [AX] tax lda LSTJOB,X and #$F0 ; isolate command code cmp #$90 ; code for writing? rts ;** Check if the file is open [DDB7] ; used: AXY IsFileOpen 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 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 [DDF1] ; used: AX GetBufWrSec jsr GetBufNumber2 ; get buffer number [AX] bvc B_DDFC ; no REL file? jsr WriteSector3 ; write block [AX] jsr VerifyExec ; and verify [AX] B_DDFC rts ;** Write bytes for following track [DDFD] ; used: AXY WrNxtSecBuf jsr SetBufPtrZero ; set buffer pointer [AXY] jsr UseLBA2DirBuf jmp WrBufNum2Tbl ; set rel-flag [AX] ;** Get following track and sector numbers [DE0C] ; used: AXY GetNxtSector2 jsr SetBufPtrZero ; set buffer pointer [AXY] jmp DirBuf2UseLba ; [AY] ;** Set linker for last block of record [DE19] ; used: AXY SetLinkLstRec jsr SetBufPtrZero ; set buffer pointer [AXY] ldx CURCHN ; channel number lda WRIPNT,X ; pointer in block tax dex ; minus 1 txa sta (DIRBUF),Y ; as pointer in block iny lda #$00 sta (DIRBUF),Y iny lda #$00 sta (DIRBUF),Y iny lda #$80 sta (DIRBUF),Y ; last sector rts ;** Buffer pointer to zero [DE2B] ; out: Y = 0 ; used: AXY SetBufPtrZero jsr GetBufNumber ; get buffer number [AX] 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 sector [DE3B] ; out: Y ; used: AXY GetSector jsr OpenChan4Read ; get channel number [AX] GetSector2 jsr GetBufNumber ; get buffer number [AX] sta JOBNUM ; save asl A asl A ; times 4 tax jsr TraSec2UseLBA txa lsr A tay rts ;** [DE50] WriteSector2 lda #$90 ; command code for writing sta CMD bne B_DE7F ; always -> ReadSector2 lda #$80 ; command code for reading sta CMD bne B_DE7F ; always -> WriteSector3 lda #$90 ; command code for writing sta CMD bne B_DE8B ; always -> WriteSector4 lda #$90 ; command code for writing sta CMD bne B_DE75 ;** [DE73] ; used: AX ReadSector4 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 jsr GetBufNumber ; get buffer number [AX] tax lda #0 ; drive number sta LSTJOB,X B_DE8B jsr GetBufNumber2 ; get buffer number [AX] and #$BF ; erase bit 6 ldx LBUSED ; channel number sta BUF0CH1zp,X ; write in table jsr GetBufNumber ; get buffer number [AX] tax B_DE92 jmp ChkSector ; [AX] ;** Get following track and sector from buffer ; used: AXY GetNxtSector lda #$00 jsr SetBufPointer3 ; buffer pointer to zero [AX] jmp GetByt2UseLba ; [AXY] ;** Coppy buffer contents [DEA5] ; used: AY CopyBuffer 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 a buffer [DEC1] ; in: A = buffer nummer ; used: AY EraseBuffer 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 [DED2] ; used: AXY GetNumSideSec lda #$00 jsr SetBufPtrSS ; buffer pointer to zero [AX] ; #### correct number? ldy #4 ; #### was 2 lda (DIRBUF),Y ; byte 2 contains the side-sector # rts ;** Set buffer pointer to side-sector [DEDC] ; used: AX SetBufPtrSS 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 [DEE9] ; used: X SetBufPtrSS2 pha ; pointer in side-sector jsr SetBufPtrSS ; set buffer pointer [AX] 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 [DEF8] ; used: AXY GetSideSector jsr IsSidSecInBuf ; is side-sector in buffer? [AXY] bmi B_DF0B ; no, -> bvc B_DF12 ; ok ldx CURCHN ; channel number lda SIDSECzp,X ; buffer number jsr ReadSideSec ; read side-sector [AX] jsr IsSidSecInBuf ; and check if in buffer [AXY] bpl B_DF12 ; yes? B_DF0B jsr SetPar2LstRec ; get last side-sector [AX] bit A_FECD+1 ; set V bit rts B_DF12 lda CHNNUM3 ; side-sector and pointer jsr SetBufPtrSS2 ; set pointer in side-sector [X] bit A_FECD ; erase V bit rts ;** Read side-sector [DF1B] ; in: A ; used: AX ReadSideSec sta JOBNUM ; buffer number lda #$80 ; command code for reading sta CMD ; save jsr DirBuf2UseLba ; [AY] lda JOBNUM ; buffer number jsr Par2DiskCtrl2 ; transmit parameter to disk controller ldx JOBNUM ; buffer number jmp J_D593 ; transmit command to disk controller ;** Set buffer pointer in side-sector [DF45] ; used: AX SetPtrSidSec ldx CURCHN ; channel number lda SIDSECzp,X ; buffer number jmp SetBufPointer2 ; set buffer pointer [AX] ;** Calculate number of blocks in a REL file B_DF4C lda #60 ; 60 block pointers per side-sector jsr IncSidSecPtr ; add to $70/$71 [A] ;** [DF51] ; used: AX CalcSecPtrREL dex ; next side-sector? bpl B_DF4C ; yes, -> lda TEMP3 ; pointer value in last block lsr A ; divided by 2 ##### 4 ? lda TEMP4 ; number of the side-sector block jsr IncSidSecPtr ; add to previous sum [A] ;** [DF5C] IncSidSecPtr clc adc TEMP1 sta TEMP1 ; add bcc B_DF65 inc TEMP2 B_DF65 rts ;** Verify side-sector in buffer [DF66] ; used: AXY IsSidSecInBuf jsr GetNumSideSec ; get side-sector number [AXY] cmp CHNNUM2 ; = number of necessary block? bne B_DF7B ; no, -> ldy CHNNUM3 ; pointer in side-sector iny iny iny lda (DIRBUF),Y ; sector in use? bmi B_DF77 ; no, -> 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 adc #3 tay lda #$04 sta DIRBUF lda (DIRBUF),Y ; sector in use? bmi B_DF8F ; no, -> 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 [DF93] ; out: A ; used: AX GetBufNumber 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 [DF9E] ; used: AX GetBufNumber2 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 ;** Chek if the buffer is free ; out: ZF, set = free ; used: AX ChkBufferFree 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 ; in: A ; used: AXY DeactivateBuf 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 ; used: AXY GetNxtRelRec lda #$20 jsr DeleteFlags ; [AX] lda #$80 jsr ChkChanBit ; test bit 7 [A] bne B_E01D ; if 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 [AX] ldx CURCHN ; channel number cmp WRIPNT,X ; buffer pointer smaller than write ; pointer bcc B_DFF6 ; yes, -> jsr WrRdSector ; write block, read next block [AXY] B_DFF6 ldx CURCHN ; channel number lda WRIPNT,X ; write pointer jsr SetBufPointer3 ; set buffer pointer = write pointer ; [AX] lda (BUFTABzp,X) ; byte from buffer sta DATA ; put in output register lda #$20 jsr DeleteFlags ; [AX] jsr SetPtr2NxtRec ; add record length to write pointer ; [AX] ;** [E009] P_E009 pha ; and save bcc B_E034 ; not yet in last block? lda #3 jsr GetAthByte ; does next block exist? [AXY] bpl B_E034 ; yes, -> pla ; pointer ; #### should be 4 because of LBA ptr? cmp #$02 ; = 2 beq B_E02A ; yes, -> B_E018 lda #$80 jsr SetFlags ; set bit 7 [AX] B_E01D jsr GetBufChanNum ; get byte from buffer [AXY] lda BUFTABzp,X ; buffer pointer sta ENDPNT,Y ; as end pointer lda #$0D ; CR sta DATA ; in output register rts B_E02A jsr Ptr2LastChar ; [AXY] ldx CURCHN ; channel number lda #$00 sta WRIPNT,X ; write pointer to zero rts B_E034 pla ;** Set the pointer to the last character ; used: AXY Ptr2LastChar ldx CURCHN ; channel number sta WRIPNT,X ; set write pointer J_E16E ldx CURCHN ; channel number lda WRIPNT,X ; write pointer sta R1 ; save dec R1 cmp #$02 ; A equal 2? bne B_E17E ; no, -> lda #$FF sta R1 B_E17E lda RecLength,X ; record length sta R2 jsr SetBufPointer ; set buffer pointer [AX] ldx CURCHN ; channel number cmp R1 ; buffer pointer > write pointer? bcc B_E1A4 beq B_E1A4 ; no, -> jsr ChangeBuffer2 ; change buffer [AXY] jsr LastCharNot0 ; found? [AXY] bcc B_E19D ; yes, -> ldx CURCHN ; channel number sta ENDPNT,X jmp ChangeBuffer2 ; change buffer [AXY] B_E19D jsr ChangeBuffer2 ; change buffer [AXY] lda #$FF sta R1 B_E1A4 jsr LastCharNot0 ; found last char? [AXY] bcs B_E1AC ; no, -> jsr SetBufPointer ; set buffer pointer [AX] B_E1AC ldx CURCHN ; channel number sta ENDPNT,X ; end pointer rts ;** Find the last char of the record <> 0 ; used: AXY LastCharNot0 jsr SetBufPtrZero ; buffer pointer to zero [AXY] ; Y := 0 ldy R1 B_E1B7 lda (DIRBUF),Y ; byte from buffer bne B_E1C8 ; not zero? dey cpy #$02 ; #### should be 4 because of LBA ptr? bcc B_E1C4 dec R2 bne B_E1B7 B_E1C4 dec R2 clc rts B_E1C8 tya sec rts ;** Write block and read next block ; used: AXY WrRdSector jsr GetDrvNum3 ; get drive number [AX] jsr GetNxtSector ; get track and sector number [AXY] jsr GetBufNumber2 ; get bufer number [AX] bvc B_E05D ; no REL file? jsr WriteSector3 ; write block [AX] jsr ChangeBuffer2 ; change buffer [AXY] lda #$02 jsr SetBufPointer3 ; buffer pointer to 2 [AX] jsr Chk4Write ; command code for writing? [AX] bne B_E07B ; no, -> jsr ReadSector2 ; read block [AX] jmp VerifyExec ; and verify [AX] B_E05D jsr ChangeBuffer2 ; change buffer [AXY] jsr Chk4Write ; command code for writing? [AX] bne B_E06B ; no, -> jsr ReadSector2 ; read block [AX] jsr VerifyExec ; and verify [AX] B_E06B jsr GetNxtSector ; get track and sector number [AXY] lda UseLBA+3 bmi B_E07B ; no following track, -> jsr ChangeBuffer2 ; change buffer [AXY] jsr ReadSector2 ; read block [AX] jmp ChangeBuffer2 ; change buffer [AXY] B_E07B rts ;** Write a byte in a record WrByte2Record jsr WrBufNum2Tbl ; [AX] jsr GetBufNumber ; get buffer number [AX] 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 [AX] B_E0A3 inc BUFTABzp,X ; increment buffer pointer bne B_E0AA ; not zero? jsr WrRdSector ; else write block, read next one [AXY] B_E0AA rts ;** Write byte in REL file [E0AB] J_E0AB lda #$A0 jsr ChkChanBit ; test bits 6 & 7 [A] bne B_E0D9 ; set? J_E0B2 lda DATA ; data byte jsr WrByte2Record ; write in record lda EOIFLG ; end? beq B_E0C8 ; yes, -> rts B_E0BC lda #$20 jsr ChkChanBit ; test bit 5 [A] beq B_E0C8 ; not set lda #$51 ; 51, 'overflow in record' sta ERWORD ; set error flag ;** Fill record with 0s [E0F3] B_E0C8 lda #$20 jsr ChkChanBit ; test bit 5 [A] bne B_E104 ; set? lda #$00 sta DATA ; zero as data byte jsr WrByte2Record ; write in record jmp B_E0C8 ; until record full B_E104 jsr NxtByte2Out ; [AXY] lda ERWORD ; error flag set? beq B_E0D6 ; no, -> jmp OutputErrorMsg ; set error message B_E0D6 jmp OK2Buffer ; error free execution [AXY] 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 [AXY] pla sta DATA lda #$80 jsr DeleteFlags ; erase bit 7 [AX] jmp J_E0B2 ; write byte in file ;** Write buffer number in table [E105] ; used: AX WrBufNum2Tbl lda #$40 jsr SetFlags ; set bit 6 [AX] jsr GetBufNumber2 ; get buffer number [AX] ora #$40 ; set bit 6 ldx LBUSED ; channel number + 7 sta BUF0CH1zp,X ; write in table rts ;** Get byte from REL file ; used: AXY J_E120 lda #$80 jsr ChkChanBit ; test bit 7 [A] bne NoRecord ; if set, -> jsr GetBufChanNum ; get byte from buffer [AXY] lda BUFTABzp,X ; buffer pointer cmp ENDPNT,Y ; compare to end pointer beq NxtByte2Out ; equal? [AXY] inc BUFTABzp,X ; increment buffer pointer bne B_E13B ; not zero? jsr WrRdSector ; write block, read next one [AXY] J_E138 jsr GetBufChanNum ; get byte from buffer [AXY] 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 ; used: AXY NxtByte2Out jsr GetNxtRelRec ; find next record [AXY] jsr GetBufChanNum ; get buffer and channel number [AXY] lda DATA ; data byte jmp J_E13D ; into output register ;** Message "No record present" [E15E] NoRecord 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' ;** Get last side-sector [E1CB] ; used: AXY SetPar2LstRec jsr GetNumSideSec ; get number of the side-sector [AXY] sta CHNNUM2 ; save lda #$04 sta DIRBUF ; pointer to side-sectors ldy #$0F ; #### was 0A bne B_E1DC ; always -> B_E1D8 dey dey dey dey bmi Error67 B_E1DC lda (DIRBUF),Y ; MSB se