91ce9daaf45a1e1ee92185443e19d3d122b0a72d
[gbajam22] / src / pc / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <ctype.h>
4 #include <assert.h>
5 #include "miniglut.h"
6 #include "game.h"
7 #include "gba.h"
8
9 static void display(void);
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 int translate_special(int skey);
17 static unsigned int next_pow2(unsigned int x);
18 static void set_fullscreen(int fs);
19 static void set_vsync(int vsync);
20
21 static unsigned int num_pressed;
22 static unsigned char keystate[256];
23
24 static unsigned long start_time;
25 static unsigned int modkeys;
26
27 static float win_aspect;
28 static unsigned int tex;
29
30 static int tex_xsz, tex_ysz;
31 static uint32_t convbuf[240 * 160];
32
33 #ifdef __unix__
34 #include <GL/glx.h>
35 static Display *xdpy;
36 static Window xwin;
37
38 static void (*glx_swap_interval_ext)();
39 static void (*glx_swap_interval_sgi)();
40 #endif
41 #ifdef _WIN32
42 #include <windows.h>
43 static PROC wgl_swap_interval_ext;
44 #endif
45
46 int main(int argc, char **argv)
47 {
48         glutInit(&argc, argv);
49         glutInitWindowSize(800, 600);
50         glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
51         glutCreateWindow("GBAjam22 PC build");
52
53         glutDisplayFunc(display);
54         glutIdleFunc(idle);
55         glutReshapeFunc(reshape);
56         glutKeyboardFunc(keydown);
57         glutKeyboardUpFunc(keyup);
58         glutSpecialFunc(skeydown);
59         glutSpecialUpFunc(skeyup);
60
61         glutSetCursor(GLUT_CURSOR_NONE);
62
63         glEnable(GL_TEXTURE_2D);
64         glEnable(GL_CULL_FACE);
65
66 #ifdef __unix__
67         xdpy = glXGetCurrentDisplay();
68         xwin = glXGetCurrentDrawable();
69
70         if(!(glx_swap_interval_ext = glXGetProcAddress((unsigned char*)"glXSwapIntervalEXT"))) {
71                 glx_swap_interval_sgi = glXGetProcAddress((unsigned char*)"glXSwapIntervalSGI");
72         }
73 #endif
74 #ifdef _WIN32
75         wgl_swap_interval_ext = wglGetProcAddress("wglSwapIntervalEXT");
76 #endif
77
78         glGenTextures(1, &tex);
79         glBindTexture(GL_TEXTURE_2D, tex);
80
81         tex_xsz = next_pow2(240);
82         tex_ysz = next_pow2(160);
83         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_xsz, tex_ysz, 0, GL_RGBA,
84                         GL_UNSIGNED_BYTE, 0);
85         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
86         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
87
88         glMatrixMode(GL_TEXTURE);
89         glLoadIdentity();
90         glScalef(240.0f / tex_xsz, 160.0f / tex_ysz, 1);
91
92         gamescr();
93         return 0;
94 }
95
96 void blit_frame(void *pixels, int vsync)
97 {
98         int i, npix = fb_width * fb_height;
99         uint32_t *dptr = convbuf;
100         uint16_t *sptr = pixels;
101
102         for(i=0; i<npix; i++) {
103                 int r = UNPACK_R16(*sptr);
104                 int g = UNPACK_G16(*sptr);
105                 int b = UNPACK_B16(*sptr);
106                 *dptr++ = PACK_RGB32(b, g, r);
107                 sptr++;
108         }
109
110         glBindTexture(GL_TEXTURE_2D, tex);
111         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, fb_width, fb_height, GL_RGBA,
112                         GL_UNSIGNED_BYTE, convbuf);
113
114         glMatrixMode(GL_MODELVIEW);
115         glLoadIdentity();
116         if(win_aspect >= 1.5f) {
117                 glScalef(1.5f / win_aspect, 1, 1);
118         } else {
119                 glScalef(1, win_aspect / 1.5f, 1);
120         }
121
122         glClear(GL_COLOR_BUFFER_BIT);
123
124         glBegin(GL_QUADS);
125         glTexCoord2f(0, 1);
126         glVertex2f(-1, -1);
127         glTexCoord2f(1, 1);
128         glVertex2f(1, -1);
129         glTexCoord2f(1, 0);
130         glVertex2f(1, 1);
131         glTexCoord2f(0, 0);
132         glVertex2f(-1, 1);
133         glEnd();
134
135         glutSwapBuffers();
136         assert(glGetError() == GL_NO_ERROR);
137 }
138
139 int kb_isdown(int key)
140 {
141         switch(key) {
142         case KB_ANY:
143                 return num_pressed;
144
145         case KB_ALT:
146                 return keystate[KB_LALT] + keystate[KB_RALT];
147
148         case KB_CTRL:
149                 return keystate[KB_LCTRL] + keystate[KB_RCTRL];
150         }
151
152         if(isalpha(key)) {
153                 key = tolower(key);
154         }
155         return keystate[key];
156 }
157
158 static void display(void)
159 {
160         inp_update();
161
162         time_msec = get_msec();
163         draw();
164 }
165
166 static void idle(void)
167 {
168         glutPostRedisplay();
169 }
170
171 static void reshape(int x, int y)
172 {
173         win_aspect = (float)x / (float)y;
174         glViewport(0, 0, x, y);
175 }
176
177 static void keydown(unsigned char key, int x, int y)
178 {
179         modkeys = glutGetModifiers();
180
181         keystate[key] = 1;
182         //game_key(key, 1);
183 }
184
185 static void keyup(unsigned char key, int x, int y)
186 {
187         keystate[key] = 0;
188         //game_key(key, 0);
189 }
190
191 static void skeydown(int key, int x, int y)
192 {
193         key = translate_special(key);
194         keystate[key] = 1;
195         //game_key(key, 1);
196 }
197
198 static void skeyup(int key, int x, int y)
199 {
200         key = translate_special(key);
201         keystate[key] = 0;
202         //game_key(key, 0);
203 }
204
205 static int translate_special(int skey)
206 {
207         switch(skey) {
208         case 127:
209                 return 127;
210 /*      case GLUT_KEY_LEFT:
211                 return KB_LEFT;
212         case GLUT_KEY_RIGHT:
213                 return KB_RIGHT;
214         case GLUT_KEY_UP:
215                 return KB_UP;
216         case GLUT_KEY_DOWN:
217                 return KB_DOWN;
218         case GLUT_KEY_PAGE_UP:
219                 return KB_PGUP;
220         case GLUT_KEY_PAGE_DOWN:
221                 return KB_PGDN;
222         case GLUT_KEY_HOME:
223                 return KB_HOME;
224         case GLUT_KEY_END:
225                 return KB_END;
226         default:
227                 if(skey >= GLUT_KEY_F1 && skey <= GLUT_KEY_F12) {
228                         return KB_F1 + skey - GLUT_KEY_F1;
229                 }
230                 */
231         }
232         return 0;
233 }
234
235 static unsigned int next_pow2(unsigned int x)
236 {
237         x--;
238         x |= x >> 1;
239         x |= x >> 2;
240         x |= x >> 4;
241         x |= x >> 8;
242         x |= x >> 16;
243         return x + 1;
244 }
245
246 static void set_fullscreen(int fs)
247 {
248         static int win_x, win_y;
249
250         if(fs) {
251                 if(win_x == 0) {
252                         win_x = glutGet(GLUT_WINDOW_WIDTH);
253                         win_y = glutGet(GLUT_WINDOW_HEIGHT);
254                         glutFullScreen();
255                 }
256         } else {
257                 if(win_x) {
258                         glutReshapeWindow(win_x, win_y);
259                         win_x = win_y = 0;
260                 }
261         }
262 }
263
264 #ifdef __unix__
265 static void set_vsync(int vsync)
266 {
267         vsync = vsync ? 1 : 0;
268         if(glx_swap_interval_ext) {
269                 glx_swap_interval_ext(xdpy, xwin, vsync);
270         } else if(glx_swap_interval_sgi) {
271                 glx_swap_interval_sgi(vsync);
272         }
273 }
274 #endif
275 #ifdef WIN32
276 static void set_vsync(int vsync)
277 {
278         if(wgl_swap_interval_ext) {
279                 wgl_swap_interval_ext(vsync ? 1 : 0);
280         }
281 }
282 #endif