home *** CD-ROM | disk | FTP | other *** search
Text File | 2019-04-13 | 77.8 KB | 1,601 lines |
- ACE-128/64 PROGRAMMER'S REFERENCE GUIDE (version 1.2b, for Release #11)
-
- by Craig Bruce <csbruce@ccnga.uwaterloo.ca> 02-Feb-1994, Rev. 21-Sep-1994.
-
- 1. INTRODUCTION
-
- ACE is a program for the Commodore 128 and Commodore 64 that provides a
- command shell environment that is similar to that of Unix. It is still in the
- development stage, but enough of it is complete to be useful. BTW, "ACE"
- means "Advanced Computing Environment" (well, advanced for the 128/64).
-
- So what is ACE all about? Well, originally I tried a very ambitious project
- of writing a multitasking operating system for the 128. It got it partially
- working, but it was much too fragile and incomplete to be released. It was a
- white-elephant project. So, then then it came to me that I was aiming much
- too high. What I needed was a much simpler system, one that would give the
- type of programming interface and built-in features that I wanted, but one
- that was close enough to the Commodore Kernal that it would not require much
- of a programming effort to hack together a minimal implementation. And thus,
- there was ACE-128 Release #1. And I saw it was good.
-
- What I wanted was a system that would be easier to program than the Commodore
- Kernal with all its weird and wonderful device types, non-existent memory
- management, and single-application design. The first important feature of
- this environment was to be able to pass arguments from a command line to an
- application program by typing them on the command line of the shell. It is so
- annoying to load up a program in BASIC, run it, and have it ask you for
- filenames in some highly inconvenient way.
-
- Another important system feature is to make near and far memory management
- part of the system, and to make far memory convenient to use for storing
- massively bulky data. And so it was. Also, we want to use custom device
- drivers. Commodore didn't really come through with the device drivers it
- provided. They are all REALLY SLOW. And so that was, also, although more
- custom device drivers are needed. We want to have the capability of making
- programs work together, rather than having programs that are totally
- incompatible. This functionality is still under construction. Programs will
- work together in this uni-tasking environment by allowing a program to execute
- another program as a sub-task, and then having control return to the calling
- program upon exit. Finally, we want some good quality applications and a
- powerful command shell. This is still being worked on and progress is coming
- slowly. Oh, almost forgot; we also want all programs to work on both the C64
- and C128, and they do.
-
- 2. SYSTEM INTERFACE
-
- This section describes the interface between user programs and the ACE kernel.
- I am very careful throughout this interface specification about revealing any
- internal details that you do not strictly need to know. The interface with
- ACE is not specified in terms of absolute addresses; to aid in portability and
- extensibility, all interfaces are specified in terms of symbolic assembler
- labels. All of the ACE code is currently written for the Buddy-128 assembler.
- Also, because these interface absolute addresses are subject to change from
- version to version of the kernel, executables compiled for use with an old
- version of ACE may not work with a new version.
-
- 2.1. ZERO-PAGE VARIABLES
-
- There are four zero-page variables used for passing arguments in most system
- calls. They are as follows:
-
- SYMBOL BYTES DESCRIPTION
- ------- ----- -----------
- zp 2 zeropage pointer
- zw 2 zeropage word
- mp 4 memory pointer
- syswork 16 system work area / arguments
-
- The first two, "zp" and "zw" are used in most calls. They store simple 16-bit
- values; "zp" usually stores pointers to strings in RAM0 memory. The "mp"
- variable is 32-bits in length and is used exclusively for passing far memory
- pointers for use with the far memory routines. All three of these variables
- will remain unchanged inside of system call unless they will contain a return
- value. "syswork" is a 16-byte array used mainly when there are too many
- arguments for other variables to hold, and all non-input and non-output bytes
- of "syswork" are subject to change by the kernel. All input arguments placed
- in the "syswork" locations will be preserved unless otherwise indicated.
-
- 2.2. SYSTEM VARIABLES
-
- There are several non-zeropage variables for storing system status and return
- values:
-
- SYMBOL BYTES DESCRIPTION
- ---------- ----- -----------
- errno 1 error number code returned by failed system calls
- aceID 2 proof that user program is running on top of ACE
- aceArgc 2 argument count for current process
- aceArgv 2 argument vector address for current process
- aceMemTop 2 highest address, plus one, that user prog can use
- aceShellPath 256 storage for search path for executable programs
- aceShellAlias 256 storage for shell command aliases
- aceCurDirName 128 storage for the current directory name
- aceExitData 256 storage for exit status from the last called prg
- aceDirentBuffer <next> storage for directory entries read from disk
- aceDirentLength - really a constant: length in bytes of "aceDirentBuffer"
- aceDirentBytes 4 bytes in file (usually inexact)
- aceDirentDate 8 date of file in "YY:YY:MM:DD:HH:MM:SS:TW" format
- aceDirentType 4 type of file in null-terminated string
- aceDirentFlags 1 flags of file, "drwx*-et" format
- aceDirentUsage 1 more flags of file, "ulshm---" format
- aceDirentNameLen 1 length of name of file
- aceDirentName 17 null-terminated name of file
-
- ERRNO: "errno" is used to return error codes from system calls. When a system
- call ends in error, it sets the carry flag to "1", puts the error code in
- "errno", and returns to the user program, after undoing any system work
- completed at the time the error is encountered and aborting the operation. An
- error code number is stored in binary in the single-byte "errno" location. The
- symbolic names for the possible error codes are given in the next section. If
- no error occurs in a system call, the carry flag will be cleared on return
- from the call. Note that not all system calls can run into errors, so not all
- set the carry flag accordingly.
-
- ID: "aceID" is a two-byte variable. Its purpose is to allow user programs to
- be sure that they are executing on top of ACE. The low byte (i.e., the first
- byte) must be equal to the symbolic constant "aceID1", and the high, "aceID2".
- This will allow ACE applications to inform idiot users that they cannot simply
- BOOT the program from BASIC, but rather they must run ACE first.
-
- ARGC: "aceArgc" is a two-byte unsigned number. It gives the number of
- arguments passed to the application by the program (usually the command shell)
- that called the application. The first argument is always the name of the
- application program, so the count will always be at least one. Other
- arguments are optional.
-
- ARGV: "aceArgv" is a two-byte RAM0 pointer. Pay attention. This pointer
- points to the first entry of an array of two-byte pointers which point to the
- null-terminated strings that are the arguments passed to the application
- program by the caller. (A null-terminated string is one that ends with a zero
- byte). To find the address of the N-th argument to an application, multiply N
- by two, add the "aceArgv" contents to that, and fetch the pointer from that
- address. In this scheme, the ever-present application name is the 0-th
- argument. The argv[argc] element of the argument vector will always contain a
- value of $0000, a null pointer.
-
- MEM-TOP: "aceMemTop" is a two-byte RAM0 pointer. This points to one byte past
- the highest byte that the application program is allowed to use. All
- application programs are loaded into memory at address "aceAppAddress" (next
- section), and all memory between the end of the progam code and "aceMemTop"
- can be used for temporary variables, file buffers, etc. The main problem with
- this approach is that there are no guarantees about how much memory your
- application will get to play with. Many applications, such as simple file
- utilities, can simply use all available memory for a file buffer, but other
- programs, such as a file compressor, may have much greater demand for "near"
- memory.
-
- SHELL-PATH: "aceShellPath" is a 256-byte array of characters. This stores the
- pathnames of directories to search through in order to find executable files.
- Each pathname is stored as a null-terminated string, and the list is
- terminated by an empty string (containing only the zero character). This is
- intended to be used by the shell program, or any other program that is so
- inclined, to examine or alter the search path. The search paths specified in
- the path page are global variables and are used by all programs that make the
- "exec" system call. This mechanism for reading/altering the executable search
- path may be changed in the future.
-
- SHELL-ALIAS: "aceShellAlias" is a 256-byte array of characters. This stores
- the aliases to be used with the command shell. An alias is a string that is
- substituted in the place of a command name on a shell command line whenever a
- certain command name comes up. For example, you might specify if the user
- enters the command "list a:" that the command name "list" be string-replaced
- with "cls;xls -l". Each alias is stored with the command name first, followed
- by an equals character ("="), followed by the string to substitute, followed
- by a zero. The alias list is terminated by an empty string. This mechanism
- may be extended in the future to allow multiple pages of aliases, or may be
- changed completely.
-
- CUR-DIR-NAME: "aceCurDirName" is a 128-byte array of characters. It contains
- the null-terminated string indicating the current directory. The user is not
- supposed to modify this value, and the value will not always give a full
- pathname. The implementation of this feature may need to change in future
- versions of ACE.
-
- ACE-EXIT-DATA: "aceExitData" is a 256-byte array. It is the 256-byte buffer
- allocated for user programs to give detailed return information upon exiting
- back to their parent program. See the "exit" system call. User programs are
- allowed to read and write this storage. An example use of this feature would
- be a compiler program returning the line number and character position, and
- description of a compilation error to a text editor, so the editor can
- position the cursor and display the error message for user convenience. The
- implementation of this feature may need to change in future versions of ACE.
-
- DIRENT-BUFFER: "aceDirentBuffer" is a buffer used for storing directory
- information read with the "dirread" system call, and is "aceDirentLength"
- bytes long. Only a single directory entry is (logically) read from disk at a
- time. The individual fields of a read directory entry are accessed by the
- fields described next. This field is also used for returning disk name
- information and the number of bytes free on a disk drive (see the "dirread"
- system call).
-
- DIRENT-BYTES: "aceDirentBytes" is a four-byte (32-bit) unsigned field. As
- always, the bytes are addressed from least significant to most significant.
- This field gives the number of bytes in the file. Note that this value may
- not be exact, since Commodore decided to store sizes in disk blocks rather
- than bytes. For devices that report only block counts (i.e., every disk
- device currently supported), the number of bytes returned is the number of
- blocks multiplied by 254. This field, as well and the other dirent fields are
- absolute addresses, not offsets from aceDirentBuffer.
-
- DIRENT-DATE: "aceDirentDate" is an eight-byte array of binary coded decimal
- values, stored from most significant digits to least significant. The first
- byte contains the BCD century, the second the year, and so on, and the last
- byte contains the number of tenths of seconds in its most significant nybble
- and a code for the day-of-week in its least significant nybble. Sunday has
- code 1, Monday 2, etc., Saturday 7, and a code of 0 means "unknown". This is
- the standard format for all dates used in ACE. This format is abstracted as
- "YY:YY:MM:DD:HH:MM:SS:TW". For disk devices that don't support dates, this
- field will be set to all zeroes, which can be conveniently interpreted as the
- NULL date, negative infinity, or as the time that J.C. was a seven-year-old
- boy.
-
- DIRENT-TYPE: "aceDirentType" is a three-character (four-byte) null-terminated
- string. It indicates what type the file is, in lowercase PETSCII. Standard
- types such as "SEQ" and "PRG" will be returned, as well and other
- possibilities for custom device drivers.
-
- DIRENT-FLAGS: "aceDirentFlags" is a one-byte field that is interpreted as
- consisting of eight independent one-bit fields. The abstract view of the
- fields is "drwx*-et". "d" means that the item is a subdirectory (otherwise it
- is a regular file), "r" means the item is readable, "w" means the item is
- writable, and "x" means the item is executable. The "x" option is really not
- supported currently. "*" means the item is improperly closed (a "splat" file
- in Commodore-DOS terminology). The "-" field is currently undefined. "e"
- means that the value given in the "aceDirentBytes" field is actually exact,
- and "t" means the file should be interpreted as being a "text" file
- (otherwise, its type is either binary or unknown). The bit fields are all
- booleans; a value of "1" means true, "0", false. The "d" bit occupies the
- 128-bit position, etc.
-
- DIRENT-USAGE: "aceDirentFlags" is a one-byte field very much like
- "aceDirentFlags". The abstract view of the fields is "ulshm---". "u"
- indicates whether the directory entry is used (current) or not (deleted).
- The directory system calls will not read a directory entry that is deleted, so
- you will never see this bit not set; it is used internally. "l" indicates
- whether the directory entry is for an actual file (==0, normal) or a "link"
- (==1) to another file. The "s" and "h" bits indicate which type a link is:
- "soft" or "hard", respectively. These both work similarly to Unix hard and
- soft links. The "m" flag indicates whether a file has been modified since
- the last time that a backup program cleared the "m" bit for the file, allowing
- incremental backups.
-
- DIRENT-NAME-LEN: "aceDirentNameLen" is a one-byte number. It gives the number
- of characters in the filename. It is present for convenience.
-
- DIRENT-NAME: "aceDirentName" is a 16-character (17-byte) null-terminated
- character string field. It gives the name of the file or directory or disk.
- Filenames used with ACE are limited to 16 characters.
-
- 2.3. SYSTEM CONSTANTS
-
- There are several symbolic constants that are used with the ACE system
- interface:
-
- SYMBOL DESCRIPTION
- ------------------- -------------------------
- aceAppAddress the start address of applications
- aceID1 the id characters used to identify ACE applications
- aceID2 ...
- aceID3 ...
- aceMemNull the far memory type code used to indicate null ptrs
- aceMemREU far mem type code for Ram Expansion Unit memory
- aceMemInternal far mem type code for internal memory
- aceMemRLREU far mem type code for REU memory accessed thru RAMLink
- aceMemRL far mem type code for direct-access RAMLink memory
- aceErrStopped error code for syscall aborted by STOP key
- aceErrTooManyFiles err: too many files already opened to open another
- aceErrFileOpen err: don't know what this means
- aceErrFileNotOpen err: the given file descriptor is not actually open
- aceErrFileNotFound err: named file to open for reading does not exist
- aceErrDeviceNotPresent err: the specified physical device is not online
- aceErrFileNotInput err: file cannot be opened for reading
- aceErrFileNotOutput err: file cannot be opened for writing
- aceErrMissingFilename err: pathname component is the null string
- aceErrIllegalDevice err: the specified device cannot do what you want
- aceErrWriteProtect err: trying to write to a disk that is write-protected
- aceErrFileExists err: trying to open for writing file that exists
- aceErrFileTypeMismatch err: you specified the file type incorrectly
- aceErrNoChannel err: too many open files on disk drive to open another
- aceErrInsufficientMemory err: ACE could not allocate the memory you requested
- aceErrOpenDirectory err: you are trying to open a dir as if it were a file
- aceErrDiskOnlyOperation err: trying to perform disk-only op on char device
- aceErrNullPointer err: trying to dereference a null far pointer
- aceErrInvalidFreeParms err: bad call to "pagefree": misaligned/wrong size
- aceErrFreeNotOwned err: trying to free far memory you don't own
- aceErrInvalidWindowParms err: invalid window dimensions were given
- aceErrInvlaidConParms err: invalid console parameters were given
- aceErrInvalidFileMode err: opening a file for other-than "r","w", or "a"
- aceErrNotImplemented err: system call or option is not (yet) implemented
- aceErrBloadTruncated err: a bload operation stopped before exceeding limit
- aceErrPermissionDenied err: attempt to read or write a file without perms
- stdin file descriptor reserved for stdin input stream
- stdout file descriptor reserved for stdout output stream
- stderr file descriptor reserved for stderr output stream
-
- "aceAppAddress", as discussed before, is the address that application programs
- are loaded into memory at. They must, of course, be compiled to execute
- starting at this address.
-
- The "aceMem" group of constants are for use with the "pagealloc" system call,
- except for "aceMemNull", which may be used by application programs for
- indicating null far pointers. The "pagealloc" call allows you to specify what
- types of memory you are willing to accept. This is important because the
- difference types of memory have different performance characteristics. ACE
- will try to give you the fastest memory that is available. Ram Expansion Unit
- memory has startup and byte-transfer times of about 60 us (microseconds) and 1
- us, respectively. This is the fastest type of far memory. Internal memory
- has a startup time of 24 us and a byte-transfer time of between 7 and 14 us
- (depending on whether accessing RAM0 or RAM1+). REU memory accessed through a
- RAMLink has a terrible startup time of 1000 us and a byte-transfer time of 2
- us. Direct-access RAMLink memory has a startup time of 1000 us and a
- byte-transfer time of 16 us. All these times are for the C128 in 2 MHz mode.
-
- The "aceErr" group gives the error codes returned by system calls. The error
- codes are returned in the "errno" variable. Not all possible error codes from
- Commodore disk drives are covered, but the important ones are. Finally, the
- "std" files group give the symbolic file descriptor identifiers of the default
- input, output, and error output file streams.
-
- 2.4. SYSTEM CALLS
-
- All system calls are called by setting up arguments in specified processor
- registers and memory locations, executing a JSR to the system call address,
- and pulling the return values out of processor registers and memory locations.
-
- 2.4.1. FILE CALLS
-
- NAME : open
- PURPOSE: open a file
- ARGS : (zp) = pathname
- .A = file mode ("r", "w", or "a")
- RETURNS: .A = file descriptor number
- .CS = error occurred flag
- ALTERS : .X, .Y, errno
-
- Opens a file. The name of the file is given by a pointer to a null-terminated
- string, and may contain device names and pathnames as specified in the ACE
- user documentation. The file mode is a PETSCII character. "r" means to open
- the file for reading, "w" means to open the file for writing, and "a" means to
- open the file for appending (writing, starting at the end of the file). An
- error will be returned if you attempt to open for reading or appending a file
- that does not exist, or if you attempt to open for writing a file that does
- already exist. If you wish to overwrite an existing file, you will have to
- call "remove" to delete the old version before opening the new version for
- writing.
-
- The function returns a file descriptor number, which is a small unsigned
- integer that is used with other file calls to specify the file that has been
- opened. File descriptors numbered 0, 1, and 2 are used for stdin, stdout, and
- stderr, respectively. The file descriptor returned will be the minimum number
- that is not currently in use. These numbers are system-wide (rather than
- local to a process as in Unix), and this has some implications for I/O
- redirection (see the "fdswap" call below).
-
- Restrictions: only so many Kernal files allowed to be open on a disk device,
- and there is a system maximum of open files. You will get a "too many files"
- error if you ever exceed this limit. Also, because of the nature of
- Commodore-DOS, there may be even tighter restrictions on the number of files
- that can be simultaneously open on a single disk device, resulting in a "no
- channel" error. Note that this call checks the status channel of Commodore
- disk drives on each open, so you don't have to (and should not anyway).
-
- If the current program exits either by calling "exit" or simply by doing the
- last RTS, all files that were opened by the program and are still open will be
- automatically closed by the system before returning to the parent program.
-
- NAME : close
- PURPOSE: close an open file
- ARGS : .A = File descriptor number
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Closes an open file. Not much to say about this one.
-
- NAME : read
- PURPOSE: read data from an open file
- ARGS : .X = File descriptor number
- (zp) = pointer to buffer to store data into
- .AY = maximum number of bytes to read
- RETURNS: .AY = (zw) = number of bytes actually read in
- .CS = error occurred flag
- .ZS = EOF reached flag
- ALTERS : .X, errno
-
- Reads data from the current position of an open file. Up to the specified
- maximum number of bytes will be read. You should not give a maximum of zero
- bytes, or you may misinterpret an EOF (end of file). The buffer must be at
- least the size of the maximum number of bytes to read. The data are not
- interpreted in any way, so it is the programmer's responsibility to search for
- carriage return characters to locate lines of input, if he so desires.
- However, for the console the input is naturally divided up into lines, so each
- call will return an entire line of bytes if the buffer is large enough. There
- are no guarantees about the number of bytes that will be returned, except that
- it will be between 1 and the buffer size. So, if you wish to read a certain
- number of bytes, you may have to make multiple read calls.
-
- The call returns the number of bytes read in both the .AY register pair and in
- (zw), for added convenience. A return of zero bytes read means that the end
- of the file has been reached. An attempt to read beyond the end of file will
- simply give another EOF return. End of file is also returned in the .Z flag
- of the processor.
-
- NAME : write
- PURPOSE: write data to an open file
- ARGS : .X = file descriptor number
- (zp) = pointer to data to be written
- .AY = length of data to be written in bytes
- RETURNS: .CS = error occurred
- ALTERS : .A, .X, .Y, errno
-
- Writes data at the current position of an open file. 'Nuff said.
-
- NAME : fastopen
- PURPOSE: open a file for fast reading
- ARGS : (zp) = Name
- .A = file mode (must be "r")
- RETURNS: .A = file descriptor number
- .CS = error occurred flag
- ALTERS : .X, .Y, errno
-
- This performs the same function as the regular "open" call, except this style
- of file accessing will allow files to be read much faster than the other. On
- devices that are so equipped, the "fastload" burst command is used (similar
- shortcuts may be possible with other devices too). The drawback of this
- increased speed is that no other device I/O can take place while a file is
- opened for "fast" access, not even to other devices, except for output to the
- console. Other files can be open, just not accessed. You also cannot open
- more than one "fast" file at a time. Interrupts will be disabled while a file
- is open for fast accessing, so the user cannot re-enable them, for technical
- reasons. The arguments to this call are exactly the same as the regular
- "open" to make it easy to switch from using one to the other. [Note: in
- Release #10, these "fast" calls are simply short-circuited to the regular
- file calls].
-
- NAME : fastclose
- PURPOSE: close the file that was opened for fast reading
- ARGS : .A = File descriptor number
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Closes the file that was opened for fast reading.
-
- NAME : fastread
- PURPOSE: read data from the file opened for fast reading
- ARGS : .X = File descriptor number
- (zp) = pointer to buffer to store data into
- .AY = maximum number of bytes to read
- RETURNS: .AY = (zw) = number of bytes actually read in
- .CS = error occurred flag
- .ZS = EOF reached flag
- ALTERS : .X, errno
-
- Read data from the (one) file that is currently opened for "fast" reading. The
- arguments and semantics are equivalent to the regular "read" call.
-
- NAME : bload
- PURPOSE: binary load
- ARGS : (zp) = pathname
- .AY = address to load file
- (zw) = highest address that file may occupy, plus one
- RETURNS: .AY = end address of load, plus one
- .CS = error occurred flag
- ALTERS : .X, errno
-
- Binary-load a file directly into memory. If the file will not fit into the
- specified space, an error will be returned and the load truncated if the
- device supports truncation; otherwise, important data may be overwritten.
-
- NAME : remove
- PURPOSE: delete a file
- ARGS : (zp) = pathname
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Delete the named file.
-
- NAME : rename
- PURPOSE: rename a file or directory
- ARGS : (zp) = old filename
- (zw) = new filename
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Renames a file or directory. If a file with the new name already exists, then
- the operation will be aborted and a "file exists" error will be returned. On
- most devices, the file to be renamed must be in the current directory and the
- new name may not include any path, just a filename.
-
- NAME : devinfo
- PURPOSE: give information about device
- ARGS : .X = file descriptor number
- RETURNS: .A = device type code (0=console, 1=char-dev, 2=disk-dev)
- .X = number of columns on device
- .Y = number of rows per "page" of device
- .CS = error occurred flag
- ALTERS : errno
-
- This call returns information about the device of an open file. There are
- four possible values for the device type code: 0==console,
- 1==character-oriented device, and 2==disk device. The number of rows and
- columns per "page" of the device are also returned. For the console, this
- will be the current window size. For a character-oriented device, it will be
- the natural size (typically 80 columns by 66 rows), and for a disk, it will be
- 40 columns in 64 mode or 80 columns in 128 mode, both by 66 rows.
-
- NAME : fdswap
- PURPOSE: swap two file descriptor numbers
- ARGS : .X = first file descriptor number
- .Y = second file descriptor number
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- This call swaps meanings of two file descriptor numbers. The file descriptors
- may be either in use or not use when the call is made. This call is intended
- to be used to redirect the stdin, stdout, and stderr file streams. To do
- this, simply open the new file intended to be, for example, stdout, and swap
- the file descriptor number returned from the open with file descriptor number
- 1 (stdout). Poof. Then call your subroutine or external program, and on
- return, swap the two file descriptors back, and close the redirection file.
-
- 2.4.2. DIRECTORY CALLS
-
- NAME : diropen
- PURPOSE: open a directory for scanning its directory entries
- ARGS : (zp) = directory pathname
- RETURNS: .A = file descriptor number
- .CS = error occurred flag
- ALTERS : .X, .Y, errno
-
- This call opens a directory for reading its entries. It returns a "file"
- descriptor number to you to use for reading successive directory entires with
- the "dirread" call. The pathname that you give to this call must be a proper
- directory name like "a:" or "c:2//c64/games/:", ending with a colon character.
- You can have directories from multiple devices open for reading at one time,
- but you cannot have the directory of one device open multiple times. Also
- note that you cannot pass wildcards to this call; you will receive the entire
- directory listing.
-
- NAME : dirclose
- PURPOSE: close a directory opened for scanning
- ARGS : .A = file descriptor number
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Closes a directory that is open for reading. You can make this call at any
- point while scanning a directory; you do not have to finish scanning an entire
- directory first.
-
- NAME : dirread
- PURPOSE: read the next directory entry from an open directory
- ARGS : .X = file descriptor number
- RETURNS: .Z = end of directory flag
- .CS = error occurred flag
- aceDirentBuffer = new directory entry data
- ALTERS : .A, .X, .Y, errno
-
- Reads the next directory entry from the specified open directory into the
- system interface global variable "aceDirentBuffer" described earlier. After
- opening a directory for reading, the first time you call this routine, you
- will receive the name of the disk (or directory). The "aceDirentNameLen" and
- "aceDirentName" fields are the only ones that will contain information; the
- rest of the fields should be ignored.
-
- Each subsequent call to this routine will return the next directory entry in
- the directory. All of the "dirent" fields will be valid for these.
-
- Then, after all directory entries have been read through, the last call will
- return a directory entry with a null (zero-length) name. This corresponds to
- the "blocks free" line in a Commodore disk directory listing. The
- "aceDirentBytes" field for this last entry will be set to the number of bytes
- available for storage on the disk. On a Commodore disk drive, this will be
- the number of blocks free multiplied by 254. After reading this last entry,
- you should close the directory.
-
- At any time, if something bizarre happens to the listing from the disk that is
- not considered an error (I don't actually know if this is possible or not),
- then the .Z flag will be set, indicating the abrupt ending of the directory
- listing.
-
- NAME : isdir
- PURPOSE: determine whether the given pathname is for a file or a directory
- ARGS : (zp) = pathname
- RETURNS: .A = device identifier
- .X = is a disk device flag
- .Y = is a directory flag
- .CS = error occurred flag
- ALTERS : errno
-
- Given a properly formatted directoryname or filename, this routine will return
- whether the name is for a file or a directory, whether the device of the file
- or directory is a disk or character device, and the system identifier for the
- device. The two flags return $FF for true and $00 for false. The device
- identifier is superfluous for now, but a "devinfo" call may be added later.
- Note that this file does not indicate whether the file/directory actually
- exists or not.
-
- NAME : chdir
- PURPOSE: change the current working directory
- ARGS : (zp) = new directory pathname
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Changes the current working directory to the named directory. Too bad the
- Commodore Kernal doesn't have a similar call. Unlike the "cd" shell command,
- the argument has to be a properly formatted directory name. Note that only
- directories in native partitions on CMD devices are supported by this command;
- the 1581's crummy idea of partitions is not supported.
-
- NAME : cdhome
- PURPOSE: change the current working directory back to the "home" directory
- ARGS : <none>
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Changes the current working directory back to the "home" directory that is
- defined in the "config.sys" file as the initial directory.
-
- NAME : mkdir
- PURPOSE: create a new directory
- ARGS : (zp) = pathname of new directory
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Creates a new directory. I'm not sure, but I think that the current directory
- has to be the parent directory of the directory you want to create. This may
- be required by CMD devices, which will be the lowest common denominator for
- directory support. [Note: in Release #10, this call only accepts a "flat"
- directory name].
-
- NAME : rmdir
- PURPOSE: delete an empty existing directory
- ARGS : (zp) = pathname of empty directory to remove
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Deletes an existing directory. The directory must be empty (have no directory
- entries) in order for this command to succeed. Again, I am pretty sure that
- you have to be "in" the parent directory of the one to be deleted, since this
- is probably required by CMD devices. [Note: in Release #10, this call only
- accepts a "flat" directory name].
-
- 2.4.3. MEMORY CALLS
-
- The calls given in this section are to be used for accessing "far" memory in
- ACE, which includes all REU, RAMLink, RAM1 and above, and sections of RAM0
- that are not in the application program area. Applications are not allowed to
- access "far" memory directly, because the practice of bypassing the operating
- system would undoubtedly lead to problems (can you say "MS-DOS"?).
-
- All of these calls use a 32-bit pointer that is stored in the zero-page
- argument field "mp" (memory pointer). This field is to be interpreted as
- consisting of low and high words. The low word, which of course come first,
- is the offset into the memory "bank" that is contained in the high word. Users
- may assume that offsets within a bank are continuous, so operations like
- addition may be performed without fear on offsets, to access subfields of a
- structure, for example. You may not, however, make any interpretation of the
- bank word. An application should only access far memory that it has allocated
- for itself via the "pagealloc" call.
-
- NAME : zpload
- PURPOSE: load zeropage storage from far memory
- ARGS : [mp] = source far memory pointer
- .X = destination zero-page address
- .Y = transfer length
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Load zero-page locations with the contents of far memory. "mp", of course,
- gives the address of the first byte of far memory to be retrieved. The X
- register is loaded with the first address of the storage space for the data on
- zero page. It must be in the application zero-page space. The Y register
- holds the number of bytes to be transferred, which, considering that transfers
- must be to the application zero-page storage, must be 126 bytes or less. This
- routine will return a "reference through null pointer" if [mp] contains a null
- pointer.
-
- NAME : zpstore
- PURPOSE: store zeropage data to far memory
- ARGS : .X = source zero-page address
- [mp] = destination far memory pointer
- .Y = transfer length
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- This routine is the complement of "zpload"; this transfers data from zero page
- to far memory. The arguments and restrictions are the same as "zpload".
-
- NAME : fetch
- PURPOSE: load near RAM0 storage from far memory
- ARGS : [mp] = source far memory pointer
- (zp) = destination RAM0 pointer
- .AY = transfer length
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- This routine will fetch up to 64K of data from far memory into RAM0 memory
- where it can be accessed directly by the processor. The arguments should
- mostly speak for themselves. You should not fetch into RAM0 memory that is
- not specifically allocated to the application. You will get an error if you
- try to use a null far pointer.
-
- NAME : stash
- PURPOSE: store near RAM0 data to far memory
- ARGS : (zp) = source RAM0 pointer
- [mp] = destination far memory pointer
- .AY = transfer length
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- This is the complement of "fetch" and operates analogously, except that it
- transfers data from RAM0 to far memory.
-
- NAME : pagealloc
- PURPOSE: allocate pages of far memory to current process
- ARGS : .A = requested number of pages to be allocated
- .X = starting "type" of memory to search
- .Y = ending "type" of memory to search, inclusive
- RETURNS: [mp] = far memory pointer to start of allocated memory
- .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- This routine allocates a given number of contiguous far-memory pages for use
- by the application, and returns a pointer to the first byte of the first page.
- On calling, the accumulator contains the number of pages to allocate (a page
- is 256 contiguous bytes aligned on a 256-byte address (i.e., the low byte of a
- page address is all zeros)).
-
- The X and Y registers contain the start and end "types" of far memory to
- search for the required allocation. The possible types are mentioned in the
- System Constants section. The numeric values for the "aceMem" constants are
- arranged in order of accessing speed. So, if your application has speed
- requirements that dictate, for example, that RAMLink memory should not be
- used, then you would call "pagealloc" with a search range of .X=0 to
- .Y=aceMemInternal. If you wanted to say you are willing to accept any memory
- the system can give to you, you would specify .X=0 to .Y=255. The values of 0
- and 255 will be converted to the fastest and slowest memory available. ACE
- will give you the fastest type of memory, from what you specify as acceptable,
- that it can. If you had an application that you didn't want to waste the
- high-speed memory on, you could first call "pagealloc" asking for slow memory,
- such as .X=aceMemRLREU to .Y=255, and if there is none of that type of memory
- left, make another call with .X=0 to .Y=aceMemRLREU-1.
-
- This routine will then search its available free memory for a chunk fitting
- your specifications. If it cannot find one, the routine will return a
- "insufficient memory" error and a null pointer. Note that this error may
- occur if there is actually the correct amount of memory free but just not in a
- big enough contiguous chunk. If successful, this routine will return in "mp"
- a pointer to the first byte of the first page of the allocated memory.
-
- If you call a subprogram with the "exec" call while the current program is
- holding far memory, that far memory will be kept allocated to your program and
- will be safe while the child program is executing. If you don't deallocate
- the memory with "pagefree" before exiting back to your parent program, then
- the system will automatically deallocate all memory allocated to you. So,
- have no fear about calling "exit" if you are in the middle of complicated far
- memory manipulation when a fatal error condition is discovered and you don't
- feel like figuring out what memory your program owns and deallocating it.
-
- Some applications will want to have the most amount of memory to work with,
- and if there is free space in the application program area that the program is
- not using directly, then you may want to use that as "far" memory. To do
- this, you will need to write your own stub routines that manage page
- allocation and deallocation requests to the near memory, and calls the
- "pagealloc" and "pagefree" routines to manage the far memory. The "sort"
- program distributed with ACE does this. Please note that you CANNOT simply
- free the unused memory of the application program area and expect the system
- to manage it. Bad stuff would happen.
-
- Some applications will want to have a byte-oriented memory allocation service
- rather than a page-oriented service. You can build a byte-oriented service on
- top of the page-oriented service in your application programs that manage
- memory for the application and ask the system for pages whenever more memory
- is required by the application. Note that this still means that allocated
- memory will be freed automatically when an application exits. The "sort"
- program implements this byte-oriented service, so you can check its source
- code to see how this is done (or to simply cut and paste the code into your
- own program).
-
- NAME : pagefree
- PURPOSE: free pages of far memory allocated to current process
- ARGS : [mp] = far memory pointer to start of memory to be freed
- .A = number of pages to be freed
- RETURNS: .CS = error occurred flag
- ALTERS : [mp], .A, .X, .Y, errno
-
- This deallocates memory that was allocated to a process by using the
- "pagealloc" system call. You will get an error return if you try to
- deallocate memory that you don't own.
-
- 2.4.4. SCREEN CONTROL CALLS
-
- This section describes the system calls that are available to application
- programmers for full-screen applications. These calls are intended to be
- general enough to handle different screen hardware (the VIC and VDC chips and
- a VIC soft-80-column bitmap screen, and possibly others). These calls are
- also designed to be efficient as possible, to discourage progammers from
- attempting to bypass using them. Bypassing these calls would be a bad thing.
-
- The calls are designed around the C-128/PET concept of a window. There is
- only one active window on the display at a time, which may be is large as the
- entire screen or as small as 1x1 character cells. This window is very cheap
- to setup and tear down. An application can have multiple windows on the
- screen by switching the active window around.
-
- In the calls below, all mention of "sw" in the arguments and return values
- refer to the "syswork" array. For many calls, there is a "char/color/
- high-attribute" argument. This argument determines which parts of a screen
- location will be modified. There are three components to each screen
- location: the character code, the color code, and the high-attributes. The
- character code is exactly the same as the PETSCII code for the character that
- you want to display (unlike the screen-code arrangement that Commodore chose).
- There are 128 individual characters in the normal PETSCII positions, and 128
- reversed images of the characters in the most sensible other positions. The
- codes are as follows:
-
- CODES (hex) DESCRIPTION
- ----------- -----------
- $00-$1f reverse lowercase letters
- $20-$3f digits and punctuation
- $40-$5f lowercase letters
- $60-$7f reverse graphics characters
- $80-$9f reverse uppercase letters
- $a0-$bf graphics characters
- $c0-$df uppercase letters
- $e0-$ef reverse digits and punctuation
-
- There are sixteen color codes, occupying the lower four bits of the color
- value. These are RGBI codes, as follows:
-
- CODE(dec) (hex) (bin) DESCRIPTION
- --------- ----- -rgbi -----------
- 0 $0 %0000 black
- 1 $1 %0001 dark grey
- 2 $2 %0010 blue
- 3 $3 %0011 light blue
- 4 $4 %0100 green
- 5 $5 %0101 light green
- 6 $6 %0110 dark cyan on VDC, medium grey on VIC-II
- 7 $7 %0111 cyan
- 8 $8 %1000 red
- 9 $9 %1001 light red
- 10 $a %1010 purple
- 11 $b %1011 light purple on VDC, orange on VIC-II
- 12 $c %1100 brown
- 13 $d %1101 yellow
- 14 $e %1110 light grey
- 15 $f %1111 white
-
- Finally, there are the high-attribute bits. These occupy the four most
- significant bits of the color value. Depending on the type of display (VIC
- text, VDC text, or VIC/VDC bitmap), these bits have one of three meanings:
- character attributes, background character color, or no effect. Thus, care
- must be taken in using these bits; they will have different effects on
- different displays. The background color codes are the same as the foreground
- color codes listed above. The character attributes have the following
- meanings:
-
- BIT VALUE (dec) (hex) DESCRIPTION
- -avub---- ----- ----- -----------
- %10000000 128 $80 alternate characterset (italic)
- %01000000 64 $40 reverse character
- %00100000 32 $20 underline
- %00010000 16 $10 blink
-
- These values are additive (or, should I say, "or-ative"); you can use any
- combination of them at one time. Normally, you may wish to leave the
- high-attribute bits alone, unless you take the values to give them from the
- color palettes (next section). To specify which of you wish to have changed,
- set bits in the "char/color/high-attribute" argument to system calls. The
- flags have the following values. They are or-ative as well:
-
- BIT VALUE (dec) (hex) DESCRIPTION
- -cah----- ----- ----- -----------
- %10000000 128 $80 modify character
- %01000000 64 $40 modify color
- %00100000 32 $20 modify high-attribute bits
-
- The screen calls that deal with placing characters on the screen refer to
- screen locations using absolute addresses of locations in screen memory. This
- scheme is used for increased efficiency. You can obtain information about the
- absolute screen address of the top left-hand corner of the current window and
- the number of screen addresses between successive rows, to figure out screen
- addresses for your applications. For added convenience, there is a call which
- will accept row and column numbers and return the corresponding absolute
- screen address. Each successive column of a row has an absolute screen
- address that is 1 higher than the previous, for all displays.
-
- The screen-control system calls are as follows:
-
- NAME : winmax
- PURPOSE: set window to maximum size
- ARGS : <none>
- RETURNS: <none>
- ALTERS : .A, .X, .Y
-
- Sets the current window to cover the entire screen.
-
- NAME : winclear
- PURPOSE: clear window
- ARGS : .A = char/color/high-attribute modification flags
- .X = character fill value
- .Y = color fill value
- RETURNS: <none>
- ALTERS : .A, .X, .Y
-
- This call "clears" the current window by filling it with the character/color
- you specify. You can use the char/color/hi-attr to limit what gets cleared.
-
- NAME : winset
- PURPOSE: set dimensions of window
- ARGS : .A = number of rows in window
- .X = number of columns in window
- sw+0 = absolute screen row of top left corner of window
- sw+1 = absolute screen column of top left corner of window
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- Sets the current window to the size you specify. You will get an error return
- if the window will not fit on the screen or of it does not contain at least
- one character.
-
- NAME : winsize
- PURPOSE: return dimensions of window
- ARGS : <none>
- RETURNS: .A = number of rows in window
- .X = number of columns in window
- sw+0 = absolute screen row of top left corner of window
- sw+1 = absolute screen column of top left corner of window
- (sw+2)= screen address of top left corner
- (sw+4)= screen address increment between successive rows on screen
- ALTERS : <none>
-
- Returns information about the current window.
-
- NAME : winput
- PURPOSE: put characters and color onto screen
- ARGS : (sw+0)= absolute screen address to start putting data at
- (sw+2)= character string pointer
- .X = length of character string
- .Y = color
- .A = char/color/high-attribute modification flags
- sw+4 = fill character
- sw+5 = total field length
- RETURNS: <none>
- ALTERS : .A, .X, .Y
-
- Puts text onto the screen. The output region is given by the absolute
- starting screen address and the total field length. This region must be
- contained on one line of the current window, or bad things will happen. A
- pointer to the characters to be printed is given, as well as the length of the
- character array. Control characters in this string are ignored; they are
- poked literally onto the screen, including the null character. The length of
- the character string must be less than or equal to the total length of the
- field. Remaining spaces in the field will be filled in with the "fill
- character".
-
- The color of the total field length will be filled in with "color". You can
- use the "char/color/hi-attr" modification flags to specify what is to be
- changed. If you were to, for example, specify that the colors of the field
- are not to be changed, then the call would execute faster.
-
- NAME : wincolor
- PURPOSE: set screen and border colors
- ARGS : .X = new RGBI screen color
- .Y = new RGBI border color
- .A = which colors to change ($80=screen + $40=border)
- RETURNS: .X = resulting RGBI screen color
- .Y = resulting RGBI border color
- ALTERS : .A
-
- Sets the color of the screen and border. You may optionally set one, the
- other, both, or neither. The resulting colors for colors changed, and the
- existing colors for colors unchaned will be returned. Note that not all
- screens have an adjustable color, so the border argument may be ignored.
-
- NAME : winpos
- PURPOSE: return screen address of given row and col
- ARGS : .A = row
- .X = column
- RETURNS: (sw+0)= screen memory address of position
- ALTERS : .A, .X, .Y
-
- Given a row and column in the current window, returns the corresponding
- absolute screen memory location for use with other calls. No errors are
- returned, so garbage in, garbage out.
-
- NAME : wincursor
- PURPOSE: activate/deactivate cursor
- ARGS : (sw+0)= screen address to place cursor
- .A = enable flag ($ff=cursor-on / $00=cursor-off)
- .Y = color to show cursor in
- RETURNS: <none>
- ALTERS : .A, .X, .Y
-
- Displays or undisplays the cursor at the given screen address. This call
- returns immediately in either case. No errors are returned. Do not display
- anything in or scroll the window while the cursor is being displayed, do not
- display the cursor twice, and do not undisplay the cursor twice in a row or
- bad things will happen. Also, make sure you give the same address when
- undisplaying the cursor as you did when displaying the cursor. When the
- system starts, the cursor will be in its undisplayed state (duh!). You also
- get to specify the color you want the cursor to be shown in. The
- high-attribute bits of this color are ignored.
-
- NAME : winscroll
- PURPOSE: scroll window
- ARGS : .A = flags: char/color/hi-attr + $08=up + $04=down
- .X = number of rows to scroll up/down
- sw+4 = fill character
- .Y = fill color
- RETURNS: <none>
- ALTERS : .A, .X, .Y
-
- Scrolls the contents of the current window up or down. You can scroll any
- number of rows at a time. After scrolling, the bottom (or top) rows will be
- filled with the fill character and color. You can limit whether the
- characters and/or colors are to be scrolled by using the "flags" byte in the
- usual way. Scrolling only the characters, for example, will be twice as fast
- as scrolling both characters and attributes. Whether to scroll up or down is
- specified also using bits in the "flags" field, as indicated in the input
- arguments above. You can specify scrolling in more than one way, and the
- result will be to scroll in each specified direction in turn, in the order up,
- then down. In the future, scrolling left and right may be added to this call.
- [Note: in Release #10, scrolling the screen downward is not implemented.]
-
- 2.4.5. CONSOLE CALLS
-
- The calls in this section refer to the system "console", which includes the
- screen and keyboard. The screen-related calls are at a higher level than the
- calls in the previous section.
-
- NAME : conread
- PURPOSE: read input line from console
- ARGS : (zp) = pointer to buffer to store data into
- .AY = maximum number of bytes to read
- RETURNS: .AY = (zw) = number of bytes actually read in
- .ZS = EOF reached flag
- ALTERS : .X
-
- Same as the "read" system call, except this always reads from the console, and
- there are no errors.
-
- NAME : conwrite
- PURPOSE: write data to console
- ARGS : (zp) = data to print
- .AY = bytes of data to print
- RETURNS: <none>
- ALTERS : .A, .X, .Y, errno
-
- Same as the "write" system call, except this always writes to the console, and
- no errors are possible.
-
- NAME : conputchar
- PURPOSE: write character to console
- ARGS : .A = character
- RETURNS: <none>
- ALTERS : .A, .X, .Y, errno
-
- Write a single character to the console. Control characters are interpreted
- as per usual. The control characters are as follows:
-
- CODE(hex) CODE(dec) NAME DESCRIPTION
- --------- --------- ---- -----------
- $07 7 BEL ring the bell
- $09 9 TAB move cursor to next 8-char tab stop
- $0a 10 LF move cursor to beginning of current line
- $0d 13 CR go to start of next line
- $14 20 BS non-destructive backspace
- $93 147 CLR clear the screen
-
- NAME : conputlit
- PURPOSE: write literal character to console
- ARGS : .A = character
- RETURNS: <none>
- ALTERS : .A, .X, .Y, errno
-
- Same as the "conputchar" system call, except that control characters are not
- interpreted.
-
- NAME : stopkey
- PURPOSE: check if stop key is being held down
- ARGS : <none>
- RETURNS: .CS = stop key pressed
- ALTERS : .A, .X, .Y, errno
-
- Indicates whether the STOP (RUN/STOP) key is currently being held down by the
- user. If so, carry flag is set on return (and clear if not). If the stop key
- is discovered to be pressed by this call, then the keyboard buffer will also
- be cleared.
-
- NAME : getkey
- PURPOSE: get a key code from the keyboard buffer
- ARGS : <none>
- RETURNS: .A = keyboard character
- ALTERS : .X, .Y
-
- Waits for the user to type a key (or takes a previous keystroke from the
- keyboard buffer). Regular characters are returned in their regular PETSCII
- codes, but there are many special control keystrokes. I still haven't figured
- out what all of the special codes should be, but all 256 possible character
- values will be covered. Special codes like "page up", etc. should help in
- standardizing control keystrokes for applications. Note that these
- definitions of keycodes is only suggested; your full-screen application can
- interpret them however it wants. The key code is returned in the accumulator.
- No errors are possible.
-
- The tables below summarize the meanings of the various key codes. Not all of
- the C64 keys have been decided yet. Note that the keys for "@" to "_", used
- in association with shifting keys, are "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_".
- "CT" means Control, "SH" means Shift, "AL" means Alternate, and "CO" means
- Commodore. I haven't decided how to define Alternate on a C64 yet.
-
- CODE(s) C128 KEY(s) C64 KEY(s) DESCRIPTION
- ------- ------------ ------------ -----------
- $20-$3f SPACE to "?" SPACE to "?" Regular numbers and punctuation
- $40-$5f "@" to "_" "@" to "_" Regular lowercase letters
- $60-$7f AL-@ to AL-_ <undecided> Alternate keys
- $a0-$bf CO-@ to CO-_ CO-@ to CO-_ Commodore keys
- $c0-$df "`" to HOUSE "`" to HOUSE Regular uppercase letters
- $e0-$ef CT-@ to CT-_ CT-@ to CT-_ Control keys
-
- CODE(s) C128 KEY(s) C64 KEY(s) DESCRIPTION
- ------- ------------ ------------ -----------
- $00 <none> <none> <cannot be generated>
- $01 CT-RETURN CT-RETURN EOF
- $02 SH-TAB <undecided> Backtab
- $03 STOP STOP Stop some operations
- $04 SH-HELP <undecided> Context-insensitive help
- $05 CT-2 CT-2 White
- $06 SH-LEFT <undecided> Word left
- $07 SH-LINEFEED <undecided> <undecided>
- $08 CO-DEL CO-DEL Rubout character under cursor
- $09 TAB <undecided> Tab
- $0a LINEFEED <undecided> Linefeed
- $0b SH-RIGHT <undecided> Word right
- $0c CO-UP <undecided> Goto top of document
- $0d RETURN RETURN Return
- $0e SH-ESCAPE <undecided> <undecided>
- $0f CO-DOWN <undecided> Goto bottom of document
- $10 CO-LEFT <undecided> Goto beginning of line
- $11 DOWN DOWN Cursor down
- $12 CT-9 CT-9 Rvs
- $13 HOME HOME Home
- $14 DEL DEL Backspace
- $15 CO-RIGHT <undecided> Goto end of line
- $16 CT-UP <undecided> Page up
- $17 CT-DOWN <undecided> Page down
- $18 CT-TAB <undecided> <undecided>
- $19 CT-LEFT <undecided> Page left
- $1a CT-RIGHT <undecided> Page right
- $1b ESCAPE <undecided> Escape
- $1c CT-3 CT-3 Red
- $1d RIGHT RIGHT Cursor right
- $1e CT-6 CT-6 Green
- $1f CT-7 CT-7 Blue
-
- CODE(s) C128 KEY(s) C64 KEY(s) DESCRIPTION
- ------- ------------ ------------ -----------
- $80 CT-F1 CT-F1 Function key 9
- $81 CO-1 CO-1 Orange/Purple(?)
- $82 CT-F3 CT-F3 Function key 10
- $83 SH-STOP SH-STOP <undecided>
- $84 HELP <undecided> Context-sensitive help
- $85 F1 F1 Function key 1
- $86 F3 F3 Function key 3
- $87 F5 F5 Function key 5
- $88 F7 F7 Function key 7
- $89 SH-F1 SH-F1 Function key 2
- $8a SH-F3 SH-F3 Function key 4
- $8b SH-F5 SH-F5 Function key 6
- $8c SH-F7 SH-F7 Function key 8
- $8d SH-RETURN SH-RETURN <undecided>
- $8e CT-F5 CT-F5 Function key 11
- $8f CT-F7 CT-F7 Function key 12
- $90 CT-1 CT-1 Black
- $91 UP UP Cursor up
- $92 CT-0 CT-0 Rvs off
- $93 SH-HOME SH-HOME Clear screen
- $94 SH-DELETE SH-DELETE Insert one space
- $95 CO-2 CO-2 Brown
- $96 CO-3 CO-3 Light red
- $97 CO-4 CO-4 Dark gray
- $98 CO-5 CO-5 Medium gray/dark cyan(?)
- $99 CO-6 CO-6 Light green
- $9a CO-7 CO-7 Light blue
- $9b CO-8 CO-8 Light gray
- $9c CT-5 CT-5 Magenta
- $9d LEFT LEFT Cursor left
- $9e CT-8 CT-8 Yellow
- $9f CT-4 CT-4 Cyan
-
- NAME : concolor
- PURPOSE: set the console main text and cursor colors
- ARGS : .A = which colors to modify: $02=character + $01=cursor
- + $20=modify high-attributes of colors
- .X = new RGBI character color
- .Y = new RGBI cursor color
- RETURNS: .X = resulting character color
- .Y = resulting cursor color
- ALTERS : .A
-
- Sets the character and cursor colors to be used by the console for the "read"
- and "write" system calls that refer to files opened to the console device. You
- can use the flags argument to limit what gets changed.
-
- NAME : conpalette
- PURPOSE: get standard color palette for current screen
- ARGS : <none>
- RETURNS: sw+0 = main character color
- sw+1 = cursor color
- sw+2 = status character color
- sw+3 = separator character color
- sw+4 = highlight character color
- sw+5 = alert character color
- sw+6 = screen border color
- sw+7 = screen background color
- ALTERS : .A, .X, .Y
-
- Returns the palette of colors that are recommended to be used in applications.
- These colors are chosen by the user in the system configuration, so they can
- be interpreted as being what the user wants and expects applications to use. A
- different selection is made by the user for each different screen type, and
- the palette returned will be for the screen type currently in use. The
- high-attribute bits of these colors are valid. Eight colors are included in
- the palette, and you may interpret their meaning according to the application.
- The suggested usages are given in the return arguments listed above.
-
- NAME : conscreen
- PURPOSE: set the screen size
- ARGS : .A = number of text rows required, minimum
- .X = number of text columns required, minimum
- RETURNS: .A = number of text rows you get
- .X = number of text columns you get
- .CS = error occurred flag (requested size cannot be given)
- ALTERS : .Y, errno
-
- This call selects an appropriate display device, screen, and layout for
- displaying text. You ask for the minimum number of rows and columns you
- require on the screen, and the call returns to you what you receive. If the
- system cannot match your minimum requirements, an error will be returned, and
- the current screen will be unchanged. The clock speed of the processor will
- be changed to match the screen selected, if appropriate. If you pass either
- number of rows or columns as 0, then the system default value for the current
- screen type will be used. If you pass either parameter having value 255, then
- the system will use the maximum possible value.
-
- NAME : conpos
- PURPOSE: set cursor location
- ARGS : .A = row
- .X = column
- RETURNS: .CS = error encountered flag
- ALTERS : .A, .X, .Y
-
- This call will set the screen location that the next console "read" or "write"
- system call will operate from. If the "cursor" position is outside the
- boundaries of the current window on the screen, an error will be returned.
-
- 2.4.6. PROCESS CONTROL CALLS
-
- This section describes calls that are used to control the execution of
- processes (active programs). From within one program, you can call for the
- execution of another program, have it execute, and then return to the calling
- program. Since only one program is allowed in memory at a time, some special
- problems arise.
-
- NAME : exec
- PURPOSE: execute external program as a child process
- ARGS : (zp) = program name of executable
- (zw) = start address of argument vector
- .AY = number of arguments
- [mp] = pointer to far memory volatile storage
- RETURNS: .A = exit code
- .X = number of bytes in "aceExitData" used
- (zp) = given argument count
- (zw) = given argument vector pointer
- [mp] = pointer to far memory volatile storage
- .CS = error occurred flag
- ALTERS : .Y, errno
-
- Calling this routine will cause a new "frame" to be set up on the "system
- stack" (lowering the available application area memory a little), the
- specified program to be loaded into memory over top of the current one, the
- new program to be executed, the old program to be reloaded from whatever disk
- unit it came from originally upon exit of the new program, and control to be
- returned to the old process with the return values from the executed program.
- This is a complicated procedure and many things can go wrong.
-
- The first thing that a process that wants to call another program must do is
- set up the arguments to be passed in. All arguments must be null-terminated
- strings. These arguments are to be put into high memory, starting from one
- less than the location pointed to by "aceMemTop" and working downward. It
- does not matter in which order the strings are placed, as long as they are all
- grouped together. Then, immediately below the strings comes the vector of
- two-byte RAM0 pointers that point to the strings. This array must be in
- order, with the lowest entry pointing to the first (zero subscript) string,
- etc., the second highest entry pointing to the last string, and the highest
- entry containing the value $0000. An asciigram follows:
-
- HIGHER ADDRESSES
- | |
- | | <--(aceMemTop)
- +-----------+
- | |
- | string |
- | | : collection of null-terminated strings
- | contents |
- | |
- | |
- +-----------+
- | $0000 | : argv[N] : null argument pointer
- +-----------+
- | strptrN-1 | : argv[N-1]
- +-----------+
- | strptrN-2 | : argv[N-2]
- +-----------+
- . .
- . .
- +-----------+
- | strptr 1 | : argv[1] : first actual argument
- +-----------+
- | strptr 0 | <--(zw) : argv[0] : filename of program to be executed
- +-----------+
- | |
- LOWER ADDRESSES
-
- The first entry should indicate the filename or command name of the program
- being executed, and the subsequent arguments are the actual input arguments to
- the program being called. The address of the first argument vector table
- entry is loaded into (zw), and the number of arguments is loaded into .AY.
- Note that this value also includes the command name, so if, for example, you
- were to call program "wc" to count two filenames "hello" and "goodbye", then
- you would pass an argument count of 3. The name pointed to by "argv[0]" does
- not actually have to be the literal command name, but the one pointed to by
- (zp) does. If a relative executable name is given in (zp), then the search
- path will be used to locate the executable. Oh, don't screw up the
- organization of the arguments or bad things will happen; there is no structure
- checking.
-
- After setting up the arguments, you'll want to set up any redirections of
- stdin, stdout, or stderr you'll be needing. Because there is only one open
- file table in the whole uni-tasking system, you'll have to manipulate existing
- entries using the "fdswap" system call described earlier. The open file table
- is inherited by the child process. Note that if it closes any of the open
- files it inherited, then they are also closed to your use also. If the child
- accidentally leaves open any files it opened, they will be closed by the
- system before you are reactivated.
-
- Finally, before the call is made, you have to save any volatile local
- information into "far" memory. All application zeropage and application area
- memory will be modified by the called program, so you must save whatever you
- will need to continue after the return to be able to continue. As mentioned
- earlier, all of the "far" memory that a parent program owns will be safe, so
- you can save your volatile information there, in any format you wish. All you
- have to do is save the pointer to the far memory into the [mp] pointer. Upon
- return of the child process, the value you put into [mp] will be restored, and
- you can then restore your volatile information out of far storage. If you
- wish to save no volatile information, then you can just leave garbage in the
- [mp] value, since it will not be interpreted by the system.
-
- Alright, so now you call the "exec" primitive, the child program is loaded,
- executed, and it returns.
-
- At this time, the parent program (that's you) is reloaded from wherever it was
- loaded originally and you are returned to the instruction immediately
- following the "jsr exec", with your processor stack intact but the rest of
- your volatile storage invalid. Even if there is an error return (carry flag
- set), your volatile storage will still need to be restored, since the
- application area may have been overwritten before the error was discovered.
- In the case of an error return, the child process will not have been executed.
- If the system is unable to reload the parent program (you), then an error
- return is given to your parent, and so on, as far back as necessary. (This is
- a minor exception to the rule that an error return indicates that a child
- didn't execute; in this case, the child didn't complete).
-
- You are also returned an "exit code", which will have application-specific
- meaning, although standard programs (e.g., shell script) interpret the value
- as: 0==normal exit, anything else==error exit. The X register is also set to
- indicate the amount of "aceExitData" that is used, to allow for more
- complicated return values. [Note: this call is still not implemented in
- Release #10.]
-
- NAME : execsub
- PURPOSE: execute internal subroutine as a separate process
- ARGS : (zp) = address of subroutine
- (zw) = address of argument vector
- .AY = argument count
- [mp] = far memory pointer
- RETURNS: .A = exit code
- .X = number of bytes in "aceExitData" used
- (zp) = given argument count
- (zw) = given argument vector pointer
- [mp] = given far memory pointer
- .CS = error occurred flag
- ALTERS : .Y, errno
-
- This call is very similar to "exec", except that it calls an internal
- subroutine rather than an external program. Thus, you don't have to save or
- restore your volatile storage, or worry about loading the child or reloading
- the parent. You do, however, set up the arguments and file redirections as
- you would for a full "exec".
-
- NAME : exit
- PURPOSE: exit current program, return to parent
- ARGS : .A = exit code
- .X = number of bytes in "aceExitData" used
- RETURNS: <there is no return, brah-ha-ha-ha-ha-ha!!!>
- ALTERS : <don't bloody well matter to you>
-
- This call causes the current program to exit back to its parent. A program
- that exits simply by returning to its environment will give back an exit code
- of 0, which should be interpreted as a normal return. If you wish to indicate
- a special return, you should use some exit code other than zero. Many
- utilities will interpret non-zero error codes as actual errors and may abort
- further operations because of this.
-
- You may set up a return data in "aceExitData", up to 255 bytes worth, and load
- the number of bytes used into .X if you wish. It is recommended that the
- first field of this data be a special identifier code so programs that cannot
- interpret your data will not try. You cannot give any far pointers in your
- return data, since all far memory allocated to you will be freed by the system
- before returning to your parent.
-
- NAME : memstat
- PURPOSE: get "far" memory status plus process id
- ARGS : .X = zero-page address to store status information
- RETURNS: .A = current process id
- [.X+0]= amount of "far" memory free
- [.X+4]= total amount of "far" memory
- ALTERS : .X, .Y
-
- This call returns the current process id, the number of bytes of far memory
- currently free, and the total amount of far memory.
-
- 2.4.7. MISCELLANEOUS CALLS
-
- NAME : utoa
- PURPOSE: convert unsigned 32-bit number to a decimal PETSCII string
- ARGS : .A = minimum length for return string
- .X = zero-page address of 32-bit number
- (zp) = pointer to string buffer to store string
- RETURNS: .Y = length of string
- ALTERS : .A, .X
-
- This is a utility call in the kernel. It is really not necessary for it to be
- in the kernel, but so many programs make use of it that it makes sense for it
- to be factored out. You give a pointer to a 32-bit unsigned value in zero
- page memory, a pointer to a buffer to store that string that is at least as
- long as necessary to store the value plus the null-character terminator that
- will be put on the end of the string, and a minimum length value for the
- string. If the number requires fewer digits than the minimum length, the
- string will be padded with spaces on the left. Since a 32-bit quantity can
- only contain an maximum of ten decimal digits, the string buffer will only
- need to be a maximum of eleven bytes in size.
-
- NAME : getdate
- PURPOSE: get the current date and time
- ARGS : (.AY) = address of buffer to put BCD-format date into
- RETURNS: <none>
- ALTERS : .A, .X, .Y
-
- Returns the current date and time in the BCD format described in the paragraph
- on "aceDirentDate". It puts it into the at-least-eight-byte storage area
- pointed to by (.AY).
-
- NAME : setdate
- PURPOSE: set the current date and time
- ARGS : (.AY) = address of date in BCD format
- RETURNS: <none>
- ALTERS : .A, .X, .Y
-
- Sets the current date and time in the system. (.AY) points to the BCD date
- string whose format is discussed in the paragraph on "aceDirentDate". No
- validity checking is performed on the date given.
-
- NAME : cmdopen
- PURPOSE: open command channel to Commodore disk drives
- ARGS : (zp) = device name
- RETURNS: .A = file descriptor number
- .CS = error occurred flag
- ALTERS : .X, .Y, errno
-
- This "cmd" set of system calls really should not be present, but they will be
- needed until the full complement of disk-utility system calls are implemented.
- It is really not recommended that any application program rely on these calls
- being around very long. This call opens the command channel on the named
- device (standard ACE device name string) and returns the file descriptor
- number to use thereafter.
-
- NAME : cmdclose
- PURPOSE: close command channel to Commodore disk drives
- ARGS : .A = file descriptor number
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- This closes an opened command channel to a disk drive. Closing the status
- will NOT affect any other open files on the disk unit at the time.
-
- NAME : cmdsend
- PURPOSE: send command over command channel to Commodore disk drives
- ARGS : .X = file descriptor number
- (.AY) = pointer to null-terminated command string
- RETURNS: .CS = error occurred flag
- ALTERS : .A, .X, .Y, errno
-
- This sends a command string to a disk drive. Since a null-terminated string
- representation is used, not all Commodore/CMD-DOS commands can be sent, but
- the important ones can be.
-
- NAME : cmdstatus
- PURPOSE: receive current status from command channel of Commodore disk drives
- ARGS : .X = file descriptor number
- (.AY) = pointer to buffer for null-terminated status string
- RETURNS: .A = status code in binary
- .CS = error occurred
- ALTERS : .X, .Y, errno
-
- This returns the status of a disk drive in a string as well as the binary disk
- status number in the accumulator. The given status buffer must be at least 50
- or so characters long (whatever is the longest possible disk status string).
-
- 3. USER PROGRAM ORGANIZATION
-
- The ACE system itself is written using the Buddy-128 assembler, so it is
- recommended that applications be written in this also. User programs for ACE
- have a very simple structure. Here is the standard "hello, world" example
- program written in Buddy assembler for ACE:
-
- -----=-----
- .seq acehead.s
- .org aceAppAddress
- .obj "@0:hello"
-
- jmp main
- .byte aceID1,aceID2,aceID3
- .byte 64,0
-
- main = *
- lda #<helloMsg
- ldy #>helloMsg
- sta zp+0
- sty zp+1
- lda #<helloMsgEnd-helloMsg
- ldy #>helloMsgEnd-helloMsg
- ldx #stdout
- jsr write
- rts
-
- helloMsg = *
- .asc "Hello, cruel world."
- .byte 13
- helloMsgEnd = *
- -----=-----
-
- This would normally be put into a file called "hello.s". The ".s" extension
- means that this is an assembler file (a la Unix). The first thing this
- program does is include the "acehead.s" file. This is the Buddy assembler
- file that contains the header information declarations required to access the
- ACE system interface. The next line gives the start address to start
- assembling to; it must be "aceAppAddress", which is the address that ACE will
- load the program at. The next line is a directive to the assembler to write
- the executable code to a Commodore-DOS "PRG" file named "hello". This will be
- the command to enter at the ACE shell prompt.
-
- The next eight bytes of object code (which are the first eight bytes of a
- loaded program) describe the header required by ACE programs. The first three
- bytes must be a JMP to the main routine of the program. The next three bytes
- must have the values "aceID1", "aceID2", and "aceID3", respectively. The next
- two bytes are the minimum stack requirements and flags, respectively. The
- stack requirement is for the processor stack, and ACE will make sure your
- program has at least this much space before your program starts. The flags
- field is currently undefined, but you must give it a value of 0. And that's
- all there is to it. The rest of the program can be organized however you want
- it to be.
-
- In this example, we set up the arguments for the "write" system call to print
- the string "Hello, cruel world." plus a carriage return to standard output.
- Note that this string does not need a terminating null ($00) character since
- the write call takes a buffer length. The program then returns to its calling
- environment via an RTS. This will cause an implied "exit(0)" to be performed
- by the system, returning to the parent program.
-
- Although this program does not take advantage of this, an application program
- may use zero-page locations $0002 through $007f for storage without fear of
- having the storage trodden upon by the system.
-
- Finally, an application program starts at location "aceAppAddress" (plus six)
- and is allowed to use memory all the way up to one byte less than the address
- pointed to by "aceMemTop" for its own purposes. Currently, this amount of
- space is on the order of magnitude of about 20K. This will be increased in
- the future.
-
- Application programs are not to access I/O features or even change the current
- memory configuration during execution. All I/O and other unusual contortions
- must be performed by ACE system calls; otherwise, we could end up in as bad a
- shape as MESS-DOS.
-
- 4. CONCLUSION
-
- Cool, eh?
- -----------------------------------------------------------------------=END=--
-