# LICENSING ################################################################### To the extent possible under law, I, Alison Watson, have waived all copyright and related or neighboring rights to this Document as described by the Creative Commons Zero license included in this project under the `LICENSE` file, or if unavailable, the link below: 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.) Any other copyrights not mentioned here belong to their respective owners and not me. If you need explanation on anything in this document don't hesitate to ask me. Contact information is available at . # 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 ; ... content ... #LOGOFF 1600 ehhg.431.4122// ``` ### `#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 and then goes to the next level. 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. Map tags: | Name | Description | | ---- | ----------- | | `Minf` | Static Map Info structure | | `PNTS` | Array of Point | | `EPNT` | Array of Endpoint | | `LINS` | Array of Line | | `SIDS` | Array of Side | | `POLY` | Array of Polygon | | `LITE` | Array of Light | | `NOTE` | Array of Annotation | | `OBJS` | Array of Object | | `plac` | Array of Object Frequency | | `plat` | Array of Platform Data | | `medi` | Array of Media Data | | `ambi` | Array of Ambient Sound | | `bonk` | Array of Random Sound | | `term` | Array of Terminal | | `NAME` | NTBS containing map name | | `påth` | Unused, supposed to be guardpaths (å is $8C) | | `door` | Unused, supposed to be extra door data | Map files can be identified by the `Minf` chunk. Maps 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` can be loaded directly into memory by the engine. `EPNT` also tells the engine that the map is preprocessed and that `iidx` and `PLAT` chunks also exist. With `DataVersion` as `DataM1`, the format must always be preprocessed. Physics tags: | Name | Description | | ---- | ----------- | | `FXpx` | Array of Effect Definition | | `MNpx` | Array of Monster Definition | | `PRpx` | Array of Projectile Definition | | `PXpx` | Array of Physics Definition | | `WPpx` | Array of Weapon Definition | Physics definitions may be embedded into a map in Infinity and Aleph One, so the only reliable way to check if something is a pure physics file is by checking that there are no chunks other than `**px` chunks. Image tags: | Name | Description | | ---- | ----------- | | `PICT` | Picture Resource | | `clut` | Banished to the shadow realm | Images can be identified by the `PICT` chunk. Save file tags: | Name | Description | | ---- | ----------- | | `plyr` | Not analyzed (saved player data) | | `dwol` | Not analyzed (saved dynamic world data) | | `mobj` | Not analyzed (saved object data) | | `iidx` | Not analyzed (saved map indices) | | `alin` | Not analyzed (saved automap lines) | | `apol` | Not analyzed (saved automap polygons) | | `mOns` | Not analyzed (saved monsters) | | `fx ` | Not analyzed (saved effects) | | `bang` | Not analyzed (saved projectiles) | | `PLAT` | Not analyzed (saved platform data) | | `weap` | Not analyzed (saved weapon state) | | `cint` | Not analyzed (saved terminal state) | Preferences tags: | Name | Description | | ---- | ----------- | | `graf` | Not analyzed (graphics prefs) | | `serl` | Not analyzed (serial code) | | `netw` | Not analyzed (network prefs) | | `plyr` | Not analyzed (player prefs) | | `inpu` | Not analyzed (input prefs) | | `snd ` | Not analyzed (sound prefs) | | `envr` | Not analyzed (environment prefs) | Aleph One tags: | Name | Description | | ---- | ----------- | | `ShPa` | Not analyzed (shapes) | | `MMLS` | Not analyzed (MML scripts) | | `LUAS` | Not analyzed (Lua scripts) | ## 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. Because they're actually 16-bit, the real format is 6.9s, but the integral part is ignored. "No angle" is represented by 65510 (-1.9) for some reason. The type "`unit`" refers to a 16-bit fixed point number with the format 5.10s. This is used for all world coordinates. A "`u16opt`" 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` | `fixed` | `6` | | `DeltaValue` | `fixed` | `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` | `u16opt` | `4` | - `TextureId` references 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` | `u16opt` | `12` | | `SideBack` | `u16opt` | `14` | | `PolyFrnt` | `u16opt` | `16` | | `PolyBack` | `u16opt` | `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 indices of the Sides in the front and back. - `PolyFrnt` and `PolyBack` are 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. Middle textures are not supported if `DataVersion` is `DataM1` and so `TexTra` must be set to none. - `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. If `DataVersion` is `DataM1`, this must be set to 0. ### 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.) Note that `u16opt`s not available with `DataM1` must be set to none. | 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` | If `DataVersion` is not `DataM1`: | Name | Type | Offset | | ---- | ---- | ------ | | `OrigFlr` | `struct` | `108` | | `OrigCei` | `struct` | `112` | | `Media` | `u16opt` | `116` | | `MediaLight` | `u16` | `118` | | `SoundIndices` | `u16` | `120` | | `SoundAmbient` | `u16opt` | `122` | | `SoundRandom` | `u16opt` | `124` | - `Type` is a Polygon Type enumeration, unless `DataVersion` is `DataM1`, where it is instead an Old 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. ### Light ### Light is 100 bytes. If `DataVersion` is `DataM1` this is an Old Light. | 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. ### Old Light ### Old Light is 32 bytes. The old lighting system not only sucked, but there was no Media system, so it was even more useless as it couldn't be used as a controller for liquids. So, because of these issues, the new lighting system was put in place, but it was incompatible data-wise because it had too many extensions. | Name | Type | Offset | | ---- | ---- | ------ | | `Type` | `u16` | `2` | | `Mode` | `u16` | `4` | | `Phase` | `u16` | `6` | | `ValueMin` | `fixed` | `8` | | `ValueMax` | `fixed` | `12` | | `Period` | `u16` | `16` | | `ValueCur` | `fixed` | `18` | - `Type` is an Old Light Type enumeration. To create a new light from this, you will need to write a lookup table which imitates each light type in the new lighting system. This table is tedious to write, so please reference either Aleph One or Maraiah for a full table of translations. - `Mode` is an Old Light Mode enumeration. - `Phase` is ignored in Aleph One. - If `Type` is `Strobe`, you must set each resulting `Period` to this definition's `Period` divided by 4 plus one. Otherwise, `Period` is ignored. - For each of the new definition's functions, if the intensity of it is more than 0, it should be set to `ValueMax`, otherwise `ValueMin`. - `ValueCur` is ignored in Aleph One. ### Map Annotation ### Map Annotation is 72 bytes. | Name | Type | Offset | | ---- | ---- | ------ | | `Type` | `u16` | `0` | | `Location` | `struct` | `2` | | `Polygon` | `u16` | `6` | | `Text` | `u8[64]` | `8` | - `Type` is an index into the annotation type definition, but there's only one, so this will always be `0` anyway. ### 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` | - `Flags` is a Map Object Flags bit field, and the upper 4 bits are the activation bias for monsters. ### Object Frequency ### Object Frequency is 12 bytes. | Name | Type | Offset | | ---- | ---- | ------ | | `Flags` | `u16` | `0` | | `CountInit` | `u16` | `2` | | `CountMin` | `u16` | `4` | | `CountMax` | `u16` | `6` | | `CountRand` | `u16` | `8` | | `Chance` | `u16` | `10` | - `Flags` is an Object Frequency Flags bit field. ### Platform Data ### Platform Data is 32 bytes. | Name | Type | Offset | | ---- | ---- | ------ | | `Type` | `u16` | `0` | | `Speed` | `u16` | `2` | | `Delay` | `u16` | `4` | | `HeightMax` | `unit` | `6` | | `HeightMin` | `unit` | `8` | | `Flags` | `u32` | `10` | | `Index` | `u16` | `14` | | `Tag` | `u16` | `16` | - `Type` is a Platform Type enumeration. - `Index` is the polygon this platform is attached to. - `Flags` is a Static Platform Flags bit field. ### Ambient Sound ### Ambient Sound is 16 bytes. | Name | Type | Offset | | ---- | ---- | ------ | | `Index` | `u16` | `2` | | `Volume` | `u16` | `4` | - `Volume` is the volume of this sound, in range 0-256. ### Random Sound ### Random Sound is 32 bytes. | Name | Type | Offset | | ---- | ---- | ------ | | `Flags` | `u16` | `0` | | `Index` | `u16` | `2` | | `Volume` | `u16` | `4` | | `DeltaVolume` | `u16` | `6` | | `Period` | `u16` | `8` | | `DeltaPeriod` | `u16` | `10` | | `Angle` | `angle` | `12` | | `DeltaAngle` | `angle` | `14` | | `Pitch` | `fixed` | `16` | | `DeltaPitch` | `fixed` | `20` | | `Phase` | `u16` | `24` | - `Flags` is a Random Sound Flags bit field. - `Phase` must be `65535`. ### Media Data ### Media Data is 32 bytes. "Media" refers to liquids, presumably because of the plural of the definition of "medium," a "material which waves pass through," in this case liquid. (This is likely the case of whoever programmed this system learning physics before rendering, or conflating the two.) | Name | Type | Offset | | ---- | ---- | ------ | | `Type` | `u16` | `0` | | `Flags` | `u16` | `2` | | `Control` | `u16` | `4` | | `Direction` | `angle` | `6` | | `Magnitude` | `unit` | `8` | | `Low` | `unit` | `10` | | `High` | `unit` | `12` | | `Origin` | `struct` | `14` | | `Height` | `unit` | `18` | | `Minimum` | `fixed` | `20` | | `Texture` | `u16opt` | `24` | | `XferMode` | `u16` | `26` | - `Type` is a Media Type enumeration. - `Flags` is a Media Flags bit field. - `Control` is the index of a light which is used to control the height of this media. - `XferMode` is a Transfer Mode enumeration. ### Static Map Info ### Static Map Info is 88 bytes. | Name | Type | Offset | | ---- | ---- | ------ | | `TextureId` | `u16` | `0` | | `PhysicsId` | `u16` | `2` | | `LandscapeId` | `u16` | `4` | | `MissionFlags` | `u16` | `6` | | `EnvFlags` | `u16` | `8` | | `Name` | `u8[66]` | `18` | | `EntryFlags` | `u32` | `84` | - `TextureId` is a Texture Collection enumeration. It is a preset number for texture collections and some other things such as media (liquid) presets. - `PhysicsId` used to be used for specifying three physics models: one for the Forge editor, one for the game, and one for low-gravity. However, the first one ended up being useless and the third was made into a map flag instead which simply modifies the current physics model. This should always be set to `1` by new editors. - `LandscapeId` is a Landscape enumeration. It is the landscape number to use for the sky. This starts at `0`, since it's an offset into the landscape collections. If `DataVersion` is `DataM1` or the `Music` flag of `EnvFlags` is set, then this is used as the music index instead. - `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. If `DataVersion` is `DataM1` and this is `0`, this implies the value is `Solo`. ## 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. ## Physics ## ### Physics Definition ### Physics Definition is 104 bytes. | Name | Type | Offset | | ---- | ---- | ------ | | `VelForw` | `fixed` | `0` | | `VelBack` | `fixed` | `4` | | `VelPerp` | `fixed` | `8` | | `Accel` | `fixed` | `12` | | `Decel` | `fixed` | `16` | | `DecelAir` | `fixed` | `20` | | `AccelGravity` | `fixed` | `24` | | `AccelClimb` | `fixed` | `28` | | `VelTerminal` | `fixed` | `32` | | `DecelExtern` | `fixed` | `36` | | `AccelAngular` | `fixed` | `40` | | `DecelAngular` | `fixed` | `44` | | `VelAngular` | `fixed` | `48` | | `VelRecenter` | `fixed` | `52` | | `FastVelAng` | `fixed` | `56` | | `FastVelMax` | `fixed` | `60` | | `Elevation` | `fixed` | `64` | | `DecelAngExt` | `fixed` | `68` | | `StepDelta` | `fixed` | `72` | | `StepAmp` | `fixed` | `76` | | `PlayerRadius` | `fixed` | `80` | | `PlayerHeight` | `fixed` | `84` | | `PlayerDeadHi` | `fixed` | `88` | | `PlayerCamHi` | `fixed` | `92` | | `PlayerSplash` | `fixed` | `96` | | `HalfCamSep` | `fixed` | `100` | ### Effect Definition ### Effect Definition is 14 bytes. | Name | Type | Offset | | ---- | ---- | ------ | | `Collection` | `u16` | `0` | | `Shape` | `u16` | `2` | | `Pitch` | `fixed` | `4` | | `Flags` | `u16` | `8` | | `Delay` | `u16` | `10` | | `DelaySound` | `u16` | `12` | - `Flags` is an Effect Definition Flags bit field. ### Weapon Definition ### Weapon Definition is 134 bytes. | Name | Type | Offset | | ---- | ---- | ------ | | `ItemType` | `u16` | `0` | | `PowerupType` | `u16` | `2` | | `WeaponClass` | `u16` | `4` | | `Flags` | `u16` | `6` | | `LightValue` | `fixed` | `8` | | `LightDecay` | `u16` | `12` | | `HeightIdle` | `fixed` | `14` | | `AmpBob` | `fixed` | `18` | | `HeightKick` | `fixed` | `22` | | `HeightReload` | `fixed` | `26` | | `WidthIdle` | `fixed` | `30` | | `AmpHorz` | `fixed` | `34` | | `Collection` | `u16` | `38` | | `FrameIdle` | `u16` | `40` | | `FrameFiring` | `u16` | `42` | | `FrameReload` | `u16` | `44` | | `FrameCharge` | `u16` | `48` | | `FrameCharged` | `u16` | `50` | | `TicksReady` | `u16` | `52` | | `TicksLoadBeg` | `u16` | `54` | | `TicksLoadMid` | `u16` | `56` | | `TicksLoadEnd` | `u16` | `58` | | `TicksPowerup` | `u16` | `60` | | `TriggerPri` | `struct` | `62` | | `TriggerSec` | `struct` | `98` | - `WeaponClass` is a Weapon Type enumeration. - `Flags` is a Weapon Flags bit field. - `TriggerPri` and `TriggerSec` are Trigger Definition structures used for the primary and secondary fire buttons. ### Trigger Definition ### Trigger Definition is 36 bytes. | Name | Type | Offset | | ---- | ---- | ------ | | `MagRounds` | `u16` | `0` | | `AmmoType` | `u16` | `2` | | `TicksRound` | `u16` | `4` | | `TicksRecover` | `u16` | `6` | | `TicksCharge` | `u16` | `8` | | `Recoil` | `unit` | `10` | | `SoundFire` | `u16` | `12` | | `SoundClick` | `u16` | `14` | | `SoundCharge` | `u16` | `16` | | `SoundCasing` | `u16` | `18` | | `SoundReload` | `u16` | `20` | | `SoundCharged` | `u16` | `22` | | `Projectile` | `u16` | `24` | | TODO | `u16` | `26` | | TODO | `i16` | `28` | | TODO | `i16` | `30` | | `CasingType` | `u16` | `32` | | `BurstCount` | `u16` | `34` | - `CasingType` is a Casing Type enumeration. ### Projectile Definition ### Projectile Definition is 48 bytes. | Name | Type | Offset | | ---- | ---- | ------ | | `Collection` | `u16opt` | `0` | | `Shape` | `u16` | `2` | | `FxExplode` | `u16opt` | `4` | | `FxExplodeMed` | `u16opt` | `6` | | `FxTrail` | `u16opt` | `8` | | `TicksTrail` | `u16` | `10` | | `MaxTrails` | `u16opt` | `12` | | `MediaType` | `u16opt` | `14` | | `Radius` | `unit` | `16` | | `AreaOfEffect` | `unit` | `18` | | `Damage` | `struct` | `20` | | `Flags` | `u32` | `32` | | `Speed` | `unit` | `36` | | `Range` | `unit` | `38` | | `SndPitch` | `fixed` | `40` | | `SndFly` | `u16opt` | `44` | | `SndBounce` | `u16opt` | `46` | - `MediaType` is the type of projectile this becomes when below media. - `Damage` is a Damage Definition structure. - `Flags` is a Projectile Flags bit field. ### Monster Definition ### Monster Definition is 156 bytes. | Name | Type | Offset | | ---- | ---- | ------ | | `Collection` | `u16` | `0` | | `Vitality` | `u16` | `2` | | `ImmuneTo` | `u32` | `4` | | `WeakTo` | `u32` | `8` | | `Flags` | `u32` | `12` | | `MonsterClass` | `u32` | `16` | | `FriendTo` | `u32` | `20` | | `EnemyTo` | `u32` | `24` | | `SndPitch` | `fixed` | `28` | | `SndSeeEnemy` | `u16opt` | `32` | | `SndSeeFriend` | `u16opt` | `34` | | `SndSeeClear` | `u16opt` | `36` | | `SndKill` | `u16opt` | `38` | | `SndApologize` | `u16opt` | `40` | | `SndAmicide` | `u16opt` | `42` | | `SndFlaming` | `u16opt` | `44` | | `SndActive` | `u16opt` | `46` | | `ActiveMask` | `u16` | `48` | | `DropItem` | `u16opt` | `50` | | `Radius` | `unit` | `52` | | `Height` | `unit` | `54` | | `HoverHeight` | `unit` | `56` | | `LedgeMin` | `unit` | `58` | | `LedgeMax` | `unit` | `60` | | `ExtVelScale` | `fixed` | `62` | | `FxImpact` | `u16opt` | `66` | | `FxMeleeImpact`| `u16opt` | `68` | | `FxTrail` | `u16opt` | `70` | | `HalfFOVHorz` | `u16` | `72` | | `HalfFOVVert` | `u16` | `74` | | `ViewRange` | `unit` | `76` | | `ViewRangeDark`| `unit` | `78` | | `Intelligence` | `u16` | `80` | | `Speed` | `u16` | `82` | | `Gravity` | `u16` | `84` | | `TerminalVel` | `u16` | `86` | | `DoorTryMask` | `u16` | `88` | | `ExplodeRadius`| `u16opt` | `90` | | `ExplodeDamage`| `struct` | `92` | | `SeqHit` | `u16opt` | `104` | | `SeqHardDying` | `u16opt` | `106` | | `SeqSoftDying` | `u16opt` | `108` | | `SeqHardDead` | `u16opt` | `110` | | `SeqSoftDead` | `u16opt` | `112` | | `SeqStanding` | `u16` | `114` | | `SeqMoving` | `u16` | `116` | | `SeqTeleIn` | `u16opt` | `118` | | `SeqTeleOut` | `u16opt` | `120` | | `AtkFrequency` | `u16` | `122` | | `AtkMelee` | `struct` | `124` | | `AtkRange` | `struct` | `140` | - `Flags` is a Monster Flags bit field. - `MonsterClass` is a Monster Class bit field. - `ExplodeDamage` is a Damage Definition structure. - `AtkMelee` and `AtkRange` are Attack Definition structures. ### Damage Definition ### Damage Definition is 12 bytes. | Name | Type | Offset | | ---- | ---- | ------ | | `Type` | `u16` | `0` | | `Flags` | `u16` | `2` | | `DmgBase` | `u16` | `4` | | `DmgRand` | `u16` | `6` | | `Scale` | `fixed` | `8` | - `Type` is a Damage Type enumeration. - `Flags` is a Damage Flags enumeration. ### Attack Definition ### Attack Definition is 16 bytes. | Name | Type | Offset | | ---- | ---- | ------ | | `Type` | `u16opt` | `0` | | `Repetitions` | `u16` | `2` | | `Error` | `angle` | `4` | | `Range` | `unit` | `6` | | `Shape` | `u16` | `8` | | `OfsX` | `unit` | `10` | | `OfsY` | `unit` | `12` | | `OfsZ` | `unit` | `14` | ## 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. I suppose this could be worse, considering they later used PDF files for images. - 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` | `u16opt` | `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.) ### 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` | `u16opt` | `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` | - `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 | ### Old 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 | | `MinorOuch` | `3` | Damages the player a little | None | | `MajorOuch` | `4` | Damages the player a lot | 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 | | `Glue` | `11` | Slows the player down | None | | `GlueTrigger` | `12` | TODO | TODO | | `SuperGlue` | `13` | Slows the player down a lot | None | | `MustExplore` | `14` | Must be entered for Exploration | None | | `AutoExit` | `15` | 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 | ### Old Light Type ### | Name | Value | | ---- | ----- | | `Normal` | `0` | | `Rheostat` | `1` | | `Flourescent` | `2` | | `Strobe` | `3` | | `Flickers` | `4` | | `Pulsates` | `5` | | `Annoying` | `6` | | `EnergyEfficient` | `7` | ### Old Light Mode ### | Name | Value | | ---- | ----- | | `TurningOn` | `0` | | `Active` | `1` | | `TurningOff` | `2` | | `Inactive` | `3` | | `Toggle` | `4` | - `TurningOn` and `Active` mean the new light created from this should have the `InitActive` flag. Others do not mean anything. ### 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` | Pict ID | | `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` | Pict ID | | `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. ### Media Type ### | Name | Value | | ---- | ----- | | `Water` | `0` | | `Lava` | `1` | | `Goo` | `2` | | `Sewage` | `3` | | `Jjaro` | `4` | ### Texture Collection ### | Name | Value | | ---- | ----- | | `Water` | `0` | | `Lava` | `1` | | `Sewage` | `2` | | `Jjaro` | `3` | | `Pfhor` | `4` | These are the default texture sets. ### Landscape ### | Name | Value | | ---- | ----- | | `LhowonDay` | `0` | | `LhowonNight` | `1` | | `Moon` | `2` | | `Space` | `3` | These are the default landscapes. ### Platform Type ### | Name | Value | | ---- | ----- | | `SphtDoor` | `0` | | `SphtDoorSplit` | `1` | | `SphtDoorLock` | `2` | | `SphtPlat` | `3` | | `SphtPlatNoisy` | `4` | | `SphtDoorHeavy` | `5` | | `PfhorDoor` | `6` | | `SphtPlatHeavy` | `7` | | `PfhorPlatform` | `8` | This apparently used to do something, but now does nothing, and is merely left over for editor preset usage. ### Weapon Type ### | Name | Value | | ---- | ----- | | `Melee` | `0` | | `Normal` | `1` | | `DualFunc` | `2` | | `DualPistol` | `3` | | `Multipurpose` | `4` | ### Casing Type ### | Name | Value | | ---- | ----- | | `Rifle` | `0` | | `Pistol` | `1` | | `PistolLeft` | `2` | | `PistolRight` | `3` | | `SMG` | `4` | | `None` | `65535` | ### Damage Type ### | Name | Value | | ---- | ----- | | `Explosion` | `0` | | `ElectricalStaff` | `1` | | `Projectile` | `2` | | `Absorbed` | `3` | | `Flame` | `4` | | `HoundClaws` | `5` | | `AlienProjectile` | `6` | | `HulkSlap` | `7` | | `CompilerBolt` | `8` | | `FusionBolt` | `9` | | `HunterBolt` | `10` | | `Fist` | `11` | | `Teleporter` | `12` | | `Defender` | `13` | | `YetiClaws` | `14` | | `YetiProjectile` | `15` | | `Crushing` | `16` | | `Lava` | `17` | | `Suffocation` | `18` | | `Goo` | `19` | | `EnergyDrain` | `20` | | `OxygenDrain` | `21` | | `HummerBolt` | `22` | | `ShotgunProjectile` | `23` | | `None` | `65535` | # 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 ### If `DataVersion` is `DataM1`, then `ItemOpt` must be set by the client. | 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` | | `M1Exploration` | `5` | | `M1Rescue` | `6` | | `M1Repair` | `7` | - `Extermination` means you must kill all monsters on the map, with an error threshold of 8 alien enemies maximum. - `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 50% of BoBs alive. - `M1Exploration` is the same as `Exploration` except you only need to look at each marked polygon, not actually enter them. - `M1Rescue` is the same as `Rescue`. Since this is an internal flag, all it actually does is change which monster class it checks. - `M1Repair` is the same as `Repair`, except it only requires that the last switch (by side index) be switched to succeed. ### 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` | - `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. ### Light Flags ### | Name | Bit | | ---- | --- | | `InitActive` | `0` | | `SlaveValue` | `1` | | `Stateless` | `2` | ### Entry Point Flags ### | Name | Bit | | ---- | --- | | `Solo` | `0` | | `CoOp` | `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` | ### Random Sound Flags ### | Name | Bit | | ---- | --- | | `IgnoreDirection` | `0` | ### Media Flags ### | Name | Bit | | ---- | --- | | `SoundObstruct` | `0` | - `SoundObstruct` means the media makes no sound when under the floor. This is most sensible for, for instance, lava which can be drained. ### Object Frequency Flags ### | Name | Bit | | ---- | --- | | `RandomLocation` | `0` | ### Static Platform Flags ### | Name | Bit | | ---- | --- | | `InitActive` | `0` | | `InitExtended` | `1` | | `StopAtEachLevel` | `2` | | `StopAtInitLevel` | `3` | | `StartAdjOnStop` | `4` | | `ExtendsFloorToCeil` | `5` | | `ComesFromFloor` | `6` | | `ComesFromCeil` | `7` | | `CausesDamage` | `8` | | `NoActivateParent` | `9` | | `ActivatesOnce` | `10` | | `ActivatesLight` | `11` | | `DeactivatesLight` | `12` | | `PlayerControls` | `13` | | `MonsterControls` | `14` | | `ReverseOnObstruct` | `15` | | `NoExtDeactivation` | `16` | | `UsePolygonHeights` | `17` | | `DelayedActivation` | `18` | | `StartAdjOnStart` | `19` | | `StopAdjOnStart` | `20` | | `StopAdjOnStop` | `21` | | `Slow` | `22` | | `StartAtEachLevel` | `23` | | `Locked` | `24` | | `Secret` | `25` | | `Door` | `26` | If I could explain to you why there are this many flags, I gladly would, but this actually hurts my head. ### Effect Definition Flags ### | Name | Bit | | ---- | --- | | `EndOnLoop` | `0` | | `EndOnXferLoop` | `1` | | `SoundOnly` | `2` | | `MakeTwinVisible` | `3` | | `MediaEffect` | `4` | ### Weapon Flags ### | Name | Bit | | ---- | --- | | `Automatic` | `0` | | `RemoveAfterUse` | `1` | | `InstantCasing` | `2` | | `Overloads` | `3` | | `RandomAmmo` | `4` | | `TemporaryPower` | `5` | | `ReloadOneHand` | `6` | | `FireOutOfPhase` | `7` | | `FireUnderMedia` | `8` | | `TriggerSameAmmo` | `9` | | `SecondaryFlip` | `10` | ### Damage Flags ### | Name | Bit | | ---- | --- | | `AlienDamage` | `0` | - `AlienDamage` will decrease the damage on Easy and Wuss. ### Projectile Flags ### | Name | Bit | | ---- | --- | | `Guided` | `0` | | `StopOnLoop` | `1` | | `Persistent` | `2` | | `Alien` | `3` | | `Gravity` | `4` | | `NoHorzError` | `5` | | `NoVertError` | `6` | | `TogglePanels` | `7` | | `PosVertError` | `8` | | `Melee` | `9` | | `Ripper` | `10` | | `PassTransRandom` | `11` | | `PassTransMore` | `12` | | `DoubleGravity` | `13` | | `ReboundFloor` | `14` | | `ThroughMedia` | `15` | | `BecomeItem` | `16` | | `Bloody` | `17` | | `WanderHorz` | `18` | | `WanderVert` | `19` | | `UseLowGrav` | `20` | | `PassMedia` | `21` | ### Monster Flags ### | Name | Bit | | ---- | --- | | `IgnoreLOS` | `0` | | `Flying` | `1` | | `Alien` | `2` | | `Major` | `3` | | `Minor` | `4` | | `NoOmit` | `5` | | `Floats` | `6` | | `NoAttack` | `7` | | `Snipe` | `8` | | `Invisible` | `9` | | `SubtlyInvisible` | `10` | | `Kamikaze` | `11` | | `Berserker` | `12` | | `Enlarged` | `13` | | `DelayedDeath` | `14` | | `FireSymmetrical` | `15` | | `NuclearDeath` | `16` | | `NoFireBackwards` | `17` | | `CanDieInFlames` | `18` | | `WaitForGoodShot` | `19` | | `Tiny` | `20` | | `FastAttack` | `21` | | `LikesWater` | `22` | | `LikesSewage` | `23` | | `LikesLava` | `24` | | `LikesGoo` | `25` | | `TeleUnderMedia` | `26` | | `UseRandomWeapon` | `27` | ### Monster Class ### | Name | Bit | | ---- | --- | | `Player` | `0` | | `Civilian` | `1` | | `Madd` | `2` | | `PossessedHummer` | `3` | | `Defender` | `4` | | `Fighter` | `5` | | `Trooper` | `6` | | `Hunter` | `7` | | `Enforcer` | `8` | | `Juggernaut` | `9` | | `Hummer` | `10` | | `Compiler` | `11` | | `Cyborg` | `12` | | `Assimilated` | `13` | | `Tick` | `14` | | `Yeti` | `15` | ### Damage Type Flag ### | Name | Bit | | ---- | --- | | `Explosion` | `0` | | `ElectricalStaff` | `1` | | `Projectile` | `2` | | `Absorbed` | `3` | | `Flame` | `4` | | `HoundClaws` | `5` | | `AlienProjectile` | `6` | | `HulkSlap` | `7` | | `CompilerBolt` | `8` | | `FusionBolt` | `9` | | `HunterBolt` | `10` | | `Fist` | `11` | | `Teleporter` | `12` | | `Defender` | `13` | | `YetiClaws` | `14` | | `YetiProjectile` | `15` | | `Crushing` | `16` | | `Lava` | `17` | | `Suffocation` | `18` | | `Goo` | `19` | | `EnergyDrain` | `20` | | `OxygenDrain` | `21` | | `HummerBolt` | `22` | | `ShotgunProjectile` | `23` |