;****************************************************************************** ; ; 1541-II ; ; This source code generates the ROM for the 1541-II in the address ; range $E000-$FFFF. The code for this version is: ; ; 251968-03 ; .ba $E000 .by $85 ; sta DATA ; put in output register lda #$20 jsr DeleteFlags ; erase bit 5 jsr SetPtr2NxtRec ; add record length to write pointer SaveRecEnd: pha ; and save bcc A_E034 ; if still inside sector, -> lda #$00 jsr GetAthByte ; does block exist? bne A_E034 ; yes, -> pla ; pointer cmp #$02 ; points to start of sector? beq A_E02A ; yes, -> A_E018: ; [E018] lda #$80 jsr SetFlags ; record not present A_E01D: ; [E01D] jsr GetBufChanNum ; get byte from buffer [D12F] lda BUFTABzp,X ; buffer pointer sta ENDPNT,Y ; as end pointer lda #$0D ; CR sta DATA ; in output register rts A_E02A: ; [E02A] jsr Ptr2LastChar ldx CURCHN ; channel number lda #$00 sta WRIPNT,X ; write pointer to zero rts A_E034: ; [E034] pla ;** Set the pointer to the last character Ptr2LastChar: ; [E035] ldx CURCHN ; channel number sta WRIPNT,X ; set write pointer jmp J_E16E ; continue -> ;** Write block and read next block WrSecRdNxtSec: ; [E03C] jsr GetDrvNum3 ; get drive number jsr GetNxtSector ; get track and sector number jsr GetBufNumber2 ; write buffer to disk? bvc A_E05D ; no, -> jsr WriteSector3 ; write block jsr SwapBuffers2 ; change buffer lda #$02 jsr SetBufPointer3 ; buffer pointer to 2 jsr Chk4Write ; command code for writing? bne A_E07B ; no, -> jsr ReadSector2 ; read block jmp VerifyExec ; and verify A_E05D: ; [E05D] jsr SwapBuffers2 ; change buffer jsr Chk4Write ; command code for writing? bne A_E06B ; no, -> jsr ReadSector2 ; read block jsr VerifyExec ; and verify A_E06B: ; [E06B] jsr GetNxtSector ; get track and sector number lda TRACK ; last sector? beq A_E07B ; yes, -> jsr SwapBuffers2 ; change buffer jsr ReadSector2 ; read block jsr SwapBuffers2 ; change buffer A_E07B: ; [E07B] rts ;** Write a byte in a record WrByte2Record: ; [E07C] jsr WrBufNum2Tbl jsr GetBufNumber ; get buffer number asl A ; times 2 tax lda DATA ; data byte sta (BUFTABzp,X) ; write in buffer ldy BUFTABzp,X ; buffer pointer iny ; increment bne A_E096 ; not equal zero? ldy CURCHN ; channel number lda WRIPNTab,Y ; write pointer beq A_E09E ; equal zero? ldy #$02 ; buffer pointer to 2 A_E096: ; [E096] tya ldy CURCHN ; channel number cmp WRIPNTab,Y ; buffer pointer = write pointer? bne A_E0A3 ; no, -> A_E09E: ; [E09E] lda #$20 jmp SetFlags ; set bit 5 A_E0A3: ; [E0A3] inc BUFTABzp,X ; increment buffer pointer bne A_E0AA ; not zero? jsr WrSecRdNxtSec ; else write block, read next one A_E0AA: ; [E0AA] rts ;** Write byte in REL file WrByte2REL: lda #$A0 jsr ChkFTypeBit ; test bits 5 & 7, at least one set? bne A_E0D9 ; yes, -> J_E0B2: ; [E0B2] lda DATA ; data byte jsr WrByte2Record ; write in record lda EOIFLG ; end? beq A_E0C8 ; yes, -> rts A_E0BC: ; [E0BC] lda #$20 jsr ChkFTypeBit ; test bit 5 = overflow beq A_E0C8 ; not set lda #$51 ; 51, 'overflow in record' sta ERWORD ; set error flag A_E0C8: ; [E0C8] jsr FillUpZeros ; fill remainder with zeroes jsr NxtByte2Out lda ERWORD ; error flag set? beq A_E0D6 ; no, -> jmp OutputErrorMsg ; set error message A_E0D6: ; [E0D6] jmp OK2Buffer ; error free execution A_E0D9: ; [E0D9] and #$80 ; new record needed? bne A_E0E2 ; yes, -> lda EOIFLG ; EOI set? beq A_E0BC ; yes, -> rts A_E0E2: ; [E0E2] lda DATA ; data byte pha jsr ExpandSidSec ; expand side-sector pla sta DATA lda #$80 jsr DeleteFlags ; erase bit 7 jmp J_E0B2 ; write byte in file ;** Fill record with zeros FillUpZeros: lda #$20 jsr ChkFTypeBit ; record full? bne A_E104 ; yes, -> lda #$00 sta DATA ; zero as data byte jsr WrByte2Record ; write in record jmp FillUpZeros ; until record full A_E104: ; [E104] rts ;** Write buffer number in table WrBufNum2Tbl: ; [E105] lda #$40 jsr SetFlags ; set bit 6 jsr GetBufNumber2 ; get buffer number ora #$40 ; set bit 6 ldx LstUsedBuf sta BUF0CH1zp,X ; write in table rts ClrDirtyFlg: jsr GetBufNumber2 ; get buffer number and #$BF ; erase bit 6 ldx LstUsedBuf ; channel number sta BUF0CH1zp,X ; write in table rts ;** Get byte from REL file GetByteREL: lda #$80 jsr ChkFTypeBit ; record available? bne NoRecord ; no, -> jsr GetBufChanNum ; [D12F] lda BUFTABzp,X ; buffer pointer cmp ENDPNT,Y ; compare to end pointer, same? beq NxtByte2Out ; yes, -> inc BUFTABzp,X ; increment buffer pointer, zero? bne A_E13B ; no, -> jsr WrSecRdNxtSec ; write block, read next one J_E138: ; [E138] jsr GetBufChanNum ; [D12F] A_E13B: ; [E13B] lda (BUFTABzp,X) J_E13D: ; [E13D] sta OUTREG,Y ; in output register lda #$89 sta REWRFLab,Y ; set EOI, READ and WRITE flag lda BUFTABzp,X ; buffer pointer cmp ENDPNT,Y ; compare to end pointer beq A_E14D ; same? rts A_E14D: ; [E14D] lda #$81 sta REWRFLab,Y ; set flag for end rts ;** First byte of next record int A NxtByte2Out: ; [E153] jsr GetNxtRelRec ; find next record jsr GetBufChanNum ; get buffer and channel number [D12F] lda DATA ; data byte jmp J_E13D ; into output register ;** Message "No record present" NoRecord: ; [E15E] ldx CURCHN ; channel number lda #$0D ; CR sta OUTREG,X ; into output register lda #$81 sta REWRFLzp,X ; set flag for end lda #$50 jsr OutputErrorMsg ; 50, 'record not present' ;** Set the pointer to the last character (part 2) J_E16E: ; [E16E] ldx CURCHN ; channel number lda WRIPNT,X ; write pointer sta R1 ; save dec R1 cmp #$02 ; write pointer = 2? bne A_E17E ; no, -> lda #$FF sta R1 A_E17E: ; [E17E] lda RecLength,X ; record length sta R2 jsr SetBufPointer ; set buffer pointer ldx CURCHN ; channel number cmp R1 ; buffer pointer > write pointer? bcc A_E1A4 beq A_E1A4 ; no, -> jsr SwapBuffers2 ; change buffer jsr LastCharNot0 ; found last char? bcc A_E19D ; no, -> ldx CURCHN ; channel number sta ENDPNT,X jmp SwapBuffers2 ; change buffer A_E19D: ; [E19D] jsr SwapBuffers2 ; change buffer lda #$FF sta R1 A_E1A4: ; [E1A4] jsr LastCharNot0 ; found last char? bcs A_E1AC ; yes, -> jsr SetBufPointer ; set buffer pointer A_E1AC: ; [E1AC] ldx CURCHN ; channel number sta ENDPNT,X ; end pointer rts ;** Find the last char of the record <> 0 LastCharNot0: ; [E1B2] jsr SetBufPtrZero ; buffer pointer to zero ldy R1 A_E1B7: ; [E1B7] lda (DIRBUF),Y ; not zero? bne A_E1C8 ; yes, -> dey ; previous byte cpy #$02 ; out of data? bcc A_E1C4 ; yes, -> dec R2 ; original record length bne A_E1B7 A_E1C4: ; [E1C4] dec R2 clc ; not found rts A_E1C8: ; [E1C8] tya sec ; found rts ;** Get last side-sector SetPar2LstSSec: ; [E1CB] jsr GetNumSideSec ; get number of the side-sector sta NumSidSec ; save lda #$04 sta DIRBUF ; pointer to side-sectors ldy #$0A bne A_E1DC ; always -> A_E1D8: ; [E1D8] dey dey bmi Error67 A_E1DC: ; [E1DC] lda (DIRBUF),Y ; track number of the previous block beq A_E1D8 ; if zero, -> next try tya lsr A ; divide by 2 cmp NumSidSec ; = number of the actual block? beq A_E1EF ; yes, -> sta NumSidSec ; else save all numbers ldx CURCHN ; channel number lda SIDSECzp,X ; buffer number jsr ReadSideSec ; read block A_E1EF: ; [E1EF] ldy #$00 sty DIRBUF ; buffer pointer lda (DIRBUF),Y ; track number bne Error67 ; another block? iny lda (DIRBUF),Y ; sector number = end pointer tay dey sty PtrSideSec ; save end pointer tya jmp SetBufPtrSS2 ; set buffer pointer ;** Error67: ; [E202] lda #$67 jsr CreErrorMsg ; 67, 'illegal track or sector' ;** P - Position command Position: ; [E207] jsr ChkLineLength ; verify lines lda CMDBUF+1 ; secondary address sta SA jsr OpenChan4Read ; find channel number bcc A_E219 ; found? lda #$70 jsr OutputErrorMsg ; 70, 'no block' A_E219: ; [E219] lda #$A0 jsr DeleteFlags ; erase bits 6 & 7 jsr CheckREL ; verify if 'REL'-file beq A_E228 ; yes, -> lda #$64 jsr OutputErrorMsg ; 64, 'file type mismatch' A_E228: ; [E228] lda DIACFLzp,X and #$01 sta DRVNMB ; drive number lda CMDBUF+2 ; record number lo sta RECL,X lda CMDBUF+3 ; record number hi sta RECH,X ldx CURCHN ; channel number lda #$89 sta REWRFLzp,X ; READ and WRITE flag lda CMDBUF+4 ; byte-pointer zero? beq A_E253 ; yes, -> sec sbc #$01 beq A_E253 cmp RecLength,X ; smaller then record length? bcc A_E253 ; yes, -> lda #$51 sta ERWORD ; 51, 'overflow in record' lda #$00 A_E253: ; [E253] sta RecordPos jsr SetPtrRelFile ; calculate pointer in REL file jsr GetSideSector ; does side-sector exist? bvc A_E265 ; yes, -> lda #$80 jsr SetFlags ; set bit 7 jmp NoRecord ; 50, 'record not present' A_E265: ; [E265] jsr ChkRecordPos lda #$80 jsr ChkFTypeBit ; record present? beq A_E272 ; yes, -> jmp NoRecord ; 50, 'record not present' A_E272: ; [E272] jmp Out_Err_Msg ; done ;** Check record position ChkRecordPos: jsr Record2Buffer lda RelPointer ; pointer in REL file jsr SetBufPointer3 ; set buffer pointer ldx CURCHN ; channel number lda RecLength,X ; record length sec sbc RecordPos ; result positive? bcs A_E289 ; yes, -> jmp Error67 ; 67, 'illegal track or sector' A_E289: ; [E289] clc ; ## not needed adc RelPointer ; overflow? bcc A_E291 ; no, -> adc #$01 ; plus 2 sec A_E291: ; [E291] jsr SaveRecEnd jmp J_E138 ; get byte from buffer E_E297: ; [E297] lda #$51 jsr OutputErrorMsg ; 51, 'overflow in record' ;** Write record into the buffer Record2Buffer: ; [E29C] lda DIRBUF ; buffer pointer lo sta R3 lda DIRBUF+1 ; buffer pointer hi sta R4 jsr CompTraSec ; same? bne A_E2AA ; no, -> rts A_E2AA: ; [E2AA] jsr GetBufWrSec jsr GetNxtTraSec lda TRACK ; last sector? beq A_E2C2 ; yes, -> jsr CompTraSec2 ; compare track and sector number bne A_E2BF ; not equal? jsr SwapBuffers2 ; change buffer jmp ChkBufFree A_E2BF: ; [E2BF] jsr ChkBufFree A_E2C2: ; [E2C2] ldy #$00 lda (R3),Y ; track sta TRACK iny lda (R3),Y ; and sector of the next block sta SECTOR jmp J_D0AF ; read block ;** Comp sectors CompTraSec: ; [E2D0] jsr GetSector2 CompTraSec2: ; [E2D3] ldy #$00 lda (R3),Y ; track number cmp TRACK ; compare beq A_E2DC rts A_E2DC: ; [E2DC] iny lda (R3),Y ; sector number cmp SECTOR ; compare rts ;** Divide data blocks into records CreateRecords: ; [E2E2] jsr SetBufPtrZero ; set buffer pointer ;* Erase buffer ldy #$02 lda #$00 A_E2E9: ; [E2E9] sta (DIRBUF),Y iny bne A_E2E9 jsr SetPtr2NxtRec ; set pointer to next record A_E2F1: ; [E2F1] sta WRIPNT,X tay lda #$FF sta (DIRBUF),Y ; $FF as 1st character in record jsr SetPtr2NxtRec ; done in this block? bcc A_E2F1 ; yes, -> L_E2FD: ; [E2FD] bne A_E303 ; if block full, -> lda #$00 sta WRIPNT,X ; write pointer to zero A_E303: ; [E303] rts ;** Set pointer to next record SetPtr2NxtRec: ; [E304] ldx CURCHN ; channel number lda WRIPNT,X ; write pointer equal zero? sec beq A_E318 ; yes, -> clc adc RecLength,X ; result smaller than 256? bcc A_E31B ; yes, -> bne A_E318 ; if > 256, -> A_E312: ; [E312] lda #$02 bit A_FECC ; set the Zero flag, needed at L_E2FD rts A_E318: ; [E318] adc #$01 ; add two sec A_E31B: ; [E31B] rts ;** Expand side-sector ExpandSidSec: ; [E31C] jsr GetDrvNum3 ; get drive number jsr SetPar2LstSSec ; get last side-sector jsr Record2Buffer jsr Look4FreeBuf lda PtrSideSec sta R1 lda NumSidSec ; side-sector number sta R0 lda #$00 sta R2 lda #$00 sta RecordPos jsr SetPtrRelFile ; calculate side-sector number and ; pointer J_E33B: ; [E33B] jsr NumBlocksFree ; number of free blocks ldy CURCHN ; channel number ldx RecLength,Y ; record length dex txa clc adc RelPointer ; plus pointer in data block bcc A_E355 inc PtrSideSec inc PtrSideSec ; increment pointer to end by 2 bne A_E355 inc NumSidSec ; increment side-sector number lda #$10 sta PtrSideSec ; set pointer to 16 A_E355: ; [E355] lda R1 clc adc #$02 jsr SetBufPtrSS2 ; set buffer pointer for side-sector lda NumSidSec ; side-sector number cmp #$06 bcc A_E368 ; smaller than 6? A_E363: ; [E363] lda #$52 jsr OutputErrorMsg ; 52, 'file too large' A_E368: ; [E368] lda PtrSideSec ; end pointer sec sbc R1 ; minus last end pointer bcs A_E372 sbc #$0F ; minus 16 clc A_E372: ; [E372] sta TEMP3 lda NumSidSec ; side-sector number sbc R0 ; minus last side-sector number sta TEMP4 ; save ldx #$00 stx TEMP1 ; erase sum for calculation stx TEMP2 tax jsr CalcSecPtrREL ; calculate block # of REL file [DF51] lda TEMP2 bne A_E38F ldx TEMP1 dex bne A_E38F inc R2 A_E38F: ; [E38F] cmp NBTEMP1 ; block number of REL file bcc A_E39D ; greater than free blocks on disk? bne A_E363 ; 52, 'file too large' lda NBTEMP0 cmp TEMP1 bcc A_E363 ; 52, 'file too large' A_E39D: ; [E39D] lda #$01 jsr GetAthByte ; get byte from buffer clc adc #$01 ; plus 1 ldx CURCHN sta WRIPNT,X ; as write pointer jsr FindAllocSec ; find free block in BAM jsr WrNxtSecBuf ; track and sector in buffer lda R2 bne A_E3C8 ; only one block needed? jsr WriteSector3 ; write block A_E3B6: ; [E3B6] jsr SwapBuffers2 ; change buffer jsr Par2DiskCtrl ; transmit parameter to disk controller jsr FindAllocSec ; find free block in BAM jsr WrNxtSecBuf ; track and sector in buffer jsr CreateRecords jmp J_E3D4 A_E3C8: ; [E3C8] jsr SwapBuffers2 ; change buffer jsr Par2DiskCtrl ; transmit parameter to disk controller jsr CreateRecords jsr SetLinkLstRec ; zero byte and end pointer in buffer J_E3D4: ; [E3D4] jsr WriteSector3 ; write block jsr GetNxtTraSec ; get track and sector lda TRACK ; track pha lda SECTOR ; and sector pha ; save jsr GetSector2 ; get track and sector from disk lda SECTOR ; controller pha lda TRACK ; save track and sector pha jsr SetPtrSidSec ; set buffer pointer for side-sector tax bne A_E3F9 ; pointer not zero? jsr WriteSideSec2 ; write side-sector lda #$10 jsr SetBufPtrSS2 ; buffer pointer to 16 inc R0 ; increment side-sector number A_E3F9: ; [E3F9] pla jsr WrBytSidSec ; track in side-sector pla jsr WrBytSidSec ; sector in side-sector pla sta SECTOR ; sector pla sta TRACK ; and get track back beq A_E418 ; no more blocks? lda R0 ; side-sector number cmp NumSidSec ; changed? bne A_E3B6 ; yes, -> jsr SetPtrSidSec ; set buffer pointer in side-sector cmp PtrSideSec ; end pointer bcc A_E3B6 ; smaller? beq A_E3C8 ; same A_E418: ; [E418] jsr SetPtrSidSec ; set buffer pointer in side-sector pha lda #$00 jsr SetBufPtrSS ; buffer pointer to zero lda #$00 tay sta (DIRBUF),Y ; zero as track number iny pla ; end pointer sec sbc #$01 ; minus one sta (DIRBUF),Y ; as sector jsr WriteSector4 ; write block jsr VerifyExec ; and verify jsr WriteBam ; update BAM jsr SetPtrRelFile ; update pointer for REL file jsr SwapBuffers2 ; change buffer jsr GetSideSector ; right side-sector? bvs A_E444 ; no, -> jmp ChkRecordPos A_E444: ; [E444] lda #$80 jsr SetFlags ; set bit 7 lda #$50 jsr OutputErrorMsg ; 50, 'record not present' ;** Write side-sector and allocate new WriteSideSec2: jsr FindAllocSec ; find free block in BAM jsr SwapBuffers2 ; change buffer jsr GetBufWrSec ; write block jsr GetBufNumber ; get buffer number pha jsr EraseBuffer ; erase buffer ldx CURCHN ; channel number lda SIDSECzp,X ; buffer number tay pla tax lda #$10 ; 16 bytes of the side-sector jsr CopyBuffer ; copy in buffer lda #$00 jsr SetBufPtrSS ; buffer pointer to 0, old side-sector ldy #$02 lda (DIRBUF),Y ; side-sector number pha lda #$00 jsr SetBufPointer3 ; buffer pointer to 0, new side-sector pla clc adc #$01 ; increment side-sector number sta (DIRBUF),Y ; and in buffer asl A ; times 2 adc #$04 ; plus 4 sta R3 tay sec sbc #$02 ; minus 2 sta R4 ; same pointer to old side-sector lda TRACK ; track sta R1 sta (DIRBUF),Y ; in buffer iny lda SECTOR ; sector sta R2 sta (DIRBUF),Y ; in buffer ldy #$00 tya sta (DIRBUF),Y ; zero in buffer iny lda #$11 ; 17 sta (DIRBUF),Y ; number of bytes in block lda #$10 ; 16 jsr SetBufPointer3 ; buffer pointer to 16 jsr WriteSector2 ; write block jsr VerifyExec ; and verify ldx CURCHN ; channel number lda SIDSECzp,X ; buffer number of the side-sector pha jsr GetBufNumber2 ; get buffer number ldx CURCHN ; channel number sta SIDSECzp,X ; write in table pla ldx LstUsedBuf ; channel number + 7 sta BUF0CH1zp,X ; in table lda #$00 jsr SetBufPointer3 ; buffer pointer to zero ldy #$00 lda TRACK ; track sta (DIRBUF),Y ; in buffer iny lda SECTOR ; sector sta (DIRBUF),Y ; in buffer jmp J_E4DE A_E4D1: ; [E4D1] jsr GetBufNumber ; get buffer number ldx CURCHN ; channel number jsr ReadSideSec ; read block lda #$00 jsr SetBufPointer3 ; buffer pointer to zero J_E4DE: ; [E4DE] dec R4 dec R4 ; counter for side-sector blocks ldy R3 lda R1 ; track number sta (DIRBUF),Y ; in buffer iny lda R2 ; sector number sta (DIRBUF),Y ; in buffer jsr WriteSector3 ; write block jsr VerifyExec ; and verify ldy R4 ; counter for side-sector blocks cpy #$03 bcs A_E4D1 ; greater than or equal to 3? jmp SwapBuffers2 ; change buffer ;** Table of error messages ; Format: error numbers ; description ; (with start and end letters +$80) ; If value AND DRVNMB less than $10 ; Then look up text in pointer table. ErrorMessages: ; [E4FC] ;** OK .by $00 ; error number .tz ' OK' ;** Read error .by $20,$21,$22,$23,$24,$27 ; error numbers of 'read error' .tw 'READ' .by $89 ; pointer to 'error' ;** File too large .by $52 ; 52 .by $83 ; pointer to 'file' .ty ' TOO LARGE' ;** Record not present .by $50 ; 50 .by $8B ; pointer to 'record' and 'not' .by $06 ; pointer to 'record' and 'not' .ty ' PRESENT' ;** Overflow in record .by $51 ; 51 .tw 'OVERFLOW IN' .by $8B ; pointer to 'record' ;** Write error .by $25,$28 ; error numbers of 'write error' .by $8A ; pointers to 'write' and 'error' .by $89 ; pointers to 'write' and 'error' ;** Write protect on .by $26 ; 26 .by $8A ; pointer to 'write' .ty ' PROTECT ON' ;** Disk id mismatch .by $29 ; 29 .by $88 ; pointer to 'disk' .tx ' ID' .by $85 ; pointer to 'mismatch' ;** Syntax error .by $30,$31,$32,$33,$34 ; error numbers for 'syntax error' .tw 'SYNTAX' .by $89 ; pointer to 'error' ;** Write file open .by $60 ; 60 .by $8A ; pointer to 'write' .by $03 ; pointer to 'file' .by $84 ; pointer to 'open' ;** File exists .by $63 ; 63 .by $83 ; pointer to 'file' .ty ' EXISTS' ;** File type mismatch .by $64 ; 64 .by $83 ; pointer to 'file' .tx ' TYPE' .by $85 ; pointer to 'mismatch' ;** No block .by $65 ; 65 .tz 'NO BLOCK' ;** Illegal track or sector .by $66,$67 ; error numbers for .tz 'ILLEGAL TRACK OR SECTOR' ;** File not open .by $61 ; 61 .by $83 ; pointer to 'file' .by $06 ; pointer to 'not' .by $84 ; pointer to 'open' ;** File not found .by $39,$62 ; error numbers for 'file not found' .by $83 ; pointers to 'file' .by $06 ; pointers to 'not' .by $87 ; pointers to 'found' ;** Files scratched .by $01 ; 01 .by $83 ; pointer to 'files' .ty 'S SCRATCHED' ;** No channel .by $70 ; 70 .tz 'NO CHANNEL' ;** Dir error .by $71 ; 71 .tw 'DIR' .by $89 ; pointer to 'error' ;** Disk full .by $72 ; 72 .by $88 ; pointer to 'disk' .ty ' FULL' ;** Cbm dos v2.6 1541 .by $73 ; 73 .tz 'CBM DOS V2.6 1541' ;** Drive not ready .by $74 ; 74 .tw 'DRIVE' .by $06 ; pointer to 'not' .ty ' READY' ;** Indexed words ;** Format: index number ;** description .by $09 .tz 'ERROR' .by $0A .tz 'WRITE' .by $03 .tz 'FILE' .by $04 .tz 'OPEN' .by $05 .tz 'MISMATCH' .by $06 .tz 'NOT' .by $07 .tz 'FOUND' .by $08 .tz 'DISK' .by $0B .tz 'RECORD' EndOfErrMsg: ;** Prepare error number and message PrepErrMsg: ; [E60A] pha ; save error code stx ActBufNum txa asl A ; times 2 tax ; as pointer lda TRASECzp,X sta TRACK ; get track lda TRASECzp+1,X sta SECTOR ; and sector number pla ; get error code back and #$0F ; isolate bits 0-3 beq A_E625 ; zero, then 'read error' cmp #$0F ; 15? bne A_E627 lda #$74 ; 74, 'drive not ready' bne A_E62D ; 6 A_E625: ; [E625] lda #$06 A_E627: ; [E627] ora #$20 tax dex dex ; subtract two txa A_E62D: ; [E62D] pha ; save error number lda INSTRU ; number of the disk command cmp #$00 ; OPEN or VALIDATE? bne A_E644 ; no, -> lda #$FF sta INSTRU pla ; get error number back jsr ErrMsg2Buf ; generate error message jsr LoadBAM ; load BAM jmp CreErrorMsg2 ; set error message A_E644: ; [E644] pla CreErrorMsg: ; [E645] jsr ErrMsg2Buf ; set error message CreErrorMsg2: ; [E648] jsr EraseInputBuf ; erase input buffer lda #$00 sta WBAM jsr PrepLedFlash ; turn LED off jsr Close17_18 ; close channels 17 and 18 lda #$00 sta INPPTR ; input buffer pointer to zero ldx #$45 txs ; initialize stack pointer lda ORGSA ; secondary address and #$0F sta SA cmp #$0F ; command channel? beq A_E698 ; yes, -> sei lda LSNACT ; LISTEN active? bne A_E688 ; yes, -> lda TLKACT ; TALK active? bne A_E680 ; yes, -> ldx SA ; channel number lda LINTAB,X ; open channel to this secondary addr cmp #$FF ; channel in use? beq A_E698 ; no, -> and #$0F sta CURCHN ; channel jmp J_E68E ;** TALK A_E680: ; [E680] jsr OpenChan4Read ; open channel for reading nop nop nop bne J_E68E ;** LISTEN A_E688: ; [E688] jsr OpenChan4Write ; open channel for writing nop nop nop J_E68E: ; [E68E] jsr CheckREL ; verify file type cmp #$04 ; file type REL or Direct access? bcs A_E698 ; yes, -> jsr CloseChannel ; close channel A_E698: ; [E698] jmp WaitLoop1 ;** Convert HEX to ASCII ; in: A Y ; out: - ; used: A X Y Hex2ASCII: ; [E69B] tax jmp J_C07F ; $C07F ; left over A_E69F: ; [E69F] cpx #$00 beq A_E6AA clc adc #$01 dex jmp A_E69F A_E6AA: ; [E6AA] cld ;** Convert BCD number into two ASCII bytes BCD2ASCII: ; [E6AB] tax lsr A lsr A ; shift hi-nibble down lsr A lsr A jsr Nibble2ASCII ; convert to ASCII txa Nibble2ASCII: and #$0F ; erase top 4 bits ora #'0' ; add '0' sta (ERRPTR),Y ; write in buffer iny ; increment buffer pointer rts ;** Write OK message in buffer ; in: - ; out: - ; used: A X Y OK2Buffer: ; [E6BC] jsr ClrErrorFlags ; erase error flag lda #$00 ; error number 0 ;** Write error message where track and sector = 0 ErrMsgTS00: ; [E6C1] ldy #$00 sty TRACK ; track 0 sty SECTOR ; sector 0 ;** Error message in buffer (number in A) ; in: A TRACK SECTOR ; out: - ; used: A X Y ErrMsg2Buf: ; [E6C7] ldy #$00 ; buffer pointer ldx #<(ERRBUF) stx ERRPTR ldx #>(ERRBUF) stx ERRPTR+1 ; pointer $A5/$A6 to $02D5 jsr BCD2ASCII ; error number to ASCII and in buffer lda #',' sta (ERRPTR),Y ; write in buffer iny ; increment buffer pointer lda ERRBUF ; first digit of the disk status sta OUTREG+5 ; in output register txa ; error number in accumulator jsr Message2Buffer ; error message in buffer lda #',' sta (ERRPTR),Y ; write in buffer iny ; and increment buffer pointer lda TRACK ; track number jsr Hex2ASCII ; to ASCII and in buffer lda #',' sta (ERRPTR),Y ; write in buffer iny ; increment buffer pointer lda SECTOR ; sector jsr Hex2ASCII ; convert to ASCII and in buffer dey tya clc adc #$D5 sta ENDPNT+5 ; end pointer inc ERRPTR lda #$88 ; set READ flag sta RDFLAG rts ;** Write error message to buffer ; in: A ; out: - ; used: A X Y Message2Buffer: ; [E706] tax ; save error code lda R0 pha ; preserve pointer $86/$87 lda R1 pha lda #<(ErrorMessages) sta R0 lda #>(ErrorMessages) sta R1 ; $E4FC - start of the error messages txa ; restore error code in accumulator ldx #$00 J_E718: ; [E718] cmp (R0,X) ; compare with error number in table beq A_E73D ; if same, -> pha jsr IncPointer ; bit 7 set? bcc A_E727 ; no, -> A_E722: ; [E722] jsr IncPointer ; bit 7 into carry bcc A_E722 ; wait for character with bit 7 set A_E727: ; [E727] lda R1 cmp #>(EndOfErrMsg) ; end of error msg table reached? bcc A_E735 ; no, -> bne A_E739 ; no, -> lda #<(EndOfErrMsg) cmp R0 ; end of error msg table reached? bcc A_E739 ; yes, -> A_E735: ; [E735] pla jmp J_E718 ; no, continue A_E739: ; [E739] pla jmp J_E74D ; done A_E73D: ; [E73D] jsr GetChar ; get a character, bit 7 in carry bcc A_E73D ; wait for character with bit 7 set A_E742: ; [E742] jsr WrChar2Buf ; and write in buffer jsr GetChar ; get next character [E767] bcc A_E742 ; wait for character with bit 7 set jsr WrChar2Buf ; put character in buffer J_E74D: ; [E74D] pla sta R1 pla ; get pointer $86/$87 back sta R0 rts ;** Write character into buffer ; in: A Y ; out: Y ; used: A X Y WrChar2Buf: ; [E754] cmp #' ' bcs A_E763 ; greater, then write in buffer tax ; save code lda #' ' ; blank sta (ERRPTR),Y ; write in buffer iny ; increment buffer pointer txa ; restore code in accumulator jsr Message2Buffer ; output previous message rts A_E763: ; [E763] sta (ERRPTR),Y ; write character in buffer iny ; and increment pointer rts ;** Get a char of the error message GetChar: ; [E767] inc R0 bne Bit7Carry ; increment pointer inc R1 ;** ; in: X ; out: A C ; used: A Bit7Carry: ; [E76D] lda (R0,X) ; get character asl A ; bit 7 into carry lda (R0,X) ; get character again and #$7F ; erase bit 7 rts ;** Increment pointer ; in: X ; out: A C ; used: A IncPointer: ; [E775] jsr Bit7Carry ; bit 7 into carry inc R0 bne A_E77E ; increment pointer inc R1 A_E77E: ; [E77E] rts A_E77F: ; [E77F] rts ;** Check for auto start removed P_E780: ; [E780] .fb $EA, 34 ; 34 * NOP rts ;** & - USR file execute command USRexec: ; [E7A3] lda #$8D jsr SearchInputBuf ; check command line to end USRexec2: ; [E7A8] jsr P_F258 ; RTS lda F2CNT ; number of file names pha ; save lda #$01 sta F2CNT ; file name lda #$FF sta R0 jsr SrchFileDir ; find file lda FILTRK ; found? bne A_E7C5 ; yes, -> lda #$39 jsr OutputErrorMsg ; 39, 'file not found' A_E7C5: ; [E7C5] pla sta F2CNT ; get number of file names back lda FILTRK sta TRACK ; track lda FILSEC sta SECTOR ; and sector lda #$03 ; file type 'USR' jsr ReadXxxFile ; buffer allocated, read 1st block A_E7D8: ; [E7D8] lda #$00 sta R1 ; erase checksum jsr GetBytFromFil ; get byte from file sta R2 ; save as start address lo jsr GenChecksum ; generate checksum jsr GetBytFromFil ; get byte from file sta R3 ; as start address hi jsr GenChecksum ; generate checksum lda R0 beq A_E7FA lda R2 pha ; save program start address lda R3 pha lda #$00 sta R0 A_E7FA: ; [E7FA] jsr GetBytFromFil ; get byte from file sta R4 ; save as counter jsr GenChecksum ; generate checksum A_E802: ; [E802] jsr GetBytFromFil ; get byte from file ldy #$00 sta (R2),Y ; save as program bytes jsr GenChecksum ; generate checksum lda R2 clc adc #$01 sta R2 ; increment $88/$89 bcc A_E817 inc R3 A_E817: ; [E817] dec R4 ; decrement pointer bne A_E802 jsr OpenChnGetByt ; get next byte lda DATA ; data byte cmp R1 ; equal to checksum? beq A_E82C ; yes, -> jsr GetSector2 ; transmit parameter to disk controller lda #$50 jsr CreErrorMsg ; 50, 'record not present' A_E82C: ; [E82C] lda EOIFLG ; end? bne A_E7D8 ; no, -> next data block pla sta R3 pla ; get program start address back sta R2 jmp (R2) ; and execute program ;** Get a byte from the file GetBytFromFil: ; [E839] jsr OpenChnGetByt ; get byte from file lda EOIFLG ; end of file? bne A_E848 ; no, -> jsr GetSector2 ; transmit parameter to disk controller lda #$51 jsr CreErrorMsg ; 51, 'overflow in record' A_E848: ; [E848] lda DATA ; data byte rts ;** Generate checksum GenChecksum: ; [E84B] clc adc R1 adc #$00 sta R1 rts ;** IRQ routine for serial bus P_E853: ; [E853] lda PortA1 ; read port A, erase IRQ flag lda #$01 sta ATNPND ; set flag for 'ATN received' rts ;** Service the serial bus SerialBus: ; [E85B] sei lda #$00 sta ATNPND ; erase flag for 'ATN received' sta LSNACT ; erase flag for LISTEN sta TLKACT ; erase flag for TALK ldx #$45 txs ; new stack pointer lda #$80 sta EOIFLG ; non-EOI state sta ATNMOD ; erase EOI flag jsr ClkOut_L ; CLK out (L) jsr DataOut_H ; DATA out (H) lda PortB1 ora #$10 ; switch data lines to input sta PortB1 ; DATA as input A_E87B: ; [E87B] lda PortB1 ; ATN active? bpl ClrATN ; no -> [E8D7] and #$04 ; CLOCK in? bne A_E87B ; no, wait -> A_E884: ; [E884] jsr GetByteFromBus ; read byte from bus1 cmp #$3F ; unlisten? bne A_E891 ; no -> lda #$00 sta LSNACT ; reset flag for LISTEN beq A_E902 ; always -> A_E891: ; [E891] cmp #$5F ; untalk? bne A_E89B ; no -> lda #$00 sta TLKACT ; reset flag for TALK beq A_E902 ; always -> A_E89B: ; [E89B] cmp TLKADR ; TALK-address? bne A_E8A9 ; no -> lda #$01 sta TLKACT ; set flag for TALK lda #$00 sta LSNACT ; reset flag for LISTEN beq A_E8D2 ; always -> A_E8A9: ; [E8A9] cmp LSNADR ; LISTEN-address? bne A_E8B7 ; no -> lda #$01 sta LSNACT ; set flag for LISTEN lda #$00 sta TLKACT ; reset flag for TALK beq A_E8D2 ; always -> A_E8B7: ; [E8B7] tax and #$60 cmp #$60 ; secondary address? bne A_E8FD ; no -> txa ; yes! sta ORGSA ; byte is secondary address and #$0F sta SA ; channel number lda ORGSA and #$F0 cmp #$E0 ; CLOSE? bne A_E902 ; no -> cli jsr CloseFileSA ; CLOSE-routine sei A_E8D2: ; [E8D2] bit PortB1 ; ATN still active? bmi A_E884 ; yes, read next byte -> ClrATN: ; [E8D7] lda #$00 ; no, end ATN mode sta ATNMOD lda PortB1 ; IEC port and #$EF ; switch data lines to output sta PortB1 lda LSNACT ; LISTEN? beq A_E8ED ; no -> jsr ReceiveData ; receive data jmp WaitLoop1 ; to WaitLoop A_E8ED: ; [E8ED] lda TLKACT ; TALK? beq A_E8FA ; no -> jsr DataOut_L ; free dataline jsr ClkOut_H ; CLOCK (L) jsr SendData ; send data A_E8FA: ; [E8FA] jmp WaitLoop0 ; to WaitLoop A_E8FD: ; [E8FD] lda #$10 ; nor Talk, neither LISTEN: ignore sta PortB1 ; kill all lines except ATN acknowledge A_E902: ; [E902] bit PortB1 ; ATN still present? bpl ClrATN ; no -> [E8D7] bmi A_E902 ; wait until gone -> ;** Send data SendData: ; [E909] sei jsr OpenChan4Read ; open channel for read bcs A_E915 ; channel active J_E90F: ; [E90F] ldx CURCHN ; channel number lda REWRFLzp,X ; set READ flag? bmi A_E916 ; yes, -> A_E915: ; [E915] rts A_E916: ; [E916] jsr Check4EOI ; check EOI [EA59] jsr ReadIecPort and #$01 ; isolate data bit php ; and save jsr ClkOut_L ; CLOCK OUT lo plp beq A_E937 A_E925: ; [E925] jsr Check4EOI ; check EOI [EA59] jsr ReadIecPort and #$01 ; isolate data bit bne A_E925 ldx CURCHN ; channel number lda REWRFLzp,X ; status and #$08 ; check for EOI bne A_E94B ; no, -> A_E937: ; [E937] jsr Check4EOI ; check EOI [EA59] jsr ReadIecPort and #$01 ; isolate data bit bne A_E937 A_E941: ; [E941] jsr Check4EOI ; check EOI [EA59] jsr ReadIecPort and #$01 ; isolate data bit beq A_E941 A_E94B: ; [E94B] jsr ClkOut_H ; CLOCK OUT hi jsr Check4EOI ; check EOI [EA59] jsr ReadIecPort and #$01 ; isolate data bit bne A_E94B lda #$08 ; counter to 8 bits for serial sta CONT ; transmission A_E95C: ; [E95C] jsr ReadIecPort and #$01 ; isolate data bit bne A_E999 ldx CURCHN lda OUTREG,X ror A ; lowest data bit in carry sta OUTREG,X bcs A_E973 ; set bit jsr DataOut_H ; DATA OUT, output bit '0' bne A_E976 ; always -> A_E973: ; [E973] jsr DataOut_L ; DATA OUT, output bit '1' A_E976: ; [E976] jsr ClkOut_L ; set CLOCK OUT lda VIC20mode ; VIC-20 ? bne A_E980 ; yes, no slowdown needed, -> jsr DelayC64 ; delay for serial bus for C64 A_E980: ; [E980] jsr P_FEFB ; set DATA OUT and CLOCK OUT dec CONT ; all bits output? bne A_E95C ; no, -> A_E987: ; [E987] jsr Check4EOI ; check EOI [EA59] jsr ReadIecPort and #$01 ; isolate data bit beq A_E987 cli jsr GetByte2 ; get next data byte sei jmp J_E90F ; and output A_E999: ; [E999] jmp WaitLoop0 ; to delay loop ;** DATA OUT lo DataOut_L: ; [E99C] lda PortB1 DataOut_L2: ; [E9A1] and #$FD ; output bit '1' OUTPORTB1: ; [E9A3] sta PortB1 rts ;** DATA OUT hi DataOut_H: ; [E9A5] lda PortB1 ora #$02 ; output bit '0' sta PortB1 rts ;** CLOCK OUT hi ClkOut_H: ; [E9AE] lda PortB1 ora #$08 ; set bit 3 sta PortB1 rts ;** CLOCK OUT lo ClkOut_L: ; [E9B7] lda PortB1 ClkOut_L2: ; [E9B9] and #$F7 ; erase bit 3 sta PortB1 rts ;** Read IEC port ReadIecPort: ; [E9C0] lda PortB1 ; read port cmp PortB1 ; wait for constants bne ReadIecPort rts ;** Get data byte from bus GetByteFromBus: ; [E9C9] lda #$08 sta CONT ; bit counter for serial output A_E9CD: ; [E9CD] jsr Check4EOI ; check EOI [EA59] jsr ReadIecPort and #$04 ; CLOCK IN? bne A_E9CD ; no, wait jsr DataOut_L ; DATA OUT, bit '1' lda #$01 ; NOT USED jmp PATCH2 ; set timer J_E9DF: ; [E9DF] jsr Check4EOI ; check EOI [EA59] lda IFR1 and #$40 ; timer run down? bne A_E9F2 ; yes, -> EOI jsr ReadIecPort and #$04 ; CLOCK IN? beq J_E9DF ; no, wait bne A_EA0B ; always -> ;** Accept byte with EOI A_E9F2: ; [E9F2] jsr DataOut_H ; DATA OUT bit '0' hi ldx #$0A ; 10 A_E9F7: ; [E9F7] dex ; delay loop, approx 50 micro sec. bne A_E9F7 jsr DataOut_L ; DATA OUT, bit '1', lo A_E9FD: ; [E9FD] jsr Check4EOI ; check EOI [EA59] jsr ReadIecPort and #$04 ; CLOCK IN? beq A_E9FD ; no, wait lda #$00 sta EOIFLG ; set EOI flag A_EA0B: ; [EA0B] lda PortB1 ; IEC port eor #$01 ; invert data byte lsr A and #$02 bne A_EA0B ; CLOCK IN? nop nop nop ror DATA ; prepare next bit A_EA1A: ; [EA1A] jsr Check4EOI ; check EOI [EA59] jsr ReadIecPort and #$04 ; CLOCK IN? beq A_EA1A ; no, -> dec CONT ; decrement bit counter bne A_EA0B ; all bits output? jsr DataOut_H ; DATA OUT, bit '0', hi lda DATA ; load data byte again rts ;** Accept data from serial bus ReceiveData: ; [EA2E] sei jsr OpenChan4Write ; open channel for writing bcs A_EA39 ; channel not active? lda REWRFLzp,X ; WRITE flag ror A bcs A_EA44 ; not set? A_EA39: ; [EA39] lda ORGSA ; secondary address and #$F0 cmp #$F0 ; OPEN command? beq A_EA44 ; yes, -> jmp WaitLoop0 ; to wait loop A_EA44: ; [EA44] jsr GetByteFromBus ; get data byte from bus cli jsr P_CFB7 ; and write in buffer jmp ReceiveData ; to loop beginning ;** WaitLoop0: ; [EA4E] lda #$00 sta PortB1 ; reset IEC port jmp WaitLoop1 ; to wait loop S_EA56: ; [EA56] jmp SerialBus ;** Test for EOI Check4EOI: ; [EA59] lda ATNMOD ; EOI received? beq A_EA63 ; yes, -> lda PortB1 ; ATN active? bpl A_EA6B ; no, -> A_EA62: ; [EA62] rts A_EA63: ; [EA63] lda PortB1 ; ATN active? bpl A_EA62 ; no, -> jmp J_FF50 ; to serial bus main loop A_EA6B: ; [EA6B] jmp ClrATN ; reset ATN [E8D7] ;** Flash LED for hardware defects, self-test ; if X=$FD, then continue flashing BlinkOnce: ; [EA6E] ldx #$00 ; blink once for ZeroPage .by $2C ; dummy BIT opcode BlinkX: ; [EA71] ldx TEMP0 ; blink X+1 times for RAM/ROM err txs ; use Stackreg. as extra register L_EA74: ; [EA74] tsx L_EA75: ; [EA75] lda #$08 ; LED on ora PortB2 jmp PATCH3 ; [FEEA] J_EA7D: ; [EA7D] tya ; delay L_EA7E: ; [EA7E] clc L_EA7F: ; [EA7F] adc #$01 bne L_EA7F dey bne L_EA7E lda PortB2 and #$F7 ; turn LED off sta PortB2 ; LED off L_EA8E: ; [EA8E] tya ; delay L_EA8F: ; [EA8F] clc L_EA90: ; [EA90] adc #$01 bne L_EA90 ; delay loop dey bne L_EA8F dex ; all flashes? bpl L_EA75 ; no, -> cpx #$FC bne L_EA8E ; no, extra pause beq L_EA74 ; always, -> start again flashing ;** RESET routine RESET: ; [EAA0] sei cld ldx #$FF jmp PATCH1 ;** Test ZP-RAM L_EAA7: ; [EAA7] inx ; Why ???, see R_EAAA ldy #$00 R_EAAA: ; [EAAA] ldx #$00 ;** Fill ZP with ascending pattern L_EAAC: ; [EAAC] txa ; Store 1, 2, 3 etc. sta JOBSzp,X ; .... on address 1, 2, 3 etc. inx bne L_EAAC L_EAB2: ; [EAB2] txa cmp JOBSzp,X ; check contents bne BlinkOnce ; no, then to error display (blink) L_EAB7: ; [EAB7] inc JOBSzp,X ; loop to add 256 iny bne L_EAB7 cmp JOBSzp,X ; result must be the same bne BlinkOnce ; error sty JOBSzp,X ; Y=0 lda JOBSzp,X ; A=0 ? bne BlinkOnce ; no, error -> inx bne L_EAB2 ;** Test both ROMs L_EAC9: ; [EAC9] inc TEMP0 ; number of LED-flashes stx IP+1 ; HB lda #$00 sta IP ; IP=0 tay ldx #$20 ; 8 KByte clc L_EAD5: ; [EAD5] dec IP+1 ; next page L_EAD7: ; [EAD7] adc (IP),Y ; add byte iny bne L_EAD7 dex ; all 8 KB bne L_EAD5 ; no -> adc #$00 ; add Carry tax cmp IP+1 ; A=$E0/C0 ? bne L_EB1F ; no, error -> cpx #$C0 ; $C000-$DFFF checked? bne L_EAC9 ; no, next 8 KB ;** Check RAM lda #$01 sta IP+1 ; start with page 1 inc TEMP0 ldx #$07 ; 7 pages L_EAF2: ; [EAF2] tya clc adc IP+1 sta (IP),Y iny bne L_EAF2 inc IP+1 dex ; next page bne L_EAF2 ldx #$07 L_EB02: ; [EB02] dec IP+1 L_EB04: ; [EB04] dey tya clc adc IP+1 cmp (IP),Y bne L_EB1F ; RAM-error -> eor #$FF sta (IP),Y eor (IP),Y sta (IP),Y bne L_EB1F ; RAM-error -> tya bne L_EB04 ; next byte dex bne L_EB02 ; next page beq InitStack ; always -> L_EB1F: ; [EB1F] jmp BlinkX ; to error display ;** Initialize stackpointer InitStack: ; [EB22] jmp J_FF49 J_EB25: lda PortB2 ; de-activate LED and #$F7 ; turn LED off sta PortB2 lda #$01 ; trigger CA1 (ATN IN) sta PCR1 ; on positive edge lda #$82 ; enable interrupt via ATN IN sta IFR1 ; interrupt possible through ATN IN sta IER1 ;** Read device number out of bit 5/6 of Port B1 lda PortB1 ; read port B and #$60 ; isolate bits 5 & 6 (device number) asl rol rol ; rotate to bit positions 0 & 1 rol ora #$48 ; dev. number for talk sta TLKADR ; device number for TALK (send) eor #$60 ; dev. number for listen sta LSNADR ; device number + $20 for LISTEN ;** Initialize pointers to buffers 0..4 ldx #$00 ldy #$00 L_EB4F: ; [EB4F] lda #$00 sta BUFTABzp,X ; Low Byte = 0 inx lda BufAddrHB,Y ; Load HB from tabel sta BUFTABzp,X ; save inx iny cpy #$05 bne L_EB4F ;** Let $A3/$A4 point to $0200 lda #<(CMDBUF) sta BUFTABzp,X inx ; pointer $A3/$A4 to $200, input buffer lda #>(CMDBUF) sta BUFTABzp,X inx ;** Buffer errormessage ERRBUF in $A5/$A6 lda #<(ERRBUF) sta BUFTABzp,X inx ; pointer $A5/$A6 to $2D5, error lda #>(ERRBUF) ; message pointer sta BUFTABzp,X ;** Fill channel table with $FF (= not used) lda #$FF ldx #$12 L_EB76: ; [EB76] sta LINTAB,X ; fill channel table with $FF dex bpl L_EB76 ldx #$05 L_EB7E: ; [EB7E] sta BUF0CH1zp,X ; erase buffer tables sta BUF1CH1zp,X sta SIDSECzp,X ; erase side-sector table dex bpl L_EB7E lda #$05 ; buffer 5 sta BUF0CH5 ; for channel 4 lda #$06 ; buffer 6 sta BUF0CH6 ; for channel 5 lda #$FF sta BUF0CH7 sta BUF1CH7 lda #$05 sta CH5WFL ; reset WRITE-flag channel 5 lda #$84 sta CH4WFL ; set WRITE-flag channel 4 lda #$0F ; initialize channel allocation register sta LINUSE ; mark all channels as free lda #$01 sta WRFLAG ; WRITE flag lda #$88 sta RDFLAG ; READ flag lda #$E0 ; 5 buffers free sta BUFUSEL ; 5 buffers free (bit = 0) lda #$FF ; $24F/$250, 16 bit sta BUFUSEH lda #$01 ; disk has changed sta WPSW0 sta WPSW1 jsr SetVectorU0 ; set vector for U0 jsr InitLastTable ; initialize channel table jsr InitDiskCntrlr ; initialize disk-controler ;** Initialize NMI-vector lda #<(InitStack) sta VNMI lda #>(InitStack) ; pointer $65/$66 to $EB22 sta VNMI+1 lda #$0A ; interleave 10 sta SECINC lda #$05 ; for sector assignment sta REVCNT ; try 5 times to read lda #$73 ; initialize error message jsr ErrMsgTS00 ; 73, 'cbm dos v2.6 1541' lda #$00 sta PortB1 lda #$1A ; bit 1, 3 & 4 to output sta DDRB1 jsr P_E780 ; check for autostart WaitLoop1: ; [EBE7] cli lda PortB1 and #$E5 ; reset serial port sta PortB1 lda CMDWAT ; command flag? beq WaitLoop2 ; no, -> lda #$00 sta CMDWAT ; reset command flag sta NMIFLG jsr InterprCmnd ; analyse and execute instruction ;** Wait loop WaitLoop2: ; [EBFF] cli lda ATNPND ; ATN pending? beq L_EC07 ; no, -> jmp J_FF50 ; to IEEE routine L_EC07: ; [EC07] cli lda #$0E ; 14 sta TEMP3 ; secundair address lda #$00 sta TEMP0 ; job counter sta TEMP1 L_EC12: ; [EC12] ldx TEMP3 lda LINTAB,X ; secondary address cmp #$FF ; channel added ? beq L_EC2B ; no -> and #$3F sta CURCHN ; channel number jsr GetBufNumber ; get buffer # tax lda LSTJOB,X ; get drive # and #$01 tax inc TEMP0,X ; increment job counter L_EC2B: ; [EC2B] dec TEMP3 ; decrement secundair address bpl L_EC12 ; >= 0, -> ldy #$04 ; buffer counter L_EC31: ; [EC31] lda JOBS,Y ; does disk controler work? bpl L_EC3B ; no, -> and #$01 ; isolate drive # tax inc TEMP0,X ; incr. job counter L_EC3B: ; [EC3B] dey ; next buffer? bpl L_EC31 ; yes, -> sei lda PortB2 and #$F7 ; LED bit off pha lda DRVNMB ; save drive # sta R0 lda #$00 sta DRVNMB ; drive 0 lda TEMP0 ; job for drive 0? beq L_EC5C ; no, -> lda WPSW0 ; disk change for drive 0? beq L_EC58 ; no, -> jsr ClsChanThisDrv ; close all channels to drive 0 L_EC58: ; [EC58] pla ora #$08 ; LED bit on pha L_EC5C: ; [EC5C] inc DRVNMB ; drive 1 lda TEMP1 ; job for drive 1? beq L_EC6D ; no -> lda WPSW1 ; disk change for drive 1? beq L_EC69 ; no -> jsr ClsChanThisDrv ; close all channels to drive 1 L_EC69: ; [EC69] pla ora #$00 ; LED drive 1 on (does not exist) pha L_EC6D: ; [EC6D] lda R0 ; restore drive # sta DRVNMB ; get drive number back pla ; bit for LED ldx ERWORD ; IRQ-counter for blinking LED beq L_EC98 ; no blinking, -> lda PortB2 cpx #$80 ; old error? bne L_EC81 ; yes, -> jmp L_EC8B ; no, new error -> L_EC81: ; [EC81] ldx T1CH1 ; still timing? bmi L_EC98 ; yes -> ldx #$A0 ; no, new 8 msec cycle stx T1CH1 ; set timer L_EC8B: ; [EC8B] dec ERWORD ; time is up? bne L_EC98 ; no -> eor ERLED ; toggle LED ldx #$10 stx ERWORD ; reset counter L_EC98: ; [EC98] sta PortB2 ; LED on/off jmp WaitLoop2 ; start loop all over again ;** Creat directory listing CreDirectory: lda #$00 sta SA ; secondary address 0 lda #$01 jsr FindRdChanBuf ; find channel and buffer lda #$00 jsr SetBufPointer3 ; initialize buffer pointer ldx CURCHN ; channel number lda #$00 sta ENDPNT,X ; pointer to end = zero jsr GetBufNumber ; get buffer number tax lda DRVNMB ; drive number sta LSTJOB,X ; bring in table ; write start address $0401 in buffer lda #$01 jsr Write2Buf lda #$04 jsr Write2Buf lda #$01 ; 2 times 1 jsr Write2Buf jsr Write2Buf ; write in buffer as link address lda NBTEMP0 ; drive number jsr Write2Buf ; write in buffer as line number lda #$00 ; line number hi jsr Write2Buf ; in buffer jsr DirLine2Buf ; directory entry in buffer jsr GetBufNumber ; get buffer number asl A tax dec BUFTABzp,X ; decrement buffer pointer dec BUFTABzp,X lda #$00 jsr Write2Buf ; 0 as line end in buffer CreDirLineBuf: lda #$01 jsr Write2Buf ; 2 times 1 as link address jsr Write2Buf jsr GetDirEntry ; directory entry in buffer bcc A_ED23 ; another entry? lda NBTEMP0 ; block number lo jsr Write2Buf ; in buffer lda NBTEMP1 ; block number hi jsr Write2Buf ; in buffer jsr DirLine2Buf ; directory entry in buffer lda #$00 ; zero as end marker in buffer jsr Write2Buf ; buffer full? bne CreDirLineBuf ; no, -> J_ED0D: ; [ED0D] jsr GetBufNumber ; get buffer number asl A tax lda #$00 sta BUFTABzp,X ; buffer pointer to zero lda #$88 ; set READ flag ldy CURCHN ; channel number sta DIRLST sta REWRFLab,Y ; flag for channel lda DATA ; data byte rts A_ED23: ; [ED23] lda NBTEMP0 ; block number lo jsr Write2Buf ; write in buffer lda NBTEMP1 ; block number hi jsr Write2Buf ; in buffer jsr DirLine2Buf ; 'blocks free.' in buffer jsr GetBufNumber ; get buffer number asl A tax dec BUFTABzp,X dec BUFTABzp,X ; buffer pointer minus 2 lda #$00 jsr Write2Buf jsr Write2Buf jsr Write2Buf ; three zeroes as program end jsr GetBufNumber ; get buffer number asl A ; times 2 tay lda BUFTABab,Y ; buffer pointer ldx CURCHN sta ENDPNT,X ; as end marker dec ENDPNT,X jmp J_ED0D ;** Write directory line into buffer DirLine2Buf: ; [ED59] ldy #$00 A_ED5B: ; [ED5B] lda NameBuffer,Y ; character from buffer jsr Write2Buf ; write in output buffer iny cpy #$1B ; 27 characters? bne A_ED5B ; no, -> more rts ;** Create directory line CreateDirLine: jsr GetByteFromBuf ; buffer pointer zero? beq A_ED6D ; yes, -> rts A_ED6D: ; [ED6D] sta DATA ; save data byte ldy CURCHN ; channel number lda ENDPNT,Y ; zero (LOAD $)? beq A_ED7E ; yes, -> lda #$80 sta REWRFLab,Y ; set READ flag lda DATA ; data byte rts A_ED7E: ; [ED7E] pha jsr CreDirLineBuf ; create directory line in buffer pla rts ;** V - Validate command Validate: ; [ED84] jsr ChkInputLine ; find drive number in input line jsr LoadBAM ; load BAM lda #$40 sta WBAM jsr CreateBam ; create new BAM in buffer lda #$00 sta DELIND jsr Read1stDirBlk ; 1st entry found? bne A_EDD9 ; yes, -> check if open A_ED9C: ; [ED9C] lda #$00 sta SECTOR ; sector 0 lda DirTrack ; 18 sta TRACK ; track 18 for BAM jsr AllocateFile ; allocate complete directory lda #$00 sta WBAM jsr WriteBam2 ; write BAM back to disk [EEFF] jmp Out_Err_Msg ; done, prepare disk status A_EDB3: ; [EDB3] iny lda (DIRBUF),Y ; save track pha iny lda (DIRBUF),Y ; and sector pha ldy #$13 ; pointer to side-sector block lda (DIRBUF),Y ; side sector present? beq A_EDCB ; no, -> sta TRACK ; track and iny lda (DIRBUF),Y sta SECTOR ; sector of 1st side-sector block jsr AllocateFile ; allocate side-sectors A_EDCB: ; [EDCB] pla sta SECTOR pla ; get track and sector back sta TRACK jsr AllocateFile ; mark blocks of file as allocated J_EDD4: ; [EDD4] jsr ReadNxtDirBlk ; end of directory? beq A_ED9C ; yes, -> ;* Close open file A_EDD9: ; [EDD9] ldy #$00 lda (DIRBUF),Y ; file closed? bmi A_EDB3 ; yes, -> jsr DelDirEntry ; file type to zero and write BAM jmp J_EDD4 ;** Allocate file blocks in BAM AllocateFile: ; [EDE5] jsr ChkTraSec3 ; check track and sector number jsr AllocSector ; allocate block in BAM jsr ReadSeqFile ; read next block J_EDEE: ; [EDEE] lda #$00 jsr SetBufPointer3 ; buffer pointer zero jsr GetByteFromBuf ; get byte from buffer sta TRACK ; track jsr GetByteFromBuf ; get byte from buffer sta SECTOR ; sector lda TRACK ; another block? bne A_EE04 ; yes, -> jmp CloseChannel ; close channel A_EE04: ; [EE04] jsr AllocSector ; allocate block in BAM jsr RdNxtBlock ; read next block jmp J_EDEE ; continue ;** N - New (Format) command New: ; [EE0D] jsr GetDrvNum ; get drive number lda DRVNUM ; drive number OK? bpl A_EE19 ; yes, -> lda #$33 jmp OutputErrorMsg ; 33, 'syntax error' A_EE19: ; [EE19] and #$01 sta DRVNMB ; drive number jsr P_FF36 ; lda DRVNMB ; drive number asl A ; times 2 tax ldy FILTBL+1 ; comma position cpy CMDSIZ ; compare with end name beq A_EE46 ; yes, -> format without ID lda CMDBUF,Y ; first character of ID sta DISKIDzp,X ; save lda CMDBUF+1,Y ; second character sta IMDIIDzp,X jsr CloseAllChan ; close all channels [D307] lda #$01 sta TRACK ; track 1 jsr FormatFloppy2 ; format disk jsr EraseBamBuf ; erase buffer [F005] jmp J_EE56 ; continue as below A_EE46: ; [EE46] jsr LoadBAM ; load BAM ldx DRVNMB ; drive number lda TypeChk,X cmp A_FED5 ; 'A', marker for 1541 format beq J_EE56 ; ok jmp A_D572 ; 73, 'cbm dos v2.6 1541' J_EE56: ; [EE56] jsr CreateBam ; create BAM lda ActBufNum ; buffer number tay asl A tax lda LengthBAM ; $90, start of disk name sta BUFTABzp,X ; buffer points now to name ldx FILTBL lda #27 ; 27 characters jsr FilNam2DirBuf ; write file name in buffer ldy #$12 ; position 18 ldx DRVNMB ; drive number lda A_FED5 ; 'A', 1541 format sta TypeChk,X txa asl A ; times 2 tax lda DISKIDzp,X ; ID, first character sta (DIRBUF),Y ; in buffer iny lda IMDIIDzp,X ; and second character sta (DIRBUF),Y ; in buffer iny iny lda #'2' sta (DIRBUF),Y ; in buffer iny lda A_FED5 ; 'A' 1541 format sta (DIRBUF),Y ; in buffer ldy #$02 sta (BMPNT),Y ; and at position 2 lda DirTrack ; 18 sta TRACK ; track number jsr AllocSector2 ; mark block as allocated lda #$01 ; 1 sta SECTOR ; sector number jsr AllocSector2 ; mark block as allocated jsr WriteBam2 ; write BAM [EEFF] jsr EraseBamBuf ; [F005] ldy #$01 lda #$FF sta (BMPNT),Y ; all 256 bytes of this sector used jsr WriteSector ; write BAM dec SECTOR ; decrement sector number, 0 jsr ReadSector ; read block jmp Out_Err_Msg ; prepare disk status ;** Create BAM CreateBam: ; [EEB7] jsr ClearTBAM ldy #$00 lda #$12 ; 18 sta (BMPNT),Y ; pointer to directory track iny tya ; 1 sta (BMPNT),Y ; pointer to directory sector iny iny iny A_EEC7: ; [EEC7] lda #$00 sta TEMP0 sta TEMP1 ; 3 bytes = 24 bits for sectors sta TEMP2 tya ; byte position lsr A lsr A ; divided by 4 = track number jsr GetMaxSectors ; get number of sectors sta (BMPNT),Y ; and in BAM iny tax ; X := number of sectors A_EED9: ; [EED9] sec rol TEMP0 rol TEMP1 ; create bit model rol TEMP2 dex bne A_EED9 A_EEE3: ; [EEE3] lda TEMP0,X ; 3 bytes sta (BMPNT),Y ; the BAM in buffer iny inx cpx #$03 bcc A_EEE3 cpy #$90 ; position 144? bcc A_EEC7 ; no, next track jmp CalcFreeBlks ; calculate number of free blocks ;** Write BAM to disk if needed WriteBam: ; [EEF4] jsr GetBufNumber ; get buffer number tax lda LSTJOB,X ; command for disk controller and #$01 sta DRVNMB ; isolate drive number WriteBam2: ; [EEFF] ldy DRVNMB lda MDIRTY,Y ; BAM-changed flag set? bne A_EF07 ; yes, -> rts A_EF07: ; [EF07] lda #$00 sta MDIRTY,Y ; reset BAM-changed flag jsr SetBufPtrBAM ; set buffer pointer for BAM lda DRVNMB ; drive number asl A ; times 2 pha jsr VerifyBamImage ; verify BAM entry [F0A5] pla clc adc #$01 ; increment drive number jsr VerifyBamImage ; verify BAM entry [F0A5] lda TRACK ; track pha lda #$01 ; track 1 sta TRACK A_EF24: ; [EF24] asl A ; times 4 asl A sta BMPNT ; bytes/track jsr VerifyBam ; verify BAM inc TRACK ; increment track number lda TRACK cmp A_FED7 ; and compare with max val + 1 = 36 bcc A_EF24 ; ok, next track pla sta TRACK ; get track number back jmp DskWriteBlock ; write BAM to disk ;** Set buffer pointer for BAM SetBufPtrBAM: ; [EF3A] jsr GetBufNumBAM2 ; get 13 for drive 0 tax jsr ReadBAM ; allocate buffer ldx ActBufNum ; buffer number lda BufAddrHB,X ; buffer address, hi byte sta BMPNT+1 lda #$00 ; lo byte sta BMPNT ; pointer to $6D/$6E rts ;** Get number of free blocks for dir NumBlocksFree: ; [EF4D] ldx DRVNMB ; drive number lda NDBL,X ; number of blocks, lo sta NBTEMP0 lda NDBH,X ; number of blocks, hi sta NBTEMP1 ; in buffer for directory rts ;** Is this the original start for FreeSector ???? ; This because AllocSector ($EF90) first calls $EFF1 S_EF5C: ; [EF5C] jsr P_EFF1 ; set buffer pointer ;** Mark block as free FreeSector: ; [EF5F] jsr GetBitBAM ; get state of bit for sector in BAM sec ; why ??? bne A_EF87 ; block already free, then done lda (BMPNT),Y ; bit model of BAM ora PowersOf2,X ; set bit X, marker for free sta (BMPNT),Y jsr SetBamChanged ; set flag for BAM changed ldy TEMP0 clc lda (BMPNT),Y adc #$01 ; increment number of free blocks/track sta (BMPNT),Y lda TRACK ; track cmp DirTrack ; equal to 18? beq A_EFBA ; then skip inc NDBL,X ; increment number of free blocks in ; disk bne A_EF87 inc NDBH,X ; increment number of blocks hi A_EF87: ; [EF87] rts ;** Set flag for BAM changed SetBamChanged: ldx DRVNMB ; drive number lda #$01 sta MDIRTY,X ; flag = 1 rts ;** Mark block as allocated AllocSector: ; [EF90] jsr P_EFF1 ; set buffer pointer AllocSector2: ; [EF93] jsr GetBitBAM ; already allocated? beq A_EFCE ; yes, -> done lda (BMPNT),Y eor PowersOf2,X ; allocate block sta (BMPNT),Y jsr SetBamChanged ; set flag for BAM changed ldy TEMP0 lda (BMPNT),Y sec sbc #$01 ; decrement number of blocks per track sta (BMPNT),Y lda TRACK ; track cmp DirTrack ; 18? beq A_EFBD ; yes, -> skip ;* Decrease total number of blocks lda NDBL,X ; number of free blocks lo bne A_EFBA dec NDBH,X ; decrement number of free blocks A_EFBA: ; [EFBA] dec NDBL,X A_EFBD: ; [EFBD] lda NDBH,X ; number of free blocks hi bne A_EFCE ; more than 255 blocks free? lda NDBL,X ; free blocks lo jmp J_C093 ; $C093 nop ; left over lda #$72 jsr ErrMsg2Buf ; 72, 'disk full' A_EFCE: ; [EFCE] rts ;** Get state of bit for sector in BAM entry GetBitBAM: ; [EFCF] jsr FindBamField ; find BAM field for this track tya sta TEMP0 GetBitBAM2: lda SECTOR ; sector lsr A lsr A lsr A ; divide by 8 sec adc TEMP0 tay ; byte number in BAM entry lda SECTOR ; sector number and #$07 tax ; bit number in BAM entry lda (BMPNT),Y ; byte in BAM and PowersOf2,X ; get state rts ;** Powers of 2 PowersOf2: ; [EFE9] .by $01, $02, $04, $08, $10, $20, $40, $80 ;** Write BAM after change P_EFF1: ; [EFF1] lda #$FF bit WBAM beq A_F004 bpl A_F004 bvs A_F004 lda #$00 sta WBAM ; reset flag jmp DskWriteBlock ; write block A_F004: ; [F004] rts ;** Erase BAM buffer EraseBamBuf: ; [F005] jsr SetBufPtrBAM ; pointer $6D/$6E to BAM buffer ldy #$00 tya A_F00B: ; [F00B] sta (BMPNT),Y ; erase BAM buffer iny bne A_F00B rts ;** Find BAM field for this track FindBamField: ; [F011] lda TEMP0 pha lda TEMP1 pha jmp J_FF5A ; $FF5A nop J_F01B: beq A_F022 ; drive zero? lda #$74 jsr CreErrorMsg2 ; 'drive not ready' A_F022: ; [F022] jsr GetBufNumBAM2 ; drive 0: A=13, drive 1: A=6 sta TEMP0 ; channel txa ; drive number, most probably 0 asl A sta TEMP1 ; drive number * 2 tax lda TRACK ; track cmp TBAM,X beq A_F03E inx ; altenative channel stx TEMP1 cmp TBAM,X beq A_F03E jsr P_F05B A_F03E: ; [F03E] lda TEMP1 ; drive number * 2 (maybe + 1) ldx DRVNMB ; drive number sta UBAM,X asl A asl A ; times 4 clc adc #<(BAMima) sta BMPNT lda #>(BAMima) adc #$00 sta BMPNT+1 ldy #$00 pla sta TEMP1 pla sta TEMP0 rts P_F05B: ; [F05B] ldx TEMP0 ; channel = 13 jsr ReadBAM lda DRVNMB ; drive number tax asl A ora UBAM,X eor #$01 and #$03 sta TEMP1 jsr VerifyBamImage ; [F0A5] lda ActBufNum ; buffer number asl A tax lda TRACK ; track asl A asl A ; times 4 sta BUFTABzp,X ; equal pointer in BAM field lda TEMP1 asl A asl A tay A_F07F: ; [F07F] lda (BUFTABzp,X) sta BAMima,Y lda #$00 sta (BUFTABzp,X) ; zero in buffer inc BUFTABzp,X ; increment buffer pointer iny tya and #$03 bne A_F07F ldx TEMP1 lda TRACK ; track sta TBAM,X lda WBAM bne A_F09F jmp DskWriteBlock ; write block A_F09F: ; [F09F] ora #$80 sta WBAM rts ;** Verify the BAM entry VerifyBamImage: ; [F0A5] tay lda TBAM,Y ; BAM in memory? beq A_F0D0 ; no, -> pha ; save track lda #$00 ; ???? sta TBAM,Y lda ActBufNum ; buffer number asl A ; times 2 tax pla ; restore track asl A asl A ; * 4 sta BUFTABzp,X tya ; drive asl A asl A ; * 4 to skip the four bytes of drive 0 tay A_F0BE: ; [F0BE] lda BAMima,Y sta (BUFTABzp,X) ; write in buffer lda #$00 sta BAMima,Y inc BUFTABzp,X ; increment buffer pointer iny tya and #$03 bne A_F0BE A_F0D0: ; [F0D0] rts ;** Clear the variable TBAM (+1) ClearTBAM: ; [F0D1] lda DRVNMB ; drive number asl A tax lda #$00 sta TBAM,X inx sta TBAM,X rts ;** Read BAM into page 7 if not loaded yet ; in: X = buffer number ReadBAM: ; [F0DF] lda BUF0CH1zp,X cmp #$FF ; BAM loaded? bne A_F10A ; yes, -> txa pha jsr GetBuffer tax bpl A_F0F2 lda #$70 jsr OutputErrorMsg ; 70, 'no channel' A_F0F2: ; [F0F2] stx ActBufNum pla tay txa ora #$80 sta BUF0CH1ab,Y asl A tax lda DirTrack ; 18, directory track sta TRASECzp,X ; save lda #$00 ; 0 sta TRASECzp+1,X ; as sector jmp DskReadBlock ; read block A_F10A: ; [F10A] and #$0F sta ActBufNum ; buffer number rts ;** Get buffer number for BAM GetBufNumBAM2: ; [F10F] lda #$06 ; Drive 1 -> 6 ldx DRVNMB ; drive number bne A_F118 clc adc #$07 ; Drive 0 -> 13 A_F118: ; [F118] rts ;** Get buffer number for BAM GetBufNumBAM: ; [F119] jsr GetBufNumBAM2 ; get buffer number tax rts ;** Find and allocate free block FindAllocSec: ; [F11E] jsr GetSector2 ; get track and sector number lda #$03 sta TEMP0 ; counter lda #$01 ora WBAM sta WBAM FindAllocSec2: ; [F12D] lda TEMP0 ; save counter, not needed as it is pha ; saved in FindBamField anyway jsr FindBamField ; find BAM field for this track pla sta TEMP0 ; get counter back lda (BMPNT),Y ; number of free blocks in track bne A_F173 ; blocks still free? lda TRACK ; track cmp DirTrack ; 18, directory track? beq A_F15A ; yes, 'disk full' bcc A_F15F ; smaller, then next lower track inc TRACK ; increment track number lda TRACK cmp A_FED7 ; 36, highest track number plus one bne FindAllocSec2 ; no, continue searching this track ldx DirTrack ; 18, directory track dex ; decrement stx TRACK ; save as track number lda #$00 sta SECTOR ; begin with sector number zero dec TEMP0 ; decrement counter bne FindAllocSec2 ; not yet zero, then continue A_F15A: ; [F15A] lda #$72 jsr OutputErrorMsg ; 72, 'disk full' A_F15F: ; [F15F] dec TRACK ; decrement track number bne FindAllocSec2 ; not yet 0, continue in this track ldx DirTrack ; 18, directory track inx ; increment stx TRACK ; save as track number lda #$00 sta SECTOR ; begin with sector zero dec TEMP0 ; decrement counter bne FindAllocSec2 ; not yet zero, then continue beq A_F15A ; else 'disk full' A_F173: ; [F173] lda SECTOR ; sector number clc adc SECINC ; plus step width (10) sta SECTOR ; as new number lda TRACK ; track number jsr GetMaxSectors ; get maximum sector number sta BSTSEC sta CMD ; and save cmp SECTOR ; greater than selected sector number? bcs A_F195 ; yes, -> sec ; else lda SECTOR ; sector number sbc BSTSEC ; minus maximum sector number sta SECTOR ; save as new sector number beq A_F195 ; zero? dec SECTOR ; else decrement sector number by one A_F195: ; [F195] jsr FindSecInBAM ; check BAM, find free sector beq A_F19D ; not found? A_F19A: ; [F19A] jmp AllocSector ; allocate block in BAM A_F19D: ; [F19D] lda #$00 sta SECTOR ; sector zero jsr FindSecInBAM ; find free sector bne A_F19A ; found? jmp J_F1F5 ; no, 'dir sector' ;** Find free sector and allocate FreeSecAlloc: ; [F1A9] lda #$01 ora WBAM sta WBAM ; don't write to the BAM lda R0 pha lda #$01 ; track counter sta R0 A_F1B8: ; [F1B8] lda DirTrack ; 18, directory track sec sbc R0 ; minus counter sta TRACK ; save as track number bcc A_F1CB ; result <= zero? beq A_F1CB ; then try top half of directory jsr FindBamField ; find BAM field for this track lda (BMPNT),Y ; number of free blocks in this track bne A_F1E6 ; free blocks exist A_F1CB: ; [F1CB] lda DirTrack ; 18, directory track clc adc R0 ; plus counter sta TRACK ; save as track number inc R0 ; increment counter cmp A_FED7 ; 36, max track number plus one bcc A_F1DF ; smaller, then ok lda #$67 jsr CreErrorMsg ; 67, 'illegal track or sector' A_F1DF: ; [F1DF] jsr FindBamField ; find BAM field for this track lda (BMPNT),Y ; number of free blocks? beq A_F1B8 ; no more free blocks? A_F1E6: ; [F1E6] pla sta R0 lda #$00 sta SECTOR ; sector 0 jsr FindSecInBAM ; find free sector beq J_F1F5 ; not found? jmp AllocSector ; allocate block in BAM J_F1F5: ; [F1F5] lda #$71 jsr CreErrorMsg ; 71, 'dir error' ;** Find free sectors in current track FindSecInBAM: jsr FindBamField ; find BAM field for this track tya ; Y points to number of free blocks pha jsr VerifyBam ; verify BAM lda TRACK ; track jsr GetMaxSectors ; get max number of sectors of the track sta BSTSEC ; save pla sta TEMP0 ; points to number of free blocks A_F20D: ; [F20D] lda SECTOR ; compare sector cmp BSTSEC ; with maximum number bcs A_F21D ; greater than or equal to? jsr GetBitBAM2 ; get bit number of sector bne A_F21F ; sector free? inc SECTOR ; increment sector number bne A_F20D ; always -> A_F21D: ; [F21D] lda #$00 ; no sectors free A_F21F: ; [F21F] rts ;** Verify number of free blocks in BAM [F220] VerifyBam: lda TEMP0 pha lda #$00 sta TEMP0 ; counter to zero ldy DirTrack+1 ; 4, number of bytes per track in BAM dey A_F22B: ; [F22B] ldx #7 ; check 8 bits A_F22D: ; [F22D] lda (BMPNT),Y and PowersOf2,X ; isolate bit, allocated? beq A_F236 ; yes, -> inc TEMP0 ; increment counter of free sectors A_F236: ; [F236] dex ; all 8 bits checked? bpl A_F22D ; no, -> more dey ; all bytes checked? bne A_F22B ; no, -> more lda (BMPNT),Y ; compare with number on diskette cmp TEMP0 ; same? bne A_F246 ; no, -> error pla sta TEMP0 rts A_F246: ; [F246] lda #$71 jsr CreErrorMsg ; 71, 'dir error' ;** Get maximum number of sectors for the given track GetMaxSectors: ; [F24B] ldx NumOfZones ; 4 different values A_F24E: ; [F24E] cmp NumOfZones,X ; track number dex bcs A_F24E ; not greater? lda NumSecTrack,X ; get number of sectors rts P_F258: ; [F258] rts ;** Initialize disk controller InitDiskCntrlr: ; [F259] lda #$6F ; bit 4 (write protect) and 7 (SYNC) sta DDRB2 ; as input and #$F0 sta PortB2 ; port B, control port lda PCR2 ; PCR, control register and #$FE ora #$0E ora #$E0 sta PCR2 lda #$41 ; neg. edge latch, CA2 (H), sta ACR2 ; CB1 input, CB2 = R/W control lda #$00 ; 20 msec between IRQs sta T1LL2 ; timer 1 lo latch lda #$3A sta T1LH2 ; timer 1 hi latch sta T1CH2 ; timer 1 hi lda #$7F sta IER2 ; clear IRQs lda #$C0 ; only timer 1 sta IFR2 sta IER2 ; enable IRQs lda #$FF sta CURDRV sta FTNUM ; track counter for formatting lda #$08 ; 8 sta HBID ; constants for block header lda #$07 ; 7 sta DBID ; constants for data block lda #<(StepHead) sta NXTSTzp lda #>(StepHead) ; pointer $62/$63 to $FA05 sta NXTSTzp+1 lda #$C8 ; 200 sta MINSTP lda #$04 sta AS lda #$04 sta AF ;** IRQ routine for disk controller IRQdiskCntrllr: ; [F2B0] tsx stx SAVSP ; save stackpointer lda T1CL2 ; erase flag of timer lda PCR2 ora #$0E sta PCR2 ; enable "Byte Ready" / SO J_F2BE: ; [F2BE] ldy #$05 A_F2C0: ; [F2C0] lda JOBS,Y ; command for buffer Y bpl A_F2F3 ; no, -> cmp #$D0 ; execute PRG in buffer? bne A_F2CD ; no, -> tya jmp ExecBufPRG_2 ; execute program in buffer A_F2CD: ; [F2CD] and #$01 ; isolate drive number beq A_F2D8 ; drive zero? yes, -> sty JOBN lda #$0F jmp P_F969 ; 74, 'drive not ready' A_F2D8: ; [F2D8] tax sta DRIVE cmp CURDRV ; same drive? beq A_F2E9 ; yes, -> jsr MotorOn ; turn drive motor on lda DRIVE sta CURDRV ; set flag jmp LoopDiskCntrl ; to job loop A_F2E9: ; [F2E9] lda DRVST ; ?? where initialised ?? bmi A_F2F0 asl A ; head transport programmed? bpl A_F2F9 ; no, -> A_F2F0: ; [F2F0] jmp LoopDiskCntrl ; to job loop A_F2F3: ; [F2F3] dey bpl A_F2C0 ; check next buffer jmp LoopDiskCntrl ; to job loop ;** Head transport A_F2F9: ; [F2F9] lda #$20 sta DRVST ; program motor on ldy #$05 sty JOBN A_F301: ; [F301] jsr InitPntr2Buf ; set pointer in buffer bmi A_F320 ; command for buffer? J_F306: ; [F306] dec JOBN ; decrement counter bpl A_F301 ; check next buffer ldy NXTJOB ; buffer number jsr InitPntr2Buf2 ; set pointer in buffer lda NXTTRK ; track difference for last job sta STEPS ; as counter for head transport asl STEPS lda #$60 ; set flag for head transport sta DRVST lda (HDRPNT),Y ; get track number from buffer sta DRVTRK jmp LoopDiskCntrl ; to job loop A_F320: ; [F320] and #$01 ; isolate drive number cmp DRIVE ; equal drive number of last job? bne J_F306 ; no, -> lda DRVTRK ; last track number beq A_F33C ; equal zero? sec sbc (HDRPNT),Y ; equal track number of this job? beq A_F33C ; yes, -> eor #$FF sta NXTTRK inc NXTTRK lda JOBN sta NXTJOB jmp J_F306 A_F33C: ; [F33C] ldx #$04 lda (HDRPNT),Y ; track number of the job sta TRACC ; save A_F342: ; [F342] cmp NumOfZones,X ; compare with maximum track number dex bcs A_F342 ; greater? lda NumSecTrack,X ; get number of sectors per track sta SECCNT ; and save ;** Create value for density for PB5/PB6 txa asl A asl A asl A asl A asl A sta WORK ; gives 0, 32, 64, 96 lda PortB2 and #$9F ora WORK ; generate control byte for motor sta PortB2 ldx DRIVE lda JOB ; command code cmp #$40 ; position head? beq A_F37C ; yes, -> cmp #$60 ; command code for program execution? beq ExecBufPRG ; yes, -> jmp ReadHeader ; read block header ;** Execute program in buffer ExecBufPRG: ; [F36E] lda JOBN ExecBufPRG_2: ; [F370] clc adc #$03 ; plus 3 sta BUFPNT+1 lda #$00 ; equals address of buffer sta BUFPNT jmp (J_BUFPNT) ; execute program in buffer ;** Bump, find track 1 (head at stop) A_F37C: ; [F37C] lda #$60 sta DRVST ; set flag for head transport lda PortB2 and #$FC ; turn stepper motors on sta PortB2 lda #$A4 ; -45 sta STEPS ; step counter for head transport lda #$01 sta DRVTRK ; track number A_F390: ; [F390] jmp P_F969 ; ok ;** Initialize pointer in buffer InitPntr2Buf: ; [F393] ldy JOBN InitPntr2Buf2: ; [F395] lda JOBS,Y ; command code pha ; save bpl A_F3AB and #$78 ; erase bits 0,1,2, and 7 sta JOB tya ; buffer number asl A ; times two adc #$06 ; plus 6 sta HDRPNT ; equals pointer to actual buffer tya ; buffer number clc adc #$03 ; plus 3 sta BUFPNT+1 ; equals buffer address hi A_F3AB: ; [F3AB] ldy #$00 sty BUFPNT ; buffer address lo pla ; get command code back rts ;** Read block header, verify ID ReadHeader: ; [F3B1] ldx #$5A ; 90 stx TMP ; counter ldx #$00 lda #$52 ; GRC code for block header sta STAB0zp A_F3BB: ; [F3BB] jsr Wait4Sync ; wait for SYNC A_F3BE: ; [F3BE] bvc A_F3BE ; byte ready? clv lda PortA2 ; data from read head cmp STAB0zp bne A_F407 ; 20, 'read error' A_F3C8: ; [F3C8] bvc A_F3C8 ; byte ready? clv lda PortA2 ; data byte from disk (block header) sta STAB1,X ; save 7 bytes inx cpx #$07 bne A_F3C8 ; continue reading jsr GCR2Header ldy #$04 ; 4 bytes plus parity lda #$00 A_F3DC: ; [F3DC] eor HDR1IDab,Y ; generate checksum for header dey bpl A_F3DC cmp #$00 ; parity ok? bne A_F41E ; 27, 'read error' ldx CURDRV ; drive number lda HDRTRK ; track number of header sta DRVTRK,X ; use as actual track number lda JOB cmp #$30 ; code for 'preserve header'? beq A_F410 ; yes, -> lda CURDRV asl A tay lda DISKIDab,Y cmp HDR1IDzp ; compare with ID1 bne A_F41B lda IMDIIDab,Y cmp HDR2ID ; compare with ID2 bne A_F41B ; <>, then 29, 'disk id mismatch' jmp JobOptimal A_F407: ; [F407] dec TMP ; decrement counter for attempts bne A_F3BB ; and try again lda #$02 ; else jsr P_F969 ; 20, 'read error' ;** preserve block header A_F410: ; [F410] lda HDR1IDzp ; ID1 sta DISKIDzp lda HDR2ID ; and ID2 sta IMDIIDzp ; preserve J_F418: ; [F418] lda #$01 ; ok .by $2C ; dummy BIT opcode A_F41B: ; [F41B] lda #$0B ; 29, 'disk id mismatch' .by $2C ; dummy BIT opcode A_F41E: ; [F41E] lda #$09 ; 27, 'write error' jmp P_F969 ; done ;** Job optimisation JobOptimal: ; [F423] lda #$7F sta CSECT lda HDRSEC clc adc #$02 cmp SECCNT ; max. sectors/track bcc A_F432 sbc SECCNT A_F432: ; [F432] sta NEXTS ldx #$05 stx JOBN ldx #$FF A_F43A: ; [F43A] jsr InitPntr2Buf ; set buffer pointer for disk controller bpl A_F483 ; no job, -> sta WORK ; save job code and #$01 cmp CURDRV ; momentary drive? bne A_F483 ; no, -> ldy #$00 lda (HDRPNT),Y ; get track # cmp TRACC ; same as from momentary job? bne A_F483 ; no, -> lda JOB ; command code cmp #$60 ; execute program in buffer? beq A_F461 ; yes, -> ldy #$01 sec lda (HDRPNT),Y ; get sector # sbc NEXTS bpl A_F461 clc adc SECCNT A_F461: ; [F461] cmp CSECT bcs A_F483 pha lda JOB beq A_F47E pla cmp #$09 bcc A_F483 cmp #$0C bcs A_F483 A_F473: ; [F473] sta CSECT lda JOBN tax adc #$03 sta BUFPNT+1 bne A_F483 A_F47E: ; [F47E] pla cmp #$06 bcc A_F473 A_F483: ; [F483] dec JOBN bpl A_F43A txa bpl A_F48D jmp LoopDiskCntrl ; to job loop A_F48D: ; [F48D] stx JOBN jsr InitPntr2Buf ; get buffer number lda JOB ; command code jmp J_F4CA ; continue checking GCR2Header: lda BUFPNT ; [F497] pha ; save pointer $30/$31 lda BUFPNT+1 pha lda #<(STAB0ab) sta BUFPNT lda #>(STAB0ab) ; pointer $30/$31 to $24 sta BUFPNT+1 lda #$00 sta GCRPNT jsr P_F7E6 lda BTAB3 sta HDRTRK lda BTAB2 sta HDRSEC lda BTAB1 sta HDRCHK jsr P_F7E6 lda BTAB0 sta HDR2ID lda BTAB1 sta HDR1IDzp pla sta BUFPNT+1 pla ; get pointer $30/$31 back sta BUFPNT rts ;** Test command code further J_F4CA: ; [F4CA] cmp #$00 ; command code for 'read'? beq A_F4D1 ; yes, -> jmp J_F56E ; continue checking command ;** Read sector A_F4D1: ; [F4D1] jsr FindDatablock ; find beginning of data block A_F4D4: ; [F4D4] bvc A_F4D4 ; byte ready? clv lda PortA2 ; get data byte sta (BUFPNT),Y ; and write in buffer iny ; 256 times bne A_F4D4 ldy #$BA A_F4E1: ; [F4E1] bvc A_F4E1 ; byte ready? clv lda PortA2 ; read bytes sta A_0100,Y ; from $1BA to $1FF iny bne A_F4E1 jsr P_F8E0 lda BID cmp DBID ; equal 7, beginning of data block? beq A_F4FB ; yes, -> lda #$04 ; 22, 'read error' jmp P_F969 ; error termination A_F4FB: ; [F4FB] jsr P_F5E9 ; calculate parity of data block cmp CHKSUM ; agreement? beq A_F505 ; yes, -> lda #$05 ; 23, 'read error' .by $2C ; dummy BIT opcode A_F505: ; [F505] lda #$01 ; ok jmp P_F969 ; prepare error message ;** Find start of data block FindDatablock: ; [F50A] jsr FindSector ; read block header jmp Wait4Sync ; wait for SYNC ;** Read block header FindSector: ; [F510] lda DRIVE ; drive number asl A tax lda DISKIDzp,X ; ID1 sta HDR1IDzp ; save lda IMDIIDzp,X ; ID2 sta HDR2ID ; save ldy #$00 lda (HDRPNT),Y ; get track and sta HDRTRK iny lda (HDRPNT),Y ; sector number from buffer sta HDRSEC lda #$00 eor HDR1IDzp eor HDR2ID ; calculate parity for block header eor HDRTRK eor HDRSEC sta HDRCHK ; and save ;** At this point the track and sector to be searched for is stored jsr Header2gcr ; convert to GCR ;** Now compare data of all headers with stored GCRed data ldx #$5A ; 90 attempts A_F538: ; [F538] jsr Wait4Sync ; wait for SYNC ldy #$00 A_F53D: ; [F53D] bvc A_F53D ; byte ready? clv lda PortA2 ; read data from block header cmp STAB0ab,Y ; compare with saved data bne A_F54E ; not the same, try again iny cpy #$08 ; 8 bytes read? bne A_F53D ; no, -> ;** Sector is found !!! rts A_F54E: ; [F54E] dex ; decrement counter bne A_F538 ; not yet zero? lda #$02 A_F553: ; [F553] jmp P_F969 ; 20, 'read error' ;** Wait for SYNC Wait4Sync: ; [F556] lda #$D0 ; 208 sta T1CH1 ; start timer lda #$03 ; error code A_F55D: ; [F55D] bit T1CH1 bpl A_F553 ; timer run down, then 'read error' bit PortB2 ; SYNC signal bmi A_F55D ; not yet found? lda PortA2 ; read byte clv ldy #$00 rts ;** Test command code further J_F56E: ; [F56E] cmp #$10 ; command code for 'write' beq A_F575 ; yes, -> jmp J_F691 ; continue checking command code ;** Write data block to disk A_F575: ; [F575] jsr P_F5E9 ; calculate parity for buffer sta CHKSUM ; and save lda PortB2 ; read port B and #$10 ; isolate bit for 'write protect' bne A_F586 ; not set, ok lda #$08 jmp P_F969 ; 26, 'write protect' A_F586: ; [F586] jsr P_F78F jsr FindSector ; find block header ldx #$09 A_F58E: ; [F58E] bvc A_F58E ; byte ready? clv dex bne A_F58E lda #$FF sta DDRA2 ; Port A = output lda PCR2 and #$1F ora #$C0 ; CB2 is output, manual, (L) sta PCR2 ; (L) = write lda #$FF ldx #$05 sta PortA2 ; write $FF to disk 5 times clv A_F5AB: ; [F5AB] bvc A_F5AB ; as SYNC characters clv dex bne A_F5AB ldy #$BB A_F5B3: ; [F5B3] lda A_0100,Y ; bytes $1BB to $1FF to disk A_F5B6: ; [F5B6] bvc A_F5B6 clv sta PortA2 iny bne A_F5B3 A_F5BF: ; [F5BF] lda (BUFPNT),Y ; write data buffer (256 bytes) A_F5C1: ; [F5C1] bvc A_F5C1 clv sta PortA2 iny bne A_F5BF A_F5CA: ; [F5CA] bvc A_F5CA ; byte ready? lda PCR2 ora #$E0 ; PCR to input again sta PCR2 ; (H) = read lda #$00 sta DDRA2 ; Port A = input jsr Gcr2Data ldy JOBN lda JOBS,Y eor #$30 ; convert command code 'write' to ; 'verify' sta JOBS,Y jmp ReadHeader ;** Calculate parity for data buffer P_F5E9: ; [F5E9] lda #$00 tay A_F5EC: ; [F5EC] eor (BUFPNT),Y iny bne A_F5EC rts ;** Convert GCR data to normal data Gcr2Data: ; [F5F2] lda #$00 sta SAVPNT sta BUFPNT sta NXTPNT lda BUFPNT+1 sta NXTBF lda #$01 sta BUFPNT+1 sta SAVPNT+1 lda #$BB sta GCRPNT sta BYTCNT jsr P_F7E6 lda BTAB0 sta BID ldy BYTCNT lda BTAB1 sta (SAVPNT),Y iny lda BTAB2 sta (SAVPNT),Y iny lda BTAB3 sta (SAVPNT),Y iny sty BYTCNT A_F624: ; [F624] jsr P_F7E6 ldy BYTCNT lda BTAB0 sta (SAVPNT),Y iny lda BTAB1 sta (SAVPNT),Y iny beq A_F643 lda BTAB2 sta (SAVPNT),Y iny lda BTAB3 sta (SAVPNT),Y iny sty BYTCNT bne A_F624 A_F643: ; [F643] lda BTAB2 sta (BUFPNT),Y iny lda BTAB3 sta (BUFPNT),Y iny sty BYTCNT A_F64F: ; [F64F] jsr P_F7E6 ldy BYTCNT lda BTAB0 sta (BUFPNT),Y iny lda BTAB1 sta (BUFPNT),Y iny lda BTAB2 sta (BUFPNT),Y iny lda BTAB3 sta (BUFPNT),Y iny sty BYTCNT cpy #$BB bcc A_F64F lda #$45 sta SAVPNT lda BUFPNT+1 sta SAVPNT+1 ldy #$BA A_F678: ; [F678] lda (BUFPNT),Y sta (SAVPNT),Y dey bne A_F678 lda (BUFPNT),Y sta (SAVPNT),Y ldx #$BB A_F685: ; [F685] lda A_0100,X sta (BUFPNT),Y iny inx bne A_F685 stx GCRFLG ; GCRFLG := 0 rts ;** Test command code further J_F691: ; [F691] cmp #$20 ; command code for 'verify'? beq A_F698 ; yes, -> jmp J_F6CA ; continue checking command code ;** Compare written data with data on disk A_F698: ; [F698] jsr P_F5E9 ; calculate parity for data buffer sta CHKSUM ; and save jsr P_F78F jsr FindDatablock ; find start of data block ldy #$BB A_F6A5: ; [F6A5] lda A_0100,Y ; data from buffer A_F6A8: ; [F6A8] bvc A_F6A8 ; byte ready? clv eor PortA2 ; compare with data from disk bne A_F6C5 ; not equal, then error iny bne A_F6A5 A_F6B3: ; [F6B3] lda (BUFPNT),Y ; data from buffer A_F6B5: ; [F6B5] bvc A_F6B5 clv eor PortA2 ; compare with data from disk bne A_F6C5 ; not equal, then error iny cpy #$FD bne A_F6B3 jmp J_F418 ; error free termination A_F6C5: ; [F6C5] lda #$07 jmp P_F969 ; 25, 'write error' ;** Command code for find sector J_F6CA: ; [F6CA] jsr FindSector ; read block header jmp J_F418 ; done ;** Convert 4 bytes ($52-$55) to 5 GCR bytes ($56-$5a) P_F6D0: ; [F6D0] lda #$00 sta GTAB1 sta GTAB4 ldy GCRPNT lda BTAB0 and #$F0 ; isolate hi-nibble lsr A lsr A ; and rotate to lower nibble lsr A lsr A tax ; as index in table lda A_F77F,X asl A asl A ; times 8 asl A sta GTAB0 lda BTAB0 and #$0F ; isolate lower nibble tax ; as index in table lda A_F77F,X ror A ror GTAB1 ror A ror GTAB1 and #$07 ora GTAB0 sta (BUFPNT),Y ; in buffer iny ; increment buffer lda BTAB1 and #$F0 ; isolate upper nibble lsr A lsr A lsr A ; shift to upper nibble lsr A tax ; as index in table lda A_F77F,X asl A ora GTAB1 sta GTAB1 lda BTAB1 and #$0F ; lower nibble tax ; as index lda A_F77F,X rol A rol A rol A rol A sta GTAB2 rol A and #$01 ora GTAB1 sta (BUFPNT),Y ; in buffer iny ; increment buffer lda BTAB2 and #$F0 ; isolate hi-nibble lsr A lsr A lsr A lsr A tax lda A_F77F,X clc ror A ora GTAB2 sta (BUFPNT),Y ; in buffer iny ; increment buffer pointer ror A and #$80 sta GTAB3 lda BTAB2 and #$0F ; lower nibble tax ; as index lda A_F77F,X asl A asl A and #$7C ora GTAB3 sta GTAB3 lda BTAB3 and #$F0 ; isolate hi-nibble lsr A lsr A ; shift to lower nibble lsr A lsr A tax ; as index in table lda A_F77F,X ror A ror GTAB4 ror A ror GTAB4 ror A ror GTAB4 and #$03 ora GTAB3 sta (BUFPNT),Y ; in buffer iny ; increment buffer pointer bne A_F76F lda SAVPNT+1 sta BUFPNT+1 A_F76F: ; [F76F] lda BTAB3 and #$0F ; lower nibble tax ; as index lda A_F77F,X ora GTAB4 sta (BUFPNT),Y ; in buffer iny ; increment buffer pointer sty GCRPNT ; and save rts ;** GCR code table A_F77F: ; [F77F] .by $0A, $0B, $12, $13, $0E, $0F, $16 ; ....... .by $17, $09, $19, $1A, $1B, $0D, $1D ; ....... .by $1E, $15 ; .. ;** Convert 260 bytes to 325 bytes group code P_F78F: ; [F78F] lda #$00 sta BUFPNT sta SAVPNT sta BYTCNT lda #$BB sta GCRPNT sta GCRFLG lda BUFPNT+1 sta SAVPNT+1 lda #$01 sta BUFPNT+1 lda DBID sta BTAB0 ldy BYTCNT lda (SAVPNT),Y sta BTAB1 iny lda (SAVPNT),Y sta BTAB2 iny lda (SAVPNT),Y sta BTAB3 iny A_F7BA: ; [F7BA] sty BYTCNT jsr P_F6D0 ldy BYTCNT lda (SAVPNT),Y sta BTAB0 iny beq A_F7D9 lda (SAVPNT),Y sta BTAB1 iny lda (SAVPNT),Y sta BTAB2 iny lda (SAVPNT),Y sta BTAB3 iny bne A_F7BA A_F7D9: ; [F7D9] lda CHKSUM sta BTAB1 lda #$00 sta BTAB2 sta BTAB3 jmp P_F6D0 ;** Convert 5 GCR bytes to 4 normal bytes P_F7E6: ; [F7E6] ldy GCRPNT lda (BUFPNT),Y and #$F8 lsr A lsr A lsr A sta GTAB0 lda (BUFPNT),Y and #$07 asl A asl A sta GTAB1 iny bne A_F802 lda NXTBF sta BUFPNT+1 ldy NXTPNT A_F802: ; [F802] lda (BUFPNT),Y and #$C0 rol A rol A rol A ora GTAB1 sta GTAB1 lda (BUFPNT),Y and #$3E lsr A sta GTAB2 lda (BUFPNT),Y and #$01 asl A asl A asl A asl A sta GTAB3 iny lda (BUFPNT),Y and #$F0 lsr A lsr A lsr A lsr A ora GTAB3 sta GTAB3 lda (BUFPNT),Y and #$0F asl A sta GTAB4 iny lda (BUFPNT),Y and #$80 clc rol A rol A and #$01 ora GTAB4 sta GTAB4 lda (BUFPNT),Y and #$7C lsr A lsr A sta GTAB5 lda (BUFPNT),Y and #$03 asl A asl A asl A sta GTAB6 iny bne A_F85A lda NXTBF sta BUFPNT+1 ldy NXTPNT A_F85A: ; [F85A] lda (BUFPNT),Y and #$E0 rol A rol A rol A rol A ora GTAB6 sta GTAB6 lda (BUFPNT),Y and #$1F sta GTAB7 iny sty GCRPNT ldx GTAB0 lda A_F8A0,X ldx GTAB1 ora A_F8C0,X sta BTAB0 ldx GTAB2 lda A_F8A0,X ldx GTAB3 ora A_F8C0,X sta BTAB1 ldx GTAB4 lda A_F8A0,X ldx GTAB5 ora A_F8C0,X sta BTAB2 ldx GTAB6 lda A_F8A0,X ldx GTAB7 ora A_F8C0,X sta BTAB3 rts ;** Conversion table GCR to binary - high byte $FF means invalid A_F8A0: ; [F8A0] .by $FF, $FF, $FF, $FF, $FF, $FF, $FF ; ....... .by $FF, $FF, $80, $00, $10, $FF, $C0 ; ....... .by $40, $50, $FF, $FF, $20, $30, $FF ; @P.. 0. .by $F0, $60, $70, $FF, $90, $A0, $B0 ; .`p.... .by $FF, $D0, $E0, $FF ; .... ;** Conversion table GCR to binary - low byte $FF means invalid A_F8C0: ; [F8C0] .by $FF, $FF, $FF, $FF, $FF, $FF, $FF ; ....... .by $FF, $FF, $08, $00, $01, $FF, $0C ; ....... .by $04, $05, $FF, $FF, $02, $03, $FF ; ....... .by $0F, $06, $07, $FF, $09, $0A, $0B ; ....... .by $FF, $0D, $0E, $FF ; .... ;** Decode 69 GCR bytes P_F8E0: ; [F8E0] lda #$00 sta GCRPNT sta SAVPNT sta BYTCNT lda #$01 sta NXTBF lda #$BA sta NXTPNT lda BUFPNT+1 sta SAVPNT+1 jsr P_F7E6 lda BTAB0 sta BID ldy BYTCNT lda BTAB1 sta (SAVPNT),Y iny lda BTAB2 sta (SAVPNT),Y iny lda BTAB3 sta (SAVPNT),Y iny A_F90C: ; [F90C] sty BYTCNT jsr P_F7E6 ldy BYTCNT lda BTAB0 sta (SAVPNT),Y iny beq A_F92B lda BTAB1 sta (SAVPNT),Y iny lda BTAB2 sta (SAVPNT),Y iny lda BTAB3 sta (SAVPNT),Y iny bne A_F90C A_F92B: ; [F92B] lda BTAB1 sta CHKSUM lda SAVPNT+1 sta BUFPNT+1 rts ;** Convert block header to GCR code Header2gcr: ; [F934] lda BUFPNT+1 sta SAVPNT+1 lda #$00 sta BUFPNT+1 lda #$24 sta GCRPNT lda HBID sta BTAB0 lda HDRCHK sta BTAB1 lda HDRSEC sta BTAB2 lda HDRTRK sta BTAB3 jsr P_F6D0 lda HDR2ID sta BTAB0 lda HDR1IDzp sta BTAB1 lda #$00 sta BTAB2 sta BTAB3 jsr P_F6D0 lda SAVPNT+1 sta BUFPNT+1 rts ;** Error entry disk controller P_F969: ; [F969] ldy JOBN sta JOBS,Y lda GCRFLG beq A_F975 jsr Gcr2Data ; [F5F2] A_F975: ; [F975] jsr MotorOff ldx SAVSP ; get stack pointer back txs jmp J_F2BE ;** Turn drive motor on MotorOn: ; [F97E] lda #$A0 sta DRVST lda PortB2 ora #$04 ; turn drive motor on sta PortB2 lda #$3C sta ACLTIM rts ;** Turn drive motor off (logical) MotorOff: ; [F98F] ldx CURDRV ; why? -> see $F978 lda DRVST ora #$10 ; turn drive motor off sta DRVST lda #$FF sta ACLTIM rts ;** Job loop disk controller LoopDiskCntrl: ; [F99C] lda T1LH2 sta T1CH2 ;* has writeprotect status changed? lda PortB2 and #$10 ; write protect? cmp LWPT0 sta LWPT0 beq A_F9B1 ; Not changed, -> lda #$01 sta WPSW0 ; state has changed ;* check if head is above track: PHASE is 0 or 2 A_F9B1: ; [F9B1] lda PHASE beq A_F9CB cmp #$02 bne A_F9C1 lda #$00 sta PHASE beq A_F9CB ; always -> A_F9C1: ; [F9C1] sta STEPS lda #$02 ; why, PHASE is already 2 IMHO ??? sta PHASE jmp J_FA2E A_F9CB: ; [F9CB] ldx CURDRV ; drive active? bmi A_F9D6 ; no, -> lda DRVST tay cmp #$20 ; drivemotor on? bne A_F9D9 ; no, -> A_F9D6: ; [F9D6] jmp J_FABE A_F9D9: ; [F9D9] dec ACLTIM ; drive is up to speed? bne A_F9FA ; no, -> tya ; A = DRVST bpl A_F9E4 ; drive already marked ready, -> and #$7F ; mark ready sta DRVST A_F9E4: ; [F9E4] and #$10 ; shut down drive motor ? beq A_F9FA ; no, -> ;** Drive motor off (hardware) lda PortB2 and #$FB sta PortB2 lda #$FF sta CURDRV lda #$00 sta DRVST beq A_F9D6 ; always -> A_F9FA: ; [F9FA] tya and #$40 ; activate steppermotor? bne A_FA02 ; yes, -> jmp J_FABE A_FA02: ; [FA02] jmp (NXTSTab) ; StepHead [FA05] ;** Step the head StepHead: ; [FA05] lda STEPS bpl A_FA0E eor #$FF clc adc #$01 A_FA0E: ; [FA0E] cmp MINSTP ; fast stepping? bcs A_FA1C ; yes, -> lda #<(E_FA3B) sta NXTSTzp lda #>(E_FA3B) ; pointer $62/$63 to $FA3B sta NXTSTzp+1 bne J_FA2E ;** Calculate number of head steps A_FA1C: ; [FA1C] sbc AS sbc AS sta RSTEPS lda AS sta ACLSTP lda #<(E_FA7B) sta NXTSTzp lda #>(E_FA7B) ; pointer $62/$63 to $FA7B sta NXTSTzp+1 J_FA2E: ; [FA2E] lda STEPS ; step counter for head transport bpl A_FA63 inc STEPS ; increment ldx PortB2 dex jmp J_FA69 ;** Move stepper motor short distance E_FA3B: ; [FA3B] lda STEPS ; step counter for head transport bne J_FA2E ; not yet zero? lda #<(E_FA4E) sta NXTSTzp lda #>(E_FA4E) ; pointer $62/$63 to $FA4E sta NXTSTzp+1 lda #5 sta ACLSTP ; counter to 5 jmp J_FABE ;** Load head E_FA4E: ; [FA4E] dec ACLSTP ; decrement counter bne J_FABE ; not yet zero? lda DRVST and #$BF ; erase bit 6 sta DRVST lda #<(StepHead) sta NXTSTzp lda #>(StepHead) ; pointer $62/$63 to $FA05 sta NXTSTzp+1 jmp J_FABE A_FA63: ; [FA63] dec STEPS ; step counter for head transport ldx PortB2 inx J_FA69: ; [FA69] txa and #$03 sta TMP lda PortB2 and #$FC ora TMP sta PortB2 jmp J_FABE ;** prepare fast head movement E_FA7B: ; [FA7B] sec lda T1LH2 sbc AF sta T1CH2 dec ACLSTP ; decrement counter bne A_FA94 ; not yet zero? lda AS sta ACLSTP lda #<(E_FA97) sta NXTSTzp lda #>(E_FA97) ; pointer $62/$63 to $FA97 sta NXTSTzp+1 A_FA94: ; [FA94] jmp J_FA2E ;** Fast head movement E_FA97: ; [FA97] dec RSTEPS bne A_FA94 lda #<(E_FAA5) sta NXTSTzp lda #>(E_FAA5) ; pointer $62/$63 to $FAA5 sta NXTSTzp+1 bne A_FA94 ;** prepare slow head moveme\nt E_FAA5: ; [FAA5] lda T1LH2 clc adc AF sta T1CH2 dec ACLSTP ; decrement counter bne A_FA94 ; not yet zero? lda #<(E_FA4E) sta NXTSTzp lda #>(E_FA4E) ; pointer $62/$63 to $FA4E sta NXTSTzp+1 lda #5 sta ACLSTP ; counter to 5 J_FABE: ; [FABE] lda PCR2 and #$FD ; erase bit 1 sta PCR2 ; disable "Byte ready" rts ;** Formatting E_FAC7: ; [FAC7] lda FTNUM ; track number bpl A_FAF5 ; formatting already in progress ldx DRIVE ; drive number lda #$60 ; flag for head transport sta DRVST,X ; set lda #$01 sta DRVTRK,X ; set destination track sta FTNUM ; running track number for format lda #$A4 ; - 46 tracks sta STEPS ; step counter for head transport lda PortB2 and #$FC ; set phase to 0 sta PortB2 lda #$0A ; 10 sta A_0620 ; error counter lda #$A0 ; $621/$622 = 4000 sta A_0621 ; initialize track capacity lda #$0F ; 4000 < capacity < 2*4000 bytes sta A_0622 jmp LoopDiskCntrl ; back in job loop A_FAF5: ; [FAF5] ldy #$00 cmp (HDRPNT),Y beq A_FB00 sta (HDRPNT),Y jmp LoopDiskCntrl ; to job loop A_FB00: ; [FB00] lda PortB2 and #$10 ; write protect? bne J_FB0C ; no, -> lda #$08 jmp J_FDD3 ; 26, 'write protect on' J_FB0C: ; [FB0C] jsr P_FDA3 ; write $FF to disk 10240 times jsr P_FDC3 ; code ($621/$622) times to disk lda #$55 ; $55 sta PortA2 ; to write head jsr P_FDC3 ; and ($621/$622) times to disk jsr P_FE00 ; switch to read jsr Wait4Sync ; set timer, find $FF (SYNC) lda #$40 ora ACR1 ; timer 1 free running sta ACR1 lda #$62 ; 98 cycles, about 0.1 ms sta T1LL1 lda #$00 sta T1LH1 sta T1CH1 ; start timer ldy #$00 ; counter to zero ldx #$00 A_FB39: ; [FB39] bit PortB2 ; SYNC found? bmi A_FB39 ; no, wait A_FB3E: ; [FB3E] bit PortB2 ; SYNC found? bpl A_FB3E ; wait for SYNC A_FB43: ; [FB43] lda T1CL1 ; reset interrupt flag timer A_FB46: ; [FB46] bit PortB2 ; SYNC found? bpl A_FB5C ; not SYNC ($55)? lda IFR1 ; interrupt flag register asl A ; shift timer flag bpl A_FB46 ; timer not run down yet? inx ; increment counter bne A_FB43 iny ; increment hi-byte of counter bne A_FB43 lda #$02 ; overflow, then error jmp J_FDD3 ; 20, 'read error' A_FB5C: ; [FB5C] stx TEMP2 sty TEMP3 ldx #$00 ldy #$00 ; counter to zero again A_FB64: ; [FB64] lda T1CL1 ; reset timer 1 interrupt flag A_FB67: ; [FB67] bit PortB2 ; SYNC found? bmi A_FB7D ; yes, -> lda IFR1 ; interrupt-flag register asl A ; timer flag to bit 7 bpl A_FB67 ; no, wait until timer run down inx bne A_FB64 ; increment counter iny bne A_FB64 lda #$02 ; overflow, then error jmp J_FDD3 ; 20, 'read error' A_FB7D: ; [FB7D] sec txa sbc TEMP2 ; difference between counter tax sta TEMP1 tya ; and value for $FF-storage sbc TEMP3 tay ; bring to $70/$71 sta TEMP2 bpl A_FB97 ; difference positive? eor #$FF tay txa eor #$FF ; calculate absolute value of difference tax inx bne A_FB97 iny A_FB97: ; [FB97] tya bne A_FB9E cpx #$04 ; difference less than 4 * 0.1 ms bcc A_FBB6 ; yes, -> A_FB9E: ; [FB9E] asl TEMP1 rol TEMP2 ; double difference clc lda TEMP1 adc A_0621 sta A_0621 ; add to 4000 lda TEMP2 adc A_0622 sta A_0622 jmp J_FB0C ; repeat until difference < 4 * 0.1 ms A_FBB6: ; [FBB6] ldx #$00 ldy #$00 ; counter to zero clv A_FBBB: ; [FBBB] lda PortB2 ; SYNC? bpl A_FBCE ; no, -> bvc A_FBBB ; byte ready? clv inx bne A_FBBB ; increment counter iny bne A_FBBB lda #$03 ; overflow, then error jmp J_FDD3 ; 21, 'read error' A_FBCE: ; [FBCE] txa asl A ; double counter sta A_0625 tya rol A sta A_0624 ; and to $624/$625 as track capacity lda #$BF and ACR1 sta ACR1 lda #$66 ; 102 sta A_0626 ldx SECCNT ; number of sectors in this track ldy #$00 tya A_FBEA: ; [FBEA] clc adc A_0626 bcc A_FBF1 iny A_FBF1: ; [FBF1] iny dex bne A_FBEA ; calculate number of bytes eor #$FF sec adc #$00 clc adc A_0625 bcs A_FC03 dec A_0624 A_FC03: ; [FC03] tax tya eor #$FF sec adc #$00 clc adc A_0624 ; result in A/X bpl A_FC15 lda #$04 jmp J_FDD3 ; 22, 'read error' A_FC15: ; [FC15] tay txa ldx #$00 A_FC19: ; [FC19] sec ; total divided by number sbc SECCNT ; of sectors ($43) bcs A_FC21 dey bmi A_FC24 A_FC21: ; [FC21] inx bne A_FC19 A_FC24: ; [FC24] stx A_0626 ; compare number of bytes per interval cpx #$04 ; with minimum value bcs A_FC30 ; ok lda #$05 jmp J_FDD3 ; 23, 'read error' A_FC30: ; [FC30] clc ; remainder of division adc SECCNT ; plus number of sectors sta A_0627 ; save lda #$00 sta A_0628 ; counter for sectors ldy #$00 ; counter lo ldx DRIVE ; drive number A_FC3F: ; [FC3F] lda HBID ; constant 8, marker for header sta BUF0,Y ; in buffer iny iny lda A_0628 ; sector number sta BUF0,Y ; in buffer iny lda FTNUM ; track number sta BUF0,Y ; in buffer iny lda IMDIIDzp,X ; ID 2 sta BUF0,Y ; in buffer iny lda DISKIDzp,X ; ID 1 sta BUF0,Y ; in buffer iny lda #$0F ; 15 sta BUF0,Y ; in buffer iny sta BUF0,Y ; 15 in buffer iny lda #$00 eor NDBL,Y eor A_02FB,Y eor NDBH,Y ; generate checksum eor A_02FD,Y sta WBAM,Y inc A_0628 ; increment counter lda A_0628 ; counter cmp SECCNT ; compare with number of sectors bcc A_FC3F ; smaller, then continue tya pha inx ; X := 1 WHY? is said to be bug txa ; A := 1 A_FC88: ; [FC88] sta BUF2,X inx bne A_FC88 lda #$03 ; buffer pointer to $300 sta BUFPNT+1 jsr P_FE30 pla tay dey jsr P_FDE5 ; copy buffer data jsr P_FDF5 ; copy data in buffer lda #$05 sta BUFPNT+1 ; buffer pointer to $500 jsr P_F5E9 ; calculate parity for data buffer sta CHKSUM ; and save jsr P_F78F lda #$00 sta HDRPNT jsr P_C04E A_FCB1: ; [FCB1] lda #$FF sta PortA2 ; to write head ldx #$05 ; write $FF 5 times A_FCB8: ; [FCB8] bvc A_FCB8 ; byte ready clv dex bne A_FCB8 ldx #$0A ; 10 times ldy HDRPNT ; buffer pointer A_FCC2: ; [FCC2] bvc A_FCC2 ; byte ready? clv lda BUF0,Y ; data from buffer sta PortA2 ; write iny dex ; 10 data written? bne A_FCC2 ldx #$09 A_FCD1: ; [FCD1] bvc A_FCD1 ; byte ready? clv lda #$55 ; $55 sta PortA2 ; write dex bne A_FCD1 ; 9 times? lda #$FF ; $FF ldx #$05 ; 5 times A_FCE0: ; [FCE0] bvc A_FCE0 ; byte ready? clv sta PortA2 ; to write head dex bne A_FCE0 ldx #$BB A_FCEB: ; [FCEB] bvc A_FCEB clv lda A_0100,X ; area $1BB to $1FF sta PortA2 ; save inx bne A_FCEB ldy #$00 A_FCF9: ; [FCF9] bvc A_FCF9 ; byte ready? clv lda (BUFPNT),Y ; 256 bytes of data sta PortA2 ; write byte to disk iny bne A_FCF9 lda #$55 ; $55 ldx A_0626 ; ($626) times A_FD09: ; [FD09] bvc A_FD09 clv sta PortA2 ; write dex bne A_FD09 lda HDRPNT clc adc #$0A ; plus 10 sta HDRPNT dec A_0628 ; decrement sector number bne A_FCB1 A_FD1E: ; [FD1E] bvc A_FD1E ; byte ready? clv A_FD21: ; [FD21] bvc A_FD21 ; byte ready? clv jsr P_FE00 ; switch to reading lda #$C8 ; 200 sta A_0623 A_FD2C: ; [FD2C] lda #$00 sta BUFPNT lda #$03 ; buffer pointer to $300 sta BUFPNT+1 lda SECCNT ; number of sectors per track sta A_0628 A_FD39: ; [FD39] jsr Wait4Sync ; wait for SYNC ldx #$0A ; 10 data ldy #$00 A_FD40: ; [FD40] bvc A_FD40 ; byte ready? clv lda PortA2 ; read byte cmp (BUFPNT),Y ; compare with data in buffer bne A_FD58 ; not equal, error iny dex bne A_FD40 clc lda BUFPNT adc #$0A ; increment pointer by 10 sta BUFPNT jmp J_FD62 A_FD58: ; [FD58] dec A_0623 ; decrement counter for attempts bne A_FD2C ; not yet zero? lda #$06 ; else error jmp J_FDD3 ; 24, 'read error' J_FD62: ; [FD62] jsr Wait4Sync ; wait for SYNC ldy #$BB A_FD67: ; [FD67] bvc A_FD67 ; byte ready? clv lda PortA2 ; read byte cmp A_0100,Y ; compare with buffer contents bne A_FD58 ; not equal, error iny bne A_FD67 ; next byte ldx #$FC A_FD77: ; [FD77] bvc A_FD77 ; byte ready? clv lda PortA2 ; read byte cmp BUF2,Y ; compare with buffer contents bne A_FD58 ; not equal, then error iny dex ; next byte bne A_FD77 dec A_0628 ; decrement sector counter bne A_FD39 ; not yet zero? inc FTNUM ; increment track number lda FTNUM cmp #$24 ; compare with 36, highest track ; number + 1 bcs A_FD96 ; greater, then formatting done jmp LoopDiskCntrl ; continue A_FD96: ; [FD96] lda #$FF sta FTNUM ; track number to $FF lda #$00 sta GCRFLG lda #$01 jmp P_F969 ; ok ;** Write SYNC 10240 times, erase track P_FDA3: ; [FDA3] lda PCR2 and #$1F ora #$C0 sta PCR2 ; switch PCR to writing lda #$FF sta DDRA2 ; port A (read/write head) to output sta PortA2 ; write $FF to disk ldx #$28 ; 40 ldy #$00 A_FDB9: ; [FDB9] bvc A_FDB9 ; byte ready? clv dey bne A_FDB9 dex bne A_FDB9 rts ;** Read/write (X*Y) times P_FDC3: ; [FDC3] ldx A_0621 ldy A_0622 A_FDC9: ; [FDC9] bvc A_FDC9 ; byte ready? clv dex bne A_FDC9 dey bpl A_FDC9 rts ;** Attempt counter for formatting J_FDD3: ; [FDD3] dec A_0620 ; decrement number of attempts beq A_FDDB ; zero, then error jmp LoopDiskCntrl ; continue A_FDDB: ; [FDDB] ldy #$FF sty FTNUM ; flag for end of formatting iny sty GCRFLG ; GCRFLG := 0 jmp P_F969 ; error termination P_FDE5: ; [FDE5] lda BUF0,Y sta A_0345,Y dey ; copy buffer contents bne P_FDE5 lda BUF0 sta A_0345 rts ;** Copy data from overflow buffer P_FDF5: ; [FDF5] ldy #$44 A_FDF7: ; [FDF7] lda BufGCR,Y ; $1BB to $1FF sta (BUFPNT),Y ; write in buffer $30/$31 dey bpl A_FDF7 rts ;** Switch to reading P_FE00: ; [FE00] lda PCR2 ora #$E0 ; switch PCR to reading sta PCR2 lda #$00 sta DDRA2 ; port A to input rts ;** Write $55 10240 times P_FE0E: ; [FE0E] lda PCR2 and #$1F ora #$C0 ; switch PCR to writing sta PCR2 lda #$FF sta DDRA2 ; port A to output (write head) lda #$55 ; %01010101 sta PortA2 ; to port A (write head) ldx #$28 ldy #$00 A_FE26: ; [FE26] bvc A_FE26 ; byte ready for write electronics clv dey bne A_FE26 ; 10240 times dex bne A_FE26 rts ;** Convert header in buffer 0 to GCR code P_FE30: ; [FE30] lda #$00 sta BUFPNT sta SAVPNT sta BYTCNT lda #$BB sta GCRPNT lda BUFPNT+1 sta SAVPNT+1 lda #$01 sta BUFPNT+1 J_FE44: ; [FE44] ldy BYTCNT lda (SAVPNT),Y sta BTAB0 iny lda (SAVPNT),Y sta BTAB1 iny lda (SAVPNT),Y sta BTAB2 iny lda (SAVPNT),Y sta BTAB3 iny beq A_FE64 sty BYTCNT jsr P_F6D0 jmp J_FE44 A_FE64: ; [FE64] jmp P_F6D0 ;** Interrupt routine IRQ: ; [FE67] pha txa pha ; save registers tya pha lda IFR1 ; interrupt from serial bus? and #$02 beq A_FE76 ; no, -> jsr P_E853 ; serve serial bus A_FE76: ; [FE76] lda IFR2 ; interrupt from timer 1? asl A bpl A_FE7F ; no, -> jsr IRQdiskCntrllr ; IRQ routine for disk controller A_FE7F: ; [FE7F] pla tay pla ; get registers back tax pla rti ;** Constands for disk format DirTrack: ; [FE85] .by $12 ;** directory track .by $04 ;** start of bam .by $04 ;** length of bam per track LengthBAM: ; [FE88] .by $90 ;** end of bam ;** Table of command words TblCommands: ; [FE89] .by "V" ; Validate .by "I" ; Initialize .by "D" ; D (back up, not used) .by "M" ; Memory .by "B" ; Block .by "U" ; User .by "P" ; Position .by "&" ; USR execute .by "C" ; Copy .by "R" ; Rename .by "S" ; Scratch .by "N" ; New (Format) ;** Low byte of command addresses CmdAddrLB: ; [FE95] .by <(Validate) .by <(Initialize) .by <(SyntaxError) .by <(Memory) .by <(Block) .by <(User) .by <(Position) .by <(USRexec) .by <(Copy) .by <(Rename) .by <(Scratch) .by <(New) ;** High byte of command addresses CmdAddrHB: ; [FEA1] .by >(Validate) .by >(Initialize) .by >(SyntaxError) .by >(Memory) .by >(Block) .by >(User) .by >(Position) .by >(USRexec) .by >(Copy) .by >(Rename) .by >(Scratch) .by >(New) ;** Bytes for syntax check TblSyntax: ; [FEAD] .by $51, $DD, $1C, $9E, $1C ;** File control methods TblRWAM: .tx "RWAM" ;** File types TblDSPUL: .tx "DSPUL" ;** Names of file types TblFileTyp: ; [FEBB] .tx "DSPUR" ;** 1st char .tx "EERSE" ;** 2nd char .tx "LQGRL" ;** 3rd char ;** Value of LED-byte for every drive A_FECA: .by $08,$00 ;** For setting the Zero flag, see routine at A_E312 A_FECC: .by $00 ;** Masks for bit command [FECD] MaskBits: .by $3F,$7F,$BF,$FF ;** Number of sectors per track NumSecTrack: .by 17, 18, 19, 21 ;** Constands for disk format A_FED5: .by 'A' ; marker for 1541 format NumOfZones: .by 4 ; 4 track ranges [FED6] A_FED7: .by 36 ; number of tracks + .by 31, 25, 18 ; tracks on which sector numbers ; change ;** Control bytes for head postion ReadAttempts: .by $01,$FF, $FF,$01,$00 ;** High byte addresses of buffers BufAddrHB: ; [FEE0] .by 3, 4, 5, 6, 7, 7 ;** ROM checksum .by $79 NMI: ; [FEE7] jmp (J_VNMI) ;** Patch for diagnostic routine, from $EA7A PATCH3: ; [FEEA] sta PortB2 ; turn LED on sta DDRB2 ; port to output jmp J_EA7D ; back to diagnostic routine ;** Delay loop for serial bus in 1541 mode from $E97D DelayC64: ; [FEF3] txa ldx #$05 ; about 40 microseconds Delay2: ; [FEF6] dex bne Delay2 tax rts ;** Patch for data output to serial bus from $E980 P_FEFB: ; [FEFB] jsr ClkOut_H ; CLOCK OUT hi jmp DataOut_L ; DATA OUT lo ;** U9 vector, switch 1540/1541 UI_U9: lda CMDBUF+2 cmp #'-' beq A_FF0D ; if parameter is '+', then at A_FF0D result is 0 sec sbc #'+' bne NMI ; indirect jump over ($0065) A_FF0D: ; [FF0D] sta VIC20mode rts ;** Patch for reset routine, from $EAA4 PATCH1: ; [FF10] stx DDRA1 ; port A to output lda #$02 sta PortB1 lda #$1A sta DDRB1 jmp L_EAA7 ;** Patch for listen to serial bus from $E9DC PATCH2: ; [FF20] lda PortB1 and #$01 bne PATCH2 lda #$01 sta T1CH1 jmp J_E9DF FormatFloppy2: ; [FF2F] lda #$FF sta FTNUM jmp FormatFloppy ; $C8C6 P_FF36: sta Z_FF jmp LedOn ; $C100 J_FF3B: cmp #$02 bcc A_FF46 cmp #$0F beq A_FF46 jmp J_D36B ; $D36B A_FF46: jmp A_D373 ; steal buffer J_FF49: sei ldx #$45 txs jmp J_EB25 ; $EB25 J_FF50: bit PortA1 jmp SerialBus ; $E85B J_FF56: lda A_0100-1,X rts J_FF5A: ldx DRVNMB lda A_0100-1,X jmp J_F01B ; $F01B J_FF62: lda #$00 sta A_0100-1,X jmp J_C1B7 ; $C1B7 J_FF6A: tya sta A_0100-1,X jmp J_C664 ; $C664 J_FF71: sta WPSW0,X sta A_0100-1,X jmp CalcFreeBlks ; $D075 ;** unused ; [FF79] .fb $AA, 108 .by $EB ;??? Are these two vectors used ??? [FFE6] .wo FormatFloppy .wo MotorOff ;** USER vectors UserVectors: ; [FFEA] .wo UA_U1 ;** UA, U1 .wo UA_U2 ;** UB, U2 .wo BUF2+0 ;** UC, U3 .wo BUF2+3 ;** UD, U4 .wo BUF2+6 ;** UE, U5 .wo BUF2+9 ;** UF, U6 .wo BUF2+12 ;** UG, U7 .wo BUF2+15 ;** UH, U8 .wo UI_U9 ;** UI, U9 ;** Hardware vectors .wo RESET ;** RESET .wo IRQ ;** IRQ ;******************************************************************************