shithub: qk1

Download patch

ref: a2a1e4ddd855afe9caf7ac420dca9aaa9a3de223
parent: 231f3bd7af6081361a67bfdd095a625d34b893d8
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Tue Sep 19 17:42:26 EDT 2023

normalquake: redo screen image conversion; remove scaling; make sound chop less

--- a/d_scan.c
+++ b/d_scan.c
@@ -339,28 +339,10 @@
 				}
 			}
 
+			void dospan(uchar *, uchar *, int, int, int, int, int, int);
+			if(spancount > 0)
+				dospan(pdest, pbase, s, t, sstep, tstep, spancount, cachewidth);
 			pdest += spancount;
-			switch (spancount)
-			{
-			case 16: pdest[-16] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
-			case 15: pdest[-15] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
-			case 14: pdest[-14] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
-			case 13: pdest[-13] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
-			case 12: pdest[-12] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
-			case 11: pdest[-11] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
-			case 10: pdest[-10] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
-			case 9: pdest[-9] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
-			case 8: pdest[-8] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
-			case 7: pdest[-7] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
-			case 6: pdest[-6] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
-			case 5: pdest[-5] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
-			case 4: pdest[-4] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
-			case 3: pdest[-3] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
-			case 2: pdest[-2] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
-			case 1: pdest[-1] = pbase[(s >> 16) + (t >> 16) * cachewidth];
-			case 0: break;
-			}
-
 			s = snext;
 			t = tnext;
 
--- a/dat.h
+++ b/dat.h
@@ -44,5 +44,4 @@
 };
 #define Spktatt 1.0
 
-extern int dumpwin, scaleon;
 extern int debug;
--- a/fns.h
+++ b/fns.h
@@ -1,5 +1,6 @@
 void	setpal(uchar*);
-void	flipfb(int);
+void	stopfb(void);
+void	flipfb(void);
 void	initfb(void);
 void	conscmd(void);
 void	Sys_SendKeyEvents(void);
--- a/mkfile
+++ b/mkfile
@@ -2,8 +2,11 @@
 
 BIN=/$objtype/bin/games
 TARG=quake
+CFLAGS=$CFLAGS -D__${objtype}__
 
 OFILES=\
+	pal`{test -f pal_$objtype.s && echo -n _$objtype}.$O\
+	span`{test -f span_$objtype.s && echo -n _$objtype}.$O\
 	cd.$O\
 	cl_demo.$O\
 	cl_input.$O\
--- /dev/null
+++ b/pal.c
@@ -1,0 +1,8 @@
+#include <u.h>
+
+void
+pal2xrgb(int n, s32int *pal, u8int *s, u32int *d)
+{
+	while(n-- > 0)
+		*d++ = pal[*s++];
+}
--- /dev/null
+++ b/pal_arm64.s
@@ -1,0 +1,52 @@
+TEXT	pal2xrgb+0(SB), 1, $-4
+	MOV pal+8(FP), R1
+	MOV s+16(FP), R2
+	MOV d+24(FP), R3
+
+	ADD R2, R0
+
+	CMP $8, R0
+	BLE _l1
+
+	AND $7, R0, R12
+	SUB R12, R0, R12
+
+_l8:
+	MOVWU 0(R2), R4
+	MOVWU 4(R2), R8
+	UBFXW $8, $8, R4, R5
+	UBFXW $8, $8, R8, R9
+	UBFXW $16, $8, R4, R6
+	UBFXW $16, $8, R8, R10
+	UBFXW $24, $8, R4, R7
+	MOVBU R4, R4
+	UBFXW $24, $8, R8, R11
+	MOVBU R8, R8
+	MOVWU (R1)[R4], R13
+	MOVWU (R1)[R5], R14
+	MOVWU (R1)[R6], R15
+	MOVWU (R1)[R7], R16
+	MOVWU (R1)[R8], R17
+	MOVWU (R1)[R9], R18
+	MOVWU (R1)[R10], R19
+	MOVWU (R1)[R11], R20
+	MOVPW R13, R14, 0(R3)
+	MOVPW R15, R16, 8(R3)
+	MOVPW R17, R18, 16(R3)
+	MOVPW R19, R20, 24(R3)
+	ADD $32, R3
+	ADD $8, R2
+	CMP R2, R12
+	BNE _l8
+	CMP R2, R0
+	BEQ _end
+
+_l1:
+	MOVBU 1(R2)!, R4
+	MOVWU (R1)[R4], R4
+	MOVWU R4, 4(R3)!
+	CMP R2, R0
+	BNE _l1
+
+_end:
+	RETURN
--- a/qk1.c
+++ b/qk1.c
@@ -92,6 +92,7 @@
 void
 shutdown(void)
 {
+	stopfb();
 	Host_Shutdown();
 	threadexitsall(nil);
 }
