💾 Archived View for mirrors.apple2.org.za › archive › apple.cabi.net › System › GSOS.P8.Anatomy › SY… captured on 2024-02-05 at 14:49:13.

View Raw

More Information

⬅️ Previous capture (2023-01-29)

-=-=-=-=-=-=-

Pro

A system program is simply an assembly-language program, requiring the resources of
GS/OS or ProDOS 8, that communicates directly with users. It is generally a primary
application like a word processor, spreadsheet, or telecommunications program or a
programming environment for languages like C, BASIC, or Pascal.

Under ProDOS 8, a system program takes control of the entire Apple II memory
space, except for the portion ProDOS 8 uses, and is responsible for managing it
properly. This space includes the 64K main memory bank in all Apple IIs and the 64K
auxiliary memory bank in a IIc, IIcs, or lIe with an extended 80-column text card.

Under GS/OS, a system program must use the 1Ics Memory Manager to allocate
blocks of memory it may need. Since the Memory Manager allocates only blocks that
are not in use, the system program will peacefully co-exist with other programs that
may be in memory at the same time.

The operating system identifies a system program by inspecting its file type code. A
ProDOS 8 system program has a file type code of $FF and a directory mnemonic of
SYS. A GS/OS system program has a file type code of $B3 and a directory mnemonic
of 516. But assigning a file type code of $B3 or $FF to a program file is not enough to
convert it to a true system program. As we see, a system program must also follow
certain software conventions and take care not to interfere with memory areas used by
the operating system or other co-resident programs.
In this chapter, we review the features of well-designed GS/OS and ProDOS 8
system programs. We then examine one very common, and very important, ProDOS 8
system program, BASIC.SYSTEM. The discussion of BASIC.SYSTEM is quite de-
tailed: We see how it installs itself in the system, how it calls ProDOS 8 commands,
how its command set can be extended, and how it handles errors. We also take a close
look at the global page it uses to manage the communication between ProDOS 8 and
Applesofi programs. The analysis of BASIC.SYSTEM should assist you in creating
your own ProDOS 8 system programs.

219

THE STRUCTURE OF A GS/OS SYSTEM PROGItAM
To be considered a true GS/OS system program, a program must possess four -
properties.

1. The executable code for the program must be in 65816/6502 assembly'
and it must be stored to disk as a load file in Apple's object module format
This is not to say you cannot use a high-level language like C, Pascal, or r: a
create a system program. You can as long as the language compiler creates
assembly-language object code. The Apple Programmer's Workshop linker
care of creating load files for you, as does the linker for Merlin 8/16.

2. The program must have a file type code of $B3. You can use the Apple
mer's Workshop FILETYPE command to set the file type after compiling
linking an application. By assigning the $B3 file type code, you can execute
programs directly from the Apple Itcs Finder.

3. The program must use the IIcs toolbox's Memory Manager tool set to allocate
blocks of memory it may need. By using the Memory Manager, the program
avoid overwriting memory areas used by other co-resident programs, such as
accessories, printer drivers, or interrupt handlers.

4. The program must end using the GS/OS Quit command. It can use the
command to return to the system program that called it (usually the Finder) or
call another system program as if it were a subroutine, regaining control when
other system program ends. (See Chapter 4 for a discussion of the Quit command.)

In general, you can assign any valid name to a system program. If you want to create
a disk that automatically boots and rnns the system program, you should assign it a
name that ends in .SYS16, place the program file in the root directory of the disk, and
delete the START program from the SYSTE M/ subdirectory. Alternatively, you can
name the system program START and put it in the SYSTEM/ subdirectory.

Entry Conditions

GS/OS launches a system program by first loading it into memory using the System
Loader tool set's InitialLoad function. It then uses the Memory Manager to allocate a
direct page/stack space for use by the system program.

The size of the direct page/stack space depends on whether the program includes a
direct page/stack object segment. If it doesn't (the usual case for most applications
you re likely to develop), GS/OS uses the Memory Manager's NewHandle function to
allocate a 4096-byte space in bank $00, which begins on a page boundary. (The other
important Memory Manager attributes of the block are: locked, fixed, purge level 1,
may use special memory, and no fixed starting address.)

220 System Programs

If the program file does include a direct page/stack object segment, GS/OS allo-
cates a direct page/stack space that is the same size as the object segment. (See
Chapter 7 of the Apple II&s Programmer's Workshop Reference for how to create a
direct page/stack object segment.)

