diff --git a/MarathonData.md b/MarathonData.md index 1bc0fd6..ccde5e9 100644 --- a/MarathonData.md +++ b/MarathonData.md @@ -362,8 +362,8 @@ Example: ## Wad ## -Wad files are used for scenario data, images, and physics files. Here is a -listing of all chunks used within them: +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 | | ---- | ----------- | @@ -405,16 +405,22 @@ 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. + ## Marathon 2 Shapes (`.shpA`) ## -The Shapes file is used for storing animation and sprite data. It uses a fixed -format for everything, with sprites sorted into collections along with frames -and sequences. +The Shapes file is used for storing animation, sprite, skybox and texture data. +It uses a fixed format for everything, with sprites sorted into collections +along with frames and sequences. # STRUCTURES ################################################################## -All integers here are big-endian unless specified. +All integers here are big-endian unless specified. The type "k32" 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.) ## Wad ## @@ -430,11 +436,15 @@ after the 128th byte is entry data. ### Wad Header ### -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. +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. -The Wad Header is 128 bytes. +ChunkSize and EntrySize may be zero, in which case it will default to 16 and 10 +respectively. They exist for forward compatibility with Wad patching, although +are actually pointless and serve no practical purpose other than perhaps adding +extra data for your editor (although none actually do this.) | Type | Description | Name | | ---- | ----------- | ---- | @@ -453,10 +463,6 @@ If WadVer is greater than or equal to VerDir: | u16 | Size of chunks | ChunkSize | | u16 | Size of directory entries | EntrySize | -ChunkSize and EntrySize may be zero, in which case it will default to 16 and 10 -respectively. They exist for forward compatibility with Wad patching, although -are actually pointless and serve no practical purpose. - If WadVer is greater than or equal to VerOver: | Type | Description | Name | @@ -465,12 +471,11 @@ If WadVer is greater than or equal to VerOver: ### Directory Entry ### +Directory Entry is 8 bytes if WadVer is VerBase, or EntrySize+AppData bytes. Following this structure is AppData bytes (N), supposed to be used by editor applications for storing arbitrary extra data, and will be ignored by the engine. -Directory Entry is 8 bytes if WadVer is VerBase, or EntrySize+AppData bytes. - | Type | Description | Name | | ---- | ----------- | ---- | | u32 | Offset to start of data (from start of file) | Offset | @@ -485,11 +490,10 @@ If WadVer is greater than or equal to VerDir: ### Chunk ### -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. - -Chunk is 12 bytes if WadVer is VerBase, or ChunkSize bytes. +Chunk is 12 bytes if WadVer 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. | Type | Description | Name | | ---- | ----------- | ---- | @@ -507,9 +511,7 @@ If WadVer is greater than or equal to VerDir: ### LtFn ### -Light function specification. - -LtFn is 14 bytes. +LtFn is 14 bytes. A light function specification. | Type | Description | Name | | ---- | ----------- | ---- | @@ -523,21 +525,17 @@ LtFn is 14 bytes. ### SideTex ### -Just stores a texture and an offset. - -SideTex is 6 bytes. +SideTex is 6 bytes. Just stores a texture and an offset. | Type | Description | Name | | ---- | ----------- | ---- | | i16 | X offset | OffsX | | i16 | Y offset | OffsY | -| u16 | Texture ID (shape descriptor) | TextureId | +| u16 | Texture ID (Shape ID) | TextureId | ### Point ### -A geometric point. - -Point is 4 bytes. +Point is 4 bytes. A geometric point. | Type | Description | Name | | ---- | ----------- | ---- | @@ -546,9 +544,7 @@ Point is 4 bytes. ### Endpoint ### -More advanced point structure. - -Endpoint is 16 bytes. +Endpoint is 16 bytes. More advanced point structure. | Type | Description | Name | | ---- | ----------- | ---- | @@ -561,9 +557,7 @@ Endpoint is 16 bytes. ### Line ### -A geometric line segment. - -Line is 32 bytes. +Line is 32 bytes. A geometric line segment. | Type | Description | Name | | ---- | ----------- | ---- | @@ -580,9 +574,7 @@ Line is 32 bytes. ### Side ### -One side of a line segment. - -Side is 64 bytes. +Side is 64 bytes. One possibly textured side of a line segment. | Type | Description | Name | | ---- | ----------- | ---- | @@ -600,13 +592,12 @@ Side is 64 bytes. | u16 | First texture transfer mode | XferPri | | u16 | Second texture transfer mode | XferSec | | u16 | Transparent texture transfer mode | XferTra | -| 15_16s | Ambient shading for visual contrast | Shade | +| k32 | Ambient shading for visual contrast | Shade | ### Polygon ### -A geometric polygon, essentially Doom's "sector," but must be convex. - -Polygon is 128 bytes. +Polygon is 128 bytes. A geometric polygon, essentially Doom's "sector," but +must be convex. | Type | Description | Name | | ---- | ----------- | ---- | @@ -616,8 +607,8 @@ Polygon is 128 bytes. | u16 | Vertex count | | | u16[8] | Endpoint indices (clockwise) | | | u16[8] | Line indices | | -| u16 | Floor texture (shape descriptor) | | -| u16 | Ceiling texture (shape descriptor) | | +| u16 | Floor texture (Shape ID) | | +| u16 | Ceiling texture (Shape ID) | | | i16 | Floor height | | | i16 | Ceiling height | | | u16 | Floor lightsource index | | @@ -674,7 +665,10 @@ Object is 16 bytes. ### Static Map Info ### -Static Map Info is 88 bytes. +Static Map Info is 88 bytes. The level name was intended to be 65 bytes, but +one padding byte was left over, so the real length is 66 bytes. It is unknown +why the entry point flags are stored in a 32-bit integer when they can fit in 8 +bits. | Type | Description | Name | | ---- | ----------- | ---- | @@ -687,10 +681,6 @@ Static Map Info is 88 bytes. | u8[66] | Level name | Name | | u32 | Entry point flags | EntryFlags | -The level name was intended to be 65 bytes, but one padding byte was left over, -so the real length is 66 bytes. It is unknown why the entry point flags are -stored in a 32-bit integer when they can fit in 8 bits. - ## Terminal ## ### Terminal ### @@ -786,8 +776,8 @@ If direct copy: If PICT2: * PixMap -Else: -* assume pack type is default and bit depth is 1 +Otherwise: +* Assume pack type is default and bit depth is 1. If packed pixmap: @@ -813,7 +803,7 @@ The following are ignored in Aleph One: | u16 | Transfer mode | XferMode | If clip: -* Clip Region (skipped the same way as opcode $0001 in A1) +* Clip Region (skipped the same way as opcode $0001 in A1.) Image data follows. @@ -881,14 +871,20 @@ if matte: ## 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. +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 skyboxes that Marathon 2 has. | Type | Description | Name | | ---- | ----------- | ---- | -| u16 | Status (TODO: unknown purpose) | Status | -| u16 | Flags (TODO: unknown purpose) | Flags | +| 4 bytes | Unused | | | u32 | Offset for lo-res collection | OffsetLo | | u32 | Length for lo-res collection | LengthLo | | u32 | Offset for hi-res collection | OffsetHi | @@ -896,25 +892,77 @@ Collection Header is 32 bytes. ### Collection Definition ### -Collection Definition is 544 bytes (no, I'm not kidding, there are actually 506 -unused bytes.) +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. The version number isn't checked by +the engine and should always be `3`. | Type | Description | Name | | ---- | ----------- | ---- | -| u16 | Version, not checked by engine (current is 3) | Version | +| u16 | Version | Version | | u16 | Collection Type | Type | | 2 bytes | Unused | | | u16 | Colors per CLUT | Colors | | u16 | Number of CLUTs | CLUNum | | u32 | Offset to CLUTs | CLUOfs | | u16 | Number of sequences | SeqNum | -| u32 | Offset to sequences | SeqOfs | +| u32 | Offset to sequence table | SeqOfs | | u16 | Number of frames | FrmNum | -| u32 | Offset to frames | FrmOfs | +| u32 | Offset to frame table | FrmOfs | | u16 | Number of bitmaps | BmpNum | -| u32 | Offset to bitmaps | BmpOfs | +| u32 | Offset to bitmap table | BmpOfs | + +### Frame ### + +Frame is 36 bytes. TODO: document how world transform works. + +| Type | Description | Name | +| ---- | ----------- | ---- | +| u16 | Frame Flags | Flags | +| k32 | Minimum light intensity (0-1) | MinLight | +| u16 | Bitmap index (Shape ID) | BmpIndex | +| 8 bytes | Unused | | +| u16 | Left of pixels-to-world transform | WldLeft | +| u16 | Right of pixels-to-world transform | WldRight | +| u16 | Top of pixels-to-world transform | WldTop | +| u16 | Bottom of pixels-to-world transform | WldBottom | +| u16 | X origin of pixels-to-world transform | WldXOrig | +| u16 | Y origin of pixels-to-world transform | WldYOrig | + +### Sequence ### + +Sequence is 88 bytes. The name is supposed to be 33 bytes, but due to padding, +the real length is 34 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. + +| Type | Description | Name | +| ---- | ----------- | ---- | +| 4 bytes | Unused | | +| u8[34] | Sequence name for editors | Name | +| u16 | View Type | ViewType | +| u16 | Number of frames | FrameNum | +| u16 | Ticks per frame | FrameTick | +| u16 | Key frame | FrameKey | +| u16 | Transfer Mode | XferMode | +| u16 | Transfer mode period | XferPeriod | +| u16 | Transfer mode period | XferPeriod | +| u16 | Sound of first frame | SndFirst | +| u16 | Sound of key frame | SndKey | +| u16 | Sound of last frame | SndLast | | 2 bytes | Unused | | -| u32 | Size of entire collection | | +| u16 | Frame to loop | FrameLoop | + +### Shape ID ### + +A Shape ID is a 16-bit integer which references a bitmap by index from the +currently used texture set collection. If all bits are set, it is to be +interpreted as "no texture." Traditionally, these are signed integers, but they +can be treated as unsigned with no reprecussions. # ENUMERATIONS ################################################################