rayzor

view src/main.cc @ 9:70e332156d02

moving along
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 10 Apr 2014 02:31:31 +0300
parents 75bc89c2abc4
children 235c8b764c0b
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5 #include <signal.h>
6 #include "inttypes.h"
7 #include "gfx.h"
8 #include "keyb.h"
9 #include "mouse.h"
10 #include "logger.h"
11 #include "scene.h"
12 #include "rayzor.h"
13 #include "screen.h"
14 #include "modeller.h"
15 #include "renderer.h"
16 #include "scrman.h"
18 static bool init();
19 static void cleanup();
20 static void display();
21 static void swap_buffers();
22 static void draw_cursor(uint32_t *buf, int mx, int my);
23 static void handle_keyboard();
24 static void handle_mouse();
25 static bool parse_args(int argc, char **argv);
26 static void sig(int s);
28 uint32_t *fb_pixels;
29 int fb_width = 640;
30 int fb_height = 480;
31 int fb_bpp = 32;
32 Scene *scene;
34 static int bytespp;
35 static bool novideo;
36 static void *fb;
37 static int rbits, gbits, bbits;
38 static int rshift, gshift, bshift;
39 static unsigned int rmask, gmask, bmask;
41 static bool use_mouse;
42 static int mouse_x, mouse_y;
43 static bool quit;
45 int main(int argc, char **argv)
46 {
47 if(!parse_args(argc, argv)) {
48 return 1;
49 }
50 if(!init()) {
51 return 1;
52 }
54 // main loop
55 for(;;) {
56 handle_keyboard();
57 handle_mouse();
58 if(quit) break;
60 display();
62 if(novideo) break;
63 }
65 cleanup();
66 printf("Thank you for using Rayzor!\n");
67 return 0;
68 }
70 void quit_app()
71 {
72 quit = true;
73 }
75 static bool init()
76 {
77 signal(SIGINT, sig);
78 signal(SIGSEGV, sig);
79 signal(SIGILL, sig);
80 signal(SIGFPE, sig);
82 if(!novideo) {
83 if(kb_init(32) == -1) {
84 fprintf(stderr, "failed to initialize keyboard driver\n");
85 return false;
86 }
88 if(!(fb = set_video_mode(fb_width, fb_height, fb_bpp))) {
89 set_text_mode();
90 fprintf(stderr, "failed to set video mode: %dx%d %dbpp\n", fb_width, fb_height, fb_bpp);
91 return false;
92 }
93 fb_bpp = get_color_depth();
94 get_color_bits(&rbits, &gbits, &bbits);
95 get_color_shift(&rshift, &gshift, &bshift);
96 get_color_mask(&rmask, &gmask, &bmask);
97 bytespp = (int)ceil(fb_bpp / 8.0);
99 printlog("bpp: %d (%d %d %d)\n", fb_bpp, rbits, gbits, bbits);
100 printlog("shift: %d %d %d\n", rshift, gshift, bshift);
101 printlog("mask: %x %x %x\n", rmask, gmask, bmask);
103 if(have_mouse()) {
104 use_mouse = true;
105 set_mouse_limits(0, 0, fb_width - 1, fb_height - 1);
106 }
107 } else {
108 logger_output(stdout);
109 printlog("novideo (debug) mode\n");
110 fb_bpp = 32;
111 rbits = gbits = bbits = 8;
112 bytespp = 3;
113 }
115 fb_pixels = new uint32_t[fb_width * fb_height * 4];
116 if(!fb_pixels) {
117 return false;
118 }
120 scene = new Scene;
122 Sphere *sph = new Sphere;
123 scene->add_object(sph);
125 Modeller *modeller = new Modeller;
126 if(!modeller->init()) {
127 return false;
128 }
129 add_screen(modeller);
131 Renderer *renderer = new Renderer;
132 if(!renderer->init()) {
133 return false;
134 }
135 add_screen(renderer);
137 activate_screen(modeller); // start the modeller screen
138 return true;
139 }
141 static void cleanup()
142 {
143 delete scene;
144 delete [] fb_pixels;
146 destroy_screens();
148 if(!novideo) {
149 set_text_mode();
150 kb_shutdown();
151 }
152 }
154 static void display()
155 {
156 Screen *scr = active_screen();
157 if(scr) {
158 scr->update();
159 scr->draw();
160 }
162 // draw the mouse cursor
163 if(use_mouse) {
164 draw_cursor(fb_pixels, mouse_x, mouse_y);
165 }
167 if(!novideo) {
168 swap_buffers();
169 wait_vsync();
170 }
171 }
173 #define PACK_RGB(r, g, b) \
174 ((((r) << rshift) & rmask) | \
175 (((g) << gshift) & gmask) | \
176 (((b) << bshift) & bmask))
178 #define UNPACK_RED(c) (((c) >> 16) & 0xff)
179 #define UNPACK_GREEN(c) (((c) >> 8) & 0xff)
180 #define UNPACK_BLUE(c) ((c) & 0xff)
182 static void swap_buffers()
183 {
184 uint32_t *src = fb_pixels;
185 int num_pixels = fb_width * fb_height;
187 switch(fb_bpp) {
188 case 32:
189 memcpy(fb, fb_pixels, num_pixels * 4);
190 break;
192 case 24:
193 {
194 unsigned char *dest = (unsigned char*)fb;
195 for(int i=0; i<num_pixels; i++) {
196 uint32_t c = *src++;
197 *dest++ = UNPACK_RED(c);
198 *dest++ = UNPACK_GREEN(c);
199 *dest++ = UNPACK_BLUE(c);
200 }
201 }
202 break;
204 case 16:
205 case 15:
206 {
207 uint16_t *dest = (uint16_t*)fb;
208 for(int i=0; i<num_pixels; i++) {
209 uint32_t c = *src++;
210 unsigned char r = UNPACK_RED(c);
211 unsigned char g = UNPACK_GREEN(c);
212 unsigned char b = UNPACK_BLUE(c);
214 *dest++ = PACK_RGB(r, g, b);
215 }
216 }
217 break;
219 default:
220 break;
221 }
222 }
224 static void draw_cursor(uint32_t *buf, int mx, int my)
225 {
226 uint32_t *cptr = buf + my * fb_width + mx;
227 int i, cw[2] = {4, 4}, ch[2] = {4, 4};
229 if(mx < cw[0]) cw[0] = mx;
230 if(my < ch[0]) ch[0] = my;
231 if(fb_width - mx < cw[1]) cw[1] = fb_width - mx - 1;
232 if(fb_height - my < ch[1]) ch[1] = fb_height - my - 1;
234 for(i=1; i<cw[0]; i++) {
235 int idx = -i;
236 cptr[idx] = 0xffffff;
237 }
238 for(i=1; i<cw[1]; i++) {
239 int idx = i;
240 cptr[idx] = 0xffffff;
241 }
242 for(i=1; i<ch[0]; i++) {
243 int idx = -i * fb_width;
244 cptr[idx] = 0xffffff;
245 }
246 for(i=1; i<ch[1]; i++) {
247 int idx = i * fb_width;
248 cptr[idx] = 0xffffff;
249 }
250 }
252 static void handle_keyboard()
253 {
254 int key;
255 Screen *scr = active_screen();
257 if(novideo) return;
259 while((key = kb_getkey()) != -1) {
260 scr->handle_keyboard(key, true); // TODO also generate release events...
261 }
262 }
264 static void handle_mouse()
265 {
266 static int prev_mx, prev_my, prev_bnmask, bndiff;
267 int mx, my, bnmask;
268 Screen *scr = active_screen();
270 if(!use_mouse || novideo) return;
272 bnmask = read_mouse(&mx, &my);
273 if(scr && (bndiff = bnmask ^ prev_bnmask)) {
274 for(int i=0; i<8; i++) {
275 int bit = 1 << i;
276 if(bndiff & bit) {
277 scr->handle_mbutton(i, bnmask & bit, mx, my);
278 }
279 }
280 }
281 prev_bnmask = bnmask;
283 if(scr && (mx != prev_mx || my != prev_my)) {
284 scr->handle_mmotion(mx, my);
285 }
286 prev_mx = mx;
287 prev_my = my;
288 }
291 static struct {
292 int opt;
293 const char *lopt;
294 const char *desc;
295 } options[] = {
296 {'s', "size", "resolution <xres>x<yres>[:bpp]"},
297 {'n', "novid", "don't switch video mode (for debugging)"},
298 {'h', "help", "print usage information and exit"},
299 {-1, 0, 0}
300 };
302 static void print_usage(const char *argv0)
303 {
304 printf("%s usage\n", argv0);
305 for(int i=0; options[i].opt != -1; i++) {
306 printf(" -%c, -%s: %s\n", options[i].opt, options[i].lopt, options[i].desc);
307 }
308 exit(0);
309 }
311 static bool parse_args(int argc, char **argv)
312 {
313 for(int i=1; i<argc; i++) {
314 if(argv[i][0] == '-') {
315 int opt = -1;
317 for(int j=0; options[j].opt != -1; j++) {
318 if(argv[i][2] == 0) {
319 if(argv[i][1] == options[j].opt) {
320 opt = options[j].opt;
321 break;
322 }
323 } else {
324 if(strcmp(argv[i] + 1, options[j].lopt) == 0) {
325 opt = options[j].opt;
326 break;
327 }
328 }
329 }
331 switch(opt) {
332 case 's':
333 if(sscanf(argv[++i], "%dx%d:%d", &fb_width, &fb_height, &fb_bpp) < 2) {
334 fprintf(stderr, "%s must be followed by a resolution: WxH\n", argv[i - 1]);
335 return false;
336 }
337 break;
339 case 'n':
340 novideo = true;
341 break;
343 case 'h':
344 print_usage(argv[0]); // doesn't return
345 break;
347 default:
348 fprintf(stderr, "unknown option: %s\n", argv[i]);
349 return false;
350 }
351 } else {
352 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
353 return false;
354 }
355 }
356 return true;
357 }
359 static void sig(int s)
360 {
361 cleanup();
362 fprintf(stderr, "signal caught: %d\n", s);
363 exit(1);
364 }