src/misc.c
changeset 5584 1111b4d36e35
parent 5583 136d8764c7e6
child 5585 189f096bc9a3
equal deleted inserted replaced
5583:136d8764c7e6 5584:1111b4d36e35
     1 /* $Id$ */
       
     2 
       
     3 #include "stdafx.h"
       
     4 #include "openttd.h"
       
     5 #include "currency.h"
       
     6 #include "functions.h"
       
     7 #include "news.h"
       
     8 #include "player.h"
       
     9 #include "string.h"
       
    10 #include "table/strings.h"
       
    11 #include "table/sprites.h"
       
    12 #include "map.h"
       
    13 #include "vehicle.h"
       
    14 #include "saveload.h"
       
    15 #include "engine.h"
       
    16 #include "vehicle_gui.h"
       
    17 #include "variables.h"
       
    18 #include "ai/ai.h"
       
    19 #include "table/landscape_const.h"
       
    20 #include "date.h"
       
    21 
       
    22 char _name_array[512][32];
       
    23 
       
    24 #ifndef MERSENNE_TWISTER
       
    25 
       
    26 #ifdef RANDOM_DEBUG
       
    27 #include "network/network_data.h"
       
    28 uint32 DoRandom(int line, const char *file)
       
    29 #else // RANDOM_DEBUG
       
    30 uint32 Random(void)
       
    31 #endif // RANDOM_DEBUG
       
    32 {
       
    33 
       
    34 uint32 s;
       
    35 uint32 t;
       
    36 
       
    37 #ifdef RANDOM_DEBUG
       
    38 	if (_networking && (DEREF_CLIENT(0)->status != STATUS_INACTIVE || !_network_server))
       
    39 		printf("Random [%d/%d] %s:%d\n",_frame_counter, _current_player, file, line);
       
    40 #endif
       
    41 
       
    42 	s = _random_seeds[0][0];
       
    43 	t = _random_seeds[0][1];
       
    44 	_random_seeds[0][0] = s + ROR(t ^ 0x1234567F, 7) + 1;
       
    45 	return _random_seeds[0][1] = ROR(s, 3) - 1;
       
    46 }
       
    47 #endif // MERSENNE_TWISTER
       
    48 
       
    49 #if defined(RANDOM_DEBUG) && !defined(MERSENNE_TWISTER)
       
    50 uint DoRandomRange(uint max, int line, const char *file)
       
    51 {
       
    52 	return GB(DoRandom(line, file), 0, 16) * max >> 16;
       
    53 }
       
    54 #else
       
    55 uint RandomRange(uint max)
       
    56 {
       
    57 	return GB(Random(), 0, 16) * max >> 16;
       
    58 }
       
    59 #endif
       
    60 
       
    61 
       
    62 uint32 InteractiveRandom(void)
       
    63 {
       
    64 	uint32 t = _random_seeds[1][1];
       
    65 	uint32 s = _random_seeds[1][0];
       
    66 	_random_seeds[1][0] = s + ROR(t ^ 0x1234567F, 7) + 1;
       
    67 	return _random_seeds[1][1] = ROR(s, 3) - 1;
       
    68 }
       
    69 
       
    70 uint InteractiveRandomRange(uint max)
       
    71 {
       
    72 	return GB(InteractiveRandom(), 0, 16) * max >> 16;
       
    73 }
       
    74 
       
    75 void InitializeVehicles(void);
       
    76 void InitializeWaypoints(void);
       
    77 void InitializeDepots(void);
       
    78 void InitializeEngines(void);
       
    79 void InitializeOrders(void);
       
    80 void InitializeClearLand(void);
       
    81 void InitializeRailGui(void);
       
    82 void InitializeRoadGui(void);
       
    83 void InitializeAirportGui(void);
       
    84 void InitializeDockGui(void);
       
    85 void InitializeIndustries(void);
       
    86 void InitializeMainGui(void);
       
    87 void InitializeLandscape(void);
       
    88 void InitializeTowns(void);
       
    89 void InitializeTrees(void);
       
    90 void InitializeSigns(void);
       
    91 void InitializeStations(void);
       
    92 static void InitializeNameMgr(void);
       
    93 void InitializePlayers(void);
       
    94 static void InitializeCheats(void);
       
    95 void InitializeNPF(void);
       
    96 
       
    97 void InitializeGame(int mode, uint size_x, uint size_y)
       
    98 {
       
    99 	AllocateMap(size_x, size_y);
       
   100 
       
   101 	AddTypeToEngines(); // make sure all engines have a type
       
   102 
       
   103 	SetObjectToPlace(SPR_CURSOR_ZZZ, 0, 0, 0);
       
   104 
       
   105 	_pause = 0;
       
   106 	_fast_forward = 0;
       
   107 	_tick_counter = 0;
       
   108 	_date_fract = 0;
       
   109 	_cur_tileloop_tile = 0;
       
   110 
       
   111 	if ((mode & IG_DATE_RESET) == IG_DATE_RESET) {
       
   112 		SetDate(ConvertYMDToDate(_patches.starting_year, 0, 1));
       
   113 	}
       
   114 
       
   115 	InitializeEngines();
       
   116 	InitializeVehicles();
       
   117 	InitializeWaypoints();
       
   118 	InitializeDepots();
       
   119 	InitializeOrders();
       
   120 
       
   121 	InitNewsItemStructs();
       
   122 	InitializeLandscape();
       
   123 	InitializeClearLand();
       
   124 	InitializeRailGui();
       
   125 	InitializeRoadGui();
       
   126 	InitializeAirportGui();
       
   127 	InitializeDockGui();
       
   128 	InitializeTowns();
       
   129 	InitializeTrees();
       
   130 	InitializeSigns();
       
   131 	InitializeStations();
       
   132 	InitializeIndustries();
       
   133 	InitializeMainGui();
       
   134 
       
   135 	InitializeNameMgr();
       
   136 	InitializeVehiclesGuiList();
       
   137 	InitializeTrains();
       
   138 	InitializeNPF();
       
   139 
       
   140 	AI_Initialize();
       
   141 	InitializePlayers();
       
   142 	InitializeCheats();
       
   143 
       
   144 	InitTextEffects();
       
   145 	InitTextMessage();
       
   146 	InitializeAnimatedTiles();
       
   147 
       
   148 	InitializeLandscapeVariables(false);
       
   149 
       
   150 	ResetObjectToPlace();
       
   151 }
       
   152 
       
   153 bool IsCustomName(StringID id)
       
   154 {
       
   155 	return GB(id, 11, 5) == 15;
       
   156 }
       
   157 
       
   158 void DeleteName(StringID id)
       
   159 {
       
   160 	if (IsCustomName(id)) {
       
   161 		memset(_name_array[id & 0x1FF], 0, sizeof(_name_array[id & 0x1FF]));
       
   162 	}
       
   163 }
       
   164 
       
   165 char *GetName(char *buff, StringID id, const char* last)
       
   166 {
       
   167 	return strecpy(buff, _name_array[id & ~0x600], last);
       
   168 }
       
   169 
       
   170 
       
   171 static void InitializeCheats(void)
       
   172 {
       
   173 	memset(&_cheats, 0, sizeof(Cheats));
       
   174 }
       
   175 
       
   176 
       
   177 static void InitializeNameMgr(void)
       
   178 {
       
   179 	memset(_name_array, 0, sizeof(_name_array));
       
   180 }
       
   181 
       
   182 StringID RealAllocateName(const char *name, byte skip, bool check_double)
       
   183 {
       
   184 	char (*free_item)[lengthof(*_name_array)] = NULL;
       
   185 	char (*i)[lengthof(*_name_array)];
       
   186 
       
   187 	for (i = _name_array; i != endof(_name_array); ++i) {
       
   188 		if ((*i)[0] == '\0') {
       
   189 			if (free_item == NULL) free_item = i;
       
   190 		} else if (check_double && strncmp(*i, name, lengthof(*i) - 1) == 0) {
       
   191 			_error_message = STR_0132_CHOSEN_NAME_IN_USE_ALREADY;
       
   192 			return 0;
       
   193 		}
       
   194 	}
       
   195 
       
   196 	if (free_item != NULL) {
       
   197 		ttd_strlcpy(*free_item, name, lengthof(*free_item));
       
   198 		return (free_item - _name_array) | 0x7800 | (skip << 8);
       
   199 	} else {
       
   200 		_error_message = STR_0131_TOO_MANY_NAMES_DEFINED;
       
   201 		return 0;
       
   202 	}
       
   203 }
       
   204 
       
   205 void ConvertNameArray(void)
       
   206 {
       
   207 	uint i;
       
   208 
       
   209 	for (i = 0; i < lengthof(_name_array); i++) {
       
   210 		const char *strfrom = _name_array[i];
       
   211 		char tmp[sizeof(*_name_array)];
       
   212 		char *strto = tmp;
       
   213 
       
   214 		for (; *strfrom != '\0'; strfrom++) {
       
   215 			WChar c = (byte)*strfrom;
       
   216 			switch (c) {
       
   217 				case 0xA4: c = 0x20AC; break; // Euro
       
   218 				case 0xA6: c = 0x0160; break; // S with caron
       
   219 				case 0xA8: c = 0x0161; break; // s with caron
       
   220 				case 0xB4: c = 0x017D; break; // Z with caron
       
   221 				case 0xB8: c = 0x017E; break; // z with caron
       
   222 				case 0xBC: c = 0x0152; break; // OE ligature
       
   223 				case 0xBD: c = 0x0153; break; // oe ligature
       
   224 				case 0xBE: c = 0x0178; break; // Y with diaresis
       
   225 				default: break;
       
   226 			}
       
   227 			if (strto + Utf8CharLen(c) > lastof(tmp)) break;
       
   228 			strto += Utf8Encode(strto, c);
       
   229 		}
       
   230 
       
   231 		/* Terminate the new string and copy it back to the name array */
       
   232 		*strto = '\0';
       
   233 		memcpy(_name_array[i], tmp, sizeof(*_name_array));
       
   234 	}
       
   235 }
       
   236 
       
   237 // Calculate constants that depend on the landscape type.
       
   238 void InitializeLandscapeVariables(bool only_constants)
       
   239 {
       
   240 	const CargoTypesValues *lpd;
       
   241 	uint i;
       
   242 	StringID str;
       
   243 
       
   244 	lpd = &_cargo_types_base_values[_opt.landscape];
       
   245 
       
   246 	for (i = 0; i != NUM_CARGO; i++) {
       
   247 		_cargoc.sprites[i] = lpd->sprites[i];
       
   248 
       
   249 		str = lpd->names[i];
       
   250 		_cargoc.names_s[i] = str;
       
   251 		_cargoc.names_long[i] = (str += 0x40);
       
   252 		_cargoc.names_short[i] = (str += 0x20);
       
   253 		_cargoc.weights[i] = lpd->weights[i];
       
   254 
       
   255 		if (!only_constants) {
       
   256 			_cargo_payment_rates[i] = lpd->initial_cargo_payment[i];
       
   257 			_cargo_payment_rates_frac[i] = 0;
       
   258 		}
       
   259 
       
   260 		_cargoc.transit_days_1[i] = lpd->transit_days_table_1[i];
       
   261 		_cargoc.transit_days_2[i] = lpd->transit_days_table_2[i];
       
   262 	}
       
   263 }
       
   264 
       
   265 
       
   266 
       
   267 int FindFirstBit(uint32 value)
       
   268 {
       
   269 	// This is much faster than the one that was before here.
       
   270 	//  Created by Darkvater.. blame him if it is wrong ;)
       
   271 	// Btw, the macro FINDFIRSTBIT is better to use when your value is
       
   272 	//  not more than 128.
       
   273 	byte i = 0;
       
   274 	if (value & 0xffff0000) { value >>= 16; i += 16; }
       
   275 	if (value & 0x0000ff00) { value >>= 8;  i +=  8; }
       
   276 	if (value & 0x000000f0) { value >>= 4;  i +=  4; }
       
   277 	if (value & 0x0000000c) { value >>= 2;  i +=  2; }
       
   278 	if (value & 0x00000002) { i += 1; }
       
   279 	return i;
       
   280 }
       
   281 
       
   282 
       
   283 static void Save_NAME(void)
       
   284 {
       
   285 	int i;
       
   286 
       
   287 	for (i = 0; i != lengthof(_name_array); ++i) {
       
   288 		if (_name_array[i][0] != '\0') {
       
   289 			SlSetArrayIndex(i);
       
   290 			SlArray(_name_array[i], (uint)strlen(_name_array[i]), SLE_UINT8);
       
   291 		}
       
   292 	}
       
   293 }
       
   294 
       
   295 static void Load_NAME(void)
       
   296 {
       
   297 	int index;
       
   298 
       
   299 	while ((index = SlIterateArray()) != -1) {
       
   300 		SlArray(_name_array[index],SlGetFieldLength(),SLE_UINT8);
       
   301 	}
       
   302 }
       
   303 
       
   304 static const SaveLoadGlobVarList _date_desc[] = {
       
   305 	SLEG_CONDVAR(_date,                   SLE_FILE_U16 | SLE_VAR_I32,  0,  30),
       
   306 	SLEG_CONDVAR(_date,                   SLE_INT32,                  31, SL_MAX_VERSION),
       
   307 	    SLEG_VAR(_date_fract,             SLE_UINT16),
       
   308 	    SLEG_VAR(_tick_counter,           SLE_UINT16),
       
   309 	    SLEG_VAR(_vehicle_id_ctr_day,     SLE_UINT16),
       
   310 	    SLEG_VAR(_age_cargo_skip_counter, SLE_UINT8),
       
   311 	    SLEG_VAR(_avail_aircraft,         SLE_UINT8),
       
   312 	SLEG_CONDVAR(_cur_tileloop_tile,      SLE_FILE_U16 | SLE_VAR_U32,  0, 5),
       
   313 	SLEG_CONDVAR(_cur_tileloop_tile,      SLE_UINT32,                  6, SL_MAX_VERSION),
       
   314 	    SLEG_VAR(_disaster_delay,         SLE_UINT16),
       
   315 	    SLEG_VAR(_station_tick_ctr,       SLE_UINT16),
       
   316 	    SLEG_VAR(_random_seeds[0][0],     SLE_UINT32),
       
   317 	    SLEG_VAR(_random_seeds[0][1],     SLE_UINT32),
       
   318 	SLEG_CONDVAR(_cur_town_ctr,           SLE_FILE_U8  | SLE_VAR_U32,  0, 9),
       
   319 	SLEG_CONDVAR(_cur_town_ctr,           SLE_UINT32,                 10, SL_MAX_VERSION),
       
   320 	    SLEG_VAR(_cur_player_tick_index,  SLE_FILE_U8  | SLE_VAR_U32),
       
   321 	    SLEG_VAR(_next_competitor_start,  SLE_FILE_U16 | SLE_VAR_U32),
       
   322 	    SLEG_VAR(_trees_tick_ctr,         SLE_UINT8),
       
   323 	SLEG_CONDVAR(_pause,                  SLE_UINT8,                   4, SL_MAX_VERSION),
       
   324 	SLEG_CONDVAR(_cur_town_iter,          SLE_UINT32,                 11, SL_MAX_VERSION),
       
   325 	    SLEG_END()
       
   326 };
       
   327 
       
   328 // Save load date related variables as well as persistent tick counters
       
   329 // XXX: currently some unrelated stuff is just put here
       
   330 static void SaveLoad_DATE(void)
       
   331 {
       
   332 	SlGlobList(_date_desc);
       
   333 }
       
   334 
       
   335 
       
   336 static const SaveLoadGlobVarList _view_desc[] = {
       
   337 	SLEG_CONDVAR(_saved_scrollpos_x,    SLE_FILE_I16 | SLE_VAR_I32, 0, 5),
       
   338 	SLEG_CONDVAR(_saved_scrollpos_x,    SLE_INT32,                  6, SL_MAX_VERSION),
       
   339 	SLEG_CONDVAR(_saved_scrollpos_y,    SLE_FILE_I16 | SLE_VAR_I32, 0, 5),
       
   340 	SLEG_CONDVAR(_saved_scrollpos_y,    SLE_INT32,                  6, SL_MAX_VERSION),
       
   341 	    SLEG_VAR(_saved_scrollpos_zoom, SLE_UINT8),
       
   342 	    SLEG_END()
       
   343 };
       
   344 
       
   345 static void SaveLoad_VIEW(void)
       
   346 {
       
   347 	SlGlobList(_view_desc);
       
   348 }
       
   349 
       
   350 static uint32 _map_dim_x;
       
   351 static uint32 _map_dim_y;
       
   352 
       
   353 static const SaveLoadGlobVarList _map_dimensions[] = {
       
   354 	SLEG_CONDVAR(_map_dim_x, SLE_UINT32, 6, SL_MAX_VERSION),
       
   355 	SLEG_CONDVAR(_map_dim_y, SLE_UINT32, 6, SL_MAX_VERSION),
       
   356 	    SLEG_END()
       
   357 };
       
   358 
       
   359 static void Save_MAPS(void)
       
   360 {
       
   361 	_map_dim_x = MapSizeX();
       
   362 	_map_dim_y = MapSizeY();
       
   363 	SlGlobList(_map_dimensions);
       
   364 }
       
   365 
       
   366 static void Load_MAPS(void)
       
   367 {
       
   368 	SlGlobList(_map_dimensions);
       
   369 	AllocateMap(_map_dim_x, _map_dim_y);
       
   370 }
       
   371 
       
   372 static void Load_MAPT(void)
       
   373 {
       
   374 	uint size = MapSize();
       
   375 	uint i;
       
   376 
       
   377 	for (i = 0; i != size;) {
       
   378 		byte buf[4096];
       
   379 		uint j;
       
   380 
       
   381 		SlArray(buf, lengthof(buf), SLE_UINT8);
       
   382 		for (j = 0; j != lengthof(buf); j++) _m[i++].type_height = buf[j];
       
   383 	}
       
   384 }
       
   385 
       
   386 static void Save_MAPT(void)
       
   387 {
       
   388 	uint size = MapSize();
       
   389 	uint i;
       
   390 
       
   391 	SlSetLength(size);
       
   392 	for (i = 0; i != size;) {
       
   393 		byte buf[4096];
       
   394 		uint j;
       
   395 
       
   396 		for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].type_height;
       
   397 		SlArray(buf, lengthof(buf), SLE_UINT8);
       
   398 	}
       
   399 }
       
   400 
       
   401 static void Load_MAP1(void)
       
   402 {
       
   403 	uint size = MapSize();
       
   404 	uint i;
       
   405 
       
   406 	for (i = 0; i != size;) {
       
   407 		byte buf[4096];
       
   408 		uint j;
       
   409 
       
   410 		SlArray(buf, lengthof(buf), SLE_UINT8);
       
   411 		for (j = 0; j != lengthof(buf); j++) _m[i++].m1 = buf[j];
       
   412 	}
       
   413 }
       
   414 
       
   415 static void Save_MAP1(void)
       
   416 {
       
   417 	uint size = MapSize();
       
   418 	uint i;
       
   419 
       
   420 	SlSetLength(size);
       
   421 	for (i = 0; i != size;) {
       
   422 		byte buf[4096];
       
   423 		uint j;
       
   424 
       
   425 		for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m1;
       
   426 		SlArray(buf, lengthof(buf), SLE_UINT8);
       
   427 	}
       
   428 }
       
   429 
       
   430 static void Load_MAP2(void)
       
   431 {
       
   432 	uint size = MapSize();
       
   433 	uint i;
       
   434 
       
   435 	for (i = 0; i != size;) {
       
   436 		uint16 buf[4096];
       
   437 		uint j;
       
   438 
       
   439 		SlArray(buf, lengthof(buf),
       
   440 			/* In those versions the m2 was 8 bits */
       
   441 			CheckSavegameVersion(5) ? SLE_FILE_U8 | SLE_VAR_U16 : SLE_UINT16
       
   442 		);
       
   443 		for (j = 0; j != lengthof(buf); j++) _m[i++].m2 = buf[j];
       
   444 	}
       
   445 }
       
   446 
       
   447 static void Save_MAP2(void)
       
   448 {
       
   449 	uint size = MapSize();
       
   450 	uint i;
       
   451 
       
   452 	SlSetLength(size * sizeof(_m[0].m2));
       
   453 	for (i = 0; i != size;) {
       
   454 		uint16 buf[4096];
       
   455 		uint j;
       
   456 
       
   457 		for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m2;
       
   458 		SlArray(buf, lengthof(buf), SLE_UINT16);
       
   459 	}
       
   460 }
       
   461 
       
   462 static void Load_MAP3(void)
       
   463 {
       
   464 	uint size = MapSize();
       
   465 	uint i;
       
   466 
       
   467 	for (i = 0; i != size;) {
       
   468 		byte buf[4096];
       
   469 		uint j;
       
   470 
       
   471 		SlArray(buf, lengthof(buf), SLE_UINT8);
       
   472 		for (j = 0; j != lengthof(buf); j++) _m[i++].m3 = buf[j];
       
   473 	}
       
   474 }
       
   475 
       
   476 static void Save_MAP3(void)
       
   477 {
       
   478 	uint size = MapSize();
       
   479 	uint i;
       
   480 
       
   481 	SlSetLength(size);
       
   482 	for (i = 0; i != size;) {
       
   483 		byte buf[4096];
       
   484 		uint j;
       
   485 
       
   486 		for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m3;
       
   487 		SlArray(buf, lengthof(buf), SLE_UINT8);
       
   488 	}
       
   489 }
       
   490 
       
   491 static void Load_MAP4(void)
       
   492 {
       
   493 	uint size = MapSize();
       
   494 	uint i;
       
   495 
       
   496 	for (i = 0; i != size;) {
       
   497 		byte buf[4096];
       
   498 		uint j;
       
   499 
       
   500 		SlArray(buf, lengthof(buf), SLE_UINT8);
       
   501 		for (j = 0; j != lengthof(buf); j++) _m[i++].m4 = buf[j];
       
   502 	}
       
   503 }
       
   504 
       
   505 static void Save_MAP4(void)
       
   506 {
       
   507 	uint size = MapSize();
       
   508 	uint i;
       
   509 
       
   510 	SlSetLength(size);
       
   511 	for (i = 0; i != size;) {
       
   512 		byte buf[4096];
       
   513 		uint j;
       
   514 
       
   515 		for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m4;
       
   516 		SlArray(buf, lengthof(buf), SLE_UINT8);
       
   517 	}
       
   518 }
       
   519 
       
   520 static void Load_MAP5(void)
       
   521 {
       
   522 	uint size = MapSize();
       
   523 	uint i;
       
   524 
       
   525 	for (i = 0; i != size;) {
       
   526 		byte buf[4096];
       
   527 		uint j;
       
   528 
       
   529 		SlArray(buf, lengthof(buf), SLE_UINT8);
       
   530 		for (j = 0; j != lengthof(buf); j++) _m[i++].m5 = buf[j];
       
   531 	}
       
   532 }
       
   533 
       
   534 static void Save_MAP5(void)
       
   535 {
       
   536 	uint size = MapSize();
       
   537 	uint i;
       
   538 
       
   539 	SlSetLength(size);
       
   540 	for (i = 0; i != size;) {
       
   541 		byte buf[4096];
       
   542 		uint j;
       
   543 
       
   544 		for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m5;
       
   545 		SlArray(buf, lengthof(buf), SLE_UINT8);
       
   546 	}
       
   547 }
       
   548 
       
   549 static void Load_MAPE(void)
       
   550 {
       
   551 	uint size = MapSize();
       
   552 	uint i;
       
   553 
       
   554 	if (CheckSavegameVersion(42)) {
       
   555 		for (i = 0; i != size;) {
       
   556 			uint8 buf[1024];
       
   557 			uint j;
       
   558 
       
   559 			SlArray(buf, lengthof(buf), SLE_UINT8);
       
   560 			for (j = 0; j != lengthof(buf); j++) {
       
   561 				_m[i++].extra = GB(buf[j], 0, 2);
       
   562 				_m[i++].extra = GB(buf[j], 2, 2);
       
   563 				_m[i++].extra = GB(buf[j], 4, 2);
       
   564 				_m[i++].extra = GB(buf[j], 6, 2);
       
   565 			}
       
   566 		}
       
   567 	} else {
       
   568 		for (i = 0; i != size;) {
       
   569 			byte buf[4096];
       
   570 			uint j;
       
   571 
       
   572 			SlArray(buf, lengthof(buf), SLE_UINT8);
       
   573 			for (j = 0; j != lengthof(buf); j++) _m[i++].extra = buf[j];
       
   574 		}
       
   575 	}
       
   576 }
       
   577 
       
   578 static void Save_MAPE(void)
       
   579 {
       
   580 	uint size = MapSize();
       
   581 	uint i;
       
   582 
       
   583 	SlSetLength(size);
       
   584 	for (i = 0; i != size;) {
       
   585 		uint8 buf[4096];
       
   586 		uint j;
       
   587 
       
   588 		for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].extra;
       
   589 		SlArray(buf, lengthof(buf), SLE_UINT8);
       
   590 	}
       
   591 }
       
   592 
       
   593 
       
   594 static void Save_CHTS(void)
       
   595 {
       
   596 	byte count = sizeof(_cheats)/sizeof(Cheat);
       
   597 	Cheat* cht = (Cheat*) &_cheats;
       
   598 	Cheat* cht_last = &cht[count];
       
   599 
       
   600 	SlSetLength(count * 2);
       
   601 	for (; cht != cht_last; cht++) {
       
   602 		SlWriteByte(cht->been_used);
       
   603 		SlWriteByte(cht->value);
       
   604 	}
       
   605 }
       
   606 
       
   607 static void Load_CHTS(void)
       
   608 {
       
   609 	Cheat* cht = (Cheat*)&_cheats;
       
   610 	uint count = SlGetFieldLength() / 2;
       
   611 	uint i;
       
   612 
       
   613 	for (i = 0; i < count; i++) {
       
   614 		cht[i].been_used = SlReadByte();
       
   615 		cht[i].value     = SlReadByte();
       
   616 	}
       
   617 }
       
   618 
       
   619 
       
   620 const ChunkHandler _misc_chunk_handlers[] = {
       
   621 	{ 'MAPS', Save_MAPS,     Load_MAPS,     CH_RIFF },
       
   622 	{ 'MAPT', Save_MAPT,     Load_MAPT,     CH_RIFF },
       
   623 	{ 'MAPO', Save_MAP1,     Load_MAP1,     CH_RIFF },
       
   624 	{ 'MAP2', Save_MAP2,     Load_MAP2,     CH_RIFF },
       
   625 	{ 'M3LO', Save_MAP3,     Load_MAP3,     CH_RIFF },
       
   626 	{ 'M3HI', Save_MAP4,     Load_MAP4,     CH_RIFF },
       
   627 	{ 'MAP5', Save_MAP5,     Load_MAP5,     CH_RIFF },
       
   628 	{ 'MAPE', Save_MAPE,     Load_MAPE,     CH_RIFF },
       
   629 
       
   630 	{ 'NAME', Save_NAME,     Load_NAME,     CH_ARRAY},
       
   631 	{ 'DATE', SaveLoad_DATE, SaveLoad_DATE, CH_RIFF},
       
   632 	{ 'VIEW', SaveLoad_VIEW, SaveLoad_VIEW, CH_RIFF},
       
   633 	{ 'CHTS', Save_CHTS,     Load_CHTS,     CH_RIFF | CH_LAST}
       
   634 };