; ; Vertically Sorted Directory ; (VSD) ; version 1.1 ; ; This program is one of three designed to do, basically, what SD ; does, but without the overhead. This program displays sorted ; files vertically, and is terminal dependant. See SSD.DOC for ; information on patching this program for your particular ; terminal. See SSD.DOC for more detailed information about this ; program and the other two (SSD and SSDR). ; ; This program cannot be assembled with ASM due to the fact that ; ASM doesn't accept negative numbers with LXI and MVI statements. ; MAC works fine, as should RMAC. ; ; true equ 0ffh false equ not true ; rowfrst equ true ;true if cursor addressing sends row before ;column ; vers equ 1 ;version rev equ 1 ;revision ; month equ 05 ;last revision date day equ 09 ; / year equ 86 ;/ ; cr equ 13 ;carriage return lf equ 10 ;line feed tab equ 9 ;tab esc equ 27 ;terminal escape ; base equ 0 ;base of CP/M dfcb equ 5ch ;CP/M default FCB ddma equ base+80h ;CP/M default DMA ; bdos equ base+5 ;BDOS vector dircon equ 6 ;BDOS direct console I/O pstring equ 9 ;BDOS print string resetd equ 13 ;BDOS reset disks setd equ 14 ;BDOS select disk searchf equ 17 ;BDOS search for first occurance of file searchn equ 18 ;BDOS search for next occurance of file getd equ 25 ;BDOS get drive # setdma equ 26 ;BDOS set DMA address galloc equ 27 ;BDOS get address of allocation vector curdpb equ 31 ;BDOS get current disk parameters userst equ 32 ;BDOS get/set user # ; org base+100h ; jmp start ;jump past following data ; ; +----- delay after printing string in .1 second intervals ; | +--- # of bytes in terminal control string ; | | +- up to 10 bytes for terminal control string ; | | | ; v v v clrscr: db 0,2,esc,'E',0,0,0,0,0,0,0,0 revon: db 0,2,esc,'p',0,0,0,0,0,0,0,0 revoff: db 0,2,esc,'q',0,0,0,0,0,0,0,0 fence: db 0,5,esc,'F|',esc,'G',0,0,0,0,0 cpstr: db 0,2,esc,'Y',0,0,0,0,0,0,0,0 e2eop: db 0,2,esc,'J',0,0,0,0,0,0,0,0 offset: db 20h ;offset for cursor addressing numcol: db 3 ;# of columns-1 mhz: db 2 ;clock speed in MHz ; start: lxi h,0 ;zero HL dad sp ;get stack pointer shld oldsp ;put it away lxi sp,stack ;...and initialize local stack ; call print db cr,lf,'V>ertically S>orted D>irectory v' db vers+'0','.',rev+'0',' | ' db (month/10)+'0',(month mod 10)+'0','/' db (day/10)+'0',(day mod 10)+'0','/' db (year/10)+'0',(year mod 10)+'0' db 0 ; ; Clear data bytes, making program re-entrant ; mvi b,datend-defd ;# of bytes to clear lxi h,defd ;place to start clearing cllop: mvi m,0 ;clear byte at (HL) inx h ;bump pointer dcr b ;decrement counter jnz cllop ;if not done, clear the next one ; lda numcol ;# of columns sta column ;store it ; ; mvi c,getd ;get default drive call bdos sta defd ;save it mvi c,userst ;get default user mvi e,0ffh call bdos sta defu ;save it ; ; Search FCB filename for a $ denoting options. If one exists, ; clear FCB by making first byte a space. ; lxi h,dfcb+1 ;point to first byte of FCB filename mvi b,11 ;# of bytes to check snfopt: mov a,m ;get byte at (HL) cpi '$' ;dollar sign? jnz snfo1 ;no? then try next byte mvi a,20h ;there's a $ sign in the FCB. Get a space... sta dfcb+1 ;...make it the first byte of the filename jmp clrfcb ;...and break out of the loop snfo1: inx h ;wasn't a $, bump pointer dcr b ;...tweak counter jnz snfopt ;...and try again if we're not done ; ; Clear the FCB of all but drive, filename ; clrfcb: lxi h,dfcb+12 ;end of filename buffer mvi b,24 ;# of bytes to clear clrlp: mvi m,0 ;zero out (HL) inx h ;bump pointer dcr b ;decrement counter jnz clrlp ;do the next byte if we're not done ; ; Check the command-line buffer (in the DMA) for any options ; lxi h,ddma ;beginning of buffer mov a,m ;get character count ora a ;zero? jz dodir ;if so, no options inx h ;point past count push h ;save pointer mvi d,0 ;get count in DE mov e,a ;/ dad d ;add to HL mvi m,0 ;make last byte of buffer a null pop h ;point back to beginning of buffer dcx h ;for INX to follow ; getlp: inx h ;point to first/next byte of command-line mov a,m ;get a byte cpi '$' ;option delimeter? jz doopt ;if so, handle it appropriately ora a ;null terminator? jnz getlp ;if not a null or a $, try again ; dodir: lda dfcb+1 ;get first byte of filename cpi 20h ;space? cz qfill ;fill with ?'s ; mvi a,'?' ;force wild extent sta dfcb+12 ;/ call setsrc ;set DMA for BDOS media change check lxi h,dfcb ;point to drive code for directory mov a,m ;get the drive code out of the FCB ora a ;zero? jz deflt ;then don't change the drive mov e,a ;else move to E for BDOS dcr e ;normalize drive code for select mvi c,setd ;select the directory drive to retrieve call bdos ;...the proper allocation vector ; deflt: mvi c,curdpb ;request DPB call bdos ;/ inx h inx h mov a,m ;get block shift sta blkshf ;save it inx h ;bump to block mask mov a,m ;get it sta blkmsk ;save it inx h inx h mov e,m ;get max block number inx h mov d,m xchg shld blkmax ;save it xchg inx h mov e,m ;get directory size inx h mov d,m xchg shld dirmax ;save it mvi c,galloc ;get address of allocation vector call bdos xchg lhld blkmax ;get it length inx h lxi b,0 ;init block count to zero ; gspbyt: push d ;save alloc address ldax d mvi e,8 ;set to process 8 blocks ; gsplup: ral ;test bit jc notfre inx b ; notfre: mov d,a ;save bits dcx h ;count down blocks mov a,l ora h jz endalc ;quit if out of blocks mov a,d ;restore bits dcr e ;count down 8 bits jnz gsplup ;do another bit pop d ;bump to next byte... inx d ;of allocation vector jmp gspbyt ;process it ; endalc: pop d ;clear stack mov l,c ;copy blocks to HL mov h,b lda blkshf ;get block shift factor sui 3 ;convert from sectors to k jz savfre ;skip shifts if 1k blocks ret free in HL ; freklp: dad h ;multiply blocks by k/blk dcr a jnz freklp savfre: shld freeby ;save free disk space mvi a,'?' lxi h,dfcb+12 mov m,a ;match all extents inx h mov m,a ;match all S1 bytes inx h mov m,a ;match all S2 bytes call setsrc ;set DMA for directory search ; ; Calculate total storage capacity of disk -system and directory tracks ; lhld dirmax ;get total # of directory entries inx h ; lxi d,-32 ;prepare to divide HL by 32 mvi b,0 ;initialize counter ; dvlp: dad d ;subtract jnc dvex ;exit if overflow inr b ;otherwise, bump counter jmp dvlp ;subtract again ; dvex: mov a,b ;get value in A sta dirspc ;...for save ; lda blkmsk ;get block mask rar ;rotate right 3 times rar rar ani 00011111b ;clear any crud inr a ;add one to get block size mov b,a ;to B to act as counter ; lhld blkmax ;get max # of blocks inx h ;normalize mov d,h ;move HL->DE mov e,l ;/ mullp: dcr b ;bump down counter jz mulex ;if done, exit dad d ;add HL to itself jmp mullp ; mulex: push h ;save # of k on disk lda dirspc ;get directory space back mov b,a ;for count lxi d,0 ;initialize DE nloop: dcx d ;decrement DE dcr b ;ditto for B jnz nloop ;if not done, decrement another dad d ;subtract directory space shld totfre ;save it ; ; Initialize order table ; lhld dirmax ;get directory maximum inx h ;actual maximum is dirmax+1 dad h ;double it to get size of order table lxi d,order ;point to brginning of order table dad d ;add offset shld filebuf ;save beginning of filename buffer shld fbufp ;and initialize working pointer xchg lhld bdos+1 ;make sure we have room to continue mov a,e sub l mov a,d sbb h jnc outmem ; ; Start filename search ; lxi d,dfcb ;point to filename fcb mvi c,searchf ;search for first occurance call bdos ;/ ; inr a ;FFh returned? jz nofile ;nofile error message dcr a ;else set A straight call sfilen ;and print the filename info ; floop: mvi c,searchn ;find next occurance of file call bdos ;/ inr a ;FFh returned? jz pfiles ;print files and quit if so dcr a ;...else set A straight call sfilen ;store the filename info jmp floop ;do it again ; pfiles: lhld numfls ;get # of extents read mov a,h ;zero? ora l ;/ jz nofile ;if so, print 'no files' and exit ; call sort ;sort filenames lxi h,clrscr ;clear console screen call prntesc ;/ lxi h,order ;point to beginning of order table shld fbufp ;re-initialize filebuf pointer xchg ;filebuf pointer to DE lhld numfls ;get # of files inx h ;increment for first decrement shld count ;save as file count pf1: lhld count ;get file count dcx h ;bump down shld count ;save it mov a,h ;done? ora l ;/ jz rcur ;exit if so lhld fbufp ;get pointer push h ;save it lhld count ;get the file count dcx h ;decrement mov a,h ;is this the last file? ora l ;/ pop h ;restore pointer jz okprt ;if the last file, go ahead and print ; ; Compare current entry to next one to find last extent of ; a given filename ; mvi a,11 ;# of bytes to compare call comp ;do it jnz okprt ;if they don't match, then it must be ok inx h ;point to next entry inx h shld fbufp ;re-save pointer jmp pf1 ;...and try again ; okprt: lda xpos ;get cursor position mov b,a ; / lda ypos ; / mov c,a ;/ call curpos ;position cursor lhld fbufp ;get pointer mov e,m ;get low nibble of filename addr inx h mov d,m ;ditto for high nibble inx h ;point to next entry shld fbufp ;save pointer xchg ;get filename pointer from DE to HL push h ;save it call pfn ;print filename pop h ;restore pointer lxi d,11 ;offset to filesize dad d ;add it call doit ;convert to k lhld totsiz ;get old total size count dad d ;add this file's size to it shld totsiz ;save new value lhld totfil ;get old total files count inx h ;increment shld totfil ;save new value mvi a,1 ;be sure not to suppress leading spaces sta supspc ;/ xchg ;DE->HL ; lda recflg ;filesizes in records? ora a ;/ jz prntfs ;if not, treat as for k mvi a,20h ;else print an extra space call pchar ;/ ; prntfs: call decprt ;print file size ; lda recflg ;filesizes in records? ora a ;/ jnz nok ;if so, don't print the 'k' mvi a,'k' ;print a "k" call pchar ;/ nok: lda xpos ;get line number inr a ;increment sta xpos ;save it cpi 20 ;last line? cz newcol ;new column if so jmp pf1 ;do another ; newcol: lhld count ;get file count dcx h ;decrement mov a,h ;last file? ora l ;/ rz ;simply return if so ; lda column ;get column count dcr a ;decrement jm wait ;if minus, wait until key struck to continue sta column ;store it ; lda ypos ;get y position marker adi 19 ;add offset for fence mov c,a ;put in in C for cursor addressing mvi b,0 ;zero B pflop: push b ;save cursor positions call curpos ;move cursor to BC push h ;save HL lxi h,fence ;print fence call prntesc ;/ pop h ;restore HL pop b ;restore positions inr b ;increment line lda xpos ;get last x position marker cmp b ;same as current x position? jnz pflop ;if not, do another ; xra a ;zero x position marker sta xpos ;/ lda ypos ;get y position marker adi 20 ;add offset to next column sta ypos ;save it ret ;go home ; wait: mvi b,23 ;move cursor to line 23 mvi c,32 ;column 32 call curpos ;do it call print db '<<< Any Key >>>',0 wloop: mvi c,dircon ;poll console mvi e,0ffh ; / call bdos ;/ ora a ;zero returned? jz wloop ;if so, loop until key typed; else... xra a ;zero cursor pointers sta xpos ; / sta ypos ;/ lxi h,clrscr ;clear the console screen call prntesc ;/ lda numcol ;reset column count sta column ;/ ret ; rcur: mvi b,21 ;set cursor for orderly exit mvi c,0 ; / call curpos ;/ xra a ;supress leading spaces sta supspc ;/ call pdu ;print DU: call print db 20h,20h,0 lhld totfil ;get # of files displayed call decprt ;print the # call print db ' files occupying ',0 lhld numfls ;get total # of extents call decprt ;print it mvi a,'/' ;...a slash call pchar ;/ lhld dirmax ;...get total # of entries allowed inx h ;...normalize call decprt ;...and print it call print db ' extents in ',0 lhld totsiz ;get total K used by displayed files call decprt ;print it ; lda recflg ;filesizes in records? ora a ;/ jz ptfk ;if not, print a 'k' call print ;else print 'records' db ' records/',0 jmp pfree ;continue, printing free space ; ptfk: call print db '/',0 pfree: lhld totfre ;get total free space call decprt ;print it call print db 'k (',0 ; lhld freeby ;get free space call decprt ;print it call print db 'k free)',cr,lf,0 jmp quit ;exit to CP/M ; outmem: call print db cr,lf,cr,lf,7,'ERROR - Out of Memory',cr,lf,cr,lf,0 jmp quit ; usrerr: call print db cr,lf,cr,lf,'Illegal user-area',cr,lf,cr,lf,0 jmp quit ; nofile: call print db cr,lf,cr,lf,'No file(s) on ',0 ; xra a ;suppress leading spaces sta supspc ;/ ; call pdu ;print DU: call print db ' (',0 lhld freeby ;get disk free space call decprt ;print it call print db 'k free)',cr,lf,0 ; quit: lda defd ;get default drive back mov e,a ;for BDOS operation mvi c,setd call bdos ;set it as new default ; lda defu ;get old default user back mov e,a ;for BDOS mvi c,userst call bdos ;set it as new default ; lhld oldsp ;get old stack pointer back sphl ;set it ret ;to CP/M ; ; Subroutines ; ; SFILEN - store filename ; sfilen: add a ;perform (A x 32) + 1 add a ;x4 add a ;x8 add a ;x16 add a ;x32 inr a ;+1 ; lxi h,ddma ;point to default DMA mvi d,0 ;put offset in DE mov e,a ;/ dad d ;add offset to HL ; lda sysflg ;$SYS files to be displayed? ora a ;/ jnz sf1 ;if so, don't do the following push h ;save pointer lxi d,9 ;offset to $SYS byte dad d ;add to fname pointer mov a,m ;get $SYS byte ani 80h ;will be zero if not $SYS pop h ;restore stack rnz ;return if $SYS ; sf1: push h ;save pointer lhld fbufp ;get filename buffer pointer pop d ;restore current filename pointer in DE xchg ;swap lxi b,11 ;# of bytes to move call move ;move it xchg ;get new filename buffer pointer in HL inx d ;DE->S1 inx d ;DE->S2 ldax d ;get S2 byte, overflow=int(extents/32) push h ;save HL mov l,a ;set up 16-bit multiply mvi h,0 mvi b,5 call shll ;HL is now # of overflow extents dcx d ;DE->S1 dcx d ;DE->extent ldax d ;get extent add l mov l,a mov a,h aci 0 mov h,a ;HL now has total sectors mvi b,7 call shll ;HL now has total sectors less last ext inx d ;DE->S1 inx d ;DE->S2 inx d ;point to sector count ldax d ;get it add l mov l,a mov a,h aci 0 mov h,a ;HL now has total sectors xthl ;do some fancy shuffling xchg xthl xchg mov m,d inx h mov m,e pop d ;all back to normal inx h shld fbufp ;save new pointer xchg lhld numfls ;get file count inx h ;increment shld numfls ;save it lxi h,13 ;size of next entry dad d xchg ;future fbufp in DE lhld bdos+1 ;pick up TPA end mov a,e sub l ;compare fbufp-tpa end mov a,d sbb h jnc outmem ;if no memory left, error out ret ; ; ; PCHAR - print character in A with Ctrl-C/S check ; pchar: push b ;save all registers push d ; / push h ; / push psw ;/ ; mvi c,dircon ;poll console mvi e,0ffh ; / call bdos ;/ ; cpi 'C'-40h ;^C? jz abort ;abort if so cpi 'S'-40h ;^S? cz pause ;pause if so ; pop psw ;get A back ani 7fh ;strip high bit mvi c,dircon ;print it mov e,a ; / call bdos ;/ ; pop h ;restore other registers pop d ; / pop b ;/ ret ;to caller ; abort: mvi b,20 ;prepare to move the cursor to row 20 mvi c,0 ;...column 0 call curpos ;do it lxi h,e2eop ;erase to the end of the page call prntesc ;/ mvi c,pstring ;bdos print string lxi d,amsg ;abort message call bdos ;print it jmp quit ;...and end the program ; amsg: db cr,lf,'+++ Aborted +++',cr,lf,'$' ; pause: mvi c,dircon ;poll console mvi e,0ffh ; / call bdos ;/ ora a ;character typed? jz pause ;if not, loop again cpi 'C'-40h ;is the typed character a ^C? jz abort ;if so, abort ret ;...else go home ; ; ; PRINT - print string past call ; print: pop h ;get RET address print1: mov a,m ;get a character ora a ;null terminator? jz prend ;done - back to program call pchar ;print the character inx h ;bump pointer jmp print1 ;get another prend: inx h ;point past text pchl ;RET there ; ; ; PRHL - print string at HL up to a null terminator ; prhl: mov a,m ;get a character ora a ;null terminator? rz ;return if so call pchar ;else print it inx h ;bump pointer jmp prhl ;print another character ; ; ; PFN - print filename pointed to by HL ; pfn: push h ;save the pointer mvi b,8 ;# of characters to print call pnum ;print the filename, mvi a,'.' ;...the dot, call pchar ;/ pop h ;...restore the pointer, lxi d,8 ;...point to filetype, dad d ;/ mvi b,3 ;...# of characters to print, call pnum ;...and print the filename ret ; ; ; PNUM - print # of bytes in B of string pointed to by HL ; pnum: mov a,m ;get character push h ;save pointer ani 80h ;high bit set? jz norev ;if not, no reverse video lxi h,revon ;turn reverse video (if any) on call prntesc ;/ pop h ;restore pointer mov a,m ;get character back ani 7fh ;strip high bit call pchar ;print it push h ;save pointer lxi h,revoff ;exit reverse video call prntesc ;/ pop h ;restore pointer jmp pn1 norev: pop h ;restore pointer mov a,m ;get character ani 7fh ;strip high bit call pchar ;print it on console pn1: inx h ;bump pointer dcr b ;decrement counter rz ;return if counter zero jmp pnum ;...else do it again ; ; ; CURPOS - position cursor at location in BC. B=X, C=Y ; curpos: push b ;save cursor position lxi h,cpstr ;direct cursor positioning command call prntesc pop b ;get cursor position back ; if rowfrst ;row before column? ; lda offset ;get positioning offset in A add b ;add to x value call epchar ;print it lda offset ;get offset add c ;add to y value call epchar ;print it ; else ;if column before row ; lda offset ;get positioning offset in A add c ;add to y value call epchar ;print it lda offset ;get offset add b ;add to x value call epchar ;print it ; endif ; ret ;go home ; ; PRNTESC - print string of length (HL+1), first delaying amount of ; time specified at (HL) and typing text beginning ; at (HL+2) without allowing ctrl-c abort ; prntesc: push b ;save counter register inx h ;point to # of bytes mov a,m ;get counter ora a ;zero? pop b ;restore old BC just in case there's rz ;...no string, return ; push b ;...else save BC again push h ;save pointer for later ; mov b,m ;set up counter inx h ;point to beginning of string pescl: mov a,m ;get byte at HL call epchar ;print it inx h ;point to next byte dcr b ;decrement counter jnz pescl ;if not done, go again ; pop h ;get old pointer back dcx h ;point to delay value mov a,m ;get it ora a ;zero? jz pehme ;if so, go home, else... ; mov b,a ;get time counter in B edlop: call delay ;delay .1 seconds dcr b ;decrement counter jnz edlop ;if not done, wait another .1 seconds ; pehme: pop b ;restore BC ret ;go home ; epchar: push psw ;save all registers push b ; / push d ; / push h ;/ mov e,a ;move character to E for BDOS mvi c,dircon ;direct console output call bdos ;print it pop h ;restore registers pop d ; / pop b ; / pop psw ;/ ret ; ; DELAY - delay .1 seconds ; delay: push h ;save registers push d ;/ ; lxi h,2500 ;timing constant, to be multiplied against lxi d,2500 ;...clock speed in MHz lda mhz ;get clock speed ; delmul: dcr a ;decrement counter jz dellp ;if done, go loop dad d ;add counter to itself jmp delmul ;keep going till we're finished ; dellp: dcx h ;decrement it mov a,h ;done? ora l ;/ jnz dellp ;if not, loop again ; pop d ;restore saved registers pop h ;/ ret ; ; QFILL - fill default fcb with question-marks (*.*) ; qfill: lxi h,dfcb+1 ;point to default fcb filename mvi b,11 ;# of bytes to fill qflop: mvi m,'?' ;move a question mark into the fcb inx h ;increment pointer dcr b ;decrement counter jnz qflop ;if not done, then do again ret ;...else go home ; ; ; This sort routine is adapted from software tools by Kernigan and ; Plaugher. ; sort: ; ; Initialize the order table ; lhld numfls ;get file name count push h ;save it ; lhld filebuf ;get start of name table xchg ;into DE lxi h,order ;point to order table lxi b,13 ;entry length ; bldord: mov m,e ;save low order address inx h mov m,d ;save high order address inx h xchg ;table addr to DE dad b ;point to next entry xchg xthl ;save tbl addr, fetch loop counter dcx h ;count down loop mov a,l ora h ;more? xthl ;(restore tbl addr, save counter) jnz bldord ;yes, go do another one ; pop h ;clean loop counter off stack lhld numfls ;get max # of entry pairs shld count ;save for sort dcx h ;subtract one to get max # of pairs mov a,h ;zero? ora l ;/ rz ;if so, only one file. No need to sort ; lhld count ;# of entries ; l0: ora a ;clear carry mov a,h ;gap = gap/2 rar mov h,a mov a,l rar mov l,a ora h ;is it zero? rz ;then none left mov a,l ;make gap odd ori 1 mov l,a shld gap inx h ;i = gap+1 ; l2: shld i xchg lhld gap mov a,e ;j = i-gap sub l mov l,a mov a,d sbb h mov h,a ; l3: shld j xchg lhld gap ;jg = j+gap dad d shld jg mvi a,13 ;compare 13 characters call scomp ;compare (j) and (jg) jp l5 ;if a(j) <= a(jg) lhld j xchg lhld jg call swap lhld j xchg lhld gap mov a,e sub l mov l,a mov a,d sbb h mov h,a jm l5 ;if j > 0 goto l3 ora l ;check for zero jz l5 jmp l3 ; l5: lhld count ;for later xchg lhld i ;i = i+1 inx h mov a,e ;if i <= n goto l2 sub l mov a,d sbb h jp l2 lhld gap jmp l0 ; ; Swap entries in the order table ; swap: lxi b,order-2 ;table base dad h ;*2 dad b ;plus base xchg dad h ;*2 dad b ;plus base mov c,m ldax d xchg mov m,c stax d inx h inx d mov c,m ldax d xchg mov m,c stax d ret ; ; Special compare for sort ; scomp: lxi b,order-2 dad h dad b xchg dad h dad b xchg mov c,m inx h mov b,m xchg mov e,m inx h mov d,m xchg mov e,a ;count ; cmplp: mov a,m ani 7fh mov d,a ldax b ani 7fh cmp d inx b inx h rnz dcr e jnz cmplp ret ; ; COMP - Compares two strings. ; comp: push h ;save table addr mov e,m ;load low order inx h mov d,m ;load high order inx h mov c,m inx h mov b,m ; ; BC, DE now point to entries to be compared ; xchg mov e,a ;get count ; cmplp1: mov a,m ani 7fh mov d,a ldax b ani 7fh cmp d inx h inx b jnz noteql ;quit on mismatch dcr e ;or end of count jnz cmplp1 ; noteql: pop h ret ;cond code tells all ; ; MOVE - Moves the number of characters in BC from (HL) to (DE) ; move: mov a,m ;get char from (HL) stax d ;put in (DE) inx h inx d dcx b mov a,c ;get LS count byte ora b ;both B & C zero? jnz move ;loop til done ret ; ; DOIT - Convert filesize at (HL) to K ; doit: mov d,m inx h mov e,m ;size in DE (sectors) ; lda recflg ;filesizes displayed in records? ora a ;/ rnz ;if so, don't convert to K ; lda cmpflg ;block-size compensation wanted? ora a ;/ jz cmpsat ;yes, go ahead ; mvi a,7 ;put 1k block mask in A jmp compk ;go compute K ; cmpsat: lda blkmsk compk: push psw add e mov e,a mov a,d aci 0 mov d,a pop psw cma ana e mov e,a mvi b,3 sder: mov a,d ora a rar mov d,a mov a,e rar mov e,a dcr b jnz sder ret ; ; SHLL - shift HL left by B bits ; shll: dad h dcr b rz jmp shll ; ; DECPRT - print HL in decimal with leading zero suppression ; decprt: xra a ;clear leading zero flag sta lzflg lxi d,-10000 ;print 10000's digit call digit lxi d,-1000 ;print 1000's digit call digit lxi d,-100 ;etc. call digit lxi d,-10 call digit mvi a,'0' ;get 1's digit add l jmp pchar ; digit: mvi b,'0' ;start off with ASCII "0" ; diglp: push h ;save current remainder dad d ;subtract jnc digex ;quit on overflow pop psw ;throw away remainder inr b ;bump digit jmp diglp ;loop back ; digex: pop h ;restore pointer mov a,b cpi '0' ;zero digit? jnz dignz ;no, type it lda lzflg ;leading zero? ora a mvi a,'0' jnz pchar ;print digit lda supspc ;get space suppression flag ora a ;see if printing file totals rz ;yes, don't give leading spaces mvi a,20h ;leading zero...print space jmp pchar ; dignz: sta lzflg ;leading zero flag so next zero prints jmp pchar ;...and print digit ; ; SETSRC - Set DMA to default standard (base+80h) ; setsrc: lxi d,ddma mvi c,setdma jmp bdos ; ; PDU - print current DU: ; pdu: mvi c,getd ;get current disk call bdos adi 'A' ;convert to ASCII call pchar ;print it mvi c,userst ;get current user mvi e,0ffh call bdos mov l,a ;move result to HL for print mvi h,0 call decprt ;print it mvi a,':' ;the colon jmp pchar ;print and go home ; ; DOOPT - Handle command-line options ; doopt: push h ;save option pointer doopt1: inx h ;point to option mov a,m ;get character ora a ;null? jz optret ;return if so cpi 'S' ;request for $SYS files? jz setsys ;take care of it if so cpi 'R' ;filesizes in records? jz setrec cpi 'U' ;user-area change? jz newusr cpi 'D' ;reset disk? jz rstdsk cpi 'B' ;no block compensation? jz nobcmp cpi 20h ;space? jnz opterr ;if not, must be bad option ; optret: pop h ;clear stack jmp dodir ;do directory ; setsys: mvi a,0ffh ;set so $SYS files displayed sta sysflg ;/ jmp doopt1 ;check for another option ; setrec: mvi a,0ffh ;set so filesizes given in records sta recflg ;/ jmp doopt1 ;check for another option ; rstdsk: push h ;save pointer on stack mvi c,resetd ;BDOS reset disk system call bdos ;do it pop h ;clear stack jmp doopt1 ;check for another option ; nobcmp: mvi a,0ffh ;set flag for no block compensation sta cmpflg ;/ jmp doopt1 ; newusr: inx h ;first user-area digit inx h ;second " mov a,m ;get it sui '0' ;subtract ASCII offset cpi 10 ;0-9? jnc onenum ;no, maybe one digit mov c,a ;else move to C for future ADD dcx h ;point to ten's place digit mov a,m ;get it sui '0' ;subtract ASCII offset cpi 10 ;0-9? jnc usrerr ;no, must be bad # mov b,a ;to be for ADD add a ;multiply x2 add a ;x4 add a ;x8 add b ;x9 add b ;x10 add c ;add to one's place value inx h ;point to last digit jmp setusr ;select the specified user area ; onenum: dcx h ;come here if only one digit mov a,m ;get digit sui '0' ;subtract ASCII offset cpi 10 ;0-9? jnc usrerr ;if not, error out; else... ; setusr: cpi 32 ;user area in the range of 0-31? jnc usrerr ;if not, error out ; push h ;save pointer mvi c,userst ;BDOS get/set user area mov e,a ;for call call bdos ;do it pop h ;restore pointer jmp doopt1 ;check for another option ; ; opterr: inx h ;point past bad option mvi m,0 ;terminate string with a null lxi h,clrscr ;clear terminal screen call prntesc ;/ call print db cr,lf,'Illegal option -> ',0 pop h ;restore pointer to beginning of options call prhl ;print up to bad apple call print db cr,lf,cr,lf,'Options available are:',cr,lf,cr,lf db 'B - don''t compensate for Block-size in filesizes',cr,lf db 'D - reset the Disk drives before directory',cr,lf db 'R - display file sizes in Records instead of k',cr,lf db 'S - display files with the System flag set',cr,lf db 'Unn - change the default User area to nn (0-31)',cr,lf db cr,lf,0 jmp quit ;exit to CP/M ; ;************************ ;*** UNITIALIZED AREA *** ;************************ ; defd: db 0 ;storage for default disk defu: db 0 ;storage for default user area gap: dw 0 ;storage used by SORT i: dw 0 ; / j: dw 0 ; / jg: dw 0 ;/ sysflg: db 0 ;$SYS file display flag recflg: db 0 ;filesizes in records flag cmpflg: db 0 ;block-size compensation flag xpos: db 0 ;cursor x position stored here ypos: db 0 ;ditto for y column: db 0 ;column # pointer filebuf:dw 0 ;points to beginning of filename buffer fbufp: dw 0 ;file buffer/order table pointer numfls: dw 0 ;# of files (extents) blkshf: db 0 ;disk block shift factor blkmsk: db 0 ;block mask blkmax: dw 0 ;max # of blocks on disk dirmax: dw 0 ;max # of directory entries on disk freeby: dw 0 ;free space left on disk totfil: dw 0 ;total # of files on disk totsiz: dw 0 ;total amount of space taken up by files dirspc: db 0 ;amount of space (in K) taken up by dir tracks totfre: dw 0 ;total space available on disk count: dw 0 ;file count used by display routine lzflg: dw 0 ;leading zero flag, used by decprt: supspc: dw 0 ;suppress zeading spaces flag, decprt: again ; datend equ $ ;marks end of flags and data ; oldsp: dw 0 ;storage space for old stack pointer ds 64 ;32 level stack stack equ $ ; db 0 order equ $ ;beginning of order table ; end