dos3d
diff src/test.c @ 0:f04884489bad
dos3d initial import
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 21 Nov 2011 06:14:01 +0200 |
parents | |
children | 0b7f840afe4a |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/test.c Mon Nov 21 06:14:01 2011 +0200 1.3 @@ -0,0 +1,399 @@ 1.4 +/* 1.5 +256-color 3D graphics hack for real-mode DOS. 1.6 +Copyright (C) 2011 John Tsiombikas <nuclear@member.fsf.org> 1.7 + 1.8 +This program is free software: you can redistribute it and/or modify 1.9 +it under the terms of the GNU General Public License as published by 1.10 +the Free Software Foundation, either version 3 of the License, or 1.11 +(at your option) any later version. 1.12 + 1.13 +This program is distributed in the hope that it will be useful, 1.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 1.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.16 +GNU General Public License for more details. 1.17 + 1.18 +You should have received a copy of the GNU General Public License 1.19 +along with this program. If not, see <http://www.gnu.org/licenses/>. 1.20 +*/ 1.21 +#include <stdio.h> 1.22 +#include <stdlib.h> 1.23 +#include <string.h> 1.24 +#include <signal.h> 1.25 +#include <conio.h> 1.26 +#include "vga.h" 1.27 +#include "mingl.h" 1.28 +#include "timer.h" 1.29 +#include "mouse.h" 1.30 + 1.31 +#define ROFFS 64 1.32 +#define GOFFS 128 1.33 +#define BOFFS 192 1.34 + 1.35 +static int init(void); 1.36 +static void shutdown(void); 1.37 +static void redraw(void); 1.38 +static void draw_cursor(unsigned char *fb, int xsz, int ysz, int mx, int my, int cidx); 1.39 +static int keyb(char key); 1.40 +static void mouse_button(int bn, int x, int y); 1.41 +static void mouse_motion(int x, int y); 1.42 +static void sighandler(int s); 1.43 +static int parse_args(int argc, char **argv); 1.44 +static void print_perf(void); 1.45 + 1.46 +static unsigned char *fbuf; 1.47 + 1.48 +static int use_vsync = 1; 1.49 +static int under_windows = 0; 1.50 +static unsigned long num_frm; 1.51 + 1.52 +enum { CUBE, SPHERE, TORUS, NUM_PRIMS }; 1.53 +static int prim = SPHERE; 1.54 +static int auto_rotate = 1; 1.55 +static float cam_theta, cam_phi; 1.56 + 1.57 +static int mx, my; 1.58 + 1.59 +int main(int argc, char **argv) 1.60 +{ 1.61 + int mbn, prev_mx = -1, prev_my = -1, prev_mbn = 0; 1.62 + 1.63 + if(parse_args(argc, argv) == -1) { 1.64 + return 1; 1.65 + } 1.66 + 1.67 + if(init() == -1) { 1.68 + return 1; 1.69 + } 1.70 + 1.71 + reset_timer(); 1.72 + 1.73 + for(;;) { 1.74 + if(kbhit()) { 1.75 + if(keyb(getch()) == 0) { 1.76 + break; 1.77 + } 1.78 + } 1.79 + 1.80 + mbn = read_mouse(&mx, &my); 1.81 + if(mbn != prev_mbn) { 1.82 + mouse_button(mbn, mx, my); 1.83 + prev_mbn = mbn; 1.84 + } 1.85 + if(mx != prev_mx || my != prev_my) { 1.86 + if(mbn) { 1.87 + mouse_motion(mx, my); 1.88 + } 1.89 + prev_mx = mx; 1.90 + prev_my = my; 1.91 + } 1.92 + 1.93 + redraw(); 1.94 + } 1.95 + 1.96 + shutdown(); 1.97 + print_perf(); 1.98 + return 0; 1.99 +} 1.100 + 1.101 +static int init(void) 1.102 +{ 1.103 + int i; 1.104 + 1.105 + init_timer(under_windows ? 0 : 100); 1.106 + 1.107 + set_video_mode(0x13); 1.108 + 1.109 + signal(SIGINT, sighandler); 1.110 + signal(SIGSEGV, sighandler); 1.111 + signal(SIGFPE, sighandler); 1.112 + signal(SIGILL, sighandler); 1.113 + signal(SIGABRT, sighandler); 1.114 + 1.115 + for(i=0; i<64; i++) { 1.116 + int x = i << 2; 1.117 + set_palette(i, x, x, x); 1.118 + set_palette(i + ROFFS, x, 0, 0); 1.119 + set_palette(i + GOFFS, 0, x, 0); 1.120 + set_palette(i + BOFFS, 0, 0, x); 1.121 + } 1.122 + 1.123 + if(mgl_init(320, 200) == -1) { 1.124 + fprintf(stderr, "mgl init failed\n"); 1.125 + return -1; 1.126 + } 1.127 + fbuf = mgl_framebuffer(); 1.128 + 1.129 + mgl_enable(MGL_CULL_FACE); 1.130 + mgl_enable(MGL_SMOOTH); 1.131 + mgl_color_range(63); /* gradient range */ 1.132 + 1.133 + mgl_enable(MGL_LIGHTING); 1.134 + mgl_light_intensity(0, 1.0); 1.135 + mgl_light_direction(0, -0.5, 0.5, 1); 1.136 + 1.137 + mgl_matrix_mode(MGL_PROJECTION); 1.138 + mgl_load_identity(); 1.139 + mgl_perspective(45.0, 320.0 / 200.0, 0.5, 100.0); 1.140 + 1.141 + return 0; 1.142 +} 1.143 + 1.144 +static void shutdown(void) 1.145 +{ 1.146 + mgl_free(); 1.147 + set_video_mode(3); 1.148 +} 1.149 + 1.150 +static void redraw(void) 1.151 +{ 1.152 + float angle = get_msec() / 10.0; 1.153 + mgl_clear(0); 1.154 + 1.155 + mgl_matrix_mode(MGL_MODELVIEW); 1.156 + mgl_load_identity(); 1.157 + if(auto_rotate) { 1.158 + mgl_rotate(angle, 0, 0, 1); 1.159 + mgl_rotate(angle * 0.5, 1, 0, 0); 1.160 + } else { 1.161 + mgl_rotate(cam_theta, 0, 1, 0); 1.162 + mgl_rotate(cam_phi, 1, 0, 0); 1.163 + } 1.164 + mgl_translate(0, 0, -4); 1.165 + 1.166 + switch(prim) { 1.167 + case TORUS: 1.168 + mgl_index(GOFFS); 1.169 + mgl_torus(1.0, 0.25, 16, 8); 1.170 + break; 1.171 + case SPHERE: 1.172 + mgl_index(BOFFS); 1.173 + mgl_sphere(1.0, 16, 8); 1.174 + break; 1.175 + case CUBE: 1.176 + mgl_index(ROFFS); 1.177 + mgl_cube(1.0); 1.178 + } 1.179 + 1.180 + /*mgl_begin(MGL_QUADS); 1.181 + mgl_index(ROFFS); 1.182 + mgl_color1f(1.0); 1.183 + mgl_vertex2f(-1, -1); 1.184 + mgl_vertex2f(1, -1); 1.185 + mgl_color1f(0.1); 1.186 + mgl_vertex2f(1, 1); 1.187 + mgl_vertex2f(-1, 1); 1.188 + mgl_end();*/ 1.189 + 1.190 + if(!auto_rotate) { 1.191 + draw_cursor(fbuf, 320, 200, mx, my, 63); 1.192 + } 1.193 + 1.194 + copy_frame(fbuf); 1.195 + if(use_vsync) { 1.196 + wait_vsync(); 1.197 + } 1.198 + num_frm++; 1.199 +} 1.200 + 1.201 +static void draw_cursor(unsigned char *fb, int xsz, int ysz, int mx, int my, int cidx) 1.202 +{ 1.203 + static char img[] = 1.204 + "oo........" 1.205 + "oxo......." 1.206 + "oxxo......" 1.207 + "oxxxo....." 1.208 + "oxxxxo...." 1.209 + "oxxxxxo..." 1.210 + "oxxxxxxo.." 1.211 + "oxxxxxxxo." 1.212 + "oxxxxxxxxo" 1.213 + "oxxxxxoooo" 1.214 + "oxxoxxo..." 1.215 + "oxo.oxxo.." 1.216 + "oo..oxxo.." 1.217 + ".....oxxo." 1.218 + ".....oxxo." 1.219 + "......oo.."; 1.220 + int i, j, w = 10, h = 16; 1.221 + 1.222 + if(mx < 0 || my < 0) { 1.223 + return; 1.224 + } 1.225 + if(mx + w >= xsz) { 1.226 + w = xsz - mx; 1.227 + } 1.228 + if(my + h >= ysz) { 1.229 + h = ysz - my; 1.230 + } 1.231 + 1.232 + fb += my * xsz + mx; 1.233 + for(i=0; i<h; i++) { 1.234 + for(j=0; j<w; j++) { 1.235 + char c = img[(i << 3) + (i << 1) + j]; 1.236 + if(c != '.') { 1.237 + fb[j] = c == 'x' ? 0 : cidx; 1.238 + } 1.239 + } 1.240 + fb += xsz; 1.241 + } 1.242 +} 1.243 + 1.244 +static int keyb(char key) 1.245 +{ 1.246 + switch(key) { 1.247 + case 'q': 1.248 + case 27: 1.249 + return 0; 1.250 + 1.251 + case ' ': 1.252 + auto_rotate = !auto_rotate; 1.253 + break; 1.254 + 1.255 + case 'p': 1.256 + prim = (prim + 1) % NUM_PRIMS; 1.257 + break; 1.258 + 1.259 + default: 1.260 + break; 1.261 + } 1.262 + return 1; 1.263 +} 1.264 + 1.265 +static int bnstate; 1.266 +static int prev_x, prev_y; 1.267 + 1.268 +static void mouse_button(int bn, int x, int y) 1.269 +{ 1.270 + bnstate = bn; 1.271 + prev_x = x; 1.272 + prev_y = y; 1.273 +} 1.274 + 1.275 +static void mouse_motion(int x, int y) 1.276 +{ 1.277 + int dx, dy; 1.278 + 1.279 + dx = x - prev_x; 1.280 + dy = y - prev_y; 1.281 + prev_x = x; 1.282 + prev_y = y; 1.283 + 1.284 + if(bnstate) { 1.285 + cam_theta += dx; 1.286 + cam_phi += dy; 1.287 + 1.288 + if(cam_phi > 90) cam_phi = 90; 1.289 + if(cam_phi < -90) cam_phi = -90; 1.290 + } 1.291 +} 1.292 + 1.293 +static void sighandler(int s) 1.294 +{ 1.295 + set_video_mode(3); 1.296 + 1.297 + switch(s) { 1.298 + case SIGABRT: 1.299 + fprintf(stderr, "abort\n"); 1.300 + break; 1.301 + 1.302 + case SIGILL: 1.303 + fprintf(stderr, "illegal operation\n"); 1.304 + break; 1.305 + 1.306 + case SIGSEGV: 1.307 + fprintf(stderr, "segmentation fault\n"); 1.308 + break; 1.309 + 1.310 + case SIGINT: 1.311 + fprintf(stderr, "interrupted\n"); 1.312 + break; 1.313 + 1.314 + case SIGFPE: 1.315 + fprintf(stderr, "floating point exception\n"); 1.316 + break; 1.317 + 1.318 + default: 1.319 + fprintf(stderr, "unexpected signal\n"); 1.320 + } 1.321 + 1.322 + exit(1); 1.323 +} 1.324 + 1.325 +static int parse_args(int argc, char **argv) 1.326 +{ 1.327 + int i; 1.328 + 1.329 + for(i=1; i<argc; i++) { 1.330 + if(argv[i][0] == '-') { 1.331 + if(argv[i][2] != 0) { 1.332 + goto invalid; 1.333 + } 1.334 + switch(argv[i][1]) { 1.335 + case 'a': 1.336 + auto_rotate = !auto_rotate; 1.337 + break; 1.338 + 1.339 + case 'v': 1.340 + use_vsync = !use_vsync; 1.341 + break; 1.342 + 1.343 + case 'p': 1.344 + if(strcmp(argv[++i], "cube") == 0) { 1.345 + prim = CUBE; 1.346 + } else if(strcmp(argv[i], "sphere") == 0) { 1.347 + prim = SPHERE; 1.348 + } else if(strcmp(argv[i], "torus") == 0) { 1.349 + prim = TORUS; 1.350 + } else { 1.351 + goto invalid; 1.352 + } 1.353 + break; 1.354 + 1.355 + case 'w': 1.356 + under_windows = 1; 1.357 + break; 1.358 + 1.359 + case 'h': 1.360 + printf("Usage %s [options]\n", argv[0]); 1.361 + printf("options:\n"); 1.362 + printf(" -p select one of (cube|sphere|torus)\n"); 1.363 + printf(" -v use vsync\n"); 1.364 + printf(" -w run under windows\n"); 1.365 + printf(" -h print usage information and exit\n"); 1.366 + exit(0); 1.367 + 1.368 + default: 1.369 + goto invalid; 1.370 + } 1.371 + } else { 1.372 + goto invalid; 1.373 + } 1.374 + } 1.375 + 1.376 + return 0; 1.377 + 1.378 +invalid: 1.379 + fprintf(stderr, "invalid argument: %s\n", argv[i]); 1.380 + return -1; 1.381 +} 1.382 + 1.383 + 1.384 +static void print_perf(void) 1.385 +{ 1.386 + unsigned long msec, avg_frame_time; 1.387 + float sec, fps; 1.388 + 1.389 + msec = get_msec(); 1.390 + if(!num_frm || msec < 1000) { 1.391 + printf("leaving so soon? (%lu ms)\n", msec); 1.392 + return; 1.393 + } 1.394 + 1.395 + sec = msec / 1000.0f; 1.396 + fps = (float)num_frm / sec; 1.397 + avg_frame_time = msec / num_frm; 1.398 + 1.399 + printf("%lu frames in %.2f seconds\n", num_frm, sec); 1.400 + printf(" avg. frame time: %lu ms\n", avg_frame_time); 1.401 + printf(" avg. framerate: %.2f fps\n", fps); 1.402 +}