Sphinx and the Cursed Mummy Wiki
Advertisement

EngineX DataBase (*.edb) files are the binary, general-purpose workhorse container format used in Eurocom's EngineX titles. They are created by exporting an .ELF from the EuroLand editor. Every file has an unique hashcode that needs to be referenced in the Filelist descriptor for the game to find the path and load it.

Characters are usually self-contained into a single file, while levels are prefixed by area and are generally split into the main file, an IO_*.edb file for trigger objects and sometimes a CS_*.edb for cutscenes. In the original Eurocom release all these assets were bundled into uncompressed Filelist archives.

Contents[]

A non-exhaustive list of things you can find inside:

  • BSP maps
    • Submaps
      • Trigger instances
        • Gamescript events
      • AI navigation paths
  • Entities (3D models, often with several LOD meshes)
  • Entity trees (when the model is a composite or too big/complicated)
    • 3D geometry (in nested entities)
  • Textures (Generally S3TC-compressed)
    • Texture regions (mainly for button prompts stored into a single UV atlas)
    • Material properties (like sound or texture flags)
  • Animations (skinned animations with morph targets and complex blending rules)
    • Animation skins
    • Animation datums
    • Animation modes
    • Animation sets
  • Scripts (event-driven timelines that contain animations/particle effects/actors/camera movements, like cutscenes)
    • HUD and GUI elements (internally called HudScripts, the title screen and pause menus are built using script events, while the memory card and the inventory screens, as well as the in-game HUD are hardcoded in behavior to use certain entity/mesh elements by hashcode)
  • Particle effects (it supports textured billboard rectangles or custom 3D meshes)
  • Swooshes (camera-facing speed trail effects used for demonic red eyes or sword hits)
  • Spreadsheets (loaded from a referenced Excel spreadsheet on export)
    • Text spreadsheets (different sections per language)
      • Localized text strings
    • Data spreadsheets (where the data structure is fixed but the data itself is configurable)
      • Level data descriptors
      • Inventory items
        • Ability Items
        • Quest Items
        • Weapon Items
      • Shop prices
      • Context actions
      • Monster tweaks (stats and monster abilities)
      • Surface types
      • ...
  • Bitmap fonts (Internally bound to a texture; this look-up table stores Unicode codepoints and its UV rects and glyph metrics)


Debug output files[]

Euroland is full of surprises, and it has a hidden debug mode that dumps a text version of the exported target file and their fields, and can be used to interpret the different sections and blocks visually[1].

  • Euroland-secret-debug-export-functions

    The secret menu that appears when you hold the Shift key while pressing Output.

    You get secret menus by pressing different key combinations. In this case Shift while exporting an .EDB file.
  • Euroland-secret-dbg-text-format-for-edb-files

    Example output of some exported _ab_sewr.dbg file for a PC _ab_sewr.edb.

    Pressing Ctrl while using the Output function dumps the target .EDB into a readable text version with a .DBG extension. I have been searching for this functionality for a while, it was there all along.[2]


This was originally added to debug the exporter itself, but it can be used to analyze the very complex binary format in a more straightforward way. Here is a rough overview of what the different keys mean, they seem to mirror the MSVC assembler directives for the most part (e.g. see here):

(Writing Raw Data)

DB -> BYTE (note: these are raw data because the value is written directly from the exporter)
DW -> WORD: one or more
DD -> DWORD: one or more
DF -> write floats, one or more in the same line, a float is a number with decimals stored in a special way and takes 32 bits / 4 bytes
DS -> deferred string (note: strings have variable size)
DS.nn -> deferred string (with nn being the length)



(Writing deferred data)

DB -> deferred BYTE (note: these are deferred (i.e. delayed) because the final value is computed right after writing from some instructed computation)
DW -> deferred WORD
DD -> deferred DWORD (appears formatted with >> (shifts), hex or decimal values or + XX hex or decimal data)
DD -> deferred float (appears formatted with +X.Xxx, probably should be DF)

ALIGN.W -> WORD padding, 2 bytes of 16 bits (note: block alignment, pads to the next WORD)
ALIGN.DW -> DWORD alignment, 4 bytes or 32 bits
ALIGN.QUADWORD -> QWORD; 8 bytes or 64 bits
ALIGN.BYTES nn -> pad to nn BYTEs
ALIGN.CDSECTOR -> pad to a CD sector (0x800 / 2048 bytes by default)



(Sub blocks within the main file)

INSERT.BLK -> (Sub) Block within the main file



(Text File Comments)

////////////////////////////////////////////////////////////////////// -> separator
xxxxxxxxxxxxxxxxxxxxxxxxxxxxx -> other custom separators with user-specified characters
// Comment Blah Blah Bleh -> formatted comment line



