Comparison with Shadow of Mordor

How Shadow of Mordor (2014) differs from Shadow of War at the file and engine level: the executable, the archive format and its compression, container and asset format versions, the GameDB, the orc skeletons, materials and textures, the Army screen's arena, and the Mordor-to-War nemesis importer that ships inside Shadow of War.

Shadow of Mordor (2014) is the predecessor engine generation. Its internal project name is Firebird; Shadow of War's is Kraken. The two games share their archive family, container idea, GameDB format and much of their orc rig, but nearly every asset format moved on by several versions, so no Mordor asset loads in War unchanged.

The executables

Shadow of Mordor Shadow of War
x64 executable ShadowOfMordor.exe, 27,930,624 bytes ShadowOfWar.exe, 117,732,784 bytes
Load address 0x140000000 preferred, relocatable (DYNAMIC_BASE, relocation table present) always 0x140000000 (relocations stripped)
Code a conventional .text section of about 20.6 MB .arch (about 30 MB) plus 70 MB of code in .bss a (see The executable)

Because Mordor's executable is relocatable, its addresses move with ASLR every run; War's static addresses never move.

Archives

Both games use LTAR archives. Mordor's are version 3 (.arch05), War's version 4 (.arch06, see Archives and file formats). The Mordor install has 66 archives, 45.4 GB.

header (0x18 bytes)  "LTAR" | u32 version (3) | u32 names size | u32 folder count | u32 file count | u32 1
names                null-separated strings from 0x18; the last string may run past the declared size,
                     and a small block precedes the entry table
entry (0x20 bytes)   u64 data offset | u64 compressed size | u64 uncompressed size | u32 flag (9) | u32 name offset

The entry table is found by its signature (the flag 9 at +0x18 of consecutive entries). Parsing all 66 archives gives 28,884 entries, equal to the 28,884 declared in the headers; every entry's data lies inside its file and the data offsets ascend in all 28,828 consecutive pairs. A name offset may point into the middle of a string, and an entry's name does not reliably describe its payload, so asset paths are taken from the containers' own path tables, as in War.

Compression. Mordor stores each entry as a stream of chunks {u32 compressed length, u32 uncompressed length (at most 65,536), data} compressed with zlib; chunks whose two lengths are equal are stored uncompressed (of 192 sampled chunk headers, 166 began with the zlib marker and 26 were stored). Chunks are padded, so the next chunk header can sit a few bytes after the previous chunk's data. War compresses with Oodle.

Containers and asset formats

Mordor's containers are BNDL version 4 (War: version 6); 8,034 of them hold 67,982 asset paths (66,731 distinct). Mordor's world prefabs are PRFB version 5 and its Scaleform movies GFX version 8 (ActionScript 2). Asset formats are older versions that War's loaders reject:

Format Shadow of Mordor Shadow of War
mesh (MMSH) 9 16-17
skeleton (SKEL) 8 (War's loader rejects it)
texture (TEXR) 3 8
material instance (LTMI) 4 7-8

Mordor's version-9 mesh vertex is 60 bytes: half-precision position (4 halves), 16-bit texture coordinates, 32-bit normal, tangent and bitangent, a colour, blend weights in BGRA order and bone indices; strides can differ between a mesh's elements. Every Mordor mesh has one UV set, while War's orc gear shaders read a second one. Mordor's texture coordinates can run to 2.0. Textures use the same DDS-based payload, and War's texture header adds a 23-byte block.

Materials are authored differently: Mordor's orcs use about 21 generic shaders, War's use the dedicated nemesis gear, head and body shader trees (see Rendering). For the one weapon compared directly (the Master Pike), Mordor's albedo was about half as bright as War's equivalent (mean 56 / 45 / 39 against 108 / 93 / 82).

The GameDB

Mordor's GameDB is a GADB version 17 file (the same container version as War's; see GameDB) of 23,264,671 bytes inside hotchunk.arch05's globaldatabase bundle: the entry after the named manifest entry, a BNDL v4 wrapping the database. It holds 115 character models named Cha_*. The Black Númenórean characters are three unique models: Cha_Belroth (the Hammer), Cha_Imrakhad (the Tower) and Cha_Zainzadan (the Black Hand, whose mesh one of Talion's alternative skins in Mordor is built from). Mordor ships no generic Black Númenórean soldier armour: a census of every container path (66,731 distinct), every self-named texture (12,714, none unreferenced) and every XML manifest (8,071) finds none.

The warband downloads (layer52 to layer56 archives) are 216-byte unlock stubs: the Guardian, Blood Hunter, Crusher and Flesh Burner orcs are GameDB presets assembling base-game pieces with paint, not new assets.

Orc skeletons

Shadow of Mordor Shadow of War
orc body rig 112 bones (the berserker 116) orc_base, 100 bones
shared bone names 72 72
face rig 33 joints 124 joints

The 72 shared bones sit at the same bind positions (median difference 0.07 cm, at most 0.94 cm for the core bones), but 36 of them differ in bind rotation (the forearm twist by 81 degrees). The face rigs share no joint names. Of Mordor's orc pieces, those that use only bones orc_base also has: armour 35 of 40, flair 116 of 131, bodies 15 of 15, heads 44 of 111.

