This page documents the function and format of some of Halo's installation and profile files, excluding maps. Many of these files are only applicable to Custom Edition.

haloce.exe

This is the main Custom Edition game executable containing the bulk of the game's code.

By default, it is only permitted to use 2 GB of virtual memory. By applying value 0x2F at offset 0x136 in the 1.0.10 executable, Halo can be made "Large Address Aware" and capable of using up to 4GB of virtual memory. The same upgrade can be made to Sapien. The increased limit can be useful for client mods like Chimera which run in the game's address space and allocate more memory to speed up map loading.

strings.dll

The library strings.dll is required to run the game or dedicated server. It serves multiple purposes:

  • Contains the loading screen image seen before the main menu (all other loading screens are contained in maps).
  • Displays crash messages in a window.
  • Prior to the 1.10 patch, it contained the executable_is_valid checksum.

This DLL is often replaced with a modified version for mods like SAPP and Chimera 1.0+.

Watson

The Watson directory and the files within it (dw15.exe, various dwintl.dll) are a defunct crash reporting system. The server to which crash reports would be sent is no longer running. The mod Chimera disables this to allow the game to crash faster without waiting for a network timeout.

Multiplayer chat: Keystone, controls, and content

An example modified chat editbox.

The library Keystone.dll is used for Halo's stock multiplayer chat functionality. The game also requires the library msxml.dll to be installed on the system for chat to display properly. An installer can be found in Halo's redist directory.

The controls directory is host to Controls.ini and Controls.dll, a library used to render the multiplayer chat input box. It makes use of files in the content directory, which can be modified to customize the appearance of the chat "editbox" and text input.

The mods HAC2 and Chimera implement their own chat display to replace Halo's, which becomes unreliable after tabbing out of the game.

Profile and savegame files

Halo stores savegames and profile data according to the system-wide %USERPROFILE% environment variable. On Windows, with a system drive "C" and user name "John", Halo saves can be found in C:\Users\You\Documents\My Games\Halo CE\. When running on Linux under Wine, the default location is ~/My Games/Halo CE/. Some mods also store data under this location, such as downloaded maps.

lastprof.txt

The file lastprof.txt stores the path of the last used profile so it can be loaded at game startup. It has a fixed length of 256 bytes and a very simple structure:

  1. An ASCII-encoded absolute filesystem path to a profile directory, with trailing \. For example, C:\Users\You\My Documents\My Games\Halo CE\savegames\New001\
  2. A null byte, 0x00, to terminate the above string.
  3. The ASCII-encoded string lam.sav (not a typo).
  4. 0x00 padding until the end of the file.

savegame.bin

The file savegames\<profile name>\savegame.bin contains the saved state of the campaign, allowing progress to be resumed when reloading from a checkpoint or returning from the main menu. The Halo console commands game_save and game_revert use this file. A newly-created savegame.bin is typically filled with NULL to 0x480000 (4,718,592 bytes).

The structure of this file is not fully mapped out, however some fields are known:

FieldOffset (relative)TypeComments
0x0pad(482)
last difficulty0x1E2DifficultyOpts: enum8
OptionValueComments
easy0x0
normal0x1
hard0x2
legendary0x3
0x1E3pad(5)
last played scenario0x1E8char[32]

An ASCII-encoded scenario tag path, null-terminated and 32 characters max. An example value is levels\b30\b30 for The Silent Cartographer.

blam.sav

The file savegames\<profile name>\blam.sav contains the configuration for a HCE profile. Information includes player details, video/audio/network settings, and input configurations (mouse, keyboard, and controller). It has a fixed length of 8192 bytes (8 KiB). File integrity is verified by a checksum at the end of the file; if the checksum does not match the game will fall back to default settings.

The file structure follows. All data is little-endian unless otherwise stated.

FieldOffset (relative)TypeComments
0x0pad(2)
player details0x2PlayerDetails
FieldOffset (relative)TypeComments
player name0x0UTF-16(24)

The player's name, encoded as UTF-16. Null-terminated with a maximum of 11 characters (excluding the null).

0x18pad(256)
player color0x118PlayerColors: enum8

Determines the player's multiplayer armour colour. Defaults to 0xFF (random).

