From ddcb3bf560cfff6c0f9c56615b001d23ca93b41c Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Fri, 11 Sep 2015 15:16:19 +0100 Subject: [PATCH 1/5] Update project files. --- projects/openttd_vs140.vcxproj | 2 ++ projects/openttd_vs140.vcxproj.filters | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/projects/openttd_vs140.vcxproj b/projects/openttd_vs140.vcxproj index 88f7b44ddd..b82aba741c 100644 --- a/projects/openttd_vs140.vcxproj +++ b/projects/openttd_vs140.vcxproj @@ -886,6 +886,8 @@ + + diff --git a/projects/openttd_vs140.vcxproj.filters b/projects/openttd_vs140.vcxproj.filters index 06800ffdaf..0b6dc573b4 100644 --- a/projects/openttd_vs140.vcxproj.filters +++ b/projects/openttd_vs140.vcxproj.filters @@ -1836,6 +1836,12 @@ Save/Load handlers + + Save/Load handlers + + + Save/Load handlers + Tables From 7d2b4bd3ead9f8cd1c8eba2148b99cbc6ac98893 Mon Sep 17 00:00:00 2001 From: patch-import Date: Fri, 11 Sep 2015 19:53:02 +0100 Subject: [PATCH 2/5] Import extra large maps patch. http://www.tt-forums.net/viewtopic.php?f=33&t=33137 --- src/genworld_gui.cpp | 74 +++++++++++++++++++++++++++++++++++----- src/lang/english.txt | 2 ++ src/map.cpp | 10 +++--- src/map_type.h | 6 ++-- src/newgrf_debug_gui.cpp | 10 +++--- src/openttd.cpp | 22 ++++++++++++ 6 files changed, 105 insertions(+), 19 deletions(-) diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp index 3ce473e97f..5bc0722846 100644 --- a/src/genworld_gui.cpp +++ b/src/genworld_gui.cpp @@ -20,6 +20,7 @@ #include "sound_func.h" #include "fios.h" #include "string_func.h" +#include "gui.h" #include "widgets/dropdown_type.h" #include "widgets/dropdown_func.h" #include "querystring_gui.h" @@ -277,12 +278,37 @@ static void LandscapeGenerationCallback(Window *w, bool confirmed) if (confirmed) StartGeneratingLandscape((GenenerateLandscapeWindowMode)w->window_number); } -static DropDownList *BuildMapsizeDropDown() +/** + * Check if map size set lies in allowed boundaries. + * @param print_warning If set to true, messagebox with warning is printed out if size is outside limits. + * @return true if size is ok, false otherwise. + */ +static bool CheckMapSize(bool print_warning = true) +{ + uint64 tiles = 1ULL << (_settings_newgame.game_creation.map_x + _settings_newgame.game_creation.map_y); + + if (_settings_newgame.game_creation.map_x + _settings_newgame.game_creation.map_y > MAX_MAP_TILES_BITS) { + if (print_warning) { + SetDParam(0, MAX_MAP_TILES); + SetDParam(1, tiles); + ShowErrorMessage(STR_MAPGEN_TOO_MANY_TILES_MESSAGE, INVALID_STRING_ID, WL_ERROR, 0, 0); + } + return false; + } + return true; +} + +/** + * Build dropdown list with map sizes + * Dimension selected in the other dropdown is used to suggest which choices are 'valid' + * @param other_dimension Dimension specified by the second dropdown. + */ +static DropDownList *BuildMapsizeDropDown(int other_dimension) { DropDownList *list = new DropDownList(); for (uint i = MIN_MAP_SIZE_BITS; i <= MAX_MAP_SIZE_BITS; i++) { - DropDownListParamStringItem *item = new DropDownListParamStringItem(STR_JUST_INT, i, false); + DropDownListParamStringItem *item = new DropDownListParamStringItem((i + other_dimension > MAX_MAP_TILES_BITS) ? STR_RED_INT : STR_JUST_INT, i, false); item->SetParam(0, 1 << i); list->push_back(item); } @@ -310,6 +336,14 @@ struct GenerateLandscapeWindow : public QueryStringBaseWindow { char name[64]; GenenerateLandscapeWindowMode mode; + void SetDropDownColor() + { + /* Draw sizes in mapsize selection dropdowns in red if too large size is selected */ + bool mapsize_valid = CheckMapSize(false); + this->GetWidget(WID_GL_MAPSIZE_X_PULLDOWN)->widget_data = mapsize_valid ? STR_JUST_INT : STR_RED_INT; + this->GetWidget(WID_GL_MAPSIZE_Y_PULLDOWN)->widget_data = mapsize_valid ? STR_JUST_INT : STR_RED_INT; + } + GenerateLandscapeWindow(const WindowDesc *desc, WindowNumber number = 0) : QueryStringBaseWindow(11) { this->InitNested(desc, number); @@ -324,6 +358,8 @@ struct GenerateLandscapeWindow : public QueryStringBaseWindow { this->mode = (GenenerateLandscapeWindowMode)this->window_number; + SetDropDownColor(); + /* Disable town, industry and trees in SE */ this->SetWidgetDisabledState(WID_GL_TOWN_PULLDOWN, _game_mode == GM_EDITOR); this->SetWidgetDisabledState(WID_GL_INDUSTRY_PULLDOWN, _game_mode == GM_EDITOR); @@ -538,11 +574,11 @@ struct GenerateLandscapeWindow : public QueryStringBaseWindow { break; case WID_GL_MAPSIZE_X_PULLDOWN: // Mapsize X - ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_x, WID_GL_MAPSIZE_X_PULLDOWN); + ShowDropDownList(this, BuildMapsizeDropDown(_settings_newgame.game_creation.map_y), _settings_newgame.game_creation.map_x, WID_GL_MAPSIZE_X_PULLDOWN); break; case WID_GL_MAPSIZE_Y_PULLDOWN: // Mapsize Y - ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_y, WID_GL_MAPSIZE_Y_PULLDOWN); + ShowDropDownList(this, BuildMapsizeDropDown(_settings_newgame.game_creation.map_x), _settings_newgame.game_creation.map_y, WID_GL_MAPSIZE_Y_PULLDOWN); break; case WID_GL_TOWN_PULLDOWN: // Number of towns @@ -561,6 +597,7 @@ struct GenerateLandscapeWindow : public QueryStringBaseWindow { break; case WID_GL_GENERATE_BUTTON: { // Generate + if (!CheckMapSize()) break; /* Get rotated map size. */ uint map_x; uint map_y; @@ -720,8 +757,14 @@ struct GenerateLandscapeWindow : public QueryStringBaseWindow { virtual void OnDropdownSelect(int widget, int index) { switch (widget) { - case WID_GL_MAPSIZE_X_PULLDOWN: _settings_newgame.game_creation.map_x = index; break; - case WID_GL_MAPSIZE_Y_PULLDOWN: _settings_newgame.game_creation.map_y = index; break; + case WID_GL_MAPSIZE_X_PULLDOWN: + _settings_newgame.game_creation.map_x = index; + SetDropDownColor(); + break; + case WID_GL_MAPSIZE_Y_PULLDOWN: + _settings_newgame.game_creation.map_y = index; + SetDropDownColor(); + break; case WID_GL_TREE_PULLDOWN: _settings_newgame.game_creation.tree_placer = index; break; case WID_GL_RIVER_PULLDOWN: _settings_newgame.game_creation.amount_of_rivers = index; break; case WID_GL_SMOOTHNESS_PULLDOWN: _settings_newgame.game_creation.tgen_smoothness = index; break; @@ -883,10 +926,19 @@ struct CreateScenarioWindow : public Window { uint widget_id; + void SetDropDownColor() + { + /* Draw sizes in mapsize selection dropdowns in red if too large size is selected */ + bool mapsize_valid = CheckMapSize(false); + this->GetWidget(WID_CS_MAPSIZE_X_PULLDOWN)->widget_data = mapsize_valid ? STR_JUST_INT : STR_RED_INT; + this->GetWidget(WID_CS_MAPSIZE_Y_PULLDOWN)->widget_data = mapsize_valid ? STR_JUST_INT : STR_RED_INT; + } + CreateScenarioWindow(const WindowDesc *desc, WindowNumber window_number) : Window() { this->InitNested(desc, window_number); this->LowerWidget(_settings_newgame.game_creation.landscape + WID_CS_TEMPERATE); + SetDropDownColor(); } virtual void SetStringParameters(int widget) const @@ -910,6 +962,8 @@ struct CreateScenarioWindow : public Window } } + + virtual void OnPaint() { this->SetWidgetDisabledState(WID_CS_START_DATE_DOWN, _settings_newgame.game_creation.starting_year <= MIN_YEAR); @@ -963,18 +1017,20 @@ struct CreateScenarioWindow : public Window break; case WID_CS_MAPSIZE_X_PULLDOWN: // Mapsize X - ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_x, WID_CS_MAPSIZE_X_PULLDOWN); + ShowDropDownList(this, BuildMapsizeDropDown(_settings_newgame.game_creation.map_y), _settings_newgame.game_creation.map_x, WID_CS_MAPSIZE_X_PULLDOWN); break; case WID_CS_MAPSIZE_Y_PULLDOWN: // Mapsize Y - ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_y, WID_CS_MAPSIZE_Y_PULLDOWN); + ShowDropDownList(this, BuildMapsizeDropDown(_settings_newgame.game_creation.map_x), _settings_newgame.game_creation.map_y, WID_CS_MAPSIZE_Y_PULLDOWN); break; case WID_CS_EMPTY_WORLD: // Empty world / flat world + if (!CheckMapSize()) break; StartGeneratingLandscape(GLWM_SCENARIO); break; case WID_CS_RANDOM_WORLD: // Generate + if (!CheckMapSize()) break; ShowGenerateLandscape(); break; @@ -1033,6 +1089,8 @@ struct CreateScenarioWindow : public Window case WID_CS_MAPSIZE_X_PULLDOWN: _settings_newgame.game_creation.map_x = index; break; case WID_CS_MAPSIZE_Y_PULLDOWN: _settings_newgame.game_creation.map_y = index; break; } + SetDropDownColor(); + this->SetDirty(); } diff --git a/src/lang/english.txt b/src/lang/english.txt index 0f919a9d60..f96f0fbfbe 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2399,6 +2399,7 @@ STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Heightma STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Heightmap name: STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}Size: STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} x {NUM} +STR_MAPGEN_TOO_MANY_TILES_MESSAGE :{YELLOW}Too many tiles in map. Maximum number of tiles is {NUM}, you have selected {NUM} STR_MAPGEN_RANDOM_SEED_OSKTITLE :{BLACK}Enter a random seed STR_MAPGEN_SNOW_LINE_QUERY_CAPT :{WHITE}Change snow line height @@ -4449,6 +4450,7 @@ STR_DATE_LONG_SMALL :{TINY_FONT}{BLA STR_TINY_GROUP :{TINY_FONT}{GROUP} STR_BLACK_INT :{BLACK}{NUM} STR_ORANGE_INT :{ORANGE}{NUM} +STR_RED_INT :{RED}{NUM} STR_WHITE_SIGN :{WHITE}{SIGN} STR_TINY_BLACK_STATION :{TINY_FONT}{BLACK}{STATION} STR_BLACK_STRING :{BLACK}{STRING} diff --git a/src/map.cpp b/src/map.cpp index 1ee0ba247c..16c611fd46 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -37,17 +37,19 @@ TileExtended *_me = NULL; ///< Extended Tiles of the map */ void AllocateMap(uint size_x, uint size_y) { + DEBUG(map, 2, "Min/max map size %d/%d, max map tiles %d", MIN_MAP_SIZE, MAX_MAP_SIZE, MAX_MAP_TILES); + DEBUG(map, 1, "Allocating map of size %dx%d", size_x, size_y); + /* Make sure that the map size is within the limits and that * size of both axes is a power of 2. */ - if (!IsInsideMM(size_x, MIN_MAP_SIZE, MAX_MAP_SIZE + 1) || - !IsInsideMM(size_y, MIN_MAP_SIZE, MAX_MAP_SIZE + 1) || + if (size_x * size_y > MAX_MAP_TILES || + size_x < MIN_MAP_SIZE || + size_y < MIN_MAP_SIZE || (size_x & (size_x - 1)) != 0 || (size_y & (size_y - 1)) != 0) { error("Invalid map size"); } - DEBUG(map, 1, "Allocating map of size %dx%d", size_x, size_y); - _map_log_x = FindFirstBit(size_x); _map_log_y = FindFirstBit(size_y); _map_size_x = size_x; diff --git a/src/map_type.h b/src/map_type.h index 93aded4d98..787a31d92c 100644 --- a/src/map_type.h +++ b/src/map_type.h @@ -59,9 +59,11 @@ struct TileIndexDiffC { /** Minimal and maximal map width and height */ static const uint MIN_MAP_SIZE_BITS = 6; ///< Minimal size of map is equal to 2 ^ MIN_MAP_SIZE_BITS -static const uint MAX_MAP_SIZE_BITS = 11; ///< Maximal size of map is equal to 2 ^ MAX_MAP_SIZE_BITS +static const uint MAX_MAP_SIZE_BITS = 20; ///< Maximal size of map is equal to 2 ^ MAX_MAP_SIZE_BITS +static const uint MAX_MAP_TILES_BITS = 26; ///< Maximal number of tiles in a map is equal to 2 ^ MAX_MAP_TILES_BITS. static const uint MIN_MAP_SIZE = 1 << MIN_MAP_SIZE_BITS; ///< Minimal map size = 64 -static const uint MAX_MAP_SIZE = 1 << MAX_MAP_SIZE_BITS; ///< Maximal map size = 2048 +static const uint MAX_MAP_SIZE = 1 << MAX_MAP_SIZE_BITS; ///< Maximal map size = 8192 +static const uint MAX_MAP_TILES = 1 << MAX_MAP_TILES_BITS;///< Maximal number of tiles in a map = 2048 * 2048 /** * Approximation of the length of a straight track, relative to a diagonal diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp index 1547671944..3665ad75a1 100644 --- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -47,7 +47,7 @@ NewGrfDebugSpritePicker _newgrf_debug_sprite_picker = { SPM_NONE, NULL, 0, Small */ static inline uint GetFeatureIndex(uint window_number) { - return GB(window_number, 0, 24); + return GB(window_number, 0, 27); } /** @@ -59,8 +59,8 @@ static inline uint GetFeatureIndex(uint window_number) */ static inline uint GetInspectWindowNumber(GrfSpecFeature feature, uint index) { - assert((index >> 24) == 0); - return (feature << 24) | index; + assert((index >> 27) == 0); + return (feature << 27) | index; } /** @@ -251,7 +251,7 @@ struct NIFeature { */ static inline GrfSpecFeature GetFeatureNum(uint window_number) { - return (GrfSpecFeature)GB(window_number, 24, 8); + return (GrfSpecFeature)GB(window_number, 27, 5); } /** @@ -470,7 +470,7 @@ struct NewGRFInspectWindow : Window { case WID_NGRFI_PARENT: { const NIHelper *nih = GetFeatureHelper(this->window_number); uint index = nih->GetParent(GetFeatureIndex(this->window_number)); - ::ShowNewGRFInspectWindow((GrfSpecFeature)GB(index, 24, 8), GetFeatureIndex(index), nih->GetGRFID(GetFeatureIndex(this->window_number))); + ::ShowNewGRFInspectWindow((GrfSpecFeature)GB(index, 27, 5), GetFeatureIndex(index), nih->GetGRFID(GetFeatureIndex(this->window_number))); break; } diff --git a/src/openttd.cpp b/src/openttd.cpp index 3c8047b269..5c77fb52f2 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -902,6 +902,24 @@ static void MakeNewGameDone() MarkWholeScreenDirty(); } +/* + * Too large size may be stored in settings (especially if switching between between OpenTTD + * versions with different map size limits), we have to check if it is valid before generating world. + * Simple separate checking of X and Y map sizes is not enough, as their sum is what counts for the limit. + * Check the size and decrease the larger of the sizes till the size is in limit. + */ +static void FixConfigMapSize() +{ + while (_settings_game.game_creation.map_x + _settings_game.game_creation.map_y > MAX_MAP_TILES_BITS) { + /* Repeat reducing larger of X/Y dimensions until the map size is within allowable limits */ + if (_settings_game.game_creation.map_x > _settings_game.game_creation.map_y) { + _settings_game.game_creation.map_x--; + } else { + _settings_game.game_creation.map_y--; + } + } +} + static void MakeNewGame(bool from_heightmap, bool reset_settings) { _game_mode = GM_NORMAL; @@ -909,6 +927,7 @@ static void MakeNewGame(bool from_heightmap, bool reset_settings) ResetGRFConfig(true); GenerateWorldSetCallback(&MakeNewGameDone); + FixConfigMapSize(); GenerateWorld(from_heightmap ? GWM_HEIGHTMAP : GWM_NEWGAME, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y, reset_settings); } @@ -924,6 +943,7 @@ static void MakeNewEditorWorld() ResetGRFConfig(true); GenerateWorldSetCallback(&MakeNewEditorWorldDone); + FixConfigMapSize(); GenerateWorld(GWM_EMPTY, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y); } @@ -1068,6 +1088,7 @@ void SwitchToMode(SwitchMode new_mode) case SM_LOAD_HEIGHTMAP: // Load heightmap from scenario editor SetLocalCompany(OWNER_NONE); + FixConfigMapSize(); GenerateWorld(GWM_HEIGHTMAP, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y); MarkWholeScreenDirty(); break; @@ -1110,6 +1131,7 @@ void SwitchToMode(SwitchMode new_mode) case SM_GENRANDLAND: // Generate random land within scenario editor SetLocalCompany(OWNER_NONE); + FixConfigMapSize(); GenerateWorld(GWM_RANDOM, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y); /* XXX: set date */ MarkWholeScreenDirty(); From 86dea90c4f46ed418e1c8e6ad7a45664a9337768 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Fri, 11 Sep 2015 19:44:16 +0100 Subject: [PATCH 3/5] save_ext: Initial support for save/load of RIFF chunk sizes > 28 bits. Add a chunk extension header with a flag for increased RIFF size. --- src/saveload/saveload.cpp | 63 +++++++++++++++++++++++++++++++++++++-- src/saveload/saveload.h | 7 +++++ 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 74f6fba1e2..6fe2a8e636 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -888,9 +888,20 @@ void SlSetLength(size_t length) case CH_RIFF: /* Ugly encoding of >16M RIFF chunks * The lower 24 bits are normal - * The uppermost 4 bits are bits 24:27 */ - assert(length < (1 << 28)); + * The uppermost 4 bits are bits 24:27 + * + * If we have more than 28 bits, use an extra uint32 and + * signal this using the extended chunk header */ + assert(length < (1LL << 32)); + if (length >= (1 << 28)) { + /* write out extended chunk header */ + SlWriteByte(CH_EXT_HDR); + SlWriteUint32(static_cast(SLCEHF_BIG_RIFF)); + } SlWriteUint32((uint32)((length & 0xFFFFFF) | ((length >> 24) << 28))); + if (length >= (1 << 28)) { + SlWriteUint32(length >> 28); + } break; case CH_ARRAY: assert(_sl.last_array_index <= _sl.array_index); @@ -1661,6 +1672,16 @@ void SlAutolength(AutolengthProc *proc, void *arg) if (offs != _sl.dumper->GetSize()) SlErrorCorrupt("Invalid chunk size"); } +/* + * Notes on extended chunk header: + * + * If the chunk type is CH_EXT_HDR (15), then a u32 flags field follows. + * This flag field may define additional fields which follow the flags field in future. + * The standard chunk header follows, though it my be modified by the flags field. + * At present SLCEHF_BIG_RIFF increases the RIFF size limit to a theoretical 60 bits, + * by adding a further u32 field for the high bits after the existing RIFF size field. + */ + /** * Load a chunk of data (eg vehicles, stations, etc.) * @param ch The chunkhandler that will be used for the operation @@ -1674,6 +1695,15 @@ static void SlLoadChunk(const ChunkHandler *ch) _sl.block_mode = m; _sl.obj_len = 0; + SaveLoadChunkExtHeaderFlags ext_flags = static_cast(0); + if ((m & 0xF) == CH_EXT_HDR) { + ext_flags = static_cast(SlReadUint32()); + + /* read in real header */ + m = SlReadByte(); + _sl.block_mode = m; + } + switch (m) { case CH_ARRAY: _sl.array_index = 0; @@ -1689,6 +1719,10 @@ static void SlLoadChunk(const ChunkHandler *ch) /* Read length */ len = (SlReadByte() << 16) | ((m >> 4) << 24); len += SlReadUint16(); + if (ext_flags & SLCEHF_BIG_RIFF) { + len |= SlReadUint32() << 28; + } + _sl.obj_len = len; endoffs = _sl.reader->GetSize() + len; ch->load_proc(); @@ -1714,9 +1748,21 @@ static void SlLoadCheckChunk(const ChunkHandler *ch) _sl.block_mode = m; _sl.obj_len = 0; + SaveLoadChunkExtHeaderFlags ext_flags = static_cast(0); + if ((m & 0xF) == CH_EXT_HDR) { + ext_flags = static_cast(SlReadUint32()); + + /* read in real header */ + m = SlReadByte(); + _sl.block_mode = m; + } + switch (m) { case CH_ARRAY: _sl.array_index = 0; + if (ext_flags) { + SlErrorCorruptFmt("CH_ARRAY does not take chunk header extension flags: 0x%X", ext_flags); + } if (ch && ch->load_check_proc) { ch->load_check_proc(); } else { @@ -1724,6 +1770,9 @@ static void SlLoadCheckChunk(const ChunkHandler *ch) } break; case CH_SPARSE_ARRAY: + if (ext_flags) { + SlErrorCorruptFmt("CH_SPARSE_ARRAY does not take chunk header extension flags: 0x%X", ext_flags); + } if (ch && ch->load_check_proc) { ch->load_check_proc(); } else { @@ -1732,9 +1781,19 @@ static void SlLoadCheckChunk(const ChunkHandler *ch) break; default: if ((m & 0xF) == CH_RIFF) { + if (ext_flags != (ext_flags & SLCEHF_BIG_RIFF)) { + SlErrorCorruptFmt("Unknown chunk header extension flags for CH_RIFF: 0x%X", ext_flags); + } /* Read length */ len = (SlReadByte() << 16) | ((m >> 4) << 24); len += SlReadUint16(); + if (ext_flags & SLCEHF_BIG_RIFF) { + uint64 full_len = len | (static_cast(SlReadUint32()) << 28); + if (full_len >= (1LL << 32)) { + SlErrorCorrupt("Chunk size too large: " OTTD_PRINTFHEX64, full_len); + } + len = static_cast(full_len); + } _sl.obj_len = len; endoffs = _sl.reader->GetSize() + len; if (ch && ch->load_check_proc) { diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index e34d4f3e9e..330cdde072 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -99,10 +99,17 @@ enum ChunkType { CH_ARRAY = 1, CH_SPARSE_ARRAY = 2, CH_TYPE_MASK = 3, + CH_EXT_HDR = 15, ///< Extended chunk header CH_LAST = 8, ///< Last chunk in this array. CH_AUTO_LENGTH = 16, }; +/** Flags for chunk extended headers */ +enum SaveLoadChunkExtHeaderFlags { + SLCEHF_BIG_RIFF = 1 << 0, ///< This block uses a 60-bit RIFF chunk size +}; +DECLARE_ENUM_AS_BIT_SET(SaveLoadChunkExtHeaderFlags) + /** * VarTypes is the general bitmasked magic type that tells us * certain characteristics about the variable it refers to. For example From 5934cc4995c1cea473ec017b0662c55c0c332742 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Fri, 11 Sep 2015 22:34:54 +0100 Subject: [PATCH 4/5] Fix compile and landscape creation for large maps. --- src/landscape.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/landscape.cpp b/src/landscape.cpp index d1c73fd42b..b94e315b95 100644 --- a/src/landscape.cpp +++ b/src/landscape.cpp @@ -723,12 +723,13 @@ void RunTileLoop() * shift register (LFSR). This allows a deterministic pseudorandom ordering, but * still with minimal state and fast iteration. */ - /* Maximal length LFSR feedback terms, from 12-bit (for 64x64 maps) to 24-bit (for 4096x4096 maps). + /* Maximal length LFSR feedback terms, from 12-bit (for 64x64 maps) to 26-bit (for 8kx8k maps). * Extracted from http://www.ece.cmu.edu/~koopman/lfsr/ */ static const uint32 feedbacks[] = { - 0xD8F, 0x1296, 0x2496, 0x4357, 0x8679, 0x1030E, 0x206CD, 0x403FE, 0x807B8, 0x1004B2, 0x2006A8, 0x4004B2, 0x800B87 + 0xD8F, 0x1296, 0x2496, 0x4357, 0x8679, 0x1030E, 0x206CD, 0x403FE, 0x807B8, 0x1004B2, 0x2006A8, + 0x4004B2, 0x800B87, 0x10004F3, 0x200072D, }; - assert_compile(lengthof(feedbacks) == 2 * MAX_MAP_SIZE_BITS - 2 * MIN_MAP_SIZE_BITS + 1); + assert_compile(lengthof(feedbacks) == MAX_MAP_TILES_BITS - 2 * MIN_MAP_SIZE_BITS + 1); const uint32 feedback = feedbacks[MapLogX() + MapLogY() - 2 * MIN_MAP_SIZE_BITS]; /* We update every tile every 256 ticks, so divide the map size by 2^8 = 256 */ From 1891e7dfc89feab7a5745ac041902c6ed2738a08 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Fri, 11 Sep 2015 22:36:15 +0100 Subject: [PATCH 5/5] Bump max map size to 28 bits. Prevent opening NewGRF debug window on tile indexes > 27 bits, to avoid overflowing field. --- src/landscape.cpp | 4 ++-- src/map_type.h | 4 ++-- src/newgrf_debug_gui.cpp | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/landscape.cpp b/src/landscape.cpp index b94e315b95..00640f9486 100644 --- a/src/landscape.cpp +++ b/src/landscape.cpp @@ -723,11 +723,11 @@ void RunTileLoop() * shift register (LFSR). This allows a deterministic pseudorandom ordering, but * still with minimal state and fast iteration. */ - /* Maximal length LFSR feedback terms, from 12-bit (for 64x64 maps) to 26-bit (for 8kx8k maps). + /* Maximal length LFSR feedback terms, from 12-bit (for 64x64 maps) to 28-bit (for 16kx16k maps). * Extracted from http://www.ece.cmu.edu/~koopman/lfsr/ */ static const uint32 feedbacks[] = { 0xD8F, 0x1296, 0x2496, 0x4357, 0x8679, 0x1030E, 0x206CD, 0x403FE, 0x807B8, 0x1004B2, 0x2006A8, - 0x4004B2, 0x800B87, 0x10004F3, 0x200072D, + 0x4004B2, 0x800B87, 0x10004F3, 0x200072D, 0x40006AE, 0x80009E3, }; assert_compile(lengthof(feedbacks) == MAX_MAP_TILES_BITS - 2 * MIN_MAP_SIZE_BITS + 1); const uint32 feedback = feedbacks[MapLogX() + MapLogY() - 2 * MIN_MAP_SIZE_BITS]; diff --git a/src/map_type.h b/src/map_type.h index 7e50a03140..d2403fdb3d 100644 --- a/src/map_type.h +++ b/src/map_type.h @@ -63,10 +63,10 @@ struct TileIndexDiffC { /** Minimal and maximal map width and height */ static const uint MIN_MAP_SIZE_BITS = 6; ///< Minimal size of map is equal to 2 ^ MIN_MAP_SIZE_BITS static const uint MAX_MAP_SIZE_BITS = 20; ///< Maximal size of map is equal to 2 ^ MAX_MAP_SIZE_BITS -static const uint MAX_MAP_TILES_BITS = 26; ///< Maximal number of tiles in a map is equal to 2 ^ MAX_MAP_TILES_BITS. +static const uint MAX_MAP_TILES_BITS = 28; ///< Maximal number of tiles in a map is equal to 2 ^ MAX_MAP_TILES_BITS. static const uint MIN_MAP_SIZE = 1 << MIN_MAP_SIZE_BITS; ///< Minimal map size = 64 static const uint MAX_MAP_SIZE = 1 << MAX_MAP_SIZE_BITS; ///< Maximal map size = 1M -static const uint MAX_MAP_TILES = 1 << MAX_MAP_TILES_BITS;///< Maximal number of tiles in a map = 64M +static const uint MAX_MAP_TILES = 1 << MAX_MAP_TILES_BITS;///< Maximal number of tiles in a map = 256M (16k x 16k) /** * Approximation of the length of a straight track, relative to a diagonal diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp index 2ec678aea7..af9094c693 100644 --- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -699,6 +699,7 @@ static WindowDesc _newgrf_inspect_desc( */ void ShowNewGRFInspectWindow(GrfSpecFeature feature, uint index, const uint32 grfid) { + if (index >= (1 << 27)) return; if (!IsNewGRFInspectable(feature, index)) return; WindowNumber wno = GetInspectWindowNumber(feature, index); @@ -718,6 +719,7 @@ void ShowNewGRFInspectWindow(GrfSpecFeature feature, uint index, const uint32 gr void InvalidateNewGRFInspectWindow(GrfSpecFeature feature, uint index) { if (feature == GSF_INVALID) return; + if (index >= (1 << 27)) return; WindowNumber wno = GetInspectWindowNumber(feature, index); InvalidateWindowData(WC_NEWGRF_INSPECT, wno); @@ -734,6 +736,7 @@ void InvalidateNewGRFInspectWindow(GrfSpecFeature feature, uint index) void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index) { if (feature == GSF_INVALID) return; + if (index >= (1 << 27)) return; WindowNumber wno = GetInspectWindowNumber(feature, index); DeleteWindowById(WC_NEWGRF_INSPECT, wno); @@ -755,6 +758,7 @@ void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index) */ bool IsNewGRFInspectable(GrfSpecFeature feature, uint index) { + if (index >= (1 << 27)) return false; const NIFeature *nif = GetFeature(GetInspectWindowNumber(feature, index)); if (nif == NULL) return false; return nif->helper->IsInspectable(index);