shithub: wl3d

Download patch

ref: 6141459776d34b526b6a7b500929210020cf3a6d
parent: c357c95979607c5a1e897aefff881e8991f8e2f2
author: qwx <>
date: Sun Sep 10 22:47:53 EDT 2017

refactor load/save code using cinap packing technology

also reduce calls to disking() to bare minimum, since these just
slow everything down

--- a/fns.h
+++ b/fns.h
@@ -2,8 +2,10 @@
 void	grab(int);
 void	toss(void);
 void	flush(void);
-int	wrsav(int);
-int	ldsav(int);
+void	pack(char*, ...);
+void	unpack(char*, ...);
+void	wrsav(int);
+void	ldsav(int);
 char*	demof(char*);
 void	wrconf(void);
 void	rdconf(void);
@@ -64,8 +66,8 @@
 Obj*	ospawn(Tile*, State*);
 void	uworld(void);
 void	mapmus(void);
-uchar*	wrmap(uchar*);
-int	ldmap(uchar*, uchar**);
+void	wrmap(void);
+void	ldmap(void);
 void	initmap(void);
 void	sodmap(void);
 void	dieturn(void);
@@ -81,8 +83,8 @@
 void	nextmap(void);
 void	game(void);
 void	spshunt(void);
-uchar*	wrgm(uchar*);
-uchar*	ldgm(uchar*);
+void	wrgm(void);
+void	ldgm(void);
 void	greset(void);
 void	ginit(uchar*, int, int);
 uchar*	opl2out(uchar*, int);
@@ -96,10 +98,3 @@
 void	stopmus(void);
 void	mus(int);
 void	initsnd(void);
-
-#define	GET8(p)	((p)[0]);(p)++
-#define	GET16(p)	((p)[0]|((p)[1]<<8));(p)+=2
-#define	GET32(p)	((p)[0]|((p)[1]<<8)|((p)[2]<<16)|((p)[3]<<24));(p)+=4
-#define	PUT8(p,v)	(p)[0]=(v);(p)++
-#define	PUT16(p,v)	(p)[0]=(v);(p)[1]=(v)>>8;(p)+=2
-#define	PUT32(p,v)	(p)[0]=(v);(p)[1]=(v)>>8;(p)[2]=(v)>>16;(p)[3]=(v)>>24;(p)+=4
--- a/fs.c
+++ b/fs.c
@@ -1,6 +1,7 @@
 #include <u.h>
 #include <libc.h>
 #include <bio.h>
+#include <fcall.h>
 #include "dat.h"
 #include "fns.h"
 
@@ -446,20 +447,13 @@
 enum{
 	Nplane = 2,
 	Planesz = Mapa * Nplane,
-	Mapsz = Planesz * Nplane,
-	Svgmsz = 2+2+4+4+4+17*2+4+4+4+2+2+2+4+4+1+1,
-	Svmapsz = Mapa * (2+2+1+1) + Narea + Narea * Narea,
-	Svobjsz = 2+2+2+2+1+4+4+4+2+2+1+2+2+4+2+2+4+2+2,
-	Svstsz = 2+2+1+1,
-	Svdrsz = 2+1+1+2+2+2,
-	Svpshsz = 2+2+2+2,
-	Svsz = sizeof(savs[0]) + Svgmsz + Svmapsz + Svobjsz + 2 + 2 + 2 + Svpshsz,
-	Svmax = Svsz + Nobj * Svobjsz + (Nstc-1) * Svstsz + (Ndoor-1) * Svdrsz
+	Mapsz = Planesz * Nplane
 };
 static Dat *pcms;
 static int alofs, npcm;
 static u16int rlewtag;
 static u32int *mapofs, *mape;
+static Biobuf *outbf;
 
 struct Conf{
 	char *s;
@@ -477,8 +471,6 @@
 };
 static int badconf;
 
-#define	GBIT16(p)	((p)[0]|((p)[1]<<8))
-
 static Biobuf *
 bopen(char *f, int m)
 {
@@ -504,6 +496,13 @@
 	return bf;
 }
 
+static void
+ewrite(Biobuf *bf, void *u, long n)
+{
+	if(Bwrite(bf, u, n) != n)
+		sysfatal("ewrite: short write: %r");
+}
+
 static long
 eread(Biobuf *bf, void *u, long n)
 {
@@ -1089,53 +1088,121 @@
 	}
 }
 
