Index: src/settings.cpp =================================================================== --- src/settings.cpp (revision 10727) +++ src/settings.cpp (working copy) @@ -1341,8 +1341,8 @@ SDT_VAR(Patches, window_snap_radius, SLE_UINT8, S,D0, 10, 1, 32, 0, STR_CONFIG_PATCHES_SNAP_RADIUS, NULL), SDT_BOOL(Patches, invisible_trees, S, 0, false, STR_CONFIG_PATCHES_INVISIBLE_TREES, RedrawScreen), SDT_BOOL(Patches, population_in_label, S, 0, true, STR_CONFIG_PATCHES_POPULATION_IN_LABEL, PopulationInLabelActive), - SDT_VAR(Patches, map_x, SLE_UINT8, S, 0, 8, 6, 11, 0, STR_CONFIG_PATCHES_MAP_X, NULL), - SDT_VAR(Patches, map_y, SLE_UINT8, S, 0, 8, 6, 11, 0, STR_CONFIG_PATCHES_MAP_Y, NULL), + SDT_VAR(Patches, map_x, SLE_UINT8, S, 0, 8, 6, 18, 0, STR_CONFIG_PATCHES_MAP_X, NULL), + SDT_VAR(Patches, map_y, SLE_UINT8, S, 0, 8, 6, 18, 0, STR_CONFIG_PATCHES_MAP_Y, NULL), SDT_BOOL(Patches, link_terraform_toolbar, S, 0, false, STR_CONFIG_PATCHES_LINK_TERRAFORM_TOOLBAR,NULL), SDT_VAR(Patches, liveries, SLE_UINT8, S,MS, 2, 0, 2, 0, STR_CONFIG_PATCHES_LIVERIES, RedrawScreen), SDT_BOOL(Patches, prefer_teamchat, S, 0, false, STR_CONFIG_PATCHES_PREFER_TEAMCHAT, NULL), Index: src/lang/american.txt =================================================================== --- src/lang/american.txt (revision 10727) +++ src/lang/american.txt (working copy) @@ -306,6 +306,13 @@ STR_512 :512 STR_1024 :1024 STR_2048 :2048 +STR_4096 :4096 +STR_8192 :8192 +STR_16K :16384 +STR_32K :32768 +STR_64K :65536 +STR_128K :131072 +STR_256K :262144 STR_MAPSIZE :{BLACK}Map size: STR_BY :{BLACK}* STR_0148_GAME_OPTIONS :{BLACK}Game Options @@ -3245,6 +3252,7 @@ STR_HEIGHTMAP_SCALE_WARNING_MESSAGE :{YELLOW}Resizing source map too much is not recommended. Continue with the generation? STR_TOWN_LAYOUT_WARNING_CAPTION :{WHITE}Town layout warning STR_TOWN_LAYOUT_WARNING_MESSAGE :{YELLOW}The town layout "no more roads" is not recommended. Continue with the generation? +STR_MAP_TOO_MANY_TILES_MESSAGE :{YELLOW}Too many tiles in map. Maximum number of tiles is {NUM}, you have selected {NUM} STR_SNOW_LINE_HEIGHT_NUM :{NUM} STR_HEIGHTMAP_NAME :{BLACK}Heightmap name: STR_HEIGHTMAP_SIZE :{BLACK}Size: {ORANGE}{NUM} x {NUM} Index: src/lang/english.txt =================================================================== --- src/lang/english.txt (revision 10727) +++ src/lang/english.txt (working copy) @@ -306,6 +306,13 @@ STR_512 :512 STR_1024 :1024 STR_2048 :2048 +STR_4096 :4096 +STR_8192 :8192 +STR_16K :16384 +STR_32K :32768 +STR_64K :65536 +STR_128K :131072 +STR_256K :262144 STR_MAPSIZE :{BLACK}Map size: STR_BY :{BLACK}* STR_0148_GAME_OPTIONS :{BLACK}Game Options @@ -3245,6 +3252,7 @@ STR_HEIGHTMAP_SCALE_WARNING_MESSAGE :{YELLOW}Resizing source map too much is not recommended. Continue with the generation? STR_TOWN_LAYOUT_WARNING_CAPTION :{WHITE}Town layout warning STR_TOWN_LAYOUT_WARNING_MESSAGE :{YELLOW}The town layout "no more roads" is not recommended. Continue with the generation? +STR_MAP_TOO_MANY_TILES_MESSAGE :{YELLOW}Too many tiles in map. Maximum number of tiles is {NUM}, you have selected {NUM} STR_SNOW_LINE_HEIGHT_NUM :{NUM} STR_HEIGHTMAP_NAME :{BLACK}Heightmap name: STR_HEIGHTMAP_SIZE :{BLACK}Size: {ORANGE}{NUM} x {NUM} Index: src/lang/czech.txt =================================================================== --- src/lang/czech.txt (revision 10727) +++ src/lang/czech.txt (working copy) @@ -364,6 +364,13 @@ STR_512 :512 STR_1024 :1024 STR_2048 :2048 +STR_4096 :4096 +STR_8192 :8192 +STR_16K :16384 +STR_32K :32768 +STR_64K :65536 +STR_128K :131072 +STR_256K :262144 STR_MAPSIZE :{BLACK}Velikost mapy: STR_BY :{BLACK}* STR_0148_GAME_OPTIONS :{BLACK}Možnosti hry @@ -3309,6 +3316,7 @@ STR_HEIGHTMAP_SCALE_WARNING_MESSAGE :{YELLOW}Tak velká zmena velikosti zdrojové mapy není doporučena. Pokračovat s generováním? STR_TOWN_LAYOUT_WARNING_CAPTION :{WHITE}Varování kvůli vzoru silnic STR_TOWN_LAYOUT_WARNING_MESSAGE :{YELLOW}Vzor "žádné silnice" není doporučen (nepostaví se ani domy). Pokračovat ve vytváření mapy? +STR_MAP_TOO_MANY_TILES_MESSAGE :{YELLOW}Příliš mnoho políček v mapě. Maximální počet je {NUM}, zvoleno je {NUM} STR_SNOW_LINE_HEIGHT_NUM :{NUM} STR_HEIGHTMAP_NAME :{BLACK}Jméno výškové mapy: STR_HEIGHTMAP_SIZE :{BLACK}Velikost: {ORANGE}{NUM} x {NUM} Index: src/genworld_gui.cpp =================================================================== --- src/genworld_gui.cpp (revision 10727) +++ src/genworld_gui.cpp (working copy) @@ -25,6 +25,7 @@ #include "thread.h" #include "date.h" #include "newgrf_config.h" +#include "map.h" /** * In what 'mode' the GenerateLandscapeWindowProc is. @@ -106,10 +107,10 @@ { WWT_IMGBTN_2, RESIZE_NONE, 12, 170, 246, 24, 78, SPR_SELECT_SUB_TROPICAL, STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE}, { WWT_IMGBTN_2, RESIZE_NONE, 12, 250, 326, 24, 78, SPR_SELECT_TOYLAND, STR_0311_SELECT_TOYLAND_LANDSCAPE}, -{ WWT_PANEL, RESIZE_NONE, 12, 114, 149, 90, 101, 0x0, STR_NULL}, -{ WWT_TEXTBTN, RESIZE_NONE, 12, 150, 161, 90, 101, STR_0225, STR_NULL}, // Mapsize X -{ WWT_PANEL, RESIZE_NONE, 12, 180, 215, 90, 101, 0x0, STR_NULL}, -{ WWT_TEXTBTN, RESIZE_NONE, 12, 216, 227, 90, 101, STR_0225, STR_NULL}, // Mapsize Y +{ WWT_PANEL, RESIZE_NONE, 12, 114, 159, 90, 101, 0x0, STR_NULL}, +{ WWT_TEXTBTN, RESIZE_NONE, 12, 160, 171, 90, 101, STR_0225, STR_NULL}, // Mapsize X +{ WWT_PANEL, RESIZE_NONE, 12, 190, 235, 90, 101, 0x0, STR_NULL}, +{ WWT_TEXTBTN, RESIZE_NONE, 12, 236, 247, 90, 101, STR_0225, STR_NULL}, // Mapsize Y { WWT_PANEL, RESIZE_NONE, 12, 114, 163, 112, 123, 0x0, STR_NULL}, { WWT_TEXTBTN, RESIZE_NONE, 12, 164, 175, 112, 123, STR_0225, STR_NULL}, // Number of towns @@ -152,10 +153,10 @@ { WWT_IMGBTN_2, RESIZE_NONE, 12, 170, 246, 24, 78, SPR_SELECT_SUB_TROPICAL, STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE}, { WWT_IMGBTN_2, RESIZE_NONE, 12, 250, 326, 24, 78, SPR_SELECT_TOYLAND, STR_0311_SELECT_TOYLAND_LANDSCAPE}, -{ WWT_PANEL, RESIZE_NONE, 12, 114, 149, 112, 123, 0x0, STR_NULL}, -{ WWT_TEXTBTN, RESIZE_NONE, 12, 150, 161, 112, 123, STR_0225, STR_NULL}, // Mapsize X -{ WWT_PANEL, RESIZE_NONE, 12, 180, 215, 112, 123, 0x0, STR_NULL}, -{ WWT_TEXTBTN, RESIZE_NONE, 12, 216, 227, 112, 123, STR_0225, STR_NULL}, // Mapsize Y +{ WWT_PANEL, RESIZE_NONE, 12, 114, 159, 112, 123, 0x0, STR_NULL}, +{ WWT_TEXTBTN, RESIZE_NONE, 12, 160, 171, 112, 123, STR_0225, STR_NULL}, // Mapsize X +{ WWT_PANEL, RESIZE_NONE, 12, 190, 235, 112, 123, 0x0, STR_NULL}, +{ WWT_TEXTBTN, RESIZE_NONE, 12, 236, 247, 112, 123, STR_0225, STR_NULL}, // Mapsize Y { WWT_PANEL, RESIZE_NONE, 12, 114, 163, 134, 145, 0x0, STR_NULL}, { WWT_TEXTBTN, RESIZE_NONE, 12, 164, 175, 134, 145, STR_0225, STR_NULL}, // Number of towns @@ -183,6 +184,9 @@ { WIDGETS_END}, }; +/** Allowed map sizes, common for scenario editor and new map GUI */ +static const StringID mapsizes[] = {STR_64, STR_128, STR_256, STR_512, STR_1024, STR_2048, STR_4096, STR_8192, STR_16K, STR_32K, STR_64K, STR_128K, STR_256K, INVALID_STRING_ID}; + void StartGeneratingLandscape(glwp_modes mode) { DeleteAllNonVitalWindows(); @@ -207,9 +211,29 @@ if (confirmed) StartGeneratingLandscape((glwp_modes)w->window_number); } +/** + Check if map size set lies in allowed boundaries. + If size is outside limits, warning is printed out + @return true if size is ok, false otherwise. +*/ +static bool CheckMapSize() { + uint64 map_x = 1U << _patches_newgame.map_x; + uint64 map_y = 1U << _patches_newgame.map_y; + uint64 tiles = map_x * map_y; + + if (tiles > MAX_MAP_TILES) { + SetDParam(0, MAX_MAP_TILES); + + SetDParam(1, tiles); + ShowErrorMessage(INVALID_STRING_ID, STR_MAP_TOO_MANY_TILES_MESSAGE, 0, 0); + return false; + } + return true; +} + + static void GenerateLandscapeWndProc(Window *w, WindowEvent *e) { - static const StringID mapsizes[] = {STR_64, STR_128, STR_256, STR_512, STR_1024, STR_2048, INVALID_STRING_ID}; static const StringID elevations[] = {STR_682A_VERY_FLAT, STR_682B_FLAT, STR_682C_HILLY, STR_682D_MOUNTAINOUS, INVALID_STRING_ID}; static const StringID sea_lakes[] = {STR_VERY_LOW, STR_6820_LOW, STR_6821_MEDIUM, STR_6822_HIGH, INVALID_STRING_ID}; static const StringID smoothness[] = {STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_SMOOTH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_ROUGH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_ROUGH, INVALID_STRING_ID}; @@ -267,8 +291,8 @@ DrawString( 12, 91 + y, STR_MAPSIZE, 0); DrawString(119, 91 + y, mapsizes[_patches_newgame.map_x - 6], 0x10); - DrawString(168, 91 + y, STR_BY, 0); - DrawString(182, 91 + y, mapsizes[_patches_newgame.map_y - 6], 0x10); + DrawString(178, 91 + y, STR_BY, 0); + DrawString(192, 91 + y, mapsizes[_patches_newgame.map_y - 6], 0x10); DrawString( 12, 113 + y, STR_NUMBER_OF_TOWNS, 0); DrawString( 12, 131 + y, STR_NUMBER_OF_INDUSTRIES, 0); @@ -356,10 +380,11 @@ UpdateTextBufferSize(&_genseed_query.text); SetWindowDirty(w); break; - case GLAND_GENERATE_BUTTON: // Generate + case GLAND_GENERATE_BUTTON: { // Generate UpdatePatches(); + if (!CheckMapSize()) break; if (_patches.town_layout == TL_NO_ROADS) { ShowQuery( STR_TOWN_LAYOUT_WARNING_CAPTION, @@ -381,6 +406,7 @@ StartGeneratingLandscape(mode); } break; + } case GLAND_START_DATE_DOWN: case GLAND_START_DATE_UP: // Year buttons /* Don't allow too fast scrolling */ if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) { @@ -602,8 +628,6 @@ static void CreateScenarioWndProc(Window *w, WindowEvent *e) { - static const StringID mapsizes[] = {STR_64, STR_128, STR_256, STR_512, STR_1024, STR_2048, INVALID_STRING_ID}; - switch (e->event) { case WE_CREATE: LowerWindowWidget(w, _opt_newgame.landscape + CSCEN_TEMPERATE); break; @@ -619,10 +643,10 @@ SetWindowWidgetLoweredState(w, CSCEN_TOYLAND, _opt_newgame.landscape == LT_TOYLAND); DrawWindowWidgets(w); - DrawStringRightAligned(211, 97, STR_MAPSIZE, 0); - DrawString( 221, 97, mapsizes[_patches_newgame.map_x - 6], 0x10); - DrawStringCentered( 272, 97, STR_BY, 0); - DrawString( 284, 97, mapsizes[_patches_newgame.map_y - 6], 0x10); + DrawStringRightAligned(191, 97, STR_MAPSIZE, 0); + DrawString( 201, 97, mapsizes[_patches_newgame.map_x - 6], 0x10); + DrawStringCentered( 262, 97, STR_BY, 0); + DrawString( 274, 97, mapsizes[_patches_newgame.map_y - 6], 0x10); DrawStringRightAligned(211, 115, STR_DATE, 0); SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1)); @@ -646,9 +670,11 @@ ShowDropDownMenu(w, mapsizes, _patches_newgame.map_y - 6, CSCEN_MAPSIZE_Y_PULLDOWN, 0, 0); break; case CSCEN_EMPTY_WORLD: // Empty world / flat world + if (!CheckMapSize()) break; StartGeneratingLandscape(GLWP_SCENARIO); break; case CSCEN_RANDOM_WORLD: // Generate + if (!CheckMapSize()) break; ShowGenerateLandscape(); break; case CSCEN_START_DATE_DOWN: case CSCEN_START_DATE_UP: // Year buttons @@ -727,9 +753,9 @@ { WWT_TEXTBTN, RESIZE_NONE, 6, 12, 115, 95, 124, STR_SE_FLAT_WORLD, STR_SE_FLAT_WORLD_TIP}, // Empty (sea-level) map { WWT_TEXTBTN, RESIZE_NONE, 6, 12, 115, 131, 160, STR_SE_RANDOM_LAND, STR_022A_GENERATE_RANDOM_LAND}, // Generate -{ WWT_PANEL, RESIZE_NONE, 12, 216, 251, 95, 106, 0x0, STR_NULL}, -{ WWT_TEXTBTN, RESIZE_NONE, 12, 252, 263, 95, 106, STR_0225, STR_NULL}, // Mapsize X -{ WWT_PANEL, RESIZE_NONE, 12, 279, 314, 95, 106, 0x0, STR_NULL}, +{ WWT_PANEL, RESIZE_NONE, 12, 196, 241, 95, 106, 0x0, STR_NULL}, +{ WWT_TEXTBTN, RESIZE_NONE, 12, 242, 253, 95, 106, STR_0225, STR_NULL}, // Mapsize X +{ WWT_PANEL, RESIZE_NONE, 12, 269, 314, 95, 106, 0x0, STR_NULL}, { WWT_TEXTBTN, RESIZE_NONE, 12, 315, 326, 95, 106, STR_0225, STR_NULL}, // Mapsize Y { WWT_IMGBTN, RESIZE_NONE, 12, 216, 227, 113, 124, SPR_ARROW_DOWN, STR_029E_MOVE_THE_STARTING_DATE}, Index: src/saveload.cpp =================================================================== --- src/saveload.cpp (revision 10727) +++ src/saveload.cpp (working copy) @@ -1114,8 +1114,11 @@ CursorID cursor; }; -/* A maximum size of of 128K * 500 = 64.000KB savegames */ -STATIC_OLD_POOL(Savegame, byte, 17, 500, NULL, NULL) +/* + * A maximum size of of 128K * 500 * N = 64000 KiB savegames + * N = 1 for 2048*2048 or appropriately more for larger sizes + */ +STATIC_OLD_POOL(Savegame, byte, 17, 500 * (MAX_MAP_TILES / 2048) / 2048, NULL, NULL) static ThreadedSave _ts; static bool InitMem() Index: src/map.h =================================================================== --- src/map.h (revision 10727) +++ src/map.h (working copy) @@ -8,6 +8,13 @@ #include "stdafx.h" #include "direction.h" +/** Minimal size of map. Must be power of two. */ +#define MIN_MAP_SIZE 64 +/** Maximal size of map. Must be power of two. */ +#define MAX_MAP_SIZE (256 * 1024) +/** Maximal number of tiles in a map */ +#define MAX_MAP_TILES (4096 * 4096) + extern uint _map_tile_mask; /** Index: src/map.cpp =================================================================== --- src/map.cpp (revision 10727) +++ src/map.cpp (working copy) @@ -35,8 +35,9 @@ { /* Make sure that the map size is within the limits and that * the x axis size is a power of 2. */ - if (size_x < 64 || size_x > 2048 || - size_y < 64 || size_y > 2048 || + if (size_x < MIN_MAP_SIZE || size_x > MAX_MAP_SIZE || + size_x * size_y > MAX_MAP_TILES || + size_y < MIN_MAP_SIZE || size_y > MAX_MAP_SIZE || (size_x & (size_x - 1)) != 0 || (size_y & (size_y - 1)) != 0) error("Invalid map size"); Index: src/openttd.cpp =================================================================== --- src/openttd.cpp (revision 10727) +++ src/openttd.cpp (working copy) @@ -750,7 +750,21 @@ ResetGRFConfig(true); GenerateWorldSetCallback(&MakeNewEditorWorldDone); - GenerateWorld(GW_EMPTY, 1 << _patches.map_x, 1 << _patches.map_y); + + /** + * Too large size may be stored in config. + * Check the size and fall back to minimal size if the size is invalid + */ + uint64 map_x = 1U << _patches.map_x; + uint64 map_y = 1U << _patches.map_y; + uint64 tiles = map_x * map_y; + + if (tiles > MAX_MAP_TILES) { + map_x = MIN_MAP_SIZE; + map_y = MIN_MAP_SIZE; + } + + GenerateWorld(GW_EMPTY, map_x, map_y); } void StartupPlayers();