Rename project to sacredK
sacred_re.dll/.exe/.ini/.log/_crash files are now sacredK.*; inventory saves with the old "sacred_re.inventory" format id still load. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
462ebf8c0b
commit
70673dc301
34 files changed
+95
-93
No files matched your search
+1
-1
@@ -3,6 +3,6 @@
|
|||||||
/.idea/
|
/.idea/
|
||||||
/cmake-build-*/
|
/cmake-build-*/
|
||||||
*.rea-snapshot
|
*.rea-snapshot
|
||||||
sacred_re.ini
|
sacredK.ini
|
||||||
/ghidra/
|
/ghidra/
|
||||||
/screenshots/
|
/screenshots/
|
||||||
Vendored
+3
-3
@@ -3,10 +3,10 @@
|
|||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
// Builds, then starts the game through the launcher (no debugger in the game).
|
// Builds, then starts the game through the launcher (no debugger in the game).
|
||||||
"name": "Run Sacred (sacred_re)",
|
"name": "Run Sacred (sacredK)",
|
||||||
"type": "cppvsdbg",
|
"type": "cppvsdbg",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceFolder}/build/x86-debug/sacred_re.exe",
|
"program": "${workspaceFolder}/build/x86-debug/sacredK.exe",
|
||||||
"args": ["--game-dir", "D:\\Gaming\\Sacred Gold", "log"],
|
"args": ["--game-dir", "D:\\Gaming\\Sacred Gold", "log"],
|
||||||
"cwd": "${workspaceFolder}/build/x86-debug",
|
"cwd": "${workspaceFolder}/build/x86-debug",
|
||||||
"preLaunchTask": "CMake: build",
|
"preLaunchTask": "CMake: build",
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Debug our DLL inside the game: set [debug] WaitForDebugger=1 in
|
// Debug our DLL inside the game: set [debug] WaitForDebugger=1 in
|
||||||
// build/<preset>/sacred_re.ini, start "Run Sacred", then run this and
|
// build/<preset>/sacredK.ini, start "Run Sacred", then run this and
|
||||||
// pick sacred.exe. The DLL waits (up to 60 s) before installing hooks.
|
// pick sacred.exe. The DLL waits (up to 60 s) before installing hooks.
|
||||||
"name": "Attach to sacred.exe",
|
"name": "Attach to sacred.exe",
|
||||||
"type": "cppvsdbg",
|
"type": "cppvsdbg",
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ project, autotest) first; this file adds how we work and what we learned.
|
|||||||
|
|
||||||
## What this is
|
## What this is
|
||||||
|
|
||||||
`sacred_re.dll` is injected into the original **Sacred Gold 2.28**
|
`sacredK.dll` is injected into the original **Sacred Gold 2.28**
|
||||||
`sacred.exe` (2006, 32-bit, MSVC 6) by the launcher `sacred_re.exe`. It
|
`sacred.exe` (2006, 32-bit, MSVC 6) by the launcher `sacredK.exe`. It
|
||||||
hooks and patches the running game: some functions are rewritten, most of
|
hooks and patches the running game: some functions are rewritten, most of
|
||||||
the work so far is **mods** — behaviour changes on top of the original
|
the work so far is **mods** — behaviour changes on top of the original
|
||||||
(widescreen, HUD layout, 7 weapon sets / art slots, key bindings, WASD,
|
(widescreen, HUD layout, 7 weapon sets / art slots, key bindings, WASD,
|
||||||
@@ -15,7 +15,7 @@ auto-attack, skill reworks, respec, map fixes, ...). The game stays playable
|
|||||||
at every step; the user plays it to test.
|
at every step; the user plays it to test.
|
||||||
|
|
||||||
- Target binary: the original `sacred.exe` in `D:\Gaming\Sacred Gold\`
|
- Target binary: the original `sacred.exe` in `D:\Gaming\Sacred Gold\`
|
||||||
(path in `build\x86-debug\sacred_re.ini`, `[paths] GameDir`). Ignore the
|
(path in `build\x86-debug\sacredK.ini`, `[paths] GameDir`). Ignore the
|
||||||
`SacredReborn*` files in that folder.
|
`SacredReborn*` files in that folder.
|
||||||
- Game texts are German (Fertigkeiten, Attribute, Blitzschlag, ...); keep the
|
- Game texts are German (Fertigkeiten, Attribute, Blitzschlag, ...); keep the
|
||||||
game's names when talking about features.
|
game's names when talking about features.
|
||||||
@@ -65,12 +65,12 @@ at every step; the user plays it to test.
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
.\build.ps1 # x86-debug -> build\x86-debug\
|
.\build.ps1 # x86-debug -> build\x86-debug\
|
||||||
build\x86-debug\sacred_re.exe log # start the game with the DLL
|
build\x86-debug\sacredK.exe log # start the game with the DLL
|
||||||
```
|
```
|
||||||
|
|
||||||
New source files must be added to `CMakeLists.txt`. Output to check:
|
New source files must be added to `CMakeLists.txt`. Output to check:
|
||||||
`build\x86-debug\sacred_re.log` (written anew each start; our lines plus the
|
`build\x86-debug\sacredK.log` (written anew each start; our lines plus the
|
||||||
game's own log). Crashes: `sacred_re_crash.txt` / `.dmp` next to the DLL
|
game's own log). Crashes: `sacredK_crash.txt` / `.dmp` next to the DLL
|
||||||
(exception, module+offset, ebp chain); Windows also records the faulting
|
(exception, module+offset, ebp chain); Windows also records the faulting
|
||||||
offset in the Application event log (`Get-WinEvent`, provider "Application
|
offset in the Application event log (`Get-WinEvent`, provider "Application
|
||||||
Error"). The debug build's run-time checks turn calling-convention mistakes
|
Error"). The debug build's run-time checks turn calling-convention mistakes
|
||||||
|
|||||||
+16
-16
@@ -1,12 +1,12 @@
|
|||||||
cmake_minimum_required(VERSION 3.24)
|
cmake_minimum_required(VERSION 3.24)
|
||||||
project(sacred_re LANGUAGES C CXX)
|
project(sacredK LANGUAGES C CXX)
|
||||||
|
|
||||||
# sacred.exe is a 32-bit process; everything we inject into it must be 32-bit too.
|
# sacred.exe is a 32-bit process; everything we inject into it must be 32-bit too.
|
||||||
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 4)
|
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||||
message(FATAL_ERROR "sacred_re must be built for 32-bit x86 (use the 'x86-*' presets / an x86 MSVC environment).")
|
message(FATAL_ERROR "sacredK must be built for 32-bit x86 (use the 'x86-*' presets / an x86 MSVC environment).")
|
||||||
endif()
|
endif()
|
||||||
if(NOT MSVC)
|
if(NOT MSVC)
|
||||||
message(FATAL_ERROR "sacred_re requires MSVC (the game's C++ ABI is MSVC's).")
|
message(FATAL_ERROR "sacredK requires MSVC (the game's C++ ABI is MSVC's).")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
@@ -19,17 +19,17 @@ add_compile_definitions(WIN32_LEAN_AND_MEAN NOMINMAX _CRT_SECURE_NO_WARNINGS)
|
|||||||
include(cmake/Detours.cmake)
|
include(cmake/Detours.cmake)
|
||||||
include(cmake/Json.cmake)
|
include(cmake/Json.cmake)
|
||||||
|
|
||||||
set(SACRED_RE_CXX_FLAGS /W4 /permissive- /utf-8)
|
set(SACREDK_CXX_FLAGS /W4 /permissive- /utf-8)
|
||||||
|
|
||||||
# --- sacred_re.dll: injected into sacred.exe, installs the hooks -------------
|
# --- sacredK.dll: injected into sacred.exe, installs the hooks -------------
|
||||||
add_library(sacred_re SHARED
|
add_library(sacredK SHARED
|
||||||
src/re/dllmain.cpp
|
src/re/dllmain.cpp
|
||||||
src/re/hook.cpp
|
src/re/hook.cpp
|
||||||
src/re/log.cpp
|
src/re/log.cpp
|
||||||
src/re/config.cpp
|
src/re/config.cpp
|
||||||
src/re/patch.cpp
|
src/re/patch.cpp
|
||||||
src/re/crash.cpp
|
src/re/crash.cpp
|
||||||
src/re/sacred_re.def
|
src/re/sacredK.def
|
||||||
src/game/engine/log.cpp
|
src/game/engine/log.cpp
|
||||||
src/game/engine/cmdline.cpp
|
src/game/engine/cmdline.cpp
|
||||||
src/game/engine/events.cpp
|
src/game/engine/events.cpp
|
||||||
@@ -70,13 +70,13 @@ add_library(sacred_re SHARED
|
|||||||
src/mods/charexport.cpp
|
src/mods/charexport.cpp
|
||||||
src/mods/options.cpp
|
src/mods/options.cpp
|
||||||
)
|
)
|
||||||
target_include_directories(sacred_re PRIVATE src)
|
target_include_directories(sacredK PRIVATE src)
|
||||||
target_compile_options(sacred_re PRIVATE ${SACRED_RE_CXX_FLAGS})
|
target_compile_options(sacredK PRIVATE ${SACREDK_CXX_FLAGS})
|
||||||
target_link_libraries(sacred_re PRIVATE detours nlohmann_json::nlohmann_json dbghelp)
|
target_link_libraries(sacredK PRIVATE detours nlohmann_json::nlohmann_json dbghelp)
|
||||||
|
|
||||||
# --- sacred_re.exe: launches sacred.exe with sacred_re.dll injected ----------
|
# --- sacredK.exe: launches sacred.exe with sacredK.dll injected ----------
|
||||||
add_executable(sacred_re_launcher WIN32 src/launcher/main.cpp)
|
add_executable(sacredK_launcher WIN32 src/launcher/main.cpp)
|
||||||
set_target_properties(sacred_re_launcher PROPERTIES OUTPUT_NAME sacred_re)
|
set_target_properties(sacredK_launcher PROPERTIES OUTPUT_NAME sacredK)
|
||||||
target_compile_options(sacred_re_launcher PRIVATE ${SACRED_RE_CXX_FLAGS})
|
target_compile_options(sacredK_launcher PRIVATE ${SACREDK_CXX_FLAGS})
|
||||||
target_link_libraries(sacred_re_launcher PRIVATE detours)
|
target_link_libraries(sacredK_launcher PRIVATE detours)
|
||||||
add_dependencies(sacred_re_launcher sacred_re)
|
add_dependencies(sacredK_launcher sacredK)
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
# sacred_re
|
# sacredK
|
||||||
|
|
||||||
An incremental reimplementation of **Sacred Gold 2.28** (`sacred.exe`, 2006).
|
An incremental reimplementation of **Sacred Gold 2.28** (`sacred.exe`, 2006).
|
||||||
|
|
||||||
`sacred_re.dll` is injected into the original game at startup and replaces game
|
`sacredK.dll` is injected into the original game at startup and replaces game
|
||||||
functions with rewritten C++ one by one. Everything not yet rewritten keeps
|
functions with rewritten C++ one by one. Everything not yet rewritten keeps
|
||||||
running as original machine code, so the game stays playable at every step and
|
running as original machine code, so the game stays playable at every step and
|
||||||
each rewrite can be tested in-game immediately. Once enough is rewritten, the
|
each rewrite can be tested in-game immediately. Once enough is rewritten, the
|
||||||
@@ -42,14 +42,14 @@ the CMake presets.
|
|||||||
## Running
|
## Running
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
build\x86-debug\sacred_re.exe --game-dir "D:\Gaming\Sacred Gold" # first run; remembered in sacred_re.ini
|
build\x86-debug\sacredK.exe --game-dir "D:\Gaming\Sacred Gold" # first run; remembered in sacredK.ini
|
||||||
build\x86-debug\sacred_re.exe log # later runs; extra args go to the game
|
build\x86-debug\sacredK.exe log # later runs; extra args go to the game
|
||||||
```
|
```
|
||||||
|
|
||||||
`sacred_re.log` (next to the DLL) records what was hooked plus every message the
|
`sacredK.log` (next to the DLL) records what was hooked plus every message the
|
||||||
game sends to its internal logger, even when the game's own logging is off.
|
game sends to its internal logger, even when the game's own logging is off.
|
||||||
|
|
||||||
Hooks can be switched off individually in `sacred_re.ini` (next to the DLL)
|
Hooks can be switched off individually in `sacredK.ini` (next to the DLL)
|
||||||
to compare a rewrite against the original:
|
to compare a rewrite against the original:
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
@@ -61,7 +61,7 @@ CmdLineHasFlag=0
|
|||||||
|
|
||||||
```
|
```
|
||||||
src/re/ hook framework, injection-side startup, logging, config
|
src/re/ hook framework, injection-side startup, logging, config
|
||||||
src/launcher/ sacred_re.exe — starts sacred.exe with the DLL injected
|
src/launcher/ sacredK.exe — starts sacred.exe with the DLL injected
|
||||||
src/game/ rewritten game code and original-layout structs, by subsystem
|
src/game/ rewritten game code and original-layout structs, by subsystem
|
||||||
src/mods/ behaviour changes on top of the original (e.g. borderless.cpp)
|
src/mods/ behaviour changes on top of the original (e.g. borderless.cpp)
|
||||||
docs/ reverse-engineering notes; function-map.md tracks progress
|
docs/ reverse-engineering notes; function-map.md tracks progress
|
||||||
|
|||||||
+2
-2
@@ -3,7 +3,7 @@
|
|||||||
Request (2026-10-18): the settings screen gets three tabs: *Allgemein*,
|
Request (2026-10-18): the settings screen gets three tabs: *Allgemein*,
|
||||||
*Beute* (loot filter; first iteration: the game's loot options moved there
|
*Beute* (loot filter; first iteration: the game's loot options moved there
|
||||||
from the common page) and *Tastenbelegung* (key bindings, so far only
|
from the common page) and *Tastenbelegung* (key bindings, so far only
|
||||||
settable in `sacred_re.ini`). Code: `src/mods/options.cpp`; bindings in
|
settable in `sacredK.ini`). Code: `src/mods/options.cpp`; bindings in
|
||||||
`src/mods/input.cpp`.
|
`src/mods/input.cpp`.
|
||||||
|
|
||||||
## The window (cUI_Options)
|
## The window (cUI_Options)
|
||||||
@@ -42,7 +42,7 @@ settable in `sacred_re.ini`). Code: `src/mods/options.cpp`; bindings in
|
|||||||
a box captures the next key press (`input::SetKeyCapture`, swallowed before
|
a box captures the next key press (`input::SetKeyCapture`, swallowed before
|
||||||
the game sees it): Esc cancels, Backspace unbinds, a bindable key is taken
|
the game sees it): Esc cancels, Backspace unbinds, a bindable key is taken
|
||||||
(and removed from any other action). The page works on a copy loaded when
|
(and removed from any other action). The page works on a copy loaded when
|
||||||
the window opens; OK (`0x717460`) saves it to `[keys]` in `sacred_re.ini`,
|
the window opens; OK (`0x717460`) saves it to `[keys]` in `sacredK.ini`,
|
||||||
Cancel drops it.
|
Cancel drops it.
|
||||||
- Movement keys (W/A/S/D) are bindings now (`MoveUp/Left/Down/Right`);
|
- Movement keys (W/A/S/D) are bindings now (`MoveUp/Left/Down/Right`);
|
||||||
`mods/wasd.cpp` polls the bound keys.
|
`mods/wasd.cpp` polls the bound keys.
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ was empty after loading another character (in-game saves don't call saveHero).
|
|||||||
the chest drew at the wrong spot after some loads. Both tabs' grids are put
|
the chest drew at the wrong spot after some loads. Both tabs' grids are put
|
||||||
back to the constructor's values every tick and on each tab switch.
|
back to the constructor's values every tick and on each tab switch.
|
||||||
- `MoveItem` from/to 0x11 while the shared tab is open moves from/to it.
|
- `MoveItem` from/to 0x11 while the shared tab is open moves from/to it.
|
||||||
- File: `{"format": "sacred_re.shared_chest", "version": 1, "items": [{cell,
|
- File: `{"format": "sacredK.shared_chest", "version": 1, "items": [{cell,
|
||||||
w, h, type, data (hex of vf1c), count}]}`; written after each successful
|
w, h, type, data (hex of vf1c), count}]}`; written after each successful
|
||||||
`saveHero` and after each save-game write (in-game saves don't call saveHero;
|
`saveHero` and after each save-game write (in-game saves don't call saveHero;
|
||||||
via a temp file), read on the first engine tick with a hero after a session
|
via a temp file), read on the first engine tick with a hero after a session
|
||||||
|
|||||||
+2
-2
@@ -93,7 +93,7 @@ mouse/keyboard like `tools/autotest-load.ps1`:
|
|||||||
2. play scripted input through the existing hooks (keys, casting arts, weapon
|
2. play scripted input through the existing hooks (keys, casting arts, weapon
|
||||||
set switches, save + reload);
|
set switches, save + reload);
|
||||||
3. take back-buffer screenshots at checkpoints and log checks to
|
3. take back-buffer screenshots at checkpoints and log checks to
|
||||||
`sacred_re.log` (aura effect present after reload, slot 6-7 inventories
|
`sacredK.log` (aura effect present after reload, slot 6-7 inventories
|
||||||
survive a save, ...);
|
survive a save, ...);
|
||||||
4. exit the game.
|
4. exit the game.
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ W, A and S were game hotkeys. With WASD movement (`src/mods/wasd.cpp`) their
|
|||||||
actions moved to other keys for now; choose final bindings (and update the
|
actions moved to other keys for now; choose final bindings (and update the
|
||||||
in-game texts/tooltips that name the old keys):
|
in-game texts/tooltips that name the old keys):
|
||||||
|
|
||||||
| Key | Action | Temporary key (sacred_re.ini) |
|
| Key | Action | Temporary key (sacredK.ini) |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| W | potion kind 3 (`cEngine::UseActionSlot`, like Q/E/R/B/Space) | game potion keys switched off; `[keys] Potion1-5` (docs/options.md) |
|
| W | potion kind 3 (`cEngine::UseActionSlot`, like Q/E/R/B/Space) | game potion keys switched off; `[keys] Potion1-5` (docs/options.md) |
|
||||||
| A | pick up items nearby (creature event 0x113) | Q (`[keys] PickUp`, 2026-10-17; was V) |
|
| A | pick up items nearby (creature event 0x113) | Q (`[keys] PickUp`, 2026-10-17; was V) |
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
// optional callback (0x017e5ee4) and to either OutputDebugString or the
|
// optional callback (0x017e5ee4) and to either OutputDebugString or the
|
||||||
// in-game console object (0x017e5edc).
|
// in-game console object (0x017e5edc).
|
||||||
//
|
//
|
||||||
// Status: hooked, not rewritten. Every message is mirrored into sacred_re.log
|
// Status: hooked, not rewritten. Every message is mirrored into sacredK.log
|
||||||
// whether or not the game's own logging is enabled, then forwarded.
|
// whether or not the game's own logging is enabled, then forwarded.
|
||||||
|
|
||||||
#include "game/engine/log.h"
|
#include "game/engine/log.h"
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
// sacred_re.exe: starts sacred.exe with sacred_re.dll injected.
|
// sacredK.exe: starts sacred.exe with sacredK.dll injected.
|
||||||
//
|
//
|
||||||
// sacred_re.exe [--game-dir <dir>] [game arguments...]
|
// sacredK.exe [--game-dir <dir>] [game arguments...]
|
||||||
//
|
//
|
||||||
// The game directory comes from --game-dir (which is then remembered in
|
// The game directory comes from --game-dir (which is then remembered in
|
||||||
// sacred_re.ini), else from [paths] GameDir in sacred_re.ini, else the
|
// sacredK.ini), else from [paths] GameDir in sacredK.ini, else the
|
||||||
// launcher's own directory. Remaining arguments are passed to the game
|
// launcher's own directory. Remaining arguments are passed to the game
|
||||||
// unchanged, e.g. `sacred_re.exe log` enables the game's DEBUG.LOG.
|
// unchanged, e.g. `sacredK.exe log` enables the game's DEBUG.LOG.
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ std::wstring WithTrailingSlash(std::wstring dir) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Fail(const std::wstring& message) {
|
int Fail(const std::wstring& message) {
|
||||||
MessageBoxW(nullptr, message.c_str(), L"sacred_re", MB_OK | MB_ICONERROR);
|
MessageBoxW(nullptr, message.c_str(), L"sacredK", MB_OK | MB_ICONERROR);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ int Fail(const std::wstring& message) {
|
|||||||
|
|
||||||
int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) {
|
int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) {
|
||||||
const std::wstring launcherDir = ExeDir();
|
const std::wstring launcherDir = ExeDir();
|
||||||
const std::wstring ini = launcherDir + L"sacred_re.ini";
|
const std::wstring ini = launcherDir + L"sacredK.ini";
|
||||||
|
|
||||||
int argc = 0;
|
int argc = 0;
|
||||||
wchar_t** argv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
wchar_t** argv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||||
@@ -71,12 +71,12 @@ int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) {
|
|||||||
const std::wstring gameExe = gameDir + L"sacred.exe";
|
const std::wstring gameExe = gameDir + L"sacred.exe";
|
||||||
if (!FileExists(gameExe)) {
|
if (!FileExists(gameExe)) {
|
||||||
return Fail(L"sacred.exe not found in\n" + gameDir +
|
return Fail(L"sacred.exe not found in\n" + gameDir +
|
||||||
L"\n\nRun once with: sacred_re.exe --game-dir \"<Sacred Gold folder>\"");
|
L"\n\nRun once with: sacredK.exe --game-dir \"<Sacred Gold folder>\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::wstring dllPath = launcherDir + L"sacred_re.dll";
|
const std::wstring dllPath = launcherDir + L"sacredK.dll";
|
||||||
if (!FileExists(dllPath)) {
|
if (!FileExists(dllPath)) {
|
||||||
return Fail(L"sacred_re.dll not found next to the launcher:\n" + dllPath);
|
return Fail(L"sacredK.dll not found next to the launcher:\n" + dllPath);
|
||||||
}
|
}
|
||||||
// Detours takes the DLL path as ANSI.
|
// Detours takes the DLL path as ANSI.
|
||||||
char dllPathA[MAX_PATH];
|
char dllPathA[MAX_PATH];
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
// Mouse positions are mapped back from that rectangle to game pixels, both in
|
// Mouse positions are mapped back from that rectangle to game pixels, both in
|
||||||
// GetMouseClientPos (polled by the game) and in mouse window messages.
|
// GetMouseClientPos (polled by the game) and in mouse window messages.
|
||||||
//
|
//
|
||||||
// sacred_re.ini:
|
// sacredK.ini:
|
||||||
// [borderless]
|
// [borderless]
|
||||||
// Enabled=1 ; 0 = original behaviour
|
// Enabled=1 ; 0 = original behaviour
|
||||||
// IntegerScale=0 ; 1 = scale by whole multiples only (sharper, larger bars)
|
// IntegerScale=0 ; 1 = scale by whole multiples only (sharper, larger bars)
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ namespace game {
|
|||||||
// cParticleSystem_burningBone::Render (vf04 0x774e10, vtable 0x895b84):
|
// cParticleSystem_burningBone::Render (vf04 0x774e10, vtable 0x895b84):
|
||||||
// crashed reading the device it was given, which was null (2026-10-16, Esc
|
// crashed reading the device it was given, which was null (2026-10-16, Esc
|
||||||
// pressed while walking; Windows reported sacred.exe+0x374e39). Who renders
|
// pressed while walking; Windows reported sacred.exe+0x374e39). Who renders
|
||||||
// it without a device is not known yet (sacred_re_crash.txt will tell). With
|
// it without a device is not known yet (sacredK_crash.txt will tell). With
|
||||||
// no device there is nothing to draw.
|
// no device there is nothing to draw.
|
||||||
// (device, a 4x4 matrix by value; ret 0x44).
|
// (device, a 4x4 matrix by value; ret 0x44).
|
||||||
struct Matrix4 {
|
struct Matrix4 {
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@
|
|||||||
// inside both.
|
// inside both.
|
||||||
// The world never sees these offsets: they are only active inside the hooks.
|
// The world never sees these offsets: they are only active inside the hooks.
|
||||||
//
|
//
|
||||||
// sacred_re.ini:
|
// sacredK.ini:
|
||||||
// [hud]
|
// [hud]
|
||||||
// Enabled=1
|
// Enabled=1
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@
|
|||||||
// off. Alt+key arrives as WM_SYSKEYDOWN and is not handled here anyway.)
|
// off. Alt+key arrives as WM_SYSKEYDOWN and is not handled here anyway.)
|
||||||
//
|
//
|
||||||
// The bindings are set on the options window's key bindings tab
|
// The bindings are set on the options window's key bindings tab
|
||||||
// (mods/options.cpp) and kept in sacred_re.ini (key names: kKeyNames below,
|
// (mods/options.cpp) and kept in sacredK.ini (key names: kKeyNames below,
|
||||||
// None):
|
// None):
|
||||||
// [keys]
|
// [keys]
|
||||||
// SkillSlot0=0 ... SkillSlot6=6 ; cast combat-art slot (0 = right mouse button art)
|
// SkillSlot0=0 ... SkillSlot6=6 ; cast combat-art slot (0 = right mouse button art)
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ const wchar_t* BindingGroup(int index);
|
|||||||
int BindingKey(int index); // virtual key, 0 = none
|
int BindingKey(int index); // virtual key, 0 = none
|
||||||
int DefaultBindingKey(int index);
|
int DefaultBindingKey(int index);
|
||||||
|
|
||||||
// Sets all bindings (`keys[BindingCount()]`) and writes them to sacred_re.ini.
|
// Sets all bindings (`keys[BindingCount()]`) and writes them to sacredK.ini.
|
||||||
void SetBindingKeys(const int* keys);
|
void SetBindingKeys(const int* keys);
|
||||||
|
|
||||||
// Whether `vk` can be bound, and its name as shown ("Leertaste", "F1", ...).
|
// Whether `vk` can be bound, and its name as shown ("Leertaste", "F1", ...).
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ void PutArtSlot(const json& variants, uint8_t* slot) {
|
|||||||
json ToJson(const std::vector<uint8_t>& block, const uint8_t* shadow) {
|
json ToJson(const std::vector<uint8_t>& block, const uint8_t* shadow) {
|
||||||
Reader r(block);
|
Reader r(block);
|
||||||
json j;
|
json j;
|
||||||
j["format"] = "sacred_re.inventory";
|
j["format"] = "sacredK.inventory";
|
||||||
j["version"] = kVersion;
|
j["version"] = kVersion;
|
||||||
j["player"] = r.U16();
|
j["player"] = r.U16();
|
||||||
j["flags"] = r.U16();
|
j["flags"] = r.U16();
|
||||||
@@ -262,7 +262,9 @@ json ToJson(const std::vector<uint8_t>& block, const uint8_t* shadow) {
|
|||||||
|
|
||||||
// The original block for slots 1-5; slots 6-7 are applied afterwards.
|
// The original block for slots 1-5; slots 6-7 are applied afterwards.
|
||||||
std::vector<uint8_t> ToBlock(const json& j) {
|
std::vector<uint8_t> ToBlock(const json& j) {
|
||||||
if (j.at("format") != "sacred_re.inventory" || j.at("version").get<int>() > kVersion) {
|
// "sacred_re.inventory": saves from before the project was renamed to sacredK.
|
||||||
|
const auto format = j.at("format").get<std::string>();
|
||||||
|
if ((format != "sacredK.inventory" && format != "sacred_re.inventory") || j.at("version").get<int>() > kVersion) {
|
||||||
throw std::runtime_error("unknown inventory format / version");
|
throw std::runtime_error("unknown inventory format / version");
|
||||||
}
|
}
|
||||||
Writer w;
|
Writer w;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Options window in three tabs: Allgemein, Beute, Tastenbelegung (request of
|
// Options window in three tabs: Allgemein, Beute, Tastenbelegung (request of
|
||||||
// 2026-10-18). Beute holds the game's auto-pickup settings (first iteration:
|
// 2026-10-18). Beute holds the game's auto-pickup settings (first iteration:
|
||||||
// moved there from the common page); Tastenbelegung sets the key bindings of
|
// moved there from the common page); Tastenbelegung sets the key bindings of
|
||||||
// mods/input.cpp, which had only been settable in sacred_re.ini.
|
// mods/input.cpp, which had only been settable in sacredK.ini.
|
||||||
//
|
//
|
||||||
// The window (cUI_Options, vtable 0x89505c, constructor 0x716570 building its
|
// The window (cUI_Options, vtable 0x89505c, constructor 0x716570 building its
|
||||||
// controls in 0x7184e0) is laid out for 1024x768: six frames in two columns
|
// controls in 0x7184e0) is laid out for 1024x768: six frames in two columns
|
||||||
|
|||||||
@@ -334,7 +334,7 @@ void Save() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const json j = {{"format", "sacred_re.shared_chest"}, {"version", kFileVersion}, {"items", items}};
|
const json j = {{"format", "sacredK.shared_chest"}, {"version", kFileVersion}, {"items", items}};
|
||||||
const std::string path = FilePath();
|
const std::string path = FilePath();
|
||||||
const std::string temp = path + ".tmp";
|
const std::string temp = path + ".tmp";
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
// 1024x768 layout, and set the variables from the render size.
|
// 1024x768 layout, and set the variables from the render size.
|
||||||
// See docs/widescreen.md.
|
// See docs/widescreen.md.
|
||||||
//
|
//
|
||||||
// sacred_re.ini:
|
// sacredK.ini:
|
||||||
// [widescreen]
|
// [widescreen]
|
||||||
// Enabled=1
|
// Enabled=1
|
||||||
// Height=768 ; world pixels visible vertically (768 = original look);
|
// Height=768 ; world pixels visible vertically (768 = original look);
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
// sacred_re.ini next to sacred_re.dll / sacred_re.exe.
|
// sacredK.ini next to sacredK.dll / sacredK.exe.
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ namespace re {
|
|||||||
|
|
||||||
void SetConfigPath(const std::wstring& path);
|
void SetConfigPath(const std::wstring& path);
|
||||||
const std::wstring& ConfigPath();
|
const std::wstring& ConfigPath();
|
||||||
// Folder of sacred_re.dll (with trailing separator), derived from the config path.
|
// Folder of sacredK.dll (with trailing separator), derived from the config path.
|
||||||
std::wstring ModuleDirectory();
|
std::wstring ModuleDirectory();
|
||||||
int ConfigInt(const char* section, const char* key, int fallback);
|
int ConfigInt(const char* section, const char* key, int fallback);
|
||||||
std::string ConfigString(const char* section, const char* key, const char* fallback);
|
std::string ConfigString(const char* section, const char* key, const char* fallback);
|
||||||
|
|||||||
+7
-7
@@ -1,10 +1,10 @@
|
|||||||
// Crash report: on an unhandled exception, writes sacred_re_crash.txt (code,
|
// Crash report: on an unhandled exception, writes sacredK_crash.txt (code,
|
||||||
// address as module + offset, registers, return addresses found on the stack)
|
// address as module + offset, registers, return addresses found on the stack)
|
||||||
// and sacred_re_crash.dmp next to the DLL. The game may install its own
|
// and sacredK_crash.dmp next to the DLL. The game may install its own
|
||||||
// filter later; SetUnhandledExceptionFilter is hooked so ours stays first and
|
// filter later; SetUnhandledExceptionFilter is hooked so ours stays first and
|
||||||
// passes the crash on to the game's afterwards.
|
// passes the crash on to the game's afterwards.
|
||||||
//
|
//
|
||||||
// Hangs: a watchdog thread writes sacred_re_hang.dmp (all threads) when the
|
// Hangs: a watchdog thread writes sacredK_hang.dmp (all threads) when the
|
||||||
// engine tick (re::EngineHeartbeat) has stopped for kHangMs while the game
|
// engine tick (re::EngineHeartbeat) has stopped for kHangMs while the game
|
||||||
// window is in front; once per hang. The game freezing on F2 while walking
|
// window is in front; once per hang. The game freezing on F2 while walking
|
||||||
// (2026-10-18) left no report.
|
// (2026-10-18) left no report.
|
||||||
@@ -52,7 +52,7 @@ bool IsCode(uintptr_t address) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WriteReport(EXCEPTION_POINTERS* info) {
|
void WriteReport(EXCEPTION_POINTERS* info) {
|
||||||
FILE* file = _wfopen((g_dir + L"sacred_re_crash.txt").c_str(), L"w");
|
FILE* file = _wfopen((g_dir + L"sacredK_crash.txt").c_str(), L"w");
|
||||||
if (!file) {
|
if (!file) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -100,7 +100,7 @@ void WriteReport(EXCEPTION_POINTERS* info) {
|
|||||||
}
|
}
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
HANDLE dump = CreateFileW((g_dir + L"sacred_re_crash.dmp").c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
|
HANDLE dump = CreateFileW((g_dir + L"sacredK_crash.dmp").c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
|
||||||
FILE_ATTRIBUTE_NORMAL, nullptr);
|
FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
if (dump != INVALID_HANDLE_VALUE) {
|
if (dump != INVALID_HANDLE_VALUE) {
|
||||||
MINIDUMP_EXCEPTION_INFORMATION exception = {GetCurrentThreadId(), info, FALSE};
|
MINIDUMP_EXCEPTION_INFORMATION exception = {GetCurrentThreadId(), info, FALSE};
|
||||||
@@ -120,7 +120,7 @@ bool GameInFront() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WriteHangDump() {
|
void WriteHangDump() {
|
||||||
HANDLE dump = CreateFileW((g_dir + L"sacred_re_hang.dmp").c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
|
HANDLE dump = CreateFileW((g_dir + L"sacredK_hang.dmp").c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
|
||||||
FILE_ATTRIBUTE_NORMAL, nullptr);
|
FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
if (dump != INVALID_HANDLE_VALUE) {
|
if (dump != INVALID_HANDLE_VALUE) {
|
||||||
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), dump,
|
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), dump,
|
||||||
@@ -142,7 +142,7 @@ DWORD WINAPI Watchdog(void*) {
|
|||||||
}
|
}
|
||||||
if (!reported && GameInFront()) {
|
if (!reported && GameInFront()) {
|
||||||
reported = true;
|
reported = true;
|
||||||
Log("hang: no engine tick for %lu ms, writing sacred_re_hang.dmp", GetTickCount() - beat);
|
Log("hang: no engine tick for %lu ms, writing sacredK_hang.dmp", GetTickCount() - beat);
|
||||||
WriteHangDump();
|
WriteHangDump();
|
||||||
Log("hang: dump written");
|
Log("hang: dump written");
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
namespace re {
|
namespace re {
|
||||||
|
|
||||||
// Writes sacred_re_crash.txt / .dmp into `dir` when the game crashes, and
|
// Writes sacredK_crash.txt / .dmp into `dir` when the game crashes, and
|
||||||
// sacred_re_hang.dmp when the engine stops ticking (see EngineHeartbeat).
|
// sacredK_hang.dmp when the engine stops ticking (see EngineHeartbeat).
|
||||||
void InstallCrashHandler(const std::wstring& dir);
|
void InstallCrashHandler(const std::wstring& dir);
|
||||||
|
|
||||||
// The engine ticked (running), or the game ended (not running).
|
// The engine ticked (running), or the game ended (not running).
|
||||||
|
|||||||
+6
-6
@@ -1,4 +1,4 @@
|
|||||||
// sacred_re.dll entry point. Loaded into sacred.exe by the launcher before the
|
// sacredK.dll entry point. Loaded into sacred.exe by the launcher before the
|
||||||
// game's own entry point runs, so every hook is in place from the first
|
// game's own entry point runs, so every hook is in place from the first
|
||||||
// instruction of game code.
|
// instruction of game code.
|
||||||
|
|
||||||
@@ -40,17 +40,17 @@ bool IsSupportedGameBuild() {
|
|||||||
|
|
||||||
void Startup(HMODULE module) {
|
void Startup(HMODULE module) {
|
||||||
std::wstring dir = ModuleDir(module);
|
std::wstring dir = ModuleDir(module);
|
||||||
re::OpenLog((dir + L"sacred_re.log").c_str());
|
re::OpenLog((dir + L"sacredK.log").c_str());
|
||||||
re::SetConfigPath(dir + L"sacred_re.ini");
|
re::SetConfigPath(dir + L"sacredK.ini");
|
||||||
re::Log("sacred_re loaded");
|
re::Log("sacredK loaded");
|
||||||
re::InstallCrashHandler(dir);
|
re::InstallCrashHandler(dir);
|
||||||
|
|
||||||
if (!IsSupportedGameBuild()) {
|
if (!IsSupportedGameBuild()) {
|
||||||
re::Log("unsupported sacred.exe build, no hooks installed");
|
re::Log("unsupported sacred.exe build, no hooks installed");
|
||||||
MessageBoxW(nullptr,
|
MessageBoxW(nullptr,
|
||||||
L"This sacred.exe is not the supported Sacred Gold 2.28 build.\n"
|
L"This sacred.exe is not the supported Sacred Gold 2.28 build.\n"
|
||||||
L"sacred_re will not patch it; the game runs unmodified.",
|
L"sacredK will not patch it; the game runs unmodified.",
|
||||||
L"sacred_re", MB_OK | MB_ICONWARNING);
|
L"sacredK", MB_OK | MB_ICONWARNING);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (re::ConfigInt("debug", "WaitForDebugger", 0)) {
|
if (re::ConfigInt("debug", "WaitForDebugger", 0)) {
|
||||||
|
|||||||
+2
-2
@@ -13,7 +13,7 @@
|
|||||||
//
|
//
|
||||||
// The signature, including the calling convention, must match the original
|
// The signature, including the calling convention, must match the original
|
||||||
// exactly (`__cdecl`, `__stdcall`, `__thiscall` / `__fastcall` stand-in, ...).
|
// exactly (`__cdecl`, `__stdcall`, `__thiscall` / `__fastcall` stand-in, ...).
|
||||||
// Hooks can be disabled individually at runtime in sacred_re.ini:
|
// Hooks can be disabled individually at runtime in sacredK.ini:
|
||||||
//
|
//
|
||||||
// [hooks]
|
// [hooks]
|
||||||
// Log=0
|
// Log=0
|
||||||
@@ -40,7 +40,7 @@ bool AttachRuntimeHook(const char* name, void** original, void* replacement);
|
|||||||
|
|
||||||
// Hooks a Windows API function for the whole process (game and DLLs alike).
|
// Hooks a Windows API function for the whole process (game and DLLs alike).
|
||||||
// `replacement` must have the API's exact signature; defines
|
// `replacement` must have the API's exact signature; defines
|
||||||
// `replacement##_original`. Disabled in sacred_re.ini under the API's name.
|
// `replacement##_original`. Disabled in sacredK.ini under the API's name.
|
||||||
#define RE_HOOK_API(api, replacement) \
|
#define RE_HOOK_API(api, replacement) \
|
||||||
static decltype(&replacement) replacement##_original = &api; \
|
static decltype(&replacement) replacement##_original = &api; \
|
||||||
static ::re::HookRegistration replacement##_registration( \
|
static ::re::HookRegistration replacement##_registration( \
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
// sacred_re's own log: sacred_re.log next to sacred_re.dll, plus OutputDebugString.
|
// sacredK's own log: sacredK.log next to sacredK.dll, plus OutputDebugString.
|
||||||
|
|
||||||
namespace re {
|
namespace re {
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
LIBRARY sacred_re
|
LIBRARY sacredK
|
||||||
EXPORTS
|
EXPORTS
|
||||||
; Detours requires ordinal 1 on any DLL injected via DetourCreateProcessWithDll.
|
; Detours requires ordinal 1 on any DLL injected via DetourCreateProcessWithDll.
|
||||||
DetourFinishHelperProcess @1 NONAME
|
DetourFinishHelperProcess @1 NONAME
|
||||||
+1
-1
@@ -30,7 +30,7 @@ $env:GHIDRA_HEADLESS_MAXMEM = "8G"
|
|||||||
`autotest-load.ps1` starts the game through the launcher, clicks
|
`autotest-load.ps1` starts the game through the launcher, clicks
|
||||||
"Spiel laden" -> "Laden" -> "Ok" (first save game), takes screenshots in-game
|
"Spiel laden" -> "Laden" -> "Ok" (first save game), takes screenshots in-game
|
||||||
and with the ESC menu open, and stops the game. `-Ini` appends temporary
|
and with the ESC menu open, and stops the game. `-Ini` appends temporary
|
||||||
settings to `build\x86-debug\sacred_re.ini` (restored afterwards), e.g.
|
settings to `build\x86-debug\sacredK.ini` (restored afterwards), e.g.
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
.\tools\autotest-load.ps1 -Name ws_off -Ini "[widescreen]`r`nEnabled=0"
|
.\tools\autotest-load.ps1 -Name ws_off -Ini "[widescreen]`r`nEnabled=0"
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
# the list, 1 = the first, selected by default), take
|
# the list, 1 = the first, selected by default), take
|
||||||
# screenshots in-game and with the ESC menu open, then stop the game.
|
# screenshots in-game and with the ESC menu open, then stop the game.
|
||||||
#
|
#
|
||||||
# .\tools\autotest-load.ps1 -Name ws_on # current sacred_re.ini
|
# .\tools\autotest-load.ps1 -Name ws_on # current sacredK.ini
|
||||||
# .\tools\autotest-load.ps1 -Name ws_off -Ini "[widescreen]`r`nEnabled=0"
|
# .\tools\autotest-load.ps1 -Name ws_off -Ini "[widescreen]`r`nEnabled=0"
|
||||||
#
|
#
|
||||||
# -Ini temporarily appends settings to build\x86-debug\sacred_re.ini.
|
# -Ini temporarily appends settings to build\x86-debug\sacredK.ini.
|
||||||
# Click positions are for the classic (menu) layout scaled onto a 3440x1440
|
# Click positions are for the classic (menu) layout scaled onto a 3440x1440
|
||||||
# monitor; adjust for other monitors. Don't touch mouse/keyboard while it runs.
|
# monitor; adjust for other monitors. Don't touch mouse/keyboard while it runs.
|
||||||
param(
|
param(
|
||||||
@@ -21,7 +21,7 @@ $ErrorActionPreference = "Stop"
|
|||||||
. (Join-Path $PSScriptRoot "game-input.ps1")
|
. (Join-Path $PSScriptRoot "game-input.ps1")
|
||||||
|
|
||||||
$root = Split-Path $PSScriptRoot
|
$root = Split-Path $PSScriptRoot
|
||||||
$iniPath = Join-Path $root "build\x86-debug\sacred_re.ini"
|
$iniPath = Join-Path $root "build\x86-debug\sacredK.ini"
|
||||||
$iniBackup = if (Test-Path $iniPath) { Get-Content $iniPath -Raw } else { "" }
|
$iniBackup = if (Test-Path $iniPath) { Get-Content $iniPath -Raw } else { "" }
|
||||||
if ($Ini) { Set-Content $iniPath ($iniBackup + "`r`n" + $Ini + "`r`n") -Encoding ASCII }
|
if ($Ini) { Set-Content $iniPath ($iniBackup + "`r`n" + $Ini + "`r`n") -Encoding ASCII }
|
||||||
|
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ function Focus-Sacred($Game) {
|
|||||||
[SacredRe.Input]::SetForegroundWindow($Game.MainWindowHandle)
|
[SacredRe.Input]::SetForegroundWindow($Game.MainWindowHandle)
|
||||||
}
|
}
|
||||||
|
|
||||||
$script:LogPath = Join-Path $script:Root "build\x86-debug\sacred_re.log"
|
$script:LogPath = Join-Path $script:Root "build\x86-debug\sacredK.log"
|
||||||
|
|
||||||
# Waits until sacred_re.log (written anew at every start) has at least $Count
|
# Waits until sacredK.log (written anew at every start) has at least $Count
|
||||||
# lines containing $Pattern, focusing the game meanwhile; then waits $AfterMs.
|
# lines containing $Pattern, focusing the game meanwhile; then waits $AfterMs.
|
||||||
function Wait-Log([string]$Pattern, [int]$Count = 1, [int]$TimeoutSeconds = 60, [int]$AfterMs = 500, $Game = $null) {
|
function Wait-Log([string]$Pattern, [int]$Count = 1, [int]$TimeoutSeconds = 60, [int]$AfterMs = 500, $Game = $null) {
|
||||||
$deadline = (Get-Date).AddSeconds($TimeoutSeconds)
|
$deadline = (Get-Date).AddSeconds($TimeoutSeconds)
|
||||||
@@ -46,7 +46,7 @@ function Wait-Log([string]$Pattern, [int]$Count = 1, [int]$TimeoutSeconds = 60,
|
|||||||
if ($found -ge $Count) { Start-Sleep -Milliseconds $AfterMs; return }
|
if ($found -ge $Count) { Start-Sleep -Milliseconds $AfterMs; return }
|
||||||
Start-Sleep -Milliseconds 200
|
Start-Sleep -Milliseconds 200
|
||||||
}
|
}
|
||||||
throw "timeout waiting for '$Pattern' in sacred_re.log"
|
throw "timeout waiting for '$Pattern' in sacredK.log"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Starts the game and returns once its main menu is up (the UI manager
|
# Starts the game and returns once its main menu is up (the UI manager
|
||||||
@@ -54,7 +54,7 @@ function Wait-Log([string]$Pattern, [int]$Count = 1, [int]$TimeoutSeconds = 60,
|
|||||||
function Start-Sacred([string]$Arguments = "log") {
|
function Start-Sacred([string]$Arguments = "log") {
|
||||||
if (Get-Process sacred -ErrorAction SilentlyContinue) { throw "sacred.exe is already running" }
|
if (Get-Process sacred -ErrorAction SilentlyContinue) { throw "sacred.exe is already running" }
|
||||||
if (Test-Path $script:LogPath) { Remove-Item $script:LogPath -ErrorAction SilentlyContinue }
|
if (Test-Path $script:LogPath) { Remove-Item $script:LogPath -ErrorAction SilentlyContinue }
|
||||||
$null = Start-Process (Join-Path $script:Root "build\x86-debug\sacred_re.exe") -ArgumentList $Arguments
|
$null = Start-Process (Join-Path $script:Root "build\x86-debug\sacredK.exe") -ArgumentList $Arguments
|
||||||
$game = $null
|
$game = $null
|
||||||
for ($i = 0; $i -lt 80 -and -not $game; $i++) {
|
for ($i = 0; $i -lt 80 -and -not $game; $i++) {
|
||||||
Start-Sleep -Milliseconds 250
|
Start-Sleep -Milliseconds 250
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
// Ghidra's own RecoverClassesFromRTTIScript finds nothing in this binary.
|
// Ghidra's own RecoverClassesFromRTTIScript finds nothing in this binary.
|
||||||
// Run once, headless, without -readOnly (see tools/README.md).
|
// Run once, headless, without -readOnly (see tools/README.md).
|
||||||
// @category sacred_re
|
// @category sacredK
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
// Addresses without a function (e.g. methods only reachable via a vtable) get
|
// Addresses without a function (e.g. methods only reachable via a vtable) get
|
||||||
// one created first; run without -readOnly to keep those in the project.
|
// one created first; run without -readOnly to keep those in the project.
|
||||||
// @category sacred_re
|
// @category sacredK
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
// into a class namespace; "#" starts a comment. Functions are created where
|
// into a class namespace; "#" starts a comment. Functions are created where
|
||||||
// none starts at the address yet. Names starting with "g_" label data
|
// none starts at the address yet. Names starting with "g_" label data
|
||||||
// (globals, tables) instead of functions.
|
// (globals, tables) instead of functions.
|
||||||
// @category sacred_re
|
// @category sacredK
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"name": "sacred-re-tools",
|
"name": "sacredk-tools",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "sacred-re-tools",
|
"name": "sacredk-tools",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"iced-x86": "1.21.0"
|
"iced-x86": "1.21.0"
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "sacred-re-tools",
|
"name": "sacredk-tools",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
Reference in new issue
Block a user