Merge branch 'extra_large_maps-sx' into jgrpp

Conflicts:
	src/saveload/saveload.cpp
pull/3/head
Jonathan G Rennison 9 years ago
commit 8b994e255d

@ -886,6 +886,8 @@
<ClCompile Include="..\src\saveload\town_sl.cpp" />
<ClCompile Include="..\src\saveload\vehicle_sl.cpp" />
<ClCompile Include="..\src\saveload\waypoint_sl.cpp" />
<ClInclude Include="..\src\saveload\extended_ver_sl.h" />
<ClCompile Include="..\src\saveload\extended_ver_sl.cpp" />
<ClInclude Include="..\src\table\airport_defaults.h" />
<ClInclude Include="..\src\table\airport_movement.h" />
<ClInclude Include="..\src\table\airporttile_ids.h" />

@ -1836,6 +1836,12 @@
<ClCompile Include="..\src\saveload\waypoint_sl.cpp">
<Filter>Save/Load handlers</Filter>
</ClCompile>
<ClInclude Include="..\src\saveload\extended_ver_sl.h">
<Filter>Save/Load handlers</Filter>
</ClInclude>
<ClCompile Include="..\src\saveload\extended_ver_sl.cpp">
<Filter>Save/Load handlers</Filter>
</ClCompile>
<ClInclude Include="..\src\table\airport_defaults.h">
<Filter>Tables</Filter>
</ClInclude>

