Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
9495626
reimplement: SHC_3BB0A8C1_0x00500D60 100.00% Reimplemented
gynt Sep 28, 2026
d20b395
reimplement: SHC_3BB0A8C1_0x005118C0 51.79% tail-merge of arms differs
gynt Sep 28, 2026
c0ed1e4
reimplement: SHC_3BB0A8C1_0x00500EE0 100.00% Reimplemented
gynt Sep 28, 2026
68b9eda
reimplement: SHC_3BB0A8C1_0x00500E20 56.90% reg alloc, this clobbered
gynt Sep 28, 2026
8383113
reimplement: SHC_3BB0A8C1_0x00500DD0 100.00% Reimplemented
gynt Sep 28, 2026
4093cdc
reimplement: SHC_3BB0A8C1_0x00500C80 100.00% Reimplemented
gynt Sep 28, 2026
52b7a71
reimplement: SHC_3BB0A8C1_0x00500D30 100.00% Reimplemented
gynt Sep 28, 2026
5995926
reimplement: SHC_3BB0A8C1_0x00500C20 95.65% add -0x28 vs sub 0x28
gynt Sep 28, 2026
379fc45
reimplement: SHC_3BB0A8C1_0x00500CB0 100.00% Reimplemented
gynt Sep 28, 2026
65f5f2f
reimplement: SHC_3BB0A8C1_0x00500CF0 100.00% Reimplemented
gynt Sep 28, 2026
9ce63dd
reimplement: SHC_3BB0A8C1_0x00500F40 100.00% Reimplemented
gynt Sep 28, 2026
c60bf62
cleanup: drop Ghidra comments and trailing returns in Map::WallAndPit…
gynt Sep 28, 2026
fe41302
reimplement: SHC_3BB0A8C1_0x00500E20 100.00% Reimplemented
gynt Sep 28, 2026
0456a12
reimplement: SHC_3BB0A8C1_0x005118C0 59.32% MSVC merges Param0 not Pa…
gynt Sep 28, 2026
10e449e
cleanup: use compound assignment in Map::WallAndPitchState
claude Sep 28, 2026
48f3a52
reimplement: SHC_3BB0A8C1_0x005118C0 76.92% case 4 register allocation
gynt Oct 5, 2026
0281466
reimplement: SHC_3BB0A8C1_0x00500C20 100.00% Reimplemented
gynt Oct 5, 2026
c6347d6
reimplement: SHC_3BB0A8C1_0x005118C0 100.00% Reimplemented
gynt Oct 5, 2026
cd5e3f7
Merge branch 'main' into reimpl/WallAndPitchState
gynt Oct 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/OpenSHC/Map/WallAndPitchState/addWallPlacementInfoForTile.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "../WallAndPitchState.func.hpp"

#include "OpenSHC/Game/GameMode2.hpp"

#include "OpenSHC/Globals/DAT_GameCore.hpp"
#include "OpenSHC/Globals/DAT_TileMapState.hpp"

namespace OpenSHC {
namespace Map {

using OpenSHC::Game::GameMode2;

// FUNCTION: STRONGHOLDCRUSADER 0x00500D60
void WallAndPitchState::addWallPlacementInfoForTile(int tile)
{
if (((DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SKIRMISH_AND_MULTIPLAYER)
&& (DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SIEGE_THAT))
&& (this->index < 100)) {
this->wallPlacementInfoArray[this->index].tile_OR_pitchID = tile;
this->wallPlacementInfoArray[this->index].height = DAT_TileMapState::instance.HeightLayer[tile];
this->wallPlacementInfoArray[this->index].logic = DAT_TileMapState::instance.LogicLayer[tile] & 0x470b00;
this->wallPlacementInfoArray[this->index].damage = DAT_TileMapState::instance.DamageLayer[tile];
this->index += 1;
}
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#include "../WallAndPitchState.func.hpp"

#include "OpenSHC/Synchrony/GameSynchronyState.func.hpp"
#include "OpenSHC/Commands/GameCommandType.hpp"
#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp"

#include "OpenSHC/Globals/DAT_BuildingsState.hpp"
#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp"
#include "OpenSHC/Globals/DAT_UIDragDropDefinedData.hpp"

namespace OpenSHC {
namespace Map {

using OpenSHC::Commands::GameCommandType;
using OpenSHC::WindowsHelper::Enums::BOOLEnum;

// FUNCTION: STRONGHOLDCRUSADER 0x005118C0
void WallAndPitchState::confirmAndQueueDestructionCommand()
{
if (this->countdown != 0) {
this->countdown += 1;
MACRO_CALL_MEMBER(OpenSHC::Map::WallAndPitchState_Func::updateDestructionConfirmationCountdown, this)();
if (this->countdown != 0) {
switch (this->state) {
case 0: {
int id = this->id;
DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = id;
int uid = DAT_BuildingsState::instance.buildings[id].uid;
DAT_GameSynchronyState::instance.DAT_GameCommandParam1 = 100;
DAT_GameSynchronyState::instance.DAT_GameCommandParam2 = uid;
MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand,
DAT_GameSynchronyState::ptr)(OpenSHC::Commands::GCT_DESTROY_BUILDING);
break;
}
case 1: {
int id = this->id;
DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = 1;
DAT_GameSynchronyState::instance.DAT_GameCommandParam1 = id;
MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand,
DAT_GameSynchronyState::ptr)((GameCommandType)75);
break;
}
case 2: {
int id = this->id;
DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = 2;
DAT_GameSynchronyState::instance.DAT_GameCommandParam1 = id;
MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand,
DAT_GameSynchronyState::ptr)((GameCommandType)75);
break;
}
case 3: {
DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = this->index;
DAT_GameSynchronyState::instance.DAT_GameCommandParam1 = this->counter;
DAT_GameSynchronyState::instance.DAT_GameCommandParam2 = this->flag;
DAT_GameSynchronyState::instance.DAT_GameCommandParam3 = 3;
MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand,
DAT_GameSynchronyState::ptr)((GameCommandType)76);
break;
}
case 4: {
DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = this->index;
DAT_GameSynchronyState::instance.DAT_GameCommandParam1 = this->counter;
DAT_GameSynchronyState::instance.DAT_GameCommandParam2 = this->flag;
DAT_GameSynchronyState::instance.DAT_GameCommandParam3 = 4;
MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand,
DAT_GameSynchronyState::ptr)((GameCommandType)76);
break;
}
}
}
}
this->countdown = 0;
DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE;
}

}
}
30 changes: 30 additions & 0 deletions src/OpenSHC/Map/WallAndPitchState/destroyPitch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "../WallAndPitchState.func.hpp"

#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp"
#include "OpenSHC/Map/TileMapState.func.hpp"
#include "OpenSHC/UI/MinimapViewState.func.hpp"
#include "OpenSHC/Game/Resources/ResourceType.hpp"

#include "OpenSHC/Globals/DAT_BuildingsState.hpp"
#include "OpenSHC/Globals/DAT_MinimapViewState.hpp"
#include "OpenSHC/Globals/DAT_TileMapState.hpp"

namespace OpenSHC {
namespace Map {

using OpenSHC::Game::Resources::ResourceType;

// FUNCTION: STRONGHOLDCRUSADER 0x00500EE0
void WallAndPitchState::destroyPitch(int playerID, int count, int amount, int param_4)
{
MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processResourceGain, DAT_BuildingsState::ptr)(
playerID, OpenSHC::Game::Resources::RT_PITCH, amount / 4);
for (int i = 0; i < count; i++) {
MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::destroyPitchDitch, DAT_TileMapState::ptr)(
this->receivedWallPlacementInfoArray[i].tile_OR_pitchID);
}
MACRO_CALL_MEMBER(OpenSHC::UI::MinimapViewState_Func::triggerMinimapRedraw, DAT_MinimapViewState::ptr)(1);
}

}
}
46 changes: 46 additions & 0 deletions src/OpenSHC/Map/WallAndPitchState/destroyWall.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "../WallAndPitchState.func.hpp"

#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp"
#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp"
#include "OpenSHC/UI/MinimapViewState.func.hpp"
#include "OpenSHC/Game/Resources/ResourceType.hpp"

