home *** CD-ROM | disk | FTP | other *** search
-
- 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: this call is not
- implemented in Release #9].
-
- 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: this
- call is not implemented in Release #9].
-
- 2.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
- 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
- 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
- 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
- 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
- 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
- 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 : .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. 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 character codes
- are the same as the foreground character 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.
-
- The screen-control system calls are as follows:
-
- NAME : winmax
- ARGS : <none>
- RETURNS: <none>
- ALTERS : .A, .X, .Y
-
- Sets the current window to cover the entire screen.
-
- NAME : winclear
- 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. [Note: The arguments for this call are slightly
- different in Release #9].
-
- NAME : winset
- 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. [Note: This call is not implemented in
- Release #9].
-
- NAME : winsize
- 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. [Note: the arguments are
- slightly different in Release #9].
-
- NAME : winput
- 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
- 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
- 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
- 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
- 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: The arguments and
- semantics of this call are a little different in Release #9].
-
- 2.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 : stopkey
- 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
- 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. They are
- not listed here (yet) because I 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. The key code is
- returned in the accumulator. No errors are possible.
-
- NAME : concolor
- ARGS : .A = which colors to modify: $02=character + $01=cursor
- + $80=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. [Note: flags argument is slightly different in Release #9].
-
- NAME : conpalette
- 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
- 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.
-
- NAME : conpos
- 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. [Note: this function is not implemented in Release
- #9].
-
- 2.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. Also, only rudimentary versions of
- these system calls are implemented in Release #9 and I haven't decided
- completely how they should work. So, this section is a bit tentative.
-
- 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
- [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 different in Release #9].
-
- NAME : execsub
- PURPOSE: execute internal subroutine as a separate process
- ARGS : (zp) = address of subroutine
- (zw) = address of argument vector
- RETURNS: .A = exit code
- .X = number of bytes in "aceExitData" used
- .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". [Note: this call is
- different in Release #9].
-
- 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>
-
- 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 : <none>
- RETURNS: .A = current process id
- [sw+0]= amount of "far" memory free
- [sw+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.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
- (sw+0)= 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
-
- 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 six bytes of object code (which are the first six bytes of a
- 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. 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. Also,
- the processor stack may be used from the point it was at upon entry to
- your program all the way down to the bottom. I will be doing something
- about ensuring there is always enough processor space for an application
- to use in the future, but for now, all applications have to share the
-