@ -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"
@ -281,12 +282,37 @@ static void LandscapeGenerationCallback(Window *w, bool confirmed)
if (confirmed) StartGeneratingLandscape((GenerateLandscapeWindowMode)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->Append() = item;
}
@ -314,6 +340,14 @@ struct GenerateLandscapeWindow : public Window {
char name[64];
GenerateLandscapeWindowMode mode;
void SetDropDownColor()
{
/* Draw sizes in mapsize selection dropdowns in red if too large size is selected */
bool mapsize_valid = CheckMapSize(false);
this->GetWidget<NWidgetCore>(WID_GL_MAPSIZE_X_PULLDOWN)->widget_data = mapsize_valid ? STR_JUST_INT : STR_RED_INT;
this->GetWidget<NWidgetCore>(WID_GL_MAPSIZE_Y_PULLDOWN)->widget_data = mapsize_valid ? STR_JUST_INT : STR_RED_INT;
}
GenerateLandscapeWindow(WindowDesc *desc, WindowNumber number = 0) : Window(desc)
{
this->InitNested(number);
@ -322,6 +356,8 @@ struct GenerateLandscapeWindow : public Window {
this->mode = (GenerateLandscapeWindowMode)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 Window {
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
@ -554,6 +590,7 @@ struct GenerateLandscapeWindow : public Window {
break;
case WID_GL_GENERATE_BUTTON: { // Generate
if (!CheckMapSize()) break;
/* Get rotated map size. */
uint map_x;
uint map_y;
@ -716,8 +753,14 @@ struct GenerateLandscapeWindow : public Window {
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;
@ -881,10 +924,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<NWidgetCore>(WID_CS_MAPSIZE_X_PULLDOWN)->widget_data = mapsize_valid ? STR_JUST_INT : STR_RED_INT;
this->GetWidget<NWidgetCore>(WID_CS_MAPSIZE_Y_PULLDOWN)->widget_data = mapsize_valid ? STR_JUST_INT : STR_RED_INT;
}
CreateScenarioWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
{
this->InitNested(window_number);
this->LowerWidget(_settings_newgame.game_creation.landscape + WID_CS_TEMPERATE);
SetDropDownColor();
}
virtual void SetStringParameters(int widget) const
@ -908,6 +960,8 @@ struct CreateScenarioWindow : public Window
}
}
virtual void OnPaint()
{
this->SetWidgetDisabledState(WID_CS_START_DATE_DOWN, _settings_newgame.game_creation.starting_year <= MIN_YEAR);
@ -961,18 +1015,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;
@ -1031,6 +1087,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();
}

@ -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 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
0xD8F, 0x1296, 0x2496, 0x4357, 0x8679, 0x1030E, 0x206CD, 0x403FE, 0x807B8, 0x1004B2, 0x2006A8,
0x4004B2, 0x800B87, 0x10004F3, 0x200072D, 0x40006AE, 0x80009E3,
};
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 */

@ -3070,6 +3070,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_MAX_HEIGHTLEVEL_QUERY_CAPT :{WHITE}Change maximum map height
STR_MAPGEN_SNOW_LINE_QUERY_CAPT :{WHITE}Change snow line height
@ -5482,6 +5483,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}

@ -40,17 +40,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;

@ -62,9 +62,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 = 12; ///< 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 = 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 = 4096
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 = 256M (16k x 16k)
/**
* Approximation of the length of a straight track, relative to a diagonal

@ -56,7 +56,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);
}
/**
@ -68,8 +68,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;
}
/**
@ -246,7 +246,7 @@ struct NIFeature {
*/
static inline GrfSpecFeature GetFeatureNum(uint window_number)
{
return (GrfSpecFeature)GB(window_number, 24, 8);
return (GrfSpecFeature)GB(window_number, 27, 5);
}
/**
@ -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);

@ -977,6 +977,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;
@ -984,6 +1002,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);
}
@ -999,6 +1018,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);
}
@ -1144,6 +1164,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;
@ -1186,6 +1207,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();

@ -894,9 +894,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<uint32>(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);
@ -1667,6 +1678,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
@ -1680,6 +1701,15 @@ static void SlLoadChunk(const ChunkHandler *ch)
_sl.block_mode = m;
_sl.obj_len = 0;
SaveLoadChunkExtHeaderFlags ext_flags = static_cast<SaveLoadChunkExtHeaderFlags>(0);
if ((m & 0xF) == CH_EXT_HDR) {
ext_flags = static_cast<SaveLoadChunkExtHeaderFlags>(SlReadUint32());
/* read in real header */
m = SlReadByte();
_sl.block_mode = m;
}
switch (m) {
case CH_ARRAY:
_sl.array_index = 0;
@ -1701,6 +1731,10 @@ static void SlLoadChunk(const ChunkHandler *ch)
}
len = SlReadUint32();
}
if (ext_flags & SLCEHF_BIG_RIFF) {
len |= SlReadUint32() << 28;
}
_sl.obj_len = len;
endoffs = _sl.reader->GetSize() + len;
ch->load_proc();
@ -1726,9 +1760,21 @@ static void SlLoadCheckChunk(const ChunkHandler *ch)
_sl.block_mode = m;
_sl.obj_len = 0;
SaveLoadChunkExtHeaderFlags ext_flags = static_cast<SaveLoadChunkExtHeaderFlags>(0);
if ((m & 0xF) == CH_EXT_HDR) {
ext_flags = static_cast<SaveLoadChunkExtHeaderFlags>(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 {
@ -1736,6 +1782,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 {
@ -1744,6 +1793,9 @@ 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();
@ -1752,6 +1804,14 @@ static void SlLoadCheckChunk(const ChunkHandler *ch)
SlErrorCorrupt("RIFF chunk too large");
}
len = SlReadUint32();
if (ext_flags & SLCEHF_BIG_RIFF) SlErrorCorrupt("XSLFI_RIFF_HEADER_60_BIT and SLCEHF_BIG_RIFF both present");
}
if (ext_flags & SLCEHF_BIG_RIFF) {
uint64 full_len = len | (static_cast<uint64>(SlReadUint32()) << 28);
if (full_len >= (1LL << 32)) {
SlErrorCorrupt("Chunk size too large: " OTTD_PRINTFHEX64, full_len);
}
len = static_cast<size_t>(full_len);
}
_sl.obj_len = len;
endoffs = _sl.reader->GetSize() + len;

@ -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

Loading…
Cancel
Save