src/newgrf.cpp
changeset 10043 7f8f7df729d3
parent 10042 b77001494a91
child 10062 8ec5e3f048b7
equal deleted inserted replaced
10042:b77001494a91 10043:7f8f7df729d3
   435 		ClrBit(grf_sprite->sprite, 15);
   435 		ClrBit(grf_sprite->sprite, 15);
   436 		SetBit(grf_sprite->sprite, PALETTE_MODIFIER_COLOR);
   436 		SetBit(grf_sprite->sprite, PALETTE_MODIFIER_COLOR);
   437 	}
   437 	}
   438 }
   438 }
   439 
   439 
   440 typedef bool (*VCI_Handler)(uint engine, int numinfo, int prop, byte **buf, int len);
   440 enum ChangeInfoResult {
   441 
   441 	CIR_SUCCESS,    ///< Variable was parsed and read
   442 static bool CommonVehicleChangeInfo(EngineInfo *ei, int prop, byte **buf)
   442 	CIR_UNHANDLED,  ///< Variable was parsed but unread
       
   443 	CIR_UNKNOWN,    ///< Variable is unknown
       
   444 	CIR_INVALID_ID, ///< Attempt to modify an invalid ID
       
   445 };
       
   446 
       
   447 typedef ChangeInfoResult (*VCI_Handler)(uint engine, int numinfo, int prop, byte **buf, int len);
       
   448 
       
   449 static ChangeInfoResult CommonVehicleChangeInfo(EngineInfo *ei, int prop, byte **buf)
   443 {
   450 {
   444 	switch (prop) {
   451 	switch (prop) {
   445 		case 0x00: // Introduction date
   452 		case 0x00: // Introduction date
   446 			ei->base_intro = grf_load_word(buf) + DAYS_TILL_ORIGINAL_BASE_YEAR;
   453 			ei->base_intro = grf_load_word(buf) + DAYS_TILL_ORIGINAL_BASE_YEAR;
   447 			break;
   454 			break;
   469 			/* Amount of cargo loaded during a vehicle's "loading tick" */
   476 			/* Amount of cargo loaded during a vehicle's "loading tick" */
   470 			ei->load_amount = grf_load_byte(buf);
   477 			ei->load_amount = grf_load_byte(buf);
   471 			break;
   478 			break;
   472 
   479 
   473 		default:
   480 		default:
   474 			return false;
   481 			return CIR_UNKNOWN;
   475 	}
   482 	}
   476 
   483 
   477 	return true;
   484 	return CIR_SUCCESS;
   478 }
   485 }
   479 
   486 
   480 static bool RailVehicleChangeInfo(uint engine, int numinfo, int prop, byte **bufp, int len)
   487 static ChangeInfoResult RailVehicleChangeInfo(uint engine, int numinfo, int prop, byte **bufp, int len)
   481 {
   488 {
   482 	byte *buf = *bufp;
   489 	byte *buf = *bufp;
   483 	bool ret = false;
   490 	ChangeInfoResult ret = CIR_SUCCESS;
   484 
   491 
   485 	for (int i = 0; i < numinfo; i++) {
   492 	for (int i = 0; i < numinfo; i++) {
   486 		Engine *e = GetNewEngine(_cur_grffile, VEH_TRAIN, engine + i);
   493 		Engine *e = GetNewEngine(_cur_grffile, VEH_TRAIN, engine + i);
   487 		EngineInfo *ei = &e->info;
   494 		EngineInfo *ei = &e->info;
   488 		RailVehicleInfo *rvi = &e->u.rail;
   495 		RailVehicleInfo *rvi = &e->u.rail;
   653 				break;
   660 				break;
   654 
   661 
   655 			case 0x20: // Air drag
   662 			case 0x20: // Air drag
   656 				/** @todo Air drag for trains. */
   663 				/** @todo Air drag for trains. */
   657 				grf_load_byte(&buf);
   664 				grf_load_byte(&buf);
   658 				ret = true;
   665 				ret = CIR_UNHANDLED;
   659 				break;
   666 				break;
   660 
   667 
   661 			case 0x21: // Shorter vehicle
   668 			case 0x21: // Shorter vehicle
   662 				rvi->shorten_factor = grf_load_byte(&buf);
   669 				rvi->shorten_factor = grf_load_byte(&buf);
   663 				break;
   670 				break;
   705 			case 0x2A: // Long format introduction date (days since year 0)
   712 			case 0x2A: // Long format introduction date (days since year 0)
   706 				ei->base_intro = grf_load_dword(&buf);
   713 				ei->base_intro = grf_load_dword(&buf);
   707 				break;
   714 				break;
   708 
   715 
   709 			default:
   716 			default:
   710 				ret = !CommonVehicleChangeInfo(ei, prop, &buf);
   717 				ret = CommonVehicleChangeInfo(ei, prop, &buf);
   711 				break;
   718 				break;
   712 		}
   719 		}
   713 	}
   720 	}
   714 
   721 
   715 	*bufp = buf;
   722 	*bufp = buf;
   716 	return ret;
   723 	return ret;
   717 }
   724 }
   718 
   725 
   719 static bool RoadVehicleChangeInfo(uint engine, int numinfo, int prop, byte **bufp, int len)
   726 static ChangeInfoResult RoadVehicleChangeInfo(uint engine, int numinfo, int prop, byte **bufp, int len)
   720 {
   727 {
   721 	byte *buf = *bufp;
   728 	byte *buf = *bufp;
   722 	bool ret = false;
   729 	ChangeInfoResult ret = CIR_SUCCESS;
   723 
   730 
   724 	for (int i = 0; i < numinfo; i++) {
   731 	for (int i = 0; i < numinfo; i++) {
   725 		Engine *e = GetNewEngine(_cur_grffile, VEH_ROAD, engine + i);
   732 		Engine *e = GetNewEngine(_cur_grffile, VEH_ROAD, engine + i);
   726 		EngineInfo *ei = &e->info;
   733 		EngineInfo *ei = &e->info;
   727 		RoadVehicleInfo *rvi = &e->u.road;
   734 		RoadVehicleInfo *rvi = &e->u.road;
   794 			case 0x15: // Speed in mph*0.8
   801 			case 0x15: // Speed in mph*0.8
   795 				/** @todo Support for road vehicles realistic power
   802 				/** @todo Support for road vehicles realistic power
   796 				 * computations (called rvpower in TTDPatch) is just
   803 				 * computations (called rvpower in TTDPatch) is just
   797 				 * missing in OTTD yet. --pasky */
   804 				 * missing in OTTD yet. --pasky */
   798 				grf_load_byte(&buf);
   805 				grf_load_byte(&buf);
   799 				ret = true;
   806 				ret = CIR_UNHANDLED;
   800 				break;
   807 				break;
   801 
   808 
   802 			case 0x16: // Cargos available for refitting
   809 			case 0x16: // Cargos available for refitting
   803 				ei->refit_mask = grf_load_dword(&buf);
   810 				ei->refit_mask = grf_load_dword(&buf);
   804 				break;
   811 				break;
   809 
   816 
   810 			case 0x18: // Tractive effort
   817 			case 0x18: // Tractive effort
   811 			case 0x19: // Air drag
   818 			case 0x19: // Air drag
   812 				/** @todo Tractive effort and air drag for road vehicles. */
   819 				/** @todo Tractive effort and air drag for road vehicles. */
   813 				grf_load_byte(&buf);
   820 				grf_load_byte(&buf);
   814 				ret = true;
   821 				ret = CIR_UNHANDLED;
   815 				break;
   822 				break;
   816 
   823 
   817 			case 0x1A: // Refit cost
   824 			case 0x1A: // Refit cost
   818 				ei->refit_cost = grf_load_byte(&buf);
   825 				ei->refit_cost = grf_load_byte(&buf);
   819 				break;
   826 				break;
   842 			case 0x20: // Alter purchase list sort order
   849 			case 0x20: // Alter purchase list sort order
   843 				AlterVehicleListOrder(e->index, grf_load_extended(&buf));
   850 				AlterVehicleListOrder(e->index, grf_load_extended(&buf));
   844 				break;
   851 				break;
   845 
   852 
   846 			default:
   853 			default:
   847 				ret = !CommonVehicleChangeInfo(ei, prop, &buf);
   854 				ret = CommonVehicleChangeInfo(ei, prop, &buf);
   848 				break;
   855 				break;
   849 		}
   856 		}
   850 	}
   857 	}
   851 
   858 
   852 	*bufp = buf;
   859 	*bufp = buf;
   853 	return ret;
   860 	return ret;
   854 }
   861 }
   855 
   862 
   856 static bool ShipVehicleChangeInfo(uint engine, int numinfo, int prop, byte **bufp, int len)
   863 static ChangeInfoResult ShipVehicleChangeInfo(uint engine, int numinfo, int prop, byte **bufp, int len)
   857 {
   864 {
   858 	byte *buf = *bufp;
   865 	byte *buf = *bufp;
   859 	bool ret = false;
   866 	ChangeInfoResult ret = CIR_SUCCESS;
   860 
   867 
   861 	for (int i = 0; i < numinfo; i++) {
   868 	for (int i = 0; i < numinfo; i++) {
   862 		Engine *e = GetNewEngine(_cur_grffile, VEH_SHIP, engine + i);
   869 		Engine *e = GetNewEngine(_cur_grffile, VEH_SHIP, engine + i);
   863 		EngineInfo *ei = &e->info;
   870 		EngineInfo *ei = &e->info;
   864 		ShipVehicleInfo *svi = &e->u.ship;
   871 		ShipVehicleInfo *svi = &e->u.ship;
   926 
   933 
   927 			case 0x14: // Ocean speed fraction
   934 			case 0x14: // Ocean speed fraction
   928 			case 0x15: // Canal speed fraction
   935 			case 0x15: // Canal speed fraction
   929 				/** @todo Speed fractions for ships on oceans and canals */
   936 				/** @todo Speed fractions for ships on oceans and canals */
   930 				grf_load_byte(&buf);
   937 				grf_load_byte(&buf);
   931 				ret = true;
   938 				ret = CIR_UNHANDLED;
   932 				break;
   939 				break;
   933 
   940 
   934 			case 0x16: // Retire vehicle early
   941 			case 0x16: // Retire vehicle early
   935 				ei->retire_early = grf_load_byte(&buf);
   942 				ei->retire_early = grf_load_byte(&buf);
   936 				break;
   943 				break;
   955 			case 0x1B: // Alter purchase list sort order
   962 			case 0x1B: // Alter purchase list sort order
   956 				AlterVehicleListOrder(e->index, grf_load_extended(&buf));
   963 				AlterVehicleListOrder(e->index, grf_load_extended(&buf));
   957 				break;
   964 				break;
   958 
   965 
   959 			default:
   966 			default:
   960 				ret = !CommonVehicleChangeInfo(ei, prop, &buf);
   967 				ret = CommonVehicleChangeInfo(ei, prop, &buf);
   961 				break;
   968 				break;
   962 		}
   969 		}
   963 	}
   970 	}
   964 
   971 
   965 	*bufp = buf;
   972 	*bufp = buf;
   966 	return ret;
   973 	return ret;
   967 }
   974 }
   968 
   975 
   969 static bool AircraftVehicleChangeInfo(uint engine, int numinfo, int prop, byte **bufp, int len)
   976 static ChangeInfoResult AircraftVehicleChangeInfo(uint engine, int numinfo, int prop, byte **bufp, int len)
   970 {
   977 {
   971 	byte *buf = *bufp;
   978 	byte *buf = *bufp;
   972 	bool ret = false;
   979 	ChangeInfoResult ret = CIR_SUCCESS;
   973 
   980 
   974 	for (int i = 0; i < numinfo; i++) {
   981 	for (int i = 0; i < numinfo; i++) {
   975 		Engine *e = GetNewEngine(_cur_grffile, VEH_AIRCRAFT, engine + i);
   982 		Engine *e = GetNewEngine(_cur_grffile, VEH_AIRCRAFT, engine + i);
   976 		EngineInfo *ei = &e->info;
   983 		EngineInfo *ei = &e->info;
   977 		AircraftVehicleInfo *avi = &e->u.air;
   984 		AircraftVehicleInfo *avi = &e->u.air;
  1064 			case 0x1B: // Alter purchase list sort order
  1071 			case 0x1B: // Alter purchase list sort order
  1065 				AlterVehicleListOrder(e->index, grf_load_extended(&buf));
  1072 				AlterVehicleListOrder(e->index, grf_load_extended(&buf));
  1066 				break;
  1073 				break;
  1067 
  1074 
  1068 			default:
  1075 			default:
  1069 				ret = !CommonVehicleChangeInfo(ei, prop, &buf);
  1076 				ret = CommonVehicleChangeInfo(ei, prop, &buf);
  1070 				break;
  1077 				break;
  1071 		}
  1078 		}
  1072 	}
  1079 	}
  1073 
  1080 
  1074 	*bufp = buf;
  1081 	*bufp = buf;
  1075 	return ret;
  1082 	return ret;
  1076 }
  1083 }
  1077 
  1084 
  1078 static bool StationChangeInfo(uint stid, int numinfo, int prop, byte **bufp, int len)
  1085 static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, byte **bufp, int len)
  1079 {
  1086 {
  1080 	byte *buf = *bufp;
  1087 	byte *buf = *bufp;
  1081 	bool ret = false;
  1088 	ChangeInfoResult ret = CIR_SUCCESS;
  1082 
  1089 
  1083 	if (stid + numinfo > MAX_STATIONS) {
  1090 	if (stid + numinfo > MAX_STATIONS) {
  1084 		grfmsg(1, "StationChangeInfo: Station %u is invalid, max %u, ignoring", stid + numinfo, MAX_STATIONS);
  1091 		grfmsg(1, "StationChangeInfo: Station %u is invalid, max %u, ignoring", stid + numinfo, MAX_STATIONS);
  1085 		return false;
  1092 		return CIR_INVALID_ID;
  1086 	}
  1093 	}
  1087 
  1094 
  1088 	/* Allocate station specs if necessary */
  1095 	/* Allocate station specs if necessary */
  1089 	if (_cur_grffile->stations == NULL) _cur_grffile->stations = CallocT<StationSpec*>(MAX_STATIONS);
  1096 	if (_cur_grffile->stations == NULL) _cur_grffile->stations = CallocT<StationSpec*>(MAX_STATIONS);
  1090 
  1097 
  1092 		StationSpec *statspec = _cur_grffile->stations[stid + i];
  1099 		StationSpec *statspec = _cur_grffile->stations[stid + i];
  1093 
  1100 
  1094 		/* Check that the station we are modifying is defined. */
  1101 		/* Check that the station we are modifying is defined. */
  1095 		if (statspec == NULL && prop != 0x08) {
  1102 		if (statspec == NULL && prop != 0x08) {
  1096 			grfmsg(2, "StationChangeInfo: Attempt to modify undefined station %u, ignoring", stid + i);
  1103 			grfmsg(2, "StationChangeInfo: Attempt to modify undefined station %u, ignoring", stid + i);
  1097 			return false;
  1104 			return CIR_INVALID_ID;
  1098 		}
  1105 		}
  1099 
  1106 
  1100 		switch (prop) {
  1107 		switch (prop) {
  1101 			case 0x08: { // Class ID
  1108 			case 0x08: { // Class ID
  1102 				StationSpec **spec = &_cur_grffile->stations[stid + i];
  1109 				StationSpec **spec = &_cur_grffile->stations[stid + i];
  1273 			case 0x18: // Animation triggers
  1280 			case 0x18: // Animation triggers
  1274 				statspec->anim_triggers = grf_load_word(&buf);
  1281 				statspec->anim_triggers = grf_load_word(&buf);
  1275 				break;
  1282 				break;
  1276 
  1283 
  1277 			default:
  1284 			default:
  1278 				ret = true;
  1285 				ret = CIR_UNKNOWN;
  1279 				break;
  1286 				break;
  1280 		}
  1287 		}
  1281 	}
  1288 	}
  1282 
  1289 
  1283 	*bufp = buf;
  1290 	*bufp = buf;
  1284 	return ret;
  1291 	return ret;
  1285 }
  1292 }
  1286 
  1293 
  1287 static bool CanalChangeInfo(uint id, int numinfo, int prop, byte **bufp, int len)
  1294 static ChangeInfoResult CanalChangeInfo(uint id, int numinfo, int prop, byte **bufp, int len)
  1288 {
  1295 {
  1289 	byte *buf = *bufp;
  1296 	byte *buf = *bufp;
  1290 	bool ret = false;
  1297 	ChangeInfoResult ret = CIR_SUCCESS;
  1291 
  1298 
  1292 	if (id + numinfo > CF_END) {
  1299 	if (id + numinfo > CF_END) {
  1293 		grfmsg(1, "CanalChangeInfo: Canal feature %u is invalid, max %u, ignoreing", id + numinfo, CF_END);
  1300 		grfmsg(1, "CanalChangeInfo: Canal feature %u is invalid, max %u, ignoreing", id + numinfo, CF_END);
  1294 		return false;
  1301 		return CIR_INVALID_ID;
  1295 	}
  1302 	}
  1296 
  1303 
  1297 	for (int i = 0; i < numinfo; i++) {
  1304 	for (int i = 0; i < numinfo; i++) {
  1298 		WaterFeature *wf = &_water_feature[id + i];
  1305 		WaterFeature *wf = &_water_feature[id + i];
  1299 
  1306 
  1305 			case 0x09:
  1312 			case 0x09:
  1306 				wf->flags = grf_load_byte(&buf);
  1313 				wf->flags = grf_load_byte(&buf);
  1307 				break;
  1314 				break;
  1308 
  1315 
  1309 			default:
  1316 			default:
  1310 				ret = true;
  1317 				ret = CIR_UNKNOWN;
  1311 				break;
  1318 				break;
  1312 		}
  1319 		}
  1313 	}
  1320 	}
  1314 
  1321 
  1315 	*bufp = buf;
  1322 	*bufp = buf;
  1316 	return ret;
  1323 	return ret;
  1317 }
  1324 }
  1318 
  1325 
  1319 static bool BridgeChangeInfo(uint brid, int numinfo, int prop, byte **bufp, int len)
  1326 static ChangeInfoResult BridgeChangeInfo(uint brid, int numinfo, int prop, byte **bufp, int len)
  1320 {
  1327 {
  1321 	byte *buf = *bufp;
  1328 	byte *buf = *bufp;
  1322 	bool ret = false;
  1329 	ChangeInfoResult ret = CIR_SUCCESS;
  1323 
  1330 
  1324 	if (brid + numinfo > MAX_BRIDGES) {
  1331 	if (brid + numinfo > MAX_BRIDGES) {
  1325 		grfmsg(1, "BridgeChangeInfo: Bridge %u is invalid, max %u, ignoring", brid + numinfo, MAX_BRIDGES);
  1332 		grfmsg(1, "BridgeChangeInfo: Bridge %u is invalid, max %u, ignoring", brid + numinfo, MAX_BRIDGES);
  1326 		return false;
  1333 		return CIR_INVALID_ID;
  1327 	}
  1334 	}
  1328 
  1335 
  1329 	for (int i = 0; i < numinfo; i++) {
  1336 	for (int i = 0; i < numinfo; i++) {
  1330 		BridgeSpec *bridge = &_bridge[brid + i];
  1337 		BridgeSpec *bridge = &_bridge[brid + i];
  1331 
  1338 
  1404 			case 0x13: // 16 bits cost multiplier
  1411 			case 0x13: // 16 bits cost multiplier
  1405 				bridge->price = grf_load_word(&buf);
  1412 				bridge->price = grf_load_word(&buf);
  1406 				break;
  1413 				break;
  1407 
  1414 
  1408 			default:
  1415 			default:
  1409 				ret = true;
  1416 				ret = CIR_UNKNOWN;
  1410 				break;
  1417 				break;
  1411 		}
  1418 		}
  1412 	}
  1419 	}
  1413 
  1420 
  1414 	*bufp = buf;
  1421 	*bufp = buf;
  1415 	return ret;
  1422 	return ret;
  1416 }
  1423 }
  1417 
  1424 
  1418 static bool TownHouseChangeInfo(uint hid, int numinfo, int prop, byte **bufp, int len)
  1425 static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, byte **bufp, int len)
  1419 {
  1426 {
  1420 	byte *buf = *bufp;
  1427 	byte *buf = *bufp;
  1421 	bool ret = false;
  1428 	ChangeInfoResult ret = CIR_SUCCESS;
  1422 
  1429 
  1423 	if (hid + numinfo > HOUSE_MAX) {
  1430 	if (hid + numinfo > HOUSE_MAX) {
  1424 		grfmsg(1, "TownHouseChangeInfo: Too many houses loaded (%u), max (%u). Ignoring.", hid + numinfo, HOUSE_MAX);
  1431 		grfmsg(1, "TownHouseChangeInfo: Too many houses loaded (%u), max (%u). Ignoring.", hid + numinfo, HOUSE_MAX);
  1425 		return false;
  1432 		return CIR_INVALID_ID;
  1426 	}
  1433 	}
  1427 
  1434 
  1428 	/* Allocate house specs if they haven't been allocated already. */
  1435 	/* Allocate house specs if they haven't been allocated already. */
  1429 	if (_cur_grffile->housespec == NULL) {
  1436 	if (_cur_grffile->housespec == NULL) {
  1430 		_cur_grffile->housespec = CallocT<HouseSpec*>(HOUSE_MAX);
  1437 		_cur_grffile->housespec = CallocT<HouseSpec*>(HOUSE_MAX);
  1433 	for (int i = 0; i < numinfo; i++) {
  1440 	for (int i = 0; i < numinfo; i++) {
  1434 		HouseSpec *housespec = _cur_grffile->housespec[hid + i];
  1441 		HouseSpec *housespec = _cur_grffile->housespec[hid + i];
  1435 
  1442 
  1436 		if (prop != 0x08 && housespec == NULL) {
  1443 		if (prop != 0x08 && housespec == NULL) {
  1437 			grfmsg(2, "TownHouseChangeInfo: Attempt to modify undefined house %u. Ignoring.", hid + i);
  1444 			grfmsg(2, "TownHouseChangeInfo: Attempt to modify undefined house %u. Ignoring.", hid + i);
  1438 			return false;
  1445 			return CIR_INVALID_ID;
  1439 		}
  1446 		}
  1440 
  1447 
  1441 		switch (prop) {
  1448 		switch (prop) {
  1442 			case 0x08: { // Substitute building type, and definition of a new house
  1449 			case 0x08: { // Substitute building type, and definition of a new house
  1443 				HouseSpec **house = &_cur_grffile->housespec[hid + i];
  1450 				HouseSpec **house = &_cur_grffile->housespec[hid + i];
  1616 				break;
  1623 				break;
  1617 
  1624 
  1618 			case 0x20: { // @todo Cargo acceptance watch list
  1625 			case 0x20: { // @todo Cargo acceptance watch list
  1619 				byte count = grf_load_byte(&buf);
  1626 				byte count = grf_load_byte(&buf);
  1620 				for (byte j = 0; j < count; j++) grf_load_byte(&buf);
  1627 				for (byte j = 0; j < count; j++) grf_load_byte(&buf);
  1621 				ret = true;
  1628 				ret = CIR_UNHANDLED;
  1622 			} break;
  1629 			} break;
  1623 
  1630 
  1624 			case 0x21: // long introduction year
  1631 			case 0x21: // long introduction year
  1625 				housespec->min_year = grf_load_word(&buf);
  1632 				housespec->min_year = grf_load_word(&buf);
  1626 				break;
  1633 				break;
  1628 			case 0x22: // long maximum year
  1635 			case 0x22: // long maximum year
  1629 				housespec->max_year = grf_load_word(&buf);
  1636 				housespec->max_year = grf_load_word(&buf);
  1630 				break;
  1637 				break;
  1631 
  1638 
  1632 			default:
  1639 			default:
  1633 				ret = true;
  1640 				ret = CIR_UNKNOWN;
  1634 				break;
  1641 				break;
  1635 		}
  1642 		}
  1636 	}
  1643 	}
  1637 
  1644 
  1638 	*bufp = buf;
  1645 	*bufp = buf;
  1639 	return ret;
  1646 	return ret;
  1640 }
  1647 }
  1641 
  1648 
  1642 static bool GlobalVarChangeInfo(uint gvid, int numinfo, int prop, byte **bufp, int len)
  1649 static ChangeInfoResult GlobalVarChangeInfo(uint gvid, int numinfo, int prop, byte **bufp, int len)
  1643 {
  1650 {
  1644 	byte *buf = *bufp;
  1651 	byte *buf = *bufp;
  1645 	bool ret = false;
  1652 	ChangeInfoResult ret = CIR_SUCCESS;
  1646 
  1653 
  1647 	for (int i = 0; i < numinfo; i++) {
  1654 	for (int i = 0; i < numinfo; i++) {
  1648 		switch (prop) {
  1655 		switch (prop) {
  1649 			case 0x08: { // Cost base factor
  1656 			case 0x08: { // Cost base factor
  1650 				byte factor = grf_load_byte(&buf);
  1657 				byte factor = grf_load_byte(&buf);
  1757 				/* Each entry is 8 bytes. */
  1764 				/* Each entry is 8 bytes. */
  1758 				buf += 8;
  1765 				buf += 8;
  1759 				break;
  1766 				break;
  1760 
  1767 
  1761 			default:
  1768 			default:
  1762 				ret = true;
  1769 				ret = CIR_UNKNOWN;
  1763 				break;
  1770 				break;
  1764 		}
  1771 		}
  1765 	}
  1772 	}
  1766 
  1773 
  1767 	*bufp = buf;
  1774 	*bufp = buf;
  1768 	return ret;
  1775 	return ret;
  1769 }
  1776 }
  1770 
  1777 
  1771 static bool CargoChangeInfo(uint cid, int numinfo, int prop, byte **bufp, int len)
  1778 static ChangeInfoResult CargoChangeInfo(uint cid, int numinfo, int prop, byte **bufp, int len)
  1772 {
  1779 {
  1773 	byte *buf = *bufp;
  1780 	byte *buf = *bufp;
  1774 	bool ret = false;
  1781 	ChangeInfoResult ret = CIR_SUCCESS;
  1775 
  1782 
  1776 	if (cid + numinfo > NUM_CARGO) {
  1783 	if (cid + numinfo > NUM_CARGO) {
  1777 		grfmsg(2, "CargoChangeInfo: Cargo type %d out of range (max %d)", cid + numinfo, NUM_CARGO - 1);
  1784 		grfmsg(2, "CargoChangeInfo: Cargo type %d out of range (max %d)", cid + numinfo, NUM_CARGO - 1);
  1778 		return false;
  1785 		return CIR_INVALID_ID;
  1779 	}
  1786 	}
  1780 
  1787 
  1781 	for (int i = 0; i < numinfo; i++) {
  1788 	for (int i = 0; i < numinfo; i++) {
  1782 		CargoSpec *cs = &_cargo[cid + i];
  1789 		CargoSpec *cs = &_cargo[cid + i];
  1783 
  1790 
  1882 			case 0x1A: /* Bitmask of callbacks to use */
  1889 			case 0x1A: /* Bitmask of callbacks to use */
  1883 				cs->callback_mask = grf_load_byte(&buf);
  1890 				cs->callback_mask = grf_load_byte(&buf);
  1884 				break;
  1891 				break;
  1885 
  1892 
  1886 			default:
  1893 			default:
  1887 				ret = true;
  1894 				ret = CIR_UNKNOWN;
  1888 				break;
  1895 				break;
  1889 		}
  1896 		}
  1890 	}
  1897 	}
  1891 
  1898 
  1892 	*bufp = buf;
  1899 	*bufp = buf;
  1893 	return ret;
  1900 	return ret;
  1894 }
  1901 }
  1895 
  1902 
  1896 
  1903 
  1897 static bool SoundEffectChangeInfo(uint sid, int numinfo, int prop, byte **bufp, int len)
  1904 static ChangeInfoResult SoundEffectChangeInfo(uint sid, int numinfo, int prop, byte **bufp, int len)
  1898 {
  1905 {
  1899 	byte *buf = *bufp;
  1906 	byte *buf = *bufp;
  1900 	bool ret = false;
  1907 	ChangeInfoResult ret = CIR_SUCCESS;
  1901 
  1908 
  1902 	if (_cur_grffile->sound_offset == 0) {
  1909 	if (_cur_grffile->sound_offset == 0) {
  1903 		grfmsg(1, "SoundEffectChangeInfo: No effects defined, skipping");
  1910 		grfmsg(1, "SoundEffectChangeInfo: No effects defined, skipping");
  1904 		return false;
  1911 		return CIR_INVALID_ID;
  1905 	}
  1912 	}
  1906 
  1913 
  1907 	for (int i = 0; i < numinfo; i++) {
  1914 	for (int i = 0; i < numinfo; i++) {
  1908 		uint sound = sid + i + _cur_grffile->sound_offset - GetNumOriginalSounds();
  1915 		uint sound = sid + i + _cur_grffile->sound_offset - GetNumOriginalSounds();
  1909 
  1916 
  1910 		if (sound >= GetNumSounds()) {
  1917 		if (sound >= GetNumSounds()) {
  1911 			grfmsg(1, "SoundEffectChangeInfo: Sound %d not defined (max %d)", sound, GetNumSounds());
  1918 			grfmsg(1, "SoundEffectChangeInfo: Sound %d not defined (max %d)", sound, GetNumSounds());
  1912 			return false;
  1919 			return CIR_INVALID_ID;
  1913 		}
  1920 		}
  1914 
  1921 
  1915 		switch (prop) {
  1922 		switch (prop) {
  1916 			case 0x08: // Relative volume
  1923 			case 0x08: // Relative volume
  1917 				GetSound(sound)->volume = grf_load_byte(&buf);
  1924 				GetSound(sound)->volume = grf_load_byte(&buf);
  1934 					*oldfe = *newfe;
  1941 					*oldfe = *newfe;
  1935 				}
  1942 				}
  1936 			} break;
  1943 			} break;
  1937 
  1944 
  1938 			default:
  1945 			default:
  1939 				ret = true;
  1946 				ret = CIR_UNKNOWN;
  1940 				break;
  1947 				break;
  1941 		}
  1948 		}
  1942 	}
  1949 	}
  1943 
  1950 
  1944 	*bufp = buf;
  1951 	*bufp = buf;
  1945 	return ret;
  1952 	return ret;
  1946 }
  1953 }
  1947 
  1954 
  1948 static bool IndustrytilesChangeInfo(uint indtid, int numinfo, int prop, byte **bufp, int len)
  1955 static ChangeInfoResult IndustrytilesChangeInfo(uint indtid, int numinfo, int prop, byte **bufp, int len)
  1949 {
  1956 {
  1950 	byte *buf = *bufp;
  1957 	byte *buf = *bufp;
  1951 	bool ret = false;
  1958 	ChangeInfoResult ret = CIR_SUCCESS;
  1952 
  1959 
  1953 	if (indtid + numinfo > NUM_INDUSTRYTILES) {
  1960 	if (indtid + numinfo > NUM_INDUSTRYTILES) {
  1954 		grfmsg(1, "IndustryTilesChangeInfo: Too many industry tiles loaded (%u), max (%u). Ignoring.", indtid + numinfo, NUM_INDUSTRYTILES);
  1961 		grfmsg(1, "IndustryTilesChangeInfo: Too many industry tiles loaded (%u), max (%u). Ignoring.", indtid + numinfo, NUM_INDUSTRYTILES);
  1955 		return false;
  1962 		return CIR_INVALID_ID;
  1956 	}
  1963 	}
  1957 
  1964 
  1958 	/* Allocate industry tile specs if they haven't been allocated already. */
  1965 	/* Allocate industry tile specs if they haven't been allocated already. */
  1959 	if (_cur_grffile->indtspec == NULL) {
  1966 	if (_cur_grffile->indtspec == NULL) {
  1960 		_cur_grffile->indtspec = CallocT<IndustryTileSpec*>(NUM_INDUSTRYTILES);
  1967 		_cur_grffile->indtspec = CallocT<IndustryTileSpec*>(NUM_INDUSTRYTILES);
  1963 	for (int i = 0; i < numinfo; i++) {
  1970 	for (int i = 0; i < numinfo; i++) {
  1964 		IndustryTileSpec *tsp = _cur_grffile->indtspec[indtid + i];
  1971 		IndustryTileSpec *tsp = _cur_grffile->indtspec[indtid + i];
  1965 
  1972 
  1966 		if (prop != 0x08 && tsp == NULL) {
  1973 		if (prop != 0x08 && tsp == NULL) {
  1967 			grfmsg(2, "IndustryTilesChangeInfo: Attempt to modify undefined industry tile %u. Ignoring.", indtid + i);
  1974 			grfmsg(2, "IndustryTilesChangeInfo: Attempt to modify undefined industry tile %u. Ignoring.", indtid + i);
  1968 			return false;
  1975 			return CIR_INVALID_ID;
  1969 		}
  1976 		}
  1970 
  1977 
  1971 		switch (prop) {
  1978 		switch (prop) {
  1972 			case 0x08: { // Substitute industry tile type
  1979 			case 0x08: { // Substitute industry tile type
  1973 				IndustryTileSpec **tilespec = &_cur_grffile->indtspec[indtid + i];
  1980 				IndustryTileSpec **tilespec = &_cur_grffile->indtspec[indtid + i];
  2044 			case 0x12: // Special flags
  2051 			case 0x12: // Special flags
  2045 				tsp->animation_special_flags = grf_load_byte(&buf);
  2052 				tsp->animation_special_flags = grf_load_byte(&buf);
  2046 				break;
  2053 				break;
  2047 
  2054 
  2048 			default:
  2055 			default:
  2049 				ret = true;
  2056 				ret = CIR_UNKNOWN;
  2050 				break;
  2057 				break;
  2051 		}
  2058 		}
  2052 	}
  2059 	}
  2053 
  2060 
  2054 	*bufp = buf;
  2061 	*bufp = buf;
  2055 	return ret;
  2062 	return ret;
  2056 }
  2063 }
  2057 
  2064 
  2058 static bool IndustriesChangeInfo(uint indid, int numinfo, int prop, byte **bufp, int len)
  2065 static ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop, byte **bufp, int len)
  2059 {
  2066 {
  2060 	byte *buf = *bufp;
  2067 	byte *buf = *bufp;
  2061 	bool ret = false;
  2068 	ChangeInfoResult ret = CIR_SUCCESS;
  2062 
  2069 
  2063 	if (indid + numinfo > NUM_INDUSTRYTYPES) {
  2070 	if (indid + numinfo > NUM_INDUSTRYTYPES) {
  2064 		grfmsg(1, "IndustriesChangeInfo: Too many industries loaded (%u), max (%u). Ignoring.", indid + numinfo, NUM_INDUSTRYTYPES);
  2071 		grfmsg(1, "IndustriesChangeInfo: Too many industries loaded (%u), max (%u). Ignoring.", indid + numinfo, NUM_INDUSTRYTYPES);
  2065 		return false;
  2072 		return CIR_INVALID_ID;
  2066 	}
  2073 	}
  2067 
  2074 
  2068 	grfmsg(1, "IndustriesChangeInfo: newid %u", indid);
  2075 	grfmsg(1, "IndustriesChangeInfo: newid %u", indid);
  2069 
  2076 
  2070 	/* Allocate industry specs if they haven't been allocated already. */
  2077 	/* Allocate industry specs if they haven't been allocated already. */
  2075 	for (int i = 0; i < numinfo; i++) {
  2082 	for (int i = 0; i < numinfo; i++) {
  2076 		IndustrySpec *indsp = _cur_grffile->industryspec[indid + i];
  2083 		IndustrySpec *indsp = _cur_grffile->industryspec[indid + i];
  2077 
  2084 
  2078 		if (prop != 0x08 && indsp == NULL) {
  2085 		if (prop != 0x08 && indsp == NULL) {
  2079 			grfmsg(2, "IndustriesChangeInfo: Attempt to modify undefined industry %u. Ignoring.", indid + i);
  2086 			grfmsg(2, "IndustriesChangeInfo: Attempt to modify undefined industry %u. Ignoring.", indid + i);
  2080 			return false;
  2087 			return CIR_INVALID_ID;
  2081 		}
  2088 		}
  2082 
  2089 
  2083 		switch (prop) {
  2090 		switch (prop) {
  2084 			case 0x08: { // Substitute industry type
  2091 			case 0x08: { // Substitute industry type
  2085 				IndustrySpec **indspec = &_cur_grffile->industryspec[indid + i];
  2092 				IndustrySpec **indspec = &_cur_grffile->industryspec[indid + i];
  2305 				indsp->station_name = grf_load_word(&buf);
  2312 				indsp->station_name = grf_load_word(&buf);
  2306 				_string_to_grf_mapping[&indsp->station_name] = _cur_grffile->grfid;
  2313 				_string_to_grf_mapping[&indsp->station_name] = _cur_grffile->grfid;
  2307 				break;
  2314 				break;
  2308 
  2315 
  2309 			default:
  2316 			default:
  2310 				ret = true;
  2317 				ret = CIR_UNKNOWN;
  2311 				break;
  2318 				break;
  2312 		}
  2319 		}
  2313 	}
  2320 	}
  2314 
  2321 
  2315 	*bufp = buf;
  2322 	*bufp = buf;
  2366 	}
  2373 	}
  2367 
  2374 
  2368 	while (numprops-- && buf < bufend) {
  2375 	while (numprops-- && buf < bufend) {
  2369 		uint8 prop = grf_load_byte(&buf);
  2376 		uint8 prop = grf_load_byte(&buf);
  2370 
  2377 
  2371 		if (handler[feature](engine, numinfo, prop, &buf, bufend - buf)) {
  2378 		ChangeInfoResult cir = handler[feature](engine, numinfo, prop, &buf, bufend - buf);
  2372 			grfmsg(1, "FeatureChangeInfo: Ignoring property 0x%02X of feature 0x%02X (not implemented)", prop, feature);
  2379 		switch (cir) {
       
  2380 			case CIR_SUCCESS:
       
  2381 				break;
       
  2382 
       
  2383 			case CIR_UNHANDLED:
       
  2384 				grfmsg(1, "FeatureChangeInfo: Ignoring property 0x%02X of feature 0x%02X (not implemented)", prop, feature);
       
  2385 				break;
       
  2386 
       
  2387 			case CIR_UNKNOWN:
       
  2388 				grfmsg(0, "FeatureChangeInfo: Unknown property 0x%02X of feature 0x%02X, disabling", prop, feature);
       
  2389 				/* Fall through */
       
  2390 
       
  2391 			case CIR_INVALID_ID:
       
  2392 				/* No debug message for an invalid ID, as it has already been output */
       
  2393 				_skip_sprites = -1;
       
  2394 				_cur_grfconfig->status = GCS_DISABLED;
       
  2395 				_cur_grfconfig->error  = CallocT<GRFError>(1);
       
  2396 				_cur_grfconfig->error->severity = STR_NEWGRF_ERROR_MSG_FATAL;
       
  2397 				_cur_grfconfig->error->message  = (cir == CIR_INVALID_ID) ? STR_NEWGRF_ERROR_INVALID_ID : STR_NEWGRF_ERROR_UNKNOWN_PROPERTY;
       
  2398 				return;
  2373 		}
  2399 		}
  2374 	}
  2400 	}
  2375 }
  2401 }
  2376 
  2402 
  2377 /* Action 0x00 (GLS_SAFETYSCAN) */
  2403 /* Action 0x00 (GLS_SAFETYSCAN) */