1 /**
2  * @file loadsave.cpp
3  *
4  * Implementation of save game functionality.
5  */
6 #include "all.h"
7 
8 DEVILUTION_BEGIN_NAMESPACE
9 
10 bool gbIsHellfireSaveGame;
11 int giNumberOfLevels;
12 int giNumberQuests;
13 int giNumberOfSmithPremiumItems;
14 
15 namespace {
16 
17 template <class T>
SwapLE(T in)18 T SwapLE(T in)
19 {
20 	switch (sizeof(T)) {
21 	case 2:
22 		return SDL_SwapLE16(in);
23 	case 4:
24 		return SDL_SwapLE32(in);
25 	case 8:
26 		return SDL_SwapLE64(in);
27 	default:
28 		return in;
29 	}
30 }
31 
32 template <class T>
SwapBE(T in)33 T SwapBE(T in)
34 {
35 	switch (sizeof(T)) {
36 	case 2:
37 		return SDL_SwapBE16(in);
38 	case 4:
39 		return SDL_SwapBE32(in);
40 	case 8:
41 		return SDL_SwapBE64(in);
42 	default:
43 		return in;
44 	}
45 }
46 
47 class LoadHelper {
48 	Uint8 *m_buffer;
49 	Uint32 m_bufferPtr = 0;
50 	Uint32 m_bufferLen;
51 
52 	template <class T>
next()53 	T next()
54 	{
55 		const auto size = sizeof(T);
56 		if (!isValid(size))
57 			return 0;
58 
59 		T value;
60 		memcpy(&value, &m_buffer[m_bufferPtr], size);
61 		m_bufferPtr += size;
62 
63 		return value;
64 	}
65 
66 public:
LoadHelper(const char * szFileName)67 	LoadHelper(const char *szFileName)
68 	{
69 		m_buffer = pfile_read(szFileName, &m_bufferLen);
70 	}
71 
isValid(Uint32 size=1)72 	bool isValid(Uint32 size = 1)
73 	{
74 		return m_buffer != nullptr
75 		    && m_bufferLen >= (m_bufferPtr + size);
76 	}
77 
skip(Uint32 size)78 	void skip(Uint32 size)
79 	{
80 		m_bufferPtr += size;
81 	}
82 
nextBytes(void * bytes,size_t size)83 	void nextBytes(void *bytes, size_t size)
84 	{
85 		if (!isValid(size))
86 			return;
87 
88 		memcpy(bytes, &m_buffer[m_bufferPtr], size);
89 		m_bufferPtr += size;
90 	}
91 
92 	template <class T>
nextLE()93 	T nextLE()
94 	{
95 		return SwapLE(next<T>());
96 	}
97 
98 	template <class T>
nextBE()99 	T nextBE()
100 	{
101 		return SwapBE(next<T>());
102 	}
103 
nextBool8()104 	bool nextBool8()
105 	{
106 		return next<Uint8>() != 0;
107 	}
108 
nextBool32()109 	bool nextBool32()
110 	{
111 		return next<Uint32>() != 0;
112 	}
113 
~LoadHelper()114 	~LoadHelper()
115 	{
116 		mem_free_dbg(m_buffer);
117 	}
118 };
119 
120 class SaveHelper {
121 	const char *m_szFileName;
122 	Uint8 *m_buffer;
123 	Uint32 m_bufferPtr = 0;
124 	Uint32 m_bufferLen;
125 
126 public:
SaveHelper(const char * szFileName,size_t bufferLen)127 	SaveHelper(const char *szFileName, size_t bufferLen)
128 	{
129 		m_szFileName = szFileName;
130 		m_bufferLen = bufferLen;
131 		m_buffer = DiabloAllocPtr(codec_get_encoded_len(m_bufferLen));
132 	}
133 
isValid(Uint32 len=1)134 	bool isValid(Uint32 len = 1)
135 	{
136 		return m_buffer != nullptr
137 		    && m_bufferLen >= (m_bufferPtr + len);
138 	}
139 
skip(Uint32 len)140 	void skip(Uint32 len)
141 	{
142 		m_bufferPtr += len;
143 	}
144 
writeBytes(const void * bytes,size_t len)145 	void writeBytes(const void *bytes, size_t len)
146 	{
147 		if (!isValid(len))
148 			return;
149 
150 		memcpy(&m_buffer[m_bufferPtr], bytes, len);
151 		m_bufferPtr += len;
152 	}
153 
154 	template <class T>
writeLE(T value)155 	void writeLE(T value)
156 	{
157 		value = SwapLE(value);
158 		writeBytes(&value, sizeof(value));
159 	}
160 
161 	template <class T>
writeBE(T value)162 	void writeBE(T value)
163 	{
164 		value = SwapBE(value);
165 		writeBytes(&value, sizeof(value));
166 	}
167 
flush()168 	void flush()
169 	{
170 		if (m_buffer == nullptr)
171 			return;
172 
173 		pfile_write_save_file(m_szFileName, m_buffer, m_bufferPtr, codec_get_encoded_len(m_bufferPtr));
174 		mem_free_dbg(m_buffer);
175 		m_buffer = nullptr;
176 	}
177 
~SaveHelper()178 	~SaveHelper()
179 	{
180 		flush();
181 	}
182 };
183 
184 }
185 
RemoveInvalidItem(ItemStruct * pItem)186 void RemoveInvalidItem(ItemStruct *pItem)
187 {
188 	bool isInvalid = !IsItemAvailable(pItem->IDidx) || !IsUniqueAvailable(pItem->_iUid);
189 
190 	if (!gbIsHellfire) {
191 		isInvalid = isInvalid || (pItem->_itype == ITYPE_STAFF && GetSpellStaffLevel(pItem->_iSpell) == -1);
192 		isInvalid = isInvalid || (pItem->_iMiscId == IMISC_BOOK && GetSpellBookLevel(pItem->_iSpell) == -1);
193 		isInvalid = isInvalid || pItem->_iDamAcFlags != 0;
194 		isInvalid = isInvalid || pItem->_iPrePower > IDI_LASTDIABLO;
195 		isInvalid = isInvalid || pItem->_iSufPower > IDI_LASTDIABLO;
196 	}
197 
198 	if (isInvalid) {
199 		pItem->_itype = ITYPE_NONE;
200 	}
201 }
202 
LoadItemData(LoadHelper * file,ItemStruct * pItem)203 static void LoadItemData(LoadHelper *file, ItemStruct *pItem)
204 {
205 	pItem->_iSeed = file->nextLE<Sint32>();
206 	pItem->_iCreateInfo = file->nextLE<Uint16>();
207 	file->skip(2); // Alignment
208 	pItem->_itype = (item_type)file->nextLE<Uint32>();
209 	pItem->_ix = file->nextLE<Sint32>();
210 	pItem->_iy = file->nextLE<Sint32>();
211 	pItem->_iAnimFlag = file->nextBool32();
212 	file->skip(4); // Skip pointer _iAnimData
213 	pItem->_iAnimLen = file->nextLE<Sint32>();
214 	pItem->_iAnimFrame = file->nextLE<Sint32>();
215 	pItem->_iAnimWidth = file->nextLE<Sint32>();
216 	pItem->_iAnimWidth2 = file->nextLE<Sint32>();
217 	file->skip(4); // Unused since 1.02
218 	pItem->_iSelFlag = file->nextLE<Uint8>();
219 	file->skip(3); // Alignment
220 	pItem->_iPostDraw = file->nextBool32();
221 	pItem->_iIdentified = file->nextBool32();
222 	pItem->_iMagical = file->nextLE<Sint8>();
223 	file->nextBytes(pItem->_iName, 64);
224 	file->nextBytes(pItem->_iIName, 64);
225 	pItem->_iLoc = (item_equip_type)file->nextLE<Sint8>();
226 	pItem->_iClass = (item_class)file->nextLE<Uint8>();
227 	file->skip(1); // Alignment
228 	pItem->_iCurs = file->nextLE<Sint32>();
229 	pItem->_ivalue = file->nextLE<Sint32>();
230 	pItem->_iIvalue = file->nextLE<Sint32>();
231 	pItem->_iMinDam = file->nextLE<Sint32>();
232 	pItem->_iMaxDam = file->nextLE<Sint32>();
233 	pItem->_iAC = file->nextLE<Sint32>();
234 	pItem->_iFlags = file->nextLE<Sint32>();
235 	pItem->_iMiscId = (item_misc_id)file->nextLE<Sint32>();
236 	pItem->_iSpell = (spell_id)file->nextLE<Sint32>();
237 	pItem->_iCharges = file->nextLE<Sint32>();
238 	pItem->_iMaxCharges = file->nextLE<Sint32>();
239 	pItem->_iDurability = file->nextLE<Sint32>();
240 	pItem->_iMaxDur = file->nextLE<Sint32>();
241 	pItem->_iPLDam = file->nextLE<Sint32>();
242 	pItem->_iPLToHit = file->nextLE<Sint32>();
243 	pItem->_iPLAC = file->nextLE<Sint32>();
244 	pItem->_iPLStr = file->nextLE<Sint32>();
245 	pItem->_iPLMag = file->nextLE<Sint32>();
246 	pItem->_iPLDex = file->nextLE<Sint32>();
247 	pItem->_iPLVit = file->nextLE<Sint32>();
248 	pItem->_iPLFR = file->nextLE<Sint32>();
249 	pItem->_iPLLR = file->nextLE<Sint32>();
250 	pItem->_iPLMR = file->nextLE<Sint32>();
251 	pItem->_iPLMana = file->nextLE<Sint32>();
252 	pItem->_iPLHP = file->nextLE<Sint32>();
253 	pItem->_iPLDamMod = file->nextLE<Sint32>();
254 	pItem->_iPLGetHit = file->nextLE<Sint32>();
255 	pItem->_iPLLight = file->nextLE<Sint32>();
256 	pItem->_iSplLvlAdd = file->nextLE<Sint8>();
257 	pItem->_iRequest = file->nextLE<Sint8>();
258 	file->skip(2); // Alignment
259 	pItem->_iUid = file->nextLE<Sint32>();
260 	pItem->_iFMinDam = file->nextLE<Sint32>();
261 	pItem->_iFMaxDam = file->nextLE<Sint32>();
262 	pItem->_iLMinDam = file->nextLE<Sint32>();
263 	pItem->_iLMaxDam = file->nextLE<Sint32>();
264 	pItem->_iPLEnAc = file->nextLE<Sint32>();
265 	pItem->_iPrePower = (item_effect_type)file->nextLE<Sint8>();
266 	pItem->_iSufPower = (item_effect_type)file->nextLE<Sint8>();
267 	file->skip(2); // Alignment
268 	pItem->_iVAdd1 = file->nextLE<Sint32>();
269 	pItem->_iVMult1 = file->nextLE<Sint32>();
270 	pItem->_iVAdd2 = file->nextLE<Sint32>();
271 	pItem->_iVMult2 = file->nextLE<Sint32>();
272 	pItem->_iMinStr = file->nextLE<Sint8>();
273 	pItem->_iMinMag = file->nextLE<Uint8>();
274 	pItem->_iMinDex = file->nextLE<Sint8>();
275 	file->skip(1); // Alignment
276 	pItem->_iStatFlag = file->nextBool32();
277 	pItem->IDidx = file->nextLE<Sint32>();
278 	if (!gbIsHellfireSaveGame) {
279 		pItem->IDidx = RemapItemIdxFromDiablo(pItem->IDidx);
280 	}
281 	pItem->dwBuff = file->nextLE<Uint32>();
282 	if (gbIsHellfireSaveGame)
283 		pItem->_iDamAcFlags = file->nextLE<Sint32>();
284 	else
285 		pItem->_iDamAcFlags = 0;
286 
287 	RemoveInvalidItem(pItem);
288 }
289 
LoadItems(LoadHelper * file,const int n,ItemStruct * pItem)290 static void LoadItems(LoadHelper *file, const int n, ItemStruct *pItem)
291 {
292 	for (int i = 0; i < n; i++) {
293 		LoadItemData(file, &pItem[i]);
294 	}
295 }
296 
LoadPlayer(LoadHelper * file,int p)297 static void LoadPlayer(LoadHelper *file, int p)
298 {
299 	PlayerStruct *pPlayer = &plr[p];
300 
301 	pPlayer->_pmode = (PLR_MODE)file->nextLE<Sint32>();
302 
303 	for (int i = 0; i < MAX_PATH_LENGTH; i++) {
304 		pPlayer->walkpath[i] = file->nextLE<Sint8>();
305 	}
306 	pPlayer->plractive = file->nextBool8();
307 	file->skip(2); // Alignment
308 	pPlayer->destAction = (action_id)file->nextLE<Sint32>();
309 	pPlayer->destParam1 = file->nextLE<Sint32>();
310 	pPlayer->destParam2 = file->nextLE<Sint32>();
311 	pPlayer->destParam3 = (direction)file->nextLE<Sint32>();
312 	pPlayer->destParam4 = file->nextLE<Sint32>();
313 	pPlayer->plrlevel = file->nextLE<Sint32>();
314 	pPlayer->_px = file->nextLE<Sint32>();
315 	pPlayer->_py = file->nextLE<Sint32>();
316 	pPlayer->_pfutx = file->nextLE<Sint32>();
317 	pPlayer->_pfuty = file->nextLE<Sint32>();
318 	pPlayer->_ptargx = file->nextLE<Sint32>();
319 	pPlayer->_ptargy = file->nextLE<Sint32>();
320 	pPlayer->_pownerx = file->nextLE<Sint32>();
321 	pPlayer->_pownery = file->nextLE<Sint32>();
322 	pPlayer->_poldx = file->nextLE<Sint32>();
323 	pPlayer->_poldy = file->nextLE<Sint32>();
324 	pPlayer->_pxoff = file->nextLE<Sint32>();
325 	pPlayer->_pyoff = file->nextLE<Sint32>();
326 	pPlayer->_pxvel = file->nextLE<Sint32>();
327 	pPlayer->_pyvel = file->nextLE<Sint32>();
328 	pPlayer->_pdir = (direction)file->nextLE<Sint32>();
329 	file->skip(4); // Unused
330 	pPlayer->_pgfxnum = file->nextLE<Sint32>();
331 	file->skip(4); // Skip pointer _pAnimData
332 	pPlayer->_pAnimDelay = file->nextLE<Sint32>();
333 	pPlayer->_pAnimCnt = file->nextLE<Sint32>();
334 	pPlayer->_pAnimLen = file->nextLE<Sint32>();
335 	pPlayer->_pAnimFrame = file->nextLE<Sint32>();
336 	pPlayer->_pAnimWidth = file->nextLE<Sint32>();
337 	pPlayer->_pAnimWidth2 = file->nextLE<Sint32>();
338 	file->skip(4); // Skip _peflag
339 	pPlayer->_plid = file->nextLE<Sint32>();
340 	pPlayer->_pvid = file->nextLE<Sint32>();
341 
342 	pPlayer->_pSpell = (spell_id)file->nextLE<Sint32>();
343 	pPlayer->_pSplType = (spell_type)file->nextLE<Sint8>();
344 	pPlayer->_pSplFrom = file->nextLE<Sint8>();
345 	file->skip(2); // Alignment
346 	pPlayer->_pTSpell = (spell_id)file->nextLE<Sint32>();
347 	pPlayer->_pTSplType = (spell_type)file->nextLE<Sint8>();
348 	file->skip(3); // Alignment
349 	pPlayer->_pRSpell = (spell_id)file->nextLE<Sint32>();
350 	pPlayer->_pRSplType = (spell_type)file->nextLE<Sint8>();
351 	file->skip(3); // Alignment
352 	pPlayer->_pSBkSpell = (spell_id)file->nextLE<Sint32>();
353 	pPlayer->_pSBkSplType = (spell_type)file->nextLE<Sint8>();
354 	for (int i = 0; i < 64; i++)
355 		pPlayer->_pSplLvl[i] = file->nextLE<Sint8>();
356 	file->skip(7); // Alignment
357 	pPlayer->_pMemSpells = file->nextLE<Uint64>();
358 	pPlayer->_pAblSpells = file->nextLE<Uint64>();
359 	pPlayer->_pScrlSpells = file->nextLE<Uint64>();
360 	pPlayer->_pSpellFlags = file->nextLE<Uint8>();
361 	file->skip(3); // Alignment
362 	for (int i = 0; i < 4; i++)
363 		pPlayer->_pSplHotKey[i] = (spell_id)file->nextLE<Sint32>();
364 	for (int i = 0; i < 4; i++)
365 		pPlayer->_pSplTHotKey[i] = (spell_type)file->nextLE<Sint8>();
366 
367 	pPlayer->_pwtype = (player_weapon_type)file->nextLE<Sint32>();
368 	pPlayer->_pBlockFlag = file->nextBool8();
369 	pPlayer->_pInvincible = file->nextBool8();
370 	pPlayer->_pLightRad = file->nextLE<Sint8>();
371 	pPlayer->_pLvlChanging = file->nextBool8();
372 
373 	file->nextBytes(pPlayer->_pName, PLR_NAME_LEN);
374 	pPlayer->_pClass = (plr_class)file->nextLE<Sint8>();
375 	file->skip(3); // Alignment
376 	pPlayer->_pStrength = file->nextLE<Sint32>();
377 	pPlayer->_pBaseStr = file->nextLE<Sint32>();
378 	pPlayer->_pMagic = file->nextLE<Sint32>();
379 	pPlayer->_pBaseMag = file->nextLE<Sint32>();
380 	pPlayer->_pDexterity = file->nextLE<Sint32>();
381 	pPlayer->_pBaseDex = file->nextLE<Sint32>();
382 	pPlayer->_pVitality = file->nextLE<Sint32>();
383 	pPlayer->_pBaseVit = file->nextLE<Sint32>();
384 	pPlayer->_pStatPts = file->nextLE<Sint32>();
385 	pPlayer->_pDamageMod = file->nextLE<Sint32>();
386 	pPlayer->_pBaseToBlk = file->nextLE<Sint32>();
387 	if (pPlayer->_pBaseToBlk == 0)
388 		pPlayer->_pBaseToBlk = ToBlkTbl[pPlayer->_pClass];
389 	pPlayer->_pHPBase = file->nextLE<Sint32>();
390 	pPlayer->_pMaxHPBase = file->nextLE<Sint32>();
391 	pPlayer->_pHitPoints = file->nextLE<Sint32>();
392 	pPlayer->_pMaxHP = file->nextLE<Sint32>();
393 	pPlayer->_pHPPer = file->nextLE<Sint32>();
394 	pPlayer->_pManaBase = file->nextLE<Sint32>();
395 	pPlayer->_pMaxManaBase = file->nextLE<Sint32>();
396 	pPlayer->_pMana = file->nextLE<Sint32>();
397 	pPlayer->_pMaxMana = file->nextLE<Sint32>();
398 	pPlayer->_pManaPer = file->nextLE<Sint32>();
399 	pPlayer->_pLevel = file->nextLE<Sint8>();
400 	pPlayer->_pMaxLvl = file->nextLE<Sint8>();
401 	file->skip(2); // Alignment
402 	pPlayer->_pExperience = file->nextLE<Sint32>();
403 	pPlayer->_pMaxExp = file->nextLE<Sint32>();
404 	pPlayer->_pNextExper = file->nextLE<Sint32>();
405 	pPlayer->_pArmorClass = file->nextLE<Sint8>();
406 	pPlayer->_pMagResist = file->nextLE<Sint8>();
407 	pPlayer->_pFireResist = file->nextLE<Sint8>();
408 	pPlayer->_pLghtResist = file->nextLE<Sint8>();
409 	pPlayer->_pGold = file->nextLE<Sint32>();
410 
411 	pPlayer->_pInfraFlag = file->nextBool32();
412 	pPlayer->_pVar1 = file->nextLE<Sint32>();
413 	pPlayer->_pVar2 = file->nextLE<Sint32>();
414 	pPlayer->_pVar3 = (direction)file->nextLE<Sint32>();
415 	pPlayer->_pVar4 = file->nextLE<Sint32>();
416 	pPlayer->_pVar5 = file->nextLE<Sint32>();
417 	pPlayer->_pVar6 = file->nextLE<Sint32>();
418 	pPlayer->_pVar7 = file->nextLE<Sint32>();
419 	pPlayer->_pVar8 = file->nextLE<Sint32>();
420 	for (int i = 0; i < giNumberOfLevels; i++)
421 		pPlayer->_pLvlVisited[i] = file->nextBool8();
422 	for (int i = 0; i < giNumberOfLevels; i++)
423 		pPlayer->_pSLvlVisited[i] = file->nextBool8();
424 
425 	file->skip(2); // Alignment
426 
427 	pPlayer->_pGFXLoad = file->nextLE<Sint32>();
428 	file->skip(4 * 8); // Skip pointers _pNAnim
429 	pPlayer->_pNFrames = file->nextLE<Sint32>();
430 	pPlayer->_pNWidth = file->nextLE<Sint32>();
431 	file->skip(4 * 8); // Skip pointers _pWAnim
432 	pPlayer->_pWFrames = file->nextLE<Sint32>();
433 	pPlayer->_pWWidth = file->nextLE<Sint32>();
434 	file->skip(4 * 8); // Skip pointers _pAAnim
435 	pPlayer->_pAFrames = file->nextLE<Sint32>();
436 	pPlayer->_pAWidth = file->nextLE<Sint32>();
437 	pPlayer->_pAFNum = file->nextLE<Sint32>();
438 	file->skip(4 * 8); // Skip pointers _pLAnim
439 	file->skip(4 * 8); // Skip pointers _pFAnim
440 	file->skip(4 * 8); // Skip pointers _pTAnim
441 	pPlayer->_pSFrames = file->nextLE<Sint32>();
442 	pPlayer->_pSWidth = file->nextLE<Sint32>();
443 	pPlayer->_pSFNum = file->nextLE<Sint32>();
444 	file->skip(4 * 8); // Skip pointers _pHAnim
445 	pPlayer->_pHFrames = file->nextLE<Sint32>();
446 	pPlayer->_pHWidth = file->nextLE<Sint32>();
447 	file->skip(4 * 8); // Skip pointers _pDAnim
448 	pPlayer->_pDFrames = file->nextLE<Sint32>();
449 	pPlayer->_pDWidth = file->nextLE<Sint32>();
450 	file->skip(4 * 8); // Skip pointers _pBAnim
451 	pPlayer->_pBFrames = file->nextLE<Sint32>();
452 	pPlayer->_pBWidth = file->nextLE<Sint32>();
453 
454 	LoadItems(file, NUM_INVLOC, pPlayer->InvBody);
455 	LoadItems(file, NUM_INV_GRID_ELEM, pPlayer->InvList);
456 	pPlayer->_pNumInv = file->nextLE<Sint32>();
457 	for (int i = 0; i < NUM_INV_GRID_ELEM; i++)
458 		pPlayer->InvGrid[i] = file->nextLE<Sint8>();
459 	LoadItems(file, MAXBELTITEMS, pPlayer->SpdList);
460 	LoadItemData(file, &pPlayer->HoldItem);
461 
462 	pPlayer->_pIMinDam = file->nextLE<Sint32>();
463 	pPlayer->_pIMaxDam = file->nextLE<Sint32>();
464 	pPlayer->_pIAC = file->nextLE<Sint32>();
465 	pPlayer->_pIBonusDam = file->nextLE<Sint32>();
466 	pPlayer->_pIBonusToHit = file->nextLE<Sint32>();
467 	pPlayer->_pIBonusAC = file->nextLE<Sint32>();
468 	pPlayer->_pIBonusDamMod = file->nextLE<Sint32>();
469 	file->skip(4); // Alignment
470 
471 	pPlayer->_pISpells = file->nextLE<Uint64>();
472 	pPlayer->_pIFlags = file->nextLE<Sint32>();
473 	pPlayer->_pIGetHit = file->nextLE<Sint32>();
474 	pPlayer->_pISplLvlAdd = file->nextLE<Sint8>();
475 	file->skip(1); // Unused
476 	file->skip(2); // Alignment
477 	pPlayer->_pISplDur = file->nextLE<Sint32>();
478 	pPlayer->_pIEnAc = file->nextLE<Sint32>();
479 	pPlayer->_pIFMinDam = file->nextLE<Sint32>();
480 	pPlayer->_pIFMaxDam = file->nextLE<Sint32>();
481 	pPlayer->_pILMinDam = file->nextLE<Sint32>();
482 	pPlayer->_pILMaxDam = file->nextLE<Sint32>();
483 	pPlayer->_pOilType = (item_misc_id)file->nextLE<Sint32>();
484 	pPlayer->pTownWarps = file->nextLE<Uint8>();
485 	pPlayer->pDungMsgs = file->nextLE<Uint8>();
486 	pPlayer->pLvlLoad = file->nextLE<Uint8>();
487 
488 	if (gbIsHellfireSaveGame) {
489 		pPlayer->pDungMsgs2 = file->nextLE<Uint8>();
490 		pPlayer->pBattleNet = false;
491 	} else {
492 		pPlayer->pDungMsgs2 = 0;
493 		pPlayer->pBattleNet = file->nextBool8();
494 	}
495 	pPlayer->pManaShield = file->nextBool8();
496 	if (gbIsHellfireSaveGame) {
497 		pPlayer->pOriginalCathedral = file->nextBool8();
498 	} else {
499 		file->skip(1);
500 		pPlayer->pOriginalCathedral = true;
501 	}
502 	file->skip(2); // Available bytes
503 	pPlayer->wReflections = file->nextLE<Uint16>();
504 	file->skip(14); // Available bytes
505 
506 	pPlayer->pDiabloKillLevel = file->nextLE<Uint32>();
507 	pPlayer->pDifficulty = file->nextLE<Uint32>();
508 	pPlayer->pDamAcFlags = file->nextLE<Uint32>();
509 	file->skip(20); // Available bytes
510 	CalcPlrItemVals(p, FALSE);
511 
512 	// Omit pointer _pNData
513 	// Omit pointer _pWData
514 	// Omit pointer _pAData
515 	// Omit pointer _pLData
516 	// Omit pointer _pFData
517 	// Omit pointer  _pTData
518 	// Omit pointer _pHData
519 	// Omit pointer _pDData
520 	// Omit pointer _pBData
521 	// Omit pointer pReserved
522 }
523 
524 bool gbSkipSync = false;
525 
LoadMonster(LoadHelper * file,int i)526 static void LoadMonster(LoadHelper *file, int i)
527 {
528 	MonsterStruct *pMonster = &monster[i];
529 
530 	pMonster->_mMTidx = file->nextLE<Sint32>();
531 	pMonster->_mmode = (MON_MODE)file->nextLE<Sint32>();
532 	pMonster->_mgoal = file->nextLE<Uint8>();
533 	file->skip(3); // Alignment
534 	pMonster->_mgoalvar1 = file->nextLE<Sint32>();
535 	pMonster->_mgoalvar2 = file->nextLE<Sint32>();
536 	pMonster->_mgoalvar3 = file->nextLE<Sint32>();
537 	file->skip(4); // Unused
538 	pMonster->_pathcount = file->nextLE<Uint8>();
539 	file->skip(3); // Alignment
540 	pMonster->_mx = file->nextLE<Sint32>();
541 	pMonster->_my = file->nextLE<Sint32>();
542 	pMonster->_mfutx = file->nextLE<Sint32>();
543 	pMonster->_mfuty = file->nextLE<Sint32>();
544 	pMonster->_moldx = file->nextLE<Sint32>();
545 	pMonster->_moldy = file->nextLE<Sint32>();
546 	pMonster->_mxoff = file->nextLE<Sint32>();
547 	pMonster->_myoff = file->nextLE<Sint32>();
548 	pMonster->_mxvel = file->nextLE<Sint32>();
549 	pMonster->_myvel = file->nextLE<Sint32>();
550 	pMonster->_mdir = file->nextLE<Sint32>();
551 	pMonster->_menemy = file->nextLE<Sint32>();
552 	pMonster->_menemyx = file->nextLE<Uint8>();
553 	pMonster->_menemyy = file->nextLE<Uint8>();
554 	file->skip(2); // Unused
555 
556 	file->skip(4); // Skip pointer _mAnimData
557 	pMonster->_mAnimDelay = file->nextLE<Sint32>();
558 	pMonster->_mAnimCnt = file->nextLE<Sint32>();
559 	pMonster->_mAnimLen = file->nextLE<Sint32>();
560 	pMonster->_mAnimFrame = file->nextLE<Sint32>();
561 	file->skip(4); // Skip _meflag
562 	pMonster->_mDelFlag = file->nextBool32();
563 	pMonster->_mVar1 = file->nextLE<Sint32>();
564 	pMonster->_mVar2 = file->nextLE<Sint32>();
565 	pMonster->_mVar3 = file->nextLE<Sint32>();
566 	pMonster->_mVar4 = file->nextLE<Sint32>();
567 	pMonster->_mVar5 = file->nextLE<Sint32>();
568 	pMonster->_mVar6 = file->nextLE<Sint32>();
569 	pMonster->_mVar7 = file->nextLE<Sint32>();
570 	pMonster->_mVar8 = file->nextLE<Sint32>();
571 	pMonster->_mmaxhp = file->nextLE<Sint32>();
572 	pMonster->_mhitpoints = file->nextLE<Sint32>();
573 
574 	pMonster->_mAi = (_mai_id)file->nextLE<Uint8>();
575 	pMonster->_mint = file->nextLE<Uint8>();
576 	file->skip(2); // Alignment
577 	pMonster->_mFlags = file->nextLE<Uint32>();
578 	pMonster->_msquelch = file->nextLE<Uint8>();
579 	file->skip(3); // Alignment
580 	file->skip(4); // Unused
581 	pMonster->_lastx = file->nextLE<Sint32>();
582 	pMonster->_lasty = file->nextLE<Sint32>();
583 	pMonster->_mRndSeed = file->nextLE<Sint32>();
584 	pMonster->_mAISeed = file->nextLE<Sint32>();
585 	file->skip(4); // Unused
586 
587 	pMonster->_uniqtype = file->nextLE<Uint8>();
588 	pMonster->_uniqtrans = file->nextLE<Uint8>();
589 	pMonster->_udeadval = file->nextLE<Sint8>();
590 
591 	pMonster->mWhoHit = file->nextLE<Sint8>();
592 	pMonster->mLevel = file->nextLE<Sint8>();
593 	file->skip(1); // Alignment
594 	pMonster->mExp = file->nextLE<Uint16>();
595 
596 	file->skip(1); // Skip mHit as it's already initialized
597 	pMonster->mMinDamage = file->nextLE<Uint8>();
598 	pMonster->mMaxDamage = file->nextLE<Uint8>();
599 	file->skip(1); // Skip mHit2 as it's already initialized
600 	pMonster->mMinDamage2 = file->nextLE<Uint8>();
601 	pMonster->mMaxDamage2 = file->nextLE<Uint8>();
602 	pMonster->mArmorClass = file->nextLE<Uint8>();
603 	file->skip(1); // Alignment
604 	pMonster->mMagicRes = file->nextLE<Uint16>();
605 	file->skip(2); // Alignment
606 
607 	pMonster->mtalkmsg = file->nextLE<Sint32>();
608 	pMonster->leader = file->nextLE<Uint8>();
609 	pMonster->leaderflag = file->nextLE<Uint8>();
610 	pMonster->packsize = file->nextLE<Uint8>();
611 	pMonster->mlid = file->nextLE<Sint8>();
612 	if (pMonster->mlid == plr[myplr]._plid)
613 		pMonster->mlid = NO_LIGHT; // Correct incorect values in old saves
614 
615 	// Omit pointer mName;
616 	// Omit pointer MType;
617 	// Omit pointer MData;
618 
619 	if (gbSkipSync)
620 		return;
621 
622 	SyncMonsterAnim(i);
623 }
624 
LoadMissile(LoadHelper * file,int i)625 static void LoadMissile(LoadHelper *file, int i)
626 {
627 	MissileStruct *pMissile = &missile[i];
628 
629 	pMissile->_mitype = file->nextLE<Sint32>();
630 	pMissile->_mix = file->nextLE<Sint32>();
631 	pMissile->_miy = file->nextLE<Sint32>();
632 	pMissile->_mixoff = file->nextLE<Sint32>();
633 	pMissile->_miyoff = file->nextLE<Sint32>();
634 	pMissile->_mixvel = file->nextLE<Sint32>();
635 	pMissile->_miyvel = file->nextLE<Sint32>();
636 	pMissile->_misx = file->nextLE<Sint32>();
637 	pMissile->_misy = file->nextLE<Sint32>();
638 	pMissile->_mitxoff = file->nextLE<Sint32>();
639 	pMissile->_mityoff = file->nextLE<Sint32>();
640 	pMissile->_mimfnum = file->nextLE<Sint32>();
641 	pMissile->_mispllvl = file->nextLE<Sint32>();
642 	pMissile->_miDelFlag = file->nextBool32();
643 	pMissile->_miAnimType = file->nextLE<Uint8>();
644 	file->skip(3); // Alignment
645 	pMissile->_miAnimFlags = file->nextLE<Sint32>();
646 	file->skip(4); // Skip pointer _miAnimData
647 	pMissile->_miAnimDelay = file->nextLE<Sint32>();
648 	pMissile->_miAnimLen = file->nextLE<Sint32>();
649 	pMissile->_miAnimWidth = file->nextLE<Sint32>();
650 	pMissile->_miAnimWidth2 = file->nextLE<Sint32>();
651 	pMissile->_miAnimCnt = file->nextLE<Sint32>();
652 	pMissile->_miAnimAdd = file->nextLE<Sint32>();
653 	pMissile->_miAnimFrame = file->nextLE<Sint32>();
654 	pMissile->_miDrawFlag = file->nextBool32();
655 	pMissile->_miLightFlag = file->nextBool32();
656 	pMissile->_miPreFlag = file->nextBool32();
657 	pMissile->_miUniqTrans = file->nextLE<Uint32>();
658 	pMissile->_mirange = file->nextLE<Sint32>();
659 	pMissile->_misource = file->nextLE<Sint32>();
660 	pMissile->_micaster = file->nextLE<Sint32>();
661 	pMissile->_midam = file->nextLE<Sint32>();
662 	pMissile->_miHitFlag = file->nextBool32();
663 	pMissile->_midist = file->nextLE<Sint32>();
664 	pMissile->_mlid = file->nextLE<Sint32>();
665 	pMissile->_mirnd = file->nextLE<Sint32>();
666 	pMissile->_miVar1 = file->nextLE<Sint32>();
667 	pMissile->_miVar2 = file->nextLE<Sint32>();
668 	pMissile->_miVar3 = file->nextLE<Sint32>();
669 	pMissile->_miVar4 = file->nextLE<Sint32>();
670 	pMissile->_miVar5 = file->nextLE<Sint32>();
671 	pMissile->_miVar6 = file->nextLE<Sint32>();
672 	pMissile->_miVar7 = file->nextLE<Sint32>();
673 	pMissile->_miVar8 = file->nextLE<Sint32>();
674 }
675 
LoadObject(LoadHelper * file,int i)676 static void LoadObject(LoadHelper *file, int i)
677 {
678 	ObjectStruct *pObject = &object[i];
679 
680 	pObject->_otype = file->nextLE<Sint32>();
681 	pObject->_ox = file->nextLE<Sint32>();
682 	pObject->_oy = file->nextLE<Sint32>();
683 	pObject->_oLight = file->nextBool32();
684 	pObject->_oAnimFlag = file->nextLE<Uint32>();
685 	file->skip(4); // Skip pointer _oAnimData
686 	pObject->_oAnimDelay = file->nextLE<Sint32>();
687 	pObject->_oAnimCnt = file->nextLE<Sint32>();
688 	pObject->_oAnimLen = file->nextLE<Sint32>();
689 	pObject->_oAnimFrame = file->nextLE<Sint32>();
690 	pObject->_oAnimWidth = file->nextLE<Sint32>();
691 	pObject->_oAnimWidth2 = file->nextLE<Sint32>();
692 	pObject->_oDelFlag = file->nextBool32();
693 	pObject->_oBreak = file->nextLE<Sint8>();
694 	file->skip(3); // Alignment
695 	pObject->_oSolidFlag = file->nextBool32();
696 	pObject->_oMissFlag = file->nextBool32();
697 
698 	pObject->_oSelFlag = file->nextLE<Sint8>();
699 	file->skip(3); // Alignment
700 	pObject->_oPreFlag = file->nextBool32();
701 	pObject->_oTrapFlag = file->nextBool32();
702 	pObject->_oDoorFlag = file->nextBool32();
703 	pObject->_olid = file->nextLE<Sint32>();
704 	pObject->_oRndSeed = file->nextLE<Sint32>();
705 	pObject->_oVar1 = file->nextLE<Sint32>();
706 	pObject->_oVar2 = file->nextLE<Sint32>();
707 	pObject->_oVar3 = file->nextLE<Sint32>();
708 	pObject->_oVar4 = file->nextLE<Sint32>();
709 	pObject->_oVar5 = file->nextLE<Sint32>();
710 	pObject->_oVar6 = file->nextLE<Sint32>();
711 	pObject->_oVar7 = (_speech_id)file->nextLE<Sint32>();
712 	pObject->_oVar8 = file->nextLE<Sint32>();
713 }
714 
LoadItem(LoadHelper * file,int i)715 static void LoadItem(LoadHelper *file, int i)
716 {
717 	LoadItemData(file, &item[i]);
718 	GetItemFrm(i);
719 }
720 
LoadPremium(LoadHelper * file,int i)721 static void LoadPremium(LoadHelper *file, int i)
722 {
723 	LoadItemData(file, &premiumitem[i]);
724 }
725 
LoadQuest(LoadHelper * file,int i)726 static void LoadQuest(LoadHelper *file, int i)
727 {
728 	QuestStruct *pQuest = &quests[i];
729 
730 	pQuest->_qlevel = file->nextLE<Uint8>();
731 	pQuest->_qtype = file->nextLE<Uint8>();
732 	pQuest->_qactive = file->nextLE<Uint8>();
733 	pQuest->_qlvltype = (dungeon_type)file->nextLE<Uint8>();
734 	pQuest->_qtx = file->nextLE<Sint32>();
735 	pQuest->_qty = file->nextLE<Sint32>();
736 	pQuest->_qslvl = file->nextLE<Uint8>();
737 	pQuest->_qidx = file->nextLE<Uint8>();
738 	if (gbIsHellfireSaveGame) {
739 		file->skip(2); // Alignment
740 		pQuest->_qmsg = file->nextLE<Sint32>();
741 	} else {
742 		pQuest->_qmsg = file->nextLE<Uint8>();
743 	}
744 	pQuest->_qvar1 = file->nextLE<Uint8>();
745 	pQuest->_qvar2 = file->nextLE<Uint8>();
746 	file->skip(2); // Alignment
747 	if (!gbIsHellfireSaveGame)
748 		file->skip(1); // Alignment
749 	pQuest->_qlog = file->nextBool32();
750 
751 	ReturnLvlX = file->nextBE<Sint32>();
752 	ReturnLvlY = file->nextBE<Sint32>();
753 	ReturnLvl = file->nextBE<Sint32>();
754 	ReturnLvlT = (dungeon_type)file->nextBE<Sint32>();
755 	DoomQuestState = file->nextBE<Sint32>();
756 }
757 
LoadLighting(LoadHelper * file,LightListStruct * pLight)758 static void LoadLighting(LoadHelper *file, LightListStruct *pLight)
759 {
760 	pLight->_lx = file->nextLE<Sint32>();
761 	pLight->_ly = file->nextLE<Sint32>();
762 	pLight->_lradius = file->nextLE<Sint32>();
763 	pLight->_lid = file->nextLE<Sint32>();
764 	pLight->_ldel = file->nextBool32();
765 	pLight->_lunflag = file->nextBool32();
766 	file->skip(4); // Unused
767 	pLight->_lunx = file->nextLE<Sint32>();
768 	pLight->_luny = file->nextLE<Sint32>();
769 	pLight->_lunr = file->nextLE<Sint32>();
770 	pLight->_xoff = file->nextLE<Sint32>();
771 	pLight->_yoff = file->nextLE<Sint32>();
772 	pLight->_lflags = file->nextBool32();
773 }
774 
LoadPortal(LoadHelper * file,int i)775 static void LoadPortal(LoadHelper *file, int i)
776 {
777 	PortalStruct *pPortal = &portal[i];
778 
779 	pPortal->open = file->nextBool32();
780 	pPortal->x = file->nextLE<Sint32>();
781 	pPortal->y = file->nextLE<Sint32>();
782 	pPortal->level = file->nextLE<Sint32>();
783 	pPortal->ltype = (dungeon_type)file->nextLE<Sint32>();
784 	pPortal->setlvl = file->nextBool32();
785 }
786 
RemapItemIdxFromDiablo(int i)787 int RemapItemIdxFromDiablo(int i)
788 {
789 	if (i == IDI_SORCERER) {
790 		return 166;
791 	}
792 	if (i >= 156) {
793 		i += 5; // Hellfire exclusive items
794 	}
795 	if (i >= 88) {
796 		i += 1; // Scroll of Search
797 	}
798 	if (i >= 83) {
799 		i += 4; // Oils
800 	}
801 
802 	return i;
803 }
804 
RemapItemIdxToDiablo(int i)805 int RemapItemIdxToDiablo(int i)
806 {
807 	if (i == 166) {
808 		return IDI_SORCERER;
809 	}
810 	if ((i >= 83 && i <= 86) || i == 92 || i >= 161) {
811 		return -1; // Hellfire exclusive items
812 	}
813 	if (i >= 93) {
814 		i -= 1; // Scroll of Search
815 	}
816 	if (i >= 87) {
817 		i -= 4; // Oils
818 	}
819 
820 	return i;
821 }
822 
IsHeaderValid(Uint32 magicNumber)823 bool IsHeaderValid(Uint32 magicNumber)
824 {
825 	gbIsHellfireSaveGame = false;
826 	if (magicNumber == LOAD_LE32("SHAR")) {
827 		return true;
828 	} else if (magicNumber == LOAD_LE32("SHLF")) {
829 		gbIsHellfireSaveGame = true;
830 		return true;
831 	} else if (!gbIsSpawn && magicNumber == LOAD_LE32("RETL")) {
832 		return true;
833 	} else if (!gbIsSpawn && magicNumber == LOAD_LE32("HELF")) {
834 		gbIsHellfireSaveGame = true;
835 		return true;
836 	}
837 
838 	return false;
839 }
840 
ConvertLevels()841 static void ConvertLevels()
842 {
843 	// Backup current level state
844 	bool _setlevel = setlevel;
845 	int _setlvlnum = setlvlnum;
846 	int _currlevel = currlevel;
847 	dungeon_type _leveltype = leveltype;
848 
849 	gbSkipSync = true;
850 
851 	setlevel = false; // Convert regular levels
852 	for (int i = 0; i < giNumberOfLevels; i++) {
853 		currlevel = i;
854 		if (!LevelFileExists())
855 			continue;
856 
857 		leveltype = gnLevelTypeTbl[i];
858 
859 		LoadLevel();
860 		SaveLevel();
861 	}
862 
863 	setlevel = true; // Convert quest levels
864 	for (int i = 0; i < MAXQUESTS; i++) {
865 		if (quests[i]._qactive == QUEST_NOTAVAIL) {
866 			continue;
867 		}
868 
869 		leveltype = quests[i]._qlvltype;
870 		if (leveltype == DTYPE_NONE) {
871 			continue;
872 		}
873 
874 		setlvlnum = quests[i]._qslvl;
875 		if (!LevelFileExists())
876 			continue;
877 
878 		LoadLevel();
879 		SaveLevel();
880 	}
881 
882 	gbSkipSync = false;
883 
884 	// Restor current level state
885 	setlevel = _setlevel;
886 	setlvlnum = _setlvlnum;
887 	currlevel = _currlevel;
888 	leveltype = _leveltype;
889 }
890 
LoadHotkeys()891 void LoadHotkeys()
892 {
893 	LoadHelper file("hotkeys");
894 	if (!file.isValid())
895 		return;
896 
897 	const size_t nHotkeyTypes = sizeof(plr[myplr]._pSplHotKey) / sizeof(plr[myplr]._pSplHotKey[0]);
898 	const size_t nHotkeySpells = sizeof(plr[myplr]._pSplTHotKey) / sizeof(plr[myplr]._pSplTHotKey[0]);
899 
900 	for (size_t i = 0; i < nHotkeyTypes; i++) {
901 		plr[myplr]._pSplHotKey[i] = (spell_id)file.nextLE<Sint32>();
902 	}
903 	for (size_t i = 0; i < nHotkeySpells; i++) {
904 		plr[myplr]._pSplTHotKey[i] = (spell_type)file.nextLE<Sint8>();
905 	}
906 	plr[myplr]._pRSpell = (spell_id)file.nextLE<Sint32>();
907 	plr[myplr]._pRSplType = (spell_type)file.nextLE<Sint8>();
908 }
909 
SaveHotkeys()910 void SaveHotkeys()
911 {
912 	const size_t nHotkeyTypes = sizeof(plr[myplr]._pSplHotKey) / sizeof(plr[myplr]._pSplHotKey[0]);
913 	const size_t nHotkeySpells = sizeof(plr[myplr]._pSplTHotKey) / sizeof(plr[myplr]._pSplTHotKey[0]);
914 
915 	SaveHelper file("hotkeys", (nHotkeyTypes * 4) + nHotkeySpells + 4 + 1);
916 
917 	for (size_t i = 0; i < nHotkeyTypes; i++) {
918 		file.writeLE<Sint32>(plr[myplr]._pSplHotKey[i]);
919 	}
920 	for (size_t i = 0; i < nHotkeySpells; i++) {
921 		file.writeLE<Uint8>(plr[myplr]._pSplTHotKey[i]);
922 	}
923 	file.writeLE<Sint32>(plr[myplr]._pRSpell);
924 	file.writeLE<Uint8>(plr[myplr]._pRSplType);
925 }
926 
LoadMatchingItems(LoadHelper * file,const int n,ItemStruct * pItem)927 static void LoadMatchingItems(LoadHelper *file, const int n, ItemStruct *pItem)
928 {
929 	ItemStruct tempItem;
930 
931 	for (int i = 0; i < n; i++) {
932 		LoadItemData(file, &tempItem);
933 		if (pItem[i].isEmpty() || tempItem.isEmpty())
934 			continue;
935 		if (pItem[i]._iSeed != tempItem._iSeed)
936 			continue;
937 		pItem[i] = tempItem;
938 	}
939 }
940 
LoadHeroItems(PlayerStruct * pPlayer)941 void LoadHeroItems(PlayerStruct *pPlayer)
942 {
943 	LoadHelper file("heroitems");
944 	if (!file.isValid())
945 		return;
946 
947 	gbIsHellfireSaveGame = file.nextBool8();
948 
949 	LoadMatchingItems(&file, NUM_INVLOC, pPlayer->InvBody);
950 	LoadMatchingItems(&file, NUM_INV_GRID_ELEM, pPlayer->InvList);
951 	LoadMatchingItems(&file, MAXBELTITEMS, pPlayer->SpdList);
952 
953 	gbIsHellfireSaveGame = gbIsHellfire;
954 }
955 
RemoveEmptyInventory(int pnum)956 void RemoveEmptyInventory(int pnum)
957 {
958 	for (int i = NUM_INV_GRID_ELEM; i > 0; i--) {
959 		int idx = plr[pnum].InvGrid[i - 1];
960 		if (idx > 0 && plr[pnum].InvList[idx - 1].isEmpty()) {
961 			RemoveInvItem(pnum, idx - 1);
962 		}
963 	};
964 }
965 
RemoveEmptyLevelItems()966 void RemoveEmptyLevelItems()
967 {
968 	for (int i = numitems; i > 0; i--) {
969 		int ii = itemactive[i];
970 		if (item[ii].isEmpty()) {
971 			dItem[item[ii]._ix][item[ii]._iy] = 0;
972 			DeleteItem(ii, i);
973 		}
974 	}
975 }
976 
977 /**
978  * @brief Load game state
979  * @param firstflag Can be set to false if we are simply reloading the current game
980  */
LoadGame(BOOL firstflag)981 void LoadGame(BOOL firstflag)
982 {
983 	FreeGameMem();
984 	pfile_remove_temp_files();
985 
986 	LoadHelper file("game");
987 	if (!file.isValid())
988 		app_fatal("Unable to open save file archive");
989 
990 	if (!IsHeaderValid(file.nextLE<Uint32>()))
991 		app_fatal("Invalid save file");
992 
993 	if (gbIsHellfireSaveGame) {
994 		giNumberOfLevels = 25;
995 		giNumberQuests = 24;
996 		giNumberOfSmithPremiumItems = 15;
997 	} else {
998 		// Todo initialize additional levels and quests if we are running Hellfire
999 		giNumberOfLevels = 17;
1000 		giNumberQuests = 16;
1001 		giNumberOfSmithPremiumItems = 6;
1002 	}
1003 
1004 	setlevel = file.nextBool8();
1005 	setlvlnum = file.nextBE<Uint32>();
1006 	currlevel = file.nextBE<Uint32>();
1007 	leveltype = (dungeon_type)file.nextBE<Uint32>();
1008 	if (!setlevel)
1009 		leveltype = gnLevelTypeTbl[currlevel];
1010 	int _ViewX = file.nextBE<Sint32>();
1011 	int _ViewY = file.nextBE<Sint32>();
1012 	invflag = file.nextBool8();
1013 	chrflag = file.nextBool8();
1014 	int _nummonsters = file.nextBE<Sint32>();
1015 	int _numitems = file.nextBE<Sint32>();
1016 	int _nummissiles = file.nextBE<Sint32>();
1017 	int _nobjects = file.nextBE<Sint32>();
1018 
1019 	if (!gbIsHellfire && currlevel > 17)
1020 		app_fatal("Player is on a Hellfire only level");
1021 
1022 	for (int i = 0; i < giNumberOfLevels; i++) {
1023 		glSeedTbl[i] = file.nextBE<Uint32>();
1024 		file.skip(4); // Skip loading gnLevelTypeTbl
1025 	}
1026 
1027 	LoadPlayer(&file, myplr);
1028 
1029 	gnDifficulty = plr[myplr].pDifficulty;
1030 	if (gnDifficulty < DIFF_NORMAL || gnDifficulty > DIFF_HELL)
1031 		gnDifficulty = DIFF_NORMAL;
1032 
1033 	for (int i = 0; i < giNumberQuests; i++)
1034 		LoadQuest(&file, i);
1035 	for (int i = 0; i < MAXPORTAL; i++)
1036 		LoadPortal(&file, i);
1037 
1038 	if (gbIsHellfireSaveGame != gbIsHellfire) {
1039 		ConvertLevels();
1040 		RemoveEmptyInventory(myplr);
1041 	}
1042 
1043 	LoadGameLevel(firstflag, ENTRY_LOAD);
1044 	SyncInitPlr(myplr);
1045 	SyncPlrAnim(myplr);
1046 
1047 	ViewX = _ViewX;
1048 	ViewY = _ViewY;
1049 	nummonsters = _nummonsters;
1050 	numitems = _numitems;
1051 	nummissiles = _nummissiles;
1052 	nobjects = _nobjects;
1053 
1054 	for (int i = 0; i < MAXMONSTERS; i++)
1055 		monstkills[i] = file.nextBE<Sint32>();
1056 
1057 	if (leveltype != DTYPE_TOWN) {
1058 		for (int i = 0; i < MAXMONSTERS; i++)
1059 			monstactive[i] = file.nextBE<Sint32>();
1060 		for (int i = 0; i < nummonsters; i++)
1061 			LoadMonster(&file, monstactive[i]);
1062 		for (int i = 0; i < MAXMISSILES; i++)
1063 			missileactive[i] = file.nextLE<Sint8>();
1064 		for (int i = 0; i < MAXMISSILES; i++)
1065 			missileavail[i] = file.nextLE<Sint8>();
1066 		for (int i = 0; i < nummissiles; i++)
1067 			LoadMissile(&file, missileactive[i]);
1068 		for (int i = 0; i < MAXOBJECTS; i++)
1069 			objectactive[i] = file.nextLE<Sint8>();
1070 		for (int i = 0; i < MAXOBJECTS; i++)
1071 			objectavail[i] = file.nextLE<Sint8>();
1072 		for (int i = 0; i < nobjects; i++)
1073 			LoadObject(&file, objectactive[i]);
1074 		for (int i = 0; i < nobjects; i++)
1075 			SyncObjectAnim(objectactive[i]);
1076 
1077 		numlights = file.nextBE<Sint32>();
1078 
1079 		for (int i = 0; i < MAXLIGHTS; i++)
1080 			lightactive[i] = file.nextLE<Uint8>();
1081 		for (int i = 0; i < numlights; i++)
1082 			LoadLighting(&file, &LightList[lightactive[i]]);
1083 
1084 		visionid = file.nextBE<Sint32>();
1085 		numvision = file.nextBE<Sint32>();
1086 
1087 		for (int i = 0; i < numvision; i++)
1088 			LoadLighting(&file, &VisionList[i]);
1089 	}
1090 
1091 	for (int i = 0; i < MAXITEMS; i++)
1092 		itemactive[i] = file.nextLE<Sint8>();
1093 	for (int i = 0; i < MAXITEMS; i++)
1094 		itemavail[i] = file.nextLE<Sint8>();
1095 	for (int i = 0; i < numitems; i++)
1096 		LoadItem(&file, itemactive[i]);
1097 	for (int i = 0; i < 128; i++)
1098 		UniqueItemFlag[i] = file.nextBool8();
1099 
1100 	for (int j = 0; j < MAXDUNY; j++) {
1101 		for (int i = 0; i < MAXDUNX; i++)
1102 			dLight[i][j] = file.nextLE<Sint8>();
1103 	}
1104 	for (int j = 0; j < MAXDUNY; j++) {
1105 		for (int i = 0; i < MAXDUNX; i++)
1106 			dFlags[i][j] = file.nextLE<Sint8>();
1107 	}
1108 	for (int j = 0; j < MAXDUNY; j++) {
1109 		for (int i = 0; i < MAXDUNX; i++)
1110 			dPlayer[i][j] = file.nextLE<Sint8>();
1111 	}
1112 	for (int j = 0; j < MAXDUNY; j++) {
1113 		for (int i = 0; i < MAXDUNX; i++)
1114 			dItem[i][j] = file.nextLE<Sint8>();
1115 	}
1116 
1117 	if (leveltype != DTYPE_TOWN) {
1118 		for (int j = 0; j < MAXDUNY; j++) {
1119 			for (int i = 0; i < MAXDUNX; i++)
1120 				dMonster[i][j] = file.nextBE<Sint32>();
1121 		}
1122 		for (int j = 0; j < MAXDUNY; j++) {
1123 			for (int i = 0; i < MAXDUNX; i++)
1124 				dDead[i][j] = file.nextLE<Sint8>();
1125 		}
1126 		for (int j = 0; j < MAXDUNY; j++) {
1127 			for (int i = 0; i < MAXDUNX; i++)
1128 				dObject[i][j] = file.nextLE<Sint8>();
1129 		}
1130 		for (int j = 0; j < MAXDUNY; j++) {
1131 			for (int i = 0; i < MAXDUNX; i++)
1132 				dLight[i][j] = file.nextLE<Sint8>();
1133 		}
1134 		for (int j = 0; j < MAXDUNY; j++) {
1135 			for (int i = 0; i < MAXDUNX; i++)
1136 				dPreLight[i][j] = file.nextLE<Sint8>();
1137 		}
1138 		for (int j = 0; j < DMAXY; j++) {
1139 			for (int i = 0; i < DMAXX; i++)
1140 				automapview[i][j] = file.nextBool8();
1141 		}
1142 		for (int j = 0; j < MAXDUNY; j++) {
1143 			for (int i = 0; i < MAXDUNX; i++)
1144 				dMissile[i][j] = file.nextLE<Sint8>();
1145 		}
1146 	}
1147 
1148 	numpremium = file.nextBE<Sint32>();
1149 	premiumlevel = file.nextBE<Sint32>();
1150 
1151 	for (int i = 0; i < giNumberOfSmithPremiumItems; i++)
1152 		LoadPremium(&file, i);
1153 	if (gbIsHellfire && !gbIsHellfireSaveGame)
1154 		SpawnPremium(myplr);
1155 
1156 	automapflag = file.nextBool8();
1157 	AutoMapScale = file.nextBE<Sint32>();
1158 	AutomapZoomReset();
1159 	ResyncQuests();
1160 
1161 	if (leveltype != DTYPE_TOWN)
1162 		ProcessLightList();
1163 
1164 	RedoPlayerVision();
1165 	ProcessVisionList();
1166 	missiles_process_charge();
1167 	ResetPal();
1168 	SetCursor_(CURSOR_HAND);
1169 	gbProcessPlayers = TRUE;
1170 
1171 	if (gbIsHellfireSaveGame != gbIsHellfire) {
1172 		RemoveEmptyLevelItems();
1173 		SaveGame();
1174 	}
1175 
1176 	gbIsHellfireSaveGame = gbIsHellfire;
1177 }
1178 
SaveItem(SaveHelper * file,ItemStruct * pItem)1179 static void SaveItem(SaveHelper *file, ItemStruct *pItem)
1180 {
1181 	int idx = pItem->IDidx;
1182 	if (!gbIsHellfire)
1183 		idx = RemapItemIdxToDiablo(idx);
1184 	int iType = pItem->_itype;
1185 	if (idx == -1) {
1186 		idx = 0;
1187 		iType = ITYPE_NONE;
1188 	}
1189 
1190 	file->writeLE<Sint32>(pItem->_iSeed);
1191 	file->writeLE<Sint16>(pItem->_iCreateInfo);
1192 	file->skip(2); // Alignment
1193 	file->writeLE<Sint32>(iType);
1194 	file->writeLE<Sint32>(pItem->_ix);
1195 	file->writeLE<Sint32>(pItem->_iy);
1196 	file->writeLE<Uint32>(pItem->_iAnimFlag);
1197 	file->skip(4); // Skip pointer _iAnimData
1198 	file->writeLE<Sint32>(pItem->_iAnimLen);
1199 	file->writeLE<Sint32>(pItem->_iAnimFrame);
1200 	file->writeLE<Sint32>(pItem->_iAnimWidth);
1201 	file->writeLE<Sint32>(pItem->_iAnimWidth2);
1202 	file->skip(4); // Unused since 1.02
1203 	file->writeLE<Uint8>(pItem->_iSelFlag);
1204 	file->skip(3); // Alignment
1205 	file->writeLE<Uint32>(pItem->_iPostDraw);
1206 	file->writeLE<Uint32>(pItem->_iIdentified);
1207 	file->writeLE<Sint8>(pItem->_iMagical);
1208 	file->writeBytes(pItem->_iName, 64);
1209 	file->writeBytes(pItem->_iIName, 64);
1210 	file->writeLE<Sint8>(pItem->_iLoc);
1211 	file->writeLE<Uint8>(pItem->_iClass);
1212 	file->skip(1); // Alignment
1213 	file->writeLE<Sint32>(pItem->_iCurs);
1214 	file->writeLE<Sint32>(pItem->_ivalue);
1215 	file->writeLE<Sint32>(pItem->_iIvalue);
1216 	file->writeLE<Sint32>(pItem->_iMinDam);
1217 	file->writeLE<Sint32>(pItem->_iMaxDam);
1218 	file->writeLE<Sint32>(pItem->_iAC);
1219 	file->writeLE<Sint32>(pItem->_iFlags);
1220 	file->writeLE<Sint32>(pItem->_iMiscId);
1221 	file->writeLE<Sint32>(pItem->_iSpell);
1222 	file->writeLE<Sint32>(pItem->_iCharges);
1223 	file->writeLE<Sint32>(pItem->_iMaxCharges);
1224 	file->writeLE<Sint32>(pItem->_iDurability);
1225 	file->writeLE<Sint32>(pItem->_iMaxDur);
1226 	file->writeLE<Sint32>(pItem->_iPLDam);
1227 	file->writeLE<Sint32>(pItem->_iPLToHit);
1228 	file->writeLE<Sint32>(pItem->_iPLAC);
1229 	file->writeLE<Sint32>(pItem->_iPLStr);
1230 	file->writeLE<Sint32>(pItem->_iPLMag);
1231 	file->writeLE<Sint32>(pItem->_iPLDex);
1232 	file->writeLE<Sint32>(pItem->_iPLVit);
1233 	file->writeLE<Sint32>(pItem->_iPLFR);
1234 	file->writeLE<Sint32>(pItem->_iPLLR);
1235 	file->writeLE<Sint32>(pItem->_iPLMR);
1236 	file->writeLE<Sint32>(pItem->_iPLMana);
1237 	file->writeLE<Sint32>(pItem->_iPLHP);
1238 	file->writeLE<Sint32>(pItem->_iPLDamMod);
1239 	file->writeLE<Sint32>(pItem->_iPLGetHit);
1240 	file->writeLE<Sint32>(pItem->_iPLLight);
1241 	file->writeLE<Sint8>(pItem->_iSplLvlAdd);
1242 	file->writeLE<Sint8>(pItem->_iRequest);
1243 	file->skip(2); // Alignment
1244 	file->writeLE<Sint32>(pItem->_iUid);
1245 	file->writeLE<Sint32>(pItem->_iFMinDam);
1246 	file->writeLE<Sint32>(pItem->_iFMaxDam);
1247 	file->writeLE<Sint32>(pItem->_iLMinDam);
1248 	file->writeLE<Sint32>(pItem->_iLMaxDam);
1249 	file->writeLE<Sint32>(pItem->_iPLEnAc);
1250 	file->writeLE<Sint8>(pItem->_iPrePower);
1251 	file->writeLE<Sint8>(pItem->_iSufPower);
1252 	file->skip(2); // Alignment
1253 	file->writeLE<Sint32>(pItem->_iVAdd1);
1254 	file->writeLE<Sint32>(pItem->_iVMult1);
1255 	file->writeLE<Sint32>(pItem->_iVAdd2);
1256 	file->writeLE<Sint32>(pItem->_iVMult2);
1257 	file->writeLE<Sint8>(pItem->_iMinStr);
1258 	file->writeLE<Uint8>(pItem->_iMinMag);
1259 	file->writeLE<Sint8>(pItem->_iMinDex);
1260 	file->skip(1); // Alignment
1261 	file->writeLE<Uint32>(pItem->_iStatFlag);
1262 	file->writeLE<Sint32>(idx);
1263 	file->writeLE<Uint32>(pItem->dwBuff);
1264 	if (gbIsHellfire)
1265 		file->writeLE<Uint32>(pItem->_iDamAcFlags);
1266 }
1267 
SaveItems(SaveHelper * file,ItemStruct * pItem,const int n)1268 static void SaveItems(SaveHelper *file, ItemStruct *pItem, const int n)
1269 {
1270 	for (int i = 0; i < n; i++) {
1271 		SaveItem(file, &pItem[i]);
1272 	}
1273 }
1274 
SavePlayer(SaveHelper * file,int p)1275 static void SavePlayer(SaveHelper *file, int p)
1276 {
1277 	PlayerStruct *pPlayer = &plr[p];
1278 
1279 	file->writeLE<Sint32>(pPlayer->_pmode);
1280 	for (int i = 0; i < MAX_PATH_LENGTH; i++)
1281 		file->writeLE<Sint8>(pPlayer->walkpath[i]);
1282 	file->writeLE<Uint8>(pPlayer->plractive);
1283 	file->skip(2); // Alignment
1284 	file->writeLE<Sint32>(pPlayer->destAction);
1285 	file->writeLE<Sint32>(pPlayer->destParam1);
1286 	file->writeLE<Sint32>(pPlayer->destParam2);
1287 	file->writeLE<Sint32>(pPlayer->destParam3);
1288 	file->writeLE<Sint32>(pPlayer->destParam4);
1289 	file->writeLE<Sint32>(pPlayer->plrlevel);
1290 	file->writeLE<Sint32>(pPlayer->_px);
1291 	file->writeLE<Sint32>(pPlayer->_py);
1292 	file->writeLE<Sint32>(pPlayer->_pfutx);
1293 	file->writeLE<Sint32>(pPlayer->_pfuty);
1294 	file->writeLE<Sint32>(pPlayer->_ptargx);
1295 	file->writeLE<Sint32>(pPlayer->_ptargy);
1296 	file->writeLE<Sint32>(pPlayer->_pownerx);
1297 	file->writeLE<Sint32>(pPlayer->_pownery);
1298 	file->writeLE<Sint32>(pPlayer->_poldx);
1299 	file->writeLE<Sint32>(pPlayer->_poldy);
1300 	file->writeLE<Sint32>(pPlayer->_pxoff);
1301 	file->writeLE<Sint32>(pPlayer->_pyoff);
1302 	file->writeLE<Sint32>(pPlayer->_pxvel);
1303 	file->writeLE<Sint32>(pPlayer->_pyvel);
1304 	file->writeLE<Sint32>(pPlayer->_pdir);
1305 	file->skip(4); // Unused
1306 	file->writeLE<Sint32>(pPlayer->_pgfxnum);
1307 	file->skip(4); // Skip pointer _pAnimData
1308 	file->writeLE<Sint32>(pPlayer->_pAnimDelay);
1309 	file->writeLE<Sint32>(pPlayer->_pAnimCnt);
1310 	file->writeLE<Sint32>(pPlayer->_pAnimLen);
1311 	file->writeLE<Sint32>(pPlayer->_pAnimFrame);
1312 	file->writeLE<Sint32>(pPlayer->_pAnimWidth);
1313 	file->writeLE<Sint32>(pPlayer->_pAnimWidth2);
1314 	file->skip(4); // Skip _peflag
1315 	file->writeLE<Sint32>(pPlayer->_plid);
1316 	file->writeLE<Sint32>(pPlayer->_pvid);
1317 
1318 	file->writeLE<Sint32>(pPlayer->_pSpell);
1319 	file->writeLE<Sint8>(pPlayer->_pSplType);
1320 	file->writeLE<Sint8>(pPlayer->_pSplFrom);
1321 	file->skip(2); // Alignment
1322 	file->writeLE<Sint32>(pPlayer->_pTSpell);
1323 	file->writeLE<Sint8>(pPlayer->_pTSplType);
1324 	file->skip(3); // Alignment
1325 	file->writeLE<Sint32>(pPlayer->_pRSpell);
1326 	file->writeLE<Sint8>(pPlayer->_pRSplType);
1327 	file->skip(3); // Alignment
1328 	file->writeLE<Sint32>(pPlayer->_pSBkSpell);
1329 	file->writeLE<Sint8>(pPlayer->_pSBkSplType);
1330 	for (int i = 0; i < 64; i++)
1331 		file->writeLE<Sint8>(pPlayer->_pSplLvl[i]);
1332 	file->skip(7); // Alignment
1333 	file->writeLE<Uint64>(pPlayer->_pMemSpells);
1334 	file->writeLE<Uint64>(pPlayer->_pAblSpells);
1335 	file->writeLE<Uint64>(pPlayer->_pScrlSpells);
1336 	file->writeLE<Uint8>(pPlayer->_pSpellFlags);
1337 	file->skip(3); // Alignment
1338 	for (int i = 0; i < 4; i++)
1339 		file->writeLE<Sint32>(pPlayer->_pSplHotKey[i]);
1340 	for (int i = 0; i < 4; i++)
1341 		file->writeLE<Sint8>(pPlayer->_pSplTHotKey[i]);
1342 
1343 	file->writeLE<Sint32>(pPlayer->_pwtype);
1344 	file->writeLE<Uint8>(pPlayer->_pBlockFlag);
1345 	file->writeLE<Uint8>(pPlayer->_pInvincible);
1346 	file->writeLE<Sint8>(pPlayer->_pLightRad);
1347 	file->writeLE<Uint8>(pPlayer->_pLvlChanging);
1348 
1349 	file->writeBytes(pPlayer->_pName, PLR_NAME_LEN);
1350 	file->writeLE<Sint8>(pPlayer->_pClass);
1351 	file->skip(3); // Alignment
1352 	file->writeLE<Sint32>(pPlayer->_pStrength);
1353 	file->writeLE<Sint32>(pPlayer->_pBaseStr);
1354 	file->writeLE<Sint32>(pPlayer->_pMagic);
1355 	file->writeLE<Sint32>(pPlayer->_pBaseMag);
1356 	file->writeLE<Sint32>(pPlayer->_pDexterity);
1357 	file->writeLE<Sint32>(pPlayer->_pBaseDex);
1358 	file->writeLE<Sint32>(pPlayer->_pVitality);
1359 	file->writeLE<Sint32>(pPlayer->_pBaseVit);
1360 	file->writeLE<Sint32>(pPlayer->_pStatPts);
1361 	file->writeLE<Sint32>(pPlayer->_pDamageMod);
1362 
1363 	file->writeLE<Sint32>(pPlayer->_pBaseToBlk);
1364 	file->writeLE<Sint32>(pPlayer->_pHPBase);
1365 	file->writeLE<Sint32>(pPlayer->_pMaxHPBase);
1366 	file->writeLE<Sint32>(pPlayer->_pHitPoints);
1367 	file->writeLE<Sint32>(pPlayer->_pMaxHP);
1368 	file->writeLE<Sint32>(pPlayer->_pHPPer);
1369 	file->writeLE<Sint32>(pPlayer->_pManaBase);
1370 	file->writeLE<Sint32>(pPlayer->_pMaxManaBase);
1371 	file->writeLE<Sint32>(pPlayer->_pMana);
1372 	file->writeLE<Sint32>(pPlayer->_pMaxMana);
1373 	file->writeLE<Sint32>(pPlayer->_pManaPer);
1374 	file->writeLE<Sint8>(pPlayer->_pLevel);
1375 	file->writeLE<Sint8>(pPlayer->_pMaxLvl);
1376 	file->skip(2); // Alignment
1377 	file->writeLE<Sint32>(pPlayer->_pExperience);
1378 	file->writeLE<Sint32>(pPlayer->_pMaxExp);
1379 	file->writeLE<Sint32>(pPlayer->_pNextExper);
1380 	file->writeLE<Sint8>(pPlayer->_pArmorClass);
1381 	file->writeLE<Sint8>(pPlayer->_pMagResist);
1382 	file->writeLE<Sint8>(pPlayer->_pFireResist);
1383 	file->writeLE<Sint8>(pPlayer->_pLghtResist);
1384 	file->writeLE<Sint32>(pPlayer->_pGold);
1385 
1386 	file->writeLE<Uint32>(pPlayer->_pInfraFlag);
1387 	file->writeLE<Sint32>(pPlayer->_pVar1);
1388 	file->writeLE<Sint32>(pPlayer->_pVar2);
1389 	file->writeLE<Sint32>(pPlayer->_pVar3);
1390 	file->writeLE<Sint32>(pPlayer->_pVar4);
1391 	file->writeLE<Sint32>(pPlayer->_pVar5);
1392 	file->writeLE<Sint32>(pPlayer->_pVar6);
1393 	file->writeLE<Sint32>(pPlayer->_pVar7);
1394 	file->writeLE<Sint32>(pPlayer->_pVar8);
1395 	for (int i = 0; i < giNumberOfLevels; i++)
1396 		file->writeLE<Uint8>(pPlayer->_pLvlVisited[i]);
1397 	for (int i = 0; i < giNumberOfLevels; i++)
1398 		file->writeLE<Uint8>(pPlayer->_pSLvlVisited[i]); // only 10 used
1399 
1400 	file->skip(2); // Alignment
1401 
1402 	file->writeLE<Sint32>(pPlayer->_pGFXLoad);
1403 	file->skip(4 * 8); // Skip pointers _pNAnim
1404 	file->writeLE<Sint32>(pPlayer->_pNFrames);
1405 	file->writeLE<Sint32>(pPlayer->_pNWidth);
1406 	file->skip(4 * 8); // Skip pointers _pWAnim
1407 	file->writeLE<Sint32>(pPlayer->_pWFrames);
1408 	file->writeLE<Sint32>(pPlayer->_pWWidth);
1409 	file->skip(4 * 8); // Skip pointers _pAAnim
1410 	file->writeLE<Sint32>(pPlayer->_pAFrames);
1411 	file->writeLE<Sint32>(pPlayer->_pAWidth);
1412 	file->writeLE<Sint32>(pPlayer->_pAFNum);
1413 	file->skip(4 * 8); // Skip pointers _pLAnim
1414 	file->skip(4 * 8); // Skip pointers _pFAnim
1415 	file->skip(4 * 8); // Skip pointers _pTAnim
1416 	file->writeLE<Sint32>(pPlayer->_pSFrames);
1417 	file->writeLE<Sint32>(pPlayer->_pSWidth);
1418 	file->writeLE<Sint32>(pPlayer->_pSFNum);
1419 	file->skip(4 * 8); // Skip pointers _pHAnim
1420 	file->writeLE<Sint32>(pPlayer->_pHFrames);
1421 	file->writeLE<Sint32>(pPlayer->_pHWidth);
1422 	file->skip(4 * 8); // Skip pointers _pDAnim
1423 	file->writeLE<Sint32>(pPlayer->_pDFrames);
1424 	file->writeLE<Sint32>(pPlayer->_pDWidth);
1425 	file->skip(4 * 8); // Skip pointers _pBAnim
1426 	file->writeLE<Sint32>(pPlayer->_pBFrames);
1427 	file->writeLE<Sint32>(pPlayer->_pBWidth);
1428 
1429 	SaveItems(file, pPlayer->InvBody, NUM_INVLOC);
1430 	SaveItems(file, pPlayer->InvList, NUM_INV_GRID_ELEM);
1431 	file->writeLE<Sint32>(pPlayer->_pNumInv);
1432 	for (int i = 0; i < NUM_INV_GRID_ELEM; i++)
1433 		file->writeLE<Sint8>(pPlayer->InvGrid[i]);
1434 	SaveItems(file, pPlayer->SpdList, MAXBELTITEMS);
1435 	SaveItem(file, &pPlayer->HoldItem);
1436 
1437 	file->writeLE<Sint32>(pPlayer->_pIMinDam);
1438 	file->writeLE<Sint32>(pPlayer->_pIMaxDam);
1439 	file->writeLE<Sint32>(pPlayer->_pIAC);
1440 	file->writeLE<Sint32>(pPlayer->_pIBonusDam);
1441 	file->writeLE<Sint32>(pPlayer->_pIBonusToHit);
1442 	file->writeLE<Sint32>(pPlayer->_pIBonusAC);
1443 	file->writeLE<Sint32>(pPlayer->_pIBonusDamMod);
1444 	file->skip(4); // Alignment
1445 
1446 	file->writeLE<Uint64>(pPlayer->_pISpells);
1447 	file->writeLE<Sint32>(pPlayer->_pIFlags);
1448 	file->writeLE<Sint32>(pPlayer->_pIGetHit);
1449 
1450 	file->writeLE<Sint8>(pPlayer->_pISplLvlAdd);
1451 	file->skip(1); // Unused
1452 	file->skip(2); // Alignment
1453 	file->writeLE<Sint32>(pPlayer->_pISplDur);
1454 	file->writeLE<Sint32>(pPlayer->_pIEnAc);
1455 	file->writeLE<Sint32>(pPlayer->_pIFMinDam);
1456 	file->writeLE<Sint32>(pPlayer->_pIFMaxDam);
1457 	file->writeLE<Sint32>(pPlayer->_pILMinDam);
1458 	file->writeLE<Sint32>(pPlayer->_pILMaxDam);
1459 	file->writeLE<Sint32>(pPlayer->_pOilType);
1460 	file->writeLE<Uint8>(pPlayer->pTownWarps);
1461 	file->writeLE<Uint8>(pPlayer->pDungMsgs);
1462 	file->writeLE<Uint8>(pPlayer->pLvlLoad);
1463 	if (gbIsHellfire)
1464 		file->writeLE<Uint8>(pPlayer->pDungMsgs2);
1465 	else
1466 		file->writeLE<Uint8>(pPlayer->pBattleNet);
1467 	file->writeLE<Uint8>(pPlayer->pManaShield);
1468 	file->writeLE<Uint8>(pPlayer->pOriginalCathedral);
1469 	file->skip(2); // Available bytes
1470 	file->writeLE<Uint16>(pPlayer->wReflections);
1471 	file->skip(14); // Available bytes
1472 
1473 	file->writeLE<Uint32>(pPlayer->pDiabloKillLevel);
1474 	file->writeLE<Uint32>(pPlayer->pDifficulty);
1475 	file->writeLE<Uint32>(pPlayer->pDamAcFlags);
1476 	file->skip(20); // Available bytes
1477 
1478 	// Omit pointer _pNData
1479 	// Omit pointer _pWData
1480 	// Omit pointer _pAData
1481 	// Omit pointer _pLData
1482 	// Omit pointer _pFData
1483 	// Omit pointer  _pTData
1484 	// Omit pointer _pHData
1485 	// Omit pointer _pDData
1486 	// Omit pointer _pBData
1487 	// Omit pointer pReserved
1488 }
1489 
SaveMonster(SaveHelper * file,int i)1490 static void SaveMonster(SaveHelper *file, int i)
1491 {
1492 	MonsterStruct *pMonster = &monster[i];
1493 
1494 	file->writeLE<Sint32>(pMonster->_mMTidx);
1495 	file->writeLE<Sint32>(pMonster->_mmode);
1496 	file->writeLE<Uint8>(pMonster->_mgoal);
1497 	file->skip(3); // Alignment
1498 	file->writeLE<Sint32>(pMonster->_mgoalvar1);
1499 	file->writeLE<Sint32>(pMonster->_mgoalvar2);
1500 	file->writeLE<Sint32>(pMonster->_mgoalvar3);
1501 	file->skip(4); // Unused
1502 	file->writeLE<Uint8>(pMonster->_pathcount);
1503 	file->skip(3); // Alignment
1504 	file->writeLE<Sint32>(pMonster->_mx);
1505 	file->writeLE<Sint32>(pMonster->_my);
1506 	file->writeLE<Sint32>(pMonster->_mfutx);
1507 	file->writeLE<Sint32>(pMonster->_mfuty);
1508 	file->writeLE<Sint32>(pMonster->_moldx);
1509 	file->writeLE<Sint32>(pMonster->_moldy);
1510 	file->writeLE<Sint32>(pMonster->_mxoff);
1511 	file->writeLE<Sint32>(pMonster->_myoff);
1512 	file->writeLE<Sint32>(pMonster->_mxvel);
1513 	file->writeLE<Sint32>(pMonster->_myvel);
1514 	file->writeLE<Sint32>(pMonster->_mdir);
1515 	file->writeLE<Sint32>(pMonster->_menemy);
1516 	file->writeLE<Uint8>(pMonster->_menemyx);
1517 	file->writeLE<Uint8>(pMonster->_menemyy);
1518 	file->skip(2); // Unused
1519 
1520 	file->skip(4); // Skip pointer _mAnimData
1521 	file->writeLE<Sint32>(pMonster->_mAnimDelay);
1522 	file->writeLE<Sint32>(pMonster->_mAnimCnt);
1523 	file->writeLE<Sint32>(pMonster->_mAnimLen);
1524 	file->writeLE<Sint32>(pMonster->_mAnimFrame);
1525 	file->skip(4); // Skip _meflag
1526 	file->writeLE<Uint32>(pMonster->_mDelFlag);
1527 	file->writeLE<Sint32>(pMonster->_mVar1);
1528 	file->writeLE<Sint32>(pMonster->_mVar2);
1529 	file->writeLE<Sint32>(pMonster->_mVar3);
1530 	file->writeLE<Sint32>(pMonster->_mVar4);
1531 	file->writeLE<Sint32>(pMonster->_mVar5);
1532 	file->writeLE<Sint32>(pMonster->_mVar6);
1533 	file->writeLE<Sint32>(pMonster->_mVar7);
1534 	file->writeLE<Sint32>(pMonster->_mVar8);
1535 	file->writeLE<Sint32>(pMonster->_mmaxhp);
1536 	file->writeLE<Sint32>(pMonster->_mhitpoints);
1537 
1538 	file->writeLE<Uint8>(pMonster->_mAi);
1539 	file->writeLE<Uint8>(pMonster->_mint);
1540 	file->skip(2); // Alignment
1541 	file->writeLE<Uint32>(pMonster->_mFlags);
1542 	file->writeLE<Uint8>(pMonster->_msquelch);
1543 	file->skip(3); // Alignment
1544 	file->skip(4); // Unused
1545 	file->writeLE<Sint32>(pMonster->_lastx);
1546 	file->writeLE<Sint32>(pMonster->_lasty);
1547 	file->writeLE<Sint32>(pMonster->_mRndSeed);
1548 	file->writeLE<Sint32>(pMonster->_mAISeed);
1549 	file->skip(4); // Unused
1550 
1551 	file->writeLE<Uint8>(pMonster->_uniqtype);
1552 	file->writeLE<Uint8>(pMonster->_uniqtrans);
1553 	file->writeLE<Sint8>(pMonster->_udeadval);
1554 
1555 	file->writeLE<Sint8>(pMonster->mWhoHit);
1556 	file->writeLE<Sint8>(pMonster->mLevel);
1557 	file->skip(1); // Alignment
1558 	file->writeLE<Uint16>(pMonster->mExp);
1559 
1560 	file->writeLE<Uint8>(pMonster->mHit < SCHAR_MAX ? pMonster->mHit : SCHAR_MAX); // For backwards compatibility
1561 	file->writeLE<Uint8>(pMonster->mMinDamage);
1562 	file->writeLE<Uint8>(pMonster->mMaxDamage);
1563 	file->writeLE<Uint8>(pMonster->mHit2 < SCHAR_MAX ? pMonster->mHit2 : SCHAR_MAX); // For backwards compatibility
1564 	file->writeLE<Uint8>(pMonster->mMinDamage2);
1565 	file->writeLE<Uint8>(pMonster->mMaxDamage2);
1566 	file->writeLE<Uint8>(pMonster->mArmorClass);
1567 	file->skip(1); // Alignment
1568 	file->writeLE<Uint16>(pMonster->mMagicRes);
1569 	file->skip(2); // Alignment
1570 
1571 	file->writeLE<Sint32>(pMonster->mtalkmsg);
1572 	file->writeLE<Uint8>(pMonster->leader);
1573 	file->writeLE<Uint8>(pMonster->leaderflag);
1574 	file->writeLE<Uint8>(pMonster->packsize);
1575 	file->writeLE<Sint8>(pMonster->mlid);
1576 
1577 	// Omit pointer mName;
1578 	// Omit pointer MType;
1579 	// Omit pointer MData;
1580 }
1581 
SaveMissile(SaveHelper * file,int i)1582 static void SaveMissile(SaveHelper *file, int i)
1583 {
1584 	MissileStruct *pMissile = &missile[i];
1585 
1586 	file->writeLE<Sint32>(pMissile->_mitype);
1587 	file->writeLE<Sint32>(pMissile->_mix);
1588 	file->writeLE<Sint32>(pMissile->_miy);
1589 	file->writeLE<Sint32>(pMissile->_mixoff);
1590 	file->writeLE<Sint32>(pMissile->_miyoff);
1591 	file->writeLE<Sint32>(pMissile->_mixvel);
1592 	file->writeLE<Sint32>(pMissile->_miyvel);
1593 	file->writeLE<Sint32>(pMissile->_misx);
1594 	file->writeLE<Sint32>(pMissile->_misy);
1595 	file->writeLE<Sint32>(pMissile->_mitxoff);
1596 	file->writeLE<Sint32>(pMissile->_mityoff);
1597 	file->writeLE<Sint32>(pMissile->_mimfnum);
1598 	file->writeLE<Sint32>(pMissile->_mispllvl);
1599 	file->writeLE<Uint32>(pMissile->_miDelFlag);
1600 	file->writeLE<Uint8>(pMissile->_miAnimType);
1601 	file->skip(3); // Alignment
1602 	file->writeLE<Sint32>(pMissile->_miAnimFlags);
1603 	file->skip(4); // Skip pointer _miAnimData
1604 	file->writeLE<Sint32>(pMissile->_miAnimDelay);
1605 	file->writeLE<Sint32>(pMissile->_miAnimLen);
1606 	file->writeLE<Sint32>(pMissile->_miAnimWidth);
1607 	file->writeLE<Sint32>(pMissile->_miAnimWidth2);
1608 	file->writeLE<Sint32>(pMissile->_miAnimCnt);
1609 	file->writeLE<Sint32>(pMissile->_miAnimAdd);
1610 	file->writeLE<Sint32>(pMissile->_miAnimFrame);
1611 	file->writeLE<Uint32>(pMissile->_miDrawFlag);
1612 	file->writeLE<Uint32>(pMissile->_miLightFlag);
1613 	file->writeLE<Uint32>(pMissile->_miPreFlag);
1614 	file->writeLE<Uint32>(pMissile->_miUniqTrans);
1615 	file->writeLE<Sint32>(pMissile->_mirange);
1616 	file->writeLE<Sint32>(pMissile->_misource);
1617 	file->writeLE<Sint32>(pMissile->_micaster);
1618 	file->writeLE<Sint32>(pMissile->_midam);
1619 	file->writeLE<Uint32>(pMissile->_miHitFlag);
1620 	file->writeLE<Sint32>(pMissile->_midist);
1621 	file->writeLE<Sint32>(pMissile->_mlid);
1622 	file->writeLE<Sint32>(pMissile->_mirnd);
1623 	file->writeLE<Sint32>(pMissile->_miVar1);
1624 	file->writeLE<Sint32>(pMissile->_miVar2);
1625 	file->writeLE<Sint32>(pMissile->_miVar3);
1626 	file->writeLE<Sint32>(pMissile->_miVar4);
1627 	file->writeLE<Sint32>(pMissile->_miVar5);
1628 	file->writeLE<Sint32>(pMissile->_miVar6);
1629 	file->writeLE<Sint32>(pMissile->_miVar7);
1630 	file->writeLE<Sint32>(pMissile->_miVar8);
1631 }
1632 
SaveObject(SaveHelper * file,int i)1633 static void SaveObject(SaveHelper *file, int i)
1634 {
1635 	ObjectStruct *pObject = &object[i];
1636 
1637 	file->writeLE<Sint32>(pObject->_otype);
1638 	file->writeLE<Sint32>(pObject->_ox);
1639 	file->writeLE<Sint32>(pObject->_oy);
1640 	file->writeLE<Uint32>(pObject->_oLight);
1641 	file->writeLE<Uint32>(pObject->_oAnimFlag);
1642 	file->skip(4); // Skip pointer _oAnimData
1643 	file->writeLE<Sint32>(pObject->_oAnimDelay);
1644 	file->writeLE<Sint32>(pObject->_oAnimCnt);
1645 	file->writeLE<Sint32>(pObject->_oAnimLen);
1646 	file->writeLE<Sint32>(pObject->_oAnimFrame);
1647 	file->writeLE<Sint32>(pObject->_oAnimWidth);
1648 	file->writeLE<Sint32>(pObject->_oAnimWidth2);
1649 	file->writeLE<Uint32>(pObject->_oDelFlag);
1650 	file->writeLE<Sint8>(pObject->_oBreak);
1651 	file->skip(3); // Alignment
1652 	file->writeLE<Uint32>(pObject->_oSolidFlag);
1653 	file->writeLE<Uint32>(pObject->_oMissFlag);
1654 
1655 	file->writeLE<Sint8>(pObject->_oSelFlag);
1656 	file->skip(3); // Alignment
1657 	file->writeLE<Uint32>(pObject->_oPreFlag);
1658 	file->writeLE<Uint32>(pObject->_oTrapFlag);
1659 	file->writeLE<Uint32>(pObject->_oDoorFlag);
1660 	file->writeLE<Sint32>(pObject->_olid);
1661 	file->writeLE<Sint32>(pObject->_oRndSeed);
1662 	file->writeLE<Sint32>(pObject->_oVar1);
1663 	file->writeLE<Sint32>(pObject->_oVar2);
1664 	file->writeLE<Sint32>(pObject->_oVar3);
1665 	file->writeLE<Sint32>(pObject->_oVar4);
1666 	file->writeLE<Sint32>(pObject->_oVar5);
1667 	file->writeLE<Sint32>(pObject->_oVar6);
1668 	file->writeLE<Sint32>(pObject->_oVar7);
1669 	file->writeLE<Sint32>(pObject->_oVar8);
1670 }
1671 
SavePremium(SaveHelper * file,int i)1672 static void SavePremium(SaveHelper *file, int i)
1673 {
1674 	SaveItem(file, &premiumitem[i]);
1675 }
1676 
SaveQuest(SaveHelper * file,int i)1677 static void SaveQuest(SaveHelper *file, int i)
1678 {
1679 	QuestStruct *pQuest = &quests[i];
1680 
1681 	file->writeLE<Uint8>(pQuest->_qlevel);
1682 	file->writeLE<Uint8>(pQuest->_qtype);
1683 	file->writeLE<Uint8>(pQuest->_qactive);
1684 	file->writeLE<Uint8>(pQuest->_qlvltype);
1685 	file->writeLE<Sint32>(pQuest->_qtx);
1686 	file->writeLE<Sint32>(pQuest->_qty);
1687 	file->writeLE<Uint8>(pQuest->_qslvl);
1688 	file->writeLE<Uint8>(pQuest->_qidx);
1689 	if (gbIsHellfire) {
1690 		file->skip(2); // Alignment
1691 		file->writeLE<Sint32>(pQuest->_qmsg);
1692 	} else {
1693 		file->writeLE<Uint8>(pQuest->_qmsg);
1694 	}
1695 	file->writeLE<Uint8>(pQuest->_qvar1);
1696 	file->writeLE<Uint8>(pQuest->_qvar2);
1697 	file->skip(2); // Alignment
1698 	if (!gbIsHellfire)
1699 		file->skip(1); // Alignment
1700 	file->writeLE<Uint32>(pQuest->_qlog);
1701 
1702 	file->writeBE<Sint32>(ReturnLvlX);
1703 	file->writeBE<Sint32>(ReturnLvlY);
1704 	file->writeBE<Sint32>(ReturnLvl);
1705 	file->writeBE<Sint32>(ReturnLvlT);
1706 	file->writeBE<Sint32>(DoomQuestState);
1707 }
1708 
SaveLighting(SaveHelper * file,LightListStruct * pLight)1709 static void SaveLighting(SaveHelper *file, LightListStruct *pLight)
1710 {
1711 	file->writeLE<Sint32>(pLight->_lx);
1712 	file->writeLE<Sint32>(pLight->_ly);
1713 	file->writeLE<Sint32>(pLight->_lradius);
1714 	file->writeLE<Sint32>(pLight->_lid);
1715 	file->writeLE<Uint32>(pLight->_ldel);
1716 	file->writeLE<Uint32>(pLight->_lunflag);
1717 	file->skip(4); // Unused
1718 	file->writeLE<Sint32>(pLight->_lunx);
1719 	file->writeLE<Sint32>(pLight->_luny);
1720 	file->writeLE<Sint32>(pLight->_lunr);
1721 	file->writeLE<Sint32>(pLight->_xoff);
1722 	file->writeLE<Sint32>(pLight->_yoff);
1723 	file->writeLE<Uint32>(pLight->_lflags);
1724 }
1725 
SavePortal(SaveHelper * file,int i)1726 static void SavePortal(SaveHelper *file, int i)
1727 {
1728 	PortalStruct *pPortal = &portal[i];
1729 
1730 	file->writeLE<Uint32>(pPortal->open);
1731 	file->writeLE<Sint32>(pPortal->x);
1732 	file->writeLE<Sint32>(pPortal->y);
1733 	file->writeLE<Sint32>(pPortal->level);
1734 	file->writeLE<Sint32>(pPortal->ltype);
1735 	file->writeLE<Uint32>(pPortal->setlvl);
1736 }
1737 
1738 const int DiabloItemSaveSize = 368;
1739 const int HellfireItemSaveSize = 372;
1740 
SaveHeroItems(PlayerStruct * pPlayer)1741 void SaveHeroItems(PlayerStruct *pPlayer)
1742 {
1743 	size_t items = NUM_INVLOC + NUM_INV_GRID_ELEM + MAXBELTITEMS;
1744 	SaveHelper file("heroitems", items * (gbIsHellfire ? HellfireItemSaveSize : DiabloItemSaveSize) + sizeof(Uint8));
1745 
1746 	file.writeLE<Uint8>(gbIsHellfire);
1747 
1748 	SaveItems(&file, pPlayer->InvBody, NUM_INVLOC);
1749 	SaveItems(&file, pPlayer->InvList, NUM_INV_GRID_ELEM);
1750 	SaveItems(&file, pPlayer->SpdList, MAXBELTITEMS);
1751 }
1752 
SaveGame()1753 void SaveGame()
1754 {
1755 	SaveHelper file("game", FILEBUFF);
1756 
1757 	if (gbIsSpawn && !gbIsHellfire)
1758 		file.writeLE<Uint32>(LOAD_LE32("SHAR"));
1759 	else if (gbIsSpawn && gbIsHellfire)
1760 		file.writeLE<Uint32>(LOAD_LE32("SHLF"));
1761 	else if (!gbIsSpawn && gbIsHellfire)
1762 		file.writeLE<Uint32>(LOAD_LE32("HELF"));
1763 	else if (!gbIsSpawn && !gbIsHellfire)
1764 		file.writeLE<Uint32>(LOAD_LE32("RETL"));
1765 	else
1766 		app_fatal("Invalid game state");
1767 
1768 	if (gbIsHellfire) {
1769 		giNumberOfLevels = 25;
1770 		giNumberQuests = 24;
1771 		giNumberOfSmithPremiumItems = 15;
1772 	} else {
1773 		giNumberOfLevels = 17;
1774 		giNumberQuests = 16;
1775 		giNumberOfSmithPremiumItems = 6;
1776 	}
1777 
1778 	file.writeLE<Uint8>(setlevel);
1779 	file.writeBE<Uint32>(setlvlnum);
1780 	file.writeBE<Uint32>(currlevel);
1781 	file.writeBE<Uint32>(leveltype);
1782 	file.writeBE<Sint32>(ViewX);
1783 	file.writeBE<Sint32>(ViewY);
1784 	file.writeLE<Uint8>(invflag);
1785 	file.writeLE<Uint8>(chrflag);
1786 	file.writeBE<Sint32>(nummonsters);
1787 	file.writeBE<Sint32>(numitems);
1788 	file.writeBE<Sint32>(nummissiles);
1789 	file.writeBE<Sint32>(nobjects);
1790 
1791 	for (int i = 0; i < giNumberOfLevels; i++) {
1792 		file.writeBE<Uint32>(glSeedTbl[i]);
1793 		file.writeBE<Sint32>(gnLevelTypeTbl[i]);
1794 	}
1795 
1796 	plr[myplr].pDifficulty = gnDifficulty;
1797 	SavePlayer(&file, myplr);
1798 
1799 	for (int i = 0; i < giNumberQuests; i++)
1800 		SaveQuest(&file, i);
1801 	for (int i = 0; i < MAXPORTAL; i++)
1802 		SavePortal(&file, i);
1803 	for (int i = 0; i < MAXMONSTERS; i++)
1804 		file.writeBE<Sint32>(monstkills[i]);
1805 
1806 	if (leveltype != DTYPE_TOWN) {
1807 		for (int i = 0; i < MAXMONSTERS; i++)
1808 			file.writeBE<Sint32>(monstactive[i]);
1809 		for (int i = 0; i < nummonsters; i++)
1810 			SaveMonster(&file, monstactive[i]);
1811 		for (int i = 0; i < MAXMISSILES; i++)
1812 			file.writeLE<Sint8>(missileactive[i]);
1813 		for (int i = 0; i < MAXMISSILES; i++)
1814 			file.writeLE<Sint8>(missileavail[i]);
1815 		for (int i = 0; i < nummissiles; i++)
1816 			SaveMissile(&file, missileactive[i]);
1817 		for (int i = 0; i < MAXOBJECTS; i++)
1818 			file.writeLE<Sint8>(objectactive[i]);
1819 		for (int i = 0; i < MAXOBJECTS; i++)
1820 			file.writeLE<Sint8>(objectavail[i]);
1821 		for (int i = 0; i < nobjects; i++)
1822 			SaveObject(&file, objectactive[i]);
1823 
1824 		file.writeBE<Sint32>(numlights);
1825 
1826 		for (int i = 0; i < MAXLIGHTS; i++)
1827 			file.writeLE<Uint8>(lightactive[i]);
1828 		for (int i = 0; i < numlights; i++)
1829 			SaveLighting(&file, &LightList[lightactive[i]]);
1830 
1831 		file.writeBE<Sint32>(visionid);
1832 		file.writeBE<Sint32>(numvision);
1833 
1834 		for (int i = 0; i < numvision; i++)
1835 			SaveLighting(&file, &VisionList[i]);
1836 	}
1837 
1838 	for (int i = 0; i < MAXITEMS; i++)
1839 		file.writeLE<Sint8>(itemactive[i]);
1840 	for (int i = 0; i < MAXITEMS; i++)
1841 		file.writeLE<Sint8>(itemavail[i]);
1842 	for (int i = 0; i < numitems; i++)
1843 		SaveItem(&file, &item[itemactive[i]]);
1844 	for (int i = 0; i < 128; i++)
1845 		file.writeLE<Sint8>(UniqueItemFlag[i]);
1846 
1847 	for (int j = 0; j < MAXDUNY; j++) {
1848 		for (int i = 0; i < MAXDUNX; i++)
1849 			file.writeLE<Sint8>(dLight[i][j]);
1850 	}
1851 	for (int j = 0; j < MAXDUNY; j++) {
1852 		for (int i = 0; i < MAXDUNX; i++)
1853 			file.writeLE<Sint8>(dFlags[i][j] & ~(BFLAG_MISSILE | BFLAG_VISIBLE | BFLAG_DEAD_PLAYER));
1854 	}
1855 	for (int j = 0; j < MAXDUNY; j++) {
1856 		for (int i = 0; i < MAXDUNX; i++)
1857 			file.writeLE<Sint8>(dPlayer[i][j]);
1858 	}
1859 	for (int j = 0; j < MAXDUNY; j++) {
1860 		for (int i = 0; i < MAXDUNX; i++)
1861 			file.writeLE<Sint8>(dItem[i][j]);
1862 	}
1863 
1864 	if (leveltype != DTYPE_TOWN) {
1865 		for (int j = 0; j < MAXDUNY; j++) {
1866 			for (int i = 0; i < MAXDUNX; i++)
1867 				file.writeBE<Sint32>(dMonster[i][j]);
1868 		}
1869 		for (int j = 0; j < MAXDUNY; j++) {
1870 			for (int i = 0; i < MAXDUNX; i++)
1871 				file.writeLE<Sint8>(dDead[i][j]);
1872 		}
1873 		for (int j = 0; j < MAXDUNY; j++) {
1874 			for (int i = 0; i < MAXDUNX; i++)
1875 				file.writeLE<Sint8>(dObject[i][j]);
1876 		}
1877 		for (int j = 0; j < MAXDUNY; j++) {
1878 			for (int i = 0; i < MAXDUNX; i++)
1879 				file.writeLE<Sint8>(dLight[i][j]);
1880 		}
1881 		for (int j = 0; j < MAXDUNY; j++) {
1882 			for (int i = 0; i < MAXDUNX; i++)
1883 				file.writeLE<Sint8>(dPreLight[i][j]);
1884 		}
1885 		for (int j = 0; j < DMAXY; j++) {
1886 			for (int i = 0; i < DMAXX; i++)
1887 				file.writeLE<Uint8>(automapview[i][j]);
1888 		}
1889 		for (int j = 0; j < MAXDUNY; j++) {
1890 			for (int i = 0; i < MAXDUNX; i++)
1891 				file.writeLE<Sint8>(dMissile[i][j]);
1892 		}
1893 	}
1894 
1895 	file.writeBE<Sint32>(numpremium);
1896 	file.writeBE<Sint32>(premiumlevel);
1897 
1898 	for (int i = 0; i < giNumberOfSmithPremiumItems; i++)
1899 		SavePremium(&file, i);
1900 
1901 	file.writeLE<Uint8>(automapflag);
1902 	file.writeBE<Sint32>(AutoMapScale);
1903 
1904 	file.flush();
1905 
1906 	gbValidSaveFile = TRUE;
1907 	pfile_rename_temp_to_perm();
1908 	pfile_write_hero();
1909 }
1910 
SaveLevel()1911 void SaveLevel()
1912 {
1913 	DoUnVision(plr[myplr]._px, plr[myplr]._py, plr[myplr]._pLightRad); // fix for vision staying on the level
1914 
1915 	if (currlevel == 0)
1916 		glSeedTbl[0] = AdvanceRndSeed();
1917 
1918 	char szName[MAX_PATH];
1919 	GetTempLevelNames(szName);
1920 	SaveHelper file(szName, FILEBUFF);
1921 
1922 	if (leveltype != DTYPE_TOWN) {
1923 		for (int j = 0; j < MAXDUNY; j++) {
1924 			for (int i = 0; i < MAXDUNX; i++)
1925 				file.writeLE<Sint8>(dDead[i][j]);
1926 		}
1927 	}
1928 
1929 	file.writeBE<Sint32>(nummonsters);
1930 	file.writeBE<Sint32>(numitems);
1931 	file.writeBE<Sint32>(nobjects);
1932 
1933 	if (leveltype != DTYPE_TOWN) {
1934 		for (int i = 0; i < MAXMONSTERS; i++)
1935 			file.writeBE<Sint32>(monstactive[i]);
1936 		for (int i = 0; i < nummonsters; i++)
1937 			SaveMonster(&file, monstactive[i]);
1938 		for (int i = 0; i < MAXOBJECTS; i++)
1939 			file.writeLE<Sint8>(objectactive[i]);
1940 		for (int i = 0; i < MAXOBJECTS; i++)
1941 			file.writeLE<Sint8>(objectavail[i]);
1942 		for (int i = 0; i < nobjects; i++)
1943 			SaveObject(&file, objectactive[i]);
1944 	}
1945 
1946 	for (int i = 0; i < MAXITEMS; i++)
1947 		file.writeLE<Sint8>(itemactive[i]);
1948 	for (int i = 0; i < MAXITEMS; i++)
1949 		file.writeLE<Sint8>(itemavail[i]);
1950 
1951 	for (int i = 0; i < numitems; i++)
1952 		SaveItem(&file, &item[itemactive[i]]);
1953 
1954 	for (int j = 0; j < MAXDUNY; j++) {
1955 		for (int i = 0; i < MAXDUNX; i++)
1956 			file.writeLE<Sint8>(dFlags[i][j] & ~(BFLAG_MISSILE | BFLAG_VISIBLE | BFLAG_DEAD_PLAYER));
1957 	}
1958 	for (int j = 0; j < MAXDUNY; j++) {
1959 		for (int i = 0; i < MAXDUNX; i++)
1960 			file.writeLE<Sint8>(dItem[i][j]);
1961 	}
1962 
1963 	if (leveltype != DTYPE_TOWN) {
1964 		for (int j = 0; j < MAXDUNY; j++) {
1965 			for (int i = 0; i < MAXDUNX; i++)
1966 				file.writeBE<Sint32>(dMonster[i][j]);
1967 		}
1968 		for (int j = 0; j < MAXDUNY; j++) {
1969 			for (int i = 0; i < MAXDUNX; i++)
1970 				file.writeLE<Sint8>(dObject[i][j]);
1971 		}
1972 		for (int j = 0; j < MAXDUNY; j++) {
1973 			for (int i = 0; i < MAXDUNX; i++)
1974 				file.writeLE<Sint8>(dLight[i][j]);
1975 		}
1976 		for (int j = 0; j < MAXDUNY; j++) {
1977 			for (int i = 0; i < MAXDUNX; i++)
1978 				file.writeLE<Sint8>(dPreLight[i][j]);
1979 		}
1980 		for (int j = 0; j < DMAXY; j++) {
1981 			for (int i = 0; i < DMAXX; i++)
1982 				file.writeLE<Uint8>(automapview[i][j]);
1983 		}
1984 		for (int j = 0; j < MAXDUNY; j++) {
1985 			for (int i = 0; i < MAXDUNX; i++)
1986 				file.writeLE<Sint8>(dMissile[i][j]);
1987 		}
1988 	}
1989 
1990 	if (!setlevel)
1991 		plr[myplr]._pLvlVisited[currlevel] = TRUE;
1992 	else
1993 		plr[myplr]._pSLvlVisited[setlvlnum] = TRUE;
1994 }
1995 
LoadLevel()1996 void LoadLevel()
1997 {
1998 	char szName[MAX_PATH];
1999 	GetPermLevelNames(szName);
2000 	LoadHelper file(szName);
2001 	if (!file.isValid())
2002 		app_fatal("Unable to open save file archive");
2003 
2004 	if (leveltype != DTYPE_TOWN) {
2005 		for (int j = 0; j < MAXDUNY; j++) {
2006 			for (int i = 0; i < MAXDUNX; i++)
2007 				dDead[i][j] = file.nextLE<Sint8>();
2008 		}
2009 		SetDead();
2010 	}
2011 
2012 	nummonsters = file.nextBE<Sint32>();
2013 	numitems = file.nextBE<Sint32>();
2014 	nobjects = file.nextBE<Sint32>();
2015 
2016 	if (leveltype != DTYPE_TOWN) {
2017 		for (int i = 0; i < MAXMONSTERS; i++)
2018 			monstactive[i] = file.nextBE<Sint32>();
2019 		for (int i = 0; i < nummonsters; i++)
2020 			LoadMonster(&file, monstactive[i]);
2021 		for (int i = 0; i < MAXOBJECTS; i++)
2022 			objectactive[i] = file.nextLE<Sint8>();
2023 		for (int i = 0; i < MAXOBJECTS; i++)
2024 			objectavail[i] = file.nextLE<Sint8>();
2025 		for (int i = 0; i < nobjects; i++)
2026 			LoadObject(&file, objectactive[i]);
2027 		if (!gbSkipSync) {
2028 			for (int i = 0; i < nobjects; i++)
2029 				SyncObjectAnim(objectactive[i]);
2030 		}
2031 	}
2032 
2033 	for (int i = 0; i < MAXITEMS; i++)
2034 		itemactive[i] = file.nextLE<Sint8>();
2035 	for (int i = 0; i < MAXITEMS; i++)
2036 		itemavail[i] = file.nextLE<Sint8>();
2037 	for (int i = 0; i < numitems; i++)
2038 		LoadItem(&file, itemactive[i]);
2039 
2040 	for (int j = 0; j < MAXDUNY; j++) {
2041 		for (int i = 0; i < MAXDUNX; i++)
2042 			dFlags[i][j] = file.nextLE<Sint8>();
2043 	}
2044 	for (int j = 0; j < MAXDUNY; j++) {
2045 		for (int i = 0; i < MAXDUNX; i++)
2046 			dItem[i][j] = file.nextLE<Sint8>();
2047 	}
2048 
2049 	if (leveltype != DTYPE_TOWN) {
2050 		for (int j = 0; j < MAXDUNY; j++) {
2051 			for (int i = 0; i < MAXDUNX; i++)
2052 				dMonster[i][j] = file.nextBE<Sint32>();
2053 		}
2054 		for (int j = 0; j < MAXDUNY; j++) {
2055 			for (int i = 0; i < MAXDUNX; i++)
2056 				dObject[i][j] = file.nextLE<Sint8>();
2057 		}
2058 		for (int j = 0; j < MAXDUNY; j++) {
2059 			for (int i = 0; i < MAXDUNX; i++)
2060 				dLight[i][j] = file.nextLE<Sint8>();
2061 		}
2062 		for (int j = 0; j < MAXDUNY; j++) {
2063 			for (int i = 0; i < MAXDUNX; i++)
2064 				dPreLight[i][j] = file.nextLE<Sint8>();
2065 		}
2066 		for (int j = 0; j < DMAXY; j++) {
2067 			for (int i = 0; i < DMAXX; i++)
2068 				automapview[i][j] = file.nextBool8();
2069 		}
2070 		for (int j = 0; j < MAXDUNY; j++) {
2071 			for (int i = 0; i < MAXDUNX; i++)
2072 				dMissile[i][j] = 0; /// BUGFIX: supposed to load saved missiles with "file.nextLE<Sint8>()"?
2073 		}
2074 	}
2075 
2076 	if (gbIsHellfireSaveGame != gbIsHellfire) {
2077 		RemoveEmptyLevelItems();
2078 	}
2079 
2080 	if (!gbSkipSync) {
2081 		AutomapZoomReset();
2082 		ResyncQuests();
2083 		SyncPortals();
2084 		dolighting = TRUE;
2085 	}
2086 
2087 	for (int i = 0; i < MAX_PLRS; i++) {
2088 		if (plr[i].plractive && currlevel == plr[i].plrlevel)
2089 			LightList[plr[i]._plid]._lunflag = TRUE;
2090 	}
2091 }
2092 
2093 DEVILUTION_END_NAMESPACE
2094