OptionValueComments
white0x0
black0x1
red0x2
blue0x3
gray0x4
yellow0x5
green0x6
pink0x7
purple0xA
cyan0xB
cobalt0xC
orange0xD
teal0xE
sage0xF
brown0x10
tan0x11
maroon0x14
salmon0x15
random0xFF
0x11Bpad(20)
control settings0x12FControlSettings

Contains input-related settings, including mouse, keyboard, and gamepad bindings.

FieldOffset (relative)TypeComments
invert vertical axis0x0bool

Controls if the player's vertical aiming axis controls are inverted, e.g. pulling the mouse down aims up.

0x1pad(4)
keyboard bindings0x5KeyboardBindings

A mapping of 109 keyboard inputs to game functions, each a little-endian uint16 (2 bytes long). The entries are ordered roughly like the rows of a QWERTY keyboard, with each position in the array corresponding to a certain input key. If a key is unbound, then that position holds the bytes 0x7F 0xFF. Otherwise, bound keys store a value representing the game function the key is mapped to, for example 0x05 0x00 for flashlight.

FieldOffset (relative)TypeComments
Escape0x0Action: enum16

Defaults to 0x09 (MenuBack) and is unchangeable. Hardcoded to pause the game.

OptionValueComments
Jump0x0
SwitchGrenade0x1
Action0x2
SwitchWeapon0x3
MeleeAttack0x4
Flashlight0x5
ThrowGrenade0x6
FireWeapon0x7
MenuAccept0x8

Keyboard only

MenuBack0x9

Keyboard only

Crouch0xA
ScopeZoom0xB
ShowScores0xC
Reload0xD
ExchangeWeapon0xE
Say0xF
SayToTeam0x10
SayToVehicle0x11
Screenshot0x12
MoveForward0x13
MoveBackward0x14
MoveLeft0x15
MoveRight0x16
LookUp0x17
LookDown0x18
LookLeft0x19
LookRight0x1A
ShowRules0x1B
ShowPlayerNames0x1C
F10x2Action: enum16?

Defaults to 0x0C (ShowScores)

F20x4Action: enum16?

Defaults to 0x1B (ShowRules)

F30x6Action: enum16?

Defaults to 0x1C (ShowPlayerNames)

F40x8Action: enum16?
F50xAAction: enum16?
F60xCAction: enum16?
F70xEAction: enum16?
F80x10Action: enum16?
F90x12Action: enum16?
F100x14Action: enum16?
F110x16Action: enum16?
F120x18Action: enum16?
Printscreen0x1AAction: enum16?

Defaults to 0x12 (Screenshot)

ScrollLock0x1CAction: enum16?
PauseBreak0x1EAction: enum16?
Grave0x20Action: enum16?
NumRow10x22Action: enum16?
NumRow20x24Action: enum16?
NumRow30x26Action: enum16?
NumRow40x28Action: enum16?
NumRow50x2AAction: enum16?
NumRow60x2CAction: enum16?
NumRow70x2EAction: enum16?
NumRow80x30Action: enum16?
NumRow90x32Action: enum16?
NumRow00x34Action: enum16?
EnDash0x36Action: enum16?
Equals0x38Action: enum16?
Backspace0x3AAction: enum16?
Tab0x3CAction: enum16?

Defaults to 0x03 (SwitchWeapon)

Q0x3EAction: enum16?

Defaults to 0x05 (Flashlight)

W0x40Action: enum16?

Defaults to 0x13 (MoveForward)

E0x42Action: enum16?

Defaults to 0x02 (Action)

R0x44Action: enum16?

Defaults to 0x0D (Reload)

T0x46Action: enum16?

Defaults to 0x0F (Say)

Y0x48Action: enum16?

Defaults to 0x10 (SayToTeam)

U0x4AAction: enum16?
I0x4CAction: enum16?
O0x4EAction: enum16?
P0x50Action: enum16?
BracketL0x52Action: enum16?
BracketR0x54Action: enum16?
Backslash0x56Action: enum16?
CapsLock0x58Action: enum16?
A0x5AAction: enum16?

Defaults to 0x15 (MoveLeft)

S0x5CAction: enum16?

Defaults to 0x14 (MoveBackward)

D0x5EAction: enum16?

Defaults to 0x16 (MoveRight)

F0x60Action: enum16?

Defaults to 0x04 (MeleeAttack)

G0x62Action: enum16?

Defaults to 0x01 (SwitchGrenade)

H0x64Action: enum16?

