00001
00002
00005 #include "stdafx.h"
00006 #include "debug.h"
00007 #include "md5.h"
00008 #include "newgrf.h"
00009 #include "string_func.h"
00010 #include "gamelog.h"
00011 #include "network/network_type.h"
00012 #include "network/network_func.h"
00013 #include "gfx_func.h"
00014
00015 #include "fileio_func.h"
00016 #include "fios.h"
00017
00018
00019 GRFConfig *_all_grfs;
00020 GRFConfig *_grfconfig;
00021 GRFConfig *_grfconfig_newgame;
00022 GRFConfig *_grfconfig_static;
00023
00024
00033 void UpdateNewGRFConfigPalette()
00034 {
00035 for (GRFConfig *c = _grfconfig_newgame; c != NULL; c = c->next) c->windows_paletted = (_use_palette == PAL_WINDOWS);
00036 for (GRFConfig *c = _grfconfig_static; c != NULL; c = c->next) c->windows_paletted = (_use_palette == PAL_WINDOWS);
00037 }
00038
00039
00040 static bool CalcGRFMD5Sum(GRFConfig *config)
00041 {
00042 FILE *f;
00043 Md5 checksum;
00044 uint8 buffer[1024];
00045 size_t len, size;
00046
00047
00048 f = FioFOpenFile(config->filename, "rb", DATA_DIR, &size);
00049 if (f == NULL) return false;
00050
00051
00052 while ((len = fread(buffer, 1, (size > sizeof(buffer)) ? sizeof(buffer) : size, f)) != 0 && size != 0) {
00053 size -= len;
00054 checksum.Append(buffer, len);
00055 }
00056 checksum.Finish(config->md5sum);
00057
00058 FioFCloseFile(f);
00059
00060 return true;
00061 }
00062
00063
00064
00065 bool FillGRFDetails(GRFConfig *config, bool is_static)
00066 {
00067 if (!FioCheckFileExists(config->filename)) {
00068 config->status = GCS_NOT_FOUND;
00069 return false;
00070 }
00071
00072
00073 LoadNewGRFFile(config, CONFIG_SLOT, GLS_FILESCAN);
00074
00075
00076 if (config->grfid == 0 || config->grfid == 0xFFFFFFFF || config->IsOpenTTDBaseGRF()) return false;
00077
00078 if (is_static) {
00079
00080 LoadNewGRFFile(config, 62, GLS_SAFETYSCAN);
00081
00082
00083 if (HasBit(config->flags, GCF_UNSAFE)) return false;
00084 }
00085
00086 config->windows_paletted = (_use_palette == PAL_WINDOWS);
00087
00088 return CalcGRFMD5Sum(config);
00089 }
00090
00091
00092 void ClearGRFConfig(GRFConfig **config)
00093 {
00094
00095 if (!HasBit((*config)->flags, GCF_COPY)) {
00096 free((*config)->filename);
00097 free((*config)->name);
00098 free((*config)->info);
00099
00100 if ((*config)->error != NULL) {
00101 free((*config)->error->custom_message);
00102 free((*config)->error->data);
00103 free((*config)->error);
00104 }
00105 }
00106 free(*config);
00107 *config = NULL;
00108 }
00109
00110
00111
00112 void ClearGRFConfigList(GRFConfig **config)
00113 {
00114 GRFConfig *c, *next;
00115 for (c = *config; c != NULL; c = next) {
00116 next = c->next;
00117 ClearGRFConfig(&c);
00118 }
00119 *config = NULL;
00120 }
00121
00122
00128 GRFConfig **CopyGRFConfigList(GRFConfig **dst, const GRFConfig *src, bool init_only)
00129 {
00130
00131 ClearGRFConfigList(dst);
00132 for (; src != NULL; src = src->next) {
00133 GRFConfig *c = CallocT<GRFConfig>(1);
00134 *c = *src;
00135 if (src->filename != NULL) c->filename = strdup(src->filename);
00136 if (src->name != NULL) c->name = strdup(src->name);
00137 if (src->info != NULL) c->info = strdup(src->info);
00138 if (src->error != NULL) {
00139 c->error = CallocT<GRFError>(1);
00140 memcpy(c->error, src->error, sizeof(GRFError));
00141 if (src->error->data != NULL) c->error->data = strdup(src->error->data);
00142 if (src->error->custom_message != NULL) c->error->custom_message = strdup(src->error->custom_message);
00143 }
00144
00145 ClrBit(c->flags, GCF_COPY);
00146
00147 ClrBit(c->flags, GCF_INIT_ONLY);
00148 if (init_only) SetBit(c->flags, GCF_INIT_ONLY);
00149
00150 *dst = c;
00151 dst = &c->next;
00152 }
00153
00154 return dst;
00155 }
00156
00170 static void RemoveDuplicatesFromGRFConfigList(GRFConfig *list)
00171 {
00172 GRFConfig *prev;
00173 GRFConfig *cur;
00174
00175 if (list == NULL) return;
00176
00177 for (prev = list, cur = list->next; cur != NULL; prev = cur, cur = cur->next) {
00178 if (cur->grfid != list->grfid) continue;
00179
00180 prev->next = cur->next;
00181 ClearGRFConfig(&cur);
00182 cur = prev;
00183 }
00184
00185 RemoveDuplicatesFromGRFConfigList(list->next);
00186 }
00187
00192 void AppendStaticGRFConfigs(GRFConfig **dst)
00193 {
00194 GRFConfig **tail = dst;
00195 while (*tail != NULL) tail = &(*tail)->next;
00196
00197 CopyGRFConfigList(tail, _grfconfig_static, false);
00198 RemoveDuplicatesFromGRFConfigList(*dst);
00199 }
00200
00204 void AppendToGRFConfigList(GRFConfig **dst, GRFConfig *el)
00205 {
00206 GRFConfig **tail = dst;
00207 while (*tail != NULL) tail = &(*tail)->next;
00208 *tail = el;
00209
00210 RemoveDuplicatesFromGRFConfigList(*dst);
00211 }
00212
00213
00214
00215 void ResetGRFConfig(bool defaults)
00216 {
00217 CopyGRFConfigList(&_grfconfig, _grfconfig_newgame, !defaults);
00218 AppendStaticGRFConfigs(&_grfconfig);
00219 }
00220
00221
00230 GRFListCompatibility IsGoodGRFConfigList()
00231 {
00232 GRFListCompatibility res = GLC_ALL_GOOD;
00233
00234 for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
00235 const GRFConfig *f = FindGRFConfig(c->grfid, c->md5sum);
00236 if (f == NULL) {
00237 char buf[256];
00238
00239
00240
00241 f = FindGRFConfig(c->grfid);
00242 if (f != NULL) {
00243 md5sumToString(buf, lastof(buf), c->md5sum);
00244 DEBUG(grf, 1, "NewGRF %08X (%s) not found; checksum %s. Compatibility mode on", BSWAP32(c->grfid), c->filename, buf);
00245 SetBit(c->flags, GCF_COMPATIBLE);
00246
00247
00248 if (res != GLC_NOT_FOUND) res = GLC_COMPATIBLE;
00249 GamelogGRFCompatible(f);
00250 goto compatible_grf;
00251 }
00252
00253
00254 md5sumToString(buf, lastof(buf), c->md5sum);
00255 DEBUG(grf, 0, "NewGRF %08X (%s) not found; checksum %s", BSWAP32(c->grfid), c->filename, buf);
00256
00257 GamelogGRFRemove(c->grfid);
00258
00259 c->status = GCS_NOT_FOUND;
00260 res = GLC_NOT_FOUND;
00261 } else {
00262 compatible_grf:
00263 DEBUG(grf, 1, "Loading GRF %08X from %s", BSWAP32(f->grfid), f->filename);
00264
00265
00266
00267
00268
00269 if (!HasBit(c->flags, GCF_COPY)) {
00270 free(c->filename);
00271 c->filename = strdup(f->filename);
00272 memcpy(c->md5sum, f->md5sum, sizeof(c->md5sum));
00273 if (c->name == NULL && f->name != NULL) c->name = strdup(f->name);
00274 if (c->info == NULL && f->info != NULL) c->info = strdup(f->info);
00275 c->error = NULL;
00276 }
00277 }
00278 }
00279
00280 return res;
00281 }
00282
00284 class GRFFileScanner : FileScanner {
00285 public:
00286 bool AddFile(const char *filename, size_t basepath_length);
00287
00289 static uint DoScan()
00290 {
00291 GRFFileScanner fs;
00292 return fs.Scan(".grf", DATA_DIR);
00293 }
00294 };
00295
00296 bool GRFFileScanner::AddFile(const char *filename, size_t basepath_length)
00297 {
00298 GRFConfig *c = CallocT<GRFConfig>(1);
00299 c->filename = strdup(filename + basepath_length);
00300
00301 bool added = true;
00302 if (FillGRFDetails(c, false)) {
00303 if (_all_grfs == NULL) {
00304 _all_grfs = c;
00305 } else {
00306
00307
00308 GRFConfig **pd, *d;
00309 bool stop = false;
00310 for (pd = &_all_grfs; (d = *pd) != NULL; pd = &d->next) {
00311 if (c->grfid == d->grfid && memcmp(c->md5sum, d->md5sum, sizeof(c->md5sum)) == 0) added = false;
00312
00313
00314
00315 if (strcasecmp(c->name, d->name) <= 0) {
00316 stop = true;
00317 } else if (stop) {
00318 break;
00319 }
00320 }
00321 if (added) {
00322 c->next = d;
00323 *pd = c;
00324 }
00325 }
00326 } else {
00327 added = false;
00328 }
00329
00330 if (!added) {
00331
00332
00333 free(c->filename);
00334 free(c->name);
00335 free(c->info);
00336 free(c);
00337 }
00338
00339 return added;
00340 }
00341
00348 static int CDECL GRFSorter(const void *p1, const void *p2)
00349 {
00350 const GRFConfig *c1 = *(const GRFConfig **)p1;
00351 const GRFConfig *c2 = *(const GRFConfig **)p2;
00352
00353 return strcasecmp(c1->name != NULL ? c1->name : c1->filename,
00354 c2->name != NULL ? c2->name : c2->filename);
00355 }
00356
00357
00358 void ScanNewGRFFiles()
00359 {
00360 ClearGRFConfigList(&_all_grfs);
00361
00362 DEBUG(grf, 1, "Scanning for NewGRFs");
00363 uint num = GRFFileScanner::DoScan();
00364
00365 DEBUG(grf, 1, "Scan complete, found %d files", num);
00366 if (num == 0 || _all_grfs == NULL) return;
00367
00368
00369
00370
00371 GRFConfig **to_sort = MallocT<GRFConfig*>(num);
00372
00373 uint i = 0;
00374 for (GRFConfig *p = _all_grfs; p != NULL; p = p->next, i++) {
00375 to_sort[i] = p;
00376 }
00377
00378 num = i;
00379
00380 qsort(to_sort, num, sizeof(GRFConfig*), GRFSorter);
00381
00382 for (i = 1; i < num; i++) {
00383 to_sort[i - 1]->next = to_sort[i];
00384 }
00385 to_sort[num - 1]->next = NULL;
00386 _all_grfs = to_sort[0];
00387
00388 free(to_sort);
00389
00390 #ifdef ENABLE_NETWORK
00391 NetworkAfterNewGRFScan();
00392 #endif
00393 }
00394
00395
00396
00397 const GRFConfig *FindGRFConfig(uint32 grfid, const uint8 *md5sum)
00398 {
00399 for (const GRFConfig *c = _all_grfs; c != NULL; c = c->next) {
00400 if (c->grfid == grfid) {
00401 if (md5sum == NULL) return c;
00402
00403 if (memcmp(md5sum, c->md5sum, sizeof(c->md5sum)) == 0) return c;
00404 }
00405 }
00406
00407 return NULL;
00408 }
00409
00410 #ifdef ENABLE_NETWORK
00411
00413 struct UnknownGRF : public GRFIdentifier {
00414 UnknownGRF *next;
00415 char name[NETWORK_GRF_NAME_LENGTH];
00416 };
00417
00435 char *FindUnknownGRFName(uint32 grfid, uint8 *md5sum, bool create)
00436 {
00437 UnknownGRF *grf;
00438 static UnknownGRF *unknown_grfs = NULL;
00439
00440 for (grf = unknown_grfs; grf != NULL; grf = grf->next) {
00441 if (grf->grfid == grfid) {
00442 if (memcmp(md5sum, grf->md5sum, sizeof(grf->md5sum)) == 0) return grf->name;
00443 }
00444 }
00445
00446 if (!create) return NULL;
00447
00448 grf = CallocT<UnknownGRF>(1);
00449 grf->grfid = grfid;
00450 grf->next = unknown_grfs;
00451 strecpy(grf->name, UNKNOWN_GRF_NAME_PLACEHOLDER, lastof(grf->name));
00452 memcpy(grf->md5sum, md5sum, sizeof(grf->md5sum));
00453
00454 unknown_grfs = grf;
00455 return grf->name;
00456 }
00457
00458 #endif
00459
00460
00461
00462 GRFConfig *GetGRFConfig(uint32 grfid, uint32 mask)
00463 {
00464 GRFConfig *c;
00465
00466 for (c = _grfconfig; c != NULL; c = c->next) {
00467 if ((c->grfid & mask) == (grfid & mask)) return c;
00468 }
00469
00470 return NULL;
00471 }
00472
00473
00474
00475 char *GRFBuildParamList(char *dst, const GRFConfig *c, const char *last)
00476 {
00477 uint i;
00478
00479
00480 if (c->num_params == 0) return strecpy(dst, "", last);
00481
00482 for (i = 0; i < c->num_params; i++) {
00483 if (i > 0) dst = strecpy(dst, " ", last);
00484 dst += seprintf(dst, last, "%d", c->param[i]);
00485 }
00486 return dst;
00487 }
00488
00490 static const uint32 OPENTTD_GRAPHICS_BASE_GRF_ID = BSWAP32(0xFF4F5400);
00491
00496 bool GRFConfig::IsOpenTTDBaseGRF() const
00497 {
00498 return (this->grfid & 0x00FFFFFF) == OPENTTD_GRAPHICS_BASE_GRF_ID;
00499 }