fee1e7a37864548278dcfa518acff5c73aed02c7
[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 "music.h"
12 #include "cfgopt.h"
13 #include "tinyfps.h"
14 #include "util.h"
15
16 #define FB_WIDTH        320
17 #define FB_HEIGHT       240
18
19 int fb_width = FB_WIDTH;
20 int fb_height = FB_HEIGHT;
21 int fb_bpp = 16;
22 uint16_t *fb_pixels, *vmem;
23 unsigned long time_msec;
24 int mouse_x, mouse_y;
25 unsigned int mouse_bmask;
26
27 float sball_matrix[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
28
29 static unsigned long nframes;
30 static int console_active;
31
32 int demo_init(int argc, char **argv)
33 {
34         struct screen *scr;
35         char *env;
36
37         if(load_config("demo.cfg") == -1) {
38                 return -1;
39         }
40         if((env = getenv("START_SCR"))) {
41                 opt.start_scr = env;
42         }
43         if(parse_args(argc, argv) == -1) {
44                 return -1;
45         }
46
47         initFpsFonts();
48
49         if(g3d_init() == -1) {
50                 return -1;
51         }
52         g3d_framebuffer(fb_width, fb_height, fb_pixels);
53
54         if(opt.music) {
55                 if(music_open("data/test.mod") == -1) {
56                         return -1;
57                 }
58         }
59
60         if(scr_init() == -1) {
61                 return -1;
62         }
63         if(opt.start_scr) {
64                 scr = scr_lookup(opt.start_scr);
65         } else {
66                 scr = scr_screen(0);
67         }
68
69         if(!scr || scr_change(scr, 4000) == -1) {
70                 fprintf(stderr, "screen %s not found\n", opt.start_scr ? opt.start_scr : "0");
71                 return -1;
72         }
73
74         /* clear the framebuffer at least once */
75         memset(fb_pixels, 0, fb_width * fb_height * fb_bpp / CHAR_BIT);
76
77         if(opt.music) {
78                 music_play();
79         }
80         return 0;
81 }
82
83 void demo_cleanup(void)
84 {
85         if(opt.music) {
86                 music_close();
87         }
88         scr_shutdown();
89         g3d_destroy();
90
91         if(time_msec) {
92                 float fps = (float)nframes / ((float)time_msec / 1000.0f);
93                 printf("average framerate: %.1f\n", fps);
94         }
95 }
96
97 void demo_draw(void)
98 {
99         if(opt.music) {
100                 music_update();
101         }
102         scr_update();
103         scr_draw();
104
105         draw_mouse_pointer(vmem);
106
107         ++nframes;
108 }
109
110
111
112 #define DEST(x, y)      dest[(y) * FB_WIDTH + (x)]
113 void draw_mouse_pointer(uint16_t *fb)
114 {
115         uint16_t *dest = fb + mouse_y * FB_WIDTH + mouse_x;
116         int ylines = FB_HEIGHT - mouse_y;
117
118         switch(ylines) {
119         default:
120         case 10:
121                 DEST(0, 9) = 0xffff;
122         case 9:
123                 DEST(0, 8) = 0xffff;
124                 DEST(1, 8) = 0xffff;
125         case 8:
126                 DEST(0, 7) = 0xffff;
127                 DEST(2, 7) = 0xffff;
128                 DEST(1, 7) = 0;
129         case 7:
130                 DEST(6, 6) = 0xffff;
131                 DEST(0, 6) = 0xffff;
132                 DEST(3, 6) = 0xffff;
133                 DEST(4, 6) = 0xffff;
134                 DEST(5, 6) = 0xffff;
135                 DEST(1, 6) = 0;
136                 DEST(2, 6) = 0;
137         case 6:
138                 DEST(5, 5) = 0xffff;
139                 DEST(0, 5) = 0xffff;
140                 DEST(1, 5) = 0;
141                 DEST(2, 5) = 0;
142                 DEST(3, 5) = 0;
143                 DEST(4, 5) = 0;
144         case 5:
145                 DEST(4, 4) = 0xffff;
146                 DEST(0, 4) = 0xffff;
147                 DEST(1, 4) = 0;
148                 DEST(2, 4) = 0;
149                 DEST(3, 4) = 0;
150         case 4:
151                 DEST(3, 3) = 0xffff;
152                 DEST(0, 3) = 0xffff;
153                 DEST(1, 3) = 0;
154                 DEST(2, 3) = 0;
155         case 3:
156                 DEST(2, 2) = 0xffff;
157                 DEST(0, 2) = 0xffff;
158                 DEST(1, 2) = 0;
159         case 2:
160                 DEST(1, 1) = 0xffff;
161                 DEST(0, 1) = 0xffff;
162         case 1:
163                 DEST(0, 0) = 0xffff;
164         }
165 }
166
167 void cs_puts(void *fb, int x, int y, const char *str)
168 {
169         while(*str) {
170                 int c = *str++;
171
172                 if(isalpha(c)) {
173                         cs_font(fb, x, y, toupper(c) - 'A');
174                 }
175                 x += 14;
176         }
177 }
178
179 static void change_screen(int idx)
180 {
181         printf("change screen %d\n", idx);
182         scr_change(scr_screen(idx), 4000);
183 }
184
185 #define CBUF_SIZE       64
186 #define CBUF_MASK       (CBUF_SIZE - 1)
187 void demo_keyboard(int key, int press)
188 {
189         static char cbuf[CBUF_SIZE];
190         static int rd, wr;
191         char inp[CBUF_SIZE + 1], *dptr;
192         int i, nscr;
193
194         if(press) {
195                 switch(key) {
196                 case 27:
197                         demo_quit();
198                         return;
199
200                 case 127:
201                         debug_break();
202                         return;
203
204                 case '`':
205                         console_active = !console_active;
206                         if(console_active) {
207                                 printf("> ");
208                                 fflush(stdout);
209                         } else {
210                                 putchar('\n');
211                         }
212                         return;
213
214                 case '\b':
215                         if(console_active) {
216                                 if(wr != rd) {
217                                         printf("\b \b");
218                                         fflush(stdout);
219                                         wr = (wr + CBUF_SIZE - 1) & CBUF_MASK;
220                                 }
221                                 return;
222                         }
223                         break;
224
225                 case '\n':
226                 case '\r':
227                         if(console_active) {
228                                 dptr = inp;
229                                 while(rd != wr) {
230                                         *dptr++ = cbuf[rd];
231                                         rd = (rd + 1) & CBUF_MASK;
232                                 }
233                                 *dptr = 0;
234                                 if(inp[0]) {
235                                         printf("\ntrying to match: %s\n", inp);
236                                         nscr = scr_num_screens();
237                                         for(i=0; i<nscr; i++) {
238                                                 if(strstr(scr_screen(i)->name, inp)) {
239                                                         change_screen(i);
240                                                         break;
241                                                 }
242                                         }
243                                 }
244                                 console_active = 0;
245                                 return;
246                         }
247                         break;
248
249                 default:
250                         if(key >= '1' && key <= '9' && key <= '1' + scr_num_screens()) {
251                                 change_screen(key - '1');
252                         } else if(key == '0' && scr_num_screens() >= 10) {
253                                 change_screen(9);
254                         }
255
256                         if(console_active) {
257                                 if(key < 256 && isprint(key)) {
258                                         putchar(key);
259                                         fflush(stdout);
260
261                                         cbuf[wr] = key;
262                                         wr = (wr + 1) & CBUF_MASK;
263                                         if(wr == rd) { /* overflow */
264                                                 rd = (rd + 1) & CBUF_MASK;
265                                         }
266                                 }
267                                 return;
268                         }
269                         break;
270                 }
271
272                 scr_keypress(key);
273         }
274 }
275
276
277 void mouse_orbit_update(float *theta, float *phi, float *dist)
278 {
279         static int prev_mx, prev_my;
280         static unsigned int prev_bmask;
281
282         if(mouse_bmask) {
283                 if((mouse_bmask ^ prev_bmask) == 0) {
284                         int dx = mouse_x - prev_mx;
285                         int dy = mouse_y - prev_my;
286
287                         if(dx || dy) {
288                                 if(mouse_bmask & MOUSE_BN_LEFT) {
289                                         float p = *phi;
290                                         *theta += dx * 1.0;
291                                         p += dy * 1.0;
292
293                                         if(p < -90) p = -90;
294                                         if(p > 90) p = 90;
295                                         *phi = p;
296                                 }
297                                 if(mouse_bmask & MOUSE_BN_RIGHT) {
298                                         *dist += dy * 0.5;
299
300                                         if(*dist < 0) *dist = 0;
301                                 }
302                         }
303                 }
304         }
305
306         prev_mx = mouse_x;
307         prev_my = mouse_y;
308         prev_bmask = mouse_bmask;
309 }