shithub: wl3d

Download patch

ref: ddcaa37baf64e0fc44f8ebf051005a0b0a1fd29b
parent: 7d1bc4ab95db2a1199150eb91cc0d7b1a5dd1128
author: Konstantinn Bonnet <[email protected]>
date: Sun Dec 4 22:15:07 EST 2016

add scaled walls and sprites, misc fixes

- fs: use more appropriate types for vswap data, interpret sprite data partially
  on load
- fs: fix stt sprites set based on sprs before it's allocated
- fs: fix pcm number and placement for wl1/sdm
- gm: use mtc as tic count for cam sprite display
- gm: constant time checks in gm only, not in main loop
- gm: fix demo and deathcam sprites placements
- hub: slow fadeout after demof end
- map: fix blocking static objects being set as pickable bonus items
- map: fix sod sprite offsets
- rend: remove bullshit special shape check
- rend: fix viss sorting in scaleall
- snd: fix extra pcm clipping/cracking; the remainder seems similar to reference

--- a/dat.h
+++ b/dat.h
@@ -2,6 +2,8 @@
 typedef int s32int;
 typedef struct Col Col;
 typedef struct Dat Dat;
+typedef struct Sprc Sprc;
+typedef struct Spr Spr;
 typedef struct Pic Pic;
 typedef struct Fnt Fnt;
 typedef struct Sfx Sfx;
@@ -82,8 +84,22 @@
 	uchar *p;
 	uchar *e;
 };
-extern Dat *wals, *sprs, *imfs;
-extern uchar **exts, **dems, **epis;
+extern Dat *imfs;
+struct Sprc{
+	uchar *p;
+	int s;
+	int e;
+};
+struct Spr{
+	int lx;
+	int rx;
+	Sprc **cs;
+	Sprc **ce;
+	uchar *sp;
+};
+extern Spr *sprs;
+extern uchar **exts, **dems, **epis, **wals;
+extern int drofs;
 
 struct Pic{
 	int x;
@@ -1096,6 +1112,7 @@
 	GSspark2,
 	GSspark3,
 	GSspark4,
+	GSe,
 
 	θE = 0,
 	θNE = 45,
@@ -1123,9 +1140,10 @@
 	void (*up)(Obj *);
 	void (*act)(Obj *);
 	int dt;
-	Dat *spr;
+	int sprn;
 	State *n;
 	int rot;
+	Spr *spr;
 };
 extern State stt[];
 struct Obj{
@@ -1164,7 +1182,7 @@
 extern Door doors[], *doore, pusher;
 struct Static{
 	Tile *tl;
-	Dat *spr;
+	Spr *spr;
 	int f;
 	int item;
 };
@@ -1243,7 +1261,6 @@
 	int demo;
 	int record;
 	int load;
-	int fizz;
 };
 extern Game gm;
 extern int god, noclip, onestep;
--- a/debug.c
+++ b/debug.c
@@ -1,326 +1,10 @@
-// WL_DEBUG.C
-
-#include "WL_DEF.H"
-#pragma hdrstop
-#include <BIOS.H>
-
-/*
-=============================================================================
-
-						 LOCAL CONSTANTS
-
-=============================================================================
-*/
-
 #define VIEWTILEX	(vw.dx/16)
 #define VIEWTILEY	(vw.dy/16)
 
-/*
-=============================================================================
-
-						 GLOBAL VARIABLES
-
-=============================================================================
-*/
-
-
-s16int DebugKeys (void);
-
-/*
-=============================================================================
-
-						 LOCAL VARIABLES
-
-=============================================================================
-*/
-
-
 s16int	maporgx;
 s16int	maporgy;
 enum {mapview,tilemapview,actoratview,visview}	viewtype;
 
-void ViewMap (void);
-
-//===========================================================================
-
-/*
-==================
-=
-= DebugMemory
-=
-==================
-*/
-
-void DebugMemory (void)
-{
-	s16int	i;
-	char    scratch[80],str[10];
-	s32int	mem;
-
-	CenterWindow (16,7);
-
-	US_CPrint ("Memory Usage");
-	US_CPrint ("------------");
-	US_Print ("Total     :");
-	US_PrintUnsigned (mminfo.mainmem/1024);
-	US_Print ("k\nFree      :");
-	US_PrintUnsigned (MM_UnusedMemory()/1024);
-	US_Print ("k\nWith purge:");
-	US_PrintUnsigned (MM_TotalFree()/1024);
-	US_Print ("k\n");
-	VW_UpdateScreen();
-	IN_Ack ();
-}
-
-//===========================================================================
-
-/*
-==================
-=
-= CountObjects
-=
-==================
-*/
-
-void CountObjects (void)
-{
-	s16int	i,total,count,active,inactive,doors;
-	objtype	*obj;
-
-	CenterWindow (16,7);
-	active = inactive = count = doors = 0;
-
-	US_Print ("Total statics :");
-	total = laststatobj-&statobjlist[0];
-	US_PrintUnsigned (total);
-
-	US_Print ("\nIn use statics:");
-	for (i=0;i<total;i++)
-		if (statobjlist[i].shapenum != -1)
-			count++;
-		else
-			doors++;	//debug
-	US_PrintUnsigned (count);
-
-	US_Print ("\nDoors         :");
-	US_PrintUnsigned (doornum);
-
-	for (obj=player->next;obj;obj=obj->next)
-	{
-		if (obj->active)
-			active++;
-		else
-			inactive++;
-	}
-
-	US_Print ("\nTotal actors  :");
-	US_PrintUnsigned (active+inactive);
-
-	US_Print ("\nActive actors :");
-	US_PrintUnsigned (active);
-
-	VW_UpdateScreen();
-	IN_Ack ();
-}
-
-void ShapeTest (void)
-{
-extern	u16int	NumDigi;
-extern	u16int	_seg *DigiList;
-static	char	buf[10];
-
-	int			done;
-	u8int		scan;
-	s16int				i,j,k,x;
-	u32int l;
-	uchar *addr;
-	PageListStruct	far *page;
-
-	CenterWindow(20,16);
-	VW_UpdateScreen();
-	for (i = 0,done = false;!done;)
-	{
-		US_ClearWindow();
-//		sound = -1;
-
-		page = &PMPages[i];
-		US_Print(" Page #");
-		US_PrintUnsigned(i);
-		if (i < PMSpriteStart)
-			US_Print(" (Wall)");
-		else if (i < PMSoundStart)
-			US_Print(" (Sprite)");
-		else if (i == ChunksInFile - 1)
-			US_Print(" (Sound Info)");
-		else
-			US_Print(" (Sound)");
-
-		US_Print("\n XMS: ");
-		if (page->xmsPage != -1)
-			US_PrintUnsigned(page->xmsPage);
-		else
-			US_Print("No");
-
-		US_Print("\n Main: ");
-		if (page->mainPage != -1)
-			US_PrintUnsigned(page->mainPage);
-		else if (page->emsPage != -1)
-		{
-			US_Print("EMS ");
-			US_PrintUnsigned(page->emsPage);
-		}
-		else
-			US_Print("No");
-
-		US_Print("\n Last hit: ");
-		US_PrintUnsigned(page->lastHit);
-
-		US_Print("\n Address: ");
-		addr = PM_GetPageAddress(i);
-		sprintf(buf,"0x%04x",(u16int)addr);
-		US_Print(buf);
-
-		if (addr)
-		{
-			if (i < PMSpriteStart)
-			{
-			//
-			// draw the wall
-			//
-				bufferofs += 32*SCREENWIDTH;
-				postx = 128;
-				postwidth = 1;
-				postsource = ((s32int)((u16int)addr))<<16;
-				for (x=0;x<64;x++,postx++,postsource+=64)
-				{
-					wallheight[postx] = 256;
-					ScalePost ();
-				}
-				bufferofs -= 32*SCREENWIDTH;
-			}
-			else if (i < PMSoundStart)
-			{
-			//
-			// draw the sprite
-			//
-				bufferofs += 32*SCREENWIDTH;
-				scalespr (160, i-PMSpriteStart, 64);
-				bufferofs -= 32*SCREENWIDTH;
-			}
-			else if (i == ChunksInFile - 1)
-			{
-				US_Print("\n\n Number of sounds: ");
-				US_PrintUnsigned(NumDigi);
-				for (l = j = k = 0;j < NumDigi;j++)
-				{
-					l += DigiList[(j * 2) + 1];
-					k += (DigiList[(j * 2) + 1] + (PMPageSize - 1)) / PMPageSize;
-				}
-				US_Print("\n Total bytes: ");
-				US_PrintUnsigned(l);
-				US_Print("\n Total pages: ");
-				US_PrintUnsigned(k);
-			}
-			else
-			{
-				u8int far *dp = (u8int far *)MK_FP(addr,0);
-				for (j = 0;j < NumDigi;j++)
-				{
-					k = (DigiList[(j * 2) + 1] + (PMPageSize - 1)) / PMPageSize;
-					if
-					(
-						(i >= PMSoundStart + DigiList[j * 2])
-					&&	(i < PMSoundStart + DigiList[j * 2] + k)
-					)
-						break;
-				}
-				if (j < NumDigi)
-				{
-//					sound = j;
-					US_Print("\n Sound #");
-					US_PrintUnsigned(j);
-					US_Print("\n Segment #");
-					US_PrintUnsigned(i - PMSoundStart - DigiList[j * 2]);
-				}
-				for (j = 0;j < page->length;j += 32)
-				{
-					u8int v = dp[j];
-					s16int v2 = (u16int)v;
-					v2 -= 128;
-					v2 /= 4;
-					if (v2 < 0)
-						VWB_Vlin(WindowY + WindowH - 32 + v2,
-								WindowY + WindowH - 32,
-								WindowX + 8 + (j / 32),BLACK);
-					else
-						VWB_Vlin(WindowY + WindowH - 32,
-								WindowY + WindowH - 32 + v2,
-								WindowX + 8 + (j / 32),BLACK);
-				}
-			}
-		}
-
-		VW_UpdateScreen();
-
-		while (!(scan = LastScan))
-			SD_Poll();
-
-		IN_ClearKey(scan);
-		switch (scan)
-		{
-		case sc_LeftArrow:
-			if (i)
-				i--;
-			break;
-		case sc_RightArrow:
-			if (++i >= ChunksInFile)
-				i--;
-			break;
-		case sc_W:	// Walls
-			i = 0;
-			break;
-		case sc_S:	// Sprites
-			i = PMSpriteStart;
-			break;
-		case sc_D:	// Digitized
-			i = PMSoundStart;
-			break;
-		case sc_I:	// Digitized info
-			i = ChunksInFile - 1;
-			break;
-		case sc_L:	// Load all pages
-			for (j = 0;j < ChunksInFile;j++)
-				PM_GetPage(j);
-			break;
-		case sc_P:
-//			if (sound != -1)
-//				SD_PlayDigitized(sound);
-			break;
-		case sc_Escape:
-			done = true;
-			break;
-		case sc_Enter:
-			PM_GetPage(i);
-			break;
-		}
-	}
-	SD_StopDigitized();
-}
-#pragma warn +pia
-
-
-
-//===========================================================================
-
-
-/*
-================
-=
-= DebugKeys
-=
-================
-*/
-
 s16int DebugKeys (void)
 {
 	int esc;
@@ -342,12 +26,6 @@
 		return 1;
 	}
 
-	if (Keyboard[sc_C])		// C = count objects
-	{
-		CountObjects();
-		return 1;
-	}
-
 	if (Keyboard[sc_E])		// E = quit level
 	{
 		if (tedlevel)
@@ -401,11 +79,6 @@
 			gamestate.ammo = 99;
 		huda ();
 		IN_Ack ();
-		return 1;
-	}
-	else if (Keyboard[sc_M])			// M = memory info
-	{
-		DebugMemory();
 		return 1;
 	}
 #ifdef SPEAR
--- a/def.h
+++ b/def.h
@@ -161,7 +161,7 @@
 
 // refresh variables
 extern	s32int		postsource;
-extern	u16int	postx;
+extern	u16int	scx;
 extern	u16int	postwidth;
 
 extern	dirtype opposite[9];
--- a/drw.c
+++ b/drw.c
@@ -5,8 +5,8 @@
 
 Fnt fnts[2], *fnt;
 Pic *pics;
-uchar **exts, **dems, **epis;
-Dat *wals, *sprs;
+uchar **exts, **dems, **epis, **wals;
+Spr *sprs;
 
 int scale, npx;
 uchar *px, pxb[Va], fzb[Vw*Vhud];
--- a/fns.h
+++ b/fns.h
@@ -31,6 +31,7 @@
 void	hudw(void);
 void	hudp(void);
 void	clear(void);
+void	scalspr(int, int, int);
 s32int	ffs(s32int, s32int);
 void	render(void);
 void	initscal(void);
@@ -50,6 +51,7 @@
 void	mapmus(void);
 void	initmap(void);
 void	sodmap(void);
+void	camwarp(void);
 void	bonus(Static*);
 int	rnd(void);
 void	gstep(void);
--- a/fs.c
+++ b/fs.c
@@ -4,6 +4,7 @@
 #include "dat.h"
 #include "fns.h"
 
+int drofs;
 u32int *pal, pals[Cend][256]={ {
 	0x000000, 0x0000aa, 0x00aa00, 0x00aaaa, 0xaa0000, 0xaa00aa, 0xaa5500,
 	0xaaaaaa, 0x555555, 0x5555ff, 0x55ff55, 0x55ffff, 0xff5555, 0xff55ff,
@@ -446,8 +447,7 @@
 	Mapsz = Planesz * Nplane
 };
 static Dat *pcms;
-static uchar *swpb;
-static int alofs;
+static int alofs, npcm;
 static u16int rlewtag;
 static u32int *mapofs, *mape;
 
@@ -628,66 +628,132 @@
 }
 
 static void
-packpcm(Biobuf *bf, Dat *e, u16int so, u16int po)
+walls(Biobuf *bf, int n, u16int *sz, u32int *of)
 {
-	u16int n;
-	Dat *p, *s;
+	uchar **d, **e;
 
-	p = s = wals+po;
-	while(++p < e){
+	drofs = n - 8;
+	wals = emalloc(n * sizeof *wals);
+	e = wals + n;
+	for(d=wals; d<e; d++, of++){
+		n = *sz++;
+		if(n == 0)
+			continue;
+		Bseek(bf, *of, 0);
+		*d = emalloc(n);
+		eread(bf, *d, n);
+	}
+}
+
+static void
+sprites(Biobuf *bf, int n, u16int *sz, u32int *of)
+{
+	uchar *hu, *u;
+	Spr *s, *e;
+	Sprc **c, *ap, a[65];
+
+	sprs = emalloc(n * sizeof *sprs);
+	e = sprs + n;
+	for(s=sprs; s<e; s++, of++){
+		n = *sz++;
+		if(n == 0)
+			continue;
+		Bseek(bf, *of, 0);
+		s->lx = get16(bf);
+		s->rx = get16(bf);
+		n -= 4;
+		s->sp = emalloc(n);
+		eread(bf, s->sp, n);
+		n = s->rx - s->lx + 1;
+		s->cs = emalloc(n * sizeof *s->cs);
+		s->ce = s->cs + n;
+		hu = s->sp;
+		c = s->cs;
+		while(n-- > 0){
+			u = s->sp + GBIT16(hu) - 4;
+			hu += 2;
+			ap = a;
+			ap->e = GBIT16(u) / 2, u+=2;
+			while(ap->e != 0){
+				ap->p = s->sp + (s16int)GBIT16(u) - 4, u+=2;
+				ap->s = GBIT16(u) / 2, u+=2;
+				ap->p += ap->s;
+				ap++;
+				ap->e = GBIT16(u) / 2, u+=2;
+			}
+			ap++;
+			*c = emalloc((ap-a) * sizeof **c);
+			memcpy(*c, a, (ap-a) * sizeof **c);
+			c++;
+		}
+	}
+}
+
+static void
+pcmpak(Biobuf *bf, int n, u16int *sz, u32int *of)
+{
+	u16int *csz, *cp, *ce;
+	uchar *u;
+	vlong sof;
+	Dat *d, *e;
+
+	sof = Bseek(bf, 0, 1);
+	Bseek(bf, of[n], 0);
+	n = sz[n] / 4;
+	csz = emalloc(n * sizeof *csz);
+	cp = csz;
+	ce = csz + n;
+	while(cp < ce){
 		Bseek(bf, 2, 1);
-		n = get16(bf);
-		while(s->e < s->p + n)
-			s->e = p++->e;
-		while(p->p == nil && p < e-1)
-			p++;
-		s++;
-		s->p = p->p;
-		s->e = p->e;
+		*cp++ = get16(bf);
 	}
-	n = s-wals;
-	wals = erealloc(wals, n * sizeof *wals);
-	sprs = wals + so;
-	pcms = wals + po;
+	npcm = n;
+	pcms = emalloc(n * sizeof *pcms);
+	Bseek(bf, sof, 0);
+	for(d=pcms, e=pcms+n, cp=csz; d<e; d++){
+		n = *cp++;
+		if(*sz == 0){
+			n = (n-1) / 4096 + 1;
+			sz += n;
+			of += n;
+			continue;
+		}
+		d->p = emalloc(n * sizeof *d->p);
+		d->e = d->p + n;
+		u = d->p;
+		while(u < d->e){
+			Bseek(bf, *of++, 0);
+			u += eread(bf, u, *sz++);
+		}
+	}
+	free(csz);
 }
 
 static void
 vswap(void)
 {
-	u16int n, v, w;
-	u32int *o, *p;
-	uchar *u;
-	Dat *s, *e;
+	int n, so, po;
+	u32int *ofs, *ofp;
+	u16int *szs, *szp;
 	Biobuf *bf;
 
 	bf = bopen("vswap.", OREAD);
 	n = get16(bf);
-	s = wals = emalloc((n-1) * sizeof *wals);
-	e = s + n-1;
-	v = get16(bf);
-	w = get16(bf);
-	p = o = emalloc(n * sizeof *o);
-
-	while(p < o+n)
-		*p++ = get32(bf);
-	while(s < e)
-		s++->e = (uchar*)(uintptr)get16(bf);
-	u = swpb = emalloc(bsize(bf) - Bseek(bf, 0, 1));
-	Bseek(bf, 2, 1);
-	for(p=o, s=wals; s<e; s++, p++){
-		n = (uintptr)s->e;
-		if(n == 0)
-			continue;
-		Bseek(bf, *p, 0);
-		s->p = u;
-		s->e = u + n;
-		u += eread(bf, u, n);
-	}
-	Bseek(bf, *p, 0);
-	free(o);
-	swpb = erealloc(swpb, u-swpb);
-
-	packpcm(bf, e-1, v, w);
+	so = get16(bf);
+	po = get16(bf);
+	ofs = emalloc(n * sizeof *ofs);
+	szs = emalloc(n * sizeof *szs);
+	ofp = ofs;
+	while(ofp < ofs + n)
+		*ofp++ = get32(bf);
+	szp = szs;
+	while(szp < szs + n)
+		*szp++ = get16(bf);
+	walls(bf, so, szs, ofs);
+	sprites(bf, po - so, szs + so, ofs + so);
+	pcmpak(bf, n - po - 1, szs + po, ofs + po);
+	free(ofs);
+	free(szs);
 	Bterm(bf);
 }
 
@@ -737,7 +803,7 @@
 		swap(sfxs+Sscream9, sfxs+Sschbdie);
 	}
 	p = pcmt[ver<SDM ? 0 : 1];
-	e = p + (ver==WL6 ? 46 : ver==WL1 ? 21 : ver==SDM ? 26 : 40);
+	e = p + npcm;
 	for(pcm=pcms; p<e; p++, pcm++)
 		if(*p != Send)
 			sfxs[*p].pcm = pcm;
@@ -951,6 +1017,16 @@
 }
 
 static void
+sttspr(void)
+{
+	State *s;
+
+	for(s=stt; s<stt+GSe; s++)
+		if(s->sprn != 0)
+			s->spr = sprs + s->sprn;
+}
+
+static void
 fixpal(void)
 {
 	u32int *p, *s;
@@ -1015,10 +1091,6 @@
 	if(bind(".", dir, MBEFORE|MCREATE) < 0 || chdir(dir) < 0)
 		fprint(2, "dat: %r\n");
 
-	if(ver >= SDM){
-		fixpal();
-		sodmap();
-	}
 	e = ext;
 	loadscr();
 	ext = e;
@@ -1028,6 +1100,11 @@
 		ext = "sod";
 	audiot();
 	gfx();
+	sttspr();
+	if(ver >= SDM){
+		fixpal();
+		sodmap();
+	}
 	ext = e;
 	cfg();
 }
--- a/gm.c
+++ b/gm.c
@@ -65,7 +65,7 @@
 static Crm crms[];
 static char crs[Ncrm];
 static int dmgtc, bonustc, facetc, funtc;
