home *** CD-ROM | disk | FTP | other *** search
- ;PROGRAM: DUTIL
- ;AUTHOR: RICHARD CONN
- ;DERIVATION: DUTIL is derived from DU Version 7.5
- ;VERSION: 1.1
- ;DATE: 21 NOV 81
- ;PREVIOUS VERSIONS: 1.0 (1 JAN 81)
-
- VERS EQU 11 ; DUTIL Version Number
-
- ;
- ; DUTIL is derived from --
- ; DU.ASM V7.5 Revised 1/23/81
- ; DISK UTILITY - By Ward Christensen
- ;
- ; Principal Authors of DU V7.5 are --
- ; WLC KBP RGF BRR
- ;
- ; Key comments from DU V7.5 and DUTIL follow --
- ;
- ;This version of DU is compatible with CP/M 1.4 and 2.x
- ;and does not require 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.
- ;
- ;For DUTIL, the additional value of PAGSIZ at 104h should
- ;be set for the size of the display (in lines) on the user's
- ;CON: device. Under DUTIL, all output is paged, and this
- ;determines the page limit.
- ;
- ;*************************************************
- ;* *
- ;* This program has been heavily modified *
- ;* to allow it to work without modification *
- ;* on most versions of CP/M 1.4 and, hopefully, *
- ;* all versions of CP/M 2.x. *
- ;* If 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 *
- ;* *
- ;*************************************************
- ;
- ; The last few revision notes for note are --
- ;
- ;01/23/81 Changed SETSEC to ignore high-order result of
- ; SECTRN if SPT<256. This fixes some 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)
- ;
-
- ;
- ;System equates
- ;
- BASE EQU 0 ;SET TO 4200H FOR HEATH OR TRS-80 ALTCPM
- ;
- ;CP/M Key Areas
- ;
- FCB EQU BASE+5CH ;CP/M FCB
- BDOS EQU BASE+5 ;CP/M BDOS ENTRY POINT
- TBUFF EQU BASE+80H ;CP/M TEMPORARY DISK I/O BUFFER
- TPA EQU BASE+100H ;CP/M TRANSCIENT PROGRAM AREA
- ;
- ;CP/M BDOS Function Codes
- ;
- PRINT EQU 9
- GVERS EQU 12
- RESETDK EQU 13
- SELDK EQU 14
- SRCHF EQU 17 ;SEARCH FIRST
- SUSER EQU 32
- GETDSK EQU 25
- GETDPB EQU 31
- ;
- ;CP/M 1.4 Offsets and Some Key Values
- ;
- TRNOFF EQU 15 ;CP/M 1.4 OFFSET FROM BASE
- ;OF BDOS TO SECTRAN ROUTINE
- SKWOFF EQU 1AH ;CP/M 1.4 OFFSET TO SKEW TABLE
- S2OFF EQU 14 ;OFFSET INTO FCB FOR S2 BYTE
- DPBOFF EQU 3AH ;CP/M 1.4 OFFSET TO DPB WITHIN BDOS
- S2MASK EQU 0FH ;MASK FOR EXTENDED RC BITS OF S2
- DPBLEN EQU 15 ;SIZE OF CP/M 2.x DISK PARM BLOCK
- ;
- ;Define ASCII characters
- ;
- CR EQU 0DH ;CARRIAGE RETURN
- LF EQU 0AH ;LINE FEED
- TAB EQU 09H ;TAB
- BS EQU 08H ;BACKSPACE
-
-
-
- ;
- ;Beginning of Program
- ;
- ORG TPA
- JMP START ;JUMP OVER CLOCK BYTE AND I.D.
- ;
- CLOCK:
- DB 2 ;<---Put Processor Speed Here (1=1MHZ, 2=2MHZ, etc)
- PAGSIZ:
- DB 24 ;<---Put CRT Screen Size Here (24 Lines default)
- DB 'DUTIL.COM from DU.COM ver 7.5 1/23/81 by RLC'
- ;
- START:
- LXI H,0 ;GET PTR TO CP/M STACK
- DAD SP ;HL=SP
- SHLD DUTSTK ;SAVE IT
- ;
- LXI SP,DUTSTK ; SET STACK
- ;
- MVI C,GVERS ;GET CP/M VERSION NR
- CALL BDOS
- MOV A,H ;COMBINE THE TWO BYTE...
- ORA L ;...VERSION NR FOR A FLAG
- STA VER2FL ;SAVE IT
- ;
- ;Set up local jumps to BIOS
- ;
- LHLD BASE+1 ;WARM BOOT POINTER
- LXI D,3 ;READY FOR ADD
- DAD D
- SHLD VCONST+1 ;CON: Status
- DAD D
- SHLD VCONIN+1 ;CON: Input
- DAD D
- SHLD VCONOT+1 ;CON: Output
- DAD D
- SHLD VLIST+1 ;LST: Output
- DAD D ;Skip PUNCH
- DAD D ;Skip RDR
- DAD D
- SHLD VHOME+1 ;Home Disk
- DAD D
- SHLD VSELDK+1 ;Select Disk
- DAD D
- SHLD VSETRK+1 ;Set Track
- DAD D
- SHLD VSTSEC+1 ;Set Sector
- DAD D
- SHLD SETDMA+1 ;Set DMA Address
- DAD D
- SHLD VREAD+1 ;Read Block From Disk
- DAD D
- SHLD VWRITE+1 ;Write Block To Disk
- LDA VER2FL
- ORA A
- JZ DOCPM1
- DAD D ;Skip LISTST
- DAD D
- SHLD VSCTRN+1 ;CP/M 2.x Sector Translation Table
- JMP HELLO
- ;
- ;Set up CP/M 1.4 Parameters
- ;
- DOCPM1:
- LHLD BDOS+1
- MVI L,0 ;BDOS ON PAGE BOUNDARY
- PUSH H
- LXI D,TRNOFF ;CP/M 1.4 SECTRAN ROUTINE OFFSET
- DAD D
- SHLD VSCTRN+1 ;CP/M 1.4 Sector Translation Table
- POP H
- LXI D,SKWOFF ;CP/M 1.4 SKEW TABLE OFFSET
- DAD D
- SHLD SECTBL ;SET UP SKEW TABLE POINTER
- ;
- ;Initialization Complete -- Print Signon Message and Begin Command Processing
- ;
- HELLO:
- CALL GETSTP ;SET UP CP/M PARAMETERS
- CALL INITP ;INITIALIZE BUFFER PARAMETERS
- XRA A ;NOT QUIET
- STA QFLAG
- CALL ILPRT
- DB CR,LF,'DUTIL - Disk Utility, Version '
- DB VERS/10+'0','.',(VERS MOD 10)+'0'
- DB CR,LF,' Derived From DISK UTILITY ver 7.5, '
- DB 'Universal Version',CR,LF
- DB CR,LF
- DB 'Type ? for Help'
- DB CR,LF,0
- LXI H,TBUFF ;TO INPUT BUFF
- MOV A,M
- ORA A
- JZ PRMPTR ;NO INITIAL COMMAND FROM COMMAND LINE
- ;
- ;Got initial command, set it up
- ;
- MOV B,A ;SAVE LENGTH
- DCR B ;JUST A SPACE?
- JZ PRMPTR ;GOTO COMMAND PROCESSOR IF SO
- LXI D,INBUF ;PT TO INLINE BUFFER
- INX H ;SKIP LEN
- INX H ;SKIP ' '
- MOV A,M ;GET FIRST CHAR
- CPI '/' ;IF SLASH, PRINT INITIAL HELP (TOOLSET CONVENTION)
- JZ IHELP ;PRINT INITIAL HELP INFO
- CALL MOVE ;COPY INPUT LINE INTO INLINE BUFFER
- MVI A,CR ;STORE ENDING <CR>
- STAX D
- LXI H,INBUF ;PT TO FIRST BYTE OF INLINE BUFFER
- JMP PRMPTI ;PROCESS AS THOUGH IT WAS TYPED
- ;
- ;Input Command Line From User at Console
- ;
- PRMPTR:
- XRA A ;A=0
- STA QFLAG ;Set Not Quiet
- CALL SINBUF ;Save old INBUF into PINBUF
- CALL RDBUF ;Read Input Line
- CALL EXMAC ;Expand Macros
- ;
- ;Begin Processing Command Line in INBUF
- ; At this point, HL points to next character to process
- ;
- PRMPTI:
- MVI A,0FFH ;SET INFINITE LOOP COUNT
- STA TOGO ;LOOP COUNT FOR "/"
- STA TOGO+1
- ;
- ;Minor Command Loop; This is the entry point for each individual command in
- ; a Command Line; Commands may be separated by semicolons in this manner
- ;
- PROMPT EQU $
- SETSTK:
- LXI SP,DUTSTK ;RESET STACK
- XRA A ;ZERO 2-UP PRINT FOR DUAL-COLUMN PRINT
- STA TWOUP ;..SWITCH
- MVI A,1
- STA FTSW ;TELL SEARCH NOT TO INCR
- PUSH H
- LXI H,TBUFF ;SET NO-READ INPUT BUFFER ADDRESS
- SHLD 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
- ;
- ;Begin Command Evaluation -- Check for EOL and Capitalize
- ;
- MOV A,M ;GET NEXT CHAR IN COMMAND LINE
- INX H ;POINT TO FOLLOWING CHAR
- CPI CR ;END OF LINE PHYSICALLY?
- JZ PRMPTR ;INPUT NEW COMMAND LINE IF SO
- CPI ';' ;END OF LINE LOGICALLY?
- JZ PROMPT ;PROCESS NEXT ELEMENT IF SO
- CALL UPCASE ;CAPITALIZE COMMAND
- STA DUMTYP ;TYPE OF DUMP (A,D,H)
- ;
- ;Command dispatcher
- ; If command not found, abort with error message
- ; If command file, process command with HL pting to next command char and
- ; A containing command letter
- ;
- PUSH H ;SAVE HL
- MOV B,A ;COMMAND IN B
- LXI H,CMDTBL ;SCAN COMMAND TABLE FOR USER COMMAND
- CMDLP:
- MOV A,M ;GET COMMAND
- ORA A ;0=END OF TABLE
- JZ WHAT
- CMP B ;COMPARE COMMAND
- JZ CMDGO
- INX H ;PT TO ADR
- INX H
- INX H ;PT TO NEXT CMND
- JMP CMDLP
- CMDGO:
- INX H ;PT TO ADDRESS LOW
- MOV E,M
- INX H ;PT TO ADDRESS HIGH
- MOV D,M
- MOV A,B ;COMMAND BACK INTO A
- POP H ;RESTORE HL
- PUSH D ;PLACE ADDRESS ON STACK
- RET ;"RUN COMMAND"
- ;
- ;Macro Expansion Routine -- Expand Macros
- ;
- EXMAC:
- LXI H,INBUF ;PT TO INPUT LINE
- LXI D,CTEMP ;BUILD INTO TEMPORARY BUFFER
- EXMAC1:
- MOV A,M ;GET CHAR
- CPI '0' ;SKIP IF LESS THAN '0'
- JC EXMAC2
- CPI '9'+1 ;CHECK FOR RANGE
- JNC EXMAC2
- INX H ;PT TO NEXT CHAR
- PUSH H ;SAVE PTR TO NEXT CHAR IN LINE
- SUI '0' ;CONVERT TO BINARY (0-9)
- MOV B,A ;RESULT IN B
- MVI C,0
- LXI H,MTABL ;PT TO BASE OF MACROS
- DAD B ;PT TO MACRO
- CALL COPYM ;COPY MACRO INTO LINE
- DCX D ;BACK UP OVER <CR>
- POP H ;GET PTR TO NEXT CHAR IN COMMAND LINE
- EXMAC2:
- MOV A,M ;GET CHAR
- STAX D ;PUT CHAR
- INX H ;PT TO NEXT
- INX D
- CALL MTEST ;TEST FOR END OF BUFFER
- CPI CR ;DONE?
- JZ EXMAC3
- CPI ';' ;LOGICAL EOL?
- JNZ EXMAC2
- JMP EXMAC1 ;PROCESS NEXT COMMAND
- EXMAC3:
- LXI H,CTEMP ;COPY COMMAND LINE BACK
- LXI D,INBUF ;INTO INBUF
- CALL COPYCR ;COPY TO <CR>
- LXI H,INBUF ;PT TO INBUF
- RET ;EXPANSION COMPLETE
- ;
- ;Copy Macro Into Command Line Buffer
- ;
- COPYM:
- MOV A,M ;GET CHAR
- STAX D ;PUT CHAR
- INX H ;PT TO NEXT
- INX D
- CALL MTEST ;CHECK FOR LIMIT
- CPI CR ;END OF MACRO?
- JNZ COPYM
- RET
- ;
- ;Test for Buffer Full
- ;
- MTEST:
- PUSH H ;SAVE HL
- PUSH PSW ;SAVE A
- LXI H,CTEMPX ;CHECK FOR END OF BUFFER
- MOV A,H ;GET PAGE
- CMP D ;CHECK PAGE
- JZ MACERR
- POP PSW ;GET A
- POP H ;GET HL
- RET
- ;
- ;Macro Command Expansion Error
- ;
- MACERR:
- XRA A ;NOT QUIET
- STA QFLAG
- CALL ILPRT
- DB CR,LF,'Error -- Macro Expanded Command Line too Long',0
- JMP PRMPTR ;NEW COMMAND
- ;
- ;Save INBUF into PINBUF for later processing by '@' command
- ;
- SINBUF:
- LXI H,INBUF ;PT TO INBUF
- LXI D,PINBUF ;PT TO PINBUF (PREVIOUS INBUF)
- ;
- ;Copy (HL) to (DE) until <CR> Encountered
- ;
- COPYCR:
- MOV A,M ;GET CHAR
- STAX D ;PUT CHAR
- INX H ;PT TO NEXT
- INX D
- CPI CR ;DONE?
- JNZ COPYCR
- RET
-
- ;
- ;Command Not Found Error
- ;
- WHAT:
- XRA A ;TURN OFF QUIET FLAG
- STA QFLAG
- POP H ; RESTORE HL
- CALL ILPRT
- DB 'Invalid Command -- ',0
- MOV A,B ;GET COMMAND LETTER
- CALL TYPE ;PRINT IT
- JMP PRMPTR
- ;
- ;Memory full error
- ;
- MEMFUL:
- XRA A ;TURN OFF QUIET FLAG
- STA QFLAG
- CALL ILPRT
- DB '+++ Out of memory +++'
- DB CR,LF,0
- JMP PRMPTR
- ;
- ;COMMAND: @
- ;Repeat Previous Command Line
- ;
- PCMD:
- MOV A,M ;GET NEXT CHAR
- CPI CR ;SHOULD BE <CR>
- JZ PCMD1
- XRA A ;NOT QUIET
- STA QFLAG
- CALL ILPRT
- DB CR,LF,'Warning: Remainder of Command Line after "@" Deleted',0
- PCMD1:
- XRA A ;NOT QUIET
- STA QFLAG
- CALL ILPRT
- DB CR,LF,'Command --',CR,LF,0
- LXI H,PINBUF ;GET PREVIOUS COMMAND
- LXI D,INBUF ;COPY INTO INBUF
- PCMD2:
- MOV A,M ;GET CHAR
- STAX D ;PUT CHAR
- INX H ;PT TO NEXT
- INX D
- CPI CR ;END OF LINE?
- PUSH PSW ;SAVE FLAG
- CALL TYPE ;PRINT CHAR
- POP PSW ;GET FLAG
- JNZ PCMD2
- MVI A,LF ;<LF>
- CALL TYPE
- LXI H,INBUF ;RESTART COMMAND PROCESSING
- JMP PRMPTI ;INCLUDE LOOP CAPABILITY
- ;
- ;COMMAND: :
- ;Define or Print Macro
- ;:n<text> Defines Macro n, 0<=n<=9; ::n Prints Macro n, 0<=n<=9
- ;
- MAC:
- MOV A,M ;GET NEXT CHAR
- CALL UPCASE ;CAPITALIZE
- CPI 'P' ;PRINT MACRO?
- JNZ MACROD ;IF NOT, DEFINE MACRO
- INX H ;PT TO MACRO NUMBER
- MOV A,M ;GET IT
- CALL UPCASE ;CAPITALIZE
- CPI '@' ;PRINT PREVIOUS COMMAND?
- JZ PCPR
- PUSH PSW ;SAVE A
- XRA A ;A=0
- STA QFLAG ;NOT QUIET
- CALL ILPRT
- DB 'Macro Definitions --',0
- POP PSW ;GET A
- CPI 'A' ;PRINT ALL MACROS?
- JZ AMACPR
- CALL MNUM ;CHECK FOR VALID NUMBER AND RETURN # IN D
- INX H ;PT TO CHAR AFTER MACRO NUMBER
- CALL MACPR ;PRINT MACRO WHOSE NUMBER IS IN D
- JMP PROMPT
- ;
- ;Print Previous Command
- ;
- PCPR:
- INX H ;PT TO CHAR AFTER '@'
- LXI D,PROMPT ;SET UP RET ADR
- PUSH D ;RETURN ADR ON STACK
- PUSH H ;SAVE PTR
- XRA A ;NOT QUIET
- STA QFLAG
- CALL ILPRT
- DB 'Previous Command Line Definition --'
- DB CR,LF,'@: ',0
- LXI H,PINBUF ;PT TO PREVIOUS COMMAND
- JMP MPRINT ;USE MACRO PRINT FACILITY
- ;
- ;Print All Macros
- ;
- AMACPR:
- INX H ;PT TO CHAR AFTER 'A'
- MVI D,0 ;SET FOR FIRST MACRO
- AMPRL:
- CALL MACPR ;PRINT MACRO WHOSE NUMBER IS IN D
- INR D ;INCREMENT MACRO NUMBER
- MOV A,D ;GET VALUE
- CPI 10 ;DONE?
- JNZ AMPRL
- JMP PROMPT ;CONTINUE PROCESSING
- ;
- ;Print Macro Whose Number (0-9) is in D
- ;
- MACPR:
- PUSH H ;SAVE PTR
- XRA A ;NOT QUIET
- STA QFLAG
- CALL ILPRT ;PRINT HEADER
- DB CR,LF,0
- MOV A,D ;GET NUMBER
- ADI '0' ;CONVERT TO ASCII
- CALL TYPE ;PRINT
- CALL ILPRT
- DB ': ',0
- LXI H,MTABL ;PT TO TABLE OF MACROS
- MVI E,0 ;PAGE OFFSET OF ZERO; MACRO NUMBER ALREADY IN D
- DAD D ;PT TO MACRO
- MPRINT:
- MOV A,M ;GET CHAR
- INX H ;PT TO NEXT
- CPI CR ;END OF MACRO?
- PUSH PSW ;SAVE FLAG
- CALL TYPE ;PRINT CHAR
- POP PSW ;GET FLAG
- JNZ MPRINT
- MVI A,LF ;<LF>
- CALL TYPE
- POP H ;GET PTR TO NEXT CHAR
- RET
- ;
- ;Check char in A for valid Macro Number (0-9), print error message if
- ; not, return number in D if so
- ;
- MNUM:
- SUI '0' ;CONVERT TO 0-9
- JC MNERR ;ERROR IF LESS
- CPI 10 ;RANGE?
- JNC MNERR
- MOV D,A ;RESULT IN D
- RET
- MNERR:
- XRA A ;NOT QUIET
- STA QFLAG
- CALL ILPRT
- DB CR,LF,'Invalid Macro Number Specified in Command',0
- JMP PRMPTR ;NEW COMMAND
- ;
- ;Define Macro
- ;
- MACROD:
- CALL MNUM ;CHECK NUMBER AND RETURN IN D
- INX H ;PT TO CHAR AFTER MACRO NUMBER
- PUSH H ;SAVE PTR
- LXI H,MTABL ;PT TO MACRO TABLE
- MVI E,0 ;SET EVEN PAGE
- DAD D ;PT TO MACRO ENTRY IN HL
- XCHG ;... IN DE
- POP H ;PT TO MACRO TEXT
- CALL COPYCR ;COPY TO <CR>
- JMP PRMPTR ;NEW COMMAND
- ;
- ;COMMAND: !
- ;Delay for user input
- ;
- UWAIT:
- CALL WAIT ; USE WAIT ROUTINE
- JMP PROMPT
- ;
- ;COMMAND: #
- ;Print disk statistics
- ;
- STATS:
- PUSH H ;SAVE POINTER TO NEXT COMMAND
- CALL ILPRT
- DB '===============================',CR,LF
- DB ' -- Disk Information -- ',CR,LF
- DB '-------------------------------',CR,LF
- DB CR,LF,'Disk Drive: ',0
- LDA DRIVE
- ADI 'A' ;CONVERT TO ASCII
- CALL TYPE ;PRINT DRIVE LETTER
- CALL ILPRT
- DB CR,LF,'Tracks: ',0
- LHLD MAXTRK ;PRINT NUMBER OF TRACKS
- INX H
- CALL DEC
- CALL ILPRT
- DB CR,LF,'Sectors/Track: ',0
- LHLD SPT ;PRINT NUMBER OF SECTORS/TRACK
- CALL DEC
- CALL ILPRT
- DB CR,LF,'Group Size: ',0
- LDA BLM ;PRINT SIZE OF A GROUP
- INR A
- MOV L,A
- MVI H,0
- CALL DEC
- CALL ILPRT
- DB ' Blocks/Group'
- DB CR,LF,'Total Groups: ',0
- LHLD DSM ;PRINT TOTAL NUMBER OF GROUPS ON A DISK
- CALL DEC
- CALL ILPRT
- DB CR,LF,'Directory Entries: ',0
- LHLD DRM ;PRINT NUMBER OF DIRECTORY ENTRIES
- INX H
- CALL DEC
- CALL ILPRT
- DB CR,LF,'System Tracks: ',0
- LHLD SYSTRK ;PRINT NUMBER OF SYSTEM TRACKS
- CALL DEC
- CALL ILPRT
- DB CR,LF
- DB '===============================',CR,LF,0
- POP H ;RESTORE POINTER TO NEXT COMMAND
- JMP PROMPT
- ;
- ;COMMAND: N
- ;The following command resets the disk
- ;system thru CP/M, and may be usable for
- ;changing the disk density or format.
- ;This can only be done if your BIOS resets
- ;the auto-density select parameters at
- ;every track-zero access.
- ;
- NEWDSK:
- PUSH H ;SAVE POINTER TO NEXT LETTER
- MVI C,RESETDK ;BDOS RESET DISK FUNCTION
- CALL BDOS
- LDA DRIVE ;RESELECT CURRENT DRIVE
- MOV C,A
- POP H
- CALL SELECT
- JMP PROMPT
- ;
- ;COMMAND: Q
- ;Quite mode
- ;
- QUIET:
- STA QFLAG ;NOW QUIET (FLAG IS NON-ZERO)
- JMP PROMPT
- ;
- ;COMMAND: /
- ;Repeat buffer contents
- ;
- REPEAT:
- CALL DECIN ;NN SPECIFIED?
- MOV A,D
- ORA E
- JZ NNN ;NO -- SET FOR INFINITE LOOP OR SIMPLE REPEAT
- LHLD TOGO ;LOAD LOOP FLAG
- INX H ;TEST FOR FIRST TIME
- MOV A,H
- ORA L ;WAS IT 0FFFFH?; IF SO, WE HAVE NEW VALUE
- JNZ NNN ;NO: COUNTING
- XCHG ;GET COUNT
- SHLD TOGO ;SET COUNT
- ;
- NNN:
- LHLD TOGO ;GET CURRENT COUNT
- XCHG ;DE=CURRENT COUNT, HL=COUNT LIMIT
- LXI H,INBUF ;PT TO FIRST CHAR FOR REPEAT
- INX D ;TEST FOR 0FFFFH
- MOV A,D ;IF 0FFFFH, INX D MADE DE=0
- ORA E
- JZ PROMPT ;CONTINOUS LOOP IF 0FFFFH
- DCX D ;COUNT DOWN
- DCX D ;MAKE UP FOR PREV INX D
- XCHG
- SHLD TOGO ;SET NEW COUNT (1 LESS THAN BEFORE)
- MOV A,H ;ALL DONE?
- ORA L
- XCHG ;GET BACK INBUF PTR IN HL
- JNZ PROMPT ;KEEP GOING IF NOT YET ZERO
- JMP PRMPTR ;ALL DONE
- ;
- ;COMMAND: U
- ;Set CP/M 2.x user number
- ;
- USER:
- LDA VER2FL ;CP/M 2.X?
- ORA A
- JZ WHAT ;ERROR IF NOT
- CALL DECIN ;GET REQUESTED USER NO.
- MOV A,E
- CPI 32 ;VALID?
- JNC WHAT
- MOV A,D ;HIGH-ORDER BYTE MUST BE ZERO FOR VALID NUMBER
- ORA A
- JNZ WHAT
- MOV A,E ;SAVE USER NUMBER
- STA UNUM
- MVI C,SUSER ;SET USER NUMBER
- PUSH H ;SAVE CHAR POINTER
- CALL BDOS ;SET USER NO.
- POP H
- JMP PROMPT
- ;
- ;COMMAND: P
- ;Toggle print flag
- ;
- PRNTFF:
- LDA PFLAG ;TOGGLE PRINT FLAG
- XRI 1
- STA PFLAG
- JMP PROMPT
- ;
- ;COMMAND: Z
- ;Sleep routine, in seconds
- ;
- SLEEP:
- CALL DECIN ;GET COUNT IF ANY
- MOV A,E ;ANY?
- ORA A
- JNZ SLEPLP
- MVI E,1 ; 1 SEC DEFAULT
- ;
- SLEPLP:
- LDA CLOCK ; GET CLOCK SPEED
- MOV D,A
- ;
- SLEEP1:
- LXI B,41700 ; APPROX 1 SEC @ 1MHz
- ;
- SLEEP2:
- DCX B ;COUNT DOWN FOR 1 MHz [5 CYCLES]
- MOV A,B ;[5 CYCLES] <-- TOTAL TIME: 24 CYCLES
- ORA C ;[4 CYCLES] <-- (24 MU-SECS AT 1MHz)
- JNZ SLEEP2 ;[10 CYCLES]
- PUSH D
- CALL CTLCS ;ABORT?
- POP D
- JZ PRMPTR
- DCR D ;COUNT DOWN FOR CLOCK SPEED
- JNZ SLEEP1
- DCR E ;COUNT DOWN NUMBER OF REQUESTED SECONDS
- JNZ SLEPLP
- JMP PROMPT
- ;
- ;Check for control-C or S
- ;
- CTLCS:
- CALL CONST ;CHAR AVAILABLE?
- ORA A
- JNZ GETC
- ORI 1 ;NO CHAR, RETURN NZ
- RET
- ;
- GETC: CALL CONIN ;INPUT CHAR
- ANI 1FH ;ALLOW ASCII
- CPI 'S'-40H ;WAIT FOR NEXT CHAR IF ^S OR S OR s
- CZ CONIN
- CPI 'C'-40H ;CHECK FOR ^C OR C OR c
- RET ;0 SET IF CTL-C
- ;
- ;Initialize Memory Buffers
- ;
- INITP:
- XRA A ;A=0
- STA GLFLAG ;CLEAR GROUP LOADED FLAG (GROUP NOT LOADED)
- STA HEXAD ;CLEAR ADDRESS
- STA HEXAD+1
- STA PFLAG ;SET NO PRINT
- STA SAVEFL ;SET NO SAVE DONE
- STA WRFLG ;MAY NOT WRITE
- STA DIRPOS ;SET NO DIRECTORY POSITION
- STA FINDFL ;SET NO POSITION
- INR A ;A=1
- STA FTSW ;SET SEARCH WITHOUT INCREMENT
- STA NOTPOS ;NOT POSITIONED
- LXI H,0 ;HL=0
- SHLD MFPTR ;SET NO MULTI FILE PTR
- SHLD CURTRK ;SET TRACK 0
- INX H ;HL=1
- SHLD CURSEC ;SET LOGICAL SECTOR 1
- SHLD PHYSEC ;SET PHYSICAL SECTOR 1
- MVI A,CR ;CLEAR PREVIOUS COMMAND
- STA PINBUF ;SET PREVIOUS COMMAND TO NIL
- LXI H,MTABL ;CLEAR MACRO TABLE
- MVI B,10 ;10 ENTRIES
- INITP1:
- MVI M,CR ;STORE <CR>
- INR H ;PT TO NEXT PAGE
- DCR B ;COUNT DOWN
- JNZ INITP1
- RET
- ;
- ;Set up flags, etc, at initialization
- ;Find our way at initialization
- ;
- GETSTP:
- MVI A,CR ;INITIALIZE INPUT BUFFER
- STA INBUF ;EMPTY BUFFER
- LDA VER2FL ;VERSION 2 OR BETTER?
- ORA A ;0=1.X
- JZ GSTP1
- MVI C,SUSER ;GET USER NUMBER
- MVI E,0FFH ;GET USER
- CALL BDOS
- STA UNUM ;SET USER NUMBER
- GSTP1:
- MVI C,GETDSK
- CALL BDOS ;GET CURRENT DISK
- MOV C,A ;WE HAVE TO SELECT
- JMP SELECT ;TO GET THE DPH
- ;
- ;COMMAND: L
- ;Log in the selected disk
- ;
- LOGIN:
- CALL DOLOG
- JMP PROMPT
- ;
- DOLOG:
- MOV A,M ;DISK REQUESTED?
- LXI D,0
- CPI CR ;NO REQUEST OF PHYSICAL EOL
- JZ LGNODK
- CPI ';' ;NO REQUEST IF LOGICAL EOL
- JZ LGNODK
- CALL UPCASE ;CAPITALIZE
- INX H ;POINT TO NEXT CHAR
- SUI 'A' ;CONVERT TO 0-15
- MOV C,A ;DISK NUMBER IN C
- ;
- ;Select Disk Whose Number is in C (A=0, B=1, etc)
- ;
- SELECT:
- PUSH H ;SAVE PTR TO NEXT COMMAND LETTER
- MOV A,C
- STA DRIVE ;REMEMBER LATER WHERE WE ARE
- ;
- VSELDK: CALL $-$ ;ADDR FILLED IN BY 'INIT'
- LDA VER2FL
- ORA A ;IF NOT CP/M 2.x ...
- JZ SELSKP ;..THEN SKIP THIS JUNK
- MOV A,H
- ORA L
- JZ WHAT ;SELECT ERROR
- MOV E,M ;GET THE SECTOR TABLE PNTR
- INX H
- MOV D,M
- INX H
- XCHG
- SHLD SECTBL ;SET THE SECTOR TABLE PTR
- LXI H,8 ;OFFSET TO DPBPTR
- DAD D
- MOV A,M ;PICK UP DPB POINTER
- INX H ; TO USE
- MOV H,M ; AS PARAMETER
- MOV L,A ; TO LOGIT
- ;
- SELSKP:
- CALL LOGIT
- LHLD SYSTRK ;RESET TRACK AND SECTOR
- XCHG ; TO DIRECTORY
- CALL SETTRK ; ON EVERY
- LXI D,1 ; LOGIN
- CALL SETSEC ; CHANGE
- LHLD PHYSEC ;THIS LOGIC WILL TELL
- MOV A,H ; IF FIRST SEC
- ORA L ; IS PHYSICAL 0
- STA FIRST0
- CALL CLCSUB ;CALCULATE WHAT GROUP/GRPDISP WE ARE IN
- POP H ;GET PTR TO NEXT LETTER
- ;
- LGNODK:
- CALL NORITE ;SET NO DISK I/O DONE (NO POSITION)
- RET
- ;
- ;Read in the disk directory
- ;
- REDDIR:
- PUSH H ;SAVE PTR TO NEXT LETTER
- CALL NORITE ;POSITIONING LOST
- LHLD SYSTRK ;SAVE CURRENT TRACK
- SHLD CURTRK
- LXI H,1 ;SET SECTOR 1
- SHLD CURSEC
- LHLD DRM ;GET DIR SIZE FROM DPB
- INX H ;MAKE 1-RELATIVE
- CALL ROTRHL
- CALL ROTRHL ;DIVIDE BY 4 (4 NAMES/SECTOR)
- MOV B,H ;BC=NUMBER OF BLOCKS TO READ
- MOV C,L
- LXI D,DIRECT ;DMA ADDR
- XRA A ;A=0
- STA GLFLAG ;SAY NO GROUP LOADED
- ;
- ;Read Disk Directory Loop
- ;
- RDIRLP:
- PUSH B ;SAVE REGS
- PUSH D
- MOV B,D ;BC=DMA ADDRESS
- MOV C,E
- LDA BDOS+2 ;CHECK MEM AVAIL
- DCR A ;ARE WE RNNING INTO BDOS?
- CMP D
- JC MEMFUL ;MEMORY FULL ERROR IF SO
- CALL SETDMA ;SET DMA ADDRESS TO THAT IN BC
- LHLD CURTRK ;SET TRACK
- XCHG
- CALL SETTRK
- LHLD CURSEC ;SET SECTOR
- XCHG
- CALL SETSEC
- CALL READ ;READ DIRECTORY BLOCK
- CALL NXTSEC ;INCREMENT TO NEXT SECTOR
- POP D
- POP B
- LXI H,80H ;ADVANCE TO NEXT DMA ADDRESS
- DAD D
- XCHG ;DE=NEXT DMA ADDRESS
- DCX B ;COUNT DOWN DIRECTORY BLOCKS
- MOV A,B
- ORA C
- JNZ RDIRLP
- LXI B,TBUFF ;RESET DMA ADDRESS TO TBUFF
- CALL SETDMA
- POP H ;GET PTR TO NEXT CHAR
- RET
- ;
- ;COMMAND: M
- ;Map the directory
- ;
- MAP:
- CALL PAGSET ;SET PAGING COUNTER
- XRA A
- STA ONLY1 ;SET FLAG FOR ALL GROUPS (NOT ONLY 1)
- CALL REDDIR ;READ IN DIRECTORY
- MVI C,0 ;INIT START GRP #
- LDA AL0 ;READ DIR GRP BITS
- CALL 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 ;GET SPECIFIED GROUP IF ANY
- PUSH H ;SAVE INBUF PTR
- MOV A,E ;GET START
- ORA D ;NOTHING?
- JZ MAPDF ;..YES, DFLT
- MVI A,0FFH ;SET FLAG FOR ONLY 1 GROUP
- STA ONLY1
- MOV B,D ;GET VALUE IN BC
- MOV C,E
- ;
- MAPDF:
- CALL HEXB ;PRINT FIRST GROUP NUMBER
- MVI A,'-' ;PRINT SEPARATOR
- CALL TYPE
- MVI A,' ' ;SET NO DUPLICATES
- STA DUPFLG
- CALL GETGRP ;GET GRP(C) TO HL
- ;
- 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 ;ABORT?
- JZ MAPND2
- MOV A,D
- CMP H
- JNZ MAPDIF
- MOV A,E
- CMP L
- JZ MAPCNT ;SAME, CONTINUE
- ;
- ;Different file encountered
- ;
- MAPDIF:
- DCX B
- CALL HEXB ;PRINT ENDING GROUP NUMBER
- INX B
- XCHG
- CALL MAPNAM ;PRINT FILE NAME
- LDA ONLY1 ;ONLY 1 NAME TO BE PRINTED?
- ORA A ;0=NO
- JNZ MAPND1
- JMP MAPDF
- ;
- ;End of map
- ;
- MAPEND:
- DCX B ;GET LAST
- CALL HEXB ;PRINT LAST GROUP NUMBER
- CALL MAPNAM ;PRINT FILE NAME
- CALL WAIT ;DELAY FOR USER
- MAPND1:
- POP H
- CALL CRLF ;NEW LINE
- ;
- ;End of map - reposition to previous group
- ;
- MAPND2:
- PUSH H
- LHLD GROUP ;POINT TO GROUP IN DE
- XCHG
- JMP POSGP2
- ;
- ;Print file name pointed to by HL
- ;
- MAPNAM:
- CALL SPACE ;LEADING SPACE
- MOV A,H
- ORA L ;NONE?
- JZ NONAME
- MOV A,M ;SEE IF ALLOC
- CPI 0E5H ;FREE?
- MVI A,' ' ;MARK ALLOCATED
- JNZ MPNSP1
- MVI A,'(' ;MARK NOT ALLOCATED (ERASED FILE)
- ;
- MPNSP1:
- CALL TYPE ;PRINT ALLOCATION INDICATOR (SPACE OR '(')
- PUSH H ;SAVE POINTER
- MOV A,M
- CALL HEX ;SHOW USER NUMBER
- CALL SPACE
- INX H ;SKIP USER BYTE
- PUSH B
- MVI B,8 ;PRINT FILE NAME
- CALL MAPN2
- MVI A,'.' ;PRINT DECIMAL SEPARATOR
- CALL TYPE
- MVI B,3 ;PRINT FILE TYPE
- CALL MAPN2
- LDA DUPFLG ;DUPLICATE?
- CALL TYPE ;SPACE OR STAR
- POP B
- MOV A,M ;GET EXT
- CALL HEX ;PRINT EXTENT NUMBER
- POP H
- MOV A,M
- CPI 0E5H ;DELETED ENTRY?
- MVI A,' ' ;PRINT ENDING SPACE
- JNZ MPNSP2
- MVI A,')' ;PRINT ALLOCATION FLAG
- ;
- MPNSP2:
- CALL TYPE ;")" IF ERASED FILE OR SPACE IF NOT
- JMP FLIP
- ;
- NONAME:
- CALL ILPRT
- DB ' ++ Free ++ ',0
- ;
- FLIP:
- LDA TWOUP ;FLIP FLAG FOR TWO ENTRIES PER LINE
- XRI 1
- STA TWOUP
- JZ PAGER ;NEW LINE WITH PAGING IF REQUIRED
- ;
- DELIM:
- MVI A,':' ;PRINT DELIMITER BETWEEN ADJACENT ENTRIES ON LINE
- CALL TYPE
- JMP SPACE
- ;
- ;Print name pted to by HL, length in B
- ;
- MAPN2:
- MOV A,M
- ANI 7FH ;STRIP POSSIBLE 2.x ATTRIBUTE BIT
- INX H
- CPI ' ' ;PRINTABLE?
- JC MAPN2H ;..NO, IN HEX
- CPI 7EH ;7E IS LEADIN ON SOME CRTS
- JC MAPN2A
- ;
- MAPN2H:
- CALL BHEX ;PRINT A AS HEX CHARS
- JMP MAPN2Z
- ;
- MAPN2A:
- CALL TYPE ;PRINT AS CHAR
- ;
- MAPN2Z:
- DCR B ;COUNT DOWN
- JNZ MAPN2
- RET
- ;
- ;Find which file group (BC) belongs to
- ;
- GETGRP:
- LHLD DRM ;MAX DIR ENTRY #
- INX H ;MAKE 1-RELATIVE
- SHLD FILECT
- LXI H,0
- SHLD MFPTR ;SET MULTI-FILE (MORE THAN ONE USER) PTR
- LXI H,DIRECT ;PT TO DIRECTORY
- XRA A ;SAY NO GROUP LOADED
- STA GLFLAG
- ;
- GETGLP:
- PUSH H ;SAVE POINTER TO NAME
- MOV A,M ;PICK UP DN BYTE
- CPI 0E5H ;ERASED?
- 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 NOT FOUND
- ;
- ;Found the file
- ;
- PUSH H ;SAVE GROUP PTR
- LHLD MFPTR
- MOV A,H ;ANY ENTRIES?
- ORA L
- POP H ;GET PTR
- XTHL ;SAVE ENTRY START AND SAVE PTR
- JZ MPFRST ;IF ZERO, THEN FIRST ENTRY
- MVI A,'*' ;SET MULTI FLAG
- STA DUPFLG
- MPFRST:
- SHLD MFPTR ;SAVE POINTER
- XTHL ;RESTORE ENTRY START AND GET PTR
- NOTGOT:
- DCR E ;COUNT DOWN
- JNZ GETGL2 ;GO TEST SOME 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
- ;
- ;Set the allocation address, if any
- ;
- LHLD MFPTR ;GET ADDRESS
- RET
- ;
- ;COMMAND: <
- ;Save the current sector
- ;
- SAVE:
- LDA WRFLG ;READ DONE?
- ORA A
- JZ BADW ;NONE TO SAVE
- PUSH H
- LXI H,TBUFF ;COPY FROM TBUFF
- LXI D,SAVBUF ;INTO SAVBUF
- MVI B,128 ;128 BYTES
- CALL MOVE
- MVI A,1 ;..SHOW
- STA SAVEFL ;..SAVED EXISTS
- POP H ;GET PTR TO NEXT CHAR
- JMP PROMPT
- ;
- ;This routine is common to Save Group (RG) and Write Group (WG); it is used
- ; to extract the group number, check it, and position DUTIL to it
- ; On exit, GROUP = Group Number, GRPDIS = 0, and DUTIL is positioned
- ;
- COMG:
- INX H ;PT TO CHAR AFTER 'G' OF '<G' COMMAND
- MOV A,M ;GET CHAR AFTER 'G'
- CALL UPCASE ;CAPITALIZE
- CPI ';' ;ERROR IF LOGICAL EOL
- JZ WHAT
- CPI CR ;ERROR IF PHYSICAL EOL
- JZ WHAT
- CALL HEXIN ;GET GROUP NUMBER IN HEX
- PUSH H ;SAVE PTR TO NEXT CHAR
- LHLD DSM ;CHECK FOR BOUNDS ERROR
- CALL SUBDE ;SUBTRACT GROUP NUMBER FROM DSM
- POP H ;RESTORE PTR
- JC OUTLIM ;LIMIT ERROR IF CARRY
- XCHG ;SAVE GROUP NUMBER
- SHLD GROUP
- SHLD TGRP ;TEMPORARY GROUP NUMBER
- XCHG ;GROUP NUMBER IN DE
- XRA A ;A=0
- STA GRPDIS ;SET GROUP DISPLACEMENT
- PUSH H ;SAVE PTR TO NEXT CHAR
- CALL GTKSEC ;CONVERT GROUP NUMBER TO TRACK AND SECTOR
- CALL SETTRK ;SET TRACK
- XCHG
- CALL SETSEC ;SET SECTOR
- POP H ;GET PTR TO NEXT CHAR
- RET
- ;
- ;This is the Save Group Routine; it copies the indicated group into the save
- ; buffer.
- ;
- SAVEG:
- CALL COMG ;EXTRACT COMMON GROUP INFO -- GROUP NUMBER AND POS
- PUSH H
- CALL ILPRT
- DB 'Reading from Group ',0
- LHLD GROUP ;GET CURRENT GROUP
- MOV B,H ;VALUE IN BC
- MOV C,L
- CALL HEXB ;PRINT AS HEX
- CALL ILPRT
- DB CR,LF,0
- POP H
- MVI A,0FFH ;SET GROUP LOADED FLAG
- STA GLFLAG ;GROUP HAS BEEN LOADED
- MVI A,0 ;SET COPY FUNCTION TO SAVE
- STA CPYFCT ;0=READ, 0FFH=WRITE
- ;
- ;Group Copy Routine -- if CPYFCT = 0, Read Group; if CPYFCT = 0FFH, Write Group
- ;
- COPYG:
- PUSH H ;SAVE PTR TO NEXT CHAR IN COMMAND LINE
- CALL NORITE ;POSITIONING LOST
- LXI D,GBUFF ;PT TO BUFFER
- LDA BLM ;GET NUMBER OF BLOCKS/GROUP
- INR A ; ADD 1 TO BLM FOR CORRECT COUNT
- MOV B,A ;COUNT IN B
- ;
- COPYGL:
- PUSH B ;SAVE COUNT
- PUSH D ;SAVE PTR TO NEXT BLOCK TO LOAD
- LDA BDOS+2 ;CHECK THAT MEMORY ISN'T FULL
- CMP D ;COMPARE TO LOAD ADDRESS
- JC MEMFUL
- MOV B,D ;SET BC=DE FOR SET DMA
- MOV C,E
- CALL SETDMA ;SET ADDRESS TO LOAD
- LDA CPYFCT ;READ OR WRITE?
- ORA A ;0=READ
- PUSH PSW ;SAVE FLAGS
- CZ READ ;READ BLOCK
- POP PSW ;GET FLAGS
- CNZ PWRITE ;WRITE BLOCK (NO CHECK)
- CALL NXTSEC ;COMPUTE NEXT SECTOR ADDRESS
- LHLD CURTRK ;GET NEXT TRACK ADDRESS
- XCHG ;... IN DE
- CALL SETTRK ;SET IT
- LHLD CURSEC ;GET NEXT SECTOR ADDRESS
- XCHG ;... IN DE
- CALL SETSEC ;SET IT
- POP D ;GET PTR TO NEXT BLOCK
- POP B ;GET COUNTER
- LXI H,80H ;OFFSET TO NEXT BLOCK
- DAD D
- XCHG ;DE PTS TO NEXT BLOCK
- DCR B ;COUNT DOWN
- JNZ COPYGL ;LOOP UNTIL FINISHED
- LXI B,TBUFF ;RESET DMA ADDRESS
- CALL SETDMA
- XRA A ;A=0
- STA WRFLG ;SET NO READ DONE
- LHLD TGRP ;GET GROUP NUMBER
- XCHG ;... IN DE
- POP H ;GET PTR TO NEXT CHAR
- JMP POSGRP ;POSITION TO GROUP IN DE AND CONTINUE PROCESSING
- ;
- ;COMMAND: >
- ;Restore the current sector
- ;
- RESTOR:
- LDA SAVEFL ;SAVE DONE PREVIOUSLY?
- ORA A
- JZ NOSAVE ;NONE TO SAVE
- PUSH H
- LXI H,SAVBUF ;COPY FROM SAVBUF
- LXI D,TBUFF ;INTO TBUFF
- MVI B,128 ;128 BYTES
- CALL MOVE
- POP H ;GET PTR TO NEXT CHAR
- JMP PROMPT
- ;
- ;Write Group Loaded in GBUFF to Disk
- ;
- RESTRG:
- LDA GLFLAG ;GROUP ALREADY LOADED?
- ORA A ;0=NO
- JZ RGERR
- CALL COMG ;GET GROUP NUMBER FROM COMMAND LINE AND POS
- PUSH H
- CALL ILPRT
- DB 'Writing to Group ',0
- LHLD GROUP ;GET GROUP NUMBER
- MOV B,H ;VALUE IN BC
- MOV C,L
- CALL HEXB ;PRINT IN HEX
- CALL ILPRT
- DB CR,LF,0
- POP H
- MVI A,0FFH ;WRITE FUNCTION
- STA CPYFCT ;COPY FUNCTION FOR GROUP COPY ROUTINE
- JMP COPYG ;GROUP COPY ROUTINE
- ;
- RGERR:
- XRA A ;NOT QUIET
- STA QFLAG
- CALL ILPRT
- DB '++ No "RG" Read Group Command Issued or Loaded Group'
- DB ' Trashed ++'
- DB CR,LF,0
- JMP PRMPTR
- ;
- NOSAVE:
- XRA A ;NOT QUIET
- STA QFLAG
- CALL ILPRT
- DB '++ No "<" Save Command Issued ++'
- DB CR,LF,0
- JMP PRMPTR
- ;
- ;Move (HL) to (DE) length in B
- ;
- MOVE:
- MOV A,M
- STAX D
- INX H
- INX D
- DCR B
- JNZ MOVE
- RET
- ;
- NORITE:
- XRA A ;GET 0
- STA WRFLG ;CAN'T WRITE NOW
- RET
- ;
- ;No match in search, try next char
- ;
- SRNOMT:
- POP H
- CALL CTLCS ;ABORT?
- JNZ SEARCH ;..YES
- LXI H,INBUF
- MVI M,CR
- JMP CLCGRP ;SHOW WHERE STOPPED
- ;
- ;COMMAND: =
- ;Search for character string
- ;
- SEARCH:
- PUSH H ;SAVE STRING POINTER
- ;
- SRCHL:
- CALL RDBYTE ;GET A BYTE
- MOV B,A ;SAVE IT
- MOV A,M ;CHECK NEXT MATCH CHAR.
- CPI '<' ;WILL IT BE HEX?
- MOV A,B ;RESTORE DISK CHAR
- JZ SRCHL1
- ANI 7FH ;NEXT CHAR IS ASCII...STRIP BIT 7
- ;
- SRCHL1:
- PUSH PSW
- CALL GETVAL ;GET SEARCH VALUE
- MOV B,A
- POP PSW
- CMP B ;MATCH?
- JNZ SRNOMT ;NO MATCH
- INX H
- MOV A,M ;DONE?
- CPI CR ;END OF LINE?
- JZ SREQU
- CPI ';' ;LOGICAL EOL?
- JNZ SRCHL
- ;
- ;Got match
- ;
- SREQU:
- XRA A ;NOT QUIET
- STA QFLAG
- CALL ILPRT
- DB '= at ',0
- LDA BUFAD
- ANI 7FH
- CALL HEX
- CALL CRLF
- JMP CLCGRP
- ;
- ;Get value from input buffer
- ;
- GETVAL:
- MOV A,M ;GET NEXT CHAR
- CPI '<' ;HEX ESCAPE?
- RNZ ;NO, RETURN
- ;"<<" means one "<"
- INX H
- MOV A,M
- CPI '<'
- RZ
- ;Got hex
- PUSH D
- CALL HEXIN ;GET VALUE
- CPI '>' ;PROPER DELIM?
- MOV A,E ;GET VALUE
- POP D
- JNZ WHAT ;ERROR
- RET
- ;
- ;Read a byte at a time from disk
- ;
- RDBYTE:
- 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 ;ADVANCE TO NEXT BLOCK
- ;
- READ1:
- XRA A
- STA FTSW ;NOT FIRST READ
- LHLD CURSEC
- XCHG
- CALL SETSEC
- LHLD CURTRK
- XCHG
- CALL SETTRK
- CALL READ
- CALL CLCSUB
- LXI H,TBUFF
- ;
- NORD:
- MOV A,M
- INX H
- SHLD BUFAD
- POP H
- RET
- ;
- ;COMMAND: V
- ;View the file in ASCII starting at
- ;current sector, stepping thru the disk
- ;
- VIEW:
- LDA WRFLG
- ORA A
- JZ BADDMP
- CALL DECIN ;GET DISPL IF ANY
- PUSH H
- MOV A,E
- ORA A
- JNZ VIEWLP
- INR E ;DFLT=1
- ;
- VIEWLP:
- LXI H,TBUFF ;TO DATA
- ;
- VEWCHR:
- CALL CTLCS ;ABORT?
- JZ VEWEND
- MOV A,M ;GET NEXT CHAR
- CPI 1AH ;EOF?
- JZ VEWEOF
- ANI 7FH ;MASK
- CPI 7EH ;ESC CHAR FOR H1500
- JNC VIEWHX ;SHOW RUBOUT AND TILDE AS HEX
- CPI ' '
- JNC VIEWPR
- CPI CR ;CR PASS
- JZ VIEWPR
- CPI LF ;LF PASS
- JZ VIEWPR
- CPI TAB ;TAB PASS
- JZ VIEWPR
- ;
- VIEWHX:
- MOV A,M ;NOT ASCII...PRINT AS <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,' ++ EOF ++',CR,LF,0
- ;
- VEWEND:
- POP H
- CALL CRLF
- JMP CLCGRP
- ;
- ;COMMAND: A or D
- ;Dump in hex or ASCII
- ;
- DUMP:
- LDA WRFLG
- ORA A
- JNZ DUMPOK
- ;
- BADDMP:
- XRA A
- STA QFLAG ;NOT QUIET
- CALL ILPRT
- DB '++ Can''t dump, no sector read ++',CR,LF,0
- ;
- EXPL:
- XRA A
- STA QFLAG ;NOT QUIET
- CALL ILPRT
- DB 'Use G command following F,',CR,LF
- DB 'or R or S following T',CR,LF,0
- JMP PRMPTR
- ;
- DUMPOK:
- MOV A,M ;GET NEXT CHAR
- CPI ';' ;LOGICAL EOL?
- JZ DUMPDF ;DFLT
- CPI CR ;PHYSICAL EOL?
- JNZ DMPNDF
- ;
- ;Use default
- ;
- DUMPDF:
- LXI B,TBUFF
- LXI D,0FFH
- JMP DUMP1
- ;
- DMPNDF:
- CALL DISP
- MOV B,D
- MOV C,E
- CPI CR
- JZ DUMP1
- CPI ';'
- JZ DUMP1
- INX H ;SKIP ','
- CALL DISP
- ;
- ;BC = start, DE = end
- ;
- DUMP1:
- PUSH H ;SAVE COMMAND POINTER
- MOV H,B
- MOV L,C
- ;
- DUMPLP:
- MOV A,L
- ANI 7FH
- CALL HEX ;PRINT HEX VALUE
- CALL SPACE
- CALL SPACE
- LDA DUMTYP
- CPI 'A'
- JZ DUMPAS
- PUSH H ;SAVE START
- ;
- DHEX:
- MOV A,M
- CALL HEX ;PRINT HEX VALUE PTED TO BY HL
- MOV A,L
- ANI 3
- CPI 3 ;EXTRA SPACE EVERY 4
- CZ SPACE
- MOV A,L
- ANI 7
- CPI 7 ;TWO EXTRA SPACES EVERY 8
- CZ SPACE
- MOV A,E
- CMP L
- JZ DPOP
- INX H
- MOV A,L
- ANI 0FH
- JNZ DHEX
- ;
- DPOP:
- CALL CTLCS ;ABORT?
- JZ PRMPTR
- LDA DUMTYP
- CPI 'H'
- JZ DNOAS ;HEX ONLY
- POP H ;GET START ADDR
- ;
- DUMPAS:
- CALL ASTER ;PRINT FIRST ASTERISK TO SEPARATE TEXT
- ;
- DCHR:
- MOV A,M ;GET CHAR
- ANI 7FH
- CPI ' '
- JC DPER
- CPI 7EH ;TRAP ESC FOR H1500
- JC DOK
- ;
- DPER:
- MVI A,'.' ;PRINT PRINTING CHAR
- ;
- DOK:
- CALL TYPE ;PRINT CHAR
- MOV A,E
- CMP L
- JZ DEND
- INX H
- MOV A,L
- ANI 0FH
- JNZ DCHR
- ;
- DEND:
- CALL ASTER ;PRINT ENDING ASTERISK
- CALL CRLF ;NEW LINE
- PUSH D
- CALL CTLCS ;ABORT?
- POP D
- JZ PRMPTR
- MOV A,E
- CMP L
- JNZ DUMPLP
- POP H
- JMP PROMPT
- ;
- DNOAS:
- POP B
- CALL CRLF
- MOV A,E
- CMP L
- JNZ DUMPLP
- POP H
- JMP PROMPT
- ;
- ;COMMAND: G
- ;Position
- ;
- POS:
- PUSH PSW
- MOV A,M
- CPI ';' ;LOGICAL EOL?
- JZ POSINQ
- CPI CR ;PHYSICAL EOL?
- JNZ POSOK
- ;
- POSINQ:
- POP PSW
- JMP INQ
- ;
- POSOK:
- POP PSW
- CPI 'T' ;TRACK?
- JZ POSTKD
- CPI 'S' ;SECTOR?
- JZ POSSCD
- CPI 'G' ;GROUP?
- JZ POSGPH
- JMP WHAT ;ERROR OTHERWISE
- ;
- ;Position to Track
- ;
- POSTKD:
- CALL DECIN ;GET NUMBER IN DECIMAL
- ;
- POSTRK:
- PUSH H
- LHLD MAXTRK ;CHECK FOR BEYOND END OF DISK
- CALL SUBDE
- POP H
- JC OUTLIM
- CALL SETTRK ;SET TRACK
- CALL NORITE ;TRACK DOESN'T READ
- MVI A,1
- STA NOTPOS ;SHOW NOT POSITIONED
- JMP CLCGRP
- ;
- ;Position to Sector
- ;
- POSSCD:
- CALL DECIN ;GET NUMBER IN DECIMAL
- MOV A,D
- ORA E
- JZ WHAT ;DON'T ALLOW SECTOR 0
- ;
- POSSEC:
- PUSH H
- LHLD SPT ;CHECK FOR WITHIN RANGE
- CALL SUBDE
- POP H
- JC WHAT
- CALL SETSEC ;SET SECTOR
- CALL READ ;READ
- XRA A
- STA NOTPOS ;POSITIONED OK
- ;
- ;Calculate Group Number/Group Displacement and Print
- ;
- CLCGRP:
- CALL CLCSUB
- JMP INQ
- ;
- ;Calculate group from track and sector
- ; On exit, GROUP = Group Number and GRPDIS = Displacement within Group
- ;
- CLCSUB:
- PUSH H
- LHLD SYSTRK
- XCHG
- LHLD CURTRK
- CALL SUBDE ;COMPUTE RELATIVE TRACK NUMBER (SKIP SYSTEM TRACKS)
- XCHG
- LHLD SPT ;MULTIPLY BY NUMBER OF SECTORS/TRACK
- CALL MULT
- XCHG ;DE=TOTAL NUMBER OF SECTORS IN TRACKS
- LHLD CURSEC ;GET SECTOR OFFSET FROM BEGINNING OF TRACK
- DCX H
- DAD D ;HL=TOTAL NUMBER OF SECTORS WITH OFFSET
- LDA BLM
- MOV B,A
- MOV A,L
- ANA B
- STA GRPDIS ;DISPLACEMENT WITHIN GROUP
- LDA BSH
- MOV B,A
- ;
- CLCLOP:
- CALL ROTRHL
- DCR B
- JNZ CLCLOP
- SHLD GROUP ;GROUP NUMBER
- POP H
- RET
- ;
- ;Position in the directory after a find
- ;(Does not work in CP/M-2.x)
- ;
- POSDIR:
- PUSH H ;SAVE INBUF
- LHLD BSH
- XRA A
- STA FINDFL ;CANCEL POS REQ
- LDA DIRPOS ;GET POSITION
- RAR
- RAR
- PUSH PSW
- ANA H
- STA GRPDIS
- POP PSW
- ;
- POSDLP:
- RAR
- DCR L
- JNZ POSDLP
- ANI 1 ;GET GROUP
- MOV L,A ;SETUP FOR POSGP2
- MVI H,0
- SHLD GROUP
- XCHG
- JMP POSGP2 ;POSITION TO IT
- ;
- ;Position to Group
- ;
- POSGPH:
- CALL HEXIN ;GET PARAMETER
- ;
- ;Position to Group Numbered in DE and Print Position
- ;
- POSGRP:
- PUSH H
- LHLD DSM ;CHECK FOR WITHIN BOUNDS
- CALL SUBDE
- POP H
- JC OUTLIM
- XCHG
- SHLD GROUP ;SET GROUP NUMBER
- XCHG
- XRA A
- STA GRPDIS ;SET ZERO DISPLACEMENT
- PUSH H
- ;
- POSGP2:
- CALL GTKSEC ;CONVERT GROUP TO SECTOR/TRACK
- CALL SETTRK ;SET TRACK
- XCHG
- CALL SETSEC ;SET SECTOR
- CALL READ ;READ BLOCK
- XRA A
- STA NOTPOS ;NOW POSITIONED
- POP H
- JMP INQ
- ;
- ;Convert Group Number in DE to Sector and Track; also, GRPDIS = Offset in Grp
- ; On exit, DE = Track Number, HL = Sector Number
- ;
- GTKSEC:
- MOV H,D ;HL=GROUP NUMBER
- MOV L,E
- LDA BSH ;GET NUMBER OF SECTORS IN GROUP
- ;
- GLOOP:
- DAD H
- DCR A
- JNZ GLOOP
- LDA GRPDIS ;ADD IN DISPLACEMENT WITHIN GROUP
- ADD L ;CAN'T CARRY
- MOV L,A
- ;
- ;Divide by number of sectors, quotient=track, remainder=sector
- ;
- XCHG ;DE=TOTAL NUMBER OF SECTORS
- LHLD SPT ;GET NUMBER OF SECTORS/TRACK
- CALL NEG ;HL = -SECTORS/TRACK
- XCHG
- LXI B,0 ;SET TRACK COUNTER TO ZERO
- ;
- DIVLP:
- INX B ;INCREMENT TRACK COUNT
- DAD D ;SUBTRACT SECTORS/TRACK FROM SECTORS TOTAL
- JC DIVLP
- DCX B ;ADJUST TRACK COUNT
- XCHG
- LHLD SPT ;ADD SECTORS/TRACK BACK IN TO ADJUST
- DAD D ;HL=NUMBER OF SECTORS ON LAST TRACK OF GROUP
- PUSH H
- LHLD SYSTRK ;ADD IN NUMBER OF SYSTEM TRACKS
- DAD B
- XCHG ;DE=TRACK NUMBER
- POP H
- INX H ;HL=SECTOR NUMBER
- RET
- ;
- ;COMMAND: F
- ;Find Directory Entry for specified file
- ;
- POSFIL:
- CALL 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,TBUFF
- 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 ;GET NEXT CHAR OF FILE NAME/TYPE
- CPI '.' ;END OF FILE NAME?
- JZ MVIPAD ;PAD OUT IF SO
- CPI CR ;END OF ENTRY?
- JZ PAD ;PAD OUT IF SO
- CPI ';' ;END OF ENTRY?
- JZ PAD ;PAD OUT IF SO
- CALL UPCASE ;CAPITALIZE
- STAX D ;STORE
- INX H ;PT TO NEXT
- INX D
- DCR B ;COUNT DOWN
- JNZ MVNAME
- MOV A,M ;CHECK FOR ERROR
- CPI CR ;OK IF EOL
- RZ
- CPI ';' ;OK IF LOGICAL EOL
- RZ
- INX H
- CPI '.' ;OK IF DECIMAL
- RZ
- JMP WHAT
- ;
- MVIPAD:
- INX H
- ;
- PAD:
- MVI A,' ' ;PRINT PADDING SPACES
- STAX D
- INX D
- DCR B
- JNZ PAD
- RET
- ;
- ;COMMAND: +
- ;Advance to Next Logical Sector
- ;
- PLUS:
- LXI D,1 ;DFLT TO 1 SECT
- MOV A,M ;GET NEXT CHAR
- CPI CR ;CR?
- JZ PLUSGO ;..YES, DFLT TO 1
- CPI ';'
- JZ PLUSGO
- CALL DECIN ;GET #
- MOV A,D
- ORA E
- JZ WHAT
- ;
- PLUSGO:
- CALL NXTSEC ;ADVANCE TO NEXT LOGICAL SECTOR
- DCX D ;MORE TO GO?
- MOV A,D
- ORA E
- JNZ PLUSGO ;..YES
- ;
- ;Ok, incremented to sector. Setup and read
- ;
- PLUSMI:
- PUSH H
- LHLD CURSEC
- XCHG
- CALL SETSEC ;SET SECTOR
- LHLD CURTRK
- XCHG
- CALL SETTRK ;SET TRACK
- POP H
- CALL READ ;READ IT
- JMP CLCGRP ;CALCULATE GROUP AND DISPLAY
- ;
- ;COMMAND: -
- ;Back up to previous sector
- ;
- MINUS:
- LXI D,1 ;SET DFLT
- MOV A,M ;GET CHAR
- CPI CR ;CR?
- JZ MINGO ;..YES, DFLT=1
- CPI ';'
- JZ MINGO
- CALL DECIN ;..NO, GET ##
- MOV A,D
- ORA E
- JZ WHAT
- ;
- MINGO:
- PUSH H
- LHLD CURSEC ;BACK UP SECTOR
- DCX H
- MOV A,H
- ORA L
- JNZ MINOK
- LHLD CURTRK ;BEYOND SECTOR ZERO, SO BACK UP TRACK
- MOV A,H
- ORA L
- JNZ SEASH
- LHLD MAXTRK ;WRAP TO END OF DISK
- SHLD CURTRK
- LHLD MAXSEC
- JMP MINOK
- ;
- SEASH:
- DCX H
- SHLD CURTRK
- LHLD SPT ;GET NUMBER OF SECTORS/TRACK
- ;
- MINOK:
- SHLD CURSEC ;SET NEW CURRENT SECTOR
- POP H
- DCX D ;COUNT DOWN ON NUMBER OF TIMES TO BACKUP
- MOV A,D
- ORA E
- JNZ MINGO
- JMP PLUSMI ;READ BLOCK
- ;
- ;Go to next sector
- ; On exit, CURSEC = Current Sector and CURTRK = Current Track
- ;
- NXTSEC:
- PUSH H
- PUSH D
- LHLD CURSEC ;INCREMENT CURRENT SECTOR
- INX H
- XCHG
- LHLD SPT ;CHECK TO SEE IF BEYOND END OF TRACK
- CALL SUBDE
- XCHG
- JNC NEXTOK
- LHLD CURTRK ;BEYOND END OF TRACK, SO INCR CURRENT TRACK
- INX H
- XCHG
- LHLD MAXTRK ;SEE IF BEYOND END OF DISK
- CALL SUBDE
- JNC TRASK
- LXI D,0 ;WRAP TO START OF DISK
- ;
- TRASK:
- XCHG
- SHLD CURTRK ;SET NEW CURRENT TRACK
- LXI H,1 ;SET SECTOR 1
- ;
- NEXTOK:
- SHLD CURSEC ;SET NEW CURRENT SECTOR
- POP D
- POP H
- RET
- ;
- ;Tell what group, displacement, track, sector, physical sector
- ;
- INQ:
- CALL INQSUB
- JMP PROMPT
- ;
- ;Position inquiry subroutine
- ;Executed via: G S or T (with no operands)
- ;
- INQSUB:
- PUSH H
- LHLD SYSTRK ;CHECK IF IN SYSTEM TRACKS
- XCHG
- LHLD CURTRK
- CALL SUBDE
- JC NOGRP
- CALL ILPRT ;PRINT GROUP NUMBER IF NOT IN SYSTEM TRACKS
- DB 'Group = ',0
- LHLD GROUP
- MOV B,H
- MOV C,L
- CALL HEXB ;PRINT GROUP NUMBER IN BC
- MVI A,':'
- CALL TYPE
- LDA GRPDIS
- CALL HEX ;PRINT GROUP DISPLACEMENT IN A
- MVI A,','
- CALL TYPE
- ;
- NOGRP:
- CALL ILPRT ;PRINT TRACK NUMBER
- DB ' Track = ',0
- LHLD CURTRK
- CALL DEC ;TRACK NUMBER IN DECIMAL
- CALL ILPRT ;PRINT SECTOR NUMBER
- DB ', Sector = ',0
- LHLD CURSEC
- CALL DEC ;SECTOR NUMBER IN DECIMAL
- CALL ILPRT ;PRINT PHYSCIAL SECTOR NUMBER
- DB ', Physical Sector = ',0
- LHLD PHYSEC
- CALL DEC ;PHYSICAL SECTOR NUMBER IN DECIMAL
- CALL CRLF
- POP H
- RET
- ;
- ;COMMAND: C
- ;Change Contents of Current Block
- ;
- CHG:
- MOV A,M ;GET TYPE (HEX, ASCII)
- CALL UPCASE
- PUSH PSW ;SAVE "H" OR "A"
- INX H
- CALL HEXIN ;GET DISP IN HEX
- CALL DISP1 ;VALIDATE DISP TO DE
- INX H
- LXI B,0 ;SHOW NO 'THRU' ADDR
- CPI '-' ;TEST DELIM FR. DISP
- JNZ CHGNTH ;NO THRU
- PUSH D ;SAVE FROM
- CALL HEXIN
- CALL DISP1 ;GET THRU
- INX H ;SKIP END DELIM
- MOV B,D
- MOV C,E ;BC = THRU
- POP D ;GET FROM
- JMP CHGAH
- ;
- CHGNTH:
- CPI ','
- JNZ WHAT
- ;
- CHGAH:
- POP PSW
- CPI 'H' ;HEX?
- JZ CHGHEX
- CPI 'A' ;ASCII?
- JNZ WHAT
- ;
- ;Change ASCII
- ;
- CHGALP:
- MOV A,M ;GET CHAR
- CPI CR
- JZ PROMPT
- CPI ';'
- JZ PROMPT
- ;
- ;The following print of the deleted byte is commented out; if leading
- ; semicolons are removed, deleted bytes will be printed
- ;
- ; LDAX D ;GET BYTE THAT IS REPLACED
- ; CPI ' '
- ; JC CHGAHX
- ; CPI 7EH ;DON'T PRINT ESC CHAR FOR H1500
- ; JNC CHGAHX
- ; JMP CHGA2
- ;
- ;CHGAHX:
- ; CALL BHEX
- ; JMP CHGA3
- ;
- ;CHGA2:
- ; CALL TYPE
- ;
- ;End of print of delete bytes
- ;
- CHGA3:
- SHLD BACK ;IN CASE "THRU"
- CALL GETVAL ;GET ASCII OR <HEX> VALUE
- STAX D ;UPDATE BYTE
- INX H ;PT TO NEXT INPUT CHAR
- ;
- ;See if 'THRU' requested
- ;
- MOV A,C
- ORA A
- JZ CHANTH
- CMP E ;DONE?..
- JZ PROMPT ;..YES
- LHLD BACK
- ;
- CHANTH:
- INR E
- JNZ CHGALP
- MOV A,M
- CPI CR
- JZ PROMPT
- CPI ';'
- JZ PROMPT
- JMP WHAT
- ;
- ;Change hex
- ;
- CHGHCM:
- INX H
- ;
- CHGHEX:
- MOV A,M ;GET HEX DIGIT
- CPI CR
- JZ PROMPT
- CPI ';'
- JZ PROMPT
- CPI ',' ;DELIM?
- JZ CHGHCM
- PUSH D
- SHLD HEXAD ;IN CASE 'THRU'
- CALL HEXIN ;POSITIONS TO DELIM
- MOV A,E ;GET VALUE
- POP D ;..ADDR
- ;
- ;The following comments out the echo of the deleted byte; removing the
- ; leading semicolons restores the echo
- ;
- ; PUSH PSW ;SAVE VALUE
- ; LDAX D ;GET OLD
- ; CALL HEX ;ECHO IN HEX
- ; POP PSW ;GET NEW
- ;
- ;End of echo of bytes
- ;
- STAX D ;SAVE NEW BYTE
- MOV A,C ;SEE IF 'THRU'
- ORA A
- JZ CHHNTH ;..NO.
- CMP E ;..YES, DONE?
- JZ PROMPT
- LHLD HEXAD ;..NO: MORE
- ;
- CHHNTH:
- INR E
- JNZ CHGHEX
- MOV A,M
- CPI CR
- JZ PROMPT
- CPI ';'
- JZ PROMPT
- JMP WHAT
- ;
- ;COMMAND: R
- ;Read Current Block into TBUFF
- ;COMMAND: RG
- ;Read Specified Group into GBUFF
- ;
- DOREAD:
- MOV A,M ;GET CHAR AFTER R
- CALL UPCASE ;CAPITALIZE
- CPI 'G' ;READ GROUP?
- JZ SAVEG ;SAVE GROUP IF SO
- LDA NOTPOS ;POSITIONED?
- ORA A
- JNZ CANTRD
- CALL READ ;READ BLOCK
- JMP PROMPT
- ;
- CANTRD:
- XRA A
- STA QFLAG ;NOT QUIET
- CALL ILPRT
- DB '++ Can''t read - not positioned ++',CR,LF
- DB 'Position by:',CR,LF
- DB ' Track then Sector, or',CR,LF
- DB ' Group',CR,LF,0
- JMP PROMPT
- ;
- ;COMMAND: W
- ;Write Current Block to Disk
- ;COMMAND: WG
- ;Write Specified Group from GBUFF
- ;
- DORITE:
- MOV A,M ;GET NEXT CHAR
- CALL UPCASE ;CAPITALIZE
- CPI 'G' ;GROUP?
- JZ RESTRG ;DO GROUP WRITE
- CALL WRITE ;DO WRITE
- JMP PROMPT
- ;
- ;Print Byte in A as Hex Digits
- ;
- BHEX:
- PUSH PSW
- MVI A,'<'
- CALL TYPE
- POP PSW
- CALL HEX
- MVI A,'>'
- CALL TYPE
- RET
- ;
- ;Print Number in BC as Hex Digits
- ;
- HEXB:
- LDA DSM+1
- ORA A
- JZ HEXX
- MOV A,B
- CALL HEX
- ;
- HEXX:
- MOV A,C
- ;
- ;Print Byte in A as 2 Hex Digits
- ;
- HEX:
- PUSH PSW
- RAR ;GET HIGH NYBBLE
- RAR
- RAR
- RAR
- CALL NIBBL ;PRINT IT
- POP PSW ;GET LOW NYBBLE
- ;
- NIBBL:
- ANI 0FH ;MASK LOW NYBBLE
- CPI 10 ;0-9?
- JC HEXNU
- ADI 7 ;CONVERT TO A-F
- ;
- HEXNU:
- ADI '0' ;CONVERT TO ASCII
- JMP TYPE ;PRINT IT
- ;
- ;Decimal output routine
- ; Print Number in HL as decimal digits (HL<100)
- ;
- DEC:
- PUSH B
- PUSH D
- PUSH H
- LXI B,-10
- LXI D,-1
- ;
- DECOU2:
- DAD B
- INX D
- JC DECOU2
- LXI B,10
- DAD B
- XCHG
- MOV A,H
- ORA L
- CNZ DEC
- MOV A,E
- ADI '0'
- CALL TYPE
- POP H
- POP D
- POP B
- RET
- ;
- ;Print <SP>
- ;
- SPACE: MVI A,' '
- JMP TYPE
- ;
- ;Print '*'
- ;
- ASTER: MVI A,'*'
- JMP TYPE
- ;
- ;Inline print routine
- ; Print Chars ending in 0 pted to by Return Address; return to byte after
- ;
- ILPRT:
- XTHL ;GET PTR AND SAVE HL
- ;
- ILPLP:
- CALL CTLCS ;ABORT?
- JZ PRMPTR
- MOV A,M ;GET CHAR
- CPI 1 ;PAUSE? -- ^A
- JNZ ILPOK
- CALL CONIN ;WAIT FOR ANY CHAR
- CPI 3 ;ABORT?
- JZ PRMPTR
- JMP ILPNX
- ;
- ILPOK:
- CALL TYPE ;PRINT CHAR
- ;
- ILPNX:
- INX H ;PT TO NEXT
- MOV A,M ;GET IT
- ORA A ;DONE?
- JNZ ILPLP
- INX H ;PT TO BYTE AFTER ENDING 0
- XTHL ;RESTORE HL AND RET ADR
- RET
- ;
- ;DISP calls DECIN, and validates a sector
- ;displacement, then converts it to an address
- ;
- DISP:
- CALL DECIN
- DISP1:
- PUSH PSW ;SAVE DELIMITER
- MOV A,D
- ORA A
- JNZ BADISP
- MOV A,E
- ORA A
- JM BADISP
- ADI 80H ;TO POINT TO BUFFER AT BASE+80H
- MOV E,A
- MVI D,BASE/256
- POP PSW ;GET DELIM
- RET
- ;
- BADISP:
- XRA A
- STA QFLAG ;NOT QUIET
- CALL ILPRT
- DB '++ Bad Displacement (Not 0-7FH) ++'
- DB CR,LF,0
- JMP PRMPTR
- ;
- ;Input Number from Command Line -- Assume it to be Hex
- ; Number returned in DE
- ;
- HEXIN:
- LXI D,0
- MOV A,M
- CPI '#' ;DECIMAL?
- JZ HDIN ;MAKE DECIMAL
- ;
- HINLP:
- MOV A,M ;GET CHAR
- CALL UPCASE ;CAPITALIZE
- CPI CR ;EOL?
- RZ
- CPI ';' ;EOL?
- RZ
- CPI ','
- RZ
- CPI '-' ;'THRU'?
- RZ
- CPI '>'
- RZ
- INX H ;PT TO NEXT CHAR
- CPI '0' ;RANGE?
- JC WHAT
- CPI '9'+1 ;RANGE?
- JC HINNUM
- CPI 'A' ;RANGE?
- JC WHAT
- CPI 'F'+1 ;RANGE?
- JNC WHAT
- SUI 7 ;ADJUST FROM A-F TO 10-15
- ;
- HINNUM:
- SUI '0' ;CONVERT FROM ASCII TO BINARY
- XCHG
- DAD H ;MULT PREVIOUS VALUE BY 16
- DAD H
- DAD H
- DAD H
- ADD L ;ADD IN NEW DIGIT
- MOV L,A
- XCHG
- JMP HINLP
- ;
- HDIN:
- INX H ;SKIP '.'
- ;
- ;Input Number in Command Line as Decimal
- ; Number is returned in DE
- ;
- DECIN:
- LXI D,0
- MOV A,M ; GET 1ST CHAR
- CPI '#' ; HEX?
- JNZ DINLP
- INX H ; PT TO DIGIT
- JMP HINLP ; DO HEX PROCESSING
- ;
- DINLP:
- MOV A,M ;GET DIGIT
- CALL UPCASE ;CAPITALIZE
- CPI CR ;EOL?
- RZ
- CPI ';' ;EOL?
- RZ
- CPI ','
- RZ
- CPI '-' ;'THRU'?
- RZ
- INX H ;PT TO NEXT
- CPI '0' ;RANGE?
- JC WHAT
- CPI '9'+1 ;RANGE?
- JNC WHAT
- SUI '0' ;CONVERT TO BINARY
- PUSH H
- MOV H,D
- MOV L,E
- DAD H ;X2
- DAD H ;X4
- DAD D ;X5
- DAD H ;X10
- ADD L ;ADD IN DIGIT
- MOV L,A
- MOV A,H
- ACI 0
- MOV H,A
- XCHG ;RESULT IN DE
- POP H
- JMP DINLP
- ;
- ;Read in a console buffer
- ;
- RDBUF:
- CALL ILPRT ;PRINT PROMPT
- DB CR,LF,'DUTIL ',0
- LDA DRIVE ;GET DRIVE NUMBER
- ADI 'A' ;CONVERT TO ASCII
- CALL TYPE
- LDA VER2FL ;VERSION 2 OR BETTER?
- ORA A ;0=NO
- JZ RDBUF1
- MVI A,'/'
- CALL TYPE
- LDA UNUM ;DISPLAY USER NUMBER
- MOV L,A ;VALUE IN HL
- MVI H,0
- CALL DEC ;PRINT IN DECIMAL
- RDBUF1:
- CALL ILPRT ;PRINT PROMPT
- DB '? ',0
- LXI D,INBUF-2 ;USE CP/M READLN
- MVI C,10
- CALL BDOS
- LDA INBUF-1 ;GET CHAR COUNT
- MOV B,A ;CHAR COUNT IN B
- LXI H,INBUF ;STORE ENDING <CR>
- ADD L ;ADD CHAR COUNT TO HL
- MOV L,A
- MOV A,H
- ACI 0
- MOV H,A
- MVI A,CR ;STORE ENDING <CR>
- MOV M,A ;SAVE IT
- CALL TYPE ;ECHO IT
- MVI A,LF ;ECHO..
- CALL TYPE ;..LF
- LXI H,INBUF ;SET PTR TO FIRST CHAR IN LINE
- RET
- ;
- ;Set paging flag for page routine
- ;
- PAGSET:
- LDA PAGSIZ ;GET SIZE OF PAGE
- STA PAGFLG ;SET FLAG
- RET
- ;
- ;Page output
- ;
- PAGER:
- LDA PAGFLG ;GET FLAG
- CPI 2 ;2 LINES LEFT?
- JZ WAIT ;SAME AS USER DELAY
- DCR A ;COUNT DOWN
- STA PAGFLG
- JMP CRLF
- ;
- ;Delay Routine
- ;
- WAIT: PUSH H
- CALL ILPRT
- DB CR,LF,'Type Any Character to Continue or ^C to Abort - ',0
- POP H
- CALL CONIN ;GET RESPONSE
- CPI 'C'-40H ;^C?
- JZ WAIT1
- CALL CRLF ;NEW LINE
- CALL PAGSET ;RESET PAGE COUNT
- RET
- WAIT1:
- LDA IHFLG ;INITIAL HELP?
- ORA A ;0=NO
- JZ PRMPTR ;ABORT TO COMMAND PROMPT
- JMP EXIT1 ;ABORT TO CP/M
- ;
- ;CRLF Routine
- ;
- CRLF: MVI A,CR
- CALL TYPE
- MVI A,LF
- JMP TYPE
- ;
- ;Convert to Upper Case
- ;
- UPCASE:
- ANI 7FH ;MASK OUT MSB
- CPI 60H ;LESS THAN SMALL A?
- RC ;RETURN IF SO
- ANI 5FH ;MAKE UPPER CASE
- RET
- ;
- ;CON: Status Routine
- ;
- CONST:
- PUSH B
- PUSH D
- PUSH H
- VCONST:
- CALL $-$ ;ADDR FILLED IN BY 'INIT'
- POP H
- POP D
- POP B
- RET
- ;
- ;CON: Input Routine
- ;
- CONIN:
- PUSH B
- PUSH D
- PUSH H
- VCONIN:
- CALL $-$ ;ADDR FILLED IN BY 'INIT'
- POP H
- POP D
- POP B
- RET
- ;
- ;Console out with TAB expansion
- ; Char in A
- ;
- TYPE:
- PUSH B ;SAVE REGS
- PUSH D
- PUSH H
- MOV C,A ;FOR OUTPUT ROUTINE
- CPI TAB
- JNZ TYPE2
- ;Tabulate
- TYPTAB:
- MVI A,' ' ;PRINT SPACE
- CALL TYPE
- LDA TABCOL ;GET COL COUNT
- ANI 7 ;DONE?
- JNZ TYPTAB
- JMP TYPRET
- ;
- ;Filter out control characters to
- ;prevent garbage during view of file
- ;
- TYPE2:
- CPI ' '
- JNC TYPEQ
- CPI CR
- JZ TYPEQ
- CPI LF
- JNZ TYPNCR
- ;
- TYPEQ:
- LDA QFLAG ;CHECK QUIET FLAG FOR NO MESSAGES
- ORA A
-
- ;
- ;CON: Output Routine
- ;
- VCONOT: CZ $-$ ;ADDR FILLED IN BY 'INIT'
- ;
- ;Update column used in tab expansion
- ;
- MOV A,C ;GET CHAR
- CPI CR
- JNZ TYPNCR
- MVI A,0 ;RESET TAB COLUMN IF <CR>
- STA TABCOL
- JMP TYPLST
- ;
- TYPNCR:
- CPI ' ' ;CTL CHAR?
- JC TYPLST ;..NO CHANGE IN COL
- LDA TABCOL ;INCR TAB COUNT
- INR A
- STA TABCOL
- ;
- TYPLST:
- LDA PFLAG ;CHECK FOR PRINTER OUTPUT
- ANI 1
- CNZ LIST ;FROM C REG
- ;
- TYPRET:
- POP H ;RESTORE REGS
- POP D
- POP B
- RET
- ;
- ;LST: Output Routine
- ; Char in C
- ;
- LIST:
- PUSH B ;SAVED REGS
- PUSH D
- PUSH H
- VLIST:
- CALL $-$ ;ADDR FILLED IN BY 'INIT'
- POP H
- POP D
- POP B
- RET
- ;
- ;Home Disk Routine
- ;
- HOME:
- PUSH H
- VHOME:
- CALL $-$ ;ADDR FILLED IN BY 'INIT'
- POP H
- RET
- ;
- ;Set track # in DE
- ;
- SETTRK:
- PUSH H
- LHLD MAXTRK ;CHECK FOR WITHIN BOUNDS
- CALL SUBDE ;IF TRACK # IN DE > MAX, THEN ERROR
- POP H
- JC OUTLIM
- XCHG ;RESET CURRENT TRACK
- SHLD CURTRK
- XCHG
- MOV B,D ;BC=TRACK NUMBER
- MOV C,E
- PUSH H
- ;
- VSETRK:
- CALL $-$ ;ADDR FILLED IN BY 'INIT'
- POP H
- RET
- ;
- ;Set Sector Number in DE
- ;
- SETSEC:
- PUSH H
- PUSH D
- LHLD SYSTRK ;GET NUMBER OF SYSTEM TRACKS
- XCHG
- SHLD CURSEC ;SET CURRENT SECTOR
- LHLD CURTRK ;GET CURRENT TRACK
- CALL SUBDE ;SEE IF WE ARE IN THE SYSTEM TRACKS
- POP B ;BC=SECTOR NUMBER
- MOV H,B ;HL=SECTOR NUMBER
- MOV L,C
- JNC NOTSYS ;IF NO CARRY FOR SUBDE, WE ARE NOT IN SYSTEM TRACKS
- LDA FIRST0 ;SEE IF FIRST SEC 0
- ORA A
- JNZ GSTSEC ;NO, JUMP AWAY
- DCX H ;YES, SO DECREMENT
- JMP GSTSEC ;REQUESTED, THEN GO
- ;
- ;Not in System Tracks, so Skew Factor is effective
- ;
- NOTSYS:
- LHLD SECTBL ;GET PTR TO SECTOR TABLE
- XCHG ;... IN DE
- DCX B ;DECREMENT SECTOR NUMBER BY 1
- ;
- VSCTRN:
- CALL $-$ ;ADDR FILLED IN BY 'INIT'
- LDA SPT+1 ;IF SPT<256 (HI-ORD = 0)
- ORA A ; THEN FORCE 8-BIT TRANSLATION
- JNZ VSCTR1 ; ELSE KEEP ALL 16 BITS
- MOV H,A
- VSCTR1:
- LDA VER2FL ;SEE IF VERSION 2.x
- ORA A ;SET FLAGS
- JNZ GSTSEC ;JUMP IF CP/M 2.x
- MVI H,0 ;CP/M 1.4 GOOD TO ONLY 8 BITS
- MOV L,C ;MOST BIOS'S RETURN THE
- ; PHYSICAL SEC # IN REG C
- GSTSEC:
- SHLD PHYSEC ;THIS MAY BE 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 ;RESTORE PTR TO NEXT CHAR
- RET
- ;
- ;Out of Disk Track Limit
- ;
- OUTLIM:
- XRA A ;NOT QUIET
- STA QFLAG
- CALL ILPRT
- DB '++ Not Within Tracks 0-',0
- PUSH H
- LHLD MAXTRK ;PRINT MAX TRACK NUMBER
- CALL DEC
- POP H
- CALL ILPRT
- DB ' ++',CR,LF,0
- CALL NORITE ;NOT POSITIONED
- JMP PRMPTR
- ;
- ;Set DMA Address
- ;
- SETDMA:
- JMP $-$ ;ADDR FILLED IN BY 'INIT'
- ;
- ;Read Next Block into DMA Address
- ;
- READ:
- MVI A,1 ;SET FLAG
- STA WRFLG
- PUSH H ;SAVE PTR TO NEXT CHAR
- ;
- VREAD:
- CALL $-$ ;ADDR FILLED IN BY 'INIT'
- ORA A ;ERROR?
- JZ READOK
- XRA A ;NOT QUIET
- STA QFLAG
- CALL ILPRT
- DB '++ READ Failed, Sector may be Invalid ++'
- DB CR,LF,0
- ;
- READOK:
- POP H ;GET PTR TO NEXT CHAR
- RET
- ;
- ;Write Block in DMA Address to Disk
- ;
- WRITE:
- LDA WRFLG ;READ ALREADY PERFORMED?
- ORA A ;ERROR IF NOT
- JNZ PWRITE
- ;
- BADW:
- XRA A ;NOT QUIET
- STA QFLAG
- CALL ILPRT
- DB '++ Cannot Write Unless Read Issued ++'
- DB CR,LF,0
- JMP EXPL
- ;
- ;Do Write
- ;
- PWRITE:
- PUSH H ;SAVE PTR TO NEXT CHAR
- MVI C,1 ;FORCE WRITE TYPE 1 IN CASE 2.x DEBLOCK USED
- ;
- VWRITE:
- CALL $-$ ;ADDR FILLED IN BY 'INIT'
- ORA A ;ERROR?
- JZ WRITOK
- XRA A ;NOT QUIET
- STA QFLAG
- CALL ILPRT
- DB '++ WRITE Failed ++',CR,LF,0
- ;
- WRITOK:
- POP H
- RET
- ;
- ;Help; HELP is entry point for HELP (?) command, HELP1 is entry point for
- ; Initial Help Command, and IHELP is entry point for HELP (/) from command
- ; line
- ;
- IHELP:
- XRA A
- STA QFLAG ;NOT QUIET
- CALL ILPRT
- DB 'Introductory HELP on DUTIL (Disk Utility)',CR,LF
- DB ' The DUTIL program is designed to provide the user with'
- DB CR,LF
- DB 'the ability to manipulate information on the disk as easily'
- DB CR,LF
- DB 'as the DDT and SID utilities allow the user to manipulate'
- DB CR,LF
- DB 'information in memory.',CR,LF
- DB ' The following is a summary of the commands available to'
- DB CR,LF
- DB 'the DUTIL user. This same list is invoked internally by the'
- DB CR,LF
- DB '? Command of DUTIL. For additional information on disk'
- DB CR,LF
- DB 'structures and how to use DUTIL in general, refer to the'
- DB CR,LF
- DB 'files DUTIL.DOC and DUTIL.HLP.',CR,LF,0
- MVI A,0FFH ;A=0FFH
- STA IHFLG ;SET INITIAL HELP
- CALL WAIT
- JMP HELP1 ;PROCESS NORMALLY
- HELP:
- XRA A ;A=0
- STA IHFLG ;SET NO INITIAL HELP
- HELP1:
- XRA A
- STA QFLAG ;NOT QUIET
- CALL ILPRT
- DB '=======================================================',CR,LF
- DB ' -- Command Summary -- ',CR,LF
- DB '-------------------------------------------------------',CR,LF
- DB CR,LF
- DB 'Operands in brackets [...] are optional'
- DB CR,LF,CR,LF
- DB '@ Repeat Previous Non-@ Command Line'
- DB CR,LF
- DB '+[nn] Step In [nn (decimal)] Sectors; -[nn] Step Out '
- DB 'Sectors'
- DB CR,LF
- DB '# Print Disk Parameters for Current Drive'
- DB CR,LF
- DB '=xxx Search for ASCII xxx from Current Sector'
- DB CR,LF
- DB ' Caution: upper/lower case matters.'
- DB CR,LF
- DB ' Use <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; > Restore Saved Sector'
- DB CR,LF
- DB '/[nn] Repeat [nn (decimal) times]; ! Pause for User'
- DB CR,LF
- DB ':ntext Define ''text'' to be Macro n; n Perform Macro'
- DB ' n, 0<=n<=9'
- DB CR,LF
- DB ':Pn Print Macro n, 0<=n<=9'
- DB CR,LF
- DB ':Px Print All Macros if x=A or Print Prev Line if x=@'
- DB CR,LF,CR,LF,0
- CALL WAIT
- CALL ILPRT
- DB '-------------------------------------------------------',CR,LF
- DB 'A[ff,tt] ASCII Dump'
- DB CR,LF
- DB 'C Change:'
- DB CR,LF
- DB ' CHaddr,byte,byte... (hex)'
- DB CR,LF
- DB ' or CAaddr,data... (Ascii)'
- DB CR,LF
- DB ' <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 and ASCII)'
- DB CR,LF
- DB 'Fn.t Find File'
- DB CR,LF
- DB 'Gnn CP/M Allocation Group nn (hex)'
- DB CR,LF
- DB 'H[ff,tt] Hex Dump'
- DB CR,LF
- DB 'L Log in drive; Lx Log in drive x'
- DB CR,LF
- DB 'M[nn] Map [from group nn (hex)]'
- DB CR,LF,CR,LF,0
- CALL WAIT
- CALL ILPRT
- DB '-------------------------------------------------------',CR,LF
- DB CR,LF
- DB 'N Load New Disk; P Toggle Printer Switch'
- DB CR,LF
- DB 'Q Quiet Mode (no messages)'
- DB CR,LF
- DB 'R Read Current Sector; RG Read Specified Group'
- DB CR,LF
- DB 'Snn Sector nn (decimal)'
- DB CR,LF
- DB 'Tnn Track nn (decimal)'
- DB CR,LF
- DB 'Unn Set User nn (decimal) for Find command (CP/M-2 only)'
- DB CR,LF
- DB 'V[nn] View [nn (decimal)] ASCII Sectors'
- DB CR,LF
- DB 'W Write Current Sector; WG Write Specified Group'
- DB CR,LF
- DB 'X Exit Program'
- DB CR,LF
- DB 'Z[nn] Sleep [nn (decimal) seconds]'
- DB CR,LF,CR,LF,0
- CALL WAIT
- CALL ILPRT
- DB '-------------------------------------------------------',CR,LF
- DB CR,LF
- DB 'Command Line is of the form: DUTIL d/u?',CR,LF
- DB ' "d" is Logged-In Disk, "u" is Current User',CR,LF
- DB CR,LF
- DB 'Cancel a function with C or Ctrl-C.'
- DB CR,LF
- DB 'Suspend output with S or Ctrl-S.'
- DB CR,LF
- DB 'Separate commands with ";".'
- DB CR,LF
- DB ' Example: g0'
- DB CR,LF
- DB ' +;d;z2;/'
- DB CR,LF
- DB ' would step in, dump, sleep 2 sec, '
- DB CR,LF
- DB ' and repeat until control-c typed.'
- DB CR,LF
- DB '"nn" usage varies with command as follows:',CR,LF
- DB ' +, -, /, T, S, U, V, Z nn in Decimal',CR,LF
- DB ' (use #nn for Hex)',CR,LF
- DB ' G, M nn in Hexadecimal',CR,LF
- DB ' (use #nn for Decimal)'
- DB CR,LF
- DB '"ff" and "tt" are in Hexadecimal (use #ff or #tt for Decimal)'
- DB CR,LF,CR,LF
- DB '=======================================================',CR,LF
- DB 0
- CALL WAIT
- CALL ILPRT
- DB '=======================================================',CR,LF
- DB 'DUTIL Status Information',CR,LF
- DB '-------------------------------------------------------',CR,LF
- DB 'Processor Speed: ',0
- LDA CLOCK ;GET CLOCK SPEED
- ADI '0' ;CONVERT TO ASCII
- CALL TYPE ;PRINT
- CALL ILPRT
- DB ' MHz',CR,LF
- DB 'Number of Lines on CON: ',0
- LDA PAGSIZ ;GET PAGE SIZE
- MOV L,A ;NUMBER IN HL
- MVI H,0
- CALL DEC ;PRINT NUMBER IN DECIMAL
- CALL ILPRT
- DB CR,LF,'Group Save Buffer Address: ',0
- LXI B,GBUFF ;BC=ADDRESS
- CALL HEXB ;PRINT AS HEX
- CALL ILPRT
- DB ' Hex',CR,LF
- DB '=======================================================',CR,LF
- DB 0
- LDA IHFLG ;INITIAL HELP?
- ORA A ;0=NO
- JNZ EXIT1 ;RETURN TO CP/M IF SO
- JMP PRMPTR ;NEW LINE INPUT IF NOT
- ;
- ;COMMAND: X
- ;Exit to CP/M
- ;
- EXIT:
- XRA A
- STA QFLAG ;NOT QUIET
- CALL ILPRT ;PRINT
- DB CR,LF,'Exit to CP/M -- Do you wish to Warm Boot (Y/N/<CR>=N)?'
- DB ' ',0
- CALL CONIN ;GET RESPONSE
- CALL UPCASE ;CAPITALIZE
- CPI 'Y' ;YES?
- JZ BASE ;WARM BOOT IF SO
- ;
- ;Quick Exit to CP/M
- ;
- EXIT1:
- LHLD DUTSTK ;GET CP/M STACK PTR
- SPHL ;SET SP
- RET
-
- ;
- ;********************************
- ;* *
- ;* Utility Subroutines *
- ;* *
- ;********************************
- ;
- GRPCMP:
- MOV A,C
- INR D
- DCR D
- JZ CMP8
- CMP M
- INX 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 ;NUMBER OF BITS
- ;
- COLOP:
- RAL
- JNC COSKIP
- INR C
- ;
- COSKIP:
- DCR B
- JNZ COLOP
- RET
- ;
- ;HL-DE ==> HL
- ; Carry Flag is Significant
- ;
- SUBDE:
- MOV A,L
- SUB E
- MOV L,A
- MOV A,H
- SBB D
- MOV H,A
- RET
- ;
- ;Quick Kludge multiply
- ;HL*DE ==> HL
- ;
- MULT:
- PUSH B
- PUSH D
- XCHG
- MOV B,D
- MOV C,E
- MOV A,B
- ORA C
- JNZ MULCON
- LXI H,0 ;FILTER SPECIAL CASE
- JMP MLDONE ; OF MULTIPLY BY 0
- ;
- MULCON:
- DCX B
- MOV D,H
- MOV E,L
- ;
- MULTLP:
- MOV A,B
- ORA C
- JZ MLDONE
- DAD D
- DCX B
- JMP MULTLP
- ;
- MLDONE:
- POP D
- POP B
- RET
- ;
- ;Routine to fill in disk params
- ;with every drive change
- ;
- LOGIT:
- LDA VER2FL
- ORA A ;IF NOT CP/M 2.x THEN
- JZ LOG14 ; DO IT AS 1.4
- ;
- ;CP/M 2.x
- ;
- LXI D,DPB ; THEN MOVE TO LOCAL
- MVI B,DPBLEN ; WORKSPACE
- CALL MOVE
- JMP LOGCAL
- ;
- ;CP/M 1.4
- ;
- LOG14:
- LHLD BDOS+1 ;FIRST FIND 1.4 BDOS
- MVI L,0
- LXI D,DPBOFF ;THEN OFFSET TO 1.4'S DPB
- DAD D
- MVI D,0 ;SO 8 BIT PARMS WILL BE 16
- MOV E,M ;NOW MOVE PARMS
- INX H
- XCHG
- SHLD SPT
- XCHG
- MOV E,M
- INX H
- XCHG
- SHLD DRM
- XCHG
- MOV A,M
- INX H
- STA BSH
- MOV A,M
- INX H
- STA BLM
- MOV E,M
- INX H
- XCHG
- SHLD DSM
- XCHG
- MOV E,M
- INX H
- XCHG
- SHLD AL0
- XCHG
- MOV E,M
- XCHG
- SHLD SYSTRK
- ;
- LOGCAL:
- LXI H,GRPDIS
- MOV A,M
- PUSH PSW
- LDA BLM
- MOV M,A
- PUSH H
- LHLD DSM
- XCHG
- CALL GTKSEC
- SHLD MAXSEC
- XCHG
- SHLD MAXTRK
- POP H
- POP PSW
- MOV M,A
- RET
-
- ;***********************************
- ;
- ; DUTIL Command Table
- ;
- ;***********************************
- CMDTBL:
- DB ':'
- DW MAC
- ;
- DB '@'
- DW PCMD
- ;
- DB '+'
- DW PLUS
- ;
- DB '-'
- DW MINUS
- ;
- DB '='
- DW SEARCH
- ;
- DB '<'
- DW SAVE
- ;
- DB '>'
- DW RESTOR
- ;
- DB '#'
- DW STATS
- ;
- DB '?'
- DW HELP
- ;
- DB '/'
- DW REPEAT
- ;
- DB '!'
- DW UWAIT
- ;
- DB 'A'
- DW DUMP
- ;
- DB 'C'
- DW CHG
- ;
- DB 'D'
- DW DUMP
- ;
- DB 'F'
- DW POSFIL
- ;
- DB 'G'
- DW POS
- ;
- DB 'H'
- DW DUMP
- ;
- DB 'L'
- DW LOGIN
- ;
- DB 'M'
- DW MAP
- ;
- DB 'N'
- DW NEWDSK
- ;
- DB 'P'
- DW PRNTFF
- ;
- DB 'Q'
- DW QUIET
- ;
- DB 'R'
- DW DOREAD
- ;
- DB 'S'
- DW POS
- ;
- DB 'T'
- DW POS
- ;
- DB 'U' ;******CP/M 2.x ONLY******
- DW USER
- ;
- DB 'V'
- DW VIEW
- ;
- DB 'W'
- DW DORITE
- ;
- DB 'X'
- DW EXIT
- ;
- DB 'Z'
- DW SLEEP
- ;
- DB 0 ; End of Table
- ;*************************************
-
- ;
- ;Temporary storage area
- ;
- DS 100 ;50-ELT STACK
- DUTSTK:
- DS 2 ;OLD CP/M STACK POINTER; TOP OF DUTIL STACK
- BUFAD:
- DS 2 ;FORCES INITIAL READ
- HEXAD:
- DS 2 ;TO RE-FETCH A VALUE
- TOGO:
- DS 2 ;REPEAT COUNT (FFFF=CONT)
- TWOUP:
- DS 1
- UNUM:
- DS 1 ;NUMBER OF CURRENT USER
- ONLY1:
- DS 1 ;FLAG TO PRINT ONLY 1 MAP ENTRY (0=NO)
- MFPTR:
- DS 2 ;MULTI FILE PTR FOR GETGRP
- PAGFLG:
- DS 1 ;LINE COUNTER FOR PAGING
- PFLAG:
- DS 1 ;1=PRINT
- GROUP:
- DS 2 ;GROUP NUMBER
- GRPDIS:
- DS 1 ;DISPLACEMENT INTO GROUP
- SAVEFL:
- DS 1 ;SAVE FLAG
- CURTRK:
- DS 2 ;CURRENT TRACK NUMBER
- CURSEC:
- DS 2 ;CURRENT SECTOR NUMBER
- PHYSEC:
- DS 2 ;CURRENT PHYSICAL SECTOR NUMBER
- TABCOL:
- DS 1 ;TAB COLUMN
- GLFLAG:
- DS 1 ;GROUP LOADED FLAG; 0=NO
- CPYFCT:
- DS 1 ;GROUP COPY FUNCTION; 0=READ, 0FFH=WRITE
- FILECT:
- DS 2 ;FILE COUNT
- DIRPOS:
- DS 1 ;POSITION IN DIRECTORY
- FINDFL:
- DS 1 ;1=MUST POSITION AFTER FIND
- FTSW:
- DS 1 ;SEARCH W/O INCREMENT
- NOTPOS:
- DS 1 ;INITIALLY NOT POSITIONED
- WRFLG:
- DS 1 ;MAY NOT WRITE UNTIL '+', '-',
- ; OR 'G' COMMAND
- TGRP:
- DS 2 ;TEMPORARY GROUP FLAG
- QFLAG:
- DS 1 ;QUIET? (0=NO)
- FIRST0:
- DS 1 ;SETS TO 0 IF FIRST SEC # IS 0
- DRIVE:
- DS 1 ;DRIVE NUMBER
- MAXTRK:
- DS 2 ;MAX TRACK NUMBER
- MAXSEC:
- DS 2 ;MAX SECTOR NUMBER
- VER2FL:
- DS 1 ;CP/M VERSION 2.X FLAG
- SECTBL:
- DS 2 ;POINTER TO SECTOR SKEW TABLE
- ;
- IHFLG:
- DS 1 ;0=NOT AT INITIAL HELP, 0FFH=AT INITIAL HELP
- DUPFLG:
- DS 1 ;SPACE OR STAR TO INDICATE MULTIPLE USERS
- BACK:
- DS 2 ;TO 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+2+2
- ;
- ;Set INBUF to a Page Boundary
- ;
- ORG $/100H*100H+100H-2
- DB 126 ; SIZE OF BUFFER FOR CP/M
- DS 1
- INBUF:
- DS 400H ;EXTRA SPACE FOR MACRO EXPANSION
- PINBUF:
- DS 400H ;PREVIOUS CONTENTS OF INPUT BUFFER
- CTEMP:
- DS 400H ;BUILD NEW COMMAND LINE BUFFER
- CTEMPX EQU $ ;END OF CTEMP
- ;
- ;Directory read in here; also loaded group area and Macros
- ;
- MTABL: DS 100H*10 ;10 PAGES FOR 10 MACROS
- GBUFF EQU $
- DIRECT EQU $
- ;
- END
-