entry equ 0005h ; BDOS ENTRY POINT tfcb equ 005ch ; SYSTEM FILE CONTROL BLOCK dbuf equ 0080h ; SYSTEM DISK BUFFER cr equ 0dh lf equ 0ah rcfc equ 01 ; READ CONSOLE wcfc equ 02 ; WRITE CONSOLE rdfc equ 13 ; RESET DISK offc equ 15 ; OPEN FILE cffc equ 16 ; CLOSE FILE sffc equ 17 ; SEARCH FIRST snfc equ 18 ; SEARCH NEXT dffc equ 19 ; DELETE FILE rrfc equ 20 ; READ RECORD wrfc equ 21 ; WRITE RECORD mffc equ 22 ; MAKE FILE safc equ 26 ; SET ADDRESS fn equ 01 ; FILE NAME OFFSET ft equ 09 ; FILE TYPE OFFSET ex equ 12 ; EXTENT NUMBER OFFSET nr equ 32 ; NEXT RECORD OFFSET org 100h mft: ld sp,stack+64 ld hl,msg1 ; PRINT 'MFT V3.1' call wasc xor a ; CLEAR BREAK FLAGS ld (ibflg),a ld (obflg),a ; CALCULATE BUFFER SIZE = FWA(BDOS) - FWA(MBUF) ld hl,(entry+1) ; HL = (ENTRY+1) - 6 ld de,-6 add hl,de ld a,l and 80h ; HL = HL MOD 128 ld l,a ld de,mbuf ; HL = HL - FWA(MBUF) ld a,l sub e ld l,a ld a,h sbc a,d ld h,a add hl,hl ; HL = HL / 128 ld l,h ld a,0 adc a,0 ld h,a dec hl ; SUBTRACT ONE ld (space),hl ; SAVE AS BUFFER SIZE ld hl,msg2 ; WRITE 'BUFFER SIZE = ' call wasc ld hl,(space) ; WRITE SIZE OF BUFFER call wdwc ld hl,msg3 ; WRITE ' SECTORS' call wasc ; ASK USER TO MOUNT INPUT DISK mft1: ld hl,msg4 ; WRITE 'MOUNT INPUT DISK, TYPE CR' call wasc call racc ; READ RESPONSE cp cr ; LOOP IF ANYTHING BUT CR jp nz,mft1 call weolc ; ECHO CR,LF ld a,(ibflg) ; JUMP If IBFLG SET or a jp nz,mft2a ; COPY COMMAND LINE INTO CBUF ld hl,dbuf ; FWA OF COMMAND LINE IMAGE ld de,cbuf ; FWA OF COMMAND BUFFER ld b,(hl) ; FETCH COMMAND LINE IMAGE LENGTH inc hl mft2: ld a,(hl) ; FETCH NEXT BYTE FROM CLI inc hl ld (de),a ; STORE IN DBUF inc de dec b ; DECREMENT COUNT jp nz,mft2 ; LOOP UNTIL ZERO xor a ; STORE ZERO BYTE AT END ld (de),a ld hl,cbuf ; RESET CBUFP ld (cbufp),hl call cfnt ; CREATE FILE NAME TABLE ld hl,fnt ; RESET FNT POINTERS ld (ifntp),hl ld (ofntp),hl mft2a: ld hl,mbuf ; RESET MBUF POINTER ld (mbufp),hl ld hl,(space) ; RESET MSIZE ld (msize),hl ld a,(ibflg) ; JUMP IF IBFLG NOT SET or a jp z,mft3 ld hl,ifcb ; COPY IFCB INTO TFCB ld de,tfcb ld b,33 call move xor a ; CLEAR IBFLG ld (ibflg),a ld a,1 ; SET OBFLG ld (obflg),a ld hl,(ifntp) ; BACK IFNTP UP 4 BYTES ld de,-4 add hl,de ld (ifntp),hl ld hl,tfcb+fn ; WRITE FILENAME call wasc ld hl,msg6 ; WRITE ' - ' call wasc ld hl,(ifntp) ; DE = IFNTP ex de,hl jp mftu ; CONTINUE READING PREVIOUS FILE ; PARSE OFF NEXT NAME FROM CBUF mft3: ld hl,(ifntp) ; FETCH INPUT FNT POINTER ld a,(hl) ; JUMP IF END OF TABLE cp 0ffh jp z,mft9 ld (hl),1 ; SET 'FILE READ' FLAG inc hl ld de,tfcb+fn ; COPY FILENAME INTO TFCB ld b,11 call move ld (ifntp),hl ; SAVE INPUT FNT POINTER ld hl,tfcb+fn ; WRITE FILENAME call wasc ld hl,msg6 ; WRITE ' - ' call wasc xor a ; SETUP TFCB ld (tfcb),a ld (tfcb+ex),a ld (tfcb+nr),a call open ; OPEN FILE ld hl,(ifntp) ex de,hl mftu: ld hl,(mbufp) ld a,h ; COPY INTO FNt ENTRY ld (de),a inc de ld a,l ld (de),a inc de ex de,hl ; SAVE FNT POINTER ld (ifntp),hl ld hl,0 ; FILE SIZE (IN SECTORS) = 0 ld (fsize),hl ; READ NEXT FILE FROM INPUT DISK mft6: ld hl,(mbufp) ex de,hl call setdma call read ; READ NEXT SECTOR or a ; JUMP IF NORMAL TRANSFER jp z,mft7 cp 1 ; JUMP IF EOF jp z,mft8 ld hl,msg8 ; WRITE 'READ ERROR - ' call wasc jp mft8 ; CONTINUE AS IF EOF mft7: ld hl,(mbufp) ; MBUFP = MBUFP + 128 ld de,128 add hl,de ld (mbufp),hl ld hl,(fsize) ; FSIZE = FSIZE + 1 inc hl ld (fsize),hl ld hl,(msize) ; DECREMENT MSIZE dec hl ld (msize),hl ld a,h ; LOOP IF STILL POSITIVE or l jp nz,mft6 ld hl,tfcb ; COPY TFCB INTO IFCB ld de,ifcb ld b,33 call move ld a,1 ; SET IBFLG ld (ibflg),a mft8: ld de,dbuf ; RESET DMA POINTER call setdma call close ; CLOSE FILE ld hl,(fsize) ; WRITE FILE SIZE call wdwc ld hl,msg9 ; WRITE ' SECTORS READ' call wasc ; UPDATE FNT, LOOP ld hl,(fsize) ; DE = FILE SIZE ex de,hl ld hl,(ifntp) ; STORE FILE SIZE IN FNT ENTHY ld (hl),d inc hl ld (hl),e inc hl ld (ifntp),hl ; SAVE FNT POINTER ld a,(ibflg) ; LOOP IF IBFLG NOT SET or a jp z,mft3 ; ASK USER TO MOUNT OUTPUT DISK mft9: ld hl,msga ; WRITE 'MOUNT OUTPUT DISK, TYPE CR' call wasc call racc ; READ RESPONSE cp cr ; LOOP IF ANYTHING BUT CR jp nz,mft9 call weolc ; ECHO CR,LF call reset ; RESET DISK SYSTEM (MAKE R/W) ld a,(obflg) ; JUMP IF OBFLG NOT SET or a jp z,mfta ld hl,ofcb ; COPY OFCB INTO TFCB ld de,tfcb ld b,33 call move call open ; OPEN PREVIOUS FILE ld hl,(ofntp) ; BACKUP OUTPUT FNT POINTER 4 BYTES ld de,-4 add hl,de ld (ofntp),hl ld hl,tfcb+fn ; WRITE FILE NAME call wasc ld hl,msg6 ; WRITE ' - ' call wasc jp mftb ; CONTINUE WRITING PREVIOUS FILE ; WRITE NEXT FILE TO OUTPUT DISK mfta: ld hl,(ofntp) ld a,(hl) or a jp z,mftf cp 0ffh jp z,mftf inc hl ld de,tfcb+fn ld b,11 call move ld (ofntp),hl ld hl,tfcb+fn call wasc ld hl,msg6 call wasc xor a ld (tfcb),a ld (tfcb+ex),a ld (tfcb+nr),a ld a,(tfcb+9) ; FORCE TO $R/W FOR 2.0 and 7fh ld (tfcb+9),a ld a,(tfcb+10) ; FORCE TO $DIR FOR 2.0 and 7fh ld (tfcb+10),a call delt ; TRY TO CREATE OUTPUT FILE call make cp 255 ; JUMP IF OK jp nz,mftb ld hl,msgb ; WRITE 'UNABLE TO CREATE' call wasc jp mftg mftb: ld hl,(ofntp) ld d,(hl) ; FETCH FWA OF FILE FROM FNT inc hl ld e,(hl) inc hl ex de,hl ld (mbufp),hl ; SAVE IT ex de,hl ld d,(hl) ; FETCH SIZE OF FILE FROM FNT inc hl ld e,(hl) inc hl ex de,hl ld (fsize),hl ; SAVE IT ld (xsize),hl ; SAVE FOR PRINTOUT ex de,hl ld (ofntp),hl ld hl,(fsize) ; JUMP IF FSIZE=0 ld a,h or l jp z,mftda mftc: ld hl,(mbufp) ; SET DMA ADDRESS TO MBUFP ex de,hl call setdma call write ; WRITE NEXT SECTOR or a ; JUMP IF OK jp z,mftd ld hl,msgc ; WRITE 'ERROR WRITING FILE' call wasc jp mftg mftd: ld hl,(mbufp) ; MBUFP = MBUFP + 128 ld de,128 add hl,de ld (mbufp),hl ld hl,(fsize) ; FSIZE = FSIZE - 1 dec hl ld (fsize),hl ld a,h ; LOOP UNTIL ZERO or l jp nz,mftc mftda: ld hl,tfcb ; COPY TFCB INTO OFCB ld de,ofcb ld b,33 call move ld de,dbuf ; RESET DMA POINTER call setdma call close ; TRY TO CLOSE FILE cp 255 ; JUMP IF OK jp nz,mfte ld hl,msgd ; WRITE 'UNABLE TO CLOSE' call wasc mfte: ld hl,(xsize) ; WRITE NUMBER OF SECTORS WRITTEN call wdwc ld hl,msge ; WRITE ' SECTORS WRITTEN' call wasc jp mfta mftf: ld a,(ibflg) ; LOOP IF IBFLG SET or a jp nz,mft1 mftg: jp 0 ; EXIT TO CP/M ; SUBROUTINES move: ld a,(hl) inc hl ld (de),a inc de dec b jp nz,move ret ;; GFN - GET FILE NAME ; gfn: ld a,(hl) or a ret z cp ' ' jp nz,gfn0 inc hl jp gfn gfn0: ld de,xfcb xor a ld (de),a inc de push de ld b,11 ld a,' ' gfn6: ld (de),a inc de dec b jp nz,gfn6 pop de ld b,9 gfn1: ld a,(hl) or a jp z,gfn1 inc hl cp ' ' jp z,gfn4 cp '.' jp z,gfn2 cp '*' jp z,gfn7 ld (de),a inc de dec b jp z,gfn5 jp gfn1 gfn7: dec b jp z,gfn9 ld a,'?' ld (de),a inc de jp gfn7 gfn9: ld a,(hl) cp '.' jp nz,gfn4 inc hl gfn2: ld de,xfcb+ft ld b,4 gfn3: ld a,(hl) or a jp z,gfn4 inc hl cp ' ' jp z,gfn4 cp '*' jp z,gfn8 ld (de),a inc de dec b jp z,gfn5 jp gfn3 gfn8: dec b jp z,gfn4 ld a,'?' ld (de),a inc de jp gfn8 gfn4: xor a ret gfn5: scf ret ;; CFNT - CREATE FILE NAME TABLE ; cfnt: ld hl,fnt ; RESET IFNTP ld (ifntp),hl cfnt1: ld hl,(cbufp) ; GET CBUFP ld a,(hl) ; EXIT IF END OF LIST or a ret z call gfn ; GET NEXT AFN ld (cbufp),hl ; SAVE COMMAND BUFFER PTR jp nc,cfnt2 ; JUMP IF FILENAME OK ld hl,msg5 ; WRITE 'SYNTAX ERROR IN FILENAME' call wasc jp cfnt1 ; LOOP cfnt2: xor a ; CLEAR XFCB EXTENT FIELD ld (xfcb+ex),a ld de,xfcb ; SEARCH FOR FIRST OCCURANCE call srchf cp 255 ; JUMP IF FOUND jp nz,cfnt3 ld hl,xfcb+fn ; WRITE FILENAME call wasc ld hl,msg7 ; WRITE ' NOT FOUND' call wasc jp cfnt1 ; LOOP cfnt3: and 3 ; INDEX INTO CBUF ld l,a ld h,0 add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl ld de,dbuf add hl,de ex de,hl ; COPY FILENAME INTO FNT ld hl,(ifntp) ex de,hl ld b,12 call move ld hl,zeros ; ZERO FILL REST OF ENTRY ld b,4 call move ex de,hl ld (ifntp),hl ; SAVE INPUT FNT POINTER ld (hl),0ffh ; INSURE FF BYTE AT END ld de,xfcb ; SEARCH FOR NEXT OCCURANCE call srchn cp 255 ; JUMP IF FOUND jp nz,cfnt3 jp cfnt1 ; GO GET NEXT AFN ;; WASC - WRITE ASCII STRING TO CONSOLK ; wasc: ld a,(hl) or a ret z call wacc inc hl jp wasc ;; WEOLC - WRITE END OF LINE TO CONSOLE ; weolc: ld a,cr call wacc ld a,lf jp wacc ;; WDWC - WRITE DECIMAL WORD TO CONSOLE ; wdwc: push hl push de push bc ld b,0 ; CLEAR 'DIGIT WRITTEN' FLAG ld de,10000 ; WRITE 1ST DIGIT call wndd ld de,1000 ; WRITE 2ND DIGIT call wndd ld de,100 ; WRITE 3RD DIGIT call wndd ld de,10 ; WRITE 4TH DTGIT call wndd ld de,1 ; WRITE 5TH DIGIT ld b,1 ; FORCE LAST DIGIT TO PRINT call wndd pop bc pop de pop hl ret wndd: ld c,0 ; C=0 wndd1: ld a,l ; HL = HL - DE sub e ld l,a ld a,h sbc a,d ld h,a jp c,wndd2 ; JUMP IF < 0 inc c ; C = C + 1 jp wndd1 ; LOOP wndd2: add hl,de ; HL = HL + DE ld a,c ; JUMP IF C NON-ZERO or c jp nz,wndd4 ld a,b ; JUMP IF DIGIT WRITTEN or b jp nz,wndd4 ld a,' ' ; WRITE ONE SPACE jp wacc wndd4: ld b,1 ; SET 'DIGIT WRITTEN' FLAG ld a,c ; ENCODE C INTO DECIMAL ASCII add a,'0' jp wacc ; GO WRITE IT ;; WACC - WRITE ASCII CHARACTER TO CONSOLE ; wacc: push hl push de push bc push af ld c,wcfc ld e,a call entry pop af pop bc pop de pop hl ret ;; RACC - READ ASCII CHARACTER FHOM CONSOLE ; racc: push hl push de push bc ld c,rcfc call entry pop bc pop de pop hl ret ;; RESET - RESET DISK SYSTEM ; reset: push hl push de push bc ld c,rdfc call entry pop bc pop de pop hl ret ;; OPEN - OPEN DISK FILE ; open: push hl push de push bc ld de,tfcb ld c,offc call entry pop bc pop de pop hl ret ;; READ - READ RECORD FROM DISK FILE ; read: push hl push de push bc ld de,tfcb ld c,rrfc call entry pop bc pop de pop hl ret ;; CLOSE - CLOSE DISK FILE ; close: push hl push de push bc ld de,tfcb ld c,cffc call entry pop bc pop de pop hl ret ;; DELT - DELETE DISK FILE ; delt: push hl push de push bc ld de,tfcb ld c,dffc call entry pop bc pop de pop hl ret ;; MAKE - MAKE NEW DISK FILE ; make: push hl push de push bc ld de,tfcb ld c,mffc call entry pop bc pop de pop hl ret ;; WRITE - WRITE RECORD TO FILE ; write: push hl push de push bc ld de,tfcb ld c,wrfc call entry pop bc pop de pop hl ret ;; SETDMA - SET DMA ADDRESS ; setdma: push hl push de push bc ld c,safc call entry pop bc pop de pop hl ret ;; SRCHF - SEARCH FOR FIRST OCCURANCE OF AFN ; srchf: push hl push de push bc ld c,sffc call entry pop bc pop de pop hl ret ;; SRCHN - SEARCH FOR NEXT OCCURANCE OF AFN ; srchn: push hl push de push bc ld c,snfc call entry pop bc pop de pop hl ret msg1: db 'MFT V3.1',cr,lf,0 msg2: db 'Buffer size = ',0 msg3: db ' sectors',cr,lf,0 msg4: db 'Mount input disk, type CR',0 msg5: db 'Syntax error in filename',cr,lf,0 msg6: db ' - ',0 msg7: db ' not found',cr,lf,0 msg8: db 'read error - ',0 msg9: db ' sectors read ' ,cr,lf,0 msga: db 'Mount output disk, type CR',0 msgb: db 'unable to create',cr,lf,0 msgc: db 'error writing file',cr,lf,0 msgd: db 'unable to close',cr,lf,0 msge: db ' sectors written',cr,lf,0 zeros: db 0,0,0,0 org ($+15)/16*16 fnt: ds 16*64+1 stack: ds 64 space: ds 2 ; AVAILABLE SPACE msize: ds 2 ; MEMORY SIZE cbuf: ds 80 ; COMMAND BUFFEH cbufp: ds 2 ; COMMAND BUFFER POINTEH fsize: ds 2 ; FILE SIZE IN SECTORS xsize: ds 2 ; FILE SIZE FOR PRINTOUT ifntp: ds 2 ; INPUT FNT POINTER ofntp: ds 2 ; OUTPUT FNT POINTER mbufp: ds 2 ; MEMORY BUFFER POINTER ifcb: ds 33 ; INPUT FCB ofcb: ds 33 ; OUTPUT FCB xfcb: ds 33 ; TEMPORARY FCB ibflg: ds 1 ; INPUT BREAK FLAG obflg: ds 1 ; OUTPUT BREAK FLAG mbuf equ $ end mft