ref: 2feac9be1d1bebe1a05a47c0adf0254228ca558d
dir: /sys_snail.c/
#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