ISX - An ISIS-II emulator
Browsing through the CP/M unofficial pages I found an interesting piece of
software: an ISIS-II emulator for the CP/M operating system. In case you are
too young to know it (or too old to remember it), ISIS-II was an early operating
system released by Intel for their MDS series of development machines. 
I wanted to get this historical curiosity running on the P112. 
 Exact file sizes
In contrast with CP/M 2.2, ISIS-II supports file sizes with byte
resolution, and so does the ISX emulator. How it was done? A disassembly of the emulator shows that
the disk subsystem is based on the vanilla CP/M 2.2 BDOS; minor changes were
done so the BDOS size could stay the same. The exact file size support is
similar in principle to what both CP/M 3.0 and DOS+ 2.5 do, but there are
differences: 
The CP/M 3.0 and DOS+ 2.5 way: 
When a file is opened, if the CR byte at FCB offset 32 is set to 0FFh, the
count of unused bytes in the last record will be returned there.
The count may be set with function 30 (Set File Attributes) by setting the
F6 (interface attribute) bit and placing the count in CR. The count is
normally 0 and can range up to 7Fh (127). 
Note: The DOS+ 2.5 documentation explicitly states
that the last record byte count is the number of unused bytes.
Apparently, the CP/M 3.0 documentation does not mention how the S1 byte
should be interpreted, and that leaves two possibilities: the number of
used bytes or the number of unused bytes. The ISIS emulator
follows the first interpretation (see below), but a couple of other popular
utilities follow the second one: Tilmann Reh's MSDOS, PIP under DOS Plus,
and John Elliot's MSODBALL. 
 
The ISX way: 
The number of unused bytes is saved in the S1 byte (offset 13)
of the directory entry corresponding to the last extent of the file.
The count can be retrieved by using the Search First and Search Next functions
(the extent field must contain a '?' character), or by the File Open
function. The count may be set by opening the file, writing the
appropriate value into the S1 byte (offset 13) and calling the BDOS Close File
function. The count can range from 0 up to 7Fh. 
 
There is a SETEOF utility included with the emulator, which is used to
adjust the size of CP/M text files before they can be used by ISIS
utilities. Here is what it does: 
- opens the file
 
- seeks to the last record
 
- computes the unused byte count by searching backwards for the first
non-^Z character and saves the resulting value into FCB's S1
 
- clears the high bit of S2 (apparently to simulate that the file was
modified)
 