-static Obj *killer;
+static Obj *camobj;
 static int bosskillx, bosskilly;
 static int gotspear, spearx, speary, spearθ;
 static int atk[][4] = {
@@ -473,7 +473,7 @@
 	if(gm.hp <= 0){
 		gm.hp = 0;
 		gm.end = EDdie;
-		killer = from;
+		camobj = from;
 		if(ver >= SDM && from->type == Oneedle)
 			gm.mut++;
 	}
@@ -1307,9 +1307,6 @@
 static void
 cam(Obj *o)
 {
-	int Δx, Δy, Δr;
-	double θ;
-
 	if(gm.won){
 		gm.end = EDcam2;
 		return;
@@ -1316,33 +1313,9 @@
 	}
 	gm.won++;
 	gm.end = EDcam;
+	mtc = 0;
 	dofizz++;
-
-	ostate(oplr, stt+GSplrcam);
-	oplr->x = bosskillx;
-	oplr->y = bosskilly;
-	Δx = o->x - oplr->x;
-	Δy = oplr->y - o->y;
-	θ = atan2(Δy, Δx);
-	if(θ < 0)
-		θ = Fpi * 2 + θ;
-	oplr->θ = θ / (Fpi * 2) * 360;
-	Δr = 0x14000;
-	do{
-		oplr->x = o->x - ffs(Δr, cost[oplr->θ]);
-		oplr->y = o->y + ffs(Δr, sint[oplr->θ]);
-		Δr += 0x1000;
-	}while(!trymove(oplr, Dplr, 1, 0));
-	oplr->tx = oplr->x >> Dtlshift;
-	oplr->ty = oplr->y >> Dtlshift;
-	oplr->tl = tiles + oplr->ty * Mapdxy + oplr->tx;
-
-	switch(o->type){
-	case Oschb: ostate(o, stt+GSschbcam); break;
-	case Ootto: ostate(o, stt+GSottocam); break;
-	case Ofett: ostate(o, stt+GSfettcam); break;
-	case Ohitler: ostate(o, stt+GShitlercam); break;
-	}
+	camobj = o;
 }
 
 static void
@@ -1941,444 +1914,444 @@
 }
 
 State stt[] = {
-	[GSplr] {uplr, nil, 0, nil, nil, 0},
-	[GSplrcam] {nil, nil, 0, nil, nil, 0},
-	[GSblaz1] {urun, nil, 12, sprs+SPbjwalk1, stt+GSblaz2, 0},
-	[GSblaz2] {nil, nil, 3, sprs+SPbjwalk1, stt+GSblaz3, 0},
-	[GSblaz3] {urun, nil, 8, sprs+SPbjwalk2, stt+GSblaz4, 0},
-	[GSblaz4] {urun, nil, 12, sprs+SPbjwalk3, stt+GSblaz5, 0},
-	[GSblaz5] {nil, nil, 3, sprs+SPbjwalk3, stt+GSblaz6, 0},
-	[GSblaz6] {urun, nil, 8, sprs+SPbjwalk4, stt+GSblaz1, 0},
-	[GSjump1] {ujump, nil, 14, sprs+SPbjjump1, stt+GSjump2, 0},
-	[GSjump2] {ujump, runyell, 14, sprs+SPbjjump2, stt+GSjump3, 0},
-	[GSjump3] {ujump, nil, 14, sprs+SPbjjump3, stt+GSjump4, 0},
-	[GSjump4] {nil, victory, 300, sprs+SPbjjump4, stt+GSjump4, 0},
-	[GSgd] {uwait, nil, 0, sprs+SPgd, stt+GSgd, 1},
-	[GSgdwalk1] {uwalk, nil, 20, sprs+SPgdwalk1, stt+GSgdwalk2, 1},
-	[GSgdwalk2] {nil, nil, 5, sprs+SPgdwalk1, stt+GSgdwalk3, 1},
-	[GSgdwalk3] {uwalk, nil, 15, sprs+SPgdwalk2, stt+GSgdwalk4, 1},
-	[GSgdwalk4] {uwalk, nil, 20, sprs+SPgdwalk3, stt+GSgdwalk5, 1},
-	[GSgdwalk5] {nil, nil, 5, sprs+SPgdwalk3, stt+GSgdwalk6, 1},
-	[GSgdwalk6] {uwalk, nil, 15, sprs+SPgdwalk4, stt+GSgdwalk1, 1},
-	[GSgdpain1] {nil, nil, 10, sprs+SPgdpain1, stt+GSgdchase1, 2},
-	[GSgdpain2] {nil, nil, 10, sprs+SPgdpain2, stt+GSgdchase1, 2},
-	[GSgdchase1] {uchase, nil, 10, sprs+SPgdwalk1, stt+GSgdchase2, 1},
-	[GSgdchase2] {nil, nil, 3, sprs+SPgdwalk1, stt+GSgdchase3, 1},
-	[GSgdchase3] {uchase, nil, 8, sprs+SPgdwalk2, stt+GSgdchase4, 1},
-	[GSgdchase4] {uchase, nil, 10, sprs+SPgdwalk3, stt+GSgdchase5, 1},
-	[GSgdchase5] {nil, nil, 3, sprs+SPgdwalk3, stt+GSgdchase6, 1},
-	[GSgdchase6] {uchase, nil, 8, sprs+SPgdwalk4, stt+GSgdchase1, 1},
-	[GSgdfire1] {nil, nil, 20, sprs+SPgdfire1, stt+GSgdfire2, 0},
-	[GSgdfire2] {nil, fire, 20, sprs+SPgdfire2, stt+GSgdfire3, 0},
-	[GSgdfire3] {nil, nil, 20, sprs+SPgdfire3, stt+GSgdchase1, 0},
-	[GSgddie1] {nil, yelp, 15, sprs+SPgddie1, stt+GSgddie2, 0},
-	[GSgddie2] {nil, nil, 15, sprs+SPgddie2, stt+GSgddie3, 0},
-	[GSgddie3] {nil, nil, 15, sprs+SPgddie3, stt+GSgddie4, 0},
-	[GSgddie4] {nil, nil, 0, sprs+SPgddead, stt+GSgddie4, 0},
-	[GSss] {uwait, nil, 0, sprs+SPss, stt+GSss, 1},
-	[GSsswalk1] {uwalk, nil, 20, sprs+SPsswalk1, stt+GSsswalk2, 1},
-	[GSsswalk2] {nil, nil, 5, sprs+SPsswalk1, stt+GSsswalk3, 1},
-	[GSsswalk3] {uwalk, nil, 15, sprs+SPsswalk2, stt+GSsswalk4, 1},
-	[GSsswalk4] {uwalk, nil, 20, sprs+SPsswalk3, stt+GSsswalk5, 1},
-	[GSsswalk5] {nil, nil, 5, sprs+SPsswalk3, stt+GSsswalk6, 1},
-	[GSsswalk6] {uwalk, nil, 15, sprs+SPsswalk4, stt+GSsswalk1, 1},
-	[GSsspain1] {nil, nil, 10, sprs+SPsspain1, stt+GSsschase1, 2},
-	[GSsspain2] {nil, nil, 10, sprs+SPsspain2, stt+GSsschase1, 2},
-	[GSsschase1] {uchase, nil, 10, sprs+SPsswalk1, stt+GSsschase2, 1},
-	[GSsschase2] {nil, nil, 3, sprs+SPsswalk1, stt+GSsschase3, 1},
-	[GSsschase3] {uchase, nil, 8, sprs+SPsswalk2, stt+GSsschase4, 1},
-	[GSsschase4] {uchase, nil, 10, sprs+SPsswalk3, stt+GSsschase5, 1},
-	[GSsschase5] {nil, nil, 3, sprs+SPsswalk3, stt+GSsschase6, 1},
-	[GSsschase6] {uchase, nil, 8, sprs+SPsswalk4, stt+GSsschase1, 1},
-	[GSssfire1] {nil, nil, 20, sprs+SPssfire1, stt+GSssfire2, 0},
-	[GSssfire2] {nil, fire, 20, sprs+SPssfire2, stt+GSssfire3, 0},
-	[GSssfire3] {nil, nil, 10, sprs+SPssfire3, stt+GSssfire4, 0},
-	[GSssfire4] {nil, fire, 10, sprs+SPssfire2, stt+GSssfire5, 0},
-	[GSssfire5] {nil, nil, 10, sprs+SPssfire3, stt+GSssfire6, 0},
-	[GSssfire6] {nil, fire, 10, sprs+SPssfire2, stt+GSssfire7, 0},
-	[GSssfire7] {nil, nil, 10, sprs+SPssfire3, stt+GSssfire8, 0},
-	[GSssfire8] {nil, fire, 10, sprs+SPssfire2, stt+GSssfire9, 0},
-	[GSssfire9] {nil, nil, 10, sprs+SPssfire3, stt+GSsschase1, 0},
-	[GSssdie1] {nil, yelp, 15, sprs+SPssdie1, stt+GSssdie2, 0},
-	[GSssdie2] {nil, nil, 15, sprs+SPssdie2, stt+GSssdie3, 0},
-	[GSssdie3] {nil, nil, 15, sprs+SPssdie3, stt+GSssdie4, 0},
-	[GSssdie4] {nil, nil, 0, sprs+SPssdead, stt+GSssdie4, 0},
-	[GSofc] {uwait, nil, 0, sprs+SPofc, stt+GSofc, 1},
-	[GSofcwalk1] {uwalk, nil, 20, sprs+SPofcwalk1, stt+GSofcwalk2, 1},
-	[GSofcwalk2] {nil, nil, 5, sprs+SPofcwalk1, stt+GSofcwalk3, 1},
-	[GSofcwalk3] {uwalk, nil, 15, sprs+SPofcwalk2, stt+GSofcwalk4, 1},
-	[GSofcwalk4] {uwalk, nil, 20, sprs+SPofcwalk3, stt+GSofcwalk5, 1},
-	[GSofcwalk5] {nil, nil, 5, sprs+SPofcwalk3, stt+GSofcwalk6, 1},
-	[GSofcwalk6] {uwalk, nil, 15, sprs+SPofcwalk4, stt+GSofcwalk1, 1},
-	[GSofcpain1] {nil, nil, 10, sprs+SPofcpain1, stt+GSofcchase1, 2},
-	[GSofcpain2] {nil, nil, 10, sprs+SPofcpain2, stt+GSofcchase1, 2},
-	[GSofcchase1] {uchase, nil, 10, sprs+SPofcwalk1, stt+GSofcchase2, 1},
-	[GSofcchase2] {nil, nil, 3, sprs+SPofcwalk1, stt+GSofcchase3, 1},
-	[GSofcchase3] {uchase, nil, 8, sprs+SPofcwalk2, stt+GSofcchase4, 1},
-	[GSofcchase4] {uchase, nil, 10, sprs+SPofcwalk3, stt+GSofcchase5, 1},
-	[GSofcchase5] {nil, nil, 3, sprs+SPofcwalk3, stt+GSofcchase6, 1},
-	[GSofcchase6] {uchase, nil, 8, sprs+SPofcwalk4, stt+GSofcchase1, 1},
-	[GSofcfire1] {nil, nil, 6, sprs+SPofcfire1, stt+GSofcfire2, 0},
-	[GSofcfire2] {nil, fire, 20, sprs+SPofcfire2, stt+GSofcfire3, 0},
-	[GSofcfire3] {nil, nil, 10, sprs+SPofcfire3, stt+GSofcchase1, 0},
-	[GSofcdie1] {nil, yelp, 11, sprs+SPofcdie1, stt+GSofcdie2, 0},
-	[GSofcdie2] {nil, nil, 11, sprs+SPofcdie2, stt+GSofcdie3, 0},
-	[GSofcdie3] {nil, nil, 11, sprs+SPofcdie3, stt+GSofcdie4, 0},
-	[GSofcdie4] {nil, nil, 11, sprs+SPofcdie4, stt+GSofcdie5, 0},
-	[GSofcdie5] {nil, nil, 0, sprs+SPofcdead, stt+GSofcdie5, 0},
-	[GSmut] {uwait, nil, 0, sprs+SPmut, stt+GSmut, 1},
-	[GSmutwalk1] {uwalk, nil, 20, sprs+SPmutwalk1, stt+GSmutwalk2, 1},
-	[GSmutwalk2] {nil, nil, 5, sprs+SPmutwalk1, stt+GSmutwalk3, 1},
-	[GSmutwalk3] {uwalk, nil, 15, sprs+SPmutwalk2, stt+GSmutwalk4, 1},
-	[GSmutwalk4] {uwalk, nil, 20, sprs+SPmutwalk3, stt+GSmutwalk5, 1},
-	[GSmutwalk5] {nil, nil, 5, sprs+SPmutwalk3, stt+GSmutwalk6, 1},
-	[GSmutwalk6] {uwalk, nil, 15, sprs+SPmutwalk4, stt+GSmutwalk1, 1},
-	[GSmutpain1] {nil, nil, 10, sprs+SPmutpain1, stt+GSmutchase1, 2},
-	[GSmutpain2] {nil, nil, 10, sprs+SPmutpain2, stt+GSmutchase1, 2},
-	[GSmutchase1] {uchase, nil, 10, sprs+SPmutwalk1, stt+GSmutchase2, 1},
-	[GSmutchase2] {nil, nil, 3, sprs+SPmutwalk1, stt+GSmutchase3, 1},
-	[GSmutchase3] {uchase, nil, 8, sprs+SPmutwalk2, stt+GSmutchase4, 1},
-	[GSmutchase4] {uchase, nil, 10, sprs+SPmutwalk3, stt+GSmutchase5, 1},
-	[GSmutchase5] {nil, nil, 3, sprs+SPmutwalk3, stt+GSmutchase6, 1},
-	[GSmutchase6] {uchase, nil, 8, sprs+SPmutwalk4, stt+GSmutchase1, 1},
-	[GSmutfire1] {nil, fire, 6, sprs+SPmutfire1, stt+GSmutfire2, 0},
-	[GSmutfire2] {nil, nil, 20, sprs+SPmutfire2, stt+GSmutfire3, 0},
-	[GSmutfire3] {nil, fire, 10, sprs+SPmutfire3, stt+GSmutfire4, 0},
-	[GSmutfire4] {nil, nil, 20, sprs+SPmutfire4, stt+GSmutchase1, 0},
-	[GSmutdie1] {nil, yelp, 7, sprs+SPmutdie1, stt+GSmutdie2, 0},
-	[GSmutdie2] {nil, nil, 7, sprs+SPmutdie2, stt+GSmutdie3, 0},
-	[GSmutdie3] {nil, nil, 7, sprs+SPmutdie3, stt+GSmutdie4, 0},
-	[GSmutdie4] {nil, nil, 7, sprs+SPmutdie4, stt+GSmutdie5, 0},
-	[GSmutdie5] {nil, nil, 0, sprs+SPmutdead, stt+GSmutdie5, 0},
-	[GSdogwalk1] {uwalk, nil, 20, sprs+SPdogwalk1, stt+GSdogwalk2, 1},
-	[GSdogwalk2] {nil, nil, 5, sprs+SPdogwalk1, stt+GSdogwalk3, 1},
-	[GSdogwalk3] {uwalk, nil, 15, sprs+SPdogwalk2, stt+GSdogwalk4, 1},
-	[GSdogwalk4] {uwalk, nil, 20, sprs+SPdogwalk3, stt+GSdogwalk5, 1},
-	[GSdogwalk5] {nil, nil, 5, sprs+SPdogwalk3, stt+GSdogwalk6, 1},
-	[GSdogwalk6] {uwalk, nil, 15, sprs+SPdogwalk4, stt+GSdogwalk1, 1},
-	[GSdogchase1] {udogchase, nil, 10, sprs+SPdogwalk1, stt+GSdogchase2, 1},
-	[GSdogchase2] {nil, nil, 3, sprs+SPdogwalk1, stt+GSdogchase3, 1},
-	[GSdogchase3] {udogchase, nil, 8, sprs+SPdogwalk2, stt+GSdogchase4, 1},
-	[GSdogchase4] {udogchase, nil, 10, sprs+SPdogwalk3, stt+GSdogchase5, 1},
-	[GSdogchase5] {nil, nil, 3, sprs+SPdogwalk3, stt+GSdogchase6, 1},
-	[GSdogchase6] {udogchase, nil, 8, sprs+SPdogwalk4, stt+GSdogchase1, 1},
-	[GSdogfire1] {nil, nil, 10, sprs+SPdogfire1, stt+GSdogfire2, 0},
-	[GSdogfire2] {nil, bite, 10, sprs+SPdogfire2, stt+GSdogfire3, 0},
-	[GSdogfire3] {nil, nil, 10, sprs+SPdogfire3, stt+GSdogfire4, 0},
-	[GSdogfire4] {nil, nil, 10, sprs+SPdogfire1, stt+GSdogfire5, 0},
-	[GSdogfire5] {nil, nil, 10, sprs+SPdogwalk1, stt+GSdogchase1, 0},
-	[GSdogdie1] {nil, yelp, 15, sprs+SPdogdie1, stt+GSdogdie2, 0},
-	[GSdogdie2] {nil, nil, 15, sprs+SPdogdie2, stt+GSdogdie3, 0},
-	[GSdogdie3] {nil, nil, 15, sprs+SPdogdie3, stt+GSdogdie4, 0},
-	[GSdogdie4] {nil, nil, 15, sprs+SPdogdead, stt+GSdogdie4, 0},
-	[GShans] {uwait, nil, 0, sprs+SPhanswalk1, stt+GShans, 0},
-	[GShanschase1] {uchase, nil, 10, sprs+SPhanswalk1, stt+GShanschase2, 0},
-	[GShanschase2] {nil, nil, 3, sprs+SPhanswalk1, stt+GShanschase3, 0},
-	[GShanschase3] {uchase, nil, 8, sprs+SPhanswalk2, stt+GShanschase4, 0},
-	[GShanschase4] {uchase, nil, 10, sprs+SPhanswalk3, stt+GShanschase5, 0},
-	[GShanschase5] {nil, nil, 3, sprs+SPhanswalk3, stt+GShanschase6, 0},
-	[GShanschase6] {uchase, nil, 8, sprs+SPhanswalk4, stt+GShanschase1, 0},
-	[GShansfire1] {nil, nil, 30, sprs+SPhansfire1, stt+GShansfire2, 0},
-	[GShansfire2] {nil, fire, 10, sprs+SPhansfire2, stt+GShansfire3, 0},
-	[GShansfire3] {nil, fire, 10, sprs+SPhansfire3, stt+GShansfire4, 0},
-	[GShansfire4] {nil, fire, 10, sprs+SPhansfire2, stt+GShansfire5, 0},
-	[GShansfire5] {nil, fire, 10, sprs+SPhansfire3, stt+GShansfire6, 0},
-	[GShansfire6] {nil, fire, 10, sprs+SPhansfire2, stt+GShansfire7, 0},
-	[GShansfire7] {nil, fire, 10, sprs+SPhansfire3, stt+GShansfire8, 0},
-	[GShansfire8] {nil, nil, 10, sprs+SPhansfire1, stt+GShanschase1, 0},
-	[GShansdie1] {nil, yelp, 15, sprs+SPhansdie1, stt+GShansdie2, 0},
-	[GShansdie2] {nil, nil, 15, sprs+SPhansdie2, stt+GShansdie3, 0},
-	[GShansdie3] {nil, nil, 15, sprs+SPhansdie3, stt+GShansdie4, 0},
-	[GShansdie4] {nil, nil, 0, sprs+SPhansdead, stt+GShansdie4, 0},
-	[GSschb] {uwait, nil, 0, sprs+SPschbwalk1, stt+GSschb, 0},
-	[GSschbchase1] {uboss, nil, 10, sprs+SPschbwalk1, stt+GSschbchase2, 0},
-	[GSschbchase2] {nil, nil, 3, sprs+SPschbwalk1, stt+GSschbchase3, 0},
-	[GSschbchase3] {uboss, nil, 8, sprs+SPschbwalk2, stt+GSschbchase4, 0},
-	[GSschbchase4] {uboss, nil, 10, sprs+SPschbwalk3, stt+GSschbchase5, 0},
-	[GSschbchase5] {nil, nil, 3, sprs+SPschbwalk3, stt+GSschbchase6, 0},
-	[GSschbchase6] {uboss, nil, 8, sprs+SPschbwalk4, stt+GSschbchase1, 0},
-	[GSschbfire1] {nil, nil, 30, sprs+SPschbfire1, stt+GSschbfire2, 0},
-	[GSschbfire2] {nil, launch, 10, sprs+SPschbfire2, stt+GSschbchase1, 0},
-	[GSschbcam] {nil, nil, 1, sprs+SPschbwalk1, stt+GSschbdie1, 0},
-	[GSschbdie1] {nil, yelp, 10, sprs+SPschbwalk1, stt+GSschbdie2, 0},
-	[GSschbdie2] {nil, nil, 10, sprs+SPschbwalk1, stt+GSschbdie3, 0},
-	[GSschbdie3] {nil, nil, 10, sprs+SPschbdie1, stt+GSschbdie4, 0},
-	[GSschbdie4] {nil, nil, 10, sprs+SPschbdie2, stt+GSschbdie5, 0},
-	[GSschbdie5] {nil, nil, 10, sprs+SPschbdie3, stt+GSschbdie6, 0},
-	[GSschbdie6] {nil, cam, 20, sprs+SPschbdead, stt+GSschbdie6, 0},
-	[GSgretel] {uwait, nil, 0, sprs+SPgretelwalk1, stt+GSgretel, 0},
-	[GSgretelchase1] {uchase, nil, 10, sprs+SPgretelwalk1, stt+GSgretelchase2, 0},
-	[GSgretelchase2] {nil, nil, 3, sprs+SPgretelwalk1, stt+GSgretelchase3, 0},
-	[GSgretelchase3] {uchase, nil, 8, sprs+SPgretelwalk2, stt+GSgretelchase4, 0},
-	[GSgretelchase4] {uchase, nil, 10, sprs+SPgretelwalk3, stt+GSgretelchase5, 0},
-	[GSgretelchase5] {nil, nil, 3, sprs+SPgretelwalk3, stt+GSgretelchase6, 0},
-	[GSgretelchase6] {uchase, nil, 8, sprs+SPgretelwalk4, stt+GSgretelchase1, 0},
-	[GSgretelfire1] {nil, nil, 30, sprs+SPgretelfire1, stt+GSgretelfire2, 0},
-	[GSgretelfire2] {nil, fire, 10, sprs+SPgretelfire2, stt+GSgretelfire3, 0},
-	[GSgretelfire3] {nil, fire, 10, sprs+SPgretelfire3, stt+GSgretelfire4, 0},
-	[GSgretelfire4] {nil, fire, 10, sprs+SPgretelfire2, stt+GSgretelfire5, 0},
-	[GSgretelfire5] {nil, fire, 10, sprs+SPgretelfire3, stt+GSgretelfire6, 0},
-	[GSgretelfire6] {nil, fire, 10, sprs+SPgretelfire2, stt+GSgretelfire7, 0},
-	[GSgretelfire7] {nil, fire, 10, sprs+SPgretelfire3, stt+GSgretelfire8, 0},
-	[GSgretelfire8] {nil, nil, 10, sprs+SPgretelfire1, stt+GSgretelchase1, 0},
-	[GSgreteldie1] {nil, yelp, 15, sprs+SPgreteldie1, stt+GSgreteldie2, 0},
-	[GSgreteldie2] {nil, nil, 15, sprs+SPgreteldie2, stt+GSgreteldie3, 0},
-	[GSgreteldie3] {nil, nil, 15, sprs+SPgreteldie3, stt+GSgreteldie4, 0},
-	[GSgreteldie4] {nil, nil, 0, sprs+SPgreteldead, stt+GSgreteldie4, 0},
-	[GSotto] {uwait, nil, 0, sprs+SPottowalk1, stt+GSotto, 0},
-	[GSottochase1] {uboss, nil, 10, sprs+SPottowalk1, stt+GSottochase2, 0},
-	[GSottochase2] {nil, nil, 3, sprs+SPottowalk1, stt+GSottochase3, 0},
-	[GSottochase3] {uboss, nil, 8, sprs+SPottowalk2, stt+GSottochase4, 0},
-	[GSottochase4] {uboss, nil, 10, sprs+SPottowalk3, stt+GSottochase5, 0},
-	[GSottochase5] {nil, nil, 3, sprs+SPottowalk3, stt+GSottochase6, 0},
-	[GSottochase6] {uboss, nil, 8, sprs+SPottowalk4, stt+GSottochase1, 0},
-	[GSottofire1] {nil, nil, 30, sprs+SPottofire1, stt+GSottofire2, 0},
-	[GSottofire2] {nil, launch, 10, sprs+SPottofire2, stt+GSottochase1, 0},
-	[GSottocam] {nil, nil, 1, sprs+SPottowalk1, stt+GSottodie1, 0},
-	[GSottodie1] {nil, yelp, 1, sprs+SPottowalk1, stt+GSottodie2, 0},
-	[GSottodie2] {nil, nil, 10, sprs+SPottowalk1, stt+GSottodie3, 0},
-	[GSottodie3] {nil, nil, 10, sprs+SPottodie1, stt+GSottodie4, 0},
-	[GSottodie4] {nil, nil, 10, sprs+SPottodie2, stt+GSottodie5, 0},
-	[GSottodie5] {nil, nil, 10, sprs+SPottodie3, stt+GSottodie6, 0},
-	[GSottodie6] {nil, cam, 20, sprs+SPottodead, stt+GSottodie6, 0},
-	[GSfett] {uwait, nil, 0, sprs+SPfettwalk1, stt+GSfett, 0},
-	[GSfettchase1] {uboss, nil, 10, sprs+SPfettwalk1, stt+GSfettchase2, 0},
-	[GSfettchase2] {nil, nil, 3, sprs+SPfettwalk1, stt+GSfettchase3, 0},
-	[GSfettchase3] {uboss, nil, 8, sprs+SPfettwalk2, stt+GSfettchase4, 0},
-	[GSfettchase4] {uboss, nil, 10, sprs+SPfettwalk3, stt+GSfettchase5, 0},
-	[GSfettchase5] {nil, nil, 3, sprs+SPfettwalk3, stt+GSfettchase6, 0},
-	[GSfettchase6] {uboss, nil, 8, sprs+SPfettwalk4, stt+GSfettchase1, 0},
-	[GSfettfire1] {nil, nil, 30, sprs+SPfettfire1, stt+GSfettfire2, 0},
-	[GSfettfire2] {nil, launch, 10, sprs+SPfettfire2, stt+GSfettfire3, 0},
-	[GSfettfire3] {nil, fire, 10, sprs+SPfettfire3, stt+GSfettfire4, 0},
-	[GSfettfire4] {nil, fire, 10, sprs+SPfettfire4, stt+GSfettfire5, 0},
-	[GSfettfire5] {nil, fire, 10, sprs+SPfettfire3, stt+GSfettfire6, 0},
-	[GSfettfire6] {nil, fire, 10, sprs+SPfettfire4, stt+GSfettchase1, 0},
-	[GSfettcam] {nil, nil, 1, sprs+SPfettwalk1, stt+GSfettdie1, 0},
-	[GSfettdie1] {nil, yelp, 1, sprs+SPfettwalk1, stt+GSfettdie2, 0},
-	[GSfettdie2] {nil, nil, 10, sprs+SPfettwalk1, stt+GSfettdie3, 0},
-	[GSfettdie3] {nil, nil, 10, sprs+SPfettdie1, stt+GSfettdie4, 0},
-	[GSfettdie4] {nil, nil, 10, sprs+SPfettdie2, stt+GSfettdie5, 0},
-	[GSfettdie5] {nil, nil, 10, sprs+SPfettdie3, stt+GSfettdie6, 0},
-	[GSfettdie6] {nil, cam, 20, sprs+SPfettdead, stt+GSfettdie6, 0},
-	[GSfake] {uwait, nil, 0, sprs+SPfakewalk1, stt+GSfake, 0},
-	[GSfakechase1] {ufake, nil, 10, sprs+SPfakewalk1, stt+GSfakechase2, 0},
-	[GSfakechase2] {nil, nil, 3, sprs+SPfakewalk1, stt+GSfakechase3, 0},
-	[GSfakechase3] {ufake, nil, 8, sprs+SPfakewalk2, stt+GSfakechase4, 0},
-	[GSfakechase4] {ufake, nil, 10, sprs+SPfakewalk3, stt+GSfakechase5, 0},
-	[GSfakechase5] {nil, nil, 3, sprs+SPfakewalk3, stt+GSfakechase6, 0},
-	[GSfakechase6] {ufake, nil, 8, sprs+SPfakewalk4, stt+GSfakechase1, 0},
-	[GSfakefire1] {nil, launch, 8, sprs+SPfakefire, stt+GSfakefire2, 0},
-	[GSfakefire2] {nil, launch, 8, sprs+SPfakefire, stt+GSfakefire3, 0},
-	[GSfakefire3] {nil, launch, 8, sprs+SPfakefire, stt+GSfakefire4, 0},
-	[GSfakefire4] {nil, launch, 8, sprs+SPfakefire, stt+GSfakefire5, 0},
-	[GSfakefire5] {nil, launch, 8, sprs+SPfakefire, stt+GSfakefire6, 0},
-	[GSfakefire6] {nil, launch, 8, sprs+SPfakefire, stt+GSfakefire7, 0},
-	[GSfakefire7] {nil, launch, 8, sprs+SPfakefire, stt+GSfakefire8, 0},
-	[GSfakefire8] {nil, launch, 8, sprs+SPfakefire, stt+GSfakefire9, 0},
-	[GSfakefire9] {nil, nil, 8, sprs+SPfakefire, stt+GSfakechase1, 0},
-	[GSfakedie1] {nil, yelp, 10, sprs+SPfakedie1, stt+GSfakedie2, 0},
-	[GSfakedie2] {nil, nil, 10, sprs+SPfakedie2, stt+GSfakedie3, 0},
-	[GSfakedie3] {nil, nil, 10, sprs+SPfakedie3, stt+GSfakedie4, 0},
-	[GSfakedie4] {nil, nil, 10, sprs+SPfakedie4, stt+GSfakedie5, 0},
-	[GSfakedie5] {nil, nil, 10, sprs+SPfakedie5, stt+GSfakedie6, 0},
-	[GSfakedie6] {nil, nil, 0, sprs+SPfakedead, stt+GSfakedie6, 0},
-	[GSmech] {uwait, nil, 0, sprs+SPmechwalk1, stt+GSmech, 0},
-	[GSmechchase1] {uchase, mechsfx, 10, sprs+SPmechwalk1, stt+GSmechchase2, 0},
-	[GSmechchase2] {nil, nil, 6, sprs+SPmechwalk1, stt+GSmechchase3, 0},
-	[GSmechchase3] {uchase, nil, 8, sprs+SPmechwalk2, stt+GSmechchase4, 0},
-	[GSmechchase4] {uchase, mechsfx, 10, sprs+SPmechwalk3, stt+GSmechchase5, 0},
-	[GSmechchase5] {nil, nil, 6, sprs+SPmechwalk3, stt+GSmechchase6, 0},
-	[GSmechchase6] {uchase, nil, 8, sprs+SPmechwalk4, stt+GSmechchase1, 0},
-	[GSmechfire1] {nil, nil, 30, sprs+SPmechfire1, stt+GSmechfire2, 0},
-	[GSmechfire2] {nil, fire, 10, sprs+SPmechfire2, stt+GSmechfire3, 0},
-	[GSmechfire3] {nil, fire, 10, sprs+SPmechfire3, stt+GSmechfire4, 0},
-	[GSmechfire4] {nil, fire, 10, sprs+SPmechfire2, stt+GSmechfire5, 0},
-	[GSmechfire5] {nil, fire, 10, sprs+SPmechfire3, stt+GSmechfire6, 0},
-	[GSmechfire6] {nil, fire, 10, sprs+SPmechfire2, stt+GSmechchase1, 0},
-	[GSmechdie1] {nil, yelp, 10, sprs+SPmechdie1, stt+GSmechdie2, 0},
-	[GSmechdie2] {nil, nil, 10, sprs+SPmechdie2, stt+GSmechdie3, 0},
-	[GSmechdie3] {nil, mechblow, 10, sprs+SPmechdie3, stt+GSmechdie4, 0},
-	[GSmechdie4] {nil, nil, 0, sprs+SPmechdead, stt+GSmechdie4, 0},
-	[GShitlerchase1] {uchase, nil, 6, sprs+SPhitlerwalk1, stt+GShitlerchase2, 0},
-	[GShitlerchase2] {nil, nil, 4, sprs+SPhitlerwalk1, stt+GShitlerchase3, 0},
-	[GShitlerchase3] {uchase, nil, 2, sprs+SPhitlerwalk2, stt+GShitlerchase4, 0},
-	[GShitlerchase4] {uchase, nil, 6, sprs+SPhitlerwalk3, stt+GShitlerchase5, 0},
-	[GShitlerchase5] {nil, nil, 4, sprs+SPhitlerwalk3, stt+GShitlerchase6, 0},
-	[GShitlerchase6] {uchase, nil, 2, sprs+SPhitlerwalk4, stt+GShitlerchase1, 0},
-	[GShitlerfire1] {nil, nil, 30, sprs+SPhitlerfire1, stt+GShitlerfire2, 0},
-	[GShitlerfire2] {nil, fire, 10, sprs+SPhitlerfire2, stt+GShitlerfire3, 0},
-	[GShitlerfire3] {nil, fire, 10, sprs+SPhitlerfire3, stt+GShitlerfire4, 0},
-	[GShitlerfire4] {nil, fire, 10, sprs+SPhitlerfire2, stt+GShitlerfire5, 0},
-	[GShitlerfire5] {nil, fire, 10, sprs+SPhitlerfire3, stt+GShitlerfire6, 0},
-	[GShitlerfire6] {nil, fire, 10, sprs+SPhitlerfire2, stt+GShitlerchase1, 0},
-	[GShitlercam] {nil, nil, 10, sprs+SPhitlerwalk1, stt+GShitlerdie1, 0},
-	[GShitlerdie1] {nil, yelp, 1, sprs+SPhitlerwalk1, stt+GShitlerdie2, 0},
-	[GShitlerdie2] {nil, nil, 10, sprs+SPhitlerwalk1, stt+GShitlerdie3, 0},
-	[GShitlerdie3] {nil, slurp, 10, sprs+SPhitlerdie1, stt+GShitlerdie4, 0},
-	[GShitlerdie4] {nil, nil, 10, sprs+SPhitlerdie2, stt+GShitlerdie5, 0},
-	[GShitlerdie5] {nil, nil, 10, sprs+SPhitlerdie3, stt+GShitlerdie6, 0},
-	[GShitlerdie6] {nil, nil, 10, sprs+SPhitlerdie4, stt+GShitlerdie7, 0},
-	[GShitlerdie7] {nil, nil, 10, sprs+SPhitlerdie5, stt+GShitlerdie8, 0},
-	[GShitlerdie8] {nil, nil, 10, sprs+SPhitlerdie6, stt+GShitlerdie9, 0},
-	[GShitlerdie9] {nil, nil, 10, sprs+SPhitlerdie7, stt+GShitlerdie10, 0},
-	[GShitlerdie10] {nil, cam, 20, sprs+SPhitlerdead, stt+GShitlerdie10, 0},
-	[GSgh1chase1] {ughost, nil, 10, sprs+SPgh1walk1, stt+GSgh1chase2, 0},
-	[GSgh2chase1] {ughost, nil, 10, sprs+SPgh3walk1, stt+GSgh2chase2, 0},
-	[GSgh3chase1] {ughost, nil, 10, sprs+SPgh2walk1, stt+GSgh3chase2, 0},
-	[GSgh4chase1] {ughost, nil, 10, sprs+SPgh2walk1, stt+GSgh4chase2, 0},
-	[GSgh1chase2] {ughost, nil, 10, sprs+SPgh1walk2, stt+GSgh1chase1, 0},
-	[GSgh2chase2] {ughost, nil, 10, sprs+SPgh3walk2, stt+GSgh2chase1, 0},
-	[GSgh3chase2] {ughost, nil, 10, sprs+SPgh2walk2, stt+GSgh3chase1, 0},
-	[GSgh4chase2] {ughost, nil, 10, sprs+SPgh2walk2, stt+GSgh4chase1, 0},
-	[GStrans] {uwait, nil, 0, sprs+SPtranswalk1, stt+GStrans, 0},
-	[GStranschase1] {uchase, nil, 10, sprs+SPtranswalk1, stt+GStranschase2, 0},
-	[GStranschase2] {nil, nil, 3, sprs+SPtranswalk1, stt+GStranschase3, 0},
-	[GStranschase3] {uchase, nil, 8, sprs+SPtranswalk2, stt+GStranschase4, 0},
-	[GStranschase4] {uchase, nil, 10, sprs+SPtranswalk3, stt+GStranschase5, 0},
-	[GStranschase5] {nil, nil, 3, sprs+SPtranswalk3, stt+GStranschase6, 0},
-	[GStranschase6] {uchase, nil, 8, sprs+SPtranswalk4, stt+GStranschase1, 0},
-	[GStransfire1] {nil, nil, 30, sprs+SPtransfire1, stt+GStransfire2, 0},
-	[GStransfire2] {nil, fire, 10, sprs+SPtransfire2, stt+GStransfire3, 0},
-	[GStransfire3] {nil, fire, 10, sprs+SPtransfire3, stt+GStransfire4, 0},
-	[GStransfire4] {nil, fire, 10, sprs+SPtransfire2, stt+GStransfire5, 0},
-	[GStransfire5] {nil, fire, 10, sprs+SPtransfire3, stt+GStransfire6, 0},
-	[GStransfire6] {nil, fire, 10, sprs+SPtransfire2, stt+GStransfire7, 0},
-	[GStransfire7] {nil, fire, 10, sprs+SPtransfire3, stt+GStransfire8, 0},
-	[GStransfire8] {nil, nil, 10, sprs+SPtransfire1, stt+GStranschase1, 0},
-	[GStransdie1] {nil, yelp, 1, sprs+SPtranswalk1, stt+GStransdie2, 0},
-	[GStransdie2] {nil, nil, 1, sprs+SPtranswalk1, stt+GStransdie3, 0},
-	[GStransdie3] {nil, nil, 15, sprs+SPtransdie1, stt+GStransdie4, 0},
-	[GStransdie4] {nil, nil, 15, sprs+SPtransdie2, stt+GStransdie5, 0},
-	[GStransdie5] {nil, nil, 15, sprs+SPtransdie3, stt+GStransdie6, 0},
-	[GStransdie6] {nil, nil, 0, sprs+SPtransdead, stt+GStransdie6, 0},
-	[GSwilh] {uwait, nil, 0, sprs+SPwilhwalk1, stt+GSwilh, 0},
-	[GSwilhchase1] {uboss, nil, 10, sprs+SPwilhwalk1, stt+GSwilhchase2, 0},
-	[GSwilhchase2] {nil, nil, 3, sprs+SPwilhwalk1, stt+GSwilhchase3, 0},
-	[GSwilhchase3] {uboss, nil, 8, sprs+SPwilhwalk2, stt+GSwilhchase4, 0},
-	[GSwilhchase4] {uboss, nil, 10, sprs+SPwilhwalk3, stt+GSwilhchase5, 0},
-	[GSwilhchase5] {nil, nil, 3, sprs+SPwilhwalk3, stt+GSwilhchase6, 0},
-	[GSwilhchase6] {uboss, nil, 8, sprs+SPwilhwalk4, stt+GSwilhchase1, 0},
-	[GSwilhfire1] {nil, nil, 30, sprs+SPwilhfire1, stt+GSwilhfire2, 0},
-	[GSwilhfire2] {nil, launch, 10, sprs+SPwilhfire2, stt+GSwilhfire3, 0},
-	[GSwilhfire3] {nil, fire, 10, sprs+SPwilhfire3, stt+GSwilhfire4, 0},
-	[GSwilhfire4] {nil, fire, 10, sprs+SPwilhfire4, stt+GSwilhfire5, 0},
-	[GSwilhfire5] {nil, fire, 10, sprs+SPwilhfire3, stt+GSwilhfire6, 0},
-	[GSwilhfire6] {nil, fire, 10, sprs+SPwilhfire4, stt+GSwilhchase1, 0},
-	[GSwilhdie1] {nil, yelp, 1, sprs+SPwilhwalk1, stt+GSwilhdie2, 0},
-	[GSwilhdie2] {nil, nil, 10, sprs+SPwilhwalk1, stt+GSwilhdie3, 0},
-	[GSwilhdie3] {nil, nil, 10, sprs+SPwilhdie1, stt+GSwilhdie4, 0},
-	[GSwilhdie4] {nil, nil, 10, sprs+SPwilhdie2, stt+GSwilhdie5, 0},
-	[GSwilhdie5] {nil, nil, 10, sprs+SPwilhdie3, stt+GSwilhdie6, 0},
-	[GSwilhdie6] {nil, nil, 20, sprs+SPwilhdead, stt+GSwilhdie6, 0},
-	[GSuber] {uwait, nil, 0, sprs+SPuberwalk1, stt+GSuber, 0},
-	[GSuberchase1] {uchase, nil, 10, sprs+SPuberwalk1, stt+GSuberchase2, 0},
-	[GSuberchase2] {nil, nil, 3, sprs+SPuberwalk1, stt+GSuberchase3, 0},
-	[GSuberchase3] {uchase, nil, 8, sprs+SPuberwalk2, stt+GSuberchase4, 0},
-	[GSuberchase4] {uchase, nil, 10, sprs+SPuberwalk3, stt+GSuberchase5, 0},
-	[GSuberchase5] {nil, nil, 3, sprs+SPuberwalk3, stt+GSuberchase6, 0},
-	[GSuberchase6] {uchase, nil, 8, sprs+SPuberwalk4, stt+GSuberchase1, 0},
-	[GSuberfire1] {nil, nil, 30, sprs+SPuberfire1, stt+GSuberfire2, 0},
-	[GSuberfire2] {nil, uberfire, 12, sprs+SPuberfire2, stt+GSuberfire3, 0},
-	[GSuberfire3] {nil, uberfire, 12, sprs+SPuberfire3, stt+GSuberfire4, 0},
-	[GSuberfire4] {nil, uberfire, 12, sprs+SPuberfire4, stt+GSuberfire5, 0},
-	[GSuberfire5] {nil, uberfire, 12, sprs+SPuberfire3, stt+GSuberfire6, 0},
-	[GSuberfire6] {nil, uberfire, 12, sprs+SPuberfire2, stt+GSuberfire7, 0},
-	[GSuberfire7] {nil, nil, 12, sprs+SPuberfire1, stt+GSuberchase1, 0},
-	[GSuberdie1] {nil, yelp, 1, sprs+SPuberwalk1, stt+GSuberdie2, 0},
-	[GSuberdie2] {nil, nil, 1, sprs+SPuberwalk1, stt+GSuberdie3, 0},
-	[GSuberdie3] {nil, nil, 15, sprs+SPuberdie1, stt+GSuberdie4, 0},
-	[GSuberdie4] {nil, nil, 15, sprs+SPuberdie2, stt+GSuberdie5, 0},
-	[GSuberdie5] {nil, nil, 15, sprs+SPuberdie3, stt+GSuberdie6, 0},
-	[GSuberdie6] {nil, nil, 15, sprs+SPuberdie4, stt+GSuberdie7, 0},
-	[GSuberdie7] {nil, nil, 0, sprs+SPuberdead, stt+GSuberdie7, 0},
-	[GSknight] {uwait, nil, 0, sprs+SPknightwalk1, stt+GSknight, 0},
-	[GSknightchase1] {uboss, nil, 10, sprs+SPknightwalk1, stt+GSknightchase2, 0},
-	[GSknightchase2] {nil, nil, 3, sprs+SPknightwalk1, stt+GSknightchase3, 0},
-	[GSknightchase3] {uboss, nil, 8, sprs+SPknightwalk2, stt+GSknightchase4, 0},
-	[GSknightchase4] {uboss, nil, 10, sprs+SPknightwalk3, stt+GSknightchase5, 0},
-	[GSknightchase5] {nil, nil, 3, sprs+SPknightwalk3, stt+GSknightchase6, 0},
-	[GSknightchase6] {uboss, nil, 8, sprs+SPknightwalk4, stt+GSknightchase1, 0},
-	[GSknightfire1] {nil, nil, 30, sprs+SPknightfire1, stt+GSknightfire2, 0},
-	[GSknightfire2] {nil, launch, 10, sprs+SPknightfire2, stt+GSknightfire3, 0},
-	[GSknightfire3] {nil, fire, 10, sprs+SPknightfire4, stt+GSknightfire4, 0},
-	[GSknightfire4] {nil, launch, 10, sprs+SPknightfire3, stt+GSknightfire5, 0},
-	[GSknightfire5] {nil, fire, 10, sprs+SPknightfire4, stt+GSknightchase1, 0},
-	[GSknightdie1] {nil, yelp, 1, sprs+SPknightwalk1, stt+GSknightdie2, 0},
-	[GSknightdie2] {nil, nil, 10, sprs+SPknightwalk1, stt+GSknightdie3, 0},
-	[GSknightdie3] {nil, nil, 10, sprs+SPknightdie1, stt+GSknightdie4, 0},
-	[GSknightdie4] {nil, nil, 10, sprs+SPknightdie2, stt+GSknightdie5, 0},
-	[GSknightdie5] {nil, nil, 10, sprs+SPknightdie3, stt+GSknightdie6, 0},
-	[GSknightdie6] {nil, nil, 10, sprs+SPknightdie4, stt+GSknightdie7, 0},
-	[GSknightdie7] {nil, nil, 10, sprs+SPknightdie5, stt+GSknightdie8, 0},
-	[GSknightdie8] {nil, nil, 10, sprs+SPknightdie6, stt+GSknightdie9, 0},
-	[GSknightdie9] {nil, nil, 0, sprs+SPknightdead, stt+GSknightdie9, 0},
-	[GSspectrewait1] {uwait, nil, 10, sprs+SPspectrewalk1, stt+GSspectrewait2, 0},
-	[GSspectrewait2] {uwait, nil, 10, sprs+SPspectrewalk2, stt+GSspectrewait3, 0},
-	[GSspectrewait3] {uwait, nil, 10, sprs+SPspectrewalk3, stt+GSspectrewait4, 0},
-	[GSspectrewait4] {uwait, nil, 10, sprs+SPspectrewalk4, stt+GSspectrewait1, 0},
-	[GSspectrewake] {nil, wake, 10, sprs+SPspectreF4, stt+GSspectrewake, 0},
-	[GSspectrechase1] {ughost, nil, 10, sprs+SPspectrewalk1, stt+GSspectrechase2, 0},
-	[GSspectrechase2] {ughost, nil, 10, sprs+SPspectrewalk2, stt+GSspectrechase3, 0},
-	[GSspectrechase3] {ughost, nil, 10, sprs+SPspectrewalk3, stt+GSspectrechase4, 0},
-	[GSspectrechase4] {ughost, nil, 10, sprs+SPspectrewalk4, stt+GSspectrechase1, 0},
-	[GSspectredie1] {nil, nil, 10, sprs+SPspectreF1, stt+GSspectredie2, 0},
-	[GSspectredie2] {nil, nil, 10, sprs+SPspectreF2, stt+GSspectredie3, 0},
-	[GSspectredie3] {nil, nil, 10, sprs+SPspectreF3, stt+GSspectredie4, 0},
-	[GSspectredie4] {nil, nil, 300, sprs+SPspectreF4, stt+GSspectrewake, 0},
-	[GSangel] {uwait, nil, 0, sprs+SPangelwalk1, stt+GSangel, 0},
-	[GSangelchase1] {uboss, nil, 10, sprs+SPangelwalk1, stt+GSangelchase2, 0},
-	[GSangelchase2] {nil, nil, 3, sprs+SPangelwalk1, stt+GSangelchase3, 0},
-	[GSangelchase3] {uboss, nil, 8, sprs+SPangelwalk2, stt+GSangelchase4, 0},
-	[GSangelchase4] {uboss, nil, 10, sprs+SPangelwalk3, stt+GSangelchase5, 0},
-	[GSangelchase5] {nil, nil, 3, sprs+SPangelwalk3, stt+GSangelchase6, 0},
-	[GSangelchase6] {uboss, nil, 8, sprs+SPangelwalk4, stt+GSangelchase1, 0},
-	[GSangelfire1] {nil, prelaunch, 10, sprs+SPangelfire1, stt+GSangelfire2, 0},
-	[GSangelfire2] {nil, launch, 20, sprs+SPangelfire2, stt+GSangelfire3, 0},
-	[GSangelfire3] {nil, relaunch, 10, sprs+SPangelfire1, stt+GSangelfire2, 0},
-	[GSangeldie1] {nil, yelp, 1, sprs+SPangelwalk1, stt+GSangeldie2, 0},
-	[GSangeldie2] {nil, nil, 1, sprs+SPangelwalk1, stt+GSangeldie3, 0},
-	[GSangeldie3] {nil, slurp, 10, sprs+SPangeldie1, stt+GSangeldie4, 0},
-	[GSangeldie4] {nil, nil, 10, sprs+SPangeldie2, stt+GSangeldie5, 0},
-	[GSangeldie5] {nil, nil, 10, sprs+SPangeldie3, stt+GSangeldie6, 0},
-	[GSangeldie6] {nil, nil, 10, sprs+SPangeldie4, stt+GSangeldie7, 0},
-	[GSangeldie7] {nil, nil, 10, sprs+SPangeldie5, stt+GSangeldie8, 0},
-	[GSangeldie8] {nil, nil, 10, sprs+SPangeldie6, stt+GSangeldie9, 0},
-	[GSangeldie9] {nil, nil, 10, sprs+SPangeldie7, stt+GSangeldie10, 0},
-	[GSangeldie10] {nil, victory, 130, sprs+SPangeldead, stt+GSangeldie10, 0},
-	[GSangeltired1] {nil, tiredsfx, 40, sprs+SPangeltired1, stt+GSangeltired2, 0},
-	[GSangeltired2] {nil, nil, 40, sprs+SPangeltired2, stt+GSangeltired3, 0},
-	[GSangeltired3] {nil, tiredsfx, 40, sprs+SPangeltired1, stt+GSangeltired4, 0},
-	[GSangeltired4] {nil, nil, 40, sprs+SPangeltired2, stt+GSangeltired5, 0},
-	[GSangeltired5] {nil, tiredsfx, 40, sprs+SPangeltired1, stt+GSangeltired6, 0},
-	[GSangeltired6] {nil, nil, 40, sprs+SPangeltired2, stt+GSangeltired7, 0},
-	[GSangeltired7] {nil, tiredsfx, 40, sprs+SPangeltired1, stt+GSangelchase1, 0},
-	[GSmissile] {uprj, smoke, 3, sprs+SPmissile1, stt+GSmissile, 1},
-	[GSmsmoke1] {nil, nil, 3, sprs+SPmsmoke1, stt+GSmsmoke2, 0},
-	[GSmsmoke2] {nil, nil, 3, sprs+SPmsmoke2, stt+GSmsmoke3, 0},
-	[GSmsmoke3] {nil, nil, 3, sprs+SPmsmoke3, stt+GSmsmoke4, 0},
-	[GSmsmoke4] {nil, nil, 3, sprs+SPmsmoke4, nil, 0},
-	[GSmboom1] {nil, nil, 6, sprs+SPmboom1, stt+GSmboom2, 0},
-	[GSmboom2] {nil, nil, 6, sprs+SPmboom2, stt+GSmboom3, 0},
-	[GSmboom3] {nil, nil, 6, sprs+SPmboom3, nil, 0},
-	[GSrocket] {uprj, smoke, 3, sprs+SProcket1, stt+GSrocket, 1},
-	[GSrsmoke1] {nil, nil, 3, sprs+SPrsmoke1, stt+GSrsmoke2, 0},
-	[GSrsmoke2] {nil, nil, 3, sprs+SPrsmoke2, stt+GSrsmoke3, 0},
-	[GSrsmoke3] {nil, nil, 3, sprs+SPrsmoke3, stt+GSrsmoke4, 0},
-	[GSrsmoke4] {nil, nil, 3, sprs+SPrsmoke4, nil, 0},
-	[GSrboom1] {nil, nil, 6, sprs+SPrboom1, stt+GSrboom2, 0},
-	[GSrboom2] {nil, nil, 6, sprs+SPrboom2, stt+GSrboom3, 0},
-	[GSrboom3] {nil, nil, 6, sprs+SPrboom3, nil, 0},
-	[GSflame1] {nil, uprj, 6, sprs+SPflame1, stt+GSflame2, 0},
-	[GSflame2] {nil, uprj, 6, sprs+SPflame2, stt+GSflame1, 0},
-	[GSneedle1] {uprj, nil, 6, sprs+SPneedle1, stt+GSneedle2, 0},
-	[GSneedle2] {uprj, nil, 6, sprs+SPneedle2, stt+GSneedle3, 0},
-	[GSneedle3] {uprj, nil, 6, sprs+SPneedle3, stt+GSneedle4, 0},
-	[GSneedle4] {uprj, nil, 6, sprs+SPneedle4, stt+GSneedle1, 0},
-	[GSspark1] {uprj, nil, 6, sprs+SPspark1, stt+GSspark2, 0},
-	[GSspark2] {uprj, nil, 6, sprs+SPspark2, stt+GSspark3, 0},
-	[GSspark3] {uprj, nil, 6, sprs+SPspark3, stt+GSspark4, 0},
-	[GSspark4] {uprj, nil, 6, sprs+SPspark4, stt+GSspark1, 0}
+	[GSplr] {uplr, nil, 0, 0, nil, 0},
+	[GSplrcam] {nil, nil, 0, 0, nil, 0},
+	[GSblaz1] {urun, nil, 12, SPbjwalk1, stt+GSblaz2, 0},
+	[GSblaz2] {nil, nil, 3, SPbjwalk1, stt+GSblaz3, 0},
+	[GSblaz3] {urun, nil, 8, SPbjwalk2, stt+GSblaz4, 0},
+	[GSblaz4] {urun, nil, 12, SPbjwalk3, stt+GSblaz5, 0},
+	[GSblaz5] {nil, nil, 3, SPbjwalk3, stt+GSblaz6, 0},
+	[GSblaz6] {urun, nil, 8, SPbjwalk4, stt+GSblaz1, 0},
+	[GSjump1] {ujump, nil, 14, SPbjjump1, stt+GSjump2, 0},
+	[GSjump2] {ujump, runyell, 14, SPbjjump2, stt+GSjump3, 0},
+	[GSjump3] {ujump, nil, 14, SPbjjump3, stt+GSjump4, 0},
+	[GSjump4] {nil, victory, 300, SPbjjump4, stt+GSjump4, 0},
+	[GSgd] {uwait, nil, 0, SPgd, stt+GSgd, 1},
+	[GSgdwalk1] {uwalk, nil, 20, SPgdwalk1, stt+GSgdwalk2, 1},
+	[GSgdwalk2] {nil, nil, 5, SPgdwalk1, stt+GSgdwalk3, 1},
+	[GSgdwalk3] {uwalk, nil, 15, SPgdwalk2, stt+GSgdwalk4, 1},
+	[GSgdwalk4] {uwalk, nil, 20, SPgdwalk3, stt+GSgdwalk5, 1},
+	[GSgdwalk5] {nil, nil, 5, SPgdwalk3, stt+GSgdwalk6, 1},
+	[GSgdwalk6] {uwalk, nil, 15, SPgdwalk4, stt+GSgdwalk1, 1},
+	[GSgdpain1] {nil, nil, 10, SPgdpain1, stt+GSgdchase1, 2},
+	[GSgdpain2] {nil, nil, 10, SPgdpain2, stt+GSgdchase1, 2},
+	[GSgdchase1] {uchase, nil, 10, SPgdwalk1, stt+GSgdchase2, 1},
+	[GSgdchase2] {nil, nil, 3, SPgdwalk1, stt+GSgdchase3, 1},
+	[GSgdchase3] {uchase, nil, 8, SPgdwalk2, stt+GSgdchase4, 1},
+	[GSgdchase4] {uchase, nil, 10, SPgdwalk3, stt+GSgdchase5, 1},
+	[GSgdchase5] {nil, nil, 3, SPgdwalk3, stt+GSgdchase6, 1},
+	[GSgdchase6] {uchase, nil, 8, SPgdwalk4, stt+GSgdchase1, 1},
+	[GSgdfire1] {nil, nil, 20, SPgdfire1, stt+GSgdfire2, 0},
+	[GSgdfire2] {nil, fire, 20, SPgdfire2, stt+GSgdfire3, 0},
+	[GSgdfire3] {nil, nil, 20, SPgdfire3, stt+GSgdchase1, 0},
+	[GSgddie1] {nil, yelp, 15, SPgddie1, stt+GSgddie2, 0},
+	[GSgddie2] {nil, nil, 15, SPgddie2, stt+GSgddie3, 0},
+	[GSgddie3] {nil, nil, 15, SPgddie3, stt+GSgddie4, 0},
+	[GSgddie4] {nil, nil, 0, SPgddead, stt+GSgddie4, 0},
+	[GSss] {uwait, nil, 0, SPss, stt+GSss, 1},
+	[GSsswalk1] {uwalk, nil, 20, SPsswalk1, stt+GSsswalk2, 1},
+	[GSsswalk2] {nil, nil, 5, SPsswalk1, stt+GSsswalk3, 1},
+	[GSsswalk3] {uwalk, nil, 15, SPsswalk2, stt+GSsswalk4, 1},
+	[GSsswalk4] {uwalk, nil, 20, SPsswalk3, stt+GSsswalk5, 1},
+	[GSsswalk5] {nil, nil, 5, SPsswalk3, stt+GSsswalk6, 1},
+	[GSsswalk6] {uwalk, nil, 15, SPsswalk4, stt+GSsswalk1, 1},
+	[GSsspain1] {nil, nil, 10, SPsspain1, stt+GSsschase1, 2},
+	[GSsspain2] {nil, nil, 10, SPsspain2, stt+GSsschase1, 2},
+	[GSsschase1] {uchase, nil, 10, SPsswalk1, stt+GSsschase2, 1},
+	[GSsschase2] {nil, nil, 3, SPsswalk1, stt+GSsschase3, 1},
+	[GSsschase3] {uchase, nil, 8, SPsswalk2, stt+GSsschase4, 1},
+	[GSsschase4] {uchase, nil, 10, SPsswalk3, stt+GSsschase5, 1},
+	[GSsschase5] {nil, nil, 3, SPsswalk3, stt+GSsschase6, 1},
+	[GSsschase6] {uchase, nil, 8, SPsswalk4, stt+GSsschase1, 1},
+	[GSssfire1] {nil, nil, 20, SPssfire1, stt+GSssfire2, 0},
+	[GSssfire2] {nil, fire, 20, SPssfire2, stt+GSssfire3, 0},
+	[GSssfire3] {nil, nil, 10, SPssfire3, stt+GSssfire4, 0},
+	[GSssfire4] {nil, fire, 10, SPssfire2, stt+GSssfire5, 0},
+	[GSssfire5] {nil, nil, 10, SPssfire3, stt+GSssfire6, 0},
+	[GSssfire6] {nil, fire, 10, SPssfire2, stt+GSssfire7, 0},
+	[GSssfire7] {nil, nil, 10, SPssfire3, stt+GSssfire8, 0},
+	[GSssfire8] {nil, fire, 10, SPssfire2, stt+GSssfire9, 0},
+	[GSssfire9] {nil, nil, 10, SPssfire3, stt+GSsschase1, 0},
+	[GSssdie1] {nil, yelp, 15, SPssdie1, stt+GSssdie2, 0},
+	[GSssdie2] {nil, nil, 15, SPssdie2, stt+GSssdie3, 0},
+	[GSssdie3] {nil, nil, 15, SPssdie3, stt+GSssdie4, 0},
+	[GSssdie4] {nil, nil, 0, SPssdead, stt+GSssdie4, 0},
+	[GSofc] {uwait, nil, 0, SPofc, stt+GSofc, 1},
+	[GSofcwalk1] {uwalk, nil, 20, SPofcwalk1, stt+GSofcwalk2, 1},
+	[GSofcwalk2] {nil, nil, 5, SPofcwalk1, stt+GSofcwalk3, 1},
+	[GSofcwalk3] {uwalk, nil, 15, SPofcwalk2, stt+GSofcwalk4, 1},
+	[GSofcwalk4] {uwalk, nil, 20, SPofcwalk3, stt+GSofcwalk5, 1},
+	[GSofcwalk5] {nil, nil, 5, SPofcwalk3, stt+GSofcwalk6, 1},
+	[GSofcwalk6] {uwalk, nil, 15, SPofcwalk4, stt+GSofcwalk1, 1},
+	[GSofcpain1] {nil, nil, 10, SPofcpain1, stt+GSofcchase1, 2},
+	[GSofcpain2] {nil, nil, 10, SPofcpain2, stt+GSofcchase1, 2},
+	[GSofcchase1] {uchase, nil, 10, SPofcwalk1, stt+GSofcchase2, 1},
+	[GSofcchase2] {nil, nil, 3, SPofcwalk1, stt+GSofcchase3, 1},
+	[GSofcchase3] {uchase, nil, 8, SPofcwalk2, stt+GSofcchase4, 1},
+	[GSofcchase4] {uchase, nil, 10, SPofcwalk3, stt+GSofcchase5, 1},
+	[GSofcchase5] {nil, nil, 3, SPofcwalk3, stt+GSofcchase6, 1},
+	[GSofcchase6] {uchase, nil, 8, SPofcwalk4, stt+GSofcchase1, 1},
+	[GSofcfire1] {nil, nil, 6, SPofcfire1, stt+GSofcfire2, 0},
+	[GSofcfire2] {nil, fire, 20, SPofcfire2, stt+GSofcfire3, 0},
+	[GSofcfire3] {nil, nil, 10, SPofcfire3, stt+GSofcchase1, 0},
+	[GSofcdie1] {nil, yelp, 11, SPofcdie1, stt+GSofcdie2, 0},
+	[GSofcdie2] {nil, nil, 11, SPofcdie2, stt+GSofcdie3, 0},
+	[GSofcdie3] {nil, nil, 11, SPofcdie3, stt+GSofcdie4, 0},
+	[GSofcdie4] {nil, nil, 11, SPofcdie4, stt+GSofcdie5, 0},
+	[GSofcdie5] {nil, nil, 0, SPofcdead, stt+GSofcdie5, 0},
+	[GSmut] {uwait, nil, 0, SPmut, stt+GSmut, 1},
+	[GSmutwalk1] {uwalk, nil, 20, SPmutwalk1, stt+GSmutwalk2, 1},
+	[GSmutwalk2] {nil, nil, 5, SPmutwalk1, stt+GSmutwalk3, 1},
+	[GSmutwalk3] {uwalk, nil, 15, SPmutwalk2, stt+GSmutwalk4, 1},
+	[GSmutwalk4] {uwalk, nil, 20, SPmutwalk3, stt+GSmutwalk5, 1},
+	[GSmutwalk5] {nil, nil, 5, SPmutwalk3, stt+GSmutwalk6, 1},
+	[GSmutwalk6] {uwalk, nil, 15, SPmutwalk4, stt+GSmutwalk1, 1},
+	[GSmutpain1] {nil, nil, 10, SPmutpain1, stt+GSmutchase1, 2},
+	[GSmutpain2] {nil, nil, 10, SPmutpain2, stt+GSmutchase1, 2},
+	[GSmutchase1] {uchase, nil, 10, SPmutwalk1, stt+GSmutchase2, 1},
+	[GSmutchase2] {nil, nil, 3, SPmutwalk1, stt+GSmutchase3, 1},
+	[GSmutchase3] {uchase, nil, 8, SPmutwalk2, stt+GSmutchase4, 1},
+	[GSmutchase4] {uchase, nil, 10, SPmutwalk3, stt+GSmutchase5, 1},
+	[GSmutchase5] {nil, nil, 3, SPmutwalk3, stt+GSmutchase6, 1},
+	[GSmutchase6] {uchase, nil, 8, SPmutwalk4, stt+GSmutchase1, 1},
+	[GSmutfire1] {nil, fire, 6, SPmutfire1, stt+GSmutfire2, 0},
+	[GSmutfire2] {nil, nil, 20, SPmutfire2, stt+GSmutfire3, 0},
+	[GSmutfire3] {nil, fire, 10, SPmutfire3, stt+GSmutfire4, 0},
+	[GSmutfire4] {nil, nil, 20, SPmutfire4, stt+GSmutchase1, 0},
+	[GSmutdie1] {nil, yelp, 7, SPmutdie1, stt+GSmutdie2, 0},
+	[GSmutdie2] {nil, nil, 7, SPmutdie2, stt+GSmutdie3, 0},
+	[GSmutdie3] {nil, nil, 7, SPmutdie3, stt+GSmutdie4, 0},
+	[GSmutdie4] {nil, nil, 7, SPmutdie4, stt+GSmutdie5, 0},
+	[GSmutdie5] {nil, nil, 0, SPmutdead, stt+GSmutdie5, 0},
+	[GSdogwalk1] {uwalk, nil, 20, SPdogwalk1, stt+GSdogwalk2, 1},
+	[GSdogwalk2] {nil, nil, 5, SPdogwalk1, stt+GSdogwalk3, 1},
+	[GSdogwalk3] {uwalk, nil, 15, SPdogwalk2, stt+GSdogwalk4, 1},
+	[GSdogwalk4] {uwalk, nil, 20, SPdogwalk3, stt+GSdogwalk5, 1},
+	[GSdogwalk5] {nil, nil, 5, SPdogwalk3, stt+GSdogwalk6, 1},
+	[GSdogwalk6] {uwalk, nil, 15, SPdogwalk4, stt+GSdogwalk1, 1},
+	[GSdogchase1] {udogchase, nil, 10, SPdogwalk1, stt+GSdogchase2, 1},
+	[GSdogchase2] {nil, nil, 3, SPdogwalk1, stt+GSdogchase3, 1},
+	[GSdogchase3] {udogchase, nil, 8, SPdogwalk2, stt+GSdogchase4, 1},
+	[GSdogchase4] {udogchase, nil, 10, SPdogwalk3, stt+GSdogchase5, 1},
+	[GSdogchase5] {nil, nil, 3, SPdogwalk3, stt+GSdogchase6, 1},
+	[GSdogchase6] {udogchase, nil, 8, SPdogwalk4, stt+GSdogchase1, 1},
+	[GSdogfire1] {nil, nil, 10, SPdogfire1, stt+GSdogfire2, 0},
+	[GSdogfire2] {nil, bite, 10, SPdogfire2, stt+GSdogfire3, 0},
+	[GSdogfire3] {nil, nil, 10, SPdogfire3, stt+GSdogfire4, 0},
+	[GSdogfire4] {nil, nil, 10, SPdogfire1, stt+GSdogfire5, 0},
+	[GSdogfire5] {nil, nil, 10, SPdogwalk1, stt+GSdogchase1, 0},
+	[GSdogdie1] {nil, yelp, 15, SPdogdie1, stt+GSdogdie2, 0},
+	[GSdogdie2] {nil, nil, 15, SPdogdie2, stt+GSdogdie3, 0},
+	[GSdogdie3] {nil, nil, 15, SPdogdie3, stt+GSdogdie4, 0},
+	[GSdogdie4] {nil, nil, 15, SPdogdead, stt+GSdogdie4, 0},
+	[GShans] {uwait, nil, 0, SPhanswalk1, stt+GShans, 0},
+	[GShanschase1] {uchase, nil, 10, SPhanswalk1, stt+GShanschase2, 0},
+	[GShanschase2] {nil, nil, 3, SPhanswalk1, stt+GShanschase3, 0},
+	[GShanschase3] {uchase, nil, 8, SPhanswalk2, stt+GShanschase4, 0},
+	[GShanschase4] {uchase, nil, 10, SPhanswalk3, stt+GShanschase5, 0},
+	[GShanschase5] {nil, nil, 3, SPhanswalk3, stt+GShanschase6, 0},
+	[GShanschase6] {uchase, nil, 8, SPhanswalk4, stt+GShanschase1, 0},
+	[GShansfire1] {nil, nil, 30, SPhansfire1, stt+GShansfire2, 0},
+	[GShansfire2] {nil, fire, 10, SPhansfire2, stt+GShansfire3, 0},
+	[GShansfire3] {nil, fire, 10, SPhansfire3, stt+GShansfire4, 0},
+	[GShansfire4] {nil, fire, 10, SPhansfire2, stt+GShansfire5, 0},
+	[GShansfire5] {nil, fire, 10, SPhansfire3, stt+GShansfire6, 0},
+	[GShansfire6] {nil, fire, 10, SPhansfire2, stt+GShansfire7, 0},
+	[GShansfire7] {nil, fire, 10, SPhansfire3, stt+GShansfire8, 0},
+	[GShansfire8] {nil, nil, 10, SPhansfire1, stt+GShanschase1, 0},
+	[GShansdie1] {nil, yelp, 15, SPhansdie1, stt+GShansdie2, 0},
+	[GShansdie2] {nil, nil, 15, SPhansdie2, stt+GShansdie3, 0},
+	[GShansdie3] {nil, nil, 15, SPhansdie3, stt+GShansdie4, 0},
+	[GShansdie4] {nil, nil, 0, SPhansdead, stt+GShansdie4, 0},
+	[GSschb] {uwait, nil, 0, SPschbwalk1, stt+GSschb, 0},
+	[GSschbchase1] {uboss, nil, 10, SPschbwalk1, stt+GSschbchase2, 0},
+	[GSschbchase2] {nil, nil, 3, SPschbwalk1, stt+GSschbchase3, 0},
+	[GSschbchase3] {uboss, nil, 8, SPschbwalk2, stt+GSschbchase4, 0},
+	[GSschbchase4] {uboss, nil, 10, SPschbwalk3, stt+GSschbchase5, 0},
+	[GSschbchase5] {nil, nil, 3, SPschbwalk3, stt+GSschbchase6, 0},
+	[GSschbchase6] {uboss, nil, 8, SPschbwalk4, stt+GSschbchase1, 0},
+	[GSschbfire1] {nil, nil, 30, SPschbfire1, stt+GSschbfire2, 0},
+	[GSschbfire2] {nil, launch, 10, SPschbfire2, stt+GSschbchase1, 0},
+	[GSschbcam] {nil, nil, 1, SPschbwalk1, stt+GSschbdie1, 0},
+	[GSschbdie1] {nil, yelp, 10, SPschbwalk1, stt+GSschbdie2, 0},
+	[GSschbdie2] {nil, nil, 10, SPschbwalk1, stt+GSschbdie3, 0},
+	[GSschbdie3] {nil, nil, 10, SPschbdie1, stt+GSschbdie4, 0},
+	[GSschbdie4] {nil, nil, 10, SPschbdie2, stt+GSschbdie5, 0},
+	[GSschbdie5] {nil, nil, 10, SPschbdie3, stt+GSschbdie6, 0},
+	[GSschbdie6] {nil, cam, 20, SPschbdead, stt+GSschbdie6, 0},
+	[GSgretel] {uwait, nil, 0, SPgretelwalk1, stt+GSgretel, 0},
+	[GSgretelchase1] {uchase, nil, 10, SPgretelwalk1, stt+GSgretelchase2, 0},
+	[GSgretelchase2] {nil, nil, 3, SPgretelwalk1, stt+GSgretelchase3, 0},
+	[GSgretelchase3] {uchase, nil, 8, SPgretelwalk2, stt+GSgretelchase4, 0},
+	[GSgretelchase4] {uchase, nil, 10, SPgretelwalk3, stt+GSgretelchase5, 0},
+	[GSgretelchase5] {nil, nil, 3, SPgretelwalk3, stt+GSgretelchase6, 0},
+	[GSgretelchase6] {uchase, nil, 8, SPgretelwalk4, stt+GSgretelchase1, 0},
+	[GSgretelfire1] {nil, nil, 30, SPgretelfire1, stt+GSgretelfire2, 0},
+	[GSgretelfire2] {nil, fire, 10, SPgretelfire2, stt+GSgretelfire3, 0},
+	[GSgretelfire3] {nil, fire, 10, SPgretelfire3, stt+GSgretelfire4, 0},
+	[GSgretelfire4] {nil, fire, 10, SPgretelfire2, stt+GSgretelfire5, 0},
+	[GSgretelfire5] {nil, fire, 10, SPgretelfire3, stt+GSgretelfire6, 0},
+	[GSgretelfire6] {nil, fire, 10, SPgretelfire2, stt+GSgretelfire7, 0},
+	[GSgretelfire7] {nil, fire, 10, SPgretelfire3, stt+GSgretelfire8, 0},
+	[GSgretelfire8] {nil, nil, 10, SPgretelfire1, stt+GSgretelchase1, 0},
+	[GSgreteldie1] {nil, yelp, 15, SPgreteldie1, stt+GSgreteldie2, 0},
+	[GSgreteldie2] {nil, nil, 15, SPgreteldie2, stt+GSgreteldie3, 0},
+	[GSgreteldie3] {nil, nil, 15, SPgreteldie3, stt+GSgreteldie4, 0},
+	[GSgreteldie4] {nil, nil, 0, SPgreteldead, stt+GSgreteldie4, 0},
+	[GSotto] {uwait, nil, 0, SPottowalk1, stt+GSotto, 0},
+	[GSottochase1] {uboss, nil, 10, SPottowalk1, stt+GSottochase2, 0},
+	[GSottochase2] {nil, nil, 3, SPottowalk1, stt+GSottochase3, 0},
+	[GSottochase3] {uboss, nil, 8, SPottowalk2, stt+GSottochase4, 0},
+	[GSottochase4] {uboss, nil, 10, SPottowalk3, stt+GSottochase5, 0},
+	[GSottochase5] {nil, nil, 3, SPottowalk3, stt+GSottochase6, 0},
+	[GSottochase6] {uboss, nil, 8, SPottowalk4, stt+GSottochase1, 0},
+	[GSottofire1] {nil, nil, 30, SPottofire1, stt+GSottofire2, 0},
+	[GSottofire2] {nil, launch, 10, SPottofire2, stt+GSottochase1, 0},
+	[GSottocam] {nil, nil, 1, SPottowalk1, stt+GSottodie1, 0},
+	[GSottodie1] {nil, yelp, 1, SPottowalk1, stt+GSottodie2, 0},
+	[GSottodie2] {nil, nil, 10, SPottowalk1, stt+GSottodie3, 0},
+	[GSottodie3] {nil, nil, 10, SPottodie1, stt+GSottodie4, 0},
+	[GSottodie4] {nil, nil, 10, SPottodie2, stt+GSottodie5, 0},
+	[GSottodie5] {nil, nil, 10, SPottodie3, stt+GSottodie6, 0},
+	[GSottodie6] {nil, cam, 20, SPottodead, stt+GSottodie6, 0},
+	[GSfett] {uwait, nil, 0, SPfettwalk1, stt+GSfett, 0},
+	[GSfettchase1] {uboss, nil, 10, SPfettwalk1, stt+GSfettchase2, 0},
+	[GSfettchase2] {nil, nil, 3, SPfettwalk1, stt+GSfettchase3, 0},
+	[GSfettchase3] {uboss, nil, 8, SPfettwalk2, stt+GSfettchase4, 0},
+	[GSfettchase4] {uboss, nil, 10, SPfettwalk3, stt+GSfettchase5, 0},
+	[GSfettchase5] {nil, nil, 3, SPfettwalk3, stt+GSfettchase6, 0},
+	[GSfettchase6] {uboss, nil, 8, SPfettwalk4, stt+GSfettchase1, 0},
+	[GSfettfire1] {nil, nil, 30, SPfettfire1, stt+GSfettfire2, 0},
+	[GSfettfire2] {nil, launch, 10, SPfettfire2, stt+GSfettfire3, 0},
+	[GSfettfire3] {nil, fire, 10, SPfettfire3, stt+GSfettfire4, 0},
+	[GSfettfire4] {nil, fire, 10, SPfettfire4, stt+GSfettfire5, 0},
+	[GSfettfire5] {nil, fire, 10, SPfettfire3, stt+GSfettfire6, 0},
+	[GSfettfire6] {nil, fire, 10, SPfettfire4, stt+GSfettchase1, 0},
+	[GSfettcam] {nil, nil, 1, SPfettwalk1, stt+GSfettdie1, 0},
+	[GSfettdie1] {nil, yelp, 1, SPfettwalk1, stt+GSfettdie2, 0},
+	[GSfettdie2] {nil, nil, 10, SPfettwalk1, stt+GSfettdie3, 0},
+	[GSfettdie3] {nil, nil, 10, SPfettdie1, stt+GSfettdie4, 0},
+	[GSfettdie4] {nil, nil, 10, SPfettdie2, stt+GSfettdie5, 0},
+	[GSfettdie5] {nil, nil, 10, SPfettdie3, stt+GSfettdie6, 0},
+	[GSfettdie6] {nil, cam, 20, SPfettdead, stt+GSfettdie6, 0},
+	[GSfake] {uwait, nil, 0, SPfakewalk1, stt+GSfake, 0},
+	[GSfakechase1] {ufake, nil, 10, SPfakewalk1, stt+GSfakechase2, 0},
+	[GSfakechase2] {nil, nil, 3, SPfakewalk1, stt+GSfakechase3, 0},
+	[GSfakechase3] {ufake, nil, 8, SPfakewalk2, stt+GSfakechase4, 0},
+	[GSfakechase4] {ufake, nil, 10, SPfakewalk3, stt+GSfakechase5, 0},
+	[GSfakechase5] {nil, nil, 3, SPfakewalk3, stt+GSfakechase6, 0},
+	[GSfakechase6] {ufake, nil, 8, SPfakewalk4, stt+GSfakechase1, 0},
+	[GSfakefire1] {nil, launch, 8, SPfakefire, stt+GSfakefire2, 0},
+	[GSfakefire2] {nil, launch, 8, SPfakefire, stt+GSfakefire3, 0},
+	[GSfakefire3] {nil, launch, 8, SPfakefire, stt+GSfakefire4, 0},
+	[GSfakefire4] {nil, launch, 8, SPfakefire, stt+GSfakefire5, 0},
+	[GSfakefire5] {nil, launch, 8, SPfakefire, stt+GSfakefire6, 0},
+	[GSfakefire6] {nil, launch, 8, SPfakefire, stt+GSfakefire7, 0},
+	[GSfakefire7] {nil, launch, 8, SPfakefire, stt+GSfakefire8, 0},
+	[GSfakefire8] {nil, launch, 8, SPfakefire, stt+GSfakefire9, 0},
+	[GSfakefire9] {nil, nil, 8, SPfakefire, stt+GSfakechase1, 0},
+	[GSfakedie1] {nil, yelp, 10, SPfakedie1, stt+GSfakedie2, 0},
+	[GSfakedie2] {nil, nil, 10, SPfakedie2, stt+GSfakedie3, 0},
+	[GSfakedie3] {nil, nil, 10, SPfakedie3, stt+GSfakedie4, 0},
+	[GSfakedie4] {nil, nil, 10, SPfakedie4, stt+GSfakedie5, 0},
+	[GSfakedie5] {nil, nil, 10, SPfakedie5, stt+GSfakedie6, 0},
+	[GSfakedie6] {nil, nil, 0, SPfakedead, stt+GSfakedie6, 0},
+	[GSmech] {uwait, nil, 0, SPmechwalk1, stt+GSmech, 0},
+	[GSmechchase1] {uchase, mechsfx, 10, SPmechwalk1, stt+GSmechchase2, 0},
+	[GSmechchase2] {nil, nil, 6, SPmechwalk1, stt+GSmechchase3, 0},
+	[GSmechchase3] {uchase, nil, 8, SPmechwalk2, stt+GSmechchase4, 0},
+	[GSmechchase4] {uchase, mechsfx, 10, SPmechwalk3, stt+GSmechchase5, 0},
+	[GSmechchase5] {nil, nil, 6, SPmechwalk3, stt+GSmechchase6, 0},
+	[GSmechchase6] {uchase, nil, 8, SPmechwalk4, stt+GSmechchase1, 0},
+	[GSmechfire1] {nil, nil, 30, SPmechfire1, stt+GSmechfire2, 0},
+	[GSmechfire2] {nil, fire, 10, SPmechfire2, stt+GSmechfire3, 0},
+	[GSmechfire3] {nil, fire, 10, SPmechfire3, stt+GSmechfire4, 0},
+	[GSmechfire4] {nil, fire, 10, SPmechfire2, stt+GSmechfire5, 0},
+	[GSmechfire5] {nil, fire, 10, SPmechfire3, stt+GSmechfire6, 0},
+	[GSmechfire6] {nil, fire, 10, SPmechfire2, stt+GSmechchase1, 0},
+	[GSmechdie1] {nil, yelp, 10, SPmechdie1, stt+GSmechdie2, 0},
+	[GSmechdie2] {nil, nil, 10, SPmechdie2, stt+GSmechdie3, 0},
+	[GSmechdie3] {nil, mechblow, 10, SPmechdie3, stt+GSmechdie4, 0},
+	[GSmechdie4] {nil, nil, 0, SPmechdead, stt+GSmechdie4, 0},
+	[GShitlerchase1] {uchase, nil, 6, SPhitlerwalk1, stt+GShitlerchase2, 0},
+	[GShitlerchase2] {nil, nil, 4, SPhitlerwalk1, stt+GShitlerchase3, 0},
+	[GShitlerchase3] {uchase, nil, 2, SPhitlerwalk2, stt+GShitlerchase4, 0},
+	[GShitlerchase4] {uchase, nil, 6, SPhitlerwalk3, stt+GShitlerchase5, 0},
+	[GShitlerchase5] {nil, nil, 4, SPhitlerwalk3, stt+GShitlerchase6, 0},
+	[GShitlerchase6] {uchase, nil, 2, SPhitlerwalk4, stt+GShitlerchase1, 0},
+	[GShitlerfire1] {nil, nil, 30, SPhitlerfire1, stt+GShitlerfire2, 0},
+	[GShitlerfire2] {nil, fire, 10, SPhitlerfire2, stt+GShitlerfire3, 0},
+	[GShitlerfire3] {nil, fire, 10, SPhitlerfire3, stt+GShitlerfire4, 0},
+	[GShitlerfire4] {nil, fire, 10, SPhitlerfire2, stt+GShitlerfire5, 0},
+	[GShitlerfire5] {nil, fire, 10, SPhitlerfire3, stt+GShitlerfire6, 0},
+	[GShitlerfire6] {nil, fire, 10, SPhitlerfire2, stt+GShitlerchase1, 0},
+	[GShitlercam] {nil, nil, 10, SPhitlerwalk1, stt+GShitlerdie1, 0},
+	[GShitlerdie1] {nil, yelp, 1, SPhitlerwalk1, stt+GShitlerdie2, 0},
+	[GShitlerdie2] {nil, nil, 10, SPhitlerwalk1, stt+GShitlerdie3, 0},
+	[GShitlerdie3] {nil, slurp, 10, SPhitlerdie1, stt+GShitlerdie4, 0},
+	[GShitlerdie4] {nil, nil, 10, SPhitlerdie2, stt+GShitlerdie5, 0},
+	[GShitlerdie5] {nil, nil, 10, SPhitlerdie3, stt+GShitlerdie6, 0},
+	[GShitlerdie6] {nil, nil, 10, SPhitlerdie4, stt+GShitlerdie7, 0},
+	[GShitlerdie7] {nil, nil, 10, SPhitlerdie5, stt+GShitlerdie8, 0},
+	[GShitlerdie8] {nil, nil, 10, SPhitlerdie6, stt+GShitlerdie9, 0},
+	[GShitlerdie9] {nil, nil, 10, SPhitlerdie7, stt+GShitlerdie10, 0},
+	[GShitlerdie10] {nil, cam, 20, SPhitlerdead, stt+GShitlerdie10, 0},
+	[GSgh1chase1] {ughost, nil, 10, SPgh1walk1, stt+GSgh1chase2, 0},
+	[GSgh2chase1] {ughost, nil, 10, SPgh3walk1, stt+GSgh2chase2, 0},
+	[GSgh3chase1] {ughost, nil, 10, SPgh2walk1, stt+GSgh3chase2, 0},
+	[GSgh4chase1] {ughost, nil, 10, SPgh2walk1, stt+GSgh4chase2, 0},
+	[GSgh1chase2] {ughost, nil, 10, SPgh1walk2, stt+GSgh1chase1, 0},
+	[GSgh2chase2] {ughost, nil, 10, SPgh3walk2, stt+GSgh2chase1, 0},
+	[GSgh3chase2] {ughost, nil, 10, SPgh2walk2, stt+GSgh3chase1, 0},
+	[GSgh4chase2] {ughost, nil, 10, SPgh2walk2, stt+GSgh4chase1, 0},
+	[GStrans] {uwait, nil, 0, SPtranswalk1, stt+GStrans, 0},
+	[GStranschase1] {uchase, nil, 10, SPtranswalk1, stt+GStranschase2, 0},
+	[GStranschase2] {nil, nil, 3, SPtranswalk1, stt+GStranschase3, 0},
+	[GStranschase3] {uchase, nil, 8, SPtranswalk2, stt+GStranschase4, 0},
+	[GStranschase4] {uchase, nil, 10, SPtranswalk3, stt+GStranschase5, 0},
+	[GStranschase5] {nil, nil, 3, SPtranswalk3, stt+GStranschase6, 0},
+	[GStranschase6] {uchase, nil, 8, SPtranswalk4, stt+GStranschase1, 0},
+	[GStransfire1] {nil, nil, 30, SPtransfire1, stt+GStransfire2, 0},
+	[GStransfire2] {nil, fire, 10, SPtransfire2, stt+GStransfire3, 0},
+	[GStransfire3] {nil, fire, 10, SPtransfire3, stt+GStransfire4, 0},
+	[GStransfire4] {nil, fire, 10, SPtransfire2, stt+GStransfire5, 0},
+	[GStransfire5] {nil, fire, 10, SPtransfire3, stt+GStransfire6, 0},
+	[GStransfire6] {nil, fire, 10, SPtransfire2, stt+GStransfire7, 0},
+	[GStransfire7] {nil, fire, 10, SPtransfire3, stt+GStransfire8, 0},
+	[GStransfire8] {nil, nil, 10, SPtransfire1, stt+GStranschase1, 0},
+	[GStransdie1] {nil, yelp, 1, SPtranswalk1, stt+GStransdie2, 0},
+	[GStransdie2] {nil, nil, 1, SPtranswalk1, stt+GStransdie3, 0},
+	[GStransdie3] {nil, nil, 15, SPtransdie1, stt+GStransdie4, 0},
+	[GStransdie4] {nil, nil, 15, SPtransdie2, stt+GStransdie5, 0},
+	[GStransdie5] {nil, nil, 15, SPtransdie3, stt+GStransdie6, 0},
+	[GStransdie6] {nil, nil, 0, SPtransdead, stt+GStransdie6, 0},
+	[GSwilh] {uwait, nil, 0, SPwilhwalk1, stt+GSwilh, 0},
+	[GSwilhchase1] {uboss, nil, 10, SPwilhwalk1, stt+GSwilhchase2, 0},
+	[GSwilhchase2] {nil, nil, 3, SPwilhwalk1, stt+GSwilhchase3, 0},
+	[GSwilhchase3] {uboss, nil, 8, SPwilhwalk2, stt+GSwilhchase4, 0},
+	[GSwilhchase4] {uboss, nil, 10, SPwilhwalk3, stt+GSwilhchase5, 0},
+	[GSwilhchase5] {nil, nil, 3, SPwilhwalk3, stt+GSwilhchase6, 0},
+	[GSwilhchase6] {uboss, nil, 8, SPwilhwalk4, stt+GSwilhchase1, 0},
+	[GSwilhfire1] {nil, nil, 30, SPwilhfire1, stt+GSwilhfire2, 0},
+	[GSwilhfire2] {nil, launch, 10, SPwilhfire2, stt+GSwilhfire3, 0},
+	[GSwilhfire3] {nil, fire, 10, SPwilhfire3, stt+GSwilhfire4, 0},
+	[GSwilhfire4] {nil, fire, 10, SPwilhfire4, stt+GSwilhfire5, 0},
+	[GSwilhfire5] {nil, fire, 10, SPwilhfire3, stt+GSwilhfire6, 0},
+	[GSwilhfire6] {nil, fire, 10, SPwilhfire4, stt+GSwilhchase1, 0},
+	[GSwilhdie1] {nil, yelp, 1, SPwilhwalk1, stt+GSwilhdie2, 0},
+	[GSwilhdie2] {nil, nil, 10, SPwilhwalk1, stt+GSwilhdie3, 0},
+	[GSwilhdie3] {nil, nil, 10, SPwilhdie1, stt+GSwilhdie4, 0},
+	[GSwilhdie4] {nil, nil, 10, SPwilhdie2, stt+GSwilhdie5, 0},
+	[GSwilhdie5] {nil, nil, 10, SPwilhdie3, stt+GSwilhdie6, 0},
+	[GSwilhdie6] {nil, nil, 20, SPwilhdead, stt+GSwilhdie6, 0},
+	[GSuber] {uwait, nil, 0, SPuberwalk1, stt+GSuber, 0},
+	[GSuberchase1] {uchase, nil, 10, SPuberwalk1, stt+GSuberchase2, 0},
+	[GSuberchase2] {nil, nil, 3, SPuberwalk1, stt+GSuberchase3, 0},
+	[GSuberchase3] {uchase, nil, 8, SPuberwalk2, stt+GSuberchase4, 0},
+	[GSuberchase4] {uchase, nil, 10, SPuberwalk3, stt+GSuberchase5, 0},
+	[GSuberchase5] {nil, nil, 3, SPuberwalk3, stt+GSuberchase6, 0},
+	[GSuberchase6] {uchase, nil, 8, SPuberwalk4, stt+GSuberchase1, 0},
+	[GSuberfire1] {nil, nil, 30, SPuberfire1, stt+GSuberfire2, 0},
+	[GSuberfire2] {nil, uberfire, 12, SPuberfire2, stt+GSuberfire3, 0},
+	[GSuberfire3] {nil, uberfire, 12, SPuberfire3, stt+GSuberfire4, 0},
+	[GSuberfire4] {nil, uberfire, 12, SPuberfire4, stt+GSuberfire5, 0},
+	[GSuberfire5] {nil, uberfire, 12, SPuberfire3, stt+GSuberfire6, 0},
+	[GSuberfire6] {nil, uberfire, 12, SPuberfire2, stt+GSuberfire7, 0},
+	[GSuberfire7] {nil, nil, 12, SPuberfire1, stt+GSuberchase1, 0},
+	[GSuberdie1] {nil, yelp, 1, SPuberwalk1, stt+GSuberdie2, 0},
+	[GSuberdie2] {nil, nil, 1, SPuberwalk1, stt+GSuberdie3, 0},
+	[GSuberdie3] {nil, nil, 15, SPuberdie1, stt+GSuberdie4, 0},
+	[GSuberdie4] {nil, nil, 15, SPuberdie2, stt+GSuberdie5, 0},
+	[GSuberdie5] {nil, nil, 15, SPuberdie3, stt+GSuberdie6, 0},
+	[GSuberdie6] {nil, nil, 15, SPuberdie4, stt+GSuberdie7, 0},
+	[GSuberdie7] {nil, nil, 0, SPuberdead, stt+GSuberdie7, 0},
+	[GSknight] {uwait, nil, 0, SPknightwalk1, stt+GSknight, 0},
+	[GSknightchase1] {uboss, nil, 10, SPknightwalk1, stt+GSknightchase2, 0},
+	[GSknightchase2] {nil, nil, 3, SPknightwalk1, stt+GSknightchase3, 0},
+	[GSknightchase3] {uboss, nil, 8, SPknightwalk2, stt+GSknightchase4, 0},
+	[GSknightchase4] {uboss, nil, 10, SPknightwalk3, stt+GSknightchase5, 0},
+	[GSknightchase5] {nil, nil, 3, SPknightwalk3, stt+GSknightchase6, 0},
+	[GSknightchase6] {uboss, nil, 8, SPknightwalk4, stt+GSknightchase1, 0},
+	[GSknightfire1] {nil, nil, 30, SPknightfire1, stt+GSknightfire2, 0},
+	[GSknightfire2] {nil, launch, 10, SPknightfire2, stt+GSknightfire3, 0},
+	[GSknightfire3] {nil, fire, 10, SPknightfire4, stt+GSknightfire4, 0},
+	[GSknightfire4] {nil, launch, 10, SPknightfire3, stt+GSknightfire5, 0},
+	[GSknightfire5] {nil, fire, 10, SPknightfire4, stt+GSknightchase1, 0},
+	[GSknightdie1] {nil, yelp, 1, SPknightwalk1, stt+GSknightdie2, 0},
+	[GSknightdie2] {nil, nil, 10, SPknightwalk1, stt+GSknightdie3, 0},
+	[GSknightdie3] {nil, nil, 10, SPknightdie1, stt+GSknightdie4, 0},
+	[GSknightdie4] {nil, nil, 10, SPknightdie2, stt+GSknightdie5, 0},
+	[GSknightdie5] {nil, nil, 10, SPknightdie3, stt+GSknightdie6, 0},
+	[GSknightdie6] {nil, nil, 10, SPknightdie4, stt+GSknightdie7, 0},
+	[GSknightdie7] {nil, nil, 10, SPknightdie5, stt+GSknightdie8, 0},
+	[GSknightdie8] {nil, nil, 10, SPknightdie6, stt+GSknightdie9, 0},
+	[GSknightdie9] {nil, nil, 0, SPknightdead, stt+GSknightdie9, 0},
+	[GSspectrewait1] {uwait, nil, 10, SPspectrewalk1, stt+GSspectrewait2, 0},
+	[GSspectrewait2] {uwait, nil, 10, SPspectrewalk2, stt+GSspectrewait3, 0},
+	[GSspectrewait3] {uwait, nil, 10, SPspectrewalk3, stt+GSspectrewait4, 0},
+	[GSspectrewait4] {uwait, nil, 10, SPspectrewalk4, stt+GSspectrewait1, 0},
+	[GSspectrewake] {nil, wake, 10, SPspectreF4, stt+GSspectrewake, 0},
+	[GSspectrechase1] {ughost, nil, 10, SPspectrewalk1, stt+GSspectrechase2, 0},
+	[GSspectrechase2] {ughost, nil, 10, SPspectrewalk2, stt+GSspectrechase3, 0},
+	[GSspectrechase3] {ughost, nil, 10, SPspectrewalk3, stt+GSspectrechase4, 0},
+	[GSspectrechase4] {ughost, nil, 10, SPspectrewalk4, stt+GSspectrechase1, 0},
+	[GSspectredie1] {nil, nil, 10, SPspectreF1, stt+GSspectredie2, 0},
+	[GSspectredie2] {nil, nil, 10, SPspectreF2, stt+GSspectredie3, 0},
+	[GSspectredie3] {nil, nil, 10, SPspectreF3, stt+GSspectredie4, 0},
+	[GSspectredie4] {nil, nil, 300, SPspectreF4, stt+GSspectrewake, 0},
+	[GSangel] {uwait, nil, 0, SPangelwalk1, stt+GSangel, 0},
+	[GSangelchase1] {uboss, nil, 10, SPangelwalk1, stt+GSangelchase2, 0},
+	[GSangelchase2] {nil, nil, 3, SPangelwalk1, stt+GSangelchase3, 0},
+	[GSangelchase3] {uboss, nil, 8, SPangelwalk2, stt+GSangelchase4, 0},
+	[GSangelchase4] {uboss, nil, 10, SPangelwalk3, stt+GSangelchase5, 0},
+	[GSangelchase5] {nil, nil, 3, SPangelwalk3, stt+GSangelchase6, 0},
+	[GSangelchase6] {uboss, nil, 8, SPangelwalk4, stt+GSangelchase1, 0},
+	[GSangelfire1] {nil, prelaunch, 10, SPangelfire1, stt+GSangelfire2, 0},
+	[GSangelfire2] {nil, launch, 20, SPangelfire2, stt+GSangelfire3, 0},
+	[GSangelfire3] {nil, relaunch, 10, SPangelfire1, stt+GSangelfire2, 0},
+	[GSangeldie1] {nil, yelp, 1, SPangelwalk1, stt+GSangeldie2, 0},
+	[GSangeldie2] {nil, nil, 1, SPangelwalk1, stt+GSangeldie3, 0},
+	[GSangeldie3] {nil, slurp, 10, SPangeldie1, stt+GSangeldie4, 0},
+	[GSangeldie4] {nil, nil, 10, SPangeldie2, stt+GSangeldie5, 0},
+	[GSangeldie5] {nil, nil, 10, SPangeldie3, stt+GSangeldie6, 0},
+	[GSangeldie6] {nil, nil, 10, SPangeldie4, stt+GSangeldie7, 0},
+	[GSangeldie7] {nil, nil, 10, SPangeldie5, stt+GSangeldie8, 0},
+	[GSangeldie8] {nil, nil, 10, SPangeldie6, stt+GSangeldie9, 0},
+	[GSangeldie9] {nil, nil, 10, SPangeldie7, stt+GSangeldie10, 0},
+	[GSangeldie10] {nil, victory, 130, SPangeldead, stt+GSangeldie10, 0},
+	[GSangeltired1] {nil, tiredsfx, 40, SPangeltired1, stt+GSangeltired2, 0},
+	[GSangeltired2] {nil, nil, 40, SPangeltired2, stt+GSangeltired3, 0},
+	[GSangeltired3] {nil, tiredsfx, 40, SPangeltired1, stt+GSangeltired4, 0},
+	[GSangeltired4] {nil, nil, 40, SPangeltired2, stt+GSangeltired5, 0},
+	[GSangeltired5] {nil, tiredsfx, 40, SPangeltired1, stt+GSangeltired6, 0},
+	[GSangeltired6] {nil, nil, 40, SPangeltired2, stt+GSangeltired7, 0},
+	[GSangeltired7] {nil, tiredsfx, 40, SPangeltired1, stt+GSangelchase1, 0},
+	[GSmissile] {uprj, smoke, 3, SPmissile1, stt+GSmissile, 1},
+	[GSmsmoke1] {nil, nil, 3, SPmsmoke1, stt+GSmsmoke2, 0},
+	[GSmsmoke2] {nil, nil, 3, SPmsmoke2, stt+GSmsmoke3, 0},
+	[GSmsmoke3] {nil, nil, 3, SPmsmoke3, stt+GSmsmoke4, 0},
+	[GSmsmoke4] {nil, nil, 3, SPmsmoke4, nil, 0},
+	[GSmboom1] {nil, nil, 6, SPmboom1, stt+GSmboom2, 0},
+	[GSmboom2] {nil, nil, 6, SPmboom2, stt+GSmboom3, 0},
+	[GSmboom3] {nil, nil, 6, SPmboom3, nil, 0},
+	[GSrocket] {uprj, smoke, 3, SProcket1, stt+GSrocket, 1},
+	[GSrsmoke1] {nil, nil, 3, SPrsmoke1, stt+GSrsmoke2, 0},
+	[GSrsmoke2] {nil, nil, 3, SPrsmoke2, stt+GSrsmoke3, 0},
+	[GSrsmoke3] {nil, nil, 3, SPrsmoke3, stt+GSrsmoke4, 0},
+	[GSrsmoke4] {nil, nil, 3, SPrsmoke4, nil, 0},
+	[GSrboom1] {nil, nil, 6, SPrboom1, stt+GSrboom2, 0},
+	[GSrboom2] {nil, nil, 6, SPrboom2, stt+GSrboom3, 0},
+	[GSrboom3] {nil, nil, 6, SPrboom3, nil, 0},
+	[GSflame1] {nil, uprj, 6, SPflame1, stt+GSflame2, 0},
+	[GSflame2] {nil, uprj, 6, SPflame2, stt+GSflame1, 0},
+	[GSneedle1] {uprj, nil, 6, SPneedle1, stt+GSneedle2, 0},
+	[GSneedle2] {uprj, nil, 6, SPneedle2, stt+GSneedle3, 0},
+	[GSneedle3] {uprj, nil, 6, SPneedle3, stt+GSneedle4, 0},
+	[GSneedle4] {uprj, nil, 6, SPneedle4, stt+GSneedle1, 0},
+	[GSspark1] {uprj, nil, 6, SPspark1, stt+GSspark2, 0},
+	[GSspark2] {uprj, nil, 6, SPspark2, stt+GSspark3, 0},
+	[GSspark3] {uprj, nil, 6, SPspark3, stt+GSspark4, 0},
+	[GSspark4] {uprj, nil, 6, SPspark4, stt+GSspark1, 0}
 };
 
 static void
