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;
}