OpenTTD
newgrf_config.cpp
Go to the documentation of this file.
1 /* $Id: newgrf_config.cpp 27063 2014-11-18 20:12:42Z frosch $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
12 #include "stdafx.h"
13 #include "debug.h"
14 #include "3rdparty/md5/md5.h"
15 #include "newgrf.h"
16 #include "network/network_func.h"
17 #include "gfx_func.h"
18 #include "newgrf_text.h"
19 #include "window_func.h"
20 #include "progress.h"
21 #include "video/video_driver.hpp"
22 #include "strings_func.h"
23 #include "textfile_gui.h"
24 
25 #include "fileio_func.h"
26 #include "fios.h"
27 
28 #include "safeguards.h"
29 
32  text(NULL)
33 {
34 }
35 
38 {
39  CleanUpGRFText(this->text);
40 }
41 
47 GRFConfig::GRFConfig(const char *filename) :
48  name(new GRFTextWrapper()),
49  info(new GRFTextWrapper()),
50  url(new GRFTextWrapper()),
51  num_valid_params(lengthof(param))
52 {
53  if (filename != NULL) this->filename = stredup(filename);
54  this->name->AddRef();
55  this->info->AddRef();
56  this->url->AddRef();
57 }
58 
65  ident(config.ident),
66  name(config.name),
67  info(config.info),
68  url(config.url),
69  version(config.version),
70  min_loadable_version(config.min_loadable_version),
71  flags(config.flags & ~(1 << GCF_COPY)),
72  status(config.status),
73  grf_bugs(config.grf_bugs),
74  num_params(config.num_params),
75  num_valid_params(config.num_valid_params),
76  palette(config.palette),
77  has_param_defaults(config.has_param_defaults)
78 {
79  MemCpyT<uint8>(this->original_md5sum, config.original_md5sum, lengthof(this->original_md5sum));
80  MemCpyT<uint32>(this->param, config.param, lengthof(this->param));
81  if (config.filename != NULL) this->filename = stredup(config.filename);
82  this->name->AddRef();
83  this->info->AddRef();
84  this->url->AddRef();
85  if (config.error != NULL) this->error = new GRFError(*config.error);
86  for (uint i = 0; i < config.param_info.Length(); i++) {
87  if (config.param_info[i] == NULL) {
88  *this->param_info.Append() = NULL;
89  } else {
90  *this->param_info.Append() = new GRFParameterInfo(*config.param_info[i]);
91  }
92  }
93 }
94 
97 {
98  /* GCF_COPY as in NOT stredupped/alloced the filename */
99  if (!HasBit(this->flags, GCF_COPY)) {
100  free(this->filename);
101  delete this->error;
102  }
103  this->name->Release();
104  this->info->Release();
105  this->url->Release();
106 
107  for (uint i = 0; i < this->param_info.Length(); i++) delete this->param_info[i];
108 }
109 
115 {
116  this->num_params = src.num_params;
118  MemCpyT<uint32>(this->param, src.param, lengthof(this->param));
119 }
120 
126 const char *GRFConfig::GetName() const
127 {
128  const char *name = GetGRFStringFromGRFText(this->name->text);
129  return StrEmpty(name) ? this->filename : name;
130 }
131 
136 const char *GRFConfig::GetDescription() const
137 {
138  return GetGRFStringFromGRFText(this->info->text);
139 }
140 
145 const char *GRFConfig::GetURL() const
146 {
147  return GetGRFStringFromGRFText(this->url->text);
148 }
149 
152 {
153  this->num_params = 0;
154  MemSetT<uint32>(this->param, 0, lengthof(this->param));
155 
156  if (!this->has_param_defaults) return;
157 
158  for (uint i = 0; i < this->param_info.Length(); i++) {
159  if (this->param_info[i] == NULL) continue;
160  this->param_info[i]->SetValue(this, this->param_info[i]->def_value);
161  }
162 }
163 
170 {
171  PaletteType pal;
172  switch (this->palette & GRFP_GRF_MASK) {
173  case GRFP_GRF_DOS: pal = PAL_DOS; break;
174  case GRFP_GRF_WINDOWS: pal = PAL_WINDOWS; break;
175  default: pal = _settings_client.gui.newgrf_default_palette == 1 ? PAL_WINDOWS : PAL_DOS; break;
176  }
178 }
179 
184 {
185  for (GRFParameterInfo **info = this->param_info.Begin(); info != this->param_info.End(); ++info) {
186  if (*info == NULL) continue;
187  (*info)->Finalize();
188  }
189 }
190 
195 
202  message(message),
203  severity(severity)
204 {
205 }
206 
213  custom_message(error.custom_message),
214  data(error.data),
215  message(error.message),
216  severity(error.severity)
217 {
218  if (error.custom_message != NULL) this->custom_message = stredup(error.custom_message);
219  if (error.data != NULL) this->data = stredup(error.data);
220  memcpy(this->param_value, error.param_value, sizeof(this->param_value));
221 }
222 
223 GRFError::~GRFError()
224 {
225  free(this->custom_message);
226  free(this->data);
227 }
228 
234  name(NULL),
235  desc(NULL),
236  type(PTYPE_UINT_ENUM),
237  min_value(0),
238  max_value(UINT32_MAX),
239  def_value(0),
240  param_nr(nr),
241  first_bit(0),
242  num_bit(32),
243  complete_labels(false)
244 {}
245 
252  name(DuplicateGRFText(info.name)),
253  desc(DuplicateGRFText(info.desc)),
254  type(info.type),
255  min_value(info.min_value),
256  max_value(info.max_value),
257  def_value(info.def_value),
258  param_nr(info.param_nr),
259  first_bit(info.first_bit),
260  num_bit(info.num_bit),
261  complete_labels(info.complete_labels)
262 {
263  for (uint i = 0; i < info.value_names.Length(); i++) {
265  this->value_names.Insert(data->first, DuplicateGRFText(data->second));
266  }
267 }
268 
271 {
272  CleanUpGRFText(this->name);
273  CleanUpGRFText(this->desc);
274  for (uint i = 0; i < this->value_names.Length(); i++) {
276  CleanUpGRFText(data->second);
277  }
278 }
279 
285 uint32 GRFParameterInfo::GetValue(struct GRFConfig *config) const
286 {
287  /* GB doesn't work correctly with nbits == 32, so handle that case here. */
288  if (this->num_bit == 32) return config->param[this->param_nr];
289  return GB(config->param[this->param_nr], this->first_bit, this->num_bit);
290 }
291 
297 void GRFParameterInfo::SetValue(struct GRFConfig *config, uint32 value)
298 {
299  /* SB doesn't work correctly with nbits == 32, so handle that case here. */
300  if (this->num_bit == 32) {
301  config->param[this->param_nr] = value;
302  } else {
303  SB(config->param[this->param_nr], this->first_bit, this->num_bit, value);
304  }
305  config->num_params = max<uint>(config->num_params, this->param_nr + 1);
307 }
308 
313 {
314  this->complete_labels = true;
315  for (uint32 value = this->min_value; value <= this->max_value; value++) {
316  if (!this->value_names.Contains(value)) {
317  this->complete_labels = false;
318  break;
319  }
320  }
321 }
322 
330 {
331  for (GRFConfig *c = _grfconfig_newgame; c != NULL; c = c->next) c->SetSuitablePalette();
332  for (GRFConfig *c = _grfconfig_static; c != NULL; c = c->next) c->SetSuitablePalette();
333  for (GRFConfig *c = _all_grfs; c != NULL; c = c->next) c->SetSuitablePalette();
334  return true;
335 }
336 
342 size_t GRFGetSizeOfDataSection(FILE *f)
343 {
344  extern const byte _grf_cont_v2_sig[];
345  static const uint header_len = 14;
346 
347  byte data[header_len];
348  if (fread(data, 1, header_len, f) == header_len) {
349  if (data[0] == 0 && data[1] == 0 && MemCmpT(data + 2, _grf_cont_v2_sig, 8) == 0) {
350  /* Valid container version 2, get data section size. */
351  size_t offset = ((size_t)data[13] << 24) | ((size_t)data[12] << 16) | ((size_t)data[11] << 8) | (size_t)data[10];
352  if (offset >= 1 * 1024 * 1024 * 1024) {
353  DEBUG(grf, 0, "Unexpectedly large offset for NewGRF");
354  /* Having more than 1 GiB of data is very implausible. Mostly because then
355  * all pools in OpenTTD are flooded already. Or it's just Action C all over.
356  * In any case, the offsets to graphics will likely not work either. */
357  return SIZE_MAX;
358  }
359  return header_len + offset;
360  }
361  }
362 
363  return SIZE_MAX;
364 }
365 
372 static bool CalcGRFMD5Sum(GRFConfig *config, Subdirectory subdir)
373 {
374  FILE *f;
375  Md5 checksum;
376  uint8 buffer[1024];
377  size_t len, size;
378 
379  /* open the file */
380  f = FioFOpenFile(config->filename, "rb", subdir, &size);
381  if (f == NULL) return false;
382 
383  long start = ftell(f);
384  size = min(size, GRFGetSizeOfDataSection(f));
385 
386  if (start < 0 || fseek(f, start, SEEK_SET) < 0) {
387  FioFCloseFile(f);
388  return false;
389  }
390 
391  /* calculate md5sum */
392  while ((len = fread(buffer, 1, (size > sizeof(buffer)) ? sizeof(buffer) : size, f)) != 0 && size != 0) {
393  size -= len;
394  checksum.Append(buffer, len);
395  }
396  checksum.Finish(config->ident.md5sum);
397 
398  FioFCloseFile(f);
399 
400  return true;
401 }
402 
403 
411 bool FillGRFDetails(GRFConfig *config, bool is_static, Subdirectory subdir)
412 {
413  if (!FioCheckFileExists(config->filename, subdir)) {
414  config->status = GCS_NOT_FOUND;
415  return false;
416  }
417 
418  /* Find and load the Action 8 information */
419  LoadNewGRFFile(config, CONFIG_SLOT, GLS_FILESCAN, subdir);
420  config->SetSuitablePalette();
421  config->FinalizeParameterInfo();
422 
423  /* Skip if the grfid is 0 (not read) or 0xFFFFFFFF (ttdp system grf) */
424  if (config->ident.grfid == 0 || config->ident.grfid == 0xFFFFFFFF || config->IsOpenTTDBaseGRF()) return false;
425 
426  if (is_static) {
427  /* Perform a 'safety scan' for static GRFs */
428  LoadNewGRFFile(config, 62, GLS_SAFETYSCAN, subdir);
429 
430  /* GCF_UNSAFE is set if GLS_SAFETYSCAN finds unsafe actions */
431  if (HasBit(config->flags, GCF_UNSAFE)) return false;
432  }
433 
434  return CalcGRFMD5Sum(config, subdir);
435 }
436 
437 
444 {
445  GRFConfig *c, *next;
446  for (c = *config; c != NULL; c = next) {
447  next = c->next;
448  delete c;
449  }
450  *config = NULL;
451 }
452 
453 
461 GRFConfig **CopyGRFConfigList(GRFConfig **dst, const GRFConfig *src, bool init_only)
462 {
463  /* Clear destination as it will be overwritten */
464  ClearGRFConfigList(dst);
465  for (; src != NULL; src = src->next) {
466  GRFConfig *c = new GRFConfig(*src);
467 
469  if (init_only) SetBit(c->flags, GCF_INIT_ONLY);
470 
471  *dst = c;
472  dst = &c->next;
473  }
474 
475  return dst;
476 }
477 
492 {
493  GRFConfig *prev;
494  GRFConfig *cur;
495 
496  if (list == NULL) return;
497 
498  for (prev = list, cur = list->next; cur != NULL; prev = cur, cur = cur->next) {
499  if (cur->ident.grfid != list->ident.grfid) continue;
500 
501  prev->next = cur->next;
502  delete cur;
503  cur = prev; // Just go back one so it continues as normal later on
504  }
505 
507 }
508 
514 {
515  GRFConfig **tail = dst;
516  while (*tail != NULL) tail = &(*tail)->next;
517 
518  CopyGRFConfigList(tail, _grfconfig_static, false);
520 }
521 
528 {
529  GRFConfig **tail = dst;
530  while (*tail != NULL) tail = &(*tail)->next;
531  *tail = el;
532 
534 }
535 
536 
538 void ResetGRFConfig(bool defaults)
539 {
540  CopyGRFConfigList(&_grfconfig, _grfconfig_newgame, !defaults);
541  AppendStaticGRFConfigs(&_grfconfig);
542 }
543 
544 
557 {
559 
560  for (GRFConfig *c = grfconfig; c != NULL; c = c->next) {
561  const GRFConfig *f = FindGRFConfig(c->ident.grfid, FGCM_EXACT, c->ident.md5sum);
562  if (f == NULL || HasBit(f->flags, GCF_INVALID)) {
563  char buf[256];
564 
565  /* If we have not found the exactly matching GRF try to find one with the
566  * same grfid, as it most likely is compatible */
567  f = FindGRFConfig(c->ident.grfid, FGCM_COMPATIBLE, NULL, c->version);
568  if (f != NULL) {
569  md5sumToString(buf, lastof(buf), c->ident.md5sum);
570  DEBUG(grf, 1, "NewGRF %08X (%s) not found; checksum %s. Compatibility mode on", BSWAP32(c->ident.grfid), c->filename, buf);
571  if (!HasBit(c->flags, GCF_COMPATIBLE)) {
572  /* Preserve original_md5sum after it has been assigned */
573  SetBit(c->flags, GCF_COMPATIBLE);
574  memcpy(c->original_md5sum, c->ident.md5sum, sizeof(c->original_md5sum));
575  }
576 
577  /* Non-found has precedence over compatibility load */
578  if (res != GLC_NOT_FOUND) res = GLC_COMPATIBLE;
579  goto compatible_grf;
580  }
581 
582  /* No compatible grf was found, mark it as disabled */
583  md5sumToString(buf, lastof(buf), c->ident.md5sum);
584  DEBUG(grf, 0, "NewGRF %08X (%s) not found; checksum %s", BSWAP32(c->ident.grfid), c->filename, buf);
585 
586  c->status = GCS_NOT_FOUND;
587  res = GLC_NOT_FOUND;
588  } else {
589 compatible_grf:
590  DEBUG(grf, 1, "Loading GRF %08X from %s", BSWAP32(f->ident.grfid), f->filename);
591  /* The filename could be the filename as in the savegame. As we need
592  * to load the GRF here, we need the correct filename, so overwrite that
593  * in any case and set the name and info when it is not set already.
594  * When the GCF_COPY flag is set, it is certain that the filename is
595  * already a local one, so there is no need to replace it. */
596  if (!HasBit(c->flags, GCF_COPY)) {
597  free(c->filename);
598  c->filename = stredup(f->filename);
599  memcpy(c->ident.md5sum, f->ident.md5sum, sizeof(c->ident.md5sum));
600  c->name->Release();
601  c->name = f->name;
602  c->name->AddRef();
603  c->info->Release();
604  c->info = f->name;
605  c->info->AddRef();
606  c->error = NULL;
607  c->version = f->version;
608  c->min_loadable_version = f->min_loadable_version;
609  c->num_valid_params = f->num_valid_params;
610  c->has_param_defaults = f->has_param_defaults;
611  for (uint i = 0; i < f->param_info.Length(); i++) {
612  if (f->param_info[i] == NULL) {
613  *c->param_info.Append() = NULL;
614  } else {
615  *c->param_info.Append() = new GRFParameterInfo(*f->param_info[i]);
616  }
617  }
618  }
619  }
620  }
621 
622  return res;
623 }
624 
627  uint next_update;
628  uint num_scanned;
629 
630 public:
632  {
633  }
634 
635  /* virtual */ bool AddFile(const char *filename, size_t basepath_length, const char *tar_filename);
636 
638  static uint DoScan()
639  {
640  GRFFileScanner fs;
641  int ret = fs.Scan(".grf", NEWGRF_DIR);
642  /* The number scanned and the number returned may not be the same;
643  * duplicate NewGRFs and base sets are ignored in the return value. */
645  return ret;
646  }
647 };
648 
649 bool GRFFileScanner::AddFile(const char *filename, size_t basepath_length, const char *tar_filename)
650 {
651  GRFConfig *c = new GRFConfig(filename + basepath_length);
652 
653  bool added = true;
654  if (FillGRFDetails(c, false)) {
655  if (_all_grfs == NULL) {
656  _all_grfs = c;
657  } else {
658  /* Insert file into list at a position determined by its
659  * name, so the list is sorted as we go along */
660  GRFConfig **pd, *d;
661  bool stop = false;
662  for (pd = &_all_grfs; (d = *pd) != NULL; pd = &d->next) {
663  if (c->ident.grfid == d->ident.grfid && memcmp(c->ident.md5sum, d->ident.md5sum, sizeof(c->ident.md5sum)) == 0) added = false;
664  /* Because there can be multiple grfs with the same name, make sure we checked all grfs with the same name,
665  * before inserting the entry. So insert a new grf at the end of all grfs with the same name, instead of
666  * just after the first with the same name. Avoids doubles in the list. */
667  if (strcasecmp(c->GetName(), d->GetName()) <= 0) {
668  stop = true;
669  } else if (stop) {
670  break;
671  }
672  }
673  if (added) {
674  c->next = d;
675  *pd = c;
676  }
677  }
678  } else {
679  added = false;
680  }
681 
682  this->num_scanned++;
683  if (this->next_update <= _realtime_tick) {
686 
687  const char *name = NULL;
688  if (c->name != NULL) name = GetGRFStringFromGRFText(c->name->text);
689  if (name == NULL) name = c->filename;
690  UpdateNewGRFScanStatus(this->num_scanned, name);
691 
694 
695  this->next_update = _realtime_tick + 200;
696  }
697 
698  if (!added) {
699  /* File couldn't be opened, or is either not a NewGRF or is a
700  * 'system' NewGRF or it's already known, so forget about it. */
701  delete c;
702  }
703 
704  return added;
705 }
706 
713 static int CDECL GRFSorter(GRFConfig * const *p1, GRFConfig * const *p2)
714 {
715  const GRFConfig *c1 = *p1;
716  const GRFConfig *c2 = *p2;
717 
718  return strnatcmp(c1->GetName(), c2->GetName());
719 }
720 
725 void DoScanNewGRFFiles(void *callback)
726 {
728 
729  ClearGRFConfigList(&_all_grfs);
731 
732  DEBUG(grf, 1, "Scanning for NewGRFs");
733  uint num = GRFFileScanner::DoScan();
734 
735  DEBUG(grf, 1, "Scan complete, found %d files", num);
736  if (num != 0 && _all_grfs != NULL) {
737  /* Sort the linked list using quicksort.
738  * For that we first have to make an array, then sort and
739  * then remake the linked list. */
740  GRFConfig **to_sort = MallocT<GRFConfig*>(num);
741 
742  uint i = 0;
743  for (GRFConfig *p = _all_grfs; p != NULL; p = p->next, i++) {
744  to_sort[i] = p;
745  }
746  /* Number of files is not necessarily right */
747  num = i;
748 
749  QSortT(to_sort, num, &GRFSorter);
750 
751  for (i = 1; i < num; i++) {
752  to_sort[i - 1]->next = to_sort[i];
753  }
754  to_sort[num - 1]->next = NULL;
755  _all_grfs = to_sort[0];
756 
757  free(to_sort);
758 
759 #ifdef ENABLE_NETWORK
761 #endif
762  }
763 
766 
767  /* Yes... these are the NewGRF windows */
770  if (callback != NULL) ((NewGRFScanCallback*)callback)->OnNewGRFsScanned();
771 
773  SetModalProgress(false);
776 }
777 
783 {
784  /* First set the modal progress. This ensures that it will eventually let go of the paint mutex. */
785  SetModalProgress(true);
786  /* Only then can we really start, especially by marking the whole screen dirty. Get those other windows hidden!. */
788 
789  if (!VideoDriver::GetInstance()->HasGUI() || !ThreadObject::New(&DoScanNewGRFFiles, callback, NULL)) {
792  DoScanNewGRFFiles(callback);
795  } else {
796  UpdateNewGRFScanStatus(0, NULL);
797  }
798 }
799 
808 const GRFConfig *FindGRFConfig(uint32 grfid, FindGRFConfigMode mode, const uint8 *md5sum, uint32 desired_version)
809 {
810  assert((mode == FGCM_EXACT) != (md5sum == NULL));
811  const GRFConfig *best = NULL;
812  for (const GRFConfig *c = _all_grfs; c != NULL; c = c->next) {
813  /* if md5sum is set, we look for an exact match and continue if not found */
814  if (!c->ident.HasGrfIdentifier(grfid, md5sum)) continue;
815  /* return it, if the exact same newgrf is found, or if we do not care about finding "the best" */
816  if (md5sum != NULL || mode == FGCM_ANY) return c;
817  /* Skip incompatible stuff, unless explicitly allowed */
818  if (mode != FGCM_NEWEST && HasBit(c->flags, GCF_INVALID)) continue;
819  /* check version compatibility */
820  if (mode == FGCM_COMPATIBLE && (c->version < desired_version || c->min_loadable_version > desired_version)) continue;
821  /* remember the newest one as "the best" */
822  if (best == NULL || c->version > best->version) best = c;
823  }
824 
825  return best;
826 }
827 
828 #ifdef ENABLE_NETWORK
829 
831 struct UnknownGRF : public GRFIdentifier {
834 };
835 
853 GRFTextWrapper *FindUnknownGRFName(uint32 grfid, uint8 *md5sum, bool create)
854 {
855  UnknownGRF *grf;
856  static UnknownGRF *unknown_grfs = NULL;
857 
858  for (grf = unknown_grfs; grf != NULL; grf = grf->next) {
859  if (grf->grfid == grfid) {
860  if (memcmp(md5sum, grf->md5sum, sizeof(grf->md5sum)) == 0) return grf->name;
861  }
862  }
863 
864  if (!create) return NULL;
865 
866  grf = CallocT<UnknownGRF>(1);
867  grf->grfid = grfid;
868  grf->next = unknown_grfs;
869  grf->name = new GRFTextWrapper();
870  grf->name->AddRef();
871 
873  memcpy(grf->md5sum, md5sum, sizeof(grf->md5sum));
874 
875  unknown_grfs = grf;
876  return grf->name;
877 }
878 
879 #endif /* ENABLE_NETWORK */
880 
881 
888 GRFConfig *GetGRFConfig(uint32 grfid, uint32 mask)
889 {
890  GRFConfig *c;
891 
892  for (c = _grfconfig; c != NULL; c = c->next) {
893  if ((c->ident.grfid & mask) == (grfid & mask)) return c;
894  }
895 
896  return NULL;
897 }
898 
899 
901 char *GRFBuildParamList(char *dst, const GRFConfig *c, const char *last)
902 {
903  uint i;
904 
905  /* Return an empty string if there are no parameters */
906  if (c->num_params == 0) return strecpy(dst, "", last);
907 
908  for (i = 0; i < c->num_params; i++) {
909  if (i > 0) dst = strecpy(dst, " ", last);
910  dst += seprintf(dst, last, "%d", c->param[i]);
911  }
912  return dst;
913 }
914 
916 static const uint32 OPENTTD_GRAPHICS_BASE_GRF_ID = BSWAP32(0xFF4F5400);
917 
923 {
924  return (this->ident.grfid & 0x00FFFFFF) == OPENTTD_GRAPHICS_BASE_GRF_ID;
925 }
926 
932 const char *GRFConfig::GetTextfile(TextfileType type) const
933 {
934  return ::GetTextfile(type, NEWGRF_DIR, this->filename);
935 }