00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013
00014 #include <stdarg.h>
00015
00016 #include "debug.h"
00017 #include "fileio_func.h"
00018 #include "engine_func.h"
00019 #include "engine_base.h"
00020 #include "bridge.h"
00021 #include "town.h"
00022 #include "newgrf_engine.h"
00023 #include "newgrf_text.h"
00024 #include "fontcache.h"
00025 #include "currency.h"
00026 #include "landscape.h"
00027 #include "newgrf_cargo.h"
00028 #include "newgrf_house.h"
00029 #include "newgrf_sound.h"
00030 #include "newgrf_station.h"
00031 #include "industrytype.h"
00032 #include "newgrf_canal.h"
00033 #include "newgrf_townname.h"
00034 #include "newgrf_industries.h"
00035 #include "newgrf_airporttiles.h"
00036 #include "newgrf_airport.h"
00037 #include "newgrf_object.h"
00038 #include "rev.h"
00039 #include "fios.h"
00040 #include "strings_func.h"
00041 #include "date_func.h"
00042 #include "string_func.h"
00043 #include "network/network.h"
00044 #include <map>
00045 #include "smallmap_gui.h"
00046 #include "genworld.h"
00047 #include "error.h"
00048 #include "vehicle_func.h"
00049 #include "language.h"
00050 #include "vehicle_base.h"
00051
00052 #include "table/strings.h"
00053 #include "table/build_industry.h"
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00065 static SmallVector<GRFFile *, 16> _grf_files;
00066
00068 byte _misc_grf_features = 0;
00069
00071 static uint32 _ttdpatch_flags[8];
00072
00074 GRFLoadedFeatures _loaded_newgrf_features;
00075
00076 static const uint MAX_SPRITEGROUP = UINT8_MAX;
00077
00079 struct GrfProcessingState {
00080 private:
00082 struct SpriteSet {
00083 SpriteID sprite;
00084 uint num_sprites;
00085 };
00086
00088 std::map<uint, SpriteSet> spritesets[GSF_END];
00089
00090 public:
00091
00092 GrfLoadingStage stage;
00093 SpriteID spriteid;
00094
00095
00096 uint file_index;
00097 GRFFile *grffile;
00098 GRFConfig *grfconfig;
00099 uint32 nfo_line;
00100 byte grf_container_ver;
00101
00102
00103 int skip_sprites;
00104
00105
00106 SpriteGroup *spritegroups[MAX_SPRITEGROUP + 1];
00107
00109 void ClearDataForNextFile()
00110 {
00111 this->nfo_line = 0;
00112 this->skip_sprites = 0;
00113
00114 for (uint i = 0; i < GSF_END; i++) {
00115 this->spritesets[i].clear();
00116 }
00117
00118 memset(this->spritegroups, 0, sizeof(this->spritegroups));
00119 }
00120
00129 void AddSpriteSets(byte feature, SpriteID first_sprite, uint first_set, uint numsets, uint numents)
00130 {
00131 assert(feature < GSF_END);
00132 for (uint i = 0; i < numsets; i++) {
00133 SpriteSet &set = this->spritesets[feature][first_set + i];
00134 set.sprite = first_sprite + i * numents;
00135 set.num_sprites = numents;
00136 }
00137 }
00138
00145 bool HasValidSpriteSets(byte feature) const
00146 {
00147 assert(feature < GSF_END);
00148 return !this->spritesets[feature].empty();
00149 }
00150
00158 bool IsValidSpriteSet(byte feature, uint set) const
00159 {
00160 assert(feature < GSF_END);
00161 return this->spritesets[feature].find(set) != this->spritesets[feature].end();
00162 }
00163
00170 SpriteID GetSprite(byte feature, uint set) const
00171 {
00172 assert(IsValidSpriteSet(feature, set));
00173 return this->spritesets[feature].find(set)->second.sprite;
00174 }
00175
00182 uint GetNumEnts(byte feature, uint set) const
00183 {
00184 assert(IsValidSpriteSet(feature, set));
00185 return this->spritesets[feature].find(set)->second.num_sprites;
00186 }
00187 };
00188
00189 static GrfProcessingState _cur;
00190
00191
00198 template <VehicleType T>
00199 static inline bool IsValidNewGRFImageIndex(uint8 image_index)
00200 {
00201 return image_index == 0xFD || IsValidImageIndex<T>(image_index);
00202 }
00203
00204 class OTTDByteReaderSignal { };
00205
00207 class ByteReader {
00208 protected:
00209 byte *data;
00210 byte *end;
00211
00212 public:
00213 ByteReader(byte *data, byte *end) : data(data), end(end) { }
00214
00215 inline byte ReadByte()
00216 {
00217 if (data < end) return *(data)++;
00218 throw OTTDByteReaderSignal();
00219 }
00220
00221 uint16 ReadWord()
00222 {
00223 uint16 val = ReadByte();
00224 return val | (ReadByte() << 8);
00225 }
00226
00227 uint16 ReadExtendedByte()
00228 {
00229 uint16 val = ReadByte();
00230 return val == 0xFF ? ReadWord() : val;
00231 }
00232
00233 uint32 ReadDWord()
00234 {
00235 uint32 val = ReadWord();
00236 return val | (ReadWord() << 16);
00237 }
00238
00239 uint32 ReadVarSize(byte size)
00240 {
00241 switch (size) {
00242 case 1: return ReadByte();
00243 case 2: return ReadWord();
00244 case 4: return ReadDWord();
00245 default:
00246 NOT_REACHED();
00247 return 0;
00248 }
00249 }
00250
00251 const char *ReadString()
00252 {
00253 char *string = reinterpret_cast<char *>(data);
00254 size_t string_length = ttd_strnlen(string, Remaining());
00255
00256 if (string_length == Remaining()) {
00257
00258 string[string_length - 1] = '\0';
00259 grfmsg(7, "String was not terminated with a zero byte.");
00260 } else {
00261
00262 string_length++;
00263 }
00264 Skip(string_length);
00265
00266 return string;
00267 }
00268
00269 inline size_t Remaining() const
00270 {
00271 return end - data;
00272 }
00273
00274 inline bool HasData(size_t count = 1) const
00275 {
00276 return data + count <= end;
00277 }
00278
00279 inline byte *Data()
00280 {
00281 return data;
00282 }
00283
00284 inline void Skip(size_t len)
00285 {
00286 data += len;
00287
00288
00289 if (data > end) throw OTTDByteReaderSignal();
00290 }
00291 };
00292
00293 typedef void (*SpecialSpriteHandler)(ByteReader *buf);
00294
00295 static const uint NUM_STATIONS_PER_GRF = 255;
00296
00298 struct GRFTempEngineData {
00300 enum Refittability {
00301 UNSET = 0,
00302 EMPTY,
00303 NONEMPTY,
00304 };
00305
00306 uint16 cargo_allowed;
00307 uint16 cargo_disallowed;
00308 RailTypeLabel railtypelabel;
00309 const GRFFile *defaultcargo_grf;
00310 Refittability refittability;
00311 bool prop27_set;
00312 uint8 rv_max_speed;
00313 uint32 ctt_include_mask;
00314 uint32 ctt_exclude_mask;
00315
00320 void UpdateRefittability(bool non_empty)
00321 {
00322 if (non_empty) {
00323 this->refittability = NONEMPTY;
00324 } else if (this->refittability == UNSET) {
00325 this->refittability = EMPTY;
00326 }
00327 }
00328 };
00329
00330 static GRFTempEngineData *_gted;
00331
00336 static uint32 _grm_engines[256];
00337
00339 static uint32 _grm_cargoes[NUM_CARGO * 2];
00340
00341 struct GRFLocation {
00342 uint32 grfid;
00343 uint32 nfoline;
00344
00345 GRFLocation(uint32 grfid, uint32 nfoline) : grfid(grfid), nfoline(nfoline) { }
00346
00347 bool operator<(const GRFLocation &other) const
00348 {
00349 return this->grfid < other.grfid || (this->grfid == other.grfid && this->nfoline < other.nfoline);
00350 }
00351
00352 bool operator == (const GRFLocation &other) const
00353 {
00354 return this->grfid == other.grfid && this->nfoline == other.nfoline;
00355 }
00356 };
00357
00358 static std::map<GRFLocation, SpriteID> _grm_sprites;
00359 typedef std::map<GRFLocation, byte*> GRFLineToSpriteOverride;
00360 static GRFLineToSpriteOverride _grf_line_to_action6_sprite_override;
00361
00372 void CDECL grfmsg(int severity, const char *str, ...)
00373 {
00374 char buf[1024];
00375 va_list va;
00376
00377 va_start(va, str);
00378 vsnprintf(buf, sizeof(buf), str, va);
00379 va_end(va);
00380
00381 DEBUG(grf, severity, "[%s:%d] %s", _cur.grfconfig->filename, _cur.nfo_line, buf);
00382 }
00383
00389 static GRFFile *GetFileByGRFID(uint32 grfid)
00390 {
00391 const GRFFile * const *end = _grf_files.End();
00392 for (GRFFile * const *file = _grf_files.Begin(); file != end; file++) {
00393 if ((*file)->grfid == grfid) return *file;
00394 }
00395 return NULL;
00396 }
00397
00403 static GRFFile *GetFileByFilename(const char *filename)
00404 {
00405 const GRFFile * const *end = _grf_files.End();
00406 for (GRFFile * const *file = _grf_files.Begin(); file != end; file++) {
00407 if (strcmp((*file)->filename, filename) == 0) return *file;
00408 }
00409 return NULL;
00410 }
00411
00413 static void ClearTemporaryNewGRFData(GRFFile *gf)
00414 {
00415
00416 for (GRFLabel *l = gf->label; l != NULL;) {
00417 GRFLabel *l2 = l->next;
00418 free(l);
00419 l = l2;
00420 }
00421 gf->label = NULL;
00422 }
00423
00430 static GRFError *DisableGrf(StringID message = STR_NULL, GRFConfig *config = NULL)
00431 {
00432 GRFFile *file;
00433 if (config != NULL) {
00434 file = GetFileByGRFID(config->ident.grfid);
00435 } else {
00436 config = _cur.grfconfig;
00437 file = _cur.grffile;
00438 }
00439
00440 config->status = GCS_DISABLED;
00441 if (file != NULL) ClearTemporaryNewGRFData(file);
00442 if (config == _cur.grfconfig) _cur.skip_sprites = -1;
00443
00444 if (message != STR_NULL) {
00445 delete config->error;
00446 config->error = new GRFError(STR_NEWGRF_ERROR_MSG_FATAL, message);
00447 if (config == _cur.grfconfig) config->error->param_value[0] = _cur.nfo_line;
00448 }
00449
00450 return config->error;
00451 }
00452
00456 struct StringIDMapping {
00457 uint32 grfid;
00458 StringID source;
00459 StringID *target;
00460 };
00461 typedef SmallVector<StringIDMapping, 16> StringIDMappingVector;
00462 static StringIDMappingVector _string_to_grf_mapping;
00463
00469 static void AddStringForMapping(StringID source, StringID *target)
00470 {
00471 *target = STR_UNDEFINED;
00472 StringIDMapping *item = _string_to_grf_mapping.Append();
00473 item->grfid = _cur.grffile->grfid;
00474 item->source = source;
00475 item->target = target;
00476 }
00477
00485 static StringID TTDPStringIDToOTTDStringIDMapping(StringID str)
00486 {
00487
00488 static const StringID units_volume[] = {
00489 STR_ITEMS, STR_PASSENGERS, STR_TONS, STR_BAGS,
00490 STR_LITERS, STR_ITEMS, STR_CRATES, STR_TONS,
00491 STR_TONS, STR_TONS, STR_TONS, STR_BAGS,
00492 STR_TONS, STR_TONS, STR_TONS, STR_BAGS,
00493 STR_TONS, STR_TONS, STR_BAGS, STR_LITERS,
00494 STR_TONS, STR_LITERS, STR_TONS, STR_ITEMS,
00495 STR_BAGS, STR_LITERS, STR_TONS, STR_ITEMS,
00496 STR_TONS, STR_ITEMS, STR_LITERS, STR_ITEMS
00497 };
00498
00499
00500 assert(!IsInsideMM(str, 0xD000, 0xD7FF));
00501
00502 #define TEXTID_TO_STRINGID(begin, end, stringid, stringend) \
00503 assert_compile(stringend - stringid == end - begin); \
00504 if (str >= begin && str <= end) return str + (stringid - begin)
00505
00506
00507 TEXTID_TO_STRINGID(0x000E, 0x002D, STR_CARGO_PLURAL_NOTHING, STR_CARGO_PLURAL_FIZZY_DRINKS);
00508 TEXTID_TO_STRINGID(0x002E, 0x004D, STR_CARGO_SINGULAR_NOTHING, STR_CARGO_SINGULAR_FIZZY_DRINK);
00509 if (str >= 0x004E && str <= 0x006D) return units_volume[str - 0x004E];
00510 TEXTID_TO_STRINGID(0x006E, 0x008D, STR_QUANTITY_NOTHING, STR_QUANTITY_FIZZY_DRINKS);
00511 TEXTID_TO_STRINGID(0x008E, 0x00AD, STR_ABBREV_NOTHING, STR_ABBREV_FIZZY_DRINKS);
00512 TEXTID_TO_STRINGID(0x00D1, 0x00E0, STR_COLOUR_DARK_BLUE, STR_COLOUR_WHITE);
00513
00514
00515
00516
00517 TEXTID_TO_STRINGID(0x200F, 0x201F, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, STR_TOWN_BUILDING_NAME_OLD_HOUSES_1);
00518 TEXTID_TO_STRINGID(0x2036, 0x2041, STR_TOWN_BUILDING_NAME_COTTAGES_1, STR_TOWN_BUILDING_NAME_SHOPPING_MALL_1);
00519 TEXTID_TO_STRINGID(0x2059, 0x205C, STR_TOWN_BUILDING_NAME_IGLOO_1, STR_TOWN_BUILDING_NAME_PIGGY_BANK_1);
00520
00521
00522 TEXTID_TO_STRINGID(0x4802, 0x4826, STR_INDUSTRY_NAME_COAL_MINE, STR_INDUSTRY_NAME_SUGAR_MINE);
00523 TEXTID_TO_STRINGID(0x482D, 0x482E, STR_NEWS_INDUSTRY_CONSTRUCTION, STR_NEWS_INDUSTRY_PLANTED);
00524 TEXTID_TO_STRINGID(0x4832, 0x4834, STR_NEWS_INDUSTRY_CLOSURE_GENERAL, STR_NEWS_INDUSTRY_CLOSURE_LACK_OF_TREES);
00525 TEXTID_TO_STRINGID(0x4835, 0x4838, STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_GENERAL, STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_FARM);
00526 TEXTID_TO_STRINGID(0x4839, 0x483A, STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_GENERAL, STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_FARM);
00527
00528 switch (str) {
00529 case 0x4830: return STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY;
00530 case 0x4831: return STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED;
00531 case 0x483B: return STR_ERROR_CAN_ONLY_BE_POSITIONED;
00532 }
00533 #undef TEXTID_TO_STRINGID
00534
00535 if (str == STR_NULL) return STR_EMPTY;
00536
00537 DEBUG(grf, 0, "Unknown StringID 0x%04X remapped to STR_EMPTY. Please open a Feature Request if you need it", str);
00538
00539 return STR_EMPTY;
00540 }
00541
00549 StringID MapGRFStringID(uint32 grfid, StringID str)
00550 {
00551
00552
00553
00554
00555 switch (GB(str, 8, 8)) {
00556 case 0xD0: case 0xD1: case 0xD2: case 0xD3:
00557 case 0xDC:
00558 return GetGRFStringID(grfid, str);
00559
00560 case 0xD4: case 0xD5: case 0xD6: case 0xD7:
00561
00562
00563 return GetGRFStringID(grfid, str - 0x400);
00564
00565 default: break;
00566 }
00567
00568 return TTDPStringIDToOTTDStringIDMapping(str);
00569 }
00570
00571 static std::map<uint32, uint32> _grf_id_overrides;
00572
00578 static void SetNewGRFOverride(uint32 source_grfid, uint32 target_grfid)
00579 {
00580 _grf_id_overrides[source_grfid] = target_grfid;
00581 grfmsg(5, "SetNewGRFOverride: Added override of 0x%X to 0x%X", BSWAP32(source_grfid), BSWAP32(target_grfid));
00582 }
00583
00592 static Engine *GetNewEngine(const GRFFile *file, VehicleType type, uint16 internal_id, bool static_access = false)
00593 {
00594
00595
00596 uint32 scope_grfid = INVALID_GRFID;
00597 if (_settings_game.vehicle.dynamic_engines) {
00598
00599 scope_grfid = file->grfid;
00600 uint32 override = _grf_id_overrides[file->grfid];
00601 if (override != 0) {
00602 scope_grfid = override;
00603 const GRFFile *grf_match = GetFileByGRFID(override);
00604 if (grf_match == NULL) {
00605 grfmsg(5, "Tried mapping from GRFID %x to %x but target is not loaded", BSWAP32(file->grfid), BSWAP32(override));
00606 } else {
00607 grfmsg(5, "Mapping from GRFID %x to %x", BSWAP32(file->grfid), BSWAP32(override));
00608 }
00609 }
00610
00611
00612 EngineID engine = _engine_mngr.GetID(type, internal_id, scope_grfid);
00613 if (engine != INVALID_ENGINE) {
00614 Engine *e = Engine::Get(engine);
00615 if (e->grf_prop.grffile == NULL) e->grf_prop.grffile = file;
00616 return e;
00617 }
00618 }
00619
00620
00621 EngineID engine = _engine_mngr.GetID(type, internal_id, INVALID_GRFID);
00622 if (engine != INVALID_ENGINE) {
00623 Engine *e = Engine::Get(engine);
00624
00625 if (e->grf_prop.grffile == NULL) {
00626 e->grf_prop.grffile = file;
00627 grfmsg(5, "Replaced engine at index %d for GRFID %x, type %d, index %d", e->index, BSWAP32(file->grfid), type, internal_id);
00628 }
00629
00630
00631 if (!static_access) {
00632 EngineIDMapping *eid = _engine_mngr.Get(engine);
00633 eid->grfid = scope_grfid;
00634 }
00635
00636 return e;
00637 }
00638
00639 if (static_access) return NULL;
00640
00641 if (!Engine::CanAllocateItem()) {
00642 grfmsg(0, "Can't allocate any more engines");
00643 return NULL;
00644 }
00645
00646 size_t engine_pool_size = Engine::GetPoolSize();
00647
00648
00649 Engine *e = new Engine(type, internal_id);
00650 e->grf_prop.grffile = file;
00651
00652
00653 assert(_engine_mngr.Length() == e->index);
00654 EngineIDMapping *eid = _engine_mngr.Append();
00655 eid->type = type;
00656 eid->grfid = scope_grfid;
00657 eid->internal_id = internal_id;
00658 eid->substitute_id = min(internal_id, _engine_counts[type]);
00659
00660 if (engine_pool_size != Engine::GetPoolSize()) {
00661
00662 _gted = ReallocT(_gted, Engine::GetPoolSize());
00663
00664
00665 size_t len = (Engine::GetPoolSize() - engine_pool_size) * sizeof(*_gted);
00666 memset(_gted + engine_pool_size, 0, len);
00667 }
00668 if (type == VEH_TRAIN) {
00669 _gted[e->index].railtypelabel = GetRailTypeInfo(e->u.rail.railtype)->label;
00670 }
00671
00672 grfmsg(5, "Created new engine at index %d for GRFID %x, type %d, index %d", e->index, BSWAP32(file->grfid), type, internal_id);
00673
00674 return e;
00675 }
00676
00687 EngineID GetNewEngineID(const GRFFile *file, VehicleType type, uint16 internal_id)
00688 {
00689 uint32 scope_grfid = INVALID_GRFID;
00690 if (_settings_game.vehicle.dynamic_engines) {
00691 scope_grfid = file->grfid;
00692 uint32 override = _grf_id_overrides[file->grfid];
00693 if (override != 0) scope_grfid = override;
00694 }
00695
00696 return _engine_mngr.GetID(type, internal_id, scope_grfid);
00697 }
00698
00703 static void MapSpriteMappingRecolour(PalSpriteID *grf_sprite)
00704 {
00705 if (HasBit(grf_sprite->pal, 14)) {
00706 ClrBit(grf_sprite->pal, 14);
00707 SetBit(grf_sprite->sprite, SPRITE_MODIFIER_OPAQUE);
00708 }
00709
00710 if (HasBit(grf_sprite->sprite, 14)) {
00711 ClrBit(grf_sprite->sprite, 14);
00712 SetBit(grf_sprite->sprite, PALETTE_MODIFIER_TRANSPARENT);
00713 }
00714
00715 if (HasBit(grf_sprite->sprite, 15)) {
00716 ClrBit(grf_sprite->sprite, 15);
00717 SetBit(grf_sprite->sprite, PALETTE_MODIFIER_COLOUR);
00718 }
00719 }
00720
00734 static TileLayoutFlags ReadSpriteLayoutSprite(ByteReader *buf, bool read_flags, bool invert_action1_flag, bool use_cur_spritesets, int feature, PalSpriteID *grf_sprite, uint16 *max_sprite_offset = NULL, uint16 *max_palette_offset = NULL)
00735 {
00736 grf_sprite->sprite = buf->ReadWord();
00737 grf_sprite->pal = buf->ReadWord();
00738 TileLayoutFlags flags = read_flags ? (TileLayoutFlags)buf->ReadWord() : TLF_NOTHING;
00739
00740 MapSpriteMappingRecolour(grf_sprite);
00741
00742 bool custom_sprite = HasBit(grf_sprite->pal, 15) != invert_action1_flag;
00743 ClrBit(grf_sprite->pal, 15);
00744 if (custom_sprite) {
00745
00746 uint index = GB(grf_sprite->sprite, 0, 14);
00747 if (use_cur_spritesets && (!_cur.IsValidSpriteSet(feature, index) || _cur.GetNumEnts(feature, index) == 0)) {
00748 grfmsg(1, "ReadSpriteLayoutSprite: Spritelayout uses undefined custom spriteset %d", index);
00749 grf_sprite->sprite = SPR_IMG_QUERY;
00750 grf_sprite->pal = PAL_NONE;
00751 } else {
00752 SpriteID sprite = use_cur_spritesets ? _cur.GetSprite(feature, index) : index;
00753 if (max_sprite_offset != NULL) *max_sprite_offset = use_cur_spritesets ? _cur.GetNumEnts(feature, index) : UINT16_MAX;
00754 SB(grf_sprite->sprite, 0, SPRITE_WIDTH, sprite);
00755 SetBit(grf_sprite->sprite, SPRITE_MODIFIER_CUSTOM_SPRITE);
00756 }
00757 } else if ((flags & TLF_SPRITE_VAR10) && !(flags & TLF_SPRITE_REG_FLAGS)) {
00758 grfmsg(1, "ReadSpriteLayoutSprite: Spritelayout specifies var10 value for non-action-1 sprite");
00759 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
00760 return flags;
00761 }
00762
00763 if (flags & TLF_CUSTOM_PALETTE) {
00764
00765 uint index = GB(grf_sprite->pal, 0, 14);
00766 if (use_cur_spritesets && (!_cur.IsValidSpriteSet(feature, index) || _cur.GetNumEnts(feature, index) == 0)) {
00767 grfmsg(1, "ReadSpriteLayoutSprite: Spritelayout uses undefined custom spriteset %d for 'palette'", index);
00768 grf_sprite->pal = PAL_NONE;
00769 } else {
00770 SpriteID sprite = use_cur_spritesets ? _cur.GetSprite(feature, index) : index;
00771 if (max_palette_offset != NULL) *max_palette_offset = use_cur_spritesets ? _cur.GetNumEnts(feature, index) : UINT16_MAX;
00772 SB(grf_sprite->pal, 0, SPRITE_WIDTH, sprite);
00773 SetBit(grf_sprite->pal, SPRITE_MODIFIER_CUSTOM_SPRITE);
00774 }
00775 } else if ((flags & TLF_PALETTE_VAR10) && !(flags & TLF_PALETTE_REG_FLAGS)) {
00776 grfmsg(1, "ReadSpriteLayoutRegisters: Spritelayout specifies var10 value for non-action-1 palette");
00777 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
00778 return flags;
00779 }
00780
00781 return flags;
00782 }
00783
00792 static void ReadSpriteLayoutRegisters(ByteReader *buf, TileLayoutFlags flags, bool is_parent, NewGRFSpriteLayout *dts, uint index)
00793 {
00794 if (!(flags & TLF_DRAWING_FLAGS)) return;
00795
00796 if (dts->registers == NULL) dts->AllocateRegisters();
00797 TileLayoutRegisters ®s = const_cast<TileLayoutRegisters&>(dts->registers[index]);
00798 regs.flags = flags & TLF_DRAWING_FLAGS;
00799
00800 if (flags & TLF_DODRAW) regs.dodraw = buf->ReadByte();
00801 if (flags & TLF_SPRITE) regs.sprite = buf->ReadByte();
00802 if (flags & TLF_PALETTE) regs.palette = buf->ReadByte();
00803
00804 if (is_parent) {
00805 if (flags & TLF_BB_XY_OFFSET) {
00806 regs.delta.parent[0] = buf->ReadByte();
00807 regs.delta.parent[1] = buf->ReadByte();
00808 }
00809 if (flags & TLF_BB_Z_OFFSET) regs.delta.parent[2] = buf->ReadByte();
00810 } else {
00811 if (flags & TLF_CHILD_X_OFFSET) regs.delta.child[0] = buf->ReadByte();
00812 if (flags & TLF_CHILD_Y_OFFSET) regs.delta.child[1] = buf->ReadByte();
00813 }
00814
00815 if (flags & TLF_SPRITE_VAR10) {
00816 regs.sprite_var10 = buf->ReadByte();
00817 if (regs.sprite_var10 > TLR_MAX_VAR10) {
00818 grfmsg(1, "ReadSpriteLayoutRegisters: Spritelayout specifies var10 (%d) exceeding the maximal allowed value %d", regs.sprite_var10, TLR_MAX_VAR10);
00819 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
00820 return;
00821 }
00822 }
00823
00824 if (flags & TLF_PALETTE_VAR10) {
00825 regs.palette_var10 = buf->ReadByte();
00826 if (regs.palette_var10 > TLR_MAX_VAR10) {
00827 grfmsg(1, "ReadSpriteLayoutRegisters: Spritelayout specifies var10 (%d) exceeding the maximal allowed value %d", regs.palette_var10, TLR_MAX_VAR10);
00828 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
00829 return;
00830 }
00831 }
00832 }
00833
00845 static bool ReadSpriteLayout(ByteReader *buf, uint num_building_sprites, bool use_cur_spritesets, byte feature, bool allow_var10, bool no_z_position, NewGRFSpriteLayout *dts)
00846 {
00847 bool has_flags = HasBit(num_building_sprites, 6);
00848 ClrBit(num_building_sprites, 6);
00849 TileLayoutFlags valid_flags = TLF_KNOWN_FLAGS;
00850 if (!allow_var10) valid_flags &= ~TLF_VAR10_FLAGS;
00851 dts->Allocate(num_building_sprites);
00852
00853 uint16 *max_sprite_offset = AllocaM(uint16, num_building_sprites + 1);
00854 uint16 *max_palette_offset = AllocaM(uint16, num_building_sprites + 1);
00855 MemSetT(max_sprite_offset, 0, num_building_sprites + 1);
00856 MemSetT(max_palette_offset, 0, num_building_sprites + 1);
00857
00858
00859 TileLayoutFlags flags = ReadSpriteLayoutSprite(buf, has_flags, false, use_cur_spritesets, feature, &dts->ground, max_sprite_offset, max_palette_offset);
00860 if (_cur.skip_sprites < 0) return true;
00861
00862 if (flags & ~(valid_flags & ~TLF_NON_GROUND_FLAGS)) {
00863 grfmsg(1, "ReadSpriteLayout: Spritelayout uses invalid flag 0x%x for ground sprite", flags & ~(valid_flags & ~TLF_NON_GROUND_FLAGS));
00864 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
00865 return true;
00866 }
00867
00868 ReadSpriteLayoutRegisters(buf, flags, false, dts, 0);
00869 if (_cur.skip_sprites < 0) return true;
00870
00871 for (uint i = 0; i < num_building_sprites; i++) {
00872 DrawTileSeqStruct *seq = const_cast<DrawTileSeqStruct*>(&dts->seq[i]);
00873
00874 flags = ReadSpriteLayoutSprite(buf, has_flags, false, use_cur_spritesets, feature, &seq->image, max_sprite_offset + i + 1, max_palette_offset + i + 1);
00875 if (_cur.skip_sprites < 0) return true;
00876
00877 if (flags & ~valid_flags) {
00878 grfmsg(1, "ReadSpriteLayout: Spritelayout uses unknown flag 0x%x", flags & ~valid_flags);
00879 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
00880 return true;
00881 }
00882
00883 seq->delta_x = buf->ReadByte();
00884 seq->delta_y = buf->ReadByte();
00885
00886 if (!no_z_position) seq->delta_z = buf->ReadByte();
00887
00888 if (seq->IsParentSprite()) {
00889 seq->size_x = buf->ReadByte();
00890 seq->size_y = buf->ReadByte();
00891 seq->size_z = buf->ReadByte();
00892 }
00893
00894 ReadSpriteLayoutRegisters(buf, flags, seq->IsParentSprite(), dts, i + 1);
00895 if (_cur.skip_sprites < 0) return true;
00896 }
00897
00898
00899 bool is_consistent = true;
00900 dts->consistent_max_offset = 0;
00901 for (uint i = 0; i < num_building_sprites + 1; i++) {
00902 if (max_sprite_offset[i] > 0) {
00903 if (dts->consistent_max_offset == 0) {
00904 dts->consistent_max_offset = max_sprite_offset[i];
00905 } else if (dts->consistent_max_offset != max_sprite_offset[i]) {
00906 is_consistent = false;
00907 break;
00908 }
00909 }
00910 if (max_palette_offset[i] > 0) {
00911 if (dts->consistent_max_offset == 0) {
00912 dts->consistent_max_offset = max_palette_offset[i];
00913 } else if (dts->consistent_max_offset != max_palette_offset[i]) {
00914 is_consistent = false;
00915 break;
00916 }
00917 }
00918 }
00919
00920
00921 assert(use_cur_spritesets || (is_consistent && (dts->consistent_max_offset == 0 || dts->consistent_max_offset == UINT16_MAX)));
00922
00923 if (!is_consistent || dts->registers != NULL) {
00924 dts->consistent_max_offset = 0;
00925 if (dts->registers == NULL) dts->AllocateRegisters();
00926
00927 for (uint i = 0; i < num_building_sprites + 1; i++) {
00928 TileLayoutRegisters ®s = const_cast<TileLayoutRegisters&>(dts->registers[i]);
00929 regs.max_sprite_offset = max_sprite_offset[i];
00930 regs.max_palette_offset = max_palette_offset[i];
00931 }
00932 }
00933
00934 return false;
00935 }
00936
00940 static uint32 TranslateRefitMask(uint32 refit_mask)
00941 {
00942 uint32 result = 0;
00943 uint8 bit;
00944 FOR_EACH_SET_BIT(bit, refit_mask) {
00945 CargoID cargo = GetCargoTranslation(bit, _cur.grffile, true);
00946 if (cargo != CT_INVALID) SetBit(result, cargo);
00947 }
00948 return result;
00949 }
00950
00958 static void ConvertTTDBasePrice(uint32 base_pointer, const char *error_location, Price *index)
00959 {
00960
00961 if (base_pointer == 0) {
00962 *index = INVALID_PRICE;
00963 return;
00964 }
00965
00966 static const uint32 start = 0x4B34;
00967 static const uint32 size = 6;
00968
00969 if (base_pointer < start || (base_pointer - start) % size != 0 || (base_pointer - start) / size >= PR_END) {
00970 grfmsg(1, "%s: Unsupported running cost base 0x%04X, ignoring", error_location, base_pointer);
00971 return;
00972 }
00973
00974 *index = (Price)((base_pointer - start) / size);
00975 }
00976
00978 enum ChangeInfoResult {
00979 CIR_SUCCESS,
00980 CIR_DISABLED,
00981 CIR_UNHANDLED,
00982 CIR_UNKNOWN,
00983 CIR_INVALID_ID,
00984 };
00985
00986 typedef ChangeInfoResult (*VCI_Handler)(uint engine, int numinfo, int prop, ByteReader *buf);
00987
00995 static ChangeInfoResult CommonVehicleChangeInfo(EngineInfo *ei, int prop, ByteReader *buf)
00996 {
00997 switch (prop) {
00998 case 0x00:
00999 ei->base_intro = buf->ReadWord() + DAYS_TILL_ORIGINAL_BASE_YEAR;
01000 break;
01001
01002 case 0x02:
01003 ei->decay_speed = buf->ReadByte();
01004 break;
01005
01006 case 0x03:
01007 ei->lifelength = buf->ReadByte();
01008 break;
01009
01010 case 0x04:
01011 ei->base_life = buf->ReadByte();
01012 break;
01013
01014 case 0x06:
01015 ei->climates = buf->ReadByte();
01016 break;
01017
01018 case PROP_VEHICLE_LOAD_AMOUNT:
01019
01020 ei->load_amount = buf->ReadByte();
01021 break;
01022
01023 default:
01024 return CIR_UNKNOWN;
01025 }
01026
01027 return CIR_SUCCESS;
01028 }
01029
01038 static ChangeInfoResult RailVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader *buf)
01039 {
01040 ChangeInfoResult ret = CIR_SUCCESS;
01041
01042 for (int i = 0; i < numinfo; i++) {
01043 Engine *e = GetNewEngine(_cur.grffile, VEH_TRAIN, engine + i);
01044 if (e == NULL) return CIR_INVALID_ID;
01045
01046 EngineInfo *ei = &e->info;
01047 RailVehicleInfo *rvi = &e->u.rail;
01048
01049 switch (prop) {
01050 case 0x05: {
01051 uint8 tracktype = buf->ReadByte();
01052
01053 if (tracktype < _cur.grffile->railtype_list.Length()) {
01054 _gted[e->index].railtypelabel = _cur.grffile->railtype_list[tracktype];
01055 break;
01056 }
01057
01058 switch (tracktype) {
01059 case 0: _gted[e->index].railtypelabel = rvi->engclass >= 2 ? RAILTYPE_ELECTRIC_LABEL : RAILTYPE_RAIL_LABEL; break;
01060 case 1: _gted[e->index].railtypelabel = RAILTYPE_MONO_LABEL; break;
01061 case 2: _gted[e->index].railtypelabel = RAILTYPE_MAGLEV_LABEL; break;
01062 default:
01063 grfmsg(1, "RailVehicleChangeInfo: Invalid track type %d specified, ignoring", tracktype);
01064 break;
01065 }
01066 break;
01067 }
01068
01069 case 0x08:
01070
01071
01072 rvi->ai_passenger_only = buf->ReadByte();
01073 break;
01074
01075 case PROP_TRAIN_SPEED: {
01076 uint16 speed = buf->ReadWord();
01077 if (speed == 0xFFFF) speed = 0;
01078
01079 rvi->max_speed = speed;
01080 break;
01081 }
01082
01083 case PROP_TRAIN_POWER:
01084 rvi->power = buf->ReadWord();
01085
01086
01087 if (rvi->power != 0) {
01088 if (rvi->railveh_type == RAILVEH_WAGON) {
01089 rvi->railveh_type = RAILVEH_SINGLEHEAD;
01090 }
01091 } else {
01092 rvi->railveh_type = RAILVEH_WAGON;
01093 }
01094 break;
01095
01096 case PROP_TRAIN_RUNNING_COST_FACTOR:
01097 rvi->running_cost = buf->ReadByte();
01098 break;
01099
01100 case 0x0E:
01101 ConvertTTDBasePrice(buf->ReadDWord(), "RailVehicleChangeInfo", &rvi->running_cost_class);
01102 break;
01103
01104 case 0x12: {
01105 uint8 spriteid = buf->ReadByte();
01106 uint8 orig_spriteid = spriteid;
01107
01108
01109
01110 if (spriteid < 0xFD) spriteid >>= 1;
01111
01112 if (IsValidNewGRFImageIndex<VEH_TRAIN>(spriteid)) {
01113 rvi->image_index = spriteid;
01114 } else {
01115 grfmsg(1, "RailVehicleChangeInfo: Invalid Sprite %d specified, ignoring", orig_spriteid);
01116 rvi->image_index = 0;
01117 }
01118 break;
01119 }
01120
01121 case 0x13: {
01122 uint8 dual = buf->ReadByte();
01123
01124 if (dual != 0) {
01125 rvi->railveh_type = RAILVEH_MULTIHEAD;
01126 } else {
01127 rvi->railveh_type = rvi->power == 0 ?
01128 RAILVEH_WAGON : RAILVEH_SINGLEHEAD;
01129 }
01130 break;
01131 }
01132
01133 case PROP_TRAIN_CARGO_CAPACITY:
01134 rvi->capacity = buf->ReadByte();
01135 break;
01136
01137 case 0x15: {
01138 _gted[e->index].defaultcargo_grf = _cur.grffile;
01139 uint8 ctype = buf->ReadByte();
01140
01141 if (ctype == 0xFF) {
01142
01143 ei->cargo_type = CT_INVALID;
01144 } else if (_cur.grffile->grf_version >= 8) {
01145
01146 ei->cargo_type = GetCargoTranslation(ctype, _cur.grffile);
01147 } else if (ctype < NUM_CARGO) {
01148
01149 ei->cargo_type = ctype;
01150 } else {
01151 ei->cargo_type = CT_INVALID;
01152 grfmsg(2, "RailVehicleChangeInfo: Invalid cargo type %d, using first refittable", ctype);
01153 }
01154 break;
01155 }
01156
01157 case PROP_TRAIN_WEIGHT:
01158 SB(rvi->weight, 0, 8, buf->ReadByte());
01159 break;
01160
01161 case PROP_TRAIN_COST_FACTOR:
01162 rvi->cost_factor = buf->ReadByte();
01163 break;
01164
01165 case 0x18:
01166 grfmsg(2, "RailVehicleChangeInfo: Property 0x18 'AI rank' not used by NoAI, ignored.");
01167 buf->ReadByte();
01168 break;
01169
01170 case 0x19: {
01171
01172
01173
01174
01175
01176
01177
01178 uint8 traction = buf->ReadByte();
01179 EngineClass engclass;
01180
01181 if (traction <= 0x07) {
01182 engclass = EC_STEAM;
01183 } else if (traction <= 0x27) {
01184 engclass = EC_DIESEL;
01185 } else if (traction <= 0x31) {
01186 engclass = EC_ELECTRIC;
01187 } else if (traction <= 0x37) {
01188 engclass = EC_MONORAIL;
01189 } else if (traction <= 0x41) {
01190 engclass = EC_MAGLEV;
01191 } else {
01192 break;
01193 }
01194
01195 if (_cur.grffile->railtype_list.Length() == 0) {
01196
01197
01198 if (_gted[e->index].railtypelabel == RAILTYPE_RAIL_LABEL && engclass >= EC_ELECTRIC) _gted[e->index].railtypelabel = RAILTYPE_ELECTRIC_LABEL;
01199 if (_gted[e->index].railtypelabel == RAILTYPE_ELECTRIC_LABEL && engclass < EC_ELECTRIC) _gted[e->index].railtypelabel = RAILTYPE_RAIL_LABEL;
01200 }
01201
01202 rvi->engclass = engclass;
01203 break;
01204 }
01205
01206 case 0x1A:
01207 AlterVehicleListOrder(e->index, buf->ReadExtendedByte());
01208 break;
01209
01210 case 0x1B:
01211 rvi->pow_wag_power = buf->ReadWord();
01212 break;
01213
01214 case 0x1C:
01215 ei->refit_cost = buf->ReadByte();
01216 break;
01217
01218 case 0x1D: {
01219 uint32 mask = buf->ReadDWord();
01220 _gted[e->index].UpdateRefittability(mask != 0);
01221 ei->refit_mask = TranslateRefitMask(mask);
01222 _gted[e->index].defaultcargo_grf = _cur.grffile;
01223 break;
01224 }
01225
01226 case 0x1E:
01227 ei->callback_mask = buf->ReadByte();
01228 break;
01229
01230 case PROP_TRAIN_TRACTIVE_EFFORT:
01231 rvi->tractive_effort = buf->ReadByte();
01232 break;
01233
01234 case 0x20:
01235 rvi->air_drag = buf->ReadByte();
01236 break;
01237
01238 case PROP_TRAIN_SHORTEN_FACTOR:
01239 rvi->shorten_factor = buf->ReadByte();
01240 break;
01241
01242 case 0x22:
01243 rvi->visual_effect = buf->ReadByte();
01244
01245
01246 if (rvi->visual_effect == VE_DEFAULT) {
01247 assert(HasBit(rvi->visual_effect, VE_DISABLE_EFFECT));
01248 SB(rvi->visual_effect, VE_TYPE_START, VE_TYPE_COUNT, 0);
01249 }
01250 break;
01251
01252 case 0x23:
01253 rvi->pow_wag_weight = buf->ReadByte();
01254 break;
01255
01256 case 0x24: {
01257 byte weight = buf->ReadByte();
01258
01259 if (weight > 4) {
01260 grfmsg(2, "RailVehicleChangeInfo: Nonsensical weight of %d tons, ignoring", weight << 8);
01261 } else {
01262 SB(rvi->weight, 8, 8, weight);
01263 }
01264 break;
01265 }
01266
01267 case PROP_TRAIN_USER_DATA:
01268 rvi->user_def_data = buf->ReadByte();
01269 break;
01270
01271 case 0x26:
01272 ei->retire_early = buf->ReadByte();
01273 break;
01274
01275 case 0x27:
01276 ei->misc_flags = buf->ReadByte();
01277 _loaded_newgrf_features.has_2CC |= HasBit(ei->misc_flags, EF_USES_2CC);
01278 _gted[e->index].prop27_set = true;
01279 break;
01280
01281 case 0x28:
01282 _gted[e->index].cargo_allowed = buf->ReadWord();
01283 _gted[e->index].UpdateRefittability(_gted[e->index].cargo_allowed != 0);
01284 _gted[e->index].defaultcargo_grf = _cur.grffile;
01285 break;
01286
01287 case 0x29:
01288 _gted[e->index].cargo_disallowed = buf->ReadWord();
01289 _gted[e->index].UpdateRefittability(false);
01290 break;
01291
01292 case 0x2A:
01293 ei->base_intro = buf->ReadDWord();
01294 break;
01295
01296 case PROP_TRAIN_CARGO_AGE_PERIOD:
01297 ei->cargo_age_period = buf->ReadWord();
01298 break;
01299
01300 case 0x2C:
01301 case 0x2D: {
01302 uint8 count = buf->ReadByte();
01303 _gted[e->index].UpdateRefittability(prop == 0x2C && count != 0);
01304 if (prop == 0x2C) _gted[e->index].defaultcargo_grf = _cur.grffile;
01305 uint32 &ctt = prop == 0x2C ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask;
01306 ctt = 0;
01307 while (count--) {
01308 CargoID ctype = GetCargoTranslation(buf->ReadByte(), _cur.grffile);
01309 if (ctype == CT_INVALID) continue;
01310 SetBit(ctt, ctype);
01311 }
01312 break;
01313 }
01314
01315 default:
01316 ret = CommonVehicleChangeInfo(ei, prop, buf);
01317 break;
01318 }
01319 }
01320
01321 return ret;
01322 }
01323
01332 static ChangeInfoResult RoadVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader *buf)
01333 {
01334 ChangeInfoResult ret = CIR_SUCCESS;
01335
01336 for (int i = 0; i < numinfo; i++) {
01337 Engine *e = GetNewEngine(_cur.grffile, VEH_ROAD, engine + i);
01338 if (e == NULL) return CIR_INVALID_ID;
01339
01340 EngineInfo *ei = &e->info;
01341 RoadVehicleInfo *rvi = &e->u.road;
01342
01343 switch (prop) {
01344 case 0x08:
01345 rvi->max_speed = buf->ReadByte();
01346 break;
01347
01348 case PROP_ROADVEH_RUNNING_COST_FACTOR:
01349 rvi->running_cost = buf->ReadByte();
01350 break;
01351
01352 case 0x0A:
01353 ConvertTTDBasePrice(buf->ReadDWord(), "RoadVehicleChangeInfo", &rvi->running_cost_class);
01354 break;
01355
01356 case 0x0E: {
01357 uint8 spriteid = buf->ReadByte();
01358 uint8 orig_spriteid = spriteid;
01359
01360
01361 if (spriteid == 0xFF) spriteid = 0xFD;
01362
01363 if (spriteid < 0xFD) spriteid >>= 1;
01364
01365 if (IsValidNewGRFImageIndex<VEH_ROAD>(spriteid)) {
01366 rvi->image_index = spriteid;
01367 } else {
01368 grfmsg(1, "RoadVehicleChangeInfo: Invalid Sprite %d specified, ignoring", orig_spriteid);
01369 rvi->image_index = 0;
01370 }
01371 break;
01372 }
01373
01374 case PROP_ROADVEH_CARGO_CAPACITY:
01375 rvi->capacity = buf->ReadByte();
01376 break;
01377
01378 case 0x10: {
01379 _gted[e->index].defaultcargo_grf = _cur.grffile;
01380 uint8 ctype = buf->ReadByte();
01381
01382 if (ctype == 0xFF) {
01383
01384 ei->cargo_type = CT_INVALID;
01385 } else if (_cur.grffile->grf_version >= 8) {
01386
01387 ei->cargo_type = GetCargoTranslation(ctype, _cur.grffile);
01388 } else if (ctype < NUM_CARGO) {
01389
01390 ei->cargo_type = ctype;
01391 } else {
01392 ei->cargo_type = CT_INVALID;
01393 grfmsg(2, "RailVehicleChangeInfo: Invalid cargo type %d, using first refittable", ctype);
01394 }
01395 break;
01396 }
01397
01398 case PROP_ROADVEH_COST_FACTOR:
01399 rvi->cost_factor = buf->ReadByte();
01400 break;
01401
01402 case 0x12:
01403 rvi->sfx = buf->ReadByte();
01404 break;
01405
01406 case PROP_ROADVEH_POWER:
01407 rvi->power = buf->ReadByte();
01408 break;
01409
01410 case PROP_ROADVEH_WEIGHT:
01411 rvi->weight = buf->ReadByte();
01412 break;
01413
01414 case PROP_ROADVEH_SPEED:
01415 _gted[e->index].rv_max_speed = buf->ReadByte();
01416 break;
01417
01418 case 0x16: {
01419 uint32 mask = buf->ReadDWord();
01420 _gted[e->index].UpdateRefittability(mask != 0);
01421 ei->refit_mask = TranslateRefitMask(mask);
01422 _gted[e->index].defaultcargo_grf = _cur.grffile;
01423 break;
01424 }
01425
01426 case 0x17:
01427 ei->callback_mask = buf->ReadByte();
01428 break;
01429
01430 case PROP_ROADVEH_TRACTIVE_EFFORT:
01431 rvi->tractive_effort = buf->ReadByte();
01432 break;
01433
01434 case 0x19:
01435 rvi->air_drag = buf->ReadByte();
01436 break;
01437
01438 case 0x1A:
01439 ei->refit_cost = buf->ReadByte();
01440 break;
01441
01442 case 0x1B:
01443 ei->retire_early = buf->ReadByte();
01444 break;
01445
01446 case 0x1C:
01447 ei->misc_flags = buf->ReadByte();
01448 _loaded_newgrf_features.has_2CC |= HasBit(ei->misc_flags, EF_USES_2CC);
01449 break;
01450
01451 case 0x1D:
01452 _gted[e->index].cargo_allowed = buf->ReadWord();
01453 _gted[e->index].UpdateRefittability(_gted[e->index].cargo_allowed != 0);
01454 _gted[e->index].defaultcargo_grf = _cur.grffile;
01455 break;
01456
01457 case 0x1E:
01458 _gted[e->index].cargo_disallowed = buf->ReadWord();
01459 _gted[e->index].UpdateRefittability(false);
01460 break;
01461
01462 case 0x1F:
01463 ei->base_intro = buf->ReadDWord();
01464 break;
01465
01466 case 0x20:
01467 AlterVehicleListOrder(e->index, buf->ReadExtendedByte());
01468 break;
01469
01470 case 0x21:
01471 rvi->visual_effect = buf->ReadByte();
01472
01473
01474 if (rvi->visual_effect == VE_DEFAULT) {
01475 assert(HasBit(rvi->visual_effect, VE_DISABLE_EFFECT));
01476 SB(rvi->visual_effect, VE_TYPE_START, VE_TYPE_COUNT, 0);
01477 }
01478 break;
01479
01480 case PROP_ROADVEH_CARGO_AGE_PERIOD:
01481 ei->cargo_age_period = buf->ReadWord();
01482 break;
01483
01484 case PROP_ROADVEH_SHORTEN_FACTOR:
01485 rvi->shorten_factor = buf->ReadByte();
01486 break;
01487
01488 case 0x24:
01489 case 0x25: {
01490 uint8 count = buf->ReadByte();
01491 _gted[e->index].UpdateRefittability(prop == 0x24 && count != 0);
01492 if (prop == 0x24) _gted[e->index].defaultcargo_grf = _cur.grffile;
01493 uint32 &ctt = prop == 0x24 ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask;
01494 ctt = 0;
01495 while (count--) {
01496 CargoID ctype = GetCargoTranslation(buf->ReadByte(), _cur.grffile);
01497 if (ctype == CT_INVALID) continue;
01498 SetBit(ctt, ctype);
01499 }
01500 break;
01501 }
01502
01503 default:
01504 ret = CommonVehicleChangeInfo(ei, prop, buf);
01505 break;
01506 }
01507 }
01508
01509 return ret;
01510 }
01511
01520 static ChangeInfoResult ShipVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader *buf)
01521 {
01522 ChangeInfoResult ret = CIR_SUCCESS;
01523
01524 for (int i = 0; i < numinfo; i++) {
01525 Engine *e = GetNewEngine(_cur.grffile, VEH_SHIP, engine + i);
01526 if (e == NULL) return CIR_INVALID_ID;
01527
01528 EngineInfo *ei = &e->info;
01529 ShipVehicleInfo *svi = &e->u.ship;
01530
01531 switch (prop) {
01532 case 0x08: {
01533 uint8 spriteid = buf->ReadByte();
01534 uint8 orig_spriteid = spriteid;
01535
01536
01537 if (spriteid == 0xFF) spriteid = 0xFD;
01538
01539 if (spriteid < 0xFD) spriteid >>= 1;
01540
01541 if (IsValidNewGRFImageIndex<VEH_SHIP>(spriteid)) {
01542 svi->image_index = spriteid;
01543 } else {
01544 grfmsg(1, "ShipVehicleChangeInfo: Invalid Sprite %d specified, ignoring", orig_spriteid);
01545 svi->image_index = 0;
01546 }
01547 break;
01548 }
01549
01550 case 0x09:
01551 svi->old_refittable = (buf->ReadByte() != 0);
01552 break;
01553
01554 case PROP_SHIP_COST_FACTOR:
01555 svi->cost_factor = buf->ReadByte();
01556 break;
01557
01558 case PROP_SHIP_SPEED:
01559 svi->max_speed = buf->ReadByte();
01560 break;
01561
01562 case 0x0C: {
01563 _gted[e->index].defaultcargo_grf = _cur.grffile;
01564 uint8 ctype = buf->ReadByte();
01565
01566 if (ctype == 0xFF) {
01567
01568 ei->cargo_type = CT_INVALID;
01569 } else if (_cur.grffile->grf_version >= 8) {
01570
01571 ei->cargo_type = GetCargoTranslation(ctype, _cur.grffile);
01572 } else if (ctype < NUM_CARGO) {
01573
01574 ei->cargo_type = ctype;
01575 } else {
01576 ei->cargo_type = CT_INVALID;
01577 grfmsg(2, "RailVehicleChangeInfo: Invalid cargo type %d, using first refittable", ctype);
01578 }
01579 break;
01580 }
01581
01582 case PROP_SHIP_CARGO_CAPACITY:
01583 svi->capacity = buf->ReadWord();
01584 break;
01585
01586 case PROP_SHIP_RUNNING_COST_FACTOR:
01587 svi->running_cost = buf->ReadByte();
01588 break;
01589
01590 case 0x10:
01591 svi->sfx = buf->ReadByte();
01592 break;
01593
01594 case 0x11: {
01595 uint32 mask = buf->ReadDWord();
01596 _gted[e->index].UpdateRefittability(mask != 0);
01597 ei->refit_mask = TranslateRefitMask(mask);
01598 _gted[e->index].defaultcargo_grf = _cur.grffile;
01599 break;
01600 }
01601
01602 case 0x12:
01603 ei->callback_mask = buf->ReadByte();
01604 break;
01605
01606 case 0x13:
01607 ei->refit_cost = buf->ReadByte();
01608 break;
01609
01610 case 0x14:
01611 svi->ocean_speed_frac = buf->ReadByte();
01612 break;
01613
01614 case 0x15:
01615 svi->canal_speed_frac = buf->ReadByte();
01616 break;
01617
01618 case 0x16:
01619 ei->retire_early = buf->ReadByte();
01620 break;
01621
01622 case 0x17:
01623 ei->misc_flags = buf->ReadByte();
01624 _loaded_newgrf_features.has_2CC |= HasBit(ei->misc_flags, EF_USES_2CC);
01625 break;
01626
01627 case 0x18:
01628 _gted[e->index].cargo_allowed = buf->ReadWord();
01629 _gted[e->index].UpdateRefittability(_gted[e->index].cargo_allowed != 0);
01630 _gted[e->index].defaultcargo_grf = _cur.grffile;
01631 break;
01632
01633 case 0x19:
01634 _gted[e->index].cargo_disallowed = buf->ReadWord();
01635 _gted[e->index].UpdateRefittability(false);
01636 break;
01637
01638 case 0x1A:
01639 ei->base_intro = buf->ReadDWord();
01640 break;
01641
01642 case 0x1B:
01643 AlterVehicleListOrder(e->index, buf->ReadExtendedByte());
01644 break;
01645
01646 case 0x1C:
01647 svi->visual_effect = buf->ReadByte();
01648
01649
01650 if (svi->visual_effect == VE_DEFAULT) {
01651 assert(HasBit(svi->visual_effect, VE_DISABLE_EFFECT));
01652 SB(svi->visual_effect, VE_TYPE_START, VE_TYPE_COUNT, 0);
01653 }
01654 break;
01655
01656 case PROP_SHIP_CARGO_AGE_PERIOD:
01657 ei->cargo_age_period = buf->ReadWord();
01658 break;
01659
01660 case 0x1E:
01661 case 0x1F: {
01662 uint8 count = buf->ReadByte();
01663 _gted[e->index].UpdateRefittability(prop == 0x1E && count != 0);
01664 if (prop == 0x1E) _gted[e->index].defaultcargo_grf = _cur.grffile;
01665 uint32 &ctt = prop == 0x1E ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask;
01666 ctt = 0;
01667 while (count--) {
01668 CargoID ctype = GetCargoTranslation(buf->ReadByte(), _cur.grffile);
01669 if (ctype == CT_INVALID) continue;
01670 SetBit(ctt, ctype);
01671 }
01672 break;
01673 }
01674
01675 default:
01676 ret = CommonVehicleChangeInfo(ei, prop, buf);
01677 break;
01678 }
01679 }
01680
01681 return ret;
01682 }
01683
01692 static ChangeInfoResult AircraftVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader *buf)
01693 {
01694 ChangeInfoResult ret = CIR_SUCCESS;
01695
01696 for (int i = 0; i < numinfo; i++) {
01697 Engine *e = GetNewEngine(_cur.grffile, VEH_AIRCRAFT, engine + i);
01698 if (e == NULL) return CIR_INVALID_ID;
01699
01700 EngineInfo *ei = &e->info;
01701 AircraftVehicleInfo *avi = &e->u.air;
01702
01703 switch (prop) {
01704 case 0x08: {
01705 uint8 spriteid = buf->ReadByte();
01706 uint8 orig_spriteid = spriteid;
01707
01708
01709 if (spriteid == 0xFF) spriteid = 0xFD;
01710
01711 if (spriteid < 0xFD) spriteid >>= 1;
01712
01713 if (IsValidNewGRFImageIndex<VEH_AIRCRAFT>(spriteid)) {
01714 avi->image_index = spriteid;
01715 } else {
01716 grfmsg(1, "AircraftVehicleChangeInfo: Invalid Sprite %d specified, ignoring", orig_spriteid);
01717 avi->image_index = 0;
01718 }
01719 break;
01720 }
01721
01722 case 0x09:
01723 if (buf->ReadByte() == 0) {
01724 avi->subtype = AIR_HELI;
01725 } else {
01726 SB(avi->subtype, 0, 1, 1);
01727 }
01728 break;
01729
01730 case 0x0A:
01731 SB(avi->subtype, 1, 1, (buf->ReadByte() != 0 ? 1 : 0));
01732 break;
01733
01734 case PROP_AIRCRAFT_COST_FACTOR:
01735 avi->cost_factor = buf->ReadByte();
01736 break;
01737
01738 case PROP_AIRCRAFT_SPEED:
01739 avi->max_speed = (buf->ReadByte() * 128) / 10;
01740 break;
01741
01742 case 0x0D:
01743 avi->acceleration = buf->ReadByte();
01744 break;
01745
01746 case PROP_AIRCRAFT_RUNNING_COST_FACTOR:
01747 avi->running_cost = buf->ReadByte();
01748 break;
01749
01750 case PROP_AIRCRAFT_PASSENGER_CAPACITY:
01751 avi->passenger_capacity = buf->ReadWord();
01752 break;
01753
01754 case PROP_AIRCRAFT_MAIL_CAPACITY:
01755 avi->mail_capacity = buf->ReadByte();
01756 break;
01757
01758 case 0x12:
01759 avi->sfx = buf->ReadByte();
01760 break;
01761
01762 case 0x13: {
01763 uint32 mask = buf->ReadDWord();
01764 _gted[e->index].UpdateRefittability(mask != 0);
01765 ei->refit_mask = TranslateRefitMask(mask);
01766 _gted[e->index].defaultcargo_grf = _cur.grffile;
01767 break;
01768 }
01769
01770 case 0x14:
01771 ei->callback_mask = buf->ReadByte();
01772 break;
01773
01774 case 0x15:
01775 ei->refit_cost = buf->ReadByte();
01776 break;
01777
01778 case 0x16:
01779 ei->retire_early = buf->ReadByte();
01780 break;
01781
01782 case 0x17:
01783 ei->misc_flags = buf->ReadByte();
01784 _loaded_newgrf_features.has_2CC |= HasBit(ei->misc_flags, EF_USES_2CC);
01785 break;
01786
01787 case 0x18:
01788 _gted[e->index].cargo_allowed = buf->ReadWord();
01789 _gted[e->index].UpdateRefittability(_gted[e->index].cargo_allowed != 0);
01790 _gted[e->index].defaultcargo_grf = _cur.grffile;
01791 break;
01792
01793 case 0x19:
01794 _gted[e->index].cargo_disallowed = buf->ReadWord();
01795 _gted[e->index].UpdateRefittability(false);
01796 break;
01797
01798 case 0x1A:
01799 ei->base_intro = buf->ReadDWord();
01800 break;
01801
01802 case 0x1B:
01803 AlterVehicleListOrder(e->index, buf->ReadExtendedByte());
01804 break;
01805
01806 case PROP_AIRCRAFT_CARGO_AGE_PERIOD:
01807 ei->cargo_age_period = buf->ReadWord();
01808 break;
01809
01810 case 0x1D:
01811 case 0x1E: {
01812 uint8 count = buf->ReadByte();
01813 _gted[e->index].UpdateRefittability(prop == 0x1D && count != 0);
01814 if (prop == 0x1D) _gted[e->index].defaultcargo_grf = _cur.grffile;
01815 uint32 &ctt = prop == 0x1D ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask;
01816 ctt = 0;
01817 while (count--) {
01818 CargoID ctype = GetCargoTranslation(buf->ReadByte(), _cur.grffile);
01819 if (ctype == CT_INVALID) continue;
01820 SetBit(ctt, ctype);
01821 }
01822 break;
01823 }
01824
01825 case PROP_AIRCRAFT_RANGE:
01826 avi->max_range = buf->ReadWord();
01827 break;
01828
01829 default:
01830 ret = CommonVehicleChangeInfo(ei, prop, buf);
01831 break;
01832 }
01833 }
01834
01835 return ret;
01836 }
01837
01846 static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, ByteReader *buf)
01847 {
01848 ChangeInfoResult ret = CIR_SUCCESS;
01849
01850 if (stid + numinfo > NUM_STATIONS_PER_GRF) {
01851 grfmsg(1, "StationChangeInfo: Station %u is invalid, max %u, ignoring", stid + numinfo, NUM_STATIONS_PER_GRF);
01852 return CIR_INVALID_ID;
01853 }
01854
01855
01856 if (_cur.grffile->stations == NULL) _cur.grffile->stations = CallocT<StationSpec*>(NUM_STATIONS_PER_GRF);
01857
01858 for (int i = 0; i < numinfo; i++) {
01859 StationSpec *statspec = _cur.grffile->stations[stid + i];
01860
01861
01862 if (statspec == NULL && prop != 0x08) {
01863 grfmsg(2, "StationChangeInfo: Attempt to modify undefined station %u, ignoring", stid + i);
01864 return CIR_INVALID_ID;
01865 }
01866
01867 switch (prop) {
01868 case 0x08: {
01869 StationSpec **spec = &_cur.grffile->stations[stid + i];
01870
01871
01872 if (*spec == NULL) *spec = CallocT<StationSpec>(1);
01873
01874
01875 uint32 classid = buf->ReadDWord();
01876 (*spec)->cls_id = StationClass::Allocate(BSWAP32(classid));
01877 break;
01878 }
01879
01880 case 0x09:
01881 statspec->tiles = buf->ReadExtendedByte();
01882 delete[] statspec->renderdata;
01883 statspec->renderdata = new NewGRFSpriteLayout[statspec->tiles];
01884
01885 for (uint t = 0; t < statspec->tiles; t++) {
01886 NewGRFSpriteLayout *dts = &statspec->renderdata[t];
01887 dts->consistent_max_offset = UINT16_MAX;
01888
01889 if (buf->HasData(4) && *(uint32*)buf->Data() == 0) {
01890 buf->Skip(4);
01891 extern const DrawTileSprites _station_display_datas_rail[8];
01892 dts->Clone(&_station_display_datas_rail[t % 8]);
01893 continue;
01894 }
01895
01896 ReadSpriteLayoutSprite(buf, false, false, false, GSF_STATIONS, &dts->ground);
01897
01898 if (_cur.skip_sprites < 0) return CIR_DISABLED;
01899
01900 static SmallVector<DrawTileSeqStruct, 8> tmp_layout;
01901 tmp_layout.Clear();
01902 for (;;) {
01903
01904 DrawTileSeqStruct *dtss = tmp_layout.Append();
01905 MemSetT(dtss, 0);
01906
01907 dtss->delta_x = buf->ReadByte();
01908 if (dtss->IsTerminator()) break;
01909 dtss->delta_y = buf->ReadByte();
01910 dtss->delta_z = buf->ReadByte();
01911 dtss->size_x = buf->ReadByte();
01912 dtss->size_y = buf->ReadByte();
01913 dtss->size_z = buf->ReadByte();
01914
01915 ReadSpriteLayoutSprite(buf, false, true, false, GSF_STATIONS, &dtss->image);
01916
01917 if (_cur.skip_sprites < 0) return CIR_DISABLED;
01918 }
01919 dts->Clone(tmp_layout.Begin());
01920 }
01921 break;
01922
01923 case 0x0A: {
01924 byte srcid = buf->ReadByte();
01925 const StationSpec *srcstatspec = _cur.grffile->stations[srcid];
01926
01927 if (srcstatspec == NULL) {
01928 grfmsg(1, "StationChangeInfo: Station %u is not defined, cannot copy sprite layout to %u.", srcid, stid + i);
01929 continue;
01930 }
01931
01932 delete[] statspec->renderdata;
01933
01934 statspec->tiles = srcstatspec->tiles;
01935 statspec->renderdata = new NewGRFSpriteLayout[statspec->tiles];
01936 for (uint t = 0; t < statspec->tiles; t++) {
01937 statspec->renderdata[t].Clone(&srcstatspec->renderdata[t]);
01938 }
01939 break;
01940 }
01941
01942 case 0x0B:
01943 statspec->callback_mask = buf->ReadByte();
01944 break;
01945
01946 case 0x0C:
01947 statspec->disallowed_platforms = buf->ReadByte();
01948 break;
01949
01950 case 0x0D:
01951 statspec->disallowed_lengths = buf->ReadByte();
01952 break;
01953
01954 case 0x0E:
01955 statspec->copied_layouts = false;
01956
01957 while (buf->HasData()) {
01958 byte length = buf->ReadByte();
01959 byte number = buf->ReadByte();
01960 StationLayout layout;
01961 uint l, p;
01962
01963 if (length == 0 || number == 0) break;
01964
01965 if (length > statspec->lengths) {
01966 statspec->platforms = ReallocT(statspec->platforms, length);
01967 memset(statspec->platforms + statspec->lengths, 0, length - statspec->lengths);
01968
01969 statspec->layouts = ReallocT(statspec->layouts, length);
01970 memset(statspec->layouts + statspec->lengths, 0,
01971 (length - statspec->lengths) * sizeof(*statspec->layouts));
01972
01973 statspec->lengths = length;
01974 }
01975 l = length - 1;
01976
01977 if (number > statspec->platforms[l]) {
01978 statspec->layouts[l] = ReallocT(statspec->layouts[l], number);
01979
01980 memset(statspec->layouts[l] + statspec->platforms[l], 0,
01981 (number - statspec->platforms[l]) * sizeof(**statspec->layouts));
01982
01983 statspec->platforms[l] = number;
01984 }
01985
01986 p = 0;
01987 layout = MallocT<byte>(length * number);
01988 try {
01989 for (l = 0; l < length; l++) {
01990 for (p = 0; p < number; p++) {
01991 layout[l * number + p] = buf->ReadByte();
01992 }
01993 }
01994 } catch (...) {
01995 free(layout);
01996 throw;
01997 }
01998
01999 l--;
02000 p--;
02001 free(statspec->layouts[l][p]);
02002 statspec->layouts[l][p] = layout;
02003 }
02004 break;
02005
02006 case 0x0F: {
02007 byte srcid = buf->ReadByte();
02008 const StationSpec *srcstatspec = _cur.grffile->stations[srcid];
02009
02010 if (srcstatspec == NULL) {
02011 grfmsg(1, "StationChangeInfo: Station %u is not defined, cannot copy tile layout to %u.", srcid, stid + i);
02012 continue;
02013 }
02014
02015 statspec->lengths = srcstatspec->lengths;
02016 statspec->platforms = srcstatspec->platforms;
02017 statspec->layouts = srcstatspec->layouts;
02018 statspec->copied_layouts = true;
02019 break;
02020 }
02021
02022 case 0x10:
02023 statspec->cargo_threshold = buf->ReadWord();
02024 break;
02025
02026 case 0x11:
02027 statspec->pylons = buf->ReadByte();
02028 break;
02029
02030 case 0x12:
02031 statspec->cargo_triggers = buf->ReadDWord();
02032 if (_cur.grffile->grf_version >= 7) {
02033 statspec->cargo_triggers = TranslateRefitMask(statspec->cargo_triggers);
02034 }
02035 break;
02036
02037 case 0x13:
02038 statspec->flags = buf->ReadByte();
02039 break;
02040
02041 case 0x14:
02042 statspec->wires = buf->ReadByte();
02043 break;
02044
02045 case 0x15:
02046 statspec->blocked = buf->ReadByte();
02047 break;
02048
02049 case 0x16:
02050 statspec->animation.frames = buf->ReadByte();
02051 statspec->animation.status = buf->ReadByte();
02052 break;
02053
02054 case 0x17:
02055 statspec->animation.speed = buf->ReadByte();
02056 break;
02057
02058 case 0x18:
02059 statspec->animation.triggers = buf->ReadWord();
02060 break;
02061
02062 case 0x1A:
02063 statspec->tiles = buf->ReadExtendedByte();
02064 delete[] statspec->renderdata;
02065 statspec->renderdata = new NewGRFSpriteLayout[statspec->tiles];
02066
02067 for (uint t = 0; t < statspec->tiles; t++) {
02068 NewGRFSpriteLayout *dts = &statspec->renderdata[t];
02069 uint num_building_sprites = buf->ReadByte();
02070
02071 if (ReadSpriteLayout(buf, num_building_sprites, false, GSF_STATIONS, true, false, dts)) return CIR_DISABLED;
02072 }
02073 break;
02074
02075 default:
02076 ret = CIR_UNKNOWN;
02077 break;
02078 }
02079 }
02080
02081 return ret;
02082 }
02083
02092 static ChangeInfoResult CanalChangeInfo(uint id, int numinfo, int prop, ByteReader *buf)
02093 {
02094 ChangeInfoResult ret = CIR_SUCCESS;
02095
02096 if (id + numinfo > CF_END) {
02097 grfmsg(1, "CanalChangeInfo: Canal feature %u is invalid, max %u, ignoring", id + numinfo, CF_END);
02098 return CIR_INVALID_ID;
02099 }
02100
02101 for (int i = 0; i < numinfo; i++) {
02102 CanalProperties *cp = &_cur.grffile->canal_local_properties[id + i];
02103
02104 switch (prop) {
02105 case 0x08:
02106 cp->callback_mask = buf->ReadByte();
02107 break;
02108
02109 case 0x09:
02110 cp->flags = buf->ReadByte();
02111 break;
02112
02113 default:
02114 ret = CIR_UNKNOWN;
02115 break;
02116 }
02117 }
02118
02119 return ret;
02120 }
02121
02130 static ChangeInfoResult BridgeChangeInfo(uint brid, int numinfo, int prop, ByteReader *buf)
02131 {
02132 ChangeInfoResult ret = CIR_SUCCESS;
02133
02134 if (brid + numinfo > MAX_BRIDGES) {
02135 grfmsg(1, "BridgeChangeInfo: Bridge %u is invalid, max %u, ignoring", brid + numinfo, MAX_BRIDGES);
02136 return CIR_INVALID_ID;
02137 }
02138
02139 for (int i = 0; i < numinfo; i++) {
02140 BridgeSpec *bridge = &_bridge[brid + i];
02141
02142 switch (prop) {
02143 case 0x08: {
02144
02145 byte year = buf->ReadByte();
02146 bridge->avail_year = (year > 0 ? ORIGINAL_BASE_YEAR + year : 0);
02147 break;
02148 }
02149
02150 case 0x09:
02151 bridge->min_length = buf->ReadByte();
02152 break;
02153
02154 case 0x0A:
02155 bridge->max_length = buf->ReadByte();
02156 if (bridge->max_length > 16) bridge->max_length = 0xFFFF;
02157 break;
02158
02159 case 0x0B:
02160 bridge->price = buf->ReadByte();
02161 break;
02162
02163 case 0x0C:
02164 bridge->speed = buf->ReadWord();
02165 break;
02166
02167 case 0x0D: {
02168 byte tableid = buf->ReadByte();
02169 byte numtables = buf->ReadByte();
02170
02171 if (bridge->sprite_table == NULL) {
02172
02173 bridge->sprite_table = CallocT<PalSpriteID*>(7);
02174 }
02175
02176 for (; numtables-- != 0; tableid++) {
02177 if (tableid >= 7) {
02178 grfmsg(1, "BridgeChangeInfo: Table %d >= 7, skipping", tableid);
02179 for (byte sprite = 0; sprite < 32; sprite++) buf->ReadDWord();
02180 continue;
02181 }
02182
02183 if (bridge->sprite_table[tableid] == NULL) {
02184 bridge->sprite_table[tableid] = MallocT<PalSpriteID>(32);
02185 }
02186
02187 for (byte sprite = 0; sprite < 32; sprite++) {
02188 SpriteID image = buf->ReadWord();
02189 PaletteID pal = buf->ReadWord();
02190
02191 bridge->sprite_table[tableid][sprite].sprite = image;
02192 bridge->sprite_table[tableid][sprite].pal = pal;
02193
02194 MapSpriteMappingRecolour(&bridge->sprite_table[tableid][sprite]);
02195 }
02196 }
02197 break;
02198 }
02199
02200 case 0x0E:
02201 bridge->flags = buf->ReadByte();
02202 break;
02203
02204 case 0x0F:
02205 bridge->avail_year = Clamp(buf->ReadDWord(), MIN_YEAR, MAX_YEAR);
02206 break;
02207
02208 case 0x10: {
02209 StringID newone = GetGRFStringID(_cur.grffile->grfid, buf->ReadWord());
02210 if (newone != STR_UNDEFINED) bridge->material = newone;
02211 break;
02212 }
02213
02214 case 0x11:
02215 case 0x12: {
02216 StringID newone = GetGRFStringID(_cur.grffile->grfid, buf->ReadWord());
02217 if (newone != STR_UNDEFINED) bridge->transport_name[prop - 0x11] = newone;
02218 break;
02219 }
02220
02221 case 0x13:
02222 bridge->price = buf->ReadWord();
02223 break;
02224
02225 default:
02226 ret = CIR_UNKNOWN;
02227 break;
02228 }
02229 }
02230
02231 return ret;
02232 }
02233
02240 static ChangeInfoResult IgnoreTownHouseProperty(int prop, ByteReader *buf)
02241 {
02242 ChangeInfoResult ret = CIR_SUCCESS;
02243
02244 switch (prop) {
02245 case 0x09:
02246 case 0x0B:
02247 case 0x0C:
02248 case 0x0D:
02249 case 0x0E:
02250 case 0x0F:
02251 case 0x11:
02252 case 0x14:
02253 case 0x15:
02254 case 0x16:
02255 case 0x18:
02256 case 0x19:
02257 case 0x1A:
02258 case 0x1B:
02259 case 0x1C:
02260 case 0x1D:
02261 case 0x1F:
02262 buf->ReadByte();
02263 break;
02264
02265 case 0x0A:
02266 case 0x10:
02267 case 0x12:
02268 case 0x13:
02269 case 0x21:
02270 case 0x22:
02271 buf->ReadWord();
02272 break;
02273
02274 case 0x1E:
02275 buf->ReadDWord();
02276 break;
02277
02278 case 0x17:
02279 for (uint j = 0; j < 4; j++) buf->ReadByte();
02280 break;
02281
02282 case 0x20: {
02283 byte count = buf->ReadByte();
02284 for (byte j = 0; j < count; j++) buf->ReadByte();
02285 break;
02286 }
02287
02288 default:
02289 ret = CIR_UNKNOWN;
02290 break;
02291 }
02292 return ret;
02293 }
02294
02303 static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, ByteReader *buf)
02304 {
02305 ChangeInfoResult ret = CIR_SUCCESS;
02306
02307 if (hid + numinfo > NUM_HOUSES_PER_GRF) {
02308 grfmsg(1, "TownHouseChangeInfo: Too many houses loaded (%u), max (%u). Ignoring.", hid + numinfo, NUM_HOUSES_PER_GRF);
02309 return CIR_INVALID_ID;
02310 }
02311
02312
02313 if (_cur.grffile->housespec == NULL) {
02314 _cur.grffile->housespec = CallocT<HouseSpec*>(NUM_HOUSES_PER_GRF);
02315 }
02316
02317 for (int i = 0; i < numinfo; i++) {
02318 HouseSpec *housespec = _cur.grffile->housespec[hid + i];
02319
02320 if (prop != 0x08 && housespec == NULL) {
02321
02322 ChangeInfoResult cir = IgnoreTownHouseProperty(prop, buf);
02323 if (cir > ret) ret = cir;
02324 continue;
02325 }
02326
02327 switch (prop) {
02328 case 0x08: {
02329 HouseSpec **house = &_cur.grffile->housespec[hid + i];
02330 byte subs_id = buf->ReadByte();
02331
02332 if (subs_id == 0xFF) {
02333
02334
02335 HouseSpec::Get(hid + i)->enabled = false;
02336 continue;
02337 } else if (subs_id >= NEW_HOUSE_OFFSET) {
02338
02339 grfmsg(2, "TownHouseChangeInfo: Attempt to use new house %u as substitute house for %u. Ignoring.", subs_id, hid + i);
02340 continue;
02341 }
02342
02343
02344 if (*house == NULL) *house = CallocT<HouseSpec>(1);
02345
02346 housespec = *house;
02347
02348 MemCpyT(housespec, HouseSpec::Get(subs_id));
02349
02350 housespec->enabled = true;
02351 housespec->grf_prop.local_id = hid + i;
02352 housespec->grf_prop.subst_id = subs_id;
02353 housespec->grf_prop.grffile = _cur.grffile;
02354 housespec->random_colour[0] = 0x04;
02355 housespec->random_colour[1] = 0x08;
02356 housespec->random_colour[2] = 0x0C;
02357 housespec->random_colour[3] = 0x06;
02358
02359
02360
02361
02362
02363 if (!CargoSpec::Get(housespec->accepts_cargo[2])->IsValid()) {
02364 housespec->cargo_acceptance[2] = 0;
02365 }
02366
02367 _loaded_newgrf_features.has_newhouses = true;
02368 break;
02369 }
02370
02371 case 0x09:
02372 housespec->building_flags = (BuildingFlags)buf->ReadByte();
02373 break;
02374
02375 case 0x0A: {
02376 uint16 years = buf->ReadWord();
02377 housespec->min_year = GB(years, 0, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 0, 8);
02378 housespec->max_year = GB(years, 8, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 8, 8);
02379 break;
02380 }
02381
02382 case 0x0B:
02383 housespec->population = buf->ReadByte();
02384 break;
02385
02386 case 0x0C:
02387 housespec->mail_generation = buf->ReadByte();
02388 break;
02389
02390 case 0x0D:
02391 case 0x0E:
02392 housespec->cargo_acceptance[prop - 0x0D] = buf->ReadByte();
02393 break;
02394
02395 case 0x0F: {
02396 int8 goods = buf->ReadByte();
02397
02398
02399
02400 CargoID cid = (goods >= 0) ? ((_settings_game.game_creation.landscape == LT_TOYLAND) ? CT_CANDY : CT_GOODS) :
02401 ((_settings_game.game_creation.landscape == LT_TOYLAND) ? CT_FIZZY_DRINKS : CT_FOOD);
02402
02403
02404 if (!CargoSpec::Get(cid)->IsValid()) goods = 0;
02405
02406 housespec->accepts_cargo[2] = cid;
02407 housespec->cargo_acceptance[2] = abs(goods);
02408 break;
02409 }
02410
02411 case 0x10:
02412 housespec->remove_rating_decrease = buf->ReadWord();
02413 break;
02414
02415 case 0x11:
02416 housespec->removal_cost = buf->ReadByte();
02417 break;
02418
02419 case 0x12:
02420 AddStringForMapping(buf->ReadWord(), &housespec->building_name);
02421 break;
02422
02423 case 0x13:
02424 housespec->building_availability = (HouseZones)buf->ReadWord();
02425 break;
02426
02427 case 0x14:
02428 housespec->callback_mask |= buf->ReadByte();
02429 break;
02430
02431 case 0x15: {
02432 byte override = buf->ReadByte();
02433
02434
02435 if (override >= NEW_HOUSE_OFFSET) {
02436 grfmsg(2, "TownHouseChangeInfo: Attempt to override new house %u with house id %u. Ignoring.", override, hid + i);
02437 continue;
02438 }
02439
02440 _house_mngr.Add(hid + i, _cur.grffile->grfid, override);
02441 break;
02442 }
02443
02444 case 0x16:
02445 housespec->processing_time = min(buf->ReadByte(), 63);
02446 break;
02447
02448 case 0x17:
02449 for (uint j = 0; j < 4; j++) housespec->random_colour[j] = buf->ReadByte();
02450 break;
02451
02452 case 0x18:
02453 housespec->probability = buf->ReadByte();
02454 break;
02455
02456 case 0x19:
02457 housespec->extra_flags = (HouseExtraFlags)buf->ReadByte();
02458 break;
02459
02460 case 0x1A:
02461 housespec->animation.frames = buf->ReadByte();
02462 housespec->animation.status = GB(housespec->animation.frames, 7, 1);
02463 SB(housespec->animation.frames, 7, 1, 0);
02464 break;
02465
02466 case 0x1B:
02467 housespec->animation.speed = Clamp(buf->ReadByte(), 2, 16);
02468 break;
02469
02470 case 0x1C:
02471 housespec->class_id = AllocateHouseClassID(buf->ReadByte(), _cur.grffile->grfid);
02472 break;
02473
02474 case 0x1D:
02475 housespec->callback_mask |= (buf->ReadByte() << 8);
02476 break;
02477
02478 case 0x1E: {
02479 uint32 cargotypes = buf->ReadDWord();
02480
02481
02482 if (cargotypes == 0xFFFFFFFF) break;
02483
02484 for (uint j = 0; j < 3; j++) {
02485
02486 uint8 cargo_part = GB(cargotypes, 8 * j, 8);
02487 CargoID cargo = GetCargoTranslation(cargo_part, _cur.grffile);
02488
02489 if (cargo == CT_INVALID) {
02490
02491 housespec->cargo_acceptance[j] = 0;
02492 } else {
02493 housespec->accepts_cargo[j] = cargo;
02494 }
02495 }
02496 break;
02497 }
02498
02499 case 0x1F:
02500 housespec->minimum_life = buf->ReadByte();
02501 break;
02502
02503 case 0x20: {
02504 byte count = buf->ReadByte();
02505 for (byte j = 0; j < count; j++) {
02506 CargoID cargo = GetCargoTranslation(buf->ReadByte(), _cur.grffile);
02507 if (cargo != CT_INVALID) SetBit(housespec->watched_cargoes, cargo);
02508 }
02509 break;
02510 }
02511
02512 case 0x21:
02513 housespec->min_year = buf->ReadWord();
02514 break;
02515
02516 case 0x22:
02517 housespec->max_year = buf->ReadWord();
02518 break;
02519
02520 default:
02521 ret = CIR_UNKNOWN;
02522 break;
02523 }
02524 }
02525
02526 return ret;
02527 }
02528
02535 const LanguageMap *LanguageMap::GetLanguageMap(uint32 grfid, uint8 language_id)
02536 {
02537
02538 const GRFFile *grffile = GetFileByGRFID(grfid);
02539 return (grffile != NULL && grffile->language_map != NULL && language_id < MAX_LANG) ? &grffile->language_map[language_id] : NULL;
02540 }
02541
02551 template <typename T>
02552 static ChangeInfoResult LoadTranslationTable(uint gvid, int numinfo, ByteReader *buf, T &translation_table, const char *name)
02553 {
02554 if (gvid != 0) {
02555 grfmsg(1, "LoadTranslationTable: %s translation table must start at zero", name);
02556 return CIR_INVALID_ID;
02557 }
02558
02559 translation_table.Clear();
02560 for (int i = 0; i < numinfo; i++) {
02561 uint32 item = buf->ReadDWord();
02562 *translation_table.Append() = BSWAP32(item);
02563 }
02564
02565 return CIR_SUCCESS;
02566 }
02567
02576 static ChangeInfoResult GlobalVarChangeInfo(uint gvid, int numinfo, int prop, ByteReader *buf)
02577 {
02578
02579 switch (prop) {
02580 case 0x09:
02581 return LoadTranslationTable(gvid, numinfo, buf, _cur.grffile->cargo_list, "Cargo");
02582
02583 case 0x12:
02584 return LoadTranslationTable(gvid, numinfo, buf, _cur.grffile->railtype_list, "Rail type");
02585
02586 default:
02587 break;
02588 }
02589
02590
02591 ChangeInfoResult ret = CIR_SUCCESS;
02592 for (int i = 0; i < numinfo; i++) {
02593 switch (prop) {
02594 case 0x08: {
02595 int factor = buf->ReadByte();
02596 uint price = gvid + i;
02597
02598 if (price < PR_END) {
02599 _cur.grffile->price_base_multipliers[price] = min<int>(factor - 8, MAX_PRICE_MODIFIER);
02600 } else {
02601 grfmsg(1, "GlobalVarChangeInfo: Price %d out of range, ignoring", price);
02602 }
02603 break;
02604 }
02605
02606 case 0x0A: {
02607 uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
02608 StringID newone = GetGRFStringID(_cur.grffile->grfid, buf->ReadWord());
02609
02610 if ((newone != STR_UNDEFINED) && (curidx < CURRENCY_END)) {
02611 _currency_specs[curidx].name = newone;
02612 }
02613 break;
02614 }
02615
02616 case 0x0B: {
02617 uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
02618 uint32 rate = buf->ReadDWord();
02619
02620 if (curidx < CURRENCY_END) {
02621
02622
02623
02624 _currency_specs[curidx].rate = rate / 1000;
02625 } else {
02626 grfmsg(1, "GlobalVarChangeInfo: Currency multipliers %d out of range, ignoring", curidx);
02627 }
02628 break;
02629 }
02630
02631 case 0x0C: {
02632 uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
02633 uint16 options = buf->ReadWord();
02634
02635 if (curidx < CURRENCY_END) {
02636 _currency_specs[curidx].separator[0] = GB(options, 0, 8);
02637 _currency_specs[curidx].separator[1] = '\0';
02638
02639
02640 _currency_specs[curidx].symbol_pos = GB(options, 8, 1);
02641 } else {
02642 grfmsg(1, "GlobalVarChangeInfo: Currency option %d out of range, ignoring", curidx);
02643 }
02644 break;
02645 }
02646
02647 case 0x0D: {
02648 uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
02649 uint32 tempfix = buf->ReadDWord();
02650
02651 if (curidx < CURRENCY_END) {
02652 memcpy(_currency_specs[curidx].prefix, &tempfix, 4);
02653 _currency_specs[curidx].prefix[4] = 0;
02654 } else {
02655 grfmsg(1, "GlobalVarChangeInfo: Currency symbol %d out of range, ignoring", curidx);
02656 }
02657 break;
02658 }
02659
02660 case 0x0E: {
02661 uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
02662 uint32 tempfix = buf->ReadDWord();
02663
02664 if (curidx < CURRENCY_END) {
02665 memcpy(&_currency_specs[curidx].suffix, &tempfix, 4);
02666 _currency_specs[curidx].suffix[4] = 0;
02667 } else {
02668 grfmsg(1, "GlobalVarChangeInfo: Currency symbol %d out of range, ignoring", curidx);
02669 }
02670 break;
02671 }
02672
02673 case 0x0F: {
02674 uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
02675 Year year_euro = buf->ReadWord();
02676
02677 if (curidx < CURRENCY_END) {
02678 _currency_specs[curidx].to_euro = year_euro;
02679 } else {
02680 grfmsg(1, "GlobalVarChangeInfo: Euro intro date %d out of range, ignoring", curidx);
02681 }
02682 break;
02683 }
02684
02685 case 0x10:
02686 if (numinfo > 1 || IsSnowLineSet()) {
02687 grfmsg(1, "GlobalVarChangeInfo: The snowline can only be set once (%d)", numinfo);
02688 } else if (buf->Remaining() < SNOW_LINE_MONTHS * SNOW_LINE_DAYS) {
02689 grfmsg(1, "GlobalVarChangeInfo: Not enough entries set in the snowline table (" PRINTF_SIZE ")", buf->Remaining());
02690 } else {
02691 byte table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS];
02692
02693 for (uint i = 0; i < SNOW_LINE_MONTHS; i++) {
02694 for (uint j = 0; j < SNOW_LINE_DAYS; j++) {
02695 table[i][j] = buf->ReadByte();
02696 if (_cur.grffile->grf_version >= 8) {
02697 if (table[i][j] != 0xFF) table[i][j] = table[i][j] * (1 + MAX_TILE_HEIGHT) / 256;
02698 } else {
02699 if (table[i][j] >= 128) {
02700
02701 table[i][j] = 0xFF;
02702 } else {
02703 table[i][j] = table[i][j] * (1 + MAX_TILE_HEIGHT) / 128;
02704 }
02705 }
02706 }
02707 }
02708 SetSnowLine(table);
02709 }
02710 break;
02711
02712 case 0x11:
02713
02714
02715 buf->Skip(8);
02716 break;
02717
02718 case 0x13:
02719 case 0x14:
02720 case 0x15: {
02721 uint curidx = gvid + i;
02722 const LanguageMetadata *lang = curidx < MAX_LANG ? GetLanguage(curidx) : NULL;
02723 if (lang == NULL) {
02724 grfmsg(1, "GlobalVarChangeInfo: Language %d is not known, ignoring", curidx);
02725
02726 if (prop == 0x15) {
02727 buf->ReadByte();
02728 } else {
02729 while (buf->ReadByte() != 0) {
02730 buf->ReadString();
02731 }
02732 }
02733 break;
02734 }
02735
02736 if (_cur.grffile->language_map == NULL) _cur.grffile->language_map = new LanguageMap[MAX_LANG];
02737
02738 if (prop == 0x15) {
02739 uint plural_form = buf->ReadByte();
02740 if (plural_form >= LANGUAGE_MAX_PLURAL) {
02741 grfmsg(1, "GlobalVarChanceInfo: Plural form %d is out of range, ignoring", plural_form);
02742 } else {
02743 _cur.grffile->language_map[curidx].plural_form = plural_form;
02744 }
02745 break;
02746 }
02747
02748 byte newgrf_id = buf->ReadByte();
02749 while (newgrf_id != 0) {
02750 const char *name = buf->ReadString();
02751
02752
02753
02754
02755
02756 WChar c;
02757 size_t len = Utf8Decode(&c, name);
02758 if (c == NFO_UTF8_IDENTIFIER) name += len;
02759
02760 LanguageMap::Mapping map;
02761 map.newgrf_id = newgrf_id;
02762 if (prop == 0x13) {
02763 map.openttd_id = lang->GetGenderIndex(name);
02764 if (map.openttd_id >= MAX_NUM_GENDERS) {
02765 grfmsg(1, "GlobalVarChangeInfo: Gender name %s is not known, ignoring", name);
02766 } else {
02767 *_cur.grffile->language_map[curidx].gender_map.Append() = map;
02768 }
02769 } else {
02770 map.openttd_id = lang->GetCaseIndex(name);
02771 if (map.openttd_id >= MAX_NUM_CASES) {
02772 grfmsg(1, "GlobalVarChangeInfo: Case name %s is not known, ignoring", name);
02773 } else {
02774 *_cur.grffile->language_map[curidx].case_map.Append() = map;
02775 }
02776 }
02777 newgrf_id = buf->ReadByte();
02778 }
02779 break;
02780 }
02781
02782 default:
02783 ret = CIR_UNKNOWN;
02784 break;
02785 }
02786 }
02787
02788 return ret;
02789 }
02790
02791 static ChangeInfoResult GlobalVarReserveInfo(uint gvid, int numinfo, int prop, ByteReader *buf)
02792 {
02793
02794 switch (prop) {
02795 case 0x09:
02796 return LoadTranslationTable(gvid, numinfo, buf, _cur.grffile->cargo_list, "Cargo");
02797
02798 case 0x12:
02799 return LoadTranslationTable(gvid, numinfo, buf, _cur.grffile->railtype_list, "Rail type");
02800
02801 default:
02802 break;
02803 }
02804
02805
02806 ChangeInfoResult ret = CIR_SUCCESS;
02807 for (int i = 0; i < numinfo; i++) {
02808 switch (prop) {
02809 case 0x08:
02810 case 0x15:
02811 buf->ReadByte();
02812 break;
02813
02814 case 0x0A:
02815 case 0x0C:
02816 case 0x0F:
02817 buf->ReadWord();
02818 break;
02819
02820 case 0x0B:
02821 case 0x0D:
02822 case 0x0E:
02823 buf->ReadDWord();
02824 break;
02825
02826 case 0x10:
02827 buf->Skip(SNOW_LINE_MONTHS * SNOW_LINE_DAYS);
02828 break;
02829
02830 case 0x11: {
02831 uint32 s = buf->ReadDWord();
02832 uint32 t = buf->ReadDWord();
02833 SetNewGRFOverride(s, t);
02834 break;
02835 }
02836
02837 case 0x13:
02838 case 0x14:
02839 while (buf->ReadByte() != 0) {
02840 buf->ReadString();
02841 }
02842 break;
02843
02844 default:
02845 ret = CIR_UNKNOWN;
02846 break;
02847 }
02848 }
02849
02850 return ret;
02851 }
02852
02853
02862 static ChangeInfoResult CargoChangeInfo(uint cid, int numinfo, int prop, ByteReader *buf)
02863 {
02864 ChangeInfoResult ret = CIR_SUCCESS;
02865
02866 if (cid + numinfo > NUM_CARGO) {
02867 grfmsg(2, "CargoChangeInfo: Cargo type %d out of range (max %d)", cid + numinfo, NUM_CARGO - 1);
02868 return CIR_INVALID_ID;
02869 }
02870
02871 for (int i = 0; i < numinfo; i++) {
02872 CargoSpec *cs = CargoSpec::Get(cid + i);
02873
02874 switch (prop) {
02875 case 0x08:
02876 cs->bitnum = buf->ReadByte();
02877 if (cs->IsValid()) {
02878 cs->grffile = _cur.grffile;
02879 SetBit(_cargo_mask, cid + i);
02880 } else {
02881 ClrBit(_cargo_mask, cid + i);
02882 }
02883 break;
02884
02885 case 0x09:
02886 AddStringForMapping(buf->ReadWord(), &cs->name);
02887 break;
02888
02889 case 0x0A:
02890 AddStringForMapping(buf->ReadWord(), &cs->name_single);
02891 break;
02892
02893 case 0x0B:
02894 case 0x1B:
02895
02896
02897
02898 AddStringForMapping(buf->ReadWord(), &cs->units_volume);
02899 break;
02900
02901 case 0x0C:
02902 case 0x1C:
02903
02904
02905
02906 AddStringForMapping(buf->ReadWord(), &cs->quantifier);
02907 break;
02908
02909 case 0x0D:
02910 AddStringForMapping(buf->ReadWord(), &cs->abbrev);
02911 break;
02912
02913 case 0x0E:
02914 cs->sprite = buf->ReadWord();
02915 break;
02916
02917 case 0x0F:
02918 cs->weight = buf->ReadByte();
02919 break;
02920
02921 case 0x10:
02922 cs->transit_days[0] = buf->ReadByte();
02923 break;
02924
02925 case 0x11:
02926 cs->transit_days[1] = buf->ReadByte();
02927 break;
02928
02929 case 0x12:
02930 cs->initial_payment = buf->ReadDWord();
02931 break;
02932
02933 case 0x13:
02934 cs->rating_colour = buf->ReadByte();
02935 break;
02936
02937 case 0x14:
02938 cs->legend_colour = buf->ReadByte();
02939 break;
02940
02941 case 0x15:
02942 cs->is_freight = (buf->ReadByte() != 0);
02943 break;
02944
02945 case 0x16:
02946 cs->classes = buf->ReadWord();
02947 break;
02948
02949 case 0x17:
02950 cs->label = buf->ReadDWord();
02951 cs->label = BSWAP32(cs->label);
02952 break;
02953
02954 case 0x18: {
02955 uint8 substitute_type = buf->ReadByte();
02956
02957 switch (substitute_type) {
02958 case 0x00: cs->town_effect = TE_PASSENGERS; break;
02959 case 0x02: cs->town_effect = TE_MAIL; break;
02960 case 0x05: cs->town_effect = TE_GOODS; break;
02961 case 0x09: cs->town_effect = TE_WATER; break;
02962 case 0x0B: cs->town_effect = TE_FOOD; break;
02963 default:
02964 grfmsg(1, "CargoChangeInfo: Unknown town growth substitute value %d, setting to none.", substitute_type);
02965
02966 case 0xFF: cs->town_effect = TE_NONE; break;
02967 }
02968 break;
02969 }
02970
02971 case 0x19:
02972 cs->multipliertowngrowth = buf->ReadWord();
02973 break;
02974
02975 case 0x1A:
02976 cs->callback_mask = buf->ReadByte();
02977 break;
02978
02979 case 0x1D:
02980 cs->multiplier = max<uint16>(1u, buf->ReadWord());
02981 break;
02982
02983 default:
02984 ret = CIR_UNKNOWN;
02985 break;
02986 }
02987 }
02988
02989 return ret;
02990 }
02991
02992
03001 static ChangeInfoResult SoundEffectChangeInfo(uint sid, int numinfo, int prop, ByteReader *buf)
03002 {
03003 ChangeInfoResult ret = CIR_SUCCESS;
03004
03005 if (_cur.grffile->sound_offset == 0) {
03006 grfmsg(1, "SoundEffectChangeInfo: No effects defined, skipping");
03007 return CIR_INVALID_ID;
03008 }
03009
03010 if (sid + numinfo - ORIGINAL_SAMPLE_COUNT > _cur.grffile->num_sounds) {
03011 grfmsg(1, "SoundEffectChangeInfo: Attemting to change undefined sound effect (%u), max (%u). Ignoring.", sid + numinfo, ORIGINAL_SAMPLE_COUNT + _cur.grffile->num_sounds);
03012 return CIR_INVALID_ID;
03013 }
03014
03015 for (int i = 0; i < numinfo; i++) {
03016 SoundEntry *sound = GetSound(sid + i + _cur.grffile->sound_offset - ORIGINAL_SAMPLE_COUNT);
03017
03018 switch (prop) {
03019 case 0x08:
03020 sound->volume = buf->ReadByte();
03021 break;
03022
03023 case 0x09:
03024 sound->priority = buf->ReadByte();
03025 break;
03026
03027 case 0x0A: {
03028 SoundID orig_sound = buf->ReadByte();
03029
03030 if (orig_sound >= ORIGINAL_SAMPLE_COUNT) {
03031 grfmsg(1, "SoundEffectChangeInfo: Original sound %d not defined (max %d)", orig_sound, ORIGINAL_SAMPLE_COUNT);
03032 } else {
03033 SoundEntry *old_sound = GetSound(orig_sound);
03034
03035
03036 *old_sound = *sound;
03037 }
03038 break;
03039 }
03040
03041 default:
03042 ret = CIR_UNKNOWN;
03043 break;
03044 }
03045 }
03046
03047 return ret;
03048 }
03049
03056 static ChangeInfoResult IgnoreIndustryTileProperty(int prop, ByteReader *buf)
03057 {
03058 ChangeInfoResult ret = CIR_SUCCESS;
03059
03060 switch (prop) {
03061 case 0x09:
03062 case 0x0D:
03063 case 0x0E:
03064 case 0x10:
03065 case 0x11:
03066 case 0x12:
03067 buf->ReadByte();
03068 break;
03069
03070 case 0x0A:
03071 case 0x0B:
03072 case 0x0C:
03073 case 0x0F:
03074 buf->ReadWord();
03075 break;
03076
03077 default:
03078 ret = CIR_UNKNOWN;
03079 break;
03080 }
03081 return ret;
03082 }
03083
03092 static ChangeInfoResult IndustrytilesChangeInfo(uint indtid, int numinfo, int prop, ByteReader *buf)
03093 {
03094 ChangeInfoResult ret = CIR_SUCCESS;
03095
03096 if (indtid + numinfo > NUM_INDUSTRYTILES_PER_GRF) {
03097 grfmsg(1, "IndustryTilesChangeInfo: Too many industry tiles loaded (%u), max (%u). Ignoring.", indtid + numinfo, NUM_INDUSTRYTILES_PER_GRF);
03098 return CIR_INVALID_ID;
03099 }
03100
03101
03102 if (_cur.grffile->indtspec == NULL) {
03103 _cur.grffile->indtspec = CallocT<IndustryTileSpec*>(NUM_INDUSTRYTILES_PER_GRF);
03104 }
03105
03106 for (int i = 0; i < numinfo; i++) {
03107 IndustryTileSpec *tsp = _cur.grffile->indtspec[indtid + i];
03108
03109 if (prop != 0x08 && tsp == NULL) {
03110 ChangeInfoResult cir = IgnoreIndustryTileProperty(prop, buf);
03111 if (cir > ret) ret = cir;
03112 continue;
03113 }
03114
03115 switch (prop) {
03116 case 0x08: {
03117 IndustryTileSpec **tilespec = &_cur.grffile->indtspec[indtid + i];
03118 byte subs_id = buf->ReadByte();
03119
03120 if (subs_id >= NEW_INDUSTRYTILEOFFSET) {
03121
03122 grfmsg(2, "IndustryTilesChangeInfo: Attempt to use new industry tile %u as substitute industry tile for %u. Ignoring.", subs_id, indtid + i);
03123 continue;
03124 }
03125
03126
03127 if (*tilespec == NULL) {
03128 *tilespec = CallocT<IndustryTileSpec>(1);
03129 tsp = *tilespec;
03130
03131 memcpy(tsp, &_industry_tile_specs[subs_id], sizeof(_industry_tile_specs[subs_id]));
03132 tsp->enabled = true;
03133
03134
03135
03136
03137 tsp->anim_production = INDUSTRYTILE_NOANIM;
03138 tsp->anim_next = INDUSTRYTILE_NOANIM;
03139
03140 tsp->grf_prop.local_id = indtid + i;
03141 tsp->grf_prop.subst_id = subs_id;
03142 tsp->grf_prop.grffile = _cur.grffile;
03143 _industile_mngr.AddEntityID(indtid + i, _cur.grffile->grfid, subs_id);
03144 }
03145 break;
03146 }
03147
03148 case 0x09: {
03149 byte ovrid = buf->ReadByte();
03150
03151
03152 if (ovrid >= NEW_INDUSTRYTILEOFFSET) {
03153 grfmsg(2, "IndustryTilesChangeInfo: Attempt to override new industry tile %u with industry tile id %u. Ignoring.", ovrid, indtid + i);
03154 continue;
03155 }
03156
03157 _industile_mngr.Add(indtid + i, _cur.grffile->grfid, ovrid);
03158 break;
03159 }
03160
03161 case 0x0A:
03162 case 0x0B:
03163 case 0x0C: {
03164 uint16 acctp = buf->ReadWord();
03165 tsp->accepts_cargo[prop - 0x0A] = GetCargoTranslation(GB(acctp, 0, 8), _cur.grffile);
03166 tsp->acceptance[prop - 0x0A] = GB(acctp, 8, 8);
03167 break;
03168 }
03169
03170 case 0x0D:
03171 tsp->slopes_refused = (Slope)buf->ReadByte();
03172 break;
03173
03174 case 0x0E:
03175 tsp->callback_mask = buf->ReadByte();
03176 break;
03177
03178 case 0x0F:
03179 tsp->animation.frames = buf->ReadByte();
03180 tsp->animation.status = buf->ReadByte();
03181 break;
03182
03183 case 0x10:
03184 tsp->animation.speed = buf->ReadByte();
03185 break;
03186
03187 case 0x11:
03188 tsp->animation.triggers = buf->ReadByte();
03189 break;
03190
03191 case 0x12:
03192 tsp->special_flags = (IndustryTileSpecialFlags)buf->ReadByte();
03193 break;
03194
03195 default:
03196 ret = CIR_UNKNOWN;
03197 break;
03198 }
03199 }
03200
03201 return ret;
03202 }
03203
03210 static ChangeInfoResult IgnoreIndustryProperty(int prop, ByteReader *buf)
03211 {
03212 ChangeInfoResult ret = CIR_SUCCESS;
03213
03214 switch (prop) {
03215 case 0x09:
03216 case 0x0B:
03217 case 0x0F:
03218 case 0x12:
03219 case 0x13:
03220 case 0x14:
03221 case 0x17:
03222 case 0x18:
03223 case 0x19:
03224 case 0x21:
03225 case 0x22:
03226 buf->ReadByte();
03227 break;
03228
03229 case 0x0C:
03230 case 0x0D:
03231 case 0x0E:
03232 case 0x10:
03233 case 0x1B:
03234 case 0x1F:
03235 case 0x24:
03236 buf->ReadWord();
03237 break;
03238
03239 case 0x11:
03240 case 0x1A:
03241 case 0x1C:
03242 case 0x1D:
03243 case 0x1E:
03244 case 0x20:
03245 case 0x23:
03246 buf->ReadDWord();
03247 break;
03248
03249 case 0x0A: {
03250 byte num_table = buf->ReadByte();
03251 for (byte j = 0; j < num_table; j++) {
03252 for (uint k = 0;; k++) {
03253 byte x = buf->ReadByte();
03254 if (x == 0xFE && k == 0) {
03255 buf->ReadByte();
03256 buf->ReadByte();
03257 break;
03258 }
03259
03260 byte y = buf->ReadByte();
03261 if (x == 0 && y == 0x80) break;
03262
03263 byte gfx = buf->ReadByte();
03264 if (gfx == 0xFE) buf->ReadWord();
03265 }
03266 }
03267 break;
03268 }
03269
03270 case 0x16:
03271 for (byte j = 0; j < 3; j++) buf->ReadByte();
03272 break;
03273
03274 case 0x15: {
03275 byte number_of_sounds = buf->ReadByte();
03276 for (uint8 j = 0; j < number_of_sounds; j++) {
03277 buf->ReadByte();
03278 }
03279 break;
03280 }
03281
03282 default:
03283 ret = CIR_UNKNOWN;
03284 break;
03285 }
03286 return ret;
03287 }
03288
03295 static bool ValidateIndustryLayout(const IndustryTileTable *layout, int size)
03296 {
03297 for (int i = 0; i < size - 1; i++) {
03298 for (int j = i + 1; j < size; j++) {
03299 if (layout[i].ti.x == layout[j].ti.x &&
03300 layout[i].ti.y == layout[j].ti.y) {
03301 return false;
03302 }
03303 }
03304 }
03305 return true;
03306 }
03307
03309 static void CleanIndustryTileTable(IndustrySpec *ind)
03310 {
03311 if (HasBit(ind->cleanup_flag, CLEAN_TILELAYOUT) && ind->table != NULL) {
03312 for (int j = 0; j < ind->num_table; j++) {
03313
03314 free(ind->table[j]);
03315 }
03316
03317 free(ind->table);
03318 ind->table = NULL;
03319 }
03320 }
03321
03330 static ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop, ByteReader *buf)
03331 {
03332 ChangeInfoResult ret = CIR_SUCCESS;
03333
03334 if (indid + numinfo > NUM_INDUSTRYTYPES_PER_GRF) {
03335 grfmsg(1, "IndustriesChangeInfo: Too many industries loaded (%u), max (%u). Ignoring.", indid + numinfo, NUM_INDUSTRYTYPES_PER_GRF);
03336 return CIR_INVALID_ID;
03337 }
03338
03339
03340 if (_cur.grffile->industryspec == NULL) {
03341 _cur.grffile->industryspec = CallocT<IndustrySpec*>(NUM_INDUSTRYTYPES_PER_GRF);
03342 }
03343
03344 for (int i = 0; i < numinfo; i++) {
03345 IndustrySpec *indsp = _cur.grffile->industryspec[indid + i];
03346
03347 if (prop != 0x08 && indsp == NULL) {
03348 ChangeInfoResult cir = IgnoreIndustryProperty(prop, buf);
03349 if (cir > ret) ret = cir;
03350 continue;
03351 }
03352
03353 switch (prop) {
03354 case 0x08: {
03355 IndustrySpec **indspec = &_cur.grffile->industryspec[indid + i];
03356 byte subs_id = buf->ReadByte();
03357
03358 if (subs_id == 0xFF) {
03359
03360
03361 _industry_specs[indid + i].enabled = false;
03362 continue;
03363 } else if (subs_id >= NEW_INDUSTRYOFFSET) {
03364
03365 grfmsg(2, "_industry_specs: Attempt to use new industry %u as substitute industry for %u. Ignoring.", subs_id, indid + i);
03366 continue;
03367 }
03368
03369
03370
03371
03372 if (*indspec == NULL) {
03373 *indspec = CallocT<IndustrySpec>(1);
03374 indsp = *indspec;
03375
03376 memcpy(indsp, &_origin_industry_specs[subs_id], sizeof(_industry_specs[subs_id]));
03377 indsp->enabled = true;
03378 indsp->grf_prop.local_id = indid + i;
03379 indsp->grf_prop.subst_id = subs_id;
03380 indsp->grf_prop.grffile = _cur.grffile;
03381
03382
03383 indsp->check_proc = CHECK_NOTHING;
03384 }
03385 break;
03386 }
03387
03388 case 0x09: {
03389 byte ovrid = buf->ReadByte();
03390
03391
03392 if (ovrid >= NEW_INDUSTRYOFFSET) {
03393 grfmsg(2, "IndustriesChangeInfo: Attempt to override new industry %u with industry id %u. Ignoring.", ovrid, indid + i);
03394 continue;
03395 }
03396 indsp->grf_prop.override = ovrid;
03397 _industry_mngr.Add(indid + i, _cur.grffile->grfid, ovrid);
03398 break;
03399 }
03400
03401 case 0x0A: {
03402 byte new_num_layouts = buf->ReadByte();
03403
03404
03405
03406
03407
03408 uint32 def_num_tiles = buf->ReadDWord() / 3 + 1;
03409 IndustryTileTable **tile_table = CallocT<IndustryTileTable*>(new_num_layouts);
03410 IndustryTileTable *itt = CallocT<IndustryTileTable>(def_num_tiles);
03411 uint size;
03412 const IndustryTileTable *copy_from;
03413
03414 try {
03415 for (byte j = 0; j < new_num_layouts; j++) {
03416 for (uint k = 0;; k++) {
03417 if (k >= def_num_tiles) {
03418 grfmsg(3, "IndustriesChangeInfo: Incorrect size for industry tile layout definition for industry %u.", indid);
03419
03420 def_num_tiles *= 2;
03421 itt = ReallocT<IndustryTileTable>(itt, def_num_tiles);
03422 }
03423
03424 itt[k].ti.x = buf->ReadByte();
03425
03426 if (itt[k].ti.x == 0xFE && k == 0) {
03427
03428 IndustryType type = buf->ReadByte();
03429 byte laynbr = buf->ReadByte();
03430
03431 copy_from = _origin_industry_specs[type].table[laynbr];
03432 for (size = 1;; size++) {
03433 if (copy_from[size - 1].ti.x == -0x80 && copy_from[size - 1].ti.y == 0) break;
03434 }
03435 break;
03436 }
03437
03438 itt[k].ti.y = buf->ReadByte();
03439
03440 if (itt[k].ti.x == 0 && itt[k].ti.y == 0x80) {
03441
03442
03443 itt[k].ti.x = -0x80;
03444 itt[k].ti.y = 0;
03445 itt[k].gfx = 0;
03446
03447 size = k + 1;
03448 copy_from = itt;
03449 break;
03450 }
03451
03452 itt[k].gfx = buf->ReadByte();
03453
03454 if (itt[k].gfx == 0xFE) {
03455
03456 int local_tile_id = buf->ReadWord();
03457
03458
03459 int tempid = _industile_mngr.GetID(local_tile_id, _cur.grffile->grfid);
03460
03461 if (tempid == INVALID_INDUSTRYTILE) {
03462 grfmsg(2, "IndustriesChangeInfo: Attempt to use industry tile %u with industry id %u, not yet defined. Ignoring.", local_tile_id, indid);
03463 } else {
03464
03465 itt[k].gfx = tempid;
03466 size = k + 1;
03467 copy_from = itt;
03468 }
03469 } else if (itt[k].gfx == 0xFF) {
03470 itt[k].ti.x = (int8)GB(itt[k].ti.x, 0, 8);
03471 itt[k].ti.y = (int8)GB(itt[k].ti.y, 0, 8);
03472 }
03473 }
03474
03475 if (!ValidateIndustryLayout(copy_from, size)) {
03476
03477 grfmsg(1, "IndustriesChangeInfo: Invalid industry layout for industry id %u. Ignoring", indid);
03478 new_num_layouts--;
03479 j--;
03480 } else {
03481 tile_table[j] = CallocT<IndustryTileTable>(size);
03482 memcpy(tile_table[j], copy_from, sizeof(*copy_from) * size);
03483 }
03484 }
03485 } catch (...) {
03486 for (int i = 0; i < new_num_layouts; i++) {
03487 free(tile_table[i]);
03488 }
03489 free(tile_table);
03490 free(itt);
03491 throw;
03492 }
03493
03494
03495 CleanIndustryTileTable(indsp);
03496
03497 indsp->num_table = new_num_layouts;
03498 indsp->table = tile_table;
03499 SetBit(indsp->cleanup_flag, CLEAN_TILELAYOUT);
03500 free(itt);
03501 break;
03502 }
03503
03504 case 0x0B:
03505 indsp->life_type = (IndustryLifeType)buf->ReadByte();
03506 break;
03507
03508 case 0x0C:
03509 AddStringForMapping(buf->ReadWord(), &indsp->closure_text);
03510 break;
03511
03512 case 0x0D:
03513 AddStringForMapping(buf->ReadWord(), &indsp->production_up_text);
03514 break;
03515
03516 case 0x0E:
03517 AddStringForMapping(buf->ReadWord(), &indsp->production_down_text);
03518 break;
03519
03520 case 0x0F:
03521 indsp->cost_multiplier = buf->ReadByte();
03522 break;
03523
03524 case 0x10:
03525 for (byte j = 0; j < 2; j++) {
03526 indsp->produced_cargo[j] = GetCargoTranslation(buf->ReadByte(), _cur.grffile);
03527 }
03528 break;
03529
03530 case 0x11:
03531 for (byte j = 0; j < 3; j++) {
03532 indsp->accepts_cargo[j] = GetCargoTranslation(buf->ReadByte(), _cur.grffile);
03533 }
03534 buf->ReadByte();
03535 break;
03536
03537 case 0x12:
03538 case 0x13:
03539 indsp->production_rate[prop - 0x12] = buf->ReadByte();
03540 break;
03541
03542 case 0x14:
03543 indsp->minimal_cargo = buf->ReadByte();
03544 break;
03545
03546 case 0x15: {
03547 indsp->number_of_sounds = buf->ReadByte();
03548 uint8 *sounds = MallocT<uint8>(indsp->number_of_sounds);
03549
03550 try {
03551 for (uint8 j = 0; j < indsp->number_of_sounds; j++) {
03552 sounds[j] = buf->ReadByte();
03553 }
03554 } catch (...) {
03555 free(sounds);
03556 throw;
03557 }
03558
03559 if (HasBit(indsp->cleanup_flag, CLEAN_RANDOMSOUNDS)) {
03560 free(indsp->random_sounds);
03561 }
03562 indsp->random_sounds = sounds;
03563 SetBit(indsp->cleanup_flag, CLEAN_RANDOMSOUNDS);
03564 break;
03565 }
03566
03567 case 0x16:
03568 for (byte j = 0; j < 3; j++) indsp->conflicting[j] = buf->ReadByte();
03569 break;
03570
03571 case 0x17:
03572 indsp->appear_creation[_settings_game.game_creation.landscape] = buf->ReadByte();
03573 break;
03574
03575 case 0x18:
03576 indsp->appear_ingame[_settings_game.game_creation.landscape] = buf->ReadByte();
03577 break;
03578
03579 case 0x19:
03580 indsp->map_colour = buf->ReadByte();
03581 break;
03582
03583 case 0x1A:
03584 indsp->behaviour = (IndustryBehaviour)buf->ReadDWord();
03585 break;
03586
03587 case 0x1B:
03588 AddStringForMapping(buf->ReadWord(), &indsp->new_industry_text);
03589 break;
03590
03591 case 0x1C:
03592 case 0x1D:
03593 case 0x1E: {
03594 uint32 multiples = buf->ReadDWord();
03595 indsp->input_cargo_multiplier[prop - 0x1C][0] = GB(multiples, 0, 16);
03596 indsp->input_cargo_multiplier[prop - 0x1C][1] = GB(multiples, 16, 16);
03597 break;
03598 }
03599
03600 case 0x1F:
03601 AddStringForMapping(buf->ReadWord(), &indsp->name);
03602 break;
03603
03604 case 0x20:
03605 indsp->prospecting_chance = buf->ReadDWord();
03606 break;
03607
03608 case 0x21:
03609 case 0x22: {
03610 byte aflag = buf->ReadByte();
03611 SB(indsp->callback_mask, (prop - 0x21) * 8, 8, aflag);
03612 break;
03613 }
03614
03615 case 0x23:
03616 indsp->removal_cost_multiplier = buf->ReadDWord();
03617 break;
03618
03619 case 0x24: {
03620 uint16 str = buf->ReadWord();
03621 if (str == 0) {
03622 indsp->station_name = STR_NULL;
03623 } else {
03624 AddStringForMapping(str, &indsp->station_name);
03625 }
03626 break;
03627 }
03628
03629 default:
03630 ret = CIR_UNKNOWN;
03631 break;
03632 }
03633 }
03634
03635 return ret;
03636 }
03637
03643 static void DuplicateTileTable(AirportSpec *as)
03644 {
03645 AirportTileTable **table_list = MallocT<AirportTileTable*>(as->num_table);
03646 for (int i = 0; i < as->num_table; i++) {
03647 uint num_tiles = 1;
03648 const AirportTileTable *it = as->table[0];
03649 do {
03650 num_tiles++;
03651 } while ((++it)->ti.x != -0x80);
03652 table_list[i] = MallocT<AirportTileTable>(num_tiles);
03653 MemCpyT(table_list[i], as->table[i], num_tiles);
03654 }
03655 as->table = table_list;
03656 HangarTileTable *depot_table = MallocT<HangarTileTable>(as->nof_depots);
03657 MemCpyT(depot_table, as->depot_table, as->nof_depots);
03658 as->depot_table = depot_table;
03659 }
03660
03669 static ChangeInfoResult AirportChangeInfo(uint airport, int numinfo, int prop, ByteReader *buf)
03670 {
03671 ChangeInfoResult ret = CIR_SUCCESS;
03672
03673 if (airport + numinfo > NUM_AIRPORTS_PER_GRF) {
03674 grfmsg(1, "AirportChangeInfo: Too many airports, trying id (%u), max (%u). Ignoring.", airport + numinfo, NUM_AIRPORTS_PER_GRF);
03675 return CIR_INVALID_ID;
03676 }
03677
03678
03679 if (_cur.grffile->airportspec == NULL) {
03680 _cur.grffile->airportspec = CallocT<AirportSpec*>(NUM_AIRPORTS_PER_GRF);
03681 }
03682
03683 for (int i = 0; i < numinfo; i++) {
03684 AirportSpec *as = _cur.grffile->airportspec[airport + i];
03685
03686 if (as == NULL && prop != 0x08 && prop != 0x09) {
03687 grfmsg(2, "AirportChangeInfo: Attempt to modify undefined airport %u, ignoring", airport + i);
03688 return CIR_INVALID_ID;
03689 }
03690
03691 switch (prop) {
03692 case 0x08: {
03693 byte subs_id = buf->ReadByte();
03694
03695 if (subs_id == 0xFF) {
03696
03697
03698 AirportSpec::GetWithoutOverride(airport + i)->enabled = false;
03699 continue;
03700 } else if (subs_id >= NEW_AIRPORT_OFFSET) {
03701
03702 grfmsg(2, "AirportChangeInfo: Attempt to use new airport %u as substitute airport for %u. Ignoring.", subs_id, airport + i);
03703 continue;
03704 }
03705
03706 AirportSpec **spec = &_cur.grffile->airportspec[airport + i];
03707
03708
03709
03710 if (*spec == NULL) {
03711 *spec = MallocT<AirportSpec>(1);
03712 as = *spec;
03713
03714 memcpy(as, AirportSpec::GetWithoutOverride(subs_id), sizeof(*as));
03715 as->enabled = true;
03716 as->grf_prop.local_id = airport + i;
03717 as->grf_prop.subst_id = subs_id;
03718 as->grf_prop.grffile = _cur.grffile;
03719
03720 _airport_mngr.Add(airport + i, _cur.grffile->grfid, subs_id);
03721
03722 DuplicateTileTable(as);
03723 }
03724 break;
03725 }
03726
03727 case 0x0A: {
03728 as->num_table = buf->ReadByte();
03729 as->rotation = MallocT<Direction>(as->num_table);
03730 uint32 defsize = buf->ReadDWord();
03731 AirportTileTable **tile_table = CallocT<AirportTileTable*>(as->num_table);
03732 AirportTileTable *att = CallocT<AirportTileTable>(defsize);
03733 int size;
03734 const AirportTileTable *copy_from;
03735 try {
03736 for (byte j = 0; j < as->num_table; j++) {
03737 as->rotation[j] = (Direction)buf->ReadByte();
03738 for (int k = 0;; k++) {
03739 att[k].ti.x = buf->ReadByte();
03740 att[k].ti.y = buf->ReadByte();
03741
03742 if (att[k].ti.x == 0 && att[k].ti.y == 0x80) {
03743
03744
03745 att[k].ti.x = -0x80;
03746 att[k].ti.y = 0;
03747 att[k].gfx = 0;
03748
03749 size = k + 1;
03750 copy_from = att;
03751 break;
03752 }
03753
03754 att[k].gfx = buf->ReadByte();
03755
03756 if (att[k].gfx == 0xFE) {
03757
03758 int local_tile_id = buf->ReadWord();
03759
03760
03761 uint16 tempid = _airporttile_mngr.GetID(local_tile_id, _cur.grffile->grfid);
03762
03763 if (tempid == INVALID_AIRPORTTILE) {
03764 grfmsg(2, "AirportChangeInfo: Attempt to use airport tile %u with airport id %u, not yet defined. Ignoring.", local_tile_id, airport + i);
03765 } else {
03766
03767 att[k].gfx = tempid;
03768 size = k + 1;
03769 copy_from = att;
03770 }
03771 } else if (att[k].gfx == 0xFF) {
03772 att[k].ti.x = (int8)GB(att[k].ti.x, 0, 8);
03773 att[k].ti.y = (int8)GB(att[k].ti.y, 0, 8);
03774 }
03775
03776 if (as->rotation[j] == DIR_E || as->rotation[j] == DIR_W) {
03777 as->size_x = max<byte>(as->size_x, att[k].ti.y + 1);
03778 as->size_y = max<byte>(as->size_y, att[k].ti.x + 1);
03779 } else {
03780 as->size_x = max<byte>(as->size_x, att[k].ti.x + 1);
03781 as->size_y = max<byte>(as->size_y, att[k].ti.y + 1);
03782 }
03783 }
03784 tile_table[j] = CallocT<AirportTileTable>(size);
03785 memcpy(tile_table[j], copy_from, sizeof(*copy_from) * size);
03786 }
03787
03788 as->table = tile_table;
03789 free(att);
03790 } catch (...) {
03791 for (int i = 0; i < as->num_table; i++) {
03792 free(tile_table[i]);
03793 }
03794 free(tile_table);
03795 free(att);
03796 throw;
03797 }
03798 break;
03799 }
03800
03801 case 0x0C:
03802 as->min_year = buf->ReadWord();
03803 as->max_year = buf->ReadWord();
03804 if (as->max_year == 0xFFFF) as->max_year = MAX_YEAR;
03805 break;
03806
03807 case 0x0D:
03808 as->ttd_airport_type = (TTDPAirportType)buf->ReadByte();
03809 break;
03810
03811 case 0x0E:
03812 as->catchment = Clamp(buf->ReadByte(), 1, MAX_CATCHMENT);
03813 break;
03814
03815 case 0x0F:
03816 as->noise_level = buf->ReadByte();
03817 break;
03818
03819 case 0x10:
03820 AddStringForMapping(buf->ReadWord(), &as->name);
03821 break;
03822
03823 case 0x11:
03824 as->maintenance_cost = buf->ReadWord();
03825 break;
03826
03827 default:
03828 ret = CIR_UNKNOWN;
03829 break;
03830 }
03831 }
03832
03833 return ret;
03834 }
03835
03842 static ChangeInfoResult IgnoreObjectProperty(uint prop, ByteReader *buf)
03843 {
03844 ChangeInfoResult ret = CIR_SUCCESS;
03845
03846 switch (prop) {
03847 case 0x0B:
03848 case 0x0C:
03849 case 0x0D:
03850 case 0x12:
03851 case 0x14:
03852 case 0x16:
03853 case 0x17:
03854 buf->ReadByte();
03855 break;
03856
03857 case 0x09:
03858 case 0x0A:
03859 case 0x10:
03860 case 0x11:
03861 case 0x13:
03862 case 0x15:
03863 buf->ReadWord();
03864 break;
03865
03866 case 0x08:
03867 case 0x0E:
03868 case 0x0F:
03869 buf->ReadDWord();
03870 break;
03871
03872 default:
03873 ret = CIR_UNKNOWN;
03874 break;
03875 }
03876
03877 return ret;
03878 }
03879
03888 static ChangeInfoResult ObjectChangeInfo(uint id, int numinfo, int prop, ByteReader *buf)
03889 {
03890 ChangeInfoResult ret = CIR_SUCCESS;
03891
03892 if (id + numinfo > NUM_OBJECTS_PER_GRF) {
03893 grfmsg(1, "ObjectChangeInfo: Too many objects loaded (%u), max (%u). Ignoring.", id + numinfo, NUM_OBJECTS_PER_GRF);
03894 return CIR_INVALID_ID;
03895 }
03896
03897
03898 if (_cur.grffile->objectspec == NULL) {
03899 _cur.grffile->objectspec = CallocT<ObjectSpec*>(NUM_OBJECTS_PER_GRF);
03900 }
03901
03902 for (int i = 0; i < numinfo; i++) {
03903 ObjectSpec *spec = _cur.grffile->objectspec[id + i];
03904
03905 if (prop != 0x08 && spec == NULL) {
03906
03907 ChangeInfoResult cir = IgnoreObjectProperty(prop, buf);
03908 if (cir > ret) ret = cir;
03909 continue;
03910 }
03911
03912 switch (prop) {
03913 case 0x08: {
03914 ObjectSpec **ospec = &_cur.grffile->objectspec[id + i];
03915
03916
03917 if (*ospec == NULL) {
03918 *ospec = CallocT<ObjectSpec>(1);
03919 (*ospec)->views = 1;
03920 }
03921
03922
03923 uint32 classid = buf->ReadDWord();
03924 (*ospec)->cls_id = ObjectClass::Allocate(BSWAP32(classid));
03925 (*ospec)->enabled = true;
03926 break;
03927 }
03928
03929 case 0x09: {
03930 ObjectClass *objclass = ObjectClass::Get(spec->cls_id);
03931 AddStringForMapping(buf->ReadWord(), &objclass->name);
03932 break;
03933 }
03934
03935 case 0x0A:
03936 AddStringForMapping(buf->ReadWord(), &spec->name);
03937 break;
03938
03939 case 0x0B:
03940 spec->climate = buf->ReadByte();
03941 break;
03942
03943 case 0x0C:
03944 spec->size = buf->ReadByte();
03945 break;
03946
03947 case 0x0D:
03948 spec->build_cost_multiplier = buf->ReadByte();
03949 spec->clear_cost_multiplier = spec->build_cost_multiplier;
03950 break;
03951
03952 case 0x0E:
03953 spec->introduction_date = buf->ReadDWord();
03954 break;
03955
03956 case 0x0F:
03957 spec->end_of_life_date = buf->ReadDWord();
03958 break;
03959
03960 case 0x10:
03961 spec->flags = (ObjectFlags)buf->ReadWord();
03962 _loaded_newgrf_features.has_2CC |= (spec->flags & OBJECT_FLAG_2CC_COLOUR) != 0;
03963 break;
03964
03965 case 0x11:
03966 spec->animation.frames = buf->ReadByte();
03967 spec->animation.status = buf->ReadByte();
03968 break;
03969
03970 case 0x12:
03971 spec->animation.speed = buf->ReadByte();
03972 break;
03973
03974 case 0x13:
03975 spec->animation.triggers = buf->ReadWord();
03976 break;
03977
03978 case 0x14:
03979 spec->clear_cost_multiplier = buf->ReadByte();
03980 break;
03981
03982 case 0x15:
03983 spec->callback_mask = buf->ReadWord();
03984 break;
03985
03986 case 0x16:
03987 spec->height = buf->ReadByte();
03988 break;
03989
03990 case 0x17:
03991 spec->views = buf->ReadByte();
03992 if (spec->views != 1 && spec->views != 2 && spec->views != 4) {
03993 grfmsg(2, "ObjectChangeInfo: Invalid number of views (%u) for object id %u. Ignoring.", spec->views, id + i);
03994 spec->views = 1;
03995 }
03996 break;
03997
03998 case 0x18:
03999 spec->generate_amount = buf->ReadByte();
04000 break;
04001
04002 default:
04003 ret = CIR_UNKNOWN;
04004 break;
04005 }
04006 }
04007
04008 return ret;
04009 }
04010
04019 static ChangeInfoResult RailTypeChangeInfo(uint id, int numinfo, int prop, ByteReader *buf)
04020 {
04021 ChangeInfoResult ret = CIR_SUCCESS;
04022
04023 extern RailtypeInfo _railtypes[RAILTYPE_END];
04024
04025 if (id + numinfo > RAILTYPE_END) {
04026 grfmsg(1, "RailTypeChangeInfo: Rail type %u is invalid, max %u, ignoring", id + numinfo, RAILTYPE_END);
04027 return CIR_INVALID_ID;
04028 }
04029
04030 for (int i = 0; i < numinfo; i++) {
04031 RailType rt = _cur.grffile->railtype_map[id + i];
04032 if (rt == INVALID_RAILTYPE) return CIR_INVALID_ID;
04033
04034 RailtypeInfo *rti = &_railtypes[rt];
04035
04036 switch (prop) {
04037 case 0x08:
04038
04039 buf->ReadDWord();
04040 break;
04041
04042 case 0x09: {
04043 uint16 str = buf->ReadWord();
04044 AddStringForMapping(str, &rti->strings.toolbar_caption);
04045 if (_cur.grffile->grf_version < 8) {
04046 AddStringForMapping(str, &rti->strings.name);
04047 }
04048 break;
04049 }
04050
04051 case 0x0A:
04052 AddStringForMapping(buf->ReadWord(), &rti->strings.menu_text);
04053 break;
04054
04055 case 0x0B:
04056 AddStringForMapping(buf->ReadWord(), &rti->strings.build_caption);
04057 break;
04058
04059 case 0x0C:
04060 AddStringForMapping(buf->ReadWord(), &rti->strings.replace_text);
04061 break;
04062
04063 case 0x0D:
04064 AddStringForMapping(buf->ReadWord(), &rti->strings.new_loco);
04065 break;
04066
04067 case 0x0E:
04068 case 0x0F:
04069 case 0x18:
04070 case 0x19:
04071 {
04072
04073
04074
04075 int n = buf->ReadByte();
04076 for (int j = 0; j != n; j++) {
04077 RailTypeLabel label = buf->ReadDWord();
04078 RailType rt = GetRailTypeByLabel(BSWAP32(label), false);
04079 if (rt != INVALID_RAILTYPE) {
04080 switch (prop) {
04081 case 0x0F: SetBit(rti->powered_railtypes, rt);
04082 case 0x0E: SetBit(rti->compatible_railtypes, rt); break;
04083 case 0x18: SetBit(rti->introduction_required_railtypes, rt); break;
04084 case 0x19: SetBit(rti->introduces_railtypes, rt); break;
04085 }
04086 }
04087 }
04088 break;
04089 }
04090
04091 case 0x10:
04092 rti->flags = (RailTypeFlags)buf->ReadByte();
04093 break;
04094
04095 case 0x11:
04096 rti->curve_speed = buf->ReadByte();
04097 break;
04098
04099 case 0x12:
04100 rti->fallback_railtype = Clamp(buf->ReadByte(), 0, 2);
04101 break;
04102
04103 case 0x13:
04104 rti->cost_multiplier = buf->ReadWord();
04105 break;
04106
04107 case 0x14:
04108 rti->max_speed = buf->ReadWord();
04109 break;
04110
04111 case 0x15:
04112 rti->acceleration_type = Clamp(buf->ReadByte(), 0, 2);
04113 break;
04114
04115 case 0x16:
04116 rti->map_colour = buf->ReadByte();
04117 break;
04118
04119 case 0x17:
04120 rti->introduction_date = buf->ReadDWord();
04121 break;
04122
04123 case 0x1A:
04124 rti->sorting_order = buf->ReadByte();
04125 break;
04126
04127 case 0x1B:
04128 AddStringForMapping(buf->ReadWord(), &rti->strings.name);
04129 break;
04130
04131 case 0x1C:
04132 rti->maintenance_multiplier = buf->ReadWord();
04133 break;
04134
04135 case 0x1D:
04136
04137 for (int j = buf->ReadByte(); j != 0; j--) buf->ReadDWord();
04138 break;
04139
04140 default:
04141 ret = CIR_UNKNOWN;
04142 break;
04143 }
04144 }
04145
04146 return ret;
04147 }
04148
04149 static ChangeInfoResult RailTypeReserveInfo(uint id, int numinfo, int prop, ByteReader *buf)
04150 {
04151 ChangeInfoResult ret = CIR_SUCCESS;
04152
04153 extern RailtypeInfo _railtypes[RAILTYPE_END];
04154
04155 if (id + numinfo > RAILTYPE_END) {
04156 grfmsg(1, "RailTypeReserveInfo: Rail type %u is invalid, max %u, ignoring", id + numinfo, RAILTYPE_END);
04157 return CIR_INVALID_ID;
04158 }
04159
04160 for (int i = 0; i < numinfo; i++) {
04161 switch (prop) {
04162 case 0x08:
04163 {
04164 RailTypeLabel rtl = buf->ReadDWord();
04165 rtl = BSWAP32(rtl);
04166
04167 RailType rt = GetRailTypeByLabel(rtl, false);
04168 if (rt == INVALID_RAILTYPE) {
04169
04170 rt = AllocateRailType(rtl);
04171 }
04172
04173 _cur.grffile->railtype_map[id + i] = rt;
04174 break;
04175 }
04176
04177 case 0x09:
04178 case 0x0A:
04179 case 0x0B:
04180 case 0x0C:
04181 case 0x0D:
04182 case 0x13:
04183 case 0x14:
04184 case 0x1B:
04185 case 0x1C:
04186 buf->ReadWord();
04187 break;
04188
04189 case 0x1D:
04190 if (_cur.grffile->railtype_map[id + i] != INVALID_RAILTYPE) {
04191 int n = buf->ReadByte();
04192 for (int j = 0; j != n; j++) {
04193 *_railtypes[_cur.grffile->railtype_map[id + i]].alternate_labels.Append() = BSWAP32(buf->ReadDWord());
04194 }
04195 break;
04196 }
04197 grfmsg(1, "RailTypeReserveInfo: Ignoring property 1D for rail type %u because no label was set", id + i);
04198
04199
04200 case 0x0E:
04201 case 0x0F:
04202 case 0x18:
04203 case 0x19:
04204 for (int j = buf->ReadByte(); j != 0; j--) buf->ReadDWord();
04205 break;
04206
04207 case 0x10:
04208 case 0x11:
04209 case 0x12:
04210 case 0x15:
04211 case 0x16:
04212 case 0x1A:
04213 buf->ReadByte();
04214 break;
04215
04216 case 0x17:
04217 buf->ReadDWord();
04218 break;
04219
04220 default:
04221 ret = CIR_UNKNOWN;
04222 break;
04223 }
04224 }
04225
04226 return ret;
04227 }
04228
04229 static ChangeInfoResult AirportTilesChangeInfo(uint airtid, int numinfo, int prop, ByteReader *buf)
04230 {
04231 ChangeInfoResult ret = CIR_SUCCESS;
04232
04233 if (airtid + numinfo > NUM_AIRPORTTILES_PER_GRF) {
04234 grfmsg(1, "AirportTileChangeInfo: Too many airport tiles loaded (%u), max (%u). Ignoring.", airtid + numinfo, NUM_AIRPORTTILES_PER_GRF);
04235 return CIR_INVALID_ID;
04236 }
04237
04238
04239 if (_cur.grffile->airtspec == NULL) {
04240 _cur.grffile->airtspec = CallocT<AirportTileSpec*>(NUM_AIRPORTTILES_PER_GRF);
04241 }
04242
04243 for (int i = 0; i < numinfo; i++) {
04244 AirportTileSpec *tsp = _cur.grffile->airtspec[airtid + i];
04245
04246 if (prop != 0x08 && tsp == NULL) {
04247 grfmsg(2, "AirportTileChangeInfo: Attempt to modify undefined airport tile %u. Ignoring.", airtid + i);
04248 return CIR_INVALID_ID;
04249 }
04250
04251 switch (prop) {
04252 case 0x08: {
04253 AirportTileSpec **tilespec = &_cur.grffile->airtspec[airtid + i];
04254 byte subs_id = buf->ReadByte();
04255
04256 if (subs_id >= NEW_AIRPORTTILE_OFFSET) {
04257
04258 grfmsg(2, "AirportTileChangeInfo: Attempt to use new airport tile %u as substitute airport tile for %u. Ignoring.", subs_id, airtid + i);
04259 continue;
04260 }
04261
04262
04263 if (*tilespec == NULL) {
04264 *tilespec = CallocT<AirportTileSpec>(1);
04265 tsp = *tilespec;
04266
04267 memcpy(tsp, AirportTileSpec::Get(subs_id), sizeof(AirportTileSpec));
04268 tsp->enabled = true;
04269
04270 tsp->animation.status = ANIM_STATUS_NO_ANIMATION;
04271
04272 tsp->grf_prop.local_id = airtid + i;
04273 tsp->grf_prop.subst_id = subs_id;
04274 tsp->grf_prop.grffile = _cur.grffile;
04275 _airporttile_mngr.AddEntityID(airtid + i, _cur.grffile->grfid, subs_id);
04276 }
04277 break;
04278 }
04279
04280 case 0x09: {
04281 byte override = buf->ReadByte();
04282
04283
04284 if (override >= NEW_AIRPORTTILE_OFFSET) {
04285 grfmsg(2, "AirportTileChangeInfo: Attempt to override new airport tile %u with airport tile id %u. Ignoring.", override, airtid + i);
04286 continue;
04287 }
04288
04289 _airporttile_mngr.Add(airtid + i, _cur.grffile->grfid, override);
04290 break;
04291 }
04292
04293 case 0x0E:
04294 tsp->callback_mask = buf->ReadByte();
04295 break;
04296
04297 case 0x0F:
04298 tsp->animation.frames = buf->ReadByte();
04299 tsp->animation.status = buf->ReadByte();
04300 break;
04301
04302 case 0x10:
04303 tsp->animation.speed = buf->ReadByte();
04304 break;
04305
04306 case 0x11:
04307 tsp->animation.triggers = buf->ReadByte();
04308 break;
04309
04310 default:
04311 ret = CIR_UNKNOWN;
04312 break;
04313 }
04314 }
04315
04316 return ret;
04317 }
04318
04319 static bool HandleChangeInfoResult(const char *caller, ChangeInfoResult cir, uint8 feature, uint8 property)
04320 {
04321 switch (cir) {
04322 default: NOT_REACHED();
04323
04324 case CIR_DISABLED:
04325
04326 return true;
04327
04328 case CIR_SUCCESS:
04329 return false;
04330
04331 case CIR_UNHANDLED:
04332 grfmsg(1, "%s: Ignoring property 0x%02X of feature 0x%02X (not implemented)", caller, property, feature);
04333 return false;
04334
04335 case CIR_UNKNOWN:
04336 grfmsg(0, "%s: Unknown property 0x%02X of feature 0x%02X, disabling", caller, property, feature);
04337
04338
04339 case CIR_INVALID_ID: {
04340
04341 GRFError *error = DisableGrf(cir == CIR_INVALID_ID ? STR_NEWGRF_ERROR_INVALID_ID : STR_NEWGRF_ERROR_UNKNOWN_PROPERTY);
04342 if (cir != CIR_INVALID_ID) error->param_value[1] = property;
04343 return true;
04344 }
04345 }
04346 }
04347
04348
04349 static void FeatureChangeInfo(ByteReader *buf)
04350 {
04351
04352
04353
04354
04355
04356
04357
04358
04359
04360
04361
04362 static const VCI_Handler handler[] = {
04363 RailVehicleChangeInfo,
04364 RoadVehicleChangeInfo,
04365 ShipVehicleChangeInfo,
04366 AircraftVehicleChangeInfo,
04367 StationChangeInfo,
04368 CanalChangeInfo,
04369 BridgeChangeInfo,
04370 TownHouseChangeInfo,
04371 GlobalVarChangeInfo,
04372 IndustrytilesChangeInfo,
04373 IndustriesChangeInfo,
04374 NULL,
04375 SoundEffectChangeInfo,
04376 AirportChangeInfo,
04377 NULL,
04378 ObjectChangeInfo,
04379 RailTypeChangeInfo,
04380 AirportTilesChangeInfo,
04381 };
04382
04383 uint8 feature = buf->ReadByte();
04384 uint8 numprops = buf->ReadByte();
04385 uint numinfo = buf->ReadByte();
04386 uint engine = buf->ReadExtendedByte();
04387
04388 grfmsg(6, "FeatureChangeInfo: feature %d, %d properties, to apply to %d+%d",
04389 feature, numprops, engine, numinfo);
04390
04391 if (feature >= lengthof(handler) || handler[feature] == NULL) {
04392 if (feature != GSF_CARGOES) grfmsg(1, "FeatureChangeInfo: Unsupported feature %d, skipping", feature);
04393 return;
04394 }
04395
04396
04397 SetBit(_cur.grffile->grf_features, feature);
04398
04399 while (numprops-- && buf->HasData()) {
04400 uint8 prop = buf->ReadByte();
04401
04402 ChangeInfoResult cir = handler[feature](engine, numinfo, prop, buf);
04403 if (HandleChangeInfoResult("FeatureChangeInfo", cir, feature, prop)) return;
04404 }
04405 }
04406
04407
04408 static void SafeChangeInfo(ByteReader *buf)
04409 {
04410 uint8 feature = buf->ReadByte();
04411 uint8 numprops = buf->ReadByte();
04412 uint numinfo = buf->ReadByte();
04413 buf->ReadExtendedByte();
04414
04415 if (feature == GSF_BRIDGES && numprops == 1) {
04416 uint8 prop = buf->ReadByte();
04417
04418
04419 if (prop == 0x0D) return;
04420 } else if (feature == GSF_GLOBALVAR && numprops == 1) {
04421 uint8 prop = buf->ReadByte();
04422
04423 if (prop == 0x11) {
04424 bool is_safe = true;
04425 for (uint i = 0; i < numinfo; i++) {
04426 uint32 s = buf->ReadDWord();
04427 buf->ReadDWord();
04428 const GRFConfig *grfconfig = GetGRFConfig(s);
04429 if (grfconfig != NULL && !HasBit(grfconfig->flags, GCF_STATIC)) {
04430 is_safe = false;
04431 break;
04432 }
04433 }
04434 if (is_safe) return;
04435 }
04436 }
04437
04438 SetBit(_cur.grfconfig->flags, GCF_UNSAFE);
04439
04440
04441 _cur.skip_sprites = -1;
04442 }
04443
04444
04445 static void ReserveChangeInfo(ByteReader *buf)
04446 {
04447 uint8 feature = buf->ReadByte();
04448
04449 if (feature != GSF_CARGOES && feature != GSF_GLOBALVAR && feature != GSF_RAILTYPES) return;
04450
04451 uint8 numprops = buf->ReadByte();
04452 uint8 numinfo = buf->ReadByte();
04453 uint8 index = buf->ReadExtendedByte();
04454
04455 while (numprops-- && buf->HasData()) {
04456 uint8 prop = buf->ReadByte();
04457 ChangeInfoResult cir = CIR_SUCCESS;
04458
04459 switch (feature) {
04460 default: NOT_REACHED();
04461 case GSF_CARGOES:
04462 cir = CargoChangeInfo(index, numinfo, prop, buf);
04463 break;
04464
04465 case GSF_GLOBALVAR:
04466 cir = GlobalVarReserveInfo(index, numinfo, prop, buf);
04467 break;
04468
04469 case GSF_RAILTYPES:
04470 cir = RailTypeReserveInfo(index, numinfo, prop, buf);
04471 break;
04472 }
04473
04474 if (HandleChangeInfoResult("ReserveChangeInfo", cir, feature, prop)) return;
04475 }
04476 }
04477
04478
04479 static void NewSpriteSet(ByteReader *buf)
04480 {
04481
04482
04483
04484
04485
04486
04487
04488
04489
04490
04491
04492
04493
04494
04495 uint8 feature = buf->ReadByte();
04496 uint16 num_sets = buf->ReadByte();
04497 uint16 first_set = 0;
04498
04499 if (num_sets == 0 && buf->HasData(3)) {
04500
04501
04502 first_set = buf->ReadExtendedByte();
04503 num_sets = buf->ReadExtendedByte();
04504 }
04505 uint16 num_ents = buf->ReadExtendedByte();
04506
04507 _cur.AddSpriteSets(feature, _cur.spriteid, first_set, num_sets, num_ents);
04508
04509 grfmsg(7, "New sprite set at %d of type %d, consisting of %d sets with %d views each (total %d)",
04510 _cur.spriteid, feature, num_sets, num_ents, num_sets * num_ents
04511 );
04512
04513 for (int i = 0; i < num_sets * num_ents; i++) {
04514 _cur.nfo_line++;
04515 LoadNextSprite(_cur.spriteid++, _cur.file_index, _cur.nfo_line, _cur.grf_container_ver);
04516 }
04517 }
04518
04519
04520 static void SkipAct1(ByteReader *buf)
04521 {
04522 buf->ReadByte();
04523 uint16 num_sets = buf->ReadByte();
04524
04525 if (num_sets == 0 && buf->HasData(3)) {
04526
04527
04528 buf->ReadExtendedByte();
04529 num_sets = buf->ReadExtendedByte();
04530 }
04531 uint16 num_ents = buf->ReadExtendedByte();
04532
04533 _cur.skip_sprites = num_sets * num_ents;
04534
04535 grfmsg(3, "SkipAct1: Skipping %d sprites", _cur.skip_sprites);
04536 }
04537
04538
04539
04540 static const SpriteGroup *GetGroupFromGroupID(byte setid, byte type, uint16 groupid)
04541 {
04542 if (HasBit(groupid, 15)) {
04543 assert(CallbackResultSpriteGroup::CanAllocateItem());
04544 return new CallbackResultSpriteGroup(groupid, _cur.grffile->grf_version >= 8);
04545 }
04546
04547 if (groupid > MAX_SPRITEGROUP || _cur.spritegroups[groupid] == NULL) {
04548 grfmsg(1, "GetGroupFromGroupID(0x%02X:0x%02X): Groupid 0x%04X does not exist, leaving empty", setid, type, groupid);
04549 return NULL;
04550 }
04551
04552 return _cur.spritegroups[groupid];
04553 }
04554
04563 static const SpriteGroup *CreateGroupFromGroupID(byte feature, byte setid, byte type, uint16 spriteid)
04564 {
04565 if (HasBit(spriteid, 15)) {
04566 assert(CallbackResultSpriteGroup::CanAllocateItem());
04567 return new CallbackResultSpriteGroup(spriteid, _cur.grffile->grf_version >= 8);
04568 }
04569
04570 if (!_cur.IsValidSpriteSet(feature, spriteid)) {
04571 grfmsg(1, "CreateGroupFromGroupID(0x%02X:0x%02X): Sprite set %u invalid", setid, type, spriteid);
04572 return NULL;
04573 }
04574
04575 SpriteID spriteset_start = _cur.GetSprite(feature, spriteid);
04576 uint num_sprites = _cur.GetNumEnts(feature, spriteid);
04577
04578
04579 assert(spriteset_start + num_sprites <= _cur.spriteid);
04580
04581 assert(ResultSpriteGroup::CanAllocateItem());
04582 return new ResultSpriteGroup(spriteset_start, num_sprites);
04583 }
04584
04585
04586 static void NewSpriteGroup(ByteReader *buf)
04587 {
04588
04589
04590
04591
04592
04593
04594
04595
04596
04597
04598 SpriteGroup *act_group = NULL;
04599
04600 uint8 feature = buf->ReadByte();
04601 uint8 setid = buf->ReadByte();
04602 uint8 type = buf->ReadByte();
04603
04604
04605
04606
04607
04608 switch (type) {
04609
04610 case 0x81:
04611 case 0x82:
04612 case 0x85:
04613 case 0x86:
04614 case 0x89:
04615 case 0x8A:
04616 {
04617 byte varadjust;
04618 byte varsize;
04619
04620 assert(DeterministicSpriteGroup::CanAllocateItem());
04621 DeterministicSpriteGroup *group = new DeterministicSpriteGroup();
04622 act_group = group;
04623 group->var_scope = HasBit(type, 1) ? VSG_SCOPE_PARENT : VSG_SCOPE_SELF;
04624
04625 switch (GB(type, 2, 2)) {
04626 default: NOT_REACHED();
04627 case 0: group->size = DSG_SIZE_BYTE; varsize = 1; break;
04628 case 1: group->size = DSG_SIZE_WORD; varsize = 2; break;
04629 case 2: group->size = DSG_SIZE_DWORD; varsize = 4; break;
04630 }
04631
04632 static SmallVector<DeterministicSpriteGroupAdjust, 16> adjusts;
04633 adjusts.Clear();
04634
04635
04636
04637 do {
04638 DeterministicSpriteGroupAdjust *adjust = adjusts.Append();
04639
04640
04641 adjust->operation = adjusts.Length() == 1 ? DSGA_OP_ADD : (DeterministicSpriteGroupAdjustOperation)buf->ReadByte();
04642 adjust->variable = buf->ReadByte();
04643 if (adjust->variable == 0x7E) {
04644
04645 adjust->subroutine = GetGroupFromGroupID(setid, type, buf->ReadByte());
04646 } else {
04647 adjust->parameter = IsInsideMM(adjust->variable, 0x60, 0x80) ? buf->ReadByte() : 0;
04648 }
04649
04650 varadjust = buf->ReadByte();
04651 adjust->shift_num = GB(varadjust, 0, 5);
04652 adjust->type = (DeterministicSpriteGroupAdjustType)GB(varadjust, 6, 2);
04653 adjust->and_mask = buf->ReadVarSize(varsize);
04654
04655 if (adjust->type != DSGA_TYPE_NONE) {
04656 adjust->add_val = buf->ReadVarSize(varsize);
04657 adjust->divmod_val = buf->ReadVarSize(varsize);
04658 } else {
04659 adjust->add_val = 0;
04660 adjust->divmod_val = 0;
04661 }
04662
04663
04664 } while (HasBit(varadjust, 5));
04665
04666 group->num_adjusts = adjusts.Length();
04667 group->adjusts = MallocT<DeterministicSpriteGroupAdjust>(group->num_adjusts);
04668 MemCpyT(group->adjusts, adjusts.Begin(), group->num_adjusts);
04669
04670 group->num_ranges = buf->ReadByte();
04671 if (group->num_ranges > 0) group->ranges = CallocT<DeterministicSpriteGroupRange>(group->num_ranges);
04672
04673 for (uint i = 0; i < group->num_ranges; i++) {
04674 group->ranges[i].group = GetGroupFromGroupID(setid, type, buf->ReadWord());
04675 group->ranges[i].low = buf->ReadVarSize(varsize);
04676 group->ranges[i].high = buf->ReadVarSize(varsize);
04677 }
04678
04679 group->default_group = GetGroupFromGroupID(setid, type, buf->ReadWord());
04680 break;
04681 }
04682
04683
04684 case 0x80:
04685 case 0x83:
04686 case 0x84:
04687 {
04688 assert(RandomizedSpriteGroup::CanAllocateItem());
04689 RandomizedSpriteGroup *group = new RandomizedSpriteGroup();
04690 act_group = group;
04691 group->var_scope = HasBit(type, 1) ? VSG_SCOPE_PARENT : VSG_SCOPE_SELF;
04692
04693 if (HasBit(type, 2)) {
04694 if (feature <= GSF_AIRCRAFT) group->var_scope = VSG_SCOPE_RELATIVE;
04695 group->count = buf->ReadByte();
04696 }
04697
04698 uint8 triggers = buf->ReadByte();
04699 group->triggers = GB(triggers, 0, 7);
04700 group->cmp_mode = HasBit(triggers, 7) ? RSG_CMP_ALL : RSG_CMP_ANY;
04701 group->lowest_randbit = buf->ReadByte();
04702 group->num_groups = buf->ReadByte();
04703 group->groups = CallocT<const SpriteGroup*>(group->num_groups);
04704
04705 for (uint i = 0; i < group->num_groups; i++) {
04706 group->groups[i] = GetGroupFromGroupID(setid, type, buf->ReadWord());
04707 }
04708
04709 break;
04710 }
04711
04712
04713 default:
04714 {
04715 switch (feature) {
04716 case GSF_TRAINS:
04717 case GSF_ROADVEHICLES:
04718 case GSF_SHIPS:
04719 case GSF_AIRCRAFT:
04720 case GSF_STATIONS:
04721 case GSF_CANALS:
04722 case GSF_CARGOES:
04723 case GSF_AIRPORTS:
04724 case GSF_RAILTYPES:
04725 {
04726 byte num_loaded = type;
04727 byte num_loading = buf->ReadByte();
04728
04729 if (!_cur.HasValidSpriteSets(feature)) {
04730 grfmsg(0, "NewSpriteGroup: No sprite set to work on! Skipping");
04731 return;
04732 }
04733
04734 assert(RealSpriteGroup::CanAllocateItem());
04735 RealSpriteGroup *group = new RealSpriteGroup();
04736 act_group = group;
04737
04738 group->num_loaded = num_loaded;
04739 group->num_loading = num_loading;
04740 if (num_loaded > 0) group->loaded = CallocT<const SpriteGroup*>(num_loaded);
04741 if (num_loading > 0) group->loading = CallocT<const SpriteGroup*>(num_loading);
04742
04743 grfmsg(6, "NewSpriteGroup: New SpriteGroup 0x%02X, %u loaded, %u loading",
04744 setid, num_loaded, num_loading);
04745
04746 for (uint i = 0; i < num_loaded; i++) {
04747 uint16 spriteid = buf->ReadWord();
04748 group->loaded[i] = CreateGroupFromGroupID(feature, setid, type, spriteid);
04749 grfmsg(8, "NewSpriteGroup: + rg->loaded[%i] = subset %u", i, spriteid);
04750 }
04751
04752 for (uint i = 0; i < num_loading; i++) {
04753 uint16 spriteid = buf->ReadWord();
04754 group->loading[i] = CreateGroupFromGroupID(feature, setid, type, spriteid);
04755 grfmsg(8, "NewSpriteGroup: + rg->loading[%i] = subset %u", i, spriteid);
04756 }
04757
04758 break;
04759 }
04760
04761 case GSF_HOUSES:
04762 case GSF_AIRPORTTILES:
04763 case GSF_OBJECTS:
04764 case GSF_INDUSTRYTILES: {
04765 byte num_building_sprites = max((uint8)1, type);
04766
04767 assert(TileLayoutSpriteGroup::CanAllocateItem());
04768 TileLayoutSpriteGroup *group = new TileLayoutSpriteGroup();
04769 act_group = group;
04770
04771
04772 if (ReadSpriteLayout(buf, num_building_sprites, true, feature, false, type == 0, &group->dts)) return;
04773 break;
04774 }
04775
04776 case GSF_INDUSTRIES: {
04777 if (type > 1) {
04778 grfmsg(1, "NewSpriteGroup: Unsupported industry production version %d, skipping", type);
04779 break;
04780 }
04781
04782 assert(IndustryProductionSpriteGroup::CanAllocateItem());
04783 IndustryProductionSpriteGroup *group = new IndustryProductionSpriteGroup();
04784 act_group = group;
04785 group->version = type;
04786 if (type == 0) {
04787 for (uint i = 0; i < 3; i++) {
04788 group->subtract_input[i] = (int16)buf->ReadWord();
04789 }
04790 for (uint i = 0; i < 2; i++) {
04791 group->add_output[i] = buf->ReadWord();
04792 }
04793 group->again = buf->ReadByte();
04794 } else {
04795 for (uint i = 0; i < 3; i++) {
04796 group->subtract_input[i] = buf->ReadByte();
04797 }
04798 for (uint i = 0; i < 2; i++) {
04799 group->add_output[i] = buf->ReadByte();
04800 }
04801 group->again = buf->ReadByte();
04802 }
04803 break;
04804 }
04805
04806
04807 default: grfmsg(1, "NewSpriteGroup: Unsupported feature %d, skipping", feature);
04808 }
04809 }
04810 }
04811
04812 _cur.spritegroups[setid] = act_group;
04813 }
04814
04815 static CargoID TranslateCargo(uint8 feature, uint8 ctype)
04816 {
04817 if (feature == GSF_OBJECTS) {
04818 switch (ctype) {
04819 case 0: return 0;
04820 case 0xFF: return CT_PURCHASE_OBJECT;
04821 default:
04822 grfmsg(1, "TranslateCargo: Invalid cargo bitnum %d for objects, skipping.", ctype);
04823 return CT_INVALID;
04824 }
04825 }
04826
04827 if (feature == GSF_STATIONS && ctype == 0xFE) return CT_DEFAULT_NA;
04828 if (ctype == 0xFF) return CT_PURCHASE;
04829
04830 if (_cur.grffile->cargo_list.Length() == 0) {
04831
04832 if (ctype >= 32) {
04833 grfmsg(1, "TranslateCargo: Cargo bitnum %d out of range (max 31), skipping.", ctype);
04834 return CT_INVALID;
04835 }
04836
04837 const CargoSpec *cs;
04838 FOR_ALL_CARGOSPECS(cs) {
04839 if (cs->bitnum == ctype) {
04840 grfmsg(6, "TranslateCargo: Cargo bitnum %d mapped to cargo type %d.", ctype, cs->Index());
04841 return cs->Index();
04842 }
04843 }
04844
04845 grfmsg(5, "TranslateCargo: Cargo bitnum %d not available in this climate, skipping.", ctype);
04846 return CT_INVALID;
04847 }
04848
04849
04850 if (ctype >= _cur.grffile->cargo_list.Length()) {
04851 grfmsg(1, "TranslateCargo: Cargo type %d out of range (max %d), skipping.", ctype, _cur.grffile->cargo_list.Length() - 1);
04852 return CT_INVALID;
04853 }
04854
04855
04856 CargoLabel cl = _cur.grffile->cargo_list[ctype];
04857 if (cl == 0) {
04858 grfmsg(5, "TranslateCargo: Cargo type %d not available in this climate, skipping.", ctype);
04859 return CT_INVALID;
04860 }
04861
04862 ctype = GetCargoIDByLabel(cl);
04863 if (ctype == CT_INVALID) {
04864 grfmsg(5, "TranslateCargo: Cargo '%c%c%c%c' unsupported, skipping.", GB(cl, 24, 8), GB(cl, 16, 8), GB(cl, 8, 8), GB(cl, 0, 8));
04865 return CT_INVALID;
04866 }
04867
04868 grfmsg(6, "TranslateCargo: Cargo '%c%c%c%c' mapped to cargo type %d.", GB(cl, 24, 8), GB(cl, 16, 8), GB(cl, 8, 8), GB(cl, 0, 8), ctype);
04869 return ctype;
04870 }
04871
04872
04873 static bool IsValidGroupID(uint16 groupid, const char *function)
04874 {
04875 if (groupid > MAX_SPRITEGROUP || _cur.spritegroups[groupid] == NULL) {
04876 grfmsg(1, "%s: Spritegroup 0x%04X out of range or empty, skipping.", function, groupid);
04877 return false;
04878 }
04879
04880 return true;
04881 }
04882
04883 static void VehicleMapSpriteGroup(ByteReader *buf, byte feature, uint8 idcount)
04884 {
04885 static EngineID *last_engines;
04886 static uint last_engines_count;
04887 bool wagover = false;
04888
04889
04890 if (HasBit(idcount, 7)) {
04891 wagover = true;
04892
04893 idcount = GB(idcount, 0, 7);
04894
04895 if (last_engines_count == 0) {
04896 grfmsg(0, "VehicleMapSpriteGroup: WagonOverride: No engine to do override with");
04897 return;
04898 }
04899
04900 grfmsg(6, "VehicleMapSpriteGroup: WagonOverride: %u engines, %u wagons",
04901 last_engines_count, idcount);
04902 } else {
04903 if (last_engines_count != idcount) {
04904 last_engines = ReallocT(last_engines, idcount);
04905 last_engines_count = idcount;
04906 }
04907 }
04908
04909 EngineID *engines = AllocaM(EngineID, idcount);
04910 for (uint i = 0; i < idcount; i++) {
04911 Engine *e = GetNewEngine(_cur.grffile, (VehicleType)feature, buf->ReadExtendedByte());
04912 if (e == NULL) {
04913
04914
04915
04916 HandleChangeInfoResult("VehicleMapSpriteGroup", CIR_INVALID_ID, 0, 0);
04917 return;
04918 }
04919
04920 engines[i] = e->index;
04921 if (!wagover) last_engines[i] = engines[i];
04922 }
04923
04924 uint8 cidcount = buf->ReadByte();
04925 for (uint c = 0; c < cidcount; c++) {
04926 uint8 ctype = buf->ReadByte();
04927 uint16 groupid = buf->ReadWord();
04928 if (!IsValidGroupID(groupid, "VehicleMapSpriteGroup")) continue;
04929
04930 grfmsg(8, "VehicleMapSpriteGroup: * [%d] Cargo type 0x%X, group id 0x%02X", c, ctype, groupid);
04931
04932 ctype = TranslateCargo(feature, ctype);
04933 if (ctype == CT_INVALID) continue;
04934
04935 for (uint i = 0; i < idcount; i++) {
04936 EngineID engine = engines[i];
04937
04938 grfmsg(7, "VehicleMapSpriteGroup: [%d] Engine %d...", i, engine);
04939
04940 if (wagover) {
04941 SetWagonOverrideSprites(engine, ctype, _cur.spritegroups[groupid], last_engines, last_engines_count);
04942 } else {
04943 SetCustomEngineSprites(engine, ctype, _cur.spritegroups[groupid]);
04944 }
04945 }
04946 }
04947
04948 uint16 groupid = buf->ReadWord();
04949 if (!IsValidGroupID(groupid, "VehicleMapSpriteGroup")) return;
04950
04951 grfmsg(8, "-- Default group id 0x%04X", groupid);
04952
04953 for (uint i = 0; i < idcount; i++) {
04954 EngineID engine = engines[i];
04955
04956 if (wagover) {
04957 SetWagonOverrideSprites(engine, CT_DEFAULT, _cur.spritegroups[groupid], last_engines, last_engines_count);
04958 } else {
04959 SetCustomEngineSprites(engine, CT_DEFAULT, _cur.spritegroups[groupid]);
04960 SetEngineGRF(engine, _cur.grffile);
04961 }
04962 }
04963 }
04964
04965
04966 static void CanalMapSpriteGroup(ByteReader *buf, uint8 idcount)
04967 {
04968 CanalFeature *cfs = AllocaM(CanalFeature, idcount);
04969 for (uint i = 0; i < idcount; i++) {
04970 cfs[i] = (CanalFeature)buf->ReadByte();
04971 }
04972
04973 uint8 cidcount = buf->ReadByte();
04974 buf->Skip(cidcount * 3);
04975
04976 uint16 groupid = buf->ReadWord();
04977 if (!IsValidGroupID(groupid, "CanalMapSpriteGroup")) return;
04978
04979 for (uint i = 0; i < idcount; i++) {
04980 CanalFeature cf = cfs[i];
04981
04982 if (cf >= CF_END) {
04983 grfmsg(1, "CanalMapSpriteGroup: Canal subset %d out of range, skipping", cf);
04984 continue;
04985 }
04986
04987 _water_feature[cf].grffile = _cur.grffile;
04988 _water_feature[cf].group = _cur.spritegroups[groupid];
04989 }
04990 }
04991
04992
04993 static void StationMapSpriteGroup(ByteReader *buf, uint8 idcount)
04994 {
04995 uint8 *stations = AllocaM(uint8, idcount);
04996 for (uint i = 0; i < idcount; i++) {
04997 stations[i] = buf->ReadByte();
04998 }
04999
05000 uint8 cidcount = buf->ReadByte();
05001 for (uint c = 0; c < cidcount; c++) {
05002 uint8 ctype = buf->ReadByte();
05003 uint16 groupid = buf->ReadWord();
05004 if (!IsValidGroupID(groupid, "StationMapSpriteGroup")) continue;
05005
05006 ctype = TranslateCargo(GSF_STATIONS, ctype);
05007 if (ctype == CT_INVALID) continue;
05008
05009 for (uint i = 0; i < idcount; i++) {
05010 StationSpec *statspec = _cur.grffile->stations == NULL ? NULL : _cur.grffile->stations[stations[i]];
05011
05012 if (statspec == NULL) {
05013 grfmsg(1, "StationMapSpriteGroup: Station with ID 0x%02X does not exist, skipping", stations[i]);
05014 continue;
05015 }
05016
05017 statspec->grf_prop.spritegroup[ctype] = _cur.spritegroups[groupid];
05018 }
05019 }
05020
05021 uint16 groupid = buf->ReadWord();
05022 if (!IsValidGroupID(groupid, "StationMapSpriteGroup")) return;
05023
05024 for (uint i = 0; i < idcount; i++) {
05025 StationSpec *statspec = _cur.grffile->stations == NULL ? NULL : _cur.grffile->stations[stations[i]];
05026
05027 if (statspec == NULL) {
05028 grfmsg(1, "StationMapSpriteGroup: Station with ID 0x%02X does not exist, skipping", stations[i]);
05029 continue;
05030 }
05031
05032 if (statspec->grf_prop.grffile != NULL) {
05033 grfmsg(1, "StationMapSpriteGroup: Station with ID 0x%02X mapped multiple times, skipping", stations[i]);
05034 continue;
05035 }
05036
05037 statspec->grf_prop.spritegroup[CT_DEFAULT] = _cur.spritegroups[groupid];
05038 statspec->grf_prop.grffile = _cur.grffile;
05039 statspec->grf_prop.local_id = stations[i];
05040 StationClass::Assign(statspec);
05041 }
05042 }
05043
05044
05045 static void TownHouseMapSpriteGroup(ByteReader *buf, uint8 idcount)
05046 {
05047 uint8 *houses = AllocaM(uint8, idcount);
05048 for (uint i = 0; i < idcount; i++) {
05049 houses[i] = buf->ReadByte();
05050 }
05051
05052
05053 uint8 cidcount = buf->ReadByte();
05054 buf->Skip(cidcount * 3);
05055
05056 uint16 groupid = buf->ReadWord();
05057 if (!IsValidGroupID(groupid, "TownHouseMapSpriteGroup")) return;
05058
05059 if (_cur.grffile->housespec == NULL) {
05060 grfmsg(1, "TownHouseMapSpriteGroup: No houses defined, skipping");
05061 return;
05062 }
05063
05064 for (uint i = 0; i < idcount; i++) {
05065 HouseSpec *hs = _cur.grffile->housespec[houses[i]];
05066
05067 if (hs == NULL) {
05068 grfmsg(1, "TownHouseMapSpriteGroup: House %d undefined, skipping.", houses[i]);
05069 continue;
05070 }
05071
05072 hs->grf_prop.spritegroup[0] = _cur.spritegroups[groupid];
05073 }
05074 }
05075
05076 static void IndustryMapSpriteGroup(ByteReader *buf, uint8 idcount)
05077 {
05078 uint8 *industries = AllocaM(uint8, idcount);
05079 for (uint i = 0; i < idcount; i++) {
05080 industries[i] = buf->ReadByte();
05081 }
05082
05083
05084 uint8 cidcount = buf->ReadByte();
05085 buf->Skip(cidcount * 3);
05086
05087 uint16 groupid = buf->ReadWord();
05088 if (!IsValidGroupID(groupid, "IndustryMapSpriteGroup")) return;
05089
05090 if (_cur.grffile->industryspec == NULL) {
05091 grfmsg(1, "IndustryMapSpriteGroup: No industries defined, skipping");
05092 return;
05093 }
05094
05095 for (uint i = 0; i < idcount; i++) {
05096 IndustrySpec *indsp = _cur.grffile->industryspec[industries[i]];
05097
05098 if (indsp == NULL) {
05099 grfmsg(1, "IndustryMapSpriteGroup: Industry %d undefined, skipping", industries[i]);
05100 continue;
05101 }
05102
05103 indsp->grf_prop.spritegroup[0] = _cur.spritegroups[groupid];
05104 }
05105 }
05106
05107 static void IndustrytileMapSpriteGroup(ByteReader *buf, uint8 idcount)
05108 {
05109 uint8 *indtiles = AllocaM(uint8, idcount);
05110 for (uint i = 0; i < idcount; i++) {
05111 indtiles[i] = buf->ReadByte();
05112 }
05113
05114
05115 uint8 cidcount = buf->ReadByte();
05116 buf->Skip(cidcount * 3);
05117
05118 uint16 groupid = buf->ReadWord();
05119 if (!IsValidGroupID(groupid, "IndustrytileMapSpriteGroup")) return;
05120
05121 if (_cur.grffile->indtspec == NULL) {
05122 grfmsg(1, "IndustrytileMapSpriteGroup: No industry tiles defined, skipping");
05123 return;
05124 }
05125
05126 for (uint i = 0; i < idcount; i++) {
05127 IndustryTileSpec *indtsp = _cur.grffile->indtspec[indtiles[i]];
05128
05129 if (indtsp == NULL) {
05130 grfmsg(1, "IndustrytileMapSpriteGroup: Industry tile %d undefined, skipping", indtiles[i]);
05131 continue;
05132 }
05133
05134 indtsp->grf_prop.spritegroup[0] = _cur.spritegroups[groupid];
05135 }
05136 }
05137
05138 static void CargoMapSpriteGroup(ByteReader *buf, uint8 idcount)
05139 {
05140 CargoID *cargoes = AllocaM(CargoID, idcount);
05141 for (uint i = 0; i < idcount; i++) {
05142 cargoes[i] = buf->ReadByte();
05143 }
05144
05145
05146 uint8 cidcount = buf->ReadByte();
05147 buf->Skip(cidcount * 3);
05148
05149 uint16 groupid = buf->ReadWord();
05150 if (!IsValidGroupID(groupid, "CargoMapSpriteGroup")) return;
05151
05152 for (uint i = 0; i < idcount; i++) {
05153 CargoID cid = cargoes[i];
05154
05155 if (cid >= NUM_CARGO) {
05156 grfmsg(1, "CargoMapSpriteGroup: Cargo ID %d out of range, skipping", cid);
05157 continue;
05158 }
05159
05160 CargoSpec *cs = CargoSpec::Get(cid);
05161 cs->grffile = _cur.grffile;
05162 cs->group = _cur.spritegroups[groupid];
05163 }
05164 }
05165
05166 static void ObjectMapSpriteGroup(ByteReader *buf, uint8 idcount)
05167 {
05168 if (_cur.grffile->objectspec == NULL) {
05169 grfmsg(1, "ObjectMapSpriteGroup: No object tiles defined, skipping");
05170 return;
05171 }
05172
05173 uint8 *objects = AllocaM(uint8, idcount);
05174 for (uint i = 0; i < idcount; i++) {
05175 objects[i] = buf->ReadByte();
05176 }
05177
05178 uint8 cidcount = buf->ReadByte();
05179 for (uint c = 0; c < cidcount; c++) {
05180 uint8 ctype = buf->ReadByte();
05181 uint16 groupid = buf->ReadWord();
05182 if (!IsValidGroupID(groupid, "ObjectMapSpriteGroup")) continue;
05183
05184 ctype = TranslateCargo(GSF_OBJECTS, ctype);
05185 if (ctype == CT_INVALID) continue;
05186
05187 for (uint i = 0; i < idcount; i++) {
05188 ObjectSpec *spec = _cur.grffile->objectspec[objects[i]];
05189
05190 if (spec == NULL) {
05191 grfmsg(1, "ObjectMapSpriteGroup: Object with ID 0x%02X undefined, skipping", objects[i]);
05192 continue;
05193 }
05194
05195 spec->grf_prop.spritegroup[ctype] = _cur.spritegroups[groupid];
05196 }
05197 }
05198
05199 uint16 groupid = buf->ReadWord();
05200 if (!IsValidGroupID(groupid, "ObjectMapSpriteGroup")) return;
05201
05202 for (uint i = 0; i < idcount; i++) {
05203 ObjectSpec *spec = _cur.grffile->objectspec[objects[i]];
05204
05205 if (spec == NULL) {
05206 grfmsg(1, "ObjectMapSpriteGroup: Object with ID 0x%02X undefined, skipping", objects[i]);
05207 continue;
05208 }
05209
05210 if (spec->grf_prop.grffile != NULL) {
05211 grfmsg(1, "ObjectMapSpriteGroup: Object with ID 0x%02X mapped multiple times, skipping", objects[i]);
05212 continue;
05213 }
05214
05215 spec->grf_prop.spritegroup[0] = _cur.spritegroups[groupid];
05216 spec->grf_prop.grffile = _cur.grffile;
05217 spec->grf_prop.local_id = objects[i];
05218 }
05219 }
05220
05221 static void RailTypeMapSpriteGroup(ByteReader *buf, uint8 idcount)
05222 {
05223 uint8 *railtypes = AllocaM(uint8, idcount);
05224 for (uint i = 0; i < idcount; i++) {
05225 railtypes[i] = _cur.grffile->railtype_map[buf->ReadByte()];
05226 }
05227
05228 uint8 cidcount = buf->ReadByte();
05229 for (uint c = 0; c < cidcount; c++) {
05230 uint8 ctype = buf->ReadByte();
05231 uint16 groupid = buf->ReadWord();
05232 if (!IsValidGroupID(groupid, "RailTypeMapSpriteGroup")) continue;
05233
05234 if (ctype >= RTSG_END) continue;
05235
05236 extern RailtypeInfo _railtypes[RAILTYPE_END];
05237 for (uint i = 0; i < idcount; i++) {
05238 if (railtypes[i] != INVALID_RAILTYPE) {
05239 RailtypeInfo *rti = &_railtypes[railtypes[i]];
05240
05241 rti->grffile[ctype] = _cur.grffile;
05242 rti->group[ctype] = _cur.spritegroups[groupid];
05243 }
05244 }
05245 }
05246
05247
05248 buf->ReadWord();
05249 }
05250
05251 static void AirportMapSpriteGroup(ByteReader *buf, uint8 idcount)
05252 {
05253 uint8 *airports = AllocaM(uint8, idcount);
05254 for (uint i = 0; i < idcount; i++) {
05255 airports[i] = buf->ReadByte();
05256 }
05257
05258
05259 uint8 cidcount = buf->ReadByte();
05260 buf->Skip(cidcount * 3);
05261
05262 uint16 groupid = buf->ReadWord();
05263 if (!IsValidGroupID(groupid, "AirportMapSpriteGroup")) return;
05264
05265 if (_cur.grffile->airportspec == NULL) {
05266 grfmsg(1, "AirportMapSpriteGroup: No airports defined, skipping");
05267 return;
05268 }
05269
05270 for (uint i = 0; i < idcount; i++) {
05271 AirportSpec *as = _cur.grffile->airportspec[airports[i]];
05272
05273 if (as == NULL) {
05274 grfmsg(1, "AirportMapSpriteGroup: Airport %d undefined, skipping", airports[i]);
05275 continue;
05276 }
05277
05278 as->grf_prop.spritegroup[0] = _cur.spritegroups[groupid];
05279 }
05280 }
05281
05282 static void AirportTileMapSpriteGroup(ByteReader *buf, uint8 idcount)
05283 {
05284 uint8 *airptiles = AllocaM(uint8, idcount);
05285 for (uint i = 0; i < idcount; i++) {
05286 airptiles[i] = buf->ReadByte();
05287 }
05288
05289
05290 uint8 cidcount = buf->ReadByte();
05291 buf->Skip(cidcount * 3);
05292
05293 uint16 groupid = buf->ReadWord();
05294 if (!IsValidGroupID(groupid, "AirportTileMapSpriteGroup")) return;
05295
05296 if (_cur.grffile->airtspec == NULL) {
05297 grfmsg(1, "AirportTileMapSpriteGroup: No airport tiles defined, skipping");
05298 return;
05299 }
05300
05301 for (uint i = 0; i < idcount; i++) {
05302 AirportTileSpec *airtsp = _cur.grffile->airtspec[airptiles[i]];
05303
05304 if (airtsp == NULL) {
05305 grfmsg(1, "AirportTileMapSpriteGroup: Airport tile %d undefined, skipping", airptiles[i]);
05306 continue;
05307 }
05308
05309 airtsp->grf_prop.spritegroup[0] = _cur.spritegroups[groupid];
05310 }
05311 }
05312
05313
05314
05315 static void FeatureMapSpriteGroup(ByteReader *buf)
05316 {
05317
05318
05319
05320
05321
05322
05323
05324
05325
05326
05327
05328
05329
05330
05331 uint8 feature = buf->ReadByte();
05332 uint8 idcount = buf->ReadByte();
05333
05334
05335 if (idcount == 0) {
05336
05337 buf->ReadByte();
05338 uint16 groupid = buf->ReadWord();
05339 if (!IsValidGroupID(groupid, "FeatureMapSpriteGroup")) return;
05340
05341 grfmsg(6, "FeatureMapSpriteGroup: Adding generic feature callback for feature %d", feature);
05342
05343 AddGenericCallback(feature, _cur.grffile, _cur.spritegroups[groupid]);
05344 return;
05345 }
05346
05347
05348 SetBit(_cur.grffile->grf_features, feature);
05349
05350 grfmsg(6, "FeatureMapSpriteGroup: Feature %d, %d ids", feature, idcount);
05351
05352 switch (feature) {
05353 case GSF_TRAINS:
05354 case GSF_ROADVEHICLES:
05355 case GSF_SHIPS:
05356 case GSF_AIRCRAFT:
05357 VehicleMapSpriteGroup(buf, feature, idcount);
05358 return;
05359
05360 case GSF_CANALS:
05361 CanalMapSpriteGroup(buf, idcount);
05362 return;
05363
05364 case GSF_STATIONS:
05365 StationMapSpriteGroup(buf, idcount);
05366 return;
05367
05368 case GSF_HOUSES:
05369 TownHouseMapSpriteGroup(buf, idcount);
05370 return;
05371
05372 case GSF_INDUSTRIES:
05373 IndustryMapSpriteGroup(buf, idcount);
05374 return;
05375
05376 case GSF_INDUSTRYTILES:
05377 IndustrytileMapSpriteGroup(buf, idcount);
05378 return;
05379
05380 case GSF_CARGOES:
05381 CargoMapSpriteGroup(buf, idcount);
05382 return;
05383
05384 case GSF_AIRPORTS:
05385 AirportMapSpriteGroup(buf, idcount);
05386 return;
05387
05388 case GSF_OBJECTS:
05389 ObjectMapSpriteGroup(buf, idcount);
05390 break;
05391
05392 case GSF_RAILTYPES:
05393 RailTypeMapSpriteGroup(buf, idcount);
05394 break;
05395
05396 case GSF_AIRPORTTILES:
05397 AirportTileMapSpriteGroup(buf, idcount);
05398 return;
05399
05400 default:
05401 grfmsg(1, "FeatureMapSpriteGroup: Unsupported feature %d, skipping", feature);
05402 return;
05403 }
05404 }
05405
05406
05407 static void FeatureNewName(ByteReader *buf)
05408 {
05409
05410
05411
05412
05413
05414
05415
05416
05417
05418
05419
05420
05421
05422
05423
05424
05425 bool new_scheme = _cur.grffile->grf_version >= 7;
05426
05427 uint8 feature = buf->ReadByte();
05428 uint8 lang = buf->ReadByte();
05429 uint8 num = buf->ReadByte();
05430 bool generic = HasBit(lang, 7);
05431 uint16 id;
05432 if (generic) {
05433 id = buf->ReadWord();
05434 } else if (feature <= GSF_AIRCRAFT) {
05435 id = buf->ReadExtendedByte();
05436 } else {
05437 id = buf->ReadByte();
05438 }
05439
05440 ClrBit(lang, 7);
05441
05442 uint16 endid = id + num;
05443
05444 grfmsg(6, "FeatureNewName: About to rename engines %d..%d (feature %d) in language 0x%02X",
05445 id, endid, feature, lang);
05446
05447 for (; id < endid && buf->HasData(); id++) {
05448 const char *name = buf->ReadString();
05449 grfmsg(8, "FeatureNewName: 0x%04X <- %s", id, name);
05450
05451 switch (feature) {
05452 case GSF_TRAINS:
05453 case GSF_ROADVEHICLES:
05454 case GSF_SHIPS:
05455 case GSF_AIRCRAFT:
05456 if (!generic) {
05457 Engine *e = GetNewEngine(_cur.grffile, (VehicleType)feature, id, HasBit(_cur.grfconfig->flags, GCF_STATIC));
05458 if (e == NULL) break;
05459 StringID string = AddGRFString(_cur.grffile->grfid, e->index, lang, new_scheme, false, name, e->info.string_id);
05460 e->info.string_id = string;
05461 } else {
05462 AddGRFString(_cur.grffile->grfid, id, lang, new_scheme, true, name, STR_UNDEFINED);
05463 }
05464 break;
05465
05466 case GSF_INDUSTRIES: {
05467 AddGRFString(_cur.grffile->grfid, id, lang, new_scheme, true, name, STR_UNDEFINED);
05468 break;
05469 }
05470
05471 case GSF_HOUSES:
05472 default:
05473 switch (GB(id, 8, 8)) {
05474 case 0xC4:
05475 if (_cur.grffile->stations == NULL || _cur.grffile->stations[GB(id, 0, 8)] == NULL) {
05476 grfmsg(1, "FeatureNewName: Attempt to name undefined station 0x%X, ignoring", GB(id, 0, 8));
05477 } else {
05478 StationClassID cls_id = _cur.grffile->stations[GB(id, 0, 8)]->cls_id;
05479 StationClass::Get(cls_id)->name = AddGRFString(_cur.grffile->grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
05480 }
05481 break;
05482
05483 case 0xC5:
05484 if (_cur.grffile->stations == NULL || _cur.grffile->stations[GB(id, 0, 8)] == NULL) {
05485 grfmsg(1, "FeatureNewName: Attempt to name undefined station 0x%X, ignoring", GB(id, 0, 8));
05486 } else {
05487 _cur.grffile->stations[GB(id, 0, 8)]->name = AddGRFString(_cur.grffile->grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
05488 }
05489 break;
05490
05491 case 0xC7:
05492 if (_cur.grffile->airtspec == NULL || _cur.grffile->airtspec[GB(id, 0, 8)] == NULL) {
05493 grfmsg(1, "FeatureNewName: Attempt to name undefined airport tile 0x%X, ignoring", GB(id, 0, 8));
05494 } else {
05495 _cur.grffile->airtspec[GB(id, 0, 8)]->name = AddGRFString(_cur.grffile->grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
05496 }
05497 break;
05498
05499 case 0xC9:
05500 if (_cur.grffile->housespec == NULL || _cur.grffile->housespec[GB(id, 0, 8)] == NULL) {
05501 grfmsg(1, "FeatureNewName: Attempt to name undefined house 0x%X, ignoring.", GB(id, 0, 8));
05502 } else {
05503 _cur.grffile->housespec[GB(id, 0, 8)]->building_name = AddGRFString(_cur.grffile->grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
05504 }
05505 break;
05506
05507 case 0xD0:
05508 case 0xD1:
05509 case 0xD2:
05510 case 0xD3:
05511 case 0xDC:
05512 AddGRFString(_cur.grffile->grfid, id, lang, new_scheme, true, name, STR_UNDEFINED);
05513 break;
05514
05515 default:
05516 grfmsg(7, "FeatureNewName: Unsupported ID (0x%04X)", id);
05517 break;
05518 }
05519 break;
05520 }
05521 }
05522 }
05523
05532 static uint16 SanitizeSpriteOffset(uint16& num, uint16 offset, int max_sprites, const char *name)
05533 {
05534
05535 if (offset >= max_sprites) {
05536 grfmsg(1, "GraphicsNew: %s sprite offset must be less than %i, skipping", name, max_sprites);
05537 uint orig_num = num;
05538 num = 0;
05539 return orig_num;
05540 }
05541
05542 if (offset + num > max_sprites) {
05543 grfmsg(4, "GraphicsNew: %s sprite overflow, truncating...", name);
05544 uint orig_num = num;
05545 num = max(max_sprites - offset, 0);
05546 return orig_num - num;
05547 }
05548
05549 return 0;
05550 }
05551
05552
05554 enum Action5BlockType {
05555 A5BLOCK_FIXED,
05556 A5BLOCK_ALLOW_OFFSET,
05557 A5BLOCK_INVALID,
05558 };
05560 struct Action5Type {
05561 Action5BlockType block_type;
05562 SpriteID sprite_base;
05563 uint16 min_sprites;
05564 uint16 max_sprites;
05565 const char *name;
05566 };
05567
05569 static const Action5Type _action5_types[] = {
05570
05571 { A5BLOCK_INVALID, 0, 0, 0, "Type 0x00" },
05572 { A5BLOCK_INVALID, 0, 0, 0, "Type 0x01" },
05573 { A5BLOCK_INVALID, 0, 0, 0, "Type 0x02" },
05574 { A5BLOCK_INVALID, 0, 0, 0, "Type 0x03" },
05575 { A5BLOCK_ALLOW_OFFSET, SPR_SIGNALS_BASE, 1, PRESIGNAL_SEMAPHORE_AND_PBS_SPRITE_COUNT, "Signal graphics" },
05576 { A5BLOCK_ALLOW_OFFSET, SPR_ELRAIL_BASE, 1, ELRAIL_SPRITE_COUNT, "Catenary graphics" },
05577 { A5BLOCK_ALLOW_OFFSET, SPR_SLOPES_BASE, 1, NORMAL_AND_HALFTILE_FOUNDATION_SPRITE_COUNT, "Foundation graphics" },
05578 { A5BLOCK_INVALID, 0, 75, 0, "TTDP GUI graphics" },
05579 { A5BLOCK_ALLOW_OFFSET, SPR_CANALS_BASE, 1, CANALS_SPRITE_COUNT, "Canal graphics" },
05580 { A5BLOCK_ALLOW_OFFSET, SPR_ONEWAY_BASE, 1, ONEWAY_SPRITE_COUNT, "One way road graphics" },
05581 { A5BLOCK_ALLOW_OFFSET, SPR_2CCMAP_BASE, 1, TWOCCMAP_SPRITE_COUNT, "2CC colour maps" },
05582 { A5BLOCK_ALLOW_OFFSET, SPR_TRAMWAY_BASE, 1, TRAMWAY_SPRITE_COUNT, "Tramway graphics" },
05583 { A5BLOCK_INVALID, 0, 133, 0, "Snowy temperate tree" },
05584 { A5BLOCK_FIXED, SPR_SHORE_BASE, 16, SPR_SHORE_SPRITE_COUNT, "Shore graphics" },
05585 { A5BLOCK_INVALID, 0, 0, 0, "New Signals graphics" },
05586 { A5BLOCK_ALLOW_OFFSET, SPR_TRACKS_FOR_SLOPES_BASE, 1, TRACKS_FOR_SLOPES_SPRITE_COUNT, "Sloped rail track" },
05587 { A5BLOCK_ALLOW_OFFSET, SPR_AIRPORTX_BASE, 1, AIRPORTX_SPRITE_COUNT, "Airport graphics" },
05588 { A5BLOCK_ALLOW_OFFSET, SPR_ROADSTOP_BASE, 1, ROADSTOP_SPRITE_COUNT, "Road stop graphics" },
05589 { A5BLOCK_ALLOW_OFFSET, SPR_AQUEDUCT_BASE, 1, AQUEDUCT_SPRITE_COUNT, "Aqueduct graphics" },
05590 { A5BLOCK_ALLOW_OFFSET, SPR_AUTORAIL_BASE, 1, AUTORAIL_SPRITE_COUNT, "Autorail graphics" },
05591 { A5BLOCK_ALLOW_OFFSET, SPR_FLAGS_BASE, 1, FLAGS_SPRITE_COUNT, "Flag graphics" },
05592 { A5BLOCK_ALLOW_OFFSET, SPR_OPENTTD_BASE, 1, OPENTTD_SPRITE_COUNT, "OpenTTD GUI graphics" },
05593 { A5BLOCK_ALLOW_OFFSET, SPR_AIRPORT_PREVIEW_BASE, 1, SPR_AIRPORT_PREVIEW_COUNT, "Airport preview graphics" },
05594 { A5BLOCK_ALLOW_OFFSET, SPR_RAILTYPE_TUNNEL_BASE, 1, RAILTYPE_TUNNEL_BASE_COUNT, "Railtype tunnel base" },
05595 };
05596
05597
05598 static void GraphicsNew(ByteReader *buf)
05599 {
05600
05601
05602
05603
05604
05605
05606
05607 uint8 type = buf->ReadByte();
05608 uint16 num = buf->ReadExtendedByte();
05609 uint16 offset = HasBit(type, 7) ? buf->ReadExtendedByte() : 0;
05610 ClrBit(type, 7);
05611
05612 if ((type == 0x0D) && (num == 10) && _cur.grffile->is_ottdfile) {
05613
05614
05615 grfmsg(2, "GraphicsNew: Loading 10 missing shore sprites from extra grf.");
05616 LoadNextSprite(SPR_SHORE_BASE + 0, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver);
05617 LoadNextSprite(SPR_SHORE_BASE + 5, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver);
05618 LoadNextSprite(SPR_SHORE_BASE + 7, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver);
05619 LoadNextSprite(SPR_SHORE_BASE + 10, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver);
05620 LoadNextSprite(SPR_SHORE_BASE + 11, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver);
05621 LoadNextSprite(SPR_SHORE_BASE + 13, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver);
05622 LoadNextSprite(SPR_SHORE_BASE + 14, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver);
05623 LoadNextSprite(SPR_SHORE_BASE + 15, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver);
05624 LoadNextSprite(SPR_SHORE_BASE + 16, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver);
05625 LoadNextSprite(SPR_SHORE_BASE + 17, _cur.file_index, _cur.nfo_line++, _cur.grf_container_ver);
05626 if (_loaded_newgrf_features.shore == SHORE_REPLACE_NONE) _loaded_newgrf_features.shore = SHORE_REPLACE_ONLY_NEW;
05627 return;
05628 }
05629
05630
05631 if ((type >= lengthof(_action5_types)) || (_action5_types[type].block_type == A5BLOCK_INVALID)) {
05632 grfmsg(2, "GraphicsNew: Custom graphics (type 0x%02X) sprite block of length %u (unimplemented, ignoring)", type, num);
05633 _cur.skip_sprites = num;
05634 return;
05635 }
05636
05637 const Action5Type *action5_type = &_action5_types[type];
05638
05639
05640
05641
05642 if ((action5_type->block_type != A5BLOCK_ALLOW_OFFSET) && (offset != 0)) {
05643 grfmsg(1, "GraphicsNew: %s (type 0x%02X) do not allow an <offset> field. Ignoring offset.", action5_type->name, type);
05644 offset = 0;
05645 }
05646
05647
05648
05649 if ((action5_type->block_type == A5BLOCK_FIXED) && (num < action5_type->min_sprites)) {
05650 grfmsg(1, "GraphicsNew: %s (type 0x%02X) count must be at least %d. Only %d were specified. Skipping.", action5_type->name, type, action5_type->min_sprites, num);
05651 _cur.skip_sprites = num;
05652 return;
05653 }
05654
05655
05656 uint16 skip_num = SanitizeSpriteOffset(num, offset, action5_type->max_sprites, action5_type->name);
05657 SpriteID replace = action5_type->sprite_base + offset;
05658
05659
05660 grfmsg(2, "GraphicsNew: Replacing sprites %d to %d of %s (type 0x%02X) at SpriteID 0x%04X", offset, offset + num - 1, action5_type->name, type, replace);
05661
05662 for (; num > 0; num--) {
05663 _cur.nfo_line++;
05664 LoadNextSprite(replace == 0 ? _cur.spriteid++ : replace++, _cur.file_index, _cur.nfo_line, _cur.grf_container_ver);
05665 }
05666
05667 if (type == 0x0D) _loaded_newgrf_features.shore = SHORE_REPLACE_ACTION_5;
05668
05669 _cur.skip_sprites = skip_num;
05670 }
05671
05672
05673 static void SkipAct5(ByteReader *buf)
05674 {
05675
05676 buf->ReadByte();
05677
05678
05679 _cur.skip_sprites = buf->ReadExtendedByte();
05680
05681 grfmsg(3, "SkipAct5: Skipping %d sprites", _cur.skip_sprites);
05682 }
05683
05689 void CheckForMissingSprites()
05690 {
05691
05692
05693 bool missing = false;
05694 for (uint8 i = 0; i < lengthof(_action5_types); i++) {
05695 const Action5Type *type = &_action5_types[i];
05696 if (type->block_type == A5BLOCK_INVALID) continue;
05697
05698 for (uint j = 0; j < type->max_sprites; j++) {
05699 if (!SpriteExists(type->sprite_base + j)) {
05700 DEBUG(grf, 0, "%s sprites are missing", type->name);
05701 missing = true;
05702
05703 break;
05704 }
05705 }
05706 }
05707
05708 if (missing) {
05709 ShowErrorMessage(IsReleasedVersion() ? STR_NEWGRF_ERROR_MISSING_SPRITES : STR_NEWGRF_ERROR_MISSING_SPRITES_UNSTABLE, INVALID_STRING_ID, WL_CRITICAL);
05710 }
05711 }
05712
05724 bool GetGlobalVariable(byte param, uint32 *value, const GRFFile *grffile)
05725 {
05726 switch (param) {
05727 case 0x00:
05728 *value = max(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0);
05729 return true;
05730
05731 case 0x01:
05732 *value = Clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR;
05733 return true;
05734
05735 case 0x02: {
05736 YearMonthDay ymd;
05737 ConvertDateToYMD(_date, &ymd);
05738 Date start_of_year = ConvertYMDToDate(ymd.year, 0, 1);
05739 *value = ymd.month | (ymd.day - 1) << 8 | (IsLeapYear(ymd.year) ? 1 << 15 : 0) | (_date - start_of_year) << 16;
05740 return true;
05741 }
05742
05743 case 0x03:
05744 *value = _settings_game.game_creation.landscape;
05745 return true;
05746
05747 case 0x06:
05748 *value = _settings_game.vehicle.road_side << 4;
05749 return true;
05750
05751 case 0x09:
05752 *value = _date_fract * 885;
05753 return true;
05754
05755 case 0x0A:
05756 *value = _tick_counter;
05757 return true;
05758
05759 case 0x0B: {
05760 uint major = 2;
05761 uint minor = 6;
05762 uint revision = 1;
05763 uint build = 1382;
05764 *value = (major << 24) | (minor << 20) | (revision << 16) | build;
05765 return true;
05766 }
05767
05768 case 0x0D:
05769 *value = _cur.grfconfig->palette & GRFP_USE_MASK;
05770 return true;
05771
05772 case 0x0E:
05773 *value = _cur.grffile->traininfo_vehicle_pitch;
05774 return true;
05775
05776 case 0x0F:
05777 *value = 0;
05778 SB(*value, 0, 8, GetRailTypeInfo(RAILTYPE_RAIL)->cost_multiplier);
05779 if (_settings_game.vehicle.disable_elrails) {
05780
05781 SB(*value, 8, 8, GetRailTypeInfo(RAILTYPE_MONO)->cost_multiplier);
05782 } else {
05783 SB(*value, 8, 8, GetRailTypeInfo(RAILTYPE_ELECTRIC)->cost_multiplier);
05784
05785 }
05786 SB(*value, 16, 8, GetRailTypeInfo(RAILTYPE_MAGLEV)->cost_multiplier);
05787 return true;
05788
05789 case 0x11:
05790 *value = 0;
05791 return true;
05792
05793 case 0x12:
05794 *value = _game_mode;
05795 return true;
05796
05797
05798
05799
05800
05801
05802
05803 case 0x1A:
05804 *value = UINT_MAX;
05805 return true;
05806
05807 case 0x1B:
05808 *value = 0x3F;
05809 return true;
05810
05811 case 0x1D:
05812 *value = 1;
05813 return true;
05814
05815 case 0x1E:
05816 *value = _misc_grf_features;
05817
05818
05819 assert(!HasBit(*value, GMB_TRAIN_WIDTH_32_PIXELS));
05820 if (_cur.grffile->traininfo_vehicle_width == VEHICLEINFO_FULL_VEHICLE_WIDTH) SetBit(*value, GMB_TRAIN_WIDTH_32_PIXELS);
05821 return true;
05822
05823
05824
05825 case 0x20: {
05826 byte snowline = GetSnowLine();
05827 if (_settings_game.game_creation.landscape == LT_ARCTIC && snowline <= MAX_TILE_HEIGHT) {
05828 *value = Clamp(snowline * (grffile->grf_version >= 8 ? 1 : TILE_HEIGHT), 0, 0xFE);
05829 } else {
05830
05831 *value = 0xFF;
05832 }
05833 return true;
05834 }
05835
05836 case 0x21:
05837 *value = _openttd_newgrf_version;
05838 return true;
05839
05840 case 0x22:
05841 *value = SP_CUSTOM;
05842 return true;
05843
05844 case 0x23:
05845 *value = _date;
05846 return true;
05847
05848 case 0x24:
05849 *value = _cur_year;
05850 return true;
05851
05852 default: return false;
05853 }
05854 }
05855
05856 static uint32 GetParamVal(byte param, uint32 *cond_val)
05857 {
05858
05859 uint32 value;
05860 if (GetGlobalVariable(param - 0x80, &value, _cur.grffile)) return value;
05861
05862
05863 switch (param) {
05864 case 0x84: {
05865 uint32 res = 0;
05866
05867 if (_cur.stage > GLS_INIT) SetBit(res, 0);
05868 if (_cur.stage == GLS_RESERVE) SetBit(res, 8);
05869 if (_cur.stage == GLS_ACTIVATION) SetBit(res, 9);
05870 return res;
05871 }
05872
05873 case 0x85:
05874 if (cond_val == NULL) {
05875
05876 return 0;
05877 } else {
05878 uint32 param_val = _ttdpatch_flags[*cond_val / 0x20];
05879 *cond_val %= 0x20;
05880 return param_val;
05881 }
05882
05883 case 0x88:
05884 return 0;
05885
05886
05887
05888 default:
05889
05890 if (param < 0x80) return _cur.grffile->GetParam(param);
05891
05892
05893 grfmsg(1, "Unsupported in-game variable 0x%02X", param);
05894 return UINT_MAX;
05895 }
05896 }
05897
05898
05899 static void CfgApply(ByteReader *buf)
05900 {
05901
05902
05903
05904
05905
05906
05907
05908
05909
05910
05911
05912
05913 size_t pos = FioGetPos();
05914 uint32 num = _cur.grf_container_ver >= 2 ? FioReadDword() : FioReadWord();
05915 uint8 type = FioReadByte();
05916 byte *preload_sprite = NULL;
05917
05918
05919 if (type == 0xFF) {
05920 preload_sprite = MallocT<byte>(num);
05921 FioReadBlock(preload_sprite, num);
05922 }
05923
05924
05925 FioSeekTo(pos, SEEK_SET);
05926
05927 if (type != 0xFF) {
05928 grfmsg(2, "CfgApply: Ignoring (next sprite is real, unsupported)");
05929 free(preload_sprite);
05930 return;
05931 }
05932
05933 GRFLocation location(_cur.grfconfig->ident.grfid, _cur.nfo_line + 1);
05934 GRFLineToSpriteOverride::iterator it = _grf_line_to_action6_sprite_override.find(location);
05935 if (it != _grf_line_to_action6_sprite_override.end()) {
05936 free(preload_sprite);
05937 preload_sprite = _grf_line_to_action6_sprite_override[location];
05938 } else {
05939 _grf_line_to_action6_sprite_override[location] = preload_sprite;
05940 }
05941
05942
05943
05944 for (;;) {
05945 uint i;
05946 uint param_num;
05947 uint param_size;
05948 uint offset;
05949 bool add_value;
05950
05951
05952 param_num = buf->ReadByte();
05953 if (param_num == 0xFF) break;
05954
05955
05956
05957 param_size = buf->ReadByte();
05958
05959
05960
05961 add_value = HasBit(param_size, 7);
05962 param_size = GB(param_size, 0, 7);
05963
05964
05965 offset = buf->ReadExtendedByte();
05966
05967
05968
05969 if (param_num < 0x80 && (param_num + (param_size - 1) / 4) >= _cur.grffile->param_end) {
05970 grfmsg(2, "CfgApply: Ignoring (param %d not set)", (param_num + (param_size - 1) / 4));
05971 break;
05972 }
05973
05974 grfmsg(8, "CfgApply: Applying %u bytes from parameter 0x%02X at offset 0x%04X", param_size, param_num, offset);
05975
05976 bool carry = false;
05977 for (i = 0; i < param_size && offset + i < num; i++) {
05978 uint32 value = GetParamVal(param_num + i / 4, NULL);
05979
05980
05981 if (i % 4 == 0) carry = false;
05982
05983 if (add_value) {
05984 uint new_value = preload_sprite[offset + i] + GB(value, (i % 4) * 8, 8) + (carry ? 1 : 0);
05985 preload_sprite[offset + i] = GB(new_value, 0, 8);
05986
05987 carry = new_value >= 256;
05988 } else {
05989 preload_sprite[offset + i] = GB(value, (i % 4) * 8, 8);
05990 }
05991 }
05992 }
05993 }
05994
06004 static void DisableStaticNewGRFInfluencingNonStaticNewGRFs(GRFConfig *c)
06005 {
06006 GRFError *error = DisableGrf(STR_NEWGRF_ERROR_STATIC_GRF_CAUSES_DESYNC, c);
06007 error->data = strdup(_cur.grfconfig->GetName());
06008 }
06009
06010
06011
06012 static void SkipIf(ByteReader *buf)
06013 {
06014
06015
06016
06017
06018
06019
06020
06021
06022 uint32 cond_val = 0;
06023 uint32 mask = 0;
06024 bool result;
06025
06026 uint8 param = buf->ReadByte();
06027 uint8 paramsize = buf->ReadByte();
06028 uint8 condtype = buf->ReadByte();
06029
06030 if (condtype < 2) {
06031
06032 paramsize = 1;
06033 }
06034
06035 switch (paramsize) {
06036 case 8: cond_val = buf->ReadDWord(); mask = buf->ReadDWord(); break;
06037 case 4: cond_val = buf->ReadDWord(); mask = 0xFFFFFFFF; break;
06038 case 2: cond_val = buf->ReadWord(); mask = 0x0000FFFF; break;
06039 case 1: cond_val = buf->ReadByte(); mask = 0x000000FF; break;
06040 default: break;
06041 }
06042
06043 if (param < 0x80 && _cur.grffile->param_end <= param) {
06044 grfmsg(7, "SkipIf: Param %d undefined, skipping test", param);
06045 return;
06046 }
06047
06048 uint32 param_val = GetParamVal(param, &cond_val);
06049
06050 grfmsg(7, "SkipIf: Test condtype %d, param 0x%08X, condval 0x%08X", condtype, param_val, cond_val);
06051
06052
06053
06054
06055
06056
06057
06058
06059
06060 if (param == 0x88 && (condtype < 0x0B || condtype > 0x0E)) {
06061
06062
06063 GRFConfig *c = GetGRFConfig(cond_val, mask);
06064
06065 if (c != NULL && HasBit(c->flags, GCF_STATIC) && !HasBit(_cur.grfconfig->flags, GCF_STATIC) && _networking) {
06066 DisableStaticNewGRFInfluencingNonStaticNewGRFs(c);
06067 c = NULL;
06068 }
06069
06070 if (condtype != 10 && c == NULL) {
06071 grfmsg(7, "SkipIf: GRFID 0x%08X unknown, skipping test", BSWAP32(cond_val));
06072 return;
06073 }
06074
06075 switch (condtype) {
06076
06077 case 0x06:
06078 result = c->status == GCS_ACTIVATED;
06079 break;
06080
06081 case 0x07:
06082 result = c->status != GCS_ACTIVATED;
06083 break;
06084
06085 case 0x08:
06086 result = c->status == GCS_INITIALISED;
06087 break;
06088
06089 case 0x09:
06090 result = c->status == GCS_ACTIVATED || c->status == GCS_INITIALISED;
06091 break;
06092
06093 case 0x0A:
06094
06095 result = c == NULL || c->flags == GCS_DISABLED || c->status == GCS_NOT_FOUND;
06096 break;
06097
06098 default: grfmsg(1, "SkipIf: Unsupported GRF condition type %02X. Ignoring", condtype); return;
06099 }
06100 } else {
06101
06102 switch (condtype) {
06103 case 0x00: result = !!(param_val & (1 << cond_val));
06104 break;
06105 case 0x01: result = !(param_val & (1 << cond_val));
06106 break;
06107 case 0x02: result = (param_val & mask) == cond_val;
06108 break;
06109 case 0x03: result = (param_val & mask) != cond_val;
06110 break;
06111 case 0x04: result = (param_val & mask) < cond_val;
06112 break;
06113 case 0x05: result = (param_val & mask) > cond_val;
06114 break;
06115 case 0x0B: result = GetCargoIDByLabel(BSWAP32(cond_val)) == CT_INVALID;
06116 break;
06117 case 0x0C: result = GetCargoIDByLabel(BSWAP32(cond_val)) != CT_INVALID;
06118 break;
06119 case 0x0D: result = GetRailTypeByLabel(BSWAP32(cond_val)) == INVALID_RAILTYPE;
06120 break;
06121 case 0x0E: result = GetRailTypeByLabel(BSWAP32(cond_val)) != INVALID_RAILTYPE;
06122 break;
06123
06124 default: grfmsg(1, "SkipIf: Unsupported condition type %02X. Ignoring", condtype); return;
06125 }
06126 }
06127
06128 if (!result) {
06129 grfmsg(2, "SkipIf: Not skipping sprites, test was false");
06130 return;
06131 }
06132
06133 uint8 numsprites = buf->ReadByte();
06134
06135
06136
06137
06138
06139 GRFLabel *choice = NULL;
06140 for (GRFLabel *label = _cur.grffile->label; label != NULL; label = label->next) {
06141 if (label->label != numsprites) continue;
06142
06143
06144 if (choice == NULL) choice = label;
06145
06146 if (label->nfo_line > _cur.nfo_line) {
06147 choice = label;
06148 break;
06149 }
06150 }
06151
06152 if (choice != NULL) {
06153 grfmsg(2, "SkipIf: Jumping to label 0x%0X at line %d, test was true", choice->label, choice->nfo_line);
06154 FioSeekTo(choice->pos, SEEK_SET);
06155 _cur.nfo_line = choice->nfo_line;
06156 return;
06157 }
06158
06159 grfmsg(2, "SkipIf: Skipping %d sprites, test was true", numsprites);
06160 _cur.skip_sprites = numsprites;
06161 if (_cur.skip_sprites == 0) {
06162
06163
06164
06165 _cur.skip_sprites = -1;
06166
06167
06168 if (_cur.grfconfig->status != (_cur.stage < GLS_RESERVE ? GCS_INITIALISED : GCS_ACTIVATED)) {
06169 DisableGrf();
06170 }
06171 }
06172 }
06173
06174
06175
06176 static void ScanInfo(ByteReader *buf)
06177 {
06178 uint8 grf_version = buf->ReadByte();
06179 uint32 grfid = buf->ReadDWord();
06180 const char *name = buf->ReadString();
06181
06182 _cur.grfconfig->ident.grfid = grfid;
06183
06184 if (grf_version < 2 || grf_version > 8) {
06185 SetBit(_cur.grfconfig->flags, GCF_INVALID);
06186 DEBUG(grf, 0, "%s: NewGRF \"%s\" (GRFID %08X) uses GRF version %d, which is incompatible with this version of OpenTTD.", _cur.grfconfig->filename, name, BSWAP32(grfid), grf_version);
06187 }
06188
06189
06190 if (GB(grfid, 24, 8) == 0xFF) SetBit(_cur.grfconfig->flags, GCF_SYSTEM);
06191
06192 AddGRFTextToList(&_cur.grfconfig->name->text, 0x7F, grfid, false, name);
06193
06194 if (buf->HasData()) {
06195 const char *info = buf->ReadString();
06196 AddGRFTextToList(&_cur.grfconfig->info->text, 0x7F, grfid, true, info);
06197 }
06198
06199
06200 _cur.skip_sprites = -1;
06201 }
06202
06203
06204 static void GRFInfo(ByteReader *buf)
06205 {
06206
06207
06208
06209
06210
06211
06212
06213 uint8 version = buf->ReadByte();
06214 uint32 grfid = buf->ReadDWord();
06215 const char *name = buf->ReadString();
06216
06217 if (_cur.stage < GLS_RESERVE && _cur.grfconfig->status != GCS_UNKNOWN) {
06218 DisableGrf(STR_NEWGRF_ERROR_MULTIPLE_ACTION_8);
06219 return;
06220 }
06221
06222 if (_cur.grffile->grfid != grfid) {
06223 DEBUG(grf, 0, "GRFInfo: GRFID %08X in FILESCAN stage does not match GRFID %08X in INIT/RESERVE/ACTIVATION stage", BSWAP32(_cur.grffile->grfid), BSWAP32(grfid));
06224 _cur.grffile->grfid = grfid;
06225 }
06226
06227 _cur.grffile->grf_version = version;
06228 _cur.grfconfig->status = _cur.stage < GLS_RESERVE ? GCS_INITIALISED : GCS_ACTIVATED;
06229
06230
06231 DEBUG(grf, 1, "GRFInfo: Loaded GRFv%d set %08X - %s (palette: %s, version: %i)", version, BSWAP32(grfid), name, (_cur.grfconfig->palette & GRFP_USE_MASK) ? "Windows" : "DOS", _cur.grfconfig->version);
06232 }
06233
06234
06235 static void SpriteReplace(ByteReader *buf)
06236 {
06237
06238
06239
06240
06241
06242
06243
06244
06245 uint8 num_sets = buf->ReadByte();
06246
06247 for (uint i = 0; i < num_sets; i++) {
06248 uint8 num_sprites = buf->ReadByte();
06249 uint16 first_sprite = buf->ReadWord();
06250
06251 grfmsg(2, "SpriteReplace: [Set %d] Changing %d sprites, beginning with %d",
06252 i, num_sprites, first_sprite
06253 );
06254
06255 for (uint j = 0; j < num_sprites; j++) {
06256 int load_index = first_sprite + j;
06257 _cur.nfo_line++;
06258 LoadNextSprite(load_index, _cur.file_index, _cur.nfo_line, _cur.grf_container_ver);
06259
06260
06261
06262 if (IsInsideMM(load_index, SPR_ORIGINALSHORE_START, SPR_ORIGINALSHORE_END + 1)) {
06263 if (_loaded_newgrf_features.shore != SHORE_REPLACE_ACTION_5) _loaded_newgrf_features.shore = SHORE_REPLACE_ACTION_A;
06264 }
06265 }
06266 }
06267 }
06268
06269
06270 static void SkipActA(ByteReader *buf)
06271 {
06272 uint8 num_sets = buf->ReadByte();
06273
06274 for (uint i = 0; i < num_sets; i++) {
06275
06276 _cur.skip_sprites += buf->ReadByte();
06277
06278 buf->ReadWord();
06279 }
06280
06281 grfmsg(3, "SkipActA: Skipping %d sprites", _cur.skip_sprites);
06282 }
06283
06284
06285 static void GRFLoadError(ByteReader *buf)
06286 {
06287
06288
06289
06290
06291
06292
06293
06294
06295
06296
06297
06298
06299
06300
06301
06302 static const StringID msgstr[] = {
06303 STR_NEWGRF_ERROR_VERSION_NUMBER,
06304 STR_NEWGRF_ERROR_DOS_OR_WINDOWS,
06305 STR_NEWGRF_ERROR_UNSET_SWITCH,
06306 STR_NEWGRF_ERROR_INVALID_PARAMETER,
06307 STR_NEWGRF_ERROR_LOAD_BEFORE,
06308 STR_NEWGRF_ERROR_LOAD_AFTER,
06309 STR_NEWGRF_ERROR_OTTD_VERSION_NUMBER,
06310 };
06311
06312 static const StringID sevstr[] = {
06313 STR_NEWGRF_ERROR_MSG_INFO,
06314 STR_NEWGRF_ERROR_MSG_WARNING,
06315 STR_NEWGRF_ERROR_MSG_ERROR,
06316 STR_NEWGRF_ERROR_MSG_FATAL
06317 };
06318
06319 byte severity = buf->ReadByte();
06320 byte lang = buf->ReadByte();
06321 byte message_id = buf->ReadByte();
06322
06323
06324 if (!CheckGrfLangID(lang, _cur.grffile->grf_version)) return;
06325
06326
06327
06328 if (!HasBit(severity, 7) && _cur.stage == GLS_INIT) {
06329 grfmsg(7, "GRFLoadError: Skipping non-fatal GRFLoadError in stage %d", _cur.stage);
06330 return;
06331 }
06332 ClrBit(severity, 7);
06333
06334 if (severity >= lengthof(sevstr)) {
06335 grfmsg(7, "GRFLoadError: Invalid severity id %d. Setting to 2 (non-fatal error).", severity);
06336 severity = 2;
06337 } else if (severity == 3) {
06338
06339
06340 DisableGrf();
06341
06342
06343 delete _cur.grfconfig->error;
06344 _cur.grfconfig->error = NULL;
06345 }
06346
06347 if (message_id >= lengthof(msgstr) && message_id != 0xFF) {
06348 grfmsg(7, "GRFLoadError: Invalid message id.");
06349 return;
06350 }
06351
06352 if (buf->Remaining() <= 1) {
06353 grfmsg(7, "GRFLoadError: No message data supplied.");
06354 return;
06355 }
06356
06357
06358 if (_cur.grfconfig->error != NULL) return;
06359
06360 GRFError *error = new GRFError(sevstr[severity]);
06361
06362 if (message_id == 0xFF) {
06363
06364 if (buf->HasData()) {
06365 const char *message = buf->ReadString();
06366
06367 error->custom_message = TranslateTTDPatchCodes(_cur.grffile->grfid, lang, true, message, NULL, SCC_RAW_STRING_POINTER);
06368 } else {
06369 grfmsg(7, "GRFLoadError: No custom message supplied.");
06370 error->custom_message = strdup("");
06371 }
06372 } else {
06373 error->message = msgstr[message_id];
06374 }
06375
06376 if (buf->HasData()) {
06377 const char *data = buf->ReadString();
06378
06379 error->data = TranslateTTDPatchCodes(_cur.grffile->grfid, lang, true, data);
06380 } else {
06381 grfmsg(7, "GRFLoadError: No message data supplied.");
06382 error->data = strdup("");
06383 }
06384
06385
06386 for (uint i = 0; i < lengthof(error->param_value) && buf->HasData(); i++) {
06387 uint param_number = buf->ReadByte();
06388 error->param_value[i] = _cur.grffile->GetParam(param_number);
06389 }
06390
06391 _cur.grfconfig->error = error;
06392 }
06393
06394
06395 static void GRFComment(ByteReader *buf)
06396 {
06397
06398
06399
06400
06401 if (!buf->HasData()) return;
06402
06403 const char *text = buf->ReadString();
06404 grfmsg(2, "GRFComment: %s", text);
06405 }
06406
06407
06408 static void SafeParamSet(ByteReader *buf)
06409 {
06410 uint8 target = buf->ReadByte();
06411
06412
06413 if (target < 0x80) return;
06414
06415
06416
06417
06418
06419
06420 SetBit(_cur.grfconfig->flags, GCF_UNSAFE);
06421
06422
06423 _cur.skip_sprites = -1;
06424 }
06425
06426
06427 static uint32 GetPatchVariable(uint8 param)
06428 {
06429 switch (param) {
06430
06431 case 0x0B: return max(_settings_game.game_creation.starting_year, ORIGINAL_BASE_YEAR) - ORIGINAL_BASE_YEAR;
06432
06433
06434 case 0x0E: return _settings_game.vehicle.freight_trains;
06435
06436
06437 case 0x0F: return 0;
06438
06439
06440
06441
06442 case 0x10:
06443 switch (_settings_game.vehicle.plane_speed) {
06444 default:
06445 case 4: return 1;
06446 case 3: return 2;
06447 case 2: return 2;
06448 case 1: return 4;
06449 }
06450
06451
06452
06453 case 0x11: return SPR_2CCMAP_BASE;
06454
06455
06456
06457
06458
06459
06460
06461
06462
06463
06464
06465
06466 case 0x13: {
06467 byte map_bits = 0;
06468 byte log_X = MapLogX() - 6;
06469 byte log_Y = MapLogY() - 6;
06470 byte max_edge = max(log_X, log_Y);
06471
06472 if (log_X == log_Y) {
06473 SetBit(map_bits, 0);
06474 } else {
06475 if (max_edge == log_Y) SetBit(map_bits, 1);
06476 }
06477
06478 return (map_bits << 24) | (min(log_X, log_Y) << 20) | (max_edge << 16) |
06479 (log_X << 12) | (log_Y << 8) | (log_X + log_Y);
06480 }
06481
06482
06483 case 0x14:
06484 return MAX_TILE_HEIGHT;
06485
06486
06487 case 0x15:
06488 return SPR_SLOPES_BASE;
06489
06490
06491 case 0x16:
06492 return SPR_SHORE_BASE;
06493
06494 default:
06495 grfmsg(2, "ParamSet: Unknown Patch variable 0x%02X.", param);
06496 return 0;
06497 }
06498 }
06499
06500
06501 static uint32 PerformGRM(uint32 *grm, uint16 num_ids, uint16 count, uint8 op, uint8 target, const char *type)
06502 {
06503 uint start = 0;
06504 uint size = 0;
06505
06506 if (op == 6) {
06507
06508 return grm[_cur.grffile->GetParam(target)];
06509 }
06510
06511
06512 if (op == 2 || op == 3) start = _cur.grffile->GetParam(target);
06513
06514 for (uint i = start; i < num_ids; i++) {
06515 if (grm[i] == 0) {
06516 size++;
06517 } else {
06518 if (op == 2 || op == 3) break;
06519 start = i + 1;
06520 size = 0;
06521 }
06522
06523 if (size == count) break;
06524 }
06525
06526 if (size == count) {
06527
06528 if (op == 0 || op == 3) {
06529 grfmsg(2, "ParamSet: GRM: Reserving %d %s at %d", count, type, start);
06530 for (uint i = 0; i < count; i++) grm[start + i] = _cur.grffile->grfid;
06531 }
06532 return start;
06533 }
06534
06535
06536 if (op != 4 && op != 5) {
06537
06538 grfmsg(0, "ParamSet: GRM: Unable to allocate %d %s, deactivating", count, type);
06539 DisableGrf(STR_NEWGRF_ERROR_GRM_FAILED);
06540 return UINT_MAX;
06541 }
06542
06543 grfmsg(1, "ParamSet: GRM: Unable to allocate %d %s", count, type);
06544 return UINT_MAX;
06545 }
06546
06547
06549 static void ParamSet(ByteReader *buf)
06550 {
06551
06552
06553
06554
06555
06556
06557
06558
06559
06560
06561
06562
06563
06564
06565
06566
06567
06568
06569
06570
06571
06572
06573 uint8 target = buf->ReadByte();
06574 uint8 oper = buf->ReadByte();
06575 uint32 src1 = buf->ReadByte();
06576 uint32 src2 = buf->ReadByte();
06577
06578 uint32 data = 0;
06579 if (buf->Remaining() >= 4) data = buf->ReadDWord();
06580
06581
06582
06583
06584
06585
06586
06587 if (HasBit(oper, 7)) {
06588 if (target < 0x80 && target < _cur.grffile->param_end) {
06589 grfmsg(7, "ParamSet: Param %u already defined, skipping", target);
06590 return;
06591 }
06592
06593 oper = GB(oper, 0, 7);
06594 }
06595
06596 if (src2 == 0xFE) {
06597 if (GB(data, 0, 8) == 0xFF) {
06598 if (data == 0x0000FFFF) {
06599
06600 src1 = GetPatchVariable(src1);
06601 } else {
06602
06603 uint8 op = src1;
06604 uint8 feature = GB(data, 8, 8);
06605 uint16 count = GB(data, 16, 16);
06606
06607 if (_cur.stage == GLS_RESERVE) {
06608 if (feature == 0x08) {
06609
06610 if (op == 0) {
06611
06612 if (_cur.spriteid + count >= 16384) {
06613 grfmsg(0, "ParamSet: GRM: Unable to allocate %d sprites; try changing NewGRF order", count);
06614 DisableGrf(STR_NEWGRF_ERROR_GRM_FAILED);
06615 return;
06616 }
06617
06618
06619 grfmsg(4, "ParamSet: GRM: Allocated %d sprites at %d", count, _cur.spriteid);
06620 _grm_sprites[GRFLocation(_cur.grffile->grfid, _cur.nfo_line)] = _cur.spriteid;
06621 _cur.spriteid += count;
06622 }
06623 }
06624
06625 src1 = 0;
06626 } else if (_cur.stage == GLS_ACTIVATION) {
06627 switch (feature) {
06628 case 0x00:
06629 case 0x01:
06630 case 0x02:
06631 case 0x03:
06632 if (!_settings_game.vehicle.dynamic_engines) {
06633 src1 = PerformGRM(&_grm_engines[_engine_offsets[feature]], _engine_counts[feature], count, op, target, "vehicles");
06634 if (_cur.skip_sprites == -1) return;
06635 } else {
06636
06637 switch (op) {
06638 case 2:
06639 case 3:
06640 src1 = _cur.grffile->GetParam(target);
06641 break;
06642
06643 default:
06644 src1 = 0;
06645 break;
06646 }
06647 }
06648 break;
06649
06650 case 0x08:
06651 switch (op) {
06652 case 0:
06653
06654 src1 = _grm_sprites[GRFLocation(_cur.grffile->grfid, _cur.nfo_line)];
06655 grfmsg(4, "ParamSet: GRM: Using pre-allocated sprites at %d", src1);
06656 break;
06657
06658 case 1:
06659 src1 = _cur.spriteid;
06660 break;
06661
06662 default:
06663 grfmsg(1, "ParamSet: GRM: Unsupported operation %d for general sprites", op);
06664 return;
06665 }
06666 break;
06667
06668 case 0x0B:
06669
06670 src1 = PerformGRM(_grm_cargoes, NUM_CARGO * 2, count, op, target, "cargoes");
06671 if (_cur.skip_sprites == -1) return;
06672 break;
06673
06674 default: grfmsg(1, "ParamSet: GRM: Unsupported feature 0x%X", feature); return;
06675 }
06676 } else {
06677
06678 src1 = 0;
06679 }
06680 }
06681 } else {
06682
06683 const GRFFile *file = GetFileByGRFID(data);
06684 GRFConfig *c = GetGRFConfig(data);
06685 if (c != NULL && HasBit(c->flags, GCF_STATIC) && !HasBit(_cur.grfconfig->flags, GCF_STATIC) && _networking) {
06686
06687 DisableStaticNewGRFInfluencingNonStaticNewGRFs(c);
06688 src1 = 0;
06689 } else if (file == NULL || c == NULL || c->status == GCS_DISABLED) {
06690 src1 = 0;
06691 } else if (src1 == 0xFE) {
06692 src1 = c->version;
06693 } else {
06694 src1 = file->GetParam(src1);
06695 }
06696 }
06697 } else {
06698
06699
06700
06701
06702
06703 src1 = (src1 == 0xFF) ? data : GetParamVal(src1, NULL);
06704 src2 = (src2 == 0xFF) ? data : GetParamVal(src2, NULL);
06705 }
06706
06707
06708
06709
06710
06711
06712
06713 uint32 res;
06714 switch (oper) {
06715 case 0x00:
06716 res = src1;
06717 break;
06718
06719 case 0x01:
06720 res = src1 + src2;
06721 break;
06722
06723 case 0x02:
06724 res = src1 - src2;
06725 break;
06726
06727 case 0x03:
06728 res = src1 * src2;
06729 break;
06730
06731 case 0x04:
06732 res = (int32)src1 * (int32)src2;
06733 break;
06734
06735 case 0x05:
06736 if ((int32)src2 < 0) {
06737 res = src1 >> -(int32)src2;
06738 } else {
06739 res = src1 << (src2 & 0x1F);
06740 }
06741 break;
06742
06743 case 0x06:
06744 if ((int32)src2 < 0) {
06745 res = (int32)src1 >> -(int32)src2;
06746 } else {
06747 res = (int32)src1 << (src2 & 0x1F);
06748 }
06749 break;
06750
06751 case 0x07:
06752 res = src1 & src2;
06753 break;
06754
06755 case 0x08:
06756 res = src1 | src2;
06757 break;
06758
06759 case 0x09:
06760 if (src2 == 0) {
06761 res = src1;
06762 } else {
06763 res = src1 / src2;
06764 }
06765 break;
06766
06767 case 0x0A:
06768 if (src2 == 0) {
06769 res = src1;
06770 } else {
06771 res = (int32)src1 / (int32)src2;
06772 }
06773 break;
06774
06775 case 0x0B:
06776 if (src2 == 0) {
06777 res = src1;
06778 } else {
06779 res = src1 % src2;
06780 }
06781 break;
06782
06783 case 0x0C:
06784 if (src2 == 0) {
06785 res = src1;
06786 } else {
06787 res = (int32)src1 % (int32)src2;
06788 }
06789 break;
06790
06791 default: grfmsg(0, "ParamSet: Unknown operation %d, skipping", oper); return;
06792 }
06793
06794 switch (target) {
06795 case 0x8E:
06796 _cur.grffile->traininfo_vehicle_pitch = res;
06797 break;
06798
06799 case 0x8F: {
06800 extern RailtypeInfo _railtypes[RAILTYPE_END];
06801 _railtypes[RAILTYPE_RAIL].cost_multiplier = GB(res, 0, 8);
06802 if (_settings_game.vehicle.disable_elrails) {
06803 _railtypes[RAILTYPE_ELECTRIC].cost_multiplier = GB(res, 0, 8);
06804 _railtypes[RAILTYPE_MONO].cost_multiplier = GB(res, 8, 8);
06805 } else {
06806 _railtypes[RAILTYPE_ELECTRIC].cost_multiplier = GB(res, 8, 8);
06807 _railtypes[RAILTYPE_MONO].cost_multiplier = GB(res, 16, 8);
06808 }
06809 _railtypes[RAILTYPE_MAGLEV].cost_multiplier = GB(res, 16, 8);
06810 break;
06811 }
06812
06813
06814 case 0x93:
06815 case 0x94:
06816 case 0x95:
06817 case 0x96:
06818 case 0x97:
06819 case 0x99:
06820 grfmsg(7, "ParamSet: Skipping unimplemented target 0x%02X", target);
06821 break;
06822
06823 case 0x9E:
06824
06825 _cur.grffile->traininfo_vehicle_width = HasBit(res, GMB_TRAIN_WIDTH_32_PIXELS) ? VEHICLEINFO_FULL_VEHICLE_WIDTH : TRAININFO_DEFAULT_VEHICLE_WIDTH;
06826
06827 ClrBit(res, GMB_TRAIN_WIDTH_32_PIXELS);
06828
06829 _misc_grf_features = res;
06830 break;
06831
06832 case 0x9F:
06833 grfmsg(7, "ParamSet: Skipping unimplemented target 0x%02X", target);
06834 break;
06835
06836 default:
06837 if (target < 0x80) {
06838 _cur.grffile->param[target] = res;
06839
06840 if (target + 1U > _cur.grffile->param_end) _cur.grffile->param_end = target + 1;
06841 } else {
06842 grfmsg(7, "ParamSet: Skipping unknown target 0x%02X", target);
06843 }
06844 break;
06845 }
06846 }
06847
06848
06849 static void SafeGRFInhibit(ByteReader *buf)
06850 {
06851
06852
06853
06854
06855
06856 uint8 num = buf->ReadByte();
06857
06858 for (uint i = 0; i < num; i++) {
06859 uint32 grfid = buf->ReadDWord();
06860
06861
06862 if (grfid != _cur.grfconfig->ident.grfid) {
06863 SetBit(_cur.grfconfig->flags, GCF_UNSAFE);
06864
06865
06866 _cur.skip_sprites = -1;
06867
06868 return;
06869 }
06870 }
06871 }
06872
06873
06874 static void GRFInhibit(ByteReader *buf)
06875 {
06876
06877
06878
06879
06880
06881 uint8 num = buf->ReadByte();
06882
06883 for (uint i = 0; i < num; i++) {
06884 uint32 grfid = buf->ReadDWord();
06885 GRFConfig *file = GetGRFConfig(grfid);
06886
06887
06888 if (file != NULL && file != _cur.grfconfig) {
06889 grfmsg(2, "GRFInhibit: Deactivating file '%s'", file->filename);
06890 GRFError *error = DisableGrf(STR_NEWGRF_ERROR_FORCEFULLY_DISABLED, file);
06891 error->data = strdup(_cur.grfconfig->GetName());
06892 }
06893 }
06894 }
06895
06897 static void FeatureTownName(ByteReader *buf)
06898 {
06899
06900
06901
06902
06903
06904
06905
06906 uint32 grfid = _cur.grffile->grfid;
06907
06908 GRFTownName *townname = AddGRFTownName(grfid);
06909
06910 byte id = buf->ReadByte();
06911 grfmsg(6, "FeatureTownName: definition 0x%02X", id & 0x7F);
06912
06913 if (HasBit(id, 7)) {
06914
06915 ClrBit(id, 7);
06916 bool new_scheme = _cur.grffile->grf_version >= 7;
06917
06918 byte lang = buf->ReadByte();
06919
06920 byte nb_gen = townname->nb_gen;
06921 do {
06922 ClrBit(lang, 7);
06923
06924 const char *name = buf->ReadString();
06925
06926 char *lang_name = TranslateTTDPatchCodes(grfid, lang, false, name);
06927 grfmsg(6, "FeatureTownName: lang 0x%X -> '%s'", lang, lang_name);
06928 free(lang_name);
06929
06930 townname->name[nb_gen] = AddGRFString(grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
06931
06932 lang = buf->ReadByte();
06933 } while (lang != 0);
06934 townname->id[nb_gen] = id;
06935 townname->nb_gen++;
06936 }
06937
06938 byte nb = buf->ReadByte();
06939 grfmsg(6, "FeatureTownName: %u parts", nb);
06940
06941 townname->nbparts[id] = nb;
06942 townname->partlist[id] = CallocT<NamePartList>(nb);
06943
06944 for (int i = 0; i < nb; i++) {
06945 byte nbtext = buf->ReadByte();
06946 townname->partlist[id][i].bitstart = buf->ReadByte();
06947 townname->partlist[id][i].bitcount = buf->ReadByte();
06948 townname->partlist[id][i].maxprob = 0;
06949 townname->partlist[id][i].partcount = nbtext;
06950 townname->partlist[id][i].parts = CallocT<NamePart>(nbtext);
06951 grfmsg(6, "FeatureTownName: part %d contains %d texts and will use GB(seed, %d, %d)", i, nbtext, townname->partlist[id][i].bitstart, townname->partlist[id][i].bitcount);
06952
06953 for (int j = 0; j < nbtext; j++) {
06954 byte prob = buf->ReadByte();
06955
06956 if (HasBit(prob, 7)) {
06957 byte ref_id = buf->ReadByte();
06958
06959 if (townname->nbparts[ref_id] == 0) {
06960 grfmsg(0, "FeatureTownName: definition 0x%02X doesn't exist, deactivating", ref_id);
06961 DelGRFTownName(grfid);
06962 DisableGrf(STR_NEWGRF_ERROR_INVALID_ID);
06963 return;
06964 }
06965
06966 grfmsg(6, "FeatureTownName: part %d, text %d, uses intermediate definition 0x%02X (with probability %d)", i, j, ref_id, prob & 0x7F);
06967 townname->partlist[id][i].parts[j].data.id = ref_id;
06968 } else {
06969 const char *text = buf->ReadString();
06970 townname->partlist[id][i].parts[j].data.text = TranslateTTDPatchCodes(grfid, 0, false, text);
06971 grfmsg(6, "FeatureTownName: part %d, text %d, '%s' (with probability %d)", i, j, townname->partlist[id][i].parts[j].data.text, prob);
06972 }
06973 townname->partlist[id][i].parts[j].prob = prob;
06974 townname->partlist[id][i].maxprob += GB(prob, 0, 7);
06975 }
06976 grfmsg(6, "FeatureTownName: part %d, total probability %d", i, townname->partlist[id][i].maxprob);
06977 }
06978 }
06979
06981 static void DefineGotoLabel(ByteReader *buf)
06982 {
06983
06984
06985
06986
06987
06988 byte nfo_label = buf->ReadByte();
06989
06990 GRFLabel *label = MallocT<GRFLabel>(1);
06991 label->label = nfo_label;
06992 label->nfo_line = _cur.nfo_line;
06993 label->pos = FioGetPos();
06994 label->next = NULL;
06995
06996
06997 if (_cur.grffile->label == NULL) {
06998 _cur.grffile->label = label;
06999 } else {
07000
07001 GRFLabel *l;
07002 for (l = _cur.grffile->label; l->next != NULL; l = l->next) {}
07003 l->next = label;
07004 }
07005
07006 grfmsg(2, "DefineGotoLabel: GOTO target with label 0x%02X", label->label);
07007 }
07008
07013 static void ImportGRFSound(SoundEntry *sound)
07014 {
07015 const GRFFile *file;
07016 uint32 grfid = FioReadDword();
07017 SoundID sound_id = FioReadWord();
07018
07019 file = GetFileByGRFID(grfid);
07020 if (file == NULL || file->sound_offset == 0) {
07021 grfmsg(1, "ImportGRFSound: Source file not available");
07022 return;
07023 }
07024
07025 if (sound_id >= file->num_sounds) {
07026 grfmsg(1, "ImportGRFSound: Sound effect %d is invalid", sound_id);
07027 return;
07028 }
07029
07030 grfmsg(2, "ImportGRFSound: Copying sound %d (%d) from file %X", sound_id, file->sound_offset + sound_id, grfid);
07031
07032 *sound = *GetSound(file->sound_offset + sound_id);
07033
07034
07035 sound->volume = 128;
07036 sound->priority = 0;
07037 }
07038
07044 static void LoadGRFSound(size_t offs, SoundEntry *sound)
07045 {
07046
07047 sound->volume = 0x80;
07048 sound->priority = 0;
07049
07050 if (offs != SIZE_MAX) {
07051
07052 sound->file_slot = _cur.file_index;
07053 sound->file_offset = offs;
07054 sound->grf_container_ver = _cur.grf_container_ver;
07055 }
07056 }
07057
07058
07059 static void GRFSound(ByteReader *buf)
07060 {
07061
07062
07063
07064
07065 uint16 num = buf->ReadWord();
07066 if (num == 0) return;
07067
07068 SoundEntry *sound;
07069 if (_cur.grffile->sound_offset == 0) {
07070 _cur.grffile->sound_offset = GetNumSounds();
07071 _cur.grffile->num_sounds = num;
07072 sound = AllocateSound(num);
07073 } else {
07074 sound = GetSound(_cur.grffile->sound_offset);
07075 }
07076
07077 for (int i = 0; i < num; i++) {
07078 _cur.nfo_line++;
07079
07080
07081
07082 bool invalid = i >= _cur.grffile->num_sounds;
07083
07084 size_t offs = FioGetPos();
07085
07086 uint32 len = _cur.grf_container_ver >= 2 ? FioReadDword() : FioReadWord();
07087 byte type = FioReadByte();
07088
07089 if (_cur.grf_container_ver >= 2 && type == 0xFD) {
07090
07091 if (invalid) {
07092 grfmsg(1, "GRFSound: Sound index out of range (multiple Action 11?)");
07093 FioSkipBytes(len);
07094 } else if (len != 4) {
07095 grfmsg(1, "GRFSound: Invalid sprite section import");
07096 FioSkipBytes(len);
07097 } else {
07098 uint32 id = FioReadDword();
07099 if (_cur.stage == GLS_INIT) LoadGRFSound(GetGRFSpriteOffset(id), sound + i);
07100 }
07101 continue;
07102 }
07103
07104 if (type != 0xFF) {
07105 grfmsg(1, "GRFSound: Unexpected RealSprite found, skipping");
07106 FioSkipBytes(7);
07107 SkipSpriteData(type, len - 8);
07108 continue;
07109 }
07110
07111 if (invalid) {
07112 grfmsg(1, "GRFSound: Sound index out of range (multiple Action 11?)");
07113 FioSkipBytes(len);
07114 }
07115
07116 byte action = FioReadByte();
07117 switch (action) {
07118 case 0xFF:
07119
07120 if (_cur.stage == GLS_INIT) {
07121 if (_cur.grf_container_ver >= 2) {
07122 grfmsg(1, "GRFSound: Inline sounds are not supported for container version >= 2");
07123 } else {
07124 LoadGRFSound(offs, sound + i);
07125 }
07126 }
07127 FioSkipBytes(len - 1);
07128 break;
07129
07130 case 0xFE:
07131 if (_cur.stage == GLS_ACTIVATION) {
07132
07133
07134 if (FioReadByte() != 0) grfmsg(1, "GRFSound: Import type mismatch");
07135 ImportGRFSound(sound + i);
07136 } else {
07137 FioSkipBytes(len - 1);
07138 }
07139 break;
07140
07141 default:
07142 grfmsg(1, "GRFSound: Unexpected Action %x found, skipping", action);
07143 FioSkipBytes(len - 1);
07144 break;
07145 }
07146 }
07147 }
07148
07149
07150 static void SkipAct11(ByteReader *buf)
07151 {
07152
07153
07154
07155
07156 _cur.skip_sprites = buf->ReadWord();
07157
07158 grfmsg(3, "SkipAct11: Skipping %d sprites", _cur.skip_sprites);
07159 }
07160
07162 static void LoadFontGlyph(ByteReader *buf)
07163 {
07164
07165
07166
07167
07168
07169
07170
07171 uint8 num_def = buf->ReadByte();
07172
07173 for (uint i = 0; i < num_def; i++) {
07174 FontSize size = (FontSize)buf->ReadByte();
07175 uint8 num_char = buf->ReadByte();
07176 uint16 base_char = buf->ReadWord();
07177
07178 if (size >= FS_END) {
07179 grfmsg(1, "LoadFontGlyph: Size %u is not supported, ignoring", size);
07180 }
07181
07182 grfmsg(7, "LoadFontGlyph: Loading %u glyph(s) at 0x%04X for size %u", num_char, base_char, size);
07183
07184 for (uint c = 0; c < num_char; c++) {
07185 if (size < FS_END) SetUnicodeGlyph(size, base_char + c, _cur.spriteid);
07186 _cur.nfo_line++;
07187 LoadNextSprite(_cur.spriteid++, _cur.file_index, _cur.nfo_line, _cur.grf_container_ver);
07188 }
07189 }
07190 }
07191
07193 static void SkipAct12(ByteReader *buf)
07194 {
07195
07196
07197
07198
07199
07200
07201
07202 uint8 num_def = buf->ReadByte();
07203
07204 for (uint i = 0; i < num_def; i++) {
07205
07206 buf->ReadByte();
07207
07208
07209 _cur.skip_sprites += buf->ReadByte();
07210
07211
07212 buf->ReadWord();
07213 }
07214
07215 grfmsg(3, "SkipAct12: Skipping %d sprites", _cur.skip_sprites);
07216 }
07217
07219 static void TranslateGRFStrings(ByteReader *buf)
07220 {
07221
07222
07223
07224
07225
07226
07227
07228 uint32 grfid = buf->ReadDWord();
07229 const GRFConfig *c = GetGRFConfig(grfid);
07230 if (c == NULL || (c->status != GCS_INITIALISED && c->status != GCS_ACTIVATED)) {
07231 grfmsg(7, "TranslateGRFStrings: GRFID 0x%08x unknown, skipping action 13", BSWAP32(grfid));
07232 return;
07233 }
07234
07235 if (c->status == GCS_INITIALISED) {
07236
07237
07238 GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LOAD_AFTER);
07239
07240 char tmp[256];
07241 GetString(tmp, STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE, lastof(tmp));
07242 error->data = strdup(tmp);
07243
07244 return;
07245 }
07246
07247
07248
07249
07250
07251
07252 byte language = _cur.grffile->grf_version >= 8 ? buf->ReadByte() : 0x7F;
07253 byte num_strings = buf->ReadByte();
07254 uint16 first_id = buf->ReadWord();
07255
07256 if (!((first_id >= 0xD000 && first_id + num_strings <= 0xD3FF) || (first_id >= 0xDC00 && first_id + num_strings <= 0xDCFF))) {
07257 grfmsg(7, "TranslateGRFStrings: Attempting to set out-of-range string IDs in action 13 (first: 0x%4X, number: 0x%2X)", first_id, num_strings);
07258 return;
07259 }
07260
07261 for (uint i = 0; i < num_strings && buf->HasData(); i++) {
07262 const char *string = buf->ReadString();
07263
07264 if (StrEmpty(string)) {
07265 grfmsg(7, "TranslateGRFString: Ignoring empty string.");
07266 continue;
07267 }
07268
07269 AddGRFString(grfid, first_id + i, language, true, true, string, STR_UNDEFINED);
07270 }
07271 }
07272
07274 static bool ChangeGRFName(byte langid, const char *str)
07275 {
07276 AddGRFTextToList(&_cur.grfconfig->name->text, langid, _cur.grfconfig->ident.grfid, false, str);
07277 return true;
07278 }
07279
07281 static bool ChangeGRFDescription(byte langid, const char *str)
07282 {
07283 AddGRFTextToList(&_cur.grfconfig->info->text, langid, _cur.grfconfig->ident.grfid, true, str);
07284 return true;
07285 }
07286
07288 static bool ChangeGRFURL(byte langid, const char *str)
07289 {
07290 AddGRFTextToList(&_cur.grfconfig->url->text, langid, _cur.grfconfig->ident.grfid, false, str);
07291 return true;
07292 }
07293
07295 static bool ChangeGRFNumUsedParams(size_t len, ByteReader *buf)
07296 {
07297 if (len != 1) {
07298 grfmsg(2, "StaticGRFInfo: expected only 1 byte for 'INFO'->'NPAR' but got " PRINTF_SIZE ", ignoring this field", len);
07299 buf->Skip(len);
07300 } else {
07301 _cur.grfconfig->num_valid_params = min(buf->ReadByte(), lengthof(_cur.grfconfig->param));
07302 }
07303 return true;
07304 }
07305
07307 static bool ChangeGRFPalette(size_t len, ByteReader *buf)
07308 {
07309 if (len != 1) {
07310 grfmsg(2, "StaticGRFInfo: expected only 1 byte for 'INFO'->'PALS' but got " PRINTF_SIZE ", ignoring this field", len);
07311 buf->Skip(len);
07312 } else {
07313 char data = buf->ReadByte();
07314 GRFPalette pal = GRFP_GRF_UNSET;
07315 switch (data) {
07316 case '*':
07317 case 'A': pal = GRFP_GRF_ANY; break;
07318 case 'W': pal = GRFP_GRF_WINDOWS; break;
07319 case 'D': pal = GRFP_GRF_DOS; break;
07320 default:
07321 grfmsg(2, "StaticGRFInfo: unexpected value '%02x' for 'INFO'->'PALS', ignoring this field", data);
07322 break;
07323 }
07324 if (pal != GRFP_GRF_UNSET) {
07325 _cur.grfconfig->palette &= ~GRFP_GRF_MASK;
07326 _cur.grfconfig->palette |= pal;
07327 }
07328 }
07329 return true;
07330 }
07331
07333 static bool ChangeGRFBlitter(size_t len, ByteReader *buf)
07334 {
07335 if (len != 1) {
07336 grfmsg(2, "StaticGRFInfo: expected only 1 byte for 'INFO'->'BLTR' but got " PRINTF_SIZE ", ignoring this field", len);
07337 buf->Skip(len);
07338 } else {
07339 char data = buf->ReadByte();
07340 GRFPalette pal = GRFP_BLT_UNSET;
07341 switch (data) {
07342 case '8': pal = GRFP_BLT_UNSET; break;
07343 case '3': pal = GRFP_BLT_32BPP; break;
07344 default:
07345 grfmsg(2, "StaticGRFInfo: unexpected value '%02x' for 'INFO'->'BLTR', ignoring this field", data);
07346 return true;
07347 }
07348 _cur.grfconfig->palette &= ~GRFP_BLT_MASK;
07349 _cur.grfconfig->palette |= pal;
07350 }
07351 return true;
07352 }
07353
07355 static bool ChangeGRFVersion(size_t len, ByteReader *buf)
07356 {
07357 if (len != 4) {
07358 grfmsg(2, "StaticGRFInfo: expected 4 bytes for 'INFO'->'VRSN' but got " PRINTF_SIZE ", ignoring this field", len);
07359 buf->Skip(len);
07360 } else {
07361
07362 _cur.grfconfig->version = _cur.grfconfig->min_loadable_version = buf->ReadDWord();
07363 }
07364 return true;
07365 }
07366
07368 static bool ChangeGRFMinVersion(size_t len, ByteReader *buf)
07369 {
07370 if (len != 4) {
07371 grfmsg(2, "StaticGRFInfo: expected 4 bytes for 'INFO'->'MINV' but got " PRINTF_SIZE ", ignoring this field", len);
07372 buf->Skip(len);
07373 } else {
07374 _cur.grfconfig->min_loadable_version = buf->ReadDWord();
07375 if (_cur.grfconfig->version == 0) {
07376 grfmsg(2, "StaticGRFInfo: 'MINV' defined before 'VRSN' or 'VRSN' set to 0, ignoring this field");
07377 _cur.grfconfig->min_loadable_version = 0;
07378 }
07379 if (_cur.grfconfig->version < _cur.grfconfig->min_loadable_version) {
07380 grfmsg(2, "StaticGRFInfo: 'MINV' defined as %d, limiting it to 'VRSN'", _cur.grfconfig->min_loadable_version);
07381 _cur.grfconfig->min_loadable_version = _cur.grfconfig->version;
07382 }
07383 }
07384 return true;
07385 }
07386
07387 static GRFParameterInfo *_cur_parameter;
07388
07390 static bool ChangeGRFParamName(byte langid, const char *str)
07391 {
07392 AddGRFTextToList(&_cur_parameter->name, langid, _cur.grfconfig->ident.grfid, false, str);
07393 return true;
07394 }
07395
07397 static bool ChangeGRFParamDescription(byte langid, const char *str)
07398 {
07399 AddGRFTextToList(&_cur_parameter->desc, langid, _cur.grfconfig->ident.grfid, true, str);
07400 return true;
07401 }
07402
07404 static bool ChangeGRFParamType(size_t len, ByteReader *buf)
07405 {
07406 if (len != 1) {
07407 grfmsg(2, "StaticGRFInfo: expected 1 byte for 'INFO'->'PARA'->'TYPE' but got " PRINTF_SIZE ", ignoring this field", len);
07408 buf->Skip(len);
07409 } else {
07410 GRFParameterType type = (GRFParameterType)buf->ReadByte();
07411 if (type < PTYPE_END) {
07412 _cur_parameter->type = type;
07413 } else {
07414 grfmsg(3, "StaticGRFInfo: unknown parameter type %d, ignoring this field", type);
07415 }
07416 }
07417 return true;
07418 }
07419
07421 static bool ChangeGRFParamLimits(size_t len, ByteReader *buf)
07422 {
07423 if (_cur_parameter->type != PTYPE_UINT_ENUM) {
07424 grfmsg(2, "StaticGRFInfo: 'INFO'->'PARA'->'LIMI' is only valid for parameters with type uint/enum, ignoring this field");
07425 buf->Skip(len);
07426 } else if (len != 8) {
07427 grfmsg(2, "StaticGRFInfo: expected 8 bytes for 'INFO'->'PARA'->'LIMI' but got " PRINTF_SIZE ", ignoring this field", len);
07428 buf->Skip(len);
07429 } else {
07430 _cur_parameter->min_value = buf->ReadDWord();
07431 _cur_parameter->max_value = buf->ReadDWord();
07432 }
07433 return true;
07434 }
07435
07437 static bool ChangeGRFParamMask(size_t len, ByteReader *buf)
07438 {
07439 if (len < 1 || len > 3) {
07440 grfmsg(2, "StaticGRFInfo: expected 1 to 3 bytes for 'INFO'->'PARA'->'MASK' but got " PRINTF_SIZE ", ignoring this field", len);
07441 buf->Skip(len);
07442 } else {
07443 byte param_nr = buf->ReadByte();
07444 if (param_nr >= lengthof(_cur.grfconfig->param)) {
07445 grfmsg(2, "StaticGRFInfo: invalid parameter number in 'INFO'->'PARA'->'MASK', param %d, ignoring this field", param_nr);
07446 buf->Skip(len - 1);
07447 } else {
07448 _cur_parameter->param_nr = param_nr;
07449 if (len >= 2) _cur_parameter->first_bit = min(buf->ReadByte(), 31);
07450 if (len >= 3) _cur_parameter->num_bit = min(buf->ReadByte(), 32 - _cur_parameter->first_bit);
07451 }
07452 }
07453
07454 return true;
07455 }
07456
07458 static bool ChangeGRFParamDefault(size_t len, ByteReader *buf)
07459 {
07460 if (len != 4) {
07461 grfmsg(2, "StaticGRFInfo: expected 4 bytes for 'INFO'->'PARA'->'DEFA' but got " PRINTF_SIZE ", ignoring this field", len);
07462 buf->Skip(len);
07463 } else {
07464 _cur_parameter->def_value = buf->ReadDWord();
07465 }
07466 _cur.grfconfig->has_param_defaults = true;
07467 return true;
07468 }
07469
07470 typedef bool (*DataHandler)(size_t, ByteReader *);
07471 typedef bool (*TextHandler)(byte, const char *str);
07472 typedef bool (*BranchHandler)(ByteReader *);
07473
07481 struct AllowedSubtags {
07483 AllowedSubtags() :
07484 id(0),
07485 type(0)
07486 {}
07487
07493 AllowedSubtags(uint32 id, DataHandler handler) :
07494 id(id),
07495 type('B')
07496 {
07497 this->handler.data = handler;
07498 }
07499
07505 AllowedSubtags(uint32 id, TextHandler handler) :
07506 id(id),
07507 type('T')
07508 {
07509 this->handler.text = handler;
07510 }
07511
07517 AllowedSubtags(uint32 id, BranchHandler handler) :
07518 id(id),
07519 type('C')
07520 {
07521 this->handler.call_handler = true;
07522 this->handler.u.branch = handler;
07523 }
07524
07530 AllowedSubtags(uint32 id, AllowedSubtags *subtags) :
07531 id(id),
07532 type('C')
07533 {
07534 this->handler.call_handler = false;
07535 this->handler.u.subtags = subtags;
07536 }
07537
07538 uint32 id;
07539 byte type;
07540 union {
07541 DataHandler data;
07542 TextHandler text;
07543 struct {
07544 union {
07545 BranchHandler branch;
07546 AllowedSubtags *subtags;
07547 } u;
07548 bool call_handler;
07549 };
07550 } handler;
07551 };
07552
07553 static bool SkipUnknownInfo(ByteReader *buf, byte type);
07554 static bool HandleNodes(ByteReader *buf, AllowedSubtags *tags);
07555
07562 static bool ChangeGRFParamValueNames(ByteReader *buf)
07563 {
07564 byte type = buf->ReadByte();
07565 while (type != 0) {
07566 uint32 id = buf->ReadDWord();
07567 if (type != 'T' || id > _cur_parameter->max_value) {
07568 grfmsg(2, "StaticGRFInfo: all child nodes of 'INFO'->'PARA'->param_num->'VALU' should have type 't' and the value/bit number as id");
07569 if (!SkipUnknownInfo(buf, type)) return false;
07570 type = buf->ReadByte();
07571 continue;
07572 }
07573
07574 byte langid = buf->ReadByte();
07575 const char *name_string = buf->ReadString();
07576
07577 SmallPair<uint32, GRFText *> *val_name = _cur_parameter->value_names.Find(id);
07578 if (val_name != _cur_parameter->value_names.End()) {
07579 AddGRFTextToList(&val_name->second, langid, _cur.grfconfig->ident.grfid, false, name_string);
07580 } else {
07581 GRFText *list = NULL;
07582 AddGRFTextToList(&list, langid, _cur.grfconfig->ident.grfid, false, name_string);
07583 _cur_parameter->value_names.Insert(id, list);
07584 }
07585
07586 type = buf->ReadByte();
07587 }
07588 return true;
07589 }
07590
07592 AllowedSubtags _tags_parameters[] = {
07593 AllowedSubtags('NAME', ChangeGRFParamName),
07594 AllowedSubtags('DESC', ChangeGRFParamDescription),
07595 AllowedSubtags('TYPE', ChangeGRFParamType),
07596 AllowedSubtags('LIMI', ChangeGRFParamLimits),
07597 AllowedSubtags('MASK', ChangeGRFParamMask),
07598 AllowedSubtags('VALU', ChangeGRFParamValueNames),
07599 AllowedSubtags('DFLT', ChangeGRFParamDefault),
07600 AllowedSubtags()
07601 };
07602
07609 static bool HandleParameterInfo(ByteReader *buf)
07610 {
07611 byte type = buf->ReadByte();
07612 while (type != 0) {
07613 uint32 id = buf->ReadDWord();
07614 if (type != 'C' || id >= _cur.grfconfig->num_valid_params) {
07615 grfmsg(2, "StaticGRFInfo: all child nodes of 'INFO'->'PARA' should have type 'C' and their parameter number as id");
07616 if (!SkipUnknownInfo(buf, type)) return false;
07617 type = buf->ReadByte();
07618 continue;
07619 }
07620
07621 if (id >= _cur.grfconfig->param_info.Length()) {
07622 uint num_to_add = id - _cur.grfconfig->param_info.Length() + 1;
07623 GRFParameterInfo **newdata = _cur.grfconfig->param_info.Append(num_to_add);
07624 MemSetT<GRFParameterInfo *>(newdata, 0, num_to_add);
07625 }
07626 if (_cur.grfconfig->param_info[id] == NULL) {
07627 _cur.grfconfig->param_info[id] = new GRFParameterInfo(id);
07628 }
07629 _cur_parameter = _cur.grfconfig->param_info[id];
07630
07631 if (!HandleNodes(buf, _tags_parameters)) return false;
07632 type = buf->ReadByte();
07633 }
07634 return true;
07635 }
07636
07638 AllowedSubtags _tags_info[] = {
07639 AllowedSubtags('NAME', ChangeGRFName),
07640 AllowedSubtags('DESC', ChangeGRFDescription),
07641 AllowedSubtags('URL_', ChangeGRFURL),
07642 AllowedSubtags('NPAR', ChangeGRFNumUsedParams),
07643 AllowedSubtags('PALS', ChangeGRFPalette),
07644 AllowedSubtags('BLTR', ChangeGRFBlitter),
07645 AllowedSubtags('VRSN', ChangeGRFVersion),
07646 AllowedSubtags('MINV', ChangeGRFMinVersion),
07647 AllowedSubtags('PARA', HandleParameterInfo),
07648 AllowedSubtags()
07649 };
07650
07652 AllowedSubtags _tags_root[] = {
07653 AllowedSubtags('INFO', _tags_info),
07654 AllowedSubtags()
07655 };
07656
07657
07664 static bool SkipUnknownInfo(ByteReader *buf, byte type)
07665 {
07666
07667 switch (type) {
07668 case 'C': {
07669 byte new_type = buf->ReadByte();
07670 while (new_type != 0) {
07671 buf->ReadDWord();
07672 if (!SkipUnknownInfo(buf, new_type)) return false;
07673 new_type = buf->ReadByte();
07674 }
07675 break;
07676 }
07677
07678 case 'T':
07679 buf->ReadByte();
07680 buf->ReadString();
07681 break;
07682
07683 case 'B': {
07684 uint16 size = buf->ReadWord();
07685 buf->Skip(size);
07686 break;
07687 }
07688
07689 default:
07690 return false;
07691 }
07692
07693 return true;
07694 }
07695
07704 static bool HandleNode(byte type, uint32 id, ByteReader *buf, AllowedSubtags subtags[])
07705 {
07706 uint i = 0;
07707 AllowedSubtags *tag;
07708 while ((tag = &subtags[i++])->type != 0) {
07709 if (tag->id != BSWAP32(id) || tag->type != type) continue;
07710 switch (type) {
07711 default: NOT_REACHED();
07712
07713 case 'T': {
07714 byte langid = buf->ReadByte();
07715 return tag->handler.text(langid, buf->ReadString());
07716 }
07717
07718 case 'B': {
07719 size_t len = buf->ReadWord();
07720 if (buf->Remaining() < len) return false;
07721 return tag->handler.data(len, buf);
07722 }
07723
07724 case 'C': {
07725 if (tag->handler.call_handler) {
07726 return tag->handler.u.branch(buf);
07727 }
07728 return HandleNodes(buf, tag->handler.u.subtags);
07729 }
07730 }
07731 }
07732 grfmsg(2, "StaticGRFInfo: unknown type/id combination found, type=%c, id=%x", type, id);
07733 return SkipUnknownInfo(buf, type);
07734 }
07735
07742 static bool HandleNodes(ByteReader *buf, AllowedSubtags subtags[])
07743 {
07744 byte type = buf->ReadByte();
07745 while (type != 0) {
07746 uint32 id = buf->ReadDWord();
07747 if (!HandleNode(type, id, buf, subtags)) return false;
07748 type = buf->ReadByte();
07749 }
07750 return true;
07751 }
07752
07757 static void StaticGRFInfo(ByteReader *buf)
07758 {
07759
07760 HandleNodes(buf, _tags_root);
07761 }
07762
07768 static void GRFUnsafe(ByteReader *buf)
07769 {
07770 SetBit(_cur.grfconfig->flags, GCF_UNSAFE);
07771
07772
07773 _cur.skip_sprites = -1;
07774 }
07775
07776
07778 static void InitializeGRFSpecial()
07779 {
07780 _ttdpatch_flags[0] = ((_settings_game.station.never_expire_airports ? 1 : 0) << 0x0C)
07781 | (1 << 0x0D)
07782 | (1 << 0x0E)
07783 | ((_settings_game.construction.max_bridge_length > 16 ? 1 : 0) << 0x0F)
07784 | (0 << 0x10)
07785 | (1 << 0x12)
07786 | (1 << 0x13)
07787 | ((_settings_game.vehicle.never_expire_vehicles ? 1 : 0) << 0x16)
07788 | (1 << 0x1B)
07789 | (1 << 0x1D)
07790 | (1 << 0x1E);
07791
07792 _ttdpatch_flags[1] = ((_settings_game.economy.station_noise_level ? 1 : 0) << 0x07)
07793 | (1 << 0x08)
07794 | (1 << 0x09)
07795 | (0 << 0x0B)
07796 | ((_settings_game.order.gradual_loading ? 1 : 0) << 0x0C)
07797 | (1 << 0x12)
07798 | (1 << 0x13)
07799 | (1 << 0x14)
07800 | (1 << 0x16)
07801 | (1 << 0x17)
07802 | (1 << 0x18)
07803 | (1 << 0x19)
07804 | (1 << 0x1A)
07805 | ((_settings_game.construction.train_signal_side == 1 ? 1 : 0) << 0x1B)
07806 | ((_settings_game.vehicle.disable_elrails ? 0 : 1) << 0x1C);
07807
07808 _ttdpatch_flags[2] = (1 << 0x01)
07809 | (1 << 0x03)
07810 | (1 << 0x0A)
07811 | (0 << 0x0B)
07812 | (0 << 0x0C)
07813 | ((_settings_game.construction.build_on_slopes ? 1 : 0) << 0x0D)
07814 | (1 << 0x0E)
07815 | (1 << 0x0F)
07816 | (0 << 0x10)
07817 | (0 << 0x11)
07818 | (1 << 0x12)
07819 | (1 << 0x13)
07820 | (1 << 0x14)
07821 | ((_settings_game.construction.build_on_slopes ? 1 : 0) << 0x15)
07822 | (1 << 0x16)
07823 | (1 << 0x17)
07824 | ((_settings_game.vehicle.freight_trains > 1 ? 1 : 0) << 0x18)
07825 | (1 << 0x19)
07826 | (1 << 0x1A)
07827 | (1 << 0x1B)
07828 | (1 << 0x1C)
07829 | ((_settings_game.vehicle.wagon_speed_limits ? 1 : 0) << 0x1D)
07830 | (1 << 0x1E)
07831 | (0 << 0x1F);
07832
07833 _ttdpatch_flags[3] = (0 << 0x00)
07834 | (1 << 0x01)
07835 | ((_settings_game.economy.allow_town_roads || _generating_world ? 0 : 1) << 0x02)
07836 | (1 << 0x03)
07837 | (0 << 0x04)
07838 | (1 << 0x05)
07839 | (1 << 0x06)
07840 | (1 << 0x07)
07841 | ((_settings_game.order.improved_load ? 1 : 0) << 0x08)
07842 | (0 << 0x09)
07843 | (0 << 0x0A)
07844 | (1 << 0x0B)
07845 | (1 << 0x0C)
07846 | (1 << 0x0D)
07847 | (1 << 0x0E)
07848 | (1 << 0x0F)
07849 | (1 << 0x10)
07850 | (1 << 0x11)
07851 | (1 << 0x12)
07852 | (0 << 0x13)
07853 | (1 << 0x14)
07854 | (0 << 0x15)
07855 | (1 << 0x16)
07856 | (1 << 0x17)
07857 | ((_settings_game.vehicle.dynamic_engines ? 1 : 0) << 0x18)
07858 | (1 << 0x1E)
07859 | (1 << 0x1F);
07860 }
07861
07863 static void ResetCustomStations()
07864 {
07865 const GRFFile * const *end = _grf_files.End();
07866 for (GRFFile **file = _grf_files.Begin(); file != end; file++) {
07867 StationSpec **&stations = (*file)->stations;
07868 if (stations == NULL) continue;
07869 for (uint i = 0; i < NUM_STATIONS_PER_GRF; i++) {
07870 if (stations[i] == NULL) continue;
07871 StationSpec *statspec = stations[i];
07872
07873 delete[] statspec->renderdata;
07874
07875
07876 if (!statspec->copied_layouts) {
07877 for (uint l = 0; l < statspec->lengths; l++) {
07878 for (uint p = 0; p < statspec->platforms[l]; p++) {
07879 free(statspec->layouts[l][p]);
07880 }
07881 free(statspec->layouts[l]);
07882 }
07883 free(statspec->layouts);
07884 free(statspec->platforms);
07885 }
07886
07887
07888 free(statspec);
07889 }
07890
07891
07892 free(stations);
07893 stations = NULL;
07894 }
07895 }
07896
07898 static void ResetCustomHouses()
07899 {
07900 const GRFFile * const *end = _grf_files.End();
07901 for (GRFFile **file = _grf_files.Begin(); file != end; file++) {
07902 HouseSpec **&housespec = (*file)->housespec;
07903 if (housespec == NULL) continue;
07904 for (uint i = 0; i < NUM_HOUSES_PER_GRF; i++) {
07905 free(housespec[i]);
07906 }
07907
07908 free(housespec);
07909 housespec = NULL;
07910 }
07911 }
07912
07914 static void ResetCustomAirports()
07915 {
07916 const GRFFile * const *end = _grf_files.End();
07917 for (GRFFile **file = _grf_files.Begin(); file != end; file++) {
07918 AirportSpec **aslist = (*file)->airportspec;
07919 if (aslist != NULL) {
07920 for (uint i = 0; i < NUM_AIRPORTS_PER_GRF; i++) {
07921 AirportSpec *as = aslist[i];
07922
07923 if (as != NULL) {
07924
07925 for (int j = 0; j < as->num_table; j++) {
07926
07927 free(as->table[j]);
07928 }
07929 free(as->table);
07930 free(as->depot_table);
07931
07932 free(as);
07933 }
07934 }
07935 free(aslist);
07936 (*file)->airportspec = NULL;
07937 }
07938
07939 AirportTileSpec **&airporttilespec = (*file)->airtspec;
07940 if (airporttilespec != NULL) {
07941 for (uint i = 0; i < NUM_AIRPORTTILES_PER_GRF; i++) {
07942 free(airporttilespec[i]);
07943 }
07944 free(airporttilespec);
07945 airporttilespec = NULL;
07946 }
07947 }
07948 }
07949
07951 static void ResetCustomIndustries()
07952 {
07953 const GRFFile * const *end = _grf_files.End();
07954 for (GRFFile **file = _grf_files.Begin(); file != end; file++) {
07955 IndustrySpec **&industryspec = (*file)->industryspec;
07956 IndustryTileSpec **&indtspec = (*file)->indtspec;
07957
07958
07959
07960 if (industryspec != NULL) {
07961 for (uint i = 0; i < NUM_INDUSTRYTYPES_PER_GRF; i++) {
07962 IndustrySpec *ind = industryspec[i];
07963 if (ind == NULL) continue;
07964
07965
07966 if (HasBit(ind->cleanup_flag, CLEAN_RANDOMSOUNDS)) {
07967 free(ind->random_sounds);
07968 }
07969
07970
07971 CleanIndustryTileTable(ind);
07972
07973 free(ind);
07974 }
07975
07976 free(industryspec);
07977 industryspec = NULL;
07978 }
07979
07980 if (indtspec == NULL) continue;
07981 for (uint i = 0; i < NUM_INDUSTRYTILES_PER_GRF; i++) {
07982 free(indtspec[i]);
07983 }
07984
07985 free(indtspec);
07986 indtspec = NULL;
07987 }
07988 }
07989
07991 static void ResetCustomObjects()
07992 {
07993 const GRFFile * const *end = _grf_files.End();
07994 for (GRFFile **file = _grf_files.Begin(); file != end; file++) {
07995 ObjectSpec **&objectspec = (*file)->objectspec;
07996 if (objectspec == NULL) continue;
07997 for (uint i = 0; i < NUM_OBJECTS_PER_GRF; i++) {
07998 free(objectspec[i]);
07999 }
08000
08001 free(objectspec);
08002 objectspec = NULL;
08003 }
08004 }
08005
08007 static void ResetNewGRF()
08008 {
08009 const GRFFile * const *end = _grf_files.End();
08010 for (GRFFile **file = _grf_files.Begin(); file != end; file++) {
08011 delete *file;
08012 }
08013
08014 _grf_files.Clear();
08015 _cur.grffile = NULL;
08016 }
08017
08019 static void ResetNewGRFErrors()
08020 {
08021 for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
08022 if (!HasBit(c->flags, GCF_COPY) && c->error != NULL) {
08023 delete c->error;
08024 c->error = NULL;
08025 }
08026 }
08027 }
08028
08033 void ResetNewGRFData()
08034 {
08035 CleanUpStrings();
08036 CleanUpGRFTownNames();
08037
08038
08039 SetupEngines();
08040
08041
08042 ResetBridges();
08043
08044
08045 ResetRailTypes();
08046
08047
08048 _gted = CallocT<GRFTempEngineData>(Engine::GetPoolSize());
08049
08050
08051 Engine *e;
08052 FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
08053 _gted[e->index].railtypelabel = GetRailTypeInfo(e->u.rail.railtype)->label;
08054 }
08055
08056
08057 memset(&_grm_engines, 0, sizeof(_grm_engines));
08058 memset(&_grm_cargoes, 0, sizeof(_grm_cargoes));
08059
08060
08061 ResetGenericCallbacks();
08062
08063
08064 ResetPriceBaseMultipliers();
08065
08066
08067 ResetCurrencies();
08068
08069
08070 ResetCustomHouses();
08071 ResetHouses();
08072
08073
08074 ResetCustomIndustries();
08075 ResetIndustries();
08076
08077
08078 ObjectClass::Reset();
08079 ResetCustomObjects();
08080 ResetObjects();
08081
08082
08083 StationClass::Reset();
08084 ResetCustomStations();
08085
08086
08087 AirportClass::Reset();
08088 ResetCustomAirports();
08089 AirportSpec::ResetAirports();
08090 AirportTileSpec::ResetAirportTiles();
08091
08092
08093 memset(_water_feature, 0, sizeof(_water_feature));
08094
08095
08096 ClearSnowLine();
08097
08098
08099 ResetNewGRF();
08100
08101
08102 ResetNewGRFErrors();
08103
08104
08105 SetupCargoForClimate(_settings_game.game_creation.landscape);
08106
08107
08108 _misc_grf_features = 0;
08109
08110 _loaded_newgrf_features.has_2CC = false;
08111 _loaded_newgrf_features.used_liveries = 1 << LS_DEFAULT;
08112 _loaded_newgrf_features.has_newhouses = false;
08113 _loaded_newgrf_features.has_newindustries = false;
08114 _loaded_newgrf_features.shore = SHORE_REPLACE_NONE;
08115
08116
08117 _grf_id_overrides.clear();
08118
08119 InitializeSoundPool();
08120 _spritegroup_pool.CleanPool();
08121 }
08122
08126 void ResetPersistentNewGRFData()
08127 {
08128
08129 _engine_mngr.ResetToDefaultMapping();
08130 _house_mngr.ResetMapping();
08131 _industry_mngr.ResetMapping();
08132 _industile_mngr.ResetMapping();
08133 _airport_mngr.ResetMapping();
08134 _airporttile_mngr.ResetMapping();
08135 }
08136
08141 static void BuildCargoTranslationMap()
08142 {
08143 memset(_cur.grffile->cargo_map, 0xFF, sizeof(_cur.grffile->cargo_map));
08144
08145 for (CargoID c = 0; c < NUM_CARGO; c++) {
08146 const CargoSpec *cs = CargoSpec::Get(c);
08147 if (!cs->IsValid()) continue;
08148
08149 if (_cur.grffile->cargo_list.Length() == 0) {
08150
08151 _cur.grffile->cargo_map[c] = cs->bitnum;
08152 } else {
08153
08154 int index = _cur.grffile->cargo_list.FindIndex(cs->label);
08155 if (index >= 0) _cur.grffile->cargo_map[c] = index;
08156 }
08157 }
08158 }
08159
08164 static void InitNewGRFFile(const GRFConfig *config)
08165 {
08166 GRFFile *newfile = GetFileByFilename(config->filename);
08167 if (newfile != NULL) {
08168
08169 _cur.grffile = newfile;
08170 return;
08171 }
08172
08173 newfile = new GRFFile(config);
08174 *_grf_files.Append() = _cur.grffile = newfile;
08175 }
08176
08181 GRFFile::GRFFile(const GRFConfig *config)
08182 {
08183 this->filename = strdup(config->filename);
08184 this->grfid = config->ident.grfid;
08185
08186
08187 this->traininfo_vehicle_pitch = 0;
08188 this->traininfo_vehicle_width = TRAININFO_DEFAULT_VEHICLE_WIDTH;
08189
08190
08191 for (Price i = PR_BEGIN; i < PR_END; i++) {
08192 this->price_base_multipliers[i] = INVALID_PRICE_MODIFIER;
08193 }
08194
08195
08196 memset(this->railtype_map, INVALID_RAILTYPE, sizeof(this->railtype_map));
08197 this->railtype_map[0] = RAILTYPE_RAIL;
08198 this->railtype_map[1] = RAILTYPE_ELECTRIC;
08199 this->railtype_map[2] = RAILTYPE_MONO;
08200 this->railtype_map[3] = RAILTYPE_MAGLEV;
08201
08202
08203
08204 assert_compile(lengthof(this->param) == lengthof(config->param) && lengthof(this->param) == 0x80);
08205
08206 assert(config->num_params <= lengthof(config->param));
08207 this->param_end = config->num_params;
08208 if (this->param_end > 0) {
08209 MemCpyT(this->param, config->param, this->param_end);
08210 }
08211 }
08212
08213 GRFFile::~GRFFile()
08214 {
08215 free(this->filename);
08216 delete[] this->language_map;
08217 }
08218
08219
08224 static const CargoLabel _default_refitmasks_rail[] = {
08225 'PASS', 'COAL', 'MAIL', 'LVST', 'GOOD', 'GRAI', 'WHEA', 'MAIZ', 'WOOD',
08226 'IORE', 'STEL', 'VALU', 'GOLD', 'DIAM', 'PAPR', 'FOOD', 'FRUT', 'CORE',
08227 'WATR', 'SUGR', 'TOYS', 'BATT', 'SWET', 'TOFF', 'COLA', 'CTCD', 'BUBL',
08228 'PLST', 'FZDR',
08229 0 };
08230
08231 static const CargoLabel _default_refitmasks_road[] = {
08232 0 };
08233
08234 static const CargoLabel _default_refitmasks_ships[] = {
08235 'COAL', 'MAIL', 'LVST', 'GOOD', 'GRAI', 'WHEA', 'MAIZ', 'WOOD', 'IORE',
08236 'STEL', 'VALU', 'GOLD', 'DIAM', 'PAPR', 'FOOD', 'FRUT', 'CORE', 'WATR',
08237 'RUBR', 'SUGR', 'TOYS', 'BATT', 'SWET', 'TOFF', 'COLA', 'CTCD', 'BUBL',
08238 'PLST', 'FZDR',
08239 0 };
08240
08241 static const CargoLabel _default_refitmasks_aircraft[] = {
08242 'PASS', 'MAIL', 'GOOD', 'VALU', 'GOLD', 'DIAM', 'FOOD', 'FRUT', 'SUGR',
08243 'TOYS', 'BATT', 'SWET', 'TOFF', 'COLA', 'CTCD', 'BUBL', 'PLST', 'FZDR',
08244 0 };
08245
08246 static const CargoLabel * const _default_refitmasks[] = {
08247 _default_refitmasks_rail,
08248 _default_refitmasks_road,
08249 _default_refitmasks_ships,
08250 _default_refitmasks_aircraft,
08251 };
08252
08253
08257 static void CalculateRefitMasks()
08258 {
08259 Engine *e;
08260
08261 FOR_ALL_ENGINES(e) {
08262 EngineID engine = e->index;
08263 EngineInfo *ei = &e->info;
08264 bool only_defaultcargo;
08265
08266
08267 if (_gted[engine].refittability != GRFTempEngineData::UNSET) {
08268 uint32 mask = 0;
08269 uint32 not_mask = 0;
08270 uint32 xor_mask = ei->refit_mask;
08271
08272
08273
08274 only_defaultcargo = _gted[engine].refittability == GRFTempEngineData::EMPTY;
08275
08276 if (_gted[engine].cargo_allowed != 0) {
08277
08278 const CargoSpec *cs;
08279 FOR_ALL_CARGOSPECS(cs) {
08280 if (_gted[engine].cargo_allowed & cs->classes) SetBit(mask, cs->Index());
08281 if (_gted[engine].cargo_disallowed & cs->classes) SetBit(not_mask, cs->Index());
08282 }
08283 }
08284
08285 ei->refit_mask = ((mask & ~not_mask) ^ xor_mask) & _cargo_mask;
08286
08287
08288 ei->refit_mask |= _gted[engine].ctt_include_mask;
08289 ei->refit_mask &= ~_gted[engine].ctt_exclude_mask;
08290 } else {
08291 uint32 xor_mask = 0;
08292
08293
08294 if (e->type != VEH_TRAIN || (e->u.rail.capacity != 0 && e->u.rail.railveh_type != RAILVEH_WAGON)) {
08295 const CargoLabel *cl = _default_refitmasks[e->type];
08296 for (uint i = 0;; i++) {
08297 if (cl[i] == 0) break;
08298
08299 CargoID cargo = GetCargoIDByLabel(cl[i]);
08300 if (cargo == CT_INVALID) continue;
08301
08302 SetBit(xor_mask, cargo);
08303 }
08304 }
08305
08306 ei->refit_mask = xor_mask & _cargo_mask;
08307
08308
08309 only_defaultcargo = (ei->refit_mask == 0);
08310 }
08311
08312
08313 if (!HasBit(_cargo_mask, ei->cargo_type)) ei->cargo_type = CT_INVALID;
08314
08315
08316
08317 if (!only_defaultcargo && (e->type != VEH_SHIP || e->u.ship.old_refittable) && ei->cargo_type != CT_INVALID && !HasBit(ei->refit_mask, ei->cargo_type)) {
08318 ei->cargo_type = CT_INVALID;
08319 }
08320
08321
08322
08323 if (ei->cargo_type == CT_INVALID && ei->refit_mask != 0) {
08324
08325 const uint8 *cargo_map_for_first_refittable = NULL;
08326 {
08327 const GRFFile *file = _gted[engine].defaultcargo_grf;
08328 if (file == NULL) file = e->GetGRF();
08329 if (file != NULL && file->grf_version >= 8 && file->cargo_list.Length() != 0) {
08330 cargo_map_for_first_refittable = file->cargo_map;
08331 }
08332 }
08333
08334 if (cargo_map_for_first_refittable != NULL) {
08335
08336 byte best_local_slot = 0xFF;
08337 CargoID cargo_type;
08338 FOR_EACH_SET_CARGO_ID(cargo_type, ei->refit_mask) {
08339 byte local_slot = cargo_map_for_first_refittable[cargo_type];
08340 if (local_slot < best_local_slot) {
08341 best_local_slot = local_slot;
08342 ei->cargo_type = cargo_type;
08343 }
08344 }
08345 }
08346
08347 if (ei->cargo_type == CT_INVALID) {
08348
08349 ei->cargo_type = (CargoID)FindFirstBit(ei->refit_mask);
08350 }
08351 }
08352 if (ei->cargo_type == CT_INVALID) ei->climates = 0;
08353
08354
08355 if (e->type == VEH_SHIP && !e->u.ship.old_refittable) {
08356 ei->refit_mask = 0;
08357 }
08358 }
08359 }
08360
08362 static void FinaliseCanals()
08363 {
08364 for (uint i = 0; i < CF_END; i++) {
08365 if (_water_feature[i].grffile != NULL) {
08366 _water_feature[i].callback_mask = _water_feature[i].grffile->canal_local_properties[i].callback_mask;
08367 _water_feature[i].flags = _water_feature[i].grffile->canal_local_properties[i].flags;
08368 }
08369 }
08370 }
08371
08373 static void FinaliseEngineArray()
08374 {
08375 Engine *e;
08376
08377 FOR_ALL_ENGINES(e) {
08378 if (e->GetGRF() == NULL) {
08379 const EngineIDMapping &eid = _engine_mngr[e->index];
08380 if (eid.grfid != INVALID_GRFID || eid.internal_id != eid.substitute_id) {
08381 e->info.string_id = STR_NEWGRF_INVALID_ENGINE;
08382 }
08383 }
08384
08385
08386
08387
08388 if (e->type == VEH_TRAIN && !_gted[e->index].prop27_set && e->GetGRF() != NULL && is_custom_sprite(e->u.rail.image_index)) {
08389 ClrBit(e->info.misc_flags, EF_RAIL_FLIPS);
08390 }
08391
08392
08393 if (e->type != VEH_TRAIN || e->u.rail.railveh_type != RAILVEH_WAGON) {
08394 LiveryScheme ls = GetEngineLiveryScheme(e->index, INVALID_ENGINE, NULL);
08395 SetBit(_loaded_newgrf_features.used_liveries, ls);
08396
08397
08398 if (e->type == VEH_TRAIN) {
08399 SetBit(_loaded_newgrf_features.used_liveries, LS_FREIGHT_WAGON);
08400 switch (ls) {
08401 case LS_STEAM:
08402 case LS_DIESEL:
08403 case LS_ELECTRIC:
08404 case LS_MONORAIL:
08405 case LS_MAGLEV:
08406 SetBit(_loaded_newgrf_features.used_liveries, LS_PASSENGER_WAGON_STEAM + ls - LS_STEAM);
08407 break;
08408
08409 case LS_DMU:
08410 case LS_EMU:
08411 SetBit(_loaded_newgrf_features.used_liveries, LS_PASSENGER_WAGON_DIESEL + ls - LS_DMU);
08412 break;
08413
08414 default: NOT_REACHED();
08415 }
08416 }
08417 }
08418 }
08419 }
08420
08422 static void FinaliseCargoArray()
08423 {
08424 for (CargoID c = 0; c < NUM_CARGO; c++) {
08425 CargoSpec *cs = CargoSpec::Get(c);
08426 if (!cs->IsValid()) {
08427 cs->name = cs->name_single = cs->units_volume = STR_NEWGRF_INVALID_CARGO;
08428 cs->quantifier = STR_NEWGRF_INVALID_CARGO_QUANTITY;
08429 cs->abbrev = STR_NEWGRF_INVALID_CARGO_ABBREV;
08430 }
08431 }
08432 }
08433
08445 static bool IsHouseSpecValid(HouseSpec *hs, const HouseSpec *next1, const HouseSpec *next2, const HouseSpec *next3, const char *filename)
08446 {
08447 if (((hs->building_flags & BUILDING_HAS_2_TILES) != 0 &&
08448 (next1 == NULL || !next1->enabled || (next1->building_flags & BUILDING_HAS_1_TILE) != 0)) ||
08449 ((hs->building_flags & BUILDING_HAS_4_TILES) != 0 &&
08450 (next2 == NULL || !next2->enabled || (next2->building_flags & BUILDING_HAS_1_TILE) != 0 ||
08451 next3 == NULL || !next3->enabled || (next3->building_flags & BUILDING_HAS_1_TILE) != 0))) {
08452 hs->enabled = false;
08453 if (filename != NULL) DEBUG(grf, 1, "FinaliseHouseArray: %s defines house %d as multitile, but no suitable tiles follow. Disabling house.", filename, hs->grf_prop.local_id);
08454 return false;
08455 }
08456
08457
08458
08459
08460 if (((hs->building_flags & BUILDING_HAS_2_TILES) != 0 && next1->population != 0) ||
08461 ((hs->building_flags & BUILDING_HAS_4_TILES) != 0 && (next2->population != 0 || next3->population != 0))) {
08462 hs->enabled = false;
08463 if (filename != NULL) DEBUG(grf, 1, "FinaliseHouseArray: %s defines multitile house %d with non-zero population on additional tiles. Disabling house.", filename, hs->grf_prop.local_id);
08464 return false;
08465 }
08466
08467
08468
08469 if (filename != NULL && (hs->building_flags & BUILDING_HAS_1_TILE) != (HouseSpec::Get(hs->grf_prop.subst_id)->building_flags & BUILDING_HAS_1_TILE)) {
08470 hs->enabled = false;
08471 DEBUG(grf, 1, "FinaliseHouseArray: %s defines house %d with different house size then it's substitute type. Disabling house.", filename, hs->grf_prop.local_id);
08472 return false;
08473 }
08474
08475
08476 if ((hs->building_flags & BUILDING_HAS_1_TILE) == 0 && (hs->building_availability & HZ_ZONALL) != 0 && (hs->building_availability & HZ_CLIMALL) != 0) {
08477 hs->enabled = false;
08478 if (filename != NULL) DEBUG(grf, 1, "FinaliseHouseArray: %s defines house %d without a size but marked it as available. Disabling house.", filename, hs->grf_prop.local_id);
08479 return false;
08480 }
08481
08482 return true;
08483 }
08484
08491 static void EnsureEarlyHouse(HouseZones bitmask)
08492 {
08493 Year min_year = MAX_YEAR;
08494
08495 for (int i = 0; i < NUM_HOUSES; i++) {
08496 HouseSpec *hs = HouseSpec::Get(i);
08497 if (hs == NULL || !hs->enabled) continue;
08498 if ((hs->building_availability & bitmask) != bitmask) continue;
08499 if (hs->min_year < min_year) min_year = hs->min_year;
08500 }
08501
08502 if (min_year == 0) return;
08503
08504 for (int i = 0; i < NUM_HOUSES; i++) {
08505 HouseSpec *hs = HouseSpec::Get(i);
08506 if (hs == NULL || !hs->enabled) continue;
08507 if ((hs->building_availability & bitmask) != bitmask) continue;
08508 if (hs->min_year == min_year) hs->min_year = 0;
08509 }
08510 }
08511
08518 static void FinaliseHouseArray()
08519 {
08520
08521
08522
08523
08524
08525
08526
08527
08528
08529 const GRFFile * const *end = _grf_files.End();
08530 for (GRFFile **file = _grf_files.Begin(); file != end; file++) {
08531 HouseSpec **&housespec = (*file)->housespec;
08532 if (housespec == NULL) continue;
08533
08534 for (int i = 0; i < NUM_HOUSES_PER_GRF; i++) {
08535 HouseSpec *hs = housespec[i];
08536
08537 if (hs == NULL) continue;
08538
08539 const HouseSpec *next1 = (i + 1 < NUM_HOUSES_PER_GRF ? housespec[i + 1] : NULL);
08540 const HouseSpec *next2 = (i + 2 < NUM_HOUSES_PER_GRF ? housespec[i + 2] : NULL);
08541 const HouseSpec *next3 = (i + 3 < NUM_HOUSES_PER_GRF ? housespec[i + 3] : NULL);
08542
08543 if (!IsHouseSpecValid(hs, next1, next2, next3, (*file)->filename)) continue;
08544
08545 _house_mngr.SetEntitySpec(hs);
08546 }
08547 }
08548
08549 for (int i = 0; i < NUM_HOUSES; i++) {
08550 HouseSpec *hs = HouseSpec::Get(i);
08551 const HouseSpec *next1 = (i + 1 < NUM_HOUSES ? HouseSpec::Get(i + 1) : NULL);
08552 const HouseSpec *next2 = (i + 2 < NUM_HOUSES ? HouseSpec::Get(i + 2) : NULL);
08553 const HouseSpec *next3 = (i + 3 < NUM_HOUSES ? HouseSpec::Get(i + 3) : NULL);
08554
08555
08556
08557 if (!IsHouseSpecValid(hs, next1, next2, next3, NULL)) {
08558
08559
08560
08561
08562
08563
08564
08565 hs->building_flags = TILE_NO_FLAG;
08566 }
08567 }
08568
08569 HouseZones climate_mask = (HouseZones)(1 << (_settings_game.game_creation.landscape + 12));
08570 EnsureEarlyHouse(HZ_ZON1 | climate_mask);
08571 EnsureEarlyHouse(HZ_ZON2 | climate_mask);
08572 EnsureEarlyHouse(HZ_ZON3 | climate_mask);
08573 EnsureEarlyHouse(HZ_ZON4 | climate_mask);
08574 EnsureEarlyHouse(HZ_ZON5 | climate_mask);
08575
08576 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
08577 EnsureEarlyHouse(HZ_ZON1 | HZ_SUBARTC_ABOVE);
08578 EnsureEarlyHouse(HZ_ZON2 | HZ_SUBARTC_ABOVE);
08579 EnsureEarlyHouse(HZ_ZON3 | HZ_SUBARTC_ABOVE);
08580 EnsureEarlyHouse(HZ_ZON4 | HZ_SUBARTC_ABOVE);
08581 EnsureEarlyHouse(HZ_ZON5 | HZ_SUBARTC_ABOVE);
08582 }
08583 }
08584
08590 static void FinaliseIndustriesArray()
08591 {
08592 const GRFFile * const *end = _grf_files.End();
08593 for (GRFFile **file = _grf_files.Begin(); file != end; file++) {
08594 IndustrySpec **&industryspec = (*file)->industryspec;
08595 IndustryTileSpec **&indtspec = (*file)->indtspec;
08596 if (industryspec != NULL) {
08597 for (int i = 0; i < NUM_INDUSTRYTYPES_PER_GRF; i++) {
08598 IndustrySpec *indsp = industryspec[i];
08599
08600 if (indsp != NULL && indsp->enabled) {
08601 StringID strid;
08602
08603
08604
08605 strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->name);
08606 if (strid != STR_UNDEFINED) indsp->name = strid;
08607
08608 strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->closure_text);
08609 if (strid != STR_UNDEFINED) indsp->closure_text = strid;
08610
08611 strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->production_up_text);
08612 if (strid != STR_UNDEFINED) indsp->production_up_text = strid;
08613
08614 strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->production_down_text);
08615 if (strid != STR_UNDEFINED) indsp->production_down_text = strid;
08616
08617 strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->new_industry_text);
08618 if (strid != STR_UNDEFINED) indsp->new_industry_text = strid;
08619
08620 if (indsp->station_name != STR_NULL) {
08621
08622
08623 strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->station_name);
08624 if (strid != STR_UNDEFINED) indsp->station_name = strid;
08625 }
08626
08627 _industry_mngr.SetEntitySpec(indsp);
08628 _loaded_newgrf_features.has_newindustries = true;
08629 }
08630 }
08631 }
08632
08633 if (indtspec != NULL) {
08634 for (int i = 0; i < NUM_INDUSTRYTILES_PER_GRF; i++) {
08635 IndustryTileSpec *indtsp = indtspec[i];
08636 if (indtsp != NULL) {
08637 _industile_mngr.SetEntitySpec(indtsp);
08638 }
08639 }
08640 }
08641 }
08642
08643 for (uint j = 0; j < NUM_INDUSTRYTYPES; j++) {
08644 IndustrySpec *indsp = &_industry_specs[j];
08645 if (indsp->enabled && indsp->grf_prop.grffile != NULL) {
08646 for (uint i = 0; i < 3; i++) {
08647 indsp->conflicting[i] = MapNewGRFIndustryType(indsp->conflicting[i], indsp->grf_prop.grffile->grfid);
08648 }
08649 }
08650 if (!indsp->enabled) {
08651 indsp->name = STR_NEWGRF_INVALID_INDUSTRYTYPE;
08652 }
08653 }
08654 }
08655
08661 static void FinaliseObjectsArray()
08662 {
08663 const GRFFile * const *end = _grf_files.End();
08664 for (GRFFile **file = _grf_files.Begin(); file != end; file++) {
08665 ObjectSpec **&objectspec = (*file)->objectspec;
08666 if (objectspec != NULL) {
08667 for (int i = 0; i < NUM_OBJECTS_PER_GRF; i++) {
08668 if (objectspec[i] != NULL && objectspec[i]->grf_prop.grffile != NULL && objectspec[i]->enabled) {
08669 _object_mngr.SetEntitySpec(objectspec[i]);
08670 }
08671 }
08672 }
08673 }
08674 }
08675
08681 static void FinaliseAirportsArray()
08682 {
08683 const GRFFile * const *end = _grf_files.End();
08684 for (GRFFile **file = _grf_files.Begin(); file != end; file++) {
08685 AirportSpec **&airportspec = (*file)->airportspec;
08686 if (airportspec != NULL) {
08687 for (int i = 0; i < NUM_AIRPORTS_PER_GRF; i++) {
08688 if (airportspec[i] != NULL && airportspec[i]->enabled) {
08689 _airport_mngr.SetEntitySpec(airportspec[i]);
08690 }
08691 }
08692 }
08693
08694 AirportTileSpec **&airporttilespec = (*file)->airtspec;
08695 if (airporttilespec != NULL) {
08696 for (uint i = 0; i < NUM_AIRPORTTILES_PER_GRF; i++) {
08697 if (airporttilespec[i] != NULL && airporttilespec[i]->enabled) {
08698 _airporttile_mngr.SetEntitySpec(airporttilespec[i]);
08699 }
08700 }
08701 }
08702 }
08703 }
08704
08705
08706
08707
08708
08709
08710
08711 static void DecodeSpecialSprite(byte *buf, uint num, GrfLoadingStage stage)
08712 {
08713
08714
08715
08716
08717
08718
08719
08720
08721
08722
08723
08724
08725 static const SpecialSpriteHandler handlers[][GLS_END] = {
08726 { NULL, SafeChangeInfo, NULL, NULL, ReserveChangeInfo, FeatureChangeInfo, },
08727 { SkipAct1, SkipAct1, SkipAct1, SkipAct1, SkipAct1, NewSpriteSet, },
08728 { NULL, NULL, NULL, NULL, NULL, NewSpriteGroup, },
08729 { NULL, GRFUnsafe, NULL, NULL, NULL, FeatureMapSpriteGroup, },
08730 { NULL, NULL, NULL, NULL, NULL, FeatureNewName, },
08731 { SkipAct5, SkipAct5, SkipAct5, SkipAct5, SkipAct5, GraphicsNew, },
08732 { NULL, NULL, NULL, CfgApply, CfgApply, CfgApply, },
08733 { NULL, NULL, NULL, NULL, SkipIf, SkipIf, },
08734 { ScanInfo, NULL, NULL, GRFInfo, GRFInfo, GRFInfo, },
08735 { NULL, NULL, NULL, SkipIf, SkipIf, SkipIf, },
08736 { SkipActA, SkipActA, SkipActA, SkipActA, SkipActA, SpriteReplace, },
08737 { NULL, NULL, NULL, GRFLoadError, GRFLoadError, GRFLoadError, },
08738 { NULL, NULL, NULL, GRFComment, NULL, GRFComment, },
08739 { NULL, SafeParamSet, NULL, ParamSet, ParamSet, ParamSet, },
08740 { NULL, SafeGRFInhibit, NULL, GRFInhibit, GRFInhibit, GRFInhibit, },
08741 { NULL, GRFUnsafe, NULL, FeatureTownName, NULL, NULL, },
08742 { NULL, NULL, DefineGotoLabel, NULL, NULL, NULL, },
08743 { SkipAct11,GRFUnsafe, SkipAct11, GRFSound, SkipAct11, GRFSound, },
08744 { SkipAct12, SkipAct12, SkipAct12, SkipAct12, SkipAct12, LoadFontGlyph, },
08745 { NULL, NULL, NULL, NULL, NULL, TranslateGRFStrings, },
08746 { StaticGRFInfo, NULL, NULL, NULL, NULL, NULL, },
08747 };
08748
08749 GRFLocation location(_cur.grfconfig->ident.grfid, _cur.nfo_line);
08750
08751 GRFLineToSpriteOverride::iterator it = _grf_line_to_action6_sprite_override.find(location);
08752 if (it == _grf_line_to_action6_sprite_override.end()) {
08753
08754
08755 FioReadBlock(buf, num);
08756 } else {
08757
08758 buf = _grf_line_to_action6_sprite_override[location];
08759 grfmsg(7, "DecodeSpecialSprite: Using preloaded pseudo sprite data");
08760
08761
08762 FioSeekTo(num, SEEK_CUR);
08763 }
08764
08765 ByteReader br(buf, buf + num);
08766 ByteReader *bufp = &br;
08767
08768 try {
08769 byte action = bufp->ReadByte();
08770
08771 if (action == 0xFF) {
08772 grfmsg(2, "DecodeSpecialSprite: Unexpected data block, skipping");
08773 } else if (action == 0xFE) {
08774 grfmsg(2, "DecodeSpecialSprite: Unexpected import block, skipping");
08775 } else if (action >= lengthof(handlers)) {
08776 grfmsg(7, "DecodeSpecialSprite: Skipping unknown action 0x%02X", action);
08777 } else if (handlers[action][stage] == NULL) {
08778 grfmsg(7, "DecodeSpecialSprite: Skipping action 0x%02X in stage %d", action, stage);
08779 } else {
08780 grfmsg(7, "DecodeSpecialSprite: Handling action 0x%02X in stage %d", action, stage);
08781 handlers[action][stage](bufp);
08782 }
08783 } catch (...) {
08784 grfmsg(1, "DecodeSpecialSprite: Tried to read past end of pseudo-sprite data");
08785 DisableGrf(STR_NEWGRF_ERROR_READ_BOUNDS);
08786 }
08787 }
08788
08789
08791 extern const byte _grf_cont_v2_sig[8] = {'G', 'R', 'F', 0x82, 0x0D, 0x0A, 0x1A, 0x0A};
08792
08797 byte GetGRFContainerVersion()
08798 {
08799 size_t pos = FioGetPos();
08800
08801 if (FioReadWord() == 0) {
08802
08803
08804 for (uint i = 0; i < lengthof(_grf_cont_v2_sig); i++) {
08805 if (FioReadByte() != _grf_cont_v2_sig[i]) return 0;
08806 }
08807
08808 return 2;
08809 }
08810
08811
08812 FioSeekTo(pos, SEEK_SET);
08813 return 1;
08814 }
08815
08823 void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage, Subdirectory subdir)
08824 {
08825 const char *filename = config->filename;
08826
08827
08828
08829
08830
08831
08832
08833
08834
08835
08836 if (stage != GLS_FILESCAN && stage != GLS_SAFETYSCAN && stage != GLS_LABELSCAN) {
08837 _cur.grffile = GetFileByFilename(filename);
08838 if (_cur.grffile == NULL) usererror("File '%s' lost in cache.\n", filename);
08839 if (stage == GLS_RESERVE && config->status != GCS_INITIALISED) return;
08840 if (stage == GLS_ACTIVATION && !HasBit(config->flags, GCF_RESERVED)) return;
08841 _cur.grffile->is_ottdfile = config->IsOpenTTDBaseGRF();
08842 }
08843
08844 if (file_index > LAST_GRF_SLOT) {
08845 DEBUG(grf, 0, "'%s' is not loaded as the maximum number of GRFs has been reached", filename);
08846 config->status = GCS_DISABLED;
08847 config->error = new GRFError(STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED);
08848 return;
08849 }
08850
08851 FioOpenFile(file_index, filename, subdir);
08852 _cur.file_index = file_index;
08853 _palette_remap_grf[_cur.file_index] = (config->palette & GRFP_USE_MASK);
08854
08855 _cur.grfconfig = config;
08856
08857 DEBUG(grf, 2, "LoadNewGRFFile: Reading NewGRF-file '%s'", filename);
08858
08859 _cur.grf_container_ver = GetGRFContainerVersion();
08860 if (_cur.grf_container_ver == 0) {
08861 DEBUG(grf, 7, "LoadNewGRFFile: Custom .grf has invalid format");
08862 return;
08863 }
08864
08865 if (stage == GLS_INIT || stage == GLS_ACTIVATION) {
08866
08867
08868 ReadGRFSpriteOffsets(_cur.grf_container_ver);
08869 } else {
08870
08871 if (_cur.grf_container_ver >= 2) FioReadDword();
08872 }
08873
08874 if (_cur.grf_container_ver >= 2) {
08875
08876 byte compression = FioReadByte();
08877 if (compression != 0) {
08878 DEBUG(grf, 7, "LoadNewGRFFile: Unsupported compression format");
08879 return;
08880 }
08881 }
08882
08883
08884
08885
08886 uint32 num = _cur.grf_container_ver >= 2 ? FioReadDword() : FioReadWord();
08887 if (num == 4 && FioReadByte() == 0xFF) {
08888 FioReadDword();
08889 } else {
08890 DEBUG(grf, 7, "LoadNewGRFFile: Custom .grf has invalid format");
08891 return;
08892 }
08893
08894 _cur.ClearDataForNextFile();
08895
08896 ReusableBuffer<byte> buf;
08897
08898 while ((num = (_cur.grf_container_ver >= 2 ? FioReadDword() : FioReadWord())) != 0) {
08899 byte type = FioReadByte();
08900 _cur.nfo_line++;
08901
08902 if (type == 0xFF) {
08903 if (_cur.skip_sprites == 0) {
08904 DecodeSpecialSprite(buf.Allocate(num), num, stage);
08905
08906
08907 if (_cur.skip_sprites == -1) break;
08908
08909 continue;
08910 } else {
08911 FioSkipBytes(num);
08912 }
08913 } else {
08914 if (_cur.skip_sprites == 0) {
08915 grfmsg(0, "LoadNewGRFFile: Unexpected sprite, disabling");
08916 DisableGrf(STR_NEWGRF_ERROR_UNEXPECTED_SPRITE);
08917 break;
08918 }
08919
08920 if (_cur.grf_container_ver >= 2 && type == 0xFD) {
08921
08922 FioSkipBytes(num);
08923 } else {
08924 FioSkipBytes(7);
08925 SkipSpriteData(type, num - 8);
08926 }
08927 }
08928
08929 if (_cur.skip_sprites > 0) _cur.skip_sprites--;
08930 }
08931 }
08932
08940 static void ActivateOldShore()
08941 {
08942
08943
08944 if (_loaded_newgrf_features.shore == SHORE_REPLACE_NONE) _loaded_newgrf_features.shore = SHORE_REPLACE_ACTION_A;
08945
08946 if (_loaded_newgrf_features.shore != SHORE_REPLACE_ACTION_5) {
08947 DupSprite(SPR_ORIGINALSHORE_START + 1, SPR_SHORE_BASE + 1);
08948 DupSprite(SPR_ORIGINALSHORE_START + 2, SPR_SHORE_BASE + 2);
08949 DupSprite(SPR_ORIGINALSHORE_START + 6, SPR_SHORE_BASE + 3);
08950 DupSprite(SPR_ORIGINALSHORE_START + 0, SPR_SHORE_BASE + 4);
08951 DupSprite(SPR_ORIGINALSHORE_START + 4, SPR_SHORE_BASE + 6);
08952 DupSprite(SPR_ORIGINALSHORE_START + 3, SPR_SHORE_BASE + 8);
08953 DupSprite(SPR_ORIGINALSHORE_START + 7, SPR_SHORE_BASE + 9);
08954 DupSprite(SPR_ORIGINALSHORE_START + 5, SPR_SHORE_BASE + 12);
08955 }
08956
08957 if (_loaded_newgrf_features.shore == SHORE_REPLACE_ACTION_A) {
08958 DupSprite(SPR_FLAT_GRASS_TILE + 16, SPR_SHORE_BASE + 0);
08959 DupSprite(SPR_FLAT_GRASS_TILE + 17, SPR_SHORE_BASE + 5);
08960 DupSprite(SPR_FLAT_GRASS_TILE + 7, SPR_SHORE_BASE + 7);
08961 DupSprite(SPR_FLAT_GRASS_TILE + 15, SPR_SHORE_BASE + 10);
08962 DupSprite(SPR_FLAT_GRASS_TILE + 11, SPR_SHORE_BASE + 11);
08963 DupSprite(SPR_FLAT_GRASS_TILE + 13, SPR_SHORE_BASE + 13);
08964 DupSprite(SPR_FLAT_GRASS_TILE + 14, SPR_SHORE_BASE + 14);
08965 DupSprite(SPR_FLAT_GRASS_TILE + 18, SPR_SHORE_BASE + 15);
08966
08967
08968
08969 DupSprite(SPR_FLAT_GRASS_TILE + 5, SPR_SHORE_BASE + 16);
08970 DupSprite(SPR_FLAT_GRASS_TILE + 10, SPR_SHORE_BASE + 17);
08971 }
08972 }
08973
08977 static void FinalisePriceBaseMultipliers()
08978 {
08979 extern const PriceBaseSpec _price_base_specs[];
08981 static const uint32 override_features = (1 << GSF_TRAINS) | (1 << GSF_ROADVEHICLES) | (1 << GSF_SHIPS) | (1 << GSF_AIRCRAFT);
08982
08983
08984 int num_grfs = _grf_files.Length();
08985 int *grf_overrides = AllocaM(int, num_grfs);
08986 for (int i = 0; i < num_grfs; i++) {
08987 grf_overrides[i] = -1;
08988
08989 GRFFile *source = _grf_files[i];
08990 uint32 override = _grf_id_overrides[source->grfid];
08991 if (override == 0) continue;
08992
08993 GRFFile *dest = GetFileByGRFID(override);
08994 if (dest == NULL) continue;
08995
08996 grf_overrides[i] = _grf_files.FindIndex(dest);
08997 assert(grf_overrides[i] >= 0);
08998 }
08999
09000
09001 for (int i = 0; i < num_grfs; i++) {
09002 if (grf_overrides[i] < 0 || grf_overrides[i] >= i) continue;
09003 GRFFile *source = _grf_files[i];
09004 GRFFile *dest = _grf_files[grf_overrides[i]];
09005
09006 uint32 features = (source->grf_features | dest->grf_features) & override_features;
09007 source->grf_features |= features;
09008 dest->grf_features |= features;
09009
09010 for (Price p = PR_BEGIN; p < PR_END; p++) {
09011
09012 if (!HasBit(features, _price_base_specs[p].grf_feature) || source->price_base_multipliers[p] == INVALID_PRICE_MODIFIER) continue;
09013 DEBUG(grf, 3, "'%s' overrides price base multiplier %d of '%s'", source->filename, p, dest->filename);
09014 dest->price_base_multipliers[p] = source->price_base_multipliers[p];
09015 }
09016 }
09017
09018
09019 for (int i = num_grfs - 1; i >= 0; i--) {
09020 if (grf_overrides[i] < 0 || grf_overrides[i] <= i) continue;
09021 GRFFile *source = _grf_files[i];
09022 GRFFile *dest = _grf_files[grf_overrides[i]];
09023
09024 uint32 features = (source->grf_features | dest->grf_features) & override_features;
09025 source->grf_features |= features;
09026 dest->grf_features |= features;
09027
09028 for (Price p = PR_BEGIN; p < PR_END; p++) {
09029
09030 if (!HasBit(features, _price_base_specs[p].grf_feature) || dest->price_base_multipliers[p] != INVALID_PRICE_MODIFIER) continue;
09031 DEBUG(grf, 3, "Price base multiplier %d from '%s' propagated to '%s'", p, source->filename, dest->filename);
09032 dest->price_base_multipliers[p] = source->price_base_multipliers[p];
09033 }
09034 }
09035
09036
09037 for (int i = 0; i < num_grfs; i++) {
09038 if (grf_overrides[i] < 0) continue;
09039 GRFFile *source = _grf_files[i];
09040 GRFFile *dest = _grf_files[grf_overrides[i]];
09041
09042 uint32 features = (source->grf_features | dest->grf_features) & override_features;
09043 source->grf_features |= features;
09044 dest->grf_features |= features;
09045
09046 for (Price p = PR_BEGIN; p < PR_END; p++) {
09047 if (!HasBit(features, _price_base_specs[p].grf_feature)) continue;
09048 if (source->price_base_multipliers[p] != dest->price_base_multipliers[p]) {
09049 DEBUG(grf, 3, "Price base multiplier %d from '%s' propagated to '%s'", p, dest->filename, source->filename);
09050 }
09051 source->price_base_multipliers[p] = dest->price_base_multipliers[p];
09052 }
09053 }
09054
09055
09056 const GRFFile * const *end = _grf_files.End();
09057 for (GRFFile **file = _grf_files.Begin(); file != end; file++) {
09058 if ((*file)->grf_version >= 8) continue;
09059 PriceMultipliers &price_base_multipliers = (*file)->price_base_multipliers;
09060 for (Price p = PR_BEGIN; p < PR_END; p++) {
09061 Price fallback_price = _price_base_specs[p].fallback_price;
09062 if (fallback_price != INVALID_PRICE && price_base_multipliers[p] == INVALID_PRICE_MODIFIER) {
09063
09064
09065 price_base_multipliers[p] = price_base_multipliers[fallback_price];
09066 }
09067 }
09068 }
09069
09070
09071 for (GRFFile **file = _grf_files.Begin(); file != end; file++) {
09072 PriceMultipliers &price_base_multipliers = (*file)->price_base_multipliers;
09073 for (Price p = PR_BEGIN; p < PR_END; p++) {
09074 if (price_base_multipliers[p] == INVALID_PRICE_MODIFIER) {
09075
09076 price_base_multipliers[p] = 0;
09077 } else {
09078 if (!HasBit((*file)->grf_features, _price_base_specs[p].grf_feature)) {
09079
09080
09081 DEBUG(grf, 3, "'%s' sets global price base multiplier %d", (*file)->filename, p);
09082 SetPriceBaseMultiplier(p, price_base_multipliers[p]);
09083 price_base_multipliers[p] = 0;
09084 } else {
09085 DEBUG(grf, 3, "'%s' sets local price base multiplier %d", (*file)->filename, p);
09086 }
09087 }
09088 }
09089 }
09090 }
09091
09092 void InitDepotWindowBlockSizes();
09093
09094 extern void InitGRFTownGeneratorNames();
09095
09097 static void AfterLoadGRFs()
09098 {
09099 for (StringIDMapping *it = _string_to_grf_mapping.Begin(); it != _string_to_grf_mapping.End(); it++) {
09100 *it->target = MapGRFStringID(it->grfid, it->source);
09101 }
09102 _string_to_grf_mapping.Clear();
09103
09104
09105 for (GRFLineToSpriteOverride::iterator it = _grf_line_to_action6_sprite_override.begin(); it != _grf_line_to_action6_sprite_override.end(); it++) {
09106 free((*it).second);
09107 }
09108 _grf_line_to_action6_sprite_override.clear();
09109
09110
09111 FinaliseCargoArray();
09112
09113
09114 CalculateRefitMasks();
09115
09116
09117 FinaliseEngineArray();
09118
09119
09120 FinaliseCanals();
09121
09122
09123 InitDepotWindowBlockSizes();
09124
09125
09126 FinaliseHouseArray();
09127
09128
09129 FinaliseIndustriesArray();
09130
09131
09132 FinaliseObjectsArray();
09133
09134 InitializeSortedCargoSpecs();
09135
09136
09137 SortIndustryTypes();
09138
09139
09140 BuildIndustriesLegend();
09141
09142
09143 BuildLinkStatsLegend();
09144
09145
09146 FinaliseAirportsArray();
09147 BindAirportSpecs();
09148
09149
09150 InitGRFTownGeneratorNames();
09151
09152
09153 CommitVehicleListOrderChanges();
09154
09155
09156 ActivateOldShore();
09157
09158
09159 InitRailTypes();
09160
09161 Engine *e;
09162 FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
09163 if (_gted[e->index].rv_max_speed != 0) {
09164
09165 e->u.road.max_speed = _gted[e->index].rv_max_speed * 4;
09166 }
09167 }
09168
09169 FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
09170 RailType railtype = GetRailTypeByLabel(_gted[e->index].railtypelabel);
09171 if (railtype == INVALID_RAILTYPE) {
09172
09173 e->info.climates = 0;
09174 } else {
09175 e->u.rail.railtype = railtype;
09176 }
09177 }
09178
09179 SetYearEngineAgingStops();
09180
09181 FinalisePriceBaseMultipliers();
09182
09183
09184 free(_gted);
09185 _grm_sprites.clear();
09186 }
09187
09193 void LoadNewGRF(uint load_index, uint file_index)
09194 {
09195
09196
09197
09198
09199 Date date = _date;
09200 Year year = _cur_year;
09201 DateFract date_fract = _date_fract;
09202 uint16 tick_counter = _tick_counter;
09203 byte display_opt = _display_opt;
09204
09205 if (_networking) {
09206 _cur_year = _settings_game.game_creation.starting_year;
09207 _date = ConvertYMDToDate(_cur_year, 0, 1);
09208 _date_fract = 0;
09209 _tick_counter = 0;
09210 _display_opt = 0;
09211 }
09212
09213 InitializeGRFSpecial();
09214
09215 ResetNewGRFData();
09216
09217
09218
09219
09220
09221
09222
09223
09224 for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
09225 if (c->status != GCS_NOT_FOUND) c->status = GCS_UNKNOWN;
09226 }
09227
09228 _cur.spriteid = load_index;
09229
09230
09231
09232
09233 for (GrfLoadingStage stage = GLS_LABELSCAN; stage <= GLS_ACTIVATION; stage++) {
09234
09235
09236 for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
09237 if (c->status == GCS_ACTIVATED) c->status = GCS_INITIALISED;
09238 }
09239
09240 if (stage == GLS_RESERVE) {
09241 static const uint32 overrides[][2] = {
09242 { 0x44442202, 0x44440111 },
09243 { 0x6D620402, 0x6D620401 },
09244 { 0x4D656f20, 0x4D656F17 },
09245 };
09246 for (size_t i = 0; i < lengthof(overrides); i++) {
09247 SetNewGRFOverride(BSWAP32(overrides[i][0]), BSWAP32(overrides[i][1]));
09248 }
09249 }
09250
09251 uint slot = file_index;
09252
09253 _cur.stage = stage;
09254 for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
09255 if (c->status == GCS_DISABLED || c->status == GCS_NOT_FOUND) continue;
09256 if (stage > GLS_INIT && HasBit(c->flags, GCF_INIT_ONLY)) continue;
09257
09258 Subdirectory subdir = slot == file_index ? BASESET_DIR : NEWGRF_DIR;
09259 if (!FioCheckFileExists(c->filename, subdir)) {
09260 DEBUG(grf, 0, "NewGRF file is missing '%s'; disabling", c->filename);
09261 c->status = GCS_NOT_FOUND;
09262 continue;
09263 }
09264
09265 if (stage == GLS_LABELSCAN) InitNewGRFFile(c);
09266 LoadNewGRFFile(c, slot++, stage, subdir);
09267 if (stage == GLS_RESERVE) {
09268 SetBit(c->flags, GCF_RESERVED);
09269 } else if (stage == GLS_ACTIVATION) {
09270 ClrBit(c->flags, GCF_RESERVED);
09271 assert(GetFileByGRFID(c->ident.grfid) == _cur.grffile);
09272 ClearTemporaryNewGRFData(_cur.grffile);
09273 BuildCargoTranslationMap();
09274 DEBUG(sprite, 2, "LoadNewGRF: Currently %i sprites are loaded", _cur.spriteid);
09275 } else if (stage == GLS_INIT && HasBit(c->flags, GCF_INIT_ONLY)) {
09276
09277 ClearTemporaryNewGRFData(_cur.grffile);
09278 }
09279 }
09280 }
09281
09282
09283 _cur.ClearDataForNextFile();
09284
09285
09286 AfterLoadGRFs();
09287
09288
09289 _cur_year = year;
09290 _date = date;
09291 _date_fract = date_fract;
09292 _tick_counter = tick_counter;
09293 _display_opt = display_opt;
09294 }