49a5b507a6a9eed1cb9834f59d5f1e5c2089762a
[dosdemo] / src / scr / greets.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5 #include <assert.h>
6 #include "demo.h"
7 #include "3dgfx.h"
8 #include "screen.h"
9 #include "cfgopt.h"
10 #include "imago2.h"
11 #include "util.h"
12 #include "gfxutil.h"
13 #include "timer.h"
14 #include "smoketxt.h"
15
16 #ifdef MSDOS
17 #include "dos/gfx.h"    /* for wait_vsync assembly macro */
18 #else
19 void wait_vsync(void);
20 #endif
21
22 #define BLUR_RAD        5
23
24
25 static int init(void);
26 static void destroy(void);
27 static void start(long trans_time);
28 static void draw(void);
29
30
31 static struct screen scr = {
32         "greets",
33         init,
34         destroy,
35         start, 0,
36         draw
37 };
38
39 static long start_time;
40
41 static struct smktxt *stx;
42
43 static uint16_t *cur_smokebuf, *prev_smokebuf;
44 static int smokebuf_size;
45 #define smokebuf_start  (cur_smokebuf < prev_smokebuf ? cur_smokebuf : prev_smokebuf)
46 #define swap_smoke_buffers() \
47         do { \
48                 uint16_t *tmp = cur_smokebuf; \
49                 cur_smokebuf = prev_smokebuf; \
50                 prev_smokebuf = tmp; \
51         } while(0)
52
53 static float cam_theta, cam_phi = 25;
54 static float cam_dist = 3;
55
56 struct screen *greets_screen(void)
57 {
58         return &scr;
59 }
60
61
62 static int init(void)
63 {
64         if(!(stx = create_smktxt("data/greets1.png", "data/vfield1"))) {
65                 return -1;
66         }
67
68         smokebuf_size = FB_WIDTH * FB_HEIGHT * sizeof *cur_smokebuf;
69         if(!(cur_smokebuf = malloc(smokebuf_size * 2))) {
70                 perror("failed to allocate smoke framebuffer");
71                 return -1;
72         }
73         prev_smokebuf = cur_smokebuf + FB_WIDTH * FB_HEIGHT;
74
75         return 0;
76 }
77
78 static void destroy(void)
79 {
80         free(smokebuf_start);
81         destroy_smktxt(stx);
82 }
83
84 static void start(long trans_time)
85 {
86         g3d_matrix_mode(G3D_PROJECTION);
87         g3d_load_identity();
88         g3d_perspective(50.0, 1.3333333, 0.5, 100.0);
89
90         memset(smokebuf_start, 0, smokebuf_size * 2);
91
92         start_time = time_msec;
93 }
94
95 static void update(void)
96 {
97         static long prev_msec;
98         static int prev_mx, prev_my;
99         static unsigned int prev_bmask;
100
101         long msec = time_msec - start_time;
102         float dt = (msec - prev_msec) / 1000.0f;
103         prev_msec = msec;
104
105         if(mouse_bmask) {
106                 if((mouse_bmask ^ prev_bmask) == 0) {
107                         int dx = mouse_x - prev_mx;
108                         int dy = mouse_y - prev_my;
109
110                         if(dx || dy) {
111                                 if(mouse_bmask & 1) {
112                                         cam_theta += dx * 1.0;
113                                         cam_phi += dy * 1.0;
114
115                                         if(cam_phi < -90) cam_phi = -90;
116                                         if(cam_phi > 90) cam_phi = 90;
117                                 }
118                                 if(mouse_bmask & 4) {
119                                         cam_dist += dy * 0.5;
120
121                                         if(cam_dist < 0) cam_dist = 0;
122                                 }
123                         }
124                 }
125         }
126         prev_mx = mouse_x;
127         prev_my = mouse_y;
128         prev_bmask = mouse_bmask;
129
130         update_smktxt(stx, dt);
131 }
132
133 static void draw(void)
134 {
135         int i, j;
136         uint16_t *dest, *src;
137         unsigned long msec;
138         static unsigned long last_swap;
139
140         update();
141
142         g3d_matrix_mode(G3D_MODELVIEW);
143         g3d_load_identity();
144         g3d_translate(0, 0, -cam_dist);
145         g3d_rotate(cam_phi, 1, 0, 0);
146         g3d_rotate(cam_theta, 0, 1, 0);
147         if(opt.sball) {
148                 g3d_mult_matrix(sball_matrix);
149         }
150
151         memcpy(cur_smokebuf, prev_smokebuf, smokebuf_size);
152
153         g3d_framebuffer(FB_WIDTH, FB_HEIGHT, cur_smokebuf);
154         draw_smktxt(stx);
155         g3d_framebuffer(FB_WIDTH, FB_HEIGHT, fb_pixels);
156
157         dest = fb_pixels;
158         src = cur_smokebuf;
159         for(i=0; i<FB_HEIGHT; i++) {
160                 for(j=0; j<FB_WIDTH; j++) {
161                         unsigned int alpha = *src++;
162                         *dest++ = PACK_RGB16(alpha, alpha, alpha);
163                 }
164         }
165
166         /*perf_start();*/
167         blur_grey_horiz(prev_smokebuf, cur_smokebuf, FB_WIDTH, FB_HEIGHT, BLUR_RAD, 240);
168         /*
169         perf_end();
170         printf("blur perf: %lu\n", (unsigned long)perf_interval_count);
171         */
172         blur_grey_vert(cur_smokebuf, prev_smokebuf, FB_WIDTH, FB_HEIGHT, BLUR_RAD, 240);
173         swap_smoke_buffers();
174
175         msec = get_msec();
176         if(msec - last_swap < 16) {
177                 wait_vsync();
178         }
179         if(!opt.vsync) {
180                 wait_vsync();
181         }
182         swap_buffers(fb_pixels);
183         last_swap = get_msec();
184 }