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); +}