@@ -2409,6 +2382,38 @@
 }
 
 void
+camwarp(void)
+{
+	int Δx, Δy, Δr;
+	double θ;
+
+	oplr->x = bosskillx;
+	oplr->y = bosskilly;
+	Δx = camobj->x - oplr->x;
+	Δy = oplr->y - camobj->y;
+	θ = atan2(Δy, Δx);
+	if(θ < 0)
+		θ = Fpi * 2 + θ;
+	oplr->θ = θ / (Fpi * 2) * 360;
+	Δr = 0x14000;
+	do{
+		oplr->x = camobj->x - ffs(Δr, cost[oplr->θ]);
+		oplr->y = camobj->y + ffs(Δr, sint[oplr->θ]);
+		Δr += 0x1000;
+	}while(!trymove(oplr, Dplr, 1, 0));
+	oplr->tx = oplr->x >> Dtlshift;
+	oplr->ty = oplr->y >> Dtlshift;
+	oplr->tl = tiles + oplr->ty * Mapdxy + oplr->tx;
+	ostate(oplr, stt+GSplrcam);
+	switch(camobj->type){
+	case Oschb: ostate(camobj, stt+GSschbcam); break;
+	case Ootto: ostate(camobj, stt+GSottocam); break;
+	case Ofett: ostate(camobj, stt+GSfettcam); break;
+	case Ohitler: ostate(camobj, stt+GShitlercam); break;
+	}
+}
+
+void
 bonus(Static *s)
 {
 	switch(s->item){
@@ -2519,20 +2524,23 @@
 void
 gstep(void)
 {
-	if((gm.demo || gm.record) && demfrm-- != 0)
-		return;
-	demfrm = 3;
+	if(gm.demo || gm.record){
+		if(demfrm-- != 0)
+			return;
+		demfrm = 3;
+		Δtc = 4;
+	}
 	input();
 	noise = 0;
 	uworld();
 	upal();
 	render();
+	mtc += Δtc;
 	gm.lvltc += Δtc;
 	if(dofizz){
+		dofizz = 0;
 		if(!gm.end)
 			gm.end = EDfizz;
-		gm.fizz++;
-		dofizz = 0;
 		gend();
 		return;
 	}
--- a/hub.c
+++ b/hub.c
@@ -52,7 +52,8 @@
 	Lmscore,
 	Lpants,
 	Lquit,
-	Ldie
+	Lmexit,
+	Lexit
 };
 struct Seq{
 	int dt;
@@ -241,7 +242,7 @@
 		return;
 	if(r == 'y'){
 		sfx(Sshoot);
-		reset(ml+Ldie);
+		reset(ml+Lmexit);
 	}
 	else if(r == 'n' || r == Kesc){
 		sfx(Sesc);
@@ -448,19 +449,21 @@
 {
 	step = gstep;
 	gm.end = 0;
-	gm.fizz = 0;
 }
 
 static void
 camtxt2(void)
 {
-	put(0, 56, Vw, 16, 0x7f);
+	camwarp();
+	mtc = 32;
+	render();
+	fizzop(-1, 1);
+	put(0, 0, Vw, Vhud, 0x7f);
 	viewbox();
 }
 static void
 camtxt(void)
 {
-	fizzop(-1, 0);
 	pictxt(0, 56, "LET\'S SEE THAT AGAIN!");
 	out();
 }
@@ -565,7 +568,7 @@
 }
 
 static void
-die(void)
+exit(void)
 {
 	threadexitsall(nil);
 }
@@ -604,7 +607,8 @@
 	mscoreq[] = {{10, fadeout}, {0, score}, {10, fadein}},
 	pantsq[] = {{30, fadeout}, {0, pants}, {30, fadein}},
 	quitq[] = {{0, blink}, {10, ask}},
-	dieq[] = {{10, fadeout}, {1, die}};
+	mexitq[] = {{10, fadeout}},
+	exitq[] = {{1, exit}};
 
 static Menu *mp, ml[] = {
 	[Lload] {nil, decq, decq+nelem(decq), ml+Lintro, &fblk},
@@ -628,7 +632,8 @@
 	[Lmscore] {nil, mscoreq, mscoreq+nelem(mscoreq), ml+Lack, &fmenu},
 	[Lpants] {nil, pantsq, pantsq+nelem(pantsq), ml+Lwait, &fblk},
 	[Lquit] {quit, quitq, quitq+nelem(quitq), ml+Lquit},
-	[Ldie] {nil, dieq, dieq+nelem(dieq), nil, &fmenu}
+	[Lmexit] {nil, mexitq, mexitq+nelem(mexitq), ml+Lexit, &fmenu},
+	[Lexit] {nil, exitq, exitq+nelem(exitq)}
 };
 
 static void
@@ -637,11 +642,11 @@
 	gm.demo = gm.record = 0;
 	pal = pals[Cfad];
 	if(demf != nil){
-		if(demexit)
-			threadexitsall(nil);
 		free(demf);
 		demf = nil;
 		demd = dems;
+		if(demexit)
+			mp->m = ml+Lexit;
 	}
 }
 void
@@ -655,14 +660,16 @@
 		break;
 	enddem:
 	case EDdem:
-		dend();
 		mp->m = ml+Ltitle;
+		dend();
 		break;
 	case EDcam:
-		fizzop(0x7f, 1);
+		if(gm.record || gm.demo)
+			scalspr(SPdemo, vw.dx/2, vw.dy+1);
+		out();
+		fizzop(0x7f, 0);
 		reset(ml+Lcam);
 		mp->m = gm.demo || gm.record ? ml+Ltitle : ml+Lwin;
-		gm.fizz++;
 		break;
 	case EDcam2:
 		if(gm.demo || gm.record)
@@ -669,10 +676,11 @@
 			dend();
 		else
 			pal = pals[Cfad];
+		scalspr(SPcam, vw.dx/2, vw.dy+1);
 		break;
 	case EDkey:
-		dend();
 		mp->m = ml+Linctl;
+		dend();
 		break;
 	case EDdie:
 		if(gm.demo || gm.record)
@@ -686,6 +694,7 @@
 		mp->m = ml+Lsfxwait;
 		break;
 	}
+	mtc = 0;
 	step = mstep;
 }
 
