shithub: duke3d

Download patch

ref: 9213cca6363a951057fdcff5c4f394988c66d2d4
parent: 8ddc713957a1ecf73b83c1d28b558220a4caa50f
parent: b3de9147fd1261573e9b9014f081bf960ebd7903
author: Tanguy Fautre <[email protected]>
date: Tue Feb 18 15:45:50 EST 2020

Fixed compatibility between 32-bit and 64-bit savegames 


--- a/Engine/src/draw.c
+++ b/Engine/src/draw.c
@@ -859,8 +859,8 @@
 extern int32_t reciptable[2048];
 extern int32_t globalx3, globaly3;
 extern int32_t fpuasm;
-#define low32(a) ((a&0xffffffff))
-#define high32(a) ((int)(((__int64)a&(__int64)0xffffffff00000000)>>32))
+#define low32(a) (((a)&0xffffffff))
+#define high32(a) ((int)(((int64_t)(a)&(int64_t)0xffffffff00000000)>>32))
 
 //FCS: Render RENDER_SLOPPED_CEILING_AND_FLOOR
 void slopevlin(intptr_t i1, uint32_t i2, intptr_t* i3, uint32_t index, int32_t i4, int32_t i5, int32_t i6)
@@ -871,8 +871,8 @@
 //This is so bad to cast asm3 to int then float :( !!!
     float a = (float)(int32_t) asm3 + asm2_f;
     i1 -= slopemach_ecx;
-    esi = i5 + low32((__int64)globalx3 * (__int64)(i2<<3));
-    edi = i6 + low32((__int64)globaly3 * (__int64)(i2<<3));
+    esi = i5 + low32((int64_t)globalx3 * (int64_t)(i2<<3));
+    edi = i6 + low32((int64_t)globaly3 * (int64_t)(i2<<3));
     ebx = i4;
 
 	if (!RENDER_SLOPPED_CEILING_AND_FLOOR)
@@ -895,8 +895,8 @@
 	    edx = i2;
 	    i2 = eax;
 	    eax -= edx;
-	    ecx = low32((__int64)globalx3 * (__int64)eax);
-	    eax = low32((__int64)globaly3 * (__int64)eax);
+	    ecx = low32((int64_t)globalx3 * (int64_t)eax);
+	    eax = low32((int64_t)globaly3 * (int64_t)eax);
 	    a += asm2_f;
 
 	    asm4 = ebx;
--- a/Engine/src/filesystem.c
+++ b/Engine/src/filesystem.c
@@ -603,6 +603,9 @@
 		k += dasizeof;
 		ptr += dasizeof;
 	}
+
+    assert(k == kgoal);
+	
 	lzwbuflock[0] = lzwbuflock[1] = lzwbuflock[2] = lzwbuflock[3] = lzwbuflock[4] = 1;
 }
 
--- a/Engine/src/macos_compat.h
+++ b/Engine/src/macos_compat.h
@@ -20,7 +20,6 @@
 #endif
 
 #include <inttypes.h>
-#define __int64 int64_t
 
 #define O_BINARY 0
 
--- a/Engine/src/unix_compat.h
+++ b/Engine/src/unix_compat.h
@@ -22,7 +22,6 @@
 #endif
 
 #include <inttypes.h>
-#define __int64 int64_t
 
 #define O_BINARY 0
 
