/** Cargo payment rates in pre 126 savegames */ static void Load_CAPR() { uint num_cargo = IsSavegameVersionBefore(55) ? 12 : NUM_CARGO; int vt = IsSavegameVersionBefore(65) ? SLE_FILE_I32 : SLE_FILE_I64; SlArray(NULL, num_cargo, vt | SLE_VAR_NULL); SlArray(NULL, num_cargo, SLE_FILE_U16 | SLE_VAR_NULL); }
/** Prices in pre 126 savegames */ static void Load_PRIC() { /* Old games store 49 base prices, very old games store them as int32 */ int vt = IsSavegameVersionBefore(65) ? SLE_FILE_I32 : SLE_FILE_I64; SlArray(NULL, 49, vt | SLE_VAR_NULL); SlArray(NULL, 49, SLE_FILE_U16 | SLE_VAR_NULL); }
/* static */ bool ScriptInstance::LoadObjects(HSQUIRRELVM vm) { SlObject(NULL, _script_byte); switch (_script_sl_byte) { case SQSL_INT: { int value; SlArray(&value, 1, SLE_INT32); if (vm != NULL) sq_pushinteger(vm, (SQInteger)value); return true; } case SQSL_STRING: { SlObject(NULL, _script_byte); static char buf[256]; SlArray(buf, _script_sl_byte, SLE_CHAR); if (vm != NULL) sq_pushstring(vm, OTTD2SQ(buf), -1); return true; } case SQSL_ARRAY: { if (vm != NULL) sq_newarray(vm, 0); while (LoadObjects(vm)) { if (vm != NULL) sq_arrayappend(vm, -2); /* The value is popped from the stack by squirrel. */ } return true; } case SQSL_TABLE: { if (vm != NULL) sq_newtable(vm); while (LoadObjects(vm)) { LoadObjects(vm); if (vm != NULL) sq_rawset(vm, -3); /* The key (-2) and value (-1) are popped from the stack by squirrel. */ } return true; } case SQSL_BOOL: { SlObject(NULL, _script_byte); if (vm != NULL) sq_pushinteger(vm, (SQBool)(_script_sl_byte != 0)); return true; } case SQSL_NULL: { if (vm != NULL) sq_pushnull(vm); return true; } case SQSL_ARRAY_TABLE_END: { return false; } default: NOT_REACHED(); } }
static void Load_ORDR() { if (IsSavegameVersionBefore(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(); if (IsSavegameVersionBefore(5)) { /* Pre-version 5 had another layout for orders * (uint16 instead of uint32) */ len /= sizeof(uint16); uint16 *orders = MallocT<uint16>(len + 1); SlArray(orders, len, SLE_UINT16); for (size_t i = 0; i < len; ++i) { Order *o = new (i) Order(); o->AssignOrder(UnpackVersion4Order(orders[i])); } free(orders); } else if (IsSavegameVersionBefore(5, 2)) { len /= sizeof(uint32); uint32 *orders = MallocT<uint32>(len + 1); SlArray(orders, len, SLE_UINT32); for (size_t i = 0; i < len; ++i) { new (i) Order(orders[i]); } free(orders); } /* Update all the next pointer */ Order *o; FOR_ALL_ORDERS(o) { /* Delete invalid orders */ if (o->IsType(OT_NOTHING)) { delete o; continue; } /* The orders were built like this: * While the order is valid, set the previous will get its next pointer set */ Order *prev = Order::GetIfValid(order_index - 1); if (prev != NULL) prev->next = o; } } else {
static void Load_TOWN() { int index; while ((index = SlIterateArray()) != -1) { Town *t = new (index) Town(); SlObject(t, _town_desc); for (CargoID i = 0; i < NUM_CARGO; i++) { SlObject(&t->supplied[i], _town_supplied_desc); } for (int i = TE_BEGIN; i < TE_END; i++) { SlObject(&t->received[i], _town_received_desc); } if (t->townnamegrfid == 0 && !IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1) && GB(t->townnametype, 11, 5) != 15) { SlErrorCorrupt("Invalid town name generator"); } if (IsSavegameVersionBefore(166)) continue; SlObject(&t->cargo_accepted, GetTileMatrixDesc()); if (t->cargo_accepted.area.w != 0) { uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID; t->cargo_accepted.data = MallocT<uint32>(arr_len); SlArray(t->cargo_accepted.data, arr_len, SLE_UINT32); /* Rebuild total cargo acceptance. */ UpdateTownCargoTotal(t); } } }
void Load_TOWN() { int index; while ((index = SlIterateArray()) != -1) { Town *t = new (index) Town(); SlObject(t, _town_desc); t->LoadCargoSourceSink(); if (IsSavegameVersionBefore(161)) continue; SlObject(&t->cargo_accepted, GetTileMatrixDesc()); if (t->cargo_accepted.area.w != 0) { uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID; t->cargo_accepted.data = MallocT<uint32>(arr_len); SlArray(t->cargo_accepted.data, arr_len, SLE_UINT32); /* Rebuild total cargo acceptance. */ UpdateTownCargoTotal(t); } /* Cache the aligned tile index of the centre tile. */ uint town_x = (TileX(t->xy) / AcceptanceMatrix::GRID) * AcceptanceMatrix::GRID; uint town_y = (TileY(t->xy) / AcceptanceMatrix::GRID) * AcceptanceMatrix::GRID; t->xy_aligned= TileXY(town_x, town_y); } }
static void Load_NAME() { int index; while ((index = SlIterateArray()) != -1) { SlArray(&_old_name_array[32 * index], SlGetFieldLength(), SLE_UINT8); } }
static void Load_MAPH() { SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf; TileIndex size = MapSize(); for (TileIndex i = 0; i != size;) { SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8); for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _main_map.m[i++].height = buf[j]; } }
static void Save_MAPH() { SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf; TileIndex size = MapSize(); SlSetLength(size); for (TileIndex i = 0; i != size;) { for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _main_map.m[i++].height; SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8); } }
static void Save_MAP2() { SmallStackSafeStackAlloc<uint16, MAP_SL_BUF_SIZE> buf; TileIndex size = MapSize(); SlSetLength(size * sizeof(uint16)); for (TileIndex i = 0; i != size;) { for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _main_map.m[i++].m2; SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT16); } }
static void Load_MAP2() { SmallStackSafeStackAlloc<uint16, MAP_SL_BUF_SIZE> buf; TileIndex size = MapSize(); for (TileIndex i = 0; i != size;) { SlArray(buf, MAP_SL_BUF_SIZE, /* In those versions the m2 was 8 bits */ IsSavegameVersionBefore(5) ? SLE_FILE_U8 | SLE_VAR_U16 : SLE_UINT16 ); for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _main_map.m[i++].m2 = buf[j]; } }
/** * Load the NAME chunk. */ static void Load_NAME() { int index; while ((index = SlIterateArray()) != -1) { if (index >= NUM_OLD_STRINGS) SlErrorCorrupt("Invalid old name index"); if (SlGetFieldLength() > (uint)LEN_OLD_STRINGS) SlErrorCorrupt("Invalid old name length"); SlArray(&_old_name_array[LEN_OLD_STRINGS * index], SlGetFieldLength(), SLE_UINT8); /* Make sure the old name is null terminated */ _old_name_array[LEN_OLD_STRINGS * index + LEN_OLD_STRINGS - 1] = '\0'; } }
void RealSave_TOWN(Town *t) { SlObject(t, _town_desc); t->SaveCargoSourceSink(); if (IsSavegameVersionBefore(161)) return; SlObject(&t->cargo_accepted, GetTileMatrixDesc()); if (t->cargo_accepted.area.w != 0) { uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID; SlArray(t->cargo_accepted.data, arr_len, SLE_UINT32); } }
/** * Load the ANIT chunk; the chunk containing the animated tiles. */ static void Load_ANIT() { /* Before version 80 we did NOT have a variable length animated tile table */ if (IsSavegameVersionBefore(80)) { /* In pre version 6, we has 16bit per tile, now we have 32bit per tile, convert it ;) */ SlArray(_animated_tile_list, 256, IsSavegameVersionBefore(6) ? (SLE_FILE_U16 | SLE_VAR_U32) : SLE_UINT32); for (_animated_tile_count = 0; _animated_tile_count < 256; _animated_tile_count++) { if (_animated_tile_list[_animated_tile_count] == 0) break; } return; } _animated_tile_count = (uint)SlGetFieldLength() / sizeof(*_animated_tile_list); /* Determine a nice rounded size for the amount of allocated tiles */ _animated_tile_allocated = 256; while (_animated_tile_allocated < _animated_tile_count) _animated_tile_allocated *= 2; _animated_tile_list = ReallocT<TileIndex>(_animated_tile_list, _animated_tile_allocated); SlArray(_animated_tile_list, _animated_tile_count, SLE_UINT32); }
static bool LoadObjects() { SlObject(NULL, _ai_byte); switch (_ai_sl_byte) { case SQSL_INT: { int value; SlArray(&value, 1, SLE_INT32); return true; } case SQSL_STRING: { SlObject(NULL, _ai_byte); static char buf[256]; SlArray(buf, _ai_sl_byte, SLE_CHAR); return true; } case SQSL_ARRAY: while (LoadObjects()) { } return true; case SQSL_TABLE: while (LoadObjects()) { LoadObjects(); } return true; case SQSL_BOOL: SlObject(NULL, _ai_byte); return true; case SQSL_NULL: return true; case SQSL_ARRAY_TABLE_END: return false; default: SlErrorCorrupt("Invalid AI data type"); } }
static void Load_MAP6() { SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf; TileIndex size = MapSize(); if (IsSavegameVersionBefore(42)) { for (TileIndex i = 0; i != size;) { /* 1024, otherwise we overflow on 64x64 maps! */ SlArray(buf, 1024, SLE_UINT8); for (uint j = 0; j != 1024; j++) { _main_map.me[i++].m6 = GB(buf[j], 0, 2); _main_map.me[i++].m6 = GB(buf[j], 2, 2); _main_map.me[i++].m6 = GB(buf[j], 4, 2); _main_map.me[i++].m6 = GB(buf[j], 6, 2); } } } else { for (TileIndex i = 0; i != size;) { SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8); for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _main_map.me[i++].m6 = buf[j]; } } }
static void Load_ENGS() { /* Load old separate String ID list into a temporary array. This * was always 256 entries. */ StringID names[256]; SlArray(names, lengthof(names), SLE_STRINGID); /* Copy each string into the temporary engine array. */ for (EngineID engine = 0; engine < lengthof(names); engine++) { Engine *e = GetTempDataEngine(engine); e->name = CopyFromOldName(names[engine]); } }
static void Load_MAPT() { SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf; TileIndex size = MapSize(); for (TileIndex i = 0; i != size;) { SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8); for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _main_map.m[i++].type = buf[j]; } if (IsSavegameVersionBefore(MORE_HEIGHTLEVEL_SAVEGAME_VERSION)) { // In old savegame versions, the heightlevel was coded in bits 0..3 of the type field for (TileIndex tile = 0; tile != size; tile++) { _main_map.m[tile].height = GB(_main_map.m[tile].type, 0, 4); } } }
static void RealSave_Town(Town *t) { SlObject(t, _town_desc); for (CargoID i = 0; i < NUM_CARGO; i++) { SlObject(&t->supplied[i], _town_supplied_desc); } for (int i = TE_BEGIN; i < NUM_TE; i++) { SlObject(&t->received[i], _town_received_desc); } if (IsSavegameVersionBefore(166)) return; SlObject(&t->cargo_accepted, GetTileMatrixDesc()); if (t->cargo_accepted.area.w != 0) { uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID; SlArray(t->cargo_accepted.data, arr_len, SLE_UINT32); } }
/* static */ bool ScriptInstance::SaveObject(HSQUIRRELVM vm, SQInteger index, int max_depth, bool test) { if (max_depth == 0) { ScriptLog::Error("Savedata can only be nested to 25 deep. No data saved."); // SQUIRREL_MAX_DEPTH = 25 return false; } switch (sq_gettype(vm, index)) { case OT_INTEGER: { if (!test) { _script_sl_byte = SQSL_INT; SlObject(NULL, _script_byte); } SQInteger res; sq_getinteger(vm, index, &res); if (!test) { int value = (int)res; SlArray(&value, 1, SLE_INT32); } return true; } case OT_STRING: { if (!test) { _script_sl_byte = SQSL_STRING; SlObject(NULL, _script_byte); } const SQChar *res; sq_getstring(vm, index, &res); /* @bug if a string longer than 512 characters is given to SQ2OTTD, the * internal buffer overflows. */ const char *buf = SQ2OTTD(res); size_t len = strlen(buf) + 1; if (len >= 255) { ScriptLog::Error("Maximum string length is 254 chars. No data saved."); return false; } if (!test) { _script_sl_byte = (byte)len; SlObject(NULL, _script_byte); SlArray(const_cast<char *>(buf), len, SLE_CHAR); } return true; } case OT_ARRAY: { if (!test) { _script_sl_byte = SQSL_ARRAY; SlObject(NULL, _script_byte); } sq_pushnull(vm); while (SQ_SUCCEEDED(sq_next(vm, index - 1))) { /* Store the value */ bool res = SaveObject(vm, -1, max_depth - 1, test); sq_pop(vm, 2); if (!res) { sq_pop(vm, 1); return false; } } sq_pop(vm, 1); if (!test) { _script_sl_byte = SQSL_ARRAY_TABLE_END; SlObject(NULL, _script_byte); } return true; } case OT_TABLE: { if (!test) { _script_sl_byte = SQSL_TABLE; SlObject(NULL, _script_byte); } sq_pushnull(vm); while (SQ_SUCCEEDED(sq_next(vm, index - 1))) { /* Store the key + value */ bool res = SaveObject(vm, -2, max_depth - 1, test) && SaveObject(vm, -1, max_depth - 1, test); sq_pop(vm, 2); if (!res) { sq_pop(vm, 1); return false; } } sq_pop(vm, 1); if (!test) { _script_sl_byte = SQSL_ARRAY_TABLE_END; SlObject(NULL, _script_byte); } return true; } case OT_BOOL: { if (!test) { _script_sl_byte = SQSL_BOOL; SlObject(NULL, _script_byte); } SQBool res; sq_getbool(vm, index, &res); if (!test) { _script_sl_byte = res ? 1 : 0; SlObject(NULL, _script_byte); } return true; } case OT_NULL: { if (!test) { _script_sl_byte = SQSL_NULL; SlObject(NULL, _script_byte); } return true; } default: ScriptLog::Error("You tried to save an unsupported type. No data saved."); return false; } }
/** * Save the ANIT chunk. */ static void Save_ANIT() { SlSetLength(_animated_tile_count * sizeof(*_animated_tile_list)); SlArray(_animated_tile_list, _animated_tile_count, SLE_UINT32); }