LHScript: Implement LHScriptX<c>/<w> text script engine#247
Merged
Conversation
Report for BW1W110 (b2442de - 2151214)No changesReport for BW1W100 (b2442de - 2151214)No changesReport for BW1W120 (b2442de - 2151214)Total code: 4710972 bytes (-195 bytes) ✅ 29 new matches
📈 18 improvements in unmatched items
|
Implement the LHLib text script engine (BW1W120 0x7E7260-0x7EA0B0) as the genuine template it was: LHScriptX<T>, LHScriptCommandX<T>, LHScriptPramX<T> and LHScriptVariable<T>, instantiated for char and wchar_t through the original's own bodge_to_force_compilation_of_versions(). Static data (Commands/Conditions/NamesToCondition tables, the Pram buffers and LastLineParsed) reconstructed verbatim from the binary. Key build-model findings, all evidence-driven: - The TU was compiled with inlining disabled (/Ob0) plus /GX: every tiny header-inline member (LHScreen::Depth/MaxDepth, LHSpriteList ctor, LHStringOps wrappers, makechar/fromchar) exists as a called comdat inside the TU's range. Depth/MaxDepth move from LHScreen.cpp into the header. - The memory-tracking operator new has a matching placement delete (declared in LHWin.h); its presence is what gives /GX functions using new(__FILE__, __LINE__) on ctor types their EH frames, and its calls are the unwind funclets parked at 0x8A7B20+. - #line pins reproduce the original __FILE__/__LINE__ values (C:\Dev\Libs\lionhead\lhlib\VER5.0\LHScript.cpp, lines 312/333/355/737/ 1032/1035), matching both the pushed line immediates and the path string. - LH_RETURN's real enumerator names (LH_OK/LH_FAIL/LH_ERROR/LH_NO_MEMORY) fall out of the script condition tables; the enum moves to LHReturn.h. - LHStringOps<char>/<wchar_t> CRT wrappers land in LHString.h (name fabricated); LHText gains LoadFont and the LHSpriteList ctor/Set. Result: 29 of 44 target functions at 100.0% instruction match and all 98 data objects (tables, both Pram statics, ~90 string literals) matching. ScanLine, ProcessCommand and GetConditionValue remain nonmatching with TODO notes; switch jump-table symbols are capped by diff-tool representation, not bytes. The wide string literals required decomp-toolkit v0.0.20 (dtk_tag bumped): its abs32 reconstruction previously ignored noreloc symbols and invented relocations inside UTF-16 text whose characters look like in-image pointers (openblack/decomp-toolkit#2). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the LHLib text script engine (BW1W120
0x7E7260–0x7EA0B0) as the genuine template it was:LHScriptX<T>,LHScriptCommandX<T>,LHScriptPramX<T>andLHScriptVariable<T>, instantiated forcharandwchar_tthrough the original's ownbodge_to_force_compilation_of_versions()(which survives at 0x7E6B70 with its Mac symbol name). Static data — theCommands/Conditions/NamesToConditiontables, bothPrambuffers andLastLineParsed— is reconstructed verbatim from the binary.Results: 29 of 44 target functions at 100.0% instruction match; all 98 data objects (tables, both Pram statics, ~90 string literals) matching.
ScanLine,ProcessCommandandGetConditionValueremain nonmatching with TODO notes describing what's known; the switch-heavy functions (GetConditionState,GetCommandAsText) are byte-identical in code but capped by jump-table representation in the diff tooling.Build-model findings (all evidence-driven, details in source comments):
/Ob0(no inlining) +/GX— that's why trivial header-inline members (LHScreen::Depth/MaxDepth, theLHSpriteListctor, all theLHStringOpswrappers) exist as called comdats inside this TU's range.Depth/MaxDepthmove from LHScreen.cpp into the header accordingly.operator newhas a matching placementoperator delete(void*, const char*, uint32_t)(now declared in LHWin.h). Its existence is what gives/GXfunctions usingnew(__FILE__, __LINE__)on ctor types their EH frames — the mystery funclets at 0x8A7B20+ are ProcessCommand's unwinders calling it.#linepins reproduce the original__FILE__/__LINE__values (C:\Dev\Libs\lionhead\lhlib\VER5.0\LHScript.cpp, lines 312/333/355/737/1032/1035), so the tracking-new immediates and the path string match bytes.LH_RETURN's real enumerator names (LH_OK/LH_FAIL/LH_ERROR/LH_NO_MEMORY) fall out of the script condition tables; the enum moves from LHTransportInfo.h to a shared LHReturn.h.LHStringOps<char>/<wchar_t>CRT wrappers (header name fabricated, marked TODO).Depends on decomp-toolkit v0.0.20 (
dtk_tagbumped here): the wide string literals need openblack/decomp-toolkit#2, without which dtk invents abs32 relocations inside UTF-16 text whose characters happen to look like in-image pointers. The new dtk also validates a pre-existingtrnsctrl.objsplit/symbol overlap, fixed here by giving?_GetRangeOfTrysToCheckits truesize:0x7B.🤖 Generated with Claude Code