-int
+void
+vpack(char *fmt, va_list a)
+{
+	long n;
+	void *p;
+	u32int v;
+	uchar u[4];
+
+	for(;;){
+		switch(*fmt++){
+		default: sysfatal("unknown format %c", fmt[-1]);
+		case 0: return;
+		out8:
+			ewrite(outbf, u, sizeof(u8int));
+			break;
+		out16:
+			PBIT16(u, v);
+			ewrite(outbf, u, sizeof(u16int));
+			break;
+		case 'b':
+			u[0] = va_arg(a, int);
+			goto out8;
+		case 'B':
+			u[0] = va_arg(a, u8int);
+			goto out8;
+		case 'w':
+			v = va_arg(a, int);
+			goto out16;
+		case 'W':
+			v = va_arg(a, u16int);
+			goto out16;
+		case 'd':
+			v = va_arg(a, int);
+			PBIT32(u, v);
+			ewrite(outbf, u, sizeof(u32int));
+			break;
+		case 'n':
+			p = va_arg(a, void*);
+			n = va_arg(a, long);
+			ewrite(outbf, p, n);
+			break;
+		}
+	}
+}
+
+void
+vunpack(char *fmt, va_list a)
+{
+	long n;
+	void *p;
+
+	for(;;){
+		switch(*fmt++){
+		default: sysfatal("unknown format %c", fmt[-1]);
+		case 0: return;
+		case 'b': *va_arg(a, int*) = get8(outbf); break;
+		case 'B': *va_arg(a, u8int*) = get8(outbf); break;
+		case 'w': *va_arg(a, int*) = get16(outbf); break;
+		case 'W': *va_arg(a, u16int*) = get16(outbf); break;
+		case 'd': *va_arg(a, int*) = get32(outbf); break;
+		case 's': *va_arg(a, int*) = (s16int)get16(outbf); break;
+		case 'S': *va_arg(a, int*) = (s32int)get32(outbf); break;
+		case 'n':
+			p = va_arg(a, void*);
+			n = va_arg(a, long);
+			eread(outbf, p, n);
+			break;
+		}
+	}
+}
+
+void
+pack(char *fmt, ...)
+{
+	va_list a;
+
+	va_start(a, fmt);
+	vpack(fmt, a);
+	va_end(a);
+}
+
+void
+unpack(char *fmt, ...)
+{
+	va_list a;
+
+	va_start(a, fmt);
+	vunpack(fmt, a);
+	va_end(a);
+}
+
+void
 wrsav(int i)
 {
-	int r;
-	vlong n;
-	uchar *u, *p;
 	char s[10] = "savegam?.";
-	Biobuf *bf;
 
 	s[7] = '0' + i;
-	bf = eopen(s, OWRITE);
-	u = emalloc(Svmax);
-	memcpy(u, savs[i], sizeof savs[0]);
-	p = wrgm(u + sizeof savs[0]);
-	p = wrmap(p);
-	assert(p <= u + Svmax);
-	n = p - u;
-	r = Bwrite(bf, u, n) != n ? -1 : 0;
-	Bterm(bf);
-	free(u);
-	return r;
+	outbf = eopen(s, OWRITE);
+	ewrite(outbf, savs[i], sizeof savs[0]);
+	wrgm();
+	wrmap();
+	Bterm(outbf);
 }
 
-int
+void
 ldsav(int i)
 {
-	int r;
-	vlong n;
-	uchar *u, *p;
 	char s[10] = "savegam?.";
-	Biobuf *bf;
 
 	s[7] = '0' + i;
-	bf = eopen(s, OREAD);
-	n = bsize(bf);
-	if(n < Svsz){
-		werrstr("ldsav: short map");
-		return -1;
-	}
-	u = emalloc(n);
-	eread(bf, u, n);
-	Bterm(bf);
-	p = ldgm(u + sizeof savs[0]);
-	r = ldmap(p, &p);
-	assert(p <= u + n);
-	free(u);
-	return r;
+	outbf = eopen(s, OREAD);
+	Bseek(outbf, sizeof savs[0], 0);
+	ldgm();
+	ldmap();
+	Bterm(outbf);
 }
 
 u16int *
--- a/gm.c
+++ b/gm.c
@@ -2664,80 +2664,27 @@
 	oplr->areaid = oplr->tl->p0 - MTfloor;
 }
 
