
Summary of words from HP-IPL/OS 1.60 (6/20/10)

Base version...

EXECUTE - pops stack and executes from address contained there
RUN - pops stack and runs machine code there
WBOOT - restarts hpiplos without running autostart words
AND - pops stack twice, does bit-wise AND and pushes result
OR - pops stack twice, does OR and pushes result
XOR - pops stack twice, does XOR and pushes result
ADD - pops stack twice, adds the two and pushes result
SUB - subtracts 1st pop from 2nd pop and pushes res. (3 2 SUB pushes 1)
MUL - pops two items from stack, multiplies and pushes results
DIV - divides 2nd pop by 1st pop and pushes res. (6 2 DIV pushes 3)
INC - pops stack, adds one and pushes results
DEC - pops stack, subtracts one and pushes results
ROL - pops stack, rotates left, pushes results
ROR - pops stack, rotates right, pushes results
ASL - pops stack, shifts left (lsb 0), pushes results
ASR - pops stack, shifts right (msb 0), pushes results
NOT - pops stack, reverses 1's and 0's and pushes results
2CPL - pops stack, does 2's compliment and pushes results
DUP - pops stack and pushes twice, duplicating the top entry
DROP - pops stack to nothing
OVER - duplicates stack over current (1 2 OVER yields 1 2 1 on stack)
ROT - swaps two items over current (1 2 3 ROT yields 2 1 3)
SWAP - swaps the top two stack items
GET - pops stack, gets memory there and pushes data
PUT - a b PUT writes b to location a
DO - pushes address of next instruction on return stack - starts a loop
UNTIL - pops stack, if zero continues DO loop
WHILE - pops stack, if not zero continues DO loop
PNUM - pops stack and prints as a number
CRLF - prints a new-line to the console
DECIMAL - sets number-radix to 10 with leading zeros suppressed
OCTAL - sets radix to 8, displays numbers as 6 digits
BINARY - sets radix to 2, displays numbers as 16 digits
SP>S - pushes stack pointer to stack (pushes 1st unused pos. BEFORE the push)
SB>S - pushes stack base to stack
XP>S, XB>S, YP>S, YB>S, ZP>S, ZB>S - pointer/base for X/Y/Z stacks
>STEP - pops stack and sets +DO increment used by next +LOOP
 (do not use within nested loops unless outer loop inc is 1)
+DO - pops startval and endval and sets up a loop
INDEX - pushes current DO index
+LOOP - adds one to index and if <> endval repeats loop
DMPS - dumps the stack
DEFINE name - starts a new word definition
END - terminates a definition
PCHR - pops stack and prints as a single character
PWRD - pops stack and prints as a double-character
$PRINT - prints string on the X stack
IFNZ - pops stack, if not 0 continues else jumps to corresponding ELSE/ENDIF
IFZ - pops stack, if zero continues else jumps to ELSE or ENDIF
IF<0 - pops stack, if less than zero continues else jumps to ELSE or ENDIF
ELSE - when run jumps to corresponding ENDIF
ENDIF - terminates an IFZ/IFNZ/IF<0/ELSE block
CASE - pops stack and searches for matching condition
= < > <= >= <>  - condition markers, must be followed by number, const or var
DEFAULT - optional default condition marker for when no matches
ENDCASE - terminates a case structure
S>X - pops (system) stack and pushes to X stack
X>S - pops X stack and pushes to system stack
S>Y, S>Z, Y>S and Z>S provide same for Y and Z stacks
X>>Y, X>>Z, Y>>X, Z>>X - string moves
S>SR - pops stack and writes to Switch Register
SR>S - reads Switch Register and pushes to stack
$CPY - string copy from X to Y (leaving on X)
$DUP - duplicates string on X
$SWAP - swaps 2 strings on X
$DROP - removes string from X
$IN - inputs string up to CR and pushes (without CR) to the X stack
$GET - n $GET gets byte# n from string on X and pushes to system stack
$PUT - n b $PUT puts b into byte# n of string on X
$LEN - pushes true character length of string on X to S
$CREATE - n b $CREATE creates a string on X containing n bytes of b
$ADR - pushes address of first element of string on X
$XTEST - prints error message and restarts if value on stack is below XB
$STR - pops stack and converts to a string on X
CHRIN - inputs one character and pushes to stack
RND - pushes random number to S
$APPEND - pops stack and appends character to string on X
$HEAD - removes 1st char from string on X and pushes to stack
$TAIL - removes last char from string on X and pushes to stack
$IN - inputs string up to but not including return to string on X
$VAL - pops string on X and pushes value to stack (0 if not a number)
$CAT - combines two strings on X into one string
<>CON - resets I/O to console
CONSOLE - like <>CON but also sets MS to papertape
>PTP - redirects output to papertape punch
<PTR - redirects input from papertape reader
MSBIN - reads byte from mass-storage and pushes to stack
MSWIN - reads word from mass-storage and pushes to stack
MSBOUT - pops stack and writes byte from mass-storage
MSWOUT - pops stack and writes word to mass-storage
MS$OUT - pops and writes string from X to mass storage
MS$IN - inputs string from mass storage using redirected $IN
MSCRLF - sends a CRLF sequence to mass storage output
MSPAPER - sets mass storage vectors to paper-tape
MS_SAVE - saves current MS byte vectors
MS_RESTORE - restores previously saved MS byte vectors
INBLOCK - pops and sets mass storage input to specified block
OUTBLOCK - pops and sets mass storage output to specified block
BPUT - block word put - word offset block BPUT
BGET - block word get - offset block BGET (word on stack)
ZEROBLOCK - pops stack and writes 1K word zeros to that block
 (note.. redirects MS output, MS_SAVE/MS_RESTORE if important)
GETIP - pushes value of input byte pointer
SETIP - pops and sets input byte pointer
GETOP - pushes value of output byte pointer
SETOP - pops and sets output byte pointer
>MS - directs regular text output to mass storage
<MS - directs regular text and console input from mass storage
EOD - pushes current end-of-dictionary
RADIX - pushes current radix number
VARIABLE - defines a variable, usage: VARIABLE Name [size]
CONSTANT - defines a constant, usage: CONSTANT Name Value
TOKEN - if another token in buffer returns in @TL,@TB1,@TB2
        and pushes 0, otherwise pushes non-zero
SDIC - searches dictionary for token in @TL,@TB1,@TB2 and
       pushes address twice if found, else pushes 0
HEADER$ - pops stack and pushes string containing header name + " "
WORDS - lists defined words, prints EOD and free space
ALLOCATE - pops and allocates specified number of blocks
$DEFADR - pops string and pushes word address of definition
+IRQ - turns on interrupts (note usually renamed to !IRQ)
-IRQ - turns off interrupts
+AUTO - turns on autostart of words beginning with !
-AUTO - turns off autostart (or put 177777 in switch reg)

Used by defining words... (variable constant create etc)

ADDCODE - pops stack, writes to mem spec'd by @DIPTR, increments @DIPTR
ADDHEADER - finds end, adds definition header spec'd by @TL/@TB1/@TB2,
  saves fix info (len, initial address) to Z, sets @DIPTR to where
  the ENSEC or *+1 code should go
ADDHEADER$ - pops string containing definition name, sets @TL/@TB1/@TB2
  and runs ADDHEADER
ADDMLVAR - adds definition body containing *+1 and machine code that
  pushes the contents of an internal location, used by VARIABLE/CONSTANT
FIXLINKS - pops initial address and len from Z and completes definition

Constants and addresses...

