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\town_sl.cpp" />
|
||||||
<ClCompile Include="..\src\saveload\vehicle_sl.cpp" />
|
<ClCompile Include="..\src\saveload\vehicle_sl.cpp" />
|
||||||
<ClCompile Include="..\src\saveload\waypoint_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_defaults.h" />
|
||||||
<ClInclude Include="..\src\table\airport_movement.h" />
|
<ClInclude Include="..\src\table\airport_movement.h" />
|
||||||
<ClInclude Include="..\src\table\airporttile_ids.h" />
|
<ClInclude Include="..\src\table\airporttile_ids.h" />
|
||||||
|
@@ -1836,6 +1836,12 @@
|
|||||||
<ClCompile Include="..\src\saveload\waypoint_sl.cpp">
|
<ClCompile Include="..\src\saveload\waypoint_sl.cpp">
|
||||||
<Filter>Save/Load handlers</Filter>
|
<Filter>Save/Load handlers</Filter>
|
||||||
</ClCompile>
|
</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">
|
<ClInclude Include="..\src\table\airport_defaults.h">
|
||||||
<Filter>Tables</Filter>
|
<Filter>Tables</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
#include "sound_func.h"
|
#include "sound_func.h"
|
||||||
#include "fios.h"
|
#include "fios.h"
|
||||||
#include "string_func.h"
|
#include "string_func.h"
|
||||||
|
#include "gui.h"
|
||||||
#include "widgets/dropdown_type.h"
|
#include "widgets/dropdown_type.h"
|
||||||
#include "widgets/dropdown_func.h"
|
#include "widgets/dropdown_func.h"
|
||||||
#include "querystring_gui.h"
|
#include "querystring_gui.h"
|
||||||
@@ -281,12 +282,37 @@ static void LandscapeGenerationCallback(Window *w, bool confirmed)
|
|||||||
if (confirmed) StartGeneratingLandscape((GenerateLandscapeWindowMode)w->window_number);
|
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();
|
DropDownList *list = new DropDownList();
|
||||||
|
|
||||||
for (uint i = MIN_MAP_SIZE_BITS; i <= MAX_MAP_SIZE_BITS; i++) {
|
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);
|
item->SetParam(0, 1 << i);
|
||||||
*list->Append() = item;
|
*list->Append() = item;
|
||||||
}
|
}
|
||||||
@@ -314,6 +340,14 @@ struct GenerateLandscapeWindow : public Window {
|
|||||||
char name[64];
|
char name[64];
|
||||||
GenerateLandscapeWindowMode mode;
|
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)
|
GenerateLandscapeWindow(WindowDesc *desc, WindowNumber number = 0) : Window(desc)
|
||||||
{
|
{
|
||||||
this->InitNested(number);
|
this->InitNested(number);
|
||||||
@@ -322,6 +356,8 @@ struct GenerateLandscapeWindow : public Window {
|
|||||||
|
|
||||||
this->mode = (GenerateLandscapeWindowMode)this->window_number;
|
this->mode = (GenerateLandscapeWindowMode)this->window_number;
|
||||||
|
|
||||||
|
SetDropDownColor();
|
||||||
|
|
||||||
/* Disable town, industry and trees in SE */
|
/* Disable town, industry and trees in SE */
|
||||||
this->SetWidgetDisabledState(WID_GL_TOWN_PULLDOWN, _game_mode == GM_EDITOR);
|
this->SetWidgetDisabledState(WID_GL_TOWN_PULLDOWN, _game_mode == GM_EDITOR);
|
||||||
this->SetWidgetDisabledState(WID_GL_INDUSTRY_PULLDOWN, _game_mode == GM_EDITOR);
|
this->SetWidgetDisabledState(WID_GL_INDUSTRY_PULLDOWN, _game_mode == GM_EDITOR);
|
||||||
@@ -538,11 +574,11 @@ struct GenerateLandscapeWindow : public Window {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_GL_MAPSIZE_X_PULLDOWN: // Mapsize X
|
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;
|
break;
|
||||||
|
|
||||||
case WID_GL_MAPSIZE_Y_PULLDOWN: // Mapsize Y
|
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;
|
break;
|
||||||
|
|
||||||
case WID_GL_TOWN_PULLDOWN: // Number of towns
|
case WID_GL_TOWN_PULLDOWN: // Number of towns
|
||||||
@@ -554,6 +590,7 @@ struct GenerateLandscapeWindow : public Window {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_GL_GENERATE_BUTTON: { // Generate
|
case WID_GL_GENERATE_BUTTON: { // Generate
|
||||||
|
if (!CheckMapSize()) break;
|
||||||
/* Get rotated map size. */
|
/* Get rotated map size. */
|
||||||
uint map_x;
|
uint map_x;
|
||||||
uint map_y;
|
uint map_y;
|
||||||
@@ -716,8 +753,14 @@ struct GenerateLandscapeWindow : public Window {
|
|||||||
virtual void OnDropdownSelect(int widget, int index)
|
virtual void OnDropdownSelect(int widget, int index)
|
||||||
{
|
{
|
||||||
switch (widget) {
|
switch (widget) {
|
||||||
case WID_GL_MAPSIZE_X_PULLDOWN: _settings_newgame.game_creation.map_x = index; break;
|
case WID_GL_MAPSIZE_X_PULLDOWN:
|
||||||
case WID_GL_MAPSIZE_Y_PULLDOWN: _settings_newgame.game_creation.map_y = index; break;
|
_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_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_RIVER_PULLDOWN: _settings_newgame.game_creation.amount_of_rivers = index; break;
|
||||||
case WID_GL_SMOOTHNESS_PULLDOWN: _settings_newgame.game_creation.tgen_smoothness = 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;
|
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)
|
CreateScenarioWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
|
||||||
{
|
{
|
||||||
this->InitNested(window_number);
|
this->InitNested(window_number);
|
||||||
this->LowerWidget(_settings_newgame.game_creation.landscape + WID_CS_TEMPERATE);
|
this->LowerWidget(_settings_newgame.game_creation.landscape + WID_CS_TEMPERATE);
|
||||||
|
SetDropDownColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void SetStringParameters(int widget) const
|
virtual void SetStringParameters(int widget) const
|
||||||
@@ -908,6 +960,8 @@ struct CreateScenarioWindow : public Window
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
virtual void OnPaint()
|
virtual void OnPaint()
|
||||||
{
|
{
|
||||||
this->SetWidgetDisabledState(WID_CS_START_DATE_DOWN, _settings_newgame.game_creation.starting_year <= MIN_YEAR);
|
this->SetWidgetDisabledState(WID_CS_START_DATE_DOWN, _settings_newgame.game_creation.starting_year <= MIN_YEAR);
|
||||||
@@ -961,18 +1015,20 @@ struct CreateScenarioWindow : public Window
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_CS_MAPSIZE_X_PULLDOWN: // Mapsize X
|
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;
|
break;
|
||||||
|
|
||||||
case WID_CS_MAPSIZE_Y_PULLDOWN: // Mapsize Y
|
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;
|
break;
|
||||||
|
|
||||||
case WID_CS_EMPTY_WORLD: // Empty world / flat world
|
case WID_CS_EMPTY_WORLD: // Empty world / flat world
|
||||||
|
if (!CheckMapSize()) break;
|
||||||
StartGeneratingLandscape(GLWM_SCENARIO);
|
StartGeneratingLandscape(GLWM_SCENARIO);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_CS_RANDOM_WORLD: // Generate
|
case WID_CS_RANDOM_WORLD: // Generate
|
||||||
|
if (!CheckMapSize()) break;
|
||||||
ShowGenerateLandscape();
|
ShowGenerateLandscape();
|
||||||
break;
|
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_X_PULLDOWN: _settings_newgame.game_creation.map_x = index; break;
|
||||||
case WID_CS_MAPSIZE_Y_PULLDOWN: _settings_newgame.game_creation.map_y = index; break;
|
case WID_CS_MAPSIZE_Y_PULLDOWN: _settings_newgame.game_creation.map_y = index; break;
|
||||||
}
|
}
|
||||||
|
SetDropDownColor();
|
||||||
|
|
||||||
this->SetDirty();
|
this->SetDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -723,12 +723,13 @@ void RunTileLoop()
|
|||||||
* shift register (LFSR). This allows a deterministic pseudorandom ordering, but
|
* shift register (LFSR). This allows a deterministic pseudorandom ordering, but
|
||||||
* still with minimal state and fast iteration. */
|
* 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/ */
|
* Extracted from http://www.ece.cmu.edu/~koopman/lfsr/ */
|
||||||
static const uint32 feedbacks[] = {
|
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];
|
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 */
|
/* 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_NAME :{BLACK}Heightmap name:
|
||||||
STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}Size:
|
STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}Size:
|
||||||
STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} x {NUM}
|
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_MAX_HEIGHTLEVEL_QUERY_CAPT :{WHITE}Change maximum map height
|
||||||
STR_MAPGEN_SNOW_LINE_QUERY_CAPT :{WHITE}Change snow line 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_TINY_GROUP :{TINY_FONT}{GROUP}
|
||||||
STR_BLACK_INT :{BLACK}{NUM}
|
STR_BLACK_INT :{BLACK}{NUM}
|
||||||
STR_ORANGE_INT :{ORANGE}{NUM}
|
STR_ORANGE_INT :{ORANGE}{NUM}
|
||||||
|
STR_RED_INT :{RED}{NUM}
|
||||||
STR_WHITE_SIGN :{WHITE}{SIGN}
|
STR_WHITE_SIGN :{WHITE}{SIGN}
|
||||||
STR_TINY_BLACK_STATION :{TINY_FONT}{BLACK}{STATION}
|
STR_TINY_BLACK_STATION :{TINY_FONT}{BLACK}{STATION}
|
||||||
STR_BLACK_STRING :{BLACK}{STRING}
|
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)
|
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
|
/* Make sure that the map size is within the limits and that
|
||||||
* size of both axes is a power of 2. */
|
* size of both axes is a power of 2. */
|
||||||
if (!IsInsideMM(size_x, MIN_MAP_SIZE, MAX_MAP_SIZE + 1) ||
|
if (size_x * size_y > MAX_MAP_TILES ||
|
||||||
!IsInsideMM(size_y, MIN_MAP_SIZE, MAX_MAP_SIZE + 1) ||
|
size_x < MIN_MAP_SIZE ||
|
||||||
|
size_y < MIN_MAP_SIZE ||
|
||||||
(size_x & (size_x - 1)) != 0 ||
|
(size_x & (size_x - 1)) != 0 ||
|
||||||
(size_y & (size_y - 1)) != 0) {
|
(size_y & (size_y - 1)) != 0) {
|
||||||
error("Invalid map size");
|
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_x = FindFirstBit(size_x);
|
||||||
_map_log_y = FindFirstBit(size_y);
|
_map_log_y = FindFirstBit(size_y);
|
||||||
_map_size_x = size_x;
|
_map_size_x = size_x;
|
||||||
|
@@ -62,9 +62,11 @@ struct TileIndexDiffC {
|
|||||||
|
|
||||||
/** Minimal and maximal map width and height */
|
/** 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 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 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
|
* 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)
|
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)
|
static inline uint GetInspectWindowNumber(GrfSpecFeature feature, uint index)
|
||||||
{
|
{
|
||||||
assert((index >> 24) == 0);
|
assert((index >> 27) == 0);
|
||||||
return (feature << 24) | index;
|
return (feature << 27) | index;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -246,7 +246,7 @@ struct NIFeature {
|
|||||||
*/
|
*/
|
||||||
static inline GrfSpecFeature GetFeatureNum(uint window_number)
|
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)
|
void ShowNewGRFInspectWindow(GrfSpecFeature feature, uint index, const uint32 grfid)
|
||||||
{
|
{
|
||||||
|
if (index >= (1 << 27)) return;
|
||||||
if (!IsNewGRFInspectable(feature, index)) return;
|
if (!IsNewGRFInspectable(feature, index)) return;
|
||||||
|
|
||||||
WindowNumber wno = GetInspectWindowNumber(feature, index);
|
WindowNumber wno = GetInspectWindowNumber(feature, index);
|
||||||
@@ -718,6 +719,7 @@ void ShowNewGRFInspectWindow(GrfSpecFeature feature, uint index, const uint32 gr
|
|||||||
void InvalidateNewGRFInspectWindow(GrfSpecFeature feature, uint index)
|
void InvalidateNewGRFInspectWindow(GrfSpecFeature feature, uint index)
|
||||||
{
|
{
|
||||||
if (feature == GSF_INVALID) return;
|
if (feature == GSF_INVALID) return;
|
||||||
|
if (index >= (1 << 27)) return;
|
||||||
|
|
||||||
WindowNumber wno = GetInspectWindowNumber(feature, index);
|
WindowNumber wno = GetInspectWindowNumber(feature, index);
|
||||||
InvalidateWindowData(WC_NEWGRF_INSPECT, wno);
|
InvalidateWindowData(WC_NEWGRF_INSPECT, wno);
|
||||||
@@ -734,6 +736,7 @@ void InvalidateNewGRFInspectWindow(GrfSpecFeature feature, uint index)
|
|||||||
void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index)
|
void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index)
|
||||||
{
|
{
|
||||||
if (feature == GSF_INVALID) return;
|
if (feature == GSF_INVALID) return;
|
||||||
|
if (index >= (1 << 27)) return;
|
||||||
|
|
||||||
WindowNumber wno = GetInspectWindowNumber(feature, index);
|
WindowNumber wno = GetInspectWindowNumber(feature, index);
|
||||||
DeleteWindowById(WC_NEWGRF_INSPECT, wno);
|
DeleteWindowById(WC_NEWGRF_INSPECT, wno);
|
||||||
@@ -755,6 +758,7 @@ void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index)
|
|||||||
*/
|
*/
|
||||||
bool IsNewGRFInspectable(GrfSpecFeature feature, uint index)
|
bool IsNewGRFInspectable(GrfSpecFeature feature, uint index)
|
||||||
{
|
{
|
||||||
|
if (index >= (1 << 27)) return false;
|
||||||
const NIFeature *nif = GetFeature(GetInspectWindowNumber(feature, index));
|
const NIFeature *nif = GetFeature(GetInspectWindowNumber(feature, index));
|
||||||
if (nif == NULL) return false;
|
if (nif == NULL) return false;
|
||||||
return nif->helper->IsInspectable(index);
|
return nif->helper->IsInspectable(index);
|
||||||
|
@@ -977,6 +977,24 @@ static void MakeNewGameDone()
|
|||||||
MarkWholeScreenDirty();
|
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)
|
static void MakeNewGame(bool from_heightmap, bool reset_settings)
|
||||||
{
|
{
|
||||||
_game_mode = GM_NORMAL;
|
_game_mode = GM_NORMAL;
|
||||||
@@ -984,6 +1002,7 @@ static void MakeNewGame(bool from_heightmap, bool reset_settings)
|
|||||||
ResetGRFConfig(true);
|
ResetGRFConfig(true);
|
||||||
|
|
||||||
GenerateWorldSetCallback(&MakeNewGameDone);
|
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);
|
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);
|
ResetGRFConfig(true);
|
||||||
|
|
||||||
GenerateWorldSetCallback(&MakeNewEditorWorldDone);
|
GenerateWorldSetCallback(&MakeNewEditorWorldDone);
|
||||||
|
FixConfigMapSize();
|
||||||
GenerateWorld(GWM_EMPTY, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
|
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
|
case SM_LOAD_HEIGHTMAP: // Load heightmap from scenario editor
|
||||||
SetLocalCompany(OWNER_NONE);
|
SetLocalCompany(OWNER_NONE);
|
||||||
|
|
||||||
|
FixConfigMapSize();
|
||||||
GenerateWorld(GWM_HEIGHTMAP, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
|
GenerateWorld(GWM_HEIGHTMAP, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
|
||||||
MarkWholeScreenDirty();
|
MarkWholeScreenDirty();
|
||||||
break;
|
break;
|
||||||
@@ -1186,6 +1207,7 @@ void SwitchToMode(SwitchMode new_mode)
|
|||||||
|
|
||||||
case SM_GENRANDLAND: // Generate random land within scenario editor
|
case SM_GENRANDLAND: // Generate random land within scenario editor
|
||||||
SetLocalCompany(OWNER_NONE);
|
SetLocalCompany(OWNER_NONE);
|
||||||
|
FixConfigMapSize();
|
||||||
GenerateWorld(GWM_RANDOM, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
|
GenerateWorld(GWM_RANDOM, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
|
||||||
/* XXX: set date */
|
/* XXX: set date */
|
||||||
MarkWholeScreenDirty();
|
MarkWholeScreenDirty();
|
||||||
|
@@ -894,9 +894,20 @@ void SlSetLength(size_t length)
|
|||||||
case CH_RIFF:
|
case CH_RIFF:
|
||||||
/* Ugly encoding of >16M RIFF chunks
|
/* Ugly encoding of >16M RIFF chunks
|
||||||
* The lower 24 bits are normal
|
* The lower 24 bits are normal
|
||||||
* The uppermost 4 bits are bits 24:27 */
|
* The uppermost 4 bits are bits 24:27
|
||||||
assert(length < (1 << 28));
|
*
|
||||||
|
* 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)));
|
SlWriteUint32((uint32)((length & 0xFFFFFF) | ((length >> 24) << 28)));
|
||||||
|
if (length >= (1 << 28)) {
|
||||||
|
SlWriteUint32(length >> 28);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CH_ARRAY:
|
case CH_ARRAY:
|
||||||
assert(_sl.last_array_index <= _sl.array_index);
|
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");
|
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.)
|
* Load a chunk of data (eg vehicles, stations, etc.)
|
||||||
* @param ch The chunkhandler that will be used for the operation
|
* @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.block_mode = m;
|
||||||
_sl.obj_len = 0;
|
_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) {
|
switch (m) {
|
||||||
case CH_ARRAY:
|
case CH_ARRAY:
|
||||||
_sl.array_index = 0;
|
_sl.array_index = 0;
|
||||||
@@ -1701,6 +1731,10 @@ static void SlLoadChunk(const ChunkHandler *ch)
|
|||||||
}
|
}
|
||||||
len = SlReadUint32();
|
len = SlReadUint32();
|
||||||
}
|
}
|
||||||
|
if (ext_flags & SLCEHF_BIG_RIFF) {
|
||||||
|
len |= SlReadUint32() << 28;
|
||||||
|
}
|
||||||
|
|
||||||
_sl.obj_len = len;
|
_sl.obj_len = len;
|
||||||
endoffs = _sl.reader->GetSize() + len;
|
endoffs = _sl.reader->GetSize() + len;
|
||||||
ch->load_proc();
|
ch->load_proc();
|
||||||
@@ -1726,9 +1760,21 @@ static void SlLoadCheckChunk(const ChunkHandler *ch)
|
|||||||
_sl.block_mode = m;
|
_sl.block_mode = m;
|
||||||
_sl.obj_len = 0;
|
_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) {
|
switch (m) {
|
||||||
case CH_ARRAY:
|
case CH_ARRAY:
|
||||||
_sl.array_index = 0;
|
_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) {
|
if (ch && ch->load_check_proc) {
|
||||||
ch->load_check_proc();
|
ch->load_check_proc();
|
||||||
} else {
|
} else {
|
||||||
@@ -1736,6 +1782,9 @@ static void SlLoadCheckChunk(const ChunkHandler *ch)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CH_SPARSE_ARRAY:
|
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) {
|
if (ch && ch->load_check_proc) {
|
||||||
ch->load_check_proc();
|
ch->load_check_proc();
|
||||||
} else {
|
} else {
|
||||||
@@ -1744,6 +1793,9 @@ static void SlLoadCheckChunk(const ChunkHandler *ch)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if ((m & 0xF) == CH_RIFF) {
|
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 */
|
/* Read length */
|
||||||
len = (SlReadByte() << 16) | ((m >> 4) << 24);
|
len = (SlReadByte() << 16) | ((m >> 4) << 24);
|
||||||
len += SlReadUint16();
|
len += SlReadUint16();
|
||||||
@@ -1752,6 +1804,14 @@ static void SlLoadCheckChunk(const ChunkHandler *ch)
|
|||||||
SlErrorCorrupt("RIFF chunk too large");
|
SlErrorCorrupt("RIFF chunk too large");
|
||||||
}
|
}
|
||||||
len = SlReadUint32();
|
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;
|
_sl.obj_len = len;
|
||||||
endoffs = _sl.reader->GetSize() + len;
|
endoffs = _sl.reader->GetSize() + len;
|
||||||
|
@@ -99,10 +99,17 @@ enum ChunkType {
|
|||||||
CH_ARRAY = 1,
|
CH_ARRAY = 1,
|
||||||
CH_SPARSE_ARRAY = 2,
|
CH_SPARSE_ARRAY = 2,
|
||||||
CH_TYPE_MASK = 3,
|
CH_TYPE_MASK = 3,
|
||||||
|
CH_EXT_HDR = 15, ///< Extended chunk header
|
||||||
CH_LAST = 8, ///< Last chunk in this array.
|
CH_LAST = 8, ///< Last chunk in this array.
|
||||||
CH_AUTO_LENGTH = 16,
|
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
|
* VarTypes is the general bitmasked magic type that tells us
|
||||||
* certain characteristics about the variable it refers to. For example
|
* certain characteristics about the variable it refers to. For example
|
||||||
|
Reference in New Issue
Block a user