Game and profile files

This page documents the function and format of some of Halo's installation and profile files, excluding maps.

haloce.exe

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

By default, Halo 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, a practice abandoned after mods implemented better chat systems.

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:

Field Type Comments
pad(482)
last difficulty DifficultyOpts: enum(8-bit)
Option Value Comments
easy 0x0
normal 0x1
hard 0x2
legendary 0x3
pad(5)
last played scenario char[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.

Field Offset (relative) Type Comments
0x0 pad(2)
player details 0x2 PlayerDetails
Field Offset (relative) Type Comments
player name 0x0 UTF-16(24)

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

0x18 pad(256)
player color 0x118 PlayerColors: enum(8-bit)

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

Option Value Comments
white 0x0
black 0x1
red 0x2
blue 0x3
gray 0x4
yellow 0x5
green 0x6
pink 0x7
purple 0xA
cyan 0xB
cobalt 0xC
orange 0xD
teal 0xE
sage 0xF
brown 0x10
tan 0x11
maroon 0x14
salmon 0x15
random 0xFF
0x11B pad(20)
control settings 0x12F ControlSettings

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

Field Offset (relative) Type Comments
invert vertical axis 0x0 bool

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

0x1 pad(4)
keyboard bindings 0x5 KeyboardBindings

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.

Field Offset (relative) Type Comments
Escape 0x0 Action: enum(16-bit)

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

Option Value Comments
Jump 0x0
SwitchGrenade 0x1
Action 0x2
SwitchWeapon 0x3
MeleeAttack 0x4
Flashlight 0x5
ThrowGrenade 0x6
FireWeapon 0x7
MenuAccept 0x8

Keyboard only

MenuBack 0x9

Keyboard only

Crouch 0xA
ScopeZoom 0xB
ShowScores 0xC
Reload 0xD
ExchangeWeapon 0xE
Say 0xF
SayToTeam 0x10
SayToVehicle 0x11
Screenshot 0x12
MoveForward 0x13
MoveBackward 0x14
MoveLeft 0x15
MoveRight 0x16
LookUp 0x17
LookDown 0x18
LookLeft 0x19
LookRight 0x1A
ShowRules 0x1B
ShowPlayerNames 0x1C
F1 0x2 Action: enum(16-bit)

Defaults to 0x0C (ShowScores)

F2 0x4 Action: enum(16-bit)

Defaults to 0x1B (ShowRules)

F3 0x6 Action: enum(16-bit)

Defaults to 0x1C (ShowPlayerNames)

F4 0x8 Action: enum(16-bit)
F5 0xA Action: enum(16-bit)
F6 0xC Action: enum(16-bit)
F7 0xE Action: enum(16-bit)
F8 0x10 Action: enum(16-bit)
F9 0x12 Action: enum(16-bit)
F10 0x14 Action: enum(16-bit)
F11 0x16 Action: enum(16-bit)
F12 0x18 Action: enum(16-bit)
Printscreen 0x1A Action: enum(16-bit)

Defaults to 0x12 (Screenshot)

ScrollLock 0x1C Action: enum(16-bit)
PauseBreak 0x1E Action: enum(16-bit)
Grave 0x20 Action: enum(16-bit)
NumRow1 0x22 Action: enum(16-bit)
NumRow2 0x24 Action: enum(16-bit)
NumRow3 0x26 Action: enum(16-bit)
NumRow4 0x28 Action: enum(16-bit)
NumRow5 0x2A Action: enum(16-bit)
NumRow6 0x2C Action: enum(16-bit)
NumRow7 0x2E Action: enum(16-bit)
NumRow8 0x30 Action: enum(16-bit)
NumRow9 0x32 Action: enum(16-bit)
NumRow0 0x34 Action: enum(16-bit)
EnDash 0x36 Action: enum(16-bit)
Equals 0x38 Action: enum(16-bit)
Backspace 0x3A Action: enum(16-bit)
Tab 0x3C Action: enum(16-bit)

Defaults to 0x03 (SwitchWeapon)

Q 0x3E Action: enum(16-bit)

Defaults to 0x05 (Flashlight)

W 0x40 Action: enum(16-bit)

Defaults to 0x13 (MoveForward)

E 0x42 Action: enum(16-bit)

Defaults to 0x02 (Action)

R 0x44 Action: enum(16-bit)

Defaults to 0x0D (Reload)

T 0x46 Action: enum(16-bit)

Defaults to 0x0F (Say)

Y 0x48 Action: enum(16-bit)

Defaults to 0x10 (SayToTeam)

U 0x4A Action: enum(16-bit)
I 0x4C Action: enum(16-bit)
O 0x4E Action: enum(16-bit)
P 0x50 Action: enum(16-bit)
BracketL 0x52 Action: enum(16-bit)
BracketR 0x54 Action: enum(16-bit)
Backslash 0x56 Action: enum(16-bit)
CapsLock 0x58 Action: enum(16-bit)
A 0x5A Action: enum(16-bit)

Defaults to 0x15 (MoveLeft)

S 0x5C Action: enum(16-bit)

Defaults to 0x14 (MoveBackward)

D 0x5E Action: enum(16-bit)

Defaults to 0x16 (MoveRight)

F 0x60 Action: enum(16-bit)

Defaults to 0x04 (MeleeAttack)

G 0x62 Action: enum(16-bit)

Defaults to 0x01 (SwitchGrenade)

H 0x64 Action: enum(16-bit)

Defaults to 0x11 (SayToVehicle)

J 0x66 Action: enum(16-bit)
K 0x68 Action: enum(16-bit)
L 0x6A Action: enum(16-bit)
SemiColon 0x6C Action: enum(16-bit)
Apostrophe 0x6E Action: enum(16-bit)
Enter 0x70 Action: enum(16-bit)

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

ShiftL 0x72 Action: enum(16-bit)
Z 0x74 Action: enum(16-bit)

Defaults to 0x0B (ScopeZoom)

X 0x76 Action: enum(16-bit)

Defaults to 0x0E (ExchangeWeapon)

C 0x78 Action: enum(16-bit)
V 0x7A Action: enum(16-bit)
B 0x7C Action: enum(16-bit)
N 0x7E Action: enum(16-bit)
M 0x80 Action: enum(16-bit)
Comma 0x82 Action: enum(16-bit)
Period 0x84 Action: enum(16-bit)
Slash 0x86 Action: enum(16-bit)
RShift 0x88 Action: enum(16-bit)
LCtrl 0x8A Action: enum(16-bit)

Defaults to 0x0A (Crouch)

LWin 0x8C Action: enum(16-bit)
LAlt 0x8E Action: enum(16-bit)
Space 0x90 Action: enum(16-bit)

Defaults to 0x00 (Jump)

RAlt 0x92 Action: enum(16-bit)
RWin 0x94 Action: enum(16-bit)

Unchangeable

Menu 0x96 Action: enum(16-bit)

Unchangeable

RCtrl 0x98 Action: enum(16-bit)
UpArrow 0x9A Action: enum(16-bit)
DownArrow 0x9C Action: enum(16-bit)
LeftArrow 0x9E Action: enum(16-bit)
RightArrow 0xA0 Action: enum(16-bit)
Insert 0xA2 Action: enum(16-bit)
Home 0xA4 Action: enum(16-bit)
PgUp 0xA6 Action: enum(16-bit)
Delete 0xA8 Action: enum(16-bit)
End 0xAA Action: enum(16-bit)
PgDown 0xAC Action: enum(16-bit)
NumLock 0xAE Action: enum(16-bit)

Unchangeable

KPDivide 0xB0 Action: enum(16-bit)
KPMultiply 0xB2 Action: enum(16-bit)
Keypad0 0xB4 Action: enum(16-bit)
Keypad1 0xB6 Action: enum(16-bit)
Keypad2 0xB8 Action: enum(16-bit)
Keypad3 0xBA Action: enum(16-bit)
Keypad4 0xBC Action: enum(16-bit)
Keypad5 0xBE Action: enum(16-bit)
Keypad6 0xC0 Action: enum(16-bit)
Keypad7 0xC2 Action: enum(16-bit)
Keypad8 0xC4 Action: enum(16-bit)
Keypad9 0xC6 Action: enum(16-bit)
KeypadMinus 0xC8 Action: enum(16-bit)
KeypadPlus 0xCA Action: enum(16-bit)
Unknown1 0xCC Action: enum(16-bit)

Probably KeyPadEnter

KeypadDecimal 0xCE Action: enum(16-bit)
Unknown2 0xD0 Action: enum(16-bit)
Unknown3 0xD2 Action: enum(16-bit)
Unknown4 0xD4 Action: enum(16-bit)
Unknown5 0xD6 Action: enum(16-bit)
Unknown6 0xD8 Action: enum(16-bit)
mouse bindings 0xDF MouseBindings

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

Field Offset (relative) Type Comments
Left Button 0x0 Action: enum(16-bit)
Middle Button 0x2 Action: enum(16-bit)
Right Button 0x4 Action: enum(16-bit)
Button 4 0x6 Action: enum(16-bit)
Button 5 0x8 Action: enum(16-bit)
Button 6 0xA Action: enum(16-bit)
Button 7 0xC Action: enum(16-bit)
Button 8 0xE Action: enum(16-bit)
Horizontal Axis - 0x10 Action: enum(16-bit)
Horizontal Axis + 0x12 Action: enum(16-bit)
Vertical Axis - 0x14 Action: enum(16-bit)
Vertical Axis + 0x16 Action: enum(16-bit)
Wheel - 0x18 Action: enum(16-bit)
Wheel + 0x1A Action: enum(16-bit)
gamepad bindings 0xFB GamepadBindings

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

Field Offset (relative) Type Comments
gamepad buttons 0x0 GamepadButtonBindings[4]
Field Offset (relative) Type Comments
Button0 0x0 Action: enum(16-bit)

DirectInput Button 0 (Face - button A)

Button1 0x2 Action: enum(16-bit)

DirectInput Button 1 (Face - button B)

Button2 0x4 Action: enum(16-bit)

DirectInput Button 2 (Face - button X)

Button3 0x6 Action: enum(16-bit)

DirectInput Button 3 (Face - button Y)

Button4 0x8 Action: enum(16-bit)

DirectInput Button 4 (Shoulder - left bumper)

Button5 0xA Action: enum(16-bit)

DirectInput Button 5 (Shoulder - right bumper)

Button6 0xC Action: enum(16-bit)

DirectInput Button 6 (Home - back)

Button7 0xE Action: enum(16-bit)

DirectInput Button 7 (Home - start)

Button8 0x10 Action: enum(16-bit)

DirectInput Button 8 (Analogue - left stick - click)

Button9 0x12 Action: enum(16-bit)

DirectInput Button 9 (Analogue - right stick - click)

Button10 0x14 Action: enum(16-bit)

DirectInput Button 10

0x16 pad(42)
gamepad menu bindings 0x100 GamePadMenuBindings[4]
Field Offset (relative) Type Comments
menu accept 0x0 DirectInputButtons: enum(16-bit)

Holds the button ID used to accept menu selections.

Option Value Comments
Button0 0x0

Face - button A

Button1 0x1

Face - button B

Button2 0x2

Face - button X

Button3 0x3

Face - button Y

Button4 0x4

Shoulder - L shoulder, white

Button5 0x5

Shoulder - R shoulder, black

Button6 0x6

Home - back

Button7 0x7

Home - start

Button8 0x8

Analogue - left stick - click

Button9 0x9

Analogue - right stick - click

Button10 0xA
Button11 0xB
Button12 0xC
Button13 0xD
Button14 0xE
menu back 0x2 DirectInputButtons: enum(16-bit)

Holds the button ID used to go back in menus.

gamepad axis set 0x110 GamepadAxisBindings[4]
Field Offset (relative) Type Comments
Axis1Pos 0x0 Action: enum(16-bit)

DirectInput Axis 1 (Analogue - left stick - down)

Axis1Neg 0x2 Action: enum(16-bit)

DirectInput Axis 1 (Analogue - left stick - up)

Axis2Pos 0x4 Action: enum(16-bit)

DirectInput Axis 2 (Analogue - left stick - right)

Axis2Neg 0x6 Action: enum(16-bit)

DirectInput Axis 2 (Analogue - left stick - left)

Axis3Pos 0x8 Action: enum(16-bit)

DirectInput Axis 3 (Analogue - right stick - down)

Axis3Neg 0xA Action: enum(16-bit)

DirectInput Axis 3 (Analogue - right stick - up)

Axis4Pos 0xC Action: enum(16-bit)

DirectInput Axis 4 (Analogue - right stick - right)

Axis4Neg 0xE Action: enum(16-bit)

DirectInput Axis 4 (Analogue - right stick - left)

Axis5Pos 0x10 Action: enum(16-bit)

DirectInput Axis 5 (Shoulder - trigger - left)

Axis5Neg 0x12 Action: enum(16-bit)

DirectInput Axis 5 (Shoulder - trigger - right)

Axis6Pos 0x14 Action: enum(16-bit)

DirectInput Axis 6+

Axis6Neg 0x16 Action: enum(16-bit)

DirectInput Axis 6-

0x18 pad(104)
gamepad dpad buttons 0x310 GamepadDirPadBindings[4]
Field Offset (relative) Type Comments
DirPadUp 0x0 Action: enum(16-bit)

Directional - up

0x2 pad(2)
DirPadRight 0x4 Action: enum(16-bit)

Directional - right

0x6 pad(2)
DirPadDown 0x8 Action: enum(16-bit)

Directional - down

0xA pad(2)
DirPadLeft 0xC Action: enum(16-bit)

Directional - left

0xE pad(242)
0x80B pad(26)
horizontal mouse sensitivity 0x825 uint8

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

vertical mouse sensitivity 0x826 uint8

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

gamepad horizontal sensitivities 0x827 uint8[4]

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

gamepad vertical sensitivities 0x82B uint8[4]

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

0x95E pad(266)
video settings 0xA68 VideoSettings
Field Offset (relative) Type Comments
resolution width 0x0 uint16
resolution height 0x2 uint16
refresh rate 0x4 uint8

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

unknown 0x5 pad(2)

Has a value of 0x00 0x02

frame rate 0x7 FrameRateOptions: enum(8-bit)
Option Value Comments
vsync off 0x0
vsync on 0x1
30 FPS 0x2
specular 0x8 bool
shadows 0x9 bool
decals 0xA bool
particles 0xB ParticlesSettings: enum(8-bit)
Option Value Comments
off 0x0
low 0x1
high 0x2
texture quality 0xC QualityOptions: enum(8-bit)
Option Value Comments
low 0x0
medium 0x1
high 0x2
0xD pad(1)
gamma 0xE uint8

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

0xF pad(1)
0xA78 pad(256)
audio settings 0xB78 AudioSettings
Field Offset (relative) Type Comments
master volume 0x0 uint8
effects volume 0x1 uint8
music volume 0x2 uint8
enable EAX 0x3 bool
enable hardware acceleration 0x4 bool
sound quality 0x5 QualityOptions: enum(8-bit)
0x6 pad(1)
audio variety 0x7 QualityOptions: enum(8-bit)
0xB80 pad(524)
network settings 0xD8C NetworkSettings
Field Offset (relative) Type Comments
server name 0x0 UTF-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).

0x40 pad(224)
password 0x120 UTF-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)

0x132 pad(1)
max players 0x133 uint8

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.

0x134 pad(256)
connection type 0x234 ConnectionTypes: enum(8-bit)
Option Value Comments
56k 0x0
dsl-low 0x1
dsl-avg 0x2
dsl-high 0x3
t1/lan 0x4
0x235 pad(1)
server address 0x236 UTF-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 port 0x276 uint16

Defaults to the value 2302

client port 0x278 uint16

Defaults to the value 2303

0x1006 pad(258)
gamepad info 0x1108 GamepadInfo[4]
Field Offset (relative) Type Comments
gamepad name 0x0 UTF-16(512) LE/BE

Stores the name of the controller device seen when configuring button bindings (if configured). UTF-16 String; can be little-endian ("Xbox Controller S via XBCD") or big-endian ("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.

0x200 pad(12)

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

vendor ID 0x20C uint16

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 ID 0x20E uint16

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).

0x210 pad[6]

Zeroed-out values

pidvid 0x216 char[6]

An ASCII string with value "PIDVID"

dupe ID 0x21C uint8

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

0x21D pad(3)
0x1988 pad(1652)

Unknown region

crc32 hash 0x1FFC uint32

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)