set -eu camellia_path_check fetch() { git clone https://github.com/ozkl/doomgeneric cd doomgeneric # TODO use a newer commit git -c advice.detachedHead=false checkout ee3ee581912dacd38af06e81da2374c1267453e8 cd doomgeneric rm doomgeneric # a leftover OS X binary sed s/xlib/camellia/ -i Makefile sed s/-lX11// -i Makefile echo note: you need to supply your own WADs cat <<\EOF > doomgeneric_camellia.c #include #include #include #include #include #include #include #include #include #include "doomgeneric.h" #include "doomkeys.h" static struct framebuf fb; static hid_t kb; static const char keymap_lower[] = { '\0', '\0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\r', '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', '\0', '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', '\0', '*', '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', }; static char kb_backbuf[256]; static ring_t kb_backlog = {kb_backbuf, sizeof kb_backbuf, 0, 0}; static void kb_thread(void *arg) { (void)arg; char buf[sizeof kb_backbuf]; for (;;) { int ret = _sys_read(kb, buf, sizeof buf, 0); if (ret <= 0) break; ring_put(&kb_backlog, buf, ret); } } void DG_Init(void) { if (fb_setup(&fb, "/kdev/video/") < 0) { puts("DG_Init: fb_setup error"); abort(); } kb = _sys_open("/kdev/ps2/kb", 12, 0); if (kb < 0) { puts("DG_Init: can't open keyboard"); abort(); } thread_create(0, kb_thread, NULL); } void DG_DrawFrame(void) { size_t doomw = DOOMGENERIC_RESX; size_t doomh = DOOMGENERIC_RESY; size_t doompitch = doomw * 4; for (int y = 0; y < DOOMGENERIC_RESY; y++) { memcpy(fb.b + fb.pitch * y, ((char*)DG_ScreenBuffer) + doompitch * y, doompitch); } struct rect d; dirty_mark(&d, 0, 0); dirty_mark(&d, doomw, doomh); dirty_flush(&d, &fb); } static uint32_t timer = 0; void DG_SleepMs(uint32_t ms) { timer += ms; _sys_sleep(ms); } uint32_t DG_GetTicksMs(void) { /* if it's stupid and it works... */ return timer; } int DG_GetKey(int *pressed, unsigned char *key) { uint8_t c; int read = ring_get(&kb_backlog, (char*)&c, 1); bool extended = c == 0xe0;; if (read == 0) return 0; if (extended) ring_get(&kb_backlog, (char*)&c, 1); bool down = !(c & 0x80); c &= 0x7f; if (!extended) { switch (c) { case 0x01: c = KEY_ESCAPE; break; case 0x2a: case 0x36: c = KEY_RSHIFT; break; case 0x1d: c = KEY_FIRE; break; default: c = keymap_lower[c & 0x7f]; switch (c) { case ' ': c = KEY_USE; break; } } } else { switch (c) { case 0x48: c = KEY_UPARROW; break; case 0x50: c = KEY_DOWNARROW; break; case 0x4B: c = KEY_LEFTARROW; break; case 0x4D: c = KEY_RIGHTARROW; break; default: c = '\0'; break; } } *pressed = down; *key = c; return 1; } void DG_SetWindowTitle(const char *title) { (void)title; } EOF } prep() { [ -d doomgeneric ] || (fetch) cd doomgeneric/doomgeneric } case $1 in install) (prep; make "CC=cc" && cp doomgeneric $PREFIX/bin/doom && cp *.WAD $PREFIX/) ;; clean) (prep; make clean) ;; deepclean) (rm -rf doomgeneric) ;; *) echo "usage: $0 install|clean"; false ;; esac