From 7368c740a646c958797b5dff90d6c5b51236e2a4 Mon Sep 17 00:00:00 2001 From: smatz Date: Sun, 4 Jan 2009 15:32:25 +0000 Subject: (svn r14828) -Codechange: move most of save/load-specific code to separate files --- src/saveload/order_sl.cpp | 203 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 src/saveload/order_sl.cpp (limited to 'src/saveload/order_sl.cpp') diff --git a/src/saveload/order_sl.cpp b/src/saveload/order_sl.cpp new file mode 100644 index 000000000..ef11056ed --- /dev/null +++ b/src/saveload/order_sl.cpp @@ -0,0 +1,203 @@ +/* $Id$ */ + +/** @file order_sl.cpp Code handling saving and loading of orders */ + +#include "../stdafx.h" +#include "../order_base.h" +#include "../core/alloc_func.hpp" +#include "../settings_type.h" + +#include "saveload.h" + +void Order::ConvertFromOldSavegame() +{ + uint8 old_flags = this->flags; + this->flags = 0; + + /* First handle non-stop */ + if (_settings_client.gui.sg_new_nonstop) { + /* OFB_NON_STOP */ + this->SetNonStopType((old_flags & 8) ? ONSF_NO_STOP_AT_ANY_STATION : ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS); + } else { + this->SetNonStopType((old_flags & 8) ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE); + } + + switch (this->GetType()) { + /* Only a few types need the other savegame conversions. */ + case OT_GOTO_DEPOT: case OT_GOTO_STATION: case OT_LOADING: break; + default: return; + } + + if (this->GetType() != OT_GOTO_DEPOT) { + /* Then the load flags */ + if ((old_flags & 2) != 0) { // OFB_UNLOAD + this->SetLoadType(OLFB_NO_LOAD); + } else if ((old_flags & 4) == 0) { // !OFB_FULL_LOAD + this->SetLoadType(OLF_LOAD_IF_POSSIBLE); + } else { + this->SetLoadType(_settings_client.gui.sg_full_load_any ? OLF_FULL_LOAD_ANY : OLFB_FULL_LOAD); + } + + /* Finally fix the unload flags */ + if ((old_flags & 1) != 0) { // OFB_TRANSFER + this->SetUnloadType(OUFB_TRANSFER); + } else if ((old_flags & 2) != 0) { // OFB_UNLOAD + this->SetUnloadType(OUFB_UNLOAD); + } else { + this->SetUnloadType(OUF_UNLOAD_IF_POSSIBLE); + } + } else { + /* Then the depot action flags */ + this->SetDepotActionType(((old_flags & 6) == 4) ? ODATFB_HALT : ODATF_SERVICE_ONLY); + + /* Finally fix the depot type flags */ + uint t = ((old_flags & 6) == 6) ? ODTFB_SERVICE : ODTF_MANUAL; + if ((old_flags & 2) != 0) t |= ODTFB_PART_OF_ORDERS; + this->SetDepotOrderType((OrderDepotTypeFlags)t); + } +} + +/** Unpacks a order from savegames with version 4 and lower + * @param packed packed order + * @return unpacked order + */ +static Order UnpackVersion4Order(uint16 packed) +{ + return Order(GB(packed, 8, 8) << 16 | GB(packed, 4, 4) << 8 | GB(packed, 0, 4)); +} + +/** Unpacks a order from savegames made with TTD(Patch) + * @param packed packed order + * @return unpacked order + */ +Order UnpackOldOrder(uint16 packed) +{ + Order order = UnpackVersion4Order(packed); + + /* + * Sanity check + * TTD stores invalid orders as OT_NOTHING with non-zero flags/station + */ + if (!order.IsValid() && packed != 0) order.MakeDummy(); + + return order; +} + +const SaveLoad *GetOrderDescription() +{ + static const SaveLoad _order_desc[] = { + SLE_VAR(Order, type, SLE_UINT8), + SLE_VAR(Order, flags, SLE_UINT8), + SLE_VAR(Order, dest, SLE_UINT16), + SLE_REF(Order, next, REF_ORDER), + SLE_CONDVAR(Order, refit_cargo, SLE_UINT8, 36, SL_MAX_VERSION), + SLE_CONDVAR(Order, refit_subtype, SLE_UINT8, 36, SL_MAX_VERSION), + SLE_CONDVAR(Order, wait_time, SLE_UINT16, 67, SL_MAX_VERSION), + SLE_CONDVAR(Order, travel_time, SLE_UINT16, 67, SL_MAX_VERSION), + + /* Leftover from the minor savegame version stuff + * We will never use those free bytes, but we have to keep this line to allow loading of old savegames */ + SLE_CONDNULL(10, 5, 35), + SLE_END() + }; + + return _order_desc; +} + +static void Save_ORDR() +{ + Order *order; + + FOR_ALL_ORDERS(order) { + SlSetArrayIndex(order->index); + SlObject(order, GetOrderDescription()); + } +} + +static void Load_ORDR() +{ + if (CheckSavegameVersionOldStyle(5, 2)) { + /* Version older than 5.2 did not have a ->next pointer. Convert them + (in the old days, the orderlist was 5000 items big) */ + size_t len = SlGetFieldLength(); + uint i; + + if (CheckSavegameVersion(5)) { + /* Pre-version 5 had an other layout for orders + (uint16 instead of uint32) */ + len /= sizeof(uint16); + uint16 *orders = MallocT(len + 1); + + SlArray(orders, len, SLE_UINT16); + + for (i = 0; i < len; ++i) { + Order *order = new (i) Order(); + order->AssignOrder(UnpackVersion4Order(orders[i])); + } + + free(orders); + } else if (CheckSavegameVersionOldStyle(5, 2)) { + len /= sizeof(uint16); + uint16 *orders = MallocT(len + 1); + + SlArray(orders, len, SLE_UINT32); + + for (i = 0; i < len; ++i) { + new (i) Order(orders[i]); + } + + free(orders); + } + + /* Update all the next pointer */ + for (i = 1; i < len; ++i) { + /* The orders were built like this: + * While the order is valid, set the previous will get it's next pointer set + * We start with index 1 because no order will have the first in it's next pointer */ + if (GetOrder(i)->IsValid()) + GetOrder(i - 1)->next = GetOrder(i); + } + } else { + int index; + + while ((index = SlIterateArray()) != -1) { + Order *order = new (index) Order(); + SlObject(order, GetOrderDescription()); + } + } +} + +const SaveLoad *GetOrderListDescription() +{ + static const SaveLoad _orderlist_desc[] = { + SLE_REF(OrderList, first, REF_ORDER), + SLE_END() + }; + + return _orderlist_desc; +} + +static void Save_ORDL() +{ + OrderList *list; + + FOR_ALL_ORDER_LISTS(list) { + SlSetArrayIndex(list->index); + SlObject(list, GetOrderListDescription()); + } +} + +static void Load_ORDL() +{ + int index; + + while ((index = SlIterateArray()) != -1) { + OrderList *list = new (index) OrderList(); + SlObject(list, GetOrderListDescription()); + } +} + +extern const ChunkHandler _order_chunk_handlers[] = { + { 'ORDR', Save_ORDR, Load_ORDR, CH_ARRAY}, + { 'ORDL', Save_ORDL, Load_ORDL, CH_ARRAY | CH_LAST}, +}; -- cgit v1.2.3-70-g09d2