--- a/Game/src/actors.c
+++ b/Game/src/actors.c
@@ -1516,8 +1516,7 @@
 void movestandables(void)
 {
     short i, j, k, m, nexti, nextj, p, sect;
-    intptr_t l=0,*t;
-    int32_t x;
+    int32_t l=0,x,*t;
     spritetype *s;
 
     i = headspritestat[6];
@@ -3139,8 +3138,7 @@
 
 void moveactors(void)
 {
-    int32_t x, m, l;
-	intptr_t *t;
+    int32_t x, m, l, *t;
     short a, i, j, nexti, nextj, sect, p;
     spritetype *s;
     uint16_t k;
@@ -4397,8 +4395,7 @@
 void moveexplosions(void)  // STATNUM 5
 {
     short i, j, nexti, sect, p;
-    intptr_t l, *t;
-    int32_t x;
+    int32_t l, x, *t;
     spritetype *s;
 
     i = headspritestat[5];
@@ -4930,8 +4927,7 @@
 
 void moveeffectors(void)   //STATNUM 3
 {
-    intptr_t q=0, l, st, j, *t;
-    int32_t x,m;
+    int32_t q = 0, l, m, x, st, j, * t;
     short i, k, nexti, nextk, p, sh, nextj;
     spritetype *s;
     sectortype *sc;
@@ -6486,32 +6482,35 @@
                 break;
 
             case 21: // Cascading effect
+            {
+                int32_t *lp;
 
-                if( t[0] == 0 ) break;
+                if (t[0] == 0) break;
 
-                if( s->ang == 1536 )
-                    l = (intptr_t) &sc->ceilingz;
+                if (s->ang == 1536)
+                    lp = &sc->ceilingz;
                 else
-                    l = (intptr_t) &sc->floorz;
+                    lp = &sc->floorz;
 
-                if( t[0] == 1 ) //Decide if the s->sectnum should go up or down
+                if (t[0] == 1) //Decide if the s->sectnum should go up or down
                 {
-                    s->zvel = ksgn(s->z-*(intptr_t*)l) * (SP<<4);
+                    s->zvel = ksgn(s->z - *lp) * (SP << 4);
                     t[0]++;
                 }
 
-                if( sc->extra == 0 )
+                if (sc->extra == 0)
                 {
-                    *(intptr_t*)l += s->zvel;
+                    *lp += s->zvel;
 
-                    if(klabs(*(intptr_t*)l-s->z) < 1024)
+                    if (klabs(*lp - s->z) < 1024)
                     {
-                        *(intptr_t*)l = s->z;
+                        *lp = s->z;
                         KILLIT(i); //All done
                     }
                 }
                 else sc->extra--;
                 break;
+            }
 
             case 22:
 
--- a/Game/src/duke3d.h
+++ b/Game/src/duke3d.h
@@ -26,23 +26,6 @@
 #ifndef _INCL_DUKE3D_H_
 #define _INCL_DUKE3D_H_
 
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-
-
-#include "platform.h"
-#if !PLATFORM_MACOSX
-#include <malloc.h>
-#endif
-
-#include <inttypes.h>
-
-#include <fcntl.h>
-#include <time.h>
-#include <ctype.h>
-
 #include "build.h"
 
 #if (!defined MAX_PATH)
@@ -67,7 +50,6 @@
 #include "dukewin.h"
 #endif
 
-#include "function.h"
 
 //  FIX_00022: Automatically recognize the shareware grp (v1.3) + full version (1.3d) +
 //             atomic (1.4/1.5 grp) and the con files version (either 1.3 or 1.4) (JonoF's idea)
@@ -360,6 +342,7 @@
 extern short cyclers[MAXCYCLERS][6],numcyclers;
 extern char  myname[2048];
 
+#pragma pack(push, 4)
 struct user_defs
 {
     uint8_t  god,warp_on,cashman,eog,showallmap;
@@ -378,19 +361,19 @@
     int32_t camera_time,folfvel,folavel,folx,foly,fola;
     int32_t reccnt;
 
-    int32 entered_name,screen_tilting,shadows,fta_on,executions,auto_run;
-    int32 coords,tickrate,m_coop,coop,screen_size,extended_screen_size,lockout,crosshair,showweapons;
-    int32 mywchoice[MAX_WEAPONS],wchoice[MAXPLAYERS][MAX_WEAPONS],playerai;
+    int32_t entered_name,screen_tilting,shadows,fta_on,executions,auto_run;
+    int32_t coords,tickrate,m_coop,coop,screen_size,extended_screen_size,lockout,crosshair,showweapons;
+    int32_t mywchoice[MAX_WEAPONS],wchoice[MAXPLAYERS][MAX_WEAPONS],playerai;
 
-    int32 respawn_monsters,respawn_items,respawn_inventory,recstat,monsters_off,brightness;
-    int32 m_respawn_items,m_respawn_monsters,m_respawn_inventory,m_recstat,m_monsters_off,detail;
+    int32_t respawn_monsters,respawn_items,respawn_inventory,recstat,monsters_off,brightness;
+    int32_t m_respawn_items,m_respawn_monsters,m_respawn_inventory,m_recstat,m_monsters_off,detail;
 	// FIX_00082: /q option taken off when playing a demo (multimode_bot)    
-	int32 m_ffire,ffire,m_player_skill,m_level_number,m_volume_number,multimode,multimode_bot;
-    int32 player_skill,level_number,volume_number,m_marker,marker,mouseflip;
+    int32_t m_ffire,ffire,m_player_skill,m_level_number,m_volume_number,multimode,multimode_bot;
+    int32_t player_skill,level_number,volume_number,m_marker,marker,mouseflip;
 
-	int32 showcinematics, hideweapon;
-	int32 auto_aim, gitdat_mdk; //AutoAim toggle variable.
-	int32 weaponautoswitch;
+    int32_t showcinematics, hideweapon;
+    int32_t auto_aim, gitdat_mdk; //AutoAim toggle variable.
+    int32_t weaponautoswitch;
 
 	// FIX_00015: Backward compliance with older demos (down to demos v27, 28, 116 and 117 only)
 	uint8_t  playing_demo_rev;
@@ -405,6 +388,7 @@
 	uint32_t exeCRC[MAXPLAYERS];
 	uint32_t conCRC[MAXPLAYERS];
 };
+#pragma pack(pop)
 
 struct player_orig
 {
@@ -430,6 +414,7 @@
 
 extern int32_t fricxv,fricyv;
 
+#pragma pack(push, 4)
 struct player_struct
 {
     int32_t zoom,exitx,exity,loogiex[64],loogiey[64],numloogs,loogcnt;
@@ -440,7 +425,7 @@
     int32_t bobcounter,weapon_sway;
     int32_t pals_time,randomflamex,crack_time;
 
-    int32 aim_mode;
+    int32_t aim_mode;
 
     short ang,oang,angvel,cursectnum,look_ang,last_extra,subweapon;
     short ammo_amount[MAX_WEAPONS],wackedbyactor,frag,fraggedself;
@@ -474,8 +459,15 @@
     uint8_t  scuba_on,footprintpal,heat_on;
 
     uint8_t   holster_weapon,falling_counter;
-    uint8_t   gotweapon[MAX_WEAPONS],refresh_inventory,*palette;
+    uint8_t   gotweapon[MAX_WEAPONS],refresh_inventory;
 
+	// tanguyf: fix the palette pointer size being 32/64-bit dependent. For some reason this is serialised into savegames.
+    union
+    {
+	    uint8_t* palette;
+        uint64_t _palette_padding;
+    };
+
     uint8_t  toggle_key_flag,knuckle_incs; // ,select_dir;
     uint8_t  walking_snd_toggle, palookup, hard_landing;
     uint8_t  max_secret_rooms,secret_rooms,/*fire_flag,*/pals[3];
@@ -484,15 +476,16 @@
 	// local but synch variables (ud is local but not synch):
 
 	// FIX_00023: Moved Addfaz's autoaim handler to synch variables (to avoid out of synch)
-	int32 auto_aim; //AutoAim toggle variable.
+    int32_t auto_aim; //AutoAim toggle variable.
 
 	// FIX_00012: added "weapon autoswitch" toggle allowing to turn the autoswitch off
 	//            when picking up new weapons. The weapon sound on pickup will remain on, to not 
 	//           affect the opponent's gameplay (so he can still hear you picking up new weapons)
-	int32 weaponautoswitch;
+    int32_t weaponautoswitch;
 
-	uint8_t  fakeplayer;
+	uint8_t fakeplayer;
 };
+#pragma pack(pop)
 
 extern uint8_t  tempbuf[2048];
 extern uint8_t packbuf[576];
@@ -524,10 +517,10 @@
 extern uint8_t  playerreadyflag[MAXPLAYERS],playerquitflag[MAXPLAYERS];
 extern char  sounds[NUM_SOUNDS][14];
 
-extern intptr_t script[MAXSCRIPTSIZE],*scriptptr,*insptr,*labelcode,labelcnt;
+extern int32_t script[MAXSCRIPTSIZE],*scriptptr,*insptr,*labelcode,labelcnt;
 extern char  *label,*textptr,error,warning;
 extern uint8_t killit_flag;
-extern intptr_t*actorscrptr[MAXTILES],*parsing_actor;
+extern int32_t*actorscrptr[MAXTILES],*parsing_actor;
 extern uint8_t  actortype[MAXTILES];
 extern uint8_t  *music_pointer;
 
@@ -542,6 +535,7 @@
 extern uint8_t  inspace(short sectnum);
 
 
+#pragma pack(push, 4)
 struct weaponhit
 {
     uint8_t  cgg;
@@ -549,8 +543,9 @@
     short tempang,actorstayput,dispicnum;
     short timetosleep;
     int32_t floorz,ceilingz,lastvx,lastvy,bposx,bposy,bposz;
-    intptr_t temp_data[6]; // tanguyf: this causes savegames not to be compatible between 32 and 64-bits
+    int32_t temp_data[6];
 };
+#pragma pack(pop)
 
 extern struct weaponhit hittype[MAXSPRITES];
 
--- a/Game/src/dukewin.h
+++ b/Game/src/dukewin.h
@@ -1,10 +1,6 @@
 #ifndef _INCL_DUKEWIN_H_
 #define _INCL_DUKEWIN_H_ 1
 
-#ifndef _MSC_VER  /* might need this. */
-typedef int32_t int32_t __int64;
-#endif
-
 #pragma warning(disable:4761)
 
 #ifdef _DEBUG
@@ -46,11 +42,6 @@
 #ifndef max
 #define max(x, y) ((x) > (y) ? (x) : (y))
 #endif
-
-#ifdef FP_OFF
-#undef FP_OFF
-#endif
-#define FP_OFF(x) ((int32_t) (x))
 
 // 64 megs should be enough for anybody.  :)  --ryan.
 #define Z_AvailHeap() ((64 * 1024) * 1024)
--- a/Game/src/funct.h
+++ b/Game/src/funct.h
@@ -30,564 +30,289 @@
 #include "duke3d.h"
 
 extern void sendscore(char  *s);
-//#line "sounds.c" 25
 extern void SoundStartup(void );
-//#line "sounds.c" 95
 extern void SoundShutdown(void );
-//#line "sounds.c" 118
 extern void MusicStartup(void );
-//#line "sounds.c" 166
 extern void MusicShutdown(void );
-//#line "sounds.c" 181
 extern int USRHOOKS_GetMem(void  **ptr,uint32_t size);
-//#line "sounds.c" 192
 extern int USRHOOKS_FreeMem(void  *ptr);
-//#line "sounds.c" 200
 extern void intomenusounds(void );
-//#line "sounds.c" 227
 extern void playmusic(char  *fn);
-//#line "sounds.c" 251
 extern uint8_t  loadsound(uint16_t num);
-//#line "sounds.c" 277
 extern int xyzsound(short num,short i,int32_t x,int32_t y,int32_t z);
-//#line "sounds.c" 407
 extern void sound(short num);
-//#line "sounds.c" 463
 extern int spritesound(uint16_t num,short i);
-//#line "sounds.c" 469
 extern void stopsound(short num);
-//#line "sounds.c" 478
 extern void stopenvsound(short num,short i);
-//#line "sounds.c" 494
 extern void pan3dsound(void );
-//#line "sounds.c" 571
 extern void TestCallBack(int32_t num);
-//#line "sector.c" 9
 extern short callsound(short sn,short whatsprite);
-//#line "sector.c" 56
 extern short check_activator_motion(short lotag);
-//#line "sector.c" 93
 extern uint8_t  isadoorwall(short dapic);
-//#line "sector.c" 124
 extern uint8_t  isanunderoperator(short lotag);
-//#line "sector.c" 139
 extern uint8_t  isanearoperator(short lotag);
-//#line "sector.c" 161
 extern short checkcursectnums(short sect);
-//#line "sector.c" 169
 extern int32_t ldist(spritetype *s1,spritetype *s2);
-//#line "sector.c" 177
 extern int32_t dist(spritetype *s1,spritetype *s2);
-//#line "sector.c" 186
 extern short findplayer(spritetype *s,int32_t *d);
-//#line "sector.c" 214
 extern short findotherplayer(short p,int32_t *d);
-//#line "sector.c" 240
 extern void doanimations(void );
-//#line "sector.c" 301
 extern int32_t getanimationgoal(int32_t *animptr);
-//#line "sector.c" 315
 extern int32_t setanimation(short animsect,int32_t *animptr,int32_t thegoal,int32_t thevel);
-//#line "sector.c" 348
 extern void animatecamsprite(void );
-//#line "sector.c" 369
 extern void animatewalls(void );
-//#line "sector.c" 457
 extern uint8_t  activatewarpelevators(short s,short d);
-//#line "sector.c" 504
 extern void operatesectors(short sn,short ii);
-//#line "sector.c" 997
 extern void operaterespawns(short low);
-//#line "sector.c" 1020
 extern void operateactivators(short low,short snum);
-//#line "sector.c" 1089
 extern void operatemasterswitches(short low);
-//#line "sector.c" 1104
 extern void operateforcefields(short s,short low);
-//#line "sector.c" 1140
 extern uint8_t  checkhitswitch(short snum,int32_t w,uint8_t  switchtype);
-//#line "sector.c" 1515
 extern void activatebysector(short sect,short j);
-//#line "sector.c" 1532
 extern void checkhitwall(short spr,short dawallnum,int32_t x,int32_t y,int32_t z,short atwith);
-//#line "sector.c" 1746
 extern void checkplayerhurt(struct player_struct *p,short j);
-//#line "sector.c" 1816
 extern uint8_t  checkhitceiling(short sn);
-//#line "sector.c" 1891
 extern void checkhitsprite(short i,short sn);
-//#line "sector.c" 2326
 extern void allignwarpelevators(void );
-//#line "sector.c" 2357
 extern void cheatkeys(short snum);
-//#line "sector.c" 2766
 extern void checksectors(short snum);
-//#line "rts.c" 36
 extern void RTS_AddFile(char  *filename);
-//#line "rts.c" 93
 extern void RTS_Init(char *filename);
-//#line "rts.c" 126
 extern int32 RTS_NumSounds(void );
-//#line "rts.c" 141
 extern int32 RTS_SoundLength(int32 lump);
-//#line "rts.c" 157
 extern char  *RTS_GetSoundName(int32 i);
-//#line "rts.c" 174
 extern void RTS_ReadLump(int32 lump,void *dest);
-//#line "rts.c" 194
 extern void *RTS_GetSound(int32 lump);
-//#line "premap.c" 7
 extern void xyzmirror(short i,short wn);
-//#line "premap.c" 20
 extern void vscrn(void );
-//#line "premap.c" 58
 int countfragbars(void);
 extern void pickrandomspot(short snum);
-//#line "premap.c" 80
 extern void resetplayerstats(short snum);
-//#line "premap.c" 187
 extern void resetweapons(short snum);
-//#line "premap.c" 212
 extern void resetinventory(short snum);
-//#line "premap.c" 232
 extern void resetprestat(short snum,uint8_t  g);
-//#line "premap.c" 294
 extern void setupbackdrop(short backpicnum);
-//#line "premap.c" 329
 extern void cachespritenum(short i);
-//#line "premap.c" 443
 extern void cachegoodsprites(void );
-//#line "premap.c" 516
 extern void prelevel(uint8_t  g);
-//#line "premap.c" 823
 extern void newgame(uint8_t  vn,uint8_t  ln,uint8_t  sk);
-//#line "premap.c" 874
 extern void resetpspritevars(uint8_t  g);
-//#line "premap.c" 1012
 extern void resettimevars(void );
-//#line "premap.c" 1043
 extern void genspriteremaps(void );
-//#line "premap.c" 1077
 extern void waitforeverybody(void);
-//#line "premap.c" 1131
 extern uint8_t  checksum(int32_t sum);
-//#line "premap.c" 1163
 extern uint8_t  getsound(uint16_t num);
-//#line "premap.c" 1189
 extern void precachenecessarysounds(void );
-//#line "premap.c" 1201
 extern void cacheit(void );
-//#line "premap.c" 1244
 extern void dofrontscreens(void );
-//#line "premap.c" 1285
 extern void enterlevel(uint8_t  g);
-//#line "player.c" 10
 extern void setpal(struct player_struct *p);
-//#line "player.c" 28
 extern void incur_damage(struct player_struct *p);
-//#line "player.c" 59
 extern void quickkill(struct player_struct *p);
-//#line "player.c" 73
 extern void forceplayerangle(struct player_struct *p);
-//#line "player.c" 85
 extern void tracers(int32_t x1,int32_t y1,int32_t z1,int32_t x2,int32_t y2,int32_t z2,int32_t n);
-//#line "player.c" 114
 extern int32_t hits(short i);
-//#line "player.c" 131
 extern int32_t hitasprite(short i,short *hitsp);
-//#line "player.c" 152
 extern int32_t hitawall(struct player_struct *p,short *hitw);
-//#line "player.c" 163
 extern short aim(spritetype *s,short aang, short auto_aim);
-//#line "player.c" 234
 extern void shoot(short i,short atwith);
-//#line "player.c" 939
 extern void displayloogie(short snum);
-//#line "player.c" 958
 extern uint8_t  animatefist(short gs,short snum);
-//#line "player.c" 986
 extern uint8_t  animateknee(short gs,short snum);
-//#line "player.c" 1002
 extern uint8_t  animateknuckles(short gs,short snum);
-//#line "player.c" 1022
 extern void displaymasks(short snum);
-//#line "player.c" 1043
 extern uint8_t  animatetip(short gs,short snum);
-//#line "player.c" 1064
 extern uint8_t  animateaccess(short gs,short snum);
-//#line "player.c" 1090
 extern void displayweapon(short snum);
-//#line "player.c" 1501
 extern void getinput(short snum);
-//#line "player.c" 1742
 extern uint8_t  doincrements(struct player_struct *p);
-//#line "player.c" 1935
 extern void checkweapons(struct player_struct *p);
-//#line "player.c" 1951
 extern void processinput(short snum);
-//#line "menues.c" 18
 extern void cmenu(short cm);
-//#line "menues.c" 38
 extern void savetemp(char  *fn,uint8_t* daptr,int32_t dasiz);
-//#line "menues.c" 49
 extern void getangplayers(short snum);
-//#line "menues.c" 67
 extern int loadpheader(uint8_t  spot,int32 *vn,int32 *ln,int32 *psk,int32 *numplr);
-//#line "menues.c" 105
 extern int loadplayer(int8_t spot);
-//#line "menues.c" 276
 extern int saveplayer(int8_t spot);
-//#line "menues.c" 421
 extern void sendgameinfo(void );
-//#line "menues.c" 434
 extern int probe(int x,int y,int i,int n);
 extern int probeXduke(int x,int y,int i,int n, int32_t spriteSize);
-//#line "menues.c" 521
 extern int menutext(int x,int y,short s,short p,char  *t);
-//#line "menues.c" 630
 extern int menutextc(int x,int y,short s,short p,char  *t);
-//#line "menues.c" 727
 extern void bar(int x,int y,short *p,short dainc,uint8_t  damodify,short s,short pa);
-//#line "menues.c" 806
 extern void dispnames(void );
-//#line "menues.c" 832
 extern int getfilenames(char  kind[]);
-//#line "menues.c" 865
 extern void sortfilenames(void);
-//#line "menues.c" 886
 extern void menus(void );
 void gameexitanycase(void);
-//#line "menues.c" 2414
 extern void palto(uint8_t  r,uint8_t  g,uint8_t  b,int32_t e, int present);
-//#line "menues.c" 2436
 extern void drawoverheadmap(int32_t cposx,int32_t cposy,int32_t czoom,short cang);
-//#line "menues.c" 2685
 extern void playanm(char  *fn,uint8_t );
-//#line "gamedef.c" 122
 extern short getincangle(short a,short na);
-//#line "gamedef.c" 140
 extern uint8_t  ispecial(uint8_t  c);
-//#line "gamedef.c" 154
 extern uint8_t  isaltok(uint8_t  c);
-//#line "gamedef.c" 159
 extern void getglobalz(short i);
-//#line "gamedef.c" 203
 extern void makeitfall(short i);
-//#line "gamedef.c" 243
 extern void getlabel(void );
-//#line "gamedef.c" 267
 extern int32_t keyword(void );
-//#line "gamedef.c" 300
 extern int32_t transword(void );
-//#line "gamedef.c" 342
 extern void transnum(void );
-//#line "gamedef.c" 402
 extern uint8_t  parsecommand(int readfromGRP );
-//#line "gamedef.c" 1227
 extern void passone(int readfromGRP);
-//#line "gamedef.c" 1239
 extern void loadefs(char  *fn,char  *mptr, int readfromGRP);
-//#line "gamedef.c" 1342
 extern uint8_t  dodge(spritetype *s);
-//#line "gamedef.c" 1374
 extern short furthestangle(short i,short angs);
-//#line "gamedef.c" 1404
 extern short furthestcanseepoint(short i,spritetype *ts,int32_t *dax,int32_t *day);
-//#line "gamedef.c" 1444
 extern void alterang(short a);
-//#line "gamedef.c" 1512
 extern void move(void);
-//#line "gamedef.c" 1711
 extern void parseifelse(int32_t condition);
-//#line "gamedef.c" 1729
 extern uint8_t  parse(void );
-//#line "gamedef.c" 2699
 extern void execute(short i,short p,int32_t x);
-//#line "game.c" 63
 extern void overwritesprite(int32_t thex,int32_t they,short tilenum,int8_t shade,uint8_t  stat,uint8_t  dapalnum);
-//#line "game.c" 70
 extern void timerhandler(void);
-//#line "game.c" 75
 extern int inittimer(int);
-//#line "game.c" 81
 extern void uninittimer(void );
-//#line "game.c" 89
 extern int gametext(int x,int y,char  *t,uint8_t  s,short dabits);
-//#line "game.c" 136
 extern int gametextpart(int x,int y,char  *t,uint8_t  s,short p);
-//#line "game.c" 192
 extern int minitext(int x,int y,char  *t,uint8_t  p,uint8_t  sb);
-//#line "game.c" 231
 extern void gamenumber(int32_t x,int32_t y,int32_t n,uint8_t  s);
-//#line "game.c" 248
 extern void ShutDown(void );
-//#line "game.c" 260
 extern void allowtimetocorrecterrorswhenquitting(void );
-//#line "game.c" 280
 extern void getpackets(void );
-//#line "game.c" 502
 extern void faketimerhandler(void);
-//#line "game.c" 788
 extern void checksync(void );
-//#line "game.c" 815
 extern void check_fta_sounds(short i);
-//#line "game.c" 869
 extern short inventory(spritetype *s);
-//#line "game.c" 886
 extern short badguy(spritetype *s);
-//#line "game.c" 924
 extern short badguypic(short pn);
-//#line "game.c" 963
 extern void myos(int32_t x,int32_t y,short tilenum,int8_t shade,uint8_t  orientation);
-//#line "game.c" 976
 extern void myospal(int32_t x,int32_t y,short tilenum,int8_t shade,uint8_t  orientation,uint8_t  p);
-//#line "game.c" 991
 extern void invennum(int32_t x,int32_t y,uint8_t  num1,uint8_t  ha,uint8_t  sbits);
-//#line "game.c" 1021
 extern void weaponnum(short ind,int32_t x,int32_t y,int32_t num1,int32_t num2,uint8_t  ha);
-//#line "game.c" 1049
 extern void weaponnum999(uint8_t  ind,int32_t x,int32_t y,int32_t num1,int32_t num2,uint8_t  ha);
-//#line "game.c" 1088
 extern void weapon_amounts(struct player_struct *p,int32_t x,int32_t y,int32_t u);
-//#line "game.c" 1197
 extern void digitalnumber(int32_t x,int32_t y,int32_t n,uint8_t  s,uint8_t  cs);
-//#line "game.c" 1223
 extern void scratchmarks(int32_t x,int32_t y,int32_t n,uint8_t  s,uint8_t  p);
-//#line "game.c" 1238
 extern void displayinventory(struct player_struct *p);
-//#line "game.c" 1296
 extern void displayfragbar(void );
-//#line "game.c" 1318
 void drawsmallweapon(short weapon, float scale, short x, short y); // xduke
 extern void coolgaugetext(short snum);
-//#line "game.c" 1557
 extern void tics(short offx, short offy , short color);
-//#line "game.c" 1572
 extern void clocks(void );
-//#line "game.c" 1582
 extern void coords(short snum);
-//#line "game.c" 1607
 extern void operatefta(void);
-//#line "game.c" 1654
 extern void FTA(short q,struct player_struct *p, int mode);
-//#line "game.c" 1668
 extern void showtwoscreens(void );
 
-//#line "game.c" 1705
 extern void gameexit(char  *t);
-//#line "game.c" 1752
 extern short strget(short x,short y,char  *t,short dalen,short c);
-//#line "game.c" 1819
 extern void displayrest(int32_t smoothratio);
-//#line "game.c" 2047
 extern void updatesectorz(int32_t x,int32_t y,int32_t z,short *sectnum);
-//#line "game.c" 2085
 extern void view(struct player_struct *pp,int32_t *vx,int32_t *vy,int32_t *vz,short *vsectnum,short ang,short horiz);
-//#line "game.c" 2137
 extern void drawbackground(void );
-//#line "game.c" 2200
 extern void displayrooms(short snum,int32_t smoothratio);
-//#line "game.c" 2445
 extern short LocateTheLocator(short n,short sn);
-//#line "game.c" 2459
 extern short EGS(short whatsect,int32_t s_x,int32_t s_y,int32_t s_z,short s_pn,int8_t s_s,int8_t s_xr,int8_t s_yr,short s_a,short s_ve,int32_t s_zv,short s_ow,int8_t s_ss);
-//#line "game.c" 2537
 extern uint8_t  wallswitchcheck(short i);
-//#line "game.c" 2588
 extern short spawn(short j,short pn);
-//#line "game.c" 4181
 extern void animatesprites(int32_t x,int32_t y,short a,int32_t smoothratio);
-//#line "game.c" 4859
 extern void cheats(void );
-//#line "game.c" 5303
 extern void nonsharedkeys(void );
-//#line "game.c" 5863
 extern void comlinehelp(char  **argv);
-//#line "game.c" 5889
 extern void checkcommandline(int argc,char  **argv);
-//#line "game.c" 6078
 extern void printstr(short x,short y,uint8_t  string[],uint8_t  attribute);
-//#line "game.c" 6104
 extern void Logo(void );
-//#line "game.c" 6187
 extern void loadtmb(void );
-//#line "game.c" 6210
 extern void compilecons(void );
-//#line "game.c" 6230
+extern int32_t encodescriptptr(int32_t* scptr);
+extern int32_t* decodescriptptr(int32_t scptr);
 extern void Startup(void );
-//#line "game.c" 6284
 extern void getnames(void );
-//#line "game.c" 6309
 extern int main(int argc,char  **argv);
-//#line "game.c" 6563
 extern uint8_t  opendemoread(uint8_t  which_demo);
-//#line "game.c" 6589
 extern void opendemowrite(void );
-//#line "game.c" 6608
 extern void record(void );
-//#line "game.c" 6626
 extern void closedemowrite(void );
-//#line "game.c" 6642
 extern int32_t playback(void );
-//#line "game.c" 6777
 extern uint8_t  moveloop(void);
-//#line "game.c" 6796
 extern void fakedomovethingscorrect(void);
-//#line "game.c" 6829
 extern void fakedomovethings(void );
-//#line "game.c" 7247
 extern uint8_t  domovethings(void );
-//#line "game.c" 7373
 extern void displaybonuspics(short x,short y,short p);
-//#line "game.c" 7396
 extern void doorders(void );
-//#line "game.c" 7432
 extern void dobonus(uint8_t  bonusonly);
-//#line "game.c" 7846
 extern void cameratext(short i);
-//#line "game.c" 7869
 extern void vglass(int32_t x,int32_t y,short a,short wn,short n);
-//#line "game.c" 7882
 extern void lotsofglass(short i,short wallnum,short n);
-//#line "game.c" 7924
 extern void spriteglass(short i,short n);
-//#line "game.c" 7937
 extern void ceilingglass(short i,short sectnum,short n);
-//#line "game.c" 7966
 extern void lotsofcolourglass(short i,short wallnum,short n);
-//#line "game.c" 8004
 extern void SetupGameButtons(void );
-//#line "game.c" 8068
 extern int32_t GetTime(void );
-//#line "game.c" 8082
 extern void CenterCenter(void );
-//#line "game.c" 8095
 extern void UpperLeft(void );
-//#line "game.c" 8108
 extern void LowerRight(void );
-//#line "game.c" 8121
 extern void CenterThrottle(void );
-//#line "game.c" 8134
 extern void CenterRudder(void );
-//#line "game.c" ????
 extern void takescreenshot(void );
-//#line "config.c" 57
 extern void CONFIG_GetSetupFilename(void );
-//#line "config.c" 170
 extern int32 CONFIG_FunctionNameToNum(char  *func);
-//#line "config.c" 192
 extern char  *CONFIG_FunctionNumToName(int32 func);
-//#line "config.c" 211
 extern int32 CONFIG_AnalogNameToNum(char  *func);
-//#line "config.c" 240
 extern void CONFIG_SetDefaults(void );
-//#line "config.c" 264
 extern void CONFIG_ReadKeys(void );
-//#line "config.c" 314
 extern void CONFIG_SetupMouse(int32 scripthandle);
-//#line "config.c" 376
 extern void CONFIG_SetupGamePad(int32 scripthandle);
-//#line "config.c" 427
 extern void CONFIG_SetupJoystick(int32 scripthandle);
-//#line "config.c" 485
 extern void readsavenames(void );
-//#line "config.c" 512
 extern void CONFIG_ReadSetup(void );
-//#line "config.c" 613
 extern void CONFIG_WriteSetup(void );
-//#line "animlib.c" 34
 extern void CheckAnimStarted(uint8_t  *funcname);
-//#line "animlib.c" 46
 extern uint16 findpage(uint16 framenumber);
-//#line "animlib.c" 71
 extern void loadpage(uint16 pagenumber,uint16 *pagepointer);
-//#line "animlib.c" 97
 extern void CPlayRunSkipDump(byte *srcP,byte *dstP);
-//#line "animlib.c" 177
 extern void renderframe(uint16 framenumber,uint16 *pagepointer);
-//#line "animlib.c" 214
 extern void drawframe(uint16 framenumber);
-//#line "animlib.c" 228
 extern void ANIM_LoadAnim(byte *buffer);
-//#line "animlib.c" 260
 extern void ANIM_FreeAnim(void );
-//#line "animlib.c" 275
 extern int32 ANIM_NumFrames(void );
-//#line "animlib.c" 287
 extern byte *ANIM_DrawFrame(int32 framenumber);
-//#line "animlib.c" 312
 extern byte *ANIM_GetPalette(void );
-//#line "actors.c" 7
 extern void updateinterpolations(void);
-//#line "actors.c" 15
 extern void setinterpolation(int32_t *posptr);
-//#line "actors.c" 27
 extern void stopinterpolation(int32_t *posptr);
-//#line "actors.c" 41
 extern void dointerpolations(int32_t smoothratio);
-//#line "actors.c" 55
 extern void restoreinterpolations(void);
-//#line "actors.c" 63
 extern int32_t ceilingspace(short sectnum);
-//#line "actors.c" 77
 extern int32_t floorspace(short sectnum);
-//#line "actors.c" 91
 extern void addammo(short weapon,struct player_struct *p,short amount);
-//#line "actors.c" 99
 extern void addweapon(struct player_struct *p,short weapon);
-//#line "actors.c" 132
 extern void checkavailinven(struct player_struct *p);
-//#line "actors.c" 152
 extern void checkavailweapon(struct player_struct *p);
-//#line "actors.c" 301
 extern int32_t ifsquished(short i,short p);
-//#line "actors.c" 326
 extern void hitradius(short i,int32_t r,int32_t hp1,int32_t hp2,int32_t hp3,int32_t hp4);
-//#line "actors.c" 556
 extern int movesprite(short spritenum,int32_t xchange,int32_t ychange,int32_t zchange,uint32_t cliptype);
-//#line "actors.c" 643
 extern short ssp(short i,uint32_t cliptype);
-//#line "actors.c" 658
 extern void insertspriteq(short i);
-//#line "actors.c" 666
 extern void lotsofmoney(spritetype *s,short n);
-//#line "actors.c" 676
 extern void guts(spritetype *s,short gtype,short n,short p);
-//#line "actors.c" 718
 extern void setsectinterpolate(short i);
-//#line "actors.c" 742
 extern void clearsectinterpolate(short i);
-//#line "actors.c" 760
 extern void ms(short i);
-//#line "actors.c" 791
 extern void movefta(void );
-//#line "actors.c" 882
 extern short ifhitsectors(short sectnum);
-//#line "actors.c" 896
 extern short ifhitbyweapon(short sn);
-//#line "actors.c" 970
 extern void movecyclers(void );
-//#line "actors.c" 1007
 extern void movedummyplayers(void );
-//#line "actors.c" 1053
 extern void moveplayers(void );
-//#line "actors.c" 1192
 extern void movefx(void );
-//#line "actors.c" 1294
 extern void movefallers(void );
-//#line "actors.c" 1389
 extern void movestandables(void );
-//#line "actors.c" 2234
 extern void bounce(short i);
-//#line "actors.c" 2273
 extern void moveweapons(void );
-//#line "actors.c" 2613
 extern void movetransports(void );
-//#line "actors.c" 2887
 extern void moveeffectors(void );
-//#line "actors.c" 4840
 extern void moveactors(void );
-//#line "actors.c" 6005
 extern void moveexplosions(void );
 
 #endif
--- a/Game/src/game.c
+++ b/Game/src/game.c
@@ -24,6 +24,8 @@
 */
 //-------------------------------------------------------------------------
 
+#include <time.h>
+
 #ifdef _WIN32
   #include <windows.h>
 #elif defined(__APPLE__)
@@ -5370,11 +5372,10 @@
     return i;
 }
 
-
 void animatesprites(int32_t x,int32_t y,short a,int32_t smoothratio)
 {
     short i, j, k, p, sect;
-    intptr_t l, t1,t3,t4;
+    int32_t l, t1,t3,t4;
     spritetype *s,*t;
 
     for(j=0;j < spritesortcnt; j++)
@@ -5859,7 +5860,7 @@
 
         if( actorscrptr[s->picnum] )
         {
-            if(t4>10000)
+            if(t4<0)
 				// FIX_00093: fixed crashbugs in multiplayer (mine/blimp)
 				// This is the mine issue (confusion bug in hittype[i].temp_data[4] usage)
 				// close to blimp bug (search for BLIMP)
@@ -5872,8 +5873,10 @@
 				// at the bottom of the chain. Crashes when it's about to respawn.
 				// Lame fix. ok for w32. Doesn't work for other plateform.
 				// How to make a differene between a timer and an address??
+				// 
+				// tanguyf: encoded script ptr are now negative.
             {
-                l = *(intptr_t *)(t4+sizeof(intptr_t)*2);
+                l = *(decodescriptptr(t4) + 2);
 
                 switch( l )
                 {
@@ -5921,7 +5924,7 @@
                         break;
                 }
 
-                t->picnum += k + ( *(intptr_t *)t4 ) + l * t3;
+                t->picnum += k + (*decodescriptptr(t4)) + l * t3;
 
                 if(l > 0)
                     while(tiles[t->picnum].dim.width == 0 && t->picnum > 0 )
@@ -7685,16 +7688,14 @@
 
 void compilecons(void)
 {
-	char  userconfilename[512];
+    char  userconfilename[512];
 
-   mymembuf = (char  *)hittype;
-   labelcode = (intptr_t *)&sector[0];
-   label = (char  *)sprite;
+    mymembuf = (char*)hittype;
+    labelcode = (int32_t*)&sector[0];
+    label = (char*)sprite;
 
-	sprintf(userconfilename, "%s", confilename);
-
-   loadefs(userconfilename,mymembuf, 0);  
-
+    sprintf(userconfilename, "%s", confilename);
+    loadefs(userconfilename, mymembuf, 0);
 }
 
 
--- a/Game/src/gamedef.c
+++ b/Game/src/gamedef.c
@@ -37,7 +37,7 @@
 
 static short g_i,g_p;
 static int32_t g_x;
-static intptr_t *g_t;
+static int32_t *g_t;
 static spritetype *g_sp;
 
 #define NUMKEYWORDS     112
@@ -53,7 +53,7 @@
 {
     "definelevelname",  // 0
     "actor",            // 1    [#]
-    "addammo",   // 2    [#]
+    "addammo",          // 2    [#]
     "ifrnd",            // 3    [C]
     "enda",             // 4    [:]
     "ifcansee",         // 5    [C]
@@ -134,35 +134,35 @@
     "quote",            // 80
     "ifinouterspace",   // 81
     "ifnotmoving",      // 82
-    "respawnhitag",        // 83
-    "tip",             // 84
+    "respawnhitag",     // 83
+    "tip",              // 84
     "ifspritepal",      // 85
-    "money",         // 86
-    "soundonce",         // 87
+    "money",            // 86
+    "soundonce",        // 87
     "addkills",         // 88
     "stopsound",        // 89
-    "ifawayfromwall",       // 90
+    "ifawayfromwall",   // 90
     "ifcanseetarget",   // 91
-    "globalsound",  // 92
-    "lotsofglass", // 93
-    "ifgotweaponce", // 94
-    "getlastpal", // 95
-    "pkick",  // 96
-    "mikesnd", // 97
-    "useractor",  // 98
-    "sizeat",  // 99
-    "addstrength", // 100   [#]
-    "cstator", // 101
-    "mail", // 102
-    "paper", // 103
-    "tossweapon", // 104
-    "sleeptime", // 105
-    "nullop", // 106
+    "globalsound",      // 92
+    "lotsofglass",      // 93
+    "ifgotweaponce",    // 94
+    "getlastpal",       // 95
+    "pkick",            // 96
+    "mikesnd",          // 97
+    "useractor",        // 98
+    "sizeat",           // 99
+    "addstrength",      // 100   [#]
+    "cstator",          // 101
+    "mail",             // 102
+    "paper",            // 103
+    "tossweapon",       // 104
+    "sleeptime",        // 105
+    "nullop",           // 106
     "definevolumename", // 107
-    "defineskillname", // 108
-    "ifnosounds", // 109
-    "clipdist", // 110
-    "ifangdiffl" // 111
+    "defineskillname",  // 108
+    "ifnosounds",       // 109
+    "clipdist",         // 110
+    "ifangdiffl"        // 111
 };
 
 
@@ -442,11 +442,40 @@
     textptr += l;
 }
 
+/**
+ * Encode a scriptptr into a form suitable for portably
+ * inserting into bytecode. We store the pointer as minus
+ * the offset from the start of the script buffer, just
+ * to make it perhaps a little more obvious what is happening.
+ */
+int32_t encodescriptptr(int32_t* scptr)
+{
+    int32_t offs = (int32_t)(scptr - script);
 
-uint8_t  parsecommand(int readfromGRP)
+	assert(offs >= 0);
+    assert(offs < MAXSCRIPTSIZE);
+
+	return -offs;
+}
+
+/**
+ * Decode an encoded representation of a scriptptr
+ */
+int32_t* decodescriptptr(int32_t scptr)
 {
-    int32_t i, j, k;
-    intptr_t *tempscrptr;
+    assert(scptr <= 0);
+
+	int32_t offs = -scptr;
+
+	assert(offs >= 0);
+    assert(offs < MAXSCRIPTSIZE);
+
+	return script + offs;
+}
+
+uint8_t parsecommand(int readfromGRP)
+{
+    int32_t i, j, k, *tempscrptr;
     uint8_t  done, temp_ifelse_check;
     int32_t tw;
     char *origtptr;
@@ -484,7 +513,7 @@
             {
                 getlabel();
                 scriptptr--;
-                labelcode[labelcnt] = (intptr_t) scriptptr;
+                labelcode[labelcnt] = encodescriptptr(scriptptr);
                 labelcnt++;
 
                 parsing_state = 1;
@@ -629,7 +658,7 @@
                         break;
                     }
                 if(i == labelcnt)
-                    labelcode[labelcnt++] = (intptr_t) scriptptr;
+                    labelcode[labelcnt++] = encodescriptptr(scriptptr);
                 for(j=0;j<2;j++)
                 {
                     if(keyword() >= 0) break;
@@ -787,7 +816,7 @@
                     }
 
                 if(i == labelcnt)
-                    labelcode[labelcnt++] = (intptr_t) scriptptr;
+                    labelcode[labelcnt++] = encodescriptptr(scriptptr);
 
                 for(j=0;j<3;j++)
                 {
@@ -841,7 +870,7 @@
                     }
 
                 if(i == labelcnt)
-                    labelcode[labelcnt++] = (intptr_t) scriptptr;
+                    labelcode[labelcnt++] = encodescriptptr(scriptptr);
 
                 for(j=0;j<5;j++)
                 {
@@ -1018,7 +1047,7 @@
                 tempscrptr = scriptptr;
                 scriptptr++; //Leave a spot for the fail location
                 parsecommand(readfromGRP);
-                *tempscrptr = (intptr_t) scriptptr;
+                *tempscrptr = encodescriptptr(scriptptr);
             }
             else
             {
@@ -1099,7 +1128,7 @@
 
             parsecommand(readfromGRP);
 
-            *tempscrptr = (intptr_t) scriptptr;
+            *tempscrptr = encodescriptptr(scriptptr);
 
             checking_ifelse++;
             return 0;
@@ -1586,7 +1615,7 @@
     total_lines = 0;
 
     passone(readfromGRP); //Tokenize
-    *script = (intptr_t) scriptptr;
+    *script = encodescriptptr(scriptptr);
 
     if(warning|error)
         printf("Found %hhd warning(s), '%c' error(s).\n",warning,error);
@@ -1765,10 +1794,9 @@
 void alterang(short a)
 {
     short aang, angdif, goalang,j;
-    int32_t ticselapsed;
-    intptr_t* moveptr;
+    int32_t ticselapsed, *moveptr;
 
-    moveptr = (intptr_t*)g_t[1];
+    moveptr = decodescriptptr(g_t[1]);
     ticselapsed = (g_t[0])&31;
     aang = g_sp->ang;
 
@@ -1831,8 +1859,7 @@
 
 void move()
 {
-    int32_t l;
-	intptr_t *moveptr;
+    int32_t l, *moveptr;
     short a, goalang, angdif;
     int32_t daxvel;
 
@@ -1899,7 +1926,7 @@
         return;
     }
 
-    moveptr = (intptr_t*)g_t[1];
+    moveptr = decodescriptptr(g_t[1]);
 
     if(a&geth) g_sp->xvel += (*moveptr-g_sp->xvel)>>1;
     if(a&getv) g_sp->zvel += ((*(moveptr+1)<<4)-g_sp->zvel)>>1;
@@ -2027,8 +2054,6 @@
    }
 }
 
-uint8_t  parse(void);
-
 void parseifelse(int32_t condition)
 {
     if( condition )
@@ -2038,7 +2063,7 @@
     }
     else
     {
-        insptr = (intptr_t *) *(insptr+1);
+        insptr = decodescriptptr(*(insptr+1));
         if(*insptr == 10)
         {
             insptr+=2;
@@ -2188,9 +2213,9 @@
         case 24:
             insptr++;
             g_t[5] = *insptr;
-            g_t[4] = *(intptr_t*)(g_t[5]);       // Action
-            g_t[1] = *(intptr_t*)(g_t[5]+sizeof(intptr_t));       // move
-            g_sp->hitag = *(intptr_t*)(g_t[5]+sizeof(intptr_t)*2);    // Ai
+            g_t[4] = *(decodescriptptr(g_t[5]));       // Action
+            g_t[1] = *(decodescriptptr(g_t[5]) + 1);   // move
+            g_sp->hitag = *(decodescriptptr(g_t[5]) + 2);    // Ai
             g_t[0] = g_t[2] = g_t[3] = 0;
             if(g_sp->hitag&random_angle)
                 g_sp->ang = TRAND&2047;
@@ -2225,7 +2250,7 @@
                 hittype[g_i].timetosleep = SLEEPTIME;
             break;
         case 10:
-            insptr = (intptr_t*) *(insptr+1);
+            insptr = decodescriptptr(*(insptr + 1));
             break;
         case 100:
             insptr++;
@@ -2576,11 +2601,11 @@
             break;
         case 17:
             {
-				intptr_t *tempscrptr;
-
+				int32_t *tempscrptr;
+        		
                 tempscrptr = insptr+2;
 
-                insptr = (intptr_t *) *(insptr+1);
+                insptr = decodescriptptr(*(insptr + 1));
                 while(1) if(parse()) break;
                 insptr = tempscrptr;
             }
@@ -3154,13 +3179,13 @@
     if(g_t[4])
     {
         g_sp->lotag += TICSPERFRAME;
-        if(g_sp->lotag > *(intptr_t*)(g_t[4]+(sizeof(intptr_t) * 4)))
+        if (g_sp->lotag > * (decodescriptptr(g_t[4]) + 4))
         {
             g_t[2]++;
             g_sp->lotag = 0;
-            g_t[3] += *(intptr_t*)(g_t[4] + (sizeof(intptr_t) * 3));
+            g_t[3] += *(decodescriptptr(g_t[4]) + 3);
         }
-        if( klabs(g_t[3]) >= klabs( *(intptr_t*)(g_t[4]+sizeof(intptr_t)) * *(intptr_t*)(g_t[4]+ (sizeof(intptr_t) * 3)) ))
+        if( klabs(g_t[3]) >= klabs( *(decodescriptptr(g_t[4])+1) * *(decodescriptptr(g_t[4])+3) ) )
             g_t[3] = 0;
     }
 
--- a/Game/src/global.c
+++ b/Game/src/global.c
@@ -28,6 +28,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
+#include <time.h>
 #include <errno.h>
 #include "global.h"
 #include "duke3d.h"
@@ -148,8 +149,8 @@
 uint8_t  playerquitflag[MAXPLAYERS];
 int32_t vel, svel, angvel, horiz, ototalclock, respawnactortime=768, respawnitemtime=768, groupfile;
 
-intptr_t script[MAXSCRIPTSIZE],*scriptptr,*insptr,*labelcode,labelcnt;
-intptr_t *actorscrptr[MAXTILES],*parsing_actor;
+int32_t script[MAXSCRIPTSIZE],*scriptptr,*insptr,*labelcode,labelcnt;
+int32_t*actorscrptr[MAXTILES],*parsing_actor;
 char  *label,*textptr,error,warning ;
 uint8_t killit_flag;
 uint8_t  *music_pointer;
--- a/Game/src/menues.c
+++ b/Game/src/menues.c
@@ -224,9 +224,13 @@
     char  mpfn[] = "gameA_00.sav";
     char* fnptr, scriptptrs[MAXSCRIPTSIZE];
     int32_t fil, bv, i, x;
-    intptr_t j;
     int32 nump;
+    int32 ptrbuf[MAXTILES];
 
+    assert(MAXTILES > MAXANIMATES);
+
+    int off = offsetof(struct player_struct, fakeplayer);
+
     if (spot < 0)
     {
         multiflag = 1;
@@ -363,34 +367,15 @@
     kdfread(&cloudx[0], sizeof(short) << 7, 1, fil);
     kdfread(&cloudy[0], sizeof(short) << 7, 1, fil);
 
-    kdfread(&scriptptrs[0], 1, MAXSCRIPTSIZE, fil);
     kdfread(&script[0], 4, MAXSCRIPTSIZE, fil);
-    for (i = 0; i < MAXSCRIPTSIZE; i++)
-        if (scriptptrs[i])
-        {
-            j = (intptr_t)script[i] + (intptr_t)&script[0];
-            script[i] = j;
-        }
-
-    kdfread(&actorscrptr[0], 4, MAXTILES, fil);
+    kdfread(&ptrbuf[0], 4, MAXTILES, fil);
     for (i = 0; i < MAXTILES; i++)
-        if (actorscrptr[i])
+        if (ptrbuf[i])
         {
-            j = (intptr_t)actorscrptr[i] + (intptr_t)&script[0];
-            actorscrptr[i] = (intptr_t*)j;
+            actorscrptr[i] = (int32_t*)((intptr_t)&script[0] + ptrbuf[i]);
         }
 
-    kdfread(&scriptptrs[0], 1, MAXSPRITES, fil);
     kdfread(&hittype[0], sizeof(struct weaponhit), MAXSPRITES, fil);
-
-    for (i = 0; i < MAXSPRITES; i++)
-    {
-        j = (intptr_t)(&script[0]);
-        if (scriptptrs[i] & 1) T2 += j;
-        if (scriptptrs[i] & 2) T5 += j;
-        if (scriptptrs[i] & 4) T6 += j;
-    }
-
     kdfread(&lockclock, sizeof(lockclock), 1, fil);
     kdfread(&pskybits, sizeof(pskybits), 1, fil);
     kdfread(&pskyoff[0], sizeof(pskyoff[0]), MAXPSKYTILES, fil);
@@ -397,8 +382,11 @@
 
     kdfread(&animatecnt, sizeof(animatecnt), 1, fil);
     kdfread(&animatesect[0], 2, MAXANIMATES, fil);
-    kdfread(&animateptr[0], 4, MAXANIMATES, fil);
-    for (i = animatecnt - 1; i >= 0; i--) animateptr[i] = (int32_t*)((intptr_t)animateptr[i] + (intptr_t)(&sector[0]));
+	kdfread(&ptrbuf[0], 4, MAXANIMATES, fil);
+    for (i = animatecnt - 1; i >= 0; i--)
+    {
+        animateptr[i] = (int32_t*)((intptr_t)&sector[0] + ptrbuf[i]);
+    }
     kdfread(&animategoal[0], 4, MAXANIMATES, fil);
     kdfread(&animatevel[0], 4, MAXANIMATES, fil);
 
@@ -560,7 +548,10 @@
     FILE* fil;
     int32_t bv = BYTEVERSION;
     char  fullpathsavefilename[16];
+    int ptrbuf[MAXTILES];
 
+    assert(MAXTILES > MAXANIMATES);
+
     if (spot < 0)
     {
         multiflag = 1;
@@ -649,90 +640,29 @@
     dfwrite(&cloudx[0], sizeof(short) << 7, 1, fil);
     dfwrite(&cloudy[0], sizeof(short) << 7, 1, fil);
 
-    for (i = 0; i < MAXSCRIPTSIZE; i++)
-    {
-        if (script[i] >= (intptr_t)(&script[0]) && script[i] < (intptr_t)(&script[MAXSCRIPTSIZE]))
-        {
-            scriptptrs[i] = 1;
-            j = script[i] - (intptr_t)&script[0];
-            script[i] = j;
-        }
-        else scriptptrs[i] = 0;
-    }
-
-    dfwrite(&scriptptrs[0], 1, MAXSCRIPTSIZE, fil);
     dfwrite(&script[0], 4, MAXSCRIPTSIZE, fil);
 
-    for (i = 0; i < MAXSCRIPTSIZE; i++)
-        if (scriptptrs[i])
-        {
-            j = script[i] + (intptr_t)&script[0];
-            script[i] = j;
-        }
-
+	memset(ptrbuf, 0, sizeof(ptrbuf));
     for (i = 0; i < MAXTILES; i++)
         if (actorscrptr[i])
         {
-            j = (intptr_t)actorscrptr[i] - (intptr_t)&script[0];
-            actorscrptr[i] = (intptr_t*)j;
+            ptrbuf[i] = (int32_t)((intptr_t)actorscrptr[i] - (intptr_t)&script[0]);
         }
-    dfwrite(&actorscrptr[0], 4, MAXTILES, fil);
-    for (i = 0; i < MAXTILES; i++)
-        if (actorscrptr[i])
-        {
-            j = (intptr_t)actorscrptr[i] + (intptr_t)&script[0];
-            actorscrptr[i] = (intptr_t*)j;
-        }
+    dfwrite(&ptrbuf[0], 4, MAXTILES, fil);
 
-    for (i = 0; i < MAXSPRITES; i++)
-    {
-        scriptptrs[i] = 0;
-
-        if (actorscrptr[PN] == 0) continue;
-
-        j = (intptr_t)&script[0];
-
-        if (T2 >= j && T2 < (intptr_t)(&script[MAXSCRIPTSIZE]))
-        {
-            scriptptrs[i] |= 1;
-            T2 -= j;
-        }
-        if (T5 >= j && T5 < (intptr_t)(&script[MAXSCRIPTSIZE]))
-        {
-            scriptptrs[i] |= 2;
-            T5 -= j;
-        }
-        if (T6 >= j && T6 < (intptr_t)(&script[MAXSCRIPTSIZE]))
-        {
-            scriptptrs[i] |= 4;
-            T6 -= j;
-        }
-    }
-
-    dfwrite(&scriptptrs[0], 1, MAXSPRITES, fil);
-    dfwrite(&hittype[0], sizeof(struct weaponhit), MAXSPRITES, fil);
-
-    for (i = 0; i < MAXSPRITES; i++)
-    {
-        if (actorscrptr[PN] == 0) continue;
-        j = (intptr_t)&script[0];
-
-        if (scriptptrs[i] & 1)
-            T2 += j;
-        if (scriptptrs[i] & 2)
-            T5 += j;
-        if (scriptptrs[i] & 4)
-            T6 += j;
-    }
-
+	dfwrite(&hittype[0], sizeof(struct weaponhit), MAXSPRITES, fil);
     dfwrite(&lockclock, sizeof(lockclock), 1, fil);
     dfwrite(&pskybits, sizeof(pskybits), 1, fil);
     dfwrite(&pskyoff[0], sizeof(pskyoff[0]), MAXPSKYTILES, fil);
     dfwrite(&animatecnt, sizeof(animatecnt), 1, fil);
     dfwrite(&animatesect[0], 2, MAXANIMATES, fil);
-    for (i = animatecnt - 1; i >= 0; i--) animateptr[i] = (int32_t*)((intptr_t)animateptr[i] - (intptr_t)(&sector[0]));
-    dfwrite(&animateptr[0], 4, MAXANIMATES, fil);
-    for (i = animatecnt - 1; i >= 0; i--) animateptr[i] = (int32_t*)((intptr_t)animateptr[i] + (intptr_t)(&sector[0]));
+	
+    for (i = animatecnt - 1; i >= 0; i--) {
+        ptrbuf[i] = (int32_t)((intptr_t)animateptr[i] - (intptr_t)&sector[0]);
+    }
+	
+    dfwrite(&ptrbuf[0], 4, MAXANIMATES, fil);
+	
     dfwrite(&animategoal[0], 4, MAXANIMATES, fil);
     dfwrite(&animatevel[0], 4, MAXANIMATES, fil);
 
--- a/Game/src/rts.c
+++ b/Game/src/rts.c
@@ -26,6 +26,7 @@
 
 #include "duke3d.h"
 #include "global.h"
+#include <malloc.h>
 
 //=============
 // STATICS
--- a/README.md
+++ b/README.md
@@ -17,14 +17,14 @@
 * Ported to SDL2.
 * Ported to vcpkg and CMake.
 * Added continuous integration (via GitHub Actions).
-* Added 64-bit support.
+* Added 64-bit support (savegames are compatible between 32-bit and 64-bit).
 
 ### Known Issues
 
-* Save games are not compatible between 32-bit and 64-bit (due to serialization of `intptr_t` values).
 * Linux: MIDI does not play (vcpkg does not configure sdl2-mixer for it).
 * Engine: Leaning left/right falls back to low-res rendering.
-* Engine: minimap has rendering glitches when fully-textured.
+* Engine: Minimap has rendering glitches when fully-textured.
+* Engine: Pixel imprecision when rendering health/ammo numbers in the status bar, leaving ghost pixels.
 
 ## Requirements
 
@@ -53,6 +53,7 @@
 * **Project Initiator:** [Fabien Sanglard](https://github.com/fabiensanglard)
 * **Linux Integration:** [Juan Manuel Borges Caño](https://github.com/juanmabc)
 * **64-bit Port:** [Rohit Nirmal](https://github.com/rohit-n)
+* **64-bit Port:** [Jonathon Fowler] (https://github.com/jonof/jfduke3d)
 * **Belgian Chocolate fork:** [Tanguy Fautre](https://github.com/GPSnoopy/)
 
 ## More Information