#include "OpenSHC/Globals/DAT_BuildingsState.hpp"
#include "OpenSHC/Globals/DAT_MinimapViewState.hpp"
#include "OpenSHC/Globals/DAT_PathFindingState.hpp"
#include "OpenSHC/Globals/DAT_TileMapState.hpp"
#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp"

namespace OpenSHC {
namespace Map {

using OpenSHC::Game::Resources::ResourceType;

// FUNCTION: STRONGHOLDCRUSADER 0x00500E20
void WallAndPitchState::destroyWall(int playerID, int count, int amount, int param_4)
{
if (param_4 == 0) {
MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processResourceGain,
DAT_BuildingsState::ptr)(playerID, OpenSHC::Game::Resources::RT_STONE, amount);
} else {
MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processResourceGain,
DAT_BuildingsState::ptr)(playerID, OpenSHC::Game::Resources::RT_WOOD, amount);
}
for (int i = 0; i < count; i++) {
int _tile = this->receivedWallPlacementInfoArray[i].tile_OR_pitchID;
int _y = (int)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[_tile];
DAT_TileMapState::instance.DamageLayer[_tile] = this->receivedWallPlacementInfoArray[i].damage;
DAT_TileMapState::instance.HeightLayer[_tile] = this->receivedWallPlacementInfoArray[i].height;
DAT_TileMapState::instance.LogicLayer[_tile] &= 0xffb8f4ff;
DAT_TileMapState::instance.LogicLayer[_tile] |= this->receivedWallPlacementInfoArray[i].logic;
int _tileDelta = _tile - DAT_ViewportRenderState::instance.translationMatrix[_y].addXgetTile;
MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections,
DAT_PathFindingState::ptr)(_y, _tile);
MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer,
DAT_PathFindingState::ptr)(9, (uint)_tileDelta, _y);
}
MACRO_CALL_MEMBER(OpenSHC::UI::MinimapViewState_Func::triggerMinimapRedraw, DAT_MinimapViewState::ptr)(1);
}

}
}
32 changes: 32 additions & 0 deletions src/OpenSHC/Map/WallAndPitchState/placePitchDitch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include "../WallAndPitchState.func.hpp"

#include "OpenSHC/Game/GameMode2.hpp"

#include "OpenSHC/Globals/DAT_GameCore.hpp"

namespace OpenSHC {
namespace Map {

using OpenSHC::Game::GameMode2;

// FUNCTION: STRONGHOLDCRUSADER 0x00500DD0
void WallAndPitchState::placePitchDitch(int pitchID)
{
if ((DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SKIRMISH_AND_MULTIPLAYER)
&& (DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SIEGE_THAT)) {
if (this->countdown == 0) {
this->countdown = 400;
this->index = 0;
this->counter = 0;
}
if (this->index < 100) {
this->wallPlacementInfoArray[this->index].tile_OR_pitchID = pitchID;
this->index += 1;
this->counter += 1;
this->countdown = 400;
}
}
}

}
}
18 changes: 9 additions & 9 deletions src/OpenSHC/Map/WallAndPitchState/resetWallAndPitchState.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "OpenSHC/Map/WallAndPitchState.func.hpp"
#include "../WallAndPitchState.func.hpp"

#include "OpenSHC/Game/GameMode2.hpp"
#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp"

