Skip to content

Instantly share code, notes, and snippets.

@Darksecond
Last active May 23, 2017 08:00
Show Gist options
  • Save Darksecond/3706842f74ba04ceecebd5f10e89b0ec to your computer and use it in GitHub Desktop.
Save Darksecond/3706842f74ba04ceecebd5f10e89b0ec to your computer and use it in GitHub Desktop.
patch_v3.lvl

Halo 2 patch_v3.lvl signer/checker.

The chunk checksum is just a CRC32. It seems to be inverted though. Right now it does nothing except check the signatures of each chunk.

It is easy to add json serialization/unserialization later.

{
"name": "patchnode-19232",
"version": "1.0.0",
"description": "",
"main": "patch.js",
"dependencies": {
"crc-32": "^1.0.1"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Tim Peters",
"license": "ISC"
}
const CRC32 = require('crc-32');
const fs = require('fs');
const buffer = fs.readFileSync('./patch_v3.lvl.3');
const header = buffer.slice(0,8);
const maps = buffer.readUInt32LE(4);
console.log(maps);
for(let index = 0; index < maps; index++) {
let chunk = buffer.slice(8+185344*index,8+185344*(index+1));
let checksum = chunk.readUInt32LE(4);
chunk[4] = 0;
chunk[5] = 0;
chunk[6] = 0;
chunk[7] = 0;
// checksum seems to be inverted.
// So invert & treat as unsigned.
let crc = ~CRC32.buf(chunk) >>> 0;
console.log(checksum.toString(16), crc.toString(16));
}
meta:
id: patch_v3
file-extension: lvl
endian: le
instances:
header:
type: header
pos: 0
maps:
type: map
pos: 8
repeat: expr
repeat-expr: header.map_count
size: 185344
types:
max_teams:
seq:
- id: none
type: u1
- id: ctf
type: u1
- id: slayer
type: u1
- id: oddball
type: u1
- id: koth
type: u1
- id: race
type: u1
- id: headhunter
type: u1
- id: juggernaught
type: u1
- id: territories
type: u1
- id: assault
type: u1
- id: stub_10
type: u1
- id: stub_11
type: u1
- id: stub_12
type: u1
- id: stub_13
type: u1
- id: stub_14
type: u1
- id: stub_15
type: u1
header:
seq:
- id: version
type: u4
- id: map_count
type: u4
map:
seq:
- id: version
type: u4
- id: patch_checksum
type: u4
doc: >
Inverted CRC32 of the chunk, patch_checksum field should be zero.
A chunk is 185344 bytes long.
It does not include the 8 byte file header.
- id: unknown2
type: u4
doc: always seems to be '1'
- id: scenario
type: str
encoding: UTF-8
size: 256
- id: map_checksum
type: u4
- id: map_end
type: u4
doc: offering_id?
- id: unknown5
type: u4
doc: always seems to be '0xFFFFFFFF'
- id: name_en
type: str
encoding: UTF-16
size: 64
- id: name2
type: str
encoding: UTF-16
size: 64
- id: name_de
type: str
encoding: UTF-16
size: 64
- id: name_fr
type: str
encoding: UTF-16
size: 64
- id: name5
type: str
encoding: UTF-16
size: 64
- id: name6
type: str
encoding: UTF-16
size: 64
- id: name_ch
type: str
encoding: UTF-16
size: 64
- id: name8
type: str
encoding: UTF-16
size: 64
- id: name9
type: str
encoding: UTF-16
size: 64
- id: description_en
type: str
encoding: UTF-16
size: 256
- id: description2
type: str
encoding: UTF-16
size: 256
- id: description_de
type: str
encoding: UTF-16
size: 256
- id: description_fr
type: str
encoding: UTF-16
size: 256
- id: description5
type: str
encoding: UTF-16
size: 256
- id: description6
type: str
encoding: UTF-16
size: 256
- id: description_ch
type: str
encoding: UTF-16
size: 256
- id: description8
type: str
encoding: UTF-16
size: 256
- id: description9
type: str
encoding: UTF-16
size: 256
- id: map_start
type: u4
- id: unknown6
type: u4
doc: >
always seems be '0'.
Possibly flags or sort order?
- id: max_teams
type: max_teams
- id: raw_dxt1
size: 0x2C790
doc: >
This is DDS file with DXT1.
Width is 220.
Height is 207.
Size is 0x2C790.
This is the raw dxt1 bitmap, it just needs a header.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment