Phoenix 0.95 for TI-82/83/85/86 by Patrick Davidson - Internal Documentation                

This is the internal documentation for the game Phoenix.  For information
on using the game, see the file 'PHOENIX.TXT'.  This document explains the
internal workings of the program.  It is mainly intended for people who
want to modify the game.

This file is not yet complete; internal interfaces and data structures are
not yet described in it.  However, the introduction and description of the
build process which produces code for all 3 calculators from a single set of
source files.

 _____________________________________ Table of Contents

 1. Introduction ..................................................... 18
 2. Build process and compatibility system ........................... 51
 3. General program flow .............................................
 4. Data structures ..................................................
 5. Level data format ................................................
 6. Memory arrangement ...............................................
 7. File-by-file description .........................................

 _____________________________________ Introduction

Phoenix is free/open source software.  This means that everyone is allowed
to develop modified versions of the game.  Phoenix is now in the public
domain, so it may be used in any way without restrictions.

I chose this for the simple reason of trying to maximize the usefulness of
the program.  This provides many benefits, such as:

1) Allowing people who want to have a slightly different game to make it
   themselves with a minimum of effort.
2) Allowing intermediately-skilled programmers to learn from the design
   of the game.
3) Allowing the more advanced programmers to develop substantially different
   games based on this one more easily than writing new games from scratch.
4) Allowing the program to continue even if I stop supporting it myself.
                           
However, even though several people have talked to me about making such
modified games, nobody has actually released one yet.  To try to make it
easier for people to do that, I am releasing this document which describes
the internals of the game, and have also added many additional comments to
the code itself.

This document only provides an overview of the working of the game.  More
detailed information about specific functions is present in the comments of
the source files themselves.  (That is, it hopefully will be when/if I get
around to putting in more complete comments).

This document assumes that the reader has at least basic familiarity with
programming the Z80-based calculators in assembly.  If you are a complete
beginner, this is probably not the best resource for learning to program the
calculators.

 ______________________________________ Build process and compatibility

Beginning with version 0.95, the cross-calculator compatibility has been
changed to a simpler (?) method that no longer requires running a
conversion program at any point.

All five versions of the program are built from more or less the same set of
source files.  To allow this to work, each different calculator has its own
"main" program file which includes initialization, address definitions, and
library routines specific to that calculator.  In addition, files dealing
directly with the display have two versions; one for the narrow-screen
calculators (82, 83, and 83+) and one for the wide-screen calculators (85 and
86).  There is also conditional code in some places.

Batch file to automatically build each version are included.  The files
with names "build8?.bat" build the version specifically for that calculator;
the 'build.bat' file automatically builds all versions, and deletes the
temporary files.  Additionally, each build script will automatically make
the full distribution archive, containing all files needed to distribute
with the game (that is, the executable, documentation, and source code).

All of the source code is included in the 'source' directory.  The
'main8?.asm' files are the main source files for each calculator.  For the
TI-86, there is also 'loader86.asm' which contains initialization,
decompression, and write-back routines.  For the files that have separate
versions depending on screen width, the narrow-screen version's name ends
in 12 (because the screen is 12 bytes wide for them) and the wide-screen
version has a name ending in 16 (because those screens are 16 bytes wide).

The program should be built from the main directory (not inside the source
directory) as all include directives expect files to be included from that
subdirectory.  Standard include files (that is, stuff like "usgard.h",
"ion.inc", etc.) should be in the main directory.  This arrangement keeps
Phoenix source files separate from the others.  The build scripts normally
make a file containing simply an include directive for the main source file
in the main directory and assemble that, primarily just so the assembler
will make a file named 'phoenix'.

You will, of course, need to install the standard build tools for each
calculator you want to assemble Phoenix for, and copy the standard includes
into Phoenix's main directory.  Also, make sure that the utilities and
batch files normally used to compile with them are in your path.

The program uses TI-85 style names for RAM addresses and ROM routines.  For
the TI-86 and Ion, where different naming is normally used, I have added
new equates in those calculators' main files to make the TI-85 names work.

There are two special considerations needed to keep things compatible across
calculators, in addition to obvious differences between the calculators.
The first is relocation for Usgard; since Usgard programs can be moved around
in memory, addresses of data inside the program can change.  For this reason,
"relocation labels" have to be used (see Usgard documentation for details).
Essentially, you must put a label of the form "R_<something>:" in front of
any instruction containing a reference that needs to be relocated, such as a
call or jp within the program, or anything that loads the address of a
variable in the program.  The slightly more convenient "&" relocation method
is not practical, as it will confuse the assembler when building for other
calculators.  Of course, you can use "&" relocation for code that will only
be assembled for the TI-85, and you can avoid relocation at all for code that
will not be assembled on the TI-85 at all.

The other problem is with ROM calls.  On many calculators, ROM calls can be
made just by a call to an address.  However, for Ion, "bcall" msut be used
for many calls, and some calls must use ROM_CALL under Crash.  The solution
to this is to use ROM_CALL for all calls where it will be needed on any
calculator; for the calculators where a simple call can be used, ROM_CALL
will be a macro that expands to a simple call, while it expands to the other
needed form on the calculators that require that.  So, ROM_CALL should be
used for all functions except a few simple ones like CP_HL_DE, LD_HL_MHL, and
GET_KEY where even the TI-82 does not need ROM_CALL.  Of course, even some
of these simple functions need a "bcall" in Ion, so for them I wrote small
routines that either do the bcall, or just do the function, to avoid trouble
(for small things like CP_HL_DE and LD_HL_MHL that are called often, this
also avoids the slowdown of a "bcall" on the TI-83+).  Also, ROM_CALL is
defined to expand to a bcall under Ion, so you just use ROM_CALL everywhere.

_______________________________________ General program flow

[Note: the TI-86 version does several additional things to set up its
memory arrangement; see the memory arrangement section for information on
what its loader does].

External levels on the TI-85 and TI-86 are run by running the level file,
which stores its address and an identifier in a special memory location,
and then runs the main phoenix program.

When the main program is run on the TI-85 or TI-86, the first step is to
initialize the scrolling side data (which is used only as a decoration; it
doesn't interact with the game).

The first step common to all calculators when the main Phoenix program is
run is to initialize the timer interrupt, which is used to synchronize the
game to a constant speed (except on the TI-82 version, which first checks if
an existing interrupt it installed [in which case its interrupt can't be
installed] or whether it is running from MirageOS [in which case it wouls
crash] and exits in either condition).

Next, the program checks to see whether there is a saved game.  If there is,
it loads the saved data into the "active" memory area, and then jumps
straight to the main loop.

If there is no saved game, the next step is to check for an external level,
if the calculator being used supports them.  On the TI-85 and TI-86, this
means checking the memory locations where external level identification is
stored.  If an external level was run, the external level's address is saved
in the running level's address variable, and the external level flag is set.
Otherwise, the running level's address variable is initialized to the address
in the program of the built-in level.

_______________________________________ Data structures

_______________________________________ Level data format

_______________________________________ Memory arrangement

_______________________________________ File-by-file description