#0 - pushes a 0
#1 - pushes a 1
@DIC - pushes location w/ start of dictionary
@USR - pushes location w/ start of user dictionary
@BLK - pushes location w/ start of block memory
@END - pushes location w/ end of block memory
@TB, @TL1, @TL2 - addresses of TOKEN/SDIC variables
@ENSEC, @RTSEC - addresses of Enter/Return Secondary
@LITERAL - address of threaded literal push
@STRING - address of threaded string push
@CLH - address of Console Literal handler (SDIC returns for literals)
@ANVAL - address of Ascii Number Value (SDIC sets for literals)
@DIPTR - zero-page variable for use as a code pointer
@LLP - "last load point" var, set to EOD before <PTR or <MS (new for 1.6)

The base 8K version does not auto-enable interrupts, interrupt-using
options in 16K+ builds (extra.ipl loaded) typically RENAME +IRQ !IRQ
to enable interrupts all the time. "+IRQ" $DEFADR 3 SUB 20511 PUT
at the console does the same thing if you want interrupts in 8K.

Configured for TTY Console in slot 11, PTR in slot 12, PTP in slot 13.
Change locations 355, 357, 356 and restart to change configuration.

----------------------------------------------------------------------

Extra definitions in the extra.ipl file...

$EQUAL - pops string and compares to next, if equal pushes 1 else 0
From To $SLICE - pushes a substring of a string
$TRIM - removes leading and trailing spaces from string
n PDEF - pops stack and prints definition there if it can
EXPLAIN - lists definition, use at console only
from to ABSOUT - outputs range on stack to mass-storage in ABS format,
 does not terminate to permit multiple ranges to be saved in one file
PTZERO - writes 20 zeros to papertape
from to DUMP - dumps range in binary and text format
MARKCON n - compiles a context marker with value n (named ~)
GLOBAL - compiles a global marker (named ~~)
SETCON n - makes defs following the matching ~ marker visible
SETCON 0 - hides all contexts
FORGET [name] - forgets last thing or everything after specified def
ERASE - uses @LLP to erase the last package that was loaded (changed for 1.6)
"defname" n STASH - decompiles defname to block n, ends with CONSOLE
n FETCH - pops stack and loads definition from that block
HIDEDUPS name - hides duplicate definitions by naming " "
RENAME name newname - renames a definition
DELETE name - "deletes" definition by naming " "
WHEREIS defname - prints word address and span of definition
UNDELETE - finds and allows restoring of deleted definitions

----------------------------------------------------------------------

Octapus support...

OE - run OCTAPUS-E
OE? - display control keys and run octapus
SYSALL - writes hpiplos and octapus to MS output in abs format

Oct34/Oct70.ipl require the ABSOUT, PTZERO definitions from
the extra.ipl file, oct14.ipl includes those definitions on-board.

SYSALL writes an 8 byte leader before the ABS, the number is hard-coded
in the first word of the definition. If a different number of zeros or
no leader at all is desired, do "SYSALL" $DEFADR 2 ADD PNUM to get the
address to change then [address] [number of zeros] PUT to change.

----------------------------------------------------------------------

Contained in the create.ipl file...

CREATE DefName [/L|/K] - creates a low-level assembly definition
If /L or /LARGE specified uses all available block memory for symbols
If /K or /KEEP specified keeps the previous symbols

"Mostly" HPASM compatible.. no labels or math in EQU except for
the form *+/-something. Takes care of adding the header, end your
code with END to assemble a JMP ZNXT,I instruction. If you need
to exit early (say if data at the end) use JMP ZNXT,I or JMP END.
All constants interpreted as octal regardless of if xxxB specified
or not, exceptions are DEC and the number for ASC which are decimal.
Multiple OCT/DEC values are not supported. Supports extended
multi-word instructions as op-codes only, add the parameters
seperately using OCT or DEF. Several popular z.p. locations are
pre-defined, view create.ipl towards the end. Other locations can
be defined using EQU, get values from the hpiplos1.lst file.
Note.. z.p. locations are generally safe and won't move but
locations outside of z.p. often change with every new version.
Make sure comments are spaced well away from instructions to
avoid parsing as data. Forward references are allowed, unresolved
references are fixed after parsing END.

A smaller version for smaller builds is in smallcre.ipl, no /L option.

PRESET - turns off interrupts, does CLC/STF for all channels from 6-57,
clears overflow flag. Similar to what the real Preset switch does, and
avoids binary load failures caused by dangling interrupts from TBG etc.

----------------------------------------------------------------------

Contained in the debug.ipl file... (requires CREATE)

DEBUG - turns on the debugger, press C to turn it off.
S runs the "instruction" being displayed, D dumps the stack,
T dumps the return stack, E examines memory, R displays registers
(default after entry), ? displays a brief help screen.

----------------------------------------------------------------------

In their own IPL files...

CFGE - adds config-startup at 70 which sets TTY slot to SR bits 0-5, sets BACI
   slot to SR bits 6-11, if SR bit 15 set disables autostarting (SR=177777).
CONFIG - allows setting slots and terminal configuration (req. BACI)
   Includes !SDC to set default console to BACI if bit 12 of location 72 set.
   If running via CFGE entry at 70, sets BACI console if SR bit 12 is set.
CONFIG (smallconfig.ipl) - allows setting only TBG TTY PTR PTP 790x slots
VERSION - allows the sign-on string to be changed
from to MKLDR - encodes an area of memory and writes IPL to MS out
"NAME" from to MKCLDR - encodes memory to MS out in CREATE format
"NAME" MKWORD - permits defining a group of variables, subroutines and
   a main word in a way that appears as one word in the dictionary. MKWORD
   defines a word with the specified name and leaves name string on the X
   stack, when ENDWORD is used it modifies the specified word so that it
   calls the last word defined and modifies the pointers so that it appears
   as a single word. Such compound words cannot be EXPLAINed, only removed.
!NOLF (in nolf.ipl) - inserts a console input driver which ignores linefeeds,
   useful for terminals which emit CRLF when Enter pressed. If removing do
   2 RUN immediately to avoid locking up the system when other things loaded.
+CAPS -CAPS (in capslock.ipl) - enables/disables a console input driver which
   converts all characters to upper-case letters (lower-case still displayed).
   If removing either -CAPS or do 2 RUN afterwards to avoid lockup.

----------------------------------------------------------------------

BACI support in the baci.ipl file... (requires CREATE)

!BACI - initializes BACI interface (autostarts)
MSBACI - sets mass-storage IO to BACI interface
>BACI - sets print output to go to BACI interface
<BACI - sets input to come from BACI interface
BACICON - switches console to BACI interface
TTYCON - switches console to TTY interface

Location 271 holds the default BACI slot, patched when !BACI runs.
Default is slot 22.

----------------------------------------------------------------------

TBG support in the tbg.ipl file... (requires CREATE)

+IRQ renamed to !IRQ to autostart-enable interrupts
+TBG - turns the time-base generator on
-TBG - turns the tbg off
>TBG - pops stack and loads value into the tbg
       1 for 1ms, 2 for 10ms, 3 for 100ms etc
TBGZERO - zeros the tbg counter (locations 473 low, 474 high)
!100MS - zeros/starts the TBG with 100ms count (autostarts)
T>>S - pushes timer low, then pushes timer high
TIME>>S - pushes 10ths, seconds, minutes then hours
PTIME - prints elapsed time since last reset
>WDT - pops stack and sets watchdog timeout (12 oct = 1 second)
+WDT and -WDT - enable/disable watchdog
!WDA - autostart word that indicates a timeout

Tbg.ipl uses RENAME from extra.ipl to rename +IRQ to !IRQ when
loading to ensure interrupts are enabled.

Location 270 holds the default TBG slot.
Default is slot 10.

----------------------------------------------------------------------

Double-word support in double.ipl file... (CREATE)

