; THIS PROGRAM ADDS A LABEL FILE TO A DISK (OF THE FORM -filename.ext) ; AND OPTIONALLY PRINTS A LABEL FOR THE DISK, SHOWING THE FILES ON IT. ; ; THIS SOURCE FILE IS FOR THE MICROSOFT M80 ASSEMBLER. REMOVE ASEG ; STATEMENT FOR USE WITH DIGITAL RESEARCH'S ASM. ; ; BY: JON DART ; DEPT. OF ANTHROPOLOGY ; UCSD C-001 ; LA JOLLA, CA 92093 ; ; CREATION DATE: 28-JAN-84 ; LAST MOD: 05-APR-84 ; ASEG FPL EQU 5 ;FILES PER LINE LMAX EQU 8 ;MAX. PRINTED LINES/LABEL LABSIZ EQU 10 ;FORM LENGTH (= #LINES FROM TOP OF LABEL TO TOP ;OF NEXT LABEL) BOOT EQU 0 BDOS EQU 5 CR EQU 0DH LF EQU 0AH SPACE EQU 20H CTRL$Z EQU 1AH DEFBUF EQU BOOT+80H DEFFCB EQU BOOT+5CH RDBUF EQU 0AH SYSRES EQU 0DH FOPEN EQU 0FH FDELET EQU 13H FMAKE EQU 16H WRRAND EQU 22H FCLOSE EQU 10H SELDSK EQU 0EH RDRAND EQU 21H SFF EQU 11H SFN EQU 12H LSTOUT EQU 05H PRTSTR EQU 09H DCIO EQU 06H SETDMA EQU 1AH ORG 100H LXI H,STACK SPHL LXI D,MSG1 MVI C,PRTSTR CALL BDOS ;PRINT SIGN-ON MSG. GETDSK: LXI D,MSG2 MVI C,PRTSTR ;PROMPT FOR DISK TO USE CALL BDOS CALL GETCHR ;GET A CHAR. CALL UC ;MAKE UPPER CASE STA DSK CALL COUT ;ECHO IT SUI 'A'-1 ;CONVERT ASCII TO DRIVE CODE STA DEFFCB ;STORE IN FCB CALL CRLF LDA DEFFCB ;GET DRIVE CODE CPI 16+1 JNC GETDSK ;IF >16, NO GOOD ANA A JZ GETDSK ;0 NO GOOD EITHER TOP EQU $ LXI H,0 SHLD TOTAL ;CLEAR COUNT OF FILES XRA A STA LCOUNT ;CLEAR LINE COUNT LXI H,DSKNAM MVI B,8 MVI A,SPACE CALL FILL ;CLEAR BUFFER FOR DISK NAME LXI D,MSG3 MVI C,PRTSTR CALL BDOS ;ASK USER TO INSERT DISK WAITNL: CALL GETCHR ;WAIT FOR USER TO TYPE CR CPI 3 ;GOT ^C? JZ EXIT ;YES, EXIT CPI CR JNZ WAITNL CALL CRLF MVI C,SYSRES CALL BDOS ;GOT CR, RESET SYSTEM LDA DEFFCB DCR A MOV E,A MVI C,SELDSK CALL BDOS ;SELECT DISK LXI H,DEFFCB+1 MVI B,11 MVI A,'?' CALL FILL ;FILL NAME & EXT FIELDS W. '?' MVI M,0 ;ZERO THE EX BYTE SRC1: LXI D,DEFFCB MVI C,SFF CALL BDOS ;SEARCH FOR FIRST CPI 0FFH JZ NOFILE ;IF NO FILE GOTFILE: DS 0 ADD A ADD A ADD A ADD A ADD A LXI H,DEFBUF MVI D,0 MOV E,A DAD D ;COMPUTE ADDRESS OF DIRECTORY ENTRY INX H ;+1 TO POINT TO FILE NAME CALL ADDLST ;ADD NAME TO LIST SRC2: MVI C,SFN LXI D,DEFFCB CALL BDOS ;SEARCH FOR NEXT CPI 0FFH JNZ GOTFILE ;IF GOT A FILE LABEND: DS 0 ;COME HERE WHEN NO MORE FILES LXI H,STACK SPHL LXI D,MSG6 MVI C,PRTSTR CALL BDOS ;PRINT HEADER CALL SHOWFIL ;SHOW FILES IN LIST NAMECHK: DS 0 SHDONE: LDA DSKNAM CPI SPACE ;SEE IF NAME FILE FOUND JNZ HAVEIT ;IF FOUND LXI D,MSG8 ;NO NAME FILE, PROMPT FOR ONE MVI C,PRTSTR CALL BDOS GETYN: CALL GETCHR CALL UC CPI 'Y' JZ MAKEIT CPI 'N' JNZ GETYN CALL COUT JMP NOMAKE ;USER SAID 'N' HAVEIT: DS 0 LXI H,DSKNAM LXI D,DNAME MVI B,8 CALL COPY ;COPY DISK NAME INX D ;POINT PAST . MVI B,3 CALL COPY ;COPY EXTENSION LXI D,MSG12 MVI C,PRTSTR CALL BDOS ;ASK IF USER WANTS TO CHANGE NAME CALL GETCHR CALL UC CALL COUT CPI 'Y' JNZ MAKEOK ;IF USER SAID 'N' CALL CRLF LDA DEFFCB STA LABFCB ;COPY DRIVE CODE TO FCB STA FCB LXI D,LABFCB MVI C,FDELET CALL BDOS ;DELETE OLD NAME FILE(S) CPI 0FFH JNZ MKIT ;IF OK, PROMPT FOR NEW NAME LXI D,MSG13 CALL BDOS ;IF NOT OK, GIVE ERROR MSG. JMP MAKEOK MAKEIT: CALL COUT ;USER SAID 'Y', ECHO IT CALL CRLF LXI H,DSKNAM MVI A,' ' MVI B,11 CALL FILL ;FILL DSKNAM WITH SPACES MKIT: LXI D,MSG9 MVI C,PRTSTR CALL BDOS ;PROMPT FOR CHARS LXI D,LINEBUF MVI A,7 ;7 MAX. STAX D MVI C,RDBUF CALL BDOS ;READ LINE CALL CRLF ;ECHO CR/LF LXI D,DSKNAM MVI A,'-' STAX D INX D LDA LINEBUF+1 MOV B,A ANA A JZ NOCHRS ;IF NOTHING TYPED LXI H,LINEBUF+2 ;POINT TO CHARS. UCOPY: MOV A,M ;COPY TO DISKNAM CALL UC ;MAKE UPPER-CASE STAX D INX H INX D DCR B JNZ UCOPY NOCHRS: LXI D,MSG10 MVI C,PRTSTR CALL BDOS ;PROMPT FOR NUMBER LXI D,LINEBUF MVI A,3 STAX D MVI C,RDBUF CALL BDOS ;READ FROM CONSOLE LDA LINEBUF+1 MOV C,A ;GET # CHARACTERS ENTERED ANA A JZ BADNUM ;IF NONE MVI A,3 SUB C MOV B,A LXI H,NUMBUF ANA A MVI A,'0' CNZ FILL ;ZERO FILL XCHG ;(DE) IS DEST MOV B,C LXI H,LINEBUF+2 ;SOURCE CALL COPY LXI H,NUMBUF MVI B,3 CHKNUM: MOV A,M ;MAKE SURE ONLY DIGITS ENTERED CPI '0' JC BADNUM CPI '9'+1 JNC BADNUM INX H DCR B JNZ CHKNUM LDA DEFFCB STA FCB LXI D,FCB MVI C,FMAKE CALL BDOS ;CREATE THE NAME FILE CPI 0FFH JZ DIRFULL ;IF ERROR MVI C,FCLOSE LXI D,FCB CALL BDOS ;CLOSE THE FILE JMP MAKEOK BADNUM: CALL CRLF JMP NOCHRS DIRFULL: DS 0 LXI D,MSG11 MVI C,PRTSTR CALL BDOS JMP NOMAKE MAKEOK: LXI D,MSG7A LXI H,DSKNAM MVI B,8 CALL COPY ;COPY NAME TO PROMPT LINE MVI A,'.' STAX D INX D MVI B,3 CALL COPY ;COPY SERIAL #, TOO JMP PROMPT NOMAKE: MVI B,12 ;USER DOESN'T WANT NAME FILE LXI H,MSG7A MVI A,0 CALL FILL ;JUST ZERO NAME FIELD IN PROMPT PROMPT: LXI D,MSG14 MVI C,PRTSTR CALL BDOS ;ASK IF USER WANTS PRINTED LABEL CALL GETCHR CALL UC CALL COUT CPI 'Y' JNZ NOPRNT ;IF NO LXI D,MSG7 MVI C,PRTSTR CALL BDOS ;PROMPT FOR LINE DESCRIBING DISK LXI D,LINEBUF MVI A,60 STAX D ;STORE MAX. # CHARACTERS MVI C,RDBUF CALL BDOS ;READ CONSOLE BUFFER CALL CRLF ;ECHO CR/LF LDA DSKNAM CPI SPACE JZ JUSTSP ;IF NO DISK NAME MVI B,8 LXI H,DSKNAM PRTDN: MOV A,M ;PRINT DISK NAME CALL UC MOV M,A ;MAKE IT UC CPI SPACE CNZ POUT INX H DCR B JNZ PRTDN MVI A,'.' CALL POUT MVI B,3 PRTDSN: MOV A,M ;PRINT DISK SERIAL CALL POUT INX H DCR B JNZ PRTDSN MVI A,SPACE CALL POUT JUSTSP: LXI H,LINEBUF+1 MOV B,M ;GET # READ MOV A,M ANA A JZ NOREAD ;IF NO CHARS. PRTLAB: INX H ;PRINT LINE MOV A,M CALL POUT DCR B JNZ PRTLAB NOREAD: MVI A,CR CALL POUT MVI A,LF CALL POUT LXI H,LCOUNT INR M ;BUMP LINE COUNT CALL PRTFIL ;PRINT FILES MVI A,CR CALL POUT LXI H,LCOUNT DOFF: MOV A,M ;SKIP TO TOP OF NEXT LABEL CPI LABSIZ JNC NXTLAB MVI A,LF CALL POUT INR M JMP DOFF NOPRNT: CALL CRLF NXTLAB: MVI C,SYSRES CALL BDOS ;DO A SYSTEM RESET JMP TOP NOFILE: LXI D,MSG5 MVI C,PRTSTR CALL BDOS JMP NAMECHK ; COME HERE TO ADD A FILE TO THE LIST ; ON ENTRY, (HL) POINTS TO THE FILE NAME (IN FCB FORMAT) ; ; FILES ARE STORED IN THE FORM OF A BINARY TREE. ; EACH NODE OF THE TREE HOLDS 16 BYTES. ; ; BYTE 1 = RESERVED FOR THE USE OF THE EXTRACT ROUTINE. ; BYTES 2-3 = ADDRESS OF LEFT DESCENDANT (0 IF NONE) ; BYTES 4-5 = ADDRESS OF RIGHT DESCENDANT (0 IF NONE) ; BYTES 6-7 = ADDRESS OF HIGHER NODE (0 IF NONE) ; BYTES 8-15 = FILE NAME ; BYTE 16 = UNUSED ; ADDLST EQU $ MOV A,M ;GET 1ST CHAR. CPI '-' JZ NAMEFIL ;IF HYPHEN PUSH H CALL SRCLST POP H RET NAMEFIL: MVI B,11 ;IF NAME FILE, STORE IN SPECIAL PLACE LXI D,DSKNAM PUSH H CALL COPY POP H RET SRCLST EQU $ SHLD START ;SAVE START OF NAME LXI H,FLIST SHLD NODE ;START AT NODE 1 LXI H,0 SHLD LASTND ;CLEAR LAST NODE ADDRESS LHLD TOTAL MOV A,H ORA L JZ ADDNODE ;IF TREE EMPTY CMP1: LHLD NODE ;GET NODE ADDRESS LXI D,7 DAD D ;POINT TO NAME XCHG ;NAME ADDR. IN (DE) LHLD START XCHG CALL COMP8 ;COMPARE NEW ITEM W. ITEM IN TREE JC LESS ;IF NEW ITEM LESS THAN ITEM IN TREE JNZ MORE ;IF NEW ITEM GREATER THAN ITEM IN TREE RET ; NAME ALREADY IN, SO DON'T ADD TO TREE. LESS: LHLD NODE SHLD LASTND INX H MOV E,M INX H MOV D,M DCX H MOV A,D ORA E JZ ADDNODE XCHG SHLD NODE JMP CMP1 MORE: LHLD NODE SHLD LASTND INX H INX H INX H MOV E,M INX H MOV D,M DCX H MOV A,D ORA E JZ ADDNODE XCHG SHLD NODE JMP CMP1 ADDNODE: PUSH H ;SAVE PLACE FOR NEW NODE ADDRESS LHLD TOTAL DAD H DAD H DAD H DAD H LXI D,FLIST DAD D ;COMPUTE ADDRESS OF NEW NODE PUSH H MVI B,8 XRA A CALL FILL ;ZERO 1ST 8 BYTES POP H XCHG ;NEW NODE ADDRESS IN (DE) POP H ;PLACE TO PUT IT IN (HL) MOV A,H ORA L JZ SKIP ;IF NO UPPER NODE MOV M,E INX H MOV M,D ;MAKE LINK DOWN FROM UPPER NODE SKIP: XCHG ;NEW NODE ADDRESS IN (HL) LXI D,5 DAD D XCHG LHLD LASTND ;GET LAST NODE XCHG MOV M,E INX H MOV M,D ;MAKE LINK UP INX H XCHG LHLD START MVI B,8 CPYNAM: MOV A,M ;COPY NAME TO NODE STAX D INX H INX D DCR B JNZ CPYNAM LHLD TOTAL INX H ;BUMP TOTAL COUNT SHLD TOTAL RET GETADD: DCX H ;-1 MOV E,L MOV D,H DAD H DAD H DAD H ;TIMES 8 DAD D ;TIMES 9 XCHG LXI H,FLIST DAD D ;ADD TO START OF LIST RET COMP8: MVI C,8 ;SIZE OF FILE NAME CMP2: LDAX D CMP M RNZ INX H INX D DCR C JNZ CMP2 RET ; EXTRACT = EXTRACT ITEMS FROM BINARY TREE, IN SORTED ORDER ; ; EVERY TIME THIS ROUTINE IS CALLED, IT SETS (HL) TO POINT ; TO THE NEXT NAME IN THE TREE. ; ; THE 'C' FLAG IS SET =1 WHEN ALL ITEMS HAVE BEEN EXTRACTED. ; EXTRACT EQU $ LHLD TOTAL MOV A,L ORA H STC RZ ;IF TREE EMPTY ; WALK DOWN THE TREE ; DOWN: LHLD NODE MOV A,M ;GET 1ST BYTE OF ENTRY CPI 0 JZ DOWNL ;IF ZERO, GO DOWN LEFT CPI 1 ;IF 1, LEFT SUB-TREE DONE, JZ RETNODE ; SO RETURN THIS NODE CPI 2 ;IF 2, NODE DONE BUT R. SUB-TREE NOT DONE, JZ DOWNR ; SO GO DOWN RIGHT JMP UP ;OTHERWISE, GO UP RETNODE: LHLD NODE INR M LXI D,7 DAD D ANA A RET DOWNL: LHLD NODE INX H MOV E,M INX H MOV D,M MOV A,D ORA E JZ NODESC XCHG SHLD NODE JMP DOWN DOWNR: LHLD NODE INX H INX H INX H MOV E,M INX H MOV D,M MOV A,D ORA E JZ NODESC XCHG SHLD NODE JMP DOWN NODESC: LHLD NODE INR M JMP DOWN UP: LHLD NODE ;GET NODE # LXI D,5 DAD D MOV E,M INX H MOV D,M MOV A,D ORA E STC RZ ;IF NO UPPER NODE XCHG SHLD NODE ;STORE NEW NODE INR M ;BUMP 1ST BYTE JMP DOWN ; INIT = INITIALIZE BEFORE EXTRACTION ; INIT: LXI H,FLIST SHLD NODE ;SET NODE TO ROOT OF TREE LXI H,FLIST LXI D,16 LXI B,512 INIT1: MVI M,0 ;MARK ALL NODES UNVISITED DAD D DCX B MOV A,C ORA B JNZ INIT1 RET ; SHOW FILES ON SCREEN ; SHOWFIL EQU $ CALL INIT SHOWF: MVI B,6 ;COUNT OF FILES/LINE SHOWF1: PUSH B CALL EXTRACT POP B JC CRLF ;QUIT IF NO MORE FILES CALL SHOW1 ;SHOW 1 FILE DCR B ;KEEP COUNT OF FILES/LINE JNZ SHOWF2 ;IF NOT PAST LIMIT CALL CRLF ;START NEW LINE JMP SHOWF SHOWF2: MVI A,SPACE CALL COUT MVI A,SPACE CALL COUT JMP SHOWF1 SHOW1: MVI C,8 SHOW1A: MOV A,M CALL COUT INX H DCR C JNZ SHOW1A RET ; PRINT FILES ; PRTFIL EQU $ XRA A STA FCOUNT CALL INIT PRTF: CALL EXTRACT RC LDA FCOUNT INR A STA FCOUNT ;BUMP COUNT OF FILES ON LINE CPI FPL+1 JNC NEWLIN ;IF TOO MANY CALL PRTN ;PRINT NAME JMP PRTF NEWLIN: MVI A,1 STA FCOUNT ;RESET COUNT OF FILES ON LINE MVI A,CR CALL POUT MVI A,LF CALL POUT LDA LCOUNT INR A STA LCOUNT CPI LMAX ;REACHED MAX. LINES? RNC ;YES, QUIT CALL PRTN JMP PRTF PRTN: MVI B,8 PRTN1: MOV A,M ;PRINT NAME CALL POUT DCR B INX H JNZ PRTN1 MVI A,SPACE CALL POUT ;PRINT A SPACE RET ; UTILITY ROUTINES: ; GET A CHAR. FROM THE KEYBOARD ; GETCHR: MVI E,0FFH MVI C,DCIO CALL BDOS ;GET A CHAR. ANA A JZ GETCHR RET ; OUTPUT A CHARACTER TO THE SCREEN ; COUT: PUSH H PUSH D PUSH B PUSH PSW MOV E,A MVI C,DCIO CALL BDOS POP PSW POP B POP D POP H RET POUT: PUSH H PUSH D PUSH B PUSH PSW MOV E,A MVI C,LSTOUT CALL BDOS POP PSW POP B POP D POP H RET UC: CPI 'a' RC CPI 'z'+1 RNC SUI 'a'-'A' RET CRLF: MVI A,CR CALL COUT MVI A,LF JMP COUT COPY: MOV A,M STAX D INX H INX D DCR B JNZ COPY RET FILL: MOV M,A INX H DCR B JNZ FILL RET EXIT: LXI D,MSG4 MVI C,PRTSTR CALL BDOS EXIT2: CALL GETCHR CPI CR JNZ EXIT2 JMP BOOT MSG1: DB CR,LF,'DISK LABEL PROGRAM' DB SPACE,SPACE DB 'VERS. 2.1',SPACE,SPACE,'BY JON DART',CR,LF,'$' MSG2: DB CR,LF,'WHAT DRIVE DO YOU WANT TO USE? $' MSG3: DB CR,LF,'INSERT A DISK INTO DRIVE ' DSK: DB 'A:. TYPE RETURN WHEN READY: $' MSG4: DB CR,LF,CR,LF,'INSERT A BOOTABLE DISK INTO DRIVE A:.',CR,LF DB 'TYPE RETURN TO RE-BOOT: $' MSG5: DB CR,LF,'THERE ARE NO FILES ON THIS DISK.',CR,LF,'$' MSG6: DB CR,LF,'FILES ON THIS DISK:',CR,LF,'$' MSG7: DB CR,LF,'ENTER A LINE DESCRIBING THIS DISK (OPTIONAL)',CR,LF MSG7A: DB '-NNNNNNN.NNN:',SPACE DB '$' MSG8: DB CR,LF,'THIS DISK HAS NO NAME FILE.',SPACE,SPACE DB 'CREATE ONE (Y OR N):',SPACE,'$' MSG9: DB 'ENTER UP TO SEVEN CHARACTERS:',SPACE,'$' MSG10: DB 'ENTER A NUMBER (UP TO 3 DIGITS):',SPACE,'$' MSG11: DB CR,LF,'ERROR -- DIRECTORY FULL!',CR,LF,'$' MSG12: DB CR,LF,'DISK LABEL FILE IS: ' DNAME: DS 8 DB '.' DS 3 DB '. CHANGE IT (Y OR N)? $' MSG13: DB CR,LF,'ERROR -- CAN''T DELETE OLD NAME FILE',CR,LF,'$' MSG14: DB CR,LF,'PRINT A LABEL (Y OR N)? $' LCOUNT: DS 1 ;COUNT OF LINES PRINTED FCOUNT: DS 1 ;COUNT OF FILES PRINTED ON LINE TOTAL: DS 2 ;TOTAL # FILES IN TREE START: DS 2 NODE: DS 2 LASTND: DS 2 FCB: DS 1 DSKNAM: DS 8 ;DISK NAME FILE (STARTS W. '-') NUMBUF: DS 3 ;DISK SERIAL NUMBER DS FCB+36-$ ;ROOM FOR FCB LABFCB: DS 1 DB '-??????????' DS LABFCB+36-$ DS 50 STACK: DS 0 ;STACK LINEBUF: DS 0 ;LINE BUFFER (ABOVE PROGRAM) FLIST EQU LINEBUF+80 ;FILE LIST (ABOVE PROGRAM) END