shithub: sce

Download patch

ref: 0622cb8e9d9874ee52e9881415554bc38570551d
parent: 10cff16795c01635a868ec5d09beb587df4edb79
author: qwx <qwx@sciops.net>
date: Wed Jul 28 08:26:19 EDT 2021

fs: fix not loading redundant pics, explicit rules for sprite sharing

previously, assumptions were made which make the code difficult
to understand and maintain for no gain.
data driven programming is nice, stupidity driven programming
less so.
instead, explicitely specify sprites for all needed states and
whether to freeze a frame or not.

--- a/dat.h
+++ b/dat.h
@@ -78,7 +78,8 @@
 	int teamcol;
 	int nf;
 	int nr;
-	int iscopy;
+	int shared;
+	int freeze;
 };
 
 struct Attack{
@@ -127,6 +128,7 @@
 	PFpoor = OSpoor,
 	PFstatemask = (1 << 5) - 1,
 
+	PFfreezepic = 1<<11,
 	PFimmutable = 1<<12,
 	PFglow = 1<<13,
 	PFalpha = 1<<14,
@@ -180,7 +182,7 @@
 	double v;
 	double speed;
 	Mobjl *movingp;
-	Mobjl *mobjl;
+	Mobjl *mapp;
 };
 struct Mobj{
 	Obj *o;
--- a/drw.c
+++ b/drw.c
@@ -322,7 +322,7 @@
 	pp = &mo->o->pics[n][type];
 	if(pp->pic == nil)
 		return nil;
-	frm = pp->iscopy ? mo->freezefrm : tc % pp->nf;
+	frm = pp->freeze ? mo->freezefrm : tc % pp->nf;
 	θ = mo->θ * 32.0 / 256;
 	switch(pp->nr){
 	case 17: θ = rot17[θ]; break;
--- a/fs.c
+++ b/fs.c
@@ -32,6 +32,7 @@
 	int type;
 	int teamcol;
 	char *name;
+	char *suff;
 	char iname[64];
 	int nr;
 	Pic *p;
@@ -98,7 +99,7 @@
 }
 
 static void
-loadobjpic(Pic *pic, Picl *pl, char *suff)
+loadobjpic(Pic *pic, Picl *pl)
 {
 	int n, i, j;
 	char path[128];
@@ -107,7 +108,7 @@
 
 	for(i=0; i<pl->nr; i++){
 		snprint(path, sizeof path, "%s.%02d.%02d%s.bit",
-			pl->name, pl->frm, rot17idx[i], suff);
+			pl->name, pl->frm, rot17idx[i], pl->suff);
 		loadpic(path, &pic0, pl->type & PFalpha);
 		if(!pl->teamcol){		
 			memcpy(pic++, &pic0, sizeof *pic);
@@ -163,12 +164,8 @@
 		p = pl->p;
 		if(pl->type & PFtile)
 			loadtilepic(p, pl);
-		else if(pl->type & PFshadow)
-			loadobjpic(p, pl, ".s");
-		else if(pl->type & PFglow)
-			loadobjpic(p, pl, ".g");
 		else
-			loadobjpic(p, pl, "");
+			loadobjpic(p, pl);
 		pic->l = pl->l;
 		free(pl);
 	}
@@ -176,16 +173,26 @@
 }
 
 static Pic *
-pushpic(char *name, int frm, int type, int nr, int hasteam)
+pushpic(char *name, int frm, int type, int nr, int hasteam, Pics *ps)
 {
 	int n;
-	char iname[64];
+	char iname[64], *suff;
 	Picl *pl;
 
-	snprint(iname, sizeof iname, "%s%02d%02ux", name, frm, type);
+	if(type & PFshadow)
+		suff = ".s";
+	else if(type & PFglow)
+		suff = ".g";
+	else
+		suff = "";
+	snprint(iname, sizeof iname, "%s.%02d%s", name, frm, suff);
 	for(pl=pic->l; pl!=pic; pl=pl->l)
-		if(strcmp(iname, pl->iname) == 0)
+		if(strcmp(iname, pl->iname) == 0){
+			if(ps == nil)
+				sysfatal("pushpic: tile pic cannot be shared");
+			ps->shared = 1;
 			break;
+		}
 	if(pl == pic){
 		pl = emalloc(sizeof *pl);
 		memcpy(pl->iname, iname, nelem(pl->iname));
@@ -192,6 +199,7 @@
 		pl->frm = frm;
 		pl->type = type;
 		pl->name = name;
+		pl->suff = suff;
 		pl->nr = nr;
 		pl->teamcol = hasteam;
 		if(nr != 17 && nr != 1)
@@ -220,7 +228,7 @@
 		tl = emalloc(sizeof *tl);
 		tl->id = id;
 		tl->t = emalloc(sizeof *tl->t);
-		tl->t->p = pushpic("/tile/", id - 1, PFtile, 1, 0);
+		tl->t->p = pushpic("/tile/", id - 1, PFtile, 1, 0, nil);
 		tl->l = tilel->l;
 		tilel->l = tl;
 	}
@@ -482,6 +490,7 @@
 		sysfatal("readspr %s: pic type %#ux already allocated", o->name, type);
 	if(ps->nf != 0 && ps->nf != n || ps->nr != 0 && ps->nr != nr)
 		sysfatal("readspr %s: spriteset phase error", o->name);
+	ps->freeze = (type & PFfreezepic) != 0;
 	ps->teamcol = (type & PFimmutable) == 0;
 	ps->nf = n;
 	ps->nr = nr;
@@ -489,7 +498,7 @@
 	*ppp = p;
 	for(pe=p+n; p<pe; p++){
 		unpack(fld++, "d", &frm);
-		*p = pushpic(o->name, frm, type, nr, ps->teamcol);
+		*p = pushpic(o->name, frm, type, nr, ps->teamcol, ps);
 	}
 }
 
@@ -626,30 +635,13 @@
 }
 
 static void
