The RGM files found in Redguard's maps directory are data file for the game maps. They contains the static objects, dynamic objects and map scripts.
RGM Format OverviewEdit
Each RGM file is composed of multiple sections containing different data.
The format of a ROB file is:
SectionHeader (8 if that section does not have a record count and 12 bytes if it does) SectionData (variable sized) This pattern is repeated until section "END ", which is the last 4-bytes of the file
The sections are always in the same order and will exist as an empty section if there is no data in all cases except the RAVC section which does not exist if unused.
The table below contains all sections with the description used in Redguard's logging:
Ordinal | Name | Description | Record Count | Record Size | Notes |
---|---|---|---|---|---|
1 | RAHD | Header data | Yes | 165 | Lists all scripted and mobile/3D objects in the level and contains pointers to its data in other sections where applicable |
2 | RAFS | FSphere data | ? | ? | Empty in all |
3 | RAST | String data | No | Variable | Strings to display for the object, not directly referenced in RAHD |
4 | RASB | String tables | No | 4 | Offsets to RAST section |
5 | RAVA | Local variable | No | 4 | Variables for that object - each instance of an object has its own set of variables RAHD.RAVA_Record * RAHD.MPOB_Record - First byte in RAVA is VarCount (= RAHD.RAVA_Record) |
6 | RASC | Script data | No | Variable | Scripting logic attached to the object |
7 | RAHK | Hook data | No | Variable | Audio hooks |
8 | RALC | Location data | No | 24 | Scripted coordinates for an object - i.e. the Boatman |
9 | RAEX | Extra data | No | 30 | Additional details for the object, primarily visual, and some combat details |
10 | RAAT | Attribute data | No | 256 | The object's attributes RAAT.Length = 2 (bytes) x 128 (total atts) * RAHD.RecCount Note: Hardcoded list in executable is used to list these in console, unknown if that is correct or if SOUP386.DEF should be used |
11 | RAAN | Animation file | Yes | Variable | Lists all 3D/3DC files linked to an object - only used for standalone models not embedded in the level's ROB file |
12 | RAGR | Animation group | No | Variable | Animation frame lists and logic |
13 | RANM | Namespace | No | Variable | Honestly don't recall, need to doublecheck :) |
14 | RAVC | VCollide data | No | 9 | Collision vertex/radius details for the dragon and golem Only exists in CATACOMB/DRINT.RGM - flat out missing (as in not there - not just empty like RAFS is) in others |
15 | MPOB | Object data | Yes | 66 | Scriptable/mobile objects |
16 | MPRP | Rope data | Yes | 80 | Rope definitions - location, type, swing speed, etc |
17 | MPSO | Static data | Yes | 66 | Static objects (i.e. trees) |
18 | MPSL | Light data | Yes | 42 | The level's static lights (excluding sun/ambient) |
19 | MPSF | Flat data | Yes | 24 | Flat textures |
20 | MPMK | Marker data | Yes | 12 | Contains the marker coordinates you can teleport to using the console Corresponding single byte footer with boolean flags indicating if a marker is enabled (all defined markers are) |
21 | MPSZ | Size data | No | 49 | Object scaling details |
22 | WDNM | Node map | No | Variable | Defines all the nodes that make up the level |
23 | FLAT | - | No desc in EXE, identical in all files except HIDEOUT.RGM which isn't used - assumed unused | ||
24 | END | , THE |
Note: All coordinates in the RGM files are signed 24-bit values but can vary by section and/or value (usually Z) whether 3 or 4 bytes are allocated to it. When 4 bytes, they can be read as a s32 or as s24 with the 4th byte skipped.
RGM SectionsEdit
All sections (excluding END) begin with a short 8-byte header that contains the section name and length with a third of them having an addition 4-byte record count value.
Offset | DataType | Name | Description |
---|---|---|---|
0 | char[4] | SectionName | String containing the section name |
4 | be u32 | DataLength | The length of the section excluding the Name value (so -4) in big endian format Note: The "END" section does not have this data (or anything else) |
8 | u32 | RecordCount | Number of records in this section Note: When not applicable, this value does not exist at and the section's data will begin here |
RAHD: Header dataEdit
Lists all scripted and mobile/3D objects in the level and contains pointers to its data in other sections where applicable.
Offset | DataType | Name | Description |
---|---|---|---|
0 | u32 | Unknown_00 | No clue, always set to 1B803700 (3637275) for MAPCOUNT record in every map, 00 for everything else except SULGEM_G in Catacombs (set to 6) and XDRGEAR in Dwarven Ruins (set to 2) |
4 | u32 | Unknown_04 | Always 00 |
8 | char[9] | ScriptName | Script/Object name, NULL padded |
17 | u32 | MPOB_Record | Count of MPOB records using this record |
21 | u32 | Unknown_15 | Always 00 |
25 | u32 | RANM_Length | Length of data to read from RANM section |
29 | u32 | RANM_Offset | Offset to beginning of object's RANM section data |
33 | u8 | Unknown_21 | Always 00 |
34 | u16 | RecordID | Matches index of this record in this section (RAHD) |
36 | u8 | Unknown_24 | Always 00 |
37 | u32 | RAAN_Record | Number of RAAN records (variable length NULL terminated) |
41 | u32 | RAAN_Length | Length of data to read from RAAN section |
45 | u32 | RAAN_Offset | Offset to beginning of object's RAAN section data |
49 | u32 | RAGR_MaxAnimGroup | The highest numbered AnimGroupID this object uses Unclear point of this as RAGR are unordered (at least not by AnimGroupID) so it doesn't help find the end of the record's data |
53 | u32 | RAGR_Offset | Offset to beginning of object's RAGR section data |
57 | u32 | Unknown_39 | Always 00 |
61 | u32 | Unknown_3D | Always 00 - If I had to guess for these 3 it could be Record/Length/Offset values for the unused RAFS section |
65 | u32 | Unknown_41 | Always 00 |
69 | u32 | RASB_Record | Number of RASB records |
73 | u32 | RASB_Length | Always 00 just assuming name/original purpose based on position, record length is 4 so just multiply by RASB_Record |
77 | u32 | RASB_Offset | Offset to beginning of object's RASB section data |
81 | u32 | RASC_Length | Length of data to read from RASC section |
85 | u32 | RASC_Offset | Offset to beginning of object's RASC section data |
89 | u32 | RASC_StartAt | Offset to script's entry point |
93 | u32 | RAHK_Length | Length of data to read from RAHK section |
97 | u32 | RAHK_Offset | Offset to beginning of object's RAHK section data |
101 | u32 | RALC_Record | Number of RALC records |
105 | u32 | RALC_Length | Length of data to read from RALC section |
109 | u32 | RALC_Offset | Offset to beginning of object's RALC section data |
113 | u32 | RAEX_Length | Length of data to read from RAEX section |
117 | u32 | RAEX_Offset | Offset to beginning of object's RAEX section data |
121 | u32 | RAVA_Record | Number of variables each MPOB instance of this object has, not the total number of variables for this object Total records to read for this object is RAVA_Record * MPOB_Record |
125 | u32 | RAVA_Length | Length of data to read from RAVA section |
129 | u32 | RAVA_Offset | Offset to beginning of object's RAVA section data |
133 | u32 | Unknown_85 | Always 00 |
137 | u32 | FrameCount | Total frames across all 3D/3DCs files this object has |
141 | s32 | MPSZ_Normal_ID | Index of the MPSZ record that contains the normal (default) animation size record |
145 | s32 | MPSZ_Combat_ID | Index of the MPSZ record that contains the combat animation size record - uses the normal size if blank and combat capable |
149 | s32 | MPSZ_Dead_ID | Index of the MPSZ record that contains the dead animation size record - uses the normal size if blank and can be killed |
153 | u16 | Unknown_99 | Only has value (not 00) for NPCs (and door in Vile's realm?) - Note: Scene NPCs excluded |
155 | s16 | Unknown_9B | Always set to 778 for Cyrus, 88 for guards, and 110 for pirates, and 1 for Vermai, not set (-1) for everything else |
157 | s16 | Unknown_9D | Always set to 210 for guards and 1 for Vermai, not set (-1) for everything else |
159 | u16 | TextureID | TextureID to override/remap the texture that is set in the 3D/3DC file |
161 | u32 | RAVC_Offset | Offset to beginning of object's RAVC section data - Not sure if laziness since only 2 objects have these in two separate levels but there is no length or record count so all records apply |
RAST: String dataEdit
This section contains strings that are used by the script in the RASC section. It is comprised of variable length NULL (00) terminated text strings that are indirectly accessed through the RASB section by the RAHD record.
A RAHD record can have multiple string records (primarily for scenes) and accesses them in the script by their index. Additionally, some strings can be used by multiple RAHD records.
Offset | DataType | Name | Description |
---|---|---|---|
0 | char[] | StringValue | This is a NULL (00) terminated string accessed through the RASB section by offset |
RASB: String tablesEdit
This section contains offsets to the RAST section and is used by the RAHD record to point to its strings. When a string is reused, it will have multiple records in this table pointing to the same offset, no record is reused by RAHD in this section.
For RAHD records with multiple RASB records (and therefore, multiple RAST strings), just continue reading additional records until the RASB_Record count is reached.
Offset | DataType | Name | Description |
---|---|---|---|
0 | u32 | RAST_Offset | This is simply an offset to the record in the RAST section |
RAVA: Local variableEdit
This section contains the variables for each MPOB object. These are accessed by the RAVA_Offset and can be split into per MPOB variable sets by either:
- RAHD.RAVA_Length / RAHD.MPOB_Record
- RAHD.RAVA_Length / (RAHD.RAVA_Record * 4)
Each set is then linked to its MPOB record by index, where the first instance of the RAHD record in MPOB will use the first set of RAVA variables, second MPOB record uses the seconds, etc. Note that the MPOB records are not ordered by RAHD.
The first variable in every set is the number of variables in the set, including itself which will always match the RAVA_Record value in RAHD. This means all MPOB/RAHD records will always have at least one variable, with records that really don't have any still having that first variable which will have a value of 1.
Variables are referenced by the script by index (0 based).
Offset | DataType | Name | Description |
---|---|---|---|
0 | u32 | Var00 | The first variable containing the count of variables in this set |
- | u32 | Var## | Any additional variables beyond the variable count above (Var00) will follow |
RASC: Script dataEdit
<TBA>
Offset | DataType | Name | Description |
---|
RAHK: Hook dataEdit
<TBA>
Offset | DataType | Name | Description |
---|
RALC: Location dataEdit
<TBA>
Offset | DataType | Name | Description |
---|
RAEX: Extra dataEdit
<TBA>
Offset | DataType | Name | Description |
---|
RAAT: Attribute dataEdit
<TBA>
Offset | DataType | Name | Description |
---|
RAAN: Animation fileEdit
<TBA>
Offset | DataType | Name | Description |
---|
RAGR: Animation groupEdit
<TBA>
Offset | DataType | Name | Description |
---|
RANM: NamespaceEdit
<TBA>
Offset | DataType | Name | Description |
---|
RAVC: VCollide dataEdit
This section contains collision spheres used by the dragon in the Catacombs map and the golem in the Dwarven Ruins. This section does not exist in any other RGM file.
There is no record count but both usages of this only has 2 records of 9 bytes each.
Offset | DataType | Name | Description |
---|---|---|---|
0 | s8 | OffsetX | The X offset from the specified Vertex for the sphere's center point |
1 | s8 | OffsetY | The Y offset from the specified Vertex for the sphere's center point |
2 | s8 | OffsetZ | The Z offset from the specified Vertex for the sphere's center point |
3 | u16 | Vertex | Vertex on the object's model that is used as a reference point for the collision sphere |
5 | u32 | Radius | The collision sphere's radius Note: This is probably a s16 or u16 value, not 32, but the following 2 bytes are always 00 so no real point in reading separate |
MPOB: Object dataEdit
These are the instances of the scriptable/mobile objects initially defined in the RAHD section and can be linked to the header record using the ScriptName value. This section contains the record count in the section header with fixed length 66-byte records.
Offset | DataType | Name | Description |
---|---|---|---|
0 | u32 | Unknown_00 | Believe this is some sort of unique identifier for the object but unclear how this works |
4 | u8 | TypeID | Enumeration field using ObjectType <TBA> |
5 | bool | IsActive | Not entirely clear what makes an object "active" but this flag matches up with the results of "show active" in the console |
6 | char[9] | ScriptName | Script object name in RAHD object belongs to |
15 | char[9] | ModelName | The 3D model file name but truncated to 9 characters so usually incomplete - static objects only |
24 | bool | IsStatic | Boolean flag for static objects |
25 | u16 | Unknown_19 | Looks to be padding, always 0000 |
27 | s24 | PosX | Object's X coordinate Note: This is a s24 value but has 4 bytes allocated to it - if negative the 4th byte will be set correctly (FF) but can be ignored |
31 | s24 | PosY | Object's Y coordinate Note: This is a s24 value but has 4 bytes allocated to it - if negative the 4th byte will be set correctly (FF) but can be ignored |
35 | s24 | PosZ | Object's Z coordinate |
38 | u32 | ViewPitch | The object's pitch (↕) or vx angle - standard Bethesda 2048 angle type Need to & 2047 to get value - Unclear why 4 bytes |
42 | u32 | ViewYaw | The object's yaw (↔) or vy angle - standard Bethesda 2048 angle type Need to & 2047 to get value - Unclear why 4 bytes |
46 | u32 | ViewRoll | The object's roll (↻) or vz angle - standard Bethesda 2048 angle type Need to & 2047 to get value - Unclear why 4 bytes |
50 | u16 | TextureID | Val >> 7 Note: Only set on flats (type 3) |
SubImageID | Val & 127 Note: Only set for animation/multi-frame subimages - single images are not counted here Example: if a texture file has two single images, one multi-frame image, another single image, then a second multi-frame image, to reference the 2nd multi-frame image the value will be 2 not 5 | ||
52 | s16 | Intensity | Light intensity value - Only set on lights (type 4) |
54 | s16 | Radius | Light radius value - Set on type 4/6 (may be different use on 6?) |
56 | s16 | ModelID | Looks to be some type of ID number for the 3D file in ModelName - starts at 00, same ID used for all instances of ModelName in map -1 if no value in ModelName (or IsStatic = 00) |
58 | s16 | Unknown_3A | These 4 only set on type 6 |
60 | s16 | Unknown_3C | Unknown purpose |
62 | s16 | Unknown_3E | |
64 | s16 | Unknown_40 |
MPRP: Rope dataEdit
This sections contains all ropes in the map. If no ropes, section will be essentially empty with a length of 8 and a record count of 0.
The primary thing to note is the positioning coordinates are for the top end of the rope, basically where it is fixed or mounted to whatever (typically the ceiling).
Offset | DataType | Name | Description |
---|---|---|---|
0 | u32 | Unknown_00 | Believe this is some sort of unique identifier for the object but unclear how this works |
4 | u8 | Unknown_04 | Always 00 |
5 | s24 | PosX | The X coordinate where the rope is affixed/mounted Note: This is a s24 value but has 4 bytes allocated to it |
9 | s24 | PosY | The Y coordinate where the rope is affixed/mounted Note: This is a s24 value but has 4 bytes allocated to it |
13 | s24 | PosZ | The Z coordinate where the rope is affixed/mounted |
16 | u32 | YAngle | Not clear what this means or does - value changes when on rope |
20 | u32 | Type | Name from console, not sure what exactly makes these different Values are 0/1/18 - 18 only set on two ropes with a static object attached |
24 | u32 | Swing | Controls how far the rope can swing Think this is an actual degree (not 2048 style) it can move from its neutral hanging position |
28 | u32 | Speed | How fast the rope swings back and forth Larger swing values typically have higher speeds set |
32 | u16 | Length | Length of the rope hanging straight down from it's mount point |
34 | char[9] | StaticModel | Name of the static model attached to the end of the rope (i.e. chandelier) Only 2 usages, both type 18 - when populated, pointer to model is shown in "Stat" value in console |
43 | char[9] | ModelName | Name of the rope model used, only two types: CHAINLNK & ROPELINK |
52 | u32 | Unknown_34 | These next three values are always 00 00 00 or 3E 3E 3F (62 62 63) or 3E 3E 3E (62 62 62) |
56 | u32 | Unknown_38 | Only one instance of all 3Es in the Goblin Cavern |
60 | u32 | Unknown_3C | And only 5 that are all 00s, all in the Dwarven Ruins |
64 | u32 | Unknown_40 | Always 00 |
68 | u32 | Unknown_44 | Always 00 |
72 | u32 | Unknown_48 | Always 00 |
76 | u32 | Unknown_4C | Always 00 |
MPSO: Static dataEdit
These are the static objects in the map without a script attached to it (buildings, rocks, trees, etc). This section contains the record count in the section header with fixed length 66-byte records.
Offset | DataType | Name | Description |
---|---|---|---|
0 | u32 | Unknown_00 | Believe this is some sort of unique identifier for the object but unclear how this works |
4 | char[8] | ModelName | Model name without extension so not truncated like in MPOB |
12 | u32 | Unknown_0C | Always 00 |
16 | s24 | PosX | Object's X coordinate Note: This is a s24 value but has 4 bytes allocated to it |
20 | s24 | PosY | Object's Y coordinate Note: This is a s24 value but has 4 bytes allocated to it |
24 | s24 | PosZ | Object's Y coordinate Note: This is a s24 value but has 4 bytes allocated to it |
28 | s32 | XX | Transform matrix |
32 | s32 | YX | Q4.28 fixed point values (left 4 bits are integer / right 28 bits are decimal) |
36 | s32 | ZX | Technically allows range of -8 - 8 but min/max value is 1 across all records in all maps |
40 | s32 | XY | |
44 | s32 | YY | |
48 | s32 | ZY | |
52 | s32 | XZ | |
56 | s32 | YZ | |
60 | s32 | ZZ | |
64 | u16 | Unknown_40 | Always 00 |
MPSL: Light dataEdit
This section contains the all the lights for the RGM file which, in the case of ISLAND.RGM, is more than one map. It appears to contain both shadow/negative lights which apply to all worlds/maps contained in the file and standard lights which are assigned to a specific WorldID (which except for ISLAND will just be the current map).
This section has a record count in the header with records of 42 bytes.
Offset | DataType | Name | Description |
---|---|---|---|
0 | u32 | Unknown_00 | Believe this is some sort of unique identifier for the object but unclear how this works |
4 | u32 | WorldID | This value is either 0 or the world (map) ID the lights apply to which is just the current map number except for the ISLAND map which has separate "worlds" for day/evening/night When 0, these apply to all (only really relevant to ISLAND as all other are just one map) and also appear to all be shadowing/negative lights Additionally, the WorldID 0 lights are not counted by the "show objects" command or selectable with the FX light controls in the console |
8 | s24 | PosX | Light's X coordinate Note: This is a s24 value but has 4 bytes allocated to it |
12 | s24 | PosY | Light's Y coordinate Note: This is a s24 value but has 4 bytes allocated to it |
16 | s24 | PosZ | Light's Z coordinate Note: This is a s24 value but has 4 bytes allocated to it |
20 | s16 | Radius | Signed value but only positive values allowed so max possible is 32767 (max used is 12000) |
22 | s16 | Intensity | Light intensity value - only set on shadow/negative lights (WorldID 0) |
24 | s16 | Red | Standard RGB colors |
26 | s16 | Green | -255 - 255 range |
28 | s16 | Blue | Negative values drain the color from anything illuminated (deluminated?) by the light |
30 | u8 | Unknown_1E | These 12 are kinda odd and I have no idea what they do |
31 | u8 | Unknown_1F | These are only and always set when WorldID is not 0 |
32 | u8 | Unknown_20 | When set these always are set as increments from 0 to 11 |
33 | u8 | Unknown_21 | So 1E is 0, 1F is 1, 20 is 2, etc |
34 | u8 | Unknown_22 | |
35 | u8 | Unknown_23 | |
36 | u8 | Unknown_24 | |
37 | u8 | Unknown_25 | |
38 | u8 | Unknown_26 | |
39 | u8 | Unknown_27 | |
40 | u8 | Unknown_28 | |
41 | u8 | Unknown_29 |
MPSF: Flat dataEdit
This sections contains the flat textures for the map.
This section has a record count in the header with records of 24 bytes.
Offset | DataType | Name | Description |
---|---|---|---|
0 | u32 | Unknown_00 | Believe this is some sort of unique identifier for the object but unclear how this works |
4 | u32 | Unknown_04 | Always 00 |
8 | s24 | PosX | Object's X coordinate Note: This is a s24 value but has 4 bytes allocated to it |
12 | s24 | PosY | Object's Y coordinate Note: This is a s24 value but has 4 bytes allocated to it |
16 | s24 | PosZ | Object's Z coordinate Note: This is a s24 value but has 4 bytes allocated to it |
20 | u16 | TextureID | Val >> 7 |
SubImageID | Val & 127 Note: SubImages are referenced normally, not like MPOB records |
MPMK: Marker dataEdit
This sections contains the map markers accessible in the console (unsure on other uses).
This section has a record count in the header with records of 12* bytes.
Offset | DataType | Name | Description |
---|---|---|---|
0 | s24 | PosX | Marker's X coordinate Note: This is a s24 value but has 4 bytes allocated to it |
4 | s24 | PosY | Marker's Y coordinate Note: This is a s24 value but has 4 bytes allocated to it |
8 | s24 | PosZ | Marker's Z coordinate Note: This is a s24 value but has 4 bytes allocated to it |
At the end of the section, after all the records, there is a small footer section composed of single byte values for each marker (so a map with 10 markers will have 10 bytes at the end).
These are boolean flags that enable/disable the marker and are paired to records based on their index (i.e., 1st byte goes to 1st record, 2nd to 2nd, etc). All marker records are enabled in all maps so not really used.
MPSZ: Size dataEdit
Contains scaling information for objects, with each object having up to 3 scaling values used (normal, combat, and dead).
This section does not have a record count but records are fixed size at 49 bytes, so record count can be deduced from DataLength in header.
Offset | DataType | Name | Description |
---|---|---|---|
0 | u8 | Unknown_00 | Always 00 |
1 | u32 | SizeX | |
5 | u32 | SizeY | |
9 | u32 | SizeZ | |
13 | s32 | PosX | Always 00 - Name is from console output |
17 | s32 | PosY | Always 00 - not sure if really supposed to be a position (and thus s24) |
21 | s32 | PosZ | Always 00 - or an offset since all 00s |
25 | u32 | PSizeX | What I know about 3D modeling amounts to basic awareness |
29 | u32 | PSizeY | So I have no idea what a "P" size is... Perspective? |
33 | u32 | PSizeZ | Polysomethingorother? |
37 | u32 | MSizeX | Or a "M" size either |
41 | u32 | MSizeY | Mesh? |
45 | u32 | MSizeZ | Maybe? |
WDNM: Node mapEdit
<TBA>
Offset | DataType | Name | Description |
---|