OpenTTD
newgrf_debug_data.h
Go to the documentation of this file.
1 /* $Id: newgrf_debug_data.h 27654 2016-09-05 19:11:01Z 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 "../newgrf_house.h"
13 #include "../newgrf_engine.h"
14 
15 /* Helper for filling property tables */
16 #define NIP(prop, base, variable, type, name) { name, (ptrdiff_t)cpp_offsetof(base, variable), cpp_sizeof(base, variable), prop, type }
17 #define NIP_END() { NULL, 0, 0, 0, 0 }
18 
19 /* Helper for filling callback tables */
20 #define NIC(cb_id, base, variable, bit) { #cb_id, (ptrdiff_t)cpp_offsetof(base, variable), cpp_sizeof(base, variable), bit, cb_id }
21 #define NIC_END() { NULL, 0, 0, 0, 0 }
22 
23 /* Helper for filling variable tables */
24 #define NIV(var, name) { name, var }
25 #define NIV_END() { NULL, 0 }
26 
27 
28 /*** NewGRF Vehicles ***/
29 
30 #define NICV(cb_id, bit) NIC(cb_id, Engine, info.callback_mask, bit)
31 static const NICallback _nic_vehicles[] = {
46  NIC_END()
47 };
48 
49 
50 static const NIVariable _niv_vehicles[] = {
51  NIV(0x40, "position in consist and length"),
52  NIV(0x41, "position and length of chain of same vehicles"),
53  NIV(0x42, "transported cargo types"),
54  NIV(0x43, "player info"),
55  NIV(0x44, "aircraft info"),
56  NIV(0x45, "curvature info"),
57  NIV(0x46, "motion counter"),
58  NIV(0x47, "vehicle cargo info"),
59  NIV(0x48, "vehicle type info"),
60  NIV(0x49, "year of construction"),
61  NIV(0x4A, "current rail type info"),
62  NIV(0x4B, "long date of last service"),
63  NIV(0x4C, "current max speed"),
64  NIV(0x4D, "position in articulated vehicle"),
65  NIV(0x60, "count vehicle id occurrences"),
66  // 0x61 not useful, since it requires register 0x10F
67  NIV(0x62, "Curvature/position difference to other vehicle"),
68  NIV_END()
69 };
70 
71 class NIHVehicle : public NIHelper {
72  bool IsInspectable(uint index) const { return Vehicle::Get(index)->GetGRF() != NULL; }
73  uint GetParent(uint index) const { const Vehicle *first = Vehicle::Get(index)->First(); return GetInspectWindowNumber(GetGrfSpecFeature(first->type), first->index); }
74  const void *GetInstance(uint index)const { return Vehicle::Get(index); }
75  const void *GetSpec(uint index) const { return Vehicle::Get(index)->GetEngine(); }
76  void SetStringParameters(uint index) const { this->SetSimpleStringParameters(STR_VEHICLE_NAME, index); }
77  uint32 GetGRFID(uint index) const { return Vehicle::Get(index)->GetGRFID(); }
78 
79  /* virtual */ uint Resolve(uint index, uint var, uint param, bool *avail) const
80  {
81  Vehicle *v = Vehicle::Get(index);
83  return ro.GetScope(VSG_SCOPE_SELF)->GetVariable(var, param, avail);
84  }
85 };
86 
87 static const NIFeature _nif_vehicle = {
88  NULL,
89  _nic_vehicles,
90  _niv_vehicles,
91  new NIHVehicle(),
92 };
93 
94 
95 /*** NewGRF station (tiles) ***/
96 
97 #define NICS(cb_id, bit) NIC(cb_id, StationSpec, callback_mask, bit)
98 static const NICallback _nic_stations[] = {
106  NIC_END()
107 };
108 
109 static const NIVariable _niv_stations[] = {
110  NIV(0x40, "platform info and relative position"),
111  NIV(0x41, "platform info and relative position for individually built sections"),
112  NIV(0x42, "terrain and track type"),
113  NIV(0x43, "player info"),
114  NIV(0x44, "path signalling info"),
115  NIV(0x45, "rail continuation info"),
116  NIV(0x46, "platform info and relative position from middle"),
117  NIV(0x47, "platform info and relative position from middle for individually built sections"),
118  NIV(0x48, "bitmask of accepted cargoes"),
119  NIV(0x49, "platform info and relative position of same-direction section"),
120  NIV(0x4A, "current animation frame"),
121  NIV(0x60, "amount of cargo waiting"),
122  NIV(0x61, "time since last cargo pickup"),
123  NIV(0x62, "rating of cargo"),
124  NIV(0x63, "time spent on route"),
125  NIV(0x64, "information about last vehicle picking cargo up"),
126  NIV(0x65, "amount of cargo acceptance"),
127  NIV(0x66, "animation frame of nearby tile"),
128  NIV(0x67, "land info of nearby tiles"),
129  NIV(0x68, "station info of nearby tiles"),
130  NIV(0x69, "information about cargo accepted in the past"),
131  NIV_END()
132 };
133 
134 class NIHStation : public NIHelper {
135  bool IsInspectable(uint index) const { return GetStationSpec(index) != NULL; }
136  uint GetParent(uint index) const { return GetInspectWindowNumber(GSF_FAKE_TOWNS, Station::GetByTile(index)->town->index); }
137  const void *GetInstance(uint index)const { return NULL; }
138  const void *GetSpec(uint index) const { return GetStationSpec(index); }
139  void SetStringParameters(uint index) const { this->SetObjectAtStringParameters(STR_STATION_NAME, GetStationIndex(index), index); }
140  uint32 GetGRFID(uint index) const { return (this->IsInspectable(index)) ? GetStationSpec(index)->grf_prop.grffile->grfid : 0; }
141 
142  /* virtual */ uint Resolve(uint index, uint var, uint param, bool *avail) const
143  {
144  StationResolverObject ro(GetStationSpec(index), Station::GetByTile(index), index);
145  return ro.GetScope(VSG_SCOPE_SELF)->GetVariable(var, param, avail);
146  }
147 };
148 
149 static const NIFeature _nif_station = {
150  NULL,
151  _nic_stations,
152  _niv_stations,
153  new NIHStation(),
154 };
155 
156 
157 /*** NewGRF house tiles ***/
158 
159 #define NICH(cb_id, bit) NIC(cb_id, HouseSpec, callback_mask, bit)
160 static const NICallback _nic_house[] = {
176  NIC_END()
177 };
178 
179 static const NIVariable _niv_house[] = {
180  NIV(0x40, "construction state of tile and pseudo-random value"),
181  NIV(0x41, "age of building in years"),
182  NIV(0x42, "town zone"),
183  NIV(0x43, "terrain type"),
184  NIV(0x44, "building counts"),
185  NIV(0x45, "town expansion bits"),
186  NIV(0x46, "current animation frame"),
187  NIV(0x47, "xy coordinate of the building"),
188  NIV(0x60, "other building counts (old house type)"),
189  NIV(0x61, "other building counts (new house type)"),
190  NIV(0x62, "land info of nearby tiles"),
191  NIV(0x63, "current animation frame of nearby house tile"),
192  NIV(0x64, "cargo acceptance history of nearby stations"),
193  NIV(0x65, "distance of nearest house matching a given criterion"),
194  NIV(0x66, "class and ID of nearby house tile"),
195  NIV(0x67, "GRFID of nearby house tile"),
196  NIV_END()
197 };
198 
199 class NIHHouse : public NIHelper {
200  bool IsInspectable(uint index) const { return HouseSpec::Get(GetHouseType(index))->grf_prop.grffile != NULL; }
201  uint GetParent(uint index) const { return GetInspectWindowNumber(GSF_FAKE_TOWNS, GetTownIndex(index)); }
202  const void *GetInstance(uint index)const { return NULL; }
203  const void *GetSpec(uint index) const { return HouseSpec::Get(GetHouseType(index)); }
204  void SetStringParameters(uint index) const { this->SetObjectAtStringParameters(STR_TOWN_NAME, GetTownIndex(index), index); }
205  uint32 GetGRFID(uint index) const { return (this->IsInspectable(index)) ? HouseSpec::Get(GetHouseType(index))->grf_prop.grffile->grfid : 0; }
206 
207  /* virtual */ uint Resolve(uint index, uint var, uint param, bool *avail) const
208  {
209  HouseResolverObject ro(GetHouseType(index), index, Town::GetByTile(index));
210  return ro.GetScope(VSG_SCOPE_SELF)->GetVariable(var, param, avail);
211  }
212 };
213 
214 static const NIFeature _nif_house = {
215  NULL,
216  _nic_house,
217  _niv_house,
218  new NIHHouse(),
219 };
220 
221 
222 /*** NewGRF industry tiles ***/
223 
224 #define NICIT(cb_id, bit) NIC(cb_id, IndustryTileSpec, callback_mask, bit)
225 static const NICallback _nic_industrytiles[] = {
234  NIC_END()
235 };
236 
237 static const NIVariable _niv_industrytiles[] = {
238  NIV(0x40, "construction state of tile"),
239  NIV(0x41, "ground type"),
240  NIV(0x42, "current town zone in nearest town"),
241  NIV(0x43, "relative position"),
242  NIV(0x44, "animation frame"),
243  NIV(0x60, "land info of nearby tiles"),
244  NIV(0x61, "animation stage of nearby tiles"),
245  NIV(0x62, "get industry or airport tile ID at offset"),
246  NIV_END()
247 };
248 
249 class NIHIndustryTile : public NIHelper {
250  bool IsInspectable(uint index) const { return GetIndustryTileSpec(GetIndustryGfx(index))->grf_prop.grffile != NULL; }
251  uint GetParent(uint index) const { return GetInspectWindowNumber(GSF_INDUSTRIES, GetIndustryIndex(index)); }
252  const void *GetInstance(uint index)const { return NULL; }
253  const void *GetSpec(uint index) const { return GetIndustryTileSpec(GetIndustryGfx(index)); }
254  void SetStringParameters(uint index) const { this->SetObjectAtStringParameters(STR_INDUSTRY_NAME, GetIndustryIndex(index), index); }
255  uint32 GetGRFID(uint index) const { return (this->IsInspectable(index)) ? GetIndustryTileSpec(GetIndustryGfx(index))->grf_prop.grffile->grfid : 0; }
256 
257  /* virtual */ uint Resolve(uint index, uint var, uint param, bool *avail) const
258  {
260  return ro.GetScope(VSG_SCOPE_SELF)->GetVariable(var, param, avail);
261  }
262 };
263 
264 static const NIFeature _nif_industrytile = {
265  NULL,
266  _nic_industrytiles,
267  _niv_industrytiles,
268  new NIHIndustryTile(),
269 };
270 
271 
272 /*** NewGRF industries ***/
273 
274 static const NIProperty _nip_industries[] = {
275  NIP(0x10, Industry, produced_cargo[0], NIT_CARGO, "produced cargo 0"),
276  NIP(0x10, Industry, produced_cargo[1], NIT_CARGO, "produced cargo 1"),
277  NIP(0x11, Industry, accepts_cargo[0], NIT_CARGO, "accepted cargo 0"),
278  NIP(0x11, Industry, accepts_cargo[1], NIT_CARGO, "accepted cargo 1"),
279  NIP(0x11, Industry, accepts_cargo[2], NIT_CARGO, "accepted cargo 2"),
280  NIP_END()
281 };
282 
283 #define NICI(cb_id, bit) NIC(cb_id, IndustrySpec, callback_mask, bit)
284 static const NICallback _nic_industries[] = {
298  NIC_END()
299 };
300 
301 static const NIVariable _niv_industries[] = {
302  NIV(0x40, "waiting cargo 0"),
303  NIV(0x41, "waiting cargo 1"),
304  NIV(0x42, "waiting cargo 2"),
305  NIV(0x43, "distance to closest dry/land tile"),
306  NIV(0x44, "layout number"),
307  NIV(0x45, "player info"),
308  NIV(0x46, "industry construction date"),
309  NIV(0x60, "get industry tile ID at offset"),
310  NIV(0x61, "get random tile bits at offset"),
311  NIV(0x62, "land info of nearby tiles"),
312  NIV(0x63, "animation stage of nearby tiles"),
313  NIV(0x64, "distance on nearest industry with given type"),
314  NIV(0x65, "get town zone and Manhattan distance of closest town"),
315  NIV(0x66, "get square of Euclidean distance of closes town"),
316  NIV(0x67, "count of industry and distance of closest instance"),
317  NIV(0x68, "count of industry and distance of closest instance with layout filter"),
318  NIV_END()
319 };
320 
321 class NIHIndustry : public NIHelper {
322  bool IsInspectable(uint index) const { return GetIndustrySpec(Industry::Get(index)->type)->grf_prop.grffile != NULL; }
323  uint GetParent(uint index) const { return GetInspectWindowNumber(GSF_FAKE_TOWNS, Industry::Get(index)->town->index); }
324  const void *GetInstance(uint index)const { return Industry::Get(index); }
325  const void *GetSpec(uint index) const { return GetIndustrySpec(Industry::Get(index)->type); }
326  void SetStringParameters(uint index) const { this->SetSimpleStringParameters(STR_INDUSTRY_NAME, index); }
327  uint32 GetGRFID(uint index) const { return (this->IsInspectable(index)) ? GetIndustrySpec(Industry::Get(index)->type)->grf_prop.grffile->grfid : 0; }
328 
329  /* virtual */ uint Resolve(uint index, uint var, uint param, bool *avail) const
330  {
331  Industry *i = Industry::Get(index);
333  return ro.GetScope(VSG_SCOPE_SELF)->GetVariable(var, param, avail);
334  }
335 
336  uint GetPSASize(uint index, uint32 grfid) const { return cpp_lengthof(PersistentStorage, storage); }
337 
338  const int32 *GetPSAFirstPosition(uint index, uint32 grfid) const
339  {
340  const Industry *i = (const Industry *)this->GetInstance(index);
341  if (i->psa == NULL) return NULL;
342  return (int32 *)(&i->psa->storage);
343  }
344 };
345 
346 static const NIFeature _nif_industry = {
347  _nip_industries,
348  _nic_industries,
349  _niv_industries,
350  new NIHIndustry(),
351 };
352 
353 
354 /*** NewGRF objects ***/
355 
356 #define NICO(cb_id, bit) NIC(cb_id, ObjectSpec, callback_mask, bit)
357 static const NICallback _nic_objects[] = {
365  NIC_END()
366 };
367 
368 static const NIVariable _niv_objects[] = {
369  NIV(0x40, "relative position"),
370  NIV(0x41, "tile information"),
371  NIV(0x42, "construction date"),
372  NIV(0x43, "animation counter"),
373  NIV(0x44, "object founder"),
374  NIV(0x45, "get town zone and Manhattan distance of closest town"),
375  NIV(0x46, "get square of Euclidean distance of closes town"),
376  NIV(0x47, "colour"),
377  NIV(0x48, "view"),
378  NIV(0x60, "get object ID at offset"),
379  NIV(0x61, "get random tile bits at offset"),
380  NIV(0x62, "land info of nearby tiles"),
381  NIV(0x63, "animation stage of nearby tiles"),
382  NIV(0x64, "distance on nearest object with given type"),
383  NIV_END()
384 };
385 
386 class NIHObject : public NIHelper {
387  bool IsInspectable(uint index) const { return ObjectSpec::GetByTile(index)->grf_prop.grffile != NULL; }
388  uint GetParent(uint index) const { return GetInspectWindowNumber(GSF_FAKE_TOWNS, Object::GetByTile(index)->town->index); }
389  const void *GetInstance(uint index)const { return Object::GetByTile(index); }
390  const void *GetSpec(uint index) const { return ObjectSpec::GetByTile(index); }
391  void SetStringParameters(uint index) const { this->SetObjectAtStringParameters(STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT_OBJECT, INVALID_STRING_ID, index); }
392  uint32 GetGRFID(uint index) const { return (this->IsInspectable(index)) ? ObjectSpec::GetByTile(index)->grf_prop.grffile->grfid : 0; }
393 
394  /* virtual */ uint Resolve(uint index, uint var, uint param, bool *avail) const
395  {
397  return ro.GetScope(VSG_SCOPE_SELF)->GetVariable(var, param, avail);
398  }
399 };
400 
401 static const NIFeature _nif_object = {
402  NULL,
403  _nic_objects,
404  _niv_objects,
405  new NIHObject(),
406 };
407 
408 
409 /*** NewGRF rail types ***/
410 
411 static const NIVariable _niv_railtypes[] = {
412  NIV(0x40, "terrain type"),
413  NIV(0x41, "enhanced tunnels"),
414  NIV(0x42, "level crossing status"),
415  NIV(0x43, "construction date"),
416  NIV(0x44, "town zone"),
417  NIV_END()
418 };
419 
420 class NIHRailType : public NIHelper {
421  bool IsInspectable(uint index) const { return true; }
422  uint GetParent(uint index) const { return UINT32_MAX; }
423  const void *GetInstance(uint index)const { return NULL; }
424  const void *GetSpec(uint index) const { return NULL; }
425  void SetStringParameters(uint index) const { this->SetObjectAtStringParameters(STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT_RAIL_TYPE, INVALID_STRING_ID, index); }
426  uint32 GetGRFID(uint index) const { return 0; }
427 
428  /* virtual */ uint Resolve(uint index, uint var, uint param, bool *avail) const
429  {
430  /* There is no unique GRFFile for the tile. Multiple GRFs can define different parts of the railtype.
431  * However, currently the NewGRF Debug GUI does not display variables depending on the GRF (like 0x7F) anyway. */
432  RailTypeResolverObject ro(NULL, index, TCX_NORMAL, RTSG_END);
433  return ro.GetScope(VSG_SCOPE_SELF)->GetVariable(var, param, avail);
434  }
435 };
436 
437 static const NIFeature _nif_railtype = {
438  NULL,
439  NULL,
440  _niv_railtypes,
441  new NIHRailType(),
442 };
443 
444 
445 /*** NewGRF airport tiles ***/
446 
447 #define NICAT(cb_id, bit) NIC(cb_id, AirportTileSpec, callback_mask, bit)
448 static const NICallback _nic_airporttiles[] = {
453  NIC_END()
454 };
455 
456 class NIHAirportTile : public NIHelper {
457  bool IsInspectable(uint index) const { return AirportTileSpec::Get(GetAirportGfx(index))->grf_prop.grffile != NULL; }
458  uint GetParent(uint index) const { return GetInspectWindowNumber(GSF_FAKE_TOWNS, Station::GetByTile(index)->town->index); }
459  const void *GetInstance(uint index)const { return NULL; }
460  const void *GetSpec(uint index) const { return AirportTileSpec::Get(GetAirportGfx(index)); }
461  void SetStringParameters(uint index) const { this->SetObjectAtStringParameters(STR_STATION_NAME, GetStationIndex(index), index); }
462  uint32 GetGRFID(uint index) const { return (this->IsInspectable(index)) ? AirportTileSpec::Get(GetAirportGfx(index))->grf_prop.grffile->grfid : 0; }
463 
464  /* virtual */ uint Resolve(uint index, uint var, uint param, bool *avail) const
465  {
467  return ro.GetScope(VSG_SCOPE_SELF)->GetVariable(var, param, avail);
468  }
469 };
470 
471 static const NIFeature _nif_airporttile = {
472  NULL,
473  _nic_airporttiles,
474  _niv_industrytiles, // Yes, they share this (at least now)
475  new NIHAirportTile(),
476 };
477 
478 
479 /*** NewGRF towns ***/
480 
481 static const NIVariable _niv_towns[] = {
482  NIV(0x40, "larger town effect on this town"),
483  NIV(0x41, "town index"),
484  NIV(0x82, "population"),
485  NIV(0x94, "zone radius 0"),
486  NIV(0x96, "zone radius 1"),
487  NIV(0x98, "zone radius 2"),
488  NIV(0x9A, "zone radius 3"),
489  NIV(0x9C, "zone radius 4"),
490  NIV(0xB6, "number of buildings"),
491  NIV_END()
492 };
493 
494 class NIHTown : public NIHelper {
495  bool IsInspectable(uint index) const { return Town::IsValidID(index); }
496  uint GetParent(uint index) const { return UINT32_MAX; }
497  const void *GetInstance(uint index)const { return Town::Get(index); }
498  const void *GetSpec(uint index) const { return NULL; }
499  void SetStringParameters(uint index) const { this->SetSimpleStringParameters(STR_TOWN_NAME, index); }
500  uint32 GetGRFID(uint index) const { return 0; }
501  bool PSAWithParameter() const { return true; }
502  uint GetPSASize(uint index, uint32 grfid) const { return cpp_lengthof(PersistentStorage, storage); }
503 
504  /* virtual */ uint Resolve(uint index, uint var, uint param, bool *avail) const
505  {
506  TownResolverObject ro(NULL, Town::Get(index), true);
507  return ro.GetScope(VSG_SCOPE_SELF)->GetVariable(var, param, avail);
508  }
509 
510  const int32 *GetPSAFirstPosition(uint index, uint32 grfid) const
511  {
512  Town *t = Town::Get(index);
513 
514  std::list<PersistentStorage *>::iterator iter;
515  for (iter = t->psa_list.begin(); iter != t->psa_list.end(); iter++) {
516  if ((*iter)->grfid == grfid) return (int32 *)(&(*iter)->storage[0]);
517  }
518 
519  return NULL;
520  }
521 };
522 
523 static const NIFeature _nif_town = {
524  NULL,
525  NULL,
526  _niv_towns,
527  new NIHTown(),
528 };
529 
531 static const NIFeature * const _nifeatures[] = {
532  &_nif_vehicle, // GSF_TRAINS
533  &_nif_vehicle, // GSF_ROADVEHICLES
534  &_nif_vehicle, // GSF_SHIPS
535  &_nif_vehicle, // GSF_AIRCRAFT
536  &_nif_station, // GSF_STATIONS
537  NULL, // GSF_CANALS (no callbacks/action2 implemented)
538  NULL, // GSF_BRIDGES (no callbacks/action2)
539  &_nif_house, // GSF_HOUSES
540  NULL, // GSF_GLOBALVAR (has no "physical" objects)
541  &_nif_industrytile, // GSF_INDUSTRYTILES
542  &_nif_industry, // GSF_INDUSTRIES
543  NULL, // GSF_CARGOES (has no "physical" objects)
544  NULL, // GSF_SOUNDFX (has no "physical" objects)
545  NULL, // GSF_AIRPORTS (feature not implemented)
546  NULL, // GSF_SIGNALS (feature not implemented)
547  &_nif_object, // GSF_OBJECTS
548  &_nif_railtype, // GSF_RAILTYPES
549  &_nif_airporttile, // GSF_AIRPORTTILES
550  &_nif_town, // GSF_FAKE_TOWNS
551 };
552 assert_compile(lengthof(_nifeatures) == GSF_FAKE_END);