shithub: qk1

Download patch

ref: cedb64a092b304c671d81049b8513614402b951b
parent: 49a810aeb5cb996bf9a6d4e3c38fc4d17fb77610
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Tue Jan 2 19:13:03 EST 2024

add v_snail mode

--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@
 BIN=${DESTDIR}${PREFIX}/bin
 EXTRA_CFLAGS=$$(pkg-config --cflags sdl2 openal)
 EXTRA_LDFLAGS=$$(pkg-config --libs sdl2 openal)
-CFLAGS?=-O3 -g -march=native
+CFLAGS?=-O3 -g -march=native -ffast-math
 CFLAGS+=-Wall -Wextra -Wno-unknown-pragmas -Wno-missing-field-initializers -Wno-implicit-fallthrough -Wno-microsoft-anon-tag
 CFLAGS+=-fms-extensions
 CFLAGS+=-I3rd/parg -Iunix -I. ${EXTRA_CFLAGS}
@@ -86,6 +86,7 @@
 	sv_move.o\
 	sv_phys.o\
 	sv_user.o\
+	sys_snail.o\
 	sys_unix.o\
 	vid_sdl.o\
 	view.o\
--- a/fns.h
+++ b/fns.h
@@ -65,6 +65,10 @@
 int	sys_mkdir(char *path);
 char *sys_timestamp(void);
 
+extern bool snailenabled;
+void sys_snail(bool);
+void initsnail(void);
+
 long sndqueued(void);
 void sndstop(void);
 void sndwrite(byte *buf, long sz);
--- a/host.c
+++ b/host.c
@@ -530,6 +530,8 @@
 					pass1+pass2+pass3, pass1, pass2, pass3);
 	}
 
+	sys_snail(false);
+
 	host_framecount++;
 }
 
--- a/sys_plan9.c
+++ b/sys_plan9.c
@@ -65,6 +65,11 @@
 	return ts;
 }
 
