So looking through some old source code I found a folder inside a project called "for hamp", given to me by either Altimit01 or Modzy. It was a collection of methods and structures to use for editing the compiled halo mapfiles.
It contained a whole lot of methods and offsets, and I'm certain these are well known, but in case any at all were lost to time or their meanings misremembered, I'm dumping all of it here. Sorry, not sorry.
Read BSP Header
Quote:
//Read and move stream to the start of the tag's attributes
br.Position = Raw_offset
Dim tag_start As New Magic_mod_pointer
tag_start.read(br, magic, Raw_offset)
br.Position = tag_start.Offset_in_map
//start reading header attributes
Dim SBSP_class As String = flip(br.Read(4))
Lightmap = New Reference
Lightmap.read(br)
Vehicle_floor = br.ReadInt32
Vehicle_ceiling = br.ReadInt32
garb = br.Read(&h8C) //Something do to with colors, I'll have to install a VM to map this
Collision_materials = New Reflexive
Collision_materials.read(br, magic, Raw_offset)
Collision_BSP = New Reflexive
Collision_BSP.read(br, magic, Raw_offset)
Nodes = New Reflexive
Nodes.read(br, magic, Raw_offset)
World_bounds_x_from = br.ReadSingle
World_bounds_x_to = br.ReadSingle
World_bounds_y_from = br.ReadSingle
World_bounds_y_to = br.ReadSingle
World_bounds_z_from = br.ReadSingle
World_bounds_z_to = br.ReadSingle
Leaves = New Reflexive
Leaves.read(br, magic, Raw_offset)
Leaf_surfaces = New Reflexive
Leaf_surfaces.read(br, magic, Raw_offset)
Surfaces = New Reflexive
Surfaces.read(br, magic, Raw_offset)
Lightmaps_mesh = New Reflexive
Lightmaps_mesh.read(br, magic, Raw_offset)
Loading a map
Quote:
If Map <> nil AND Map.Exists then //If all is true, load the map.
Dim br As BinaryStream = Map.OpenAsBinaryFile(FALSE)
br.LittleEndian = TRUE
Map_file = Map
//Read Header
Dim Header As String=br.Read(4)
If Header="daeh" Then
br.Position = 4
Game_build = br.ReadUInt32
Map_size = br.ReadUInt32
Garb = br.Read(4)
Index_offset = br.ReadUInt32
Meta_data_length = br.ReadUInt32
Garb = br.Read(8)
Map_name = string_reader(br)
br.Position = &h40
Build_date = string_reader(br)
br.Position = &h60
Map_type = br.ReadUInt32
load_map_attributes(br)
Load_boolean = True
Else
br.Position=&h2C0
Header=br.Read(4)
If Header="dehE" then
br.Position = 2
Map_type = br.ReadUInt8
br.Position = &h2C4
Meta_data_length = br.ReadUInt32
Build_date = string_reader(br)
br.Position = &h588
Game_build = br.ReadUInt32
Map_name = string_reader(br)
br.Position = &h5E8
Map_size = br.ReadUInt32
Index_offset = br.ReadUInt32
load_map_attributes(br)
Load_boolean = True
Else
MsgBox "Not a supported Map file."
Load_boolean = False
end
end
br.Close
end
Load Map Attributes
Quote:
//Read Index header
br.Position = Index_offset //Relocate the stream to the start of the index header, offset derived from method "load."
Memory_offset = br.ReadUInt32 - &h28 //Offset to index-array within run-time memory.
Map_magic = Memory_offset - Index_offset //Universal magic for calculating offsets within the map file which have been modified by version-specific offsets.
scnr_ID = br.ReadUInt32 //The ID of the map files' Scenario.
Map_ID = br.ReadUInt32 //Unknown 32-bit integer. Calling it a map ID for now.
Tag_count = br.ReadUInt32 //The number of items in the index array; tags.
Verticie_count = br.ReadUInt32 //Number of verticies in model data section.
Verticie_offset = br.ReadUInt32 //Offset to the start of all verticies in model data section.
Indicie_count = br.ReadUInt32 //Number of indicies in model data section.
Indicie_offset = br.ReadUInt32 //Offset to the start of all indicies in model data section, must be modified by "Verticie_offset."
Model_data_length = br.ReadUInt32 //Size of model data section.
Garb = br.Read(4) //Unneeded string; "sgat" -- "tags."
//Read Index Items
Tag_IDs = New Dictionary //A place to store and call tags' IDs.
Dim Temp_tags() As Tag
Tag_classes = New Dictionary
For I = 0 to Tag_count - 1 //Start loop.
Dim New_tag As New Tag //New tag to be given attributes.
New_tag.First_class = flip(br.Read(4)) //
New_tag.Second_class = flip(br.Read(4))
New_tag.Third_class = flip(br.Read(4))
New_tag.ID = br.ReadUInt32
New_tag.Name_offset = br.ReadUInt32 - Map_magic
Dim Meta As UInt32 = br.ReadUInt32
New_tag.Indexed = br.ReadUInt32
Garb = br.Read(4)
If New_tag.First_class <> "sbsp" AND New_tag.Indexed = 0 then
New_tag.Meta_offset = Meta - Map_magic
end
Tag_classes.Value(New_tag.First_class) = New_tag.First_class
Temp_tags.Append New_tag
Tag_IDs.Value(New_tag.ID) = I
next
Tags() = Temp_tags
//Read Tag Names
For I = 0 to Tag_count - 1
br.Position = Tags(I).Name_offset
Tags(I).Name = string_reader(br)
next
////Calculate tag lengths////
Dim Tag_lengths() As UInt32
Dim Tag_offsets As New Dictionary
For I = 0 to Tag_count - 1
If Tags(I).First_class <> "sbsp" AND Tags(I).Indexed = 0 then
Dim Offset As UInt32 = Tags(I).Meta_offset
Tag_lengths.Append Offset
Tag_offsets.Value(Offset) = I
end
next
Tag_lengths.Sort
For I = 0 to Tag_lengths.Ubound
If I = Tag_lengths.Ubound then
Dim Meta_offset As UInt32 = Tag_lengths(I)
Dim Tag_number As UInt32 = Tag_offsets.Value(Meta_offset)
Tags(Tag_number).Length = br.Length - Meta_offset
else
Dim Meta_offset As UInt32 = Tag_lengths(I)
Dim Second_offset As UInt32 = Tag_lengths(I + 1)
Dim Tag_number As UInt32 = Tag_offsets.Value(Meta_offset)
Tags(Tag_number).Length = Second_offset - Meta_offset
end
next
//Get BSP offset and length
br.Position = Tags(Tag_IDs.Value(scnr_ID)).Meta_offset + &h5A4
Dim BSP_chunk As New Reflexive
BSP_chunk.Offset = br.Position
BSP_chunk.Count = br.ReadInt32
BSP_chunk.Offset_in_map = br.ReadInt32 - Map_magic
Dim temp_bsps() As SBSP_info
For I = 0 to BSP_chunk.Count - 1
br.Position = BSP_chunk.Offset_in_map + (I * &h20)
Dim New_BSP As New SBSP_info
New_BSP.Raw_offset = br.ReadInt32
New_BSP.Length = br.ReadInt32
New_BSP.Memory_offset = br.ReadInt32
New_BSP.Magic = New_BSP.Memory_offset - New_BSP.Raw_offset
Garb = br.Read(&h10)
New_BSP.Tag_id = br.ReadInt32
New_BSP.Tag_name = Tags(Tag_IDs.Value(New_BSP.Tag_id)).Name
Tags(Tag_IDs.Value(New_BSP.Tag_id)).Meta_offset = New_BSP.Raw_offset
Tags(Tag_IDs.Value(New_BSP.Tag_id)).Length = New_BSP.Length
temp_bsps.Append New_BSP
next
SBSPs = temp_bsps
Reflexive
Quote: offset = Stream.Position
Count = Stream.ReadInt32
Offset_in_map = Stream.ReadInt32 - Magic
Transition = Offset_in_map - meta_start
garb = Stream.Read(4)
Reference
Quote: Offset = Stream.Position
Tag_class = flip(Stream.Read(4))
Name_offset = Stream.ReadInt32
garb = Stream.Read(4)
ID = Stream.ReadInt32
Notes: Memory Structure
Quote:
0x- Tag data stored as:
-Total length(Int32)
-Tag Name
-Handle Name
-Meta data length(Int32)
-Meta data
-Reflexive array start/count of Reflexives(Int32):
-offset from start of meta data
-count
-transition; not magic modified
-Reference Array start/count of References(Int32):
-offset from start of meta data
-Tag Class
-Handle Name
-Reference ID
-Lone ID Array start/count of Lone ID(Int32):
-offset from start of meta data
-Handle Name
-Reference ID
-Raw Data(Not necessary for every tag. Structure changes between tags.)