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