From 0ccd22d3abc436293cce201636bbe21cbfb08acf Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sat, 15 Aug 2026 23:16:14 +0200 Subject: [PATCH 01/37] reimplement: SHC_3BB0A8C1_0x00471BE0 100% --- .../Constructor_ResourceManager.cpp | 22 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/Constructor_ResourceManager.cpp diff --git a/src/OpenSHC/IO/ResourceManager/Constructor_ResourceManager.cpp b/src/OpenSHC/IO/ResourceManager/Constructor_ResourceManager.cpp new file mode 100644 index 00000000..d6ace3a8 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/Constructor_ResourceManager.cpp @@ -0,0 +1,22 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x00471BE0 + ResourceManager* ResourceManager::Constructor_ResourceManager() + { + this->mapFileCounter = 0; + + // FIXME?: Assuming the loadedMapNames is [500][1001], then this fill does not null the entire array. + MACRO_CALL_MEMBER(LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 500000, 0, this->loadedMapNames); + return this; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index a31b91b1..b1aedd06 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -21335,7 +21335,7 @@ SHC_3BB0A8C1_0x00471A80 | 0.0% | Pending SHC_3BB0A8C1_0x00471AA0 | 0.0% | Pending -SHC_3BB0A8C1_0x00471BE0 | 0.0% | Pending +SHC_3BB0A8C1_0x00471BE0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00471C10 | 0.0% | Pending From d523720b21d43486e3a3f2c60548b2c051cdef4f Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sat, 15 Aug 2026 23:26:01 +0200 Subject: [PATCH 02/37] reimplement: SHC_3BB0A8C1_0x0046C200 100% --- .../IO/ResourceManager/loadMapMetaByID.cpp | 23 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/loadMapMetaByID.cpp diff --git a/src/OpenSHC/IO/ResourceManager/loadMapMetaByID.cpp b/src/OpenSHC/IO/ResourceManager/loadMapMetaByID.cpp new file mode 100644 index 00000000..cdad9fa6 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/loadMapMetaByID.cpp @@ -0,0 +1,23 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_MapPropertiesState.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046C200 + void ResourceManager::loadMapMetaByID(dword id) + { + DAT_GameCore::instance.mapType = this->mapMetaInfoArray[id].mapType; + DAT_GameCore::instance.savedMapLocked = this->mapMetaInfoArray[id].mapLocked; + DAT_GameCore::instance.savedMapBalance = this->mapMetaInfoArray[id].mapBalance; + DAT_GameCore::instance.savedMapEndInt2 = this->mapMetaInfoArray[id].mapEndInt2; + DAT_GameCore::instance.mapPlayerCount = this->mapMetaInfoArray[id].mapPlayerCount; + DAT_MapPropertiesState::instance.scenarionMissionType = this->mapMetaInfoArray[id].int0; + DAT_MapPropertiesState::instance.scenarioMissionSiegeOrInvasion = this->mapMetaInfoArray[id].mapType2; + DAT_GameCore::instance.mapU4Int0_2 = 0; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index b1aedd06..5473a842 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -20899,7 +20899,7 @@ SHC_3BB0A8C1_0x0046BD50 | 0.0% | Pending SHC_3BB0A8C1_0x0046BDB0 | 0.0% | Pending -SHC_3BB0A8C1_0x0046C200 | 0.0% | Pending +SHC_3BB0A8C1_0x0046C200 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046C280 | 0.0% | Pending From c7032fa298b819f61c0a1a16516d9eb94f8fd5ce Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sat, 15 Aug 2026 23:34:06 +0200 Subject: [PATCH 03/37] reimplement: SHC_3BB0A8C1_0x0046C280 100% --- .../getChecksumOfMapByName.cpp | 20 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/getChecksumOfMapByName.cpp diff --git a/src/OpenSHC/IO/ResourceManager/getChecksumOfMapByName.cpp b/src/OpenSHC/IO/ResourceManager/getChecksumOfMapByName.cpp new file mode 100644 index 00000000..e6a24b24 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/getChecksumOfMapByName.cpp @@ -0,0 +1,20 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/OS.func.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046C280 + dword ResourceManager::getChecksumOfMapByName(char* mapNameAddress) + { + for (int _mapIndex = 0; _mapIndex < this->loadedMapsCount; ++_mapIndex) { + if (!MACRO_CALL(OS_Func::__stricmp)(this->mapNames[_mapIndex], mapNameAddress)) { + return this->mapMetaInfoArray[_mapIndex].loadedMapsChecksumArray; + } + } + return 0; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 5473a842..bb598cba 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -20901,7 +20901,7 @@ SHC_3BB0A8C1_0x0046BDB0 | 0.0% | Pending SHC_3BB0A8C1_0x0046C200 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0046C280 | 0.0% | Pending +SHC_3BB0A8C1_0x0046C280 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046C2E0 | 0.0% | Pending From 4ed88b721f0ce95a68ff185beab3a1c4db4bb83e Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sat, 15 Aug 2026 23:37:44 +0200 Subject: [PATCH 04/37] reimplement: SHC_3BB0A8C1_0x0046C2E0 100% --- .../ResourceManager/getLoadedMapNameForIndex.cpp | 16 ++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/getLoadedMapNameForIndex.cpp diff --git a/src/OpenSHC/IO/ResourceManager/getLoadedMapNameForIndex.cpp b/src/OpenSHC/IO/ResourceManager/getLoadedMapNameForIndex.cpp new file mode 100644 index 00000000..57d25172 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/getLoadedMapNameForIndex.cpp @@ -0,0 +1,16 @@ +#include "../ResourceManager.func.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046C2E0 + char* ResourceManager::getLoadedMapNameForIndex(int mapIndex) + { + if (mapIndex >= 500) { + return NULL; + } + return this->loadedMapNames[mapIndex]; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index bb598cba..d5b5883b 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -20903,7 +20903,7 @@ SHC_3BB0A8C1_0x0046C200 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046C280 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0046C2E0 | 0.0% | Pending +SHC_3BB0A8C1_0x0046C2E0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046C300 | 0.0% | Pending From a64457ccbfae1fa27f2e1fe67a69049270d78f85 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sat, 15 Aug 2026 23:39:36 +0200 Subject: [PATCH 05/37] reimplement: SHC_3BB0A8C1_0x0046C300 100% --- .../getFileNameOfCurrentActiveResource.cpp | 13 +++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/getFileNameOfCurrentActiveResource.cpp diff --git a/src/OpenSHC/IO/ResourceManager/getFileNameOfCurrentActiveResource.cpp b/src/OpenSHC/IO/ResourceManager/getFileNameOfCurrentActiveResource.cpp new file mode 100644 index 00000000..acd34eaf --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/getFileNameOfCurrentActiveResource.cpp @@ -0,0 +1,13 @@ +#include "../ResourceManager.func.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046C300 + char* ResourceManager::getFileNameOfCurrentActiveResource() + { + return this->resourceFileNameArray[this->currentActiveResourceType]; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index d5b5883b..d58ba048 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -20905,7 +20905,7 @@ SHC_3BB0A8C1_0x0046C280 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046C2E0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0046C300 | 0.0% | Pending +SHC_3BB0A8C1_0x0046C300 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046C320 | 0.0% | Pending From e6c3226c98f870801ead54cd2893335d39f532a2 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 00:02:33 +0200 Subject: [PATCH 06/37] reimplement: SHC_3BB0A8C1_0x0046C320 100% --- .../IO/ResourceManager/loadConfigPathTxt.cpp | 51 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/loadConfigPathTxt.cpp diff --git a/src/OpenSHC/IO/ResourceManager/loadConfigPathTxt.cpp b/src/OpenSHC/IO/ResourceManager/loadConfigPathTxt.cpp new file mode 100644 index 00000000..e2188028 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/loadConfigPathTxt.cpp @@ -0,0 +1,51 @@ +// disable deprecation warnings for strcpy +#pragma warning(disable : 4996) + +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/OS.func.hpp" +#include "OpenSHC/string-literals.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046C320 + void ResourceManager::loadConfigPathTxt() + { + FILE* _File = MACRO_CALL(OS_Func::_fopen)(s_configpath_txt_005a5a0c, s_rb_005a4e18); + if (!_File) { + return; + } + + MACRO_CALL(OS_Func::_fseek)(_File, 0, FILE_END); + int _count = MACRO_CALL(OS_Func::_ftell)(_File); + MACRO_CALL(OS_Func::_fseek)(_File, 0, FILE_BEGIN); + + if (_count > 500) { + _count = 500; + } + + char _configPathBufferUnk[1000]; + MACRO_CALL(OS_Func::_fread)(_configPathBufferUnk, sizeof(char), _count, _File); + + _configPathBufferUnk[_count] = '\0'; + int index = 0; + for (; index < _count; ++index) { + if (_configPathBufferUnk[index] == '\r' || _configPathBufferUnk[index] == '\n') { + _configPathBufferUnk[index] = '\0'; + break; + } + } + if (index > 2) { + if (_configPathBufferUnk[index + -1] == '\\') { + _configPathBufferUnk[index + -1] = '\0'; + } + this->configPathLoadedUnk_0x7da = true; + strcpy(this->configPathUnk_0x7db, _configPathBufferUnk); + } + + MACRO_CALL(OS_Func::_fclose)(_File); + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index d58ba048..2821ea43 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -20907,7 +20907,7 @@ SHC_3BB0A8C1_0x0046C2E0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046C300 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0046C320 | 0.0% | Pending +SHC_3BB0A8C1_0x0046C320 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046C420 | 0.0% | Pending From f190acadc3e84b39928020f17513dfde8045ccfc Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 00:08:46 +0200 Subject: [PATCH 07/37] reimplement: SHC_3BB0A8C1_0x0046C420 100% --- .../IO/ResourceManager/doesFileExist.cpp | 20 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/doesFileExist.cpp diff --git a/src/OpenSHC/IO/ResourceManager/doesFileExist.cpp b/src/OpenSHC/IO/ResourceManager/doesFileExist.cpp new file mode 100644 index 00000000..5420fc7a --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/doesFileExist.cpp @@ -0,0 +1,20 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/OS.func.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046C420 + BOOLEnum ResourceManager::doesFileExist(char* filename) + { + int _fileHandle = MACRO_CALL(OS_Func::_ucrt_open)(filename, _O_BINARY, 0); + if (_fileHandle == -1) { + return FALSE; + } + MACRO_CALL(OS_Func::_ucrt_close)(_fileHandle); + return TRUE; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 2821ea43..b5fd80a9 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -20909,7 +20909,7 @@ SHC_3BB0A8C1_0x0046C300 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046C320 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0046C420 | 0.0% | Pending +SHC_3BB0A8C1_0x0046C420 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046C450 | 0.0% | Pending From 655134c2ff3ab8044f0e5448a461cfbf844c49ba Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 00:11:52 +0200 Subject: [PATCH 08/37] reimplement: SHC_3BB0A8C1_0x0046C450 100% --- .../IO/ResourceManager/setGfxFileFilter.cpp | 20 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/setGfxFileFilter.cpp diff --git a/src/OpenSHC/IO/ResourceManager/setGfxFileFilter.cpp b/src/OpenSHC/IO/ResourceManager/setGfxFileFilter.cpp new file mode 100644 index 00000000..997ff1da --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/setGfxFileFilter.cpp @@ -0,0 +1,20 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/string-literals.hpp" + +#include "OpenSHC/Globals/DAT_TextInputDefinedData.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046C450 + void ResourceManager::setGfxFileFilter() + { + this->openFileNameA.lpstrFilter = DAT_TextInputDefinedData::instance.field19_0x710; + this->openFileNameA.nFilterIndex = 1; + this->openFileNameA.lpstrDefExt = DAT_TextInputDefinedData::instance.field19_0x710; + this->openFileNameA.lpstrInitialDir = s_gfx__005a5a1c; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index b5fd80a9..9ec88925 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -20911,7 +20911,7 @@ SHC_3BB0A8C1_0x0046C320 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046C420 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0046C450 | 0.0% | Pending +SHC_3BB0A8C1_0x0046C450 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046C480 | 0.0% | Pending From 0a4bde4f76507056e9ee4d11db48184a580cec40 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 00:13:58 +0200 Subject: [PATCH 09/37] reimplement: SHC_3BB0A8C1_0x0046C480 100% --- .../IO/ResourceManager/setHelpFileFilter.cpp | 20 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/setHelpFileFilter.cpp diff --git a/src/OpenSHC/IO/ResourceManager/setHelpFileFilter.cpp b/src/OpenSHC/IO/ResourceManager/setHelpFileFilter.cpp new file mode 100644 index 00000000..c7f26bdc --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/setHelpFileFilter.cpp @@ -0,0 +1,20 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/string-literals.hpp" + +#include "OpenSHC/Globals/DAT_TextInputDefinedData.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046C480 + void ResourceManager::setHelpFileFilter() + { + this->openFileNameA.lpstrFilter = DAT_TextInputDefinedData::instance.field23_0x71c; + this->openFileNameA.nFilterIndex = 1; + this->openFileNameA.lpstrDefExt = DAT_TextInputDefinedData::instance.field23_0x71c; + this->openFileNameA.lpstrInitialDir = s_help__005a5a24; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 9ec88925..7505a600 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -20913,7 +20913,7 @@ SHC_3BB0A8C1_0x0046C420 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046C450 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0046C480 | 0.0% | Pending +SHC_3BB0A8C1_0x0046C480 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046C4B0 | 0.0% | Pending From 089d30b48a56172f8f63a2c3d705343f42d57149 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 00:16:09 +0200 Subject: [PATCH 10/37] reimplement: SHC_3BB0A8C1_0x0046C4B0 100% --- .../IO/ResourceManager/setSoundFileFilter.cpp | 21 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/setSoundFileFilter.cpp diff --git a/src/OpenSHC/IO/ResourceManager/setSoundFileFilter.cpp b/src/OpenSHC/IO/ResourceManager/setSoundFileFilter.cpp new file mode 100644 index 00000000..0f97fc51 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/setSoundFileFilter.cpp @@ -0,0 +1,21 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/string-literals.hpp" + +#include "OpenSHC/Globals/DAT_TextInputDefinedData.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046C4B0 + void ResourceManager::setSoundFileFilter() + + { + this->openFileNameA.lpstrFilter = DAT_TextInputDefinedData::instance.field27_0x728; + this->openFileNameA.nFilterIndex = 1; + this->openFileNameA.lpstrDefExt = DAT_TextInputDefinedData::instance.field27_0x728; + this->openFileNameA.lpstrInitialDir = s_fx__005a5a2c; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 7505a600..9447f437 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -20915,7 +20915,7 @@ SHC_3BB0A8C1_0x0046C450 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046C480 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0046C4B0 | 0.0% | Pending +SHC_3BB0A8C1_0x0046C4B0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046C4E0 | 0.0% | Pending From d0bfaff88956595e6ec19eb9c83b820dcef11ae4 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 00:31:47 +0200 Subject: [PATCH 11/37] reimplement: SHC_3BB0A8C1_0x0046C4E0 100% --- .../getSimpleFirst1024ByteSumOfFile.cpp | 33 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/getSimpleFirst1024ByteSumOfFile.cpp diff --git a/src/OpenSHC/IO/ResourceManager/getSimpleFirst1024ByteSumOfFile.cpp b/src/OpenSHC/IO/ResourceManager/getSimpleFirst1024ByteSumOfFile.cpp new file mode 100644 index 00000000..e06affb9 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/getSimpleFirst1024ByteSumOfFile.cpp @@ -0,0 +1,33 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/OS.func.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046C4E0 + int ResourceManager::getSimpleFirst1024ByteSumOfFile(char* filename) + { + int _byteValueSumUnk = 0; + + int _fileHandle = MACRO_CALL(OS_Func::_ucrt_open)(filename, _O_BINARY, 0); + if (_fileHandle == -1) { + _byteValueSumUnk = -1; + } else { + char _buf[1024]; + + int _lengthUnk; + do { + _lengthUnk = MACRO_CALL(OS_Func::_ucrt_read)(_fileHandle, _buf, sizeof(_buf)); + for (int _counter = 0; _counter < _lengthUnk; ++_counter) { + _byteValueSumUnk += _buf[_counter]; + } + } while (_lengthUnk != 0); + + MACRO_CALL(OS_Func::_ucrt_close)(_fileHandle); + } + return _byteValueSumUnk; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 9447f437..f98f682f 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -20917,7 +20917,7 @@ SHC_3BB0A8C1_0x0046C480 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046C4B0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0046C4E0 | 0.0% | Pending +SHC_3BB0A8C1_0x0046C4E0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046C520 | 0.0% | Pending From 10777e352c4221c2c6727e40f8af9234b02556aa Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 01:41:17 +0200 Subject: [PATCH 12/37] reimplement: SHC_3BB0A8C1_0x00471C10 100% --- .../getLoadedMapNameForIndex.cpp | 16 ---------- src/OpenSHC/IO/ResourceManager/mapNames.cpp | 29 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 3 files changed, 30 insertions(+), 17 deletions(-) delete mode 100644 src/OpenSHC/IO/ResourceManager/getLoadedMapNameForIndex.cpp create mode 100644 src/OpenSHC/IO/ResourceManager/mapNames.cpp diff --git a/src/OpenSHC/IO/ResourceManager/getLoadedMapNameForIndex.cpp b/src/OpenSHC/IO/ResourceManager/getLoadedMapNameForIndex.cpp deleted file mode 100644 index 57d25172..00000000 --- a/src/OpenSHC/IO/ResourceManager/getLoadedMapNameForIndex.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "../ResourceManager.func.hpp" - -namespace OpenSHC { -namespace IO { - - // FUNCTION: STRONGHOLDCRUSADER 0x0046C2E0 - char* ResourceManager::getLoadedMapNameForIndex(int mapIndex) - { - if (mapIndex >= 500) { - return NULL; - } - return this->loadedMapNames[mapIndex]; - } - -} // namespace IO -} // namespace OpenSHC diff --git a/src/OpenSHC/IO/ResourceManager/mapNames.cpp b/src/OpenSHC/IO/ResourceManager/mapNames.cpp new file mode 100644 index 00000000..4bf74782 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/mapNames.cpp @@ -0,0 +1,29 @@ +// disable deprecation warnings for strcpy +#pragma warning(disable : 4996) + +#include "../ResourceManager.func.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046C2E0 + char* ResourceManager::mapNames_getLoadedMapNameForIndex(int mapIndex) + { + if (mapIndex >= 500) { + return NULL; + } + return this->loadedMapNames[mapIndex]; + } + + // FUNCTION: STRONGHOLDCRUSADER 0x00471C10 + void ResourceManager::mapNames_syncLoadedMapNames() + { + this->mapFileCounter = this->loadedMapsCount; + for (int mapIndex = 0; mapIndex < (int)this->mapFileCounter; ++mapIndex) { + strcpy(MACRO_CALL_MEMBER(ResourceManager_Func::mapNames_getLoadedMapNameForIndex, this)(mapIndex), + this->mapNames[mapIndex]); + } + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f98f682f..2b1727db 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -21337,7 +21337,7 @@ SHC_3BB0A8C1_0x00471AA0 | 0.0% | Pending SHC_3BB0A8C1_0x00471BE0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00471C10 | 0.0% | Pending +SHC_3BB0A8C1_0x00471C10 | 100.0% | Reimplemented, requires called function to be active SHC_3BB0A8C1_0x00471C50 | 0.0% | Pending From 40b59b580a9f5303c29fd0e42c72a03b25b3f42c Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 10:29:56 +0200 Subject: [PATCH 13/37] reimplement: SHC_3BB0A8C1_0x00471C50 100% --- cmake/compiler-flags-gl.txt | 2 +- .../swapMapDataWithNextMap.cpp | 26 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 src/OpenSHC/IO/ResourceManager/swapMapDataWithNextMap.cpp diff --git a/cmake/compiler-flags-gl.txt b/cmake/compiler-flags-gl.txt index 5c4c1fe8..79e35428 100644 --- a/cmake/compiler-flags-gl.txt +++ b/cmake/compiler-flags-gl.txt @@ -2,5 +2,5 @@ src/OpenSHC/IO/LowLevelMemory/copyData.cpp src/OpenSHC/IO/LowLevelMemory/fillMemory_ByteValue.cpp src/OpenSHC/IO/DecoderState/encodeData.cpp src/OpenSHC/IO/DecoderState/decodeData.cpp -src/OpenSHC/IO/DecoderState/swapMapDataWithNextMap.cpp +src/OpenSHC/IO/ResourceManager/swapMapDataWithNextMap.cpp src/OpenSHC/UI/Rendering/WindowAndDirectDraw/takeScreenshot.cpp diff --git a/src/OpenSHC/IO/ResourceManager/swapMapDataWithNextMap.cpp b/src/OpenSHC/IO/ResourceManager/swapMapDataWithNextMap.cpp new file mode 100644 index 00000000..078afce8 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/swapMapDataWithNextMap.cpp @@ -0,0 +1,26 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x00471C50 + void ResourceManager::swapMapDataWithNextMap(int _mapFileIndex) + { + MACRO_CALL_MEMBER(LowLevelMemory_Func::copyData, DAT_LowLevelMemory::ptr)( + 1000, this->loadedMapNames[_mapFileIndex], this->resourceFileNameArray); + MACRO_CALL_MEMBER(LowLevelMemory_Func::copyData, DAT_LowLevelMemory::ptr)( + 1000, this->loadedMapNames[_mapFileIndex + 1], this->loadedMapNames[_mapFileIndex]); + MACRO_CALL_MEMBER(LowLevelMemory_Func::copyData, DAT_LowLevelMemory::ptr)( + 1000, this->resourceFileNameArray, this->loadedMapNames[_mapFileIndex + 1]); + + dword const nextFileTime = this->mapFileTimes[_mapFileIndex]; + this->mapFileTimes[_mapFileIndex] = this->mapFileTimes[_mapFileIndex + 1]; + this->mapFileTimes[_mapFileIndex + 1] = nextFileTime; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 2b1727db..1c77f314 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -21339,7 +21339,7 @@ SHC_3BB0A8C1_0x00471BE0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00471C10 | 100.0% | Reimplemented, requires called function to be active -SHC_3BB0A8C1_0x00471C50 | 0.0% | Pending +SHC_3BB0A8C1_0x00471C50 | 100.0% | Reimplemented, requires called function and subfunction to be active SHC_3BB0A8C1_0x00471CD0 | 0.0% | Pending From 83ad6ec9009fd8bd9011d5423b4f5c48fd8495c7 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 10:32:59 +0200 Subject: [PATCH 14/37] reimplement: SHC_3BB0A8C1_0x00471CD0 100% --- .../IO/ResourceManager/replaceMapNameWith.cpp | 22 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/replaceMapNameWith.cpp diff --git a/src/OpenSHC/IO/ResourceManager/replaceMapNameWith.cpp b/src/OpenSHC/IO/ResourceManager/replaceMapNameWith.cpp new file mode 100644 index 00000000..50000914 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/replaceMapNameWith.cpp @@ -0,0 +1,22 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x00471CD0 + void ResourceManager::replaceMapNameWith(dword id1, dword id2) + { + if (id1 == id2) { + return; + } + MACRO_CALL_MEMBER(LowLevelMemory_Func::copyData, DAT_LowLevelMemory::ptr)( + 1000, this->loadedMapNames[id1], this->loadedMapNames[id2]); + this->mapFileTimes[id2] = this->mapFileTimes[id1]; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 1c77f314..74eade06 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -21341,7 +21341,7 @@ SHC_3BB0A8C1_0x00471C10 | 100.0% | Reimplemented, requires called function to be SHC_3BB0A8C1_0x00471C50 | 100.0% | Reimplemented, requires called function and subfunction to be active -SHC_3BB0A8C1_0x00471CD0 | 0.0% | Pending +SHC_3BB0A8C1_0x00471CD0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00471D30 | 0.0% | Pending From 5816702fc177982420d29ad382cfdfb69186671d Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 17:33:13 +0200 Subject: [PATCH 15/37] reimplement: SHC_3BB0A8C1_0x00471D30 81.1% --- .../getCurrentResourceCoreNameUnk.cpp | 37 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/getCurrentResourceCoreNameUnk.cpp diff --git a/src/OpenSHC/IO/ResourceManager/getCurrentResourceCoreNameUnk.cpp b/src/OpenSHC/IO/ResourceManager/getCurrentResourceCoreNameUnk.cpp new file mode 100644 index 00000000..353d3c90 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/getCurrentResourceCoreNameUnk.cpp @@ -0,0 +1,37 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/Globals/DAT_CurrentResourceCoreName.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x00471D30 + char* ResourceManager::getCurrentResourceCoreNameUnk() + { + char const* _resourceName = MACRO_CALL_MEMBER(ResourceManager_Func::getFileNameOfCurrentActiveResource, this)(); + int basenameEnd = strlen(_resourceName); + DAT_CurrentResourceCoreName::instance[0] = '\0'; + + for (int basenameStart = basenameEnd + -1; basenameStart >= 0; --basenameStart) { + if (_resourceName[basenameStart] == '.') { + basenameEnd = basenameStart; + } + if (_resourceName[basenameStart] != '\\') { + continue; + } + ++basenameStart; + int basenameLength = 0; + if (basenameStart < basenameEnd) { + basenameLength = basenameEnd - basenameStart; + for (int i = basenameStart; i < basenameEnd; ++i) { + DAT_CurrentResourceCoreName::instance[i - basenameStart] = _resourceName[i]; + } + } + DAT_CurrentResourceCoreName::instance[basenameLength] = '\0'; + break; + } + return DAT_CurrentResourceCoreName::instance; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 74eade06..16c25cca 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -21343,7 +21343,7 @@ SHC_3BB0A8C1_0x00471C50 | 100.0% | Reimplemented, requires called function and s SHC_3BB0A8C1_0x00471CD0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00471D30 | 0.0% | Pending +SHC_3BB0A8C1_0x00471D30 | 81.1% | Reimplemented, but register diffs; logic is sound SHC_3BB0A8C1_0x00471DC0 | 0.0% | Pending From c3fc4367e7e79e23477fc12a947cef5d12fa31d6 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 18:39:04 +0200 Subject: [PATCH 16/37] reimplement: SHC_3BB0A8C1_0x00471DC0 100% --- .../doesFileOfActiveResourceExist.cpp | 21 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/doesFileOfActiveResourceExist.cpp diff --git a/src/OpenSHC/IO/ResourceManager/doesFileOfActiveResourceExist.cpp b/src/OpenSHC/IO/ResourceManager/doesFileOfActiveResourceExist.cpp new file mode 100644 index 00000000..24fd1549 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/doesFileOfActiveResourceExist.cpp @@ -0,0 +1,21 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/OS.func.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x00471DC0 + BOOLEnum ResourceManager::doesFileOfActiveResourceExist() + { + char* _Filename = MACRO_CALL_MEMBER(ResourceManager_Func::getFileNameOfCurrentActiveResource, this)(); + int fileDescriptor = MACRO_CALL(OpenSHC::OS_Func::_ucrt_open)(_Filename, _O_BINARY, 0); + if (fileDescriptor == -1) { + return FALSE; + } + MACRO_CALL(OpenSHC::OS_Func::_ucrt_close)(fileDescriptor); + return TRUE; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 16c25cca..edfe5fe4 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -21345,7 +21345,7 @@ SHC_3BB0A8C1_0x00471CD0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00471D30 | 81.1% | Reimplemented, but register diffs; logic is sound -SHC_3BB0A8C1_0x00471DC0 | 0.0% | Pending +SHC_3BB0A8C1_0x00471DC0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00471DF0 | 0.0% | Pending From 69144a1c8ce2e9f05713fcb862c651f9efb0dee1 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 18:44:53 +0200 Subject: [PATCH 17/37] reimplement: SHC_3BB0A8C1_0x00471DF0 100% --- .../resetOpenFileNameStruct.cpp | 26 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/resetOpenFileNameStruct.cpp diff --git a/src/OpenSHC/IO/ResourceManager/resetOpenFileNameStruct.cpp b/src/OpenSHC/IO/ResourceManager/resetOpenFileNameStruct.cpp new file mode 100644 index 00000000..21830fbe --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/resetOpenFileNameStruct.cpp @@ -0,0 +1,26 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_WindowAndDirectDraw.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x00471DF0 + void ResourceManager::resetOpenFileNameStruct() + { + MACRO_CALL_MEMBER(LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->openFileNameA), '\0', &this->openFileNameA); + this->openFileNameA.lStructSize = sizeof(this->openFileNameA); + this->openFileNameA.hwndOwner = DAT_WindowAndDirectDraw::instance.windowHandle; + this->openFileNameA.lpstrFile = this->strFile; + this->openFileNameA.nMaxFile = 1000; + this->openFileNameA.lpstrFileTitle = this->strFileTitle; + this->openFileNameA.nMaxFileTitle = 1000; + this->openFileNameA.Flags = OFN_NOCHANGEDIR; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index edfe5fe4..cb50d877 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -21347,7 +21347,7 @@ SHC_3BB0A8C1_0x00471D30 | 81.1% | Reimplemented, but register diffs; logic is so SHC_3BB0A8C1_0x00471DC0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00471DF0 | 0.0% | Pending +SHC_3BB0A8C1_0x00471DF0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00471E50 | 0.0% | Pending From 2a6c57531d038ed49c8734e99114f228704924bc Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 18:48:46 +0200 Subject: [PATCH 18/37] reimplement: SHC_3BB0A8C1_0x00471E50 100% --- .../readCurrentResourceIntoDestination.cpp | 22 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/readCurrentResourceIntoDestination.cpp diff --git a/src/OpenSHC/IO/ResourceManager/readCurrentResourceIntoDestination.cpp b/src/OpenSHC/IO/ResourceManager/readCurrentResourceIntoDestination.cpp new file mode 100644 index 00000000..8b6d1350 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/readCurrentResourceIntoDestination.cpp @@ -0,0 +1,22 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/OS.func.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x00471E50 + BOOLEnum ResourceManager::readCurrentResourceIntoDestination(void* destination, size_t size) + { + char* _Filename = MACRO_CALL_MEMBER(ResourceManager_Func::getFileNameOfCurrentActiveResource, this)(); + this->fileHandle = MACRO_CALL(OS_Func::_ucrt_open)(_Filename, _O_BINARY, 0); + if (this->fileHandle == -1) { + return FALSE; + } + this->loadPositionInCurrentResource = MACRO_CALL(OS_Func::_ucrt_read)(this->fileHandle, destination, size); + MACRO_CALL(OpenSHC::OS_Func::_ucrt_close)(this->fileHandle); + return TRUE; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index cb50d877..f1c0a4be 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -21349,7 +21349,7 @@ SHC_3BB0A8C1_0x00471DC0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00471DF0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00471E50 | 0.0% | Pending +SHC_3BB0A8C1_0x00471E50 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00471EB0 | 0.0% | Pending From 198ed81598683006ebddaa9a8a4b8e118e063e0d Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:01:58 +0200 Subject: [PATCH 19/37] reimplement: SHC_3BB0A8C1_0x00471EB0 100% --- .../getCurrentResourceSize.cpp | 24 +++++++++++++++++++ src/OpenSHC/OS/OS.cpp | 3 +++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/getCurrentResourceSize.cpp diff --git a/src/OpenSHC/IO/ResourceManager/getCurrentResourceSize.cpp b/src/OpenSHC/IO/ResourceManager/getCurrentResourceSize.cpp new file mode 100644 index 00000000..986b6d50 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/getCurrentResourceSize.cpp @@ -0,0 +1,24 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/Global.func.hpp" +#include "OpenSHC/OS.func.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x00471EB0 + int ResourceManager::getCurrentResourceSize() + { + char* _filename = MACRO_CALL_MEMBER(ResourceManager_Func::getFileNameOfCurrentActiveResource, this)(); + this->fileHandle = MACRO_CALL(OS_Func::_ucrt_open)(_filename, _O_BINARY, 0); + if (this->fileHandle == -1) { + return 0; + } + MACRO_CALL(OS_Func::_ucrt_lseek)(this->fileHandle, 0, FILE_END); + int _fileSize = MACRO_CALL(OS_Func::_ucrt_tell)(this->fileHandle); + MACRO_CALL(OS_Func::_ucrt_close)(this->fileHandle); + return _fileSize; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/src/OpenSHC/OS/OS.cpp b/src/OpenSHC/OS/OS.cpp index d38226ce..91d77adc 100644 --- a/src/OpenSHC/OS/OS.cpp +++ b/src/OpenSHC/OS/OS.cpp @@ -128,6 +128,9 @@ namespace OS { // STUB: STRONGHOLDCRUSADER 0x005824CD int __cdecl __toupper(int _C) { return toupper(_C); } + // STUB: STRONGHOLDCRUSADER 0x005826FB + int __cdecl _ucrt_tell(int handle) { return _tell(handle); } + // STUB: STRONGHOLDCRUSADER 0x0058277E int _ucrt_lseek(int fileDescriptor, long lDistanceToMove, DWORD moveMethod) { diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f1c0a4be..c4bcf953 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -21351,7 +21351,7 @@ SHC_3BB0A8C1_0x00471DF0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00471E50 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00471EB0 | 0.0% | Pending +SHC_3BB0A8C1_0x00471EB0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00471F10 | 0.0% | Pending From f1ea7148b1408110064aa93ee38d7730209ba844 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:24:17 +0200 Subject: [PATCH 20/37] reimplement: SHC_3BB0A8C1_0x00471F10 100% --- cmake/compiler-flags-gl.txt | 4 +- ...adFirstPartOfCurrentResourceIntoMemory.cpp | 40 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 src/OpenSHC/IO/ResourceManager/readFirstPartOfCurrentResourceIntoMemory.cpp diff --git a/cmake/compiler-flags-gl.txt b/cmake/compiler-flags-gl.txt index 79e35428..596c89eb 100644 --- a/cmake/compiler-flags-gl.txt +++ b/cmake/compiler-flags-gl.txt @@ -1,6 +1,8 @@ src/OpenSHC/IO/LowLevelMemory/copyData.cpp -src/OpenSHC/IO/LowLevelMemory/fillMemory_ByteValue.cpp +src/OpenSHC/IO/LowLevelMemory/fillMemory.cpp +src/OpenSHC/IO/LowLevelMemory/putFileNameAndAppendFileExtension.cpp src/OpenSHC/IO/DecoderState/encodeData.cpp src/OpenSHC/IO/DecoderState/decodeData.cpp src/OpenSHC/IO/ResourceManager/swapMapDataWithNextMap.cpp src/OpenSHC/UI/Rendering/WindowAndDirectDraw/takeScreenshot.cpp +src/OpenSHC/IO/ResourceManager/readFirstPartOfCurrentResourceIntoMemory.cpp diff --git a/src/OpenSHC/IO/ResourceManager/readFirstPartOfCurrentResourceIntoMemory.cpp b/src/OpenSHC/IO/ResourceManager/readFirstPartOfCurrentResourceIntoMemory.cpp new file mode 100644 index 00000000..f4e15f84 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/readFirstPartOfCurrentResourceIntoMemory.cpp @@ -0,0 +1,40 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/OS.func.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x00471F10 + BOOLEnum ResourceManager::readFirstPartOfCurrentResourceIntoMemory( + void* destination, int partSize, char* fileExtension) + { + // Why do these not use the complete size? Or it the array not 1001 bytes? But what about the instructions that + // basically use this number? + MACRO_CALL_MEMBER(LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 1000, '\0', this->resourceFileNameArray[0]); + MACRO_CALL_MEMBER(LowLevelMemory_Func::putFileNameAndAppendFileExtension, DAT_LowLevelMemory::ptr)( + this->resourceFileNameArray[this->currentActiveResourceType], this->resourceFileNameArray[0], + fileExtension); + + FileResourceTypeInt tempActiveResource = this->currentActiveResourceType; + this->currentActiveResourceType = NULL; + + char* _Filename = MACRO_CALL_MEMBER(ResourceManager_Func::getFileNameOfCurrentActiveResource, this)(); + this->fileHandle = MACRO_CALL(OS_Func::_ucrt_open)(_Filename, _O_BINARY, 0); + + this->currentActiveResourceType = tempActiveResource; + + if (this->fileHandle == -1) { + return FALSE; + } + this->loadPositionInCurrentResource = MACRO_CALL(OS_Func::_ucrt_read)(this->fileHandle, destination, partSize); + MACRO_CALL(OS_Func::_ucrt_close)(this->fileHandle); + return TRUE; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c4bcf953..3136b434 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -21353,7 +21353,7 @@ SHC_3BB0A8C1_0x00471E50 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00471EB0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00471F10 | 0.0% | Pending +SHC_3BB0A8C1_0x00471F10 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00471FC0 | 0.0% | Pending From 1d97fa329a2a189fa3a9f2e27d6f49e9f5f49fad Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 20:16:41 +0200 Subject: [PATCH 21/37] reimplement: SHC_3BB0A8C1_0x00471FC0 100% --- cmake/compiler-flags-gl.txt | 1 + ...eadNextPartOfCurrentResourceIntoMemory.cpp | 39 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 4 +- 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 src/OpenSHC/IO/ResourceManager/readNextPartOfCurrentResourceIntoMemory.cpp diff --git a/cmake/compiler-flags-gl.txt b/cmake/compiler-flags-gl.txt index 596c89eb..848d70de 100644 --- a/cmake/compiler-flags-gl.txt +++ b/cmake/compiler-flags-gl.txt @@ -6,3 +6,4 @@ src/OpenSHC/IO/DecoderState/decodeData.cpp src/OpenSHC/IO/ResourceManager/swapMapDataWithNextMap.cpp src/OpenSHC/UI/Rendering/WindowAndDirectDraw/takeScreenshot.cpp src/OpenSHC/IO/ResourceManager/readFirstPartOfCurrentResourceIntoMemory.cpp +src/OpenSHC/IO/ResourceManager/readNextPartOfCurrentResourceIntoMemory.cpp diff --git a/src/OpenSHC/IO/ResourceManager/readNextPartOfCurrentResourceIntoMemory.cpp b/src/OpenSHC/IO/ResourceManager/readNextPartOfCurrentResourceIntoMemory.cpp new file mode 100644 index 00000000..92e14353 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/readNextPartOfCurrentResourceIntoMemory.cpp @@ -0,0 +1,39 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/OS.func.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x00471FC0 + BOOLEnum ResourceManager::readNextPartOfCurrentResourceIntoMemory( + void* destination, int partSize, char* fileExtension) + { + MACRO_CALL_MEMBER(LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 1000, '\0', this->resourceFileNameArray[0]); + MACRO_CALL_MEMBER(LowLevelMemory_Func::putFileNameAndAppendFileExtension, DAT_LowLevelMemory::ptr)( + this->resourceFileNameArray[this->currentActiveResourceType], this->resourceFileNameArray[0], + fileExtension); + + FileResourceTypeInt tempActiveResource = this->currentActiveResourceType; + this->currentActiveResourceType = NULL; + + char* _Filename = MACRO_CALL_MEMBER(ResourceManager_Func::getFileNameOfCurrentActiveResource, this)(); + this->fileHandle = MACRO_CALL(OS_Func::_ucrt_open)(_Filename, _O_BINARY, 0); + + this->currentActiveResourceType = tempActiveResource; + + if (this->fileHandle == -1) { + return FALSE; + } + MACRO_CALL(OS_Func::_ucrt_lseek)(this->fileHandle, this->loadPositionInCurrentResource, FILE_BEGIN); + this->loadPositionInCurrentResource += MACRO_CALL(OS_Func::_ucrt_read)(this->fileHandle, destination, partSize); + MACRO_CALL(OS_Func::_ucrt_close)(this->fileHandle); + return TRUE; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 3136b434..2af32ae4 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -21353,9 +21353,9 @@ SHC_3BB0A8C1_0x00471E50 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00471EB0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00471F10 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00471F10 | 100.0% | Reimplemented, needs LowLevelMemory functions active -SHC_3BB0A8C1_0x00471FC0 | 0.0% | Pending +SHC_3BB0A8C1_0x00471FC0 | 100.0% | Reimplemented, needs LowLevelMemory functions active SHC_3BB0A8C1_0x00472080 | 0.0% | Pending From cabd478732463677e6f3dba39c73a0fe1ecb81c7 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 20:26:28 +0200 Subject: [PATCH 22/37] reimplement: SHC_3BB0A8C1_0x00472080 100% --- .../ResourceManager/showOpenGfxFileDialog.cpp | 22 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/showOpenGfxFileDialog.cpp diff --git a/src/OpenSHC/IO/ResourceManager/showOpenGfxFileDialog.cpp b/src/OpenSHC/IO/ResourceManager/showOpenGfxFileDialog.cpp new file mode 100644 index 00000000..0f677b5a --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/showOpenGfxFileDialog.cpp @@ -0,0 +1,22 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/Input/MouseState.func.hpp" +#include "OpenSHC/string-literals.hpp" + +#include "OpenSHC/Globals/DAT_MouseState.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x00472080 + BOOLEnum ResourceManager::showOpenGfxFileDialog() + { + MACRO_CALL_MEMBER(ResourceManager_Func::resetOpenFileNameStruct, this)(); + MACRO_CALL_MEMBER(ResourceManager_Func::setGfxFileFilter, this)(); + this->openFileNameA.lpstrTitle = s_Select_TGX_file_to_import_005a6268; + MACRO_CALL_MEMBER(OpenSHC::Input::MouseState_Func::resetMouseState2, DAT_MouseState::ptr)(); + return GetOpenFileNameA((LPOPENFILENAMEA) & this->openFileNameA) != NULL; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 2af32ae4..842c2ff2 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -21357,7 +21357,7 @@ SHC_3BB0A8C1_0x00471F10 | 100.0% | Reimplemented, needs LowLevelMemory functions SHC_3BB0A8C1_0x00471FC0 | 100.0% | Reimplemented, needs LowLevelMemory functions active -SHC_3BB0A8C1_0x00472080 | 0.0% | Pending +SHC_3BB0A8C1_0x00472080 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004720C0 | 0.0% | Pending From 7b9269990f174b19646ea13261aed0594510a06a Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 21:02:07 +0200 Subject: [PATCH 23/37] reimplement: SHC_3BB0A8C1_0x004720C0 100% --- .../showOpenHelpFileDialog.cpp | 21 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/showOpenHelpFileDialog.cpp diff --git a/src/OpenSHC/IO/ResourceManager/showOpenHelpFileDialog.cpp b/src/OpenSHC/IO/ResourceManager/showOpenHelpFileDialog.cpp new file mode 100644 index 00000000..7fef007a --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/showOpenHelpFileDialog.cpp @@ -0,0 +1,21 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/Input/MouseState.func.hpp" + +#include "OpenSHC/Globals/DAT_MouseState.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x004720C0 + BOOLEnum ResourceManager::showOpenHelpFileDialog(LPCSTR param_1) + { + MACRO_CALL_MEMBER(ResourceManager_Func::resetOpenFileNameStruct, this)(); + MACRO_CALL_MEMBER(ResourceManager_Func::setHelpFileFilter, this)(); + this->openFileNameA.lpstrTitle = param_1; + MACRO_CALL_MEMBER(Input::MouseState_Func::resetMouseState2, DAT_MouseState::ptr)(); + return GetOpenFileNameA((LPOPENFILENAMEA) & this->openFileNameA) != NULL; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 842c2ff2..d147e08a 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -21359,7 +21359,7 @@ SHC_3BB0A8C1_0x00471FC0 | 100.0% | Reimplemented, needs LowLevelMemory functions SHC_3BB0A8C1_0x00472080 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004720C0 | 0.0% | Pending +SHC_3BB0A8C1_0x004720C0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00472100 | 0.0% | Pending From d726f50f425dff774167a85440ea788ac2c23475 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 21:06:10 +0200 Subject: [PATCH 24/37] reimplement: SHC_3BB0A8C1_0x00472100 100% --- .../showSaveHelpFileDialog.cpp | 22 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/showSaveHelpFileDialog.cpp diff --git a/src/OpenSHC/IO/ResourceManager/showSaveHelpFileDialog.cpp b/src/OpenSHC/IO/ResourceManager/showSaveHelpFileDialog.cpp new file mode 100644 index 00000000..08ddde65 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/showSaveHelpFileDialog.cpp @@ -0,0 +1,22 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/Input/MouseState.func.hpp" +#include "OpenSHC/string-literals.hpp" + +#include "OpenSHC/Globals/DAT_MouseState.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x00472100 + BOOLEnum ResourceManager::showSaveHelpFileDialog() + { + MACRO_CALL_MEMBER(OpenSHC::IO::ResourceManager_Func::resetOpenFileNameStruct, this)(); + MACRO_CALL_MEMBER(OpenSHC::IO::ResourceManager_Func::setHelpFileFilter, this)(); + this->openFileNameA.lpstrTitle = s_Select_help_file_to_save_005a6284; + MACRO_CALL_MEMBER(OpenSHC::Input::MouseState_Func::resetMouseState2, DAT_MouseState::ptr)(); + return GetSaveFileNameA((LPOPENFILENAMEA) & this->openFileNameA) != NULL; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index d147e08a..4ac30d47 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -21361,7 +21361,7 @@ SHC_3BB0A8C1_0x00472080 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004720C0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00472100 | 0.0% | Pending +SHC_3BB0A8C1_0x00472100 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00472140 | 0.0% | Pending From c34f3a0f43e0e6cbfa84619e08ed91e4afeeb63c Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 21:09:11 +0200 Subject: [PATCH 25/37] reimplement: SHC_3BB0A8C1_0x00472140 100% --- .../showOpenSoundFileDialog.cpp | 22 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/showOpenSoundFileDialog.cpp diff --git a/src/OpenSHC/IO/ResourceManager/showOpenSoundFileDialog.cpp b/src/OpenSHC/IO/ResourceManager/showOpenSoundFileDialog.cpp new file mode 100644 index 00000000..006e9d9b --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/showOpenSoundFileDialog.cpp @@ -0,0 +1,22 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/Input/MouseState.func.hpp" +#include "OpenSHC/string-literals.hpp" + +#include "OpenSHC/Globals/DAT_MouseState.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x00472140 + BOOLEnum ResourceManager::showOpenSoundFileDialog() + { + MACRO_CALL_MEMBER(ResourceManager_Func::resetOpenFileNameStruct, this)(); + MACRO_CALL_MEMBER(ResourceManager_Func::setSoundFileFilter, this)(); + this->openFileNameA.lpstrTitle = s_Select_sound_file_to_import_005a62a0; + MACRO_CALL_MEMBER(Input::MouseState_Func::resetMouseState2, DAT_MouseState::ptr)(); + return GetOpenFileNameA((LPOPENFILENAMEA) & this->openFileNameA) != NULL; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 4ac30d47..4260746a 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -21363,7 +21363,7 @@ SHC_3BB0A8C1_0x004720C0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00472100 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00472140 | 0.0% | Pending +SHC_3BB0A8C1_0x00472140 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00472180 | 0.0% | Pending From 2d3cd62f215b531c7cea50d0d879d6fe5f216cb3 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Sun, 16 Aug 2026 21:17:39 +0200 Subject: [PATCH 26/37] reimplement: SHC_3BB0A8C1_0x00472180 100% --- .../fileHashFunctionByteByByte.cpp | 33 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/fileHashFunctionByteByByte.cpp diff --git a/src/OpenSHC/IO/ResourceManager/fileHashFunctionByteByByte.cpp b/src/OpenSHC/IO/ResourceManager/fileHashFunctionByteByByte.cpp new file mode 100644 index 00000000..1436445d --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/fileHashFunctionByteByByte.cpp @@ -0,0 +1,33 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/OS.func.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x00472180 + int ResourceManager::fileHashFunctionByteByByte() + { + int _total = 0; + + char* _fileName = MACRO_CALL_MEMBER(ResourceManager_Func::getFileNameOfCurrentActiveResource, this)(); + int _fileHandle = MACRO_CALL(OS_Func::_ucrt_open)(_fileName, _O_BINARY, 0); + if (_fileHandle == -1) { + return -1; + } + + char _first1024chars[1024]; + int _numReadUnk; + do { + _numReadUnk = MACRO_CALL(OS_Func::_ucrt_read)(_fileHandle, _first1024chars, sizeof(_first1024chars)); + + for (int i = 0; i < _numReadUnk; ++i) { + _total += _first1024chars[i]; + } + } while (_numReadUnk != 0); + MACRO_CALL(OS_Func::_ucrt_close)(_fileHandle); + return _total; + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 4260746a..1ce9668f 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -21365,7 +21365,7 @@ SHC_3BB0A8C1_0x00472100 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00472140 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00472180 | 0.0% | Pending +SHC_3BB0A8C1_0x00472180 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004721D0 | 0.0% | Pending From 9f10697de4f99bbf25b9306c92b8024fc33ad88e Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Mon, 17 Aug 2026 12:42:53 +0200 Subject: [PATCH 27/37] reimplement: SHC_3BB0A8C1_0x00477710 and SHC_3BB0A8C1_0x004778E0 100% --- src/OpenSHC/IO/ResourceManager/paths.cpp | 63 ++++++++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 4 +- 2 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 src/OpenSHC/IO/ResourceManager/paths.cpp diff --git a/src/OpenSHC/IO/ResourceManager/paths.cpp b/src/OpenSHC/IO/ResourceManager/paths.cpp new file mode 100644 index 00000000..e06c25cd --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/paths.cpp @@ -0,0 +1,63 @@ +#include "../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" + +#include "shlobj.h" + +namespace OpenSHC { +namespace IO { + + // NOTE: "string_prependUserPathToString" can likely not be resolved, since the call is optimized and ignores proper + // call conventions in the game. Trying it does not make much sense also, since the strings interact with the + // allocator of the game, causing memory issues if hooked anyway. + + // FUNCTION: STRONGHOLDCRUSADER 0x00477710 + static bool string_prependUserPathToString(std::string& out, char const* path, int csidl) + { + if (DAT_ResourceManager::instance.configPathLoadedUnk_0x7da) { + std::string localStr(DAT_ResourceManager::instance.configPathUnk_0x7db); + out = localStr; + out.append(path); + } else { + // apparently, SHGetFolderPathW only returns a maximum of MAX_PATH, which is 260, so they overdid it + WCHAR pszPath[2000]; + if (SHGetFolderPathW(NULL, csidl | CSIDL_FLAG_CREATE, NULL, NULL, pszPath) < S_OK) { + return false; + } + + WCHAR _wideCharStr[2000]; + GetShortPathNameW(pszPath, _wideCharStr, sizeof(_wideCharStr) / sizeof(WCHAR)); + + CHAR _multiByteStr[2000]; + MACRO_CALL_MEMBER(Util::WideCharMultiByteState_Func::wideCharToMultiByteWithSize, + DAT_WideCharMultiByteState::ptr)(_multiByteStr, _wideCharStr, sizeof(_multiByteStr) - 1); + + out.append(_multiByteStr); + out.append(path); + } + if (GetFileAttributesA(out.c_str()) == INVALID_FILE_ATTRIBUTES && !CreateDirectoryA(out.c_str(), NULL)) { + return false; + } + return true; + } + + // FUNCTION: STRONGHOLDCRUSADER 0x004778E0 + std::string ResourceManager::paths_getDocumentsFolderString(bool param_2) + { + std::string suffix(s__Stronghold_Crusader__005a6434); + std::string userPath; + string_prependUserPathToString(userPath, suffix.c_str(), CSIDL_PERSONAL); + if (param_2) { + return userPath; + } else { + return suffix; + } + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 1ce9668f..c0d5a779 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -22009,9 +22009,9 @@ SHC_3BB0A8C1_0x00477670 | 0.0% | Pending SHC_3BB0A8C1_0x00477690 | 0.0% | Pending -SHC_3BB0A8C1_0x00477710 | 0.0% | Pending +SHC_3BB0A8C1_0x00477710 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004778E0 | 0.0% | Pending +SHC_3BB0A8C1_0x004778E0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004779F0 | 0.0% | Pending From 8aaa352d63a82ed0c2fedabef5bdbdadfcb39091 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Mon, 17 Aug 2026 14:43:01 +0200 Subject: [PATCH 28/37] reimplement: SHC_3BB0A8C1_0x004779F0 100% --- IMPLEMENTATION_CHEAT_SHEET.md | 24 ++++++++++++++++++++++++ src/OpenSHC/IO/ResourceManager/paths.cpp | 16 ++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 4 ++-- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/IMPLEMENTATION_CHEAT_SHEET.md b/IMPLEMENTATION_CHEAT_SHEET.md index f2b6b98b..4ca91e1d 100644 --- a/IMPLEMENTATION_CHEAT_SHEET.md +++ b/IMPLEMENTATION_CHEAT_SHEET.md @@ -291,3 +291,27 @@ A prominent example are `malloc` and `free`, where it is simply needed to use th since the memory management in the std library is rather complex. For other std functions, mostly the math functions, we decided to just use the std library directly. + +### Copy Elision and Return Value Optimization + +The compiler may use copy elision and return value optimization. + +The return value optimization may appear if a function returns an object, but instead of putting the whole object on the stack, the function receives a hidden pointer to memory from the caller. This memory is then initialized and the pointer to it is also return. +The actual function signature will only have the object as value return. + +Example in Ghidra: +```cpp +std::string* paths_getDocumentsFolderString(std::string* out, bool param_2); +``` + +Actual signature: +```cpp +std::string paths_getDocumentsFolderString(bool param_2); +``` + +This structure can be reproduced. However, this can not be said about the resulting Copy Elision. +If the value is assigned to another object, the compiler tries to avoid creating a copy. + +**This only works if the function is called directly. Any form of indirection via pointer or resolver will not optimize. This is a fundamental limitation of the MSVC2005 compiler.** + +As a result, such cases do not use the resolver. The limitation through this is accepted, although, it should be noted in the status entry for the caller. diff --git a/src/OpenSHC/IO/ResourceManager/paths.cpp b/src/OpenSHC/IO/ResourceManager/paths.cpp index e06c25cd..f233c226 100644 --- a/src/OpenSHC/IO/ResourceManager/paths.cpp +++ b/src/OpenSHC/IO/ResourceManager/paths.cpp @@ -59,5 +59,21 @@ namespace IO { } } + // Return Value Optimization is not compatible with the resolver, therefore, the call needs to be direct. + + // FUNCTION: STRONGHOLDCRUSADER 0x004779F0 + std::string ResourceManager::paths_getSavesPath(bool param_2) + { + std::string suffix(this->paths_getDocumentsFolderString(false)); + suffix.append(s_Saves__005a644c); + std::string userPath; + string_prependUserPathToString(userPath, suffix.c_str(), CSIDL_PERSONAL); + if (param_2) { + return userPath; + } else { + return suffix; + } + } + } // namespace IO } // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c0d5a779..b6b567c1 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -22009,11 +22009,11 @@ SHC_3BB0A8C1_0x00477670 | 0.0% | Pending SHC_3BB0A8C1_0x00477690 | 0.0% | Pending -SHC_3BB0A8C1_0x00477710 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00477710 | 100.0% | Reimplemented; static helper, not resolver due to optimized call convention SHC_3BB0A8C1_0x004778E0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004779F0 | 0.0% | Pending +SHC_3BB0A8C1_0x004779F0 | 100.0% | Reimplemented; Return value optimization, always needs SHC_3BB0A8C1_0x004778E0 active SHC_3BB0A8C1_0x00477B00 | 0.0% | Pending From 794edf6248073bc594d5aa2e7756452609b8cf33 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Mon, 17 Aug 2026 14:48:22 +0200 Subject: [PATCH 29/37] reimplement: SHC_3BB0A8C1_0x00477B00 100% --- src/OpenSHC/IO/ResourceManager/paths.cpp | 14 ++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/OpenSHC/IO/ResourceManager/paths.cpp b/src/OpenSHC/IO/ResourceManager/paths.cpp index f233c226..6b6604af 100644 --- a/src/OpenSHC/IO/ResourceManager/paths.cpp +++ b/src/OpenSHC/IO/ResourceManager/paths.cpp @@ -75,5 +75,19 @@ namespace IO { } } + // FUNCTION: STRONGHOLDCRUSADER 0x00477B00 + std::string ResourceManager::paths_getDocumentsMapsFolderString(bool prependUserPath) + { + std::string suffix(this->paths_getDocumentsFolderString(false)); + suffix.append(s_Maps__005a6454); + std::string userPath; + string_prependUserPathToString(userPath, suffix.c_str(), CSIDL_PERSONAL); + if (prependUserPath) { + return userPath; + } else { + return suffix; + } + } + } // namespace IO } // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index b6b567c1..5a751609 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -22015,7 +22015,7 @@ SHC_3BB0A8C1_0x004778E0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004779F0 | 100.0% | Reimplemented; Return value optimization, always needs SHC_3BB0A8C1_0x004778E0 active -SHC_3BB0A8C1_0x00477B00 | 0.0% | Pending +SHC_3BB0A8C1_0x00477B00 | 100.0% | Reimplemented; Return value optimization, always needs SHC_3BB0A8C1_0x004778E0 active SHC_3BB0A8C1_0x00477C10 | 0.0% | Pending From d8193f351adb3ea1acbac1c14f0cad76e727f840 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Mon, 17 Aug 2026 21:06:35 +0200 Subject: [PATCH 30/37] reimplement: SHC_3BB0A8C1_0x00477EE0 still issues --- .../IO/ResourceManager/discoverMapFiles.cpp | 204 ++++++++++++++++++ src/OpenSHC/OS/OS.cpp | 5 +- 2 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/discoverMapFiles.cpp diff --git a/src/OpenSHC/IO/ResourceManager/discoverMapFiles.cpp b/src/OpenSHC/IO/ResourceManager/discoverMapFiles.cpp new file mode 100644 index 00000000..33d32f0c --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/discoverMapFiles.cpp @@ -0,0 +1,204 @@ +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/Global.func.hpp" +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/OS.func.hpp" +#include "OpenSHC/string-literals.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" + +namespace OpenSHC { +namespace IO { + + // helper copied from the std lib + typedef union { + unsigned long long ft_scalar; + FILETIME ft_struct; + } FILETIME_UNION; + + // FUNCTION: STRONGHOLDCRUSADER 0x00477EE0 + void ResourceManager::discoverMapFiles(char* param_1) + { + // TODO: are these really set here, or is it part of the loops down there? + BOOLEnum _hasSwapped = TRUE; + int _mapIndex = 0; + + FILETIME_UNION filetimeBias; + filetimeBias.ft_scalar = 0; + + BOOLEnum _missionMaps = FALSE; + BOOLEnum _originalMaps = FALSE; + int local_22c = 0; + + if (!MACRO_CALL(OS_Func::__stricmp)(param_1, s_maps_map_005a64b0)) { + _missionMaps = TRUE; + _originalMaps = TRUE; + } + if (!MACRO_CALL(OS_Func::__stricmp)(param_1, s_mapsExtreme_map_005a649c)) { + _missionMaps = TRUE; + _originalMaps = TRUE; + } + + // the whole time part appears like something that should be part of the std libray, but I found nothing + // FIXME?: According to the chatbot I used, this seems to lack proper handling for the general bias + + _TIME_ZONE_INFORMATION timeZoneInformation; + DWORD timeZoneResult = GetTimeZoneInformation(&timeZoneInformation); + if (timeZoneResult == TIME_ZONE_ID_STANDARD) { + filetimeBias.ft_scalar = -timeZoneInformation.StandardBias; + } else if (timeZoneResult == TIME_ZONE_ID_DAYLIGHT) { + filetimeBias.ft_scalar = -timeZoneInformation.DaylightBias; + } + filetimeBias.ft_scalar *= 600000000; // transform into filetime ticks + + this->mapFileCounter = 0; + MACRO_CALL_MEMBER(LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 500000, 0, this->loadedMapNames); + + WIN32_FIND_DATAA _win32FindData; + HANDLE _handle = FindFirstFileA(param_1, &_win32FindData); + if (_handle == INVALID_HANDLE_VALUE) { + return; + } + + while (this->mapFileCounter < 500) { + MACRO_CALL_MEMBER(LowLevelMemory_Func::copyStringUntilFirstDot, DAT_LowLevelMemory::ptr)( + _win32FindData.cFileName, this->loadedMapNames[this->mapFileCounter]); + + FILETIME_UNION currentFileTime; + currentFileTime.ft_struct = _win32FindData.ftLastWriteTime; + currentFileTime.ft_scalar += filetimeBias.ft_scalar; + + WORD fatDate; + WORD fatTime; + FileTimeToDosDateTime(¤tFileTime.ft_struct, &fatDate, &fatTime); + + // this might indicate that they used a struct here to handle the time + // although other usages use it like a number + this->mapFileTimes[this->mapFileCounter] = fatDate << 16 | fatTime; + + // since all strings are of type ptr, I can not get the length of the string during runtime via sizeof + // "magic numbers" here consider the length of "mission" and in relation to that + + if (_missionMaps + && !MACRO_CALL(OS_Func::__strnicmp)(this->loadedMapNames[this->mapFileCounter], s_mission_005a6494, 7) + && this->loadedMapNames[this->mapFileCounter][7] >= '0' + && this->loadedMapNames[this->mapFileCounter][7] <= '9') { + + // TODO still issues, logic discards certain maps if it is a mission map, but the current logic does not + // properly reproduce the binary. Also, other issues in the function + + bool discard = true; + + if (this->loadedMapNames[this->mapFileCounter][7] == '1') { + if (this->loadedMapNames[this->mapFileCounter][8] < '0' + || this->loadedMapNames[this->mapFileCounter][8] > '9' + || this->loadedMapNames[this->mapFileCounter][9] != '\0') { + if (this->loadedMapNames[this->mapFileCounter][8] != '\0') { + discard = false; + } + } + } else if (this->loadedMapNames[this->mapFileCounter][7] == '2') { + if (this->loadedMapNames[this->mapFileCounter][8] < '0' + || this->loadedMapNames[this->mapFileCounter][8] > '1' + || this->loadedMapNames[this->mapFileCounter][9] != '\0') { + if (this->loadedMapNames[this->mapFileCounter][8] != '\0') { + discard = false; + } + } + } else if (this->loadedMapNames[this->mapFileCounter][7] == '3') { + if (this->loadedMapNames[this->mapFileCounter][8] < '3' + || this->loadedMapNames[this->mapFileCounter][8] > '7' + || this->loadedMapNames[this->mapFileCounter][9] != '\0') { + if (this->loadedMapNames[this->mapFileCounter][8] != '\0') { + discard = false; + } + } + } else { + if (this->loadedMapNames[this->mapFileCounter][8] != '\0') { + discard = false; + } + } + + if (discard) { + MACRO_CALL_MEMBER(LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 1000, '\0', this->loadedMapNames[this->mapFileCounter]); + --this->mapFileCounter; + } + } + + ++this->mapFileCounter; + if (FindNextFileA(_handle, &_win32FindData) == 0) { + if (!_originalMaps) { + break; + } + if (local_22c != 0) { + break; + } + local_22c = 1; + + // required, otherwise copy elision will not work + std::string path(this->paths_getDocumentsMapsFolderString(TRUE)); + path.append(s__map_005a648c); + + // does this truly overwrite? + _handle = FindFirstFileA(path.c_str(), &_win32FindData); + if (_handle == INVALID_HANDLE_VALUE) { + break; + } + } + } + + if (_originalMaps) { + do { + ++_mapIndex; + if (!_hasSwapped) { + break; + } + _hasSwapped = FALSE; + for (int _currentMapIndex = 0; _currentMapIndex < this->mapFileCounter - _mapIndex; + ++_currentMapIndex) { + if (this->loadedMapNames[_currentMapIndex][0] == '\0' + || this->loadedMapNames[_currentMapIndex + 1][0] == '\0') { + break; + } + + char* _Str2 = MACRO_CALL(Global_Func::GetStringBasedOnHardcodedMaps)( + this->loadedMapNames[_currentMapIndex + 1], &local_22c); + char* _Str1 = MACRO_CALL(Global_Func::GetStringBasedOnHardcodedMaps)( + this->loadedMapNames[_currentMapIndex], &_missionMaps); + if (MACRO_CALL(OS_Func::__stricmp)(_Str1, _Str2) > 0) { + MACRO_CALL_MEMBER(ResourceManager_Func::swapMapDataWithNextMap, this)(_currentMapIndex); + _hasSwapped = TRUE; + } + } + } while (_mapIndex < 500); + } else { + do { + ++_mapIndex; + if (!_hasSwapped) { + break; + } + _hasSwapped = FALSE; + + for (int _currentMapIndex = 0; _currentMapIndex < this->mapFileCounter - _mapIndex; + ++_currentMapIndex) { + if (this->loadedMapNames[_currentMapIndex][0] == '\0' + || this->loadedMapNames[_currentMapIndex + 1][0] == '\0') { + break; + } + + if (MACRO_CALL(OS_Func::__stricmp)( + this->loadedMapNames[_currentMapIndex], this->loadedMapNames[_currentMapIndex + 1]) + > 0) { + MACRO_CALL_MEMBER(ResourceManager_Func::swapMapDataWithNextMap, this)(_currentMapIndex); + _hasSwapped = TRUE; + } + } + } while (_mapIndex < 500); + } + FindClose(_handle); + } + +} // namespace IO +} // namespace OpenSHC diff --git a/src/OpenSHC/OS/OS.cpp b/src/OpenSHC/OS/OS.cpp index 91d77adc..1200943c 100644 --- a/src/OpenSHC/OS/OS.cpp +++ b/src/OpenSHC/OS/OS.cpp @@ -138,7 +138,10 @@ namespace OS { } // STUB: STRONGHOLDCRUSADER 0x005835BB - int __strnicmp(char* _Str1, char* _Str2, size_t _MaxCount) { return _strnicmp(_Str1, _Str2, _MaxCount); } + int __strnicmp(char const* _Str1, char const* _Str2, size_t _MaxCount) + { + return _strnicmp(_Str1, _Str2, _MaxCount); + } // STUB: STRONGHOLDCRUSADER 0x00583D55 void _exit(int _Code) { exit(_Code); } From 9a778b4f5e5916b39b201ed743228b1826a7194c Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Tue, 18 Aug 2026 23:36:27 +0200 Subject: [PATCH 31/37] reimplement: SHC_3BB0A8C1_0x00477EE0 86.0% --- .../IO/ResourceManager/discoverMapFiles.cpp | 83 +++++++++---------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 41 insertions(+), 44 deletions(-) diff --git a/src/OpenSHC/IO/ResourceManager/discoverMapFiles.cpp b/src/OpenSHC/IO/ResourceManager/discoverMapFiles.cpp index 33d32f0c..cad31f21 100644 --- a/src/OpenSHC/IO/ResourceManager/discoverMapFiles.cpp +++ b/src/OpenSHC/IO/ResourceManager/discoverMapFiles.cpp @@ -19,7 +19,6 @@ namespace IO { // FUNCTION: STRONGHOLDCRUSADER 0x00477EE0 void ResourceManager::discoverMapFiles(char* param_1) { - // TODO: are these really set here, or is it part of the loops down there? BOOLEnum _hasSwapped = TRUE; int _mapIndex = 0; @@ -55,8 +54,10 @@ namespace IO { MACRO_CALL_MEMBER(LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( 500000, 0, this->loadedMapNames); + HANDLE _handle; + WIN32_FIND_DATAA _win32FindData; - HANDLE _handle = FindFirstFileA(param_1, &_win32FindData); + _handle = FindFirstFileA(param_1, &_win32FindData); if (_handle == INVALID_HANDLE_VALUE) { return; } @@ -65,17 +66,19 @@ namespace IO { MACRO_CALL_MEMBER(LowLevelMemory_Func::copyStringUntilFirstDot, DAT_LowLevelMemory::ptr)( _win32FindData.cFileName, this->loadedMapNames[this->mapFileCounter]); - FILETIME_UNION currentFileTime; - currentFileTime.ft_struct = _win32FindData.ftLastWriteTime; - currentFileTime.ft_scalar += filetimeBias.ft_scalar; + { + FILETIME_UNION currentFileTime; + currentFileTime.ft_struct = _win32FindData.ftLastWriteTime; + currentFileTime.ft_scalar += filetimeBias.ft_scalar; - WORD fatDate; - WORD fatTime; - FileTimeToDosDateTime(¤tFileTime.ft_struct, &fatDate, &fatTime); + WORD fatDate; + WORD fatTime; + FileTimeToDosDateTime(¤tFileTime.ft_struct, &fatDate, &fatTime); - // this might indicate that they used a struct here to handle the time - // although other usages use it like a number - this->mapFileTimes[this->mapFileCounter] = fatDate << 16 | fatTime; + // this might indicate that they used a struct here to handle the time + // although other usages use it like a number + this->mapFileTimes[this->mapFileCounter] = (fatDate << 16) + fatTime; + } // since all strings are of type ptr, I can not get the length of the string during runtime via sizeof // "magic numbers" here consider the length of "mission" and in relation to that @@ -85,17 +88,12 @@ namespace IO { && this->loadedMapNames[this->mapFileCounter][7] >= '0' && this->loadedMapNames[this->mapFileCounter][7] <= '9') { - // TODO still issues, logic discards certain maps if it is a mission map, but the current logic does not - // properly reproduce the binary. Also, other issues in the function - - bool discard = true; - if (this->loadedMapNames[this->mapFileCounter][7] == '1') { if (this->loadedMapNames[this->mapFileCounter][8] < '0' || this->loadedMapNames[this->mapFileCounter][8] > '9' || this->loadedMapNames[this->mapFileCounter][9] != '\0') { if (this->loadedMapNames[this->mapFileCounter][8] != '\0') { - discard = false; + goto keepMap; } } } else if (this->loadedMapNames[this->mapFileCounter][7] == '2') { @@ -103,7 +101,7 @@ namespace IO { || this->loadedMapNames[this->mapFileCounter][8] > '1' || this->loadedMapNames[this->mapFileCounter][9] != '\0') { if (this->loadedMapNames[this->mapFileCounter][8] != '\0') { - discard = false; + goto keepMap; } } } else if (this->loadedMapNames[this->mapFileCounter][7] == '3') { @@ -111,41 +109,39 @@ namespace IO { || this->loadedMapNames[this->mapFileCounter][8] > '7' || this->loadedMapNames[this->mapFileCounter][9] != '\0') { if (this->loadedMapNames[this->mapFileCounter][8] != '\0') { - discard = false; + goto keepMap; } } } else { if (this->loadedMapNames[this->mapFileCounter][8] != '\0') { - discard = false; + goto keepMap; } } - if (discard) { - MACRO_CALL_MEMBER(LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( - 1000, '\0', this->loadedMapNames[this->mapFileCounter]); - --this->mapFileCounter; - } + MACRO_CALL_MEMBER(LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 1000, '\0', this->loadedMapNames[this->mapFileCounter]); + --this->mapFileCounter; + + keepMap:; // best matching solution so far } ++this->mapFileCounter; - if (FindNextFileA(_handle, &_win32FindData) == 0) { - if (!_originalMaps) { - break; - } - if (local_22c != 0) { - break; - } - local_22c = 1; + if (FindNextFileA(_handle, &_win32FindData)) { + continue; + } + if (!_originalMaps || local_22c) { + break; + } + local_22c = 1; - // required, otherwise copy elision will not work - std::string path(this->paths_getDocumentsMapsFolderString(TRUE)); - path.append(s__map_005a648c); + // required, otherwise copy elision will not work + std::string path(this->paths_getDocumentsMapsFolderString(TRUE)); + path.append(s__map_005a648c); - // does this truly overwrite? - _handle = FindFirstFileA(path.c_str(), &_win32FindData); - if (_handle == INVALID_HANDLE_VALUE) { - break; - } + // does this truly overwrite? + _handle = FindFirstFileA(path.c_str(), &_win32FindData); + if (_handle == INVALID_HANDLE_VALUE) { + break; } } @@ -163,10 +159,11 @@ namespace IO { break; } + int receiver; char* _Str2 = MACRO_CALL(Global_Func::GetStringBasedOnHardcodedMaps)( - this->loadedMapNames[_currentMapIndex + 1], &local_22c); + this->loadedMapNames[_currentMapIndex + 1], &receiver); char* _Str1 = MACRO_CALL(Global_Func::GetStringBasedOnHardcodedMaps)( - this->loadedMapNames[_currentMapIndex], &_missionMaps); + this->loadedMapNames[_currentMapIndex], &receiver); if (MACRO_CALL(OS_Func::__stricmp)(_Str1, _Str2) > 0) { MACRO_CALL_MEMBER(ResourceManager_Func::swapMapDataWithNextMap, this)(_currentMapIndex); _hasSwapped = TRUE; diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 5a751609..794b6f6f 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -22033,7 +22033,7 @@ SHC_3BB0A8C1_0x00477EA0 | 0.0% | Pending SHC_3BB0A8C1_0x00477EC0 | 0.0% | Pending -SHC_3BB0A8C1_0x00477EE0 | 0.0% | Pending +SHC_3BB0A8C1_0x00477EE0 | 86.0% | Reimplemented, heavy stack reorder mismatch, logic should be sound; Return value optimization, always needs SHC_3BB0A8C1_0x00477B00 active SHC_3BB0A8C1_0x00478010 | 0.0% | Pending From 4b35d8a6d2d9be52374409dc5e7e3e81d18dfd5e Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Wed, 19 Aug 2026 00:44:11 +0200 Subject: [PATCH 32/37] reimplement: SHC_3BB0A8C1_0x00478C60 100% --- src/OpenSHC/IO/ResourceManager/mapNames.cpp | 33 ++++++++++++++++++++- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/IO/ResourceManager/mapNames.cpp b/src/OpenSHC/IO/ResourceManager/mapNames.cpp index 4bf74782..ad504e6d 100644 --- a/src/OpenSHC/IO/ResourceManager/mapNames.cpp +++ b/src/OpenSHC/IO/ResourceManager/mapNames.cpp @@ -1,8 +1,15 @@ -// disable deprecation warnings for strcpy +// disable deprecation warnings for strcpy and strcat #pragma warning(disable : 4996) #include "../ResourceManager.func.hpp" +#include "OpenSHC/IO/FilePackager.func.hpp" +#include "OpenSHC/string-literals.hpp" + +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_ResourceManager.hpp" +#include "OpenSHC/Globals/FilePackagerObj.hpp" + namespace OpenSHC { namespace IO { @@ -25,5 +32,29 @@ namespace IO { } } + // FUNCTION: STRONGHOLDCRUSADER 0x00478C60 + void ResourceManager::mapNames_filterMapsIfMapLock() + { + int const currentFileNumber = DAT_ResourceManager::instance.mapFileCounter; + + int id2 = 0; + for (int id1 = 0; id1 < currentFileNumber; ++id1) { + char* mapName = MACRO_CALL_MEMBER( + ResourceManager_Func::mapNames_getLoadedMapNameForIndex, DAT_ResourceManager::ptr)(id1); + + char local_3f0[1008]; + strcpy(local_3f0, mapName); + strcat(local_3f0, s__map_005a2294); + MACRO_CALL_MEMBER(ResourceManager_Func::resolveResourceFileName, this)(FRT_MAPS, local_3f0); + MACRO_CALL_MEMBER(FilePackager_Func::readMapHeader, FilePackagerObj::ptr)(FALSE); + if (DAT_GameCore::instance.savedMapLocked == Map::MLS_EDITABLE) { + MACRO_CALL_MEMBER(ResourceManager_Func::replaceMapNameWith, this)(id1, id2); + ++id2; + } else { + --DAT_ResourceManager::instance.mapFileCounter; + } + } + } + } // namespace IO } // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 794b6f6f..bc91d076 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -22095,7 +22095,7 @@ SHC_3BB0A8C1_0x00478AC0 | 0.0% | Pending SHC_3BB0A8C1_0x00478AE0 | 0.0% | Pending -SHC_3BB0A8C1_0x00478C60 | 0.0% | Pending +SHC_3BB0A8C1_0x00478C60 | 100.0% | Reimplemented, needs SHC_3BB0A8C1_0x0046C2E0 active SHC_3BB0A8C1_0x00478D30 | 0.0% | Pending From f83869a7bb181bf1673a19a4246a3075c2fdf33f Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Wed, 19 Aug 2026 20:42:20 +0200 Subject: [PATCH 33/37] reimplement: SHC_3BB0A8C1_0x00477EE0 add small fixme comment --- src/OpenSHC/IO/ResourceManager/discoverMapFiles.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/OpenSHC/IO/ResourceManager/discoverMapFiles.cpp b/src/OpenSHC/IO/ResourceManager/discoverMapFiles.cpp index cad31f21..52b9b180 100644 --- a/src/OpenSHC/IO/ResourceManager/discoverMapFiles.cpp +++ b/src/OpenSHC/IO/ResourceManager/discoverMapFiles.cpp @@ -138,6 +138,9 @@ namespace IO { std::string path(this->paths_getDocumentsMapsFolderString(TRUE)); path.append(s__map_005a648c); + // FIXME: Assuming it did not get lost in the recomp process, since the func does not perfectly match, then + // this is a resource leak here. The older handle does not get closed properly + // does this truly overwrite? _handle = FindFirstFileA(path.c_str(), &_win32FindData); if (_handle == INVALID_HANDLE_VALUE) { From 8847a9ee3789e11cd06933fd20b36a4954608ef4 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Wed, 19 Aug 2026 21:33:28 +0200 Subject: [PATCH 34/37] reimplement: SHC_3BB0A8C1_0x00478AE0 100% --- .../IO/ResourceManager/discoverMapFiles.cpp | 2 +- .../IO/ResourceManager/loadMapHeaders.cpp | 58 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 3 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 src/OpenSHC/IO/ResourceManager/loadMapHeaders.cpp diff --git a/src/OpenSHC/IO/ResourceManager/discoverMapFiles.cpp b/src/OpenSHC/IO/ResourceManager/discoverMapFiles.cpp index 52b9b180..74eae848 100644 --- a/src/OpenSHC/IO/ResourceManager/discoverMapFiles.cpp +++ b/src/OpenSHC/IO/ResourceManager/discoverMapFiles.cpp @@ -17,7 +17,7 @@ namespace IO { } FILETIME_UNION; // FUNCTION: STRONGHOLDCRUSADER 0x00477EE0 - void ResourceManager::discoverMapFiles(char* param_1) + void ResourceManager::discoverMapFiles(char const* param_1) { BOOLEnum _hasSwapped = TRUE; int _mapIndex = 0; diff --git a/src/OpenSHC/IO/ResourceManager/loadMapHeaders.cpp b/src/OpenSHC/IO/ResourceManager/loadMapHeaders.cpp new file mode 100644 index 00000000..c310a602 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/loadMapHeaders.cpp @@ -0,0 +1,58 @@ +// disable deprecation warnings for strcpy and strcat +#pragma warning(disable : 4996) + +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/IO/FilePackager.func.hpp" +#include "OpenSHC/UI/Rendering/TextureRenderCore.func.hpp" +#include "OpenSHC/string-literals.hpp" + +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_LoadingBarProgress.hpp" +#include "OpenSHC/Globals/DAT_MapPropertiesState.hpp" +#include "OpenSHC/Globals/DAT_ResourceManager.hpp" +#include "OpenSHC/Globals/DAT_TextureRenderCoreObject.hpp" +#include "OpenSHC/Globals/FilePackagerObj.hpp" + +namespace OpenSHC { +namespace IO { + + // FUNCTION: STRONGHOLDCRUSADER 0x00478AE0 + void ResourceManager::loadMapHeaders(BOOLEnum drawLoadingBar) + { + MACRO_CALL_MEMBER(ResourceManager_Func::discoverMapFiles, this)(s_maps_map_005a64b0); + this->loadedMapsCount = this->mapFileCounter; + + for (int mapIndex = 0; mapIndex < this->mapFileCounter; ++mapIndex) { + char* mapName = MACRO_CALL_MEMBER(ResourceManager_Func::mapNames_getLoadedMapNameForIndex, this)(mapIndex); + strcpy(this->mapNames[mapIndex], mapName); + + char resourceFileName[1008]; + strcpy(resourceFileName, mapName); + strcat(resourceFileName, s__map_005a2294); + MACRO_CALL_MEMBER(ResourceManager_Func::resolveResourceFileName, DAT_ResourceManager::ptr)( + FRT_MAPS, resourceFileName); + MACRO_CALL_MEMBER(FilePackager_Func::readMapHeader, FilePackagerObj::ptr)(FALSE); + + this->mapMetaInfoArray[mapIndex].loadedMapsChecksumArray + = MACRO_CALL_MEMBER(ResourceManager_Func::fileHashFunctionByteByByte, DAT_ResourceManager::ptr)(); + this->mapMetaInfoArray[mapIndex].mapType = DAT_GameCore::instance.mapType; + this->mapMetaInfoArray[mapIndex].mapLocked = DAT_GameCore::instance.savedMapLocked; + this->mapMetaInfoArray[mapIndex].mapBalance = DAT_GameCore::instance.savedMapBalance; + this->mapMetaInfoArray[mapIndex].mapEndInt2 = DAT_GameCore::instance.savedMapEndInt2; + this->mapMetaInfoArray[mapIndex].mapPlayerCount = DAT_GameCore::instance.mapPlayerCount; + this->mapMetaInfoArray[mapIndex].int0 = DAT_MapPropertiesState::instance.scenarionMissionType; + this->mapMetaInfoArray[mapIndex].mapType2 = DAT_MapPropertiesState::instance.scenarioMissionSiegeOrInvasion; + + int _progress = mapIndex * 100; + if (drawLoadingBar == TRUE) { + MACRO_CALL_MEMBER( + UI::Rendering::TextureRenderCore_Func::drawLoadingBarUnk, DAT_TextureRenderCoreObject::ptr)( + (Graphics::GmID)((_progress / this->mapFileCounter) + 80 + DAT_LoadingBarProgress::instance), + DAT_LoadingBarProgress::instance + 180); + } + } + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index bc91d076..73d8060e 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -22093,7 +22093,7 @@ SHC_3BB0A8C1_0x00478A50 | 0.0% | Pending SHC_3BB0A8C1_0x00478AC0 | 0.0% | Pending -SHC_3BB0A8C1_0x00478AE0 | 0.0% | Pending +SHC_3BB0A8C1_0x00478AE0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00478C60 | 100.0% | Reimplemented, needs SHC_3BB0A8C1_0x0046C2E0 active From e33dc2f4dd8723ed5491c5afb5d5186d25fdc6e9 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Thu, 20 Aug 2026 22:49:42 +0200 Subject: [PATCH 35/37] reimplement: SHC_3BB0A8C1_0x00478360 100%, but literals still in file --- .../resolveResourceFileName.cpp | 103 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/IO/ResourceManager/resolveResourceFileName.cpp diff --git a/src/OpenSHC/IO/ResourceManager/resolveResourceFileName.cpp b/src/OpenSHC/IO/ResourceManager/resolveResourceFileName.cpp new file mode 100644 index 00000000..63c67105 --- /dev/null +++ b/src/OpenSHC/IO/ResourceManager/resolveResourceFileName.cpp @@ -0,0 +1,103 @@ +// disable deprecation warnings for strcpy and strcat +#pragma warning(disable : 4996) + +#include "../ResourceManager.func.hpp" + +#include "OpenSHC/IO/FileResourceType.hpp" + +namespace OpenSHC { +namespace IO { + + // TODO: Decide how to deal with string literals that need to be split + + // FUNCTION: STRONGHOLDCRUSADER 0x00478360 + void ResourceManager::resolveResourceFileName(FileResourceType resourceType, char const* shortFileName) + { + this->currentActiveResourceType = resourceType; + switch (resourceType) { + case FRT_GM: + strcpy(this->resourceFileNameArray[resourceType], "gm\\"); + strcat(this->resourceFileNameArray[resourceType], shortFileName); + return; + + case FRT_SCENARIOS: + strcpy(this->resourceFileNameArray[resourceType], "scenarios\\"); + strcat(this->resourceFileNameArray[resourceType], shortFileName); + return; + + case FRT_GFX: + strcpy(this->resourceFileNameArray[resourceType], "gfx\\"); + strcat(this->resourceFileNameArray[resourceType], shortFileName); + return; + + case FRT_GFX8: + strcpy(this->resourceFileNameArray[resourceType], "gfx8\\"); + strcat(this->resourceFileNameArray[resourceType], shortFileName); + return; + + case FRT_CASTLES: + strcpy(this->resourceFileNameArray[resourceType], "castles\\"); + strcat(this->resourceFileNameArray[resourceType], shortFileName); + return; + + case FRT_UNKNOWN: { + // NOTE: Requires direct, non-resolved call due to copy elision. + std::string savePath(this->paths_getSavesPath(true)); + strcpy(this->resourceFileNameArray[resourceType], savePath.c_str()); + strcat(this->resourceFileNameArray[resourceType], shortFileName); + return; + } + + case FRT_HELP: + strcpy(this->resourceFileNameArray[resourceType], "help\\"); + strcat(this->resourceFileNameArray[resourceType], shortFileName); + return; + + case FRT_BINKS: + strcpy(this->resourceFileNameArray[resourceType], "binks\\"); + strcat(this->resourceFileNameArray[resourceType], shortFileName); + return; + + case FRT_FX: + strcpy(this->resourceFileNameArray[resourceType], "fx\\"); + strcat(this->resourceFileNameArray[resourceType], shortFileName); + return; + + case FRT_GFX_SPEECH: // FIXME: Wrong name? Should be FRT_FX_SPEECH, or not? + strcpy(this->resourceFileNameArray[resourceType], "fx\\speech\\"); + strcat(this->resourceFileNameArray[resourceType], shortFileName); + return; + + case FRT_MAPS: { + strcpy(this->resourceFileNameArray[resourceType], "maps\\"); + strcat(this->resourceFileNameArray[resourceType], shortFileName); + + if (MACRO_CALL_MEMBER(ResourceManager_Func::doesFileExist, this)( + this->resourceFileNameArray[resourceType])) { + return; + } + // NOTE: Requires direct, non-resolved calls due to copy elision. + std::string documentMapsFolder(this->paths_getDocumentsMapsFolderString(true)); + strcpy(this->resourceFileNameArray[resourceType], documentMapsFolder.c_str()); + strcat(this->resourceFileNameArray[resourceType], shortFileName); + return; + } + + case FRT_SCORES: + strcpy(this->resourceFileNameArray[resourceType], "scores\\"); + strcat(this->resourceFileNameArray[resourceType], shortFileName); + return; + + case FRT_BMP: + strcpy(this->resourceFileNameArray[resourceType], ""); + strcat(this->resourceFileNameArray[resourceType], shortFileName); + return; + + default: + strcpy(this->resourceFileNameArray[resourceType], shortFileName); + return; + } + } + +} // namespace IO +} // namespace OpenSHC diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 73d8060e..c00bd8f3 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -22037,7 +22037,7 @@ SHC_3BB0A8C1_0x00477EE0 | 86.0% | Reimplemented, heavy stack reorder mismatch, l SHC_3BB0A8C1_0x00478010 | 0.0% | Pending -SHC_3BB0A8C1_0x00478360 | 0.0% | Pending +SHC_3BB0A8C1_0x00478360 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00478500 | 0.0% | Pending From fb415bacb6a3e36c500f3cc925b6aa57df5c56cb Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Fri, 21 Aug 2026 23:10:44 +0200 Subject: [PATCH 36/37] reimplement: SHC_3BB0A8C1_0x00478360 now using macros --- .../resolveResourceFileName.cpp | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/OpenSHC/IO/ResourceManager/resolveResourceFileName.cpp b/src/OpenSHC/IO/ResourceManager/resolveResourceFileName.cpp index 63c67105..020fd73a 100644 --- a/src/OpenSHC/IO/ResourceManager/resolveResourceFileName.cpp +++ b/src/OpenSHC/IO/ResourceManager/resolveResourceFileName.cpp @@ -4,39 +4,38 @@ #include "../ResourceManager.func.hpp" #include "OpenSHC/IO/FileResourceType.hpp" +#include "OpenSHC/string-macros.hpp" namespace OpenSHC { namespace IO { - // TODO: Decide how to deal with string literals that need to be split - // FUNCTION: STRONGHOLDCRUSADER 0x00478360 void ResourceManager::resolveResourceFileName(FileResourceType resourceType, char const* shortFileName) { this->currentActiveResourceType = resourceType; switch (resourceType) { case FRT_GM: - strcpy(this->resourceFileNameArray[resourceType], "gm\\"); + strcpy(this->resourceFileNameArray[resourceType], S_GM); strcat(this->resourceFileNameArray[resourceType], shortFileName); return; case FRT_SCENARIOS: - strcpy(this->resourceFileNameArray[resourceType], "scenarios\\"); + strcpy(this->resourceFileNameArray[resourceType], S_SCENARIOS__005A64F4); strcat(this->resourceFileNameArray[resourceType], shortFileName); return; case FRT_GFX: - strcpy(this->resourceFileNameArray[resourceType], "gfx\\"); + strcpy(this->resourceFileNameArray[resourceType], S_GFX__005A5A1C); strcat(this->resourceFileNameArray[resourceType], shortFileName); return; case FRT_GFX8: - strcpy(this->resourceFileNameArray[resourceType], "gfx8\\"); + strcpy(this->resourceFileNameArray[resourceType], S_GFX8__005A64EC); strcat(this->resourceFileNameArray[resourceType], shortFileName); return; case FRT_CASTLES: - strcpy(this->resourceFileNameArray[resourceType], "castles\\"); + strcpy(this->resourceFileNameArray[resourceType], S_CASTLES__005A64E0); strcat(this->resourceFileNameArray[resourceType], shortFileName); return; @@ -49,27 +48,27 @@ namespace IO { } case FRT_HELP: - strcpy(this->resourceFileNameArray[resourceType], "help\\"); + strcpy(this->resourceFileNameArray[resourceType], S_HELP__005A5A24); strcat(this->resourceFileNameArray[resourceType], shortFileName); return; case FRT_BINKS: - strcpy(this->resourceFileNameArray[resourceType], "binks\\"); + strcpy(this->resourceFileNameArray[resourceType], S_BINKS__005A64D8); strcat(this->resourceFileNameArray[resourceType], shortFileName); return; case FRT_FX: - strcpy(this->resourceFileNameArray[resourceType], "fx\\"); + strcpy(this->resourceFileNameArray[resourceType], S_FX__005A5A2C); strcat(this->resourceFileNameArray[resourceType], shortFileName); return; case FRT_GFX_SPEECH: // FIXME: Wrong name? Should be FRT_FX_SPEECH, or not? - strcpy(this->resourceFileNameArray[resourceType], "fx\\speech\\"); + strcpy(this->resourceFileNameArray[resourceType], S_FX_SPEECH__005A64CC); strcat(this->resourceFileNameArray[resourceType], shortFileName); return; case FRT_MAPS: { - strcpy(this->resourceFileNameArray[resourceType], "maps\\"); + strcpy(this->resourceFileNameArray[resourceType], S_MAPS__005A64C4); strcat(this->resourceFileNameArray[resourceType], shortFileName); if (MACRO_CALL_MEMBER(ResourceManager_Func::doesFileExist, this)( @@ -84,7 +83,7 @@ namespace IO { } case FRT_SCORES: - strcpy(this->resourceFileNameArray[resourceType], "scores\\"); + strcpy(this->resourceFileNameArray[resourceType], S_SCORES__005A64BC); strcat(this->resourceFileNameArray[resourceType], shortFileName); return; From 2cd80a2d8a80b97c9e345d055eddd7e56bec0345 Mon Sep 17 00:00:00 2001 From: TheRedDaemon <66257843+TheRedDaemon@users.noreply.github.com> Date: Fri, 21 Aug 2026 23:18:00 +0200 Subject: [PATCH 37/37] feat(docs): extended cheat sheet regarding strings --- IMPLEMENTATION_CHEAT_SHEET.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/IMPLEMENTATION_CHEAT_SHEET.md b/IMPLEMENTATION_CHEAT_SHEET.md index 4ca91e1d..e27f53a1 100644 --- a/IMPLEMENTATION_CHEAT_SHEET.md +++ b/IMPLEMENTATION_CHEAT_SHEET.md @@ -190,8 +190,15 @@ They might be worth trying in very tricky cases, but they were usually seen as c ### String Literals -String literals are not resolved. Instead we use a big `string-literals.hpp` file. -Make always sure to use a reference from this file instead of a string literal. +String literals are not resolved. Instead we use tow big files, `string-macros.hpp` and `string-literals.hpp`. +`string-macros.hpp` is the ground truth. However, when ever possible, using the pointers from `string-literals.hpp` is preferred. + +There is one known case that requires using only the macros: +Only literals can by split up into multiple parts and be moved into registers to copy a string, for example via "strcpy". +In this case, use the macros for the strings and **DO NOT** include `string-literals.hpp`, since this might cause different behavior. +Should a mixture of pointers and macros be required, because the macro to not produce the fitting structure, still only use the macros from `string-macros.hpp`. Create a string pointer in the cpp file and use this for the pointer. + +Make always sure to use a reference from this files instead of a direct string literal. ### Blocks and Scopes