From 7742f8c0804ed39f47356312be7051482a5d85bb Mon Sep 17 00:00:00 2001 From: rubidium Date: Mon, 25 May 2009 17:15:15 +0000 Subject: [PATCH] (svn r16423) [0.7] -Backport from trunk: - Fix: Do not allow content download via the console when there is no zlib as it is done for the GUI already [FS#2919] (r16420) - Fix: Some 64bit architectures require size_t to be aligned at 8-byte boundary, ensure it for MemBlock (r16415) - Add: [NoAI] AISignList that can be used to get a list of valid signs (r16400) - Fix: [NewGRF] Disable multitile houses with non-zero population on additional tiles as they cause desyncs and because the specs do not allow that either (r16383) - Fix: [NewGRF] Valid UTF-8 sequences between 0x20 and 0xFF should be allowed as is instead of being treated as control codes (r16374) - Fix: [NewGRF] Use a valid StringID as fall-back when undefined generic NewGRF strings of vehicles are requested (r16366) --- bin/ai/regression/regression.nut | 7 ++++--- bin/ai/regression/regression.txt | 13 ------------- projects/openttd_vs80.vcproj | 8 ++++++++ projects/openttd_vs90.vcproj | 8 ++++++++ source.list | 2 ++ src/ai/ai_instance.cpp | 2 ++ src/ai/api/ai_sign.hpp | 1 + src/ai/api/ai_signlist.cpp | 15 +++++++++++++++ src/ai/api/ai_signlist.hpp | 20 ++++++++++++++++++++ src/ai/api/ai_signlist.hpp.sq | 21 +++++++++++++++++++++ src/console_cmds.cpp | 8 +++++++- src/economy.cpp | 4 ++-- src/newgrf.cpp | 12 +++++++++++- src/newgrf_text.cpp | 8 +++++++- src/spritecache.cpp | 18 ++++++++++++++---- 15 files changed, 122 insertions(+), 25 deletions(-) create mode 100644 src/ai/api/ai_signlist.cpp create mode 100644 src/ai/api/ai_signlist.hpp create mode 100644 src/ai/api/ai_signlist.hpp.sq diff --git a/bin/ai/regression/regression.nut b/bin/ai/regression/regression.nut index 82154c9dbe..7ec415639e 100644 --- a/bin/ai/regression/regression.nut +++ b/bin/ai/regression/regression.nut @@ -1077,9 +1077,10 @@ function Regression::Sign() print(" BuildSign(33409, 'Some other Sign'): " + sign_id); print(" RemoveSign(" + sign_id + "): " + AISign.RemoveSign(sign_id)); print(""); - print(" GetMaxSignID(): " + AISign.GetMaxSignID()); - for (local i = -1; i < AISign.GetMaxSignID() + 1; i++) { - if (AISign.IsValidSign(i)) j++; + local list = AISignList(); + list.Sort(AIAbstractList.SORT_BY_ITEM, true); + for (local i = list.Begin(); list.HasNext(); i = list.Next()) { + j++; print(" Sign " + i); print(" IsValidSign(): " + AISign.IsValidSign(i)); print(" GetName(): " + AISign.GetName(i)); diff --git a/bin/ai/regression/regression.txt b/bin/ai/regression/regression.txt index d19c93605a..c6745d0565 100644 --- a/bin/ai/regression/regression.txt +++ b/bin/ai/regression/regression.txt @@ -7242,11 +7242,6 @@ BuildSign(33409, 'Some other Sign'): 2 RemoveSign(2): true - GetMaxSignID(): 3 - Sign -1 - IsValidSign(): false - GetName(): (null : 0x00000000) - GetLocation(): -1 Sign 0 IsValidSign(): true GetName(): Some Sign @@ -7255,14 +7250,6 @@ IsValidSign(): true GetName(): Test2 GetLocation(): 33411 - Sign 2 - IsValidSign(): false - GetName(): (null : 0x00000000) - GetLocation(): -1 - Sign 3 - IsValidSign(): false - GetName(): (null : 0x00000000) - GetLocation(): -1 Valid Signs: 2 --Station-- diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index ff547623b0..37273e8b12 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -2659,6 +2659,10 @@ RelativePath=".\..\src\ai\api\ai_sign.hpp" > + + @@ -2863,6 +2867,10 @@ RelativePath=".\..\src\ai\api\ai_sign.cpp" > + + diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj index ee5c4a1e4b..283fcda362 100644 --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -2656,6 +2656,10 @@ RelativePath=".\..\src\ai\api\ai_sign.hpp" > + + @@ -2860,6 +2864,10 @@ RelativePath=".\..\src\ai\api\ai_sign.cpp" > + + diff --git a/source.list b/source.list index 6622024693..508cd10efb 100644 --- a/source.list +++ b/source.list @@ -620,6 +620,7 @@ ai/api/ai_rail.hpp ai/api/ai_railtypelist.hpp ai/api/ai_road.hpp ai/api/ai_sign.hpp +ai/api/ai_signlist.hpp ai/api/ai_station.hpp ai/api/ai_stationlist.hpp ai/api/ai_subsidy.hpp @@ -672,6 +673,7 @@ ai/api/ai_rail.cpp ai/api/ai_railtypelist.cpp ai/api/ai_road.cpp ai/api/ai_sign.cpp +ai/api/ai_signlist.cpp ai/api/ai_station.cpp ai/api/ai_stationlist.cpp ai/api/ai_subsidy.cpp diff --git a/src/ai/ai_instance.cpp b/src/ai/ai_instance.cpp index 0ad34836ba..68be5fdd6d 100644 --- a/src/ai/ai_instance.cpp +++ b/src/ai/ai_instance.cpp @@ -60,6 +60,7 @@ #include "api/ai_railtypelist.hpp.sq" #include "api/ai_road.hpp.sq" #include "api/ai_sign.hpp.sq" +#include "api/ai_signlist.hpp.sq" #include "api/ai_station.hpp.sq" #include "api/ai_stationlist.hpp.sq" #include "api/ai_subsidy.hpp.sq" @@ -212,6 +213,7 @@ void AIInstance::RegisterAPI() SQAIRailTypeList_Register(this->engine); SQAIRoad_Register(this->engine); SQAISign_Register(this->engine); + SQAISignList_Register(this->engine); SQAIStation_Register(this->engine); SQAIStationList_Register(this->engine); SQAIStationList_Vehicle_Register(this->engine); diff --git a/src/ai/api/ai_sign.hpp b/src/ai/api/ai_sign.hpp index 441b9b3493..f6f0a422a5 100644 --- a/src/ai/api/ai_sign.hpp +++ b/src/ai/api/ai_sign.hpp @@ -30,6 +30,7 @@ public: /** * Gets the maximum sign index; there are no valid signs with a higher index. + * @deprecated This function is deprecated and might be removed in future versions of the API. Use AISignList() instead. * @return The maximum sign index. * @post Return value is always non-negative. */ diff --git a/src/ai/api/ai_signlist.cpp b/src/ai/api/ai_signlist.cpp new file mode 100644 index 0000000000..33cb7fed4e --- /dev/null +++ b/src/ai/api/ai_signlist.cpp @@ -0,0 +1,15 @@ +/* $Id$ */ + +/** @file ai_signlist.cpp Implementation of AISignList and friends. */ + +#include "ai_signlist.hpp" +#include "ai_sign.hpp" +#include "../../signs_base.h" + +AISignList::AISignList() +{ + Sign *s; + FOR_ALL_SIGNS(s) { + if (AISign::IsValidSign(s->index)) this->AddItem(s->index); + } +} diff --git a/src/ai/api/ai_signlist.hpp b/src/ai/api/ai_signlist.hpp new file mode 100644 index 0000000000..17faa9a80e --- /dev/null +++ b/src/ai/api/ai_signlist.hpp @@ -0,0 +1,20 @@ +/* $Id$ */ + +/** @file ai_signlist.hpp List all the signs of your company. */ + +#ifndef AI_SIGNLIST_HPP +#define AI_SIGNLIST_HPP + +#include "ai_abstractlist.hpp" + +/** + * Create a list of signs your company has created. + * @ingroup AIList + */ +class AISignList : public AIAbstractList { +public: + static const char *GetClassName() { return "AISignList"; } + AISignList(); +}; + +#endif /* AI_SIGNLIST_HPP */ diff --git a/src/ai/api/ai_signlist.hpp.sq b/src/ai/api/ai_signlist.hpp.sq new file mode 100644 index 0000000000..b350e86f60 --- /dev/null +++ b/src/ai/api/ai_signlist.hpp.sq @@ -0,0 +1,21 @@ +/* $Id$ */ +/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */ + +#include "ai_signlist.hpp" + +namespace SQConvert { + /* Allow AISignList to be used as Squirrel parameter */ + template <> AISignList *GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AISignList *)instance; } + template <> AISignList &GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AISignList *)instance; } + template <> const AISignList *GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AISignList *)instance; } + template <> const AISignList &GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AISignList *)instance; } + template <> int Return(HSQUIRRELVM vm, AISignList *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AISignList", res, NULL, DefSQDestructorCallback); return 1; } +}; // namespace SQConvert + +void SQAISignList_Register(Squirrel *engine) { + DefSQClass SQAISignList("AISignList"); + SQAISignList.PreRegister(engine, "AIAbstractList"); + SQAISignList.AddConstructor(engine, "x"); + + SQAISignList.PostRegister(engine); +} diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 058aa77df9..c6a3c8cd73 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -1518,6 +1518,8 @@ bool NetworkChangeCompanyPassword(byte argc, char *argv[]) return true; } +/* Content downloading only is available with ZLIB */ +#if defined(WITH_ZLIB) #include "network/network_content.h" /** Resolve a string to a content type. */ @@ -1626,7 +1628,7 @@ DEF_CONSOLE_CMD(ConContent) return false; } - +#endif /* defined(WITH_ZLIB) */ #endif /* ENABLE_NETWORK */ DEF_CONSOLE_CMD(ConSetting) @@ -1773,7 +1775,11 @@ void IConsoleStdLibRegister() #ifdef ENABLE_NETWORK /* Network hooks; only active in network */ IConsoleCmdHookAdd ("resetengines", ICONSOLE_HOOK_ACCESS, ConHookNoNetwork); + +/* Content downloading is only available with ZLIB */ +#if defined(WITH_ZLIB) IConsoleCmdRegister("content", ConContent); +#endif /* defined(WITH_ZLIB) */ /*** Networking commands ***/ IConsoleCmdRegister("say", ConSay); diff --git a/src/economy.cpp b/src/economy.cpp index 71be0f50fd..2f3d36a5fd 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -1366,11 +1366,11 @@ static Money DeliverGoods(int num_pieces, CargoID cargo_type, StationID source, } /* Get station pointers. */ - s_from = GetStation(source); + s_from = IsValidStationID(source) ? GetStation(source) : NULL; s_to = GetStation(dest); /* Check if a subsidy applies. */ - subsidised = CheckSubsidised(s_from, s_to, cargo_type); + subsidised = s_from != NULL && CheckSubsidised(s_from, s_to, cargo_type); /* Increase town's counter for some special goods types */ const CargoSpec *cs = GetCargo(cargo_type); diff --git a/src/newgrf.cpp b/src/newgrf.cpp index f0b00fd129..3790d0ad83 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -3478,7 +3478,7 @@ static void FeatureNewName(byte *buf, size_t len) StringID string = AddGRFString(_cur_grffile->grfid, e->index, lang, new_scheme, name, e->info.string_id); e->info.string_id = string; } else { - AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, id); + AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_UNDEFINED); } break; @@ -5851,6 +5851,16 @@ static void FinaliseHouseArray() continue; } + /* Some places sum population by only counting north tiles. Other places use all tiles causing desyncs. + * As the newgrf specs define population to be zero for non-north tiles, we just disable the offending house. + * If you want to allow non-zero populations somewhen, make sure to sum the population of all tiles in all places. */ + if (((hs->building_flags & BUILDING_HAS_2_TILES) != 0 && next1->population != 0) || + ((hs->building_flags & BUILDING_HAS_4_TILES) != 0 && (next2->population != 0 || next3->population != 0))) { + hs->enabled = false; + DEBUG(grf, 1, "FinaliseHouseArray: %s defines multitile house %d with non-zero population on additional tiles. Disabling house.", file->filename, hs->local_id); + continue; + } + _house_mngr.SetEntitySpec(hs); if (hs->min_year < min_year) min_year = hs->min_year; } diff --git a/src/newgrf_text.cpp b/src/newgrf_text.cpp index 9edd243da0..0e5e620f7a 100644 --- a/src/newgrf_text.cpp +++ b/src/newgrf_text.cpp @@ -120,7 +120,13 @@ char *TranslateTTDPatchCodes(uint32 grfid, const char *str) if (unicode && Utf8EncodedCharLen(*str) != 0) { c = Utf8Consume(&str); /* 'Magic' range of control codes. */ - if (GB(c, 8, 8) == 0xE0) c = GB(c, 0, 8); + if (GB(c, 8, 8) == 0xE0) { + c = GB(c, 0, 8); + } else if (c >= 0x20) { + if (!IsValidChar(c, CS_ALPHANUMERAL)) c = '?'; + d += Utf8Encode(d, c); + continue; + } } else { c = (byte)*str++; } diff --git a/src/spritecache.cpp b/src/spritecache.cpp index 990f407262..1470522d23 100644 --- a/src/spritecache.cpp +++ b/src/spritecache.cpp @@ -306,8 +306,18 @@ void DupSprite(SpriteID old_spr, SpriteID new_spr) scnew->warned = false; } +/** + * S_FREE_MASK is used to mask-out lower bits of MemBlock::size + * If they are non-zero, the block is free. + * S_FREE_MASK has to ensure MemBlock is correctly aligned - + * it means 8B (S_FREE_MASK == 7) on 64bit systems! + */ +static const size_t S_FREE_MASK = sizeof(size_t) - 1; -#define S_FREE_MASK 1 +/* to make sure nobody adds things to MemBlock without checking S_FREE_MASK first */ +assert_compile(sizeof(MemBlock) == sizeof(size_t)); +/* make sure it's a power of two */ +assert_compile((sizeof(size_t) & (sizeof(size_t) - 1)) == 0); static inline MemBlock *NextBlock(MemBlock *block) { @@ -439,9 +449,9 @@ void *AllocSprite(size_t mem_req) { mem_req += sizeof(MemBlock); - /* Align this to an uint32 boundary. This also makes sure that the 2 least - * bits are not used, so we could use those for other things. */ - mem_req = Align(mem_req, sizeof(uint32)); + /* Align this to correct boundary. This also makes sure at least one + * bit is not used, so we can use it for other things. */ + mem_req = Align(mem_req, S_FREE_MASK + 1); for (;;) { MemBlock *s;