rnd-20100327-1-src
[rocksndiamonds.git] / src / game_sp / Explosions.c
1 // ----------------------------------------------------------------------------
2 // Explosions.c
3 // ----------------------------------------------------------------------------
4
5 #include "Explosions.h"
6
7
8 static void LetExplodeFieldSP(int tsi, int cx, int dh);
9 static void subExplodeInfotron(int tsi, int cx);
10 static void subExplodeZonk(int tsi, int cx);
11
12
13 // ==========================================================================
14 //                              SUBROUTINE
15 // Animate explosion
16 // ==========================================================================
17
18 void subAnimateExplosion(int si)
19 {
20   int ax, bl, X, Y;
21
22   if (LowByte(PlayField16[si]) != fiExplosion)
23     return;
24
25   ax = (TimerVar & 3);
26   if (ax != 0)
27     return;
28
29   bl = HighByte(PlayField16[si]);
30
31   if ((bl & 0x80) != 0) // infotron explosion!
32     goto loc_g_28D0;
33
34   bl = bl + 1;
35   MovHighByte(&PlayField16[si], bl);
36
37   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38   X = GetStretchX(si);
39   Y = GetStretchY(si);
40   GfxGraphic[GetX(si)][GetY(si)] = aniDefaultExplosion;
41   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
42
43   if (bl == 8)
44   {
45     PlayField16[si] = 0;
46     ExplosionShake = 0; // nothing explodes
47
48     // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
49     GfxGraphic[GetX(si)][GetY(si)] = aniSpace;
50     // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
51   } // loc_ret_g_28CF:
52
53   return;
54
55 loc_g_28D0: // explosion produces infotron
56   bl = bl + 1;
57   if (bl == 0x89)
58   {
59     PlayField16[si] = fiInfotron;
60     MovLowByte(&ExplosionShake, 0); // nothing explodes
61
62     // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
63     GfxGraphic[GetX(si)][GetY(si)] = aniInfotron;
64     // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
65
66     return;
67   } // loc_g_28E3:
68
69   MovHighByte(&PlayField16[si], bl);
70
71   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
72   X = GetStretchX(si);
73   Y = GetStretchY(si);
74   GfxGraphic[GetX(si)][GetY(si)] = aniElectronExplosion;
75   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
76 }
77
78 // ==========================================================================
79 //                              SUBROUTINE
80 // Explode
81 // ==========================================================================
82
83 void ExplodeFieldSP(int si)
84 {
85   int ax, cx, dl;
86
87   ax = LowByte(PlayField16[si]);
88   if (ax == fiHardWare)
89     return;
90
91   ExplosionShake = 1; // something explodes
92   if (ax == fiMurphy)
93   {
94 #if 1
95     printf("::: Explosions.c: ExplodeFieldSP(): killing murphy\n");
96 #endif
97
98     KillMurphyFlag = 1;
99   }
100
101   if (ax == fiElectron)
102   {
103     cx = 0x801F; // produce infotrons
104     dl = 0xF3;
105   }
106   else // loc_g_2977:
107   {
108     cx = 0x1F; // normal explosion
109     dl = 0xD;
110   } // loc_g_297C:
111
112   LetExplodeFieldSP(si - FieldWidth - 1, cx, dl);
113   LetExplodeFieldSP(si - FieldWidth, cx, dl);
114   LetExplodeFieldSP(si - FieldWidth + 1, cx, dl);
115   LetExplodeFieldSP(si - 1, cx, dl);
116   PlayField16[si] = cx;
117   LetExplodeFieldSP(si + 1, cx, dl);
118   LetExplodeFieldSP(si + FieldWidth - 1, cx, dl);
119   LetExplodeFieldSP(si + FieldWidth, cx, dl);
120   LetExplodeFieldSP(si + FieldWidth + 1, cx, dl);
121
122   GfxGraphic[GetX(si)][GetY(si)] = -1;          // restart for chain-explosions
123
124   // loc_g_2C3B:
125   subSoundFX(si, ax, actExploding);
126 }
127
128 static void LetExplodeFieldSP(int tsi, int cx, int dh)
129 {
130   int al;
131
132   if (tsi < (-FieldWidth))
133     return;
134
135   al = LowByte(PlayField16[tsi]);
136   switch (al)
137   {
138     case fiHardWare:
139       return;
140
141       break;
142
143     case fiOrangeDisk:
144     case fiYellowDisk:
145     case fiSnikSnak:
146       PlayField8[tsi] = dh;
147       PlayField16[tsi] = cx;
148       break;
149
150     case fiZonk:
151       subExplodeZonk(tsi, cx);
152       break;
153
154     case fiInfotron:
155       subExplodeInfotron(tsi, cx);
156       break;
157
158     case fiElectron:
159       PlayField8[tsi] = (-dh) & 0xFF;
160       PlayField16[tsi] = 0x801F;
161       break;
162
163     case fiMurphy:
164 #if 1
165       printf("::: Explosions.c: LetExplodeFieldSP(): killing murphy [%d]\n",
166              tsi);
167 #endif
168
169       KillMurphyFlag = 1;
170       PlayField8[tsi] = dh;
171       PlayField16[tsi] = cx;
172       break;
173
174     default:
175       PlayField16[tsi] = cx;
176       break;
177   }
178
179   GfxGraphic[GetX(tsi)][GetY(tsi)] = -1;        // restart for chain-explosions
180 }
181
182 static void subExplodeZonk(int tsi, int cx)
183 {
184   int ah;
185
186   ah = HighByte(PlayField16[tsi]) & 0xF0;
187   PlayField16[tsi] = cx;
188   switch (ah)
189   {
190     case 0x10:
191     case 0x70:
192       subClearFieldDueToExplosion(tsi - FieldWidth);
193       tsi = tsi + FieldWidth;
194       if (PlayField16[tsi] == 0x9999)
195         subClearFieldDueToExplosion(tsi);
196
197       break;
198
199     case 0x20:
200       subClearFieldDueToExplosion(tsi + 1);
201       subClearFieldDueToExplosion(tsi + FieldWidth);
202       break;
203
204     case 0x30:
205       subClearFieldDueToExplosion(tsi - 1);
206       subClearFieldDueToExplosion(tsi + FieldWidth);
207       break;
208
209     case 0x50:
210       subClearFieldDueToExplosion(tsi - 1);
211       break;
212
213     case 0x60:
214       subClearFieldDueToExplosion(tsi + 1);
215       break;
216
217     case 0xFF000070: // !!! 0x70; this will never be reached! ...??
218       subClearFieldDueToExplosion(tsi + FieldWidth);
219       break;
220   }
221 }
222
223 static void subExplodeInfotron(int tsi, int cx)
224 {
225   int ah;
226
227   ah = HighByte(PlayField16[tsi]) & 0xF0;
228   PlayField16[tsi] = cx;
229   switch (ah)
230   {
231     case 0x10:
232     case 0x70:
233       subClearFieldDueToExplosion(tsi - FieldWidth);
234       tsi = tsi + FieldWidth;
235       if (PlayField16[tsi] == 0x9999)
236         subClearFieldDueToExplosion(tsi);
237
238       break;
239
240     case 0x20:
241       subClearFieldDueToExplosion(tsi + 1);
242       tsi = tsi + FieldWidth; // differnt from zonk version
243       if (PlayField16[tsi] == 0x9999)
244         subClearFieldDueToExplosion(tsi);
245
246       break;
247
248     case 0x30:
249       subClearFieldDueToExplosion(tsi - 1);
250       tsi = tsi + FieldWidth; // differnt from zonk version
251       if (PlayField16[tsi] == 0x9999)
252         subClearFieldDueToExplosion(tsi);
253
254       break;
255
256     case 0x50:
257       subClearFieldDueToExplosion(tsi - 1);
258       break;
259
260     case 0x60:
261       subClearFieldDueToExplosion(tsi + 1);
262       break;
263
264     case 0xFF000070: // !!! 0x70; this will never be reached! ...??
265       subClearFieldDueToExplosion(tsi + FieldWidth);
266       break;
267   }
268 }
269
270 void subClearFieldDueToExplosion(int si)
271 {
272   int X, Y;
273
274   if (LowByte(PlayField16[si]) == fiExplosion)
275     return;
276
277   PlayField16[si] = 0;
278   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
279   X = GetStretchX(si);
280   Y = GetStretchY(si);
281   GfxGraphic[GetX(si)][GetY(si)] = aniSpace;
282   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
283 }
284
285 void subRedDiskReleaseExplosion()
286 {
287   int al, X, Y, si;
288
289   al = RedDiskReleasePhase;            // Red disk release phase
290   if (al <= 1)
291     return;
292
293   si = RedDiskReleaseMurphyPos;
294   if (PlayField16[si] == 0) // Release red disk
295     PlayField16[si] = fiRedDisk;
296
297   // +++++++++++++++++++++++++++++++++++++++++
298   X = GetStretchX(si);
299   Y = GetStretchY(si);
300 #if 0
301   // !!! causes flicker -- fix in Murphy.c !!!
302   GfxGraphic[GetX(si)][GetY(si)] = aniRedDisk;
303 #else
304   DDSpriteBuffer_BltImg(X, Y, aniRedDisk, 0);
305 #endif
306   // +++++++++++++++++++++++++++++++++++++++++
307
308   RedDiskReleasePhase = RedDiskReleasePhase + 1;
309   if (RedDiskReleasePhase >= 0x28)
310   {
311     // si = RedDiskReleaseMurphyPos           ' Red disk was released here
312     ExplodeFieldSP(si);                 // Explode
313     RedDiskReleasePhase = 0;
314   }
315 }
316
317 void subFollowUpExplosions()
318 {
319   int ax, si;
320
321   // locloop_g_2919:
322   for (si = 0; si <= LevelMax; si++)
323   {
324     ax = ByteToInt(PlayField8[si]);
325     if (ax != 0)
326     {
327       if (ax < 0)
328       {
329         ax = ax + 1;
330         PlayField8[si] = ax & 0xFF;
331         if (ax == 0)
332         {
333           PlayField16[si] = 0xFF18;
334           ExplodeFieldSP(si);                 // Explode
335         }
336       }
337       else
338       {
339         ax = ax - 1;
340         PlayField8[si] = ax;
341         if (ax == 0)
342           ExplodeFieldSP(si);
343       }
344     }
345   }
346 }