diff --git a/.gitignore b/.gitignore index 3d0376aa94..38765312bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /.vs +/.cache/* /build* CMakeSettings.json docs/aidocs/* diff --git a/media/baseset/opntitle_testing.dat b/media/baseset/opntitle_testing.dat new file mode 100644 index 0000000000..b43b3f6cd3 Binary files /dev/null and b/media/baseset/opntitle_testing.dat differ diff --git a/src/cargomonitor.h b/src/cargomonitor.h index 614f10002e..505ce957e8 100644 --- a/src/cargomonitor.h +++ b/src/cargomonitor.h @@ -12,6 +12,7 @@ #include "cargo_type.h" #include "company_func.h" +#include "company_type.h" #include "industry.h" #include "town.h" #include "core/overflowsafe_type.hpp" @@ -24,12 +25,12 @@ struct Station; * - bits 0-15 town or industry number * - bit 16 is set if it is an industry number (else it is a town number). * - bits 19-23 Cargo type. - * - bits 24-31 %Company number. + * - bits 24 - 24 + COMPANY_BIT_SIZE %Company number. */ typedef uint32_t CargoMonitorID; ///< Type of the cargo monitor number. /** Map type for storing and updating active cargo monitor numbers and their amounts. */ -typedef std::map CargoMonitorMap; +typedef std::map CargoMonitorMap; extern CargoMonitorMap _cargo_pickups; extern CargoMonitorMap _cargo_deliveries; @@ -44,9 +45,11 @@ enum CargoCompanyBits { CCB_CARGO_TYPE_START = 19, ///< Start bit of the cargo type field. CCB_CARGO_TYPE_LENGTH = 6, ///< Number of bits of the cargo type field. CCB_COMPANY_START = 25, ///< Start bit of the company field. - CCB_COMPANY_LENGTH = 4, ///< Number of bits of the company field. + CCB_COMPANY_LENGTH = COMPANY_SIZE_BITS, ///< Number of bits of the company field. }; + +static_assert(CCB_COMPANY_LENGTH <= (1 << 8)); static_assert(NUM_CARGO <= (1 << CCB_CARGO_TYPE_LENGTH)); static_assert(MAX_COMPANIES <= (1 << CCB_COMPANY_LENGTH)); @@ -63,7 +66,7 @@ inline CargoMonitorID EncodeCargoIndustryMonitor(CompanyID company, CargoID ctyp assert(ctype < (1 << CCB_CARGO_TYPE_LENGTH)); assert(company < (1 << CCB_COMPANY_LENGTH)); - uint32_t ret = 0; + uint64_t ret = 0; SB(ret, CCB_TOWN_IND_NUMBER_START, CCB_TOWN_IND_NUMBER_LENGTH, ind); SetBit(ret, CCB_IS_INDUSTRY_BIT); SB(ret, CCB_CARGO_TYPE_START, CCB_CARGO_TYPE_LENGTH, ctype); @@ -83,7 +86,7 @@ inline CargoMonitorID EncodeCargoTownMonitor(CompanyID company, CargoID ctype, T assert(ctype < (1 << CCB_CARGO_TYPE_LENGTH)); assert(company < (1 << CCB_COMPANY_LENGTH)); - uint32_t ret = 0; + uint64_t ret = 0; SB(ret, CCB_TOWN_IND_NUMBER_START, CCB_TOWN_IND_NUMBER_LENGTH, town); SB(ret, CCB_CARGO_TYPE_START, CCB_CARGO_TYPE_LENGTH, ctype); SB(ret, CCB_COMPANY_START, CCB_COMPANY_LENGTH, company); diff --git a/src/clear_map.h b/src/clear_map.h index 64eb640d12..b24753c5f2 100644 --- a/src/clear_map.h +++ b/src/clear_map.h @@ -260,7 +260,6 @@ inline void MakeClear(Tile t, ClearGround g, uint density) { SetTileType(t, MP_CLEAR); t.m1() = 0; - SetTileOwner(t, OWNER_NONE); t.m2() = 0; t.m3() = 0; t.m4() = 0 << 5 | 0 << 2; @@ -268,6 +267,8 @@ inline void MakeClear(Tile t, ClearGround g, uint density) t.m6() = 0; t.m7() = 0; t.m8() = 0; + t.m9() = 0; + SetTileOwner(t, OWNER_NONE); } @@ -281,7 +282,6 @@ inline void MakeField(Tile t, uint field_type, IndustryID industry) { SetTileType(t, MP_CLEAR); t.m1() = 0; - SetTileOwner(t, OWNER_NONE); t.m2() = industry; t.m3() = field_type; t.m4() = 0 << 5 | 0 << 2; @@ -289,6 +289,8 @@ inline void MakeField(Tile t, uint field_type, IndustryID industry) SB(t.m6(), 2, 4, 0); t.m7() = 0; t.m8() = 0; + t.m9() = 0; + SetTileOwner(t, OWNER_NONE); } /** diff --git a/src/company_base.h b/src/company_base.h index 814665777b..8173fdda4e 100644 --- a/src/company_base.h +++ b/src/company_base.h @@ -96,6 +96,7 @@ struct CompanyProperties { uint8_t months_empty = 0; ///< NOSAVE: Number of months this company has not had a client in multiplayer. uint8_t months_of_bankruptcy; ///< Number of months that the company is unable to pay its debts CompanyMask bankrupt_asked; ///< which companies were asked about buying it? + uint16_t old_bankrupt_asked; int16_t bankrupt_timeout; ///< If bigger than \c 0, amount of time to wait for an answer on an offer to buy this company. Money bankrupt_value; diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 74ad2893f4..ecc8bb2f52 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -7,6 +7,8 @@ /** @file company_cmd.cpp Handling of companies. */ +#include "company_type.h" +#include "gfx_type.h" #include "stdafx.h" #include "company_base.h" #include "company_func.h" @@ -448,27 +450,6 @@ bad_town_name:; } } -/** Sorting weights for the company colours. */ -static const uint8_t _colour_sort[COLOUR_END] = {2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2, 2, 3, 1, 1, 1}; -/** Similar colours, so we can try to prevent same coloured companies. */ -static const Colours _similar_colour[COLOUR_END][2] = { - { COLOUR_BLUE, COLOUR_LIGHT_BLUE }, // COLOUR_DARK_BLUE - { COLOUR_GREEN, COLOUR_DARK_GREEN }, // COLOUR_PALE_GREEN - { INVALID_COLOUR, INVALID_COLOUR }, // COLOUR_PINK - { COLOUR_ORANGE, INVALID_COLOUR }, // COLOUR_YELLOW - { INVALID_COLOUR, INVALID_COLOUR }, // COLOUR_RED - { COLOUR_DARK_BLUE, COLOUR_BLUE }, // COLOUR_LIGHT_BLUE - { COLOUR_PALE_GREEN, COLOUR_DARK_GREEN }, // COLOUR_GREEN - { COLOUR_PALE_GREEN, COLOUR_GREEN }, // COLOUR_DARK_GREEN - { COLOUR_DARK_BLUE, COLOUR_LIGHT_BLUE }, // COLOUR_BLUE - { COLOUR_BROWN, COLOUR_ORANGE }, // COLOUR_CREAM - { COLOUR_PURPLE, INVALID_COLOUR }, // COLOUR_MAUVE - { COLOUR_MAUVE, INVALID_COLOUR }, // COLOUR_PURPLE - { COLOUR_YELLOW, COLOUR_CREAM }, // COLOUR_ORANGE - { COLOUR_CREAM, INVALID_COLOUR }, // COLOUR_BROWN - { COLOUR_WHITE, INVALID_COLOUR }, // COLOUR_GREY - { COLOUR_GREY, INVALID_COLOUR }, // COLOUR_WHITE -}; /** * Generate a company colour. @@ -476,53 +457,13 @@ static const Colours _similar_colour[COLOUR_END][2] = { */ static Colours GenerateCompanyColour() { - Colours colours[COLOUR_END]; + int num_colours = COLOUR_END - COLOUR_BEGIN; - /* Initialize array */ - for (uint i = 0; i < COLOUR_END; i++) colours[i] = static_cast(i); - - /* And randomize it */ - for (uint i = 0; i < 100; i++) { - uint r = Random(); - Swap(colours[GB(r, 0, 4)], colours[GB(r, 4, 4)]); + int companies = 0; + for (const Company *_ : Company::Iterate()) { + companies++; } - - /* Bubble sort it according to the values in table 1 */ - for (uint i = 0; i < COLOUR_END; i++) { - for (uint j = 1; j < COLOUR_END; j++) { - if (_colour_sort[colours[j - 1]] < _colour_sort[colours[j]]) { - Swap(colours[j - 1], colours[j]); - } - } - } - - /* Move the colours that look similar to each company's colour to the side */ - for (const Company *c : Company::Iterate()) { - Colours pcolour = c->colour; - - for (uint i = 0; i < COLOUR_END; i++) { - if (colours[i] == pcolour) { - colours[i] = INVALID_COLOUR; - break; - } - } - - for (uint j = 0; j < 2; j++) { - Colours similar = _similar_colour[pcolour][j]; - if (similar == INVALID_COLOUR) break; - - for (uint i = 1; i < COLOUR_END; i++) { - if (colours[i - 1] == similar) Swap(colours[i - 1], colours[i]); - } - } - } - - /* Return the first available colour */ - for (uint i = 0; i < COLOUR_END; i++) { - if (colours[i] != INVALID_COLOUR) return colours[i]; - } - - NOT_REACHED(); + return Colours(companies % num_colours); } /** diff --git a/src/company_type.h b/src/company_type.h index 355bde8630..42305ecbbd 100644 --- a/src/company_type.h +++ b/src/company_type.h @@ -11,6 +11,7 @@ #define COMPANY_TYPE_H #include "core/enum_type.hpp" +#include /** * Enum for all companies/owners. @@ -18,22 +19,39 @@ enum Owner : uint8_t { /* All companies below MAX_COMPANIES are playable * companies, above, they are special, computer controlled 'companies' */ - OWNER_BEGIN = 0x00, ///< First owner - COMPANY_FIRST = 0x00, ///< First company, same as owner - MAX_COMPANIES = 0x0F, ///< Maximum number of companies - OWNER_TOWN = 0x0F, ///< A town owns the tile, or a town is expanding - OWNER_NONE = 0x10, ///< The tile has no ownership - OWNER_WATER = 0x11, ///< The tile/execution is done by "water" - OWNER_DEITY = 0x12, ///< The object is owned by a superuser / goal script + OWNER_BEGIN = 0x00, ///< First owner + COMPANY_FIRST = 0x00, ///< First company, same as owner + MAX_COMPANIES = 0xF0, ///< Maximum number of companies + OLD_MAX_COMPANIES = 0x0F, ///< Maximum number of companies + OWNER_TOWN = 0xF1, ///< A town owns the tile, or a town is expanding + OLD_OWNER_TOWN = 0x0F, + OWNER_NONE = 0xF2, ///< The tile has no ownership + OLD_OWNER_NONE = 0x10, ///< The tile has no ownership + + + OWNER_WATER = 0xF3, ///< The tile/execution is done by "water" + OLD_OWNER_WATER = 0x11, ///< The tile/execution is done by "water" + OWNER_DEITY = 0xF4, ///< The object is owned by a superuser / goal script OWNER_END, ///< Last + 1 owner - INVALID_OWNER = 0xFF, ///< An invalid owner - INVALID_COMPANY = 0xFF, ///< An invalid company + INVALID_OWNER = 0xFF, ///< An invalid owner + INVALID_COMPANY = 0xFF, ///< An invalid company /* 'Fake' companies used for networks */ - COMPANY_INACTIVE_CLIENT = 253, ///< The client is joining - COMPANY_NEW_COMPANY = 254, ///< The client wants a new company - COMPANY_SPECTATOR = 255, ///< The client is spectating + COMPANY_INACTIVE_CLIENT = 0xF7, ///< The client is joining + COMPANY_NEW_COMPANY = 0xF8, ///< The client wants a new company + COMPANY_SPECTATOR = 0xF9, ///< The client is spectating }; + + +const uint8_t COMPANY_SIZE_BITS = 8; /// Size of the company id in bits + +static_assert(COMPANY_SIZE_BITS <= 10); /// 32bit m9 can only fit 3 owners of size 10 + +static_assert(MAX_COMPANIES <= (1U << COMPANY_SIZE_BITS) - 1); /// Checking that MAX_COMPANIES is in bounds +static_assert(OWNER_END <= (1U << COMPANY_SIZE_BITS) - 1); +static_assert(INVALID_OWNER <= (1U << COMPANY_SIZE_BITS) - 1); +static_assert(INVALID_COMPANY <= (1U << COMPANY_SIZE_BITS) - 1); + DECLARE_POSTFIX_INCREMENT(Owner) DECLARE_ENUM_AS_ADDABLE(Owner) @@ -47,7 +65,7 @@ static const uint MAX_COMPETITORS_INTERVAL = 500; ///< The maximum interval (in typedef Owner CompanyID; -typedef uint16_t CompanyMask; +typedef std::bitset CompanyMask; struct Company; typedef uint32_t CompanyManagerFace; ///< Company manager face bits, info see in company_manager_face.h diff --git a/src/engine.cpp b/src/engine.cpp index 979c6a7e31..74f2928636 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -940,7 +940,7 @@ static IntervalTimer _calendar_engines_daily({TimerGameCalend CloseWindowById(WC_ENGINE_PREVIEW, i); e->preview_company = INVALID_COMPANY; } - } else if (CountBits(e->preview_asked) < MAX_COMPANIES) { + } else if (e->preview_asked.count() < MAX_COMPANIES) { e->preview_company = GetPreviewCompany(e); if (e->preview_company == INVALID_COMPANY) { @@ -969,7 +969,7 @@ static IntervalTimer _calendar_engines_daily({TimerGameCalend void ClearEnginesHiddenFlagOfCompany(CompanyID cid) { for (Engine *e : Engine::Iterate()) { - SB(e->company_hidden, cid, 1, 0); + e->company_hidden.reset(cid); } } @@ -987,7 +987,7 @@ CommandCost CmdSetVehicleVisibility(DoCommandFlag flags, EngineID engine_id, boo if (!IsEngineBuildable(e->index, e->type, _current_company)) return CMD_ERROR; if ((flags & DC_EXEC) != 0) { - SB(e->company_hidden, _current_company, 1, hide ? 1 : 0); + e->company_hidden.set(_current_company, hide ? 1 : 0); AddRemoveEngineFromAutoreplaceAndBuildWindows(e->type); } diff --git a/src/engine_base.h b/src/engine_base.h index de552bd9a7..4f545a7bd3 100644 --- a/src/engine_base.h +++ b/src/engine_base.h @@ -15,6 +15,7 @@ #include "core/pool_type.hpp" #include "newgrf_commons.h" #include "timer/timer_game_calendar.h" +#include struct WagonOverride { std::vector engines; @@ -47,11 +48,19 @@ struct Engine : EnginePool::PoolItem<&_engine_pool> { uint16_t duration_phase_2; ///< Second reliability phase in months, keeping #reliability_max. uint16_t duration_phase_3; ///< Third reliability phase in months, decaying to #reliability_final. uint8_t flags; ///< Flags of the engine. @see EngineFlags + CompanyMask preview_asked; ///< Bit for each company which has already been offered a preview. + uint16_t old_preview_asked; + CompanyID preview_company; ///< Company which is currently being offered a preview \c INVALID_COMPANY means no company. uint8_t preview_wait; ///< Daily countdown timer for timeout of offering the engine to the #preview_company company. + CompanyMask company_avail; ///< Bit for each company whether the engine is available for that company. + uint16_t old_company_avail; + CompanyMask company_hidden; ///< Bit for each company whether the engine is normally hidden in the build gui for that company. + uint16_t old_company_hidden; + uint8_t original_image_index; ///< Original vehicle image index, thus the image index of the overridden vehicle VehicleType type; ///< %Vehicle type, ie #VEH_ROAD, #VEH_TRAIN, etc. diff --git a/src/framerate_gui.cpp b/src/framerate_gui.cpp index 59325d3653..5fb0eb7179 100644 --- a/src/framerate_gui.cpp +++ b/src/framerate_gui.cpp @@ -217,7 +217,232 @@ namespace { PerformanceData(1), PerformanceData(1), PerformanceData(1), - PerformanceData(1), // PFE_AI14 + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), + PerformanceData(1), // PFE_AI239 }; } diff --git a/src/framerate_type.h b/src/framerate_type.h index 8dd84c29ce..fc05dd0813 100644 --- a/src/framerate_type.h +++ b/src/framerate_type.h @@ -75,8 +75,234 @@ enum PerformanceElement { PFE_AI12, ///< AI execution for player slot 13 PFE_AI13, ///< AI execution for player slot 14 PFE_AI14, ///< AI execution for player slot 15 + PFE_AI15, ///< AI execution for player slot 16 + PFE_AI16, ///< AI execution for player slot 17 + PFE_AI17, ///< AI execution for player slot 18 + PFE_AI18, ///< AI execution for player slot 19 + PFE_AI19, ///< AI execution for player slot 20 + PFE_AI20, ///< AI execution for player slot 21 + PFE_AI21, ///< AI execution for player slot 22 + PFE_AI22, ///< AI execution for player slot 23 + PFE_AI23, ///< AI execution for player slot 24 + PFE_AI24, ///< AI execution for player slot 25 + PFE_AI25, ///< AI execution for player slot 26 + PFE_AI26, ///< AI execution for player slot 27 + PFE_AI27, ///< AI execution for player slot 28 + PFE_AI28, ///< AI execution for player slot 29 + PFE_AI29, ///< AI execution for player slot 30 + PFE_AI30, ///< AI execution for player slot 31 + PFE_AI31, ///< AI execution for player slot 32 + PFE_AI32, ///< AI execution for player slot 33 + PFE_AI33, ///< AI execution for player slot 34 + PFE_AI34, ///< AI execution for player slot 35 + PFE_AI35, ///< AI execution for player slot 36 + PFE_AI36, ///< AI execution for player slot 37 + PFE_AI37, ///< AI execution for player slot 38 + PFE_AI38, ///< AI execution for player slot 39 + PFE_AI39, ///< AI execution for player slot 40 + PFE_AI40, ///< AI execution for player slot 41 + PFE_AI41, ///< AI execution for player slot 42 + PFE_AI42, ///< AI execution for player slot 43 + PFE_AI43, ///< AI execution for player slot 44 + PFE_AI44, ///< AI execution for player slot 45 + PFE_AI45, ///< AI execution for player slot 46 + PFE_AI46, ///< AI execution for player slot 47 + PFE_AI47, ///< AI execution for player slot 48 + PFE_AI48, ///< AI execution for player slot 49 + PFE_AI49, ///< AI execution for player slot 50 + PFE_AI50, ///< AI execution for player slot 51 + PFE_AI51, ///< AI execution for player slot 52 + PFE_AI52, ///< AI execution for player slot 53 + PFE_AI53, ///< AI execution for player slot 54 + PFE_AI54, ///< AI execution for player slot 55 + PFE_AI55, ///< AI execution for player slot 56 + PFE_AI56, ///< AI execution for player slot 57 + PFE_AI57, ///< AI execution for player slot 58 + PFE_AI58, ///< AI execution for player slot 59 + PFE_AI59, ///< AI execution for player slot 60 + PFE_AI60, ///< AI execution for player slot 61 + PFE_AI61, ///< AI execution for player slot 62 + PFE_AI62, ///< AI execution for player slot 63 + PFE_AI63, ///< AI execution for player slot 64 + PFE_AI64, ///< AI execution for player slot 65 + PFE_AI65, ///< AI execution for player slot 66 + PFE_AI66, ///< AI execution for player slot 67 + PFE_AI67, ///< AI execution for player slot 68 + PFE_AI68, ///< AI execution for player slot 69 + PFE_AI69, ///< AI execution for player slot 70 + PFE_AI70, ///< AI execution for player slot 71 + PFE_AI71, ///< AI execution for player slot 72 + PFE_AI72, ///< AI execution for player slot 73 + PFE_AI73, ///< AI execution for player slot 74 + PFE_AI74, ///< AI execution for player slot 75 + PFE_AI75, ///< AI execution for player slot 76 + PFE_AI76, ///< AI execution for player slot 77 + PFE_AI77, ///< AI execution for player slot 78 + PFE_AI78, ///< AI execution for player slot 79 + PFE_AI79, ///< AI execution for player slot 80 + PFE_AI80, ///< AI execution for player slot 81 + PFE_AI81, ///< AI execution for player slot 82 + PFE_AI82, ///< AI execution for player slot 83 + PFE_AI83, ///< AI execution for player slot 84 + PFE_AI84, ///< AI execution for player slot 85 + PFE_AI85, ///< AI execution for player slot 86 + PFE_AI86, ///< AI execution for player slot 87 + PFE_AI87, ///< AI execution for player slot 88 + PFE_AI88, ///< AI execution for player slot 89 + PFE_AI89, ///< AI execution for player slot 90 + PFE_AI90, ///< AI execution for player slot 91 + PFE_AI91, ///< AI execution for player slot 92 + PFE_AI92, ///< AI execution for player slot 93 + PFE_AI93, ///< AI execution for player slot 94 + PFE_AI94, ///< AI execution for player slot 95 + PFE_AI95, ///< AI execution for player slot 96 + PFE_AI96, ///< AI execution for player slot 97 + PFE_AI97, ///< AI execution for player slot 98 + PFE_AI98, ///< AI execution for player slot 99 + PFE_AI99, ///< AI execution for player slot 100 + PFE_AI100, ///< AI execution for player slot 101 + PFE_AI101, ///< AI execution for player slot 102 + PFE_AI102, ///< AI execution for player slot 103 + PFE_AI103, ///< AI execution for player slot 104 + PFE_AI104, ///< AI execution for player slot 105 + PFE_AI105, ///< AI execution for player slot 106 + PFE_AI106, ///< AI execution for player slot 107 + PFE_AI107, ///< AI execution for player slot 108 + PFE_AI108, ///< AI execution for player slot 109 + PFE_AI109, ///< AI execution for player slot 110 + PFE_AI110, ///< AI execution for player slot 111 + PFE_AI111, ///< AI execution for player slot 112 + PFE_AI112, ///< AI execution for player slot 113 + PFE_AI113, ///< AI execution for player slot 114 + PFE_AI114, ///< AI execution for player slot 115 + PFE_AI115, ///< AI execution for player slot 116 + PFE_AI116, ///< AI execution for player slot 117 + PFE_AI117, ///< AI execution for player slot 118 + PFE_AI118, ///< AI execution for player slot 119 + PFE_AI119, ///< AI execution for player slot 120 + PFE_AI120, ///< AI execution for player slot 121 + PFE_AI121, ///< AI execution for player slot 122 + PFE_AI122, ///< AI execution for player slot 123 + PFE_AI123, ///< AI execution for player slot 124 + PFE_AI124, ///< AI execution for player slot 125 + PFE_AI125, ///< AI execution for player slot 126 + PFE_AI126, ///< AI execution for player slot 127 + PFE_AI127, ///< AI execution for player slot 128 + PFE_AI128, ///< AI execution for player slot 129 + PFE_AI129, ///< AI execution for player slot 130 + PFE_AI130, ///< AI execution for player slot 131 + PFE_AI131, ///< AI execution for player slot 132 + PFE_AI132, ///< AI execution for player slot 133 + PFE_AI133, ///< AI execution for player slot 134 + PFE_AI134, ///< AI execution for player slot 135 + PFE_AI135, ///< AI execution for player slot 136 + PFE_AI136, ///< AI execution for player slot 137 + PFE_AI137, ///< AI execution for player slot 138 + PFE_AI138, ///< AI execution for player slot 139 + PFE_AI139, ///< AI execution for player slot 140 + PFE_AI140, ///< AI execution for player slot 141 + PFE_AI141, ///< AI execution for player slot 142 + PFE_AI142, ///< AI execution for player slot 143 + PFE_AI143, ///< AI execution for player slot 144 + PFE_AI144, ///< AI execution for player slot 145 + PFE_AI145, ///< AI execution for player slot 146 + PFE_AI146, ///< AI execution for player slot 147 + PFE_AI147, ///< AI execution for player slot 148 + PFE_AI148, ///< AI execution for player slot 149 + PFE_AI149, ///< AI execution for player slot 150 + PFE_AI150, ///< AI execution for player slot 151 + PFE_AI151, ///< AI execution for player slot 152 + PFE_AI152, ///< AI execution for player slot 153 + PFE_AI153, ///< AI execution for player slot 154 + PFE_AI154, ///< AI execution for player slot 155 + PFE_AI155, ///< AI execution for player slot 156 + PFE_AI156, ///< AI execution for player slot 157 + PFE_AI157, ///< AI execution for player slot 158 + PFE_AI158, ///< AI execution for player slot 159 + PFE_AI159, ///< AI execution for player slot 160 + PFE_AI160, ///< AI execution for player slot 161 + PFE_AI161, ///< AI execution for player slot 162 + PFE_AI162, ///< AI execution for player slot 163 + PFE_AI163, ///< AI execution for player slot 164 + PFE_AI164, ///< AI execution for player slot 165 + PFE_AI165, ///< AI execution for player slot 166 + PFE_AI166, ///< AI execution for player slot 167 + PFE_AI167, ///< AI execution for player slot 168 + PFE_AI168, ///< AI execution for player slot 169 + PFE_AI169, ///< AI execution for player slot 170 + PFE_AI170, ///< AI execution for player slot 171 + PFE_AI171, ///< AI execution for player slot 172 + PFE_AI172, ///< AI execution for player slot 173 + PFE_AI173, ///< AI execution for player slot 174 + PFE_AI174, ///< AI execution for player slot 175 + PFE_AI175, ///< AI execution for player slot 176 + PFE_AI176, ///< AI execution for player slot 177 + PFE_AI177, ///< AI execution for player slot 178 + PFE_AI178, ///< AI execution for player slot 179 + PFE_AI179, ///< AI execution for player slot 180 + PFE_AI180, ///< AI execution for player slot 181 + PFE_AI181, ///< AI execution for player slot 182 + PFE_AI182, ///< AI execution for player slot 183 + PFE_AI183, ///< AI execution for player slot 184 + PFE_AI184, ///< AI execution for player slot 185 + PFE_AI185, ///< AI execution for player slot 186 + PFE_AI186, ///< AI execution for player slot 187 + PFE_AI187, ///< AI execution for player slot 188 + PFE_AI188, ///< AI execution for player slot 189 + PFE_AI189, ///< AI execution for player slot 190 + PFE_AI190, ///< AI execution for player slot 191 + PFE_AI191, ///< AI execution for player slot 192 + PFE_AI192, ///< AI execution for player slot 193 + PFE_AI193, ///< AI execution for player slot 194 + PFE_AI194, ///< AI execution for player slot 195 + PFE_AI195, ///< AI execution for player slot 196 + PFE_AI196, ///< AI execution for player slot 197 + PFE_AI197, ///< AI execution for player slot 198 + PFE_AI198, ///< AI execution for player slot 199 + PFE_AI199, ///< AI execution for player slot 200 + PFE_AI200, ///< AI execution for player slot 201 + PFE_AI201, ///< AI execution for player slot 202 + PFE_AI202, ///< AI execution for player slot 203 + PFE_AI203, ///< AI execution for player slot 204 + PFE_AI204, ///< AI execution for player slot 205 + PFE_AI205, ///< AI execution for player slot 206 + PFE_AI206, ///< AI execution for player slot 207 + PFE_AI207, ///< AI execution for player slot 208 + PFE_AI208, ///< AI execution for player slot 209 + PFE_AI209, ///< AI execution for player slot 210 + PFE_AI210, ///< AI execution for player slot 211 + PFE_AI211, ///< AI execution for player slot 212 + PFE_AI212, ///< AI execution for player slot 213 + PFE_AI213, ///< AI execution for player slot 214 + PFE_AI214, ///< AI execution for player slot 215 + PFE_AI215, ///< AI execution for player slot 216 + PFE_AI216, ///< AI execution for player slot 217 + PFE_AI217, ///< AI execution for player slot 218 + PFE_AI218, ///< AI execution for player slot 219 + PFE_AI219, ///< AI execution for player slot 220 + PFE_AI220, ///< AI execution for player slot 221 + PFE_AI221, ///< AI execution for player slot 222 + PFE_AI222, ///< AI execution for player slot 223 + PFE_AI223, ///< AI execution for player slot 224 + PFE_AI224, ///< AI execution for player slot 225 + PFE_AI225, ///< AI execution for player slot 226 + PFE_AI226, ///< AI execution for player slot 227 + PFE_AI227, ///< AI execution for player slot 228 + PFE_AI228, ///< AI execution for player slot 229 + PFE_AI229, ///< AI execution for player slot 230 + PFE_AI230, ///< AI execution for player slot 231 + PFE_AI231, ///< AI execution for player slot 232 + PFE_AI232, ///< AI execution for player slot 233 + PFE_AI233, ///< AI execution for player slot 234 + PFE_AI234, ///< AI execution for player slot 235 + PFE_AI235, ///< AI execution for player slot 236 + PFE_AI236, ///< AI execution for player slot 237 + PFE_AI237, ///< AI execution for player slot 238 + PFE_AI238, ///< AI execution for player slot 239 + PFE_AI239, ///< AI execution for player slot 240 PFE_MAX, ///< End of enum, must be last. }; + DECLARE_POSTFIX_INCREMENT(PerformanceElement) /** Type used to hold a performance timing measurement */ diff --git a/src/graph_gui.cpp b/src/graph_gui.cpp index 9424144c4c..6070ac8061 100644 --- a/src/graph_gui.cpp +++ b/src/graph_gui.cpp @@ -7,6 +7,7 @@ /** @file graph_gui.cpp GUI that shows performance graphs. */ +#include "company_type.h" #include "stdafx.h" #include "graph_gui.h" #include "window_gui.h" @@ -166,7 +167,7 @@ struct ValuesInterval { struct BaseGraphWindow : Window { protected: - static const int GRAPH_MAX_DATASETS = 64; + static const int GRAPH_MAX_DATASETS = 300; static const int GRAPH_BASE_COLOUR = GREY_SCALE(2); static const int GRAPH_GRID_COLOUR = GREY_SCALE(3); static const int GRAPH_AXIS_LINE_COLOUR = GREY_SCALE(1); @@ -182,7 +183,7 @@ protected: static const int MIN_GRAPH_NUM_LINES_Y = 9; ///< Minimal number of horizontal lines to draw. static const int MIN_GRID_PIXEL_SIZE = 20; ///< Minimum distance between graph lines. - uint64_t excluded_data; ///< bitmask of the datasets that shouldn't be displayed. + CompanyMask excluded_data; ///< bitmask of the datasets that shouldn't be displayed. uint8_t num_dataset; uint8_t num_on_x_axis; uint8_t num_vert_lines; diff --git a/src/industry_map.h b/src/industry_map.h index ee45ade7c9..0f6021527f 100644 --- a/src/industry_map.h +++ b/src/industry_map.h @@ -10,7 +10,9 @@ #ifndef INDUSTRY_MAP_H #define INDUSTRY_MAP_H +#include "company_type.h" #include "industrytype.h" +#include "tile_map.h" #include "water_map.h" @@ -100,7 +102,7 @@ inline void SetIndustryCompleted(Tile tile) inline uint8_t GetIndustryConstructionStage(Tile tile) { assert(IsTileType(tile, MP_INDUSTRY)); - return IsIndustryCompleted(tile) ? (uint8_t)INDUSTRY_COMPLETED : GB(tile.m1(), 0, 2); + return IsIndustryCompleted(tile) ? (uint8_t)INDUSTRY_COMPLETED : GB(tile.m1(), 0, 2); // MYTODO: Figure this out, seams like it would read bits of the owner } /** @@ -286,6 +288,8 @@ inline void MakeIndustry(Tile t, IndustryID index, IndustryGfx gfx, uint8_t rand SetIndustryTriggers(t, 0); // rest of m6 SetWaterClass(t, wc); t.m7() = 0; + t.m8() = 0; + t.m9() = 0; } #endif /* INDUSTRY_MAP_H */ diff --git a/src/map_func.h b/src/map_func.h index 7d3e11cd80..c85ac32795 100644 --- a/src/map_func.h +++ b/src/map_func.h @@ -10,6 +10,8 @@ #ifndef MAP_FUNC_H #define MAP_FUNC_H +#include "company_type.h" +#include "core/bitmath_func.hpp" #include "core/math_func.hpp" #include "tile_type.h" #include "map_type.h" @@ -33,7 +35,7 @@ private: uint8_t type; ///< The type (bits 4..7), bridges (2..3), rainforest/desert (0..1) uint8_t height; ///< The height of the northern corner. uint16_t m2; ///< Primarily used for indices to towns, industries and stations - uint8_t m1; ///< Primarily used for ownership information + uint8_t m1; ///< Primarily used for ownership information (In old versions) uint8_t m3; ///< General purpose uint8_t m4; ///< General purpose uint8_t m5; ///< General purpose @@ -49,6 +51,7 @@ private: uint8_t m6; ///< General purpose uint8_t m7; ///< Primarily used for newgrf support uint16_t m8; ///< General purpose + uint32_t m9; ///< Stores the actuall ownership information }; static TileBase *base_tiles; ///< Pointer to the tile-array. @@ -198,6 +201,18 @@ public: { return extended_tiles[tile.base()].m8; } + + /** + * Primarily used for ownership information + * TODO: Add more docs + * Look at docs/landscape.html for the exact meaning of the data. + * @param tile The tile to get the data for. + * @return reference to the byte holding the data. + */ + debug_inline uint32_t &m9() + { + return extended_tiles[tile.base()].m9; + } }; /** diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 1b3d6778c8..bbea2ea285 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -130,6 +130,7 @@ public: Debug(misc, LANDINFOD_LEVEL, "m6 = 0x{:x}", tile.m6()); Debug(misc, LANDINFOD_LEVEL, "m7 = 0x{:x}", tile.m7()); Debug(misc, LANDINFOD_LEVEL, "m8 = 0x{:x}", tile.m8()); + Debug(misc, LANDINFOD_LEVEL, "m9 = 0x{:x}", tile.m9()); PrintWaterRegionDebugInfo(tile); #undef LANDINFOD_LEVEL diff --git a/src/newgrf_town.cpp b/src/newgrf_town.cpp index d144d56561..75227b788c 100644 --- a/src/newgrf_town.cpp +++ b/src/newgrf_town.cpp @@ -83,8 +83,9 @@ case 0xAB: return GB(this->t->ratings[6], 8, 8); case 0xAC: return this->t->ratings[7]; case 0xAD: return GB(this->t->ratings[7], 8, 8); - case 0xAE: return this->t->have_ratings; - case 0xB2: return this->t->statues; + // MYTODO: Fix this crap later + //case 0xAE: return this->t->have_ratings; + //case 0xB2: return this->t->statues; case 0xB6: return ClampTo(this->t->cache.num_houses); case 0xB9: return this->t->growth_rate / Ticks::TOWN_GROWTH_TICKS; case 0xBA: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? ClampTo(this->t->supplied[cid].new_max) : 0; diff --git a/src/rail_map.h b/src/rail_map.h index 5ff2fb9ec3..7b2170e3ed 100644 --- a/src/rail_map.h +++ b/src/rail_map.h @@ -552,8 +552,9 @@ inline void SetRailDepotExitDirection(Tile tile, DiagDirection dir) inline void MakeRailDepot(Tile tile, Owner owner, DepotID depot_id, DiagDirection dir, RailType rail_type) { SetTileType(tile, MP_RAILWAY); - SetTileOwner(tile, owner); SetDockingTile(tile, false); + SetTileOwner(tile, owner); + tile.m1() = 0; tile.m2() = depot_id; tile.m3() = 0; tile.m4() = 0; diff --git a/src/road_map.h b/src/road_map.h index 9179579b4c..e5b3a01ceb 100644 --- a/src/road_map.h +++ b/src/road_map.h @@ -10,6 +10,7 @@ #ifndef ROAD_MAP_H #define ROAD_MAP_H +#include "company_type.h" #include "track_func.h" #include "depot_type.h" #include "rail_type.h" @@ -231,7 +232,7 @@ inline bool HasTileAnyRoadType(Tile t, RoadTypes rts) * @param rtt RoadTramType. * @return Owner of the given road type. */ -inline Owner GetRoadOwner(Tile t, RoadTramType rtt) +inline Owner OldGetRoadOwner(Tile t, RoadTramType rtt) { assert(MayHaveRoad(t)); if (rtt == RTT_ROAD) return (Owner)GB(IsNormalRoadTile(t) ? t.m1() : t.m7(), 0, 5); @@ -239,6 +240,21 @@ inline Owner GetRoadOwner(Tile t, RoadTramType rtt) /* Trams don't need OWNER_TOWN, and remapping OWNER_NONE * to OWNER_TOWN makes it use one bit less */ Owner o = (Owner)GB(t.m3(), 4, 4); + return o == OLD_OWNER_TOWN ? OLD_OWNER_NONE : o; +} + +/** + * Get the owner of a specific road type. + * @param t The tile to query. + * @param rtt RoadTramType. + * @return Owner of the given road type. + */ +inline Owner GetRoadOwner(Tile t, RoadTramType rtt) +{ + assert(MayHaveRoad(t)); + if (rtt == RTT_ROAD) return (Owner)GB(t.m9(), IsNormalRoadTile(t) ? 0 : COMPANY_SIZE_BITS * 2, COMPANY_SIZE_BITS); + + Owner o = (Owner)GB(t.m9(), COMPANY_SIZE_BITS, COMPANY_SIZE_BITS); return o == OWNER_TOWN ? OWNER_NONE : o; } @@ -249,11 +265,26 @@ inline Owner GetRoadOwner(Tile t, RoadTramType rtt) * @param o New owner of the given road type. */ inline void SetRoadOwner(Tile t, RoadTramType rtt, Owner o) +{ + if (rtt == RTT_ROAD) { + SB(t.m9(), IsNormalRoadTile(t) ? 0 : COMPANY_SIZE_BITS * 2, COMPANY_SIZE_BITS, o); + } else { + SB(t.m9(), COMPANY_SIZE_BITS, COMPANY_SIZE_BITS, o==OWNER_NONE ? OWNER_TOWN : o); + } +} + +/** + * Set the owner of a specific road type. + * @param t The tile to change. + * @param rtt RoadTramType. + * @param o New owner of the given road type. + */ +inline void OldSetRoadOwner(Tile t, RoadTramType rtt, Owner o) { if (rtt == RTT_ROAD) { SB(IsNormalRoadTile(t) ? t.m1() : t.m7(), 0, 5, o); } else { - SB(t.m3(), 4, 4, o == OWNER_NONE ? OWNER_TOWN : o); + SB(t.m3(), 4, 4, o == OLD_OWNER_NONE ? OLD_OWNER_TOWN : o); } } diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 4771490268..78f14c4a74 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -63,11 +63,16 @@ #include "../timer/timer_game_economy.h" #include "../timer/timer_game_tick.h" +#include "company_type.h" +#include "road_map.h" +#include "saveload/saveload.h" #include "saveload_internal.h" #include #include "../safeguards.h" +#include "tile_map.h" +#include "tile_type.h" extern Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY); @@ -163,7 +168,7 @@ static void ConvertTownOwner() [[fallthrough]]; case MP_TUNNELBRIDGE: - if (tile.m1() & 0x80) SetTileOwner(tile, OWNER_TOWN); + if (tile.m1() & 0x80) OldSetTileOwner(tile, OWNER_TOWN); break; default: break; @@ -421,7 +426,7 @@ static void CDECL HandleSavegameLoadCrash(int signum) */ static void FixOwnerOfRailTrack(Tile t) { - assert(!Company::IsValidID(GetTileOwner(t)) && (IsLevelCrossingTile(t) || IsPlainRailTile(t))); + assert(!Company::IsValidID(OldGetTileOwner(t)) && (IsLevelCrossingTile(t) || IsPlainRailTile(t))); /* remove leftover rail piece from crossing (from very old savegames) */ Train *v = nullptr; @@ -434,7 +439,7 @@ static void FixOwnerOfRailTrack(Tile t) if (v != nullptr) { /* when there is a train on crossing (it could happen in TTD), set owner of crossing to train owner */ - SetTileOwner(t, v->owner); + OldSetTileOwner(t, v->owner); return; } @@ -443,27 +448,27 @@ static void FixOwnerOfRailTrack(Tile t) TileIndex tt = t + TileOffsByDiagDir(dd); if (GetTileTrackStatus(t, TRANSPORT_RAIL, 0, dd) != 0 && GetTileTrackStatus(tt, TRANSPORT_RAIL, 0, ReverseDiagDir(dd)) != 0 && - Company::IsValidID(GetTileOwner(tt))) { - SetTileOwner(t, GetTileOwner(tt)); + Company::IsValidID(OldGetTileOwner(tt))) { + OldSetTileOwner(t, OldGetTileOwner(tt)); return; } } if (IsLevelCrossingTile(t)) { /* else change the crossing to normal road (road vehicles won't care) */ - Owner road = GetRoadOwner(t, RTT_ROAD); - Owner tram = GetRoadOwner(t, RTT_TRAM); + Owner road = OldGetRoadOwner(t, RTT_ROAD); + Owner tram = OldGetRoadOwner(t, RTT_TRAM); RoadBits bits = GetCrossingRoadBits(t); bool hasroad = HasBit(t.m7(), 6); bool hastram = HasBit(t.m7(), 7); /* MakeRoadNormal */ SetTileType(t, MP_ROAD); - SetTileOwner(t, road); + OldSetTileOwner(t, road); t.m3() = (hasroad ? bits : 0); t.m5() = (hastram ? bits : 0) | ROAD_TILE_NORMAL << 6; SB(t.m6(), 2, 4, 0); - SetRoadOwner(t, RTT_TRAM, tram); + OldSetRoadOwner(t, RTT_TRAM, tram); return; } @@ -471,6 +476,7 @@ static void FixOwnerOfRailTrack(Tile t) MakeClear(t, CLEAR_GRASS, 0); } + /** * Fixes inclination of a vehicle. Older OpenTTD versions didn't update the bits correctly. * @param v vehicle @@ -656,8 +662,8 @@ bool AfterLoadGame() * walk through the whole map.. */ if (IsSavegameVersionBefore(SLV_4, 3)) { for (auto t : Map::Iterate()) { - if (IsTileType(t, MP_WATER) && GetTileOwner(t) >= MAX_COMPANIES) { - SetTileOwner(t, OWNER_WATER); + if (IsTileType(t, MP_WATER) && OldGetTileOwner(t) >= OLD_MAX_COMPANIES) { + OldSetTileOwner(t, OWNER_WATER); } } } @@ -858,7 +864,7 @@ bool AfterLoadGame() default: break; case MP_WATER: - if (GetWaterTileType(t) == WATER_TILE_LOCK && GetTileOwner(t) == OWNER_WATER) SetTileOwner(t, OWNER_NONE); + if (GetWaterTileType(t) == WATER_TILE_LOCK && OldGetTileOwner(t) == OWNER_WATER) OldSetTileOwner(t, OWNER_NONE); break; case MP_STATION: { @@ -913,7 +919,7 @@ bool AfterLoadGame() BaseStation *bst = BaseStation::GetByTile(t); /* Sanity check */ - if (!IsBuoy(t) && bst->owner != GetTileOwner(t)) SlErrorCorrupt("Wrong owner for station tile"); + if (!IsBuoy(t) && bst->owner != OldGetTileOwner(t)) SlErrorCorrupt("Wrong owner for station tile"); /* Set up station spread */ bst->rect.BeforeAddTile(t, StationRect::ADD_FORCE); @@ -986,7 +992,7 @@ bool AfterLoadGame() case MP_ROAD: t.m4() |= (t.m2() << 4); - if ((GB(t.m5(), 4, 2) == ROAD_TILE_CROSSING ? (Owner)t.m3() : GetTileOwner(t)) == OWNER_TOWN) { + if ((GB(t.m5(), 4, 2) == ROAD_TILE_CROSSING ? (Owner)t.m3() : OldGetTileOwner(t)) == OLD_OWNER_TOWN) { SetTownIndex(t, CalcClosestTownFromTile(t)->index); } else { SetTownIndex(t, 0); @@ -1139,7 +1145,7 @@ bool AfterLoadGame() if (!IsRoadStop(t)) break; if (fix_roadtypes) SB(t.m7(), 6, 2, (RoadTypes)GB(t.m3(), 0, 3)); - SB(t.m7(), 0, 5, HasBit(t.m6(), 2) ? OWNER_TOWN : GetTileOwner(t)); + SB(t.m7(), 0, 5, HasBit(t.m6(), 2) ? OWNER_TOWN : OldGetTileOwner(t)); SB(t.m3(), 4, 4, t.m1()); t.m4() = 0; break; @@ -1149,9 +1155,9 @@ bool AfterLoadGame() if (((old_bridge && IsBridge(t)) ? (TransportType)GB(t.m5(), 1, 2) : GetTunnelBridgeTransportType(t)) == TRANSPORT_ROAD) { if (fix_roadtypes) SB(t.m7(), 6, 2, (RoadTypes)GB(t.m3(), 0, 3)); - Owner o = GetTileOwner(t); + Owner o = OldGetTileOwner(t); SB(t.m7(), 0, 5, o); // road owner - SB(t.m3(), 4, 4, o == OWNER_NONE ? OWNER_TOWN : o); // tram owner + SB(t.m3(), 4, 4, o == OLD_OWNER_NONE ? OWNER_TOWN : o); // tram owner } SB(t.m6(), 2, 4, GB(t.m2(), 4, 4)); // bridge type SB(t.m7(), 5, 1, GB(t.m4(), 7, 1)); // snow/desert @@ -1208,12 +1214,12 @@ bool AfterLoadGame() if (GB(t.m5(), 3, 2) == TRANSPORT_RAIL) { MakeRailNormal( t, - GetTileOwner(t), + OldGetTileOwner(t), axis == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X, GetRailType(t) ); } else { - TownID town = IsTileOwner(t, OWNER_TOWN) ? ClosestTownFromTile(t, UINT_MAX)->index : 0; + TownID town = IsTileOwner(t, OLD_OWNER_TOWN) ? ClosestTownFromTile(t, UINT_MAX)->index : 0; /* MakeRoadNormal */ SetTileType(t, MP_ROAD); @@ -1222,7 +1228,7 @@ bool AfterLoadGame() t.m5() = (axis == AXIS_X ? ROAD_Y : ROAD_X) | ROAD_TILE_NORMAL << 6; SB(t.m6(), 2, 4, 0); t.m7() = 1 << 6; - SetRoadOwner(t, RTT_TRAM, OWNER_NONE); + OldSetRoadOwner(t, RTT_TRAM, OWNER_NONE); } } else { if (GB(t.m5(), 3, 2) == 0) { @@ -1231,10 +1237,10 @@ bool AfterLoadGame() if (!IsTileFlat(t)) { MakeShore(t); } else { - if (GetTileOwner(t) == OWNER_WATER) { + if (OldGetTileOwner(t) == OWNER_WATER) { MakeSea(t); } else { - MakeCanal(t, GetTileOwner(t), Random()); + MakeCanal(t, OldGetTileOwner(t), Random()); } } } @@ -1568,7 +1574,7 @@ bool AfterLoadGame() * be OWNER_NONE. So replace OWNER_NONE with OWNER_WATER. */ if (IsSavegameVersionBefore(SLV_46)) { for (Waypoint *wp : Waypoint::Iterate()) { - if ((wp->facilities & FACIL_DOCK) != 0 && IsTileOwner(wp->xy, OWNER_NONE) && TileHeight(wp->xy) == 0) SetTileOwner(wp->xy, OWNER_WATER); + if ((wp->facilities & FACIL_DOCK) != 0 && IsTileOwner(wp->xy, OLD_OWNER_NONE) && TileHeight(wp->xy) == 0) OldSetTileOwner(wp->xy, OWNER_WATER); } } @@ -1678,9 +1684,9 @@ bool AfterLoadGame() for (auto t : Map::Iterate()) { if (IsTileType(t, MP_WATER) && GetWaterTileType(t) == WATER_TILE_CLEAR && - GetTileOwner(t) == OWNER_WATER && + OldGetTileOwner(t) == OWNER_WATER && TileHeight(t) != 0) { - SetTileOwner(t, OWNER_NONE); + OldSetTileOwner(t, OWNER_NONE); } } } @@ -1828,7 +1834,7 @@ bool AfterLoadGame() if (IsTileType(t, MP_WATER)) { if (GetWaterClass(t) != WATER_CLASS_RIVER) { if (IsWater(t)) { - Owner o = GetTileOwner(t); + Owner o = OldGetTileOwner(t); if (o == OWNER_WATER) { MakeSea(t); } else { @@ -1864,8 +1870,8 @@ bool AfterLoadGame() } if (IsBuoyTile(t) || IsDriveThroughStopTile(t) || IsTileType(t, MP_WATER)) { - Owner o = GetTileOwner(t); - if (o < MAX_COMPANIES && !Company::IsValidID(o)) { + Owner o = OldGetTileOwner(t); + if (o < OLD_MAX_COMPANIES && !Company::IsValidID(o)) { Backup cur_company(_current_company, o); ChangeTileOwner(t, o, INVALID_OWNER); cur_company.Restore(); @@ -1879,14 +1885,14 @@ bool AfterLoadGame() /* works for all RoadTileType */ for (RoadTramType rtt : _roadtramtypes) { /* update even non-existing road types to update tile owner too */ - Owner o = GetRoadOwner(t, rtt); - if (o < MAX_COMPANIES && !Company::IsValidID(o)) SetRoadOwner(t, rtt, OWNER_NONE); + Owner o = OldGetRoadOwner(t, rtt); + if (o < OLD_MAX_COMPANIES && !Company::IsValidID(o)) OldSetRoadOwner(t, rtt, OWNER_NONE); } if (IsLevelCrossing(t)) { - if (!Company::IsValidID(GetTileOwner(t))) FixOwnerOfRailTrack(t); + if (!Company::IsValidID(OldGetTileOwner(t))) FixOwnerOfRailTrack(t); } } else if (IsPlainRailTile(t)) { - if (!Company::IsValidID(GetTileOwner(t))) FixOwnerOfRailTrack(t); + if (!Company::IsValidID(OldGetTileOwner(t))) FixOwnerOfRailTrack(t); } } } @@ -1996,7 +2002,7 @@ bool AfterLoadGame() /* signs with invalid owner left from older savegames */ for (Sign *si : Sign::Iterate()) { - if (si->owner != OWNER_NONE && !Company::IsValidID(si->owner)) si->owner = OWNER_NONE; + if (si->owner != OLD_OWNER_NONE && !Company::IsValidID(si->owner)) si->owner = OWNER_NONE; } /* Station can get named based on an industry type, but the current ones @@ -2025,7 +2031,7 @@ bool AfterLoadGame() for (Town *t : Town::Iterate()) { if (t->have_ratings == 0xFF) t->have_ratings = MAX_UVALUE(CompanyMask); - for (uint i = 8; i != MAX_COMPANIES; i++) t->ratings[i] = RATING_INITIAL; + for (uint i = 8; i != OLD_MAX_COMPANIES; i++) t->ratings[i] = RATING_INITIAL; } } @@ -2407,7 +2413,6 @@ bool AfterLoadGame() /* We need to properly number/name the depots. * The first step is making sure none of the depots uses the * 'default' names, after that we can assign the names. */ - for (Depot *d : Depot::Iterate()) d->town_cn = UINT16_MAX; for (Depot *d : Depot::Iterate()) MakeDefaultName(d); } @@ -2473,8 +2478,8 @@ bool AfterLoadGame() /* Add (random) colour to all objects. */ if (IsSavegameVersionBefore(SLV_148)) { for (Object *o : Object::Iterate()) { - Owner owner = GetTileOwner(o->location.tile); - o->colour = (owner == OWNER_NONE) ? static_cast(GB(Random(), 0, 4)) : Company::Get(owner)->livery->colour1; + Owner owner = OldGetTileOwner(o->location.tile); + o->colour = (owner == OLD_OWNER_NONE) ? static_cast(GB(Random(), 0, 4)) : Company::Get(owner)->livery->colour1; } } @@ -2841,9 +2846,9 @@ bool AfterLoadGame() if (IsSavegameVersionBefore(SLV_172)) { for (auto t : Map::Iterate()) { if (!IsBayRoadStopTile(t)) continue; - Owner o = GetTileOwner(t); - SetRoadOwner(t, RTT_ROAD, o); - SetRoadOwner(t, RTT_TRAM, o); + Owner o = OldGetTileOwner(t); + OldSetRoadOwner(t, RTT_ROAD, o); + OldSetRoadOwner(t, RTT_TRAM, o); } } @@ -3262,6 +3267,27 @@ bool AfterLoadGame() if (IsSavegameVersionBefore(SLV_SCRIPT_RANDOMIZER)) { ScriptObject::InitializeRandomizers(); } + if (IsSavegameVersionBefore(SLV_MORE_COMPANIES)) { + for (auto t : Map::Iterate()) { + //SB(t.m9(), 0, COMPANY_SIZE_BITS, OWNER_NONE); + if (!IsValidTile(t)) { + continue; + } + if (!IsTileType(t, MP_HOUSE) + && !IsTileType(t, MP_INDUSTRY)) { + Owner o =OldGetTileOwner(t) ; + o = ParseOldOwner(o); + SetTileOwner(t, o); + } + if (MayHaveRoad(t)) { + for (RoadTramType rtt : _roadtramtypes) { + Owner o = OldGetRoadOwner(t, rtt); + o = ParseOldOwner(o); + SetRoadOwner(t, rtt, o); + } + } + } + } for (Company *c : Company::Iterate()) { UpdateCompanyLiveries(c); diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp index 651daa1bcb..ae58efb6b2 100644 --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -475,9 +475,11 @@ static const SaveLoad _company_desc[] = { SLE_CONDVAR(CompanyProperties, num_valid_stat_ent, SLE_UINT8, SL_MIN_VERSION, SLV_SAVELOAD_LIST_LENGTH), - SLE_VAR(CompanyProperties, months_of_bankruptcy, SLE_UINT8), - SLE_CONDVAR(CompanyProperties, bankrupt_asked, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104), - SLE_CONDVAR(CompanyProperties, bankrupt_asked, SLE_UINT16, SLV_104, SL_MAX_VERSION), + SLE_VAR(CompanyProperties, months_of_bankruptcy, SLE_UINT8), +SLE_CONDVARNAME(CompanyProperties, old_bankrupt_asked, "bankrupt_asked", SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104), +SLE_CONDVARNAME(CompanyProperties, old_bankrupt_asked, "bankrupt_asked", SLE_UINT16, SLV_104, SLV_MORE_COMPANIES), +SLE_CONDCOMPMASK(CompanyProperties, bankrupt_asked, MAX_COMPANIES, SLV_MORE_COMPANIES, SL_MAX_VERSION), + SLE_VAR(CompanyProperties, bankrupt_timeout, SLE_INT16), SLE_CONDVAR(CompanyProperties, bankrupt_value, SLE_VAR_I64 | SLE_FILE_I32, SL_MIN_VERSION, SLV_65), SLE_CONDVAR(CompanyProperties, bankrupt_value, SLE_INT64, SLV_65, SL_MAX_VERSION), @@ -520,6 +522,9 @@ struct PLYRChunkHandler : ChunkHandler { Company *c = new (index) Company(); SlObject(c, slt); _company_colours[index] = c->colour; + if (IsSavegameVersionBefore(SLV_MORE_COMPANIES)) { + c->bankrupt_asked = ParseOldCompMask(c->old_bankrupt_asked); + } } } diff --git a/src/saveload/engine_sl.cpp b/src/saveload/engine_sl.cpp index ab62d756a8..987fd93fd5 100644 --- a/src/saveload/engine_sl.cpp +++ b/src/saveload/engine_sl.cpp @@ -9,6 +9,7 @@ #include "../stdafx.h" +#include "company_type.h" #include "saveload.h" #include "compat/engine_sl_compat.h" @@ -19,25 +20,32 @@ #include "../safeguards.h" static const SaveLoad _engine_desc[] = { - SLE_CONDVAR(Engine, intro_date, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31), - SLE_CONDVAR(Engine, intro_date, SLE_INT32, SLV_31, SL_MAX_VERSION), - SLE_CONDVAR(Engine, age, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31), - SLE_CONDVAR(Engine, age, SLE_INT32, SLV_31, SL_MAX_VERSION), - SLE_VAR(Engine, reliability, SLE_UINT16), - SLE_VAR(Engine, reliability_spd_dec, SLE_UINT16), - SLE_VAR(Engine, reliability_start, SLE_UINT16), - SLE_VAR(Engine, reliability_max, SLE_UINT16), - SLE_VAR(Engine, reliability_final, SLE_UINT16), - SLE_VAR(Engine, duration_phase_1, SLE_UINT16), - SLE_VAR(Engine, duration_phase_2, SLE_UINT16), - SLE_VAR(Engine, duration_phase_3, SLE_UINT16), - SLE_VAR(Engine, flags, SLE_UINT8), - SLE_CONDVAR(Engine, preview_asked, SLE_UINT16, SLV_179, SL_MAX_VERSION), - SLE_CONDVAR(Engine, preview_company, SLE_UINT8, SLV_179, SL_MAX_VERSION), - SLE_VAR(Engine, preview_wait, SLE_UINT8), - SLE_CONDVAR(Engine, company_avail, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104), - SLE_CONDVAR(Engine, company_avail, SLE_UINT16, SLV_104, SL_MAX_VERSION), - SLE_CONDVAR(Engine, company_hidden, SLE_UINT16, SLV_193, SL_MAX_VERSION), + SLE_CONDVAR(Engine, intro_date, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31), + SLE_CONDVAR(Engine, intro_date, SLE_INT32, SLV_31, SL_MAX_VERSION), + SLE_CONDVAR(Engine, age, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31), + SLE_CONDVAR(Engine, age, SLE_INT32, SLV_31, SL_MAX_VERSION), + SLE_VAR(Engine, reliability, SLE_UINT16), + SLE_VAR(Engine, reliability_spd_dec, SLE_UINT16), + SLE_VAR(Engine, reliability_start, SLE_UINT16), + SLE_VAR(Engine, reliability_max, SLE_UINT16), + SLE_VAR(Engine, reliability_final, SLE_UINT16), + SLE_VAR(Engine, duration_phase_1, SLE_UINT16), + SLE_VAR(Engine, duration_phase_2, SLE_UINT16), + SLE_VAR(Engine, duration_phase_3, SLE_UINT16), + SLE_VAR(Engine, flags, SLE_UINT8), + + SLE_CONDVARNAME(Engine, old_preview_asked, "preview_asked", SLE_UINT16, SLV_179, SLV_MORE_COMPANIES), +SLE_CONDCOMPMASK(Engine, preview_asked, MAX_COMPANIES, SLV_MORE_COMPANIES, SL_MAX_VERSION), + + SLE_CONDVAR(Engine, preview_company, SLE_UINT8, SLV_179, SL_MAX_VERSION), + SLE_VAR(Engine, preview_wait, SLE_UINT8), + + SLE_CONDVARNAME(Engine, old_company_avail, "company_avail", SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104), + SLE_CONDVARNAME(Engine, old_company_avail, "company_avail", SLE_UINT16, SLV_104, SLV_MORE_COMPANIES), +SLE_CONDCOMPMASK(Engine, company_avail, MAX_COMPANIES, SLV_MORE_COMPANIES, SL_MAX_VERSION), + +SLE_CONDCOMPMASK(Engine, company_hidden, MAX_COMPANIES, SLV_MORE_COMPANIES, SL_MAX_VERSION), + SLE_CONDVARNAME(Engine, old_company_hidden, "company_hidden", SLE_UINT16, SLV_193, SLV_MORE_COMPANIES), SLE_CONDSSTR(Engine, name, SLE_STR, SLV_84, SL_MAX_VERSION), }; @@ -111,6 +119,11 @@ struct ENGNChunkHandler : ChunkHandler { e->preview_company = INVALID_COMPANY; e->preview_asked = MAX_UVALUE(CompanyMask); } + if (IsSavegameVersionBefore(SLV_MORE_COMPANIES)) { + e->preview_asked = ParseOldCompMask(e->old_preview_asked); + e->company_avail = ParseOldCompMask(e->old_company_avail); + e->company_hidden = ParseOldCompMask(e->old_company_hidden); + } } } }; diff --git a/src/saveload/group_sl.cpp b/src/saveload/group_sl.cpp index 82ef465e08..e4e8674671 100644 --- a/src/saveload/group_sl.cpp +++ b/src/saveload/group_sl.cpp @@ -54,6 +54,9 @@ struct GRPSChunkHandler : ChunkHandler { SlObject(g, slt); if (IsSavegameVersionBefore(SLV_189)) g->parent = INVALID_GROUP; + if (IsSavegameVersionBefore(SLV_MORE_COMPANIES)) { + g->owner = ParseOldOwner(g->owner); + } } } }; diff --git a/src/saveload/industry_sl.cpp b/src/saveload/industry_sl.cpp index 6edea24e05..5cfdf58404 100644 --- a/src/saveload/industry_sl.cpp +++ b/src/saveload/industry_sl.cpp @@ -9,6 +9,7 @@ #include "../stdafx.h" +#include "company_type.h" #include "saveload.h" #include "compat/industry_sl_compat.h" @@ -265,6 +266,12 @@ struct INDYChunkHandler : ChunkHandler { } else if (IsSavegameVersionBefore(SLV_INDUSTRY_CARGO_REORGANISE)) { LoadMoveAcceptsProduced(i, INDUSTRY_NUM_INPUTS, INDUSTRY_NUM_OUTPUTS); } + if (IsSavegameVersionBefore(SLV_MORE_COMPANIES)) { + i->owner = ParseOldOwner(i-> owner); + i->founder = ParseOldOwner(i-> founder); + i->exclusive_supplier = ParseOldOwner(i-> exclusive_supplier); + i->exclusive_consumer = ParseOldOwner(i-> exclusive_consumer); + } Industry::IncIndustryTypeCount(i->type); } } diff --git a/src/saveload/map_sl.cpp b/src/saveload/map_sl.cpp index 3ce23a42b2..5869f823b4 100644 --- a/src/saveload/map_sl.cpp +++ b/src/saveload/map_sl.cpp @@ -17,6 +17,7 @@ #include "../fios.h" #include "../safeguards.h" +#include static uint32_t _map_dim_x; static uint32_t _map_dim_y; @@ -128,10 +129,10 @@ struct MAPOChunkHandler : ChunkHandler { std::array buf; uint size = Map::Size(); - for (TileIndex i = 0; i != size;) { - SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); - for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) Tile(i++).m1() = buf[j]; - } + for (TileIndex i = 0; i != size;) { + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) Tile(i++).m1() = buf[j]; + } } void Save() const override @@ -352,6 +353,34 @@ struct MAP8ChunkHandler : ChunkHandler { } }; +struct MAP9ChunkHandler : ChunkHandler { + MAP9ChunkHandler() : ChunkHandler('MAP9', CH_RIFF) {} + + void Load() const override + { + std::array buf; + uint size = Map::Size(); + + for (TileIndex i = 0; i != size;) { + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT32); + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) Tile(i++).m9() = buf[j]; + } + } + + void Save() const override + { + std::array buf; + uint size = Map::Size(); + + std::cout<< "loading m9" << std::endl; + SlSetLength(static_cast(size) * sizeof(uint32_t)); + for (TileIndex i = 0; i != size;) { + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = Tile(i++).m9(); + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT32); + } + } +}; + static const MAPSChunkHandler MAPS; static const MAPTChunkHandler MAPT; static const MAPHChunkHandler MAPH; @@ -363,6 +392,7 @@ static const MAP5ChunkHandler MAP5; static const MAPEChunkHandler MAPE; static const MAP7ChunkHandler MAP7; static const MAP8ChunkHandler MAP8; +static const MAP9ChunkHandler MAP9; static const ChunkHandlerRef map_chunk_handlers[] = { MAPS, MAPT, @@ -375,6 +405,7 @@ static const ChunkHandlerRef map_chunk_handlers[] = { MAPE, MAP7, MAP8, + MAP9, }; extern const ChunkHandlerTable _map_chunk_handlers(map_chunk_handlers); diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp index 538c1336c3..9985bccb57 100644 --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -253,6 +253,7 @@ static bool FixTTOMapArray() break; case 1: // ROAD_TILE_CROSSING (there aren't monorail crossings in TTO) tile.m3() = tile.m1(); // set owner of road = owner of rail + // TODO: Fix this break; case 2: // ROAD_TILE_DEPOT break; diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 6155e3723d..20ba938eac 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -20,6 +20,7 @@ * */ +#include "saveload/saveload.h" #include "../stdafx.h" #include "../debug.h" #include "../station_base.h" @@ -42,7 +43,13 @@ #include "../string_func.h" #include "../fios.h" #include "../error.h" +#include "company_type.h" +#include "core/bitmath_func.hpp" #include +#include +#include +#include +#include #ifdef __EMSCRIPTEN__ # include #endif @@ -53,6 +60,7 @@ #include "saveload_filter.h" #include "../safeguards.h" +#include extern const SaveLoadVersion SAVEGAME_VERSION = (SaveLoadVersion)(SL_MAX_VERSION - 1); ///< Current savegame version of OpenTTD. @@ -558,6 +566,7 @@ static uint8_t GetSavegameFileType(const SaveLoad &sld) case SL_STDSTR: case SL_ARR: case SL_VECTOR: + case SL_COMPANY_MASK: case SL_DEQUE: return GetVarFileType(sld.conv) | SLE_FILE_HAS_LENGTH_FIELD; break; @@ -1075,6 +1084,7 @@ static void SlArray(void *array, size_t length, VarType conv) /* If the SLE_ARR changes size, a savegame bump is required * and the developer should have written conversion lines. * Error out to make this more visible. */ + std::cout << "Corrupted array!!" << std::endl; SlErrorCorrupt("Fixed-length array is of wrong length"); } } @@ -1092,6 +1102,82 @@ static void SlArray(void *array, size_t length, VarType conv) } } + + +// MYTODO: Put this somewhere it belongs +std::vector bitset_to_bytes(const CompanyMask& mask) +{ + std::vector result((MAX_COMPANIES + 7) >> 3); + for (int j = 0; j < MAX_COMPANIES; j++) + result[j>>3] |= (mask[j] << (j & 7)); + return result; +} + +CompanyMask bitset_from_bytes(const std::vector& buf) { + CompanyMask result; + for (int j=0; j < MAX_COMPANIES; j++) + result[j] = ((buf[j>>3] >> (j & 7)) & 1); + return result; +} + + +CompanyMask ParseOldCompMask(uint16_t old_owner) { + CompanyMask result; + for (int i = 0; i < 16; i++) { + result[i] = GB(old_owner, i, 1) & 1; + } + return result; +} + +Owner ParseOldOwner(Owner old) { + if (old == OLD_OWNER_NONE) { + old = OWNER_NONE; + } else if (old == OLD_OWNER_TOWN){ + old = OWNER_TOWN; + } else if (old == OLD_OWNER_WATER) { + old = OWNER_WATER; + } + return old; +} + + +/** + * Save/Load the length of the bitset followed by the array of SL_VAR bits. + * @param array The array being manipulated + * @param length The length of the bitset in bytes, + */ +static void SlCompanyMask(void *array, size_t byte_length, VarType conv) +{ + switch (_sl.action) { + case SLA_SAVE: { + CompanyMask *bs = static_cast(array); + std::vector bytes = bitset_to_bytes(*bs); + uint8_t *bytes_arr = &bytes[0]; + SlArray(bytes_arr, bytes.size(), conv); + return; + } + + case SLA_LOAD_CHECK: + case SLA_LOAD: { + assert(byte_length == (MAX_COMPANIES + 7) >> 3); + + std::vector buff((MAX_COMPANIES + 7) >> 3); + SlArray(&buff[0], byte_length, conv); + + CompanyMask *bs = static_cast(array); + *bs = bitset_from_bytes(buff); // we don't want to write direc + return; + } + + case SLA_PTRS: + case SLA_NULL: + return; + + default: + NOT_REACHED(); + } +} + /** * Pointers cannot be saved to a savegame, so this functions gets * the index of the item, and if not available, it hussles with @@ -1500,6 +1586,7 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld) case SL_VAR: return SlCalcConvFileLen(sld.conv); case SL_REF: return SlCalcRefLen(); case SL_ARR: return SlCalcArrayLen(sld.length, sld.conv); + case SL_COMPANY_MASK: return SlCalcArrayLen(sld.length, sld.conv); case SL_REFLIST: return SlCalcRefListLen(GetVariableAddress(object, sld), sld.conv); case SL_DEQUE: return SlCalcDequeLen(GetVariableAddress(object, sld), sld.conv); case SL_VECTOR: return SlCalcVectorLen(GetVariableAddress(object, sld), sld.conv); @@ -1538,6 +1625,7 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld) static bool SlObjectMember(void *object, const SaveLoad &sld) { + std::cout <<"Object: "<< sld.name << std::endl; if (!SlIsObjectValidInSavegame(sld)) return false; VarType conv = GB(sld.conv, 0, 8); @@ -1548,6 +1636,7 @@ static bool SlObjectMember(void *object, const SaveLoad &sld) case SL_REFLIST: case SL_DEQUE: case SL_VECTOR: + case SL_COMPANY_MASK: case SL_STDSTR: { void *ptr = GetVariableAddress(object, sld); @@ -1555,6 +1644,7 @@ static bool SlObjectMember(void *object, const SaveLoad &sld) case SL_VAR: SlSaveLoadConv(ptr, conv); break; case SL_REF: SlSaveLoadRef(ptr, conv); break; case SL_ARR: SlArray(ptr, sld.length, conv); break; + case SL_COMPANY_MASK: SlCompanyMask(ptr, sld.length, conv); break; case SL_REFLIST: SlRefList(ptr, conv); break; case SL_DEQUE: SlDeque(ptr, conv); break; case SL_VECTOR: SlVector(ptr, conv); break; @@ -2156,10 +2246,12 @@ static void SlLoadCheckChunks() const ChunkHandler *ch; for (id = SlReadUint32(); id != 0; id = SlReadUint32()) { - Debug(sl, 2, "Loading chunk {:c}{:c}{:c}{:c}", id >> 24, id >> 16, id >> 8, id); + Debug(sl, 2, "Loading chunk (for checking) {:c}{:c}{:c}{:c}", id >> 24, id >> 16, id >> 8, id); ch = SlFindChunkHandler(id); - if (ch == nullptr) SlErrorCorrupt("Unknown chunk type"); + if (ch == nullptr) { + SlErrorCorrupt("Unknown chunk type"); + } SlLoadCheckChunk(*ch); } } diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 99f74777bf..458fc5bca0 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -381,6 +381,7 @@ enum SaveLoadVersion : uint16_t { SLV_COMPANY_ALLOW_LIST, ///< 335 PR#12337 Saving of list of client keys that are allowed to join this company. SLV_GROUP_NUMBERS, ///< 336 PR#12297 Add per-company group numbers. + SLV_MORE_COMPANIES, /// Added more companies MYTODO: Fix this comment SL_MAX_VERSION, ///< Highest possible saveload version }; @@ -690,9 +691,10 @@ enum SaveLoadType : uint8_t { SL_VECTOR = 7, ///< Save/load a vector of #SL_VAR elements. SL_REFLIST = 8, ///< Save/load a list of #SL_REF elements. SL_STRUCTLIST = 9, ///< Save/load a list of structs. + SL_COMPANY_MASK = 10, ///< Save/load a fixed-size bitset of #SL_VAR bits. - SL_SAVEBYTE = 10, ///< Save (but not load) a byte. - SL_NULL = 11, ///< Save null-bytes and load to nowhere. + SL_SAVEBYTE = 11, ///< Save (but not load) a byte. + SL_NULL = 12, ///< Save null-bytes and load to nowhere. }; typedef void *SaveLoadAddrProc(void *base, size_t extra); @@ -799,6 +801,7 @@ inline constexpr bool SlCheckVarSize(SaveLoadType cmd, VarType type, size_t leng case SL_REF: return sizeof(void *) == size; case SL_STDSTR: return SlVarSize(type) == size; case SL_ARR: return SlVarSize(type) * length <= size; // Partial load of array is permitted. + case SL_COMPANY_MASK: return SlVarSize(type) * length <= size; // Partial load of array is permitted. case SL_DEQUE: return sizeof(std::deque) == size; case SL_VECTOR: return sizeof(std::vector) == size; case SL_REFLIST: return sizeof(std::list) == size; @@ -1001,6 +1004,17 @@ inline constexpr bool SlCheckVarSize(SaveLoadType cmd, VarType type, size_t leng */ #define SLE_ARRNAME(base, variable, name, type, length) SLE_CONDARRNAME(base, variable, name, type, length, SL_MIN_VERSION, SL_MAX_VERSION) + +/** + * Storage of a company mask bitset of #MAX_COMPANIES bits in some savegame versions. + * @param base Name of the class or struct containing the company mask. + * @param variable Name of the variable in the class or struct referenced by \a base. + * @param bit_length Number of bits in the serialized form. + * @param from First savegame version that has the array. + * @param to Last savegame version that has the array. + */ +#define SLE_CONDCOMPMASK(base, variable, bit_length, from, to) SLE_GENERAL(SL_COMPANY_MASK, base, variable, SLE_CHAR, (bit_length + 7) >> 3, from, to, 0) + /** * Storage of a \c std::string in every savegame version. * @param base Name of the class or struct containing the string. @@ -1300,6 +1314,8 @@ void SlCopy(void *object, size_t length, VarType conv); std::vector SlTableHeader(const SaveLoadTable &slt); std::vector SlCompatTableHeader(const SaveLoadTable &slt, const SaveLoadCompatTable &slct); void SlObject(void *object, const SaveLoadTable &slt); +CompanyMask ParseOldCompMask(uint16_t old_owner); +Owner ParseOldOwner(Owner old); bool SaveloadCrashWithMissingNewGRFs(); diff --git a/src/saveload/signs_sl.cpp b/src/saveload/signs_sl.cpp index 336a552f76..a7aa87d373 100644 --- a/src/saveload/signs_sl.cpp +++ b/src/saveload/signs_sl.cpp @@ -9,6 +9,7 @@ #include "../stdafx.h" +#include "company_type.h" #include "saveload.h" #include "compat/signs_sl_compat.h" @@ -62,9 +63,12 @@ struct SIGNChunkHandler : ChunkHandler { } /* Signs placed in scenario editor shall now be OWNER_DEITY */ - if (IsSavegameVersionBefore(SLV_171) && si->owner == OWNER_NONE && _file_to_saveload.abstract_ftype == FT_SCENARIO) { + if (IsSavegameVersionBefore(SLV_171) && si->owner == OLD_OWNER_NONE && _file_to_saveload.abstract_ftype == FT_SCENARIO) { si->owner = OWNER_DEITY; } + if (IsSavegameVersionBefore(SLV_MORE_COMPANIES)) { + si->owner = ParseOldOwner(si->owner); + } } } }; diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp index c964ceb46a..fc01c80be9 100644 --- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -502,6 +502,9 @@ struct STNSChunkHandler : ChunkHandler { _waiting_acceptance = 0; SlObject(st, slt); + if (IsSavegameVersionBefore(SLV_MORE_COMPANIES)) { + st->owner = ParseOldOwner(st->owner); + } } } diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp index e09bf9d444..66375d663a 100644 --- a/src/saveload/town_sl.cpp +++ b/src/saveload/town_sl.cpp @@ -215,15 +215,21 @@ static const SaveLoad _town_desc[] = { SLE_CONDSSTR(Town, name, SLE_STR | SLF_ALLOW_CONTROL, SLV_84, SL_MAX_VERSION), SLE_VAR(Town, flags, SLE_UINT8), - SLE_CONDVAR(Town, statues, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104), - SLE_CONDVAR(Town, statues, SLE_UINT16, SLV_104, SL_MAX_VERSION), +SLE_CONDVARNAME(Town, old_statues, "statues", SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104), +SLE_CONDVARNAME(Town, old_statues, "statues", SLE_UINT16, SLV_104, SLV_MORE_COMPANIES), +SLE_CONDCOMPMASK(Town, statues, MAX_COMPANIES, SLV_MORE_COMPANIES, SL_MAX_VERSION), + +SLE_CONDCOMPMASK(Town, have_ratings, MAX_COMPANIES, SLV_MORE_COMPANIES, SL_MAX_VERSION), +SLE_CONDVARNAME(Town, old_have_ratings, "have_ratings", SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104), +SLE_CONDVARNAME(Town, old_have_ratings, "have_ratings", SLE_UINT16, SLV_104, SLV_MORE_COMPANIES), - SLE_CONDVAR(Town, have_ratings, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104), - SLE_CONDVAR(Town, have_ratings, SLE_UINT16, SLV_104, SL_MAX_VERSION), SLE_CONDARR(Town, ratings, SLE_INT16, 8, SL_MIN_VERSION, SLV_104), - SLE_CONDARR(Town, ratings, SLE_INT16, MAX_COMPANIES, SLV_104, SL_MAX_VERSION), + SLE_CONDARR(Town, ratings, SLE_INT16, 15, SLV_104, SLV_MORE_COMPANIES), + SLE_CONDARR(Town, ratings, SLE_INT16, MAX_COMPANIES, SLV_MORE_COMPANIES, SL_MAX_VERSION), + SLE_CONDARR(Town, unwanted, SLE_INT8, 8, SLV_4, SLV_104), - SLE_CONDARR(Town, unwanted, SLE_INT8, MAX_COMPANIES, SLV_104, SL_MAX_VERSION), + SLE_CONDARR(Town, unwanted, SLE_INT8, 15, SLV_104, SLV_MORE_COMPANIES), + SLE_CONDARR(Town, unwanted, SLE_INT8, MAX_COMPANIES, SLV_MORE_COMPANIES, SL_MAX_VERSION), /* Slots 0 and 2 are passengers and mail respectively for old saves. */ SLE_CONDVARNAME(Town, supplied[0].old_max, "supplied[CT_PASSENGERS].old_max", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9), @@ -306,6 +312,10 @@ struct CITYChunkHandler : ChunkHandler { if (t->townnamegrfid == 0 && !IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1) && GetStringTab(t->townnametype) != TEXT_TAB_OLD_CUSTOM) { SlErrorCorrupt("Invalid town name generator"); } + if (IsSavegameVersionBefore(SLV_MORE_COMPANIES)) { + t->statues = ParseOldCompMask(t->old_statues); + t->have_ratings = ParseOldCompMask(t->old_have_ratings); + } } } diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index 4e42de3962..02989dfe13 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -405,6 +405,11 @@ void AfterLoadVehicles(bool part_of_load) v->economy_age = v->age.base(); } } + if (IsSavegameVersionBefore(SLV_MORE_COMPANIES)) { + for (Vehicle *v : Vehicle::Iterate()) { + v->owner = ParseOldOwner(v->owner); + } + } } CheckValidVehicles(); diff --git a/src/saveload/waypoint_sl.cpp b/src/saveload/waypoint_sl.cpp index 7745c9b6e5..557081faff 100644 --- a/src/saveload/waypoint_sl.cpp +++ b/src/saveload/waypoint_sl.cpp @@ -16,6 +16,7 @@ #include "../newgrf.h" #include "../timer/timer_game_calendar.h" +#include "saveload/saveload.h" #include "table/strings.h" #include "saveload_internal.h" @@ -200,6 +201,9 @@ struct CHKPChunkHandler : ChunkHandler { wp->index = index; SlObject(wp, _old_waypoint_desc); + if (IsSavegameVersionBefore(SLV_MORE_COMPANIES)) { + wp->owner = ParseOldOwner(wp->owner); + } } } diff --git a/src/tile_map.h b/src/tile_map.h index 6fbb3a53fa..032d75f6d7 100644 --- a/src/tile_map.h +++ b/src/tile_map.h @@ -10,6 +10,7 @@ #ifndef TILE_MAP_H #define TILE_MAP_H +#include "company_type.h" #include "slope_type.h" #include "map_func.h" #include "core/bitmath_func.hpp" @@ -181,6 +182,27 @@ inline Owner GetTileOwner(Tile tile) assert(!IsTileType(tile, MP_HOUSE)); assert(!IsTileType(tile, MP_INDUSTRY)); + return (Owner)GB(tile.m9(), 0, COMPANY_SIZE_BITS); +} + +/** + * Returns the owner of a tile. Only used for legacy code + * + * This function returns the owner of a tile. This cannot used + * for tiles which type is one of MP_HOUSE, MP_VOID and MP_INDUSTRY + * as no company owned any of these buildings. + * + * @param tile The tile to check + * @return The owner of the tile + * @pre IsValidTile(tile) + * @pre The type of the tile must not be MP_HOUSE and MP_INDUSTRY + */ +inline Owner OldGetTileOwner(Tile tile) +{ + assert(IsValidTile(tile)); + assert(!IsTileType(tile, MP_HOUSE)); + assert(!IsTileType(tile, MP_INDUSTRY)); + return (Owner)GB(tile.m1(), 0, 5); } @@ -201,9 +223,30 @@ inline void SetTileOwner(Tile tile, Owner owner) assert(!IsTileType(tile, MP_HOUSE)); assert(!IsTileType(tile, MP_INDUSTRY)); + SB(tile.m9(), 0, COMPANY_SIZE_BITS, owner); +} + +/** + * Sets the owner of a tile (Only for old formats) + * + * This function sets the owner status of a tile. Note that you cannot + * set a owner for tiles of type MP_HOUSE, MP_VOID and MP_INDUSTRY. + * + * @param tile The tile to change the owner status. + * @param owner The new owner. + * @pre IsValidTile(tile) + * @pre The type of the tile must not be MP_HOUSE and MP_INDUSTRY + */ +inline void OldSetTileOwner(Tile tile, Owner owner) +{ + assert(IsValidTile(tile)); + assert(!IsTileType(tile, MP_HOUSE)); + assert(!IsTileType(tile, MP_INDUSTRY)); + SB(tile.m1(), 0, 5, owner); } + /** * Checks if a tile belongs to the given owner * diff --git a/src/town.h b/src/town.h index ce930bb180..d8512d1db1 100644 --- a/src/town.h +++ b/src/town.h @@ -16,6 +16,7 @@ #include "subsidy_type.h" #include "newgrf_storage.h" #include "cargotype.h" +#include template struct BuildingCounts { @@ -68,9 +69,11 @@ struct Town : TownPool::PoolItem<&_town_pool> { uint16_t noise_reached; ///< level of noise that all the airports are generating CompanyMask statues; ///< which companies have a statue? + uint16_t old_statues; /* Company ratings. */ CompanyMask have_ratings; ///< which companies have a rating + uint16_t old_have_ratings; uint8_t unwanted[MAX_COMPANIES]; ///< how many months companies aren't wanted by towns (bribe) CompanyID exclusivity; ///< which company has exclusivity uint8_t exclusive_counter; ///< months till the exclusivity expires diff --git a/src/vehiclelist.cpp b/src/vehiclelist.cpp index 48214d9384..aa4cd9ac16 100644 --- a/src/vehiclelist.cpp +++ b/src/vehiclelist.cpp @@ -7,6 +7,7 @@ /** @file vehiclelist.cpp Lists of vehicles. */ +#include "cargomonitor.h" #include "stdafx.h" #include "train.h" #include "vehicle_func.h" @@ -23,7 +24,6 @@ uint32_t VehicleListIdentifier::Pack() const { uint8_t c = this->company == OWNER_NONE ? 0xF : (uint8_t)this->company; - assert(c < (1 << 4)); assert(this->vtype < (1 << 2)); assert(this->index < (1 << 20)); assert(this->type < VLT_END); diff --git a/src/void_map.h b/src/void_map.h index e8e031be79..ede9f19d77 100644 --- a/src/void_map.h +++ b/src/void_map.h @@ -27,6 +27,8 @@ inline void MakeVoid(Tile t) t.m5() = 0; t.m6() = 0; t.m7() = 0; + t.m8() = 0; + t.m9() = 0; } #endif /* VOID_MAP_H */