--- a/man/1/wl3d
+++ b/man/1/wl3d
@@ -33,6 +33,42 @@
 Now, you must do anything to escape from the belly of a Nazi dungeon - or die trying."
 .RE
 .PP
+The command line options are:
+.TP \w'\fLf\ \ \ \fIdemo'u
+.B -2
+Set game version to Spear of Destiny Mission 2: Return to Danger.
+.TP
+.B -3
+Set game version to Spear of Destiny Mission 3: The Ultimate Challenge.
+.TP
+.B -d
+Set game version to Wolfenstein 3-D 1.4 shareware.
+.TP
+.BI -f\  demo
+Play demo from file on startup.
+.TP
+.BI -m\  dir
+Set game data directory.
+.TP
+.B -o
+Set game version to Spear of Destiny 1.0 demo.
+.TP
+.B -p
+Run at full speed.
+.TP
+.B -q
+Quit after demofile playback.
+.TP
+.B -s
+Set game version to Spear of Destiny 1.0 retail.
+.TP
+.BI -w\  map
+Warp to the given map number on startup.
+.TP
+.BI -x\  1-4
+Set default game difficulty.
+.PD
+.PP
 .I Wl3d
 requires several data files to operate, containing sound effects, music, and several types of graphics.
 These are detailed in
@@ -51,7 +87,8 @@
 .B MBEFORE
 and
 .B MCREATE