+void
+sys_snail(bool)
+{
+}
+
 char *
 lerr(void)
 {
--- /dev/null
+++ b/sys_snail.c
@@ -1,0 +1,83 @@
+#ifdef SNAIL
+
+#define _GNU_SOURCE
+#include "quakedef.h"
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/ucontext.h>
+
+static bool snailing;
+bool snailenabled;
+
+static int
+vidsize(void)
+{
+	return vid.width*vid.height*sizeof(pixel_t);
+}
+
+static void
+wobble(int s, siginfo_t *info, void *ctx_)
+{
+	ucontext_t *ctx = ctx_;
+
+	USED(info);
+	if(!snailing)
+		return;
+	if(s == SIGSEGV){
+		mprotect(vid.buffer, vidsize(), PROT_READ | PROT_WRITE);
+		ctx->uc_mcontext.gregs[REG_EFL] |= 0x100;
+	}else if(s == SIGTRAP){
+		mprotect(vid.buffer, vidsize(), PROT_READ);
+		ctx->uc_mcontext.gregs[REG_EFL] &= ~0x100;
+		flipfb();
+	}
+}
+
+void
+sys_snail(bool enable)
+{
+	if(!snailenabled || enable == snailing)
+		return;
+
+	if(enable){
+		memset(vid.buffer, 0, vidsize());
+		flipfb();
+	}
+	if(mprotect(vid.buffer, vidsize(), PROT_READ | (enable ? 0 : PROT_WRITE)) < 0){
+		perror("mprotect");
+		return;
+	}
+	snailing = enable;
+}
+
+void
+initsnail(void)
+{
+	struct sigaction act = {0};
+	act.sa_sigaction = wobble;
+	act.sa_flags = SA_SIGINFO;
+	if(sigaction(SIGSEGV, &act, nil) < 0)
+		perror("sigsegv");
+	else if(sigaction(SIGTRAP, &act, nil) < 0)
+		perror("sigtrap");
+}
+
+#else
+
+#include "quakedef.h"
+
+bool snailenabled;
+
+void
+sys_snail(bool enable)
+{
+	USED(enable);
+}
+
+void
+initsnail(void)
+{
+	snailenabled = false;
+}
+
+#endif
--- a/sys_unix.c
+++ b/sys_unix.c
@@ -140,14 +140,10 @@
 	sigset_t ss;
 	pthread_t tid;
 
-	sigemptyset(&ss);
-	sigaddset(&ss, SIGPIPE);
-	pthread_sigmask(SIG_BLOCK, &ss, NULL);
-	pthread_create(&tid, nil, sighandler, &ss);
-
 	parg_init(&ps);
 	nargs = 0;
-	while((c = parg_getopt(&ps, argc, argv, "Ddg:N:")) >= 0){
+	snailenabled = false;
+	while((c = parg_getopt(&ps, argc, argv, "Ddg:N:S")) >= 0){
 		switch(c){
 		case 1:
 			argv[nargs++] = (char*)ps.optarg;
@@ -169,6 +165,9 @@
 			fprintf(stderr, "usage: qk1 [-g game]\n");
 			return 0;
 			break;
+		case 'S':
+			snailenabled = true;
+			break;
 		case '?':
 			fprintf(stderr, "unknown option -%c\n", ps.optopt);
 			return 1;
@@ -179,6 +178,14 @@
 			break;
 		}
 	}
+
+	sigemptyset(&ss);
+	sigaddset(&ss, SIGPIPE);
+	pthread_sigmask(SIG_BLOCK, &ss, NULL);
+	pthread_create(&tid, nil, sighandler, &ss);
+
+	if(snailenabled)
+		initsnail();
 
 	srand(nanosec() + time(nil));
 
--- a/vid_sdl.c
+++ b/vid_sdl.c
@@ -1,5 +1,6 @@
 #include "quakedef.h"
 #include <SDL.h>
+#include <sys/mman.h>
 
 pixel_t q1pal[256];
 
@@ -9,11 +10,14 @@
 static pixel_t *vidbuffer;
 extern pixel_t *r_warpbuffer;
 
+static cvar_t v_snail = {"v_snail", "0"};
+static int oldvidbuffersz;
+
 static void
 resetfb(void)
 {
 	void *surfcache;
-	int hunkvbuf, scachesz;
+	int hunkvbuf, scachesz, n;
 
 	/* lower than 320x240 doesn't really make sense,
 	 * but at least this prevents a crash, beyond that
@@ -28,10 +32,18 @@
 	vid.conwidth = vid.width;
 	vid.conheight = vid.height;
 
-	free(vidbuffer);
-	vidbuffer = emalloc((vid.width*vid.height+16)*sizeof(pixel_t));
+	n = (vid.width*vid.height+16)*sizeof(pixel_t);
+	if(snailenabled){
+		if(oldvidbuffersz != 0)
+			munmap(vidbuffer, oldvidbuffersz);
+		vidbuffer = mmap(nil, n, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+		oldvidbuffersz = n;
+	}else{
+		free(vidbuffer);
+		vidbuffer = emalloc(n);
+	}
 	free(r_warpbuffer);
-	r_warpbuffer = emalloc((vid.width*vid.height+16)*sizeof(pixel_t));
+	r_warpbuffer = emalloc(n);
 	vid.maxwarpwidth = vid.width;
 	vid.maxwarpheight = vid.height;
 
@@ -93,6 +105,12 @@
 	scr_fullupdate = 0;
 }
 
+static void
+v_snail_cb(cvar_t *var)
+{
+	sys_snail(var->value != 0);
+}
+
 void
 initfb(void)
 {
@@ -117,4 +135,7 @@
 	SDL_SetWindowResizable(win, SDL_TRUE);
 	SDL_SetWindowMinimumSize(win, 320, 240);
 	IN_Grabm(1);
+
+	Cvar_RegisterVariable(&v_snail);
+	v_snail.cb = v_snail_cb;
 }