summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortruelight <truelight@openttd.org>2005-02-03 17:22:35 +0000
committertruelight <truelight@openttd.org>2005-02-03 17:22:35 +0000
commit3eda5e61f7d078e64581afea2859062fb1622617 (patch)
treebe17b2ce20037210425d4757c66ffc50cccc6d77
parentaa299a8b6dc3510da51355e7765b3d202fd0ccac (diff)
downloadopenttd-3eda5e61f7d078e64581afea2859062fb1622617.tar.xz
(svn r1776) -Add: Dynamic stations. You can now have up to 64k of stations
-rw-r--r--oldloader.c3
-rw-r--r--saveload.c6
-rw-r--r--station.h22
-rw-r--r--station_cmd.c74
-rw-r--r--station_gui.c4
-rw-r--r--ttd.c2
6 files changed, 72 insertions, 39 deletions
diff --git a/oldloader.c b/oldloader.c
index 6de0c483e..4ad72a72f 100644
--- a/oldloader.c
+++ b/oldloader.c
@@ -713,6 +713,9 @@ static void FixStation(OldStation *o, int num)
if (o->xy == 0)
continue;
+ if (!AddBlockIfNeeded(&_station_pool, i))
+ error("Stations: failed loading savegame: too many stations");
+
s = GetStation(i);
s->xy = o->xy;
diff --git a/saveload.c b/saveload.c
index 8db82bf2c..174d65703 100644
--- a/saveload.c
+++ b/saveload.c
@@ -943,7 +943,11 @@ static void *IntToReference(uint r, uint t)
switch (t) {
case REF_ORDER: return GetOrder(r - 1);
case REF_VEHICLE: return GetVehicle(r - 1);
- case REF_STATION: return GetStation(r - 1);
+ case REF_STATION: {
+ if (!AddBlockIfNeeded(&_station_pool, r - 1))
+ error("Stations: failed loading savegame: too many stations");
+ return GetStation(r - 1);
+ }
case REF_TOWN: {
if (!AddBlockIfNeeded(&_town_pool, r - 1))
error("Towns: failed loading savegame: too many towns");
diff --git a/station.h b/station.h
index 7202099c6..2334be6e2 100644
--- a/station.h
+++ b/station.h
@@ -1,6 +1,7 @@
#ifndef STATION_H
#define STATION_H
+#include "pool.h"
#include "sprite.h"
#include "tile.h"
#include "vehicle.h"
@@ -125,19 +126,30 @@ void ShowStationViewWindow(int station);
void UpdateAllStationVirtCoord(void);
VARDEF RoadStop _roadstops[NUM_ROAD_STOPS * 2];
-VARDEF Station _stations[250];
VARDEF uint _roadstops_size;
-VARDEF uint _stations_size;
VARDEF SortStruct *_station_sort;
+extern MemoryPool _station_pool;
+
+/**
+ * Get the pointer to the station with index 'index'
+ */
static inline Station *GetStation(uint index)
{
- assert(index < _stations_size);
- return &_stations[index];
+ return (Station*)GetItemFromPool(&_station_pool, index);
+}
+
+/**
+ * Get the current size of the StationPool
+ */
+static inline uint16 GetStationPoolSize(void)
+{
+ return _station_pool.total_items;
}
-#define FOR_ALL_STATIONS(st) for(st = _stations; st != &_stations[_stations_size]; st++)
+#define FOR_ALL_STATIONS_FROM(st, start) for (st = GetStation(start); st != NULL; st = (st->index + 1 < GetStationPoolSize()) ? GetStation(st->index + 1) : NULL)
+#define FOR_ALL_STATIONS(st) FOR_ALL_STATIONS_FROM(st, 0)
VARDEF bool _station_sort_dirty[MAX_PLAYERS];
VARDEF bool _global_station_sort_dirty;
diff --git a/station_cmd.c b/station_cmd.c
index cbce2014b..edcefccb4 100644
--- a/station_cmd.c
+++ b/station_cmd.c
@@ -18,6 +18,27 @@
#include "sprite.h"
#include "npf.h"
+enum {
+ /* Max stations: 64000 (64 * 1000) */
+ STATION_POOL_BLOCK_SIZE_BITS = 6, /* In bits, so (1 << 6) == 64 */
+ STATION_POOL_MAX_BLOCKS = 1000,
+};
+
+/**
+ * Called if a new block is added to the station-pool
+ */
+static void StationPoolNewBlock(uint start_item)
+{
+ Station *st;
+
+ FOR_ALL_STATIONS_FROM(st, start_item)
+ st->index = start_item++;
+}
+
+/* Initialize the station-pool */
+MemoryPool _station_pool = { "Stations", STATION_POOL_MAX_BLOCKS, STATION_POOL_BLOCK_SIZE_BITS, sizeof(Station), &StationPoolNewBlock, 0, 0, NULL };
+
+
// FIXME -- need to be embedded into Airport variable. Is dynamically
// deducteable from graphics-tile array, so will not be needed
const byte _airport_size_x[5] = {4, 6, 1, 6, 7 };
@@ -26,10 +47,6 @@ const byte _airport_size_y[5] = {3, 6, 1, 6, 7 };
void ShowAircraftDepotWindow(uint tile);
extern void UpdateAirplanesOnNewStation(Station *st);
-enum {
- STATIONS_MIN_FREE_FOR_AI = 30
-};
-
static void MarkStationDirty(Station *st)
{
if (st->sign.width_1 != 0) {
@@ -216,28 +233,25 @@ static bool CheckStationSpreadOut(Station *st, uint tile, int w, int h)
static Station *AllocateStation(void)
{
- Station *st, *a_free = NULL;
- int num_free = 0;
- int i;
+ Station *st = NULL;
FOR_ALL_STATIONS(st) {
if (st->xy == 0) {
- num_free++;
- if (a_free == NULL)
- a_free = st;
+ uint index = st->index;
+
+ memset(st, 0, sizeof(Station));
+ st->index = index;
+
+ return st;
}
}
- if (a_free == NULL ||
- (num_free < STATIONS_MIN_FREE_FOR_AI && IS_HUMAN_PLAYER(_current_player))) {
- _error_message = STR_3008_TOO_MANY_STATIONS_LOADING;
- return NULL;
- }
+ /* Check if we can add a block to the pool */
+ if (AddBlockToPool(&_station_pool))
+ return AllocateStation();
- i = a_free->index;
- memset(a_free, 0, sizeof(Station));
- a_free->index = i;
- return a_free;
+ _error_message = STR_3008_TOO_MANY_STATIONS_LOADING;
+ return NULL;
}
@@ -2552,14 +2566,14 @@ static void StationHandleSmallTick(Station *st)
void OnTick_Station(void)
{
- int i;
+ uint i;
Station *st;
if (_game_mode == GM_EDITOR)
return;
i = _station_tick_ctr;
- if (++_station_tick_ctr == _stations_size)
+ if (++_station_tick_ctr == GetStationPoolSize())
_station_tick_ctr = 0;
st = GetStation(i);
@@ -2890,15 +2904,11 @@ static int32 ClearTile_Station(uint tile, byte flags) {
void InitializeStations(void)
{
- int i;
- Station *s;
+ /* Clean the station pool and create 1 block in it */
+ CleanPool(&_station_pool);
+ AddBlockToPool(&_station_pool);
memset(_roadstops, 0, sizeof(_roadstops));
- memset(_stations, 0, sizeof(_stations[0]) * _stations_size);
-
- i = 0;
- FOR_ALL_STATIONS(s)
- s->index = i++;
_station_tick_ctr = 0;
@@ -3038,8 +3048,12 @@ static void Load_STNS(void)
{
int index;
while ((index = SlIterateArray()) != -1) {
- Station *st = GetStation(index);
+ Station *st;
+
+ if (!AddBlockIfNeeded(&_station_pool, index))
+ error("Stations: failed loading savegame: too many stations");
+ st = GetStation(index);
SaveLoad_STNS(st);
// this means it's an oldstyle savegame without support for nonuniform stations
@@ -3080,7 +3094,7 @@ static void Load_STNS(void)
/* This is to ensure all pointers are within the limits of
_stations_size */
- if (_station_tick_ctr > _stations_size)
+ if (_station_tick_ctr > GetStationPoolSize())
_station_tick_ctr = 0;
}
diff --git a/station_gui.c b/station_gui.c
index d7316d429..fe57f4dbe 100644
--- a/station_gui.c
+++ b/station_gui.c
@@ -84,7 +84,7 @@ static void GlobalSortStationList(void)
*i = 0;
/* Create array for sorting */
- _station_sort = realloc(_station_sort, _stations_size * sizeof(_station_sort[0]));
+ _station_sort = realloc(_station_sort, GetStationPoolSize() * sizeof(_station_sort[0]));
if (_station_sort == NULL)
error("Could not allocate memory for the station-sorting-list");
@@ -318,7 +318,7 @@ static void DrawStationViewWindow(Window *w)
byte *b;
- station_id = (byte)w->window_number;
+ station_id = (uint16)w->window_number;
st = GetStation(w->window_number);
diff --git a/ttd.c b/ttd.c
index abc59df83..342b84d5c 100644
--- a/ttd.c
+++ b/ttd.c
@@ -495,7 +495,6 @@ static void ParseResolution(int res[2], char *s)
static void InitializeDynamicVariables(void)
{
/* Dynamic stuff needs to be initialized somewhere... */
- _stations_size = lengthof(_stations);
_roadstops_size = lengthof(_roadstops);
_vehicles_size = lengthof(_vehicles);
_sign_size = lengthof(_sign_list);
@@ -512,6 +511,7 @@ static void UnInitializeDynamicVariables(void)
/* Dynamic stuff needs to be free'd somewhere... */
CleanPool(&_town_pool);
CleanPool(&_industry_pool);
+ CleanPool(&_station_pool);
free(_station_sort);
free(_vehicle_sort);