-uchar *
-wrgm(uchar *p)
+void
+wrgm(void)
 {
 	disking();
-	PUT16(p, gm.difc);
-	PUT16(p, gm.map);
-	PUT32(p, gm.oldpt);
-	PUT32(p, gm.pt);
-	PUT32(p, gm.to1up);
-	PUT16(p, gm.lives);
-	PUT16(p, gm.hp);
-	PUT16(p, gm.ammo);
-	PUT16(p, gm.keys);
-	PUT16(p, gm.bestw);
-	PUT16(p, gm.w);
-	PUT16(p, gm.lastw);
-	PUT16(p, gm.facefrm);
-	PUT16(p, atkfrm);
-	PUT16(p, atktc);
-	PUT16(p, gm.wfrm);
-	PUT16(p, gm.sp);
-	PUT16(p, gm.tp);
-	PUT16(p, gm.kp);
-	PUT16(p, gm.stot);
-	PUT16(p, gm.ttot);
-	PUT16(p, gm.ktot);
-	PUT32(p, gm.tc);
-	PUT32(p, killx);
-	PUT32(p, killy);
-	PUT16(p, gm.epk);
-	PUT16(p, gm.eps);
-	PUT16(p, gm.ept);
-	PUT32(p, gm.eptm);
-	PUT8(p, dirty);
-	PUT8(p, firing);
-	return p;
+	pack("wwdddwwwwwwwwwwwwwwwwwdddwwwdbb", gm.difc, gm.map, gm.oldpt,
+		gm.pt, gm.to1up, gm.lives, gm.hp, gm.ammo, gm.keys, gm.bestw,
+		gm.w, gm.lastw, gm.facefrm, atkfrm, atktc, gm.wfrm, gm.sp,
+		gm.tp, gm.kp, gm.stot, gm.ttot, gm.ktot, gm.tc, killx, killy,
+		gm.epk, gm.eps, gm.ept, gm.eptm, dirty, firing);
 }
 
-uchar *
-ldgm(uchar *p)
+void
+ldgm(void)
 {
 	disking();
-	gm.difc = GET16(p);
-	gm.map = GET16(p);
-	gm.oldpt = GET32(p);
-	gm.pt = GET32(p);
-	gm.to1up = GET32(p);
-	gm.lives = GET16(p);
-	gm.hp = GET16(p);
-	gm.ammo = GET16(p);
-	gm.keys = GET16(p);
-	gm.bestw = GET16(p);
-	gm.w = GET16(p);
-	gm.lastw = GET16(p);
-	gm.facefrm = GET16(p);
-	atkfrm = GET16(p);
-	atktc = (s16int)GET16(p);
-	gm.wfrm = GET16(p);
-	gm.sp = GET16(p);
-	gm.tp = GET16(p);
-	gm.kp = GET16(p);
-	gm.stot = GET16(p);
-	gm.ttot = GET16(p);
-	gm.ktot = GET16(p);
-	gm.tc = GET32(p);
-	killx = GET32(p);
-	killy = GET32(p);
-	gm.epk = GET16(p);
-	gm.eps = GET16(p);
-	gm.ept = GET16(p);
-	gm.eptm = GET32(p);
-	dirty = GET8(p);
-	firing = GET8(p);
-	return p;
+	unpack("wwdddwwwwwwwwwswwwwwwwdddwwwdbb", &gm.difc, &gm.map, &gm.oldpt,
+		&gm.pt, &gm.to1up, &gm.lives, &gm.hp, &gm.ammo, &gm.keys,
+		&gm.bestw, &gm.w, &gm.lastw, &gm.facefrm, &atkfrm, &atktc,
+		&gm.wfrm, &gm.sp, &gm.tp, &gm.kp, &gm.stot, &gm.ttot, &gm.ktot,
+		&gm.tc, &killx, &killy, &gm.epk, &gm.eps, &gm.ept, &gm.eptm,
+		&dirty, &firing);
 }
 
 void
--- a/hub.c
+++ b/hub.c
@@ -664,23 +664,16 @@
 	n = mp->p - mp->s;
 	if(qsp == ql+Lwrsav){
 		qsp->q = ql+Lftoctl;
-		if(wrsav(n) < 0)
-			goto err;
+		wrsav(n);
 	}else{
 		qsp->q = ql+Lldsav2;
 		ginit(nil, -1, 0);
 		greset();
-		if(ldsav(n) < 0)
-			goto err;
+		ldsav(n);
 		ingctl();
 		loaded++;
 	}
 	sfx(Sshoot);
