diff --git a/changelog.txt b/changelog.txt index 21486983f3..48a3304c15 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,16 @@ +0.6.2 (2008-??-??) +------------------------------------------------------------------------ +- Fix: NewGRF Callback 10 (visual effect and powered wagons setting) and powered wagons operation were not performed for articulated wagons [FS#2167] (r13870) +- Fix: In some cases the sprite cache could be filled with unremovable items [FS#2153] (r13869) +- Fix: Return of wrong parent scope of (NewGRF) industry variables (r13868) +- Fix: Loading of TTD(Patch) savegames from the command line did not work (r13859) +- Fix: Buffer overflow for too long filename supplied as '-g' parameter (r13858) +- Fix: Cargo type lookup was incorrect for NewGRF version 7 files without a translation table [FS#2157] (r13855) +- Fix: GetTownByTile() is only valid for houses and roads (r13851) +- Fix: Power, running cost and capacity of multiheaded engines were (too often) doubled in newspaper resp. offer window (r13844) +- Fix: FreeType may return a bitmap glyph even if a grey-scale glyph was requested [FS#2152] (r13832) + + 0.6.2-RC2 (2008-07-25) ------------------------------------------------------------------------ - Fix: Building through the wrong side of a drive through station was allowed [FS#2166] (r13822) diff --git a/src/engine_gui.cpp b/src/engine_gui.cpp index 51bfc30760..9125027b05 100644 --- a/src/engine_gui.cpp +++ b/src/engine_gui.cpp @@ -14,6 +14,7 @@ #include "variables.h" #include "newgrf_engine.h" #include "strings_func.h" +#include "articulated_vehicles.h" #include "table/strings.h" #include "table/sprites.h" @@ -116,21 +117,34 @@ void ShowEnginePreviewWindow(EngineID engine) AllocateWindowDescFront(&_engine_preview_desc, engine); } +static uint GetTotalCapacityOfArticulatedParts(EngineID engine, VehicleType type) +{ + uint total = 0; + + uint16 *cap = GetCapacityOfArticulatedParts(engine, type); + for (uint c = 0; c < NUM_CARGO; c++) { + total += cap[c]; + } + + return total; +} + static void DrawTrainEngineInfo(EngineID engine, int x, int y, int maxw) { const RailVehicleInfo *rvi = RailVehInfo(engine); int multihead = (rvi->railveh_type == RAILVEH_MULTIHEAD) ? 1 : 0; - SetDParam(0, (_price.build_railvehicle >> 3) * rvi->base_cost >> 5); - SetDParam(2, rvi->max_speed * 10 / 16); - SetDParam(3, rvi->power << multihead); - SetDParam(1, rvi->weight << multihead); + SetDParam(0, (_price.build_railvehicle >> 3) * GetEngineProperty(engine, 0x17, rvi->base_cost) >> 5); + SetDParam(2, GetEngineProperty(engine, 0x09, rvi->max_speed) * 10 / 16); + SetDParam(3, GetEngineProperty(engine, 0x0B, rvi->power)); + SetDParam(1, GetEngineProperty(engine, 0x16, rvi->weight) << multihead); - SetDParam(4, rvi->running_cost * GetPriceByIndex(rvi->running_cost_class) >> 8 << multihead); + SetDParam(4, GetEngineProperty(engine, 0x0D, rvi->running_cost) * GetPriceByIndex(rvi->running_cost_class) >> 8); - if (rvi->capacity != 0) { + uint capacity = GetTotalCapacityOfArticulatedParts(engine, VEH_TRAIN); + if (capacity != 0) { SetDParam(5, rvi->cargo_type); - SetDParam(6, rvi->capacity << multihead); + SetDParam(6, capacity); } else { SetDParam(5, CT_INVALID); } @@ -140,11 +154,11 @@ static void DrawTrainEngineInfo(EngineID engine, int x, int y, int maxw) static void DrawAircraftEngineInfo(EngineID engine, int x, int y, int maxw) { const AircraftVehicleInfo *avi = AircraftVehInfo(engine); - SetDParam(0, (_price.aircraft_base >> 3) * avi->base_cost >> 5); + SetDParam(0, (_price.aircraft_base >> 3) * GetEngineProperty(engine, 0x0B, avi->base_cost) >> 5); SetDParam(1, avi->max_speed * 10 / 16); SetDParam(2, avi->passenger_capacity); SetDParam(3, avi->mail_capacity); - SetDParam(4, avi->running_cost * _price.aircraft_running >> 8); + SetDParam(4, GetEngineProperty(engine, 0x0E, avi->running_cost) * _price.aircraft_running >> 8); DrawStringMultiCenter(x, y, STR_A02E_COST_MAX_SPEED_CAPACITY, maxw); } @@ -153,11 +167,11 @@ static void DrawRoadVehEngineInfo(EngineID engine, int x, int y, int maxw) { const RoadVehicleInfo *rvi = RoadVehInfo(engine); - SetDParam(0, (_price.roadveh_base >> 3) * rvi->base_cost >> 5); + SetDParam(0, (_price.roadveh_base >> 3) * GetEngineProperty(engine, 0x11, rvi->base_cost) >> 5); SetDParam(1, rvi->max_speed * 10 / 32); SetDParam(2, rvi->running_cost * GetPriceByIndex(rvi->running_cost_class) >> 8); SetDParam(3, rvi->cargo_type); - SetDParam(4, rvi->capacity); + SetDParam(4, GetTotalCapacityOfArticulatedParts(engine, VEH_ROAD)); DrawStringMultiCenter(x, y, STR_902A_COST_SPEED_RUNNING_COST, maxw); } @@ -165,11 +179,11 @@ static void DrawRoadVehEngineInfo(EngineID engine, int x, int y, int maxw) static void DrawShipEngineInfo(EngineID engine, int x, int y, int maxw) { const ShipVehicleInfo *svi = ShipVehInfo(engine); - SetDParam(0, svi->base_cost * (_price.ship_base >> 3) >> 5); - SetDParam(1, svi->max_speed * 10 / 32); + SetDParam(0, GetEngineProperty(engine, 0x0A, svi->base_cost) * (_price.ship_base >> 3) >> 5); + SetDParam(1, GetEngineProperty(engine, 0x0B, svi->max_speed) * 10 / 32); SetDParam(2, svi->cargo_type); - SetDParam(3, svi->capacity); - SetDParam(4, svi->running_cost * _price.ship_running >> 8); + SetDParam(3, GetEngineProperty(engine, 0x0D, svi->capacity)); + SetDParam(4, GetEngineProperty(engine, 0x0F, svi->running_cost) * _price.ship_running >> 8); DrawStringMultiCenter(x, y, STR_982E_COST_MAX_SPEED_CAPACITY, maxw); } diff --git a/src/fios.cpp b/src/fios.cpp index b34939f32a..6d557d3540 100644 --- a/src/fios.cpp +++ b/src/fios.cpp @@ -308,12 +308,12 @@ static FiosItem *FiosGetFileList(int mode, fios_getlist_callback_proc *callback_ * @param mode Save/load mode. * @param file Name of the file to check. * @param ext A pointer to the extension identifier inside file - * @param title Buffer if a callback wants to lookup the title of the file + * @param title Buffer if a callback wants to lookup the title of the file; NULL to skip the lookup * @return a FIOS_TYPE_* type of the found file, FIOS_TYPE_INVALID if not a savegame * @see FiosGetFileList * @see FiosGetSavegameList */ -static byte FiosGetSavegameListCallback(int mode, const char *file, const char *ext, char *title) +byte FiosGetSavegameListCallback(int mode, const char *file, const char *ext, char *title) { /* Show savegame files * .SAV OpenTTD saved game @@ -325,7 +325,7 @@ static byte FiosGetSavegameListCallback(int mode, const char *file, const char * if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO) { if (strcasecmp(ext, ".ss1") == 0 || strcasecmp(ext, ".sv1") == 0 || strcasecmp(ext, ".sv2") == 0) { - GetOldSaveGameName(title, _fios_path, file); + if (title != NULL) GetOldSaveGameName(title, _fios_path, file); return FIOS_TYPE_OLDFILE; } } diff --git a/src/fios.h b/src/fios.h index ccc5482867..e71abe966f 100644 --- a/src/fios.h +++ b/src/fios.h @@ -42,7 +42,7 @@ enum FileType { FT_HEIGHTMAP, ///< heightmap file }; -enum { +enum FiosType { FIOS_TYPE_DRIVE = 0, FIOS_TYPE_PARENT = 1, FIOS_TYPE_DIR = 2, @@ -99,6 +99,8 @@ bool FiosDelete(const char *name); void FiosMakeSavegameName(char *buf, const char *name, size_t size); /* Allocate a new FiosItem */ FiosItem *FiosAlloc(); +/* Determines type of savegame (or tells it is not a savegame) */ +byte FiosGetSavegameListCallback(int mode, const char *file, const char *ext, char *title); int CDECL compare_FiosItems(const void *a, const void *b); diff --git a/src/fontcache.cpp b/src/fontcache.cpp index 14c735c02f..4774279b92 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -415,6 +415,9 @@ const Sprite *GetGlyph(FontSize size, WChar key) FT_Load_Char(face, key, FT_LOAD_DEFAULT); FT_Render_Glyph(face->glyph, aa ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO); + /* Despite requesting a normal glyph, FreeType may have returned a bitmap */ + aa = (slot->bitmap.palette_mode == FT_PIXEL_MODE_GRAY); + /* Add 1 pixel for the shadow on the medium font. Our sprite must be at least 1x1 pixel */ width = max(1, slot->bitmap.width + (size == FS_NORMAL)); height = max(1, slot->bitmap.rows + (size == FS_NORMAL)); diff --git a/src/newgrf_cargo.cpp b/src/newgrf_cargo.cpp index d43f61019c..b38ea52522 100644 --- a/src/newgrf_cargo.cpp +++ b/src/newgrf_cargo.cpp @@ -106,9 +106,15 @@ CargoID GetCargoTranslation(uint8 cargo, const GRFFile *grffile, bool usebit) /* Else the cargo value is a 'climate independent' 'bitnum' */ if (HasBit(_cargo_mask, cargo)) return GetCargoIDByBitnum(cargo); } else { - /* If the GRF contains a translation table (and the cargo is in bounds) - * then get the cargo ID for the label */ - if (cargo < grffile->cargo_max) return GetCargoIDByLabel(grffile->cargo_list[cargo]); + /* If the GRF contains a translation table... */ + if (grffile->cargo_max > 0) { + /* ...and the cargo is in bounds, then get the cargo ID for + * the label */ + if (cargo < grffile->cargo_max) return GetCargoIDByLabel(grffile->cargo_list[cargo]); + } else { + /* Else the cargo value is a 'climate independent' 'bitnum' */ + if (HasBit(_cargo_mask, cargo)) return GetCargoIDByBitnum(cargo); + } } return CT_INVALID; } diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp index 618458d6ba..b84762230d 100644 --- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -210,6 +210,23 @@ uint32 IndustryGetVariable(const ResolverObject *object, byte variable, byte par IndustryType type = object->u.industry.type; const IndustrySpec *indspec = GetIndustrySpec(type); + /* Shall the variable get resolved in parent scope and are we not yet in parent scope? */ + if (object->u.industry.gfx == INVALID_INDUSTRYTILE && object->scope == VSG_SCOPE_PARENT) { + /* Pass the request on to the town of the industry */ + const Town *t; + + if (industry != NULL) { + t = industry->town; + } else if (tile != INVALID_TILE) { + t = ClosestTownFromTile(tile, UINT_MAX); + } else { + *available = false; + return UINT_MAX; + } + + return TownGetVariable(variable, parameter, available, t); + } + if (industry == NULL) { /* industry does not exist, only use those variables that are "safe" */ switch (variable) { diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index 36603befbe..9cfebc56cf 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -17,7 +17,7 @@ #include "newgrf_station.h" #include "newgrf_spritegroup.h" #include "cargotype.h" -#include "town_map.h" +#include "town.h" #include "newgrf_town.h" #include "gfx_func.h" #include "date_func.h" @@ -358,12 +358,12 @@ static uint32 StationGetVariable(const ResolverObject *object, byte variable, by if (object->scope == VSG_SCOPE_PARENT) { /* Pass the request on to the town of the station */ - Town *t; + const Town *t; if (st != NULL) { t = st->town; } else if (tile != INVALID_TILE) { - t = GetTownByTile(tile); + t = ClosestTownFromTile(tile, UINT_MAX); } else { *available = false; return UINT_MAX; diff --git a/src/openttd.cpp b/src/openttd.cpp index 3f61ff85b0..516f453740 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -410,13 +410,23 @@ int ttd_main(int argc, char *argv[]) case 'i': _use_dos_palette = true; break; case 'g': if (mgo.opt != NULL) { - strcpy(_file_to_saveload.name, mgo.opt); + ttd_strlcpy(_file_to_saveload.name, mgo.opt, sizeof(_file_to_saveload.name)); _switch_mode = SM_LOAD; - } else { - _switch_mode = SM_NEWGAME; - /* Give a random map */ - generation_seed = InteractiveRandom(); + _file_to_saveload.mode = SL_LOAD; + + /* if the file doesn't exist or it is not a valid savegame, let the saveload code show an error */ + const char *t = strrchr(_file_to_saveload.name, '.'); + if (t != NULL) { + FiosType ft = (FiosType)FiosGetSavegameListCallback(SLD_LOAD_GAME, _file_to_saveload.name, t, NULL); + if (ft != FIOS_TYPE_INVALID) SetFiosType(ft); + } + + break; } + + _switch_mode = SM_NEWGAME; + /* Give a random map */ + generation_seed = InteractiveRandom(); break; case 'G': generation_seed = atoi(mgo.opt); break; case 'c': _config_file = strdup(mgo.opt); break; diff --git a/src/spritecache.cpp b/src/spritecache.cpp index 9fb77d0448..a1677ad585 100644 --- a/src/spritecache.cpp +++ b/src/spritecache.cpp @@ -137,7 +137,7 @@ static void* ReadSprite(SpriteCache *sc, SpriteID id, bool real_sprite) file_pos = GetSpriteCache(SPR_IMG_QUERY)->file_pos; } - if (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() == 32) { + if (real_sprite && BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() == 32) { #ifdef WITH_PNG /* Try loading 32bpp graphics in case we are 32bpp output */ SpriteLoaderPNG sprite_loader; @@ -147,7 +147,7 @@ static void* ReadSprite(SpriteCache *sc, SpriteID id, bool real_sprite) sc->ptr = BlitterFactoryBase::GetCurrentBlitter()->Encode(&sprite, &AllocSprite); free(sprite.data); - sc->real_sprite = true; + sc->real_sprite = real_sprite; return sc->ptr; } @@ -173,13 +173,13 @@ static void* ReadSprite(SpriteCache *sc, SpriteID id, bool real_sprite) DEBUG(sprite, warning_level, "Tried to load non sprite #%d as a real sprite. Probable cause: NewGRF interference", id); warning_level = 6; if (id == SPR_IMG_QUERY) error("Uhm, would you be so kind not to load a NewGRF that makes the 'query' sprite a non- sprite?"); - return (void*)GetSprite(SPR_IMG_QUERY); + return (void*)GetRawSprite(SPR_IMG_QUERY, true); } byte *dest = (byte *)AllocSprite(num); sc->ptr = dest; - sc->real_sprite = false; + sc->real_sprite = real_sprite; FioReadBlock(dest, num); return sc->ptr; @@ -194,6 +194,7 @@ static void* ReadSprite(SpriteCache *sc, SpriteID id, bool real_sprite) * something ;) The image should really have been a data-stream * (so type = 0xFF basicly). */ if (id >= 4845 && id <= 4881) { + assert(real_sprite); uint height = FioReadByte(); uint width = FioReadWord(); Sprite *sprite; @@ -221,22 +222,23 @@ static void* ReadSprite(SpriteCache *sc, SpriteID id, bool real_sprite) } } - sc->real_sprite = false; + sc->real_sprite = real_sprite; return sc->ptr; } - sc->real_sprite = true; - if (!real_sprite) { static byte warning_level = 0; DEBUG(sprite, warning_level, "Tried to load real sprite #%d as a non sprite. Probable cause: NewGRF interference", id); warning_level = 6; + return (void*)GetRawSprite(id, true); } SpriteLoaderGrf sprite_loader; SpriteLoader::Sprite sprite; + sc->real_sprite = real_sprite; + if (!sprite_loader.LoadSprite(&sprite, file_slot, file_pos)) return NULL; if (id == 142) sprite.height = 10; // Compensate for a TTD bug sc->ptr = BlitterFactoryBase::GetCurrentBlitter()->Encode(&sprite, &AllocSprite);