Merge branch 'extra_large_maps-sx' into jgrpp
Conflicts: src/saveload/saveload.cpp
This commit is contained in:
@@ -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}
|
||||
|
10
src/map.cpp
10
src/map.cpp
@@ -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
|
||||
|
Reference in New Issue
Block a user