fixed bug in single button handling causing broken tapes (EM engine)
[rocksndiamonds.git] / src / game_sp / Electrons.c
1 // ----------------------------------------------------------------------------
2 // Electrons.c
3 // ----------------------------------------------------------------------------
4
5 #include "Electrons.h"
6
7
8 // ==========================================================================
9 //                              SUBROUTINE
10 // Animate/move Electrons
11 // ==========================================================================
12
13 void subAnimateElectrons(int si)
14 {
15   int bx, Tmp;
16
17   if (SnikSnaksElectronsFrozen == 1)
18     return;
19
20   if (LowByte(PlayField16[si]) != fiElectron)
21     return;
22
23   bx = HighByte(PlayField16[si]);
24
25   Tmp = bx / 8;
26   switch (Tmp)
27   {
28     case 0:
29       subElectronTurnLeft(si, bx); // turning, bx=0 -> point N, bx = 1 -> point NW etc.
30       break;
31
32     case 1:
33       subElectronTurnRight(si, bx); // turn right
34       break;
35
36     case 2:
37       subElectronFromBelow(si, bx); // access si from below
38       break;
39
40     case 3:
41       subElectronFromRight(si, bx); // access si from right
42       break;
43
44     case 4:
45       subElectronFromAbove(si, bx); // access si from above
46       break;
47
48     case 5:
49       subElectronFromLeft(si, bx); // access si from left
50       break;
51   }
52 }
53
54 void subDrawAnimatedElectrons(int si)
55 {
56   int bx, Tmp;
57
58   // If SnikSnaksElectronsFrozen = 1 Then Exit Function
59   if (LowByte(PlayField16[si]) != fiElectron)
60     return;
61
62   bx = HighByte(PlayField16[si]);
63
64   Tmp = bx / 8;
65   switch (Tmp)
66   {
67     case 0:
68       subDrawElectronTurnLeft(si, bx); // turning, bx=0 -> point N, bx = 1 -> point NW etc.
69       break;
70
71     case 1:
72       subDrawElectronTurnRight(si, bx); // turn right
73       break;
74
75     case 2:
76       subDrawElectronFromBelow(si, bx); // access si from below
77       break;
78
79     case 3:
80       subDrawElectronFromRight(si, bx); // access si from right
81       break;
82
83     case 4:
84       subDrawElectronFromAbove(si, bx); // access si from above
85       break;
86
87     case 5:
88       subDrawElectronFromLeft(si, bx); // access si from left
89       break;
90   }
91 }
92
93 void subElectronTurnLeft(int si, int bx)
94 {
95   int ax, bl;
96
97   ax = (TimerVar & 3);
98   if (ax != 0)
99   {
100     if (ax == 3)
101       goto loc_g_7ACD;
102
103     return;
104   } // loc_g_7A9F:
105
106   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
107   subDrawElectronTurnLeft(si, bx);
108   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
109
110   bx = (bx + 1) & 0x7;
111   MovHighByte(&PlayField16[si], bx);
112
113   return;
114
115 loc_g_7ACD:
116   bl = HighByte(PlayField16[si]);
117   if (bl == 0)
118     goto loc_g_7AE6;
119
120   if (bl == 2)
121     goto loc_g_7B05;
122
123   if (bl == 4)
124     goto loc_g_7B24;
125
126   if (bl == 6)
127     goto loc_g_7B43;
128
129   return;
130
131 loc_g_7AE6: // pointing up
132   ax = PlayField16[si - FieldWidth];
133   if (ax == 0) // above is empty -> go up
134     goto loc_g_7AF5;
135
136   if (LowByte(ax) == fiMurphy) // above is murphy -> explode
137     ExplodeFieldSP(si);
138
139   return;
140
141 loc_g_7AF5: // above is empty -> go up
142   PlayField16[si] = 0x1BB;
143   si = si - FieldWidth; // 1 field up
144   PlayField16[si] = 0x1018;
145
146   return;
147
148 loc_g_7B05: // pointing left
149   ax = PlayField16[si - 1];
150   if (ax == 0) // left is empty -> go there
151     goto loc_g_7B14;
152
153   if (LowByte(ax) == fiMurphy) // left is murphy -> explode
154     ExplodeFieldSP(si);
155
156   return;
157
158 loc_g_7B14: // left is empty -> go there
159   PlayField16[si] = 0x2BB;
160   si = si - 1; // 1 field left
161   PlayField16[si] = 0x1818;
162
163   return;
164
165 loc_g_7B24: // pointing down
166   ax = PlayField16[si + FieldWidth];
167   if (ax == 0) // below is empty -> go down
168     goto loc_g_7B33;
169
170   if (LowByte(ax) == fiMurphy) // below is murphy -> explode
171     ExplodeFieldSP(si);
172
173   return;
174
175 loc_g_7B33: // below is empty -> go down
176   PlayField16[si] = 0x3BB;
177   si = si + FieldWidth; // 1 field down
178   PlayField16[si] = 0x2018;
179
180   return;
181
182 loc_g_7B43: // pointing Right
183   ax = PlayField16[si + 1];
184   if (ax == 0) // right is empty -> go there
185     goto loc_g_7B55;
186
187   if (LowByte(ax) == fiMurphy) // right is murphy -> explode
188     ExplodeFieldSP(si);
189
190   return;
191
192 loc_g_7B55: // right is empty -> go there
193   PlayField16[si] = 0x4BB;
194   si = si + 1; // 1 field right
195   PlayField16[si] = 0x2818;
196 }
197
198 void subElectronTurnRight(int si, int bx)
199 {
200   int ax, bl;
201
202   ax = (TimerVar & 3);
203   if (ax != 0)
204   {
205     if (ax == 3)
206       goto loc_g_7BA3;
207
208     return;
209   } // loc_g_7B73:
210
211   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
212   subDrawElectronTurnRight(si, bx);
213   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
214
215   bx = ((bx + 1) & 0x7) | 8;
216   MovHighByte(&PlayField16[si], bx);
217
218   return;
219
220 loc_g_7BA3:
221   bl = HighByte(PlayField16[si]);
222   if (bl == 0x8)
223     goto loc_g_7BBC;
224
225   if (bl == 0xA)
226     goto loc_g_7C19;
227
228   if (bl == 0xC)
229     goto loc_g_7BFA;
230
231   if (bl == 0xE)
232     goto loc_g_7BDB;
233
234   return;
235
236 loc_g_7BBC: // pointing up
237   ax = PlayField16[si - FieldWidth];
238   if (ax == 0) // above is empty -> go up
239     goto loc_g_7BCB;
240
241   if (LowByte(ax) == fiMurphy) // above is murphy -> explode
242     ExplodeFieldSP(si);
243
244   return;
245
246 loc_g_7BCB: // above is empty -> go up
247   PlayField16[si] = 0x1BB;
248   si = si - FieldWidth; // 1 field up
249   PlayField16[si] = 0x1018;
250
251   return;
252
253 loc_g_7BDB: // pointing left
254   ax = PlayField16[si - 1];
255   if (ax == 0) // left is empty -> go there
256     goto loc_g_7BEA;
257
258   if (LowByte(ax) == fiMurphy) // left is murphy -> explode
259     ExplodeFieldSP(si);
260
261   return;
262
263 loc_g_7BEA: // left is empty -> go there
264   PlayField16[si] = 0x2BB;
265   si = si - 1; // 1 field left
266   PlayField16[si] = 0x1818;
267
268   return;
269
270 loc_g_7BFA: // pointing down
271   ax = PlayField16[si + FieldWidth];
272   if (ax == 0) // below is empty -> go down
273     goto loc_g_7C09;
274
275   if (LowByte(ax) == fiMurphy) // below is murphy -> explode
276     ExplodeFieldSP(si);
277
278   return;
279
280 loc_g_7C09: // below is empty -> go down
281   PlayField16[si] = 0x3BB;
282   si = si + FieldWidth; // 1 field down
283   PlayField16[si] = 0x2018;
284
285   return;
286
287 loc_g_7C19: // pointing Right
288   ax = PlayField16[si + 1];
289   if (ax == 0) // right is empty -> go there
290     goto loc_g_7C2B;
291
292   if (LowByte(ax) == fiMurphy) // right is murphy -> explode
293     ExplodeFieldSP(si);
294
295   return;
296
297 loc_g_7C2B: // right is empty -> go there
298   PlayField16[si] = 0x4BB;
299   si = si + 1; // 1 field right
300   PlayField16[si] = 0x2818;
301 }
302
303 void subElectronFromBelow(int si, int bx)
304 {
305   int ax, bl;
306
307   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
308   subDrawElectronFromBelow(si, bx);
309   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
310   bx = bx - 0xF;  // get and increment sequence#
311
312   bl = LowByte(bx);
313   if (bl == 7 && LowByte(PlayField16[si + FieldWidth]) != fiExplosion)
314   {
315     PlayField16[si + FieldWidth] = 0; // electron left that field
316   }
317
318   if (bl < 8) // electron still goes up
319   {
320     bl = bl + 0x10;
321     MovHighByte(&PlayField16[si], bl);
322
323     return;
324   } // loc_g_7C84
325
326   PlayField16[si] = 0x18; // sequence#=8 -> arrived at the new field
327   ax = PlayField16[si - 1]; // check left field
328   if (ax == 0 || LowByte(ax) == fiMurphy) // check for empty or murphy
329   {
330     MovHighByte(&PlayField16[si], 1); // start to turn left
331
332     return;
333   } // loc_g_7CA4:
334
335   ax = PlayField16[si - FieldWidth]; // cannot turn left -> check above
336   if (ax == 0) // check if empty
337   {
338     PlayField16[si] = 0x1BB; // mark as "electron leaving"
339     si = si - FieldWidth; // go up!
340     PlayField16[si] = 0x1018;
341
342     return;
343   }
344
345   if (LowByte(ax) == fiMurphy) // check for murphy above
346   {
347     ExplodeFieldSP(si); // Explode
348
349     return;
350   } // loc_g_7CC6:
351
352   ax = PlayField16[si + 1]; // check right field
353   if (ax == 0 || LowByte(ax) == fiMurphy) // check for empty or murphy
354   {
355     MovHighByte(&PlayField16[si], 9); // start to turn right
356
357     return;
358   } // loc_g_7CE0:
359
360   // else: no way to go, start turning around
361   MovHighByte(&PlayField16[si], 1);
362 }
363
364 void subElectronFromRight(int si, int bx)
365 {
366   int ax, bl;
367
368   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
369   subDrawElectronFromRight(si, bx);
370   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
371   bx = bx - 0x17;  // get and increment sequence#
372
373   bl = LowByte(bx);
374   if (bl == 7 && LowByte(PlayField16[si + 1]) != fiExplosion)
375   {
376     PlayField16[si + 1] = 0; // electron left that field
377   } // loc_g_7D1D:
378
379   if (bl < 8) // sniksnak still goes left
380   {
381     bl = bl + 0x18;
382     MovHighByte(&PlayField16[si], bl);
383
384     return;
385   } // loc_g_7D2A:
386
387   PlayField16[si] = 0x18; // sequence#=8 -> arrived at the new field
388   ax = PlayField16[si + FieldWidth]; // check below
389   if (ax == 0 || LowByte(ax) == fiMurphy) // empty or murphy?
390   {
391     MovHighByte(&PlayField16[si], 3); // yes -> turn left down
392
393     return;
394   } // loc_g_7D4A:
395
396   ax = PlayField16[si - 1]; // check left, etc ... see the comments on subElectronFromBelow()
397   if (ax == 0)
398   {
399     PlayField16[si] = 0x2BB;
400     si = si - 1;                // 1 field left
401     PlayField16[si] = 0x1818;
402
403     return;
404   } // loc_g_7D61:
405
406   if (LowByte(ax) == fiMurphy)
407   {
408     ExplodeFieldSP(si);      // Explode
409
410     return;
411   } // loc_g_7D6C:
412
413   ax = PlayField16[si - FieldWidth]; // check above
414   if (ax == 0 || LowByte(ax) == fiMurphy)
415   {
416     MovHighByte(&PlayField16[si], 0xF);
417
418     return;
419   } // loc_g_7D86:
420
421   MovHighByte(&PlayField16[si], 3);
422 }
423
424 void subElectronFromAbove(int si, int bx)
425 {
426   int ax, bl;
427
428   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
429   subDrawElectronFromAbove(si, bx);
430   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
431   bx = bx - 0x1F;  // get and increment sequence#
432
433   bl = LowByte(bx);
434   if (bl == 7 && LowByte(PlayField16[si - FieldWidth]) != fiExplosion)
435   {
436     PlayField16[si - FieldWidth] = 0; // electron left that field
437   }
438
439   if (bl < 8) // electron still goes down
440   {
441     bl = bl + 0x20;
442     MovHighByte(&PlayField16[si], bl);
443
444     return;
445   } // loc_g_7DD7
446
447   PlayField16[si] = 0x18; // sequence#=8 -> arrived at the new field
448   ax = PlayField16[si + 1]; // check right
449   if (ax == 0 || LowByte(ax) == fiMurphy)
450   {
451     MovHighByte(&PlayField16[si], 5);
452
453     return;
454   } // loc_g_7DF7:
455
456   ax = PlayField16[si + FieldWidth]; // check below
457   if (ax == 0)
458   {
459     PlayField16[si] = 0x3BB;
460     si = si + FieldWidth;                 // 1 field down
461     PlayField16[si] = 0x2018;
462
463     return;
464   } // loc_g_7E0E:
465
466   if (LowByte(ax) == fiMurphy)
467   {
468     ExplodeFieldSP(si);        // Explode
469
470     return;
471   } // loc_g_7E19:
472
473   ax = PlayField16[si - 1]; // check left
474   if (ax == 0 || LowByte(ax) == fiMurphy)
475   {
476     MovHighByte(&PlayField16[si], 0xD);
477
478     return;
479   } // loc_g_7E33:
480
481   MovHighByte(&PlayField16[si], 5);
482 }
483
484 void subElectronFromLeft(int si, int bx)
485 {
486   int ax, bl;
487
488   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
489   subDrawElectronFromLeft(si, bx);
490   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
491   bx = bx - 0x27;  // get and increment sequence#
492
493   bl = LowByte(bx);
494   if (bl == 7 && LowByte(PlayField16[si - 1]) != fiExplosion)
495   {
496     PlayField16[si - 1] = 0; // electron left that field
497   }
498
499   if (bl < 8) // electron still goes right
500   {
501     bl = bl + 0x28;
502     MovHighByte(&PlayField16[si], bl);
503
504     return;
505   } // loc_g_7E7E:
506
507   PlayField16[si] = 0x18; // sequence#=8 -> arrived at the new field
508   ax = PlayField16[si - FieldWidth]; // check above
509   if (ax == 0 || LowByte(ax) == fiMurphy)
510   {
511     MovHighByte(&PlayField16[si], 7);
512
513     return;
514   } // loc_g_7E9E:
515
516   ax = PlayField16[si + 1]; // check right(straight on)
517   if (ax == 0)
518   {
519     PlayField16[si] = 0x4BB;
520     si = si + 1;                   // 1 field right
521     PlayField16[si] = 0x2818;
522
523     return;
524   } // loc_g_7EB5:
525
526   if (LowByte(ax) == fiMurphy)
527   {
528     ExplodeFieldSP(si);    // Explode
529
530     return;
531   } // loc_g_7EC0:
532
533   ax = PlayField16[si + FieldWidth]; // check below
534   if (ax == 0 || LowByte(ax) == fiMurphy)
535   {
536     MovHighByte(&PlayField16[si], 0xB);
537
538     return;
539   } // loc_g_7A69:
540
541   MovHighByte(&PlayField16[si], 7);
542 }
543
544 void subDrawElectronTurnLeft(int si, int bx)
545 {
546   int X, Y;
547
548   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
549   X = GetStretchX(si);
550   Y = GetStretchY(si);
551   DDSpriteBuffer_BltImg(X, Y, aniElectron, bx);
552   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
553 }
554
555 void subDrawElectronTurnRight(int si, int bx)
556 {
557   int X, Y;
558
559   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
560   X = GetStretchX(si);
561   Y = GetStretchY(si);
562   DDSpriteBuffer_BltImg(X, Y, aniElectron, 0x10 - bx);
563   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
564 }
565
566 void subDrawElectronFromBelow(int si, int bx)
567 {
568   int X, Y;
569
570   bx = bx - 0xF;  // get and increment sequence#
571
572   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
573   X = GetStretchX(si);
574   Y = GetStretchY(si + FieldWidth);
575   DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
576   DDSpriteBuffer_BltImg(X, Y - bx * TwoPixels, aniElectron, bx);
577   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
578 }
579
580 void subDrawElectronFromRight(int si, int bx)
581 {
582   int X, Y;
583
584   bx = bx - 0x17;  // get and increment sequence#
585
586   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
587   X = GetStretchX(si + 1);
588   Y = GetStretchY(si);
589   DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
590   DDSpriteBuffer_BltImg(X - bx * TwoPixels, Y, aniElectron, bx);
591   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
592 }
593
594 void subDrawElectronFromAbove(int si, int bx)
595 {
596   int X, Y;
597
598   bx = bx - 0x1F;  // get and increment sequence#
599
600   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
601   X = GetStretchX(si);
602   Y = GetStretchY(si - FieldWidth);
603   DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
604   DDSpriteBuffer_BltImg(X, Y + bx * TwoPixels, aniElectron, bx);
605   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
606 }
607
608 void subDrawElectronFromLeft(int si, int bx)
609 {
610   int X, Y;
611
612   bx = bx - 0x27;  // get and increment sequence#
613
614   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
615   X = GetStretchX(si - 1);
616   Y = GetStretchY(si);
617   DDSpriteBuffer_BltImg(X, Y, aniSpace, 0);
618   DDSpriteBuffer_BltImg(X + bx * TwoPixels, Y, aniElectron, bx);
619   // +++++++++++++++++++++++++++++++++++++++++++++++++++++
620 }