IMD 1.16: 28/05/2007 16:21:00 -FOG/UTL006         1 |2d*"""""""7"{""".:dT"ai*."a"e DISK UTILITY ver 7.5+mods Universal Version (DUU.COM) Type ? for help Type X to exit Z !~Gu##> !u͚͚2]ͳ>2G2H12I>2Z!"CC~ ;#ͤ2+> -v =ʄ#?PAC_ DF G HLcMNʢP QʶR S T UVmWx XZ/ʼ2] ? 2] +++ Out of memory +++  Disk Information: -FOG/UTL006DUU COM/DUU DOCT DU ASM DU ASMJDUMP COM DUMP ASM!"#$%&'()*DISK DOC +  't dump, no sector read. 2] Use G command following F, or R or S following T ~;d mÀBK ʀ;ʀ#`i}͚ :A~͚ } } {ʸ#}˜C:H ~ ~>.;{#} ͚C{ƒ :J2J@{! @:.> x.C!ͪMʹ̴OÁ l~ ;ͤ#AOy2_:dʥ|ʹ^#V#"e!~#fo*#;*S|2^q *"O!"Q*#ͤͤDMBK:=ͳ*O#*Q;͚{ƒ ~;  T2 SN Gʢ ù́*`͸#>2[k ́zʹ*͸ڹ;Ͷ2[q **O͸*Ϳ*Q+:G}2M:Gͤ– "K@*͸"K2M #;Ͷ2[ bk:)= :Mo*͜ ** #!Ͷ ! xͳ :ͬ:ͬ@{=BK͎ >-;*#}U|zCʁzn{H ͎ ͋= ͎ ͚͋*Kú |~> >(;~͚ #>.; ~͚ ~> >); ++FREE++ :I2Iʚ>:; ~"~ ʵ ;ʵ \  *"O!"Q*#"ͳ *O#*Q;Ͷ!]# ?h h #X q  }o" 2[>D22\à ++FILE NOT FOUND  >2[*| ++Can't continue F command *+"|ʐ } oR ; ~#.# ~~ ;*#"V!~~O_#~O:CW#͐fD *V+"V|#!:\!>2N:Nʛ!2] ++NO "<" SAVE COMMAND ISSUED ~#ɯ2\C!u6 k 8G~ 2 >?2 ~.# ~ W ;W ́zʹ zW *Q;*O#Ͷk ~ ʏ ;ʏ ́zʹ*Q+| *O|¾ *Q#"Q Out of bounds +"O*"Qz ` *Q#*͸ *O#*`͸ڨ "O!"Q;2] = AT :C͚ ͚k ~<#~<@>{¹:ZK*C}f 2Z*Q;*O#Ͷq !~#"C :\́{!C~~ҫ Ҳ ʲ ʲ ʲ~~ õ;,„ *Q;*O#ͶÁ ++EOF++ ͚k :\Y2] ++Can **O͸0 G=*KDM͎ >:;:M͚ >,; T=*Oͱ , S=*Qͱ , PS=*Sͱ ͚~ͤ##-| #BKÁ ,¹H A¹~ ; ڥ ~ҥ ë ~ î ;"##y *Œ ~ ;ù#~ ;, "E@{͚ y *ETracks: *`#ͱ Sec/trk: *ͱ Grpsize: : for hex: <3b> for ";"; To find "IN 0" use: =<0> or for "(tab)H,0(CR)(LF)" use: =<9>H,0 < save curr@z{ƀ_ɯ2] ++BAD DISPLACEMENT (NOT 0-7F) ~#ʀ~ͤ ;,->#0ڹ:sAڹGҹ0))))oI#~ͤ ;,-#0ڹ:ҹ0bk)))o|gÄ>:;!uʹOʊ r! ?w#;ý+>*;ýw;> ent sector into mem. buff. > restore saved sector ? give help A[ff,tt] ASCII dump C Change: CHaddr,byte,byte... (hex) or CAaddr,data... (Ascii) Allowed for imbedded hex. or CHfrom-thru,byte e.g. ch0-7f,e5;!uɯʊ+y~;ý,ýʸ,";  $½ ^C Ignored - Use X command to exit to CP/M6 ͚!u~ ʽ;#|>^;>U;͚ó> ;> þ`_O > ;:U   :]y >2U  or CAfrom-thru,byte D[ff,tt] Dump (hex+ASCII) Fn.t Find file F Find next extent of 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] N New disk P To:U<2U:J*`͸"OBK*"Q*O͸`i[:^u+u*e :kg:du&i"SDMɯ2] ++not within tracks 0-*`ͱ ++ >2\2] ++READ failed, sector may be invalid++ :\*2]ggle printer switch Q Quiet mode (no msgs) 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 Z[nn] Sle ++CANNOT WRITE UNLESS READ ISSUED N2] ++WRITE failed++ 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 fep [nn tenths] /[nn] Repeat [nn (decimal) times] 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 unti ~ ;ù:[ Ͷ2] ++Can't read - not positioned Position by: Track then Sector, or Group ><;͚ >>;:ʙ x͚ yͣ  ڬ 0þ ں  |ı {0;> þ>*þC~ ʹ ;#~ #   can have more directory entries). Thus, DUU now does the directory search itself, positioning to the file. See the "F" description below. INDEX 1.0 INSTALLATION: 2.0 USE: 2.1 COMMANDS, BY FUNCTION 2.2 ALPHABETIC COMMAND SUMMARY 3.0 N^#"~#2~#2^#"^#"^"!M~:w* "b"`wxamples. yʚ#x}/o|/g#ɷ|g}oҳ ®}o|gBKx! T]x :d'*.:^#"OTES 4.0 INTERPRETATING DIRECTORY DATA 4.1 SINGLE DENSITY 4.2 DOUBLE DENSITY 1.0 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 thDUU.DOC by Ward Christensen (revised 09/27/81) With additional notes by Ron Fowler HOW TO USE DU ver 7.5 DISK UTILITY (Extended and called DUU on CP/MUG v.55) DUU, Disk Utility-Universal, is an enhanced version of previous DU programs, on CP/MUGe 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 environment. (see the dis- claimer for certain non-standard versions of CP/M 1.4). The o volumes 40 and 46. The primary change is the additions by Ron Fowler, to make DU work with virtually any 1.4 or 2.2 system, single or double density. A further change by Ward C. updates the "F" command. Under 1.4, the "F" command would find a nly 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. An alternative is just to use larger numfile, then position to it. This was possible because open/search returned a number in (A) which was the "directory entry number". However, since CP/M 2.2 doesn't return the actual "directory entry number" on an open or search, as 1.4 did (because 2.2bers when running 4mHZ or 5MHz. 2.0 USE: === An initial command string may optionally be placed as an operand of the original DU command, i.e.: A>DU G0;D;G2;=OK<1A>;D For example, if you want to only MAP the disk, then exit: Al 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 :d'*.:^#"  sector on Misc: Znn Sleep (nn tenths of a second) such as to allow viewing data before it scrolls off Lx Log in disk x P Turn on/off printer output toggle Q Before any command does it "quietly" X Exit to CP/M /nn Repeat previous command n initely (until ^C is pressed), or a given number of times. To avoid an accidental ^C from dropping out of DU, only an explicit "X" command will exit DU. 2.1 COMMANDS, BY FUNCTION === Help: ? request help Positioning: Gnn by allocatn times (indefinitely if nn omitted) 2.2 ALPHABETIC COMMAND SUMMARY === # Prints the disk parameters + advance 1 sector (if below track 2, this advances to next numerical, if 2 or >, advances based on CP/M's normal sector scrambliion group Snn by sector Tnn by track +nn going ahead nn sectors -nn going back nn sectors I/O: R Reads sector W Writes sector < Puts current sector "away" into a buffer > Recalls previously saved sector Displaying: G Shows current gng 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, +15 steps in 15 sectors. / Repeats entire command. Defaults /nn to "forever". nn may be 2 roup, track, sector M Maps the disk - where are the files Mxx Map starting at group xx D Dump the sector (hex + ascii) A Dump sector in ASCII H Dump sector in hex Vnn Views (like CP/M TYPE) nn sectors # Shows disk parameters Changing: CHto 65535 < Saves current sector in a save buffer =string Ascii search, starting at current sector. hex may be imbedded, or used alone: To find "IN 0FEH": = Ignores bit 7 unless is used. Since ";" is a command delnn,val Change data in hex CAnn,val Change data in ascii ( with escape to hex) Unn Change user to nn Searching: Fname Find a file in the directory F Find next occurrence (extent) of same name =aaaa Scan for aaaa (in ASCII) from current imiter, you have to use <3b> to search for a ";". Also, since "<" is a hex-escape char, use << to meane a single "<". > Gets saved buffer. < and > may be used to move a sector to another place. ? Gives command summary A Dump >DU M;X Once DU is running, it expects single-letter commands much like SID or DDT. For ease of use, multiple commands may be placed on one line, separated by ";". In addition, a given command or string of commands may be repeated, either indef-  , +, 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) Snn Position to sector nn, and read Tnn Seek to track nn (no read) Ux echoes the overlaid data for verification. CHaddr-addr,byte or CAaddr-addr,byte repeats a change D Dump sector, hex + ASCII Fname print directory for file "name", then positions to it's directory sector. F Find next occurrence Logs user 'x' for next F command. Gives '?' error if not CP/M version 2.x. (Note "F" no longer needs this - finds ALL files - erased, any user, etc) V Views the current sector. (assumes ASCII data) Vnn Views nn sectors W Write back of name in dir. Gnn Position to group nn and read. G Shows current position H Dump sector, hex only L Re-logs in the current disk. You may pull out a disk, put in a new, and "L" just to log it in. (See "LOGGING IN DISK" in NOTES bthe 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.elow) Lx Logs in disk 'x', such as: LB 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 c 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. 3.0 ====== NOTES ====== === * MULTIPLE COMMANDS: May be separated by ";" Example: the following commands hange the disk format (e.g., density, sides, etc) P Toggle printer switch on/off Q Quiet: Preceeding any command, suppresses console output R Reads the sector currently positioned to into memory. Note R (Read) is implicit in the Gwill 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 sector, ASCII only 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   , then do the read there, then change disks to the blown one. 4.0 INTERPRETATING DIRECTORY DATA === 4.1 SINGLE DENSITY === The following explains the format of a CP/M directory entry as shown by DU, using either the "F" (find file) command, od that when you had a blown directory, you DIDN'T want to log the new disk in. Thus I changed DU to just change which disk was selected. Then along came double density, with its attendant "select density" functions, and Ron apparently put this bar 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 3738393ck in. So, it now sometimes works for double density, but makes DU very "intolerant" of disks with un-readable directories. A solution is to log in a disk which is OK, and is of the same density as the blown disk, then put in the blown disk WITHOA 00000000 00000000 *3456789:........* First line - 40 00534944 20202020 20434F4D 0000003A *.SID COM...:* || ||| | || || | | || ||^----hex file name-----^ || || ^file name^ || || UT logging it in. However, you are now opening yourself up to possible problems because of the buffering of physical sectors in the BIOS. The best technique, (but not guaranteed), would be to seek to the unused inner tracks of the first disk, do || || in ASCII || || extent-^^ || || || || || || file size in sectors-^^ || || || ^^-00 = file active Other values (e.g 03) = User # || E5 = file erased ^^-di the read, THEN change disks. That way if it writes anything, you won't have destroyed anything. ...assuming the disk is not completely full. Another technique, assuming the second disk does not contain a CP/M system, would be to seek to track 1splacement of line in directory sector Second line - 50 33343536 3738393A 00000000 00000000 *3456789:........* | | | | | ^- allocation groups ^-----allocation group numbers-----^ just happened to be pr * DUMP COMMANDS: 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 * LOGGING IN DISK: In the original DU, I logged in the disk the way DU now does. Then, I foun  0:00, T=2, S=1, PS=0 The primary difference is that the groups now occupy 2 bytes, i.e. "38 00" "39 00" ... This follows the INTEL and CP/M convention of putting 16 bit values high-byte-first. Thus it means group 0038, 0039, etc. Note that in double density, each group stood for 2K, not 1K, so there were half as many groups for the same file. Be VERY careful when patching a directory under double density. I once made the mistake of putting, for example: ch10,38,39,3a,3b... When I went to read this file, it tried to access group 3938, with resultant angry exclamations from the disk stepper as it attempted to go south to Peoria for the data. 09/30/81 Ward C. intable 4.2 DOUBLE DENSITY === The following is a sample of FSID.COM running on double density system: :FSID.COM 00 00534944 20202020 20434F4D 0000003A *.SID COM...:* 10 38003900 3A003B00 00000000 00000000 *8.9.:.;.........* G=000  m 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 undertions. 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 ;as 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 thatsembly 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 time delay used in ;the 'sleep' command. ; ;* 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. Again, ************************************************ ;* * ;* 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 yousystem 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. * ; 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 proble* * ;* Ron Fowler * ;* * ;************************************************* ; ; ;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 ; DU.ASM V7.7 Revised 7/07/81 ; DISK UTILITY - By Ward Christensen ; ;See DU.DOC for description and detailed instructions. ; ;This version of DU is compatible with CP/M 1.4 and 2.x ;and does not require alteration for various hardware ;configura  ms, 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) argu 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) ; ;01ment 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. ; (RGF) ; ;01/02/81 Made compatible with MACRO80 assembler (labels ; made unique within 6 ch/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) ; ;01/11/81 Fixed problem with CP/M 1.4. Added 'N' command. ; Hard-code 'FASTCars, 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 BILOCK' 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 neOS'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 command (will always be 00 for 1.4) and only ; print parentheses if E5 present. (BRR) ; ;10/30/80cessary 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 ; 'REPEAT' to allow up to 65535 repeats. (RGF) ; ;01/06/81 Modified to allow use with ALL syste 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 D; sequentially into memory starting at 3000H, for ; later recovery by DDT, etc. (DJH) ; ;04/02/81 Added * to map showing multiple group assign- ; ment errors. Fixed bug in getgrp record counw ; (William Ernest) ; ;01/23/81 Changed SETSEC to  n 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  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/Museful. Its external ;documentation is good, but its sadly lacking ;comments on the instructions. (WLC) ; ---------------- ; ;System equates ; BASE EQU 0 ;SET TO 4200H FOR HEATH OR TRS-80 ALTCPM ; FCB EQU BASE+5CH BDOS EQU BASE+5 PRINT EQU 9 G) (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, W8SDZ ; ;02/24/80 Mod login command to not really do log, just ; drive select. (WLC) ; ;02VERS EQU 12 RESETDK EQU 13 SELDK EQU 14 SRCHF EQU 17 ;SEARCH FIRST SUSER EQU 32 GETDSK EQU 25 GETDPB EQU 31 ; 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 ;OFF/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: < sSET 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 ;LINEave sector ; > restore sect ; / repeat ; allow change from-thru. (WLC) ; ;02/25/79 Put sector read into 'S' command. (WLC) ; ;11/26/78 Add disk # to login command. (WLC) ; ;11/12/78 Add login command. (WLC) ; ;08/06/78 Originally writte FEED TAB EQU 09H ;TAB BS EQU 08H ;BACKSPACE ; ORG BASE+100H ; JMP PASTCK ;JUMP OVER CLOCK BYTE AND I.D. ; CLOCK: DB 0FFH ;<---PUT NON-ZERO HERE FOR 4 MHZ CLOCK DB 'DU.COM ver 7.7 7/12/81' ; PASTCK: LHLD BDOS+1 ;GET POINTER TO BDOS ENTRY MVBL 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. Ratoff, ACGNJ-SIG/M) ; ;09/16/80 Fix backspace in line enter routine, add MAXDIR ; equate, general  MMAND ; ;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,2ALIZE "Y" COMMAND MEMORY POINTER 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 DAD D SHLD VCONIN+1 DAD D SHLD VCONOT+1 DAD D SHLD VLIST+1 DAD D ;PUNCH DAD D 55 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 STA FTSW ;TELL SEARCH NOT TO INCR PUSH H LXI H,BASE+100H SHLD BUFAD ;FOR RDBYTE POP H ;RDR DAD D SHLD VHOME+1 DAD D SHLD VSELDK+1 DAD D SHLD VSETRK+1 DAD D SHLD VSTSEC+1 DAD D SHLD SETDMA+1 DAD D SHLD VREAD+1 DAD D SHLD VWRITE+1 LDA VER2FL ORA A JZ DOCPM1 DAD D ;LISTST DAD D SHLD VSCTRN+1 JMP HELLO  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  ; DOCPM1: LHLD BDOS+1 MVI L,0 ;BDOS ON PAGE BOUNDARY PUSH H LXI D,TRNOFF ;CP/M 1.4 SECTRAN ROUTINE OFFSET DAD D SHLD VSCTRN+1 POP H LXI D,SKWOFF ;CP/M 1.4 SKEW TABLE OFFSET DAD D SHLD SECTBL ;SET UP SKEW TABLE POINTER ; HELLO: CALL DUMTYP ;TYPE OF DUMP (A,D,H) ; ;Command dispatcher ; CPI '+' JZ PLUS ; CPI '-' JZ MINUS ; CPI '=' JZ SEARCH ; CPI '<' JZ SAVE ; CPI '>' JZ RESTOR ; CPI '#' JZ STATS ; CPI '?' JZ HELP ; CPI 'A' JZ DUMP ; CPI 'CILPRT DB CR,LF,'DISK UTILITY ver 7.7',CR,LF DB 'Universal Version',CR,LF DB CR,LF DB 'Type ? for help',CR,LF DB 'Type X to exit' DB CR,LF,0 CALL GETSTP ;SET UP PARAMETERS LXI H,BASE+80H ;TO INPUT BUFF MOV A,M ORA A JZ PRMPTR ;NO CO' 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 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 MOV A,H ;COMBINE THE TWO BYTE... ORA L ;...VERSION NR FOR A FLAG STA VER2FL ;SAVE IT LXI H,3000H ;INITI   H CALL SELECT JMP PROMPT ; ;Quite mode ; QUIET: STA QFLAG ;NOW QUIET JMP PROMPT ; ;Repeat buffer contents ; REPEAT: CALL 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 G CALL ILPRT DB '?',0 JMP PRMPTR ; ;Memory full error ; MEMFUL: XRA A STA QFLAG CALL ILPRT DB '+++ Out of memory +++' DB CR,LF,0 JMP PRMPTR ; ;Print disk statistics ; STATS: PUSH H CALL ILPRT DB 'Disk Information:',CR,LF DB 'T0FFFFH? 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 racks:',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 grp SHLD TOGO MOV A,H ;ALL DONE? ORA L XCHG ;GET BACK INBUF PTR JNZ PROMPT ;NO, KEEP GOING JMP PRMPTR ;ALL DONE ; ;Set CP/M 2.x user number ; USER: LDA VER2FL ORA A JZ WHAT CALL DECIN ;GET REQUESTED USER NO. MOV A,E CPI 32 ;VALID? s:',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 tracks:',9,0 LHLD SYSTRK CALL DEC CALL CRLF POP H JMP PROMPT ; ;The following command resets the disk ;system t 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 ; SLEEhru 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 POPP: 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 LDA CLOCK ORA A JZ SLEEP2 LXI B,16000 ;APPROX .1 SEC @ 4 MHz ; SLEEP2: DCX B MOV A,B ORA C JNZ SLEEP2 PUSH D CAI 'S' JZ POS ; CPI 'T' JZ POS ; CPI 'U' ;******CP/M 2.x ONLY****** JZ USER ; CPI 'V' JZ VIEW ; CPI 'W' JZ DORITE ; CPI 'X' JZ BASE ; CPI 'Y' JZ YANK ; CPI 'Z' JZ SLEEP ; CPI '/' JZ REPEAT ; WHAT: XRA A STA QFLA  A 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 ;MAKE 1-RELATIVE ;0 SET IF CTL-C ; ;Find our way at initialization ; 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 L 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 SETTRKGNODK 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 ; VSELDK: CALL $-$ ;ADDR FILLED IN BY 'INIT' LDA VER2FL ORA A ;IF NOT CP/M 2.x ... JZ SELSKP ;..THEN SKIP TH 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 IN DIRECTORY MVIS JUNK 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 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 ;I 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 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 ST? 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 COMPARISON MOV A,LL 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   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 JC MAPN2A ; MA 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 POP H CALL CRLF PN2H: 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: ; ;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 PUSH H ;SAVE POINTER TO NAME MOV A,M ;PICK UP DN BYTE CPI 0E5H JZ GETGNF LXI D,14 ;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-BI 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 TYPE ;SPACE OR ST 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 ;TAR 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  PUSH H ;SAVE GP PTR LHLD MFPTR MOV A,H ORA L POP H XTHL ;GET ENTRY START & SAVE 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: POPL ;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   MPT ; ;Restore the current sector ; RESTOR: LDA SAVEFL ORA A JZ NOSAVE ;NONE TO SAVE 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 ISSUEDector 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 ' 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 C 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,8TLCS ;ABORT? JNZ SEARCH ;..YES LXI H,INBUF MVI M,CR JMP CLCGRP ;SHOW WHERE STOPPED ; ;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. CP0H DAD B SHLD YNKADR ;SAVE LAST BYTE+1 FOR NEXT YANK DCX H MOV A,H CALL HEX MOV 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 'I '<' ;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 ++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 PROJZ SREQU CPI ';' JNZ SRCHL ; ;Got match SREQU: XRA A 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 CPI '<' ;HEX ESCAPE? RNZ ;NO, RETURN ;" 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 s  TTRK CALL READ POP D ;RESTORE COUNT JMP VIEWLP ; VEWEOF: CALL ILPRT DB CR,LF,TAB,'++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 READ1 LHLD BUFAD MOV A,L ORA A ;IN BUFFER? JM NORD ;YES, SKIP READ ; ;Have to read 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,BILPRT 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 ; ASE+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 I ;Use default DUMPDF: LXI B,BASE+80H 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 COMMAND POINTER MOV H,B MONR E ;DFLT=1 ; VIEWLP: LXI H,BASE+80H ;TO DATA ; VEWCHR: CALL CTLCS JZ VEWEND MOV 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 V 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 DJZ 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 SEPOP INX H MOV A,L ANI 0FH JNZ DHEX ; DPOP: CALL CTLCS JZ PRMPTR LDA DUMTYP 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,'.' ;<<" 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   ter 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 GROUPL 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 ; POSTK 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 D: 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  CALL SETTRK XCHG CALL SETSEC CALL READ XRA A STA NOTPOS ;NOW POSITIONED POP 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, quot0 ; POSSEC: PUSH H LHLD SPT CALL SUBDE POP H JC WHAT CALL SETSEC CALL READ 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 ient=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 ; 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 afSO 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 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   Z SEASH LHLD MAXTRK ;WRAP TO END OF DISK SHLD CURTRK LHLD MAXSEC JMP MINOK ; SEASH: 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 TA DUMTYP JMP DUMPLP ;WHICH POPS H ; MVNAME: MOV A,M CPI '.' JZ MVIPAD CPI CR 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 ; MVID LHLD CURSEC INX H XCHG LHLD SPT CALL SUBDE XCHG JNC NEXTOK 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 PAD: 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:  RET ; ;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 SYSTRK XCHG LHLD CURTRK CALL SUBDE JC CALL NXTSEC 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 LHLD CURTRK XCHG CALL SETTRK POP H CALL READ JMP CLCGRP ; MINUS: LXI 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 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 JNDEC 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 DE INX H LXI B,0 ;SHOW NO 'THRU' ADDR CPI ',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' S   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',CR,LF DB 'Position by:',CR,LF DB 9,'Track the 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 TYPE ; CHGA3: SHLD BACK ;IN CASE "THRU" CALL GEn 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: MTVAL ;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 PROMOV 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 H LXI B,-10 LXI D,-1 ; DECOU2: DAD B INPT 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 DELIM MOV A,E ;GET VALUE POP D ;..ADDR PUSH X 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 CTPSW ;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 CRLCS ;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 ; ;DISP calls HEXIN, and validates a sector ;disp'-' ;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'   racters ; 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 INX H INR B JM FULL CALL TYPE JMP RDBLP ;: 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 CR RZ CPI ';' RZ CPI ',' RZ CPI '-'  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.. ;'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 '.' ; 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 RDBLP ; RDCTLX: INR B ; RDCX1: DCR B JZ RDBF1 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 DAD H ;X2 DAD H ;X4 DAD D ;X5 DAD H ;X10 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,INB 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 chaUF 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 JMPlacement, 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  DE POP H JC OUTLIM XCHG SHLD CURTRK XCHG MOV B,D MOV C,E PUSH H VSETRK: CALL $-$ ;ADDR FILLED IN BY 'INIT' POP H RET ; SETSEC: PUSH H PUSH D LHLD SYSTRK XCHG SHLD CURSEC LHLD CURTRK CALL SUBDE POP B MOV H,B MOV L,C 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 JNZ TYPTAB JMP TYPRET ; ;Filter out control  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 VSCTRN: CALL $-$ ;ADDR FILLED IN BY 'INIT' LDA SPT+1 ;IF SPT<256 (HI-Ocharacters to ;prevent garbage during view of file ; TYPE2: CPI ' ' JNC TYPEQ CPI CR JZ TYPEQ CPI LF JNZ TYPNCR ; TYPEQ: LDA QFLAG ORA A VCONOT: CZ $-$ ;ADDR FILLED IN BY 'INIT' ; ;Update column used in tab expansion MOV A,C ;GET CHRD = 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 RETURNAR CPI CR JNZ TYPNCR MVI A,0 STA TABCOL JMP TYPLST ; TYPNCR: CPI ' ' ;CTL CHAR? JC TYPLST ;..NO CHANGE IN 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 ;  THE ; PHYSICAL 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 VSTSEC: CALL $-$ ;ADDR FILLED IN BY 'INIT' POP H RET ; OUTLIM: XRA A STA QFLAG CALLIST: 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 VHOME: CALL $-$ ;ADDR FILLED IN BY 'INIT' POP H RET ; ;Set track # in DE ; SETTRK: PUSH H LHLD MAXTRK CALL SUBL ILPRT DB '++not within tracks 0-',0 PUSH H LHLD MAXTRK CALL DEC POP H CALL ILPRT DB '++' DB CR,LF,0 CALL NORITE JMP PRMPTR ; SETDMA: JMP $-$ ;ADDR FILLED IN BY 'INIT' ; READ: MVI A,1 STA WRFLG PUSH H VREAD: CALL $-$ ;ADDR FIL 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'   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  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 VWRITE: CALL $-$ ;ADDR FILLED IN BY 'INIT' ORA A JZ WRITOK XRA A STA QFLAG CALL ILPRT DB '++WRITE failed++',CR,LF,0 ; WRITimbedded 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 DB 'Gnn CP/M Allocation Group nn' DB CR,LF OK: POP H RET ; ;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 '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, DB CR,LF 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 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,LF DB 'Unn Set User nn for Find command (CP/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 '? give help' DB CR,LF DB '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]' LED IN BY 'INIT' ORA A JZ READOK 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   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 M";".' 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" aOV 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 LXI D,re' 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 ; ;******************************** ;* * ;* Utility Subroutines * ;* * ;**********************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 ********** ; 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 AXCHG 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 SHLD SYSTRK ; LOGCAL: LXI H,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,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-FETC 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 or Ctl-S.' DB CR,LF DB 'Separate commands with   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 VER2FL: DB 0 SECTBL: DW 0 ;POINTER TO SECTOR SKEW TABLE MFPTR: DW 0 DUPFLG: DB 0 YNKADR: DW 0 ;POINTER TO CURRENT YANK ADDRESS ; 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 SYSTRK: DS 2 ; ;End of disk parameter block ;-----------------------------!9"~ 1 2t :):og,ʹw!L CP/M DUMP UTILITY VERS 1.32 $, xCOPYRIGHT 1978 BY S. J. SINGER $W Ç *$ >2r 1 2z !"c !s# ¨ >!\!s#  #!A:#!B:*!--------------------- ; SAVBUF: DS 128 INBUF: DS 128 ; ;Directory read in here; also search work area ; WORK EQU $ DIRECT EQU $ ; END  C:2!D::Y2t ?>2t ?>2t ?>2t Mx~# B!@Byx?Gt#a 7!@\ÑVALIDATEڹ!@\éGROUP!@\þG !@\MAP< !@\DIR !@\TRAH A VALUE TOGO: DW 0FFFFH ;REPEAT COUNT (FFFF=CONT) TWOUP: 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 TABCOL: DB 0 FILECT: DW 0 DIRPOS: DB 0 FINDFL: DB 0 ;1=MUST POSITION AFTER FIND    *.'" ~:y 2y <2y :x 2z  :-} 2{ M 2| ͂ #  g >!g  \%WRITE,!g 8\<STOPe!0V O)))) Ei B}x.  |‚} "e ^  ê͜Ɛ'@'_:f ͓:e ͓\  *e ~͓\  !g s#  g >i B}.  :h  =:| <2| &:{ oT))):| _><(  2u ~2v 2w :t _`o"e !"{ Æ GROUP ALLOCATION MAP DRIVE - $X  :Ø $  *e ú $  ~ 0$  :{ <2{ 1$  x y }*e w^  :e <2e Ð!"c ͊*.*"5͂ :v 7Y?YO*.!"W :u ?sO*."q& :t _*.'"å DRIVE $ :ö -$  TRACK $ !:u o  |{0__ z +  # ^  å < $.  *{ t GROUPS REMAINING ON DISK OUT OF 243 $M  :t :t _2x <2y :y 7ʴ ?ڴ O*.!" :x ? O*." *." *.'" INPUT ERROR$   SECTOR $ !:v o^  !v :w 4=:t A_>2v >2w :é6# > w# e xn .ʍw# x7yʘ# “ w# š!\] e!COM!"c :t _\ʇ \:r F  INCORRECT SECTOR NUMBER$  B INCORRECT TRACK NUMBER$)  | INCORRECT GROUP NUMBER (GREATER THAN 242)$P  ë NO FILE BY THAT NAME ON DRIVE $  : DISK DEAD ERROR$  F ERROR IN FILE NAME$   !"e *e :d ͓:c ͓# $  ~͓\  #y P\   -\  *e ~p r>._#y \   c^  *c "c *e "e >2y 2x :t _:x ?O*."& :y 7?O*.!" ADDRESS ERROR$  ; ERROR - HEX INPUT ONLY $  Ð^  :s _*~ $ $R (GREATER ë NO FILE BY THAT NAME ON DRIV     CK!@\T Z%~!#:H0 ?))) O 1-} 2u !@b\hSECTORڀ!@{\}S J:-} 2v 2w "e @\ä-:-} 2w !v G~2w p:*e @\EDIT: EDIT - $ !g  s  E DUMPED IN THE SAME FORMAT. ; ; -- OPERATION -- ; ; THE PROGRAM MAY BE RUN EITHER BY TYPING DUMP, OR DUMP FOLLOWED ;BY THE FILE NAME OR TRACK AND SECTOR. IF DUMP IS TYPED THE PROGRAM ;RESPONDS WITH A HEADING FOLLOWED BY A '*' AND WAITS FOR MORE INPUT. ;OPERATION IN THIS MODE IS SIMILAR TO OTHER UTILITIES LIKE PIP OR DDT. ; THE OPERATION DESIRED MAY THEN BE TYPED IN AS FOLLOWS: ; ; DUMP FILE.NAM ; DUMP A:FILE.NAM ; DUMP B:FILE.NAM ; ; OR DUMP MAY BE TYPED SEPARATELY AS: ; ; DUMP ; ; *FILE.NAM ; *B:FILE.NAM (THE * IS A PROGRAM PROMPT) ; ; THE PROGRAM MAY ALSO BE USED TO DUMP DISK SECTORS DIRECTLY, ;DUMP ANY CP/M EIGHT SECTOR GROUP, A MAP OF THE GROUP ALLOCATIONS FOR THE ;ENTIRE DISK OR THE DIRECTORY SORTED ALPHABETICALLY. ; ; DUMP TRACK 3 SECTOR 7 ; DUMP TRACK 5 SECTOR 3 - 9 ; DUMP TRACK 6 (DUMPS ALL 26 SECTORS) ; DUMP GROUP 19 ; DUMP MAP ; DUMP DIR (DUMPS DIRECTORY) ; ; THE WORDS TRACK, SECTOR AND GROUP MAY BE ABREVIATED AS FOLLOWS ; ; DUMP G 4 ; DU; --- DUMP --- ; ; BY: S. J. SINGER ; ; THIS PROGRAM IS AN IMPROVED DUMP UTILITY FOR CP/M. ANY CPM FILE ;MAY BE DUMPED TO THE CONSOLE IN A FORMAT SIMILAR TO THAT USED BY THE ;DDT DUMP COMMAND. IN ADDITION, ANY SECTOR OR GROUP OF SECTORS MAY ;BMP T 7 S 3-4 ; *TRACK 5 S 6 ; *SECTOR 2- 9 T 14 ; ; ; DUMP B: TRACK 3 ; DUMP A: T 9 S 4-6 ; DUMP B: G 5 ; DUMP B:MAP ; ; NOTE THAT THE FORMAT IS QUITE FREE. SPACES ARE USUALLY IGNORED ;THEY ARE ONLY REQUIRED AFTER THE WORDS TRACK AN  HEX. ENTERING NON HEX CHARACTERS ;RESULTS IN AN ERROR MESSAGE. THE PERMISSABLE ADDRESS RANGE IS 0000 TO 007F. ;LARGER ADDRESSES GIVE AN ERROR MESSAGE. WHEN ENTERING A GROUP OF BYTES THE ;ADDRESSES ARE COMPUTED MODULO 128, THE NEXT ADDRESS AFTER 007F IS OF THE SECTOR FOLLOWED BY THE WORD EDIT. ; ; DUMP B:TRACK 4 SECTOR 2 EDIT ; ; THE REQUESTED SECTOR WILL BE DISPLAYED FOLLOWED BY AN EDIT PROMPT ; ; EDIT - ; ; ENTER THE ADDRESS OF THE FIRST BYTE TO BE CHANGED. THE PROGRAM WILL ;RESPOND BY TYPING0000. ; THE EDIT FEATURE SHOULD BE USED WITH CAUTION SINCE IT IS POSSIBLE ;TO EDIT CP/M TO "DEATH" BY CHANGING A SINGLE BYTE. ONE OCCASIONAL VALUABLE ;USE IS TO RESTORE FILES THAT HAVE BEEN ACCIDENTALLY ERASED. ERASING A FILE ;USING THE ERA COMMAND DOE BACK THE ADDR ENTERED AND THE PRESENT CONTENTS OF THAT ;ADDRESS. TO CHANGE THE CONTENTS OF THE ADDRESS ENTER THE NEW BYTE FOLLOWED ;BY A CARRIAGE RETURN. THE PROGRAM WILL DISPLAY THE NEXT ADDRESS AND ITS ;CONTENTS. TO STOP ENTERING DATA TYPE A PERIOD. S NOT ERASE THE DATA FROM THE DISK, BUT ONLY ENTERS ;AN E5 INTO THE FIRST BYTE OF THE DIRECTORY. TO RESTORE A FILE, DISPLAY ;THE DIRECTORY BY DISPLAYING GROUPS 0 AND 1. FIND THE SECTOR CONTAINING THE ;NAME OF THE FILE TO BE RESTORED AND DISPLAY IT USINGTHE PROGRAM WILL REDISPLAY ;THE SECTOR SHOWING THE CHANGES MADE. THE EDIT FEATURE WORKS ALMOST EXACTLY ;LIKE THE S ENTRY FEATURE IN DDT. TYPING ONLY A CARRIAGE RETURN OMITS ENTRY. ; TYPING A PERIOD MERELY REDISPLAYS THE SECTOR FROM MEMORY, IT DOES ;NOT THE EDIT FEATURE ;CHANGE THE BYTE PRECEEDING THE FILE NAME FROM E5 TO 00 AND WRITE THE SECTOR ;BACK ON THE DISK. THIS WILL RESTORE THE FILE PROVIDED NONE OF THE SECTORS ;IN THE FILE WERE CHANGED AFTER THE FILE WAS "ERASED". ; ; AN ADDITIONAL FEATURE  CAUSE IT TO BE WRITTEN BACK ON THE DISK. WHEN EDITING IS COMPLETE, ;REDISPLAY THE SECTOR BY TYPING A PERIOD AND TYPE EITHER ; ; WRITE (WRITE SECTOR BACK ON DISK) ; STOP (STOP EDITING WITHOUT WRITING ON DISK) ; ; ALL EDIT ENTRIES MUST BE MADE IN OF DUMP IS THE ABILITY TO VALIDATE A DISK. ; ; DUMP VALIDATE ; DUMP A:VALIDATE ; DUMP B:VALIDATE ; ; THIS CAUSES THE ENTIRE DISK SELECTED TO BE READ ONE SECTOR AT A ;TIME. THE SECTOR NUMBER OF ANY SECTOR CAUSING A READ ERROR WILL BE DISPLAYED. ;D SECTOR OR T AND S, ;AND AFTER THE WORD DUMP. ; A LIMITED EDITING FEATURE IS INCLUDED IN THE DUMP UTILITY TO ;ALLOW CHANGING DATA ON THE DISK. THE EDIT FEATURE WORKS AS FOLLOWS. ;ANY SINGLE SECTOR ON EITHER DRIVE MAY BE EDITED BY REQUESTING DISPLAY ;  RO FILL 80H,0FFH ;ZERO INPUT BUFFER INPUT 80H ;READ FILE NAME ; ; SELECT DISK DRIVE AND SET UP FILE CONTROL BLOCK ; START: FILL FCB,FCB+32 ;ZERO FILE CONTROL BLOCK MATCH 82H,'A:' ;DRIVE A JZ ADISK MATCH 82H,'B:' ;DRIVE B JZ BDISK JMP GERY. ; ; DUMP WAS ASSEMBLED USING THE CP/M MACRO ASSEMBLER, AND USES A LARGE ;NUMBER OF MACROS INCLUDED IN A LIBRARY CALLED MACRO.LIB ; $-PRINT MACLIB MACRO ;INCLUDE MACRO LIBRARY ORG 100H ;SET PROG START LXI H,0 DAD SP ;GET STACK POINTER TNAM ;NO DRIVE SPECIFIED ADISK: XRA A STA NEWDRV ;SELECT DRIVE A JMP DOWN BDISK: MVI A,1 STA NEWDRV ;SELECT DRIVE B DOWN: MOVE 82H,80H,40H ;SHIFT BUFFER DOWN TWO BYTES ; ; SEARCH FOR DIRECT READ OF TRACK AND SECTOR OR VALIDATE ; GETNAM: INSHLD OLDSTK LXI SP,NEWSTK ;SET UP NEW STACK DISKIO ?DRIVE ;GET CURRENTLY LOGGED DRIVE NO STA NEWDRV ;ALSO SAVE IN NEW DRIVE NO LDA 81H ;CONSOLE INPUT ALREADY HERE ? ORA A JZ SIGNON ;BUFFER EMPTY, INPUT FROM CONSOLE LDA 80H ;GET NO OF CHASTR 82H,40H,'VALIDATE' JC VALID ;VALIDATE DISK INSTR 82H,40H,'GROUP' JC GROUP ;DISPLAY CPM 8 SECTOR GROUP INSTR 82H,40H,'G ' ;SEARCH FOR 'G' JC GROUP ;DISPLAY GROUP INSTR 82H,40H,'MAP' ;ALLOCATION MAP JC MAP ;DISPLAY GROUP ALLOCATION MAP R INPUT ORI 80H ;ADD 128 MOV L,A ;TO L XRA A ;ZERO MOV H,A ;HL CONTAINS ADDR OF END OF BUFFER ZBFF: INR L JZ START ;REMAINDER OF BUFFER ZEROED MOV M,A JMP ZBFF ;LOOP SIGNON: PRINT PRINT <'C INSTR 82H,40H,'DIR' ;DIRECTORY REQUEST JC DIR ;DISPLAY DIRECTORY INSTR 82H,40H,'TRACK' ;SEARCH FOR TRACK JC TRK1 INSTR 82H,40H,'T ' ;SEARCH FOR 'T' JNC FILNAM ;NO TRACK GO TO READ FILE TRK1: SCAN ;FIND AND CONVERT NUMBER DECIN JC INERROPYRIGHT 1978 BY S. J. SINGER',CR,LF> NEWIN: PRINT MVI A,0FFH ;SET SWITCH TO RETURN HERE AGAIN STA INFLAG LXI SP,NEWSTK ;RESET STACK POINTER XRA A STA VALFLG ;RESET VALIDATION ERROR FLAG LXI H,0 SHLD LINE ;SET LINE COUNT TO ZE ;INPUT ERROR ON CARRY STA TRACK ;SAVE TRACK NO INSTR 82H,40H,'SECTOR' ;SEARCH FOR SECTOR JC SEC1 INSTR 82H,40H,'S ' ;TRY 'S' JNC WHLTRK ;DUMP ENTIRE TRACK SEC1: SCAN DECIN JC INERR ;INPUT ERROR ON CARRY STA BSEC ;BEGINNING SECTOR WHEN VALIDATING THE PROGRAM READS EVERY FIFTH SECTOR FOR SPEED. ; ; AS WITH OTHER CP/M UTILITIES ^S "FREEZES" THE DISPLAY, AND ^C ;RETURNS TO THE MONITOR. DUMP CONTAINS MANY ERROR AND CONSISTANCY ;CHECKS. THE RESULTING MESSAGES SHOULD BE SELF EXPLANATO  OUT IPOINT ;ECHO THE ADDRESS PRINT SPACE,$ LHLD IPOINT ;ECHO PRESENT CONTENTS LXI D,0080H DAD D ;COMPUTE MEMORY ADDR MOV A,M ;GET BYTE FROM MEMORY HEXOUT PRINT SPACE,$ FILL INBUF,INBUF+5 ;ZERO INPUT BUFFER INPUT INBUF,4 ;INPUT 4 CHAR IF CARRY SET STA ESEC ;SAVE IN END SECTOR LXI H,BSEC ;POINTS TO BSEC CMP M ;COMPARE BEGIN AND END JP DOREAD ;OK IF END>=BEGIN MOV B,A ;OTHERWISE MOV A,M ;SWITCH THEM STA ESEC MOV M,B DOREAD: CALL RDISK0 ;READ DIRECT JMP ENDFIL ; MAX HEXIN INBUF+2 ;CONVERT JNC EDIT2 ;HEX CHAR LDAX D ;GET ASCII CHAR CPI '.' ;PERIOD ENDS INPUT JZ EDIT3 ;BACK FOR MORE EDITING JMP HEXERR ;ERROR NOT HEX CHAR EDIT2: LDA INBUF+1 ;LOAD NO OF CHAR TYPED ORA A JZ EDITX ;NO REPLACEMEBACK FOR MORE INPUT EDIT: LHLD IPOINT ;RESET BUFFER POINTER INSTR ,40H,'EDIT' ;CHECK EDIT FUNCTION JNC DOREAD ;GO TO DISPLAY SECTOR CALL RDISK0 ;DISPLAY SECTOR EDIT1: PRINT FILL INBUF,INBUF+9 INPUT INBUF,6 ;INPUT MAXIMUM 6NT IF JUST CR MOV A,L ;CONVERTED CHAR BACK TO A LHLD IPOINT ;LOAD MEMORY BUFFER POINTER LXI D,0080H ;OFFSET DAD D ;CALC MEMORY ADDR MOV M,A ;STORE NEW INPUT TO MEMORY EDITX: PRINT CRLF,$ LDA IPOINT ;LEAST SIGNIFICANT HALF OF ADDR INR A CHAR INSTR INBUF,8,'WRITE' ;WRITE EDITED SECTOR ON DISK? JC WRTDSK ;WRITE BUFFER BACK ON DISK INSTR INBUF,8,'STOP' ;STOP EDITING WITHOUT WRITING? JC ENDFIL ;EXIT HEXIN INBUF+2 ;CONV ASCII TO HEX JNC CKLIM ;IF NO ERROR, CHECK ADDR LDAX D  ;INCR BY ONE ANI 7FH ;COUNT MOD 128 STA IPOINT JMP PTX ;INPUT MORE DATA EDIT3: LXI H,0 SHLD LINE ;RESET LINE NO TO ZERO CALL PRTSEC ;PRINT BUFFER WITH HEADING JMP EDIT1 ;BACK FOR ADDITIONAL EDITING WRTDSK: CALLBIOS DWRITE ;WRITE BUFFE ;GET ASCII CHAR CPI '.' ;CHECK FOR EXIT CHAR JZ EDIT3 ;BACK FOR MORE EDITING JMP ADERR ;ADDRESS ERROR CKLIM: LXI D,0080H ;CHECK ADDR LIMIT CPHL JP ADERR ;ADDRESS ERROR SHLD IPOINT ;SAVE ADDRESS PRINT CRLF,$ PTX: HEXOUT IPOINT+1 HEXR BACK ON DISK JMP ENDFIL ;EXIT ; ; READ TRACK AND SECTOR DIRECT ; RDISK0: CALL FIXB RDISK: SETSEC BSEC ;SET SECTOR JC BADSEC ;WRONG SECTOR NO TRK2: SETTRK TRACK ;SET TRACK JC BADTRK ;WRONG TRACK NO LDA NEWDRV MOV E,A DISKIO LOGIN STA ESEC ;SAVE IN END SECTOR ALSO XCHG ;SET BUFFER POINTER FOR SCAN SHLD IPOINT ;SAVE BUFFER POINTER FOR EDIT INSTR ,40H,'-' ;SEARCH FOR '-' JNC EDIT ;CHECK FOR EDITION OF SECTOR SCAN DECIN ;SCAN AND CONVERT ANOTHER NO JC INERR ;ERROR!  UL READ JNZ ENDFIL ;1 INDICATES EOF CALL PRTBUF ;DO PRINT SUBROUTINE JMP RDFILE ;BACK FOR NEXT BLOCK ENDFIL: LDA INFLAG ;SEE WHERE TO GO ORA A JZ MONITOR JMP NEWIN ; ; ; PRTBUF - PRINT BUFFER IN HEX AND ASCII ; PRTBUF: MVI B,8 ;8 LI ' LXI H,0 LDA TRACK MOV L,A DECOUT PRINT ' SECTOR ' LXI H,0 LDA BSEC MOV L,A DECOUT PRINT CRLF,$ CALL PRTBUF ;PRINT IT LXI H,BSEC ;ADDR OF SECTOR NUMBER LDA ESEC ;END SECTOR NUMBER CMP M ;COMPARE THEM RZ ;EXIT IF THEY NES LXI H,80H ;INITIAL BUFFER POINTER SHLD IPOINT ;STORAGE FOR POINTER BPRN: LHLD IPOINT ;LOAD POINTER MVI C,16 ;CHAR PER LINE LDA LINE+1 ;LINE NUMBER SAVE B,H HEXOUT LDA LINE ;SECOND TWO DIGITS HEXOUT PRINT ' ' RESTORE H,B PLOARE EQUAL INR M ;INCR BSEC JMP RDISK PRNB: PRINT JMP PRNTRK ;PRINT TRACK AND SECTOR ; ; DUMP ENTIRE TRACK IF NO SECTOR INPUT ; WHLTRK: MVI A,1 ;BEGIN SECTOR STA BSEC MVI A,26 ;END SECTOR STA ESEC COP: MOV A,M ;GET A BYTE SAVE B,H HEXOUT PRINT SPACE,$ RESTORE H,B INX H ;INCR MEMORY POINTER MOV A,C CPI 9 ;CHECK 8 CHAR JNZ DECC ;SKIP IF NOT SAVE B,H PRINT SPACE,$ RESTORE H,B DECC: DCR C ;DECR CHAR COUNT JNZ PLOOP ;PRINT SALL RDISK0 ;TO READ DISK JMP ENDFIL ;BACK FOR MORE INPUT ; ; FILL IN FCB FOR NAMED FILE ; FILNAM: FILFCB FCB,82H ;FILL IN FCB NAME FROM INPUT BUFFER JC NAMERR ;ERROR IN FILE NAME MATCH FCB+9,'COM' ;TEST FOR COM FILE JNZ SELDR LXI H,100H OME MORE SAVE B PRINT SPACE,$ RESTORE B LHLD IPOINT ;RESET POINTER FOR ASCII MVI C,10H ;RESET CHAR COUNT PLOOP1: MOV A,M ;GET A BYTE ANI 7FH ;MASK OFF HIGH BIT CPI 7FH ;DELETE CODE JZ PERIOD ;PRINT PERIOD FOR DELETE CPI 20H ;TEST  SHLD LINE ;SET LINE NO. TO 100 SELDR: LDA NEWDRV ;SELECT NEW DRIVE MOV E,A DISKIO LOGIN DISKIO OPEN,FCB ;0PEN FILE CPI 255 ;CHECK FILE PRESENT JZ OPNERR ;EXIT IF ERROR RDFILE: DISKIO READ,FCB ;READ A BLOCK ORA A ;ZERO INDICATES SUCESSFFOR CONTROL CHAR JP SKIPX ;SKIP SUBSTITUTION PERIOD: MVI A,2EH ;ASCII PERIOD SKIPX: SAVE B,H CHAROUT ;PRINT IT SAVE REGS RESTORE H,B INX H ;INCR MEMORY POINTER MOV A,C CPI 9 ;CHECK 8 CHAR JNZ DECC2 SAVE B,H PRINT SPACE,$ RESTORE ;SELECT NEW DEIVE IF SPECIFIED CALLBIOS DREAD ;READ TRACK AND SECTOR ; ; PRINT DRIVE, TRACK AND SECTOR HEADING ; PRTSEC: LDA NEWDRV ;NEW DRIVE NO ORA A JNZ PRNB ;PRINT DRIVE B PRINT PRNTRK: PRINT ' TRACK"   TRACK '> LDA TNUM LXI H,0 MOV L,A DECOUT PRINT ' SECTOR ' LXI H,0 LDA SNUM MOV L,A DECOUT PRINT CRLF,$ MVI A,-1 STA VALFLG ;SET ERROR FLAG RET ; ; PRINT CONTROL AND ESCAPE ; PRNCON: MVI C,11 CALL 5 ANI 1 RZ ;RETURNOINT,16 ;INCR POINTER BY 16 JMP BPRN ;LOOP BACK ; ; THIS SECTION VALIDATES A DISK ; VALID: MVI A,1 ;START WITH SECTOR 1 STA SNUM XRA A ;START WITH TRACK 0 STA TNUM LDA NEWDRV ;SELECT NEW DRIVE MOV E,A DISKIO LOGIN RS0: SETTRK TNUM CHARIN ;READ CONSOLE CPI 3 ;TEST FOR CONTROL C JZ ENDFIL ;EXIT IF CONTROL C RET ; ; THIS SECTION DISPLAYS A CPM GROUP OF 8 SECTORS ; GROUP: SCAN ;GET THE GROUP NO DECIN ;CONVERT TO BINARY JC INERR ;INPUT ERROR IF CARRY SET ST JC BADTRK RS1: SETSEC SNUM JC BADSEC CALLBIOS DREAD ORA A CNZ VALERR ;ERROR IF NOT ZERO CALL PRNCON ;ESCAPE ON CONTROL C LDA SNUM ;SECTOR NO ADI 5 ;INCR BY 5 STA SNUM ;STORE IT BACK SBI 27 ;CALC SECTOR MOD 26 JM RS1 ;SECTOR OA G ;SAVE GROUP NO ADI 13 ;CHECK LEGAL RANGE JC BADGRP XRA A STA S ;SET SECTOR COUNT TO 0 CALL FIXB ;RESTORE DRIVE B IF SELECTED GRP1: CALL GRPTS ;CONVERT TO TRACK AND SECTOR CALL RDISK ;PRINT THE SECTOR LDA S ;CHECK SECTOR COUNT INK IF MINUS INR A ;SECTOR MOD 26 STA SNUM ;STORE IT BACK CPI 1 ;ARE WE BACK TO ONE YET JNZ RS1 ;READ SOME MORE LDA TNUM ;TRACK NUMBER INR A ;INCR BY ONE CPI 77 ;CHECK LIMIT JZ VALOUT ;TO EXIT STA TNUM ;STORE BACK TRACK NO JMP RSR A STA S ;INCR S BY 1 CPI 8 ;CHECK LIMIT JNZ GRP1 ;PRINT ANOTHER SECTOR JMP ENDFIL ;BACK FOR MORE INPUT ; ; GRPTS CONVERT CPM GROUP AND SECTOR NUMBER TO TRK AND SEC ; GRPTS: MVI H,0 ;ZERO H LDA G ;GROUP NO MOV L,A ;TO L MOV D,H0 ;BACK TO READ ROUTINE VALOUT: LDA VALFLG ;CHECK ERROR FLAG ORA A JNZ ENDFIL PRINT LDA NEWDRV ORA A JNZ VAL2 PRINT ' DRIVE A' JMP ENDFIL VAL2: PRINT ' DRIVE B' JMP ENDFIL VALERR: PRINT DECOUT G ;PRINT NO OF UNUSED SECTORS PRINT <' GROUPS REMAINING ON DISK OUT OF 243',CR,LF> JMP ENDFIL ;EXIT ; ; THIS ROUTINE SORTS AND DISPLAYS THE DIRECTORY ; (NOT IMPLEMENTED IN THIS VERSION) ; DIR: JMP ENDFIL ;EXIT ; ; THIS'> LDA NEWDRV ;LOGGED DRIVE ORA A JNZ DRB ;DRIVE B PRINT <' A',CR,LF,LF> JMP MAP1 DRB: PRINT <' B',CR,LF,LF> MAP1: LHLD IPOINT ;POINTER TO DISK ALLOCATION MAP MVI D,8 ;NO OF LINES MAP2: MVI C,4 ;WORDS PER LINE MAPX: SAVE PRINT '  ROUTINE RESTORES DRIVE B ; FIXB: LDA NEWDRV ;CHECK DRIVE NO ORA A RZ ;RETURN IF DRIVE A LDA NEWDRV ;SELECT DRIVE B MOV E,A DISKIO LOGIN XRA A STA TNUM ;SELECT TRACK ZERO INR A ;SELECT SECTOR 1 STA SNUM SETSEC SNUM SETTRK TNUM ' RESTORE MAP3: MVI B,8 ;BITS PER WORD MOV A,M ;GET A BYTE FROM ALLOC MAP MAP4: RAL ;SHIFT LEFT THRU CARRY SAVE B,D,H,PSW JC MAP5 ;PRINT A ONE PRINT '0' ;PRINT A ZERO LDA G ;UNUSED GROUPS INR A ;ADD 1 STA G ;STORE IT BACK  CALLBIOS DHOME ;HOME DRIVES CALLBIOS DREAD ;READ TRACK ZERO DIRECT RET ; ; ERROR AND EXIT ROUTINES ; ; INERR: PRINT JMP ENDFIL ; BADSEC: PRINT JMP ENDFIL ; BADTRK: PRINT JMP ENDFIL ; BADGRP: PRINT JMP ENDFIL ; OPNERR: LDA NEWDRV ;CURRENT DRIVE NO ORA A JNZ OPNER1 PRINT JMP ENDFIL OPNER1: DAD D STA TRACK ;STORE TRACK NO MOV A,M ;GET SECTOR NO STA BSEC ;SAVE IN BEGINNING SECTOR STA ESEC ;SAVE IN END SECTOR TOO RET $+PRINT ; ; THIS ROUTINE DISPLAYS THE DISK SECTOR ALLOCATION MAP ; MAP: LDA NEWDRV MOV E,A DISKIO LO$  FOR OLD STACK POINTER ENDSTK: DS 24 ;STORAGE FOR NEW STACK NEWSTK: DW 0 ;NEW STACK INB: DW 0 ;STORES POINTER TO INPUT BUFFER AREA OUTB: DW 0 ;STORES POINTER TO DIRECTORY BUFFER AREA TABLE: DB 01H ;SECTOR LOOK UP TABLE DB 07H DB 0DH DB 13H  ; HEXERR: PRINT JMP PTX ; MONITOR: PRINT CRLF,$ LDA DRVNO ;RESTORE LOGGED DRIVE NO MOV E,A DISKIO LOGIN LHLD OLDSTK SPHL ;RESET OLD STACK POINTER RET ; ; ; DATA ALLOCATIONS ; FCB EQU 5CH  DB 19H DB 05H DB 0BH DB 11H DB 17H DB 03H DB 09H DB 0FH DB 15H DB 02H DB 08H DB 0EH DB 14H DB 1AH DB 06H DB 0CH DB 12H DB 18H DB 04H DB 0AH DB 10H DB 16H PDIR DW 0 ;POINTER TABLE TO DIRECTORY (64 ENTRIES MAX) D ;FILE CONTROL BLOCK SPACE: DB ' $' ;ASCII SPACE CRLF: DB 0DH,0AH,24H ;ASCII CR LF I: DW 0 ;PSEUDO INDEX REGISTER LINE: DW 0 ;LINE NUMBER FOR LISTING IPOINT: DW 00 ;VARIABLE BUFFER POINTER INBUF: DS 10 ;USED AS CONSOLE INPUT BUFFER LASTIN: DB 0IRBUF: EQU PDIR+130 ;START OF AREA USED TO STORE AND SORT DIRECTORY END B 06H DB 0CH DB 12H DB 18H DB 04H DB 0AH DB 10H DB 16H PDIR DW 0 ;POINTER TABLE TO DIRECTORY (64 ENTRIES MAX) D ;LAST CONSOLE INPUT CHAR INFLAG: DB 0 ;FLAG, RET FOR MORE CONSOLE INPUT DRVNO: DB 0 ;STORAGE FOR ORIGINALLY LOGGED DRIVE NEWDRV: DB 0 ;STORAGE FOR NEW DRIVE NO TRACK: DB 0 ;SELECTED TRACK BSEC: DB 0 ;SELECTED BEGINNING SECTOR ESEC: DB 0 ;SELECTED ENDING SECTOR TNUM: DB 0 ;TRACK NO FOR VALIDATE SNUM: DB 0 ;SECTOR NO FOR VALIDATE VALFLG: DB 0 ;VALIDATION ERROR FLAG G: DB 0 ;CPM GROUP NO S: DB 0 ;SECTOR NO WITHIN GROUP G COUNT: DB 0 ;COUNT OF DIRECTORY ENTRIES OLDSTK: DW 0 ;STORAGE  PRINT JMP ENDFIL ; RDERR: PRINT JMP MONITOR NAMERR: PRINT JMP ENDFIL ; ADERR: PRINT JMP EDIT1 ;ADDRESS ERROR ON EDIT %  s Club in the Washington/Oregon area. Instructions are built-in. Place DUU.COM in drive A. At the A> prompt, type DUU One interesting function permits identification of erased files on any disk. Place the disk of interest in drive B and DUU.COM in drive A. At the A> prompt, type DUU LB;M;X For further information, refer to DUU.DOC. Since DUU.ASM was not available, I included DU.ASM, an earlier version, for those interested in techniques used. DUMP is from -CPMUG.024. This is not the same as DUMP.COM provided on the Osborne CP/M disk. For instructions, refer to the first few lines of DUMP.ASM. I am not positive that the .COM file was a direct result of the .ASM file; however, it does work as described.  Jim Woolley FOG Disk Librarian September, 1982 UMP.ASM. I am not positive that the .COM file was a direct result of the .ASM file; however, it does work as described.  DISK.DOC -FOG/UTL.006 First Osborne Group (FOG) Utilities Disk This disk contains utilities to read and write a disk by byte, sector, track, etc. DUU was received from the Northwest Osborne User&  '