diff --git a/src/disaster_cmd.cpp b/src/disaster_cmd.cpp index 98cfe86928..8fa0cd8df1 100644 --- a/src/disaster_cmd.cpp +++ b/src/disaster_cmd.cpp @@ -566,6 +566,12 @@ static void DisasterTick_Big_Ufo(Vehicle *v) return; } + if (!IsValidTile(v->dest_tile)) { + /* Make sure we don't land outside the map. */ + delete v; + return; + } + z = GetSlopeZ(v->x_pos, v->y_pos); if (z < v->z_pos) { SetDisasterVehiclePos(v, v->x_pos, v->y_pos, v->z_pos - 1); @@ -885,7 +891,7 @@ static void Disaster_Submarine_Init(DisasterSubType subtype) int x = TileX(r) * TILE_SIZE + TILE_SIZE / 2; if (HasBit(r, 31)) { - y = MapMaxX() * TILE_SIZE - TILE_SIZE / 2 - 1; + y = MapMaxY() * TILE_SIZE - TILE_SIZE / 2 - 1; dir = DIR_NW; } else { y = TILE_SIZE / 2; diff --git a/src/fileio.cpp b/src/fileio.cpp index 98d58b2fb7..79d2283f64 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -829,7 +829,7 @@ void ChangeWorkingDirectory(const char *exe) void DetermineBasePaths(const char *exe) { char tmp[MAX_PATH]; -#if defined(__MORPHOS__) || defined(__AMIGA__) || defined(DOS) || !defined(WITH_PERSONAL_DIR) +#if defined(__MORPHOS__) || defined(__AMIGA__) || defined(DOS) || defined(OS2) || !defined(WITH_PERSONAL_DIR) _searchpaths[SP_PERSONAL_DIR] = NULL; #else const char *homedir = getenv("HOME"); @@ -867,7 +867,7 @@ void DetermineBasePaths(const char *exe) AppendPathSeparator(tmp, MAX_PATH); _searchpaths[SP_BINARY_DIR] = strdup(tmp); -#if defined(__MORPHOS__) || defined(__AMIGA__) || defined(DOS) +#if defined(__MORPHOS__) || defined(__AMIGA__) || defined(DOS) || defined(OS2) _searchpaths[SP_INSTALLATION_DIR] = NULL; #else snprintf(tmp, MAX_PATH, "%s", GLOBAL_DATA_DIR); diff --git a/src/gfx.cpp b/src/gfx.cpp index 4423bff190..aeac0db1d0 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -1285,6 +1285,9 @@ void ScreenSizeChanged() void UndrawMouseCursor() { + /* Don't undraw the mouse cursor if the screen is not ready */ + if (_screen.dst_ptr == NULL) return; + if (_cursor.visible) { Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter(); _cursor.visible = false; @@ -1300,6 +1303,9 @@ void DrawMouseCursor() return; #endif + /* Don't draw the mouse cursor if the screen is not ready */ + if (_screen.dst_ptr == NULL) return; + Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter(); int x; int y; diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 2ccffe8ce3..1eaf4617d2 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -1361,11 +1361,11 @@ static const Widget _save_dialog_widgets[] = { { WWT_PUSHTXTBTN, RESIZE_NONE, COLOUR_GREY, 0, 127, 14, 25, STR_SORT_BY_NAME, STR_SORT_ORDER_TIP}, { WWT_PUSHTXTBTN, RESIZE_NONE, COLOUR_GREY, 128, 256, 14, 25, STR_SORT_BY_DATE, STR_SORT_ORDER_TIP}, { WWT_PANEL, RESIZE_RIGHT, COLOUR_GREY, 0, 256, 26, 47, 0x0, STR_NULL}, -{ WWT_PANEL, RESIZE_RB, COLOUR_GREY, 0, 256, 48, 151, 0x0, STR_NULL}, +{ WWT_PANEL, RESIZE_RB, COLOUR_GREY, 0, 256, 48, 167, 0x0, STR_NULL}, { WWT_PUSHIMGBTN, RESIZE_LR, COLOUR_GREY, 245, 256, 48, 59, SPR_HOUSE_ICON, STR_SAVELOAD_HOME_BUTTON}, { WWT_INSET, RESIZE_RB, COLOUR_GREY, 2, 243, 50, 150, 0x0, STR_400A_LIST_OF_DRIVES_DIRECTORIES}, { WWT_SCROLLBAR, RESIZE_LRB, COLOUR_GREY, 245, 256, 60, 151, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, -{ WWT_PANEL, RESIZE_RTB, COLOUR_GREY, 0, 256, 152, 167, 0x0, STR_NULL}, +{ WWT_PANEL, RESIZE_RTB, COLOUR_GREY, 0, 256, 152, 0, 0x0, STR_NULL}, { WWT_EDITBOX, RESIZE_RTB, COLOUR_GREY, 2, 254, 154, 165, STR_SAVE_OSKTITLE, STR_400B_CURRENTLY_SELECTED_NAME}, { WWT_PUSHTXTBTN, RESIZE_TB, COLOUR_GREY, 0, 127, 168, 179, STR_4003_DELETE, STR_400C_DELETE_THE_CURRENTLY_SELECTED}, { WWT_PUSHTXTBTN, RESIZE_TB, COLOUR_GREY, 128, 244, 168, 179, STR_4002_SAVE, STR_400D_SAVE_THE_CURRENT_GAME_USING}, diff --git a/src/newgrf_house.cpp b/src/newgrf_house.cpp index e5897c92c8..816ea513b9 100644 --- a/src/newgrf_house.cpp +++ b/src/newgrf_house.cpp @@ -22,7 +22,7 @@ #include "animated_tile_func.h" #include "company_base.h" -static BuildingCounts _building_counts; +static BuildingCounts _building_counts; static HouseClassMapping _class_mapping[HOUSE_CLASS_MAX]; HouseOverrideManager _house_mngr(NEW_HOUSE_OFFSET, HOUSE_MAX, INVALID_HOUSE_ID); @@ -61,20 +61,13 @@ void IncreaseBuildingCount(Town *t, HouseID house_id) if (!_loaded_newgrf_features.has_newhouses) return; - /* If there are 255 buildings of this type in this town, there are also - * at least that many houses of the same class in the town, and - * therefore on the map as well. */ - if (t->building_counts.id_count[house_id] == 255) return; - t->building_counts.id_count[house_id]++; - if (_building_counts.id_count[house_id] < 255) _building_counts.id_count[house_id]++; + _building_counts.id_count[house_id]++; - /* Similarly, if there are 255 houses of this class in this town, there - * must be at least that number on the map too. */ - if (class_id == HOUSE_NO_CLASS || t->building_counts.class_count[class_id] == 255) return; + if (class_id == HOUSE_NO_CLASS) return; t->building_counts.class_count[class_id]++; - if (_building_counts.class_count[class_id] < 255) _building_counts.class_count[class_id]++; + _building_counts.class_count[class_id]++; } /** @@ -121,10 +114,10 @@ static uint32 GetNumHouses(HouseID house_id, const Town *town) uint8 map_id_count, town_id_count, map_class_count, town_class_count; HouseClassID class_id = GetHouseSpecs(house_id)->class_id; - map_id_count = _building_counts.id_count[house_id]; - map_class_count = _building_counts.class_count[class_id]; - town_id_count = town->building_counts.id_count[house_id]; - town_class_count = town->building_counts.class_count[class_id]; + map_id_count = ClampU(_building_counts.id_count[house_id], 0, 255); + map_class_count = ClampU(_building_counts.class_count[class_id], 0, 255); + town_id_count = ClampU(town->building_counts.id_count[house_id], 0, 255); + town_class_count = ClampU(town->building_counts.class_count[class_id], 0, 255); return map_class_count << 24 | town_class_count << 16 | map_id_count << 8 | town_id_count; } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 77ca29f548..2d97c2fd28 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1632,6 +1632,8 @@ CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, ui ((GetRoadStopDir(tile) == DIAGDIR_NE) ? ROAD_X : ROAD_Y) : DiagDirToRoadBits(GetRoadStopDir(tile)); + Owner road_owner = GetRoadOwner(tile, ROADTYPE_ROAD); + Owner tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM); CommandCost ret = RemoveRoadStop(st, flags, tile); /* If the stop was a drive-through stop replace the road */ @@ -1640,7 +1642,7 @@ CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, ui * removed by the owner of the roadstop, _current_company is the * owner of the road stop. */ MakeRoadNormal(tile, road_bits, rts, ClosestTownFromTile(tile, UINT_MAX)->index, - GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM)); + road_owner, tram_owner); } return ret; diff --git a/src/thread_os2.cpp b/src/thread_os2.cpp index 9d05f7e022..9d494af397 100644 --- a/src/thread_os2.cpp +++ b/src/thread_os2.cpp @@ -1,66 +1,116 @@ /* $Id$ */ -/** @file thread_os2.cpp OS2 implementation of Threads. */ +/** @file thread_os2.cpp OS/2 implementation of Threads. */ #include "stdafx.h" #include "thread.h" -#if 0 -#include "debug.h" -#include "core/alloc_func.hpp" -#include - #define INCL_DOS #include #include -struct OTTDThread { - TID thread; - OTTDThreadFunc func; - void *arg; - void *ret; +/** + * OS/2 version for ThreadObject. + */ +class ThreadObject_OS2 : public ThreadObject { +private: + TID thread; ///< System thread identifier. + OTTDThreadFunc proc; ///< External thread procedure. + void *param; ///< Parameter for the external thread procedure. + bool self_destruct; ///< Free ourselves when done? + +public: + /** + * Create a thread and start it, calling proc(param). + */ + ThreadObject_OS2(OTTDThreadFunc proc, void *param, bool self_destruct) : + thread(0), + proc(proc), + param(param), + self_destruct(self_destruct) + { + thread = _beginthread(stThreadProc, NULL, 32768, this); + } + + /* virtual */ bool Exit() + { + _endthread(); + return true; + } + + /* virtual */ void Join() + { + DosWaitThread(&this->thread, DCWW_WAIT); + this->thread = 0; + } +private: + /** + * On thread creation, this function is called, which calls the real startup + * function. This to get back into the correct instance again. + */ + static void stThreadProc(void *thr) + { + ((ThreadObject_OS2 *)thr)->ThreadProc(); + } + + /** + * A new thread is created, and this function is called. Call the custom + * function of the creator of the thread. + */ + void ThreadProc() + { + /* Call the proc of the creator to continue this thread */ + try { + this->proc(this->param); + } catch (OTTDThreadExitSignal e) { + } catch (...) { + NOT_REACHED(); + } + + if (self_destruct) { + this->Exit(); + delete this; + } + } }; -static void Proxy(void *arg) +/* static */ bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread) { - OTTDThread *t = (OTTDThread *)arg; - t->ret = t->func(t->arg); + ThreadObject *to = new ThreadObject_OS2(proc, param, thread == NULL); + if (thread != NULL) *thread = to; + return true; } -OTTDThread *OTTDCreateThread(OTTDThreadFunc function, void *arg) -{ - OTTDThread *t = MallocT(1); +/** + * OS/2 version of ThreadMutex. + */ +class ThreadMutex_OS2 : public ThreadMutex { +private: + HMTX mutex; - t->func = function; - t->arg = arg; - t->thread = _beginthread(Proxy, NULL, 32768, t); - if (t->thread != (TID)-1) { - return t; - } else { - free(t); - return NULL; +public: + ThreadMutex_OS2() + { + DosCreateMutexSem(NULL, &mutex, 0, FALSE); } -} -void *OTTDJoinThread(OTTDThread *t) + /* virtual */ ~ThreadMutex_OS2() + { + DosCloseMutexSem(mutex); + } + + /* virtual */ void BeginCritical() + { + DosRequestMutexSem(mutex, (unsigned long) SEM_INDEFINITE_WAIT); + } + + /* virtual */ void EndCritical() + { + DosReleaseMutexSem(mutex); + } +}; + +/* static */ ThreadMutex *ThreadMutex::New() { - if (t == NULL) return NULL; - - DosWaitThread(&t->thread, DCWW_WAIT); - void *ret = t->ret; - free(t); - return ret; -} - -void OTTDExitThread() -{ - _endthread(); -} - -#endif - -/* static */ ThreadObject *ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread) -{ - if (thread != NULL) *thread = NULL; - return false; + return new ThreadMutex_OS2(); } diff --git a/src/town.h b/src/town.h index 9f7b3e7104..9c87b1c447 100644 --- a/src/town.h +++ b/src/town.h @@ -90,9 +90,10 @@ enum HouseExtraFlags { DECLARE_ENUM_AS_BIT_SET(HouseExtraFlags) +template struct BuildingCounts { - uint8 id_count[HOUSE_MAX]; - uint8 class_count[HOUSE_CLASS_MAX]; + T id_count[HOUSE_MAX]; + T class_count[HOUSE_CLASS_MAX]; }; static const uint CUSTOM_TOWN_NUMBER_DIFFICULTY = 4; ///< value for custom town number in difficulty settings @@ -176,7 +177,7 @@ struct Town : PoolItem { uint32 squared_town_zone_radius[HZB_END]; /* NOSAVE: The number of each type of building in the town. */ - BuildingCounts building_counts; + BuildingCounts building_counts; /** * Creates a new town diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index d84f405979..3ae9dc8ba1 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -1636,19 +1636,18 @@ bool GenerateTowns(TownLayout layout) uint num = 0; uint difficulty = _settings_game.difficulty.number_towns; uint n = (difficulty == (uint)CUSTOM_TOWN_NUMBER_DIFFICULTY) ? _settings_game.game_creation.custom_town_number : ScaleByMapSize(_num_initial_towns[difficulty] + (Random() & 7)); - uint num_cities = _settings_game.economy.larger_towns == 0 ? 0 : n / _settings_game.economy.larger_towns; SetGeneratingWorldProgress(GWP_TOWN, n); do { + bool city = (_settings_game.economy.larger_towns != 0 && Chance16(1, _settings_game.economy.larger_towns)); IncreaseGeneratingWorldProgress(GWP_TOWN); /* try 20 times to create a random-sized town for the first loop. */ - if (CreateRandomTown(20, TS_RANDOM, num_cities > 0, layout) != NULL) num++; - if (num_cities > 0) num_cities--; + if (CreateRandomTown(20, TS_RANDOM, city, layout) != NULL) num++; } while (--n); /* give it a last try, but now more aggressive */ - if (num == 0 && CreateRandomTown(10000, TS_RANDOM, false, layout) == NULL) { + if (num == 0 && CreateRandomTown(10000, TS_RANDOM, _settings_game.economy.larger_towns != 0, layout) == NULL) { if (GetNumTowns() == 0) { if (_game_mode != GM_EDITOR) { extern StringID _switch_mode_errorstr;