1710 lines
60 KiB
Markdown
1710 lines
60 KiB
Markdown
# LICENSING ###################################################################
|
|
|
|
To the extent possible under law, I, Alison Sanderson, have waived all
|
|
copyright and related or neighboring rights to this Document as described by
|
|
the Creative Commons Zero license linked below.
|
|
|
|
<http://creativecommons.org/publicdomain/zero/1.0/>
|
|
|
|
All of the information in this Document is original research. Marathon and
|
|
Forge are owned by Bungie, Inc. QuickDraw, QuickTime and Macintosh are owned by
|
|
Apple. Aleph One (also referred to as A1 in this Document) is owned by Bungie,
|
|
Inc. et al. Igni Ferroque, Ferro, and Atque are owned by Gregory Smith
|
|
(treellama.) Maraiah is owned by Project Golan. Any other copyrights belong to
|
|
their respective owners.
|
|
|
|
If you need explanation on anything in this document don't hesitate to ask me.
|
|
Contact information is available at <http://greyserv.net>.
|
|
|
|
# CONTENTS ####################################################################
|
|
|
|
| Title | Description |
|
|
| ----- | ----------- |
|
|
| LICENSING | The license this document is under. |
|
|
| CONTENTS | This table of contents. |
|
|
| TERMINAL CODE | Info on terminal definition files. |
|
|
| DATA FORMATS | Data formats used throughout Marathon. |
|
|
| STRUCTURES | Structure types used throughout Marathon. |
|
|
| ENUMERATIONS | Names for integers used in Marathon's structures. |
|
|
| FLAGS | Names for bit field flags used in Marathon's structures. |
|
|
|
|
You can scroll through sections of this document by searching for `/^# /`.
|
|
Specific sections can be searched by their name here.
|
|
|
|
# TERMINAL CODE ###############################################################
|
|
|
|
The terminal definition format is extremely straightforward. Terminal commands
|
|
begin lines and are in the format:
|
|
|
|
```
|
|
#COMMAND_NAME parameters
|
|
```
|
|
|
|
In Forge and Maraiah, commands need not be uppercase. Atque does require all
|
|
commands to be uppercase.
|
|
|
|
Comments also begin lines (they can't be after the beginning of one) and will
|
|
disable any text proceeding them. They are formed like:
|
|
|
|
```
|
|
; comment content here
|
|
```
|
|
|
|
Terminals are numbered, and this is used in the map to determine which terminal
|
|
to display when a computer is used.
|
|
|
|
## Blocks ##
|
|
|
|
### Terminal Blocks ###
|
|
|
|
The number for the terminal being currently defined is set with the `#TERMINAL`
|
|
and `#ENDTERMINAL` commands. These are formed as:
|
|
|
|
```
|
|
#TERMINAL number
|
|
#ENDTERMINAL number
|
|
```
|
|
|
|
For example, defining a terminal numbered "1" would be:
|
|
|
|
```
|
|
#TERMINAL 1
|
|
|
|
; terminal's contents here
|
|
|
|
#ENDTERMINAL 1
|
|
```
|
|
|
|
### Sections ###
|
|
|
|
There are four possible sections in a terminal, which are between the
|
|
`#TERMINAL` and `#ENDTERMINAL` blocks:
|
|
|
|
```
|
|
#UNFINISHED
|
|
#FINISHED
|
|
#FAILURE
|
|
#SUCCESS
|
|
```
|
|
|
|
These all mark the start of where the terminal will display, depending on the
|
|
current status of your mission.
|
|
|
|
| Name | Will display when |
|
|
| ---- | ----------------- |
|
|
| `UNFINISHED` | your objective has not been met or no other block exists |
|
|
| `FINISHED` | you have succeeded or failed |
|
|
| `FAILURE` | you have failed your objective |
|
|
| `SUCCESS` | you have succeeded in your objective |
|
|
|
|
Sections must have an end, which is defined with:
|
|
|
|
```
|
|
#END
|
|
```
|
|
|
|
Between sections may be any amount of regular commands. There are two kinds of
|
|
these normal commands: Text commands, and interactive commands.
|
|
|
|
## Text Commands ##
|
|
|
|
All text commands may have (but do not require) text following them, which may
|
|
be formatted.
|
|
|
|
Line breaks will break in-game, but unbroken lines will automatically wrap. It
|
|
is generally best to just put all of your text onto one line, even if this
|
|
destroys your sanity. Use a text editor with line wrapping for this.
|
|
|
|
Example:
|
|
|
|
```
|
|
#PICT 10007
|
|
~text interface terminal malfunction error ~2992dud
|
|
|
|
welcome to mabmap i am durandal the most pretty ai in ever i made the pfhor ded and won all the everything you should go shoot some things I put here because reasons
|
|
```
|
|
|
|
### Formatting ###
|
|
|
|
Text effects are designated by a '$' and then one of the following:
|
|
|
|
| $-code | Effect |
|
|
| ------ | ------ |
|
|
| `I/i` | enables/disables italic text |
|
|
| `B/b` | enables/disables bold text |
|
|
| `U/u` | enables/disables underlined text |
|
|
| `Cn` | changes the text color, where "n" is a number 0 through 9 |
|
|
|
|
For more information on colors, see section ENUMERATIONS, Terminal Color.
|
|
|
|
Example:
|
|
|
|
```
|
|
$C1$BoOooO$IooOOoo$i$b$C0 ... $C6did I $Uspook$u you?$C0
|
|
```
|
|
|
|
### Text Command Overview ###
|
|
|
|
Text commands include:
|
|
|
|
```
|
|
#PICT pict_id alignment
|
|
#LOGON pict_id
|
|
#LOGOFF pict_id
|
|
#INFORMATION
|
|
#CHECKPOINT goal_id
|
|
#BRIEFING level_number
|
|
```
|
|
|
|
### `#PICT` ###
|
|
|
|
```
|
|
#PICT pict_id alignment
|
|
```
|
|
|
|
`#PICT` is the most basic and most used command throughout Marathon 2.
|
|
|
|
It displays a picture to the specified alignment and text to the other side.
|
|
|
|
It will:
|
|
* Wait for input before proceeding.
|
|
* Display 45 characters per line, and display up to 22 lines on one page.
|
|
* Display text aligned to the left on the right side of the screen.
|
|
|
|
If alignment is specified as RIGHT, text is aligned to the right on the left of
|
|
the screen. If alignment is specified as CENTER, no text may be displayed, only
|
|
an image. If no alignment is specified, it will default to an image on the left
|
|
and text on the right.
|
|
|
|
Example:
|
|
|
|
```
|
|
#PICT 10007
|
|
~text interface terminal malfunction error ~2992dud
|
|
|
|
hellote this is example text from durnadle prettiest ai in ever thank u for reading goodbye
|
|
```
|
|
|
|
### `#LOGON`, `#LOGOFF` ###
|
|
|
|
```
|
|
#LOGON pict_id
|
|
#LOGOFF pict_id
|
|
```
|
|
|
|
`#LOGON` and `#LOGOFF` are generally used first and last in a terminal.
|
|
|
|
These two display a PICT in the middle of the screen and text below the image
|
|
if you supply it. They both do things to the screen borders.
|
|
|
|
They will:
|
|
* Automatically continue, an input will interrupt it.
|
|
* Only display one line of text, at most 72 characters.
|
|
* Display text aligned to the center in the middle of the screen.
|
|
|
|
Example:
|
|
|
|
```
|
|
#LOGON 1600
|
|
<CMND PRAMA &681g1>
|
|
; ... content ...
|
|
#LOGOFF 1600
|
|
ehhg.431.4122//<PFGR ZNE6 &49c2>
|
|
```
|
|
|
|
### `#INFORMATION` ###
|
|
|
|
```
|
|
#INFORMATION
|
|
```
|
|
|
|
`#INFORMATION` will just display text, and is mostly used in Marathon 1.
|
|
|
|
It will:
|
|
* Wait for input before proceeding.
|
|
* Display 72 characters per line, and display up to 22 lines on one page.
|
|
* Display text aligned to the left on the left side of the screen.
|
|
|
|
Example:
|
|
|
|
```
|
|
#INFORMATION
|
|
you suck at videogames love durandal
|
|
p.s. if you don't win i'm erasing your home planet from existence
|
|
```
|
|
|
|
### `#CHECKPOINT` ###
|
|
|
|
```
|
|
#CHECKPOINT goal_id
|
|
```
|
|
|
|
`#CHECKPOINT` may only be used in Marathon 1, unless you're using Aleph One
|
|
version 1.1 or higher.
|
|
|
|
This shows a map centered on the specified goal point, with the goal circled,
|
|
on the left of the screen.
|
|
|
|
The map will only show polygons connected to the polygon the goal is in, so if
|
|
you have a separated area where the goal point is, it will only display that.
|
|
It will also not display secret areas and any polygons proceeding them.
|
|
|
|
It will:
|
|
* Wait for input before proceeding.
|
|
* Display 45 characters per line, and display up to 22 lines on one page.
|
|
* Display text aligned to the left on the right side of the screen.
|
|
|
|
Example:
|
|
|
|
```
|
|
#CHECKPOINT 7
|
|
go shoot these things so i can claim this victory as mine forever and tell you about the things that i totally shot for approximately 200 years
|
|
```
|
|
|
|
### `#BRIEFING` ###
|
|
|
|
```
|
|
#BRIEFING level_number
|
|
```
|
|
|
|
BRIEFING may only be used in Marathon 1. It is identical to INFORMATION, but
|
|
after you're done reading, it will teleport you to the specified level.
|
|
|
|
## Interactive Commands ##
|
|
|
|
Interactive commands are all actions carried out by the game that do not all
|
|
effect the active terminal.
|
|
|
|
### Interactive Command Overview ###
|
|
|
|
Interactive commands include:
|
|
|
|
```
|
|
#INTERLEVEL TELEPORT level_number
|
|
#INTRALEVEL TELEPORT polygon_tag
|
|
#TAG tag
|
|
#SOUND sound_number
|
|
#STATIC duration
|
|
```
|
|
|
|
### `#INTERLEVEL TELEPORT` ###
|
|
|
|
```
|
|
#INTERLEVEL TELEPORT level_number
|
|
```
|
|
|
|
`#INTERLEVEL TELEPORT` exits the terminal and teleports you to the specified
|
|
level. If the level number is "256", this ends the game.
|
|
|
|
Example:
|
|
|
|
```
|
|
#INTERLEVEL TELEPORT 7
|
|
```
|
|
|
|
### `#INTRALEVEL TELEPORT` ###
|
|
|
|
```
|
|
#INTRALEVEL TELEPORT polygon_tag
|
|
```
|
|
|
|
`#INTRALEVEL TELEPORT` exits the terminal and teleports you to the centroid of
|
|
the specified polygon within the map.
|
|
|
|
Example:
|
|
|
|
```
|
|
#INTRALEVEL TELEPORT 77
|
|
```
|
|
|
|
### `#TAG` ###
|
|
|
|
```
|
|
#TAG tag
|
|
```
|
|
|
|
`#TAG` activates all lights and platforms with the specified tag.
|
|
|
|
Example:
|
|
|
|
```
|
|
#TAG 77
|
|
```
|
|
|
|
### `#SOUND` ###
|
|
|
|
```
|
|
#SOUND sound_number
|
|
```
|
|
|
|
`#SOUND` plays the specified sound from the Sounds file or from the Scenario.
|
|
|
|
Example:
|
|
|
|
```
|
|
#SOUND 77
|
|
```
|
|
|
|
### `#STATIC` ###
|
|
|
|
```
|
|
#STATIC duration
|
|
```
|
|
|
|
`#STATIC` fills the terminal with TV static for the specified duration in
|
|
1/30ths seconds. Aleph One only.
|
|
|
|
Example:
|
|
|
|
```
|
|
#STATIC 60
|
|
```
|
|
|
|
# DATA FORMATS ################################################################
|
|
|
|
## Wad ##
|
|
|
|
Wad files are used for scenario data, images such as those in terminals and the
|
|
main menu, and physics files. Here is a listing of all chunks used within them:
|
|
|
|
| Name | Description |
|
|
| ---- | ----------- |
|
|
| `Minf` | Static Map Info structure |
|
|
| `PNTS` | Array of Points |
|
|
| `EPNT` | Array of Endpoints |
|
|
| `LINS` | Array of Lines |
|
|
| `SIDS` | Array of Sides |
|
|
| `POLY` | Array of Polygons |
|
|
| `LITE` | Array of Lights |
|
|
| `NOTE` | Not analyzed (annotations) |
|
|
| `OBJS` | Array of Objects |
|
|
| `påth` | Not analyzed (å is $8C) (guardpaths) |
|
|
| `plac` | Not analyzed (item placement) |
|
|
| `door` | No test data (extra door data) |
|
|
| `PLAT` | No test data (platform static data) |
|
|
| `medi` | Media (liquids) |
|
|
| `ambi` | Not analyzed (ambient sounds) |
|
|
| `bonk` | Not analyzed (random sounds) |
|
|
| `term` | Array of Terminals |
|
|
| `iidx` | Not analyzed (map indices) |
|
|
| `ShPa` | Not analyzed (shapes) |
|
|
| `MMLS` | Not analyzed (MML scripts) |
|
|
| `LUAS` | Not analyzed (Lua scripts) |
|
|
| `FXpx` | Effect definitions |
|
|
| `MNpx` | Monster definitions |
|
|
| `PRpx` | Player definitions |
|
|
| `PXpx` | Physics definitions |
|
|
| `WPpx` | Weapon definitions |
|
|
| `PICT` | Picture Resource |
|
|
| `clut` | Unused(?) |
|
|
|
|
Map files can be identified by the Minf chunk.
|
|
|
|
Map files will always have either a PNTS or EPNT chunk, depending on what the
|
|
map (and editor) use. PNTS are plain and have no more information than the
|
|
actual position, while EPNT has flags and some extra stuff to help the engine
|
|
load quicker (not that it needs it.)
|
|
|
|
Images can be identified by the PICT chunk.
|
|
|
|
Physics definitions may be embedded into a map, so the only reliable way to
|
|
check if something is a pure physics file is by checking that there are no
|
|
chunks other than `XXpx` chunks.
|
|
|
|
The file extensions used for Wad files include `imgA` for `Images`, `sceA` for
|
|
`Map`, and `phyA` for `Physics`.
|
|
|
|
## Marathon 2 Shapes (`.shpA`) ##
|
|
|
|
The Shapes file is used for storing animation, sprite, sky and texture data. It
|
|
uses a fixed, offset-based format for everything, with sprites sorted into
|
|
collections along with frames and sequences.
|
|
|
|
## Marathon 2 Sounds (`.sndA`) ##
|
|
|
|
The Sounds file is used for storing information about sounds as well as the
|
|
actual PCM data.
|
|
|
|
# STRUCTURES ##################################################################
|
|
|
|
All integers here are big-endian unless specified.
|
|
|
|
All unspecified bytes must be set to `0` when written, although when reading
|
|
should not be checked as they may be garbage.
|
|
|
|
The type "`fixed`" refers to a 32-bit fixed point number with the format 15.16s
|
|
(the lower 16 bits are fractional, the upper 15 are integral, and one bit for
|
|
sign.)
|
|
|
|
The type "`angle`" refers to a 16-bit fixed point number with the format 0.9s.
|
|
This is used for all angles.
|
|
|
|
The type "`unit`" refers to a 16-bit fixed point number with the format 5.10s.
|
|
This is used for all world coordinates.
|
|
|
|
An "Object ID" is a 16-bit integer which references something by index. If all
|
|
bits are set, it is to be interpreted as "none." Traditionally, these are
|
|
signed integers, but they can be treated as unsigned with no repercussions.
|
|
|
|
## Wad ##
|
|
|
|
### Wad File ###
|
|
|
|
Wad files are structured like:
|
|
* Wad Header
|
|
* Entries/Chunks
|
|
* Directory
|
|
|
|
It *must* be in this order because the engine assumes that the data directly
|
|
after the 128th byte is entry data.
|
|
|
|
### Wad Header ###
|
|
|
|
The Wad Header is 128 bytes. The Wad header is always at the very beginning of
|
|
the file, except when it's a MacBin file or an AppleSingle file, in which case
|
|
it's at the start of the resource fork. You'll have to account for that
|
|
yourself.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `WadVersion` | `u16` | `0` |
|
|
| `DataVersion` | `u16` | `2` |
|
|
| `OriginalName` | `u8[64]` | `4` |
|
|
| `Checksum` | `u32` | `68` |
|
|
|
|
- `WadVersion` is a Wad Version enumeration.
|
|
- `DataVersion` is a Data Version enumeration.
|
|
- `OriginalName` is the original filename, null byte terminated.
|
|
- `Checksum` is a CRC-32 of the entire file with this value set to 0.
|
|
|
|
If `WadVersion` is greater than or equal to `VerDir`:
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `DirOffset` | `u32` | `72` |
|
|
| `NumEntries` | `u16` | `76` |
|
|
| `AppDataSize` | `u16` | `78` |
|
|
| `ChunkSize` | `u16` | `80` |
|
|
| `EntrySize` | `u16` | `82` |
|
|
|
|
- `DirOffset` is the offset to the first Directory Entry structure.
|
|
- `NumEntries` is the number of entries in this file.
|
|
- `AppDataSize` is the number of bytes to skip for each directory entry.
|
|
- `ChunkSize` and `EntrySize` may be zero, in which case they will default to
|
|
16 and 10 respectively. They exist for forward compatibility with Wad patching,
|
|
but because they were never actually expanded upon, are useless.
|
|
|
|
If `WadVersion` is greater than or equal to `VerOver`:
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `ParentSum` | `u32` | `84` |
|
|
|
|
- `ParentSum` is the checksum of the file this one modifies, if any.
|
|
|
|
### Directory Entry ###
|
|
|
|
Directory Entry is 8 bytes if `WadVersion` is `VerBase`, or else `EntrySize +
|
|
AppData` bytes. Following this structure is `AppData` bytes, supposed to be
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `DataOffset` | `u32` | `0` |
|
|
| `DataSize` | `u32` | `4` |
|
|
|
|
- `DataOffset` is the offset to the start of this entry's data (from the start
|
|
of the file.)
|
|
- `DataSize` is the length of this entry's data.
|
|
|
|
If `WadVersion` is greater than or equal to `VerDir`:
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Index` | `u16` | `8` |
|
|
| `AppData` | `u8[]` | `10` |
|
|
|
|
- `Index` is the index of this entry, for instance the map or PICT number.
|
|
- `AppData` is an arbitrary data array used by editor applications, and will be
|
|
ignored by the engine.
|
|
|
|
### Chunk ###
|
|
|
|
Chunk is 12 bytes if `WadVersion` is `VerBase`, or `ChunkSize` bytes otherwise.
|
|
Most Wad entries are made up of tagged data formats, the engine assumes this
|
|
for every entry and so every entry has at least one chunk. These are similar to
|
|
IFF or PNG chunks.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Ident` | `u8[4]` | `0` |
|
|
| `NextOffset` | `u32` | `4` |
|
|
| `DataSize` | `u32` | `8` |
|
|
|
|
- `Ident` is a four character code identifier for the chunk.
|
|
- `NextOffset` is the file offset of the next chunk minus the file header.
|
|
- `DataSize` is the size of the chunk (not including this header.)
|
|
|
|
If `WadVersion` is greater than or equal to `VerDir`:
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `PatchOffset` | `u32` | `12` |
|
|
|
|
## Map ##
|
|
|
|
### Light Function ###
|
|
|
|
Light Function is 14 bytes.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Type` | `u16` | `0` |
|
|
| `Period` | `u16` | `2` |
|
|
| `DeltaPeriod` | `u16` | `4` |
|
|
| `Value` | `u16` | `6` |
|
|
| `DeltaValue` | `u16` | `10` |
|
|
|
|
- `Type` is a Light Function enumeration.
|
|
|
|
### Side Texture ###
|
|
|
|
Side Texture is 6 bytes. Just stores a texture and an offset.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `OffsetX` | `unit` | `0` |
|
|
| `OffsetY` | `unit` | `2` |
|
|
| `TextureId` | `u16` | `4` |
|
|
|
|
- `TextureId` is an Object ID referencing a Shapes bitmap.
|
|
|
|
### Point ###
|
|
|
|
Point is 4 bytes. A geometric point.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `PosX` | `unit` | `0` |
|
|
| `PosY` | `unit` | `2` |
|
|
|
|
### Endpoint ###
|
|
|
|
Endpoint is 16 bytes. A point structure which can be loaded directly into
|
|
memory instead of being calculated at runtime.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Flags` | `u16` | `0` |
|
|
| `HeightHi` | `unit` | `2` |
|
|
| `HeightLo` | `unit` | `4` |
|
|
| `Position` | `struct` | `6` |
|
|
| `Support` | `u16` | `14` |
|
|
|
|
- `Flags` is an Endpoint Flags bit field.
|
|
- `HeightHi` and `HeightLo` are the highest adjacent ceiling and lowest
|
|
adjacent floor heights, respectively.
|
|
- `Position` is a Point structure.
|
|
- `Support` is the index of the highest adjacent polygon.
|
|
|
|
### Line ###
|
|
|
|
Line is 32 bytes. A geometric line segment.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `PointBeg` | `u16` | `0` |
|
|
| `PointEnd` | `u16` | `2` |
|
|
| `Flags` | `u16` | `4` |
|
|
| `Length` | `unit` | `6` |
|
|
| `HeightHi` | `unit` | `8` |
|
|
| `HeightLo` | `unit` | `10` |
|
|
| `SideFrnt` | `u16` | `12` |
|
|
| `SideBack` | `u16` | `14` |
|
|
| `PolyFrnt` | `u16` | `16` |
|
|
| `PolyBack` | `u16` | `18` |
|
|
|
|
- `PointBeg` and `PointEnd` are the beginning and terminating endpoints.
|
|
- `Flags` is a Line Flags bit field.
|
|
- `HeightHi` and `HeightLo` are the highest adjacent ceiling and lowest
|
|
adjacent floor heights, respectively.
|
|
- `SideFrnt` and `SideBack` are Object ID indices of the Sides in the front and
|
|
back.
|
|
- `PolyFrnt` and `PolyBack` are Object ID indices of the connected Polygons.
|
|
|
|
### Side ###
|
|
|
|
Side is 64 bytes. One possibly textured side of a line segment.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Type` | `u16` | `0` |
|
|
| `Flags` | `u16` | `2` |
|
|
| `TexPri` | `struct` | `4` |
|
|
| `TexSec` | `struct` | `10` |
|
|
| `TexTra` | `struct` | `16` |
|
|
| `ExTopL` | `struct` | `22` |
|
|
| `ExTopR` | `struct` | `26` |
|
|
| `ExBotL` | `struct` | `30` |
|
|
| `ExBotR` | `struct` | `34` |
|
|
| `PanelType` | `u16` | `38` |
|
|
| `PanelPerm` | `i16` | `40` |
|
|
| `XferPri` | `u16` | `42` |
|
|
| `XferSec` | `u16` | `44` |
|
|
| `XferTra` | `u16` | `46` |
|
|
| `Shade` | `fixed` | `48` |
|
|
|
|
- `Type` is a Side Type enumeration.
|
|
- `Flags` is a Side Flags bit field.
|
|
- `TexPri`, `TexSec` and `TexTra` are Side Texture structures representing the
|
|
primary, secondary and transparent (middle) textures.
|
|
- `ExTopL`, `ExTopR`, `ExBotL` and `ExBotR` are Point structures representing
|
|
the collision bounding rectangle.
|
|
- `PanelType` is a control panel preset number.
|
|
- `PanelPerm` is the permutation for this control panel (if any.)
|
|
- `XferPri`, `XferSec` and `XferTra` are Transfer Mode enumerations for each
|
|
respective texture.
|
|
- `Shade` is the ambient shading used primarily for visual contrast.
|
|
|
|
### Polygon ###
|
|
|
|
Polygon is 128 bytes. A geometric polygon, essentially Doom's "sector," but
|
|
must be convex. More similar to a "subsector" since you have to split it
|
|
yourself and the map compiler will not help you with this process. (It is a
|
|
planned feature of Maraiah to allow the user to draw polygons of arbitrary
|
|
shape and automatically split them.)
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Type` | `u16` | `0` |
|
|
| `Flags` | `u16` | `2` |
|
|
| `Permutation` | `i16` | `4` |
|
|
| `VtxNum` | `u16` | `6` |
|
|
| `VtxArray` | `u16[8]` | `8` |
|
|
| `LinArray` | `u16[8]` | `24` |
|
|
| `TexFlr` | `u16` | `40` |
|
|
| `TexCei` | `u16` | `42` |
|
|
| `HeightFlr` | `unit` | `44` |
|
|
| `HeightCei` | `unit` | `46` |
|
|
| `LightFlr` | `u16` | `48` |
|
|
| `LightCei` | `u16` | `50` |
|
|
| `Area` | `i32` | `52` |
|
|
| `ObjectFst` | `u16` | `56` |
|
|
| `ZoneFst` | `u16` | `58` |
|
|
| `ZoneNumLin` | `u16` | `60` |
|
|
| `ZoneNumVtx` | `u16` | `62` |
|
|
| `XferFlr` | `u16` | `64` |
|
|
| `XferCei` | `u16` | `66` |
|
|
| `Adjacent` | `u16[8]` | `68` |
|
|
| `NeighborFst` | `u16` | `84` |
|
|
| `NeighborNum` | `u16` | `86` |
|
|
| `Center` | `struct` | `88` |
|
|
| `SideArray` | `u16[8]` | `92` |
|
|
| `OrigFlr` | `struct` | `108` |
|
|
| `OrigCei` | `struct` | `112` |
|
|
| `Media` | `u16` | `116` |
|
|
| `MediaLight` | `u16` | `118` |
|
|
| `SoundIndices` | `u16` | `120` |
|
|
| `SoundAmbient` | `u16` | `122` |
|
|
| `SoundRandom` | `u16` | `124` |
|
|
|
|
- `Type` is a Polygon Type enumeration.
|
|
- `Flags` is a Polygon Flags bit field.
|
|
- `Area` is the power-of-two area of the polygon.
|
|
- `ObjectFst` must be `65535`.
|
|
- `Center` is a Point structure.
|
|
- `OrigFlr` is a Point structure for the texture offset of the floor.
|
|
- `OrigCei` is a Point structure for the texture offset of the ceiling.
|
|
- `Media` is an Object ID.
|
|
- `SoundAmbient` is an Object ID.
|
|
- `SoundRandom` is an Object ID.
|
|
|
|
### Light ###
|
|
|
|
Light is 100 bytes.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Type` | `u16` | `0` |
|
|
| `Flags` | `u16` | `2` |
|
|
| `Phase` | `i16` | `4` |
|
|
| `ActivPri` | `struct` | `6` |
|
|
| `ActivSec` | `struct` | `20` |
|
|
| `ActivMid` | `struct` | `34` |
|
|
| `InactPri` | `struct` | `48` |
|
|
| `InactSec` | `struct` | `62` |
|
|
| `InactMid` | `struct` | `76` |
|
|
| `Tag` | `u16` | `90` |
|
|
|
|
- `Type` is a Light Type enumeration.
|
|
- `Flags` is a Light Flags bit field.
|
|
- `ActivPri`, `ActivSec` and `ActivMid` are Light Function structures.
|
|
- `InactPri`, `InactSec` and `InactMid` are Light Function structures.
|
|
|
|
### Object ###
|
|
|
|
Object is 16 bytes.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Group` | `u16` | `0` |
|
|
| `Index` | `u16` | `2` |
|
|
| `Angle` | `angle` | `4` |
|
|
| `Polygon` | `u16` | `6` |
|
|
| `PosX` | `unit` | `8` |
|
|
| `PosY` | `unit` | `10` |
|
|
| `PosZ` | `unit` | `12` |
|
|
| `Flags` | `u16` | `14` |
|
|
|
|
### Static Map Info ###
|
|
|
|
Static Map Info is 88 bytes.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `EnvCode` | `u16` | `0` |
|
|
| `PhysicsId` | `u16` | `2` |
|
|
| `MusicId` | `u16` | `4` |
|
|
| `MissionFlags` | `u16` | `6` |
|
|
| `EnvFlags` | `u16` | `8` |
|
|
| `Name` | `u8[66]` | `18` |
|
|
| `EntryFlags` | `u32` | `84` |
|
|
|
|
- `EnvCode` is a preset number for texture collections and some other things
|
|
such as media (liquid) presets.
|
|
- `MissionFlags` is a Mission Flags bit field.
|
|
- `EnvFlags` is an Environment Flags bit field.
|
|
- `Name` is the level name, intended to be 65 bytes, but one padding byte is
|
|
left over, so the real length is 66.
|
|
- `EntryFlags` is an Entry Point Flags bit field. It is unknown why this is 32
|
|
bits wide when it could fit in even 8 bits.
|
|
|
|
## Terminal ##
|
|
|
|
### Terminal ###
|
|
|
|
Terminal text can be encoded with some weird xor bullshit for some reason.
|
|
You can decode it and encode it with the same method:
|
|
|
|
```c
|
|
for(i = 0; i < len / 4; i++) {p += 2; *p++ ^= 0xFE; *p++ ^= 0xED;}
|
|
for(i = 0; i < len % 4; i++) *p++ ^= 0xFE;
|
|
```
|
|
|
|
* Terminal Header
|
|
* Terminal Groups
|
|
* Text Faces
|
|
* Terminal text (null byte terminated)
|
|
|
|
### Terminal Header ###
|
|
|
|
Terminal Header is 10 bytes.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Size` | `u16` | `0` |
|
|
| `Flags` | `u16` | `2` |
|
|
| `PageLines` | `u16` | `4` |
|
|
| `NumGroups` | `u16` | `6` |
|
|
| `NumFaces` | `u16` | `8` |
|
|
|
|
- `Size` is the total length of the terminal, including this header.
|
|
- `Flags` is a Terminal Flags bit field.
|
|
- `PageLines` is the number of lines per page, almost always 22.
|
|
|
|
### Terminal Group ###
|
|
|
|
Terminal Group is 12 bytes.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Flags` | `u16` | `0` |
|
|
| `Type` | `u16` | `2` |
|
|
| `Permutation` | `i16` | `4` |
|
|
| `TextOfs` | `u16` | `6` |
|
|
| `TextSize` | `u16` | `8` |
|
|
| `MaxLineCount` | `u16` | `10` |
|
|
|
|
- `Flags` is a Terminal Group Flags bit field.
|
|
- `Type` is a Terminal Group Type enumeration.
|
|
|
|
### Text Face ###
|
|
|
|
Text Face is 6 bytes.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `TextOfs` | `u16` | `0` |
|
|
| `Face` | `u16` | `2` |
|
|
| `Color` | `u16` | `4` |
|
|
|
|
- `Color` is a Terminal Color enumeration.
|
|
|
|
## Images ##
|
|
|
|
### Picture Resource ###
|
|
|
|
Pictures are formed with a header and then a variable number of operations. In
|
|
other words, a small state machine is used to form an image through effects and
|
|
various fill instructions. QuickDraw is horrifying. This is the native image
|
|
format. It's a fucking metafile.
|
|
|
|
* Picture Header
|
|
* Picture Opcodes
|
|
|
|
### Picture Header ###
|
|
|
|
All QuickDraw PICTs begin with a basic 10 byte header as follows.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Size` | `u16` | `0` |
|
|
| `Top` | `u16` | `2` |
|
|
| `Left` | `u16` | `4` |
|
|
| `Height` | `u16` | `6` |
|
|
| `Width` | `u16` | `8` |
|
|
|
|
### CopyBits ###
|
|
|
|
CopyBits has a variable size. Offsets are not provided as they are variable,
|
|
sequential to the current code path.
|
|
|
|
If direct copy:
|
|
|
|
| Name | Type | Ignored |
|
|
| ---- | ---- | :-----: |
|
|
| `BaseAddr` | `u32` | Yes |
|
|
|
|
Always:
|
|
|
|
| Name | Type |
|
|
| ---- | ---- |
|
|
| `PitchFl` | `u16` |
|
|
| `Top` | `u16` |
|
|
| `Left` | `u16` |
|
|
| `Bottom` | `u16` |
|
|
| `Right` | `u16` |
|
|
|
|
- `PitchFl` is the number of bytes per row, and the upper two bits are a
|
|
CopyBits Flags bit field.
|
|
|
|
If PICT2:
|
|
|
|
| Name | Type |
|
|
| ---- | ---- |
|
|
| `PixMap` | `struct` |
|
|
|
|
- `PixMap` is a PixMap structure.
|
|
|
|
Otherwise, assume pack type is default and bit depth is 1.
|
|
|
|
If packed:
|
|
|
|
| Name | Type | Ignored |
|
|
| ---- | ---- | :-----: |
|
|
| `CLUTIden` | `u32` | Yes |
|
|
| `CLUTFlags` | `u16` | No |
|
|
| `CLUTNum` | `u16` | No |
|
|
| `CLUT` | `struct[]` | No |
|
|
|
|
- `CLUTFlags` is a Color Table Flags bit field.
|
|
- `CLUT` is an array of `CLUTNum` Color Table structures.
|
|
|
|
Always:
|
|
|
|
| Name | Type | Ignored |
|
|
| ---- | ---- | :-----: |
|
|
| `SrcTop` | `u16` | Yes |
|
|
| `SrcLeft` | `u16` | Yes |
|
|
| `SrcBottom` | `u16` | Yes |
|
|
| `SrcRight` | `u16` | Yes |
|
|
| `DstTop` | `u16` | Yes |
|
|
| `DstLeft` | `u16` | Yes |
|
|
| `DstBottom` | `u16` | Yes |
|
|
| `DstRight` | `u16` | Yes |
|
|
| `XferMode` | `u16` | Yes |
|
|
|
|
If clip:
|
|
|
|
| Name | Type | Ignored |
|
|
| ---- | ---- | :-----: |
|
|
| `ClipRgn` | `struct` | Yes |
|
|
|
|
- `ClipRgn` is skipped the same as opcode `$0001` in Aleph One.
|
|
|
|
Image data follows this header.
|
|
|
|
### PixMap ###
|
|
|
|
PixMap is 36 bytes.
|
|
|
|
| Name | Type | Ignored |
|
|
| ---- | ---- | :-----: |
|
|
| `Version` | `u16` | Yes |
|
|
| `PackType` | `u16` | No |
|
|
| `PackSize` | `u32` | Yes |
|
|
| `HorzDPI` | `u32` | Yes |
|
|
| `VertDPI` | `u32` | Yes |
|
|
| `Format` | `u16` | Yes |
|
|
| `BitDepth` | `u16` | No |
|
|
| `Components` | `u16` | Yes |
|
|
| `CompDepth` | `u16` | Yes |
|
|
| `PlaneOffs` | `u32` | Yes |
|
|
| `ClutId` | `u32` | Yes |
|
|
|
|
### Color Table ###
|
|
|
|
Color Table is 8 bytes.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Index` | `u16` | `0` |
|
|
| `Red` | `u16` | `2` |
|
|
| `Green` | `u16` | `4` |
|
|
| `Blue` | `u16` | `6` |
|
|
|
|
- `Index` is ignored if device mapping is used.
|
|
|
|
### Header Op ###
|
|
|
|
Header Op is 24 bytes.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Version` | `u16` | `0` |
|
|
| `Width` | `u32` | `4` |
|
|
| `Height` | `u32` | `8` |
|
|
| `Top` | `u16` | `12` |
|
|
| `Left` | `u16` | `14` |
|
|
| `Bottom` | `u16` | `16` |
|
|
| `Right` | `u16` | `18` |
|
|
|
|
## Shapes ##
|
|
|
|
Shapes files start with exactly 32 Collection Headers, followed by everything
|
|
else. Use the offsets provided by these structures to find where all of the
|
|
data is.
|
|
|
|
### Collection Header ###
|
|
|
|
Collection Header is 32 bytes. Each collection may have two versions, lo-res
|
|
and hi-res, which are used according to the user's settings. The main purpose
|
|
of these is for compatibility with older Macs which might not have enough video
|
|
memory for, for instance, the huge two mebibyte sky boxes that Marathon 2 has.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `OffsetLo` | `u32` | `4` |
|
|
| `LengthLo` | `u32` | `8` |
|
|
| `OffsetHi` | `u32` | `12` |
|
|
| `LengthHi` | `u32` | `16` |
|
|
|
|
### Collection Definition ###
|
|
|
|
Collection Definition is 544 bytes (no, I'm not kidding, there are actually
|
|
that many unused bytes.) The sequences, frames and bitmaps have their
|
|
individual offsets stored in tables, which themselves are at offsets specified
|
|
by this structure. Note that all offsets (including those in offset tables) are
|
|
relative to the start of this structure.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Version` | `u16` | `0` |
|
|
| `Type` | `u16` | `2` |
|
|
| `Colors` | `u16` | `6` |
|
|
| `TabNum` | `u16` | `8` |
|
|
| `TabOfs` | `u16` | `10` |
|
|
| `SeqNum` | `u16` | `12` |
|
|
| `SeqOfs` | `u16` | `14` |
|
|
| `FrmNum` | `u16` | `16` |
|
|
| `FrmOfs` | `u16` | `18` |
|
|
| `BmpNum` | `u16` | `20` |
|
|
| `BmpOfs` | `u16` | `22` |
|
|
|
|
- `Version` should always be `3`, but this isn't checked by the engine.
|
|
- `Type` is a Collection Type enumeration.
|
|
- `TabNum` and `TabOfs` are the number of and offset to the color tables.
|
|
- `SeqNum` and `SeqOfs` are the number of sequences and the offset to their
|
|
offset table.
|
|
- `FrmNum` and `FrmOfs` are the number of frames and the offset to their offset
|
|
table.
|
|
- `BmpNum` and `BmpOfs` are the number of bitmaps and the offset to their
|
|
offset table.
|
|
|
|
### Frame ###
|
|
|
|
Frame is 36 bytes. TODO: document how world transform works.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Flags` | `u16` | `0` |
|
|
| `MinLight` | `fixed` | `2` |
|
|
| `BmpIndex` | `u16` | `6` |
|
|
| `WldLeft` | `unit` | `14` |
|
|
| `WldRight` | `unit` | `16` |
|
|
| `WldTop` | `unit` | `18` |
|
|
| `WldBottom` | `unit` | `20` |
|
|
| `WldOrigX` | `unit` | `22` |
|
|
| `WldOrigY` | `unit` | `24` |
|
|
|
|
- `Flags` is a Frame Flags bit field.
|
|
- `MinLight` is the minimum light intensity (0-1.)
|
|
- `BmpIndex` is an Object ID for the bitmap index.
|
|
|
|
### Sequence ###
|
|
|
|
Sequence is 88 bytes. A sequence, also known as a "high level shape" in the
|
|
engine, is essentially a potentially animated sequence of frames organized into
|
|
angular views which may loop or play sounds. Each sequence has a "key frame"
|
|
which is used for determining when to run action code or play an attached
|
|
sound.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Name` | `u8[34]` | `4` |
|
|
| `ViewType` | `u16` | `38` |
|
|
| `FrameNum` | `u16` | `40` |
|
|
| `FrameTick` | `u16` | `42` |
|
|
| `FrameKey` | `u16` | `44` |
|
|
| `XferMode` | `u16` | `46` |
|
|
| `XferPeriod` | `u16` | `48` |
|
|
| `SndBeg` | `u16` | `50` |
|
|
| `SndKey` | `u16` | `52` |
|
|
| `SndEnd` | `u16` | `54` |
|
|
| `FrameLoop` | `u16` | `58` |
|
|
|
|
- `Name` is the sequence name, used mainly by editors, supposed to be 33 bytes,
|
|
but due to padding, the real length is 34.
|
|
- `ViewType` is a View Type enumeration.
|
|
- `FrameNum` is the number of frames in this sequence.
|
|
- `FrameTick` is the number of ticks per frame.
|
|
- `FrameKey` is the index of the key frame.
|
|
- `XferMode` is a Transfer Mode enumeration.
|
|
- `XferPeriod` is the period for the transfer mode in 1/30ths seconds.
|
|
- `SndBeg`, `SndKey` and `SndEnd` are the sounds played at the first, key and
|
|
last frame of this sequence.
|
|
|
|
### Bitmap Header ###
|
|
|
|
Bitmap Header is 26 bytes.
|
|
|
|
Each Bitmap Header is followed by either `Height * 4` or `Width * 4` empty
|
|
bytes which must be skipped.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Width` | `u16` | `0` |
|
|
| `Height` | `u16` | `2` |
|
|
| `Pitch` | `u16` | `4` |
|
|
| `Flags` | `u16` | `6` |
|
|
| `Depth` | `u16` | `8` |
|
|
|
|
- `Width` is the number of pixels on the horizontal axis.
|
|
- `Height` is the number of pixels on the vertical axis.
|
|
- `Pitch` is either the number of pixels per row if row ordered, per column if
|
|
column ordered, or `65535` if the data is transparency RLE compressed.
|
|
- `Flags` is a Bitmap Flags bit field.
|
|
- `Depth` must always be `8`.
|
|
|
|
## Sounds ##
|
|
|
|
Sounds files start with a header followed by all of the actual sound
|
|
definitions. Each sound starts with a Carbon Sound Header.
|
|
|
|
### Sounds Header ###
|
|
|
|
Sounds Header is 260 bytes. (Seriously, what's with these formats and
|
|
horrifically excessive padding?)
|
|
|
|
This header is followed by `SrcNum * SndNum` Sound Definitions.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Version` | `u32` | `0` |
|
|
| `Magic` | `u8[4]` | `4` |
|
|
| `SrcNum` | `u16` | `8` |
|
|
| `SndNum` | `u16` | `10` |
|
|
|
|
- `Version` is always `1`.
|
|
- `Magic` is always `"snd2"`.
|
|
- `SrcNum` defines the number of sound formats this file provides, similar to
|
|
Shapes' lo- and hi-res collections, although this applies to the entire file
|
|
and not just parts of it. `0` is invalid for this field, and in the original
|
|
Marathon 2 engine (on Mac only, not on Windows,) it must be `2` because of
|
|
QuickTime. A value of `1` means "8-bit 22kHz only" and a value of `2` means
|
|
"both 8-bit 22kHz and 16-bit 22kHz."
|
|
|
|
### Sound Definition ###
|
|
|
|
Sound Definition is 64 bytes.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Code` | `u16` | `0` |
|
|
| `Volume` | `u16` | `2` |
|
|
| `Flags` | `u16` | `4` |
|
|
| `Chance` | `u16` | `6` |
|
|
| `PitchLo` | `fixed` | `8` |
|
|
| `PitchHi` | `fixed` | `12` |
|
|
| `NumOfs` | `u16` | `16` |
|
|
| `GroupOffset` | `u32` | `20` |
|
|
| `Size` | `u32` | `24` |
|
|
| `GroupSize` | `u32` | `28` |
|
|
| `AddOffset` | `u32[5]` | `32` |
|
|
|
|
- `Code` is an Object ID referencing something (TODO.)
|
|
- `Volume` is a Sound Behaviour enumeration.
|
|
- `Flags` is a Sound Definition Flags bit field.
|
|
- `Chance` is the chance out of `65535` that the sound will not play.
|
|
- `PitchLo` is the lower random pitch bound, if `0` then it will be `1.0`.
|
|
- `PitchHi` is the high random pitch bound, if `0` then it will be `PitchLo`.
|
|
- `NumOfs` is the number of random sounds to pick from `AddOffset`.
|
|
- `GroupOffset` is the starting offset for each additive sound offset.
|
|
- `Size` is the sound of an individual sound in the group.
|
|
- `GroupSize` is the total size of all sounds in the group.
|
|
- `AddOffset` is the offset added to `GroupOffset` to get an individual sound.
|
|
While it is an array of `NumOfs` offsets, it has a fixed size in the format.
|
|
|
|
### Carbon Sound Header ###
|
|
|
|
Carbon Sound Header is 21 bytes.
|
|
|
|
The sound format is from Carbon's `SoundHeader` structures. It's used primarily
|
|
in System 7 programs as `snd` resources but in OS X it was deprecated in favor
|
|
of QuickTime. HFS still has Resource Forks but they aren't used anymore. I
|
|
don't imagine this format was ever used for anything else, except for Marathon,
|
|
which embeds it in the Sound files directly, instead of using `snd` resources
|
|
(which have a larger structure consisting of a resource header and sound
|
|
commands rather than just the header and sample data.)
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Size` | `u32` | `4` |
|
|
| `SampleRate` | `u16` | `8` |
|
|
| `LoopBeg` | `u32` | `12` |
|
|
| `LoopEnd` | `u32` | `16` |
|
|
| `Magic` | `u8` | `20` |
|
|
|
|
- If `Magic` is `$00` nothing else needs to be done and raw unsigned 8-bit mono
|
|
PCM sample data starts at byte 22. If it is `$FF` it is followed by a Carbon
|
|
Extended Sound Header, or if it is `$FE` it is followed by a Carbon Compressed
|
|
Sound Header. The compressed sound header is not documented because it is not
|
|
actually used by Marathon.
|
|
|
|
### Carbon Extended Sound Header ###
|
|
|
|
Carbon Extended Sound Header is 42 bytes.
|
|
|
|
The extended sound header contains more useless information and even several
|
|
fields that do absolutely nothing. Wow. At least it can store 16 bit samples.
|
|
It also has an 80-bit float in it, which horrifies me greatly. There's only one
|
|
actually useful field.
|
|
|
|
| Name | Type | Offset |
|
|
| ---- | ---- | ------ |
|
|
| `Frames` | `u32` | `0` |
|
|
| `SampleBits` | `u16` | `26` |
|
|
|
|
- `Frames` is used instead of `Size` for sounds with this header, since it
|
|
represents how many frames there are rather than how many bytes. Even though
|
|
this is actually a pointless distinction and `Size` is left at `1` anyway.
|
|
- `SampleBits` must be either `16` or `8`. If it is `16` then the sample data
|
|
is signed 16-bit *little endian* mono PCM.
|
|
|
|
# ENUMERATIONS ################################################################
|
|
|
|
Here is a list of names and descriptions for enumerations used throughout this
|
|
document. The names may not match those used in the original engine and are
|
|
re-named for clarity of purpose.
|
|
|
|
### Picture Opcode ###
|
|
|
|
Operations used in QuickDraw images. Aleph One ignores most of these, so it's
|
|
only necessary to document what's ignored and how to process CopyBits. (If
|
|
you're interested in the QuickDraw format, Apple has legacy documents still
|
|
available on the Internet.)
|
|
|
|
Opcodes `$0100` through `$7FFF` are skipped by seeking forward by the most
|
|
significant byte's value times two.
|
|
|
|
Opcodes `$8000` through `$8100` are reserved and therefore ignored.
|
|
|
|
Any unspecified opcodes are not worth skipping, and the state machine should
|
|
exit upon reading them.
|
|
|
|
| Name | Value | Ignored | Extra data |
|
|
| ---- | ----- | :-----: | ---------- |
|
|
| `NoOp` | `$0000` | No | None |
|
|
| `Clip` | `$0001` | Yes | `u16 Size`, `(Size & ~1) - 2`B |
|
|
| `BkPat` | `$0002` | Yes | 8B |
|
|
| `TxFont` | `$0003` | Yes | 2B |
|
|
| `TxFace` | `$0004` | Yes | 2B |
|
|
| `TxMode` | `$0005` | Yes | 2B |
|
|
| `SpExtra` | `$0006` | Yes | 4B |
|
|
| `PnSize` | `$0007` | Yes | 4B |
|
|
| `PnMode` | `$0008` | Yes | 2B |
|
|
| `PnPat` | `$0009` | Yes | 8B |
|
|
| `FillPat` | `$000A` | Yes | 8B |
|
|
| `OvSize` | `$000B` | Yes | 4B |
|
|
| `Origin` | `$000C` | Yes | 4B |
|
|
| `TxSize` | `$000D` | Yes | 2B |
|
|
| `FgColor` | `$000E` | Yes | 4B |
|
|
| `BgColor` | `$000F` | Yes | 4B |
|
|
| `TxRatio` | `$0010` | Yes | 8B |
|
|
| `VersionOp` | `$0011` | Yes | 2B |
|
|
| `PnLocHFrac` | `$0015` | Yes | 2B |
|
|
| `ChExtra` | `$0016` | Yes | 2B |
|
|
| `RGBFgCol` | `$001A` | Yes | 6B |
|
|
| `RGBBkCol` | `$001B` | Yes | 6B |
|
|
| `HiliteMode` | `$001C` | Yes | None |
|
|
| `HiliteColor` | `$001D` | Yes | 6B |
|
|
| `DefHilite` | `$001E` | Yes | None |
|
|
| `OpColor` | `$001F` | Yes | 6B |
|
|
| `Line` | `$0020` | Yes | 8B |
|
|
| `LineFrom` | `$0021` | Yes | 4B |
|
|
| `ShortLine` | `$0022` | Yes | 6B |
|
|
| `ShortLineFrom` | `$0023` | Yes | 2B |
|
|
| `LineJustify` | `$002D` | Yes | 10B |
|
|
| `GlyphState` | `$002E` | Yes | 8B |
|
|
| `FrameRect` | `$0030` | Yes | 8B |
|
|
| `PaintRect` | `$0031` | Yes | 8B |
|
|
| `EraseRect` | `$0032` | Yes | 8B |
|
|
| `InvertRect` | `$0033` | Yes | 8B |
|
|
| `FillRect` | `$0034` | Yes | 8B |
|
|
| `FrameSameRect` | `$0038` | Yes | None |
|
|
| `PaintSameRect` | `$0039` | Yes | None |
|
|
| `EraseSameRect` | `$003A` | Yes | None |
|
|
| `InvertSameRect` | `$003B` | Yes | None |
|
|
| `FillSameRect` | `$003C` | Yes | None |
|
|
| `PackBitsRect` | `$0098` | No | CopyBits structure |
|
|
| `PackBitsRgn` | `$0099` | No | CopyBits structure |
|
|
| `DirectBitsRect` | `$009A` | No | CopyBits structure |
|
|
| `DirectBitsRgn` | `$009B` | No | CopyBits structure |
|
|
| `ShortComment` | `$00A0` | Yes | 2B |
|
|
| `LongComment` | `$00A1` | Yes | 2B, `u16 Size`, `Size & ~1`B |
|
|
| `OpEndPic` | `$00FF` | No | 2B |
|
|
| `Version` | `$02FF` | Yes | 2B |
|
|
| `HeaderOp` | `$0C00` | Yes | Header Op structure |
|
|
| `CompressedQuickTime` | `$8200` | No | QuickTime Image structure |
|
|
|
|
### CopyBits Pixel Depth ###
|
|
|
|
| Name | Value | Description |
|
|
| ---- | ----- | ----------- |
|
|
| `Pal1` | `1` | Color mapped bit |
|
|
| `Pal2` | `2` | Color mapped dibit |
|
|
| `Pal4` | `4` | Color mapped nibble |
|
|
| `Pal8` | `8` | Color mapped byte |
|
|
| `X1RGB5` | `16` | X1RGB5 |
|
|
| `RGB8` | `32` | RGB8 (if NoPad) or XRGB8 |
|
|
|
|
### Pack Type ###
|
|
|
|
| Name | Value | Description |
|
|
| ---- | ----- | ----------- |
|
|
| `Default` | `0` | Always pack |
|
|
| `None` | `1` | Never pack |
|
|
| `NoPad` | `2` | Never pack, no padding channel in 32bpp mode |
|
|
| `RLE16` | `3` | Only pack in 16bpp mode |
|
|
| `RLE32` | `4` | Only pack in 32bpp mode, no padding channel |
|
|
|
|
### Polygon Type ###
|
|
|
|
| Name | Value | Description | Permutation |
|
|
| ---- | ----- | ----------- | ----------- |
|
|
| `Normal` | `0` | Normal, no effects | None |
|
|
| `ImpassItem` | `1` | Items may not pass | None |
|
|
| `ImpassMons` | `2` | Monsters may not pass | None |
|
|
| `Hill` | `3` | Hill (for King of the Hill) | None |
|
|
| `Base` | `4` | Base (for Capture The Flag et al) | Team |
|
|
| `Platform` | `5` | Platform | Plat index |
|
|
| `TrigLightOn` | `6` | Triggers light on | Light index |
|
|
| `TrigPlatOn` | `7` | Triggers platform on | Plat index |
|
|
| `TrigLightOff` | `8` | Triggers light off | Poly index |
|
|
| `TrigPlatOff` | `9` | Triggers platform off | Poly index |
|
|
| `Teleporter` | `10` | Teleports to polygon centroid | Poly index |
|
|
| `ZoneBorder` | `11` | Zone border | None |
|
|
| `Goal` | `12` | Goal point | None |
|
|
| `TrigMonsVis` | `13` | Triggers near-by visible monsters | None |
|
|
| `TrigMonsInv` | `14` | Triggers near-by invisible monsters | None |
|
|
| `TrigMonsDual` | `15` | Same as TrigMonsInv | None |
|
|
| `TrigItems` | `16` | Triggers near-by invisible items | None |
|
|
| `MustExplore` | `17` | Must be entered for Exploration | None |
|
|
| `AutoExit` | `18` | Teleports to next level if success | None |
|
|
|
|
### Control Panel Type ###
|
|
|
|
This is used internally for each control panel preset and determines the
|
|
permutation each one uses.
|
|
|
|
| Name | Value | Description | Permutation |
|
|
| ---- | ----- | ----------- | ----------- |
|
|
| `Oxygen` | `0` | Oxygen refuel | None |
|
|
| `Shield` | `1` | Health charger | None |
|
|
| `Shield2x` | `2` | Health charger (2x) | None |
|
|
| `Shield3x` | `3` | Health charger (3x) | None |
|
|
| `Light` | `4` | Light switch | Light index |
|
|
| `Platform` | `5` | Platform switch | Plat index |
|
|
| `Tag` | `6` | Tag switch | Tag or -1 |
|
|
| `PatternBuf` | `7` | Save station | None |
|
|
| `Terminal` | `8` | Computer terminal | None |
|
|
|
|
### Side Type ###
|
|
|
|
| Name | Value | Description |
|
|
| ---- | ----- | ----------- |
|
|
| `Full` | `0` | First texture is mapped over the whole side |
|
|
| `High` | `1` | First texture is mapped on the ceiling panel |
|
|
| `Low` | `2` | First texture is mapped on the floor panel |
|
|
| `Composite` | `3` | Composite texture (Not implemented) |
|
|
| `Split` | `4` | First texture for ceiling panel, second for floor |
|
|
|
|
"Panel" here refers to a protrusion in between two polygons. These would be
|
|
mapped to upper/lower textures in Doom for instance. Even the source code for
|
|
Marathon 2 itself acknowledges how redundant this enumeration is.
|
|
|
|
### Saved Object Group ###
|
|
|
|
| Name | Value | Description |
|
|
| ---- | ----- | ----------- |
|
|
| TODO | `0` | Monster |
|
|
| TODO | `1` | Object |
|
|
| TODO | `2` | Item |
|
|
| TODO | `3` | Player |
|
|
| TODO | `4` | Goal |
|
|
| TODO | `5` | Sound source (facing is sound volume) |
|
|
|
|
### Transfer Mode ###
|
|
|
|
| Name | Value | Description |
|
|
| ---- | ----- | ----------- |
|
|
| `Normal` | `0` | Normal |
|
|
| `FadeBlack` | `1` | Fade to black |
|
|
| `Invisibility` | `2` | Invisibility |
|
|
| `Invisibility2` | `3` | Invisibility (subtle) |
|
|
| `Pulsate` | `4` | Pulsate (polygons only) |
|
|
| `Wobble` | `5` | Wobble (polygons only) |
|
|
| `Wobble2` | `6` | Wobble (fast, polygons only) |
|
|
| `Static` | `7` | Static |
|
|
| `Static2` | `8` | 50% static |
|
|
| `Sky` | `9` | Sky |
|
|
| `Smear` | `10` | Smear |
|
|
| `StaticFade` | `11` | Static (fade out) |
|
|
| `StaticPulse` | `12` | Static (pulsating) |
|
|
| `FoldIn` | `13` | Fold-in |
|
|
| `FoldOut` | `14` | Fold-out |
|
|
| `SlideHorz` | `15` | Horizontal slide |
|
|
| `SlideHorz2` | `16` | Horizontal slide (fast) |
|
|
| `SlideVert` | `17` | Vertical slide |
|
|
| `SlideVert2` | `18` | Vertical slide (fast) |
|
|
| `Wander` | `19` | Wander |
|
|
| `Wander2` | `20` | Wander (fast) |
|
|
| `BigSky` | `21` | Big sky |
|
|
|
|
### Light Type ###
|
|
|
|
| Name | Value | Description |
|
|
| ---- | ----- | ----------- |
|
|
| `Normal` | `0` | Normal light |
|
|
| `Strobe` | `1` | Strobe light |
|
|
| `Media` | `2` | Media light |
|
|
|
|
### Wad Version ###
|
|
|
|
Used to determine how the engine loads the Wad file.
|
|
|
|
| Name | Value |
|
|
| ---- | ----- |
|
|
| `VerBase` | `0` |
|
|
| `VerDir` | `1` |
|
|
| `VerOver` | `2` |
|
|
| `VerMI` | `4` |
|
|
|
|
- `VerBase` has no directory entry.
|
|
- `VerDir` has a directory entry.
|
|
- `VerOver` supports data overlays.
|
|
- `VerMI` is used for Marathon Infinity data.
|
|
|
|
### Data Version ###
|
|
|
|
Used to determine how the engine loads map data.
|
|
|
|
| Name | Value |
|
|
| ---- | ----- |
|
|
| `DataM1` | `0` |
|
|
| `DataM2` | `1` |
|
|
|
|
- `DataM1` means Marathon 1 map data.
|
|
- `DataM2` means Marathon 2 map data.
|
|
|
|
### Terminal Group Type ###
|
|
|
|
| Name | Value | Permutation |
|
|
| ---- | ----- | ----------- |
|
|
| `Logon` | `0` | None |
|
|
| `Unfinished` | `1` | None |
|
|
| `Success` | `2` | None |
|
|
| `Failure` | `3` | None |
|
|
| `Info` | `4` | None |
|
|
| `End` | `5` | None |
|
|
| `TeleInter` | `6` | Level ID |
|
|
| `TeleIntra` | `7` | Polygon ID |
|
|
| `Checkpoint` | `8` | Goal ID |
|
|
| `Sound` | `9` | Sound ID |
|
|
| `Movie` | `10` | Movie ID |
|
|
| `Track` | `11` | Track ID |
|
|
| `Pict` | `12` | Pict ID |
|
|
| `Logoff` | `13` | None |
|
|
| `Camera` | `14` | Object ID |
|
|
| `Static` | `15` | 1/30 secs |
|
|
| `Tag` | `16` | Tag number |
|
|
|
|
### Terminal Color ###
|
|
|
|
These are the default colors. These can be overridden with mods.
|
|
|
|
| Name | Value |
|
|
| ---- | ----- |
|
|
| `LightGreen` | `0` |
|
|
| `White` | `1` |
|
|
| `Red` | `2` |
|
|
| `DarkGreen` | `3` |
|
|
| `LightBlue` | `4` |
|
|
| `Yellow` | `5` |
|
|
| `DarkRed` | `6` |
|
|
| `DarkBlue` | `7` |
|
|
| `Color8` | `8` |
|
|
| `Color9` | `9` |
|
|
|
|
### Sound Behaviour ###
|
|
|
|
Sound behaviours are used to determine falloff and volume bounds of a sound.
|
|
|
|
| Name | Value |
|
|
| ---- | ----- |
|
|
| `Quiet` | `0` |
|
|
| `Normal` | `1` |
|
|
| `Loud` | `2` |
|
|
|
|
- `Quiet` sounds will not be heard at all when obstructed, and only play at
|
|
full volume point-blank. They fall off very quickly, with a range of only 5
|
|
world units.
|
|
- `Normal` sounds will be heard at at most half volume when obstructed, and
|
|
fall off at 10 world units unobstructed.
|
|
- `Loud` sounds will be heard at 3/4 volume when obstructed and can be heard at
|
|
full volume for twice the distance as a normal sound, and fall off at 15 units
|
|
unobstructed.
|
|
|
|
### Light Function ###
|
|
|
|
| Name | Value |
|
|
| ---- | ----- |
|
|
| `Constant` | `0` |
|
|
| `Linear` | `1` |
|
|
| `Smooth` | `2` |
|
|
| `Flicker` | `3` |
|
|
|
|
- `Constant` maintains the final intensity for `Period`.
|
|
- `Linear` transitions between the initial and final intensities over `Period`.
|
|
- `Smooth` does a sine transition in the same fashion as `Linear`.
|
|
- `Flicker` flickers between a random smoothed intensity and the final one.
|
|
|
|
# FLAGS #######################################################################
|
|
|
|
### Endpoint Flags ###
|
|
|
|
| Name | Bit |
|
|
| ---- | --- |
|
|
| `Solid` | `0` |
|
|
| `SameHeight` | `1` |
|
|
| `Transparent` | `2` |
|
|
|
|
- `Solid` means the point belongs to a solid line.
|
|
- `SameHeight` means all polygons with this point have the same height,
|
|
relative to the point's lines
|
|
- `Transparent` means the point does not belong to an opaque line.
|
|
|
|
### Line Flags ###
|
|
|
|
| Name | Bit |
|
|
| ---- | --- |
|
|
| `TransSide` | `9` |
|
|
| `ElevVar` | `10` |
|
|
| `Elevation` | `11` |
|
|
| `Landscape` | `12` |
|
|
| `Transparent` | `13` |
|
|
| `Solid` | `14` |
|
|
|
|
- `TransSide` means the line has a transparent side.
|
|
- `ElevVar` means polygons on both sides do not have the same heights.
|
|
- `Elevation` means there is a differing height between this line's polygons.
|
|
- `Landscape` means this line shows only sky.
|
|
- `Transparent` means both sides are see-through.
|
|
- `Solid` means the line cannot be walked through.
|
|
|
|
### Side Flags ###
|
|
|
|
| Name | Bit |
|
|
| ---- | --- |
|
|
| `Status` | `0` |
|
|
| `Panel` | `1` |
|
|
| `Repair` | `2` |
|
|
| `ItemUse` | `3` |
|
|
| `Lighted` | `4` |
|
|
| `CanDestroy` | `5` |
|
|
| `HitOnly` | `6` |
|
|
| `ItemOpt` | `7` |
|
|
|
|
- `Status` means the panel is switched already.
|
|
- `Panel` means the side is a control panel.
|
|
- `Repair` means the panel must be switched for Repair.
|
|
- `ItemUse` means the panel uses an item (for scripts, unused otherwise.)
|
|
- `Lighted` means the panel must be 3/4ths or more lit up to be used.
|
|
- `CanDestroy` makes projectiles toggle and disable this panel.
|
|
- `HitOnly` means the panel can only be hit by projectiles.
|
|
- `ItemOpt` means the item is optional for this panel (for scripts.)
|
|
|
|
### Polygon Flags ###
|
|
|
|
| Name | Bit |
|
|
| ---- | --- |
|
|
| `Detached` | `14` |
|
|
|
|
### Map Object Flags ###
|
|
|
|
| Name | Bit |
|
|
| ---- | --- |
|
|
| `Invisible` | `0` |
|
|
| `Ceiling` | `1` |
|
|
| `Blind` | `2` |
|
|
| `Deaf` | `3` |
|
|
| `Floating` | `4` |
|
|
| `NetOnly` | `5` |
|
|
|
|
- `Invisible` makes the object initially invisible (warps in.)
|
|
- `Ceiling` reverses the Z coordinate (from the ceiling.)
|
|
- `Blind` makes the object unable to be activated by sight.
|
|
- `Deaf` makes the object unable to be activated by sound.
|
|
- `NetOnly` makes the object only show up in net-games (items only.)
|
|
|
|
### Mission Flags ###
|
|
|
|
| Name | Bit |
|
|
| ---- | --- |
|
|
| `Extermination`| `0` |
|
|
| `Exploration` | `1` |
|
|
| `Retrieval` | `2` |
|
|
| `Repair` | `3` |
|
|
| `Rescue` | `4` |
|
|
|
|
- `Extermination` means you must kill a certain percentage of monsters.
|
|
- `Exploration` means you must explore marked polygons.
|
|
- `Retrieval` means you must grab marked items.
|
|
- `Repair` means you must flip marked switches.
|
|
- `Rescue` means you must keep a certain percentage of BoBs alive.
|
|
|
|
### Environment Flags ###
|
|
|
|
| Name | Bit |
|
|
| ---- | --- |
|
|
| `Vacuum` | `0` |
|
|
| `Magnetic` | `1` |
|
|
| `Rebellion` | `2` |
|
|
| `LowGrav` | `3` |
|
|
| `M1Glue` | `4` |
|
|
| `LavaFloor` | `5` |
|
|
| `Rebellion2` | `6` |
|
|
| `Music` | `7` |
|
|
| `TermPause` | `8` |
|
|
| `M1Monster` | `9` |
|
|
| `M1Weps` | `10` |
|
|
| `NetPlay` | `13` |
|
|
| `Solo` | `14` |
|
|
|
|
- `Vacuum` makes most weapons not work and oxygen deplete.
|
|
- `Magnetic` fucks up the motion sensor.
|
|
- `Rebellion` makes S'pht friendly and strips items and health.
|
|
- `LowGrav` lowers gravity.
|
|
- `M1Glue` makes glue handle like Marathon 1.
|
|
- `LavaFloor` makes the floor damage you.
|
|
- `Rebellion2` is the same as `Rebellion` but does not strip items/health.
|
|
- `Music` makes the level have music.
|
|
- `TermPause` makes terminals stop time (in Solo only.)
|
|
- `M1Monster` sets monster activation limits to Marathon 1's.
|
|
- `M1Weps` changes weapon pickups on Total Carnage and makes grenades low
|
|
gravity.
|
|
- `NetPlay` marks the map as net-play compatible.
|
|
- `Solo` marks the map as solo compatible.
|
|
|
|
### Light Flags ###
|
|
|
|
| Name | Bit |
|
|
| ---- | --- |
|
|
| `InitActive` | `0` |
|
|
| `SlaveValue` | `1` |
|
|
| `Stateless` | `2` |
|
|
|
|
### Entry Point Flags ###
|
|
|
|
| Name | Bit |
|
|
| ---- | --- |
|
|
| `Solo` | `0` |
|
|
| `Co-op` | `1` |
|
|
| `Carnage` | `2` |
|
|
| `KTMWTB` | `3` |
|
|
| `KOTH` | `4` |
|
|
| `Defense` | `5` |
|
|
| `Rugby` | `6` |
|
|
| `CTF` | `7` |
|
|
|
|
- `KTMWTB` is Kill The Man With The Ball.
|
|
|
|
### Terminal Flags ###
|
|
|
|
| Name | Bit |
|
|
| ---- | --- |
|
|
| `Encoded` | `0` |
|
|
|
|
### Terminal Group Flags ###
|
|
|
|
| Name | Bit |
|
|
| ---- | --- |
|
|
| `DrawOnRight` | `0` |
|
|
| `DrawCenter` | `1` |
|
|
|
|
### CopyBits Flags ###
|
|
|
|
| Name | Bit |
|
|
| ---- | --- |
|
|
| `PICT2` | `15` |
|
|
|
|
### Color Table Flags ###
|
|
|
|
| Name | Bit |
|
|
| ---- | --- |
|
|
| `DeviceMap` | `15` |
|
|
|
|
### Frame Flags ###
|
|
|
|
| Name | Bit |
|
|
| ---- | --- |
|
|
| `Obscure` | `13` |
|
|
| `FlipY` | `14` |
|
|
| `FlipX` | `15` |
|
|
|
|
- `Obscure` makes the player's torso obscure the legs.
|
|
- `FlipY` and `FlipX` flip pixels on the respective axis.
|
|
|
|
### Sound Definition Flags ###
|
|
|
|
| Name | Bit |
|
|
| ---- | --- |
|
|
| `NoRestart` | `0` |
|
|
| `NoChannelSwitch` | `1` |
|
|
| `LessPitchChange` | `2` |
|
|
| `NoPitchChange` | `3` |
|
|
| `NoObstruction` | `4` |
|
|
| `NoMediaObstruct` | `5` |
|
|
| `Ambient` | `6` |
|
|
|
|
<!-- EOF -->
|