increased guard-band to 64 pixels top/bottom, and stopped demo_init2
[dosdemo] / src / demo.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5 #include <ctype.h>
6 #include <errno.h>
7 #include <limits.h>
8 #include "demo.h"
9 #include "screen.h"
10 #include "3dgfx.h"
11 #include "audio.h"
12 #include "cfgopt.h"
13 #include "console.h"
14 #include "tinyfps.h"
15 #include "util.h"
16
17 #define MOUSE_TIMEOUT   1200
18
19 #define GUARD_XPAD      0
20 #define GUARD_YPAD      64
21
22 int fb_width, fb_height, fb_bpp, fb_scan_size;
23 float fb_aspect;
24 long fb_size, fb_buf_size;
25 uint16_t *fb_pixels, *vmem;
26 uint16_t *fb_buf;
27
28 unsigned long time_msec;
29 int mouse_x, mouse_y;
30 unsigned int mouse_bmask;
31
32 static struct au_module *mod;
33
34 float sball_matrix[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
35
36 static unsigned long last_mouse_move;
37 static int prev_mx, prev_my, mouse_dx, mouse_dy;
38 static unsigned int bmask_diff, prev_bmask;
39
40 static unsigned long nframes;
41 static int con_active;
42
43 extern uint16_t loading_pixels[];       /* data.asm */
44
45 int demo_init(int argc, char **argv)
46 {
47         if(demo_init1(argc, argv) == -1) {
48                 return -1;
49         }
50         if(demo_init2() == -1) {
51                 return -1;
52         }
53         return 0;
54 }
55
56 static struct screen *scr;
57
58 int demo_init1(int argc, char **argv)
59 {
60         char *env;
61
62         if(load_config("demo.cfg") == -1) {
63                 return -1;
64         }
65         if((env = getenv("START_SCR"))) {
66                 opt.start_scr = env;
67         }
68         if(parse_args(argc, argv) == -1) {
69                 return -1;
70         }
71         return 0;
72 }
73
74 int demo_init2(void)
75 {
76         con_init();
77         initFpsFonts();
78
79         if(g3d_init() == -1) {
80                 return -1;
81         }
82         g3d_framebuffer(FB_WIDTH, FB_HEIGHT, fb_pixels);
83
84         if(opt.music) {
85                 if(!(mod = au_load_module("data/test.mod"))) {
86                         return -1;
87                 }
88         }
89
90         if(scr_init() == -1) {
91                 return -1;
92         }
93
94         if(opt.start_scr) {
95                 scr = scr_lookup(opt.start_scr);
96         } else {
97                 scr = scr_screen(0);
98         }
99
100         if(!scr || scr_change(scr, 4000) == -1) {
101                 fprintf(stderr, "screen %s not found\n", opt.start_scr ? opt.start_scr : "0");
102                 return -1;
103         }
104
105         /* clear the framebuffer at least once */
106         memset(fb_pixels, 0, FB_WIDTH * FB_HEIGHT * FB_BPP / CHAR_BIT);
107
108         if(opt.music) {
109                 au_play_module(mod);
110         }
111         return 0;
112 }
113
114 void demo_cleanup(void)
115 {
116         if(opt.music) {
117                 au_free_module(mod);
118         }
119         scr_shutdown();
120         g3d_destroy();
121
122         if(time_msec) {
123                 float fps = (float)nframes / ((float)time_msec / 1000.0f);
124                 printf("average framerate: %.1f\n", fps);
125         }
126 }
127
128 int demo_resizefb(int width, int height, int bpp)
129 {
130         int newsz, new_scansz;
131
132         if(!width || !height || !bpp) {
133                 free(fb_buf);
134                 fb_buf = fb_pixels = 0;
135                 fb_size = fb_buf_size = fb_scan_size = 0;
136                 fb_width = fb_height = fb_bpp = 0;
137                 return 0;
138         }
139
140         new_scansz = ((width + GUARD_XPAD * 2) * bpp + 7) / 8;
141         newsz = (height + GUARD_YPAD * 2) * new_scansz;
142
143         if(!fb_buf || newsz > fb_buf_size) {
144                 void *tmp = malloc(newsz);
145                 if(!tmp) return -1;
146
147                 free(fb_buf);
148                 fb_buf = tmp;
149                 fb_buf_size = newsz;
150         }
151
152         fb_scan_size = new_scansz;
153         fb_pixels = (uint16_t*)((char*)fb_buf + GUARD_YPAD * fb_scan_size + (GUARD_XPAD * bpp + 7) / 8);
154         fb_width = width;
155         fb_height = height;
156         fb_bpp = bpp;
157         fb_size = fb_scan_size * fb_height;
158
159         fb_aspect = (float)fb_width / (float)fb_height;
160
161         return 0;
162 }
163
164
165 void demo_draw(void)
166 {
167         if(opt.mouse) {
168                 mouse_dx = mouse_x - prev_mx;
169                 mouse_dy = mouse_y - prev_my;
170                 prev_mx = mouse_x;
171                 prev_my = mouse_y;
172                 bmask_diff = mouse_bmask ^ prev_bmask;
173                 prev_bmask = mouse_bmask;
174                 if(mouse_dx | mouse_dy) {
175                         last_mouse_move = time_msec;
176                 }
177         }
178
179         if(opt.music) {
180                 au_update();
181         }
182         scr_update();
183         scr_draw();
184
185         ++nframes;
186 }
187
188 /* called by swap_buffers just before the actual swap */
189 void demo_post_draw(void *pixels)
190 {
191         char buf[32];
192         if(opt.dbginfo) {
193                 drawFps(pixels);
194                 if(dbg_curscr_name) {
195                         cs_dputs(pixels, dbg_curscr_name_pos, 240 - 16, dbg_curscr_name);
196                 }
197         }
198
199         if(con_active) {
200                 con_draw(pixels);
201         }
202
203         if(opt.mouse && time_msec - last_mouse_move < MOUSE_TIMEOUT) {
204                 cs_mouseptr(pixels, mouse_x, mouse_y);
205         }
206 }
207
208 void cs_puts_font(cs_font_func csfont, int sz, void *fb, int x, int y, const char *str)
209 {
210         while(*str) {
211                 int c = *str++;
212
213                 if(c > ' ' && c < 128) {
214                         csfont(fb, x, y, c - ' ');
215                 }
216                 x += sz;
217         }
218 }
219
220 void change_screen(int idx)
221 {
222         printf("change screen %d\n", idx);
223         scr_change(scr_screen(idx), 4000);
224 }
225
226 void demo_keyboard(int key, int press)
227 {
228         int nscr;
229
230         if(press) {
231                 switch(key) {
232                 case 27:
233                         if(con_active) {
234                                 con_stop();
235                                 con_active = 0;
236                         } else {
237                                 demo_quit();
238                         }
239                         return;
240
241                 case 127:
242                         debug_break();
243                         return;
244
245                 case '`':
246                         con_active = !con_active;
247                         if(con_active) {
248                                 con_start();
249                         } else {
250                                 con_stop();
251                         }
252                         return;
253
254                 case '/':
255                         if(!con_active) {
256                                 con_start();
257                                 con_active = con_input('/');
258                                 return;
259                         }
260
261                 default:
262                         if(con_active) {
263                                 con_active = con_input(key);
264                                 return;
265                         }
266
267                         if(key >= '1' && key <= '9' && key <= '1' + scr_num_screens()) {
268                                 change_screen(key - '1');
269                                 return;
270                         } else if(key == '0' && scr_num_screens() >= 10) {
271                                 change_screen(9);
272                                 return;
273                         }
274                 }
275
276                 scr_keypress(key);
277         }
278 }
279
280
281 void mouse_orbit_update(float *theta, float *phi, float *dist)
282 {
283         if(mouse_bmask) {
284                 if(bmask_diff == 0) {
285
286                         if(mouse_dx | mouse_dy) {
287                                 if(mouse_bmask & MOUSE_BN_LEFT) {
288                                         float p = *phi;
289                                         *theta += mouse_dx * 1.0;
290                                         p += mouse_dy * 1.0;
291
292                                         if(p < -90) p = -90;
293                                         if(p > 90) p = 90;
294                                         *phi = p;
295                                 }
296                                 if(mouse_bmask & MOUSE_BN_RIGHT) {
297                                         *dist += mouse_dy * 0.5;
298
299                                         if(*dist < 0) *dist = 0;
300                                 }
301                         }
302                 }
303         }
304 }