(Offset Management)

OFFSET.B -> BYTE offset (note: these are relative offsets, i believe. all offsets have a tag and are only resolved at the end once the number and size of sections is available)
OFFSET.W -> WORD offset
OFFSET.DW -> DWORD offset

OFFSET.AB -> absolute BYTE offset
OFFSET.AW -> absolute WORD offset
OFFSET.ADW -> absolute DWORD offset (with * for unit multipliers, << shifts, | data and + for added values)


(Glossary)
TF -> Target file (for errors)

File format data structures[]

While—thanks to the Euroland debug functionality described above—one can get a decent idea of what the different exported blocks in a sample file are, and how they are internally structured, EngineX DB files still have a very complicated format—very similar to a dynamic library—that warrants some documentation about what the different fields mean and why they exist.

EDB files are divided in different loadable sections, and data may only be partially resident in memory. A good way to understand this is the Text.edb file, where all the in-game translations are stored; the game will only need one language at a time, so it should not pay the price of keeping all the other translations in memory when only Spanish is being accessed. What's more, we don't even need the Spanish text for anything other than the strings used for the current map and any common ones, so in Euroland one spreadsheet is split in hundred of piecemeal sections and only a minuscule fraction of the EDB data is kept at a time. The same strategy can be used for parts of levels; _hl_ext.edb holds most of the Heliopolis exterior map data, but while Sphinx walks around only a small section of the EDB is retrieved from the DVD; the section that holds the current submap, plus any neighboring submaps that connect to it, EngineX will stream the sections/submaps in and out when needed.

While a submap is being loaded (usually while jumping or teleporting to a map part that was far away—not directly connected—from the one Sphinx was in) you will see the game fade to black and show the spinny Ankh symbol in the bottom right. To give it enough time to read the EDB sections it needs for the game to continue.

A full level load will instead display the loading screen with the progress bar, with most of the previously used EDB files getting unloaded to free up memory, compacting any memory holes to avoid fragmentation, and then having all the new partial EDB files for characters, effects, maps and triggers overwriting that space. Once that is done, the loading screen will fade out and gameplay will start from the requested map entry point.

GeoFile header
Offset Size Description
0h 4 Contains a four-byte string with the magic value GEOM; 47 45 4F 4D in hexadecimal. When the file has been exported for little-endian platforms (like PC, PS2 and Xbox) the magic value appears reversed/from right-to-left (MOEG; 4D 4F 45 47 in hex). GameCube is the only big-endian platform, so it's the only one where it appears from left-to-right. This can be used to auto-detect and distinguish between them.
4h 4 Hashcode for the current file. Should match the one in the Filelist.
8h 4 GeoFile version to ensure that the game can read it. 182 in the final Sphinx release. Should match the one in the Filelist.
Ch 4 Flags enumerating platform, content-type and Euroland-provided information at output time. Should match the same field in the Filelist, see the accompanying page for a detailed rundown and how to detect the actual EDB platform/console from this data alone.
10h 4 32-bit UNIX-style timestamp describing the moment the ELF was last modified, usually close to the time this EDB was exported from the corresponding ELF in Euroland using the Output functionality. This will eventually suffer from the Year 2038 problem.
14h 4 The total file size, in bytes. With all the sections loaded, except the optional, trailing debug section.
18h 4 The partial file size, as reported in the Filelist. Usually the bare minimum memory this EDB file will take, when only the first section is loaded.
1Ch 24 Six platform-specific versions, they are all set to zero on PC.
34h 4 Offset to the start of the debug information section, in bytes from the file start. Usually matches the number in the total size field.
38h 4 Offset to the end of the debug information section, in bytes from the file start. Usually pointing to what would come after the last byte from the unstripped EDB. Substract it from the debug section start field to get its size.

Note: If the debug section has been stripped out, as it commonly happens in final builds (by XUtil?), the file will end at the point described by total size field.

3Ch 4 Always zero, used by the game at runtime.
40h 4
44h 4
48h 4
4Ch 4
50h 4
Array of list offsets
54h 120 After the header, each EDB file has fifteen descriptors, telling the game where each of those data arrays begin.

The 15 lists enumerate the following data types, in order: Section, Reference pointer, Entity, Animation, Animation skin, Script, Map, Animation modes, Animation sets, Particles, Swooshes, Spreadsheets, Fonts and Textures.

Each of those with the following format:

Array entry with hashcode
0h 4 Element count.
4h 4 Hashcode count.
8h 4 Relative address to the first element, from the start of this field.

And after those, there is another special entry for Texture updates, that uses the following one instead:

Array entry
0h 4 Element count.
4h 4 Relative address to the first element, from the start of this field.
Advertisement