mirror of
https://github.com/cc65/cc65.git
synced 2024-12-27 00:29:31 +00:00
700 lines
24 KiB
Plaintext
700 lines
24 KiB
Plaintext
<!doctype linuxdoc system>
|
|
|
|
<article>
|
|
<title>Apple ][ specific information for cc65
|
|
<author><url url="mailto:ol.sc@web.de" name="Oliver Schmidt">
|
|
|
|
<abstract>
|
|
An overview over the Apple ][ runtime system as it is
|
|
implemented for the cc65 C compiler.
|
|
</abstract>
|
|
|
|
<!-- Table of contents -->
|
|
<toc>
|
|
|
|
<!-- Begin the document -->
|
|
|
|
<sect>Overview<p>
|
|
|
|
This file contains an overview of the Apple ][ runtime system
|
|
as it comes with the cc65 C compiler. It describes the memory layout,
|
|
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 <url url="funcref.html"
|
|
name="function reference">. Even functions marked as "platform dependent" may
|
|
be available on more than one platform. Please see the function reference for
|
|
more information.
|
|
|
|
|
|
|
|
<sect>Binary format<p>
|
|
|
|
The standard binary file format generated by the linker for the
|
|
Apple ][ target is an <url name="AppleSingle"
|
|
url="http://kaiser-edv.de/documents/AppleSingle_AppleDouble.pdf"> file.
|
|
The default load address is $803.
|
|
|
|
<bf/AppleCommander 1.4.0/ or later (available at <url
|
|
url="https://applecommander.github.io/">) includes the option <tt/-as/ that
|
|
allows to put AppleSingle files onto disk images containing DOS 3.3 as well
|
|
as ProDOS 8.
|
|
|
|
|
|
<sect>Memory layout<p>
|
|
|
|
In the standard setup, cc65 generated programs use the memory from
|
|
$803 to $95FF, so 35.5 KB of RAM are available.
|
|
|
|
Special locations:
|
|
|
|
<descrip>
|
|
|
|
<tag/Stack/
|
|
The C runtime stack is located at HIMEM and grows downwards, regardless of
|
|
how your linker config file is setup.
|
|
|
|
<tag/Heap/
|
|
The C heap is located at the end of the program and grows towards the C
|
|
runtime stack.
|
|
|
|
</descrip><p>
|
|
|
|
While running <tt/main()/ the Language Card bank 2 is enabled for read access.
|
|
However while running module constructors/destructors the Language Card is disabled.
|
|
|
|
Enabling the Language Card allows to use it as additional memory for cc65
|
|
generated code. However code is never automatically placed there. Rather code
|
|
needs to be explicitly placed in the Language Card either per file by compiling
|
|
with <tt/--code-name LC/ or per function by enclosing in <tt/#pragma code-name
|
|
(push, "LC")/ and <tt/#pragma code-name (pop)/. In either case the cc65 runtime
|
|
system takes care of actually moving the code into the Language Card.
|
|
|
|
The amount of memory available in the Language Card for generated code depends
|
|
on the <ref id="link-configs" name="linker configuration"> parameters. There are
|
|
several usefull settings:
|
|
|
|
<descrip>
|
|
|
|
<tag>LC address: $D400, LC size: $C00</tag>
|
|
For plain vanilla ProDOS 8 which doesn't actually use the Language Card bank 2
|
|
memory from $D400 to $DFFF. This is the default setting.
|
|
|
|
<tag>LC address: $D000, LC size: $1000</tag>
|
|
For ProDOS 8 together with the function <tt/rebootafterexit()/. If a program
|
|
doesn't quit to the ProDOS 8 dispatcher but rather reboots the machine after
|
|
exit then a plain vanilla ProDOS 8 doesn't make use of the Language Card bank
|
|
2 at all.
|
|
|
|
<tag>LC address: $D000, LC size: $3000</tag>
|
|
For plain vanilla DOS 3.3 which doesn't make use of the Language Card at all.
|
|
|
|
</descrip><p>
|
|
|
|
|
|
|
|
<sect>Linker configurations<label id="link-configs"><p>
|
|
|
|
The ld65 linker comes with a default config file for the Apple ][,
|
|
which is used via <tt/-t apple2/.
|
|
The apple2 package comes with additional secondary linker config files, which
|
|
are used via <tt/-t apple2 -C <configfile>/.
|
|
|
|
|
|
<sect1>default config file (<tt/apple2.cfg/)<label id="apple-def-cfg"><p>
|
|
|
|
Default configuration for a binary program.
|
|
|
|
Parameters:
|
|
|
|
<descrip>
|
|
|
|
<tag><tt/STARTADDRESS:/ Program start address</tag>
|
|
Default: $803. Use <tt/-S <addr>/ to set a different start address.
|
|
|
|
<tag><tt/__EXEHDR__:/ AppleSingle executable file header</tag>
|
|
Default: Yes. Use <tt/-D __EXEHDR__=0/ to omit the AppleSingle header.
|
|
|
|
<tag><tt/__STACKSIZE__:/ C runtime stack size</tag>
|
|
Default: $800. Use <tt/-D __STACKSIZE__=<size>/ to set a different
|
|
stack size.
|
|
|
|
<tag><tt/__HIMEM__:/ Highest usable memory address presumed at link time</tag>
|
|
Default: $9600. Use <tt/-D __HIMEM__=<addr>/ to set a different
|
|
highest usable address.
|
|
|
|
<tag><tt/__LCADDR__:/ Address of code in the Language Card</tag>
|
|
Default: $D400. Use <tt/-D __LCADDR__=<addr>/ to set a different
|
|
code address.
|
|
|
|
<tag><tt/__LCSIZE__:/ Size of code in the Language Card</tag>
|
|
Default: $C00. Use <tt/-D __LCSIZE__=<size>/ to set a different
|
|
code size.
|
|
|
|
</descrip><p>
|
|
|
|
|
|
<sect1><tt/apple2-system.cfg/<label id="apple-sys-cfg"><p>
|
|
|
|
Configuration for a system program running on ProDOS 8 and using the memory from
|
|
$2000 to $BEFF.
|
|
|
|
Parameters:
|
|
|
|
<descrip>
|
|
|
|
<tag><tt/__EXEHDR__:/ AppleSingle executable file header</tag>
|
|
Default: Yes. Use <tt/-D __EXEHDR__=0/ to omit the AppleSingle header.
|
|
|
|
<tag><tt/__STACKSIZE__:/ C runtime stack size</tag>
|
|
Default: $800. Use <tt/-D __STACKSIZE__=<size>/ to set a different
|
|
stack size.
|
|
|
|
<tag><tt/__LCADDR__:/ Address of code in the Language Card</tag>
|
|
Default: $D400. Use <tt/-D __LCADDR__=<addr>/ to set a different
|
|
code address.
|
|
|
|
<tag><tt/__LCSIZE__:/ Size of code in the Language Card</tag>
|
|
Default: $C00. Use <tt/-D __LCSIZE__=<size>/ to set a different
|
|
code size.
|
|
|
|
</descrip><p>
|
|
|
|
|
|
<sect1><tt/apple2-hgr.cfg/<p>
|
|
|
|
Configuration for a program including a hires page. See <tt>testcode/lib/apple/hgrtest.c</tt>
|
|
for an example of such a program.
|
|
|
|
Parameters:
|
|
|
|
<descrip>
|
|
|
|
<tag><tt/STARTADDRESS:/ Program start address</tag>
|
|
Default: $803. Use <tt/-S <addr>/ to set a different start address.
|
|
|
|
<tag><tt/__EXEHDR__:/ AppleSingle executable file header</tag>
|
|
Default: Yes. Use <tt/-D __EXEHDR__=0/ to omit the AppleSingle header.
|
|
|
|
<tag><tt/__STACKSIZE__:/ C runtime stack size</tag>
|
|
Default: $800. Use <tt/-D __STACKSIZE__=<size>/ to set a different
|
|
stack size.
|
|
|
|
<tag><tt/__HIMEM__:/ Highest usable memory address presumed at link time</tag>
|
|
Default: $9600. Use <tt/-D __HIMEM__=<addr>/ to set a different
|
|
highest usable address.
|
|
|
|
<tag><tt/__LCADDR__:/ Address of code in the Language Card</tag>
|
|
Default: $D400. Use <tt/-D __LCADDR__=<addr>/ to set a different
|
|
code address.
|
|
|
|
<tag><tt/__LCSIZE__:/ Size of code in the Language Card</tag>
|
|
Default: $C00. Use <tt/-D __LCSIZE__=<size>/ to set a different
|
|
code size.
|
|
|
|
</descrip><p>
|
|
|
|
|
|
<sect1><tt/apple2-overlay.cfg/<p>
|
|
|
|
Configuration for an overlay program with up to nine overlays. The overlay files
|
|
don't include the AppleSingle header. See <tt>samples/overlaydemo.c</tt> for more
|
|
information on overlays.
|
|
|
|
Parameters:
|
|
|
|
<descrip>
|
|
|
|
<tag><tt/STARTADDRESS:/ Program start address</tag>
|
|
Default: $803. Use <tt/-S <addr>/ to set a different start address.
|
|
|
|
<tag><tt/__EXEHDR__:/ AppleSingle executable file header</tag>
|
|
Default: Yes. Use <tt/-D __EXEHDR__=0/ to omit the AppleSingle header.
|
|
|
|
<tag><tt/__STACKSIZE__:/ C runtime stack size</tag>
|
|
Default: $800. Use <tt/-D __STACKSIZE__=<size>/ to set a different
|
|
stack size.
|
|
|
|
<tag><tt/__HIMEM__:/ Highest usable memory address presumed at link time</tag>
|
|
Default: $9600. Use <tt/-D __HIMEM__=<addr>/ to set a different
|
|
highest usable address.
|
|
|
|
<tag><tt/__LCADDR__:/ Address of code in the Language Card</tag>
|
|
Default: $D400. Use <tt/-D __LCADDR__=<addr>/ to set a different
|
|
code address.
|
|
|
|
<tag><tt/__LCSIZE__:/ Size of code in the Language Card</tag>
|
|
Default: $C00. Use <tt/-D __LCSIZE__=<size>/ to set a different
|
|
code size.
|
|
|
|
<tag><tt/__OVERLAYSIZE__:/ Size of code in the overlays</tag>
|
|
Default: $1000. Use <tt/-D __OVERLAYSIZE__=<size>/ to set a different
|
|
code size.
|
|
|
|
</descrip><p>
|
|
|
|
|
|
<sect1><tt/apple2-asm.cfg/<p>
|
|
|
|
Configuration for an assembler program that doesn't need a special setup.
|
|
|
|
Parameters:
|
|
|
|
<descrip>
|
|
|
|
<tag><tt/STARTADDRESS:/ Program start address</tag>
|
|
Default: $803. Use <tt/-S <addr>/ to set a different start address.
|
|
|
|
<tag><tt/__EXEHDR__:/ AppleSingle executable file header</tag>
|
|
Default: No. Use <tt/-u __EXEHDR__ apple2.lib/ to add the AppleSingle header.
|
|
|
|
</descrip><p>
|
|
|
|
|
|
|
|
<sect>ProDOS 8 system programs<p>
|
|
|
|
ProDOS 8 system programs are always loaded to the start address $2000.
|
|
For cc65 programs this means that the 6 KB from $800 to $2000 are
|
|
by default unused. There are however several options to make use of that memory
|
|
range.
|
|
|
|
|
|
<sect1>LOADER.SYSTEM<p>
|
|
|
|
The easiest (and for really large programs in fact the only) way to have a cc65
|
|
program use the memory from $800 to $2000 is to link it as binary
|
|
(as opposed to system) program using the default linker configuration
|
|
<ref id="apple-def-cfg" name="apple2.cfg"> with <tt/__HIMEM__/ set to $BF00
|
|
and load it with the LOADER.SYSTEM utility. The program then works like a system
|
|
program (i.e. quits to the ProDOS dispatcher).
|
|
|
|
Using LOADER.SYSTEM is as simple as copying it to the ProDOS 8 directory of the
|
|
program to load under name <program>.SYSTEM as a system program. For
|
|
example the program <tt/MYPROG/ is loaded by <tt/MYPROG.SYSTEM/. The right
|
|
AppleCommander option to put LOADER.SYSTEM on a ProDOS 8 disk image is <tt/-p/.
|
|
|
|
|
|
<sect1>Heap<p>
|
|
|
|
If the cc65 program can be successfully linked as system program using the linker
|
|
configuration <ref id="apple-sys-cfg" name="apple2-system.cfg">, but
|
|
uses the heap either explicitly or implicitly (i.e. by loading a driver) then
|
|
the memory from $800 to $2000 can be added to the heap by calling
|
|
<tt/_heapadd ((void *) 0x0800, 0x1800);/ at the beginning of <tt/main()/.
|
|
|
|
|
|
<sect1>ProDOS 8 I/O buffers<p>
|
|
|
|
ProDOS 8 requires for every open file a page-aligned 1 KB I/O buffer. By default
|
|
these buffers are allocated by the cc65 runtime system on the heap using
|
|
<tt/posix_memalign()/. While this is generally the best solution it means quite
|
|
some overhead for (especially rather small) cc65 programs which do open files
|
|
but don't make use of the heap otherwise.
|
|
|
|
The apple2 package comes with the alternative ProDOS 8 I/O buffer allocation
|
|
module <tt/apple2-iobuf-0800.o/ which uses the memory between $800 and
|
|
the program start address for the 1 KB I/O buffers. For system programs (with
|
|
start address $2000) this results in up to 6 I/O buffers and thus up to 6
|
|
concurrently open files.
|
|
|
|
While using <tt/_heapadd()/ as described in the section above together with the
|
|
default I/O buffer allocation basically yields the same placement of I/O buffers
|
|
in memory the primary benefit of <tt/apple2-iobuf-0800.o/ is a reduction in code
|
|
size - and thus program file size - of more than 1400 bytes.
|
|
|
|
Using <tt/apple2-iobuf-0800.o/ is as simple as placing it on the linker command
|
|
line like this:
|
|
|
|
<tscreen><verb>
|
|
cl65 -t apple2 -C apple2-system.cfg myprog.c apple2-iobuf-0800.o
|
|
</verb></tscreen>
|
|
|
|
|
|
|
|
<sect>Platform specific header files<p>
|
|
|
|
Programs containing Apple ][ specific code may use the
|
|
<tt/apple2.h/ header file.
|
|
|
|
|
|
<sect1>Apple ][ specific functions<p>
|
|
|
|
The functions listed below are special for the Apple ][. See
|
|
the <url url="funcref.html" name="function reference"> for declaration and
|
|
usage.
|
|
|
|
<itemize>
|
|
<item>_auxtype
|
|
<item>_dos_type
|
|
<item>_filetype
|
|
<item>get_ostype
|
|
<item>rebootafterexit
|
|
<item>ser_apple2_slot
|
|
<item>tgi_apple2_mix
|
|
</itemize>
|
|
|
|
|
|
<sect1>Hardware access<p>
|
|
|
|
There's currently no support for direct hardware access. This does not mean
|
|
you cannot do it, it just means that there's no help.
|
|
|
|
|
|
|
|
<sect>Loadable drivers<p>
|
|
|
|
The names in the parentheses denote the symbols to be used for static linking of the drivers.
|
|
|
|
|
|
<sect1>Graphics drivers<p>
|
|
|
|
<descrip>
|
|
|
|
<tag><tt/a2.lo.tgi (a2_lo_tgi)/</tag>
|
|
This driver features a resolution of 40×48 with 16 colors.
|
|
|
|
The function <tt/tgi_apple2_mix()/ allows to activate 4 lines of text. The
|
|
function clears the corresponding area at the bottom of the screen.
|
|
|
|
<tag><tt/a2.hi.tgi (a2_hi_tgi)/</tag>
|
|
This driver features a resolution of 280×192 with 8 colors and two
|
|
hires pages. Note that programs using this driver will have to be linked
|
|
with <tt/-S $4000/ to reserve the first hires page or with <tt/-S $6000/
|
|
to reserve both hires pages.
|
|
|
|
The function <tt/tgi_apple2_mix()/ allows to activate 4 lines of text. The
|
|
function doesn't clear the corresponding area at the bottom of the screen.
|
|
|
|
In memory constrained situations the memory from $803 to $1FFF
|
|
can be made available to a program by calling <tt/_heapadd ((void *) 0x0803, 0x17FD);/
|
|
at the beginning of <tt/main()/. Doing so is beneficial even if the program
|
|
doesn't use the the heap explicitly because loading the driver (and in fact
|
|
already opening the driver file) uses the heap implicitly.
|
|
|
|
</descrip><p>
|
|
|
|
|
|
<sect1>Extended memory drivers<p>
|
|
|
|
<descrip>
|
|
|
|
<tag><tt/a2.auxmem.emd (a2_auxmem_emd)/</tag>
|
|
Gives access to 47.5 KB RAM (190 pages of 256 bytes each) on an Extended
|
|
80-Column Text Card.
|
|
|
|
Note that this driver doesn't check for the actual existence of the memory
|
|
and that it doesn't check for ProDOS 8 RAM disk content!
|
|
|
|
</descrip><p>
|
|
|
|
|
|
<sect1>Joystick drivers<p>
|
|
|
|
<descrip>
|
|
|
|
<tag><tt/a2.stdjoy.joy (a2_stdjoy_joy)/</tag>
|
|
Supports up to two standard analog joysticks connected to the game port of
|
|
the Apple ][.
|
|
|
|
</descrip><p>
|
|
|
|
|
|
<sect1>Mouse drivers<p>
|
|
|
|
<descrip>
|
|
|
|
<tag><tt/a2.stdmou.mou (a2_stdmou_mou)/</tag>
|
|
Driver for the AppleMouse II Card. Searches all Apple II slots
|
|
for an AppleMouse II Card compatible firmware. The default bounding
|
|
box is [0..279,0..191].
|
|
|
|
Programs using this driver will have to be linked with <tt/-S $4000/
|
|
to reserve the first hires page if they are intended to run on an
|
|
Apple ][ (in contrast to an Apple //e) because the
|
|
AppleMouse II Card firmware writes to the hires page when initializing
|
|
on that machine.
|
|
|
|
Note that the Apple ][ default mouse callbacks support text
|
|
mode only.
|
|
|
|
</descrip><p>
|
|
|
|
|
|
<sect1>RS232 device drivers<p>
|
|
|
|
<descrip>
|
|
|
|
<tag><tt/a2.ssc.ser (a2_ssc_ser)/</tag>
|
|
Driver for the Apple II Super Serial Card. Supports up to 19200 baud,
|
|
hardware flow control (RTS/CTS) and interrupt driven receives. Note
|
|
that because of the peculiarities of the 6551 chip transmits are not
|
|
interrupt driven, and the transceiver blocks if the receiver asserts
|
|
flow control because of a full buffer.
|
|
|
|
The driver defaults to slot 2. Call <tt/ser_apple2_slot()/ prior to
|
|
<tt/ser_open()/ in order to select a different slot. <tt/ser_apple2_slot()/
|
|
succeeds for all Apple II slots, but <tt/ser_open()/ fails with
|
|
<tt/SER_ERR_NO_DEVICE/ if there's no SSC firmware found in the selected slot.
|
|
|
|
</descrip><p>
|
|
|
|
|
|
|
|
<sect>Limitations<p>
|
|
|
|
|
|
<sect1>DOS 3.3<p>
|
|
|
|
Although the standard binaries generated by the linker for the Apple ][
|
|
generally run both on DOS 3.3 (with Applesoft BASIC) and on ProDOS 8 (with
|
|
BASIC.SYSTEM) there are some limitations for DOS 3.3:
|
|
|
|
<descrip>
|
|
|
|
<tag>Disk file I/O</tag>
|
|
There's no disk file I/O support. Any attempt to use it yields an error with
|
|
<tt/errno/ set to <tt/ENOSYS/. This implicitly means that loadable drivers
|
|
are in general not functional as they depend on disk file I/O. Therefore the statically
|
|
linked drivers have to be used instead.
|
|
|
|
<tag/Interrupts/
|
|
There's no <tt/interruptor/ support. Any attempt to use it yields the message
|
|
'FAILED TO ALLOC INTERRUPT' on program startup. This implicitly means that
|
|
mouse and RS232 device drivers are not functional as they depend on interrupts.
|
|
|
|
</descrip><p>
|
|
|
|
|
|
<sect1>Direct console I/O<p>
|
|
|
|
The Apple ][ has no color text mode. Therefore the functions
|
|
<tt/textcolor()/, <tt/bgcolor()/ and <tt/bordercolor()/ have no effect.
|
|
|
|
|
|
<sect1>Random number generator<p>
|
|
|
|
The random number seed is generated from the time the program waits for user input.
|
|
Therefore it is necessary to wait for at least one user keypress either via Standard
|
|
I/O or via Direct console I/O before initializing the pseudo random number generator.
|
|
|
|
|
|
<sect1>Realtime clock<p>
|
|
|
|
There are several types of realtime clocks. It's not desirable to have specific code
|
|
for all of them. As ProDOS 8 supports file timestamps, realtime clock owners usually
|
|
use ProDOS 8 drivers for their realtime clock. Those drivers read the realtime clock
|
|
and write the result to the date/time location in RAM ($BF90 to $BF93).
|
|
ProDOS 8 reads the date/time from that RAM location. If there's no realtime clock the
|
|
RAM location keeps containing zeros. ProDOS 8 uses those zeros as timestamps and the
|
|
files show up in a directory as <tt/<NO DATE>/.
|
|
|
|
There's no common interface to set realtime clocks so if a realtme clock <bf/IS/
|
|
present there's just nothing to do. However, if there's <bf/NO/ realtime clock present,
|
|
the user might very well be interested to "manually" set the RAM location in order to
|
|
have timestamps. But he surely doesn't want to manually set the RAM location over and
|
|
over again. Rather he wants to set it just once after booting ProDOS 8.
|
|
|
|
From that perspective it makes most sense to not set both the date and the time but
|
|
rather only set the date and have the time just stay zero. Then files show up in a
|
|
directory as <tt/DD-MON-YY 0:00/.
|
|
|
|
So <tt/clock_settime()/ checks if the current time equals 0:00. If it does <bf/NOT/
|
|
then a realtime clock is supposed to be active and <tt/clock_settime()/ fails with
|
|
<tt/ERANGE/. Otherwise <tt/clock_settime()/ sets the date - and completely ignores
|
|
the time provided as parameter.
|
|
|
|
<tt/clock_getres()/ too checks if the current time equals 0:00. If it does <bf/NOT/
|
|
then a realtime clock is supposed to be active and <tt/clock_getres()/ returns a time
|
|
resolution of one minute. Otherwise <tt/clock_getres()/ presumes that the only one
|
|
who sets the RAM location is <tt/clock_settime()/ and therefore returns a time
|
|
resolution of one day.
|
|
|
|
|
|
|
|
<sect>Other hints<p>
|
|
|
|
|
|
<sect1>Passing arguments to the program<p>
|
|
|
|
Command line arguments can be passed to <tt/main()/ after BLOAD. Since this is not
|
|
supported by BASIC, the following syntax was chosen:
|
|
|
|
<tscreen><verb>
|
|
]CALL2051:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5
|
|
</verb></tscreen>
|
|
|
|
<enum>
|
|
<item>Arguments are separated by spaces.
|
|
<item>Arguments may be quoted.
|
|
<item>Leading and trailing spaces around an argument are ignored. Spaces within
|
|
a quoted argument are allowed.
|
|
<item>The first argument passed to <tt/main/ is the program name.
|
|
<item>A maximum number of 10 arguments (including the program name) are
|
|
supported.
|
|
</enum>
|
|
|
|
|
|
<sect1>Interrupts<p>
|
|
|
|
The runtime for the Apple ][ uses routines marked as
|
|
<tt/.INTERRUPTOR/ for ProDOS 8 interrupt handlers. Such routines must be
|
|
written as simple machine language subroutines and will be called
|
|
automatically by the interrupt handler code when they are linked into a
|
|
program. See the discussion of the <tt/.CONDES/ feature in the <url
|
|
url="ca65.html" name="assembler manual">.
|
|
|
|
|
|
<sect1>DIO<p>
|
|
|
|
<descrip>
|
|
|
|
<tag/Drive ID/
|
|
The function <url url="dio.html#s1" name="dio_open()"> has the single
|
|
parameter <tt/device/ to identify the device to be opened. Therefore an
|
|
Apple II slot and drive pair is mapped to that <tt/device/ according
|
|
to the formula
|
|
|
|
<tscreen>
|
|
device = slot + (drive - 1) * 8
|
|
</tscreen>
|
|
|
|
so that for example slot 6 drive 2 is mapped to <tt/device/ 14.
|
|
|
|
<tag/Sector count/
|
|
The function <url url="dio.html#s3" name="dio_query_sectcount()"> returns
|
|
the correct sector count for all ProDOS 8 disks. However for any non-ProDOS 8
|
|
disk it simply always returns 280 (which is only correct for a 140 KB disk).
|
|
This condition is indicated by the <tt/_oserror/ value 82.
|
|
|
|
</descrip><p>
|
|
|
|
|
|
<sect1>Specifying file types for fopen<p>
|
|
|
|
<descrip>
|
|
|
|
<tag>Explanation of File Types</tag>
|
|
|
|
ProDOS associates a file type and an auxiliary type with each file.
|
|
These type specifications are separate from the file's name, unlike
|
|
Windows which uses the file name's suffix (a.k.a.
|
|
extension) to specify the file type. For example, <tt/.exe/,
|
|
<tt/.doc/, or <tt/.bat/.
|
|
The ProDOS low-level
|
|
Machine-Language Interface (MLI) functions for creating and opening
|
|
files require these types to be specified. And if they don't match
|
|
with the file being opened, the operation may fail.
|
|
|
|
In contrast, the ISO C function <tt/fopen()/ and the POSIX function
|
|
<tt/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.
|
|
|
|
<tag>Specifying the File Type and Auxiliary Type</tag>
|
|
|
|
There are two global variables provided that allow the file type
|
|
and auxiliary type to be specified before a call to <tt/fopen()/
|
|
or <tt/open()/. They are defined in <tt/apple2_filetype.h/:
|
|
|
|
<tscreen>
|
|
<verb>
|
|
extern unsigned char _filetype; /* Default: PRODOS_T_BIN */
|
|
extern unsigned int _auxtype; /* Default: 0 */
|
|
</verb>
|
|
</tscreen>
|
|
|
|
The header file <tt/apple2_filetype.h/ also defines many values
|
|
that can be used to set these variables. It is included in
|
|
<tt/apple2.h/, which is in turn included in <tt/apple2enh.h/.
|
|
So it isn't necessary to include it directly. Just
|
|
include one of <tt/apple2.h/ or <tt/apple2enh.h/.
|
|
|
|
<tag>Example</tag>
|
|
|
|
A text file cannot be created with just the
|
|
standard C functions because they default to the binary type
|
|
<tt/PRODOS_T_BIN/. The <tt/_filetype/ variable must be set to
|
|
<tt/PRODOS_T_TXT/ to create a text file.
|
|
|
|
For a text file,
|
|
<tt/_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 (Linux/BSD/MacOS) or
|
|
carriage return, line-feed pair (Windows).
|
|
|
|
The "sequential" text file terminology is in contrast to a
|
|
"random-access" text file which would
|
|
have a fixed-length, non-zero record length, so that the
|
|
file position of any individual record can be calculated.
|
|
|
|
For this example, the
|
|
<tt/_auxtype/ does not need to be set because it defaults to
|
|
the desired value, which is zero. To be more explicit,
|
|
<tt/_auxtype/ can also be set to <tt/PRODOS_AUX_T_TXT_SEQ/
|
|
which is defined as zero.
|
|
|
|
<tscreen>
|
|
<verb>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <apple2.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);
|
|
fputs("Daenerys Targaryen\r", out);
|
|
fputs("Sandor Clegane\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));
|
|
}
|
|
}
|
|
</verb>
|
|
</tscreen>
|
|
|
|
</descrip><p>
|
|
|
|
|
|
<sect>License<p>
|
|
|
|
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:
|
|
|
|
<enum>
|
|
<item> 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.
|
|
<item> Altered source versions must be plainly marked as such, and must not
|
|
be misrepresented as being the original software.
|
|
<item> This notice may not be removed or altered from any source
|
|
distribution.
|
|
</enum>
|
|
|
|
</article>
|