diff --git a/src/command.c b/src/command.c
index e0156274ea12353809653fd64e50a9205ee32d29..25eb83d1949b612c723ecc70ca8436277efe2b14 100644
--- a/src/command.c
+++ b/src/command.c
@@ -1722,8 +1722,7 @@ badinput:
 
 static boolean serverloading = false;
 
-static consvar_t *
-ReadNetVar (UINT8 **p, char **return_value, boolean *return_stealth)
+static consvar_t *ReadNetVar(save_t *p, char **return_value, boolean *return_stealth)
 {
 	UINT16  netid;
 	char   *val;
@@ -1731,10 +1730,10 @@ ReadNetVar (UINT8 **p, char **return_value, boolean *return_stealth)
 
 	consvar_t *cvar;
 
-	netid   = READUINT16 (*p);
-	val     = (char *)*p;
-	SKIPSTRING (*p);
-	stealth = READUINT8  (*p);
+	netid   = P_ReadUINT16(p);
+	val     = (char *)&p->buf[p->pos];
+	P_SkipString(p);
+	stealth = P_ReadUINT8(p);
 
 	cvar = CV_FindNetVar(netid);
 
@@ -1752,8 +1751,7 @@ ReadNetVar (UINT8 **p, char **return_value, boolean *return_stealth)
 }
 
 #ifdef OLD22DEMOCOMPAT
-static consvar_t *
-ReadOldDemoVar (UINT8 **p, char **return_value, boolean *return_stealth)
+static consvar_t *ReadOldDemoVar(save_t *p, char **return_value, boolean *return_stealth)
 {
 	UINT16  id;
 	char   *val;
@@ -1761,10 +1759,10 @@ ReadOldDemoVar (UINT8 **p, char **return_value, boolean *return_stealth)
 
 	old_demo_var_t *demovar;
 
-	id      = READUINT16 (*p);
-	val     = (char *)*p;
-	SKIPSTRING (*p);
-	stealth = READUINT8  (*p);
+	id      = P_ReadUINT16(p);
+	val     = (char *)&p->buf[p->pos];
+	P_SkipString(p);
+	stealth = P_ReadUINT8(p);
 
 	demovar = CV_FindOldDemoVar(id);
 
@@ -1783,8 +1781,7 @@ ReadOldDemoVar (UINT8 **p, char **return_value, boolean *return_stealth)
 }
 #endif/*OLD22DEMOCOMPAT*/
 
-static consvar_t *
-ReadDemoVar (UINT8 **p, char **return_value, boolean *return_stealth)
+static consvar_t *ReadDemoVar(save_t *p, char **return_value, boolean *return_stealth)
 {
 	char   *name;
 	char   *val;
@@ -1792,11 +1789,11 @@ ReadDemoVar (UINT8 **p, char **return_value, boolean *return_stealth)
 
 	consvar_t *cvar;
 
-	name    = (char *)*p;
-	SKIPSTRING (*p);
-	val     = (char *)*p;
-	SKIPSTRING (*p);
-	stealth = READUINT8  (*p);
+	name    = (char *)&p->buf[p->pos];
+	P_SkipString(p);
+	val     = (char *)&p->buf[p->pos];
+	P_SkipString(p);
+	stealth = P_ReadUINT8(p);
 
 	cvar = CV_FindVar(name);
 
@@ -1826,41 +1823,46 @@ static void Got_NetVar(UINT8 **p, INT32 playernum)
 		return;
 	}
 
-	cvar = ReadNetVar(p, &svalue, &stealth);
+	save_t save_p;
+	save_p.buf = *p;
+	save_p.size = MAXTEXTCMD;
+	save_p.pos = 0;
+	cvar = ReadNetVar(&save_p, &svalue, &stealth);
+	*p = &save_p.buf[save_p.pos];
 
 	if (cvar)
 		Setvalue(cvar, svalue, stealth);
 }
 
-void CV_SaveVars(UINT8 **p, boolean in_demo)
+void CV_SaveVars(save_t *p, boolean in_demo)
 {
 	consvar_t *cvar;
-	UINT8 *count_p = *p;
+	UINT8 *count_p = &p->buf[p->pos];
 	UINT16 count = 0;
 
 	// send only changed cvars ...
 	// the client will reset all netvars to default before loading
-	WRITEUINT16(*p, 0x0000);
+	P_WriteUINT16(p, 0x0000);
 	for (cvar = consvar_vars; cvar; cvar = cvar->next)
 		if ((cvar->flags & CV_NETVAR) && !CV_IsSetToDefault(cvar))
 		{
 			if (in_demo)
 			{
-				WRITESTRING(*p, cvar->name);
+				P_WriteString(p, cvar->name);
 			}
 			else
 			{
-				WRITEUINT16(*p, cvar->netid);
+				P_WriteUINT16(p, cvar->netid);
 			}
-			WRITESTRING(*p, cvar->string);
-			WRITEUINT8(*p, false);
+			P_WriteString(p, cvar->string);
+			P_WriteUINT8(p, false);
 			++count;
 		}
 	WRITEUINT16(count_p, count);
 }
 
-static void CV_LoadVars(UINT8 **p,
-		consvar_t *(*got)(UINT8 **p, char **ret_value, boolean *ret_stealth))
+static void CV_LoadVars(save_t *p,
+		consvar_t *(*got)(save_t *p, char **ret_value, boolean *ret_stealth))
 {
 	const boolean store = (client || demoplayback);
 
@@ -1888,7 +1890,7 @@ static void CV_LoadVars(UINT8 **p,
 		}
 	}
 
-	count = READUINT16(*p);
+	count = P_ReadUINT16(p);
 	while (count--)
 	{
 		cvar = (*got)(p, &val, &stealth);
@@ -1921,19 +1923,19 @@ void CV_RevertNetVars(void)
 	}
 }
 
-void CV_LoadNetVars(UINT8 **p)
+void CV_LoadNetVars(save_t *p)
 {
 	CV_LoadVars(p, ReadNetVar);
 }
 
 #ifdef OLD22DEMOCOMPAT
-void CV_LoadOldDemoVars(UINT8 **p)
+void CV_LoadOldDemoVars(save_t *p)
 {
 	CV_LoadVars(p, ReadOldDemoVar);
 }
 #endif
 
-void CV_LoadDemoVars(UINT8 **p)
+void CV_LoadDemoVars(save_t *p)
 {
 	CV_LoadVars(p, ReadDemoVar);
 }
diff --git a/src/command.h b/src/command.h
index f0dc62418a8815abfa9e7c9b84d9357aac406b73..368c2fb3f3a86206bdcf243970762a6a3f695666 100644
--- a/src/command.h
+++ b/src/command.h
@@ -15,6 +15,7 @@
 
 #include <stdio.h>
 #include "doomdef.h"
+#include "p_saveg.h"
 
 //===================================
 // Command buffer & command execution
@@ -218,19 +219,19 @@ void CV_AddValue(consvar_t *var, INT32 increment);
 void CV_SaveVariables(FILE *f);
 
 // load/save gamesate (load and save option and for network join in game)
-void CV_SaveVars(UINT8 **p, boolean in_demo);
+void CV_SaveVars(save_t *p, boolean in_demo);
 
 #define CV_SaveNetVars(p) CV_SaveVars(p, false)
-void CV_LoadNetVars(UINT8 **p);
+void CV_LoadNetVars(save_t *p);
 
 // then revert after leaving a netgame
 void CV_RevertNetVars(void);
 
 #define CV_SaveDemoVars(p) CV_SaveVars(p, true)
-void CV_LoadDemoVars(UINT8 **p);
+void CV_LoadDemoVars(save_t *p);
 
 #ifdef OLD22DEMOCOMPAT
-void CV_LoadOldDemoVars(UINT8 **p);
+void CV_LoadOldDemoVars(save_t *p);
 #endif
 
 // reset cheat netvars after cheats is deactivated
diff --git a/src/g_demo.c b/src/g_demo.c
index cfa34fc7e76c7978a52603fdd05f3e55d19f3e17..77f8f7b0dabdd7b85cd33834c2859d685aac6e1e 100644
--- a/src/g_demo.c
+++ b/src/g_demo.c
@@ -1454,6 +1454,7 @@ void G_BeginRecording(void)
 	char *filename;
 	UINT16 totalfiles;
 	UINT8 *m;
+	save_t savebuffer;
 
 	if (demo_p)
 		return;
@@ -1603,7 +1604,11 @@ void G_BeginRecording(void)
 	}
 
 	// Save netvar data
-	CV_SaveDemoVars(&demo_p);
+	savebuffer.buf = demo_p;
+	savebuffer.size = demoend - demo_p;
+	savebuffer.pos = 0;
+	CV_SaveDemoVars(&savebuffer);
+	demo_p = &savebuffer.buf[savebuffer.pos];
 
 	memset(&oldcmd,0,sizeof(oldcmd));
 	memset(&oldghost,0,sizeof(oldghost));
@@ -2236,10 +2241,24 @@ void G_DoPlayDemo(char *defdemoname)
 	// net var data
 #ifdef OLD22DEMOCOMPAT
 	if (demoversion < 0x000d)
-		CV_LoadOldDemoVars(&demo_p);
+	{
+		save_t savebuffer;
+		savebuffer.buf = demo_p;
+		savebuffer.size = demoend - demo_p;
+		savebuffer.pos = 0;
+		CV_LoadOldDemoVars(&savebuffer);
+		demo_p = &savebuffer.buf[savebuffer.pos];
+	}
 	else
 #endif
-		CV_LoadDemoVars(&demo_p);
+	{
+		save_t savebuffer;
+		savebuffer.buf = demo_p;
+		savebuffer.size = demoend - demo_p;
+		savebuffer.pos = 0;
+		CV_LoadDemoVars(&savebuffer);
+		demo_p = &savebuffer.buf[savebuffer.pos];
+	}
 
 	// Sigh ... it's an empty demo.
 	if (*demo_p == DEMOMARKER)
diff --git a/src/g_game.c b/src/g_game.c
index 7d5c396dc21e0661832b9e1ba7d0642607866466..aaaf558f451e477d2acc5056ba15a8345b07a174 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -256,8 +256,6 @@ boolean precache = true; // if true, load all graphics at start
 
 INT16 prevmap, nextmap;
 
-static UINT8 *savebuffer;
-
 // Analog Control
 static void UserAnalog_OnChange(void);
 static void UserAnalog2_OnChange(void);
@@ -4399,7 +4397,7 @@ void G_LoadGameSettings(void)
 // Loads the main data file, which stores information such as emblems found, etc.
 void G_LoadGameData(gamedata_t *data)
 {
-	size_t length;
+	save_t savebuffer;
 	INT32 i, j;
 
 	UINT32 versionID;
@@ -4441,18 +4439,18 @@ void G_LoadGameData(gamedata_t *data)
 		return;
 	}
 
-	length = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &savebuffer);
-	if (!length)
+	savebuffer.size = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &savebuffer.buf);
+	if (!savebuffer.size)
 	{
 		// No gamedata. We can save a new one.
 		data->loaded = true;
 		return;
 	}
 
-	save_p = savebuffer;
+	savebuffer.pos = 0;
 
 	// Version check
-	versionID = READUINT32(save_p);
+	versionID = P_ReadUINT32(&savebuffer);
 	if (versionID != GAMEDATA_ID
 #ifdef COMPAT_GAMEDATA_ID // backwards compat behavior
 		&& versionID != COMPAT_GAMEDATA_ID
@@ -4463,8 +4461,7 @@ void G_LoadGameData(gamedata_t *data)
 		if (strcmp(srb2home,"."))
 			gdfolder = srb2home;
 
-		Z_Free(savebuffer);
-		save_p = NULL;
+		Z_Free(savebuffer.buf);
 		I_Error("Game data is from another version of SRB2.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder);
 	}
 
@@ -4476,14 +4473,14 @@ void G_LoadGameData(gamedata_t *data)
 	}
 #endif
 
-	data->totalplaytime = READUINT32(save_p);
+	data->totalplaytime = P_ReadUINT32(&savebuffer);
 
 #ifdef COMPAT_GAMEDATA_ID
 	if (versionID == COMPAT_GAMEDATA_ID)
 	{
 		// We'll temporarily use the old condition when loading an older file.
 		// The proper mod-specific hash will get saved in afterwards.
-		boolean modded = READUINT8(save_p);
+		boolean modded = P_ReadUINT8(&savebuffer);
 
 		if (modded && !savemoddata)
 		{
@@ -4503,13 +4500,13 @@ void G_LoadGameData(gamedata_t *data)
 		strcpy(currentfilename, gamedatafilename);
 		STRBUFCPY(backupfilename, strcat(currentfilename, bak));
 
-		FIL_WriteFile(va(pandf, srb2home, backupfilename), savebuffer, length);
+		FIL_WriteFile(va(pandf, srb2home, backupfilename), &savebuffer.buf, savebuffer.size);
 	}
 	else
 #endif
 	{
 		// Quick & dirty hash for what mod this save file is for.
-		UINT32 modID = READUINT32(save_p);
+		UINT32 modID = P_ReadUINT32(&savebuffer);
 		UINT32 expectedID = quickncasehash(timeattackfolder, sizeof timeattackfolder);
 
 		if (modID != expectedID)
@@ -4521,50 +4518,50 @@ void G_LoadGameData(gamedata_t *data)
 
 	// TODO put another cipher on these things? meh, I don't care...
 	for (i = 0; i < NUMMAPS; i++)
-		if ((data->mapvisited[i] = READUINT8(save_p)) > MV_MAX)
+		if ((data->mapvisited[i] = P_ReadUINT8(&savebuffer)) > MV_MAX)
 			goto datacorrupt;
 
 	// To save space, use one bit per collected/achieved/unlocked flag
 	for (i = 0; i < max_emblems;)
 	{
-		rtemp = READUINT8(save_p);
+		rtemp = P_ReadUINT8(&savebuffer);
 		for (j = 0; j < 8 && j+i < max_emblems; ++j)
 			data->collected[j+i] = ((rtemp >> j) & 1);
 		i += j;
 	}
 	for (i = 0; i < max_extraemblems;)
 	{
-		rtemp = READUINT8(save_p);
+		rtemp = P_ReadUINT8(&savebuffer);
 		for (j = 0; j < 8 && j+i < max_extraemblems; ++j)
 			data->extraCollected[j+i] = ((rtemp >> j) & 1);
 		i += j;
 	}
 	for (i = 0; i < max_unlockables;)
 	{
-		rtemp = READUINT8(save_p);
+		rtemp = P_ReadUINT8(&savebuffer);
 		for (j = 0; j < 8 && j+i < max_unlockables; ++j)
 			data->unlocked[j+i] = ((rtemp >> j) & 1);
 		i += j;
 	}
 	for (i = 0; i < max_conditionsets;)
 	{
-		rtemp = READUINT8(save_p);
+		rtemp = P_ReadUINT8(&savebuffer);
 		for (j = 0; j < 8 && j+i < max_conditionsets; ++j)
 			data->achieved[j+i] = ((rtemp >> j) & 1);
 		i += j;
 	}
 
-	data->timesBeaten = READUINT32(save_p);
-	data->timesBeatenWithEmeralds = READUINT32(save_p);
-	data->timesBeatenUltimate = READUINT32(save_p);
+	data->timesBeaten = P_ReadUINT32(&savebuffer);
+	data->timesBeatenWithEmeralds = P_ReadUINT32(&savebuffer);
+	data->timesBeatenUltimate = P_ReadUINT32(&savebuffer);
 
 	// Main records
 	for (i = 0; i < NUMMAPS; ++i)
 	{
-		recscore = READUINT32(save_p);
-		rectime  = (tic_t)READUINT32(save_p);
-		recrings = READUINT16(save_p);
-		save_p++; // compat
+		recscore = P_ReadUINT32(&savebuffer);
+		rectime  = (tic_t)P_ReadUINT32(&savebuffer);
+		recrings = P_ReadUINT16(&savebuffer);
+		P_ReadUINT8(&savebuffer); // compat
 
 		if (recrings > 10000 || recscore > MAXSCORE)
 			goto datacorrupt;
@@ -4581,16 +4578,16 @@ void G_LoadGameData(gamedata_t *data)
 	// Nights records
 	for (i = 0; i < NUMMAPS; ++i)
 	{
-		if ((recmares = READUINT8(save_p)) == 0)
+		if ((recmares = P_ReadUINT8(&savebuffer)) == 0)
 			continue;
 
 		G_AllocNightsRecordData((INT16)i, data);
 
 		for (curmare = 0; curmare < (recmares+1); ++curmare)
 		{
-			data->nightsrecords[i]->score[curmare] = READUINT32(save_p);
-			data->nightsrecords[i]->grade[curmare] = READUINT8(save_p);
-			data->nightsrecords[i]->time[curmare] = (tic_t)READUINT32(save_p);
+			data->nightsrecords[i]->score[curmare] = P_ReadUINT32(&savebuffer);
+			data->nightsrecords[i]->grade[curmare] = P_ReadUINT8(&savebuffer);
+			data->nightsrecords[i]->time[curmare] = (tic_t)P_ReadUINT32(&savebuffer);
 
 			if (data->nightsrecords[i]->grade[curmare] > GRADE_S)
 			{
@@ -4602,8 +4599,7 @@ void G_LoadGameData(gamedata_t *data)
 	}
 
 	// done
-	Z_Free(savebuffer);
-	save_p = NULL;
+	Z_Free(savebuffer.buf);
 
 	// Don't consider loaded until it's a success!
 	// It used to do this much earlier, but this would cause the gamedata to
@@ -4624,8 +4620,7 @@ void G_LoadGameData(gamedata_t *data)
 		if (strcmp(srb2home,"."))
 			gdfolder = srb2home;
 
-		Z_Free(savebuffer);
-		save_p = NULL;
+		Z_Free(savebuffer.buf);
 
 		I_Error("Corrupt game data file.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder);
 	}
@@ -4635,9 +4630,8 @@ void G_LoadGameData(gamedata_t *data)
 // Saves the main data file, which stores information such as emblems found, etc.
 void G_SaveGameData(gamedata_t *data)
 {
-	UINT8 *data_p;
+	save_t savebuffer;
 
-	size_t length;
 	INT32 i, j;
 	UINT8 btemp;
 
@@ -4649,30 +4643,31 @@ void G_SaveGameData(gamedata_t *data)
 	if (!data->loaded)
 		return; // If never loaded (-nodata), don't save
 
-	data_p = savebuffer = (UINT8 *)malloc(GAMEDATASIZE);
-	if (!data_p)
+	savebuffer.size = GAMEDATASIZE;
+	savebuffer.buf = (UINT8 *)malloc(savebuffer.size);
+	if (!savebuffer.buf)
 	{
 		CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n"));
 		return;
 	}
+	savebuffer.pos = 0;
 
 	if (usedCheats)
 	{
-		free(savebuffer);
-		savebuffer = NULL;
+		free(savebuffer.buf);
 		return;
 	}
 
 	// Version test
-	WRITEUINT32(data_p, GAMEDATA_ID);
+	P_WriteUINT32(&savebuffer, GAMEDATA_ID);
 
-	WRITEUINT32(data_p, data->totalplaytime);
+	P_WriteUINT32(&savebuffer, data->totalplaytime);
 
-	WRITEUINT32(data_p, quickncasehash(timeattackfolder, sizeof timeattackfolder));
+	P_WriteUINT32(&savebuffer, quickncasehash(timeattackfolder, sizeof timeattackfolder));
 
 	// TODO put another cipher on these things? meh, I don't care...
 	for (i = 0; i < NUMMAPS; i++)
-		WRITEUINT8(data_p, (data->mapvisited[i] & MV_MAX));
+		P_WriteUINT8(&savebuffer, (data->mapvisited[i] & MV_MAX));
 
 	// To save space, use one bit per collected/achieved/unlocked flag
 	for (i = 0; i < MAXEMBLEMS;)
@@ -4680,7 +4675,7 @@ void G_SaveGameData(gamedata_t *data)
 		btemp = 0;
 		for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
 			btemp |= (data->collected[j+i] << j);
-		WRITEUINT8(data_p, btemp);
+		P_WriteUINT8(&savebuffer, btemp);
 		i += j;
 	}
 	for (i = 0; i < MAXEXTRAEMBLEMS;)
@@ -4688,7 +4683,7 @@ void G_SaveGameData(gamedata_t *data)
 		btemp = 0;
 		for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
 			btemp |= (data->extraCollected[j+i] << j);
-		WRITEUINT8(data_p, btemp);
+		P_WriteUINT8(&savebuffer, btemp);
 		i += j;
 	}
 	for (i = 0; i < MAXUNLOCKABLES;)
@@ -4696,7 +4691,7 @@ void G_SaveGameData(gamedata_t *data)
 		btemp = 0;
 		for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
 			btemp |= (data->unlocked[j+i] << j);
-		WRITEUINT8(data_p, btemp);
+		P_WriteUINT8(&savebuffer, btemp);
 		i += j;
 	}
 	for (i = 0; i < MAXCONDITIONSETS;)
@@ -4704,30 +4699,30 @@ void G_SaveGameData(gamedata_t *data)
 		btemp = 0;
 		for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
 			btemp |= (data->achieved[j+i] << j);
-		WRITEUINT8(data_p, btemp);
+		P_WriteUINT8(&savebuffer, btemp);
 		i += j;
 	}
 
-	WRITEUINT32(data_p, data->timesBeaten);
-	WRITEUINT32(data_p, data->timesBeatenWithEmeralds);
-	WRITEUINT32(data_p, data->timesBeatenUltimate);
+	P_WriteUINT32(&savebuffer, data->timesBeaten);
+	P_WriteUINT32(&savebuffer, data->timesBeatenWithEmeralds);
+	P_WriteUINT32(&savebuffer, data->timesBeatenUltimate);
 
 	// Main records
 	for (i = 0; i < NUMMAPS; i++)
 	{
 		if (data->mainrecords[i])
 		{
-			WRITEUINT32(data_p, data->mainrecords[i]->score);
-			WRITEUINT32(data_p, data->mainrecords[i]->time);
-			WRITEUINT16(data_p, data->mainrecords[i]->rings);
+			P_WriteUINT32(&savebuffer, data->mainrecords[i]->score);
+			P_WriteUINT32(&savebuffer, data->mainrecords[i]->time);
+			P_WriteUINT16(&savebuffer, data->mainrecords[i]->rings);
 		}
 		else
 		{
-			WRITEUINT32(data_p, 0);
-			WRITEUINT32(data_p, 0);
-			WRITEUINT16(data_p, 0);
+			P_WriteUINT32(&savebuffer, 0);
+			P_WriteUINT32(&savebuffer, 0);
+			P_WriteUINT16(&savebuffer, 0);
 		}
-		WRITEUINT8(data_p, 0); // compat
+		P_WriteUINT8(&savebuffer, 0); // compat
 	}
 
 	// NiGHTS records
@@ -4735,25 +4730,22 @@ void G_SaveGameData(gamedata_t *data)
 	{
 		if (!data->nightsrecords[i] || !data->nightsrecords[i]->nummares)
 		{
-			WRITEUINT8(data_p, 0);
+			P_WriteUINT8(&savebuffer, 0);
 			continue;
 		}
 
-		WRITEUINT8(data_p, data->nightsrecords[i]->nummares);
+		P_WriteUINT8(&savebuffer, data->nightsrecords[i]->nummares);
 
 		for (curmare = 0; curmare < (data->nightsrecords[i]->nummares + 1); ++curmare)
 		{
-			WRITEUINT32(data_p, data->nightsrecords[i]->score[curmare]);
-			WRITEUINT8(data_p, data->nightsrecords[i]->grade[curmare]);
-			WRITEUINT32(data_p, data->nightsrecords[i]->time[curmare]);
+			P_WriteUINT32(&savebuffer, data->nightsrecords[i]->score[curmare]);
+			P_WriteUINT8(&savebuffer, data->nightsrecords[i]->grade[curmare]);
+			P_WriteUINT32(&savebuffer, data->nightsrecords[i]->time[curmare]);
 		}
 	}
 
-	length = data_p - savebuffer;
-
-	FIL_WriteFile(va(pandf, srb2home, gamedatafilename), savebuffer, length);
-	free(savebuffer);
-	savebuffer = NULL;
+	FIL_WriteFile(va(pandf, srb2home, gamedatafilename), savebuffer.buf, savebuffer.pos);
+	free(savebuffer.buf);
 }
 
 #define VERSIONSIZE 16
@@ -4764,7 +4756,7 @@ void G_SaveGameData(gamedata_t *data)
 //
 void G_LoadGame(UINT32 slot, INT16 mapoverride)
 {
-	size_t length;
+	save_t savebuffer;
 	char vcheck[VERSIONSIZE];
 	char savename[255];
 
@@ -4781,18 +4773,18 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
 	else
 		sprintf(savename, savegamename, slot);
 
-	length = FIL_ReadFile(savename, &savebuffer);
-	if (!length)
+	savebuffer.size = FIL_ReadFile(savename, &savebuffer.buf);
+	if (!savebuffer.size)
 	{
 		CONS_Printf(M_GetText("Couldn't read file %s\n"), savename);
 		return;
 	}
 
-	save_p = savebuffer;
+	savebuffer.pos = 0;
 
 	memset(vcheck, 0, sizeof (vcheck));
 	sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION);
-	if (strcmp((const char *)save_p, (const char *)vcheck))
+	if (strcmp((const char *)&savebuffer.buf[savebuffer.pos], (const char *)vcheck))
 	{
 #ifdef SAVEGAME_OTHERVERSIONS
 		M_StartMessage(M_GetText("Save game from different version.\nYou can load this savegame, but\nsaving afterwards will be disabled.\n\nDo you want to continue anyway?\n\n(Press 'Y' to confirm)\n"),
@@ -4802,15 +4794,14 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
 		M_ClearMenus(true); // so ESC backs out to title
 		M_StartMessage(M_GetText("Save game from different version\n\nPress ESC\n"), NULL, MM_NOTHING);
 		Command_ExitGame_f();
-		Z_Free(savebuffer);
-		save_p = savebuffer = NULL;
+		Z_Free(savebuffer.buf);
 
 		// no cheating!
 		memset(&savedata, 0, sizeof(savedata));
 #endif
 		return; // bad version
 	}
-	save_p += VERSIONSIZE;
+	savebuffer.pos += VERSIONSIZE;
 
 //	if (demoplayback) // reset game engine
 //		G_StopDemo();
@@ -4819,13 +4810,12 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
 //	automapactive = false;
 
 	// dearchive all the modifications
-	if (!P_LoadGame(mapoverride))
+	if (!P_LoadGame(&savebuffer, mapoverride))
 	{
 		M_ClearMenus(true); // so ESC backs out to title
 		M_StartMessage(M_GetText("Savegame file corrupted\n\nPress ESC\n"), NULL, MM_NOTHING);
 		Command_ExitGame_f();
-		Z_Free(savebuffer);
-		save_p = savebuffer = NULL;
+		Z_Free(savebuffer.buf);
 
 		// no cheating!
 		memset(&savedata, 0, sizeof(savedata));
@@ -4833,13 +4823,12 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
 	}
 	if (marathonmode)
 	{
-		marathontime = READUINT32(save_p);
-		marathonmode |= READUINT8(save_p);
+		marathontime = P_ReadUINT32(&savebuffer);
+		marathonmode |= P_ReadUINT8(&savebuffer);
 	}
 
 	// done
-	Z_Free(savebuffer);
-	save_p = savebuffer = NULL;
+	Z_Free(savebuffer.buf);
 
 	displayplayer = consoleplayer;
 	multiplayer = splitscreen = false;
@@ -4857,6 +4846,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
 //
 void G_SaveGame(UINT32 slot, INT16 mapnum)
 {
+	save_t savebuffer;
 	boolean saved;
 	char savename[256] = "";
 	const char *backup;
@@ -4870,33 +4860,32 @@ void G_SaveGame(UINT32 slot, INT16 mapnum)
 	gameaction = ga_nothing;
 	{
 		char name[VERSIONSIZE];
-		size_t length;
 
-		save_p = savebuffer = (UINT8 *)malloc(SAVEGAMESIZE);
-		if (!save_p)
+		savebuffer.size = SAVEGAMESIZE;
+		savebuffer.buf = (UINT8 *)malloc(savebuffer.size);
+		if (!savebuffer.buf)
 		{
 			CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n"));
 			return;
 		}
+		savebuffer.pos = 0;
 
 		memset(name, 0, sizeof (name));
 		sprintf(name, (marathonmode ? "back-up %d" : "version %d"), VERSION);
-		WRITEMEM(save_p, name, VERSIONSIZE);
+		P_WriteMem(&savebuffer, name, VERSIONSIZE);
 
-		P_SaveGame(mapnum);
+		P_SaveGame(&savebuffer, mapnum);
 		if (marathonmode)
 		{
 			UINT32 writetime = marathontime;
 			if (!(marathonmode & MA_INGAME))
 				writetime += TICRATE*5; // live event backup penalty because we don't know how long it takes to get to the next map
-			WRITEUINT32(save_p, writetime);
-			WRITEUINT8(save_p, (marathonmode & ~MA_INIT));
+			P_WriteUINT32(&savebuffer, writetime);
+			P_WriteUINT8(&savebuffer, (marathonmode & ~MA_INIT));
 		}
 
-		length = save_p - savebuffer;
-		saved = FIL_WriteFile(backup, savebuffer, length);
-		free(savebuffer);
-		save_p = savebuffer = NULL;
+		saved = FIL_WriteFile(backup, savebuffer.buf, savebuffer.pos);
+		free(savebuffer.buf);
 	}
 
 	gameaction = ga_nothing;
@@ -4908,11 +4897,10 @@ void G_SaveGame(UINT32 slot, INT16 mapnum)
 }
 
 #define BADSAVE goto cleanup;
-#define CHECKPOS if (save_p >= end_p) BADSAVE
 void G_SaveGameOver(UINT32 slot, boolean modifylives)
 {
+	save_t savebuffer;
 	boolean saved = false;
-	size_t length;
 	char vcheck[VERSIONSIZE];
 	char savename[255];
 	const char *backup;
@@ -4923,42 +4911,38 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
 		sprintf(savename, savegamename, slot);
 	backup = va("%s",savename);
 
-	length = FIL_ReadFile(savename, &savebuffer);
-	if (!length)
+	savebuffer.size = FIL_ReadFile(savename, &savebuffer.buf);
+	if (!savebuffer.size)
 	{
 		CONS_Printf(M_GetText("Couldn't read file %s\n"), savename);
 		return;
 	}
 
+	savebuffer.pos = 0;
+
 	{
 		char temp[sizeof(timeattackfolder)];
-		UINT8 *end_p = savebuffer + length;
 		UINT8 *lives_p;
 		SINT8 pllives;
 #ifdef NEWSKINSAVES
 		INT16 backwardsCompat = 0;
 #endif
 
-		save_p = savebuffer;
 		// Version check
 		memset(vcheck, 0, sizeof (vcheck));
 		sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION);
-		if (strcmp((const char *)save_p, (const char *)vcheck)) BADSAVE
-		save_p += VERSIONSIZE;
+		if (strcmp((const char *)&savebuffer.buf[savebuffer.pos], (const char *)vcheck)) BADSAVE
+		savebuffer.pos += VERSIONSIZE;
 
 		// P_UnArchiveMisc()
-		(void)READINT16(save_p);
-		CHECKPOS
-		(void)READUINT16(save_p); // emeralds
-		CHECKPOS
-		READSTRINGN(save_p, temp, sizeof(temp)); // mod it belongs to
+		(void)P_ReadINT16(&savebuffer);
+		(void)P_ReadUINT16(&savebuffer); // emeralds
+		P_ReadStringN(&savebuffer, temp, sizeof(temp)); // mod it belongs to
 		if (strcmp(temp, timeattackfolder)) BADSAVE
 
 		// P_UnArchivePlayer()
-		CHECKPOS
 #ifdef NEWSKINSAVES
-		backwardsCompat = READUINT16(save_p);
-		CHECKPOS
+		backwardsCompat = P_ReadUINT16(&savebuffer);
 
 		if (backwardsCompat == NEWSKINSAVES) // New save, read skin names
 #endif
@@ -4966,47 +4950,37 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
 			char ourSkinName[SKINNAMESIZE+1];
 			char botSkinName[SKINNAMESIZE+1];
 
-			READSTRINGN(save_p, ourSkinName, SKINNAMESIZE);
-			CHECKPOS
+			P_ReadStringN(&savebuffer, ourSkinName, SKINNAMESIZE);
 
-			READSTRINGN(save_p, botSkinName, SKINNAMESIZE);
-			CHECKPOS
+			P_ReadStringN(&savebuffer, botSkinName, SKINNAMESIZE);
 		}
 
-		WRITEUINT8(save_p, numgameovers);
-		CHECKPOS
+		P_WriteUINT8(&savebuffer, numgameovers);
 
-		lives_p = save_p;
-		pllives = READSINT8(save_p); // lives
-		CHECKPOS
+		lives_p = &savebuffer.buf[savebuffer.pos];
+		pllives = P_ReadSINT8(&savebuffer); // lives
 		if (modifylives && pllives < startinglivesbalance[numgameovers])
 		{
-			pllives = startinglivesbalance[numgameovers];
-			WRITESINT8(lives_p, pllives);
+			*lives_p = startinglivesbalance[numgameovers];
 		}
 
-		(void)READINT32(save_p); // Score
-		CHECKPOS
-		(void)READINT32(save_p); // continues
+		(void)P_ReadINT32(&savebuffer); // Score
+		(void)P_ReadINT32(&savebuffer); // continues
 
 		// File end marker check
-		CHECKPOS
-		switch (READUINT8(save_p))
+		switch (P_ReadUINT8(&savebuffer))
 		{
 			case 0xb7:
 				{
 					UINT8 i, banksinuse;
-					CHECKPOS
-					banksinuse = READUINT8(save_p);
-					CHECKPOS
+					banksinuse = P_ReadUINT8(&savebuffer);
 					if (banksinuse > NUM_LUABANKS)
 						BADSAVE
 					for (i = 0; i < banksinuse; i++)
 					{
-						(void)READINT32(save_p);
-						CHECKPOS
+						(void)P_ReadINT32(&savebuffer);
 					}
-					if (READUINT8(save_p) != 0x1d)
+					if (P_ReadUINT8(&savebuffer) != 0x1d)
 						BADSAVE
 				}
 			case 0x1d:
@@ -5016,7 +4990,7 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
 		}
 
 		// done
-		saved = FIL_WriteFile(backup, savebuffer, length);
+		saved = FIL_WriteFile(backup, savebuffer.buf, savebuffer.size);
 	}
 
 cleanup:
@@ -5024,11 +4998,9 @@ cleanup:
 		CONS_Printf(M_GetText("Game saved.\n"));
 	else if (!saved)
 		CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, (marathonmode ? liveeventbackup : savegamename));
-	Z_Free(savebuffer);
-	save_p = savebuffer = NULL;
+	Z_Free(savebuffer.buf);
 
 }
-#undef CHECKPOS
 #undef BADSAVE
 
 //
diff --git a/src/lua_script.c b/src/lua_script.c
index 057899555480383611652c552e41bf41398b0e2b..51808977f70c4ac7b8b3b73ae3be1d0eded9fdcc 100644
--- a/src/lua_script.c
+++ b/src/lua_script.c
@@ -1098,7 +1098,7 @@ static UINT8 GetUserdataArchType(int index)
 	return ARCH_NULL;
 }
 
-static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
+static UINT8 ArchiveValue(save_t *save_p, int TABLESINDEX, int myindex)
 {
 	if (myindex < 0)
 		myindex = lua_gettop(gL)+1+myindex;
@@ -1106,34 +1106,34 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 	{
 	case LUA_TNONE:
 	case LUA_TNIL:
-		WRITEUINT8(save_p, ARCH_NULL);
+		P_WriteUINT8(save_p, ARCH_NULL);
 		break;
 	// This might be a problem. D:
 	case LUA_TLIGHTUSERDATA:
 	case LUA_TTHREAD:
 	case LUA_TFUNCTION:
-		WRITEUINT8(save_p, ARCH_NULL);
+		P_WriteUINT8(save_p, ARCH_NULL);
 		return 2;
 	case LUA_TBOOLEAN:
-		WRITEUINT8(save_p, lua_toboolean(gL, myindex) ? ARCH_TRUE : ARCH_FALSE);
+		P_WriteUINT8(save_p, lua_toboolean(gL, myindex) ? ARCH_TRUE : ARCH_FALSE);
 		break;
 	case LUA_TNUMBER:
 	{
 		lua_Integer number = lua_tointeger(gL, myindex);
 		if (number >= INT8_MIN && number <= INT8_MAX)
 		{
-			WRITEUINT8(save_p, ARCH_INT8);
-			WRITESINT8(save_p, number);
+			P_WriteUINT8(save_p, ARCH_INT8);
+			P_WriteSINT8(save_p, number);
 		}
 		else if (number >= INT16_MIN && number <= INT16_MAX)
 		{
-			WRITEUINT8(save_p, ARCH_INT16);
-			WRITEINT16(save_p, number);
+			P_WriteUINT8(save_p, ARCH_INT16);
+			P_WriteINT16(save_p, number);
 		}
 		else
 		{
-			WRITEUINT8(save_p, ARCH_INT32);
-			WRITEFIXED(save_p, number);
+			P_WriteUINT8(save_p, ARCH_INT32);
+			P_WriteFixed(save_p, number);
 		}
 		break;
 	}
@@ -1144,23 +1144,23 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 		UINT32 i = 0;
 		// if you're wondering why we're writing a string to save_p this way,
 		// it turns out that Lua can have embedded zeros ('\0') in the strings,
-		// so we can't use WRITESTRING as that cuts off when it finds a '\0'.
+		// so we can't use P_WriteString as that cuts off when it finds a '\0'.
 		// Saving the size of the string also allows us to get the size of the string on the other end,
 		// fixing the awful crashes previously encountered for reading strings longer than 1024
 		// (yes I know that's kind of a stupid thing to care about, but it'd be evil to trim or ignore them?)
 		// -- Monster Iestyn 05/08/18
 		if (len < 255)
 		{
-			WRITEUINT8(save_p, ARCH_SMALLSTRING);
-			WRITEUINT8(save_p, len); // save size of string
+			P_WriteUINT8(save_p, ARCH_SMALLSTRING);
+			P_WriteUINT8(save_p, len); // save size of string
 		}
 		else
 		{
-			WRITEUINT8(save_p, ARCH_LARGESTRING);
-			WRITEUINT32(save_p, len); // save size of string
+			P_WriteUINT8(save_p, ARCH_LARGESTRING);
+			P_WriteUINT32(save_p, len); // save size of string
 		}
 		while (i < len)
-			WRITECHAR(save_p, s[i++]); // write chars individually, including the embedded zeros
+			P_WriteChar(save_p, s[i++]); // write chars individually, including the embedded zeros
 		break;
 	}
 	case LUA_TTABLE:
@@ -1186,13 +1186,13 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 			if (t == 0)
 			{
 				CONS_Alert(CONS_ERROR, "Too many tables to archive!\n");
-				WRITEUINT8(save_p, ARCH_NULL);
+				P_WriteUINT8(save_p, ARCH_NULL);
 				return 0;
 			}
 		}
 
-		WRITEUINT8(save_p, ARCH_TABLE);
-		WRITEUINT16(save_p, t);
+		P_WriteUINT8(save_p, ARCH_TABLE);
+		P_WriteUINT16(save_p, t);
 
 		if (!found)
 		{
@@ -1208,25 +1208,25 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 		case ARCH_MOBJINFO:
 		{
 			mobjinfo_t *info = *((mobjinfo_t **)lua_touserdata(gL, myindex));
-			WRITEUINT8(save_p, ARCH_MOBJINFO);
-			WRITEUINT16(save_p, info - mobjinfo);
+			P_WriteUINT8(save_p, ARCH_MOBJINFO);
+			P_WriteUINT16(save_p, info - mobjinfo);
 			break;
 		}
 		case ARCH_STATE:
 		{
 			state_t *state = *((state_t **)lua_touserdata(gL, myindex));
-			WRITEUINT8(save_p, ARCH_STATE);
-			WRITEUINT16(save_p, state - states);
+			P_WriteUINT8(save_p, ARCH_STATE);
+			P_WriteUINT16(save_p, state - states);
 			break;
 		}
 		case ARCH_MOBJ:
 		{
 			mobj_t *mobj = *((mobj_t **)lua_touserdata(gL, myindex));
 			if (!mobj)
-				WRITEUINT8(save_p, ARCH_NULL);
+				P_WriteUINT8(save_p, ARCH_NULL);
 			else {
-				WRITEUINT8(save_p, ARCH_MOBJ);
-				WRITEUINT32(save_p, mobj->mobjnum);
+				P_WriteUINT8(save_p, ARCH_MOBJ);
+				P_WriteUINT32(save_p, mobj->mobjnum);
 			}
 			break;
 		}
@@ -1234,10 +1234,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 		{
 			player_t *player = *((player_t **)lua_touserdata(gL, myindex));
 			if (!player)
-				WRITEUINT8(save_p, ARCH_NULL);
+				P_WriteUINT8(save_p, ARCH_NULL);
 			else {
-				WRITEUINT8(save_p, ARCH_PLAYER);
-				WRITEUINT8(save_p, player - players);
+				P_WriteUINT8(save_p, ARCH_PLAYER);
+				P_WriteUINT8(save_p, player - players);
 			}
 			break;
 		}
@@ -1245,10 +1245,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 		{
 			mapthing_t *mapthing = *((mapthing_t **)lua_touserdata(gL, myindex));
 			if (!mapthing)
-				WRITEUINT8(save_p, ARCH_NULL);
+				P_WriteUINT8(save_p, ARCH_NULL);
 			else {
-				WRITEUINT8(save_p, ARCH_MAPTHING);
-				WRITEUINT16(save_p, mapthing - mapthings);
+				P_WriteUINT8(save_p, ARCH_MAPTHING);
+				P_WriteUINT16(save_p, mapthing - mapthings);
 			}
 			break;
 		}
@@ -1256,10 +1256,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 		{
 			vertex_t *vertex = *((vertex_t **)lua_touserdata(gL, myindex));
 			if (!vertex)
-				WRITEUINT8(save_p, ARCH_NULL);
+				P_WriteUINT8(save_p, ARCH_NULL);
 			else {
-				WRITEUINT8(save_p, ARCH_VERTEX);
-				WRITEUINT16(save_p, vertex - vertexes);
+				P_WriteUINT8(save_p, ARCH_VERTEX);
+				P_WriteUINT16(save_p, vertex - vertexes);
 			}
 			break;
 		}
@@ -1267,10 +1267,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 		{
 			line_t *line = *((line_t **)lua_touserdata(gL, myindex));
 			if (!line)
-				WRITEUINT8(save_p, ARCH_NULL);
+				P_WriteUINT8(save_p, ARCH_NULL);
 			else {
-				WRITEUINT8(save_p, ARCH_LINE);
-				WRITEUINT16(save_p, line - lines);
+				P_WriteUINT8(save_p, ARCH_LINE);
+				P_WriteUINT16(save_p, line - lines);
 			}
 			break;
 		}
@@ -1278,10 +1278,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 		{
 			side_t *side = *((side_t **)lua_touserdata(gL, myindex));
 			if (!side)
-				WRITEUINT8(save_p, ARCH_NULL);
+				P_WriteUINT8(save_p, ARCH_NULL);
 			else {
-				WRITEUINT8(save_p, ARCH_SIDE);
-				WRITEUINT16(save_p, side - sides);
+				P_WriteUINT8(save_p, ARCH_SIDE);
+				P_WriteUINT16(save_p, side - sides);
 			}
 			break;
 		}
@@ -1289,10 +1289,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 		{
 			subsector_t *subsector = *((subsector_t **)lua_touserdata(gL, myindex));
 			if (!subsector)
-				WRITEUINT8(save_p, ARCH_NULL);
+				P_WriteUINT8(save_p, ARCH_NULL);
 			else {
-				WRITEUINT8(save_p, ARCH_SUBSECTOR);
-				WRITEUINT16(save_p, subsector - subsectors);
+				P_WriteUINT8(save_p, ARCH_SUBSECTOR);
+				P_WriteUINT16(save_p, subsector - subsectors);
 			}
 			break;
 		}
@@ -1300,10 +1300,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 		{
 			sector_t *sector = *((sector_t **)lua_touserdata(gL, myindex));
 			if (!sector)
-				WRITEUINT8(save_p, ARCH_NULL);
+				P_WriteUINT8(save_p, ARCH_NULL);
 			else {
-				WRITEUINT8(save_p, ARCH_SECTOR);
-				WRITEUINT16(save_p, sector - sectors);
+				P_WriteUINT8(save_p, ARCH_SECTOR);
+				P_WriteUINT16(save_p, sector - sectors);
 			}
 			break;
 		}
@@ -1312,10 +1312,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 		{
 			seg_t *seg = *((seg_t **)lua_touserdata(gL, myindex));
 			if (!seg)
-				WRITEUINT8(save_p, ARCH_NULL);
+				P_WriteUINT8(save_p, ARCH_NULL);
 			else {
-				WRITEUINT8(save_p, ARCH_SEG);
-				WRITEUINT16(save_p, seg - segs);
+				P_WriteUINT8(save_p, ARCH_SEG);
+				P_WriteUINT16(save_p, seg - segs);
 			}
 			break;
 		}
@@ -1323,10 +1323,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 		{
 			node_t *node = *((node_t **)lua_touserdata(gL, myindex));
 			if (!node)
-				WRITEUINT8(save_p, ARCH_NULL);
+				P_WriteUINT8(save_p, ARCH_NULL);
 			else {
-				WRITEUINT8(save_p, ARCH_NODE);
-				WRITEUINT16(save_p, node - nodes);
+				P_WriteUINT8(save_p, ARCH_NODE);
+				P_WriteUINT16(save_p, node - nodes);
 			}
 			break;
 		}
@@ -1335,16 +1335,16 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 		{
 			ffloor_t *rover = *((ffloor_t **)lua_touserdata(gL, myindex));
 			if (!rover)
-				WRITEUINT8(save_p, ARCH_NULL);
+				P_WriteUINT8(save_p, ARCH_NULL);
 			else {
 				UINT16 i = P_GetFFloorID(rover);
 				if (i == UINT16_MAX) // invalid ID
-					WRITEUINT8(save_p, ARCH_NULL);
+					P_WriteUINT8(save_p, ARCH_NULL);
 				else
 				{
-					WRITEUINT8(save_p, ARCH_FFLOOR);
-					WRITEUINT16(save_p, rover->target - sectors);
-					WRITEUINT16(save_p, i);
+					P_WriteUINT8(save_p, ARCH_FFLOOR);
+					P_WriteUINT16(save_p, rover->target - sectors);
+					P_WriteUINT16(save_p, i);
 				}
 			}
 			break;
@@ -1353,10 +1353,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 		{
 			polyobj_t *polyobj = *((polyobj_t **)lua_touserdata(gL, myindex));
 			if (!polyobj)
-				WRITEUINT8(save_p, ARCH_NULL);
+				P_WriteUINT8(save_p, ARCH_NULL);
 			else {
-				WRITEUINT8(save_p, ARCH_POLYOBJ);
-				WRITEUINT16(save_p, polyobj-PolyObjects);
+				P_WriteUINT8(save_p, ARCH_POLYOBJ);
+				P_WriteUINT16(save_p, polyobj-PolyObjects);
 			}
 			break;
 		}
@@ -1364,10 +1364,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 		{
 			pslope_t *slope = *((pslope_t **)lua_touserdata(gL, myindex));
 			if (!slope)
-				WRITEUINT8(save_p, ARCH_NULL);
+				P_WriteUINT8(save_p, ARCH_NULL);
 			else {
-				WRITEUINT8(save_p, ARCH_SLOPE);
-				WRITEUINT16(save_p, slope->id);
+				P_WriteUINT8(save_p, ARCH_SLOPE);
+				P_WriteUINT16(save_p, slope->id);
 			}
 			break;
 		}
@@ -1375,36 +1375,36 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 		{
 			mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex));
 			if (!header)
-				WRITEUINT8(save_p, ARCH_NULL);
+				P_WriteUINT8(save_p, ARCH_NULL);
 			else {
-				WRITEUINT8(save_p, ARCH_MAPHEADER);
-				WRITEUINT16(save_p, header - *mapheaderinfo);
+				P_WriteUINT8(save_p, ARCH_MAPHEADER);
+				P_WriteUINT16(save_p, header - *mapheaderinfo);
 			}
 			break;
 		}
 		case ARCH_SKINCOLOR:
 		{
 			skincolor_t *info = *((skincolor_t **)lua_touserdata(gL, myindex));
-			WRITEUINT8(save_p, ARCH_SKINCOLOR);
-			WRITEUINT16(save_p, info - skincolors);
+			P_WriteUINT8(save_p, ARCH_SKINCOLOR);
+			P_WriteUINT16(save_p, info - skincolors);
 			break;
 		}
 		case ARCH_MOUSE:
 		{
 			mouse_t *m = *((mouse_t **)lua_touserdata(gL, myindex));
-			WRITEUINT8(save_p, ARCH_MOUSE);
-			WRITEUINT8(save_p, m == &mouse ? 1 : 2);
+			P_WriteUINT8(save_p, ARCH_MOUSE);
+			P_WriteUINT8(save_p, m == &mouse ? 1 : 2);
 			break;
 		}
 		case ARCH_SKIN:
 		{
 			skin_t *skin = *((skin_t **)lua_touserdata(gL, myindex));
-			WRITEUINT8(save_p, ARCH_SKIN);
-			WRITEUINT8(save_p, skin->skinnum); // UINT8 because MAXSKINS must be <= 256
+			P_WriteUINT8(save_p, ARCH_SKIN);
+			P_WriteUINT8(save_p, skin->skinnum); // UINT8 because MAXSKINS must be <= 256
 			break;
 		}
 		default:
-			WRITEUINT8(save_p, ARCH_NULL);
+			P_WriteUINT8(save_p, ARCH_NULL);
 			return 2;
 		}
 		break;
@@ -1412,14 +1412,14 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 	return 0;
 }
 
-static void ArchiveExtVars(void *pointer, const char *ptype)
+static void ArchiveExtVars(save_t *save_p, void *pointer, const char *ptype)
 {
 	int TABLESINDEX;
 	UINT16 i;
 
 	if (!gL) {
 		if (fastcmp(ptype,"player")) // players must always be included, even if no vars
-			WRITEUINT16(save_p, 0);
+			P_WriteUINT16(save_p, 0);
 		return;
 	}
 
@@ -1435,7 +1435,7 @@ static void ArchiveExtVars(void *pointer, const char *ptype)
 	{ // no extra values table
 		lua_pop(gL, 1);
 		if (fastcmp(ptype,"player")) // players must always be included, even if no vars
-			WRITEUINT16(save_p, 0);
+			P_WriteUINT16(save_p, 0);
 		return;
 	}
 
@@ -1447,20 +1447,20 @@ static void ArchiveExtVars(void *pointer, const char *ptype)
 	if (i == 0)
 	{
 		if (fastcmp(ptype,"player")) // always include players even if they have no extra variables
-			WRITEUINT16(save_p, 0);
+			P_WriteUINT16(save_p, 0);
 		lua_pop(gL, 1);
 		return;
 	}
 
 	if (fastcmp(ptype,"mobj")) // mobjs must write their mobjnum as a header
-		WRITEUINT32(save_p, ((mobj_t *)pointer)->mobjnum);
-	WRITEUINT16(save_p, i);
+		P_WriteUINT32(save_p, ((mobj_t *)pointer)->mobjnum);
+	P_WriteUINT16(save_p, i);
 	lua_pushnil(gL);
 	while (lua_next(gL, -2))
 	{
 		I_Assert(lua_type(gL, -2) == LUA_TSTRING);
-		WRITESTRING(save_p, lua_tostring(gL, -2));
-		if (ArchiveValue(TABLESINDEX, -1) == 2)
+		P_WriteString(save_p, lua_tostring(gL, -2));
+		if (ArchiveValue(save_p, TABLESINDEX, -1) == 2)
 			CONS_Alert(CONS_ERROR, "Type of value for %s entry '%s' (%s) could not be archived!\n", ptype, lua_tostring(gL, -2), luaL_typename(gL, -1));
 		lua_pop(gL, 1);
 	}
@@ -1468,16 +1468,19 @@ static void ArchiveExtVars(void *pointer, const char *ptype)
 	lua_pop(gL, 1);
 }
 
+// FIXME: remove and pass as local variable
+static save_t *lua_save_p;
+
 static int NetArchive(lua_State *L)
 {
 	int TABLESINDEX = lua_upvalueindex(1);
 	int i, n = lua_gettop(L);
 	for (i = 1; i <= n; i++)
-		ArchiveValue(TABLESINDEX, i);
+		ArchiveValue(lua_save_p, TABLESINDEX, i);
 	return n;
 }
 
-static void ArchiveTables(void)
+static void ArchiveTables(save_t *save_p)
 {
 	int TABLESINDEX;
 	UINT16 i, n;
@@ -1496,14 +1499,14 @@ static void ArchiveTables(void)
 		while (lua_next(gL, -2))
 		{
 			// Write key
-			e = ArchiveValue(TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this.
+			e = ArchiveValue(save_p, TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this.
 			if (e == 1)
 				n++; // the table contained a new table we'll have to archive. :(
 			else if (e == 2) // invalid key type (function, thread, lightuserdata, or anything we don't recognise)
 				CONS_Alert(CONS_ERROR, "Index '%s' (%s) of table %d could not be archived!\n", lua_tostring(gL, -2), luaL_typename(gL, -2), i);
 
 			// Write value
-			e = ArchiveValue(TABLESINDEX, -1);
+			e = ArchiveValue(save_p, TABLESINDEX, -1);
 			if (e == 1)
 				n++; // the table contained a new table we'll have to archive. :(
 			else if (e == 2) // invalid value type
@@ -1511,7 +1514,7 @@ static void ArchiveTables(void)
 
 			lua_pop(gL, 1);
 		}
-		WRITEUINT8(save_p, ARCH_TEND);
+		P_WriteUINT8(save_p, ARCH_TEND);
 
 		// Write metatable ID
 		if (lua_getmetatable(gL, -1))
@@ -1520,19 +1523,19 @@ static void ArchiveTables(void)
 			lua_getfield(gL, LUA_REGISTRYINDEX, LREG_METATABLES);
 			lua_pushvalue(gL, -2);
 			lua_gettable(gL, -2);
-			WRITEUINT16(save_p, lua_isnil(gL, -1) ? 0 : lua_tointeger(gL, -1));
+			P_WriteUINT16(save_p, lua_isnil(gL, -1) ? 0 : lua_tointeger(gL, -1));
 			lua_pop(gL, 3);
 		}
 		else
-			WRITEUINT16(save_p, 0);
+			P_WriteUINT16(save_p, 0);
 
 		lua_pop(gL, 1);
 	}
 }
 
-static UINT8 UnArchiveValue(int TABLESINDEX)
+static UINT8 UnArchiveValue(save_t *save_p, int TABLESINDEX)
 {
-	UINT8 type = READUINT8(save_p);
+	UINT8 type = P_ReadUINT8(save_p);
 	switch (type)
 	{
 	case ARCH_NULL:
@@ -1545,13 +1548,13 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
 		lua_pushboolean(gL, false);
 		break;
 	case ARCH_INT8:
-		lua_pushinteger(gL, READSINT8(save_p));
+		lua_pushinteger(gL, P_ReadSINT8(save_p));
 		break;
 	case ARCH_INT16:
-		lua_pushinteger(gL, READINT16(save_p));
+		lua_pushinteger(gL, P_ReadINT16(save_p));
 		break;
 	case ARCH_INT32:
-		lua_pushinteger(gL, READFIXED(save_p));
+		lua_pushinteger(gL, P_ReadFixed(save_p));
 		break;
 	case ARCH_SMALLSTRING:
 	case ARCH_LARGESTRING:
@@ -1562,23 +1565,23 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
 
 		// See my comments in the ArchiveValue function;
 		// it's much the same for reading strings as writing them!
-		// (i.e. we can't use READSTRING either)
+		// (i.e. we can't use P_ReadString either)
 		// -- Monster Iestyn 05/08/18
 		if (type == ARCH_SMALLSTRING)
-			len = READUINT8(save_p); // length of string, including embedded zeros
+			len = P_ReadUINT8(save_p); // length of string, including embedded zeros
 		else
-			len = READUINT32(save_p); // length of string, including embedded zeros
+			len = P_ReadUINT32(save_p); // length of string, including embedded zeros
 		value = malloc(len); // make temp buffer of size len
 		// now read the actual string
 		while (i < len)
-			value[i++] = READCHAR(save_p); // read chars individually, including the embedded zeros
+			value[i++] = P_ReadChar(save_p); // read chars individually, including the embedded zeros
 		lua_pushlstring(gL, value, len); // push the string (note: this function supports embedded zeros)
 		free(value); // free the buffer
 		break;
 	}
 	case ARCH_TABLE:
 	{
-		UINT16 tid = READUINT16(save_p);
+		UINT16 tid = P_ReadUINT16(save_p);
 		lua_rawgeti(gL, TABLESINDEX, tid);
 		if (lua_isnil(gL, -1))
 		{
@@ -1591,69 +1594,69 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
 		break;
 	}
 	case ARCH_MOBJINFO:
-		LUA_PushUserdata(gL, &mobjinfo[READUINT16(save_p)], META_MOBJINFO);
+		LUA_PushUserdata(gL, &mobjinfo[P_ReadUINT16(save_p)], META_MOBJINFO);
 		break;
 	case ARCH_STATE:
-		LUA_PushUserdata(gL, &states[READUINT16(save_p)], META_STATE);
+		LUA_PushUserdata(gL, &states[P_ReadUINT16(save_p)], META_STATE);
 		break;
 	case ARCH_MOBJ:
-		LUA_PushUserdata(gL, P_FindNewPosition(READUINT32(save_p)), META_MOBJ);
+		LUA_PushUserdata(gL, P_FindNewPosition(P_ReadUINT32(save_p)), META_MOBJ);
 		break;
 	case ARCH_PLAYER:
-		LUA_PushUserdata(gL, &players[READUINT8(save_p)], META_PLAYER);
+		LUA_PushUserdata(gL, &players[P_ReadUINT8(save_p)], META_PLAYER);
 		break;
 	case ARCH_MAPTHING:
-		LUA_PushUserdata(gL, &mapthings[READUINT16(save_p)], META_MAPTHING);
+		LUA_PushUserdata(gL, &mapthings[P_ReadUINT16(save_p)], META_MAPTHING);
 		break;
 	case ARCH_VERTEX:
-		LUA_PushUserdata(gL, &vertexes[READUINT16(save_p)], META_VERTEX);
+		LUA_PushUserdata(gL, &vertexes[P_ReadUINT16(save_p)], META_VERTEX);
 		break;
 	case ARCH_LINE:
-		LUA_PushUserdata(gL, &lines[READUINT16(save_p)], META_LINE);
+		LUA_PushUserdata(gL, &lines[P_ReadUINT16(save_p)], META_LINE);
 		break;
 	case ARCH_SIDE:
-		LUA_PushUserdata(gL, &sides[READUINT16(save_p)], META_SIDE);
+		LUA_PushUserdata(gL, &sides[P_ReadUINT16(save_p)], META_SIDE);
 		break;
 	case ARCH_SUBSECTOR:
-		LUA_PushUserdata(gL, &subsectors[READUINT16(save_p)], META_SUBSECTOR);
+		LUA_PushUserdata(gL, &subsectors[P_ReadUINT16(save_p)], META_SUBSECTOR);
 		break;
 	case ARCH_SECTOR:
-		LUA_PushUserdata(gL, &sectors[READUINT16(save_p)], META_SECTOR);
+		LUA_PushUserdata(gL, &sectors[P_ReadUINT16(save_p)], META_SECTOR);
 		break;
 #ifdef HAVE_LUA_SEGS
 	case ARCH_SEG:
-		LUA_PushUserdata(gL, &segs[READUINT16(save_p)], META_SEG);
+		LUA_PushUserdata(gL, &segs[P_ReadUINT16(save_p)], META_SEG);
 		break;
 	case ARCH_NODE:
-		LUA_PushUserdata(gL, &nodes[READUINT16(save_p)], META_NODE);
+		LUA_PushUserdata(gL, &nodes[P_ReadUINT16(save_p)], META_NODE);
 		break;
 #endif
 	case ARCH_FFLOOR:
 	{
-		sector_t *sector = &sectors[READUINT16(save_p)];
-		UINT16 id = READUINT16(save_p);
+		sector_t *sector = &sectors[P_ReadUINT16(save_p)];
+		UINT16 id = P_ReadUINT16(save_p);
 		ffloor_t *rover = P_GetFFloorByID(sector, id);
 		if (rover)
 			LUA_PushUserdata(gL, rover, META_FFLOOR);
 		break;
 	}
 	case ARCH_POLYOBJ:
-		LUA_PushUserdata(gL, &PolyObjects[READUINT16(save_p)], META_POLYOBJ);
+		LUA_PushUserdata(gL, &PolyObjects[P_ReadUINT16(save_p)], META_POLYOBJ);
 		break;
 	case ARCH_SLOPE:
-		LUA_PushUserdata(gL, P_SlopeById(READUINT16(save_p)), META_SLOPE);
+		LUA_PushUserdata(gL, P_SlopeById(P_ReadUINT16(save_p)), META_SLOPE);
 		break;
 	case ARCH_MAPHEADER:
-		LUA_PushUserdata(gL, mapheaderinfo[READUINT16(save_p)], META_MAPHEADER);
+		LUA_PushUserdata(gL, mapheaderinfo[P_ReadUINT16(save_p)], META_MAPHEADER);
 		break;
 	case ARCH_SKINCOLOR:
-		LUA_PushUserdata(gL, &skincolors[READUINT16(save_p)], META_SKINCOLOR);
+		LUA_PushUserdata(gL, &skincolors[P_ReadUINT16(save_p)], META_SKINCOLOR);
 		break;
 	case ARCH_MOUSE:
-		LUA_PushUserdata(gL, READUINT16(save_p) == 1 ? &mouse : &mouse2, META_MOUSE);
+		LUA_PushUserdata(gL, P_ReadUINT16(save_p) == 1 ? &mouse : &mouse2, META_MOUSE);
 		break;
 	case ARCH_SKIN:
-		LUA_PushUserdata(gL, skins[READUINT8(save_p)], META_SKIN);
+		LUA_PushUserdata(gL, skins[P_ReadUINT8(save_p)], META_SKIN);
 		break;
 	case ARCH_TEND:
 		return 1;
@@ -1661,10 +1664,10 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
 	return 0;
 }
 
-static void UnArchiveExtVars(void *pointer)
+static void UnArchiveExtVars(save_t *save_p, void *pointer)
 {
 	int TABLESINDEX;
-	UINT16 field_count = READUINT16(save_p);
+	UINT16 field_count = P_ReadUINT16(save_p);
 	UINT16 i;
 	char field[1024];
 
@@ -1677,8 +1680,8 @@ static void UnArchiveExtVars(void *pointer)
 
 	for (i = 0; i < field_count; i++)
 	{
-		READSTRING(save_p, field);
-		UnArchiveValue(TABLESINDEX);
+		P_ReadString(save_p, field);
+		UnArchiveValue(save_p, TABLESINDEX);
 		lua_setfield(gL, -2, field);
 	}
 
@@ -1695,11 +1698,11 @@ static int NetUnArchive(lua_State *L)
 	int TABLESINDEX = lua_upvalueindex(1);
 	int i, n = lua_gettop(L);
 	for (i = 1; i <= n; i++)
-		UnArchiveValue(TABLESINDEX);
+		UnArchiveValue(lua_save_p, TABLESINDEX);
 	return n;
 }
 
-static void UnArchiveTables(void)
+static void UnArchiveTables(save_t *save_p)
 {
 	int TABLESINDEX;
 	UINT16 i, n;
@@ -1716,13 +1719,13 @@ static void UnArchiveTables(void)
 		lua_rawgeti(gL, TABLESINDEX, i);
 		while (true)
 		{
-			UINT8 e = UnArchiveValue(TABLESINDEX); // read key
+			UINT8 e = UnArchiveValue(save_p, TABLESINDEX); // read key
 			if (e == 1) // End of table
 				break;
 			else if (e == 2) // Key contains a new table
 				n++;
 
-			if (UnArchiveValue(TABLESINDEX) == 2) // read value
+			if (UnArchiveValue(save_p, TABLESINDEX) == 2) // read value
 				n++;
 
 			if (lua_isnil(gL, -2)) // if key is nil (if a function etc was accidentally saved)
@@ -1734,7 +1737,7 @@ static void UnArchiveTables(void)
 				lua_rawset(gL, -3);
 		}
 
-		metatableid = READUINT16(save_p);
+		metatableid = P_ReadUINT16(save_p);
 		if (metatableid)
 		{
 			// setmetatable(table, registry.metatables[metatableid])
@@ -1758,7 +1761,7 @@ void LUA_Step(void)
 	lua_gc(gL, LUA_GCSTEP, 1);
 }
 
-void LUA_Archive(void)
+void LUA_Archive(save_t *save_p)
 {
 	INT32 i;
 	thinker_t *th;
@@ -1771,7 +1774,7 @@ void LUA_Archive(void)
 		if (!playeringame[i] && i > 0) // dedicated servers...
 			continue;
 		// all players in game will be archived, even if they just add a 0.
-		ArchiveExtVars(&players[i], "player");
+		ArchiveExtVars(save_p, &players[i], "player");
 	}
 
 	for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
@@ -1781,19 +1784,20 @@ void LUA_Archive(void)
 
 		// archive function will determine when to skip mobjs,
 		// and write mobjnum in otherwise.
-		ArchiveExtVars(th, "mobj");
+		ArchiveExtVars(save_p, th, "mobj");
 	}
 
-	WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum.
+	P_WriteUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum.
 
+	lua_save_p = save_p;
 	LUA_HookNetArchive(NetArchive); // call the NetArchive hook in archive mode
-	ArchiveTables();
+	ArchiveTables(save_p);
 
 	if (gL)
 		lua_pop(gL, 1); // pop tables
 }
 
-void LUA_UnArchive(void)
+void LUA_UnArchive(save_t *save_p)
 {
 	UINT32 mobjnum;
 	INT32 i;
@@ -1806,23 +1810,24 @@ void LUA_UnArchive(void)
 	{
 		if (!playeringame[i] && i > 0) // dedicated servers...
 			continue;
-		UnArchiveExtVars(&players[i]);
+		UnArchiveExtVars(save_p, &players[i]);
 	}
 
 	do {
-		mobjnum = READUINT32(save_p); // read a mobjnum
+		mobjnum = P_ReadUINT32(save_p); // read a mobjnum
 		for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
 		{
 			if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
 				continue;
 			if (((mobj_t *)th)->mobjnum != mobjnum) // find matching mobj
 				continue;
-			UnArchiveExtVars(th); // apply variables
+			UnArchiveExtVars(save_p, th); // apply variables
 		}
 	} while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker.
 
+	lua_save_p = save_p;
 	LUA_HookNetArchive(NetUnArchive); // call the NetArchive hook in unarchive mode
-	UnArchiveTables();
+	UnArchiveTables(save_p);
 
 	if (gL)
 		lua_pop(gL, 1); // pop tables
diff --git a/src/lua_script.h b/src/lua_script.h
index 45d2a37ffd1a636f1e6aaf6848fa868a25fba74b..968ef078daa9770914076cebbb6d9e250cac7404 100644
--- a/src/lua_script.h
+++ b/src/lua_script.h
@@ -13,6 +13,7 @@
 #ifndef LUA_SCRIPT_H
 #define LUA_SCRIPT_H
 
+#include "p_saveg.h"
 #include "m_fixed.h"
 #include "doomtype.h"
 #include "d_player.h"
@@ -52,8 +53,8 @@ void LUA_DumpFile(const char *filename);
 #endif
 fixed_t LUA_EvalMath(const char *word);
 void LUA_Step(void);
-void LUA_Archive(void);
-void LUA_UnArchive(void);
+void LUA_Archive(save_t *save_p);
+void LUA_UnArchive(save_t *save_p);
 int LUA_PushGlobals(lua_State *L, const char *word);
 int LUA_CheckGlobals(lua_State *L, const char *word);
 void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c
diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c
index 4134c633e5a32e23e6be085a32300bb308a694df..64feeeda314e6423354fbca9635fa30d6769db51 100644
--- a/src/netcode/d_netcmd.c
+++ b/src/netcode/d_netcmd.c
@@ -4799,12 +4799,11 @@ static void Command_Togglemodified_f(void)
 	modifiedgame = !modifiedgame;
 }
 
-extern UINT8 *save_p;
 static void Command_Archivetest_f(void)
 {
-	UINT8 *buf;
 	UINT32 i, wrote;
 	thinker_t *th;
+	save_t savebuffer;
 	if (gamestate != GS_LEVEL)
 	{
 		CONS_Printf("This command only works in-game, you dummy.\n");
@@ -4818,28 +4817,29 @@ static void Command_Archivetest_f(void)
 			((mobj_t *)th)->mobjnum = i++;
 
 	// allocate buffer
-	buf = save_p = ZZ_Alloc(1024);
+	savebuffer.size = 1024;
+	savebuffer.buf = malloc(savebuffer.size);
+	savebuffer.pos = 0;
 
 	// test archive
 	CONS_Printf("LUA_Archive...\n");
-	LUA_Archive();
-	WRITEUINT8(save_p, 0x7F);
-	wrote = (UINT32)(save_p-buf);
+	LUA_Archive(&savebuffer);
+	P_WriteUINT8(&savebuffer, 0x7F);
+	wrote = savebuffer.pos;
 
 	// clear Lua state, so we can really see what happens!
 	CONS_Printf("Clearing state!\n");
 	LUA_ClearExtVars();
 
 	// test unarchive
-	save_p = buf;
 	CONS_Printf("LUA_UnArchive...\n");
-	LUA_UnArchive();
-	i = READUINT8(save_p);
-	if (i != 0x7F || wrote != (UINT32)(save_p-buf))
-		CONS_Printf("Savegame corrupted. (write %u, read %u)\n", wrote, (UINT32)(save_p-buf));
+	LUA_UnArchive(&savebuffer);
+	i = P_ReadUINT8(&savebuffer);
+	if (i != 0x7F || wrote != (UINT32)(savebuffer.pos))
+		CONS_Printf("Savegame corrupted. (write %u, read %u)\n", wrote, (UINT32)(savebuffer.pos));
 
 	// free buffer
-	Z_Free(buf);
+	free(savebuffer.buf);
 	CONS_Printf("Done. No crash.\n");
 }
 #endif
diff --git a/src/netcode/gamestate.c b/src/netcode/gamestate.c
index f36347c6d88e94a444fb186937d2672cfe3a0df9..d38555245a42852ad00d63232a77649915df25c4 100644
--- a/src/netcode/gamestate.c
+++ b/src/netcode/gamestate.c
@@ -54,30 +54,25 @@ boolean SV_ResendingSavegameToAnyone(void)
 void SV_SendSaveGame(INT32 node, boolean resending)
 {
 	size_t length, compressedlen;
-	UINT8 *savebuffer;
+	save_t savebuffer;
 	UINT8 *compressedsave;
 	UINT8 *buffertosend;
 
 	// first save it in a malloced buffer
-	savebuffer = (UINT8 *)malloc(SAVEGAMESIZE);
-	if (!savebuffer)
+	savebuffer.size = SAVEGAMESIZE;
+	savebuffer.buf = (UINT8 *)malloc(savebuffer.size);
+	if (!savebuffer.buf)
 	{
 		CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n"));
 		return;
 	}
 
 	// Leave room for the uncompressed length.
-	save_p = savebuffer + sizeof(UINT32);
+	savebuffer.pos = sizeof(UINT32);
 
-	P_SaveNetGame(resending);
+	P_SaveNetGame(&savebuffer, resending);
 
-	length = save_p - savebuffer;
-	if (length > SAVEGAMESIZE)
-	{
-		free(savebuffer);
-		save_p = NULL;
-		I_Error("Savegame buffer overrun");
-	}
+	length = savebuffer.pos;
 
 	// Allocate space for compressed save: one byte fewer than for the
 	// uncompressed data to ensure that the compression is worthwhile.
@@ -85,15 +80,16 @@ void SV_SendSaveGame(INT32 node, boolean resending)
 	if (!compressedsave)
 	{
 		CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n"));
+		free(savebuffer.buf);
 		return;
 	}
 
 	// Attempt to compress it.
-	if((compressedlen = lzf_compress(savebuffer + sizeof(UINT32), length - sizeof(UINT32), compressedsave + sizeof(UINT32), length - sizeof(UINT32) - 1)))
+	if((compressedlen = lzf_compress(savebuffer.buf + sizeof(UINT32), length - sizeof(UINT32), compressedsave + sizeof(UINT32), length - sizeof(UINT32) - 1)))
 	{
 		// Compressing succeeded; send compressed data
 
-		free(savebuffer);
+		free(savebuffer.buf);
 
 		// State that we're compressed.
 		buffertosend = compressedsave;
@@ -107,12 +103,12 @@ void SV_SendSaveGame(INT32 node, boolean resending)
 		free(compressedsave);
 
 		// State that we're not compressed
-		buffertosend = savebuffer;
-		WRITEUINT32(savebuffer, 0);
+		buffertosend = savebuffer.buf;
+		savebuffer.pos = 0;
+		P_WriteUINT32(&savebuffer, 0);
 	}
 
 	AddRamToSendQueue(node, buffertosend, length, SF_RAM, 0);
-	save_p = NULL;
 
 	// Remember when we started sending the savegame so we can handle timeouts
 	netnodes[node].sendingsavegame = true;
@@ -125,8 +121,7 @@ static consvar_t cv_dumpconsistency = CVAR_INIT ("dumpconsistency", "Off", CV_SA
 
 void SV_SavedGame(void)
 {
-	size_t length;
-	UINT8 *savebuffer;
+	save_t savebuffer;
 	char tmpsave[256];
 
 	if (!cv_dumpconsistency.value)
@@ -135,29 +130,22 @@ void SV_SavedGame(void)
 	sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
 
 	// first save it in a malloced buffer
-	save_p = savebuffer = (UINT8 *)malloc(SAVEGAMESIZE);
-	if (!save_p)
+	savebuffer.size = SAVEGAMESIZE;
+	savebuffer.buf = (UINT8 *)malloc(savebuffer.size);
+	if (!savebuffer.buf)
 	{
 		CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n"));
 		return;
 	}
+	savebuffer.pos = 0;
 
-	P_SaveNetGame(false);
-
-	length = save_p - savebuffer;
-	if (length > SAVEGAMESIZE)
-	{
-		free(savebuffer);
-		save_p = NULL;
-		I_Error("Savegame buffer overrun");
-	}
+	P_SaveNetGame(&savebuffer, false);
 
 	// then save it!
-	if (!FIL_WriteFile(tmpsave, savebuffer, length))
+	if (!FIL_WriteFile(tmpsave, savebuffer.buf, savebuffer.pos))
 		CONS_Printf(M_GetText("Didn't save %s for netgame"), tmpsave);
 
-	free(savebuffer);
-	save_p = NULL;
+	free(savebuffer.pos);
 }
 
 #undef  TMPSAVENAME
@@ -167,33 +155,34 @@ void SV_SavedGame(void)
 
 void CL_LoadReceivedSavegame(boolean reloading)
 {
-	UINT8 *savebuffer = NULL;
-	size_t length, decompressedlen;
+	save_t savebuffer;
+	size_t decompressedlen;
 	char tmpsave[256];
 
 	FreeFileNeeded();
 
 	sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
 
-	length = FIL_ReadFile(tmpsave, &savebuffer);
+	savebuffer.size = FIL_ReadFile(tmpsave, &savebuffer.buf);
+	savebuffer.pos = 0;
 
-	CONS_Printf(M_GetText("Loading savegame length %s\n"), sizeu1(length));
-	if (!length)
+	CONS_Printf(M_GetText("Loading savegame length %s\n"), sizeu1(savebuffer.size));
+	if (!savebuffer.size)
 	{
 		I_Error("Can't read savegame sent");
 		return;
 	}
 
-	save_p = savebuffer;
-
 	// Decompress saved game if necessary.
-	decompressedlen = READUINT32(save_p);
+	decompressedlen = P_ReadUINT32(&savebuffer);
 	if(decompressedlen > 0)
 	{
 		UINT8 *decompressedbuffer = Z_Malloc(decompressedlen, PU_STATIC, NULL);
-		lzf_decompress(save_p, length - sizeof(UINT32), decompressedbuffer, decompressedlen);
-		Z_Free(savebuffer);
-		save_p = savebuffer = decompressedbuffer;
+		lzf_decompress(savebuffer.buf + sizeof(UINT32), savebuffer.size - sizeof(UINT32), decompressedbuffer, decompressedlen);
+		Z_Free(savebuffer.buf);
+		savebuffer.buf = decompressedbuffer;
+		savebuffer.size = decompressedlen;
+		savebuffer.pos = 0;
 	}
 
 	paused = false;
@@ -203,7 +192,7 @@ void CL_LoadReceivedSavegame(boolean reloading)
 	automapactive = false;
 
 	// load a base level
-	if (P_LoadNetGame(reloading))
+	if (P_LoadNetGame(&savebuffer, reloading))
 	{
 		const UINT8 actnum = mapheaderinfo[gamemap-1]->actnum;
 		CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap));
@@ -219,8 +208,7 @@ void CL_LoadReceivedSavegame(boolean reloading)
 	}
 
 	// done
-	Z_Free(savebuffer);
-	save_p = NULL;
+	Z_Free(savebuffer.buf);
 	if (unlink(tmpsave) == -1)
 		CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave);
 	consistancy[gametic%BACKUPTICS] = Consistancy();
diff --git a/src/p_mobj.h b/src/p_mobj.h
index f281410f6ddc7ece41acc963afe63a6b23420269..4ebcc993aebc675696cc09fe0e0441bffc5c2451 100644
--- a/src/p_mobj.h
+++ b/src/p_mobj.h
@@ -539,6 +539,8 @@ boolean P_SceneryZMovement(mobj_t *mo);
 void P_PlayerZMovement(mobj_t *mo);
 void P_EmeraldManager(void);
 
+mobj_t *P_FindNewPosition(UINT32 oldposition);
+
 extern INT32 modulothing;
 
 #define MAXHUNTEMERALDS 64
diff --git a/src/p_saveg.c b/src/p_saveg.c
index c5ec57d01ecad8cdde4f82195831b26c519be685..5c22285938b5e6ac1282a0692c225c50c2c841da 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -38,7 +38,246 @@
 #include "hu_stuff.h"
 
 savedata_t savedata;
-UINT8 *save_p;
+
+#define ALLOC_SIZE(p, z) \
+	if ((p)->pos + (z) > (p)->size) \
+	{ \
+		while ((p)->pos + (z) > (p)->size) \
+			(p)->size <<= 1; \
+		(p)->buf = realloc((p)->buf, (p)->size); \
+	}
+
+void P_WriteUINT8(save_t *p, UINT8 v)
+{
+	ALLOC_SIZE(p, sizeof(v));
+	memcpy(&p->buf[p->pos], &v, sizeof(v));
+	p->pos += sizeof(v);
+}
+
+void P_WriteSINT8(save_t *p, SINT8 v)
+{
+	ALLOC_SIZE(p, sizeof(v));
+	memcpy(&p->buf[p->pos], &v, sizeof(v));
+	p->pos += sizeof(v);
+}
+
+void P_WriteUINT16(save_t *p, UINT16 v)
+{
+	ALLOC_SIZE(p, sizeof(v));
+	memcpy(&p->buf[p->pos], &v, sizeof(v));
+	p->pos += sizeof(v);
+}
+
+void P_WriteINT16(save_t *p, INT16 v)
+{
+	ALLOC_SIZE(p, sizeof(v));
+	memcpy(&p->buf[p->pos], &v, sizeof(v));
+	p->pos += sizeof(v);
+}
+
+void P_WriteUINT32(save_t *p, UINT32 v)
+{
+	ALLOC_SIZE(p, sizeof(v));
+	memcpy(&p->buf[p->pos], &v, sizeof(v));
+	p->pos += sizeof(v);
+}
+
+void P_WriteINT32(save_t *p, INT32 v)
+{
+	ALLOC_SIZE(p, sizeof(v));
+	memcpy(&p->buf[p->pos], &v, sizeof(v));
+	p->pos += sizeof(v);
+}
+
+void P_WriteChar(save_t *p, char v)
+{
+	ALLOC_SIZE(p, sizeof(v));
+	memcpy(&p->buf[p->pos], &v, sizeof(v));
+	p->pos += sizeof(v);
+}
+
+void P_WriteFixed(save_t *p, fixed_t v)
+{
+	ALLOC_SIZE(p, sizeof(v));
+	memcpy(&p->buf[p->pos], &v, sizeof(v));
+	p->pos += sizeof(v);
+}
+
+void P_WriteAngle(save_t *p, angle_t v)
+{
+	ALLOC_SIZE(p, sizeof(v));
+	memcpy(&p->buf[p->pos], &v, sizeof(v));
+	p->pos += sizeof(v);
+}
+
+void P_WriteStringN(save_t *p, char const *s, size_t n)
+{
+	size_t i;
+
+	for (i = 0; i < n && s[i] != '\0'; i++)
+		P_WriteChar(p, s[i]);
+
+	if (i < n)
+		P_WriteChar(p, '\0');
+}
+
+void P_WriteStringL(save_t *p, char const *s, size_t n)
+{
+	size_t i;
+
+	for (i = 0; i < n - 1 && s[i] != '\0'; i++)
+		P_WriteChar(p, s[i]);
+
+	P_WriteChar(p, '\0');
+}
+
+void P_WriteString(save_t *p, char const *s)
+{
+	size_t i;
+
+	for (i = 0; s[i] != '\0'; i++)
+		P_WriteChar(p, s[i]);
+
+	P_WriteChar(p, '\0');
+}
+
+void P_WriteMem(save_t *p, void const *s, size_t n)
+{
+	ALLOC_SIZE(p, n);
+	memcpy(&p->buf[p->pos], s, n);
+	p->pos += n;
+}
+
+void P_SkipStringN(save_t *p, size_t n)
+{
+	size_t i;
+	for (i = 0; p->pos < p->size && i < n && P_ReadChar(p) != '\0'; i++);
+}
+
+void P_SkipStringL(save_t *p, size_t n)
+{
+	P_SkipStringN(p, n);
+}
+
+void P_SkipString(save_t *p)
+{
+	P_SkipStringN(p, SIZE_MAX);
+}
+
+UINT8 P_ReadUINT8(save_t *p)
+{
+	UINT8 v;
+	if (p->pos + sizeof(v) > p->size)
+		return 0;
+	memcpy(&v, &p->buf[p->pos], sizeof(v));
+	p->pos += sizeof(v);
+	return v;
+}
+
+SINT8 P_ReadSINT8(save_t *p)
+{
+	SINT8 v;
+	if (p->pos + sizeof(v) > p->size)
+		return 0;
+	memcpy(&v, &p->buf[p->pos], sizeof(v));
+	p->pos += sizeof(v);
+	return v;
+}
+
+UINT16 P_ReadUINT16(save_t *p)
+{
+	UINT16 v;
+	if (p->pos + sizeof(v) > p->size)
+		return 0;
+	memcpy(&v, &p->buf[p->pos], sizeof(v));
+	p->pos += sizeof(v);
+	return v;
+}
+
+INT16 P_ReadINT16(save_t *p)
+{
+	INT16 v;
+	if (p->pos + sizeof(v) > p->size)
+		return 0;
+	memcpy(&v, &p->buf[p->pos], sizeof(v));
+	p->pos += sizeof(v);
+	return v;
+}
+
+UINT32 P_ReadUINT32(save_t *p)
+{
+	UINT32 v;
+	if (p->pos + sizeof(v) > p->size)
+		return 0;
+	memcpy(&v, &p->buf[p->pos], sizeof(v));
+	p->pos += sizeof(v);
+	return v;
+}
+
+INT32 P_ReadINT32(save_t *p)
+{
+	INT32 v;
+	if (p->pos + sizeof(v) > p->size)
+		return 0;
+	memcpy(&v, &p->buf[p->pos], sizeof(v));
+	p->pos += sizeof(v);
+	return v;
+}
+
+char P_ReadChar(save_t *p)
+{
+	char v;
+	if (p->pos + sizeof(v) > p->size)
+		return 0;
+	memcpy(&v, &p->buf[p->pos], sizeof(v));
+	p->pos += sizeof(v);
+	return v;
+}
+
+fixed_t P_ReadFixed(save_t *p)
+{
+	fixed_t v;
+	if (p->pos + sizeof(v) > p->size)
+		return 0;
+	memcpy(&v, &p->buf[p->pos], sizeof(v));
+	p->pos += sizeof(v);
+	return v;
+}
+
+angle_t P_ReadAngle(save_t *p)
+{
+	angle_t v;
+	if (p->pos + sizeof(v) > p->size)
+		return 0;
+	memcpy(&v, &p->buf[p->pos], sizeof(v));
+	p->pos += sizeof(v);
+	return v;
+}
+
+void P_ReadStringN(save_t *p, char *s, size_t n)
+{
+	size_t i;
+	for (i = 0; p->pos < p->size && i < n && (s[i] = P_ReadChar(p)) != '\0'; i++);
+	s[i] = '\0';
+}
+
+void P_ReadStringL(save_t *p, char *s, size_t n)
+{
+	P_ReadStringN(p, s, n - 1);
+}
+
+void P_ReadString(save_t *p, char *s)
+{
+	P_ReadStringN(p, s, SIZE_MAX);
+}
+
+void P_ReadMem(save_t *p, void *s, size_t n)
+{
+	if (p->pos + n > p->size)
+		return;
+	memcpy(s, &p->buf[p->pos], n);
+	p->pos += n;
+}
 
 // Block UINT32s to attempt to ensure that the correct data is
 // being sent and received
@@ -63,7 +302,7 @@ typedef enum
 	DRONE      = 0x80,
 } player_saveflags;
 
-static inline void P_ArchivePlayer(void)
+static inline void P_ArchivePlayer(save_t *save_p)
 {
 	const player_t *player = &players[consoleplayer];
 	SINT8 pllives = player->lives;
@@ -73,32 +312,32 @@ static inline void P_ArchivePlayer(void)
 #ifdef NEWSKINSAVES
 	// Write a specific value into the old skininfo location.
 	// If we read something other than this, it's an older save file that used skin numbers.
-	WRITEUINT16(save_p, NEWSKINSAVES);
+	P_WriteUINT16(save_p, NEWSKINSAVES);
 #endif
 
 	// Write skin names, so that loading skins in different orders
 	// doesn't change who the save file is for!
-	WRITESTRINGN(save_p, skins[player->skin]->name, SKINNAMESIZE);
+	P_WriteStringN(save_p, skins[player->skin]->name, SKINNAMESIZE);
 
 	if (botskin != 0)
 	{
-		WRITESTRINGN(save_p, skins[botskin-1]->name, SKINNAMESIZE);
+		P_WriteStringN(save_p, skins[botskin-1]->name, SKINNAMESIZE);
 	}
 	else
 	{
-		WRITESTRINGN(save_p, "\0", SKINNAMESIZE);
+		P_WriteStringN(save_p, "\0", SKINNAMESIZE);
 	}
 
-	WRITEUINT8(save_p, numgameovers);
-	WRITESINT8(save_p, pllives);
-	WRITEUINT32(save_p, player->score);
-	WRITEINT32(save_p, player->continues);
+	P_WriteUINT8(save_p, numgameovers);
+	P_WriteSINT8(save_p, pllives);
+	P_WriteUINT32(save_p, player->score);
+	P_WriteINT32(save_p, player->continues);
 }
 
-static inline void P_UnArchivePlayer(void)
+static inline void P_UnArchivePlayer(save_t *save_p)
 {
 #ifdef NEWSKINSAVES
-	INT16 backwardsCompat = READUINT16(save_p);
+	INT16 backwardsCompat = P_ReadUINT16(save_p);
 
 	if (backwardsCompat != NEWSKINSAVES)
 	{
@@ -112,30 +351,30 @@ static inline void P_UnArchivePlayer(void)
 		char ourSkinName[SKINNAMESIZE+1];
 		char botSkinName[SKINNAMESIZE+1];
 
-		READSTRINGN(save_p, ourSkinName, SKINNAMESIZE);
+		P_ReadStringN(save_p, ourSkinName, SKINNAMESIZE);
 		savedata.skin = R_SkinAvailable(ourSkinName);
 
-		READSTRINGN(save_p, botSkinName, SKINNAMESIZE);
+		P_ReadStringN(save_p, botSkinName, SKINNAMESIZE);
 		savedata.botskin = R_SkinAvailable(botSkinName) + 1;
 	}
 
-	savedata.numgameovers = READUINT8(save_p);
-	savedata.lives = READSINT8(save_p);
-	savedata.score = READUINT32(save_p);
-	savedata.continues = READINT32(save_p);
+	savedata.numgameovers = P_ReadUINT8(save_p);
+	savedata.lives = P_ReadSINT8(save_p);
+	savedata.score = P_ReadUINT32(save_p);
+	savedata.continues = P_ReadINT32(save_p);
 }
 
-static void P_NetArchivePlayers(void)
+static void P_NetArchivePlayers(save_t *save_p)
 {
 	INT32 i, j;
 	UINT16 flags;
 //	size_t q;
 
-	WRITEUINT32(save_p, ARCHIVEBLOCK_PLAYERS);
+	P_WriteUINT32(save_p, ARCHIVEBLOCK_PLAYERS);
 
 	for (i = 0; i < MAXPLAYERS; i++)
 	{
-		WRITESINT8(save_p, (SINT8)adminplayers[i]);
+		P_WriteSINT8(save_p, (SINT8)adminplayers[i]);
 
 		if (!playeringame[i])
 			continue;
@@ -144,142 +383,142 @@ static void P_NetArchivePlayers(void)
 
 		// no longer send ticcmds
 
-		WRITESTRINGN(save_p, player_names[i], MAXPLAYERNAME);
-		WRITEINT16(save_p, players[i].angleturn);
-		WRITEINT16(save_p, players[i].oldrelangleturn);
-		WRITEANGLE(save_p, players[i].aiming);
-		WRITEANGLE(save_p, players[i].drawangle);
-		WRITEANGLE(save_p, players[i].viewrollangle);
-		WRITEANGLE(save_p, players[i].awayviewaiming);
-		WRITEINT32(save_p, players[i].awayviewtics);
-		WRITEINT16(save_p, players[i].rings);
-		WRITEINT16(save_p, players[i].spheres);
-
-		WRITESINT8(save_p, players[i].pity);
-		WRITEINT32(save_p, players[i].currentweapon);
-		WRITEINT32(save_p, players[i].ringweapons);
-
-		WRITEUINT16(save_p, players[i].ammoremoval);
-		WRITEUINT32(save_p, players[i].ammoremovaltimer);
-		WRITEINT32(save_p, players[i].ammoremovaltimer);
+		P_WriteStringN(save_p, player_names[i], MAXPLAYERNAME);
+		P_WriteINT16(save_p, players[i].angleturn);
+		P_WriteINT16(save_p, players[i].oldrelangleturn);
+		P_WriteAngle(save_p, players[i].aiming);
+		P_WriteAngle(save_p, players[i].drawangle);
+		P_WriteAngle(save_p, players[i].viewrollangle);
+		P_WriteAngle(save_p, players[i].awayviewaiming);
+		P_WriteINT32(save_p, players[i].awayviewtics);
+		P_WriteINT16(save_p, players[i].rings);
+		P_WriteINT16(save_p, players[i].spheres);
+
+		P_WriteSINT8(save_p, players[i].pity);
+		P_WriteINT32(save_p, players[i].currentweapon);
+		P_WriteINT32(save_p, players[i].ringweapons);
+
+		P_WriteUINT16(save_p, players[i].ammoremoval);
+		P_WriteUINT32(save_p, players[i].ammoremovaltimer);
+		P_WriteINT32(save_p, players[i].ammoremovaltimer);
 
 		for (j = 0; j < NUMPOWERS; j++)
-			WRITEUINT16(save_p, players[i].powers[j]);
-
-		WRITEUINT8(save_p, players[i].playerstate);
-		WRITEUINT32(save_p, players[i].pflags);
-		WRITEUINT8(save_p, players[i].panim);
-		WRITEUINT8(save_p, players[i].stronganim);
-		WRITEUINT8(save_p, players[i].spectator);
-		WRITEUINT8(save_p, players[i].muted);
-
-		WRITEUINT16(save_p, players[i].flashpal);
-		WRITEUINT16(save_p, players[i].flashcount);
-
-		WRITEUINT16(save_p, players[i].skincolor);
-		WRITEINT32(save_p, players[i].skin);
-		WRITEUINT32(save_p, players[i].availabilities);
-		WRITEUINT32(save_p, players[i].score);
-		WRITEUINT32(save_p, players[i].recordscore);
-		WRITEFIXED(save_p, players[i].dashspeed);
-		WRITESINT8(save_p, players[i].lives);
-		WRITESINT8(save_p, players[i].continues);
-		WRITESINT8(save_p, players[i].xtralife);
-		WRITEUINT8(save_p, players[i].gotcontinue);
-		WRITEFIXED(save_p, players[i].speed);
-		WRITEUINT8(save_p, players[i].secondjump);
-		WRITEUINT8(save_p, players[i].fly1);
-		WRITEUINT8(save_p, players[i].scoreadd);
-		WRITEUINT32(save_p, players[i].glidetime);
-		WRITEUINT8(save_p, players[i].climbing);
-		WRITEINT32(save_p, players[i].deadtimer);
-		WRITEUINT32(save_p, players[i].exiting);
-		WRITEUINT8(save_p, players[i].homing);
-		WRITEUINT32(save_p, players[i].dashmode);
-		WRITEUINT32(save_p, players[i].skidtime);
+			P_WriteUINT16(save_p, players[i].powers[j]);
+
+		P_WriteUINT8(save_p, players[i].playerstate);
+		P_WriteUINT32(save_p, players[i].pflags);
+		P_WriteUINT8(save_p, players[i].panim);
+		P_WriteUINT8(save_p, players[i].stronganim);
+		P_WriteUINT8(save_p, players[i].spectator);
+		P_WriteUINT8(save_p, players[i].muted);
+
+		P_WriteUINT16(save_p, players[i].flashpal);
+		P_WriteUINT16(save_p, players[i].flashcount);
+
+		P_WriteUINT16(save_p, players[i].skincolor);
+		P_WriteINT32(save_p, players[i].skin);
+		P_WriteUINT32(save_p, players[i].availabilities);
+		P_WriteUINT32(save_p, players[i].score);
+		P_WriteUINT32(save_p, players[i].recordscore);
+		P_WriteFixed(save_p, players[i].dashspeed);
+		P_WriteSINT8(save_p, players[i].lives);
+		P_WriteSINT8(save_p, players[i].continues);
+		P_WriteSINT8(save_p, players[i].xtralife);
+		P_WriteUINT8(save_p, players[i].gotcontinue);
+		P_WriteFixed(save_p, players[i].speed);
+		P_WriteUINT8(save_p, players[i].secondjump);
+		P_WriteUINT8(save_p, players[i].fly1);
+		P_WriteUINT8(save_p, players[i].scoreadd);
+		P_WriteUINT32(save_p, players[i].glidetime);
+		P_WriteUINT8(save_p, players[i].climbing);
+		P_WriteINT32(save_p, players[i].deadtimer);
+		P_WriteUINT32(save_p, players[i].exiting);
+		P_WriteUINT8(save_p, players[i].homing);
+		P_WriteUINT32(save_p, players[i].dashmode);
+		P_WriteUINT32(save_p, players[i].skidtime);
 
 		//////////
 		// Bots //
 		//////////
-		WRITEUINT8(save_p, players[i].bot);
-		WRITEUINT8(save_p, players[i].botmem.lastForward);
-		WRITEUINT8(save_p, players[i].botmem.lastBlocked);
-		WRITEUINT8(save_p, players[i].botmem.catchup_tics);
-		WRITEUINT8(save_p, players[i].botmem.thinkstate);
-		WRITEUINT8(save_p, players[i].removing);
+		P_WriteUINT8(save_p, players[i].bot);
+		P_WriteUINT8(save_p, players[i].botmem.lastForward);
+		P_WriteUINT8(save_p, players[i].botmem.lastBlocked);
+		P_WriteUINT8(save_p, players[i].botmem.catchup_tics);
+		P_WriteUINT8(save_p, players[i].botmem.thinkstate);
+		P_WriteUINT8(save_p, players[i].removing);
 
-		WRITEUINT8(save_p, players[i].blocked);
-		WRITEUINT16(save_p, players[i].lastbuttons);
+		P_WriteUINT8(save_p, players[i].blocked);
+		P_WriteUINT16(save_p, players[i].lastbuttons);
 
 		////////////////////////////
 		// Conveyor Belt Movement //
 		////////////////////////////
-		WRITEFIXED(save_p, players[i].cmomx); // Conveyor momx
-		WRITEFIXED(save_p, players[i].cmomy); // Conveyor momy
-		WRITEFIXED(save_p, players[i].rmomx); // "Real" momx (momx - cmomx)
-		WRITEFIXED(save_p, players[i].rmomy); // "Real" momy (momy - cmomy)
+		P_WriteFixed(save_p, players[i].cmomx); // Conveyor momx
+		P_WriteFixed(save_p, players[i].cmomy); // Conveyor momy
+		P_WriteFixed(save_p, players[i].rmomx); // "Real" momx (momx - cmomx)
+		P_WriteFixed(save_p, players[i].rmomy); // "Real" momy (momy - cmomy)
 
 		/////////////////////
 		// Race Mode Stuff //
 		/////////////////////
-		WRITEINT16(save_p, players[i].numboxes);
-		WRITEINT16(save_p, players[i].totalring);
-		WRITEUINT32(save_p, players[i].realtime);
-		WRITEUINT8(save_p, players[i].laps);
+		P_WriteINT16(save_p, players[i].numboxes);
+		P_WriteINT16(save_p, players[i].totalring);
+		P_WriteUINT32(save_p, players[i].realtime);
+		P_WriteUINT8(save_p, players[i].laps);
 
 		////////////////////
 		// CTF Mode Stuff //
 		////////////////////
-		WRITEINT32(save_p, players[i].ctfteam);
-		WRITEUINT16(save_p, players[i].gotflag);
-
-		WRITEINT32(save_p, players[i].weapondelay);
-		WRITEINT32(save_p, players[i].tossdelay);
-
-		WRITEUINT32(save_p, players[i].starposttime);
-		WRITEINT16(save_p, players[i].starpostx);
-		WRITEINT16(save_p, players[i].starposty);
-		WRITEINT16(save_p, players[i].starpostz);
-		WRITEINT32(save_p, players[i].starpostnum);
-		WRITEANGLE(save_p, players[i].starpostangle);
-		WRITEFIXED(save_p, players[i].starpostscale);
-
-		WRITEANGLE(save_p, players[i].angle_pos);
-		WRITEANGLE(save_p, players[i].old_angle_pos);
-
-		WRITEINT32(save_p, players[i].flyangle);
-		WRITEUINT32(save_p, players[i].drilltimer);
-		WRITEINT32(save_p, players[i].linkcount);
-		WRITEUINT32(save_p, players[i].linktimer);
-		WRITEINT32(save_p, players[i].anotherflyangle);
-		WRITEUINT32(save_p, players[i].nightstime);
-		WRITEUINT32(save_p, players[i].bumpertime);
-		WRITEINT32(save_p, players[i].drillmeter);
-		WRITEUINT8(save_p, players[i].drilldelay);
-		WRITEUINT8(save_p, players[i].bonustime);
-		WRITEFIXED(save_p, players[i].oldscale);
-		WRITEUINT8(save_p, players[i].mare);
-		WRITEUINT8(save_p, players[i].marelap);
-		WRITEUINT8(save_p, players[i].marebonuslap);
-		WRITEUINT32(save_p, players[i].marebegunat);
-		WRITEUINT32(save_p, players[i].lastmaretime);
-		WRITEUINT32(save_p, players[i].startedtime);
-		WRITEUINT32(save_p, players[i].finishedtime);
-		WRITEUINT32(save_p, players[i].lapbegunat);
-		WRITEUINT32(save_p, players[i].lapstartedtime);
-		WRITEINT16(save_p, players[i].finishedspheres);
-		WRITEINT16(save_p, players[i].finishedrings);
-		WRITEUINT32(save_p, players[i].marescore);
-		WRITEUINT32(save_p, players[i].lastmarescore);
-		WRITEUINT32(save_p, players[i].totalmarescore);
-		WRITEUINT8(save_p, players[i].lastmare);
-		WRITEUINT8(save_p, players[i].lastmarelap);
-		WRITEUINT8(save_p, players[i].lastmarebonuslap);
-		WRITEUINT8(save_p, players[i].totalmarelap);
-		WRITEUINT8(save_p, players[i].totalmarebonuslap);
-		WRITEINT32(save_p, players[i].maxlink);
-		WRITEUINT8(save_p, players[i].texttimer);
-		WRITEUINT8(save_p, players[i].textvar);
+		P_WriteINT32(save_p, players[i].ctfteam);
+		P_WriteUINT16(save_p, players[i].gotflag);
+
+		P_WriteINT32(save_p, players[i].weapondelay);
+		P_WriteINT32(save_p, players[i].tossdelay);
+
+		P_WriteUINT32(save_p, players[i].starposttime);
+		P_WriteINT16(save_p, players[i].starpostx);
+		P_WriteINT16(save_p, players[i].starposty);
+		P_WriteINT16(save_p, players[i].starpostz);
+		P_WriteINT32(save_p, players[i].starpostnum);
+		P_WriteAngle(save_p, players[i].starpostangle);
+		P_WriteFixed(save_p, players[i].starpostscale);
+
+		P_WriteAngle(save_p, players[i].angle_pos);
+		P_WriteAngle(save_p, players[i].old_angle_pos);
+
+		P_WriteINT32(save_p, players[i].flyangle);
+		P_WriteUINT32(save_p, players[i].drilltimer);
+		P_WriteINT32(save_p, players[i].linkcount);
+		P_WriteUINT32(save_p, players[i].linktimer);
+		P_WriteINT32(save_p, players[i].anotherflyangle);
+		P_WriteUINT32(save_p, players[i].nightstime);
+		P_WriteUINT32(save_p, players[i].bumpertime);
+		P_WriteINT32(save_p, players[i].drillmeter);
+		P_WriteUINT8(save_p, players[i].drilldelay);
+		P_WriteUINT8(save_p, players[i].bonustime);
+		P_WriteFixed(save_p, players[i].oldscale);
+		P_WriteUINT8(save_p, players[i].mare);
+		P_WriteUINT8(save_p, players[i].marelap);
+		P_WriteUINT8(save_p, players[i].marebonuslap);
+		P_WriteUINT32(save_p, players[i].marebegunat);
+		P_WriteUINT32(save_p, players[i].lastmaretime);
+		P_WriteUINT32(save_p, players[i].startedtime);
+		P_WriteUINT32(save_p, players[i].finishedtime);
+		P_WriteUINT32(save_p, players[i].lapbegunat);
+		P_WriteUINT32(save_p, players[i].lapstartedtime);
+		P_WriteINT16(save_p, players[i].finishedspheres);
+		P_WriteINT16(save_p, players[i].finishedrings);
+		P_WriteUINT32(save_p, players[i].marescore);
+		P_WriteUINT32(save_p, players[i].lastmarescore);
+		P_WriteUINT32(save_p, players[i].totalmarescore);
+		P_WriteUINT8(save_p, players[i].lastmare);
+		P_WriteUINT8(save_p, players[i].lastmarelap);
+		P_WriteUINT8(save_p, players[i].lastmarebonuslap);
+		P_WriteUINT8(save_p, players[i].totalmarelap);
+		P_WriteUINT8(save_p, players[i].totalmarebonuslap);
+		P_WriteINT32(save_p, players[i].maxlink);
+		P_WriteUINT8(save_p, players[i].texttimer);
+		P_WriteUINT8(save_p, players[i].textvar);
 
 		if (players[i].capsule)
 			flags |= CAPSULE;
@@ -299,73 +538,73 @@ static void P_NetArchivePlayers(void)
 		if (players[i].drone)
 			flags |= DRONE;
 
-		WRITEINT16(save_p, players[i].lastsidehit);
-		WRITEINT16(save_p, players[i].lastlinehit);
+		P_WriteINT16(save_p, players[i].lastsidehit);
+		P_WriteINT16(save_p, players[i].lastlinehit);
 
-		WRITEUINT32(save_p, players[i].losstime);
+		P_WriteUINT32(save_p, players[i].losstime);
 
-		WRITEUINT8(save_p, players[i].timeshit);
+		P_WriteUINT8(save_p, players[i].timeshit);
 
-		WRITEINT32(save_p, players[i].onconveyor);
+		P_WriteINT32(save_p, players[i].onconveyor);
 
-		WRITEUINT32(save_p, players[i].jointime);
-		WRITEUINT32(save_p, players[i].quittime);
+		P_WriteUINT32(save_p, players[i].jointime);
+		P_WriteUINT32(save_p, players[i].quittime);
 
-		WRITEUINT16(save_p, flags);
+		P_WriteUINT16(save_p, flags);
 
 		if (flags & CAPSULE)
-			WRITEUINT32(save_p, players[i].capsule->mobjnum);
+			P_WriteUINT32(save_p, players[i].capsule->mobjnum);
 
 		if (flags & FIRSTAXIS)
-			WRITEUINT32(save_p, players[i].axis1->mobjnum);
+			P_WriteUINT32(save_p, players[i].axis1->mobjnum);
 
 		if (flags & SECONDAXIS)
-			WRITEUINT32(save_p, players[i].axis2->mobjnum);
+			P_WriteUINT32(save_p, players[i].axis2->mobjnum);
 
 		if (flags & AWAYVIEW)
-			WRITEUINT32(save_p, players[i].awayviewmobj->mobjnum);
+			P_WriteUINT32(save_p, players[i].awayviewmobj->mobjnum);
 
 		if (flags & FOLLOW)
-			WRITEUINT32(save_p, players[i].followmobj->mobjnum);
+			P_WriteUINT32(save_p, players[i].followmobj->mobjnum);
 
 		if (flags & DRONE)
-			WRITEUINT32(save_p, players[i].drone->mobjnum);
-
-		WRITEFIXED(save_p, players[i].camerascale);
-		WRITEFIXED(save_p, players[i].shieldscale);
-
-		WRITEUINT8(save_p, players[i].charability);
-		WRITEUINT8(save_p, players[i].charability2);
-		WRITEUINT32(save_p, players[i].charflags);
-		WRITEUINT32(save_p, (UINT32)players[i].thokitem);
-		WRITEUINT32(save_p, (UINT32)players[i].spinitem);
-		WRITEUINT32(save_p, (UINT32)players[i].revitem);
-		WRITEUINT32(save_p, (UINT32)players[i].followitem);
-		WRITEFIXED(save_p, players[i].actionspd);
-		WRITEFIXED(save_p, players[i].mindash);
-		WRITEFIXED(save_p, players[i].maxdash);
-		WRITEFIXED(save_p, players[i].normalspeed);
-		WRITEFIXED(save_p, players[i].runspeed);
-		WRITEUINT8(save_p, players[i].thrustfactor);
-		WRITEUINT8(save_p, players[i].accelstart);
-		WRITEUINT8(save_p, players[i].acceleration);
-		WRITEFIXED(save_p, players[i].jumpfactor);
-		WRITEFIXED(save_p, players[i].height);
-		WRITEFIXED(save_p, players[i].spinheight);
+			P_WriteUINT32(save_p, players[i].drone->mobjnum);
+
+		P_WriteFixed(save_p, players[i].camerascale);
+		P_WriteFixed(save_p, players[i].shieldscale);
+
+		P_WriteUINT8(save_p, players[i].charability);
+		P_WriteUINT8(save_p, players[i].charability2);
+		P_WriteUINT32(save_p, players[i].charflags);
+		P_WriteUINT32(save_p, (UINT32)players[i].thokitem);
+		P_WriteUINT32(save_p, (UINT32)players[i].spinitem);
+		P_WriteUINT32(save_p, (UINT32)players[i].revitem);
+		P_WriteUINT32(save_p, (UINT32)players[i].followitem);
+		P_WriteFixed(save_p, players[i].actionspd);
+		P_WriteFixed(save_p, players[i].mindash);
+		P_WriteFixed(save_p, players[i].maxdash);
+		P_WriteFixed(save_p, players[i].normalspeed);
+		P_WriteFixed(save_p, players[i].runspeed);
+		P_WriteUINT8(save_p, players[i].thrustfactor);
+		P_WriteUINT8(save_p, players[i].accelstart);
+		P_WriteUINT8(save_p, players[i].acceleration);
+		P_WriteFixed(save_p, players[i].jumpfactor);
+		P_WriteFixed(save_p, players[i].height);
+		P_WriteFixed(save_p, players[i].spinheight);
 	}
 }
 
-static void P_NetUnArchivePlayers(void)
+static void P_NetUnArchivePlayers(save_t *save_p)
 {
 	INT32 i, j;
 	UINT16 flags;
 
-	if (READUINT32(save_p) != ARCHIVEBLOCK_PLAYERS)
+	if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_PLAYERS)
 		I_Error("Bad $$$.sav at archive block Players");
 
 	for (i = 0; i < MAXPLAYERS; i++)
 	{
-		adminplayers[i] = (INT32)READSINT8(save_p);
+		adminplayers[i] = (INT32)P_ReadSINT8(save_p);
 
 		// Do NOT memset player struct to 0
 		// other areas may initialize data elsewhere
@@ -375,198 +614,198 @@ static void P_NetUnArchivePlayers(void)
 
 		// NOTE: sending tics should (hopefully) no longer be necessary
 
-		READSTRINGN(save_p, player_names[i], MAXPLAYERNAME);
-		players[i].angleturn = READINT16(save_p);
-		players[i].oldrelangleturn = READINT16(save_p);
-		players[i].aiming = READANGLE(save_p);
-		players[i].drawangle = READANGLE(save_p);
-		players[i].viewrollangle = READANGLE(save_p);
-		players[i].awayviewaiming = READANGLE(save_p);
-		players[i].awayviewtics = READINT32(save_p);
-		players[i].rings = READINT16(save_p);
-		players[i].spheres = READINT16(save_p);
-
-		players[i].pity = READSINT8(save_p);
-		players[i].currentweapon = READINT32(save_p);
-		players[i].ringweapons = READINT32(save_p);
-
-		players[i].ammoremoval = READUINT16(save_p);
-		players[i].ammoremovaltimer = READUINT32(save_p);
-		players[i].ammoremovalweapon = READINT32(save_p);
+		P_ReadStringN(save_p, player_names[i], MAXPLAYERNAME);
+		players[i].angleturn = P_ReadINT16(save_p);
+		players[i].oldrelangleturn = P_ReadINT16(save_p);
+		players[i].aiming = P_ReadAngle(save_p);
+		players[i].drawangle = P_ReadAngle(save_p);
+		players[i].viewrollangle = P_ReadAngle(save_p);
+		players[i].awayviewaiming = P_ReadAngle(save_p);
+		players[i].awayviewtics = P_ReadINT32(save_p);
+		players[i].rings = P_ReadINT16(save_p);
+		players[i].spheres = P_ReadINT16(save_p);
+
+		players[i].pity = P_ReadSINT8(save_p);
+		players[i].currentweapon = P_ReadINT32(save_p);
+		players[i].ringweapons = P_ReadINT32(save_p);
+
+		players[i].ammoremoval = P_ReadUINT16(save_p);
+		players[i].ammoremovaltimer = P_ReadUINT32(save_p);
+		players[i].ammoremovalweapon = P_ReadINT32(save_p);
 
 		for (j = 0; j < NUMPOWERS; j++)
-			players[i].powers[j] = READUINT16(save_p);
-
-		players[i].playerstate = READUINT8(save_p);
-		players[i].pflags = READUINT32(save_p);
-		players[i].panim = READUINT8(save_p);
-		players[i].stronganim = READUINT8(save_p);
-		players[i].spectator = READUINT8(save_p);
-		players[i].muted = READUINT8(save_p);
-
-		players[i].flashpal = READUINT16(save_p);
-		players[i].flashcount = READUINT16(save_p);
-
-		players[i].skincolor = READUINT16(save_p);
-		players[i].skin = READINT32(save_p);
-		players[i].availabilities = READUINT32(save_p);
-		players[i].score = READUINT32(save_p);
-		players[i].recordscore = READUINT32(save_p);
-		players[i].dashspeed = READFIXED(save_p); // dashing speed
-		players[i].lives = READSINT8(save_p);
-		players[i].continues = READSINT8(save_p); // continues that player has acquired
-		players[i].xtralife = READSINT8(save_p); // Ring Extra Life counter
-		players[i].gotcontinue = READUINT8(save_p); // got continue from stage
-		players[i].speed = READFIXED(save_p); // Player's speed (distance formula of MOMX and MOMY values)
-		players[i].secondjump = READUINT8(save_p);
-		players[i].fly1 = READUINT8(save_p); // Tails flying
-		players[i].scoreadd = READUINT8(save_p); // Used for multiple enemy attack bonus
-		players[i].glidetime = READUINT32(save_p); // Glide counter for thrust
-		players[i].climbing = READUINT8(save_p); // Climbing on the wall
-		players[i].deadtimer = READINT32(save_p); // End game if game over lasts too long
-		players[i].exiting = READUINT32(save_p); // Exitlevel timer
-		players[i].homing = READUINT8(save_p); // Are you homing?
-		players[i].dashmode = READUINT32(save_p); // counter for dashmode ability
-		players[i].skidtime = READUINT32(save_p); // Skid timer
+			players[i].powers[j] = P_ReadUINT16(save_p);
+
+		players[i].playerstate = P_ReadUINT8(save_p);
+		players[i].pflags = P_ReadUINT32(save_p);
+		players[i].panim = P_ReadUINT8(save_p);
+		players[i].stronganim = P_ReadUINT8(save_p);
+		players[i].spectator = P_ReadUINT8(save_p);
+		players[i].muted = P_ReadUINT8(save_p);
+
+		players[i].flashpal = P_ReadUINT16(save_p);
+		players[i].flashcount = P_ReadUINT16(save_p);
+
+		players[i].skincolor = P_ReadUINT16(save_p);
+		players[i].skin = P_ReadINT32(save_p);
+		players[i].availabilities = P_ReadUINT32(save_p);
+		players[i].score = P_ReadUINT32(save_p);
+		players[i].recordscore = P_ReadUINT32(save_p);
+		players[i].dashspeed = P_ReadFixed(save_p); // dashing speed
+		players[i].lives = P_ReadSINT8(save_p);
+		players[i].continues = P_ReadSINT8(save_p); // continues that player has acquired
+		players[i].xtralife = P_ReadSINT8(save_p); // Ring Extra Life counter
+		players[i].gotcontinue = P_ReadUINT8(save_p); // got continue from stage
+		players[i].speed = P_ReadFixed(save_p); // Player's speed (distance formula of MOMX and MOMY values)
+		players[i].secondjump = P_ReadUINT8(save_p);
+		players[i].fly1 = P_ReadUINT8(save_p); // Tails flying
+		players[i].scoreadd = P_ReadUINT8(save_p); // Used for multiple enemy attack bonus
+		players[i].glidetime = P_ReadUINT32(save_p); // Glide counter for thrust
+		players[i].climbing = P_ReadUINT8(save_p); // Climbing on the wall
+		players[i].deadtimer = P_ReadINT32(save_p); // End game if game over lasts too long
+		players[i].exiting = P_ReadUINT32(save_p); // Exitlevel timer
+		players[i].homing = P_ReadUINT8(save_p); // Are you homing?
+		players[i].dashmode = P_ReadUINT32(save_p); // counter for dashmode ability
+		players[i].skidtime = P_ReadUINT32(save_p); // Skid timer
 
 		//////////
 		// Bots //
 		//////////
-		players[i].bot = READUINT8(save_p);
+		players[i].bot = P_ReadUINT8(save_p);
 
-		players[i].botmem.lastForward = READUINT8(save_p);
-		players[i].botmem.lastBlocked = READUINT8(save_p);
-		players[i].botmem.catchup_tics = READUINT8(save_p);
-		players[i].botmem.thinkstate = READUINT8(save_p);
-		players[i].removing = READUINT8(save_p);
+		players[i].botmem.lastForward = P_ReadUINT8(save_p);
+		players[i].botmem.lastBlocked = P_ReadUINT8(save_p);
+		players[i].botmem.catchup_tics = P_ReadUINT8(save_p);
+		players[i].botmem.thinkstate = P_ReadUINT8(save_p);
+		players[i].removing = P_ReadUINT8(save_p);
 
-		players[i].blocked = READUINT8(save_p);
-		players[i].lastbuttons = READUINT16(save_p);
+		players[i].blocked = P_ReadUINT8(save_p);
+		players[i].lastbuttons = P_ReadUINT16(save_p);
 
 		////////////////////////////
 		// Conveyor Belt Movement //
 		////////////////////////////
-		players[i].cmomx = READFIXED(save_p); // Conveyor momx
-		players[i].cmomy = READFIXED(save_p); // Conveyor momy
-		players[i].rmomx = READFIXED(save_p); // "Real" momx (momx - cmomx)
-		players[i].rmomy = READFIXED(save_p); // "Real" momy (momy - cmomy)
+		players[i].cmomx = P_ReadFixed(save_p); // Conveyor momx
+		players[i].cmomy = P_ReadFixed(save_p); // Conveyor momy
+		players[i].rmomx = P_ReadFixed(save_p); // "Real" momx (momx - cmomx)
+		players[i].rmomy = P_ReadFixed(save_p); // "Real" momy (momy - cmomy)
 
 		/////////////////////
 		// Race Mode Stuff //
 		/////////////////////
-		players[i].numboxes = READINT16(save_p); // Number of item boxes obtained for Race Mode
-		players[i].totalring = READINT16(save_p); // Total number of rings obtained for Race Mode
-		players[i].realtime = READUINT32(save_p); // integer replacement for leveltime
-		players[i].laps = READUINT8(save_p); // Number of laps (optional)
+		players[i].numboxes = P_ReadINT16(save_p); // Number of item boxes obtained for Race Mode
+		players[i].totalring = P_ReadINT16(save_p); // Total number of rings obtained for Race Mode
+		players[i].realtime = P_ReadUINT32(save_p); // integer replacement for leveltime
+		players[i].laps = P_ReadUINT8(save_p); // Number of laps (optional)
 
 		////////////////////
 		// CTF Mode Stuff //
 		////////////////////
-		players[i].ctfteam = READINT32(save_p); // 1 == Red, 2 == Blue
-		players[i].gotflag = READUINT16(save_p); // 1 == Red, 2 == Blue Do you have the flag?
-
-		players[i].weapondelay = READINT32(save_p);
-		players[i].tossdelay = READINT32(save_p);
-
-		players[i].starposttime = READUINT32(save_p);
-		players[i].starpostx = READINT16(save_p);
-		players[i].starposty = READINT16(save_p);
-		players[i].starpostz = READINT16(save_p);
-		players[i].starpostnum = READINT32(save_p);
-		players[i].starpostangle = READANGLE(save_p);
-		players[i].starpostscale = READFIXED(save_p);
-
-		players[i].angle_pos = READANGLE(save_p);
-		players[i].old_angle_pos = READANGLE(save_p);
-
-		players[i].flyangle = READINT32(save_p);
-		players[i].drilltimer = READUINT32(save_p);
-		players[i].linkcount = READINT32(save_p);
-		players[i].linktimer = READUINT32(save_p);
-		players[i].anotherflyangle = READINT32(save_p);
-		players[i].nightstime = READUINT32(save_p);
-		players[i].bumpertime = READUINT32(save_p);
-		players[i].drillmeter = READINT32(save_p);
-		players[i].drilldelay = READUINT8(save_p);
-		players[i].bonustime = (boolean)READUINT8(save_p);
-		players[i].oldscale = READFIXED(save_p);
-		players[i].mare = READUINT8(save_p);
-		players[i].marelap = READUINT8(save_p);
-		players[i].marebonuslap = READUINT8(save_p);
-		players[i].marebegunat = READUINT32(save_p);
-		players[i].lastmaretime = READUINT32(save_p);
-		players[i].startedtime = READUINT32(save_p);
-		players[i].finishedtime = READUINT32(save_p);
-		players[i].lapbegunat = READUINT32(save_p);
-		players[i].lapstartedtime = READUINT32(save_p);
-		players[i].finishedspheres = READINT16(save_p);
-		players[i].finishedrings = READINT16(save_p);
-		players[i].marescore = READUINT32(save_p);
-		players[i].lastmarescore = READUINT32(save_p);
-		players[i].totalmarescore = READUINT32(save_p);
-		players[i].lastmare = READUINT8(save_p);
-		players[i].lastmarelap = READUINT8(save_p);
-		players[i].lastmarebonuslap = READUINT8(save_p);
-		players[i].totalmarelap = READUINT8(save_p);
-		players[i].totalmarebonuslap = READUINT8(save_p);
-		players[i].maxlink = READINT32(save_p);
-		players[i].texttimer = READUINT8(save_p);
-		players[i].textvar = READUINT8(save_p);
-
-		players[i].lastsidehit = READINT16(save_p);
-		players[i].lastlinehit = READINT16(save_p);
-
-		players[i].losstime = READUINT32(save_p);
-
-		players[i].timeshit = READUINT8(save_p);
-
-		players[i].onconveyor = READINT32(save_p);
-
-		players[i].jointime = READUINT32(save_p);
-		players[i].quittime = READUINT32(save_p);
-
-		flags = READUINT16(save_p);
+		players[i].ctfteam = P_ReadINT32(save_p); // 1 == Red, 2 == Blue
+		players[i].gotflag = P_ReadUINT16(save_p); // 1 == Red, 2 == Blue Do you have the flag?
+
+		players[i].weapondelay = P_ReadINT32(save_p);
+		players[i].tossdelay = P_ReadINT32(save_p);
+
+		players[i].starposttime = P_ReadUINT32(save_p);
+		players[i].starpostx = P_ReadINT16(save_p);
+		players[i].starposty = P_ReadINT16(save_p);
+		players[i].starpostz = P_ReadINT16(save_p);
+		players[i].starpostnum = P_ReadINT32(save_p);
+		players[i].starpostangle = P_ReadAngle(save_p);
+		players[i].starpostscale = P_ReadFixed(save_p);
+
+		players[i].angle_pos = P_ReadAngle(save_p);
+		players[i].old_angle_pos = P_ReadAngle(save_p);
+
+		players[i].flyangle = P_ReadINT32(save_p);
+		players[i].drilltimer = P_ReadUINT32(save_p);
+		players[i].linkcount = P_ReadINT32(save_p);
+		players[i].linktimer = P_ReadUINT32(save_p);
+		players[i].anotherflyangle = P_ReadINT32(save_p);
+		players[i].nightstime = P_ReadUINT32(save_p);
+		players[i].bumpertime = P_ReadUINT32(save_p);
+		players[i].drillmeter = P_ReadINT32(save_p);
+		players[i].drilldelay = P_ReadUINT8(save_p);
+		players[i].bonustime = (boolean)P_ReadUINT8(save_p);
+		players[i].oldscale = P_ReadFixed(save_p);
+		players[i].mare = P_ReadUINT8(save_p);
+		players[i].marelap = P_ReadUINT8(save_p);
+		players[i].marebonuslap = P_ReadUINT8(save_p);
+		players[i].marebegunat = P_ReadUINT32(save_p);
+		players[i].lastmaretime = P_ReadUINT32(save_p);
+		players[i].startedtime = P_ReadUINT32(save_p);
+		players[i].finishedtime = P_ReadUINT32(save_p);
+		players[i].lapbegunat = P_ReadUINT32(save_p);
+		players[i].lapstartedtime = P_ReadUINT32(save_p);
+		players[i].finishedspheres = P_ReadINT16(save_p);
+		players[i].finishedrings = P_ReadINT16(save_p);
+		players[i].marescore = P_ReadUINT32(save_p);
+		players[i].lastmarescore = P_ReadUINT32(save_p);
+		players[i].totalmarescore = P_ReadUINT32(save_p);
+		players[i].lastmare = P_ReadUINT8(save_p);
+		players[i].lastmarelap = P_ReadUINT8(save_p);
+		players[i].lastmarebonuslap = P_ReadUINT8(save_p);
+		players[i].totalmarelap = P_ReadUINT8(save_p);
+		players[i].totalmarebonuslap = P_ReadUINT8(save_p);
+		players[i].maxlink = P_ReadINT32(save_p);
+		players[i].texttimer = P_ReadUINT8(save_p);
+		players[i].textvar = P_ReadUINT8(save_p);
+
+		players[i].lastsidehit = P_ReadINT16(save_p);
+		players[i].lastlinehit = P_ReadINT16(save_p);
+
+		players[i].losstime = P_ReadUINT32(save_p);
+
+		players[i].timeshit = P_ReadUINT8(save_p);
+
+		players[i].onconveyor = P_ReadINT32(save_p);
+
+		players[i].jointime = P_ReadUINT32(save_p);
+		players[i].quittime = P_ReadUINT32(save_p);
+
+		flags = P_ReadUINT16(save_p);
 
 		if (flags & CAPSULE)
-			players[i].capsule = (mobj_t *)(size_t)READUINT32(save_p);
+			players[i].capsule = (mobj_t *)(size_t)P_ReadUINT32(save_p);
 
 		if (flags & FIRSTAXIS)
-			players[i].axis1 = (mobj_t *)(size_t)READUINT32(save_p);
+			players[i].axis1 = (mobj_t *)(size_t)P_ReadUINT32(save_p);
 
 		if (flags & SECONDAXIS)
-			players[i].axis2 = (mobj_t *)(size_t)READUINT32(save_p);
+			players[i].axis2 = (mobj_t *)(size_t)P_ReadUINT32(save_p);
 
 		if (flags & AWAYVIEW)
-			players[i].awayviewmobj = (mobj_t *)(size_t)READUINT32(save_p);
+			players[i].awayviewmobj = (mobj_t *)(size_t)P_ReadUINT32(save_p);
 
 		if (flags & FOLLOW)
-			players[i].followmobj = (mobj_t *)(size_t)READUINT32(save_p);
+			players[i].followmobj = (mobj_t *)(size_t)P_ReadUINT32(save_p);
 
 		if (flags & DRONE)
-			players[i].drone = (mobj_t *)(size_t)READUINT32(save_p);
+			players[i].drone = (mobj_t *)(size_t)P_ReadUINT32(save_p);
 
-		players[i].camerascale = READFIXED(save_p);
-		players[i].shieldscale = READFIXED(save_p);
+		players[i].camerascale = P_ReadFixed(save_p);
+		players[i].shieldscale = P_ReadFixed(save_p);
 
 		//SetPlayerSkinByNum(i, players[i].skin);
-		players[i].charability = READUINT8(save_p);
-		players[i].charability2 = READUINT8(save_p);
-		players[i].charflags = READUINT32(save_p);
-		players[i].thokitem = (mobjtype_t)READUINT32(save_p);
-		players[i].spinitem = (mobjtype_t)READUINT32(save_p);
-		players[i].revitem = (mobjtype_t)READUINT32(save_p);
-		players[i].followitem = (mobjtype_t)READUINT32(save_p);
-		players[i].actionspd = READFIXED(save_p);
-		players[i].mindash = READFIXED(save_p);
-		players[i].maxdash = READFIXED(save_p);
-		players[i].normalspeed = READFIXED(save_p);
-		players[i].runspeed = READFIXED(save_p);
-		players[i].thrustfactor = READUINT8(save_p);
-		players[i].accelstart = READUINT8(save_p);
-		players[i].acceleration = READUINT8(save_p);
-		players[i].jumpfactor = READFIXED(save_p);
-		players[i].height = READFIXED(save_p);
-		players[i].spinheight = READFIXED(save_p);
+		players[i].charability = P_ReadUINT8(save_p);
+		players[i].charability2 = P_ReadUINT8(save_p);
+		players[i].charflags = P_ReadUINT32(save_p);
+		players[i].thokitem = P_ReadUINT32(save_p);
+		players[i].spinitem = P_ReadUINT32(save_p);
+		players[i].revitem = P_ReadUINT32(save_p);
+		players[i].followitem = P_ReadUINT32(save_p);
+		players[i].actionspd = P_ReadFixed(save_p);
+		players[i].mindash = P_ReadFixed(save_p);
+		players[i].maxdash = P_ReadFixed(save_p);
+		players[i].normalspeed = P_ReadFixed(save_p);
+		players[i].runspeed = P_ReadFixed(save_p);
+		players[i].thrustfactor = P_ReadUINT8(save_p);
+		players[i].accelstart = P_ReadUINT8(save_p);
+		players[i].acceleration = P_ReadUINT8(save_p);
+		players[i].jumpfactor = P_ReadFixed(save_p);
+		players[i].height = P_ReadFixed(save_p);
+		players[i].spinheight = P_ReadFixed(save_p);
 
 		players[i].viewheight = 41*players[i].height/48; // scale cannot be factored in at this point
 	}
@@ -669,12 +908,12 @@ static void ClearNetColormaps(void)
 	net_colormaps = NULL;
 }
 
-static void P_NetArchiveColormaps(void)
+static void P_NetArchiveColormaps(save_t *save_p)
 {
 	// We save and then we clean up our colormap mess
 	extracolormap_t *exc, *exc_next;
 	UINT32 i = 0;
-	WRITEUINT32(save_p, num_net_colormaps); // save for safety
+	P_WriteUINT32(save_p, num_net_colormaps); // save for safety
 
 	for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next)
 	{
@@ -683,15 +922,15 @@ static void P_NetArchiveColormaps(void)
 		if (!exc)
 			exc = R_CreateDefaultColormap(false);
 
-		WRITEUINT8(save_p, exc->fadestart);
-		WRITEUINT8(save_p, exc->fadeend);
-		WRITEUINT8(save_p, exc->flags);
+		P_WriteUINT8(save_p, exc->fadestart);
+		P_WriteUINT8(save_p, exc->fadeend);
+		P_WriteUINT8(save_p, exc->flags);
 
-		WRITEINT32(save_p, exc->rgba);
-		WRITEINT32(save_p, exc->fadergba);
+		P_WriteINT32(save_p, exc->rgba);
+		P_WriteINT32(save_p, exc->fadergba);
 
 #ifdef EXTRACOLORMAPLUMPS
-		WRITESTRINGN(save_p, exc->lumpname, 9);
+		P_WriteStringN(save_p, exc->lumpname, 9);
 #endif
 
 		exc_next = exc->next;
@@ -703,7 +942,7 @@ static void P_NetArchiveColormaps(void)
 	net_colormaps = NULL;
 }
 
-static void P_NetUnArchiveColormaps(void)
+static void P_NetUnArchiveColormaps(save_t *save_p)
 {
 	// When we reach this point, we already populated our list with
 	// dummy colormaps. Now that we are loading the color data,
@@ -711,7 +950,7 @@ static void P_NetUnArchiveColormaps(void)
 	extracolormap_t *exc, *existing_exc, *exc_next = NULL;
 	UINT32 i = 0;
 
-	num_net_colormaps = READUINT32(save_p);
+	num_net_colormaps = P_ReadUINT32(save_p);
 
 	for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next)
 	{
@@ -721,15 +960,15 @@ static void P_NetUnArchiveColormaps(void)
 		char lumpname[9];
 #endif
 
-		fadestart = READUINT8(save_p);
-		fadeend = READUINT8(save_p);
-		flags = READUINT8(save_p);
+		fadestart = P_ReadUINT8(save_p);
+		fadeend = P_ReadUINT8(save_p);
+		flags = P_ReadUINT8(save_p);
 
-		rgba = READINT32(save_p);
-		fadergba = READINT32(save_p);
+		rgba = P_ReadINT32(save_p);
+		fadergba = P_ReadINT32(save_p);
 
 #ifdef EXTRACOLORMAPLUMPS
-		READSTRINGN(save_p, lumpname, 9);
+		P_ReadStringN(save_p, lumpname, 9);
 
 		if (lumpname[0])
 		{
@@ -805,29 +1044,29 @@ static void P_NetUnArchiveColormaps(void)
 	net_colormaps = NULL;
 }
 
-static void P_NetArchiveWaypoints(void)
+static void P_NetArchiveWaypoints(save_t *save_p)
 {
 	INT32 i, j;
 
 	for (i = 0; i < NUMWAYPOINTSEQUENCES; i++)
 	{
-		WRITEUINT16(save_p, numwaypoints[i]);
+		P_WriteUINT16(save_p, numwaypoints[i]);
 		for (j = 0; j < numwaypoints[i]; j++)
-			WRITEUINT32(save_p, waypoints[i][j] ? waypoints[i][j]->mobjnum : 0);
+			P_WriteUINT32(save_p, waypoints[i][j] ? waypoints[i][j]->mobjnum : 0);
 	}
 }
 
-static void P_NetUnArchiveWaypoints(void)
+static void P_NetUnArchiveWaypoints(save_t *save_p)
 {
 	INT32 i, j;
 	UINT32 mobjnum;
 
 	for (i = 0; i < NUMWAYPOINTSEQUENCES; i++)
 	{
-		numwaypoints[i] = READUINT16(save_p);
+		numwaypoints[i] = P_ReadUINT16(save_p);
 		for (j = 0; j < numwaypoints[i]; j++)
 		{
-			mobjnum = READUINT32(save_p);
+			mobjnum = P_ReadUINT32(save_p);
 			waypoints[i][j] = (mobjnum == 0) ? NULL : P_FindNewPosition(mobjnum);
 		}
 	}
@@ -974,7 +1213,7 @@ static boolean CheckFFloorDiff(const sector_t *ss)
 
 // Special case: save the stats of all modified ffloors along with their ffloor "number"s
 // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed
-static void ArchiveFFloors(const sector_t *ss)
+static void ArchiveFFloors(save_t *save_p, const sector_t *ss)
 {
 	size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc
 	ffloor_t *rover;
@@ -989,19 +1228,19 @@ static void ArchiveFFloors(const sector_t *ss)
 
 		if (fflr_diff)
 		{
-			WRITEUINT16(save_p, j); // save ffloor "number"
-			WRITEUINT8(save_p, fflr_diff);
+			P_WriteUINT16(save_p, j); // save ffloor "number"
+			P_WriteUINT8(save_p, fflr_diff);
 			if (fflr_diff & FD_FLAGS)
-				WRITEUINT32(save_p, rover->fofflags);
+				P_WriteUINT32(save_p, rover->fofflags);
 			if (fflr_diff & FD_ALPHA)
-				WRITEINT16(save_p, rover->alpha);
+				P_WriteINT16(save_p, rover->alpha);
 		}
 		j++;
 	}
-	WRITEUINT16(save_p, 0xffff);
+	P_WriteUINT16(save_p, 0xffff);
 }
 
-static void UnArchiveFFloors(const sector_t *ss)
+static void UnArchiveFFloors(save_t *save_p, const sector_t *ss)
 {
 	UINT16 j = 0; // number of current ffloor in loop
 	UINT16 fflr_i; // saved ffloor "number" of next modified ffloor
@@ -1012,7 +1251,7 @@ static void UnArchiveFFloors(const sector_t *ss)
 	if (!rover) // it is assumed sectors[i].ffloors actually exists, but just in case...
 		I_Error("Sector does not have any ffloors!");
 
-	fflr_i = READUINT16(save_p); // get first modified ffloor's number ready
+	fflr_i = P_ReadUINT16(save_p); // get first modified ffloor's number ready
 	for (;;) // for some reason the usual for (rover = x; ...) thing doesn't work here?
 	{
 		if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already
@@ -1027,21 +1266,21 @@ static void UnArchiveFFloors(const sector_t *ss)
 			continue;
 		}
 
-		fflr_diff = READUINT8(save_p);
+		fflr_diff = P_ReadUINT8(save_p);
 
 		if (fflr_diff & FD_FLAGS)
-			rover->fofflags = READUINT32(save_p);
+			rover->fofflags = P_ReadUINT32(save_p);
 		if (fflr_diff & FD_ALPHA)
-			rover->alpha = READINT16(save_p);
+			rover->alpha = P_ReadINT16(save_p);
 
-		fflr_i = READUINT16(save_p); // get next ffloor "number" ready
+		fflr_i = P_ReadUINT16(save_p); // get next ffloor "number" ready
 
 		j++;
 		rover = rover->next;
 	}
 }
 
-static void ArchiveSectors(void)
+static void ArchiveSectors(save_t *save_p)
 {
 	size_t i, j;
 	const sector_t *ss = sectors;
@@ -1135,102 +1374,102 @@ static void ArchiveSectors(void)
 
 		if (diff)
 		{
-			WRITEUINT32(save_p, i);
-			WRITEUINT8(save_p, diff);
+			P_WriteUINT32(save_p, i);
+			P_WriteUINT8(save_p, diff);
 			if (diff & SD_DIFF2)
-				WRITEUINT8(save_p, diff2);
+				P_WriteUINT8(save_p, diff2);
 			if (diff2 & SD_DIFF3)
-				WRITEUINT8(save_p, diff3);
+				P_WriteUINT8(save_p, diff3);
 			if (diff3 & SD_DIFF4)
-				WRITEUINT8(save_p, diff4);
+				P_WriteUINT8(save_p, diff4);
 			if (diff4 & SD_DIFF5)
-				WRITEUINT8(save_p, diff5);
+				P_WriteUINT8(save_p, diff5);
 			if (diff & SD_FLOORHT)
-				WRITEFIXED(save_p, ss->floorheight);
+				P_WriteFixed(save_p, ss->floorheight);
 			if (diff & SD_CEILHT)
-				WRITEFIXED(save_p, ss->ceilingheight);
+				P_WriteFixed(save_p, ss->ceilingheight);
 			if (diff & SD_FLOORPIC)
-				WRITEMEM(save_p, levelflats[ss->floorpic].name, 8);
+				P_WriteMem(save_p, levelflats[ss->floorpic].name, 8);
 			if (diff & SD_CEILPIC)
-				WRITEMEM(save_p, levelflats[ss->ceilingpic].name, 8);
+				P_WriteMem(save_p, levelflats[ss->ceilingpic].name, 8);
 			if (diff & SD_LIGHT)
-				WRITEINT16(save_p, ss->lightlevel);
+				P_WriteINT16(save_p, ss->lightlevel);
 			if (diff & SD_SPECIAL)
-				WRITEINT16(save_p, ss->special);
+				P_WriteINT16(save_p, ss->special);
 			if (diff2 & SD_FXOFFS)
-				WRITEFIXED(save_p, ss->floorxoffset);
+				P_WriteFixed(save_p, ss->floorxoffset);
 			if (diff2 & SD_FYOFFS)
-				WRITEFIXED(save_p, ss->flooryoffset);
+				P_WriteFixed(save_p, ss->flooryoffset);
 			if (diff2 & SD_CXOFFS)
-				WRITEFIXED(save_p, ss->ceilingxoffset);
+				P_WriteFixed(save_p, ss->ceilingxoffset);
 			if (diff2 & SD_CYOFFS)
-				WRITEFIXED(save_p, ss->ceilingyoffset);
+				P_WriteFixed(save_p, ss->ceilingyoffset);
 			if (diff2 & SD_FLOORANG)
-				WRITEANGLE(save_p, ss->floorangle);
+				P_WriteAngle(save_p, ss->floorangle);
 			if (diff2 & SD_CEILANG)
-				WRITEANGLE(save_p, ss->ceilingangle);
+				P_WriteAngle(save_p, ss->ceilingangle);
 			if (diff2 & SD_TAG)
 			{
-				WRITEUINT32(save_p, ss->tags.count);
+				P_WriteUINT32(save_p, ss->tags.count);
 				for (j = 0; j < ss->tags.count; j++)
-					WRITEINT16(save_p, ss->tags.tags[j]);
+					P_WriteINT16(save_p, ss->tags.tags[j]);
 			}
 
 			if (diff3 & SD_COLORMAP)
-				WRITEUINT32(save_p, CheckAddNetColormapToList(ss->extra_colormap));
+				P_WriteUINT32(save_p, CheckAddNetColormapToList(ss->extra_colormap));
 					// returns existing index if already added, or appends to net_colormaps and returns new index
 			if (diff3 & SD_CRUMBLESTATE)
-				WRITEINT32(save_p, ss->crumblestate);
+				P_WriteINT32(save_p, ss->crumblestate);
 			if (diff3 & SD_FLOORLIGHT)
 			{
-				WRITEINT16(save_p, ss->floorlightlevel);
-				WRITEUINT8(save_p, ss->floorlightabsolute);
+				P_WriteINT16(save_p, ss->floorlightlevel);
+				P_WriteUINT8(save_p, ss->floorlightabsolute);
 			}
 			if (diff3 & SD_CEILLIGHT)
 			{
-				WRITEINT16(save_p, ss->ceilinglightlevel);
-				WRITEUINT8(save_p, ss->ceilinglightabsolute);
+				P_WriteINT16(save_p, ss->ceilinglightlevel);
+				P_WriteUINT8(save_p, ss->ceilinglightabsolute);
 			}
 			if (diff3 & SD_FLAG)
-				WRITEUINT32(save_p, ss->flags);
+				P_WriteUINT32(save_p, ss->flags);
 			if (diff3 & SD_SPECIALFLAG)
-				WRITEUINT32(save_p, ss->specialflags);
+				P_WriteUINT32(save_p, ss->specialflags);
 			if (diff4 & SD_DAMAGETYPE)
-				WRITEUINT8(save_p, ss->damagetype);
+				P_WriteUINT8(save_p, ss->damagetype);
 			if (diff4 & SD_TRIGGERTAG)
-				WRITEINT16(save_p, ss->triggertag);
+				P_WriteINT16(save_p, ss->triggertag);
 			if (diff4 & SD_TRIGGERER)
-				WRITEUINT8(save_p, ss->triggerer);
+				P_WriteUINT8(save_p, ss->triggerer);
 			if (diff4 & SD_FXSCALE)
-				WRITEFIXED(save_p, ss->floorxscale);
+				P_WriteFixed(save_p, ss->floorxscale);
 			if (diff4 & SD_FYSCALE)
-				WRITEFIXED(save_p, ss->flooryscale);
+				P_WriteFixed(save_p, ss->flooryscale);
 			if (diff4 & SD_CXSCALE)
-				WRITEFIXED(save_p, ss->ceilingxscale);
+				P_WriteFixed(save_p, ss->ceilingxscale);
 			if (diff4 & SD_CYSCALE)
-				WRITEFIXED(save_p, ss->ceilingyscale);
+				P_WriteFixed(save_p, ss->ceilingyscale);
 			if (diff5 & SD_GRAVITY)
-				WRITEFIXED(save_p, ss->gravity);
+				P_WriteFixed(save_p, ss->gravity);
 			if (diff5 & SD_FLOORPORTAL)
-				WRITEUINT32(save_p, ss->portal_floor);
+				P_WriteUINT32(save_p, ss->portal_floor);
 			if (diff5 & SD_CEILPORTAL)
-				WRITEUINT32(save_p, ss->portal_ceiling);
+				P_WriteUINT32(save_p, ss->portal_ceiling);
 			if (diff & SD_FFLOORS)
-				ArchiveFFloors(ss);
+				ArchiveFFloors(save_p, ss);
 		}
 	}
 
-	WRITEUINT32(save_p, 0xffffffff);
+	P_WriteUINT32(save_p, 0xffffffff);
 }
 
-static void UnArchiveSectors(void)
+static void UnArchiveSectors(save_t *save_p)
 {
 	UINT32 i;
 	UINT16 j;
 	UINT8 diff, diff2, diff3, diff4, diff5;
 	for (;;)
 	{
-		i = READUINT32(save_p);
+		i = P_ReadUINT32(save_p);
 
 		if (i == 0xffffffff)
 			break;
@@ -1238,28 +1477,28 @@ static void UnArchiveSectors(void)
 		if (i > numsectors)
 			I_Error("Invalid sector number %u from server (expected end at %s)", i, sizeu1(numsectors));
 
-		diff = READUINT8(save_p);
+		diff = P_ReadUINT8(save_p);
 		if (diff & SD_DIFF2)
-			diff2 = READUINT8(save_p);
+			diff2 = P_ReadUINT8(save_p);
 		else
 			diff2 = 0;
 		if (diff2 & SD_DIFF3)
-			diff3 = READUINT8(save_p);
+			diff3 = P_ReadUINT8(save_p);
 		else
 			diff3 = 0;
 		if (diff3 & SD_DIFF4)
-			diff4 = READUINT8(save_p);
+			diff4 = P_ReadUINT8(save_p);
 		else
 			diff4 = 0;
 		if (diff4 & SD_DIFF5)
-			diff5 = READUINT8(save_p);
+			diff5 = P_ReadUINT8(save_p);
 		else
 			diff5 = 0;
 
 		if (diff & SD_FLOORHT)
-			sectors[i].floorheight = READFIXED(save_p);
+			sectors[i].floorheight = P_ReadFixed(save_p);
 		if (diff & SD_CEILHT)
-			sectors[i].ceilingheight = READFIXED(save_p);
+			sectors[i].ceilingheight = P_ReadFixed(save_p);
 		if (diff & SD_FLOORPIC)
 		{
 			sectors[i].floorpic = P_AddLevelFlatRuntime((char *)save_p);
@@ -1271,25 +1510,25 @@ static void UnArchiveSectors(void)
 			save_p += 8;
 		}
 		if (diff & SD_LIGHT)
-			sectors[i].lightlevel = READINT16(save_p);
+			sectors[i].lightlevel = P_ReadINT16(save_p);
 		if (diff & SD_SPECIAL)
-			sectors[i].special = READINT16(save_p);
+			sectors[i].special = P_ReadINT16(save_p);
 
 		if (diff2 & SD_FXOFFS)
-			sectors[i].floorxoffset = READFIXED(save_p);
+			sectors[i].floorxoffset = P_ReadFixed(save_p);
 		if (diff2 & SD_FYOFFS)
-			sectors[i].flooryoffset = READFIXED(save_p);
+			sectors[i].flooryoffset = P_ReadFixed(save_p);
 		if (diff2 & SD_CXOFFS)
-			sectors[i].ceilingxoffset = READFIXED(save_p);
+			sectors[i].ceilingxoffset = P_ReadFixed(save_p);
 		if (diff2 & SD_CYOFFS)
-			sectors[i].ceilingyoffset = READFIXED(save_p);
+			sectors[i].ceilingyoffset = P_ReadFixed(save_p);
 		if (diff2 & SD_FLOORANG)
-			sectors[i].floorangle  = READANGLE(save_p);
+			sectors[i].floorangle  = P_ReadAngle(save_p);
 		if (diff2 & SD_CEILANG)
-			sectors[i].ceilingangle = READANGLE(save_p);
+			sectors[i].ceilingangle = P_ReadAngle(save_p);
 		if (diff2 & SD_TAG)
 		{
-			size_t ncount = READUINT32(save_p);
+			size_t ncount = P_ReadUINT32(save_p);
 
 			// Remove entries from global lists.
 			for (j = 0; j < sectors[i].tags.count; j++)
@@ -1303,7 +1542,7 @@ static void UnArchiveSectors(void)
 			}
 
 			for (j = 0; j < ncount; j++)
-				sectors[i].tags.tags[j] = READINT16(save_p);
+				sectors[i].tags.tags[j] = P_ReadINT16(save_p);
 
 			// Add new entries.
 			for (j = 0; j < sectors[i].tags.count; j++)
@@ -1312,49 +1551,49 @@ static void UnArchiveSectors(void)
 
 
 		if (diff3 & SD_COLORMAP)
-			sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p));
+			sectors[i].extra_colormap = GetNetColormapFromList(P_ReadUINT32(save_p));
 		if (diff3 & SD_CRUMBLESTATE)
-			sectors[i].crumblestate = READINT32(save_p);
+			sectors[i].crumblestate = P_ReadINT32(save_p);
 		if (diff3 & SD_FLOORLIGHT)
 		{
-			sectors[i].floorlightlevel = READINT16(save_p);
-			sectors[i].floorlightabsolute = READUINT8(save_p);
+			sectors[i].floorlightlevel = P_ReadINT16(save_p);
+			sectors[i].floorlightabsolute = P_ReadUINT8(save_p);
 		}
 		if (diff3 & SD_CEILLIGHT)
 		{
-			sectors[i].ceilinglightlevel = READINT16(save_p);
-			sectors[i].ceilinglightabsolute = READUINT8(save_p);
+			sectors[i].ceilinglightlevel = P_ReadINT16(save_p);
+			sectors[i].ceilinglightabsolute = P_ReadUINT8(save_p);
 		}
 		if (diff3 & SD_FLAG)
 		{
-			sectors[i].flags = READUINT32(save_p);
+			sectors[i].flags = P_ReadUINT32(save_p);
 			CheckForReverseGravity |= (sectors[i].flags & MSF_GRAVITYFLIP);
 		}
 		if (diff3 & SD_SPECIALFLAG)
-			sectors[i].specialflags = READUINT32(save_p);
+			sectors[i].specialflags = P_ReadUINT32(save_p);
 		if (diff4 & SD_DAMAGETYPE)
-			sectors[i].damagetype = READUINT8(save_p);
+			sectors[i].damagetype = P_ReadUINT8(save_p);
 		if (diff4 & SD_TRIGGERTAG)
-			sectors[i].triggertag = READINT16(save_p);
+			sectors[i].triggertag = P_ReadINT16(save_p);
 		if (diff4 & SD_TRIGGERER)
-			sectors[i].triggerer = READUINT8(save_p);
+			sectors[i].triggerer = P_ReadUINT8(save_p);
 		if (diff4 & SD_FXSCALE)
-			sectors[i].floorxscale = READFIXED(save_p);
+			sectors[i].floorxscale = P_ReadFixed(save_p);
 		if (diff4 & SD_FYSCALE)
-			sectors[i].flooryscale = READFIXED(save_p);
+			sectors[i].flooryscale = P_ReadFixed(save_p);
 		if (diff4 & SD_CXSCALE)
-			sectors[i].ceilingxscale = READFIXED(save_p);
+			sectors[i].ceilingxscale = P_ReadFixed(save_p);
 		if (diff4 & SD_CYSCALE)
-			sectors[i].ceilingyscale = READFIXED(save_p);
+			sectors[i].ceilingyscale = P_ReadFixed(save_p);
 		if (diff5 & SD_GRAVITY)
-			sectors[i].gravity = READFIXED(save_p);
+			sectors[i].gravity = P_ReadFixed(save_p);
 		if (diff5 & SD_FLOORPORTAL)
-			sectors[i].portal_floor = READUINT32(save_p);
+			sectors[i].portal_floor = P_ReadUINT32(save_p);
 		if (diff5 & SD_CEILPORTAL)
-			sectors[i].portal_ceiling = READUINT32(save_p);
+			sectors[i].portal_ceiling = P_ReadUINT32(save_p);
 
 		if (diff & SD_FFLOORS)
-			UnArchiveFFloors(&sectors[i]);
+			UnArchiveFFloors(save_p, &sectors[i]);
 	}
 }
 
@@ -1417,65 +1656,65 @@ static UINT32 GetSideDiff(const side_t *si, const side_t *spawnsi)
 	return diff;
 }
 
-static void ArchiveSide(const side_t *si, UINT32 diff)
+static void ArchiveSide(save_t *save_p, const side_t *si, UINT32 diff)
 {
-	WRITEUINT32(save_p, diff);
+	P_WriteUINT32(save_p, diff);
 
 	if (diff & LD_SDTEXOFFX)
-		WRITEFIXED(save_p, si->textureoffset);
+		P_WriteFixed(save_p, si->textureoffset);
 	if (diff & LD_SDTEXOFFY)
-		WRITEFIXED(save_p, si->rowoffset);
+		P_WriteFixed(save_p, si->rowoffset);
 	if (diff & LD_SDTOPTEX)
-		WRITEINT32(save_p, si->toptexture);
+		P_WriteINT32(save_p, si->toptexture);
 	if (diff & LD_SDBOTTEX)
-		WRITEINT32(save_p, si->bottomtexture);
+		P_WriteINT32(save_p, si->bottomtexture);
 	if (diff & LD_SDMIDTEX)
-		WRITEINT32(save_p, si->midtexture);
+		P_WriteINT32(save_p, si->midtexture);
 	if (diff & LD_SDTOPOFFX)
-		WRITEFIXED(save_p, si->offsetx_top);
+		P_WriteFixed(save_p, si->offsetx_top);
 	if (diff & LD_SDMIDOFFX)
-		WRITEFIXED(save_p, si->offsetx_mid);
+		P_WriteFixed(save_p, si->offsetx_mid);
 	if (diff & LD_SDBOTOFFX)
-		WRITEFIXED(save_p, si->offsetx_bottom);
+		P_WriteFixed(save_p, si->offsetx_bottom);
 	if (diff & LD_SDTOPOFFY)
-		WRITEFIXED(save_p, si->offsety_top);
+		P_WriteFixed(save_p, si->offsety_top);
 	if (diff & LD_SDMIDOFFY)
-		WRITEFIXED(save_p, si->offsety_mid);
+		P_WriteFixed(save_p, si->offsety_mid);
 	if (diff & LD_SDBOTOFFY)
-		WRITEFIXED(save_p, si->offsety_bottom);
+		P_WriteFixed(save_p, si->offsety_bottom);
 	if (diff & LD_SDTOPSCALEX)
-		WRITEFIXED(save_p, si->scalex_top);
+		P_WriteFixed(save_p, si->scalex_top);
 	if (diff & LD_SDMIDSCALEX)
-		WRITEFIXED(save_p, si->scalex_mid);
+		P_WriteFixed(save_p, si->scalex_mid);
 	if (diff & LD_SDBOTSCALEX)
-		WRITEFIXED(save_p, si->scalex_bottom);
+		P_WriteFixed(save_p, si->scalex_bottom);
 	if (diff & LD_SDTOPSCALEY)
-		WRITEFIXED(save_p, si->scaley_top);
+		P_WriteFixed(save_p, si->scaley_top);
 	if (diff & LD_SDMIDSCALEY)
-		WRITEFIXED(save_p, si->scaley_mid);
+		P_WriteFixed(save_p, si->scaley_mid);
 	if (diff & LD_SDBOTSCALEY)
-		WRITEFIXED(save_p, si->scaley_bottom);
+		P_WriteFixed(save_p, si->scaley_bottom);
 	if (diff & LD_SDREPEATCNT)
-		WRITEINT16(save_p, si->repeatcnt);
+		P_WriteINT16(save_p, si->repeatcnt);
 	if (diff & LD_SDLIGHT)
-		WRITEINT16(save_p, si->light);
+		P_WriteINT16(save_p, si->light);
 	if (diff & LD_SDTOPLIGHT)
-		WRITEINT16(save_p, si->light_top);
+		P_WriteINT16(save_p, si->light_top);
 	if (diff & LD_SDMIDLIGHT)
-		WRITEINT16(save_p, si->light_mid);
+		P_WriteINT16(save_p, si->light_mid);
 	if (diff & LD_SDBOTLIGHT)
-		WRITEINT16(save_p, si->light_bottom);
+		P_WriteINT16(save_p, si->light_bottom);
 	if (diff & LD_SDLIGHTABS)
-		WRITEUINT8(save_p, si->lightabsolute);
+		P_WriteUINT8(save_p, si->lightabsolute);
 	if (diff & LD_SDTOPLIGHTABS)
-		WRITEUINT8(save_p, si->lightabsolute_top);
+		P_WriteUINT8(save_p, si->lightabsolute_top);
 	if (diff & LD_SDMIDLIGHTABS)
-		WRITEUINT8(save_p, si->lightabsolute_mid);
+		P_WriteUINT8(save_p, si->lightabsolute_mid);
 	if (diff & LD_SDBOTLIGHTABS)
-		WRITEUINT8(save_p, si->lightabsolute_bottom);
+		P_WriteUINT8(save_p, si->lightabsolute_bottom);
 }
 
-static void ArchiveLines(void)
+static void ArchiveLines(save_t *save_p)
 {
 	size_t i;
 	const line_t *li = lines;
@@ -1525,21 +1764,21 @@ static void ArchiveLines(void)
 
 		if (diff)
 		{
-			WRITEUINT32(save_p, i);
-			WRITEUINT8(save_p, diff);
+			P_WriteUINT32(save_p, i);
+			P_WriteUINT8(save_p, diff);
 			if (diff & LD_DIFF2)
-				WRITEUINT8(save_p, diff2);
+				P_WriteUINT8(save_p, diff2);
 			if (diff & LD_FLAG)
-				WRITEINT16(save_p, li->flags);
+				P_WriteINT16(save_p, li->flags);
 			if (diff & LD_SPECIAL)
-				WRITEINT16(save_p, li->special);
+				P_WriteINT16(save_p, li->special);
 			if (diff & LD_CLLCOUNT)
-				WRITEINT16(save_p, li->callcount);
+				P_WriteINT16(save_p, li->callcount);
 			if (diff & LD_ARGS)
 			{
 				UINT8 j;
 				for (j = 0; j < NUMLINEARGS; j++)
-					WRITEINT32(save_p, li->args[j]);
+					P_WriteINT32(save_p, li->args[j]);
 			}
 			if (diff & LD_STRINGARGS)
 			{
@@ -1550,88 +1789,88 @@ static void ArchiveLines(void)
 
 					if (!li->stringargs[j])
 					{
-						WRITEINT32(save_p, 0);
+						P_WriteINT32(save_p, 0);
 						continue;
 					}
 
 					len = strlen(li->stringargs[j]);
-					WRITEINT32(save_p, len);
+					P_WriteINT32(save_p, len);
 					for (k = 0; k < len; k++)
-						WRITECHAR(save_p, li->stringargs[j][k]);
+						P_WriteChar(save_p, li->stringargs[j][k]);
 				}
 			}
 			if (diff & LD_SIDE1)
-				ArchiveSide(&sides[li->sidenum[0]], side1diff);
+				ArchiveSide(save_p, &sides[li->sidenum[0]], side1diff);
 			if (diff & LD_SIDE2)
-				ArchiveSide(&sides[li->sidenum[1]], side2diff);
+				ArchiveSide(save_p, &sides[li->sidenum[1]], side2diff);
 			if (diff2 & LD_EXECUTORDELAY)
-				WRITEINT32(save_p, li->executordelay);
+				P_WriteINT32(save_p, li->executordelay);
 			if (diff2 & LD_TRANSFPORTAL)
-				WRITEUINT32(save_p, li->secportal);
+				P_WriteUINT32(save_p, li->secportal);
 		}
 	}
-	WRITEUINT32(save_p, 0xffffffff);
+	P_WriteUINT32(save_p, 0xffffffff);
 }
 
-static void UnArchiveSide(side_t *si)
+static void UnArchiveSide(save_t *save_p, side_t *si)
 {
-	UINT32 diff = READUINT32(save_p);
+	UINT32 diff = P_ReadUINT32(save_p);
 
 	if (diff & LD_SDTEXOFFX)
-		si->textureoffset = READFIXED(save_p);
+		si->textureoffset = P_ReadFixed(save_p);
 	if (diff & LD_SDTEXOFFY)
-		si->rowoffset = READFIXED(save_p);
+		si->rowoffset = P_ReadFixed(save_p);
 	if (diff & LD_SDTOPTEX)
-		si->toptexture = READINT32(save_p);
+		si->toptexture = P_ReadINT32(save_p);
 	if (diff & LD_SDBOTTEX)
-		si->bottomtexture = READINT32(save_p);
+		si->bottomtexture = P_ReadINT32(save_p);
 	if (diff & LD_SDMIDTEX)
-		si->midtexture = READINT32(save_p);
+		si->midtexture = P_ReadINT32(save_p);
 	if (diff & LD_SDTOPOFFX)
-		si->offsetx_top = READFIXED(save_p);
+		si->offsetx_top = P_ReadFixed(save_p);
 	if (diff & LD_SDMIDOFFX)
-		si->offsetx_mid = READFIXED(save_p);
+		si->offsetx_mid = P_ReadFixed(save_p);
 	if (diff & LD_SDBOTOFFX)
-		si->offsetx_bottom = READFIXED(save_p);
+		si->offsetx_bottom = P_ReadFixed(save_p);
 	if (diff & LD_SDTOPOFFY)
-		si->offsety_top = READFIXED(save_p);
+		si->offsety_top = P_ReadFixed(save_p);
 	if (diff & LD_SDMIDOFFY)
-		si->offsety_mid = READFIXED(save_p);
+		si->offsety_mid = P_ReadFixed(save_p);
 	if (diff & LD_SDBOTOFFY)
-		si->offsety_bottom = READFIXED(save_p);
+		si->offsety_bottom = P_ReadFixed(save_p);
 	if (diff & LD_SDTOPSCALEX)
-		si->scalex_top = READFIXED(save_p);
+		si->scalex_top = P_ReadFixed(save_p);
 	if (diff & LD_SDMIDSCALEX)
-		si->scalex_mid = READFIXED(save_p);
+		si->scalex_mid = P_ReadFixed(save_p);
 	if (diff & LD_SDBOTSCALEX)
-		si->scalex_bottom = READFIXED(save_p);
+		si->scalex_bottom = P_ReadFixed(save_p);
 	if (diff & LD_SDTOPSCALEY)
-		si->scaley_top = READFIXED(save_p);
+		si->scaley_top = P_ReadFixed(save_p);
 	if (diff & LD_SDMIDSCALEY)
-		si->scaley_mid = READFIXED(save_p);
+		si->scaley_mid = P_ReadFixed(save_p);
 	if (diff & LD_SDBOTSCALEY)
-		si->scaley_bottom = READFIXED(save_p);
+		si->scaley_bottom = P_ReadFixed(save_p);
 	if (diff & LD_SDREPEATCNT)
-		si->repeatcnt = READINT16(save_p);
+		si->repeatcnt = P_ReadINT16(save_p);
 	if (diff & LD_SDLIGHT)
-		si->light = READINT16(save_p);
+		si->light = P_ReadINT16(save_p);
 	if (diff & LD_SDTOPLIGHT)
-		si->light_top = READINT16(save_p);
+		si->light_top = P_ReadINT16(save_p);
 	if (diff & LD_SDMIDLIGHT)
-		si->light_mid = READINT16(save_p);
+		si->light_mid = P_ReadINT16(save_p);
 	if (diff & LD_SDBOTLIGHT)
-		si->light_bottom = READINT16(save_p);
+		si->light_bottom = P_ReadINT16(save_p);
 	if (diff & LD_SDLIGHTABS)
-		si->lightabsolute = READUINT8(save_p);
+		si->lightabsolute = P_ReadUINT8(save_p);
 	if (diff & LD_SDTOPLIGHTABS)
-		si->lightabsolute_top = READUINT8(save_p);
+		si->lightabsolute_top = P_ReadUINT8(save_p);
 	if (diff & LD_SDMIDLIGHTABS)
-		si->lightabsolute_mid = READUINT8(save_p);
+		si->lightabsolute_mid = P_ReadUINT8(save_p);
 	if (diff & LD_SDBOTLIGHTABS)
-		si->lightabsolute_bottom = READUINT8(save_p);
+		si->lightabsolute_bottom = P_ReadUINT8(save_p);
 }
 
-static void UnArchiveLines(void)
+static void UnArchiveLines(save_t *save_p)
 {
 	UINT32 i;
 	line_t *li;
@@ -1639,38 +1878,38 @@ static void UnArchiveLines(void)
 
 	for (;;)
 	{
-		i = READUINT32(save_p);
+		i = P_ReadUINT32(save_p);
 
 		if (i == 0xffffffff)
 			break;
 		if (i > numlines)
 			I_Error("Invalid line number %u from server", i);
 
-		diff = READUINT8(save_p);
+		diff = P_ReadUINT8(save_p);
 		if (diff & LD_DIFF2)
-			diff2 = READUINT8(save_p);
+			diff2 = P_ReadUINT8(save_p);
 		else
 			diff2 = 0;
 		li = &lines[i];
 
 		if (diff & LD_FLAG)
-			li->flags = READINT16(save_p);
+			li->flags = P_ReadINT16(save_p);
 		if (diff & LD_SPECIAL)
-			li->special = READINT16(save_p);
+			li->special = P_ReadINT16(save_p);
 		if (diff & LD_CLLCOUNT)
-			li->callcount = READINT16(save_p);
+			li->callcount = P_ReadINT16(save_p);
 		if (diff & LD_ARGS)
 		{
 			UINT8 j;
 			for (j = 0; j < NUMLINEARGS; j++)
-				li->args[j] = READINT32(save_p);
+				li->args[j] = P_ReadINT32(save_p);
 		}
 		if (diff & LD_STRINGARGS)
 		{
 			UINT8 j;
 			for (j = 0; j < NUMLINESTRINGARGS; j++)
 			{
-				size_t len = READINT32(save_p);
+				size_t len = P_ReadINT32(save_p);
 				size_t k;
 
 				if (!len)
@@ -1682,38 +1921,38 @@ static void UnArchiveLines(void)
 
 				li->stringargs[j] = Z_Realloc(li->stringargs[j], len + 1, PU_LEVEL, NULL);
 				for (k = 0; k < len; k++)
-					li->stringargs[j][k] = READCHAR(save_p);
+					li->stringargs[j][k] = P_ReadChar(save_p);
 				li->stringargs[j][len] = '\0';
 			}
 		}
 		if (diff & LD_SIDE1)
-			UnArchiveSide(&sides[li->sidenum[0]]);
+			UnArchiveSide(save_p, &sides[li->sidenum[0]]);
 		if (diff & LD_SIDE2)
-			UnArchiveSide(&sides[li->sidenum[1]]);
+			UnArchiveSide(save_p, &sides[li->sidenum[1]]);
 		if (diff2 & LD_EXECUTORDELAY)
-			li->executordelay = READINT32(save_p);
+			li->executordelay = P_ReadINT32(save_p);
 		if (diff2 & LD_TRANSFPORTAL)
-			li->secportal = READUINT32(save_p);
+			li->secportal = P_ReadUINT32(save_p);
 	}
 }
 
-static void P_NetArchiveWorld(void)
+static void P_NetArchiveWorld(save_t *save_p)
 {
 	// initialize colormap vars because paranoia
 	ClearNetColormaps();
 
-	WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD);
+	P_WriteUINT32(save_p, ARCHIVEBLOCK_WORLD);
 
-	ArchiveSectors();
-	ArchiveLines();
+	ArchiveSectors(save_p);
+	ArchiveLines(save_p);
 	R_ClearTextureNumCache(false);
 }
 
-static void P_NetUnArchiveWorld(void)
+static void P_NetUnArchiveWorld(save_t *save_p)
 {
 	UINT16 i;
 
-	if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD)
+	if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_WORLD)
 		I_Error("Bad $$$.sav at archive block World");
 
 	// initialize colormap vars because paranoia
@@ -1727,8 +1966,8 @@ static void P_NetUnArchiveWorld(void)
 			num_ffloors++;
 	}
 
-	UnArchiveSectors();
-	UnArchiveLines();
+	UnArchiveSectors(save_p);
+	UnArchiveLines(save_p);
 }
 
 //
@@ -1879,7 +2118,7 @@ static UINT32 SaveSlope(const pslope_t *slope)
 	return 0xFFFFFFFF;
 }
 
-static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
+static void SaveMobjThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const mobj_t *mobj = (const mobj_t *)th;
 	UINT32 diff;
@@ -2053,28 +2292,28 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 	if (mobj->type == MT_HOOPCENTER)
 		diff = MD_SPAWNPOINT;
 
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, diff);
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, diff);
 	if (diff & MD_MORE)
-		WRITEUINT32(save_p, diff2);
+		P_WriteUINT32(save_p, diff2);
 
 	// save pointer, at load time we will search this pointer to reinitilize pointers
-	WRITEUINT32(save_p, (size_t)mobj);
+	P_WriteUINT32(save_p, (size_t)mobj);
 
-	WRITEFIXED(save_p, mobj->z); // Force this so 3dfloor problems don't arise.
-	WRITEFIXED(save_p, mobj->floorz);
-	WRITEFIXED(save_p, mobj->ceilingz);
+	P_WriteFixed(save_p, mobj->z); // Force this so 3dfloor problems don't arise.
+	P_WriteFixed(save_p, mobj->floorz);
+	P_WriteFixed(save_p, mobj->ceilingz);
 
 	if (diff2 & MD2_FLOORROVER)
 	{
-		WRITEUINT32(save_p, SaveSector(mobj->floorrover->target));
-		WRITEUINT16(save_p, P_GetFFloorID(mobj->floorrover));
+		P_WriteUINT32(save_p, SaveSector(mobj->floorrover->target));
+		P_WriteUINT16(save_p, P_GetFFloorID(mobj->floorrover));
 	}
 
 	if (diff2 & MD2_CEILINGROVER)
 	{
-		WRITEUINT32(save_p, SaveSector(mobj->ceilingrover->target));
-		WRITEUINT16(save_p, P_GetFFloorID(mobj->ceilingrover));
+		P_WriteUINT32(save_p, SaveSector(mobj->ceilingrover->target));
+		P_WriteUINT16(save_p, P_GetFFloorID(mobj->ceilingrover));
 	}
 
 	if (diff & MD_SPAWNPOINT)
@@ -2083,649 +2322,649 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 
 		for (z = 0; z < nummapthings; z++)
 			if (&mapthings[z] == mobj->spawnpoint)
-				WRITEUINT16(save_p, z);
+				P_WriteUINT16(save_p, z);
 		if (mobj->type == MT_HOOPCENTER)
 			return;
 	}
 
 	if (diff & MD_TYPE)
-		WRITEUINT32(save_p, mobj->type);
+		P_WriteUINT32(save_p, mobj->type);
 	if (diff & MD_POS)
 	{
-		WRITEFIXED(save_p, mobj->x);
-		WRITEFIXED(save_p, mobj->y);
-		WRITEANGLE(save_p, mobj->angle);
-		WRITEANGLE(save_p, mobj->pitch);
-		WRITEANGLE(save_p, mobj->roll);
+		P_WriteFixed(save_p, mobj->x);
+		P_WriteFixed(save_p, mobj->y);
+		P_WriteAngle(save_p, mobj->angle);
+		P_WriteAngle(save_p, mobj->pitch);
+		P_WriteAngle(save_p, mobj->roll);
 	}
 	if (diff & MD_MOM)
 	{
-		WRITEFIXED(save_p, mobj->momx);
-		WRITEFIXED(save_p, mobj->momy);
-		WRITEFIXED(save_p, mobj->momz);
-		WRITEFIXED(save_p, mobj->pmomz);
+		P_WriteFixed(save_p, mobj->momx);
+		P_WriteFixed(save_p, mobj->momy);
+		P_WriteFixed(save_p, mobj->momz);
+		P_WriteFixed(save_p, mobj->pmomz);
 	}
 	if (diff & MD_RADIUS)
-		WRITEFIXED(save_p, mobj->radius);
+		P_WriteFixed(save_p, mobj->radius);
 	if (diff & MD_HEIGHT)
-		WRITEFIXED(save_p, mobj->height);
+		P_WriteFixed(save_p, mobj->height);
 	if (diff & MD_FLAGS)
-		WRITEUINT32(save_p, mobj->flags);
+		P_WriteUINT32(save_p, mobj->flags);
 	if (diff & MD_FLAGS2)
-		WRITEUINT32(save_p, mobj->flags2);
+		P_WriteUINT32(save_p, mobj->flags2);
 	if (diff & MD_HEALTH)
-		WRITEINT32(save_p, mobj->health);
+		P_WriteINT32(save_p, mobj->health);
 	if (diff & MD_RTIME)
-		WRITEINT32(save_p, mobj->reactiontime);
+		P_WriteINT32(save_p, mobj->reactiontime);
 	if (diff & MD_STATE)
-		WRITEUINT16(save_p, mobj->state-states);
+		P_WriteUINT16(save_p, mobj->state-states);
 	if (diff & MD_TICS)
-		WRITEINT32(save_p, mobj->tics);
+		P_WriteINT32(save_p, mobj->tics);
 	if (diff & MD_SPRITE) {
-		WRITEUINT16(save_p, mobj->sprite);
+		P_WriteUINT16(save_p, mobj->sprite);
 		if (mobj->sprite == SPR_PLAY)
-			WRITEUINT16(save_p, mobj->sprite2);
+			P_WriteUINT16(save_p, mobj->sprite2);
 	}
 	if (diff & MD_FRAME)
 	{
-		WRITEUINT32(save_p, mobj->frame);
-		WRITEUINT16(save_p, mobj->anim_duration);
+		P_WriteUINT32(save_p, mobj->frame);
+		P_WriteUINT16(save_p, mobj->anim_duration);
 	}
 	if (diff & MD_EFLAGS)
-		WRITEUINT16(save_p, mobj->eflags);
+		P_WriteUINT16(save_p, mobj->eflags);
 	if (diff & MD_PLAYER)
-		WRITEUINT8(save_p, mobj->player-players);
+		P_WriteUINT8(save_p, mobj->player-players);
 	if (diff & MD_MOVEDIR)
-		WRITEANGLE(save_p, mobj->movedir);
+		P_WriteAngle(save_p, mobj->movedir);
 	if (diff & MD_MOVECOUNT)
-		WRITEINT32(save_p, mobj->movecount);
+		P_WriteINT32(save_p, mobj->movecount);
 	if (diff & MD_THRESHOLD)
-		WRITEINT32(save_p, mobj->threshold);
+		P_WriteINT32(save_p, mobj->threshold);
 	if (diff & MD_LASTLOOK)
-		WRITEINT32(save_p, mobj->lastlook);
+		P_WriteINT32(save_p, mobj->lastlook);
 	if (diff & MD_TARGET)
-		WRITEUINT32(save_p, mobj->target->mobjnum);
+		P_WriteUINT32(save_p, mobj->target->mobjnum);
 	if (diff & MD_TRACER)
-		WRITEUINT32(save_p, mobj->tracer->mobjnum);
+		P_WriteUINT32(save_p, mobj->tracer->mobjnum);
 	if (diff & MD_FRICTION)
-		WRITEFIXED(save_p, mobj->friction);
+		P_WriteFixed(save_p, mobj->friction);
 	if (diff & MD_MOVEFACTOR)
-		WRITEFIXED(save_p, mobj->movefactor);
+		P_WriteFixed(save_p, mobj->movefactor);
 	if (diff & MD_FUSE)
-		WRITEINT32(save_p, mobj->fuse);
+		P_WriteINT32(save_p, mobj->fuse);
 	if (diff & MD_WATERTOP)
-		WRITEFIXED(save_p, mobj->watertop);
+		P_WriteFixed(save_p, mobj->watertop);
 	if (diff & MD_WATERBOTTOM)
-		WRITEFIXED(save_p, mobj->waterbottom);
+		P_WriteFixed(save_p, mobj->waterbottom);
 	if (diff & MD_SCALE)
-		WRITEFIXED(save_p, mobj->scale);
+		P_WriteFixed(save_p, mobj->scale);
 	if (diff & MD_DSCALE)
-		WRITEFIXED(save_p, mobj->destscale);
+		P_WriteFixed(save_p, mobj->destscale);
 	if (diff2 & MD2_SCALESPEED)
-		WRITEFIXED(save_p, mobj->scalespeed);
+		P_WriteFixed(save_p, mobj->scalespeed);
 	if (diff2 & MD2_CUSVAL)
-		WRITEINT32(save_p, mobj->cusval);
+		P_WriteINT32(save_p, mobj->cusval);
 	if (diff2 & MD2_CVMEM)
-		WRITEINT32(save_p, mobj->cvmem);
+		P_WriteINT32(save_p, mobj->cvmem);
 	if (diff2 & MD2_SKIN)
-		WRITEUINT8(save_p, (UINT8)(((skin_t *)mobj->skin)->skinnum));
+		P_WriteUINT8(save_p, (UINT8)(((skin_t *)mobj->skin)->skinnum));
 	if (diff2 & MD2_COLOR)
-		WRITEUINT16(save_p, mobj->color);
+		P_WriteUINT16(save_p, mobj->color);
 	if (diff2 & MD2_EXTVAL1)
-		WRITEINT32(save_p, mobj->extravalue1);
+		P_WriteINT32(save_p, mobj->extravalue1);
 	if (diff2 & MD2_EXTVAL2)
-		WRITEINT32(save_p, mobj->extravalue2);
+		P_WriteINT32(save_p, mobj->extravalue2);
 	if (diff2 & MD2_HNEXT)
-		WRITEUINT32(save_p, mobj->hnext->mobjnum);
+		P_WriteUINT32(save_p, mobj->hnext->mobjnum);
 	if (diff2 & MD2_HPREV)
-		WRITEUINT32(save_p, mobj->hprev->mobjnum);
+		P_WriteUINT32(save_p, mobj->hprev->mobjnum);
 	if (diff2 & MD2_SLOPE)
-		WRITEUINT16(save_p, mobj->standingslope->id);
+		P_WriteUINT16(save_p, mobj->standingslope->id);
 	if (diff2 & MD2_COLORIZED)
-		WRITEUINT8(save_p, mobj->colorized);
+		P_WriteUINT8(save_p, mobj->colorized);
 	if (diff2 & MD2_MIRRORED)
-		WRITEUINT8(save_p, mobj->mirrored);
+		P_WriteUINT8(save_p, mobj->mirrored);
 	if (diff2 & MD2_SPRITEROLL)
-		WRITEANGLE(save_p, mobj->spriteroll);
+		P_WriteAngle(save_p, mobj->spriteroll);
 	if (diff2 & MD2_SHADOWSCALE)
-		WRITEFIXED(save_p, mobj->shadowscale);
+		P_WriteFixed(save_p, mobj->shadowscale);
 	if (diff2 & MD2_RENDERFLAGS)
-		WRITEUINT32(save_p, mobj->renderflags);
+		P_WriteUINT32(save_p, mobj->renderflags);
 	if (diff2 & MD2_BLENDMODE)
-		WRITEINT32(save_p, mobj->blendmode);
+		P_WriteINT32(save_p, mobj->blendmode);
 	if (diff2 & MD2_SPRITEXSCALE)
-		WRITEFIXED(save_p, mobj->spritexscale);
+		P_WriteFixed(save_p, mobj->spritexscale);
 	if (diff2 & MD2_SPRITEYSCALE)
-		WRITEFIXED(save_p, mobj->spriteyscale);
+		P_WriteFixed(save_p, mobj->spriteyscale);
 	if (diff2 & MD2_SPRITEXOFFSET)
-		WRITEFIXED(save_p, mobj->spritexoffset);
+		P_WriteFixed(save_p, mobj->spritexoffset);
 	if (diff2 & MD2_SPRITEYOFFSET)
-		WRITEFIXED(save_p, mobj->spriteyoffset);
+		P_WriteFixed(save_p, mobj->spriteyoffset);
 	if (diff2 & MD2_FLOORSPRITESLOPE)
 	{
 		pslope_t *slope = mobj->floorspriteslope;
 
-		WRITEFIXED(save_p, slope->zdelta);
-		WRITEANGLE(save_p, slope->zangle);
-		WRITEANGLE(save_p, slope->xydirection);
+		P_WriteFixed(save_p, slope->zdelta);
+		P_WriteAngle(save_p, slope->zangle);
+		P_WriteAngle(save_p, slope->xydirection);
 
-		WRITEFIXED(save_p, slope->o.x);
-		WRITEFIXED(save_p, slope->o.y);
-		WRITEFIXED(save_p, slope->o.z);
+		P_WriteFixed(save_p, slope->o.x);
+		P_WriteFixed(save_p, slope->o.y);
+		P_WriteFixed(save_p, slope->o.z);
 
-		WRITEFIXED(save_p, slope->d.x);
-		WRITEFIXED(save_p, slope->d.y);
+		P_WriteFixed(save_p, slope->d.x);
+		P_WriteFixed(save_p, slope->d.y);
 
-		WRITEFIXED(save_p, slope->normal.x);
-		WRITEFIXED(save_p, slope->normal.y);
-		WRITEFIXED(save_p, slope->normal.z);
+		P_WriteFixed(save_p, slope->normal.x);
+		P_WriteFixed(save_p, slope->normal.y);
+		P_WriteFixed(save_p, slope->normal.z);
 	}
 	if (diff2 & MD2_DRAWONLYFORPLAYER)
-		WRITEUINT8(save_p, mobj->drawonlyforplayer-players);
+		P_WriteUINT8(save_p, mobj->drawonlyforplayer-players);
 	if (diff2 & MD2_DONTDRAWFORVIEWMOBJ)
-		WRITEUINT32(save_p, mobj->dontdrawforviewmobj->mobjnum);
+		P_WriteUINT32(save_p, mobj->dontdrawforviewmobj->mobjnum);
 	if (diff2 & MD2_DISPOFFSET)
-		WRITEINT32(save_p, mobj->dispoffset);
+		P_WriteINT32(save_p, mobj->dispoffset);
 	if (diff2 & MD2_TRANSLATION)
-		WRITEUINT16(save_p, mobj->translation);
+		P_WriteUINT16(save_p, mobj->translation);
 	if (diff2 & MD2_ALPHA)
-		WRITEFIXED(save_p, mobj->alpha);
+		P_WriteFixed(save_p, mobj->alpha);
 
-	WRITEUINT32(save_p, mobj->mobjnum);
+	P_WriteUINT32(save_p, mobj->mobjnum);
 }
 
-static void SaveNoEnemiesThinker(const thinker_t *th, const UINT8 type)
+static void SaveNoEnemiesThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const noenemies_t *ht  = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, SaveLine(ht->sourceline));
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, SaveLine(ht->sourceline));
 }
 
-static void SaveBounceCheeseThinker(const thinker_t *th, const UINT8 type)
+static void SaveBounceCheeseThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const bouncecheese_t *ht  = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, SaveLine(ht->sourceline));
-	WRITEUINT32(save_p, SaveSector(ht->sector));
-	WRITEFIXED(save_p, ht->speed);
-	WRITEFIXED(save_p, ht->distance);
-	WRITEFIXED(save_p, ht->floorwasheight);
-	WRITEFIXED(save_p, ht->ceilingwasheight);
-	WRITECHAR(save_p, ht->low);
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, SaveLine(ht->sourceline));
+	P_WriteUINT32(save_p, SaveSector(ht->sector));
+	P_WriteFixed(save_p, ht->speed);
+	P_WriteFixed(save_p, ht->distance);
+	P_WriteFixed(save_p, ht->floorwasheight);
+	P_WriteFixed(save_p, ht->ceilingwasheight);
+	P_WriteChar(save_p, ht->low);
 }
 
-static void SaveContinuousFallThinker(const thinker_t *th, const UINT8 type)
+static void SaveContinuousFallThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const continuousfall_t *ht  = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, SaveSector(ht->sector));
-	WRITEFIXED(save_p, ht->speed);
-	WRITEINT32(save_p, ht->direction);
-	WRITEFIXED(save_p, ht->floorstartheight);
-	WRITEFIXED(save_p, ht->ceilingstartheight);
-	WRITEFIXED(save_p, ht->destheight);
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, SaveSector(ht->sector));
+	P_WriteFixed(save_p, ht->speed);
+	P_WriteINT32(save_p, ht->direction);
+	P_WriteFixed(save_p, ht->floorstartheight);
+	P_WriteFixed(save_p, ht->ceilingstartheight);
+	P_WriteFixed(save_p, ht->destheight);
 }
 
-static void SaveMarioBlockThinker(const thinker_t *th, const UINT8 type)
+static void SaveMarioBlockThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const mariothink_t *ht  = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, SaveSector(ht->sector));
-	WRITEFIXED(save_p, ht->speed);
-	WRITEINT32(save_p, ht->direction);
-	WRITEFIXED(save_p, ht->floorstartheight);
-	WRITEFIXED(save_p, ht->ceilingstartheight);
-	WRITEINT16(save_p, ht->tag);
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, SaveSector(ht->sector));
+	P_WriteFixed(save_p, ht->speed);
+	P_WriteINT32(save_p, ht->direction);
+	P_WriteFixed(save_p, ht->floorstartheight);
+	P_WriteFixed(save_p, ht->ceilingstartheight);
+	P_WriteINT16(save_p, ht->tag);
 }
 
-static void SaveMarioCheckThinker(const thinker_t *th, const UINT8 type)
+static void SaveMarioCheckThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const mariocheck_t *ht  = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, SaveLine(ht->sourceline));
-	WRITEUINT32(save_p, SaveSector(ht->sector));
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, SaveLine(ht->sourceline));
+	P_WriteUINT32(save_p, SaveSector(ht->sector));
 }
 
-static void SaveThwompThinker(const thinker_t *th, const UINT8 type)
+static void SaveThwompThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const thwomp_t *ht  = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, SaveLine(ht->sourceline));
-	WRITEUINT32(save_p, SaveSector(ht->sector));
-	WRITEFIXED(save_p, ht->crushspeed);
-	WRITEFIXED(save_p, ht->retractspeed);
-	WRITEINT32(save_p, ht->direction);
-	WRITEFIXED(save_p, ht->floorstartheight);
-	WRITEFIXED(save_p, ht->ceilingstartheight);
-	WRITEINT32(save_p, ht->delay);
-	WRITEINT16(save_p, ht->tag);
-	WRITEUINT16(save_p, ht->sound);
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, SaveLine(ht->sourceline));
+	P_WriteUINT32(save_p, SaveSector(ht->sector));
+	P_WriteFixed(save_p, ht->crushspeed);
+	P_WriteFixed(save_p, ht->retractspeed);
+	P_WriteINT32(save_p, ht->direction);
+	P_WriteFixed(save_p, ht->floorstartheight);
+	P_WriteFixed(save_p, ht->ceilingstartheight);
+	P_WriteINT32(save_p, ht->delay);
+	P_WriteINT16(save_p, ht->tag);
+	P_WriteUINT16(save_p, ht->sound);
 }
 
-static void SaveFloatThinker(const thinker_t *th, const UINT8 type)
+static void SaveFloatThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const floatthink_t *ht  = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, SaveLine(ht->sourceline));
-	WRITEUINT32(save_p, SaveSector(ht->sector));
-	WRITEINT16(save_p, ht->tag);
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, SaveLine(ht->sourceline));
+	P_WriteUINT32(save_p, SaveSector(ht->sector));
+	P_WriteINT16(save_p, ht->tag);
 }
 
-static void SaveEachTimeThinker(const thinker_t *th, const UINT8 type)
+static void SaveEachTimeThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const eachtime_t *ht  = (const void *)th;
 	size_t i;
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, SaveLine(ht->sourceline));
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, SaveLine(ht->sourceline));
 	for (i = 0; i < MAXPLAYERS; i++)
 	{
-		WRITECHAR(save_p, ht->playersInArea[i]);
+		P_WriteChar(save_p, ht->playersInArea[i]);
 	}
-	WRITECHAR(save_p, ht->triggerOnExit);
+	P_WriteChar(save_p, ht->triggerOnExit);
 }
 
-static void SaveRaiseThinker(const thinker_t *th, const UINT8 type)
+static void SaveRaiseThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const raise_t *ht  = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEINT16(save_p, ht->tag);
-	WRITEUINT32(save_p, SaveSector(ht->sector));
-	WRITEFIXED(save_p, ht->ceilingbottom);
-	WRITEFIXED(save_p, ht->ceilingtop);
-	WRITEFIXED(save_p, ht->basespeed);
-	WRITEFIXED(save_p, ht->extraspeed);
-	WRITEUINT8(save_p, ht->shaketimer);
-	WRITEUINT8(save_p, ht->flags);
+	P_WriteUINT8(save_p, type);
+	P_WriteINT16(save_p, ht->tag);
+	P_WriteUINT32(save_p, SaveSector(ht->sector));
+	P_WriteFixed(save_p, ht->ceilingbottom);
+	P_WriteFixed(save_p, ht->ceilingtop);
+	P_WriteFixed(save_p, ht->basespeed);
+	P_WriteFixed(save_p, ht->extraspeed);
+	P_WriteUINT8(save_p, ht->shaketimer);
+	P_WriteUINT8(save_p, ht->flags);
 }
 
-static void SaveCeilingThinker(const thinker_t *th, const UINT8 type)
+static void SaveCeilingThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const ceiling_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT8(save_p, ht->type);
-	WRITEUINT32(save_p, SaveSector(ht->sector));
-	WRITEFIXED(save_p, ht->bottomheight);
-	WRITEFIXED(save_p, ht->topheight);
-	WRITEFIXED(save_p, ht->speed);
-	WRITEFIXED(save_p, ht->delay);
-	WRITEFIXED(save_p, ht->delaytimer);
-	WRITEUINT8(save_p, ht->crush);
-	WRITEINT32(save_p, ht->texture);
-	WRITEINT32(save_p, ht->direction);
-	WRITEINT16(save_p, ht->tag);
-	WRITEFIXED(save_p, ht->origspeed);
-	WRITEFIXED(save_p, ht->sourceline);
-}
-
-static void SaveFloormoveThinker(const thinker_t *th, const UINT8 type)
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT8(save_p, ht->type);
+	P_WriteUINT32(save_p, SaveSector(ht->sector));
+	P_WriteFixed(save_p, ht->bottomheight);
+	P_WriteFixed(save_p, ht->topheight);
+	P_WriteFixed(save_p, ht->speed);
+	P_WriteFixed(save_p, ht->delay);
+	P_WriteFixed(save_p, ht->delaytimer);
+	P_WriteUINT8(save_p, ht->crush);
+	P_WriteINT32(save_p, ht->texture);
+	P_WriteINT32(save_p, ht->direction);
+	P_WriteINT16(save_p, ht->tag);
+	P_WriteFixed(save_p, ht->origspeed);
+	P_WriteFixed(save_p, ht->sourceline);
+}
+
+static void SaveFloormoveThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const floormove_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT8(save_p, ht->type);
-	WRITEUINT8(save_p, ht->crush);
-	WRITEUINT32(save_p, SaveSector(ht->sector));
-	WRITEINT32(save_p, ht->direction);
-	WRITEINT32(save_p, ht->texture);
-	WRITEFIXED(save_p, ht->floordestheight);
-	WRITEFIXED(save_p, ht->speed);
-	WRITEFIXED(save_p, ht->origspeed);
-	WRITEFIXED(save_p, ht->delay);
-	WRITEFIXED(save_p, ht->delaytimer);
-	WRITEINT16(save_p, ht->tag);
-	WRITEFIXED(save_p, ht->sourceline);
-}
-
-static void SaveLightflashThinker(const thinker_t *th, const UINT8 type)
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT8(save_p, ht->type);
+	P_WriteUINT8(save_p, ht->crush);
+	P_WriteUINT32(save_p, SaveSector(ht->sector));
+	P_WriteINT32(save_p, ht->direction);
+	P_WriteINT32(save_p, ht->texture);
+	P_WriteFixed(save_p, ht->floordestheight);
+	P_WriteFixed(save_p, ht->speed);
+	P_WriteFixed(save_p, ht->origspeed);
+	P_WriteFixed(save_p, ht->delay);
+	P_WriteFixed(save_p, ht->delaytimer);
+	P_WriteINT16(save_p, ht->tag);
+	P_WriteFixed(save_p, ht->sourceline);
+}
+
+static void SaveLightflashThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const lightflash_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, SaveSector(ht->sector));
-	WRITEINT32(save_p, ht->maxlight);
-	WRITEINT32(save_p, ht->minlight);
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, SaveSector(ht->sector));
+	P_WriteINT32(save_p, ht->maxlight);
+	P_WriteINT32(save_p, ht->minlight);
 }
 
-static void SaveStrobeThinker(const thinker_t *th, const UINT8 type)
+static void SaveStrobeThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const strobe_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, SaveSector(ht->sector));
-	WRITEINT32(save_p, ht->count);
-	WRITEINT16(save_p, ht->minlight);
-	WRITEINT16(save_p, ht->maxlight);
-	WRITEINT32(save_p, ht->darktime);
-	WRITEINT32(save_p, ht->brighttime);
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, SaveSector(ht->sector));
+	P_WriteINT32(save_p, ht->count);
+	P_WriteINT16(save_p, ht->minlight);
+	P_WriteINT16(save_p, ht->maxlight);
+	P_WriteINT32(save_p, ht->darktime);
+	P_WriteINT32(save_p, ht->brighttime);
 }
 
-static void SaveGlowThinker(const thinker_t *th, const UINT8 type)
+static void SaveGlowThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const glow_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, SaveSector(ht->sector));
-	WRITEINT16(save_p, ht->minlight);
-	WRITEINT16(save_p, ht->maxlight);
-	WRITEINT16(save_p, ht->direction);
-	WRITEINT16(save_p, ht->speed);
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, SaveSector(ht->sector));
+	P_WriteINT16(save_p, ht->minlight);
+	P_WriteINT16(save_p, ht->maxlight);
+	P_WriteINT16(save_p, ht->direction);
+	P_WriteINT16(save_p, ht->speed);
 }
 
-static inline void SaveFireflickerThinker(const thinker_t *th, const UINT8 type)
+static inline void SaveFireflickerThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const fireflicker_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, SaveSector(ht->sector));
-	WRITEINT32(save_p, ht->count);
-	WRITEINT32(save_p, ht->resetcount);
-	WRITEINT16(save_p, ht->maxlight);
-	WRITEINT16(save_p, ht->minlight);
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, SaveSector(ht->sector));
+	P_WriteINT32(save_p, ht->count);
+	P_WriteINT32(save_p, ht->resetcount);
+	P_WriteINT16(save_p, ht->maxlight);
+	P_WriteINT16(save_p, ht->minlight);
 }
 
-static void SaveElevatorThinker(const thinker_t *th, const UINT8 type)
+static void SaveElevatorThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const elevator_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT8(save_p, ht->type);
-	WRITEUINT32(save_p, SaveSector(ht->sector));
-	WRITEUINT32(save_p, SaveSector(ht->actionsector));
-	WRITEINT32(save_p, ht->direction);
-	WRITEFIXED(save_p, ht->floordestheight);
-	WRITEFIXED(save_p, ht->ceilingdestheight);
-	WRITEFIXED(save_p, ht->speed);
-	WRITEFIXED(save_p, ht->origspeed);
-	WRITEFIXED(save_p, ht->low);
-	WRITEFIXED(save_p, ht->high);
-	WRITEFIXED(save_p, ht->distance);
-	WRITEFIXED(save_p, ht->delay);
-	WRITEFIXED(save_p, ht->delaytimer);
-	WRITEFIXED(save_p, ht->floorwasheight);
-	WRITEFIXED(save_p, ht->ceilingwasheight);
-	WRITEUINT32(save_p, SaveLine(ht->sourceline));
-}
-
-static void SaveCrumbleThinker(const thinker_t *th, const UINT8 type)
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT8(save_p, ht->type);
+	P_WriteUINT32(save_p, SaveSector(ht->sector));
+	P_WriteUINT32(save_p, SaveSector(ht->actionsector));
+	P_WriteINT32(save_p, ht->direction);
+	P_WriteFixed(save_p, ht->floordestheight);
+	P_WriteFixed(save_p, ht->ceilingdestheight);
+	P_WriteFixed(save_p, ht->speed);
+	P_WriteFixed(save_p, ht->origspeed);
+	P_WriteFixed(save_p, ht->low);
+	P_WriteFixed(save_p, ht->high);
+	P_WriteFixed(save_p, ht->distance);
+	P_WriteFixed(save_p, ht->delay);
+	P_WriteFixed(save_p, ht->delaytimer);
+	P_WriteFixed(save_p, ht->floorwasheight);
+	P_WriteFixed(save_p, ht->ceilingwasheight);
+	P_WriteUINT32(save_p, SaveLine(ht->sourceline));
+}
+
+static void SaveCrumbleThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const crumble_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, SaveLine(ht->sourceline));
-	WRITEUINT32(save_p, SaveSector(ht->sector));
-	WRITEUINT32(save_p, SaveSector(ht->actionsector));
-	WRITEUINT32(save_p, SavePlayer(ht->player)); // was dummy
-	WRITEINT32(save_p, ht->direction);
-	WRITEINT32(save_p, ht->origalpha);
-	WRITEINT32(save_p, ht->timer);
-	WRITEFIXED(save_p, ht->speed);
-	WRITEFIXED(save_p, ht->floorwasheight);
-	WRITEFIXED(save_p, ht->ceilingwasheight);
-	WRITEUINT8(save_p, ht->flags);
-}
-
-static inline void SaveScrollThinker(const thinker_t *th, const UINT8 type)
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, SaveLine(ht->sourceline));
+	P_WriteUINT32(save_p, SaveSector(ht->sector));
+	P_WriteUINT32(save_p, SaveSector(ht->actionsector));
+	P_WriteUINT32(save_p, SavePlayer(ht->player)); // was dummy
+	P_WriteINT32(save_p, ht->direction);
+	P_WriteINT32(save_p, ht->origalpha);
+	P_WriteINT32(save_p, ht->timer);
+	P_WriteFixed(save_p, ht->speed);
+	P_WriteFixed(save_p, ht->floorwasheight);
+	P_WriteFixed(save_p, ht->ceilingwasheight);
+	P_WriteUINT8(save_p, ht->flags);
+}
+
+static inline void SaveScrollThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const scroll_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEFIXED(save_p, ht->dx);
-	WRITEFIXED(save_p, ht->dy);
-	WRITEINT32(save_p, ht->affectee);
-	WRITEINT32(save_p, ht->control);
-	WRITEFIXED(save_p, ht->last_height);
-	WRITEFIXED(save_p, ht->vdx);
-	WRITEFIXED(save_p, ht->vdy);
-	WRITEINT32(save_p, ht->accel);
-	WRITEINT32(save_p, ht->exclusive);
-	WRITEUINT8(save_p, ht->type);
+	P_WriteUINT8(save_p, type);
+	P_WriteFixed(save_p, ht->dx);
+	P_WriteFixed(save_p, ht->dy);
+	P_WriteINT32(save_p, ht->affectee);
+	P_WriteINT32(save_p, ht->control);
+	P_WriteFixed(save_p, ht->last_height);
+	P_WriteFixed(save_p, ht->vdx);
+	P_WriteFixed(save_p, ht->vdy);
+	P_WriteINT32(save_p, ht->accel);
+	P_WriteINT32(save_p, ht->exclusive);
+	P_WriteUINT8(save_p, ht->type);
 }
 
-static inline void SaveFrictionThinker(const thinker_t *th, const UINT8 type)
+static inline void SaveFrictionThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const friction_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEINT32(save_p, ht->friction);
-	WRITEINT32(save_p, ht->movefactor);
-	WRITEINT32(save_p, ht->affectee);
-	WRITEINT32(save_p, ht->referrer);
-	WRITEUINT8(save_p, ht->roverfriction);
+	P_WriteUINT8(save_p, type);
+	P_WriteINT32(save_p, ht->friction);
+	P_WriteINT32(save_p, ht->movefactor);
+	P_WriteINT32(save_p, ht->affectee);
+	P_WriteINT32(save_p, ht->referrer);
+	P_WriteUINT8(save_p, ht->roverfriction);
 }
 
-static inline void SavePusherThinker(const thinker_t *th, const UINT8 type)
+static inline void SavePusherThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const pusher_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT8(save_p, ht->type);
-	WRITEFIXED(save_p, ht->x_mag);
-	WRITEFIXED(save_p, ht->y_mag);
-	WRITEFIXED(save_p, ht->z_mag);
-	WRITEINT32(save_p, ht->affectee);
-	WRITEUINT8(save_p, ht->roverpusher);
-	WRITEINT32(save_p, ht->referrer);
-	WRITEINT32(save_p, ht->exclusive);
-	WRITEINT32(save_p, ht->slider);
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT8(save_p, ht->type);
+	P_WriteFixed(save_p, ht->x_mag);
+	P_WriteFixed(save_p, ht->y_mag);
+	P_WriteFixed(save_p, ht->z_mag);
+	P_WriteINT32(save_p, ht->affectee);
+	P_WriteUINT8(save_p, ht->roverpusher);
+	P_WriteINT32(save_p, ht->referrer);
+	P_WriteINT32(save_p, ht->exclusive);
+	P_WriteINT32(save_p, ht->slider);
 }
 
-static void SaveLaserThinker(const thinker_t *th, const UINT8 type)
+static void SaveLaserThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const laserthink_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEINT16(save_p, ht->tag);
-	WRITEUINT32(save_p, SaveLine(ht->sourceline));
-	WRITEUINT8(save_p, ht->nobosses);
+	P_WriteUINT8(save_p, type);
+	P_WriteINT16(save_p, ht->tag);
+	P_WriteUINT32(save_p, SaveLine(ht->sourceline));
+	P_WriteUINT8(save_p, ht->nobosses);
 }
 
-static void SaveLightlevelThinker(const thinker_t *th, const UINT8 type)
+static void SaveLightlevelThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const lightlevel_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, SaveSector(ht->sector));
-	WRITEINT16(save_p, ht->sourcelevel);
-	WRITEINT16(save_p, ht->destlevel);
-	WRITEFIXED(save_p, ht->fixedcurlevel);
-	WRITEFIXED(save_p, ht->fixedpertic);
-	WRITEINT32(save_p, ht->timer);
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, SaveSector(ht->sector));
+	P_WriteINT16(save_p, ht->sourcelevel);
+	P_WriteINT16(save_p, ht->destlevel);
+	P_WriteFixed(save_p, ht->fixedcurlevel);
+	P_WriteFixed(save_p, ht->fixedpertic);
+	P_WriteINT32(save_p, ht->timer);
 }
 
-static void SaveExecutorThinker(const thinker_t *th, const UINT8 type)
+static void SaveExecutorThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const executor_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, SaveLine(ht->line));
-	WRITEUINT32(save_p, SaveMobjnum(ht->caller));
-	WRITEUINT32(save_p, SaveSector(ht->sector));
-	WRITEINT32(save_p, ht->timer);
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, SaveLine(ht->line));
+	P_WriteUINT32(save_p, SaveMobjnum(ht->caller));
+	P_WriteUINT32(save_p, SaveSector(ht->sector));
+	P_WriteINT32(save_p, ht->timer);
 }
 
-static void SaveDisappearThinker(const thinker_t *th, const UINT8 type)
+static void SaveDisappearThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const disappear_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, ht->appeartime);
-	WRITEUINT32(save_p, ht->disappeartime);
-	WRITEUINT32(save_p, ht->offset);
-	WRITEUINT32(save_p, ht->timer);
-	WRITEINT32(save_p, ht->affectee);
-	WRITEINT32(save_p, ht->sourceline);
-	WRITEINT32(save_p, ht->exists);
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, ht->appeartime);
+	P_WriteUINT32(save_p, ht->disappeartime);
+	P_WriteUINT32(save_p, ht->offset);
+	P_WriteUINT32(save_p, ht->timer);
+	P_WriteINT32(save_p, ht->affectee);
+	P_WriteINT32(save_p, ht->sourceline);
+	P_WriteINT32(save_p, ht->exists);
 }
 
-static void SaveFadeThinker(const thinker_t *th, const UINT8 type)
+static void SaveFadeThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const fade_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc));
-	WRITEUINT32(save_p, ht->sectornum);
-	WRITEUINT32(save_p, ht->ffloornum);
-	WRITEINT32(save_p, ht->alpha);
-	WRITEINT16(save_p, ht->sourcevalue);
-	WRITEINT16(save_p, ht->destvalue);
-	WRITEINT16(save_p, ht->destlightlevel);
-	WRITEINT16(save_p, ht->speed);
-	WRITEUINT8(save_p, (UINT8)ht->ticbased);
-	WRITEINT32(save_p, ht->timer);
-	WRITEUINT8(save_p, ht->doexists);
-	WRITEUINT8(save_p, ht->dotranslucent);
-	WRITEUINT8(save_p, ht->dolighting);
-	WRITEUINT8(save_p, ht->docolormap);
-	WRITEUINT8(save_p, ht->docollision);
-	WRITEUINT8(save_p, ht->doghostfade);
-	WRITEUINT8(save_p, ht->exactalpha);
-}
-
-static void SaveFadeColormapThinker(const thinker_t *th, const UINT8 type)
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc));
+	P_WriteUINT32(save_p, ht->sectornum);
+	P_WriteUINT32(save_p, ht->ffloornum);
+	P_WriteINT32(save_p, ht->alpha);
+	P_WriteINT16(save_p, ht->sourcevalue);
+	P_WriteINT16(save_p, ht->destvalue);
+	P_WriteINT16(save_p, ht->destlightlevel);
+	P_WriteINT16(save_p, ht->speed);
+	P_WriteUINT8(save_p, (UINT8)ht->ticbased);
+	P_WriteINT32(save_p, ht->timer);
+	P_WriteUINT8(save_p, ht->doexists);
+	P_WriteUINT8(save_p, ht->dotranslucent);
+	P_WriteUINT8(save_p, ht->dolighting);
+	P_WriteUINT8(save_p, ht->docolormap);
+	P_WriteUINT8(save_p, ht->docollision);
+	P_WriteUINT8(save_p, ht->doghostfade);
+	P_WriteUINT8(save_p, ht->exactalpha);
+}
+
+static void SaveFadeColormapThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const fadecolormap_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, SaveSector(ht->sector));
-	WRITEUINT32(save_p, CheckAddNetColormapToList(ht->source_exc));
-	WRITEUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc));
-	WRITEUINT8(save_p, (UINT8)ht->ticbased);
-	WRITEINT32(save_p, ht->duration);
-	WRITEINT32(save_p, ht->timer);
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, SaveSector(ht->sector));
+	P_WriteUINT32(save_p, CheckAddNetColormapToList(ht->source_exc));
+	P_WriteUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc));
+	P_WriteUINT8(save_p, (UINT8)ht->ticbased);
+	P_WriteINT32(save_p, ht->duration);
+	P_WriteINT32(save_p, ht->timer);
 }
 
-static void SavePlaneDisplaceThinker(const thinker_t *th, const UINT8 type)
+static void SavePlaneDisplaceThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const planedisplace_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEINT32(save_p, ht->affectee);
-	WRITEINT32(save_p, ht->control);
-	WRITEFIXED(save_p, ht->last_height);
-	WRITEFIXED(save_p, ht->speed);
-	WRITEUINT8(save_p, ht->type);
+	P_WriteUINT8(save_p, type);
+	P_WriteINT32(save_p, ht->affectee);
+	P_WriteINT32(save_p, ht->control);
+	P_WriteFixed(save_p, ht->last_height);
+	P_WriteFixed(save_p, ht->speed);
+	P_WriteUINT8(save_p, ht->type);
 }
 
-static inline void SaveDynamicLineSlopeThinker(const thinker_t *th, const UINT8 type)
+static inline void SaveDynamicLineSlopeThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const dynlineplanethink_t* ht = (const void*)th;
 
-	WRITEUINT8(save_p, type);
-	WRITEUINT8(save_p, ht->type);
-	WRITEUINT32(save_p, SaveSlope(ht->slope));
-	WRITEUINT32(save_p, SaveLine(ht->sourceline));
-	WRITEFIXED(save_p, ht->extent);
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT8(save_p, ht->type);
+	P_WriteUINT32(save_p, SaveSlope(ht->slope));
+	P_WriteUINT32(save_p, SaveLine(ht->sourceline));
+	P_WriteFixed(save_p, ht->extent);
 }
 
-static inline void SaveDynamicVertexSlopeThinker(const thinker_t *th, const UINT8 type)
+static inline void SaveDynamicVertexSlopeThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	size_t i;
 	const dynvertexplanethink_t* ht = (const void*)th;
 
-	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, SaveSlope(ht->slope));
+	P_WriteUINT8(save_p, type);
+	P_WriteUINT32(save_p, SaveSlope(ht->slope));
 	for (i = 0; i < 3; i++)
-		WRITEUINT32(save_p, SaveSector(ht->secs[i]));
-	WRITEMEM(save_p, ht->vex, sizeof(ht->vex));
-	WRITEMEM(save_p, ht->origsecheights, sizeof(ht->origsecheights));
-	WRITEMEM(save_p, ht->origvecheights, sizeof(ht->origvecheights));
-	WRITEUINT8(save_p, ht->relative);
+		P_WriteUINT32(save_p, SaveSector(ht->secs[i]));
+	P_WriteMem(save_p, ht->vex, sizeof(ht->vex));
+	P_WriteMem(save_p, ht->origsecheights, sizeof(ht->origsecheights));
+	P_WriteMem(save_p, ht->origvecheights, sizeof(ht->origvecheights));
+	P_WriteUINT8(save_p, ht->relative);
 }
 
-static inline void SavePolyrotatetThinker(const thinker_t *th, const UINT8 type)
+static inline void SavePolyrotatetThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const polyrotate_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEINT32(save_p, ht->polyObjNum);
-	WRITEINT32(save_p, ht->speed);
-	WRITEINT32(save_p, ht->distance);
-	WRITEUINT8(save_p, ht->turnobjs);
+	P_WriteUINT8(save_p, type);
+	P_WriteINT32(save_p, ht->polyObjNum);
+	P_WriteINT32(save_p, ht->speed);
+	P_WriteINT32(save_p, ht->distance);
+	P_WriteUINT8(save_p, ht->turnobjs);
 }
 
-static void SavePolymoveThinker(const thinker_t *th, const UINT8 type)
+static void SavePolymoveThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const polymove_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEINT32(save_p, ht->polyObjNum);
-	WRITEINT32(save_p, ht->speed);
-	WRITEFIXED(save_p, ht->momx);
-	WRITEFIXED(save_p, ht->momy);
-	WRITEINT32(save_p, ht->distance);
-	WRITEANGLE(save_p, ht->angle);
+	P_WriteUINT8(save_p, type);
+	P_WriteINT32(save_p, ht->polyObjNum);
+	P_WriteINT32(save_p, ht->speed);
+	P_WriteFixed(save_p, ht->momx);
+	P_WriteFixed(save_p, ht->momy);
+	P_WriteINT32(save_p, ht->distance);
+	P_WriteAngle(save_p, ht->angle);
 }
 
-static void SavePolywaypointThinker(const thinker_t *th, UINT8 type)
+static void SavePolywaypointThinker(save_t *save_p, const thinker_t *th, UINT8 type)
 {
 	const polywaypoint_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEINT32(save_p, ht->polyObjNum);
-	WRITEINT32(save_p, ht->speed);
-	WRITEINT32(save_p, ht->sequence);
-	WRITEINT32(save_p, ht->pointnum);
-	WRITEINT32(save_p, ht->direction);
-	WRITEUINT8(save_p, ht->returnbehavior);
-	WRITEUINT8(save_p, ht->continuous);
-	WRITEUINT8(save_p, ht->stophere);
+	P_WriteUINT8(save_p, type);
+	P_WriteINT32(save_p, ht->polyObjNum);
+	P_WriteINT32(save_p, ht->speed);
+	P_WriteINT32(save_p, ht->sequence);
+	P_WriteINT32(save_p, ht->pointnum);
+	P_WriteINT32(save_p, ht->direction);
+	P_WriteUINT8(save_p, ht->returnbehavior);
+	P_WriteUINT8(save_p, ht->continuous);
+	P_WriteUINT8(save_p, ht->stophere);
 }
 
-static void SavePolyslidedoorThinker(const thinker_t *th, const UINT8 type)
+static void SavePolyslidedoorThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const polyslidedoor_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEINT32(save_p, ht->polyObjNum);
-	WRITEINT32(save_p, ht->delay);
-	WRITEINT32(save_p, ht->delayCount);
-	WRITEINT32(save_p, ht->initSpeed);
-	WRITEINT32(save_p, ht->speed);
-	WRITEINT32(save_p, ht->initDistance);
-	WRITEINT32(save_p, ht->distance);
-	WRITEUINT32(save_p, ht->initAngle);
-	WRITEUINT32(save_p, ht->angle);
-	WRITEUINT32(save_p, ht->revAngle);
-	WRITEFIXED(save_p, ht->momx);
-	WRITEFIXED(save_p, ht->momy);
-	WRITEUINT8(save_p, ht->closing);
-}
-
-static void SavePolyswingdoorThinker(const thinker_t *th, const UINT8 type)
+	P_WriteUINT8(save_p, type);
+	P_WriteINT32(save_p, ht->polyObjNum);
+	P_WriteINT32(save_p, ht->delay);
+	P_WriteINT32(save_p, ht->delayCount);
+	P_WriteINT32(save_p, ht->initSpeed);
+	P_WriteINT32(save_p, ht->speed);
+	P_WriteINT32(save_p, ht->initDistance);
+	P_WriteINT32(save_p, ht->distance);
+	P_WriteUINT32(save_p, ht->initAngle);
+	P_WriteUINT32(save_p, ht->angle);
+	P_WriteUINT32(save_p, ht->revAngle);
+	P_WriteFixed(save_p, ht->momx);
+	P_WriteFixed(save_p, ht->momy);
+	P_WriteUINT8(save_p, ht->closing);
+}
+
+static void SavePolyswingdoorThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const polyswingdoor_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEINT32(save_p, ht->polyObjNum);
-	WRITEINT32(save_p, ht->delay);
-	WRITEINT32(save_p, ht->delayCount);
-	WRITEINT32(save_p, ht->initSpeed);
-	WRITEINT32(save_p, ht->speed);
-	WRITEINT32(save_p, ht->initDistance);
-	WRITEINT32(save_p, ht->distance);
-	WRITEUINT8(save_p, ht->closing);
+	P_WriteUINT8(save_p, type);
+	P_WriteINT32(save_p, ht->polyObjNum);
+	P_WriteINT32(save_p, ht->delay);
+	P_WriteINT32(save_p, ht->delayCount);
+	P_WriteINT32(save_p, ht->initSpeed);
+	P_WriteINT32(save_p, ht->speed);
+	P_WriteINT32(save_p, ht->initDistance);
+	P_WriteINT32(save_p, ht->distance);
+	P_WriteUINT8(save_p, ht->closing);
 }
 
-static void SavePolydisplaceThinker(const thinker_t *th, const UINT8 type)
+static void SavePolydisplaceThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const polydisplace_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEINT32(save_p, ht->polyObjNum);
-	WRITEUINT32(save_p, SaveSector(ht->controlSector));
-	WRITEFIXED(save_p, ht->dx);
-	WRITEFIXED(save_p, ht->dy);
-	WRITEFIXED(save_p, ht->oldHeights);
+	P_WriteUINT8(save_p, type);
+	P_WriteINT32(save_p, ht->polyObjNum);
+	P_WriteUINT32(save_p, SaveSector(ht->controlSector));
+	P_WriteFixed(save_p, ht->dx);
+	P_WriteFixed(save_p, ht->dy);
+	P_WriteFixed(save_p, ht->oldHeights);
 }
 
-static void SavePolyrotdisplaceThinker(const thinker_t *th, const UINT8 type)
+static void SavePolyrotdisplaceThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const polyrotdisplace_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEINT32(save_p, ht->polyObjNum);
-	WRITEUINT32(save_p, SaveSector(ht->controlSector));
-	WRITEFIXED(save_p, ht->rotscale);
-	WRITEUINT8(save_p, ht->turnobjs);
-	WRITEFIXED(save_p, ht->oldHeights);
+	P_WriteUINT8(save_p, type);
+	P_WriteINT32(save_p, ht->polyObjNum);
+	P_WriteUINT32(save_p, SaveSector(ht->controlSector));
+	P_WriteFixed(save_p, ht->rotscale);
+	P_WriteUINT8(save_p, ht->turnobjs);
+	P_WriteFixed(save_p, ht->oldHeights);
 }
 
-static void SavePolyfadeThinker(const thinker_t *th, const UINT8 type)
+static void SavePolyfadeThinker(save_t *save_p, const thinker_t *th, const UINT8 type)
 {
 	const polyfade_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-	WRITEINT32(save_p, ht->polyObjNum);
-	WRITEINT32(save_p, ht->sourcevalue);
-	WRITEINT32(save_p, ht->destvalue);
-	WRITEUINT8(save_p, (UINT8)ht->docollision);
-	WRITEUINT8(save_p, (UINT8)ht->doghostfade);
-	WRITEUINT8(save_p, (UINT8)ht->ticbased);
-	WRITEINT32(save_p, ht->duration);
-	WRITEINT32(save_p, ht->timer);
+	P_WriteUINT8(save_p, type);
+	P_WriteINT32(save_p, ht->polyObjNum);
+	P_WriteINT32(save_p, ht->sourcevalue);
+	P_WriteINT32(save_p, ht->destvalue);
+	P_WriteUINT8(save_p, (UINT8)ht->docollision);
+	P_WriteUINT8(save_p, (UINT8)ht->doghostfade);
+	P_WriteUINT8(save_p, (UINT8)ht->ticbased);
+	P_WriteINT32(save_p, ht->duration);
+	P_WriteINT32(save_p, ht->timer);
 }
 
-static void P_NetArchiveThinkers(void)
+static void P_NetArchiveThinkers(save_t *save_p)
 {
 	const thinker_t *th;
 	UINT32 i;
 
-	WRITEUINT32(save_p, ARCHIVEBLOCK_THINKERS);
+	P_WriteUINT32(save_p, ARCHIVEBLOCK_THINKERS);
 
 	for (i = 0; i < NUM_THINKERLISTS; i++)
 	{
@@ -2739,7 +2978,7 @@ static void P_NetArchiveThinkers(void)
 
 			if (th->function.acp1 == (actionf_p1)P_MobjThinker)
 			{
-				SaveMobjThinker(th, tc_mobj);
+				SaveMobjThinker(save_p, th, tc_mobj);
 				continue;
 			}
 	#ifdef PARANOIA
@@ -2747,202 +2986,202 @@ static void P_NetArchiveThinkers(void)
 	#endif
 			else if (th->function.acp1 == (actionf_p1)T_MoveCeiling)
 			{
-				SaveCeilingThinker(th, tc_ceiling);
+				SaveCeilingThinker(save_p, th, tc_ceiling);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_CrushCeiling)
 			{
-				SaveCeilingThinker(th, tc_crushceiling);
+				SaveCeilingThinker(save_p, th, tc_crushceiling);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_MoveFloor)
 			{
-				SaveFloormoveThinker(th, tc_floor);
+				SaveFloormoveThinker(save_p, th, tc_floor);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_LightningFlash)
 			{
-				SaveLightflashThinker(th, tc_flash);
+				SaveLightflashThinker(save_p, th, tc_flash);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_StrobeFlash)
 			{
-				SaveStrobeThinker(th, tc_strobe);
+				SaveStrobeThinker(save_p, th, tc_strobe);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_Glow)
 			{
-				SaveGlowThinker(th, tc_glow);
+				SaveGlowThinker(save_p, th, tc_glow);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_FireFlicker)
 			{
-				SaveFireflickerThinker(th, tc_fireflicker);
+				SaveFireflickerThinker(save_p, th, tc_fireflicker);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_MoveElevator)
 			{
-				SaveElevatorThinker(th, tc_elevator);
+				SaveElevatorThinker(save_p, th, tc_elevator);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_ContinuousFalling)
 			{
-				SaveContinuousFallThinker(th, tc_continuousfalling);
+				SaveContinuousFallThinker(save_p, th, tc_continuousfalling);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_ThwompSector)
 			{
-				SaveThwompThinker(th, tc_thwomp);
+				SaveThwompThinker(save_p, th, tc_thwomp);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_NoEnemiesSector)
 			{
-				SaveNoEnemiesThinker(th, tc_noenemies);
+				SaveNoEnemiesThinker(save_p, th, tc_noenemies);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_EachTimeThinker)
 			{
-				SaveEachTimeThinker(th, tc_eachtime);
+				SaveEachTimeThinker(save_p, th, tc_eachtime);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_RaiseSector)
 			{
-				SaveRaiseThinker(th, tc_raisesector);
+				SaveRaiseThinker(save_p, th, tc_raisesector);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_CameraScanner)
 			{
-				SaveElevatorThinker(th, tc_camerascanner);
+				SaveElevatorThinker(save_p, th, tc_camerascanner);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_Scroll)
 			{
-				SaveScrollThinker(th, tc_scroll);
+				SaveScrollThinker(save_p, th, tc_scroll);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_Friction)
 			{
-				SaveFrictionThinker(th, tc_friction);
+				SaveFrictionThinker(save_p, th, tc_friction);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_Pusher)
 			{
-				SavePusherThinker(th, tc_pusher);
+				SavePusherThinker(save_p, th, tc_pusher);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_BounceCheese)
 			{
-				SaveBounceCheeseThinker(th, tc_bouncecheese);
+				SaveBounceCheeseThinker(save_p, th, tc_bouncecheese);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_StartCrumble)
 			{
-				SaveCrumbleThinker(th, tc_startcrumble);
+				SaveCrumbleThinker(save_p, th, tc_startcrumble);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_MarioBlock)
 			{
-				SaveMarioBlockThinker(th, tc_marioblock);
+				SaveMarioBlockThinker(save_p, th, tc_marioblock);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_MarioBlockChecker)
 			{
-				SaveMarioCheckThinker(th, tc_marioblockchecker);
+				SaveMarioCheckThinker(save_p, th, tc_marioblockchecker);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_FloatSector)
 			{
-				SaveFloatThinker(th, tc_floatsector);
+				SaveFloatThinker(save_p, th, tc_floatsector);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_LaserFlash)
 			{
-				SaveLaserThinker(th, tc_laserflash);
+				SaveLaserThinker(save_p, th, tc_laserflash);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_LightFade)
 			{
-				SaveLightlevelThinker(th, tc_lightfade);
+				SaveLightlevelThinker(save_p, th, tc_lightfade);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_ExecutorDelay)
 			{
-				SaveExecutorThinker(th, tc_executor);
+				SaveExecutorThinker(save_p, th, tc_executor);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_Disappear)
 			{
-				SaveDisappearThinker(th, tc_disappear);
+				SaveDisappearThinker(save_p, th, tc_disappear);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_Fade)
 			{
-				SaveFadeThinker(th, tc_fade);
+				SaveFadeThinker(save_p, th, tc_fade);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_FadeColormap)
 			{
-				SaveFadeColormapThinker(th, tc_fadecolormap);
+				SaveFadeColormapThinker(save_p, th, tc_fadecolormap);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_PlaneDisplace)
 			{
-				SavePlaneDisplaceThinker(th, tc_planedisplace);
+				SavePlaneDisplaceThinker(save_p, th, tc_planedisplace);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_PolyObjRotate)
 			{
-				SavePolyrotatetThinker(th, tc_polyrotate);
+				SavePolyrotatetThinker(save_p, th, tc_polyrotate);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_PolyObjMove)
 			{
-				SavePolymoveThinker(th, tc_polymove);
+				SavePolymoveThinker(save_p, th, tc_polymove);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_PolyObjWaypoint)
 			{
-				SavePolywaypointThinker(th, tc_polywaypoint);
+				SavePolywaypointThinker(save_p, th, tc_polywaypoint);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_PolyDoorSlide)
 			{
-				SavePolyslidedoorThinker(th, tc_polyslidedoor);
+				SavePolyslidedoorThinker(save_p, th, tc_polyslidedoor);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_PolyDoorSwing)
 			{
-				SavePolyswingdoorThinker(th, tc_polyswingdoor);
+				SavePolyswingdoorThinker(save_p, th, tc_polyswingdoor);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_PolyObjFlag)
 			{
-				SavePolymoveThinker(th, tc_polyflag);
+				SavePolymoveThinker(save_p, th, tc_polyflag);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_PolyObjDisplace)
 			{
-				SavePolydisplaceThinker(th, tc_polydisplace);
+				SavePolydisplaceThinker(save_p, th, tc_polydisplace);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_PolyObjRotDisplace)
 			{
-				SavePolyrotdisplaceThinker(th, tc_polyrotdisplace);
+				SavePolyrotdisplaceThinker(save_p, th, tc_polyrotdisplace);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_PolyObjFade)
 			{
-				SavePolyfadeThinker(th, tc_polyfade);
+				SavePolyfadeThinker(save_p, th, tc_polyfade);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeLine)
 			{
-				SaveDynamicLineSlopeThinker(th, tc_dynslopeline);
+				SaveDynamicLineSlopeThinker(save_p, th, tc_dynslopeline);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeVert)
 			{
-				SaveDynamicVertexSlopeThinker(th, tc_dynslopevert);
+				SaveDynamicVertexSlopeThinker(save_p, th, tc_dynslopevert);
 				continue;
 			}
 #ifdef PARANOIA
@@ -2953,7 +3192,7 @@ static void P_NetArchiveThinkers(void)
 
 		CONS_Debug(DBG_NETPLAY, "%u thinkers saved in list %d\n", numsaved, i);
 
-		WRITEUINT8(save_p, tc_end);
+		P_WriteUINT8(save_p, tc_end);
 	}
 }
 
@@ -3017,7 +3256,7 @@ static inline pslope_t *LoadSlope(UINT32 slopeid)
 	return NULL;
 }
 
-static thinker_t* LoadMobjThinker(actionf_p1 thinker)
+static thinker_t* LoadMobjThinker(save_t *save_p, actionf_p1 thinker)
 {
 	thinker_t *next;
 	mobj_t *mobj;
@@ -3027,35 +3266,35 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
 	fixed_t z, floorz, ceilingz;
 	ffloor_t *floorrover = NULL, *ceilingrover = NULL;
 
-	diff = READUINT32(save_p);
+	diff = P_ReadUINT32(save_p);
 	if (diff & MD_MORE)
-		diff2 = READUINT32(save_p);
+		diff2 = P_ReadUINT32(save_p);
 	else
 		diff2 = 0;
 
-	next = (void *)(size_t)READUINT32(save_p);
+	next = (void *)(size_t)P_ReadUINT32(save_p);
 
-	z = READFIXED(save_p); // Force this so 3dfloor problems don't arise.
-	floorz = READFIXED(save_p);
-	ceilingz = READFIXED(save_p);
+	z = P_ReadFixed(save_p); // Force this so 3dfloor problems don't arise.
+	floorz = P_ReadFixed(save_p);
+	ceilingz = P_ReadFixed(save_p);
 
 	if (diff2 & MD2_FLOORROVER)
 	{
-		sector_t *sec = LoadSector(READUINT32(save_p));
-		UINT16 id = READUINT16(save_p);
+		sector_t *sec = LoadSector(P_ReadUINT32(save_p));
+		UINT16 id = P_ReadUINT16(save_p);
 		floorrover = P_GetFFloorByID(sec, id);
 	}
 
 	if (diff2 & MD2_CEILINGROVER)
 	{
-		sector_t *sec = LoadSector(READUINT32(save_p));
-		UINT16 id = READUINT16(save_p);
+		sector_t *sec = LoadSector(P_ReadUINT32(save_p));
+		UINT16 id = P_ReadUINT16(save_p);
 		ceilingrover = P_GetFFloorByID(sec, id);
 	}
 
 	if (diff & MD_SPAWNPOINT)
 	{
-		UINT16 spawnpointnum = READUINT16(save_p);
+		UINT16 spawnpointnum = P_ReadUINT16(save_p);
 
 		if (mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case
 		{
@@ -3081,7 +3320,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
 	mobj->ceilingrover = ceilingrover;
 
 	if (diff & MD_TYPE)
-		mobj->type = READUINT32(save_p);
+		mobj->type = P_ReadUINT32(save_p);
 	else
 	{
 		for (i = 0; i < NUMMOBJTYPES; i++)
@@ -3100,11 +3339,11 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
 	mobj->info = &mobjinfo[mobj->type];
 	if (diff & MD_POS)
 	{
-		mobj->x = READFIXED(save_p);
-		mobj->y = READFIXED(save_p);
-		mobj->angle = READANGLE(save_p);
-		mobj->pitch = READANGLE(save_p);
-		mobj->roll = READANGLE(save_p);
+		mobj->x = P_ReadFixed(save_p);
+		mobj->y = P_ReadFixed(save_p);
+		mobj->angle = P_ReadAngle(save_p);
+		mobj->pitch = P_ReadAngle(save_p);
+		mobj->roll = P_ReadAngle(save_p);
 	}
 	else
 	{
@@ -3116,47 +3355,47 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
 	}
 	if (diff & MD_MOM)
 	{
-		mobj->momx = READFIXED(save_p);
-		mobj->momy = READFIXED(save_p);
-		mobj->momz = READFIXED(save_p);
-		mobj->pmomz = READFIXED(save_p);
+		mobj->momx = P_ReadFixed(save_p);
+		mobj->momy = P_ReadFixed(save_p);
+		mobj->momz = P_ReadFixed(save_p);
+		mobj->pmomz = P_ReadFixed(save_p);
 	} // otherwise they're zero, and the memset took care of it
 
 	if (diff & MD_RADIUS)
-		mobj->radius = READFIXED(save_p);
+		mobj->radius = P_ReadFixed(save_p);
 	else
 		mobj->radius = mobj->info->radius;
 	if (diff & MD_HEIGHT)
-		mobj->height = READFIXED(save_p);
+		mobj->height = P_ReadFixed(save_p);
 	else
 		mobj->height = mobj->info->height;
 	if (diff & MD_FLAGS)
-		mobj->flags = READUINT32(save_p);
+		mobj->flags = P_ReadUINT32(save_p);
 	else
 		mobj->flags = mobj->info->flags;
 	if (diff & MD_FLAGS2)
-		mobj->flags2 = READUINT32(save_p);
+		mobj->flags2 = P_ReadUINT32(save_p);
 	if (diff & MD_HEALTH)
-		mobj->health = READINT32(save_p);
+		mobj->health = P_ReadINT32(save_p);
 	else
 		mobj->health = mobj->info->spawnhealth;
 	if (diff & MD_RTIME)
-		mobj->reactiontime = READINT32(save_p);
+		mobj->reactiontime = P_ReadINT32(save_p);
 	else
 		mobj->reactiontime = mobj->info->reactiontime;
 
 	if (diff & MD_STATE)
-		mobj->state = &states[READUINT16(save_p)];
+		mobj->state = &states[P_ReadUINT16(save_p)];
 	else
 		mobj->state = &states[mobj->info->spawnstate];
 	if (diff & MD_TICS)
-		mobj->tics = READINT32(save_p);
+		mobj->tics = P_ReadINT32(save_p);
 	else
 		mobj->tics = mobj->state->tics;
 	if (diff & MD_SPRITE) {
-		mobj->sprite = READUINT16(save_p);
+		mobj->sprite = P_ReadUINT16(save_p);
 		if (mobj->sprite == SPR_PLAY)
-			mobj->sprite2 = READUINT16(save_p);
+			mobj->sprite2 = P_ReadUINT16(save_p);
 	}
 	else {
 		mobj->sprite = mobj->state->sprite;
@@ -3165,8 +3404,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
 	}
 	if (diff & MD_FRAME)
 	{
-		mobj->frame = READUINT32(save_p);
-		mobj->anim_duration = READUINT16(save_p);
+		mobj->frame = P_ReadUINT32(save_p);
+		mobj->anim_duration = P_ReadUINT16(save_p);
 	}
 	else
 	{
@@ -3174,130 +3413,130 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
 		mobj->anim_duration = (UINT16)mobj->state->var2;
 	}
 	if (diff & MD_EFLAGS)
-		mobj->eflags = READUINT16(save_p);
+		mobj->eflags = P_ReadUINT16(save_p);
 	if (diff & MD_PLAYER)
 	{
-		i = READUINT8(save_p);
+		i = P_ReadUINT8(save_p);
 		mobj->player = &players[i];
 		mobj->player->mo = mobj;
 	}
 	if (diff & MD_MOVEDIR)
-		mobj->movedir = READANGLE(save_p);
+		mobj->movedir = P_ReadAngle(save_p);
 	if (diff & MD_MOVECOUNT)
-		mobj->movecount = READINT32(save_p);
+		mobj->movecount = P_ReadINT32(save_p);
 	if (diff & MD_THRESHOLD)
-		mobj->threshold = READINT32(save_p);
+		mobj->threshold = P_ReadINT32(save_p);
 	if (diff & MD_LASTLOOK)
-		mobj->lastlook = READINT32(save_p);
+		mobj->lastlook = P_ReadINT32(save_p);
 	else
 		mobj->lastlook = -1;
 	if (diff & MD_TARGET)
-		mobj->target = (mobj_t *)(size_t)READUINT32(save_p);
+		mobj->target = (mobj_t *)(size_t)P_ReadUINT32(save_p);
 	if (diff & MD_TRACER)
-		mobj->tracer = (mobj_t *)(size_t)READUINT32(save_p);
+		mobj->tracer = (mobj_t *)(size_t)P_ReadUINT32(save_p);
 	if (diff & MD_FRICTION)
-		mobj->friction = READFIXED(save_p);
+		mobj->friction = P_ReadFixed(save_p);
 	else
 		mobj->friction = ORIG_FRICTION;
 	if (diff & MD_MOVEFACTOR)
-		mobj->movefactor = READFIXED(save_p);
+		mobj->movefactor = P_ReadFixed(save_p);
 	else
 		mobj->movefactor = FRACUNIT;
 	if (diff & MD_FUSE)
-		mobj->fuse = READINT32(save_p);
+		mobj->fuse = P_ReadINT32(save_p);
 	if (diff & MD_WATERTOP)
-		mobj->watertop = READFIXED(save_p);
+		mobj->watertop = P_ReadFixed(save_p);
 	if (diff & MD_WATERBOTTOM)
-		mobj->waterbottom = READFIXED(save_p);
+		mobj->waterbottom = P_ReadFixed(save_p);
 	if (diff & MD_SCALE)
-		mobj->scale = READFIXED(save_p);
+		mobj->scale = P_ReadFixed(save_p);
 	else
 		mobj->scale = FRACUNIT;
 	if (diff & MD_DSCALE)
-		mobj->destscale = READFIXED(save_p);
+		mobj->destscale = P_ReadFixed(save_p);
 	else
 		mobj->destscale = mobj->scale;
 	if (diff2 & MD2_SCALESPEED)
-		mobj->scalespeed = READFIXED(save_p);
+		mobj->scalespeed = P_ReadFixed(save_p);
 	else
 		mobj->scalespeed = FRACUNIT/12;
 	if (diff2 & MD2_CUSVAL)
-		mobj->cusval = READINT32(save_p);
+		mobj->cusval = P_ReadINT32(save_p);
 	if (diff2 & MD2_CVMEM)
-		mobj->cvmem = READINT32(save_p);
+		mobj->cvmem = P_ReadINT32(save_p);
 	if (diff2 & MD2_SKIN)
-		mobj->skin = skins[READUINT8(save_p)];
+		mobj->skin = skins[P_ReadUINT8(save_p)];
 	if (diff2 & MD2_COLOR)
-		mobj->color = READUINT16(save_p);
+		mobj->color = P_ReadUINT16(save_p);
 	if (diff2 & MD2_EXTVAL1)
-		mobj->extravalue1 = READINT32(save_p);
+		mobj->extravalue1 = P_ReadINT32(save_p);
 	if (diff2 & MD2_EXTVAL2)
-		mobj->extravalue2 = READINT32(save_p);
+		mobj->extravalue2 = P_ReadINT32(save_p);
 	if (diff2 & MD2_HNEXT)
-		mobj->hnext = (mobj_t *)(size_t)READUINT32(save_p);
+		mobj->hnext = (mobj_t *)(size_t)P_ReadUINT32(save_p);
 	if (diff2 & MD2_HPREV)
-		mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p);
+		mobj->hprev = (mobj_t *)(size_t)P_ReadUINT32(save_p);
 	if (diff2 & MD2_SLOPE)
-		mobj->standingslope = P_SlopeById(READUINT16(save_p));
+		mobj->standingslope = P_SlopeById(P_ReadUINT16(save_p));
 	if (diff2 & MD2_COLORIZED)
-		mobj->colorized = READUINT8(save_p);
+		mobj->colorized = P_ReadUINT8(save_p);
 	if (diff2 & MD2_MIRRORED)
-		mobj->mirrored = READUINT8(save_p);
+		mobj->mirrored = P_ReadUINT8(save_p);
 	if (diff2 & MD2_SPRITEROLL)
-		mobj->spriteroll = READANGLE(save_p);
+		mobj->spriteroll = P_ReadAngle(save_p);
 	if (diff2 & MD2_SHADOWSCALE)
-		mobj->shadowscale = READFIXED(save_p);
+		mobj->shadowscale = P_ReadFixed(save_p);
 	if (diff2 & MD2_RENDERFLAGS)
-		mobj->renderflags = READUINT32(save_p);
+		mobj->renderflags = P_ReadUINT32(save_p);
 	if (diff2 & MD2_BLENDMODE)
-		mobj->blendmode = READINT32(save_p);
+		mobj->blendmode = P_ReadINT32(save_p);
 	else
 		mobj->blendmode = AST_TRANSLUCENT;
 	if (diff2 & MD2_SPRITEXSCALE)
-		mobj->spritexscale = READFIXED(save_p);
+		mobj->spritexscale = P_ReadFixed(save_p);
 	else
 		mobj->spritexscale = FRACUNIT;
 	if (diff2 & MD2_SPRITEYSCALE)
-		mobj->spriteyscale = READFIXED(save_p);
+		mobj->spriteyscale = P_ReadFixed(save_p);
 	else
 		mobj->spriteyscale = FRACUNIT;
 	if (diff2 & MD2_SPRITEXOFFSET)
-		mobj->spritexoffset = READFIXED(save_p);
+		mobj->spritexoffset = P_ReadFixed(save_p);
 	if (diff2 & MD2_SPRITEYOFFSET)
-		mobj->spriteyoffset = READFIXED(save_p);
+		mobj->spriteyoffset = P_ReadFixed(save_p);
 	if (diff2 & MD2_FLOORSPRITESLOPE)
 	{
 		pslope_t *slope = (pslope_t *)P_CreateFloorSpriteSlope(mobj);
 
-		slope->zdelta = READFIXED(save_p);
-		slope->zangle = READANGLE(save_p);
-		slope->xydirection = READANGLE(save_p);
+		slope->zdelta = P_ReadFixed(save_p);
+		slope->zangle = P_ReadAngle(save_p);
+		slope->xydirection = P_ReadAngle(save_p);
 
-		slope->o.x = READFIXED(save_p);
-		slope->o.y = READFIXED(save_p);
-		slope->o.z = READFIXED(save_p);
+		slope->o.x = P_ReadFixed(save_p);
+		slope->o.y = P_ReadFixed(save_p);
+		slope->o.z = P_ReadFixed(save_p);
 
-		slope->d.x = READFIXED(save_p);
-		slope->d.y = READFIXED(save_p);
+		slope->d.x = P_ReadFixed(save_p);
+		slope->d.y = P_ReadFixed(save_p);
 
-		slope->normal.x = READFIXED(save_p);
-		slope->normal.y = READFIXED(save_p);
-		slope->normal.z = READFIXED(save_p);
+		slope->normal.x = P_ReadFixed(save_p);
+		slope->normal.y = P_ReadFixed(save_p);
+		slope->normal.z = P_ReadFixed(save_p);
 
 		slope->moved = true;
 	}
 	if (diff2 & MD2_DRAWONLYFORPLAYER)
-		mobj->drawonlyforplayer = &players[READUINT8(save_p)];
+		mobj->drawonlyforplayer = &players[P_ReadUINT8(save_p)];
 	if (diff2 & MD2_DONTDRAWFORVIEWMOBJ)
-		mobj->dontdrawforviewmobj = (mobj_t *)(size_t)READUINT32(save_p);
+		mobj->dontdrawforviewmobj = (mobj_t *)(size_t)P_ReadUINT32(save_p);
 	if (diff2 & MD2_DISPOFFSET)
-		mobj->dispoffset = READINT32(save_p);
+		mobj->dispoffset = P_ReadINT32(save_p);
 	else
 		mobj->dispoffset = mobj->info->dispoffset;
 	if (diff2 & MD2_TRANSLATION)
-		mobj->translation = READUINT16(save_p);
+		mobj->translation = P_ReadUINT16(save_p);
 	if (diff2 & MD2_ALPHA)
-		mobj->alpha = READFIXED(save_p);
+		mobj->alpha = P_ReadFixed(save_p);
 	else
 		mobj->alpha = FRACUNIT;
 
@@ -3315,7 +3554,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
 	// set sprev, snext, bprev, bnext, subsector
 	P_SetThingPosition(mobj);
 
-	mobj->mobjnum = READUINT32(save_p);
+	mobj->mobjnum = P_ReadUINT32(save_p);
 
 	if (mobj->player)
 	{
@@ -3344,25 +3583,25 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
 	return &mobj->thinker;
 }
 
-static thinker_t* LoadNoEnemiesThinker(actionf_p1 thinker)
+static thinker_t* LoadNoEnemiesThinker(save_t *save_p, actionf_p1 thinker)
 {
 	noenemies_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->sourceline = LoadLine(READUINT32(save_p));
+	ht->sourceline = LoadLine(P_ReadUINT32(save_p));
 	return &ht->thinker;
 }
 
-static thinker_t* LoadBounceCheeseThinker(actionf_p1 thinker)
+static thinker_t* LoadBounceCheeseThinker(save_t *save_p, actionf_p1 thinker)
 {
 	bouncecheese_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->sourceline = LoadLine(READUINT32(save_p));
-	ht->sector = LoadSector(READUINT32(save_p));
-	ht->speed = READFIXED(save_p);
-	ht->distance = READFIXED(save_p);
-	ht->floorwasheight = READFIXED(save_p);
-	ht->ceilingwasheight = READFIXED(save_p);
-	ht->low = READCHAR(save_p);
+	ht->sourceline = LoadLine(P_ReadUINT32(save_p));
+	ht->sector = LoadSector(P_ReadUINT32(save_p));
+	ht->speed = P_ReadFixed(save_p);
+	ht->distance = P_ReadFixed(save_p);
+	ht->floorwasheight = P_ReadFixed(save_p);
+	ht->ceilingwasheight = P_ReadFixed(save_p);
+	ht->low = P_ReadChar(save_p);
 
 	if (ht->sector)
 		ht->sector->ceilingdata = ht;
@@ -3370,16 +3609,16 @@ static thinker_t* LoadBounceCheeseThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-static thinker_t* LoadContinuousFallThinker(actionf_p1 thinker)
+static thinker_t* LoadContinuousFallThinker(save_t *save_p, actionf_p1 thinker)
 {
 	continuousfall_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->sector = LoadSector(READUINT32(save_p));
-	ht->speed = READFIXED(save_p);
-	ht->direction = READINT32(save_p);
-	ht->floorstartheight = READFIXED(save_p);
-	ht->ceilingstartheight = READFIXED(save_p);
-	ht->destheight = READFIXED(save_p);
+	ht->sector = LoadSector(P_ReadUINT32(save_p));
+	ht->speed = P_ReadFixed(save_p);
+	ht->direction = P_ReadINT32(save_p);
+	ht->floorstartheight = P_ReadFixed(save_p);
+	ht->ceilingstartheight = P_ReadFixed(save_p);
+	ht->destheight = P_ReadFixed(save_p);
 
 	if (ht->sector)
 	{
@@ -3390,16 +3629,16 @@ static thinker_t* LoadContinuousFallThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker)
+static thinker_t* LoadMarioBlockThinker(save_t *save_p, actionf_p1 thinker)
 {
 	mariothink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->sector = LoadSector(READUINT32(save_p));
-	ht->speed = READFIXED(save_p);
-	ht->direction = READINT32(save_p);
-	ht->floorstartheight = READFIXED(save_p);
-	ht->ceilingstartheight = READFIXED(save_p);
-	ht->tag = READINT16(save_p);
+	ht->sector = LoadSector(P_ReadUINT32(save_p));
+	ht->speed = P_ReadFixed(save_p);
+	ht->direction = P_ReadINT32(save_p);
+	ht->floorstartheight = P_ReadFixed(save_p);
+	ht->ceilingstartheight = P_ReadFixed(save_p);
+	ht->tag = P_ReadINT16(save_p);
 
 	if (ht->sector)
 	{
@@ -3410,29 +3649,29 @@ static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-static thinker_t* LoadMarioCheckThinker(actionf_p1 thinker)
+static thinker_t* LoadMarioCheckThinker(save_t *save_p, actionf_p1 thinker)
 {
 	mariocheck_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->sourceline = LoadLine(READUINT32(save_p));
-	ht->sector = LoadSector(READUINT32(save_p));
+	ht->sourceline = LoadLine(P_ReadUINT32(save_p));
+	ht->sector = LoadSector(P_ReadUINT32(save_p));
 	return &ht->thinker;
 }
 
-static thinker_t* LoadThwompThinker(actionf_p1 thinker)
+static thinker_t* LoadThwompThinker(save_t *save_p, actionf_p1 thinker)
 {
 	thwomp_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->sourceline = LoadLine(READUINT32(save_p));
-	ht->sector = LoadSector(READUINT32(save_p));
-	ht->crushspeed = READFIXED(save_p);
-	ht->retractspeed = READFIXED(save_p);
-	ht->direction = READINT32(save_p);
-	ht->floorstartheight = READFIXED(save_p);
-	ht->ceilingstartheight = READFIXED(save_p);
-	ht->delay = READINT32(save_p);
-	ht->tag = READINT16(save_p);
-	ht->sound = READUINT16(save_p);
+	ht->sourceline = LoadLine(P_ReadUINT32(save_p));
+	ht->sector = LoadSector(P_ReadUINT32(save_p));
+	ht->crushspeed = P_ReadFixed(save_p);
+	ht->retractspeed = P_ReadFixed(save_p);
+	ht->direction = P_ReadINT32(save_p);
+	ht->floorstartheight = P_ReadFixed(save_p);
+	ht->ceilingstartheight = P_ReadFixed(save_p);
+	ht->delay = P_ReadINT32(save_p);
+	ht->tag = P_ReadINT16(save_p);
+	ht->sound = P_ReadUINT16(save_p);
 
 	if (ht->sector)
 	{
@@ -3443,163 +3682,163 @@ static thinker_t* LoadThwompThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-static thinker_t* LoadFloatThinker(actionf_p1 thinker)
+static thinker_t* LoadFloatThinker(save_t *save_p, actionf_p1 thinker)
 {
 	floatthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->sourceline = LoadLine(READUINT32(save_p));
-	ht->sector = LoadSector(READUINT32(save_p));
-	ht->tag = READINT16(save_p);
+	ht->sourceline = LoadLine(P_ReadUINT32(save_p));
+	ht->sector = LoadSector(P_ReadUINT32(save_p));
+	ht->tag = P_ReadINT16(save_p);
 	return &ht->thinker;
 }
 
-static thinker_t* LoadEachTimeThinker(actionf_p1 thinker)
+static thinker_t* LoadEachTimeThinker(save_t *save_p, actionf_p1 thinker)
 {
 	size_t i;
 	eachtime_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->sourceline = LoadLine(READUINT32(save_p));
+	ht->sourceline = LoadLine(P_ReadUINT32(save_p));
 	for (i = 0; i < MAXPLAYERS; i++)
 	{
-		ht->playersInArea[i] = READCHAR(save_p);
+		ht->playersInArea[i] = P_ReadChar(save_p);
 	}
-	ht->triggerOnExit = READCHAR(save_p);
+	ht->triggerOnExit = P_ReadChar(save_p);
 	return &ht->thinker;
 }
 
-static thinker_t* LoadRaiseThinker(actionf_p1 thinker)
+static thinker_t* LoadRaiseThinker(save_t *save_p, actionf_p1 thinker)
 {
 	raise_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->tag = READINT16(save_p);
-	ht->sector = LoadSector(READUINT32(save_p));
-	ht->ceilingbottom = READFIXED(save_p);
-	ht->ceilingtop = READFIXED(save_p);
-	ht->basespeed = READFIXED(save_p);
-	ht->extraspeed = READFIXED(save_p);
-	ht->shaketimer = READUINT8(save_p);
-	ht->flags = READUINT8(save_p);
+	ht->tag = P_ReadINT16(save_p);
+	ht->sector = LoadSector(P_ReadUINT32(save_p));
+	ht->ceilingbottom = P_ReadFixed(save_p);
+	ht->ceilingtop = P_ReadFixed(save_p);
+	ht->basespeed = P_ReadFixed(save_p);
+	ht->extraspeed = P_ReadFixed(save_p);
+	ht->shaketimer = P_ReadUINT8(save_p);
+	ht->flags = P_ReadUINT8(save_p);
 	return &ht->thinker;
 }
 
-static thinker_t* LoadCeilingThinker(actionf_p1 thinker)
+static thinker_t* LoadCeilingThinker(save_t *save_p, actionf_p1 thinker)
 {
 	ceiling_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->type = READUINT8(save_p);
-	ht->sector = LoadSector(READUINT32(save_p));
-	ht->bottomheight = READFIXED(save_p);
-	ht->topheight = READFIXED(save_p);
-	ht->speed = READFIXED(save_p);
-	ht->delay = READFIXED(save_p);
-	ht->delaytimer = READFIXED(save_p);
-	ht->crush = READUINT8(save_p);
-	ht->texture = READINT32(save_p);
-	ht->direction = READINT32(save_p);
-	ht->tag = READINT16(save_p);
-	ht->origspeed = READFIXED(save_p);
-	ht->sourceline = READFIXED(save_p);
+	ht->type = P_ReadUINT8(save_p);
+	ht->sector = LoadSector(P_ReadUINT32(save_p));
+	ht->bottomheight = P_ReadFixed(save_p);
+	ht->topheight = P_ReadFixed(save_p);
+	ht->speed = P_ReadFixed(save_p);
+	ht->delay = P_ReadFixed(save_p);
+	ht->delaytimer = P_ReadFixed(save_p);
+	ht->crush = P_ReadUINT8(save_p);
+	ht->texture = P_ReadINT32(save_p);
+	ht->direction = P_ReadINT32(save_p);
+	ht->tag = P_ReadINT16(save_p);
+	ht->origspeed = P_ReadFixed(save_p);
+	ht->sourceline = P_ReadFixed(save_p);
 	if (ht->sector)
 		ht->sector->ceilingdata = ht;
 	return &ht->thinker;
 }
 
-static thinker_t* LoadFloormoveThinker(actionf_p1 thinker)
+static thinker_t* LoadFloormoveThinker(save_t *save_p, actionf_p1 thinker)
 {
 	floormove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->type = READUINT8(save_p);
-	ht->crush = READUINT8(save_p);
-	ht->sector = LoadSector(READUINT32(save_p));
-	ht->direction = READINT32(save_p);
-	ht->texture = READINT32(save_p);
-	ht->floordestheight = READFIXED(save_p);
-	ht->speed = READFIXED(save_p);
-	ht->origspeed = READFIXED(save_p);
-	ht->delay = READFIXED(save_p);
-	ht->delaytimer = READFIXED(save_p);
-	ht->tag = READINT16(save_p);
-	ht->sourceline = READFIXED(save_p);
+	ht->type = P_ReadUINT8(save_p);
+	ht->crush = P_ReadUINT8(save_p);
+	ht->sector = LoadSector(P_ReadUINT32(save_p));
+	ht->direction = P_ReadINT32(save_p);
+	ht->texture = P_ReadINT32(save_p);
+	ht->floordestheight = P_ReadFixed(save_p);
+	ht->speed = P_ReadFixed(save_p);
+	ht->origspeed = P_ReadFixed(save_p);
+	ht->delay = P_ReadFixed(save_p);
+	ht->delaytimer = P_ReadFixed(save_p);
+	ht->tag = P_ReadINT16(save_p);
+	ht->sourceline = P_ReadFixed(save_p);
 	if (ht->sector)
 		ht->sector->floordata = ht;
 	return &ht->thinker;
 }
 
-static thinker_t* LoadLightflashThinker(actionf_p1 thinker)
+static thinker_t* LoadLightflashThinker(save_t *save_p, actionf_p1 thinker)
 {
 	lightflash_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->sector = LoadSector(READUINT32(save_p));
-	ht->maxlight = READINT32(save_p);
-	ht->minlight = READINT32(save_p);
+	ht->sector = LoadSector(P_ReadUINT32(save_p));
+	ht->maxlight = P_ReadINT32(save_p);
+	ht->minlight = P_ReadINT32(save_p);
 	if (ht->sector)
 		ht->sector->lightingdata = ht;
 	return &ht->thinker;
 }
 
-static thinker_t* LoadStrobeThinker(actionf_p1 thinker)
+static thinker_t* LoadStrobeThinker(save_t *save_p, actionf_p1 thinker)
 {
 	strobe_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->sector = LoadSector(READUINT32(save_p));
-	ht->count = READINT32(save_p);
-	ht->minlight = READINT16(save_p);
-	ht->maxlight = READINT16(save_p);
-	ht->darktime = READINT32(save_p);
-	ht->brighttime = READINT32(save_p);
+	ht->sector = LoadSector(P_ReadUINT32(save_p));
+	ht->count = P_ReadINT32(save_p);
+	ht->minlight = P_ReadINT16(save_p);
+	ht->maxlight = P_ReadINT16(save_p);
+	ht->darktime = P_ReadINT32(save_p);
+	ht->brighttime = P_ReadINT32(save_p);
 	if (ht->sector)
 		ht->sector->lightingdata = ht;
 	return &ht->thinker;
 }
 
-static thinker_t* LoadGlowThinker(actionf_p1 thinker)
+static thinker_t* LoadGlowThinker(save_t *save_p, actionf_p1 thinker)
 {
 	glow_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->sector = LoadSector(READUINT32(save_p));
-	ht->minlight = READINT16(save_p);
-	ht->maxlight = READINT16(save_p);
-	ht->direction = READINT16(save_p);
-	ht->speed = READINT16(save_p);
+	ht->sector = LoadSector(P_ReadUINT32(save_p));
+	ht->minlight = P_ReadINT16(save_p);
+	ht->maxlight = P_ReadINT16(save_p);
+	ht->direction = P_ReadINT16(save_p);
+	ht->speed = P_ReadINT16(save_p);
 	if (ht->sector)
 		ht->sector->lightingdata = ht;
 	return &ht->thinker;
 }
 
-static thinker_t* LoadFireflickerThinker(actionf_p1 thinker)
+static thinker_t* LoadFireflickerThinker(save_t *save_p, actionf_p1 thinker)
 {
 	fireflicker_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->sector = LoadSector(READUINT32(save_p));
-	ht->count = READINT32(save_p);
-	ht->resetcount = READINT32(save_p);
-	ht->maxlight = READINT16(save_p);
-	ht->minlight = READINT16(save_p);
+	ht->sector = LoadSector(P_ReadUINT32(save_p));
+	ht->count = P_ReadINT32(save_p);
+	ht->resetcount = P_ReadINT32(save_p);
+	ht->maxlight = P_ReadINT16(save_p);
+	ht->minlight = P_ReadINT16(save_p);
 	if (ht->sector)
 		ht->sector->lightingdata = ht;
 	return &ht->thinker;
 }
 
-static thinker_t* LoadElevatorThinker(actionf_p1 thinker, boolean setplanedata)
+static thinker_t* LoadElevatorThinker(save_t *save_p, actionf_p1 thinker, boolean setplanedata)
 {
 	elevator_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->type = READUINT8(save_p);
-	ht->sector = LoadSector(READUINT32(save_p));
-	ht->actionsector = LoadSector(READUINT32(save_p));
-	ht->direction = READINT32(save_p);
-	ht->floordestheight = READFIXED(save_p);
-	ht->ceilingdestheight = READFIXED(save_p);
-	ht->speed = READFIXED(save_p);
-	ht->origspeed = READFIXED(save_p);
-	ht->low = READFIXED(save_p);
-	ht->high = READFIXED(save_p);
-	ht->distance = READFIXED(save_p);
-	ht->delay = READFIXED(save_p);
-	ht->delaytimer = READFIXED(save_p);
-	ht->floorwasheight = READFIXED(save_p);
-	ht->ceilingwasheight = READFIXED(save_p);
-	ht->sourceline = LoadLine(READUINT32(save_p));
+	ht->type = P_ReadUINT8(save_p);
+	ht->sector = LoadSector(P_ReadUINT32(save_p));
+	ht->actionsector = LoadSector(P_ReadUINT32(save_p));
+	ht->direction = P_ReadINT32(save_p);
+	ht->floordestheight = P_ReadFixed(save_p);
+	ht->ceilingdestheight = P_ReadFixed(save_p);
+	ht->speed = P_ReadFixed(save_p);
+	ht->origspeed = P_ReadFixed(save_p);
+	ht->low = P_ReadFixed(save_p);
+	ht->high = P_ReadFixed(save_p);
+	ht->distance = P_ReadFixed(save_p);
+	ht->delay = P_ReadFixed(save_p);
+	ht->delaytimer = P_ReadFixed(save_p);
+	ht->floorwasheight = P_ReadFixed(save_p);
+	ht->ceilingwasheight = P_ReadFixed(save_p);
+	ht->sourceline = LoadLine(P_ReadUINT32(save_p));
 
 	if (ht->sector && setplanedata)
 	{
@@ -3610,21 +3849,21 @@ static thinker_t* LoadElevatorThinker(actionf_p1 thinker, boolean setplanedata)
 	return &ht->thinker;
 }
 
-static thinker_t* LoadCrumbleThinker(actionf_p1 thinker)
+static thinker_t* LoadCrumbleThinker(save_t *save_p, actionf_p1 thinker)
 {
 	crumble_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->sourceline = LoadLine(READUINT32(save_p));
-	ht->sector = LoadSector(READUINT32(save_p));
-	ht->actionsector = LoadSector(READUINT32(save_p));
-	ht->player = LoadPlayer(READUINT32(save_p));
-	ht->direction = READINT32(save_p);
-	ht->origalpha = READINT32(save_p);
-	ht->timer = READINT32(save_p);
-	ht->speed = READFIXED(save_p);
-	ht->floorwasheight = READFIXED(save_p);
-	ht->ceilingwasheight = READFIXED(save_p);
-	ht->flags = READUINT8(save_p);
+	ht->sourceline = LoadLine(P_ReadUINT32(save_p));
+	ht->sector = LoadSector(P_ReadUINT32(save_p));
+	ht->actionsector = LoadSector(P_ReadUINT32(save_p));
+	ht->player = LoadPlayer(P_ReadUINT32(save_p));
+	ht->direction = P_ReadINT32(save_p);
+	ht->origalpha = P_ReadINT32(save_p);
+	ht->timer = P_ReadINT32(save_p);
+	ht->speed = P_ReadFixed(save_p);
+	ht->floorwasheight = P_ReadFixed(save_p);
+	ht->ceilingwasheight = P_ReadFixed(save_p);
+	ht->flags = P_ReadUINT8(save_p);
 
 	if (ht->sector)
 		ht->sector->floordata = ht;
@@ -3632,123 +3871,123 @@ static thinker_t* LoadCrumbleThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-static thinker_t* LoadScrollThinker(actionf_p1 thinker)
+static thinker_t* LoadScrollThinker(save_t *save_p, actionf_p1 thinker)
 {
 	scroll_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->dx = READFIXED(save_p);
-	ht->dy = READFIXED(save_p);
-	ht->affectee = READINT32(save_p);
-	ht->control = READINT32(save_p);
-	ht->last_height = READFIXED(save_p);
-	ht->vdx = READFIXED(save_p);
-	ht->vdy = READFIXED(save_p);
-	ht->accel = READINT32(save_p);
-	ht->exclusive = READINT32(save_p);
-	ht->type = READUINT8(save_p);
+	ht->dx = P_ReadFixed(save_p);
+	ht->dy = P_ReadFixed(save_p);
+	ht->affectee = P_ReadINT32(save_p);
+	ht->control = P_ReadINT32(save_p);
+	ht->last_height = P_ReadFixed(save_p);
+	ht->vdx = P_ReadFixed(save_p);
+	ht->vdy = P_ReadFixed(save_p);
+	ht->accel = P_ReadINT32(save_p);
+	ht->exclusive = P_ReadINT32(save_p);
+	ht->type = P_ReadUINT8(save_p);
 	return &ht->thinker;
 }
 
-static inline thinker_t* LoadFrictionThinker(actionf_p1 thinker)
+static inline thinker_t* LoadFrictionThinker(save_t *save_p, actionf_p1 thinker)
 {
 	friction_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->friction = READINT32(save_p);
-	ht->movefactor = READINT32(save_p);
-	ht->affectee = READINT32(save_p);
-	ht->referrer = READINT32(save_p);
-	ht->roverfriction = READUINT8(save_p);
+	ht->friction = P_ReadINT32(save_p);
+	ht->movefactor = P_ReadINT32(save_p);
+	ht->affectee = P_ReadINT32(save_p);
+	ht->referrer = P_ReadINT32(save_p);
+	ht->roverfriction = P_ReadUINT8(save_p);
 	return &ht->thinker;
 }
 
-static thinker_t* LoadPusherThinker(actionf_p1 thinker)
+static thinker_t* LoadPusherThinker(save_t *save_p, actionf_p1 thinker)
 {
 	pusher_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->type = READUINT8(save_p);
-	ht->x_mag = READFIXED(save_p);
-	ht->y_mag = READFIXED(save_p);
-	ht->z_mag = READFIXED(save_p);
-	ht->affectee = READINT32(save_p);
-	ht->roverpusher = READUINT8(save_p);
-	ht->referrer = READINT32(save_p);
-	ht->exclusive = READINT32(save_p);
-	ht->slider = READINT32(save_p);
+	ht->type = P_ReadUINT8(save_p);
+	ht->x_mag = P_ReadFixed(save_p);
+	ht->y_mag = P_ReadFixed(save_p);
+	ht->z_mag = P_ReadFixed(save_p);
+	ht->affectee = P_ReadINT32(save_p);
+	ht->roverpusher = P_ReadUINT8(save_p);
+	ht->referrer = P_ReadINT32(save_p);
+	ht->exclusive = P_ReadINT32(save_p);
+	ht->slider = P_ReadINT32(save_p);
 	return &ht->thinker;
 }
 
-static inline thinker_t* LoadLaserThinker(actionf_p1 thinker)
+static inline thinker_t* LoadLaserThinker(save_t *save_p, actionf_p1 thinker)
 {
 	laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->tag = READINT16(save_p);
-	ht->sourceline = LoadLine(READUINT32(save_p));
-	ht->nobosses = READUINT8(save_p);
+	ht->tag = P_ReadINT16(save_p);
+	ht->sourceline = LoadLine(P_ReadUINT32(save_p));
+	ht->nobosses = P_ReadUINT8(save_p);
 	return &ht->thinker;
 }
 
-static inline thinker_t* LoadLightlevelThinker(actionf_p1 thinker)
+static inline thinker_t* LoadLightlevelThinker(save_t *save_p, actionf_p1 thinker)
 {
 	lightlevel_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->sector = LoadSector(READUINT32(save_p));
-	ht->sourcelevel = READINT16(save_p);
-	ht->destlevel = READINT16(save_p);
-	ht->fixedcurlevel = READFIXED(save_p);
-	ht->fixedpertic = READFIXED(save_p);
-	ht->timer = READINT32(save_p);
+	ht->sector = LoadSector(P_ReadUINT32(save_p));
+	ht->sourcelevel = P_ReadINT16(save_p);
+	ht->destlevel = P_ReadINT16(save_p);
+	ht->fixedcurlevel = P_ReadFixed(save_p);
+	ht->fixedpertic = P_ReadFixed(save_p);
+	ht->timer = P_ReadINT32(save_p);
 	if (ht->sector)
 		ht->sector->lightingdata = ht;
 	return &ht->thinker;
 }
 
-static inline thinker_t* LoadExecutorThinker(actionf_p1 thinker)
+static inline thinker_t* LoadExecutorThinker(save_t *save_p, actionf_p1 thinker)
 {
 	executor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->line = LoadLine(READUINT32(save_p));
-	ht->caller = LoadMobj(READUINT32(save_p));
-	ht->sector = LoadSector(READUINT32(save_p));
-	ht->timer = READINT32(save_p);
+	ht->line = LoadLine(P_ReadUINT32(save_p));
+	ht->caller = LoadMobj(P_ReadUINT32(save_p));
+	ht->sector = LoadSector(P_ReadUINT32(save_p));
+	ht->timer = P_ReadINT32(save_p);
 	return &ht->thinker;
 }
 
-static inline thinker_t* LoadDisappearThinker(actionf_p1 thinker)
+static inline thinker_t* LoadDisappearThinker(save_t *save_p, actionf_p1 thinker)
 {
 	disappear_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->appeartime = READUINT32(save_p);
-	ht->disappeartime = READUINT32(save_p);
-	ht->offset = READUINT32(save_p);
-	ht->timer = READUINT32(save_p);
-	ht->affectee = READINT32(save_p);
-	ht->sourceline = READINT32(save_p);
-	ht->exists = READINT32(save_p);
+	ht->appeartime = P_ReadUINT32(save_p);
+	ht->disappeartime = P_ReadUINT32(save_p);
+	ht->offset = P_ReadUINT32(save_p);
+	ht->timer = P_ReadUINT32(save_p);
+	ht->affectee = P_ReadINT32(save_p);
+	ht->sourceline = P_ReadINT32(save_p);
+	ht->exists = P_ReadINT32(save_p);
 	return &ht->thinker;
 }
 
-static inline thinker_t* LoadFadeThinker(actionf_p1 thinker)
+static inline thinker_t* LoadFadeThinker(save_t *save_p, actionf_p1 thinker)
 {
 	sector_t *ss;
 	fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->dest_exc = GetNetColormapFromList(READUINT32(save_p));
-	ht->sectornum = READUINT32(save_p);
-	ht->ffloornum = READUINT32(save_p);
-	ht->alpha = READINT32(save_p);
-	ht->sourcevalue = READINT16(save_p);
-	ht->destvalue = READINT16(save_p);
-	ht->destlightlevel = READINT16(save_p);
-	ht->speed = READINT16(save_p);
-	ht->ticbased = (boolean)READUINT8(save_p);
-	ht->timer = READINT32(save_p);
-	ht->doexists = READUINT8(save_p);
-	ht->dotranslucent = READUINT8(save_p);
-	ht->dolighting = READUINT8(save_p);
-	ht->docolormap = READUINT8(save_p);
-	ht->docollision = READUINT8(save_p);
-	ht->doghostfade = READUINT8(save_p);
-	ht->exactalpha = READUINT8(save_p);
+	ht->dest_exc = GetNetColormapFromList(P_ReadUINT32(save_p));
+	ht->sectornum = P_ReadUINT32(save_p);
+	ht->ffloornum = P_ReadUINT32(save_p);
+	ht->alpha = P_ReadINT32(save_p);
+	ht->sourcevalue = P_ReadINT16(save_p);
+	ht->destvalue = P_ReadINT16(save_p);
+	ht->destlightlevel = P_ReadINT16(save_p);
+	ht->speed = P_ReadINT16(save_p);
+	ht->ticbased = (boolean)P_ReadUINT8(save_p);
+	ht->timer = P_ReadINT32(save_p);
+	ht->doexists = P_ReadUINT8(save_p);
+	ht->dotranslucent = P_ReadUINT8(save_p);
+	ht->dolighting = P_ReadUINT8(save_p);
+	ht->docolormap = P_ReadUINT8(save_p);
+	ht->docollision = P_ReadUINT8(save_p);
+	ht->doghostfade = P_ReadUINT8(save_p);
+	ht->exactalpha = P_ReadUINT8(save_p);
 
 	ss = LoadSector(ht->sectornum);
 	if (ss)
@@ -3769,176 +4008,176 @@ static inline thinker_t* LoadFadeThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-static inline thinker_t* LoadFadeColormapThinker(actionf_p1 thinker)
+static inline thinker_t* LoadFadeColormapThinker(save_t *save_p, actionf_p1 thinker)
 {
 	fadecolormap_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->sector = LoadSector(READUINT32(save_p));
-	ht->source_exc = GetNetColormapFromList(READUINT32(save_p));
-	ht->dest_exc = GetNetColormapFromList(READUINT32(save_p));
-	ht->ticbased = (boolean)READUINT8(save_p);
-	ht->duration = READINT32(save_p);
-	ht->timer = READINT32(save_p);
+	ht->sector = LoadSector(P_ReadUINT32(save_p));
+	ht->source_exc = GetNetColormapFromList(P_ReadUINT32(save_p));
+	ht->dest_exc = GetNetColormapFromList(P_ReadUINT32(save_p));
+	ht->ticbased = (boolean)P_ReadUINT8(save_p);
+	ht->duration = P_ReadINT32(save_p);
+	ht->timer = P_ReadINT32(save_p);
 	if (ht->sector)
 		ht->sector->fadecolormapdata = ht;
 	return &ht->thinker;
 }
 
-static inline thinker_t* LoadPlaneDisplaceThinker(actionf_p1 thinker)
+static inline thinker_t* LoadPlaneDisplaceThinker(save_t *save_p, actionf_p1 thinker)
 {
 	planedisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
 
-	ht->affectee = READINT32(save_p);
-	ht->control = READINT32(save_p);
-	ht->last_height = READFIXED(save_p);
-	ht->speed = READFIXED(save_p);
-	ht->type = READUINT8(save_p);
+	ht->affectee = P_ReadINT32(save_p);
+	ht->control = P_ReadINT32(save_p);
+	ht->last_height = P_ReadFixed(save_p);
+	ht->speed = P_ReadFixed(save_p);
+	ht->type = P_ReadUINT8(save_p);
 	return &ht->thinker;
 }
 
-static inline thinker_t* LoadDynamicLineSlopeThinker(actionf_p1 thinker)
+static inline thinker_t* LoadDynamicLineSlopeThinker(save_t *save_p, actionf_p1 thinker)
 {
 	dynlineplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
 
-	ht->type = READUINT8(save_p);
-	ht->slope = LoadSlope(READUINT32(save_p));
-	ht->sourceline = LoadLine(READUINT32(save_p));
-	ht->extent = READFIXED(save_p);
+	ht->type = P_ReadUINT8(save_p);
+	ht->slope = LoadSlope(P_ReadUINT32(save_p));
+	ht->sourceline = LoadLine(P_ReadUINT32(save_p));
+	ht->extent = P_ReadFixed(save_p);
 	return &ht->thinker;
 }
 
-static inline thinker_t* LoadDynamicVertexSlopeThinker(actionf_p1 thinker)
+static inline thinker_t* LoadDynamicVertexSlopeThinker(save_t *save_p, actionf_p1 thinker)
 {
 	size_t i;
 	dynvertexplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
 
-	ht->slope = LoadSlope(READUINT32(save_p));
+	ht->slope = LoadSlope(P_ReadUINT32(save_p));
 	for (i = 0; i < 3; i++)
-		ht->secs[i] = LoadSector(READUINT32(save_p));
-	READMEM(save_p, ht->vex, sizeof(ht->vex));
-	READMEM(save_p, ht->origsecheights, sizeof(ht->origsecheights));
-	READMEM(save_p, ht->origvecheights, sizeof(ht->origvecheights));
-	ht->relative = READUINT8(save_p);
+		ht->secs[i] = LoadSector(P_ReadUINT32(save_p));
+	P_ReadMem(save_p, ht->vex, sizeof(ht->vex));
+	P_ReadMem(save_p, ht->origsecheights, sizeof(ht->origsecheights));
+	P_ReadMem(save_p, ht->origvecheights, sizeof(ht->origvecheights));
+	ht->relative = P_ReadUINT8(save_p);
 	return &ht->thinker;
 }
 
-static inline thinker_t* LoadPolyrotatetThinker(actionf_p1 thinker)
+static inline thinker_t* LoadPolyrotatetThinker(save_t *save_p, actionf_p1 thinker)
 {
 	polyrotate_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->polyObjNum = READINT32(save_p);
-	ht->speed = READINT32(save_p);
-	ht->distance = READINT32(save_p);
-	ht->turnobjs = READUINT8(save_p);
+	ht->polyObjNum = P_ReadINT32(save_p);
+	ht->speed = P_ReadINT32(save_p);
+	ht->distance = P_ReadINT32(save_p);
+	ht->turnobjs = P_ReadUINT8(save_p);
 	return &ht->thinker;
 }
 
-static thinker_t* LoadPolymoveThinker(actionf_p1 thinker)
+static thinker_t* LoadPolymoveThinker(save_t *save_p, actionf_p1 thinker)
 {
 	polymove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->polyObjNum = READINT32(save_p);
-	ht->speed = READINT32(save_p);
-	ht->momx = READFIXED(save_p);
-	ht->momy = READFIXED(save_p);
-	ht->distance = READINT32(save_p);
-	ht->angle = READANGLE(save_p);
+	ht->polyObjNum = P_ReadINT32(save_p);
+	ht->speed = P_ReadINT32(save_p);
+	ht->momx = P_ReadFixed(save_p);
+	ht->momy = P_ReadFixed(save_p);
+	ht->distance = P_ReadINT32(save_p);
+	ht->angle = P_ReadAngle(save_p);
 	return &ht->thinker;
 }
 
-static inline thinker_t* LoadPolywaypointThinker(actionf_p1 thinker)
+static inline thinker_t* LoadPolywaypointThinker(save_t *save_p, actionf_p1 thinker)
 {
 	polywaypoint_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->polyObjNum = READINT32(save_p);
-	ht->speed = READINT32(save_p);
-	ht->sequence = READINT32(save_p);
-	ht->pointnum = READINT32(save_p);
-	ht->direction = READINT32(save_p);
-	ht->returnbehavior = READUINT8(save_p);
-	ht->continuous = READUINT8(save_p);
-	ht->stophere = READUINT8(save_p);
+	ht->polyObjNum = P_ReadINT32(save_p);
+	ht->speed = P_ReadINT32(save_p);
+	ht->sequence = P_ReadINT32(save_p);
+	ht->pointnum = P_ReadINT32(save_p);
+	ht->direction = P_ReadINT32(save_p);
+	ht->returnbehavior = P_ReadUINT8(save_p);
+	ht->continuous = P_ReadUINT8(save_p);
+	ht->stophere = P_ReadUINT8(save_p);
 	return &ht->thinker;
 }
 
-static inline thinker_t* LoadPolyslidedoorThinker(actionf_p1 thinker)
+static inline thinker_t* LoadPolyslidedoorThinker(save_t *save_p, actionf_p1 thinker)
 {
 	polyslidedoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->polyObjNum = READINT32(save_p);
-	ht->delay = READINT32(save_p);
-	ht->delayCount = READINT32(save_p);
-	ht->initSpeed = READINT32(save_p);
-	ht->speed = READINT32(save_p);
-	ht->initDistance = READINT32(save_p);
-	ht->distance = READINT32(save_p);
-	ht->initAngle = READUINT32(save_p);
-	ht->angle = READUINT32(save_p);
-	ht->revAngle = READUINT32(save_p);
-	ht->momx = READFIXED(save_p);
-	ht->momy = READFIXED(save_p);
-	ht->closing = READUINT8(save_p);
+	ht->polyObjNum = P_ReadINT32(save_p);
+	ht->delay = P_ReadINT32(save_p);
+	ht->delayCount = P_ReadINT32(save_p);
+	ht->initSpeed = P_ReadINT32(save_p);
+	ht->speed = P_ReadINT32(save_p);
+	ht->initDistance = P_ReadINT32(save_p);
+	ht->distance = P_ReadINT32(save_p);
+	ht->initAngle = P_ReadUINT32(save_p);
+	ht->angle = P_ReadUINT32(save_p);
+	ht->revAngle = P_ReadUINT32(save_p);
+	ht->momx = P_ReadFixed(save_p);
+	ht->momy = P_ReadFixed(save_p);
+	ht->closing = P_ReadUINT8(save_p);
 	return &ht->thinker;
 }
 
-static inline thinker_t* LoadPolyswingdoorThinker(actionf_p1 thinker)
+static inline thinker_t* LoadPolyswingdoorThinker(save_t *save_p, actionf_p1 thinker)
 {
 	polyswingdoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->polyObjNum = READINT32(save_p);
-	ht->delay = READINT32(save_p);
-	ht->delayCount = READINT32(save_p);
-	ht->initSpeed = READINT32(save_p);
-	ht->speed = READINT32(save_p);
-	ht->initDistance = READINT32(save_p);
-	ht->distance = READINT32(save_p);
-	ht->closing = READUINT8(save_p);
+	ht->polyObjNum = P_ReadINT32(save_p);
+	ht->delay = P_ReadINT32(save_p);
+	ht->delayCount = P_ReadINT32(save_p);
+	ht->initSpeed = P_ReadINT32(save_p);
+	ht->speed = P_ReadINT32(save_p);
+	ht->initDistance = P_ReadINT32(save_p);
+	ht->distance = P_ReadINT32(save_p);
+	ht->closing = P_ReadUINT8(save_p);
 	return &ht->thinker;
 }
 
-static inline thinker_t* LoadPolydisplaceThinker(actionf_p1 thinker)
+static inline thinker_t* LoadPolydisplaceThinker(save_t *save_p, actionf_p1 thinker)
 {
 	polydisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->polyObjNum = READINT32(save_p);
-	ht->controlSector = LoadSector(READUINT32(save_p));
-	ht->dx = READFIXED(save_p);
-	ht->dy = READFIXED(save_p);
-	ht->oldHeights = READFIXED(save_p);
+	ht->polyObjNum = P_ReadINT32(save_p);
+	ht->controlSector = LoadSector(P_ReadUINT32(save_p));
+	ht->dx = P_ReadFixed(save_p);
+	ht->dy = P_ReadFixed(save_p);
+	ht->oldHeights = P_ReadFixed(save_p);
 	return &ht->thinker;
 }
 
-static inline thinker_t* LoadPolyrotdisplaceThinker(actionf_p1 thinker)
+static inline thinker_t* LoadPolyrotdisplaceThinker(save_t *save_p, actionf_p1 thinker)
 {
 	polyrotdisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->polyObjNum = READINT32(save_p);
-	ht->controlSector = LoadSector(READUINT32(save_p));
-	ht->rotscale = READFIXED(save_p);
-	ht->turnobjs = READUINT8(save_p);
-	ht->oldHeights = READFIXED(save_p);
+	ht->polyObjNum = P_ReadINT32(save_p);
+	ht->controlSector = LoadSector(P_ReadUINT32(save_p));
+	ht->rotscale = P_ReadFixed(save_p);
+	ht->turnobjs = P_ReadUINT8(save_p);
+	ht->oldHeights = P_ReadFixed(save_p);
 	return &ht->thinker;
 }
 
-static thinker_t* LoadPolyfadeThinker(actionf_p1 thinker)
+static thinker_t* LoadPolyfadeThinker(save_t *save_p, actionf_p1 thinker)
 {
 	polyfade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->polyObjNum = READINT32(save_p);
-	ht->sourcevalue = READINT32(save_p);
-	ht->destvalue = READINT32(save_p);
-	ht->docollision = (boolean)READUINT8(save_p);
-	ht->doghostfade = (boolean)READUINT8(save_p);
-	ht->ticbased = (boolean)READUINT8(save_p);
-	ht->duration = READINT32(save_p);
-	ht->timer = READINT32(save_p);
+	ht->polyObjNum = P_ReadINT32(save_p);
+	ht->sourcevalue = P_ReadINT32(save_p);
+	ht->destvalue = P_ReadINT32(save_p);
+	ht->docollision = (boolean)P_ReadUINT8(save_p);
+	ht->doghostfade = (boolean)P_ReadUINT8(save_p);
+	ht->ticbased = (boolean)P_ReadUINT8(save_p);
+	ht->duration = P_ReadINT32(save_p);
+	ht->timer = P_ReadINT32(save_p);
 	return &ht->thinker;
 }
 
-static void P_NetUnArchiveThinkers(void)
+static void P_NetUnArchiveThinkers(save_t *save_p)
 {
 	thinker_t *currentthinker;
 	thinker_t *next;
@@ -3947,7 +4186,7 @@ static void P_NetUnArchiveThinkers(void)
 	UINT32 i;
 	UINT32 numloaded = 0;
 
-	if (READUINT32(save_p) != ARCHIVEBLOCK_THINKERS)
+	if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_THINKERS)
 		I_Error("Bad $$$.sav at archive block Thinkers");
 
 	// remove all the current thinkers
@@ -3985,7 +4224,7 @@ static void P_NetUnArchiveThinkers(void)
 		for (;;)
 		{
 			thinker_t* th = NULL;
-			tclass = READUINT8(save_p);
+			tclass = P_ReadUINT8(save_p);
 
 			if (tclass == tc_end)
 				break; // leave the saved thinker reading loop
@@ -3994,167 +4233,167 @@ static void P_NetUnArchiveThinkers(void)
 			switch (tclass)
 			{
 				case tc_mobj:
-					th = LoadMobjThinker((actionf_p1)P_MobjThinker);
+					th = LoadMobjThinker(save_p, (actionf_p1)P_MobjThinker);
 					break;
 
 				case tc_ceiling:
-					th = LoadCeilingThinker((actionf_p1)T_MoveCeiling);
+					th = LoadCeilingThinker(save_p, (actionf_p1)T_MoveCeiling);
 					break;
 
 				case tc_crushceiling:
-					th = LoadCeilingThinker((actionf_p1)T_CrushCeiling);
+					th = LoadCeilingThinker(save_p, (actionf_p1)T_CrushCeiling);
 					break;
 
 				case tc_floor:
-					th = LoadFloormoveThinker((actionf_p1)T_MoveFloor);
+					th = LoadFloormoveThinker(save_p, (actionf_p1)T_MoveFloor);
 					break;
 
 				case tc_flash:
-					th = LoadLightflashThinker((actionf_p1)T_LightningFlash);
+					th = LoadLightflashThinker(save_p, (actionf_p1)T_LightningFlash);
 					break;
 
 				case tc_strobe:
-					th = LoadStrobeThinker((actionf_p1)T_StrobeFlash);
+					th = LoadStrobeThinker(save_p, (actionf_p1)T_StrobeFlash);
 					break;
 
 				case tc_glow:
-					th = LoadGlowThinker((actionf_p1)T_Glow);
+					th = LoadGlowThinker(save_p, (actionf_p1)T_Glow);
 					break;
 
 				case tc_fireflicker:
-					th = LoadFireflickerThinker((actionf_p1)T_FireFlicker);
+					th = LoadFireflickerThinker(save_p, (actionf_p1)T_FireFlicker);
 					break;
 
 				case tc_elevator:
-					th = LoadElevatorThinker((actionf_p1)T_MoveElevator, true);
+					th = LoadElevatorThinker(save_p, (actionf_p1)T_MoveElevator, true);
 					break;
 
 				case tc_continuousfalling:
-					th = LoadContinuousFallThinker((actionf_p1)T_ContinuousFalling);
+					th = LoadContinuousFallThinker(save_p, (actionf_p1)T_ContinuousFalling);
 					break;
 
 				case tc_thwomp:
-					th = LoadThwompThinker((actionf_p1)T_ThwompSector);
+					th = LoadThwompThinker(save_p, (actionf_p1)T_ThwompSector);
 					break;
 
 				case tc_noenemies:
-					th = LoadNoEnemiesThinker((actionf_p1)T_NoEnemiesSector);
+					th = LoadNoEnemiesThinker(save_p, (actionf_p1)T_NoEnemiesSector);
 					break;
 
 				case tc_eachtime:
-					th = LoadEachTimeThinker((actionf_p1)T_EachTimeThinker);
+					th = LoadEachTimeThinker(save_p, (actionf_p1)T_EachTimeThinker);
 					break;
 
 				case tc_raisesector:
-					th = LoadRaiseThinker((actionf_p1)T_RaiseSector);
+					th = LoadRaiseThinker(save_p, (actionf_p1)T_RaiseSector);
 					break;
 
 				case tc_camerascanner:
-					th = LoadElevatorThinker((actionf_p1)T_CameraScanner, false);
+					th = LoadElevatorThinker(save_p, (actionf_p1)T_CameraScanner, false);
 					break;
 
 				case tc_bouncecheese:
-					th = LoadBounceCheeseThinker((actionf_p1)T_BounceCheese);
+					th = LoadBounceCheeseThinker(save_p, (actionf_p1)T_BounceCheese);
 					break;
 
 				case tc_startcrumble:
-					th = LoadCrumbleThinker((actionf_p1)T_StartCrumble);
+					th = LoadCrumbleThinker(save_p, (actionf_p1)T_StartCrumble);
 					break;
 
 				case tc_marioblock:
-					th = LoadMarioBlockThinker((actionf_p1)T_MarioBlock);
+					th = LoadMarioBlockThinker(save_p, (actionf_p1)T_MarioBlock);
 					break;
 
 				case tc_marioblockchecker:
-					th = LoadMarioCheckThinker((actionf_p1)T_MarioBlockChecker);
+					th = LoadMarioCheckThinker(save_p, (actionf_p1)T_MarioBlockChecker);
 					break;
 
 				case tc_floatsector:
-					th = LoadFloatThinker((actionf_p1)T_FloatSector);
+					th = LoadFloatThinker(save_p, (actionf_p1)T_FloatSector);
 					break;
 
 				case tc_laserflash:
-					th = LoadLaserThinker((actionf_p1)T_LaserFlash);
+					th = LoadLaserThinker(save_p, (actionf_p1)T_LaserFlash);
 					break;
 
 				case tc_lightfade:
-					th = LoadLightlevelThinker((actionf_p1)T_LightFade);
+					th = LoadLightlevelThinker(save_p, (actionf_p1)T_LightFade);
 					break;
 
 				case tc_executor:
-					th = LoadExecutorThinker((actionf_p1)T_ExecutorDelay);
+					th = LoadExecutorThinker(save_p, (actionf_p1)T_ExecutorDelay);
 					restoreNum = true;
 					break;
 
 				case tc_disappear:
-					th = LoadDisappearThinker((actionf_p1)T_Disappear);
+					th = LoadDisappearThinker(save_p, (actionf_p1)T_Disappear);
 					break;
 
 				case tc_fade:
-					th = LoadFadeThinker((actionf_p1)T_Fade);
+					th = LoadFadeThinker(save_p, (actionf_p1)T_Fade);
 					break;
 
 				case tc_fadecolormap:
-					th = LoadFadeColormapThinker((actionf_p1)T_FadeColormap);
+					th = LoadFadeColormapThinker(save_p, (actionf_p1)T_FadeColormap);
 					break;
 
 				case tc_planedisplace:
-					th = LoadPlaneDisplaceThinker((actionf_p1)T_PlaneDisplace);
+					th = LoadPlaneDisplaceThinker(save_p, (actionf_p1)T_PlaneDisplace);
 					break;
 				case tc_polyrotate:
-					th = LoadPolyrotatetThinker((actionf_p1)T_PolyObjRotate);
+					th = LoadPolyrotatetThinker(save_p, (actionf_p1)T_PolyObjRotate);
 					break;
 
 				case tc_polymove:
-					th = LoadPolymoveThinker((actionf_p1)T_PolyObjMove);
+					th = LoadPolymoveThinker(save_p, (actionf_p1)T_PolyObjMove);
 					break;
 
 				case tc_polywaypoint:
-					th = LoadPolywaypointThinker((actionf_p1)T_PolyObjWaypoint);
+					th = LoadPolywaypointThinker(save_p, (actionf_p1)T_PolyObjWaypoint);
 					break;
 
 				case tc_polyslidedoor:
-					th = LoadPolyslidedoorThinker((actionf_p1)T_PolyDoorSlide);
+					th = LoadPolyslidedoorThinker(save_p, (actionf_p1)T_PolyDoorSlide);
 					break;
 
 				case tc_polyswingdoor:
-					th = LoadPolyswingdoorThinker((actionf_p1)T_PolyDoorSwing);
+					th = LoadPolyswingdoorThinker(save_p, (actionf_p1)T_PolyDoorSwing);
 					break;
 
 				case tc_polyflag:
-					th = LoadPolymoveThinker((actionf_p1)T_PolyObjFlag);
+					th = LoadPolymoveThinker(save_p, (actionf_p1)T_PolyObjFlag);
 					break;
 
 				case tc_polydisplace:
-					th = LoadPolydisplaceThinker((actionf_p1)T_PolyObjDisplace);
+					th = LoadPolydisplaceThinker(save_p, (actionf_p1)T_PolyObjDisplace);
 					break;
 
 				case tc_polyrotdisplace:
-					th = LoadPolyrotdisplaceThinker((actionf_p1)T_PolyObjRotDisplace);
+					th = LoadPolyrotdisplaceThinker(save_p, (actionf_p1)T_PolyObjRotDisplace);
 					break;
 
 				case tc_polyfade:
-					th = LoadPolyfadeThinker((actionf_p1)T_PolyObjFade);
+					th = LoadPolyfadeThinker(save_p, (actionf_p1)T_PolyObjFade);
 					break;
 
 				case tc_dynslopeline:
-					th = LoadDynamicLineSlopeThinker((actionf_p1)T_DynamicSlopeLine);
+					th = LoadDynamicLineSlopeThinker(save_p, (actionf_p1)T_DynamicSlopeLine);
 					break;
 
 				case tc_dynslopevert:
-					th = LoadDynamicVertexSlopeThinker((actionf_p1)T_DynamicSlopeVert);
+					th = LoadDynamicVertexSlopeThinker(save_p, (actionf_p1)T_DynamicSlopeVert);
 					break;
 
 				case tc_scroll:
-					th = LoadScrollThinker((actionf_p1)T_Scroll);
+					th = LoadScrollThinker(save_p, (actionf_p1)T_Scroll);
 					break;
 
 				case tc_friction:
-					th = LoadFrictionThinker((actionf_p1)T_Friction);
+					th = LoadFrictionThinker(save_p, (actionf_p1)T_Friction);
 					break;
 
 				case tc_pusher:
-					th = LoadPusherThinker((actionf_p1)T_Pusher);
+					th = LoadPusherThinker(save_p, (actionf_p1)T_Pusher);
 					break;
 
 				default:
@@ -4194,29 +4433,29 @@ static void P_NetUnArchiveThinkers(void)
 #define PD_FLAGS  0x01
 #define PD_TRANS   0x02
 
-static inline void P_ArchivePolyObj(polyobj_t *po)
+static inline void P_ArchivePolyObj(save_t *save_p, polyobj_t *po)
 {
 	UINT8 diff = 0;
-	WRITEINT32(save_p, po->id);
-	WRITEANGLE(save_p, po->angle);
+	P_WriteINT32(save_p, po->id);
+	P_WriteAngle(save_p, po->angle);
 
-	WRITEFIXED(save_p, po->spawnSpot.x);
-	WRITEFIXED(save_p, po->spawnSpot.y);
+	P_WriteFixed(save_p, po->spawnSpot.x);
+	P_WriteFixed(save_p, po->spawnSpot.y);
 
 	if (po->flags != po->spawnflags)
 		diff |= PD_FLAGS;
 	if (po->translucency != po->spawntrans)
 		diff |= PD_TRANS;
 
-	WRITEUINT8(save_p, diff);
+	P_WriteUINT8(save_p, diff);
 
 	if (diff & PD_FLAGS)
-		WRITEINT32(save_p, po->flags);
+		P_WriteINT32(save_p, po->flags);
 	if (diff & PD_TRANS)
-		WRITEINT32(save_p, po->translucency);
+		P_WriteINT32(save_p, po->translucency);
 }
 
-static inline void P_UnArchivePolyObj(polyobj_t *po)
+static inline void P_UnArchivePolyObj(save_t *save_p, polyobj_t *po)
 {
 	INT32 id;
 	UINT32 angle;
@@ -4228,19 +4467,19 @@ static inline void P_UnArchivePolyObj(polyobj_t *po)
 	// when they first start to run.
 	po->thinker = NULL;
 
-	id = READINT32(save_p);
+	id = P_ReadINT32(save_p);
 
-	angle = READANGLE(save_p);
+	angle = P_ReadAngle(save_p);
 
-	x = READFIXED(save_p);
-	y = READFIXED(save_p);
+	x = P_ReadFixed(save_p);
+	y = P_ReadFixed(save_p);
 
-	diff = READUINT8(save_p);
+	diff = P_ReadUINT8(save_p);
 
 	if (diff & PD_FLAGS)
-		po->flags = READINT32(save_p);
+		po->flags = P_ReadINT32(save_p);
 	if (diff & PD_TRANS)
-		po->translucency = READINT32(save_p);
+		po->translucency = P_ReadINT32(save_p);
 
 	// if the object is bad or isn't in the id hash, we can do nothing more
 	// with it, so return now
@@ -4251,33 +4490,33 @@ static inline void P_UnArchivePolyObj(polyobj_t *po)
 	Polyobj_MoveOnLoad(po, angle, x, y);
 }
 
-static inline void P_ArchivePolyObjects(void)
+static inline void P_ArchivePolyObjects(save_t *save_p)
 {
 	INT32 i;
 
-	WRITEUINT32(save_p, ARCHIVEBLOCK_POBJS);
+	P_WriteUINT32(save_p, ARCHIVEBLOCK_POBJS);
 
 	// save number of polyobjects
-	WRITEINT32(save_p, numPolyObjects);
+	P_WriteINT32(save_p, numPolyObjects);
 
 	for (i = 0; i < numPolyObjects; ++i)
-		P_ArchivePolyObj(&PolyObjects[i]);
+		P_ArchivePolyObj(save_p, &PolyObjects[i]);
 }
 
-static inline void P_UnArchivePolyObjects(void)
+static inline void P_UnArchivePolyObjects(save_t *save_p)
 {
 	INT32 i, numSavedPolys;
 
-	if (READUINT32(save_p) != ARCHIVEBLOCK_POBJS)
+	if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_POBJS)
 		I_Error("Bad $$$.sav at archive block Pobjs");
 
-	numSavedPolys = READINT32(save_p);
+	numSavedPolys = P_ReadINT32(save_p);
 
 	if (numSavedPolys != numPolyObjects)
 		I_Error("P_UnArchivePolyObjects: polyobj count inconsistency\n");
 
 	for (i = 0; i < numSavedPolys; ++i)
-		P_UnArchivePolyObj(&PolyObjects[i]);
+		P_UnArchivePolyObj(save_p, &PolyObjects[i]);
 }
 
 static inline void P_FinishMobjs(void)
@@ -4395,11 +4634,11 @@ static void P_RelinkPointers(void)
 	}
 }
 
-static inline void P_NetArchiveSpecials(void)
+static inline void P_NetArchiveSpecials(save_t *save_p)
 {
 	size_t i, z;
 
-	WRITEUINT32(save_p, ARCHIVEBLOCK_SPECIALS);
+	P_WriteUINT32(save_p, ARCHIVEBLOCK_SPECIALS);
 
 	// itemrespawn queue for deathmatch
 	i = iquetail;
@@ -4409,53 +4648,54 @@ static inline void P_NetArchiveSpecials(void)
 		{
 			if (&mapthings[z] == itemrespawnque[i])
 			{
-				WRITEUINT32(save_p, z);
+				P_WriteUINT32(save_p, z);
 				break;
 			}
 		}
-		WRITEUINT32(save_p, itemrespawntime[i]);
+		P_WriteUINT32(save_p, itemrespawntime[i]);
 		i = (i + 1) & (ITEMQUESIZE-1);
 	}
 
 	// end delimiter
-	WRITEUINT32(save_p, 0xffffffff);
+	P_WriteUINT32(save_p, 0xffffffff);
 
 	// Sky number
-	WRITEINT32(save_p, globallevelskynum);
+	P_WriteINT32(save_p, globallevelskynum);
 
 	// Current global weather type
-	WRITEUINT8(save_p, globalweather);
+	P_WriteUINT8(save_p, globalweather);
 
 	if (metalplayback) // Is metal sonic running?
 	{
-		WRITEUINT8(save_p, 0x01);
-		G_SaveMetal(&save_p);
+		UINT8 *p = &save_p->buf[save_p->pos+1];
+		P_WriteUINT8(save_p, 0x01);
+		G_SaveMetal(&p);
 	}
 	else
-		WRITEUINT8(save_p, 0x00);
+		P_WriteUINT8(save_p, 0x00);
 }
 
-static void P_NetUnArchiveSpecials(void)
+static void P_NetUnArchiveSpecials(save_t *save_p)
 {
 	size_t i;
 	INT32 j;
 
-	if (READUINT32(save_p) != ARCHIVEBLOCK_SPECIALS)
+	if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_SPECIALS)
 		I_Error("Bad $$$.sav at archive block Specials");
 
 	// BP: added save itemrespawn queue for deathmatch
 	iquetail = iquehead = 0;
-	while ((i = READUINT32(save_p)) != 0xffffffff)
+	while ((i = P_ReadUINT32(save_p)) != 0xffffffff)
 	{
 		itemrespawnque[iquehead] = &mapthings[i];
-		itemrespawntime[iquehead++] = READINT32(save_p);
+		itemrespawntime[iquehead++] = P_ReadINT32(save_p);
 	}
 
-	j = READINT32(save_p);
+	j = P_ReadINT32(save_p);
 	if (j != globallevelskynum)
 		P_SetupLevelSky(j, true);
 
-	globalweather = READUINT8(save_p);
+	globalweather = P_ReadUINT8(save_p);
 
 	if (globalweather)
 	{
@@ -4470,14 +4710,17 @@ static void P_NetUnArchiveSpecials(void)
 			P_SwitchWeather(globalweather);
 	}
 
-	if (READUINT8(save_p) == 0x01) // metal sonic
-		G_LoadMetal(&save_p);
+	if (P_ReadUINT8(save_p) == 0x01) // metal sonic
+	{
+		UINT8 *p = &save_p->buf[save_p->pos];
+		G_LoadMetal(&p);
+	}
 }
 
 // =======================================================================
 //          Misc
 // =======================================================================
-static inline void P_ArchiveMisc(INT16 mapnum)
+static inline void P_ArchiveMisc(save_t *save_p, INT16 mapnum)
 {
 	//lastmapsaved = mapnum;
 	lastmaploaded = mapnum;
@@ -4485,16 +4728,16 @@ static inline void P_ArchiveMisc(INT16 mapnum)
 	if (gamecomplete)
 		mapnum |= 8192;
 
-	WRITEINT16(save_p, mapnum);
-	WRITEUINT16(save_p, emeralds+357);
-	WRITESTRINGN(save_p, timeattackfolder, sizeof(timeattackfolder));
+	P_WriteINT16(save_p, mapnum);
+	P_WriteUINT16(save_p, emeralds+357);
+	P_WriteStringN(save_p, timeattackfolder, sizeof(timeattackfolder));
 }
 
-static inline void P_UnArchiveSPGame(INT16 mapoverride)
+static inline void P_UnArchiveSPGame(save_t *save_p, INT16 mapoverride)
 {
 	char testname[sizeof(timeattackfolder)];
 
-	gamemap = READINT16(save_p);
+	gamemap = P_ReadINT16(save_p);
 
 	if (mapoverride != 0)
 	{
@@ -4515,9 +4758,9 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride)
 	tokenlist = 0;
 	token = 0;
 
-	savedata.emeralds = READUINT16(save_p)-357;
+	savedata.emeralds = P_ReadUINT16(save_p)-357;
 
-	READSTRINGN(save_p, testname, sizeof(testname));
+	P_ReadStringN(save_p, testname, sizeof(testname));
 
 	if (strcmp(testname, timeattackfolder))
 	{
@@ -4531,106 +4774,106 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride)
 	playeringame[consoleplayer] = true;
 }
 
-static void P_NetArchiveMisc(boolean resending)
+static void P_NetArchiveMisc(save_t *save_p, boolean resending)
 {
 	INT32 i;
 
-	WRITEUINT32(save_p, ARCHIVEBLOCK_MISC);
+	P_WriteUINT32(save_p, ARCHIVEBLOCK_MISC);
 
 	if (resending)
-		WRITEUINT32(save_p, gametic);
-	WRITEINT16(save_p, gamemap);
+		P_WriteUINT32(save_p, gametic);
+	P_WriteINT16(save_p, gamemap);
 
 	if (gamestate != GS_LEVEL)
-		WRITEINT16(save_p, GS_WAITINGPLAYERS); // nice hack to put people back into waitingplayers
+		P_WriteINT16(save_p, GS_WAITINGPLAYERS); // nice hack to put people back into waitingplayers
 	else
-		WRITEINT16(save_p, gamestate);
-	WRITEINT16(save_p, gametype);
+		P_WriteINT16(save_p, gamestate);
+	P_WriteINT16(save_p, gametype);
 
 	{
 		UINT32 pig = 0;
 		for (i = 0; i < MAXPLAYERS; i++)
 			pig |= (playeringame[i] != 0)<<i;
-		WRITEUINT32(save_p, pig);
+		P_WriteUINT32(save_p, pig);
 	}
 
-	WRITEUINT32(save_p, P_GetRandSeed());
+	P_WriteUINT32(save_p, P_GetRandSeed());
 
-	WRITEUINT32(save_p, tokenlist);
+	P_WriteUINT32(save_p, tokenlist);
 
-	WRITEUINT32(save_p, leveltime);
-	WRITEUINT32(save_p, ssspheres);
-	WRITEINT16(save_p, lastmap);
-	WRITEUINT16(save_p, bossdisabled);
+	P_WriteUINT32(save_p, leveltime);
+	P_WriteUINT32(save_p, ssspheres);
+	P_WriteINT16(save_p, lastmap);
+	P_WriteUINT16(save_p, bossdisabled);
 
-	WRITEUINT16(save_p, emeralds);
+	P_WriteUINT16(save_p, emeralds);
 	{
 		UINT8 globools = 0;
 		if (stagefailed)
 			globools |= 1;
 		if (stoppedclock)
 			globools |= (1<<1);
-		WRITEUINT8(save_p, globools);
+		P_WriteUINT8(save_p, globools);
 	}
 
-	WRITEUINT32(save_p, token);
-	WRITEINT32(save_p, sstimer);
-	WRITEUINT32(save_p, bluescore);
-	WRITEUINT32(save_p, redscore);
+	P_WriteUINT32(save_p, token);
+	P_WriteINT32(save_p, sstimer);
+	P_WriteUINT32(save_p, bluescore);
+	P_WriteUINT32(save_p, redscore);
 
-	WRITEUINT16(save_p, skincolor_redteam);
-	WRITEUINT16(save_p, skincolor_blueteam);
-	WRITEUINT16(save_p, skincolor_redring);
-	WRITEUINT16(save_p, skincolor_bluering);
+	P_WriteUINT16(save_p, skincolor_redteam);
+	P_WriteUINT16(save_p, skincolor_blueteam);
+	P_WriteUINT16(save_p, skincolor_redring);
+	P_WriteUINT16(save_p, skincolor_bluering);
 
-	WRITEINT32(save_p, modulothing);
+	P_WriteINT32(save_p, modulothing);
 
-	WRITEINT16(save_p, autobalance);
-	WRITEINT16(save_p, teamscramble);
+	P_WriteINT16(save_p, autobalance);
+	P_WriteINT16(save_p, teamscramble);
 
 	for (i = 0; i < MAXPLAYERS; i++)
-		WRITEINT16(save_p, scrambleplayers[i]);
+		P_WriteINT16(save_p, scrambleplayers[i]);
 
 	for (i = 0; i < MAXPLAYERS; i++)
-		WRITEINT16(save_p, scrambleteams[i]);
+		P_WriteINT16(save_p, scrambleteams[i]);
 
-	WRITEINT16(save_p, scrambletotal);
-	WRITEINT16(save_p, scramblecount);
+	P_WriteINT16(save_p, scrambletotal);
+	P_WriteINT16(save_p, scramblecount);
 
-	WRITEUINT32(save_p, countdown);
-	WRITEUINT32(save_p, countdown2);
+	P_WriteUINT32(save_p, countdown);
+	P_WriteUINT32(save_p, countdown2);
 
-	WRITEFIXED(save_p, gravity);
+	P_WriteFixed(save_p, gravity);
 
-	WRITEUINT32(save_p, countdowntimer);
-	WRITEUINT8(save_p, countdowntimeup);
+	P_WriteUINT32(save_p, countdowntimer);
+	P_WriteUINT8(save_p, countdowntimeup);
 
-	WRITEUINT32(save_p, hidetime);
+	P_WriteUINT32(save_p, hidetime);
 
 	// Is it paused?
 	if (paused)
-		WRITEUINT8(save_p, 0x2f);
+		P_WriteUINT8(save_p, 0x2f);
 	else
-		WRITEUINT8(save_p, 0x2e);
+		P_WriteUINT8(save_p, 0x2e);
 
 	for (i = 0; i < MAXPLAYERS; i++)
 	{
-		WRITEUINT8(save_p, spam_tokens[i]);
-		WRITEUINT32(save_p, spam_tics[i]);
+		P_WriteUINT8(save_p, spam_tokens[i]);
+		P_WriteUINT32(save_p, spam_tics[i]);
 	}
 }
 
-static inline boolean P_NetUnArchiveMisc(boolean reloading)
+static inline boolean P_NetUnArchiveMisc(save_t *save_p, boolean reloading)
 {
 	INT32 i;
 
-	if (READUINT32(save_p) != ARCHIVEBLOCK_MISC)
+	if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_MISC)
 		I_Error("Bad $$$.sav at archive block Misc");
 
 	if (reloading)
-		gametic = READUINT32(save_p);
+		gametic = P_ReadUINT32(save_p);
 
-	gamemap = READINT16(save_p);
+	gamemap = P_ReadINT16(save_p);
 
 	// gamemap changed; we assume that its map header is always valid,
 	// so make it so
@@ -4641,12 +4884,12 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
 	// normally sets this flag
 	mapmusflags |= MUSIC_RELOADRESET;
 
-	G_SetGamestate(READINT16(save_p));
+	G_SetGamestate(P_ReadINT16(save_p));
 
-	gametype = READINT16(save_p);
+	gametype = P_ReadINT16(save_p);
 
 	{
-		UINT32 pig = READUINT32(save_p);
+		UINT32 pig = P_ReadUINT32(save_p);
 		for (i = 0; i < MAXPLAYERS; i++)
 		{
 			playeringame[i] = (pig & (1<<i)) != 0;
@@ -4654,9 +4897,9 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
 		}
 	}
 
-	P_SetRandSeed(READUINT32(save_p));
+	P_SetRandSeed(P_ReadUINT32(save_p));
 
-	tokenlist = READUINT32(save_p);
+	tokenlist = P_ReadUINT32(save_p);
 
 	if (!P_LoadLevel(true, reloading))
 	{
@@ -4665,89 +4908,89 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
 	}
 
 	// get the time
-	leveltime = READUINT32(save_p);
-	ssspheres = READUINT32(save_p);
-	lastmap = READINT16(save_p);
-	bossdisabled = READUINT16(save_p);
+	leveltime = P_ReadUINT32(save_p);
+	ssspheres = P_ReadUINT32(save_p);
+	lastmap = P_ReadINT16(save_p);
+	bossdisabled = P_ReadUINT16(save_p);
 
-	emeralds = READUINT16(save_p);
+	emeralds = P_ReadUINT16(save_p);
 	{
-		UINT8 globools = READUINT8(save_p);
+		UINT8 globools = P_ReadUINT8(save_p);
 		stagefailed = !!(globools & 1);
 		stoppedclock = !!(globools & (1<<1));
 	}
 
-	token = READUINT32(save_p);
-	sstimer = READINT32(save_p);
-	bluescore = READUINT32(save_p);
-	redscore = READUINT32(save_p);
+	token = P_ReadUINT32(save_p);
+	sstimer = P_ReadINT32(save_p);
+	bluescore = P_ReadUINT32(save_p);
+	redscore = P_ReadUINT32(save_p);
 
-	skincolor_redteam = READUINT16(save_p);
-	skincolor_blueteam = READUINT16(save_p);
-	skincolor_redring = READUINT16(save_p);
-	skincolor_bluering = READUINT16(save_p);
+	skincolor_redteam = P_ReadUINT16(save_p);
+	skincolor_blueteam = P_ReadUINT16(save_p);
+	skincolor_redring = P_ReadUINT16(save_p);
+	skincolor_bluering = P_ReadUINT16(save_p);
 
-	modulothing = READINT32(save_p);
+	modulothing = P_ReadINT32(save_p);
 
-	autobalance = READINT16(save_p);
-	teamscramble = READINT16(save_p);
+	autobalance = P_ReadINT16(save_p);
+	teamscramble = P_ReadINT16(save_p);
 
 	for (i = 0; i < MAXPLAYERS; i++)
-		scrambleplayers[i] = READINT16(save_p);
+		scrambleplayers[i] = P_ReadINT16(save_p);
 
 	for (i = 0; i < MAXPLAYERS; i++)
-		scrambleteams[i] = READINT16(save_p);
+		scrambleteams[i] = P_ReadINT16(save_p);
 
-	scrambletotal = READINT16(save_p);
-	scramblecount = READINT16(save_p);
+	scrambletotal = P_ReadINT16(save_p);
+	scramblecount = P_ReadINT16(save_p);
 
-	countdown = READUINT32(save_p);
-	countdown2 = READUINT32(save_p);
+	countdown = P_ReadUINT32(save_p);
+	countdown2 = P_ReadUINT32(save_p);
 
-	gravity = READFIXED(save_p);
+	gravity = P_ReadFixed(save_p);
 
-	countdowntimer = (tic_t)READUINT32(save_p);
-	countdowntimeup = (boolean)READUINT8(save_p);
+	countdowntimer = (tic_t)P_ReadUINT32(save_p);
+	countdowntimeup = (boolean)P_ReadUINT8(save_p);
 
-	hidetime = READUINT32(save_p);
+	hidetime = P_ReadUINT32(save_p);
 
 	// Is it paused?
-	if (READUINT8(save_p) == 0x2f)
+	if (P_ReadUINT8(save_p) == 0x2f)
 		paused = true;
 
 	for (i = 0; i < MAXPLAYERS; i++)
 	{
-		spam_tokens[i] = READUINT8(save_p);
-		spam_tics[i] = READUINT32(save_p);
+		spam_tokens[i] = P_ReadUINT8(save_p);
+		spam_tics[i] = P_ReadUINT32(save_p);
 	}
 
 	return true;
 }
 
-static inline void P_NetArchiveEmblems(void)
+static inline void P_NetArchiveEmblems(save_t *save_p)
 {
 	gamedata_t *data = serverGamedata;
 	INT32 i, j;
 	UINT8 btemp;
 	INT32 curmare;
 
-	WRITEUINT32(save_p, ARCHIVEBLOCK_EMBLEMS);
+	P_WriteUINT32(save_p, ARCHIVEBLOCK_EMBLEMS);
 
 	// These should be synchronized before savegame loading by the wad files being the same anyway,
 	// but just in case, for now, we'll leave them here for testing. It would be very bad if they mismatch.
-	WRITEUINT8(save_p, (UINT8)savemoddata);
-	WRITEINT32(save_p, numemblems);
-	WRITEINT32(save_p, numextraemblems);
+	P_WriteUINT8(save_p, (UINT8)savemoddata);
+	P_WriteINT32(save_p, numemblems);
+	P_WriteINT32(save_p, numextraemblems);
 
 	// The rest of this is lifted straight from G_SaveGameData in g_game.c
 	// TODO: Optimize this to only send information about emblems, unlocks, etc. which actually exist
 	//       There is no need to go all the way up to MAXEMBLEMS when wads are guaranteed to be the same.
 
-	WRITEUINT32(save_p, data->totalplaytime);
+	P_WriteUINT32(save_p, data->totalplaytime);
 
 	// TODO put another cipher on these things? meh, I don't care...
 	for (i = 0; i < NUMMAPS; i++)
-		WRITEUINT8(save_p, (data->mapvisited[i] & MV_MAX));
+		P_WriteUINT8(save_p, (data->mapvisited[i] & MV_MAX));
 
 	// To save space, use one bit per collected/achieved/unlocked flag
 	for (i = 0; i < MAXEMBLEMS;)
@@ -4755,7 +4998,7 @@ static inline void P_NetArchiveEmblems(void)
 		btemp = 0;
 		for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
 			btemp |= (data->collected[j+i] << j);
-		WRITEUINT8(save_p, btemp);
+		P_WriteUINT8(save_p, btemp);
 		i += j;
 	}
 	for (i = 0; i < MAXEXTRAEMBLEMS;)
@@ -4763,7 +5006,7 @@ static inline void P_NetArchiveEmblems(void)
 		btemp = 0;
 		for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
 			btemp |= (data->extraCollected[j+i] << j);
-		WRITEUINT8(save_p, btemp);
+		P_WriteUINT8(save_p, btemp);
 		i += j;
 	}
 	for (i = 0; i < MAXUNLOCKABLES;)
@@ -4771,7 +5014,7 @@ static inline void P_NetArchiveEmblems(void)
 		btemp = 0;
 		for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
 			btemp |= (data->unlocked[j+i] << j);
-		WRITEUINT8(save_p, btemp);
+		P_WriteUINT8(save_p, btemp);
 		i += j;
 	}
 	for (i = 0; i < MAXCONDITIONSETS;)
@@ -4779,28 +5022,28 @@ static inline void P_NetArchiveEmblems(void)
 		btemp = 0;
 		for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
 			btemp |= (data->achieved[j+i] << j);
-		WRITEUINT8(save_p, btemp);
+		P_WriteUINT8(save_p, btemp);
 		i += j;
 	}
 
-	WRITEUINT32(save_p, data->timesBeaten);
-	WRITEUINT32(save_p, data->timesBeatenWithEmeralds);
-	WRITEUINT32(save_p, data->timesBeatenUltimate);
+	P_WriteUINT32(save_p, data->timesBeaten);
+	P_WriteUINT32(save_p, data->timesBeatenWithEmeralds);
+	P_WriteUINT32(save_p, data->timesBeatenUltimate);
 
 	// Main records
 	for (i = 0; i < NUMMAPS; i++)
 	{
 		if (data->mainrecords[i])
 		{
-			WRITEUINT32(save_p, data->mainrecords[i]->score);
-			WRITEUINT32(save_p, data->mainrecords[i]->time);
-			WRITEUINT16(save_p, data->mainrecords[i]->rings);
+			P_WriteUINT32(save_p, data->mainrecords[i]->score);
+			P_WriteUINT32(save_p, data->mainrecords[i]->time);
+			P_WriteUINT16(save_p, data->mainrecords[i]->rings);
 		}
 		else
 		{
-			WRITEUINT32(save_p, 0);
-			WRITEUINT32(save_p, 0);
-			WRITEUINT16(save_p, 0);
+			P_WriteUINT32(save_p, 0);
+			P_WriteUINT32(save_p, 0);
+			P_WriteUINT16(save_p, 0);
 		}
 	}
 
@@ -4809,43 +5052,43 @@ static inline void P_NetArchiveEmblems(void)
 	{
 		if (!data->nightsrecords[i] || !data->nightsrecords[i]->nummares)
 		{
-			WRITEUINT8(save_p, 0);
+			P_WriteUINT8(save_p, 0);
 			continue;
 		}
 
-		WRITEUINT8(save_p, data->nightsrecords[i]->nummares);
+		P_WriteUINT8(save_p, data->nightsrecords[i]->nummares);
 
 		for (curmare = 0; curmare < (data->nightsrecords[i]->nummares + 1); ++curmare)
 		{
-			WRITEUINT32(save_p, data->nightsrecords[i]->score[curmare]);
-			WRITEUINT8(save_p, data->nightsrecords[i]->grade[curmare]);
-			WRITEUINT32(save_p, data->nightsrecords[i]->time[curmare]);
+			P_WriteUINT32(save_p, data->nightsrecords[i]->score[curmare]);
+			P_WriteUINT8(save_p, data->nightsrecords[i]->grade[curmare]);
+			P_WriteUINT32(save_p, data->nightsrecords[i]->time[curmare]);
 		}
 	}
 
 	// Mid-map stuff
-	WRITEUINT32(save_p, unlocktriggers);
+	P_WriteUINT32(save_p, unlocktriggers);
 
 	for (i = 0; i < MAXPLAYERS; i++)
 	{
 		if (!ntemprecords[i].nummares)
 		{
-			WRITEUINT8(save_p, 0);
+			P_WriteUINT8(save_p, 0);
 			continue;
 		}
 
-		WRITEUINT8(save_p, ntemprecords[i].nummares);
+		P_WriteUINT8(save_p, ntemprecords[i].nummares);
 
 		for (curmare = 0; curmare < (ntemprecords[i].nummares + 1); ++curmare)
 		{
-			WRITEUINT32(save_p, ntemprecords[i].score[curmare]);
-			WRITEUINT8(save_p, ntemprecords[i].grade[curmare]);
-			WRITEUINT32(save_p, ntemprecords[i].time[curmare]);
+			P_WriteUINT32(save_p, ntemprecords[i].score[curmare]);
+			P_WriteUINT8(save_p, ntemprecords[i].grade[curmare]);
+			P_WriteUINT32(save_p, ntemprecords[i].time[curmare]);
 		}
 	}
 }
 
-static inline void P_NetUnArchiveEmblems(void)
+static inline void P_NetUnArchiveEmblems(save_t *save_p)
 {
 	gamedata_t *data = serverGamedata;
 	INT32 i, j;
@@ -4856,14 +5099,14 @@ static inline void P_NetUnArchiveEmblems(void)
 	UINT8 recmares;
 	INT32 curmare;
 
-	if (READUINT32(save_p) != ARCHIVEBLOCK_EMBLEMS)
+	if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_EMBLEMS)
 		I_Error("Bad $$$.sav at archive block Emblems");
 
-	savemoddata = (boolean)READUINT8(save_p); // this one is actually necessary because savemoddata stays false otherwise for some reason.
+	savemoddata = (boolean)P_ReadUINT8(save_p); // this one is actually necessary because savemoddata stays false otherwise for some reason.
 
-	if (numemblems != READINT32(save_p))
+	if (numemblems != P_ReadINT32(save_p))
 		I_Error("Bad $$$.sav dearchiving Emblems (numemblems mismatch)");
-	if (numextraemblems != READINT32(save_p))
+	if (numextraemblems != P_ReadINT32(save_p))
 		I_Error("Bad $$$.sav dearchiving Emblems (numextraemblems mismatch)");
 
 	// This shouldn't happen, but if something really fucked up happens and you transfer
@@ -4878,53 +5121,53 @@ static inline void P_NetUnArchiveEmblems(void)
 	// TODO: Optimize this to only read information about emblems, unlocks, etc. which actually exist
 	//       There is no need to go all the way up to MAXEMBLEMS when wads are guaranteed to be the same.
 
-	data->totalplaytime = READUINT32(save_p);
+	data->totalplaytime = P_ReadUINT32(save_p);
 
 	// TODO put another cipher on these things? meh, I don't care...
 	for (i = 0; i < NUMMAPS; i++)
-		if ((data->mapvisited[i] = READUINT8(save_p)) > MV_MAX)
+		if ((data->mapvisited[i] = P_ReadUINT8(save_p)) > MV_MAX)
 			I_Error("Bad $$$.sav dearchiving Emblems (invalid visit flags)");
 
 	// To save space, use one bit per collected/achieved/unlocked flag
 	for (i = 0; i < MAXEMBLEMS;)
 	{
-		rtemp = READUINT8(save_p);
+		rtemp = P_ReadUINT8(save_p);
 		for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
 			data->collected[j+i] = ((rtemp >> j) & 1);
 		i += j;
 	}
 	for (i = 0; i < MAXEXTRAEMBLEMS;)
 	{
-		rtemp = READUINT8(save_p);
+		rtemp = P_ReadUINT8(save_p);
 		for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
 			data->extraCollected[j+i] = ((rtemp >> j) & 1);
 		i += j;
 	}
 	for (i = 0; i < MAXUNLOCKABLES;)
 	{
-		rtemp = READUINT8(save_p);
+		rtemp = P_ReadUINT8(save_p);
 		for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
 			data->unlocked[j+i] = ((rtemp >> j) & 1);
 		i += j;
 	}
 	for (i = 0; i < MAXCONDITIONSETS;)
 	{
-		rtemp = READUINT8(save_p);
+		rtemp = P_ReadUINT8(save_p);
 		for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
 			data->achieved[j+i] = ((rtemp >> j) & 1);
 		i += j;
 	}
 
-	data->timesBeaten = READUINT32(save_p);
-	data->timesBeatenWithEmeralds = READUINT32(save_p);
-	data->timesBeatenUltimate = READUINT32(save_p);
+	data->timesBeaten = P_ReadUINT32(save_p);
+	data->timesBeatenWithEmeralds = P_ReadUINT32(save_p);
+	data->timesBeatenUltimate = P_ReadUINT32(save_p);
 
 	// Main records
 	for (i = 0; i < NUMMAPS; ++i)
 	{
-		recscore = READUINT32(save_p);
-		rectime  = (tic_t)READUINT32(save_p);
-		recrings = READUINT16(save_p);
+		recscore = P_ReadUINT32(save_p);
+		rectime  = (tic_t)P_ReadUINT32(save_p);
+		recrings = P_ReadUINT16(save_p);
 
 		if (recrings > 10000 || recscore > MAXSCORE)
 			I_Error("Bad $$$.sav dearchiving Emblems (invalid score)");
@@ -4941,16 +5184,16 @@ static inline void P_NetUnArchiveEmblems(void)
 	// Nights records
 	for (i = 0; i < NUMMAPS; ++i)
 	{
-		if ((recmares = READUINT8(save_p)) == 0)
+		if ((recmares = P_ReadUINT8(save_p)) == 0)
 			continue;
 
 		G_AllocNightsRecordData((INT16)i, data);
 
 		for (curmare = 0; curmare < (recmares+1); ++curmare)
 		{
-			data->nightsrecords[i]->score[curmare] = READUINT32(save_p);
-			data->nightsrecords[i]->grade[curmare] = READUINT8(save_p);
-			data->nightsrecords[i]->time[curmare] = (tic_t)READUINT32(save_p);
+			data->nightsrecords[i]->score[curmare] = P_ReadUINT32(save_p);
+			data->nightsrecords[i]->grade[curmare] = P_ReadUINT8(save_p);
+			data->nightsrecords[i]->time[curmare] = (tic_t)P_ReadUINT32(save_p);
 
 			if (data->nightsrecords[i]->grade[curmare] > GRADE_S)
 			{
@@ -4962,18 +5205,18 @@ static inline void P_NetUnArchiveEmblems(void)
 	}
 
 	// Mid-map stuff
-	unlocktriggers = READUINT32(save_p);
+	unlocktriggers = P_ReadUINT32(save_p);
 
 	for (i = 0; i < MAXPLAYERS; ++i)
 	{
-		if ((recmares = READUINT8(save_p)) == 0)
+		if ((recmares = P_ReadUINT8(save_p)) == 0)
 			continue;
 
 		for (curmare = 0; curmare < (recmares+1); ++curmare)
 		{
-			ntemprecords[i].score[curmare] = READUINT32(save_p);
-			ntemprecords[i].grade[curmare] = READUINT8(save_p);
-			ntemprecords[i].time[curmare] = (tic_t)READUINT32(save_p);
+			ntemprecords[i].score[curmare] = P_ReadUINT32(save_p);
+			ntemprecords[i].grade[curmare] = P_ReadUINT8(save_p);
+			ntemprecords[i].time[curmare] = (tic_t)P_ReadUINT32(save_p);
 
 			if (ntemprecords[i].grade[curmare] > GRADE_S)
 			{
@@ -4985,37 +5228,37 @@ static inline void P_NetUnArchiveEmblems(void)
 	}
 }
 
-static void P_NetArchiveSectorPortals(void)
+static void P_NetArchiveSectorPortals(save_t *save_p)
 {
-	WRITEUINT32(save_p, ARCHIVEBLOCK_SECPORTALS);
+	P_WriteUINT32(save_p, ARCHIVEBLOCK_SECPORTALS);
 
-	WRITEUINT32(save_p, secportalcount);
+	P_WriteUINT32(save_p, secportalcount);
 
 	for (size_t i = 0; i < secportalcount; i++)
 	{
 		UINT8 type = secportals[i].type;
 
-		WRITEUINT8(save_p, type);
-		WRITEFIXED(save_p, secportals[i].origin.x);
-		WRITEFIXED(save_p, secportals[i].origin.y);
+		P_WriteUINT8(save_p, type);
+		P_WriteFixed(save_p, secportals[i].origin.x);
+		P_WriteFixed(save_p, secportals[i].origin.y);
 
 		switch (type)
 		{
 		case SECPORTAL_LINE:
-			WRITEUINT32(save_p, SaveLine(secportals[i].line.start));
-			WRITEUINT32(save_p, SaveLine(secportals[i].line.dest));
+			P_WriteUINT32(save_p, SaveLine(secportals[i].line.start));
+			P_WriteUINT32(save_p, SaveLine(secportals[i].line.dest));
 			break;
 		case SECPORTAL_PLANE:
 		case SECPORTAL_HORIZON:
 		case SECPORTAL_FLOOR:
 		case SECPORTAL_CEILING:
-			WRITEUINT32(save_p, SaveSector(secportals[i].sector));
+			P_WriteUINT32(save_p, SaveSector(secportals[i].sector));
 			break;
 		case SECPORTAL_OBJECT:
 			if (secportals[i].mobj && !P_MobjWasRemoved(secportals[i].mobj))
 				SaveMobjnum(secportals[i].mobj);
 			else
-				WRITEUINT32(save_p, 0);
+				P_WriteUINT32(save_p, 0);
 			break;
 		default:
 			break;
@@ -5023,15 +5266,15 @@ static void P_NetArchiveSectorPortals(void)
 	}
 }
 
-static void P_NetUnArchiveSectorPortals(void)
+static void P_NetUnArchiveSectorPortals(save_t *save_p)
 {
-	if (READUINT32(save_p) != ARCHIVEBLOCK_SECPORTALS)
+	if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_SECPORTALS)
 		I_Error("Bad $$$.sav at archive block Secportals");
 
 	Z_Free(secportals);
 	P_InitSectorPortals();
 
-	UINT32 count = READUINT32(save_p);
+	UINT32 count = P_ReadUINT32(save_p);
 
 	for (UINT32 i = 0; i < count; i++)
 	{
@@ -5039,24 +5282,24 @@ static void P_NetUnArchiveSectorPortals(void)
 
 		sectorportal_t *secportal = &secportals[id];
 
-		secportal->type = READUINT8(save_p);
-		secportal->origin.x = READFIXED(save_p);
-		secportal->origin.y = READFIXED(save_p);
+		secportal->type = P_ReadUINT8(save_p);
+		secportal->origin.x = P_ReadFixed(save_p);
+		secportal->origin.y = P_ReadFixed(save_p);
 
 		switch (secportal->type)
 		{
 		case SECPORTAL_LINE:
-			secportal->line.start = LoadLine(READUINT32(save_p));
-			secportal->line.dest = LoadLine(READUINT32(save_p));
+			secportal->line.start = LoadLine(P_ReadUINT32(save_p));
+			secportal->line.dest = LoadLine(P_ReadUINT32(save_p));
 			break;
 		case SECPORTAL_PLANE:
 		case SECPORTAL_HORIZON:
 		case SECPORTAL_FLOOR:
 		case SECPORTAL_CEILING:
-			secportal->sector = LoadSector(READUINT32(save_p));
+			secportal->sector = LoadSector(P_ReadUINT32(save_p));
 			break;
 		case SECPORTAL_OBJECT:
-			id = READUINT32(save_p);
+			id = P_ReadUINT32(save_p);
 			secportal->mobj = (id == 0) ? NULL : P_FindNewPosition(id);
 			break;
 		default:
@@ -5065,7 +5308,7 @@ static void P_NetUnArchiveSectorPortals(void)
 	}
 }
 
-static inline void P_ArchiveLuabanksAndConsistency(void)
+static inline void P_ArchiveLuabanksAndConsistency(save_t *save_p)
 {
 	UINT8 i, banksinuse = NUM_LUABANKS;
 
@@ -5074,30 +5317,30 @@ static inline void P_ArchiveLuabanksAndConsistency(void)
 
 	if (banksinuse)
 	{
-		WRITEUINT8(save_p, 0xb7); // luabanks marker
-		WRITEUINT8(save_p, banksinuse);
+		P_WriteUINT8(save_p, 0xb7); // luabanks marker
+		P_WriteUINT8(save_p, banksinuse);
 		for (i = 0; i < banksinuse; i++)
-			WRITEINT32(save_p, luabanks[i]);
+			P_WriteINT32(save_p, luabanks[i]);
 	}
 
-	WRITEUINT8(save_p, 0x1d); // consistency marker
+	P_WriteUINT8(save_p, 0x1d); // consistency marker
 }
 
-static inline boolean P_UnArchiveLuabanksAndConsistency(void)
+static inline boolean P_UnArchiveLuabanksAndConsistency(save_t *save_p)
 {
-	switch (READUINT8(save_p))
+	switch (P_ReadUINT8(save_p))
 	{
 		case 0xb7: // luabanks marker
 			{
-				UINT8 i, banksinuse = READUINT8(save_p);
+				UINT8 i, banksinuse = P_ReadUINT8(save_p);
 				if (banksinuse > NUM_LUABANKS)
 				{
 					CONS_Alert(CONS_ERROR, M_GetText("Corrupt Luabanks! (Too many banks in use)\n"));
 					return false;
 				}
 				for (i = 0; i < banksinuse; i++)
-					luabanks[i] = READINT32(save_p);
-				if (READUINT8(save_p) != 0x1d) // consistency marker
+					luabanks[i] = P_ReadINT32(save_p);
+				if (P_ReadUINT8(save_p) != 0x1d) // consistency marker
 				{
 					CONS_Alert(CONS_ERROR, M_GetText("Corrupt Luabanks! (Failed consistency check)\n"));
 					return false;
@@ -5113,22 +5356,22 @@ static inline boolean P_UnArchiveLuabanksAndConsistency(void)
 	return true;
 }
 
-void P_SaveGame(INT16 mapnum)
+void P_SaveGame(save_t *save_p, INT16 mapnum)
 {
-	P_ArchiveMisc(mapnum);
-	P_ArchivePlayer();
-	P_ArchiveLuabanksAndConsistency();
+	P_ArchiveMisc(save_p, mapnum);
+	P_ArchivePlayer(save_p);
+	P_ArchiveLuabanksAndConsistency(save_p);
 }
 
-void P_SaveNetGame(boolean resending)
+void P_SaveNetGame(save_t *save_p, boolean resending)
 {
 	thinker_t *th;
 	mobj_t *mobj;
 	INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise
 
-	CV_SaveNetVars(&save_p);
-	P_NetArchiveMisc(resending);
-	P_NetArchiveEmblems();
+	CV_SaveNetVars(save_p);
+	P_NetArchiveMisc(save_p, resending);
+	P_NetArchiveEmblems(save_p);
 
 	// Assign the mobjnumber for pointer tracking
 	for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
@@ -5142,32 +5385,32 @@ void P_SaveNetGame(boolean resending)
 		mobj->mobjnum = i++;
 	}
 
-	P_NetArchivePlayers();
+	P_NetArchivePlayers(save_p);
 	if (gamestate == GS_LEVEL)
 	{
-		P_NetArchiveWorld();
-		P_ArchivePolyObjects();
-		P_NetArchiveThinkers();
-		P_NetArchiveSpecials();
-		P_NetArchiveColormaps();
-		P_NetArchiveWaypoints();
-		P_NetArchiveSectorPortals();
+		P_NetArchiveWorld(save_p);
+		P_ArchivePolyObjects(save_p);
+		P_NetArchiveThinkers(save_p);
+		P_NetArchiveSpecials(save_p);
+		P_NetArchiveColormaps(save_p);
+		P_NetArchiveWaypoints(save_p);
+		P_NetArchiveSectorPortals(save_p);
 	}
-	LUA_Archive();
+	LUA_Archive(save_p);
 
-	P_ArchiveLuabanksAndConsistency();
+	P_ArchiveLuabanksAndConsistency(save_p);
 }
 
-boolean P_LoadGame(INT16 mapoverride)
+boolean P_LoadGame(save_t *save_p, INT16 mapoverride)
 {
 	if (gamestate == GS_INTERMISSION)
 		Y_EndIntermission();
 	G_SetGamestate(GS_NULL); // should be changed in P_UnArchiveMisc
 
-	P_UnArchiveSPGame(mapoverride);
-	P_UnArchivePlayer();
+	P_UnArchiveSPGame(save_p, mapoverride);
+	P_UnArchivePlayer(save_p);
 
-	if (!P_UnArchiveLuabanksAndConsistency())
+	if (!P_UnArchiveLuabanksAndConsistency(save_p))
 		return false;
 
 	// Only do this after confirming savegame is ok
@@ -5177,26 +5420,26 @@ boolean P_LoadGame(INT16 mapoverride)
 	return true;
 }
 
-boolean P_LoadNetGame(boolean reloading)
+boolean P_LoadNetGame(save_t *save_p, boolean reloading)
 {
-	CV_LoadNetVars(&save_p);
-	if (!P_NetUnArchiveMisc(reloading))
+	CV_LoadNetVars(save_p);
+	if (!P_NetUnArchiveMisc(save_p, reloading))
 		return false;
-	P_NetUnArchiveEmblems();
-	P_NetUnArchivePlayers();
+	P_NetUnArchiveEmblems(save_p);
+	P_NetUnArchivePlayers(save_p);
 	if (gamestate == GS_LEVEL)
 	{
-		P_NetUnArchiveWorld();
-		P_UnArchivePolyObjects();
-		P_NetUnArchiveThinkers();
-		P_NetUnArchiveSpecials();
-		P_NetUnArchiveColormaps();
-		P_NetUnArchiveWaypoints();
-		P_NetUnArchiveSectorPortals();
+		P_NetUnArchiveWorld(save_p);
+		P_UnArchivePolyObjects(save_p);
+		P_NetUnArchiveThinkers(save_p);
+		P_NetUnArchiveSpecials(save_p);
+		P_NetUnArchiveColormaps(save_p);
+		P_NetUnArchiveWaypoints(save_p);
+		P_NetUnArchiveSectorPortals(save_p);
 		P_RelinkPointers();
 		P_FinishMobjs();
 	}
-	LUA_UnArchive();
+	LUA_UnArchive(save_p);
 
 	// This is stupid and hacky, but maybe it'll work!
 	P_SetRandSeed(P_GetInitSeed());
@@ -5207,5 +5450,5 @@ boolean P_LoadNetGame(boolean reloading)
 	// precipitation when loading a netgame save. Instead, precip has to be spawned here.
 	// This is done in P_NetUnArchiveSpecials now.
 
-	return P_UnArchiveLuabanksAndConsistency();
+	return P_UnArchiveLuabanksAndConsistency(save_p);
 }
diff --git a/src/p_saveg.h b/src/p_saveg.h
index 545008e7efc6af656fe94864a4ebcf8ea28e5f27..8aa83c80f8b530b266c1e16cccc6bf86272ddce4 100644
--- a/src/p_saveg.h
+++ b/src/p_saveg.h
@@ -18,17 +18,24 @@
 #pragma interface
 #endif
 
+#include "tables.h"
+
 #define NEWSKINSAVES (INT16_MAX) // TODO: 2.3: Delete (Purely for backwards compatibility)
 
 // Persistent storage/archiving.
 // These are the load / save game routines.
 
-void P_SaveGame(INT16 mapnum);
-void P_SaveNetGame(boolean resending);
-boolean P_LoadGame(INT16 mapoverride);
-boolean P_LoadNetGame(boolean reloading);
+typedef struct
+{
+	unsigned char *buf;
+	size_t size;
+	size_t pos;
+} save_t;
 
-mobj_t *P_FindNewPosition(UINT32 oldposition);
+void P_SaveGame(save_t *save_p, INT16 mapnum);
+void P_SaveNetGame(save_t *save_p, boolean resending);
+boolean P_LoadGame(save_t *save_p, INT16 mapoverride);
+boolean P_LoadNetGame(save_t *save_p, boolean reloading);
 
 typedef struct
 {
@@ -42,6 +49,37 @@ typedef struct
 } savedata_t;
 
 extern savedata_t savedata;
-extern UINT8 *save_p;
+
+void P_WriteUINT8(save_t *p, UINT8 v);
+void P_WriteSINT8(save_t *p, SINT8 v);
+void P_WriteUINT16(save_t *p, UINT16 v);
+void P_WriteINT16(save_t *p, INT16 v);
+void P_WriteUINT32(save_t *p, UINT32 v);
+void P_WriteINT32(save_t *p, INT32 v);
+void P_WriteChar(save_t *p, char v);
+void P_WriteFixed(save_t *p, fixed_t v);
+void P_WriteAngle(save_t *p, angle_t v);
+void P_WriteStringN(save_t *p, char const *s, size_t n);
+void P_WriteStringL(save_t *p, char const *s, size_t n);
+void P_WriteString(save_t *p, char const *s);
+void P_WriteMem(save_t *p, void const *s, size_t n);
+
+void P_SkipStringN(save_t *p, size_t n);
+void P_SkipStringL(save_t *p, size_t n);
+void P_SkipString(save_t *p);
+
+UINT8 P_ReadUINT8(save_t *p);
+SINT8 P_ReadSINT8(save_t *p);
+UINT16 P_ReadUINT16(save_t *p);
+INT16 P_ReadINT16(save_t *p);
+UINT32 P_ReadUINT32(save_t *p);
+INT32 P_ReadINT32(save_t *p);
+char P_ReadChar(save_t *p);
+fixed_t P_ReadFixed(save_t *p);
+angle_t P_ReadAngle(save_t *p);
+void P_ReadStringN(save_t *p, char *s, size_t n);
+void P_ReadStringL(save_t *p, char *s, size_t n);
+void P_ReadString(save_t *p, char *s);
+void P_ReadMem(save_t *p, void *s, size_t n);
 
 #endif