home *** CD-ROM | disk | FTP | other *** search
- ; 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
- ;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 time delay used in
- ;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. *
- ;* If you 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 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 *
- ;* register. 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 *
- ;* *
- ;*************************************************
- ;
- ;
- ;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-
- ; ment 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/M 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
- ; '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.
- ; (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 <nn> form was used. Display
- ; unprintables as <nn> 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/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. Ratoff, 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, W8SDZ
- ;
- ;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 # 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 EQU 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
- ;
- 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
- ;
- ORG BASE+100H
- ;
- JMP PASTCK ;JUMP OVER CLOCK BYTE AND I.D.
- ;
- CLOCK: DB 0 ;<---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
- 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
- MOV A,H ;COMBINE THE TWO BYTE...
- ORA L ;...VERSION NR FOR A FLAG
- STA VER2FL ;SAVE IT
- LXI H,3000H ;INITIALIZE "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 ;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
- ;
- 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 ILPRT
- 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 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
- STA 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 '>'
- 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 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 QFLAG
- 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 '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 tracks:',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
- ;
- ;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 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 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?
- 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
- 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
- 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 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 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
- ;
- VSELDK: CALL $-$ ;ADDR FILLED IN BY 'INIT'
- LDA VER2FL
- ORA A ;IF NOT CP/M 2.x ...
- JZ SELSKP ;..THEN SKIP THIS 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 ; 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 ;MAKE 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 IN 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 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
- 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
- POP 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 TYPE ;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
- 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
- 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-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 & 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: 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
- 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 '++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 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 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 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.
- 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
- 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
- ;"<<" 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 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,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
- 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
- JZ VIEWPR
- ;
- VIEWHX: MOV A,M ;NOT ASCII...PRINT AS <NN>
- 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,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 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
- 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
- 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
- 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
- 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 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 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
- 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,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
- 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, 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 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
- ;
- 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 D
- 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
- 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 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 DE
- 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 TYPE
- ;
- CHGA3: SHLD BACK ;IN CASE "THRU"
- CALL GETVAL ;ASCII OR <HEX>
- 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 DELIM
- 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',CR,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 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
- ;
- 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
- ;
- ;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 CR
- 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
- 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
- INX 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 RDBLP
- ;
- 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
- 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
- ORA A
-
- VCONOT: CZ $-$ ;ADDR FILLED IN BY 'INIT'
- ;
- ;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 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
- ;
- 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
- VHOME: CALL $-$ ;ADDR FILLED IN BY 'INIT'
- 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
- 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
- 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-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 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
- CALL 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 FILLED 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 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
- ;
- WRITOK: 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 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 <xx> for hex:'
- DB CR,LF
- DB ' To find "IN 0" use: =<db><0> or'
- DB CR,LF
- DB ' "(tab)H,0(CR)(LF)" use: =<9>H,0<D><A>'
- 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 '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 ' <xx> 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
- DB '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,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 or 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
- ;
- ;********************************
- ;* *
- ;* Utility 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 VER2FL
- ORA A ;IF NOT 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
- XCHG
- 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
- 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
- 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
- ;--------------------------------------------------
- ;
- SAVBUF: DS 128
- INBUF: DS 128
- ;
- ;Directory read in here; also search work area
- ;
- WORK EQU $
- DIRECT EQU $
- ;
- END
-