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