Main interface for PCK file operations.
public interface IPckFile : IDisposable
{
int SoundBankCount { get; }
int StreamingFileCount { get; }
byte[]? FindWem(uint sourceId);
bool ContainsWem(uint sourceId);
void AddSoundBank(ISoundBank soundBank);
bool RemoveSoundBank(uint bankId);
void AddStreamingFile(uint sourceId, byte[] data);
bool RemoveStreamingFile(uint sourceId);
WemReplacementResult ReplaceWem(uint sourceId, byte[] data, bool updateHircSizes = true);
void Save(string path);
void Save(Stream stream);
}Factory for creating and loading PCK files.
public interface IPckFileFactory
{
IPckFile Create();
IPckFile Load(string path);
IPckFile Load(Stream stream);
}Interface for Wwise soundbank operations.
public interface ISoundBank
{
uint Id { get; }
uint Version { get; }
uint LanguageId { get; }
int MediaCount { get; }
int HircItemCount { get; }
bool ContainsMedia(uint sourceId);
int ReplaceWem(uint sourceId, byte[] data, bool updateHircSizes = true);
byte[] ToByteArray();
}Fluent builder for creating soundbanks from scratch.
public interface ISoundBankBuilder
{
ISoundBankBuilder WithId(uint bankId);
ISoundBankBuilder WithVersion(uint version);
ISoundBankBuilder WithLanguage(uint languageId);
ISoundBankBuilder AddMedia(uint sourceId, byte[] data);
ISoundBankBuilder AddHircItem(IHircItem hircItem);
ISoundBank Build();
ISoundBankBuilder Reset();
}using PckTool.Services;
// Load PCK file
var pck = ServiceProvider.PckFileFactory.Load("sounds.pck");
Console.WriteLine($"Sound banks: {pck.SoundBankCount}");
Console.WriteLine($"Streaming files: {pck.StreamingFileCount}");
// Find a WEM file
var wemData = pck.FindWem(970927665);
if (wemData != null)
File.WriteAllBytes("extracted.wem", wemData);
pck.Dispose();using PckTool.Services;
var pck = ServiceProvider.PckFileFactory.Load("sounds.pck");
// Load replacement audio
var newWem = File.ReadAllBytes("replacement.wem");
// Replace WEM file (updates HIRC sizes automatically)
var result = pck.ReplaceWem(970927665, newWem);
Console.WriteLine($"Streaming: {result.ReplacedInStreaming}");
Console.WriteLine($"Banks modified: {result.EmbeddedBanksModified}");
Console.WriteLine($"HIRC refs updated: {result.HircReferencesUpdated}");
// Save changes
if (result.WasReplaced)
{
pck.Save("sounds_modified.pck");
}
pck.Dispose();using PckTool.Services;
// Create a new soundbank using the builder
var soundBank = ServiceProvider.CreateSoundBankBuilder()
.WithId(0xDEADBEEF)
.WithVersion(0x71) // Wwise version
.WithLanguage(0) // SFX (non-localized)
.AddMedia(12345, File.ReadAllBytes("sound1.wem"))
.AddMedia(67890, File.ReadAllBytes("sound2.wem"))
.Build();
// Create a new PCK and add the soundbank
var pck = ServiceProvider.PckFileFactory.Create();
pck.AddSoundBank(soundBank);
pck.AddStreamingFile(11111, File.ReadAllBytes("music.wem"));
pck.Save("custom.pck");
pck.Dispose();var result = pck.ReplaceWem(sourceId, newData);
if (result.WasReplaced)
{
Console.WriteLine($"Replaced in {result.EmbeddedBanksModified} bank(s)");
Console.WriteLine(result.Summary);
}
else
{
Console.WriteLine("WEM not found in package");
}See PckTool --help for full command documentation.
# Extract all audio (using --game for auto-detection via Steam/registry)
PckTool dump --game hwde --output dumps/
# Extract all audio (using --game-dir to override auto-detected path)
PckTool dump --game hwde --game-dir "C:\Games\HaloWars" --output dumps/
# Replace a WEM file
PckTool replace-wem --game hwde --target 970927665 --source replacement.wem --output ./
# Replace multiple WEMs in one command
PckTool replace-wem --game hwde --target 0x39E3B0F1 --source sound1.wem --target 0x12345678 --source sound2.wem --output ./
# Replace multiple sound banks in one command
PckTool replace --game hwde --target 0x1A2B3C4D --source bank1.bnk --target 0x5E6F7A8B --source bank2.bnk --output ./
# List sound banks
PckTool list --game hwde --verbose
# Interactive browser
PckTool browse --game hwde --language "English(US)"
# Find a WEM ID or cue name
PckTool find --game hwde --wem 970927665
PckTool find --game hwde --name "explosion"Batch projects allow you to define multiple audio replacement operations in a JSON file for reproducible mod builds.
Batch project files are standard JSON files:
{
"$schema": "./batch-project-schema.json",
"schemaVersion": 1,
"name": "My Audio Mod",
"description": "Custom audio replacements",
"game": "hwde",
"inputFiles": ["Sounds.pck"],
"outputDirectory": "./output",
"actions": [
{
"action": "replace",
"targetType": "wem",
"targetId": 970927665,
"sourcePath": "./audio/custom.wem",
"description": "Replace explosion sound"
}
]
}# Create a new batch project
PckTool batch create mymod.json --name "My Mod" --game hwde
# Add actions to the project
PckTool batch add-action mymod.json --target 0x39E3B0F1 --source custom.wem
# View project information
PckTool batch info mymod.json
# Validate the project
PckTool batch validate mymod.json
# Execute the project (dry run first)
PckTool batch run mymod.json --dry-run
# Execute for real
PckTool batch run mymod.json
# Generate JSON schema for IDE autocomplete
PckTool batch schema batch-project-schema.json