diff --git a/IMPLEMENTATION_CHEAT_SHEET.md b/IMPLEMENTATION_CHEAT_SHEET.md index 0b7151e3..5d7dac4f 100644 --- a/IMPLEMENTATION_CHEAT_SHEET.md +++ b/IMPLEMENTATION_CHEAT_SHEET.md @@ -196,6 +196,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. + ### GOTO A function may contain multiple GOTOs. diff --git a/src/OpenSHC/Text/TextEditorState.func.hpp b/src/OpenSHC/Text/TextEditorState.func.hpp index d8f348f7..6d3169a3 100644 --- a/src/OpenSHC/Text/TextEditorState.func.hpp +++ b/src/OpenSHC/Text/TextEditorState.func.hpp @@ -35,8 +35,8 @@ namespace Text { &TextEditorState::findOrAddHelpSectionName) findOrAddHelpSectionName; - MACRO_FUNCTION_RESOLVER( - uint (TextEditorState::*)(FILE*), false, Address::SHC_3BB0A8C1_0x0045D200, &TextEditorState::parseHLPPart) + MACRO_FUNCTION_RESOLVER(LPCWSTR (TextEditorState::*)(FILE*), false, Address::SHC_3BB0A8C1_0x0045D200, + &TextEditorState::parseHLPPart) parseHLPPart; MACRO_FUNCTION_RESOLVER(void (TextEditorState::*)(), false, Address::SHC_3BB0A8C1_0x0045D370, diff --git a/src/OpenSHC/Text/TextEditorState.hpp b/src/OpenSHC/Text/TextEditorState.hpp index 3d08c6d0..9428f0fe 100644 --- a/src/OpenSHC/Text/TextEditorState.hpp +++ b/src/OpenSHC/Text/TextEditorState.hpp @@ -35,7 +35,7 @@ namespace Text { BOOLEnum helpSectionParseSucceeded; // 0x00000024 length: 4 int currentHelpSectionID; // 0x00000028 length: 4 int helpSectionHistoryStack[30]; // 0x0000002C length: 120 - undefined4 counter; // 0x000000A4 length: 4 + int counter; // 0x000000A4 length: 4 undefined4 helpContentScrollOffsetY; // 0x000000A8 length: 4 undefined4 topVisibleLineIndex; // 0x000000AC length: 4 undefined4 dialogX; // 0x000000B0 length: 4 @@ -58,17 +58,22 @@ namespace Text { char* customHelpTextPointer; // 0x000000F4 length: 4 undefined4 isCustomHelpTextWide; // 0x000000F8 length: 4 undefined4 customHelpTextBufferSize; // 0x000000FC length: 4 - undefined4 customTextMaxLength; // 0x00000100 length: 4 + int customTextMaxLength; // 0x00000100 length: 4 char soundFileNames[5][1000]; // 0x00000104 length: 5000 byte soundFilePlayedFlags[5]; // 0x0000148C length: 5 undefined1 padding_0x1491[3]; // 0x00001491 length: 3 undefined4 soundFileCount; // 0x00001494 length: 4 char graphicFileNames[20][1000]; // 0x00001498 length: 20000 - undefined4 graphicFileCount; // 0x000062B8 length: 4 + int graphicFileCount; // 0x000062B8 length: 4 short lineLayoutTable[60000]; // 0x000062BC length: 120000 int imageHotspotCount; // 0x0002377C length: 4 short imageHotspotTable[50][4]; // 0x00023780 length: 400 - int intArray1[25]; // 0x00023910 length: 100 + int intArray1[20]; // 0x00023910 length: 80 + int unknown_0x23960; // 0x00023960 length: 4 + int unknown_0x23964; // 0x00023964 length: 4 + int unknown_0x23968; // 0x00023968 length: 4 + int unknown_0x2396C; // 0x0002396C length: 4 + int unknown_0x23970; // 0x00023970 length: 4 private: TextEditorState(TextEditorState const&); @@ -81,7 +86,7 @@ namespace Text { // Constructor TextEditorState* Constructor_TextEditorState(); - void setHelpWindowBounds(undefined4 param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4); + void setHelpWindowBounds(undefined4 x, undefined4 y, undefined4 height, undefined4 width); void resetHelpStateFields(); @@ -89,7 +94,7 @@ namespace Text { int findOrAddHelpSectionName(char* param_1); - uint parseHLPPart(FILE* filePointer); + LPCWSTR parseHLPPart(FILE* filePointer); void loadHelpSectionGraphics(); diff --git a/src/OpenSHC/Text/TextEditorState/Constructor_TextEditorState.cpp b/src/OpenSHC/Text/TextEditorState/Constructor_TextEditorState.cpp new file mode 100644 index 00000000..afb18c1b --- /dev/null +++ b/src/OpenSHC/Text/TextEditorState/Constructor_TextEditorState.cpp @@ -0,0 +1,43 @@ +#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; + + // 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; + } + this->counter = counter; + break; + } + + for (int i = 0; i < 20; ++i) { + this->intArray1[i] = 0; + } + return this; + } + +} +} diff --git a/src/OpenSHC/Text/TextEditorState/findHelpSectionIndexByName.cpp b/src/OpenSHC/Text/TextEditorState/findHelpSectionIndexByName.cpp new file mode 100644 index 00000000..018ef45a --- /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/src/OpenSHC/Text/TextEditorState/findOrAddHelpSectionName.cpp b/src/OpenSHC/Text/TextEditorState/findOrAddHelpSectionName.cpp new file mode 100644 index 00000000..d1be3a1e --- /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/src/OpenSHC/Text/TextEditorState/loadHelpSectionGraphics.cpp b/src/OpenSHC/Text/TextEditorState/loadHelpSectionGraphics.cpp new file mode 100644 index 00000000..ea5ba6b5 --- /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/src/OpenSHC/Text/TextEditorState/parseHLPPart.cpp b/src/OpenSHC/Text/TextEditorState/parseHLPPart.cpp new file mode 100644 index 00000000..f630aa3b --- /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/src/OpenSHC/Text/TextEditorState/resetHelpStateFields.cpp b/src/OpenSHC/Text/TextEditorState/resetHelpStateFields.cpp new file mode 100644 index 00000000..de0e1f34 --- /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/src/OpenSHC/Text/TextEditorState/setHelpWindowBounds.cpp b/src/OpenSHC/Text/TextEditorState/setHelpWindowBounds.cpp new file mode 100644 index 00000000..ba116919 --- /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 10a0c2b0..9393da1c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -18147,17 +18147,17 @@ SHC_3BB0A8C1_0x0045CD10 | 0.0% | Pending SHC_3BB0A8C1_0x0045D060 | 0.0% | Pending -SHC_3BB0A8C1_0x0045D080 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D080 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D0B0 | 0.0% | Pending -SHC_3BB0A8C1_0x0045D0C0 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D0C0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045D140 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D140 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045D1A0 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D1A0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0045D200 | 0.0% | Pending +SHC_3BB0A8C1_0x0045D200 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045D300 | 0.0% | Pending @@ -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 @@ -18749,7 +18749,7 @@ SHC_3BB0A8C1_0x0045F0D0 | 0.0% | Pending SHC_3BB0A8C1_0x0045F120 | 0.0% | Pending -SHC_3BB0A8C1_0x0045F130 | 0.0% | Pending +SHC_3BB0A8C1_0x0045F130 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0045F240 | 0.0% | Pending