Expand All @@ -14,15 +15,14 @@ namespace Map {
// FUNCTION: STRONGHOLDCRUSADER 0x00500C80
void WallAndPitchState::resetWallAndPitchState()
{
if (DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_SKIRMISH_AND_MULTIPLAYER
|| DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_SIEGE_THAT) {
return;
if ((DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SKIRMISH_AND_MULTIPLAYER)
&& (DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SIEGE_THAT)) {
this->state = 4;
this->countdown = 400;
this->index = 0;
this->counter = 0;
DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE;
}
this->state = 4;
this->countdown = 400;
this->index = 0;
this->counter = 0;
DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE;
}

}
Expand Down
18 changes: 9 additions & 9 deletions src/OpenSHC/Map/WallAndPitchState/resetWallPlacementInfo.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "OpenSHC/Map/WallAndPitchState.func.hpp"
#include "../WallAndPitchState.func.hpp"

#include "OpenSHC/Game/GameMode2.hpp"
#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp"

Expand All @@ -14,15 +15,14 @@ namespace Map {
// FUNCTION: STRONGHOLDCRUSADER 0x00500D30
void WallAndPitchState::resetWallPlacementInfo()
{
if (DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_SKIRMISH_AND_MULTIPLAYER
|| DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_SIEGE_THAT) {
return;
if ((DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SKIRMISH_AND_MULTIPLAYER)
&& (DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SIEGE_THAT)) {
this->state = 3;
this->countdown = 400;
this->index = 0;
this->counter = 0;
DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE;
}
this->state = 3;
this->countdown = 400;
this->index = 0;
this->counter = 0;
DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE;
}

}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "../WallAndPitchState.func.hpp"

#include "OpenSHC/Game/GameMode2.hpp"
#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp"

#include "OpenSHC/Globals/DAT_BuildingsState.hpp"
#include "OpenSHC/Globals/DAT_GameCore.hpp"
#include "OpenSHC/Globals/DAT_UIDragDropDefinedData.hpp"

namespace OpenSHC {
namespace Map {

using OpenSHC::Game::GameMode2;
using OpenSHC::WindowsHelper::Enums::BOOLEnum;

// FUNCTION: STRONGHOLDCRUSADER 0x00500C20
void WallAndPitchState::startBuildingDestructionConfirmation(int buildingID)
{
if ((DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SKIRMISH_AND_MULTIPLAYER)
&& (DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SIEGE_THAT)) {
int buildingType = DAT_BuildingsState::instance.buildings[buildingID].buildingType;
if (buildingType >= OpenSHC::Map::Buildings::BT_MANORHOUSE
&& buildingType <= OpenSHC::Map::Buildings::BT_KEEPFIVE) {
this->countdown = 0;
return;
}
this->state = 0;
this->countdown = 400;
this->id = buildingID;
this->uid = DAT_BuildingsState::instance.buildings[buildingID].uid;
DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE;
}
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "../WallAndPitchState.func.hpp"

#include "OpenSHC/Game/GameMode2.hpp"
#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp"

#include "OpenSHC/Globals/DAT_EntityState.hpp"
#include "OpenSHC/Globals/DAT_GameCore.hpp"
#include "OpenSHC/Globals/DAT_UIDragDropDefinedData.hpp"

namespace OpenSHC {
namespace Map {

using OpenSHC::Game::GameMode2;
using OpenSHC::WindowsHelper::Enums::BOOLEnum;

// FUNCTION: STRONGHOLDCRUSADER 0x00500CB0
void WallAndPitchState::startEntityDestructionConfirmation(int entityID)
{
if ((DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SKIRMISH_AND_MULTIPLAYER)
&& (DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SIEGE_THAT)) {
this->id = entityID;
this->state = 1;
this->countdown = 400;
this->uid = DAT_EntityState::instance.entityArray[entityID].uid;
DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE;
}
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "../WallAndPitchState.func.hpp"

#include "OpenSHC/Game/GameMode2.hpp"
#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp"

#include "OpenSHC/Globals/DAT_GameCore.hpp"
#include "OpenSHC/Globals/DAT_UIDragDropDefinedData.hpp"
#include "OpenSHC/Globals/DAT_UnitsState.hpp"

namespace OpenSHC {
namespace Map {

using OpenSHC::Game::GameMode2;
using OpenSHC::WindowsHelper::Enums::BOOLEnum;

// FUNCTION: STRONGHOLDCRUSADER 0x00500CF0
void WallAndPitchState::startUnitDestructionConfirmation(int unitID)
{
if ((DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SKIRMISH_AND_MULTIPLAYER)
&& (DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SIEGE_THAT)) {
this->id = unitID;
this->state = 2;
this->countdown = 400;
this->uid = DAT_UnitsState::instance.units[unitID].uid;
DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE;
}
}

}
}
Loading
Loading