The Army screen

Mordor's hierarchy screen is a world of its own, worlds\cinematics\wraith_visions\hierarchymenu_son.bndl (son.arch05 entry 15, 232,667,989 bytes, 446 assets; near-identical copies in intro.arch05 and outro.arch05): a scene, an object database, a world mesh and 10 prefabs (the hierarchy art, the Warchief pedestals, glyphs, orc light posts, a ruin wall, backdrop rocks), with the crowd drawn as card meshes (fx\ui\hierarchy\models\orcarmy_outlinecards.mesh). The seats are logical rows and columns in _StructuresFaction.HierarchyFactionPos (5 Warchiefs and captain rows of 8, 7 and 5: 25 seats), placed in the world as objects Hier.Faction_<row>_<column> with a character spot .Chr, a camera .Cam and about 20 points of interest each. The screen's movie is interface\flash\widgets\hierarchy.gfx, which holds no logic.

The Mordor importer in Shadow of War

Shadow of War ships an importer that rebuilds a player's Shadow of Mordor nemesis as a War captain or follower, compiled from ...\KRAKEN_CODE_STREAM\source\Game\Shared\NemesisForgeUtils.cpp (log tag [NEMESISFORGE]:; the logger is compiled out of the shipping build).

The check. The loading-progress tick 0x1E3E78 ([GM+0x6D30]) calls 0x1B3ABFC. It returns without checking when either of two state bytes of its object (+0x38, +0x80) is set, or when the predicate Invasion/Settings.HaltNemesisForgeCheckPredicate (the settings record at +0x468) evaluates true. Otherwise it tail-jumps to 0x1B3AA94, which builds an online request carrying the player's FirebirdProfileID and platform and registers 0x1B32CD0 as its completion handler. The data therefore comes from the publisher's online service, not from Mordor's local save.

The conversion. When an army's pool is filled (0xFD51A0, the Faction/Definition.Pool consumer) an imported nemesis goes through 0x1BC05D0, which logs its name and faction and calls 0x1C6369C. That maps each Mordor value to a War record through the conversion tables: combat tree, personality, role, the minimum level (MinXPLevel), whether it becomes the player's follower, its scar type, its traits and its trait markers. 0x1BC05D0 then builds the captain with the ordinary FactionMember builder 0x1BBF928 (see The Nemesis system). The builder's model step 0x1C04F20 converts the look: the base model (NemesisForge/FirebirdSimpleModel.Base), body and body type, armour, head (FirebirdSimpleModelHead.KrakenHead), helmet, hair (CanApplyHair), legs and accessories, then nine colour channels (skin, eyes, clothing, tattoo, paint, hair, two armour colours and leg leather). Each colour goes through 0x1C7664C: the Mordor colour id is looked up in a War colour setup's entries by their FirebirdColorId, with the entry's HueDeltaRange and NumRandomCalls applied. The record's CreationSimEventPicker chooses the sim event that introduces the captain, and quest jobs can ask for the imported captain through Quest/Jobs/Definition.UseNemesisForgeNemesis and UseNemesisForgeAlly.

The tables in the shipped GameDB:

Category Records Examples
NemesisForge/FirebirdSimpleModel 5 the Mordor orc classes AI_Spearman, AI_Infantry, AI_Berserker, AI_Defender, AI_Archer
NemesisForge/FirebirdFactionRole 131 Role_LimpLeg, Role_GrogBurner, Role_NeckSnapper, Role_Massive_DLC2
NemesisForge/FirebirdFactionTrait 83 Ground_Pound, Flaming_Weapon_Spearman, Monster_Slayer, Quirk_Aggressive
NemesisForge/FirebirdFactionPersonality 12 Clever_Sniveling, Psychotic, Commanding_1
NemesisForge/FirebirdModelScarType 6 Wraith, Burn, Pin_Cusion, Sack_Head, Eyepatch, Melee
NemesisForge/FirebirdSimpleModelHead 30 OrcStk03 ...
NemesisForge/FirebirdSimpleModelPiece 76 Smp_Orc_Buff_Hair01_Head03_01 ...
NemesisForge/FirebirdSimpleModelColorId 15 Red, White, Fleshtone, Grey, Black, Blue
NemesisForge/FirebirdSimpleModelColorSetup 11 Orc_Infantry_Skin_Color, Orc_Hair_Color, Armor_Color_01_Grey

The executable also names the console commands NemesisForge.CreateNemesis, NemesisForge.CreateFollower and NemesisForge.Override.ClearAll, the events Events_NemesisForgeImportEnabled and Events_NemesisForgeImportSampled, and a user property User.OwnsShadowOfMordor.

Open questions

Shadow of War (Steam), game version 1.21. An unofficial fan research project, not affiliated with or endorsed by Warner Bros. Games, Monolith Productions or Middle-earth Enterprises. Middle-earth: Shadow of War belongs to its owners.