summaryrefslogtreecommitdiff
path: root/ports/doom
blob: 7ef03ddcb038c84e003a072c37c550ac7a8409f0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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 <camellia/syscalls.h>
#include <shared/ring.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <draw.h>
#include <thread.h>

#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=x86_64-camellia-gcc" && cp doomgeneric $PREFIX/bin/doom && cp *.WAD $PREFIX/) ;;
	clean)   (prep; make clean) ;;
	deepclean) (rm -rf doomgeneric) ;;
	*)       echo "usage: $0 install|clean"; false ;;
esac