FAQ
Everything extracted as @bytes(...) — why?
No schema. Pass --game-root pointing at the game install, and make sure it actually contains the
script packages (Core.u, Engine.u, the game's own .u files). Run
schema-resolve on a known class to check the index:
ue3-tools --game-root /path/to/game schema-resolve engine "Class Engine.Actor"
package 'x' not in --game-root
The import graph reached a package your root doesn't cover. Point --game-root higher up, or check
that DLC and patch directories are included. --verbose streams every miss as it happens.
Invalid file signature
Not a UE3 package, or it's encrypted/wrapped by the title. The tool requires the literal
0x9E2A83C1 tag at offset zero.
Corrupted pak
The header parsed but reported a non-positive name, export or import count. Usually a truncated
file or a wrong offset — try upk-header to see how far it got.
Decompression fails or panics
Only LZO is implemented. Zlib and LZX packages are recognised but can't be inflated. A panic inside decompression means the chunk data didn't match its declared size — the file is likely truncated.
Textures extract with no .dds
Three common causes:
- Unmapped pixel format. Only
PF_DXT1,PF_DXT3,PF_DXT5,PF_A8R8G8B8,PF_G8,PF_BC5,PF_FloatRGBAare handled; anything else warns and skips. - Mips live in a
.tfcthat isn't under--game-root, or whose payload is compressed — compressed TFC payloads aren't inflated. - No resolvable mips at all, which the warning states explicitly.
My replacement .dds is rejected
Its top mip has to match one of the original mips' dimensions. To change resolution, also update
SizeX and SizeY in the .uo to your DDS's top mip — that authorises replacing the whole mip
list.
Can I replace audio?
Not through the packer. SoundNodeWave extracts to .ogg / .wav but has no injector.
Can I edit a class, add a function, or change UnrealScript?
No. Class, struct, enum and const .uo files are read-only reference material — pack-mod skips
them. Bytecode is located and skipped during schema parsing, never decompiled or re-emitted.
type mismatch: original is Int but edit is string
By design. The packer won't coerce types, because a wrong guess produces a package the game will
mis-deserialize. Match the original's form — quotes for strings, bare digits for numbers, 'name'
for names, Enum::Value for enums, &Ref for object references.
struct has no field 'X' in the original export
That field held its default value, so the engine never serialized it. With --game-root the packer
creates it from the schema; without one, it can't know the field's type and fails.
could not resolve object reference '&Foo'
The label was ambiguous or matched nothing. Use a fuller dotted path (Outer.Foo), or extern: for
imports. If the target genuinely doesn't exist yet, the packer reserves a slot and records it in
.newexports instead of failing.
Does pack-mod produce a modified .upk?
No, and pack is unimplemented. The output is per-export .bin blobs plus a .namemap, intended
for a runtime loader such as CU3ML. Repacking a whole
package is out of scope.
Do I have to ship the .namemap?
Yes. Property tags reference names by index, and almost any edit can append entries. Ship the
.namemap from the same run as the .bin files.
Can the GUI extract?
No — it's a read-only inspector. It decodes headers, tables, schemas and hex, but extraction and packing are CLI-only.
Is it slow?
Yes, on large packages. Whole packages are held in memory, import resolution scans export tables
linearly, and resolving one import can pull in and decompress another package. Running
decompress once and working against the flattened file helps.
Will it work on my game?
Anything UE3-era with a package version inside the supported gate range should read. Console (byte-swapped) packages decompress, but cooked-for-console script layouts aren't wired up yet, so their meta-objects will mis-parse. Expect to add version constants for anything far from the Dishonored-era target.