- Spielen hero panel shows the selected hero in 3D (cUI_NetGranny,
game/ui/granny.h).
- All menu screens draw on the options' rock wall; the main menu's 1024
frame is drawn centred over it, mouse and cursor shifted to match.
- The main menu's and options' own pictures and the main menu's 3D scene
are left out (textures hidden by surface, scene call redirected).
- Logo top left: FX_SACREDLOGO.TGA, drawn added.
- Game textures by name (game/ui/texture.h), textured and added quads.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Shared screen kit (mods/screen, docs/screens.md): a 1365x768 canvas
centred in the render width on our own dark background, the game's
frames and buttons; the main menu renders full width while it is shown.
- The load window (cUI_Savegame) is replaced by the Spielen screen:
character list, hero panel, campaign x difficulty grid, save/autosave
choice, rename/delete/reset/new character dialogs.
- Migrated characters without a shared hero load their hero's world
first, then start the new world.
- Options, Allgemein: autosave interval (Aus/5/10/15/30 minutes).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Esc menu: "Exportieren" became "Laden"; it opens the load window, always
in load mode. In a game every world loads (the current one reloads); a
"(neu)" world stops the game (cCommand_armaStop) and starts the new one
without the main menu. The character being played cannot be deleted.
- Silent autosave every sacredK.ini [characters] AutosaveMinutes (default
10, 0 = off) into the character's autosave file.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
"Zuruecksetzen" in the load window lists the selected character's worlds
and asks for confirmation. The world goes (a copy in characters\deleted),
with an autosave of it, and the shared hero's story completion of that
difficulty is cleared. The dialog is one generic list (title + entries).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- cUI_EscMenu::BuildLines hook: the UI_ESC_EXPORT line is removed, the
lines below move up, the window shrinks by one line, centred.
- game/ui/control.h: control vector helpers (ControlsIn, RemoveControl,
SetControlAt, DeleteControl, ControlNamed), used by the main menu too.
- The export screen is unreachable now: charexport.cpp and
docs/char-export.md deleted. Spielen screen redesign noted in todo.md.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- One world per campaign and difficulty in a character file (sections
ancaria<d> / underworld<d>; old world<d> renamed when read). Difficulty
unlocks by the shared hero's story completions (hero header +0xed..),
shared by both campaigns.
- Main menu: "Kampagne Ancaria", "Kampagne Underworld" and "Spielstaende"
become "Spielen" (mods/mainmenu.cpp). The load window lists all
characters, the world dialog offers both campaigns, "Neuer Charakter"
asks for the campaign and opens character creation.
- Character window: no Underworld import mode (new Underworld heroes, all
classes, slots light up), no "Importieren"; load window without
"Speichern".
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- CharacterNN.sacredK holds the shared hero and one world per difficulty,
plus an autosave file; the game works in save\characters\_work
- Load window: one row per character, a difficulty dialog on Laden
(worlds, newer autosaves, "(neu)" starts a new game with the shared
hero), Umbenennen, delete moves the character to characters\deleted
- The world keeps its own portals and hero position when the shared hero
is put on
- K and the Esc menu's "Speichern" save directly (quicksave path)
- One-time migration of the old save rows and exported heroes, after a
backup
- Startup no longer hangs in the game's foreground loop (0x810af0)
- Text overrides apply to our own text ids too; shared cUI_Button2
helpers in game/ui/button.h
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
README explains --game-dir and the stored GameDir; the VS Code launch
uses the stored path and builds through build.ps1.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The game's ANSI file API calls are hooked; paths under save\ and
Settings.cfg are redirected to Documents\Sacred\save and
Documents\Sacred\config, copied there once from the game folder.
The shared chest uses the same save folder.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Per category (Gold, Tränke, white/blue/yellow/brown/green items) one of
Löschen (loot deleted at once), Ignorieren (pickup key leaves it), Standard,
Immer anzeigen (label without the labels key). Replaces the game's
PICKUPAUTO choice; settings in [loot] of sacredK.ini. docs/loot-filter.md.
Also ignore MSYS *.stackdump files.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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>
- Options window in three tabs; the auto-pickup settings move to Beute;
sliders move with their page; black sides like the save game screen.
- Tastenbelegung: every binding settable (click, press key; Esc cancels,
Backspace unbinds), "Alle zurücksetzen" as a game button, saved on OK.
- Potions bindable (default unbound), named by the game's potion texts; the
game's own potion hotkeys are off; bar tooltips show the bound key.
- Map (M), overview map (Tab, held) and labels (Alt, held) bindable; the
game's own M / Tab / Alt handling is switched off.
- Save game key calls the game's save window code instead of a posted key.
- Teleportationstrank: fixed text replacement from startup (also the
Ausdauertrank items, potion kind 5 as well).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- cUI_Character (export) and cUI_Savegame draw inside the centred 1024x768
frame (viewport) with the render target beside it cleared black; the
export screen's 3D heroes were stretched across the wide viewport, away
from their labels and hit areas.
- Export screen shows the game's erase button for an occupied slot and
reloads the heroes after a delete. Overwriting was already the game's
own path once clicks hit the right slot.
- game/ui/control.h: shared show/hide for cUI_Control2.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Arts are objects (game::Art) built from the game's definitions: name,
launch type, damage source, regeneration group and the skills' art lists.
The tooltip gets one line per effect of a skill or attribute, sorted by
size; unlearned class skills are greyed out at 0%. Weapon arts list only
the damage types the held weapon deals and the held weapon's skill.
Tooltip line wrap ignores colour codes; art tooltips wrap wider.
Blitzschlag's tooltip rewrite becomes a tooltip filter.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The chains of a cast share the enemies they have claimed and prefer
unclaimed ones. Each chain keeps its heading and ranks candidates by
distance and turn; a chain's first jump turns away from the directions
the other chains set out in, so they keep fanning out. Jumps reach 75 %
of the cast range.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The keys rewrite the hero's path every cCreature::Update: one segment
along the held direction, the facing set to it, sliding along blocked
cells. Starting from idle runs the game's own Think steps at once
(StartPendingWalk, WalkAction) instead of waiting up to 110 ms, so
weapon switches no longer stop the walk. Stops wait 50 ms after the
keys are released, and a stop in progress is taken back when keys are
held again. Names for movement, stats and text-key functions.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Switching between weapon classes resets the hero's animation state inside
cUI_Taskbar2::SelectWeaponSet, which dropped the walk for a tick. The hook
sends the WASD walk again at once. Checkpoint before the movement rework.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- The shot end's button check (0x4def52) answers "held" for the auto-attack
target, like the melee swing end.
- An art order counts as started when the art's cooldown rises, so bow arts
and arts ordered mid-swing hand over to auto-attack.
- re/crash.cpp: a watchdog writes sacred_re_hang.dmp when the engine tick
stops for 10 s while the game is in front.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Character creation and the save window were not detected (the UI manager's
dialog slot held a hidden busy dialog); bound keys were swallowed or posted
their hotkey into the field. A text field now counts while it is the focused
edit control and was drawn in the last 250 ms.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The zoomed map view resets the viewport to the full render size when done;
the HUD layer shifted that reset past the render target, SetViewport failed
and the map's 256x256 viewport stayed set, clipping the cursor. Full-width
viewports at x 0 are no longer shifted.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Every yellow potion (potion kind 5, all stages) is a Teleportationstrank:
drinking it posts the teleporter's event to the busy dialog with the
hero's known portals; the potion is used up only when the hero teleports
from that window (closing it keeps the potion)
- Names replaced in every game text (ReplaceInTexts), so item names and the
bottom bar's quick-select tooltip read Teleportationstrank; GameText reads
the game's own text
- HeroIndex / HeroInventory moved to skillslots for shared use
- docs/teleport-potion.md; walking animation after loading noted in todo
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Shared chest: tabs "Truhe"/"Gemeinsam" as a column left of the grid
(game tab sheet), grids placed every tick, persistent across heroes
- Inventory tab texts capitalized (RegisterText / CapitalizeText)
- Combat-art runes stack like potions (itemstack, renamed from potionstack)
- Rune master: any rune for any number of runes, price by rune count
(4 runes = 1,000, x10 per missing rune), bought rune goes into the
backpack, Buy disabled without runes, gold or room, last rune remembered
per hero (saved), the chosen rune's name below its icon, dropping a
stack gives up one rune
- Keys: the old key handling no longer takes over after the save screen
(text field focus only counts while its dialog is shown)
- Esc crash: tooltips forgotten when the game destroys them
- Pick up (Q) sends the pickup order directly; search reach doubled
- Kettenblitz: tooltip shows hits per chain, chains, cast and jump range;
cast range 900 (longer ray segments), jumps half of that
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The chest is inventory 0x11 and already saved as JSON; stacking now applies
to all inventories below 0x12. Traders keep selling single potions.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- potioncounts.cpp: each potion slot shows how many potions of its kind the
hero carries (stacks added up)
- potionstack.cpp: potions of one type stack up to 20 per cell; every
potion entering the hero's grid pours into stacks with room, the sort
button stacks first, drinking takes one off a stack, counts drawn on the
cells and saved in the JSON inventories
- game/engine/items.h: potion kinds and grid helpers; ObjectManager and
DestroyObject in objects.h
- auto-attack: the projectile-weapon target radius is a design value
- docs/potion-stacks.md: measured paths and the design
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- autoattack: when the target dies, the nearest enemy within close range
(contact distance + a step) takes over; after an art the hero auto-attacks
if the art was melee (walked up / cast close by), or ranged with a ranged
weapon, or ranged with an enemy already in melee range; measured action
codes and weapon classes in game/engine/orders.h
- chainlightning: jumps reach Blitzschlag's cast range (20 ray segments of
30, the art code's hit check) via the shared NearestHostile search
- guards: burning bone render hook had the wrong signature (device plus a
4x4 matrix by value, ret 0x44) and corrupted the stack when fire arrows hit
- crash reports follow the ebp chain before the raw stack scan
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- re/crash: unhandled exceptions write sacred_re_crash.txt (module+offset,
registers, return addresses on the stack) and a minidump; the game's own
filter is chained behind ours
- guards: cParticleSystem_burningBone::Render (0x774e10) skips drawing when
given a null device (crash at sacred.exe+0x374e39 after Esc while walking)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- megamap: the zoomed view (0x6cc950) is shared by the large map and the
TAB overview map; its centre is now set per call from the drawing
window's offset (hud::DrawOffsetX) instead of fixed to the render width
- input: drop the Ctrl/Alt pass-through; GetKeyState reports Alt as held
after Alt+Tab, which switched all bindings back to the game's handling
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- respec: the panel's unused second button array becomes − buttons between
name and value; attributes give back invested points, skills give back
skill points, a level-1 skill is removed and can be chosen anew; all
through the game's own point functions (protected copy stays in sync)
- the − is the + icon with its vertical arm covered (no minus image exists)
- hud: RenderCentred / HandleCentred for mods hooking centred windows;
mouse event helpers shared in game/ui/events.h
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- hud: shift SetViewport/Clear with moved windows (TAB overview map)
- megamap: view constants patched to the render width (clip, scroll limit,
edge scrolling, centre, dark band, zoomed view and its markers); frame
stretched to the screen edges, zoom controls and their click area centred
- hud: Anchor::Screen windows are drawn and clicked unshifted but still own
the event scope
- autotest waits for log markers instead of fixed delays (~18 s per run)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Quest dialogs are tooltips. A tooltip now keeps the offset it gets when it
becomes visible (the hovered window's, or centred for dialogs) and records
it for hit tests; its own event handler is shifted too. Hidden windows no
longer count as hovered.
- Esc closes a visible dialog the way its answer buttons do: hide, then
cDialogManager::Answer with no answer (ends the input lock, nothing chosen).
- Autotest can select a save game row (-Save).
- Names for the UI manager, tooltip and dialog functions.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Skill bar: no art selection; slot 0 is the right-click art, keys 0-6 cast
slots directly; cooldown labels in exact seconds; slot 0 set apart.
- Arts regenerate on their own (casting no longer refills the group).
- Auto-attack after targeting or casting at a hostile creature, at the speed
of a held button.
- Auras can be recast while active (renew, no second visual).
- Blicke wie Klingen hits every enemy in range, physical, with life leech.
- Blitzschlag steers the game's own chain: 3 + level/5 hits, 1 + level/10
chains, re-hits a lone enemy.
- Weapon sets: click selects, drag only from the selected set; the leftmost
set is clickable (signed hit tests).
- Esc closes open windows before opening the game menu.
- HUD: standalone buttons and texts are centred.
- Record cache sized for widened views (town lag while walking).
- Shared game code: orders, fx events, text drawing, cooldowns, effects.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Saving marks effect objects dead, so after a load the Heldenmut /
Klingenblick buff was active but its aura effect (cObjectFX 842) was
gone. A few ticks after a save game has loaded, the effect is created
again for each such buff of a player hero (CreateAt + cEventFX 0x42,
as the art's cast effect does), with the buff's remaining time.
Shared game events (game/engine/events): engine tick and "save game
loaded" callbacks; the WASD mod uses the tick through it.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Arts with launch type 2 (buffs, auras, heals) are only valid on allies
or without a target; with an enemy under the cursor the game dropped
the order. Orders of a player hero for such arts lose a non-ally target,
which casts them on the hero. The launch type comes from the art
definition tables (game/engine/arts.h, tools/arttable.mjs).
Also: skill keys check the relocated taskbar slots (all 7), Ghidra
data labels (g_ names in names.txt).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
cUI_Taskbar2's slot arrays move behind the (enlarged) object with room
for 7 each; all instructions addressing them, the relative accesses
between the two arrays, the slot loops and the count clamp are patched
from tables in game/addresses.h (belt loops untouched). Slots 6 / 7
unlock at levels 45 / 65; AssignArtToSlot accepts slots up to 6. Slot
keys call the taskbar's selection directly (honouring COMBINE_SLOTS).
Shared code: re::PatchAll / PatchInstructionByte for patch tables,
game/engine/objects.h for object, RTTI and kernel calls, slot-hook
templates in skillslots.cpp.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Weapon sets and combat-art slots 6-7 live in a shadow inventory per
inventory; the slot methods run the original code on it for slots >= 5,
so item references, icon resources and selection events stay the
game's own. Save games (cInventoryManager::Serialize) and hero files
(saveHero / loadHero) store inventories as JSON ("SRIJ" + length);
vanilla blocks are still read, which migrates old saves. Multiplayer
transfers keep the binary format. nlohmann/json fetched via git.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Raw WM_KEYDOWN/WM_KEYUP are handled in both window procedures (the game
swaps 0x8110d0 and 0x8122a0 with SetWindowLong; 0x8110d0 is the in-game
one). Bound keys are swallowed and post the original hotkey's key event
to the kernel, so F-keys work and bindings are layout independent
([keys] in sacred_re.ini). Replaces the WASD hotkey remap and the digit
swap; W/A/S/D and the digit row no longer reach the game. Skill keys
still cast through the right mouse button. Enabled switches removed.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A digit that selects a combat-art slot now also presses the right mouse
button (posted WM_RBUTTONDOWN, released with the key), so the game casts
the art at the cursor like a right-click. SwapDigits trades the digit
rows; the key rewrite shares the WASD remap in the engine/UI receivers.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
While W/A/S/D are held, the controlled creature gets a plain walk order every
engine tick toward its position plus the pressed screen direction, as the
mouse does while its button is held (every mouse event re-sends a walk to the
cursor point); releasing sends the target-less stop order of a released mouse
button. W/A/S/D key events are swallowed before the hotkeys see them; their
old actions move to G (action slot 3), V (pick up nearby) and K (save game
window) for now, configurable in [wasd].
docs/wasd.md: order format, measured mouse behaviour, hotkey map.
docs/todo.md: better pathfinder; final bindings for the moved hotkeys.
re::ConfigString for string settings.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- tools/names.txt lists identified sacred.exe functions ("0xADDR
Class::Method"); rename.ps1 / Rename.java apply them to the persistent
Ghidra project, so decompiles read with real names.
- decompile.ps1: parameters other than the addresses are named-only (the
first address was taken as -Out).
- game-input.ps1: Hold-Key for polled keys such as movement.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Primitives covering the whole 1024x768 layout inside a moved window, such as
the dimming behind the exit confirmation, were shifted with the window and
left both sides undimmed; they are stretched to the render width instead.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Creatures were culled beyond 1024+200 x 768+200 screen pixels (cmp 4C8h /
3C8h in both object passes): invisible in the right part of a wide view,
and the player too once the centre passed 1224. The bounds follow the
render size now.
- Centre immediates written as negatives (-200h / -180h), missed before:
the row renderer's static object origin (0x62babb) and aiming at the
cursor (0x4fb620).
- HUD: moved windows no longer shift the shared mouse cursor object; the
cursor accessor (0x6550f0) hands them a per-thread shifted copy and writes
back what they changed. World input on other threads read the shifted
position now and then, which made hold-to-move jerky.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Mouse move events carry previous and current x (+4, +0xc); button events
x at +8. All are shifted, and restored to the saved values.
- The cursor object's previous x (+0xc) is shifted too: picking up an item
writes the cursor position into the event (0x6559a0).
- GetMouseClientPos returns the shifted position inside a moved window.
- Window hit tests (vf1c 0x731d40, taskbar 0x6dfb10) called outside a window
scope, e.g. 'is UI under the cursor' for world picking (0x75a370), use the
offset the top-level window was last drawn with.
- The item carried by the cursor (0x6555e0) and the UI manager's centred
status line / message box (0x75bbf0, 0x75c200) draw with the centre offset.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Alt object labels and floating texts are packed into a 1024x768 area
(push 300h/400h at 0x6272f8 and 0x60e940): widened to the render size.
- Screen centre immediates in the light/effect position list (0x41b1xx..)
and the floating text (damage number) projection 0x41e460/0x41eaf0 now use
the render centre; lights were offset from the player before.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Windows poll the mouse cursor object (0xcdbadc, x +4) for hover; it is
shifted inside a moved window's render/event scope like the events.
Tooltips are separate windows placed by the hovered window in its 1024
layout, so cUI_Tooltip renders with the offset of the moved window under
the cursor. Adds Move-To to the test input helpers.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Generic cUI_Window2 hooks centre dialogs, inventory, maps, traders and the
ESC menu. Event shifting now targets the cursor position of mouse events
(move/down/up, x at +8) instead of category 5 UI events, whose +0x48 is not
a point for commands such as opening the ESC menu.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
New mods/hud: while a HUD window renders, screen-space vertices passed to
D3D7 DrawPrimitive/DrawIndexedPrimitive are shifted by dx; while it handles
an event, the UI event point (category 5, +0x48) is shifted by -dx. Applied
to cUI_Taskbar2 (centred) and cUI_Mercenary (portrait + health, right edge).
3D belt items line up without help (their projection is screen-centred).
re::AttachRuntimeHook hooks functions only known at runtime (COM methods).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The default render size (1835x768) is below Direct3D 7's 2048 limit, so the
D3D7 -> D3D9 wrapper and its device-info workaround are no longer needed.
The game pauses start-up until its window is active; game-input.ps1 now
activates it reliably (Alt + SetForegroundWindow, polled), which dxwrapper
had masked. borderless logs the first failed presents.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Default render size is 768 high and as wide as the monitor aspect
(1835x768 on 3440x1440), scaled up: everything keeps the size players
know and the view only grows sideways. Height=0 keeps native 1:1.
- Ground: 818/888 clip limits, screen centre floats and integer
immediates, ground quad list (capped at 1749) moved with the tile list.
- 3D: cGranny ortho (+-512 x +-384, incl. HUD items) scaled; inverse
projection 0x623a20 (1/1024, 1/768) follows the render size, which fixes
the camera following the player ("outside world") and the missing
player / ESC menu.
- tools: game-input.ps1 + autotest-load.ps1 drive the game (load the first
save game, screenshots in-game and with the ESC menu).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- mods/widescreen: redirect the world view's reads of the 1024.0/768.0
constants and the 3D ortho extents to our variables; render size =
monitor; relocate the world view's tile draw list (1750 entries, no
bounds check) into an enlarged object (16384 entries).
- mods/dxwrapper: route DirectDraw through dxwrapper (Dd7to9, D3D9) since
Windows' D3D7 cannot render to targets larger than 2048; fix the game's
device info GUID pointer that dxwrapper's enumeration leaves invalid.
Pinned release fetched by CMake (hash-checked), installed next to the DLL.
- Main menu (UI thread) and loading screen render in a 1024x768 viewport
and are presented scaled ("classic" layout); in-game uses the full size.
- re/patch: verified code patches (operand redirect, push immediates,
displacements) and startup hooks; build.ps1/CMake download fixes.
In-game view untested yet; HUD still at the top-left.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Hooks now refer to addr::* instead of literal addresses; the header also
lists the world view's users of the 1024.0/768.0 constants and the ortho
projection extent pushes for the widescreen work.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Launcher (sacred_re.exe) starts sacred.exe with sacred_re.dll injected
via Detours; the DLL verifies the Sacred Gold 2.28 build before hooking.
- Hook framework: RE_HOOK for game addresses, RE_HOOK_API for Windows
APIs, per-hook enable/disable in sacred_re.ini, sacred_re.log.
- Game code: Log (0x66f1c0) hooked, CmdLineHasFlag (0x813140) rewritten.
- Borderless mod: forces windowed mode, covers the monitor, scales the
1024x768 image aspect-correct, remaps mouse input, keeps running in the
background with keyboard input hidden while unfocused.
- CMake/Ninja/MSVC x86 build, VS Code setup, disasm tool, function map.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>