summaryrefslogtreecommitdiff
path: root/games
diff options
context:
space:
mode:
authornia <nia@pkgsrc.org>2019-07-28 10:26:43 +0000
committernia <nia@pkgsrc.org>2019-07-28 10:26:43 +0000
commitfa9d677a97508f941193ac74b10bbfb9c2a60e70 (patch)
treeec49af1f38fc65fd14620d64135995094214d0f3 /games
parentc012864a97dab79e09b4321b79ebd86673320702 (diff)
downloadpkgsrc-fa9d677a97508f941193ac74b10bbfb9c2a60e70.tar.gz
devilutionx: Backport some fixes for 64-bit save files and UB.
Diffstat (limited to 'games')
-rw-r--r--games/devilutionx/Makefile3
-rw-r--r--games/devilutionx/distinfo6
-rw-r--r--games/devilutionx/patches/patch-Source_inv.cpp952
-rw-r--r--games/devilutionx/patches/patch-Source_loadsave.cpp1092
-rw-r--r--games/devilutionx/patches/patch-Source_loadsave.h19
-rw-r--r--games/devilutionx/patches/patch-structs.h53
6 files changed, 2123 insertions, 2 deletions
diff --git a/games/devilutionx/Makefile b/games/devilutionx/Makefile
index 249fa33dbb7..aeabe89f93e 100644
--- a/games/devilutionx/Makefile
+++ b/games/devilutionx/Makefile
@@ -1,6 +1,7 @@
-# $NetBSD: Makefile,v 1.5 2019/07/11 12:56:04 nia Exp $
+# $NetBSD: Makefile,v 1.6 2019/07/28 10:26:43 nia Exp $
DISTNAME= devilutionx-0.4.0
+PKGREVISION= 1
CATEGORIES= games
MASTER_SITES= ${MASTER_SITE_GITHUB:=diasurgical/}
GITHUB_PROJECT= devilutionX
diff --git a/games/devilutionx/distinfo b/games/devilutionx/distinfo
index 2706d5c17ec..5e7faa846c6 100644
--- a/games/devilutionx/distinfo
+++ b/games/devilutionx/distinfo
@@ -1,6 +1,10 @@
-$NetBSD: distinfo,v 1.2 2019/07/11 12:56:04 nia Exp $
+$NetBSD: distinfo,v 1.3 2019/07/28 10:26:43 nia Exp $
SHA1 (devilutionx-0.4.0.tar.gz) = d5d71cf752dc0b5c89f9827b52f1567cb5cfb8f4
RMD160 (devilutionx-0.4.0.tar.gz) = 0b647b8ee4641d9af000d4d54e1008a506a9fc66
SHA512 (devilutionx-0.4.0.tar.gz) = ba8f650f8dd00e3b08f6ac082566351c8f3b6162d7bfa2fdf3464b38c201b08677d2f6151f2272e1d73eb972b8babc49b38364523d10763eb179f6b682641443
Size (devilutionx-0.4.0.tar.gz) = 1351201 bytes
+SHA1 (patch-Source_inv.cpp) = 788414c9141da13391cd4f540e364a034fd87b41
+SHA1 (patch-Source_loadsave.cpp) = 22d8d6e4ca44358dfbc55741b8aebeac6af8e468
+SHA1 (patch-Source_loadsave.h) = 6d7e7cc9e188e5a406c10caceb0aa80139c6e301
+SHA1 (patch-structs.h) = d9cba47b2ca876529aef33d4190f082d134cdcb6
diff --git a/games/devilutionx/patches/patch-Source_inv.cpp b/games/devilutionx/patches/patch-Source_inv.cpp
new file mode 100644
index 00000000000..a472607b624
--- /dev/null
+++ b/games/devilutionx/patches/patch-Source_inv.cpp
@@ -0,0 +1,952 @@
+$NetBSD: patch-Source_inv.cpp,v 1.1 2019/07/28 10:26:43 nia Exp $
+
+[PATCH] Clean up CheckInvPaste (bin exact) (#1205)
+Fixes some item duplication.
+https://github.com/diasurgical/devilutionX/commit/a549d5ebc461e757065c4536cb351969dcf60fe9.patch
+
+--- Source/inv.cpp.orig 2019-05-19 17:06:45.000000000 +0000
++++ Source/inv.cpp
+@@ -686,562 +686,408 @@ int SwapItem(ItemStruct *a, ItemStruct *
+
+ void CheckInvPaste(int pnum, int mx, int my)
+ {
+- int v3; // ebx
+- int v4; // edi
+- int v5; // eax
+- int v6; // esi
+- signed int v7; // edi
+- int v8; // edx
+- int v9; // edx
+- signed int v10; // edi
+- char v11; // al
+- signed int v12; // ecx
+- int v13; // eax
+- int v14; // eax
+- char *v15; // edi
+- int v16; // esi
+- int v17; // ecx
+- int v18; // edx
+- int v21; // esi
+- ItemStruct *v22; // edi
+- ItemStruct *v23; // ecx
+- int v24; // eax
+- int v25; // eax
+- int v26; // edx
+- ItemStruct *v27; // esi
+- int v28; // eax
+- int v29; // ecx
+- int v30; // esi
+- int v31; // eax
+- int v32; // eax
+- int v33; // ecx
+- int v34; // eax
+- int v35; // ecx
+- char *v36; // eax
+- int v37; // edx
+- int v38; // ecx
+- int v39; // edi
+- int v40; // esi
+- int v41; // ebx
+- int v42; // edx
+- int v43; // eax
+- int v44; // eax
+- signed int v45; // ecx
+- int v46; // edx
+- char *v47; // eax
+- int v48; // edi
+- int v49; // eax
+- int v50; // ecx
+- char *v51; // esi
+- char v52; // cl
+- int v53; // ecx
+- int v54; // eax
+- int v55; // edi
+- int v56; // edx
+- int v57; // esi
+- int v58; // ebx
+- int v59; // eax
+- int v60; // esi
+- ItemStruct tempitem; // [esp+Ch] [ebp-190h]
+- int v62; // [esp+17Ch] [ebp-20h]
+- int p; // [esp+180h] [ebp-1Ch]
+- int v64; // [esp+184h] [ebp-18h]
+- int v65; // [esp+188h] [ebp-14h]
+- int v66; // [esp+18Ch] [ebp-10h]
+- int v67; // [esp+190h] [ebp-Ch]
+- int v68; // [esp+194h] [ebp-8h]
+- int v69; // [esp+198h] [ebp-4h]
+- int cursor_id; // [esp+1A4h] [ebp+8h]
+- int cursor_ida; // [esp+1A4h] [ebp+8h]
+-
+- p = pnum;
+- v3 = pnum;
+- v4 = mx;
++ int r, sx, sy;
++ int i, j, xx, yy, ii;
++ BOOL done, done2h;
++ int il, cn, it, iv, ig, gt;
++ ItemStruct tempitem;
++
+ SetICursor(plr[pnum].HoldItem._iCurs + CURSOR_FIRSTITEM);
+- v5 = my + (icursH >> 1);
+- v6 = v4 + (icursW >> 1);
+- v64 = icursW28;
+- v7 = 0;
+- v67 = icursH28;
+- v68 = 0;
+- do {
+- if (v7)
+- goto LABEL_18;
+- v8 = InvRect[v68].X;
+- if (v6 >= v8 && v6 < v8 + 28) {
+- v9 = InvRect[v68].Y;
+- if (v5 >= v9 - 29 && v5 < v9) {
+- v7 = 1;
+- --v68;
+- }
+- }
+- if (v68 != 24)
+- goto LABEL_13;
+- if (!(v64 & 1))
+- v6 -= 14;
+- if (!(v67 & 1)) {
+- v5 -= 14;
+- LABEL_13:
+- if (v68 == 64 && !(v67 & 1))
+- v5 += 14;
+- }
+- ++v68;
+- } while ((unsigned int)v68 < 0x49);
+- if (!v7)
++ i = mx + (icursW >> 1);
++ j = my + (icursH >> 1);
++ sx = icursW28;
++ sy = icursH28;
++ done = FALSE;
++ for (r = 0; r < sizeof(InvRect) / sizeof(InvRect[0]) && !done; r++) {
++ if (i >= InvRect[r].X && i < InvRect[r].X + INV_SLOT_SIZE_PX) {
++ if (j >= InvRect[r].Y - INV_SLOT_SIZE_PX - 1 && j < InvRect[r].Y) {
++ done = TRUE;
++ r--;
++ }
++ }
++ if (r == 24) {
++ if ((sx & 1) == 0)
++ i -= 14;
++ if ((sy & 1) == 0) {
++ j -= 14;
++ }
++ }
++ if (r == 64 && (sy & 1) == 0)
++ j += 14;
++ }
++ if (!done)
+ return;
+-LABEL_18:
+- v10 = v68;
+- v69 = ILOC_UNEQUIPABLE;
+- if (v68 >= 0 && v68 <= ILOC_ARMOR)
+- v69 = ILOC_HELM;
+- if (v68 >= ILOC_HELM && v68 <= ILOC_RING)
+- v69 = ILOC_RING;
+- if (v68 == ILOC_AMULET)
+- v69 = ILOC_AMULET;
+- if (v68 >= ILOC_UNEQUIPABLE && v68 <= 18)
+- v69 = ILOC_ONEHAND;
+- if (v68 >= 19 && v68 <= 24)
+- v69 = ILOC_ARMOR;
+- if (v68 >= 65 && v68 <= 72)
+- v69 = ILOC_BELT;
+- v11 = plr[v3].HoldItem._iLoc;
+- v12 = 0;
+- if ((char)v11 == v69)
+- v12 = 1;
+- if (v69 == 1 && v11 == ILOC_TWOHAND) {
+- v69 = ILOC_TWOHAND;
+- v12 = 1;
+- }
+- if (v11 != 7 || v69 != ILOC_BELT) {
+- LABEL_50:
+- if (v69 != ILOC_UNEQUIPABLE)
+- goto LABEL_81;
+- v66 = 0;
+- cursor_id = 1;
+- v13 = (v68 - 25) / 10;
+- if (plr[v3].HoldItem._itype == ITYPE_GOLD) {
+- _LOBYTE(v13) = plr[0].InvGrid[10 * v13 + v3 * 21720 + (v68 - 25) % 10];
+- if (!(_BYTE)v13)
+- goto LABEL_93;
+- v13 = (char)v13;
+- if ((char)v13 <= 0) {
+- v13 = -v13;
+- } else if (*(int *)((char *)&plr[0].InvBody[v13 + 6]._itype + v3 * 21720) == ITYPE_GOLD) {
+- goto LABEL_93;
+- }
+- v66 = v13;
+- LABEL_93:
+- v21 = p;
+- if (p == myplr) {
+- PlaySFX(ItemInvSnds[ItemCAnimTbl[plr[v3].HoldItem._iCurs]]);
+- v10 = v68;
+- }
+- cursor_ida = 1;
+- switch (v69) {
+- case ILOC_ONEHAND:
+- if (v10 > 12) {
+- if (plr[v3].InvBody[INVLOC_HAND_RIGHT]._itype == ITYPE_NONE) {
+- v25 = plr[v3].InvBody[INVLOC_HAND_LEFT]._itype;
+- if (v25 == ITYPE_NONE)
+- goto LABEL_232;
+- if (plr[v3].InvBody[INVLOC_HAND_LEFT]._iLoc == ILOC_TWOHAND) {
+- NetSendCmdDelItem(FALSE, 4u);
+- NetSendCmdChItem(FALSE, 5u);
+- SwapItem(&plr[v3].InvBody[INVLOC_HAND_RIGHT], &plr[v3].InvBody[INVLOC_HAND_LEFT]);
+- v23 = &plr[v3].InvBody[INVLOC_HAND_RIGHT];
+- LABEL_99:
+- v24 = SwapItem(v23, &plr[v3].HoldItem);
+- LABEL_172:
+- cursor_ida = v24;
+- goto LABEL_226;
+- }
+- if (v25 == ITYPE_NONE || plr[v3].InvBody[INVLOC_HAND_LEFT]._iClass != plr[v3].HoldItem._iClass) {
+- LABEL_232:
+- NetSendCmdChItem(FALSE, 5u);
+- v22 = &plr[v3].InvBody[INVLOC_HAND_RIGHT];
+- LABEL_158:
+- qmemcpy(v22, &plr[v3].HoldItem, sizeof(ItemStruct));
+- goto LABEL_226;
+- }
+- } else if (plr[v3].InvBody[INVLOC_HAND_LEFT]._itype == ITYPE_NONE
+- || plr[v3].InvBody[INVLOC_HAND_LEFT]._iClass != plr[v3].HoldItem._iClass) {
+- goto LABEL_114;
++ il = ILOC_UNEQUIPABLE;
++ if (r >= 0 && r <= 3)
++ il = ILOC_HELM;
++ if (r >= 4 && r <= 5)
++ il = ILOC_RING;
++ if (r == 6)
++ il = ILOC_AMULET;
++ if (r >= 7 && r <= 18)
++ il = ILOC_ONEHAND;
++ if (r >= 19 && r <= 24)
++ il = ILOC_ARMOR;
++ if (r >= 65 && r <= 72)
++ il = ILOC_BELT;
++ done = FALSE;
++ if (plr[pnum].HoldItem._iLoc == il)
++ done = TRUE;
++ if (il == ILOC_ONEHAND && plr[pnum].HoldItem._iLoc == ILOC_TWOHAND) {
++ il = ILOC_TWOHAND;
++ done = TRUE;
++ }
++ if (plr[pnum].HoldItem._iLoc == ILOC_UNEQUIPABLE && il == ILOC_BELT) {
++ if (sx == 1 && sy == 1) {
++ done = TRUE;
++ if (!AllItemsList[plr[pnum].HoldItem.IDidx].iUsable)
++ done = FALSE;
++ if (!plr[pnum].HoldItem._iStatFlag)
++ done = FALSE;
++ if (plr[pnum].HoldItem._itype == ITYPE_GOLD)
++ done = FALSE;
++ }
++ }
++
++ if (il == ILOC_UNEQUIPABLE) {
++ done = TRUE;
++ it = 0;
++ ii = r - 25;
++ if (plr[pnum].HoldItem._itype == ITYPE_GOLD) {
++ yy = 10 * (ii / 10);
++ xx = ii % 10;
++ if (plr[pnum].InvGrid[xx + yy] != 0) {
++ iv = plr[pnum].InvGrid[xx + yy];
++ if (iv > 0) {
++ if (plr[pnum].InvList[iv - 1]._itype != ITYPE_GOLD) {
++ it = iv;
+ }
+ } else {
+- if (plr[v3].InvBody[INVLOC_HAND_LEFT]._itype == ITYPE_NONE) {
+- if (plr[v3].InvBody[INVLOC_HAND_RIGHT]._itype != ITYPE_NONE
+- && plr[v3].InvBody[INVLOC_HAND_RIGHT]._iClass == plr[v3].HoldItem._iClass) {
+- LABEL_114:
+- NetSendCmdChItem(FALSE, 5u);
+- v23 = &plr[v3].InvBody[INVLOC_HAND_RIGHT];
+- goto LABEL_99;
++ it = -iv;
++ }
++ }
++ } else {
++ yy = 10 * ((ii / 10) - ((sy - 1) >> 1));
++ if (yy < 0)
++ yy = 0;
++ for (j = 0; j < sy && done; j++) {
++ if (yy >= NUM_INV_GRID_ELEM)
++ done = FALSE;
++ xx = (ii % 10) - ((sx - 1) >> 1);
++ if (xx < 0)
++ xx = 0;
++ for (i = 0; i < sx && done; i++) {
++ if (xx >= 10) {
++ done = FALSE;
++ } else {
++ if (plr[pnum].InvGrid[xx + yy] != 0) {
++ iv = plr[pnum].InvGrid[xx + yy];
++ if (iv < 0)
++ iv = -iv;
++ if (it != 0) {
++ if (it != iv)
++ done = FALSE;
++ } else
++ it = iv;
+ }
+- NetSendCmdChItem(FALSE, 4u);
+- v22 = &plr[v3].InvBody[INVLOC_HAND_LEFT];
+- goto LABEL_158;
+- }
+- if (plr[v3].InvBody[INVLOC_HAND_RIGHT]._itype != ITYPE_NONE
+- && plr[v3].InvBody[INVLOC_HAND_RIGHT]._iClass == plr[v3].HoldItem._iClass) {
+- goto LABEL_114;
+ }
++ xx++;
+ }
+- NetSendCmdChItem(FALSE, 4u);
+- v23 = &plr[v3].InvBody[INVLOC_HAND_LEFT];
+- goto LABEL_99;
+- case ILOC_TWOHAND:
+- NetSendCmdDelItem(FALSE, 5u);
+- if (plr[v3].InvBody[INVLOC_HAND_LEFT]._itype == ITYPE_NONE)
+- goto LABEL_147;
+- v26 = plr[v3].InvBody[INVLOC_HAND_RIGHT]._itype;
+- if (v26 == -1)
+- goto LABEL_146;
+- qmemcpy(&tempitem, &plr[v3].HoldItem, sizeof(tempitem));
+- v27 = &plr[v3].InvBody[INVLOC_HAND_RIGHT];
+- if (v26 != ITYPE_SHIELD)
+- v27 = &plr[v3].InvBody[INVLOC_HAND_LEFT];
+- v28 = p;
+- qmemcpy(&plr[v3].HoldItem, v27, sizeof(plr[v3].HoldItem));
+- v29 = plr[v3].HoldItem._iCurs + CURSOR_FIRSTITEM;
+- if (v28 == myplr)
+- SetCursor_(v29);
+- else
+- SetICursor(v29);
+- v67 = 0;
+- v30 = 0;
+- do {
+- if (v67)
+- break;
+- v31 = AutoPlace(p, v30++, icursW28, icursH28, 1);
+- v67 = v31;
+- } while (v30 < 40);
+- v32 = p;
+- qmemcpy(&plr[v3].HoldItem, &tempitem, sizeof(plr[v3].HoldItem));
+- v33 = plr[v3].HoldItem._iCurs + CURSOR_FIRSTITEM;
+- if (v32 == myplr)
+- SetCursor_(v33);
+- else
+- SetICursor(v33);
+- if (!v67)
+- return;
+- if (plr[v3].InvBody[INVLOC_HAND_RIGHT]._itype == ITYPE_SHIELD)
+- plr[v3].InvBody[INVLOC_HAND_RIGHT]._itype = ITYPE_NONE;
+- else
+- plr[v3].InvBody[INVLOC_HAND_LEFT]._itype = ITYPE_NONE;
+- LABEL_146:
+- if (plr[v3].InvBody[INVLOC_HAND_LEFT]._itype != ITYPE_NONE)
+- goto LABEL_149;
+- LABEL_147:
+- if (plr[v3].InvBody[INVLOC_HAND_RIGHT]._itype == ITYPE_NONE) {
+- NetSendCmdChItem(FALSE, 4u);
+- qmemcpy(&plr[v3].InvBody[INVLOC_HAND_LEFT], &plr[v3].HoldItem, sizeof(plr[v3].InvBody[INVLOC_HAND_LEFT]));
++ yy += 10;
++ }
++ }
++ }
++
++ if (!done)
++ return;
++
++ if (il != ILOC_UNEQUIPABLE && il != ILOC_BELT && !plr[pnum].HoldItem._iStatFlag) {
++ done = FALSE;
++ if (plr[pnum]._pClass == PC_WARRIOR)
++ PlaySFX(PS_WARR13);
++ else if (plr[pnum]._pClass == PC_ROGUE)
++ PlaySFX(PS_ROGUE13);
++ else if (plr[pnum]._pClass == PC_SORCERER)
++ PlaySFX(PS_MAGE13);
++ }
++
++ if (!done)
++ return;
++
++ if (pnum == myplr)
++ PlaySFX(ItemInvSnds[ItemCAnimTbl[plr[pnum].HoldItem._iCurs]]);
++
++ cn = CURSOR_HAND;
++ switch (il) {
++ case ILOC_HELM:
++ NetSendCmdChItem(FALSE, INVLOC_HEAD);
++ if (plr[pnum].InvBody[INVLOC_HEAD]._itype == ITYPE_NONE)
++ plr[pnum].InvBody[INVLOC_HEAD] = plr[pnum].HoldItem;
++ else
++ cn = SwapItem(&plr[pnum].InvBody[INVLOC_HEAD], &plr[pnum].HoldItem);
++ break;
++ case ILOC_RING:
++ if (r == 4) {
++ NetSendCmdChItem(FALSE, INVLOC_RING_LEFT);
++ if (plr[pnum].InvBody[INVLOC_RING_LEFT]._itype == ITYPE_NONE)
++ plr[pnum].InvBody[INVLOC_RING_LEFT] = plr[pnum].HoldItem;
++ else
++ cn = SwapItem(&plr[pnum].InvBody[INVLOC_RING_LEFT], &plr[pnum].HoldItem);
++ } else {
++ NetSendCmdChItem(FALSE, INVLOC_RING_RIGHT);
++ if (plr[pnum].InvBody[INVLOC_RING_RIGHT]._itype == ITYPE_NONE)
++ plr[pnum].InvBody[INVLOC_RING_RIGHT] = plr[pnum].HoldItem;
++ else
++ cn = SwapItem(&plr[pnum].InvBody[INVLOC_RING_RIGHT], &plr[pnum].HoldItem);
++ }
++ break;
++ case ILOC_AMULET:
++ NetSendCmdChItem(0, INVLOC_AMULET);
++ if (plr[pnum].InvBody[INVLOC_AMULET]._itype == ITYPE_NONE)
++ plr[pnum].InvBody[INVLOC_AMULET] = plr[pnum].HoldItem;
++ else
++ cn = SwapItem(&plr[pnum].InvBody[INVLOC_AMULET], &plr[pnum].HoldItem);
++ break;
++ case ILOC_ONEHAND:
++ if (r <= 12) {
++ if (plr[pnum].InvBody[INVLOC_HAND_LEFT]._itype == ITYPE_NONE) {
++ if (plr[pnum].InvBody[INVLOC_HAND_RIGHT]._itype == ITYPE_NONE || plr[pnum].InvBody[INVLOC_HAND_RIGHT]._iClass != plr[pnum].HoldItem._iClass) {
++ NetSendCmdChItem(FALSE, INVLOC_HAND_LEFT);
++ plr[pnum].InvBody[INVLOC_HAND_LEFT] = plr[pnum].HoldItem;
+ } else {
+- LABEL_149:
+- NetSendCmdChItem(FALSE, 4u);
+- if (plr[v3].InvBody[INVLOC_HAND_LEFT]._itype == ITYPE_NONE)
+- SwapItem(&plr[v3].InvBody[INVLOC_HAND_LEFT], &plr[v3].InvBody[INVLOC_HAND_RIGHT]);
+- cursor_ida = SwapItem(&plr[v3].InvBody[INVLOC_HAND_LEFT], &plr[v3].HoldItem);
+- }
+- if (plr[v3].InvBody[INVLOC_HAND_LEFT]._itype == ITYPE_STAFF) {
+- v34 = plr[v3].InvBody[INVLOC_HAND_LEFT]._iSpell;
+- if (v34) {
+- if (plr[v3].InvBody[INVLOC_HAND_LEFT]._iCharges > 0) {
+- plr[v3]._pRSpell = v34;
+- _LOBYTE(plr[v3]._pRSplType) = RSPLTYPE_CHARGES;
+- drawpanflag = 255;
+- }
+- }
++ NetSendCmdChItem(FALSE, INVLOC_HAND_RIGHT);
++ cn = SwapItem(&plr[pnum].InvBody[INVLOC_HAND_RIGHT], &plr[pnum].HoldItem);
+ }
+- goto LABEL_226;
+- case ILOC_ARMOR:
+- NetSendCmdChItem(FALSE, 6u);
+- if (plr[v3].InvBody[INVLOC_CHEST]._itype == ITYPE_NONE) {
+- v22 = &plr[v3].InvBody[INVLOC_CHEST];
+- goto LABEL_158;
+- }
+- v23 = &plr[v3].InvBody[INVLOC_CHEST];
+- goto LABEL_99;
+- case ILOC_HELM:
+- NetSendCmdChItem(FALSE, 0);
+- if (plr[v3].InvBody[INVLOC_HEAD]._itype == ITYPE_NONE) {
+- v22 = plr[v3].InvBody;
+- goto LABEL_158;
+- }
+- v23 = plr[v3].InvBody;
+- goto LABEL_99;
+- case ILOC_RING:
+- if (v10 == 4) {
+- NetSendCmdChItem(FALSE, 1u);
+- if (plr[v3].InvBody[INVLOC_RING_LEFT]._itype == ITYPE_NONE) {
+- v22 = &plr[v3].InvBody[INVLOC_RING_LEFT];
+- goto LABEL_158;
+- }
+- v23 = &plr[v3].InvBody[INVLOC_RING_LEFT];
++ break;
++ }
++ if (plr[pnum].InvBody[INVLOC_HAND_RIGHT]._itype == ITYPE_NONE || plr[pnum].InvBody[INVLOC_HAND_RIGHT]._iClass != plr[pnum].HoldItem._iClass) {
++ NetSendCmdChItem(FALSE, INVLOC_HAND_LEFT);
++ cn = SwapItem(&plr[pnum].InvBody[INVLOC_HAND_LEFT], &plr[pnum].HoldItem);
++ break;
++ }
++
++ NetSendCmdChItem(FALSE, INVLOC_HAND_RIGHT);
++ cn = SwapItem(&plr[pnum].InvBody[INVLOC_HAND_RIGHT], &plr[pnum].HoldItem);
++ break;
++ }
++ if (plr[pnum].InvBody[INVLOC_HAND_RIGHT]._itype == ITYPE_NONE) {
++ if (plr[pnum].InvBody[INVLOC_HAND_LEFT]._itype == ITYPE_NONE || plr[pnum].InvBody[INVLOC_HAND_LEFT]._iLoc != ILOC_TWOHAND) {
++ if (plr[pnum].InvBody[INVLOC_HAND_LEFT]._itype == ITYPE_NONE || plr[pnum].InvBody[INVLOC_HAND_LEFT]._iClass != plr[pnum].HoldItem._iClass) {
++ NetSendCmdChItem(FALSE, INVLOC_HAND_RIGHT);
++ plr[pnum].InvBody[INVLOC_HAND_RIGHT] = plr[pnum].HoldItem;
++ break;
++ }
++ NetSendCmdChItem(FALSE, INVLOC_HAND_LEFT);
++ cn = SwapItem(&plr[pnum].InvBody[INVLOC_HAND_LEFT], &plr[pnum].HoldItem);
++ break;
++ }
++ NetSendCmdDelItem(FALSE, INVLOC_HAND_LEFT);
++ NetSendCmdChItem(FALSE, INVLOC_HAND_RIGHT);
++ SwapItem(&plr[pnum].InvBody[INVLOC_HAND_RIGHT], &plr[pnum].InvBody[INVLOC_HAND_LEFT]);
++ cn = SwapItem(&plr[pnum].InvBody[INVLOC_HAND_RIGHT], &plr[pnum].HoldItem);
++ break;
++ }
++
++ if (plr[pnum].InvBody[INVLOC_HAND_LEFT]._itype != ITYPE_NONE && plr[pnum].InvBody[INVLOC_HAND_LEFT]._iClass == plr[pnum].HoldItem._iClass) {
++ NetSendCmdChItem(FALSE, INVLOC_HAND_LEFT);
++ cn = SwapItem(&plr[pnum].InvBody[INVLOC_HAND_LEFT], &plr[pnum].HoldItem);
++ break;
++ }
++ NetSendCmdChItem(FALSE, INVLOC_HAND_RIGHT);
++ cn = SwapItem(&plr[pnum].InvBody[INVLOC_HAND_RIGHT], &plr[pnum].HoldItem);
++ break;
++ case ILOC_TWOHAND:
++ NetSendCmdDelItem(FALSE, INVLOC_HAND_RIGHT);
++ if (plr[pnum].InvBody[INVLOC_HAND_LEFT]._itype != ITYPE_NONE && plr[pnum].InvBody[INVLOC_HAND_RIGHT]._itype != ITYPE_NONE) {
++ tempitem = plr[pnum].HoldItem;
++ if (plr[pnum].InvBody[INVLOC_HAND_RIGHT]._itype == ITYPE_SHIELD)
++ plr[pnum].HoldItem = plr[pnum].InvBody[INVLOC_HAND_RIGHT];
++ else
++ plr[pnum].HoldItem = plr[pnum].InvBody[INVLOC_HAND_LEFT];
++ if (pnum == myplr)
++ SetCursor_(plr[pnum].HoldItem._iCurs + CURSOR_FIRSTITEM);
++ else
++ SetICursor(plr[pnum].HoldItem._iCurs + CURSOR_FIRSTITEM);
++ done2h = FALSE;
++ for (i = 0; i < NUM_INV_GRID_ELEM && !done2h; i++)
++ done2h = AutoPlace(pnum, i, icursW28, icursH28, TRUE);
++ plr[pnum].HoldItem = tempitem;
++ if (pnum == myplr)
++ SetCursor_(plr[pnum].HoldItem._iCurs + CURSOR_FIRSTITEM);
++ else
++ SetICursor(plr[pnum].HoldItem._iCurs + CURSOR_FIRSTITEM);
++ if (!done2h)
++ return;
++
++ if (plr[pnum].InvBody[INVLOC_HAND_RIGHT]._itype == ITYPE_SHIELD)
++ plr[pnum].InvBody[INVLOC_HAND_RIGHT]._itype = ITYPE_NONE;
++ else
++ plr[pnum].InvBody[INVLOC_HAND_LEFT]._itype = ITYPE_NONE;
++ }
++
++ if (plr[pnum].InvBody[INVLOC_HAND_LEFT]._itype != ITYPE_NONE || plr[pnum].InvBody[INVLOC_HAND_RIGHT]._itype != ITYPE_NONE) {
++ NetSendCmdChItem(FALSE, INVLOC_HAND_LEFT);
++ if (plr[pnum].InvBody[INVLOC_HAND_LEFT]._itype == ITYPE_NONE)
++ SwapItem(&plr[pnum].InvBody[INVLOC_HAND_LEFT], &plr[pnum].InvBody[INVLOC_HAND_RIGHT]);
++ cn = SwapItem(&plr[pnum].InvBody[INVLOC_HAND_LEFT], &plr[pnum].HoldItem);
++ } else {
++ NetSendCmdChItem(FALSE, INVLOC_HAND_LEFT);
++ plr[pnum].InvBody[INVLOC_HAND_LEFT] = plr[pnum].HoldItem;
++ }
++ if (plr[pnum].InvBody[INVLOC_HAND_LEFT]._itype == ITYPE_STAFF && plr[pnum].InvBody[INVLOC_HAND_LEFT]._iSpell != 0 && plr[pnum].InvBody[INVLOC_HAND_LEFT]._iCharges > 0) {
++ plr[pnum]._pRSpell = plr[pnum].InvBody[INVLOC_HAND_LEFT]._iSpell;
++ plr[pnum]._pRSplType = RSPLTYPE_CHARGES;
++ drawpanflag = 255;
++ }
++ break;
++ case ILOC_ARMOR:
++ NetSendCmdChItem(FALSE, INVLOC_CHEST);
++ if (plr[pnum].InvBody[INVLOC_CHEST]._itype == ITYPE_NONE)
++ plr[pnum].InvBody[INVLOC_CHEST] = plr[pnum].HoldItem;
++ else
++ cn = SwapItem(&plr[pnum].InvBody[INVLOC_CHEST], &plr[pnum].HoldItem);
++ break;
++ case ILOC_UNEQUIPABLE:
++ if (plr[pnum].HoldItem._itype == ITYPE_GOLD && it == 0) {
++ ii = r - 25;
++ yy = 10 * (ii / 10);
++ xx = ii % 10;
++ if (plr[pnum].InvGrid[yy + xx] > 0) {
++ il = plr[pnum].InvGrid[yy + xx];
++ il--;
++ gt = plr[pnum].InvList[il]._ivalue;
++ ig = plr[pnum].HoldItem._ivalue + gt;
++ if (ig <= 5000) {
++ plr[pnum].InvList[il]._ivalue = ig;
++ plr[pnum]._pGold += plr[pnum].HoldItem._ivalue;
++ if (ig >= 2500)
++ plr[pnum].InvList[il]._iCurs = ICURS_GOLD_LARGE;
++ else if (ig <= 1000)
++ plr[pnum].InvList[il]._iCurs = ICURS_GOLD_SMALL;
++ else
++ plr[pnum].InvList[il]._iCurs = ICURS_GOLD_MEDIUM;
+ } else {
+- NetSendCmdChItem(FALSE, 2u);
+- if (plr[v3].InvBody[INVLOC_RING_RIGHT]._itype == ITYPE_NONE) {
+- v22 = &plr[v3].InvBody[INVLOC_RING_RIGHT];
+- goto LABEL_158;
+- }
+- v23 = &plr[v3].InvBody[INVLOC_RING_RIGHT];
++ ig = 5000 - gt;
++ plr[pnum]._pGold += ig;
++ plr[pnum].HoldItem._ivalue -= ig;
++ plr[pnum].InvList[il]._ivalue = 5000;
++ plr[pnum].InvList[il]._iCurs = ICURS_GOLD_LARGE;
++ // BUGFIX: incorrect values here are leftover from beta
++ if (plr[pnum].HoldItem._ivalue >= 2500)
++ cn = 18;
++ else if (plr[pnum].HoldItem._ivalue <= 1000)
++ cn = 16;
++ else
++ cn = 17;
+ }
+- goto LABEL_99;
+- case ILOC_AMULET:
+- NetSendCmdChItem(FALSE, 3u);
+- if (plr[v3].InvBody[INVLOC_AMULET]._itype == ITYPE_NONE) {
+- v22 = &plr[v3].InvBody[INVLOC_AMULET];
+- goto LABEL_158;
+- }
+- v23 = &plr[v3].InvBody[INVLOC_AMULET];
+- goto LABEL_99;
+- case ILOC_UNEQUIPABLE:
+- v35 = plr[v3].HoldItem._itype;
+- if (v35 == ITYPE_GOLD) {
+- if (!v66) {
+- v36 = &plr[0].InvGrid[10 * ((v68 - 25) / 10) + v3 * 21720 + (v68 - 25) % 10];
+- if (*v36 <= 0) {
+- v42 = 368 * plr[v3]._pNumInv + v3 * 21720;
+- qmemcpy((char *)plr[0].InvList + v42, &plr[v3].HoldItem, 0x170u);
+- ++plr[v3]._pNumInv;
+- *v36 = plr[v3]._pNumInv;
+- v43 = plr[v3].HoldItem._ivalue;
+- plr[v3]._pGold += v43;
+- if (v43 <= 5000) {
+- if (v43 < 2500) {
+- if (v43 > 1000)
+- *(int *)((char *)&plr[0].InvList[0]._iCurs + v42) = 5;
+- else
+- *(int *)((char *)&plr[0].InvList[0]._iCurs + v42) = 4;
+- } else {
+- *(int *)((char *)&plr[0].InvList[0]._iCurs + v42) = 6;
+- }
+- }
+- goto LABEL_226;
+- }
+- v37 = plr[v3].HoldItem._ivalue;
+- v38 = 368 * (*v36 - 1) + v3 * 21720;
+- v39 = *(int *)((char *)&plr[0].InvList[0]._ivalue + v38);
+- v40 = v37 + v39;
+- if (v37 + v39 <= 5000) {
+- *(int *)((char *)&plr[0].InvList[0]._ivalue + v38) = v40;
+- plr[v3]._pGold += plr[v3].HoldItem._ivalue;
+- if (v40 < 2500) {
+- if (v40 > 1000)
+- *(int *)((char *)&plr[0].InvList[0]._iCurs + v38) = 5;
+- else
+- *(int *)((char *)&plr[0].InvList[0]._iCurs + v38) = 4;
+- } else {
+- *(int *)((char *)&plr[0].InvList[0]._iCurs + v38) = 6;
+- }
+- goto LABEL_226;
+- }
+- plr[v3]._pGold += 5000 - v39;
+- plr[v3].HoldItem._ivalue = v37 - (5000 - v39);
+- *(int *)((char *)&plr[0].InvList[0]._ivalue + v38) = 5000;
+- *(int *)((char *)&plr[0].InvList[0]._iCurs + v38) = 6;
+- v41 = plr[v3].HoldItem._ivalue;
+- if (v41 >= 2500) {
+- cursor_ida = 18;
+- goto LABEL_226;
+- }
+- v24 = (v41 > 1000) + 16;
+- goto LABEL_172;
+- }
+- } else if (!v66) {
+- qmemcpy((char *)&plr[0].InvList[plr[v3]._pNumInv++] + v3 * 21720, &plr[v3].HoldItem, 0x170u);
+- v66 = plr[v3]._pNumInv;
+- LABEL_191:
+- v48 = v67;
+- v49 = 10 * ((v68 - 25) / 10 - ((v67 - 1) >> 1));
+- if (v49 < 0)
+- v49 = 0;
+- v65 = 0;
+- if (v67 > 0) {
+- v69 = (v68 - 25) % 10 - ((v64 - 1) >> 1);
+- do {
+- v50 = v69;
+- if (v69 < 0)
+- v50 = 0;
+- v67 = 0;
+- if (v64 > 0) {
+- v51 = &plr[v3].InvGrid[v50 + v49];
+- do {
+- if (v67 || v65 != v48 - 1)
+- v52 = -(char)v66;
+- else
+- v52 = v66;
+- *v51++ = v52;
+- ++v67;
+- } while (v67 < v64);
+- }
+- v49 += 10;
+- ++v65;
+- } while (v65 < v48);
+- }
+- goto LABEL_226;
++ } else {
++ il = plr[pnum]._pNumInv;
++ plr[pnum].InvList[il] = plr[pnum].HoldItem;
++ plr[pnum]._pNumInv++;
++ plr[pnum].InvGrid[yy + xx] = plr[pnum]._pNumInv;
++ plr[pnum]._pGold += plr[pnum].HoldItem._ivalue;
++ if (plr[pnum].HoldItem._ivalue <= 5000) {
++ if (plr[pnum].HoldItem._ivalue >= 2500)
++ plr[pnum].InvList[il]._iCurs = ICURS_GOLD_LARGE;
++ else if (plr[pnum].HoldItem._ivalue <= 1000)
++ plr[pnum].InvList[il]._iCurs = ICURS_GOLD_SMALL;
++ else
++ plr[pnum].InvList[il]._iCurs = ICURS_GOLD_MEDIUM;
+ }
+- v44 = v66 - 1;
+- if (v35 == ITYPE_GOLD)
+- plr[v3]._pGold += plr[v3].HoldItem._ivalue;
+- cursor_ida = SwapItem((ItemStruct *)((char *)&plr[0].InvList[v44] + v3 * 21720), &plr[v3].HoldItem);
+- if (plr[v3].HoldItem._itype == ITYPE_GOLD)
+- plr[v3]._pGold = CalculateGold(v21);
+- v45 = 0;
+- v46 = -v66;
+- do {
+- v47 = &plr[v3].InvGrid[v45];
+- if (*v47 == v66)
+- *v47 = 0;
+- if (*v47 == v46)
+- *v47 = 0;
+- ++v45;
+- } while (v45 < 40);
+- goto LABEL_191;
+- case ILOC_BELT:
+- v53 = v3 * 21720 + 368 * (v68 - 65);
+- if (plr[v3].HoldItem._itype != ITYPE_GOLD) {
+- if (*(int *)((char *)&plr[0].SpdList[0]._itype + v53) == ITYPE_NONE) {
+- qmemcpy((char *)plr[0].SpdList + v53, &plr[v3].HoldItem, 0x170u);
+- } else {
+- cursor_ida = SwapItem((ItemStruct *)((char *)plr[0].SpdList + v53), &plr[v3].HoldItem);
+- if (plr[v3].HoldItem._itype == ITYPE_GOLD)
+- plr[v3]._pGold = CalculateGold(p);
+- }
+- goto LABEL_225;
++ }
++ } else {
++ if (it == 0) {
++ plr[pnum].InvList[plr[pnum]._pNumInv] = plr[pnum].HoldItem;
++ plr[pnum]._pNumInv++;
++ it = plr[pnum]._pNumInv;
++ } else {
++ il = it - 1;
++ if (plr[pnum].HoldItem._itype == ITYPE_GOLD)
++ plr[pnum]._pGold += plr[pnum].HoldItem._ivalue;
++ cn = SwapItem(&plr[pnum].InvList[il], &plr[pnum].HoldItem);
++ if (plr[pnum].HoldItem._itype == ITYPE_GOLD)
++ plr[pnum]._pGold = CalculateGold(pnum);
++ for (i = 0; i < NUM_INV_GRID_ELEM; i++) {
++ if (plr[pnum].InvGrid[i] == it)
++ plr[pnum].InvGrid[i] = 0;
++ if (plr[pnum].InvGrid[i] == -it)
++ plr[pnum].InvGrid[i] = 0;
++ }
++ }
++ ii = r - 25;
++ yy = 10 * (ii / 10 - ((sy - 1) >> 1));
++ if (yy < 0)
++ yy = 0;
++ for (j = 0; j < sy; j++) {
++ xx = (ii % 10 - ((sx - 1) >> 1));
++ if (xx < 0)
++ xx = 0;
++ for (i = 0; i < sx; i++) {
++ if (i != 0 || j != sy - 1)
++ plr[pnum].InvGrid[xx + yy] = -it;
++ else
++ plr[pnum].InvGrid[xx + yy] = it;
++ xx++;
+ }
+- v54 = *(int *)((char *)&plr[0].SpdList[0]._itype + v53);
+- if (v54 != ITYPE_NONE) {
+- if (v54 == ITYPE_GOLD) {
+- v55 = *(int *)((char *)&plr[0].SpdList[0]._ivalue + v53);
+- v56 = plr[v3].HoldItem._ivalue;
+- v57 = v55 + v56;
+- if (v55 + v56 <= 5000) {
+- *(int *)((char *)&plr[0].SpdList[0]._ivalue + v53) = v57;
+- plr[v3]._pGold += plr[v3].HoldItem._ivalue;
+- if (v57 < 2500) {
+- if (v57 > 1000)
+- *(int *)((char *)&plr[0].SpdList[0]._iCurs + v53) = 5;
+- else
+- *(int *)((char *)&plr[0].SpdList[0]._iCurs + v53) = 4;
+- } else {
+- *(int *)((char *)&plr[0].SpdList[0]._iCurs + v53) = 6;
+- }
+- goto LABEL_225;
+- }
+- plr[v3]._pGold += 5000 - v55;
+- plr[v3].HoldItem._ivalue = v56 - (5000 - v55);
+- *(int *)((char *)&plr[0].SpdList[0]._ivalue + v53) = 5000;
+- *(int *)((char *)&plr[0].SpdList[0]._iCurs + v53) = 6;
+- v58 = plr[v3].HoldItem._ivalue;
+- if (v58 >= 2500) {
+- cursor_ida = 18;
+- goto LABEL_225;
+- }
+- v59 = (v58 > 1000) + 16;
++ yy += 10;
++ }
++ }
++ break;
++ case ILOC_BELT:
++ ii = r - 65;
++ if (plr[pnum].HoldItem._itype == ITYPE_GOLD) {
++ if (plr[pnum].SpdList[ii]._itype != ITYPE_NONE) {
++ if (plr[pnum].SpdList[ii]._itype == ITYPE_GOLD) {
++ i = plr[pnum].HoldItem._ivalue + plr[pnum].SpdList[ii]._ivalue;
++ if (i <= 5000) {
++ plr[pnum].SpdList[ii]._ivalue += plr[pnum].HoldItem._ivalue;
++ plr[pnum]._pGold += plr[pnum].HoldItem._ivalue;
++ if (i >= 2500)
++ plr[pnum].SpdList[ii]._iCurs = ICURS_GOLD_LARGE;
++ else if (i <= 1000)
++ plr[pnum].SpdList[ii]._iCurs = ICURS_GOLD_SMALL;
++ else
++ plr[pnum].SpdList[ii]._iCurs = ICURS_GOLD_MEDIUM;
+ } else {
+- plr[v3]._pGold += plr[v3].HoldItem._ivalue;
+- v59 = SwapItem((ItemStruct *)((char *)plr[0].SpdList + v53), &plr[v3].HoldItem);
++ i = 5000 - plr[pnum].SpdList[ii]._ivalue;
++ plr[pnum]._pGold += i;
++ plr[pnum].HoldItem._ivalue -= i;
++ plr[pnum].SpdList[ii]._ivalue = 5000;
++ plr[pnum].SpdList[ii]._iCurs = ICURS_GOLD_LARGE;
++
++ // BUGFIX: incorrect values here are leftover from beta
++ if (plr[pnum].HoldItem._ivalue >= 2500)
++ cn = 18;
++ else if (plr[pnum].HoldItem._ivalue <= 1000)
++ cn = 16;
++ else
++ cn = 17;
+ }
+- cursor_ida = v59;
+- goto LABEL_225;
+- }
+- qmemcpy((char *)plr[0].SpdList + v53, &plr[v3].HoldItem, 0x170u);
+- plr[v3]._pGold += plr[v3].HoldItem._ivalue;
+- LABEL_225:
+- drawsbarflag = TRUE;
+- LABEL_226:
+- v60 = p;
+- CalcPlrInv(p, 1u);
+- if (v60 == myplr) {
+- if (cursor_ida == 1)
+- SetCursorPos(MouseX + (cursW >> 1), MouseY + (cursH >> 1));
+- SetCursor_(cursor_ida);
++ } else {
++ plr[pnum]._pGold += plr[pnum].HoldItem._ivalue;
++ cn = SwapItem(&plr[pnum].SpdList[ii], &plr[pnum].HoldItem);
+ }
+- return;
+- default:
+- goto LABEL_226;
++ } else {
++ plr[pnum].SpdList[ii] = plr[pnum].HoldItem;
++ plr[pnum]._pGold += plr[pnum].HoldItem._ivalue;
+ }
++ } else if (plr[pnum].SpdList[ii]._itype == ITYPE_NONE) {
++ plr[pnum].SpdList[ii] = plr[pnum].HoldItem;
++ } else {
++ cn = SwapItem(&plr[pnum].SpdList[ii], &plr[pnum].HoldItem);
++ if (plr[pnum].HoldItem._itype == 11)
++ plr[pnum]._pGold = CalculateGold(pnum);
+ }
+- v62 = (v68 - 25) % 10;
+- v14 = 10 * (v13 - ((v67 - 1) >> 1));
+- if (v14 < 0)
+- v14 = 0;
+- v65 = 0;
+- if (v67 <= 0)
+- goto LABEL_93;
+- v15 = &plr[v3].InvGrid[v14];
+- while (1) {
+- if (cursor_id == CURSOR_NONE)
+- return;
+- if (v14 >= 40)
+- cursor_id = 0;
+- v16 = v62 - ((v64 - 1) >> 1);
+- if (v16 < 0)
+- v16 = 0;
+- v17 = 0;
+- if (v64 > 0)
+- break;
+- LABEL_79:
+- v14 += 10;
+- v15 += 10;
+- if (++v65 >= v67) {
+- v12 = cursor_id;
+- v10 = v68;
+- goto LABEL_81;
+- }
+- }
+- while (1) {
+- if (cursor_id == CURSOR_NONE)
+- goto LABEL_79;
+- if (v16 >= 10)
+- goto LABEL_233;
+- _LOBYTE(v18) = v15[v16];
+- if ((_BYTE)v18) {
+- v18 = (char)v18;
+- if ((v18 & 0x80u) != 0)
+- v18 = -v18;
+- if (!v66) {
+- v66 = v18;
+- goto LABEL_78;
+- }
+- if (v66 != v18)
+- LABEL_233:
+- cursor_id = 0;
+- }
+- LABEL_78:
+- ++v16;
+- if (++v17 >= v64)
+- goto LABEL_79;
+- }
+- }
+- if (v64 == 1 && v67 == 1) {
+- v12 = 1;
+- if (!AllItemsList[plr[v3].HoldItem.IDidx].iUsable)
+- v12 = 0;
+- if (!plr[v3].HoldItem._iStatFlag)
+- v12 = 0;
+- if (plr[v3].HoldItem._itype == ITYPE_GOLD) {
+- v12 = 0;
+- goto LABEL_50;
+- }
+- }
+-LABEL_81:
+- if (!v12)
+- return;
+- if (v69 == ILOC_UNEQUIPABLE || v69 == ILOC_BELT || plr[v3].HoldItem._iStatFlag) {
+- goto LABEL_93;
++ drawsbarflag = 1;
++ break;
+ }
+- if (plr[v3]._pClass == PC_WARRIOR) {
+- PlaySFX(PS_WARR13);
+- } else if (plr[v3]._pClass == PC_ROGUE) {
+- PlaySFX(PS_ROGUE13);
+- } else if (plr[v3]._pClass == PC_SORCERER) {
+- PlaySFX(PS_MAGE13);
++ CalcPlrInv(pnum, 1);
++ if (pnum == myplr) {
++ if (cn == 1)
++ SetCursorPos(MouseX + (cursW >> 1), MouseY + (cursH >> 1));
++ SetCursor_(cn);
+ }
+ }
+-// 4B8C9C: using guessed type int cursH;
+-// 4B8CB4: using guessed type int icursH;
+-// 4B8CBC: using guessed type int icursW;
+-// 52571C: using guessed type int drawpanflag;
+
+ void CheckInvSwap(int pnum, BYTE bLoc, int idx, WORD wCI, int seed, BOOL bId)
+ {
diff --git a/games/devilutionx/patches/patch-Source_loadsave.cpp b/games/devilutionx/patches/patch-Source_loadsave.cpp
new file mode 100644
index 00000000000..dafa72b2a83
--- /dev/null
+++ b/games/devilutionx/patches/patch-Source_loadsave.cpp
@@ -0,0 +1,1092 @@
+$NetBSD: patch-Source_loadsave.cpp,v 1.1 2019/07/28 10:26:43 nia Exp $
+
+64bit Compatible Saves
+https://patch-diff.githubusercontent.com/raw/diasurgical/devilutionX/pull/162.patch
+
+[PATCH] Fix load/save monster padding
+https://github.com/diasurgical/devilutionX/commit/10ebca4efd422bbf46bad6d12ea4cdade9038b01.patch
+
+--- Source/loadsave.cpp.orig 2019-05-19 17:06:45.000000000 +0000
++++ Source/loadsave.cpp
+@@ -207,42 +207,829 @@ BOOL OLoad()
+ return FALSE;
+ }
+
++void CopyInt(const void *src, void * dst)
++{
++ memcpy(dst, src, 4);
++ tbuff += 4;
++}
++
++void CopyShort(const void *src, void * dst)
++{
++ memcpy(dst, src, 2);
++ tbuff += 2;
++}
++
++void CopyShorts(const void *src, const int n, void * dst)
++{
++ memcpy(dst, src, 2 * n);
++ tbuff += 2 * n;
++}
++
++void CopyInts(const void *src, const int n, void * dst)
++{
++ memcpy(dst, src, 4 * n);
++ tbuff += 4 * n;
++}
++
++void CopyBytes(const void *src, const int n, void * dst)
++{
++ memcpy(dst, src, n);
++ tbuff += n;
++}
++
++void CopyChar(const void *src, void * dst)
++{
++ memcpy(dst, src, 1);
++ tbuff += 1;
++}
++
++void CopyInt64(const void *src, void * dst)
++{
++ memcpy(dst, src, 8);
++ tbuff += 8;
++}
++
+ void LoadPlayer(int i)
+ {
+- memcpy(&plr[i], tbuff, sizeof(*plr) - (10 * sizeof(void *)));
+- tbuff += sizeof(*plr) - (10 * sizeof(void *)); // omit last 10 pointers
++ PlayerStruct *pPlayer = &plr[i];
++
++ CopyInt(tbuff, &pPlayer->_pmode);
++
++ CopyBytes(tbuff, 25, pPlayer->walkpath);
++ CopyBytes(tbuff, 1, &pPlayer->plractive);
++ tbuff += 2;
++
++ CopyInt(tbuff, &pPlayer->destAction);
++ CopyInt(tbuff, &pPlayer->destParam1);
++ CopyInt(tbuff, &pPlayer->destParam2);
++ CopyInt(tbuff, &pPlayer->destParam3);
++ CopyInt(tbuff, &pPlayer->destParam4);
++ CopyInt(tbuff, &pPlayer->plrlevel);
++ CopyInt(tbuff, &pPlayer->WorldX);
++ CopyInt(tbuff, &pPlayer->WorldY);
++ CopyInt(tbuff, &pPlayer->_px);
++ CopyInt(tbuff, &pPlayer->_py);
++ CopyInt(tbuff, &pPlayer->_ptargx);
++ CopyInt(tbuff, &pPlayer->_ptargy);
++ CopyInt(tbuff, &pPlayer->_pownerx);
++ CopyInt(tbuff, &pPlayer->_pownery);
++ CopyInt(tbuff, &pPlayer->_poldx);
++ CopyInt(tbuff, &pPlayer->_poldy);
++ CopyInt(tbuff, &pPlayer->_pxoff);
++ CopyInt(tbuff, &pPlayer->_pyoff);
++ CopyInt(tbuff, &pPlayer->_pxvel);
++ CopyInt(tbuff, &pPlayer->_pyvel);
++ CopyInt(tbuff, &pPlayer->_pdir);
++ CopyInt(tbuff, &pPlayer->_nextdir);
++ CopyInt(tbuff, &pPlayer->_pgfxnum);
++ tbuff += 4; // Skip pointers
++ CopyInt(tbuff, &pPlayer->_pAnimDelay);
++ CopyInt(tbuff, &pPlayer->_pAnimCnt);
++ CopyInt(tbuff, &pPlayer->_pAnimLen);
++ CopyInt(tbuff, &pPlayer->_pAnimFrame);
++ CopyInt(tbuff, &pPlayer->_pAnimWidth);
++ CopyInt(tbuff, &pPlayer->_pAnimWidth2);
++ CopyInt(tbuff, &pPlayer->_peflag);
++ CopyInt(tbuff, &pPlayer->_plid);
++ CopyInt(tbuff, &pPlayer->_pvid);
++
++ CopyInt(tbuff, &pPlayer->_pSpell);
++ CopyChar(tbuff, &pPlayer->_pSplType);
++ CopyChar(tbuff, &pPlayer->_pSplFrom);
++ tbuff += 2;
++ CopyInt(tbuff, &pPlayer->_pTSpell);
++ CopyChar(tbuff, &pPlayer->_pTSplType);
++ tbuff += 3;
++ CopyInt(tbuff, &pPlayer->_pRSpell);
++ CopyChar(tbuff, &pPlayer->_pRSplType);
++ tbuff += 3;
++ CopyInt(tbuff, &pPlayer->_pSBkSpell);
++ CopyChar(tbuff, &pPlayer->_pSBkSplType);
++
++ CopyBytes(tbuff, 64, &pPlayer->_pSplLvl);
++ tbuff += 7;
++ CopyInt64(tbuff, &pPlayer->_pMemSpells);
++ CopyInt64(tbuff, &pPlayer->_pAblSpells);
++ CopyInt64(tbuff, &pPlayer->_pScrlSpells);
++ CopyChar(tbuff, &pPlayer->_pSpellFlags);
++ tbuff += 3;
++ CopyInts(tbuff, 4, &pPlayer->_pSplHotKey);
++ CopyBytes(tbuff, 4, &pPlayer->_pSplTHotKey);
++ CopyInt(tbuff, &pPlayer->_pwtype);
++ CopyChar(tbuff, &pPlayer->_pBlockFlag);
++ CopyChar(tbuff, &pPlayer->_pInvincible);
++ CopyChar(tbuff, &pPlayer->_pLightRad);
++ CopyChar(tbuff, &pPlayer->_pLvlChanging);
++ CopyBytes(tbuff, PLR_NAME_LEN, &pPlayer->_pName);
++ CopyChar(tbuff, &pPlayer->_pClass);
++ tbuff += 3;
++ CopyInt(tbuff, &pPlayer->_pStrength);
++ CopyInt(tbuff, &pPlayer->_pBaseStr);
++ CopyInt(tbuff, &pPlayer->_pMagic);
++ CopyInt(tbuff, &pPlayer->_pBaseMag);
++ CopyInt(tbuff, &pPlayer->_pDexterity);
++ CopyInt(tbuff, &pPlayer->_pBaseDex);
++ CopyInt(tbuff, &pPlayer->_pVitality);
++ CopyInt(tbuff, &pPlayer->_pBaseVit);
++ CopyInt(tbuff, &pPlayer->_pStatPts);
++ CopyInt(tbuff, &pPlayer->_pDamageMod);
++ CopyInt(tbuff, &pPlayer->_pBaseToBlk);
++ CopyInt(tbuff, &pPlayer->_pHPBase);
++ CopyInt(tbuff, &pPlayer->_pMaxHPBase);
++ CopyInt(tbuff, &pPlayer->_pHitPoints);
++ CopyInt(tbuff, &pPlayer->_pMaxHP);
++ CopyInt(tbuff, &pPlayer->_pHPPer);
++ CopyInt(tbuff, &pPlayer->_pManaBase);
++ CopyInt(tbuff, &pPlayer->_pMaxManaBase);
++ CopyInt(tbuff, &pPlayer->_pMana);
++ CopyInt(tbuff, &pPlayer->_pMaxMana);
++ CopyInt(tbuff, &pPlayer->_pManaPer);
++ CopyChar(tbuff, &pPlayer->_pLevel);
++ CopyChar(tbuff, &pPlayer->_pMaxLvl);
++ tbuff += 2;
++ CopyInt(tbuff, &pPlayer->_pExperience);
++ CopyInt(tbuff, &pPlayer->_pMaxExp);
++ CopyInt(tbuff, &pPlayer->_pNextExper);
++ CopyChar(tbuff, &pPlayer->_pArmorClass);
++ CopyChar(tbuff, &pPlayer->_pMagResist);
++ CopyChar(tbuff, &pPlayer->_pFireResist);
++ CopyChar(tbuff, &pPlayer->_pLghtResist);
++ CopyInt(tbuff, &pPlayer->_pGold);
++ CopyInt(tbuff, &pPlayer->_pInfraFlag);
++ CopyInt(tbuff, &pPlayer->_pVar1);
++ CopyInt(tbuff, &pPlayer->_pVar2);
++ CopyInt(tbuff, &pPlayer->_pVar3);
++ CopyInt(tbuff, &pPlayer->_pVar4);
++ CopyInt(tbuff, &pPlayer->_pVar5);
++ CopyInt(tbuff, &pPlayer->_pVar6);
++ CopyInt(tbuff, &pPlayer->_pVar7);
++ CopyInt(tbuff, &pPlayer->_pVar8);
++ CopyBytes(tbuff, NUMLEVELS, &pPlayer->_pLvlVisited);
++ CopyBytes(tbuff, NUMLEVELS, &pPlayer->_pSLvlVisited);
++ tbuff += 2;
++ CopyInt(tbuff, &pPlayer->_pGFXLoad);
++
++ tbuff += sizeof(__uint32_t) * 8;
++ CopyInt(tbuff, &pPlayer->_pNFrames);
++ CopyInt(tbuff, &pPlayer->_pNWidth);
++
++ tbuff += sizeof(__uint32_t) * 8;
++
++ CopyInt(tbuff, &pPlayer->_pWFrames);
++ CopyInt(tbuff, &pPlayer->_pWWidth);
++
++ tbuff += sizeof(__uint32_t) * 8;
++
++ CopyInt(tbuff, &pPlayer->_pAFrames);
++ CopyInt(tbuff, &pPlayer->_pAWidth);
++ CopyInt(tbuff, &pPlayer->_pAFNum);
++
++ tbuff += sizeof(__uint32_t) * 24;
++
++ CopyInt(tbuff, &pPlayer->_pSFrames);
++ CopyInt(tbuff, &pPlayer->_pSWidth);
++ CopyInt(tbuff, &pPlayer->_pSFNum);
++
++ tbuff += sizeof(__uint32_t) * 8;
++
++ CopyInt(tbuff, &pPlayer->_pHFrames);
++ CopyInt(tbuff, &pPlayer->_pHWidth);
++
++ tbuff += sizeof(__uint32_t) * 8;
++
++ CopyInt(tbuff, &pPlayer->_pDFrames);
++ CopyInt(tbuff, &pPlayer->_pDWidth);
++
++ tbuff += sizeof(__uint32_t) * 8;
++
++ CopyInt(tbuff, &pPlayer->_pBFrames);
++ CopyInt(tbuff, &pPlayer->_pBWidth);
++ CopyItems(NUM_INVLOC, pPlayer->InvBody);
++ CopyItems(NUM_INV_GRID_ELEM, pPlayer->InvList);
++ CopyInt(tbuff, &pPlayer->_pNumInv);
++ CopyBytes(tbuff, NUM_INV_GRID_ELEM, pPlayer->InvGrid);
++ CopyItems(MAXBELTITEMS, pPlayer->SpdList);
++ CopyItem(&pPlayer->HoldItem);
++ CopyInt(tbuff, &pPlayer->_pIMinDam);
++ CopyInt(tbuff, &pPlayer->_pIMaxDam);
++ CopyInt(tbuff, &pPlayer->_pIAC);
++ CopyInt(tbuff, &pPlayer->_pIBonusDam);
++ CopyInt(tbuff, &pPlayer->_pIBonusToHit);
++ CopyInt(tbuff, &pPlayer->_pIBonusAC);
++ CopyInt(tbuff, &pPlayer->_pIBonusDamMod);
++ tbuff += 4;
++ CopyInt64(tbuff, &pPlayer->_pISpells);
++ CopyInt(tbuff, &pPlayer->_pIFlags);
++ CopyInt(tbuff, &pPlayer->_pIGetHit);
++
++ CopyChar(tbuff, &pPlayer->_pISplLvlAdd);
++ CopyChar(tbuff, &pPlayer->_pISplCost);
++ tbuff += 2;
++
++ CopyInt(tbuff, &pPlayer->_pISplDur);
++ CopyInt(tbuff, &pPlayer->_pIEnAc);
++ CopyInt(tbuff, &pPlayer->_pIFMinDam);
++ CopyInt(tbuff, &pPlayer->_pIFMaxDam);
++ CopyInt(tbuff, &pPlayer->_pILMinDam);
++ CopyInt(tbuff, &pPlayer->_pILMaxDam);
++ CopyInt(tbuff, &pPlayer->_pOilType);
++
++ CopyChar(tbuff, &pPlayer->pTownWarps);
++ CopyChar(tbuff, &pPlayer->pDungMsgs);
++ CopyChar(tbuff, &pPlayer->pLvlLoad);
++ CopyChar(tbuff, &pPlayer->pBattleNet);
++
++ CopyChar(tbuff, &pPlayer->pManaShield);
++ CopyBytes(tbuff, 3, &pPlayer->bReserved);
++
++ CopyShorts(tbuff, 8, &pPlayer->wReserved);
++
++ CopyInt(tbuff, &pPlayer->pDiabloKillLevel);
++ CopyInts(tbuff, 7, &pPlayer->dwReserved);
++
++ // Omit 10 pointers
++
++}
++
++void SavePlayer(int i)
++{
++ PlayerStruct *pPlayer = &plr[i];
++
++ CopyInt(&pPlayer->_pmode, tbuff);
++
++ CopyBytes(&pPlayer->walkpath, 25, tbuff);
++ CopyBytes(&pPlayer->plractive, 1, tbuff);
++ tbuff += 2;
++
++ CopyInt(&pPlayer->destAction, tbuff);
++ CopyInt(&pPlayer->destParam1, tbuff);
++ CopyInt(&pPlayer->destParam2, tbuff);
++ CopyInt(&pPlayer->destParam3, tbuff);
++ CopyInt(&pPlayer->destParam4, tbuff);
++ CopyInt(&pPlayer->plrlevel, tbuff);
++ CopyInt(&pPlayer->WorldX, tbuff);
++ CopyInt(&pPlayer->WorldY, tbuff);
++ CopyInt(&pPlayer->_px, tbuff);
++ CopyInt(&pPlayer->_py, tbuff);
++ CopyInt(&pPlayer->_ptargx, tbuff);
++ CopyInt(&pPlayer->_ptargy, tbuff);
++ CopyInt(&pPlayer->_pownerx, tbuff);
++ CopyInt(&pPlayer->_pownery, tbuff);
++ CopyInt(&pPlayer->_poldx, tbuff);
++ CopyInt(&pPlayer->_poldy, tbuff);
++ CopyInt(&pPlayer->_pxoff, tbuff);
++ CopyInt(&pPlayer->_pyoff, tbuff);
++ CopyInt(&pPlayer->_pxvel, tbuff);
++ CopyInt(&pPlayer->_pyvel, tbuff);
++ CopyInt(&pPlayer->_pdir, tbuff);
++ CopyInt(&pPlayer->_nextdir, tbuff);
++ CopyInt(&pPlayer->_pgfxnum, tbuff);
++ tbuff += 4; // Skip pointers
++ CopyInt(&pPlayer->_pAnimDelay, tbuff);
++ CopyInt(&pPlayer->_pAnimCnt, tbuff);
++ CopyInt(&pPlayer->_pAnimLen, tbuff);
++ CopyInt(&pPlayer->_pAnimFrame, tbuff);
++ CopyInt(&pPlayer->_pAnimWidth, tbuff);
++ CopyInt(&pPlayer->_pAnimWidth2, tbuff);
++ CopyInt(&pPlayer->_peflag, tbuff);
++ CopyInt(&pPlayer->_plid, tbuff);
++ CopyInt(&pPlayer->_pvid, tbuff);
++
++ CopyInt(&pPlayer->_pSpell, tbuff);
++
++ CopyChar(&pPlayer->_pSplType, tbuff);
++ CopyChar(&pPlayer->_pSplFrom, tbuff);
++ tbuff += 2;
++
++ CopyInt(&pPlayer->_pTSpell, tbuff);
++ CopyChar(&pPlayer->_pTSplType, tbuff);
++ tbuff += 3;
++ CopyInt(&pPlayer->_pRSpell, tbuff);
++ CopyChar(&pPlayer->_pRSplType, tbuff);
++ tbuff += 3;
++ CopyInt(&pPlayer->_pSBkSpell, tbuff);
++ CopyChar(&pPlayer->_pSBkSplType, tbuff);
++
++ CopyBytes(&pPlayer->_pSplLvl, 64, tbuff);
++ tbuff += 7;
++ CopyInt64(&pPlayer->_pMemSpells, tbuff);
++ CopyInt64(&pPlayer->_pAblSpells, tbuff);
++ CopyInt64(&pPlayer->_pScrlSpells, tbuff);
++ CopyChar(&pPlayer->_pSpellFlags, tbuff);
++ tbuff += 3;
++ CopyInts(&pPlayer->_pSplHotKey, 4, tbuff);
++ CopyBytes(&pPlayer->_pSplTHotKey, 4, tbuff);
++ CopyInt(&pPlayer->_pwtype, tbuff);
++ CopyChar(&pPlayer->_pBlockFlag, tbuff);
++ CopyChar(&pPlayer->_pInvincible, tbuff);
++ CopyChar(&pPlayer->_pLightRad, tbuff);
++ CopyChar(&pPlayer->_pLvlChanging, tbuff);
++ CopyBytes(&pPlayer->_pName, PLR_NAME_LEN, tbuff);
++ CopyChar(&pPlayer->_pClass, tbuff);
++ tbuff += 3;
++ CopyInt(&pPlayer->_pStrength, tbuff);
++ CopyInt(&pPlayer->_pBaseStr, tbuff);
++ CopyInt(&pPlayer->_pMagic, tbuff);
++ CopyInt(&pPlayer->_pBaseMag, tbuff);
++ CopyInt(&pPlayer->_pDexterity, tbuff);
++ CopyInt(&pPlayer->_pBaseDex, tbuff);
++ CopyInt(&pPlayer->_pVitality, tbuff);
++ CopyInt(&pPlayer->_pBaseVit, tbuff);
++ CopyInt(&pPlayer->_pStatPts, tbuff);
++ CopyInt(&pPlayer->_pDamageMod, tbuff);
++ CopyInt(&pPlayer->_pBaseToBlk, tbuff);
++ CopyInt(&pPlayer->_pHPBase, tbuff);
++ CopyInt(&pPlayer->_pMaxHPBase, tbuff);
++ CopyInt(&pPlayer->_pHitPoints, tbuff);
++ CopyInt(&pPlayer->_pMaxHP, tbuff);
++ CopyInt(&pPlayer->_pHPPer, tbuff);
++ CopyInt(&pPlayer->_pManaBase, tbuff);
++ CopyInt(&pPlayer->_pMaxManaBase, tbuff);
++ CopyInt(&pPlayer->_pMana, tbuff);
++ CopyInt(&pPlayer->_pMaxMana, tbuff);
++ CopyInt(&pPlayer->_pManaPer, tbuff);
++ CopyChar(&pPlayer->_pLevel, tbuff);
++ CopyChar(&pPlayer->_pMaxLvl, tbuff);
++ tbuff += 2;
++ CopyInt(&pPlayer->_pExperience, tbuff);
++ CopyInt(&pPlayer->_pMaxExp, tbuff);
++ CopyInt(&pPlayer->_pNextExper, tbuff);
++ CopyChar(&pPlayer->_pArmorClass, tbuff);
++ CopyChar(&pPlayer->_pMagResist, tbuff);
++ CopyChar(&pPlayer->_pFireResist, tbuff);
++ CopyChar(&pPlayer->_pLghtResist, tbuff);
++ CopyInt(&pPlayer->_pGold, tbuff);
++ CopyInt(&pPlayer->_pInfraFlag, tbuff);
++ CopyInt(&pPlayer->_pVar1, tbuff);
++ CopyInt(&pPlayer->_pVar2, tbuff);
++ CopyInt(&pPlayer->_pVar3, tbuff);
++ CopyInt(&pPlayer->_pVar4, tbuff);
++ CopyInt(&pPlayer->_pVar5, tbuff);
++ CopyInt(&pPlayer->_pVar6, tbuff);
++ CopyInt(&pPlayer->_pVar7, tbuff);
++ CopyInt(&pPlayer->_pVar8, tbuff);
++ CopyBytes(&pPlayer->_pLvlVisited, NUMLEVELS, tbuff);
++ CopyBytes(&pPlayer->_pSLvlVisited, NUMLEVELS, tbuff); // only 10 used
++ tbuff += 2;
++ CopyInt(&pPlayer->_pGFXLoad, tbuff);
++
++ tbuff += sizeof(__uint32_t) * 8; // Skip 8 pointers
++ CopyInt(&pPlayer->_pNFrames, tbuff);
++ CopyInt(&pPlayer->_pNWidth, tbuff);
++
++ tbuff += sizeof(__uint32_t) * 8; // Skip 8 pointers
++
++ CopyInt(&pPlayer->_pWFrames, tbuff);
++ CopyInt(&pPlayer->_pWWidth, tbuff);
++
++ tbuff += sizeof(__uint32_t) * 8; // Skip 8 pointers
++
++ CopyInt(&pPlayer->_pAFrames, tbuff);
++ CopyInt(&pPlayer->_pAWidth, tbuff);
++ CopyInt(&pPlayer->_pAFNum, tbuff);
++
++ tbuff += sizeof(__uint32_t) * 24; // Skip 24 pointers
++
++ CopyInt(&pPlayer->_pSFrames, tbuff);
++ CopyInt(&pPlayer->_pSWidth, tbuff);
++ CopyInt(&pPlayer->_pSFNum, tbuff);
++
++ tbuff += sizeof(__uint32_t) * 8; // Skip 8 pointers
++
++ CopyInt(&pPlayer->_pHFrames, tbuff);
++ CopyInt(&pPlayer->_pHWidth, tbuff);
++
++ tbuff += sizeof(__uint32_t) * 8; // Skip 8 pointers
++
++ CopyInt(&pPlayer->_pDFrames, tbuff);
++ CopyInt(&pPlayer->_pDWidth, tbuff);
++
++ tbuff += sizeof(__uint32_t) * 8; // Skip 8 pointers
++
++ CopyInt(&pPlayer->_pBFrames, tbuff);
++ CopyInt(&pPlayer->_pBWidth, tbuff);
++ SaveItems(pPlayer->InvBody, NUM_INVLOC);
++ SaveItems(pPlayer->InvList, NUM_INV_GRID_ELEM);
++ CopyInt(&pPlayer->_pNumInv, tbuff);
++ CopyBytes(pPlayer->InvGrid, NUM_INV_GRID_ELEM, tbuff);
++ SaveItems(pPlayer->SpdList, MAXBELTITEMS);
++ SaveItem(&pPlayer->HoldItem);
++ CopyInt(&pPlayer->_pIMinDam, tbuff);
++ CopyInt(&pPlayer->_pIMaxDam, tbuff);
++ CopyInt(&pPlayer->_pIAC, tbuff);
++ CopyInt(&pPlayer->_pIBonusDam, tbuff);
++ CopyInt(&pPlayer->_pIBonusToHit, tbuff);
++ CopyInt(&pPlayer->_pIBonusAC, tbuff);
++ CopyInt(&pPlayer->_pIBonusDamMod, tbuff);
++ tbuff += 4;
++ CopyInt64(&pPlayer->_pISpells, tbuff);
++ CopyInt(&pPlayer->_pIFlags, tbuff);
++ CopyInt(&pPlayer->_pIGetHit, tbuff);
++
++ CopyChar(&pPlayer->_pISplLvlAdd, tbuff);
++ CopyChar(&pPlayer->_pISplCost, tbuff);
++ tbuff += 2;
++
++ CopyInt(&pPlayer->_pISplDur, tbuff);
++ CopyInt(&pPlayer->_pIEnAc, tbuff);
++ CopyInt(&pPlayer->_pIFMinDam, tbuff);
++ CopyInt(&pPlayer->_pIFMaxDam, tbuff);
++ CopyInt(&pPlayer->_pILMinDam, tbuff);
++ CopyInt(&pPlayer->_pILMaxDam, tbuff);
++ CopyInt(&pPlayer->_pOilType, tbuff);
++
++ CopyChar(&pPlayer->pTownWarps, tbuff);
++ CopyChar(&pPlayer->pDungMsgs, tbuff);
++ CopyChar(&pPlayer->pLvlLoad, tbuff);
++ CopyChar(&pPlayer->pBattleNet, tbuff);
++
++ CopyChar(&pPlayer->pManaShield, tbuff);
++ CopyBytes(&pPlayer->bReserved, 3, tbuff);
++
++ CopyShorts(&pPlayer->wReserved, 8, tbuff);
++
++ CopyInt(&pPlayer->pDiabloKillLevel, tbuff);
++ CopyInts(&pPlayer->dwReserved, 7, tbuff);
++
++ // Omit 10 pointers
++
+ }
+
+ void LoadMonster(int i)
+ {
+- memcpy(&monster[i], tbuff, sizeof(*monster) - (3 * sizeof(void *)));
+- tbuff += sizeof(*monster) - (3 * sizeof(void *)); // omit last 3 pointers
++ MonsterStruct *pMonster = &monster[i];
++
++ CopyInt(tbuff, &pMonster->_mMTidx);
++ CopyInt(tbuff, &pMonster->_mmode);
++
++ CopyChar(tbuff, &pMonster->_mgoal);
++ tbuff += 3;
++
++ CopyInt(tbuff, &pMonster->_mgoalvar1);
++ CopyInt(tbuff, &pMonster->_mgoalvar2);
++ CopyInt(tbuff, &pMonster->_mgoalvar3);
++ CopyInt(tbuff, &pMonster->field_18);
++
++ CopyChar(tbuff, &pMonster->_pathcount);
++ tbuff += 3;
++
++ CopyInt(tbuff, &pMonster->_mx);
++ CopyInt(tbuff, &pMonster->_my);
++ CopyInt(tbuff, &pMonster->_mfutx);
++ CopyInt(tbuff, &pMonster->_mfuty);
++ CopyInt(tbuff, &pMonster->_moldx);
++ CopyInt(tbuff, &pMonster->_moldy);
++ CopyInt(tbuff, &pMonster->_mxoff);
++ CopyInt(tbuff, &pMonster->_myoff);
++ CopyInt(tbuff, &pMonster->_mxvel);
++ CopyInt(tbuff, &pMonster->_myvel);
++ CopyInt(tbuff, &pMonster->_mdir);
++ CopyInt(tbuff, &pMonster->_menemy);
++
++ CopyChar(tbuff, &pMonster->_menemyx);
++ CopyChar(tbuff, &pMonster->_menemyy);
++ CopyShort(tbuff, &pMonster->falign_52);
++
++ tbuff += 4; // Skip pointer
++ CopyInt(tbuff, &pMonster->_mAnimDelay);
++ CopyInt(tbuff, &pMonster->_mAnimCnt);
++ CopyInt(tbuff, &pMonster->_mAnimLen);
++ CopyInt(tbuff, &pMonster->_mAnimFrame);
++ CopyInt(tbuff, &pMonster->_meflag);
++ CopyInt(tbuff, &pMonster->_mDelFlag);
++ CopyInt(tbuff, &pMonster->_mVar1);
++ CopyInt(tbuff, &pMonster->_mVar2);
++ CopyInt(tbuff, &pMonster->_mVar3);
++ CopyInt(tbuff, &pMonster->_mVar4);
++ CopyInt(tbuff, &pMonster->_mVar5);
++ CopyInt(tbuff, &pMonster->_mVar6);
++ CopyInt(tbuff, &pMonster->_mVar7);
++ CopyInt(tbuff, &pMonster->_mVar8);
++ CopyInt(tbuff, &pMonster->_mmaxhp);
++ CopyInt(tbuff, &pMonster->_mhitpoints);
++
++ CopyChar(tbuff, &pMonster->_mAi);
++ CopyChar(tbuff, &pMonster->_mint);
++ CopyShort(tbuff, &pMonster->falign_9A);
++
++ CopyInt(tbuff, &pMonster->_mFlags);
++
++ CopyChar(tbuff, &pMonster->_msquelch);
++ tbuff += 3;
++
++ CopyInt(tbuff, &pMonster->falign_A4);
++ CopyInt(tbuff, &pMonster->_lastx);
++ CopyInt(tbuff, &pMonster->_lasty);
++ CopyInt(tbuff, &pMonster->_mRndSeed);
++ CopyInt(tbuff, &pMonster->_mAISeed);
++ CopyInt(tbuff, &pMonster->falign_B8);
++
++ CopyChar(tbuff, &pMonster->_uniqtype);
++ CopyChar(tbuff, &pMonster->_uniqtrans);
++ CopyChar(tbuff, &pMonster->_udeadval);
++ CopyChar(tbuff, &pMonster->mWhoHit);
++
++ CopyChar(tbuff, &pMonster->mLevel);
++ tbuff += 1;
++ CopyShort(tbuff, &pMonster->mExp);
++
++ CopyChar(tbuff, &pMonster->mHit);
++ CopyChar(tbuff, &pMonster->mMinDamage);
++ CopyChar(tbuff, &pMonster->mMaxDamage);
++ CopyChar(tbuff, &pMonster->mHit2);
++
++ CopyChar(tbuff, &pMonster->mMinDamage2);
++ CopyChar(tbuff, &pMonster->mMaxDamage2);
++ CopyChar(tbuff, &pMonster->mArmorClass);
++ CopyChar(tbuff, &pMonster->falign_CB);
++
++ CopyShort(tbuff, &pMonster->mMagicRes);
++ tbuff += 2;
++
++ CopyInt(tbuff, &pMonster->mtalkmsg);
++
++ CopyChar(tbuff, &pMonster->leader);
++ CopyChar(tbuff, &pMonster->leaderflag);
++ CopyChar(tbuff, &pMonster->packsize);
++ CopyChar(tbuff, &pMonster->mlid);
++
+ SyncMonsterAnim(i);
+ }
+
+ void LoadMissile(int i)
+ {
+- memcpy(&missile[i], tbuff, sizeof(*missile));
+- tbuff += sizeof(*missile);
++ MissileStruct *pMissile = &missile[i];
++
++ CopyInt(tbuff, &pMissile->_mitype);
++ CopyInt(tbuff, &pMissile->_mix);
++ CopyInt(tbuff, &pMissile->_miy);
++ CopyInt(tbuff, &pMissile->_mixoff);
++ CopyInt(tbuff, &pMissile->_miyoff);
++ CopyInt(tbuff, &pMissile->_mixvel);
++ CopyInt(tbuff, &pMissile->_miyvel);
++ CopyInt(tbuff, &pMissile->_misx);
++ CopyInt(tbuff, &pMissile->_misy);
++ CopyInt(tbuff, &pMissile->_mitxoff);
++ CopyInt(tbuff, &pMissile->_mityoff);
++ CopyInt(tbuff, &pMissile->_mimfnum);
++ CopyInt(tbuff, &pMissile->_mispllvl);
++ CopyInt(tbuff, &pMissile->_miDelFlag);
++ CopyChar(tbuff, &pMissile->_miAnimType);
++ tbuff += 3;
++
++ CopyInt(tbuff, &pMissile->_miAnimFlags);
++ tbuff += 4;
++ CopyInt(tbuff, &pMissile->_miAnimDelay);
++ CopyInt(tbuff, &pMissile->_miAnimLen);
++ CopyInt(tbuff, &pMissile->_miAnimWidth);
++ CopyInt(tbuff, &pMissile->_miAnimWidth2);
++ CopyInt(tbuff, &pMissile->_miAnimCnt);
++ CopyInt(tbuff, &pMissile->_miAnimAdd);
++ CopyInt(tbuff, &pMissile->_miAnimFrame);
++ CopyInt(tbuff, &pMissile->_miDrawFlag);
++ CopyInt(tbuff, &pMissile->_miLightFlag);
++ CopyInt(tbuff, &pMissile->_miPreFlag);
++ CopyInt(tbuff, &pMissile->_miUniqTrans);
++ CopyInt(tbuff, &pMissile->_mirange);
++ CopyInt(tbuff, &pMissile->_misource);
++ CopyInt(tbuff, &pMissile->_micaster);
++ CopyInt(tbuff, &pMissile->_midam);
++ CopyInt(tbuff, &pMissile->_miHitFlag);
++ CopyInt(tbuff, &pMissile->_midist);
++ CopyInt(tbuff, &pMissile->_mlid);
++ CopyInt(tbuff, &pMissile->_mirnd);
++ CopyInt(tbuff, &pMissile->_miVar1);
++ CopyInt(tbuff, &pMissile->_miVar2);
++ CopyInt(tbuff, &pMissile->_miVar3);
++ CopyInt(tbuff, &pMissile->_miVar4);
++ CopyInt(tbuff, &pMissile->_miVar5);
++ CopyInt(tbuff, &pMissile->_miVar6);
++ CopyInt(tbuff, &pMissile->_miVar7);
++ CopyInt(tbuff, &pMissile->_miVar8);
+ }
+
+ void LoadObject(int i)
+ {
+- memcpy(&object[i], tbuff, sizeof(*object));
+- tbuff += sizeof(*object);
++ ObjectStruct *pObject = &object[i];
++ CopyInt(tbuff, &pObject->_otype);
++ CopyInt(tbuff, &pObject->_ox);
++ CopyInt(tbuff, &pObject->_oy);
++ CopyInt(tbuff, &pObject->_oLight);
++ CopyInt(tbuff, &pObject->_oAnimFlag);
++ tbuff += 4;
++ CopyInt(tbuff, &pObject->_oAnimDelay);
++ CopyInt(tbuff, &pObject->_oAnimCnt);
++ CopyInt(tbuff, &pObject->_oAnimLen);
++ CopyInt(tbuff, &pObject->_oAnimFrame);
++ CopyInt(tbuff, &pObject->_oAnimWidth);
++ CopyInt(tbuff, &pObject->_oAnimWidth2);
++ CopyInt(tbuff, &pObject->_oDelFlag);
++
++ CopyChar(tbuff, &pObject->_oBreak);
++ tbuff += 3;
++
++ CopyInt(tbuff, &pObject->_oSolidFlag);
++ CopyInt(tbuff, &pObject->_oMissFlag);
++
++ CopyChar(tbuff, &pObject->_oSelFlag);
++ tbuff += 3;
++
++ CopyInt(tbuff, &pObject->_oPreFlag);
++ CopyInt(tbuff, &pObject->_oTrapFlag);
++ CopyInt(tbuff, &pObject->_oDoorFlag);
++ CopyInt(tbuff, &pObject->_olid);
++ CopyInt(tbuff, &pObject->_oRndSeed);
++ CopyInt(tbuff, &pObject->_oVar1);
++ CopyInt(tbuff, &pObject->_oVar2);
++ CopyInt(tbuff, &pObject->_oVar3);
++ CopyInt(tbuff, &pObject->_oVar4);
++ CopyInt(tbuff, &pObject->_oVar5);
++ CopyInt(tbuff, &pObject->_oVar6);
++ CopyInt(tbuff, &pObject->_oVar7);
++ CopyInt(tbuff, &pObject->_oVar8);
+ }
+
+ void LoadItem(int i)
+ {
+- memcpy(&item[i], tbuff, sizeof(*item));
+- tbuff += sizeof(*item);
++ CopyItem(&item[i]);
+ GetItemFrm(i);
+ }
+
++void CopyItem(ItemStruct *pItem)
++{
++ CopyInt(tbuff, &pItem->_iSeed);
++ CopyShort(tbuff, &pItem->_iCreateInfo);
++ tbuff += 2;
++ CopyInt(tbuff, &pItem->_itype);
++ CopyInt(tbuff, &pItem->_ix);
++ CopyInt(tbuff, &pItem->_iy);
++ CopyInt(tbuff, &pItem->_iAnimFlag);
++ tbuff += 4; // Skip pointer _iAnimData
++ CopyInt(tbuff, &pItem->_iAnimLen);
++ CopyInt(tbuff, &pItem->_iAnimFrame);
++ CopyInt(tbuff, &pItem->_iAnimWidth);
++ CopyInt(tbuff, &pItem->_iAnimWidth2);
++ CopyInt(tbuff, &pItem->_isin);
++ CopyChar(tbuff, &pItem->_iSelFlag);
++ tbuff += 3;
++ CopyInt(tbuff, &pItem->_iPostDraw);
++ CopyInt(tbuff, &pItem->_iIdentified);
++ CopyChar(tbuff, &pItem->_iMagical);
++ CopyBytes(tbuff, 64, &pItem->_iName);
++ CopyBytes(tbuff, 64, &pItem->_iIName);
++ CopyChar(tbuff, &pItem->_iLoc);
++ CopyChar(tbuff, &pItem->_iClass);
++ tbuff += 1;
++ CopyInt(tbuff, &pItem->_iCurs);
++ CopyInt(tbuff, &pItem->_ivalue);
++ CopyInt(tbuff, &pItem->_iIvalue);
++ CopyInt(tbuff, &pItem->_iMinDam);
++ CopyInt(tbuff, &pItem->_iMaxDam);
++ CopyInt(tbuff, &pItem->_iAC);
++ CopyInt(tbuff, &pItem->_iFlags);
++ CopyInt(tbuff, &pItem->_iMiscId);
++ CopyInt(tbuff, &pItem->_iSpell);
++ CopyInt(tbuff, &pItem->_iCharges);
++ CopyInt(tbuff, &pItem->_iMaxCharges);
++ CopyInt(tbuff, &pItem->_iDurability);
++ CopyInt(tbuff, &pItem->_iMaxDur);
++ CopyInt(tbuff, &pItem->_iPLDam);
++ CopyInt(tbuff, &pItem->_iPLToHit);
++ CopyInt(tbuff, &pItem->_iPLAC);
++ CopyInt(tbuff, &pItem->_iPLStr);
++ CopyInt(tbuff, &pItem->_iPLMag);
++ CopyInt(tbuff, &pItem->_iPLDex);
++ CopyInt(tbuff, &pItem->_iPLVit);
++ CopyInt(tbuff, &pItem->_iPLFR);
++ CopyInt(tbuff, &pItem->_iPLLR);
++ CopyInt(tbuff, &pItem->_iPLMR);
++ CopyInt(tbuff, &pItem->_iPLMana);
++ CopyInt(tbuff, &pItem->_iPLHP);
++ CopyInt(tbuff, &pItem->_iPLDamMod);
++ CopyInt(tbuff, &pItem->_iPLGetHit);
++ CopyInt(tbuff, &pItem->_iPLLight);
++ CopyChar(tbuff, &pItem->_iSplLvlAdd);
++ CopyChar(tbuff, &pItem->_iRequest);
++ tbuff += 2;
++ CopyInt(tbuff, &pItem->_iUid);
++ CopyInt(tbuff, &pItem->_iFMinDam);
++ CopyInt(tbuff, &pItem->_iFMaxDam);
++ CopyInt(tbuff, &pItem->_iLMinDam);
++ CopyInt(tbuff, &pItem->_iLMaxDam);
++ CopyInt(tbuff, &pItem->_iPLEnAc);
++ CopyChar(tbuff, &pItem->_iPrePower);
++ CopyChar(tbuff, &pItem->_iSufPower);
++ tbuff += 2;
++ CopyInt(tbuff, &pItem->_iVAdd1);
++ CopyInt(tbuff, &pItem->_iVMult1);
++ CopyInt(tbuff, &pItem->_iVAdd2);
++ CopyInt(tbuff, &pItem->_iVMult2);
++ CopyChar(tbuff, &pItem->_iMinStr);
++ CopyChar(tbuff, &pItem->_iMinMag);
++ CopyChar(tbuff, &pItem->_iMinDex);
++ tbuff += 1;
++ CopyInt(tbuff, &pItem->_iStatFlag);
++ CopyInt(tbuff, &pItem->IDidx);
++ CopyInt(tbuff, &pItem->offs016C);
++}
++
++void CopyItems(const int n, ItemStruct *pItem)
++{
++ for (int i = 0; i < n; i++)
++ {
++ CopyItem(&pItem[i]);
++ }
++}
++
++void SaveItem(ItemStruct *pItem)
++{
++ CopyInt(&pItem->_iSeed, tbuff);
++ CopyShort(&pItem->_iCreateInfo, tbuff);
++ tbuff += 2;
++ CopyInt(&pItem->_itype, tbuff);
++ CopyInt(&pItem->_ix, tbuff);
++ CopyInt(&pItem->_iy, tbuff);
++ CopyInt(&pItem->_iAnimFlag, tbuff);
++ tbuff += 4; // Skip pointer _iAnimData
++ CopyInt(&pItem->_iAnimLen, tbuff);
++ CopyInt(&pItem->_iAnimFrame, tbuff);
++ CopyInt(&pItem->_iAnimWidth, tbuff);
++ CopyInt(&pItem->_iAnimWidth2, tbuff); // width 2?
++ CopyInt(&pItem->_isin, tbuff); // set when item is flagged for deletion, deprecated in 1.02
++ CopyChar(&pItem->_iSelFlag, tbuff);
++ tbuff += 3;
++ CopyInt(&pItem->_iPostDraw, tbuff);
++ CopyInt(&pItem->_iIdentified, tbuff);
++ CopyChar(&pItem->_iMagical, tbuff);
++ CopyBytes(&pItem->_iName, 64, tbuff);
++ CopyBytes(&pItem->_iIName, 64, tbuff);
++ CopyChar(&pItem->_iLoc, tbuff);
++ CopyChar(&pItem->_iClass, tbuff);
++ tbuff += 1;
++ CopyInt(&pItem->_iCurs, tbuff);
++ CopyInt(&pItem->_ivalue, tbuff);
++ CopyInt(&pItem->_iIvalue, tbuff);
++ CopyInt(&pItem->_iMinDam, tbuff);
++ CopyInt(&pItem->_iMaxDam, tbuff);
++ CopyInt(&pItem->_iAC, tbuff);
++ CopyInt(&pItem->_iFlags, tbuff);
++ CopyInt(&pItem->_iMiscId, tbuff);
++ CopyInt(&pItem->_iSpell, tbuff);
++ CopyInt(&pItem->_iCharges, tbuff);
++ CopyInt(&pItem->_iMaxCharges, tbuff);
++ CopyInt(&pItem->_iDurability, tbuff);
++ CopyInt(&pItem->_iMaxDur, tbuff);
++ CopyInt(&pItem->_iPLDam, tbuff);
++ CopyInt(&pItem->_iPLToHit, tbuff);
++ CopyInt(&pItem->_iPLAC, tbuff);
++ CopyInt(&pItem->_iPLStr, tbuff);
++ CopyInt(&pItem->_iPLMag, tbuff);
++ CopyInt(&pItem->_iPLDex, tbuff);
++ CopyInt(&pItem->_iPLVit, tbuff);
++ CopyInt(&pItem->_iPLFR, tbuff);
++ CopyInt(&pItem->_iPLLR, tbuff);
++ CopyInt(&pItem->_iPLMR, tbuff);
++ CopyInt(&pItem->_iPLMana, tbuff);
++ CopyInt(&pItem->_iPLHP, tbuff);
++ CopyInt(&pItem->_iPLDamMod, tbuff);
++ CopyInt(&pItem->_iPLGetHit, tbuff);
++ CopyInt(&pItem->_iPLLight, tbuff);
++ CopyChar(&pItem->_iSplLvlAdd, tbuff);
++ CopyChar(&pItem->_iRequest, tbuff);
++ tbuff += 2;
++ CopyInt(&pItem->_iUid, tbuff);
++ CopyInt(&pItem->_iFMinDam, tbuff);
++ CopyInt(&pItem->_iFMaxDam, tbuff);
++ CopyInt(&pItem->_iLMinDam, tbuff);
++ CopyInt(&pItem->_iLMaxDam, tbuff);
++ CopyInt(&pItem->_iPLEnAc, tbuff);
++ CopyChar(&pItem->_iPrePower, tbuff);
++ CopyChar(&pItem->_iSufPower, tbuff);
++ tbuff += 2;
++ CopyInt(&pItem->_iVAdd1, tbuff);
++ CopyInt(&pItem->_iVMult1, tbuff);
++ CopyInt(&pItem->_iVAdd2, tbuff);
++ CopyInt(&pItem->_iVMult2, tbuff);
++ CopyChar(&pItem->_iMinStr, tbuff);
++ CopyChar(&pItem->_iMinMag, tbuff);
++ CopyChar(&pItem->_iMinDex, tbuff);
++ tbuff += 1;
++ CopyInt(&pItem->_iStatFlag, tbuff);
++ CopyInt(&pItem->IDidx, tbuff);
++ CopyInt(&pItem->offs016C, tbuff);
++}
++
++void SaveItems(ItemStruct *pItem, const int n)
++{
++ for (int i = 0; i < n; i++)
++ {
++ SaveItem(&pItem[i]);
++ }
++}
++
+ void LoadPremium(int i)
+ {
+- memcpy(&premiumitem[i], tbuff, sizeof(*premiumitem));
+- tbuff += sizeof(*premiumitem);
++ CopyItem(&item[i]);
+ }
+
+ void LoadQuest(int i)
+@@ -348,7 +1135,7 @@ void SaveGame()
+ for (i = 0; i < MAXITEMS; i++)
+ BSave(itemavail[i]);
+ for (i = 0; i < numitems; i++)
+- SaveItem(itemactive[i]);
++ SaveItem(&item[itemactive[i]]);
+ for (i = 0; i < 128; i++)
+ OSave(UniqueItemFlag[i]);
+
+@@ -446,40 +1233,201 @@ void OSave(BOOL v)
+ *tbuff++ = FALSE;
+ }
+
+-void SavePlayer(int i)
+-{
+- memcpy(tbuff, &plr[i], sizeof(*plr) - (10 * sizeof(void *)));
+- tbuff += sizeof(*plr) - (10 * sizeof(void *)); // omit last 10 pointers
+-}
+-
+ void SaveMonster(int i)
+ {
+- memcpy(tbuff, &monster[i], sizeof(*monster) - (3 * sizeof(void *)));
+- tbuff += sizeof(*monster) - (3 * sizeof(void *)); // omit last 3 pointers
++ MonsterStruct *pMonster = &monster[i];
++
++ CopyInt(&pMonster->_mMTidx, tbuff);
++ CopyInt(&pMonster->_mmode, tbuff);
++
++ CopyChar(&pMonster->_mgoal, tbuff);
++ tbuff += 3;
++
++ CopyInt(&pMonster->_mgoalvar1, tbuff);
++ CopyInt(&pMonster->_mgoalvar2, tbuff);
++ CopyInt(&pMonster->_mgoalvar3, tbuff);
++ CopyInt(&pMonster->field_18, tbuff);
++
++ CopyChar(&pMonster->_pathcount, tbuff);
++ tbuff += 3;
++
++ CopyInt(&pMonster->_mx, tbuff);
++ CopyInt(&pMonster->_my, tbuff);
++ CopyInt(&pMonster->_mfutx, tbuff);
++ CopyInt(&pMonster->_mfuty, tbuff);
++ CopyInt(&pMonster->_moldx, tbuff);
++ CopyInt(&pMonster->_moldy, tbuff);
++ CopyInt(&pMonster->_mxoff, tbuff);
++ CopyInt(&pMonster->_myoff, tbuff);
++ CopyInt(&pMonster->_mxvel, tbuff);
++ CopyInt(&pMonster->_myvel, tbuff);
++ CopyInt(&pMonster->_mdir, tbuff);
++ CopyInt(&pMonster->_menemy, tbuff);
++
++ CopyChar(&pMonster->_menemyx, tbuff);
++ CopyChar(&pMonster->_menemyy, tbuff);
++ CopyShort(&pMonster->falign_52, tbuff);
++
++ tbuff += 4; // Skip pointer
++ CopyInt(&pMonster->_mAnimDelay, tbuff);
++ CopyInt(&pMonster->_mAnimCnt, tbuff);
++ CopyInt(&pMonster->_mAnimLen, tbuff);
++ CopyInt(&pMonster->_mAnimFrame, tbuff);
++ CopyInt(&pMonster->_meflag, tbuff);
++ CopyInt(&pMonster->_mDelFlag, tbuff);
++ CopyInt(&pMonster->_mVar1, tbuff);
++ CopyInt(&pMonster->_mVar2, tbuff);
++ CopyInt(&pMonster->_mVar3, tbuff);
++ CopyInt(&pMonster->_mVar4, tbuff);
++ CopyInt(&pMonster->_mVar5, tbuff);
++ CopyInt(&pMonster->_mVar6, tbuff);
++ CopyInt(&pMonster->_mVar7, tbuff);
++ CopyInt(&pMonster->_mVar8, tbuff);
++ CopyInt(&pMonster->_mmaxhp, tbuff);
++ CopyInt(&pMonster->_mhitpoints, tbuff);
++
++ CopyChar(&pMonster->_mAi, tbuff);
++ CopyChar(&pMonster->_mint, tbuff);
++ CopyShort(&pMonster->falign_9A, tbuff);
++
++ CopyInt(&pMonster->_mFlags, tbuff);
++
++ CopyChar(&pMonster->_msquelch, tbuff);
++ tbuff += 3;
++
++ CopyInt(&pMonster->falign_A4, tbuff);
++ CopyInt(&pMonster->_lastx, tbuff);
++ CopyInt(&pMonster->_lasty, tbuff);
++ CopyInt(&pMonster->_mRndSeed, tbuff);
++ CopyInt(&pMonster->_mAISeed, tbuff);
++ CopyInt(&pMonster->falign_B8, tbuff);
++
++ CopyChar(&pMonster->_uniqtype, tbuff);
++ CopyChar(&pMonster->_uniqtrans, tbuff);
++ CopyChar(&pMonster->_udeadval, tbuff);
++ CopyChar(&pMonster->mWhoHit, tbuff);
++
++ CopyChar(&pMonster->mLevel, tbuff);
++ tbuff += 1;
++ CopyShort(&pMonster->mExp, tbuff);
++
++ CopyChar(&pMonster->mHit, tbuff);
++ CopyChar(&pMonster->mMinDamage, tbuff);
++ CopyChar(&pMonster->mMaxDamage, tbuff);
++ CopyChar(&pMonster->mHit2, tbuff);
++
++ CopyChar(&pMonster->mMinDamage2, tbuff);
++ CopyChar(&pMonster->mMaxDamage2, tbuff);
++ CopyChar(&pMonster->mArmorClass, tbuff);
++ CopyChar(&pMonster->falign_CB, tbuff);
++
++ CopyShort(&pMonster->mMagicRes, tbuff);
++ tbuff += 2;
++
++ CopyInt(&pMonster->mtalkmsg, tbuff);
++
++ CopyChar(&pMonster->leader, tbuff);
++ CopyChar(&pMonster->leaderflag, tbuff);
++ CopyChar(&pMonster->packsize, tbuff);
++ CopyChar(&pMonster->mlid, tbuff);
+ }
+
+ void SaveMissile(int i)
+ {
+- memcpy(tbuff, &missile[i], sizeof(*missile));
+- tbuff += sizeof(*missile);
+-}
++ MissileStruct *pMissile = &missile[i];
+
+-void SaveObject(int i)
+-{
+- memcpy(tbuff, &object[i], sizeof(*object));
+- tbuff += sizeof(*object);
++ CopyInt(&pMissile->_mitype, tbuff);
++ CopyInt(&pMissile->_mix, tbuff);
++ CopyInt(&pMissile->_miy, tbuff);
++ CopyInt(&pMissile->_mixoff, tbuff);
++ CopyInt(&pMissile->_miyoff, tbuff);
++ CopyInt(&pMissile->_mixvel, tbuff);
++ CopyInt(&pMissile->_miyvel, tbuff);
++ CopyInt(&pMissile->_misx, tbuff);
++ CopyInt(&pMissile->_misy, tbuff);
++ CopyInt(&pMissile->_mitxoff, tbuff);
++ CopyInt(&pMissile->_mityoff, tbuff);
++ CopyInt(&pMissile->_mimfnum, tbuff);
++ CopyInt(&pMissile->_mispllvl, tbuff);
++ CopyInt(&pMissile->_miDelFlag, tbuff);
++ CopyChar(&pMissile->_miAnimType, tbuff);
++ tbuff += 3;
++
++ CopyInt(&pMissile->_miAnimFlags, tbuff);
++ tbuff += 4;
++ CopyInt(&pMissile->_miAnimDelay, tbuff);
++ CopyInt(&pMissile->_miAnimLen, tbuff);
++ CopyInt(&pMissile->_miAnimWidth, tbuff);
++ CopyInt(&pMissile->_miAnimWidth2, tbuff);
++ CopyInt(&pMissile->_miAnimCnt, tbuff);
++ CopyInt(&pMissile->_miAnimAdd, tbuff);
++ CopyInt(&pMissile->_miAnimFrame, tbuff);
++ CopyInt(&pMissile->_miDrawFlag, tbuff);
++ CopyInt(&pMissile->_miLightFlag, tbuff);
++ CopyInt(&pMissile->_miPreFlag, tbuff);
++ CopyInt(&pMissile->_miUniqTrans, tbuff);
++ CopyInt(&pMissile->_mirange, tbuff);
++ CopyInt(&pMissile->_misource, tbuff);
++ CopyInt(&pMissile->_micaster, tbuff);
++ CopyInt(&pMissile->_midam, tbuff);
++ CopyInt(&pMissile->_miHitFlag, tbuff);
++ CopyInt(&pMissile->_midist, tbuff);
++ CopyInt(&pMissile->_mlid, tbuff);
++ CopyInt(&pMissile->_mirnd, tbuff);
++ CopyInt(&pMissile->_miVar1, tbuff);
++ CopyInt(&pMissile->_miVar2, tbuff);
++ CopyInt(&pMissile->_miVar3, tbuff);
++ CopyInt(&pMissile->_miVar4, tbuff);
++ CopyInt(&pMissile->_miVar5, tbuff);
++ CopyInt(&pMissile->_miVar6, tbuff);
++ CopyInt(&pMissile->_miVar7, tbuff);
++ CopyInt(&pMissile->_miVar8, tbuff);
+ }
+
+-void SaveItem(int i)
++void SaveObject(int i)
+ {
+- memcpy(tbuff, &item[i], sizeof(*item));
+- tbuff += sizeof(*item);
++ ObjectStruct *pObject = &object[i];
++ CopyInt(tbuff, &pObject->_otype);
++ CopyInt(&pObject->_ox, tbuff);
++ CopyInt(&pObject->_oy, tbuff);
++ CopyInt(&pObject->_oLight, tbuff);
++ CopyInt(&pObject->_oAnimFlag, tbuff);
++ tbuff += 4;
++ CopyInt(&pObject->_oAnimDelay, tbuff);
++ CopyInt(&pObject->_oAnimCnt, tbuff);
++ CopyInt(&pObject->_oAnimLen, tbuff);
++ CopyInt(&pObject->_oAnimFrame, tbuff);
++ CopyInt(&pObject->_oAnimWidth, tbuff);
++ CopyInt(&pObject->_oAnimWidth2, tbuff);
++ CopyInt(&pObject->_oDelFlag, tbuff);
++
++ CopyChar(&pObject->_oBreak, tbuff);
++ tbuff += 3;
++
++ CopyInt(&pObject->_oSolidFlag, tbuff);
++ CopyInt(&pObject->_oMissFlag, tbuff);
++
++ CopyChar(&pObject->_oSelFlag, tbuff);
++ tbuff += 3;
++
++ CopyInt(&pObject->_oPreFlag, tbuff);
++ CopyInt(&pObject->_oTrapFlag, tbuff);
++ CopyInt(&pObject->_oDoorFlag, tbuff);
++ CopyInt(&pObject->_olid, tbuff);
++ CopyInt(&pObject->_oRndSeed, tbuff);
++ CopyInt(&pObject->_oVar1, tbuff);
++ CopyInt(&pObject->_oVar2, tbuff);
++ CopyInt(&pObject->_oVar3, tbuff);
++ CopyInt(&pObject->_oVar4, tbuff);
++ CopyInt(&pObject->_oVar5, tbuff);
++ CopyInt(&pObject->_oVar6, tbuff);
++ CopyInt(&pObject->_oVar7, tbuff);
++ CopyInt(&pObject->_oVar8, tbuff);
+ }
+
+ void SavePremium(int i)
+ {
+- memcpy(tbuff, &premiumitem[i], sizeof(*premiumitem));
+- tbuff += sizeof(*premiumitem);
++ SaveItem(&item[i]);
+ }
+
+ void SaveQuest(int i)
+@@ -554,7 +1502,7 @@ void SaveLevel()
+ for (i = 0; i < MAXITEMS; i++)
+ BSave(itemavail[i]);
+ for (i = 0; i < numitems; i++)
+- SaveItem(itemactive[i]);
++ SaveItem(&item[itemactive[i]]);
+
+ for (j = 0; j < MAXDUNY; j++) {
+ for (i = 0; i < MAXDUNX; i++)
diff --git a/games/devilutionx/patches/patch-Source_loadsave.h b/games/devilutionx/patches/patch-Source_loadsave.h
new file mode 100644
index 00000000000..d7584ecf025
--- /dev/null
+++ b/games/devilutionx/patches/patch-Source_loadsave.h
@@ -0,0 +1,19 @@
+$NetBSD: patch-Source_loadsave.h,v 1.1 2019/07/28 10:26:43 nia Exp $
+
+64bit Compatible Saves
+https://patch-diff.githubusercontent.com/raw/diasurgical/devilutionX/pull/162.patch
+
+--- Source/loadsave.h.orig 2019-05-19 17:06:45.000000000 +0000
++++ Source/loadsave.h
+@@ -9,6 +9,11 @@ char BLoad();
+ int WLoad();
+ int ILoad();
+ BOOL OLoad();
++void CopyItems(const int n, ItemStruct *pItem);
++void CopyItem(ItemStruct *pItem);
++void SaveItem(ItemStruct *pItem);
++void SaveItems(ItemStruct *pItem, const int n);
++
+ void LoadPlayer(int i);
+ void LoadMonster(int i);
+ void LoadMissile(int i);
diff --git a/games/devilutionx/patches/patch-structs.h b/games/devilutionx/patches/patch-structs.h
new file mode 100644
index 00000000000..89dc42b15b7
--- /dev/null
+++ b/games/devilutionx/patches/patch-structs.h
@@ -0,0 +1,53 @@
+$NetBSD: patch-structs.h,v 1.1 2019/07/28 10:26:43 nia Exp $
+
+64bit Compatible Saves
+https://patch-diff.githubusercontent.com/raw/diasurgical/devilutionX/pull/162.patch
+
+--- structs.h.orig 2019-05-19 17:06:45.000000000 +0000
++++ structs.h
+@@ -655,6 +655,7 @@ typedef struct ObjDataStruct {
+ BOOL oTrapFlag;
+ } ObjDataStruct;
+
++#pragma pack(push, 4)
+ typedef struct ObjectStruct {
+ int _otype;
+ int _ox;
+@@ -687,11 +688,13 @@ typedef struct ObjectStruct {
+ int _oVar7;
+ int _oVar8;
+ } ObjectStruct;
++#pragma pack(pop)
+
+ //////////////////////////////////////////////////
+ // portal
+ //////////////////////////////////////////////////
+
++#pragma pack(push, 4)
+ typedef struct PortalStruct {
+ BOOL open;
+ int x;
+@@ -700,6 +703,7 @@ typedef struct PortalStruct {
+ int ltype;
+ BOOL setlvl;
+ } PortalStruct;
++#pragma pack(pop)
+
+ //////////////////////////////////////////////////
+ // msg
+@@ -966,6 +970,7 @@ typedef struct TBuffer {
+ // quests
+ //////////////////////////////////////////////////
+
++#pragma pack(push, 4)
+ typedef struct QuestStruct {
+ unsigned char _qlevel;
+ unsigned char _qtype;
+@@ -980,6 +985,7 @@ typedef struct QuestStruct {
+ unsigned char _qvar2;
+ int _qlog;
+ } QuestStruct;
++#pragma pack(pop)
+
+ typedef struct QuestData {
+ unsigned char _qdlvl;