From 092495ef5ff8eca311030c9afada0c9cdacb64be Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 6 Sep 2026 19:40:37 +0200 Subject: [PATCH 01/44] reimplement: SHC_3BB0A8C1_0x0045F130 100% --- .../Constructor_TextEditorState.cpp | 42 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/Constructor_TextEditorState.cpp diff --git a/src/OpenSHC/Text/TextEditorState/Constructor_TextEditorState.cpp b/src/OpenSHC/Text/TextEditorState/Constructor_TextEditorState.cpp new file mode 100644 index 000000000..70d1b72d3 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/Constructor_TextEditorState.cpp @@ -0,0 +1,42 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/OS.func.hpp" + +#include "OpenSHC/Globals/DAT_UserHelpDefinedData.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045F130 + TextEditorState* TextEditorState ::Constructor_TextEditorState() + { + this->isDialogStateInitialized = 0; + this->helpDialogVariant = 0; + this->unknown_0x23960 = 0; + this->helpDialogSubMode = 0; + this->useAlternateHelpTab = 0; + this->customHelpTextLength = 0; + this->pendingTokenTypeToSkip = 0; + this->useWideHelpLayout = 0; + + MACRO_CALL_MEMBER(TextEditorState_Func::resetHelpStateFields, this)(); + + this->DAT_PointerToTemporaryTextMemory = MACRO_CALL(OS_Func::_malloc)(40000); + this->customTextMaxLength = -1; + + for (int counter = 0; counter < 500; ++counter) { + if (strlen(DAT_UserHelpDefinedData::instance.HelpSections[counter])) { + continue; + } + this->counter = counter; + break; + } + + for (int i = 0; i < 20; ++i) { + this->intArray1[i] = 0; + } + return this; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c51eb419d..6dc96a67e 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18749,7 +18749,7 @@ SHC_3BB0A8C1_0x0045F0D0 | 0.0% | Pending SHC_3BB0A8C1_0x0045F120 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045F130 | 0.0% | Pending +SHC_3BB0A8C1_0x0045F130 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045F240 | 0.0% | Pending From 04f4f006328f16b6bedbda0c0e13c40199922f35 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 6 Sep 2026 19:53:13 +0200 Subject: [PATCH 02/44] reimplement: SHC_3BB0A8C1_0x0045D080 100% --- .../Text/TextEditorState/setHelpWindowBounds.cpp | 16 ++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/setHelpWindowBounds.cpp diff --git a/src/OpenSHC/Text/TextEditorState/setHelpWindowBounds.cpp b/src/OpenSHC/Text/TextEditorState/setHelpWindowBounds.cpp new file mode 100644 index 000000000..ba116919b --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/setHelpWindowBounds.cpp @@ -0,0 +1,16 @@ +#include "../TextEditorState.func.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045D080 + void TextEditorState::setHelpWindowBounds(undefined4 x, undefined4 y, undefined4 height, undefined4 width) + { + this->dialogContentX = x; + this->dialogContentY = y; + this->dialogContentHeight = height; + this->dialogContentWidth = width; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 6dc96a67e..1442c5aea 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18147,7 +18147,7 @@ SHC_3BB0A8C1_0x0045CD10 | 0.0% | Pending SHC_3BB0A8C1_0x0045D060 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045D080 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D080 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D0B0 | 100.0% | Reimplemented From b066a7b23c47b8395fa07c5c9cc51e63f5a46a25 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 6 Sep 2026 19:56:35 +0200 Subject: [PATCH 03/44] reimplement: SHC_3BB0A8C1_0x0045D0C0 100% --- .../TextEditorState/resetHelpStateFields.cpp | 16 ++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/resetHelpStateFields.cpp diff --git a/src/OpenSHC/Text/TextEditorState/resetHelpStateFields.cpp b/src/OpenSHC/Text/TextEditorState/resetHelpStateFields.cpp new file mode 100644 index 000000000..de0e1f34a --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/resetHelpStateFields.cpp @@ -0,0 +1,16 @@ +#include "../TextEditorState.func.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045D0C0 + void TextEditorState::resetHelpStateFields() + { + for (int i = 0; i < 30; ++i) { + this->helpSectionHistoryStack[i] = -1; + } + this->currentHelpSectionID = -1; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 1442c5aea..f0a323319 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18151,7 +18151,7 @@ SHC_3BB0A8C1_0x0045D080 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D0B0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045D0C0 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D0C0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D140 | 0.0% | Pending From 7b2bf257579817e75c85290a1bb8ec62f27f5b58 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 6 Sep 2026 20:00:48 +0200 Subject: [PATCH 04/44] reimplement: SHC_3BB0A8C1_0x0045D140 100% --- .../findHelpSectionIndexByName.cpp | 22 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/findHelpSectionIndexByName.cpp diff --git a/src/OpenSHC/Text/TextEditorState/findHelpSectionIndexByName.cpp b/src/OpenSHC/Text/TextEditorState/findHelpSectionIndexByName.cpp new file mode 100644 index 000000000..018ef45a5 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/findHelpSectionIndexByName.cpp @@ -0,0 +1,22 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/OS.func.hpp" + +#include "OpenSHC/Globals/DAT_UserHelpDefinedData.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045D140 + int TextEditorState::findHelpSectionIndexByName(char* param_1) + { + for (int counter = 0; counter < this->counter; ++counter) { + if (!MACRO_CALL(OS_Func::__stricmp)(DAT_UserHelpDefinedData::instance.HelpSections[counter], param_1)) { + return counter; + } + } + return -1; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f0a323319..0133f7362 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18153,7 +18153,7 @@ SHC_3BB0A8C1_0x0045D0B0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D0C0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045D140 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D140 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D1A0 | 0.0% | Pending From b4cd8aae7756a2cff34d01a69bc22dd54a28dbb2 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 6 Sep 2026 20:15:39 +0200 Subject: [PATCH 05/44] reimplement: SHC_3BB0A8C1_0x0045D1A0 100% --- .../Constructor_TextEditorState.cpp | 1 + .../findOrAddHelpSectionName.cpp | 32 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/findOrAddHelpSectionName.cpp diff --git a/src/OpenSHC/Text/TextEditorState/Constructor_TextEditorState.cpp b/src/OpenSHC/Text/TextEditorState/Constructor_TextEditorState.cpp index 70d1b72d3..afb18c1b7 100644 --- a/src/OpenSHC/Text/TextEditorState/Constructor_TextEditorState.cpp +++ b/src/OpenSHC/Text/TextEditorState/Constructor_TextEditorState.cpp @@ -24,6 +24,7 @@ namespace Text { this->DAT_PointerToTemporaryTextMemory = MACRO_CALL(OS_Func::_malloc)(40000); this->customTextMaxLength = -1; + // FIXME:: Requires a finishing zero case, or it will not set the counter for (int counter = 0; counter < 500; ++counter) { if (strlen(DAT_UserHelpDefinedData::instance.HelpSections[counter])) { continue; diff --git a/src/OpenSHC/Text/TextEditorState/findOrAddHelpSectionName.cpp b/src/OpenSHC/Text/TextEditorState/findOrAddHelpSectionName.cpp new file mode 100644 index 000000000..d1be3a1e5 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/findOrAddHelpSectionName.cpp @@ -0,0 +1,32 @@ +// disable deprecation warnings for strcpy +#pragma warning(disable : 4996) + +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/Text/TextEditorState.func.hpp" + +#include "OpenSHC/Globals/DAT_UserHelpDefinedData.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045D1A0 + int TextEditorState::findOrAddHelpSectionName(char* param_1) + { + int helpSectionId + = MACRO_CALL_MEMBER(OpenSHC::Text::TextEditorState_Func::findHelpSectionIndexByName, this)(param_1); + if (helpSectionId != -1) { + return helpSectionId; + } + // FIXME:: This should overflow the buffer if filled to much. The counter can reach 500, which is one over the + // buffer, ignoring that it will just overwrite this again and again. + helpSectionId = this->counter; + strcpy(DAT_UserHelpDefinedData::instance.HelpSections[helpSectionId], param_1); + if (this->counter < 500) { + ++this->counter; + } + return helpSectionId; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 0133f7362..8a879afc1 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18155,7 +18155,7 @@ SHC_3BB0A8C1_0x0045D0C0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D140 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045D1A0 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D1A0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D200 | 0.0% | Pending From 29815ead4749c3afe7e1deb786ad2957b0e765e0 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Mon, 7 Sep 2026 22:12:55 +0200 Subject: [PATCH 06/44] reimplement: SHC_3BB0A8C1_0x0045D200 100% --- IMPLEMENTATION_CHEAT_SHEET.md | 2 + .../Text/TextEditorState/parseHLPPart.cpp | 78 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/parseHLPPart.cpp diff --git a/IMPLEMENTATION_CHEAT_SHEET.md b/IMPLEMENTATION_CHEAT_SHEET.md index 12991e55d..087740438 100644 --- a/IMPLEMENTATION_CHEAT_SHEET.md +++ b/IMPLEMENTATION_CHEAT_SHEET.md @@ -386,6 +386,8 @@ you might have found an unrolled loop. Therefore, try to reproduce the logic in If GOTOs are present that clearly jump to the start of a loop, but the logic does not allow to do this without a GOTO, for example from a loop inside a loop, you might be able to move the continue or break condition to the outside. Methods could be placing a fitting condition related to the contained loop conditions after the loop or using a boolean flag that then functions as conditional. Both can sometimes be optimized away. +If an explicit loop condition is removed from the compiler, it is able to prove all paths through the loop. If such a case happens where the condition is actually eliminated from the re-implementation, the re-implementation might be missing a condition that is present in the logic somewhere, but removed from the loop condition itself. The optimization pass failed to detect the resulting predictable loop in this latter case and the condition remains. + A global used as a running counter alongside the loop index is usually incremented inside the loop, even when its final value is a constant. Ghidra shows the folded result: `DAT_CurrentUnitSlotID = 2500;` placed around the loop is really `DAT_CurrentUnitSlotID = 1;` before it and `DAT_CurrentUnitSlotID += 1;` as the first statement of the body. This was diff --git a/src/OpenSHC/Text/TextEditorState/parseHLPPart.cpp b/src/OpenSHC/Text/TextEditorState/parseHLPPart.cpp new file mode 100644 index 000000000..f630aa3b0 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/parseHLPPart.cpp @@ -0,0 +1,78 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/OS.func.hpp" + +#include "OpenSHC/Globals/HLP_WCHAR_Buffer.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045D200 + LPCWSTR TextEditorState::parseHLPPart(FILE* filePointer) + { + + int finishedParsing = FALSE; + int quoteActive = FALSE; + int reachedWEOF = FALSE; + wchar_t* bufferPtr = HLP_WCHAR_Buffer::instance; + while (!reachedWEOF) { + if (finishedParsing) { + return HLP_WCHAR_Buffer::instance; + } + + int readWChar = MACRO_CALL(OS_Func::_fgetwc)(filePointer); + switch (readWChar) { + case L'"': + quoteActive ^= TRUE; + continue; + + case L'\t': + case L' ': + case L',': + case L'=': + if (!quoteActive) { + int consumed = FALSE; + while (!reachedWEOF && !consumed) { + readWChar = MACRO_CALL(OS_Func::_fgetwc)(filePointer); + + if (readWChar == WEOF) { + reachedWEOF = TRUE; + continue; + } + + switch (readWChar) { + default: + MACRO_CALL(OS_Func::_fseek)(filePointer, -2, FILE_CURRENT); + case L'>': + consumed = true; + case L'\t': + case L' ': + case L',': + case L'=': + break; + } + } + } + case L'>': + if (!quoteActive) { + finishedParsing = true; + *bufferPtr = L'\0'; + continue; + } + break; + + case L'\n': + case L'\r': + continue; + + case WEOF: + reachedWEOF = true; + continue; + } + *bufferPtr++ = readWChar; + } + return NULL; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 8a879afc1..438bf489b 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18157,7 +18157,7 @@ SHC_3BB0A8C1_0x0045D140 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D1A0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045D200 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D200 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D300 | 0.0% | Pending From 6483df4341c75e65a94c5c972d54c672e25c51cc Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Mon, 7 Sep 2026 22:30:24 +0200 Subject: [PATCH 07/44] reimplement: SHC_3BB0A8C1_0x0045D370 100% --- .../loadHelpSectionGraphics.cpp | 22 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/loadHelpSectionGraphics.cpp diff --git a/src/OpenSHC/Text/TextEditorState/loadHelpSectionGraphics.cpp b/src/OpenSHC/Text/TextEditorState/loadHelpSectionGraphics.cpp new file mode 100644 index 000000000..ea5ba6b53 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/loadHelpSectionGraphics.cpp @@ -0,0 +1,22 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/UI/Rendering/TextureRenderCore.func.hpp" + +#include "OpenSHC/Globals/DAT_TextureRenderCoreObject.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045D370 + void TextEditorState::loadHelpSectionGraphics() + { + DAT_TextureRenderCoreObject::instance.backwardsLoadedGfxIndex_0x16C850 = 99; + DAT_TextureRenderCoreObject::instance.loadedGfxArray[99].backwardsOffsetInBuffer = 0; + for (int i = 0; i < this->graphicFileCount; ++i) { + MACRO_CALL_MEMBER(UI::Rendering::TextureRenderCore_Func::loadGfxAtBufferEnd, + DAT_TextureRenderCoreObject::ptr)(this->graphicFileNames[i]); + } + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 438bf489b..d16ced94f 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18327,7 +18327,7 @@ SHC_3BB0A8C1_0x0045D364 | 0.0% | Pending SHC_3BB0A8C1_0x0045D365 | 0.0% | Pending -SHC_3BB0A8C1_0x0045D370 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D370 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D3C0 | 0.0% | Pending From 8bdf42abaee45cc521503f56979183a131ea061f Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Tue, 8 Sep 2026 22:06:19 +0200 Subject: [PATCH 08/44] reimplement: SHC_3BB0A8C1_0x0045D3C0 100% --- .../getWideCharOrWideCharPointer.cpp | 36 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/getWideCharOrWideCharPointer.cpp diff --git a/src/OpenSHC/Text/TextEditorState/getWideCharOrWideCharPointer.cpp b/src/OpenSHC/Text/TextEditorState/getWideCharOrWideCharPointer.cpp new file mode 100644 index 000000000..7e28ededd --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/getWideCharOrWideCharPointer.cpp @@ -0,0 +1,36 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/Globals/DAT_ARRAY_00df2b78.hpp" + +namespace OpenSHC { +namespace Text { + + // NOTE: Return is essentially a "union", however, it needs to be a value for the proper structure + // Also, it might be likely that this function is "known" by its only user "processHelpRichTextTokens" + + // FUNCTION: STRONGHOLDCRUSADER 0x0045D3C0 + uint TextEditorState::getWideCharOrWideCharPointer(int* param_1) + { + int result = this->DAT_PointerToTemporaryTextMemory[*param_1]; + *param_1 += 1; + + if (result >= L' ') { + DAT_ARRAY_00df2b78::instance[0] = result; + + int length = 1; + while (this->DAT_PointerToTemporaryTextMemory[*param_1] >= L' ') { + DAT_ARRAY_00df2b78::instance[length] = this->DAT_PointerToTemporaryTextMemory[*param_1]; + *param_1 += 1; + ++length; + if (this->DAT_PointerToTemporaryTextMemory[*param_1 - 1] == L' ') { + break; + } + } + DAT_ARRAY_00df2b78::instance[length] = L'\0'; + result = (int)DAT_ARRAY_00df2b78::instance; + } + return (uint)result; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index d16ced94f..e649d37cc 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18329,7 +18329,7 @@ SHC_3BB0A8C1_0x0045D365 | 0.0% | Pending SHC_3BB0A8C1_0x0045D370 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045D3C0 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D3C0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D430 | 0.0% | Pending From a3ddfce53846ccab9b2dc6469cc74d78a35f91d9 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Wed, 9 Sep 2026 00:06:47 +0200 Subject: [PATCH 09/44] reimplement: SHC_3BB0A8C1_0x0045D430 100% --- .../renderHelpImageHotspots.cpp | 73 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/renderHelpImageHotspots.cpp diff --git a/src/OpenSHC/Text/TextEditorState/renderHelpImageHotspots.cpp b/src/OpenSHC/Text/TextEditorState/renderHelpImageHotspots.cpp new file mode 100644 index 000000000..d468a9d7c --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/renderHelpImageHotspots.cpp @@ -0,0 +1,73 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/Input/MouseState.func.hpp" +#include "OpenSHC/UI/Rendering/PencilRenderCore.func.hpp" +#include "OpenSHC/UI/Rendering/TextureRenderCore.func.hpp" + +#include "OpenSHC/Globals/COL_GREYISH_YELLOW.hpp" +#include "OpenSHC/Globals/DAT_MouseState.hpp" +#include "OpenSHC/Globals/DAT_PencilRenderCore.hpp" +#include "OpenSHC/Globals/DAT_TextureRenderCoreObject.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045D430 + void TextEditorState::renderHelpImageHotspots() + { + for (int i = 0; i < this->imageHotspotCount; ++i) { + int _gfxIndex = 99 - this->imageHotspotTable[i].imageRelated; + if ((this->useInGameHelpHandler || this->helpDialogVariant == 1) + && !MACRO_CALL_MEMBER(UI::Rendering::TextureRenderCore_Func::checkIfGfxTgxStartsWithTransparentPixels, + DAT_TextureRenderCoreObject::ptr)(_gfxIndex)) { + int x1 = this->imageHotspotTable[i].xPos + this->dialogContentX - 2; + int y1 = this->imageHotspotTable[i].yPos - this->helpContentScrollOffsetY + this->dialogContentY - 2; + int width = DAT_TextureRenderCoreObject::instance.loadedGfxArray[_gfxIndex].width + 3; + int height = DAT_TextureRenderCoreObject::instance.loadedGfxArray[_gfxIndex].height + 3; + if (y1 < this->dialogContentY) { + height += y1 - this->dialogContentY; + y1 = this->dialogContentY; + } + // Does the naming "dialogContentWidth" fit? Is it related to width? + if (height + y1 > this->dialogContentY + this->dialogContentWidth) { + height = this->dialogContentWidth * 2 - y1; + } + int const y2 = y1 + height; + if (y2 >= this->dialogContentY && y1 < this->dialogContentY + this->dialogContentWidth) { + int const x2 = x1 + width; + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( + x1, y1, x2, y1, COL_GREYISH_YELLOW::instance.shortValue); + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( + x1, y1 + 1, x2, y1 + 1, COL_GREYISH_YELLOW::instance.shortValue); + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( + x1, y2, x2, y2, COL_GREYISH_YELLOW::instance.shortValue); + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( + x1, y2 + -1, x2, y2 + -1, COL_GREYISH_YELLOW::instance.shortValue); + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( + x1, y1, x1, y2, COL_GREYISH_YELLOW::instance.shortValue); + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( + x1 + 1, y1, x1 + 1, y2, COL_GREYISH_YELLOW::instance.shortValue); + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( + x2, y1, x2, y2, COL_GREYISH_YELLOW::instance.shortValue); + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( + x2 + -1, y1, x2 + -1, y2, COL_GREYISH_YELLOW::instance.shortValue); + } + } + MACRO_CALL_MEMBER(UI::Rendering::TextureRenderCore_Func::drawGfxOnFlaggedSurface, + DAT_TextureRenderCoreObject::ptr)(_gfxIndex, this->imageHotspotTable[i].xPos + this->dialogContentX, + this->imageHotspotTable[i].yPos - this->helpContentScrollOffsetY + this->dialogContentY); + + int const boxHeight = DAT_TextureRenderCoreObject::instance.loadedGfxArray[_gfxIndex].height; + int const boxWidth = DAT_TextureRenderCoreObject::instance.loadedGfxArray[_gfxIndex].width; + if (MACRO_CALL_MEMBER(Input::MouseState_Func::isMouseInsideBox, DAT_MouseState::ptr)( + this->imageHotspotTable[i].xPos - this->helpContentScrollX + this->dialogContentX, + this->imageHotspotTable[i].yPos - this->helpContentScrollY + this->dialogContentY + - this->helpContentScrollOffsetY, + boxWidth, boxHeight)) { + this->unknown_0x23968 = this->imageHotspotTable[i].unknown3; + } + } + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index e649d37cc..abdb50692 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18331,7 +18331,7 @@ SHC_3BB0A8C1_0x0045D370 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D3C0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045D430 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D430 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D460 | 0.0% | Pending From 90ce68b9f42e83a7d055700853d017dcf5e48f2b Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Wed, 9 Sep 2026 00:19:29 +0200 Subject: [PATCH 10/44] reimplement: SHC_3BB0A8C1_0x0045D690 100% --- .../bltTextToScreenIfNeedBe.cpp | 27 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/bltTextToScreenIfNeedBe.cpp diff --git a/src/OpenSHC/Text/TextEditorState/bltTextToScreenIfNeedBe.cpp b/src/OpenSHC/Text/TextEditorState/bltTextToScreenIfNeedBe.cpp new file mode 100644 index 000000000..d6bb78b88 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/bltTextToScreenIfNeedBe.cpp @@ -0,0 +1,27 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/UI/Rendering/WindowAndDirectDraw.func.hpp" + +#include "OpenSHC/Globals/DAT_TextEditorState.hpp" +#include "OpenSHC/Globals/DAT_WindowAndDirectDraw.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045D690 + void TextEditorState::bltTextToScreenIfNeedBe() + { + if (!DAT_TextEditorState::instance.unknown_0x23960) { + return; + } + if (this->savedMenuViewType == UI::Enums::MVT_MAP_EDITOR_LANDSCAPING + || this->savedMenuViewType == UI::Enums::MVT_BUILD_MENU + || this->savedMenuViewType == UI::Enums::MVT_BUILDING_AND_STATUS_MENU) { + MACRO_CALL_MEMBER(UI::Rendering::WindowAndDirectDraw_Func::bltMapGameSurfaceToScreenMenuSurfaceComplete, + DAT_WindowAndDirectDraw::ptr)(); + } + DAT_TextEditorState::instance.unknown_0x23960 = FALSE; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index abdb50692..1b13f6cea 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18335,7 +18335,7 @@ SHC_3BB0A8C1_0x0045D430 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D460 | 0.0% | Pending -SHC_3BB0A8C1_0x0045D690 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D690 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D6C0 | 0.0% | Pending From 8d0f978e7f217afbb32e98712f3d9e85890509aa Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Wed, 9 Sep 2026 21:22:26 +0200 Subject: [PATCH 11/44] reimplement: SHC_3BB0A8C1_0x0045D6C0 100% --- .../TextEditorState/drawBorderStyle0x20.cpp | 37 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/drawBorderStyle0x20.cpp diff --git a/src/OpenSHC/Text/TextEditorState/drawBorderStyle0x20.cpp b/src/OpenSHC/Text/TextEditorState/drawBorderStyle0x20.cpp new file mode 100644 index 000000000..c36e3e66a --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/drawBorderStyle0x20.cpp @@ -0,0 +1,37 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/Globals/DAT_00df2964.hpp" +#include "OpenSHC/Globals/DAT_00df296c.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/INT_00df2968.hpp" +#include "OpenSHC/Globals/INT_00df2970.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045D6C0 + void TextEditorState::drawBorderStyle0x20(int dialogX, int dialogY, int dialogWidth, int dialogHeight) + { + this->dialogX = dialogX; + this->dialogY = dialogY; + this->dialogWidth = dialogWidth; + this->dialogHeight = dialogHeight; + + // NOTE: dialogWidth is used to compute the content height and vice versa, no idea if something was switched; + // also, the required order feels strange, maybe they used a RECT struct or macro + // FIXME: ContentHeight and ContentWidth or the dialogWidth and dialogHeight are swapped + int const contentX = this->dialogX + DAT_00df2964::instance; + int const contentY = this->dialogY + DAT_00df296c::instance; + int const contentWidth = this->dialogHeight - INT_00df2970::instance; + int const contentHeight = this->dialogWidth - INT_00df2968::instance; + this->dialogContentX = contentX; + this->dialogContentY = contentY; + this->dialogContentHeight = contentHeight; + this->dialogContentWidth = contentWidth; + + this->helpContentScrollX = DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetX; + this->helpContentScrollY = DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetY; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 1b13f6cea..3648fcc22 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18337,7 +18337,7 @@ SHC_3BB0A8C1_0x0045D460 | 0.0% | Pending SHC_3BB0A8C1_0x0045D690 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045D6C0 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D6C0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D740 | 0.0% | Pending From fa58174f665e64663239ffbb5029eb479c47b439 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Wed, 9 Sep 2026 22:00:49 +0200 Subject: [PATCH 12/44] reimplement: SHC_3BB0A8C1_0x0045D200 update return type --- src/OpenSHC/Text/TextEditorState/parseHLPPart.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenSHC/Text/TextEditorState/parseHLPPart.cpp b/src/OpenSHC/Text/TextEditorState/parseHLPPart.cpp index f630aa3b0..cc97503d3 100644 --- a/src/OpenSHC/Text/TextEditorState/parseHLPPart.cpp +++ b/src/OpenSHC/Text/TextEditorState/parseHLPPart.cpp @@ -8,7 +8,7 @@ namespace OpenSHC { namespace Text { // FUNCTION: STRONGHOLDCRUSADER 0x0045D200 - LPCWSTR TextEditorState::parseHLPPart(FILE* filePointer) + LPWSTR TextEditorState::parseHLPPart(FILE* filePointer) { int finishedParsing = FALSE; From 2a57a09e5cb302173d15bda891ebd091ca7bae6c Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Wed, 9 Sep 2026 22:53:30 +0200 Subject: [PATCH 13/44] reimplement: SHC_3BB0A8C1_0x0045D740 100% --- .../drawHelpWindowBackground.cpp | 52 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/drawHelpWindowBackground.cpp diff --git a/src/OpenSHC/Text/TextEditorState/drawHelpWindowBackground.cpp b/src/OpenSHC/Text/TextEditorState/drawHelpWindowBackground.cpp new file mode 100644 index 000000000..ac5555d62 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/drawHelpWindowBackground.cpp @@ -0,0 +1,52 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/UI/Rendering/PencilRenderCore.func.hpp" + +#include "OpenSHC/Globals/COL_BLACK.hpp" +#include "OpenSHC/Globals/COL_DARK_CYAN_GREY.hpp" +#include "OpenSHC/Globals/COL_VERY_DARK_GREY.hpp" +#include "OpenSHC/Globals/DAT_PencilRenderCore.hpp" +#include "OpenSHC/Globals/DAT_TextManagerObject.hpp" +#include "OpenSHC/Globals/DAT_TextureRenderCoreObject.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045D740 + void TextEditorState::drawHelpWindowBackground() + { + if (this->helpDialogVariant != 1) { + DAT_TextureRenderCoreObject::instance.drawBufferChoiceValue = Rendering::Enums::RT_SCREEN_MENU; + } else { + DAT_TextManagerObject::instance.textSurfaceTarget = Rendering::Enums::RT_MAP_GAME; + DAT_PencilRenderCore::instance.surfaceTarget = Rendering::Enums::RT_MAP_GAME; + } + if (this->isCustomTextMode) { + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawBoxWithRoundedEdges, DAT_PencilRenderCore::ptr)( + this->dialogX, this->dialogY, this->dialogWidth + this->dialogX, this->dialogHeight + this->dialogY, + UI::Enums::RBERL_SLIGHT); + } else if (!this->useAlternateHelpTab) { + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawColorBox, DAT_PencilRenderCore::ptr)( + this->dialogX, this->dialogY, this->dialogWidth + this->dialogX, this->dialogHeight + this->dialogY, + COL_BLACK::instance.shortValue); + } else if (this->helpDialogVariant != 2) { + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawColorBox, DAT_PencilRenderCore::ptr)( + this->dialogX, this->dialogY, this->dialogWidth + this->dialogX, this->dialogHeight + this->dialogY, + COL_VERY_DARK_GREY::instance.shortValue); + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawColorBox, DAT_PencilRenderCore::ptr)( + this->dialogContentX, this->dialogContentY, this->dialogContentHeight + this->dialogContentX, + this->dialogContentWidth + this->dialogContentY, COL_BLACK::instance.shortValue); + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawColorBox, DAT_PencilRenderCore::ptr)( + this->dialogX, this->dialogY + this->dialogHeight, this->dialogWidth + this->dialogX, + this->dialogY + this->dialogHeight + 60, COL_DARK_CYAN_GREY::instance.shortValue); + } + if (this->helpDialogVariant != 1) { + DAT_TextureRenderCoreObject::instance.drawBufferChoiceValue = Rendering::Enums::RT_MAP_GAME; + } else { + DAT_TextManagerObject::instance.textSurfaceTarget = Rendering::Enums::RT_SCREEN_MENU; + DAT_PencilRenderCore::instance.surfaceTarget = Rendering::Enums::RT_SCREEN_MENU; + } + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 3648fcc22..fa62413d4 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18339,7 +18339,7 @@ SHC_3BB0A8C1_0x0045D690 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D6C0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045D740 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D740 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D890 | 0.0% | Pending From 0c55173e6077f83d32d272875254d5e5b667930a Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Wed, 9 Sep 2026 23:06:18 +0200 Subject: [PATCH 14/44] reimplement: SHC_3BB0A8C1_0x0045D890 100% --- .../findHelpGraphicIndexByName.cpp | 20 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/findHelpGraphicIndexByName.cpp diff --git a/src/OpenSHC/Text/TextEditorState/findHelpGraphicIndexByName.cpp b/src/OpenSHC/Text/TextEditorState/findHelpGraphicIndexByName.cpp new file mode 100644 index 000000000..76afd0b00 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/findHelpGraphicIndexByName.cpp @@ -0,0 +1,20 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/OS.func.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045D890 + int TextEditorState::findHelpGraphicIndexByName(char* param_1) + { + for (int i = 0; i < this->graphicFileCount; ++i) { + if (!MACRO_CALL(OS_Func::__stricmp)(this->graphicFileNames[i], param_1)) { + return i; + } + } + return -1; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index fa62413d4..d51251c9a 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18341,7 +18341,7 @@ SHC_3BB0A8C1_0x0045D6C0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D740 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045D890 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D890 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D8F0 | 0.0% | Pending From 130ea72a26c26703954b3679176ae949b2c1fa2f Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 10 Sep 2026 21:13:21 +0200 Subject: [PATCH 15/44] reimplement: SHC_3BB0A8C1_0x0045D8F0 100% --- .../findOrAddHelpGraphicName.cpp | 25 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/findOrAddHelpGraphicName.cpp diff --git a/src/OpenSHC/Text/TextEditorState/findOrAddHelpGraphicName.cpp b/src/OpenSHC/Text/TextEditorState/findOrAddHelpGraphicName.cpp new file mode 100644 index 000000000..4e668a43b --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/findOrAddHelpGraphicName.cpp @@ -0,0 +1,25 @@ +// disable deprecation warnings for strcpy +#pragma warning(disable : 4996) + +#include "../TextEditorState.func.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045D8F0 + int TextEditorState::findOrAddHelpGraphicName(char* param_1) + { + int graphicIndex = MACRO_CALL_MEMBER(TextEditorState_Func::findHelpGraphicIndexByName, this)(param_1); + if (graphicIndex != -1) { + return graphicIndex; + } + graphicIndex = this->graphicFileCount; + strcpy(this->graphicFileNames[graphicIndex], param_1); + if (this->graphicFileCount < 20) { + ++this->graphicFileCount; + } + return graphicIndex; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index d51251c9a..bd053e5b2 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18343,7 +18343,7 @@ SHC_3BB0A8C1_0x0045D740 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D890 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045D8F0 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D8F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D950 | 0.0% | Pending From c8f53bb72ff2db2f31c7c5e23ecbe8de3f535126 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 10 Sep 2026 21:30:24 +0200 Subject: [PATCH 16/44] reimplement: SHC_3BB0A8C1_0x0045D950 100% --- .../TextEditorState/getNextHelpSectionID.cpp | 26 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/getNextHelpSectionID.cpp diff --git a/src/OpenSHC/Text/TextEditorState/getNextHelpSectionID.cpp b/src/OpenSHC/Text/TextEditorState/getNextHelpSectionID.cpp new file mode 100644 index 000000000..dd1e12b33 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/getNextHelpSectionID.cpp @@ -0,0 +1,26 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/Globals/DAT_UserHelpDefinedData.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045D950 + int TextEditorState::getNextHelpSectionID(int param_1) + { + for (int index = 0; DAT_UserHelpDefinedData::instance.field5_0x7a124[index].unknown_0x4 != -1; ++index) { + if (DAT_UserHelpDefinedData::instance.field5_0x7a124[index].unknown_0x4 != param_1) { + continue; + } + + ++index; + if (DAT_UserHelpDefinedData::instance.field5_0x7a124[index].unknown_0x4 == -1) { + index = 0; + } + return DAT_UserHelpDefinedData::instance.field5_0x7a124[index].unknown_0x4; + } + return -1; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index bd053e5b2..b980df536 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18345,7 +18345,7 @@ SHC_3BB0A8C1_0x0045D890 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D8F0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045D950 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D950 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D990 | 0.0% | Pending From c37f34a1505783f9ea509dc17b45c952ea22ea62 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 10 Sep 2026 21:55:11 +0200 Subject: [PATCH 17/44] reimplement: SHC_3BB0A8C1_0x0045D990 100% --- .../TextEditorState/getPrevHelpSectionID.cpp | 28 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/getPrevHelpSectionID.cpp diff --git a/src/OpenSHC/Text/TextEditorState/getPrevHelpSectionID.cpp b/src/OpenSHC/Text/TextEditorState/getPrevHelpSectionID.cpp new file mode 100644 index 000000000..4e5d3ba84 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/getPrevHelpSectionID.cpp @@ -0,0 +1,28 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/Globals/DAT_UserHelpDefinedData.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045D990 + int TextEditorState::getPrevHelpSectionID(int param_1) + { + for (int index = 0; DAT_UserHelpDefinedData::instance.field5_0x7a124[index].unknown_0x4 != -1; ++index) { + if (DAT_UserHelpDefinedData::instance.field5_0x7a124[index].unknown_0x4 == param_1) { + --index; + if (index < 0) { + index = 0; + while (DAT_UserHelpDefinedData::instance.field5_0x7a124[index].unknown_0x4 != -1) { + ++index; + } + --index; + } + return DAT_UserHelpDefinedData::instance.field5_0x7a124[index].unknown_0x4; + } + } + return -1; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index b980df536..fe7ed1a29 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18347,7 +18347,7 @@ SHC_3BB0A8C1_0x0045D8F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D950 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045D990 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D990 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D9E0 | 0.0% | Pending From a4c403ad67f2dd91c03f0991d262e90622fc4aae Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 10 Sep 2026 21:58:52 +0200 Subject: [PATCH 18/44] reimplement: SHC_3BB0A8C1_0x0045D9E0 100% --- .../TextEditorState/getHelpSectionText.cpp | 20 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/getHelpSectionText.cpp diff --git a/src/OpenSHC/Text/TextEditorState/getHelpSectionText.cpp b/src/OpenSHC/Text/TextEditorState/getHelpSectionText.cpp new file mode 100644 index 000000000..a0c88560b --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/getHelpSectionText.cpp @@ -0,0 +1,20 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/Globals/DAT_UserHelpDefinedData.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045D9E0 + char* TextEditorState::getHelpSectionText(int param_1) + { + for (int index = 0; DAT_UserHelpDefinedData::instance.field5_0x7a124[index].unknown_0x4 != -1; ++index) { + if (DAT_UserHelpDefinedData::instance.field5_0x7a124[index].unknown_0x4 == param_1) { + return DAT_UserHelpDefinedData::instance.field5_0x7a124[index].text_0x0; + } + } + return NULL; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index fe7ed1a29..a8f6283e9 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18349,7 +18349,7 @@ SHC_3BB0A8C1_0x0045D950 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D990 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045D9E0 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D9E0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045DA20 | 0.0% | Pending From 55f21bc6dd56641f21f79d2100dfb54f35e65851 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 10 Sep 2026 22:03:26 +0200 Subject: [PATCH 19/44] reimplement: SHC_3BB0A8C1_0x0045DA20 100% --- .../getNextHelpColorEntryIndex.cpp | 19 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/getNextHelpColorEntryIndex.cpp diff --git a/src/OpenSHC/Text/TextEditorState/getNextHelpColorEntryIndex.cpp b/src/OpenSHC/Text/TextEditorState/getNextHelpColorEntryIndex.cpp new file mode 100644 index 000000000..98ad9021a --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/getNextHelpColorEntryIndex.cpp @@ -0,0 +1,19 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/Globals/DAT_UserHelpDefinedData.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045DA20 + int TextEditorState::getNextHelpColorEntryIndex(int param_1) + { + int newIndex = param_1 + 1; + if (DAT_UserHelpDefinedData::instance.field6_0x7a16c[newIndex].name_0x0 == NULL) { + newIndex = 0; + } + return newIndex; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index a8f6283e9..cd96647ce 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18351,7 +18351,7 @@ SHC_3BB0A8C1_0x0045D990 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D9E0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045DA20 | 0.0% | Pending +SHC_3BB0A8C1_0x0045DA20 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045DA40 | 0.0% | Pending From 56d82f19d28199ec7d326cf578cb274eaaabe182 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 10 Sep 2026 22:09:16 +0200 Subject: [PATCH 20/44] reimplement: SHC_3BB0A8C1_0x0045DA40 100% --- .../getPrevHelpColorEntryIndex.cpp | 23 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/getPrevHelpColorEntryIndex.cpp diff --git a/src/OpenSHC/Text/TextEditorState/getPrevHelpColorEntryIndex.cpp b/src/OpenSHC/Text/TextEditorState/getPrevHelpColorEntryIndex.cpp new file mode 100644 index 000000000..d3f15557e --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/getPrevHelpColorEntryIndex.cpp @@ -0,0 +1,23 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/Globals/DAT_UserHelpDefinedData.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045DA40 + int TextEditorState::getPrevHelpColorEntryIndex(int param_1) + { + --param_1; + if (param_1 < 0) { + param_1 = 0; + while (DAT_UserHelpDefinedData::instance.field6_0x7a16c[param_1].name_0x0 != NULL) { + ++param_1; + } + --param_1; + } + return param_1; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index cd96647ce..e0d050603 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18353,7 +18353,7 @@ SHC_3BB0A8C1_0x0045D9E0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045DA20 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045DA40 | 0.0% | Pending +SHC_3BB0A8C1_0x0045DA40 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045DA60 | 0.0% | Pending From 8c1577acd31c4ec9a9ee493b570e21d97381231c Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Fri, 11 Sep 2026 22:44:36 +0200 Subject: [PATCH 21/44] reimplement: SHC_3BB0A8C1_0x0045DA80 100% --- .../TextEditorState/findSoundIndexByName.cpp | 20 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/findSoundIndexByName.cpp diff --git a/src/OpenSHC/Text/TextEditorState/findSoundIndexByName.cpp b/src/OpenSHC/Text/TextEditorState/findSoundIndexByName.cpp new file mode 100644 index 000000000..f105e1de4 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/findSoundIndexByName.cpp @@ -0,0 +1,20 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/OS.func.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045DA80 + int TextEditorState::findSoundIndexByName(char* param_1) + { + for (int i = 0; i < this->soundFileCount; i = i + 1) { + if (!MACRO_CALL(OpenSHC::OS_Func::__stricmp)(this->soundFileNames[i], param_1)) { + return i; + } + } + return -1; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index e0d050603..888b2b885 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18357,7 +18357,7 @@ SHC_3BB0A8C1_0x0045DA40 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045DA60 | 0.0% | Pending -SHC_3BB0A8C1_0x0045DA80 | 0.0% | Pending +SHC_3BB0A8C1_0x0045DA80 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045DAE0 | 0.0% | Pending From f5b5d9656148b1d2bae2868a85a8479464439ac6 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Fri, 11 Sep 2026 22:53:05 +0200 Subject: [PATCH 22/44] reimplement: SHC_3BB0A8C1_0x0045DAE0 100% --- .../TextEditorState/findOrAddSoundName.cpp | 29 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/findOrAddSoundName.cpp diff --git a/src/OpenSHC/Text/TextEditorState/findOrAddSoundName.cpp b/src/OpenSHC/Text/TextEditorState/findOrAddSoundName.cpp new file mode 100644 index 000000000..154d8464b --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/findOrAddSoundName.cpp @@ -0,0 +1,29 @@ +// disable deprecation warnings for strcpy +#pragma warning(disable : 4996) + +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/Text/TextEditorState.func.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045DAE0 + int TextEditorState::findOrAddSoundName(char* param_1) + { + int index = MACRO_CALL_MEMBER(OpenSHC::Text::TextEditorState_Func::findSoundIndexByName, this)(param_1); + if (index != -1) { + return index; + } + + index = this->soundFileCount; + strcpy(this->soundFileNames[index], param_1); + this->soundFilePlayedFlags[index] = 0; + if (this->soundFileCount < 5) { + ++this->soundFileCount; + } + return index; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 888b2b885..47be1a72f 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18359,7 +18359,7 @@ SHC_3BB0A8C1_0x0045DA60 | 0.0% | Pending SHC_3BB0A8C1_0x0045DA80 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045DAE0 | 0.0% | Pending +SHC_3BB0A8C1_0x0045DAE0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045DB40 | 0.0% | Pending From 7434c6e2e982ab158fd6c3a31c2917a30756a8ef Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sat, 12 Sep 2026 20:08:33 +0200 Subject: [PATCH 23/44] reimplement: SHC_3BB0A8C1_0x0045DB40 100% --- src/OpenSHC/OS.func.hpp | 4 + src/OpenSHC/OS.hpp | 2 + src/OpenSHC/OS/OS.cpp | 11 ++ .../saveHelpFileToResource.cpp | 118 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 5 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/saveHelpFileToResource.cpp diff --git a/src/OpenSHC/OS.func.hpp b/src/OpenSHC/OS.func.hpp index 4523a0835..c11a6c39e 100644 --- a/src/OpenSHC/OS.func.hpp +++ b/src/OpenSHC/OS.func.hpp @@ -179,5 +179,9 @@ namespace OS_Func { void(__cdecl*)(int _Code), REIMPLEMENTED_CRT, Address::SHC_3BB0A8C1_0x00583D55, &OpenSHC::OS::_exit) _exit; + MACRO_FUNCTION_RESOLVER(int(__cdecl*)(FILE*, wchar_t const*, ...), REIMPLEMENTED_CRT, + Address::SHC_3BB0A8C1_0x005807A8, &OpenSHC::OS::_fwprintf) + _fwprintf; + } // namespace OS_Func } // namespace OpenSHC diff --git a/src/OpenSHC/OS.hpp b/src/OpenSHC/OS.hpp index b0cad4b80..710bea1f5 100644 --- a/src/OpenSHC/OS.hpp +++ b/src/OpenSHC/OS.hpp @@ -103,5 +103,7 @@ namespace OS { void __cdecl _exit(int _Code); + int _fwprintf(FILE* stream, wchar_t const* format, ...); + } // namespace OS } // namespace OpenSHC diff --git a/src/OpenSHC/OS/OS.cpp b/src/OpenSHC/OS/OS.cpp index 057972635..bc455be20 100644 --- a/src/OpenSHC/OS/OS.cpp +++ b/src/OpenSHC/OS/OS.cpp @@ -146,5 +146,16 @@ namespace OS { // STUB: STRONGHOLDCRUSADER 0x00583D55 void _exit(int _Code) { exit(_Code); } + // STUB: STRONGHOLDCRUSADER 0x005807A8 + int _fwprintf(FILE* stream, wchar_t const* format, ...) + { + // needed for proxy + va_list args; + va_start(args, format); + int result = vfwprintf(stream, format, args); + va_end(args); + return result; + } + } } diff --git a/src/OpenSHC/Text/TextEditorState/saveHelpFileToResource.cpp b/src/OpenSHC/Text/TextEditorState/saveHelpFileToResource.cpp new file mode 100644 index 000000000..1ae12edc8 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/saveHelpFileToResource.cpp @@ -0,0 +1,118 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/IO/ResourceManager.func.hpp" +#include "OpenSHC/OS.func.hpp" +#include "OpenSHC/string-literals.hpp" + +#include "OpenSHC/Globals/DAT_ResourceManager.hpp" +#include "OpenSHC/Globals/DAT_UserHelpDefinedData.hpp" + +namespace OpenSHC { +namespace Text { + + // TODO: Replace L strings with references from a file + + // FUNCTION: STRONGHOLDCRUSADER 0x0045DB40 + void TextEditorState::saveHelpFileToResource() + { + MACRO_CALL_MEMBER(IO::ResourceManager_Func::resolveResourceFileName, DAT_ResourceManager::ptr)( + IO::FRT_HELP, DAT_UserHelpDefinedData::instance.HelpSections[this->currentHelpSectionID]); + char const* const _Filename = MACRO_CALL_MEMBER( + IO::ResourceManager_Func::getFileNameOfCurrentActiveResource, DAT_ResourceManager::ptr)(); + FILE* _File = MACRO_CALL(OS_Func::_fopen)(_Filename, s_wb_005a5510); + if (!_File) { + return; + } + wchar_t const utf16bom = L'\uFEFF'; + MACRO_CALL(OS_Func::_fwrite)((void*)&utf16bom, sizeof(wchar_t), 1, _File); + + MACRO_CALL(OS_Func::_fwprintf)(_File, L"
\n"); + for (int i = 0; i < this->graphicFileCount; ++i) { + MACRO_CALL(OS_Func::_fwprintf)(_File, L"\n", this->graphicFileNames[i]); + } + MACRO_CALL(OS_Func::_fwprintf)(_File, L"<\\HEADER>\n"); + MACRO_CALL(OS_Func::_fwprintf)(_File, L"\n"); + + for (int i = 0; this->DAT_PointerToTemporaryTextMemory[i];) { + HelpTextToken const switchValue = (HelpTextToken)this->DAT_PointerToTemporaryTextMemory[i]; + i += 1; + switch (switchValue) { + case HTT_PIC: + MACRO_CALL(OS_Func::_fwprintf)(_File, L"DAT_PointerToTemporaryTextMemory[i]); + i += 1; + switch ((HelpTextPicturePositionToken)this->DAT_PointerToTemporaryTextMemory[i]) { + case HTT_PIC_LEFT: + MACRO_CALL(OS_Func::_fwprintf)(_File, L"LEFT>"); + i += 2; + break; + case HTT_PIC_RIGHT: + MACRO_CALL(OS_Func::_fwprintf)(_File, L"RIGHT>"); + i += 2; + break; + case HTT_PIC_CENTRE: + MACRO_CALL(OS_Func::_fwprintf)(_File, L"CENTRE>"); + i += 2; + break; + case HTT_PIC_HERE: + MACRO_CALL(OS_Func::_fwprintf)(_File, L"HERE>"); + default: + i += 2; + break; + } + break; + case HTT_FONT: + MACRO_CALL(OS_Func::_fwprintf)(_File, L"", this->DAT_PointerToTemporaryTextMemory[i]); + i += 2; + break; + case HTT_COLOUR: + MACRO_CALL(OS_Func::_fwprintf)(_File, L"", this->DAT_PointerToTemporaryTextMemory[i]); + i += 2; + break; + case HTT_LINKCOLOUR: + MACRO_CALL(OS_Func::_fwprintf)(_File, L"", this->DAT_PointerToTemporaryTextMemory[i]); + i += 2; + break; + case HTT_LINK: + MACRO_CALL(OS_Func::_fwprintf)(_File, L"", + DAT_UserHelpDefinedData::instance.HelpSections[this->DAT_PointerToTemporaryTextMemory[i]]); + i += 2; + break; + case HTT_INCLUDE: + MACRO_CALL(OS_Func::_fwprintf)(_File, L"", + DAT_UserHelpDefinedData::instance.HelpSections[this->DAT_PointerToTemporaryTextMemory[i]]); + i += 2; + break; + case HTT_ENDLINK: + MACRO_CALL(OS_Func::_fwprintf)(_File, L"<\\LINK>"); + break; + case HTT_NEWPARAGRAPH: + MACRO_CALL(OS_Func::_fwprintf)(_File, L"\n\n"); + break; + case HTT_CENTRE: + MACRO_CALL(OS_Func::_fwprintf)(_File, L""); + break; + case HTT_ENDCENTRE: + MACRO_CALL(OS_Func::_fwprintf)(_File, L"<\\CENTRE>"); + break; + case HTT_SOUND: + MACRO_CALL(OS_Func::_fwprintf)(_File, L"", this->DAT_PointerToTemporaryTextMemory[i]); + i += 2; + break; + case HTT_STRING: + MACRO_CALL(OS_Func::_fwprintf)(_File, L"", this->DAT_PointerToTemporaryTextMemory[i]); + i += 2; + break; + default: + MACRO_CALL(OS_Func::_fwprintf)(_File, L"%c", (wchar_t)switchValue); + break; + } + } + + MACRO_CALL(OS_Func::_fwprintf)(_File, L"\n<\\BODY>\n"); + MACRO_CALL(OS_Func::_fclose)(_File); + } + +#undef MACRO_TEXT_ACCESS + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 47be1a72f..e58142a89 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18361,7 +18361,7 @@ SHC_3BB0A8C1_0x0045DA80 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045DAE0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045DB40 | 0.0% | Pending +SHC_3BB0A8C1_0x0045DB40 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045DDF4 | 0.0% | Pending From beb3ad76bc7a1d6d08cf97bd5316a1b590d42e31 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sat, 12 Sep 2026 21:38:53 +0200 Subject: [PATCH 24/44] reimplement: SHC_3BB0A8C1_0x0045F080 and SHC_3BB0A8C1_0x0045F0D0 100% --- .../Text/TextEditorState/helpToken.cpp | 39 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 4 +- 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 src/OpenSHC/Text/TextEditorState/helpToken.cpp diff --git a/src/OpenSHC/Text/TextEditorState/helpToken.cpp b/src/OpenSHC/Text/TextEditorState/helpToken.cpp new file mode 100644 index 000000000..6931a374e --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/helpToken.cpp @@ -0,0 +1,39 @@ +#include "../TextEditorState.func.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045F080 + int TextEditorState::helpToken_getHelpTokenAdvanceLength(HelpTextToken token) + { + switch (token) { + case HTT_PIC: + return 4; + + case HTT_FONT: + case HTT_COLOUR: + case HTT_LINK: + case HTT_LINKCOLOUR: + case HTT_SOUND: + case HTT_STRING: + case HTT_INCLUDE: + return 3; + + default: + return 1; + } + } + + // FUNCTION: STRONGHOLDCRUSADER 0x0045F0D0 + void TextEditorState::helpToken_insertSpaceForHelpTextToken(HelpTextToken token) + { + int tokenLength = MACRO_CALL_MEMBER(TextEditorState_Func::helpToken_getHelpTokenAdvanceLength, this)(token); + for (int textIndex = this->customHelpTextLength; textIndex >= this->activeHelpHotspotIndex; --textIndex) { + this->DAT_PointerToTemporaryTextMemory[textIndex + tokenLength] + = this->DAT_PointerToTemporaryTextMemory[textIndex]; + } + this->customHelpTextLength += tokenLength; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index e58142a89..a59ea814d 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18709,7 +18709,7 @@ SHC_3BB0A8C1_0x0045EF84 | 0.0% | Pending SHC_3BB0A8C1_0x0045EF90 | 0.0% | Pending -SHC_3BB0A8C1_0x0045F080 | 0.0% | Pending +SHC_3BB0A8C1_0x0045F080 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045F0B4 | 0.0% | Pending @@ -18745,7 +18745,7 @@ SHC_3BB0A8C1_0x0045F0CC | 0.0% | Pending SHC_3BB0A8C1_0x0045F0CD | 0.0% | Pending -SHC_3BB0A8C1_0x0045F0D0 | 0.0% | Pending +SHC_3BB0A8C1_0x0045F0D0 | 100.0% | Reimplemented, requires SHC_3BB0A8C1_0x0045F130 active SHC_3BB0A8C1_0x0045F120 | 100.0% | Reimplemented From 67c28dad98e8cef2f3e3d7e224e1b598ace18cd5 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sat, 12 Sep 2026 22:08:50 +0200 Subject: [PATCH 25/44] reimplement: SHC_3BB0A8C1_0x0045F240 100% --- .../closeHelpDialogAndReturnToMenu.cpp | 78 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/closeHelpDialogAndReturnToMenu.cpp diff --git a/src/OpenSHC/Text/TextEditorState/closeHelpDialogAndReturnToMenu.cpp b/src/OpenSHC/Text/TextEditorState/closeHelpDialogAndReturnToMenu.cpp new file mode 100644 index 000000000..04a89a421 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/closeHelpDialogAndReturnToMenu.cpp @@ -0,0 +1,78 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/Game/GameCore.func.hpp" +#include "OpenSHC/OS.func.hpp" +#include "OpenSHC/UI/MenuModalComposition.func.hpp" +#include "OpenSHC/Util/WideCharMultiByteState.func.hpp" + +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_MenuModalComposition1.hpp" +#include "OpenSHC/Globals/DAT_MenuView_TriggerPrepare.hpp" +#include "OpenSHC/Globals/DAT_WideCharMultiByteState.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045F240 + void TextEditorState::closeHelpDialogAndReturnToMenu() + { + if (!this->isDialogStateInitialized) { + return; + } + MACRO_CALL_MEMBER(TextEditorState_Func::resetHelpStateFields, this)(); + this->isDialogStateInitialized = 0; + + if (this->isCustomTextMode) { + MACRO_CALL_MEMBER(UI::MenuModalComposition_Func::activateModalDialog, DAT_MenuModalComposition1::ptr)( + UI::Enums::MMT_NONE, FALSE); + for (int i = 0; i < 20; ++i) { + this->intArray1[i] = 0; + } + if (this->customHelpTextPointer) { + if (!this->isCustomHelpTextWide) { + MACRO_CALL_MEMBER(Util::WideCharMultiByteState_Func::wideCharToMultiByteWithSize, + DAT_WideCharMultiByteState::ptr)(this->customHelpTextPointer, + this->DAT_PointerToTemporaryTextMemory, this->customHelpTextBufferSize); + } else { + MACRO_CALL(OS_Func::_wcsncpy)((wchar_t*)this->customHelpTextPointer, + this->DAT_PointerToTemporaryTextMemory, this->customHelpTextBufferSize); + } + } + DAT_MenuView_TriggerPrepare::instance = TRUE; + + } else if (this->helpDialogVariant == 0) { + + if (this->savedMenuViewType == UI::Enums::MVT_BUILD_MENU) { + DAT_GameCore::instance.buildmenuMenuTabToSwitchTo.tabType = this->savedActiveMenuTab; + MACRO_CALL_MEMBER(Game::GameCore_Func::switchToMenuView, DAT_GameCore::ptr)( + (UI::Enums::MenuViewType)this->savedMenuViewType, 0); + + } else if (this->savedMenuViewType == UI::Enums::MVT_MAP_EDITOR_LANDSCAPING) { + DAT_GameCore::instance.landscapingmenuMenuTabToSwitchTo = this->savedActiveMenuTab; + MACRO_CALL_MEMBER(Game::GameCore_Func::switchToMenuView, DAT_GameCore::ptr)( + (UI::Enums::MenuViewType)this->savedMenuViewType, 0); + + } else if (this->savedMenuViewType == UI::Enums::MVT_BUILDING_AND_STATUS_MENU) { + DAT_GameCore::instance.buildingandstatusmenuMenuTabToSwitchTo = this->savedActiveMenuTab; + MACRO_CALL_MEMBER(Game::GameCore_Func::switchToMenuView, DAT_GameCore::ptr)( + (UI::Enums::MenuViewType)this->savedMenuViewType, 0); + + } else { + DAT_GameCore::instance.menuTabToSwitchTo.tabType = this->savedActiveMenuTab; + MACRO_CALL_MEMBER(Game::GameCore_Func::switchToMenuView, DAT_GameCore::ptr)( + (UI::Enums::MenuViewType)this->savedMenuViewType, 0); + } + + } else { + MACRO_CALL_MEMBER(UI::MenuModalComposition_Func::activateModalDialog, DAT_MenuModalComposition1::ptr)( + UI::Enums::MMT_NONE, FALSE); + for (int i = 0; i < 20; ++i) { + this->intArray1[i] = 0; + } + } + + this->helpDialogVariant = 0; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index a59ea814d..c0c18c883 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18751,7 +18751,7 @@ SHC_3BB0A8C1_0x0045F120 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045F130 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045F240 | 0.0% | Pending +SHC_3BB0A8C1_0x0045F240 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045F470 | 0.0% | Pending From 00fdfc159e93c3616faa58bb408dd3e3af559b62 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 13 Sep 2026 00:11:00 +0200 Subject: [PATCH 26/44] reimplement: SHC_3BB0A8C1_0x0045F470 100% --- .../TextEditorState/readCrusaderHelpHlp.cpp | 66 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/readCrusaderHelpHlp.cpp diff --git a/src/OpenSHC/Text/TextEditorState/readCrusaderHelpHlp.cpp b/src/OpenSHC/Text/TextEditorState/readCrusaderHelpHlp.cpp new file mode 100644 index 000000000..1f6bf9c84 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/readCrusaderHelpHlp.cpp @@ -0,0 +1,66 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/IO/ResourceManager.func.hpp" +#include "OpenSHC/OS.func.hpp" +#include "OpenSHC/Util/WideCharMultiByteState.func.hpp" +#include "OpenSHC/string-literals.hpp" + +#include "OpenSHC/Globals/DAT_ResourceManager.hpp" +#include "OpenSHC/Globals/DAT_WideCharMultiByteState.hpp" + +namespace OpenSHC { +namespace Text { + + // TODO: Replace L-strings with str-ptr + + // FUNCTION: STRONGHOLDCRUSADER 0x0045F470 + FILE* TextEditorState::readCrusaderHelpHlp(LPCSTR searchedPart) + { + this->helpSectionParseSucceeded = FALSE; + + WCHAR searchedPartWide[200]; + MACRO_CALL_MEMBER(Util::WideCharMultiByteState_Func::multiByteToWideCharacter, DAT_WideCharMultiByteState::ptr)( + searchedPartWide, searchedPart); + MACRO_CALL_MEMBER(IO::ResourceManager_Func::resolveResourceFileName, DAT_ResourceManager::ptr)( + IO::FRT_HELP, s_crusader_help_hlp_005a5620); + + char const* const _Filename = MACRO_CALL_MEMBER( + IO::ResourceManager_Func::getFileNameOfCurrentActiveResource, DAT_ResourceManager::ptr)(); + FILE* _File = MACRO_CALL(OS_Func::_fopen)(_Filename, s_rb_005a4e18); + if (_File) { + MACRO_CALL(OS_Func::_fseek)(_File, 2, FILE_BEGIN); // Skip BOM? + + int wideChar; + while (true) { + wideChar = MACRO_CALL(OS_Func::_fgetwc)(_File); + if (wideChar != L'<') { + if (wideChar == WEOF) { + return _File; + } + continue; + } + wchar_t* hlpPart = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)(_File); + if (!hlpPart || MACRO_CALL(OS_Func::__wcsicmp)(L"section", hlpPart)) { + continue; + } + wchar_t* sectionHlpPart = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)(_File); + if (!sectionHlpPart || MACRO_CALL(OS_Func::__wcsicmp)(searchedPartWide, sectionHlpPart)) { + continue; + } + break; + }; + + do { + wideChar = MACRO_CALL(OS_Func::_fgetwc)(_File); + if (wideChar == L'>') { + this->helpSectionParseSucceeded = TRUE; + break; + } + } while (wideChar != WEOF); + } + + return _File; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c0c18c883..bc9e75068 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18753,7 +18753,7 @@ SHC_3BB0A8C1_0x0045F130 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045F240 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045F470 | 0.0% | Pending +SHC_3BB0A8C1_0x0045F470 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045F580 | 0.0% | Pending From 6308b41708e7efbd70933331f63f91205b88b9b0 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 13 Sep 2026 00:20:31 +0200 Subject: [PATCH 27/44] reimplement: SHC_3BB0A8C1_0x0045F580 100% --- .../TextEditorState/loadAndParseHelpFile.cpp | 22 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/loadAndParseHelpFile.cpp diff --git a/src/OpenSHC/Text/TextEditorState/loadAndParseHelpFile.cpp b/src/OpenSHC/Text/TextEditorState/loadAndParseHelpFile.cpp new file mode 100644 index 000000000..7a0e6bf84 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/loadAndParseHelpFile.cpp @@ -0,0 +1,22 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/OS.func.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x0045F580 + BOOLEnum TextEditorState::loadAndParseHelpFile(char const* searchedPart) + { + FILE* _File = MACRO_CALL_MEMBER(TextEditorState_Func::readCrusaderHelpHlp, this)(searchedPart); + if (_File) { + MACRO_CALL(OS_Func::_fclose)(_File); + if (this->helpSectionParseSucceeded) { + return TRUE; + } + } + return FALSE; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index bc9e75068..78fedf7d0 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18755,7 +18755,7 @@ SHC_3BB0A8C1_0x0045F240 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045F470 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045F580 | 0.0% | Pending +SHC_3BB0A8C1_0x0045F580 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045F5B0 | 0.0% | Pending From d7a520cd01f5dc206e59517ae767478bcf8081fd Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 13 Sep 2026 20:57:24 +0200 Subject: [PATCH 28/44] reimplement: SHC_3BB0A8C1_0x0045F5B0 99% --- IMPLEMENTATION_CHEAT_SHEET.md | 1 + src/OpenSHC/OS.func.hpp | 4 + src/OpenSHC/OS.hpp | 2 + src/OpenSHC/OS/OS.cpp | 3 + src/OpenSHC/Text/TextEditorState/parseHlp.cpp | 352 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 6 files changed, 363 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/parseHlp.cpp diff --git a/IMPLEMENTATION_CHEAT_SHEET.md b/IMPLEMENTATION_CHEAT_SHEET.md index 087740438..6a19c9856 100644 --- a/IMPLEMENTATION_CHEAT_SHEET.md +++ b/IMPLEMENTATION_CHEAT_SHEET.md @@ -319,6 +319,7 @@ SEC_RNG::ptr->currentNumber1 % 4 } ``` Consider this, should a switch structure arise with strange fallthrough and loops, like SHC_3BB0A8C1_0x004870B0. +- Non-consecutive case labels will likely result in a mixture of if-else and switch cases, sometimes even only if-elses. These are hard to spot. One sign, outside of weird decompiler artifacts, is that logic might be put inside a lot of conditions that feature only a single variable. Another can be a lot of GOTOs. - Write a comparison with its operands in the order the assembly shows. `if (a > b)` gives `cmp eax, ecx` where `if (b < a)` gives `cmp ecx, eax`; flipping seven `iVar6 < lag[n].average1` to `lag[n].average1 > iVar6` took diff --git a/src/OpenSHC/OS.func.hpp b/src/OpenSHC/OS.func.hpp index c11a6c39e..1be1b6d1e 100644 --- a/src/OpenSHC/OS.func.hpp +++ b/src/OpenSHC/OS.func.hpp @@ -183,5 +183,9 @@ namespace OS_Func { Address::SHC_3BB0A8C1_0x005807A8, &OpenSHC::OS::_fwprintf) _fwprintf; + MACRO_FUNCTION_RESOLVER( + long(__cdecl*)(wchar_t const*), REIMPLEMENTED_CRT, Address::SHC_3BB0A8C1_0x00580C0B, &OpenSHC::OS::__wtol) + __wtol; + } // namespace OS_Func } // namespace OpenSHC diff --git a/src/OpenSHC/OS.hpp b/src/OpenSHC/OS.hpp index 710bea1f5..de952d160 100644 --- a/src/OpenSHC/OS.hpp +++ b/src/OpenSHC/OS.hpp @@ -105,5 +105,7 @@ namespace OS { int _fwprintf(FILE* stream, wchar_t const* format, ...); + long __wtol(wchar_t const* str); + } // namespace OS } // namespace OpenSHC diff --git a/src/OpenSHC/OS/OS.cpp b/src/OpenSHC/OS/OS.cpp index bc455be20..e300ed41a 100644 --- a/src/OpenSHC/OS/OS.cpp +++ b/src/OpenSHC/OS/OS.cpp @@ -157,5 +157,8 @@ namespace OS { return result; } + // STUB: STRONGHOLDCRUSADER 0x00580C0B + long __wtol(wchar_t const* str) { return _wtol(str); } + } } diff --git a/src/OpenSHC/Text/TextEditorState/parseHlp.cpp b/src/OpenSHC/Text/TextEditorState/parseHlp.cpp new file mode 100644 index 000000000..792efc700 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/parseHlp.cpp @@ -0,0 +1,352 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/OS.func.hpp" +#include "OpenSHC/UI/Rendering/TextureRenderCore.func.hpp" +#include "OpenSHC/Util/WideCharMultiByteState.func.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TextEditorState.hpp" +#include "OpenSHC/Globals/DAT_TextureRenderCoreObject.hpp" +#include "OpenSHC/Globals/DAT_UserHelpDefinedData.hpp" +#include "OpenSHC/Globals/DAT_WideCharMultiByteState.hpp" + +namespace OpenSHC { +namespace Text { + + // TODO: fix L-strings + + // FUNCTION: STRONGHOLDCRUSADER 0x0045F5B0 + void TextEditorState::parseHlp() + { + FILE* filePointer[4]; + int graphicIndexes[4][100]; + + int const currentHelpSectionID = this->currentHelpSectionID; + int textMemIndex = 0; + + BOOL headerActive = FALSE; + BOOL bodyActive = FALSE; + int _filePointerIndex = 0; + + int loadedGraphics[4] = { 0, 0, 0, 0 }; + this->customHelpTextLength = 0; + MACRO_CALL_MEMBER(IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 40000, NULL, this->DAT_PointerToTemporaryTextMemory); + filePointer[0] = MACRO_CALL_MEMBER(TextEditorState_Func::readCrusaderHelpHlp, this)( + DAT_UserHelpDefinedData::instance.HelpSections[currentHelpSectionID]); + if (!filePointer[0]) { + return; + } + + while (_filePointerIndex >= 0) { + BOOL closeFile = FALSE; + while (!closeFile) { + int _wchar = MACRO_CALL(OS_Func::_fgetwc)(filePointer[_filePointerIndex]); + switch (_wchar) { + case '\n': + case '\r': + continue; + + case '<': { + wchar_t* hlpTag + = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)(filePointer[_filePointerIndex]); + if (hlpTag) { + if (!MACRO_CALL(OS_Func::__wcsicmp)(L"header", hlpTag)) { + headerActive = TRUE; + continue; + + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"\\header", hlpTag)) { + headerActive = FALSE; + continue; + + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"body", hlpTag)) { + bodyActive = TRUE; + continue; + + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"\\body", hlpTag)) { + bodyActive = FALSE; + continue; + + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"loadpic", hlpTag)) { + if (headerActive) { + wchar_t* resourceName = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( + filePointer[_filePointerIndex]); + if (resourceName) { + char resourceNameChars[1000]; + MACRO_CALL_MEMBER(Util::WideCharMultiByteState_Func::wideCharToMultiByteComplete, + DAT_WideCharMultiByteState::ptr)(resourceNameChars, resourceName); + + bool validPic = true; + if (!MACRO_CALL_MEMBER( + UI::Rendering::TextureRenderCore_Func::checkGfxResourceExists, + DAT_TextureRenderCoreObject::ptr)(resourceNameChars)) { + validPic = false; + } else if (!MACRO_CALL(OS_Func::__stricmp)( + resourceNameChars, "st99_dog_cage.tgx")) { + validPic = false; + } + if (!validPic) { + graphicIndexes[_filePointerIndex][loadedGraphics[_filePointerIndex]++] = -1; + } else { + graphicIndexes[_filePointerIndex][loadedGraphics[_filePointerIndex]++] + = MACRO_CALL_MEMBER(TextEditorState_Func::findOrAddHelpGraphicName, this)( + resourceNameChars); + } + continue; + } + } + + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"pic", hlpTag)) { + if (bodyActive) { + wchar_t* picId = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( + filePointer[_filePointerIndex]); + if (picId) { + if (MACRO_CALL(OS_Func::__wtol)(picId) < loadedGraphics[_filePointerIndex]) { + if (graphicIndexes[_filePointerIndex][MACRO_CALL(OS_Func::__wtol)(picId)] + != -1) { + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_PIC; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] + = graphicIndexes[_filePointerIndex][MACRO_CALL(OS_Func::__wtol)(picId)]; + wchar_t* picPosition = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, + this)(filePointer[_filePointerIndex]); + if (!picPosition) { + closeFile = TRUE; + } else { + if (!MACRO_CALL(OS_Func::__wcsicmp)(L"left", picPosition)) { + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] + = HTT_PIC_LEFT; + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"right", picPosition)) { + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] + = HTT_PIC_RIGHT; + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"centre", picPosition)) { + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] + = HTT_PIC_CENTRE; + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"here", picPosition)) { + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] + = HTT_PIC_HERE; + } + } + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_PIC; + continue; + } + } + if (!MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( + filePointer[_filePointerIndex])) { + closeFile = TRUE; + } + continue; + } + } + + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"font", hlpTag)) { + if (bodyActive) { + wchar_t* fontId = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( + filePointer[_filePointerIndex]); + if (fontId) { + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_FONT; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] + = (short)MACRO_CALL(OS_Func::__wtol)(fontId); + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_FONT; + continue; + } + } + + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"colour", hlpTag)) { + if (bodyActive) { + wchar_t* colorId = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( + filePointer[_filePointerIndex]); + if (colorId) { + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_COLOUR; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] + = (short)MACRO_CALL(OS_Func::__wtol)(colorId); + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_COLOUR; + continue; + } + } + + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"linkcolour", hlpTag)) { + if (bodyActive) { + wchar_t* linkColorId = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( + filePointer[_filePointerIndex]); + if (linkColorId) { + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_LINKCOLOUR; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] + = (short)MACRO_CALL(OS_Func::__wtol)(linkColorId); + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_LINKCOLOUR; + continue; + } + } + + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"link", hlpTag)) { + if (bodyActive) { + wchar_t* linkName = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( + filePointer[_filePointerIndex]); + if (linkName) { + char linkNameChars[1000]; + MACRO_CALL_MEMBER(Util::WideCharMultiByteState_Func::wideCharToMultiByteComplete, + DAT_WideCharMultiByteState::ptr)(linkNameChars, linkName); + int const helpSectionIndex = MACRO_CALL_MEMBER( + TextEditorState_Func::findOrAddHelpSectionName, this)(linkNameChars); + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_LINK; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = helpSectionIndex; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_LINK; + continue; + } + } + + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"\\link", hlpTag)) { + if (bodyActive) { + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_ENDLINK; + continue; + } + + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"newparagraph", hlpTag)) { + if (bodyActive) { + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_NEWPARAGRAPH; + continue; + } + + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"centre", hlpTag)) { + if (bodyActive) { + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_CENTRE; + continue; + } + + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"\\centre", hlpTag)) { + if (bodyActive) { + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_ENDCENTRE; + continue; + } + + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"sound", hlpTag)) { + if (bodyActive) { + wchar_t* soundName = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( + filePointer[_filePointerIndex]); + if (soundName) { + char soundNameChars[1000]; + MACRO_CALL_MEMBER(Util::WideCharMultiByteState_Func::wideCharToMultiByteComplete, + DAT_WideCharMultiByteState::ptr)(soundNameChars, soundName); + int const soundIndex = MACRO_CALL_MEMBER( + TextEditorState_Func::findOrAddSoundName, this)(soundNameChars); + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_SOUND; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = soundIndex; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_SOUND; + continue; + } + } + + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"include", hlpTag)) { + if (bodyActive) { + if (DAT_TextEditorState::instance.useAlternateHelpTab) { + wchar_t* includeName = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( + filePointer[_filePointerIndex]); + if (includeName) { + char includeNameChars[1000]; + MACRO_CALL_MEMBER( + Util::WideCharMultiByteState_Func::wideCharToMultiByteComplete, + DAT_WideCharMultiByteState::ptr)(includeNameChars, includeName); + int const helpSectionIndex = MACRO_CALL_MEMBER( + TextEditorState_Func::findOrAddHelpSectionName, this)(includeNameChars); + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_INCLUDE; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = helpSectionIndex; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_INCLUDE; + continue; + } + } else { + wchar_t* includeName = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( + filePointer[_filePointerIndex]); + if (includeName) { + char includeNameChars[1000]; + MACRO_CALL_MEMBER( + Util::WideCharMultiByteState_Func::wideCharToMultiByteComplete, + DAT_WideCharMultiByteState::ptr)(includeNameChars, includeName); + int sectionId = MACRO_CALL_MEMBER( + TextEditorState_Func::findOrAddHelpSectionName, this)(includeNameChars); + ++_filePointerIndex; + bodyActive = FALSE; + headerActive = FALSE; + loadedGraphics[_filePointerIndex] = 0; + filePointer[_filePointerIndex] + = MACRO_CALL_MEMBER(TextEditorState_Func::readCrusaderHelpHlp, this)( + DAT_UserHelpDefinedData::instance.HelpSections[sectionId]); + continue; + } + } + } + + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"string", hlpTag)) { + if (bodyActive) { + wchar_t* stringId = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( + filePointer[_filePointerIndex]); + if (stringId) { + if (this->helpDialogVariant) { + long const textIndex = MACRO_CALL(OS_Func::__wtol)(stringId); + + if (this->intArray1[textIndex]) { + int i = 0; + // Mismatch: wrong order of ptr access addition + while (this->intArray1[textIndex][i]) { + wchar_t const ch = this->intArray1[textIndex][i++]; + if (ch == L'\n') { + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] + = HTT_NEWPARAGRAPH; + } else if (ch >= L' ') { + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = ch; + } + } + } + + } else { + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_STRING; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] + = (short)MACRO_CALL(OS_Func::__wtol)(stringId); + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_STRING; + } + continue; + } + } + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"\\section", hlpTag)) { + closeFile = TRUE; + continue; + } else { + continue; + } + } + + closeFile = TRUE; + continue; + } + + case L'\u2019': // ’ + _wchar = L'`'; + break; + + case L'\u201C': // “ + case L'\u201D': // ” + _wchar = L'"'; + break; + + case WEOF: + closeFile = TRUE; + continue; + + default: + break; + } + + if (bodyActive) { + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = _wchar; + } + }; + + MACRO_CALL(OS_Func::_fclose)(filePointer[_filePointerIndex]); + bodyActive = TRUE; + headerActive = FALSE; + --_filePointerIndex; + } + this->customHelpTextLength = textMemIndex; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 78fedf7d0..5ba701b3f 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18757,7 +18757,7 @@ SHC_3BB0A8C1_0x0045F470 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045F580 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045F5B0 | 0.0% | Pending +SHC_3BB0A8C1_0x0045F5B0 | 99.0% | Reimplemented, two cases where an "edx + ecx" is flipped to "ecx + edx" SHC_3BB0A8C1_0x0045FDC0 | 0.0% | Pending From 64faf8fb29fa8ee981314eac1f01aa0373f004de Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 17 Sep 2026 15:29:18 +0200 Subject: [PATCH 29/44] reimplement: SHC_3BB0A8C1_0x004614D0 100% --- src/OpenSHC/Text/TextEditorState.hpp | 6 +++++ .../initializeAndLayoutHelpText.cpp | 22 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/initializeAndLayoutHelpText.cpp diff --git a/src/OpenSHC/Text/TextEditorState.hpp b/src/OpenSHC/Text/TextEditorState.hpp index 5c547d91c..13440b205 100644 --- a/src/OpenSHC/Text/TextEditorState.hpp +++ b/src/OpenSHC/Text/TextEditorState.hpp @@ -20,6 +20,12 @@ namespace OpenSHC { namespace Text { + struct LineLayout { + short unknown0; + short unknown1; + short unknown2; + }; + using OpenSHC::Text::ImageHotspot; using OpenSHC::Text::LineLayout; using OpenSHC::Text::Enums::HelpTextToken; diff --git a/src/OpenSHC/Text/TextEditorState/initializeAndLayoutHelpText.cpp b/src/OpenSHC/Text/TextEditorState/initializeAndLayoutHelpText.cpp new file mode 100644 index 000000000..44b86a79c --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/initializeAndLayoutHelpText.cpp @@ -0,0 +1,22 @@ +#include "../TextEditorState.func.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x004614D0 + void TextEditorState::initializeAndLayoutHelpText() + { + for (int i = 0; i < 20000; ++i) { + this->lineLayoutTable[i].unknown0 = 25; + this->lineLayoutTable[i].unknown1 = this->dialogContentHeight - 25; + this->lineLayoutTable[i].unknown2 = 0; + } + for (int i = 0; i < 4; ++i) { + this->lineLayoutTable[i].unknown0 = -1; + } + this->imageHotspotCount = 0; + while (!MACRO_CALL_MEMBER(TextEditorState_Func::processHelpRichTextTokens, this)(0)) {}; + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 5ba701b3f..e37e588e4 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18827,7 +18827,7 @@ SHC_3BB0A8C1_0x004613D4 | 0.0% | Pending SHC_3BB0A8C1_0x004613E0 | 0.0% | Pending -SHC_3BB0A8C1_0x004614D0 | 0.0% | Pending +SHC_3BB0A8C1_0x004614D0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004614F0 | 0.0% | Pending From 427813f631b4e65d5c53d70113197fda4de6e258 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 17 Sep 2026 15:37:25 +0200 Subject: [PATCH 30/44] reimplement: SHC_3BB0A8C1_0x004613E0 100% --- .../TextEditorState/setTextRenderingLogic.cpp | 55 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/setTextRenderingLogic.cpp diff --git a/src/OpenSHC/Text/TextEditorState/setTextRenderingLogic.cpp b/src/OpenSHC/Text/TextEditorState/setTextRenderingLogic.cpp new file mode 100644 index 000000000..72ef3128d --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/setTextRenderingLogic.cpp @@ -0,0 +1,55 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/UI/Rendering/TextureRenderCore.func.hpp" + +#include "OpenSHC/Globals/DAT_PencilRenderCore.hpp" +#include "OpenSHC/Globals/DAT_TextManagerObject.hpp" +#include "OpenSHC/Globals/DAT_TextureRenderCoreObject.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x004613E0 + void TextEditorState::setTextRenderingLogic() + { + if (this->helpDialogVariant != 1) { + MACRO_CALL_MEMBER(UI::Rendering::TextureRenderCore_Func::setRenderingRect, + DAT_TextureRenderCoreObject::ptr)(this->dialogContentX, this->dialogContentY, + this->dialogContentHeight + this->dialogContentX, this->dialogContentWidth + this->dialogContentY); + MACRO_CALL_MEMBER(UI::Rendering::TextureRenderCore_Func::setScreenMenuSurfaceHeightRange, + DAT_TextureRenderCoreObject::ptr)( + this->dialogContentY, this->dialogContentWidth + this->dialogContentY); + DAT_TextureRenderCoreObject::instance.drawBufferChoiceValue = Rendering::Enums::RT_SCREEN_MENU; + } else { + MACRO_CALL_MEMBER(UI::Rendering::TextureRenderCore_Func::setRenderingRect, + DAT_TextureRenderCoreObject::ptr)(this->dialogContentX, this->dialogContentY, + this->dialogContentHeight + this->dialogContentX, this->dialogContentWidth + this->dialogContentY); + MACRO_CALL_MEMBER( + UI::Rendering::TextureRenderCore_Func::setMapSurfaceHeightRange, DAT_TextureRenderCoreObject::ptr)( + this->dialogContentY, this->dialogContentWidth + this->dialogContentY); + DAT_TextManagerObject::instance.textSurfaceTarget = Rendering::Enums::RT_MAP_GAME; + DAT_PencilRenderCore::instance.surfaceTarget = Rendering::Enums::RT_MAP_GAME; + DAT_TextureRenderCoreObject::instance.currentRenderSurfaceIdentifierUnk_0x8 = Rendering::Enums::RT_MAP_GAME; + } + MACRO_CALL_MEMBER(TextEditorState_Func::processHelpRichTextTokens, this)(TRUE); + MACRO_CALL_MEMBER(TextEditorState_Func::renderHelpImageHotspots, this)(); + if (this->helpDialogVariant != 1) { + DAT_TextureRenderCoreObject::instance.drawBufferChoiceValue = Rendering::Enums::RT_MAP_GAME; + MACRO_CALL_MEMBER(UI::Rendering::TextureRenderCore_Func::setScreenMenuSurfaceHeightRangeToResolution, + DAT_TextureRenderCoreObject::ptr)(); + MACRO_CALL_MEMBER(UI::Rendering::TextureRenderCore_Func::setRenderingRectToGameResolution, + DAT_TextureRenderCoreObject::ptr)(); + } else { + MACRO_CALL_MEMBER( + UI::Rendering::TextureRenderCore_Func::setMapSurfaceHeightRangeUnk, DAT_TextureRenderCoreObject::ptr)(); + MACRO_CALL_MEMBER(UI::Rendering::TextureRenderCore_Func::setRenderingRectToGameResolution, + DAT_TextureRenderCoreObject::ptr)(); + DAT_TextManagerObject::instance.textSurfaceTarget = Rendering::Enums::RT_SCREEN_MENU; + DAT_PencilRenderCore::instance.surfaceTarget = Rendering::Enums::RT_SCREEN_MENU; + DAT_TextureRenderCoreObject::instance.currentRenderSurfaceIdentifierUnk_0x8 + = Rendering::Enums::RT_SCREEN_MENU; + } + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index e37e588e4..f6691c395 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18825,7 +18825,7 @@ SHC_3BB0A8C1_0x004613D0 | 0.0% | Pending SHC_3BB0A8C1_0x004613D4 | 0.0% | Pending -SHC_3BB0A8C1_0x004613E0 | 0.0% | Pending +SHC_3BB0A8C1_0x004613E0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004614D0 | 100.0% | Reimplemented From 2efc138375b4e3f8e4b55868a83eedf6c38f62cc Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 17 Sep 2026 15:42:26 +0200 Subject: [PATCH 31/44] reimplement: SHC_3BB0A8C1_0x00461550 100% --- .../TextEditorState/renderHelpDialogIfOpen.cpp | 16 ++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/renderHelpDialogIfOpen.cpp diff --git a/src/OpenSHC/Text/TextEditorState/renderHelpDialogIfOpen.cpp b/src/OpenSHC/Text/TextEditorState/renderHelpDialogIfOpen.cpp new file mode 100644 index 000000000..13ff6f4a4 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/renderHelpDialogIfOpen.cpp @@ -0,0 +1,16 @@ +#include "../TextEditorState.func.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x00461550 + void TextEditorState::renderHelpDialogIfOpen() + { + if (this->isDialogStateInitialized) { + MACRO_CALL_MEMBER(TextEditorState_Func::drawHelpWindowBackground, this)(); + MACRO_CALL_MEMBER(TextEditorState_Func::setTextRenderingLogic, this)(); + } + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f6691c395..405a627c2 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18833,7 +18833,7 @@ SHC_3BB0A8C1_0x004614F0 | 0.0% | Pending SHC_3BB0A8C1_0x00461520 | 0.0% | Pending -SHC_3BB0A8C1_0x00461550 | 0.0% | Pending +SHC_3BB0A8C1_0x00461550 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00461570 | 0.0% | Pending From 16c035eae75265955a69d6e11e823c2b4b2874a4 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 17 Sep 2026 15:45:55 +0200 Subject: [PATCH 32/44] reimplement: SHC_3BB0A8C1_0x004619D0 100% --- .../loadAndLayoutHelpContent.cpp | 22 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/loadAndLayoutHelpContent.cpp diff --git a/src/OpenSHC/Text/TextEditorState/loadAndLayoutHelpContent.cpp b/src/OpenSHC/Text/TextEditorState/loadAndLayoutHelpContent.cpp new file mode 100644 index 000000000..62a5eddb7 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/loadAndLayoutHelpContent.cpp @@ -0,0 +1,22 @@ +#include "../TextEditorState.func.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x004619D0 + void TextEditorState::loadAndLayoutHelpContent() + { + this->graphicFileCount = 0; + this->soundFileCount = 0; + this->topVisibleLineIndex = -1; + this->helpContentScrollOffsetY = 0; + if (!this->isCustomTextMode) { + MACRO_CALL_MEMBER(TextEditorState_Func::parseHlp, this)(); + MACRO_CALL_MEMBER(TextEditorState_Func::loadHelpSectionGraphics, this)(); + } + this->activeHelpHotspotIndex = 0; + MACRO_CALL_MEMBER(TextEditorState_Func::initializeAndLayoutHelpText, this)(); + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 405a627c2..c9347363c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18879,7 +18879,7 @@ SHC_3BB0A8C1_0x004619C4 | 0.0% | Pending SHC_3BB0A8C1_0x004619C8 | 0.0% | Pending -SHC_3BB0A8C1_0x004619D0 | 0.0% | Pending +SHC_3BB0A8C1_0x004619D0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00461A20 | 0.0% | Pending From 6e32ff366c1d5aa839b5faabbf6c0609c0c01a25 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 17 Sep 2026 16:24:34 +0200 Subject: [PATCH 33/44] reimplement: SHC_3BB0A8C1_0x00461A20 100% --- .../openBuildingHelpDialog.cpp | 79 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/openBuildingHelpDialog.cpp diff --git a/src/OpenSHC/Text/TextEditorState/openBuildingHelpDialog.cpp b/src/OpenSHC/Text/TextEditorState/openBuildingHelpDialog.cpp new file mode 100644 index 000000000..fd849ca46 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/openBuildingHelpDialog.cpp @@ -0,0 +1,79 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/Text/TextEditorState.func.hpp" +#include "OpenSHC/UI/MenuModalComposition.func.hpp" + +#include "OpenSHC/Globals/DAT_00df2964.hpp" +#include "OpenSHC/Globals/DAT_00df296c.hpp" +#include "OpenSHC/Globals/DAT_MenuModalComposition1.hpp" +#include "OpenSHC/Globals/DAT_UserTextHandlerState.hpp" +#include "OpenSHC/Globals/INT_00df2968.hpp" +#include "OpenSHC/Globals/INT_00df2970.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x00461A20 + void TextEditorState::openBuildingHelpDialog(int sectionId) + { + if (!this->isDialogStateInitialized) { + this->isDialogStateInitialized = TRUE; + this->helpDialogVariant = 1; + this->useInGameHelpHandler = 0; + this->helpDialogSubMode = 0; + this->useAlternateHelpTab = 0; + this->isCustomTextMode = 0; + DAT_UserTextHandlerState::instance.inputBufferIndex = 0; + this->helpContentScrollX = 0; + this->helpContentScrollY = 0; + } else if (sectionId == this->currentHelpSectionID) { + return; + } + + this->activeHelpHotspotIndex = 0; + if (sectionId == -1) { + MACRO_CALL_MEMBER(TextEditorState_Func::closeHelpDialogAndReturnToMenu, this)(); + return; + } + + this->isTextHelpDialogMode = 1; + MACRO_CALL_MEMBER(UI::MenuModalComposition_Func::activateModalDialog, DAT_MenuModalComposition1::ptr)( + UI::Enums::MMT_BUILDING_HELP_TEXT, FALSE); + + int modalX; + int modalY; + int modalWidth; + int modalHeight; + MACRO_CALL_MEMBER(UI::MenuModalComposition_Func::fillWithMenuModalDimensions, DAT_MenuModalComposition1::ptr)( + &modalX, &modalY, &modalWidth, &modalHeight); + // Likely also some rect structure + DAT_00df2964::instance = 15; + DAT_00df296c::instance = 13; + INT_00df2968::instance = 60; + INT_00df2970::instance = 65; + this->dialogX = modalX; + this->dialogY = modalY; + this->dialogWidth = modalWidth; + this->dialogHeight = modalHeight; + + int const dialogContentX = this->dialogX + DAT_00df2964::instance; + int const dialogContentY = this->dialogY + DAT_00df296c::instance; + int const dialogContentHeight = this->dialogHeight - INT_00df2970::instance; + int const dialogContentWidth = this->dialogWidth - INT_00df2968::instance; + this->dialogContentX = dialogContentX; + this->dialogContentY = dialogContentY; + this->dialogContentHeight = dialogContentWidth; + this->dialogContentWidth = dialogContentHeight; + + for (int i = 28; i >= 0; --i) { + this->helpSectionHistoryStack[i + 1] = this->helpSectionHistoryStack[i]; + } + this->helpSectionHistoryStack[0] = this->currentHelpSectionID; + + this->currentHelpSectionID = sectionId; + this->helpContentScrollOffsetY = 0; + MACRO_CALL_MEMBER(TextEditorState_Func::loadAndLayoutHelpContent, this)(); + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c9347363c..1c377d374 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18881,7 +18881,7 @@ SHC_3BB0A8C1_0x004619C8 | 0.0% | Pending SHC_3BB0A8C1_0x004619D0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00461A20 | 0.0% | Pending +SHC_3BB0A8C1_0x00461A20 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00461B90 | 0.0% | Pending From f994a66250cebc923a8aeade1c7ff97c8cc9333d Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 17 Sep 2026 18:58:52 +0200 Subject: [PATCH 34/44] reimplement: SHC_3BB0A8C1_0x00461B90 100% --- .../TextEditorState/openInGameHelpDialog.cpp | 74 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/openInGameHelpDialog.cpp diff --git a/src/OpenSHC/Text/TextEditorState/openInGameHelpDialog.cpp b/src/OpenSHC/Text/TextEditorState/openInGameHelpDialog.cpp new file mode 100644 index 000000000..cdb41b1d7 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/openInGameHelpDialog.cpp @@ -0,0 +1,74 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/UI/MenuModalComposition.func.hpp" + +#include "OpenSHC/Globals/DAT_00df2964.hpp" +#include "OpenSHC/Globals/DAT_00df296c.hpp" +#include "OpenSHC/Globals/DAT_MenuModalComposition1.hpp" +#include "OpenSHC/Globals/DAT_UserTextHandlerState.hpp" +#include "OpenSHC/Globals/INT_00df2968.hpp" +#include "OpenSHC/Globals/INT_00df2970.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x00461B90 + void TextEditorState::openInGameHelpDialog(int sectionId) + { + if (!this->isDialogStateInitialized) { + this->isDialogStateInitialized = TRUE; + this->helpDialogVariant = 1; + this->useInGameHelpHandler = TRUE; + this->helpDialogSubMode = 0; + this->useAlternateHelpTab = 0; + this->isCustomTextMode = 0; + DAT_UserTextHandlerState::instance.inputBufferIndex = 0; + this->helpContentScrollX = 0; + this->helpContentScrollY = 0; + } + this->activeHelpHotspotIndex = 0; + if (sectionId == -1) { + MACRO_CALL_MEMBER(TextEditorState_Func::closeHelpDialogAndReturnToMenu, this)(); + return; + } + this->isTextHelpDialogMode = TRUE; + MACRO_CALL_MEMBER(UI::MenuModalComposition_Func::activateModalDialog, DAT_MenuModalComposition1::ptr)( + UI::Enums::MMT_IN_GAME_HELP_TEXT, FALSE); + + int modalX; + int modalY; + int modalWidth; + int modalHeight; + MACRO_CALL_MEMBER(UI::MenuModalComposition_Func::fillWithMenuModalDimensions, DAT_MenuModalComposition1::ptr)( + &modalX, &modalY, &modalWidth, &modalHeight); + + DAT_00df2964::instance = 15; + DAT_00df296c::instance = 13; + INT_00df2968::instance = 60; + INT_00df2970::instance = 65; + this->dialogX = modalX; + this->dialogY = modalY; + this->dialogWidth = modalWidth; + this->dialogHeight = modalHeight; + + int const dialogContentX = this->dialogX + DAT_00df2964::instance; + int const dialogContentY = this->dialogY + DAT_00df296c::instance; + int const dialogContentHeight = this->dialogHeight - INT_00df2970::instance; + int const dialogContentWidth = this->dialogWidth - INT_00df2968::instance; + this->dialogContentX = dialogContentX; + this->dialogContentY = dialogContentY; + this->dialogContentHeight = dialogContentWidth; + this->dialogContentWidth = dialogContentHeight; + + for (int i = 28; i >= 0; --i) { + this->helpSectionHistoryStack[i + 1] = this->helpSectionHistoryStack[i]; + } + this->helpSectionHistoryStack[0] = this->currentHelpSectionID; + + this->currentHelpSectionID = sectionId; + this->helpContentScrollOffsetY = 0; + MACRO_CALL_MEMBER(TextEditorState_Func::loadAndLayoutHelpContent, this)(); + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 1c377d374..73ac6429c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18883,7 +18883,7 @@ SHC_3BB0A8C1_0x004619D0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00461A20 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00461B90 | 0.0% | Pending +SHC_3BB0A8C1_0x00461B90 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00461CF0 | 0.0% | Pending From 803645d729ab36d5141fd6254654ff920d0be773 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 17 Sep 2026 19:05:09 +0200 Subject: [PATCH 35/44] reimplement: SHC_3BB0A8C1_0x00461CF0 100% --- .../openScenarioHelpDialog.cpp | 74 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/openScenarioHelpDialog.cpp diff --git a/src/OpenSHC/Text/TextEditorState/openScenarioHelpDialog.cpp b/src/OpenSHC/Text/TextEditorState/openScenarioHelpDialog.cpp new file mode 100644 index 000000000..cbe2b44f4 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/openScenarioHelpDialog.cpp @@ -0,0 +1,74 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/UI/MenuModalComposition.func.hpp" + +#include "OpenSHC/Globals/DAT_00df2964.hpp" +#include "OpenSHC/Globals/DAT_00df296c.hpp" +#include "OpenSHC/Globals/DAT_MenuModalComposition1.hpp" +#include "OpenSHC/Globals/DAT_UserTextHandlerState.hpp" +#include "OpenSHC/Globals/INT_00df2968.hpp" +#include "OpenSHC/Globals/INT_00df2970.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x00461CF0 + void TextEditorState::openScenarioHelpDialog(int sectionId) + { + if (!this->isDialogStateInitialized) { + this->isDialogStateInitialized = TRUE; + this->helpDialogVariant = 2; + this->useInGameHelpHandler = FALSE; + this->helpDialogSubMode = 0; + this->useAlternateHelpTab = FALSE; + this->isCustomTextMode = FALSE; + DAT_UserTextHandlerState::instance.inputBufferIndex = 0; + this->helpContentScrollX = 0; + this->helpContentScrollY = 0; + } + this->activeHelpHotspotIndex = 0; + if (sectionId == -1) { + MACRO_CALL_MEMBER(OpenSHC::Text::TextEditorState_Func::closeHelpDialogAndReturnToMenu, this)(); + return; + } + this->isTextHelpDialogMode = TRUE; + MACRO_CALL_MEMBER(OpenSHC::UI::MenuModalComposition_Func::activateModalDialog, DAT_MenuModalComposition1::ptr)( + OpenSHC::UI::Enums::MMT_DISPLAY_SCENARIO_HELP_TEXT, FALSE); + + int modalX; + int modalY; + int modalWidth; + int modalHeight; + MACRO_CALL_MEMBER(UI::MenuModalComposition_Func::fillWithMenuModalDimensions, DAT_MenuModalComposition1::ptr)( + &modalX, &modalY, &modalWidth, &modalHeight); + + DAT_00df2964::instance = 10; + DAT_00df296c::instance = 10; + INT_00df2968::instance = 45; + INT_00df2970::instance = 20; + this->dialogX = modalX; + this->dialogY = modalY; + this->dialogWidth = modalWidth; + this->dialogHeight = modalHeight; + + int const dialogContentX = this->dialogX + DAT_00df2964::instance; + int const dialogContentY = this->dialogY + DAT_00df296c::instance; + int const dialogContentHeight = this->dialogHeight - INT_00df2970::instance; + int const dialogContentWidth = this->dialogWidth - INT_00df2968::instance; + this->dialogContentX = dialogContentX; + this->dialogContentY = dialogContentY; + this->dialogContentHeight = dialogContentWidth; + this->dialogContentWidth = dialogContentHeight; + + for (int i = 28; i >= 0; --i) { + this->helpSectionHistoryStack[i + 1] = this->helpSectionHistoryStack[i]; + } + this->helpSectionHistoryStack[0] = this->currentHelpSectionID; + + this->currentHelpSectionID = sectionId; + this->helpContentScrollOffsetY = 0; + MACRO_CALL_MEMBER(OpenSHC::Text::TextEditorState_Func::loadAndLayoutHelpContent, this)(); + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 73ac6429c..b723b042d 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18885,7 +18885,7 @@ SHC_3BB0A8C1_0x00461A20 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00461B90 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00461CF0 | 0.0% | Pending +SHC_3BB0A8C1_0x00461CF0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00461E50 | 0.0% | Pending From 92db2d4d2bd0b9b85b6768b372076c516646e3a3 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 17 Sep 2026 19:10:11 +0200 Subject: [PATCH 36/44] reimplement: SHC_3BB0A8C1_0x00461E50 100% --- .../openCreditsScrollDialog.cpp | 73 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/openCreditsScrollDialog.cpp diff --git a/src/OpenSHC/Text/TextEditorState/openCreditsScrollDialog.cpp b/src/OpenSHC/Text/TextEditorState/openCreditsScrollDialog.cpp new file mode 100644 index 000000000..cc8d182e5 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/openCreditsScrollDialog.cpp @@ -0,0 +1,73 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/UI/MenuModalComposition.func.hpp" + +#include "OpenSHC/Globals/DAT_00df2964.hpp" +#include "OpenSHC/Globals/DAT_00df296c.hpp" +#include "OpenSHC/Globals/DAT_MenuModalComposition1.hpp" +#include "OpenSHC/Globals/DAT_UserTextHandlerState.hpp" +#include "OpenSHC/Globals/INT_00df2968.hpp" +#include "OpenSHC/Globals/INT_00df2970.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x00461E50 + void TextEditorState::openCreditsScrollDialog(int sectionId) + { + if (!this->isDialogStateInitialized) { + this->isDialogStateInitialized = TRUE; + this->helpDialogVariant = 2; + this->useInGameHelpHandler = FALSE; + this->helpDialogSubMode = 0; + this->useAlternateHelpTab = FALSE; + this->isCustomTextMode = FALSE; + DAT_UserTextHandlerState::instance.inputBufferIndex = 0; + } + this->activeHelpHotspotIndex = 0; + if (sectionId == -1) { + MACRO_CALL_MEMBER(TextEditorState_Func::closeHelpDialogAndReturnToMenu, this)(); + return; + } + + this->isTextHelpDialogMode = TRUE; + MACRO_CALL_MEMBER(UI::MenuModalComposition_Func::activateModalDialog, DAT_MenuModalComposition1::ptr)( + UI::Enums::MMT_CREDITS_SCROLL, FALSE); + + int modalX; + int modalY; + int modalWidth; + int modalHeight; + MACRO_CALL_MEMBER(UI::MenuModalComposition_Func::fillWithMenuModalDimensions, DAT_MenuModalComposition1::ptr)( + &modalX, &modalY, &modalWidth, &modalHeight); + + DAT_00df2964::instance = 0; + DAT_00df296c::instance = 0; + INT_00df2968::instance = 0; + INT_00df2970::instance = 0; + this->dialogX = modalX; + this->dialogY = modalY; + this->dialogWidth = modalWidth; + this->dialogHeight = modalHeight; + + int const dialogContentX = this->dialogX + DAT_00df2964::instance; + int const dialogContentY = this->dialogY + DAT_00df296c::instance; + int const dialogContentHeight = this->dialogHeight - INT_00df2970::instance; + int const dialogContentWidth = this->dialogWidth - INT_00df2968::instance; + this->dialogContentX = dialogContentX; + this->dialogContentY = dialogContentY; + this->dialogContentHeight = dialogContentWidth; + this->dialogContentWidth = dialogContentHeight; + + for (int i = 28; i >= 0; --i) { + this->helpSectionHistoryStack[i + 1] = this->helpSectionHistoryStack[i]; + } + this->helpSectionHistoryStack[0] = this->currentHelpSectionID; + + this->currentHelpSectionID = sectionId; + this->helpContentScrollOffsetY = 0; + MACRO_CALL_MEMBER(TextEditorState_Func::loadAndLayoutHelpContent, this)(); + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index b723b042d..2bd61b0ed 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18887,7 +18887,7 @@ SHC_3BB0A8C1_0x00461B90 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00461CF0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00461E50 | 0.0% | Pending +SHC_3BB0A8C1_0x00461E50 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00461F90 | 0.0% | Pending From 77c6a8ce18e10749d23b378a239d8845f1446551 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 17 Sep 2026 19:14:43 +0200 Subject: [PATCH 37/44] reimplement: SHC_3BB0A8C1_0x00461F90 100% --- .../openMapDescriptionEditorDialog.cpp | 75 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/openMapDescriptionEditorDialog.cpp diff --git a/src/OpenSHC/Text/TextEditorState/openMapDescriptionEditorDialog.cpp b/src/OpenSHC/Text/TextEditorState/openMapDescriptionEditorDialog.cpp new file mode 100644 index 000000000..ab6933b08 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/openMapDescriptionEditorDialog.cpp @@ -0,0 +1,75 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/UI/MenuModalComposition.func.hpp" + +#include "OpenSHC/Globals/DAT_00df2964.hpp" +#include "OpenSHC/Globals/DAT_00df296c.hpp" +#include "OpenSHC/Globals/DAT_MenuModalComposition1.hpp" +#include "OpenSHC/Globals/DAT_UserTextHandlerState.hpp" +#include "OpenSHC/Globals/INT_00df2968.hpp" +#include "OpenSHC/Globals/INT_00df2970.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x00461F90 + void TextEditorState::openMapDescriptionEditorDialog(int sectionId) + { + if (!this->isDialogStateInitialized) { + this->isDialogStateInitialized = TRUE; + this->helpDialogVariant = 0; + this->useInGameHelpHandler = FALSE; + this->helpDialogSubMode = 0; + this->useAlternateHelpTab = TRUE; + this->isCustomTextMode = TRUE; + DAT_UserTextHandlerState::instance.inputBufferIndex = 0; + this->helpContentScrollX = 0; + this->helpContentScrollY = 0; + } + this->activeHelpHotspotIndex = 0; + this->customHelpTextPointer = NULL; + if (sectionId == -1) { + MACRO_CALL_MEMBER(TextEditorState_Func::closeHelpDialogAndReturnToMenu, this)(); + return; + } + this->isTextHelpDialogMode = 0; + MACRO_CALL_MEMBER(UI::MenuModalComposition_Func::activateModalDialog, DAT_MenuModalComposition1::ptr)( + UI::Enums::MMT_MAP_DESCRIPTION_EDITOR, FALSE); + + int modalX; + int modalY; + int modalWidth; + int modalHeight; + MACRO_CALL_MEMBER(UI::MenuModalComposition_Func::fillWithMenuModalDimensions, DAT_MenuModalComposition1::ptr)( + &modalX, &modalY, &modalWidth, &modalHeight); + + DAT_00df2964::instance = 10; + DAT_00df296c::instance = 10; + INT_00df2968::instance = 45; + INT_00df2970::instance = 53; + this->dialogX = modalX; + this->dialogY = modalY; + this->dialogWidth = modalWidth; + this->dialogHeight = modalHeight; + + int const dialogContentX = this->dialogX + DAT_00df2964::instance; + int const dialogContentY = this->dialogY + DAT_00df296c::instance; + int const dialogContentHeight = this->dialogHeight - INT_00df2970::instance; + int const dialogContentWidth = this->dialogWidth - INT_00df2968::instance; + this->dialogContentX = dialogContentX; + this->dialogContentY = dialogContentY; + this->dialogContentHeight = dialogContentWidth; + this->dialogContentWidth = dialogContentHeight; + + for (int i = 28; i >= 0; --i) { + this->helpSectionHistoryStack[i + 1] = this->helpSectionHistoryStack[i]; + } + this->helpSectionHistoryStack[0] = this->currentHelpSectionID; + + this->currentHelpSectionID = -1; + this->helpContentScrollOffsetY = 0; + MACRO_CALL_MEMBER(TextEditorState_Func::loadAndLayoutHelpContent, this)(); + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 2bd61b0ed..56b0dce0c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18889,7 +18889,7 @@ SHC_3BB0A8C1_0x00461CF0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00461E50 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00461F90 | 0.0% | Pending +SHC_3BB0A8C1_0x00461F90 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004620F0 | 0.0% | Pending From bba5eba600d45e8e4b81ff4d653ad4ceb3aee9eb Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 17 Sep 2026 19:21:41 +0200 Subject: [PATCH 38/44] reimplement: SHC_3BB0A8C1_0x004620F0 100% --- .../TextEditorState/setCustomHelpText.cpp | 24 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/setCustomHelpText.cpp diff --git a/src/OpenSHC/Text/TextEditorState/setCustomHelpText.cpp b/src/OpenSHC/Text/TextEditorState/setCustomHelpText.cpp new file mode 100644 index 000000000..83c6495a6 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/setCustomHelpText.cpp @@ -0,0 +1,24 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/Util/WideCharMultiByteState.func.hpp" + +#include "OpenSHC/Globals/DAT_WideCharMultiByteState.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x004620F0 + void TextEditorState::setCustomHelpText(char* helpText, int bufferSize) + { + this->customHelpTextPointer = helpText; + this->isCustomHelpTextWide = 0; + this->customHelpTextBufferSize = bufferSize; + MACRO_CALL_MEMBER(Util::WideCharMultiByteState_Func::multiByteToWideCharacter, DAT_WideCharMultiByteState::ptr)( + this->DAT_PointerToTemporaryTextMemory, helpText); + this->customHelpTextLength = strlen(helpText); + this->isTextHelpDialogMode = TRUE; + MACRO_CALL_MEMBER(TextEditorState_Func::loadAndLayoutHelpContent, this)(); + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 56b0dce0c..7289b8b39 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18891,7 +18891,7 @@ SHC_3BB0A8C1_0x00461E50 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00461F90 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004620F0 | 0.0% | Pending +SHC_3BB0A8C1_0x004620F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00462150 | 0.0% | Pending From 7b962143088f201b72a2444c3a08d4cce48ad365 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 17 Sep 2026 19:28:52 +0200 Subject: [PATCH 39/44] reimplement: SHC_3BB0A8C1_0x00462150 100% --- .../TextEditorState/popHelpDialogStack.cpp | 25 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Text/TextEditorState/popHelpDialogStack.cpp diff --git a/src/OpenSHC/Text/TextEditorState/popHelpDialogStack.cpp b/src/OpenSHC/Text/TextEditorState/popHelpDialogStack.cpp new file mode 100644 index 000000000..5fd6604c0 --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/popHelpDialogStack.cpp @@ -0,0 +1,25 @@ +#include "../TextEditorState.func.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x00462150 + void TextEditorState::popHelpDialogStack() + { + int sectionId = this->helpSectionHistoryStack[0]; + + for (int i = 0; i < 29; ++i) { + this->helpSectionHistoryStack[i] = this->helpSectionHistoryStack[i + 1]; + } + this->helpSectionHistoryStack[29] = -1; + + this->currentHelpSectionID = sectionId; + if (sectionId == -1) { + MACRO_CALL_MEMBER(TextEditorState_Func::closeHelpDialogAndReturnToMenu, this)(); + } else { + MACRO_CALL_MEMBER(TextEditorState_Func::loadAndLayoutHelpContent, this)(); + } + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 7289b8b39..23b32bdd5 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18893,7 +18893,7 @@ SHC_3BB0A8C1_0x00461F90 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004620F0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00462150 | 0.0% | Pending +SHC_3BB0A8C1_0x00462150 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00462190 | 0.0% | Pending From b07dbc0dc9fc49ab2b3ab0af0916595bfd0710f5 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 17 Sep 2026 20:11:51 +0200 Subject: [PATCH 40/44] reimplement: SHC_3BB0A8C1_0x00462190 100% --- src/OpenSHC/Text/TextEditorState.hpp | 2 +- .../openUnusedHelpTextEditorDialog.cpp | 95 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 3 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 src/OpenSHC/Text/TextEditorState/openUnusedHelpTextEditorDialog.cpp diff --git a/src/OpenSHC/Text/TextEditorState.hpp b/src/OpenSHC/Text/TextEditorState.hpp index 13440b205..2f904d89c 100644 --- a/src/OpenSHC/Text/TextEditorState.hpp +++ b/src/OpenSHC/Text/TextEditorState.hpp @@ -178,7 +178,7 @@ namespace Text { void popHelpDialogStack(); - void openUnusedHelpTextEditorDialog(int param_1); + void openUnusedHelpTextEditorDialog(int sectionId); }; static_assert_cpp98_obj(sizeof(TextEditorState) == 145780, TextEditorState); diff --git a/src/OpenSHC/Text/TextEditorState/openUnusedHelpTextEditorDialog.cpp b/src/OpenSHC/Text/TextEditorState/openUnusedHelpTextEditorDialog.cpp new file mode 100644 index 000000000..45951bd8d --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/openUnusedHelpTextEditorDialog.cpp @@ -0,0 +1,95 @@ +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/Game/GameCore.func.hpp" + +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_UserTextHandlerState.hpp" +#include "OpenSHC/Globals/DAT_WindowAndDirectDraw.hpp" +#include "OpenSHC/Globals/Menu_UnusedHelpTextEditor.hpp" + +namespace OpenSHC { +namespace Text { + + // FUNCTION: STRONGHOLDCRUSADER 0x00462190 + void TextEditorState::openUnusedHelpTextEditorDialog(int sectionId) + { + if (this->helpDialogVariant) { + if (this->helpDialogVariant == 2) { + MACRO_CALL_MEMBER(TextEditorState_Func::openScenarioHelpDialog, this)(sectionId); + return; + } + if (this->useInGameHelpHandler) { + MACRO_CALL_MEMBER(TextEditorState_Func::openInGameHelpDialog, this)(sectionId); + return; + } + MACRO_CALL_MEMBER(TextEditorState_Func::openBuildingHelpDialog, this)(sectionId); + return; + } + + if (!this->isDialogStateInitialized) { + this->savedMenuViewType = DAT_GameCore::instance.currentMenuViewType; + this->savedActiveMenuTab = DAT_GameCore::instance.activeMenuTab.tabType; + this->savedMenuFlag = DAT_GameCore::instance.unknownAlwaysZero01; + this->unknown_0x23960 = 1; + this->isDialogStateInitialized = TRUE; + this->useInGameHelpHandler = FALSE; + this->helpDialogVariant = 0; + this->helpDialogSubMode = 0; + this->useAlternateHelpTab = FALSE; + this->isCustomTextMode = FALSE; + this->helpContentScrollX = 0; + this->helpContentScrollY = 0; + this->useWideHelpLayout = FALSE; + DAT_UserTextHandlerState::instance.inputBufferIndex = 0; + } + this->activeHelpHotspotIndex = 0; + if (sectionId == -1) { + MACRO_CALL_MEMBER(TextEditorState_Func::closeHelpDialogAndReturnToMenu, this)(); + return; + } + if (!this->useAlternateHelpTab) { + this->isTextHelpDialogMode = TRUE; + DAT_GameCore::instance.menuTabToSwitchTo.tabType = 0; + MACRO_CALL_MEMBER(Game::GameCore_Func::switchToMenuView, DAT_GameCore::ptr)( + UI::Enums::MVT_UNUSED_HELP_TEXT_EDITOR, 0); + } else { + this->isTextHelpDialogMode = TRUE; + DAT_GameCore::instance.menuTabToSwitchTo.tabType = 1; + MACRO_CALL_MEMBER(Game::GameCore_Func::switchToMenuView, DAT_GameCore::ptr)( + UI::Enums::MVT_UNUSED_HELP_TEXT_EDITOR, 0); + } + Menu_UnusedHelpTextEditor::instance.thousand = 0; + + int const dialogX = DAT_WindowAndDirectDraw::instance.mainMenuBorderWidth + 80; + int const dialogY = DAT_WindowAndDirectDraw::instance.mainMenuBorderHeight + 60; + int const dialogWidth = 640; + int const dialogHeight = 480; + this->dialogX = dialogX; + this->dialogY = dialogY; + this->dialogWidth = dialogWidth; + this->dialogHeight = dialogHeight; + + if (!this->useWideHelpLayout) { + this->dialogContentX = this->dialogX + 10; + this->dialogContentY = this->dialogY + 10; + this->dialogContentHeight = 600; + this->dialogContentWidth = 435; + } else { + this->dialogContentX = this->dialogX + 10; + this->dialogContentY = this->dialogY + 10; + this->dialogContentHeight = 664; + this->dialogContentWidth = 291; + } + + for (int i = 28; i >= 0; --i) { + this->helpSectionHistoryStack[i + 1] = this->helpSectionHistoryStack[i]; + } + this->helpSectionHistoryStack[0] = this->currentHelpSectionID; + + this->currentHelpSectionID = sectionId; + this->helpContentScrollOffsetY = 0; + MACRO_CALL_MEMBER(TextEditorState_Func::loadAndLayoutHelpContent, this)(); + } + +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 23b32bdd5..91ba63d60 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18895,7 +18895,7 @@ SHC_3BB0A8C1_0x004620F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00462150 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00462190 | 0.0% | Pending +SHC_3BB0A8C1_0x00462190 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00462340 | 0.0% | Pending From 8c299e74f1afc86b31a9af0463f7c39da6bb941d Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sat, 19 Sep 2026 00:19:43 +0200 Subject: [PATCH 41/44] reimplement: SHC_3BB0A8C1_0x0045FDC0 buildable, horrible match --- IMPLEMENTATION_CHEAT_SHEET.md | 49 +- src/OpenSHC/Text/TextEditorState.hpp | 9 +- .../initializeAndLayoutHelpText.cpp | 7 +- .../processHelpRichTextTokens.cpp | 815 ++++++++++++++++++ 4 files changed, 857 insertions(+), 23 deletions(-) create mode 100644 src/OpenSHC/Text/TextEditorState/processHelpRichTextTokens.cpp diff --git a/IMPLEMENTATION_CHEAT_SHEET.md b/IMPLEMENTATION_CHEAT_SHEET.md index 6a19c9856..afc4ac661 100644 --- a/IMPLEMENTATION_CHEAT_SHEET.md +++ b/IMPLEMENTATION_CHEAT_SHEET.md @@ -545,25 +545,36 @@ They are replaced by specific assembly instructions or otherwise inlined. A list of all intrinsics can be found in `intrin.h` in the std library, but these are mainly very low level instructions. However, there are also C functions that can be replaced by intrinsics. The following attempts to extract these from the header: -| Intrinsic | Does | -| --------- | ---------------------------------------------------------------------------------------------- | -| `memcpy` | Copies a memory block. **Does not support overlapping regions** (use `memmove` for overlap). | -| `memset` | Fills a memory block with a byte value. | -| `memcmp` | Compares two memory blocks byte-by-byte. | -| `memchr` | Searches memory for the first occurrence of a byte. | -| `strcpy` | Copies a null-terminated C string. | -| `strlen` | Returns the length of a null-terminated string (excluding `\0`). | -| `strcmp` | Compares two null-terminated C strings. | -| `strcat` | Appends one null-terminated C string to another. | -| `strncpy` | Copies up to N characters from a string; **may not null-terminate** if the source is too long. | -| `strncmp` | Compares up to N characters of two strings. | -| `wcscpy` | Copies a null-terminated wide-character string. | -| `wcslen` | Returns the length of a null-terminated wide string. | -| `ceil` | Rounds a floating-point value upward to the nearest integer value. | -| `abs` | Returns the absolute value of an `int`. | -| `labs` | Returns the absolute value of a `long`. | -| `longjmp` | Restores a saved execution context created by `setjmp`, continuing execution from that point. | -| `_setjmp` | Saves the current execution context for later restoration with `longjmp`. | +| Intrinsic | Does | +|---------------------------|----------------------------------------------------------------------------------------------------------------------| +| `memcpy` | Copies a memory block. **Does not support overlapping regions** (use `memmove` for overlap). | +| `memset` | Fills a memory block with a byte value. | +| `memcmp` | Compares two memory blocks byte-by-byte. | +| `memchr` | Searches memory for the first occurrence of a byte. | +| `strcpy` | Copies a null-terminated C string. | +| `strlen` | Returns the length of a null-terminated string (excluding `\0`). | +| `strcmp` | Compares two null-terminated C strings. | +| `strcat` | Appends one null-terminated C string to another. | +| `strncpy` | Copies up to N characters from a string; **may not null-terminate** if the source is too long. | +| `strncmp` | Compares up to N characters of two strings. | +| `strset` | Sets every character in a null-terminated string to the specified character. | +| `_strset` | Microsoft-specific version of `strset`; sets every character in a null-terminated string to the specified character. | +| `wcscpy` | Copies a null-terminated wide-character string. | +| `wcslen` | Returns the length of a null-terminated wide string. | +| `wcscmp` | Compares two null-terminated wide-character strings. | +| `wcscat` | Appends one null-terminated wide-character string to another. | +| `wcsncpy` | Copies up to N wide characters; **may not null-terminate** if the source is too long. | +| `wcsncmp` | Compares up to N wide characters of two strings. | +| `_wcsset` | Sets every character in a null-terminated wide string to the specified wide character. | +| `ceil` | Returns the smallest integral floating-point value greater than or equal to the argument. | +| `abs` | Returns the absolute value of an `int`. | +| `labs` | Returns the absolute value of a `long`. | +| `longjmp` | Restores a saved execution context created by `setjmp`, continuing execution from that point. | +| `_setjmp` | Saves the current execution context for later restoration with `longjmp`. | +| `_AddressOfReturnAddress` | Returns the address of the current function's return-address storage. | +| `_WriteBarrier` | Prevents certain compiler memory-write reorderings across the barrier. | +| `__trap` | Generates a processor/compiler trap, optionally with arguments. | + In cases where the decompiler seems to perform one of these actions via simple instructions, one can also try one of these functions. diff --git a/src/OpenSHC/Text/TextEditorState.hpp b/src/OpenSHC/Text/TextEditorState.hpp index 2f904d89c..be0f30e8e 100644 --- a/src/OpenSHC/Text/TextEditorState.hpp +++ b/src/OpenSHC/Text/TextEditorState.hpp @@ -20,6 +20,13 @@ namespace OpenSHC { namespace Text { + struct ImageHotspot { + short xPos; + short yPos; + short imageRelated; + short unknown3; + }; + struct LineLayout { short unknown0; short unknown1; @@ -178,7 +185,7 @@ namespace Text { void popHelpDialogStack(); - void openUnusedHelpTextEditorDialog(int sectionId); + void openUnusedHelpTextEditorDialog(int param_1); }; static_assert_cpp98_obj(sizeof(TextEditorState) == 145780, TextEditorState); diff --git a/src/OpenSHC/Text/TextEditorState/initializeAndLayoutHelpText.cpp b/src/OpenSHC/Text/TextEditorState/initializeAndLayoutHelpText.cpp index 44b86a79c..99fef53e0 100644 --- a/src/OpenSHC/Text/TextEditorState/initializeAndLayoutHelpText.cpp +++ b/src/OpenSHC/Text/TextEditorState/initializeAndLayoutHelpText.cpp @@ -7,12 +7,13 @@ namespace Text { void TextEditorState::initializeAndLayoutHelpText() { for (int i = 0; i < 20000; ++i) { - this->lineLayoutTable[i].unknown0 = 25; - this->lineLayoutTable[i].unknown1 = this->dialogContentHeight - 25; + this->lineLayoutTable[i].leftBorder = 25; + this->lineLayoutTable[i].rightBorder = this->dialogContentHeight - 25; this->lineLayoutTable[i].unknown2 = 0; } + // Adds vertical space at start for (int i = 0; i < 4; ++i) { - this->lineLayoutTable[i].unknown0 = -1; + this->lineLayoutTable[i].leftBorder = -1; } this->imageHotspotCount = 0; while (!MACRO_CALL_MEMBER(TextEditorState_Func::processHelpRichTextTokens, this)(0)) {}; diff --git a/src/OpenSHC/Text/TextEditorState/processHelpRichTextTokens.cpp b/src/OpenSHC/Text/TextEditorState/processHelpRichTextTokens.cpp new file mode 100644 index 000000000..837af17dd --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/processHelpRichTextTokens.cpp @@ -0,0 +1,815 @@ +// disable deprecation warnings for wcscpy and wcscat +#pragma warning(disable : 4996) + +#include "../TextEditorState.func.hpp" + +#include "OpenSHC/Global.func.hpp" +#include "OpenSHC/Input/MouseState.func.hpp" +#include "OpenSHC/Text/FontSizeClass.func.hpp" +#include "OpenSHC/UI/Rendering/PencilRenderCore.func.hpp" + +#include "OpenSHC/Globals/COL_DARK_LIME.hpp" +#include "OpenSHC/Globals/DAT_00df3348.hpp" +#include "OpenSHC/Globals/DAT_00df334c.hpp" +#include "OpenSHC/Globals/DAT_MouseState.hpp" +#include "OpenSHC/Globals/DAT_PencilRenderCore.hpp" +#include "OpenSHC/Globals/DAT_TextManagerObject.hpp" +#include "OpenSHC/Globals/DAT_TextureRenderCoreObject.hpp" +#include "OpenSHC/Globals/DAT_UserHelpDefinedData.hpp" + +namespace OpenSHC { +namespace Text { + + union TextMemUnion { + int value; + wchar_t* text; + HelpTextToken helpToken; + HelpTextPicturePositionToken picturePositionToken; + }; + + // FUNCTION: STRONGHOLDCRUSADER 0x0045FDC0 + int TextEditorState::processHelpRichTextTokens(int param_1) + { + int iVar5; + wchar_t* pwVar6; + int iVar12; + int dVar14; + int iVar17; + int local_12c; + int local_118; + int local_114; + int local_104; + int local_f8; + int local_f4; + wchar_t wideTextBuffer[100]; + int currentLinkId = -1; + int textMemIndex = 0; + FontSizeClass* currentFontClass = DAT_TextManagerObject::instance.fontSizeClassArray + 17; + int currentFontLineHeight = DAT_TextManagerObject::instance.fontSizeClassArray[17].lineHeight_0x14; + BOOL local_f0 = FALSE; + BGR24 color = 0xccfaff; + BGR24 linkColor = 0x8bcf84; + int imageCount = -1; + BOOL centreActive = FALSE; + BOOL local_120 = FALSE; + int lineStartY = 0; + int lineEndY = 0; + int local_11c = 0; + int local_100 = 0; + int local_10c = 0; + BOOL local_e4 = FALSE; + int local_134 = -10000; + if (this->helpDialogVariant == 2 || this->isCustomTextMode) { + color = 0xc2f0eb; + } + if (!this->isTextHelpDialogMode) { + return 1; + } + this->unknown_0x23964 = -1; + this->unknown_0x23968 = -1; + if (this->unknown_0x2396C) { + DAT_00df334c::instance = 1; + } + if (this->activeHelpHotspotIndex < 0) { + this->activeHelpHotspotIndex = 0; + } + if (this->activeHelpHotspotIndex > this->customHelpTextLength) { + this->activeHelpHotspotIndex = this->customHelpTextLength; + } + int leftPosition; + int lineY = -1; + do { + leftPosition = this->lineLayoutTable[++lineY].leftBorder; + } while (leftPosition == -1); + while (true) { + iVar5 = textMemIndex; + BGR24 charColor = color; + local_12c = 1; + if (0 <= currentLinkId) { + charColor = linkColor; + } + local_114 = textMemIndex; + TextMemUnion textMemUnion; + textMemUnion.value + = MACRO_CALL_MEMBER(TextEditorState_Func::getWideCharOrWideCharPointer, this)(&textMemIndex); + if (this->useAlternateHelpTab && textMemUnion.value < L' ' && textMemUnion.helpToken != HTT_NEWPARAGRAPH + && iVar5 == this->activeHelpHotspotIndex) { + lineEndY = lineY + currentFontLineHeight; + lineStartY = lineY; + if (param_1 == 1) { + int xModify = 0; + if (local_120) { + xModify = this->lineLayoutTable[lineY].unknown2 / 2; + } + local_10c = local_114 - local_11c; + if (this->unknown_0x2396C < 0) { + this->activeHelpHotspotIndex = local_100 + DAT_00df3348::instance; + if (this->activeHelpHotspotIndex >= local_11c) { + this->activeHelpHotspotIndex = local_11c - 1; + } + this->unknown_0x2396C = 0; + } + local_134 = 0; + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( + this->dialogContentX + xModify - 1 + leftPosition, + this->dialogContentY - this->helpContentScrollOffsetY - 1 + lineY, + this->dialogContentX + xModify - 1 + leftPosition, + this->dialogContentY - this->helpContentScrollOffsetY + 1 + lineEndY, + COL_DARK_LIME::instance.shortValue); + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( + this->dialogContentX + xModify + leftPosition, + this->dialogContentY - this->helpContentScrollOffsetY - 1 + lineY, + this->dialogContentX + xModify + leftPosition, + this->dialogContentY - this->helpContentScrollOffsetY + 1 + lineEndY, + COL_DARK_LIME::instance.shortValue); + local_e4 = TRUE; + } + } + + iVar17 = local_11c; + switch (textMemUnion.helpToken) { + case HTT_PIC: + if (this->helpDialogSubMode == 1) { + charColor = 0xff; + local_12c = 0; + MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, L"DAT_PointerToTemporaryTextMemory[textMemIndex], + this->graphicFileNames[this->DAT_PointerToTemporaryTextMemory[textMemIndex]]); + ++textMemIndex; + switch ((HelpTextPicturePositionToken)this->DAT_PointerToTemporaryTextMemory[textMemIndex]) { + case HTT_PIC_LEFT: + wcscat(wideTextBuffer, L"LEFT>"); + textMemIndex += 2; + break; + case HTT_PIC_RIGHT: + wcscat(wideTextBuffer, L"RIGHT>"); + textMemIndex += 2; + break; + case HTT_PIC_CENTRE: + wcscat(wideTextBuffer, L"CENTRE>"); + textMemIndex += 2; + break; + case HTT_PIC_HERE: + wcscat(wideTextBuffer, L"HERE>"); + textMemIndex += 2; + break; + default: + textMemIndex += 2; + break; + } + break; + } else { + ++imageCount; + if (param_1 == 1) { + if (this->DAT_PointerToTemporaryTextMemory[textMemIndex + 1] != 3) { + textMemIndex += 3; + continue; + } + } else { + if (param_1 + || (imageCount != this->imageHotspotCount + && this->DAT_PointerToTemporaryTextMemory[textMemIndex + 1] != 3)) { + textMemIndex += 3; + continue; + } + if (imageCount == this->imageHotspotCount) { + this->imageHotspotTable[this->imageHotspotCount].yPos = lineY + 25; + this->imageHotspotTable[this->imageHotspotCount].imageRelated + = this->DAT_PointerToTemporaryTextMemory[textMemIndex]; + this->imageHotspotTable[this->imageHotspotCount].unknown3 = currentLinkId; + } + } + HelpTextPicturePositionToken positionToken + = (HelpTextPicturePositionToken)this->DAT_PointerToTemporaryTextMemory[textMemIndex + 1]; + int imageHeight = DAT_TextureRenderCoreObject::instance + .loadedGfxArray[99 - this->DAT_PointerToTemporaryTextMemory[textMemIndex]] + .height; + int imageWidth = DAT_TextureRenderCoreObject::instance + .loadedGfxArray[99 - this->DAT_PointerToTemporaryTextMemory[textMemIndex]] + .width; + switch (positionToken) { + case HTT_PIC_LEFT: + this->imageHotspotTable[this->imageHotspotCount].xPos = this->lineLayoutTable[lineY].leftBorder; + for (int i = 0; i < imageHeight + 50; ++i) { + this->lineLayoutTable[lineY + i].rightBorder + = this->lineLayoutTable[lineY].leftBorder + 25 + imageWidth; + } + break; + case HTT_PIC_RIGHT: + this->imageHotspotTable[this->imageHotspotCount].xPos + = this->lineLayoutTable[lineY].rightBorder - imageWidth; + for (int i = 0; i < imageHeight + 50; ++i) { + this->lineLayoutTable[lineY + i].rightBorder + = this->lineLayoutTable[lineY].rightBorder - imageWidth - 25; + this->lineLayoutTable[lineY + i].leftBorder = -1; + } + break; + case HTT_PIC_CENTRE: + this->imageHotspotTable[this->imageHotspotCount].xPos + = (this->dialogContentHeight - imageWidth) / 2; + for (int i = 0; i < imageHeight + 50; ++i) { + this->lineLayoutTable[lineY + i].leftBorder = -1; + } + break; + case HTT_PIC_HERE: + imageWidth += 3; + if (this->lineLayoutTable[lineY].rightBorder < imageWidth + leftPosition) { + local_f0 = FALSE; + if (local_120) { + this->lineLayoutTable[lineY].unknown2 + = this->lineLayoutTable[lineY].rightBorder - leftPosition; + local_120 = centreActive; + } + do { + lineY += currentFontLineHeight + 1; + do { + leftPosition = this->lineLayoutTable[lineY++].leftBorder; + } while (leftPosition == -1); + } while (this->lineLayoutTable[lineY].rightBorder < leftPosition + imageWidth); + if (this->useAlternateHelpTab && param_1 == 1) { + ++local_134; + local_100 = local_11c; + local_11c = local_114; + if (0 < this->unknown_0x2396C && 1 < local_134) { + this->activeHelpHotspotIndex = iVar17 + local_10c; + local_134 = -10000; + if (local_114 <= this->activeHelpHotspotIndex) { + this->activeHelpHotspotIndex = local_114 + -1; + } + this->unknown_0x2396C = 0; + } + } + currentFontLineHeight = currentFontClass->lineHeight_0x14; + } + if (currentFontLineHeight < imageHeight) { + currentFontLineHeight = imageHeight; + } + leftPosition += imageWidth; + if (param_1 != 1 && imageCount == this->imageHotspotCount) { + this->imageHotspotTable[this->imageHotspotCount].xPos = leftPosition - imageWidth; + this->imageHotspotTable[this->imageHotspotCount].yPos = lineY; + ++this->imageHotspotCount; + } + break; + } + textMemIndex += 3; + if (positionToken == HTT_PIC_HERE || param_1) { + continue; + } + ++this->imageHotspotCount; + DAT_TextManagerObject::instance.field6_0x18 = 0; + return FALSE; + } + case HTT_FONT: + if (this->helpDialogSubMode == 1) { + charColor = 0xff; + local_12c = 0; + MACRO_CALL(Global_Func::PrintToDestination)( + wideTextBuffer, L"", this->DAT_PointerToTemporaryTextMemory[textMemIndex]); + textMemIndex += 2; + break; + } else { + int fontSize = this->DAT_PointerToTemporaryTextMemory[textMemIndex]; + if (fontSize < 15) { + fontSize += 5; + } + textMemIndex = textMemIndex + 2; + currentFontClass = DAT_TextManagerObject::instance.fontSizeClassArray + fontSize; + dVar14 = DAT_TextManagerObject::instance.fontSizeClassArray[fontSize].lineHeight_0x14; + if (currentFontLineHeight < dVar14 || !local_f0) { + currentFontLineHeight = dVar14; + } + continue; + } + case HTT_COLOUR: + if (this->helpDialogSubMode == 1) { + charColor = 0xff; + local_12c = 0; + MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, L"", + DAT_UserHelpDefinedData::instance + .field6_0x7a16c[this->DAT_PointerToTemporaryTextMemory[textMemIndex]] + .name_0x0); + textMemIndex += 2; + break; + } else { + if (param_1 == 1) { + int const colorIndex = this->DAT_PointerToTemporaryTextMemory[textMemIndex]; + + uint colorRed; + uint colorGreen; + uint colorBlue; + if (this->helpDialogVariant == 2 && colorIndex == 1) { + colorRed = 0xd7; + colorGreen = 0xd2; + colorBlue = 0xa4; + } else { + colorRed = DAT_UserHelpDefinedData::instance.field6_0x7a16c[colorIndex].r_0x4; + colorGreen = DAT_UserHelpDefinedData::instance.field6_0x7a16c[colorIndex].g_0x8; + colorBlue = DAT_UserHelpDefinedData::instance.field6_0x7a16c[colorIndex].b_0xc; + } + textMemIndex += 2; + color = ((colorBlue << 16) & 0xff0000) | ((colorGreen << 8) & 0x00ff00) | colorRed & 0x0000ff; + } else { + textMemIndex += 2; + } + continue; + } + case HTT_LINKCOLOUR: + if (this->helpDialogSubMode == 1) { + charColor = 0xff; + local_12c = 0; + MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, L"", + DAT_UserHelpDefinedData::instance + .field6_0x7a16c[this->DAT_PointerToTemporaryTextMemory[textMemIndex]] + .name_0x0); + textMemIndex += 2; + break; + } else { + if (param_1 == 1) { + int const colorIndex = this->DAT_PointerToTemporaryTextMemory[textMemIndex]; + textMemIndex += 2; + linkColor + = ((DAT_UserHelpDefinedData::instance.field6_0x7a16c[colorIndex].b_0xc << 16) & 0xff0000) + | ((DAT_UserHelpDefinedData::instance.field6_0x7a16c[colorIndex].g_0x8 << 8) & 0x00ff00) + | DAT_UserHelpDefinedData::instance.field6_0x7a16c[colorIndex].r_0x4 & 0x0000ff; + } else { + textMemIndex += 2; + } + continue; + } + case HTT_LINK: + if (this->helpDialogSubMode == 1) { + charColor = 0xff; + local_12c = 0; + MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, L"", + DAT_UserHelpDefinedData::instance + .HelpSections[this->DAT_PointerToTemporaryTextMemory[textMemIndex]]); + textMemIndex += 2; + break; + } else { + currentLinkId = this->DAT_PointerToTemporaryTextMemory[textMemIndex]; + if (param_1 == 1) { + DAT_TextManagerObject::instance.field6_0x18 = 1; + } + textMemIndex += 2; + continue; + } + case HTT_INCLUDE: + if (this->helpDialogSubMode == 1) { + charColor = 0xff; + local_12c = 0; + MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, L"", + DAT_UserHelpDefinedData::instance + .HelpSections[this->DAT_PointerToTemporaryTextMemory[textMemIndex]]); + textMemIndex += 2; + break; + } else { + textMemIndex += 2; + continue; + } + case HTT_SOUND: + if (this->helpDialogSubMode == 1) { + charColor = 0xff; + local_12c = 0; + MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, L"", + this->soundFileNames[this->DAT_PointerToTemporaryTextMemory[textMemIndex]]); + textMemIndex += 2; + break; + } else { + if (param_1 == 1 && -1 < lineY - this->helpContentScrollOffsetY + && lineY - this->helpContentScrollOffsetY < this->dialogContentWidth + && !this->soundFilePlayedFlags[this->DAT_PointerToTemporaryTextMemory[textMemIndex]]) { + this->soundFilePlayedFlags[this->DAT_PointerToTemporaryTextMemory[textMemIndex]] = 1; + } + textMemIndex += 2; + continue; + } + case HTT_ENDLINK: + if (this->helpDialogSubMode == 1) { + charColor = 0xff; + local_12c = 0; + wcscpy(wideTextBuffer, L"<\\LINK>"); + break; + } else { + currentLinkId = -1; + if (param_1 == 1) { + DAT_TextManagerObject::instance.field6_0x18 = 0; + } + continue; + } + case (wchar_t*)13: // unknown case? + default: + pwVar6 = textMemUnion.text; + goto switchD_00460064_caseD_d; + case HTT_STRING: + if (this->helpDialogSubMode == 1) { + charColor = 0xff; + local_12c = 0; + MACRO_CALL(Global_Func::PrintToDestination)( + wideTextBuffer, L"", this->DAT_PointerToTemporaryTextMemory[textMemIndex]); + textMemIndex += 2; + break; + } else { + textMemIndex += 2; + continue; + } + case HTT_CENTRE: + if (this->helpDialogSubMode == 1) { + charColor = 0xff; + local_12c = 0; + wcscpy(wideTextBuffer, L""); + break; + } else { + centreActive = TRUE; + local_120 = TRUE; + continue; + } + case HTT_ENDCENTRE: + if (this->helpDialogSubMode == 1) { + charColor = 0xff; + local_12c = 0; + wcscpy(wideTextBuffer, L"<\\CENTRE>"); + break; + } else { + centreActive = FALSE; + continue; + } + case HTT_NEWPARAGRAPH: + if (local_120) { + this->lineLayoutTable[lineY].unknown2 = this->lineLayoutTable[lineY].rightBorder - leftPosition; + local_120 = centreActive; + } + if (this->useAlternateHelpTab && iVar5 == this->activeHelpHotspotIndex) { + lineEndY = currentFontLineHeight + lineY; + iVar12 = 0; + lineStartY = lineY; + if (param_1 == 1) { + if (local_120) { + iVar12 = this->lineLayoutTable[lineY].unknown2 / 2; + } + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( + this->dialogContentX + iVar12 - 1 + leftPosition, + this->dialogContentY - this->helpContentScrollOffsetY - 1 + lineY, + this->dialogContentX + iVar12 - 1 + leftPosition, + this->dialogContentY - this->helpContentScrollOffsetY + 1 + lineEndY, + COL_DARK_LIME::instance.shortValue); + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( + this->dialogContentX + iVar12 + leftPosition, + this->dialogContentY - this->helpContentScrollOffsetY - 1 + lineY, + this->dialogContentX + iVar12 + leftPosition, + this->dialogContentY - this->helpContentScrollOffsetY + 1 + lineEndY, + COL_DARK_LIME::instance.shortValue); + local_e4 = TRUE; + } + } + lineY += 3 + currentFontLineHeight; + local_f0 = FALSE; + do { + leftPosition = this->lineLayoutTable[lineY++].leftBorder; + } while (leftPosition == -1); + currentFontLineHeight = currentFontClass->lineHeight_0x14; + iVar12 = local_11c; + if (this->useAlternateHelpTab != 0) { + local_100 = local_11c; + if (param_1 == 1) { + ++local_134; + if (0 < this->unknown_0x2396C && 1 < local_134) { + this->activeHelpHotspotIndex = local_10c + local_11c; + local_134 = -10000; + if (iVar5 <= this->activeHelpHotspotIndex) { + this->activeHelpHotspotIndex = iVar5 + -1; + } + this->unknown_0x2396C = 0; + } + } + iVar12 = iVar5; + if (iVar5 == this->activeHelpHotspotIndex && param_1 == 1) { + local_10c = 0; + if (this->unknown_0x2396C < 0) { + this->activeHelpHotspotIndex = DAT_00df3348::instance + local_11c; + if (iVar5 <= this->activeHelpHotspotIndex) { + this->activeHelpHotspotIndex = iVar5 + -1; + } + this->unknown_0x2396C = 0; + } + local_134 = 0; + } + } + local_11c = iVar12; + if (this->helpDialogSubMode == 1) { + charColor = 0xff; + local_12c = 0; + wcscpy(wideTextBuffer, L""); + break; + } + continue; + case HTT_TAB: // TODO?: unknown token + if (this->helpDialogSubMode == 1) { + charColor = 0xff; + local_12c = 0; + wcscpy(wideTextBuffer, L""); + break; + } else { + if (this->lineLayoutTable[lineY].rightBorder < leftPosition + 30) { + local_f0 = FALSE; + if (local_120) { + this->lineLayoutTable[lineY].unknown2 + = this->lineLayoutTable[lineY].rightBorder - leftPosition; + local_120 = centreActive; + } + do { + lineY += currentFontLineHeight + 1; + do { + leftPosition = this->lineLayoutTable[lineY++].leftBorder; + } while (leftPosition == -1); + } while (this->lineLayoutTable[lineY].rightBorder < leftPosition + 30); + iVar12 = local_11c; + if (this->useAlternateHelpTab && param_1 == 1) { + ++local_134; + local_100 = local_11c; + iVar12 = iVar5; + if (0 < this->unknown_0x2396C && 1 < local_134) { + this->activeHelpHotspotIndex = local_11c + local_10c; + local_134 = -10000; + if (iVar5 <= this->activeHelpHotspotIndex) { + this->activeHelpHotspotIndex = iVar5 + -1; + } + this->unknown_0x2396C = 0; + } + } + local_11c = iVar12; + currentFontLineHeight = currentFontClass->lineHeight_0x14; + } + leftPosition += 30; + continue; + } + case (wchar_t*)0: // TODO?: unknown token, or just NULL, meaning end? + if (param_1 == 0) { + this->topVisibleLineIndex = lineY + currentFontLineHeight - 1; + do { + ++this->topVisibleLineIndex; + if (this->lineLayoutTable[this->topVisibleLineIndex].leftBorder == 25 + && this->lineLayoutTable[this->topVisibleLineIndex].rightBorder + == this->dialogContentHeight - 25) { + break; + } + } while (this->topVisibleLineIndex < 20000); + this->topVisibleLineIndex += 5; + if (this->useAlternateHelpTab) { + if (lineStartY < this->helpContentScrollOffsetY) { + this->helpContentScrollOffsetY = lineStartY; + } + if (lineEndY > this->helpContentScrollOffsetY + this->dialogContentWidth) { + this->helpContentScrollOffsetY = (lineEndY - this->dialogContentWidth) + 5; + DAT_TextManagerObject::instance.field6_0x18 = 0; + return TRUE; + } + } + DAT_TextManagerObject::instance.field6_0x18 = 0; + return TRUE; + } + if (!this->useAlternateHelpTab) { + DAT_TextManagerObject::instance.field6_0x18 = 0; + return TRUE; + } + DAT_00df3348::instance = local_10c; + if (0 < this->unknown_0x2396C && local_134 == 1) { + this->activeHelpHotspotIndex = local_10c + local_11c; + if (this->activeHelpHotspotIndex > this->customHelpTextLength) { + this->activeHelpHotspotIndex = this->customHelpTextLength; + } + this->unknown_0x2396C = 0; + } + if (!local_e4 && this->activeHelpHotspotIndex && DAT_00df334c::instance) { + --this->activeHelpHotspotIndex; + this->unknown_0x23970 = 0; + DAT_TextManagerObject::instance.field6_0x18 = 0; + return TRUE; + } + DAT_00df334c::instance = 0; + DAT_TextManagerObject::instance.field6_0x18 = 0; + return TRUE; + } + // NOTE: This is either the local text buffer, or the text directly from the text memory... + pwVar6 = wideTextBuffer; + switchD_00460064_caseD_d: + if (0x1f < (int)pwVar6) { + iVar12 = MACRO_CALL_MEMBER(FontSizeClass_Func::getWidthOfWideText, currentFontClass)( + pwVar6, wcslen((wchar_t*)pwVar6)); + iVar5 = local_11c; + local_f4 = leftPosition + iVar12; + if (this->lineLayoutTable[lineY].rightBorder < local_f4) { + local_f0 = FALSE; + if (local_120) { + this->lineLayoutTable[lineY].unknown2 = this->lineLayoutTable[lineY].rightBorder - leftPosition; + local_120 = centreActive; + } + lineY += 1 + currentFontLineHeight; + do { + leftPosition = this->lineLayoutTable[lineY++].leftBorder; + } while (leftPosition == -1); + currentFontLineHeight = currentFontClass->lineHeight_0x14; + if (this->useAlternateHelpTab) { + ++local_134; + local_100 = local_11c; + local_11c = local_114; + if (0 < this->unknown_0x2396C && 1 < local_134) { + this->activeHelpHotspotIndex = iVar5 + local_10c; + local_134 = -10000; + if (local_114 <= this->activeHelpHotspotIndex) { + this->activeHelpHotspotIndex = local_114 - 1; + } + this->unknown_0x2396C = 0; + } + } + local_f4 = iVar12 + leftPosition; + if (this->lineLayoutTable[lineY].rightBorder < (int)local_f4) { + local_f8 = 0; + if (local_120) { + local_f8 = this->lineLayoutTable[lineY].unknown2 / 2; + } + int const wideStrLength = wcslen((wchar_t*)pwVar6); + for (local_118 = 0; local_118 < wideStrLength; ++local_118) { + int wideCharWidth = MACRO_CALL_MEMBER( + FontSizeClass_Func::getWideCharWidth, currentFontClass)(textMemUnion.text[local_118]); + while (this->lineLayoutTable[lineY].rightBorder < leftPosition + wideCharWidth) { + iVar5 = local_11c; + if (local_120) { + this->lineLayoutTable[lineY].unknown2 + = this->lineLayoutTable[lineY].rightBorder - leftPosition; + local_120 = centreActive; + } + lineY += currentFontLineHeight + 1; + if (this->useAlternateHelpTab && param_1 == 1) { + ++local_134; + local_100 = local_11c; + local_11c = local_114 + local_118; + if (0 < this->unknown_0x2396C && 1 < local_134) { + this->activeHelpHotspotIndex = iVar5 + local_10c; + local_134 = -10000; + if (local_114 + local_118 <= this->activeHelpHotspotIndex) { + this->activeHelpHotspotIndex = local_114 + local_118 - 1; + } + this->unknown_0x2396C = 0; + } + } + do { + leftPosition = this->lineLayoutTable[lineY++].leftBorder; + } while (leftPosition == -1); + if (local_120) { + local_f8 = this->lineLayoutTable[lineY].unknown2 / 2; + } + } + if (!this->useAlternateHelpTab || local_114 + local_118 != this->activeHelpHotspotIndex) { + if (param_1 == 1) { + iVar5 = MACRO_CALL_MEMBER(FontSizeClass_Func::renderWideChar, currentFontClass)( + textMemUnion.text[local_118], this->dialogContentX + local_f8 + leftPosition, + this->dialogContentY - this->helpContentScrollOffsetY + lineY, charColor, 0); + local_f0 = TRUE; + if (MACRO_CALL_MEMBER( + Input::MouseState_Func::isMouseInsideBox, DAT_MouseState::ptr)( + this->dialogContentX + local_f8 + leftPosition - this->helpContentScrollX, + this->dialogContentY - this->helpContentScrollOffsetY + lineY + - this->helpContentScrollY, + iVar5 - this->dialogContentX + local_f8 + leftPosition, + currentFontLineHeight + 2)) { + if (local_12c) { + this->unknown_0x23964 = local_114 + local_118; + this->unknown_0x23968 = currentLinkId; + } else { + this->unknown_0x23964 = local_114; + } + } + } + } else { + lineEndY = lineY + currentFontLineHeight; + lineStartY = lineY; + if (param_1 == 1) { + if (local_12c) { + local_10c = (local_118 - local_11c) + local_114; + if (this->unknown_0x2396C < 0) { + this->activeHelpHotspotIndex = DAT_00df3348::instance + local_100; + if (this->activeHelpHotspotIndex >= local_11c) { + this->activeHelpHotspotIndex = local_11c - 1; + } + this->unknown_0x2396C = 0; + } + local_134 = 0; + MACRO_CALL_MEMBER( + UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( + this->dialogContentX + local_f8 - 1 + leftPosition, + this->dialogContentY - this->helpContentScrollOffsetY + -1 + lineY, + this->dialogContentX + local_f8 - 1 + leftPosition, + this->dialogContentY - this->helpContentScrollOffsetY + 1 + lineEndY, + COL_DARK_LIME::instance.shortValue); + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, + DAT_PencilRenderCore::ptr)(this->dialogContentX + local_f8 + leftPosition, + this->dialogContentY - this->helpContentScrollOffsetY - 1 + lineY, + this->dialogContentX + local_f8 + leftPosition, + this->dialogContentY - this->helpContentScrollOffsetY + 1 + lineEndY, + COL_DARK_LIME::instance.shortValue); + local_e4 = TRUE; + } + iVar5 = MACRO_CALL_MEMBER(FontSizeClass_Func::renderWideChar, currentFontClass)( + textMemUnion.text[local_118], this->dialogContentX + local_f8 + leftPosition, + this->dialogContentY - this->helpContentScrollOffsetY + lineY, charColor, 0); + local_f0 = TRUE; + if (MACRO_CALL_MEMBER( + Input::MouseState_Func::isMouseInsideBox, DAT_MouseState::ptr)( + this->dialogContentX + local_f8 + leftPosition - this->helpContentScrollX, + this->dialogContentY - this->helpContentScrollOffsetY + lineY + - this->helpContentScrollY, + iVar5 - this->dialogContentX + local_f8 + leftPosition, + currentFontLineHeight + 2)) { + if (local_12c) { + this->unknown_0x23964 = local_114 + local_118; + this->unknown_0x23968 = currentLinkId; + } else { + this->unknown_0x23964 = local_114; + } + } + } + } + leftPosition += wideCharWidth; + } + continue; + } + } + iVar5 = this->dialogContentX + leftPosition; + local_104 = (this->dialogContentY - this->helpContentScrollOffsetY) + lineY; + if (local_120) { + iVar5 += this->lineLayoutTable[lineY].unknown2 / 2; + } + int const wideStrLength = wcslen((wchar_t*)pwVar6); + for (int i = 0; i < wideStrLength; ++i) { + local_f8 = local_114 - local_11c; + if ((this->useAlternateHelpTab == 0) || (i + local_114 != this->activeHelpHotspotIndex)) { + if (param_1 == 1) { + local_f0 = TRUE; + iVar12 = MACRO_CALL_MEMBER(FontSizeClass_Func::renderWideChar, currentFontClass)( + textMemUnion.text[i], iVar5, local_104, charColor, 0); + if (MACRO_CALL_MEMBER(Input::MouseState_Func::isMouseInsideBox, DAT_MouseState::ptr)( + iVar5 - this->helpContentScrollX, local_104 - this->helpContentScrollY, + iVar12 - iVar5, currentFontLineHeight + 2)) { + if (local_12c) { + this->unknown_0x23964 = i + local_114; + this->unknown_0x23968 = currentLinkId; + } else { + this->unknown_0x23964 = local_114; + } + } + } else { + dVar14 = MACRO_CALL_MEMBER(FontSizeClass_Func::getWideCharWidth, currentFontClass)( + textMemUnion.text[i]); + iVar12 = iVar5 + dVar14; + } + } else { + if (param_1 == 1 && local_12c) { + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, + DAT_PencilRenderCore::ptr)(iVar5 + -1, local_104 - 1, iVar5 + -1, + local_104 + 1 + currentFontLineHeight, COL_DARK_LIME::instance.shortValue); + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, + DAT_PencilRenderCore::ptr)(iVar5, local_104 - 1, iVar5, + local_104 + 1 + currentFontLineHeight, COL_DARK_LIME::instance.shortValue); + local_e4 = TRUE; + } + lineEndY = lineY + currentFontLineHeight; + lineStartY = lineY; + if (param_1 == 1) { + local_10c = local_f8 + i; + local_134 = 0; + if (this->unknown_0x2396C < 0 && local_12c) { + this->activeHelpHotspotIndex = local_100 + DAT_00df3348::instance; + if (this->activeHelpHotspotIndex >= local_11c) { + this->activeHelpHotspotIndex = local_11c + -1; + } + this->unknown_0x2396C = 0; + } + local_f0 = TRUE; + iVar12 = MACRO_CALL_MEMBER(FontSizeClass_Func::renderWideChar, currentFontClass)( + textMemUnion.text[i], iVar5, local_104, charColor, 0); + if (MACRO_CALL_MEMBER(Input::MouseState_Func::isMouseInsideBox, DAT_MouseState::ptr)( + iVar5 - this->helpContentScrollX, local_104 - this->helpContentScrollY, + iVar12 - iVar5, currentFontLineHeight + 2)) { + if (local_12c) { + this->unknown_0x23964 = i + local_114; + this->unknown_0x23968 = currentLinkId; + } else { + this->unknown_0x23964 = local_114; + } + } + } else { + dVar14 = MACRO_CALL_MEMBER(FontSizeClass_Func::getWideCharWidth, currentFontClass)( + textMemUnion.text[i]); + iVar12 = iVar5 + dVar14; + } + } + iVar5 = iVar12; + } + leftPosition = local_f4; + } + } + } + +} +} From a21f1db29ab3cef1f205626716ab35fa8cab0d05 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Mon, 21 Sep 2026 23:08:06 +0200 Subject: [PATCH 42/44] reimplement: OpenSHC::Text::TextEditorState adapt to upstream changes --- src/OpenSHC/OS/OS.cpp | 2 +- src/OpenSHC/Text/TextEditorState.hpp | 11 +- .../Constructor_TextEditorState.cpp | 6 +- .../bltTextToScreenIfNeedBe.cpp | 4 +- .../TextEditorState/drawBorderStyle0x20.cpp | 6 +- .../drawHelpWindowBackground.cpp | 4 +- .../Text/TextEditorState/helpToken.cpp | 16 +- .../initializeAndLayoutHelpText.cpp | 2 +- .../openBuildingHelpDialog.cpp | 4 +- .../openCreditsScrollDialog.cpp | 4 +- .../TextEditorState/openInGameHelpDialog.cpp | 4 +- .../openMapDescriptionEditorDialog.cpp | 4 +- .../openScenarioHelpDialog.cpp | 4 +- .../openUnusedHelpTextEditorDialog.cpp | 10 +- src/OpenSHC/Text/TextEditorState/parseHlp.cpp | 101 +++++----- .../processHelpRichTextTokens.cpp | 174 +++++++++--------- .../TextEditorState/readCrusaderHelpHlp.cpp | 5 +- .../renderHelpImageHotspots.cpp | 10 +- .../saveHelpFileToResource.cpp | 84 ++++----- .../TextEditorState/setHelpWindowBounds.cpp | 4 +- .../TextEditorState/setTextRenderingLogic.cpp | 8 +- 21 files changed, 232 insertions(+), 235 deletions(-) diff --git a/src/OpenSHC/OS/OS.cpp b/src/OpenSHC/OS/OS.cpp index e300ed41a..686831bf5 100644 --- a/src/OpenSHC/OS/OS.cpp +++ b/src/OpenSHC/OS/OS.cpp @@ -85,7 +85,7 @@ namespace OS { wchar_t* _wcsncpy(wchar_t* _Dest, wchar_t* _Source, size_t _Count) { return wcsncpy(_Dest, _Source, _Count); } // STUB: STRONGHOLDCRUSADER 0x00580B69 - int __wcsicmp(wchar_t* _Str1, wchar_t* _Str2) { return _wcsicmp(_Str1, _Str2); } + int __wcsicmp(wchar_t const* _Str1, wchar_t const* _Str2) { return _wcsicmp(_Str1, _Str2); } // Only jumps to _free in game version // STUB: STRONGHOLDCRUSADER 0x00580DC1 diff --git a/src/OpenSHC/Text/TextEditorState.hpp b/src/OpenSHC/Text/TextEditorState.hpp index be0f30e8e..713559868 100644 --- a/src/OpenSHC/Text/TextEditorState.hpp +++ b/src/OpenSHC/Text/TextEditorState.hpp @@ -20,16 +20,9 @@ namespace OpenSHC { namespace Text { - struct ImageHotspot { - short xPos; - short yPos; - short imageRelated; - short unknown3; - }; - struct LineLayout { - short unknown0; - short unknown1; + short leftBorder; + short rightBorder; short unknown2; }; diff --git a/src/OpenSHC/Text/TextEditorState/Constructor_TextEditorState.cpp b/src/OpenSHC/Text/TextEditorState/Constructor_TextEditorState.cpp index afb18c1b7..e98ffe2c0 100644 --- a/src/OpenSHC/Text/TextEditorState/Constructor_TextEditorState.cpp +++ b/src/OpenSHC/Text/TextEditorState/Constructor_TextEditorState.cpp @@ -8,11 +8,11 @@ namespace OpenSHC { namespace Text { // FUNCTION: STRONGHOLDCRUSADER 0x0045F130 - TextEditorState* TextEditorState ::Constructor_TextEditorState() + TextEditorState* TextEditorState::Constructor_TextEditorState() { this->isDialogStateInitialized = 0; this->helpDialogVariant = 0; - this->unknown_0x23960 = 0; + this->field48_0x23960 = 0; this->helpDialogSubMode = 0; this->useAlternateHelpTab = 0; this->customHelpTextLength = 0; @@ -21,7 +21,7 @@ namespace Text { MACRO_CALL_MEMBER(TextEditorState_Func::resetHelpStateFields, this)(); - this->DAT_PointerToTemporaryTextMemory = MACRO_CALL(OS_Func::_malloc)(40000); + this->DAT_PointerToTemporaryTextMemory = (LPWSTR)MACRO_CALL(OS_Func::_malloc)(40000); this->customTextMaxLength = -1; // FIXME:: Requires a finishing zero case, or it will not set the counter diff --git a/src/OpenSHC/Text/TextEditorState/bltTextToScreenIfNeedBe.cpp b/src/OpenSHC/Text/TextEditorState/bltTextToScreenIfNeedBe.cpp index d6bb78b88..8e81abad4 100644 --- a/src/OpenSHC/Text/TextEditorState/bltTextToScreenIfNeedBe.cpp +++ b/src/OpenSHC/Text/TextEditorState/bltTextToScreenIfNeedBe.cpp @@ -11,7 +11,7 @@ namespace Text { // FUNCTION: STRONGHOLDCRUSADER 0x0045D690 void TextEditorState::bltTextToScreenIfNeedBe() { - if (!DAT_TextEditorState::instance.unknown_0x23960) { + if (!DAT_TextEditorState::instance.field48_0x23960) { return; } if (this->savedMenuViewType == UI::Enums::MVT_MAP_EDITOR_LANDSCAPING @@ -20,7 +20,7 @@ namespace Text { MACRO_CALL_MEMBER(UI::Rendering::WindowAndDirectDraw_Func::bltMapGameSurfaceToScreenMenuSurfaceComplete, DAT_WindowAndDirectDraw::ptr)(); } - DAT_TextEditorState::instance.unknown_0x23960 = FALSE; + DAT_TextEditorState::instance.field48_0x23960 = FALSE; } } diff --git a/src/OpenSHC/Text/TextEditorState/drawBorderStyle0x20.cpp b/src/OpenSHC/Text/TextEditorState/drawBorderStyle0x20.cpp index c36e3e66a..bb01a0ba2 100644 --- a/src/OpenSHC/Text/TextEditorState/drawBorderStyle0x20.cpp +++ b/src/OpenSHC/Text/TextEditorState/drawBorderStyle0x20.cpp @@ -22,12 +22,12 @@ namespace Text { // FIXME: ContentHeight and ContentWidth or the dialogWidth and dialogHeight are swapped int const contentX = this->dialogX + DAT_00df2964::instance; int const contentY = this->dialogY + DAT_00df296c::instance; - int const contentWidth = this->dialogHeight - INT_00df2970::instance; - int const contentHeight = this->dialogWidth - INT_00df2968::instance; + int const contentHeight = this->dialogHeight - INT_00df2970::instance; + int const contentWidth = this->dialogWidth - INT_00df2968::instance; this->dialogContentX = contentX; this->dialogContentY = contentY; - this->dialogContentHeight = contentHeight; this->dialogContentWidth = contentWidth; + this->dialogContentHeight = contentHeight; this->helpContentScrollX = DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetX; this->helpContentScrollY = DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetY; diff --git a/src/OpenSHC/Text/TextEditorState/drawHelpWindowBackground.cpp b/src/OpenSHC/Text/TextEditorState/drawHelpWindowBackground.cpp index ac5555d62..82378f4ff 100644 --- a/src/OpenSHC/Text/TextEditorState/drawHelpWindowBackground.cpp +++ b/src/OpenSHC/Text/TextEditorState/drawHelpWindowBackground.cpp @@ -34,8 +34,8 @@ namespace Text { this->dialogX, this->dialogY, this->dialogWidth + this->dialogX, this->dialogHeight + this->dialogY, COL_VERY_DARK_GREY::instance.shortValue); MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawColorBox, DAT_PencilRenderCore::ptr)( - this->dialogContentX, this->dialogContentY, this->dialogContentHeight + this->dialogContentX, - this->dialogContentWidth + this->dialogContentY, COL_BLACK::instance.shortValue); + this->dialogContentX, this->dialogContentY, this->dialogContentWidth + this->dialogContentX, + this->dialogContentHeight + this->dialogContentY, COL_BLACK::instance.shortValue); MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawColorBox, DAT_PencilRenderCore::ptr)( this->dialogX, this->dialogY + this->dialogHeight, this->dialogWidth + this->dialogX, this->dialogY + this->dialogHeight + 60, COL_DARK_CYAN_GREY::instance.shortValue); diff --git a/src/OpenSHC/Text/TextEditorState/helpToken.cpp b/src/OpenSHC/Text/TextEditorState/helpToken.cpp index 6931a374e..8cfb867ff 100644 --- a/src/OpenSHC/Text/TextEditorState/helpToken.cpp +++ b/src/OpenSHC/Text/TextEditorState/helpToken.cpp @@ -7,16 +7,16 @@ namespace Text { int TextEditorState::helpToken_getHelpTokenAdvanceLength(HelpTextToken token) { switch (token) { - case HTT_PIC: + case Enums::HTT_PIC: return 4; - case HTT_FONT: - case HTT_COLOUR: - case HTT_LINK: - case HTT_LINKCOLOUR: - case HTT_SOUND: - case HTT_STRING: - case HTT_INCLUDE: + case Enums::HTT_FONT: + case Enums::HTT_COLOUR: + case Enums::HTT_LINK: + case Enums::HTT_LINKCOLOUR: + case Enums::HTT_SOUND: + case Enums::HTT_STRING: + case Enums::HTT_INCLUDE: return 3; default: diff --git a/src/OpenSHC/Text/TextEditorState/initializeAndLayoutHelpText.cpp b/src/OpenSHC/Text/TextEditorState/initializeAndLayoutHelpText.cpp index 99fef53e0..ac6882fef 100644 --- a/src/OpenSHC/Text/TextEditorState/initializeAndLayoutHelpText.cpp +++ b/src/OpenSHC/Text/TextEditorState/initializeAndLayoutHelpText.cpp @@ -8,7 +8,7 @@ namespace Text { { for (int i = 0; i < 20000; ++i) { this->lineLayoutTable[i].leftBorder = 25; - this->lineLayoutTable[i].rightBorder = this->dialogContentHeight - 25; + this->lineLayoutTable[i].rightBorder = this->dialogContentWidth - 25; this->lineLayoutTable[i].unknown2 = 0; } // Adds vertical space at start diff --git a/src/OpenSHC/Text/TextEditorState/openBuildingHelpDialog.cpp b/src/OpenSHC/Text/TextEditorState/openBuildingHelpDialog.cpp index fd849ca46..5c40b0e56 100644 --- a/src/OpenSHC/Text/TextEditorState/openBuildingHelpDialog.cpp +++ b/src/OpenSHC/Text/TextEditorState/openBuildingHelpDialog.cpp @@ -62,8 +62,8 @@ namespace Text { int const dialogContentWidth = this->dialogWidth - INT_00df2968::instance; this->dialogContentX = dialogContentX; this->dialogContentY = dialogContentY; - this->dialogContentHeight = dialogContentWidth; - this->dialogContentWidth = dialogContentHeight; + this->dialogContentWidth = dialogContentWidth; + this->dialogContentHeight = dialogContentHeight; for (int i = 28; i >= 0; --i) { this->helpSectionHistoryStack[i + 1] = this->helpSectionHistoryStack[i]; diff --git a/src/OpenSHC/Text/TextEditorState/openCreditsScrollDialog.cpp b/src/OpenSHC/Text/TextEditorState/openCreditsScrollDialog.cpp index cc8d182e5..f7b398bae 100644 --- a/src/OpenSHC/Text/TextEditorState/openCreditsScrollDialog.cpp +++ b/src/OpenSHC/Text/TextEditorState/openCreditsScrollDialog.cpp @@ -56,8 +56,8 @@ namespace Text { int const dialogContentWidth = this->dialogWidth - INT_00df2968::instance; this->dialogContentX = dialogContentX; this->dialogContentY = dialogContentY; - this->dialogContentHeight = dialogContentWidth; - this->dialogContentWidth = dialogContentHeight; + this->dialogContentWidth = dialogContentWidth; + this->dialogContentHeight = dialogContentHeight; for (int i = 28; i >= 0; --i) { this->helpSectionHistoryStack[i + 1] = this->helpSectionHistoryStack[i]; diff --git a/src/OpenSHC/Text/TextEditorState/openInGameHelpDialog.cpp b/src/OpenSHC/Text/TextEditorState/openInGameHelpDialog.cpp index cdb41b1d7..f8c1c455b 100644 --- a/src/OpenSHC/Text/TextEditorState/openInGameHelpDialog.cpp +++ b/src/OpenSHC/Text/TextEditorState/openInGameHelpDialog.cpp @@ -57,8 +57,8 @@ namespace Text { int const dialogContentWidth = this->dialogWidth - INT_00df2968::instance; this->dialogContentX = dialogContentX; this->dialogContentY = dialogContentY; - this->dialogContentHeight = dialogContentWidth; - this->dialogContentWidth = dialogContentHeight; + this->dialogContentWidth = dialogContentWidth; + this->dialogContentHeight = dialogContentHeight; for (int i = 28; i >= 0; --i) { this->helpSectionHistoryStack[i + 1] = this->helpSectionHistoryStack[i]; diff --git a/src/OpenSHC/Text/TextEditorState/openMapDescriptionEditorDialog.cpp b/src/OpenSHC/Text/TextEditorState/openMapDescriptionEditorDialog.cpp index ab6933b08..d024a872a 100644 --- a/src/OpenSHC/Text/TextEditorState/openMapDescriptionEditorDialog.cpp +++ b/src/OpenSHC/Text/TextEditorState/openMapDescriptionEditorDialog.cpp @@ -58,8 +58,8 @@ namespace Text { int const dialogContentWidth = this->dialogWidth - INT_00df2968::instance; this->dialogContentX = dialogContentX; this->dialogContentY = dialogContentY; - this->dialogContentHeight = dialogContentWidth; - this->dialogContentWidth = dialogContentHeight; + this->dialogContentWidth = dialogContentWidth; + this->dialogContentHeight = dialogContentHeight; for (int i = 28; i >= 0; --i) { this->helpSectionHistoryStack[i + 1] = this->helpSectionHistoryStack[i]; diff --git a/src/OpenSHC/Text/TextEditorState/openScenarioHelpDialog.cpp b/src/OpenSHC/Text/TextEditorState/openScenarioHelpDialog.cpp index cbe2b44f4..8ce0c7f67 100644 --- a/src/OpenSHC/Text/TextEditorState/openScenarioHelpDialog.cpp +++ b/src/OpenSHC/Text/TextEditorState/openScenarioHelpDialog.cpp @@ -57,8 +57,8 @@ namespace Text { int const dialogContentWidth = this->dialogWidth - INT_00df2968::instance; this->dialogContentX = dialogContentX; this->dialogContentY = dialogContentY; - this->dialogContentHeight = dialogContentWidth; - this->dialogContentWidth = dialogContentHeight; + this->dialogContentWidth = dialogContentWidth; + this->dialogContentHeight = dialogContentHeight; for (int i = 28; i >= 0; --i) { this->helpSectionHistoryStack[i + 1] = this->helpSectionHistoryStack[i]; diff --git a/src/OpenSHC/Text/TextEditorState/openUnusedHelpTextEditorDialog.cpp b/src/OpenSHC/Text/TextEditorState/openUnusedHelpTextEditorDialog.cpp index 45951bd8d..9ffdd0038 100644 --- a/src/OpenSHC/Text/TextEditorState/openUnusedHelpTextEditorDialog.cpp +++ b/src/OpenSHC/Text/TextEditorState/openUnusedHelpTextEditorDialog.cpp @@ -30,7 +30,7 @@ namespace Text { this->savedMenuViewType = DAT_GameCore::instance.currentMenuViewType; this->savedActiveMenuTab = DAT_GameCore::instance.activeMenuTab.tabType; this->savedMenuFlag = DAT_GameCore::instance.unknownAlwaysZero01; - this->unknown_0x23960 = 1; + this->field48_0x23960 = 1; this->isDialogStateInitialized = TRUE; this->useInGameHelpHandler = FALSE; this->helpDialogVariant = 0; @@ -72,13 +72,13 @@ namespace Text { if (!this->useWideHelpLayout) { this->dialogContentX = this->dialogX + 10; this->dialogContentY = this->dialogY + 10; - this->dialogContentHeight = 600; - this->dialogContentWidth = 435; + this->dialogContentWidth = 600; + this->dialogContentHeight = 435; } else { this->dialogContentX = this->dialogX + 10; this->dialogContentY = this->dialogY + 10; - this->dialogContentHeight = 664; - this->dialogContentWidth = 291; + this->dialogContentWidth = 664; + this->dialogContentHeight = 291; } for (int i = 28; i >= 0; --i) { diff --git a/src/OpenSHC/Text/TextEditorState/parseHlp.cpp b/src/OpenSHC/Text/TextEditorState/parseHlp.cpp index 792efc700..cfc8eb8fb 100644 --- a/src/OpenSHC/Text/TextEditorState/parseHlp.cpp +++ b/src/OpenSHC/Text/TextEditorState/parseHlp.cpp @@ -4,6 +4,9 @@ #include "OpenSHC/OS.func.hpp" #include "OpenSHC/UI/Rendering/TextureRenderCore.func.hpp" #include "OpenSHC/Util/WideCharMultiByteState.func.hpp" +#include "OpenSHC/Text/Enums/HelpTextPicturePositionToken.hpp" +#include "OpenSHC/wstring-literals.hpp" +#include "OpenSHC/string-literals.hpp" #include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" #include "OpenSHC/Globals/DAT_TextEditorState.hpp" @@ -14,8 +17,6 @@ namespace OpenSHC { namespace Text { - // TODO: fix L-strings - // FUNCTION: STRONGHOLDCRUSADER 0x0045F5B0 void TextEditorState::parseHlp() { @@ -52,23 +53,23 @@ namespace Text { wchar_t* hlpTag = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)(filePointer[_filePointerIndex]); if (hlpTag) { - if (!MACRO_CALL(OS_Func::__wcsicmp)(L"header", hlpTag)) { + if (!MACRO_CALL(OS_Func::__wcsicmp)(u_header_005a5774, hlpTag)) { headerActive = TRUE; continue; - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"\\header", hlpTag)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u__header_005a5764, hlpTag)) { headerActive = FALSE; continue; - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"body", hlpTag)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u_body_005a5758, hlpTag)) { bodyActive = TRUE; continue; - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"\\body", hlpTag)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u__body_005a574c, hlpTag)) { bodyActive = FALSE; continue; - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"loadpic", hlpTag)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u_loadpic_005a573c, hlpTag)) { if (headerActive) { wchar_t* resourceName = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( filePointer[_filePointerIndex]); @@ -83,7 +84,7 @@ namespace Text { DAT_TextureRenderCoreObject::ptr)(resourceNameChars)) { validPic = false; } else if (!MACRO_CALL(OS_Func::__stricmp)( - resourceNameChars, "st99_dog_cage.tgx")) { + resourceNameChars, s_st99_dog_cage_tgx_005a5728)) { validPic = false; } if (!validPic) { @@ -97,7 +98,7 @@ namespace Text { } } - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"pic", hlpTag)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u_pic_005a5720, hlpTag)) { if (bodyActive) { wchar_t* picId = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( filePointer[_filePointerIndex]); @@ -105,7 +106,7 @@ namespace Text { if (MACRO_CALL(OS_Func::__wtol)(picId) < loadedGraphics[_filePointerIndex]) { if (graphicIndexes[_filePointerIndex][MACRO_CALL(OS_Func::__wtol)(picId)] != -1) { - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_PIC; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_PIC; this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = graphicIndexes[_filePointerIndex][MACRO_CALL(OS_Func::__wtol)(picId)]; wchar_t* picPosition = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, @@ -113,21 +114,21 @@ namespace Text { if (!picPosition) { closeFile = TRUE; } else { - if (!MACRO_CALL(OS_Func::__wcsicmp)(L"left", picPosition)) { + if (!MACRO_CALL(OS_Func::__wcsicmp)(u_left_005a5714, picPosition)) { this->DAT_PointerToTemporaryTextMemory[textMemIndex++] - = HTT_PIC_LEFT; - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"right", picPosition)) { + = Enums::HTPPT_LEFT; + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u_right_005a5708, picPosition)) { this->DAT_PointerToTemporaryTextMemory[textMemIndex++] - = HTT_PIC_RIGHT; - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"centre", picPosition)) { + = Enums::HTPPT_RIGHT; + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u_centre_005a56f8, picPosition)) { this->DAT_PointerToTemporaryTextMemory[textMemIndex++] - = HTT_PIC_CENTRE; - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"here", picPosition)) { + = Enums::HTPPT_CENTRE; + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u_here_005a56ec, picPosition)) { this->DAT_PointerToTemporaryTextMemory[textMemIndex++] - = HTT_PIC_HERE; + = Enums::HTPPT_HERE; } } - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_PIC; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_PIC; continue; } } @@ -139,46 +140,46 @@ namespace Text { } } - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"font", hlpTag)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u_font_005a56e0, hlpTag)) { if (bodyActive) { wchar_t* fontId = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( filePointer[_filePointerIndex]); if (fontId) { - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_FONT; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_FONT; this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = (short)MACRO_CALL(OS_Func::__wtol)(fontId); - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_FONT; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_FONT; continue; } } - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"colour", hlpTag)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u_colour_005a56d0, hlpTag)) { if (bodyActive) { wchar_t* colorId = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( filePointer[_filePointerIndex]); if (colorId) { - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_COLOUR; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_COLOUR; this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = (short)MACRO_CALL(OS_Func::__wtol)(colorId); - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_COLOUR; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_COLOUR; continue; } } - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"linkcolour", hlpTag)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u_linkcolour_005a56b8, hlpTag)) { if (bodyActive) { wchar_t* linkColorId = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( filePointer[_filePointerIndex]); if (linkColorId) { - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_LINKCOLOUR; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_LINKCOLOUR; this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = (short)MACRO_CALL(OS_Func::__wtol)(linkColorId); - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_LINKCOLOUR; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_LINKCOLOUR; continue; } } - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"link", hlpTag)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u_link_005a56ac, hlpTag)) { if (bodyActive) { wchar_t* linkName = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( filePointer[_filePointerIndex]); @@ -188,38 +189,38 @@ namespace Text { DAT_WideCharMultiByteState::ptr)(linkNameChars, linkName); int const helpSectionIndex = MACRO_CALL_MEMBER( TextEditorState_Func::findOrAddHelpSectionName, this)(linkNameChars); - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_LINK; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_LINK; this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = helpSectionIndex; - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_LINK; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_LINK; continue; } } - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"\\link", hlpTag)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u__link_005a56a0, hlpTag)) { if (bodyActive) { - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_ENDLINK; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_ENDLINK; continue; } - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"newparagraph", hlpTag)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u_newparagraph_005a5684, hlpTag)) { if (bodyActive) { - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_NEWPARAGRAPH; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_NEWPARAGRAPH; continue; } - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"centre", hlpTag)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u_centre_005a56f8, hlpTag)) { if (bodyActive) { - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_CENTRE; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_CENTRE; continue; } - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"\\centre", hlpTag)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u__centre_005a5674, hlpTag)) { if (bodyActive) { - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_ENDCENTRE; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_ENDCENTRE; continue; } - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"sound", hlpTag)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u_sound_005a5668, hlpTag)) { if (bodyActive) { wchar_t* soundName = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( filePointer[_filePointerIndex]); @@ -229,14 +230,14 @@ namespace Text { DAT_WideCharMultiByteState::ptr)(soundNameChars, soundName); int const soundIndex = MACRO_CALL_MEMBER( TextEditorState_Func::findOrAddSoundName, this)(soundNameChars); - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_SOUND; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_SOUND; this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = soundIndex; - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_SOUND; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_SOUND; continue; } } - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"include", hlpTag)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u_include_005a5658, hlpTag)) { if (bodyActive) { if (DAT_TextEditorState::instance.useAlternateHelpTab) { wchar_t* includeName = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( @@ -248,9 +249,9 @@ namespace Text { DAT_WideCharMultiByteState::ptr)(includeNameChars, includeName); int const helpSectionIndex = MACRO_CALL_MEMBER( TextEditorState_Func::findOrAddHelpSectionName, this)(includeNameChars); - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_INCLUDE; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_INCLUDE; this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = helpSectionIndex; - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_INCLUDE; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_INCLUDE; continue; } } else { @@ -275,7 +276,7 @@ namespace Text { } } - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"string", hlpTag)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u_string_005a5648, hlpTag)) { if (bodyActive) { wchar_t* stringId = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)( filePointer[_filePointerIndex]); @@ -290,7 +291,7 @@ namespace Text { wchar_t const ch = this->intArray1[textIndex][i++]; if (ch == L'\n') { this->DAT_PointerToTemporaryTextMemory[textMemIndex++] - = HTT_NEWPARAGRAPH; + = Enums::HTT_NEWPARAGRAPH; } else if (ch >= L' ') { this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = ch; } @@ -298,15 +299,15 @@ namespace Text { } } else { - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_STRING; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_STRING; this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = (short)MACRO_CALL(OS_Func::__wtol)(stringId); - this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = HTT_STRING; + this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTT_STRING; } continue; } } - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(L"\\section", hlpTag)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u__section_005a5634, hlpTag)) { closeFile = TRUE; continue; } else { diff --git a/src/OpenSHC/Text/TextEditorState/processHelpRichTextTokens.cpp b/src/OpenSHC/Text/TextEditorState/processHelpRichTextTokens.cpp index 837af17dd..760bec549 100644 --- a/src/OpenSHC/Text/TextEditorState/processHelpRichTextTokens.cpp +++ b/src/OpenSHC/Text/TextEditorState/processHelpRichTextTokens.cpp @@ -7,6 +7,8 @@ #include "OpenSHC/Input/MouseState.func.hpp" #include "OpenSHC/Text/FontSizeClass.func.hpp" #include "OpenSHC/UI/Rendering/PencilRenderCore.func.hpp" +#include "OpenSHC/Text/Enums/HelpTextPicturePositionToken.hpp" +#include "OpenSHC/wstring-literals.hpp" #include "OpenSHC/Globals/COL_DARK_LIME.hpp" #include "OpenSHC/Globals/DAT_00df3348.hpp" @@ -24,7 +26,7 @@ namespace Text { int value; wchar_t* text; HelpTextToken helpToken; - HelpTextPicturePositionToken picturePositionToken; + Enums::HelpTextPicturePositionToken picturePositionToken; }; // FUNCTION: STRONGHOLDCRUSADER 0x0045FDC0 @@ -65,9 +67,9 @@ namespace Text { if (!this->isTextHelpDialogMode) { return 1; } - this->unknown_0x23964 = -1; - this->unknown_0x23968 = -1; - if (this->unknown_0x2396C) { + this->field49_0x23964 = -1; + this->field50_0x23968 = -1; + if (this->field51_0x2396c) { DAT_00df334c::instance = 1; } if (this->activeHelpHotspotIndex < 0) { @@ -92,8 +94,8 @@ namespace Text { TextMemUnion textMemUnion; textMemUnion.value = MACRO_CALL_MEMBER(TextEditorState_Func::getWideCharOrWideCharPointer, this)(&textMemIndex); - if (this->useAlternateHelpTab && textMemUnion.value < L' ' && textMemUnion.helpToken != HTT_NEWPARAGRAPH - && iVar5 == this->activeHelpHotspotIndex) { + if (this->useAlternateHelpTab && textMemUnion.value < L' ' + && textMemUnion.helpToken != Enums::HTT_NEWPARAGRAPH && iVar5 == this->activeHelpHotspotIndex) { lineEndY = lineY + currentFontLineHeight; lineStartY = lineY; if (param_1 == 1) { @@ -102,12 +104,12 @@ namespace Text { xModify = this->lineLayoutTable[lineY].unknown2 / 2; } local_10c = local_114 - local_11c; - if (this->unknown_0x2396C < 0) { + if (this->field51_0x2396c < 0) { this->activeHelpHotspotIndex = local_100 + DAT_00df3348::instance; if (this->activeHelpHotspotIndex >= local_11c) { this->activeHelpHotspotIndex = local_11c - 1; } - this->unknown_0x2396C = 0; + this->field51_0x2396c = 0; } local_134 = 0; MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( @@ -128,29 +130,29 @@ namespace Text { iVar17 = local_11c; switch (textMemUnion.helpToken) { - case HTT_PIC: + case Enums::HTT_PIC: if (this->helpDialogSubMode == 1) { charColor = 0xff; local_12c = 0; - MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, L"DAT_PointerToTemporaryTextMemory[textMemIndex], this->graphicFileNames[this->DAT_PointerToTemporaryTextMemory[textMemIndex]]); ++textMemIndex; - switch ((HelpTextPicturePositionToken)this->DAT_PointerToTemporaryTextMemory[textMemIndex]) { - case HTT_PIC_LEFT: - wcscat(wideTextBuffer, L"LEFT>"); + switch ((Enums::HelpTextPicturePositionToken)this->DAT_PointerToTemporaryTextMemory[textMemIndex]) { + case Enums::HTPPT_LEFT: + wcscat(wideTextBuffer, u_LEFT__005a5494); textMemIndex += 2; break; - case HTT_PIC_RIGHT: - wcscat(wideTextBuffer, L"RIGHT>"); + case Enums::HTPPT_RIGHT: + wcscat(wideTextBuffer, u_RIGHT__005a5484); textMemIndex += 2; break; - case HTT_PIC_CENTRE: - wcscat(wideTextBuffer, L"CENTRE>"); + case Enums::HTPPT_CENTRE: + wcscat(wideTextBuffer, u_CENTRE__005a5474); textMemIndex += 2; break; - case HTT_PIC_HERE: - wcscat(wideTextBuffer, L"HERE>"); + case Enums::HTPPT_HERE: + wcscat(wideTextBuffer, u_HERE__005a5468); textMemIndex += 2; break; default: @@ -179,8 +181,8 @@ namespace Text { this->imageHotspotTable[this->imageHotspotCount].unknown3 = currentLinkId; } } - HelpTextPicturePositionToken positionToken - = (HelpTextPicturePositionToken)this->DAT_PointerToTemporaryTextMemory[textMemIndex + 1]; + Enums::HelpTextPicturePositionToken positionToken + = (Enums::HelpTextPicturePositionToken)this->DAT_PointerToTemporaryTextMemory[textMemIndex + 1]; int imageHeight = DAT_TextureRenderCoreObject::instance .loadedGfxArray[99 - this->DAT_PointerToTemporaryTextMemory[textMemIndex]] .height; @@ -188,14 +190,14 @@ namespace Text { .loadedGfxArray[99 - this->DAT_PointerToTemporaryTextMemory[textMemIndex]] .width; switch (positionToken) { - case HTT_PIC_LEFT: + case Enums::HTPPT_LEFT: this->imageHotspotTable[this->imageHotspotCount].xPos = this->lineLayoutTable[lineY].leftBorder; for (int i = 0; i < imageHeight + 50; ++i) { this->lineLayoutTable[lineY + i].rightBorder = this->lineLayoutTable[lineY].leftBorder + 25 + imageWidth; } break; - case HTT_PIC_RIGHT: + case Enums::HTPPT_RIGHT: this->imageHotspotTable[this->imageHotspotCount].xPos = this->lineLayoutTable[lineY].rightBorder - imageWidth; for (int i = 0; i < imageHeight + 50; ++i) { @@ -204,14 +206,14 @@ namespace Text { this->lineLayoutTable[lineY + i].leftBorder = -1; } break; - case HTT_PIC_CENTRE: + case Enums::HTPPT_CENTRE: this->imageHotspotTable[this->imageHotspotCount].xPos - = (this->dialogContentHeight - imageWidth) / 2; + = (this->dialogContentWidth - imageWidth) / 2; for (int i = 0; i < imageHeight + 50; ++i) { this->lineLayoutTable[lineY + i].leftBorder = -1; } break; - case HTT_PIC_HERE: + case Enums::HTPPT_HERE: imageWidth += 3; if (this->lineLayoutTable[lineY].rightBorder < imageWidth + leftPosition) { local_f0 = FALSE; @@ -230,13 +232,13 @@ namespace Text { ++local_134; local_100 = local_11c; local_11c = local_114; - if (0 < this->unknown_0x2396C && 1 < local_134) { + if (0 < this->field51_0x2396c && 1 < local_134) { this->activeHelpHotspotIndex = iVar17 + local_10c; local_134 = -10000; if (local_114 <= this->activeHelpHotspotIndex) { this->activeHelpHotspotIndex = local_114 + -1; } - this->unknown_0x2396C = 0; + this->field51_0x2396c = 0; } } currentFontLineHeight = currentFontClass->lineHeight_0x14; @@ -253,19 +255,19 @@ namespace Text { break; } textMemIndex += 3; - if (positionToken == HTT_PIC_HERE || param_1) { + if (positionToken == Enums::HTPPT_HERE || param_1) { continue; } ++this->imageHotspotCount; DAT_TextManagerObject::instance.field6_0x18 = 0; return FALSE; } - case HTT_FONT: + case Enums::HTT_FONT: if (this->helpDialogSubMode == 1) { charColor = 0xff; local_12c = 0; MACRO_CALL(Global_Func::PrintToDestination)( - wideTextBuffer, L"", this->DAT_PointerToTemporaryTextMemory[textMemIndex]); + wideTextBuffer, u__FONT__d__005a5454, this->DAT_PointerToTemporaryTextMemory[textMemIndex]); textMemIndex += 2; break; } else { @@ -281,11 +283,11 @@ namespace Text { } continue; } - case HTT_COLOUR: + case Enums::HTT_COLOUR: if (this->helpDialogSubMode == 1) { charColor = 0xff; local_12c = 0; - MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, L"", + MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, u__COLOUR__S__005a5824, DAT_UserHelpDefinedData::instance .field6_0x7a16c[this->DAT_PointerToTemporaryTextMemory[textMemIndex]] .name_0x0); @@ -314,11 +316,11 @@ namespace Text { } continue; } - case HTT_LINKCOLOUR: + case Enums::HTT_LINKCOLOUR: if (this->helpDialogSubMode == 1) { charColor = 0xff; local_12c = 0; - MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, L"", + MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, u__LINKCOLOUR__S__005a5804, DAT_UserHelpDefinedData::instance .field6_0x7a16c[this->DAT_PointerToTemporaryTextMemory[textMemIndex]] .name_0x0); @@ -337,11 +339,11 @@ namespace Text { } continue; } - case HTT_LINK: + case Enums::HTT_LINK: if (this->helpDialogSubMode == 1) { charColor = 0xff; local_12c = 0; - MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, L"", + MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, u__LINK_S__005a57ec, DAT_UserHelpDefinedData::instance .HelpSections[this->DAT_PointerToTemporaryTextMemory[textMemIndex]]); textMemIndex += 2; @@ -354,11 +356,11 @@ namespace Text { textMemIndex += 2; continue; } - case HTT_INCLUDE: + case Enums::HTT_INCLUDE: if (this->helpDialogSubMode == 1) { charColor = 0xff; local_12c = 0; - MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, L"", + MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, u__INCLUDE_S__005a57cc, DAT_UserHelpDefinedData::instance .HelpSections[this->DAT_PointerToTemporaryTextMemory[textMemIndex]]); textMemIndex += 2; @@ -367,28 +369,28 @@ namespace Text { textMemIndex += 2; continue; } - case HTT_SOUND: + case Enums::HTT_SOUND: if (this->helpDialogSubMode == 1) { charColor = 0xff; local_12c = 0; - MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, L"", + MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, u__SOUND_S__005a57b0, this->soundFileNames[this->DAT_PointerToTemporaryTextMemory[textMemIndex]]); textMemIndex += 2; break; } else { if (param_1 == 1 && -1 < lineY - this->helpContentScrollOffsetY - && lineY - this->helpContentScrollOffsetY < this->dialogContentWidth + && lineY - this->helpContentScrollOffsetY < this->dialogContentHeight && !this->soundFilePlayedFlags[this->DAT_PointerToTemporaryTextMemory[textMemIndex]]) { this->soundFilePlayedFlags[this->DAT_PointerToTemporaryTextMemory[textMemIndex]] = 1; } textMemIndex += 2; continue; } - case HTT_ENDLINK: + case Enums::HTT_ENDLINK: if (this->helpDialogSubMode == 1) { charColor = 0xff; local_12c = 0; - wcscpy(wideTextBuffer, L"<\\LINK>"); + wcscpy(wideTextBuffer, u__LINK__005a53d4); break; } else { currentLinkId = -1; @@ -401,40 +403,40 @@ namespace Text { default: pwVar6 = textMemUnion.text; goto switchD_00460064_caseD_d; - case HTT_STRING: + case Enums::HTT_STRING: if (this->helpDialogSubMode == 1) { charColor = 0xff; local_12c = 0; MACRO_CALL(Global_Func::PrintToDestination)( - wideTextBuffer, L"", this->DAT_PointerToTemporaryTextMemory[textMemIndex]); + wideTextBuffer, u__STRING__d__005a5358, this->DAT_PointerToTemporaryTextMemory[textMemIndex]); textMemIndex += 2; break; } else { textMemIndex += 2; continue; } - case HTT_CENTRE: + case Enums::HTT_CENTRE: if (this->helpDialogSubMode == 1) { charColor = 0xff; local_12c = 0; - wcscpy(wideTextBuffer, L""); + wcscpy(wideTextBuffer, u__CENTRE__005a539c); break; } else { centreActive = TRUE; local_120 = TRUE; continue; } - case HTT_ENDCENTRE: + case Enums::HTT_ENDCENTRE: if (this->helpDialogSubMode == 1) { charColor = 0xff; local_12c = 0; - wcscpy(wideTextBuffer, L"<\\CENTRE>"); + wcscpy(wideTextBuffer, u__CENTRE__005a5388); break; } else { centreActive = FALSE; continue; } - case HTT_NEWPARAGRAPH: + case Enums::HTT_NEWPARAGRAPH: if (local_120) { this->lineLayoutTable[lineY].unknown2 = this->lineLayoutTable[lineY].rightBorder - leftPosition; local_120 = centreActive; @@ -473,24 +475,24 @@ namespace Text { local_100 = local_11c; if (param_1 == 1) { ++local_134; - if (0 < this->unknown_0x2396C && 1 < local_134) { + if (0 < this->field51_0x2396c && 1 < local_134) { this->activeHelpHotspotIndex = local_10c + local_11c; local_134 = -10000; if (iVar5 <= this->activeHelpHotspotIndex) { this->activeHelpHotspotIndex = iVar5 + -1; } - this->unknown_0x2396C = 0; + this->field51_0x2396c = 0; } } iVar12 = iVar5; if (iVar5 == this->activeHelpHotspotIndex && param_1 == 1) { local_10c = 0; - if (this->unknown_0x2396C < 0) { + if (this->field51_0x2396c < 0) { this->activeHelpHotspotIndex = DAT_00df3348::instance + local_11c; if (iVar5 <= this->activeHelpHotspotIndex) { this->activeHelpHotspotIndex = iVar5 + -1; } - this->unknown_0x2396C = 0; + this->field51_0x2396c = 0; } local_134 = 0; } @@ -499,15 +501,15 @@ namespace Text { if (this->helpDialogSubMode == 1) { charColor = 0xff; local_12c = 0; - wcscpy(wideTextBuffer, L""); + wcscpy(wideTextBuffer, u__NEWPARAGRAPH__005a5790); break; } continue; - case HTT_TAB: // TODO?: unknown token + case Enums::HTT_TAB: // TODO?: unknown token if (this->helpDialogSubMode == 1) { charColor = 0xff; local_12c = 0; - wcscpy(wideTextBuffer, L""); + wcscpy(wideTextBuffer, u__tab__005a5784); break; } else { if (this->lineLayoutTable[lineY].rightBorder < leftPosition + 30) { @@ -528,13 +530,13 @@ namespace Text { ++local_134; local_100 = local_11c; iVar12 = iVar5; - if (0 < this->unknown_0x2396C && 1 < local_134) { + if (0 < this->field51_0x2396c && 1 < local_134) { this->activeHelpHotspotIndex = local_11c + local_10c; local_134 = -10000; if (iVar5 <= this->activeHelpHotspotIndex) { this->activeHelpHotspotIndex = iVar5 + -1; } - this->unknown_0x2396C = 0; + this->field51_0x2396c = 0; } } local_11c = iVar12; @@ -550,7 +552,7 @@ namespace Text { ++this->topVisibleLineIndex; if (this->lineLayoutTable[this->topVisibleLineIndex].leftBorder == 25 && this->lineLayoutTable[this->topVisibleLineIndex].rightBorder - == this->dialogContentHeight - 25) { + == this->dialogContentWidth - 25) { break; } } while (this->topVisibleLineIndex < 20000); @@ -559,8 +561,8 @@ namespace Text { if (lineStartY < this->helpContentScrollOffsetY) { this->helpContentScrollOffsetY = lineStartY; } - if (lineEndY > this->helpContentScrollOffsetY + this->dialogContentWidth) { - this->helpContentScrollOffsetY = (lineEndY - this->dialogContentWidth) + 5; + if (lineEndY > this->helpContentScrollOffsetY + this->dialogContentHeight) { + this->helpContentScrollOffsetY = (lineEndY - this->dialogContentHeight) + 5; DAT_TextManagerObject::instance.field6_0x18 = 0; return TRUE; } @@ -573,16 +575,16 @@ namespace Text { return TRUE; } DAT_00df3348::instance = local_10c; - if (0 < this->unknown_0x2396C && local_134 == 1) { + if (0 < this->field51_0x2396c && local_134 == 1) { this->activeHelpHotspotIndex = local_10c + local_11c; if (this->activeHelpHotspotIndex > this->customHelpTextLength) { this->activeHelpHotspotIndex = this->customHelpTextLength; } - this->unknown_0x2396C = 0; + this->field51_0x2396c = 0; } if (!local_e4 && this->activeHelpHotspotIndex && DAT_00df334c::instance) { --this->activeHelpHotspotIndex; - this->unknown_0x23970 = 0; + this->field52_0x23970 = 0; DAT_TextManagerObject::instance.field6_0x18 = 0; return TRUE; } @@ -613,13 +615,13 @@ namespace Text { ++local_134; local_100 = local_11c; local_11c = local_114; - if (0 < this->unknown_0x2396C && 1 < local_134) { + if (0 < this->field51_0x2396c && 1 < local_134) { this->activeHelpHotspotIndex = iVar5 + local_10c; local_134 = -10000; if (local_114 <= this->activeHelpHotspotIndex) { this->activeHelpHotspotIndex = local_114 - 1; } - this->unknown_0x2396C = 0; + this->field51_0x2396c = 0; } } local_f4 = iVar12 + leftPosition; @@ -644,13 +646,13 @@ namespace Text { ++local_134; local_100 = local_11c; local_11c = local_114 + local_118; - if (0 < this->unknown_0x2396C && 1 < local_134) { + if (0 < this->field51_0x2396c && 1 < local_134) { this->activeHelpHotspotIndex = iVar5 + local_10c; local_134 = -10000; if (local_114 + local_118 <= this->activeHelpHotspotIndex) { this->activeHelpHotspotIndex = local_114 + local_118 - 1; } - this->unknown_0x2396C = 0; + this->field51_0x2396c = 0; } } do { @@ -674,10 +676,10 @@ namespace Text { iVar5 - this->dialogContentX + local_f8 + leftPosition, currentFontLineHeight + 2)) { if (local_12c) { - this->unknown_0x23964 = local_114 + local_118; - this->unknown_0x23968 = currentLinkId; + this->field49_0x23964 = local_114 + local_118; + this->field50_0x23968 = currentLinkId; } else { - this->unknown_0x23964 = local_114; + this->field49_0x23964 = local_114; } } } @@ -687,12 +689,12 @@ namespace Text { if (param_1 == 1) { if (local_12c) { local_10c = (local_118 - local_11c) + local_114; - if (this->unknown_0x2396C < 0) { + if (this->field51_0x2396c < 0) { this->activeHelpHotspotIndex = DAT_00df3348::instance + local_100; if (this->activeHelpHotspotIndex >= local_11c) { this->activeHelpHotspotIndex = local_11c - 1; } - this->unknown_0x2396C = 0; + this->field51_0x2396c = 0; } local_134 = 0; MACRO_CALL_MEMBER( @@ -722,10 +724,10 @@ namespace Text { iVar5 - this->dialogContentX + local_f8 + leftPosition, currentFontLineHeight + 2)) { if (local_12c) { - this->unknown_0x23964 = local_114 + local_118; - this->unknown_0x23968 = currentLinkId; + this->field49_0x23964 = local_114 + local_118; + this->field50_0x23968 = currentLinkId; } else { - this->unknown_0x23964 = local_114; + this->field49_0x23964 = local_114; } } } @@ -752,10 +754,10 @@ namespace Text { iVar5 - this->helpContentScrollX, local_104 - this->helpContentScrollY, iVar12 - iVar5, currentFontLineHeight + 2)) { if (local_12c) { - this->unknown_0x23964 = i + local_114; - this->unknown_0x23968 = currentLinkId; + this->field49_0x23964 = i + local_114; + this->field50_0x23968 = currentLinkId; } else { - this->unknown_0x23964 = local_114; + this->field49_0x23964 = local_114; } } } else { @@ -778,12 +780,12 @@ namespace Text { if (param_1 == 1) { local_10c = local_f8 + i; local_134 = 0; - if (this->unknown_0x2396C < 0 && local_12c) { + if (this->field51_0x2396c < 0 && local_12c) { this->activeHelpHotspotIndex = local_100 + DAT_00df3348::instance; if (this->activeHelpHotspotIndex >= local_11c) { this->activeHelpHotspotIndex = local_11c + -1; } - this->unknown_0x2396C = 0; + this->field51_0x2396c = 0; } local_f0 = TRUE; iVar12 = MACRO_CALL_MEMBER(FontSizeClass_Func::renderWideChar, currentFontClass)( @@ -792,10 +794,10 @@ namespace Text { iVar5 - this->helpContentScrollX, local_104 - this->helpContentScrollY, iVar12 - iVar5, currentFontLineHeight + 2)) { if (local_12c) { - this->unknown_0x23964 = i + local_114; - this->unknown_0x23968 = currentLinkId; + this->field49_0x23964 = i + local_114; + this->field50_0x23968 = currentLinkId; } else { - this->unknown_0x23964 = local_114; + this->field49_0x23964 = local_114; } } } else { diff --git a/src/OpenSHC/Text/TextEditorState/readCrusaderHelpHlp.cpp b/src/OpenSHC/Text/TextEditorState/readCrusaderHelpHlp.cpp index 1f6bf9c84..523598141 100644 --- a/src/OpenSHC/Text/TextEditorState/readCrusaderHelpHlp.cpp +++ b/src/OpenSHC/Text/TextEditorState/readCrusaderHelpHlp.cpp @@ -4,6 +4,7 @@ #include "OpenSHC/OS.func.hpp" #include "OpenSHC/Util/WideCharMultiByteState.func.hpp" #include "OpenSHC/string-literals.hpp" +#include "OpenSHC/wstring-literals.hpp" #include "OpenSHC/Globals/DAT_ResourceManager.hpp" #include "OpenSHC/Globals/DAT_WideCharMultiByteState.hpp" @@ -11,8 +12,6 @@ namespace OpenSHC { namespace Text { - // TODO: Replace L-strings with str-ptr - // FUNCTION: STRONGHOLDCRUSADER 0x0045F470 FILE* TextEditorState::readCrusaderHelpHlp(LPCSTR searchedPart) { @@ -40,7 +39,7 @@ namespace Text { continue; } wchar_t* hlpPart = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)(_File); - if (!hlpPart || MACRO_CALL(OS_Func::__wcsicmp)(L"section", hlpPart)) { + if (!hlpPart || MACRO_CALL(OS_Func::__wcsicmp)(u_section_005a5610, hlpPart)) { continue; } wchar_t* sectionHlpPart = MACRO_CALL_MEMBER(TextEditorState_Func::parseHLPPart, this)(_File); diff --git a/src/OpenSHC/Text/TextEditorState/renderHelpImageHotspots.cpp b/src/OpenSHC/Text/TextEditorState/renderHelpImageHotspots.cpp index d468a9d7c..fee866c9d 100644 --- a/src/OpenSHC/Text/TextEditorState/renderHelpImageHotspots.cpp +++ b/src/OpenSHC/Text/TextEditorState/renderHelpImageHotspots.cpp @@ -28,12 +28,12 @@ namespace Text { height += y1 - this->dialogContentY; y1 = this->dialogContentY; } - // Does the naming "dialogContentWidth" fit? Is it related to width? - if (height + y1 > this->dialogContentY + this->dialogContentWidth) { - height = this->dialogContentWidth * 2 - y1; + + if (height + y1 > this->dialogContentY + this->dialogContentHeight) { + height = this->dialogContentHeight * 2 - y1; } int const y2 = y1 + height; - if (y2 >= this->dialogContentY && y1 < this->dialogContentY + this->dialogContentWidth) { + if (y2 >= this->dialogContentY && y1 < this->dialogContentY + this->dialogContentHeight) { int const x2 = x1 + width; MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( x1, y1, x2, y1, COL_GREYISH_YELLOW::instance.shortValue); @@ -64,7 +64,7 @@ namespace Text { this->imageHotspotTable[i].yPos - this->helpContentScrollY + this->dialogContentY - this->helpContentScrollOffsetY, boxWidth, boxHeight)) { - this->unknown_0x23968 = this->imageHotspotTable[i].unknown3; + this->field50_0x23968 = this->imageHotspotTable[i].unknown3; } } } diff --git a/src/OpenSHC/Text/TextEditorState/saveHelpFileToResource.cpp b/src/OpenSHC/Text/TextEditorState/saveHelpFileToResource.cpp index 1ae12edc8..009aa59dc 100644 --- a/src/OpenSHC/Text/TextEditorState/saveHelpFileToResource.cpp +++ b/src/OpenSHC/Text/TextEditorState/saveHelpFileToResource.cpp @@ -2,7 +2,9 @@ #include "OpenSHC/IO/ResourceManager.func.hpp" #include "OpenSHC/OS.func.hpp" +#include "OpenSHC/Text/Enums/HelpTextPicturePositionToken.hpp" #include "OpenSHC/string-literals.hpp" +#include "OpenSHC/wstring-literals.hpp" #include "OpenSHC/Globals/DAT_ResourceManager.hpp" #include "OpenSHC/Globals/DAT_UserHelpDefinedData.hpp" @@ -10,8 +12,6 @@ namespace OpenSHC { namespace Text { - // TODO: Replace L strings with references from a file - // FUNCTION: STRONGHOLDCRUSADER 0x0045DB40 void TextEditorState::saveHelpFileToResource() { @@ -26,89 +26,91 @@ namespace Text { wchar_t const utf16bom = L'\uFEFF'; MACRO_CALL(OS_Func::_fwrite)((void*)&utf16bom, sizeof(wchar_t), 1, _File); - MACRO_CALL(OS_Func::_fwprintf)(_File, L"
\n"); + MACRO_CALL(OS_Func::_fwprintf)(_File, u__HEADER__005a54fc); for (int i = 0; i < this->graphicFileCount; ++i) { - MACRO_CALL(OS_Func::_fwprintf)(_File, L"\n", this->graphicFileNames[i]); + MACRO_CALL(OS_Func::_fwprintf)(_File, u__LOADPIC_S__005a54dc, this->graphicFileNames[i]); } - MACRO_CALL(OS_Func::_fwprintf)(_File, L"<\\HEADER>\n"); - MACRO_CALL(OS_Func::_fwprintf)(_File, L"\n"); + MACRO_CALL(OS_Func::_fwprintf)(_File, u__HEADER__005a54c4); + MACRO_CALL(OS_Func::_fwprintf)(_File, u__BODY__005a54b4); for (int i = 0; this->DAT_PointerToTemporaryTextMemory[i];) { HelpTextToken const switchValue = (HelpTextToken)this->DAT_PointerToTemporaryTextMemory[i]; i += 1; switch (switchValue) { - case HTT_PIC: - MACRO_CALL(OS_Func::_fwprintf)(_File, L"DAT_PointerToTemporaryTextMemory[i]); + case Enums::HTT_PIC: + MACRO_CALL(OS_Func::_fwprintf)(_File, u__PIC__d__005a54a0, this->DAT_PointerToTemporaryTextMemory[i]); i += 1; - switch ((HelpTextPicturePositionToken)this->DAT_PointerToTemporaryTextMemory[i]) { - case HTT_PIC_LEFT: - MACRO_CALL(OS_Func::_fwprintf)(_File, L"LEFT>"); + switch ((Enums::HelpTextPicturePositionToken)this->DAT_PointerToTemporaryTextMemory[i]) { + case Enums::HTPPT_LEFT: + MACRO_CALL(OS_Func::_fwprintf)(_File, u_LEFT__005a5494); i += 2; break; - case HTT_PIC_RIGHT: - MACRO_CALL(OS_Func::_fwprintf)(_File, L"RIGHT>"); + case Enums::HTPPT_RIGHT: + MACRO_CALL(OS_Func::_fwprintf)(_File, u_RIGHT__005a5484); i += 2; break; - case HTT_PIC_CENTRE: - MACRO_CALL(OS_Func::_fwprintf)(_File, L"CENTRE>"); + case Enums::HTPPT_CENTRE: + MACRO_CALL(OS_Func::_fwprintf)(_File, u_CENTRE__005a5474); i += 2; break; - case HTT_PIC_HERE: - MACRO_CALL(OS_Func::_fwprintf)(_File, L"HERE>"); + case Enums::HTPPT_HERE: + MACRO_CALL(OS_Func::_fwprintf)(_File, u_HERE__005a5468); default: i += 2; break; } break; - case HTT_FONT: - MACRO_CALL(OS_Func::_fwprintf)(_File, L"", this->DAT_PointerToTemporaryTextMemory[i]); + case Enums::HTT_FONT: + MACRO_CALL(OS_Func::_fwprintf)(_File, u__FONT__d__005a5454, this->DAT_PointerToTemporaryTextMemory[i]); i += 2; break; - case HTT_COLOUR: - MACRO_CALL(OS_Func::_fwprintf)(_File, L"", this->DAT_PointerToTemporaryTextMemory[i]); + case Enums::HTT_COLOUR: + MACRO_CALL(OS_Func::_fwprintf)(_File, u__COLOUR_d__005a543c, this->DAT_PointerToTemporaryTextMemory[i]); i += 2; break; - case HTT_LINKCOLOUR: - MACRO_CALL(OS_Func::_fwprintf)(_File, L"", this->DAT_PointerToTemporaryTextMemory[i]); + case Enums::HTT_LINKCOLOUR: + MACRO_CALL(OS_Func::_fwprintf)( + _File, u__LINKCOLOUR_d__005a541c, this->DAT_PointerToTemporaryTextMemory[i]); i += 2; break; - case HTT_LINK: - MACRO_CALL(OS_Func::_fwprintf)(_File, L"", + case Enums::HTT_LINK: + MACRO_CALL(OS_Func::_fwprintf)(_File, u__LINK__S__005a5404, DAT_UserHelpDefinedData::instance.HelpSections[this->DAT_PointerToTemporaryTextMemory[i]]); i += 2; break; - case HTT_INCLUDE: - MACRO_CALL(OS_Func::_fwprintf)(_File, L"", + case Enums::HTT_INCLUDE: + MACRO_CALL(OS_Func::_fwprintf)(_File, u__INCLUDE__S__005a53e4, DAT_UserHelpDefinedData::instance.HelpSections[this->DAT_PointerToTemporaryTextMemory[i]]); i += 2; break; - case HTT_ENDLINK: - MACRO_CALL(OS_Func::_fwprintf)(_File, L"<\\LINK>"); + case Enums::HTT_ENDLINK: + MACRO_CALL(OS_Func::_fwprintf)(_File, u__LINK__005a53d4); break; - case HTT_NEWPARAGRAPH: - MACRO_CALL(OS_Func::_fwprintf)(_File, L"\n\n"); + case Enums::HTT_NEWPARAGRAPH: + MACRO_CALL(OS_Func::_fwprintf)(_File, u__NEWPARAGRAPH__005a53b0); break; - case HTT_CENTRE: - MACRO_CALL(OS_Func::_fwprintf)(_File, L""); + case Enums::HTT_CENTRE: + MACRO_CALL(OS_Func::_fwprintf)(_File, u__CENTRE__005a539c); break; - case HTT_ENDCENTRE: - MACRO_CALL(OS_Func::_fwprintf)(_File, L"<\\CENTRE>"); + case Enums::HTT_ENDCENTRE: + MACRO_CALL(OS_Func::_fwprintf)(_File, u__CENTRE__005a5388); break; - case HTT_SOUND: - MACRO_CALL(OS_Func::_fwprintf)(_File, L"", this->DAT_PointerToTemporaryTextMemory[i]); + case Enums::HTT_SOUND: + MACRO_CALL(OS_Func::_fwprintf)(_File, u__SOUND__d__005a5370, this->DAT_PointerToTemporaryTextMemory[i]); i += 2; break; - case HTT_STRING: - MACRO_CALL(OS_Func::_fwprintf)(_File, L"", this->DAT_PointerToTemporaryTextMemory[i]); + case Enums::HTT_STRING: + MACRO_CALL(OS_Func::_fwprintf)( + _File, u__STRING__d__005a5358, this->DAT_PointerToTemporaryTextMemory[i]); i += 2; break; default: - MACRO_CALL(OS_Func::_fwprintf)(_File, L"%c", (wchar_t)switchValue); + MACRO_CALL(OS_Func::_fwprintf)(_File, u__c_005a5350, (wchar_t)switchValue); break; } } - MACRO_CALL(OS_Func::_fwprintf)(_File, L"\n<\\BODY>\n"); + MACRO_CALL(OS_Func::_fwprintf)(_File, u__BODY__005a533c); MACRO_CALL(OS_Func::_fclose)(_File); } diff --git a/src/OpenSHC/Text/TextEditorState/setHelpWindowBounds.cpp b/src/OpenSHC/Text/TextEditorState/setHelpWindowBounds.cpp index ba116919b..eab80e92c 100644 --- a/src/OpenSHC/Text/TextEditorState/setHelpWindowBounds.cpp +++ b/src/OpenSHC/Text/TextEditorState/setHelpWindowBounds.cpp @@ -4,12 +4,12 @@ namespace OpenSHC { namespace Text { // FUNCTION: STRONGHOLDCRUSADER 0x0045D080 - void TextEditorState::setHelpWindowBounds(undefined4 x, undefined4 y, undefined4 height, undefined4 width) + void TextEditorState::setHelpWindowBounds(int x, int y, int width, int height) { this->dialogContentX = x; this->dialogContentY = y; - this->dialogContentHeight = height; this->dialogContentWidth = width; + this->dialogContentHeight = height; } } diff --git a/src/OpenSHC/Text/TextEditorState/setTextRenderingLogic.cpp b/src/OpenSHC/Text/TextEditorState/setTextRenderingLogic.cpp index 72ef3128d..c553407e2 100644 --- a/src/OpenSHC/Text/TextEditorState/setTextRenderingLogic.cpp +++ b/src/OpenSHC/Text/TextEditorState/setTextRenderingLogic.cpp @@ -15,18 +15,18 @@ namespace Text { if (this->helpDialogVariant != 1) { MACRO_CALL_MEMBER(UI::Rendering::TextureRenderCore_Func::setRenderingRect, DAT_TextureRenderCoreObject::ptr)(this->dialogContentX, this->dialogContentY, - this->dialogContentHeight + this->dialogContentX, this->dialogContentWidth + this->dialogContentY); + this->dialogContentWidth + this->dialogContentX, this->dialogContentHeight + this->dialogContentY); MACRO_CALL_MEMBER(UI::Rendering::TextureRenderCore_Func::setScreenMenuSurfaceHeightRange, DAT_TextureRenderCoreObject::ptr)( - this->dialogContentY, this->dialogContentWidth + this->dialogContentY); + this->dialogContentY, this->dialogContentHeight + this->dialogContentY); DAT_TextureRenderCoreObject::instance.drawBufferChoiceValue = Rendering::Enums::RT_SCREEN_MENU; } else { MACRO_CALL_MEMBER(UI::Rendering::TextureRenderCore_Func::setRenderingRect, DAT_TextureRenderCoreObject::ptr)(this->dialogContentX, this->dialogContentY, - this->dialogContentHeight + this->dialogContentX, this->dialogContentWidth + this->dialogContentY); + this->dialogContentWidth + this->dialogContentX, this->dialogContentHeight + this->dialogContentY); MACRO_CALL_MEMBER( UI::Rendering::TextureRenderCore_Func::setMapSurfaceHeightRange, DAT_TextureRenderCoreObject::ptr)( - this->dialogContentY, this->dialogContentWidth + this->dialogContentY); + this->dialogContentY, this->dialogContentHeight + this->dialogContentY); DAT_TextManagerObject::instance.textSurfaceTarget = Rendering::Enums::RT_MAP_GAME; DAT_PencilRenderCore::instance.surfaceTarget = Rendering::Enums::RT_MAP_GAME; DAT_TextureRenderCoreObject::instance.currentRenderSurfaceIdentifierUnk_0x8 = Rendering::Enums::RT_MAP_GAME; From d512f74e4a32cc89dfb98a21ec4e5af073b16a58 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 27 Sep 2026 03:43:43 +0200 Subject: [PATCH 43/44] reimplement: SHC_3BB0A8C1_0x0045FDC0 70.1% --- IMPLEMENTATION_CHEAT_SHEET.md | 3 +- src/OpenSHC/Text/TextEditorState.hpp | 6 - .../TextEditorState/drawBorderStyle0x20.cpp | 3 - .../getWideCharOrWideCharPointer.cpp | 1 - .../initializeAndLayoutHelpText.cpp | 2 +- .../processHelpRichTextTokens.cpp | 924 +++++++++--------- .../renderHelpImageHotspots.cpp | 4 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 8 files changed, 456 insertions(+), 489 deletions(-) diff --git a/IMPLEMENTATION_CHEAT_SHEET.md b/IMPLEMENTATION_CHEAT_SHEET.md index afc4ac661..e29a3b222 100644 --- a/IMPLEMENTATION_CHEAT_SHEET.md +++ b/IMPLEMENTATION_CHEAT_SHEET.md @@ -516,7 +516,8 @@ translation unit. ### Parameters Parameters might not be pushed like normal in certain cases. -Usually, if two functions are followed by each other, the parameters are pushed for the first function, then the call is executed and then parameters for the second function are pushed. If parameters for the second function are pushed before the first call, it might indicate that the first call was executed in place of a variable, to directly feed the return into the second function. +Usually, if two functions are followed by each other, the parameters are pushed for the first function, then the call is executed and then parameters for the second function are pushed. If parameters for the second function are pushed before the first call, it might indicate that the first call was executed in place of a variable, to directly feed the return into the second function. +This possibility is actually universal. If a computation of a value happens between pushes of parameters, it makes it likely the value was computed in-place. The other way around is also possible. If a computed value is created completely or partially before any push, it might have been a temporary. ### Implicit functions diff --git a/src/OpenSHC/Text/TextEditorState.hpp b/src/OpenSHC/Text/TextEditorState.hpp index 713559868..5c547d91c 100644 --- a/src/OpenSHC/Text/TextEditorState.hpp +++ b/src/OpenSHC/Text/TextEditorState.hpp @@ -20,12 +20,6 @@ namespace OpenSHC { namespace Text { - struct LineLayout { - short leftBorder; - short rightBorder; - short unknown2; - }; - using OpenSHC::Text::ImageHotspot; using OpenSHC::Text::LineLayout; using OpenSHC::Text::Enums::HelpTextToken; diff --git a/src/OpenSHC/Text/TextEditorState/drawBorderStyle0x20.cpp b/src/OpenSHC/Text/TextEditorState/drawBorderStyle0x20.cpp index bb01a0ba2..81cf0d158 100644 --- a/src/OpenSHC/Text/TextEditorState/drawBorderStyle0x20.cpp +++ b/src/OpenSHC/Text/TextEditorState/drawBorderStyle0x20.cpp @@ -17,9 +17,6 @@ namespace Text { this->dialogWidth = dialogWidth; this->dialogHeight = dialogHeight; - // NOTE: dialogWidth is used to compute the content height and vice versa, no idea if something was switched; - // also, the required order feels strange, maybe they used a RECT struct or macro - // FIXME: ContentHeight and ContentWidth or the dialogWidth and dialogHeight are swapped int const contentX = this->dialogX + DAT_00df2964::instance; int const contentY = this->dialogY + DAT_00df296c::instance; int const contentHeight = this->dialogHeight - INT_00df2970::instance; diff --git a/src/OpenSHC/Text/TextEditorState/getWideCharOrWideCharPointer.cpp b/src/OpenSHC/Text/TextEditorState/getWideCharOrWideCharPointer.cpp index 7e28ededd..c6a74bae4 100644 --- a/src/OpenSHC/Text/TextEditorState/getWideCharOrWideCharPointer.cpp +++ b/src/OpenSHC/Text/TextEditorState/getWideCharOrWideCharPointer.cpp @@ -6,7 +6,6 @@ namespace OpenSHC { namespace Text { // NOTE: Return is essentially a "union", however, it needs to be a value for the proper structure - // Also, it might be likely that this function is "known" by its only user "processHelpRichTextTokens" // FUNCTION: STRONGHOLDCRUSADER 0x0045D3C0 uint TextEditorState::getWideCharOrWideCharPointer(int* param_1) diff --git a/src/OpenSHC/Text/TextEditorState/initializeAndLayoutHelpText.cpp b/src/OpenSHC/Text/TextEditorState/initializeAndLayoutHelpText.cpp index ac6882fef..01f33a511 100644 --- a/src/OpenSHC/Text/TextEditorState/initializeAndLayoutHelpText.cpp +++ b/src/OpenSHC/Text/TextEditorState/initializeAndLayoutHelpText.cpp @@ -9,7 +9,7 @@ namespace Text { for (int i = 0; i < 20000; ++i) { this->lineLayoutTable[i].leftBorder = 25; this->lineLayoutTable[i].rightBorder = this->dialogContentWidth - 25; - this->lineLayoutTable[i].unknown2 = 0; + this->lineLayoutTable[i].widthForCentering = 0; } // Adds vertical space at start for (int i = 0; i < 4; ++i) { diff --git a/src/OpenSHC/Text/TextEditorState/processHelpRichTextTokens.cpp b/src/OpenSHC/Text/TextEditorState/processHelpRichTextTokens.cpp index 760bec549..ca3e75a9c 100644 --- a/src/OpenSHC/Text/TextEditorState/processHelpRichTextTokens.cpp +++ b/src/OpenSHC/Text/TextEditorState/processHelpRichTextTokens.cpp @@ -19,6 +19,16 @@ #include "OpenSHC/Globals/DAT_TextureRenderCoreObject.hpp" #include "OpenSHC/Globals/DAT_UserHelpDefinedData.hpp" +// Even now, part of the logic after the L' ' is pulled into the switch, but not the right way +// the position after endlink might be related to being the first position that has no +2 on the the memindex, but still +// sets the wideBuffer; no idea how to trigger it, though + +// It is possible to move the pulled section by messing with certain branches, however, this likely really requires the +// right structure over all cases, it might even involve mixed structures, since a human wrote it + +// most unmarked things are related to the alternate help text, which only seems to be active for the map editor text, +// which is strange. So either this is a left over, or maybe the help text editor hat a switch for this in some way + namespace OpenSHC { namespace Text { @@ -32,28 +42,20 @@ namespace Text { // FUNCTION: STRONGHOLDCRUSADER 0x0045FDC0 int TextEditorState::processHelpRichTextTokens(int param_1) { - int iVar5; - wchar_t* pwVar6; - int iVar12; - int dVar14; - int iVar17; - int local_12c; - int local_118; - int local_114; - int local_104; - int local_f8; - int local_f4; wchar_t wideTextBuffer[100]; + + int local_f8; + int currentLinkId = -1; int textMemIndex = 0; FontSizeClass* currentFontClass = DAT_TextManagerObject::instance.fontSizeClassArray + 17; - int currentFontLineHeight = DAT_TextManagerObject::instance.fontSizeClassArray[17].lineHeight_0x14; + int currentFontLineHeight = currentFontClass->lineHeight_0x14; BOOL local_f0 = FALSE; BGR24 color = 0xccfaff; BGR24 linkColor = 0x8bcf84; int imageCount = -1; BOOL centreActive = FALSE; - BOOL local_120 = FALSE; + BOOL centerCurrentLine = FALSE; int lineStartY = 0; int lineEndY = 0; int local_11c = 0; @@ -68,7 +70,7 @@ namespace Text { return 1; } this->field49_0x23964 = -1; - this->field50_0x23968 = -1; + this->currentLinkId = -1; if (this->field51_0x2396c) { DAT_00df334c::instance = 1; } @@ -78,30 +80,38 @@ namespace Text { if (this->activeHelpHotspotIndex > this->customHelpTextLength) { this->activeHelpHotspotIndex = this->customHelpTextLength; } - int leftPosition; int lineY = -1; + int leftPosition; do { leftPosition = this->lineLayoutTable[++lineY].leftBorder; } while (leftPosition == -1); - while (true) { - iVar5 = textMemIndex; - BGR24 charColor = color; - local_12c = 1; + + bool abortProcessing; + do { + abortProcessing = false; + + TextMemUnion textToRender; + int local_114; + BGR24 charColor; + // false if text debug view token handled (this->helpDialogSubMode == 1), maybe related to input? + BOOL local_12c; + + charColor = color; + local_12c = TRUE; if (0 <= currentLinkId) { charColor = linkColor; } local_114 = textMemIndex; - TextMemUnion textMemUnion; - textMemUnion.value + textToRender.value = MACRO_CALL_MEMBER(TextEditorState_Func::getWideCharOrWideCharPointer, this)(&textMemIndex); - if (this->useAlternateHelpTab && textMemUnion.value < L' ' - && textMemUnion.helpToken != Enums::HTT_NEWPARAGRAPH && iVar5 == this->activeHelpHotspotIndex) { - lineEndY = lineY + currentFontLineHeight; + if (this->useAlternateHelpTab && textToRender.value < L' ' + && textToRender.helpToken != Enums::HTT_NEWPARAGRAPH && local_114 == this->activeHelpHotspotIndex) { lineStartY = lineY; + lineEndY = lineY + currentFontLineHeight; if (param_1 == 1) { int xModify = 0; - if (local_120) { - xModify = this->lineLayoutTable[lineY].unknown2 / 2; + if (centerCurrentLine) { + xModify = this->lineLayoutTable[lineY].widthForCentering / 2; } local_10c = local_114 - local_11c; if (this->field51_0x2396c < 0) { @@ -112,100 +122,101 @@ namespace Text { this->field51_0x2396c = 0; } local_134 = 0; + int xPos = this->dialogContentX + xModify; + int yPos = this->dialogContentY - this->helpContentScrollOffsetY; MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( - this->dialogContentX + xModify - 1 + leftPosition, - this->dialogContentY - this->helpContentScrollOffsetY - 1 + lineY, - this->dialogContentX + xModify - 1 + leftPosition, - this->dialogContentY - this->helpContentScrollOffsetY + 1 + lineEndY, + xPos + leftPosition - 1, yPos + lineY - 1, xPos + leftPosition - 1, yPos + lineEndY + 1, COL_DARK_LIME::instance.shortValue); + xPos = this->dialogContentX + xModify; + yPos = this->dialogContentY - this->helpContentScrollOffsetY; MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( - this->dialogContentX + xModify + leftPosition, - this->dialogContentY - this->helpContentScrollOffsetY - 1 + lineY, - this->dialogContentX + xModify + leftPosition, - this->dialogContentY - this->helpContentScrollOffsetY + 1 + lineEndY, + xPos + leftPosition, yPos + lineY - 1, xPos + leftPosition, yPos + lineEndY + 1, COL_DARK_LIME::instance.shortValue); local_e4 = TRUE; } } - iVar17 = local_11c; - switch (textMemUnion.helpToken) { - case Enums::HTT_PIC: + switch (textToRender.helpToken) { + case Enums::HTT_PIC: { if (this->helpDialogSubMode == 1) { charColor = 0xff; - local_12c = 0; + local_12c = FALSE; MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, u__PIC__d__S__005a583c, this->DAT_PointerToTemporaryTextMemory[textMemIndex], this->graphicFileNames[this->DAT_PointerToTemporaryTextMemory[textMemIndex]]); + Enums::HelpTextPicturePositionToken positionToken + = (Enums::HelpTextPicturePositionToken)this->DAT_PointerToTemporaryTextMemory[textMemIndex + 1]; ++textMemIndex; - switch ((Enums::HelpTextPicturePositionToken)this->DAT_PointerToTemporaryTextMemory[textMemIndex]) { + switch (positionToken) { case Enums::HTPPT_LEFT: wcscat(wideTextBuffer, u_LEFT__005a5494); textMemIndex += 2; + textToRender.text = wideTextBuffer; break; case Enums::HTPPT_RIGHT: wcscat(wideTextBuffer, u_RIGHT__005a5484); textMemIndex += 2; + textToRender.text = wideTextBuffer; break; case Enums::HTPPT_CENTRE: wcscat(wideTextBuffer, u_CENTRE__005a5474); textMemIndex += 2; + textToRender.text = wideTextBuffer; break; case Enums::HTPPT_HERE: wcscat(wideTextBuffer, u_HERE__005a5468); textMemIndex += 2; + textToRender.text = wideTextBuffer; break; default: textMemIndex += 2; + textToRender.text = wideTextBuffer; break; } break; - } else { - ++imageCount; - if (param_1 == 1) { - if (this->DAT_PointerToTemporaryTextMemory[textMemIndex + 1] != 3) { - textMemIndex += 3; - continue; - } - } else { - if (param_1 - || (imageCount != this->imageHotspotCount - && this->DAT_PointerToTemporaryTextMemory[textMemIndex + 1] != 3)) { - textMemIndex += 3; - continue; - } - if (imageCount == this->imageHotspotCount) { - this->imageHotspotTable[this->imageHotspotCount].yPos = lineY + 25; - this->imageHotspotTable[this->imageHotspotCount].imageRelated - = this->DAT_PointerToTemporaryTextMemory[textMemIndex]; - this->imageHotspotTable[this->imageHotspotCount].unknown3 = currentLinkId; - } + } + ++imageCount; + + bool validImageIndex = false; + int imageIndex; + if (param_1 == 1 && this->DAT_PointerToTemporaryTextMemory[textMemIndex + 1] == Enums::HTPPT_HERE) { + imageIndex = this->DAT_PointerToTemporaryTextMemory[textMemIndex]; + validImageIndex = true; + } else if (!param_1 + && (imageCount == this->imageHotspotCount + || this->DAT_PointerToTemporaryTextMemory[textMemIndex + 1] == Enums::HTPPT_HERE)) { + imageIndex = this->DAT_PointerToTemporaryTextMemory[textMemIndex]; + if (imageCount == this->imageHotspotCount) { + this->imageHotspotTable[this->imageHotspotCount].yPos = lineY + 25; + this->imageHotspotTable[this->imageHotspotCount].imageIndex = imageIndex; + this->imageHotspotTable[this->imageHotspotCount].linkId = currentLinkId; } + validImageIndex = true; + } + if (validImageIndex) { Enums::HelpTextPicturePositionToken positionToken = (Enums::HelpTextPicturePositionToken)this->DAT_PointerToTemporaryTextMemory[textMemIndex + 1]; - int imageHeight = DAT_TextureRenderCoreObject::instance - .loadedGfxArray[99 - this->DAT_PointerToTemporaryTextMemory[textMemIndex]] - .height; - int imageWidth = DAT_TextureRenderCoreObject::instance - .loadedGfxArray[99 - this->DAT_PointerToTemporaryTextMemory[textMemIndex]] - .width; + ++textMemIndex; + int imageWidth = DAT_TextureRenderCoreObject::instance.loadedGfxArray[99 - imageIndex].width; + int imageHeight = DAT_TextureRenderCoreObject::instance.loadedGfxArray[99 - imageIndex].height; switch (positionToken) { - case Enums::HTPPT_LEFT: + case Enums::HTPPT_LEFT: { this->imageHotspotTable[this->imageHotspotCount].xPos = this->lineLayoutTable[lineY].leftBorder; + int newLeftBorder = this->lineLayoutTable[lineY].leftBorder + 25 + imageWidth; for (int i = 0; i < imageHeight + 50; ++i) { - this->lineLayoutTable[lineY + i].rightBorder - = this->lineLayoutTable[lineY].leftBorder + 25 + imageWidth; + this->lineLayoutTable[lineY + i].leftBorder = newLeftBorder; } break; - case Enums::HTPPT_RIGHT: + } + case Enums::HTPPT_RIGHT: { this->imageHotspotTable[this->imageHotspotCount].xPos = this->lineLayoutTable[lineY].rightBorder - imageWidth; + int newRightBorder = this->lineLayoutTable[lineY].rightBorder - imageWidth - 25; for (int i = 0; i < imageHeight + 50; ++i) { - this->lineLayoutTable[lineY + i].rightBorder - = this->lineLayoutTable[lineY].rightBorder - imageWidth - 25; - this->lineLayoutTable[lineY + i].leftBorder = -1; + this->lineLayoutTable[lineY + i].rightBorder = newRightBorder; } break; + } case Enums::HTPPT_CENTRE: this->imageHotspotTable[this->imageHotspotCount].xPos = (this->dialogContentWidth - imageWidth) / 2; @@ -213,339 +224,350 @@ namespace Text { this->lineLayoutTable[lineY + i].leftBorder = -1; } break; - case Enums::HTPPT_HERE: - imageWidth += 3; - if (this->lineLayoutTable[lineY].rightBorder < imageWidth + leftPosition) { + case Enums::HTPPT_HERE: { + int const hereWidth = imageWidth + 3; + if (hereWidth + leftPosition > this->lineLayoutTable[lineY].rightBorder) { local_f0 = FALSE; - if (local_120) { - this->lineLayoutTable[lineY].unknown2 + if (centerCurrentLine) { + this->lineLayoutTable[lineY].widthForCentering = this->lineLayoutTable[lineY].rightBorder - leftPosition; - local_120 = centreActive; + centerCurrentLine = centreActive; } do { lineY += currentFontLineHeight + 1; do { - leftPosition = this->lineLayoutTable[lineY++].leftBorder; + leftPosition = this->lineLayoutTable[++lineY].leftBorder; } while (leftPosition == -1); - } while (this->lineLayoutTable[lineY].rightBorder < leftPosition + imageWidth); + } while (leftPosition + hereWidth > this->lineLayoutTable[lineY].rightBorder); if (this->useAlternateHelpTab && param_1 == 1) { - ++local_134; local_100 = local_11c; local_11c = local_114; - if (0 < this->field51_0x2396c && 1 < local_134) { - this->activeHelpHotspotIndex = iVar17 + local_10c; + ++local_134; + if (0 < this->field51_0x2396c && 2 <= local_134) { local_134 = -10000; - if (local_114 <= this->activeHelpHotspotIndex) { - this->activeHelpHotspotIndex = local_114 + -1; + this->activeHelpHotspotIndex = local_100 + local_10c; + if (this->activeHelpHotspotIndex >= local_11c) { + this->activeHelpHotspotIndex = local_11c - 1; } this->field51_0x2396c = 0; } } currentFontLineHeight = currentFontClass->lineHeight_0x14; } - if (currentFontLineHeight < imageHeight) { + if (imageHeight > currentFontLineHeight) { currentFontLineHeight = imageHeight; } - leftPosition += imageWidth; + leftPosition += hereWidth; if (param_1 != 1 && imageCount == this->imageHotspotCount) { - this->imageHotspotTable[this->imageHotspotCount].xPos = leftPosition - imageWidth; + this->imageHotspotTable[this->imageHotspotCount].xPos = leftPosition - hereWidth; this->imageHotspotTable[this->imageHotspotCount].yPos = lineY; ++this->imageHotspotCount; } break; } - textMemIndex += 3; - if (positionToken == Enums::HTPPT_HERE || param_1) { - continue; } - ++this->imageHotspotCount; - DAT_TextManagerObject::instance.field6_0x18 = 0; - return FALSE; + textMemIndex += 2; + if (positionToken != Enums::HTPPT_HERE && !param_1) { + ++this->imageHotspotCount; + DAT_TextManagerObject::instance.helpTextLinkActive = FALSE; + abortProcessing = true; + // continue; + } + } else { + textMemIndex += 3; } - case Enums::HTT_FONT: + break; + } + case Enums::HTT_FONT: { if (this->helpDialogSubMode == 1) { charColor = 0xff; - local_12c = 0; + local_12c = FALSE; MACRO_CALL(Global_Func::PrintToDestination)( wideTextBuffer, u__FONT__d__005a5454, this->DAT_PointerToTemporaryTextMemory[textMemIndex]); textMemIndex += 2; + textToRender.text = wideTextBuffer; break; - } else { - int fontSize = this->DAT_PointerToTemporaryTextMemory[textMemIndex]; - if (fontSize < 15) { - fontSize += 5; - } - textMemIndex = textMemIndex + 2; - currentFontClass = DAT_TextManagerObject::instance.fontSizeClassArray + fontSize; - dVar14 = DAT_TextManagerObject::instance.fontSizeClassArray[fontSize].lineHeight_0x14; - if (currentFontLineHeight < dVar14 || !local_f0) { - currentFontLineHeight = dVar14; - } - continue; } - case Enums::HTT_COLOUR: + int fontSize = this->DAT_PointerToTemporaryTextMemory[textMemIndex]; + if (fontSize < 15) { + fontSize += 5; + } + textMemIndex += 2; + currentFontClass = &DAT_TextManagerObject::instance.fontSizeClassArray[fontSize]; + if (currentFontClass->lineHeight_0x14 > currentFontLineHeight || !local_f0) { + currentFontLineHeight = currentFontClass->lineHeight_0x14; + } + break; + } + case Enums::HTT_COLOUR: { if (this->helpDialogSubMode == 1) { charColor = 0xff; - local_12c = 0; + local_12c = FALSE; MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, u__COLOUR__S__005a5824, DAT_UserHelpDefinedData::instance .field6_0x7a16c[this->DAT_PointerToTemporaryTextMemory[textMemIndex]] .name_0x0); textMemIndex += 2; + textToRender.text = wideTextBuffer; break; - } else { - if (param_1 == 1) { - int const colorIndex = this->DAT_PointerToTemporaryTextMemory[textMemIndex]; + } + if (param_1 == 1) { + int const colorIndex = this->DAT_PointerToTemporaryTextMemory[textMemIndex]; - uint colorRed; - uint colorGreen; - uint colorBlue; - if (this->helpDialogVariant == 2 && colorIndex == 1) { - colorRed = 0xd7; - colorGreen = 0xd2; - colorBlue = 0xa4; - } else { - colorRed = DAT_UserHelpDefinedData::instance.field6_0x7a16c[colorIndex].r_0x4; - colorGreen = DAT_UserHelpDefinedData::instance.field6_0x7a16c[colorIndex].g_0x8; - colorBlue = DAT_UserHelpDefinedData::instance.field6_0x7a16c[colorIndex].b_0xc; - } - textMemIndex += 2; - color = ((colorBlue << 16) & 0xff0000) | ((colorGreen << 8) & 0x00ff00) | colorRed & 0x0000ff; + uint colorRed; + uint colorGreen; + uint colorBlue; + if (this->helpDialogVariant == 2 && colorIndex == 1) { + colorRed = 0xd7; + colorGreen = 0xd2; + colorBlue = 0xa4; } else { - textMemIndex += 2; + colorRed = DAT_UserHelpDefinedData::instance.field6_0x7a16c[colorIndex].r_0x4; + colorGreen = DAT_UserHelpDefinedData::instance.field6_0x7a16c[colorIndex].g_0x8; + colorBlue = DAT_UserHelpDefinedData::instance.field6_0x7a16c[colorIndex].b_0xc; } - continue; + textMemIndex += 2; + color = RGB(colorRed, colorGreen, colorBlue); + } else { + textMemIndex += 2; } - case Enums::HTT_LINKCOLOUR: + break; + } + case Enums::HTT_LINKCOLOUR: { if (this->helpDialogSubMode == 1) { charColor = 0xff; - local_12c = 0; + local_12c = FALSE; MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, u__LINKCOLOUR__S__005a5804, DAT_UserHelpDefinedData::instance .field6_0x7a16c[this->DAT_PointerToTemporaryTextMemory[textMemIndex]] .name_0x0); textMemIndex += 2; + textToRender.text = wideTextBuffer; break; + } + if (param_1 == 1) { + int const colorIndex = this->DAT_PointerToTemporaryTextMemory[textMemIndex]; + textMemIndex += 2; + linkColor = RGB(DAT_UserHelpDefinedData::instance.field6_0x7a16c[colorIndex].r_0x4, + DAT_UserHelpDefinedData::instance.field6_0x7a16c[colorIndex].g_0x8, + DAT_UserHelpDefinedData::instance.field6_0x7a16c[colorIndex].b_0xc); } else { - if (param_1 == 1) { - int const colorIndex = this->DAT_PointerToTemporaryTextMemory[textMemIndex]; - textMemIndex += 2; - linkColor - = ((DAT_UserHelpDefinedData::instance.field6_0x7a16c[colorIndex].b_0xc << 16) & 0xff0000) - | ((DAT_UserHelpDefinedData::instance.field6_0x7a16c[colorIndex].g_0x8 << 8) & 0x00ff00) - | DAT_UserHelpDefinedData::instance.field6_0x7a16c[colorIndex].r_0x4 & 0x0000ff; - } else { - textMemIndex += 2; - } - continue; + textMemIndex += 2; } - case Enums::HTT_LINK: + break; + } + case Enums::HTT_LINK: { if (this->helpDialogSubMode == 1) { charColor = 0xff; - local_12c = 0; + local_12c = FALSE; MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, u__LINK_S__005a57ec, DAT_UserHelpDefinedData::instance .HelpSections[this->DAT_PointerToTemporaryTextMemory[textMemIndex]]); textMemIndex += 2; + textToRender.text = wideTextBuffer; break; - } else { - currentLinkId = this->DAT_PointerToTemporaryTextMemory[textMemIndex]; - if (param_1 == 1) { - DAT_TextManagerObject::instance.field6_0x18 = 1; - } - textMemIndex += 2; - continue; } - case Enums::HTT_INCLUDE: + currentLinkId = this->DAT_PointerToTemporaryTextMemory[textMemIndex]; + if (param_1 == 1) { + DAT_TextManagerObject::instance.helpTextLinkActive = TRUE; + } + textMemIndex += 2; + break; + } + case Enums::HTT_INCLUDE: { if (this->helpDialogSubMode == 1) { charColor = 0xff; - local_12c = 0; + local_12c = FALSE; MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, u__INCLUDE_S__005a57cc, DAT_UserHelpDefinedData::instance .HelpSections[this->DAT_PointerToTemporaryTextMemory[textMemIndex]]); textMemIndex += 2; + textToRender.text = wideTextBuffer; break; - } else { - textMemIndex += 2; - continue; } - case Enums::HTT_SOUND: + textMemIndex += 2; + break; + } + case Enums::HTT_SOUND: { if (this->helpDialogSubMode == 1) { charColor = 0xff; - local_12c = 0; + local_12c = FALSE; MACRO_CALL(Global_Func::PrintToDestination)(wideTextBuffer, u__SOUND_S__005a57b0, this->soundFileNames[this->DAT_PointerToTemporaryTextMemory[textMemIndex]]); textMemIndex += 2; + textToRender.text = wideTextBuffer; break; - } else { - if (param_1 == 1 && -1 < lineY - this->helpContentScrollOffsetY - && lineY - this->helpContentScrollOffsetY < this->dialogContentHeight + } + if (param_1 == 1) { + int const visibleY = lineY - this->helpContentScrollOffsetY; + if (0 <= visibleY && visibleY < this->dialogContentHeight && !this->soundFilePlayedFlags[this->DAT_PointerToTemporaryTextMemory[textMemIndex]]) { this->soundFilePlayedFlags[this->DAT_PointerToTemporaryTextMemory[textMemIndex]] = 1; } - textMemIndex += 2; - continue; } - case Enums::HTT_ENDLINK: + textMemIndex += 2; + break; + } + case Enums::HTT_ENDLINK: { if (this->helpDialogSubMode == 1) { charColor = 0xff; - local_12c = 0; + local_12c = FALSE; wcscpy(wideTextBuffer, u__LINK__005a53d4); + textToRender.text = wideTextBuffer; break; - } else { - currentLinkId = -1; - if (param_1 == 1) { - DAT_TextManagerObject::instance.field6_0x18 = 0; - } - continue; } - case (wchar_t*)13: // unknown case? - default: - pwVar6 = textMemUnion.text; - goto switchD_00460064_caseD_d; - case Enums::HTT_STRING: + currentLinkId = -1; + if (param_1 == 1) { + DAT_TextManagerObject::instance.helpTextLinkActive = FALSE; + } + break; + } + case Enums::HTT_STRING: { if (this->helpDialogSubMode == 1) { charColor = 0xff; - local_12c = 0; + local_12c = FALSE; MACRO_CALL(Global_Func::PrintToDestination)( wideTextBuffer, u__STRING__d__005a5358, this->DAT_PointerToTemporaryTextMemory[textMemIndex]); textMemIndex += 2; + textToRender.text = wideTextBuffer; break; - } else { - textMemIndex += 2; - continue; } - case Enums::HTT_CENTRE: + textMemIndex += 2; + break; + } + case Enums::HTT_CENTRE: { if (this->helpDialogSubMode == 1) { charColor = 0xff; - local_12c = 0; + local_12c = FALSE; wcscpy(wideTextBuffer, u__CENTRE__005a539c); + textToRender.text = wideTextBuffer; break; - } else { - centreActive = TRUE; - local_120 = TRUE; - continue; } - case Enums::HTT_ENDCENTRE: + centreActive = TRUE; + centerCurrentLine = TRUE; + break; + } + case Enums::HTT_ENDCENTRE: { if (this->helpDialogSubMode == 1) { charColor = 0xff; - local_12c = 0; + local_12c = FALSE; wcscpy(wideTextBuffer, u__CENTRE__005a5388); + textToRender.text = wideTextBuffer; break; - } else { - centreActive = FALSE; - continue; } - case Enums::HTT_NEWPARAGRAPH: - if (local_120) { - this->lineLayoutTable[lineY].unknown2 = this->lineLayoutTable[lineY].rightBorder - leftPosition; - local_120 = centreActive; + centreActive = FALSE; + break; + } + case Enums::HTT_NEWPARAGRAPH: { + if (centerCurrentLine) { + this->lineLayoutTable[lineY].widthForCentering + = this->lineLayoutTable[lineY].rightBorder - leftPosition; + centerCurrentLine = centreActive; } - if (this->useAlternateHelpTab && iVar5 == this->activeHelpHotspotIndex) { - lineEndY = currentFontLineHeight + lineY; - iVar12 = 0; + if (this->useAlternateHelpTab && local_114 == this->activeHelpHotspotIndex) { lineStartY = lineY; + lineEndY = currentFontLineHeight + lineY; if (param_1 == 1) { - if (local_120) { - iVar12 = this->lineLayoutTable[lineY].unknown2 / 2; + int xModify = 0; + if (centerCurrentLine) { + xModify = this->lineLayoutTable[lineY].widthForCentering / 2; } + int xPos = this->dialogContentX + xModify; + int yPos = this->dialogContentY - this->helpContentScrollOffsetY; MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( - this->dialogContentX + iVar12 - 1 + leftPosition, - this->dialogContentY - this->helpContentScrollOffsetY - 1 + lineY, - this->dialogContentX + iVar12 - 1 + leftPosition, - this->dialogContentY - this->helpContentScrollOffsetY + 1 + lineEndY, - COL_DARK_LIME::instance.shortValue); + xPos - 1 + leftPosition, yPos - 1 + lineStartY, xPos - 1 + leftPosition, + yPos + 1 + lineEndY, COL_DARK_LIME::instance.shortValue); + xPos = this->dialogContentX + xModify; + yPos = this->dialogContentY - this->helpContentScrollOffsetY; MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( - this->dialogContentX + iVar12 + leftPosition, - this->dialogContentY - this->helpContentScrollOffsetY - 1 + lineY, - this->dialogContentX + iVar12 + leftPosition, - this->dialogContentY - this->helpContentScrollOffsetY + 1 + lineEndY, + xPos + leftPosition, yPos - 1 + lineStartY, xPos + leftPosition, yPos + 1 + lineEndY, COL_DARK_LIME::instance.shortValue); local_e4 = TRUE; } } - lineY += 3 + currentFontLineHeight; local_f0 = FALSE; + lineY += 3 + currentFontLineHeight; do { - leftPosition = this->lineLayoutTable[lineY++].leftBorder; + leftPosition = this->lineLayoutTable[++lineY].leftBorder; } while (leftPosition == -1); currentFontLineHeight = currentFontClass->lineHeight_0x14; - iVar12 = local_11c; - if (this->useAlternateHelpTab != 0) { + + if (this->useAlternateHelpTab) { local_100 = local_11c; + local_11c = local_114; if (param_1 == 1) { ++local_134; - if (0 < this->field51_0x2396c && 1 < local_134) { - this->activeHelpHotspotIndex = local_10c + local_11c; + if (0 < this->field51_0x2396c && 2 <= local_134) { local_134 = -10000; - if (iVar5 <= this->activeHelpHotspotIndex) { - this->activeHelpHotspotIndex = iVar5 + -1; + this->activeHelpHotspotIndex = local_10c + local_100; + if (this->activeHelpHotspotIndex >= local_11c) { + this->activeHelpHotspotIndex = local_11c - 1; } this->field51_0x2396c = 0; } } - iVar12 = iVar5; - if (iVar5 == this->activeHelpHotspotIndex && param_1 == 1) { + if (local_11c == this->activeHelpHotspotIndex && param_1 == 1) { local_10c = 0; if (this->field51_0x2396c < 0) { - this->activeHelpHotspotIndex = DAT_00df3348::instance + local_11c; - if (iVar5 <= this->activeHelpHotspotIndex) { - this->activeHelpHotspotIndex = iVar5 + -1; + this->activeHelpHotspotIndex = DAT_00df3348::instance + local_100; + if (this->activeHelpHotspotIndex >= local_11c) { + this->activeHelpHotspotIndex = local_11c - 1; } this->field51_0x2396c = 0; } local_134 = 0; } } - local_11c = iVar12; if (this->helpDialogSubMode == 1) { charColor = 0xff; - local_12c = 0; + local_12c = FALSE; wcscpy(wideTextBuffer, u__NEWPARAGRAPH__005a5790); + textToRender.text = wideTextBuffer; break; } - continue; - case Enums::HTT_TAB: // TODO?: unknown token + break; + } + case Enums::HTT_TAB: { // TODO?: unknown token if (this->helpDialogSubMode == 1) { charColor = 0xff; - local_12c = 0; + local_12c = FALSE; wcscpy(wideTextBuffer, u__tab__005a5784); + textToRender.text = wideTextBuffer; break; - } else { - if (this->lineLayoutTable[lineY].rightBorder < leftPosition + 30) { - local_f0 = FALSE; - if (local_120) { - this->lineLayoutTable[lineY].unknown2 - = this->lineLayoutTable[lineY].rightBorder - leftPosition; - local_120 = centreActive; - } + } + if (leftPosition + 30 > this->lineLayoutTable[lineY].rightBorder) { + local_f0 = FALSE; + if (centerCurrentLine) { + this->lineLayoutTable[lineY].widthForCentering + = this->lineLayoutTable[lineY].rightBorder - leftPosition; + centerCurrentLine = centreActive; + } + do { + lineY += currentFontLineHeight + 1; do { - lineY += currentFontLineHeight + 1; - do { - leftPosition = this->lineLayoutTable[lineY++].leftBorder; - } while (leftPosition == -1); - } while (this->lineLayoutTable[lineY].rightBorder < leftPosition + 30); - iVar12 = local_11c; - if (this->useAlternateHelpTab && param_1 == 1) { - ++local_134; - local_100 = local_11c; - iVar12 = iVar5; - if (0 < this->field51_0x2396c && 1 < local_134) { - this->activeHelpHotspotIndex = local_11c + local_10c; - local_134 = -10000; - if (iVar5 <= this->activeHelpHotspotIndex) { - this->activeHelpHotspotIndex = iVar5 + -1; - } - this->field51_0x2396c = 0; + leftPosition = this->lineLayoutTable[++lineY].leftBorder; + } while (leftPosition == -1); + } while (leftPosition + 30 > this->lineLayoutTable[lineY].rightBorder); + + if (this->useAlternateHelpTab && param_1 == 1) { + local_100 = local_11c; + local_11c = local_114; + ++local_134; + if (0 < this->field51_0x2396c && 2 <= local_134) { + local_134 = -10000; + this->activeHelpHotspotIndex = local_100 + local_10c; + if (this->activeHelpHotspotIndex >= local_11c) { + this->activeHelpHotspotIndex = local_11c - 1; } + this->field51_0x2396c = 0; } - local_11c = iVar12; - currentFontLineHeight = currentFontClass->lineHeight_0x14; } - leftPosition += 30; - continue; + currentFontLineHeight = currentFontClass->lineHeight_0x14; } - case (wchar_t*)0: // TODO?: unknown token, or just NULL, meaning end? + leftPosition += 30; + break; + } + case (wchar_t*)0: { // TODO?: unknown token, or just NULL, meaning end? if (param_1 == 0) { this->topVisibleLineIndex = lineY + currentFontLineHeight - 1; do { @@ -563,255 +585,209 @@ namespace Text { } if (lineEndY > this->helpContentScrollOffsetY + this->dialogContentHeight) { this->helpContentScrollOffsetY = (lineEndY - this->dialogContentHeight) + 5; - DAT_TextManagerObject::instance.field6_0x18 = 0; + DAT_TextManagerObject::instance.helpTextLinkActive = FALSE; return TRUE; } } - DAT_TextManagerObject::instance.field6_0x18 = 0; - return TRUE; - } - if (!this->useAlternateHelpTab) { - DAT_TextManagerObject::instance.field6_0x18 = 0; - return TRUE; - } - DAT_00df3348::instance = local_10c; - if (0 < this->field51_0x2396c && local_134 == 1) { - this->activeHelpHotspotIndex = local_10c + local_11c; - if (this->activeHelpHotspotIndex > this->customHelpTextLength) { - this->activeHelpHotspotIndex = this->customHelpTextLength; + } else if (this->useAlternateHelpTab) { + DAT_00df3348::instance = local_10c; + if (0 < this->field51_0x2396c && local_134 == 1) { + this->activeHelpHotspotIndex = local_10c + local_11c; + if (this->activeHelpHotspotIndex > this->customHelpTextLength) { + this->activeHelpHotspotIndex = this->customHelpTextLength; + } + this->field51_0x2396c = 0; } - this->field51_0x2396c = 0; - } - if (!local_e4 && this->activeHelpHotspotIndex && DAT_00df334c::instance) { - --this->activeHelpHotspotIndex; - this->field52_0x23970 = 0; - DAT_TextManagerObject::instance.field6_0x18 = 0; - return TRUE; + if (!local_e4 && this->activeHelpHotspotIndex && DAT_00df334c::instance) { + --this->activeHelpHotspotIndex; + this->field52_0x23970 = 0; + DAT_TextManagerObject::instance.helpTextLinkActive = FALSE; + return TRUE; + } + DAT_00df334c::instance = 0; } - DAT_00df334c::instance = 0; - DAT_TextManagerObject::instance.field6_0x18 = 0; + DAT_TextManagerObject::instance.helpTextLinkActive = FALSE; return TRUE; } - // NOTE: This is either the local text buffer, or the text directly from the text memory... - pwVar6 = wideTextBuffer; - switchD_00460064_caseD_d: - if (0x1f < (int)pwVar6) { - iVar12 = MACRO_CALL_MEMBER(FontSizeClass_Func::getWidthOfWideText, currentFontClass)( - pwVar6, wcslen((wchar_t*)pwVar6)); - iVar5 = local_11c; - local_f4 = leftPosition + iVar12; - if (this->lineLayoutTable[lineY].rightBorder < local_f4) { - local_f0 = FALSE; - if (local_120) { - this->lineLayoutTable[lineY].unknown2 = this->lineLayoutTable[lineY].rightBorder - leftPosition; - local_120 = centreActive; - } - lineY += 1 + currentFontLineHeight; - do { - leftPosition = this->lineLayoutTable[lineY++].leftBorder; - } while (leftPosition == -1); - currentFontLineHeight = currentFontClass->lineHeight_0x14; - if (this->useAlternateHelpTab) { - ++local_134; - local_100 = local_11c; - local_11c = local_114; - if (0 < this->field51_0x2396c && 1 < local_134) { - this->activeHelpHotspotIndex = iVar5 + local_10c; - local_134 = -10000; - if (local_114 <= this->activeHelpHotspotIndex) { - this->activeHelpHotspotIndex = local_114 - 1; - } - this->field51_0x2396c = 0; + } + if (textToRender.value < L' ') { + continue; + } + + int textWidth = MACRO_CALL_MEMBER(FontSizeClass_Func::getWidthOfWideText, currentFontClass)( + textToRender.text, wcslen(textToRender.text)); + if (leftPosition + textWidth > this->lineLayoutTable[lineY].rightBorder) { + local_f0 = FALSE; + if (centerCurrentLine) { + this->lineLayoutTable[lineY].widthForCentering + = this->lineLayoutTable[lineY].rightBorder - leftPosition; + centerCurrentLine = centreActive; + } + lineY += 1 + currentFontLineHeight; + do { + leftPosition = this->lineLayoutTable[++lineY].leftBorder; + } while (leftPosition == -1); + currentFontLineHeight = currentFontClass->lineHeight_0x14; + if (this->useAlternateHelpTab) { + ++local_134; + local_100 = local_11c; + local_11c = local_114; + if (0 < this->field51_0x2396c && 2 <= local_134) { + local_134 = -10000; + this->activeHelpHotspotIndex = local_100 + local_10c; + if (this->activeHelpHotspotIndex >= local_11c) { + this->activeHelpHotspotIndex = local_11c - 1; } + this->field51_0x2396c = 0; } - local_f4 = iVar12 + leftPosition; - if (this->lineLayoutTable[lineY].rightBorder < (int)local_f4) { - local_f8 = 0; - if (local_120) { - local_f8 = this->lineLayoutTable[lineY].unknown2 / 2; - } - int const wideStrLength = wcslen((wchar_t*)pwVar6); - for (local_118 = 0; local_118 < wideStrLength; ++local_118) { - int wideCharWidth = MACRO_CALL_MEMBER( - FontSizeClass_Func::getWideCharWidth, currentFontClass)(textMemUnion.text[local_118]); - while (this->lineLayoutTable[lineY].rightBorder < leftPosition + wideCharWidth) { - iVar5 = local_11c; - if (local_120) { - this->lineLayoutTable[lineY].unknown2 - = this->lineLayoutTable[lineY].rightBorder - leftPosition; - local_120 = centreActive; - } - lineY += currentFontLineHeight + 1; - if (this->useAlternateHelpTab && param_1 == 1) { - ++local_134; - local_100 = local_11c; - local_11c = local_114 + local_118; - if (0 < this->field51_0x2396c && 1 < local_134) { - this->activeHelpHotspotIndex = iVar5 + local_10c; - local_134 = -10000; - if (local_114 + local_118 <= this->activeHelpHotspotIndex) { - this->activeHelpHotspotIndex = local_114 + local_118 - 1; - } - this->field51_0x2396c = 0; - } - } - do { - leftPosition = this->lineLayoutTable[lineY++].leftBorder; - } while (leftPosition == -1); - if (local_120) { - local_f8 = this->lineLayoutTable[lineY].unknown2 / 2; - } + } + if (leftPosition + textWidth > this->lineLayoutTable[lineY].rightBorder) { + local_f8 = 0; + if (centerCurrentLine) { + local_f8 = this->lineLayoutTable[lineY].widthForCentering / 2; + } + int wordLength = wcslen(textToRender.text); + for (int i = 0; i < wordLength; ++i) { + int wideCharWidth = MACRO_CALL_MEMBER(FontSizeClass_Func::getWideCharWidth, currentFontClass)( + textToRender.text[i]); + while (leftPosition + wideCharWidth > this->lineLayoutTable[lineY].rightBorder) { + + if (centerCurrentLine) { + this->lineLayoutTable[lineY].widthForCentering + = this->lineLayoutTable[lineY].rightBorder - leftPosition; + centerCurrentLine = centreActive; } - if (!this->useAlternateHelpTab || local_114 + local_118 != this->activeHelpHotspotIndex) { - if (param_1 == 1) { - iVar5 = MACRO_CALL_MEMBER(FontSizeClass_Func::renderWideChar, currentFontClass)( - textMemUnion.text[local_118], this->dialogContentX + local_f8 + leftPosition, - this->dialogContentY - this->helpContentScrollOffsetY + lineY, charColor, 0); - local_f0 = TRUE; - if (MACRO_CALL_MEMBER( - Input::MouseState_Func::isMouseInsideBox, DAT_MouseState::ptr)( - this->dialogContentX + local_f8 + leftPosition - this->helpContentScrollX, - this->dialogContentY - this->helpContentScrollOffsetY + lineY - - this->helpContentScrollY, - iVar5 - this->dialogContentX + local_f8 + leftPosition, - currentFontLineHeight + 2)) { - if (local_12c) { - this->field49_0x23964 = local_114 + local_118; - this->field50_0x23968 = currentLinkId; - } else { - this->field49_0x23964 = local_114; - } + lineY += currentFontLineHeight + 1; + if (this->useAlternateHelpTab && param_1 == 1) { + local_100 = local_11c; + local_11c = local_114 + i; + ++local_134; + if (0 < this->field51_0x2396c && 2 <= local_134) { + local_134 = -10000; + this->activeHelpHotspotIndex = local_100 + local_10c; + if (this->activeHelpHotspotIndex >= local_11c) { + this->activeHelpHotspotIndex = local_11c - 1; } + this->field51_0x2396c = 0; } - } else { - lineEndY = lineY + currentFontLineHeight; - lineStartY = lineY; - if (param_1 == 1) { - if (local_12c) { - local_10c = (local_118 - local_11c) + local_114; - if (this->field51_0x2396c < 0) { - this->activeHelpHotspotIndex = DAT_00df3348::instance + local_100; - if (this->activeHelpHotspotIndex >= local_11c) { - this->activeHelpHotspotIndex = local_11c - 1; - } - this->field51_0x2396c = 0; - } - local_134 = 0; - MACRO_CALL_MEMBER( - UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( - this->dialogContentX + local_f8 - 1 + leftPosition, - this->dialogContentY - this->helpContentScrollOffsetY + -1 + lineY, - this->dialogContentX + local_f8 - 1 + leftPosition, - this->dialogContentY - this->helpContentScrollOffsetY + 1 + lineEndY, - COL_DARK_LIME::instance.shortValue); - MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, - DAT_PencilRenderCore::ptr)(this->dialogContentX + local_f8 + leftPosition, - this->dialogContentY - this->helpContentScrollOffsetY - 1 + lineY, - this->dialogContentX + local_f8 + leftPosition, - this->dialogContentY - this->helpContentScrollOffsetY + 1 + lineEndY, - COL_DARK_LIME::instance.shortValue); - local_e4 = TRUE; - } - iVar5 = MACRO_CALL_MEMBER(FontSizeClass_Func::renderWideChar, currentFontClass)( - textMemUnion.text[local_118], this->dialogContentX + local_f8 + leftPosition, - this->dialogContentY - this->helpContentScrollOffsetY + lineY, charColor, 0); - local_f0 = TRUE; - if (MACRO_CALL_MEMBER( - Input::MouseState_Func::isMouseInsideBox, DAT_MouseState::ptr)( - this->dialogContentX + local_f8 + leftPosition - this->helpContentScrollX, - this->dialogContentY - this->helpContentScrollOffsetY + lineY - - this->helpContentScrollY, - iVar5 - this->dialogContentX + local_f8 + leftPosition, - currentFontLineHeight + 2)) { - if (local_12c) { - this->field49_0x23964 = local_114 + local_118; - this->field50_0x23968 = currentLinkId; - } else { - this->field49_0x23964 = local_114; + } + do { + leftPosition = this->lineLayoutTable[++lineY].leftBorder; + } while (leftPosition == -1); + if (centerCurrentLine) { + local_f8 = this->lineLayoutTable[lineY].widthForCentering / 2; + } + } + if (this->useAlternateHelpTab && local_114 + i == this->activeHelpHotspotIndex) { + lineStartY = lineY; + lineEndY = lineY + currentFontLineHeight; + if (param_1 == 1) { + if (local_12c) { + local_10c = (i - local_11c) + local_114; + if (this->field51_0x2396c < 0) { + this->activeHelpHotspotIndex = DAT_00df3348::instance + local_100; + if (this->activeHelpHotspotIndex >= local_11c) { + this->activeHelpHotspotIndex = local_11c - 1; } + this->field51_0x2396c = 0; } + local_134 = 0; + int xPos = this->dialogContentX + local_f8; + int yPos = this->dialogContentY - this->helpContentScrollOffsetY; + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, + DAT_PencilRenderCore::ptr)(xPos - 1 + leftPosition, yPos - 1 + lineY, + xPos - 1 + leftPosition, yPos + 1 + lineEndY, + COL_DARK_LIME::instance.shortValue); + xPos = this->dialogContentX + local_f8; + yPos = this->dialogContentY - this->helpContentScrollOffsetY; + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, + DAT_PencilRenderCore::ptr)(xPos + leftPosition, yPos - 1 + lineY, + xPos + leftPosition, yPos + 1 + lineEndY, COL_DARK_LIME::instance.shortValue); + local_e4 = TRUE; } } - leftPosition += wideCharWidth; } - continue; - } - } - iVar5 = this->dialogContentX + leftPosition; - local_104 = (this->dialogContentY - this->helpContentScrollOffsetY) + lineY; - if (local_120) { - iVar5 += this->lineLayoutTable[lineY].unknown2 / 2; - } - int const wideStrLength = wcslen((wchar_t*)pwVar6); - for (int i = 0; i < wideStrLength; ++i) { - local_f8 = local_114 - local_11c; - if ((this->useAlternateHelpTab == 0) || (i + local_114 != this->activeHelpHotspotIndex)) { if (param_1 == 1) { + int charXPos = this->dialogContentX + local_f8 + leftPosition; + int charYPos = this->dialogContentY - this->helpContentScrollOffsetY + lineY; + + wchar_t currentChar = textToRender.text[i]; + int const newCharXPos = MACRO_CALL_MEMBER(FontSizeClass_Func::renderWideChar, + currentFontClass)(currentChar, charXPos, charYPos, charColor, 0); local_f0 = TRUE; - iVar12 = MACRO_CALL_MEMBER(FontSizeClass_Func::renderWideChar, currentFontClass)( - textMemUnion.text[i], iVar5, local_104, charColor, 0); if (MACRO_CALL_MEMBER(Input::MouseState_Func::isMouseInsideBox, DAT_MouseState::ptr)( - iVar5 - this->helpContentScrollX, local_104 - this->helpContentScrollY, - iVar12 - iVar5, currentFontLineHeight + 2)) { + charXPos - this->helpContentScrollX, charYPos - this->helpContentScrollY, + newCharXPos - charXPos, currentFontLineHeight + 2)) { if (local_12c) { - this->field49_0x23964 = i + local_114; - this->field50_0x23968 = currentLinkId; + this->field49_0x23964 = local_114 + i; + this->currentLinkId = currentLinkId; } else { this->field49_0x23964 = local_114; } } - } else { - dVar14 = MACRO_CALL_MEMBER(FontSizeClass_Func::getWideCharWidth, currentFontClass)( - textMemUnion.text[i]); - iVar12 = iVar5 + dVar14; - } - } else { - if (param_1 == 1 && local_12c) { - MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, - DAT_PencilRenderCore::ptr)(iVar5 + -1, local_104 - 1, iVar5 + -1, - local_104 + 1 + currentFontLineHeight, COL_DARK_LIME::instance.shortValue); - MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, - DAT_PencilRenderCore::ptr)(iVar5, local_104 - 1, iVar5, - local_104 + 1 + currentFontLineHeight, COL_DARK_LIME::instance.shortValue); - local_e4 = TRUE; } - lineEndY = lineY + currentFontLineHeight; - lineStartY = lineY; - if (param_1 == 1) { - local_10c = local_f8 + i; - local_134 = 0; - if (this->field51_0x2396c < 0 && local_12c) { - this->activeHelpHotspotIndex = local_100 + DAT_00df3348::instance; - if (this->activeHelpHotspotIndex >= local_11c) { - this->activeHelpHotspotIndex = local_11c + -1; - } - this->field51_0x2396c = 0; - } - local_f0 = TRUE; - iVar12 = MACRO_CALL_MEMBER(FontSizeClass_Func::renderWideChar, currentFontClass)( - textMemUnion.text[i], iVar5, local_104, charColor, 0); - if (MACRO_CALL_MEMBER(Input::MouseState_Func::isMouseInsideBox, DAT_MouseState::ptr)( - iVar5 - this->helpContentScrollX, local_104 - this->helpContentScrollY, - iVar12 - iVar5, currentFontLineHeight + 2)) { - if (local_12c) { - this->field49_0x23964 = i + local_114; - this->field50_0x23968 = currentLinkId; - } else { - this->field49_0x23964 = local_114; - } + + leftPosition += wideCharWidth; + } + continue; + } + } + int charXPos = this->dialogContentX + leftPosition; + int charYPos = (this->dialogContentY - this->helpContentScrollOffsetY) + lineY; + if (centerCurrentLine) { + charXPos += this->lineLayoutTable[lineY].widthForCentering / 2; + } + int wordLength = wcslen(textToRender.text); + for (int i = 0; i < wordLength; ++i) { + if (this->useAlternateHelpTab && i + local_114 == this->activeHelpHotspotIndex) { + if (param_1 == 1 && local_12c) { + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( + charXPos - 1, charYPos - 1, charXPos - 1, charYPos + 1 + currentFontLineHeight, + COL_DARK_LIME::instance.shortValue); + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawLine, DAT_PencilRenderCore::ptr)( + charXPos, charYPos - 1, charXPos, charYPos + 1 + currentFontLineHeight, + COL_DARK_LIME::instance.shortValue); + local_e4 = TRUE; + } + lineStartY = lineY; + lineEndY = lineY + currentFontLineHeight; + if (param_1 == 1) { + local_134 = 0; + local_10c = local_114 - local_11c + i; + if (this->field51_0x2396c < 0 && local_12c) { + this->activeHelpHotspotIndex = local_100 + DAT_00df3348::instance; + if (this->activeHelpHotspotIndex >= local_11c) { + this->activeHelpHotspotIndex = local_11c - 1; } + this->field51_0x2396c = 0; + } + } + } + + if (param_1 == 1) { + local_f0 = TRUE; + int oldCharPos = charXPos; + wchar_t const currentChar = textToRender.text[i]; + charXPos = MACRO_CALL_MEMBER(FontSizeClass_Func::renderWideChar, currentFontClass)( + currentChar, charXPos, charYPos, charColor, 0); + if (MACRO_CALL_MEMBER(Input::MouseState_Func::isMouseInsideBox, DAT_MouseState::ptr)( + oldCharPos - this->helpContentScrollX, charYPos - this->helpContentScrollY, + charXPos - oldCharPos, currentFontLineHeight + 2)) { + if (local_12c) { + this->field49_0x23964 = i + local_114; + this->currentLinkId = currentLinkId; } else { - dVar14 = MACRO_CALL_MEMBER(FontSizeClass_Func::getWideCharWidth, currentFontClass)( - textMemUnion.text[i]); - iVar12 = iVar5 + dVar14; + this->field49_0x23964 = local_114; } } - iVar5 = iVar12; + } else { + charXPos += MACRO_CALL_MEMBER(FontSizeClass_Func::getWideCharWidth, currentFontClass)( + textToRender.text[i]); } - leftPosition = local_f4; } - } + leftPosition += textWidth; + } while (!abortProcessing); + return FALSE; } - } } diff --git a/src/OpenSHC/Text/TextEditorState/renderHelpImageHotspots.cpp b/src/OpenSHC/Text/TextEditorState/renderHelpImageHotspots.cpp index fee866c9d..08998118c 100644 --- a/src/OpenSHC/Text/TextEditorState/renderHelpImageHotspots.cpp +++ b/src/OpenSHC/Text/TextEditorState/renderHelpImageHotspots.cpp @@ -16,7 +16,7 @@ namespace Text { void TextEditorState::renderHelpImageHotspots() { for (int i = 0; i < this->imageHotspotCount; ++i) { - int _gfxIndex = 99 - this->imageHotspotTable[i].imageRelated; + int _gfxIndex = 99 - this->imageHotspotTable[i].imageIndex; if ((this->useInGameHelpHandler || this->helpDialogVariant == 1) && !MACRO_CALL_MEMBER(UI::Rendering::TextureRenderCore_Func::checkIfGfxTgxStartsWithTransparentPixels, DAT_TextureRenderCoreObject::ptr)(_gfxIndex)) { @@ -64,7 +64,7 @@ namespace Text { this->imageHotspotTable[i].yPos - this->helpContentScrollY + this->dialogContentY - this->helpContentScrollOffsetY, boxWidth, boxHeight)) { - this->field50_0x23968 = this->imageHotspotTable[i].unknown3; + this->currentLinkId = this->imageHotspotTable[i].linkId; } } } diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 91ba63d60..422a04fb7 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18759,7 +18759,7 @@ SHC_3BB0A8C1_0x0045F580 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045F5B0 | 99.0% | Reimplemented, two cases where an "edx + ecx" is flipped to "ecx + edx" -SHC_3BB0A8C1_0x0045FDC0 | 0.0% | Pending +SHC_3BB0A8C1_0x0045FDC0 | 70.1% | Reimplemented, but heavy structural mismatch, seems functional SHC_3BB0A8C1_0x0045FEC0 | 0.0% | Pending From d799d92df507805c04b5dea0b8c1d25c722cb622 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 15 Oct 2026 22:16:01 +0200 Subject: [PATCH 44/44] reimplement: OpenSHC::Text::TextEditorState clean up --- src/OpenSHC/OS.func.hpp | 8 -------- src/OpenSHC/OS.hpp | 4 ---- src/OpenSHC/Text/TextEditorState/parseHlp.cpp | 11 +++++++---- 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/OpenSHC/OS.func.hpp b/src/OpenSHC/OS.func.hpp index 1be1b6d1e..4523a0835 100644 --- a/src/OpenSHC/OS.func.hpp +++ b/src/OpenSHC/OS.func.hpp @@ -179,13 +179,5 @@ namespace OS_Func { void(__cdecl*)(int _Code), REIMPLEMENTED_CRT, Address::SHC_3BB0A8C1_0x00583D55, &OpenSHC::OS::_exit) _exit; - MACRO_FUNCTION_RESOLVER(int(__cdecl*)(FILE*, wchar_t const*, ...), REIMPLEMENTED_CRT, - Address::SHC_3BB0A8C1_0x005807A8, &OpenSHC::OS::_fwprintf) - _fwprintf; - - MACRO_FUNCTION_RESOLVER( - long(__cdecl*)(wchar_t const*), REIMPLEMENTED_CRT, Address::SHC_3BB0A8C1_0x00580C0B, &OpenSHC::OS::__wtol) - __wtol; - } // namespace OS_Func } // namespace OpenSHC diff --git a/src/OpenSHC/OS.hpp b/src/OpenSHC/OS.hpp index de952d160..b0cad4b80 100644 --- a/src/OpenSHC/OS.hpp +++ b/src/OpenSHC/OS.hpp @@ -103,9 +103,5 @@ namespace OS { void __cdecl _exit(int _Code); - int _fwprintf(FILE* stream, wchar_t const* format, ...); - - long __wtol(wchar_t const* str); - } // namespace OS } // namespace OpenSHC diff --git a/src/OpenSHC/Text/TextEditorState/parseHlp.cpp b/src/OpenSHC/Text/TextEditorState/parseHlp.cpp index cfc8eb8fb..42a2a910a 100644 --- a/src/OpenSHC/Text/TextEditorState/parseHlp.cpp +++ b/src/OpenSHC/Text/TextEditorState/parseHlp.cpp @@ -5,8 +5,8 @@ #include "OpenSHC/UI/Rendering/TextureRenderCore.func.hpp" #include "OpenSHC/Util/WideCharMultiByteState.func.hpp" #include "OpenSHC/Text/Enums/HelpTextPicturePositionToken.hpp" -#include "OpenSHC/wstring-literals.hpp" #include "OpenSHC/string-literals.hpp" +#include "OpenSHC/wstring-literals.hpp" #include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" #include "OpenSHC/Globals/DAT_TextEditorState.hpp" @@ -117,13 +117,16 @@ namespace Text { if (!MACRO_CALL(OS_Func::__wcsicmp)(u_left_005a5714, picPosition)) { this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTPPT_LEFT; - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u_right_005a5708, picPosition)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)( + u_right_005a5708, picPosition)) { this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTPPT_RIGHT; - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u_centre_005a56f8, picPosition)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)( + u_centre_005a56f8, picPosition)) { this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTPPT_CENTRE; - } else if (!MACRO_CALL(OS_Func::__wcsicmp)(u_here_005a56ec, picPosition)) { + } else if (!MACRO_CALL(OS_Func::__wcsicmp)( + u_here_005a56ec, picPosition)) { this->DAT_PointerToTemporaryTextMemory[textMemIndex++] = Enums::HTPPT_HERE; }