-fixobjspr(void)
+checkobj(void)
 {
 	Obj *o;
-	Pics *idle, *move;
 
-	for(o=obj; o<obj+nobj; o++){
-		if(o->f & (Fbuild|Fimmutable))
-			continue;
-		idle = o->pics[OSidle];
-		move = o->pics[OSmove];
-		if(idle[PTbase].pic == nil && move[PTbase].pic == nil)
+	for(o=obj; o<obj+nobj; o++)
+		if(o->pics[OSidle][PTbase].pic == nil)
 			sysfatal("obj %s: no base sprites loaded", o->name);
-		if(idle[PTbase].pic == nil){
-			memcpy(idle+PTbase, move+PTbase, sizeof *idle);
-			memcpy(idle+PTshadow, move+PTshadow, sizeof *idle);
-			idle[PTbase].iscopy = 1;
-			idle[PTshadow].iscopy = 1;
-		}else if(move[PTbase].pic == nil){
-			memcpy(move+PTbase, idle+PTbase, sizeof *move);
-			memcpy(move+PTshadow, idle+PTshadow, sizeof *move);
-			move[PTbase].iscopy = 1;
-			move[PTshadow].iscopy = 1;
-		}
-	}
 }
 
 static void
@@ -670,10 +662,10 @@
 initdb(void)
 {
 	checkdb();
+	checkobj();
 	initmap();
 	initmapobj();
 	cleanup();
-	fixobjspr();
 }
 
 void
--- a/sce/sce.db
+++ b/sce/sce.db
@@ -25,9 +25,13 @@
 # spr: objname, flags (PF enum), rotations, [frame..]
 spr,scv,0x0000,17,0
 spr,scv,0xc000,17,0
+spr,scv,0x0001,17,0
+spr,scv,0xc001,17,0
 spr,scv,0x6001,17,0,1,2,3
 spr,control,0x0000,1,0
 spr,control,0xc000,1,0
+spr,drone,0x0800,17,0,1,2,3,4
+spr,drone,0xc800,17,0,1,2,3,4
 spr,drone,0x0001,17,0,1,2,3,4
 spr,drone,0xc001,17,0,1,2,3,4
 spr,hatchery,0x0000,1,0,1,2,3,3,2,1,0
--- a/sim.move.c
+++ b/sim.move.c
@@ -12,7 +12,7 @@
 	Map *m;
 
 	m = map + mo->y / Node2Tile * mapwidth + mo->x / Node2Tile;
-	mo->mobjl = linkmobj(mo->o->f & Fair ? m->ml.lp : &m->ml, mo, mo->mobjl);
+	mo->mapp = linkmobj(mo->o->f & Fair ? m->ml.lp : &m->ml, mo, mo->mapp);
 }
 
 static void
@@ -58,9 +58,19 @@
 static void
 freemove(Mobj *mo)
 {
+	Pics *old, *new;
+
 	unlinkmobj(mo->movingp);
 	mo->pathp = nil;
-	mo->freezefrm = tc % mo->o->pics[mo->state][PTbase].nf;
+	old = mo->o->pics[mo->state];
+	new = mo->o->pics[OSidle];
+	if(new->freeze && old->shared){
+		mo->freezefrm = tc % old[PTbase].nf;
+		if(mo->freezefrm > new[PTbase].nf)
+			sysfatal("freemove obj %s: invalid frame number %d > %d",
+				mo->o->name, mo->freezefrm, new[PTbase].nf);
+	}else
+		mo->freezefrm = 0;
 	mo->state = OSidle;
 	resetcoords(mo);
 }
@@ -219,7 +229,7 @@
 	int r;
 
 	updatespeed(mo);
-	unlinkmobj(mo->mobjl);
+	unlinkmobj(mo->mapp);
 	r = trymove(mo);
 	linktomap(mo);
 	return r;