Skip to content

Installation

Borys Stelmakh edited this page Sep 16, 2026 · 4 revisions

Installation

SacredSDK lets you mod Sacred Gold (Ascaron, 2004) in Lua without touching a single original game file. Mods live in custom/, and the game reads them through a thin DLL injected at startup.

Verified on Sacred Gold Steam, build 2.0.2.28 (2006-10-13).

Contents

How it hangs together

The SDK ships as a proxy ijl15.dll that the game loads automatically at launch (Sacred imports the Intel JPEG library ijl15.dll, so a DLL of that name next to Sacred.exe is loaded before the game's entry point runs). The proxy forwards every JPEG call to the renamed-original ijl15_real.dll, so the game behaves identically — the only new code is our DllMain, which boots the SDK.

Once running, the SDK does two things:

                                    +-- DLL load --+
Steam runs Sacred.exe -------------> |  ijl15.dll   |
                                    +------+-------+
                                           |
            +------------------------------+--------------------------+
            |                                                         |
            v                                                         v
   +------------------+                                +---------------------+
   |  Embedded Lua    | scans custom/lua/**/*.lua,     |  IAT hook on        |
   |  (5.4)           | executes each, writes the      |  CreateFileA        |
   |                  | result to custom/<rel>.bin     |                     |
   +------------------+                                |  Redirects any read |
                                                       |  of bin/<X> ->      |
                                                       |  custom/bin/<X>     |
                                                       |  (if it exists)     |
                                                       +---------------------+
                                                                  |
                                                                  v
                                                Sacred opens FunkCode.bin etc.
                                                and never knows it was modded.

Two halves:

  1. A bake (Lua -> .bin) that runs once at game startup. Each .lua mod is executed and its result written to a matching file under custom/bin/.
  2. A read-time override (fs_override) that swaps in your custom files when Sacred opens something. The vanilla bin/ tree is never modified.

See Reverse Engineering for the mechanism in detail.

Installing the proxy DLL

The proxy is ijl15.dll.

From a release archive: extract it into the game folder and run install.cmd — it renames the game's own ijl15.dll to ijl15_real.dll and puts the SDK proxy in its place. uninstall.cmd undoes exactly that.

From a source build, by hand, from the game install root (<Sacred Gold>/):

:: back up the original Intel JPEG library (do this ONCE)
copy ijl15.dll ijl15_real.dll

:: drop the SacredSDK proxy in
copy sdk\Release\ijl15.dll ijl15.dll

State afterwards:

File What it is
ijl15.dll the SacredSDK proxy
ijl15_real.dll the original Intel JPEG library (renamed)

That is the whole install. The SDK edits none of the game's data files, and custom/ and sdk/ are folders Steam does not track. ijl15.dll is a game file, though: Steam's "Verify integrity of game files" restores the original ijl15.dll, and the SDK stops loading. Run install.cmd again afterwards (it finds ijl15_real.dll already in place and only copies the proxy back).

The mod tree

There are two Lua trees and yours wins.

<Sacred Gold>/
|-- ijl15.dll                 <- SacredSDK proxy (don't edit)
|-- ijl15_real.dll            <- original; we forward to it
|-- bin/, scripts/, ...       <- vanilla; never touched
|-- sdk/                      <- THE FRAMEWORK (ships with the SDK)
|   |-- ijl15.dll             <- the proxy, before install.cmd copies it out
|   +-- custom/lua/
|       |-- lib/              <- the standard library: quests, NPCs, dialog, zones...
|       +-- examples/         <- copy-paste starters (01_hello.lua ... 15_storyline.lua)
+-- custom/                   <- YOURS
    |-- lua/
    |   |-- lib/              <- optional: a patched copy of any framework module
    |   |-- mods/             <- YOUR runtime mods (return {}; replace no game file)
    |   +-- bin/              <- YOUR script mods, mirroring the game's bin/
    |       +-- TYPE_NPC_*/   <- per-class scripts
    |           |-- QuestCode.lua
    |           +-- FunkCode.lua
    |-- mods/                 <- auto-generated by the bake; the game reads none of it
    |-- bin/                  <- auto-generated by the bake, served via fs_override
    +-- scripts/              <- auto-generated (e.g. scripts/us/global.res)

The priority rule, for both mods and library modules: a file under custom/lua/<path> beats the file at sdk/custom/lua/<path>. So you can replace any single framework module, or a mod the SDK ships, by putting your version at the same relative path — the SDK's copy is then skipped, not merged. require "npcobj" searches your lib/ first and the framework's second.

Baked output always lands in your custom/ tree; the sdk/ tree is only ever read. custom/bin/ and custom/scripts/ are generated — don't edit them.

A mod's location decides which game file it overrides. A file at custom/lua/bin/TYPE_NPC_GLADIATOR/QuestCode.lua bakes to custom/bin/TYPE_NPC_GLADIATOR/QuestCode.bin, which the fs_override hook then serves whenever Sacred opens bin/TYPE_NPC_GLADIATOR/QuestCode.bin.

That holds for every mod, whatever it returns. A runtime mod (NPCs, dialog buttons, zones: callbacks that run while the game does) returns {} and bakes to an empty file, so keep it in custom/lua/mods/, which mirrors no game file. At a path such as custom/lua/bin/TYPE_NPC_GLADIATOR/FunkCode.lua it would hand the game an empty FunkCode.bin for that class. The bake skips only the folders lib/, examples/ and those whose names start with _.

Verifying the install

  1. Launch Sacred (via Steam or directly).
  2. Look at sdk/logs/sdk_loaded.log. On a working install you will see a DllMain DLL_PROCESS_ATTACH banner with the exe path, then bake lines like [lua_bake] baked '...' -> '...'.
  3. The SacredSDK overlay (toggle F11 to interact) shows live bake stats: baked files, baked records, and the last status.

A quick override smoke test, from the game root:

copy scripts\us\global.res custom\scripts\us\global.res
:: launch Sacred, reach the main menu

The overlay's Custom/ overrides panel should then show redirected >= 1 with last pointing at scripts\us\global.res -> custom\scripts\us\global.res.

The overlay

The SDK draws its own window over the game.

Key Action
F12 Show or hide the overlay, the SDK's messages (sacred.notify) included.
F11 Switch the mouse and keyboard between the overlay and the game. The overlay has them when the game starts, so if the game ignores the mouse, press F11.
F7 Copy the hero's map position to the clipboard as X, Y and write it to the log ([overlay] F7 -> hero map pos). These are the coordinates o:teleport, zones and sacred.hero_pos() use.
F8 Write the quest book to the log.
F9 / F10 Clear the runtime trigger ring / write it to the log.

Rolling back

Delete the proxy and restore the original:

del ijl15.dll
ren ijl15_real.dll ijl15.dll       :: or: copy /y ijl15_real.dll ijl15.dll

Deleting an individual override file under custom/ restores that one vanilla file on the next launch; the SDK is fully reversible.

Next steps

Clone this wiki locally