Apple /// specific information for cc65

Robert Justice


An overview over the Apple /// runtime system as it is implemented for the cc65 C compiler.

1. Overview

2. Binary format

3. Memory layout

4. Linker configurations

5. Platform specific header files

6. Loadable drivers

7. Standard I/O

8. Other hints

9. Limitations

10. License


1. Overview

This file contains an overview of the Apple /// runtime system as it comes with the cc65 C compiler. It describes the memory layout, the Apple /// specific header files, available drivers, and any pitfalls specific to that platform.

Please note that Apple /// specific functions are just mentioned here, they are described in detail in the separate function reference. Even functions marked as "platform dependent" may be available on more than one platform. Please see the function reference for more information.

2. Binary format

The standard binary file format generated by the linker for the Apple /// target is an SOS interpreter program file. The linker prepends a header that identifies the file to the SOS interpreter. This header has the following layout:

"SOS NTRP"                      ; Interpreter label
.word $0000                     ; Option header length
.word __MAIN_START__            ; Code start address
.word code length               ; Code length

The default load address is $2000. A program is executed by an SOS interpreter, i.e. it must be launched from a system that is able to run SOS program files (the SOS interpreter that is part of the SOS disk system on the Apple /// loads such files at boot time or from the interrupt loop).

The linker configuration sets the default file type of the generated file to $000C (an SOS system file). This can be changed at link time, see the linker configuration section below.

3. Memory layout

In the standard setup, cc65 generated programs use the memory from $2000 to $B7FF, so about 38 KB of RAM are available. The memory below $2000 is used by the SOS interpreter and must not be touched.

Special locations:

Stack

The C runtime stack is located at the top of main memory ($B7FF) and grows downwards, regardless of how your linker config file is setup.

Heap

The C heap is located at the end of the program and grows towards the C runtime stack.

4. Linker configurations

The ld65 linker comes with a default config file for the Apple ///, which is used via -t apple3. The apple3 package currently doesn't contain any additional secondary linker config files.

4.1 Default config file (apple3.cfg)

Default configuration for a program to be executed by an SOS interpreter.

Parameters:

STARTADDRESS: Program start address

$2000. The start address is fixed by the memory layout of the SOS interpreter and cannot be changed.

__EXEHDR__: SOS interpreter header

Default: Yes. Use -D __EXEHDR__=0 to omit the interpreter header.

__FILETYPE__: SOS file type

Default: $000C (SOS system file). Use -D __FILETYPE__=<type> to set a different file type.

__STACKSIZE__: C runtime stack size

Default: $0800. Use -D __STACKSIZE__=<size> to set a different stack size.

5. Platform specific header files

Programs containing Apple /// specific code may use the apple3.h and apple3_filetype.h header files.

5.1 Apple /// specific functions

The functions and variables listed below are special for the Apple ///. See the function reference for declaration and usage.

5.2 File handling

The apple3_filetype.h header is included from apple3.h and defines many SOS/ProDOS file type constants. See Specifying file types for fopen below for an example of how to use them.

5.3 Hardware access

The Apple /// memory is bank switched. The functions xpeek() and xpoke() allow to access memory in any bank by temporarily setting the interpreter extended addressing byte. For assembler programs the hardware register and I/O definitions (VIA ports and timers, keyboard, speaker, video modes, and so on) are available in the apple3.inc include file.

6. Loadable drivers

The names in the parentheses denote the symbols to be used for static linking of the drivers.

6.1 Joystick drivers

a3.stdjoy.joy (a3_stdjoy_joy)

Supports up to two standard joysticks connected to the game controller port. The joystick directions and buttons are read via the SOS GET_ANALOG device call.

7. Standard I/O

The standard I/O streams stdin, stdout and stderr are connected to the console device. Reads from stdin turn the cursor on, echo each character and convert carriage returns to line feeds. Writes to stdout and stderr convert line feeds to carriage returns; the output is written to the console in chunks (single SOS write calls) to speed up the console output.

The console is initialized to 80 columns by default. The screen size can be queried with screensize() and changed with videomode().

Up to 16 files may be open at the same time.

8. Other hints

8.1 exec()

The function exec() terminates the running program and executes another SOS program file. The executed file must have the SOS file type ($000C).

8.2 DIO

Device ID

The function dio_open() has the single parameter device to identify the device to be opened. The Apple /// assigns a device number to each device present in the system. dio_open() fails with _oserror $28 ("No device connected") if the device is invalid or not a block device.

Sector size

The function dio_query_sectsize() always returns 512 bytes, which is the block size used by SOS.

Sector count

The function dio_query_sectcount() returns the total number of blocks of the device, as reported by the SOS Get_Device_Info call.

8.3 Video modes

The function videomode() allows to switch between the text modes of the Apple ///. The following modes are supported:

After a program started the console defaults to 80 columns.

8.4 Specifying file types for fopen

Explanation of File Types

SOS associates a file type and an auxiliary type with each file. These type specifications are separate from the file's name; the file name's suffix (a.k.a. extension) does not specify the file type. The SOS function for creating a file requires these types to be specified.

In contrast, the ISO C function fopen() and the POSIX function open() have no parameter to specify either a file type or an auxiliary type. Therefore, some additional mechanism for specifying the file types is needed.

Specifying the File Type and Auxiliary Type

There are two global variables provided that allow the file type and auxiliary type to be specified before a call to fopen() or open(). They are defined in apple3_filetype.h:

  extern unsigned char _filetype;  /* Default: PRODOS_T_BIN */
  extern unsigned int _auxtype;    /* Default: 0            */
  

The header file apple3_filetype.h also defines many values that can be used to set these variables. It is included in apple3.h.

Example

A text file cannot be created with just the standard C functions because they default to the binary type PRODOS_T_BIN. The _filetype variable must be set to PRODOS_T_TXT to create a text file.

For a text file, _auxtype specifies the record length. A zero record length text file is referred to as a sequential text file. This is equivalent to text files on other operating systems, except that the line terminator is a carriage return instead of a line-feed (Unix) or carriage return, line-feed pair (Windows).

For this example, the _auxtype does not need to be set because it defaults to the desired value, which is zero.

    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    #include <apple3.h>

    void main(void)
    {
        FILE *out;
        char *name = "MY.FAVS";

        /*-----------------------------*/

        _filetype = PRODOS_T_TXT;
        _auxtype  = PRODOS_AUX_T_TXT_SEQ;

        /*-----------------------------*/

        if ((out = fopen(name, "w")) != NULL) {
            fputs("Jorah Mormont\r", out);
            fputs("Brienne of Tarth\r", out);
            if (fclose(out) == EOF) {
                fprintf(stderr, "fclose failed for %s: %s", name, strerror(errno));
            }
        }
        else {
            fprintf(stderr, "fopen failed for %s: %s", name, strerror(errno));
        }
    }
  

9. Limitations

9.1 Command line arguments

The Apple /// does not have any command line support. A program started from an interpreter will always get argc = 0 and argv = NULL, so there is not even an argv[0].

9.2 Direct console I/O

The textcolor() and bgcolor() functions are supported via the SOS console fore- and background color commands. bordercolor() has no effect since the Apple /// has no border color. cpeekcolor() always returns white and cpeekrevers() always returns zero.

9.3 Realtime clock

SOS takes care of setting the file timestamps itself. Therefore the _datetime variable is not used and there are no functions to read a realtime clock.

9.4 Interrupts

There's currently no interrupt/IRQ support for the Apple /// runtime. A program using an .INTERRUPTOR (see the discussion of the .CONDES feature in the assembler manual) will fail to link since no __CALLIRQ__ module is provided for this target.

10. License

This software is provided 'as-is', without any expressed or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.

Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.