Introduction
The file says where each segment goes, and nothing else; there is no field for the program’s start address. Instead two words in the operating system’s page 2 are used as the start vectors, and a segment sets them like any other memory, by loading bytes over them:
| Address | Name | Used |
|---|---|---|
$02E0–$02E1 | RUNAD | where DOS jumps when the whole file has been loaded |
$02E2–$02E3 | INITAD | a routine DOS calls after loading a segment, before it reads the next one |
The names are those of the Atari operating system equates; the explorer shows them wherever a program refers to them (named addresses).
The run address, RUNAD
A segment that covers $02E0 and $02E1 sets RUNAD to the two bytes it
holds there. The usual form is a segment of exactly those two bytes at the end of the file, as in
the example on the overview. When the whole file is loaded,
DOS jumps through RUNAD. If several segments set it, the last one wins.
The explorer lists the final value, the segment that set it, and names the address
run_address in the disassembly (marking it as the region’s entry point). When
no segment sets it, the explorer says so: a file with no run address does not start anything by
itself, and what DOS 2 does then (it returns to its menu) is as published, not checked on a real
disk.
The init address, INITAD
A segment that covers $02E2 and $02E3 sets INITAD. After each segment
DOS calls the routine INITAD points at, with a subroutine call, so the routine ends with
rts; then it reads the next segment. This lets a file load part of itself, run a
setup routine (to clear the screen, to move memory or to turn off the BASIC cartridge) and load
the rest. The loader of an emulator that was disassembled for the tests sets INITAD to a harmless
return before every segment and calls it after every segment, so that a segment which does not
set it calls nothing useful; the explorer assumes the same.
A file can have many INITAD segments. The explorer lists each value with the segment it follows,
and gives each one that lies inside the file the name init_address_1,
init_address_2 and so on (just init_address when there is only one).
Order of events
- read the marker;
- for each segment: read the start and end, load the data, and if the segment changed INITAD, call it;
- at the end of the file: if RUNAD was set, jump through it.
Because INITAD is called straight after the segment that sets it, its routine must already be in memory: in that segment or an earlier one. A RUNAD segment is simply replaced if another RUNAD segment follows it.
Vectors written in parts
A segment may cover only one of the two bytes of a vector, or the end of one vector and the
start of the next (a segment from $02DF to $02E4, say). The explorer
reads a vector only when both of its bytes are in the segment and shows a segment that touches
one byte as setting “part of” the vector. A segment that lies wholly inside
$02E0–$02E3 is a vector segment: it is listed but not
disassembled, since its bytes are addresses.
Other loaders
Other DOSes (MyDOS, SpartaDOS, DOS XL) and many game loaders read the same files with the same two vectors. They add their own conventions, such as the header words mentioned on the overview, which are not described here.