diff --git a/internal/erf/erf.go b/internal/erf/erf.go index a160d8d..5e207fc 100644 --- a/internal/erf/erf.go +++ b/internal/erf/erf.go @@ -68,9 +68,18 @@ type resourceEntry struct { } // extensionTypes and typeExtensions must stay exact inverses of each other; -// init() panics if they drift apart. Numbers below 0x0BB8 follow upstream -// neverwinter.nim (neverwinter/restype.nim). The 0x0BB8 and up entries are -// local additions for source formats upstream does not register. +// init() panics if they drift apart. +// +// Numbers below 0x0BB8 follow upstream neverwinter.nim +// (neverwinter/restype.nim). The 0x0BB8 and up entries are lyt/vis/mdx: real +// Aurora archive types that NWN1 ships in its own data/*.bif but upstream +// happens not to register. xoreos corroborates those three numbers +// (src/aurora/types.h). +// +// This table is NWN:EE only. Do not add NWN2 formats (mdb, gr2, wlk, xml): +// NWN:EE either gives that number to something else (2070 is xbc here and mdb +// in NWN2) or has no number for it at all, so packing one into a HAK writes a +// resource the game misreads. See the reserved list in erf_test.go. var extensionTypes = map[string]uint16{ "res": 0x0000, "bmp": 0x0001, @@ -131,9 +140,6 @@ var extensionTypes = map[string]uint16{ "lyt": 0x0BB8, "vis": 0x0BB9, "mdx": 0x0BC0, - "wlk": 0x0BCC, - "xml": 0x0BCD, - "gr2": 0x0FA3, } var typeExtensions = map[uint16]string{ @@ -196,9 +202,6 @@ var typeExtensions = map[uint16]string{ 0x0BB8: "lyt", 0x0BB9: "vis", 0x0BC0: "mdx", - 0x0BCC: "wlk", - 0x0BCD: "xml", - 0x0FA3: "gr2", } func init() { diff --git a/internal/erf/erf_test.go b/internal/erf/erf_test.go index 216d641..3634495 100644 --- a/internal/erf/erf_test.go +++ b/internal/erf/erf_test.go @@ -138,9 +138,6 @@ func TestExtensionMappingsSupportModernAssetTypes(t *testing.T) { "lyt": 0x0BB8, "vis": 0x0BB9, "mdx": 0x0BC0, - "xml": 0x0BCD, - "wlk": 0x0BCC, - "gr2": 0x0FA3, } for ext, wantType := range cases { gotType, ok := ResourceTypeForExtension(ext) @@ -227,6 +224,19 @@ func TestRestypeTableMatchesUpstream(t *testing.T) { } } +// TestNWN2FormatsAreNotRegistered keeps NWN2 file formats out of an NWN:EE +// table. mdb and gr2 have Aurora numbers that mean something else (or nothing) +// in NWN:EE; wlk and xml have no archive number in any Aurora game, so the +// values Crucible used for them were invented. Packing any of these into a HAK +// writes a resource the game misreads. +func TestNWN2FormatsAreNotRegistered(t *testing.T) { + for _, ext := range []string{"mdb", "gr2", "wlk", "xml"} { + if number, ok := ResourceTypeForExtension(ext); ok { + t.Errorf("%s is an NWN2 format but is registered as 0x%04X", ext, number) + } + } +} + // TestRestypeTablesAreMutualInverses is the check init() is meant to enforce. func TestRestypeTablesAreMutualInverses(t *testing.T) { for ext, number := range extensionTypes { diff --git a/internal/project/project.go b/internal/project/project.go index 9334a2f..03954ed 100644 --- a/internal/project/project.go +++ b/internal/project/project.go @@ -31,7 +31,7 @@ var SourceExtensions = []string{ } var AssetExtensions = []string{ - ".2da", ".bik", ".bmp", ".bmu", ".dds", ".dwk", ".gr2", ".itp", ".jpg", ".lod", ".lyt", ".mdl", ".mdx", ".mtr", ".plt", ".png", ".pwk", ".set", ".shd", ".tga", ".txi", ".uti", ".vis", ".wav", ".wlk", ".wok", ".xml", + ".2da", ".bik", ".bmp", ".bmu", ".dds", ".dwk", ".itp", ".jpg", ".lod", ".lyt", ".mdl", ".mdx", ".mtr", ".plt", ".png", ".pwk", ".set", ".shd", ".tga", ".txi", ".uti", ".vis", ".wav", ".wok", } var BuiltinScriptPrefixes = []string{