tron@2186: /* $Id$ */ tron@2186: truelight@0: #include "stdafx.h" Darkvater@1891: #include "openttd.h" tron@2308: #include "currency.h" tron@2163: #include "functions.h" tron@2548: #include "news.h" tron@2191: #include "player.h" tron@1375: #include "string.h" tron@507: #include "table/strings.h" Darkvater@1914: #include "table/sprites.h" tron@679: #include "map.h" truelight@0: #include "vehicle.h" truelight@0: #include "saveload.h" bjarni@842: #include "engine.h" matthijs@1752: #include "vehicle_gui.h" tron@2159: #include "variables.h" truelight@2706: #include "ai/ai.h" belugas@3616: #include "table/landscape_const.h" rubidium@4261: #include "date.h" truelight@0: tron@1328: char _name_array[512][32]; truelight@0: ludde@2073: #ifndef MERSENNE_TWISTER ludde@2073: truelight@543: #ifdef RANDOM_DEBUG truelight@543: #include "network_data.h" truelight@1120: uint32 DoRandom(int line, const char *file) ludde@2073: #else // RANDOM_DEBUG tron@1093: uint32 Random(void) ludde@2073: #endif // RANDOM_DEBUG truelight@543: { truelight@1121: truelight@1121: uint32 s; truelight@1121: uint32 t; truelight@1121: truelight@543: #ifdef RANDOM_DEBUG truelight@543: if (_networking && (DEREF_CLIENT(0)->status != STATUS_INACTIVE || !_network_server)) truelight@543: printf("Random [%d/%d] %s:%d\n",_frame_counter, _current_player, file, line); truelight@260: #endif truelight@260: truelight@1121: s = _random_seeds[0][0]; truelight@1121: t = _random_seeds[0][1]; pasky@1446: _random_seeds[0][0] = s + ROR(t ^ 0x1234567F, 7) + 1; pasky@1446: return _random_seeds[0][1] = ROR(s, 3) - 1; truelight@0: } ludde@2073: #endif // MERSENNE_TWISTER truelight@0: ludde@2073: #if defined(RANDOM_DEBUG) && !defined(MERSENNE_TWISTER) truelight@1120: uint DoRandomRange(uint max, int line, const char *file) truelight@543: { tron@2484: return GB(DoRandom(line, file), 0, 16) * max >> 16; truelight@543: } truelight@543: #else truelight@0: uint RandomRange(uint max) truelight@0: { tron@2484: return GB(Random(), 0, 16) * max >> 16; truelight@0: } truelight@543: #endif truelight@0: ludde@2073: tron@1093: uint32 InteractiveRandom(void) truelight@0: { signde@206: uint32 t = _random_seeds[1][1]; signde@206: uint32 s = _random_seeds[1][0]; pasky@1446: _random_seeds[1][0] = s + ROR(t ^ 0x1234567F, 7) + 1; pasky@1446: return _random_seeds[1][1] = ROR(s, 3) - 1; signde@206: } signde@206: signde@239: uint InteractiveRandomRange(uint max) signde@239: { tron@2484: return GB(InteractiveRandom(), 0, 16) * max >> 16; signde@239: } signde@239: tron@1093: void InitializeVehicles(void); truelight@1542: void InitializeWaypoints(void); truelight@4347: void InitializeDepots(void); peter1138@2848: void InitializeEngines(void); tron@1093: void InitializeOrders(void); tron@1093: void InitializeClearLand(void); tron@1093: void InitializeRailGui(void); tron@1093: void InitializeRoadGui(void); tron@1093: void InitializeAirportGui(void); tron@1093: void InitializeDockGui(void); tron@1093: void InitializeIndustries(void); celestar@3622: void InitializeMainGui(void); ludde@2051: void InitializeLandscape(void); tron@1093: void InitializeTowns(void); tron@1093: void InitializeTrees(void); tron@1093: void InitializeSigns(void); tron@1093: void InitializeStations(void); tron@1093: static void InitializeNameMgr(void); tron@1093: void InitializePlayers(void); tron@1093: static void InitializeCheats(void); matthijs@1247: void InitializeNPF(void); truelight@0: truelight@2828: void InitializeGame(int mode, uint size_x, uint size_y) truelight@0: { ludde@2051: AllocateMap(size_x, size_y); ludde@2051: bjarni@842: AddTypeToEngines(); // make sure all engines have a type tron@915: Darkvater@1914: SetObjectToPlace(SPR_CURSOR_ZZZ, 0, 0, 0); truelight@0: truelight@0: _pause = 0; truelight@0: _fast_forward = 0; truelight@0: _tick_counter = 0; truelight@0: _date_fract = 0; truelight@0: _cur_tileloop_tile = 0; truelight@201: truelight@2828: if ((mode & IG_DATE_RESET) == IG_DATE_RESET) { rubidium@4295: SetDate(ConvertYMDToDate(_patches.starting_year, 0, 1)); truelight@0: } truelight@0: peter1138@2848: InitializeEngines(); truelight@0: InitializeVehicles(); truelight@1542: InitializeWaypoints(); truelight@4347: InitializeDepots(); truelight@1024: InitializeOrders(); truelight@0: truelight@0: InitNewsItemStructs(); ludde@2051: InitializeLandscape(); truelight@0: InitializeClearLand(); truelight@0: InitializeRailGui(); truelight@0: InitializeRoadGui(); truelight@0: InitializeAirportGui(); truelight@0: InitializeDockGui(); truelight@0: InitializeTowns(); truelight@0: InitializeTrees(); truelight@988: InitializeSigns(); truelight@0: InitializeStations(); truelight@0: InitializeIndustries(); celestar@3622: InitializeMainGui(); truelight@201: truelight@0: InitializeNameMgr(); darkvater@164: InitializeVehiclesGuiList(); truelight@0: InitializeTrains(); matthijs@1247: InitializeNPF(); truelight@0: truelight@2706: AI_Initialize(); truelight@0: InitializePlayers(); truelight@0: InitializeCheats(); truelight@0: truelight@0: InitTextEffects(); truelight@543: InitTextMessage(); truelight@0: InitializeAnimatedTiles(); truelight@0: truelight@0: InitializeLandscapeVariables(false); truelight@0: truelight@0: ResetObjectToPlace(); truelight@0: } truelight@0: peter1138@4862: bool IsCustomName(StringID id) peter1138@4862: { peter1138@4862: return GB(id, 11, 5) == 15; peter1138@4862: } peter1138@4862: truelight@0: void DeleteName(StringID id) truelight@0: { peter1138@4862: if (IsCustomName(id)) { truelight@0: memset(_name_array[id & 0x1FF], 0, sizeof(_name_array[id & 0x1FF])); truelight@0: } truelight@0: } truelight@0: Darkvater@4912: char *GetName(char *buff, StringID id, const char* last) truelight@0: { Darkvater@4912: return strecpy(buff, _name_array[id & ~0x600], last); truelight@0: } truelight@0: truelight@0: tron@1093: static void InitializeCheats(void) truelight@0: { truelight@201: memset(&_cheats, 0, sizeof(Cheats)); truelight@0: } truelight@0: truelight@0: tron@1093: static void InitializeNameMgr(void) truelight@0: { truelight@0: memset(_name_array, 0, sizeof(_name_array)); truelight@0: } truelight@0: tron@1328: StringID RealAllocateName(const char *name, byte skip, bool check_double) truelight@0: { tron@1375: char (*free_item)[lengthof(*_name_array)] = NULL; tron@1375: char (*i)[lengthof(*_name_array)]; truelight@0: tron@1375: for (i = _name_array; i != endof(_name_array); ++i) { tron@1375: if ((*i)[0] == '\0') { tron@1375: if (free_item == NULL) free_item = i; tron@1375: } else if (check_double && strncmp(*i, name, lengthof(*i) - 1) == 0) { tron@1375: _error_message = STR_0132_CHOSEN_NAME_IN_USE_ALREADY; tron@1375: return 0; truelight@0: } truelight@0: } truelight@0: tron@1375: if (free_item != NULL) { tron@1375: ttd_strlcpy(*free_item, name, lengthof(*free_item)); tron@1375: return (free_item - _name_array) | 0x7800 | (skip << 8); tron@1375: } else { truelight@0: _error_message = STR_0131_TOO_MANY_NAMES_DEFINED; truelight@0: return 0; truelight@0: } truelight@0: } truelight@0: peter1138@5108: void ConvertNameArray(void) peter1138@5108: { peter1138@5108: uint i; peter1138@5108: peter1138@5108: for (i = 0; i < lengthof(_name_array); i++) { peter1138@5108: const char *strfrom = _name_array[i]; peter1138@5108: char tmp[sizeof(*_name_array)]; peter1138@5108: char *strto = tmp; peter1138@5108: peter1138@5108: for (; *strfrom != '\0'; strfrom++) { peter1138@5108: WChar c = (byte)*strfrom; peter1138@5108: switch (c) { peter1138@5108: case 0xA4: c = 0x20AC; break; // Euro peter1138@5108: case 0xA6: c = 0x0160; break; // S with caron peter1138@5108: case 0xA8: c = 0x0161; break; // s with caron peter1138@5108: case 0xB4: c = 0x017D; break; // Z with caron peter1138@5108: case 0xB8: c = 0x017E; break; // z with caron peter1138@5108: case 0xBC: c = 0x0152; break; // OE ligature peter1138@5108: case 0xBD: c = 0x0153; break; // oe ligature peter1138@5108: case 0xBE: c = 0x0178; break; // Y with diaresis peter1138@5108: default: break; peter1138@5108: } peter1138@5108: if (strto + Utf8CharLen(c) > lastof(tmp)) break; peter1138@5108: strto += Utf8Encode(strto, c); peter1138@5108: } peter1138@5108: peter1138@5108: /* Terminate the new string and copy it back to the name array */ peter1138@5108: *strto = '\0'; peter1138@5108: memcpy(_name_array[i], tmp, sizeof(*_name_array)); peter1138@5108: } peter1138@5108: } peter1138@5108: truelight@0: // Calculate constants that depend on the landscape type. truelight@0: void InitializeLandscapeVariables(bool only_constants) truelight@0: { belugas@3616: const CargoTypesValues *lpd; tron@2989: uint i; truelight@0: StringID str; truelight@0: belugas@3616: lpd = &_cargo_types_base_values[_opt.landscape]; truelight@0: tron@2951: for (i = 0; i != NUM_CARGO; i++) { truelight@0: _cargoc.sprites[i] = lpd->sprites[i]; truelight@201: truelight@0: str = lpd->names[i]; truelight@0: _cargoc.names_s[i] = str; ludde@2112: _cargoc.names_long[i] = (str += 0x40); truelight@0: _cargoc.names_short[i] = (str += 0x20); truelight@0: _cargoc.weights[i] = lpd->weights[i]; truelight@201: truelight@0: if (!only_constants) { truelight@0: _cargo_payment_rates[i] = lpd->initial_cargo_payment[i]; truelight@0: _cargo_payment_rates_frac[i] = 0; truelight@0: } truelight@0: truelight@0: _cargoc.transit_days_1[i] = lpd->transit_days_table_1[i]; truelight@0: _cargoc.transit_days_2[i] = lpd->transit_days_table_2[i]; truelight@0: } truelight@0: } truelight@0: truelight@0: truelight@0: dominik@116: int FindFirstBit(uint32 value) truelight@0: { miham@826: // This is much faster than the one that was before here. dominik@116: // Created by Darkvater.. blame him if it is wrong ;) dominik@116: // Btw, the macro FINDFIRSTBIT is better to use when your value is miham@826: // not more than 128. dominik@116: byte i = 0; dominik@116: if (value & 0xffff0000) { value >>= 16; i += 16; } tron@3033: if (value & 0x0000ff00) { value >>= 8; i += 8; } tron@3033: if (value & 0x000000f0) { value >>= 4; i += 4; } tron@3033: if (value & 0x0000000c) { value >>= 2; i += 2; } dominik@116: if (value & 0x00000002) { i += 1; } truelight@0: return i; truelight@0: } truelight@0: truelight@0: tron@1093: static void Save_NAME(void) truelight@0: { truelight@0: int i; truelight@0: tron@1375: for (i = 0; i != lengthof(_name_array); ++i) { tron@1375: if (_name_array[i][0] != '\0') { truelight@0: SlSetArrayIndex(i); truelight@4321: SlArray(_name_array[i], (uint)strlen(_name_array[i]), SLE_UINT8); truelight@201: } truelight@0: } truelight@0: } truelight@0: tron@1093: static void Load_NAME(void) truelight@0: { truelight@0: int index; truelight@201: truelight@0: while ((index = SlIterateArray()) != -1) { truelight@0: SlArray(_name_array[index],SlGetFieldLength(),SLE_UINT8); truelight@0: } truelight@0: } truelight@0: truelight@0: static const SaveLoadGlobVarList _date_desc[] = { truelight@4383: SLEG_CONDVAR(_date, SLE_FILE_U16 | SLE_VAR_I32, 0, 30), truelight@4383: SLEG_CONDVAR(_date, SLE_INT32, 31, SL_MAX_VERSION), rubidium@4344: SLEG_VAR(_date_fract, SLE_UINT16), rubidium@4344: SLEG_VAR(_tick_counter, SLE_UINT16), rubidium@4344: SLEG_VAR(_vehicle_id_ctr_day, SLE_UINT16), rubidium@4344: SLEG_VAR(_age_cargo_skip_counter, SLE_UINT8), rubidium@4344: SLEG_VAR(_avail_aircraft, SLE_UINT8), rubidium@4344: SLEG_CONDVAR(_cur_tileloop_tile, SLE_FILE_U16 | SLE_VAR_U32, 0, 5), rubidium@4344: SLEG_CONDVAR(_cur_tileloop_tile, SLE_UINT32, 6, SL_MAX_VERSION), rubidium@4344: SLEG_VAR(_disaster_delay, SLE_UINT16), rubidium@4344: SLEG_VAR(_station_tick_ctr, SLE_UINT16), rubidium@4344: SLEG_VAR(_random_seeds[0][0], SLE_UINT32), rubidium@4344: SLEG_VAR(_random_seeds[0][1], SLE_UINT32), rubidium@4344: SLEG_CONDVAR(_cur_town_ctr, SLE_FILE_U8 | SLE_VAR_U32, 0, 9), rubidium@4344: SLEG_CONDVAR(_cur_town_ctr, SLE_UINT32, 10, SL_MAX_VERSION), rubidium@4344: SLEG_VAR(_cur_player_tick_index, SLE_FILE_U8 | SLE_VAR_U32), rubidium@4344: SLEG_VAR(_next_competitor_start, SLE_FILE_U16 | SLE_VAR_U32), rubidium@4344: SLEG_VAR(_trees_tick_ctr, SLE_UINT8), rubidium@4344: SLEG_CONDVAR(_pause, SLE_UINT8, 4, SL_MAX_VERSION), rubidium@4344: SLEG_CONDVAR(_cur_town_iter, SLE_UINT32, 11, SL_MAX_VERSION), Darkvater@3046: SLEG_END() truelight@0: }; truelight@0: truelight@0: // Save load date related variables as well as persistent tick counters truelight@0: // XXX: currently some unrelated stuff is just put here tron@1093: static void SaveLoad_DATE(void) truelight@0: { truelight@0: SlGlobList(_date_desc); truelight@0: } truelight@0: truelight@0: truelight@0: static const SaveLoadGlobVarList _view_desc[] = { rubidium@4344: SLEG_CONDVAR(_saved_scrollpos_x, SLE_FILE_I16 | SLE_VAR_I32, 0, 5), rubidium@4344: SLEG_CONDVAR(_saved_scrollpos_x, SLE_INT32, 6, SL_MAX_VERSION), rubidium@4344: SLEG_CONDVAR(_saved_scrollpos_y, SLE_FILE_I16 | SLE_VAR_I32, 0, 5), rubidium@4344: SLEG_CONDVAR(_saved_scrollpos_y, SLE_INT32, 6, SL_MAX_VERSION), rubidium@4344: SLEG_VAR(_saved_scrollpos_zoom, SLE_UINT8), Darkvater@3046: SLEG_END() truelight@0: }; truelight@0: tron@1093: static void SaveLoad_VIEW(void) truelight@0: { truelight@0: SlGlobList(_view_desc); truelight@0: } truelight@0: tron@1218: static uint32 _map_dim_x; tron@1218: static uint32 _map_dim_y; tron@1218: tron@1218: static const SaveLoadGlobVarList _map_dimensions[] = { Darkvater@3046: SLEG_CONDVAR(_map_dim_x, SLE_UINT32, 6, SL_MAX_VERSION), Darkvater@3046: SLEG_CONDVAR(_map_dim_y, SLE_UINT32, 6, SL_MAX_VERSION), Darkvater@3046: SLEG_END() tron@1218: }; tron@1218: tron@2049: static void Save_MAPS(void) tron@1218: { tron@1219: _map_dim_x = MapSizeX(); tron@1219: _map_dim_y = MapSizeY(); tron@1218: SlGlobList(_map_dimensions); tron@1218: } tron@1218: tron@2049: static void Load_MAPS(void) tron@1218: { tron@1218: SlGlobList(_map_dimensions); ludde@2051: AllocateMap(_map_dim_x, _map_dim_y); tron@1218: } tron@1218: tron@2295: static void Load_MAPT(void) ludde@2050: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2295: for (j = 0; j != lengthof(buf); j++) _m[i++].type_height = buf[j]; truelight@817: } truelight@0: } truelight@0: tron@2295: static void Save_MAPT(void) tron@1093: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: SlSetLength(size); tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2295: for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].type_height; tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2295: } truelight@0: } truelight@0: tron@2360: static void Load_MAP1(void) tron@1093: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2360: for (j = 0; j != lengthof(buf); j++) _m[i++].m1 = buf[j]; tron@2295: } tron@2295: } tron@2295: tron@2360: static void Save_MAP1(void) tron@2295: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: SlSetLength(size); tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2360: for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m1; tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2295: } truelight@0: } truelight@0: tron@2049: static void Load_MAP2(void) tron@1093: { tron@2049: uint size = MapSize(); tron@2049: uint i; tron@2049: tron@2049: for (i = 0; i != size;) { tron@2049: uint16 buf[4096]; tron@2049: uint j; tron@2049: tron@2049: SlArray(buf, lengthof(buf), tron@2049: /* In those versions the m2 was 8 bits */ truelight@2685: CheckSavegameVersion(5) ? SLE_FILE_U8 | SLE_VAR_U16 : SLE_UINT16 tron@2049: ); tron@2049: for (j = 0; j != lengthof(buf); j++) _m[i++].m2 = buf[j]; tron@2049: } tron@2049: } tron@2049: tron@2049: static void Save_MAP2(void) tron@2049: { tron@2049: uint size = MapSize(); tron@2049: uint i; tron@2049: tron@2049: SlSetLength(size * sizeof(_m[0].m2)); tron@2049: for (i = 0; i != size;) { tron@2049: uint16 buf[4096]; tron@2049: uint j; tron@2049: tron@2049: for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m2; tron@2049: SlArray(buf, lengthof(buf), SLE_UINT16); tron@2049: } tron@2049: } tron@2049: tron@2295: static void Load_MAP3(void) tron@2049: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2295: for (j = 0; j != lengthof(buf); j++) _m[i++].m3 = buf[j]; tron@2295: } tron@2049: } tron@2049: tron@2295: static void Save_MAP3(void) tron@2049: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: SlSetLength(size); tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2295: for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m3; tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2295: } tron@2049: } tron@2049: tron@2295: static void Load_MAP4(void) tron@2049: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2295: for (j = 0; j != lengthof(buf); j++) _m[i++].m4 = buf[j]; tron@2295: } tron@2295: } tron@2295: tron@2295: static void Save_MAP4(void) tron@2295: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: SlSetLength(size); tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2295: for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m4; tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2295: } tron@2295: } tron@2295: tron@2295: static void Load_MAP5(void) tron@2295: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2295: for (j = 0; j != lengthof(buf); j++) _m[i++].m5 = buf[j]; tron@2295: } tron@2295: } tron@2295: tron@2295: static void Save_MAP5(void) tron@2295: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: SlSetLength(size); tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2295: for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m5; tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2295: } tron@2049: } tron@2049: tron@2049: static void Load_MAPE(void) tron@2049: { tron@2049: uint size = MapSize(); tron@2049: uint i; tron@2049: celestar@5573: if (CheckSavegameVersion(42)) { celestar@5573: for (i = 0; i != size;) { celestar@5573: uint8 buf[1024]; celestar@5573: uint j; tron@2049: celestar@5573: SlArray(buf, lengthof(buf), SLE_UINT8); celestar@5573: for (j = 0; j != lengthof(buf); j++) { celestar@5573: _m[i++].extra = GB(buf[j], 0, 2); celestar@5573: _m[i++].extra = GB(buf[j], 2, 2); celestar@5573: _m[i++].extra = GB(buf[j], 4, 2); celestar@5573: _m[i++].extra = GB(buf[j], 6, 2); celestar@5573: } celestar@5573: } celestar@5573: } else { celestar@5573: for (i = 0; i != size;) { celestar@5573: byte buf[4096]; celestar@5573: uint j; celestar@5573: celestar@5573: SlArray(buf, lengthof(buf), SLE_UINT8); celestar@5573: for (j = 0; j != lengthof(buf); j++) _m[i++].extra = buf[j]; tron@2049: } tron@2049: } tron@2049: } tron@2049: tron@2049: static void Save_MAPE(void) tron@2049: { tron@2049: uint size = MapSize(); tron@2049: uint i; tron@2049: celestar@5573: SlSetLength(size); tron@2049: for (i = 0; i != size;) { celestar@5573: uint8 buf[4096]; tron@2049: uint j; tron@2049: celestar@5573: for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].extra; tron@2049: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2049: } truelight@0: } truelight@0: truelight@0: tron@1093: static void Save_CHTS(void) truelight@0: { truelight@0: byte count = sizeof(_cheats)/sizeof(Cheat); truelight@0: Cheat* cht = (Cheat*) &_cheats; truelight@0: Cheat* cht_last = &cht[count]; truelight@0: tron@2951: SlSetLength(count * 2); tron@2951: for (; cht != cht_last; cht++) { truelight@0: SlWriteByte(cht->been_used); truelight@0: SlWriteByte(cht->value); truelight@0: } truelight@0: } truelight@0: tron@1093: static void Load_CHTS(void) truelight@0: { tron@2989: Cheat* cht = (Cheat*)&_cheats; tron@2989: uint count = SlGetFieldLength() / 2; tron@2989: uint i; truelight@0: tron@2989: for (i = 0; i < count; i++) { tron@2989: cht[i].been_used = SlReadByte(); tron@2989: cht[i].value = SlReadByte(); truelight@0: } truelight@0: } truelight@0: truelight@0: truelight@0: const ChunkHandler _misc_chunk_handlers[] = { rubidium@4344: { 'MAPS', Save_MAPS, Load_MAPS, CH_RIFF }, rubidium@4344: { 'MAPT', Save_MAPT, Load_MAPT, CH_RIFF }, rubidium@4344: { 'MAPO', Save_MAP1, Load_MAP1, CH_RIFF }, rubidium@4344: { 'MAP2', Save_MAP2, Load_MAP2, CH_RIFF }, rubidium@4344: { 'M3LO', Save_MAP3, Load_MAP3, CH_RIFF }, rubidium@4344: { 'M3HI', Save_MAP4, Load_MAP4, CH_RIFF }, rubidium@4344: { 'MAP5', Save_MAP5, Load_MAP5, CH_RIFF }, rubidium@4344: { 'MAPE', Save_MAPE, Load_MAPE, CH_RIFF }, truelight@0: rubidium@4344: { 'NAME', Save_NAME, Load_NAME, CH_ARRAY}, truelight@0: { 'DATE', SaveLoad_DATE, SaveLoad_DATE, CH_RIFF}, truelight@0: { 'VIEW', SaveLoad_VIEW, SaveLoad_VIEW, CH_RIFF}, rubidium@4344: { 'CHTS', Save_CHTS, Load_CHTS, CH_RIFF | CH_LAST} truelight@0: };