dbus function is done
[shermanaquarium] / sherman-aquarium / shermans / plasma.c
1
2
3 /* Plasma "plugin" for Sherman's aquarium by Jonas Aaberg <cja@gmx.net> 2002 */
4
5 /*
6
7   This plasma is based upon Jeremy Longley's JCL plasma for MS-DOS
8   that was written probably around 1995.
9
10 */
11
12 #include "aquarium.h"
13 #include "over.h"
14 #include "plasma.h"
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <math.h>
18
19 #define MAX_FRAMES 1000
20 #define GEN_PALETTE 11
21 #define GEN_MOVEMENT 10
22 #define START_UP_PLASMA 13
23
24 static unsigned char *surface = NULL, *movement = NULL, *palette = NULL, *pscreen = NULL;
25
26 static int frame;
27
28 static int p1, p2, p3, p4, p5, p6;
29 static int m1, m2, m3, m4;
30 static int c1, c2, c3, c11, c21, c31;
31
32 static int surface_x = 512;
33 static int surface_y = 300;
34
35
36
37 void plasma_exit(void)
38 {
39
40 }
41
42 void plasma_init(void)
43 {
44     surface = movement = palette = pscreen = NULL;
45 }
46
47 void plasma_end(void)
48
49     if(surface != NULL)
50         g_free(surface);
51     if(movement != NULL)
52         g_free(movement);
53     if(palette != NULL)
54         g_free(palette);
55     if(pscreen != NULL)
56         g_free(pscreen);
57     surface = movement = palette = pscreen = NULL;
58
59 }
60
61
62 void plasma_gen_surface(int start_num)
63 {
64     int ypos;
65     unsigned char value;
66     float x, y;
67
68     for(y = start_num * (surface_y / 10); y < ((start_num + 1) * surface_y / 10); y++){
69         ypos = (int) y * surface_x;
70         for(x = 0; x < surface_x; x++){
71             value = 64 + (unsigned char)(10 * (sin(x / p1) + cos(y / p2) +
72                          cos(x / p3) + sin(y / p4) +
73                          sin((x + y) / p5) +
74                          cos(hypot(256 - x, 150 - y) / p6)));
75             surface[ypos+(int)x] = value;
76         }
77     }
78
79 }
80
81
82
83 void plasma_start(void)
84 {
85     AquariumData *ad;
86
87     ad = aquarium_get_settings_ptr();
88
89     frame=0;
90
91     /* Surface randomization */
92     p1 = g_rand_int_range(ad->rnd, 1, 101);
93     p2 = p1 + g_rand_int_range(ad->rnd, -25, 25);
94     p3 = g_rand_int_range(ad->rnd, 1, 101);
95     p4 = p3 + g_rand_int_range(ad->rnd, -25, 25);
96     p5 = g_rand_int_range(ad->rnd, 1, 101);
97     p6 = p5 + g_rand_int_range(ad->rnd, -25, 25);
98
99     /* Movement randomization */
100     m1 = g_rand_int_range(ad->rnd, 1, 101);
101     m2 = g_rand_int_range(ad->rnd, 1, 101);
102     m3 = g_rand_int_range(ad->rnd, 1, 101);
103     m4 = g_rand_int_range(ad->rnd, 1, 101);
104
105     /* Colour randomization */
106
107     c1 = g_rand_int_range(ad->rnd, 1, 101);
108     c11 = g_rand_int_range(ad->rnd, 1, 101);
109     c2 = g_rand_int_range(ad->rnd, 1, 101);
110     c21 = g_rand_int_range(ad->rnd, 1, 101);
111     c3 = g_rand_int_range(ad->rnd, 1, 101);
112     c31= g_rand_int_range(ad->rnd, 1, 101);
113
114
115     if(surface!=NULL)
116         plasma_end();
117
118     ad = aquarium_get_settings_ptr();
119
120     /* Allocating memory */
121
122     surface_x = ((int)(ad->xmax / 512.0 + 1)) * 512;
123     surface_y = 2 * ad->ymax;
124
125     surface = g_malloc0(surface_x * surface_y);
126     movement = g_malloc0(4 * MAX_FRAMES);
127     palette = g_malloc0(3 * 2 * MAX_FRAMES);
128
129
130     pscreen = g_malloc0(ad->xmax*ad->ymax * 4);
131
132 }
133
134 void plasma_start_2(int start_num)
135 {
136     float count;
137     int lead, offset;
138
139     if(start_num < GEN_MOVEMENT)
140         plasma_gen_surface(start_num);
141     if(start_num == GEN_MOVEMENT){
142
143         for(count = 0; count < MAX_FRAMES; count++){
144             lead = (int)((surface_y / 3 - 4) + (surface_y / 3 - 10) * cos(count / m1)
145                          + surface_x * (int)((surface_y / 6 - 2) + (surface_y / 6 - 3) * sin(count / m2)));
146             offset = (int)((surface_y / 3 - 4) + (surface_y / 3 - 8) * sin(count / m3)
147                           + surface_x * (int)((surface_y / 6 - 2) + (surface_y / 6 - 3) * cos(count / m4))
148                          - lead);
149             movement[(int)count * 4 + 0] = (unsigned char)((lead & 0xff00) >> 8);
150             movement[(int)count * 4 + 1] = (unsigned char)(lead & 0xff);
151             movement[(int)count * 4 + 2] = (unsigned char)((offset & 0xff00) >> 8);
152             movement[(int)count * 4 + 3] = (unsigned char)(offset & 0xff);
153         }
154     }
155
156     if(start_num == GEN_PALETTE){
157         for(count = 0; count < (((MAX_FRAMES + 768) / 256 + 1) * 256); count++){
158             palette[(int)count * 3 + 0] = (unsigned char)(sin(count / c11) * sin(count / c1) * 126 + 126);
159             palette[(int)count * 3 + 1] = (unsigned char)(sin(count / c21) * sin(count / c2) * 126 + 126);
160             palette[(int)count * 3 + 2] = (unsigned char)(sin(count / c31) * sin(count / c3) * 126 + 126);
161         }
162     }
163     
164 }
165
166
167 void plasma_update(void)
168 {
169     unsigned int lead, offset;
170     unsigned char t;
171     unsigned int sum;
172     int p, ypos;
173     int surface_ptr = 0;
174     AquariumData *ad;
175
176     int x, y;
177
178     if(frame == MAX_FRAMES){
179         plasma_start();
180     }
181
182     frame++;
183         
184     if(frame < START_UP_PLASMA){
185         plasma_start_2(frame - 1);
186         return;
187     }
188
189     t = movement[frame * 4 + 1];
190     lead = (unsigned int)t;
191     t = movement[frame * 4 + 0];
192     lead += ((unsigned int)t) << 8;
193
194     t = movement[frame * 4 + 3];
195     offset = (unsigned int)t;
196     t = movement[frame * 4 + 2];
197     offset += ((unsigned int)t) << 8;
198
199     sum = (offset + lead) & 0xffff;
200
201     ad = aquarium_get_settings_ptr();
202
203     for(y = 0; y < ad->ymax; y++){
204         ypos = y * ad->xmax * 4;
205         for(x = 0; x < ad->xmax; x++){
206             t = (unsigned char)((surface[lead + surface_ptr + x] + surface[sum + surface_ptr + x]) & 0xff);
207             p = 3 * (int)t;
208             pscreen[ypos + x * 4 + 0] = palette[3 * frame + p + 0];
209             pscreen[ypos + x * 4 + 1] = palette[3 * frame + p + 1];
210             pscreen[ypos + x * 4 + 2] = palette[3 * frame + p + 2];
211             //      pscreen[ypos + x * 4 + 3] = 'E';
212         }
213         surface_ptr += surface_x;
214     }
215
216     over_draw(0, 0, 0, ad->xmax, ad->ymax,pscreen);
217     
218
219 }