9 static void swap_interval(int vsync);
10 static void idle(void);
11 static void reshape(int x, int y);
12 static void keydown(unsigned char key, int x, int y);
13 static void keyup(unsigned char key, int x, int y);
14 static void skeydown(int key, int x, int y);
15 static void skeyup(int key, int x, int y);
16 static void mouse(int bn, int st, int x, int y);
17 static void motion(int x, int y);
18 static int translate_skey(int key);
19 static unsigned int next_pow2(unsigned int x);
21 #if defined(__unix__) || defined(unix)
26 static void (*glx_swap_interval_ext)();
27 static void (*glx_swap_interval_sgi)();
31 static PROC wgl_swap_interval_ext;
35 #define GL_BGRA 0x80e1
37 #ifndef GL_CLAMP_TO_EDGE
38 #define GL_CLAMP_TO_EDGE 0x812f
41 unsigned char *framebuf;
42 static unsigned int tex;
43 static int tex_xsz, tex_ysz;
45 static int win_width, win_height;
46 static float win_aspect;
47 static float scale = 3;
48 static unsigned long start_time;
49 static uint32_t cmap[256];
51 int main(int argc, char **argv)
53 glutInit(&argc, argv);
55 glutInitWindowSize(FB_WIDTH * scale, FB_HEIGHT * scale);
56 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
57 glutCreateWindow("metatoy");
59 glutDisplayFunc(game_draw);
61 glutReshapeFunc(reshape);
62 glutKeyboardFunc(keydown);
63 glutKeyboardUpFunc(keyup);
64 glutSpecialFunc(skeydown);
65 glutSpecialUpFunc(skeyup);
67 glutMotionFunc(motion);
68 glutPassiveMotionFunc(motion);
70 #if defined(__unix__) || defined(unix)
71 xdpy = glXGetCurrentDisplay();
72 xwin = glXGetCurrentDrawable();
74 if(!(glx_swap_interval_ext = glXGetProcAddress((unsigned char*)"glXSwapIntervalEXT"))) {
75 glx_swap_interval_sgi = glXGetProcAddress((unsigned char*)"glXSwapIntervalSGI");
79 wgl_swap_interval_ext = wglGetProcAddress("wglSwapIntervalEXT");
83 if(!(framebuf = malloc(FB_WIDTH * FB_HEIGHT))) {
84 fprintf(stderr, "failed to allocate framebuffer\n");
88 glGenTextures(1, &tex);
89 glBindTexture(GL_TEXTURE_2D, tex);
90 tex_xsz = next_pow2(FB_WIDTH);
91 tex_ysz = next_pow2(FB_HEIGHT);
92 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_xsz, tex_ysz, 0, GL_RGBA,
94 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
95 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
96 glMatrixMode(GL_TEXTURE);
98 glScalef((float)FB_WIDTH / tex_xsz, (float)FB_HEIGHT / tex_ysz, 1);
99 glEnable(GL_TEXTURE_2D);
101 if(game_init() == -1) {
104 atexit(game_shutdown);
106 start_time = glutGet(GLUT_ELAPSED_TIME);
111 unsigned long game_getmsec(void)
113 return (unsigned long)glutGet(GLUT_ELAPSED_TIME) - start_time;
121 #define FB_ASPECT ((float)FB_WIDTH / (float)FB_HEIGHT)
123 void game_swap_buffers(void)
126 static uint32_t fbrgba[FB_WIDTH * FB_HEIGHT * 4];
128 for(i=0; i<FB_WIDTH * FB_HEIGHT; i++) {
129 int cidx = framebuf[i];
130 fbrgba[i] = cmap[cidx];
133 glBindTexture(GL_TEXTURE_2D, tex);
134 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, FB_WIDTH, FB_HEIGHT, GL_RGBA,
135 GL_UNSIGNED_BYTE, fbrgba);
137 glMatrixMode(GL_MODELVIEW);
139 if(win_aspect >= FB_ASPECT) {
140 glScalef(FB_ASPECT / win_aspect, 1, 1);
142 glScalef(1, win_aspect / FB_ASPECT, 1);
145 glClear(GL_COLOR_BUFFER_BIT);
159 assert(glGetError() == GL_NO_ERROR);
162 void vga_setpalent(int idx, int r, int g, int b)
164 cmap[idx] = (b << 16) | (g << 8) | r;
167 void vga_setpal(int startidx, int count, unsigned char *col)
169 int i, idx = startidx;
170 for(i=0; i<count; i++) {
171 vga_setpalent(idx++, col[0], col[1], col[2]);
176 void panic(const char *fmt, ...)
181 vfprintf(stderr, fmt, ap);
185 #if defined(__unix__) || defined(unix)
186 static void swap_interval(int vsync)
188 vsync = vsync ? 1 : 0;
189 if(glx_swap_interval_ext) {
190 glx_swap_interval_ext(xdpy, xwin, vsync);
191 } else if(glx_swap_interval_sgi) {
192 glx_swap_interval_sgi(vsync);
197 static void swap_interval(int vsync)
199 if(wgl_swap_interval_ext) {
200 wgl_swap_interval_ext(vsync ? 1 : 0);
205 static void idle(void)
210 static void reshape(int x, int y)
214 win_aspect = (float)x / (float)y;
215 glViewport(0, 0, x, y);
218 static void keydown(unsigned char key, int x, int y)
220 /*modkeys = glutGetModifiers();*/
221 game_keyboard(key, 1);
224 static void keyup(unsigned char key, int x, int y)
226 game_keyboard(key, 0);
229 static void skeydown(int key, int x, int y)
232 /*modkeys = glutGetModifiers();*/
233 if((k = translate_skey(key)) >= 0) {
238 static void skeyup(int key, int x, int y)
240 int k = translate_skey(key);
246 static void mouse(int bn, int st, int x, int y)
248 /*modkeys = glutGetModifiers();*/
249 game_mouse(bn - GLUT_LEFT_BUTTON, st == GLUT_DOWN, x / scale, y / scale);
252 static void motion(int x, int y)
254 game_motion(x / scale, y / scale);
257 static int translate_skey(int key)
268 case GLUT_KEY_PAGE_UP:
270 case GLUT_KEY_PAGE_DOWN:
276 case GLUT_KEY_INSERT:
279 if(key >= GLUT_KEY_F1 && key <= GLUT_KEY_F12) {
280 return key - GLUT_KEY_F1 + KB_F1;
287 static unsigned int next_pow2(unsigned int x)