IMD 1.16: 8/06/2007 19:22:39                    MDIR21 ASM^MENU-V2 ASM  SURVEY COM LCOPY COMLDIR COM/LDIR MSGLOCATE ASMWLPR COM+ LPRINT ASM !LRUN20 ASM'"#$%&'()*+,MOVER ASM-DD COM .DIF-SSEDDOC!/01DIF RNO23DIRR COM45DISASM DOC6DU-V77 DOC-DU2 COM.DYNATESTASM; MDIR.ASM 2.1 ; revised 02/25/82 ; ; CP/M-2 MASTER DISK DIRECTORY PROGRAM ; by Jeff Hammersley, MD. ; ; PRINTS A COMPLETE DISK DIRECTORY INCLUDING ALL USERS, ; SORTED ALPHABETICALLY AND PRINTED 4 WIDE. ; ; Based on 'FMAP' as originally written by Ward Christensen ; and its subsequent evolution to 'SDIR' by Keith Petersen. ; ;---------------------------------------------------------------; ; ; ; Commands: ; ; ; ; MDIR returns all files on the default disDISASM COM0789DISSAM ASM1:;<=>?@ABCDEDISSAM COMFGDISSAM DOCHDIF2 COMsIJKLMNOPDOS COMQDU COM0RSTDU DOCUVWXYZ[\]^_`abcdDU DOCefDUTIL ASMghijklmnopqrstuvDUTIL ASMzwxyz{|}~DUTIL COMHDU-V80 DOC0DU-V80 COM3DU-V81 ASMDU-V81 ASMk under any user. ; ; ; ; Note: optional drive name may be specified. ; ; ; ; ; ; MDIR FILENAME.FILETYPE searches for all files that match ; ; in all user areas. ; ; ; ; MDIR S???.* returns all 4 character files with any extention ; ; in any user areas. ; ; ; ;_______________________________________________________________; ; ; 02/25/82 FIXED PROBLEM WITH TOP-OF-MEMORY CHECK...PROGRAM NOW ; KEEPS TRACK OF WHETHER OR NOT IT OVERWRITES CCP, AN   D ; DOES A WARM BOOT IF NECESSARY. ALSO ADDED TOP-OF-MEM ; CHECK IN BLDORD (MISSED THAT IN VERSION 2.0). THANKS ; TO KEITH PETERSEN (W8SDZ) FOR POINTING OUT THESE DEF- ; ICIENCIES. RON FOWLER ; ; 01/11/81 FIXED PROBLEM WITH SYSTEMS USING NON-ZERO EXTENT MASKS ; BY MODIFYING EXTENT CHECK WITHIN 80H BUFFER TO USE EXM ; FIELD OF THE DISK PARAMETER BLOCK. ; ALSO REMOVED "NAMES" COUNT, ADDED DYNAMIC MEMORY SIZING, ; AND OUT-OF-MEMORY CHECK. ; (you may wonder: "with the ;08/17/80 CORRECTED MISSING INR A IN SEARCH FIRST ROUTINE, ; WHICH CAUSED DUPLICATE LISTING OF THIRD DIRECTORY ; ENTRY. (KBP) ; BASE SET 0 ; ALTCPM EQU 0 ;PUT 1 HERE FOR H8 OR TRS-80 CP/M ; IF ALTCPM BASE SET 4200H ENDIF ; GETVER EQU 12 ;GET VERSION BDOS FUNCT # GETDPB EQU 31 ;GET DPB ADRS BDOS FUNCT # ; FCB EQU BASE+5CH ;SYSTEM FCB NPL EQU 4 ;NUMBER OF NAMES PER LINE CR EQU 0DH ;CARRIAGE RETURN LF EQU 0AH ;LINE FEED DELIM EQU ':' ;FENCE (DELIMITER) CHARACTER ; ORG BASE+100H ;IND OUT WHERE WE'RE LOGGED CALL BDOS ADI 'A' ;MAKE PRINTABLE STA DRNAME ;PRINT HEADER CALL GETEXM ;GET EXTENT MASK CALL FSPEC3 DB CR,LF DB '...Master Directory - Drive ' DRNAME DB 'X:' DB CR,LF,CR,LF,'$' ; FSPEC3 POP D MVI C,PRINT CALL BDOS LXI H,FCB+1 MOV A,M ;GET 1ST CHAR. OF NAME REQUEST STA SAVFCB ;SAVE FOR LATER ; ;MAKE DR FIELD OF FCB '?' TO FORCE RETURN OF ALL USER ENTRIES DCX H ;POINT TO DR FIELD MVI M,'?' ;STORE '?' IN FCB ; ;RETURN ALL DIRECTORY ENTRIES MVI A ;..BYTES LONG LXI H,BASE+80H ;POINT TO BUFFER ADD L ;POINT TO ENTRY MOV L,A ;SAVE (CAN'T CARRY TO H) ;MOVE ENTRY TO TABLE MOV A,M ;GET DR FIELD CPI 0E5H ;IS IT AN ERASED FILE ? JZ MOREDIR ;YES, IGNORE AND GET ANOTHER XCHG ;ENTRY TO DE LXI H,12 ;OFFSET TO EXTENT BYTE DAD D LDA EXTMSK ;GET DPB EXTENT MASK CMA ;GET NOT(EXTMSK) ANA M ;MASK OUT ZERO-EXT BITS JNZ MOREDIR ;IGNORE NON-ZERO PHYSICAL EXTENTS LHLD NEXTT ;NEXT TABLE ENTRY TO HL MVI B,12 ;ENTRY LENGTH LDA BASE+7 ;GETORDER TABLE LOC SHLD ORDER LHLD COUNT ;GET COUNT MOV A,H ORA L ;CHECK FOR ZERO COUNT JZ NFEXIT ;NOTHING IN DIRECTORY, EXIT SHLD OCOUNT ;SAVE FOR ORDER TABLE COUNT SHLD SCOUNT ;SAVE FOR SORT COUNT LHLD ORDER LXI D,TABLE LXI B,12 ;ENTRY LENGTH ; BLDORD MOV M,E ;SAVE LO ORD ADDR INX H MOV M,D ;SAVE HI ORD ADDR INX H ; ; TEST FOR MEMORY LIMIT EXCEEDED ; LDA BASE+7 ;GET TOP PAGE # SUB H ;SUBTRACT CUSO ;AMECf;BLCHH STOOOOOHATHT STTfOOOOOOOOOOOOOOOOOOOOOOWR  power of SD-4x, why bother ; with MDIR?"...answer: "I like its simplicity.") ; ; -- RON FOWLER ; ;07/02/80 FIXED TO ALLOW MORE THAN 256 NAMES IN DIRECTORY, ; PRINT DRIVE NAME, AND ALLOW SPECIFYING DRIVE. ; BY KEITH PETERSEN, W8SDZ. ; ;07/30/80 FIXED TO ELIMINATE CRASH WHEN NO NAMES ARE IN ; DIRECTORY. REPLACED DECIMAL OUTPUT ROUTINE WITH ; SIMPLER ONE WHICH IS SMALLER AND ALLOWS USE OF ; ONE LESS LEADING SPACE SO DISPLAY CAN BE PRINTED ; ON A 72-CHARACTER PRINTER. (KBP) ; JMP START ;JUMP AROUND I.D. DB 'MDIR.COM 02/25/82 ' ; ;SAVE THE STACK START LXI H,0 DAD SP ;H=STACK SHLD STACK ;SAVE IT LXI SP,STACK ;GET NEW STACK LDA FCB ORA A ;ANY DRIVE SPECIFIED? JZ FSPEC2 DCR A ;CORRECT DISK NUMBER FOR CP/M PUSH PSW ;SAVE REQUESTED DISK NUMBER MVI C,CURDSK ;FIND OUT WHERE WE'RE LOGGED CALL BDOS STA CDSK ;SAVE IT FOR LATER POP PSW ;GET REQUESTED DISK NR. MOV E,A ;TO E FOR CP/M MVI C,SELDSK ;SELECT DISK REQUESTED CALL BDOS ; FSPEC2 MVI C,CURDSK ;FC,FSRCHF ;GET 'SEARCH FIRST' FNC LXI D,FCB CALL BDOS ;READ FIRST INR A ;COMPENSATE FOR LATER DCR JMP SOME ;GOT SOME (BECAUSE OF ? IN DR FIELD) ; ;READ MORE DIRECTORY ENTRIES MOREDIR MVI C,FSRCHN ;SEARCH NEXT LXI D,FCB CALL BDOS ;READ DIR ENTRY INR A ;CHECK FOR END (0FFH) JZ SPRINT ;NO MORE - SORT & PRINT ; ;POINT TO DIRECTORY ENTRY SOME DCR A ;UNDO PREV 'INR A' ANI 3 ;MAKE MODULUS 4 ADD A ;MULTIPLY... ADD A ;..BY 32 BECAUSE ADD A ;..EACH DIRECTORY ADD A ;..ENTRY IS 32 ADD  TOP OF SYS PAGE # MOV C,A ;INTO C REG ; TMOVE LDAX D ;GET ENTRY CHAR ANI 7FH ;REMOVE ATTRIBUTES MOV M,A ;STORE IN TABLE INX D INX H MOV A,H ;SUBTRACT PTR FROM TOP SUB C JNZ OKMEM ;JUMP, NOT OUT OF MEM ; MEMFUL: CALL ERXIT ;OOPS, END REACHED DB CR,LF,'OUT OF MEMORY' DB CR,LF,'$' ; OKMEM: DCR B ;MORE? JNZ TMOVE SHLD NEXTT ;SAVE UPDATED TABLE ADDR LHLD COUNT ;GET PREV COUNT INX H ;ADD ONE SHLD COUNT ;RESAVE COUNT JMP MOREDIR ; ;SORT AND PRINT SPRINT LHLD NEXTT ;DEFINE  NOO M H MOV A,L ORA H ;MORE? POP H JNZ BLDORD ;..YES SHLD HIMEM ;SAVE FOR CCP REBOOT FLAG LHLD COUNT ;GET COUNT DCX H MOV A,L ORA H ;ONLY 1 ENTRY? JZ DONE ;..YES, SO SKIP SORT ; SORT XRA A ;GET A ZERO STA SWITCH ;SHOW NONE SWITCHED LHLD SCOUNT ;GET COUNT DCX H ;USE 1 LESS SHLD TEMP ;SAVE # TO COMPARE SHLD SCOU   NT ;SAVE HIGHEST ENTRY MOV A,L ORA H JZ DONE ;EXIT IF NO MORE LHLD ORDER ;POINT TO ORDER TABLE ; SORTLP CALL COMPR ;COMPARE 2 ENTRIES CM SWAP ;SWAP IF NOT IN ORDER INX H ;BUMP ORDER INX H ;..TABLE POINTER PUSH H LHLD TEMP ;GET COUNT DCX H ;ONE LESS SHLD TEMP ;SAVE COUNT MOV A,L ORA H ;DONE? POP H JNZ SORTLP ;CONTINUE ;ONE PASS OF SORT DONE LDA SWITCH ;ANY SWAPS DONE? ORA A JNZ SORT ; ;SORT IS ALL DONE - PRINT ENTRIES DONE LHLD ORDER SHLD NEXTT ; ;PRINT AN ENTRY 2) JNC NULL ; NO, IGNORE IT ORA A ;IS IT USER 0 ? JNZ PTONE2 ;NO, SKIP NEXT ROUTINE CALL SPACE2 ;USER 0, FILL WITH SPACES JMP PTONE3 ;SKIP DECOUT PRINT ; PTONE2 PUSH H MVI H,0 MOV L,A ;NUMBER TO L FOR DECOUT CPI 10 ;LESS THAN 10? CC SPACE ;YES, ADD ONE SPACE CALL DECOUT ;PRINT USER NUMBER POP H ; PTONE3 CALL SPACE ;MAKE IT LOOK NICE INX H ;POINT TO NAME MVI B,8 ;FILE NAME LENGTH CALL TYPEIT ;TYPE FILENAME CALL PERIOD ;PERIOD AFTER FN MVI B,3 ;GET THE FILETYPE CALL TYPEIH ONE CPI '?' ;IS IT A AMBIGUOUS CHARACTER ? JZ AMBC ; YES CMP M ;COMPARE TO MEMORY JNZ NOMATCH ;MATCH FAILURE ; AMBC INX D INX H ;GET NEW CHARACTERS DCR B ;ARE WE DONE ? JNZ MAT1 ;NO, COMPARE NEXT ; FTYP POP H POP D ;RESTORE REGISTERS JMP PTONE ;GO PRINT ONE ; ; SUBROUTINE TO RETRIEVE EXTENT MASK FROM DISK PARM BLK ; GETEXM: MVI C,GETVER ;GET CP/M VERSION NUMBER CALL BDOS MOV A,H ORA L ;TEST FOR VERS 1.4 JZ PUTEXM ;MOVE THE ZERO EXTMSK IF 1.4 MVI C,GETDPB ;IS CPM >1.4, GALL SPACE ; SPACE MVI A,' ' ; ;TYPE CHAR IN A TYPE PUSH B PUSH D PUSH H MOV E,A MVI C,WRCHR CALL BDOS POP H POP D POP B RET ; TYPEIT MOV A,M CALL TYPE INX H DCR B JNZ TYPEIT RET ; CRLF MVI A,CR ;CARRIAGE RETURN CALL TYPE MVI A,LF ;LINE FEED CALL TYPE MVI C,NPL ;NUMBER OF NAMES PER LINE RET ; ;DECIMAL OUTPUT ROUTINE ; DECOUT: PUSH B PUSH D PUSH H LXI B,-10 LXI D,-1 ; DECOU2: DAD B INX D JC DECOU2 LXI B,10 DAD B XCHG MOV A,H ORA L CNM MOV M,C INX H MOV D,M MOV M,B POP H MOV M,D DCX H ;BACK POINTER TO CORRECT LOC'N MOV M,E RET ; NFEXIT CALL ERXIT DB '++NO FILES ON THIS DISK',CR,LF,'$' ; ;ERROR EXIT ERXIT POP D ;GET MSG MVI C,PRINT JMP CALLB ;PRINT MSG, EXIT ; ;ABORT - READ CHAR ENTERED ABORT MVI C,RDCHR ;DELETE THE CHAR ; CALLB CALL BDOS ; ;FALL INTO EXIT ;EXIT - ALL DONE, RESTORE DISK LOG IN AND STACK EXIT LDA CDSK ;GET ORIGINAL DISK NR. MOV E,A ;TO E FOR CP/M MVI C,SELDSK ;RESTORE LOG-IN TO IT MVI C,NPL ;NR. OF NAMES PER LINE ; ENTRY: PUSH B MVI C,CONST ;CK STATUS OF KBD CALL BDOS ;ANY KEY PRESSED? POP B ORA A JNZ ABORT ;YES, ABORT LHLD NEXTT ;GET ORDER TABLE POINTER MOV E,M ;GET LO ADDR INX H MOV D,M ;GET HI ADDR INX H SHLD NEXTT ;SAVE UPDATED TABLE POINTER XCHG ;TABLE ENTRY TO HL LDA SAVFCB ;GET SAVED 1ST CHAR. OF FCB CPI ' ' ;WAS NAME SPECIFIED? JNZ MATCH ;YES, GO SEE IF PRESENT ; ;PRINT USER # PTONE MOV A,M ;GET USER NUMBER CPI 32 ;IS IT VALID ? (IE.< 3T DCR C ;ONE LESS ON THIS LINE PUSH PSW CNZ FENCE ;NO CR-LF NEEDED, DO FENCE POP PSW CZ CRLF ;CR-LF NEEDED ; ;SEE IF MORE ENTRIES NULL PUSH H LHLD COUNT DCX H SHLD COUNT MOV A,L ORA H POP H JNZ ENTRY ;YES, MORE JMP EXIT ; MATCH PUSH D ;SAVE DE PUSH H ;SAVE HL LXI D,FCB ;GET FCB REQUEST INX H ;MOVE TO FN.FT INX D ; MVI B,11 ;GET NUMBER OF CHARACTERS TO COMPARE ; MAT1 LDAX D ;GET CHARACTER CPI '*' ;IS FILENAME OR FILETYPE AMBIGUOUS ? JZ WHCH ; YES, DETERMINE WHICET DPB ADRS CALL BDOS LXI D,4 ;INDEX TO EXTMSK DAD D MOV A,M ;FETCH EXTENT MASK ; PUTEXM: STA EXTMSK ;PUT IT AWAY RET ; WHCH MOV A,B ;GET B CPI 3 ;IS IT STILL THE FILENAME ? JC FTYP ; NO, IT IS ANY TYPE SO WE ARE DONE. MVI B,3 ;YES, LOAD UP TO FILETYPE JMP MAT1 ;RETURN FOR MORE ; NOMATCH POP H POP D ;RESTORE REGISTERS JMP NULL ;GET NEW FILENAME TO TRY ; PERIOD MVI A,'.' JMP TYPE ; FENCE CALL SPACE2 MVI A,DELIM ;FENCE CHARACTER JMP TYPE ; SPACE3 CALL SPACE ; SPACE2 CZ DECOUT MOV A,E ADI '0' CALL TYPE POP H POP D POP B RET ; ;COMPARE ROUTINE FOR SORT COMPR PUSH H ;SAVE TABLE ADDR MOV E,M ;LOAD LO INX H MOV D,M ;LOAD HI INX H MOV C,M INX H MOV B,M ;BC, DE NOW POINT TO ENTRIES TO BE COMPARED XCHG ; CMPLP LDAX B CMP M INX H INX B JZ CMPLP POP H RET ;COND CODE TELLS ALL ; ;SWAP ENTRIES IN THE ORDER TABLE SWAP MVI A,1 STA SWITCH ;SHOW A SWAP WAS MADE MOV C,M INX H PUSH H ;SAVE TABLE ADDR+1 MOV B,M INX H MOV E, CALL BDOS LHLD BASE+6 ;GET TOP-OF-MEMORY PTR MVI L,0 ;ROUND TO PAGE ADRS LXI D,-800H ;SUBTRACT SIZE OF CCP DAD D XCHG ;DE=@CCP LHLD HIMEM ;FETCH OUR HIGHEST USED MOV A,L ;SUBTRACT: HIMEM-CCPLOC SUB E MOV A,H SBB D JC BASE ;MUST WARM-BOOT, CCP NOT THERE LHLD STACK ;GET OLD STACK SPHL ;MOVE TO STACK RET ;..AND RETURN ; HIMEM: DW 0 ;HIGHEST MEMORY USED EXTMSK: DB 0 ;EXTENT MASK NEXTT DW TABLE ;NEXT TABLE ENTRY COUNT DW 0 ;ENTRY COUNT SWITCH DB 0 ;SWAP SWITCH FOR SORT SA   VFCB DS 1 ;SAVED 1ST CHAR. OF FCB CDSK DS 1 ;CURRENTLY LOGGED DISK NUMBER OCOUNT DS 2 ;# NAMES TO PUT IN ORDER TABLE SCOUNT DS 2 ;# TO SORT TEMP DS 2 ;SAVE DIR ENTRY ORDER: DS 2 ;LOC OF ORDER TABLE (TWO BYTES PER NAME) DS 60 ;STACK AREA STACK DS 2 ;SAVE OLD STACK HERE TABLE EQU $ ;READ ENTRIES IN HERE ; ; BDOS EQUATES ; RDCHR EQU 1 ;READ CHAR FROM CONSOLE WRCHR EQU 2 ;WRITE CHR TO CONSOLE PRINT EQU 9 ;PRINT CONSOLE BUFF CONST EQU 11 ;CHECK CONS STAT SELDSK EQU 14 ;SELECT DISK DRIVE FSRCHF ; ; MENU.ASM Version 2.0 as of April 26, 1981 ; ; Original Program by: James J. Frantz, May 31, 1979 ; ;Menu Program Selection for '.BAS', '.INT' or '.COM' Files ; ; ; Modified from original by: Kelly Smith ; ; Version 2.0 contains the following modifications: ; ;(1) Made CP/M 2.x compatible; previous version would ; "clobber" the '$' string delimiter in filename and ; would display filenames and garbage memory 'ad ; nauseum'. ; ;(2) Added  to true, '.COM' ; filetypes are assumed. ; ;(3) Added command option to select drive for user ; requested MENU. (i.e., MENU B:). If corresponding ; filetype is not found for assembled MENU type (.BAS, ; .INT or .COM), MENU will display "+++ File Not Found ; +++" and return to the default drive. ; ;(4) Added "Disk Drive - X:" to heading display, where 'X' ; is the selected drive. ; ;(5) Added conditional assembly switches for 'upper' ; hout ; this. ; ;(8) Fixed bug when MENU is set for BASIC file (either ; MBASIC or CBASIC) and is in B: (or greater drive) and ; attempting to load the MBASIC (or CRUN) and THEN the ; '.BAS' (or '.INT') file...now looks on same diskette ; that MENU is on. ; ;(9) Added 'widecrt' equate for two CRT terminal display ; formats. Set the equate 'widecrt' to true if your CRT ; terminal can display 80 columns by 24 rows. If ; 'widecrt' is false, the d'SYS' files: no$sys$files = true ; ; ; ; A Generalized Suggestions for Using MENU ; ; If you have kids that love to play games on your system, ;this is perhaps the most 'protective' way to keep there ;"busy little hands" out of the CP/M operating ;system...Just set them up with a GAMES diskette that ;AUTOLOAD's the MENU program, and never ever again will you ;hear "Gee Dad, I tried ERA *.* and now nuthi'n works...". ; ; ; true equ -1 ;define true false EQU 17 ; " " FSRCHN EQU 18 ; " " CURDSK EQU 25 ;CHECK CURRENT DISK 0=A: 1=B:, ETC. BDOS EQU BASE+5 ; END D COUNT DCX H SHLD COUNT MOV A,L ORA H POP H JNZ ENTRY ;YES, MORE JMP EXIT ; MAT;SAVE OLD STACK HERE TABLE EQU $ ;READ ENTRIES IN HERE ; ; BDOS EQUATES ; RDCHR EQU 1 ;READ CHAR FROM CONSOLE WRCHR EQU 2 ;WRITE CHR TO CONSOLE PRINT EQU 9 ;PRINT CONSOLE BUFF CONST EQU 11 ;CHECK CONS STAT SELDSK EQU 14 ;SELECT DISK DRIVE FSRCHF  equates for either MBASIC or CBASIC assembly ; function, and corresponding 'heading'. ; ; Note: You must have MBASIC.COM on the currently ; logged diskette if 'mbasic$program' equate is ; true, and it will expect files of type '.BAS'. ; If 'cbasic$program' equate is true, you must ; have CRUN.COM on the currently logged ; diskette, and it will expect files of type ; '.INT'. If neither is equated (uppercase only terminals), 'stdcpm' (standard CP/M), ; 'altcpm' (alternate CP/M). ; ;(6) Added conditional assembly switch for 'no$sys$files', ; to inhibit display of CP/M 2.X 'SYS' files. Handy, if ; running a Remote CP/M System and you don't want to let ; the whole world know whats 'hidden'... ; ;(7) Stripped MSB "tag bit" for files set-up for Remote ; CP/M Systems as "not for distribution". Files would ; not be sorted in proper order for display witefault display is 64 columns ; by 16 rows. ; ; As supplied, MENU.ASM is set-up for the following system ;configuration and display format: ; ; Lowercase terminal display: upper = false ; ; 80 column by 24 row display: widecrt = true ; ; Standard CP/M: stdcpm = true ; altcpm = false ; ; Display '.COM' Menu: mbasic$program = false ; cbasic$program = false ; ; No display of equ not true;define false ; mbasic$program equ false ;true = .BAS cbasic$program equ false ;true = .INT ; ;Note: Only one may be true, and ; both false = .COM ; no$sys$files equ true ;true = no SYS display, false = SYS display ; upper equ false ;true if uppercase only terminal widecrt equ false ;true if 80 column/24 row terminal ; stdcpm equ true ;true if standard CP/M (base address 0000h) altcpm equ false ;true if alternate CP/M (base address 4200h) ; if stdcpm ;if standar   d CP/M... base equ 0000h ;base for standard CP/M system endif ;end if... ; if altcpm ;if alternate CP/M... base equ 4200h ;base for H8 or TRS-80 CP/M system endif ;end if... ; bdos equ base+5 ;CP/M BDOS entry address for function call tfcb equ base+5ch;transient file control block base address ; nbr$col equ 4 ;number of columns to display if widecrt ;if 80 column/24 row crt terminal... screen$size equ 24 ;terminal has 24 lines/screen display screen$hgt equ 80 ;terminal has 80 rows/scive explicity requested? jnz drive$request ;if yes, skip interrogate disk request mvi c,25 ;'interrogate disk' function call bdos ;find out which disk we're on... inr a ;make A: = 1 ; drive$request: ; adi 'A'-1 ;make it ASCII sta driveid ;save the ASCII drive identification sbi '@' ;make it HEX sta srch$fcb ;set selection for requested or default drive mvi c,17 ;'search first' command ; sort$loop: ; lxi d,srch$fcb ;point file control block call bdos ;use CP/M entry point vi c,8 ;length of compare push h ;save pointer to table ; compare1: ; ldax d ;get trial name char ani 7fh ;mask-off high bit 'cause may be ;"tagged" as 'not for distribution' for RCPM's cmp m ;match? jnz end$compare ;if not, try next entry inx h ;advance pointers inx d dcr c ;one less char to compare jnz compare1 ;keep testing ; end$compare: ; pop b ;restore table pointer jc insert$name ;directory name goes in ;front of current table ;entry if lowernters jnz abort ;abort this filename, if "SYS" endif ;end if... ldax d ;get first byte of filename ani 7fh ;mask-off high bit 'cause may be ;"tagged" as 'not for distribution' for RCPM's stax d ;and save back, so proper file sort display lxi h,file$count ;count the number of files inr m ;to be displayed lhld end$of$table ;get pointer to table xchg lxi h,14 ;distance to move dad d ;(hl) point destination shld end$of$table ;save the new end of table inx h inx d ; k mvi c,0 ;initial file number lxi h,dirtable+11 ;point first file number lxi d,13 ;offset to other numbers ; number$files: ; mov a,c ;put file number in (a) adi 1 ;increment daa ;decimal convert mov c,a ;resave in (c) rrc ;get tens digit into rrc ;proper place rrc ; rrc ani 0fh ;add mask jz use$blank ;supress leading zero by adi 10h ;add either 20h (ASCII ' ') ; use$blank: ; adi ' ' ;or 20h + 10h for numeral mov m,a ;put in text stream mov a,c ;get reen display endif ;end if... if not widecrt ;if 64 column/16 row crt terminal... screen$size equ 16 ;terminal has 16 lines/screen display screen$hgt equ 64 ;terminal has 64 rows/screen display endif ;end if... ; ccp$len equ 3c06h-3400h ;calculate CCP length ; bel equ 007h ;(^g) bell - human attention required lf equ 00ah ;(^j) line feed cr equ 00dh ;(^m) carriage return org base+100h start: lxi sp,stack$area ;set up a stack lda tfcb ;get drive specification ora a ;was dr ora a ;test for -1 jm assign$menu$nbr ;print empty jz kludge ;do not set file found, if zero sta file$found ;set file found flag kludge: rrc ;this is the same as rrc ;5 "add a's" rrc ani 60h ;mask correct bits adi 80h ;add base address (0080h) mov e,a ;put pointer in (de) mvi d,0 ;as 16 bit value lxi h,dirtable ;point start of table of ;sorted names inx d ;point past erase field ; compare$loop: ; push d ;save pointer to next ;entry from disk directory m (cy = 1) lxi h,14 ;length of table entry dad b ;(hl) to next table entry pop d ;recover trailer name point jmp compare$loop ;loop again ; insert$name: ; if no$sys$files ;if no SYStem files to be displayed... push b ;save pointer to table entry push d ;save pointer to file name xchg lxi d,9 ;add bias for "SYS" flag character dad d mov a,m ;get character ani 80h ;mask for "SYS" flag pop d ;adjust stack, in case we take the next jump pop b ;...or we really need the poimove$up: ; dcx d dcx h ldax d ;get byte to move mov m,a ;put in new spot mov a,c ;test for done cmp e ;(bc) = (de)? jnz move$up mov a,b cmp d jnz move$up pop h ;recover pointer mvi c,8 call block$move ;insert name in table lxi h,menu$buff ;point menu number block mvi c,6 ;length of movek call block$move ;insert text in table abort: mvi c,18 ;'search next' command jmp sort$loop ; assign$menu$nbr: ; lda file$count mov b,a ;save in (b) push psw ;and on stacunits portion ani 0fh ;mask off tens portion adi '0' ;convert to ASCII inx h mov m,a dad d ;repeat until all files dcr b ;are sequentially numbered jnz number$files pop psw ;get file$count from stack push psw ;and save again for later adi nbr$col-1 mvi b,255 ;(b) accumulates quotient ;so set to -1 for at least ;1 pass thru gives 0 ; divx: ; inr b sui nbr$col ;divide (file$count+3) by ;fout to get offset1 jp divx adi nbr$col ;substracted once too mu   ch ;so add it back on lxi h,offset1 mov m,b ;insert offset1 into table inx h ;point offset2 location jnz setoffset2 ;same as offset1 if non- ;zero remainder dcr b ;else offset2 = offset1-1 ; setoffset2: ; mov m,b ;put offset2 in table inx h ;point offset for col 3 dcr a ;test for remainder of 1 jnz setoffset3 ;if remainder <> 1, use ;offset3 = offset2-1 dcr b ;else offset3 = offset2-1y ; setoffset3: ; mov m,b ;else offset to column 4 ; reprint: ; po mvi a,nbr$col ;4 column per line ; print$name: ; sta column$cnt ;save count of columns push h ;save current name pointer push d ;save offset table pointer if widecrt ;if 80 column/24 row crt terminal... lxi d,doubl$space ;print 2 spaces mvi c,9 ;'print buffer' command call bdos ;use CP/M endif ;end if... lxi d,doubl$space ;print 2 spaces mvi c,9 ;'print buffer' command call bdos ;use CP/M pop d ;get offset table pointer pop h ;get name pointer ldax d ;get t inx d ;advance offset pointer lda column$cnt dcr a ;see if column left = 0 jnz print$name ;print another save line call crlf pop h ;get base of previous line lxi d,14 ;add offset dad d jmp print$line ; finish: ; pop h ;unjunk stack ; lf$loop: ; call crlf lxi d,prompt ;point instruction message mvi c,9 call bdos lxi d,input$buff mvi a,10 ;10 characters maximum stax d mvi c,10 ;'read buffer' command call bdos lxi h,input$buff+1 ;point to character dad d ;add offset b times dcr b jnz find$name push d ;found filename, tidy-up screen... push h lxi d,crlfmsg mvi c,9 call bdos pop h pop d xchg ;save pointer to file name lhld base+6 ;get bdos entry point lxi b,-ccp$len ;offset to start of CP/M dad b push h ;save CP/M entry point ;on stack for branch lxi b,8 ;offset to command buffer "autoload" dad b ;(hl) points place to put name of ;.BAS, .INT, or .COM file to be ;executed push d ;save pointe filename if mbasic$program or cbasic$program ;if BASIC program... lxi h,command$name ;point command name mvi c,len$cmd$name ;length of command name call block$move lda driveid ;get selected drive identification stax d ;store at start of command buffer inx d ;bump for ':' delimeter position mvi a,':' ;make delimeter stax d ;and store it... inx d ;bump for destination pointer to filename endif ;end if... pop h ;point selected file name mvi c,8 ;length of file name cap psw ;recover file count ; reprint1: ; push psw ;save again for later use sta file$count ;save for counting mvi a,screen$hgt ;set for video display size sta line$count lda file$found ;get file$found flag ora a ;and set psw flags jz exit ;if zero, no files of this type found lxi d,heading mvi c,9 ;buffer printer command call bdos ;CP/M prints heading lxi h,dir$table-14 ;point dummy 0th entry ; print$line: ; push h ;save base address lxi d,offset0 ;point offset tableoffset value lxi b,14 ;each name is 14 long ; mult$14: ; dad b ;add 14 for each offset dcr a ;until offset = 0 jnz mult$14 push h ;save new name pointer push d ;save offset pointer xchg ;pointer name to print w/(de) mvi c,9 ;print buffer call bdos ;print file name ;and it's menu number ; test$finish: ; lxi h,file$count ;see if done printing dcr m ;by testing count of files pop d ;get offset pointer pop h ;get pointer to last name jz finish ;no more to prin counter mov a,m ;get it and see if >2 cpi 3 jnc reprint ;reprint the menu mov c,a ;count of digits to (c) mvi b,0 ; get$menu$nbr: ; inx h ;point ASCII digit mov a,m ;get it call ascii$convert ;convert to binary jc reprint ;re-display on error dcr c jnz get$menu$nbr pop psw ;recover file counter cmp b ;file count - request number jc reprint1 ;redisplay menu if illegal lxi d,14 ;increment between names lxi h,dir$table-14 ;point dummy 0th entry ; find$name: ; r to file name xchg ;(de) points to command buffer lxi h,128 ;offset to end of command buffer ;where pointer is stored dad d ;(hl) points to storage place mov m,e ;update buffer pointer to inx h ;the start of the command mov m,d ;buffer so CP/M will read lda driveid ;get selected drive identification stax d ;store at start of command buffer inx d ;bump for ':' delimeter position mvi a,':' ;make delimeter stax d ;and store it... inx d ;bump for destination pointer toll block$move if mbasic$program or cbasic$program ;if BASIC program... lxi h, spec$type mvi c,4 call block$move endif ;end if... xra a ;needs a 0 at end stax d ;of command line ret ; block$move: ; mov a,m stax d inx d inx h dcr c jnz block$move ret ; ascii$convert: ; sui '0' ;subtract ASCII bias cpi 9+1 ;be sure it's numeric cmc rc mov d,a mov a,b rlc rlc rlc add b rc add b rc add d mov b,a ret ; crlf: ; lxi d,crlfmsg mvi    c,9 call bdos lxi h,line$count dcr m ret ; exit: lxi d,nofile ;indicate no files present mvi c,9 call bdos jmp base ;and exit to CP/M via "warm boot" ; if upper ;if uppercase only terminal... nofile: db cr,lf,lf,'+++ FILE NOT FOUND! +++',cr,lf,'$' endif if not upper ;if not uppercase only terminal... nofile: db cr,lf,lf,'+++ File Not Found! +++',cr,lf,'$' endif crlfmsg: db cr,lf,'$' ; heading: db cr,lf,lf if widecrt and mbasic$program db ' ' endier Systems Compatible BASIC File Menu' endif if widecrt and not mbasic$program and not cbasic$program db ' ' endif if not widecrt and not mbasic$program and not cbasic$program db ' ' endif if upper and not mbasic$program and not cbasic$program db 'CP/M COMMAND FILE MENU' endif if not upper and not mbasic$program and not cbasic$program db 'CP/M Command File Menu' endif db cr,lf if widecrt ;if 80 column/24 row crt terminal.. PRESS RETURN: $' endif ;end if... if not upper ;if not uppercase only terminal... prompt: db cr,lf,bel,' Enter menu number, and press return: $' endif ;end if... if mbasic$program ;if MBASIC program... command$name: db 'MBASIC ' ;Microsoft BASIC ; len$cmd$name equ $-command$name ; spec$type: db '.BAS' endif ;end if... if cbasic$program ;if CBASIC program... command$name: db 'CRUN ' ;Compiler Systems BASIC ; len$cmd$name equ $-command$name ; spec$type: db '.INT' endif . srch$fcb: db 0,'????????COM',0,0,0,0 endif ;end if... dir$table: db 255 ; stack$area equ 200*14 + 30 ; input$buff equ stack$area ; end start ;if MBASIC program... srch$fcb: db 0,'????????BAS',0,0,0,0 endif ;end if... if cbasic$program ;if CBASIC program... srch$fcb: db 0,'????????INT',0,0,0,0 endif ;end if... if not mbasic$program and not cbasic$program ;if not BASIC program..!9"i1  *** System Survey (June 82) *** !P Drive>A_! :\o` }‡*.<~2q##n&"r ù>?2I##~2q###~#fo"r#|g}o¤E:rʹ~ #½& K bytes inI!ƀ_#I  files with*r&|/g}/o# K bytes remaining $-<  Memory map: 0 8 16 24 32 40 48 56 64 | | | | | | | | | !k6#6#6 !?2o2p~G/wp!k4#42o>:p2p!m4#4#¶:o#%f if not widecrt and mbasic$program db ' ' endif if upper and mbasic$program db 'MICROSOFT COMPATIBLE BASIC FILE MENU' endif if not upper and mbasic$program db 'Microsoft Compatible BASIC File Menu' endif if widecrt and cbasic$program db ' ' endif if not widecrt and cbasic$program db ' ' endif if upper and cbasic$program db 'COMPILER SYSTEMS COMPATIBLE BASIC FILE MENU' endif if not upper and cbasic$program db 'Compil. db ' ' endif ;end if... if not widecrt ;if 64 column/16 row crt terminal db ' ' endif ;end if... if upper ;if uppercase only terminal... db 'DISK DRIVE - ' endif ;end if... if not upper ;if not uppercase only terminal db 'Disk Drive - ' endif ;end if... driveid:ds 1 ;current logged ASCII drive identification db ':',cr,lf,lf,'$' if upper ;if uppercase only terminal prompt: db cr,lf,bel,' ENTER MENU NUMBER, AND;end if... doubl$space: db ' $' ; menu$buff: db ' - 00$' ; offset0: db 1 ; offset1: db 0,0,0 ; end$of$table: dw dirtable ; file$count: db 0 ; column$cnt: db 4 ; line$count: db 0 ; file$found: db 0 ;file found flag if mbasic$program ;if MBASIC program... srch$fcb: db 0,'????????BAS',0,0,0,0 endif ;end if... if cbasic$program ;if CBASIC program... srch$fcb: db 0,'????????INT',0,0,0,0 endif ;end if... if not mbasic$program and not cbasic$program ;if not BASIC program..: 5: 5 5:p1 5  ¬  T=TPA C=CPM B=BIOS or unassigned R=ROM or bad BIOS atÔ͆Ɛ'@'_:}:}  iobyte:}  drive:}  BDOS at:}:}  *k  Bytes RAM *m  Bytes ROM *  Bytes in TPA |/g}/o  Bytes Empty   Total Active Bytes Active I/O ports!+|z!zʜG2ʹʹzʬ  z_z}# ‡    Ports active *i  |{0__   ~W_!#> :q2k&?{o/G)C???????????͆Ɛ'@'_:}:}  iobyte:}  drive:}  BDOS at:}:}  *k  Bytes RAM *m  Bytes ROM *  Bytes in TPA |/g}/o  Bytes Empty   Total Active Bytes Active I/O ports!+|z!zʜG2ʹʹzʬ  z_z}# ‡    Ports active *i  |{0__ÌM1 ʹ_A:FTT:2pA2:p  ʹ_AhFʂڂh!ph2}A2:} d ʹ 1:O:O _R1 ¹0:O :O:-:O:22::NI:<:q>2:<2<42ͪ<2:ʈ:{:­:<2u4:/g:<2:/g:2!. O222!">2:/2:2:O::O:0OMD***$, DRIVE $ + ERROR ON TRACK (HEX)$ SECTOR (HEX)$ ++PERMANENT $ + READ ERROR $ + WRITE ERROR $ SOURCE ON : OBJECT ON : TYPE TO CONTINUE, OR CONTROL-C TO EXIT: $ TYPE OR "R", TO REPEAT COPY: $ $ SOURCE DRIVE (A THRU D): $ OBJECT DRIVE (A THRU D): $ COPYING TRACK $ + MEMORY COMPARE ERROR ON TRACK (HEX)$ + MEMORY ADDRESS $ (OBJ,SRC) DATA $  *D !|:<2ÖEXIT: $ ",*!9"!9" ! 9" !9"!9"!9"!9""!!9"%!9"y4K͞+88W'+FÎr*y*w#w#w^#V#*~#fo^#*~#fo^#V#*n^#*n^#V# ~#fo^#& ~#fo!+!#!+!#!+!+}|z{|}|z7||7zZZ)|/g}/o#|͉k|/g}/o#ɯ2qZZk:q|/g}/o#|/g}/o#:q<2qqDM!xxGyO҃)v|͔`i|)Öxڷz/W{/_ѯzW{_=yOxGæ2qZZ͉M|}ȯ|g}o)|/g}/o!a{   `OE!y6$ -7rBo&))T])))!yV5:=b#:=#:$=2#v+:<"(">6͋5:&=͋5#*&=|"M1Ϳ5#>6͋5:&=͋5>#͋5>6͋5:'=͋5#*&="<(#>͋5:&=͋5>s͋5>@2=#R1Ϳ5#(,#:==2=)(@#>s͋5#͘(Y#X1:>͋5:&=͋5c1Ϳ5#f1Ϳ52=#(—#>͋5:&=͋5>{͋5c1Ϳ5#(#:$=µ#>}͋5c1Ú#:$=;-͘(#>&͋5͋5f2Ú#:$=$v+è":$CS :&::AO 2ʪ ʹê] ʹ**":Oy|O*" *! "'n*":2ڪ2*"ê ʹ*"!r N& i)))))))**  !" *! "' *H# y8ê":&+)>J~2|}, ~2|}^:, :2::2>2>22!"!"!@"!" ʞ!F#x±~#±!b2r~# "2r+}|~#G:rx"2r+w# +6#!6#2w2x*s!>r<o&F=-/` r'~h6!+`W?_!~7z?` :>ª@w#G.¶ww#?*>?w#> w#.7:77=$,v+2#:$=>$$>͋5v+>͋5>@2$=2#*="<1Ϳ5:=2="<|s$}d$[2Ϳ5z$g$[3Ϳ5>G>)͋5$#͞*D)͏,Ͷ,v++4ʱ$óvR äP ä !9DM!!!!!!͡! ͤ ! ͧ>2N!"S͐G!, ͪ!A ͪ!^ ͪ!} ͪ! ͪ! ͪÈ! ^#Vr+szʈ! ^#Vr+s~#foͭ|xͰÅ!:! ͡G Press CTRL-S to pause; CTRL-C to cancelCopyright (c) 1982 Gary P. Novosielski82-11-14Library DIRectory Ver:%d.%   02d %s %s %s Requires CP/M 2.0 or better Correct syntax is: LDIR []... where , , etc. are library names. Filetype .LBR is assumed if not specified. Ambiguous names are not allowed. %s not found on disk.  väc!9DM͐ ͐͐͐ !3 For help, type LDIR alone.n f  ivm !9DM*N}ʙ *8S #|™ !:!I V >2N͐Y | ! ͐\ #| ͐!b V ͐!:_ !.͐\ #| !x !:b ! ! ! !9!9DM`iw#w͐n}^ ! ^#Vr+sn! n}R ͐d `i^#Vr+s' !d !9 C# !p }“ s !!*8v !*S*8y +| !*S| | *S ~#fo| *S~#fo| ! *S~#fod*S~#fokp })s *S~#fo+*S*8y *S~#fo+d!  !*S~#fok"O"Q*S"U*Un}ʰ*Q|ʰ*Q+"Q*U "UÊ no directorya bad directory!9DM! w#w`i6#6͐ +9DM`i6 #6`i^#Vr+szg͐n͐ nѯgW! s#rzN͐ n}?N͐m! ^#Vr+s! ^#Vr+s !m!9ä!y9DM! `iy`i|!9êí!9DM͐n}! ^#Vr+sn&ͧòE&!h9DM! ^#Vr+s~#fo! s#r͐! s#r! ^#Vr+sn`is{6`in}% ! ! s#r! 6#6! s! s! s͐n}-u! ^#Vr+s! 4͐n}0…! 4͐n&}ʢ! å!! s#r! ^#Vr+sn`is{.! ! s#r! 4! ^#Vr+sn`is`in&}DU6 ! ^#Vr+s`ins3! ^#Vr+s`ins͐6!9KE!9DM͐͐ қ͐^#Vr+s͐ ҈͐0Ð͐7s!&͐ ͐͐ ͉͐H`is͐ ͐͐ )͐H`in&#&!9!9DM`iw#w͐~#fon&}B͐ ?͐^#Vr+snѯg`is#r͐I!97:O* #7,2q*&:q):ʥ=ʥ=r:qo&   > _ 7:,*:= * * * File: LDIR.MSG Date: 82-11-14 To: All Remote System Operators From: Gary P. Novosielski CIS[70160,120] Subj: Library Directory program There have been several requests from RCPM and other remote system operators for a utility to allow callers to see the directory of .LBR files available on the system. LDIR is such a program. LDIR performs no other function besides displaying the directory of .LBR files, and can be made available to callers as a .COM file. While the LU library util!:e "8#|& !:!} h k + !>2N*Q*O! h ! Can't close library: %s Bad library name: %s.LBR Library: %s has %d entries, %d free:ð ív!9DM*S"U! s#r! s#r*O*Q! s#r! ^#Vr+szU *U "Un}G ͐)| !  ! ͧ *U`iͪ `i! ͭ ! ^#Vr+sR ! ^#Vr+s *O*Q͐! ^#Vr+s! ͭ ! ^#Vr+sÉ !9%-8s Active entries: %u, Deleted: %u, Free: %u, Total: %u. !9DM! ^#Vr+sn`is{ `in}* `in}?! ~#fo͐n&|g}os`i^#Vr+s`i6#6͐ Ґ! ~#fo͐n} XÐ! ~#fo! ^#Vr+s! ~#fo͐ns`i^#Vr+s2! ~#fo n} ʽ! ~#fo! ^#Vr+s6.`i6 #6͐ "! ~#fo͐n} "! ~#fo! ^#Vr+s! ~#fo͐ns`i^#Vr+s! ~#fo͐6͐:!9Iò!9DM!! s#r͐͐~#fox!&! ^#Vr+s͐~#foF`is#rzª!&*S|¹͐"S͐͐s#r!&!9 !run out of memory!UX^OgCʭS ͐~#fo|U! ^#Vr+s6-͐͐~#fos#r! ^#Vr+s! 6 m! 6m! 6! ~#fo! n&! ^#Vr+s~#fo! ѯgs#rV! ^#Vr+s! ^#Vr+s~#fos! ^#Vr+sV! n}! 6#6! ^#Vr+s~#fo! s#r͐n}V͐|V! ^#Vr+s! ^#Vr+sns! ^#Vr+s! ^#Vr+s ͐6! ! s#r! n}­! ^#Vr+s!ҭ! ^#Vr+s! n}ʤ!0ç! sr͐! ^#Vr+sns{! ^#Vr+sí! n}! ^#Vr+s!! ^#Vr+s#*!s#r!^#V7:)~:,"s!"u*|*uR**s!ѷʉxO! ! ~„6*u*+"*"*u#"u*s! N#Fp+qE *+*|/g}/o#9#"z{7**~#*7**~#+w# *!9~!0:,!9~o&a{_o:q):ʥ=ʥ=r:qo&   > _ 7:,*:=ity can also perform this function, it would be sucide to leave this out in a useable form, since it could be used to introduce any arbitrary .COM file onto the system. There has been a difference of opinion on whether .LBR's should be squeezed before transmission, or whether the indivudual members should be squeezed before being added to the .LBR. There are good arguments for both sides, but since squeezing an entire library would render the directory unreadable, I suggest taking the latter alte   rnative, and leaving the library as an unsqueezed .LBR rather than a .LQR file. Experimentation has shown that on many libraries, there will be a slight cost in library size by opting for this method, but the visibility of the directory would seem to outweigh this objection. Of course any or all members of the unsqueezed library can still be squeezed files, so there is still a large saving over normal ASCII encoded files. The savings in time and disk space which are inherent in the use of .LBR fards, Gary P. Novosielski # # # e. LDIR.COM BDS C Object code, compiled with V1.44 using the -E option, and CLINKed using the BDSNEW routines where possible. NOBOOT has been run on this version. LDIR.MSG This file. If there are any questions or problems, please feel free to contact me at (201) 935-4087 voice, evenings (EST) and weekends, or via CompuServe [70160,120] using EMAIL or CP-MIG. Reg; LOCATE.ASM - Relocator Program by George D. Massar - Version 1.0 ; ; To generate a relocatable program to be located at the offset below ; the base address of the CP/M BDOS. ; ; NOTE: The program is in the public domain, but not to be ; used for commercial benefit. DONOT remove the ; author's name and his credit. ; ; Command synthax: ; ; LOCATE [(-/+)] ; ; where may be optionally chosen below or above ; the base of BDOS expressing respectively in negative ; CON EQU 2 ; write console function PSTRF EQU 9 ; print string function OPENF EQU 15 ; open file function MAKEF EQU 22 ; make file funciton DELETF EQU 19 ; delete file function CLOSF EQU 16 ; close file function READF EQU 20 ; disk read function WRITF EQU 21 ; write file function SETDMA EQU 26 ; set DMA address FCB EQU 05CH ; file control block FTYP EQU FCB+9 ; file type FCBCR EQU FCB+32 ; current record # FCB2 EQU FCB+16 ; second file field DBUF EQU 80H ; default buffer CTL Eiles also helps to mitigate the slight size increase. The files distributed with this package are: LDIR.C BDS C Source file. LDIR.COM BDS C Object code, compiled with V1.44 using the -E option, and CLINKed using the BDSNEW routines where possible. NOBOOT has been run on this version. LDIR.MSG This file. If there are any questions or problems, please feel free to contact me at (201) 935-4087 voice, evenings (EST) and weekends, or via CompuServe [70160,120] using EMAIL or CP-MIG. Regor positive hex-value with its sign (required). The ; value must be on the page boundary. ; ; Input file(s) expected: .COZ (ORG 000H) ; .COM (ORG 100H) ; ; Output file(s) generated: .COM (relocatable) ; ; Please see LOCATE.DOC for complete description. ; ; ; 1 Nov 81 - First implementation ; 7 Nov 81 - Page offset inquiry added (GDM) ; 5 Dec 81 - Program ID added (GDM) ; 12 Dec 81 - First release, Vers. 1.0 TPA EQU 0100H BDOS EQU 5 WRQU 1FH CR EQU 0DH LF EQU 0AH EOT EQU CTL AND 'Z' ; end of ASCII text ORG TPA GENERATOR: JMP START DB CR,LF,'Relocator - Vers 1.0' DB CR,LF,'George D. Massar' DB CR,LF,'Woodland Hills, CA' DB EOT START: LXI D,FCB2+1 ; get page offset value from ; the command line LDAX D ; look at its sign CPI ' ' ; zero offset if not given JZ ZEROFF CPI '-' ; offset below the BDOS base JZ NEGOFF CPI '+' ; offset above the BDOS base JZ POSOFF GETERR: LXI D,SYNERR ; syntha   x error JMP SENDMSG ZEROFF: XRA A ; zero offset JMP STOFF NEGOFF: CALL CONVERT ; to binary value in HL MOV A,L ORA A ; at page boundary? JNZ GETERR ; no MOV A,H CMA INR A ; negate page offset JMP STOFF POSOFF: CALL CONVERT ; to binary value in HL MOV A,L ORA A ; at page boundary? JNZ GETERR ; no MOV A,H STOFF: STA PGOFF ; store page offset value ; Open program file with org 0000, .COZ OPENZ: LXI H,0 SHLD CSIZE ; reset counter LXILXI D,DBUF LHLD BUFPTR MVI C,128 LOADZ1: LDAX D ; get next byte from DBUF INX D MOV M,A ; and put it in the buffer INX H DCR C ; end of record? JZ LOADZ2 ; yes MOV A,C ANI 07H ; mod 8 = 0? JNZ LOADZ1 ; no - not yet INX H ; leave a room for bit pattern JMP LOADZ1 LOADZ2: INX H ; last room for bit pattern SHLD BUFPTR CALL CKBPTR ; check memory space JMP LOADZ ; ok - go on ; Open program file with org 0100H, .COM OPENX: LXI H,BUFFER SHLD BUFPTRmp if both are the same LDA BITPAT ORA B ; set bit in the pattern STA BITPAT LOADX2: MOV A,B RAR ; advance bit position MOV B,A DCR C ; end of record? JZ LOADX3 ; yes MOV A,C ANI 07H ; mod 8 = 0? JNZ LOADX1 ; no - not yet LDA BITPAT MOV M,A ; store the pattern in buffer INX H JMP LOADX0 LOADX3: LDA BITPAT MOV M,A ; store the last pattern before INX H ; reading the next record SHLD BUFPTR CALL CKBPTR ; check memory space JMP LOADX ; ok - go on END$LOe MOVER location MAKEY: LHLD BUFPTR DCX H SHLD LBYTE ; loc. of the last byte in buf LXI D,-DELTA ; DELTA is the size of Generator DAD D SHLD BUFPTR ; ptr to last byte to be moved MVI A,'C' STA FTYP MVI A,'O' STA FTYP+1 MVI A,'M' STA FTYP+2 ; FTYP = 'COM' LXI D,FCB MVI C,DELETF CALL BDOS ; delete input file .COM XRA A STA FCBCR ; clear current rec # LXI D,FCB MVI C,MAKEF CALL BDOS ; re-create the file .COM CPI 255 ; disk full? (do we need this?) JNZ WRITYe the output file JMP 0 ; warmboot ; SUPPORT SUBROUTINES ; Convert a value in ASCII pointed-to by DE to binary val. in HL CONVERT: LXI H,0 MOV B,H CONV1: INX D LDAX D CPI ' ' ; end of ASCII string? RZ ; yes SUI '0' ; A < '0'? JNC CONV2 ; no LXI D,SYNERR ; synthax error JMP SENDMSG CONV2: CPI 10 JM CONV3 SUI 7 ; A = hex digit CONV3: CPI 17 ; A > 16? JC CONV4 ; no LXI D,SYNERR ; synthax error JMP SENDMSG CONV4: DAD H DAD H DAD H DAD H MOV H,BUFFER SHLD BUFPTR ; at the beg. of the buffer LXI H,FTYP MVI M,'C' INX H MVI M,'O' INX H MVI M,'Z' ; FTYP = 'COZ' XRA A STA FCBCR ; clear current record # LXI D,FCB MVI C,OPENF CALL BDOS CPI 255 ; file present? JNZ LOADZ ; yes - go on LXI D,OPNERR JMP SENDMSG LOADZ: LXI D,FCB MVI C,READF CALL BDOS ; read next record in DBUF ORA A ; end of file? JNZ OPENX ; yes - open the next file LHLD CSIZE LXI D,128 DAD D SHLD CSIZE ; CSIZE = CSIZE + 128  MVI A,'M' STA FTYP+2 ; FTYP = 'COM' XRA A STA FCBCR ; clear current record # MVI C,OPENF LXI D,FCB CALL BDOS CPI 255 ; file present? JNZ LOADX ; yes LXI D,OPNERR JMP SENDMSG LOADX: LXI D,FCB MVI C,READF CALL BDOS ; read next record ORA A ; end of file? JNZ END$LOAD ; yes LXI D,DBUF LHLD BUFPTR MVI C,128 LOADX0: XRA A STA BITPAT ; clear bit pattern MVI B,10000000B LOADX1: LDAX D INX D CMP M ; compare contents bet. files INX H JZ LOADX2 ; juAD: ; Print statistic results and also store them in program ID CALL PRINTA DB CR,LF,'CODE size: $' PRINTA: POP D MVI C,PSTRF CALL BDOS LXI H,CODSIZ SHLD ID$PTR ; ptr to code size in the ID LHLD CSIZE CALL PVALUE ; print CSIZE value CALL PRINTB DB CR,LF,'BDOS offset: $' PRINTB: POP D MVI C,PSTRF CALL BDOS LXI H,BDOFF SHLD ID$PTR ; ptr to BDOS offset in the ID LDA PGOFF MOV H,A MVI L,0 CALL PVALUE ; print BDOFF value ; Write the buffer beginning at th ; no LXI D,DSKERR JMP SENDMSG WRITY: LXI H,MOVER ; set DMA at the beginning of SHLD DMA ; the buffer XCHG WRITY1: MVI C,SETDMA CALL BDOS LXI D,FCB MVI C,WRITF CALL BDOS ; write the next record CPI 255 ; write error? JNZ WRITY2 ; no - go on LXI D,DSKERR JMP SENDMSG WRITY2: LHLD DMA LXI D,128 DAD D ; next DMA SHLD DMA XCHG LHLD LBYTE CALL DSUB ; HL = LBYT-DMA JNC WRITY1 ; jump if need to write more CLOSY: LXI D,FCB MVI C,CLOSF CALL BDOS ; clos C,A DAD B ; HL = 16*HL + digit JMP CONV1 ; continue for next digit ; Print address value in HL PVALUE: MOV A,H PUSH H CALL PHEX ; print MSB of addr POP H MOV A,L CALL PHEX ; print LSB of addr MVI A,'H' CALL PCHAR RET ; print hex char in reg. A PHEX: PUSH PSW RRC RRC RRC RRC ; shift high 4 bits to right CALL PNIB POP PSW PNIB: ANI 0FH CPI 10 ; A < 10 ? JNC PNIB1 ; no ADI '0' JMP PCHAR PNIB1: ADI 'A'-10 ; print a char in reg. A PCHAR   : LHLD ID$PTR MOV M,A ; put char in program ID INX H SHLD ID$PTR MOV E,A MVI C,WRCON CALL BDOS ; and print it on console, too RET ; Check memory space left CKBPTR: PUSH D LXI D,10 DAD D ; HL = BUFPTR+10 XCHG LHLD 6 ; HL = TOPMEM+1 CALL DSUB ; HL = TOPMEM-(BUFPTR+9) LXI D,MEMERR ; memory full? JC SENDMSG ; yes POP D RET ; Send error message and go home SENDMSG: MVI C,PSTRF CALL BDOS JMP 0 ; warmboot ; DATA SPACE FOR GENERATOR ROUTINE ; ID$PThor of the program when- ; ever a user wishes to see by TYPE-ing .COM. ; The dashed line may be substituted with a program name and ; its version. Your name as an author of your own program ; may replace the existing name of the LOCATE creator. ; NOTE: this is the only place you can remove the orginal ; author's name! ; The PASS$ID vector should be at the page boundary or some ; other location where the equivalent ASCII characters of ; the vector would not jeopardize while TYPE-ing the JMP PASS$ID DB CR,LF,'Relocatable Program' DB CR,LF,'----------------------' DB CR,LF,'CODE size: ' CODSIZ: DS 5 DB CR,LF,'BDOS offset: ' BDOFF: DS 5 DB CR,LF,'George D. Massar' DB CR,LF,'Woodland Hills, CA' DB EOT ; DONOT remove EOT here DS 128-(($-MOVER) MOD 128) PASS$ID EQU $-DELTA ; The DELTA offset as indicated here are the special feature ; to locate the MOVER program with the relocatable program ; at 0100H when loading the program under the CCP command. LHLD CSIZE-DEL ; get next byte in the buffer DCX D JNC SKIP ; jump if bit is not set ADD B ; displacement SKIP EQU $-DELTA MOV M,A ; put CODE byte in memory above DCX H DCR C ; 8th byte? JNZ MOVE ; no - go on INX H MOV A,L ORA A ; at page boundary? JNZ MOVEUP ; no - continue to move MOV A,H CMP B ; HL = ptr to the first byte? JNZ MOVEUP ; no - not yet PCHL ; jump to the relocated program ; SUPPORT SUBROUTINE(S) common to both routines DSUB: MOV A,L SUB E MOV L,A R: DS 2 BITPAT: DS 1 ; bit pattern LBYTE: DS 2 ; loc of the last byte DMA: DS 2 ; addr of DMA DS 32*2 STACK: OPNERR: DB CR,LF,'>> File not present <<$' DSKERR: DB CR,LF,'>> Disk full <<$' SYNERR: DB CR,LF,'>> Synthax error <<$' MEMERR: DB CR,LF,'>> Memory overflow <<$' DELTA EQU $-GENERATOR ; size of generator program ; <<<<<<<<< THE FOLLOWING WILL BE WRITTEN INTO DISK >>>>>>>>>> ; The program ID below is to indicate the name of program, ; its size & location*, and the aut program ; ID heading. ; * The location of the relocatable program can be computed ; as follows, for example: ; ; Say BDOS vector is E406H (located at 0006H), ; the offset is F800 (-800H), and the program ; size is 180H. ; ; So, the "ending" of the program is E400+F800-1 = DBFFH ; and the starting is DBFF+1-200 = DA00H. ; ; Note: the value of 200H is the next page greater than 180H. ; The actual ending of the program may be far below than ; DBFFH but no more than a page. MOVER: TA ; program size XCHG LHLD 6 ; HL = base of BDOS+6 LDA PGOFF-DELTA ADD H ; add page offset MOV H,A CALL DSUB-DELTA MOV B,H ; B = displacement MVI L,0 ; HL = new program base DAD D ; HL = dest. of program code XCHG LHLD BUFPTR-DELTA XCHG ; DE = CODE ptr in buffer MOVEUP EQU $-DELTA DCX H LDAX D ; get next pattern byte STA PATTERN DCX D MVI C,8 ; count of 8 bytes to move MOVE EQU $-DELTA LDA PATTERN RAR ; put the corresp. bit in CY STA PATTERN LDAX D MOV A,H SBB D MOV H,A ; HL = HL - DE RET ; DATA SPACE for MOVER routine PATTERN EQU $-DELTA DS 1 ; bit pattern hold ; DATA ALLOCATION common to both routines CSIZE: DS 2 ; size of movable program code PGOFF: DS 1 ; page offset BUFPTR: DS 2 ; buffer pointer hold BUFFER: ; start of "big" buffer END  PCHL ; jump to the relocated program ; SUPPORT SUBROUTINE(S) common to both routines DSUB: MOV A,L SUB E MOV L,A    *K͞+EEI'+FÎr ͖ 8{ Ăw#w#w^#V#*~#fo^#*~#fo^#V#*n^#*n^#V# ~#fo^#& ~#fo!+!#!+!#!+!+}|z{|}|z7||7zZZ)|/g}/o#|͉k|/g}/o#ɯ2qZZk:q|/g}/o#|/g}/o#:q<2qqDM!xxGyO҃)v|͔`i|)Öxڷz/W{/_ѯzW{_=yOxGæ2qZZ͉M|}ȯ|g}o)|/g}/o!a{   `OE!y6$ -7rBo&))T])))!y2=͖)Ͷ)))2=D':>".6:=º#:=Q$:>ʊ#+:=J#\)#>6O6:>O6w#*>|,#2̓6w#>6O6:>O6>#O6>6O6:>O6w#*>"=\)n#>O6:>O6>sO6>@2=w#2̓6f#C)„#:==2=s)\)˜#>sO6f# )±#2:=ʫ#!2̓6f#L3̓6f#*="=*>"=:>$:=#\)#>>O6:>O6'2̓6w#*2̓62=w#\)#>O6:>O6>{O6'2̓6f#\)4$:> $>}O6'2#:>  \ Ϳ! ^#Vr+sÍͿ͐!9 Enter file to print, or CR if done: Can't open %s Printing %-13spage file: %18s%-13s%10s%-3d%25s ð !9DM`i6#6! 6#6! 6! n&  ͐! n& |g}os! n&! ͐n&|g}os! 4 ! n&` ! n&|g}o|R ! ! s#r] ! ! s#rk ! ! s#r! n&! n&! n&! n&|g}o! n&|g}o ?! nѯg͐! n&! n&! n&|g}o ?! nѯg! ͐ͭ !9! Þv!9DM`i6#6͐ ! s#r͐  ! s#r!H ͐#|N ! ! ^#Vr+s͐s{ ˜ ͐͐ #ҕ ͐++n} • ! ^#Vr+s6 `i^#Vr+sz ͐  ! s#rz ͐N ͐ ͐ ͐ ͐6͐ !9 Ö(!h9DM! ^#Vr+s~#fo! s#r͐! s#r! ^#Vr+sn`is{]`in}%G! ! s#r! 6#6! s! s! s͐n}-œ! ^#Vr+s! 4͐n}0¬! 4͐n&}! !! s#r! ^#Vr+sn`is{.! ! s#r! n}.! ^#Vr+s!.! ^#Vr+s6 D! ^#Vr+s`insZ! ^#Vr+s`ins;͐6!9rü!9DM͐n}ʜ! ^#Vr+sn&ozêí!9DM͐|͡m͐+++|!ͤm͐##^#Vr+s|V!͐͐~#foͧ`is#r!)͐##^#Vr+sm͐##͐?+s#r͐͐s#r͐^#Vr+sn&m!9|6!9DM͐|›! n&y͐ڻ͐##~#fo!͐^#Vr+s! ns͐##^#Vr+s!!9DM͐#z/W{/_!9~#fo! ! ! ! ! ! !9~#A"s!`*"!"!Y">2>2>22!"!"!@"!" ʞ!F#x±~#±!b2r~# "2r+}|~#G:rx"2r+w# +6#!6#2w2x*s!>r<o&F=-` r'~h6!+`W?_!~7z?` :>ª@w#G.¶ww#?*>?w#> w#.7:77- )K$>&O6O6*3#:>_$+#:=p$,+Ê#:>>|$>O6+>O6>@2>Ê#*="=2̓6:=2="=|$}¼$3̓6$¿$4̓6>GÏm Û ê ü (  6!/9DM*s#r! s#r*##6B#6̓+|! ^#Vr+s~#fo! s#r! ^#Vr+s<!@ ͤ! ͡! s#rn}<7 ! ͐ͧ! s#rzm͐!f ͤ{͐!u ͤ! ͪ! 6#6!*ͭ! ͐! ͐! ! !$ Ͱ!9!$ ͳ! !$ Ͷ|( ͹|ͼ( !$ ͳ|9PMAM%d:%d%d %s - %d/%d%d/%d%d1 L  !9DM! 6! ^#Vr+sn`is{ `in} l u ʛ ! 6 ! + ! + *w#w*##^#Vr+s ! + *^#Vr+s\|› `in&  `in&|g}o+ *^#Vr+s? ! n} . ! n& !9 L !  @ *##^#Vr+sz@ !  # *##6B#6R E!9DM! n&!O v l!y9DM! `ip `is !9á i!9DM͐!͐͞ s#rz !͐##w#w͐~#fo !9DM! ͐  4! ^#Vr+sn`is`in& }D@U|XʅOʎCS1͐~#fo||! ^#Vr+s6-͐͐~#fos#r! ^#Vr+s! 6 Ô! 6Ô! 6! ~#fo! n&! ^#Vr+s~#fo! ѯgs#r}! ^#Vr+s! ^#Vr+s~#fos! ^#Vr+s}! n}! 6#6! ^#Vr+s~#fo! s#r͐n}}͐|}! ^#Vr+s! ^#Vr+sns! ^#Vr+s! ^#Vr+s3͐6! ! s#r! n}! ^#Vr+s!! ^#Vr+s! n}!0! sÙ͐! ^#Vr+sns{! ^#Vr+s! B͐^#Vr+s͐ /͐07͐7s!&Í͐ ͐͐ ͉͐`is͐ ͐͐ )͐`in&#&Í!9!9DM! n&0ͯ! n&9ͯÖ!9DM`iw#w͐~#fon&}͐ ?͐^#Vr+snѯg`is#r͐!9.`!9DM! n&+|U! n&Z! n&!9DM! n&aͯڋ! n&zͯ 6  #F#xʷ~#ê   > _ :w&o !,   :wo2w&!o 3 . & )6!7*+++:G_*DM!do&7,2q*&:q):ʥ=ʥ=r:qo&7:O*o`7:)~:,"s!"u*|**s! ~6*u*+"*"*u#"u:wo2w&&zͯ 6  #F#xʷ~#ê   > _ :w&o !,; 22/2/80: 1117 ; P.P.H. LEE, ; ROYAL MELBOURNE INSTITUTE OF TECHNOLOGY, ; APPLIED PHYSICS DEPARTMENT, ; 124 LATROBE STREET, MELBOURNE, ; VICTORIA 3000, AUSTRALIA. ; PROGRAM TO SET THE LIST DEVICE BITS OF THE SYSTEM'S ; IOBYTE TO LINE PRINTER OR TTY. ; TO EXECUTE TYPE: ; LPRINT ON - EQUIVALENT TO STAT LST:=LPT: ; LPRINT OFF - EQUIVALENT TO STAT LST:=TTY: ; EQUATES: IOBYTE EQU 3 ; SYSTEM'S IOBYTE BDOS EQU 5 ; CP/M BDOS ENTRY POINT PRINT EQU 9 ; BDOS PRINT BUFFER TFCB EQU 5CH ; DEFAULT FCB V A,B ; GET CLEARED IOBYTE TO A STA IOBYTE ; REPLACE CALL EXIT DB 'LST:=TTY:',0DH,0AH,'$' LPRNT2: CALL EXIT DB '++ NO ON/OFF',0DH,0AH,'$' EXIT: POP D ; GET START OF MESSAGE MVI C,PRINT ; PRINT MESSAGE CALL BDOS LHLD STACK ; GET OLD STACK SPHL ; RESTORE RET ; EXIT BACK TO CP/M COMP: MVI C,3 ; SET CHARACTER COUNT COMP1: LDAX D ; GET TEST CHAR CMP M ; COMPARE WITH INPUT CHAR RNZ ; RIF NOT SAME INX D INX H DCR C JNZ COMP1 ; BRIF SOME MORE RET ; DATA: ON: DB 'ON 'TITLE 'LRUN Library Run--a utility for .LBR files' VERSION EQU 2$0 ;82-11-19 Added equates for user ; area to search for command.lbr. ; ; 1$0 ;82-08-06 Initial source release PAGE 60 ; ; Requires MAC for assembly. Due to the complexity of ; the relocation macros, this program may take a while ; to assemble. Be prepared for periods of no disk activity ; on both passes before pressing panic button. G.P.N. ; ;--------------------------NOTICE------------------------------ ; ; (c) Copyrit prior written aproval is granted ; only under the following conditions. ; ; 1. No charge is imposed for the program. ; 2. Charges for incidental costs including ; but not limited to media, postage, tele- ; communications, and data storage do not ; exceed those costs actually incurred. ; 3. This Notice and any copright notices in ; the object code remain intact ; ; (signed) Gary P. Novosielski ; ;-------------------------------------------------------------- ; ; LRUN i ORG 100H LPRINT: LXI H,0 ; GET OLD STACK DAD SP SHLD STACK ; AND SAVE IT LXI SP,STACK ; SET NEW STACK POINTER LDA IOBYTE ; GET SYSTEM'S IOBYTE ANI 3FH ; CLEAR LST: BITS MOV B,A ; SAVE IT FOR LATER LXI H,TFCB+1 LXI D,ON ; CHECK FOR ON CALL COMP JNZ LPRNT1 ; BRIF NOT MOV A,B ; GET CLEARED IOBYTE TO A ORI 80H ; SET IT TO LPT: STA IOBYTE ; REPLACE CALL EXIT DB 'LST:=LPT:',0DH,0AH,'$' LPRNT1: LXI H,TFCB+1 LXI D,OFF ; CHECK FOR OFF CALL COMP JNZ LPRNT2 ; BRIF NOT MO OFF: DB 'OFF' DS 128 ; STACK AREA STACK: DS 2 ; OLD STACK END  ON/OFF',0DH,0AH,'$' EXIT: POP D ; GET START OF MESSAGE MVI C,PRINT ; PRINT MESSAGE CALL BDOS LHLD STACK ; GET OLD STACK SPHL ; RESTORE RET ; EXIT BACK TO CP/M COMP: MVI C,3 ; SET CHARACTER COUNT COMP1: LDAX D ; GET TEST CHAR CMP M ; COMPARE WITH INPUT CHAR RNZ ; RIF NOT SAME INX D INX H DCR C JNZ COMP1 ; BRIF SOME MORE RET ; DATA: ON: DB 'ON 'ght 1982 Gary P. Novosielski ; All rights reserved. ; ; The following features courtesy of Ron Fowler: ; 1) command line reparsing and repacking (this allows ; the former load-only program to become a load & run ; utility). ; 2) code necessary to actually execute the loaded file ; 3) the HELP facility (LRUN with no arguments) ; 4) modified error routines to avoid warm-boot delay ; (return to CCP directly instead) ; ; Permission to distribute this program in source or ; object form withous intended to be used in conjunction with libraries ; created with LU.COM, a library utility based upon the ; groundwork laid by Michael Rubenstein, with some additional ; inspiration from Leor Zolman's CLIB librarian for .CRL files. ; ; The user can place the less frequently used command (.COM) ; files in a library to save space, and still be able to run ; them when required, by typing: ; LRUN . ; The name of the library can be specified, but the greatest ; utility will be    achieved by placing all commands in one ; library called COMMAND.LBR, or some locally defined name, ; and always letting LRUN use that name as the default. ; ;Syntax: ; LRUN [-] [] ; ;where: ; is the optional library name. In the ; distrubution version, this defaults to ; COMMAND.LBR. If the user wishes to use a ; different name for the default, the 8-byte ; literal at DFLTNAM below may be changed to ; suit local requirements. The current drive ne> ; which is just the normal command line with ; LRUN prefixed to it. ; ;-------------------------------------------------------------- ; USER MODIFIABLE EQUATES ; ; Define a secondary search drive and user if .LBR is ; not found after initial search of current area: ; SSDRV: EQU 'A' ;Valid values are 'A' through 'P'. SSUSR: EQU 0 ;Valid values are 0 through 31. ; ;Default library may also be modified. See label DFLTNAM. ;-------------------------------------------------------------- SET BOOT+5 TFCB EQU BOOT+5CH TFCB1 EQU TFCB TFCB2 EQU TFCB+16 TBUFF EQU BOOT+80H TPA EQU BOOT+100H CTRL EQU ' '-1 ;Ctrl char mask CR SET CTRL AND 'M' LF SET CTRL AND 'J' TAB SET CTRL AND 'I' FF SET CTRL AND 'L' BS SET CTRL AND 'H' FALSE SET 0 TRUE SET NOT FALSE ; CPM MACRO FUNC,OPERAND,CONDTN LOCAL PAST IF NOT NUL CONDTN DB ( J&CONDTN ) XOR 8 DW PAST ENDIF ;;of not nul condtn IF NOT NUL OPERAND LXI D,OPERAND ENDIF ;;of not nul operand IF NOT NUL FUNC MVI C,@&FUNC ENDI ; RTAG MACRO LBL ??R&LBL EQU $+2-@BASE ENDM ; RGRND MACRO LBL ??R&LBL EQU 0FFFFH ENDM ; R MACRO INST @RLBL SET @RLBL+1 RTAG %@RLBL INST-@BASE ENDM ; NXTRLD MACRO NN @RLD SET ??R&NN @NXTRLD SET @NXTRLD + 1 ENDM ; ; ; Enter here from Console Command Processor (CCP) ; CCPIN ORG TPA JMP INTRO ;Jump around signon ; SIGNON: DB 'LRUN Ver ' ;Signon message DB VERSION/10+'0' DB '.' DB VERSION MOD 10+'0' DB CR,LF DB ' Copyright (c) 1982 Gary P. Novosielski ' DB '$',Cwhich specifies ;which addresses need to be adjusted is located ;just after the last byte of the source segment, ;so (HL) is now pointing at it. POP D ;beginning of newly moved code. LXI B,SEGLEN;length of segment PUSH H ;save pointer to reloc info MOV H,D ;offset page address ; FIXLOOP: ;Scan through the newly moved code, and adjust any ;page addresses by adding (H) to them. The word on ;top of the stack points to the next byte of the ;relocation bit table. Each bit in the table ;correspo; is searched for the .LBR file, and if not ; found there, the A: drive is searched. ; **Note that the leading minus sign (not a part ; of the name) is required to indicate an ; override library name is being entered. ; ; is the name of the .COM file in the library ; ; is the (possibly empty) set of parameters ; which are to be passed to , as in ; normal CP/M syntax. Notice that if the ; library name is defaulted, the syntax is ; simply: ; LRUN only (look like CCP) RET ; End of setup. ; ; Utility subroutines NEGDE: ;DE = -DE MOV A,D CMA MOV D,A ; MOV A,E CMA MOV E,A INX D RET ; ; REPARSE re-parsa null? (no arguments) JZ HELP ;interpret as a call for help CPI ' ' ;not null, skip blanks JZ SCANBK CPI '-' ;library name specifier? JNZ NOTLBR ;skip if not INX H ;it is, skip over flag character LXI D,LBRFIL ;parse library name into FCB CALL GETFN NOTLBR: LXI D,MEMBER ;now parse the command name CALL GETFN LXI D,HOLD+1 ;pnt to temp storage for rest of cmd line MVI B,-1 ;init a counter CLSAVE: INR B ;bump up counter MOV A,M ;fetch a char STAX D ;move it to hold area byte doesn't INX B ; include itself or null terminator BLKMOV TBUFF ;moving everybody to Tbuff LXI H,TBUFF+1 ;point to the command tail LXI D,TFCB1 ;first parse out tfcb1 CALL GETFN LXI D,TFCB2 ;then tfcb2 CALL GETFN RET ; ; Here when HELP is requested (indicated ; by LRUN with no arguments) ; HELP: CPM MSG,HLPMSG ;print the HELP message EXIT: LHLD SPSAVE ;find CCP re-entry adrs SPHL ;fix & return RET ; ; the HELP message ; HLPMSG: DB CR,LF,'Correct syntax is:' DB CR,   LF DB LF,TAB,'LRUN [-] ' DB CR,LF DB LF,'Where is the optional library name' DB CR,LF,'(Note the preceding "-". ) If omitted,' DB CR,LF,'the default command library is used.' DB LF DB CR,LF,' is the name and parameters' DB CR,LF,'of the command being run from the library,' DB CR,LF,'just as if a separate .COM file were being run.' DB CR,LF,'$' ; ; COMPARE: ;Test status, name and type of PUSH H ;a directory entry. MVI B,1+8+3 XCHG file name ; ; ; GETFN: CALL NITF ;init 1st half of fcb CALL GSTART ;scan to first character of name RZ ;end of line was found - leave fcb blank CALL GETDRV ;get drive spec. if present CALL GETPS ;get primary and secondary name RET ; ; nitf fills the fcb with dflt info - 0 in drive field ; all-blank in name field, and 0 in ex,s1,s2 and rc flds ; NITF: PUSH D ;save fcb loc XCHG ;move it to hl MVI M,0 ;zap dr field INX H ;bump to name field MVI B,11 ;zap all of name fld NITLPrn CPI ';' ;end of line? RZ ;yup - return w/flag ORA A RZ ;yup - return w/flag INX H ;nope - move over it JMP GSTART ;and try next char ; ; getdrv checks for the presence of a drive spec at the text ; pointer, and if present formats it into the fcb and ; advances the text pointer over it. ; entry hl text pointer ; de pointer to first byte of fcb ; exit hl possibly updated text pointer ; de pointer to second (primary name) byte of fcb ; GETDRV: INX D ;point to name if spec not found name (if present) ; GETPS: MVI C,8 ;max length of primary name CALL GETNAM ;pack primary name into fcb MOV A,M ;see if terminated by a period CPI '.' RNZ ;nope - secondary name not given ;return default (blanks) INX H ;yup - move text pointer over period FTPOINT:MOV A,C ;yup - update fcb pointer to secondary ORA A JZ GETFT INX D DCR C JMP FTPOINT GETFT: MVI C,3 ;max length of secondary name CALL GETNAM ;pack secondary name into fcb RET ; ; getnam copies a name from the tex delimiter yet? RZ ;if so, name is transfered INX H ;if not, move over character CPI '*' ;ambigious file reference? JZ AMBIG ;if so, fill the rest of field with '?' STAX D ;if not, just copy into name field INX D ;increment name field pointer DCR C ;if name field full? JNZ GETNAM ;nope - keep filling JMP GETDEL ;yup - ignore until delimiter AMBIG: MVI A,'?' ;fill character for wild card match QFILL: STAX D ;fill until field is full INX D DCR C JNZ QFILL ;fall thru to ingore rest o ;with the one we're LXI H,MEMBER ;looking for. COMPAR1: LDAX D CMP M JNZ COMPEXIT INX D INX H DCR B JNZ COMPAR1 COMPEXIT: ;Return with DE pointing to POP H ;last match + 1, and HL still RET ;pointing to beginning. ; ; ; File name parsing subroutines ; ; getfn gets a file name from text pointed to by reg hl into ; an fcb pointed to by reg de. leading delimeters are ; ignored. ; entry hl first character to be scanned ; de first byte of fcb ; exit hl character following1: MVI M,' ' INX H DCR B JNZ NITLP1 MVI B,4 ;zero others NITLP2: MVI M,0 INX H DCR B JNZ NITLP2 XCHG ;restore hl POP D ;restore fcb pointer RET ; ; gstart advances the text pointer (reg hl) to the first ; non delimiter character (i.e. ignores blanks). returns a ; flag if end of line (00h or ';') is found while scaning. ; exit hl pointing to first non delimiter ; a clobbered ; zero set if end of line was found ; GSTART: CALL GETCH ;see if pointing to delim? RNZ ;nope - retu INX H ;look ahead to see if ':' present MOV A,M DCX H ;put back in case not present CPI ':' ;is a drive spec present? RNZ ;nope - return MOV A,M ;yup - get the ascii drive name SUI 'A'-1 ;convert to fcb drive spec DCX D ;point back to drive spec byte STAX D ;store spec into fcb INX D ;point back to name INX H ;skip over drive name INX H ;and over ':' RET ; ; getps gets the primary and secondary names into the fcb. ; entry hl text pointer ; exit hl character following secondary t pointer into the fcb for ; a given maximum length or until a delimiter is found, which ; ever occurs first. if more than the maximum number of ; characters is present, characters are ignored until a ; a delimiter is found. ; entry hl first character of name to be scaned ; de pointer into fcb name field ; c maximum length ; exit hl pointing to terminating delimiter ; de next empty byte in fcb name field ; c max length - number of characters transfered ; GETNAM: CALL GETCH ;are we pointing to af name GETDEL: CALL GETCH ;pointing to a delimiter? RZ ;yup - all done INX H ;nope - ignore another one JMP GETDEL ; ; getch gets the character pointed to by the text pointer ; and sets the zero flag if it is a delimiter. ; entry hl text pointer ; exit hl preserved ; a character at text pointer ; z set if a delimiter ; GETCH: MOV A,M ;get the character CPI '.' RZ CPI ',' RZ CPI ';' RZ CPI ' ' RZ CPI ':' RZ CPI '=' RZ CPI '<' RZ CPI '>' RZ ORA A ;Set ze    ro flag on end of text RET ; ; ; Error routines: ; BADVER: CALL ABEND DB 'Can''t run under CP/M 1.4' DB '$' NODIR: CALL ABEND DB 'Library not found' DB '$' FISHY: CALL ABEND DB 'Name after "-" isn''t a library' DB '$' NOMEMB: CALL ABEND DB 'Command not in directory' DB '$' NOLOAD: CALL ABEND DB 'No program in memory' DB '$' NOFIT: CALL ABEND DB 'Program too large to load' DB '$' ; COMLIT: DB 'COM' ; DFLTNAM:DB 'COMMAND ' ; <---change this if you like--- ********************* R ;Get length of .COM member to load. MVI A,TPA/128 ADD L ;Calculate highest address MOV L,A ;To see if it will fit in ADC H ;available memory SUB L MOV H,A REPT 7 DAD H ENDM XCHG CALL NEGDE ;IT'S STILL IN LOW MEMORY R DAD D JNC NOFIT ;Haven't overwritten it yet. LBROPN: ; The library file is still open. The open FCB has been ; moved up here into high memory with the loader code. ; R ;Set up for random readthe sector ORA A ;Ok? R ;No, bail out. ; R ;Increment random record field INX H R ; R ;Until done. ; ERR: MVI A,( JMP ) ;Prevent execution of bad code STA TPA R SHLD TPA+1 R ;Execute dummy program instead ERRX: LXI H,BOOT ;One more time, but this time SHLD TPA+1 ;Jump to BOOT ; R CPM MSG R ;Abort SUBMIT if in progress CPM DEL LOADED: R s MAXMEM DS 2 LOADDR DS 2 ;************************************************* ;End of segment to be relocated. IF OVERLAY EQ 0 OVERLAY SET $ ENDIF ; PAGES EQU ($-@BASE+0FFH)/256+8 ; SEGLEN EQU OVERLAY-@BASE ORG @BASE+SEGLEN PAGE ; Build the relocation information into a ; bit table immediately following. ; @X SET 0 @BITCNT SET 0 @RLD SET ??R1 @NXTRLD SET 2 RGRND %@RLBL+1 ;define one more label ; REPT SEGLEN+8 IF @BITCNT>@RLD NXTRLD %@NXTRLD ;next value ENDIF IF @BITCNT=@RLBRLIT: DB 'LBR' ; ABEND: LDA ENTUSR MOV E,A CPM USR ;Reset to entry user. CPM MSG,NEWLIN POP D CPM MSG CPM DEL,SUBFILE CPM MSG,ABTMSG JMP EXIT ABTMSG: DB '...ABORTED.$' NEWLIN: DB CR,LF,'$' SPSAVE: DS 2 ;stack pointer save ; PAGE ;Adjust location counter to next 256-byte boundry @BASE ORG ($ + 0FFH) AND 0FF00H @RLBL SET 0 ; ; The segment to be relocated goes here. ; Any position dependent (3-byte) instructions ; are handled by the "R" macro. ;****************************s R XRA A R ; LXI H,TPA R ; This high memory address and above, including CCP, must be ; protected from being overlaid by loaded program PROTECT: ; LOADLOOP: ;Load that sucker. R ;See if done yet. MOV A,L ORA H R DCX H R ; R ;Increment for next time MOV D,H MOV E,L LXI B,80H DAD B R CPM DMA ;but use old value (DE) ; R CPM RRD ;Read MOV E,A CPM USR ;Restore USR number from setup. CPM DMA,TBUFF ;Restore DMA adrs for user pgm CPM CON,LF ;Turn up a new line on console JMP TPA ; LDMSG: DB 'BAD LOAD$' INDEX DW 0 LENX DW 0 ENTUSR DB 0 SUBFILE: DB 1,'$$$ SUB',0,0,0,0 ;If used, this FCB will clobber the following one. ;but it's only used on a fatal error, anyway. LBRFIL: DS 32 ;Name placed here at setup DB 0 ;Normal FCB plus... OVERLAY SET $ ;(Nothing past here but DS's) RANDOM DS 3 ;...Random access byteLD @X SET @X OR 1 ;mark a bit ENDIF @BITCNT SET @BITCNT + 1 IF @BITCNT MOD 8 = 0 DB @X @X SET 0 ;clear hold variable for more ELSE @X SET @X SHL 1 ;not 8 yet. move over. ENDIF ENDM ; DB 0 HOLD: DB 0,0 ;0 length, null terminator DS 128-2 ;rest of HOLD area MEMBER: DS 16 ; END CCPIN RGRND %@RLBL+1 ;define one more label ; REPT SEGLEN+8 IF @BITCNT>@RLD NXTRLD %@NXTRLD ;next value ENDIF IF @BITCNT=@R   ; junk rom mover ; 13 mar 1983 ; org 5000h ; start: in 1ch db 0cbh,0ffh out 1ch ; we just banked in the lower 16k of bank 2 ; the first 2048 bytes are the system rom ; move: lxi h,0 ;start address lxi d,4000h ;where to put things lxi b,800h ;count of bytes to move movelp: mov a,m ;get byte stax d ;move it inx h ;point to next get inx d ;point to next put dcx b ;down count bytes to go mov a,c ;get count.low ora b ;test for done jnz movelp ;branch not done in 1ch ;get bank p!9"1:m222 "}a 2:a/ : O>1: 0C >2!\~r<2\@2!]~ ‰ 6?#‚>?2h:\=_2\:##~2y#~2z##^#V"{#^#V"}*.;^#~2y#~2z#^"{"}#)""*{zҫ\ >  (Strike any key to continue)$^#V#N#F_ #XM>2N#F#^q#Vpr+s *0x0(:>0:22 * * *{#oW+}ʀzjfi`:yʏ)=Š t : Total of $k in $ files with $k space remaining.$> > *. Oz~#*. z: DIF-SSED.DOC Reducing the Swelling of the Phone Bill with DIF and SSED November 17, 1981 Chuck Forsberg Computer Development Inc Beaverton OR Lately (if not sooner) it has become obvious that there must be a better and cheaper way to distribute software updates to changing programs than to transmit all of the new files in their totality, even though only a few lines in each have beenort db 0cbh,0bfh ;deselect rom out 1ch ;deselect bank2 ret ;exit bank 2 ; the first 2048 bytes are the system rom ; move: lxi h,0 ;start address lxi d,4000h ;where to put things lxi b,800h ;count of bytes to move movelp: mov a,m ;get byte stax d ;move it inx h ;point to next get inx d ;point to next put dcx b ;down count bytes to go mov a,c ;get count.low ora b ;test for done jnz movelp ;branch not done in 1ch ;get bank p!> CZ##*+"}:!"!""*+}{*.z_t_t*> C{##"*+"4*^#V#">.^#~))))!zo&:z/o*"*#">k*+}." 42>00x0(:>0:22 * * *{#oW+}ʀzjfi`:yʏ)=Š t : Total of $k in $ files with $k space remaining.$> > *. Oz~#*. z: changed. For some years the Unix differential file print program diff(1) (the (1) refers to the section of the Unix Programmers Manual in which it is described) has had a -e flag which provides a set of ed commands suitable for transforming the first file to the second. With these tools, only an update file need be transmitted, provided, of course, that both the sender and the receiver had copies of the same antecdent file. I have written a "new" diff called dif.    c which manages to operate in the primitive CP/M environment. The editing commands output in response to the -e option refrence sequential lines in the source files, so they (the commands) can be executed by a stream editor. (The Unix diff(1) creates difference files with non-forward-sequential commands.) To generate a difference file, the command is dif -e oldfile newfile >file.dif The >file.dif redirects the standard output to the file. A + may be susbtituted for > iflittle trouble keeping the files synchronized. (If the antecedent files are different, there's no telling what the output file will look like!) For us poor CP/M folks (verrry) patiently awaiting something like Unix to appear magically on out desktops, I propose that the revision or revision date of the antecedent file be placed in the new file adjacent to the new revision or date, preferably on the same line. This way the user may easily verify that he has the correct antecedee identical) It ought to work if you said dif -e filea fileb |ssed filea |dif fileb and it does, with version 2.0. Version 2.0 of dif.c adds a -u flag which will unsqueeze filea before comparing it to fileb. Thus you can say sq filea dif -eu filea.qqq fileb |ssed filea |dif fileb Or you can say dif -eu filea.qqq fileb |ssed -u filea.qqq |dif fileb to test dif and ssed. (Be sure dif and ssed are exactly where you say they are, or else pipes will be broken.) Restriction:. Unix is a trademark of WECO, CP/M of Digital Research. CP/M's cr/lf terminated lines and **nixs' \n terminated lines, dif was written to strip cr's from the input in order that only one cr appear on the output. As a result, lines terminated by cr/lf, lf, and lf/cr all come out the same! This would munge files where lf/cr has a special meaning (MBASIC continuation lines) or where embedded cr's are used (RTTY art) simultaneous console output is desired. The receiver then invokes: ssed oldfile newfile Which will result in newfile being created identical to the oroginal newfile. Well, not precisely identical, but identical up to and including the EOF (^Z) character. The dribble after that may change, so CRCK may say they are different. To check, compare the two files with dif. Unix folks with 14 character file names and modification times stored by the filesystem have nt. Dif Versions 1.10 and later place hash indices of the RETAINED lines of the antecedent file in the difference output. This allows ssed 1.10 or later to verify correctness of the antecedent file. the new .dif files are compatible with the old ssed, but, alas, not with Unix ed or sed. The array sizes in dif.c may have to be shrunk somewhat to run on a 48k system. For testing, give dif -e filea fileb |ssed filea >filec dif fileb filec (fileb and filec should b Since the BDS Standard I/O library and the Directed I/O package are somewhat confused about translation between CP/M's cr/lf terminated lines and **nixs' \n terminated lines, dif was written to strip cr's from the input in order that only one cr appear on the output. As a result, lines terminated by cr/lf, lf, and lf/cr all come out the same! This would munge files where lf/cr has a special meaning (MBASIC continuation lines) or where embedded cr's are used (RTTY art)   .in 8 .rm 72 .ce 99 Reducing the Swelling of the Phone Bill with DIF and SSED November 17, 1981 Chuck Forsberg Computer Development Inc Beaverton OR .ce 0 Lately (if not sooner) it has become obvious that there must be a better and cheaper way to distribute software updates to changing programs than to transmit all of the new files in their totality, even though only a few lines in each have been changed. For some years the Unix differential file print program diff(1) (the (1) refers to ence sequential lines in the source files, so they (the commands) can be executed by a stream editor. (The Unix diff(1) creates difference files with non-forward-sequential commands.) To generate a difference file, the command is dif -e oldfile newfile >file.dif The >file.dif redirects the standard output to the file. A + may be susbtituted for > if simultaneous console output is desired. The receiver then invokes: ssed oldfile newfile Which will result in newfile beCP/M folks (verrry) patiently awaiting something like Unix to appear magically on out desktops, I propose that the revision or revision date of the antecedent file be placed in the new file adjacent to the new revision or date, preferably on the same line. This way the user may easily verify that he has the correct antecedent. Dif Versions 1.10 and later place hash indices of the RETAINED lines of the antecedent file in the difference output. This allows ssed 1.10 or later to verify correctness oaring it to fileb. Thus you can say sq filea dif -eu filea.qqq fileb |ssed filea |dif fileb Or you can say dif -eu filea.qqq fileb |ssed -u filea.qqq |dif fileb to test dif and ssed. (Be sure dif and ssed are exactly where you say they are, or else pipes will be broken.) Restriction: Since the BDS Standard I/O library and the Directed I/O package are somewhat confused about translation between CP/M's cr/lf terminated lines and **nixs' \n terminated lines, dif was written to strip c Hit SPACEName Ext Bytes UN At ! File(s), occupying K of K total capacity directory entries and K bytes remain on 1 !9" ! J> # ->! . *ͪe> # < * v K  K  K !B r+s+p+qA ?  p*A *? :]$Ž l]Q !]6 !E 6!C 6 :C *C &l ~2D U¼:E 2 :D S:E 2:D F:E 2:D V:E 2:D P:E 2 :D N2E !the section of the Unix Programmers Manual in which it is described) has had a -e flag which provides a set of ed commands suitable for transforming the first file to the second. With these tools, only an update file need be transmitted, provided, of course, that both the sender and the receiver had copies of the same antecdent file. I have written a "new" diff called dif.c which manages to operate in the primitive CP/M environment. The editing commands output in response to the -e option refring created identical to the oroginal newfile. Well, not precisely identical, but identical up to and including the EOF (^Z) character. The dribble after that may change, so CRCK may say they are different. To check, compare the two files with dif. Unix folks with 14 character file names and modification times stored by the filesystem have little trouble keeping the files synchronized. (If the antecedent files are different, there's no telling what the output file will look like!) For us poor f the antecedent file. the new .dif files are compatible with the old ssed, but, alas, not with Unix ed or sed. The array sizes in dif.c may have to be shrunk somewhat to run on a 48k system. For testing, give dif -e filea fileb |ssed filea >filec dif fileb filec (fileb and filec should be identical) It ought to work if you said dif -e filea fileb |ssed filea |dif fileb and it does, with version 2.0. Version 2.0 of dif.c adds a -u flag which will unsqueeze filea before compr's from the input in order that only one cr appear on the output. As a result, lines terminated by cr/lf, lf, and lf/cr all come out the same! This would munge files where lf/cr has a special meaning (MBASIC continuation lines) or where embedded cr's are used (RTTY art). Unix is a trademark of WECO, CP/M of Digital Research. o work if you said dif -e filea fileb |ssed ft confused about translation between CP/M's cr/lf terminated lines and **nixs' \n terminated lines, dif was written to strip cC 4Ø:!4:!5(  ! I3= : [= t:\a:\=_: :] t ?]\ : ҃! 6?Î : 2   ]Q  ?\\ : DM, Q ! "= *3 ##)*= "; */ &# "! *3 #"#  !! "% >!1 . 2' \: 2 : ʩ: ƀo&"* ~ʛ*# +"# ** DMY қ** DM  *; q#p* " . ** #DM*; -e**  *; w* #" )*= *; s#r*; "; : 2 !S 6!"V * "n >!S d*S &T ) ^#V"K O!l ^#V"M :S =2S M K  a*K "G *    M "I *K  )*= ^#V"O I G  *G )*= N#F*O ? J*G #"G (*I )*= ^#V*O DM? m*I +"I JI G  *G )*= ^#V"Q *I )*= *G )*= N#Fq#p*I )*= *Q s#r*G #"G *I +"I K I  G M   !M G  :S <2S O!T *G s#r*S &l ) *M s#r*I "M ^I K  X:S <2S O!T *K s#r*S &l ) *I s#r*G "K û!" "    #* #" )*= * #" )*= N#Fq#p   * )*= * ) *= ^#VN#F? H * #" )*= ^#V";  *; ^#V" * )*= *( * " 3*1 #" " " *5 " > # R : B * +" ! +s#r( ! 6: " * ~2 * #" * +" > ʶ : 2 Ғ * +" : <2 O>ҳ ! 6* #" * ~2 p K* DMf = * *% DMf = * *% DMf = *( #"( K*# DMf = * *% DMf = : AOK :K . g S -A >>!  ~?l W >#^ : /!:' —  ʑ #‹  W ʢ #™ i`N#FogDM!>))덑o|g =¼ DM!>)) = ^#V) ^#V|g}o Disasm.doc Documentation for DISASM.COM as of 7.3.80 by HBR This software was 'picked-up' during my travels. As a result the documentation is rather short. Command Format: A>DISASM infile.hex outfile.asm Comments: infile.hex must exist. If necessary use 'UNLOAD' or such to create from infile.com file outname.asm will be output file for source generated by DISASM. If it already exists, then it will be overwritten. Be carefull ! ^#V"; *;  ͪ  *; q#pÝn* " ! p+q* )*= ^#V"; ! 6> ! i* &*; >OK : <2 E:/ *; ^#V*% DMf KK : *; Nf E*; ~ڻWK þE *; ~SK E = ! 6:! '= :/ = : = !: = : <2 * " !" >! .  * *&͵ "( * *&͵ > j*( #"( *DM*( V"( !" (   K!" }2 : <2 O:* * * "    >! = * DM** +" *( * " Ø* #" *& _{ozgO{ozgi`N#Fogo&og_{_z#W OK = Y -S {-_ ! s+p+q*  ͼ 2 <2 : ! ڗ  K ! 4Á ! 6: =! ڻ * & NK ! 4œ >3  03} Z; { ) #  The program will prompt you with questions asking if you want Z-80 instructions, comments etc. Program runs on my Imsai 8080 and my Northstar Horizon II under CP/M I can't find it now, but there is an additional program ASSM.COM which runs nicely with DISASM. I'll go look for that and UNLOAD.COM to put on this same disk. 7.3.80 HBR be output file for source generated by DISASM. If it already exists, then it will be overwritten. Be carefull !    *WANT OUTPUT PUNCHED? END BCDEHLMASPPSWEQU READ ERROR CHECKSUM ERROR ORG 0H WANT TABS? WANT Z80 INSTRUCTIONS? WANT ASCII COMMENTS? NOP LXI ,STAXINX INR DCR MVI RLC DB DAD LDAXDCX RRC RAL RAR SHLD+DAA LHLD+CMA STA +STC LDA +CMC MOV HLT ADD ADC SUB SBB ANA XRA ORA CMP RNZ POP JNZ +JMP +CNZ +PUSHADI RST RZ RET JZ +CZ +CALL+ACI RNC JNC +OUT CNC +SUI RC JC +IN CC +SBI RPO JPO +XTHLCPO +ANI RPE PCHLJPE +XCHGCPE +XRI RP JP + R ST  UV   !"#$%&'()*+,-.(/"012&3(4O5678(9":;<&=(>?@ABC(D"EFG&H(IJKLMN(WXYZ[\]^^^^^^^^________````````abcdefghabijklabcmnoabipqrabcsabitabcuabivwxyz{|}~ ~24+:3+ >!4+ҿ 2I+!8+6:4+O! ^#V:I+O! ~24+ÿ *I+&  ~24+ÿ :H+Y2:+*I+&  ~24+¶ !8+62J+2<+2K+:<+ʣ !4+6ö :<+O!  ~24+ÿ 4 J Z >N!4+ !4+6*4+& ~20+25+:0+2;+: *E+DM?!1+6!++6:5+!++W *++M*++&H+ w:P  > *++&H+ N͵:1+21+!++4 > !;+ :0+™ *I+&"C+>!C+(҉ C++s#r*C+*E+##"C+ÿ :5+=O!H+ N*5+&H+ N "C+:/ *C+DM͓ : *1+M?: !5+:7+=27+O>, !++6:7"b+!g+4” :e+r+*i+& "b+!i+:e+w*b+DM*i+f !v+p+q*u+!!r+s>u+͹!t+s*r+& ~2s+:t+t !t+6À *t+M>2t+:s+!t+ >>!x+p+q*w+!"y+*y+DM6  *y+) w+ *y+#"y+ !"y+:t+!s++N! w*y+) *w+s#ræ !~+p+q*}+!"{+L+}+N++H6>*{+DM6 /F>*{+) }+[>*{+#"{+r!"{+6*r+& :t+w*{+) ^#V!6+~/t 23+ 2=+!2+6 2>+ i 22+!"}2-+>!-+*-+& 6*-+& 6!-+4+f [ !"+!++ڨ*+DM6 *+) L+/HN++/Hқ*r+& :t+›L> *+) N#F?4f ?0> *+) N#FH> [ *+"+[ :ҷ?f ͝!+q:4+*+&' N> c:4+ :+*:+M> *+&' N> c:+!*+&' N> c[> *:+M> :J+2+O>J-> :+/<2+O+> *+M]> :1+21+!1+6 *8+&H+ ~2,+*;+M! ^#V*H+M!1+6 !1+6*8+&H+ >O!1+6 *,+M,> *8+&H+ >O:,+1f !1+6 *,+M:,+DI CP +ORI RM SPHLJM +EI CM +CPI EXX EXAFDJNZJMPRJRNZJRZ JRNCJRC RLCRRRCRRALRRARRSLARSRARSRLRBIT RES SET INP OUTPDSBBSBCD;NEG RETNIM0 STAIDADCLBCD;RETISTARSDED;IM1 LDAILDED;IM2 LDARRRD RLD SSPD;LSPD;LDI CCI INI OUTILDD CCD IND OUTDLDIRCCIRINIROTIRLDDRCCDRINDROTDRDAD@LXI !9 ͑:7+!// :5+E+ͬ#+s#rBK :7+!6+!6+6*A+"E+"?+:ҟ?:Ҿ Wf *A+DMdf *E+DM :7+29+2H+:!6+:9+H!7+6P!8+6*H+&+!++, :5+!++O!H+ :++=O!H+ w!++4 Px!4Dv!P+q:>+S *P+MZ *P+M͛ >  > !S+s+p+q!T+6:S+=!T+ږ *T+&*Q+~O> !T+4s !W+s+p+q!Y+6:W+=!Y+ *Y+&*U+~2X+@ ::+2X+:X+ :2+/H *X+M> !Y+4¤ !\+s+p+q!]+6:\+=!]+ *]+&*Z+N͛!]+4 !`+s+p+q*^+DM*`+ ͕2a+Y:a+NHR ͛- *a+M͛ ͛ ͛:a+Y!f+s+q+q+p+q>!e+Ҋ !e+6!i+6!g+6:e+!g+ *b+*d+&0!h+s>9 :h+2h+:g+!f+>b+H !i+4!g+>O!j+ :h+w*b+*d+&!5+6!7+6!.+6#6!"E+!"?+:>+/!22+:+A/>F!+/HV:+ 2+x:+0>9!+Hx7 !+6:+,,H2-+:-+!/+w:-+:ʨÛ~2.+:.+2/+!+q*+&l !+q0> *+M͵H> !+p+q*+l !+p+qL++/N++/H(L> *+DM>0> *+DMH> !1+5!+q:2+n!-+6:+=!-+k > !-+4OÉ!-+6:+!-+ډ > !-+4s!+q:=+/җ!G+6;!+6+6:+!+*+&G+ >2+ />|!+/H!+6*+&G+ 6 !+4¤:+*1+M?:+<_G2,+/f !1+6 !*,+M:,+0O> *,+M!1+6 :,+0O> ,> *8+&H+ >O!1+6 *5+&H+ N!1+6*,+M,> *5+&H+ N!1+6 *C+DM!1+6:,+/f !1+6*,+M,> *C+DM$0:`u!+q!7+:+*+&H+ ~:+<27+*?+#"?+:6+!*>:.+²͛:.+E!6>~o&~O ~"A+:/ҜL+A+|*A+"L+:.+A+ͬ+N+ Ҝ:.+A+ͬ+"N+*?++A+ ʲ!6+6>~2+:.+=2.+~2-+:/+E :+?*4+& DM͗ ?d    :5+!+ګ:++ͬ++DM*r+& :t+HҤ:^?L> vDM:+{:> á?4f ?$> -> !+>2O> [ !+4_og_ogDM!>))덑o|g =DM!>)) =ɇ {ozgO{ozgi`N#Fogo&og_{_z#Wɯ2* "###"!]~ Z !\ ;͹!4N!@ ~2!6@; ; SELF-RELOCATING 8080 DIS-ASSEMBLER ; FOR CP/M COM FILES ; ; CP/M FUNCTION CODES ; RDCON: EQU 1 WRTCON: EQU 2 WRTLST: EQU 5 CSTAT: EQU 11 OPENF: EQU 15 CLOSF: EQU 16 DSKRD: EQU 20 DSKWRT: EQU 21 CREATF: EQU 22 SETDMA: EQU 26 ; ; CP/M INTERFACE ADDRESSES ; BOOT: EQU 0 CPM: EQU 5 FCB: EQU 5CH FCBCR: EQU FCB+32 DBUFF: EQU 80H ; ; MISCELLANEOUS EQUATES ; CR: EQU 0DH LF: EQU 0AH TAB: EQU 09H BSP: EQU 08H CTRL: EQU 40H ; ORG 0100H ;BASE OF TPA ; ; FIRST, RELOCATE THE DIS-ASSNG LENGTH ORA C ;SET FLAGS JZ CHGADR ;DONE MOVING DCX H ;LOWER DESTINATION DCX D ;LOWER ORIGIN DCX B ;LOWER COUNT JMP MOVER ;CONTINUE CHGADR: PUSH H ;SAVE DESTINATION XCHG ;GET BEGINNING CALL COMPH ;COMPLEMENT IT POP D ;RECOVER DESTINATION DAD D ;COMPUTE OFFSET SHLD DISP ;SAVE IT XCHG ;SAVE COPY OF DISPLACEMENT LHLD STOP ;END OF DIS-ASSEMBLER DAD D ;DERIVE NEW ADDRESS SHLD STOP ;SAVE IT LHLD STRT ;START OF CODE DAD D ;DERIVE NEW END SHLD STRT ;SAVE IT DCX H ;MINUS DRESS OF 2 BYTE TABLE CHEK2: LDAX D ;GET TABLE ENTRY CMP M ;COMPARE TO THIS OPCODE JZ SKIP ;GOT IT DCR B ;COUNT - 1 INX D ;TABLE + 1 JNZ CHEK2 ;KEEP GOING JMP LOOP ;SKIP THIS BYTE SKIP: INX H ;SKIP TWO BYTES JMP LOOP ;AND CONTINUE ACT: PUSH H ;SAVE THIS ADDRESS LHLD SBOT ;GET END OF BLOCK ADDRESS XCHG ;PUT IT IN DE LHLD SSTRT ;GET START OF BLOCK MOV B,H ;PUT START ADDRESS MOV C,L ; IN BC POP H ;RECOVER CURRENT ADDRESS INX H ;ADD 1 MOV A,E ;SET UP A SUBTRACT SUB ME MOV A,M ;GET IT ADC D ;OFFSET IT MOV M,A ;PUT IT BACK JMP LOOP ;ON TO THE NEXT ONE COMPH: MOV A,H ;GET H CMA ;REVERSE IT MOV H,A ;PUT IT BACK MOV A,L ;GET L CMA ;REVERSE IT MOV L,A ;PUT IT BACK INX H ;PLUS 1 RET ;AND GO BACK COMPLT: LXI D,START ;ORIGINAL START ADDRESS LHLD DISP ;DISPLACEMENT DAD D ;CURRENT ADDRESS PCHL ;START DIS-ASSMEBLER TAB3: DB 001H,011H,021H,022H ;LXI B,LXI D,LXI H,SHLD DB 02AH,031H,032H,03AH ;LHLD,LXI SP,STA,LDA DB 0C2H,0C3H,0C4H,0CAH ;JN=>Û!4GN! qyC>2!G6! !6@! ù ~# p#  NO MORE DISK SPACE$ NO INPUT FILE SPECIFIED$ INPUT FILE NOT ON DISK$HEXASMEMBLER ; LXI SP,STACK ;SET UP A TEMPORARY STACK LXI H,RELMSG ;POINT TO RELOCATION MESSAGE CALL PMSG ;WRITE IT CALL RDHEX ;READ THE NEW ADDRESS PUSH H ;SAVE IT ON STACK LHLD SBOT ;GET END OF RELOC BLOCK XCHG ;PUT IT IN DE LHLD SSTRT ;GET BEGINNING OF RELOC BLOCK CALL COMPH ;COMPLEMENT HL DAD D ;COMPUTE LENGTH MOV B,H ;MOVE IT TO B MOV C,L ; AND C POP H ;RECOVER DESTINATION DAD B ;ADD LENGTH MOVER: LDAX D ;GET A BYTE FROM SOURCE MOV M,A ;RELOCATE IT MOV A,B ;TEST REMAINIONE TO ENTER LOOP LOOP: INX H ;NEXT BYTE XCHG ;ADDRESS TO DE LHLD STOP ;GET END ADDRESS XCHG ;SWITCH BACK MOV A,E ;GET LOW BYTE SUB L ;COMPARE MOV A,D ;GET HIGH BYTE SBB H ;FINISH COMPARE JC COMPLT ;EXIT ADDRESS MVI B,1AH ;GET 3 BYTE OPCODE COUNT LXI D,TAB3 ;ADDRESS OF 3 BYTE OPCODE TABLE CHEK3: LDAX D ;GET TABLE ENTRY CMP M ;COMPARE TO THIS OPCODE JZ ACT ;GOT ONE DCR B ;COUNT - 1 INX D ;TABLE + 1 JNZ CHEK3 ;TRY AGAIN MVI B,12H ;LENGTH OF 2 BYTE TABLE LXI D,TAB2 ;AD ;ADJUST THE LOW BYTE INX H ;POINT TO HIGH BYTE MOV A,D ;SET UP SUBTRACT SBB M ;ADJUST HIGH BYTE JC LOOP ;PAST END OF PROGRAM,DON'T ADJUST DCX H ;BACK TO LOW BYTE MOV A,M ;GET IT SUB C ;OFFSET IT INX H ;POINT TO NEXT MOV A,M ;GET HIGH BYTE SBB B ;OFFSET IT JC LOOP ;BEFORE START OF PROGRAM, DON'T ADJUST DCX H ;BACK TO LOW BYTE XCHG ;SWITCH WITH DE LHLD DISP ;GET OFFSET XCHG ;RESTORE HL MOV A,M ;GET LOW BYTE ADD E ;ADD OFFSET MOV M,A ;REPLACE IT INX H ;POINT TO HIGH BYTZ,JMP,CNZ,JZ DB 0CCH,0CDH,0D2H,0D4H ;CZ,CALL,JNC,CNC DB 0DAH,0DCH,0E2H,0E4H ;JC,CC,JPO,CPO DB 0EAH,0ECH,0F2H,0F4H ;JPE,CPE,JP,CP DB 0FAH,0FCH ;JM,CM TAB2: DB 006H,00EH,016H,01EH ;MVI B,MVI C,MVI D,MVI E DB 026H,02EH,036H,03EH ;MVI H,MVI L,MVI M,MVI A DB 0C6H,0CEH,0D3H,0D6H ;ADI,ACI,OUT,SUI DB 0DBH,0DEH,0E6H,0EEH ;IN,SBI,ANI,XRI DB 0F6H,0FEH ;ORI,CPI ; ; STORAGE AREAS FOR RELOCATOR ; SSTRT: DW START ;START OF SOURCE SBOT: DW LAST ;BOTTOM OF SOURCE STRT: DW START ;START OF FIX    AREA STOP: DW DATA ;END OF FIX AREA DISP: DW 0 ;DISPLACEMENT ; DS 32 ;STACK SPACE ; STACK: EQU $ ; ; BEGIN DIS-ASSEMBLER PROGRAM ; ; SET MEMORY POINTERS ; START: LHLD CPM+1 DCX H SPHL MOV A,L SUI 64 MOV L,A MOV A,H SBI 0 MOV H,A SHLD ENDMEM ; ; OPEN THE TARGET FILE ; OBJRTY: CALL CLFCB LXI H,OFMSG CALL PMSG LXI H,FCB+1 CALL RDFCB LXI D,FCB MVI C,OPENF CALL CPM CPI 255 JNZ OBJOK OBJERR: LXI H,FERMSG CALL PMSG JMP OBJRTY OBJOK: LXI H,FLDLXI H,STAMSG CALL PMSG CALL RDHEX SHLD NXTADD SHLD STADD LXI H,ENDMSG CALL PMSG CALL RDHEX SHLD ENDAD SHLD ENDAD2 LXI H,OFSTMS CALL PMSG CALL RDHEX SHLD OFFSET LXI H,PRMSG CALL PMSG CALL CONIN MVI E,0 CPI 'Y' JZ PRTOPT DCR E PRTOPT: MOV A,E STA PRSWCH LXI H,SOMSG CALL PMSG CALL CONIN MVI E,0 CPI 'Y' JZ SRCOPT INR E SRCOPT: MOV A,E STA SROSW JNZ NOSRC ; ; DISK OUTPUT IS DESIRED ; OPNOUT: CALL CLFCB LXI H,SFMSG CALL PMSG LXI H,FCB+1 XCHG LXI H,SYMTB ; ; FILL THE SYMBOL TABLE WITH FF'S ; CLRTAB: XRA A DCR A MOV M,A INX H CALL TSTHD JC CLRTAB CALL ADDISP LXI H,OPRLEN MVI M,0 CALL CHKDTA JC NXTLIN ; ; BUILD THE SYMBOL TABLE ; BY SETTING UP ALL ADDRESSES ; REFERRED TO ; BLDTBL: LHLD NXTWRK XCHG CALL GETOPC LDA OPRLEN CPI 2 JNZ NXTLIN LHLD NXTWRK INX H MOV E,M INX H MOV D,M XCHG SHLD TMPSYM CALL SYMTST JNC NXTLIN LXI H,-1 CALL SYMTST JC TBLFUL LHLD TMPSYM XCHG TADD CALL ADDRO LXI H,LOPCOD LXI D,ORGLIT CALL STRMOV XCHG LHLD NXTADD XCHG LXI H,LOPRND CALL DETOLN CALL FINLIN LXI H,LINE CALL PRTLIN ; ; DECODE THE OBJECT AREA TO INSTRUCTIONS ; DECODE: CALL ADDRO LXI H,OPRLEN MVI M,0 CALL MOVHEX CALL CHKDTA JC ISDATA LHLD NXTWRK XCHG CALL GETOPC PUSH B CALL MOVHEX LDA OPRLEN CPI 3 JZ ISDATA POP H MOV A,M CPI ' ' JZ NOREG CPI 'S' JNZ NOTSP INX H MVI M,'P' JMP NOTPSW NOTSP: CPI 'P' JNZ NOTPSNOTSYM LXI H,LSYMBL CALL PUTSYM MVI M,':' LXI H,SEMICL CALL WRTLIN NOTSYM: LHLD NXTWRK INX H LDA OPRLEN CPI 2 JNZ NOT3BT MOV E,M INX H MOV D,M XCHG CALL SYMTST JNC PTCMNT XCHG LHLD ENDLIN CALL DETOLN JMP NOT2BT ; ; ADD A COMMENT TO SHOW THE ABSOLUTE ADDRESS ; REFERRED TO IN THE INSTRUCTION ; PTCMNT: LHLD ENDLIN CALL PUTSYM LXI H,LCOMNT MVI M,';' INX H MVI M,'(' PUSH H LHLD NXTWRK INX H MOV E,M INX H MOV D,M POP H INX H CALL DEMEM MSG CALL PMSG CALL RDHEX SHLD DMA ; ; READ TARGET FILE ; NEXSEC: XCHG LXI H,START MOV A,L SUI 128 MOV L,A MOV A,H SBI 0 MOV H,A CALL TSTHD JC OOMEM MVI C,SETDMA CALL CPM LXI D,FCB MVI C,DSKRD CALL CPM ORA A JNZ OBJDON LHLD DMA LXI D,128 DAD D SHLD DMA JMP NEXSEC OOMEM: LXI H,OMMSG JMP OBJERR+3 ; ; ESTABLISH OPERATING PARAMETERS ; OBJDON: LHLD DMA DCX H XCHG LXI H,ULMSG1 CALL DEMEM LXI H,ULMSG CALL PMSG LXI H,DISMSG CALL PMSG  CALL RDFCB LXI D,FCB MVI C,CREATF CALL CPM CPI 255 JNZ OPENOK LXI H,FERMSG CALL PMSG JMP OPNOUT OPENOK: LXI H,DBUFF SHLD NXTOUT XCHG MVI C,SETDMA CALL CPM NOSRC: MVI B,6 PUSH B LXI D,DATAS ; ; ESTABLISH KNOWN DATA AREAS ; SETKDA: POP B DCR B PUSH B JZ NODATA LXI H,KDAMSG CALL PMSG CALL CONIN CPI 'N' JZ NODATA LXI H,STAMSG CALL RSTHEX LXI H,ENDMSG CALL RSTHEX JMP SETKDA NODATA: POP B CALL CLINE LXI H,WRKMSG CALL PMSG LHLD ENDMEM  MOV M,E INX H MOV M,D SHLD ESYMT NXTLIN: CALL NXTOPR XCHG LHLD ENDAD CALL TSTHD JNC BLDTBL LHLD ESYMT SHLD ENDMEM LXI D,0 LXI H,SYMTB+2 ; ; ASSIGN NUMBERS TO THE SYMBOL ADDRESSES ; NBRSYM: MOV M,E INX H MOV M,D INX H INX H INX H PUSH D XCHG LHLD ENDMEM INX H INX H CALL TSTHD JC DOORG XCHG POP D MOV A,E ADI 1 DAA MOV E,A MOV A,D ACI 0 DAA MOV D,A JMP NBRSYM ; ; WRITE AN ORG STATEMENT TO START THE PROGRAM ; DOORG: CALL SEW INX H MVI M,'S' INX H MVI M,'W' NOTPSW: LDA OPRLEN DCR A JM NOREG INX H MVI M,',' INX H NOREG: SHLD ENDLIN JMP PUTLAB ISDATA: LXI H,OPRLEN MVI M,0 LXI H,LOPCOD LXI D,DBLIT MVI C,4 PUTOPR: LDAX D MOV M,A INX D INX H DCR C JNZ PUTOPR LHLD NXTWRK XCHG LXI H,LOPRND MVI M,'0' INX H LDAX D CALL VALCH1 JNC PUTOP2 DCX H CALL PUTLIT JMP PUTOP3 PUTOP2: CALL HEXMEM MVI M,'H' PUTOP3: SHLD ENDLIN PUTLAB: LHLD NXTADD CALL SYMTST JC  MVI M,')' SHLD ENDLIN JMP NOT2BT NOT3BT: CPI 1 JNZ NOT2BT LHLD ENDLIN MVI M,'0' INX H XCHG LHLD NXTWRK INX H MOV A,M CALL VALCH1 JNC LITRAL XCHG DCX H CALL PUTLIT JMP NOTLIT LITRAL: XCHG CALL HEXMEM MVI M,'H' NOTLIT: SHLD ENDLIN NOT2BT: CALL FINLIN LXI H,LINE CALL PRTLIN CALL NXTOPR LHLD NXTADD XCHG LHLD ENDAD CALL TSTHD JNC DECODE JMP ENDDIS ADDRO: CALL CLINE LHLD NXTADD XCHG LXI H,LINADR JMP DEMEM DETOLN: XRA A CALL H   EXMEM CALL DEMEM MVI M,'H' SHLD ENDLIN RET STRMOV: LDAX D MOV B,A STRMV2: INX D LDAX D MOV M,A INX H DCR B RZ JMP STRMV2 PUTLIT: MVI M,'''' INX H MOV M,A INX H MVI M,'''' RET ; ; DETERMINE IF THE CURRENT CHARACTER IS A ; VALID ASCII CHARACTER. THIS ROUTINE HAS A ; LIMIT CHANGED IN THE SECOND PASS. FIRST PASS ; DISK OUTPUT USES TABS INSTEAD OF BLANK ; SPACES FOR DELIMITERS. THE SECOND ; PASS (PRINT ASCII MAP) CHANGES THE LIMIT TO ; PRINT SPACES. ; VALCH1:W LXI D,DSKSWC MOV A,M STAX D INR M CALL CLINE LXI D,SYMTB TBLOUT: MVI C,5 LDAX D INR A JNZ NOTFIN INX D LDAX D INR A RZ DCX D NOTFIN: INX D INX D INX D LXI H,LINADR MORSYM: MVI M,'L' INX H CALL LOADAD DCX D CALL LOADAD INX H INX H INX D INX D INX D INX D INX D INX D INX D DCR C JNZ MORSYM LXI H,LINE CALL PRTLIN DCX D DCX D DCX D JMP TBLOUT LOADAD: LDAX D CALL HEXMEM DCX D LDAX D CALL HEXMEM INX H RET GETOMBLED. ; ; BITS 7 & 6 = LENGTH OF OPERAND ; (3 = INVALID INSTRUCTION) ; BITS 5 - 0 = OPERAND MINUS 20H ; ; NOTE THAT BITS 5-0 ARE AUTOMATICALLY ; INSERTED INTO THE OUTPUT LINE, THEN ; OVERLAYED IF THE DIS-ASSEMBLER DETERMINES ; THAT THE NEXT BYTE IS USED TO DETERMINE ; WHAT THIS OPERATION IS TO DO. ; ; SINCE BITS 5-0 HAVE A 20H ADDED TO THEM, ; SETTING THEM TO ZERO RESULTS IN A BLANK ; SPACE BEING WRITTEN TO THE OUTPUT LINE. ; ; XINFO: LDAX D RLC RLC MVI H,003H ANA H STAAD D XCHG RET FIXOPC: ADD D ADD D ADD D PUSH PSW ANI 038H LXI H,OPTAB2 LXI D,0 RRC RRC RRC MOV E,A DAD D DAD D DAD D XCHG LXI B,LOPCOD MVI H,3 CALL TOLINE XRA A STA OPRLEN LXI B,LOPRND POP PSW ANI 007H JMP REGIN ; ; THE SYMBOL TABLE IS FULL ; TBLFUL: LXI H,TFMSG CALL PMSG ; ; END OF OPERATION DIS-ASSEMBLY PASS ; ENDDIS: CALL CLINE LXI H,LOPCOD MVI M,'E' INX H MVI M,'N' INX H MVI M,'D' CALL MCRLF LXI H,LINE CALL PRTLIN H MVI M,' ' MOV A,E ANI 3FH JNZ NXASCI CALL MCRLF LXI H,LINE CALL PRTLIN LHLD ENDAD CALL TSTHD JC DOXREF JMP PRASCI GETFIL: MVI M,'.' JMP GOODCH ; ; CROSS-REFERENCE ALL SYMBOLS ; DOXREF: CALL CLINE LXI H,SEMICL CALL WRTLIN LXI H,PUTIT XRA A MOV M,A LXI H,ALTER2 MOV M,A LXI H,0 SHLD SYMPTR XRFNXT: CALL ADDSYM CALL SETADD XRFSYM: LHLD NXTWRK XCHG CALL GETOPC LDA OPRLEN CPI 2 JNZ NOXREF CALL ADDSRC LHLD NXTWRK INX H MOV A,M CMP E  CPI 07FH RNC CPI '!' ; CHGLIM: EQU $-1 ; CMC RET MOVHEX: LHLD NXTWRK XCHG LXI H,LHEXDA LDA OPRLEN CPI 3 JNZ SKIP1 XRA A SKIP1: INR A MOV C,A LHXDAT: LDAX D CALL HEXMEM INX D DCR C JNZ LHXDAT RET CLINE: MVI B,71 LXI H,LINADR MVI A,' ' CLIN2: MOV M,A INX H DCR B JNZ CLIN2 RET PUTSYM: MVI M,'L' INX H INX D INX D LDAX D MOV B,A INX D LDAX D MOV D,A MOV E,B JMP DEMEM ; ; PRINT THE SYMBOL TABLE ; PRTTBL: LXI H,SROSPC: LDAX D CPI 076H JNZ RANGE LXI H,HLTLIT JMP PUTOPC RANGE: MVI D,040H SUB D JC REGOPT SUB D JC ISMOV SUB D JC FIXOPC REGOPT: ADD D LXI H,OPTABL MVI D,0 MOV E,A DAD D DAD D DAD D DAD D DAD D PUTOPC: LXI B,LOPCOD XCHG MVI H,4 CALL TOLINE INX B CALL XINFO RET TOLINE: LDAX D PUTIT: STAX B INX D DCR H RZ INX B JMP TOLINE ; ; DECODE THE DATA BYTE FOLLOWING THE ; OPCODE LITERAL FOR INFORMATION ABOUT ; THE INSTRUCTION BEING DIS-ASSE OPRLEN LDAX D MVI H,3FH ANA H ADI 020H LXI B,LOPRND ALTER2: STAX B RET ISMOV: ADD D STA ISMOV2+1 LXI B,LOPCOD LXI D,MOVLIT MVI H,3 CALL TOLINE INX B ISMOV2: MVI A,0 MVI H,007H RRC RRC RRC LXI B,LOPRND CALL MASKRG MVI A,',' MVI H,001H INX B CALL PUTIT MVI H,007H LDA ISMOV2+1 INX B CALL MASKRG XRA A STA OPRLEN RET MASKRG: ANA H REGIN: CALL GETREG MVI H,1 CALL TOLINE RET GETREG: LXI H,REGTAB MOV E,A SUB A MOV D,A D LXI H,SEMICL CALL PRTLIN CALL PRTTBL LXI H,SEMICL CALL PRTLIN MVI A,' ' STA CHGLIM CALL SETADD LHLD OFFSET XCHG LHLD ENDAD DAD D SHLD ENDAD LHLD NXTWRK XCHG ; ; PRINT ASCII MAP OF PROGRAM AREA ; PRASCI: LXI H,LINADR PUSH D PUSH H LXI H,OFFSET MOV A,E SUB M MOV E,A INX H MOV A,D SBB M MOV D,A POP H CALL DEMEM POP D MVI M,' ' NXASCI: INX H LDAX D CALL VALCH1 JNC GETFIL MOV M,A GOODCH: INX D MOV A,E ANI 00FH JNZ NXASCI INX JNZ NOXREF INX H MOV A,M CMP D JNZ NOXREF LHLD NXTADD XCHG LHLD ENDLIN CALL DEMEM INX H SHLD ENDLIN LXI D,LLAST CALL TSTHD JC NOXREF CALL FINLIN LXI H,LINE CALL PRTLIN LXI H,SYMLOC SHLD ENDLIN NOXREF: CALL NXTOPR XCHG LHLD ENDAD CALL TSTHD JNC XRFSYM CALL FINLIN LXI H,LINE CALL PRTLIN LHLD SYMPTR INX H SHLD SYMPTR LXI D,SYMTB DAD H DAD H DAD D XCHG LHLD ENDMEM CALL TSTHD JC ENDING JMP XRFNXT ; ; JOB FINISHED. CLOSE DISK ; F   ILE IF NECESSARY. ; ENDING: LDA DSKSWC ADD A JNZ BOOT JMP DCLOSE ADDSYM: CALL LBLSCH LXI H,LINADR MVI M,'L' INX H CALL DEMEM INX H SHLD ENDLIN RET CONSCH: LHLD SYMPTR DAD H DAD H DAD D MOV E,M INX H MOV D,M RET ADDSRC: LXI D,SYMTB JMP CONSCH LBLSCH: LXI D,SYMTB+2 JMP CONSCH HANGUP: MVI C,'?' CALL CONOUT JMP START RDHEX: LXI H,0 NXTHEX: CALL CONIN CPI CR RZ CPI 'C'-CTRL JZ START DAD H DAD H DAD H DAD H JC HANGUP CALL TOP D POP B CPI 0 RZ HLT WAITER: PUSH B PUSH D PUSH H MVI C,CSTAT CALL CPM ANI 1 JNZ WAITR3 WAITR2: POP H POP D POP B RET WAITR3: MVI C,RDCON CALL CPM CPI 'C'-CTRL JZ BOOT CPI 'P'-CTRL JNZ WAITR2 LDA PRSWCH CMA STA PRSWCH JMP WAITR2 CONIN: PUSH B PUSH D PUSH H MVI C,RDCON USECPM: CALL CPM POP H POP D POP B RET CONOUT: PUSH B PUSH D PUSH H MOV E,C MVI C,WRTCON JMP USECPM LSTOUT: CALL WAITER PUSH B PUSH D PUSH H MOV FINLIN: LHLD ENDLIN MCRLF: INX H MVI M,CR INX H MVI M,LF RET TSTHD: MOV A,L SUB E MOV A,H SBB D RET ADDISP: LHLD OFFSET XCHG LHLD NXTADD DAD D SHLD NXTWRK RET TOASCI: ANI 00FH ADI 090H DAA ACI 40H DAA RET DEMEM: MOV A,D CALL HEXMEM MOV A,E JMP HEXMEM NXTOPR: LHLD NXTADD XCHG LHLD NXTWRK LDA OPRLEN INR A NXTOP1: DCR A JM NXTOP2 INX H INX D JMP NXTOP1 NXTOP2: SHLD NXTWRK XCHG SHLD NXTADD RET CRLF: MVI C,CR  LDA SROSW ADD A JNZ NODISK MOV A,B CPI 57 JNC NODISK MOV A,C CPI ' ' JNZ OVLFLO LDA THOLD CPI TAB JZ NODISK MVI C,TAB OVLFLO: MOV A,C STA THOLD CALL DWRITE NODISK: LDA CHAR DCR B CPI LF JNZ WRTLN2 POP B RET CHKDTA: MVI B,5 LXI H,DATAS CHKDT2: CALL LOADDE PUSH H LHLD NXTADD CALL TSTHD POP H JNC CHKDT4 CHKDT3: CMC RET CHKDT4: CALL LOADDE PUSH H LHLD NXTADD XCHG CALL TSTHD POP H JNC CHKDT3 DCR B JNZ CHKDT2 CMC RET ; ; DATA AREAS ; DATA: EQU $ ; NXTOUT: DW 0 NXTADD: DW 0 STADD: DW 0 ENDAD2: DW 0 ENDAD: DW 0 OFFSET: DW 0 NXTWRK: DW 0 OPRLEN: DB 0 TMPSYM: DW 0 SROSW: DB 0 THOLD: DB 0 DATAS: DB 0FFH,0FFH,0FFH,0FFH DB 0FFH,0FFH,0FFH,0FFH DB 0FFH,0FFH,0FFH,0FFH DB 0FFH,0FFH,0FFH,0FFH DB 0FFH,0FFH,0FFH,0FFH CHAR: DB 0 ENDLIN: DW 0 DBLIT: DB 'DB ',0C9H SEMICL: DB 03H,';',CR,LF ORGLIT: DB 03H,'ORG' MOVLIT: DB 'MOV ' HLTLIT: DB 'HLT ',000H OPTABL: DB 'BINY JC HANGUP ORA L MOV L,A JMP NXTHEX TOBINY: SUI '0' RC ADI 0E9H RC ADI 006H JP TOBIN2 ADI 007H RC TOBIN2: ADI 10 ORA A RET DCLOSE: LHLD NXTOUT MOV A,L CPI DBUFF JZ DONE MVI C,1AH CALL DWRITE JMP DCLOSE DONE: LXI D,FCB MVI C,CLOSF CALL CPM JMP BOOT DWRITE: PUSH H LHLD NXTOUT MOV M,C INX H SHLD NXTOUT MOV A,H POP H CPI 0 RZ PUSH B PUSH D PUSH H LXI H,DBUFF SHLD NXTOUT LXI D,FCB MVI C,DSKWRT CALL CPM POP H PO E,C MVI C,WRTCON CALL CPM POP H POP D POP B LDA PRSWCH ORA A RNZ PUSH B PUSH D PUSH H MOV E,C MVI C,WRTLST JMP USECPM HEXOUT: PUSH PSW RRC RRC RRC RRC CALL TOASCI MOV C,A CALL LSTOUT POP PSW CALL TOASCI MOV C,A JMP LSTOUT HEXMEM: PUSH PSW RRC RRC RRC RRC CALL TOASCI MOV M,A INX H POP PSW CALL TOASCI MOV M,A INX H RET PMSG: MOV B,M INX H CALL CRLF PMSG1: MOV C,M CALL CONOUT DCR B RZ INX H JMP PMSG1  CALL CONOUT MVI C,LF JMP CONOUT SYMTST: LXI D,SYMTB SYMTS2: LDAX D CMP L JNZ SYMTS3 INX D LDAX D CMP H JZ SYMFND JMP SYMTS3+1 SYMTS3: INX D INX D INX D INX D PUSH H LHLD ENDMEM CALL TSTHD POP H JNC SYMTS2 RET SYMFND: STC CMC DCX D RET SETADD: LHLD STADD SHLD NXTADD LHLD ENDAD2 SHLD ENDAD JMP ADDISP PRTLIN: CALL WRTLIN JMP CLINE WRTLIN: PUSH B MOV B,M WRTLN2: INX H MOV C,M MOV A,M STA CHAR PUSH B CALL LSTOUT POP B LOADDE: MOV E,M INX H MOV D,M INX H RET RSTHEX: CALL PMSG CALL RDHEX XCHG MOV M,E INX H MOV M,D INX H XCHG RET CLFCB: XRA A STA FCB LXI H,FCB+1 MVI B,11 CLFCB2: MVI M,' ' INX H DCR B JNZ CLFCB2 MVI B,21 CLFCB3: MVI M,0 INX H DCR B JNZ CLFCB3 RET RDFCB: CALL CONIN CPI CR RZ CPI '.' JZ RDFCB1 CPI 7FH JNZ RDFCB2 DCX H MVI C,BSP CALL CONOUT JMP RDFCB RDFCB2: MOV M,A INX H JMP RDFCB RDFCB1: LXI H,FCB+9 JMP RDFCBNOP ',000H DB 'LXI ',0A2H DB 'STAX',022H DB 'INX ',022H DB 'INR ',022H DB 'DCR ',022H DB 'MVI ',062H DB 'RLC ',000H DB 'ILLG',0C0H DB 'DAD ',022H DB 'LDAX',022H DB 'DCX ',022H DB 'INR ',023H DB 'DCR ',023H DB 'MVI ',063H DB 'RRC ',000H DB 'ILLG',0C0H DB 'LXI ',0A4H DB 'STAX',024H DB 'INX ',024H DB 'INR ',024H DB 'DCR ',024H DB 'MVI ',064H DB 'RAL ',000H DB 'ILLG',0C0H DB 'DAD ',024H DB 'LDAX',024H DB 'DCX ',024H DB 'INR ',025H DB 'DCR ',025H DB 'MV   I ',065H DB 'RAR ',000H DB 'ILLG',0C0H DB 'LXI ',0A8H DB 'SHLD',080H DB 'INX ',028H DB 'INR ',028H DB 'DCR ',028H DB 'MVI ',068H DB 'DAA ',000H DB 'ILLG',0C0H DB 'DAD ',028H DB 'LHLD',080H DB 'DCX ',028H DB 'INR ',02CH DB 'DCR ',02CH DB 'MVI ',06CH DB 'CMA ',000H DB 'ILLG',0C0H DB 'LXI ',0B3H DB 'STA ',080H DB 'INX ',033H DB 'INR ',02DH DB 'DCR ',02DH DB 'MVI ',06DH DB 'STC ',000H DB 'ILLG',0C0H DB 'DAD ',033H DB 'LDA ',080H DB 'DCX ',033H DB 'INR 080H DB 'IN ',040H DB 'CC ',080H DB 'ILLG',0C0H DB 'SBI ',040H DB 'RST ',013H DB 'RPO ',000H DB 'POP ',028H DB 'JPO ',080H DB 'XTHL',000H DB 'CPO ',080H DB 'PUSH',028H DB 'ANI ',040H DB 'RST ',014H DB 'RPE ',000H DB 'PCHL',000H DB 'JPE ',080H DB 'XCHG',000H DB 'CPE ',080H DB 'ILLG',0C0H DB 'XRI ',040H DB 'RST ',015H DB 'RP ',000H DB 'POP ',030H DB 'JP ',080H DB 'DI ',000H DB 'CP ',080H DB 'PUSH',030H DB 'ORI ',040H DB 'RST ',016H DB 'RM ',00SG-TFMSG)-1 DB 'SYMBOL TABLE FULL' ; SYMTB: EQU $ ; FLDMSG: DB (STAMSG-FLDMSG)-1 DB 'ADDRESS TO LOAD FILE AT IN HEX = ' STAMSG: DB (ENDMSG-STAMSG)-1 DB 'STARTING ADDRESS IN HEX = ' ENDMSG: DB (OFSTMS-ENDMSG)-1 DB 'ENDING ADDRESS IN HEX = ' OFSTMS: DB (PRMSG-OFSTMS)-1 DB 'OFFSET IN HEX = ' PRMSG: DB (SOMSG-PRMSG)-1 DB 'PRINT DIS-ASSEMBLED CODE (Y/N) ? ' SOMSG: DB (KDAMSG-SOMSG)-1 DB 'SOURCE FILE OUTPUT TO DISK (Y/N) ? ' KDAMSG: DB (WRKMSG-KDAMSG)-1 DB 'KNOWN DATA AREA ; LAST EQU $ ; END  DB (FERMSG-SFMSG)-1 DB 'NAME OF SOURCE FILE TO CREATE ? ' FERMSG: DB (OMMSG-FERMSG)-1 DB 'FILE ERROR' OMMSG: DB (DISMSG-OMMSG)-1 DB 'OBJECT FILE TOO LARGE' DISMSG: DB (RELMSG-DISMSG)-1 DB 'DIS-ASSEMBLY PARAMETERS ----' RELMSG: DB (ULMSG-RELMSG)-1 DB 'ADDRESS TO LOAD DIS-ASSEMBLER IN HEX = ' ULMSG: DB (LAST-ULMSG)-1 DB 'UPPER LIMIT = ' ULMSG1: DS 4 ',021H DB 'DCR ',021H DB 'MVI ',061H DB 'CMC ',000H DB 'RNZ ',000H DB 'POP ',022H DB 'JNZ ',080H DB 'JMP ',080H DB 'CNZ ',080H DB 'PUSH',022H DB 'ADI ',040H DB 'RST ',010H DB 'RZ ',000H DB 'RET ',000H DB 'JZ ',080H DB 'ILLG',0C0H DB 'CZ ',080H DB 'CALL',080H DB 'ACI ',040H DB 'RST ',011H DB 'RNC ',000H DB 'POP ',024H DB 'JNC ',080H DB 'OUT ',040H DB 'CNC ',080H DB 'PUSH',024H DB 'SUI ',040H DB 'RST ',012H DB 'RC ',000H DB 'ILLG',0C0H DB 'JC ',0H DB 'SPHL',000H DB 'JM ',080H DB 'EI ',000H DB 'CM ',080H DB 'ILLG',0C0H DB 'CPI ',040H DB 'RST ',017H REGTAB: DB 'BCDEHLMA' OPTAB2: DB 'ADD' DB 'ADC' DB 'SUB' DB 'SBB' DB 'ANA' DB 'XRA' DB 'ORA' DB 'CMP' SYMPTR: DW 0 DSKSWC: DB 0 PRSWCH: DB 0 DMA: DW 0 ESYMT: DW 0 ENDMEM: DW 0 LINE: DB 71 LINADR: DS 5 LHEXDA: DS 1 SYMLOC: DS 9 LSYMBL: DS 8 LOPCOD: DS 8 LOPRND: DS 10 LCOMNT: DS 20 LLAST: DS 10 DB CR,LF TFMSG: DB (FLDM(Y/N) ? ' WRKMSG: DB (OFMSG-WRKMSG)-1 DB 'WORKING',CR,LF OFMSG: DB (SFMSG-OFMSG)-1 DB 'NAME OF OBJECT FILE ? ' SFMSG: DB (FERMSG-SFMSG)-1 DB 'NAME OF SOURCE FILE TO CREATE ? ' FERMSG: DB (OMMSG-FERMSG)-1 DB 'FILE ERROR' OMMSG: DB (DISMSG-OMMSG)-1 DB 'OBJECT FILE TOO LARGE' DISMSG: DB (RELMSG-DISMSG)-1 DB 'DIS-ASSEMBLY PARAMETERS ----' RELMSG: DB (ULMSG-RELMSG)-1 DB 'ADDRESS TO LOAD DIS-ASSEMBLER IN HEX = ' ULMSG: DB (LAST-ULMSG)-1 DB 'UPPER LIMIT = ' ULMSG1: DS 4    1!**͢DM wx)+ ͢"*"*"+#*{zڪuUqdC#C**DM#{#zC+~#~C+*~w#~wC|/g}/o#*!"*12:&.6>A ͡ :6:6͡ :71!*+}@o|g")  !W!] \=!! "% !}րo|g y\*% "% I!7*% +!# !!! "C "E ! "I "G ! "K ! ͙Y{2$ !͙Y{2R  !n!] \6H"i !+ ͅ + *C *I çv*C !, # # 6H"i Gw#B6'#w#6'!?*M !1 :O j w#}6L#GWX# !R # ~4v <­<!, 6L### ³!+ ͅ á#v!| @2x! _C &%&2O &? K ɂ2CC x &>&K e>,&&:Ce2O ɤo&! _Wɂ8! _C &2O K f!u v!C 6E#6N#6D !+ ͅ !p ͅ ͒!p ͅ > 2Wv *K *I "I *M !, !K {_#zW# 6 #Si #6 #6 }|*K *C "M Ɛ'@'z{*C *M :O <=? #6 "M "C  ͥ å b r c *) T 7?*E "C *G "I  ͋ vF#N~2h ͮ:R ¼ x9Ҽ y µ :S ʼ  y2S I:h   !T *C ? *C  ?^#V#s#r#ɯ2\!] 6 # 6# ͙ .; 6 +ͥ w# !e DB ; ORGMOV HLT NOP LXI STAX"INX "INR "DCR "MVI bRLC ILLGDAD "LDAX"DCX "INR #DCR #MVI cRRC ILLGLXI STAX$INX $INR $DCR $MVI dRAL ILLGDABCDEHLMAADDADCSUBSBBANAXRAORACMPGSH$SUI @RST RC ILLGJC IN @CC ILLGSBI @RST RPO POP (JPO XTH SYMBOL TABLE FULL!ADDRESS TO LOAD FILE AT IN HEX = STARTING ADDRESS IN HEX = ENDING ADDRESS IN HEX = OFFSET IN HEX = !PRINT DIS-ASSEMBLED CODE (Y/N) ? #SOURCE FILE OUTPUT TO DISK (Y/N) ? KNOWN DATA AREA (Y/N) ? WORKING NAME OF OBJECT FILE ? NAME OF SOURCE FILE TO CREATE ? FILE ERROROBJECT FILE TOO LARGEDIS-ASSEMBLY PARAMETERS ----'ADDRESS TO LOAD DIS-ASSEMBLER IN HEX = UPPER LIMI Following instructions were furnished for use with DISSAM.COM Dissassembler commands etc. INstruction do we want instructins to proceed each interogation? Object file input (is this coming from a disk?) OFFSET? offset will generally be 0; is amount required for program to wrap from true location to 0100 (or wherever you loaded it; 100 is usual in cp/m stuff) reader is always NO format-hex-ascii will not come up; only for readers offset same as above; entered twice s!!"A T G!4͙NG! ! $v!M*) ! =w# X !O 6 ڣ*M :O £*M #^#V"P Q ң!Q ڡ*P s#r"' + *I p*' ") ! s#r###*) ## {'_z'Wüv &!C t @*C !K 3!+ ͅ &!O 6Z S*M Z:O S~ MS7#6PBPB#6S#6W:O =M#6,#"i È!O 6!C k w# `*M !K 60#SҀ+KÅ6H"i *C Q ڟ!; ̈́6:!p ͋ *M #:O ^#VQ ҿ*i 3 *i ̈́!U 6;#6(*M #^#V## 6)"i  *i 60#*M #~S+K(w{#6 {? !+ ͅ *I -6.v!p ͋ !w!0w!"! v *M :O ’*M #~’#~’*C *i # #"i i ڒ!+ ͅ !2 "i + *I K!+ ͅ *! #"!  ))*) E:# -!, 6L## #"i *! ))^#V  ?ͥ!͙ ))))o0) *A }>I-\*A q#"A |!"A \v €|:$ /2$ |YÞoY:$ YÞ Oͮ Oî w# w#F#G Nͥ#*D $LDAX$DCX $INR %DCR %MVI eRAR ILLGLXI SHLDINX (INR (DCR (MVI hDAA ILLGDAD (LHLDDCX (INR ,DCR ,MVI lCMA ILLGLXI STA INX 3INR -DCR -MVI mSTC ILLGDAD 3LDA DCX 3INR !DCR !MVI aCMC RNZ POP "JNZ JMP CNZ PUSH"ADI @RST RZ RET JZ ILLGCZ CALLACI @RST RNC POP $JNC OUT @CNC PUSH$SUI @RST RC ILLGJC IN @CC ILLGSBI @RST RPO POP (JPO XTHLCPO PUSH(ANI @RST RPE PCHLJPE XCHGCPE ILLGXRI @RST RP POP 0JP DI CP PUSH0ORI @RST RM SPHLJM EI CM ILLGCPI @RST T = LE FULL!ADDRESS TO LOAD FILE AT IN HEX = STARTING ADDRESS IN HEX = ENDING ADDRESS IN HEX = OFFSET IN HEX = !PRINT DIS-ASSEMBLED CODE (Y/N) ? #SOURCE FILE OUTPUT TO DISK (Y/N) ? KNOWN DATA AREA (Y/N) ? WORKING NAME OF OBJECT FILE ? NAME OF SOURCE FILE TO CREATE ? FILE ERROROBJECT FILE TOO LARGEDIS-ASSEMBLY PARAMETERS ----'ADDRESS TO LOAD DIS-ASSEMBLER IN HEX = UPPER LIMItart and end of where you have it (0100 and endadd from load or SID; inspect end of the thing to see, and put that in. source file output usually yes known data areas if you say yes, give start, end, hex for first; will prompt again; continue until you say no. after you get an output, you inspect; if you find junk or ascii stuff, you declare those to be data areas. The first task is to define data areas. The ASCII listing is useful in doing this. You can get this with the ascii    study in SID, through dumps, etc. A series of meaningless move register to register instructions are probably ASCII since most printable ascii is 40H to 7fH Using the cross-reference listing, locate areas that are referenced by three or more instructions. They will usually be+ i/o routines or vectors small utility routines frequently used data 2. Once you have defined the data areas and isolated the i/o and utility routines, edit the generated source by inserting comments, and as*K͞+@O:'+FÎr ͖ 8{ Ăw#w#w^#V#*~#fo^#*~#fo^#V#*n^#*n^#V# ~#fo^#& ~#fo!+!#!+!#!+!+}|z{|}|z7||7zZZ)|/g}/o#|͉k|/g}/o#ɯ2qZZk:q|/g}/o#|/g}/o#:q<2qqDM!xxGyO҃)v|͔`i|)Öxڷz/W{/_ѯzW{_=yOxGæ2qZZ͉M|}ȯ|g}o)|/g}/o!a{   `OE!y6$ -7rBo&))T])))!y:=b#:=#:$=2#v+:<"(">6͋5:&=͋5#*&=|"M1Ϳ5#>6͋5:&=͋5>#͋5>6͋5:'=͋5#*&="<(#>͋5:&=͋5>s͋5>@2=#R1Ϳ5#(,#:==2=)(@#>s͋5#͘(Y#X1:>͋5:&=͋5c1Ϳ5#f1Ϳ52=#(—#>͋5:&=͋5>{͋5c1Ϳ5#(#:$=µ#>}͋5c1Ú#:$=;-͘(#>&͋5͋5f2Ú#:$=$v+è":= >& - !bP40 !aP40 *"jP!cP40 !`P40 X öÅ! ~#foX ! ~#foҮ !6 !Ͱ!T !Ͱ! !Ͱ! !Ͱ! !Ͱ! !Ͱ!ͳ!)H! ~#fo~#fo"?PͶ#| ! ~#fo~#fo! !Ͱ!ͳ )H"5P! ~#fo++|\ !/L! ~#fo##~#fo"APͶ#|R ! ~#fo##~#fo! !Ͱ!ͳY /L"7Ph *"lP! "AP*cP}y *"jPͼ!"=P";P"dP{2iP{2hPd"CP"pP"TP"GP"EP"\P"IP*`P} `i6`in& `in&)GP~#fo`in&)CP~#fo`in&! !Ͱ`itandard Inputbottom[%d]=%x top=%x %s$a %u . Files are different No differences encountered '%s' Unlinked y )*5Pv Ì )*7P͉ ß l!9DM*}T *}T+"}T*T͜ `is#r! `i~#fo"T*T#| !0u"}T*T͜ "}T| !*}T++"}T*T!96%*î(]6)!9DM$'*5P*vo*?P!}!-!0*5P*! ! s#r! ~#fo*5P3s! ^#Vr+sn}ƒ! *?P!!-*5P*! s#r! ~#fo|! ~#fo *?P!!-semble. Almost without exception the UNDEFINEDs will denote one of two things: Dynamic instructin modifications reference to an undiscovered data area After the second or third disassembly it's all up to you... tructions. They will usually be+ i/o routines or vectors small utility routines frequently used data 2. Once you have defined the data areas and isolated the i/o and utility routines, edit the generated source by inserting comments, and as#z/W{/_!9~#fo! ! ! ! ! ! !9~#A"s!`*"!"!Y">2>2>22!"!"!@"!" ʞ!F#x±~#±!b2r~# "2r+}|~#G:rx"2r+w# +6#!6#2w2x*s!>r<o&F=-` r'~h6!+`W?_!~7z?` :>ª@w#G.¶ww#?*>?w#> w#.7:77$,v+2#:$=>$$>͋5v+>͋5>@2$=2#*="<1Ϳ5:=2="<|s$}d$[2Ϳ5z$g$[3Ϳ5>G>)͋5$#͞*D)͏,Ͷ,v++4ʱ$̓)c"s Æ v(Ù î(]6(&!û+)ú)`6&!9DM!"9P! ~#fo! s#r! ~#fo! s#r! ^#Vr+szP! ^#Vr+s~#fon}>=! ~#fo~#fon}+M! ~#fo~#fo#"9P! ~#fo! ͡{2`P{2bP{2cP{2aP{2_P*"jP*"lP! ^#Vr+sz6 ! ^#Vr+s~#fo! s#rn}-6 ! ^#Vr+sn}3 ! ~#fon&ͪ>d> >e> >u> >v4ü !"fP!"MP"KP!OP!Ϳ*CP"KP!WP!Ϳ*EP"MP*KP###~#foͣ*MP###~#fo|g}o| *MP*KP|ʌ  *dP*KP~#fo"dP*bP}ʵ *KP!$ *KP"KP*MP"MP9 *aP} *dP!* *_P} !3 !Ͱ* !H !Ͱ*9P|* *9P*9P!d !Ͱ!9dif.c 2.00 (dif 2.0) 11-17-81Usage: dif [-dev] filea {fileb,outfile] -d display lines that match -e generate Editor script -u Unsqueeze filea -v Verbose Can't open %sCan't open %sS!0!"yP!"{P`iw#w`i~#fo! ~#fot`i~#fo))yP*5P*s#r`i~#fo))yP##*5P*s#r`i^#Vr+s!9%s Not Squeezed (%s -> %s) %s has invalid decode tree size ,"1+î(n++!9DM! n&);P! s#r! n&)jP~#fo"nP! n&)GP~#fo"rP*rP"rP! n})*MP,*KP"tP*tP"vP! ~#fo~#fo"pP*pP|}! ~#fo"pP*pP! ~#fo "pP*`P}ʼ*pP*vP*tP*rP! ~#fo~#fo! n&!!!!9! n&hPn}E!I!*pP! ~#fo~#fo! ~#fo~#fo!    ~#fo! ~#fo~#fo! n&!e!!9!! ~#fo*pP*rPҋ! n&)CP~#fo"pP*`P}ʀ*pP!!*tP|‹ç*pP*tPڿ*pP*vPڿ*`P}ʼ!!*pP`is#r`i~#fo##! ns`i~#fo"pP>2xP!xP5n}*pP#"pP+*nP!!9~#fos{++  *`P}W! ~#fo~#fo! n&!!! n&hP6`i~#fo6#6`i~#fo`i~#fos#r`i~#fo###6#6!`i~#fo! ~#fo`i~#fos#r! ~#fo^#Vr+s*pP+"pP! ~#fo~#fo!!*pP6*pp=%x î( ,.û]6!9DM>2_P*`P}U*MP###~#fo*KP###~#fo!L! ! s! sT`is#r`i^#Vr+s*KP"Ts#r`i^#Vr+s*MP"Ts#r! 6#6! 6#6! 6! n}W! n}! n}W! n}k! ~#fo! s#r! ^#Vr+szk`i~#fo*T s#rz! 6k`i^#Vr+s~#fo"T! ^#Vr+s!L! 6*T###~#foh! 6k! n}! ~#fo! s#r! ^#Vr+sz`i~#fo*T s#rz·! 6`i^#Vr+s~#fo"T! ^#Vr+s!! 6*T###~#fo! 6! ~#fo)T~#fo! ~#fo!! !9! ^#Vr+sÌ!! 9Difference at %d:%d Dodiff Quantity=%d k't=%d w'a=%d w'b=%d HTBL %3d:addr=%x f=%d h=%4x l=%3d nxt=%x Can't find match at a:line %d b:line %d HTBL %d:addr=%x f=%d h=%4x l=%3d %.30s û!9DM! ~#fo~#fo|<! ~#fo~#fo! ~#fo! ~#fo##n& ! ~#fo~#for)!"T*yT#"yT*5Po"{T#|Ÿ!!"yT*T))yP*{T|g}o)~#fo"T*T))yP*{T"{T|g}o)~#fo"T*T|y*T##fo|!! ~#fo~#fo~#fo|$)! ~#fo~#fo~#fo~#fo! ~#fo~#fo~#fo~#fo_)! ~#fo~#fo! ~#fo~#fo;|ʎ)! ~#fo~#fo~#fo! ~#fo~#fo~#fo;|)! ~#fo~#fo###~#fo! s#r! ~#fo~#fo###~#fo! s#r! ~#fo~#fo`is#r! ~#fo~#fo! s#r! ^#Vr+sL! ^#Vr+s ! ~#fo^!Ê!*`P}ʱ! ~#fo! ~#fo!!!!`i~#fo!! ~#fo*aP}ʎ ! ~#fo*KP###~#fo! s#r! ~#fo*MP! s#r###~#fo! sAP*MP###~#fo!"*MP! s#r! ~#fo###~#fo! ~#fop!! ~#fo!("! ~#fo! s#r#!`i~#fo"KP! ~#fo"MP!Ê!!9Found match at %d:%d Fudge=%d skipa=%d skipb=%d %d%d%da %u c %u . d %u -------- Line %4d of '%s' ---- ---%s++++++++ Line %4d of '%s' ++++ +%s7*N#"*|)yoO"|g}o"*+"|0"*x"(î(]6+)`6ó-!9DM*##s*#s*s! ~#fo͐ ~#fo)*s#r! 6#6`i6#6͐͐ ~#foҭ%w}"í%! ~#fo͐)~#fon}<#P`i~#fo! s#rzK`i~#fo!! ~#fo`i~#fo;s#rU`i~#fow#w`i~#fo###! ~#fo~#fos#r! ~#fo`i~#fos#r*`P&*pP! ~#fo`i~#fo~#fo`i~#fo! ~#fo~#fo! n&!!!9!`i~#fo`i~#fo! s#r! ~#fow#w*pP#"pPE!9File %d line %d q=%x qq=%x qqq=%x p=%x Getline called after E-O-F %d %3d fp=%x hash=%04x next=%x p=%x Wrapped: p=%x Buffer Filled EOF on file %d at line %d **EOF** Line %d is too long %d %3d gp=%x hash=%04x len=%3d Å*`P}A! n&! n&! n&! ~#fo!a! *`P& ! w#w! ~#fo! ~#fo ! ~#fo)T~#fo~#fo! ~#fo)T~#fo###~#fo! ~#fo)T~#fo~#fo! ~#fo)T~#fo##n&! ~#fo)T~#fo! ~#fo!! !9! ^#Vr+sW*!! ~#fo!T! ~#fo|;C! ~#fo! ~#fos#rñ*MP###~#fo*KP###~#fo!! *`P};! w#w! ~#fo! ~#fo;! ~#fo)T~#fo! ~#fo)T~#fo###~#fo! ~#fo)T~#fo~#fo! ~#fo)T~#fo##n&"T*T!*T!"}T!c"yT!9DM! ~#fo~#fo~#fo! ~#fo~#fo~#foc!! ~#fo~#fo~#fo! ~#fo~#fo~#foҐ!! ~#fo~#fo##n! ~#fo~#fo##nѯgW+)î(n+ú)Ï'Á-!9DM! s#r! s#r! ~#fo)T! s#rT! s#r! ~#fo! ~#foG! ~#fo~#fo##n}:8! ~#fo##! s#r! ~#fo! ~#fo8! ~#fo~#fo##n}{)! ~#fo~#fo~#fo! ~#fo~#fo~#foʦ)! ~#fo~#fo###~#fo! ~#fo! ~#fo~#fo###~#fo! ~#fo)! ~#fo~#fo~#r*`P}0! ~#fo! ~#fo*fP!!!! ~#fo|*fP*KP###~#fo!!! ~#fo+|ʯ!,! ~#fo‰!$ï*fP*KP###~#fo! ~#fo+!!*fP! ~#fo"fP! ~#fo|~ ! ~#fo|*KP###~#fo *dP*MP###~#fo+!! *dP!!! ~#fo###~#fo! ~#fob ! ~#fo! ~#fo! s#r !!*fP! ~#fo"fPË *dP!!p!*?P*KP###~#fo!!*KP! s#r! ~#fo###~#fo! ~#fo ! ~#fo!"! ~#fo! s#rò *|ʾ#+7$>K$Ö%! ~#fo͐)~#fo#n}0#f$* ! ~#fo͐)~#fo#f"#|€#! ~#fo͐)~#fo#!%!i"l"*6!%! ~#fo͐)~#foo"|»#*n&|g}os$*##4! ~#fo͐)~#fo#*###s#r! ~#fo͐)~#fo#n}4$! ~#fo͐)!%s#r! ~#fo͐)*s#rK$*#n&|g}os! ~#fo͐)~#fo#n}v$!%!i"l"! ~#fo͐)~#fo#r"*! ~#fo͐)~#fo#u"#|$! ~#fo͐)~#fo#!%!i"l"*#4w}m%͐! s#r͐    ~#foG%! ~#fo͐)! ~#fo͐#)~#fos#r! ^#Vr+s$͐ ^#Vr+s`i^#Vr+s*^#Vr+sÓ%͐ ͐s#r! ~#fo͐ ~#fo)w#wá%! ^#Vr+s`i^#Vr+s"!9Can't open %s <8~# x«8 ><8~+ x8|}8):7:,*8:*9   }|2q 29(9:qw#9! {w7*!9& 6C#6O#6Ms9*|‰9!\&Û9!\&*|›9!!l&!~#fo9> +9#~¸9##ì9a{ !p9!*w#9:**9*!ѷ! , FNxg>GoyM:$"J87*|DM**8ڷ8><8~# x«8 ><8~+ x8|}8):7:,*8:*9l Software Tools System Address Locator Version 1.0 lThe Address of the system BIOS is :Rl00l The Address of the system BDOS is :Rl00l The Address of the system CCP is :Rl00 l Total TPA space with CCP overlay is :Rl00l Total TPA space with CCP intact is : Rl00 [ g0{7{~#y{m_DU.COM ver 7.7 7/12/81*." |2!0"*"g"q""""""4"m"v":v"Ë*."" DISK UTILITY ver 7.7 Universal Version Type ? for help Type X to exit h!~G###W> !#2͠>2l2m12n>2!"hQ:~, ~ ;# ]2+? -t =t<>#? AzCL DzFʫ Gʙ HzLqM'NʳPQR Sʙ Tʙ UVWe XYʒZ%/2 ?2 +++ Out of memory +++  Disk Information: Tracks: *#͞ Sec/trk: *͞ Grpsize: : x<Q/ c[mmOÌw ~ ;]#AOy2:ʰ|^#V#"!~#fo**x|2 ``*"t!"v*#DMBK:=l*t   *voͼ ! xl::-{EBK{ >-w> 2+*#}b|ʇ+Qʒz{{U { ͚E { ͚S*ph |~> ¬>(w~͇ #>.w:w~͇ ~> >)w ++FREE++ :n2nS>:w ~# ~#k &w*#"{!"!~{~_#~{:[W#͵w*|s>*2"\ *{+"{|;*:G::ʵ*!W LAST ADDR=* "+|͇ }͇ 2 ++YANK MEMORY FULL : ; # `i}͇ :AT ~͇ } } {E #}% Q:Hʌ ~ d ~f >.w{u #}W SQ{ S{ ~;ʥ © Tʼ S GP n*8`>2 nz*o2 **t**v+:G}2r:G "p*2~:}2r-? o&"ph -*8"p2r} o2 bk:)=‚ :ro*ڗ ** #`>2~\  \< 2} ++FILE NOT FOUND =2}o&))))): o 2 ++Can't read - not positioned Position by: Track then Sector, or Group ͮ >>w:ʆ x͇ y͐  ڙ 0w ڧ  |Ğ {0w> w>*wQ~ m w#~ #-z{ƀ_ɯ2 ++BAD DISPLACEMENT (NOT 0-7F) ~#m~] ;,->#0:`AG0))))o6#~] ;,-#0:0bk)))o|gq :!#mOF . ڬw#wì+>*wìww> w!#ɯF+yed++ Operands in brackets [...] are optional Numeric values: 'n' are decimal, 'x' hex +[n] step in [n] sectors; -[n] step out [n] sectors # print disk parameters for curr drive. =xxx search for ASCII xxx from curr sector. Caution: upper/lower case matters. Use for hex: To find "IN 0" use: =<0> or "(tab)H,0(CR)(LF)" use: =<9>H,0 < save current sector into mem. buff. > restore saved sector ? give help A[ff,tt] ASCII) R Read current sector Snn Sector nn Tnn Track nn Unn Set User nn for Find command (CP/M-2 only) V[nn] View [nn] ASCII sectors W Write current sector X Exit program Y Yank current sector into sequential memory Z[nn] Sleep [nn tenths] /[nn] Repeat [nn (decimal) times] (Type any char. to continue) Cancel a function with C or Ctl-C. Suspend output with S or Ctl-S. Separate commands with ";". Example: g0 +;d;z#20;/ would step in, dump, !W>2s :s.!W 2 ++NO "<" SAVE COMMAND ISSUED ~#Wɯ2Qt!#6 G~{:*h}ͼ 2*v*to !~#"h:ʁ-{!Qs~c~8 ? ? ? ?~k Bw,sͼ *v*to ++EOF++ S :2 ++Can't dump, no sector read. 2 Use G command following F, or R or S following T ~;  BK >D2 ~.5 6 ;6 ]# ~ ;#.#> 6 ~ U ;U -zͼ zU *v*to ~ ʊ ;ʊ -z*v+|¯ *t|¨ *"t*ï +"t*"vzŠ ^ *v#* *t#* "t!"v **t G=*pDM{ >:w:r͇ >,w T=*t͞ , S=*v͞ , PS=*x͞ S~]# #-i #BKn ,H A~ ;  ڒ ~Ғ Ø k Û w"ͳ#yʯ *y ~ ; #~ ; , "j-{͇ y *j ~ ;  ~wììʧ*  $6 S!#~ ʬw#8>^w>Uwà> w> w`_O > w:z€ ҟ ʟ ´:y ´>2z :z<2z:o*8"tBK*"v*t`i:.+.* :$g:.&i"xDMɯ2 ++not within tracks 0-*͞ ++ `>2ʬ2 ++READ failed, sector may be invalid++ :2 ++CANNOT WRITE UNLESS READ ISSUED è2 ++WRITE fail dump (Type any char. to continue) C Change: CHaddr,byte,byte... (hex) or CAaddr,data... (Ascii) Allowed for imbedded hex. or CHfrom-thru,byte e.g. ch0-7f,e5 or CAfrom-thru,byte D[ff,tt] Dump (hex+ASCII) Fn.t Find file Gnn CP/M Allocation Group nn H[ff,tt] hex dump L Log in drive Lx Log in drive x M[nn] Map [from group nn] (Type any char. to continue) N New disk P Toggle printer switch Q Quiet mode (no msgssleep 2 sec, and repeat until control-c typed. All "nn" usage except "/", "T", and "S" are HEX. Use #nn for decimal. See DU.DOC for complete examples. yʿ#x}/o|/g#ɷ|g}o }o|gBKx! T]x :WL*.:^#"^#"~#2~#2^#"^#"^"!r~:w*} ""w   Invoking DU2 and DU2 Installation DU2 Command Summary Commands for Logging Disks and Examining Disk Parameters Commands for Positioning and Reading Data Commands for Searching for Data Commands for Saving and Restoring Data Commands for Viewing data Commands for Altering Data Commands for Manipulating Macros and the @ Command Miscellanea Examples of command use Interpreting DU2 Directory Display :Invoking DU2 and DU2 Installation DU2 is invoked by a command line of the following form: t, in almost all cases, no changes to the source file should be necessary to get DU2 up and running. This is because DU2 uses the disk parameter block of CP/M to determine the char- acteristics of the disk environment. The only parameters that should need to be changed will be the clock speed flag and the number of lines on the CON: Device. GENINS can be used to perform this installation. DU2 is intended for use on a ZCPR2 system. As such, it will only run with a Z8ctor -n Back up to Last Sec ! Halt and Wait for User /nn Repeat Command Line n Exec Macro (0<=n<=9) :n Define Macro n :Pn Print Macro n :PA Print All Macros :P@ Print Prev Command An-n ASCII Dump Hn-n Hex Dump Dn-n ASCII and Hex Dump CAn vals or CAn1-n2 val Change ASCII Values CHn vals or CHn1-n2 val Change Hex Values Ffile Find File Uu Set User u fo Exit to CP/M; opt Warm Boot ^C Exit to CP/M A command line may consist of only one command or a series of commands separated by commas. In the latter form, the commands are executed sequentially. The only exceptions to this rule are the :ntext command (which stores the command line away as a macro) and the *nn command (which repeats the command line). :Commands for Logging and Viewing Disk Parameters The following commands are discussed in this sectioay" for info on how to interpret the information presented. Example (actual DU2 session): DU2 B1? fz80.mac 40 015A3830 20202020 204D4143 0000000E *.Z80 MAC....* 50 9A000000 00000000 00000000 00000000 *................* Group = 0000:00, Track = 122, Sector = 1, Physical Sector = 1 DU2 B1? ftest.txt ++ File Not Found ++ Group = 0000:00, Track = 122, Sector = 1, Physical Sector = 1 L[d] The simple "L" command re-logs in the current dis DU2 where is any valid DU2 command sequence. If the first two characters of are '/?', the built-in documentation is displayed and the user is returned to CP/M, as per the TOOLSET Convention. Examples: DU2 /? -- Display Built-in Documentation DU2 lb,g0,d -- Execute commands to Log in Drive B, goto Group 0, and display the first Block of Group 0 DU2 is designed to be installed with a minimum of trouble. In fac0 microprocessor and on a CP/M 2.2 (or higher) system. DU2 will NOT run on CP/M 1.4. :DU2 Command Summary @ Exec Prev Command =data Search for data < Save Current Block in Temp > Get Saved Block B Get Block from Queue G Get Current Group Gn Get Group N # Print Disk Stats ? Print Help Info +n Advance to Next Ser F Tn Position to Track n (dec) Sn Position to Sec n Gn Position to Group n (hex) G Show position Ld Log in Disk N New Disk M Map Disk Mn Show file in Group n P Toggle Printer Q Print Queue Statistics QZ Zero (Empty) Queue QSfile Save Queue as File R Read Current Block W Write Current Block Vn View n blocks Zn Sleep n Seconds Xn of the HELP file: F -- Find File L -- Log in Disk N -- New Disk (Reset Disk System) M -- Map Disk Directory U -- Select User Number # -- Print Disk and Queue Statistics Ffilename.typ Print directory for file "filename.typ". This command presents the directory entry for the first extent of the indicated file. See the section on "Interpreting the DU2 Directory Displk. You may pull out a disk, put in a new, and "L" just to log it in. The form "Ld", where d is a valid drive letter (like "LB"), is used to log in a specific disk and permit you to work on that particular disk from this time foreword. Example (actual DU2 session): DU2 B1? l DU2 B1? la DU2 A1? lb N This tells DU2 that you just put in a new disk. For those BIOS implementations that need to be told specifically (R   eset) that a disk change has been made, use this command every time you change a disk while DU2 is running. Example: DU2 B1? n Note: There was a significant delay before the prompt returned. A complete disk system reset took place. M[n] Dumps a map of the group allocations for files. Mn shows which file is allocated to group "n". Example (actual DU2 session, edited): DU2 B1? m 0010-0010 07 STD .MSG 00 : 0= 1, Physical Sector = 1 The entries are divided up as follows: 0010-0010 07 STD .MSG 00 : 0011-0011 07 TALK .SUM 00 ^ ^ ^ ^ | | Filename Extent | User Number Group Range Uu Logs user 'u' for next F (Find File) command. Example (actual DU2 session): DU2 B1? u7 DU2 B7? u1 # Prints the disk parameters: . Current Disk Drive : 3E00 Hex Address of Tail of Queue: 3E00 Hex (Continued on Next Screen) +=============================+ | -- Disk Information -- | +-----------------------------+ Disk Drive: B Tracks: 244 Sectors/Track: 336 Group Size: 32 Blocks/Group Total Groups: 1280 Directory Entries: 512 System Tracks: 122 =============================== :Commands for Positioning and Reading Data The following commands are discusserack = 122, Sector = 1, Physical Sector = 1 DU2 B1? g4 Group = 0004:00, Track = 122, Sector = 129, Physical Sector = 129 DU2 B1? g Group = 0004:00, Track = 122, Sector = 129, Physical Sector = 129 DU2 B1? g0 Group = 0000:00, Track = 122, Sector = 1, Physical Sector = 1 Tnn and Snn "Tnn" does a seek to track nn but does not read a block. "Snn" positions to sector nn on the current track and reads the block there. Example (actual DU2 session). Examples: DU2 B1? r DU2 B1? w +[nn] and =[nn] "+" advances 1 sector (if below track 2, this advances to next numerical sector and if 2 or more, advances based on the system's sector skewing algorithm, i.e. so + will get the next logical sector of the file). "-" backups up 1 sector in the same sense. Note + and - may take an amount: for example, +15 steps in 15 sectors. Note also that "-" issued at the first logical secto011-0011 07 TALK .SUM 00 0012-0012 07 Z2CON .WSH 00 : 0013-0013 00 LDIR .C 00 0014-0014 00 COMMAND .LBR 01 : 0015-0015 00 LDIR .C 00 < Detail Left Out > 004B-004B 08 MASTER .CAT 03 : 004C-0050 00 COMMAND .LBR 05 0051-0051 00 COMMAND .LBR 07 : 0052-0052 00 UNERA15 .COM 00 0053-0053 08 MENU .CPR 00 : 0054-0057 00 COMMAND .LBR 07 Type Any Character to Continue or ^C to Abort - DU2 B1? m54 0054-0057 00 COMMAND .LBR 07 : Group = 0000:00, Track = 122, Sector  . Number of Tracks on Disk . Size of Group in Blocks . Number of Sectors Per Track . Number of Groups on Disk . Number of Directory Entries . Number of System Tracks Prints the queue statistics: . Size of Queue . Space Available Example (actual DU2 session): DU2 B1? # +=============================+ | -- Queue Information -- | +-----------------------------+ 0 Blocks in Queue 249 Blocks Left in Queue Address of Head of Queued in this section of the HELP file: G -- Position to Group S -- Position to Sector T -- Position to Track R -- Read Block W -- Write Block + -- Advance to Next Logical Sector - -- Backup to Last Logical Sector G[nn] Position to group nn and read block. If the form is simply "G", show your current position. Example (actual DU2 session): DU2 B1? g0 Group = 0000:00, T: DU2 B1? t124 Group = 0015:00, Track = 124, Sector = 1, Physical Sector = 1 DU2 B1? s24 Group = 0015:17, Track = 124, Sector = 24, Physical Sector = 24 R and W R reads the block currently positioned to into memory. Note R (Read) is implicit in the G, +, and - commands, but NOT in the S and T commands. W writes back the current block (NOTE: may not be used after an F command, as CP/M was used to find the file in the directory)r of the disk will wrap back to the last and "+" issued at last sector will wrap forward to the first. Examples (actual DU2 session): DU2 B1? g0 Group = 0000:00, Track = 122, Sector = 1, Physical Sector = 1 DU2 B1? d 00 07535444 20202020 204D5347 00000002 *.STD MSG....* 10 10000000 00000000 00000000 00000000 *................* 20 004C4449 52202020 20432020 00000038 *.LDIR C ...8* 30 13001500 00000000 00000000 00000000 *................* 40 0843504D 55472   020 20434154 01000046 *.CPMUG CAT...F* 50 1C001E00 38003D00 41004300 45000000 *....8.=.A.C.E...* 60 00434F4D 4D414E44 204C4252 01000080 *.COMMAND LBR....* 70 14001600 17001800 19001A00 1B001D00 *................* DU2 B1? +d Group = 0000:01, Track = 122, Sector = 2, Physical Sector = 2 00 0754414C 4B202020 2053554D 00000049 *.TALK SUM...I* 10 11002300 24000000 00000000 00000000 *..#.$...........* 20 00554E45 52413135 2041534D 00000060 *.UNERA15 ASM...`* 30 3E003F00 400005550 20C3CF4D 0000001E *.STARTUP COM....* 30 27000000 00000000 00000000 00000000 *'...............* 40 00434F4D 4D414E44 204C4252 03000080 *.COMMAND LBR....* 50 1F002000 30003100 32003300 34003500 *.. .0.1.2.3.4.5.* 60 00434F4D 4D414E44 204C4252 05000080 *.COMMAND LBR....* 70 36003700 39004C00 4D004E00 4F005000 *6.7.9.L.M.N.O.P.* DU2 B1? +2 Group = 0000:04, Track = 122, Sector = 5, Physical Sector = 5 DU2 B1? d 00 084D4153 54455220 20434154 01000080 *.MASTER CAT....*  00 0754414C 4B202020 2053554D 00000049 *.TALK SUM...I* 10 11002300 24000000 00000000 00000000 *..#.$...........* 20 00554E45 52413135 2041534D 00000060 *.UNERA15 ASM...`* 30 3E003F00 40000000 00000000 00000000 *>.?.@...........* 40 075A3249 4E532020 20575348 0000002A *.Z2INS WSH...** 50 21002500 00000000 00000000 00000000 *!.%.............* 60 075A3243 4F4E2020 20575348 0000003F *.Z2CON WSH...?* 70 12002200 00000000 00000000 00000000 *..".............* :Commands for Sed by a ^C. Example: DU2 B1? g0 Group = 0000:00, Track = 122, Sector = 1, Physical Sector = 1 DU2 B1? =DU2 = at 24 Group = 0000:0E, Track = 122, Sector = 15, Physical Sector = 15 DU2 B1? d 00 07533130 30202020 20545854 0000000C *.S100 TXT....* 10 0C010000 00000000 00000000 00000000 *................* 20 07445532 20202020 2042414B 00000068 *.DU2 BAK...h* 30 2A006100 6D007800 00000000 00000000 **.a.m.x.........* 40 015A3830 20202020 204D4143 0000000E *.Z80 MAC 20575320 06000077 *.Z2CON WS ...w* 30 45014601 47014801 00000000 00000000 *E.F.G.H.........* 40 E5444953 4B4F5554 20434F4E 00000020 *eDISKOUT CON... * 50 97000000 00000000 00000000 00000000 *................* 60 07445532 20202020 20484C50 01000006 *.DU2 HLP....* 70 98009900 9B009C00 9D000000 00000000 *................* DU2 B1? +=DU2,d Group = 0000:11, Track = 122, Sector = 18, Physical Sector = 18 = at 24 Group = 0000:11, Track = 122, Sector = 18, Physical Sector = 18 000 00000000 00000000 *>.?.@...........* 40 075A3249 4E532020 20575348 0000002A *.Z2INS WSH...** 50 21002500 00000000 00000000 00000000 *!.%.............* 60 075A3243 4F4E2020 20575348 0000003F *.Z2CON WSH...?* 70 12002200 00000000 00000000 00000000 *..".............* DU2 B1? +d Group = 0000:02, Track = 122, Sector = 3, Physical Sector = 3 00 07445532 20202020 2042414B 00000057 *.DU2 BAK...W* 10 26002800 29000000 00000000 00000000 *&.(.)...........* 20 04535441 525410 2D002F00 3A003B00 3C004200 44004600 *-./.:.;.<.B.D.F.* 20 00464958 54455820 2041534D 0100001E *.FIXTEX ASM....* 30 65006600 69006B00 6C000000 00000000 *e.f.i.k.l.......* 40 00554E45 52413135 20434F4D 00000007 *.UNERA15 COM....* 50 52000000 00000000 00000000 00000000 *R...............* 60 084D454E 55202020 20C35052 00000008 *.MENU CPR....* 70 53000000 00000000 00000000 00000000 *S...............* DU2 B1? -3d Group = 0000:01, Track = 122, Sector = 2, Physical Sector = 2 earching for Data =string This command performs a search for the indicated ASCII text, starting at current sector. hex may be imbedded, or used alone: To find "IN 0FEH": =. Bit 7 is ignored unless is used. Note that, due to the parsing scheme of DU2, forms such as "+=string", which positions to the next sector and then starts the search, are allowed. Forms like "+2=string" are equally permitted. The search may be abort....* 50 9A000000 00000000 00000000 00000000 *................* 60 E5444953 4B4F5554 20434F4E 00000020 *eDISKOUT CON... * 70 60000000 00000000 00000000 00000000 *`...............* DU2 B1? +=DU2 Group = 0000:0F, Track = 122, Sector = 16, Physical Sector = 16 = at 64 Group = 0000:10, Track = 122, Sector = 17, Physical Sector = 17 DU2 B1? d 00 075A3243 4F4E2020 20575320 05000080 *.Z2CON WS ....* 10 3D013E01 3F014001 41014201 43014401 *=.>.?.@.A.B.C.D.* 20 075A3243 4F4E2020 00 E547454E 494E5320 204D4143 01000080 *eGENINS MAC....* 10 D700EF00 F000F400 F500F600 F700F800 *W.o.p.t.u.v.w.x.* 20 E5445532 20202020 2041534D 01000080 *eDU2 ASM....* 30 EC00ED00 EE00FA00 07010B01 0E011301 *l.m.n.z.........* 40 04445532 20202020 20C3CF4D 0000004E *.DU2 COM...N* 50 F100F200 F3000000 00000000 00000000 *q.r.s...........* 60 E547454E 494E5320 204D4143 02000039 *eGENINS MAC...9* 70 F9000F01 00000000 00000000 00000000 *y...............* :Commands for    Saving and Restoring Data The following commands are discussed in this section of the HELP file: < -- Save Current Block > -- Restore Saved Block B -- Load Current Block from Head of Queue G -- Copy Group from Head of Queue and Write Q -- Print Queue Statistics QZ -- Zero (Clear) Queue QS -- Save Queue as a disk. ">B" extracts the block at the head of the DU2 Queue and places it into the working buffer area. G[nn] "G" copies the group at the head of the DU2 Queue onto disk. If nn is specified (as in ",d 00 07535444 20202020 204D5347 00000002 *.STD MSG....* 10 10000000 00000000 00000000 00000000 *................* 20 004C4449 52202020 20432020 00000038 *.LDIR C ...8* 30 13001500 00000000 00000000 00000000 *................* 40 0843504D 55472020 20434154 01000046 *.CPMUG CAT...F* 50 1C001E00 38003D00 41004300 45000000 *....8.=.A.C.E...* 60 00434F4D 41 64 Blocks in Queue Group = 0001:00, Track = 122, Sector = 33, Physical Sector = 33 DU2 B1? q ** Queue Status Summary ** 64 Blocks in Queue 185 Blocks Left in Queue Address of Head of Queue: 3E00 Hex Address of Tail of Queue: 5E00 Hex DU2 B1? qsdir.sys Queue Saved in File DU2 B1? qz ** Queue Status Summary ** 0 Blocks in Queue 249 Blocks Left in Queue Address of Head of Queue: 3E00 Hex Address of Tail of Queue: 3E00 Hex DU2 B1? g0 Group = 0000:00, Track = 122, Sector = 1, PFile < and > "<" saves current block in an internal save buffer. ">" copies the internal save buffer into the current block area (but does NOT write it out to disk). B "Gnn"), then the indicated group is read from or written to. If nn is not given, then the group you are currently positioned to is affected. Q, QZ, and QSfile Q reports the status of the DU2 Queue, namely how many blocks are stored in it and how much space remains. QZ zeroes (clears) the DU2 Queue. "QSfilename.typ" saves the DU2 Queue on disk in the current user area as the indicated file. Examples (actual DU2 session): D LBR....* 70 14001600 17001800 19001A00 1B001D00 *................* DU2 B1? < DU2 B1? ch0-7f e5 DU2 B1? d 00 E5E5E5E5 E5E5E5E5 E5E5E5E5 E5E5E5E5 *eeeeeeeeeeeeeeee* 10 E5E5E5E5 E5E5E5E5 E5E5E5E5 E5E5E5E5 *eeeeeeeeeeeeeeee* 20 E5E5E5E5 E5E5E5E5 E5E5E5E5 E5E5E5E5 *eeeeeeeeeeeeeeee* 30 E5E5E5E5 E5E5E5E5 E5E5E5E5 E5E5E5E5 *eeeeeeeeeeeeeeee* 40 E5E5E5E5 E5E5E5E5 E5E5E5E5 E5E5E5E5 *eeeeeeeeeeeeeeee* 50 E5E5E5E5 E5E5E5E5 E5E5E5E5 E5E5E5E5 *eeeeeeeeeeeeeeee* 60 E5E5E5E5 ED414E44 204C4252 01000080 *.COMMAND LBR....* 70 14001600 17001800 19001A00 1B001D00 *................* DU2 B1? q ** Queue Status Summary ** 0 Blocks in Queue 249 Blocks Left in Queue Address of Head of Queue: 3E00 Hex Address of Tail of Queue: 3E00 Hex DU2 B1? may be hex imbedded in the ASCII: ca0 OK<1a> Use W to write changes to disk. Ranges may be specified: CHaddr-addr byte or CAaddr-addr byte Changes a range of bytes to the same value Examples (actual DU2 session): DU2 B7? g0 Group = 0000:00, Track = 122, Sector = 1, Physical Sector = 1 DU2 B7? d 00 07535444 20202020 204D5347 00000002 *.STD MSG....* 10 10000000 00000000 00000000 000000202020 204D5347 00000002 DU2 B7? a0-#f 00 *.STD MSG....* DU2 B7? fdu2.hlp 20 07445532 20202020 20484C50 01000039 *.DU2 HLP...9* 30 28009800 99009B00 9C009D00 00000000 *(...............* Group = 0000:00, Track = 122, Sector = 1, Physical Sector = 1 DU2 B7? g28 Group = 0028:00, Track = 125, Sector = 273, Physical Sector = 273 DU2 B7? d 00 496E766F 6B696E67 20445532 20616E64 *Invoking DU2 and* 10 20445532 20496E73 74616C6C 6174696F * DU2 Installatio* 20 6E0D0 = 0028:00, Track = 125, Sector = 273, Physical Sector = 273 DU2 B7? v3 Invoking DU2 and DU2 Installation DU2 Command Summary Commands for Logging Disks and Examining Disk Parameters Commands for Positioning and Reading Data Commands for Searching for Data Commands for Saving and Restoring Data Commands for Viewing data Commands for Altering Data Commands for Manipulating Macros and the @ Command Miscellanea Examples of command use Interpret Group = 0028:02, Track = 125, Sector = 275, Ph61 72616D65 74657273 * Disk Parameters* 70 0D0A436F 6D6D616E 64732066 6F722050 *..Commands for P* DU2 B7? ch0-10 0 DU2 B7? d 00 00000000 00000000 00000000 00000000 *................* 10 00445532 20496E73 74616C6C 6174696F *.DU2 Installatio* 20 6E0D0A44 55322043 6F6D6D61 6E642053 *n..DU2 Command S* 30 756D6D61 72790D0A 436F6D6D 616E6473 *ummary..Commands* 40 20666F72 204C6F67 67696E67 20446973 * for Logging Dis* 50 6B732061 6E642045 78616D69 6E696E67 *ks and Examining D0-#7F is the same as just D D3-5 A20-#3F See next section for examples. :Commands for Altering Data CH and CA CH allows the user to change the contents of the current block by specifying new values as hexadecimal numbers. CA allows the same by specifying an ASCII character string. CHaddr val val val... Change Hex data values in block CAaddr char string... Chang00 *................* 20 004C4449 52202020 20432020 00000038 *.LDIR C ...8* 30 13001500 00000000 00000000 00000000 *................* 40 0843504D 55472020 20434154 01000046 *.CPMUG CAT...F* 50 1C001E00 38003D00 41004300 45000000 *....8.=.A.C.E...* 60 00434F4D 4D414E44 204C4252 01000080 *.COMMAND LBR....* 70 14001600 17001800 19001A00 1B001D00 *................* DU2 B7? d0-#f 00 07535444 20202020 204D5347 00000002 *.STD MSG....* DU2 B7? h0-#f 00 07535444 20A44 55322043 6F6D6D61 6E642053 *n..DU2 Command S* 30 756D6D61 72790D0A 436F6D6D 616E6473 *ummary..Commands* 40 20666F72 204C6F67 67696E67 20446973 * for Logging Dis* 50 6B732061 6E642045 78616D69 6E696E67 *ks and Examining* 60 20446973 6B205061 72616D65 74657273 * Disk Parameters* 70 0D0A436F 6D6D616E 64732066 6F722050 *..Commands for P* DU2 B7? v Invoking DU2 and DU2 Installation DU2 Command Summary Commands for Logging Disks and Examining Disk Parameters Commands for P Groupysical Sector = 275 DU2 B7? g28 Group = 0028:00, Track = 125, Sector = 273, Physical Sector = 273 DU2 B7? d 00 496E766F 6B696E67 20445532 20616E64 *Invoking DU2 and* 10 20445532 20496E73 74616C6C 6174696F * DU2 Installatio* 20 6E0D0A44 55322043 6F6D6D61 6E642053 *n..DU2 Command S* 30 756D6D61 72790D0A 436F6D6D 616E6473 *ummary..Commands* 40 20666F72 204C6F67 67696E67 20446973 * for Logging Dis* 50 6B732061 6E642045 78616D69 6E696E67 *ks and Examining* 60 20446973 6B2050* 60 20446973 6B205061 72616D65 74657273 * Disk Parameters* 70 0D0A436F 6D6D616E 64732066 6F722050 *..Commands for P* DU2 B7? ca11 This is a test DU2 B7? d0-#1f 00 00000000 00000000 00000000 00000000 *................* 10 00546869 73206973 20612074 6573746F *.This is a testo* :Commands for Manipulating Macros and the @ Command Macros A Macro is a short-hand you can use to define a command sequence. Rather than having to type an inv   olved command over and over again, the DU2 macro facility allows you to assign this command sequence to a number (0 to 9) and then execute it by simply presenting this number as a command. The following commands are associated with this facility. :ntext and n ":n" defines the text following the digit 'n' to be a Macro. As always, 0 <= n <= 9. The macro definitions may be created and redefined at will. If a macro has alreadytyped. For example: g0 <-- go to Group 0 ch0-7f e5,< <-- Initialize the first block and Save >,w,+ <-- Read in the Saved Block, Write it out to disk, and advance to next logical block @ <-- Do the Previous Command Again @ <-- And Again @ <-- And Again ":P@" prints the previous command line (and does not 434F4E 00000000 *.DISKOUT CON....* 10 00000000 00000000 00000000 00000000 *................* DU2 B7? 1 Group = 0000:03, Track = 122, Sector = 4, Physical Sector = 4 00 04584449 52202020 20C3CF4D 00000054 *.XDIR COM...T* 10 2C002E00 48000000 00000000 00000000 *,...H...........* DU2 B7? g0,d0-#1f Group = 0000:00, Track = 122, Sector = 1, Physical Sector = 1 00 07535444 20202020 204D5347 00000002 *.STD MSG....* 10 10000000 00000000 00000000 00000000 *................* D....* Group = 0000:01, Track = 122, Sector = 2, Physical Sector = 2 00 0754414C 4B202020 2053554D 00000049 *.TALK SUM...I* 10 11002300 24000000 00000000 00000000 *..#.$...........* Group = 0000:02, Track = 122, Sector = 3, Physical Sector = 3 00 07444953 4B4F5554 20434F4E 00000000 *.DISKOUT CON....* 10 00000000 00000000 00000000 00000000 *................* Group = 0000:03, Track = 122, Sector = 4, Physical Sector = 4 00 04584449 52202020 20C3CF4D 00000054 *.XDIR COM...T* 10 2C02, Track = 122, Sector = 3, Physical Sector = 3 00 07444953 4B4F5554 20434F4E 00000000 *.DISKOUT CON....* 10 00000000 00000000 00000000 00000000 *................* Group = 0000:03, Track = 122, Sector = 4, Physical Sector = 4 00 04584449 52202020 20C3CF4D 00000054 *.XDIR COM...T* 10 2C002E00 48000000 00000000 00000000 *,...H...........* :Miscellanea ? "?" gives a command summary and tells the user what the current values are for Proc been defined for the indicated number, it will be overwritten by the execution of this command. "n", where 0 <= n <= 9, executes the indicated macro. :Pn and :PA ":Pn", where 0 <= n <= 9, prints the text of Macro Number n. ":PA" prints the text of all 10 macros. @ and :P@ "@" executes the previous command line that did not contain the "@" Command. This provides an easy way to repeat the last command line change it). Examples (edited DU2 session): DU2 B7? g0 Group = 0000:00, Track = 122, Sector = 1, Physical Sector = 1 DU2 B7? :1+,d0-#1f DU2 B7? :p1 Macro Definitions -- 1: +,d0-#1f DU2 B7? 1 Group = 0000:01, Track = 122, Sector = 2, Physical Sector = 2 00 0754414C 4B202020 2053554D 00000049 *.TALK SUM...I* 10 11002300 24000000 00000000 00000000 *..#.$...........* DU2 B7? 1 Group = 0000:02, Track = 122, Sector = 3, Physical Sector = 3 00 07444953 4B4F5554 20U2 B7? 1 Group = 0000:01, Track = 122, Sector = 2, Physical Sector = 2 00 0754414C 4B202020 2053554D 00000049 *.TALK SUM...I* 10 11002300 24000000 00000000 00000000 *..#.$...........* DU2 B7? :pa Macro Definitions -- 0: 1: +,d0-#1f 2: < Detail Left Out > 9: DU2 B7? g0,d0-#1f,1,1,1 Group = 0000:00, Track = 122, Sector = 1, Physical Sector = 1 00 07535444 20202020 204D5347 00000002 *.STD MSG....* 10 10000000 00000000 00000000 00000000 *............002E00 48000000 00000000 00000000 *,...H...........* DU2 B7? @ Command -- g0,d0-#1f,+,d0-#1f,+,d0-#1f,+,d0-#1f Group = 0000:00, Track = 122, Sector = 1, Physical Sector = 1 00 07535444 20202020 204D5347 00000002 *.STD MSG....* 10 10000000 00000000 00000000 00000000 *................* Group = 0000:01, Track = 122, Sector = 2, Physical Sector = 2 00 0754414C 4B202020 2053554D 00000049 *.TALK SUM...I* 10 11002300 24000000 00000000 00000000 *..#.$...........* Group = 0000:essor Clock Speed and Lines per Page on CON: as well as the address for the Group Storage Buffer (where the DU2 Queue begins). *[nn] "*nn" repeats the current command line (as entered so far) nn times. This command defaults to "forever" if nn is not specified. 'nn' may be 2 to 65535. ! "!" halts processing of commands, displays a continuation message to the user, and waits for the user t   o type any key. Typing a Control-C aborts command processing. This command is useful in stopping loops to give the user as much time as he wants to review the display. P "P" toggles the printer switch on and off. It allows you to turn on and off a recording of your console output. X "X" exit back to CP/M. The user is given the option to Warm Boot, in which case the CCP and BDOS are reloaded, or or = 1 DU2 B7? d0-#f,+,!,* 00 07535444 20202020 204D5347 00000002 *.STD MSG....* Group = 0000:01, Track = 122, Sector = 2, Physical Sector = 2 Type Any Character to Continue or ^C to Abort - 00 0754414C 4B202020 2053554D 00000049 *.TALK SUM...I* Group = 0000:02, Track = 122, Sector = 3, Physical Sector = 3 Type Any Character to Continue or ^C to Abort - 00 07444953 4B4F5554 20434F4E 00000000 *.DISKOUT CON....* Group = 0000:03, Track = 122, Sector = 4, Physical Sector = 4 AK...{* Group = 0001:02, Track = 122, Sector = 35, Physical Sector = 35 00 E5434420 20202020 204D4143 00000047 *eCD MAC...G* Group = 0001:03, Track = 122, Sector = 36, Physical Sector = 36 DU2 B7? ^C B7> :Examples Multiple commands may be separated by "," Any valid command string may be placed as an operand of the original DU2 command, i.e.: A>DU2 G0,D,G2,=OK<1A>,D Example: the following commands will erase the B disk directory to all E5ize the directory on Drive A: and then on Drive B:, the following commands could be issued: la,0 <-- Log in A and Initialize first block 1 <-- Perform write lb,0 <-- Log in B and Initialize first block 1 <-- Perform write n,0 <-- Declare New Disk and Initialize first block 1 <-- Perform write :Interpretation of Directory Data Presented by DU2 The following explains the format of a CP/M directoryII || || extent-^^ || || || || || || file size in sectors-^^ || || || ^^-00 = file active || E5 = file erased ^^-displacement of line in directory sector Second 50 33343536 3738393A 00000000 00000000 *3456789:........* line | | ^---allocation group numbers-------^ not. Z[nn] "Znn" causes the program to sleep, or pause, and may be used to look at a dump quickly in a looping command line. Z is 1 sec. Znn is nn seconds on an n MHz 8080. The processor speed may be specified by the user under GENINS for his particular system. ^C "^C" exits to CP/M and Warm Boots. Examples (actual DU2 session): DU2 B7? g0 Group = 0000:00, Track = 122, Sector = 1, Physical Sect Type Any Character to Continue or ^C to Abort - 00 04584449 52202020 20C3CF4D 00000054 *.XDIR COM...T* Group = 0000:04, Track = 122, Sector = 5, Physical Sector = 5 Type Any Character to Continue or ^C to Abort - DU2 B7? g1 Group = 0001:00, Track = 122, Sector = 33, Physical Sector = 33 DU2 B7? d0-#f,+,*3 00 E5482020 20202020 2042414B 00000004 *eH BAK....* Group = 0001:01, Track = 122, Sector = 34, Physical Sector = 34 00 E5535542 32202020 2042414B 0100007B *eSUB2 B's: lb log in b drive g0 position to dir. ch0-7f e5 fill with e5 < save the sector >,w,+,/16 restore, write, next, repeat 16 This could be shortened to: lb,g0,ch0-7f e5,< >,w,+,/16 Using Macros, the following two macros could be defined: Macro 0 -- :0g0,ch0-7f e5,< Macro 1 -- :1>,w,+,/16 Now, for the user to initial entry as shown by DU2, using either the F (Find File) command, or just doing D (Dump) of the directory sectors, which are located in groups 0 and 1 on a single density disk. Sample result of "FSID.COM" command: First 40 00534944 20202020 20434F4D 0000003A *.SID COM...:* line || ||| | || || | | || ||^----hex file name-----^ || || ^file name^ || || || || in ASC || file size in sectors-^^ || || || ^^-00 = file active || E5 = file erased ^^-displacement of line in directory sector Second 50 33343536 3738393A 00000000 00000000 *3456789:........* line | | ^---allocation group numbers-------^    ;PROGRAM: DUTIL ;AUTHOR: RICHARD CONN ;DERIVATION: DUTIL is derived from DU Version 7.5 ;VERSION: 1.1 ;DATE: 21 NOV 81 ;PREVIOUS VERSIONS: 1.0 (1 JAN 81) VERS EQU 11 ; DUTIL Version Number ; ; DUTIL is derived from -- ; DU.ASM V7.5 Revised 1/23/81 ; DISK UTILITY - By Ward Christensen ; ; Principal Authors of DU V7.5 are -- ; WLC KBP RGF BRR ; ; Key comments from DU V7.5 and DUTIL follow -- ; ;This version of DU is compatible with CP/M 1.4 and 2.x ;and does not require delay used in ;the 'sleep' command. ; ;For DUTIL, the additional value of PAGSIZ at 104h should ;be set for the size of the display (in lines) on the user's ;CON: device. Under DUTIL, all output is paged, and this ;determines the page limit. ; ;************************************************* ;* * ;* This program has been heavily modified * ;* to allow it to work without modification * ;* on most versions of CP/M 1.4 and, hopefully, * ;* all versions of CP/M 2.x. * ;* If yor CP/M * ;* to know about this. This program assumes the * ;* standard convention of no skew being used on * ;: the system tracks. This usually isn't a prob- * ;* lem because the SYSGEN program can be used to * ;* get the system from the disk so that it can * ;* be modified. * ;* This program should work under standard * ;* versions of CP/M 1.4. The only requirement * ;* is that the BIOS "SETSEC" routine not modify * ;* the sector number passed to it in the B * ;* register. Againslation ; problems where the BIOS leaves garbage in H. (BRR) ; ;01/15/81 Changed labels to be no more than 6 characters ; long. Moved stack. Cleaned up file. (KBP) ; ;01/13/81 Updated help messages for '#' and 'N' commands. ; Modified sign-on message. (RGF) ; ;01/12/81 Fixed problem with sector translation under ; CP/M 1.4. (RGF) ; ; ;System equates ; BASE EQU 0 ;SET TO 4200H FOR HEATH OR TRS-80 ALTCPM ; ;CP/M Key Areas ; FCB EQU BASE+5CH ;CP/M FCB BDOS EQU BASE+5 ;CP/M  alteration for various hardware ;configurations. It adjusts itself automatically to ;the correct number of sectors, tracks, directory size, ;etc. It has been tested on 5-1/4" and 8" floppy, and ;10 megabyte hard disk systems. ; ;Because of the automatic adaption feature, no conditional ;assembly options are included. The only alteration that ;needs to be done is to use DDT to set the byte at 103h ;to zero for systems using a 2 mHz clock or non-zero for ;4 mHz clock. This only affects the timeu have difficulty getting this program * ;* to run, AND if you are using CP/M 2.x, AND * ;* if you know your BIOS to be bug-free, leave * ;* a message on Technical CBBS of Dearborn, * ;* Michigan (313)-846-6127 with a description * ;* of the problem and a summary of your hard- * ;* ware configuration. * ;* One known possible problem involves the * ;* system tracks on some systems, and results * ;* from the system sectors being skewed. There * ;* is NO way for a program executing unden, system tracks with skewed * ;* sectors will be a problem. * ;* If you add any features or make any useful * ;* changes to this program, please modem a copy * ;* to the above CBBS, so the currency of the * ;* program can be maintained. * ;* * ;* Ron Fowler * ;* * ;************************************************* ; ; The last few revision notes for note are -- ; ;01/23/81 Changed SETSEC to ignore high-order result of ; SECTRN if SPT<256. This fixes some traBDOS ENTRY POINT TBUFF EQU BASE+80H ;CP/M TEMPORARY DISK I/O BUFFER TPA EQU BASE+100H ;CP/M TRANSCIENT PROGRAM AREA ; ;CP/M BDOS Function Codes ; PRINT EQU 9 GVERS EQU 12 RESETDK EQU 13 SELDK EQU 14 SRCHF EQU 17 ;SEARCH FIRST SUSER EQU 32 GETDSK EQU 25 GETDPB EQU 31 ; ;CP/M 1.4 Offsets and Some Key Values ; TRNOFF EQU 15 ;CP/M 1.4 OFFSET FROM BASE ;OF BDOS TO SECTRAN ROUTINE SKWOFF EQU 1AH ;CP/M 1.4 OFFSET TO SKEW TABLE S2OFF EQU 14 ;OFFSET INTO FCB FOR S2 BYTE DPBOFF EQU 3AH ;CP/M 1   .4 OFFSET TO DPB WITHIN BDOS S2MASK EQU 0FH ;MASK FOR EXTENDED RC BITS OF S2 DPBLEN EQU 15 ;SIZE OF CP/M 2.x DISK PARM BLOCK ; ;Define ASCII characters ; CR EQU 0DH ;CARRIAGE RETURN LF EQU 0AH ;LINE FEED TAB EQU 09H ;TAB BS EQU 08H ;BACKSPACE ; ;Beginning of Program ; ORG TPA JMP START ;JUMP OVER CLOCK BYTE AND I.D. ; CLOCK: DB 2 ;<---Put Processor Speed Here (1=1MHZ, 2=2MHZ, etc) PAGSIZ: DB 24 ;<---Put CRT Screen Size Here (24 Lines default) DB 'DUTIL.COM from DU.COM ver 7.5  DAD D ;Skip PUNCH DAD D ;Skip RDR DAD D SHLD VHOME+1 ;Home Disk DAD D SHLD VSELDK+1 ;Select Disk DAD D SHLD VSETRK+1 ;Set Track DAD D SHLD VSTSEC+1 ;Set Sector DAD D SHLD SETDMA+1 ;Set DMA Address DAD D SHLD VREAD+1 ;Read Block From Disk DAD D SHLD VWRITE+1 ;Write Block To Disk LDA VER2FL ORA A JZ DOCPM1 DAD D ;Skip LISTST DAD D SHLD VSCTRN+1 ;CP/M 2.x Sector Translation Table JMP HELLO ; ;Set up CP/M 1.4 Parameters ; DOCPM1: LHLD BDOS+1 MVI L,0 ;BDOS','.',(VERS MOD 10)+'0' DB CR,LF,' Derived From DISK UTILITY ver 7.5, ' DB 'Universal Version',CR,LF DB CR,LF DB 'Type ? for Help' DB CR,LF,0 LXI H,TBUFF ;TO INPUT BUFF MOV A,M ORA A JZ PRMPTR ;NO INITIAL COMMAND FROM COMMAND LINE ; ;Got initial command, set it up ; MOV B,A ;SAVE LENGTH DCR B ;JUST A SPACE? JZ PRMPTR ;GOTO COMMAND PROCESSOR IF SO LXI D,INBUF ;PT TO INLINE BUFFER INX H ;SKIP LEN INX H ;SKIP ' ' MOV A,M ;GET FIRST CHAR CPI '/' ;IF SLASH, PRINT INITIAL HELPnext character to process ; PRMPTI: MVI A,0FFH ;SET INFINITE LOOP COUNT STA TOGO ;LOOP COUNT FOR "/" STA TOGO+1 ; ;Minor Command Loop; This is the entry point for each individual command in ; a Command Line; Commands may be separated by semicolons in this manner ; PROMPT EQU $ SETSTK: LXI SP,DUTSTK ;RESET STACK XRA A ;ZERO 2-UP PRINT FOR DUAL-COLUMN PRINT STA TWOUP ;..SWITCH MVI A,1 STA FTSW ;TELL SEARCH NOT TO INCR PUSH H LXI H,TBUFF ;SET NO-READ INPUT BUFFER ADDRESS SHLD BUF STA DUMTYP ;TYPE OF DUMP (A,D,H) ; ;Command dispatcher ; If command not found, abort with error message ; If command file, process command with HL pting to next command char and ; A containing command letter ; PUSH H ;SAVE HL MOV B,A ;COMMAND IN B LXI H,CMDTBL ;SCAN COMMAND TABLE FOR USER COMMAND CMDLP: MOV A,M ;GET COMMAND ORA A ;0=END OF TABLE JZ WHAT CMP B ;COMPARE COMMAND JZ CMDGO INX H ;PT TO ADR INX H INX H ;PT TO NEXT CMND JMP CMDLP CMDGO: INX H ;PT TO ADDRESS1/23/81 by RLC' ; START: LXI H,0 ;GET PTR TO CP/M STACK DAD SP ;HL=SP SHLD DUTSTK ;SAVE IT ; LXI SP,DUTSTK ; SET STACK ; MVI C,GVERS ;GET CP/M VERSION NR CALL BDOS MOV A,H ;COMBINE THE TWO BYTE... ORA L ;...VERSION NR FOR A FLAG STA VER2FL ;SAVE IT ; ;Set up local jumps to BIOS ; LHLD BASE+1 ;WARM BOOT POINTER LXI D,3 ;READY FOR ADD DAD D SHLD VCONST+1 ;CON: Status DAD D SHLD VCONIN+1 ;CON: Input DAD D SHLD VCONOT+1 ;CON: Output DAD D SHLD VLIST+1 ;LST: Output  ON PAGE BOUNDARY PUSH H LXI D,TRNOFF ;CP/M 1.4 SECTRAN ROUTINE OFFSET DAD D SHLD VSCTRN+1 ;CP/M 1.4 Sector Translation Table POP H LXI D,SKWOFF ;CP/M 1.4 SKEW TABLE OFFSET DAD D SHLD SECTBL ;SET UP SKEW TABLE POINTER ; ;Initialization Complete -- Print Signon Message and Begin Command Processing ; HELLO: CALL GETSTP ;SET UP CP/M PARAMETERS CALL INITP ;INITIALIZE BUFFER PARAMETERS XRA A ;NOT QUIET STA QFLAG CALL ILPRT DB CR,LF,'DUTIL - Disk Utility, Version ' DB VERS/10+'0 (TOOLSET CONVENTION) JZ IHELP ;PRINT INITIAL HELP INFO CALL MOVE ;COPY INPUT LINE INTO INLINE BUFFER MVI A,CR ;STORE ENDING STAX D LXI H,INBUF ;PT TO FIRST BYTE OF INLINE BUFFER JMP PRMPTI ;PROCESS AS THOUGH IT WAS TYPED ; ;Input Command Line From User at Console ; PRMPTR: XRA A ;A=0 STA QFLAG ;Set Not Quiet CALL SINBUF ;Save old INBUF into PINBUF CALL RDBUF ;Read Input Line CALL EXMAC ;Expand Macros ; ;Begin Processing Command Line in INBUF ; At this point, HL points to AD ;FOR RDBYTE POP H CALL CTLCS ;ABORT? JZ PRMPTR ;..YES, READ BUFFER ; ;Do we have to position in directory after find? ; LDA FINDFL ORA A JNZ POSDIR ;POSITION IN DIRECTORY ; ;Begin Command Evaluation -- Check for EOL and Capitalize ; MOV A,M ;GET NEXT CHAR IN COMMAND LINE INX H ;POINT TO FOLLOWING CHAR CPI CR ;END OF LINE PHYSICALLY? JZ PRMPTR ;INPUT NEW COMMAND LINE IF SO CPI ';' ;END OF LINE LOGICALLY? JZ PROMPT ;PROCESS NEXT ELEMENT IF SO CALL UPCASE ;CAPITALIZE COMMAND  LOW MOV E,M INX H ;PT TO ADDRESS HIGH MOV D,M MOV A,B ;COMMAND BACK INTO A POP H ;RESTORE HL PUSH D ;PLACE ADDRESS ON STACK RET ;"RUN COMMAND" ; ;Macro Expansion Routine -- Expand Macros ; EXMAC: LXI H,INBUF ;PT TO INPUT LINE LXI D,CTEMP ;BUILD INTO TEMPORARY BUFFER EXMAC1: MOV A,M ;GET CHAR CPI '0' ;SKIP IF LESS THAN '0' JC EXMAC2 CPI '9'+1 ;CHECK FOR RANGE JNC EXMAC2 INX H ;PT TO NEXT CHAR PUSH H ;SAVE PTR TO NEXT CHAR IN LINE SUI '0' ;CONVERT TO BINARY (0-9) MOV    B,A ;RESULT IN B MVI C,0 LXI H,MTABL ;PT TO BASE OF MACROS DAD B ;PT TO MACRO CALL COPYM ;COPY MACRO INTO LINE DCX D ;BACK UP OVER POP H ;GET PTR TO NEXT CHAR IN COMMAND LINE EXMAC2: MOV A,M ;GET CHAR STAX D ;PUT CHAR INX H ;PT TO NEXT INX D CALL MTEST ;TEST FOR END OF BUFFER CPI CR ;DONE? JZ EXMAC3 CPI ';' ;LOGICAL EOL? JNZ EXMAC2 JMP EXMAC1 ;PROCESS NEXT COMMAND EXMAC3: LXI H,CTEMP ;COPY COMMAND LINE BACK LXI D,INBUF ;INTO INBUF CALL COPYCR ;COPY TO LXI STA QFLAG CALL ILPRT DB CR,LF,'Error -- Macro Expanded Command Line too Long',0 JMP PRMPTR ;NEW COMMAND ; ;Save INBUF into PINBUF for later processing by '@' command ; SINBUF: LXI H,INBUF ;PT TO INBUF LXI D,PINBUF ;PT TO PINBUF (PREVIOUS INBUF) ; ;Copy (HL) to (DE) until Encountered ; COPYCR: MOV A,M ;GET CHAR STAX D ;PUT CHAR INX H ;PT TO NEXT INX D CPI CR ;DONE? JNZ COPYCR RET ; ;Command Not Found Error ; WHAT: XRA A ;TURN OFF QUIET FLAG STA QFLAG POP H ;NOT QUIET STA QFLAG CALL ILPRT DB CR,LF,'Command --',CR,LF,0 LXI H,PINBUF ;GET PREVIOUS COMMAND LXI D,INBUF ;COPY INTO INBUF PCMD2: MOV A,M ;GET CHAR STAX D ;PUT CHAR INX H ;PT TO NEXT INX D CPI CR ;END OF LINE? PUSH PSW ;SAVE FLAG CALL TYPE ;PRINT CHAR POP PSW ;GET FLAG JNZ PCMD2 MVI A,LF ; CALL TYPE LXI H,INBUF ;RESTART COMMAND PROCESSING JMP PRMPTI ;INCLUDE LOOP CAPABILITY ; ;COMMAND: : ;Define or Print Macro ;:n Defines Macro n, 0<=n<=9; ::n Prints Ma ;PRINT MACRO WHOSE NUMBER IS IN D JMP PROMPT ; ;Print Previous Command ; PCPR: INX H ;PT TO CHAR AFTER '@' LXI D,PROMPT ;SET UP RET ADR PUSH D ;RETURN ADR ON STACK PUSH H ;SAVE PTR XRA A ;NOT QUIET STA QFLAG CALL ILPRT DB 'Previous Command Line Definition --' DB CR,LF,'@: ',0 LXI H,PINBUF ;PT TO PREVIOUS COMMAND JMP MPRINT ;USE MACRO PRINT FACILITY ; ;Print All Macros ; AMACPR: INX H ;PT TO CHAR AFTER 'A' MVI D,0 ;SET FOR FIRST MACRO AMPRL: CALL MACPR ;PRINT MACRO WH CHAR INX H ;PT TO NEXT CPI CR ;END OF MACRO? PUSH PSW ;SAVE FLAG CALL TYPE ;PRINT CHAR POP PSW ;GET FLAG JNZ MPRINT MVI A,LF ; CALL TYPE POP H ;GET PTR TO NEXT CHAR RET ; ;Check char in A for valid Macro Number (0-9), print error message if ; not, return number in D if so ; MNUM: SUI '0' ;CONVERT TO 0-9 JC MNERR ;ERROR IF LESS CPI 10 ;RANGE? JNC MNERR MOV D,A ;RESULT IN D RET MNERR: XRA A ;NOT QUIET STA QFLAG CALL ILPRT DB CR,LF,'Invalid Macro Number Specif H,INBUF ;PT TO INBUF RET ;EXPANSION COMPLETE ; ;Copy Macro Into Command Line Buffer ; COPYM: MOV A,M ;GET CHAR STAX D ;PUT CHAR INX H ;PT TO NEXT INX D CALL MTEST ;CHECK FOR LIMIT CPI CR ;END OF MACRO? JNZ COPYM RET ; ;Test for Buffer Full ; MTEST: PUSH H ;SAVE HL PUSH PSW ;SAVE A LXI H,CTEMPX ;CHECK FOR END OF BUFFER MOV A,H ;GET PAGE CMP D ;CHECK PAGE JZ MACERR POP PSW ;GET A POP H ;GET HL RET ; ;Macro Command Expansion Error ; MACERR: XRA A ;NOT QUIET  RESTORE HL CALL ILPRT DB 'Invalid Command -- ',0 MOV A,B ;GET COMMAND LETTER CALL TYPE ;PRINT IT JMP PRMPTR ; ;Memory full error ; MEMFUL: XRA A ;TURN OFF QUIET FLAG STA QFLAG CALL ILPRT DB '+++ Out of memory +++' DB CR,LF,0 JMP PRMPTR ; ;COMMAND: @ ;Repeat Previous Command Line ; PCMD: MOV A,M ;GET NEXT CHAR CPI CR ;SHOULD BE JZ PCMD1 XRA A ;NOT QUIET STA QFLAG CALL ILPRT DB CR,LF,'Warning: Remainder of Command Line after "@" Deleted',0 PCMD1: XRA A ;cro n, 0<=n<=9 ; MAC: MOV A,M ;GET NEXT CHAR CALL UPCASE ;CAPITALIZE CPI 'P' ;PRINT MACRO? JNZ MACROD ;IF NOT, DEFINE MACRO INX H ;PT TO MACRO NUMBER MOV A,M ;GET IT CALL UPCASE ;CAPITALIZE CPI '@' ;PRINT PREVIOUS COMMAND? JZ PCPR PUSH PSW ;SAVE A XRA A ;A=0 STA QFLAG ;NOT QUIET CALL ILPRT DB 'Macro Definitions --',0 POP PSW ;GET A CPI 'A' ;PRINT ALL MACROS? JZ AMACPR CALL MNUM ;CHECK FOR VALID NUMBER AND RETURN # IN D INX H ;PT TO CHAR AFTER MACRO NUMBER CALL MACPROSE NUMBER IS IN D INR D ;INCREMENT MACRO NUMBER MOV A,D ;GET VALUE CPI 10 ;DONE? JNZ AMPRL JMP PROMPT ;CONTINUE PROCESSING ; ;Print Macro Whose Number (0-9) is in D ; MACPR: PUSH H ;SAVE PTR XRA A ;NOT QUIET STA QFLAG CALL ILPRT ;PRINT HEADER DB CR,LF,0 MOV A,D ;GET NUMBER ADI '0' ;CONVERT TO ASCII CALL TYPE ;PRINT CALL ILPRT DB ': ',0 LXI H,MTABL ;PT TO TABLE OF MACROS MVI E,0 ;PAGE OFFSET OF ZERO; MACRO NUMBER ALREADY IN D DAD D ;PT TO MACRO MPRINT: MOV A,M ;GETied in Command',0 JMP PRMPTR ;NEW COMMAND ; ;Define Macro ; MACROD: CALL MNUM ;CHECK NUMBER AND RETURN IN D INX H ;PT TO CHAR AFTER MACRO NUMBER PUSH H ;SAVE PTR LXI H,MTABL ;PT TO MACRO TABLE MVI E,0 ;SET EVEN PAGE DAD D ;PT TO MACRO ENTRY IN HL XCHG ;... IN DE POP H ;PT TO MACRO TEXT CALL COPYCR ;COPY TO JMP PRMPTR ;NEW COMMAND ; ;COMMAND: ! ;Delay for user input ; UWAIT: CALL WAIT ; USE WAIT ROUTINE JMP PROMPT ; ;COMMAND: # ;Print disk statistics ; STATS:     PUSH H ;SAVE POINTER TO NEXT COMMAND CALL ILPRT DB '===============================',CR,LF DB ' -- Disk Information -- ',CR,LF DB '-------------------------------',CR,LF DB CR,LF,'Disk Drive: ',0 LDA DRIVE ADI 'A' ;CONVERT TO ASCII CALL TYPE ;PRINT DRIVE LETTER CALL ILPRT DB CR,LF,'Tracks: ',0 LHLD MAXTRK ;PRINT NUMBER OF TRACKS INX H CALL DEC CALL ILPRT DB CR,LF,'Sectors/Track: ',0 LHLD SPT ;PRINT NUMBER OF SECTORS/TRACK CALL DEC CALL ILPRT DB CR,LF,'Group SizNTER TO NEXT COMMAND JMP PROMPT ; ;COMMAND: N ;The following command resets the disk ;system thru CP/M, and may be usable for ;changing the disk density or format. ;This can only be done if your BIOS resets ;the auto-density select parameters at ;every track-zero access. ; NEWDSK: PUSH H ;SAVE POINTER TO NEXT LETTER MVI C,RESETDK ;BDOS RESET DISK FUNCTION CALL BDOS LDA DRIVE ;RESELECT CURRENT DRIVE MOV C,A POP H CALL SELECT JMP PROMPT ; ;COMMAND: Q ;Quite mode ; QUIET: SAT INX D ;TEST FOR 0FFFFH MOV A,D ;IF 0FFFFH, INX D MADE DE=0 ORA E JZ PROMPT ;CONTINOUS LOOP IF 0FFFFH DCX D ;COUNT DOWN DCX D ;MAKE UP FOR PREV INX D XCHG SHLD TOGO ;SET NEW COUNT (1 LESS THAN BEFORE) MOV A,H ;ALL DONE? ORA L XCHG ;GET BACK INBUF PTR IN HL JNZ PROMPT ;KEEP GOING IF NOT YET ZERO JMP PRMPTR ;ALL DONE ; ;COMMAND: U ;Set CP/M 2.x user number ; USER: LDA VER2FL ;CP/M 2.X? ORA A JZ WHAT ;ERROR IF NOT CALL DECIN ;GET REQUESTED USER NO. MOV A,E CPI 32 PLP: LDA CLOCK ; GET CLOCK SPEED MOV D,A ; SLEEP1: LXI B,41700 ; APPROX 1 SEC @ 1MHz ; SLEEP2: DCX B ;COUNT DOWN FOR 1 MHz [5 CYCLES] MOV A,B ;[5 CYCLES] <-- TOTAL TIME: 24 CYCLES ORA C ;[4 CYCLES] <-- (24 MU-SECS AT 1MHz) JNZ SLEEP2 ;[10 CYCLES] PUSH D CALL CTLCS ;ABORT? POP D JZ PRMPTR DCR D ;COUNT DOWN FOR CLOCK SPEED JNZ SLEEP1 DCR E ;COUNT DOWN NUMBER OF REQUESTED SECONDS JNZ SLEPLP JMP PROMPT ; ;Check for control-C or S ; CTLCS: CALL CONST ;CHAR AVAILABLE? OINDFL ;SET NO POSITION INR A ;A=1 STA FTSW ;SET SEARCH WITHOUT INCREMENT STA NOTPOS ;NOT POSITIONED LXI H,0 ;HL=0 SHLD MFPTR ;SET NO MULTI FILE PTR SHLD CURTRK ;SET TRACK 0 INX H ;HL=1 SHLD CURSEC ;SET LOGICAL SECTOR 1 SHLD PHYSEC ;SET PHYSICAL SECTOR 1 MVI A,CR ;CLEAR PREVIOUS COMMAND STA PINBUF ;SET PREVIOUS COMMAND TO NIL LXI H,MTABL ;CLEAR MACRO TABLE MVI B,10 ;10 ENTRIES INITP1: MVI M,CR ;STORE INR H ;PT TO NEXT PAGE DCR B ;COUNT DOWN JNZ INITP1 RET ; ;Set upe: ',0 LDA BLM ;PRINT SIZE OF A GROUP INR A MOV L,A MVI H,0 CALL DEC CALL ILPRT DB ' Blocks/Group' DB CR,LF,'Total Groups: ',0 LHLD DSM ;PRINT TOTAL NUMBER OF GROUPS ON A DISK CALL DEC CALL ILPRT DB CR,LF,'Directory Entries: ',0 LHLD DRM ;PRINT NUMBER OF DIRECTORY ENTRIES INX H CALL DEC CALL ILPRT DB CR,LF,'System Tracks: ',0 LHLD SYSTRK ;PRINT NUMBER OF SYSTEM TRACKS CALL DEC CALL ILPRT DB CR,LF DB '===============================',CR,LF,0 POP H ;RESTORE POITA QFLAG ;NOW QUIET (FLAG IS NON-ZERO) JMP PROMPT ; ;COMMAND: / ;Repeat buffer contents ; REPEAT: CALL DECIN ;NN SPECIFIED? MOV A,D ORA E JZ NNN ;NO -- SET FOR INFINITE LOOP OR SIMPLE REPEAT LHLD TOGO ;LOAD LOOP FLAG INX H ;TEST FOR FIRST TIME MOV A,H ORA L ;WAS IT 0FFFFH?; IF SO, WE HAVE NEW VALUE JNZ NNN ;NO: COUNTING XCHG ;GET COUNT SHLD TOGO ;SET COUNT ; NNN: LHLD TOGO ;GET CURRENT COUNT XCHG ;DE=CURRENT COUNT, HL=COUNT LIMIT LXI H,INBUF ;PT TO FIRST CHAR FOR REPE;VALID? JNC WHAT MOV A,D ;HIGH-ORDER BYTE MUST BE ZERO FOR VALID NUMBER ORA A JNZ WHAT MOV A,E ;SAVE USER NUMBER STA UNUM MVI C,SUSER ;SET USER NUMBER PUSH H ;SAVE CHAR POINTER CALL BDOS ;SET USER NO. POP H JMP PROMPT ; ;COMMAND: P ;Toggle print flag ; PRNTFF: LDA PFLAG ;TOGGLE PRINT FLAG XRI 1 STA PFLAG JMP PROMPT ; ;COMMAND: Z ;Sleep routine, in seconds ; SLEEP: CALL DECIN ;GET COUNT IF ANY MOV A,E ;ANY? ORA A JNZ SLEPLP MVI E,1 ; 1 SEC DEFAULT ; SLERA A JNZ GETC ORI 1 ;NO CHAR, RETURN NZ RET ; GETC: CALL CONIN ;INPUT CHAR ANI 1FH ;ALLOW ASCII CPI 'S'-40H ;WAIT FOR NEXT CHAR IF ^S OR S OR s CZ CONIN CPI 'C'-40H ;CHECK FOR ^C OR C OR c RET ;0 SET IF CTL-C ; ;Initialize Memory Buffers ; INITP: XRA A ;A=0 STA GLFLAG ;CLEAR GROUP LOADED FLAG (GROUP NOT LOADED) STA HEXAD ;CLEAR ADDRESS STA HEXAD+1 STA PFLAG ;SET NO PRINT STA SAVEFL ;SET NO SAVE DONE STA WRFLG ;MAY NOT WRITE STA DIRPOS ;SET NO DIRECTORY POSITION STA F flags, etc, at initialization ;Find our way at initialization ; GETSTP: MVI A,CR ;INITIALIZE INPUT BUFFER STA INBUF ;EMPTY BUFFER LDA VER2FL ;VERSION 2 OR BETTER? ORA A ;0=1.X JZ GSTP1 MVI C,SUSER ;GET USER NUMBER MVI E,0FFH ;GET USER CALL BDOS STA UNUM ;SET USER NUMBER GSTP1: MVI C,GETDSK CALL BDOS ;GET CURRENT DISK MOV C,A ;WE HAVE TO SELECT JMP SELECT ;TO GET THE DPH ; ;COMMAND: L ;Log in the selected disk ; LOGIN: CALL DOLOG JMP PROMPT ; DOLOG: MOV A,M ;DISK    REQUESTED? LXI D,0 CPI CR ;NO REQUEST OF PHYSICAL EOL JZ LGNODK CPI ';' ;NO REQUEST IF LOGICAL EOL JZ LGNODK CALL UPCASE ;CAPITALIZE INX H ;POINT TO NEXT CHAR SUI 'A' ;CONVERT TO 0-15 MOV C,A ;DISK NUMBER IN C ; ;Select Disk Whose Number is in C (A=0, B=1, etc) ; SELECT: PUSH H ;SAVE PTR TO NEXT COMMAND LETTER MOV A,C STA DRIVE ;REMEMBER LATER WHERE WE ARE ; VSELDK: CALL $-$ ;ADDR FILLED IN BY 'INIT' LDA VER2FL ORA A ;IF NOT CP/M 2.x ... JZ SELSKP ;..THEN SKIP THIS JUNK  IS PHYSICAL 0 STA FIRST0 CALL CLCSUB ;CALCULATE WHAT GROUP/GRPDISP WE ARE IN POP H ;GET PTR TO NEXT LETTER ; LGNODK: CALL NORITE ;SET NO DISK I/O DONE (NO POSITION) RET ; ;Read in the disk directory ; REDDIR: PUSH H ;SAVE PTR TO NEXT LETTER CALL NORITE ;POSITIONING LOST LHLD SYSTRK ;SAVE CURRENT TRACK SHLD CURTRK LXI H,1 ;SET SECTOR 1 SHLD CURSEC LHLD DRM ;GET DIR SIZE FROM DPB INX H ;MAKE 1-RELATIVE CALL ROTRHL CALL ROTRHL ;DIVIDE BY 4 (4 NAMES/SECTOR) MOV B,H ;BC=NUMMENT TO NEXT SECTOR POP D POP B LXI H,80H ;ADVANCE TO NEXT DMA ADDRESS DAD D XCHG ;DE=NEXT DMA ADDRESS DCX B ;COUNT DOWN DIRECTORY BLOCKS MOV A,B ORA C JNZ RDIRLP LXI B,TBUFF ;RESET DMA ADDRESS TO TBUFF CALL SETDMA POP H ;GET PTR TO NEXT CHAR RET ; ;COMMAND: M ;Map the directory ; MAP: CALL PAGSET ;SET PAGING COUNTER XRA A STA ONLY1 ;SET FLAG FOR ALL GROUPS (NOT ONLY 1) CALL REDDIR ;READ IN DIRECTORY MVI C,0 ;INIT START GRP # LDA AL0 ;READ DIR GRP BITS CALL COL: INX B ;NEXT GRP # PUSH H LHLD DSM ;GET HIGHEST GRP # INX H ;PLUS 1 FOR COMPARISON MOV A,L ;WHEN BC REACHES DSM+1.. CMP C ;..THEN WE HAVE EXCEEDED.. JNZ MAPC1 ;..THE DISK CAPACITY.. MOV A,H CMP B ; MAPC1: POP H JZ MAPEND ;..AND WE ARE DONE PUSH H CALL GETGRP ;GET ANOTHER POP D ;SEE IF SAME CALL CTLCS ;ABORT? JZ MAPND2 MOV A,D CMP H JNZ MAPDIF MOV A,E CMP L JZ MAPCNT ;SAME, CONTINUE ; ;Different file encountered ; MAPDIF: DCX B CALL HEXB ;PRINT ENDING GRSPACE MOV A,H ORA L ;NONE? JZ NONAME MOV A,M ;SEE IF ALLOC CPI 0E5H ;FREE? MVI A,' ' ;MARK ALLOCATED JNZ MPNSP1 MVI A,'(' ;MARK NOT ALLOCATED (ERASED FILE) ; MPNSP1: CALL TYPE ;PRINT ALLOCATION INDICATOR (SPACE OR '(') PUSH H ;SAVE POINTER MOV A,M CALL HEX ;SHOW USER NUMBER CALL SPACE INX H ;SKIP USER BYTE PUSH B MVI B,8 ;PRINT FILE NAME CALL MAPN2 MVI A,'.' ;PRINT DECIMAL SEPARATOR CALL TYPE MVI B,3 ;PRINT FILE TYPE CALL MAPN2 LDA DUPFLG ;DUPLICATE? CALL TYPE MOV A,H ORA L JZ WHAT ;SELECT ERROR MOV E,M ;GET THE SECTOR TABLE PNTR INX H MOV D,M INX H XCHG SHLD SECTBL ;SET THE SECTOR TABLE PTR LXI H,8 ;OFFSET TO DPBPTR DAD D MOV A,M ;PICK UP DPB POINTER INX H ; TO USE MOV H,M ; AS PARAMETER MOV L,A ; TO LOGIT ; SELSKP: CALL LOGIT LHLD SYSTRK ;RESET TRACK AND SECTOR XCHG ; TO DIRECTORY CALL SETTRK ; ON EVERY LXI D,1 ; LOGIN CALL SETSEC ; CHANGE LHLD PHYSEC ;THIS LOGIC WILL TELL MOV A,H ; IF FIRST SEC ORA L ; BER OF BLOCKS TO READ MOV C,L LXI D,DIRECT ;DMA ADDR XRA A ;A=0 STA GLFLAG ;SAY NO GROUP LOADED ; ;Read Disk Directory Loop ; RDIRLP: PUSH B ;SAVE REGS PUSH D MOV B,D ;BC=DMA ADDRESS MOV C,E LDA BDOS+2 ;CHECK MEM AVAIL DCR A ;ARE WE RNNING INTO BDOS? CMP D JC MEMFUL ;MEMORY FULL ERROR IF SO CALL SETDMA ;SET DMA ADDRESS TO THAT IN BC LHLD CURTRK ;SET TRACK XCHG CALL SETTRK LHLD CURSEC ;SET SECTOR XCHG CALL SETSEC CALL READ ;READ DIRECTORY BLOCK CALL NXTSEC ;INCREECT ;COLLECT COUNT OF DIR GRPS.. LDA AL1 ;..IN REGISTER C CALL COLECT MVI B,0 ;BC NOW HAS A DEFAULT START GRP # CALL HEXIN ;GET SPECIFIED GROUP IF ANY PUSH H ;SAVE INBUF PTR MOV A,E ;GET START ORA D ;NOTHING? JZ MAPDF ;..YES, DFLT MVI A,0FFH ;SET FLAG FOR ONLY 1 GROUP STA ONLY1 MOV B,D ;GET VALUE IN BC MOV C,E ; MAPDF: CALL HEXB ;PRINT FIRST GROUP NUMBER MVI A,'-' ;PRINT SEPARATOR CALL TYPE MVI A,' ' ;SET NO DUPLICATES STA DUPFLG CALL GETGRP ;GET GRP(C) TO HL ; MAPCNTOUP NUMBER INX B XCHG CALL MAPNAM ;PRINT FILE NAME LDA ONLY1 ;ONLY 1 NAME TO BE PRINTED? ORA A ;0=NO JNZ MAPND1 JMP MAPDF ; ;End of map ; MAPEND: DCX B ;GET LAST CALL HEXB ;PRINT LAST GROUP NUMBER CALL MAPNAM ;PRINT FILE NAME CALL WAIT ;DELAY FOR USER MAPND1: POP H CALL CRLF ;NEW LINE ; ;End of map - reposition to previous group ; MAPND2: PUSH H LHLD GROUP ;POINT TO GROUP IN DE XCHG JMP POSGP2 ; ;Print file name pointed to by HL ; MAPNAM: CALL SPACE ;LEADING  ;SPACE OR STAR POP B MOV A,M ;GET EXT CALL HEX ;PRINT EXTENT NUMBER POP H MOV A,M CPI 0E5H ;DELETED ENTRY? MVI A,' ' ;PRINT ENDING SPACE JNZ MPNSP2 MVI A,')' ;PRINT ALLOCATION FLAG ; MPNSP2: CALL TYPE ;")" IF ERASED FILE OR SPACE IF NOT JMP FLIP ; NONAME: CALL ILPRT DB ' ++ Free ++ ',0 ; FLIP: LDA TWOUP ;FLIP FLAG FOR TWO ENTRIES PER LINE XRI 1 STA TWOUP JZ PAGER ;NEW LINE WITH PAGING IF REQUIRED ; DELIM: MVI A,':' ;PRINT DELIMITER BETWEEN ADJACENT ENTRIE   S ON LINE CALL TYPE JMP SPACE ; ;Print name pted to by HL, length in B ; MAPN2: MOV A,M ANI 7FH ;STRIP POSSIBLE 2.x ATTRIBUTE BIT INX H CPI ' ' ;PRINTABLE? JC MAPN2H ;..NO, IN HEX CPI 7EH ;7E IS LEADIN ON SOME CRTS JC MAPN2A ; MAPN2H: CALL BHEX ;PRINT A AS HEX CHARS JMP MAPN2Z ; MAPN2A: CALL TYPE ;PRINT AS CHAR ; MAPN2Z: DCR B ;COUNT DOWN JNZ MAPN2 RET ; ;Find which file group (BC) belongs to ; GETGRP: LHLD DRM ;MAX DIR ENTRY # INX H ;MAKE 1-RELATIVE SHLD FIAVE GRP SIZE INDICATOR ; GETGL2: INX H ;POINTING INTO DM FIELD CALL GRPCMP ;COMPARE BC GP # AGAINST 1 DM FLD JNZ NOTGOT ;JUMP IF NOT FOUND ; ;Found the file ; PUSH H ;SAVE GROUP PTR LHLD MFPTR MOV A,H ;ANY ENTRIES? ORA L POP H ;GET PTR XTHL ;SAVE ENTRY START AND SAVE PTR JZ MPFRST ;IF ZERO, THEN FIRST ENTRY MVI A,'*' ;SET MULTI FLAG STA DUPFLG MPFRST: SHLD MFPTR ;SAVE POINTER XTHL ;RESTORE ENTRY START AND GET PTR NOTGOT: DCR E ;COUNT DOWN JNZ GETGL2 ;GO TEST SOME MOR.SAVED EXISTS POP H ;GET PTR TO NEXT CHAR JMP PROMPT ; ;This routine is common to Save Group (RG) and Write Group (WG); it is used ; to extract the group number, check it, and position DUTIL to it ; On exit, GROUP = Group Number, GRPDIS = 0, and DUTIL is positioned ; COMG: INX H ;PT TO CHAR AFTER 'G' OF ' ;Restore the current sector ; RESTOR: LDA SAVEFL ;SAVE DONE PREVIOUSLY? ORA A JZ NOSAVE ;NONE TO SAVE PUSH H LXI H,SAVBUF ;COPY FROM SAVBUF LXI D,TBUFF ;INTO TBUFF MVI B,128 ;128 BYTES CALL MOVE POP H ;GET PTR TO NEXT CHAR JMP PROM   PT ; ;Write Group Loaded in GBUFF to Disk ; RESTRG: LDA GLFLAG ;GROUP ALREADY LOADED? ORA A ;0=NO JZ RGERR CALL COMG ;GET GROUP NUMBER FROM COMMAND LINE AND POS PUSH H CALL ILPRT DB 'Writing to Group ',0 LHLD GROUP ;GET GROUP NUMBER MOV B,H ;VALUE IN BC MOV C,L CALL HEXB ;PRINT IN HEX CALL ILPRT DB CR,LF,0 POP H MVI A,0FFH ;WRITE FUNCTION STA CPYFCT ;COPY FUNCTION FOR GROUP COPY ROUTINE JMP COPYG ;GROUP COPY ROUTINE ; RGERR: XRA A ;NOT QUIET STA QFLAG CALL ILPRTVI M,CR JMP CLCGRP ;SHOW WHERE STOPPED ; ;COMMAND: = ;Search for character string ; SEARCH: PUSH H ;SAVE STRING POINTER ; SRCHL: CALL RDBYTE ;GET A BYTE MOV B,A ;SAVE IT MOV A,M ;CHECK NEXT MATCH CHAR. CPI '<' ;WILL IT BE HEX? MOV A,B ;RESTORE DISK CHAR JZ SRCHL1 ANI 7FH ;NEXT CHAR IS ASCII...STRIP BIT 7 ; SRCHL1: PUSH PSW CALL GETVAL ;GET SEARCH VALUE MOV B,A POP PSW CMP B ;MATCH? JNZ SRNOMT ;NO MATCH INX H MOV A,M ;DONE? CPI CR ;END OF LINE? JZ SREQU CPI 'SH H LDA FTSW ;FIRST READ? ORA A JNZ READ1 LHLD BUFAD MOV A,L ORA A ;IN BUFFER? JM NORD ;YES, SKIP READ ; ;Have to read ; CALL NXTSEC ;ADVANCE TO NEXT BLOCK ; READ1: XRA A STA FTSW ;NOT FIRST READ LHLD CURSEC XCHG CALL SETSEC LHLD CURTRK XCHG CALL SETTRK CALL READ CALL CLCSUB LXI H,TBUFF ; NORD: MOV A,M INX H SHLD BUFAD POP H RET ; ;COMMAND: V ;View the file in ASCII starting at ;current sector, stepping thru the disk ; VIEW: LDA WRFLG ORA A  VIEWPR: CALL TYPE ; VIEWNP: INR L JNZ VEWCHR DCR E JZ VEWEND PUSH D ;SAVE COUNT CALL NXTSEC LHLD CURSEC XCHG CALL SETSEC LHLD CURTRK XCHG CALL SETTRK CALL READ POP D ;RESTORE COUNT JMP VIEWLP ; VEWEOF: CALL ILPRT DB CR,LF,' ++ EOF ++',CR,LF,0 ; VEWEND: POP H CALL CRLF JMP CLCGRP ; ;COMMAND: A or D ;Dump in hex or ASCII ; DUMP: LDA WRFLG ORA A JNZ DUMPOK ; BADDMP: XRA A STA QFLAG ;NOT QUIET CALL ILPRT DB '++ Can''t dump, no sector read ND POINTER MOV H,B MOV L,C ; DUMPLP: MOV A,L ANI 7FH CALL HEX ;PRINT HEX VALUE CALL SPACE CALL SPACE LDA DUMTYP CPI 'A' JZ DUMPAS PUSH H ;SAVE START ; DHEX: MOV A,M CALL HEX ;PRINT HEX VALUE PTED TO BY HL MOV A,L ANI 3 CPI 3 ;EXTRA SPACE EVERY 4 CZ SPACE MOV A,L ANI 7 CPI 7 ;TWO EXTRA SPACES EVERY 8 CZ SPACE MOV A,E CMP L JZ DPOP INX H MOV A,L ANI 0FH JNZ DHEX ; DPOP: CALL CTLCS ;ABORT? JZ PRMPTR LDA DUMTYP CPI 'H' JZ DNOAS ;HEX ONLY  DB '++ No "RG" Read Group Command Issued or Loaded Group' DB ' Trashed ++' DB CR,LF,0 JMP PRMPTR ; NOSAVE: XRA A ;NOT QUIET STA QFLAG CALL ILPRT DB '++ No "<" Save Command Issued ++' DB CR,LF,0 JMP PRMPTR ; ;Move (HL) to (DE) length in B ; MOVE: MOV A,M STAX D INX H INX D DCR B JNZ MOVE RET ; NORITE: XRA A ;GET 0 STA WRFLG ;CAN'T WRITE NOW RET ; ;No match in search, try next char ; SRNOMT: POP H CALL CTLCS ;ABORT? JNZ SEARCH ;..YES LXI H,INBUF M;' ;LOGICAL EOL? JNZ SRCHL ; ;Got match ; SREQU: XRA A ;NOT QUIET STA QFLAG CALL ILPRT DB '= at ',0 LDA BUFAD ANI 7FH CALL HEX CALL CRLF JMP CLCGRP ; ;Get value from input buffer ; GETVAL: MOV A,M ;GET NEXT CHAR CPI '<' ;HEX ESCAPE? RNZ ;NO, RETURN ;"<<" means one "<" INX H MOV A,M CPI '<' RZ ;Got hex PUSH D CALL HEXIN ;GET VALUE CPI '>' ;PROPER DELIM? MOV A,E ;GET VALUE POP D JNZ WHAT ;ERROR RET ; ;Read a byte at a time from disk ; RDBYTE: PU JZ BADDMP CALL DECIN ;GET DISPL IF ANY PUSH H MOV A,E ORA A JNZ VIEWLP INR E ;DFLT=1 ; VIEWLP: LXI H,TBUFF ;TO DATA ; VEWCHR: CALL CTLCS ;ABORT? JZ VEWEND MOV A,M ;GET NEXT CHAR CPI 1AH ;EOF? JZ VEWEOF ANI 7FH ;MASK CPI 7EH ;ESC CHAR FOR H1500 JNC VIEWHX ;SHOW RUBOUT AND TILDE AS HEX CPI ' ' JNC VIEWPR CPI CR ;CR PASS JZ VIEWPR CPI LF ;LF PASS JZ VIEWPR CPI TAB ;TAB PASS JZ VIEWPR ; VIEWHX: MOV A,M ;NOT ASCII...PRINT AS CALL BHEX JMP VIEWNP ;++',CR,LF,0 ; EXPL: XRA A STA QFLAG ;NOT QUIET CALL ILPRT DB 'Use G command following F,',CR,LF DB 'or R or S following T',CR,LF,0 JMP PRMPTR ; DUMPOK: MOV A,M ;GET NEXT CHAR CPI ';' ;LOGICAL EOL? JZ DUMPDF ;DFLT CPI CR ;PHYSICAL EOL? JNZ DMPNDF ; ;Use default ; DUMPDF: LXI B,TBUFF LXI D,0FFH JMP DUMP1 ; DMPNDF: CALL DISP MOV B,D MOV C,E CPI CR JZ DUMP1 CPI ';' JZ DUMP1 INX H ;SKIP ',' CALL DISP ; ;BC = start, DE = end ; DUMP1: PUSH H ;SAVE COMMAPOP H ;GET START ADDR ; DUMPAS: CALL ASTER ;PRINT FIRST ASTERISK TO SEPARATE TEXT ; DCHR: MOV A,M ;GET CHAR ANI 7FH CPI ' ' JC DPER CPI 7EH ;TRAP ESC FOR H1500 JC DOK ; DPER: MVI A,'.' ;PRINT PRINTING CHAR ; DOK: CALL TYPE ;PRINT CHAR MOV A,E CMP L JZ DEND INX H MOV A,L ANI 0FH JNZ DCHR ; DEND: CALL ASTER ;PRINT ENDING ASTERISK CALL CRLF ;NEW LINE PUSH D CALL CTLCS ;ABORT? POP D JZ PRMPTR MOV A,E CMP L JNZ DUMPLP POP H JMP PROMPT ; DNOAS: P   OP B CALL CRLF MOV A,E CMP L JNZ DUMPLP POP H JMP PROMPT ; ;COMMAND: G ;Position ; POS: PUSH PSW MOV A,M CPI ';' ;LOGICAL EOL? JZ POSINQ CPI CR ;PHYSICAL EOL? JNZ POSOK ; POSINQ: POP PSW JMP INQ ; POSOK: POP PSW CPI 'T' ;TRACK? JZ POSTKD CPI 'S' ;SECTOR? JZ POSSCD CPI 'G' ;GROUP? JZ POSGPH JMP WHAT ;ERROR OTHERWISE ; ;Position to Track ; POSTKD: CALL DECIN ;GET NUMBER IN DECIMAL ; POSTRK: PUSH H LHLD MAXTRK ;CHECK FOR BEYOND END OF DISK CALSUB JMP INQ ; ;Calculate group from track and sector ; On exit, GROUP = Group Number and GRPDIS = Displacement within Group ; CLCSUB: PUSH H LHLD SYSTRK XCHG LHLD CURTRK CALL SUBDE ;COMPUTE RELATIVE TRACK NUMBER (SKIP SYSTEM TRACKS) XCHG LHLD SPT ;MULTIPLY BY NUMBER OF SECTORS/TRACK CALL MULT XCHG ;DE=TOTAL NUMBER OF SECTORS IN TRACKS LHLD CURSEC ;GET SECTOR OFFSET FROM BEGINNING OF TRACK DCX H DAD D ;HL=TOTAL NUMBER OF SECTORS WITH OFFSET LDA BLM MOV B,A MOV A,L ANAGP2 ;POSITION TO IT ; ;Position to Group ; POSGPH: CALL HEXIN ;GET PARAMETER ; ;Position to Group Numbered in DE and Print Position ; POSGRP: PUSH H LHLD DSM ;CHECK FOR WITHIN BOUNDS CALL SUBDE POP H JC OUTLIM XCHG SHLD GROUP ;SET GROUP NUMBER XCHG XRA A STA GRPDIS ;SET ZERO DISPLACEMENT PUSH H ; POSGP2: CALL GTKSEC ;CONVERT GROUP TO SECTOR/TRACK CALL SETTRK ;SET TRACK XCHG CALL SETSEC ;SET SECTOR CALL READ ;READ BLOCK XRA A STA NOTPOS ;NOW POSITIONED POP H = -SECTORS/TRACK XCHG LXI B,0 ;SET TRACK COUNTER TO ZERO ; DIVLP: INX B ;INCREMENT TRACK COUNT DAD D ;SUBTRACT SECTORS/TRACK FROM SECTORS TOTAL JC DIVLP DCX B ;ADJUST TRACK COUNT XCHG LHLD SPT ;ADD SECTORS/TRACK BACK IN TO ADJUST DAD D ;HL=NUMBER OF SECTORS ON LAST TRACK OF GROUP PUSH H LHLD SYSTRK ;ADD IN NUMBER OF SYSTEM TRACKS DAD B XCHG ;DE=TRACK NUMBER POP H INX H ;HL=SECTOR NUMBER RET ; ;COMMAND: F ;Find Directory Entry for specified file ; POSFIL: CALL NORIT DAD D XCHG MVI A,'D' STA DUMTYP JMP DUMPLP ;WHICH POPS H ; MVNAME: MOV A,M ;GET NEXT CHAR OF FILE NAME/TYPE CPI '.' ;END OF FILE NAME? JZ MVIPAD ;PAD OUT IF SO CPI CR ;END OF ENTRY? JZ PAD ;PAD OUT IF SO CPI ';' ;END OF ENTRY? JZ PAD ;PAD OUT IF SO CALL UPCASE ;CAPITALIZE STAX D ;STORE INX H ;PT TO NEXT INX D DCR B ;COUNT DOWN JNZ MVNAME MOV A,M ;CHECK FOR ERROR CPI CR ;OK IF EOL RZ CPI ';' ;OK IF LOGICAL EOL RZ INX H CPI '.' ;OK IF DECIMAL RZ JMP WHAT L SUBDE POP H JC OUTLIM CALL SETTRK ;SET TRACK CALL NORITE ;TRACK DOESN'T READ MVI A,1 STA NOTPOS ;SHOW NOT POSITIONED JMP CLCGRP ; ;Position to Sector ; POSSCD: CALL DECIN ;GET NUMBER IN DECIMAL MOV A,D ORA E JZ WHAT ;DON'T ALLOW SECTOR 0 ; POSSEC: PUSH H LHLD SPT ;CHECK FOR WITHIN RANGE CALL SUBDE POP H JC WHAT CALL SETSEC ;SET SECTOR CALL READ ;READ XRA A STA NOTPOS ;POSITIONED OK ; ;Calculate Group Number/Group Displacement and Print ; CLCGRP: CALL CLC B STA GRPDIS ;DISPLACEMENT WITHIN GROUP LDA BSH MOV B,A ; CLCLOP: CALL ROTRHL DCR B JNZ CLCLOP SHLD GROUP ;GROUP NUMBER POP H RET ; ;Position in the directory after a find ;(Does not work in CP/M-2.x) ; POSDIR: PUSH H ;SAVE INBUF LHLD BSH XRA A STA FINDFL ;CANCEL POS REQ LDA DIRPOS ;GET POSITION RAR RAR PUSH PSW ANA H STA GRPDIS POP PSW ; POSDLP: RAR DCR L JNZ POSDLP ANI 1 ;GET GROUP MOV L,A ;SETUP FOR POSGP2 MVI H,0 SHLD GROUP XCHG JMP POS JMP INQ ; ;Convert Group Number in DE to Sector and Track; also, GRPDIS = Offset in Grp ; On exit, DE = Track Number, HL = Sector Number ; GTKSEC: MOV H,D ;HL=GROUP NUMBER MOV L,E LDA BSH ;GET NUMBER OF SECTORS IN GROUP ; GLOOP: DAD H DCR A JNZ GLOOP LDA GRPDIS ;ADD IN DISPLACEMENT WITHIN GROUP ADD L ;CAN'T CARRY MOV L,A ; ;Divide by number of sectors, quotient=track, remainder=sector ; XCHG ;DE=TOTAL NUMBER OF SECTORS LHLD SPT ;GET NUMBER OF SECTORS/TRACK CALL NEG ;HL E MVI A,1 STA FINDFL ;SO WE POSITION LATER LXI D,FCB XRA A ;LOGGED IN DISK STAX D INX D MVI B,8 CALL MVNAME MVI B,3 CALL MVNAME LXI D,FCB MVI C,SRCHF PUSH H CALL BDOS INR A JNZ FLOK STA DIRPOS ;GRP 0 IF NOT FOUND CALL ILPRT DB '++ File Not Found ++',CR,LF,0 POP H JMP PROMPT ; FLOK: DCR A STA DIRPOS ;SAVE POS. IN DIR ANI 3 MOV L,A MVI H,0 DAD H ;X32 BYTES/ENTRY DAD H DAD H DAD H DAD H LXI D,TBUFF DAD D ;HL POINTS TO ENTRY LXI D,32 XCHG  ; MVIPAD: INX H ; PAD: MVI A,' ' ;PRINT PADDING SPACES STAX D INX D DCR B JNZ PAD RET ; ;COMMAND: + ;Advance to Next Logical Sector ; PLUS: LXI D,1 ;DFLT TO 1 SECT MOV A,M ;GET NEXT CHAR CPI CR ;CR? JZ PLUSGO ;..YES, DFLT TO 1 CPI ';' JZ PLUSGO CALL DECIN ;GET # MOV A,D ORA E JZ WHAT ; PLUSGO: CALL NXTSEC ;ADVANCE TO NEXT LOGICAL SECTOR DCX D ;MORE TO GO? MOV A,D ORA E JNZ PLUSGO ;..YES ; ;Ok, incremented to sector. Setup and read ; PLUSMI: PUSH    H LHLD CURSEC XCHG CALL SETSEC ;SET SECTOR LHLD CURTRK XCHG CALL SETTRK ;SET TRACK POP H CALL READ ;READ IT JMP CLCGRP ;CALCULATE GROUP AND DISPLAY ; ;COMMAND: - ;Back up to previous sector ; MINUS: LXI D,1 ;SET DFLT MOV A,M ;GET CHAR CPI CR ;CR? JZ MINGO ;..YES, DFLT=1 CPI ';' JZ MINGO CALL DECIN ;..NO, GET ## MOV A,D ORA E JZ WHAT ; MINGO: PUSH H LHLD CURSEC ;BACK UP SECTOR DCX H MOV A,H ORA L JNZ MINOK LHLD CURTRK ;BEYOND SECTOR ZERO, SO BACK U XCHG LHLD SPT ;CHECK TO SEE IF BEYOND END OF TRACK CALL SUBDE XCHG JNC NEXTOK LHLD CURTRK ;BEYOND END OF TRACK, SO INCR CURRENT TRACK INX H XCHG LHLD MAXTRK ;SEE IF BEYOND END OF DISK CALL SUBDE JNC TRASK LXI D,0 ;WRAP TO START OF DISK ; TRASK: XCHG SHLD CURTRK ;SET NEW CURRENT TRACK LXI H,1 ;SET SECTOR 1 ; NEXTOK: SHLD CURSEC ;SET NEW CURRENT SECTOR POP D POP H RET ; ;Tell what group, displacement, track, sector, physical sector ; INQ: CALL INQSUB JMP PROMP CALL DEC ;TRACK NUMBER IN DECIMAL CALL ILPRT ;PRINT SECTOR NUMBER DB ', Sector = ',0 LHLD CURSEC CALL DEC ;SECTOR NUMBER IN DECIMAL CALL ILPRT ;PRINT PHYSCIAL SECTOR NUMBER DB ', Physical Sector = ',0 LHLD PHYSEC CALL DEC ;PHYSICAL SECTOR NUMBER IN DECIMAL CALL CRLF POP H RET ; ;COMMAND: C ;Change Contents of Current Block ; CHG: MOV A,M ;GET TYPE (HEX, ASCII) CALL UPCASE PUSH PSW ;SAVE "H" OR "A" INX H CALL HEXIN ;GET DISP IN HEX CALL DISP1 ;VALIDATE DISP TO DE Isemicolons are removed, deleted bytes will be printed ; ; LDAX D ;GET BYTE THAT IS REPLACED ; CPI ' ' ; JC CHGAHX ; CPI 7EH ;DON'T PRINT ESC CHAR FOR H1500 ; JNC CHGAHX ; JMP CHGA2 ; ;CHGAHX: ; CALL BHEX ; JMP CHGA3 ; ;CHGA2: ; CALL TYPE ; ;End of print of delete bytes ; CHGA3: SHLD BACK ;IN CASE "THRU" CALL GETVAL ;GET ASCII OR VALUE STAX D ;UPDATE BYTE INX H ;PT TO NEXT INPUT CHAR ; ;See if 'THRU' requested ; MOV A,C ORA A JZ CHANTH CMP E ;DONE?.. JZ PROMPT ;.. LDAX D ;GET OLD ; CALL HEX ;ECHO IN HEX ; POP PSW ;GET NEW ; ;End of echo of bytes ; STAX D ;SAVE NEW BYTE MOV A,C ;SEE IF 'THRU' ORA A JZ CHHNTH ;..NO. CMP E ;..YES, DONE? JZ PROMPT LHLD HEXAD ;..NO: MORE ; CHHNTH: INR E JNZ CHGHEX MOV A,M CPI CR JZ PROMPT CPI ';' JZ PROMPT JMP WHAT ; ;COMMAND: R ;Read Current Block into TBUFF ;COMMAND: RG ;Read Specified Group into GBUFF ; DOREAD: MOV A,M ;GET CHAR AFTER R CALL UPCASE ;CAPITALIZE CPI 'G' ;READ GROUP? P TRACK MOV A,H ORA L JNZ SEASH LHLD MAXTRK ;WRAP TO END OF DISK SHLD CURTRK LHLD MAXSEC JMP MINOK ; SEASH: DCX H SHLD CURTRK LHLD SPT ;GET NUMBER OF SECTORS/TRACK ; MINOK: SHLD CURSEC ;SET NEW CURRENT SECTOR POP H DCX D ;COUNT DOWN ON NUMBER OF TIMES TO BACKUP MOV A,D ORA E JNZ MINGO JMP PLUSMI ;READ BLOCK ; ;Go to next sector ; On exit, CURSEC = Current Sector and CURTRK = Current Track ; NXTSEC: PUSH H PUSH D LHLD CURSEC ;INCREMENT CURRENT SECTOR INX H T ; ;Position inquiry subroutine ;Executed via: G S or T (with no operands) ; INQSUB: PUSH H LHLD SYSTRK ;CHECK IF IN SYSTEM TRACKS XCHG LHLD CURTRK CALL SUBDE JC NOGRP CALL ILPRT ;PRINT GROUP NUMBER IF NOT IN SYSTEM TRACKS DB 'Group = ',0 LHLD GROUP MOV B,H MOV C,L CALL HEXB ;PRINT GROUP NUMBER IN BC MVI A,':' CALL TYPE LDA GRPDIS CALL HEX ;PRINT GROUP DISPLACEMENT IN A MVI A,',' CALL TYPE ; NOGRP: CALL ILPRT ;PRINT TRACK NUMBER DB ' Track = ',0 LHLD CURTRK NX H LXI B,0 ;SHOW NO 'THRU' ADDR CPI '-' ;TEST DELIM FR. DISP JNZ CHGNTH ;NO THRU PUSH D ;SAVE FROM CALL HEXIN CALL DISP1 ;GET THRU INX H ;SKIP END DELIM MOV B,D MOV C,E ;BC = THRU POP D ;GET FROM JMP CHGAH ; CHGNTH: CPI ',' JNZ WHAT ; CHGAH: POP PSW CPI 'H' ;HEX? JZ CHGHEX CPI 'A' ;ASCII? JNZ WHAT ; ;Change ASCII ; CHGALP: MOV A,M ;GET CHAR CPI CR JZ PROMPT CPI ';' JZ PROMPT ; ;The following print of the deleted byte is commented out; if leading ; YES LHLD BACK ; CHANTH: INR E JNZ CHGALP MOV A,M CPI CR JZ PROMPT CPI ';' JZ PROMPT JMP WHAT ; ;Change hex ; CHGHCM: INX H ; CHGHEX: MOV A,M ;GET HEX DIGIT CPI CR JZ PROMPT CPI ';' JZ PROMPT CPI ',' ;DELIM? JZ CHGHCM PUSH D SHLD HEXAD ;IN CASE 'THRU' CALL HEXIN ;POSITIONS TO DELIM MOV A,E ;GET VALUE POP D ;..ADDR ; ;The following comments out the echo of the deleted byte; removing the ; leading semicolons restores the echo ; ; PUSH PSW ;SAVE VALUE ;JZ SAVEG ;SAVE GROUP IF SO LDA NOTPOS ;POSITIONED? ORA A JNZ CANTRD CALL READ ;READ BLOCK JMP PROMPT ; CANTRD: XRA A STA QFLAG ;NOT QUIET CALL ILPRT DB '++ Can''t read - not positioned ++',CR,LF DB 'Position by:',CR,LF DB ' Track then Sector, or',CR,LF DB ' Group',CR,LF,0 JMP PROMPT ; ;COMMAND: W ;Write Current Block to Disk ;COMMAND: WG ;Write Specified Group from GBUFF ; DORITE: MOV A,M ;GET NEXT CHAR CALL UPCASE ;CAPITALIZE CPI 'G' ;GROUP? JZ RESTRG ;DO GROUP    WRITE CALL WRITE ;DO WRITE JMP PROMPT ; ;Print Byte in A as Hex Digits ; BHEX: PUSH PSW MVI A,'<' CALL TYPE POP PSW CALL HEX MVI A,'>' CALL TYPE RET ; ;Print Number in BC as Hex Digits ; HEXB: LDA DSM+1 ORA A JZ HEXX MOV A,B CALL HEX ; HEXX: MOV A,C ; ;Print Byte in A as 2 Hex Digits ; HEX: PUSH PSW RAR ;GET HIGH NYBBLE RAR RAR RAR CALL NIBBL ;PRINT IT POP PSW ;GET LOW NYBBLE ; NIBBL: ANI 0FH ;MASK LOW NYBBLE CPI 10 ;0-9? JC HEXNU ADI 7  in 0 pted to by Return Address; return to byte after ; ILPRT: XTHL ;GET PTR AND SAVE HL ; ILPLP: CALL CTLCS ;ABORT? JZ PRMPTR MOV A,M ;GET CHAR CPI 1 ;PAUSE? -- ^A JNZ ILPOK CALL CONIN ;WAIT FOR ANY CHAR CPI 3 ;ABORT? JZ PRMPTR JMP ILPNX ; ILPOK: CALL TYPE ;PRINT CHAR ; ILPNX: INX H ;PT TO NEXT MOV A,M ;GET IT ORA A ;DONE? JNZ ILPLP INX H ;PT TO BYTE AFTER ENDING 0 XTHL ;RESTORE HL AND RET ADR RET ; ;DISP calls DECIN, and validates a sector ;displacement, thN ;MAKE DECIMAL ; HINLP: MOV A,M ;GET CHAR CALL UPCASE ;CAPITALIZE CPI CR ;EOL? RZ CPI ';' ;EOL? RZ CPI ',' RZ CPI '-' ;'THRU'? RZ CPI '>' RZ INX H ;PT TO NEXT CHAR CPI '0' ;RANGE? JC WHAT CPI '9'+1 ;RANGE? JC HINNUM CPI 'A' ;RANGE? JC WHAT CPI 'F'+1 ;RANGE? JNC WHAT SUI 7 ;ADJUST FROM A-F TO 10-15 ; HINNUM: SUI '0' ;CONVERT FROM ASCII TO BINARY XCHG DAD H ;MULT PREVIOUS VALUE BY 16 DAD H DAD H DAD H ADD L ;ADD IN NEW DIGIT MOV L,A XCHG JMP DAD H ;X2 DAD H ;X4 DAD D ;X5 DAD H ;X10 ADD L ;ADD IN DIGIT MOV L,A MOV A,H ACI 0 MOV H,A XCHG ;RESULT IN DE POP H JMP DINLP ; ;Read in a console buffer ; RDBUF: CALL ILPRT ;PRINT PROMPT DB CR,LF,'DUTIL ',0 LDA DRIVE ;GET DRIVE NUMBER ADI 'A' ;CONVERT TO ASCII CALL TYPE LDA VER2FL ;VERSION 2 OR BETTER? ORA A ;0=NO JZ RDBUF1 MVI A,'/' CALL TYPE LDA UNUM ;DISPLAY USER NUMBER MOV L,A ;VALUE IN HL MVI H,0 CALL DEC ;PRINT IN DECIMAL RDBUF1: CALL ILPR ;Page output ; PAGER: LDA PAGFLG ;GET FLAG CPI 2 ;2 LINES LEFT? JZ WAIT ;SAME AS USER DELAY DCR A ;COUNT DOWN STA PAGFLG JMP CRLF ; ;Delay Routine ; WAIT: PUSH H CALL ILPRT DB CR,LF,'Type Any Character to Continue or ^C to Abort - ',0 POP H CALL CONIN ;GET RESPONSE CPI 'C'-40H ;^C? JZ WAIT1 CALL CRLF ;NEW LINE CALL PAGSET ;RESET PAGE COUNT RET WAIT1: LDA IHFLG ;INITIAL HELP? ORA A ;0=NO JZ PRMPTR ;ABORT TO COMMAND PROMPT JMP EXIT1 ;ABORT TO CP/M ; ;CRLF Routi;CONVERT TO A-F ; HEXNU: ADI '0' ;CONVERT TO ASCII JMP TYPE ;PRINT IT ; ;Decimal output routine ; Print Number in HL as decimal digits (HL<100) ; DEC: PUSH B PUSH D PUSH H LXI B,-10 LXI D,-1 ; DECOU2: DAD B INX D JC DECOU2 LXI B,10 DAD B XCHG MOV A,H ORA L CNZ DEC MOV A,E ADI '0' CALL TYPE POP H POP D POP B RET ; ;Print ; SPACE: MVI A,' ' JMP TYPE ; ;Print '*' ; ASTER: MVI A,'*' JMP TYPE ; ;Inline print routine ; Print Chars endingen converts it to an address ; DISP: CALL DECIN DISP1: PUSH PSW ;SAVE DELIMITER MOV A,D ORA A JNZ BADISP MOV A,E ORA A JM BADISP ADI 80H ;TO POINT TO BUFFER AT BASE+80H MOV E,A MVI D,BASE/256 POP PSW ;GET DELIM RET ; BADISP: XRA A STA QFLAG ;NOT QUIET CALL ILPRT DB '++ Bad Displacement (Not 0-7FH) ++' DB CR,LF,0 JMP PRMPTR ; ;Input Number from Command Line -- Assume it to be Hex ; Number returned in DE ; HEXIN: LXI D,0 MOV A,M CPI '#' ;DECIMAL? JZ HDI HINLP ; HDIN: INX H ;SKIP '.' ; ;Input Number in Command Line as Decimal ; Number is returned in DE ; DECIN: LXI D,0 MOV A,M ; GET 1ST CHAR CPI '#' ; HEX? JNZ DINLP INX H ; PT TO DIGIT JMP HINLP ; DO HEX PROCESSING ; DINLP: MOV A,M ;GET DIGIT CALL UPCASE ;CAPITALIZE CPI CR ;EOL? RZ CPI ';' ;EOL? RZ CPI ',' RZ CPI '-' ;'THRU'? RZ INX H ;PT TO NEXT CPI '0' ;RANGE? JC WHAT CPI '9'+1 ;RANGE? JNC WHAT SUI '0' ;CONVERT TO BINARY PUSH H MOV H,D MOV L,ET ;PRINT PROMPT DB '? ',0 LXI D,INBUF-2 ;USE CP/M READLN MVI C,10 CALL BDOS LDA INBUF-1 ;GET CHAR COUNT MOV B,A ;CHAR COUNT IN B LXI H,INBUF ;STORE ENDING ADD L ;ADD CHAR COUNT TO HL MOV L,A MOV A,H ACI 0 MOV H,A MVI A,CR ;STORE ENDING MOV M,A ;SAVE IT CALL TYPE ;ECHO IT MVI A,LF ;ECHO.. CALL TYPE ;..LF LXI H,INBUF ;SET PTR TO FIRST CHAR IN LINE RET ; ;Set paging flag for page routine ; PAGSET: LDA PAGSIZ ;GET SIZE OF PAGE STA PAGFLG ;SET FLAG RET ;ne ; CRLF: MVI A,CR CALL TYPE MVI A,LF JMP TYPE ; ;Convert to Upper Case ; UPCASE: ANI 7FH ;MASK OUT MSB CPI 60H ;LESS THAN SMALL A? RC ;RETURN IF SO ANI 5FH ;MAKE UPPER CASE RET ; ;CON: Status Routine ; CONST: PUSH B PUSH D PUSH H VCONST: CALL $-$ ;ADDR FILLED IN BY 'INIT' POP H POP D POP B RET ; ;CON: Input Routine ; CONIN: PUSH B PUSH D PUSH H VCONIN: CALL $-$ ;ADDR FILLED IN BY 'INIT' POP H POP D POP B RET ; ;Console out with TAB expansi   on ; Char in A ; TYPE: PUSH B ;SAVE REGS PUSH D PUSH H MOV C,A ;FOR OUTPUT ROUTINE CPI TAB JNZ TYPE2 ;Tabulate TYPTAB: MVI A,' ' ;PRINT SPACE CALL TYPE LDA TABCOL ;GET COL COUNT ANI 7 ;DONE? JNZ TYPTAB JMP TYPRET ; ;Filter out control characters to ;prevent garbage during view of file ; TYPE2: CPI ' ' JNC TYPEQ CPI CR JZ TYPEQ CPI LF JNZ TYPNCR ; TYPEQ: LDA QFLAG ;CHECK QUIET FLAG FOR NO MESSAGES ORA A ; ;CON: Output Routine ; VCONOT: CZ $-$ ;ADDR FT: CALL $-$ ;ADDR FILLED IN BY 'INIT' POP H POP D POP B RET ; ;Home Disk Routine ; HOME: PUSH H VHOME: CALL $-$ ;ADDR FILLED IN BY 'INIT' POP H RET ; ;Set track # in DE ; SETTRK: PUSH H LHLD MAXTRK ;CHECK FOR WITHIN BOUNDS CALL SUBDE ;IF TRACK # IN DE > MAX, THEN ERROR POP H JC OUTLIM XCHG ;RESET CURRENT TRACK SHLD CURTRK XCHG MOV B,D ;BC=TRACK NUMBER MOV C,E PUSH H ; VSETRK: CALL $-$ ;ADDR FILLED IN BY 'INIT' POP H RET ; ;Set Sector Number in DE NOTSYS: LHLD SECTBL ;GET PTR TO SECTOR TABLE XCHG ;... IN DE DCX B ;DECREMENT SECTOR NUMBER BY 1 ; VSCTRN: CALL $-$ ;ADDR FILLED IN BY 'INIT' LDA SPT+1 ;IF SPT<256 (HI-ORD = 0) ORA A ; THEN FORCE 8-BIT TRANSLATION JNZ VSCTR1 ; ELSE KEEP ALL 16 BITS MOV H,A VSCTR1: LDA VER2FL ;SEE IF VERSION 2.x ORA A ;SET FLAGS JNZ GSTSEC ;JUMP IF CP/M 2.x MVI H,0 ;CP/M 1.4 GOOD TO ONLY 8 BITS MOV L,C ;MOST BIOS'S RETURN THE ; PHYSICAL SEC # IN REG C GSTSEC: SHLD PHYSEC ;THIS MAY BE REDRead Next Block into DMA Address ; READ: MVI A,1 ;SET FLAG STA WRFLG PUSH H ;SAVE PTR TO NEXT CHAR ; VREAD: CALL $-$ ;ADDR FILLED IN BY 'INIT' ORA A ;ERROR? JZ READOK XRA A ;NOT QUIET STA QFLAG CALL ILPRT DB '++ READ Failed, Sector may be Invalid ++' DB CR,LF,0 ; READOK: POP H ;GET PTR TO NEXT CHAR RET ; ;Write Block in DMA Address to Disk ; WRITE: LDA WRFLG ;READ ALREADY PERFORMED? ORA A ;ERROR IF NOT JNZ PWRITE ; BADW: XRA A ;NOT QUIET STA QFLAG CALL ILPRTmmand ; line ; IHELP: XRA A STA QFLAG ;NOT QUIET CALL ILPRT DB 'Introductory HELP on DUTIL (Disk Utility)',CR,LF DB ' The DUTIL program is designed to provide the user with' DB CR,LF DB 'the ability to manipulate information on the disk as easily' DB CR,LF DB 'as the DDT and SID utilities allow the user to manipulate' DB CR,LF DB 'information in memory.',CR,LF DB ' The following is a summary of the commands available to' DB CR,LF DB 'the DUTIL user. This same list is invokeILLED IN BY 'INIT' ; ;Update column used in tab expansion ; MOV A,C ;GET CHAR CPI CR JNZ TYPNCR MVI A,0 ;RESET TAB COLUMN IF STA TABCOL JMP TYPLST ; TYPNCR: CPI ' ' ;CTL CHAR? JC TYPLST ;..NO CHANGE IN COL LDA TABCOL ;INCR TAB COUNT INR A STA TABCOL ; TYPLST: LDA PFLAG ;CHECK FOR PRINTER OUTPUT ANI 1 CNZ LIST ;FROM C REG ; TYPRET: POP H ;RESTORE REGS POP D POP B RET ; ;LST: Output Routine ; Char in C ; LIST: PUSH B ;SAVED REGS PUSH D PUSH H VLIS; SETSEC: PUSH H PUSH D LHLD SYSTRK ;GET NUMBER OF SYSTEM TRACKS XCHG SHLD CURSEC ;SET CURRENT SECTOR LHLD CURTRK ;GET CURRENT TRACK CALL SUBDE ;SEE IF WE ARE IN THE SYSTEM TRACKS POP B ;BC=SECTOR NUMBER MOV H,B ;HL=SECTOR NUMBER MOV L,C JNC NOTSYS ;IF NO CARRY FOR SUBDE, WE ARE NOT IN SYSTEM TRACKS LDA FIRST0 ;SEE IF FIRST SEC 0 ORA A JNZ GSTSEC ;NO, JUMP AWAY DCX H ;YES, SO DECREMENT JMP GSTSEC ;REQUESTED, THEN GO ; ;Not in System Tracks, so Skew Factor is effective ; UNTANT IN ; MOST 1.4 VERSIONS, BUT ; SHOULD CAUSE NO PROBLEMS MOV B,H MOV C,L ; VSTSEC: CALL $-$ ;ADDR FILLED IN BY 'INIT' POP H ;RESTORE PTR TO NEXT CHAR RET ; ;Out of Disk Track Limit ; OUTLIM: XRA A ;NOT QUIET STA QFLAG CALL ILPRT DB '++ Not Within Tracks 0-',0 PUSH H LHLD MAXTRK ;PRINT MAX TRACK NUMBER CALL DEC POP H CALL ILPRT DB ' ++',CR,LF,0 CALL NORITE ;NOT POSITIONED JMP PRMPTR ; ;Set DMA Address ; SETDMA: JMP $-$ ;ADDR FILLED IN BY 'INIT' ; ; DB '++ Cannot Write Unless Read Issued ++' DB CR,LF,0 JMP EXPL ; ;Do Write ; PWRITE: PUSH H ;SAVE PTR TO NEXT CHAR MVI C,1 ;FORCE WRITE TYPE 1 IN CASE 2.x DEBLOCK USED ; VWRITE: CALL $-$ ;ADDR FILLED IN BY 'INIT' ORA A ;ERROR? JZ WRITOK XRA A ;NOT QUIET STA QFLAG CALL ILPRT DB '++ WRITE Failed ++',CR,LF,0 ; WRITOK: POP H RET ; ;Help; HELP is entry point for HELP (?) command, HELP1 is entry point for ; Initial Help Command, and IHELP is entry point for HELP (/) from cod internally by the' DB CR,LF DB '? Command of DUTIL. For additional information on disk' DB CR,LF DB 'structures and how to use DUTIL in general, refer to the' DB CR,LF DB 'files DUTIL.DOC and DUTIL.HLP.',CR,LF,0 MVI A,0FFH ;A=0FFH STA IHFLG ;SET INITIAL HELP CALL WAIT JMP HELP1 ;PROCESS NORMALLY HELP: XRA A ;A=0 STA IHFLG ;SET NO INITIAL HELP HELP1: XRA A STA QFLAG ;NOT QUIET CALL ILPRT DB '=======================================================',CR,LF DB ' -- Comm   and Summary -- ',CR,LF DB '-------------------------------------------------------',CR,LF DB CR,LF DB 'Operands in brackets [...] are optional' DB CR,LF,CR,LF DB '@ Repeat Previous Non-@ Command Line' DB CR,LF DB '+[nn] Step In [nn (decimal)] Sectors; -[nn] Step Out ' DB 'Sectors' DB CR,LF DB '# Print Disk Parameters for Current Drive' DB CR,LF DB '=xxx Search for ASCII xxx from Current Sector' DB CR,LF DB ' Caution: upper/lower case matters.' DB CR,LF DB ' Use for hLPRT DB '-------------------------------------------------------',CR,LF DB 'A[ff,tt] ASCII Dump' DB CR,LF DB 'C Change:' DB CR,LF DB ' CHaddr,byte,byte... (hex)' DB CR,LF DB ' or CAaddr,data... (Ascii)' DB CR,LF DB ' Allowed for imbedded hex.' DB CR,LF DB ' or CHfrom-thru,byte e.g. ch0-7f,e5' DB CR,LF DB ' or CAfrom-thru,byte' DB CR,LF DB 'D[ff,tt] Dump (Hex and ASCII)' DB CR,LF DB 'Fn.t Find File' DB CR,LF DB 'Gnn CP/M Allocation Group nn (hex)' DB CR,Lnn Set User nn (decimal) for Find command (CP/M-2 only)' DB CR,LF DB 'V[nn] View [nn (decimal)] ASCII Sectors' DB CR,LF DB 'W Write Current Sector; WG Write Specified Group' DB CR,LF DB 'X Exit Program' DB CR,LF DB 'Z[nn] Sleep [nn (decimal) seconds]' DB CR,LF,CR,LF,0 CALL WAIT CALL ILPRT DB '-------------------------------------------------------',CR,LF DB CR,LF DB 'Command Line is of the form: DUTIL d/u?',CR,LF DB ' "d" is Logged-In Disk, "u" is Current User',CR,LF DB CR,L(use #nn for Decimal)' DB CR,LF DB '"ff" and "tt" are in Hexadecimal (use #ff or #tt for Decimal)' DB CR,LF,CR,LF DB '=======================================================',CR,LF DB 0 CALL WAIT CALL ILPRT DB '=======================================================',CR,LF DB 'DUTIL Status Information',CR,LF DB '-------------------------------------------------------',CR,LF DB 'Processor Speed: ',0 LDA CLOCK ;GET CLOCK SPEED ADI '0' ;CONVERT TO ASCII CALL TYPE ;PRINT CALL ILPR ; EXIT: XRA A STA QFLAG ;NOT QUIET CALL ILPRT ;PRINT DB CR,LF,'Exit to CP/M -- Do you wish to Warm Boot (Y/N/=N)?' DB ' ',0 CALL CONIN ;GET RESPONSE CALL UPCASE ;CAPITALIZE CPI 'Y' ;YES? JZ BASE ;WARM BOOT IF SO ; ;Quick Exit to CP/M ; EXIT1: LHLD DUTSTK ;GET CP/M STACK PTR SPHL ;SET SP RET ; ;******************************** ;* * ;* Utility Subroutines * ;* * ;******************************** ; GRPCMP: MOV A,C INR D DCR D JZ CMP8 CMP M INX Hex:' DB CR,LF DB ' To find "IN 0" use: =<0> or' DB CR,LF DB ' "(tab)H,0(CR)(LF)" use: =<9>H,0' DB CR,LF DB '< Save Current Sector; > Restore Saved Sector' DB CR,LF DB '/[nn] Repeat [nn (decimal) times]; ! Pause for User' DB CR,LF DB ':ntext Define ''text'' to be Macro n; n Perform Macro' DB ' n, 0<=n<=9' DB CR,LF DB ':Pn Print Macro n, 0<=n<=9' DB CR,LF DB ':Px Print All Macros if x=A or Print Prev Line if x=@' DB CR,LF,CR,LF,0 CALL WAIT CALL IF DB 'H[ff,tt] Hex Dump' DB CR,LF DB 'L Log in drive; Lx Log in drive x' DB CR,LF DB 'M[nn] Map [from group nn (hex)]' DB CR,LF,CR,LF,0 CALL WAIT CALL ILPRT DB '-------------------------------------------------------',CR,LF DB CR,LF DB 'N Load New Disk; P Toggle Printer Switch' DB CR,LF DB 'Q Quiet Mode (no messages)' DB CR,LF DB 'R Read Current Sector; RG Read Specified Group' DB CR,LF DB 'Snn Sector nn (decimal)' DB CR,LF DB 'Tnn Track nn (decimal)' DB CR,LF DB 'UF DB 'Cancel a function with C or Ctrl-C.' DB CR,LF DB 'Suspend output with S or Ctrl-S.' DB CR,LF DB 'Separate commands with ";".' DB CR,LF DB ' Example: g0' DB CR,LF DB ' +;d;z2;/' DB CR,LF DB ' would step in, dump, sleep 2 sec, ' DB CR,LF DB ' and repeat until control-c typed.' DB CR,LF DB '"nn" usage varies with command as follows:',CR,LF DB ' +, -, /, T, S, U, V, Z nn in Decimal',CR,LF DB ' (use #nn for Hex)',CR,LF DB ' G, M nn in Hexadecimal',CR,LF DB ' T DB ' MHz',CR,LF DB 'Number of Lines on CON: ',0 LDA PAGSIZ ;GET PAGE SIZE MOV L,A ;NUMBER IN HL MVI H,0 CALL DEC ;PRINT NUMBER IN DECIMAL CALL ILPRT DB CR,LF,'Group Save Buffer Address: ',0 LXI B,GBUFF ;BC=ADDRESS CALL HEXB ;PRINT AS HEX CALL ILPRT DB ' Hex',CR,LF DB '=======================================================',CR,LF DB 0 LDA IHFLG ;INITIAL HELP? ORA A ;0=NO JNZ EXIT1 ;RETURN TO CP/M IF SO JMP PRMPTR ;NEW LINE INPUT IF NOT ; ;COMMAND: X ;Exit to CP/M  RNZ MOV A,B ; CMP8: CMP M RET ; ;2's complement HL ==> HL ; NEG: MOV A,L CMA MOV L,A MOV A,H CMA MOV H,A INX H RET ; ;HL/2 ==> HL ; ROTRHL: ORA A MOV A,H RAR MOV H,A MOV A,L RAR MOV L,A RET ; ;Collect the number of '1' bits ;in A as a count in C ; COLECT: MVI B,8 ;NUMBER OF BITS ; COLOP: RAL JNC COSKIP INR C ; COSKIP: DCR B JNZ COLOP RET ; ;HL-DE ==> HL ; Carry Flag is Significant ; SUBDE: MOV A,L SUB E MOV L,A MOV A,H     SBB D MOV H,A RET ; ;Quick Kludge multiply ;HL*DE ==> HL ; MULT: PUSH B PUSH D XCHG MOV B,D MOV C,E MOV A,B ORA C JNZ MULCON LXI H,0 ;FILTER SPECIAL CASE JMP MLDONE ; OF MULTIPLY BY 0 ; MULCON: DCX B MOV D,H MOV E,L ; MULTLP: MOV A,B ORA C JZ MLDONE DAD D DCX B JMP MULTLP ; MLDONE: POP D POP B RET ; ;Routine to fill in disk params ;with every drive change ; LOGIT: LDA VER2FL ORA A ;IF NOT CP/M 2.x THEN JZ LOG14 ; DO IT AS 1.4 ; ;CP/M  SHLD SYSTRK ; LOGCAL: LXI H,GRPDIS MOV A,M PUSH PSW LDA BLM MOV M,A PUSH H LHLD DSM XCHG CALL GTKSEC SHLD MAXSEC XCHG SHLD MAXTRK POP H POP PSW MOV M,A RET ;*********************************** ; ; DUTIL Command Table ; ;*********************************** CMDTBL: DB ':' DW MAC ; DB '@' DW PCMD ; DB '+' DW PLUS ; DB '-' DW MINUS ; DB '=' DW SEARCH ; DB '<' DW SAVE ; DB '>' DW RESTOR ; DB '#' DW STATS ; DB '?' DW HELP nd of Table ;************************************* ; ;Temporary storage area ; DS 100 ;50-ELT STACK DUTSTK: DS 2 ;OLD CP/M STACK POINTER; TOP OF DUTIL STACK BUFAD: DS 2 ;FORCES INITIAL READ HEXAD: DS 2 ;TO RE-FETCH A VALUE TOGO: DS 2 ;REPEAT COUNT (FFFF=CONT) TWOUP: DS 1 UNUM: DS 1 ;NUMBER OF CURRENT USER ONLY1: DS 1 ;FLAG TO PRINT ONLY 1 MAP ENTRY (0=NO) MFPTR: DS 2 ;MULTI FILE PTR FOR GETGRP PAGFLG: DS 1 ;LINE COUNTER FOR PAGING PFLAG: DS 1 ;1=PRINT GROUP: DS 2 ;GRTIONED WRFLG: DS 1 ;MAY NOT WRITE UNTIL '+', '-', ; OR 'G' COMMAND TGRP: DS 2 ;TEMPORARY GROUP FLAG QFLAG: DS 1 ;QUIET? (0=NO) FIRST0: DS 1 ;SETS TO 0 IF FIRST SEC # IS 0 DRIVE: DS 1 ;DRIVE NUMBER MAXTRK: DS 2 ;MAX TRACK NUMBER MAXSEC: DS 2 ;MAX SECTOR NUMBER VER2FL: DS 1 ;CP/M VERSION 2.X FLAG SECTBL: DS 2 ;POINTER TO SECTOR SKEW TABLE ; IHFLG: DS 1 ;0=NOT AT INITIAL HELP, 0FFH=AT INITIAL HELP DUPFLG: DS 1 ;SPACE OR STAR TO INDICATE MULTIPLE USERS BACK: DS 2 ;TO BACTENTS OF INPUT BUFFER CTEMP: DS 400H ;BUILD NEW COMMAND LINE BUFFER CTEMPX EQU $ ;END OF CTEMP ; ;Directory read in here; also loaded group area and Macros ; MTABL: DS 100H*10 ;10 PAGES FOR 10 MACROS GBUFF EQU $ DIRECT EQU $ ; END RK: DS 2 ; ;End of disk parameter block ; SAVBUF: DS 128+2+2 ; ;Set INBUF to a Page Boundary ; ORG $/100H*100H+100H-2 DB 126 ; SIZE OF BUFFER FOR CP/M DS 1 INBUF: DS 400H ;EXTRA SPACE FOR MACRO EXPANSION PINBUF: DS 400H ;PREVIOUS CON2.x ; LXI D,DPB ; THEN MOVE TO LOCAL MVI B,DPBLEN ; WORKSPACE CALL MOVE JMP LOGCAL ; ;CP/M 1.4 ; LOG14: LHLD BDOS+1 ;FIRST FIND 1.4 BDOS MVI L,0 LXI D,DPBOFF ;THEN OFFSET TO 1.4'S DPB DAD D MVI D,0 ;SO 8 BIT PARMS WILL BE 16 MOV E,M ;NOW MOVE PARMS INX H XCHG SHLD SPT XCHG MOV E,M INX H XCHG SHLD DRM XCHG MOV A,M INX H STA BSH MOV A,M INX H STA BLM MOV E,M INX H XCHG SHLD DSM XCHG MOV E,M INX H XCHG SHLD AL0 XCHG MOV E,M XCHG ; DB '/' DW REPEAT ; DB '!' DW UWAIT ; DB 'A' DW DUMP ; DB 'C' DW CHG ; DB 'D' DW DUMP ; DB 'F' DW POSFIL ; DB 'G' DW POS ; DB 'H' DW DUMP ; DB 'L' DW LOGIN ; DB 'M' DW MAP ; DB 'N' DW NEWDSK ; DB 'P' DW PRNTFF ; DB 'Q' DW QUIET ; DB 'R' DW DOREAD ; DB 'S' DW POS ; DB 'T' DW POS ; DB 'U' ;******CP/M 2.x ONLY****** DW USER ; DB 'V' DW VIEW ; DB 'W' DW DORITE ; DB 'X' DW EXIT ; DB 'Z' DW SLEEP ; DB 0 ; EOUP NUMBER GRPDIS: DS 1 ;DISPLACEMENT INTO GROUP SAVEFL: DS 1 ;SAVE FLAG CURTRK: DS 2 ;CURRENT TRACK NUMBER CURSEC: DS 2 ;CURRENT SECTOR NUMBER PHYSEC: DS 2 ;CURRENT PHYSICAL SECTOR NUMBER TABCOL: DS 1 ;TAB COLUMN GLFLAG: DS 1 ;GROUP LOADED FLAG; 0=NO CPYFCT: DS 1 ;GROUP COPY FUNCTION; 0=READ, 0FFH=WRITE FILECT: DS 2 ;FILE COUNT DIRPOS: DS 1 ;POSITION IN DIRECTORY FINDFL: DS 1 ;1=MUST POSITION AFTER FIND FTSW: DS 1 ;SEARCH W/O INCREMENT NOTPOS: DS 1 ;INITIALLY NOT POSIK UP IN "CA0-7F,X" DUMTYP: DS 1 ; ;The disk parameter block ;is moved here from CP/M ; DPB EQU $ ;DISK PARAMETER BLOCK (COPY) SPT: DS 2 BSH: DS 1 BLM: DS 1 EXM: DS 1 DSM: DS 2 DRM: DS 2 AL0: DS 1 AL1: DS 1 CKS: DS 2 SYSTRK: DS 2 ; ;End of disk parameter block ; SAVBUF: DS 128+2+2 ; ;Set INBUF to a Page Boundary ; ORG $/100H*100H+100H-2 DB 126 ; SIZE OF BUFFER FOR CP/M DS 1 INBUF: DS 400H ;EXTRA SPACE FOR MACRO EXPANSION PINBUF: DS 400H ;PREVIOUS CON   1DUTIL.COM from DU.COM ver 7.5 1/23/81 by RLC!9"#1# |2#*""""-"5""M""""L:#ʈ"wÝ*."w"#r02# DUTIL - Disk Utility, Version 1.1 Derived From DISK UTILITY ver 7.5, Universal Version Type ? for Help !~>G>%##~/pq > !%K2#8͢>2#2#1#2#>2#!"#>:#K~# >;S͸2#G!"~Hʚ###Ë#^#Vx!%-~0:#0G!1 ~# ;è!-%>!%~# !1|ɯ2d>#!1>>]S=============================== -- Disk Information -- ------------------------------- Disk Drive: :#A Tracks: *## Sectors/Track: *# Group Size: :#:#Hͷ{ HzH{2# S:#2#Sͷ{:WI :#~~>  >)6  ++ Free ++ :#2#N>:~# W ~] ͯ` I *##"#!"#!;2#~ʹ ~_#~ʹ :#ʙ W#"µ *#|ʱ >*2#"#š  *#+"#|y *#:#!#q >2#S#~͸;H Hv*#;"ڕ"#"#2#͜9Q Reading from Group *#DMͿ >2#>2#z ;:#2#V 2#+ >~;  , 2BK , ;, #2`i}:#As ~}}{d #}D >:#Hʫ ~ ڃ ~څ >.{ʔ #}v ͮ>{/ Sͮ{/ S~; T S GoHͷ*#;"ڕ9z >2#ͷzH*#;"HQ2#*#*#;"*#B"*#+:#G}2#:#G'"?"#*#2#:#2#-^o&"#Çv*#;"ڕ"#2#͜9Q2#bk:#)=¡:#o*#"ڶ *#*# #z >2#\00\<2#++ File Not,"#v{yS*#~ S;SH~͸G" :#DS2#++ Can't read - not positioned ++ Position by: Track then Sector, or Group S~͸G S><>>:#xy 0  |{0> >*>~&>)#~#ͷzG{Gƀ_ɯ2#++ Bad Displacement (Not 0-7FH) ++ >~#ʶ~͸ ;,->#0H:کAHGH0))))o#~##~͸ ;,-#0H:H0bk)))o|g DUTIL # Error -- Macro Expanded Command Line too Long>!%)~# >ɯ2#Invalid Command -- x>2#+++ Out of memory +++ >~ 2# Warning: Remainder of Command Line after "@" Deleted2# Command -- !)%~# > !%K~͸P#~͸@G2#Macro Definitions --Aʃ#͓S#S2#Previous Command Line Definition -- @: !)ð#͓z †S2# z0: !1~# °> 0 Wɯ2# Invalid Macro Number Specified in Comman x>S#ɯ2#2#2#2#2#2#2#2#<2#2#!"#"##"#"#> 2)!1 6 $j> 2%:#ʈ 2#Oì͗S~ ;͸#AOy2#:#|H^#V#"#!~#fob"*#9Q*#|2#z z *#"#!"#*##'"'"DM;2#BK:=k*#9*#Q! xG2#:#/":#/"v{u>2#BKͿ>-> 2#e *##}’|ʾe z«{ʅ Ϳ:#u Ϳ]ͮ*#Ç| ~> >(~#I >.+ No "RG" Read Group Command Issued or Loaded Group Trashed ++ >2#++ No "<" Save Command Issued ++ >~#q ɯ2#Ž !%6  G~{H:# *#} 2#*#Q*#9!~#"#:#ʝ ͷ{( !ʏ ~} ~R Y Y Y Y ~ͯ\ ,+ ʏ *#Q*#9(  ++ EOF ++ ͮ:# 2#++ Can't dump, no sector read ++ 2#Use G command following F, or R or S following T  Found ++ S=2#o&))))) >D2#/ ~.X Y;Y͸#0~ ;#.H#> Y~ x;xͷzHzx*#Q*#9~ ʭ;ʭͷzH*#+|*#|*#"#*#+"#*#"#z­Á*##*#;"*##*#;""#!"#S*#*#;"FGroup = *#DMͿ>::#>, Track = *#, Sector = *#, Physical Sector = *#ͮ~͸#v5#-´v5#BKù,HHAH~ S;S"# #yS*#~ S;SH#~ S;S:#A:#>/:#o&? $ :$G!%o|g> w> !%:2#:#]=2#î Type Any Character to Continue or ^C to Abort - ʤͮG:#>"> > `_O > :#%   :#y >2# :#<2#:#)*#;"ڕ"#BK*#"#*#;"`iq:#‹+Ë*# :#g:#‹&i"#DMɯ2#++ Not Within Tracks 0-*# ++ z >>2# 2#++ READ Failed, Sector may be    Invalid ++ :#H2#++ Cannot Write Unless Read Issued ++ n2#++ WRITE Failed ++ ɯ2#Introductory HELP on DUTIL (Disk Utility) The DUTIL program is designed to provide the user with the ability to manipulate information on the disk as easily as the DDT and SID utilities allow the user to manipulate information in memory. The following is a summary of the commands available to the DUTIL user. This same list is invoked internally by the ? Command of DUTIL. For adnt Sector Caution: upper/lower case matters. Use for hex: To find "IN 0" use: =<0> or "(tab)H,0(CR)(LF)" use: =<9>H,0 < Save Current Sector; > Restore Saved Sector /[nn] Repeat [nn (decimal) times]; ! Pause for User :ntext Define 'text' to be Macro n; n Perform Macro n, 0<=n<=9 :Pn Print Macro n, 0<=n<=9 :Px Print All Macros if x=A or Print Prev Line if x=@ ]------------------------------------------------------- A[ff,tt] ASCII Dump C Change: CHactor nn (decimal) Tnn Track nn (decimal) Unn Set User nn (decimal) for Find command (CP/M-2 only) V[nn] View [nn (decimal)] ASCII Sectors W Write Current Sector; WG Write Specified Group X Exit Program Z[nn] Sleep [nn (decimal) seconds] ]------------------------------------------------------- Command Line is of the form: DUTIL d/u? "d" is Logged-In Disk, "u" is Current User Cancel a function with C or Ctrl-C. Suspend output with S or Ctrl-S. Separate commands with ";". Example: g---- Processor Speed: :0 MHz Number of Lines on CON: :o& Group Save Buffer Address: ;Ϳ Hex ======================================================= :#">2# Exit to CP/M -- Do you wish to Warm Boot (Y/N/=N)? ͸Y*#y"#x}/o|/g#ɷ|g}o6" 1"}o|gBKxR"!_" T]x_" U":#t"#q ê"*.:^#"#^#"#~#2#~#2#^#"#^#"#^"#!#~:#w*#͜"#"#w:@+b-= < > #?/!A CD FG H LMKNditional information on disk structures and how to use DUTIL in general, refer to the files DUTIL.DOC and DUTIL.HLP. >2#]È2#2#======================================================= -- Command Summary -- ------------------------------------------------------- Operands in brackets [...] are optional @ Repeat Previous Non-@ Command Line +[nn] Step In [nn (decimal)] Sectors; -[nn] Step Out Sectors # Print Disk Parameters for Current Drive =xxx Search for ASCII xxx from Curreddr,byte,byte... (hex) or CAaddr,data... (Ascii) Allowed for imbedded hex. or CHfrom-thru,byte e.g. ch0-7f,e5 or CAfrom-thru,byte D[ff,tt] Dump (Hex and ASCII) Fn.t Find File Gnn CP/M Allocation Group nn (hex) H[ff,tt] Hex Dump L Log in drive; Lx Log in drive x M[nn] Map [from group nn (hex)] ]------------------------------------------------------- N Load New Disk; P Toggle Printer Switch Q Quiet Mode (no messages) R Read Current Sector; RG Read Specified Group Snn Se0 +;d;z2;/ would step in, dump, sleep 2 sec, and repeat until control-c typed. "nn" usage varies with command as follows: +, -, /, T, S, U, V, Z nn in Decimal (use #nn for Hex) G, M nn in Hexadecimal (use #nn for Decimal) "ff" and "tt" are in Hexadecimal (use #ff or #tt for Decimal) ======================================================= ]======================================================= DUTIL Status Information ---------------------------------------------------yPQR.S T UV WX!Zo|/g#ɷ|g}o6" 1"}o|gBKxR"!_" T]x_" U":#t"#q ê"*.:^#"#^#"#~#2#~#2#^#"#^#"#^"#!#~:#w*#͜"#"#w:@+b-= < > #?/!A CD FG H LMKNyPQR.S T UV WX!Zo|/g#ɷ|g}o6" 1"}o|gBKxR"!_" T]x_" U":#t"#q ê"*.:^#"#^#"#~#2#~#2#^#"#^#"#^"#!#~:#w*#͜"#"#w:@+b-= < > #?/!A CD FG H LMK~    DU-V80.DOC by Ward Christensen with additional notes by Ron Fowler and Keith Petersen (revised 10/07/83) HOW TO USE DU ver 8.x DISK UTILITY INSTALLATION: The 7.0 and later versions of DU are designed to be installed with a minimum of trouble. In fact, in al- most all cases, no changes to the source file should be necessary to get DU up and running. This is because DU uses the disk paramter block of CP/M to determine the characteristics of the disk environhe original DU command, i.e.: A>DU G0;D;G2;=OK<1A>;D Functions supported: Tnn Seek to track nn (no read) Snn Position to sector nn, and read Gnn Position to group nn and read. G Shows current position V Views the current sector. (assumes ASCII data) Vnn Views nn sectors Fname print directory for file "name", then positions to its directory sector. (Won't position under CP/M 2.x, but see = command below.) =string Ascii search, starting at current sector. <ending address: D0,7F is the same as just D D3,5 A20,3F CHaddr,val,val,val... change hex in sector CAaddr,char string... change ASCII in sector NOTE that may be hex imbedded in the Ascii: ca0,OK<1a> ----> Use W to write changes to disk. Note that the C command echoes the overlaid data for verification. CHaddr-addr,byte or CAaddr-addr,byte repeats a change + advance 1 sector (if below track 2, this advances to next numerical, if 2 or >, advances based directory entries are displayed in parentheses. # Prints the disk parameters M Dumps a map of the group allocations for files. Mn Shows which file is allocated to group "n". N Resets CP/M via the BDOS. This may make it possible under some implementations of CP/M to change the disk format (e.g., density, sides, etc) R Reads the sector currently positioned to into memory. Note R (Read) is implicit in the G, +, and - commands, but N-O-T in the S and T commands (I allows sectors to be written sequentially into memory starting at 3000H, for later recovery by DDT, etc. Z Sleep - causes the program to pause, such as to look at a dump. Z is 1 sec. Znn is nn tenths of a second on a 2 MHz 8080. < Saves current sector in a save buffer > Gets saved buffer. < and > may be used to move a sector to another place. / Repeats entire command. Defaults or /nn to "forever". NN may be 2 to 65535 multiple commands may be separated by ";" Examment. (see the dis- claimer for certain non-standard versions of CP/M 1.4). The only parameter that should need to be changed will be the clock speed flag at 103H. Leave this byte zero if you have a 2MHz clock. Patch it to 1 for 4MHz or 2 for 6MHz. This is only needed for the "Z" (sleep) command. NOTE: This latest version of DU fully supports CP/M plus (ver 3). It was tested on both banked and non-banked systems. USE: Any valid command string may be placed as an operand of txx> hex may be imbedded, or used alone: To find "IN 0FEH": = Ignores bit 7 unless is used. L Re-logs in the current disk. You may pull out a disk, put in a new, and "L" just to log it in. Lx Logs in disk 'x', such as: LB Ux Logs user 'x' for next F command. Gives '?' error if not CP/M version 2.x. D Dump sector, hex + ASCII A Dump sector, ASCII only H Dump sector, hex only note all dump commands (D, A, H) may be optionally followed by a starting and on CP/M's normal sector scrambling algorithm, i.e. so + will get the next logical sector of the file - backs up 1 logical sector Note + and - may take an amount: for example, +F steps in 15 sectors. Note also that "-" issued at the first logical sector of the disk will wrap back to the last. Further, "+" issued at the last sector will wrap forward to the first. ? Gives command summary ( Toggles display of deleted directory entries. Default on entry is OFF. Deleted did it because I was tired of disk reading after T command before I had a chance to issue the S command) W Write back the current sector (N-O-T-E may not be used after an F command, as CP/M was used to find the file in the directory X Exit back to CP/M (Must press return). Ctl-c was too easy to hit over modem lines, so I decided on 2-byte (X, CR) to exit. P Toggle printer switch on/off Y Yanks current sector into sequential memory and prints ending address. This ple: the following commands will erase the b disk directory to all E5's: lb log in b drive g0 position to dir. ch0-7f,e5 fill with e5 < save the sector >;w;+;/16 restore, write, next, repeat 16 ----This could be shortened to: lb;g0;ch0-7f,e5;< >;w;+;/16 INTERPRETATION OF DIRECTORY DATA PRESENTED BY THE DU PROGRAM The following explains the format of a CP/M directory entry as shown by DU, using either the "F" (find file) command, or just doing "D" (dump) of the di   rectory sectors, which are located in groups 0 and 1 on a single density disk. ---------------- Sample result of "FSID.COM" command: 40 00534944 20202020 20434F4D 0000003A *.SID COM...:* 50 33343536 3738393A 00000000 00000000 *3456789:........* First line - 40 00534944 20202020 20434F4D 0000003A *.SID COM...:* || ||| | || || | | || ||^----hex file name-----^ || || ^file name^ || || || || in ASCIIDU.COM ver 8.0 10/07/83*."m "F}0! 9! "7!0"M*"%"/"b"0Ҟ"" ""K"""A:Fʊ"$Þ*.!"$!"H͈ DISK UTILITY ver 8.0 Universal Version under :G>M>C5͈P/M :F>0:5>.505͈ Type ? for help Type X to exit !~]G]##> !d2?^>2'2(12)>2<!"#]:; ~ ];#l2[+ - =<ʙ>ʵ#p?ʟA C D FI G7 H LMʵN)PʐQ:Rʾ SZ#AOy2A͂> ͈):F>|0^#V+"H! ~#foͿ*iͧ*4|2@͙ *i"0!"2*c#̈́̈́DMm+BK:=N̓*0ͧ*2͘Z ! x}̓^:e͌:f͌{BK9>-5> 2L͹*a#}|͹ z { 9( 9(*, ~|r~> :>(5~E~#͝>.5͝:L5~E~> l>)5Ê͈ ++FREE++ :)2)>:5~~# ګ~ڱ)ô5*c#"8!"J!m+:*#~~!~_#~:bW#p͈ ++EOF++ Ó :>„ 2?͈++Can't dump, no sector read. 2?͈Use G command following F, or R or S following T ]~;ʏ ˜ ë ͬBK ʫ ;ʫ #ͬ`i}E~~:[A ~E}~}~{ #} ]:[H* ̓~  ~ >.5{ #} ̓]{® l{® l~;C G é TZ Sv G 0,*B͘Oͧ>2=Ó ,z0*\͘0͘2=͙ é *i*0͘*\͟*2+:_G}2.:^G̈́¾ ",*^2;::2.- o&", *a͘O",4\~#ͬ#-' ͬ#BK, ,0Hʀ A0~ l;l P ~P V )Y 5"YQ#ym l*Y7 ~ l;l0#~ l;l, "%{Eyʬ l*%€ ~ l;l0:= ͘l2?͈++Can't read - not positioned Position by: Track then Sector, or Group ll><5E>>5:bDxEyN W05 e |\{05> 5>*5]~ +]ã5#~‰#z{ƀ_ɯ2?͈++BAD DISPLACEMENT (NOT 0-7F) ]~#+~ ;, || || extent-^^ || || || || || || file size in sectors-^^ || || || ^^-nn = acvtive file's user area || OR E5 = file erased ^^-displacement of line in directory sector Second line - 50 33343536 3738393A 00000000 00000000 *3456789:........* | | | | ^---allocation group numbers-------^ ctory entry as shown by DU, using either the "F" (find file) command, or just doing "D" (dump) of the di7 T7 UqVʛW#XFY0Zʛ/@(<2?͈?]:*/2*l 2?͈+++ Out of memory +++ ]͈Disk Information: Tracks: *B#\͈ Sec/trk: *\\͈ Grpsize: :_ʺ] xº]¥l!++O l~ Z;*J|>*2L"J *8+"8|*J:G:Nz:>*M!͈LAST ADDR=*M "M+|E}E͈ l2?͈++YANK MEMORY FULL l:>!m>2/l:/!ml2?͈++NO "<" SAVE COMMAND ISSUED ]~#ɯ2>!6 Ó fG~{0:<y*#}Z 2<*2*0͙ͧ͘ !~#"#:> {¬! ~ ~    ~)5,¯ Z *2*0ͧ͘ì2. ͧ͘2=é bk:^)= :.o*\|5 *\*i #>2;\ͫ ͫ \<‹ 2:͈++FILE NOT FOUND l=2:o&))))) >D2[î ~. ; #« ~ ;#.0#>  ~ ; z0Z z *2*0ͧ͘Ó ~ ( ;( z0*2+|M *0|F *B"0*DM +"0*\"2z( *2#*\͘҉ *0#*B͘| "0!"2*B*0͘ڃ *D҃͘ | ͯ l*i*0͘ ͈G=*,DM9>:5:.E>,5͈ T=*0\͈, S=*2\͈, PS=*->#00:A0G00))))o#~ ;,-#00:00bk)))o|g/͈ :!+O ʧʴʴ jw#5j+>*5jw5> 5!ɯ+y~5jje  $6 !~ j5#>^5>U5^> 5> 5`_O N> 5:7>Æ ] ] r:?y r>27~ ~:7<27:+Ċ͂ڢ>͈*B͘O"0BK͂> ͈*i"2*0͘`i͂+:l26:kẄ́#D   M:@8+8*H ͂#>͈&:].g:F8&i"4DM͂J> ͈ɯ2?͈++not within tracks 0-*B\͈++ ]`i"O͂ڕ> È>2>͂ڴc»*O2?͈++READ failed, sector may be invalid++ :>"2?͈++CANNOT WRITE UNLESS READ ISSUED F ͂@cG*O>͈Ca2?͈++WRITE failed++ m> ͈> ͈:6 =|:F0"W"U`i"S2QQ2͈Operands in brackets [...] are optional Numeric values: 'n' are decimal, 'x' hex +[n] stdr,byte,byte... (hex) or CAaddr,data... (Ascii) Allowed for imbedded hex. or CHfrom-thru,byte e.g. ch0-7f,e5 or CAfrom-thru,byte D[ff,tt] Dump (hex+ASCII) Fn.t Find file Gnn CP/M Allocation Group nn H[ff,tt] hex dump L Log in drive Lx Log in drive x M[nn] Map [from group nn] (Type any char. to continue) N New disk P Toggle printer switch Q Quiet mode (no msgs) R Read current sector Snn Sector nn Tnn Track nn Unnge except "/", "T", and "S" are HEX. Use #nn for decimal. See DU.DOC for complete examples. lyz#x}/o|/g#ɷ|g}oғ Ž}o|gBKx¯!ü T]xʼ ò:F\*.:^#"\^#"c~#2^~#2_^#"a^#"e^"i!.~:_w*a "D"Bwxample: g0 +;d;z#20;/ would step in, dump, sleep 2 sec, and repeat until control-c typed. All "nn" usa; DU.ASM V8.1 Revised 10/12/83 ; DISK UTILITY - By Ward Christensen ; ;See DU.DOC for description and detailed instructions. ; ;This version of DU is compatible with CP/M 1.4, 2.x and 3.x ;and does not require alteration for various hardware ;configurations. It adjusts itself automatically to ;the correct number of sectors, tracks, directory size, ;etc. ;This revision is known to run on Magnolia CP/M plus banked, ;North Star 2.2, Morrow hard disk CP/M and others. ; ;Because of the automaticep in [n] sectors; -[n] step out [n] sectors # print disk parameters for curr drive. =xxx search for ASCII xxx from curr sector. Caution: upper/lower case matters. Use for hex: To find "IN 0" use: =<0> or "(tab)H,0(CR)(LF)" use: =<9>H,0 < save current sector into mem. buff. > restore saved sector ( togle map display of erased files ? give help A[ff,tt] ASCII dump (Type any char. to continue) C Change: CHad Set User nn for Find command (CP/M-2 only) V[nn] View [nn] ASCII sectors W Write current sector X Exit program Y Yank current sector into sequential memory Z[nn] Sleep [nn tenths] /[nn] Repeat [nn (decimal) times] (Type any char. to continue) Cancel a function with C or Ctl-C. Suspend output with S or Ctl-S. Separate commands with ";". Example: g0 +;d;z#20;/ would step in, dump, sleep 2 sec, and repeat until control-c typed. All "nn" usa adaption feature, no conditional ;assembly options are included. The only alteration that ;needs to be done is to use DDT to set the byte at 103h ;for your clock speed. Use 0 for 2MHz, 1 for 4MHz, 2 for 6MHz. ;This only affects the SLEEP command. ; ;************************************************* ;* * ;* This program has been heavily modified * ;* to allow it to work without modification * ;* on most versions of CP/M 1.4 and, hopefully, * ;* all versions of CP/M 2.x and 3.x. *    ;* If you have difficulty getting this program * ;* to run, AND if you are using CP/M 2.x or 3.x, * ;* AND if you know your BIOS to be bug-free, * ;* leave a message on Technical CBBS of Dearborn,* ;* Michigan (313)-846-6127 with a description * ;* of the problem and a summary of your hard- * ;* ware configuration. * ;* One known possible problem involves the * ;* system tracks on some systems, and results * ;* from the system sectors being skewed. There * ;* is NO way for a program ister. Again, system tracks with skewed * ;* sectors will be a problem. * ;* If you add any features or make any useful * ;* changes to this program, please modem a copy * ;* to the above CBBS, so the currency of the * ;* program can be maintained. * ;* * ;* Ron Fowler * ;* * ;************************************************* ; ;10/12/83 Fixed minor bug which caused garbage to be sent to ; the printer if CBIOS console output routine did not ; return with the chaon 50 for 3.x BIOS disk calls. ; Added deblocking code for CP/M 3.x disk I/O. ; Flagged all mods with initials (WFM) as comment. ; NOTE: Using BDOS function 50 should work for MP/M, ; if some MP/M user will check code to see if ; it's compatible. ; (WFM) ; ;03/27/83 Modified for use with CP/M plus (version 3.0) ; Re-enabled display of erased files (toggle on/off) ; and suppressed CP/M+ date/time fields. (SFK) ; ;02/05/82 Modified so it will not increment past last ; sectornt errors. Fixed bug in getgrp record counw ; (William Ernest) ; ;01/23/81 Changed SETSEC to ignore high-order result of ; SECTRN if SPT<256. This fixes some translation ; problems where the BIOS leaves garbage in H. (BRR) ; ;01/15/81 Changed labels to be no more than 6 characters ; long. Moved stack. Cleaned up file. (KBP) ; ;01/13/81 Updated help messages for '#' and 'N' commands. ; Modified sign-on message. (RGF) ; ;01/12/81 Fixed problem with sector translation under ; CP/ 'REPEAT' to allow up to 65535 repeats. (RGF) ; ;01/06/81 Modified to allow use with ALL systems, without ; conditional assembly, thru use of disk parameter ; block. By Ron Fowler, Westland, Mich. ; ;01/05/81 Modified '+' and '-' commands as follows: ; 1) + at end of disk now wraps to start ; 2) - at start wraps back to end ; 3) argument for + & - now good to 65535 ; (RGF) ; ;01/03/81 Modified logic in console status test to allow ; any non-zero value to indicate char waiting. ; executing under CP/M * ;* to know about this. This program assumes the * ;* standard convention of no skew being used on * ;: the system tracks. This usually isn't a prob- * ;* lem because the SYSGEN program can be used to * ;* get the system from the disk so that it can * ;* be modified. * ;* This program should work under standard * ;* versions of CP/M 1.4. The only requirement * ;* is that the BIOS "SETSEC" routine not modify * ;* the sector number passed to it in the B * ;* regracter still in the C register - ; inserted a PUSH B before VCONOT: and a POP B after it. ; Bob Clyne ; ;10/07/83 Fixed minor bug in WFM's code which prevented DU ; from working under CP/M 2.2. Verified operation on ; Magnolia CP/M plus banked. Thanks to ; for risking his disks testing the program. ; Changed MHz patch location to allow 6MHz. ; NOTE: ; no changes made to CP/M plus operation. {SFK} ;08/28/83 Modified SFK's CP/M plus fixes so they would work: ; Used BDOS functi usable by CP/M on last track while ; incrementing in. (It does this already ; while incrementing out.) Unused sectors ; are still accessable using "S" command. ; (Harvey Fishman) ; ;07/12/81 Merged DJH vers 7.6 and Bill Ernest ver 7.6 ; to form new vers 7.7 (RGF) ; ;07/07/81 Added "Y" command to allow sectors to be written ; sequentially into memory starting at 3000H, for ; later recovery by DDT, etc. (DJH) ; ;04/02/81 Added * to map showing multiple group assign- ; meM 1.4. (RGF) ; ;01/11/81 Fixed problem with CP/M 1.4. Added 'N' command. ; Hard-code 'FASTCLOCK' as a boolean at 103h. Add ; fix for sector number being 0 in system tracks, ; as suggested by Keith Petersen, W8SDZ. Added '#' ; command and memory-full check. Changed login to ; position to directory track at every log. This ; is necessary to set up the 'FIRST0' flag. (RGF) ; ;01/08/81 Corrected error in MAP routine that caused map ; to fail when >255 groups allocated. Changed ;  (RGF) ; ;01/02/81 Made compatible with MACRO80 assembler (labels ; made unique within 6 chars, and separated multi- ; statement lines). (RGF) ; ;11/14/80 Corrected missing conditional in CLCSUB routine ; for MICROP or DIGDBL. Cleaned up file. (KBP) ; ;11/04/80 Forced write type 1 (pre-read and immediate write) ; so deblocking BIOS's don't mess up. Ignore bit 7 ; in = command unless form was used. Display ; unprintables as in V command. Show user no. ; in M comman   d (will always be 00 for 1.4) and only ; print parentheses if E5 present. (BRR) ; ;10/30/80 Fixed bug in backspace/control-X. Corrected more ; bit-7 stuff. Added 'U' command to change user no. ; under CP/M 2.x. Added pauses in help file. (BRR) ; ;10/27/80 Added Thinkertoys DBL DENS, Micromation DBL DENS, ; Industrial Micro Systems DBL and QUAD DENS. ; Fixed several bit-7 problems in MAP and DUMP logic. ; Added control-X (CRT erase line) to command input ; logic. (Bruce R. Ratoff8SDZ ; ;02/24/80 Mod login command to not really do log, just ; drive select. (WLC) ; ;02/12/80 Mod for heath CP/M. (WLC) ; ;01/08/80 Reposition after 'M' command. (WLC) ; ;01/07/79 Add VIEW command. (WLC) ; ;01/06/80 Rewrite 'F' command. (WLC) ; ;10/10/79 Save regs in BIOS calls, translate input to upper case ; add commands: < save sector ; > restore sect ; / repeat ; allow change from-thru. (WLC) ; ;02/25/79 Put sector read into 'S' command. (WLC) ; ;11/26/78 Add disk  0 ;SET TO 4200H FOR HEATH OR TRS-80 ALTCPM ; FCB EQU BASE+5CH BDOS EQU BASE+5 PRINT EQU 9 GVERS EQU 12 RESETDK EQU 13 SELDK EQU 14 SRCHF EQU 17 ;SEARCH FIRST SUSER EQU 32 GETDSK EQU 25 GETDPB EQU 31 ; bhome equ 8 ;BIOS function numbers (WFM) bseldsk equ 9 ;(WFM) bsettrk equ 10 ;(WFM) bsetsec equ 11 ;(WFM) bsetdma equ 12 ;(WFM) bread equ 13 ;(WFM) bwrite equ 14 ;(WFM) bsectrn equ 16 ;(WFM) ; TRNOFF EQU 15 ;CP/M 1.4 OFFSET FROM BASE ;OF BDOS TO SECTRAN ROUTINE SKWOFF EQU 1AH ;CP/M  DU.COM ; PASTCK: LHLD BDOS+1 ;GET POINTER TO BDOS ENTRY MVI L,0 ;SET HL=BASE OF BDOS SPHL ;PUT STACK THERE SHLD SETSTK+1 ;SAVE FOR LATER LXI SP INSTR. MVI C,GVERS ;GET CP/M VERSION NR CALL BDOS shld verflg ;save version and mpm flag(WFM) mov a,l ;...VERSION NR FOR A FLAG (WFM) CPI 30H ; (WFM) LXI H,10 ;CP/M 2.x dpb offset (WFM) JC NOPLUS ; (WFM) LXI H,12 ;CP/M 3.x dpb offset (WFM) NOPLUS: SHLD DPBOFS ; (WFM) LXI H,3000H ;INITIALIZE "Y" COMMAND MEMORY  SHLD VWRITE+1 ;WRITE LDA verflg ORA A JZ DOCPM1 DAD D ;LISTST DAD D SHLD VSCTRN+1 ;SECTRAN JMP HELLO ; DOCPM1: LHLD BDOS+1 MVI L,0 ;BDOS ON PAGE BOUNDARY xchg ; (WFM) LXI h,TRNOFF ;CP/M 1.4 SECTRAN ROUTINE OFFSET (WFM) DAD D SHLD VSCTRN+1 LXI h,SKWOFF ;CP/M 1.4 SKEW TABLE OFFSET (WFM) DAD D SHLD SECTBL ;SET UP SKEW TABLE POINTER ; HELLO: CALL ILPRT DB CR,LF,'DISK UTILITY ver 8.1',CR,LF DB 'Universal Version under ',0 lda mpmflg ;(WFM) ora a ;(WF, ACGNJ-SIG/M) ; ;09/16/80 Fix backspace in line enter routine, add MAXDIR ; equate, general cleanup of ASM file. (KBP) ; ;06/22/80 Put in 'Q' command. Fix so 'P' (printer) ; mode outputs L/F's. (WLC) ; ;05/21/80 Make sector, track, be decimal, not hex. ; Also dis-allow a read until positioned. ; (DU otherwise not in sync with CP/M) (WLC) ; ;03/24/80 Mod for Micropolis, Digital Microsystems DD, ; and Northstar DD CP/M. Trap out garbage ; during VIEW of file. By Keith Petersen, W# to login command. (WLC) ; ;11/12/78 Add login command. (WLC) ; ;08/06/78 Originally written to reconstruct blown ; disks on CBBS via remote access. (WLC) ; ; ; ---------------- ;Sorry for the lack of comments in the code ;portion of this program - it was just hacked ;together to satisfy my needs, but lots of ;other people found it useful. Its external ;documentation is good, but its sadly lacking ;comments on the instructions. (WLC) ; ---------------- ; ;System equates ; BASE EQU1.4 OFFSET TO SKEW TABLE S2OFF EQU 14 ;OFFSET INTO FCB FOR S2 BYTE DPBOFF EQU 3AH ;CP/M 1.4 OFFSET TO DPB WITHIN BDOS S2MASK EQU 0FH ;MASK FOR EXTENDED RC BITS OF S2 DPBLEN EQU 17 ;SIZE OF CP/M 3.x DISK PARM BLOCK (WFM) ; ;Define ASCII characters ; CR EQU 0DH ;CARRIAGE RETURN LF EQU 0AH ;LINE FEED TAB EQU 09H ;TAB BS EQU 08H ;BACKSPACE ; ORG BASE+100H ; JMP PASTCK ;JUMP OVER CLOCK BYTE AND I.D. ; CLOCK: DB 1 ;<---0= 2MHz, 1=4MHz, 2=6MHz DB 'DU.COM ver 8.1 10/12/83',1AH ;<-- allow TYPEPOINTER SHLD YNKADR ;Set up local jumps to BIOS LHLD BASE+1 ;WARM BOOT POINTER LXI D,3 ;READY FOR ADD DAD D SHLD VCONST+1 ;CONST DAD D SHLD VCONIN+1 ;CONIN DAD D SHLD VCONOT+1 ;CONOUT DAD D SHLD VLIST+1 ;LIST cpi 30h ;CP/M 3.x? (WFM) jnc hello ; (WFM) DAD D ;PUNCH DAD D ;RDR DAD D SHLD VHOME+1 ;HOME DAD D SHLD VSELDK+1 ;SELDSK DAD D SHLD VSETRK+1 ;SETTRK DAD D SHLD VSTSEC+1 ;SETSEC DAD D SHLD VSTDMA+1 ;SETDMA DAD D SHLD VREAD+1 ;READ DAD DM) jz helcpm ;(WFM) mvi a,'M' ;(WFM) jmp helmpm ;(WFM) helcpm mvi a,'C' ;(WFM) helmpm call type ;(WFM) call ilprt ;(WFM) db 'P/M ',0 ;(WFM) LDA verflg ORA A JNZ NO14 MVI A,14H NO14: PUSH PSW RAR ! RAR ! RAR ! RAR ANI 0FH ORI 30H cpi '9'+1 ;(WFM) jc noalph ;(WFM) adi 'A'-'9' ;(WFM) noalph: CALL TYPE MVI A,'.' CALL TYPE POP PSW ANI 0FH ORI 30H CALL TYPE CALL ILPRT DB CR,LF,LF DB 'Type ? for help',CR,LF DB 'Type X to exit' DB CR,LF,0 CALL GET    STP ;SET UP PARAMETERS LXI H,BASE+80H ;TO INPUT BUFF MOV A,M ORA A JZ PRMPTR ;NO COMMAND ; ;Got initial command, set it up MOV B,A ;SAVE LENGTH DCR B JZ PRMPTR LXI D,INBUF INX H ;SKIP LEN INX H ;SKIP ' ' CALL MOVE MVI A,CR STAX D LXI H,INBUF JMP PRMPTI ; PRMPTR: XRA A STA QFLAG CALL RDBUF ; PRMPTI: MVI A,255 STA TOGO ;LOOP COUNT FOR "/" STA TOGO+1 ; PROMPT EQU $ SETSTK: LXI SP,$-$ ;MODIFIED AT INIT XRA A ;ZERO 2-UP PRINT STA TWOUP ;..SWITCH MVI A,1 S JZ RESTOR ; CPI '#' JZ STATS ; CPI '?' JZ HELP ; CPI 'A' JZ DUMP ; CPI 'C' JZ CHG ; CPI 'D' JZ DUMP ; CPI 'F' JZ POSFIL ; CPI 'G' JZ POS ; CPI 'H' JZ DUMP ; CPI 'L' JZ LOGIN ; CPI 'M' JZ MAP ; CPI 'N' JZ NEWDSK ; CPI 'P' JZ PRNTFF ; CPI 'Q' JZ QUIET ; CPI 'R' JZ DOREAD ; CPI 'S' JZ POS ; CPI 'T' JZ POS ; CPI 'U' ;******CP/M 2.x, 3.x ONLY****** JZ USER ; CPI 'V' JZ VIEW ; CPI 'W' JZ DORITE ; CPI 'X' JZ XIT ,0 JMP PRMPTR ; ;Print disk statistics ; STATS: PUSH H CALL ILPRT DB 'Disk Information:',CR,LF DB 'Tracks:',9,9,0 LHLD MAXTRK INX H CALL DEC CALL ILPRT DB CR,LF,'Sec/trk:',9,0 LHLD SPT CALL DEC CALL ILPRT DB CR,LF,'Grpsize:',9,0 LDA BLM INR A MOV L,A MVI H,0 CALL DEC CALL ILPRT DB ' (sectors per group)',CR,LF DB 'Tot grps:',9,0 LHLD DSM CALL DEC CALL ILPRT DB CR,LF,'Dir entries:',9,0 LHLD DRM INX H CALL DEC CALL ILPRT DB CR,LF,'Sys trALL DECIN ;NN SPECIFIED? MOV A,D ORA E JZ NNN ;NO. LHLD TOGO INX H ;TEST FOR FIRST TIME MOV A,H ORA L ;WAS IT 0FFFFH? JNZ NNN ;NO: COUNTING XCHG ;GET COUNT SHLD TOGO ;SET COUNT ; NNN: LHLD TOGO XCHG LXI H,INBUF ;READY TO REPEAT INX D ;TEST FOR 0FFFFH MOV A,D ORA E JZ PROMPT ;CONTINOUS DCX D ;COUNT DOWN DCX D ;MAKE UP FOR PREV INX D XCHG SHLD TOGO MOV A,H ;ALL DONE? ORA L XCHG ;GET BACK INBUF PTR JNZ PROMPT ;NO, KEEP GOING JMP PRMPTR ;ALL DONE ; ;Set CPLDA CLOCK ORA A JZ SLEEP2 LXI B,16000 ;APPROX .1 SEC @ 4 MHz cpi 1 ;{SFK} jz sleep2 ;{SFK} lxi b,24000 ;approx. .1 sec @ 6MHz {SFK} ; SLEEP2: DCX B MOV A,B ORA C JNZ SLEEP2 PUSH D CALL CTLCS POP D JZ PRMPTR DCR E JNZ SLEPLP JMP PROMPT ; ;Check for control-C or S ; CTLCS: CALL CONST ORA A JNZ GETC ORI 1 ;NO CHAR, RETN NZ RET ; GETC: CALL CONIN ANI 1FH ;ALLOW ASCII CPI 'S'-40H CZ CONIN CPI 'C'-40H RET ;0 SET IF CTL-C ; ;Find our way at initializatioTA FTSW ;TELL SEARCH NOT TO INCR PUSH H LXI H,BASE+100H SHLD BUFAD ;FOR RDBYTE POP H CALL CTLCS ;ABORT? JZ PRMPTR ;..YES, READ BUFFER ; ;Do we have to position in directory after find? LDA FINDFL ORA A JNZ POSDIR ;POSITION IN DIRECTORY MOV A,M CPI CR JZ PRMPTR CPI ';' ;LOGICAL CR? INX H JZ PROMPT CALL UPCASE STA DUMTYP ;TYPE OF DUMP (A,D,H) ; ;Command dispatcher ; CPI '+' JZ PLUS ; CPI '-' JZ MINUS ; CPI '=' JZ SEARCH ; CPI '<' JZ SAVE ; CPI '>' ; CPI 'Y' JZ YANK ; CPI 'Z' JZ SLEEP ; CPI '/' JZ REPEAT ; CPI '(' JZ TOGERA ; WHAT: XRA A STA QFLAG CALL ILPRT DB '?',0 JMP PRMPTR ; ; TOGERA - toggle display of ERAsed files ; TOGERA: LDA TOGE CMA STA TOGE JMP PROMPT ; ; eXit - Since CP/M plus doesn't do a warm boot ; at JMP 0000, we have to reset the disk system! ; XIT: MVI C,RESETDK CALL BDOS JMP BASE ; ;Memory full error ; MEMFUL: XRA A STA QFLAG CALL ILPRT DB '+++ Out of memory +++' DB CR,LFacks:',9,0 LHLD SYSTRK CALL DEC CALL CRLF POP H JMP PROMPT ; ;The following command resets the disk ;system thru CP/M, and may be usable for ;changing the disk density or format. ;This can only be done if your BIOS resets ;the auto-density select parameters at ;every track-zero access. ; NEWDSK: PUSH H MVI C,RESETDK CALL BDOS LDA DRIVE MOV C,A POP H CALL SELECT JMP PROMPT ; ;Quiet mode ; QUIET: STA QFLAG ;NOW QUIET JMP PROMPT ; ;Repeat buffer contents ; REPEAT: C/M 2.x, 3.x user number ; USER: LDA verflg ORA A JZ WHAT CALL DECIN ;GET REQUESTED USER NO. MOV A,E CPI 32 ;VALID? JNC WHAT MOV A,D ORA A JNZ WHAT MVI C,SUSER PUSH H ;SAVE CHAR POINTER CALL BDOS ;SET USER NO. POP H JMP PROMPT ; ;Toggle print flag ; PRNTFF: LDA PFLAG XRI 1 STA PFLAG JMP PROMPT ; ;Sleep routine, in tenths of a sec ; SLEEP: CALL HEXIN ;GET COUNT IF ANY MOV A,E ;ANY? ORA A JNZ SLEPLP MVI E,10 ; SLEPLP: LXI B,8000 ;APPROX .1 SEC @ 2MHz n ; GETSTP: MVI C,GETDSK CALL BDOS ;GET CURNT DSK MOV C,A ; WE HAVE TO SELECT JMP SELECT ; TO GET THE DPH ; LOGIN: CALL DOLOG JMP PROMPT ; DOLOG: MOV A,M ;DISK REQ? LXI D,0 CPI CR JZ LGNODK CPI ';' JZ LGNODK CALL UPCASE INX H SUI 'A' MOV C,A ; SELECT: PUSH H MOV A,C STA DRIVE ;REMEMBER LATER WHERE WE ARE call v3chek ;check for version 3.x (WFM) jc vseldk ;jump if 1.x or 2.x (WFM) mvi e,0 ;set first call flag (WFM) mvi a,bseldsk ;select disk function (WFM) !    call bdos50 ;call bios via bdos (WFM) jmp vseld3 ; (WFM) VSELDK: CALL $-$ ;ADDR FILLED IN BY 'INIT' LDA verflg ORA A ;IF NOT CP/M 2.x ... JZ SELSKP ;..THEN SKIP THIS JUNK vseld3: MOV A,H ORA L JZ WHAT ;SELECT ERROR MOV E,M ;GET THE SECTOR TABLE PNTR INX H MOV D,M dcx h ;point to start of dph (WFM) XCHG SHLD SECTBL LXI H,10 ;OFFSET TO DPBPTR DPBOFS: EQU $-2 ;modified during init (WFM) DAD D MOV A,M ;PICK UP DPB POINTER INX H ; TO USE MOV H,M ; AS PARAMEAKE 1-RELATIVE CALL ROTRHL CALL ROTRHL ;DIVIDE BY 4 (4 NAMES/SECTOR) MOV B,H MOV C,L LXI D,DIRECT ;DMA ADDR ; RDIRLP: PUSH B PUSH D MOV B,D MOV C,E LDA BDOS+2 ;CHECK MEM AVAIL DCR A CMP D JC MEMFUL CALL SETDMA LHLD CURTRK XCHG CALL SETTRK LHLD CURSEC XCHG CALL SETSEC CALL READ CALL NXTSEC POP D POP B LXI H,80H DAD D XCHG DCX B MOV A,B ORA C JNZ RDIRLP LXI B,BASE+80H CALL SETDMA POP H RET ; ;Map the directory ; MAP: CALL REDDIR ;READ IPARISON MOV A,L ;WHEN BC REACHES DSM+1.. CMP C ;..THEN WE HAVE EXCEEDED.. JNZ MAPC1 ;..THE DISK CAPACITY.. MOV A,H CMP B ; MAPC1: POP H JZ MAPEND ;..AND WE ARE DONE PUSH H CALL GETGRP ;GET ANOTHER POP D ;SEE IF SAME CALL CTLCS JZ MAPND2 MOV A,D CMP H JNZ MAPDIF MOV A,E CMP L JZ MAPCNT ;SAME, CONTINUE ; ;Different file encountered MAPDIF: DCX B CALL HEXB INX B XCHG CALL MAPNAM JMP MAPDF ; ;End of map ; MAPEND: DCX B ;GET LAST CALL HEXB CALL MAPNAM POTYPE ;SPACE OR STAR POP B MOV A,M ;GET EXT CALL HEX POP H MOV A,M CPI 0E5H MVI A,' ' JNZ MPNSP2 MVI A,')' ; MPNSP2: CALL TYPE ;")" IF ERASED FILE JMP FLIP ; NONAME: CALL ILPRT DB ' ++FREE++ ',0 ; FLIP: LDA TWOUP XRI 1 STA TWOUP JZ CRLF ; DELIM: MVI A,':' CALL TYPE JMP SPACE ; ;Print name, length in B ; MAPN2: MOV A,M ANI 7FH ;STRIP POSSIBLE 2.x ATTRIBUTE BIT INX H CPI ' ' ;PRINTABLE? JC MAPN2H ;..NO, IN HEX CPI 7EH ;7E IS LEADIN ON SOME CRTS 4 ;NOW GET RECORD COUNT DAD D ; S2 PORTION .. MOV A,M ; IS 0 IN CP/M 1.4 ANI 0FH MOV E,A INX H MOV A,M ORA E JZ GETGNF MVI E,16 ;FIRST SET FOR 8-BIT GRPS LDA DSM+1 ORA A JZ SMALGP MVI E,8 ;NOPE, BIG GROUPS ; SMALGP: MOV D,A ;SAVE GRP SIZE INDICATOR ; GETGL2: INX H ;POINTING INTO DM FIELD CALL GRPCMP ;COMPARE BC GP # AGAINST 1 DM FLD JNZ NOTGOT ;JUMP IF FOUND ONE ; ;Found the file ; PUSH H ;SAVE GP PTR LHLD MFPTR MOV A,H ORA L POP H XTHL ;GET ENTRY START & TER MOV L,A ; TO LOGIT ; SELSKP: CALL LOGIT LHLD SYSTRK ;RESET TRACK AND SECTOR XCHG ; TO DIRECTORY CALL SETTRK ; ON EVERY LXI D,1 ; LOGIN CALL SETSEC ; CHANGE LHLD PHYSEC ;THIS LOGIC WILL TELL MOV A,H ; IF FIRST SEC ORA L ; IS PHYSICAL 0 STA FIRST0 CALL CLCSUB POP H ; LGNODK: CALL NORITE RET ; ;Read in the disk directory ; REDDIR: PUSH H CALL NORITE ;POSITIONING LOST LHLD SYSTRK SHLD CURTRK LXI H,1 SHLD CURSEC LHLD DRM ;GET DIR SIZE FROM DPB INX H ;MN DIRECTORY MVI C,0 ;INIT START GRP # LDA AL0 ;READ DIR GRP BITS CALL COLECT ;COLLECT COUNT OF DIR GRPS.. LDA AL1 ;..IN REGISTER C CALL COLECT MVI B,0 ;BC NOW HAS A DEFAULT START GRP # CALL HEXIN PUSH H ;SAVE INBUF PTR MOV A,E ;GET START ORA D ;NOTHING? JZ MAPDF ;..YES, DFLT MOV B,D MOV C,E ; MAPDF: CALL HEXB MVI A,'-' CALL TYPE MVI A,' ' STA DUPFLG CALL GETGRP ;GET GRP(C) TO HL ; MAPCNT: INX B ;NEXT GRP # PUSH H LHLD DSM ;GET HIGHEST GRP # INX H ;PLUS 1 FOR COMP H CALL CRLF ; ;End of map - reposition to previous group ; MAPND2: PUSH H LHLD GROUP XCHG JMP POSGP2 ; ;Print file name pointed to by HL ; MAPNAM: CALL SPACE MOV A,H ORA L ;NONE? JZ NONAME MOV A,M ;SEE IF ALLOC CPI 0E5H ;FREE? MVI A,' ' JNZ MPNSP1 MVI A,'(' ; MPNSP1: CALL TYPE PUSH H ;SAVE POINTER MOV A,M CALL HEX ;SHOW USER NUMBER CALL SPACE INX H ;SKIP USER BYTE PUSH B MVI B,8 CALL MAPN2 MVI A,'.' CALL TYPE MVI B,3 CALL MAPN2 LDA DUPFLG CALL JC MAPN2A ; MAPN2H: CALL BHEX JMP MAPN2Z ; MAPN2A: CALL TYPE ; MAPN2Z: DCR B JNZ MAPN2 RET ; ;Find which file group (BC) belongs to ; GETGRP: LHLD DRM ;MAX DIR ENTRY # INX H ;MAKE 1-RELATIVE SHLD FILECT LXI H,0 SHLD MFPTR LXI H,DIRECT ; GETGLP: PUSH H ;SAVE POINTER TO NAME PUSH H LDA TOGE ORA A JZ SKERA INX H SKERA: MOV A,M ;PICK UP DN BYTE POP H CPI 0E5H JZ GETGNF MOV A,M ;this code for CP/M+ only... CPI 21H ;suppress time/date field... JZ GETGNF LXI D,1SAVE PTR JZ MPFRST MVI A,'*' STA DUPFLG MPFRST: SHLD MFPTR XTHL ;AS THEY WERE NOTGOT: DCR E ;ELSE COUNT DOWN JNZ GETGL2 ;GO TEST SOME MORE ; GETGNF: POP H ;NOT THIS ONE! LXI D,32 ;SO GO TO NEXT DAD D XCHG LHLD FILECT ;THERE IS LIMIT TO EVERYTHING DCX H SHLD FILECT MOV A,H ORA L XCHG ;RE-ALIGN JNZ GETGLP ; ;Get the allocation address, if {ny LHLD MFPTR RET ; ;Yank the current sector into memory at location YNKADR ; YANK: LDA 7 ;GET TOP BYTE OF CCP POINTER MOV B!   ,A LDA YNKADR+1 ;GET TOP BYTE OF MEMORY POINTER CMP B JNC YMFULL ;IF MEMORY FULL, THEN SAY SO AND ABORT YANK LDA WRFLG ;CHECK IF A READ HAS BEEN DONE ORA A JZ BADW ;IF NO READ, THEN CAN'T YANK, SO ABORT YANK PUSH H LHLD YNKADR ;MOVE SECTOR INTO YANK MEMORY XCHG LXI H,BASE+80H MVI B,128 CALL MOVE CALL ILPRT ;TELL WHERE LAST BYTE IS DB 'LAST ADDR=',0 LHLD YNKADR ;CALCULATE LAST BYTE LXI B,80H DAD B SHLD YNKADR ;SAVE LAST BYTE+1 FOR NEXT YANK DCX H MOV A,H CALL HEX MAVE PUSH H LXI H,SAVBUF LXI D,BASE+80H MVI B,128 CALL MOVE POP H JMP PROMPT ; NOSAVE: XRA A STA QFLAG CALL ILPRT DB '++NO "<" SAVE COMMAND ISSUED' DB CR,LF,0 JMP PRMPTR ; ;Move (HL) to (DE) length in B ; MOVE: MOV A,M STAX D INX H INX D DCR B JNZ MOVE RET ; NORITE: XRA A ;GET 0 STA WRFLG ;CAN'T WRITE NOW RET ; ;No match in search, try next char ; SRNOMT: POP H CALL CTLCS ;ABORT? JNZ SEARCH ;..YES LXI H,INBUF MVI M,CR JMP CLCGRP ;SHOW WHERE STOPPE '= AT ',0 LDA BUFAD ANI 7FH CALL HEX CALL CRLF JMP CLCGRP ; ;Get value from input buffer ; GETVAL: MOV A,M CPI '<' ;HEX ESCAPE? RNZ ;NO, RETURN ;"<<" means one "<" INX H MOV A,M CPI '<' RZ ;Got hex PUSH D CALL HEXIN ;GET VALUE CPI '>' ;PROPER DELIM? MOV A,E ;GET VALUE POP D JNZ WHAT ;ERROR RET ; ;Read a byte at a time ; RDBYTE: PUSH H LDA FTSW ;FIRST READ? ORA A JNZ READ1 LHLD BUFAD MOV A,L ORA A ;IN BUFFER? JM NORD ;YES, SKIP READ ; ;Have to r A,M CPI 1AH JZ VEWEOF ANI 7FH CPI 7EH JNC VIEWHX ;SHOW RUBOUT AND TILDE AS HEX CPI ' ' JNC VIEWPR CPI CR JZ VIEWPR CPI LF JZ VIEWPR CPI TAB JZ VIEWPR ; VIEWHX: MOV A,M ;NOT ASCII...PRINT AS CALL BHEX JMP VIEWNP ; VIEWPR: CALL TYPE ; VIEWNP: INR L JNZ VEWCHR DCR E JZ VEWEND PUSH D ;SAVE COUNT CALL NXTSEC LHLD CURSEC XCHG CALL SETSEC LHLD CURTRK XCHG CALL SETTRK CALL READ POP D ;RESTORE COUNT JMP VIEWLP ; VEWEOF: CALL ILPRT DB CR,LF,TAV B,D MOV C,E CPI CR JZ DUMP1 CPI ';' JZ DUMP1 INX H ;SKIP ',' CALL DISP ; ;BC = start, DE = end ; DUMP1: PUSH H ;SAVE COMMAND POINTER MOV H,B MOV L,C ; DUMPLP: MOV A,L ANI 7FH CALL HEX CALL SPACE CALL SPACE LDA DUMTYP CPI 'A' JZ DUMPAS PUSH H ;SAVE START ; DHEX: MOV A,M CALL HEX MOV A,L ANI 3 CPI 3 CZ SPACE MOV A,L ANI 7 CPI 7 CZ SPACE MOV A,E CMP L JZ DPOP INX H MOV A,L ANI 0FH JNZ DHEX ; DPOP: CALL CTLCS JZ PRMPTR LDA DUMTYP OV A,L CALL HEX CALL ILPRT DB CR,LF,0 POP H JMP PROMPT ; YMFULL: XRA A ;MEMORY FULL, SO SAY SO STA QFLAG ;SET TO NOT QUIET MODE FIRST CALL ILPRT DB '++YANK MEMORY FULL' DB CR,LF,0 JMP PROMPT ; ;Save the current sector ; SAVE: LDA WRFLG ORA A JZ BADW ;NONE TO SAVE PUSH H LXI H,BASE+80H LXI D,SAVBUF MVI B,128 CALL MOVE MVI A,1 ;..SHOW STA SAVEFL ;..SAVED EXISTS POP H JMP PROMPT ; ;Restore the current sector ; RESTOR: LDA SAVEFL ORA A JZ NOSAVE ;NONE TO SD ; ;Search for character string ; SEARCH: PUSH H ;SAVE STRING POINTER ; SRCHL: CALL RDBYTE ;GET A BYTE MOV B,A ;SAVE IT MOV A,M ;CHECK NEXT MATCH CHAR. CPI '<' ;WILL IT BE HEX? MOV A,B ;RESTORE DISK CHAR JZ SRCHL1 ANI 7FH ;NEXT CHAR IS ASCII...STRIP BIT 7 ; SRCHL1: PUSH PSW CALL GETVAL ;GET SEARCH VALUE MOV B,A POP PSW CMP B ;MATCH? JNZ SRNOMT ;NO MATCH INX H MOV A,M ;DONE? CPI CR JZ SREQU CPI ';' JNZ SRCHL ; ;Got match SREQU: XRA A STA QFLAG CALL ILPRT DBead CALL NXTSEC ; READ1: XRA A STA FTSW ;NOT FIRST READ LHLD CURSEC XCHG CALL SETSEC LHLD CURTRK XCHG CALL SETTRK CALL READ CALL CLCSUB LXI H,BASE+80H ; NORD: MOV A,M INX H SHLD BUFAD POP H RET ; ;View the file in ASCII starting at ;current sector, stepping thru the disk ; VIEW: LDA WRFLG ORA A JZ BADDMP CALL HEXIN ;GET DISPL IF ANY PUSH H MOV A,E ORA A JNZ VIEWLP INR E ;DFLT=1 ; VIEWLP: LXI H,BASE+80H ;TO DATA ; VEWCHR: CALL CTLCS JZ VEWEND MOVB,'++EOF++',CR,LF,0 ; VEWEND: POP H CALL CRLF JMP CLCGRP ; ;Dump in hex or ASCII ; DUMP: LDA WRFLG ORA A JNZ DUMPOK ; BADDMP: XRA A STA QFLAG CALL ILPRT DB '++Can''t dump, no sector read.',CR,LF,0 ; EXPL: XRA A STA QFLAG CALL ILPRT DB 'Use G command following F,',CR,LF DB 'or R or S following T',CR,LF,0 JMP PRMPTR ; DUMPOK: MOV A,M CPI ';' JZ DUMPDF ;DFLT CPI CR JNZ DMPNDF ; ;Use default DUMPDF: LXI B,BASE+80H LXI D,0FFH JMP DUMP1 ; DMPNDF: CALL DISP MO CPI 'H' JZ DNOAS ;HEX ONLY POP H ;GET START ADDR ; DUMPAS: CALL ASTER ; DCHR: MOV A,M ANI 7FH CPI ' ' JC DPER CPI 7EH JC DOK ; DPER: MVI A,'.' ; DOK: CALL TYPE MOV A,E CMP L JZ DEND INX H MOV A,L ANI 0FH JNZ DCHR ; DEND: CALL ASTER CALL CRLF PUSH D CALL CTLCS POP D JZ PRMPTR MOV A,E CMP L JNZ DUMPLP POP H JMP PROMPT ; DNOAS: POP B CALL CRLF MOV A,E CMP L JNZ DUMPLP POP H JMP PROMPT ; ;Position ; POS: PUSH PSW MOV A,M CPI ';' "    JZ POSINQ CPI CR JNZ POSOK ; POSINQ: POP PSW JMP INQ ; POSOK: POP PSW CPI 'T' JZ POSTKD CPI 'S' JZ POSSCD CPI 'G' JZ POSGPH JMP WHAT ; POSTKD: CALL DECIN ; POSTRK: PUSH H LHLD MAXTRK CALL SUBDE POP H JC OUTLIM CALL SETTRK CALL NORITE ;TRACK DOESN'T READ MVI A,1 STA NOTPOS ;SHOW NOT POSITIONED JMP CLCGRP ; POSSCD: CALL DECIN MOV A,D ORA E JZ WHAT ;DON'T ALLOW SECTOR 0 ; POSSEC: PUSH H LHLD SPT CALL SUBDE POP H JC WHAT CALL SETSEC CALL READ A STA FINDFL ;CANCEL POS REQ LDA DIRPOS ;GET POSITION RAR RAR PUSH PSW ANA H STA GRPDIS POP PSW ; POSDLP: RAR DCR L JNZ POSDLP ANI 1 ;GET GROUP MOV L,A ;SETUP FOR POSGP2 MVI H,0 SHLD GROUP XCHG JMP POSGP2 ;POSITION TO IT ; POSGPH: CALL HEXIN ; POSGRP: PUSH H LHLD DSM CALL SUBDE POP H JC OUTLIM XCHG SHLD GROUP XCHG XRA A STA GRPDIS PUSH H ; POSGP2: CALL GTKSEC CALL SETTRK XCHG CALL SETSEC CALL READ XRA A STA NOTPOS ;NOW POSITIONED POP L MVNAME MVI B,3 CALL MVNAME LXI D,FCB MVI C,SRCHF PUSH H CALL BDOS INR A JNZ FLOK STA DIRPOS ;GRP 0 IF NOT FOUND CALL ILPRT DB '++FILE NOT FOUND',CR,LF,0 POP H JMP PROMPT ; FLOK: DCR A STA DIRPOS ;SAVE POS. IN DIR ANI 3 MOV L,A MVI H,0 DAD H ;X32 BYTES/ENTRY DAD H DAD H DAD H DAD H LXI D,BASE+80H DAD D ;HL POINTS TO ENTRY LXI D,32 XCHG DAD D XCHG MVI A,'D' STA DUMTYP JMP DUMPLP ;WHICH POPS H ; MVNAME: MOV A,M CPI '.' JZ MVIPAD CPI CR ed to sector. Setup and read ; PLUSMI: PUSH H LHLD CURSEC XCHG CALL SETSEC LHLD CURTRK XCHG CALL SETTRK POP H CALL READ JMP CLCGRP ; MINUS: LXI D,1 ;SET DFLT MOV A,M ;GET CHAR CPI CR ;CR? JZ MINGO ;..YES, DFLT=1 CPI ';' JZ MINGO CALL HEXIN ;..NO, GET ## MOV A,D ORA E JZ WHAT ; MINGO: PUSH H LHLD CURSEC DCX H MOV A,H ORA L JNZ MINOK LHLD CURTRK MOV A,H ORA L JNZ SEASH LHLD MAXTRK ;WRAP TO END OF DISK SHLD CURTRK LHLD MAXSEC JMP MINOK ; SEXCHG ; LHLD CURTRK ; CALL SUBDE ; POP H ;GET NEW CURRENT SECTOR BACK JC NEXTOK ;IF NOT ON LAST TRACK XCHG ;ELSE, SEE IF WE ARE PAST LHLD MAXSEC ; LAST CP/M USABLE SECTOR CALL SUBDE ; XCHG ; JNC NEXTOK ;IF NOT PAST LAST USABLE SECTOR LXI D,0 ;ELSE, WRAP TO START OF DISK JMP TRASK ; ; ;Tell what group, displacement, track, sector, physical sector ; INQ: CALL INQSUB JMP PROMPT ; ;Position inquiry subroutine ;Executed via: G S or T (with no operands) ; INQSUB: PUSH H LHLD XRA A STA NOTPOS ;POSITIONED OK ; CLCGRP: CALL CLCSUB JMP INQ ; ;Calculate group from track and sector ; CLCSUB: PUSH H LHLD SYSTRK XCHG LHLD CURTRK CALL SUBDE XCHG LHLD SPT CALL MULT XCHG LHLD CURSEC DCX H DAD D LDA BLM MOV B,A MOV A,L ANA B STA GRPDIS LDA BSH MOV B,A ; CLCLOP: CALL ROTRHL DCR B JNZ CLCLOP SHLD GROUP POP H RET ; ;Position in the directory after a find ;(Does not work in CP/M-2.x) ; POSDIR: PUSH H ;SAVE INBUF LHLD BSH XRA H JMP INQ ; GTKSEC: MOV H,D MOV L,E LDA BSH ; GLOOP: DAD H DCR A JNZ GLOOP LDA GRPDIS ADD L ;CAN'T CARRY MOV L,A ; ;Divide by nr of sectors, quotient=track, remainder=sector ; XCHG LHLD SPT CALL NEG XCHG LXI B,0 ; DIVLP: INX B DAD D JC DIVLP DCX B XCHG LHLD SPT DAD D PUSH H LHLD SYSTRK DAD B XCHG POP H INX H RET ; POSFIL: CALL NORITE MVI A,1 STA FINDFL ;SO WE POSITION LATER LXI D,FCB XRA A ;LOGGED IN DISK STAX D INX D MVI B,8 CAL JZ PAD CPI ';' JZ PAD CALL UPCASE STAX D INX H INX D DCR B JNZ MVNAME MOV A,M CPI CR RZ CPI ';' RZ INX H CPI '.' RZ JMP WHAT ; MVIPAD: INX H ; PAD: MVI A,' ' STAX D INX D DCR B JNZ PAD RET ; PLUS: LXI D,1 ;DFLT TO 1 SECT MOV A,M ;GET NEXT CHAR CPI CR ;CR? JZ PLUSGO ;..YES, DFLT TO 1 CPI ';' JZ PLUSGO CALL HEXIN ;GET # MOV A,D ORA E JZ WHAT ; PLUSGO: CALL NXTSEC DCX D ;MORE TO GO? MOV A,D ORA E JNZ PLUSGO ;..YES ; ;Ok, incrementASH: DCX H SHLD CURTRK LHLD SPT ; MINOK: SHLD CURSEC POP H DCX D MOV A,D ORA E JNZ MINGO JMP PLUSMI ; ;Go to next sector ; NXTSEC: PUSH H PUSH D LHLD CURSEC INX H XCHG LHLD SPT CALL SUBDE XCHG JNC CHKLST LHLD CURTRK INX H XCHG LHLD MAXTRK CALL SUBDE JNC TRASK LXI D,0 ;WRAP TO START OF DISK ; TRASK: XCHG SHLD CURTRK LXI H,1 ; NEXTOK: SHLD CURSEC POP D POP H RET ; CHKLST: PUSH H ;SAVE NEW CURRENT SECTOR LHLD MAXTRK ;ARE WE ON LAST TRACK?  SYSTRK XCHG LHLD CURTRK CALL SUBDE JC NOGRP CALL ILPRT DB 'G=',0 LHLD GROUP MOV B,H MOV C,L CALL HEXB MVI A,':' CALL TYPE LDA GRPDIS CALL HEX MVI A,',' CALL TYPE ; NOGRP: CALL ILPRT DB ' T=',0 LHLD CURTRK CALL DEC CALL ILPRT DB ', S=',0 LHLD CURSEC CALL DEC CALL ILPRT DB ', PS=',0 LHLD PHYSEC CALL DEC CALL CRLF POP H RET ; CHG: MOV A,M ;GET TYPE (HEX, ASCII) CALL UPCASE PUSH PSW ;SAVE "H" OR "A" INX H CALL DISP ;GET, VALIDATE DISP TO D"   E INX H LXI B,0 ;SHOW NO 'THRU' ADDR CPI '-' ;TEST DELIM FR. DISP JNZ CHGNTH ;NO THRU PUSH D ;SAVE FROM CALL DISP ;GET THRU INX H ;SKIP END DELIM MOV B,D MOV C,E ;BC = THRU POP D ;GET FROM JMP CHGAH ; CHGNTH: CPI ',' JNZ WHAT ; CHGAH: POP PSW CPI 'H' JZ CHGHEX CPI 'A' JNZ WHAT ; ;Change ASCII CHGALP: MOV A,M CPI CR JZ PROMPT CPI ';' JZ PROMPT LDAX D CPI ' ' JC CHGAHX CPI 7EH JNC CHGAHX JMP CHGA2 ; CHGAHX: CALL BHEX JMP CHGA3 ; CHGA2: CALL TYPEIM MOV A,E ;GET VALUE POP D ;..ADDR PUSH PSW ;SAVE VALUE LDAX D ;GET OLD CALL HEX ;ECHO IN HEX POP PSW ;GET NEW STAX D ;SAVE NEW MOV A,C ;SEE IF 'THRU' ORA A JZ CHHNTH ;..NO. CMP E ;..YES, DONE? JZ PROMPT LHLD HEXAD ;..NO: MORE ; CHHNTH: INR E JNZ CHGHEX MOV A,M CPI CR JZ PROMPT CPI ';' JZ PROMPT JMP WHAT ; DOREAD: LDA NOTPOS ORA A JNZ CANTRD CALL READ JMP PROMPT ; CANTRD: XRA A STA QFLAG ;NOT QUIET CALL ILPRT DB '++Can''t read - not positioned',CRH LXI B,-10 LXI D,-1 ; DECOU2: DAD B INX D JC DECOU2 LXI B,10 DAD B XCHG MOV A,H ORA L CNZ DEC MOV A,E ADI '0' CALL TYPE POP H POP D POP B RET ; SPACE: MVI A,' ' JMP TYPE ; ASTER: MVI A,'*' JMP TYPE ; ;Inline print routine ; ILPRT: XTHL ; ILPLP: CALL CTLCS ;ABORT? JZ PRMPTR MOV A,M CPI 1 ;PAUSE? JNZ ILPOK CALL CONIN CPI 3 ;ABORT? JZ PRMPTR JMP ILPNX ; ILPOK: CALL TYPE ; ILPNX: INX H MOV A,M ORA A JNZ ILPLP INX H XTHL RET ; ;R RZ CPI ';' RZ CPI ',' RZ CPI '-' ;'THRU'? RZ CPI '>' RZ INX H CPI '0' JC WHAT CPI '9'+1 JC HINNUM CPI 'A' JC WHAT CPI 'F'+1 JNC WHAT SUI 7 ; HINNUM: SUI '0' XCHG DAD H DAD H DAD H DAD H ADD L MOV L,A XCHG JMP HINLP ; HDIN: INX H ;SKIP '.' ; DECIN: LXI D,0 ; DINLP: MOV A,M CALL UPCASE CPI CR RZ CPI ';' RZ CPI ',' RZ CPI '-' ;'THRU'? RZ INX H CPI '0' JC WHAT CPI '9'+1 JNC WHAT SUI '0' PUSH H MOV H,D MOV L,E  H INR B JM FULL CALL TYPE JMP RDBLP ; FULL: DCR B DCX H MVI A,'*' ;SIGNAL WE'RE FULL CALL TYPE JMP RDBLP ; ;Got CR ; RDCR: MOV M,A ;SAVE IT CALL TYPE ;ECHO IT MVI A,LF ;ECHO.. CALL TYPE ;..LF LXI H,INBUF RET ; ;Got DELETE or BS, echo if BS ; RDBS: XRA A ;AT FRONT.. ORA B ;..OF LINE? JZ RDCTLU ;..YES, ECHO ^U DCX H DCR B MOV A,C CPI 'H'-40H ;BS? JZ BACKUP ;ECHO THE BS MOV A,M ;ECHO.. CALL TYPE ;..DELETED CHAR JMP RDBLP ; BACKUP: CALL WIPER JMP RDBL ; CHGA3: SHLD BACK ;IN CASE "THRU" CALL GETVAL ;ASCII OR STAX D ;UPDATE CHAR INX H ;TO NEXT INPUT CHAR ;See if 'THRU' requested MOV A,C ORA A JZ CHANTH CMP E ;DONE?.. JZ PROMPT ;..YES LHLD BACK ; CHANTH: INR E JNZ CHGALP MOV A,M CPI CR JZ PROMPT CPI ';' JZ PROMPT JMP WHAT ; ;Change hex ; CHGHCM: INX H ; CHGHEX: MOV A,M CPI CR JZ PROMPT CPI ';' JZ PROMPT CPI ',' ;DELIM? JZ CHGHCM PUSH D SHLD HEXAD ;IN CASE 'THRU' CALL HEXIN ;POSITIONS TO DEL,LF DB 'Position by:',CR,LF DB 9,'Track then Sector, or',CR,LF DB 9,'Group',CR,LF,0 JMP PROMPT ; DORITE: CALL WRITE JMP PROMPT ; BHEX: PUSH PSW MVI A,'<' CALL TYPE POP PSW CALL HEX MVI A,'>' CALL TYPE RET ; HEXB: LDA DSM+1 ORA A JZ HEXX MOV A,B CALL HEX ; HEXX: MOV A,C ; HEX: PUSH PSW RAR RAR RAR RAR CALL NIBBL POP PSW ; NIBBL: ANI 0FH CPI 10 JC HEXNU ADI 7 ; HEXNU: ADI '0' JMP TYPE ; ;Decimal output routine ; DEC: PUSH B PUSH D PUSH DISP calls HEXIN, and validates a sector ;displacement, then converts it to an address ; DISP: CALL HEXIN PUSH PSW ;SAVE DELIMITER MOV A,D ORA A JNZ BADISP MOV A,E ORA A JM BADISP ADI 80H ;TO POINT TO BUFFER AT BASE+80H MOV E,A MVI D,BASE/256 POP PSW ;GET DELIM RET ; BADISP: XRA A STA QFLAG CALL ILPRT DB '++BAD DISPLACEMENT (NOT 0-7F)' DB CR,LF,0 JMP PRMPTR ; HEXIN: LXI D,0 MOV A,M CPI '#' ;DECIMAL? JZ HDIN ;MAKE DECIMAL ; HINLP: MOV A,M CALL UPCASE CPI C DAD H ;X2 DAD H ;X4 DAD D ;X5 DAD H ;X10 ADD L MOV L,A MOV A,H ACI 0 MOV H,A XCHG POP H JMP DINLP ; ;Read in a console buffer full ; RDBUF: CALL ILPRT DB CR,LF,':',0 ; RDBF1: LXI H,INBUF MVI B,0 ; RDBLP: CALL CONIN MOV C,A ;SAVE FOR BS TEST ; ;Evaluate control characters ; CPI 'U'-40H JZ RDCTLU ; CPI CR JZ RDCR ; CPI 'H'-40H JZ RDBS ; CPI 7FH JZ RDBS ; CPI 'R'-40H JZ RDCTLR ; CPI 'X'-40H JZ RDCTLX ; CPI ' ' JC RDBLP ; MOV M,A INXP ; RDCTLX: INR B ; RDCX1: DCR B JZ RDBF1 CALL WIPER JMP RDCX1 ; WIPER: PUSH B PUSH D PUSH H LXI D,BSMSG ;BACKSPACE, SPACE, BACKSPACE MVI C,PRINT CALL BDOS POP H POP D POP B RET ; BSMSG: DB BS,' ',BS,'$' ; ;Got CTL-R, retype ; RDCTLR: MVI M,CR CALL CRLF LXI H,INBUF MVI B,0 ; RDCRL: MOV A,M CPI CR JZ RDBLP CALL TYPE INR B INX H JMP RDCRL ; ;Got CTL-U or backup to beginning of line. ; RDCTLU: MVI A,'^' CALL TYPE MVI A,'U' CALL TYPE JMP RDBUF #    ; CRLF: MVI A,CR CALL TYPE MVI A,LF JMP TYPE ; UPCASE: CPI 60H RC ANI 5FH ;MAKE UPPER CASE RET ; CONST: PUSH B PUSH D PUSH H VCONST: CALL $-$ ;ADDR FILLED IN BY 'INIT' POP H POP D POP B RET ; CONIN: PUSH B PUSH D PUSH H VCONIN: CALL $-$ ;ADDR FILLED IN BY 'INIT' POP H POP D POP B RET ; ;Console out with TAB expansion ; TYPE: PUSH B PUSH D PUSH H MOV C,A ;FOR OUTPUT ROUTINE CPI TAB JNZ TYPE2 ; TYPTAB: MVI A,' ' CALL TYPE LDA TABCOL ANI 7 JN COL LDA TABCOL INR A STA TABCOL ; TYPLST: LDA PFLAG ANI 1 CNZ LIST ;FROM C REG. ; TYPRET: POP H POP D POP B RET ; LIST: PUSH B ;SAVED REGS PUSH D PUSH H VLIST: CALL $-$ ;ADDR FILLED IN BY 'INIT' POP H POP D POP B RET ; HOME: PUSH H call v3chek ;check for version 3.x (WFM) jc vhome ;for 1.x or 2.x (WFM) mvi a,bhome ;BIOS function number (WFM) call bdos50 ;call BIOS via BDOS (WFM) pop h ; (WFM) ret ; (WFM) VHOME: CALL $-$ ;ADDR FILLED IN BY 'INIE POP B MOV H,B MOV L,C push psw ;save flags (WFM) call v3chek ;check for version 3.x (WFM) jc setse0 ;for 1.x or 2.x (WFM) dcx h ;scale sect # to 0 (WFM) lda phm ;physical sector mask (WFM) ana l ;a=log. sect in buffer (WFM) sta logsec ;save for later (WFM) push d ; (WFM) lda psh ;phys sector shift cnt (WFM) ora a ;check for no shift (WFM) jz setse1 ;jump if none (WFM) mov d,a ;loop count in d (WFM) setse2: call rotrhl ;shift sect no right (WFM) dcr d ;dM) jc vsctrn ;for 1.x or 2.x (WFM) mvi a,bsectrn ;BIOS function number (WFM) call bdos50 ;call BIOS via BDOS (WFM) jmp vsctr3 ; (WFM) VSCTRN: CALL $-$ ;ADDR FILLED IN BY 'INIT' vsctr3: LDA SPT+1 ;IF SPT<256 (HI-ORD = 0) ORA A ; THEN FORCE 8-BIT TRANSLATION JNZ VSCTR1 ; ELSE KEEP ALL 16 BITS MOV H,A ; VSCTR1: LDA verflg ;SEE IF VERSION 2.x ORA A ;SET FLAGS JNZ GSTSEC ;JUMP IF CP/M 2.x MVI H,0 ;CP/M 1.4 GOOD TO ONLY 8 BITS MOV L,C ;MOST BIOS'S RETURN THE ; PHYSICL DEC POP H CALL ILPRT DB '++' DB CR,LF,0 CALL NORITE JMP PRMPTR ; SETDMA: push h ;save hl (WFM) mov h,b ;get dma address in hl (WFM) mov l,c ; (WFM) shld dmaadr ;save for later (WFM) pop h ;restore hl (WFM) call v3chek ;check for version 3.x (WFM) jc vstdma ;for 1.x or 2.x (WFM) mvi a,bsetdma ;BIOS function number (WFM) jmp bdos50 ;call BIOS via BDOS (WFM) vstdma: JMP $-$ ;ADDR FILLED IN BY 'INIT' ; READ: MVI A,1 STA WRFLG PUSH H call v3chek ;check forNZ TYPTAB JMP TYPRET ; ;Filter out control characters to ;prevent garbage during view of file ; TYPE2: CPI ' ' JNC TYPEQ CPI CR JZ TYPEQ CPI LF JNZ TYPNCR ; TYPEQ: LDA QFLAG ORA A PUSH B ;Save char. some CBIOS's clobber the reg. (RAC) VCONOT: CZ $-$ ;ADDR FILLED IN BY 'INIT' POP B ;Retrieve the char. (RAC) ; ;Update column used in tab expansion MOV A,C ;GET CHAR CPI CR JNZ TYPNCR MVI A,0 STA TABCOL JMP TYPLST ; TYPNCR: CPI ' ' ;CTL CHAR? JC TYPLST ;..NO CHANGE IT' POP H RET ; ;Set track # in DE ; SETTRK: PUSH H LHLD MAXTRK CALL SUBDE POP H JC OUTLIM XCHG SHLD CURTRK XCHG MOV B,D MOV C,E PUSH H call v3chek ;check for version 3.x (WFM) jc vsetrk ;for 1.x or 2.x (WFM) mvi a,bsettrk ;BIOS function number (WFM) call bdos50 ;call BIOS via BDOS (WFM) pop h ; (WFM) ret ; (WFM) VSETRK: CALL $-$ ;ADDR FILLED IN BY 'INIT' POP H RET ; SETSEC: PUSH H PUSH D LHLD SYSTRK XCHG SHLD CURSEC LHLD CURTRK CALL SUBDecrement loop count (WFM) jnz setse2 ;loop until done (WFM) setse1: pop d ; (WFM) inx h ;scale sect # to 1 (WFM) mov b,h ;repeat number in bc (WFM) mov c,l ; (WFM) ; moved next label up 1 line to remove 2.2 stack crash {SFK} setse0: pop psw ;restore flags {SFK} JNC NOTSYS LDA FIRST0 ;SEE IF FIRST SEC 0 ORA A JNZ GSTSEC ;NO, JUMP AWAY DCX H ;YES, SO DECREMENT JMP GSTSEC ; REQUESTED, THEN GO ; NOTSYS: LHLD SECTBL XCHG DCX B call v3chek ;check for version 3.x (WFAL SEC # IN REG C GSTSEC: SHLD PHYSEC ;THIS MAY BE REDUNTANT IN ; MOST 1.4 VERSIONS, BUT ; SHOULD CAUSE NO PROBLEMS MOV B,H MOV C,L call v3chek ;check for version 3.x (WFM) jc vstsec ;for 1.x or 2.x (WFM) mvi a,bsetsec ;BIOS function number (WFM) call bdos50 ;call BIOS via BDOS (WFM) pop h ; (WFM) ret ; (WFM) VSTSEC: CALL $-$ ;ADDR FILLED IN BY 'INIT' POP H RET ; OUTLIM: XRA A STA QFLAG CALL ILPRT DB '++not within tracks 0-',0 PUSH H LHLD MAXTRK CAL version 3.x (WFM) jc vread ;for 1.x or 2.x (WFM) call read3 ;read a physical sector (WFM) jnz rderr ;if error on read (WFM) xchg ;sector address to de (WFM) lhld dmaadr ;dma address to hl (WFM) xchg ;reverse addresses for: (WFM) call move ;move (WFM) pop h ;read finished (WFM) ret ; (WFM) VREAD: CALL $-$ ;ADDR FILLED IN BY 'INIT' ORA A JZ READOK rderr: XRA A STA QFLAG CALL ILPRT DB '++READ failed, sector may be invalid++' DB CR,LF,0 ; READOK: POP H RET#    ; WRITE: LDA WRFLG ORA A JNZ PWRITE ; BADW: XRA A STA QFLAG CALL ILPRT DB '++CANNOT WRITE UNLESS READ ISSUED' DB CR,LF,0 JMP EXPL ; PWRITE: PUSH H MVI C,1 ;FORCE WRITE TYPE 1 IN CASE 2.x DEBLOCK USED call v3chek ;check for version 3.x (WFM) jc vwrite ;for 1.x or 2.x (WFM) call read3 ;get physical sector (WFM) jnz wrerr ;if error (WFM) xchg ;sector address to de (WFM) lhld dmaadr ;dma address to hl (WFM) call move ;move data to buffer (WFM) mvi a,bwrite ;BIOS ora a ;check error code (WFM) rnz ;return if error (WFM) lxi b,128 ;logical sector size (WFM) lda logsec ;get logical sect number(WFM) ora a ;no offset if zero (WFM) rz ;hl=sect addr, bc=len (WFM) read3l: dad b ;offset to desired sect (WFM) dcr a ;count down log sect no (WFM) jnz read3l ;loop until done (WFM) ret ;hl=sect addr, bc=len (WFM) ; v3chek: lda verflg ;check for version 3.x (WFM) cpi 30h ;carry set if not 3.x (WFM) ret ; (WFM) ; bdos50: shld hlreg ;sa DB '# print disk parameters for curr drive.' DB CR,LF DB '=xxx search for ASCII xxx from curr sector.' DB CR,LF DB ' Caution: upper/lower case matters.' DB CR,LF DB ' Use for hex:' DB CR,LF DB ' To find "IN 0" use: =<0> or' DB CR,LF DB ' "(tab)H,0(CR)(LF)" use: =<9>H,0' DB CR,LF DB '< save current sector into mem. buff.' DB CR,LF DB '> restore saved sector' DB CR,LF DB '( toggle map display of erased files' DDB 'Gnn CP/M Allocation Group nn' DB CR,LF DB 'H[ff,tt] hex dump' DB CR,LF DB 'L Log in drive' DB CR,LF DB 'Lx Log in drive x' DB CR,LF DB 'M[nn] Map [from group nn]' DB CR,LF,CR,LF DB '(Type any char. to continue)' DB 1,CR,LF,CR,LF DB 'N New disk' DB CR,LF DB 'P Toggle printer switch' DB CR,LF DB 'Q Quiet mode (no msgs)' DB CR,LF DB 'R Read current sector' DB CR,LF DB 'Snn Sector nn' DB CR,LF DB 'Tnn Track nn' DB CR, Ctl-S.' DB CR,LF DB 'Separate commands with ";".' DB CR,LF DB ' Example: g0' DB CR,LF DB ' +;d;z#20;/' DB CR,LF DB ' would step in, dump, sleep 2 sec, ' DB CR,LF DB ' and repeat until control-c typed.' DB CR,LF DB 'All "nn" usage except "/", "T", and "S" are' DB CR,LF DB ' HEX. Use #nn for decimal.' DB CR,LF,CR,LF DB 'See DU.DOC for complete examples.' DB CR,LF,CR,LF,0 JMP PROMPT ; ;******************************** ;* * ;* Utilit write function (WFM) call bdos50 ;call BIOS via BDOS (WFM) jmp vwrit3 ;write done (WFM) VWRITE: CALL $-$ ;ADDR FILLED IN BY 'INIT' vwrit3: ORA A JZ WRITOK wrerr: XRA A STA QFLAG CALL ILPRT DB '++WRITE failed++',CR,LF,0 ; WRITOK: POP H RET ; read3: lxi b,dbuff ;CP/M version 3.x read (WFM) push b ;save for later (WFM) mvi a,bsetdma ;set dma address (WFM) call bdos50 ; (WFM) mvi a,bread ;read a buffer (WFM) call bdos50 ; (WFM) pop h ;buffer address to hl (WFM) ve regs in parm block(WFM) xchg ; (WFM) shld dereg ; (WFM) mov h,b ; (WFM) mov l,c ; (WFM) shld bcreg ; (WFM) sta func ; (WFM) lxi d,func ;point to parm block (WFM) mvi c,50 ;BDOS function number (WFM) jmp bdos ; (WFM) ; ;Help ; HELP: CALL ILPRT DB 'Operands in brackets [...] are optional' DB CR,LF DB 'Numeric values: ''n'' are decimal, ''x'' hex' DB CR,LF,CR,LF DB '+[n] step in [n] sectors;' DB CR,LF DB '-[n] step out [n] sectors' DB CR,LF B CR,LF DB '? give help' DB CR,LF DB 'A[ff,tt] ASCII dump' DB CR,LF,CR,LF DB '(Type any char. to continue)' DB 1,CR,LF,CR,LF DB 'C Change:' DB CR,LF DB ' CHaddr,byte,byte... (hex)' DB CR,LF DB ' or CAaddr,data... (Ascii)' DB CR,LF DB ' Allowed for imbedded hex.' DB CR,LF DB ' or CHfrom-thru,byte e.g. ch0-7f,e5' DB CR,LF DB ' or CAfrom-thru,byte' DB CR,LF DB 'D[ff,tt] Dump (hex+ASCII)' DB CR,LF DB 'Fn.t Find file' DB CR,LF LF DB 'Unn Set User nn for Find command (CP/M-2 only)' DB CR,LF DB 'V[nn] View [nn] ASCII sectors' DB CR,LF DB 'W Write current sector' DB CR,LF DB 'X Exit program' DB CR,LF DB 'Y Yank current sector into sequential memory' DB CR,LF DB 'Z[nn] Sleep [nn tenths]' DB CR,LF DB '/[nn] Repeat [nn (decimal) times]' DB CR,LF,CR,LF DB '(Type any char. to continue)' DB 1,CR,LF,CR,LF DB 'Cancel a function with C or Ctl-C.' DB CR,LF DB 'Suspend output with S ory Subroutines * ;* * ;******************************** ; GRPCMP: MOV A,C INR D DCR D JZ CMP8 CMP M INX H RNZ MOV A,B ; CMP8: CMP M RET ; ;2's complement HL ==> HL ; NEG: MOV A,L CMA MOV L,A MOV A,H CMA MOV H,A INX H RET ; ;HL/2 ==> HL ; ROTRHL: ORA A MOV A,H RAR MOV H,A MOV A,L RAR MOV L,A RET ; ;Collect the number of '1' bits ;in A as a count in C ; COLECT: MVI B,8 ; COLOP: RAL JNC COSKIP INR C ; COSKIP: DCR B JNZ COLOP RET ; ;$   HL-DE ==> HL ; SUBDE: MOV A,L SUB E MOV L,A MOV A,H SBB D MOV H,A RET ; ;Quick Kludge multiply ;HL*DE ==> HL ; MULT: PUSH B PUSH D XCHG MOV B,D MOV C,E MOV A,B ORA C JNZ MULCON LXI H,0 ;FILTER SPECIAL CASE JMP MLDONE ; OF MULTIPLY BY 0 ; MULCON: DCX B MOV D,H MOV E,L ; MULTLP: MOV A,B ORA C JZ MLDONE DAD D DCX B JMP MULTLP ; MLDONE: POP D POP B RET ; ;Routine to fill in disk params ;with every drive change ; LOGIT: LDA verflg ORA A ;IF NOT MOV E,M XCHG SHLD SYSTRK ; LOGCAL: LXI H,GRPDIS MOV A,M PUSH PSW LDA BLM MOV M,A PUSH H LHLD DSM XCHG CALL GTKSEC SHLD MAXSEC XCHG SHLD MAXTRK POP H POP PSW MOV M,A RET ; ;Temporary storage area ; BUFAD: DW BASE+100H ;FORCES INITIAL READ HEXAD: DW 0 ;TO RE-FETCH A VALUE TOGO: DW 0FFFFH ;REPEAT COUNT (FFFF=CONT) TWOUP: DB 0 TOGE: DB 0 PFLAG: DB 0 ;1=PRINT GROUP: DW 0 GRPDIS: DB 0 SAVEFL: DB 0 CURTRK: DW 0 CURSEC: DW 1 PHYSEC: DW 1 logsec: db 0 ;logical s0 ;POINTER TO CURRENT YANK ADDRESS dmaadr: dw 0080h ;dma address (WFM) ; func: db 0 ;bdos parameter block (WFM) areg: db 0 ; (WFM) bcreg: dw 0 ; (WFM) dereg: dw 0 ; (WFM) hlreg: dw 0 ; (WFM) ; BACK: DS 2 ;TO BACK UP IN "CA0-7F,X" DUMTYP: DS 1 ; ;-------------------------------------------------- ;The disk parameter block ;is moved here from CP/M ; DPB EQU $ ;DISK PARAMETER BLOCK (COPY) SPT: DS 2 BSH: DS 1 BLM: DS 1 EXM: DS 1 DSM: DS 2 DRM: DS 2 AL0: DS 1 AL1: DS 1 CKS: DS 2 DU-V77.DOC by Ward Christensen with additional notes by Ron Fowler and Keith Petersen (revised 7/23/81) HOW TO USE DU ver 7.7 DISK UTILITY INSTALLATION: The 7.0 and later versions of DU are designed to be installed with a minimum of trouble. In fact, in al- most all cases, no changes to the source file should be necessary to get DU up and running. This is because DU uses the disk paramter block of CP/M to determine the characteristics of the disk environmen CP/M 2.x THEN JZ LOG14 ; DO IT AS 1.4 LXI D,DPB ; THEN MOVE TO LOCAL MVI B,DPBLEN ; WORKSPACE CALL MOVE JMP LOGCAL ; LOG14: LHLD BDOS+1 ;FIRST FIND 1.4 BDOS MVI L,0 LXI D,DPBOFF ;THEN OFFSET TO 1.4'S DPB DAD D MVI D,0 ;SO 8 BIT PARMS WILL BE 16 MOV E,M ;NOW MOVE PARMS INX H XCHG SHLD SPT XCHG MOV E,M INX H XCHG SHLD DRM XCHG MOV A,M INX H STA BSH MOV A,M INX H STA BLM MOV E,M INX H XCHG SHLD DSM XCHG MOV E,M INX H XCHG SHLD AL0 XCHGector (WFM) TABCOL: DB 0 FILECT: DW 0 DIRPOS: DB 0 FINDFL: DB 0 ;1=MUST POSITION AFTER FIND FTSW: DB 1 ;SEARCH W/O INCREMENT NOTPOS: DB 1 ;INITIALLY NOT POSITIONED WRFLG: DB 0 ;MAY NOT WRITE UNTIL '+', '-', ; OR 'G' COMMAND QFLAG: DB 0 ;QUIET? (0=NO) FIRST0: DB 0 ;SETS TO 0 IF FIRST SEC # IS 0 DRIVE: DB 0 MAXTRK: DW 0 MAXSEC: DW 0 verflg: DB 0 ;CP/M version number (WFM) mpmflg: db 0 ;non-zero => MP/M (WFM) SECTBL: DW 0 ;POINTER TO SECTOR SKEW TABLE MFPTR: DW 0 DUPFLG: DB 0 YNKADR: DW  SYSTRK: DS 2 psh: ds 1 ;physical shift count (WFM) phm: ds 1 ;physical sector mask (WFM) ; ;End of disk parameter block ;-------------------------------------------------- ; SAVBUF: DS 128 INBUF: DS 128 dbuff: ds 4096 ;physical sector buffer (WFM) ; ;Directory read in here; also search work area ; WORK EQU $ DIRECT EQU $ ; END  verflg: DB 0 ;CP/M version number ;DISK PARAMETER BLOCK (COPY) SPT: DS 2 BSH: DS 1 BLM: DS 1 EXM: DS 1 DSM: DS 2 DRM: DS 2 AL0: DS 1 AL1: DS 1 CKS: DS 2t. (see the dis- claimer for certain non-standard versions of CP/M 1.4). The only parameter that should need to be changed will be the clock speed flag at 103H. Leave this byte zero if you have a 2 mhz clock. Patch it non-zero for 4 mhz. This is only needed for the "Z" (sleep) command. USE: Any valid command string may be placed as an operand of the original DU command, i.e.: A>DU G0;D;G2;=OK<1A>;D Functions supported: Tnn Seek to track nn (no read) Snn Positi$   on to sector nn, and read Gnn Position to group nn and read. G Shows current position V Views the current sector. (assumes ASCII data) Vnn Views nn sectors Fname print directory for file "name", then positions to its directory sector. (Won't position under CP/M 2.x, but see = command below.) =string Ascii search, starting at current sector. hex may be imbedded, or used alone: To find "IN 0FEH": = Ignores bit 7 unless is used. L Re-logs in the cure ASCII in sector NOTE that may be hex imbedded in the Ascii: ca0,OK<1a> ----> Use W to write changes to disk. Note that the C command echoes the overlaid data for verification. CHaddr-addr,byte or CAaddr-addr,byte repeats a change + advance 1 sector (if below track 2, this advances to next numerical, if 2 or >, advances based on CP/M's normal sector scrambling algorithm, i.e. so + will get the next logical sector of the file - backs up 1 logical sectorions of CP/M to change the disk format (e.g., density, sides, etc) R Reads the sector currently positioned to into memory. Note R (Read) is implicit in the G, +, and - commands, but N-O-T in the S and T commands (I did it because I was tired of disk reading after T command before I had a chance to issue the S command) W Write back the current sector (N-O-T-E may not be used after an F command, as CP/M was used to find the file in the directory X Exit back to CP/M (Musa save buffer > Gets saved buffer. < and > may be used to move a sector to another place. / Repeats entire command. Defaults or /nn to "forever". NN may be 2 to 65535 multiple commands may be separated by ";" Example: the following commands will erase the b disk directory to all E5's: lb log in b drive g0 position to dir. ch0-7f,e5 fill with e5 < save the sector >;w;+;/16 restore, write, next, repeat 16 ----This could be shortened to: lb;g0;ch0-7f,e5;< >; - 40 00534944 20202020 20434F4D 0000003A *.SID COM...:* || ||| | || || | | || ||^----hex file name-----^ || || ^file name^ || || || || in ASCII || || extent-^^ || || || || || || file size in sectors-^^ || || || ^^-00 = file active || E5 = file erased ^^-displacement of line in directory sector Second line - 50 33343536 3738393A 0000rent disk. You may pull out a disk, put in a new, and "L" just to log it in. Lx Logs in disk 'x', such as: LB Ux Logs user 'x' for next F command. Gives '?' error if not CP/M version 2.x. D Dump sector, hex + ASCII A Dump sector, ASCII only H Dump sector, hex only note all dump commands (D, A, H) may be optionally followed by a starting and ending address: D0,7F is the same as just D D3,5 A20,3F CHaddr,val,val,val... change hex in sector CAaddr,char string... chang Note + and - may take an amount: for example, +F steps in 15 sectors. Note also that "-" issued at the first logical sector of the disk will wrap back to the last. Further, "+" issued at the last sector will wrap forward to the first. ? Gives command summary # Prints the disk parameters M Dumps a map of the group allocations for files. Mn Shows which file is allocated to group "n". N Resets CP/M via the BDOS. This may make it possible under some implementatt press return). Ctl-c was too easy to hit over modem lines, so I decided on 2-byte (X, CR) to exit. P Toggle printer switch on/off Y Yanks current sector into sequential memory and prints ending address. This allows sectors to be written sequentially into memory starting at 3000H, for later recovery by DDT, etc. Z Sleep - causes the program to pause, such as to look at a dump. Z is 1 sec. Znn is nn tenths of a second on a 2 MHz 8080. < Saves current sector in w;+;/16 INTERPRETATION OF DIRECTORY DATA PRESENTED BY THE DU PROGRAM The following explains the format of a CP/M directory entry as shown by DU, using either the "F" (find file) command, or just doing "D" (dump) of the directory sectors, which are located in groups 0 and 1 on a single density disk. ---------------- Sample result of "FSID.COM" command: 40 00534944 20202020 20434F4D 0000003A *.SID COM...:* 50 33343536 3738393A 00000000 00000000 *3456789:........* First line0000 00000000 *3456789:........* | | | | ^---allocation group numbers-------^ END  ||^----hex file name-----^ || || ^file name^ || || || || in ASCII || || extent-^^ || || || || || || file size in sectors-^^ || || || ^^-00 = file active || E5 = file erased ^^-displacement of line in directory sector Second line - 50 33343536 3738393A 0000%   +"6# x+:`i* ">"/##~>;+> 6*s#r w+͊1>2 u+#w+>36*s#rw+6*xDM"+ڍ+s#r#À+! æ+>2:*ã+6*x+Á*~#ʽ+#~+ҽ+~+x 6*s#rw+ɯ2,x_O:*+2,x_O6*9w#w+x,+r+s=,w>#w+Á*~7^#VE,E,!~ѧ7x1P*x1~7!~#fo~ʁ,7,#~+~w}D#wx#1]*KÄ,!9*?>":u,2g>2u:u8!*͸ ͑!!!8͑!!!!8!*!͘/!/!X*|/g}/o|ʋF Ü!b !9 Fͦ +ͮu!b !FF !9" 9* ͺ +ͮF !9!|!9!+!9"  g"  g!0^p * " g!0** ͺ  +ͮ ͑!!!~! [Continuous (C) \\/ What is the name of your merge data (list) file,H What is the name of your merge (letter) file"w How many Fields in your merge file8 Val-Merge Merge Utility for Valdocs Ver 1.34 JAD 8307.15 pt[[[[ BASLIB #000000 5.30 - OWNED BY MICROSOFT, 1980 3 ~Z=DM*"*M ##" >2* 2- *^#V"+ ##^#V".  20 !~ !!""1 ! " 6#6P>2 >2 >2 * - ú _23ͤ423~4]=i=ʼ4ͤ4ð44x¬4:3=+6~#fo> at address|}2 > ̀5> À5~#*K +6~#fo(@!9" !S * Y " !z * 2 ! ~<ʦ =ʦ #~# Ò #Syntax Error in DATRETURN without GOSU Type MismatcOut of DatIllegal Function CalOverfloOut of Memor Subscript Out of Rang Division By ZerOut of String SpacString Formula Too CompleRESUME without Erro2Field Overflo3Internal Erro4Bad File Numbe5File Not Foun6Bad File Mod7File Already Ope9Disk I/O Erro:File AlreadyNU;N#"!9""y2* |,* !" A~#*6: L~^|!a̓!"ʇʓͧ*@7*>7*<7*:7à *>7à͐*@7*>7*6~#",4 : 4~!" ~,"#"~# "#"x"  +~ ydà?Redo from Start *͖!C͍*:O3*+~+qcc +w e|++~#fo͊"!5*<~2#~#^#V++͌͝3ک :O * |!Ud͊* Lʬ, PJ-,O:u,-!l{Ps",͖Q!-gQH-*fx-͸QP'-͌Q!l>P͍PH-@]T}_|H-)>-x1P*I&>4ͺ-K3y=d-e#x2#~+Œ-x-xGe#>.xʛ-e#>.xG ʩ->.x#~+>.>X6*s#r+}*W!-K^#V#~.  !'&   ͑![! 8!t ͍ !F!E ͍ !F! ͍ !F! ͇!͍ !F!͘/!/!X*|/g}/ö́ |g}o|!b bg9ͰP+æͮ ͑! +F :ͧ!98 +ͮ!z͈!v͈|g}o||!P͍ !FÈͧ! [8U!*͑! 8͑!I8͸ !9 !!E͈"  !! [͈"  T|8)?go* |g}o* |g}o|A!9 "  DM!0* ͺæ͸ H LDone#SHit return when ready for next pageys}S Printing Page with Mergeing  lines File Read File is too long 60 lines is maxI"Single Sheet (S) or 444{8E55t6/0!9" < !͝ < @ !͝  ! ͝ !R" !O" < |q >  6#s#r#=f >2 >2 >2 2 ! " !$\" >&2 L æ6#}š |š  STOͨ ø 2 * .. . ........͖* |¿ : - * |- 3 <  s#r<  {͋ w#6" * * >2 ͌ ò !9N#F< ~#~e ~+k ~#~e +^#V###C ###C |w ~#fo!  Internal Error - No Line Number < ~#  at line3 2 > <  < 0̀5  }_|W!  Exist=Disk Ful>Input Past En?Bad Record Numbe@Bad File NamCToo Many FileUnprintable Erro| O }%0t3~q3`i" !" !"  ,'|!ͧ*@7*>7*<7*:7̓! *>7̓!͐*@7*>7 “,Z'~#xd` !> 'Ud͊ʹ,  7'"LG{,xLPXʹ,ښ!Oz"yʅ ʺ …O{,yʹ,ښ …{ ʔ,> ʔʔʚʚʹ,Q"ʥ ʹ, ʥ, ʹ, * ( 4: {,6!UO +~ #6!ɷw#"*##s#rq#p !#'()+,-.06#~6+E5#w+~=w!%=K~go A= *K!^[oR=$~##~O++###^#VBâ,r+sx##^#V@ZMERGE REL?RO A%O L%O W%O %O AGO LGO WGO ͬGO AO LO WO ͬ>7b:7b">7kH~# cx2[: ›Q#U<S~ʔ4#ÈBQ#~ʗ 4#Þ>2[: F#~#foxS~#4Ì>"4G: xʔ5* +%   ~<=###~* Ô5!* * ~=,/<SB=8> 4>,4W* #^ }w+=w: =w͔5z{ڏ{_Á! " !" 2 ͽ! " !" 2 ͽ! ~6#w~! N` i&  g͉̓g͉̓g͉͕̓g͉͕̓g͉̓g͉̓g͉͕̓g͉͕̓ͤ^#V#"*ͤmͤ^#qÞͤ^#V#s"~2"O **:õ5:5:!>!>!>!>!>^#V#^#V#>ÿ>ÿ>ÿ>ÿ>ÿ>^#V#^#V# GM GMg͉̓g͉͕̓g͉͕̓g͉̓g͉̓g͉͕̓g͉͕̓ͤ^#V#"*ͤmͤ^#qÞͤ^#V#s"~2"O **:õ5:5: