Oh no
[dosdemo] / src / thunder.c
1 /* thunder. c */
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <math.h>
6 #include <assert.h>
7 #include "imago2.h"
8 #include "demo.h"
9 #include "screen.h"
10
11 /* Render blur in half x half dimenstions. Add one pixel padding in all 
12  * directions (2 pixels horizontally, 2 pixels vertically).
13  */
14 #define BLUR_BUFFER_WIDTH (320/2 + 2)
15 #define BLUR_BUFFER_HEIGHT (240/2 + 2)
16 #define BLUR_BUFFER_SIZE (BLUR_BUFFER_WIDTH * BLUR_BUFFER_HEIGHT)
17 static unsigned char *blurBuffer, *blurBuffer2;
18
19 #define THUNDER_RECT_SIZE 4
20 #define THUNDER_RANDOMNESS 80
21 #define THUNDER_SECONDS 0.1f
22
23 /* TODO: Load palette from file */
24 static unsigned short palette[256];
25
26 void clearBlurBuffer();
27 void drawPatternOnBlurBuffer(int seed);
28 void applyBlur();
29 void blitEffect();
30 void thunder(int x0, int y0, int x1, int y1, int seed, int randomness, int depth);
31
32 static int init(void);
33 static void destroy(void);
34 static void start(long trans_time);
35 static void stop(long trans_time);
36 static void draw(void);
37
38 static unsigned int lastFrameTime = 0;
39 static float lastFrameDuration = 0.0f;
40 static struct screen scr = {
41         "thunder",
42         init,
43         destroy,
44         start,
45         0,
46         draw
47 };
48
49 struct screen *thunder_screen(void)
50 {
51         return &scr;
52 }
53
54 static int init(void)
55 {
56         int i = 0;
57
58         blurBuffer = malloc(BLUR_BUFFER_SIZE);
59         blurBuffer2 = malloc(BLUR_BUFFER_SIZE);
60
61         clearBlurBuffer();
62
63         /* For now, map to blue */
64         for (i = 0; i < 256; i++) {
65                 palette[i] = i >> 3;
66         }
67
68         return 0;
69 }
70
71 static void destroy(void)
72 {
73         free(blurBuffer);
74         blurBuffer = 0;
75         
76         free(blurBuffer2);
77         blurBuffer2 = 0;
78 }
79
80 static void start(long trans_time)
81 {
82         lastFrameTime = time_msec;
83 }
84
85
86 static float remainingThunderDuration = THUNDER_SECONDS;
87 static int thunderPattern = 0;
88
89 static void draw(void)
90 {
91         lastFrameDuration = (time_msec - lastFrameTime) / 1000.0f;
92         lastFrameTime = time_msec;
93
94         remainingThunderDuration -= lastFrameDuration;
95         if (remainingThunderDuration <= 0) {
96                 thunderPattern++;
97                 remainingThunderDuration = THUNDER_SECONDS;
98         }
99         
100         
101         
102         drawPatternOnBlurBuffer(thunderPattern);
103         applyBlur();
104         blitEffect();
105
106         swap_buffers(0);
107 }
108
109 void clearBlurBuffer() {
110         /* Clear the whole buffer (including its padding ) */
111         memset(blurBuffer, 0, BLUR_BUFFER_SIZE);
112         memset(blurBuffer2, 0, BLUR_BUFFER_SIZE);
113 }
114
115 void drawPatternOnBlurBuffer(int seed) {
116         thunder(20, 20, 140, 100, seed, THUNDER_RANDOMNESS, 6);
117 }
118
119 void applyBlur() {
120         int i, j;
121         unsigned char *tmp;
122         unsigned char *src = blurBuffer + BLUR_BUFFER_WIDTH + 1;
123         unsigned char *dst = blurBuffer2 + BLUR_BUFFER_WIDTH + 1;
124
125         for (j = 0; j < 120; j++) {
126                 for (i = 0; i < 160; i++) {
127                         *dst = (*(src - 1) + *(src + 1) + *(src - BLUR_BUFFER_WIDTH) + *(src + BLUR_BUFFER_WIDTH)) >> 2;
128                         if (*dst > 4) *dst -= 4;
129                         else *dst = 0;
130                         dst++;
131                         src++;
132                 }
133                 /* Just skip the padding since we went through the scanline in the inner loop (except from the padding) */
134                 src += 2;
135                 dst += 2;
136         }
137
138         /* Swap blur buffers */
139         tmp = blurBuffer;
140         blurBuffer = blurBuffer2;
141         blurBuffer2 = tmp;
142 }
143
144 void blitEffect() {
145         unsigned int *dst1 = (unsigned int*) vmem_back;
146         unsigned int *dst2 = dst1 + 160; /* We're writing two pixels at once */
147         unsigned char *src1 = blurBuffer + BLUR_BUFFER_WIDTH + 1;
148         unsigned char *src2 = src1 + BLUR_BUFFER_WIDTH;
149         unsigned char tl, tr, bl, br;
150         int i, j;
151
152         for (j = 0; j < 120; j++) {
153                 for (i = 0; i < 160; i++) {
154                         tl = *src1;
155                         tr = (*src1 + *(src1 + 1)) >> 1;
156                         bl = (*src1 + *src2) >> 1;
157                         br = tr + ((*src2 + *(src2 + 1)) >> 1) >> 1;
158
159                         /* Pack 2 pixels in each 32 bit word */
160                         *dst1 = (palette[tr] << 16) | palette[tl];
161                         *dst2 = (palette[br] << 16) | palette[bl];
162
163                         dst1++;
164                         src1++;
165                         dst2++;
166                         src2++;
167                 }
168                 /* Again, skip padding */
169                 src1 += 2;
170                 src2 += 2;
171
172                 /* For now, skip a scanline */
173                 dst1 += 160;
174                 dst2 += 160;
175         }
176
177 }
178
179 void thunder(int x0, int y0, int x1, int y1, int seed, int randomness, int depth) {
180         int mx = ((x0 + x1) >> 1) + rand() % randomness - randomness / 2;
181         int my = ((y0 + y1) >> 1) + rand() % randomness - randomness / 2;
182         int i, j;
183         unsigned char *dst = blurBuffer + BLUR_BUFFER_WIDTH + 1 + mx + my * BLUR_BUFFER_WIDTH;
184
185         if (depth <= 0) return;
186
187         srand(seed);
188
189         for (j = 0; j < THUNDER_RECT_SIZE; j++) {
190                 memset(dst, 255, THUNDER_RECT_SIZE);
191                 dst += BLUR_BUFFER_WIDTH;
192         }
193
194         thunder(x0, y0, mx, my, rand(), randomness >> 1, depth-1);
195         thunder(mx, my, x1, y1, rand(), randomness >> 1, depth - 1);
196 }
197
198
199