Defaults to 0x11 (SayToVehicle)

J0x66Action: enum16?
K0x68Action: enum16?
L0x6AAction: enum16?
SemiColon0x6CAction: enum16?
Apostrophe0x6EAction: enum16?
Enter0x70Action: enum16?

Defaults to 0x08 (MenuAccept). Keyboard only and unchangeable.

ShiftL0x72Action: enum16?
Z0x74Action: enum16?

Defaults to 0x0B (ScopeZoom)

X0x76Action: enum16?

Defaults to 0x0E (ExchangeWeapon)

C0x78Action: enum16?
V0x7AAction: enum16?
B0x7CAction: enum16?
N0x7EAction: enum16?
M0x80Action: enum16?
Comma0x82Action: enum16?
Period0x84Action: enum16?
Slash0x86Action: enum16?
RShift0x88Action: enum16?
LCtrl0x8AAction: enum16?

Defaults to 0x0A (Crouch)

LWin0x8CAction: enum16?
LAlt0x8EAction: enum16?
Space0x90Action: enum16?

Defaults to 0x00 (Jump)

RAlt0x92Action: enum16?
RWin0x94Action: enum16?

Unchangeable

Menu0x96Action: enum16?

Unchangeable

RCtrl0x98Action: enum16?
UpArrow0x9AAction: enum16?
DownArrow0x9CAction: enum16?
LeftArrow0x9EAction: enum16?
RightArrow0xA0Action: enum16?
Insert0xA2Action: enum16?
Home0xA4Action: enum16?
PgUp0xA6Action: enum16?
Delete0xA8Action: enum16?
End0xAAAction: enum16?
PgDown0xACAction: enum16?
NumLock0xAEAction: enum16?

Unchangeable

KPDivide0xB0Action: enum16?
KPMultiply0xB2Action: enum16?
Keypad00xB4Action: enum16?
Keypad10xB6Action: enum16?
Keypad20xB8Action: enum16?
Keypad30xBAAction: enum16?
Keypad40xBCAction: enum16?
Keypad50xBEAction: enum16?
Keypad60xC0Action: enum16?
Keypad70xC2Action: enum16?
Keypad80xC4Action: enum16?
Keypad90xC6Action: enum16?
KeypadMinus0xC8Action: enum16?
KeypadPlus0xCAAction: enum16?
Unknown10xCCAction: enum16?

Probably KeyPadEnter

KeypadDecimal0xCEAction: enum16?
Unknown20xD0Action: enum16?
Unknown30xD2Action: enum16?
Unknown40xD4Action: enum16?
Unknown50xD6Action: enum16?
Unknown60xD8Action: enum16?
mouse bindings0xDFMouseBindings

Bindings for the mouse device, similar to the keyboard structure.

FieldOffset (relative)TypeComments
Left Button0x0Action: enum16?
Middle Button0x2Action: enum16?
Right Button0x4Action: enum16?
Button 40x6Action: enum16?
Button 50x8Action: enum16?
Button 60xAAction: enum16?
Button 70xCAction: enum16?
Button 80xEAction: enum16?
Horizontal Axis -0x10Action: enum16?
Horizontal Axis +0x12Action: enum16?
Vertical Axis -0x14Action: enum16?
Vertical Axis +0x16Action: enum16?
Wheel -0x18Action: enum16?
Wheel +0x1AAction: enum16?
gamepad bindings0xFBGamepadBindings

Bindings for gamepads, similar to the keyboard structure. Supports 4 controllers, with each controller's input groups interleaved.

FieldOffset (relative)TypeComments
gamepad buttons0x0GamepadButtonBindings[4]
FieldOffset (relative)TypeComments
Button00x0Action: enum16?

DirectInput Button 0 (Face - button A)

Button10x2Action: enum16?

DirectInput Button 1 (Face - button B)

Button20x4Action: enum16?

DirectInput Button 2 (Face - button X)

Button30x6Action: enum16?

DirectInput Button 3 (Face - button Y)

Button40x8Action: enum16?

DirectInput Button 4 (Shoulder - left bumper)

Button50xAAction: enum16?

DirectInput Button 5 (Shoulder - right bumper)

Button60xCAction: enum16?

DirectInput Button 6 (Home - back)

Button70xEAction: enum16?

DirectInput Button 7 (Home - start)

Button80x10Action: enum16?