- closes the file
 
 
You will probably notice that this is not the best way to determine where
a text file ends: the method might fail for text files that have been
SAVEd, since there are chances that an extra record is appended (the SAVE
command has a 2-record resolution). Also, some text editors might not fill
the remainder of the record with ^Z characters, as SETEOF expects. A better
way would be to scan the text file from the very beginning until the first
^Z is encountered. However, the SETEOF method is faster and will work for
files that have been EDited. 
Text files created by ISIS programs will have the size field setup
correctly; SETEOF does not need to be called for such files unless you
edit them under CP/M. 
SETEOF requires a CP/M system using the same modified
BDOS that the ISX emulator subsystem uses. Therefore, it will not
work under the standard CP/M or a Z-system. 
Emulator commands
The ISX command line processor is based on the standard CP/M CCP. There
are the familiar DIR, ERA, TYPE and REN commands, but USER is missing: it
was replaced by a DBUG command, which can be used to trace the execution
of ISIS system calls. The new command apparently was intended for debugging
the ISX emulator itself, according to the amount and type of information it
provides, but it can be useful when debugging ISIS programs or just to see
what they are doing. 
In response to the DBUG command, the emulator asks for a "trace level".
As response it will only accept a string of ones (111...) terminated by a
CR, or a single hash (#). Anything else will cause the prompt to be
displayed again. The more ones you enter, the more detailed trace dump you
will get (think of the 1's as some sort of bit mask), but only the first
5 ones entered are meaningful. To disable tracing, just hit Enter (CR)
when prompted for the trace level. The hash character is used when debugging
ISX under DDT, SID or a similar program; it forces the emulator to break
into the debugger via RST 7. Don't use it without a debugger, or your
system will hang. 
The trace dump format is easier to understand with an example. The
following is the output for the ISIS READ function: 
003: 261E READ     464B (44A3)
   000:0002 81  X0100. E00 U00 R03 C00 L80 @3600 B0003 ,00
   001:465D->
   002:A3A2
   003:4518->
   004:45B4->
   465D=1902   4518=0180   45B4=0000
 
 
The first line shows, from left to right: 
 003:  - ISIS function code (contents of C register)
 261E  - address of the handling routine in the DOS subsystem
 READ  - ISIS function name
 464B  - address of function argument block (contents of DE register)
(44A3) - where this routine was called from
         (address of CALL instruction in the user program)
 
Then, the function arguments will follow, one per line, in the form: 
 000:  - argument number, count starts at 0
 0002  - argument value, followed by a -> if the argument is a pointer.
         In this example, the first argument to the READ system call is a
         file descriptor, and the dump of the corresponding ISX structure
         is output next:
          81     - file descriptor flags; bits are in the form ufffffwr,
                   where:
                     u     = 'in use' bit (1 = fd used, 0 = fd is free)
                     fffff = associated internal FCB number
                     w     = 'write' mode bit
                     r     = 'read' mode bit
                   note that both r and w bits can be set at the same time
          X0100. - file name and extension
          E00    - FCB extent value
          U00    - FCB s1 value (unused bytes count)
          R03    - FCB rc value
          C00    - FCB cr value
          L80    - FCB r0 value
          @3600  - I/O buffer address
          B0003  - number of records
          ,00    - last record byte count
 
Additionally, the contents of one or more I/O buffers may be displayed,
depending on the current trace level. Finally, the word value
referenced by every pointer in the function call is shown in the form
addr=value: 
 465D=1902   4518=0180   45B4=0000
 
 
The ISIS operating system defines 15 functions, they are: 
 
  | Number | 
  Name | 
  Arguments (* means is a pointer) | 
 
  | 0 | 
  OPEN | 
  WORD *fd, BYTE *path, WORD access, WORD echo, WORD *status
   | 
 
  | 1 | 
  CLOSE | 
  WORD fd, WORD *status
   | 
 
  | 2 | 
  DELETE | 
  BYTE *path, WORD *status
   | 
 
  | 3 | 
  READ | 
  WORD fd, BYTE *buff, WORD count, WORD *actual, WORD *status
   | 
 
  | 4 | 
  WRITE | 
  WORD fd, BYTE *buff, WORD count, WORD *status
   | 
 
  | 5 | 
  SEEK | 
  WORD fd, WORD mode, WORD *block, WORD *byte, WORD *status
   | 
 
  | 6 | 
  LOAD | 
  BYTE *path, WORD offset, WORD switch, WORD *entry_pt, WORD *status
   | 
 
  | 7 | 
  RENAME | 
  BYTE *old, BYTE *new, WORD *status
   | 
 
  | 8 | 
  CONSOLE | 
  WORD *ci, WORD *co, WORD *status
   | 
 
  | 9 | 
  EXIT | 
  (none)
   | 
 
  | 10 | 
  ATTRIB | 
  BYTE *path, WORD attrib, WORD on_off, WORD *status
   | 
 
  | 11 | 
  RESCAN | 
  WORD fd, WORD *status
   | 
 
  | 12 | 
  ERROR | 
  WORD errnum
   | 
 
  | 13 | 
  WHOCON | 
  WORD fd, BYTE *buff
   | 
 
  | 14 | 
  SPATH | 
  BYTE *path, BYTE *info, WORD *status
   | 
 
 
 
Device names
Under the emulator you can use either the ISIS-II or CP/M notation
when specifying disks and device names in the command line. Thus, :F0: and
A: are the same thing, CON: and :CO: are equivalent, etc. (see table below).
That is valid at least for CP/M-style commands like DIR, ERA and REN.
ISIS-II utilities will typically allow only ISIS-style names. 
The device handling routines expect IOBYTE support in the BIOS. For some
devices, the ISX emulator changes the IOBYTE assignment before calling the
BDOS handling routine, and restores it afterwards: 
 
  | Input Devices | 
 
  | CP/M | 
  ISIS | 
  IOBYTE | 
  BDOS function | 
 
  | CON: | 
  :CI: | 
  Not changed | 
  1 | 
 
  | RDR: | 
  :RD: | 
  Not changed | 
  3 | 
 
  | TTY: | 
  :TI: | 
  CON:=TTY: | 
  1 | 
 
  | CRT: | 
  :VI: | 
  CON:=CRT: | 
  1 | 
 
  | UC1: | 
  :I1: | 
  CON:=UC1: | 
  1 | 
 
  | PTR: | 
  :HR: | 
  RDR:=PTR: | 
  3 | 
 
  | UR1: | 
  :R1: | 
  RDR:=UR1: | 
  3 | 
 
  | UR2: | 
  :R2: | 
  RDR:=UR2: | 
  3 | 
 
  | EMP: | 
  :BB: | 
  Not changed | 
  None (empty device, returns ^Z) | 
 
  | Output Devices | 
 
  | CP/M | 
  ISIS | 
  IOBYTE | 
  BDOS function | 
 
  | CON: | 
  :CO: | 
  Not changed | 
  2 | 
 
  | LST: | 
  :LS: | 
  Not changed | 
  5 | 
 
  | PUN: | 
  :PN: | 
  Not changed | 
  4 | 
 
  | TTY: | 
  :TO: | 
  CON:=TTY: | 
  2 | 
 
  | CRT: | 
  :VO: | 
  CON:=CRT: | 
  2 | 
 
  | UC1: | 
  :O1: | 
  CON:=UC1: | 
  2 | 
 
  | LPT: | 
  :LP: | 
  LST:=LPT: | 
  5 | 
 
  | UL1: | 
  :L1: | 
  LST:=UL1: | 
  5 | 
 
  | PTP: | 
  :HP: | 
  PUN:=PTP: | 
  4 | 
 
  | UP1: | 
  :P1: | 
  PUN:=UP1: | 
  4 | 
 
  | UP2: | 
  :P2: | 
  PUN:=UP2: | 
  4 | 
 
  | EMP: | 
  :BB: | 
  Not changed | 
  None (empty device) | 
 
 
 
Memory map
 
  | Address Range | 
  Description | 
 
  | 0040...0042 | 
  Jump vector to ISIS DOS.
   | 
 
  | 0180...0FFF | 
  BDOS subsystem. Replaces the CP/M BDOS,
      which can be overlaid by ISIS application programs. This is a
      slightly modified CP/M 2.2 BDOS, the modification just adds
      support for exact file lengths, feature needed by ISIS programs.
   | 
 
  | 1000...30FF | 
  ISIS DOS emulation subsystem. Emulates ISIS
      system calls and interprets user commands. The command line processor
      is based on CP/M CCP.
   | 
 
  | 4000...MEMTOP | 
  Transient area for ISIS programs. | 
 
  | MEMTOP...FFFF | 
  BIOS subsystem (standard CP/M BIOS).
      The MEMTOP address is set by the ISX emulator to the start of the BIOS
      or to F700h, whichever is lower. | 
 
  | F800...F87F | 
  MDS-800 BIOS jump table. | 
 
 
 
Running the emulator
Necessary system modifications: 
- A 128-byte area (F800h...F87Fh) must be reserved in the BIOS for the
emulated MDS-800 monitor jump table. The BIOS does not have to initialize
the jump vectors itself, ISX will take care of that.
 
- Since ISIS-II applications might overlay the CP/M BDOS, your BIOS
should reload CCP and BDOS on warm boot.
 
- For proper work of the SETEOF utility, you must replace your CP/M
BDOS module with the same modified version the ISX emulator uses.
 
 
The disassembled ISX 1.4 can be found in the
downloads area. There you'll find also
a bootable 3.5" floppy disk image
with a working copy of ISX. The system uses a 60K CP/M with a modified BIOS
whose data area is located above F900h. 
There are several SUBMIT files included with the emulator to aid
with compilation (ISIS-II command lines can get really long): 
IC.SUB - ISIS Compile (PL/M-80 source to ISIS executable) 
CC.SUB - CP/M Compile (PL/M-80 source to CP/M executable) 
PRL.SUB - PRL Compile (PL/M-80 source to MP/M PRL) 
 
Note that by default the PL/M compiler stores intermediate files in
:F1: (disk B: in the CP/M world), so your P112 should have a second drive
connected, and a disk with enough free space on it. 
Last updated: 10-Apr-2018 
     |