@@ -109,7 +110,7 @@
 static void
 usage(void)
 {
-	fprint(2, "usage: %s [-d] [-g game] [-m kB] [-s width height] [-x netmtpt]\n", argv0);
+	fprint(2, "usage: %s [-d] [-g game] [-m kB] [-x netmtpt]\n", argv0);
 	exits("usage");
 }
 
@@ -133,13 +134,6 @@
 		memsize = strtol(EARGF(usage()), nil, 0) * KB;
 		if(memsize <= 0)
 			sysfatal("invalid memsize");
-		break;
-	case 's':
-		scaleon = 1;
-		vid.width = strtol(EARGF(usage()), nil, 0);
-		vid.height = strtol(EARGF(usage()), nil, 0);
-		if(vid.width < 320 || vid.height < 200)
-			sysfatal("invalid scale resolution");
 		break;
 	case 'x':
 		netmtpt = EARGF(usage());
--- a/qw/vid.c
+++ b/qw/vid.c
@@ -6,7 +6,7 @@
 
 viddef_t vid;		/* global video state */
 int resized;
-int dumpwin, scaleon;
+int dumpwin;
 Point center;		/* of window */
 Rectangle grabr;
 
@@ -87,23 +87,15 @@
 
 	Point p;
 
-	if(scaleon){
-		scale = Dx(screen->r) / vid.width;
-		if(scale <= 0)
-			scale = 1;
-		else if(scale > 16)
-			scale = 16;
-	}else{
-		/* lower than 320x240 doesn't really make sense,
-		 * but at least this prevents a crash, beyond that
-		 * it's your funeral */
-		vid.width = Dx(screen->r);
-		if(vid.width < 320)
-			vid.width = 320;
-		vid.height = Dy(screen->r);
-		if(vid.height < 160)
-			vid.height = 160;
-	}
+	/* lower than 320x240 doesn't really make sense,
+	 * but at least this prevents a crash, beyond that
+	 * it's your funeral */
+	vid.width = Dx(screen->r);
+	if(vid.width < 320)
+		vid.width = 320;
+	vid.height = Dy(screen->r);
+	if(vid.height < 160)
+		vid.height = 160;
 	if(d_pzbuffer != nil){
 		D_FlushCaches();
 		Hunk_FreeToHighMark(highhunk);
@@ -139,10 +131,6 @@
 	if(fbi == nil)
 		sysfatal("resetfb: %r (%d %d)", vid.width, vid.height);
 	fb = emalloc(vid.rowbytes * vid.height);
-	if(scaleon){
-		free(fbs);
-		fbs = emalloc(vid.rowbytes * scale * vid.height);
-	}
 	vid.buffer = fb;
 	vid.conbuffer = fb;
 	draw(screen, screen->r, display->black, nil, ZP);
@@ -153,14 +141,6 @@
 {
 	int n;
 
-	n = COM_CheckParm("-scale");
-	if(n && n < com_argc-2){
-		scaleon = 1;
-		vid.width = strtol(com_argv[n+1], nil, 0);
-		vid.height = strtol(com_argv[n+2], nil, 0);
-		if(vid.width < 320 || vid.height < 200)
-			sysfatal("invalid scale resolution");
-	}
 	vid.maxwarpwidth = WARP_WIDTH;
 	vid.maxwarpheight = WARP_HEIGHT;
 	vid.numpages = 2;
--- a/screen.c
+++ b/screen.c
@@ -284,12 +284,6 @@
 	vid.recalc_refdef = 1;
 }
 
-static void
-screenshot(void) 
-{ 
-	dumpwin++;
-}
-
 void SCR_Init (void)
 {
 	Cvar_RegisterVariable (&scr_fov);
@@ -301,7 +295,6 @@
 	Cvar_RegisterVariable (&scr_centertime);
 	Cvar_RegisterVariable (&scr_printspeed);
 	Cvar_RegisterVariable(&scr_showfps);
-	Cmd_AddCommand("screenshot", screenshot);
 	Cmd_AddCommand ("sizeup",SCR_SizeUp_f);
 	Cmd_AddCommand ("sizedown",SCR_SizeDown_f);
 
@@ -764,6 +757,5 @@
 	SCR_DrawFPS();
 	V_UpdatePalette ();
 
-	flipfb(scr_copyeverything ? vid.height :
-		scr_copytop ? vid.height-sb_lines : scr_vrect.height);
+	flipfb();
 }
--- a/snd.c
+++ b/snd.c
@@ -1,5 +1,6 @@
 #include <u.h>
 #include <libc.h>
+#include <thread.h>
 #include "dat.h"
 #include "quakedef.h"
 #include "fns.h"
@@ -36,8 +37,8 @@
 };
 static Chan chans[Nchan], *che;
 
-static int afd = -1;
-static uchar mixbuf[Snbuf];
+static int afd = -1, mixbufi;
+static uchar mixbufs[2][Snbuf], *mixbuf = mixbufs[0];
 static vlong sndt, sampt;
 static int nsamp;
 static int sampbuf[Ssamp*Sch*sizeof(int)];
@@ -488,14 +489,43 @@
 	}
 }
 
+static void
+auproc(void *p)
+{
+	long sz;
+	uchar *m;
+
+	for(;;){
+		if((sz = recvul(p)) == 0)
+			break;
+		m = mixbufs[0];
+		if(sz < 0){
+			m = mixbufs[1];
+			sz = -sz;
+		}
+		if(write(afd, m, sz) != sz){
+			fprint(2, "sndwrite: %r\n");
+			shutsnd();
+			break;
+		}
+	}
+	chanclose(p);
+	threadexits(nil);
+}
+
 void
 stepsnd(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
 {
-	int ns;
+	long ns;
 	Chan *c, *sum;
+	static Channel *ach;
 
 	if(afd < 0)
 		return;
+	if(ach == nil){
+		ach = chancreate(sizeof(ulong), 0);
+		proccreate(auproc, ach, 4096);
+	}
 	VectorCopy(origin, listener_origin);
 	VectorCopy(forward, listener_forward);
 	VectorCopy(right, listener_right);
@@ -538,9 +568,10 @@
 	ns = nsamp * Sblk;
 	samplesfx();
 	sampt += nsamp;
-	if(write(afd, mixbuf, ns) != ns){
-		fprint(2, "sndwrite: %r\n");
-		shutsnd();
+	if(ns != 0){
+		sendul(ach, mixbufi == 0 ? ns : -ns);
+		mixbufi = (mixbufi + 1) % 2;
+		mixbuf = mixbufs[mixbufi];
 	}
 	sndt = nanosec();
 }
@@ -797,6 +828,7 @@
 	if(afd < 0)
 		return;
 	close(afd);
+	afd = -1;
 }
 
 int
--- /dev/null
+++ b/span.c
@@ -1,0 +1,26 @@
+#include <u.h>
+#include <libc.h>
+
+void
+dospan(uchar *pdest, uchar *pbase, int s, int t, int sstep, int tstep, int spancount, int cachewidth)
+{
+	switch(spancount)
+	{
+	case 16: *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
+	case 15: *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
+	case 14: *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
+	case 13: *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
+	case 12: *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
+	case 11: *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
+	case 10: *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
+	case 9: *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
+	case 8: *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
+	case 7: *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
+	case 6: *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
+	case 5: *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
+	case 4: *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
+	case 3: *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
+	case 2: *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep;
+	case 1: *pdest = pbase[(s >> 16) + (t >> 16) * cachewidth];
+	}
+}
--- /dev/null
+++ b/span_arm64.s
@@ -1,0 +1,23 @@
+TEXT	dospan+0(SB), 1, $-4
+	MOV pbase+8(FP), R1
+	MOVW s+16(FP), R2
+	MOVW t+24(FP), R3
+	MOVW sstep+32(FP), R4
+	MOVW tstep+40(FP), R5
+	MOVW spancount+48(FP), R6
+	MOVW cachewidth+56(FP), R7
+	LSRW $16, R3, R9
+	LSRW $16, R2, R8
+
+_l:
+	SUBW $1, R6
+	MADDW R7, R9, R8, R8
+	ADDW R5, R3
+	MOVBU (R1)[R8], R10
+	ADDW R4, R2
+	MOVBU R10, 1(R0)!
+	LSRW $16, R3, R9
+	LSRW $16, R2, R8
+	CBNZ R6, _l
+
+	RETURN
--- a/vid.c
+++ b/vid.c
@@ -1,6 +1,7 @@
 #include <u.h>
 #include <libc.h>
 #include <draw.h>
+#include <thread.h>
 #include "dat.h"
 #include "quakedef.h"
 #include "fns.h"
@@ -7,103 +8,36 @@
 
 viddef_t vid;		/* global video state */
 int resized;
-int dumpwin, scaleon;
 Point center;		/* of window */
 Rectangle grabr;
 
-static int scale = 1;
 static s32int fbpal[256];
-static uchar *fb, *fbs;
+static uchar *fbs;
 static Image *fbi;
 static Rectangle fbr;
+static u8int *vidbuffers[2];
+static int bufi = 0;
+static Channel *frame;
 
-static void
-scalefb(int dy)
-{
-	int *p, c, *s;
+void pal2xrgb(int n, s32int *pal, u8int *s, u32int *d);
 
-	if(scale < 2)
-		return;
-	p = (s32int *)fbs;
-	s = (s32int *)fb;
-	dy *= vid.width;
-	while(dy-- > 0){
-		c = *s++;
-		switch(scale){
-		case 16: p[15] = c;
-		case 15: p[14] = c;
-		case 14: p[13] = c;
-		case 13: p[12] = c;
-		case 12: p[11] = c;
-		case 11: p[10] = c;
-		case 10: p[9] = c;
-		case 9: p[8] = c;
-		case 8: p[7] = c;
-		case 7: p[6] = c;
-		case 6: p[5] = c;
-		case 5: p[4] = c;
-		case 4: p[3] = c;
-		case 3: p[2] = c;
-		case 2: p[1] = c; p[0] = c;
-		}
-		p += scale;
-	}
-}
-
 static void
-drawfb(int dy)
-{
-	uchar *s;
-	int n, we, w8, wr, *d;
-
-	we = vid.width - 1;
-	w8 = vid.width + 7 >> 3;
-	wr = vid.width % 8;
-	dy *= vid.rowbytes;
-	while((dy -= vid.rowbytes) >= 0){
-		s = fb + dy;
-		d = ((int *)s) + we;
-		s += we;
-		n = w8;
-		switch(wr){
-		case 0:	do{	*d-- = fbpal[*s--];
-		case 7:		*d-- = fbpal[*s--];
-		case 6:		*d-- = fbpal[*s--];
-		case 5:		*d-- = fbpal[*s--];
-		case 4:		*d-- = fbpal[*s--];
-		case 3:		*d-- = fbpal[*s--];
-		case 2:		*d-- = fbpal[*s--];
-		case 1:		*d-- = fbpal[*s--];
-			}while(--n > 0);
-		}
-	}
-}
-
-static void
 resetfb(void)
 {
 	static int highhunk;
 	void *surfcache;
-	int hunkvbuf, scachesz;
+	int hunkvbuf, scachesz, i;
 	Point p;
 
-	if(scaleon){
-		scale = Dx(screen->r) / vid.width;
-		if(scale <= 0)
-			scale = 1;
-		else if(scale > 16)
-			scale = 16;
-	}else{
-		/* lower than 320x240 doesn't really make sense,
-		 * but at least this prevents a crash, beyond that
-		 * it's your funeral */
-		vid.width = Dx(screen->r);
-		if(vid.width < 320)
-			vid.width = 320;
-		vid.height = Dy(screen->r);
-		if(vid.height < 160)
-			vid.height = 160;
-	}
+	/* lower than 320x240 doesn't really make sense,
+	 * but at least this prevents a crash, beyond that
+	 * it's your funeral */
+	vid.width = Dx(screen->r);
+	if(vid.width < 320)
+		vid.width = 320;
+	vid.height = Dy(screen->r);
+	if(vid.height < 160)
+		vid.height = 160;
 	if(d_pzbuffer != nil){
 		D_FlushCaches();
 		Hunk_FreeToHighMark(highhunk);
@@ -120,7 +54,7 @@
 	surfcache = (byte *)d_pzbuffer + vid.width * vid.height * sizeof *d_pzbuffer;
 	D_InitCaches(surfcache, scachesz);
 
-	vid.rowbytes = vid.width * sizeof *fbpal;
+	vid.rowbytes = vid.width;
 	vid.aspect = (float)vid.height / (float)vid.width * (320.0/240.0);
 	vid.conrowbytes = vid.rowbytes;
 	vid.conwidth = vid.width;
@@ -127,52 +61,57 @@
 	vid.conheight = vid.height;
 
 	center = divpt(addpt(screen->r.min, screen->r.max), 2);
-	p = Pt(scale * vid.width/2, scale * vid.height/2);
+	p = Pt(vid.width/2, vid.height/2);
 	fbr = Rpt(subpt(center, p), addpt(center, p));
 	p = Pt(vid.width/4, vid.height/4);
 	grabr = Rpt(subpt(center, p), addpt(center, p));
 	freeimage(fbi);
-	free(fb);
-	fbi = allocimage(display,
-		Rect(0, 0, vid.width * scale, scale > 1 ? 1 : vid.height),
-		XRGB32, scale > 1, 0);
+	for(i = 0; i < nelem(vidbuffers); i++){
+		free(vidbuffers[i]);
+		vidbuffers[i] = mallocalign(vid.width*vid.height*4, 64, 0, 0);
+	}
+	fbi = allocimage(display, Rect(0, 0, vid.width, vid.height), XRGB32, 0, 0);
 	if(fbi == nil)
 		sysfatal("resetfb: %r (%d %d)", vid.width, vid.height);
-	fb = emalloc(vid.rowbytes * vid.height);
-	if(scaleon){
-		free(fbs);
-		fbs = emalloc(vid.rowbytes * scale * vid.height);
-	}
-	vid.buffer = fb;
-	vid.conbuffer = fb;
+	bufi = 0;
+	vid.buffer = vidbuffers[0];
+	vid.conbuffer = vid.buffer;
 	draw(screen, screen->r, display->black, nil, ZP);
 }
 
-/* only exists to allow taking tear-free screenshots ingame... */
-static int
-writebit(void)
+static void
+loader(void *p)
 {
-	int n, fd;
-	char *s;
+	u8int *f, *fb;
 
-	s = va("%s/quake.%ld.bit", fsdir, time(nil));
-	if(access(s, AEXIST) != -1){
-		werrstr("writebit: not overwriting %s", s);
-		return -1;
+	fb = p;
+	for(;;){
+		if((f = recvp(frame)) == nil)
+			break;
+		pal2xrgb(vid.width * vid.height, fbpal, f, (u32int*)fb);
+		loadimage(fbi, Rect(0, 0, vid.width, vid.height), fb, vid.height*vid.rowbytes*4);
+		draw(screen, fbr, fbi, nil, ZP);
+		flushimage(display, 1);
 	}
-	if(fd = create(s, OWRITE, 0644), fd < 0)
-		return -1;
-	n = writeimage(fd, fbi, 0);
-	close(fd);
-	if(n >= 0)
-		Con_Printf("Wrote %s\n", s);
-	return n;
+	free(fb);
+	threadexits(nil);
 }
 
 void
-flipfb(int dy)
+stopfb(void)
 {
+	if(frame != nil){
+		sendp(frame, nil);
+		chanclose(frame);
+		frame = nil;
+	}
+}
+
+void
+flipfb(void)
+{
 	if(resized){		/* skip this frame if window resize */
+		stopfb();
 		resized = 0;
 		if(getwindow(display, Refnone) < 0)
 			sysfatal("getwindow: %r");
@@ -182,30 +121,14 @@
 		Con_Clear_f();
 		return;
 	}
-	drawfb(dy);
-	scalefb(dy);
-	if(scale == 1){
-		loadimage(fbi, Rect(0,0,vid.width,dy), fb, dy * vid.rowbytes);
-		draw(screen, Rpt(fbr.min, Pt(fbr.max.x,
-			fbr.max.y - vid.height + dy)), fbi, nil, ZP);
-	}else{
-		Rectangle r;
-		uchar *p;
-
-		p = fbs;
-		r = fbr;
-		while(r.min.y < fbr.max.y){
-			r.max.y = r.min.y + scale;
-			p += loadimage(fbi, fbi->r, p, vid.rowbytes * scale);
-			draw(screen, r, fbi, nil, ZP);
-			r.min.y = r.max.y;
-		}
+	if(frame == nil){
+		frame = chancreate(sizeof(u8int*), 0);
+		proccreate(loader, mallocalign(vid.width*vid.height*4+16, 64, 0, 0), 4096);
 	}
-	flushimage(display, 1);
-	if(dumpwin){
-		if(writebit() < 0)
-			Con_Printf(va("writebit: %r\n"));
-		dumpwin = 0;
+	if(sendp(frame, vidbuffers[bufi]) > 0){
+		bufi = (bufi+1) % nelem(vidbuffers);
+		vid.buffer = vidbuffers[bufi];
+		vid.conbuffer = vid.buffer;
 	}
 }
 
@@ -214,8 +137,9 @@
 {
 	int *fp;
 
-	for(fp=fbpal; fp<fbpal+nelem(fbpal); p+=3)
-		*fp++ = p[0] << 16 | p[1] << 8 | p[2];
+	for(fp=fbpal; fp<fbpal+nelem(fbpal); p+=3, fp++)
+		*fp = p[0] << 16 | p[1] << 8 | p[2];
+
 	scr_fullupdate = 0;
 }