diff options
author | peter1138 <peter1138@openttd.org> | 2008-04-29 21:31:29 +0000 |
---|---|---|
committer | peter1138 <peter1138@openttd.org> | 2008-04-29 21:31:29 +0000 |
commit | a00371c8db9d3b944d901ea0468eb58fe51418a7 (patch) | |
tree | 82b8c0d69acb1c38843e4fcf0b11f46a057ef270 /src/newgrf.cpp | |
parent | 1d01390fa6d6ca83cd0cb148137d2a81749b380d (diff) | |
download | openttd-a00371c8db9d3b944d901ea0468eb58fe51418a7.tar.xz |
(svn r12924) -Feature: Introducing the so called 'engine pool' which primarily removes the fixed engine type limits and also happens to allow (with the patch option 'dynamic_engines') multiple NewGRF vehicle sets to coexist.
Diffstat (limited to 'src/newgrf.cpp')
-rw-r--r-- | src/newgrf.cpp | 258 |
1 files changed, 159 insertions, 99 deletions
diff --git a/src/newgrf.cpp b/src/newgrf.cpp index dee8bae67..0ef3e81d4 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -10,6 +10,7 @@ #include "debug.h" #include "fileio.h" #include "engine_func.h" +#include "engine_base.h" #include "spritecache.h" #include "sprite.h" #include "newgrf.h" @@ -45,6 +46,7 @@ #include "player_base.h" #include "settings_type.h" #include "map_func.h" +#include <map> #include <map> @@ -97,20 +99,6 @@ static GrfDataType _grf_data_type; typedef void (*SpecialSpriteHandler)(byte *buf, int len); -static const uint _vehcounts[4] = { - /* GSF_TRAIN */ NUM_TRAIN_ENGINES, - /* GSF_ROAD */ NUM_ROAD_ENGINES, - /* GSF_SHIP */ NUM_SHIP_ENGINES, - /* GSF_AIRCRAFT */ NUM_AIRCRAFT_ENGINES -}; - -static const uint _vehshifts[4] = { - /* GSF_TRAIN */ 0, - /* GSF_ROAD */ ROAD_ENGINES_INDEX, - /* GSF_SHIP */ SHIP_ENGINES_INDEX, - /* GSF_AIRCRAFT */ AIRCRAFT_ENGINES_INDEX, -}; - enum { MAX_STATIONS = 256, }; @@ -123,8 +111,10 @@ struct GRFTempEngineData { static GRFTempEngineData *_gted; -/* Contains the GRF ID of the owner of a vehicle if it has been reserved */ -static uint32 _grm_engines[TOTAL_NUM_ENGINES]; +/* Contains the GRF ID of the owner of a vehicle if it has been reserved. + * GRM for vehicles is only used if dynamic engine allocation is disabled, + * so 256 is the number of original engines. */ +static uint32 _grm_engines[256]; /* Contains the GRF ID of the owner of a cargo if it has been reserved */ static uint32 _grm_cargos[NUM_CARGO * 2]; @@ -310,6 +300,65 @@ static uint8 MapDOSColour(uint8 colour) return colour; } +static std::map<uint32, uint32> _grf_id_overrides; + +static void SetNewGRFOverride(uint32 source_grfid, uint32 target_grfid) +{ + _grf_id_overrides[source_grfid] = target_grfid; + grfmsg(5, "SetNewGRFOverride: Added override of 0x%X to 0x%X", BSWAP32(source_grfid), BSWAP32(target_grfid)); +} + +static Engine *GetNewEngine(const GRFFile *file, VehicleType type, uint16 internal_id) +{ + /* Hack for add-on GRFs that need to modify another GRF's engines. This lets + * them use the same engine slots. */ + const GRFFile *grf_match = NULL; + if (_patches.dynamic_engines) { + uint32 override = _grf_id_overrides[file->grfid]; + if (override != 0) { + grf_match = GetFileByGRFID(override); + if (grf_match == NULL) { + grfmsg(5, "Tried mapping from GRFID %x to %x but target is not loaded", BSWAP32(file->grfid), BSWAP32(override)); + } else { + grfmsg(5, "Mapping from GRFID %x to %x", BSWAP32(file->grfid), BSWAP32(override)); + } + } + } + + /* Check if this vehicle is already defined... */ + Engine *e = NULL; + FOR_ALL_ENGINES(e) { + if (_patches.dynamic_engines && e->grffile != NULL && e->grffile != file && e->grffile != grf_match) continue; + if (e->type != type) continue; + if (e->internal_id != internal_id) continue; + + if (e->grffile == NULL) { + e->grffile = file; + grfmsg(5, "Replaced engine at index %d for GRFID %x, type %d, index %d", e->index, BSWAP32(file->grfid), type, internal_id); + } + return e; + } + + uint engine_pool_size = GetEnginePoolSize(); + + /* ... it's not, so create a new one based off an existing engine */ + e = new Engine(type, internal_id); + e->grffile = file; + + if (engine_pool_size != GetEnginePoolSize()) { + /* Resize temporary engine data ... */ + _gted = ReallocT(_gted, GetEnginePoolSize()); + + /* and blank the new block. */ + size_t len = (GetEnginePoolSize() - engine_pool_size) * sizeof(*_gted); + memset(_gted + engine_pool_size, 0, len); + } + + grfmsg(5, "Created new engine at index %d for GRFID %x, type %d, index %d", e->index, BSWAP32(file->grfid), type, internal_id); + + return e; +} + /** Map the colour modifiers of TTDPatch to those that Open is using. * @param grf_sprite pointer to the structure been modified */ @@ -333,18 +382,15 @@ static void MapSpriteMappingRecolour(PalSpriteID *grf_sprite) typedef bool (*VCI_Handler)(uint engine, int numinfo, int prop, byte **buf, int len); -static void dewagonize(int condition, int engine) +static void dewagonize(int condition, Engine *e) { - EngineInfo *ei = &_engine_info[engine]; - RailVehicleInfo *rvi = &_rail_vehicle_info[engine]; - if (condition != 0) { - ei->unk2 &= ~0x80; - if (rvi->railveh_type == RAILVEH_WAGON) - rvi->railveh_type = RAILVEH_SINGLEHEAD; + e->info.unk2 &= ~0x80; + if (e->u.rail.railveh_type == RAILVEH_WAGON) + e->u.rail.railveh_type = RAILVEH_SINGLEHEAD; } else { - ei->unk2 |= 0x80; - rvi->railveh_type = RAILVEH_WAGON; + e->info.unk2 |= 0x80; + e->u.rail.railveh_type = RAILVEH_WAGON; } } @@ -354,8 +400,9 @@ static bool RailVehicleChangeInfo(uint engine, int numinfo, int prop, byte **buf bool ret = false; for (int i = 0; i < numinfo; i++) { - EngineInfo *ei = &_engine_info[engine + i]; - RailVehicleInfo *rvi = &_rail_vehicle_info[engine + i]; + Engine *e = GetNewEngine(_cur_grffile, VEH_TRAIN, engine + i); + EngineInfo *ei = &e->info; + RailVehicleInfo *rvi = &e->u.rail; switch (prop) { case 0x05: { // Track type @@ -390,7 +437,7 @@ static bool RailVehicleChangeInfo(uint engine, int numinfo, int prop, byte **buf if (rvi->railveh_type == RAILVEH_MULTIHEAD) power /= 2; rvi->power = power; - dewagonize(power, engine + i); + dewagonize(power, e); } break; case 0x0D: { // Running cost factor @@ -505,15 +552,9 @@ static bool RailVehicleChangeInfo(uint engine, int numinfo, int prop, byte **buf rvi->engclass = engclass; } break; - case 0x1A: { // Alter purchase list sort order - EngineID pos = grf_load_byte(&buf); - - if (pos < NUM_TRAIN_ENGINES) { - AlterRailVehListOrder(engine + i, pos); - } else { - grfmsg(2, "RailVehicleChangeInfo: Invalid train engine ID %d, ignoring", pos); - } - } break; + case 0x1A: // Alter purchase list sort order + AlterRailVehListOrder(e->index, grf_load_byte(&buf)); + break; case 0x1B: // Powered wagons power bonus rvi->pow_wag_power = grf_load_word(&buf); @@ -578,11 +619,11 @@ static bool RailVehicleChangeInfo(uint engine, int numinfo, int prop, byte **buf break; case 0x28: // Cargo classes allowed - _gted[engine + i].cargo_allowed = grf_load_word(&buf); + _gted[e->index].cargo_allowed = grf_load_word(&buf); break; case 0x29: // Cargo classes disallowed - _gted[engine + i].cargo_disallowed = grf_load_word(&buf); + _gted[e->index].cargo_disallowed = grf_load_word(&buf); break; case 0x2A: // Long format introduction date (days since year 0) @@ -605,8 +646,9 @@ static bool RoadVehicleChangeInfo(uint engine, int numinfo, int prop, byte **buf bool ret = false; for (int i = 0; i < numinfo; i++) { - EngineInfo *ei = &_engine_info[ROAD_ENGINES_INDEX + engine + i]; - RoadVehicleInfo *rvi = &_road_vehicle_info[engine + i]; + Engine *e = GetNewEngine(_cur_grffile, VEH_ROAD, engine + i); + EngineInfo *ei = &e->info; + RoadVehicleInfo *rvi = &e->u.road; switch (prop) { case 0x08: // Speed (1 unit is 0.5 kmh) @@ -708,11 +750,11 @@ static bool RoadVehicleChangeInfo(uint engine, int numinfo, int prop, byte **buf break; case 0x1D: // Cargo classes allowed - _gted[ROAD_ENGINES_INDEX + engine + i].cargo_allowed = grf_load_word(&buf); + _gted[e->index].cargo_allowed = grf_load_word(&buf); break; case 0x1E: // Cargo classes disallowed - _gted[ROAD_ENGINES_INDEX + engine + i].cargo_disallowed = grf_load_word(&buf); + _gted[e->index].cargo_disallowed = grf_load_word(&buf); break; case 0x1F: // Long format introduction date (days since year 0) @@ -735,8 +777,9 @@ static bool ShipVehicleChangeInfo(uint engine, int numinfo, int prop, byte **buf bool ret = false; for (int i = 0; i < numinfo; i++) { - EngineInfo *ei = &_engine_info[SHIP_ENGINES_INDEX + engine + i]; - ShipVehicleInfo *svi = &_ship_vehicle_info[engine + i]; + Engine *e = GetNewEngine(_cur_grffile, VEH_SHIP, engine + i); + EngineInfo *ei = &e->info; + ShipVehicleInfo *svi = &e->u.ship; switch (prop) { case 0x08: { // Sprite ID @@ -814,11 +857,11 @@ static bool ShipVehicleChangeInfo(uint engine, int numinfo, int prop, byte **buf break; case 0x18: // Cargo classes allowed - _gted[SHIP_ENGINES_INDEX + engine + i].cargo_allowed = grf_load_word(&buf); + _gted[e->index].cargo_allowed = grf_load_word(&buf); break; case 0x19: // Cargo classes disallowed - _gted[SHIP_ENGINES_INDEX + engine + i].cargo_disallowed = grf_load_word(&buf); + _gted[e->index].cargo_disallowed = grf_load_word(&buf); break; case 0x1A: // Long format introduction date (days since year 0) @@ -841,8 +884,9 @@ static bool AircraftVehicleChangeInfo(uint engine, int numinfo, int prop, byte * bool ret = false; for (int i = 0; i < numinfo; i++) { - EngineInfo *ei = &_engine_info[AIRCRAFT_ENGINES_INDEX + engine + i]; - AircraftVehicleInfo *avi = &_aircraft_vehicle_info[engine + i]; + Engine *e = GetNewEngine(_cur_grffile, VEH_AIRCRAFT, engine + i); + EngineInfo *ei = &e->info; + AircraftVehicleInfo *avi = &e->u.air; switch (prop) { case 0x08: { // Sprite ID @@ -918,11 +962,11 @@ static bool AircraftVehicleChangeInfo(uint engine, int numinfo, int prop, byte * break; case 0x18: // Cargo classes allowed - _gted[AIRCRAFT_ENGINES_INDEX + engine + i].cargo_allowed = grf_load_word(&buf); + _gted[e->index].cargo_allowed = grf_load_word(&buf); break; case 0x19: // Cargo classes disallowed - _gted[AIRCRAFT_ENGINES_INDEX + engine + i].cargo_disallowed = grf_load_word(&buf); + _gted[e->index].cargo_disallowed = grf_load_word(&buf); break; case 0x1A: // Long format introduction date (days since year 0) @@ -1604,6 +1648,12 @@ static bool GlobalVarChangeInfo(uint gvid, int numinfo, int prop, byte **bufp, i } break; + case 0x11: // GRF match for engine allocation + /* This is loaded during the reservation stage, so just skip it here. */ + /* Each entry is 8 bytes. */ + buf += 8; + break; + default: ret = true; break; @@ -2211,13 +2261,6 @@ static void FeatureChangeInfo(byte *buf, int len) return; } - if (feature <= GSF_AIRCRAFT) { - if (engine + numinfo > _vehcounts[feature]) { - grfmsg(0, "FeatureChangeInfo: Last engine ID %d out of bounds (max %d), skipping", engine + numinfo, _vehcounts[feature]); - return; - } - } - while (numprops-- && buf < bufend) { uint8 prop = grf_load_byte(&buf); bool ignoring = false; @@ -2230,7 +2273,8 @@ static void FeatureChangeInfo(byte *buf, int len) bool handled = true; for (uint i = 0; i < numinfo; i++) { - EngineInfo *ei = &_engine_info[engine + _vehshifts[feature] + i]; + Engine *e = GetNewEngine(_cur_grffile, (VehicleType)feature, engine + i); + EngineInfo *ei = &e->info; /* Common properties for vehicles */ switch (prop) { @@ -2252,6 +2296,8 @@ static void FeatureChangeInfo(byte *buf, int len) case 0x06: // Climates available ei->climates = grf_load_byte(&buf); + // XXX sometimes a grf wants hidden vehicles :o + if (ei->climates == 0) ei->climates = 0x80; break; case 0x07: // Loading speed @@ -2345,6 +2391,14 @@ static void ReserveChangeInfo(byte *buf, int len) _cur_grffile->cargo_list[i] = BSWAP32(cl); } break; + + case 0x11: // GRF match for engine allocation + for (uint i = 0; i < numinfo; i++) { + uint32 s = grf_load_dword(&buf); + uint32 t = grf_load_dword(&buf); + SetNewGRFOverride(s, t); + } + break; } break; } @@ -2857,14 +2911,9 @@ static void VehicleMapSpriteGroup(byte *buf, byte feature, uint8 idcount, uint8 for (uint i = 0; i < idcount; i++) { uint8 engine_id = buf[3 + i]; - uint8 engine = engine_id + _vehshifts[feature]; + EngineID engine = GetNewEngine(_cur_grffile, (VehicleType)feature, engine_id)->index; byte *bp = &buf[4 + idcount]; - if (engine_id > _vehcounts[feature]) { - grfmsg(0, "Id %u for feature 0x%02X is out of bounds", engine_id, feature); - return; - } - grfmsg(7, "VehicleMapSpriteGroup: [%d] Engine %d...", i, engine); for (uint c = 0; c < cidcount; c++) { @@ -2897,7 +2946,7 @@ static void VehicleMapSpriteGroup(byte *buf, byte feature, uint8 idcount, uint8 grfmsg(8, "-- Default group id 0x%04X", groupid); for (uint i = 0; i < idcount; i++) { - uint8 engine = buf[3 + i] + _vehshifts[feature]; + EngineID engine = GetNewEngine(_cur_grffile, (VehicleType)feature, buf[3 + i])->index; /* Don't tell me you don't love duplicated code! */ if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) { @@ -3213,9 +3262,6 @@ static void FeatureNewName(byte *buf, int len) ClrBit(lang, 7); - if (feature <= GSF_AIRCRAFT && id < _vehcounts[feature]) { - id += _vehshifts[feature]; - } uint16 endid = id + num; grfmsg(6, "FeatureNewName: About to rename engines %d..%d (feature %d) in language 0x%02X", @@ -3236,10 +3282,10 @@ static void FeatureNewName(byte *buf, int len) case GSF_ROAD: case GSF_SHIP: case GSF_AIRCRAFT: - if (id < TOTAL_NUM_ENGINES) { - StringID string = AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_8000_KIRBY_PAUL_TANK_STEAM + id); - EngineInfo *ei = &_engine_info[id]; - ei->string_id = string; + if (id < GetEnginePoolSize()) { + Engine *e = GetNewEngine(_cur_grffile, (VehicleType)feature, id); + StringID string = AddGRFString(_cur_grffile->grfid, e->index, lang, new_scheme, name, e->info.string_id); + e->info.string_id = string; } else { AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, id); } @@ -4303,8 +4349,22 @@ static void ParamSet(byte *buf, int len) case 0x01: // Road Vehicles case 0x02: // Ships case 0x03: // Aircraft - src1 = PerformGRM(&_grm_engines[_vehshifts[feature]], _vehcounts[feature], count, op, target, "vehicles"); - if (_skip_sprites == -1) return; + if (!_patches.dynamic_engines) { + src1 = PerformGRM(&_grm_engines[_engine_offsets[feature]], _engine_counts[feature], count, op, target, "vehicles"); + if (_skip_sprites == -1) return; + } else { + // GRM does not apply for dynamic engine allocation. + switch (op) { + case 2: + case 3: + src1 = _cur_grffile->param[target]; + break; + + default: + src1 = 0; + break; + } + } break; case 0x08: // General sprites @@ -5068,6 +5128,7 @@ static void InitializeGRFSpecial() | (0 << 0x15) // enhancetunnels | (1 << 0x16) // shortrvs | (1 << 0x17) // articulatedrvs + | ((_patches.dynamic_engines ? 1 : 0) << 0x18) // dynamic engines | (1 << 0x1E); // variablerunningcosts } @@ -5224,17 +5285,12 @@ static void ResetNewGRFData() ResetBridges(); /* Allocate temporary refit/cargo class data */ - _gted = CallocT<GRFTempEngineData>(TOTAL_NUM_ENGINES); + _gted = CallocT<GRFTempEngineData>(GetEnginePoolSize()); /* Reset GRM reservations */ memset(&_grm_engines, 0, sizeof(_grm_engines)); memset(&_grm_cargos, 0, sizeof(_grm_cargos)); - /* Unload sprite group data */ - UnloadWagonOverrides(); - UnloadCustomEngineSprites(); - ResetEngineListOrder(); - /* Reset generic feature callback lists */ ResetGenericCallbacks(); @@ -5284,6 +5340,9 @@ static void ResetNewGRFData() _loaded_newgrf_features.has_newindustries = false; _loaded_newgrf_features.shore = SHORE_REPLACE_NONE; + /* Clear all GRF overrides */ + _grf_id_overrides.clear(); + InitializeSoundPool(); InitializeSpriteGroupPool(); } @@ -5397,14 +5456,17 @@ static const CargoLabel *_default_refitmasks[] = { */ static void CalculateRefitMasks() { - for (EngineID engine = 0; engine < TOTAL_NUM_ENGINES; engine++) { - EngineInfo *ei = &_engine_info[engine]; + Engine *e; + + FOR_ALL_ENGINES(e) { + EngineID engine = e->index; + EngineInfo *ei = &e->info; uint32 mask = 0; uint32 not_mask = 0; uint32 xor_mask = 0; if (ei->refit_mask != 0) { - const GRFFile *file = GetEngineGRF(engine); + const GRFFile *file = e->grffile; if (file != NULL && file->cargo_max != 0) { /* Apply cargo translation table to the refit mask */ uint num_cargo = min(32, file->cargo_max); @@ -5434,15 +5496,10 @@ static void CalculateRefitMasks() if (_gted[engine].cargo_allowed & cs->classes) SetBit(mask, i); if (_gted[engine].cargo_disallowed & cs->classes) SetBit(not_mask, i); } - } else { + } else if (xor_mask == 0) { /* Don't apply default refit mask to wagons or engines with no capacity */ - if (xor_mask == 0 && ( - GetEngine(engine)->type != VEH_TRAIN || ( - RailVehInfo(engine)->capacity != 0 && - RailVehInfo(engine)->railveh_type != RAILVEH_WAGON - ) - )) { - const CargoLabel *cl = _default_refitmasks[GetEngine(engine)->type]; + if (e->type != VEH_TRAIN || (e->u.rail.capacity != 0 && e->u.rail.railveh_type != RAILVEH_WAGON)) { + const CargoLabel *cl = _default_refitmasks[e->type]; for (uint i = 0;; i++) { if (cl[i] == 0) break; @@ -5458,25 +5515,25 @@ static void CalculateRefitMasks() /* Check if this engine's cargo type is valid. If not, set to the first refittable * cargo type. Apparently cargo_type isn't a common property... */ - switch (GetEngine(engine)->type) { + switch (e->type) { default: NOT_REACHED(); case VEH_AIRCRAFT: break; case VEH_TRAIN: { - RailVehicleInfo *rvi = &_rail_vehicle_info[engine]; + RailVehicleInfo *rvi = &e->u.rail; if (rvi->cargo_type == CT_INVALID) rvi->cargo_type = FindFirstRefittableCargo(engine); - if (rvi->cargo_type == CT_INVALID) ei->climates = 0; + if (rvi->cargo_type == CT_INVALID) ei->climates = 0x80; break; } case VEH_ROAD: { - RoadVehicleInfo *rvi = &_road_vehicle_info[engine - ROAD_ENGINES_INDEX]; + RoadVehicleInfo *rvi = &e->u.road; if (rvi->cargo_type == CT_INVALID) rvi->cargo_type = FindFirstRefittableCargo(engine); - if (rvi->cargo_type == CT_INVALID) ei->climates = 0; + if (rvi->cargo_type == CT_INVALID) ei->climates = 0x80; break; } case VEH_SHIP: { - ShipVehicleInfo *svi = &_ship_vehicle_info[engine - SHIP_ENGINES_INDEX]; + ShipVehicleInfo *svi = &e->u.ship; if (svi->cargo_type == CT_INVALID) svi->cargo_type = FindFirstRefittableCargo(engine); - if (svi->cargo_type == CT_INVALID) ei->climates = 0; + if (svi->cargo_type == CT_INVALID) ei->climates = 0x80; break; } } @@ -5851,6 +5908,9 @@ static void AfterLoadGRFs() /* Update the townname generators list */ InitGRFTownGeneratorNames(); + /* Run all queued vehicle list order changes */ + CommitRailVehListOrderChanges(); + /* Load old shore sprites in new position, if they were replaced by ActionA */ ActivateOldShore(); |