--- a/src/newgrf.cpp Sat Jun 02 19:59:29 2007 +0000
+++ b/src/newgrf.cpp Sat Jul 14 19:42:58 2007 +0000
@@ -18,6 +18,7 @@
#include "newgrf.h"
#include "variables.h"
#include "string.h"
+#include "strings.h"
#include "table/strings.h"
#include "bridge.h"
#include "town.h"
@@ -40,7 +41,10 @@
#include "cargotype.h"
#include "industry.h"
#include "newgrf_canal.h"
+#include "table/build_industry.h"
#include "newgrf_commons.h"
+#include "newgrf_townname.h"
+#include "newgrf_industries.h"
/* TTDPatch extended GRF format codec
* (c) Petr Baudis 2004 (GPL'd)
@@ -75,7 +79,7 @@
static byte *_preload_sprite = NULL;
/* Indicates which are the newgrf features currently loaded ingame */
-uint8 _loaded_newgrf_features;
+GRFLoadedFeatures _loaded_newgrf_features;
enum GrfDataType {
GDT_SOUND,
@@ -283,8 +287,6 @@
typedef bool (*VCI_Handler)(uint engine, int numinfo, int prop, byte **buf, int len);
-#define FOR_EACH_OBJECT for (i = 0; i < numinfo; i++)
-
static void dewagonize(int condition, int engine)
{
EngineInfo *ei = &_engine_info[engine];
@@ -302,153 +304,138 @@
static bool RailVehicleChangeInfo(uint engine, int numinfo, int prop, byte **bufp, int len)
{
- EngineInfo *ei = &_engine_info[engine];
- RailVehicleInfo *rvi = &_rail_vehicle_info[engine];
byte *buf = *bufp;
- int i;
bool ret = false;
- switch (prop) {
- case 0x05: // Track type
- FOR_EACH_OBJECT {
+ for (int i = 0; i < numinfo; i++) {
+ EngineInfo *ei = &_engine_info[engine + i];
+ RailVehicleInfo *rvi = &_rail_vehicle_info[engine + i];
+
+ switch (prop) {
+ case 0x05: { // Track type
uint8 tracktype = grf_load_byte(&buf);
switch (tracktype) {
- case 0: rvi[i].railtype = rvi[i].engclass >= 2 ? RAILTYPE_ELECTRIC : RAILTYPE_RAIL; break;
- case 1: rvi[i].railtype = RAILTYPE_MONO; break;
- case 2: rvi[i].railtype = RAILTYPE_MAGLEV; break;
+ case 0: rvi->railtype = rvi->engclass >= 2 ? RAILTYPE_ELECTRIC : RAILTYPE_RAIL; break;
+ case 1: rvi->railtype = RAILTYPE_MONO; break;
+ case 2: rvi->railtype = RAILTYPE_MAGLEV; break;
default:
grfmsg(1, "RailVehicleChangeInfo: Invalid track type %d specified, ignoring", tracktype);
break;
}
- }
- break;
-
- case 0x08: // AI passenger service
- /* @todo missing feature */
- FOR_EACH_OBJECT grf_load_byte(&buf);
- ret = true;
- break;
-
- case 0x09: // Speed (1 unit is 1 kmh)
- FOR_EACH_OBJECT {
+ } break;
+
+ case 0x08: // AI passenger service
+ /** @todo Tells the AI that this engine is designed for
+ * passenger services and shouldn't be used for freight. */
+ grf_load_byte(&buf);
+ ret = true;
+ break;
+
+ case 0x09: { // Speed (1 unit is 1 kmh)
uint16 speed = grf_load_word(&buf);
if (speed == 0xFFFF) speed = 0;
- rvi[i].max_speed = speed;
- }
- break;
-
- case 0x0B: // Power
- FOR_EACH_OBJECT {
+ rvi->max_speed = speed;
+ } break;
+
+ case 0x0B: { // Power
uint16 power = grf_load_word(&buf);
- if (rvi[i].railveh_type == RAILVEH_MULTIHEAD) power /= 2;
-
- rvi[i].power = power;
+ if (rvi->railveh_type == RAILVEH_MULTIHEAD) power /= 2;
+
+ rvi->power = power;
dewagonize(power, engine + i);
- }
- break;
-
- case 0x0D: // Running cost factor
- FOR_EACH_OBJECT {
+ } break;
+
+ case 0x0D: { // Running cost factor
uint8 runcostfact = grf_load_byte(&buf);
- if (rvi[i].railveh_type == RAILVEH_MULTIHEAD) runcostfact /= 2;
-
- rvi[i].running_cost_base = runcostfact;
- }
- break;
-
- case 0x0E: // Running cost base
- FOR_EACH_OBJECT {
+ if (rvi->railveh_type == RAILVEH_MULTIHEAD) runcostfact /= 2;
+
+ rvi->running_cost_base = runcostfact;
+ } break;
+
+ case 0x0E: { // Running cost base
uint32 base = grf_load_dword(&buf);
switch (base) {
- case 0x4C30: rvi[i].running_cost_class = 0; break;
- case 0x4C36: rvi[i].running_cost_class = 1; break;
- case 0x4C3C: rvi[i].running_cost_class = 2; break;
+ case 0x4C30: rvi->running_cost_class = 0; break;
+ case 0x4C36: rvi->running_cost_class = 1; break;
+ case 0x4C3C: rvi->running_cost_class = 2; break;
case 0: break; // Used by wagons
default:
grfmsg(1, "RailVehicleChangeInfo: Unsupported running cost base 0x%04X, ignoring", base);
break;
}
- }
- break;
-
- case 0x12: // Sprite ID
- FOR_EACH_OBJECT {
+ } break;
+
+ case 0x12: { // Sprite ID
uint8 spriteid = grf_load_byte(&buf);
/* TTD sprite IDs point to a location in a 16bit array, but we use it
* as an array index, so we need it to be half the original value. */
if (spriteid < 0xFD) spriteid >>= 1;
- rvi[i].image_index = spriteid;
- }
- break;
-
- case 0x13: // Dual-headed
- FOR_EACH_OBJECT {
+ rvi->image_index = spriteid;
+ } break;
+
+ case 0x13: { // Dual-headed
uint8 dual = grf_load_byte(&buf);
if (dual != 0) {
- if (rvi[i].railveh_type != RAILVEH_MULTIHEAD) {
+ if (rvi->railveh_type != RAILVEH_MULTIHEAD) {
// adjust power and running cost if needed
- rvi[i].power /= 2;
- rvi[i].running_cost_base /= 2;
+ rvi->power /= 2;
+ rvi->running_cost_base /= 2;
}
- rvi[i].railveh_type = RAILVEH_MULTIHEAD;
+ rvi->railveh_type = RAILVEH_MULTIHEAD;
} else {
- if (rvi[i].railveh_type == RAILVEH_MULTIHEAD) {
+ if (rvi->railveh_type == RAILVEH_MULTIHEAD) {
// adjust power and running cost if needed
- rvi[i].power *= 2;
- rvi[i].running_cost_base *= 2;
+ rvi->power *= 2;
+ rvi->running_cost_base *= 2;
}
- rvi[i].railveh_type = rvi[i].power == 0 ?
+ rvi->railveh_type = rvi->power == 0 ?
RAILVEH_WAGON : RAILVEH_SINGLEHEAD;
}
- }
- break;
-
- case 0x14: // Cargo capacity
- FOR_EACH_OBJECT rvi[i].capacity = grf_load_byte(&buf);
- break;
-
- case 0x15: // Cargo type
- FOR_EACH_OBJECT {
+ } break;
+
+ case 0x14: // Cargo capacity
+ rvi->capacity = grf_load_byte(&buf);
+ break;
+
+ case 0x15: { // Cargo type
uint8 ctype = grf_load_byte(&buf);
if (ctype < NUM_CARGO && HASBIT(_cargo_mask, ctype)) {
- rvi[i].cargo_type = ctype;
+ rvi->cargo_type = ctype;
} else {
- rvi[i].cargo_type = CT_INVALID;
+ rvi->cargo_type = CT_INVALID;
grfmsg(2, "RailVehicleChangeInfo: Invalid cargo type %d, using first refittable", ctype);
}
- }
- break;
-
- case 0x16: // Weight
- FOR_EACH_OBJECT SB(rvi[i].weight, 0, 8, grf_load_byte(&buf));
- break;
-
- case 0x17: // Cost factor
- FOR_EACH_OBJECT rvi[i].base_cost = grf_load_byte(&buf);
- break;
-
- case 0x18: // AI rank
- FOR_EACH_OBJECT rvi[i].ai_rank = grf_load_byte(&buf);
- break;
-
- case 0x19: // Engine traction type
- /* What do the individual numbers mean?
- * 0x00 .. 0x07: Steam
- * 0x08 .. 0x27: Diesel
- * 0x28 .. 0x31: Electric
- * 0x32 .. 0x37: Monorail
- * 0x38 .. 0x41: Maglev
- */
- FOR_EACH_OBJECT {
+ } break;
+
+ case 0x16: // Weight
+ SB(rvi->weight, 0, 8, grf_load_byte(&buf));
+ break;
+
+ case 0x17: // Cost factor
+ rvi->base_cost = grf_load_byte(&buf);
+ break;
+
+ case 0x18: // AI rank
+ rvi->ai_rank = grf_load_byte(&buf);
+ break;
+
+ case 0x19: { // Engine traction type
+ /* What do the individual numbers mean?
+ * 0x00 .. 0x07: Steam
+ * 0x08 .. 0x27: Diesel
+ * 0x28 .. 0x31: Electric
+ * 0x32 .. 0x37: Monorail
+ * 0x38 .. 0x41: Maglev
+ */
uint8 traction = grf_load_byte(&buf);
EngineClass engclass;
@@ -465,15 +452,13 @@
} else {
break;
}
- if (rvi[i].railtype == RAILTYPE_RAIL && engclass >= EC_ELECTRIC) rvi[i].railtype = RAILTYPE_ELECTRIC;
- if (rvi[i].railtype == RAILTYPE_ELECTRIC && engclass < EC_ELECTRIC) rvi[i].railtype = RAILTYPE_RAIL;
-
- rvi[i].engclass = engclass;
- }
- break;
-
- case 0x1A: // Alter purchase list sort order
- FOR_EACH_OBJECT {
+ if (rvi->railtype == RAILTYPE_RAIL && engclass >= EC_ELECTRIC) rvi->railtype = RAILTYPE_ELECTRIC;
+ if (rvi->railtype == RAILTYPE_ELECTRIC && engclass < EC_ELECTRIC) rvi->railtype = RAILTYPE_RAIL;
+
+ rvi->engclass = engclass;
+ } break;
+
+ case 0x1A: { // Alter purchase list sort order
EngineID pos = grf_load_byte(&buf);
if (pos < NUM_TRAIN_ENGINES) {
@@ -481,122 +466,118 @@
} else {
grfmsg(2, "RailVehicleChangeInfo: Invalid train engine ID %d, ignoring", pos);
}
- }
- break;
-
- case 0x1B: // Powered wagons power bonus
- FOR_EACH_OBJECT rvi[i].pow_wag_power = grf_load_word(&buf);
- break;
-
- case 0x1C: // Refit cost
- FOR_EACH_OBJECT ei[i].refit_cost = grf_load_byte(&buf);
- break;
-
- case 0x1D: // Refit cargo
- FOR_EACH_OBJECT ei[i].refit_mask = grf_load_dword(&buf);
- break;
-
- case 0x1E: // Callback
- FOR_EACH_OBJECT ei[i].callbackmask = grf_load_byte(&buf);
- break;
-
- case 0x1F: // Tractive effort coefficient
- FOR_EACH_OBJECT rvi[i].tractive_effort = grf_load_byte(&buf);
- break;
-
- case 0x21: // Shorter vehicle
- FOR_EACH_OBJECT rvi[i].shorten_factor = grf_load_byte(&buf);
- break;
-
- case 0x22: // Visual effect
- /* see note in engine.h about rvi->visual_effect */
- FOR_EACH_OBJECT rvi[i].visual_effect = grf_load_byte(&buf);
- break;
-
- case 0x23: // Powered wagons weight bonus
- FOR_EACH_OBJECT rvi[i].pow_wag_weight = grf_load_byte(&buf);
- break;
-
- case 0x24: // High byte of vehicle weight
- FOR_EACH_OBJECT {
+ } break;
+
+ case 0x1B: // Powered wagons power bonus
+ rvi->pow_wag_power = grf_load_word(&buf);
+ break;
+
+ case 0x1C: // Refit cost
+ ei->refit_cost = grf_load_byte(&buf);
+ break;
+
+ case 0x1D: // Refit cargo
+ ei->refit_mask = grf_load_dword(&buf);
+ break;
+
+ case 0x1E: // Callback
+ ei->callbackmask = grf_load_byte(&buf);
+ break;
+
+ case 0x1F: // Tractive effort coefficient
+ rvi->tractive_effort = grf_load_byte(&buf);
+ break;
+
+ case 0x21: // Shorter vehicle
+ rvi->shorten_factor = grf_load_byte(&buf);
+ break;
+
+ case 0x22: // Visual effect
+ /** @see note in engine.h about rvi->visual_effect */
+ rvi->visual_effect = grf_load_byte(&buf);
+ break;
+
+ case 0x23: // Powered wagons weight bonus
+ rvi->pow_wag_weight = grf_load_byte(&buf);
+ break;
+
+ case 0x24: { // High byte of vehicle weight
byte weight = grf_load_byte(&buf);
if (weight > 4) {
grfmsg(2, "RailVehicleChangeInfo: Nonsensical weight of %d tons, ignoring", weight << 8);
} else {
- SB(rvi[i].weight, 8, 8, weight);
+ SB(rvi->weight, 8, 8, weight);
}
- }
- break;
-
- case 0x25: // User-defined bit mask to set when checking veh. var. 42
- FOR_EACH_OBJECT rvi[i].user_def_data = grf_load_byte(&buf);
- break;
-
- case 0x26: // Retire vehicle early
- FOR_EACH_OBJECT ei[i].retire_early = grf_load_byte(&buf);
- break;
-
- case 0x27: // Miscellaneous flags
- FOR_EACH_OBJECT {
- ei[i].misc_flags = grf_load_byte(&buf);
- if (HASBIT(ei[i].misc_flags, EF_USES_2CC)) SETBIT(_loaded_newgrf_features, GRFLOADED_2CC);
- }
- break;
-
- case 0x28: // Cargo classes allowed
- FOR_EACH_OBJECT cargo_allowed[engine + i] = grf_load_word(&buf);
- break;
-
- case 0x29: // Cargo classes disallowed
- FOR_EACH_OBJECT cargo_disallowed[engine + i] = grf_load_word(&buf);
- break;
-
- case 0x2A: // Long format introduction date (days since year 0)
- FOR_EACH_OBJECT ei[i].base_intro = grf_load_dword(&buf);
- break;
-
- /* @todo air drag and retire vehicle early
- * Fall-through for unimplemented one byte long properties. */
- case 0x20: // Air drag
- FOR_EACH_OBJECT grf_load_byte(&buf);
- ret = true;
- break;
-
- default:
- ret = true;
- break;
+ } break;
+
+ case 0x25: // User-defined bit mask to set when checking veh. var. 42
+ rvi->user_def_data = grf_load_byte(&buf);
+ break;
+
+ case 0x26: // Retire vehicle early
+ ei->retire_early = grf_load_byte(&buf);
+ break;
+
+ case 0x27: // Miscellaneous flags
+ ei->misc_flags = grf_load_byte(&buf);
+ _loaded_newgrf_features.has_2CC |= HASBIT(ei->misc_flags, EF_USES_2CC);
+ break;
+
+ case 0x28: // Cargo classes allowed
+ cargo_allowed[engine + i] = grf_load_word(&buf);
+ break;
+
+ case 0x29: // Cargo classes disallowed
+ cargo_disallowed[engine + i] = grf_load_word(&buf);
+ break;
+
+ case 0x2A: // Long format introduction date (days since year 0)
+ ei->base_intro = grf_load_dword(&buf);
+ break;
+
+ case 0x20: // Air drag
+ /** @todo Air drag for trains. */
+ grf_load_byte(&buf);
+ ret = true;
+ break;
+
+ default:
+ ret = true;
+ break;
+ }
}
+
*bufp = buf;
return ret;
}
static bool RoadVehicleChangeInfo(uint engine, int numinfo, int prop, byte **bufp, int len)
{
- EngineInfo *ei = &_engine_info[ROAD_ENGINES_INDEX + engine];
- RoadVehicleInfo *rvi = &_road_vehicle_info[engine];
byte *buf = *bufp;
- int i;
bool ret = false;
- switch (prop) {
- case 0x08: // Speed (1 unit is 0.5 kmh)
- FOR_EACH_OBJECT rvi[i].max_speed = grf_load_byte(&buf);
- break;
-
- case 0x09: // Running cost factor
- FOR_EACH_OBJECT rvi[i].running_cost = grf_load_byte(&buf);
- break;
-
- case 0x0A: // Running cost base
- /* @todo : I have no idea. --pasky
- * I THINK it is used for overriding the base cost of all road vehicle (_price.roadveh_base) --belugas */
- FOR_EACH_OBJECT grf_load_dword(&buf);
- ret = true;
- break;
-
- case 0x0E: // Sprite ID
- FOR_EACH_OBJECT {
+ for (int i = 0; i < numinfo; i++) {
+ EngineInfo *ei = &_engine_info[ROAD_ENGINES_INDEX + engine + i];
+ RoadVehicleInfo *rvi = &_road_vehicle_info[engine + i];
+
+ switch (prop) {
+ case 0x08: // Speed (1 unit is 0.5 kmh)
+ rvi->max_speed = grf_load_byte(&buf);
+ break;
+
+ case 0x09: // Running cost factor
+ rvi->running_cost = grf_load_byte(&buf);
+ break;
+
+ case 0x0A: // Running cost base
+ /** @todo : I have no idea. --pasky
+ * I THINK it is used for overriding the base cost of all road vehicle (_price.roadveh_base) --belugas */
+ grf_load_dword(&buf);
+ ret = true;
+ break;
+
+ case 0x0E: { // Sprite ID
uint8 spriteid = grf_load_byte(&buf);
/* cars have different custom id in the GRF file */
@@ -604,90 +585,86 @@
if (spriteid < 0xFD) spriteid >>= 1;
- rvi[i].image_index = spriteid;
- }
- break;
-
- case 0x0F: // Cargo capacity
- FOR_EACH_OBJECT rvi[i].capacity = grf_load_byte(&buf);
- break;
-
- case 0x10: // Cargo type
- FOR_EACH_OBJECT {
+ rvi->image_index = spriteid;
+ } break;
+
+ case 0x0F: // Cargo capacity
+ rvi->capacity = grf_load_byte(&buf);
+ break;
+
+ case 0x10: { // Cargo type
uint8 cargo = grf_load_byte(&buf);
if (cargo < NUM_CARGO && HASBIT(_cargo_mask, cargo)) {
- rvi[i].cargo_type = cargo;
+ rvi->cargo_type = cargo;
} else {
- rvi[i].cargo_type = CT_INVALID;
+ rvi->cargo_type = CT_INVALID;
grfmsg(2, "RoadVehicleChangeInfo: Invalid cargo type %d, using first refittable", cargo);
}
- }
- break;
-
- case 0x11: // Cost factor
- FOR_EACH_OBJECT rvi[i].base_cost = grf_load_byte(&buf); // ?? is it base_cost?
- break;
-
- case 0x12: // SFX
- FOR_EACH_OBJECT rvi[i].sfx = (SoundFx)grf_load_byte(&buf);
- break;
-
- case 0x13: // Power in 10hp
- case 0x14: // Weight in 1/4 tons
- case 0x15: // Speed in mph*0.8
- /* TODO: Support for road vehicles realistic power
- * computations (called rvpower in TTDPatch) is just
- * missing in OTTD yet. --pasky */
- FOR_EACH_OBJECT grf_load_byte(&buf);
- ret = true;
- break;
-
- case 0x16: // Cargos available for refitting
- FOR_EACH_OBJECT ei[i].refit_mask = grf_load_dword(&buf);
- break;
-
- case 0x17: // Callback mask
- FOR_EACH_OBJECT ei[i].callbackmask = grf_load_byte(&buf);
- break;
-
- case 0x1A: // Refit cost
- FOR_EACH_OBJECT ei[i].refit_cost = grf_load_byte(&buf);
- break;
-
- case 0x1B: // Retire vehicle early
- FOR_EACH_OBJECT ei[i].retire_early = grf_load_byte(&buf);
- break;
-
- case 0x1C: // Miscellaneous flags
- FOR_EACH_OBJECT {
- ei[i].misc_flags = grf_load_byte(&buf);
- if (HASBIT(ei[i].misc_flags, EF_USES_2CC)) SETBIT(_loaded_newgrf_features, GRFLOADED_2CC);
- }
- break;
-
- case 0x1D: // Cargo classes allowed
- FOR_EACH_OBJECT cargo_allowed[ROAD_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
- break;
-
- case 0x1E: // Cargo classes disallowed
- FOR_EACH_OBJECT cargo_disallowed[ROAD_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
- break;
-
- case 0x1F: // Long format introduction date (days since year 0)
- FOR_EACH_OBJECT ei[i].base_intro = grf_load_dword(&buf);
- break;
-
- case 0x18: // Tractive effort
- case 0x19: // Air drag
- /* @todo */
- FOR_EACH_OBJECT grf_load_byte(&buf);
- ret = true;
- break;
-
- default:
- ret = true;
- break;
+ } break;
+
+ case 0x11: // Cost factor
+ rvi->base_cost = grf_load_byte(&buf); // ?? is it base_cost?
+ break;
+
+ case 0x12: // SFX
+ rvi->sfx = (SoundFx)grf_load_byte(&buf);
+ break;
+
+ case 0x13: // Power in 10hp
+ case 0x14: // Weight in 1/4 tons
+ case 0x15: // Speed in mph*0.8
+ /** @todo Support for road vehicles realistic power
+ * computations (called rvpower in TTDPatch) is just
+ * missing in OTTD yet. --pasky */
+ grf_load_byte(&buf);
+ ret = true;
+ break;
+
+ case 0x16: // Cargos available for refitting
+ ei->refit_mask = grf_load_dword(&buf);
+ break;
+
+ case 0x17: // Callback mask
+ ei->callbackmask = grf_load_byte(&buf);
+ break;
+
+ case 0x1A: // Refit cost
+ ei->refit_cost = grf_load_byte(&buf);
+ break;
+
+ case 0x1B: // Retire vehicle early
+ ei->retire_early = grf_load_byte(&buf);
+ break;
+
+ case 0x1C: // Miscellaneous flags
+ ei->misc_flags = grf_load_byte(&buf);
+ _loaded_newgrf_features.has_2CC |= HASBIT(ei->misc_flags, EF_USES_2CC);
+ break;
+
+ case 0x1D: // Cargo classes allowed
+ cargo_allowed[ROAD_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
+ break;
+
+ case 0x1E: // Cargo classes disallowed
+ cargo_disallowed[ROAD_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
+ break;
+
+ case 0x1F: // Long format introduction date (days since year 0)
+ ei->base_intro = grf_load_dword(&buf);
+ break;
+
+ case 0x18: // Tractive effort
+ case 0x19: // Air drag
+ /** @todo Tractive effort and air drag for road vehicles. */
+ grf_load_byte(&buf);
+ ret = true;
+ break;
+
+ default:
+ ret = true;
+ break;
+ }
}
*bufp = buf;
@@ -696,16 +673,15 @@
static bool ShipVehicleChangeInfo(uint engine, int numinfo, int prop, byte **bufp, int len)
{
- EngineInfo *ei = &_engine_info[SHIP_ENGINES_INDEX + engine];
- ShipVehicleInfo *svi = &_ship_vehicle_info[engine];
byte *buf = *bufp;
- int i;
bool ret = false;
- //printf("e %x prop %x?\n", engine, prop);
- switch (prop) {
- case 0x08: // Sprite ID
- FOR_EACH_OBJECT {
+ for (int i = 0; i < numinfo; i++) {
+ EngineInfo *ei = &_engine_info[SHIP_ENGINES_INDEX + engine + i];
+ ShipVehicleInfo *svi = &_ship_vehicle_info[engine + i];
+
+ switch (prop) {
+ case 0x08: { // Sprite ID
uint8 spriteid = grf_load_byte(&buf);
/* ships have different custom id in the GRF file */
@@ -713,92 +689,88 @@
if (spriteid < 0xFD) spriteid >>= 1;
- svi[i].image_index = spriteid;
- }
- break;
-
- case 0x09: // Refittable
- FOR_EACH_OBJECT svi[i].refittable = (grf_load_byte(&buf) != 0);
- break;
-
- case 0x0A: // Cost factor
- FOR_EACH_OBJECT svi[i].base_cost = grf_load_byte(&buf); // ?? is it base_cost?
- break;
-
- case 0x0B: // Speed (1 unit is 0.5 kmh)
- FOR_EACH_OBJECT svi[i].max_speed = grf_load_byte(&buf);
- break;
-
- case 0x0C: // Cargo type
- FOR_EACH_OBJECT {
+ svi->image_index = spriteid;
+ } break;
+
+ case 0x09: // Refittable
+ svi->refittable = (grf_load_byte(&buf) != 0);
+ break;
+
+ case 0x0A: // Cost factor
+ svi->base_cost = grf_load_byte(&buf); // ?? is it base_cost?
+ break;
+
+ case 0x0B: // Speed (1 unit is 0.5 kmh)
+ svi->max_speed = grf_load_byte(&buf);
+ break;
+
+ case 0x0C: { // Cargo type
uint8 cargo = grf_load_byte(&buf);
if (cargo < NUM_CARGO && HASBIT(_cargo_mask, cargo)) {
- svi[i].cargo_type = cargo;
+ svi->cargo_type = cargo;
} else {
- svi[i].cargo_type = CT_INVALID;
+ svi->cargo_type = CT_INVALID;
grfmsg(2, "ShipVehicleChangeInfo: Invalid cargo type %d, using first refittable", cargo);
}
- }
- break;
-
- case 0x0D: // Cargo capacity
- FOR_EACH_OBJECT svi[i].capacity = grf_load_word(&buf);
- break;
-
- case 0x0F: // Running cost factor
- FOR_EACH_OBJECT svi[i].running_cost = grf_load_byte(&buf);
- break;
-
- case 0x10: // SFX
- FOR_EACH_OBJECT svi[i].sfx = (SoundFx)grf_load_byte(&buf);
- break;
-
- case 0x11: // Cargos available for refitting
- FOR_EACH_OBJECT ei[i].refit_mask = grf_load_dword(&buf);
- break;
-
- case 0x12: // Callback mask
- FOR_EACH_OBJECT ei[i].callbackmask = grf_load_byte(&buf);
- break;
-
- case 0x13: // Refit cost
- FOR_EACH_OBJECT ei[i].refit_cost = grf_load_byte(&buf);
- break;
-
- case 0x16: // Retire vehicle early
- FOR_EACH_OBJECT ei[i].retire_early = grf_load_byte(&buf);
- break;
-
- case 0x17: // Miscellaneous flags
- FOR_EACH_OBJECT {
- ei[i].misc_flags = grf_load_byte(&buf);
- if (HASBIT(ei[i].misc_flags, EF_USES_2CC)) SETBIT(_loaded_newgrf_features, GRFLOADED_2CC);
- }
- break;
-
- case 0x18: // Cargo classes allowed
- FOR_EACH_OBJECT cargo_allowed[SHIP_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
- break;
-
- case 0x19: // Cargo classes disallowed
- FOR_EACH_OBJECT cargo_disallowed[SHIP_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
- break;
-
- case 0x1A: // Long format introduction date (days since year 0)
- FOR_EACH_OBJECT ei[i].base_intro = grf_load_dword(&buf);
- break;
-
- case 0x14: // Ocean speed fraction
- case 0x15: // Canal speed fraction
- /* @todo */
- FOR_EACH_OBJECT grf_load_byte(&buf);
- ret = true;
- break;
-
- default:
- ret = true;
- break;
+ } break;
+
+ case 0x0D: // Cargo capacity
+ svi->capacity = grf_load_word(&buf);
+ break;
+
+ case 0x0F: // Running cost factor
+ svi->running_cost = grf_load_byte(&buf);
+ break;
+
+ case 0x10: // SFX
+ svi->sfx = (SoundFx)grf_load_byte(&buf);
+ break;
+
+ case 0x11: // Cargos available for refitting
+ ei->refit_mask = grf_load_dword(&buf);
+ break;
+
+ case 0x12: // Callback mask
+ ei->callbackmask = grf_load_byte(&buf);
+ break;
+
+ case 0x13: // Refit cost
+ ei->refit_cost = grf_load_byte(&buf);
+ break;
+
+ case 0x16: // Retire vehicle early
+ ei->retire_early = grf_load_byte(&buf);
+ break;
+
+ case 0x17: // Miscellaneous flags
+ ei->misc_flags = grf_load_byte(&buf);
+ _loaded_newgrf_features.has_2CC |= HASBIT(ei->misc_flags, EF_USES_2CC);
+ break;
+
+ case 0x18: // Cargo classes allowed
+ cargo_allowed[SHIP_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
+ break;
+
+ case 0x19: // Cargo classes disallowed
+ cargo_disallowed[SHIP_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
+ break;
+
+ case 0x1A: // Long format introduction date (days since year 0)
+ ei->base_intro = grf_load_dword(&buf);
+ break;
+
+ case 0x14: // Ocean speed fraction
+ case 0x15: // Canal speed fraction
+ /** @todo Speed fractions for ships on oceans and canals */
+ grf_load_byte(&buf);
+ ret = true;
+ break;
+
+ default:
+ ret = true;
+ break;
+ }
}
*bufp = buf;
@@ -807,16 +779,15 @@
static bool AircraftVehicleChangeInfo(uint engine, int numinfo, int prop, byte **bufp, int len)
{
- EngineInfo *ei = &_engine_info[AIRCRAFT_ENGINES_INDEX + engine];
- AircraftVehicleInfo *avi = &_aircraft_vehicle_info[engine];
byte *buf = *bufp;
- int i;
bool ret = false;
- //printf("e %x prop %x?\n", engine, prop);
- switch (prop) {
- case 0x08: // Sprite ID
- FOR_EACH_OBJECT {
+ for (int i = 0; i < numinfo; i++) {
+ EngineInfo *ei = &_engine_info[AIRCRAFT_ENGINES_INDEX + engine + i];
+ AircraftVehicleInfo *avi = &_aircraft_vehicle_info[engine + i];
+
+ switch (prop) {
+ case 0x08: { // Sprite ID
uint8 spriteid = grf_load_byte(&buf);
/* aircraft have different custom id in the GRF file */
@@ -824,90 +795,86 @@
if (spriteid < 0xFD) spriteid >>= 1;
- avi[i].image_index = spriteid;
- }
- break;
-
- case 0x09: // Helicopter
- FOR_EACH_OBJECT {
+ avi->image_index = spriteid;
+ } break;
+
+ case 0x09: // Helicopter
if (grf_load_byte(&buf) == 0) {
- avi[i].subtype = AIR_HELI;
+ avi->subtype = AIR_HELI;
} else {
- SB(avi[i].subtype, 0, 1, 1); // AIR_CTOL
+ SB(avi->subtype, 0, 1, 1); // AIR_CTOL
}
- }
- break;
-
- case 0x0A: // Large
- FOR_EACH_OBJECT SB(avi[i].subtype, 1, 1, (grf_load_byte(&buf) != 0 ? 1 : 0)); // AIR_FAST
- break;
-
- case 0x0B: // Cost factor
- FOR_EACH_OBJECT avi[i].base_cost = grf_load_byte(&buf); // ?? is it base_cost?
- break;
-
- case 0x0C: // Speed (1 unit is 8 mph, we translate to 1 unit is 1 km/h)
- FOR_EACH_OBJECT avi[i].max_speed = (grf_load_byte(&buf) * 129) / 10;
- break;
-
- case 0x0D: // Acceleration
- FOR_EACH_OBJECT avi[i].acceleration = (grf_load_byte(&buf) * 129) / 10;
- break;
-
- case 0x0E: // Running cost factor
- FOR_EACH_OBJECT avi[i].running_cost = grf_load_byte(&buf);
- break;
-
- case 0x0F: // Passenger capacity
- FOR_EACH_OBJECT avi[i].passenger_capacity = grf_load_word(&buf);
- break;
-
- case 0x11: // Mail capacity
- FOR_EACH_OBJECT avi[i].mail_capacity = grf_load_byte(&buf);
- break;
-
- case 0x12: // SFX
- FOR_EACH_OBJECT avi[i].sfx = (SoundFx)grf_load_byte(&buf);
- break;
-
- case 0x13: // Cargos available for refitting
- FOR_EACH_OBJECT ei[i].refit_mask = grf_load_dword(&buf);
- break;
-
- case 0x14: // Callback mask
- FOR_EACH_OBJECT ei[i].callbackmask = grf_load_byte(&buf);
- break;
-
- case 0x15: // Refit cost
- FOR_EACH_OBJECT ei[i].refit_cost = grf_load_byte(&buf);
- break;
-
- case 0x16: // Retire vehicle early
- FOR_EACH_OBJECT ei[i].retire_early = grf_load_byte(&buf);
- break;
-
- case 0x17: // Miscellaneous flags
- FOR_EACH_OBJECT {
- ei[i].misc_flags = grf_load_byte(&buf);
- if (HASBIT(ei[i].misc_flags, EF_USES_2CC)) SETBIT(_loaded_newgrf_features, GRFLOADED_2CC);
- }
- break;
-
- case 0x18: // Cargo classes allowed
- FOR_EACH_OBJECT cargo_allowed[AIRCRAFT_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
- break;
-
- case 0x19: // Cargo classes disallowed
- FOR_EACH_OBJECT cargo_disallowed[AIRCRAFT_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
- break;
-
- case 0x1A: // Long format introduction date (days since year 0)
- FOR_EACH_OBJECT ei[i].base_intro = grf_load_dword(&buf);
- break;
-
- default:
- ret = true;
- break;
+ break;
+
+ case 0x0A: // Large
+ SB(avi->subtype, 1, 1, (grf_load_byte(&buf) != 0 ? 1 : 0)); // AIR_FAST
+ break;
+
+ case 0x0B: // Cost factor
+ avi->base_cost = grf_load_byte(&buf); // ?? is it base_cost?
+ break;
+
+ case 0x0C: // Speed (1 unit is 8 mph, we translate to 1 unit is 1 km/h)
+ avi->max_speed = (grf_load_byte(&buf) * 129) / 10;
+ break;
+
+ case 0x0D: // Acceleration
+ avi->acceleration = (grf_load_byte(&buf) * 129) / 10;
+ break;
+
+ case 0x0E: // Running cost factor
+ avi->running_cost = grf_load_byte(&buf);
+ break;
+
+ case 0x0F: // Passenger capacity
+ avi->passenger_capacity = grf_load_word(&buf);
+ break;
+
+ case 0x11: // Mail capacity
+ avi->mail_capacity = grf_load_byte(&buf);
+ break;
+
+ case 0x12: // SFX
+ avi->sfx = (SoundFx)grf_load_byte(&buf);
+ break;
+
+ case 0x13: // Cargos available for refitting
+ ei->refit_mask = grf_load_dword(&buf);
+ break;
+
+ case 0x14: // Callback mask
+ ei->callbackmask = grf_load_byte(&buf);
+ break;
+
+ case 0x15: // Refit cost
+ ei->refit_cost = grf_load_byte(&buf);
+ break;
+
+ case 0x16: // Retire vehicle early
+ ei->retire_early = grf_load_byte(&buf);
+ break;
+
+ case 0x17: // Miscellaneous flags
+ ei->misc_flags = grf_load_byte(&buf);
+ _loaded_newgrf_features.has_2CC |= HASBIT(ei->misc_flags, EF_USES_2CC);
+ break;
+
+ case 0x18: // Cargo classes allowed
+ cargo_allowed[AIRCRAFT_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
+ break;
+
+ case 0x19: // Cargo classes disallowed
+ cargo_disallowed[AIRCRAFT_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
+ break;
+
+ case 0x1A: // Long format introduction date (days since year 0)
+ ei->base_intro = grf_load_dword(&buf);
+ break;
+
+ default:
+ ret = true;
+ break;
+ }
}
*bufp = buf;
@@ -916,9 +883,7 @@
static bool StationChangeInfo(uint stid, int numinfo, int prop, byte **bufp, int len)
{
- StationSpec **statspec;
byte *buf = *bufp;
- int i;
bool ret = false;
if (stid + numinfo > MAX_STATIONS) {
@@ -929,34 +894,28 @@
/* Allocate station specs if necessary */
if (_cur_grffile->stations == NULL) _cur_grffile->stations = CallocT<StationSpec*>(MAX_STATIONS);
- statspec = &_cur_grffile->stations[stid];
-
- if (prop != 0x08) {
- /* Check that all stations we are modifying are defined. */
- FOR_EACH_OBJECT {
- if (statspec[i] == NULL) {
- grfmsg(2, "StationChangeInfo: Attempt to modify undefined station %u, ignoring", stid + i);
- return false;
- }
+ for (int i = 0; i < numinfo; i++) {
+ StationSpec *statspec = _cur_grffile->stations[stid + i];
+
+ /* Check that the station we are modifying is defined. */
+ if (statspec == NULL && prop != 0x08) {
+ grfmsg(2, "StationChangeInfo: Attempt to modify undefined station %u, ignoring", stid + i);
+ continue;
}
- }
-
- switch (prop) {
- case 0x08: // Class ID
- FOR_EACH_OBJECT {
+
+ switch (prop) {
+ case 0x08: { // Class ID
+ StationSpec **spec = &_cur_grffile->stations[stid + i];
+
/* Property 0x08 is special; it is where the station is allocated */
- if (statspec[i] == NULL) statspec[i] = CallocT<StationSpec>(1);
+ if (*spec == NULL) *spec = CallocT<StationSpec>(1);
/* Swap classid because we read it in BE meaning WAYP or DFLT */
uint32 classid = grf_load_dword(&buf);
- statspec[i]->sclass = AllocateStationClass(BSWAP32(classid));
- }
- break;
-
- case 0x09: // Define sprite layout
- FOR_EACH_OBJECT {
- StationSpec *statspec = _cur_grffile->stations[stid + i];
-
+ (*spec)->sclass = AllocateStationClass(BSWAP32(classid));
+ } break;
+
+ case 0x09: // Define sprite layout
statspec->tiles = grf_load_extended(&buf);
statspec->renderdata = CallocT<DrawTileSprites>(statspec->tiles);
statspec->copied_renderdata = false;
@@ -1007,37 +966,30 @@
}
}
}
- }
- break;
-
- case 0x0A: // Copy sprite layout
- FOR_EACH_OBJECT {
- StationSpec *statspec = _cur_grffile->stations[stid + i];
+ break;
+
+ case 0x0A: { // Copy sprite layout
byte srcid = grf_load_byte(&buf);
const StationSpec *srcstatspec = _cur_grffile->stations[srcid];
statspec->tiles = srcstatspec->tiles;
statspec->renderdata = srcstatspec->renderdata;
statspec->copied_renderdata = true;
- }
- break;
-
- case 0x0B: // Callback mask
- FOR_EACH_OBJECT statspec[i]->callbackmask = grf_load_byte(&buf);
- break;
-
- case 0x0C: // Disallowed number of platforms
- FOR_EACH_OBJECT statspec[i]->disallowed_platforms = grf_load_byte(&buf);
- break;
-
- case 0x0D: // Disallowed platform lengths
- FOR_EACH_OBJECT statspec[i]->disallowed_lengths = grf_load_byte(&buf);
- break;
-
- case 0x0E: // Define custom layout
- FOR_EACH_OBJECT {
- StationSpec *statspec = _cur_grffile->stations[stid + i];
-
+ } break;
+
+ case 0x0B: // Callback mask
+ statspec->callbackmask = grf_load_byte(&buf);
+ break;
+
+ case 0x0C: // Disallowed number of platforms
+ statspec->disallowed_platforms = grf_load_byte(&buf);
+ break;
+
+ case 0x0D: // Disallowed platform lengths
+ statspec->disallowed_lengths = grf_load_byte(&buf);
+ break;
+
+ case 0x0E: // Define custom layout
statspec->copied_layouts = false;
while (buf < *bufp + len) {
@@ -1084,12 +1036,9 @@
free(statspec->layouts[l][p]);
statspec->layouts[l][p] = layout;
}
- }
- break;
-
- case 0x0F: // Copy custom layout
- FOR_EACH_OBJECT {
- StationSpec *statspec = _cur_grffile->stations[stid + i];
+ break;
+
+ case 0x0F: { // Copy custom layout
byte srcid = grf_load_byte(&buf);
const StationSpec *srcstatspec = _cur_grffile->stations[srcid];
@@ -1097,51 +1046,51 @@
statspec->platforms = srcstatspec->platforms;
statspec->layouts = srcstatspec->layouts;
statspec->copied_layouts = true;
- }
- break;
-
- case 0x10: // Little/lots cargo threshold
- FOR_EACH_OBJECT statspec[i]->cargo_threshold = grf_load_word(&buf);
- break;
-
- case 0x11: // Pylon placement
- FOR_EACH_OBJECT statspec[i]->pylons = grf_load_byte(&buf);
- break;
-
- case 0x12: // Cargo types for random triggers
- FOR_EACH_OBJECT statspec[i]->cargo_triggers = grf_load_dword(&buf);
- break;
-
- case 0x13: // General flags
- FOR_EACH_OBJECT statspec[i]->flags = grf_load_byte(&buf);
- break;
-
- case 0x14: // Overhead wire placement
- FOR_EACH_OBJECT statspec[i]->wires = grf_load_byte(&buf);
- break;
-
- case 0x15: // Blocked tiles
- FOR_EACH_OBJECT statspec[i]->blocked = grf_load_byte(&buf);
- break;
-
- case 0x16: // @todo Animation info
- FOR_EACH_OBJECT grf_load_word(&buf);
- ret = true;
- break;
-
- case 0x17: // @todo Animation speed
- FOR_EACH_OBJECT grf_load_byte(&buf);
- ret = true;
- break;
-
- case 0x18: // @todo Animation triggers
- FOR_EACH_OBJECT grf_load_word(&buf);
- ret = true;
- break;
-
- default:
- ret = true;
- break;
+ } break;
+
+ case 0x10: // Little/lots cargo threshold
+ statspec->cargo_threshold = grf_load_word(&buf);
+ break;
+
+ case 0x11: // Pylon placement
+ statspec->pylons = grf_load_byte(&buf);
+ break;
+
+ case 0x12: // Cargo types for random triggers
+ statspec->cargo_triggers = grf_load_dword(&buf);
+ break;
+
+ case 0x13: // General flags
+ statspec->flags = grf_load_byte(&buf);
+ break;
+
+ case 0x14: // Overhead wire placement
+ statspec->wires = grf_load_byte(&buf);
+ break;
+
+ case 0x15: // Blocked tiles
+ statspec->blocked = grf_load_byte(&buf);
+ break;
+
+ case 0x16: // @todo Animation info
+ grf_load_word(&buf);
+ ret = true;
+ break;
+
+ case 0x17: // @todo Animation speed
+ grf_load_byte(&buf);
+ ret = true;
+ break;
+
+ case 0x18: // @todo Animation triggers
+ grf_load_word(&buf);
+ ret = true;
+ break;
+
+ default:
+ ret = true;
+ break;
+ }
}
*bufp = buf;
@@ -1151,33 +1100,38 @@
static bool BridgeChangeInfo(uint brid, int numinfo, int prop, byte **bufp, int len)
{
byte *buf = *bufp;
- int i;
bool ret = false;
- switch (prop) {
- case 0x08: // Year of availability
- FOR_EACH_OBJECT _bridge[brid + i].avail_year = ORIGINAL_BASE_YEAR + grf_load_byte(&buf);
- break;
-
- case 0x09: // Minimum length
- FOR_EACH_OBJECT _bridge[brid + i].min_length = grf_load_byte(&buf);
- break;
-
- case 0x0A: // Maximum length
- FOR_EACH_OBJECT _bridge[brid + i].max_length = grf_load_byte(&buf);
- break;
-
- case 0x0B: // Cost factor
- FOR_EACH_OBJECT _bridge[brid + i].price = grf_load_byte(&buf);
- break;
-
- case 0x0C: // Maximum speed
- FOR_EACH_OBJECT _bridge[brid + i].speed = grf_load_word(&buf);
- break;
-
- case 0x0D: // Bridge sprite tables
- FOR_EACH_OBJECT {
- Bridge *bridge = &_bridge[brid + i];
+ if (brid + numinfo > MAX_BRIDGES) {
+ grfmsg(1, "BridgeChangeInfo: Bridge %u is invalid, max %u, ignoring", brid + numinfo, MAX_BRIDGES);
+ return false;
+ }
+
+ for (int i = 0; i < numinfo; i++) {
+ Bridge *bridge = &_bridge[brid + i];
+
+ switch (prop) {
+ case 0x08: // Year of availability
+ bridge->avail_year = ORIGINAL_BASE_YEAR + grf_load_byte(&buf);
+ break;
+
+ case 0x09: // Minimum length
+ bridge->min_length = grf_load_byte(&buf);
+ break;
+
+ case 0x0A: // Maximum length
+ bridge->max_length = grf_load_byte(&buf);
+ break;
+
+ case 0x0B: // Cost factor
+ bridge->price = grf_load_byte(&buf);
+ break;
+
+ case 0x0C: // Maximum speed
+ bridge->speed = grf_load_word(&buf);
+ break;
+
+ case 0x0D: { // Bridge sprite tables
byte tableid = grf_load_byte(&buf);
byte numtables = grf_load_byte(&buf);
@@ -1212,19 +1166,20 @@
bridge->sprite_table[tableid][sprite].pal = pal;
}
}
- }
- break;
-
- case 0x0E: // Flags; bit 0 - disable far pillars
- FOR_EACH_OBJECT _bridge[brid + i].flags = grf_load_byte(&buf);
- break;
-
- case 0x0F: // Long format year of availability (year since year 0)
- FOR_EACH_OBJECT _bridge[brid + i].avail_year = clamp(grf_load_dword(&buf), MIN_YEAR, MAX_YEAR);
- break;
-
- default:
- ret = true;
+ } break;
+
+ case 0x0E: // Flags; bit 0 - disable far pillars
+ bridge->flags = grf_load_byte(&buf);
+ break;
+
+ case 0x0F: // Long format year of availability (year since year 0)
+ bridge->avail_year = clamp(grf_load_dword(&buf), MIN_YEAR, MAX_YEAR);
+ break;
+
+ default:
+ ret = true;
+ break;
+ }
}
*bufp = buf;
@@ -1233,13 +1188,11 @@
static bool TownHouseChangeInfo(uint hid, int numinfo, int prop, byte **bufp, int len)
{
- HouseSpec **housespec;
byte *buf = *bufp;
- int i;
bool ret = false;
- if (hid + numinfo >= HOUSE_MAX) {
- grfmsg(1, "TownHouseChangeInfo: Too many houses loaded (%u), max (%u). Ignoring.", hid + numinfo, HOUSE_MAX-1);
+ if (hid + numinfo > HOUSE_MAX) {
+ grfmsg(1, "TownHouseChangeInfo: Too many houses loaded (%u), max (%u). Ignoring.", hid + numinfo, HOUSE_MAX);
return false;
}
@@ -1251,21 +1204,17 @@
_house_mngr.ResetOverride();
}
- housespec = &_cur_grffile->housespec[hid];
-
- if (prop != 0x08) {
- /* Check that all the houses being modified have been defined. */
- FOR_EACH_OBJECT {
- if (housespec[i] == NULL) {
- grfmsg(2, "TownHouseChangeInfo: Attempt to modify undefined house %u. Ignoring.", hid + i);
- return false;
- }
+ for (int i = 0; i < numinfo; i++) {
+ HouseSpec *housespec = _cur_grffile->housespec[hid + i];
+
+ if (prop != 0x08 && housespec == NULL) {
+ grfmsg(2, "TownHouseChangeInfo: Attempt to modify undefined house %u. Ignoring.", hid + i);
+ continue;
}
- }
-
- switch (prop) {
- case 0x08: // Substitute building type, and definition of a new house
- FOR_EACH_OBJECT {
+
+ switch (prop) {
+ case 0x08: { // Substitute building type, and definition of a new house
+ HouseSpec **house = &_cur_grffile->housespec[hid + i];
byte subs_id = grf_load_byte(&buf);
if (subs_id == 0xFF) {
@@ -1280,144 +1229,130 @@
}
/* Allocate space for this house. */
- if (housespec[i] == NULL) housespec[i] = CallocT<HouseSpec>(1);
-
- memcpy(housespec[i], &_house_specs[subs_id], sizeof(_house_specs[subs_id]));
-
- housespec[i]->enabled = true;
- housespec[i]->local_id = hid + i;
- housespec[i]->substitute_id = subs_id;
- housespec[i]->grffile = _cur_grffile;
- housespec[i]->random_colour[0] = 0x04; // those 4 random colours are the base colour
- housespec[i]->random_colour[1] = 0x08; // for all new houses
- housespec[i]->random_colour[2] = 0x0C; // they stand for red, blue, orange and green
- housespec[i]->random_colour[3] = 0x06;
-
- /* New houses do not (currently) expect to have a default start
- * date before 1930, as this breaks the build date stuff. See
- * FinaliseHouseArray() for more details. */
- if (housespec[i]->min_date < 1930) housespec[i]->min_date = 1930;
- }
- SETBIT(_loaded_newgrf_features, GRFLOADED_NEWHOUSES);
- break;
-
- case 0x09: // Building flags
- FOR_EACH_OBJECT {
- byte state = grf_load_byte(&buf);
- housespec[i]->building_flags = (BuildingFlags)state;
- }
- break;
-
- case 0x0A: // Availability years
- FOR_EACH_OBJECT {
+ if (*house == NULL) *house = CallocT<HouseSpec>(1);
+
+ housespec = *house;
+
+ memcpy(housespec, &_house_specs[subs_id], sizeof(_house_specs[subs_id]));
+
+ housespec->enabled = true;
+ housespec->local_id = hid + i;
+ housespec->substitute_id = subs_id;
+ housespec->grffile = _cur_grffile;
+ housespec->random_colour[0] = 0x04; // those 4 random colours are the base colour
+ housespec->random_colour[1] = 0x08; // for all new houses
+ housespec->random_colour[2] = 0x0C; // they stand for red, blue, orange and green
+ housespec->random_colour[3] = 0x06;
+
+ /**
+ * New houses do not (currently) expect to have a default start
+ * date before 1930, as this breaks the build date stuff.
+ * @see FinaliseHouseArray() for more details.
+ */
+ if (housespec->min_date < 1930) housespec->min_date = 1930;
+
+ _loaded_newgrf_features.has_newhouses = true;
+ } break;
+
+ case 0x09: // Building flags
+ housespec->building_flags = (BuildingFlags)grf_load_byte(&buf);
+ break;
+
+ case 0x0A: { // Availability years
uint16 years = grf_load_word(&buf);
- housespec[i]->min_date = GB(years, 0, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 0, 8);
- housespec[i]->max_date = GB(years, 8, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 8, 8);
- }
- break;
-
- case 0x0B: // Population
- FOR_EACH_OBJECT housespec[i]->population = grf_load_byte(&buf);
- break;
-
- case 0x0C: // Mail generation multiplier
- FOR_EACH_OBJECT housespec[i]->mail_generation = grf_load_byte(&buf);
- break;
-
- case 0x0D: // Passenger acceptance
- case 0x0E: // Mail acceptance
- FOR_EACH_OBJECT housespec[i]->cargo_acceptance[prop - 0x0D] = grf_load_byte(&buf);
- break;
- case 0x0F: // Goods/candy, food/fizzy drinks acceptance
- FOR_EACH_OBJECT {
+ housespec->min_date = GB(years, 0, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 0, 8);
+ housespec->max_date = GB(years, 8, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 8, 8);
+ } break;
+
+ case 0x0B: // Population
+ housespec->population = grf_load_byte(&buf);
+ break;
+
+ case 0x0C: // Mail generation multiplier
+ housespec->mail_generation = grf_load_byte(&buf);
+ break;
+
+ case 0x0D: // Passenger acceptance
+ case 0x0E: // Mail acceptance
+ housespec->cargo_acceptance[prop - 0x0D] = grf_load_byte(&buf);
+ break;
+
+ case 0x0F: { // Goods/candy, food/fizzy drinks acceptance
int8 goods = grf_load_byte(&buf);
/* If value of goods is negative, it means in fact food or, if in toyland, fizzy_drink acceptance.
* Else, we have "standard" 3rd cargo type, goods or candy, for toyland once more */
- housespec[i]->accepts_cargo[2] = (goods >= 0) ? ((_opt.landscape == LT_TOYLAND) ? CT_CANDY : CT_GOODS) :
+ housespec->accepts_cargo[2] = (goods >= 0) ? ((_opt.landscape == LT_TOYLAND) ? CT_CANDY : CT_GOODS) :
((_opt.landscape == LT_TOYLAND) ? CT_FIZZY_DRINKS : CT_FOOD);
- housespec[i]->cargo_acceptance[2] = abs(goods); // but we do need positive value here
- }
- break;
-
- case 0x10: // Local authority rating decrease on removal
- FOR_EACH_OBJECT housespec[i]->remove_rating_decrease = grf_load_word(&buf);
- break;
-
- case 0x11: // Removal cost multiplier
- FOR_EACH_OBJECT housespec[i]->removal_cost = grf_load_byte(&buf);
- break;
-
- case 0x12: // Building name ID
- FOR_EACH_OBJECT housespec[i]->building_name = MapGRFStringID(_cur_grffile->grfid, grf_load_word(&buf));
- break;
-
- case 0x13: // Building availability mask
- FOR_EACH_OBJECT {
- uint16 avail = grf_load_word(&buf);
- housespec[i]->building_availability = (HouseZones)avail;
- }
- break;
-
- case 0x14: // House callback flags
- FOR_EACH_OBJECT housespec[i]->callback_mask = grf_load_byte(&buf);
- break;
-
- case 0x15: // House override byte
- FOR_EACH_OBJECT {
+ housespec->cargo_acceptance[2] = abs(goods); // but we do need positive value here
+ } break;
+
+ case 0x10: // Local authority rating decrease on removal
+ housespec->remove_rating_decrease = grf_load_word(&buf);
+ break;
+
+ case 0x11: // Removal cost multiplier
+ housespec->removal_cost = grf_load_byte(&buf);
+ break;
+
+ case 0x12: // Building name ID
+ housespec->building_name = MapGRFStringID(_cur_grffile->grfid, grf_load_word(&buf));
+ break;
+
+ case 0x13: // Building availability mask
+ housespec->building_availability = (HouseZones)grf_load_word(&buf);
+ break;
+
+ case 0x14: // House callback flags
+ housespec->callback_mask = grf_load_byte(&buf);
+ break;
+
+ case 0x15: { // House override byte
byte override = grf_load_byte(&buf);
/* The house being overridden must be an original house. */
if (override >= NEW_HOUSE_OFFSET) {
- grfmsg(2, "TownHouseChangeInfo: Attempt to override new house %u with house id %u. Ignoring.", override, hid);
- return false;
+ grfmsg(2, "TownHouseChangeInfo: Attempt to override new house %u with house id %u. Ignoring.", override, hid + i);
+ continue;
}
- _house_mngr.Add(hid, override);
- }
- break;
-
- case 0x16: // Periodic refresh multiplier
- FOR_EACH_OBJECT housespec[i]->processing_time = grf_load_byte(&buf);
- break;
-
- case 0x17: // Four random colours to use
- FOR_EACH_OBJECT {
- uint j;
- for (j = 0; j < 4; j++) housespec[i]->random_colour[j] = grf_load_byte(&buf);
- }
- break;
-
- case 0x18: // Relative probability of appearing
- FOR_EACH_OBJECT housespec[i]->probability = grf_load_byte(&buf);
- break;
-
- case 0x19: // Extra flags
- FOR_EACH_OBJECT {
- byte flags = grf_load_byte(&buf);
- housespec[i]->extra_flags = (HouseExtraFlags)flags;
- }
- break;
-
- case 0x1A: // Animation frames
- FOR_EACH_OBJECT housespec[i]->animation_frames = grf_load_byte(&buf);
- break;
-
- case 0x1B: // Animation speed
- FOR_EACH_OBJECT housespec[i]->animation_speed = clamp(grf_load_byte(&buf), 2, 16);
- break;
-
- case 0x1C: // Class of the building type
- FOR_EACH_OBJECT housespec[i]->class_id = AllocateHouseClassID(grf_load_byte(&buf), _cur_grffile->grfid);
- break;
-
- case 0x1D: // Callback flags 2
- FOR_EACH_OBJECT housespec[i]->callback_mask |= (grf_load_byte(&buf) << 8);
- break;
-
- case 0x1E: // Accepted cargo types
- FOR_EACH_OBJECT {
+ _house_mngr.Add(hid + i, override);
+ } break;
+
+ case 0x16: // Periodic refresh multiplier
+ housespec->processing_time = grf_load_byte(&buf);
+ break;
+
+ case 0x17: // Four random colours to use
+ for (uint j = 0; j < 4; j++) housespec->random_colour[j] = grf_load_byte(&buf);
+ break;
+
+ case 0x18: // Relative probability of appearing
+ housespec->probability = grf_load_byte(&buf);
+ break;
+
+ case 0x19: // Extra flags
+ housespec->extra_flags = (HouseExtraFlags)grf_load_byte(&buf);
+ break;
+
+ case 0x1A: // Animation frames
+ housespec->animation_frames = grf_load_byte(&buf);
+ break;
+
+ case 0x1B: // Animation speed
+ housespec->animation_speed = clamp(grf_load_byte(&buf), 2, 16);
+ break;
+
+ case 0x1C: // Class of the building type
+ housespec->class_id = AllocateHouseClassID(grf_load_byte(&buf), _cur_grffile->grfid);
+ break;
+
+ case 0x1D: // Callback flags 2
+ housespec->callback_mask |= (grf_load_byte(&buf) << 8);
+ break;
+
+ case 0x1E: { // Accepted cargo types
uint32 cargotypes = grf_load_dword(&buf);
/* Check if the cargo types should not be changed */
@@ -1430,21 +1365,21 @@
if (cargo == CT_INVALID) {
/* Disable acceptance of invalid cargo type */
- housespec[i]->cargo_acceptance[j] = 0;
+ housespec->cargo_acceptance[j] = 0;
} else {
- housespec[i]->accepts_cargo[j] = cargo;
+ housespec->accepts_cargo[j] = cargo;
}
}
- }
- break;
-
- case 0x1F: // Minimum life span
- FOR_EACH_OBJECT housespec[i]->minimum_life = grf_load_byte(&buf);
- break;
-
- default:
- ret = true;
- break;
+ } break;
+
+ case 0x1F: // Minimum life span
+ housespec->minimum_life = grf_load_byte(&buf);
+ break;
+
+ default:
+ ret = true;
+ break;
+ }
}
*bufp = buf;
@@ -1454,12 +1389,11 @@
static bool GlobalVarChangeInfo(uint gvid, int numinfo, int prop, byte **bufp, int len)
{
byte *buf = *bufp;
- int i;
bool ret = false;
- switch (prop) {
- case 0x08: /* Cost base factor */
- FOR_EACH_OBJECT {
+ for (int i = 0; i < numinfo; i++) {
+ switch (prop) {
+ case 0x08: { // Cost base factor
byte factor = grf_load_byte(&buf);
uint price = gvid + i;
@@ -1468,28 +1402,24 @@
} else {
grfmsg(1, "GlobalVarChangeInfo: Price %d out of range, ignoring", price);
}
- }
- break;
-
- case 0x09: /* Cargo translation table */
- /* This is loaded during the initialisation stage, so just skip it here. */
- /* Each entry is 4 bytes. */
- buf += numinfo * 4;
- break;
-
- case 0x0A: // Currency display names
- FOR_EACH_OBJECT {
+ } break;
+
+ case 0x09: // Cargo translation table
+ /* This is loaded during the initialisation stage, so just skip it here. */
+ /* Each entry is 4 bytes. */
+ buf += 4;
+ break;
+
+ case 0x0A: { // Currency display names
uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
StringID newone = GetGRFStringID(_cur_grffile->grfid, grf_load_word(&buf));
if ((newone != STR_UNDEFINED) && (curidx < NUM_CURRENCY)) {
_currency_specs[curidx].name = newone;
}
- }
- break;
-
- case 0x0B: // Currency multipliers
- FOR_EACH_OBJECT {
+ } break;
+
+ case 0x0B: { // Currency multipliers
uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
uint32 rate = grf_load_dword(&buf);
@@ -1501,11 +1431,9 @@
} else {
grfmsg(1, "GlobalVarChangeInfo: Currency multipliers %d out of range, ignoring", curidx);
}
- }
- break;
-
- case 0x0C: // Currency options
- FOR_EACH_OBJECT {
+ } break;
+
+ case 0x0C: { // Currency options
uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
uint16 options = grf_load_word(&buf);
@@ -1517,25 +1445,21 @@
} else {
grfmsg(1, "GlobalVarChangeInfo: Currency option %d out of range, ignoring", curidx);
}
- }
- break;
-
- case 0x0D: // Currency prefix symbol
- FOR_EACH_OBJECT {
+ } break;
+
+ case 0x0D: { // Currency prefix symbol
uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
uint32 tempfix = grf_load_dword(&buf);
if (curidx < NUM_CURRENCY) {
- memcpy(_currency_specs[curidx].prefix,&tempfix,4);
+ memcpy(_currency_specs[curidx].prefix, &tempfix, 4);
_currency_specs[curidx].prefix[4] = 0;
} else {
grfmsg(1, "GlobalVarChangeInfo: Currency symbol %d out of range, ignoring", curidx);
}
- }
- break;
-
- case 0x0E: // Currency suffix symbol
- FOR_EACH_OBJECT {
+ } break;
+
+ case 0x0E: { // Currency suffix symbol
uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
uint32 tempfix = grf_load_dword(&buf);
@@ -1545,11 +1469,9 @@
} else {
grfmsg(1, "GlobalVarChangeInfo: Currency symbol %d out of range, ignoring", curidx);
}
- }
- break;
-
- case 0x0F: // Euro introduction dates
- FOR_EACH_OBJECT {
+ } break;
+
+ case 0x0F: { // Euro introduction dates
uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
Year year_euro = grf_load_word(&buf);
@@ -1558,28 +1480,29 @@
} else {
grfmsg(1, "GlobalVarChangeInfo: Euro intro date %d out of range, ignoring", curidx);
}
- }
- break;
-
- case 0x10: // 12 * 32 * B Snow line height table
- if (numinfo > 1 || IsSnowLineSet()) {
- grfmsg(1, "GlobalVarChangeInfo: The snowline can only be set once (%d)", numinfo);
- } else if (len < SNOW_LINE_MONTHS * SNOW_LINE_DAYS) {
- grfmsg(1, "GlobalVarChangeInfo: Not enough entries set in the snowline table (%d)", len);
- } else {
- byte table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS];
-
- for (uint i = 0; i < SNOW_LINE_MONTHS; i++) {
- for (uint j = 0; j < SNOW_LINE_DAYS; j++) {
- table[i][j] = grf_load_byte(&buf);
+ } break;
+
+ case 0x10: // Snow line height table
+ if (numinfo > 1 || IsSnowLineSet()) {
+ grfmsg(1, "GlobalVarChangeInfo: The snowline can only be set once (%d)", numinfo);
+ } else if (len < SNOW_LINE_MONTHS * SNOW_LINE_DAYS) {
+ grfmsg(1, "GlobalVarChangeInfo: Not enough entries set in the snowline table (%d)", len);
+ } else {
+ byte table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS];
+
+ for (uint i = 0; i < SNOW_LINE_MONTHS; i++) {
+ for (uint j = 0; j < SNOW_LINE_DAYS; j++) {
+ table[i][j] = grf_load_byte(&buf);
+ }
}
+ SetSnowLine(table);
}
- SetSnowLine(table);
- }
- break;
-
- default:
- ret = true;
+ break;
+
+ default:
+ ret = true;
+ break;
+ }
}
*bufp = buf;
@@ -1588,120 +1511,118 @@
static bool CargoChangeInfo(uint cid, int numinfo, int prop, byte **bufp, int len)
{
+ byte *buf = *bufp;
+ bool ret = false;
+
if (cid + numinfo > NUM_CARGO) {
grfmsg(2, "CargoChangeInfo: Cargo type %d out of range (max %d)", cid + numinfo, NUM_CARGO - 1);
return false;
}
- CargoSpec *cs = &_cargo[cid];
- byte *buf = *bufp;
- int i;
- bool ret = false;
-
- switch (prop) {
- case 0x08: /* Bit number of cargo */
- FOR_EACH_OBJECT {
- cs[i].bitnum = grf_load_byte(&buf);
- cs[i].grfid = _cur_grffile->grfid;
+ for (int i = 0; i < numinfo; i++) {
+ CargoSpec *cs = &_cargo[cid + i];
+
+ switch (prop) {
+ case 0x08: /* Bit number of cargo */
+ cs->bitnum = grf_load_byte(&buf);
+ cs->grfid = _cur_grffile->grfid;
if (cs->IsValid()) {
SETBIT(_cargo_mask, cid + i);
} else {
CLRBIT(_cargo_mask, cid + i);
}
- }
- break;
-
- case 0x09: /* String ID for cargo type name */
- FOR_EACH_OBJECT cs[i].name = grf_load_word(&buf);
- break;
-
- case 0x0A: /* String for cargo name, plural */
- FOR_EACH_OBJECT cs[i].name_plural = grf_load_word(&buf);
- break;
-
- case 0x0B:
- /* String for units of cargo. This is different in OpenTTD to TTDPatch
- * (e.g. 10 tonnes of coal) */
- FOR_EACH_OBJECT cs[i].units_volume = grf_load_word(&buf);
- break;
-
- case 0x0C: /* String for quantity of cargo (e.g. 10 tonnes of coal) */
- FOR_EACH_OBJECT cs[i].quantifier = grf_load_word(&buf);
- break;
-
- case 0x0D: /* String for two letter cargo abbreviation */
- FOR_EACH_OBJECT cs[i].abbrev = grf_load_word(&buf);
- break;
-
- case 0x0E: /* Sprite ID for cargo icon */
- FOR_EACH_OBJECT cs[i].sprite = grf_load_word(&buf);
- break;
-
- case 0x0F: /* Weight of one unit of cargo */
- FOR_EACH_OBJECT cs[i].weight = grf_load_byte(&buf);
- break;
-
- case 0x10: /* Used for payment calculation */
- FOR_EACH_OBJECT cs[i].transit_days[0] = grf_load_byte(&buf);
- break;
-
- case 0x11: /* Used for payment calculation */
- FOR_EACH_OBJECT cs[i].transit_days[1] = grf_load_byte(&buf);
- break;
-
- case 0x12: /* Base cargo price */
- FOR_EACH_OBJECT cs[i].initial_payment = grf_load_dword(&buf);
- break;
-
- case 0x13: /* Colour for station rating bars */
- FOR_EACH_OBJECT cs[i].rating_colour = MapDOSColour(grf_load_byte(&buf));
- break;
-
- case 0x14: /* Colour for cargo graph */
- FOR_EACH_OBJECT cs[i].legend_colour = MapDOSColour(grf_load_byte(&buf));
- break;
-
- case 0x15: /* Freight status */
- FOR_EACH_OBJECT cs[i].is_freight = grf_load_byte(&buf) != 0;
- break;
-
- case 0x16: /* Cargo classes */
- FOR_EACH_OBJECT cs[i].classes = grf_load_word(&buf);
- break;
-
- case 0x17: /* Cargo label */
- FOR_EACH_OBJECT {
- cs[i].label = grf_load_dword(&buf);
- cs[i].label = BSWAP32(cs[i].label);
- }
- break;
-
- case 0x18: /* Town growth substitute type */
- FOR_EACH_OBJECT {
+ break;
+
+ case 0x09: /* String ID for cargo type name */
+ cs->name = grf_load_word(&buf);
+ break;
+
+ case 0x0A: /* String for cargo name, plural */
+ cs->name_plural = grf_load_word(&buf);
+ break;
+
+ case 0x0B:
+ /* String for units of cargo. This is different in OpenTTD to TTDPatch
+ * (e.g. 10 tonnes of coal) */
+ cs->units_volume = grf_load_word(&buf);
+ break;
+
+ case 0x0C: /* String for quantity of cargo (e.g. 10 tonnes of coal) */
+ cs->quantifier = grf_load_word(&buf);
+ break;
+
+ case 0x0D: /* String for two letter cargo abbreviation */
+ cs->abbrev = grf_load_word(&buf);
+ break;
+
+ case 0x0E: /* Sprite ID for cargo icon */
+ cs->sprite = grf_load_word(&buf);
+ break;
+
+ case 0x0F: /* Weight of one unit of cargo */
+ cs->weight = grf_load_byte(&buf);
+ break;
+
+ case 0x10: /* Used for payment calculation */
+ cs->transit_days[0] = grf_load_byte(&buf);
+ break;
+
+ case 0x11: /* Used for payment calculation */
+ cs->transit_days[1] = grf_load_byte(&buf);
+ break;
+
+ case 0x12: /* Base cargo price */
+ cs->initial_payment = grf_load_dword(&buf);
+ break;
+
+ case 0x13: /* Colour for station rating bars */
+ cs->rating_colour = MapDOSColour(grf_load_byte(&buf));
+ break;
+
+ case 0x14: /* Colour for cargo graph */
+ cs->legend_colour = MapDOSColour(grf_load_byte(&buf));
+ break;
+
+ case 0x15: /* Freight status */
+ cs->is_freight = (grf_load_byte(&buf) != 0);
+ break;
+
+ case 0x16: /* Cargo classes */
+ cs->classes = grf_load_word(&buf);
+ break;
+
+ case 0x17: /* Cargo label */
+ cs->label = grf_load_dword(&buf);
+ cs->label = BSWAP32(cs->label);
+ break;
+
+ case 0x18: { /* Town growth substitute type */
uint8 substitute_type = grf_load_byte(&buf);
+
switch (substitute_type) {
- case 0x00: cs[i].town_effect = TE_PASSENGERS; break;
- case 0x02: cs[i].town_effect = TE_MAIL; break;
- case 0x05: cs[i].town_effect = TE_GOODS; break;
- case 0x09: cs[i].town_effect = TE_WATER; break;
- case 0x0B: cs[i].town_effect = TE_FOOD; break;
+ case 0x00: cs->town_effect = TE_PASSENGERS; break;
+ case 0x02: cs->town_effect = TE_MAIL; break;
+ case 0x05: cs->town_effect = TE_GOODS; break;
+ case 0x09: cs->town_effect = TE_WATER; break;
+ case 0x0B: cs->town_effect = TE_FOOD; break;
default:
grfmsg(1, "CargoChangeInfo: Unknown town growth substitute value %d, setting to none.", substitute_type);
- case 0xFF: cs[i].town_effect = TE_NONE; break;
+ case 0xFF: cs->town_effect = TE_NONE; break;
}
- }
- break;
-
- case 0x19: /* Town growth coefficient */
- FOR_EACH_OBJECT cs[i].multipliertowngrowth = grf_load_word(&buf);
- break;
-
- case 0x1A: /* Bitmask of callbacks to use */
- FOR_EACH_OBJECT cs[i].callback_mask = grf_load_byte(&buf);
- break;
-
- default:
- ret = true;
+ } break;
+
+ case 0x19: /* Town growth coefficient */
+ cs->multipliertowngrowth = grf_load_word(&buf);
+ break;
+
+ case 0x1A: /* Bitmask of callbacks to use */
+ cs->callback_mask = grf_load_byte(&buf);
+ break;
+
+ default:
+ ret = true;
+ break;
+ }
}
*bufp = buf;
@@ -1712,7 +1633,6 @@
static bool SoundEffectChangeInfo(uint sid, int numinfo, int prop, byte **bufp, int len)
{
byte *buf = *bufp;
- int i;
bool ret = false;
if (_cur_grffile->sound_offset == 0) {
@@ -1720,38 +1640,28 @@
return false;
}
- switch (prop) {
- case 0x08: // Relative volume
- FOR_EACH_OBJECT {
- uint sound = sid + i + _cur_grffile->sound_offset - GetNumOriginalSounds();
-
- if (sound >= GetNumSounds()) {
- grfmsg(1, "SoundEffectChangeInfo: Sound %d not defined (max %d)", sound, GetNumSounds());
- } else {
- GetSound(sound)->volume = grf_load_byte(&buf);
- }
- }
- break;
-
- case 0x09: // Priority
- FOR_EACH_OBJECT {
- uint sound = sid + i + _cur_grffile->sound_offset - GetNumOriginalSounds();
-
- if (sound >= GetNumSounds()) {
- grfmsg(1, "SoundEffectChangeInfo: Sound %d not defined (max %d)", sound, GetNumSounds());
- } else {
- GetSound(sound)->priority = grf_load_byte(&buf);
- }
- }
- break;
-
- case 0x0A: // Override old sound
- FOR_EACH_OBJECT {
- uint sound = sid + i + _cur_grffile->sound_offset - GetNumOriginalSounds();
+ for (int i = 0; i < numinfo; i++) {
+ uint sound = sid + i + _cur_grffile->sound_offset - GetNumOriginalSounds();
+
+ if (sound >= GetNumSounds()) {
+ grfmsg(1, "SoundEffectChangeInfo: Sound %d not defined (max %d)", sound, GetNumSounds());
+ continue;
+ }
+
+ switch (prop) {
+ case 0x08: // Relative volume
+ GetSound(sound)->volume = grf_load_byte(&buf);
+ break;
+
+ case 0x09: // Priority
+ GetSound(sound)->priority = grf_load_byte(&buf);
+ break;
+
+ case 0x0A: { // Override old sound
uint orig_sound = grf_load_byte(&buf);
- if (sound >= GetNumSounds() || orig_sound >= GetNumSounds()) {
- grfmsg(1, "SoundEffectChangeInfo: Sound %d or %d not defined (max %d)", sound, orig_sound, GetNumSounds());
+ if (orig_sound >= GetNumSounds()) {
+ grfmsg(1, "SoundEffectChangeInfo: Original sound %d not defined (max %d)", orig_sound, GetNumSounds());
} else {
FileEntry *newfe = GetSound(sound);
FileEntry *oldfe = GetSound(orig_sound);
@@ -1759,11 +1669,373 @@
/* Literally copy the data of the new sound over the original */
*oldfe = *newfe;
}
- }
- break;
-
- default:
- ret = true;
+ } break;
+
+ default:
+ ret = true;
+ break;
+ }
+ }
+
+ *bufp = buf;
+ return ret;
+}
+
+static bool IndustrytilesChangeInfo(uint indtid, int numinfo, int prop, byte **bufp, int len)
+{
+ if (!HASBIT(_ttdpatch_flags[3], 0x07)) return true;
+
+ byte *buf = *bufp;
+ bool ret = false;
+
+ if (indtid + numinfo > NUM_INDUSTRYTILES) {
+ grfmsg(1, "IndustryTilesChangeInfo: Too many industry tiles loaded (%u), max (%u). Ignoring.", indtid + numinfo, NUM_INDUSTRYTILES);
+ return false;
+ }
+
+ /* Allocate industry tile specs if they haven't been allocated already. */
+ if (_cur_grffile->indtspec == NULL) {
+ _cur_grffile->indtspec = CallocT<IndustryTileSpec*>(NUM_INDUSTRYTILES);
+
+ /* Reset any overrides that have been set. */
+ _industile_mngr.ResetOverride();
+ }
+
+ for (int i = 0; i < numinfo; i++) {
+ IndustryTileSpec *tsp = _cur_grffile->indtspec[indtid + i];
+
+ if (prop != 0x08 && tsp == NULL) {
+ grfmsg(2, "IndustryTilesChangeInfo: Attempt to modify undefined industry tile %u. Ignoring.", indtid + i);
+ continue;
+ }
+
+ switch (prop) {
+ case 0x08: { // Substitute industry tile type
+ IndustryTileSpec **tilespec = &_cur_grffile->indtspec[indtid + i];
+ byte subs_id = grf_load_byte(&buf);
+
+ if (subs_id == 0xFF) {
+ /* Instead of defining a new industry, a substitute industry id
+ * of 0xFF disables the old industry with the current id. */
+ tsp->enabled = false;
+ continue;
+ } else if (subs_id >= NEW_INDUSTRYTILEOFFSET) {
+ /* The substitute id must be one of the original industry tile. */
+ grfmsg(2, "IndustryTilesChangeInfo: Attempt to use new industry tile %u as substitute industry tile for %u. Ignoring.", subs_id, indtid + i);
+ return false;
+ }
+
+ /* Allocate space for this industry. */
+ if (*tilespec == NULL) {
+ int tempid;
+ *tilespec = CallocT<IndustryTileSpec>(1);
+ tsp = *tilespec;
+
+ memcpy(tsp, &_industry_tile_specs[subs_id], sizeof(_industry_tile_specs[subs_id]));
+ tsp->enabled = true;
+ tsp->grf_prop.local_id = indtid + i;
+ tsp->grf_prop.subst_id = subs_id;
+ tsp->grf_prop.grffile = _cur_grffile;
+ tempid = _industile_mngr.AddEntityID(indtid + i, _cur_grffile->grfid, subs_id); // pre-reserve the tile slot
+ }
+ } break;
+
+ case 0x09: { // Industry tile override
+ byte ovrid = grf_load_byte(&buf);
+
+ /* The industry being overridden must be an original industry. */
+ if (ovrid >= NEW_INDUSTRYTILEOFFSET) {
+ grfmsg(2, "IndustryTilesChangeInfo: Attempt to override new industry tile %u with industry tile id %u. Ignoring.", ovrid, indtid + i);
+ return false;
+ }
+
+ tsp->grf_prop.override = ovrid;
+ _industile_mngr.Add(indtid + i, ovrid);
+ } break;
+
+ case 0x0A: // Tile acceptance
+ case 0x0B:
+ case 0x0C: {
+ uint16 acctp = grf_load_word(&buf);
+ tsp->accepts_cargo[prop - 0x0A] = GetCargoTranslation(GB(acctp, 0, 8), _cur_grffile);
+ tsp->acceptance[prop - 0x0A] = GetCargoTranslation(GB(acctp, 8, 8), _cur_grffile);
+ } break;
+
+ case 0x0D: // Land shape flags
+ tsp->slopes_refused = (Slope)grf_load_byte(&buf);
+ break;
+
+ case 0x0E: // Callback flags
+ tsp->callback_flags = grf_load_byte(&buf);
+ break;
+
+ case 0x0F: // Animation information
+ tsp->animation_info = grf_load_word(&buf);
+ break;
+
+ case 0x10: // Animation speed
+ tsp->animation_speed = grf_load_byte(&buf);
+ break;
+
+ case 0x11: // Triggers for callback 25
+ tsp->animation_triggers = grf_load_byte(&buf);
+ break;
+
+ case 0x12: // Special flags
+ tsp->animation_special_flags = grf_load_byte(&buf);
+ break;
+
+ default:
+ ret = true;
+ break;
+ }
+ }
+
+ *bufp = buf;
+ return ret;
+}
+
+static bool IndustriesChangeInfo(uint indid, int numinfo, int prop, byte **bufp, int len)
+{
+ if (!HASBIT(_ttdpatch_flags[3], 0x07)) return true;
+
+ byte *buf = *bufp;
+ bool ret = false;
+
+ if (indid + numinfo > NUM_INDUSTRYTYPES) {
+ grfmsg(1, "IndustriesChangeInfo: Too many industries loaded (%u), max (%u). Ignoring.", indid + numinfo, NUM_INDUSTRYTYPES);
+ return false;
+ }
+
+ grfmsg(1, "IndustriesChangeInfo: newid %u", indid);
+
+ /* Allocate industry specs if they haven't been allocated already. */
+ if (_cur_grffile->industryspec == NULL) {
+ _cur_grffile->industryspec = CallocT<IndustrySpec*>(NUM_INDUSTRYTYPES);
+
+ /* Reset any overrides that have been set. */
+ _industry_mngr.ResetOverride();
+ }
+
+ for (int i = 0; i < numinfo; i++) {
+ IndustrySpec *indsp = _cur_grffile->industryspec[indid + i];
+
+ if (prop != 0x08 && indsp == NULL) {
+ grfmsg(2, "IndustriesChangeInfo: Attempt to modify undefined industry %u. Ignoring.", indid + i);
+ continue;
+ }
+
+ switch (prop) {
+ case 0x08: { // Substitute industry type
+ IndustrySpec **indspec = &_cur_grffile->industryspec[indid + i];
+ byte subs_id = grf_load_byte(&buf);
+
+ if (subs_id == 0xFF) {
+ /* Instead of defining a new industry, a substitute industry id
+ * of 0xFF disables the old industry with the current id. */
+ _industry_specs[indid + i].enabled = false;
+ continue;
+ } else if (subs_id >= NEW_INDUSTRYOFFSET) {
+ /* The substitute id must be one of the original industry. */
+ grfmsg(2, "_industry_specs: Attempt to use new industry %u as substitute industry for %u. Ignoring.", subs_id, indid + i);
+ return false;
+ }
+
+ /* Allocate space for this industry.
+ * Only need to do it once. If ever it is called again, it should not
+ * do anything */
+ if (*indspec == NULL) {
+ *indspec = CallocT<IndustrySpec>(1);
+ indsp = *indspec;
+
+ memcpy(indsp, &_origin_industry_specs[subs_id], sizeof(_industry_specs[subs_id]));
+ indsp->enabled = true;
+ indsp->grf_prop.local_id = indid + i;
+ indsp->grf_prop.subst_id = subs_id;
+ indsp->grf_prop.grffile = _cur_grffile;
+ }
+ } break;
+
+ case 0x09: { // Industry type override
+ byte ovrid = grf_load_byte(&buf);
+
+ /* The industry being overridden must be an original industry. */
+ if (ovrid >= NEW_INDUSTRYOFFSET) {
+ grfmsg(2, "IndustriesChangeInfo: Attempt to override new industry %u with industry id %u. Ignoring.", ovrid, indid + i);
+ return false;
+ }
+ indsp->grf_prop.override = ovrid;
+ _industry_mngr.Add(indid + i, ovrid);
+ } break;
+
+ case 0x0A: { // Set industry layout(s)
+ indsp->num_table = grf_load_byte(&buf); // Number of layaouts
+ uint32 defsize = grf_load_dword(&buf); // Total size of the definition
+ IndustryTileTable **tile_table = CallocT<IndustryTileTable*>(indsp->num_table); // Table with tiles to compose an industry
+ IndustryTileTable *itt = CallocT<IndustryTileTable>(defsize); // Temporary array to read the tile layouts from the GRF
+ int size;
+ IndustryTileTable *copy_from;
+
+ for (byte j = 0; j < indsp->num_table; j++) {
+ for (int k = 0;; k++) {
+ itt[k].ti.x = grf_load_byte(&buf); // Offsets from northermost tile
+
+ if (itt[k].ti.x == 0xFE && k == 0) {
+ /* This means we have to borrow the layout from an old industry */
+ IndustryType type = grf_load_byte(&buf); //industry holding required layout
+ byte laynbr = grf_load_byte(&buf); //layout number to borrow
+
+ copy_from = (IndustryTileTable*)_origin_industry_specs[type].table[laynbr];
+ for (size = 1;; size++) {
+ if (_origin_industry_specs[type].table[laynbr + (size - 1)]->ti.x == -0x80 &&
+ _origin_industry_specs[type].table[laynbr + (size - 1)]->ti.y == 0) break;
+ }
+ break;
+ }
+
+ itt[k].ti.y = grf_load_byte(&buf); // Or table definition finalisation
+
+ if (itt[k].ti.x == 0 && itt[k].ti.y == 0x80) {
+ /* Not the same terminator. The one we are using is rather
+ x= -80, y = x . So, adjust it. */
+ itt[k].ti.x = -0x80;
+ itt[k].ti.y = 0;
+ itt[k].gfx = 0;
+
+ size = k + 1;
+ copy_from = itt;
+ break;
+ }
+
+ itt[k].gfx = grf_load_byte(&buf);
+
+ if (itt[k].gfx == 0xFE) {
+ /* Use a new tile from this GRF */
+ int local_tile_id = grf_load_word(&buf);
+
+ /* Read the ID from the _industile_mngr. */
+ int tempid = _industile_mngr.GetID(local_tile_id, _cur_grffile->grfid);
+
+ if (tempid == INVALID_INDUSTRYTILE) {
+ grfmsg(2, "IndustriesChangeInfo: Attempt to use industry tile %u with industry id %u, not yet defined. Ignoring.", local_tile_id, indid);
+ } else {
+ /* Declared as been valid, can be used */
+ itt[k].gfx = tempid;
+ size = k + 1;
+ copy_from = itt;
+ }
+ }
+ }
+ tile_table[j] = CallocT<IndustryTileTable>(size);
+ memcpy(tile_table[j], copy_from, sizeof(*copy_from) * size);
+ }
+ /* Install final layout construction in the industry spec */
+ indsp->table = tile_table;
+ SETBIT(indsp->cleanup_flag, 1);
+ free(itt);
+ } break;
+
+ case 0x0B: // Industry production flags
+ indsp->life_type = (IndustryLifeType)grf_load_byte(&buf);
+ break;
+
+ case 0x0C: // Industry closure message
+ indsp->closure_text = MapGRFStringID(_cur_grffile->grfid, grf_load_word(&buf));
+ break;
+
+ case 0x0D: // Production increase message
+ indsp->production_up_text = MapGRFStringID(_cur_grffile->grfid, grf_load_word(&buf));
+ break;
+
+ case 0x0E: // Production decrease message
+ indsp->production_down_text = MapGRFStringID(_cur_grffile->grfid, grf_load_word(&buf));
+ break;
+
+ case 0x0F: // Fund cost multiplier
+ indsp->cost_multiplier = grf_load_byte(&buf);
+ break;
+
+ case 0x10: // Production cargo types
+ for (byte j = 0; j < 2; j++) {
+ indsp->produced_cargo[j] = GetCargoTranslation(grf_load_byte(&buf), _cur_grffile);
+ }
+ break;
+
+ case 0x11: // Acceptance cargo types
+ for (byte j = 0; j < 3; j++) {
+ indsp->accepts_cargo[j] = GetCargoTranslation(grf_load_byte(&buf), _cur_grffile);
+ }
+ grf_load_byte(&buf); // Unnused, eat it up
+ break;
+
+ case 0x12: // Production multipliers
+ case 0x13:
+ indsp->production_rate[prop - 0x12] = grf_load_byte(&buf);
+ break;
+
+ case 0x14: // Minimal amount of cargo distributed
+ indsp->minimal_cargo = grf_load_byte(&buf);
+ break;
+
+ case 0x15: { // Random sound effects
+ indsp->number_of_sounds = grf_load_byte(&buf);
+ uint8 *sounds = MallocT<uint8>(indsp->number_of_sounds);
+
+ for (uint8 j = 0; j < indsp->number_of_sounds; j++) sounds[j] = grf_load_byte(&buf);
+ indsp->random_sounds = sounds;
+ SETBIT(indsp->cleanup_flag, 0);
+ } break;
+
+ case 0x16: // Conflicting industry types
+ for (byte j = 0; j < 3; j++) indsp->conflicting[j] = grf_load_byte(&buf);
+ break;
+
+ case 0x17: // Probability in random game
+ indsp->appear_ingame[_opt.landscape] = grf_load_byte(&buf);
+ break;
+
+ case 0x18: // Probability during gameplay
+ indsp->appear_creation[_opt.landscape] = grf_load_byte(&buf);
+ break;
+
+ case 0x19: // Map color
+ indsp->map_colour = MapDOSColour(grf_load_byte(&buf));
+ break;
+
+ case 0x1A: // Special industry flags to define special behavior
+ indsp->behaviour = (IndustyBehaviour)grf_load_dword(&buf);
+ break;
+
+ case 0x1B: // New industry text ID
+ indsp->new_industry_text = MapGRFStringID(_cur_grffile->grfid, grf_load_word(&buf));
+ break;
+
+ case 0x1C: // Input cargo multipliers for the three input cargo types
+ case 0x1D:
+ case 0x1E: {
+ uint32 multiples = grf_load_dword(&buf);
+ indsp->input_cargo_multiplier[prop - 0x1C][0] = GB(multiples, 0,15);
+ indsp->input_cargo_multiplier[prop - 0x1C][1] = GB(multiples, 15,15);
+ } break;
+
+ case 0x1F: // Industry name
+ indsp->name = MapGRFStringID(_cur_grffile->grfid, grf_load_word(&buf));
+ break;
+
+ case 0x20: // Prospecting success chance
+ indsp->prospecting_chance = grf_load_dword(&buf);
+ break;
+
+ case 0x21: // Callback flags
+ case 0x22: { // Callback additional flags
+ byte aflag = grf_load_byte(&buf);
+ SB(indsp->callback_flags, (prop - 0x21) * 8, 8, aflag);
+ } break;
+
+ default:
+ ret = true;
+ break;
+ }
}
*bufp = buf;
@@ -1783,36 +2055,30 @@
}
/* Allocate station specs if necessary */
- if (_cur_grffile->stations == NULL) _cur_grffile->stations = CallocT<StationSpec*>(MAX_FSM_PORTS);
-
- statspec = &_cur_grffile->stations[stid];
-
- if (prop != 0x08) {
- /* Check that all stations we are modifying are defined. */
- FOR_EACH_OBJECT {
- if (statspec[i] == NULL) {
- grfmsg(2, "StationChangeInfo: Attempt to modify undefined station %u, ignoring", stid + i);
- return false;
- }
+ if (_cur_grffile->stations == NULL) _cur_grffile->stations = CallocT<StationSpec*>(MAX_STATIONS);
+
+ for (int i = 0; i < numinfo; i++) {
+ StationSpec *statspec = _cur_grffile->stations[stid + i];
+
+ /* Check that the station we are modifying is defined. */
+ if (statspec == NULL && prop != 0x08) {
+ grfmsg(2, "StationChangeInfo: Attempt to modify undefined station %u, ignoring", stid + i);
+ continue;
}
- }
-
- switch (prop) {
- case 0x08: // Class ID
- FOR_EACH_OBJECT {
+
+ switch (prop) {
+ case 0x08: { // Class ID
+ StationSpec **spec = &_cur_grffile->stations[stid + i];
+
/* Property 0x08 is special; it is where the station is allocated */
- if (statspec[i] == NULL) statspec[i] = CallocT<StationSpec>(1);
+ if (*spec == NULL) *spec = CallocT<StationSpec>(1);
/* Swap classid because we read it in BE meaning WAYP or DFLT */
uint32 classid = grf_load_dword(&buf);
- statspec[i]->sclass = AllocateStationClass(BSWAP32(classid));
- }
- break;
-
- case 0x09: // Define sprite layout
- FOR_EACH_OBJECT {
- StationSpec *statspec = _cur_grffile->stations[stid + i];
-
+ (*spec)->sclass = AllocateStationClass(BSWAP32(classid));
+ } break;
+
+ case 0x09: // Define sprite layout
statspec->tiles = grf_load_extended(&buf);
statspec->renderdata = CallocT<DrawTileSprites>(statspec->tiles);
statspec->copied_renderdata = false;
@@ -1863,37 +2129,30 @@
}
}
}
- }
- break;
-
- case 0x0A: // Copy sprite layout
- FOR_EACH_OBJECT {
- StationSpec *statspec = _cur_grffile->stations[stid + i];
+ break;
+
+ case 0x0A: { // Copy sprite layout
byte srcid = grf_load_byte(&buf);
const StationSpec *srcstatspec = _cur_grffile->stations[srcid];
statspec->tiles = srcstatspec->tiles;
statspec->renderdata = srcstatspec->renderdata;
statspec->copied_renderdata = true;
- }
- break;
-
- case 0x0B: // Callback mask
- FOR_EACH_OBJECT statspec[i]->callbackmask = grf_load_byte(&buf);
- break;
-
- case 0x0C: // Disallowed number of platforms
- FOR_EACH_OBJECT statspec[i]->disallowed_platforms = grf_load_byte(&buf);
- break;
-
- case 0x0D: // Disallowed platform lengths
- FOR_EACH_OBJECT statspec[i]->disallowed_lengths = grf_load_byte(&buf);
- break;
-
- case 0x0E: // Define custom layout
- FOR_EACH_OBJECT {
- StationSpec *statspec = _cur_grffile->stations[stid + i];
-
+ } break;
+
+ case 0x0B: // Callback mask
+ statspec->callbackmask = grf_load_byte(&buf);
+ break;
+
+ case 0x0C: // Disallowed number of platforms
+ statspec->disallowed_platforms = grf_load_byte(&buf);
+ break;
+
+ case 0x0D: // Disallowed platform lengths
+ statspec->disallowed_lengths = grf_load_byte(&buf);
+ break;
+
+ case 0x0E: // Define custom layout
statspec->copied_layouts = false;
while (buf < *bufp + len) {
@@ -1940,12 +2199,9 @@
free(statspec->layouts[l][p]);
statspec->layouts[l][p] = layout;
}
- }
- break;
-
- case 0x0F: // Copy custom layout
- FOR_EACH_OBJECT {
- StationSpec *statspec = _cur_grffile->stations[stid + i];
+ break;
+
+ case 0x0F: { // Copy custom layout
byte srcid = grf_load_byte(&buf);
const StationSpec *srcstatspec = _cur_grffile->stations[srcid];
@@ -1953,51 +2209,51 @@
statspec->platforms = srcstatspec->platforms;
statspec->layouts = srcstatspec->layouts;
statspec->copied_layouts = true;
- }
- break;
-
- case 0x10: // Little/lots cargo threshold
- FOR_EACH_OBJECT statspec[i]->cargo_threshold = grf_load_word(&buf);
- break;
-
- case 0x11: // Pylon placement
- FOR_EACH_OBJECT statspec[i]->pylons = grf_load_byte(&buf);
- break;
-
- case 0x12: // Cargo types for random triggers
- FOR_EACH_OBJECT statspec[i]->cargo_triggers = grf_load_dword(&buf);
- break;
-
- case 0x13: // General flags
- FOR_EACH_OBJECT statspec[i]->flags = grf_load_byte(&buf);
- break;
-
- case 0x14: // Overhead wire placement
- FOR_EACH_OBJECT statspec[i]->wires = grf_load_byte(&buf);
- break;
-
- case 0x15: // Blocked tiles
- FOR_EACH_OBJECT statspec[i]->blocked = grf_load_byte(&buf);
- break;
-
- case 0x16: // @todo Animation info
- FOR_EACH_OBJECT grf_load_word(&buf);
- ret = true;
- break;
-
- case 0x17: // @todo Animation speed
- FOR_EACH_OBJECT grf_load_byte(&buf);
- ret = true;
- break;
-
- case 0x18: // @todo Animation triggers
- FOR_EACH_OBJECT grf_load_word(&buf);
- ret = true;
- break;
-
- default:
- ret = true;
- break;
+ } break;
+
+ case 0x10: // Little/lots cargo threshold
+ statspec->cargo_threshold = grf_load_word(&buf);
+ break;
+
+ case 0x11: // Pylon placement
+ statspec->pylons = grf_load_byte(&buf);
+ break;
+
+ case 0x12: // Cargo types for random triggers
+ statspec->cargo_triggers = grf_load_dword(&buf);
+ break;
+
+ case 0x13: // General flags
+ statspec->flags = grf_load_byte(&buf);
+ break;
+
+ case 0x14: // Overhead wire placement
+ statspec->wires = grf_load_byte(&buf);
+ break;
+
+ case 0x15: // Blocked tiles
+ statspec->blocked = grf_load_byte(&buf);
+ break;
+
+ case 0x16: // @todo Animation info
+ grf_load_word(&buf);
+ ret = true;
+ break;
+
+ case 0x17: // @todo Animation speed
+ grf_load_byte(&buf);
+ ret = true;
+ break;
+
+ case 0x18: // @todo Animation triggers
+ grf_load_word(&buf);
+ ret = true;
+ break;
+
+ default:
+ ret = true;
+ break;
+ }
}
*bufp = buf;
@@ -2008,7 +2264,6 @@
static void FeatureChangeInfo(byte *buf, int len)
{
byte *bufend = buf + len;
- uint i;
/* <00> <feature> <num-props> <num-info> <id> (<property <new-info>)...
*
@@ -2033,15 +2288,13 @@
/* GSF_BRIDGE */ BridgeChangeInfo,
/* GSF_TOWNHOUSE */ TownHouseChangeInfo,
/* GSF_GLOBALVAR */ GlobalVarChangeInfo,
- /* GSF_INDUSTRYTILES */NULL,
- /* GSF_INDUSTRIES */ NULL,
+ /* GSF_INDUSTRYTILES */IndustrytilesChangeInfo,
+ /* GSF_INDUSTRIES */ IndustriesChangeInfo,
/* GSF_CARGOS */ NULL, /* Cargo is handled during reservation */
/* GSF_SOUNDFX */ SoundEffectChangeInfo,
/* GSF_FSMPORTS */ FSMPortChangeInfo,
};
- EngineInfo *ei = NULL;
-
if (!check_length(len, 6, "FeatureChangeInfo")) return;
buf++;
uint8 feature = grf_load_byte(&buf);
@@ -2062,7 +2315,6 @@
grfmsg(0, "FeatureChangeInfo: Last engine ID %d out of bounds (max %d), skipping", engine + numinfo, _vehcounts[feature]);
return;
}
- ei = &_engine_info[engine + _vehshifts[feature]];
}
while (numprops-- && buf < bufend) {
@@ -2073,43 +2325,49 @@
case GSF_TRAIN:
case GSF_ROAD:
case GSF_SHIP:
- case GSF_AIRCRAFT:
- /* Common properties for vehicles */
- switch (prop) {
- case 0x00: // Introduction date
- FOR_EACH_OBJECT ei[i].base_intro = grf_load_word(&buf) + DAYS_TILL_ORIGINAL_BASE_YEAR;
- break;
-
- case 0x02: // Decay speed
- FOR_EACH_OBJECT SB(ei[i].unk2, 0, 7, grf_load_byte(&buf) & 0x7F);
- break;
-
- case 0x03: // Vehicle life
- FOR_EACH_OBJECT ei[i].lifelength = grf_load_byte(&buf);
- break;
-
- case 0x04: // Model life
- FOR_EACH_OBJECT ei[i].base_life = grf_load_byte(&buf);
- break;
-
- case 0x06: // Climates available
- FOR_EACH_OBJECT ei[i].climates = grf_load_byte(&buf);
- break;
-
- case 0x07: // Loading speed
- /* Hyronymus explained me what does
- * this mean and insists on having a
- * credit ;-). --pasky */
- FOR_EACH_OBJECT ei[i].load_amount = grf_load_byte(&buf);
- break;
-
- default:
- if (handler[feature](engine, numinfo, prop, &buf, bufend - buf)) {
- ignoring = true;
- }
- break;
+ case GSF_AIRCRAFT: {
+ bool handled = true;
+
+ for (uint i = 0; i < numinfo; i++) {
+ EngineInfo *ei = &_engine_info[engine + _vehshifts[feature] + i];
+
+ /* Common properties for vehicles */
+ switch (prop) {
+ case 0x00: // Introduction date
+ ei->base_intro = grf_load_word(&buf) + DAYS_TILL_ORIGINAL_BASE_YEAR;
+ break;
+
+ case 0x02: // Decay speed
+ SB(ei->unk2, 0, 7, grf_load_byte(&buf) & 0x7F);
+ break;
+
+ case 0x03: // Vehicle life
+ ei->lifelength = grf_load_byte(&buf);
+ break;
+
+ case 0x04: // Model life
+ ei->base_life = grf_load_byte(&buf);
+ break;
+
+ case 0x06: // Climates available
+ ei->climates = grf_load_byte(&buf);
+ break;
+
+ case 0x07: // Loading speed
+ /* Hyronymus explained me what does
+ * this mean and insists on having a
+ * credit ;-). --pasky */
+ ei->load_amount = grf_load_byte(&buf);
+ break;
+
+ default:
+ handled = false;
+ break;
+ }
}
- break;
+
+ if (handled) break;
+ } /* FALL THROUGH */
default:
if (handler[feature](engine, numinfo, prop, &buf, bufend - buf)) {
@@ -2173,8 +2431,7 @@
_cur_grffile->cargo_max = numinfo;
_cur_grffile->cargo_list = MallocT<CargoLabel>(numinfo);
- int i;
- FOR_EACH_OBJECT {
+ for (uint i = 0; i < numinfo; i++) {
CargoLabel cl = grf_load_dword(&buf);
_cur_grffile->cargo_list[i] = BSWAP32(cl);
}
@@ -2209,8 +2466,6 @@
}
}
-#undef FOR_EACH_OBJECT
-
/**
* Creates a spritegroup representing a callback result
* @param value The value that was used to represent this callback result
@@ -2281,7 +2536,7 @@
);
for (uint16 i = 0; i < num_sets * num_ents; i++) {
- LoadNextSprite(_cur_spriteid++, _file_index);
+ LoadNextSprite(_cur_spriteid++, _file_index, _nfo_line);
_nfo_line++;
}
}
@@ -2337,6 +2592,7 @@
if (feature != _cur_grffile->spriteset_feature) {
grfmsg(1, "CreateGroupFromGroupID(0x%02X:0x%02X): Sprite set feature 0x%02X does not match action feature 0x%02X, skipping",
+ setid, type,
_cur_grffile->spriteset_feature, feature);
return NULL;
}
@@ -2535,7 +2791,8 @@
break;
}
- case GSF_TOWNHOUSE: {
+ case GSF_TOWNHOUSE:
+ case GSF_INDUSTRYTILES: {
byte sprites = _cur_grffile->spriteset_numents;
byte num_sprites = max((uint8)1, type);
uint i;
@@ -2615,6 +2872,35 @@
break;
}
+ case GSF_INDUSTRIES: {
+ if (type > 1) {
+ grfmsg(1, "NewSpriteGroup: Unsupported industry production version %d, skipping", type);
+ break;
+ }
+
+ group = AllocateSpriteGroup();
+ group->type = SGT_INDUSTRY_PRODUCTION;
+ group->g.indprod.version = type;
+ if (type == 0) {
+ for (uint i = 0; i < 3; i++) {
+ group->g.indprod.substract_input[i] = grf_load_word(&buf);
+ }
+ for (uint i = 0; i < 2; i++) {
+ group->g.indprod.add_output[i] = grf_load_word(&buf);
+ }
+ group->g.indprod.again = grf_load_byte(&buf);
+ } else {
+ for (uint i = 0; i < 3; i++) {
+ group->g.indprod.substract_input[i] = grf_load_byte(&buf);
+ }
+ for (uint i = 0; i < 2; i++) {
+ group->g.indprod.add_output[i] = grf_load_byte(&buf);
+ }
+ group->g.indprod.again = grf_load_byte(&buf);
+ }
+ break;
+ }
+
/* Loading of Tile Layout and Production Callback groups would happen here */
default: grfmsg(1, "NewSpriteGroup: Unsupported feature %d, skipping", feature);
}
@@ -2741,7 +3027,7 @@
/* Don't tell me you don't love duplicated code! */
if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
- grfmsg(1, "FeatureMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping",
+ grfmsg(1, "VehicleMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping",
groupid, _cur_grffile->spritegroups_count);
continue;
}
@@ -2860,6 +3146,57 @@
}
}
+static void IndustryMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount)
+{
+ if (!HASBIT(_ttdpatch_flags[3], 0x07)) return;
+
+ byte *bp = &buf[4 + idcount + cidcount * 3];
+ uint16 groupid = grf_load_word(&bp);
+
+ if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
+ grfmsg(1, "IndustryMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping.",
+ groupid, _cur_grffile->spritegroups_count);
+ return;
+ }
+
+ for (uint i = 0; i < idcount; i++) {
+ uint8 id = buf[3 + i];
+ IndustrySpec *indsp = _cur_grffile->industryspec[id];
+
+ if (indsp == NULL) {
+ grfmsg(1, "IndustryMapSpriteGroup: Too many industries defined, skipping");
+ return;
+ }
+
+ indsp->grf_prop.spritegroup = _cur_grffile->spritegroups[groupid];
+ }
+}
+
+static void IndustrytileMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount)
+{
+ if (!HASBIT(_ttdpatch_flags[3], 0x07)) return;
+
+ byte *bp = &buf[4 + idcount + cidcount * 3];
+ uint16 groupid = grf_load_word(&bp);
+
+ if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
+ grfmsg(1, "IndustrytileMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping.",
+ groupid, _cur_grffile->spritegroups_count);
+ return;
+ }
+
+ for (uint i = 0; i < idcount; i++) {
+ uint8 id = buf[3 + i];
+ IndustryTileSpec *indtsp = _cur_grffile->indtspec[id];
+
+ if (indtsp == NULL) {
+ grfmsg(1, "IndustrytileMapSpriteGroup: Too many industry tiles defined, skipping");
+ return;
+ }
+
+ indtsp->grf_prop.spritegroup = _cur_grffile->spritegroups[groupid];
+ }
+}
static void CargoMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount)
{
@@ -2949,6 +3286,14 @@
TownHouseMapSpriteGroup(buf, idcount, cidcount);
return;
+ case GSF_INDUSTRIES:
+ IndustryMapSpriteGroup(buf, idcount, cidcount);
+ return;
+
+ case GSF_INDUSTRYTILES:
+ IndustrytileMapSpriteGroup(buf, idcount, cidcount);
+ return;
+
case GSF_CARGOS:
CargoMapSpriteGroup(buf, idcount, cidcount);
return;
@@ -3021,6 +3366,11 @@
}
break;
+ case GSF_INDUSTRIES: {
+ AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_UNDEFINED);
+ break;
+ }
+
case GSF_TOWNHOUSE:
default:
switch (GB(id, 8, 8)) {
@@ -3071,10 +3421,6 @@
}
break;
- case GSF_INDUSTRIES :
- case 0x48 : // for generic strings
- AddGRFString(_cur_spriteid, id, lang, name);
- break;
default :
grfmsg(7, "FeatureNewName: Unsupported feature (0x%02X)", feature);
break;
@@ -3151,7 +3497,7 @@
case 0x0B: // tramways
if (num != 113) {
- grfmsg(1, "GraphicsNews: Tramway graphics sprite count must be 113, skipping");
+ grfmsg(1, "GraphicsNew: Tramway graphics sprite count must be 113, skipping");
return;
}
replace = SPR_TRAMWAY_BASE;
@@ -3184,6 +3530,7 @@
default:
grfmsg(2, "GraphicsNew: Custom graphics (type 0x%02X) sprite block of length %u (unimplemented, ignoring)",
type, num);
+ _skip_sprites = num;
return;
}
@@ -3194,7 +3541,7 @@
}
for (; num > 0; num--) {
- LoadNextSprite(replace == 0 ? _cur_spriteid++ : replace++, _file_index);
+ LoadNextSprite(replace == 0 ? _cur_spriteid++ : replace++, _file_index, _nfo_line);
_nfo_line++;
}
}
@@ -3223,8 +3570,14 @@
case 0x83: // current climate, 0=temp, 1=arctic, 2=trop, 3=toyland
return _opt.landscape;
- case 0x84: // GRF loading stage
- return (_cur_stage > GLS_INIT) | ((_cur_stage == GLS_ACTIVATION) << 9);
+ case 0x84: { // GRF loading stage
+ uint32 res = 0;
+
+ if (_cur_stage > GLS_INIT) SETBIT(res, 0);
+ if (_cur_stage == GLS_RESERVE) SETBIT(res, 8);
+ if (_cur_stage == GLS_ACTIVATION) SETBIT(res, 9);
+ return res;
+ }
case 0x85: // TTDPatch flags, only for bit tests
if (cond_val == NULL) {
@@ -3507,7 +3860,9 @@
_skip_sprites = -1;
/* If an action 8 hasn't been encountered yet, disable the grf. */
- if (_cur_stage != GLS_RESERVE && _cur_grfconfig->status != GCS_ACTIVATED) _cur_grfconfig->status = GCS_DISABLED;
+ if (_cur_grfconfig->status != GCS_ACTIVATED && _cur_grfconfig->status != GCS_INITIALISED) {
+ _cur_grfconfig->status = GCS_DISABLED;
+ }
}
}
@@ -3557,7 +3912,7 @@
_cur_grffile->grfid = grfid;
_cur_grffile->grf_version = version;
- _cur_grfconfig->status = _cur_stage < GLS_ACTIVATION ? GCS_INITIALISED : GCS_ACTIVATED;
+ _cur_grfconfig->status = _cur_stage < GLS_RESERVE ? GCS_INITIALISED : GCS_ACTIVATED;
/* Do swap the GRFID for displaying purposes since people expect that */
DEBUG(grf, 1, "GRFInfo: Loaded GRFv%d set %08lX - %s", version, BSWAP32(grfid), name);
@@ -3586,7 +3941,7 @@
);
for (uint j = 0; j < num_sprites; j++) {
- LoadNextSprite(first_sprite + j, _file_index); // XXX
+ LoadNextSprite(first_sprite + j, _file_index, _nfo_line); // XXX
_nfo_line++;
}
}
@@ -3642,15 +3997,6 @@
STR_NEWGRF_ERROR_MSG_FATAL
};
- /* AddGRFString expects the string to be referred to by an id in the newgrf
- * file. Errors messages are never referred to however, so invent ids that
- * are unlikely to be reached in a newgrf file so they don't overwrite
- * anything else. */
- enum {
- MESSAGE_STRING_ID = MAX_UVALUE(StringID) - 1,
- MESSAGE_DATA_ID = MAX_UVALUE(StringID)
- };
-
if (!check_length(len, 6, "GRFLoadError")) return;
/* For now we can only show one message per newgrf file. */
@@ -3662,10 +4008,13 @@
byte message_id = grf_load_byte(&buf);
len -= 4;
+ /* Skip the error if it isn't valid for the current language. */
+ if (!CheckGrfLangID(lang, _cur_grffile->grf_version)) return;
+
/* Skip the error until the activation stage unless bit 7 of the severity
* is set. */
- if (!HASBIT(severity, 7) && _cur_stage < GLS_ACTIVATION) {
- grfmsg(7, "GRFLoadError: Skipping non-fatal GRFLoadError in stage 1");
+ if (!HASBIT(severity, 7) && _cur_stage == GLS_INIT) {
+ grfmsg(7, "GRFLoadError: Skipping non-fatal GRFLoadError in stage %d", _cur_stage);
return;
}
CLRBIT(severity, 7);
@@ -3691,7 +4040,6 @@
return;
}
- bool new_scheme = _cur_grffile->grf_version >= 7;
GRFError *error = CallocT<GRFError>(1);
error->severity = sevstr[severity];
@@ -3701,7 +4049,7 @@
const char *message = grf_load_string(&buf, len);
len -= (strlen(message) + 1);
- error->message = AddGRFString(_cur_grffile->grfid, MESSAGE_STRING_ID, lang, new_scheme, message, STR_UNDEFINED);
+ error->custom_message = TranslateTTDPatchCodes(message);
} else {
error->message = msgstr[message_id];
}
@@ -3710,7 +4058,7 @@
const char *data = grf_load_string(&buf, len);
len -= (strlen(data) + 1);
- error->data = AddGRFString(_cur_grffile->grfid, MESSAGE_DATA_ID, lang, new_scheme, data, STR_UNDEFINED);
+ error->data = TranslateTTDPatchCodes(data);
}
/* Only two parameter numbers can be used in the string. */
@@ -4131,6 +4479,106 @@
}
}
+/* Action 0x0F */
+static void FeatureTownName(byte *buf, int len)
+{
+ /* <0F> <id> <style-name> <num-parts> <parts>
+ *
+ * B id ID of this definition in bottom 7 bits (final definition if bit 7 set)
+ * V style-name Name of the style (only for final definition)
+ * B num-parts Number of parts in this definition
+ * V parts The parts */
+
+ if (!check_length(len, 1, "FeatureTownName: definition ID")) return;
+ buf++; len--;
+
+ uint32 grfid = _cur_grffile->grfid;
+
+ GRFTownName *townname = AddGRFTownName(grfid);
+
+ byte id = grf_load_byte(&buf);
+ len--;
+ grfmsg(6, "FeatureTownName: definition 0x%02X", id & 0x7F);
+
+ if (HASBIT(id, 7)) {
+ /* Final definition */
+ CLRBIT(id, 7);
+ bool new_scheme = _cur_grffile->grf_version >= 7;
+
+ if (!check_length(len, 1, "FeatureTownName: lang_id")) return;
+ byte lang = grf_load_byte(&buf);
+ len--;
+
+ byte nb_gen = townname->nb_gen;
+ do {
+ CLRBIT(lang, 7);
+
+ if (!check_length(len, 1, "FeatureTownName: style name")) return;
+ const char *name = grf_load_string(&buf, len);
+ len -= strlen(name) + 1;
+ grfmsg(6, "FeatureTownName: lang 0x%X -> '%s'", lang, TranslateTTDPatchCodes(name));
+
+ townname->name[nb_gen] = AddGRFString(grfid, id, lang, new_scheme, name, STR_UNDEFINED);
+
+ if (!check_length(len, 1, "FeatureTownName: lang_id")) return;
+ lang = grf_load_byte(&buf);
+ len--;
+ } while (lang != 0);
+ townname->id[nb_gen] = id;
+ townname->nb_gen++;
+ }
+
+ if (!check_length(len, 1, "FeatureTownName: number of parts")) return;
+ byte nb = grf_load_byte(&buf);
+ len--;
+ grfmsg(6, "FeatureTownName: %d parts", nb, nb);
+
+ townname->nbparts[id] = nb;
+ townname->partlist[id] = CallocT<NamePartList>(nb);
+
+ for (int i = 0; i < nb; i++) {
+ if (!check_length(len, 3, "FeatureTownName: parts header")) return;
+ byte nbtext = grf_load_byte(&buf);
+ townname->partlist[id][i].bitstart = grf_load_byte(&buf);
+ townname->partlist[id][i].bitcount = grf_load_byte(&buf);
+ townname->partlist[id][i].maxprob = 0;
+ townname->partlist[id][i].partcount = nbtext;
+ townname->partlist[id][i].parts = CallocT<NamePart>(nbtext);
+ len -= 3;
+ grfmsg(6, "FeatureTownName: part %d contains %d texts and will use GB(seed, %d, %d)", i, nbtext, townname->partlist[id][i].bitstart, townname->partlist[id][i].bitcount);
+
+ for (int j = 0; j < nbtext; j++) {
+ if (!check_length(len, 2, "FeatureTownName: part")) return;
+ byte prob = grf_load_byte(&buf);
+ len--;
+
+ if (HASBIT(prob, 7)) {
+ byte ref_id = grf_load_byte(&buf);
+ len--;
+
+ if (townname->nbparts[ref_id] == 0) {
+ grfmsg(0, "FeatureTownName: definition 0x%02X doesn't exist, deactivating", ref_id);
+ DelGRFTownName(grfid);
+ _cur_grfconfig->status = GCS_DISABLED;
+ _skip_sprites = -1;
+ return;
+ }
+
+ grfmsg(6, "FeatureTownName: part %d, text %d, uses intermediate definition 0x%02X (with probability %d)", i, j, ref_id, prob & 0x7F);
+ townname->partlist[id][i].parts[j].data.id = ref_id;
+ } else {
+ const char *text = grf_load_string(&buf, len);
+ len -= strlen(text) + 1;
+ townname->partlist[id][i].parts[j].data.text = TranslateTTDPatchCodes(text);
+ grfmsg(6, "FeatureTownName: part %d, text %d, '%s' (with probability %d)", i, j, townname->partlist[id][i].parts[j].data.text, prob);
+ }
+ townname->partlist[id][i].parts[j].prob = prob;
+ townname->partlist[id][i].maxprob += GB(prob, 0, 7);
+ }
+ grfmsg(6, "FeatureTownName: part %d, total probability %d", i, townname->partlist[id][i].maxprob);
+ }
+}
+
/* Action 0x10 */
static void DefineGotoLabel(byte *buf, int len)
{
@@ -4316,7 +4764,7 @@
for (uint c = 0; c < num_char; c++) {
SetUnicodeGlyph(size, base_char + c, _cur_spriteid);
- LoadNextSprite(_cur_spriteid++, _file_index);
+ LoadNextSprite(_cur_spriteid++, _file_index, _nfo_line);
_nfo_line++;
}
}
@@ -4346,8 +4794,12 @@
/* If the file is not active but will be activated later, give an error
* and disable this file. */
GRFError *error = CallocT<GRFError>(1);
+
+ char tmp[256];
+ GetString(tmp, STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE, lastof(tmp));
+ error->data = strdup(tmp);
+
error->message = STR_NEWGRF_ERROR_LOAD_AFTER;
- error->data = STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE;
error->severity = STR_NEWGRF_ERROR_MSG_FATAL;
if (_cur_grfconfig->error != NULL) free(_cur_grfconfig->error);
@@ -4458,7 +4910,7 @@
| (0 << 0x0C) // newagerating
| ((_patches.build_on_slopes ? 1 : 0) << 0x0D) // buildonslopes
| ((_patches.full_load_any ? 1 : 0) << 0x0E) // fullloadany
- | (0 << 0x0F) // planespeed
+ | (1 << 0x0F) // planespeed - TODO depends on patch when implemented
| (0 << 0x10) // moreindustriesperclimate - obsolete
| (0 << 0x11) // moretoylandfeatures
| (1 << 0x12) // newstations
@@ -4470,7 +4922,7 @@
| ((_patches.freight_trains > 1 ? 1 : 0) << 0x18) // freighttrains
| (1 << 0x19) // newhouses
| (1 << 0x1A) // newbridges
- | (0 << 0x1B) // newtownnames
+ | (1 << 0x1B) // newtownnames
| (0 << 0x1C) // moreanimations
| ((_patches.wagon_speed_limits ? 1 : 0) << 0x1D) // wagonspeedlimits
| (1 << 0x1E) // newshistory
@@ -4498,8 +4950,8 @@
| (0 << 0x13) // followvehicle
| (1 << 0x14) // trams
| (0 << 0x15) // enhancetunnels
- | (0 << 0x16) // shortrvs
- | (0 << 0x17) // articulatedrvs
+ | (1 << 0x16) // shortrvs
+ | (1 << 0x17) // articulatedrvs
| (1 << 0x1E); // variablerunningcosts
}
@@ -4548,7 +5000,9 @@
for (file = _first_grffile; file != NULL; file = file->next) {
if (file->housespec == NULL) continue;
- for (i = 0; i < HOUSE_MAX; i++) free(file->housespec[i]);
+ for (i = 0; i < HOUSE_MAX; i++) {
+ free(file->housespec[i]);
+ }
free(file->housespec);
file->housespec = NULL;
@@ -4626,6 +5080,18 @@
_cur_grffile = NULL;
}
+static void ResetNewGRFErrors()
+{
+ for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
+ if (!HASBIT(c->flags, GCF_COPY) && c->error != NULL) {
+ free(c->error->custom_message);
+ free(c->error->data);
+ free(c->error);
+ c->error = NULL;
+ }
+ }
+}
+
/**
* Reset all NewGRF loaded data
* TODO
@@ -4633,6 +5099,7 @@
static void ResetNewGRFData()
{
CleanUpStrings();
+ CleanUpGRFTownNames();
/* Copy/reset original engine info data */
memcpy(&_engine_info, &orig_engine_info, sizeof(orig_engine_info));
@@ -4693,6 +5160,9 @@
/* Reset NewGRF files */
ResetNewGRF();
+ /* Reset NewGRF errors. */
+ ResetNewGRFErrors();
+
/* Add engine type to engine data. This is needed for the refit precalculation. */
AddTypeToEngines();
@@ -4704,7 +5174,9 @@
_traininfo_vehicle_pitch = 0;
_traininfo_vehicle_width = 29;
- _loaded_newgrf_features = 0;
+ _loaded_newgrf_features.has_2CC = false;
+ _loaded_newgrf_features.has_newhouses = false;
+ _loaded_newgrf_features.has_newindustries = false,
_signal_base = 0;
_coast_base = 0;
@@ -4767,7 +5239,7 @@
if (newfile == NULL) error ("Out of memory");
- newfile->filename = strdup(config->full_path);
+ newfile->filename = strdup(config->filename);
newfile->sprite_offset = sprite_offset;
/* Copy the initial parameter list */
@@ -4941,6 +5413,61 @@
}
}
+/** Add all new industries to the industry array. Industry properties can be set at any
+ * time in the GRF file, so we can only add a industry spec to the industry array
+ * after the file has finished loading. */
+static void FinaliseIndustriesArray()
+{
+ for (GRFFile *file = _first_grffile; file != NULL; file = file->next) {
+ if (file->industryspec != NULL) {
+ for (int i = 0; i < NUM_INDUSTRYTYPES; i++) {
+ IndustrySpec *indsp = file->industryspec[i];
+
+ if (indsp != NULL && indsp->enabled) {
+ StringID strid;
+ /* process the conversion of text at the end, so to be sure everything will be fine
+ * and available. Check if it does not return undefind marker, which is a very good sign of a
+ * substitute industry who has not changed the string been examined, thus using it as such */
+ strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->name);
+ if (strid != STR_UNDEFINED) indsp->name = strid;
+
+ strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->closure_text);
+ if (strid != STR_UNDEFINED) indsp->closure_text = strid;
+
+ strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->production_up_text);
+ if (strid != STR_UNDEFINED) indsp->production_up_text = strid;
+
+ strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->production_down_text);
+ if (strid != STR_UNDEFINED) indsp->production_down_text = strid;
+
+ strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->new_industry_text);
+ if (strid != STR_UNDEFINED) indsp->new_industry_text = strid;
+
+ _industry_mngr.SetEntitySpec(indsp);
+ _loaded_newgrf_features.has_newindustries = true;
+ }
+ }
+ }
+
+ if (file->indtspec != NULL) {
+ for (int i = 0; i < NUM_INDUSTRYTILES; i++) {
+ IndustryTileSpec *indtsp = file->indtspec[i];
+ if (indtsp != NULL) {
+ _industile_mngr.SetEntitySpec(indtsp);
+ }
+ }
+ }
+ }
+
+ for (uint j = 0; j < NUM_INDUSTRYTYPES; j++) {
+ IndustrySpec *indsp = &_industry_specs[j];
+ if (indsp->enabled && indsp->grf_prop.grffile != NULL) {
+ for (uint i = 0; i < 3; i++) {
+ indsp->conflicting[i] = MapNewGRFIndustryType(indsp->conflicting[i], indsp->grf_prop.grffile->grfid);
+ }
+ }
+ }
+}
/** Each cargo string needs to be mapped from TTDPatch to OpenTTD string IDs.
* This is done after loading so that strings from Action 4 will be mapped
@@ -4990,14 +5517,14 @@
/* 0x05 */ { SkipAct5, SkipAct5, SkipAct5, SkipAct5, SkipAct5, GraphicsNew, },
/* 0x06 */ { NULL, NULL, NULL, CfgApply, CfgApply, CfgApply, },
/* 0x07 */ { NULL, NULL, NULL, NULL, SkipIf, SkipIf, },
- /* 0x08 */ { ScanInfo, NULL, NULL, GRFInfo, NULL, GRFInfo, },
+ /* 0x08 */ { ScanInfo, NULL, NULL, GRFInfo, GRFInfo, GRFInfo, },
/* 0x09 */ { NULL, NULL, NULL, SkipIf, SkipIf, SkipIf, },
/* 0x0A */ { SkipActA, SkipActA, SkipActA, SkipActA, SkipActA, SpriteReplace, },
/* 0x0B */ { NULL, NULL, NULL, GRFLoadError, GRFLoadError, GRFLoadError, },
/* 0x0C */ { NULL, NULL, NULL, GRFComment, NULL, GRFComment, },
/* 0x0D */ { NULL, SafeParamSet, NULL, ParamSet, ParamSet, ParamSet, },
/* 0x0E */ { NULL, SafeGRFInhibit, NULL, GRFInhibit, GRFInhibit, GRFInhibit, },
- /* 0x0F */ { NULL, NULL, NULL, NULL, NULL, NULL, },
+ /* 0x0F */ { NULL, GRFUnsafe, NULL, FeatureTownName, NULL, NULL, },
/* 0x10 */ { NULL, NULL, DefineGotoLabel, NULL, NULL, NULL, },
/* 0x11 */ { NULL, GRFUnsafe, NULL, NULL, NULL, GRFSound, },
/* 0x12 */ { NULL, NULL, NULL, NULL, NULL, LoadFontGlyph, },
@@ -5044,7 +5571,7 @@
void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage)
{
- const char *filename = config->full_path;
+ const char *filename = config->filename;
uint16 num;
/* A .grf file is activated only if it was active when the game was
@@ -5059,6 +5586,7 @@
if (stage != GLS_FILESCAN && stage != GLS_SAFETYSCAN && stage != GLS_LABELSCAN) {
_cur_grffile = GetFileByFilename(filename);
if (_cur_grffile == NULL) error("File '%s' lost in cache.\n", filename);
+ if (stage == GLS_RESERVE && config->status != GCS_INITIALISED) return;
if (stage == GLS_ACTIVATION && config->status != GCS_INITIALISED) return;
}
@@ -5126,6 +5654,8 @@
void InitDepotWindowBlockSizes();
+extern void SortTownGeneratorNames();
+
static void AfterLoadGRFs()
{
/* Update the bitmasks for the vehicle lists */
@@ -5144,12 +5674,18 @@
/* Add all new houses to the house array. */
FinaliseHouseArray();
+ /* Add all new industries to the industry array. */
+ FinaliseIndustriesArray();
+
/* Create dynamic list of industry legends for smallmap_gui.cpp */
BuildIndustriesLegend();
/* Map cargo strings. This is a separate step because cargos are
* loaded before strings... */
MapNewCargoStrings();
+
+ /* Update the townname generators list */
+ SortTownGeneratorNames();
}
void LoadNewGRF(uint load_index, uint file_index)
@@ -5168,13 +5704,16 @@
_cur_spriteid = load_index;
for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
if (c->status == GCS_DISABLED || c->status == GCS_NOT_FOUND) continue;
+ if (stage > GLS_INIT && HASBIT(c->flags, GCF_INIT_ONLY)) continue;
/* @todo usererror() */
- if (!FileExists(c->full_path)) error("NewGRF file is missing '%s'", c->filename);
+ if (!FioCheckFileExists(c->filename)) error("NewGRF file is missing '%s'", c->filename);
if (stage == GLS_LABELSCAN) InitNewGRFFile(c, _cur_spriteid);
LoadNewGRFFile(c, slot++, stage);
- if (stage == GLS_ACTIVATION) {
+ if (stage == GLS_RESERVE) {
+ if (c->status == GCS_ACTIVATED) c->status = GCS_INITIALISED;
+ } else if (stage == GLS_ACTIVATION) {
ClearTemporaryNewGRFData();
BuildCargoTranslationMap();
DEBUG(sprite, 2, "LoadNewGRF: Currently %i sprites are loaded", _cur_spriteid);