-	return;
-err:
-	memset(savs[n], 0, sizeof savs[0]);
-	qsp->q = ql+Lftoctl;
-	sfx(Snoway);
 }
 
 static void
--- a/map.c
+++ b/map.c
@@ -819,8 +819,8 @@
 	mus(ver < SDM ? wlmus[gm.map] : sdmus[gm.map]);
 }
 
-uchar *
-wrmap(uchar *p)
+void
+wrmap(void)
 {
 	Tile *tl;
 	Obj *o;
@@ -827,62 +827,25 @@
 	Static *s;
 	Door *d;
 
+	for(tl=tiles; tl<tiles+nelem(tiles); tl++)
+		pack("WWBB", tl->p0, tl->p1, tl->tl, tl->to);
+	pack("nn", conarea, sizeof conarea, plrarea, sizeof plrarea);
 	disking();
-	for(tl=tiles; tl<tiles+nelem(tiles); tl++){
-		PUT16(p, tl->p0);
-		PUT16(p, tl->p1);
-		PUT8(p, tl->tl);
-		PUT8(p, tl->to);
-	}
-	memcpy(p, conarea, sizeof conarea); p+=sizeof conarea;
-	memcpy(p, plrarea, sizeof plrarea); p+=sizeof plrarea;
-	for(o=oplr; o!=objs; o=o->n){
-		disking();
-		PUT16(p, o->on);
-		PUT16(p, o->tc);
-		PUT16(p, o->type);
-		PUT16(p, o->s - stt);
-		PUT8(p, o->f);
-		PUT32(p, o->Δr);
-		PUT32(p, o->x);
-		PUT32(p, o->y);
-		PUT16(p, o->tx);
-		PUT16(p, o->ty);
-		PUT8(p, o->areaid);
-		PUT16(p, o->vwx);
-		PUT16(p, o->vwdy);
-		PUT32(p, o->vwdx);
-		PUT16(p, o->θ);
-		PUT16(p, o->hp);
-		PUT32(p, o->v);
-		PUT16(p, o->atkdt);
-		PUT16(p, o->sdt);
-	}
-	PUT16(p, 0xffff);
+	for(o=oplr; o!=objs; o=o->n)
+		pack("wwwwbdddwwbwwdwwdww", o->on, o->tc, o->type, (int)(o->s - stt),
+			o->f, o->Δr, o->x, o->y, o->tx, o->ty, o->areaid,
+			o->vwx, o->vwdy, o->vwdx, o->θ, o->hp, o->v, o->atkdt,
+			o->sdt);
 	disking();
-	PUT16(p, stce - stcs);
-	for(s=stcs; s<stce; s++){
-		PUT16(p, s->tl != nil ? s->tl - tiles : 0xffff);
-		PUT16(p, s->spr - sprs);
-		PUT8(p, s->f);
-		PUT8(p, s->item);
-	}
-	disking();
-	PUT16(p, doore - doors);
-	for(d=doors; d<doore; d++){
-		PUT16(p, d->tl - tiles);
-		PUT8(p, d->isvert);
-		PUT8(p, d->lock);
-		PUT16(p, d->φ);
-		PUT16(p, d->tc);
-		PUT16(p, d->dopen);
-	}
-	disking();
-	PUT16(p, pusher.φ);
-	PUT16(p, pusher.tl - tiles);
-	PUT16(p, pusher.isvert);
-	PUT16(p, pusher.dopen);
-	return p;
+	pack("ww", 0xffff, (int)(stce - stcs));
+	for(s=stcs; s<stce; s++)
+		pack("wwbb", s->tl != nil ? (int)(s->tl - tiles) : 0xffff,
+			(int)(s->spr - sprs), s->f, s->item);
+	pack("w", (int)(doore - doors));
+	for(d=doors; d<doore; d++)
+		pack("wbbwwW", (int)(d->tl - tiles), d->isvert, d->lock, d->φ,d->tc,
+			d->dopen);
+	pack("wwwW", pusher.φ, (int)(pusher.tl - tiles), pusher.isvert, pusher.dopen);
 }
 
 static void
@@ -927,52 +890,32 @@
 	sttdtinit();
 }
 
