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