DirectInput Button 8 (Analogue - left stick - click)

Button90x12Action: enum16?

DirectInput Button 9 (Analogue - right stick - click)

Button100x14Action: enum16?

DirectInput Button 10

0x16pad(42)
gamepad menu bindings0x100GamePadMenuBindings[4]
FieldOffset (relative)TypeComments
menu accept0x0DirectInputButtons: enum16

Holds the button ID used to accept menu selections.

OptionValueComments
Button00x0

Face - button A

Button10x1

Face - button B

Button20x2

Face - button X

Button30x3

Face - button Y

Button40x4

Shoulder - L shoulder, white

Button50x5

Shoulder - R shoulder, black

Button60x6

Home - back

Button70x7

Home - start

Button80x8

Analogue - left stick - click

Button90x9

Analogue - right stick - click

Button100xA
Button110xB
Button120xC
Button130xD
Button140xE
menu back0x2DirectInputButtons: enum16?

Holds the button ID used to go back in menus.

gamepad axis set0x110GamepadAxisBindings[4]
FieldOffset (relative)TypeComments
Axis1Pos0x0Action: enum16?

DirectInput Axis 1 (Analogue - left stick - down)

Axis1Neg0x2Action: enum16?

DirectInput Axis 1 (Analogue - left stick - up)

Axis2Pos0x4Action: enum16?

DirectInput Axis 2 (Analogue - left stick - right)

Axis2Neg0x6Action: enum16?

DirectInput Axis 2 (Analogue - left stick - left)

Axis3Pos0x8Action: enum16?

DirectInput Axis 3 (Analogue - right stick - down)

Axis3Neg0xAAction: enum16?

DirectInput Axis 3 (Analogue - right stick - up)

Axis4Pos0xCAction: enum16?

DirectInput Axis 4 (Analogue - right stick - right)

Axis4Neg0xEAction: enum16?

DirectInput Axis 4 (Analogue - right stick - left)

Axis5Pos0x10Action: enum16?

DirectInput Axis 5 (Shoulder - trigger - left)

Axis5Neg0x12Action: enum16?

DirectInput Axis 5 (Shoulder - trigger - right)

Axis6Pos0x14Action: enum16?

DirectInput Axis 6+

Axis6Neg0x16Action: enum16?

DirectInput Axis 6-

0x18pad(104)
gamepad dpad buttons0x310GamepadDirPadBindings[4]
FieldOffset (relative)TypeComments
DirPadUp0x0Action: enum16?

Directional - up

0x2pad(2)
DirPadRight0x4Action: enum16?

Directional - right

0x6pad(2)
DirPadDown0x8Action: enum16?

Directional - down

0xApad(2)
DirPadLeft0xCAction: enum16?

Directional - left

0xEpad(242)
0x80Bpad(26)
horizontal mouse sensitivity0x825uint8

Ranges in value from 0 (minimum) to 10 (maximum).

vertical mouse sensitivity0x826uint8

Ranges in value from 0 (minimum) to 10 (maximum).

gamepad horizontal sensitivities0x827uint8[4]

An array of 4 controller horizontal aiming sensitivities. Index using 0 for the first controller, 1 for the second, etc.

gamepad vertical sensitivities0x82Buint8[4]

An array of 4 controller vertical aiming sensitivities. Index using 0 for the first controller, 1 for the second, etc.

0x95Epad(266)
video settings0xA68VideoSettings
FieldOffset (relative)TypeComments
resolution width0x0uint16
resolution height0x2uint16
refresh rate0x4uint8

Will take the literal values 59 (0x3B) or 60 (0x3C)

unknown0x5pad(2)

Has a value of 0x00 0x02

frame rate0x7FrameRateOptions: enum8
OptionValueComments
vsync off0x0
vsync on0x1
30 FPS0x2
specular0x8bool
shadows0x9bool
decals0xAbool
particles0xBParticlesSettings: enum8
OptionValueComments
off0x0
low0x1
high0x2
texture quality0xCQualityOptions: enum8
OptionValueComments
low0x0
medium0x1
high0x2
0xDpad(1)
gamma0xEuint8

Options: +1 (0xD8), +2 (0xDF), +3 (0xE6)

