diff --git a/src/openloco/localisation/stringmgr.h b/src/openloco/localisation/stringmgr.h
index 50cbc819..25f9bb67 100644
--- a/src/openloco/localisation/stringmgr.h
+++ b/src/openloco/localisation/stringmgr.h
@@ -5,6 +5,11 @@
namespace openloco
{
using string_id = uint16_t;
+
+ namespace string_ids
+ {
+ constexpr string_id null = 0xFFFF;
+ }
}
namespace openloco::stringmgr
diff --git a/src/openloco/openloco.cpp b/src/openloco/openloco.cpp
index efac8fc1..d1095f66 100644
--- a/src/openloco/openloco.cpp
+++ b/src/openloco/openloco.cpp
@@ -29,6 +29,7 @@
#include "platform/platform.h"
#include "progressbar.h"
#include "scenariomgr.h"
+#include "stationmgr.h"
#include "things/thingmgr.h"
#include "tutorial.h"
#include "ui.h"
@@ -578,7 +579,7 @@ namespace openloco
{
if (update_day_counter())
{
- call(0x0048B244);
+ stationmgr::sub_48B244();
call(0x004B94CF);
call(0x00453487);
call(0x004284DB);
diff --git a/src/openloco/openloco.vcxproj b/src/openloco/openloco.vcxproj
index 1a120ea1..0768c66b 100644
--- a/src/openloco/openloco.vcxproj
+++ b/src/openloco/openloco.vcxproj
@@ -29,6 +29,8 @@
+
+
@@ -70,6 +72,8 @@
+
+
diff --git a/src/openloco/station.cpp b/src/openloco/station.cpp
index 96218697..ff406e02 100644
--- a/src/openloco/station.cpp
+++ b/src/openloco/station.cpp
@@ -22,6 +22,14 @@ namespace openloco
return (station_id_t)index;
}
+ // 0x0048F7D1
+ void station::sub_48F7D1()
+ {
+ registers regs;
+ regs.ebx = id();
+ call(0x0048F7D1, regs);
+ }
+
// 0x00492793
bool station::update_cargo()
{
@@ -165,4 +173,12 @@ namespace openloco
regs.ebp = (int32_t)this;
call(0x004929DB, regs);
}
+
+ // 0x004CBA2D
+ void station::invalidate()
+ {
+ registers regs;
+ regs.esi = (int32_t)this;
+ call(0x004CBA2D, regs);
+ }
}
diff --git a/src/openloco/station.h b/src/openloco/station.h
index 23e3dbaf..4b347f45 100644
--- a/src/openloco/station.h
+++ b/src/openloco/station.h
@@ -1,6 +1,7 @@
#pragma once
#include "localisation/stringmgr.h"
+#include "town.h"
#include
#include
@@ -42,18 +43,22 @@ namespace openloco
string_id name; // 0x00
uint8_t pad_02[0x28 - 0x02];
uint8_t var_28;
- uint8_t pad_29[0x2A - 0x29];
+ uint8_t var_29;
uint16_t var_2A;
- string_id town_name; // 0x2C
+ town_id_t town; // 0x2C
station_cargo_stats cargo_stats[32]; // 0x2E
- uint8_t pad_1CE[0x3B0 - 0x1CE];
+ uint16_t var_1CE;
+ uint8_t pad_1D0[0x3B0 - 0x1D0];
uint8_t var_3B0;
uint8_t var_3B1;
uint8_t pad_3B2[0x3D2 - 0x3B2];
+ bool empty() const { return name == string_ids::null; }
station_id_t id();
+ void sub_48F7D1();
bool update_cargo();
int32_t calculate_cargo_rating(const station_cargo_stats& cargo) const;
+ void invalidate();
private:
void sub_4929DB();
diff --git a/src/openloco/stationmgr.cpp b/src/openloco/stationmgr.cpp
index fd38f788..a66487df 100644
--- a/src/openloco/stationmgr.cpp
+++ b/src/openloco/stationmgr.cpp
@@ -1,11 +1,21 @@
#include "stationmgr.h"
#include "interop/interop.hpp"
+#include "townmgr.h"
+#include "window.h"
+#include
using namespace openloco::interop;
+using namespace openloco::ui;
namespace openloco::stationmgr
{
- static loco_global_array _stations;
+ static loco_global_array _stations;
+
+ std::array& stations()
+ {
+ auto arr = (std::array*)_stations.get();
+ return *arr;
+ }
station* get(station_id_t id)
{
@@ -16,4 +26,70 @@ namespace openloco::stationmgr
}
return nullptr;
}
+
+ // 0x00437F29
+ // arg0: ah
+ // arg1: al
+ static void sub_437F29(uint8_t arg0, uint8_t arg1)
+ {
+ constexpr uint8_t byte_4F9462[] = { 0, 31, 10, 7, 31, 10, 31, 31, 11 };
+ static loco_global_array byte_53A334;
+ byte_53A334[(arg0 * 36776) + arg1] = byte_4F9462[arg1];
+ }
+
+ // 0x0048B244
+ void sub_48B244()
+ {
+ for (auto& town : townmgr::towns())
+ {
+ if (!town.empty())
+ {
+ town.var_06 &= town_flags::flag_1;
+ }
+ }
+
+ for (auto& station : stations())
+ {
+ if (!station.empty())
+ {
+ if (station.var_1CE == 0)
+ {
+ station.var_29++;
+ if (station.var_29 != 5)
+ {
+ // clang-format off
+ if (station.var_28 == addr<0x00525E3C, uint8_t>() ||
+ station.var_28 == addr<0x00525E3D, uint8_t>())
+ // clang-format on
+ {
+ sub_437F29(station.var_28, 8);
+ }
+ }
+ if (station.var_29 >= 10)
+ {
+ call(0x0049E1F1);
+ station.invalidate();
+ station.sub_48F7D1();
+ }
+ }
+ else
+ {
+ station.var_29 = 0;
+ }
+ if (station.update_cargo())
+ {
+ auto town = townmgr::get(station.town);
+ if (town != nullptr && !(town->var_06 & town_flags::flag_1))
+ {
+ town->var_06 |= town_flags::flag_1;
+ town->var_58 |= (1 << station.var_28);
+ if (town->var_3A[station.var_28] < 1000)
+ {
+ town->var_3A[station.var_28]++;
+ }
+ }
+ }
+ }
+ }
+ }
}
diff --git a/src/openloco/stationmgr.h b/src/openloco/stationmgr.h
index dec55a6c..d0ceca2d 100644
--- a/src/openloco/stationmgr.h
+++ b/src/openloco/stationmgr.h
@@ -1,9 +1,12 @@
#pragma once
#include "station.h"
-#include
+#include
namespace openloco::stationmgr
{
+ constexpr size_t max_stations = 1024;
+
station* get(station_id_t id);
+ void sub_48B244();
}
diff --git a/src/openloco/town.cpp b/src/openloco/town.cpp
new file mode 100644
index 00000000..ef58eecc
--- /dev/null
+++ b/src/openloco/town.cpp
@@ -0,0 +1,9 @@
+#include "town.h"
+
+namespace openloco
+{
+ bool town::empty() const
+ {
+ return var_00 != -1;
+ }
+}
diff --git a/src/openloco/town.h b/src/openloco/town.h
new file mode 100644
index 00000000..407cdf03
--- /dev/null
+++ b/src/openloco/town.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include
+#include
+
+namespace openloco
+{
+ using town_id_t = uint16_t;
+
+ namespace town_id
+ {
+ constexpr town_id_t null = std::numeric_limits::max();
+ }
+
+ namespace town_flags
+ {
+ constexpr uint16_t flag_1 = 1 << 1;
+ }
+
+#pragma pack(push, 1)
+ struct town
+ {
+ int16_t var_00;
+ uint8_t pad_02[0x06 - 0x02];
+ uint16_t var_06;
+ uint8_t pad_08[0x3A - 0x08];
+ int16_t var_3A[8]; // guess?
+ uint8_t pad_42[0x58 - 0x42];
+ uint16_t var_58;
+ uint8_t pad_5A[0x270 - 0x5A];
+
+ bool empty() const;
+ };
+#pragma pack(pop)
+}
diff --git a/src/openloco/townmgr.cpp b/src/openloco/townmgr.cpp
new file mode 100644
index 00000000..c9874084
--- /dev/null
+++ b/src/openloco/townmgr.cpp
@@ -0,0 +1,24 @@
+#include "townmgr.h"
+#include "interop/interop.hpp"
+
+using namespace openloco::interop;
+
+namespace openloco::townmgr
+{
+ static loco_global_array _towns;
+
+ std::array towns()
+ {
+ auto arr = (std::array*)_towns.get();
+ return *arr;
+ }
+
+ town* get(town_id_t id)
+ {
+ if (id >= _towns.size())
+ {
+ return nullptr;
+ }
+ return &_towns[id];
+ }
+}
diff --git a/src/openloco/townmgr.h b/src/openloco/townmgr.h
new file mode 100644
index 00000000..e42241b7
--- /dev/null
+++ b/src/openloco/townmgr.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "town.h"
+#include
+
+namespace openloco::townmgr
+{
+ constexpr size_t max_towns = 80;
+
+ std::array towns();
+ town* get(town_id_t id);
+}