home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
MBUG
/
MBUG088.ARC
/
DUTIL.ASM
< prev
next >
Wrap
Assembly Source File
|
1979-12-31
|
65KB
|
3,505 lines
;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