00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "debug.h"
00014 #include "3rdparty/md5/md5.h"
00015 #include "newgrf.h"
00016 #include "gamelog.h"
00017 #include "network/network_func.h"
00018 #include "gfx_func.h"
00019
00020 #include "fileio_func.h"
00021 #include "fios.h"
00022
00023
00024 GRFConfig *_all_grfs;
00025 GRFConfig *_grfconfig;
00026 GRFConfig *_grfconfig_newgame;
00027 GRFConfig *_grfconfig_static;
00028
00029
00038 void UpdateNewGRFConfigPalette()
00039 {
00040 for (GRFConfig *c = _grfconfig_newgame; c != NULL; c = c->next) c->windows_paletted = (_use_palette == PAL_WINDOWS);
00041 for (GRFConfig *c = _grfconfig_static; c != NULL; c = c->next) c->windows_paletted = (_use_palette == PAL_WINDOWS);
00042 }
00043
00044
00045 static bool CalcGRFMD5Sum(GRFConfig *config)
00046 {
00047 FILE *f;
00048 Md5 checksum;
00049 uint8 buffer[1024];
00050 size_t len, size;
00051
00052
00053 f = FioFOpenFile(config->filename, "rb", DATA_DIR, &size);
00054 if (f == NULL) return false;
00055
00056
00057 while ((len = fread(buffer, 1, (size > sizeof(buffer)) ? sizeof(buffer) : size, f)) != 0 && size != 0) {
00058 size -= len;
00059 checksum.Append(buffer, len);
00060 }
00061 checksum.Finish(config->md5sum);
00062
00063 FioFCloseFile(f);
00064
00065 return true;
00066 }
00067
00068
00069
00070 bool FillGRFDetails(GRFConfig *config, bool is_static)
00071 {
00072 if (!FioCheckFileExists(config->filename)) {
00073 config->status = GCS_NOT_FOUND;
00074 return false;
00075 }
00076
00077
00078 LoadNewGRFFile(config, CONFIG_SLOT, GLS_FILESCAN);
00079
00080
00081 if (config->grfid == 0 || config->grfid == 0xFFFFFFFF || config->IsOpenTTDBaseGRF()) return false;
00082
00083 if (is_static) {
00084
00085 LoadNewGRFFile(config, 62, GLS_SAFETYSCAN);
00086
00087
00088 if (HasBit(config->flags, GCF_UNSAFE)) return false;
00089 }
00090
00091 config->windows_paletted = (_use_palette == PAL_WINDOWS);
00092
00093 return CalcGRFMD5Sum(config);
00094 }
00095
00096
00097 void ClearGRFConfig(GRFConfig **config)
00098 {
00099
00100 if (!HasBit((*config)->flags, GCF_COPY)) {
00101 free((*config)->filename);
00102 free((*config)->name);
00103 free((*config)->info);
00104
00105 if ((*config)->error != NULL) {
00106 free((*config)->error->custom_message);
00107 free((*config)->error->data);
00108 free((*config)->error);
00109 }
00110 }
00111 free(*config);
00112 *config = NULL;
00113 }
00114
00115
00116
00117 void ClearGRFConfigList(GRFConfig **config)
00118 {
00119 GRFConfig *c, *next;
00120 for (c = *config; c != NULL; c = next) {
00121 next = c->next;
00122 ClearGRFConfig(&c);
00123 }
00124 *config = NULL;
00125 }
00126
00127
00133 GRFConfig *DuplicateGRFConfig(const GRFConfig *c)
00134 {
00135 GRFConfig *config = MallocT<GRFConfig>(1);
00136 *config = *c;
00137
00138 if (c->filename != NULL) config->filename = strdup(c->filename);
00139 if (c->name != NULL) config->name = strdup(c->name);
00140 if (c->info != NULL) config->info = strdup(c->info);
00141 if (c->error != NULL) {
00142 config->error = MallocT<GRFError>(1);
00143 memcpy(config->error, c->error, sizeof(GRFError));
00144 if (c->error->data != NULL) config->error->data = strdup(c->error->data);
00145 if (c->error->custom_message != NULL) config->error->custom_message = strdup(c->error->custom_message);
00146 }
00147
00148 ClrBit(config->flags, GCF_COPY);
00149
00150 return config;
00151 }
00152
00158 GRFConfig **CopyGRFConfigList(GRFConfig **dst, const GRFConfig *src, bool init_only)
00159 {
00160
00161 ClearGRFConfigList(dst);
00162 for (; src != NULL; src = src->next) {
00163 GRFConfig *c = DuplicateGRFConfig(src);
00164
00165 ClrBit(c->flags, GCF_INIT_ONLY);
00166 if (init_only) SetBit(c->flags, GCF_INIT_ONLY);
00167
00168 *dst = c;
00169 dst = &c->next;
00170 }
00171
00172 return dst;
00173 }
00174
00188 static void RemoveDuplicatesFromGRFConfigList(GRFConfig *list)
00189 {
00190 GRFConfig *prev;
00191 GRFConfig *cur;
00192
00193 if (list == NULL) return;
00194
00195 for (prev = list, cur = list->next; cur != NULL; prev = cur, cur = cur->next) {
00196 if (cur->grfid != list->grfid) continue;
00197
00198 prev->next = cur->next;
00199 ClearGRFConfig(&cur);
00200 cur = prev;
00201 }
00202
00203 RemoveDuplicatesFromGRFConfigList(list->next);
00204 }
00205
00210 void AppendStaticGRFConfigs(GRFConfig **dst)
00211 {
00212 GRFConfig **tail = dst;
00213 while (*tail != NULL) tail = &(*tail)->next;
00214
00215 CopyGRFConfigList(tail, _grfconfig_static, false);
00216 RemoveDuplicatesFromGRFConfigList(*dst);
00217 }
00218
00222 void AppendToGRFConfigList(GRFConfig **dst, GRFConfig *el)
00223 {
00224 GRFConfig **tail = dst;
00225 while (*tail != NULL) tail = &(*tail)->next;
00226 *tail = el;
00227
00228 RemoveDuplicatesFromGRFConfigList(*dst);
00229 }
00230
00231
00232
00233 void ResetGRFConfig(bool defaults)
00234 {
00235 CopyGRFConfigList(&_grfconfig, _grfconfig_newgame, !defaults);
00236 AppendStaticGRFConfigs(&_grfconfig);
00237 }
00238
00239
00248 GRFListCompatibility IsGoodGRFConfigList()
00249 {
00250 GRFListCompatibility res = GLC_ALL_GOOD;
00251
00252 for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
00253 const GRFConfig *f = FindGRFConfig(c->grfid, c->md5sum);
00254 if (f == NULL) {
00255 char buf[256];
00256
00257
00258
00259 f = FindGRFConfig(c->grfid);
00260 if (f != NULL) {
00261 md5sumToString(buf, lastof(buf), c->md5sum);
00262 DEBUG(grf, 1, "NewGRF %08X (%s) not found; checksum %s. Compatibility mode on", BSWAP32(c->grfid), c->filename, buf);
00263 SetBit(c->flags, GCF_COMPATIBLE);
00264
00265
00266 if (res != GLC_NOT_FOUND) res = GLC_COMPATIBLE;
00267 GamelogGRFCompatible(f);
00268 goto compatible_grf;
00269 }
00270
00271
00272 md5sumToString(buf, lastof(buf), c->md5sum);
00273 DEBUG(grf, 0, "NewGRF %08X (%s) not found; checksum %s", BSWAP32(c->grfid), c->filename, buf);
00274
00275 GamelogGRFRemove(c->grfid);
00276
00277 c->status = GCS_NOT_FOUND;
00278 res = GLC_NOT_FOUND;
00279 } else {
00280 compatible_grf:
00281 DEBUG(grf, 1, "Loading GRF %08X from %s", BSWAP32(f->grfid), f->filename);
00282
00283
00284
00285
00286
00287 if (!HasBit(c->flags, GCF_COPY)) {
00288 free(c->filename);
00289 c->filename = strdup(f->filename);
00290 memcpy(c->md5sum, f->md5sum, sizeof(c->md5sum));
00291 if (c->name == NULL && f->name != NULL) c->name = strdup(f->name);
00292 if (c->info == NULL && f->info != NULL) c->info = strdup(f->info);
00293 c->error = NULL;
00294 }
00295 }
00296 }
00297
00298 return res;
00299 }
00300
00302 class GRFFileScanner : FileScanner {
00303 public:
00304 bool AddFile(const char *filename, size_t basepath_length);
00305
00307 static uint DoScan()
00308 {
00309 GRFFileScanner fs;
00310 return fs.Scan(".grf", DATA_DIR);
00311 }
00312 };
00313
00314 bool GRFFileScanner::AddFile(const char *filename, size_t basepath_length)
00315 {
00316 GRFConfig *c = CallocT<GRFConfig>(1);
00317 c->filename = strdup(filename + basepath_length);
00318
00319 bool added = true;
00320 if (FillGRFDetails(c, false)) {
00321 if (_all_grfs == NULL) {
00322 _all_grfs = c;
00323 } else {
00324
00325
00326 GRFConfig **pd, *d;
00327 bool stop = false;
00328 for (pd = &_all_grfs; (d = *pd) != NULL; pd = &d->next) {
00329 if (c->grfid == d->grfid && memcmp(c->md5sum, d->md5sum, sizeof(c->md5sum)) == 0) added = false;
00330
00331
00332
00333 if (strcasecmp(c->name, d->name) <= 0) {
00334 stop = true;
00335 } else if (stop) {
00336 break;
00337 }
00338 }
00339 if (added) {
00340 c->next = d;
00341 *pd = c;
00342 }
00343 }
00344 } else {
00345 added = false;
00346 }
00347
00348 if (!added) {
00349
00350
00351 ClearGRFConfig(&c);
00352 }
00353
00354 return added;
00355 }
00356
00363 static int CDECL GRFSorter(GRFConfig * const *p1, GRFConfig * const *p2)
00364 {
00365 const GRFConfig *c1 = *p1;
00366 const GRFConfig *c2 = *p2;
00367
00368 return strcasecmp(c1->name != NULL ? c1->name : c1->filename,
00369 c2->name != NULL ? c2->name : c2->filename);
00370 }
00371
00372
00373 void ScanNewGRFFiles()
00374 {
00375 ClearGRFConfigList(&_all_grfs);
00376
00377 DEBUG(grf, 1, "Scanning for NewGRFs");
00378 uint num = GRFFileScanner::DoScan();
00379
00380 DEBUG(grf, 1, "Scan complete, found %d files", num);
00381 if (num == 0 || _all_grfs == NULL) return;
00382
00383
00384
00385
00386 GRFConfig **to_sort = MallocT<GRFConfig*>(num);
00387
00388 uint i = 0;
00389 for (GRFConfig *p = _all_grfs; p != NULL; p = p->next, i++) {
00390 to_sort[i] = p;
00391 }
00392
00393 num = i;
00394
00395 QSortT(to_sort, num, &GRFSorter);
00396
00397 for (i = 1; i < num; i++) {
00398 to_sort[i - 1]->next = to_sort[i];
00399 }
00400 to_sort[num - 1]->next = NULL;
00401 _all_grfs = to_sort[0];
00402
00403 free(to_sort);
00404
00405 #ifdef ENABLE_NETWORK
00406 NetworkAfterNewGRFScan();
00407 #endif
00408 }
00409
00410
00411
00412 const GRFConfig *FindGRFConfig(uint32 grfid, const uint8 *md5sum)
00413 {
00414 for (const GRFConfig *c = _all_grfs; c != NULL; c = c->next) {
00415 if (c->grfid == grfid) {
00416 if (md5sum == NULL) return c;
00417
00418 if (memcmp(md5sum, c->md5sum, sizeof(c->md5sum)) == 0) return c;
00419 }
00420 }
00421
00422 return NULL;
00423 }
00424
00425 #ifdef ENABLE_NETWORK
00426
00428 struct UnknownGRF : public GRFIdentifier {
00429 UnknownGRF *next;
00430 char name[NETWORK_GRF_NAME_LENGTH];
00431 };
00432
00450 char *FindUnknownGRFName(uint32 grfid, uint8 *md5sum, bool create)
00451 {
00452 UnknownGRF *grf;
00453 static UnknownGRF *unknown_grfs = NULL;
00454
00455 for (grf = unknown_grfs; grf != NULL; grf = grf->next) {
00456 if (grf->grfid == grfid) {
00457 if (memcmp(md5sum, grf->md5sum, sizeof(grf->md5sum)) == 0) return grf->name;
00458 }
00459 }
00460
00461 if (!create) return NULL;
00462
00463 grf = CallocT<UnknownGRF>(1);
00464 grf->grfid = grfid;
00465 grf->next = unknown_grfs;
00466 strecpy(grf->name, UNKNOWN_GRF_NAME_PLACEHOLDER, lastof(grf->name));
00467 memcpy(grf->md5sum, md5sum, sizeof(grf->md5sum));
00468
00469 unknown_grfs = grf;
00470 return grf->name;
00471 }
00472
00473 #endif
00474
00475
00476
00477 GRFConfig *GetGRFConfig(uint32 grfid, uint32 mask)
00478 {
00479 GRFConfig *c;
00480
00481 for (c = _grfconfig; c != NULL; c = c->next) {
00482 if ((c->grfid & mask) == (grfid & mask)) return c;
00483 }
00484
00485 return NULL;
00486 }
00487
00488
00489
00490 char *GRFBuildParamList(char *dst, const GRFConfig *c, const char *last)
00491 {
00492 uint i;
00493
00494
00495 if (c->num_params == 0) return strecpy(dst, "", last);
00496
00497 for (i = 0; i < c->num_params; i++) {
00498 if (i > 0) dst = strecpy(dst, " ", last);
00499 dst += seprintf(dst, last, "%d", c->param[i]);
00500 }
00501 return dst;
00502 }
00503
00505 static const uint32 OPENTTD_GRAPHICS_BASE_GRF_ID = BSWAP32(0xFF4F5400);
00506
00511 bool GRFConfig::IsOpenTTDBaseGRF() const
00512 {
00513 return (this->grfid & 0x00FFFFFF) == OPENTTD_GRAPHICS_BASE_GRF_ID;
00514 }