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