n1high n1low n2high n2low DADD pushes high,low of n1 + n2 
high low D2CPL pushes high,low of cmp(high/low)+1 (2's complement)
n1 n2 EMUL - pushes high,low of n1(16)*n2(16)
n1high n1low n2 EDIV - pushes result, remainder of n1(32)/n2(16)
n1high n1low n2high n2low DSWAP - makes stack n2high n2low n1high n1low
"decimal" $DVAL - converts decimal number string to high,low on stack
high low $DSTR - converts high,low to decimal number string

Requires HP2100/HP21MX.

----------------------------------------------------------------------

Double-word shifts/rotates in the bigshift.ipl file... (CREATE)

These pop a double word and push a double word result.

DASL - double arithmetic shift left  (0-->bit 0, bit 31 remains)
DASR - double arithmetic shift right (bit 31-->bit 30)
DLSL - double logical shift left (0-->bit 0)
DLSR - double logical shift right (0-->bit 31)
DROL - double rotate left
DROR - double rotate right

Requires HP2100/HP21MX.

----------------------------------------------------------------------

DMS support in the dms.ipl file... (requires CREATE and 64KW+ HP21MX)

!DMS - initialises DMS (autostarts)
-DMS - disables DMS
SDMA - sets DCPC ports A,B (DMA) to system map
UDMA - sets DMA to user map
adr UJUMP - jumps to address in user map
adr SJUMP - jumps to address in system map
page dmspage SPAGE - sets page (0-37) to dmspage (0-???)
srcadr destadr wordcnt C>ACOPY - copies current map to alternate map
srcadr destadr wordcnt A>CCOPY - copies alternate map to current map
n USPACE - sets user space to 32KW block n (1st user block = 0)
DMSTATUS - pushes value of DMS status register
ABSLOAD - uses DMS to load ABS file from MS input into alternate map
addr MSUSER - redirects MS in/out to the alternate map
UPTR - psuedo-variable containing MSUSER pointer
GOUSER - copies hpiplos to alt, turns off irq/auto and UJUMPs to 2
GOSYSTEM - copies hpiplos to alt, turns on auto and SJUMPs to 2
ALTSAVE - copies hpiplos to alt and adds swap/run code to 77000

----------------------------------------------------------------------

Magnetic Tape support in the magtape.ipl file...
(requires CREATE and DMS)

MTINIT - initializes mag-tape drive
MTREAD - pops length then address and performs DMA read from mag-tape
MTWRITE - pops length then address and performs DMA write to mag-tape
(example 24000 400 MTWRITE to write 400 words from mem at 24000)
(use UDMA first and SDMA after to write data from alt mem)
GAP - writes inter-record gap
GAPMARK - writes gap and file mark to separate tape files
FS1R - forward space one record
BS1R - back space one record
FS1F - forward space one file
BS1F - back space one file
RWLP - rewind to load point
RWOL - rewind to off-line
MTSTATUS - pushes mag-tape status word
MTWAIT - waits for MT to finish last command
?MTERROR - prints MT error if error condition
MTSCAN - lists mag-tape contents
MTGEN - writes system to magtape

Configured for 13181 controller in slots 14/15.

----------------------------------------------------------------------

Extra magtape support in the mtextra.ipl file... (requires MAGTAPE)

These words define something like a Tape Operating System that
allows magtape files to have descriptive names and records the
lengths and load addresses (if binary) to allow easy loading.
MTGEN and the HP-IPL/OS base was modified to place the version
up front for easy retrieval, the data file format uses a header
record based on the first few words of the system file format
to permit the same code to display both HP-IPL/OS versions and
data filenames. The "ID" record format is... (# in octal u.o.n.)

  0 - 15400 (magic # 1)
  1 - load address or 0 if text
  2 - length of data record(s)
  3 - number of data record(s), usually 1
  4 - 6412 (magic # 2)
  5 to 16 - 20(dec) character "filename"
  17 - not used

The data record(s) follow the ID record after a gap. Presently
only one data record is used (for 2 records total) but you can
write functions that process multiple data records if needed.

IDREC - 16(dec) word array variable for storing ID records.
MTDIR - displays magtape "directory", listing versions of HP-IPL/OS
  builds and filenames of 2-record "files", or number of records
  if either magic number is missing from the first record.
DLTF - deletes last tape file after confirming.
file# MTSEEK - skip to the specified file.
file# MTBOOT - boots a HP-IPL/OS system magtape file.
"Filename" startadr recordlen #records MMTID - make ID record and gap.
"Filename" startadr endadr MTSAVE - save an area of memory to magtape.
file# MTLOAD - "loads" the specified file, if system then boots, if
  binary loads into memory, if text copies to the alternate map then
  redirects into the console to load IPL files.
"Filename" ByteLen MS2MT - copies MS input to magtape file.
  Note.. length in bytes must be exact!
file# MT2MS - copies magtape file to MS output
"Filename" block# #words B2MT - write block memory to magtape file.
file# block# MT2B - read magtape file into block(s)
file# MTSHOW - read magtape file into alt. map and display as text.
"DefName" D2MT - writes high-level definition to magtape file.

In the mtbackup.ipl file...

MTBACKUP - saves magtape to simh-compatible MT file attached to MS out
MTRESTORE - restores or adds MT file attached to MS in to magtape
Note... recently I found that MTBACKUP no longer functioned under
sim (and likely never worked on real hardware), did scary stuff to
it to make work again.. beware. Also newer simh hp2100 sims write
large gaps of 376 377 377 377 sequences between records, MTRESTORE
was not programmed to handle these. MTRESTORE was designed to input
the output of MTBACKUP, or the output of the MAKE_MT.BAS utility.

----------------------------------------------------------------------

12555 XY Display support in the n_rocks.ipl file... (requires CREATE)

address length +XYDISPLAY - show a display list
-XYDISPLAY - turn off the display
DLRESET - zero the display list to start a new graphic.
  Known bug - when the display list is short (or zero) the
  clock will stop and the processor slows. After longer than
  10 or so entries things smooth out.
@DLBASE - variable containing the address of the display list
@DLP - variable containing the (relative) display list pointer,
  normally indicates display list length
@DLD - variable containing default intensity (default=2)
@DLI - variable containing current intensity (default=2)
  Intensity = how many DL entries per plotted pixel. With M-series
  machines this can (probably) be set to 1. The 12555 is not fully
  compatible with E/F series machines, set @DLD and @DLI to 2.
@BLANK - indicates if XY display has blanking, set to 0 if not
@X and @Y - variables for X and Y coordinates
n PEN - set intensity to n
PEN-  - set intensity to 0 (no plot, useful for moving the pen)
PEN+  - set intensity to default
x y PLOT - plot pixel x,y and set the @X/@Y variables.
x y UNPLOT - remove (all) pixel(s) x,y
"dir" n DRAW - draw a line from the current @X/@Y n pixels long.
  "dir" can be "N" "S" "E" "W" "NE" "SE" "NW" or "SW". Does not
  plot the 1st pixel to avoid double-plotting junctions, use PLOT
  to start it off. Example 30 30 PLOT "E" 20 DRAW "N" 20 DRAW etc.
@FROM and @TO - variables specifying from-to addresses for XYMOVE
x y XYMOVE - add x and y to memory from @FROM to @TO (caution!)
PEN++ - performs PEN+ and plots current @X/@Y (used by $XYPRINT)
@FSIZE - controls $XYPRINT "font" size, specifies base size of
  segments. Each letter is @FSIZE * 2 wide/tall with @FSIZE
  pixels to the left and below.
"STRING" $XYPRINT - prints text to the XY display at @X/@Y
XYHOME - positions @X/@Y to print text starting at the top left
XYCRLF - moves to the next line
x y seg OCTAGON - draws an octagon, seg specifies segment size
N_ROCKS - an XY display demo, pops stack and loops that many times

Configured for XY display in slot 20.

----------------------------------------------------------------------

HPIB support in the hpib.ipl file...

CBUS - SENDS A CONTROL WORD TO THE 59310B INTERFACE
?BUS - GETS A STATUS WORD FROM THE 59310B INTERFACE
>BUS - TRANSMITS A BYTE OVER THE HPIB BUS
<BUS - RECEIVES A BYTE OVER THE HPIB BUS
*BUS - CLEARS THE BUS VIA HPIB IFC SIGNAL
+REN - SETS REMOTE ENABLE FOR TRANSMISSIONS
-REN - CLEARS REMOTE ENABLE FOR TRANSMISSIONS
+ATN - SETS ATTENTION FOR TRANSMISSIONS
-ATN - CLEARS ATTENTION FOR TRANSMISSIONS
!HPIB - Autostart word that sets HPIB slot

Configured for slot 17, use CONFIG to change.
(same as default 7900 upper slot, if using both change one or the other)

----------------------------------------------------------------------

Basic floating point support in the float.ipl file...

FIX   pops 2-word FP, pushes 1-word int
FLT   pops 1-word int, pushes 2-word FP
FP+   2 FLT 3 FLT FP+ FIX PNUM prints 5
FP-   5 FLT 3 FLT FP- FIX PNUM prints 2
FP*   2 FLT 3 FLT FP* FIX PNUM prints 6
FP/   6 FLT 2 FLT FP/ FIX PNUM prints 3

Extra floating point support in the floatext.ipl file...

high low DFLT - convert double signed int to float (fp)
fp DFIX - convert float to double signed int (high low)
fp n PWR10 - raises fp to n power of 10
"string" $>FP - parses string and pushes fp
fp FP>$ - pushes string with fp value
fp FSGN - pushes -1, 0 or 1 for fp sign/zero
fp FSQR - pushes fp square root

Example... calculate 4.56/1.23 + 2.34 and print results...
 "4.56" $>FP "1.23" $>FP FP/ "2.34" $>FP FP+ FP>$ $PRINT
 6.04732 (a calculator gives result as 6.04731707317073...)

----------------------------------------------------------------------

Terminal support

The screen.ipl file provides basic VT100/ANSI support words...

ESC - outputs ascii 27 followed by [ to start esc sequences
row column POS - positions cursor for next print
CLS - clear the screen
forground background COLOR - sets print/cls color
(some terms don't allow setting background and parm is ignored)
-COLOR - go back to normal screen colors

Requires double.ipl, POS uses the $DSTR to convert to decimal.

The hpscreen.ipl version supports selecting HP or ANSI terminal...
TTYPE - variable w/ terminal type, 0 for HP (default), 1 for ANSI
TERMINAL - toggles terminal type (color not supported in HP mode)

For HP2645 graphics terminals the hp2645.ipl file should be loaded
and *GT run to select a normal text display.

----------------------------------------------------------------------

Printer support in the print.ipl file...

!LPT  - patches slot to location 277, container for subroutines
CKLPT - reads LPT device and pushes status (0 means not available)
MSLPT - sets MS out to LPT device (CONSOLE to undirect)
+PE   - echos all console I/O to printer
-PE   - disables printer echo
byte >LPT - sends a single byte to the printer
"string" $LPT - sends a string to the printer
NLPT - sends a newline (CRLF) to the printer

Defaults to an interface in slot 20, to change use CONFIG (or change
location 277) then 2 RUN to restart.

This is experimental, it works with the SimH HP2100 LPT device but may
not work with all hardware. The +PE word does a call to CKPRN to check
status and does nothing if 0 is returned, to disable this check the
first 3 instructions after "WA" should be cleared...

  "+PE" $DEFADR PNUM (prints an address)
  address+1 0 PUT address+2 0 PUT address+3 0 PUT

...for example if 53200 printed do 53201 0 PUT 53202 0 PUT 53203 0 PUT
(be very careful! a typo can corrupt the system in memory)

As with any console stream driver disable (-PE or 2 RUN) before removing.
If mixing with other console drivers enable/disable them in nested order.

----------------------------------------------------------------------

Alternate-Memory utilities

altutil.ipl contains...
ZAM - Zero Alternate Memory (stand-alone version)
HLT - halts the computer for attaching, swapping, etc
ALTRUN - runs system in alt mem (ALTSAVE must have been run first)
RUNABS - Load and run an ABS attached to MS input (PTR)
PTHEADER - Writes 8 zeros to MS output (PTP) (used by ALTABS)
from to AAOUT - Writes alt mem to MS out in ABS format
ALTABS - Saves alt mem to ABS file attached to MS out
from to ALTDUMP - Dumps alt mem to terminal
CLRHALT - Saves system to alt mem, halts with empty system
ALTHALT - Swaps system with system in alt mem then halts

fcam.ipl contains... (req's altutil.ipl)
_FLG _XFR _LNZ _CNT - variables used by these words
_MCZ - variable containing max consecutive zeros for FCAM
FCAM - find Code in Alt Mem
address value APUT - puts value into altmem
address AGET - pushes value from altmem
?MSOUT - prints current MS out redirection - default MS out = PTP
_PAD - variable containing # of pad words for AM2ABS
_CBD - variable containing code boundary for AM2ABS
_TRA - variable containing transition address between pad/boundary
AM2ABS - saves contents of altmem to ABS file attached to MS out
F2ABS - wrapper for AM2ABS that loads file into altmem then runs AM2ABS

----------------------------------------------------------------------

Utilities for encoding/decoding text binaries...

These can be useful for saving binary code from real hardware when
there is no PTP interface to send it out the usual way, also can be
useful for loading binaries when the PTR emulator requires burning
eproms etc by pasting the encoded binary to the console with
suitable delay settings (HyperTerminal etc).

CONGEN in congen.ipl - does a 'sysall' to console as text
L2ABS in log2abs.ipl - converts text-binary on MS in to ABS binary on MS out
LDENC in ldenc.ipl - loads/runs text-binary from MS in
conalt.ipl contains...
startadr endadr ALTENC - encodes alternate memory as text
CONGEN - same as stand-alone version but using ALTSAVE ALTENC
ALTGEN - encodes specified range in alt-mem as text
CONALT - "loads" text-binary pasted to console into alt-mem.
bkfile.ipl contains... (requires conalt.ipl)
"FILE" BKFILE - encodes a file as text
"FILE" REFILE - restores encoded text to a file

----------------------------------------------------------------------

Disk driver support in the disk.ipl file...

word >IDE           Send Command to interface
<IDE                Push Disk Status
Address W-1K        Writes 1KW from Address to selected disk block
Address R-1K        Reads 1KW from selected disk block to Address
blockH blockL SBLA  Sets Block Address
LDFB                Loads system from current block address
DBOOT               Boots default system from block 8
DGEN                Save system to block 8
drivenum CHDRV      Change drive number (location 250 oct)

Disk.ipl only provides the disk driver code interface, the actual
driver code is located in 7900.ipl, 7906.ipl or ide.ipl and provide...
?DRV - print drive information
!xxxx - autostart word containing actual driver (xxxx=7900 7906 or IDE)
7900.ipl and 7906.ipl also provide 0/1 CHPL to change platters
(0 for removeable, 1 for fixed)
For the 7900, drives 0-3 are removable and 4-7 are fixed.
For the 7906, drives 0-7 are removable and 10-17 (oct) are fixed. 

Disk.ipl doesn't care where the driver.ipl is loaded, however all
of our current disk drivers have to be loaded after disk.ipl.

Default 7900 slots are 16/17
Default 7906 slot is 16
Default IDE slot is 23

CONFIG can be used to change slot assignments.

A 7900/7906 boot extension is not required to use the disk, just
to boot from it. If booting from somewhere else just enter DBOOT
to "boot" whatever system was saved to disk by DGEN.

To use the 7900 boot extension...
 load 7900bext.abs
 clear SR
 put the lower drive slot in SR bits 6-11, assumes slot 16 if zero
 set SR bit 15 to write to the fixed platter instead of removable
 set SR bits 0-1 to the drive to write the boot extension to
 run from 2012 with the drive ready.

When booting, the 7900 boot extension patches the controller slots to
SR bits 6-11 (set by the boot-rom), SR bits 3-4 determine drive to load
from (not set by the boot-rom). Set SR bit 5 to halt for config. Hard-coded
for either fixed or removable platter, block 0 offset 12 octal must be
000020 for removable or 001020 for fixed. Or rerun 7900bext.out.

To use the 7906 boot extension...
 load 7906bext.abs
 clear SR
 put the drive slot in SR bits 6-11, assumes slot 16 if zero
 set SR bit 15 to write to the fixed platter instead of removable
 run from 2012 with the drive ready.

When booting, the 7906 boot extension patches the controller slot to
SR bits 6-11 (set by the boot-rom). Set SR bit 5 to halt for config.
Hard-coded for either fixed or removable platter, block 0 offset 12 octal
must be 000420 for removable or 001420 for fixed. Or rerun 7906bext.abs.
The 7906 boot extension is limited to drive 0 only.

To actually boot anything, DGEN must be run to write a boot system
to disk, all the boot extension does is load and run it.

----------------------------------------------------------------------

XDOS operating system in the xdos.ipl file...
(requires dms.ipl, disk.ipl, double.ipl and a disk driver)

XDOS implements an SFS-compatible disk layout using fixed 32KW file slots.
Somewhat wasteful of disk space but this greatly simplifies lots of things.
Files can be either a system binary or a general purpose file which can be
text, ipl code or just data for another program. Disks are arranged as
up to 64 volumes (aka directories) of up to 64 files each, disk space
permitting. The volume functions allow volumes to be created, renamed,
deleted and listed to the screen. XSAVE saves the current system to a
binary file, AM2F saves alternate memory to a regular file. XLOAD detects
whether the file is binary or not, system binaries are loaded and run,
text is redirected into the console to load (hopefully) ipl files.
Files can be renamed, deleted, displayed as text. XDIR lists filenames.
Additional utilities can copy files to and from MS, typically papertape,
"format" the disk, and recover volumes and files if inadvertantly deleted
or if upgrading from our old "TDOS" directory-less system.

Volume functions...
WKBUF         constant defining work buffer
XCV           variable defining current volume number for XDOS
$VOL          pushes string containing current volume name
MKVOL         makes a new volume.. "vol" MKVOL
FindEntry     subroutine that finds an entry in vol/dir table
16Pad         subroutine that pads string to 16 characters
ChkSFS        subroutine that detects buffered SFS dirs or modified files
DELVOL        deletes a volume.. "vol" DELVOL (confirms)
RENVOL        renames a volume.. "vol" "newname" RENVOL
CHVOL         changes XCV to new current volume.. "vol" CHVOL
LSVOL         lists volume index
File functions... (operate on current volume defined by XCV)
VolInfo       5 word array containing current volume specs (after GetVol)
DirInfo       6 word array containing directory specs (after GetFile)
GetVol        reads volume index and updates VolInfo
GetFile       finds existing file and updates DirInfo, returns start block
PutFile       creates new dir entry from DirInfo, returns start block
ZAM           zero alternate memory, useful for importing/creating files
AM2F          copy alt memory to a new file.. "file" bytes AM2F
F2AM          copy file to alt memory.. "file" F2AM
XSAVE         save current system to a new file (size 62KB).. "file" XSAVE
XLOAD         load an ipl or system binary file.. "file" XLOAD
XSHOW         show file on screen, if LA is not 0 (text) then hexdumps file
XDIR          lists current volume name and the files it contains
XREN          renames a file.. "file" "newname" XREN
XDEL          deletes a file.. "file" XDEL (confirms)

Additional words in the xutils.ipl file...

"file" bytelen MS2F copies MS input to a file (not redirection)
"file" F2MS         copies a file to MS output (not redirection)
"file" ABS2F        loads ABS from MS input, patches, writes to file
VRECOVER   adds volume entries if deleted but still point to a directory
XRECOVER   adds file entries if deleted but point to non-zero data
XINIT      SFS/XDOS formatter, prompts for # vols and # files in last volume

----------------------------------------------------------------------

SFS file-access system in the sfs.ipl file...
(requires xdos.ipl unless sub-words uncommented)

SFS stands for Simple File System, XDOS implements the SFS disk layout,
while the sfs.ipl provides words for accessing the files in ways XDOS
cannot. SFS provides words that allow the programmer to open up to 4 files
at once, redirect files to and from the MS stream, seek to any byte position
in a file, and reopen files to their last access point. The SFS utilities
package provides words for saving a word definitions to a file, file copy,
file duplication and file move.

Command words...

"volname" buffer drive DIRECTORY - (re)loads a directory block for a buffer
"filename" buffer OPEN - loads a file into a buffer for read/write access
"filename" buffer REOPEN - opens a file into a buffer at last access point
buffer <FILE - redirects a buffered file to MS input for reading
buffer >FILE - redirects MS output to a buffered file for writing
buffer bytepos SEEK - sets file pointer in a buffer to specified byte
buffer CLOSE - closes specified buffer (reloading dir block)
"filename" buffer CNF - creates new file in specified buffer
"filename" buffer DEL - deletes a file in specified buffer
srcbuf destbuf BCOPY - copies buffer to buffer, both must be open
buffer RELEASE - releases specified buffer (marks buffer as unused)
-SFS - turns off SFS, abandoning all buffered directories and files
?SFS - shows status of SFS buffers

SFS is based on buffer states, DIRECTORY can only be used if the buffer is
not being used or contains a previous directory. OPEN/REOPEN/CNF/DEL can only
be used if a directory is buffered, <FILE >FILE and CLOSE can only be used
if a file is open, afterwards the directory is reloaded. RELEASE immediately
abandons the specified buffer regardless of state.

Note - don't perform direct manipulation of disk structures unless all related
buffers are released first. Otherwise SFS will have stale data in memory.
For safety, SFS programs should RELEASE buffers when done with them.
Always make sure all buffers are released (-SFS) before saving a build to
make sure it doesn't start up with open files (generally not good).

Visible variables...

CWA - Control Word Array containing control words for each buffer
FPA - File Pointer Array containing byte pointers for buffered files
FSA - File Size Array containing byte file sizes for buffered files
FCA - File Control Array containing FCW's for buffered files
LAA - Load Address Array containing LA's for buffered files
RAA - Run Address Array containing RA's for buffered files
FNA - File Number Array containing file numbers of buffered files
DNA - Drive Number Array containing drive #'s of buffered files or dirs
VNA - Volume Number Array containing volume #'s of buffered files or dirs
FSS - File System Status variable containing status of last operation (0=ok)
NDEA - Number of Directory Entries Array (from block 6)
DBLA - Directory Block Low Array (from block 6)
DBHA - Directory Block High Array (from block 6)
FSLA - File Space Low Array (from block 6)
FSHA - File Space High Array (from block 6)

CWA, FPA, FSA and FSS are actually located in zero page, the high level
"variables" are constants that push zp addresses, ie FPA INC GET pushes
file ptr for buffer 1.
 
CWA bits...
(1) Bit 0 - if 1 then a file is loaded into buffer (busy)
(2) Bit 1 - if 1 then a directory block is loaded into buffer
(4) Bit 2 - if 1 then a volume index block is loaded into the buffer (when???)
(8) Bit 3 - if 1 then buffer is dirty (file changed, needs writing upon close)

FSS values...

177777 - programming error (incorrect parms)
171717 - non-existent buffer specified (DIRECTORY)
000010 - file not open error
000011 - DMS not enabled error
000012 - buffer busy error
000013 - dir not loaded error
000014 - file already open in another buffer error
000015 - file already exists error
000016 - invalid directory error
004XXX - device error, XXX = error code from <IDE
000601 - max file size reached (eof for reads)
000602 - directory full
000603 - volume index full (not implemented)
000001 - volume not found
000002 - file not found
000003 - write protect error (not implemented)

Additional SFS words in the sfsutils.ipl file...

"DefName" D2F - writes def to file of same name in current volume
"file" destdrv "destvol" FCOPY - copies a file to another volume
"file" destdrv "destvol" FMOVE - moves a file to another volume
"file" "newfile" FDUP - duplicates a file in current volume

Example SFS program... (with a bit of XDOS to get "current" volume)

OCTAL DEFINE LIST
;usage "File" LIST - lists file to screen using buffer 1
$LEN IFNZ   ;if string specified
 $VOL #1 DRV GET DIRECTORY ;load directory for current volume
 #1 OPEN FSS GET IFZ ;try to open, if no error...
  MS_SAVE ;save MS vectors
  #1 <FILE ;redirect MS input to come from buffered file
  DO ;while there's text to display
   MSBIN DUP ;get a byte, dup for while
   DUP IFZ DROP ELSE PCHR ENDIF ;if zero discard else print byte
  WHILE ;non-zero returned
  MS_RESTORE ;restore previous MS vectors
  ;CLOSE not needed since nothing was written
 ENDIF
 #1 RELEASE ;stop using buffer
ENDIF
END

----------------------------------------------------------------------

SFS Applications

The edit.ipl file contains a crude line-by-line file editor...

"File" FOPEN - open file, create if not found
FCLOSE - close file (do 0 RELEASE to abandon)
PCL - print current line
NL PL - next line, previous line
BF EF - beginning of file, end of file
[-]count MLP - move line pointer
DLINE - delete current line
CHOP - delete current line and rest of file
APPEND - append text at end of file
INSERT - insert lines at current line
LS - list 10 lines from current line
LI - list 10 lines and increment current line
?EDIT - prints file status and a summary of edit commands

SFS is handy for loading binary overlays into alternate memory, which
can be used for operating vintage software. Essentially the ABS file is
copied as-is to a disk file using MS2F then the following commands used...
(for buffer 1, assuming the file is in the "current" volume)

  #1 DRV GET $VOL DIRECTORY
  #1 "FILENAME.ABS" OPEN
  MS_SAVE #1 <FILE ABSLOAD #1 RELEASE MS_RESTORE

...altmem now contains the previous contents plus the ABS binary.

The sfslib.ipl contains a library system which can be used to store multiple
words or groups of words in a single file, individual segments can be loaded
into the dictionary, or if suitably written loaded, executed then removed
afterwards (aka run-and-forget)...

LBUF - a variable containing the buffer used by the library, default 3.
"Volume" "File" SETLIB - sets/opens/creates library file on current drive
LIB - opens library defined by SETLIB, creates if it doesn't exist
"Name" LFORGET - removes "Name" and everything after it
LDIR - lists the name of the library file and library segment names
LCLOSE - closes the library file, saving changes to disk
"Name" R - runs "Name" from buffered library then forgets it
"Name" L - loads "Name" from buffered library into dictionary
"Name" D>L - saves definition to buffered library
"NAME" A>L - copies IPL text from alternate memory to the library
"NAME" L>A - copies a library "file" chunk to alternate memory
"NAME" MS>L - copies MS input to the library (terminates when 0 received)

Note - Library IPL files must end with LIBEND to run and forget.
No conversion is performed by MS>L etc, if importing existing
run-and-forget-compatible packages change final CONSOLE to LIBEND.

Library file format...
;;;FILE:SegmentName:
[IPL code or other text lines]
LIBEND
[additional ;;;FILE -- LIBEND segments]

Maximum line length for IPL code is 76 characters + CRLF (78 characters
for non-IPL text when using A>L and L>A). Previous versions of the library
used a 128 byte to mark the end of a library file. This version has no
terminator and instead uses the 0 returned by SFS when reading past EOF.
Maximum library size is 177774 bytes, if that size is displayed by LDIR
then the last segment is probably broken, "Name" LFORGET to remove.

Before the library can be used enter a command like $VOL "LIBRARY" SETLIB
to define and create an empty library file. The setting is saved with the
build, but be sure to -SFS to shut down SFS before using XSAVE or DGEN.
When the build is reloaded enter LIB to open the default library.

The library save words automatically form the ;;;FILE tag from the specified
name string. Single self-contained high-level words can be added to an open
library using "Name" D>L with no further effort, however every word/variable
used by the target word must be in the dictionary. Note... the library
contents are immediately available, but nothing is actually written to disk
until LCLOSE is used. If an error occurs enter -SFS to abandon the changes.

If compatibility with L>A is not important and the package is for load-only,
existing IPL disk files ending with CONSOLE can be added to the library as-is
by copying to alternate memory ("File" F2AM) then using "Name.IPL" A>L to
copy to an open library. The .IPL is just to remind that it's a load-only
package, don't try to run it with R. It's better to replace CONSOLE with
LIBEND (on a line by itself, no leading spaces) to avoid possible bugs.
To save space in the library remove comments and unnecessary spaces.

Run-and-forget library apps must be composed so that the library name is
the same as the name of the first definition, which must be the word that
runs the app, and must end with LIBEND to trigger processing. There must
not be an immediate CONSOLE or the load will halt without running, leaving
the app in the dictionary.

Generalized run-and-forget segment...
OCTAL DEFINE Name  ;Name = library segment name
"MAIN" $DEFADR DUP IFZ DROP ELSE EXECUTE ENDIF END
VARIABLE VarName   ;any variables required by the app
DEFINE SubWord
...word required by the app but might not be in the dictionary
END
...any other words needed by the app
DEFINE MAIN  ;named to match $DEFADR string
...main app code here
END
LIBEND

Existing run-and-forget-compatible apps like fed.ipl are already in this
format and only require changing the ending CONSOLE to LIBEND, but for best
results the comments should be removed to take up roughly half the space.
Library segments can be composed with FED/AEDIT and saved to a file, then
debugged using XLOAD (LIBEND is equivalent to CONSOLE), once functional
add to the library using F2AM then A>L. Or just "Name" A>L if still in
alt mem (like if merely changing CONSOLE to LIBEND). Library code can be
composed using a PC editor (CRLF line ends), attaching to PTR and doing
[MSPAPER if MS not paper] "File" MS>L to copy to an open library.

See the comments in sfslib.ipl for more information.

----------------------------------------------------------------------

Full-screen "array" editor in the fed.ipl and fedutil.ipl files...
Requires DMS, [hp]screen.ipl, disk load/save requires XDOS
The LDTXT utility also requires SFS.

AEDIT is an alternate memory editor capable of composing text and IPL code.
To keep things simple each line is 78 characters long plus a CRLF, accessed
23 lines at a time. This limits the maximum file size to 782 lines (34 pages)
but this is sufficient for most applications. The data must be in array-format
to be editable, utilities are provided for converting regular text to and from
the array representation. AEDIT resumes editing array data in alt-memory where
last exited, or from the beginning if no array data present. Once an IPL file
has been created it can be loaded into the dictionary using: 2 MSUSER <MS
The IPL file should include a CONSOLE to terminate the load and avoid an
error. If fedutils.ipl is loaded ALOAD can be used instead to load IPL code.
If XDOS is present words are provided for loading and saving files, or a
wrapper word (FED) can be used to prompt for the load and save filenames.
FED is the first word so compatible with run-and-forget techniques such as
DMENU (dmenu.ipl) or the SFS library.

The fed.ipl file provides...
ZAM - zero alt mem to start a new text file (not defined if already exists)
CPAG - variable containing page currently being edited
MPAG - variable containing the last page containing data (0-41 octal)
STMPAG - scans alt mem and sets MPAG (for custom edit save words)
AEDIT - runs the editor to edit data in alt mem

The following are defined only if XDOS' AM2F is present...
FED - chains to FEDIT
"FILE" LDFILE - loads an array file into alt mem
"FILE" SVFILE - saves array data in alt mem to a file
FEDIT (or FED) - prompts for filename, runs AEDIT, prompts for save filename

To start a new edit enter ZAM AEDIT to make sure alt mem is clear.
After editing enter "FILENAME" SVFILE to save it to disk.
Enter "FILENAME" LDFILE AEDIT to load and edit an array-format file.

Or to automate, just enter FED - if a new file press enter at the filename
prompt or enter a filename to save to after editing (doesn't have to exist).
After editing enter a filename to save to, or just enter to use previously
entered filename. If the file exists prompts to delete, press Y otherwise
it prompts for a new filename. To abandon the edit press just enter at the
filename prompt. It tries pretty hard to actually save something, mainly
to avoid losing the file when running-and-forgetting from a disk menu or
library file (after forgetting there's no SVFILE to try again). Note that
if running-and-forgetting fed.ipl has to be named FED (library) or $ FED
(disk menu) to correctly run then forget the FED word.

The fedutil.ipl file provides...
ARLINES - variable containing #lines in alt mem (set by CKARRAY)
CKARRAY - pushes 0, sets ARLINES if edit data in alt mem, else pushes nonzero
STTSP - strip trailing spaces from string (if STFLG variable is non-zero)
MALOAD - loads and converts regular text from MS input (default PTR)
(the last line must be ~TERMINATE~ or it will hang at the end)
MASAVE - strips trailing spaces and outputs to MS output (default PTP)
(adds ~TERMINATE~ at end, enter STFLG 0 PUT to output with spaces intact)
CALOAD - loads regular text pasted to the console (enter ~TERMINATE~ to end)
CALIST - copies edit data from alt mem to screen to be captured or copied
ALOAD - redirects edit data from alt mem into console to load IPL code
"FILE" LDTXT - loads a regular text file for editing by AEDIT (req's SFS)

When running AEDIT control keys are used for all non-text functions...
Cursor - Ctrl-Z down, Ctrl-A left, Ctrl-S right, Ctrl-W up
Pages - Ctrl-C previous page, Ctrl-V next page, Ctrl-P goto page
Ctrl-I inserts an empty line, Ctrl-D deletes line
Ctrl-T toggles insert mode (default overwrite mode)
Ctrl-N selects HP graphics characters
Ctrl-O selects regular text characters
Ctrl-Q saves current page and quits.

Line 24 displays quick-help for these, insert/graphics status and page.
Graphics mode requires a real HP terminal (maybe, not tested yet), in
the file indicates by setting bit 7 of the character.

Files saved to disk are multiples of 80x23 bytes (3460 octal) with unused
space after the last line of text zeroed. The extra zeroes filling the end
of the last page are ignored by XSHOW but will be present if the file is
directly exported using F2MS etc (use MASAVE to export edited files) and will
cause LDTXT to issue an error (but still works, enter -SFS if it happens).
LDTXT should only be used to convert regular text to editable format.

Printing an edited file is easy if you don't mind ~TERMINATE~ being printed
on the last line: "FILENAME" LDFILE (if not loaded) then: MSLPT MASAVE
Enter CONSOLE or MSPAPER to redirect MS output back to papertape.
To print more exactly use the following word...

OCTAL DEFINE APRINT ;"FILE" LDFILE and/or AEDIT then APRINT
CKARRAY IFZ 2 MSUSER MSLPT #1 ARLINES GET +DO
MS$IN STTSP MS$OUT MSCRLF +LOOP MSPAPER ENDIF END

----------------------------------------------------------------------

Disk menu in dmenu.ipl (requires XDOS)
Expanded version in dm2.ipl (requires XDOS,xutils,altutil,fcam,sham)

This package provides a simple (single-column) menu from which binaries and
"run-and-forget" IPL apps can be loaded and run, and text files can be shown.
Not all files in the current volume are listed, rather the first character
of the filename determines the function...

# NAME - a text file, uses XSHOW to view
$ NAME - an IPL app, loads, runs NAME then forgets NAME
@ NAME - a binary file, saves HP-IPL/OS to altmem, loads and runs from 2.
         Halt and run 77000 to return to HP-IPL/OS.

All other files are ignored. In addition to listing files, also displays an
option to exit to the HP-IPL/OS prompt, and to clear alt mem and halt (useful
for entering sim commands, loading/running other code, or simply halting the
system to quit). If nothing has been changed, pressing run (or c in sim)
reruns HP-IPL/OS, otherwise run 77000 to return to HP-IPL/OS.

The main menu code is in DMENU. Also defines !DM to clear the switch register
and automatically run the menu, if this isn't desired rename or forget !DM.

The disk menu and the XDOS ABS2F import word directly support HP BASIC, to
copy a "empty" HP BASIC system to disk attach the configured ABS file to PTR
then enter something like "@ HP BASIC" ABS2F and press Y to add a 77 exit,
this enables returning to HP-IPL/OS by entering BYE. After running and exiting
HP BASIC from disk DMENU displays an option to save the file, prompts for a
file name and whether to patch to auto-run or to preserve listing.

An expanded disk menu is in the dm2.ipl file, it's based on the dmenu.ipl
code but lists files in 2 columns and has several additional menu options.
As written requires altutil.ipl, fcam.ipl and sham.ipl and uses msupatch.ipl
if present. Additional menu options permit loading binaries from PTR, deleting
and renaming files (limited to files displayed on the menu), importing and
exporting binary and text files, and if a binary program is in alternate mem
options are shown for saving the binary to disk, displaying the binary, and
punching the binary to PTP. All PTR/PTP functions prompt to halt, the binary
import option uses ABS2F, the binary export options use AM2ABS/F2ABS (fcam),
the text export option uses F2MS (xutils), the text import option is internal
and assumes the first 0-byte marks the end of the import so does not require
specifying file size, however the file transfer utility or simulator must
supply zero bytes if data is read past the end of the file. This menu
supports the use of a 31KW version of MSU BASIC that has been patched to
skip the initial program clear to permit saving to disk with the program.
If MSU BASIC is present when the save binary option is used, then it prompts
to run MSUPATCH (if present) to change the startup text and other options.
If HP BASIC is present when saving, then it prompts to optionally patch
the saved binary to preserve or auto-start the program.

----------------------------------------------------------------------

Useful locations in octal...

260 - ABFLG, alt boot flag set to 1 if timeout
261 - ABVEC, holds address of alternate boot code (sets ABFLG to 1)
262 - WDENA, non-zero to enable watchdog
263 - WDTMR, increments when +TBG's ISR runs
264 - WDTOV, timout value, JMP ABVEC,I when WDTMR=WDTOV
265 - contains +LOOP increment
266 - address of default input sub, enabled on boot
267 - address of default output sub, enabled on boot
270 - TBG slot - disable IRQ 1st, takes effect when !100MS runs
271 - BACI slot - takes effect when !BACI runs
272 - LPT slot for printer driver in print.ipl
273 - 7900 lower slot or 7906 slot
274 - IDE slot
275 - CS80 slot (not implemented yet)
276 - HPIB slot
277 - available for slot-patching user-written driver
355 - TTY slot             \
356 - PTP (punch) slot      > restart to take effect
357 - PTR (reader) slot    /
300 - buffer pointer for CONIN, TOKEN
301-305 - stack pointers for S,R,X,Y and Z
315 - @TL - token length - length of word found by TOKEN
316 - @TB1 - token buffer 1 - 1st 2 chars of word
317 - @TB2 - token buffer 2 - next 2 chars of word
321 - link to NEXT - JMP 321,I to return to HPIPLOS
323 - link to SPUSH - JSB 323,I to push A to sys stack
324 - link to SPOP - JSB 324,I to pop sys stack to A
325-334 - similar links to push,pop for R,X,Y and Z
337 - link to CHROT(*) - JSB 337,I outputs A to console
340 - link to CRLF - JSB 340,I prints crlf to console
341 - link to CHRIN(*) - JSB 341,I to get char from console to A
(* can be changed to change console to a different device)
342 - link to PTWD - JSB 342,I to print A as 2 characters
343 - link to PBFL - A=w.length, B=addr, JSB 343,I to print "string"
(not a HPIPLOS string, but for printing ML messages)
344 - link to PTRIN - JSB 344,I to get byte from PT to A
345 - link to PTROT - JSB 345,I to write byte in A to PT
346 - ZIN vector - normally points to CHRIN for input
347 - ZOUT vector - normally points to CHROT for output
(all user input/output goes thru ZIN/ZOUT - redirectable to
console or papertape using <>CON, <PTR and >PTP definitions)
350 - ZMINP or MS input vector - default PTR
351 - ZMOUT or MS output vector - default PTP
410 - holds the current number radix for reading, don't write
to since tables and everything needs to be changed to change radix.
435 - holds value for end of input buffer (614)
436 - holds value for start of input buffer (500, note previous
location 477 must contain a space for proper operation)
437 - holds start of system stack (620)
440 - holds end of system stack (777)
441 - holds start of return stack (1000)
442 - holds end of return stack (1177)
443 - holds start of X stack (1200)
444 - holds end of X stack (1377)
445 - holds start of Y stack (1400)
446 - holds end of Y stack (1577)
447 - holds start of Z stack (1600)
450 - holds end of Z stack (1777)
451 - @DIC - holds start of dictionary (4000)
452 - @USR - holds start of user dictionary
453 - @BLK - holds the end of dictionary space+1
454 - @END - holds the end of hpiplos memory
457 - address of warm-boot machine code
460 - prompt copied to 464 on startup (default "? ")
461 - global interrupt enable, set/reset by !IRQ/-IRQ
462 - IENAV - interrupt enable vector, JSB IENAV,I instead of STF 0
463 - contains the address of the sign-on message (starting w/crlf)
464 - current prompt
465 - if non-zero autostarting is enabled
470 - holds address of PIOCS subroutine, A=patchlist, B=new slot#
471 - holds address of CHRIN subroutine
472 - holds address of CHROT subroutine
473 - timer low (tbg option)
474 - timer high (tbg option)
475 - link to interrupt save sub (ISAVE) JSB ISAVE,I to save state
476 - link to interrupt restore sub (IREST) JSB IREST,I to restore


HPIPLOS string format...

addr   highbyte  lowbyte
1200      H        E      "HELLO" is first string on X
1201      L        L
1202      O        ?
1203               5      character length = 5
1204               4      word length for easy copying

Memory map including Octapus... (32K version, numbers in octal)

2-3          Jump to 2000
10-37        contain JSB dummy,I links to avoid interrupt errors
40-77        various irq/etc stuff added by some options
100-147      Reserved for the user
150-177      Temp memory used by some IPL utility words
200-237      SFS zero-page variables
240-257      Vectors for disk driver
260-477      Zero page constants, links, variables
500-615      HP-IPL/OS input buffer
620-777      System stack
1000-1177    Return stack
1200-1377    X stack
1400-1577    Y stack
1600-1777    Z stack
2000-3777    Core HP-IPL/OS code
4000-???     Dictionary
@BLK-@END(*) Up to 16 1K-word memory blocks (typically 2-4 used)
70000-72377  OCTAPUS-E
72400-76377  Room for drivers buffers display lists etc (**)
76400-77037  Alt-mem swap/run buffer/program, entry at 77000
77040-77677  More room for drivers buffers etc
77500-77677  128 words for transient code (boot/load/page/etc)
77700-77777  Actual HP bootrom

(*) the @END location determines last block location, default 67777
@BLK determines 1st block location, set by ALLOCATE
(**) entire range from 72400-77677 can be used for user programs/data but
some HP-IPL/OS operations may overwrite memory over 76400. Memory above
75777 is not preserved by DGEN XSAVE MTGEN etc, and the stock SYSALL word
for making ABS files does not save anything over 72377 (modifying to save
more is trivial - change the '72377' value to something else). For short
machine code sequences the best way to preserve it is encode it into an
autostarting IPL word using the MKLDR or MKCLDR utilities, or simply push
the code to the stack and use a +DO loop to PUT it in memory where needed.

----------------------------------------------------------------------

Thread Details
--------------

HP-IPL/OS uses an indirect-threaded interpreter that implements
a system stack (S), return stack (R) and 3 auxillary stacks
(X Y and Z). Word Address (WA) is the address HP-IPL/OS interprets
to run a word, it contains the Code Address which points to actual
machine code. If pointed to the ENSEC code, the current WA+1 is pushed
to the return stack and the code following it is interpreted until
RTSEC is encountered which pops the return stack, returning execution
to the previous thread which called the "high-level" definition.
Low level definitions generally have the next address in the WA
location (DEF *+1), the machine code executes until an indirect
jump to the NEXT code (JMP ZNXT,I) is executed.

Definition names are encoded to save space, only the first four
characters and the length are significant. Don't use names like
TEMP1 and TEMP2 together, to HP-IPL/OS they are equal.

Low-level definitions are encoded in the dictionary like...

           length   <--- prev. link (or beginning of dictionary)
           first 2 characters of name
           next 2 characters of name
           link to next definition >---.
WA ------> code address >----------.   |
           1st ML instruction <----'   |
           remaining ML instructions   |
           JMP ZNXT,I to return        |
           (optional data)             |
           next length or 0   <--------'

High-level definitions (beginning with ENSEC) are encoded like..
(using the example DEFINE TEST[cr]"HELLO " $PRINT 7 PNUM END)

           4      length   <---- link from prev. definition
           "TE"   first 2 characters
           "ST"   next 2 characters
      .--< link to next definition
WA----|--> address of ENSEC
      |    address of the string push code
      |    4      length in 16-bit words
      |    "HE"
      |    "LL"
      |    "O "
      |    6      character length of the string
      |    address of $PRINT
      |    address of literal push code
      |    7
      |    address of PNUM
      |    address of RTSEC
      `--> next length or 0

----------------------------------------------------------------------

HP-IPL/OS main page: http://www.infionline.net/~wtnewton/oldcomp/hp2100/
Testing and updates page: http://www.infionline.net/~wtnewton/hpiplos.html
Mirror site: http://newton.freehostia.com/net/oldcomp/hp2100/
Terry Newton (wtnewton@infionline.net or wtn90125@yahoo.com)