-int
-ldmap(uchar *p, uchar **ep)
+void
+ldmap(void)
 {
-	int n;
+	int n, m;
 	Tile *tl;
 	Obj *o;
 	Static *s;
 	Door *d;
 
-	disking();
 	nukemap();
+	for(tl=tiles; tl<tiles+nelem(tiles); tl++)
+		unpack("WWBB", &tl->p0, &tl->p1, &tl->tl, &tl->to);
+	unpack("nn", conarea, sizeof conarea, plrarea, sizeof plrarea);
 	disking();
-	for(tl=tiles; tl<tiles+nelem(tiles); tl++){
-		tl->p0 = GET16(p);
-		tl->p1 = GET16(p);
-		tl->tl = GET8(p);
-		tl->to = GET8(p);
-	}
-	disking();
-	memcpy(conarea, p, sizeof conarea); p+=sizeof conarea;
-	memcpy(plrarea, p, sizeof plrarea); p+=sizeof plrarea;
 	for(o=nil;;){
-		n = GET16(p);
+		unpack("w", &n);
 		if(n == 0xffff)
 			break;
 		o = o == nil ? oplr : onew();
 		o->on = n;
-		o->tc = (s16int)GET16(p);
-		o->type = GET16(p);
-		o->s = stt + GET16(p);
-		o->f = GET8(p);
-		o->Δr = (s32int)GET32(p);
-		o->x = GET32(p);
-		o->y = GET32(p);
-		o->tx = GET16(p);
-		o->ty = GET16(p);
+		unpack("swwbSddwwbwwdswdsw", &o->tc, &o->type, &n, &o->f,
+			&o->Δr, &o->x, &o->y, &o->tx, &o->ty, &o->areaid,
+			&o->vwx, &o->vwdy, &o->vwdx, &o->θ, &o->hp, &o->v,
+			&o->atkdt, &o->sdt);
+		o->s = stt + n;
 		o->tl = tiles + o->ty * Mapdxy + o->tx;
-		o->areaid = GET8(p);
-		o->vwx = GET16(p);
-		o->vwdy = GET16(p);
-		o->vwdx = GET32(p);
-		o->θ = (s16int)GET16(p);
-		o->hp = GET16(p);
-		o->v = GET32(p);
-		o->atkdt = (s16int)GET16(p);
-		o->sdt = GET16(p);
 		if(o != oplr && ((o->f & OFnevermark) == 0
 		|| (o->f & OFnomark) == 0 || o->tl->o == nil)){
 			o->tl->o = o;
@@ -980,39 +923,26 @@
 		}
 	}
 	disking();
-	stce = stcs + GET16(p);
-	if(stce > stcs + nelem(stcs)){
-		werrstr("ldmap: static object overflow");
-		return -1;
-	}
+	unpack("w", &n);
+	stce = stcs + n;
+	if(stce > stcs + nelem(stcs))
+		sysfatal("ldmap: static object overflow");
 	for(s=stcs; s<stce; s++){
-		n = GET16(p);
+		unpack("wwbb", &n, &m, &s->f, &s->item);
 		s->tl = n == 0xffff ? nil : tiles + n;
-		s->spr = sprs + GET16(p);
-		s->f = GET8(p);
-		s->item = GET8(p);
+		s->spr = sprs + m;
 	}
-	disking();
-	doore = doors + GET16(p);
-	if(doore > doors + nelem(doors)){
-		werrstr("ldmap: door overflow");
-		return -1;
-	}
+	unpack("w", &n);
+	doore = doors + n;
+	if(doore > doors + nelem(doors))
+		sysfatal("ldmap: door overflow");
 	for(d=doors; d<doore; d++){
-		d->tl = tiles + GET16(p);
-		d->isvert = GET8(p);
-		d->lock = GET8(p);
-		d->φ = GET16(p);
-		d->tc = GET16(p);
-		d->dopen = GET16(p);
+		unpack("wbbwwW", &n, &d->isvert, &d->lock, &d->φ, &d->tc,
+			&d->dopen);
+		d->tl = tiles + n;
 	}
-	disking();
-	pusher.φ = GET16(p);
-	pusher.tl = tiles + GET16(p);
-	pusher.isvert = GET16(p);
-	pusher.dopen = GET16(p);
-	*ep = p;
-	return 0;
+	unpack("wwwW", &pusher.φ, &n, &pusher.isvert, &pusher.dopen);
+	pusher.tl = tiles + n;
 }
 
 void