In either situation, GS/OS sets the A (accumulator), D (direct page), and SP (stack
pointer) registers to the following values before passing control to the program:

A = the User ID the System Loader assigns to the program.
D = the address of the first byte in the direct page/stack space.
SP = the address of the last byte in the direct page/stack space.
Note that the stack occupies the upper end of the direct page/stack space. Since the
stack grows downward in memory, it may eventually collide with the portion of the
space used for direct page storage. It is the responsibility of the application to ensure
it allocates enough direct page/stack space to prevent such a collision.
The direct page/stack space that the System Loader automatically sets up is made
purgeable when the system program ends by calling the Quit command. This means
the application does not have to explicitly release this memory with the DisposeHandle
function before ending.

Your system program can also allocate a direct page/stack space on the fly at
execution time. To do this, it should first call DisposeHandle to free up the space the
System Loader allocates. Use FindHandle to determine the handle to this space; the
high word of the long address that FindHandle requires is $0000; the low word is the
value stored in the D or SP register. Here is a piece of code that will do the trick:

PHA Space for result (long)
PHA

PEA $0000 High word of addr is always zero
PHD ;Low word of addr in dp/stack space
FindHandle ;(leave handle on stack)
DisposeHandle

The program must then use NewHandle to allocate the direct page/stack space it
requires (the Memory Manager attributes for this space should be as described earlier
in this section), and then put the starting address of the block in the D register and the
ending address in the SP register. Here is a subroutine that performs these chores
(UserID is a variable that holds the program's master user ID):

DP_Hndl GEQU $00
PHA
PHA

PushLong #$8O0
PushWord UserID

;(Assume $00 is free)
Space for result
;2K space

;Use program's user ID

The Structure of a GS/OS System Program 221

PushWord #$C105 ;Attributes
PushLong #$O0O0OO00 ;(Any bank $00 address)
NewHandle

PLA ;Pop handle
STA DP Hndl
PLA

STA DP Hndl+2

LDA [DP_Hndl] ;Get absolute address
TCD Set up new direct page

CLC ;Calculate address of
ADC #$800 ;the last byte in space
DEC A
TAX

TXS Set up new stack ptr
RTS

Note that the user ID for the direct page/stack memory block should be set to the system
program's master user ID so that the block will be automatically discarded when the
system program ends. The master user ID is in the A register when the system program
starts up; the Memory Manager's MMStartup function returns the same value.

THE STRUCTURE OF A PRODOS 8 SYSTEM PROGRAM
A properly designed ProDOS 8 system program is an executable assembly-language
program adhering to certain conventions and protocols that relate to its internal
structure and the way it takes control of the system.

First, a system program must be designed to be loaded and executed beginning at
location $2000 in main memory although it can later relocate itself anywhere else in
memory not used by ProDOS 8 or system Monitor routines. The load address of $2000
is mandatory.
You can use the BASIC.SYSTEM - (dash) command to execute a system program.

It is also possible to automatically execute a system program when ProDOS 8 first
starts up by giving the program a name of the form xxxxxxxx.SYSTEM and ensuring it
is the first entry in the volume directory with such a name.
Some system programs follow an optional auto-run protocol that allows a ProDOS 8
selector program to pass the name of a file to them. (Recall from Chapter 4 that a
selector program gets control when an application calls the QUIT command.) The
standard ProDOS 8 selector program does not allow for filename passing, but many
independent selectors, such as ProSel and RunRun, do. The description of the QUIT
command in Chapter 4 includes instructions on how to write your own selector.

The auto-run protocol is quite simple. If the first byte of the system program
($2000) is $4C (a JMP opcode) and the fourth and fifth bytes ($2003 and $2004) are
both $EE, the sixth byte ($2005) holds the size of a buffer that begins at the very next

222 System Programs

byte. This buffer begins with a name length byte and is followed by the standard
ASCII codes for the characters in the name of a file the system file is to work with
when it first starts up. (A system program file usually has a default filename stored
here.) Thus if the selector program detects the presence of the three identification
bytes, it could prompt the user to enter the name of a data file, load the system
program, store the length and name of the data file beginning at $2006, and then
execute the system program by jumping to $2000.

The BASIC.SYSTEM system program adheres to the auto-run protocol. Here is
what the first part of that program looks like:

JMP START1
DFB $EE
DFB $EE
DFB $41
DFB $07

ASC 'STARTUP'

START1

Must be a JMP instruction
Identification byte 1
Identification byte 2
Size of following buffer
Length of filename
Name of auto-run file

Main program entry point

As you can see, BASIC.SYSTEM defines a default auto-run file called STARTUP. This
is the name of the Applesoft program BASIC.SYSTEM loads and runs whenever it
starts up unless the selector passes a different name.

The selector program ensures that when a system program gets control, its path-
name or partial pathname is stored at $281; location $280 contains the length of the
name. This permits the system program to deduce the precise directory it is located
in. This is helpful for loading subsidiary programs or data files located in the same
directory as the system program itself.

Often, a system program defines an interpretive programming environment in
which application programs can be written and executed. (BASIC.SYSTEM is the best
example of such a program.) In this case, the code for the interpreter should be tucked
away in a safe place that will not conflict with memory areas the application program
can use. The best position for the code is in a contiguous block at the upper end of
main RAM memory, just below the ProDOS 8 global page at $BF00; this leaves the
space from $800 to the start of the code free for use as a work area. The system
program can protect the code space by setting to 1 those bits in the system bit map
corresponding to the pages in use. If this is done, the ProDOS 8 command interpreter
will not allow these areas to be inadvertently used as file buffers or 1/0 buffers. (See
Chapter 3 for a discussion of the system bit map.)

When a system program first gets control, it should perform several preliminary
housekeeping chores.

z Initialize the microprocessor stack pointer. To ensure the maximum amount
of stack space is available to the system program, the stack pointer should be

The Structure of a ProDOS 8 System Program 223

set to the bottom of the stack. This can be done with the following two -
structions:

LDX #$FF
TXS

You should ensure that no more than three quarters of the stack is used at
given time.

z Initialize the reset vector. When reset is pressed on an Apple II,
ultimately passes to the subroutine whose address is stored in the reset -
at SOFTEV ($3F2-$3F3) but only if the number stored at PWREDUP ($3F4)
the same as the number generated by logically exclusive-ORing the number
stored at SOFTEV + 1 with the constant $A5. If PWREDUP is not set up
properly, the system reboots when reset is pressed. To point the reset vector to
a subroutine called RTBAP within the system program and fix up PWREDUP,
execute the following code:

LDA #<RTRAP ;Address low
STA S0FTEV ;$3F2
LDA #>RTRAP ;Address high
STA SOFTEV+1 ;$3F3

EOR #$AS ;twiddle the bits
STA PWREDUP ;$3F4

A general-purpose RTBAP subroutine should close all open files and then jump
to the cold start entry point of the system program. It is not safe to do anything
else because it is impossible for the reset subroutine to determine the state of
the system just before the reset condition becomes active.

z Initialize the version numbers in the ProDOS 8 global page. IBAKVER ($BFFC)
must be set equal to the earliest version of ProDOS 8 the system program will
work with; store a 0 here if any version will do. 1VERSION ($BFFD) must be set
equal to the version number of the system program being used.

When these chores have been completed, the system program can begin its main
duties. If the system program adheres to the auto-run protocol, it must start working
with the file whose name (preceded by a length byte) is stored beginning at $2005.
The system program is then free to do almost anything it wants as long as it does not
overwrite the ProDOS 8 system global page (page $BF) or data areas in other pages
used by ProDOS 8 or system Monitor subroutines the system program might call. (See
Chapter 3 for a discussion of ProDOS 8 memory usage.)

If a system program wants to create special classes of files, it can use any of the
user-definable file type codes, $F1-$F8. All other codes are reserved. (See Table 2-5 in
Chapter 2 for a description of the file type codes ProDOS uses for standard data files.)

When a system program creates a file, it can use the 2-byte auxiliary type code in its
directory entry (at relative bytes $1F and $20; see Chapter 2) to hold miscellaneous

224 System Programs

information about the file. This code is saved to disk when you first create the file with the
CREATE command; you can change it with the SET FILE - INFO command. Here is
the meaning of the auxiliary type code for each type of file BASIC. SYSTEM uses:
BIN default loading address
TXT record length (0 for sequential files)
BAS default loading address (usually $0801)
VAR starting address of a block of variables

When the time comes for the system program to quit, the system program should first
scramble the PWREDUP byte by decrementing it; this causes the system to reboot if
reset is pressed. It should then close all open files and reconnect /RAM if it was
earlier disconnected. (See Chapter 7 for instructions on how to do this.) Finally, it
should pass control to another system program with the QUIT command. As we saw
in Chapter 4, this causes the standard ProDOS 8 selector program to be executed.
Here is what the code will look like:

[close all open files]
[restore /RAM]

DEC $3F4
JSR $BF00
DFB $65

DA PARMTBL
BCS ERROR
BRK

PARMTBL DFB 4
DFB 0
DA 0
DFB 0
DA 0

Scramble PWREDUP byte
;Call the MLI
;QUIT

;(shouldn't get here)
;4 parameters

The selector code is responsible for passing control to another system program in an
orderly manner. The standard ProDOS 8 selector asks you to enter the prefix and
pathname of the next system program to be loaded and executed.

If your ProDOS 8 application is running on a Ilcs, and the bootup operating
system was GS/OS, you can also use QUIT to transfer control directly to another
ProDOS 8 or GS/OS system program. (See the discussion of the QUIT command in
Chapter 4 for how to do this.)

THE BASIC.SYSTEM INTERPRETER

The BASIC.SYSTEM interpreter is probably the most commonly used ProDOS 8
system program. It is the program loaded whenever an Applesoft programming

The BASIC. SYSTEM Interpreter 225

environment is going to be used; it extends the Applesoft command set by ~
group of 32 disk commands an Applesoft program can use. BASIC.SYSTEM
itself by storing the addresses of its internal character input and output subrou
the system Monitor's input link (KSW: $38-$39) and output link (CSW:
(The subroutines whose addresses are stored in these links are called 1
character input or output operation is to be performed.)

The BASIC.SYSTEM input subroutine normally reads input from the current
device (usually the keyboard) and will identify and execute any valid disk c -
entered while the system is in Applesoft command mode. But if a file has pre -
been opened for read operations, it gets its input from the file instead.

Similarly, the BASIC.SYSTEM output subroutine normally sends output to the
output device (usually the video screen) unless a file has been opened to receive
output instead. It is also always on the lookout for argnments of PRINT statements
begin with a [Control-D] code; such argnments are assumed to be BASIC.SYSTEM
commands, and BASIC.SYSTEM tries to interpret them as such. The output "L=
can spot these PRINT statements because BASIC.SYSTEM always operates with
sofi trace mode on; this means line numbers will be sent to the output subroutine
the line is actually executed, giving BASIC. SYSTEM a chance to check any PRINT
ments on that line. (By the way, the line numbers generated in trace mode are not
played by BASIC.SYSTEM unless the Applesofi TRACE command has been

Fignre 5-1 shows a BASIC.SYSTEM memory map. When BASIC.SYSTEM is
loaded, it relocates its command interpreter to the high end of main RAM memory
$9A0~$BEFF &ust below the ProDOS 8 system global page), reserves a 1K
purpose file buffer from $9600 to $99FF, and then sets the Applesofi HIMEM pointer
$7~$74 to $9600. (H1MEM represents the upper limit for storage of Applesofi string
variables.) This leaves the space from $0800 to $95FF free for Applesofi program ~
variable storage.

BASIC.SYSTEM also uses the area between $3D0 and $3EC for storage of
position-independent vectors to some of its internal subroutines. We examine how
BASIC.SYSTEM uses page three in more detail later in this chapter.

The BASIC.SYSTEM interpreter, becausc of its intimate connection to the Apple-
soft ROM interpreter, can also be said to use all those RAM areas used by Applesofi
itself. This includes the input buffer at $200-$2FF (BASIC.SYSTEM also uses most of
this page as a temporary data buffer when it executes certain disk commands), the
microprocessor stack at $10~$1FF, and several locations in zero page. (See Chapter 4
of Inside the Apple lIe for a detailed description of how Applesoft uses these areas.)
Other areas, such as the video RAM area from $400 to $7FF and the system vector
area from $3ED to $3FF, are also reserved for use in a BASIC.SYSTEM environment.

The BAS1C.SYSTEM Commands

Most of the BASIC.SYSTEM disk commands provide convenient access to files for 1/0
operations (OPEN, READ, POSITION, WRITE, APPEND, FLUSH, and CLOSE),
general file management (CAT, CATALOG, CREATE, DELETE, LOCK, PREFIX,

226 System Programs

FigureS-I BASIC. SYSTEM memory map

$BFFF
~EFOOOC

HIMEM $9600
$0800
$0400

0300
0200
0100
0000

(ProDOS 8 global page)
BASIC.$YSTEM global page

~ BAS1C.SYSTEM interpreter
~ General-purpose file buffer
(moves clown by $400 bytes 'v'nen
a file is opened; moves up v'1ien a
file is closed.)

Applesoft program and

variable space

Video RAM

~ $3D0..$3EC used for vectors
Input buffer + data area
6~02 stack

(Much of zero page used)

RENAME, UNLOCK, and VERIFY), or program file loading and execution (-,
BLOAD, BRUN, BSAVE, EXEC, LOAD, RUN, and SAVE). There are also com-
mands for effecting 1/0 redirection (IN# and PR#), to perform garbage collection of
Applesofi string variables (FRE), to save and load Applesoft variables to and from files
(STORE and RESTORE), to transfer control from one Applesoft program to another
without destroying existing variables (CHAIN), and to disconnect BASIC.SYSTEM
and run another ProDOS 8 system program (BYE). One command (NOMON) is
allowed but does nothing; it is included to maintain compatability with programs
running under DOS 3.3 that use NOMON to disable the display of disk commands
and 1/0 operations.

To use a BASIC.SYSTEM command from within a program, you must use the PRINT
statement to print a [Control-D] character, the BASIC.SYSTEM command, the command
parameters, and then a carriage return. For example, to list all the files in the /RAM
volume on an Apple IIc, you would execute a line that looks something like this:

100 PRINT CHR$(4);"CATALOG/RAM"

The BASIC. SYSTEM Interpreter 227

In this example, the CHR$(4) statement generates the [Control-D] character, the
SYSTEM command is CATALOG, and the command parameter is /RAM (a
The required carriage return is automatically generated by the PRINT statement.

If you're entering a BASIC.SYSTEM command directly from the keyboard in
sofr command mode, you don't have to worry about the [Control-D]. All you have to
type in the command followed by the command arguments. The keyboard equi\
the CATALOG command is simply
CATALOG /RAM

You should be aware, however, that BASIC.SYSTEM does not permit all its
mands to be entered from the keyboard in this way.

Most BASIC.SYSTEM commands support, or require, several parameters for _
ifying such things as the pathname for the file to be acted on, loading addresses,
lengths. Table 5-1 gives brief descriptions of the 13 different parameters
by BASIC.SYSTEM.
The letter parameters shown in Table 5-1 (,A#, ,B#, and so on, where # 1

the value of a parameter) can be specified in any order by appending them to the
of the command line. The snum and pathname parameters cannot appear in the
command line. When one of these parameters is specified, it must be placed
ately after the command name. The exception is the RENAME command,
requires two pathnames; the second pathname must appear right after the first one.

Note that most BASIC.SYSTEM commands may be entered with slot (,S#) and -
(,D#) parameters that specif' the physical location of the disk to be accessed. It is not
necessary to use these parameters if the pathname specified is a full pathname or if a
prefix is active because BASIC.SYSTEM will automatically search all installed disk drives
for the file. But if a filename or partial pathname is specified, and no prefix has yet been
defined or either the ,S# or ,D# parameter is used, BASIC.SYSTEM automatically uses
the name of the volume directory specified by the slot and drive parameters (or their de-
fanlts) to create the full pathname. BASIC.SYSTEM's ability to use slot and drive param-
eters allows Applesofi programs to maintain greater compatibility with a DOS 3.3 environ-
ment where the slot and drive must be specified to access disks in the nondefault drive.

Let's now take a quick look at each of the 32 BASIC.SYSTEM commands. Table

5-2 summarizes the command syntax for each of these commands. (See Apple's BASIC
Programming with ProDOS for detailed information on these commands; see the
bibliography in Appendix III.) These commands can be divided into four distinct
categories: file management commands, file loading and execution commands, file
input/output commands, and miscellaneous commands.

File Management Commands

CAT. This command displays a list of the names of the files on the disk. Only the
names of the files in the directory specified in the pathname parameter following the

228 System Programs