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 **CopyGRFConfigList(GRFConfig **dst, const GRFConfig *src, bool init_only)
00134 {
00135
00136 ClearGRFConfigList(dst);
00137 for (; src != NULL; src = src->next) {
00138 GRFConfig *c = CallocT<GRFConfig>(1);
00139 *c = *src;
00140 if (src->filename != NULL) c->filename = strdup(src->filename);
00141 if (src->name != NULL) c->name = strdup(src->name);
00142 if (src->info != NULL) c->info = strdup(src->info);
00143 if (src->error != NULL) {
00144 c->error = CallocT<GRFError>(1);
00145 memcpy(c->error, src->error, sizeof(GRFError));
00146 if (src->error->data != NULL) c->error->data = strdup(src->error->data);
00147 if (src->error->custom_message != NULL) c->error->custom_message = strdup(src->error->custom_message);
00148 }
00149
00150 ClrBit(c->flags, GCF_COPY);
00151
00152 ClrBit(c->flags, GCF_INIT_ONLY);
00153 if (init_only) SetBit(c->flags, GCF_INIT_ONLY);
00154
00155 *dst = c;
00156 dst = &c->next;
00157 }
00158
00159 return dst;
00160 }
00161
00175 static void RemoveDuplicatesFromGRFConfigList(GRFConfig *list)
00176 {
00177 GRFConfig *prev;
00178 GRFConfig *cur;
00179
00180 if (list == NULL) return;
00181
00182 for (prev = list, cur = list->next; cur != NULL; prev = cur, cur = cur->next) {
00183 if (cur->grfid != list->grfid) continue;
00184
00185 prev->next = cur->next;
00186 ClearGRFConfig(&cur);
00187 cur = prev;
00188 }
00189
00190 RemoveDuplicatesFromGRFConfigList(list->next);
00191 }
00192
00197 void AppendStaticGRFConfigs(GRFConfig **dst)
00198 {
00199 GRFConfig **tail = dst;
00200 while (*tail != NULL) tail = &(*tail)->next;
00201
00202 CopyGRFConfigList(tail, _grfconfig_static, false);
00203 RemoveDuplicatesFromGRFConfigList(*dst);
00204 }
00205
00209 void AppendToGRFConfigList(GRFConfig **dst, GRFConfig *el)
00210 {
00211 GRFConfig **tail = dst;
00212 while (*tail != NULL) tail = &(*tail)->next;
00213 *tail = el;
00214
00215 RemoveDuplicatesFromGRFConfigList(*dst);
00216 }
00217
00218
00219
00220 void ResetGRFConfig(bool defaults)
00221 {
00222 CopyGRFConfigList(&_grfconfig, _grfconfig_newgame, !defaults);
00223 AppendStaticGRFConfigs(&_grfconfig);
00224 }
00225
00226
00235 GRFListCompatibility IsGoodGRFConfigList()
00236 {
00237 GRFListCompatibility res = GLC_ALL_GOOD;
00238
00239 for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
00240 const GRFConfig *f = FindGRFConfig(c->grfid, c->md5sum);
00241 if (f == NULL) {
00242 char buf[256];
00243
00244
00245
00246 f = FindGRFConfig(c->grfid);
00247 if (f != NULL) {
00248 md5sumToString(buf, lastof(buf), c->md5sum);
00249 DEBUG(grf, 1, "NewGRF %08X (%s) not found; checksum %s. Compatibility mode on", BSWAP32(c->grfid), c->filename, buf);
00250 SetBit(c->flags, GCF_COMPATIBLE);
00251
00252
00253 if (res != GLC_NOT_FOUND) res = GLC_COMPATIBLE;
00254 GamelogGRFCompatible(f);
00255 goto compatible_grf;
00256 }
00257
00258
00259 md5sumToString(buf, lastof(buf), c->md5sum);
00260 DEBUG(grf, 0, "NewGRF %08X (%s) not found; checksum %s", BSWAP32(c->grfid), c->filename, buf);
00261
00262 GamelogGRFRemove(c->grfid);
00263
00264 c->status = GCS_NOT_FOUND;
00265 res = GLC_NOT_FOUND;
00266 } else {
00267 compatible_grf:
00268 DEBUG(grf, 1, "Loading GRF %08X from %s", BSWAP32(f->grfid), f->filename);
00269
00270
00271
00272
00273
00274 if (!HasBit(c->flags, GCF_COPY)) {
00275 free(c->filename);
00276 c->filename = strdup(f->filename);
00277 memcpy(c->md5sum, f->md5sum, sizeof(c->md5sum));
00278 if (c->name == NULL && f->name != NULL) c->name = strdup(f->name);
00279 if (c->info == NULL && f->info != NULL) c->info = strdup(f->info);
00280 c->error = NULL;
00281 }
00282 }
00283 }
00284
00285 return res;
00286 }
00287
00289 class GRFFileScanner : FileScanner {
00290 public:
00291 bool AddFile(const char *filename, size_t basepath_length);
00292
00294 static uint DoScan()
00295 {
00296 GRFFileScanner fs;
00297 return fs.Scan(".grf", DATA_DIR);
00298 }
00299 };
00300
00301 bool GRFFileScanner::AddFile(const char *filename, size_t basepath_length)
00302 {
00303 GRFConfig *c = CallocT<GRFConfig>(1);
00304 c->filename = strdup(filename + basepath_length);
00305
00306 bool added = true;
00307 if (FillGRFDetails(c, false)) {
00308 if (_all_grfs == NULL) {
00309 _all_grfs = c;
00310 } else {
00311
00312
00313 GRFConfig **pd, *d;
00314 bool stop = false;
00315 for (pd = &_all_grfs; (d = *pd) != NULL; pd = &d->next) {
00316 if (c->grfid == d->grfid && memcmp(c->md5sum, d->md5sum, sizeof(c->md5sum)) == 0) added = false;
00317
00318
00319
00320 if (strcasecmp(c->name, d->name) <= 0) {
00321 stop = true;
00322 } else if (stop) {
00323 break;
00324 }
00325 }
00326 if (added) {
00327 c->next = d;
00328 *pd = c;
00329 }
00330 }
00331 } else {
00332 added = false;
00333 }
00334
00335 if (!added) {
00336
00337
00338 free(c->filename);
00339 free(c->name);
00340 free(c->info);
00341 free(c);
00342 }
00343
00344 return added;
00345 }
00346
00353 static int CDECL GRFSorter(GRFConfig * const *p1, GRFConfig * const *p2)
00354 {
00355 const GRFConfig *c1 = *p1;
00356 const GRFConfig *c2 = *p2;
00357
00358 return strcasecmp(c1->name != NULL ? c1->name : c1->filename,
00359 c2->name != NULL ? c2->name : c2->filename);
00360 }
00361
00362
00363 void ScanNewGRFFiles()
00364 {
00365 ClearGRFConfigList(&_all_grfs);
00366
00367 DEBUG(grf, 1, "Scanning for NewGRFs");
00368 uint num = GRFFileScanner::DoScan();
00369
00370 DEBUG(grf, 1, "Scan complete, found %d files", num);
00371 if (num == 0 || _all_grfs == NULL) return;
00372
00373
00374
00375
00376 GRFConfig **to_sort = MallocT<GRFConfig*>(num);
00377
00378 uint i = 0;
00379 for (GRFConfig *p = _all_grfs; p != NULL; p = p->next, i++) {
00380 to_sort[i] = p;
00381 }
00382
00383 num = i;
00384
00385 QSortT(to_sort, num, &GRFSorter);
00386
00387 for (i = 1; i < num; i++) {
00388 to_sort[i - 1]->next = to_sort[i];
00389 }
00390 to_sort[num - 1]->next = NULL;
00391 _all_grfs = to_sort[0];
00392
00393 free(to_sort);
00394
00395 #ifdef ENABLE_NETWORK
00396 NetworkAfterNewGRFScan();
00397 #endif
00398 }
00399
00400
00401
00402 const GRFConfig *FindGRFConfig(uint32 grfid, const uint8 *md5sum)
00403 {
00404 for (const GRFConfig *c = _all_grfs; c != NULL; c = c->next) {
00405 if (c->grfid == grfid) {
00406 if (md5sum == NULL) return c;
00407
00408 if (memcmp(md5sum, c->md5sum, sizeof(c->md5sum)) == 0) return c;
00409 }
00410 }
00411
00412 return NULL;
00413 }
00414
00415 #ifdef ENABLE_NETWORK
00416
00418 struct UnknownGRF : public GRFIdentifier {
00419 UnknownGRF *next;
00420 char name[NETWORK_GRF_NAME_LENGTH];
00421 };
00422
00440 char *FindUnknownGRFName(uint32 grfid, uint8 *md5sum, bool create)
00441 {
00442 UnknownGRF *grf;
00443 static UnknownGRF *unknown_grfs = NULL;
00444
00445 for (grf = unknown_grfs; grf != NULL; grf = grf->next) {
00446 if (grf->grfid == grfid) {
00447 if (memcmp(md5sum, grf->md5sum, sizeof(grf->md5sum)) == 0) return grf->name;
00448 }
00449 }
00450
00451 if (!create) return NULL;
00452
00453 grf = CallocT<UnknownGRF>(1);
00454 grf->grfid = grfid;
00455 grf->next = unknown_grfs;
00456 strecpy(grf->name, UNKNOWN_GRF_NAME_PLACEHOLDER, lastof(grf->name));
00457 memcpy(grf->md5sum, md5sum, sizeof(grf->md5sum));
00458
00459 unknown_grfs = grf;
00460 return grf->name;
00461 }
00462
00463 #endif
00464
00465
00466
00467 GRFConfig *GetGRFConfig(uint32 grfid, uint32 mask)
00468 {
00469 GRFConfig *c;
00470
00471 for (c = _grfconfig; c != NULL; c = c->next) {
00472 if ((c->grfid & mask) == (grfid & mask)) return c;
00473 }
00474
00475 return NULL;
00476 }
00477
00478
00479
00480 char *GRFBuildParamList(char *dst, const GRFConfig *c, const char *last)
00481 {
00482 uint i;
00483
00484
00485 if (c->num_params == 0) return strecpy(dst, "", last);
00486
00487 for (i = 0; i < c->num_params; i++) {
00488 if (i > 0) dst = strecpy(dst, " ", last);
00489 dst += seprintf(dst, last, "%d", c->param[i]);
00490 }
00491 return dst;
00492 }
00493
00495 static const uint32 OPENTTD_GRAPHICS_BASE_GRF_ID = BSWAP32(0xFF4F5400);
00496
00501 bool GRFConfig::IsOpenTTDBaseGRF() const
00502 {
00503 return (this->grfid & 0x00FFFFFF) == OPENTTD_GRAPHICS_BASE_GRF_ID;
00504 }