-flags.
+flags (see
+.IR bind (2)).
 Data files can thus be contained in a system directory while the config and save files' location, which are user-specific, can be left at the user's discretion.
 If these user-specific files exist and
 .I wl3d
@@ -68,7 +105,8 @@
 .IR map ,
 and
 .B -x
-optionally sets the game difficulty.
+optionally sets the game difficulty to 1-4, from easiest to hardest,
+the default being 2.
 The
 .B -p
 parameter runs the program at the fastest speed possible for testing purposes.
@@ -81,31 +119,19 @@
 The default game version is Wolfenstein 3-D 1.4 retail, and the data files use the
 .L wl6
 extension.
-Others are set by the following options:
-.TF -2
-.TP
-.B -d
-Wolfenstein 3-D 1.4 shareware
-.TP
-.B -s
-Spear of Destiny 1.0 retail
-.TP
+Others are set by the options
+.BR -2 ,
+.BR -3 ,
+.BR -d ,
 .B -o
-Spear of Destiny 1.0 demo
-.TP
-.B -2
-Spear of Destiny Mission 2: Return to Danger
-.TP
-.B -3
-Spear of Destiny Mission 3: The Ultimate Challenge
-.PD
-.PP
+and
+.BR -s .
 The respective data file extensions are
+.LR sd2 ,
+.LR sd3 ,
 .LR wl1 ,
