1
0
Fork 0

(svn r15764) [0.7] -Backport from trunk:

- Fix: Number of houses in house variables 0x44, 0x60 and 0x61 were incorrect after 0xFF had been reached and could desync clients joining afterwards (r15755)
- Fix: Crash when clicking the small area between the savegame list and the save button in the save game window [FS#2742] (r15753)
- Fix: Do not try to (un)draw the cursor when the screen is not ready (r15752)
- Fix: The big UFO sometimes landed just outside the map. Instead of landing, just disappear (fly away) in those cases (r15750)
- Fix: Crash because submarines would sometimes start far outside of the map [FS#2739] (r15748)
- Fix: Road ownership getting lost when removing a road stop [FS#2736] (r15747)
- Fix: Update threading code for OS/2, add mutex support, fix compilation (r15746, r15745)
- Fix: When town generator failed to create requested number of towns, there were too many cities (r15744)
release/0.7
rubidium 2009-03-18 19:47:05 +00:00
parent de7a4a4006
commit 9e592b9986
9 changed files with 131 additions and 74 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -22,7 +22,7 @@
#include "animated_tile_func.h"
#include "company_base.h"
static BuildingCounts _building_counts;
static BuildingCounts<uint32> _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;
}

View File

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

View File

@ -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 <stdlib.h>
#define INCL_DOS
#include <os2.h>
#include <process.h>
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<OTTDThread>(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();
}

View File

@ -90,9 +90,10 @@ enum HouseExtraFlags {
DECLARE_ENUM_AS_BIT_SET(HouseExtraFlags)
template <typename T>
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<Town, TownID, &_Town_pool> {
uint32 squared_town_zone_radius[HZB_END];
/* NOSAVE: The number of each type of building in the town. */
BuildingCounts building_counts;
BuildingCounts<uint16> building_counts;
/**
* Creates a new town

View File

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