0xFpad(1)
0xA78pad(256)
audio settings0xB78AudioSettings
FieldOffset (relative)TypeComments
master volume0x0uint8
effects volume0x1uint8
music volume0x2uint8
enable EAX0x3bool
enable hardware acceleration0x4bool
sound quality0x5QualityOptions: enum8?
0x6pad(1)
audio variety0x7QualityOptions: enum8?
0xB80pad(524)
network settings0xD8CNetworkSettings
FieldOffset (relative)TypeComments
server name0x0UTF-16(64)

Stores the last-used hosting server name for the "create game" menus (both LAN and Internet). Null-terminated with a maximum of 31 characters (excluding the null).

0x40pad(224)
password0x120UTF-16(18)

Stores the last-used hosting password for the "create game" menus (both LAN and Internet). Null-terminated with a maximum of 8 characters (excluding the null)

0x132pad(1)
max players0x133uint8

Stores the last-used max players for hosting a server. The value 0x00 actually corresponds to the minimum of 2 players, with 0x0E being the maximum of 16.

0x134pad(256)
connection type0x234ConnectionTypes: enum8
OptionValueComments
56k0x0
dsl-low0x1
dsl-avg0x2
dsl-high0x3
t1/lan0x4
0x235pad(1)
server address0x236UTF-16(64)

Stores the default server address for Direct IP connections. This value could contain an IP and port separated by a ":" or even a DNS host name. Encoded as UTF-16, null-terminated with a maximum of 31 characters (excluding the null).

server port0x276uint16

Defaults to the value 2302

client port0x278uint16

Defaults to the value 2303

0x1006pad(258)
gamepad info0x1108GamepadInfo[4]
FieldOffset (relative)TypeComments
gamepad name0x0UTF-16(512)

Stores the name of the controller device seen when configuring button bindings (if configured). UTF-16 String. Some examples are "Xbox Controller S via XBCD" or "Xbox 360 Controller For Windows". The size of this buffer is unknown, so 512 bytes is assumed. When Halo detects two devices with the same name, the second one will have " (2)" appended to its name.

0x200pad(12)

This padding size is unknown and depends on the above buffer's size.

vendor ID0x20Cuint16

4-digit hex identifying the vendor/manufacturer of the gamepad. For example, 045E is Microsoft. This would be little-endian encoded as 5E 04. A list of hardware vendor IDs can be found here.

product ID0x20Euint16

4-digit hex identifying the gamepad product. For example, 0289 (89 02 little-endian) is the Xbox Controller S. Devices by vendor can be found here (Microsoft).

0x210pad(6)

Zeroed-out values

pidvid0x216char[6]

An ASCII string with value "PIDVID"

dupe ID0x21Cuint8

Distinguishes multiple gamepads with the same vendor and product ID. Takes the value 0x00, then 0x01, etc.

0x21Dpad(3)
0x1988pad(1652)

Unknown region

crc32 hash0x1FFCuint32

The blam.sav has a CRC-32 checksum appended at the end of it. The value is actually stored in its complement equivalent (i.e. bitwise NOT). The checksum validates the data between 0x000 and 0x1FFC - the checksum itself is not included! There is a relatively large amount of padding before this field, and it is the final 4 bytes of the file. Due to the complement on this field, the entire file will always have a CRC of 0xFFFFFFFF. Therefore the file can be verified by either comparing its overall CRC to 0xFFFFFFFF, or comparing the CRC of its prior sections to the complement of this field.

00.sav and 01.sav

In saved\player_profiles\default_profile there are two files, 00.sav and 01.sav with the same player profile structure as blam.sav. However, these files contain empty or default values only. They have default key bindings and no controller bindings. The 01.sav file differs from 00.sav in only three ways:

  • An unknown field at offset 0x11D is set to true.
  • The invert Y axis field at offset 0x12F is set to true.
  • The checksum differs due to the above differences.

Halo overwrites or creates these files with their original contents every time the game starts. Replacing their contents with other profile data and forcing the files to be read-only does not have any effect on default profile creation, default bindings, or controls used when loaded into a map before first profile creation. Their purpose is a mystery.

Acknowledgements

Thanks to the following individuals for their research or contributions to this topic:

  • Conscars (Additional blam.sav reversing)
  • Miris (Profile and savegame reversing, LAA patch)
  • MrChromed (Loading screen tip)
  • nToss (Researching offsets for profile input bindings and other fields)
  • Sparky (Control binding ranges)
  • Vaporeon (Watson and strings.dll background)