-.LR sod ,
 .LR sdm ,
-.LR sd2 ,
-.LR sd3 .
+.LR sod .
 .PD
 Other game versions are unsupported.
 Note that
@@ -123,7 +149,7 @@
 parameter.
 The
 .B -q
-parameter causes the program to exit after playback instead.
+parameter causes the program to exit after its playback instead.
 The filename's extension, if any, is ignored.
 Regardless, a corresponding game version must be set using the aforementioned command line parameters.
 An incorrect version will cause erroneous playback or a crash.
@@ -147,7 +173,7 @@
 .I wl3d
 has been rewritten from scratch, and some parts have been implemented differently from the reference.
 Most importantly, individual data lumps are no longer read and cached as needed, but rather all loaded into memory, uncompressed, and in some cases converted, at startup.
-This bumps the required amount of free memory up to around 4 megabytes, depending on the game version and architecture.
+This bumps the required amount of free memory up to around at least 5 megabytes, depending on the game version, architecture and window size.
 In addition, a single executable handles all supported game versions.
 .PP
 Intro screens are now additional data files to be loaded on start up, rather than being compiled in, and must therefore be installed in the
@@ -156,16 +182,25 @@
 .PP
 Copy protection code and the Spear of Destiny Jukebox have been excised.
 .PP
-Some cosmetic differences exist.
+Menus are implemented differently, and some have been altered in functionality.
 .PP
 Game keys are no longer set in the options menu, but rather in the config file.
 A single global configuration file is used, rather than a version dependent one.
 Also, while savegames are in a compatible format, config files are not.
 .SH FILES
-.TF /sys/games/lib/wl3d/*
+.TF /sys/games/lib/wl3d/intro.wl6
 .TP
-.B /sys/games/lib/wl3d/*
-wl3d data files
+.B /sys/games/lib/wl3d/
+default wl3d data directory
+.TP
+.B /sys/games/lib/wl3d/intro.wl6
+.B wl6/wl1
+intro screen
+.TP
+.B /sys/games/lib/wl3d/intro.sod
+.B sdm/sod
+intro screen
+.PD
 .SH "SEE ALSO"
 .IR doom (1) ,
 .IR opl2 (1) ,
@@ -189,9 +224,9 @@
 Little is done in case the program is unable to run at a framerate of 70 Hz.
 .PD
 .SS Engine bugs
-Correct demo playback depends on the sound settings used during recording.
+Correct demo playback depends on the sound and view size settings used during recording.
 Different settings on playback may cause desynchronization.
-.PD
+.PP
 Spawned projectiles are not properly cleared when removed and may cause aberrant behavior and demo desynchronization.
 .SH HISTORY
 id Software's Wolfenstein 3-D was released for
--- a/man/6/wl3d
+++ b/man/6/wl3d
@@ -324,6 +324,8 @@
 is used in conjunction with
 .B vgadict
 to read and uncompress each lump upon retrieval.
+Pixel data is usually encoded as a palette index,
+and is used in conjunction with a 256 color palette.
 .SS Vgahead
 .RS
 .IR off [ np ][3]
@@ -361,7 +363,8 @@
 .I np
 pictures, retrieved from
 .IR pic .
-.I Np can be obtained from
+.I Np
+can be obtained from
 .IR pt 's
 uncompressed size.
 The following sections detail each lump type.
@@ -384,7 +387,7 @@
 containing its pixel data.
 The data is an array of bytes of size
 .I dy
-.L *
+.SM *
 .IR dx [ n ],
 to be translated to the character's location on the screen.
 A pixel's color is overwritten with the engine's current foreground color when a non-zero byte in the character's pixel data occurs.
@@ -473,19 +476,29 @@
 contain player input for the duration of the frame
 and correspond respectively to pressed game keys, total horizontal movement (turning) and total vertical movement (forward displacement) deltas.
 .I Bt
-is a 8-bit array of the main game keys, regardless of input method.
+is an 8-bit array of the main game keys, regardless of input method.
 These are, from least to most significant bit:
 fire, strafe, run, open, knife, pistol, machine gun and gatling gun.
 The movement deltas are bounded from -100 to 100.
 .SS Static data
-Some of the graphics data is stored in the executable and thus cannot be altered.
+Some of the graphics data is stored in the executable and thus cannot be altered
+without modifying it or the loaded object files.
 These are the base color palette and intro screen.
-The intro screen is a static screen displayed on startup while verifying available memory and hardware, changed depending on the results.
 Each have a
 .B wl1/wl6
 and a
 .B sdm/sod
 version, but only one is present.
+.PP
+The base color palette is stored as any other palette, and is the one used in most circumstances.
+Several other palettes are generated based on it,
+notably for screen flashes and fade effects.
+.PP
+The intro screen is a static screen displayed on startup while verifying available memory and hardware,
+then changed depending on the results.
+It is an uncompressed 320x200 graphic lump.
+.BR wl3d (1)
+separates the intro screen from the binary as a distinct file formatted as a 320x200 byte array, and loaded on startup.
 .SS Palettes
 .RS
 {
@@ -522,16 +535,80 @@
 for file offsets, and
 .IR sz ,
 for lengths in bytes.
+A chunk of size 0 is skipped.
+This is permitted when the specific lump is never referenced,
+which can occur in the
+.B wl1
+and
+.B sdm
+versions, where only a limited number of maps and resources are used.
+Attempting to load a sparse lump will cause a crash.
 .PP
 The rest of the file contains section data.
 .SS Wall textures
-[words]
+Wall tiles are 64x64 byte arrays of palette indices.
+Because they are drawn vertically, they are stored as an array of coloumns.
+In other words, if drawn as is using a given palette,
+the tile would appear rotated by -90° then flipped along its vertical axis.
+The last 8 wall textures are door textures.
 .SS Sprites
-[words]
+.RS
+.IR lx [2]
+.IR rx [2]
+.IR cofs [ rx-lx+1 ][2]
+.IR data []
+.br
+.BR cmd :
+{
+.IR se [2] po [2] ss [2]
+}[]
+.IR nul [2]
+.RE
+.PP
+Sprites are stored as variable-length arrays of offsets and visible pixel data,
+with an implicit maximal size of 64x64.
+.IR Lx
+and
+.IR rx
+define the 0-indexed left and right-most coloumns containing visible pixels,
+and must respect the following restrictions:
+.PP
+.RS
+.I lx  ∈ {0,1,...,63}
+.br
+.I rx ∈ {32,33,...,63}
+.br
+.I lx ≤ rx
+.RE
+.PP
+Sprites are drawn centered on the 32nd coloumn.
+A left bound equal to or greater than 32 will offset the sprite to the right.
+.PP
+The following variable-length array,
+.IR cofs ,
+contains one offset into sprite data for each visible coloumn.
+Each offset is set from the beginning of the lump, and points to a
+.I cmd
+array.
+.I Ss / 2
+and
+.I se / 2
+are, respectively, an upper and lower bound,
+defining a contiguous vertical strip of pixels to draw within a coloumn, with
+.I po + ss
+an offset into the sprite lump pointing to the strip's palette indices.
+The
+.I cmd
+array is terminated by a 16-bit wide zero.
+Since
+.I ss
+and
+.I se
+are used as word table offsets, they are multiplied by two.
 .SS Raw pcm
 .RS
 {
-.IR chunk [ size/4096 ][]
+.IR chunk [ (size-1)/4096+1 ][]
 .RI }[ npcm ]
 {
 .IR index [2]
@@ -551,20 +628,31 @@
 .I Size
 is the sum in bytes of the lengths of the lump's chunks.
 .PP
-The references for each pcm sound effect (different than those for regular sound effects), as well as their number, are hardcoded in the engine:
+The valid references for each pcm sound effect (different than those for regular sound effects), as well as their number, are hardcoded in the engine:
 .TF wl1
 .TP
 .B wl1
-21 pcms
+46 pcms (20 non empty)
 .TP
 .B wl6
 46 pcms
 .TP
 .B sdm
-26 pcms
+40 pcms (25 non empty)
 .TP
 .B sod
 40 pcms
+.PD
+.PP
+However, neither
+.I npcm
+nor the pcm table actually reflect this number.
+The number in parentheses indicates the actual number of valid pcm lumps for versions
+which may contain empty chunks.
+These are not contiguous,
+and care must be taken to skip all zero-sized chunks referencing each individual sparse
+pcm lump,
+as indicated in the pcm table.
 .SH "CONFIGURATION FILE AND HIGHSCORES"
 [words]
 .SH "SEE ALSO"
--- a/map.c
+++ b/map.c
@@ -41,9 +41,9 @@
 	case Rclip2:
 		break;
 	case Rblock:
-		tl->o = nil;	
+		tl->o = nil;
 		tl->to = 1;
-		/* wet floor */
+		break;
 	case Rcross:
 	case Rchalice:
 	case Rbible:
@@ -58,7 +58,10 @@
 		break;
 	}
 	stce->tl = tl;
-	stce->spr = sprs + (stctype[n] == Rclip2 ? 28 : 2+n);
+	n = stctype[n] == Rclip2 ? 28 : 2+n;
+	stce->spr = sprs + n;
+	if(stce->spr == nil)
+		sysfatal("spawnstc: missing static sprite %d\n", n);
 	if(++stce == stcs+Nstc)
 		sysfatal("static object overflow");
 }
@@ -720,8 +723,8 @@
 void
 drop(Tile *tl, int n)
 {
+	int sn, *sti;
 	Static *s;
-	int *sti;
 
 	for(sti=stctype; sti<stctype+nelem(stctype); sti++)
 		if(*sti == n)
@@ -737,7 +740,10 @@
 	if(s >= stcs+nelem(stcs))
 		return;
 	s->tl = tl;
-	s->spr = sprs + (n == Rclip2 ? 28 : 2+(sti-stctype));
+	sn = n == Rclip2 ? 28 : 2+(sti-stctype);
+	s->spr = sprs + sn;
+	if(s->spr == nil)
+		sysfatal("drop: missing static sprite %d\n", sn);
 	s->f = OFbonus;
 	s->item = n;
 }
--- a/rend.c
+++ b/rend.c
@@ -6,14 +6,11 @@
 s32int sint[360+90], *cost;
 
 typedef struct Vis Vis;
-struct Vis{
-	s16int vwdx;
-	s16int vwdy;
-	Dat *spr;
-};
-
+typedef struct Scaler Scaler;
 enum{
 	Nvis = 50,
+	Nscal = 256+1,
+	Wdxy = 64,
 	Fineθ = 3600,
 	Dfoclen = 0x5700,
 	Dglob = 0x10000,
@@ -20,6 +17,11 @@
 	Dtile = 0x2000,
 	Dobj = 0x4000
 };
+struct Vis{
+	s16int vwx;
+	s16int vwdy;
+	Spr *spr;
+};
 #define	Pi	3.141592657
 static float Rad = (float)Fineθ / 2 / Pi;
 
@@ -30,30 +32,159 @@
 static s32int xin, yin;
 static int dtx, dty;
 static u16int ∂xdown, ∂xup, ∂ydown, ∂yup;
-static int lastside;
 
+struct Scaler{
+	int skip;
+	int ps;
+	int pe;
+	int dx;
+};
+static Scaler scals[Nscal][Wdxy+1], *sce;
+static uchar *scps, *scts;
+static int scx, scdx, scdy;
+static int waldy[Vw];
+static s32int lastin;
+static int lasttile, lastside;
+
 static void
-scalespr(int, int, int)
+scalscol(Scaler *ss, Sprc *c, int dx)
 {
+	int ps, pe, w;
+	uchar n, *d, *sp, *ds;
+	Scaler *s, *se;
+
+	ds = pxb + vw.ofs + scx;
+	se = ss + c->e;
+	while(se != ss){
+		sp = c->p;
+		s = ss + c->s;
+		for(; s<se; s++, sp++){
+			if(s->skip)
+				continue;
+			n = *sp;
+			for(ps=s->ps, pe=s->pe; ps<pe; ps++){
+				if(ps >= vw.dy)
+					break;
+				if(ps < 0)
+					continue;
+				d = ds + ps * Vw;
+				w = dx;
+				while(w-- > 0)
+					*d++ = n;
+			}
+		}
+		c++;
+		se = ss + c->e;
+	}
 }
 
 static void
-scalevis(Vis *)
+scalvis(Vis *v)
 {
+	int x, dx, lx, rx, *lw, *rw;
+	Scaler *ss, *s, *se;
+	Spr *spr;
+	Sprc **c;
+
+	ss = scals[v->vwdy >> 3];
+	if(ss == scals[0] || ss > sce)
+		return;
+	spr = v->spr;
+	lx = spr->lx;
+	rx = spr->rx;
+	scx = v->vwx;
+	if(lx < 32){
+		s = ss + lx;
+		se = ss + 32;
+		while(s < se)
+			scx -= s++->dx;
+	}else{
+		s = ss + 32;
+		se = ss + lx;
+		while(s < se)
+			scx += s++->dx;
+	}
+	c = spr->cs;
+	for(s=ss+lx, se=ss+rx+1; s<se && scx<vw.dx; c++, scx+=dx){
+		dx = s++->dx;
+		if(dx == 0)
+			continue;
+		if(dx == 1){
+			if(scx >= 0 && waldy[scx] < v->vwdy)
+				scalscol(ss, *c, 1);
+			continue;
+		}
+		x = scx + dx;
+		if(scx < 0){
+			if(x <= 0)
+				continue;
+			dx = x;
+			scx = 0;
+		}else if(x > vw.dx)
+			dx = vw.dx - scx;
+		lw = waldy + scx;
+		rw = lw + dx - 1;
+		if(*lw < v->vwdy){
+			if(*rw < v->vwdy){
+				scalscol(ss, *c, dx);
+				continue;
+			}
+			while(*rw >= v->vwdy)
+				rw--, dx--;
+			scalscol(ss, *c, dx);
+			break;
+		}else{
+			if(*rw >= v->vwdy)
+				continue;
+			while(*lw >= v->vwdy){
+				lw++, scx++;
+				dx--;
+			}
+			scalscol(ss, *c, dx);
+		}
+	}
 }
 
 static void
