dos3d

view src/test.c @ 1:0b7f840afe4a

palette management
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 21 Nov 2011 08:35:58 +0200
parents f04884489bad
children 0e781cc43178
line source
1 /*
2 256-color 3D graphics hack for real-mode DOS.
3 Copyright (C) 2011 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <signal.h>
22 #include <conio.h>
23 #include "vga.h"
24 #include "mingl.h"
25 #include "timer.h"
26 #include "mouse.h"
27 #include "palman.h"
29 static int init(void);
30 static void shutdown(void);
31 static void redraw(void);
32 static void draw_cursor(unsigned char *fb, int xsz, int ysz, int mx, int my, int cidx);
33 static int keyb(char key);
34 static void mouse_button(int bn, int x, int y);
35 static void mouse_motion(int x, int y);
36 static void sighandler(int s);
37 static int parse_args(int argc, char **argv);
38 static void print_perf(void);
40 static unsigned char *fbuf;
42 static int white_base, red_base, green_base, blue_base;
43 static int grad_range;
45 static int use_vsync = 1;
46 static int under_windows = 0;
47 static unsigned long num_frm;
49 enum { CUBE, SPHERE, TORUS, NUM_PRIMS };
50 static int prim = SPHERE;
51 static int auto_rotate = 1;
52 static float cam_theta, cam_phi;
54 static int mx, my;
56 int main(int argc, char **argv)
57 {
58 int mbn, prev_mx = -1, prev_my = -1, prev_mbn = 0;
60 if(parse_args(argc, argv) == -1) {
61 return 1;
62 }
64 if(init() == -1) {
65 return 1;
66 }
68 reset_timer();
70 for(;;) {
71 if(kbhit()) {
72 if(keyb(getch()) == 0) {
73 break;
74 }
75 }
77 mbn = read_mouse(&mx, &my);
78 if(mbn != prev_mbn) {
79 mouse_button(mbn, mx, my);
80 prev_mbn = mbn;
81 }
82 if(mx != prev_mx || my != prev_my) {
83 if(mbn) {
84 mouse_motion(mx, my);
85 }
86 prev_mx = mx;
87 prev_my = my;
88 }
90 redraw();
91 }
93 shutdown();
94 print_perf();
95 return 0;
96 }
98 static int init(void)
99 {
100 int i;
101 struct palm_color *pal;
103 init_timer(under_windows ? 0 : 100);
105 set_video_mode(0x13);
107 signal(SIGINT, sighandler);
108 signal(SIGSEGV, sighandler);
109 signal(SIGFPE, sighandler);
110 signal(SIGILL, sighandler);
111 signal(SIGABRT, sighandler);
113 palm_add_color(255, 255, 255);
114 palm_add_color(255, 0, 0);
115 palm_add_color(0, 255, 0);
116 palm_add_color(0, 0, 255);
117 palm_build();
119 white_base = palm_color_base(255, 255, 255);
120 red_base = palm_color_base(255, 0, 0);
121 green_base = palm_color_base(0, 255, 0);
122 blue_base = palm_color_base(0, 0, 255);
123 grad_range = palm_color_range();
125 pal = palm_palette();
126 for(i=0; i<palm_palette_size(); i++) {
127 set_palette(i, pal[i].r, pal[i].g, pal[i].b);
128 }
130 if(mgl_init(320, 200) == -1) {
131 fprintf(stderr, "mgl init failed\n");
132 return -1;
133 }
134 fbuf = mgl_framebuffer();
136 mgl_enable(MGL_CULL_FACE);
137 mgl_enable(MGL_SMOOTH);
138 mgl_color_range(grad_range - 1); /* gradient range */
140 mgl_enable(MGL_LIGHTING);
141 mgl_light_intensity(0, 1.0);
142 mgl_light_direction(0, -0.5, 0.5, 1);
144 mgl_matrix_mode(MGL_PROJECTION);
145 mgl_load_identity();
146 mgl_perspective(45.0, 320.0 / 200.0, 0.5, 100.0);
148 return 0;
149 }
151 static void shutdown(void)
152 {
153 mgl_free();
154 set_video_mode(3);
155 }
157 static void redraw(void)
158 {
159 float angle = get_msec() / 10.0;
160 mgl_clear(0);
162 mgl_matrix_mode(MGL_MODELVIEW);
163 mgl_load_identity();
164 if(auto_rotate) {
165 mgl_rotate(angle, 0, 0, 1);
166 mgl_rotate(angle * 0.5, 1, 0, 0);
167 } else {
168 mgl_rotate(cam_theta, 0, 1, 0);
169 mgl_rotate(cam_phi, 1, 0, 0);
170 }
171 mgl_translate(0, 0, -4);
173 switch(prim) {
174 case TORUS:
175 mgl_index(green_base);
176 mgl_torus(1.0, 0.25, 16, 8);
177 break;
178 case SPHERE:
179 mgl_index(blue_base);
180 mgl_sphere(1.0, 16, 8);
181 break;
182 case CUBE:
183 mgl_index(red_base);
184 mgl_cube(1.0);
185 }
187 if(!auto_rotate) {
188 draw_cursor(fbuf, 320, 200, mx, my, white_base + grad_range - 1);
189 }
191 copy_frame(fbuf);
192 if(use_vsync) {
193 wait_vsync();
194 }
195 num_frm++;
196 }
198 static void draw_cursor(unsigned char *fb, int xsz, int ysz, int mx, int my, int cidx)
199 {
200 static char img[] =
201 "oo........"
202 "oxo......."
203 "oxxo......"
204 "oxxxo....."
205 "oxxxxo...."
206 "oxxxxxo..."
207 "oxxxxxxo.."
208 "oxxxxxxxo."
209 "oxxxxxxxxo"
210 "oxxxxxoooo"
211 "oxxoxxo..."
212 "oxo.oxxo.."
213 "oo..oxxo.."
214 ".....oxxo."
215 ".....oxxo."
216 "......oo..";
217 int i, j, w = 10, h = 16;
219 if(mx < 0 || my < 0) {
220 return;
221 }
222 if(mx + w >= xsz) {
223 w = xsz - mx;
224 }
225 if(my + h >= ysz) {
226 h = ysz - my;
227 }
229 fb += my * xsz + mx;
230 for(i=0; i<h; i++) {
231 for(j=0; j<w; j++) {
232 char c = img[(i << 3) + (i << 1) + j];
233 if(c != '.') {
234 fb[j] = c == 'x' ? 0 : cidx;
235 }
236 }
237 fb += xsz;
238 }
239 }
241 static int keyb(char key)
242 {
243 switch(key) {
244 case 'q':
245 case 27:
246 return 0;
248 case ' ':
249 auto_rotate = !auto_rotate;
250 break;
252 case 'p':
253 prim = (prim + 1) % NUM_PRIMS;
254 break;
256 default:
257 break;
258 }
259 return 1;
260 }
262 static int bnstate;
263 static int prev_x, prev_y;
265 static void mouse_button(int bn, int x, int y)
266 {
267 bnstate = bn;
268 prev_x = x;
269 prev_y = y;
270 }
272 static void mouse_motion(int x, int y)
273 {
274 int dx, dy;
276 dx = x - prev_x;
277 dy = y - prev_y;
278 prev_x = x;
279 prev_y = y;
281 if(bnstate) {
282 cam_theta += dx;
283 cam_phi += dy;
285 if(cam_phi > 90) cam_phi = 90;
286 if(cam_phi < -90) cam_phi = -90;
287 }
288 }
290 static void sighandler(int s)
291 {
292 set_video_mode(3);
294 switch(s) {
295 case SIGABRT:
296 fprintf(stderr, "abort\n");
297 break;
299 case SIGILL:
300 fprintf(stderr, "illegal operation\n");
301 break;
303 case SIGSEGV:
304 fprintf(stderr, "segmentation fault\n");
305 break;
307 case SIGINT:
308 fprintf(stderr, "interrupted\n");
309 break;
311 case SIGFPE:
312 fprintf(stderr, "floating point exception\n");
313 break;
315 default:
316 fprintf(stderr, "unexpected signal\n");
317 }
319 exit(1);
320 }
322 static int parse_args(int argc, char **argv)
323 {
324 int i;
326 for(i=1; i<argc; i++) {
327 if(argv[i][0] == '-') {
328 if(argv[i][2] != 0) {
329 goto invalid;
330 }
331 switch(argv[i][1]) {
332 case 'a':
333 auto_rotate = !auto_rotate;
334 break;
336 case 'v':
337 use_vsync = !use_vsync;
338 break;
340 case 'p':
341 if(strcmp(argv[++i], "cube") == 0) {
342 prim = CUBE;
343 } else if(strcmp(argv[i], "sphere") == 0) {
344 prim = SPHERE;
345 } else if(strcmp(argv[i], "torus") == 0) {
346 prim = TORUS;
347 } else {
348 goto invalid;
349 }
350 break;
352 case 'w':
353 under_windows = 1;
354 break;
356 case 'h':
357 printf("Usage %s [options]\n", argv[0]);
358 printf("options:\n");
359 printf(" -p select one of (cube|sphere|torus)\n");
360 printf(" -v use vsync\n");
361 printf(" -w run under windows\n");
362 printf(" -h print usage information and exit\n");
363 exit(0);
365 default:
366 goto invalid;
367 }
368 } else {
369 goto invalid;
370 }
371 }
373 return 0;
375 invalid:
376 fprintf(stderr, "invalid argument: %s\n", argv[i]);
377 return -1;
378 }
381 static void print_perf(void)
382 {
383 unsigned long msec, avg_frame_time;
384 float sec, fps;
386 msec = get_msec();
387 if(!num_frm || msec < 1000) {
388 printf("leaving so soon? (%lu ms)\n", msec);
389 return;
390 }
392 sec = msec / 1000.0f;
393 fps = (float)num_frm / sec;
394 avg_frame_time = msec / num_frm;
396 printf("%lu frames in %.2f seconds\n", num_frm, sec);
397 printf(" avg. frame time: %lu ms\n", avg_frame_time);
398 printf(" avg. framerate: %.2f fps\n", fps);
399 }