rev |
line source |
nuclear@1
|
1 #include <stdio.h>
|
nuclear@1
|
2 #include <stdlib.h>
|
nuclear@1
|
3 #include <string.h>
|
nuclear@1
|
4 #include <math.h>
|
nuclear@1
|
5 #include "inttypes.h"
|
nuclear@1
|
6 #include "gfx.h"
|
nuclear@1
|
7 #include "keyb.h"
|
nuclear@1
|
8 #include "mouse.h"
|
nuclear@1
|
9 #include "logger.h"
|
nuclear@6
|
10 #include "min3d.h"
|
nuclear@6
|
11 #include "scene.h"
|
nuclear@1
|
12
|
nuclear@6
|
13 static bool init();
|
nuclear@6
|
14 static void cleanup();
|
nuclear@1
|
15 static void display();
|
nuclear@1
|
16 static void swap_buffers();
|
nuclear@1
|
17 static void handle_keyboard();
|
nuclear@1
|
18 static void handle_mouse();
|
nuclear@1
|
19 static bool parse_args(int argc, char **argv);
|
nuclear@1
|
20
|
nuclear@6
|
21 static int xsz = 640;
|
nuclear@6
|
22 static int ysz = 480;
|
nuclear@1
|
23 static int bpp = 16;
|
nuclear@1
|
24 static int bytespp;
|
nuclear@6
|
25 static bool novideo;
|
nuclear@1
|
26 static unsigned char *fb;
|
nuclear@1
|
27 static unsigned char *backbuf;
|
nuclear@1
|
28 static int rbits, gbits, bbits;
|
nuclear@1
|
29 static int rshift, gshift, bshift;
|
nuclear@1
|
30 static unsigned int rmask, gmask, bmask;
|
nuclear@1
|
31
|
nuclear@1
|
32 static bool quit;
|
nuclear@1
|
33
|
nuclear@6
|
34 struct m3d_image rbuf;
|
nuclear@6
|
35 static Scene *scn;
|
nuclear@6
|
36
|
nuclear@1
|
37 int main(int argc, char **argv)
|
nuclear@1
|
38 {
|
nuclear@1
|
39 if(!parse_args(argc, argv)) {
|
nuclear@1
|
40 return 1;
|
nuclear@1
|
41 }
|
nuclear@6
|
42 if(!init()) {
|
nuclear@1
|
43 return 1;
|
nuclear@1
|
44 }
|
nuclear@1
|
45
|
nuclear@1
|
46 // main loop
|
nuclear@1
|
47 for(;;) {
|
nuclear@1
|
48 handle_keyboard();
|
nuclear@1
|
49 handle_mouse();
|
nuclear@1
|
50 if(quit) break;
|
nuclear@1
|
51
|
nuclear@1
|
52 display();
|
nuclear@6
|
53
|
nuclear@6
|
54 if(novideo) break;
|
nuclear@1
|
55 }
|
nuclear@1
|
56
|
nuclear@6
|
57 cleanup();
|
nuclear@1
|
58 printf("Thank you for using Rayzor!\n");
|
nuclear@1
|
59 return 0;
|
nuclear@1
|
60 }
|
nuclear@1
|
61
|
nuclear@6
|
62 static bool init()
|
nuclear@6
|
63 {
|
nuclear@6
|
64 if(!novideo) {
|
nuclear@6
|
65 if(kb_init(32) == -1) {
|
nuclear@6
|
66 fprintf(stderr, "failed to initialize keyboard driver\n");
|
nuclear@6
|
67 return false;
|
nuclear@6
|
68 }
|
nuclear@6
|
69
|
nuclear@6
|
70 if(!(fb = (unsigned char*)set_video_mode(xsz, ysz, bpp))) {
|
nuclear@6
|
71 set_text_mode();
|
nuclear@6
|
72 fprintf(stderr, "failed to set video mode: %dx%d %dbpp\n", xsz, ysz, bpp);
|
nuclear@6
|
73 return false;
|
nuclear@6
|
74 }
|
nuclear@6
|
75 bpp = get_color_depth();
|
nuclear@6
|
76 get_color_bits(&rbits, &gbits, &bbits);
|
nuclear@6
|
77 get_color_shift(&rshift, &gshift, &bshift);
|
nuclear@6
|
78 get_color_mask(&rmask, &gmask, &bmask);
|
nuclear@6
|
79 bytespp = (int)ceil(bpp / 8.0);
|
nuclear@6
|
80
|
nuclear@6
|
81 printlog("bpp: %d (%d %d %d)\n", bpp, rbits, gbits, bbits);
|
nuclear@6
|
82 printlog("shift: %d %d %d\n", rshift, gshift, bshift);
|
nuclear@6
|
83 printlog("mask: %x %x %x\n", rmask, gmask, bmask);
|
nuclear@6
|
84 } else {
|
nuclear@6
|
85 logger_output(stdout);
|
nuclear@6
|
86 printlog("novideo (debug) mode\n");
|
nuclear@6
|
87 bpp = 24;
|
nuclear@6
|
88 rbits = gbits = bbits = 8;
|
nuclear@6
|
89 bytespp = 3;
|
nuclear@6
|
90 }
|
nuclear@6
|
91
|
nuclear@6
|
92 backbuf = new unsigned char[xsz * ysz * 3];
|
nuclear@6
|
93 if(!backbuf) {
|
nuclear@6
|
94 return false;
|
nuclear@6
|
95 }
|
nuclear@6
|
96
|
nuclear@6
|
97 m3d_init();
|
nuclear@6
|
98 rbuf.pixels = backbuf;
|
nuclear@6
|
99 rbuf.xsz = xsz;
|
nuclear@6
|
100 rbuf.ysz = ysz;
|
nuclear@6
|
101 m3d_set_buffers(&rbuf, 0);
|
nuclear@6
|
102
|
nuclear@6
|
103 m3d_matrix_mode(M3D_PROJECTION);
|
nuclear@6
|
104 m3d_load_identity();
|
nuclear@6
|
105 m3d_perspective(50.0, (float)xsz / (float)ysz, 0.5, 500.0);
|
nuclear@6
|
106
|
nuclear@6
|
107 scn = new Scene;
|
nuclear@6
|
108
|
nuclear@6
|
109 Sphere *sph = new Sphere;
|
nuclear@6
|
110 scn->add_object(sph);
|
nuclear@6
|
111
|
nuclear@6
|
112 return true;
|
nuclear@6
|
113 }
|
nuclear@6
|
114
|
nuclear@6
|
115 static void cleanup()
|
nuclear@6
|
116 {
|
nuclear@6
|
117 delete scn;
|
nuclear@6
|
118
|
nuclear@6
|
119 m3d_shutdown();
|
nuclear@6
|
120 delete [] backbuf;
|
nuclear@6
|
121
|
nuclear@6
|
122 if(!novideo) {
|
nuclear@6
|
123 set_text_mode();
|
nuclear@6
|
124 kb_shutdown();
|
nuclear@6
|
125 }
|
nuclear@6
|
126 }
|
nuclear@6
|
127
|
nuclear@6
|
128
|
nuclear@1
|
129 static void display()
|
nuclear@1
|
130 {
|
nuclear@6
|
131 m3d_clear(M3D_COLOR_BUFFER_BIT);
|
nuclear@1
|
132
|
nuclear@6
|
133 m3d_matrix_mode(M3D_MODELVIEW);
|
nuclear@6
|
134 m3d_load_identity();
|
nuclear@6
|
135 m3d_translate(0, 0, -10);
|
nuclear@6
|
136
|
nuclear@6
|
137 scn->draw();
|
nuclear@6
|
138
|
nuclear@6
|
139 if(!novideo) {
|
nuclear@6
|
140 swap_buffers();
|
nuclear@6
|
141 wait_vsync();
|
nuclear@1
|
142 }
|
nuclear@1
|
143 }
|
nuclear@1
|
144
|
nuclear@1
|
145 #define PACK_RGB(r, g, b) \
|
nuclear@1
|
146 ((((r) << rshift) & rmask) | \
|
nuclear@1
|
147 (((g) << gshift) & gmask) | \
|
nuclear@1
|
148 (((b) << bshift) & bmask))
|
nuclear@1
|
149
|
nuclear@1
|
150 static void swap_buffers()
|
nuclear@1
|
151 {
|
nuclear@1
|
152 unsigned char *src = backbuf;
|
nuclear@1
|
153 int num_pixels = xsz * ysz;
|
nuclear@1
|
154
|
nuclear@1
|
155 switch(bpp) {
|
nuclear@1
|
156 case 32:
|
nuclear@1
|
157 {
|
nuclear@1
|
158 uint32_t *dest = (uint32_t*)fb;
|
nuclear@1
|
159 for(int i=0; i<num_pixels; i++) {
|
nuclear@1
|
160 *dest++ = PACK_RGB(src[0], src[1], src[2]);
|
nuclear@1
|
161 src += 3;
|
nuclear@1
|
162 }
|
nuclear@1
|
163 }
|
nuclear@1
|
164 break;
|
nuclear@1
|
165
|
nuclear@1
|
166 case 24:
|
nuclear@1
|
167 memcpy(fb, backbuf, num_pixels * 3);
|
nuclear@1
|
168 break;
|
nuclear@1
|
169
|
nuclear@1
|
170 case 16:
|
nuclear@1
|
171 case 15:
|
nuclear@1
|
172 {
|
nuclear@1
|
173 int srs = 8 - rbits;
|
nuclear@1
|
174 int sgs = 8 - gbits;
|
nuclear@1
|
175 int sbs = 8 - bbits;
|
nuclear@1
|
176 uint16_t *dest = (uint16_t*)fb;
|
nuclear@1
|
177 for(int i=0; i<num_pixels; i++) {
|
nuclear@1
|
178 *dest++ = PACK_RGB(src[0] >> srs, src[1] >> sgs, src[2] >> sbs);
|
nuclear@1
|
179 src += 3;
|
nuclear@1
|
180 }
|
nuclear@1
|
181 }
|
nuclear@1
|
182 break;
|
nuclear@1
|
183
|
nuclear@1
|
184 default:
|
nuclear@1
|
185 break;
|
nuclear@1
|
186 }
|
nuclear@1
|
187 }
|
nuclear@1
|
188
|
nuclear@1
|
189 static void handle_keyboard()
|
nuclear@1
|
190 {
|
nuclear@5
|
191 int key;
|
nuclear@1
|
192
|
nuclear@6
|
193 if(novideo) return;
|
nuclear@6
|
194
|
nuclear@5
|
195 while((key = kb_getkey()) != -1) {
|
nuclear@5
|
196 switch(key) {
|
nuclear@5
|
197 case 27:
|
nuclear@5
|
198 quit = true;
|
nuclear@5
|
199 return;
|
nuclear@5
|
200 }
|
nuclear@1
|
201 }
|
nuclear@1
|
202 }
|
nuclear@1
|
203
|
nuclear@1
|
204 static void handle_mouse()
|
nuclear@1
|
205 {
|
nuclear@1
|
206 }
|
nuclear@1
|
207
|
nuclear@1
|
208 static struct {
|
nuclear@1
|
209 int opt;
|
nuclear@1
|
210 const char *lopt;
|
nuclear@1
|
211 const char *desc;
|
nuclear@1
|
212 } options[] = {
|
nuclear@1
|
213 {'s', "size", "resolution <xres>x<yres>[:bpp]"},
|
nuclear@6
|
214 {'n', "novid", "don't switch video mode (for debugging)"},
|
nuclear@1
|
215 {'h', "help", "print usage information and exit"},
|
nuclear@1
|
216 {-1, 0, 0}
|
nuclear@1
|
217 };
|
nuclear@1
|
218
|
nuclear@1
|
219 static void print_usage(const char *argv0)
|
nuclear@1
|
220 {
|
nuclear@1
|
221 printf("%s usage\n", argv0);
|
nuclear@1
|
222 for(int i=0; options[i].opt != -1; i++) {
|
nuclear@1
|
223 printf(" -%c, -%s: %s\n", options[i].opt, options[i].lopt, options[i].desc);
|
nuclear@1
|
224 }
|
nuclear@1
|
225 exit(0);
|
nuclear@1
|
226 }
|
nuclear@1
|
227
|
nuclear@1
|
228 static bool parse_args(int argc, char **argv)
|
nuclear@1
|
229 {
|
nuclear@1
|
230 for(int i=1; i<argc; i++) {
|
nuclear@1
|
231 if(argv[i][0] == '-') {
|
nuclear@1
|
232 int opt = -1;
|
nuclear@1
|
233
|
nuclear@1
|
234 for(int j=0; options[j].opt != -1; j++) {
|
nuclear@1
|
235 if(argv[i][2] == 0) {
|
nuclear@1
|
236 if(argv[i][1] == options[j].opt) {
|
nuclear@1
|
237 opt = options[j].opt;
|
nuclear@1
|
238 break;
|
nuclear@1
|
239 }
|
nuclear@1
|
240 } else {
|
nuclear@1
|
241 if(strcmp(argv[i] + 1, options[j].lopt) == 0) {
|
nuclear@1
|
242 opt = options[j].opt;
|
nuclear@1
|
243 break;
|
nuclear@1
|
244 }
|
nuclear@1
|
245 }
|
nuclear@1
|
246 }
|
nuclear@1
|
247
|
nuclear@1
|
248 switch(opt) {
|
nuclear@1
|
249 case 's':
|
nuclear@1
|
250 if(sscanf(argv[++i], "%dx%d:%d", &xsz, &ysz, &bpp) < 2) {
|
nuclear@1
|
251 fprintf(stderr, "%s must be followed by a resolution: WxH\n", argv[i - 1]);
|
nuclear@1
|
252 return false;
|
nuclear@1
|
253 }
|
nuclear@1
|
254 break;
|
nuclear@1
|
255
|
nuclear@6
|
256 case 'n':
|
nuclear@6
|
257 novideo = true;
|
nuclear@6
|
258 break;
|
nuclear@6
|
259
|
nuclear@1
|
260 case 'h':
|
nuclear@1
|
261 print_usage(argv[0]); // doesn't return
|
nuclear@1
|
262 break;
|
nuclear@1
|
263
|
nuclear@1
|
264 default:
|
nuclear@1
|
265 fprintf(stderr, "unknown option: %s\n", argv[i]);
|
nuclear@1
|
266 return false;
|
nuclear@1
|
267 }
|
nuclear@1
|
268 } else {
|
nuclear@1
|
269 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
|
nuclear@1
|
270 return false;
|
nuclear@1
|
271 }
|
nuclear@1
|
272 }
|
nuclear@1
|
273 return true;
|
nuclear@1
|
274 }
|