+scalcol(void)
+{
+	int i, n, x, dx;
+	uchar c, *ds, *d;
+	Scaler *s;
+
+	s = scals[(waldy[scx] & 0xfff8) >> 3];
+	if(s > sce)
+		s = sce;
+	ds = pxb + vw.ofs + scx;
+	for(x=0; x<Wdxy; x++, s++){
+		if(s->skip)
+			continue;
+		c = scps[x];
+		for(i=s->ps, n=s->pe; i<n; i++){
+			if(i >= vw.dy)
+				break;
+			if(i < 0)
+				continue;
+			d = ds + i * Vw;
+			dx = scdx;
+			while(dx-- > 0)
+				*d++ = c;
+		}
+	}
+}
+
+static void
 topspr(void)
 {
 	if(ver < SDM && gm.won){
 		if(oplr->s == stt+GSplrcam && mtc & 32)
-			scalespr(SPcam, vw.dx/2, vw.dy+1);
+			scalspr(SPcam, vw.dx/2, vw.dy+1);
 		return;
 	}
 	if(gm.w != -1)
-		scalespr(wspr[gm.w] + gm.wfrm, vw.dx/2, vw.dy+1);
+		scalspr(wspr[gm.w] + gm.wfrm, vw.dx/2, vw.dy+1);
 	if(gm.record || gm.demo)
-		scalespr(SPdemo, vw.dx/2, vw.dy+1);
+		scalspr(SPdemo, vw.dx/2, vw.dy+1);
 }
 
 static int
@@ -83,7 +214,8 @@
 		v->vwdy = 0;
 		return 0;
 	}
-	v->vwdx = vw.mid + cy * prjw / cx;
+	v->vwx = vw.mid + cy * prjw / cx;
+	/* low 3 bits are fractional */
 	v->vwdy = prjh / (cx >> 8);
 	return cx < Dtlglobal && abs(cy) < Dtlglobal / 2;
 }
@@ -109,12 +241,13 @@
 }
 
 static void
-scaleall(void)
+scalobj(void)
 {
+	int i, n, min;
 	Obj *o;
 	Tile *tl;
 	Static *st;
-	Vis viss[Nvis], *v, *w, *e, *m;
+	Vis viss[Nvis], *v, *e, *m;
 
 	memset(viss, 0, sizeof viss);
 	e = viss;
@@ -149,11 +282,9 @@
 			if(o->vwdy == 0)
 				continue;
 			o->f |= OFvis;
-			e->vwdx = o->vwdx;
+			e->vwx = o->vwdx;
 			e->vwdy = o->vwdy;
 			e->spr = o->s->spr;
-			if(e->spr == nil)
-				e->spr = sprs + o->sdt;
 			if(o->s->rot)
 				e->spr += rot(o);
 			if(e < viss + nelem(viss)-1)
@@ -161,20 +292,23 @@
 		}else
 			o->f &= ~OFvis;
 	}
-	for(v=viss; v<e; v++){
-		for(w=v, m=v; w<=e; w++)
-			if(w->vwdy < m->vwdy)
-				m = w;
-		scalevis(m);
-		if(v != m)
-			memcpy(m, v, sizeof *m);
+	for(i=0, n=e-viss; i<n; i++){
+		min = 32000;
+		v = m = viss;
+		while(v < e){
+			if(v->vwdy < min){
+				min = v->vwdy;
+				m = v;
+			}
+			v++;
+		}
+		scalvis(m);
+		m->vwdy = 32000;
 	}
-	if(e != viss)
-		scalevis(e);
 }
 
 static s16int
