mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1384 lines
44 KiB
1384 lines
44 KiB
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
|
|
|
|
|
|
\textbf{Documentation on ZCPR - A Z80 Replacement for the CP/M CCP}
|
|
|
|
|
|
|
|
|
|
ZCPR is a Group Project By the CCP-GROUP:
|
|
RLC - Richard Conn FJW - Frank Wancho
|
|
KBP - Keith Peterson RGF - Ron Fowler
|
|
|
|
|
|
ZCPR Documentation By RLC
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Table of Contents
|
|
----- -- --------
|
|
|
|
Introduction 2
|
|
|
|
Part A: Installation Instructions 4
|
|
ZCPR Integration Example 5
|
|
Setting the ZCPR Inline Options 8
|
|
REL, BASE, CPRLOC, RAS, SUBA, CLEVEL3 8
|
|
Customization Symbols 8
|
|
NLINES, WIDE, PGDFLT 8
|
|
PGDFLG, MAXUSR, SYSFLG, SOFLG, SUPRES,
|
|
DEFUSR, SPRMPT, CPRMPT, NUMBASE, 9
|
|
SECTFLG, FENCE 10
|
|
Patching SUBMIT.COM 10
|
|
|
|
Part B: Usage Instructions and Explanation of
|
|
Commands 11
|
|
The ZCPR Command Hierarchy Search 11
|
|
The ZCPR-Resident Commands 14
|
|
DIR, ERA 14
|
|
LIST, TYPE, SAVE 15
|
|
REN, USER, DFU 16
|
|
JUMP, GO, GET 17
|
|
ZCPR Error Messages 18
|
|
|
|
Part C: ZCPR Command Levels and How to Use Them 19
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 1
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
\textbf{Documentation on ZCPR - A Z80 Replacement for the CP/M CCP}
|
|
|
|
|
|
|
|
|
|
ZCPR is a replacement for the CP/M Console Command Processor
|
|
(CCP) which is designed to run as part of CP/M on Z80-based
|
|
microcomputers. In most cases it is upward-compatible with the
|
|
original CP/M Version 2.2 CCP.
|
|
|
|
ZCPR, however, provides many extensions to the CP/M CCP.
|
|
Included in these extensions are the following features:
|
|
|
|
. The TYPE function can be made to page or not page its
|
|
output at the user's discretion
|
|
|
|
. A LIST function is available which sends its output
|
|
to the CP/M LST: Device and does NOT page
|
|
|
|
. The DIR command has been extended to allow the dis-
|
|
play of the system files or all files
|
|
|
|
. The ERA command now prints out the names of the files
|
|
it is erasing
|
|
|
|
. The current user number may be included as part of
|
|
the command prompt; if the user is under a number other than 0,
|
|
the prompt is of the form 'du>' (like 'A2>' or 'B10>'), and, if
|
|
the user is under 0, the prompt may be 'd>' or 'd0>' as per his
|
|
choice
|
|
|
|
. The SUBMIT facility has been changed in two basic
|
|
ways:
|
|
- the prompt changes to 'du$' or 'd$' when the
|
|
SUBMIT command is printed
|
|
- the $$$.SUB is executed from drive A: (note that
|
|
the original SUBMIT problem now exists, but the new SUB.COM
|
|
facility corrects it); the CCP-GROUP definition of an Indirect
|
|
Command File now applies, and this definition is that any
|
|
sequence of commands which may be issued from the console is also
|
|
a valid sequence of commands for execution from an Indirect
|
|
Command File; hence, the sequence:
|
|
|
|
DIR
|
|
B:
|
|
DIR
|
|
A:
|
|
|
|
may be issued from either the console or an Indirect Command
|
|
File, and the results of the execution of this sequence are the
|
|
same. Basically, this says that Indirect Command Files are
|
|
upward-compatible to the console input (but not necessarily that
|
|
the contents of an Indirect Command File may be issued at the
|
|
console without modification).
|
|
|
|
|
|
Page 2
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
. A command-search hierarchy is now implemented which
|
|
is executed roughly as follows:
|
|
- the user's command is checked against the CPR-
|
|
resident commands and executed immediately if a match is found
|
|
- failing that, the current user number on the
|
|
current disk is scanned for the COM file; the COM file is loaded
|
|
and executed if found
|
|
- failing that, a default user number (initially 0
|
|
but can be reset with the DFU CPR-resident command) on the cur-
|
|
rent disk is scanned for the COM file; the COM file is loaded and
|
|
executed if found
|
|
- finally, failing that, the default user number
|
|
on disk A: is scanned for the COM file; the COM file is loaded
|
|
and executed if found or an error message (COMMAND?, when COMMAND
|
|
was the user's command name) is printed
|
|
|
|
. The numeric argument for the SAVE command can be
|
|
specified in hexadecimal so that the user may employ the values
|
|
presented by tools such as DDT exactly as they are given
|
|
|
|
. A GET command which loads a file at a specified
|
|
memory address and a JUMP command which "calls" the subroutine at
|
|
a specified memory address have been added; a GO command which
|
|
"calls" the subroutine at 100H (subset of the JUMP capability)
|
|
has also been added
|
|
|
|
|
|
This document provides the user of ZCPR with the following
|
|
information:
|
|
|
|
Part A: Installation Instructions
|
|
Part B: Usage Instructions and Explanation of Commands
|
|
Part C: ZCPR Command Levels and How to Use Them
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 3
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
Part A
|
|
Installation Instructions
|
|
|
|
In order to install ZCPR on a target microcomputer (must be
|
|
currently running CP/M 2.2), the user must know two basic things:
|
|
|
|
1) Where his CCP is currently running in memory
|
|
2) Where his CCP is located in the SYSGEN image, or,
|
|
for systems which don't support SYSGEN (such as P&T CP/M 2.2 for
|
|
the TRS-80 Model II), where his CCP is located on disk and how to
|
|
place the new ZCPR on top of it
|
|
|
|
The first question is answered relatively easily. A pro-
|
|
gram, known as either BDOSLOC or BDLOC (for BDOS Locator), is
|
|
provided with ZCPR. You should assemble this program for your
|
|
particular computer (change the base ORG if you are running non-
|
|
ORG-0 CP/M) and execute it. Upon execution, it will provide you
|
|
with the base address of (1) the BDOS and (2) the CCP for your
|
|
particular system. BDOSLOC has worked correctly for all systems
|
|
tested so far, but there is always a chance that it may NOT work
|
|
for some non-tested system. For the time being, assume that it
|
|
works correctly and record the starting base page address of your
|
|
CCP.
|
|
|
|
The second question is not answered nearly so easily. If
|
|
you have the ability to SYSGEN your system, it is much easier
|
|
(commonly) than if you do not. You must, after assembling the
|
|
ZCPR properly, integrate it into the sysgen (or disk) image of
|
|
CP/M. This can be done by obtaining a SYSGEN image of your
|
|
system, scanning it via a debugger such as DDT to find the offset
|
|
for the CCP, reading the new CPR in on top of the old one, and
|
|
finally running SYSGEN again to place the resultant system on
|
|
disk. If you DO NOT have SYSGEN capability, a Disk Utility
|
|
program is required to locate the CCP on disk and then write the
|
|
new ZCPR on top of the old one. The net result of this
|
|
integration is the placement of the new ZCPR onto disk in the
|
|
proper place so that it will be loaded with the rest of CP/M on
|
|
cold boot and executed properly.
|
|
|
|
To find the original CCP, you typically have to locate it by
|
|
its appearance. It is probably stored contiguously on disk, so,
|
|
once it is found, a sequential overwrite is all that is required.
|
|
Probability is extremely high that it is stored contiguously in
|
|
the SYSGEN image. The CCP starts with two (2) and ONLY TWO jump
|
|
instructions followed by a buffer area (possibly containing an
|
|
initial command and/or the Digital Research copyright notice).
|
|
The Digital Research manuals show the CCP to reside at address
|
|
980H in the SYSGEN image, but this may vary with system. To
|
|
find this image, use DDT or some other such debugger, load the
|
|
SYSGEN image you can get via SYSGEN, and examine memory starting
|
|
at around 900H for the two (and ONLY two) jumps described above.
|
|
If you find an area with more than two jumps (a group of them),
|
|
you are probably looking at the BIOS and should go lower for the
|
|
CCP. The CCP will probably start on an even page or half-page
|
|
address (like 900H, 980H, 1100H, etc).
|
|
|
|
Page 4
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
Now that the location of the CCP has been found, record this
|
|
address for later. You are now ready for the integration of ZCPR
|
|
into your system. To do this, perform the following steps using
|
|
the information of the page address of the CCP (obtained from
|
|
BDOSLOC and called CPRLOC within ZCPR) and the SYSGEN image
|
|
address of the CCP (called IMAGE for reference in this document).
|
|
|
|
1. Edit ZCPR and set the CPRLOC equate to the value
|
|
obtained from above. Also set any flags and values as you desire
|
|
(see the section on ZCPR Customization below). When satisfied,
|
|
end the edit session.
|
|
|
|
2. Assemble ZCPR with MAC (or equivalent). This
|
|
assembler is required because of the MACROs used. Only the
|
|
resultant HEX file is required.
|
|
|
|
3. Assuming that you can use SYSGEN, obtain a SYSGEN
|
|
image of your current CP/M system and save it on disk.
|
|
|
|
4. Load the SYSGEN image into memory with DDT (or
|
|
equivalent). Once loaded, verify that the original CCP is at the
|
|
IMAGE address found above and compute the integration offset
|
|
using the DDT H command:
|
|
H<IMAGE adr>,<CPRLOC adr>
|
|
The second number displayed gives you the OFFSET value required
|
|
for step 5.
|
|
|
|
5. Integrate ZCPR into your SYSGEN image via DDT's I
|
|
and ROFFSET commands. Use IZCPR.HEX (or the name of your version
|
|
of ZCPR) to load the FCB and ROFFSET (where OFFSET was computed
|
|
in step 4) to load the ZCPR.HEX file into memory at the proper
|
|
location. Check to see that ZCPR is indeed properly loaded by
|
|
examining the SYSGEN IMAGE area.
|
|
|
|
6. Place the new system on disk by running SYSGEN and
|
|
NOT loading the system from disk (use the memory image).
|
|
|
|
For further clarification of the above process, the
|
|
following is a sample terminal session which outlines the steps
|
|
taken.
|
|
|
|
ZCPR Integration Example
|
|
|
|
|
|
B>; Sample terminal session for integrating ZCPR
|
|
B>sysgen
|
|
SYSGEN VER 2.2
|
|
SOURCE DRIVE NAME (OR RETURN TO SKIP)b
|
|
SOURCE ON B, THEN TYPE RETURN <-- I hit the RETURN key here
|
|
FUNCTION COMPLETE /
|
|
DESTINATION DRIVE NAME (OR RETURN TO REBOOT) <-- and here
|
|
B>save 44 cpm56.com <-- We now have a SYSGEN image of CP/M
|
|
to work with
|
|
|
|
|
|
|
|
Page 5
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
B>xdir
|
|
XDIR Version 2.6 User Number: 0, Double Density
|
|
File Attributes: Non-System
|
|
|
|
Filename.Typ Size K Filename.Typ Size K Filename.Typ Size K
|
|
-------- --- ------ -------- --- ------ -------- --- ------
|
|
!TEXTWRK.-12 0 CPR .DOC 8 EE687 .TXT 4
|
|
CPR .AQM 34 TFS .HLP 6 EE687PRE.TXT 4
|
|
CPR .ASM 50 CONTENTS.T01 6 SW1 .TXT 10
|
|
CPR .BAK 4 CONTENTS.T02 4 SW2 .TXT 2
|
|
CPM56 .COM 12 CONTENTS.T03 4
|
|
B: 30 Entries & 22 Files -- 338K Bytes Remaining
|
|
File Data: 14 Files -- 154K Bytes Displayed
|
|
B>bdosloc <-- Now to locate the CCP's address
|
|
The Base Page Address of this system's BDOS is C5
|
|
The Base Page Address of this system's CCP is BD <-- This is it
|
|
B>ddt cpm56.com <-- Now to find the CCP in the SYSGEN image
|
|
DDT VERS 2.0
|
|
NEXT PC
|
|
2D00 0100
|
|
-d900,90f <-- Start looking around here
|
|
0900 31 80 E7 3E 06 3C 3C FE 1B CA 00 C2 DA 11 E7 D6 1..>.<<.........
|
|
-da00,a0f
|
|
0A00 31 00 01 01 01 0C C5 CD 0F E4 21 00 BE 11 00 04 1.........!.....
|
|
-db00,b0f
|
|
0B00 31 00 01 01 01 11 C5 CD 0F E4 21 00 C0 11 00 02 1.........!.....
|
|
-db80,b8f
|
|
0B80 31 00 01 01 09 01 CD A8 00 21 00 D2 11 00 C2 0E 1........!......
|
|
-- Detail Left Out --
|
|
-d1100 <-- I found it at 1100H; note the 2 JMP's
|
|
1100 C3 FF BD C3 FB BD 50 10 20 20 20 20 20 20 20 20 ......P.
|
|
1110 20 20 20 20 20 20 20 20 00 00 00 00 00 00 00 00 ........
|
|
1120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
|
-- Detail Left Out --
|
|
-^C <-- Return to CP/M; I know that CPRLOC will be
|
|
BD00H and the IMAGE offset is 1100H
|
|
|
|
B>ed cpr.asm \{edit ZCPR here and place CPRLOC=BD00H\}#
|
|
-- Detail Left Out --
|
|
|
|
B>mac cpr $pz sz <-- Now to assemble the CPR
|
|
CP/M MACRO ASSEM 2.0
|
|
C4F0 <-- Note that CPR MUST end before BDOS
|
|
begins!
|
|
014H USE FACTOR
|
|
END OF ASSEMBLY
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 6
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
|
|
B>ddt cpm56.com <-- Now to integrate!
|
|
DDT VERS 2.0
|
|
NEXT PC
|
|
2D00 0100
|
|
-h1100,bd00 <-- Compute offset for new CPR
|
|
CE00 5400 <-- Offset is 5400H
|
|
-icpr.hex <-- Init FCB
|
|
-r5400 <-- Read in new CPR with offset
|
|
NEXT PC
|
|
2D00 0000
|
|
-^C <-- Done!
|
|
B>sysgen <-- Now to SYSGEN onto disk
|
|
SYSGEN VER 2.2
|
|
SOURCE DRIVE NAME (OR RETURN TO SKIP) <-- Use memory image
|
|
DESTINATION DRIVE NAME (OR RETURN TO REBOOT)b <-- onto B:
|
|
DESTINATION ON B, THEN TYPE RETURN
|
|
FUNCTION COMPLETE
|
|
DESTINATION DRIVE NAME (OR RETURN TO REBOOT) <-- Done for now
|
|
|
|
B>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 7
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
Setting the ZCPR Inline Options
|
|
|
|
The following are the four basic options available to the
|
|
user under ZCPR for customization of his package.
|
|
|
|
Option Name Function
|
|
|
|
REL Configures CPRLOC (CPRLOC equ 0) for integration
|
|
via MOVCPM rather than the DDT/SYSGEN technique
|
|
outlined above; set to TRUE for MOVCPM integra-
|
|
tion or FALSE for DDT/SYSGEN integration
|
|
|
|
BASE Base address of your CP/M system; standard CP/M
|
|
has a base of 0, but some CP/M systems (such as
|
|
for the TRS-80 Model I and Heath/Zenith H89/Z89)
|
|
start physical RAM memory at a higher address;
|
|
equate BASE to the starting RAM memory address of
|
|
your system
|
|
|
|
CPRLOC This is the starting address of ZCPR; set the
|
|
second CPRLOC equate to the address you obtain
|
|
from BDOSLOC
|
|
|
|
RAS This is an equate which masks out selected ZCPR
|
|
command functions for security purposes on
|
|
Remote Access Systems such as Bulletin Boards;
|
|
the masked out functions currently include
|
|
SAVE, ERA, REN, JUMP, GO, and GET; set RAS to TRUE
|
|
to mask these out or FALSE to leave them in
|
|
|
|
SUBA This is an equate which determines the drive
|
|
onto which ZCPR will look for an executing
|
|
Indirect Command File. If the basic philosophy
|
|
of the Indirect Command File described above is
|
|
to be maintained, this symbol should be set to
|
|
TRUE (look on drive A: for the $$$.SUB file); if
|
|
not, this symbol should be set to FALSE (look on
|
|
the default drive from the $$$.SUB file). To
|
|
review, the basic philosophy of the Indirect
|
|
Command File is that any sequence of commands
|
|
which may be issued from the console (within
|
|
reason, which means NOT to erase a $$$.SUB file)
|
|
may also be issued from within an Indirect
|
|
Command File, and the resultant execution should
|
|
be identical (same functions performed).
|
|
|
|
CLEVEL3 This equate enables or disables extended Command
|
|
Level 3 Processing. If set to TRUE, extended
|
|
Command Level 3 Processing is enabled and the user
|
|
command line is automatically capitalized, the
|
|
terminating zero is placed at the end of the
|
|
buffer, and the internal CIBPTR is set correctly
|
|
(see later for more information).
|
|
|
|
|
|
|
|
Page 8
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
|
|
Customization Symbols
|
|
|
|
The following symbols are provided for further customization
|
|
of ZCPR to a user's particular tastes and hardware facilities.
|
|
|
|
Option Name Function
|
|
|
|
NLINES Number of lines on the user's CRT for paging
|
|
|
|
WIDE This equate is used to select a narrow or wide
|
|
display under the DIR command; if WIDE is equated
|
|
to TRUE, each file name is separated by two
|
|
spaces, a FENCE, and two more spaces; if WIDE is
|
|
equated to FALSE, each file name is separated by
|
|
one space, a FENCE, and one more space
|
|
|
|
PGDFLT This is the Paging Default flag for the TYPE
|
|
command; if PGDFLT is set to TRUE, the TYPE
|
|
command will page its output by default and
|
|
the P option on the TYPE command (see below)
|
|
will prohibit paging; if PGDFLT is set to FALSE,
|
|
the TYPE command will NOT page its output by
|
|
default and the P option will enable paging
|
|
|
|
PGDFLG This sets the option character in the command
|
|
line for the TYPE command (the 'P' mentioned
|
|
above); if the user wishes to change this option
|
|
character, he need only change this equate
|
|
|
|
MAXUSR This is the largest user number recognized by
|
|
the USER command; if the user wishes to protect
|
|
the higher user areas, he may set this symbol
|
|
to the highest area normally accessable; 15 is
|
|
the largest permitted value for MAXUSR
|
|
|
|
SYSFLG This is the option character for the DIR command
|
|
line which is used to specify that DIR search
|
|
All Files (both $SYS and $DIR) for its display;
|
|
the distributed default for this is 'A'
|
|
|
|
SOFLG This is the option character for the DIR command
|
|
line which is used to specify that DIR search
|
|
ONLY the $SYS files for its display; the distri-
|
|
buted default for this is 'S'
|
|
|
|
SUPRES Set SUPRES to TRUE to suppress printing the user
|
|
number when the user is under User Number 0 or
|
|
set SUPRES to FALSE to ALWAYS display the User
|
|
Number with the CPR prompt; with SUPRES set to
|
|
TRUE, a user on B: in user 0 sees 'B>' as the
|
|
prompt, but with SUPRES set to FALSE, a user on
|
|
B: in user 0 sees 'B0>' as the prompt
|
|
|
|
|
|
|
|
Page 9
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
DEFUSR This is the CPR-default user number which is
|
|
searched in the command hierarchy for the COM
|
|
files (distributed as 0); the DFU changes this
|
|
temporarily until a Warm Boot or Cold Boot is
|
|
done, at which time the search reverts to this
|
|
value
|
|
|
|
SPRMPT This is the CPR prompt character which indicates
|
|
that a SUBMIT file is in execution; by default
|
|
it is set to '$', so prompts like 'A$' appear
|
|
during SUBMIT file execution
|
|
|
|
CPRMPT This is the CPR prompt character which indicates
|
|
that the CPR is awaiting a user console command;
|
|
by default it is set to '>', so prompts like
|
|
'A>' appear during user input to the CPR
|
|
|
|
NUMBASE This is the escape character used by those
|
|
commands which require a DECIMAL number as
|
|
an argument; placing this character after
|
|
the number argument switches the base to
|
|
HEXADECIMAL; for example, 'SAVE 15 MYFILE' can be
|
|
expressed as 'SAVE FH MYFILE' if NUMBASE is
|
|
set to 'H' (the default)
|
|
|
|
SECTFLG This character constant is the suffix option for
|
|
the SAVE command which specifies that sectors,
|
|
as opposed to pages, are to be saved; the default
|
|
value is 'S'
|
|
|
|
FENCE This is the character printed to separate entries
|
|
in a directory listing; it's default value is '|'
|
|
|
|
|
|
Patching SUBMIT.COM
|
|
|
|
SUBMIT.COM may be patched to run with ZCPR by the following
|
|
procedure (this is recommended if the user does not have
|
|
SUB.COM). This patch simply makes it always place the $$$.SUB
|
|
file on Drive A:. Illustrative terminal session follows:
|
|
|
|
A>ddt b:submit.com
|
|
DDT VERS 2.0
|
|
NEXT PC
|
|
0600 0100
|
|
-s5bb <-- Patch is at 5BB Hex
|
|
05BB 00 1 <-- Change 0 (default drive) to 1 (drive A:)
|
|
05BC 24 . <-- That's it!
|
|
-d5b0 5cf <-- See change
|
|
05B0 00 00 00 00 00 00 30 30 31 20 24 01 24 24 24 20 ......001 $.$$$
|
|
05C0 20 20 20 20 53 55 42 00 00 00 1A 1A 1A 1A 1A 1A SUB.........
|
|
-^C <-- Done
|
|
A>save 5 newsubmt.com <-- Save new SUBMIT.COM file
|
|
|
|
|
|
|
|
Page 10
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
Part B
|
|
Usage Instructions and Explanation of Commands
|
|
|
|
|
|
The following instructions are written with the assumption
|
|
that the reader is quite familiar with how to use CP/M 2.2 and
|
|
its CCP. ZCPR is written as a logical extension of the CP/M 2.2
|
|
CCP philosophy and should be addressed as such.
|
|
|
|
|
|
|
|
The ZCPR Command Hierarchy Search
|
|
|
|
The first, and most basic thing, to learn about ZCPR is the
|
|
order in which is searches for a COM file for execution or a file
|
|
specified by the GET command. Under the CP/M 2.2 CCP, if the
|
|
specified COM file command was not found on the current drive in
|
|
the current user area, the CCP aborted with an error message.
|
|
ZCPR, however, continues searching from this point a maximum of
|
|
two more levels. This command hierarchy search was outlined
|
|
above and is described here in further detail.
|
|
|
|
1. If the command is of the form 'COMMAND' and NOT
|
|
'd:COMMAND', the CPR-resident command list is searched for a
|
|
match. If the match is found, the CPR-resident command is
|
|
immediately processed. If the match is not found or the command
|
|
is of the form 'd:COMMAND', the next step is taken. Note that
|
|
the 'd:COMMAND' form is good for executing a command COM file
|
|
which has the same name as a CPR-resident command (such as SAVE
|
|
or DIR).
|
|
|
|
2. If the command is of the form 'd:COMMAND', disk
|
|
drive 'd:' is temporarily logged in for the purpose of the
|
|
command search. Otherwise, the currently logged-in drive is
|
|
used.
|
|
|
|
3. Now the file named COMMAND.COM is searched for. If
|
|
found, it is loaded into memory starting at 100H and executed.
|
|
If not, proceed to step 4.
|
|
|
|
4. Now that the first search for COMMAND.COM has
|
|
failed, the CPR checks to see if the user is under the current
|
|
Default User Number. The Default User Number may be that set by
|
|
the DEFUSR equate in the CPR or that set by the user via the DFU
|
|
command. DEFUSR is in effect if DFU has not been issued since
|
|
the last Warm or Cold Boot, and DFU is in effect if it was issued
|
|
since the last Warm or Cold Boot. If the user is NOT under the
|
|
current Default User Number, ZCPR temporarily logs him into it
|
|
and searches the directory. If COMMAND.COM is found, it is
|
|
loaded as described above and executed. If not, ZCPR proceeds to
|
|
the next step.
|
|
|
|
|
|
|
|
|
|
|
|
Page 11
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
5. The user is now in the Default User Number, and at
|
|
this point, ZCPR checks to see if the user is on disk drive A:.
|
|
If not, it temporarily logs into A: and searches the default user
|
|
number of A: for COMMAND.COM. If found, it is loaded as
|
|
described above and executed. If not, ZCPR prints the command
|
|
name as an error message and returns to command input mode,
|
|
aborting the SUBMIT file if COMMAND came from it.
|
|
|
|
In all cases of the search above, if COMMAND.COM is found,
|
|
after it is loaded into memory, ZCPR resets the user to his
|
|
original disk drive and user number. Hence, the files referenced
|
|
by the user by default are obtained from this environment.
|
|
|
|
To illustrate this command hierarchy search, consider the
|
|
following examples:
|
|
|
|
Example 1: DEFUSR equ 0 \{default user number is 0\}
|
|
|
|
B10> <-- User is on Drive B:, User Number 10
|
|
B10>ASM TEST.BBZ <-- User wishes to assemble TEST.ASM in
|
|
Drive B:, User 10
|
|
<-- At this point, ZCPR looks on B:/10 for ASM.COM, fails,
|
|
looks on B:/0, fails, and finally looks on A:/0; it
|
|
finds ASM.COM here and goes back to B:/10 for the file
|
|
|
|
|
|
Example 2: DEFUSR equ 0 and DFU issued
|
|
|
|
B10> <-- User is on Drive B:, User Number 10
|
|
B10>DFU 5 <-- User Selects User 5 as default
|
|
B10>ASM TEST.BBZ <-- As above
|
|
<-- At this point, ZCPR looks on B:/10 for ASM.COM, fails,
|
|
look on B:/5, fails, and finally looks on A:/5; it
|
|
fails here also and prints ASM? as an error message
|
|
|
|
Example 3: DEFUSR equ 0
|
|
|
|
B> <-- User is on Drive B:, User Number 0
|
|
B>ASM TEST.BBZ <-- As above
|
|
<-- At this point, ZCPR looks on B:/0 for ASM.COM, fails,
|
|
looks on A:/0, fails, and prints error message
|
|
|
|
Example 4: DEFUSR equ 0
|
|
|
|
A10> <-- User is on Drive A:, User Number 10
|
|
A10>ASM TEST.AAZ <-- As above, but file on A:
|
|
<-- At this point, ZCPR looks on A:/10 for ASM.COM, fails,
|
|
looks on A:/0, fails, and prints error message
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 12
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
Another Example:
|
|
|
|
For example, if the user is logged into Drive B: in
|
|
User Area 10, the Default User Number is 0, and the following COM
|
|
files are present as indicated --
|
|
|
|
WM.COM on Drive A: in User 0
|
|
MBASIC.COM on Drive A: in User 0 and on
|
|
Drive B: in User 0
|
|
TEST.COM on Drive B: in User 10 and Drive B:
|
|
in User 0
|
|
|
|
then the following happens when the following commands are
|
|
issued from the console (or Indirect Command File):
|
|
|
|
B10>WM TEST2.TXT
|
|
^ ^ ^-------- File to be edited
|
|
| +----------- Invoke the WM.COM file (Word Master editor)
|
|
+--------------- User is on Drive B: in User Area 10
|
|
|
|
Results:
|
|
ZCPR searches B: User 10, B: User 0, and A: User 0 for
|
|
WM.COM; it finds WM.COM in A: User 0, loads it, logs the user
|
|
back into B: User 10, and executes it.
|
|
|
|
B10>MBASIC
|
|
^ ^----- Invoke the MBASIC.COM file (MBASIC Interpreter)
|
|
+--------- User is on Drive B: in User Area 10
|
|
|
|
Results:
|
|
ZCPR searches B: User 10 and B: User 0 for MBASIC.COM;
|
|
it finds MBASIC.COM in B: User 0, so it doesn't bother to look on
|
|
A: User 0. MBASIC.COM is then loaded and executed as described
|
|
in the previous example.
|
|
|
|
B10>TEST
|
|
^ ^--- Invoke the TEST.COM file (TEST program)
|
|
+------- User is on Drive B: in User Area 10
|
|
|
|
Results:
|
|
ZCPR searches B: User 10 for TEST.COM; it finds
|
|
TEST.COM in B: User 0, so it doesn't bother to look further (if
|
|
it had, it would have found TEST.COM in B: User 0). TEST.COM is
|
|
then loaded and executed as described above.
|
|
|
|
B10>TEST2
|
|
| +--- Invoke the TEST2.COM file (TEST2 program)
|
|
+------- User is on Drive B: in User Area 10
|
|
|
|
Results:
|
|
ZCPR searches B: User 10, B: User 0, and A: User 0 for
|
|
TEST2.COM; it doesn't find it, so it issues the error message
|
|
'TEST2?', which says it couldn't find TEST2.COM.
|
|
|
|
|
|
|
|
Page 13
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
|
|
|
|
The ZCPR-Resident Commands
|
|
|
|
The following pages describe the ZCPR-Resident Commands.
|
|
These are commands located within ZCPR itself which are executed
|
|
from within ZCPR. The phrases <afn> and <ufn> refer to ambiguous
|
|
file name and unambigous file name as per the CP/M convention.
|
|
|
|
Command: DIR
|
|
Function: To Display a listing of the names of the files on disk
|
|
Forms:
|
|
DIR <afn> <-- Displays $DIR files
|
|
DIR <afn> S <-- Displays $SYS files
|
|
DIR <afn> A <-- Displays both $DIR and $SYS files
|
|
Customization Variables:
|
|
WIDE SYSFLG SOFLG FENCE
|
|
Examples:
|
|
DIR *.ASM <-- All $DIR .ASM files
|
|
DIR *.COM S <-- All $SYS .COM files
|
|
DIR *.COM A <-- All .COM files
|
|
Notes:
|
|
If a file is scanned for and no such name exists on disk,
|
|
the 'No Files' message will appear. However, if a file is
|
|
scanned for and the name exists as a $SYS file and $DIR files are
|
|
being scanned for, no file name is displayed but the 'No Files'
|
|
message does NOT appear. For example, if TEST.COM is a $SYS file
|
|
and 'DIR TEST.COM' is issued, no message appears. If 'DIR
|
|
TEXT.COM' is issued and TEXT.COM does not exist on disk, the 'No
|
|
Files' message is displayed.
|
|
|
|
|
|
Command: ERA
|
|
Function: To Erase the specified $R/W files from disk
|
|
Forms:
|
|
ERA <afn> <-- Erase both $DIR and $SYS files
|
|
Customization Variables:
|
|
WIDE FENCE
|
|
Examples:
|
|
ERA *.ASM <-- Erase all .ASM files
|
|
ERA *.* <-- Erase all files
|
|
Notes:
|
|
If a $R/O file is encountered, a BDOS error message will be
|
|
displayed and the procedure is stopped. The user is unsure at
|
|
this time as to which files have been erased and which have not
|
|
and should check. Sorry for this problem! The ERASE command (to
|
|
be given to SIG/M by RLC in the near future) is a solution to
|
|
this problem.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 14
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
|
|
Command: LIST
|
|
Function: To Print the specified file on the CP/M LST: device
|
|
Forms:
|
|
LIST <ufn> <-- Print the file (no paging)
|
|
Customization Variables:
|
|
-None-
|
|
Examples:
|
|
LIST TEST.TXT <-- Print TEST.TXT on LST:
|
|
Notes:
|
|
If the file has a $SYS attribute, it will be found as well
|
|
as those with $DIR attributes.
|
|
|
|
|
|
Command: TYPE
|
|
Function: To Print the specified file on the CP/M CON: device
|
|
Forms:
|
|
TYPE <ufn> <-- Print the file with the paging deflt
|
|
TYPE <ufn> P <-- Print the file with the paging deflt
|
|
negated
|
|
Customization Variables:
|
|
NLINES PGDFLT PGDFLG
|
|
Examples:
|
|
TYPE TEST.TXT
|
|
TYPE TEST.TXT P
|
|
Notes:
|
|
When the display pauses during paging, type any char to
|
|
continue or ^C to abort. ^S also works.
|
|
|
|
|
|
Command: SAVE
|
|
Function: To Copy the TPA starting at 100H to disk
|
|
Forms:
|
|
SAVE <Number of Pages> <ufn> <-- <Number of Pages> in DEC
|
|
SAVE <Number of Pages>H <ufn> <-- <Number of Pages> in HEX
|
|
SAVE <Number of Sectors> <ufn> S <-- Number of sectors
|
|
SAVE <Number of Sectors>H <ufn> S <-- Number of sectors
|
|
Customization Variables:
|
|
NUMBASE RAS
|
|
Examples:
|
|
SAVE 15 MYFILE.TXT <-- 15 pages saved
|
|
SAVE FH MYFILE.TXT <-- 15 pages saved
|
|
SAVE 10H MYFILE.TXT S <-- 16 sectors (8 pages) saved
|
|
Notes:
|
|
If the file name to be saved already exists, then SAVE will
|
|
exit with the message 'Delete File?'; if the user REALLY wants to
|
|
save under this name, he may then type Y or y and the current
|
|
file will be deleted and then recreated containing the specified
|
|
part of the TPA.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 15
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
|
|
|
|
Command: REN
|
|
Function: To Change the name of a disk file
|
|
Forms:
|
|
REN <ufn new>=<ufn old>
|
|
Customization Variables:
|
|
RAS
|
|
Examples:
|
|
REN NEWFILE.TXT=OLDFILE.TXT
|
|
Notes:
|
|
If <ufn new> already exists, the message 'Delete File?' will
|
|
be printed and the user may respond with Y or y to delete the
|
|
current <ufn new> and then rename <ufn old> to <ufn new>.
|
|
|
|
Command: USER
|
|
Function: To Change the current user number
|
|
Forms:
|
|
USER <User Number> <-- <User Number> in DEC
|
|
USER <User Number>H <-- <User Number> in HEX
|
|
Customization Variables:
|
|
-None-
|
|
Examples:
|
|
USER 15 USER FH USER 0
|
|
USER <-- Same as USER 0
|
|
Notes:
|
|
-None-
|
|
|
|
|
|
Command: DFU
|
|
Function: To Temporarily Change the default user number for the
|
|
command hierarchy search
|
|
Forms:
|
|
DFU <User Number> <-- <User Number> in DEC
|
|
DFU <User Number>H <-- <User Number> in HEX
|
|
Customization Variables:
|
|
-None-
|
|
Examples:
|
|
DFU 15 DFU FH DFU 0
|
|
DFU <-- Same as DFU 0
|
|
Notes:
|
|
See above for explanation.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 16
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
|
|
|
|
Command: JUMP
|
|
Function: To "call" the subroutine at the specified page address
|
|
Forms:
|
|
JUMP <Address> <Cmd Parms> <-- <Address> in HEX
|
|
Customization Variables:
|
|
NUMBASE RAS
|
|
Examples:
|
|
JUMP E000 or JUMP E000H <-- Jump to E000H
|
|
JUMP <-- Jump to 000H
|
|
JUMP 0 <-- Jump to 000H
|
|
Notes:
|
|
JUMP performs a subroutine "call", so the called routine may
|
|
return to the ZCPR by either a RET or a Warm Boot.
|
|
|
|
|
|
Command: GO
|
|
Function: To "call" the subroutine starting at 100H
|
|
Forms:
|
|
GO <Cmd Parms> <-- Execute reentrant at 100H
|
|
Customization Variables:
|
|
RAS
|
|
Examples:
|
|
GO *.ASM <-- Assuming XDIR is loaded,
|
|
gives directory of *.ASM
|
|
Notes:
|
|
This command is identical in function to JUMP 100H; JUMP,
|
|
however, leaves the address as the first entry in CP/M BASE + 80H
|
|
(the input line buffer), while GO has no such address.
|
|
|
|
|
|
Command: GET
|
|
Function: To load a file from disk into memory starting at the
|
|
specified page
|
|
Forms:
|
|
GET <Address> <ufn> <-- <Address> in HEX
|
|
Customization Variables:
|
|
NUMBASE RAS
|
|
Examples:
|
|
GET 8000 TEST.80 <-- Load TEST.80 starting at 8000H
|
|
GET 100 TEST.80 or GET 100H TEST.80 <-- Load TEST.80
|
|
starting at 100H
|
|
GET 0 TEST.80 <-- Load TEST.80 starting at 000H
|
|
Notes:
|
|
GET searches for the specified file according to the same
|
|
command hierarchy search employed by the ZCPR command scanner.
|
|
Hence, if the user is on B:/10 and the file is on A:/0 with the
|
|
current default user number at 0, GET will search from B:/10 to
|
|
B:/0 to A:/0 in looking for the file.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 17
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
ZCPR Error Messages
|
|
|
|
The following are the error messages issued by ZCPR and
|
|
their meanings.
|
|
|
|
Message Meaning
|
|
|
|
? Printed after a command or an argument means that such
|
|
was invalid
|
|
|
|
No File From DIR, this means that DIR did not locate any files
|
|
Also from ERA with the same meaning
|
|
|
|
All? Issued in response ERA *.*, asks the user is he really
|
|
wants to erase all the files. Unlike under the
|
|
original CP/M 2.2 CCP, single character input is
|
|
required (Y or y for yes and anything else for no)
|
|
with NO <CR> to end the line
|
|
|
|
Full From SAVE, means that there is not enough space on
|
|
disk
|
|
From GET or command load by CPR, means that there
|
|
is not enough space in memory
|
|
|
|
Delete File?
|
|
From REN or SAVE, means that the file specified already
|
|
exists on disk and the user may type Y or y to delete
|
|
it and proceed with the REN or SAVE function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 18
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
|
|
Part C
|
|
ZCPR Command Levels and How to Use Them
|
|
|
|
|
|
ZCPR Version 1.0 and beyond supports three distinct command
|
|
levels in its implementation. Each level constitutes a different
|
|
way to issue a command for ZCPR to process.
|
|
|
|
Command Levels 1 and 2 are common to all implementations of
|
|
CP/M and CP/ZM from CP/M Version 1.4. Command Level 1 is that
|
|
command level in which the command is issued by the user from his
|
|
console terminal. The prompt 'd>' or 'du>' appears on the
|
|
terminal, and the user is allowed to enter the command with
|
|
editing from the terminal. Command Level 2 is that command level
|
|
in which the command is entered from an executing $$$.SUB file.
|
|
|
|
In both cases, the command is stored in the internal ZCPR
|
|
buffer called CIBUFF (Command Input BUFFer). Under both Command
|
|
Levels 1 and 2, the command is placed into this buffer, the
|
|
characters of the command line are capitalized, a character count
|
|
which indicates the number of characters in the command line is
|
|
stored in CBUFF (the byte before CIBUFF), an ending binary 0 is
|
|
placed after the last character in the command line, and the
|
|
internal pointer CIBPTR (Command Input Buffer PoinTeR) is set to
|
|
point to CIBUFF (the first character of the command line).
|
|
|
|
Command Level 3 is an extended concept to Command Levels 1
|
|
and 2 which is specifically supported by ZCPR Version 1.0 and
|
|
beyond. This command level allows a transient program to place a
|
|
command line into CIBUFF and the character count into CBUFF and
|
|
have this command line executed by ZCPR. Once control is trans-
|
|
ferred to ZCPR to execute the command line, the transient program
|
|
which placed the command line loses control and the command is
|
|
executed exactly as though it had been typed by the user at his
|
|
console terminal.
|
|
|
|
In order for a transient program to utilize the Command
|
|
Level 3 facility, this program MUST do the following:
|
|
|
|
1. Locate the ZCPR. Since the ZCPR is ALWAYS 2K bytes
|
|
in size and located directly under the BDOS, the transient can
|
|
locate the ZCPR by examining the BDOS entry page address at
|
|
location 7 and subtracting 8 from this number (8 pages = 2K
|
|
bytes). The resulting number is the base page address of ZCPR.
|
|
|
|
2. Store the command line in CIBUFF and the character
|
|
count in CBUFF. Knowing the base page address of ZCPR, the
|
|
following information is useful in doing this:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 19
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
|
|
ORG CPRLOC ;Base Address of ZCPR
|
|
JMP CPR ;Enter ZCPR and Execute Default Cmd
|
|
JMP CPR1 ;Enter ZCPR and Don't Execute
|
|
MBUFF: DB BUFLEN ;Size of CIBUFF in bytes
|
|
CBUFF: DS 1 ;Number of Bytes in Command Line
|
|
CIBUFF: DS BUFLEN ;Buffer for Command Line
|
|
DS 1 ;Buffer for Ending 0 (set by ZCPR)
|
|
CIBPTR: DS 2 ;Address of CIBUFF (set by ZCPR)
|
|
|
|
|
|
3. Obtain the User/Disk Flag. Location 4 contains
|
|
this number, but the user may select a flag of his choice. This
|
|
flag is one byte long, and the high-order nybble (4 bits)
|
|
contains the user number and the low-order nybble contains the
|
|
disk number to process the command from. The User/Disk Flag is
|
|
to be passed to ZCPR in the C Register.
|
|
|
|
4. When ready, transfer control to ZCPR to process the
|
|
command by JMPing to the base address of ZCPR. The first JMP in
|
|
the JMP Table given above is at this address. At this time, ZCPR
|
|
will log in the user and disk in the User/Disk Flag and process
|
|
the Command Level 3 Command Line.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 20
|
|
|
|
|
|
|
|
|
|
|
|
ZCPR - A Z80 Replacement for the CP/M CCP
|
|
|
|
|
|
|
|
|
|
The following is a sample program which illustrates the
|
|
steps outlined above:
|
|
|
|
;
|
|
; Demonstration of Command Level 3 Facility by RLC
|
|
;
|
|
udflag equ 4 ;Address of User/Disk Flag
|
|
bdos equ 5 ;Address of BDOS Entry Point
|
|
|
|
org 100h
|
|
|
|
lxi d,prmpt ;Print User Prompt
|
|
mvi c,9 ;PRINT function
|
|
call bdos
|
|
|
|
lhld bdos+1 ;Get address of BDOS
|
|
mov a,h ;High-Order Address in A
|
|
sui 8 ;A=High-Order Address of CPR
|
|
mov h,a ;HL=Address of CPR
|
|
mvi l,0
|
|
shld cpr ;Save address in buffer
|
|
|
|
lxi d,6 ;Point to command line buffer
|
|
dad d ;HL points to command line buffer
|
|
xchg ;DE points to command line buffer
|
|
mvi c,10 ;READLN into this buffer
|
|
call bdos
|
|
|
|
lhld cpr ;Get Address of CPR
|
|
lda udflag ;Get User/Disk Flag
|
|
mov c,a ; ... in C
|
|
pchl ;Run Command Line
|
|
|
|
cpr: ds 2 ;CPR Address buffer
|
|
prmpt: db 'User Command? $'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Enjoy using ZCPR!
|
|
-- RLC
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 21
|