Documentation for OPIX 1.00 HyperC Operating Environment and Interpreter/Extended (c) 1992-93 by W. Hofbauer. All rights reserved. InterNet: wulf@cip.physik.uni-stuttgart.de ---------- DISCLAIMER ---------- I (W. Hofbauer) make no warranties, either express or implied, with respect to this documentation or the software it describes, its quality, correctness, performance, or fitness for anything. Running the software is entirely at the users own risk. In no event will I be held responsible for any damage resulting from the use of the software or this documentation. --------- COPYRIGHT --------- This documentation and the software it describes are the intellectual property of the author (me). You're free (and even encouraged) to use and distribute OPIX and this documentation, in its entirety and without modifications, without any royalties as long as you don't make any money out of it. If you want to use OPIX in a commercial or shareware package or bundle it with one, you must ask me for explicit allowance first (I don't intend to make money out of OPIX, but then no one else should). Though this is unlikely to happen (after all, you're an Apple II user!) it is nevertheless explicitly prohibited to use the software for programs promoting military actions, violence, discrimination of social, ethnic, religious, or sexual minorities, or actions in conflict with the human rights. Acknowledgements Writing OPIX wasn't possible without the help of other Apple II enthusiasts. Special thanks go to Gary F. Desrochers and Andy Werner for their programming advice and constructive suggestions. Thanks also to all testers and others not named here. ProDOS, ProDOS 8, Apple ][, Apple ][+, Apple //e, Apple //c, Apple //c+, Apple IIgs, and Apple Pascal are trade marks of Apple Computer, Inc. ZIP CHIP is a trade mark of ZIP Technology. Introduction OPIX is a runtime environment for the HyperC system. It can be used during program development with the HyperC tools or as a runtime library for stand alone programs. For those familiar with HyperC, it is functionally equivalent to OPSYS, but fixes some bugs and offers some new features like: - eliminates some bugs present in OPSYS - is about 10% faster than OPSYS - offers an extended file system - allows the user to install his/her own device drivers - can reserve memory for special use - can gain usable memory by decreasing number of reserved file buffers - allows for easy I/O redirection - is configurable to support non-standard setups As a companion to the OPIX kernel, there is the OPIX shell. It eliminates some minor problems with OPIX and the original shell and has several extensions like: - user-definable prompt - extended file name parsing - reports failure of built-in commands (this may seem trivial, but it wasn't the case with the original shell) - improved ls command - additional commands like chmod, echo - supports UNIX-style output redirection The OPIX shell requires OPIX and won't run under OPSYS; the original WSM shell runs under OPIX with minor drawbacks. This documentation assumes some familiarity with HyperC and 65c02 assembly language programming; it is not a tutorial. Most of the information contained in this document is only of interest to programmers anyway. Compatibility OPIX makes use of the extended instruction set of the 65c02 processor (vs. a plain 6502). This means that your machine must be equipped or upgraded with a 65c02 (65802, 65816...) processor to run OPIX. Most 6502 based machines can be upgraded with a 65c02. The ZipChips also support 65c02 instructions. Note that there are at least two different flavors of the 65c02 with different instruction sets. OPIX should run on both, though this hasn't been tested. OPIX, as the HyperC system in general, relies on the ability to trap the 6502 BRK instruction. This is possible with all Apple II models except the original Apple ][ with the "System Monitor" in ROM (if your machine boots automatically on power-up, this doesn't apply to you). These machines can be upgraded to the "Autostart Monitor" by exchanging the "F8 ROM" chip. Applesoft BASIC in ROM isn't required, so you can keep Integer Basic if you like. As sent out, OPIX also requires an 80-column card in slot 3. This is not too much a restriction since some HyperC tools (most notably the editor) are unusable in a 40 column environment and most applications blindly assume that they are running in an 80-column environment - before OPIX, there were simply no provisions for HyperC programs to run without an 80 column card. If you install suitable device drivers, OPIX can run in 40-column mode, too. This would be useful in creating stand alone programs that don't require 80 column displays. OPIX uses ProDOS 8 and requires at least 64K of memory (ProDOS 1.0 ran on 48K machines, but you can't use it). The following table describes what is needed on your machine (without any guarantee for completeness or correctness; if you find errors, please let me know): Model Requirements Apple ][ 1,2,3,4 Apple ][+ 2,3,4 Apple //e (original) 3,4,5 Apple //e (enhanced) 4 Apple //c Apple //c+ Apple IIgs Notes: 1. must be upgraded with autostart ROM 2. must be equipped with 64K RAM (48K on-board and language card) 3. must be upgraded with 65c02 processor 4. should be equipped with 80-column card in slot 3 5. can be upgraded to enhanced //e (strongly recommended) Installation and Use To install OPIX on your HyperC work disk, perform the following steps: 1. Keep a BACKUP of your original HyperC disk for the case that something goes wrong (or you decide that you don't like OPIX). Remember Murphy: if anything can go wrong, it will. 2. Delete the files C.SYSTEM, OPSYS, and SHELL from your HyperC disk. This isn't obligatory, but these files are not needed with OPIX and take up valuable disk space. If you've been using GS.SYSTEM, HC.SYSTEM, or other replacements for C.SYSTEM, you may delete them, too. Newer versions of HC.SYSTEM are compatible with OPIX, but there is no advantage in using them with OPIX - it's up to you whether to use them or not. 3. Copy the files OPIX.SYSTEM and OPIX.SHELL to the disk. It is essential that both files reside in the same directory which will become the home directory for the shell. To run OPIX, launch the OPIX.SYSTEM file from your selector. That's all there is to it. Note: OPSYS requires the shell to be named "SHELL"; this version of OPIX expects it to be named "OPIX.SHELL" by default. This allows you to keep OPSYS and OPIX in the same directory if you like to, each system using its own shell without special precautions. TIP: If you're programming in HyperC and have a large RAMdisk, run HyperC from it - it is MUCH faster. Personally, I use ShrinkIt to unpack an archive containing a workdisk to /RAM after startup. This not only makes it possible to keep the system on a single 140K disk but even is much faster than copying an entire directory structure file by file. If you have a small RAMdisk, leave the HyperC files on your startup disk, but make the RAMdisk your working directory. Many HyperC tools generate a LOT of temporary files in the working directory; doing this on a "real" disk is slllooooowwwwww... Description of the startup process If OPIX doesn't start correctly on your machine, there is not too much you can do about it yourself unless you're an assembly language expert. This paragraph may be of help however in localizing the problem so I can try to fix it. Please let me know if you discover incompatibilities or bugs, even if you're able to fix them yourself (someone else might not be as clever as you!). This description refers to OPIX in its default configuration. OPIX may behave differently if configured (see below). It is mentioned in the copyright section, but I want to repeat it: pass OPIX on only in its original, unconfigured state. On startup, OPIX displays a title screen and performs several compatibility checks. If any of these checks fail, an appropriate message is displayed and - after pressing a key - OPIX terminates and returns to ProDOS. If all these checks are satisfied, OPIX checks if the machine has the original //e ROMs and, if so, installs a special set of device drivers. This feature has been incorporated because the original //e ROMs contain severe bugs concerning the use of the 80 column card. OPIX as sent out uses the BASIC way of accessing 80 column cards for several reasons (like speed and the possibility to switch to the monitor); only on the original //e the Pascal/firmware interface is used. After this the OPIX kernel is relocated to its final position where it stays resident. Some initializations are made, and control is passed to the kernel itself. The kernel tries to load and execute the shell. If it fails, it will print an error message and try again. From there on things are controlled by the shell. Refer to the section describing the shell for further information. The Extended File System OPIX is very similar to OPSYS in many respects for the sake of compatibility. The file system used by OPSYS (which is really identical to ProDOS) has been extended transparently to include character oriented devices like the screen, the keyboard, printers, modems, and so on. Programs can use these devices without a change. These so-called "device files" are accessed in exactly the same way as regular ProDOS files, except that they have special file names of the form "/n" where n is an integer from 0 to 7. Earlier OPIX prototype versions used names of the form "#n" for device files. This has been changed for several reasons. If the I/O routines recognize a file name of this form, they perform operations corresponding to what ProDOS would do for disk based files. If the file name isn't recognized as a device file name, the I/O request is simply passed on to ProDOS (which may report an error if the file name also isn't a legal ProDOS name). On opening device files, they are assigned a file descriptor (just like ProDOS files). OPIX I/O routines that expect file descriptors instead of file names can recognize device files because the value range of the descriptors is disjunct from the ProDOS range. Don't make assumptions about the values of these descriptors - they may change without notice. There are some differences to ProDOS files however that result from the structure of character oriented devices: you can't seek on them (they are purely sequential byte streams), and you can't remove (delete) them. It is also not allowed to rename them; this could have been added but it would certainly not be worth the additional overhead in implementing it. A more subtle difference can cause problems however: several programs read data until they encounter an end of file (EOF) condition. For device files, there is never an EOF since at any time, new data could be entered. Since there is no physical EOF, it would be possible to define one special character of the incoming byte stream as an EOF marker (like ctrl-C under Apple Pascal). This would prohibit many useful applications however since data may coincide with the EOF marker. For these reasons, there is never an EOF condition for device files. Keep this in mind! One additional note: device files don't use a file buffer. You can actually open more than 8 files if some of them are device files. You can also open the same device file several times; there is no file locking. This could be incorporated into OPIX with moderate overhead but I guess it is not really important in a single-tasking environment. At the lowest level of I/O common to both ProDOS and device files are functions like create(), open(), read(), getl(), write() and close(). These functions call ProDOS for non-device files, and they call the device drivers directly for device files. The structure of the device drivers is documented in a separate chapter; you can supply your own device drivers if you like to. For ProDOS files only, there are remove(), rename(), and seek(). All other I/O functions build up on these. There are several such levels of I/O functions, and it is recommended to always use the simplest I/O function that will do the job. Above all, escape the habit of many programmers to use printf() for everything. The putstr() function calls two assembly-written functions once; printf() has to parse a string character by character and has much formatting overhead, all in interpreted cp-code. OPIX has two standard files opened for use by programs: _StdIn for input, and _StdOut for output. Both of these refer normally to the console, but they can as well be set to different files and such redirect I/O. This is similar (though not identical) to UNIX. Many I/O functions operate on these standard files; using them will often increase the usefulness of programs and/or take some burden off your shoulders as the shell does all the work in selecting an output file. Changing _StdIn and _StdOut yourself is recommended to advanced programmers only; there are several more or less obvious caveats that have to be taken into account. The OPIX shell lets you specify _StdOut on starting a program and cares about possible problems in setting _StdOut. BRK Trapping The HyperC system uses the 65xxx BRK instruction (opcode 0x00) to activate the so-called cp interpreter which emulates a hypothetical 16 bit processor. Compare this to the UCSD p machine. Using BRKs allows to mix native code and cp code subroutines transparently. It may lead to problems however if for some reason a "real" BRK (indicating a breakpoint) is encountered; this is of concern mainly on the Apple IIgs where some debugger may be installed. For this reason, BRK handling is not trivial. There are some rudimentary checks built in for the IIgs, but more reliable checks would decrease the efficiency of the cp code too much. This is the way how OPIX traps BRKs: On startup, OPIX installs its own BRK vector at location 0x03f0. The old BRK vector is saved and restored when leaving using the _quit() function. All BRKs encountered will enter the cp interpreter unconditionally. On the IIgs, BRK handling is more complicated for several reasons. OPIX installs its own BRK vector (in addition to the 8-bit BRK vector which is set also) on the IIgs, saves the old vectors, and restores them on _quit(). To allow the use of debuggers, BRKs will enter the cp interpreter only if the BRK occurred in 8 bit emulation mode; native mode BRKs will be passed on to the routine installed before OPIX was started. The BRK handling scheme for the IIgs has been contributed by Gary F. Desrochers. Note that you can't get around BRK trapping, even if you compile your programs to native code. Many functions of the OPIX kernel are in cp code for the sake of memory efficiency. Other Differences to OPSYS The resident functions in OPIX are essentially the same as in OPSYS with the entry addresses unchanged. Most of them achieve the same overall result as the OPSYS functions but differ in some details. A description of all built-in functions is supplied in a separate document. OPIX works also differently under certain other aspects like loading and executing programs. It also has some structural differences, mainly concerning the I/O functions. As long as you're not using special tricks in your programs that make keen assumptions about how things work, it is not very likely that your programs developed under OPSYS don't work under OPIX. Remember that the HyperC tools which are without doubt quite complex programs run fine with OPIX. There are very few OPSYS functions that are not supported any more under OPIX for technical reasons (for example _prtvid()), and several others still work, but should not be used any more because they're either considered bad style or are inconsistent with other related functions (for example _setPath()). Refer to the OPIX docs, and don't use undocumented functions. Configuring OPIX In contrast to OPSYS, OPIX has some limited configurability. The structure and working of OPIX is largely determined by OPSYS for the sake of compatibility, and there is not much to configure. There are however some aspects that can be controlled by the user: - You may supply your own device drivers if the standard ones are not compatible with your system or if you want to support additional devices. - You may specify the initial values of some flags concerning the printer driver. - You may set aside some memory for special purposes limited only by your imagination. - You may specify how much memory should be reserved for file buffering. For a given application, you can gain much memory (1K per buffer) if you lower the number of file buffers to the required minimum. - You may disable the installation of special driver code for the original //e if your own drivers can cope with all models. - You may disable the check for an 80 column card if your drivers don't rely on one. - You may specify the name of the startup program (normally the shell). - You may disable the title screen. The greater part of these modifications is useful mainly for creating stand alone applications. You can give your application a more meaningful name than "OPIX.SHELL" (and thus keep several applications in the same directory); you can gain memory; you can write programs that run in 40 column environments, and you can make sure that the OPIX title screen doesn't look more impressive than your own. If your printer doesn't work correctly with the standard printer flag values you also may change their defaults so you don't have to modify them on every startup. These flags control whether line feeds are added after carriage returns and if TAB characters are expanded into spaces before being sent to the printer. All these modifications are handled by the supplied CFG program. It is menu-driven and quite self-explanatory. It is not further documented in this manual; if you don't know what the options of the CFG program do after having read the online hints, better leave your hands off. You CAN configure OPIX in a way it can't recover from, and a minimum of technical knowledge is required to prevent this. The configuration data is stored inside the OPIX.SYSTEM file (or a copy of it, which is of course highly recommended). Don't let your owen programs mess around with the code. The locations of the configuration parameters may change and they shouldn't be accessed by anything else but CFG. All modifications that are less than a hack can be done with the CFG program. I've been asked how to install different cp interpreters which would be useful on machines with 16 bit processors. As of now, this is not supported; this would require massive patching and is highly version dependent. I'm thinking about it however, and future versions of OPIX may have the ability to link your own cp interpreter to the code (thank you, Andy!). Writing Your Own Device Drivers OPIX gives you one page (256 bytes) of memory to squeeze your driver code in. This is not too much, but it will suffice for most setups (the standard driver set supports the 80-column screen, a printer in slot 1, a device in slot 2 and a null-device; there is still memory left). You could also reserve some memory above the file buffers (using the CFG program) and install parts of your driver code there if you absolutely must. After relocation, the device driver code will reside at 0x1f00..0x1fff. You must assemble/link your code with these addresses in mind. The driver for a specific device is called via a jump table at 0x1ff0..0x1fff. Each driver should support the following actions: initialization, reading a byte, writing a byte, and a status request. In any case, you must return an error code in the x register (0 meaning "no error"). The protocol is quite similar to the Pascal/firmware protocol for interface cards (no coincidence). Note that the device number is not necessarily identical to the slot the device is in. INIT: To perform an INIT, your driver will be called with a 1 in the y register. Your driver should make some initializations if necessary to prepare the device for reads/writes. READ: When your driver gets called with a value of 2 in the y register, it should read a byte from the device and return it in the accumulator. ASCII data should be returned with bit 7 cleared. WRITE: To perform a WRITE, your driver will be called with a 3 in the y register. The byte to be written is in the accumulator. ASCII data has bit 7 cleared. STATUS: This call is currently not used by OPIX. Nevertheless, you should implement it. Your driver will be called with a value of 4 in the y register; the accumulator contains a one or a zero. If a==1, return with the carry set if there is input ready; if a==0, return with the carry set if the device is ready to accept output. Your driver must in any case return an error code in the x register. This code is used by OPIX in the same way as the ProDOS MLI error code. Typical values are: x= meaning 0x00 no error 0x03 illegal request 0x28 no device connected There are two other activities that are device dependent and consequently up to your driver code: positioning the cursor and retrieving the cursor position. I expect the standard drivers to work on most machines, but there is no legal way to set and retrieve the cursor position in 80 column mode reliably, and Murphy dictates that you are the one hitten by an incompatibility. The cursor position will be passed on the cp-stack and should be returned in the cp machine accumulator. It is encoded as a word with the LSB meaning the x coordinate (starting at 0) and the MSB the y coordinate (also starting at 0). Your code must total 256 bytes, consist of a TEXT section only, and be linked to absolute address 0x1f00; otherwise CFG won't let you install it. Several addresses are defined to interface your drivers to the kernel: Address Contents 0x1fec jump vector to getcurs routine 0x1fee jump vector to setcurs routine 0x1ff0 vector to /0 driver (must be the console) 0x1ff2 vector to /1 driver (should be the printer if one exists) 0x1ff4 vector to /2 driver ... ... 0x1ffe vector to /7 driver It is essential that the vectors for unused devices point to a routine returning an error (0x28) in the x register, or OPIX may crash if you try to access a non-existent device file. Take a look at the supplied source code for the standard drivers, I've commented it extensively. To install your drivers, use the CFG program and follow the on-screen instructions. You can install both drivers for the original //e and the other machines independent from each other. OPIX Memory Usage This section describes the memory regions used or reserved by OPIX. Take this information into account when writing assembly routines. It is recommended to have the code and data addresses assigned by the linker to avoid memory conflicts. Zero page addresses can't be allocated by the linker; it is not recommended to keep any static data in page zero therefore. If you do otherwise, there may be collisions between different routines. If possible, use the scratch space at 0x00..0x1f for local, non-static data. Be prepared that other routines called may change these locations also. ProDOS saves and restores parts of page zero, so you may not use some locations in interrupt routines. Also, OPIX is not reentrant, so don't call it on interruptions. Generally avoid tweaking system variables. If you must change them, be very careful. The integrity of many locations is essential for the operation of OPIX, and changing these without complete knowledge of the implications this may have is almost certain to crash the system sooner or later. The memory map as shown below refers to OPIX in first place. For monitor or ProDOS locations, refer to the documentation available (?) from Apple. The above recommendations are somewhat restrictive. You're free to ignore them if you choose to, but keep in mind that these rules help protect you from many annoying and difficult to find bugs. Address Usage 0x0000..0x001f scratch space 0x0020..0x0055 used by the monitor and in part by OPIX 0x0056..0x00c5 unused 0x00c6..0x00e5 cp machine "display" registers for 16 lexical levels 0x00e6..0x00eb cp machine work space & flags 0x00ec..0x00ed cp machine b register 0x00ee..0x00ef cp machine accumulator; return function results in it 0x00f0..0x00f1 cp machine program counter 0x00f2..0x00f3 cp machine frame pointer (base register) 0x00f4..0x00f5 cp machine stack pointer 0x00f6..0x00ff unused 0x0100..0x01ff 65c02 machine stack 0x0200..0x023f thrashed by the ProDOS clock routine 0x0240..0x027f OPIX shell prompt string 0x0280 reserved 0x0281..0x02bf shell pathname 0x02c0..0x02ff shell search path 0x0300..0x037f pointers for parameter passing 0x0380 _ioresult (I/O error code) 0x0381 _sysfd (file descriptor of running program used by the overlay loader - DON'T CHANGE) 0x0382 _prtpos (horizontal position used by printer driver) 0x0383 _pcrlf (printer driver flag, bit 7 set adds LF to CR; bit 6 set expands TABs into spaces) 0x0384..0x0385 _exitVal (exit value returned by program; of little use to applications since cleared on program startup) 0x0386..0x0387 _pname (pointer to pathname of current program) 0x0388..0x0389 _errHdlr (pointer to error handling routine; can be set to trap fatal errors or user breaks) 0x038a..0x038b _heapBase (for memory management - DON'T CHANGE) 0x038c..0x038d _heapTop (for memory management - DON'T CHANGE) 0x038e _StdIn (standard input file; setting it correctly is involved) 0x038f _StdOut (standard output file; setting it correctly is involved) 0x0390 _cmdfd (file descriptor of shell script file - DON'T CHANGE) 0x0391 _cargc (script argument count - DON'T CHANGE) 0x0392..0x03df reserved for future use 0x03e0..0x03e1 _BrkSave (saved BRK vector - DON'T CHANGE) 0x03e2..0x03e5 _BrkSaveGS (saved IIgs BRK vector - DON'T CHANGE) 0x03e6 _StkTop (first page above cp stack - DON'T CHANGE) 0x03e7 _MemTop (first page above file buffers - DON'T CHANGE) 0x03e8..0x03e9 _subVersion (minor OPIX version and identification value) 0x03ea..0x03ec reserved for future use 0x03ed..0x03ee used by AuxMem XFER routine 0x03ef reserved for future use 0x03f0..0x03f1 BRK vector - DON'T CHANGE 0x03f2..0x03f3 RESET vector 0x03f4 RESET vector validation byte 0x03f5..0x03f7 reserved for future use 0x03f8..0x03fa JMP to monitor ctrl-y service routine 0x03fb..0x03fd JMP to NMI routine 0x03fe..0x03ff IRQ vector - DON'T CHANGE 0x0400..0x07ff text video page #1 & screenholes 0x0800..0x1eff resident OPIX kernel 0x1f00..0x1fff OPIX device drivers 0x2000..0x9dff available memory for programs & data (upper bound configuration dependent) 0x9e00..0xbdff OPIX file buffer pool (standard configuration) 0xbe00..0xbeff memory reserved for shells usage (standard configuration) 0xbf00..0xbfff ProDOS global page The OPIX shell The OPIX.SHELL file distributed with OPIX is a simple shell specifically written for OPIX. It isn't fancy, but at least as useful as the original WSM shell in working with HyperC. On startup, the OPIX shell displays a welcome message and tries to execute a program or script file (see below) named "profile". You can use this to make your own initializations on startup. If "profile" is not found, you'll get an error message - just ignore it. You communicate with the shell by entering command lines. Command lines follow some simple rules: - A command line starting with a ';' is regarded a comment and will be ignored (this makes sense in script files). - Blank lines are ignored. - Command lines are separated into several items by spaces. If you want one item to include spaces, enclose it in quotes. You may also precede characters by a backslash, and they will be taken literally (and not interpreted as delimiters). In addition, the following conversion codes are supported: \n carriage return (0x0d) \r carriage return (0x0d) \f form feed (0x0c) \e escape (0x1b) \b backspace (0x08) \a bell (0x07) \\ backslash (\) \" quote (") - If the last item of the command line begins with a '>', it will be removed and the screen output of the command will be redirected to the file specified immediately behind the '>'. The output file will be created; an existing file with the same name will be lost. - The first item is compared to a list of built-in commands. If a match is found, the internal command will be executed, using the remaining items as parameters. All internal commands are lower-case only; if you want to execute a program whose file name coincides with an internal command, just type it in upper case. - If the first item is not a built-in command, the shell tries to execute a file with this name and passes the remaining items as arguments. The shell takes care of a search path (see below). Script files Script files are used to perform often-used command sequences (such as compiling, assembling and linking a C program) automatically. Files that aren't recognized as executable HyperC programs (by checking the first two bytes of the file which must be 0x00 and 0x01) are treated as script files when trying to execute them, and the subsequent command lines are taken from them. Script files can't nest; if you call one script file from another one, the old file will be closed, then the new file will be executed. Script files can use command line arguments. Whenever a dollar sign ($) followed by an integer appears in a script line, it is literally substituted by the corresponding command line argument when the script file was invoked. $0 is the script file name, $1 and on represent the arguments. If you specify less arguments that the script file expects, the undefined arguments are considered null strings. On the other hand, you can specify more arguments than are actually used, and they will be ignored. File specifications The OPIX shell does some elementary file name parsing on most commands. If you specify a full pathname (starting with a slash), it is used without modification. Otherwise, it is concatenated to the current working directory path. You can also specify ".." as a directory name anywhere in the path. This will step back one directory. Example: when your current directory is "/hd/hyperc/games", the file specification "../bin/test" will access the file "/hd/hyperc/bin/test". List of built-in commands Command: version Description: This command writes shell version data to the standard output. Command: ls {-{l}} {} Description: This command lists the files of the given directories, or of the working directory if none is specified. If the -l flag is present, the file access bits, file size, and creation/modification dates and times are listed, too. If no working directory (prefix) is set (or you specify "/" as directory name) all online volumes will be listed. Command: rm Description: This command removes (deletes) a file. Command: md Description: This command creates a new directory. Command: ren Description: This command renames a file from to . This is not the same as an UNIX "mv" as the file must remain in its old directory. Command: cp Description: This command copies a file from to . The copies contents will be identical to the original, but the file attributes aren't copied. The resultant file will be a ProDOS TXT file. Command: echo {} Description: This command echoes its parameters to the standard output. It is mainly used to display messages from within script files. Use "echo \f" to clear the screen. Command: ? Description: This command lists the names of all built-in commands as a quick reminder. Command: bye Description: This command terminates both the shell and OPIX and returns to ProDOS. Command: prompt Description: This command sets the command line prompt to what you like. Some prompts aren't recommended... try this one: "prompt \f" ;-) Command: path [] Description: This command sets (if specified) and displays the current shell search path. The search path is a list of directory specifications or null strings (meaning "current directory") separated by vertical bars (|) that will be searched consecutively for external commands. Command: pwd Description: This command displays the current working directory (ProDOS prefix). Command: cd [] Description: This command selects a new working directory. If no argument is specified, the OPIX root directory (in which OPIX.SYSTEM and OPIX.SHELL reside) is used. Command: chmod {+|-{rwnd}} Description: This command modifies the file access bits of the specified ProDOS file. Options prefixed with a '+' will set the corresponding bit (allow access); options prefixed with a '-' will clear it (deny access). The option letters stand for Read, Write, reName, and Delete. You can verify these options with the "ls -l" command. Error messages indicating trouble with I/O operations generally give you an error number in parentheses. This is the ProDOS MLI return code or the driver return code for device files. It may be helpful in identifying what caused the error.