-walldy(s32int xin, s32int yin)
+walldy(void)
 {
 	s32int cx, dy;
 
@@ -188,7 +322,7 @@
 static void
 vwall(int i, int tx, int ty, int tile)
 {
-	s16int p;
+	int n;
 	u16int tex;
 
 	tex = yin >> 4 & 0xfc0;
@@ -196,50 +330,43 @@
 		tex = 0xfc0 - tex;
 		xin += Dtlglobal;
 	}
-	p = 0;
-	USED(tex, p, tx, ty, tile, xin, i);
-#ifdef DICKS
-	wallheight[i] = walldy();
-	if(lastside==1 && lastintercept == tx && lasttilehit == tile){
-		/* in the same wall type as last time, so check for
-		 * optimized draw */
-		if(tex == (u16int)postsource){
-			// wide scale
-			postwidth++;
-			wallheight[i] = wallheight[i-1];
+	waldy[i] = walldy();
+	if(lastside == 1 && lastin == tx && lasttile == tile){
+		if(scps == scts + tex){
+			scdx++;
+			waldy[i] = waldy[i-1];
 		}else{
-			ScalePost();
-			(u16int)postsource = tex;
-			postwidth = 1;
-			postx = i;
+			scalcol();
+			scps = scts + tex;
+			scdx = 1;
+			scx = i;
 		}
 		return;
 	}
-	/* new wall */
-	if(lastside != -1)	/* if not the first scaled post */
-		ScalePost();
-	lastside = true;
-	lastintercept = tx;
-	lasttilehit = tile;
-	postx = i;
-	postwidth = 1;
-
-	if(tile & 0x40){	/* check for adjacent doors */
-		if(tiles[ty][tx-dtx].tl & 0x80)
-			p = SPdoor+3;
+	if(lastside != -1)
+		scalcol();
+	lastside = 1;
+	lastin = tx;
+	lasttile = tile;
+	scx = i;
+	scdx = 1;
+	if(tile & 0x40){
+		if(tiles[ty*Mapdxy + tx-dtx].tl & 0x80)
+			n = drofs + 3;
 		else
-			p = vertwall[tile & ~0x40];
+			n = ((tile & ~0x40) - 1) * 2 + 1;
 	}else
-		p = vertwall[tile];
-	*(((u16int *)&postsource)+1) = (u16int)PM_GetPage(p);
-	(u16int)postsource = tex;
-#endif
+		n = (tile - 1) * 2 + 1;
+	scts = wals[n];
+	if(scts == nil)
+		sysfatal("sparse wall %d\n", n);
+	scps = scts + tex;
 }
 
 static void
 hwall(int i, int tx, int ty, int tile)
 {
-	s16int p;
+	int n;
 	u16int tex;
 
 	tex = xin >> 4 & 0xfc0;
@@ -247,141 +374,130 @@
 		yin += Dtlglobal;
 	else
 		tex = 0xfc0 - tex;
-	p = 0;
-	USED(i, tx, ty, tile, tex, p);
-#ifdef DICKS
-	wallheight[i] = walldy();
-	if(lastside == 0 && lastintercept == ty && lasttilehit == tile){
-		/* in the same wall type as last time, so check for
-		 * optimized draw */
-		if(tex == (u16int)postsource){	/* wide scale */
-			postwidth++;
-			wallheight[i] = wallheight[i-1];
-			return;
+	waldy[i] = walldy();
+	if(lastside == 0 && lastin == ty && lasttile == tile){
+		if(scps == scts + tex){
+			scdx++;
+			waldy[i] = waldy[i-1];
 		}else{
-			ScalePost();
-			(u16int)postsource = tex;
-			postwidth = 1;
-			postx = i;
+			scalcol();
+			scps = scts + tex;
+			scdx = 1;
+			scx = i;
 		}
-	}else{	/* new wall */
-		if(lastside != -1)	/* if not the first scaled post */
-			ScalePost();
-
-		lastside = 0;
-		lastintercept = ty;
-		lasttilehit = tile;
-		postx = i;
-		postwidth = 1;
-		if(tile & 0x40){	/* check for adjacent doors */
-			tx = xin >> Dtlshift;
-			if(tiles[ty-dty][tx].tl & 0x80)
-				p = SPdoor+2;
-			else
-				p = horizwall[tile & ~0x40];
-		}else
-			p = horizwall[tile];
-		*( ((u16int *)&postsource)+1) = (u16int)PM_GetPage(p);
-		(u16int)postsource = tex;
+		return;
 	}
-#endif
+	if(lastside != -1)
+		scalcol();
+	lastside = 0;
+	lastin = ty;
+	lasttile = tile;
+	scx = i;
+	scdx = 1;
+	if(tile & 0x40){
+		tx = xin >> Dtlshift;
+		if(tiles[(ty-dty)*Mapdxy + tx].tl & 0x80)
+			n = drofs + 2;
+		else
+			n = ((tile & ~0x40) - 1) * 2;
+	}else
+		n = (tile - 1) * 2;
+	scts = wals[n];
+	if(scts == nil)
+		sysfatal("sparse wall %d\n", n);
+	scps = scts + tex;
 }
 
 static void
 vdoor(int i, int tile)
 {
-	USED(i, xin, yin, tile);
-#ifdef DICKS
+	int n;
+	u16int tex;
 	Door *d;
-	u16int tex, p;
 
-	wallheight[i] = walldy(xin, yin);
+	waldy[i] = walldy();
 	d = doors + (tile & 0x7f);
 	tex = yin - d->dopen >> 4 & 0xfc0;
-	if(lasttilehit == tile){
-		/* in the same door as last time, so check for optimized draw */
-		if(tex == (u16int)postsource){
-			/* wide scale */
-			postwidth++;
-			wallheight[i] = wallheight[i-1];
-			return;
+	if(lasttile == tile){
+		if(scps == scts + tex){
+			scdx++;
+			waldy[i] = waldy[i-1];
 		}else{
-			ScalePost ();
-			(u16int)postsource = tex;
-			postwidth = 1;
-			postx = i;
+			scalcol();
+			scps = scts + tex;
+			scdx = 1;
+			scx = i;
 		}
-	}else{
-		if (lastside != -1)	/* if not the first scaled post */
-			ScalePost ();		/* draw last post */
-		/* first pixel in this door */
-		lastside = 2;
-		lasttile = tile;
-		postx = i;
-		postwidth = 1;
-		switch(d->lock){
-		case DRunlk: p = SPdoor; break;
-		case DRlock1:
-		case DRlock2:
-		case DRlock3:
-		case DRlock4: p = SPdoor+6; break;
-		case DRup: p = SPdoor+4; break;
-		}
-		*( ((u16int *)&postsource)+1) = (u16int)PM_GetPage(p+1);
-		(u16int)postsource = tex;
+		return;
 	}
-#endif
+	if(lastside != -1)
+		scalcol();
+	lastside = 2;
+	lasttile = tile;
+	scx = i;
+	scdx = 1;
+	n = 1;
+	switch(d->lock){
+	case DRunlk: n += drofs; break;
+	case DRlock1:
+	case DRlock2:
+	case DRlock3:
+	case DRlock4: n += drofs + 6; break;
+	case DRup: n += drofs + 4; break;
+	}
+	scts = wals[n];
+	if(scts == nil)
+		sysfatal("sparse wall %d\n", n);
+	scps = scts + tex;
 }
 
 static void
 hdoor(int i, int tile)
 {
-	USED(i, xin, yin, tile);
-#ifdef DICKS
+	int n;
+	u16int tex;
 	Door *d;
-	u16int tex, p;
 
-	wallheight[i] = walldy(xin, yin);
+	waldy[i] = walldy();
 	d = doors + (tile & 0x7f);
 	tex = xin - d->dopen >> 4 & 0xfc0;
-	if(lasttilehit == tile){
-		/* in the same door as last time, so check for optimized draw */
-		if(tex == (u16int)postsource){	/* wide scale */
-			postwidth++;
-			wallheight[i] = wallheight[i-1];
-			return;
+	if(lasttile == tile){
+		if(scps == scts + tex){
+			scdx++;
+			waldy[i] = waldy[i-1];
 		}else{
-			ScalePost();
-			(u16int)postsource = tex;
-			postwidth = 1;
-			postx = i;
+			scalcol();
+			scps = scts + tex;
+			scdx = 1;
+			scx = i;
 		}
-	}else{
-		if(lastside != -1)	/* if not the first scaled post */
-			ScalePost();	/* draw last post */
-		/* first pixel in this door */
-		lastside = 2;
-		lasttile = tile;
-		postx = i;
-		postwidth = 1;
-		switch(d->lock){
-		case DRunlk: p = SPdoor; break;
-		case DRlock1:
-		case DRlock2:
-		case DRlock3:
-		case DRlock4: p = SPdoor+6; break;
-		case DRup: p = SPdoor+4; break;
-		}
-		*( ((u16int *)&postsource)+1) = (u16int)PM_GetPage(p);
-		(u16int)postsource = tex;
+		return;
 	}
-#endif
+	if(lastside != -1)
+		scalcol();
+	lastside = 2;
+	lasttile = tile;
+	scx = i;
+	scdx = 1;
+	n = 0;
+	switch(d->lock){
+	case DRunlk: n = drofs; break;
+	case DRlock1:
+	case DRlock2:
+	case DRlock3:
+	case DRlock4: n = drofs + 6; break;
+	case DRup: n = drofs + 4; break;
+	}
+	scts = wals[n];
+	if(scts == nil)
+		sysfatal("sparse wall %d\n", n);
+	scps = scts + tex;
 }
 
 static void
 vpush(int i, int tile)
 {
-	s16int p;
+	int n;
 	u16int tex, ofs;
 
 	tex = yin >> 4 & 0xfc0;
@@ -391,40 +507,35 @@
 		tex = 0xfc0 - tex;
 	}else
 		xin += ofs;
-	p = 0;
-	USED(i, xin, tile, p, tex, ofs);
-#ifdef DICKS
-	wallheight[i] = walldy(xin, yin);
-	if(lasttilehit == tile){
-		/* in the same wall type as last time, so check for
-		 * optimized draw */
-		if(tex == (u16int)postsource){	/* wide scale */
-			postwidth++;
-			wallheight[i] = wallheight[i-1];
-			return;
+	waldy[i] = walldy();
+	if(lasttile == tile){
+		if(scps == scts + tex){
+			scdx++;
+			waldy[i] = waldy[i-1];
 		}else{
-			ScalePost();
-			(u16int)postsource = tex;
-			postwidth = 1;
-			postx = i;
+			scalcol();
+			scps = scts + tex;
+			scdx = 1;
+			scx = i;
 		}
-	}else{	/* new wall */
-		if(lastside != -1)	// if not the first scaled post
-			ScalePost ();
-		lasttile = tile;
-		postx = i;
-		postwidth = 1;
-		p = vertwall[tile&63];
-		*( ((u16int *)&postsource)+1) = (u16int)PM_GetPage(p);
-		(u16int)postsource = tex;
+		return;
 	}
-#endif
+	if(lastside != -1)
+		scalcol();
+	lasttile = tile;
+	scx = i;
+	scdx = 1;
+	n = ((tile & 63) - 1) * 2 + 1;
+	scts = wals[n];
+	if(scts == nil)
+		sysfatal("sparse wall %d\n", n);
+	scps = scts + tex;
 }
 
 static void
 hpush(int i, int tile)
 {
-	s16int p;
+	int n;
 	u16int tex, ofs;
 
 	tex = xin >> 4 & 0xfc0;
@@ -435,34 +546,29 @@
 		tex = 0xfc0 - tex;
 		yin += ofs;
 	}
-	p = 0;
-	USED(i, yin, tile, p, tex, ofs);
-#ifdef DICKS
-	wallheight[i] = walldy(xin, yin);
-	if(lasttilehit == tile){
-		/* in the same wall type as last time, so check for
-		 * optimized draw */
-		if(tex == (u16int)postsource){	/* wide scale */
-			postwidth++;
-			wallheight[i] = wallheight[i-1];
-			return;
+	waldy[i] = walldy();
+	if(lasttile == tile){
+		if(scps == scts + tex){
+			scdx++;
+			waldy[i] = waldy[i-1];
 		}else{
-			ScalePost();
-			(u16int)postsource = tex;
-			postwidth = 1;
-			postx = i;
+			scalcol();
+			scps = scts + tex;
+			scdx = 1;
+			scx = i;
 		}
-	}else{	/* new wall */
-		if(lastside != -1)	/* if not the first scaled post */
-			ScalePost();
-		lasttile = tile;
-		postx = i;
-		postwidth = 1;
-		p = horizwall[tile&63];
-		*( ((u16int *)&postsource)+1) = (u16int)PM_GetPage(p);
-		(u16int)postsource = tex;
+		return;
 	}
-#endif
+	if(lastside != -1)
+		scalcol();
+	lasttile = tile;
+	scx = i;
+	scdx = 1;
+	n = ((tile & 63) - 1) * 2;
+	scts = wals[n];
+	if(scts == nil)
+		sysfatal("sparse wall %d\n", n);
+	scps = scts + tex;
 }
 
 static void
@@ -474,6 +580,19 @@
 	u16int dr, x, y, ∂x, ∂y, tilehit;
 	s32int rs, dx, dy;
 
+	vw.θ = oplr->θ;
+	midθ = vw.θ * (Fineθ / 360);
+	vw.sin = sint[vw.θ];
+	vw.cos = cost[vw.θ];
+	vw.x = oplr->x - ffs(Dfoclen, vw.cos);
+	vw.y = oplr->y + ffs(Dfoclen, vw.sin);
+	vw.tx = vw.x >> Dtlshift;
+	vw.ty = vw.y >> Dtlshift;
+	∂xdown = vw.x & Dtlglobal - 1;
+	∂xup = Dtlglobal - ∂xdown;
+	∂ydown = vw.y & Dtlglobal - 1;
+	∂yup = Dtlglobal - ∂ydown;
+	lastside = -1;
 	i = 0;
 	tilehit = 0;
 loop:
@@ -608,84 +727,85 @@
 next:
 	if(++i < vw.dx)
 		goto loop;
+	scalcol();
 }
 
 static void
-ScalePost(void)
+calcscal(Scaler *s, int dy)
 {
-#ifdef DICKS
-	ax = SCREENSEG;
-	es = ax;
-	bx = postx >> 1;
+	int i, step, fix, top, ps, pe;
 
-	asm mov	bp,WORD PTR [wallheight+bx]	// fractional height (low 3 bits frac)
-	asm and	bp,0xfff8			// bp = heightscaler*4
-	asm shr	bp,1
-	asm cmp	bp,[maxscaleshl2]
-	asm jle	heightok
-	asm mov	bp,[maxscaleshl2]
-heightok:
-	asm add	bp,OFFSET fullscalefarcall
+	top = (vw.dy - dy) / 2;
+	step = (dy << 16) / 64;
+	fix = 0;
+	for(i=0; i<nelem(scals[0]); i++, s++){
+		ps = (fix >> 16) + top;
+		fix += step;
+		pe = (fix >> 16) + top;
+		s->dx = pe > ps ? pe - ps : 0;
+		s->skip = ps == pe || pe < 0 || ps >= vw.dy || i == nelem(scals[0])-1;
+		if(s->skip)
+			continue;
+		s->ps = ps;
+		s->pe = pe;
+	}
+}
+static void
+scaltab(int maxdy)
+{
+	int save, dy;
+	Scaler (*s)[nelem(scals[0])];
 
-	// scale a byte wide strip of wall
-	asm mov	bx,[postx]
-	asm mov	di,bx
-	asm shr	di,2		// X in bytes
-	asm add	di,[bufferofs]
-
-	asm and	bx,3
-	asm shl	bx,3		// bx = pixel*8+pixwidth
-	asm add	bx,[postwidth]
-
-	asm mov	al,BYTE PTR [mapmasks1-1+bx]	// -1 because no widths of 0
-	asm mov	dx,SC_INDEX+1
-	asm out	dx,al		// set bit mask register
-	asm lds	si,DWORD PTR [postsource]
-	asm call DWORD PTR [bp]	// scale the line of pixels
-
-	asm mov	al,BYTE PTR [ss:mapmasks2-1+bx]   // -1 because no widths of 0
-	asm or	al,al
-	asm jz	nomore
-
-	// draw a second byte for vertical strips that cross two bytes
-	asm inc	di
-	asm out	dx,al			// set bit mask register
-	asm call DWORD PTR [bp]		// scale the line of pixels
-
-	asm mov al,BYTE PTR [ss:mapmasks3-1+bx]	// -1 because no widths of 0
-	asm or	al,al
-	asm jz	nomore
-
-	// draw a third byte for vertical strips that cross three bytes
-	asm inc	di
-	asm out	dx,al			// set bit mask register
-	asm call DWORD PTR [bp]		// scale the line of pixels
-
-nomore:
-	asm mov	ax,ss
-	asm mov	ds,ax
-#endif
+	dy = 1;
+	memset(scals, 0, sizeof scals);
+	s = scals + 1;
+	save = vw.dy / 2;
+	while(dy <= maxdy){
+		calcscal(*s++, dy * 2);
+		if(dy >= save){
+			memcpy(s[0], s[-1], sizeof scals[0]);
+			memcpy(s[1], s[-1], sizeof scals[0]);
+			s += 2, dy += 2;
+		}
+		dy++;
+	}
+	memcpy(scals, scals+1, sizeof *scals);
+	sce = scals[dy-1];
 }
 
-static void
-walls(void)
+void
+scalspr(int n, int x, int dy)
 {
-	vw.θ = oplr->θ;
-	midθ = vw.θ * (Fineθ / 360);
-	vw.sin = sint[vw.θ];
-	vw.cos = cost[vw.θ];
-	vw.x = oplr->x - ffs(Dfoclen, vw.cos);
-	vw.y = oplr->y + ffs(Dfoclen, vw.sin);
-	vw.tx = vw.x >> Dtlshift;
-	vw.ty = vw.y >> Dtlshift;
-	∂xdown = vw.x & Dtlglobal - 1;
-	∂xup = Dtlglobal - ∂xdown;
-	∂ydown = vw.y & Dtlglobal - 1;
-	∂yup = Dtlglobal - ∂ydown;
+	int dx, lx, rx;
+	Scaler *ss, *s, *se;
+	Spr *spr;
+	Sprc **c;
 
-	lastside = -1;	// the first pixel is on a new wall
-	raytrace();
-	ScalePost();	// no more optimization on last post
+	spr = sprs + n;
+	if(spr == nil)
+		sysfatal("scalspr: missing sprite %d\n", n);
+	dy >>= 1;
+	ss = scals[dy];
+	lx = spr->lx;
+	rx = spr->rx;
+	scx = x;
+	if(lx < 32){
+		s = ss + lx;
+		se = ss + 32;
+		while(s < se)
+			scx -= s++->dx;
+	}else{
+		s = ss + 32;
+		se = ss + lx;
+		while(s < se)
+			scx += s++->dx;
+	}
+	c = spr->cs;
+	for(s=ss+lx, se=ss+rx+1; s<se; c++, scx+=dx){
+		dx = s++->dx;
+		if(dx != 0)
+			scalscol(ss, *c, dx);
+	}
 }
 
 s32int
@@ -717,8 +837,8 @@
 	for(tl=tiles; tl<tiles+nelem(tiles); tl++)
 		tl->vis = 0;
 	clear();
-	walls();
-	scaleall();
+	raytrace();
+	scalobj();
 	topspr();
 }
 
@@ -745,7 +865,7 @@
 		*q-- = an;
 	}
 
-	//SetupScaling(vw.dx * 1.5);
+	scaltab((vw.dx * 1.5) / 2);
 }
 
 void
--- a/scale.c
+++ /dev/null
@@ -1,719 +1,0 @@
-#define OP_RETF	0xcb
-
-/*
-=============================================================================
-
-						  GLOBALS
-
-=============================================================================
-*/
-
-t_compscale _seg *scaledirectory[MAXSCALEHEIGHT+1];
-s32int			fullscalefarcall[MAXSCALEHEIGHT+1];
-
-s16int			maxscale,maxscaleshl2;
-
-/*
-=============================================================================
-
-						  LOCALS
-
-=============================================================================
-*/
-
-t_compscale 	_seg *work;
-u16int BuildCompScale (s16int height, uchar **finalspot);
-
-s16int			stepbytwo;
-
-//===========================================================================
-
-/*
-==============
-=
-= BadScale
-=
-==============
-*/
-
-void far BadScale (void)
-{
-	Quit ("BadScale called!");
-}
-
-
-void SetupScaling (s16int maxscaleheight)
-{
-	s16int		i,x,y;
-	u8int	far *dest;
-
-The dynamically compiled scaling routines are now a Bad Thing.  
-On uncached machines (the original target) they are the fastest 
-possible way to scale walls, but on modern processors you just 
-wind up thrashing the code cash and wrecking performance.  
-A simple looping texture mapper would be faster on 486+ machines.
-
-	maxscaleheight/=2;			// one scaler every two pixels
-
-	maxscale = maxscaleheight-1;
-	maxscaleshl2 = maxscale<<2;
-
-//
-// free up old scalers
-//
-	for (i=1;i<MAXSCALEHEIGHT;i++)
-	{
-		if (scaledirectory[i])
-			MM_FreePtr (&(uchar *)scaledirectory[i]);
-		if (i>=stepbytwo)
-			i += 2;
-	}
-	memset (scaledirectory,0,sizeof(scaledirectory));
-
-//
-// build the compiled scalers
-//
-	stepbytwo = vw.dy/2;	// save space by double stepping
-	MM_GetPtr (&(uchar *)work,20000);
-
-	for (i=1;i<=maxscaleheight;i++)
-	{
-		BuildCompScale (i*2,&(uchar *)scaledirectory[i]);
-		if (i>=stepbytwo)
-			i+= 2;
-	}
-	MM_FreePtr (&(uchar *)work);
-
-//
-// compact memory and lock down scalers
-//
-	for (i=1;i<=maxscaleheight;i++)
-	{
-		MM_SetLock (&(uchar *)scaledirectory[i],true);
-		fullscalefarcall[i] = (u16int)scaledirectory[i];
-		fullscalefarcall[i] <<=16;
-		fullscalefarcall[i] += scaledirectory[i]->codeofs[0];
-		if (i>=stepbytwo)
-		{
-			scaledirectory[i+1] = scaledirectory[i];
-			fullscalefarcall[i+1] = fullscalefarcall[i];
-			scaledirectory[i+2] = scaledirectory[i];
-			fullscalefarcall[i+2] = fullscalefarcall[i];
-			i+=2;
-		}
-	}
-	scaledirectory[0] = scaledirectory[1];
-	fullscalefarcall[0] = fullscalefarcall[1];
-
-//
-// check for oversize wall drawing
-//
-	for (i=maxscaleheight;i<MAXSCALEHEIGHT;i++)
-		fullscalefarcall[i] = (uintptr)BadScale;
-}
-
-//===========================================================================
-
-/*
-========================
-=
-= BuildCompScale
-=
-= Builds a compiled scaler object that will scale a 64 tall object to
-= the given height (centered vertically on the screen)
-=
-= height should be even
-=
-= Call with
-= ---------
-= DS:SI		Source for scale
-= ES:DI		Dest for scale
-=
-= Calling the compiled scaler only destroys AL
-=
-========================
-*/
-
-u16int BuildCompScale (s16int height, uchar **finalspot)
-{
-	a simple looping texture mapper would be better, simpler, faster
-
-	u8int		far *code;
-
-	s16int			i;
-	s32int		fix,step;
-	u16int	src,totalscaled,totalsize;
-	s16int			startpix,endpix,toppix;
-
-
-	step = ((s32int)height<<16) / 64;
-	code = &work->code[0];
-	toppix = (vw.dy-height)/2;
-	fix = 0;
-
-	for (src=0;src<=64;src++)
-	{
-		startpix = fix>>16;
-		fix += step;
-		endpix = fix>>16;
-
-		if (endpix>startpix)
-			work->width[src] = endpix-startpix;
-		else
-			work->width[src] = 0;
-
-//
-// mark the start of the code
-//
-		work->codeofs[src] = FP_OFF(code);
-
-//
-// compile some code if the source pixel generates any screen pixels
-//
-		startpix+=toppix;
-		endpix+=toppix;
-
-		if (startpix == endpix || endpix < 0 || startpix >= vw.dy || src == 64)
-			continue;
-
-	//
-	// mov al,[si+src]
-	//
-		*code++ = 0x8a;
-		*code++ = 0x44;
-		*code++ = src;
-
-		for (;startpix<endpix;startpix++)
-		{
-			if (startpix >= vw.dy)
-				break;						// off the bottom of the view area
-			if (startpix < 0)
-				continue;					// not into the view area
-
-		//
-		// mov [es:di+heightofs],al
-		//
-			*code++ = 0x26;
-			*code++ = 0x88;
-			*code++ = 0x85;
-			*((u16int far *)code)++ = startpix*SCREENBWIDE;
-		}
-
-	}
-
-//
-// retf
-//
-	*code++ = 0xcb;
-
-	totalsize = FP_OFF(code);
-	MM_GetPtr (finalspot,totalsize);
-	_fmemcpy ((u8int _seg *)(*finalspot),(u8int _seg *)work,totalsize);
-
-	return totalsize;
-}
-
-
-/*
-=======================
-=
-= ScaleLine
-=
-= linescale should have the high word set to the segment of the scaler
-=
-=======================
-*/
-
-extern	s16int			slinex,slinewidth;
-extern	u16int	far *linecmds;
-extern	s32int		linescale;
-extern	u16int	maskword;
-
-u8int	mask1,mask2,mask3;
-
-
-void near ScaleLine (void)
-{
-asm	mov	cx,WORD PTR [linescale+2]
-asm	mov	es,cx						// segment of scaler
-
-asm	mov bp,WORD PTR [linecmds]
-asm	mov	dx,SC_INDEX+1				// to set SC_MAPMASK
-
-asm	mov	bx,[slinex]
-asm	mov	di,bx
-asm	shr	di,2						// X in bytes
-asm	add	di,[bufferofs]
-asm	and	bx,3
-asm	shl	bx,3
-asm	add	bx,[slinewidth]				// bx = (pixel*8+pixwidth)
-asm	mov	al,BYTE [mapmasks3-1+bx]	// -1 because pixwidth of 1 is first
-asm	mov	ds,WORD PTR [linecmds+2]
-asm	or	al,al
-asm	jz	notthreebyte				// scale across three bytes
-asm	jmp	threebyte
-notthreebyte:
-asm	mov	al,BYTE PTR ss:[mapmasks2-1+bx]	// -1 because pixwidth of 1 is first
-asm	or	al,al
-asm	jnz	twobyte						// scale across two bytes
-
-//
-// one byte scaling
-//
-asm	mov	al,BYTE PTR ss:[mapmasks1-1+bx]	// -1 because pixwidth of 1 is first
-asm	out	dx,al						// set map mask register
-
-scalesingle:
-
-asm	mov	bx,[ds:bp]					// table location of rtl to patch
-asm	or	bx,bx
-asm	jz	linedone					// 0 signals end of segment list
-asm	mov	bx,[es:bx]
-asm	mov	dl,[es:bx]					// save old value
-asm	mov	BYTE PTR es:[bx],OP_RETF	// patch a RETF in
-asm	mov	si,[ds:bp+4]				// table location of entry spot
-asm	mov	ax,[es:si]
-asm	mov	WORD PTR ss:[linescale],ax	// call here to start scaling
-asm	mov	si,[ds:bp+2]				// corrected top of shape for this segment
-asm	add	bp,6						// next segment list
-
-asm	mov	ax,SCREENSEG
-asm	mov	es,ax
-asm	call ss:[linescale]				// scale the segment of pixels
-
-asm	mov	es,cx						// segment of scaler
-asm	mov	BYTE PTR es:[bx],dl			// unpatch the RETF
-asm	jmp	scalesingle					// do the next segment
-
-
-//
-// done
-//
-linedone:
-asm	mov	ax,ss
-asm	mov	ds,ax
-return;
-
-//
-// two byte scaling
-//
-twobyte:
-asm	mov	ss:[mask2],al
-asm	mov	al,BYTE PTR ss:[mapmasks1-1+bx]	// -1 because pixwidth of 1 is first
-asm	mov	ss:[mask1],al
-
-scaledouble:
-
-asm	mov	bx,[ds:bp]					// table location of rtl to patch
-asm	or	bx,bx
-asm	jz	linedone					// 0 signals end of segment list
-asm	mov	bx,[es:bx]
-asm	mov	cl,[es:bx]					// save old value
-asm	mov	BYTE PTR es:[bx],OP_RETF	// patch a RETF in
-asm	mov	si,[ds:bp+4]				// table location of entry spot
-asm	mov	ax,[es:si]
-asm	mov	WORD PTR ss:[linescale],ax	// call here to start scaling
-asm	mov	si,[ds:bp+2]				// corrected top of shape for this segment
-asm	add	bp,6						// next segment list
-
-asm	mov	ax,SCREENSEG
-asm	mov	es,ax
-asm	mov	al,ss:[mask1]
-asm	out	dx,al						// set map mask register
-asm	call ss:[linescale]				// scale the segment of pixels
-asm	inc	di
-asm	mov	al,ss:[mask2]
-asm	out	dx,al						// set map mask register
-asm	call ss:[linescale]				// scale the segment of pixels
-asm	dec	di
-
-asm	mov	es,WORD PTR ss:[linescale+2] // segment of scaler
-asm	mov	BYTE PTR es:[bx],cl			// unpatch the RETF
-asm	jmp	scaledouble					// do the next segment
-
-
-//
-// three byte scaling
-//
-threebyte:
-asm	mov	ss:[mask3],al
-asm	mov	al,BYTE PTR ss:[mapmasks2-1+bx]	// -1 because pixwidth of 1 is first
-asm	mov	ss:[mask2],al
-asm	mov	al,BYTE PTR ss:[mapmasks1-1+bx]	// -1 because pixwidth of 1 is first
-asm	mov	ss:[mask1],al
-
-scaletriple:
-
-asm	mov	bx,[ds:bp]					// table location of rtl to patch
-asm	or	bx,bx
-asm	jz	linedone					// 0 signals end of segment list
-asm	mov	bx,[es:bx]
-asm	mov	cl,[es:bx]					// save old value
-asm	mov	BYTE PTR es:[bx],OP_RETF	// patch a RETF in
-asm	mov	si,[ds:bp+4]				// table location of entry spot
-asm	mov	ax,[es:si]
-asm	mov	WORD PTR ss:[linescale],ax	// call here to start scaling
-asm	mov	si,[ds:bp+2]				// corrected top of shape for this segment
-asm	add	bp,6						// next segment list
-
-asm	mov	ax,SCREENSEG
-asm	mov	es,ax
-asm	mov	al,ss:[mask1]
-asm	out	dx,al						// set map mask register
-asm	call ss:[linescale]				// scale the segment of pixels
-asm	inc	di
-asm	mov	al,ss:[mask2]
-asm	out	dx,al						// set map mask register
-asm	call ss:[linescale]				// scale the segment of pixels
-asm	inc	di
-asm	mov	al,ss:[mask3]
-asm	out	dx,al						// set map mask register
-asm	call ss:[linescale]				// scale the segment of pixels
-asm	dec	di
-asm	dec	di
-
-asm	mov	es,WORD PTR ss:[linescale+2] // segment of scaler
-asm	mov	BYTE PTR es:[bx],cl			// unpatch the RETF
-asm	jmp	scaletriple					// do the next segment
-
-
-}
-
-
-/*
-=======================
-=
-= scalevis
-=
-= Draws a compiled shape at [scale] pixels high
-=
-= each vertical line of the shape has a pointer to segment data:
-= 	end of segment pixel*2 (0 terminates line) used to patch rtl in scaler
-= 	top of virtual line with segment in proper place
-=	start of segment pixel*2, used to jsl into compiled scaler
-=	<repeat>
-=
-= Setup for call
-= --------------
-= GC_MODE			read mode 1, write mode 2
-= GC_COLORDONTCARE  set to 0, so all reads from video memory return 0xff
-= GC_INDEX			pointing at GC_BITMASK
-=
-=======================
-*/
-
-static	s32int		longtemp;
-
-void scalevis (s16int xcenter, s16int shapenum, u16int height)
-{
-	t_compshape	_seg *shape;
-	t_compscale _seg *comptable;
-	u16int	scale,srcx,stopx,tempx;	/* /!\ scale shadow */
-	s16int			t;
-	u16int	far *cmdptr;
-	int		leftvis,rightvis;
-
-
-	shape = PM_GetSpritePage (shapenum);
-
-	scale = height>>3;						// low three bits are fractional
-	if (!scale || scale>maxscale)
-		return;								// too close or far away
-	comptable = scaledirectory[scale];
-
-	*(((u16int *)&linescale)+1)=(u16int)comptable;	// seg of far call
-	*(((u16int *)&linecmds)+1)=(u16int)shape;		// seg of shape
-
-//
-// scale to the left (from pixel 31 to shape->leftpix)
-//
-	srcx = 32;
-	slinex = xcenter;
-	stopx = shape->leftpix;
-	cmdptr = &shape->dataofs[31-stopx];
-
-	while ( --srcx >=stopx && slinex>0)
-	{
-		(u16int)linecmds = *cmdptr--;
-		if ( !(slinewidth = comptable->width[srcx]) )
-			continue;
-
-		if (slinewidth == 1)
-		{
-			slinex--;
-			if (slinex<vw.dx)
-			{
-				if (wallheight[slinex] >= height)
-					continue;		// obscured by closer wall
-				ScaleLine ();
-			}
-			continue;
-		}
-
-		//
-		// handle multi pixel lines
-		//
-		if (slinex>vw.dx)
-		{
-			slinex -= slinewidth;
-			slinewidth = vw.dx-slinex;
-			if (slinewidth<1)
-				continue;		// still off the right side
-		}
-		else
-		{
-			if (slinewidth>slinex)
-				slinewidth = slinex;
-			slinex -= slinewidth;
-		}
-
-
-		leftvis = (wallheight[slinex] < height);
-		rightvis = (wallheight[slinex+slinewidth-1] < height);
-
-		if (leftvis)
-		{
-			if (rightvis)
-				ScaleLine ();
-			else
-			{
-				while (wallheight[slinex+slinewidth-1] >= height)
-					slinewidth--;
-				ScaleLine ();
-			}
-		}
-		else
-		{
-			if (!rightvis)
-				continue;		// totally obscured
-
-			while (wallheight[slinex] >= height)
-			{
-				slinex++;
-				slinewidth--;
-			}
-			ScaleLine ();
-			break;			// the rest of the shape is gone
-		}
-	}
-
-
-//
-// scale to the right
-//
-	slinex = xcenter;
-	stopx = shape->rightpix;
-	if (shape->leftpix<31)
-	{
-		srcx = 31;
-		cmdptr = &shape->dataofs[32-shape->leftpix];
-	}
-	else
-	{
-		srcx = shape->leftpix-1;
-		cmdptr = &shape->dataofs[0];
-	}
-	slinewidth = 0;
-
-	while ( ++srcx <= stopx && (slinex+=slinewidth)<vw.dx)
-	{
-		(u16int)linecmds = *cmdptr++;
-		if ( !(slinewidth = comptable->width[srcx]) )
-			continue;
-
-		if (slinewidth == 1)
-		{
-			if (slinex>=0 && wallheight[slinex] < height)
-			{
-				ScaleLine ();
-			}
-			continue;
-		}
-
-		//
-		// handle multi pixel lines
-		//
-		if (slinex<0)
-		{
-			if (slinewidth <= -slinex)
-				continue;		// still off the left edge
-
-			slinewidth += slinex;
-			slinex = 0;
-		}
-		else
-		{
-			if (slinex + slinewidth > vw.dx)
-				slinewidth = vw.dx-slinex;
-		}
-
-
-		leftvis = (wallheight[slinex] < height);
-		rightvis = (wallheight[slinex+slinewidth-1] < height);
-
-		if (leftvis)
-		{
-			if (rightvis)
-			{
-				ScaleLine ();
-			}
-			else
-			{
-				while (wallheight[slinex+slinewidth-1] >= height)
-					slinewidth--;
-				ScaleLine ();
-				break;			// the rest of the shape is gone
-			}
-		}
-		else
-		{
-			if (rightvis)
-			{
-				while (wallheight[slinex] >= height)
-				{
-					slinex++;
-					slinewidth--;
-				}
-				ScaleLine ();
-			}
-			else
-				continue;		// totally obscured
-		}
-	}
-}
-
-
-
-/*
-=======================
-=
-= scalespr
-=
-= NO CLIPPING, height in pixels
-=
-= Draws a compiled shape at [scale] pixels high
-=
-= each vertical line of the shape has a pointer to segment data:
-= 	end of segment pixel*2 (0 terminates line) used to patch rtl in scaler
-= 	top of virtual line with segment in proper place
-=	start of segment pixel*2, used to jsl into compiled scaler
-=	<repeat>
-=
-= Setup for call
-= --------------
-= GC_MODE			read mode 1, write mode 2
-= GC_COLORDONTCARE  set to 0, so all reads from video memory return 0xff
-= GC_INDEX			pointing at GC_BITMASK
-=
-=======================
-*/
-
-void scalespr (s16int xcenter, s16int shapenum, u16int height)
-{
-	t_compshape	_seg *shape;
-	t_compscale _seg *comptable;
-	u16int	scale,srcx,stopx,tempx;	/* /!\ scale shadow */
-	s16int			t;
-	u16int	far *cmdptr;
-	int		leftvis,rightvis;
-
-
-	shape = PM_GetSpritePage (shapenum);
-
-	scale = height>>1;
-	comptable = scaledirectory[scale];
-
-	*(((u16int *)&linescale)+1)=(u16int)comptable;	// seg of far call
-	*(((u16int *)&linecmds)+1)=(u16int)shape;		// seg of shape
-
-//
-// scale to the left (from pixel 31 to shape->leftpix)
-//
-	srcx = 32;
-	slinex = xcenter;
-	stopx = shape->leftpix;
-	cmdptr = &shape->dataofs[31-stopx];
-
-	while ( --srcx >=stopx )
-	{
-		(u16int)linecmds = *cmdptr--;
-		if ( !(slinewidth = comptable->width[srcx]) )
-			continue;
-
-		slinex -= slinewidth;
-		ScaleLine ();
-	}
-
-
-//
-// scale to the right
-//
-	slinex = xcenter;
-	stopx = shape->rightpix;
-	if (shape->leftpix<31)
-	{
-		srcx = 31;
-		cmdptr = &shape->dataofs[32-shape->leftpix];
-	}
-	else
-	{
-		srcx = shape->leftpix-1;
-		cmdptr = &shape->dataofs[0];
-	}
-	slinewidth = 0;
-
-	while ( ++srcx <= stopx )
-	{
-		(u16int)linecmds = *cmdptr++;
-		if ( !(slinewidth = comptable->width[srcx]) )
-			continue;
-
-		ScaleLine ();
-		slinex+=slinewidth;
-	}
-}
-
-
-
-
-//
-// bit mask tables for drawing scaled strips up to eight pixels wide
-//
-// down here so the STUPID inline assembler doesn't get confused!
-//
-
-
-u8int	mapmasks1[4][8] = {
-{1 ,3 ,7 ,15,15,15,15,15},
-{2 ,6 ,14,14,14,14,14,14},
-{4 ,12,12,12,12,12,12,12},
-{8 ,8 ,8 ,8 ,8 ,8 ,8 ,8} };
-
-u8int	mapmasks2[4][8] = {
-{0 ,0 ,0 ,0 ,1 ,3 ,7 ,15},
-{0 ,0 ,0 ,1 ,3 ,7 ,15,15},
-{0 ,0 ,1 ,3 ,7 ,15,15,15},
-{0 ,1 ,3 ,7 ,15,15,15,15} };
-
-u8int	mapmasks3[4][8] = {
-{0 ,0 ,0 ,0 ,0 ,0 ,0 ,0},
-{0 ,0 ,0 ,0 ,0 ,0 ,0 ,1},
-{0 ,0 ,0 ,0 ,0 ,0 ,1 ,3},
-{0 ,0 ,0 ,0 ,0 ,1 ,3 ,7} };
-
-
-u16int	wordmasks[8][8] = {
-{0x0080,0x00c0,0x00e0,0x00f0,0x00f8,0x00fc,0x00fe,0x00ff},
-{0x0040,0x0060,0x0070,0x0078,0x007c,0x007e,0x007f,0x807f},
-{0x0020,0x0030,0x0038,0x003c,0x003e,0x003f,0x803f,0xc03f},
-{0x0010,0x0018,0x001c,0x001e,0x001f,0x801f,0xc01f,0xe01f},
-{0x0008,0x000c,0x000e,0x000f,0x800f,0xc00f,0xe00f,0xf00f},
-{0x0004,0x0006,0x0007,0x8007,0xc007,0xe007,0xf007,0xf807},
-{0x0002,0x0003,0x8003,0xc003,0xe003,0xf003,0xf803,0xfc03},
-{0x0001,0x8001,0xc001,0xe001,0xf001,0xf801,0xfc01,0xfe01} };
-
-s16int			slinex,slinewidth;
-u16int	far *linecmds;
-s32int		linescale;
-u16int	maskword;
-
--- a/snd.c
+++ b/snd.c
@@ -14,7 +14,8 @@
 	PcmHz = 7000,
 	ImfHz = 700,
 	SfxHz = 140,
-	Nsamp = Rate/ImfHz * 4,
+	Nsamp = Rate / ImfHz * 4,
+	Npsamp = Rate / PcmHz * 4,
 	Mdiv = ImfHz / Tb,
 	Pdiv = PcmHz / Tb,
 	Nbuf = Nsamp * Mdiv,
@@ -282,7 +283,7 @@
 
 /* stolen property cargocult upsampling */
 static void
-filter(int *xb, uchar *s)
+filter(uchar *s)
 {
 	ulong l, p, i;
 	int *x, o, a;
@@ -289,8 +290,6 @@
 	s16int m;
 	vlong v;
 
-	if(s >= sbuf + sizeof sbuf)
-		return;
 	v = 0;
 	x = &xb[xt>>Np];	/* left side */
 	l = p = xt & (1<<Np)-1;
@@ -339,6 +338,7 @@
 	ulong e;
 
 	b = sbuf;
+more:
 	do{
 		for(i=xbi; n>0 && i<Npbuf; n--, i++)
 			xb[i] = ((uint)*p++ << 24) - 0x7fffffff;
@@ -347,7 +347,11 @@
 			break;
 		e = i - Nextra << Np;
 		while(xt < e){	/* process buffer and mix */
-			filter(xb, b);
+			if(b >= sbuf + nelem(sbuf)){
+				n = 0;
+				break;
+			}
+			filter(b);
 			b += 4;
 			xt += TΔ;
 		}
@@ -364,6 +368,11 @@
 			xbi = s;
 		}
 	}while(n > 0);
+	if(b < sbuf + nelem(sbuf) && p < pcme){
+		n += (b - sbuf) / Npsamp;
+		goto more;
+	}
+	pcm = p;
 }
 
 static void
@@ -407,7 +416,6 @@
 		e = p + Pdiv;
 	setvol();
 	resample(p, e-p);
-	pcm = e;
 }
 
 void
--- a/wl3d.c
+++ b/wl3d.c
@@ -296,14 +296,12 @@
 			tc = 1;
 		else if(tc > 10)
 			tc = 10;
-		Δtc = (gm.demo || gm.record) && !gm.fizz ? 4 : tc;
+		Δtc = tc;
 		t0 += tc * Td;
-		if(nosleep)
-			continue;
 		if(onestep)
 			t0 += Td;
 		dt = (t0 - t) / Te6;
-		if(dt > 0)
+		if(dt > 0 && !nosleep)
 			sleep(dt);
 		else
 			t0 = t;