diff -r 9b1552d0fd9b -r f8eb3e208514 src/newgrf.cpp --- a/src/newgrf.cpp Thu Feb 21 22:34:54 2008 +0000 +++ b/src/newgrf.cpp Fri Feb 22 00:25:54 2008 +0000 @@ -93,23 +93,6 @@ static GrfDataType _grf_data_type; -enum grfspec_feature { - GSF_TRAIN, - GSF_ROAD, - GSF_SHIP, - GSF_AIRCRAFT, - GSF_STATION, - GSF_CANAL, - GSF_BRIDGE, - GSF_TOWNHOUSE, - GSF_GLOBALVAR, - GSF_INDUSTRYTILES, - GSF_INDUSTRIES, - GSF_CARGOS, - GSF_SOUNDFX, -}; - - typedef void (*SpecialSpriteHandler)(byte *buf, int len); static const uint _vehcounts[4] = { @@ -306,6 +289,26 @@ return colour; } +/** Map the colour modifiers of TTDPatch to those that Open is using. + * @param grf_sprite pointer to the structure been modified + */ +static void MapSpriteMappingRecolour(PalSpriteID *grf_sprite) +{ + if (HasBit(grf_sprite->pal, 14)) { + ClrBit(grf_sprite->pal, 14); + SetBit(grf_sprite->sprite, SPRITE_MODIFIER_OPAQUE); + } + + if (HasBit(grf_sprite->sprite, 14)) { + ClrBit(grf_sprite->sprite, 14); + SetBit(grf_sprite->sprite, PALETTE_MODIFIER_TRANSPARENT); + } + + if (HasBit(grf_sprite->sprite, 15)) { + ClrBit(grf_sprite->sprite, 15); + SetBit(grf_sprite->sprite, PALETTE_MODIFIER_COLOR); + } +} typedef bool (*VCI_Handler)(uint engine, int numinfo, int prop, byte **buf, int len); @@ -374,20 +377,22 @@ if (rvi->railveh_type == RAILVEH_MULTIHEAD) runcostfact /= 2; - rvi->running_cost_base = runcostfact; + rvi->running_cost = runcostfact; } break; case 0x0E: { // Running cost base uint32 base = grf_load_dword(&buf); - switch (base) { - 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; + /* These magic numbers are used in GRFs to specify the base cost: + * http://wiki.ttdpatch.net/tiki-index.php?page=BaseCosts + */ + if (base == 0) { + rvi->running_cost_class = 0xFF; + } else if (base < 0x4B34 || base > 0x4C54 || (base - 0x4B34) % 6 != 0) { + grfmsg(1, "RailVehicleChangeInfo: Unsupported running cost base 0x%04X, ignoring", base); + } else { + /* Convert the magic number to an index into the price data */ + rvi->running_cost_class = (base - 0x4B34) / 6; } } break; @@ -408,14 +413,14 @@ if (rvi->railveh_type != RAILVEH_MULTIHEAD) { // adjust power and running cost if needed rvi->power /= 2; - rvi->running_cost_base /= 2; + rvi->running_cost /= 2; } rvi->railveh_type = RAILVEH_MULTIHEAD; } else { if (rvi->railveh_type == RAILVEH_MULTIHEAD) { // adjust power and running cost if needed rvi->power *= 2; - rvi->running_cost_base *= 2; + rvi->running_cost *= 2; } rvi->railveh_type = rvi->power == 0 ? RAILVEH_WAGON : RAILVEH_SINGLEHEAD; @@ -591,12 +596,23 @@ 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 0x0A: { // Running cost base + uint32 base= grf_load_dword(&buf); + + /* These magic numbers are used in GRFs to specify the base cost: + * http://wiki.ttdpatch.net/tiki-index.php?page=BaseCosts + */ + if (base == 0) { + rvi->running_cost_class = 0xFF; + } else if (base < 0x4B34 || base > 0x4C54 || (base - 0x4B34) % 6 != 0) { + grfmsg(1, "RailVehicleChangeInfo: Unsupported running cost base 0x%04X, ignoring", base); + } else { + /* Convert the magic number to an index into the price data */ + rvi->running_cost_class = (base - 0x4B34) / 6; + } + + break; + } case 0x0E: { // Sprite ID uint8 spriteid = grf_load_byte(&buf); @@ -946,25 +962,15 @@ uint seq_count = 0; dts->seq = NULL; - dts->ground_sprite = grf_load_word(&buf); - dts->ground_pal = grf_load_word(&buf); - if (dts->ground_sprite == 0) continue; - if (HasBit(dts->ground_pal, 15)) { - ClrBit(dts->ground_pal, 15); - SetBit(dts->ground_sprite, SPRITE_MODIFIER_USE_OFFSET); + dts->ground.sprite = grf_load_word(&buf); + dts->ground.pal = grf_load_word(&buf); + if (dts->ground.sprite == 0) continue; + if (HasBit(dts->ground.pal, 15)) { + ClrBit(dts->ground.pal, 15); + SetBit(dts->ground.sprite, SPRITE_MODIFIER_USE_OFFSET); } - if (HasBit(dts->ground_pal, 14)) { - ClrBit(dts->ground_pal, 14); - SetBit(dts->ground_sprite, SPRITE_MODIFIER_OPAQUE); - } - if (HasBit(dts->ground_sprite, 15)) { - ClrBit(dts->ground_sprite, 15); - SetBit(dts->ground_sprite, PALETTE_MODIFIER_COLOR); - } - if (HasBit(dts->ground_sprite, 14)) { - ClrBit(dts->ground_sprite, 14); - SetBit(dts->ground_sprite, PALETTE_MODIFIER_TRANSPARENT); - } + + MapSpriteMappingRecolour(&dts->ground); while (buf < *bufp + len) { DrawTileSeqStruct *dtss; @@ -980,27 +986,16 @@ dtss->size_x = grf_load_byte(&buf); dtss->size_y = grf_load_byte(&buf); dtss->size_z = grf_load_byte(&buf); - dtss->image = grf_load_word(&buf); - dtss->pal = grf_load_word(&buf); + dtss->image.sprite = grf_load_word(&buf); + dtss->image.pal = grf_load_word(&buf); /* Remap flags as ours collide */ - if (HasBit(dtss->pal, 15)) { - ClrBit(dtss->pal, 15); - SetBit(dtss->image, SPRITE_MODIFIER_USE_OFFSET); - } - if (HasBit(dtss->pal, 14)) { - ClrBit(dtss->pal, 14); - SetBit(dtss->image, SPRITE_MODIFIER_OPAQUE); + if (HasBit(dtss->image.pal, 15)) { + ClrBit(dtss->image.pal, 15); + SetBit(dtss->image.sprite, SPRITE_MODIFIER_USE_OFFSET); } - if (HasBit(dtss->image, 15)) { - ClrBit(dtss->image, 15); - SetBit(dtss->image, PALETTE_MODIFIER_COLOR); - } - if (HasBit(dtss->image, 14)) { - ClrBit(dtss->image, 14); - SetBit(dtss->image, PALETTE_MODIFIER_TRANSPARENT); - } + MapSpriteMappingRecolour(&dtss->image); } } break; @@ -1177,7 +1172,7 @@ } for (int i = 0; i < numinfo; i++) { - Bridge *bridge = &_bridge[brid + i]; + BridgeSpec *bridge = &_bridge[brid + i]; switch (prop) { case 0x08: // Year of availability @@ -1224,15 +1219,10 @@ SpriteID image = grf_load_word(&buf); SpriteID pal = grf_load_word(&buf); - if (HasBit(pal, 15)) { - SetBit(image, PALETTE_MODIFIER_TRANSPARENT); - } - - /* Clear old color modifer bit */ - ClrBit(image, 15); - bridge->sprite_table[tableid][sprite].sprite = image; bridge->sprite_table[tableid][sprite].pal = pal; + + MapSpriteMappingRecolour(&bridge->sprite_table[tableid][sprite]); } } } break; @@ -1245,6 +1235,17 @@ bridge->avail_year = Clamp(grf_load_dword(&buf), MIN_YEAR, MAX_YEAR); break; + case 0x10: { // purchase string + StringID newone = GetGRFStringID(_cur_grffile->grfid, grf_load_word(&buf)); + if (newone != STR_UNDEFINED) bridge->material = newone; + } break; + + case 0x11: // description of bridge with rails or roads + case 0x12: { + StringID newone = GetGRFStringID(_cur_grffile->grfid, grf_load_word(&buf)); + if (newone != STR_UNDEFINED) bridge->transport_name[prop - 0x11] = newone; + } break; + default: ret = true; break; @@ -1488,21 +1489,11 @@ } } break; - case 0x09: { // Cargo translation table - if (gvid != 0) { - if (i == 0) grfmsg(1, "InitChangeInfo: Cargo translation table must start at zero"); - /* Skip data */ - buf += 4; - break; - } - if (i == 0) { - free(_cur_grffile->cargo_list); - _cur_grffile->cargo_max = numinfo; - _cur_grffile->cargo_list = MallocT(numinfo); - } - CargoLabel cl = grf_load_dword(&buf); - _cur_grffile->cargo_list[i] = BSWAP32(cl); - } break; + case 0x09: // Cargo translation table + /* This is loaded during the reservation stage, so just skip it here. */ + /* Each entry is 4 bytes. */ + buf += 4; + break; case 0x0A: { // Currency display names uint curidx = GetNewgrfCurrencyIdConverted(gvid + i); @@ -2127,7 +2118,7 @@ break; case 0x24: // name for nearby station - indsp->station_name = GRFMappedStringID(grf_load_dword(&buf), _cur_grffile->grfid); + indsp->station_name = GRFMappedStringID(grf_load_word(&buf), _cur_grffile->grfid); break; default: @@ -2167,7 +2158,7 @@ /* GSF_CANAL */ CanalChangeInfo, /* GSF_BRIDGE */ BridgeChangeInfo, /* GSF_TOWNHOUSE */ TownHouseChangeInfo, - /* GSF_GLOBALVAR */ NULL, /* Global variables are handled during reservation */ + /* GSF_GLOBALVAR */ GlobalVarChangeInfo, /* GSF_INDUSTRYTILES */IndustrytilesChangeInfo, /* GSF_INDUSTRIES */ IndustriesChangeInfo, /* GSF_CARGOS */ NULL, /* Cargo is handled during reservation */ @@ -2287,7 +2278,7 @@ { byte *bufend = buf + len; - if (!check_length(len, 6, "InitChangeInfo")) return; + if (!check_length(len, 6, "ReserveChangeInfo")) return; buf++; uint8 feature = grf_load_byte(&buf); @@ -2307,7 +2298,23 @@ ignoring = CargoChangeInfo(index, numinfo, prop, &buf, bufend - buf); break; case GSF_GLOBALVAR: - ignoring = GlobalVarChangeInfo(index, numinfo, prop, &buf, bufend - buf); + switch (prop) { + case 0x09: // Cargo Translation Table + if (index != 0) { + grfmsg(1, "ReserveChangeInfo: Cargo translation table must start at zero"); + return; + } + + free(_cur_grffile->cargo_list); + _cur_grffile->cargo_max = numinfo; + _cur_grffile->cargo_list = MallocT(numinfo); + + for (uint i = 0; i < numinfo; i++) { + CargoLabel cl = grf_load_dword(&buf); + _cur_grffile->cargo_list[i] = BSWAP32(cl); + } + break; + } break; } @@ -2652,27 +2659,18 @@ group->g.layout.dts = CallocT(1); /* Groundsprite */ - group->g.layout.dts->ground_sprite = grf_load_word(&buf); - group->g.layout.dts->ground_pal = grf_load_word(&buf); + group->g.layout.dts->ground.sprite = grf_load_word(&buf); + group->g.layout.dts->ground.pal = grf_load_word(&buf); + /* Remap transparent/colour modifier bits */ - if (HasBit(group->g.layout.dts->ground_sprite, 14)) { - ClrBit(group->g.layout.dts->ground_sprite, 14); - SetBit(group->g.layout.dts->ground_sprite, PALETTE_MODIFIER_TRANSPARENT); - } - if (HasBit(group->g.layout.dts->ground_sprite, 15)) { - ClrBit(group->g.layout.dts->ground_sprite, 15); - SetBit(group->g.layout.dts->ground_sprite, PALETTE_MODIFIER_COLOR); - } - if (HasBit(group->g.layout.dts->ground_pal, 14)) { - ClrBit(group->g.layout.dts->ground_pal, 14); - SetBit(group->g.layout.dts->ground_sprite, SPRITE_MODIFIER_OPAQUE); - } - if (HasBit(group->g.layout.dts->ground_pal, 15)) { + MapSpriteMappingRecolour(&group->g.layout.dts->ground); + + if (HasBit(group->g.layout.dts->ground.pal, 15)) { /* Bit 31 set means this is a custom sprite, so rewrite it to the * last spriteset defined. */ - SpriteID sprite = _cur_grffile->spriteset_start + GB(group->g.layout.dts->ground_sprite, 0, 14) * sprites; - SB(group->g.layout.dts->ground_sprite, 0, SPRITE_WIDTH, sprite); - ClrBit(group->g.layout.dts->ground_pal, 15); + SpriteID sprite = _cur_grffile->spriteset_start + GB(group->g.layout.dts->ground.sprite, 0, 14) * sprites; + SB(group->g.layout.dts->ground.sprite, 0, SPRITE_WIDTH, sprite); + ClrBit(group->g.layout.dts->ground.pal, 15); } group->g.layout.dts->seq = CallocT(num_sprites + 1); @@ -2680,29 +2678,19 @@ for (i = 0; i < num_sprites; i++) { DrawTileSeqStruct *seq = (DrawTileSeqStruct*)&group->g.layout.dts->seq[i]; - seq->image = grf_load_word(&buf); - seq->pal = grf_load_word(&buf); + seq->image.sprite = grf_load_word(&buf); + seq->image.pal = grf_load_word(&buf); seq->delta_x = grf_load_byte(&buf); seq->delta_y = grf_load_byte(&buf); - if (HasBit(seq->image, 14)) { - ClrBit(seq->image, 14); - SetBit(seq->image, PALETTE_MODIFIER_TRANSPARENT); - } - if (HasBit(seq->image, 15)) { - ClrBit(seq->image, 15); - SetBit(seq->image, PALETTE_MODIFIER_COLOR); - } - if (HasBit(seq->pal, 14)) { - ClrBit(seq->pal, 14); - SetBit(seq->image, SPRITE_MODIFIER_OPAQUE); - } - if (HasBit(seq->pal, 15)) { + MapSpriteMappingRecolour(&seq->image); + + if (HasBit(seq->image.pal, 15)) { /* Bit 31 set means this is a custom sprite, so rewrite it to the * last spriteset defined. */ - SpriteID sprite = _cur_grffile->spriteset_start + GB(seq->image, 0, 14) * sprites; - SB(seq->image, 0, SPRITE_WIDTH, sprite); - ClrBit(seq->pal, 15); + SpriteID sprite = _cur_grffile->spriteset_start + GB(seq->image.sprite, 0, 14) * sprites; + SB(seq->image.sprite, 0, SPRITE_WIDTH, sprite); + ClrBit(seq->image.pal, 15); } if (type > 0) { @@ -3089,6 +3077,11 @@ * W cid cargo ID (sprite group ID) for this type of cargo * W def-cid default cargo ID (sprite group ID) */ + if (_cur_grffile->spritegroups == 0) { + grfmsg(1, "FeatureMapSpriteGroup: No sprite groups to work on! Skipping"); + return; + } + if (!check_length(len, 6, "FeatureMapSpriteGroup")) return; uint8 feature = buf[1]; @@ -3099,7 +3092,12 @@ /* If idcount is zero, this is a feature callback */ if (idcount == 0) { - grfmsg(2, "FeatureMapSpriteGroup: Feature callbacks not implemented yet"); + byte *bp = &buf[4]; + uint16 groupid = grf_load_word(&bp); + + grfmsg(6, "FeatureMapSpriteGroup: Adding generic feature callback for feature %d", feature); + + AddGenericCallback(feature, _cur_grffile, _cur_grffile->spritegroups[groupid]); return; } @@ -3109,11 +3107,6 @@ grfmsg(6, "FeatureMapSpriteGroup: Feature %d, %d ids, %d cids, wagon override %d", feature, idcount, cidcount, wagover); - if (_cur_grffile->spritegroups == 0) { - grfmsg(1, "FeatureMapSpriteGroup: No sprite groups to work on! Skipping"); - return; - } - switch (feature) { case GSF_TRAIN: case GSF_ROAD: @@ -3435,15 +3428,131 @@ grfmsg(3, "SkipAct5: Skipping %d sprites", _skip_sprites); } -static uint32 GetParamVal(byte param, uint32 *cond_val) +/** + * Reads a variable common to VarAction2 and Action7/9/D. + * + * Returns VarAction2 variable 'param' resp. Action7/9/D variable '0x80 + param'. + * If a variable is not accessible from all four actions, it is handled in the action specific functions. + * + * @param param variable number (as for VarAction2, for Action7/9/D you have to subtract 0x80 first). + * @param value returns the value of the variable. + * @return true iff the variable is known and the value is returned in 'value'. + */ +bool GetGlobalVariable(byte param, uint32 *value) { switch (param) { - case 0x81: // current year - return Clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; - - case 0x83: // current climate, 0=temp, 1=arctic, 2=trop, 3=toyland - return _opt.landscape; - + case 0x00: // current date + *value = max(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0); + return true; + + case 0x01: // current year + *value = Clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; + return true; + + case 0x02: // current month + *value = _cur_month; + return true; + + case 0x03: // current climate, 0=temp, 1=arctic, 2=trop, 3=toyland + *value = _opt.landscape; + return true; + + case 0x06: // road traffic side, bit 4 clear=left, set=right + *value = _opt.road_side << 4; + return true; + + case 0x09: // date fraction + *value = _date_fract; + return true; + + case 0x0A: // animation counter + *value = _tick_counter; + return true; + + case 0x0B: { // TTDPatch version + uint major = 2; + uint minor = 6; + uint revision = 1; // special case: 2.0.1 is 2.0.10 + uint build = 1382; + *value = (major << 24) | (minor << 20) | (revision << 16) | build; + return true; + } + + case 0x0D: // TTD Version, 00=DOS, 01=Windows + *value = !_use_dos_palette; + return true; + + case 0x0E: // Y-offset for train sprites + *value = _traininfo_vehicle_pitch; + return true; + + case 0x0F: // Rail track type cost factors + *value = 0; + SB(*value, 0, 8, _railtype_cost_multiplier[0]); // normal rail + if (_patches.disable_elrails) { + /* skip elrail multiplier - disabled */ + SB(*value, 8, 8, _railtype_cost_multiplier[2]); // monorail + } else { + SB(*value, 8, 8, _railtype_cost_multiplier[1]); // electified railway + /* Skip monorail multiplier - no space in result */ + } + SB(*value, 16, 8, _railtype_cost_multiplier[3]); // maglev + return true; + + case 0x11: // current rail tool type + *value = 0; + return true; + + case 0x12: // Game mode + *value = _game_mode; + return true; + + /* case 0x13: // Tile refresh offset to left not implemented */ + /* case 0x14: // Tile refresh offset to right not implemented */ + /* case 0x15: // Tile refresh offset upwards not implemented */ + /* case 0x16: // Tile refresh offset downwards not implemented */ + /* case 0x17: // temperate snow line not implemented */ + + case 0x1A: // Always -1 + *value = UINT_MAX; + return true; + + case 0x1B: // Display options + *value = GB(_display_opt, 0, 6); + return true; + + case 0x1D: // TTD Platform, 00=TTDPatch, 01=OpenTTD + *value = 1; + return true; + + case 0x1E: // Miscellaneous GRF features + *value = _misc_grf_features; + return true; + + /* case 0x1F: // locale dependent settings not implemented */ + + case 0x20: // snow line height + *value = _opt.landscape == LT_ARCTIC ? GetSnowLine() : 0xFF; + return true; + + case 0x21: { // OpenTTD version + extern uint32 _openttd_newgrf_version; + *value = _openttd_newgrf_version; + return true; + } + + default: return false; + } +} + +static uint32 GetParamVal(byte param, uint32 *cond_val) +{ + /* First handle variable common with VarAction2 */ + uint32 value; + if (GetGlobalVariable(param - 0x80, &value)) return value; + + /* Non-common variable */ + switch (param) { case 0x84: { // GRF loading stage uint32 res = 0; @@ -3463,42 +3572,10 @@ return param_val; } - case 0x86: // road traffic side, bit 4 clear=left, set=right - return _opt.road_side << 4; - case 0x88: // GRF ID check return 0; - case 0x8B: { // TTDPatch version - uint major = 2; - uint minor = 6; - uint revision = 1; // special case: 2.0.1 is 2.0.10 - uint build = 1382; - return (major << 24) | (minor << 20) | (revision << 16) | build; - } - - case 0x8D: // TTD Version, 00=DOS, 01=Windows - return !_use_dos_palette; - - case 0x8E: // Y-offset for train sprites - return _traininfo_vehicle_pitch; - - case 0x92: // Game mode - return _game_mode; - - case 0x9A: // Always -1 - return UINT_MAX; - - case 0x9D: // TTD Platform, 00=TTDPatch, 01=OpenTTD - return 1; - - case 0x9E: // Miscellaneous GRF features - return _misc_grf_features; - - case 0xA1: { // OpenTTD version - extern uint32 _openttd_newgrf_version; - return _openttd_newgrf_version; - } + /* case 0x99: Global ID offest not implemented */ default: /* GRF Parameter */ @@ -4352,6 +4429,10 @@ _traininfo_vehicle_width = HasGrfMiscBit(GMB_TRAIN_WIDTH_32_PIXELS) ? 32 : 29; break; + case 0x9F: // locale-dependent settings + grfmsg(7, "ParamSet: Skipping unimplemented target 0x%02X", target); + break; + default: if (target < 0x80) { _cur_grffile->param[target] = res; @@ -5085,15 +5166,8 @@ /* Copy/reset original engine info data */ SetupEngines(); - /* Copy/reset original bridge info data - * First, free sprite table data */ - for (uint i = 0; i < MAX_BRIDGES; i++) { - if (_bridge[i].sprite_table != NULL) { - for (uint j = 0; j < 7; j++) free(_bridge[i].sprite_table[j]); - free(_bridge[i].sprite_table); - } - } - memcpy(&_bridge, &orig_bridge, sizeof(_bridge)); + /* Copy/reset original bridge info data */ + ResetBridges(); /* Reset refit/cargo class data */ memset(&cargo_allowed, 0, sizeof(cargo_allowed)); @@ -5108,6 +5182,9 @@ UnloadCustomEngineSprites(); ResetEngineListOrder(); + /* Reset generic feature callback lists */ + ResetGenericCallbacks(); + /* Reset price base data */ ResetPriceBaseMultipliers();