From 020c1e9b6c228ee812ed85ecc02dc52847940821 Mon Sep 17 00:00:00 2001 From: truelight Date: Sun, 6 Feb 2005 10:24:57 +0000 Subject: [PATCH] (svn r1818) -Add: Dynamic orders (up to 64k orders) --- oldloader.c | 3 +++ order.h | 28 +++++++++++++++++++++------ order_cmd.c | 52 ++++++++++++++++++++++++++++++++++++++++----------- order_gui.c | 9 --------- saveload.c | 8 ++++++-- station_cmd.c | 2 +- ttd.c | 3 +-- 7 files changed, 74 insertions(+), 31 deletions(-) diff --git a/oldloader.c b/oldloader.c index 08165476f0..b46fd3c905 100644 --- a/oldloader.c +++ b/oldloader.c @@ -803,6 +803,9 @@ static void FixOrder(uint16 *o, int num) int i; for (i = 0; i < num; ++i) { + if (!AddBlockIfNeeded(&_order_pool, i)) + error("Orders: failed loading savegame: too many orders"); + order = GetOrder(i); AssignOrder(order, UnpackOldOrder(*o)); /* Recover the next list */ diff --git a/order.h b/order.h index 430e3bb8bf..840e1ec22e 100644 --- a/order.h +++ b/order.h @@ -1,6 +1,8 @@ #ifndef ORDER_H #define ORDER_H +#include "pool.h" + /* Order types */ enum { OT_NOTHING = 0, @@ -64,17 +66,27 @@ typedef struct { VARDEF TileIndex _backup_orders_tile; VARDEF BackuppedOrders _backup_orders_data[1]; -VARDEF Order _orders[5000]; -VARDEF uint32 _orders_size; +extern MemoryPool _order_pool; +/** + * Get the pointer to the order with index 'index' + */ static inline Order *GetOrder(uint index) { - assert(index < _orders_size); - return &_orders[index]; + return (Order*)GetItemFromPool(&_order_pool, index); } -#define FOR_ALL_ORDERS_FROM(o, from) for(o = GetOrder(from); o != &_orders[_orders_size]; o++) -#define FOR_ALL_ORDERS(o) FOR_ALL_ORDERS_FROM(o, 0) +/** + * Get the current size of the OrderPool + */ +static inline uint16 GetOrderPoolSize(void) +{ + return _order_pool.total_items; +} + +#define FOR_ALL_ORDERS_FROM(order, start) for (order = GetOrder(start); order != NULL; order = (order->index + 1 < GetOrderPoolSize()) ? GetOrder(order->index + 1) : NULL) +#define FOR_ALL_ORDERS(order) FOR_ALL_ORDERS_FROM(order, 0) + #define FOR_VEHICLE_ORDERS(v, order) for (order = v->orders; order != NULL; order = order->next) @@ -82,6 +94,10 @@ static inline bool HasOrderPoolFree(uint amount) { const Order *order; + /* There is always room if not all blocks in the pool are reserved */ + if (_order_pool.current_blocks < _order_pool.max_blocks) + return true; + FOR_ALL_ORDERS(order) if (order->type == OT_NOTHING) if (--amount == 0) diff --git a/order_cmd.c b/order_cmd.c index 71ab2c0689..d28f3a6fff 100644 --- a/order_cmd.c +++ b/order_cmd.c @@ -8,6 +8,26 @@ #include "news.h" #include "saveload.h" +enum { + /* Max orders: 64000 (64 * 1000) */ + ORDER_POOL_BLOCK_SIZE_BITS = 6, /* In bits, so (1 << 6) == 64 */ + ORDER_POOL_MAX_BLOCKS = 1000, +}; + +/** + * Called if a new block is added to the order-pool + */ +static void OrderPoolNewBlock(uint start_item) +{ + Order *order; + + FOR_ALL_ORDERS_FROM(order, start_item) + order->index = start_item++; +} + +/* Initialize the order-pool */ +MemoryPool _order_pool = { "Orders", ORDER_POOL_MAX_BLOCKS, ORDER_POOL_BLOCK_SIZE_BITS, sizeof(Order), &OrderPoolNewBlock, 0, 0, NULL }; + /** * * Unpacks a order from savegames made with TTD(Patch) @@ -87,13 +107,19 @@ static Order *AllocateOrder(void) FOR_ALL_ORDERS(order) { if (order->type == OT_NOTHING) { uint index = order->index; + memset(order, 0, sizeof(Order)); order->index = index; order->next = NULL; + return order; } } + /* Check if we can add a block to the pool */ + if (AddBlockToPool(&_order_pool)) + return AllocateOrder(); + return NULL; } @@ -906,14 +932,8 @@ bool CheckForValidOrders(Vehicle *v) void InitializeOrders(void) { - Order *order; - int i; - - memset(&_orders, 0, sizeof(_orders[0]) * _orders_size); - - i = 0; - FOR_ALL_ORDERS(order) - order->index = i++; + CleanPool(&_order_pool); + AddBlockToPool(&_order_pool); _backup_orders_tile = 0; } @@ -955,22 +975,28 @@ static void Load_ORDR(void) uint16 orders[5000]; len /= sizeof(uint16); - assert (len <= _orders_size); + assert (len <= lengthof(orders)); SlArray(orders, len, SLE_UINT16); for (i = 0; i < len; ++i) { + if (!AddBlockIfNeeded(&_order_pool, i)) + error("Orders: failed loading savegame: too many orders"); + AssignOrder(GetOrder(i), UnpackVersion4Order(orders[i])); } } else if (_sl.full_version <= 0x501) { uint32 orders[5000]; len /= sizeof(uint32); - assert (len <= _orders_size); + assert (len <= lengthof(orders)); SlArray(orders, len, SLE_UINT32); for (i = 0; i < len; ++i) { + if (!AddBlockIfNeeded(&_order_pool, i)) + error("Orders: failed loading savegame: too many orders"); + AssignOrder(GetOrder(i), UnpackOrder(orders[i])); } } @@ -987,8 +1013,12 @@ static void Load_ORDR(void) int index; while ((index = SlIterateArray()) != -1) { - Order *order = GetOrder(index); + Order *order; + if (!AddBlockIfNeeded(&_order_pool, index)) + error("Orders: failed loading savegame: too many orders"); + + order = GetOrder(index); SlObject(order, _order_desc); } } diff --git a/order_gui.c b/order_gui.c index 7cbd0089c8..298b2ba674 100644 --- a/order_gui.c +++ b/order_gui.c @@ -167,15 +167,6 @@ static void *FindVehicleCallb(Vehicle *v, FindVehS *f) return v; } -static Vehicle *GetVehicleOnTile(TileIndex tile, byte owner) -{ - FindVehS fs; - fs.tile = tile; - fs.owner = owner; - fs.type = 0; - return VehicleFromPos(tile, &fs, (VehicleFromPosProc*)FindVehicleCallb); -} - static Order GetOrderCmdFromTile(Vehicle *v, uint tile) { Order order; diff --git a/saveload.c b/saveload.c index d5fabd7cc1..f4902c5f4c 100644 --- a/saveload.c +++ b/saveload.c @@ -941,7 +941,11 @@ static void *IntToReference(uint r, uint t) return NULL; switch (t) { - case REF_ORDER: return GetOrder(r - 1); + case REF_ORDER: { + if (!AddBlockIfNeeded(&_order_pool, r - 1)) + error("Orders: failed loading savegame: too many orders"); + return GetOrder(r - 1); + } case REF_VEHICLE: { if (!AddBlockIfNeeded(&_vehicle_pool, r - 1)) error("Vehicles: failed loading savegame: too many vehicles"); @@ -959,7 +963,7 @@ static void *IntToReference(uint r, uint t) } case REF_ROADSTOPS: { if (!AddBlockIfNeeded(&_roadstop_pool, r - 1)) - error("RoadStop: failed loading savegame: too many RoadStops"); + error("RoadStops: failed loading savegame: too many RoadStops"); return GetRoadStop(r - 1); } diff --git a/station_cmd.c b/station_cmd.c index 61c09e2c02..67457728df 100644 --- a/station_cmd.c +++ b/station_cmd.c @@ -3138,7 +3138,7 @@ static void Load_ROADSTOP( void ) RoadStop *rs; if (!AddBlockIfNeeded(&_roadstop_pool, index)) - error("RoadStop: failed loading savegame: too many RoadStops"); + error("RoadStops: failed loading savegame: too many RoadStops"); rs = GetRoadStop(index); SlObject(rs, _roadstop_desc); diff --git a/ttd.c b/ttd.c index 83c3e58cb0..f4d98a5b11 100644 --- a/ttd.c +++ b/ttd.c @@ -440,8 +440,6 @@ static void ParseResolution(int res[2], char *s) static void InitializeDynamicVariables(void) { /* Dynamic stuff needs to be initialized somewhere... */ - _orders_size = lengthof(_orders); - _station_sort = NULL; _vehicle_sort = NULL; _town_sort = NULL; @@ -456,6 +454,7 @@ static void UnInitializeDynamicVariables(void) CleanPool(&_station_pool); CleanPool(&_vehicle_pool); CleanPool(&_sign_pool); + CleanPool(&_order_pool); free(_station_sort); free(_vehicle_sort);