rnd-20100315-3-src
[rocksndiamonds.git] / src / game_sp / Murphy.c
1 // ----------------------------------------------------------------------------
2 // Murphy.c
3 // ----------------------------------------------------------------------------
4
5 #include "Murphy.h"
6
7
8 static void subEatRedDisk(int si);
9 static boolean subMoveKillsMurphy(int si, int ax, int bl);
10
11 #if 1
12
13 #define LocalStretch                    (2)
14 #define MurphyZoomFactor                (ZoomFactor)
15
16 #else
17
18 #define LocalStretch                    (1)
19 #define MurphyZoomFactor                (1)
20
21 #endif
22
23 // ==========================================================================
24 //                              SUBROUTINE
25 // Move Murphy in any direction
26 // ==========================================================================
27
28 void subAnimateMurphy(int *si)
29 {
30   int ax, al, bl, i, X, Y;
31   int time1, time2;
32   int tDeltaX, tDeltaY, tPos, Tmp;
33
34   // Variables that hold information about the animation sequence
35   static int *dx = 0; // an array of image positions in moving.mpx, finalized with -1
36   static int dx1 = 0; // same as "*dx" above, but as image/animation token
37   static int dx2 = 0; // an additional image position of a second sprite, for instance: yellow disk if pushed
38   static int MurphyDX = 0, MurphyDY = 0; // murphys move steps
39   static int SeqPos = 0; // index into dx()
40   static int ClearPos = 0; // Position to clear before blitting sprites, none=-1
41   static int dxPos = 0; // field-position  to draw dx(SeqPos)
42   static int dx2Step = 0; // position of dx2 relative to dx-position
43   static int dx1SequenceLength = 0;
44
45   ax = PlayField16[*si];
46   al = LowByte(ax);
47
48   if (al != fiMurphy)
49   {
50     MurphyMoveCounter = 0;             // We have no Murphy! Exit!
51
52     return;
53   }
54
55   MurphyMoveCounter = 1;             // We have a Murphy!
56   MurphyExplodePos = *si;
57
58   // (check if high byte of PlayField16 has stored movement information)
59   if (ax != fiMurphy) // yes--go proceed moving murphy?
60     goto locProceedMovingMurphy;
61
62   // FS: reset moving sequence variables
63   MurphyDX = 0;
64   MurphyDY = 0;
65   ClearPos = *si;
66   dxPos = *si;
67   dx1 = -1;
68   dx2 = -1;
69   SeqPos = 0;
70   // end of FS
71
72   ScratchGravity = 0; // scratch gravity off
73   if (GravityFlag != 0) // Gravity? (1=gravity on)
74   {
75     bl = LowByte(PlayField16[*si - FieldWidth]); // check above
76     if (! (bl == fiPortUp ||
77            bl == fiPortUpAndDown ||
78            bl == fiPortAllDirections))
79     {
80       if (PlayField16[*si + FieldWidth] == 0) // gravity on and space below!
81         ScratchGravity = 1;
82     }
83   } // loc_g_5E8B:
84
85   bl = DemoKeyCode;
86   if (bl != 0) // a key was pressed!
87     goto locKeyPressed5FCF;
88
89 #if 0
90   printf("::: Murphy.c: !!! %d [%d]\n", DemoKeyCode, GravityFlag);
91 #endif
92
93   RedDiskReleaseFlag = 1;
94   if (ScratchGravity != 0) // gravity pulls & space below?'-> force Space up to down
95   {
96     MurphyDY = 2;
97     goto loc_g_6364;
98   }
99
100 #if 1
101
102 #if 0
103   ax = (TimerVar & 3);
104   if (ax != 0)
105     return;
106 #endif
107
108   // ------------------------------------------------------------------
109   // Murphy's YAWN & SLEEP sequence, counted down by YawnSleepCounter:
110
111   YawnSleepCounter = YawnSleepCounter + 1;
112
113   if (YawnSleepCounter < 16)
114     return;
115
116   if (YawnSleepCounter < 2000)
117   {
118     // normal grin
119     // (default: single graphic, no animation)
120     subCopyAnimToScreen(*si, aniMurphy, YawnSleepCounter - 16);
121
122     return;
123   }
124
125   if (YawnSleepCounter < 4000)
126   {
127     // yawn! and look depressed afterwards...
128     // (default: 12 animation frames with delay of 8)
129     subCopyAnimToScreen(*si, aniMurphyYawn, YawnSleepCounter - 2000);
130
131     return;
132   }
133
134   if (YawnSleepCounter < 6400)
135   {
136     // yawn again!
137     // (default: 12 animation frames with delay of 8)
138     subCopyAnimToScreen(*si, aniMurphyYawn, YawnSleepCounter - 4000);
139
140     return;
141   }
142
143   // time1 = 6400 + 12 * 8;     // (default: 6496 == 6400 + 12 * 8)
144   time1 = 6400 + 12 * 10;
145
146   if (YawnSleepCounter < time1)
147   {
148     // yawn again! - third time
149     // (default: 12 animation frames with delay of 8)
150     subCopyAnimToScreen(*si, aniMurphyYawn, YawnSleepCounter - 6400);
151
152     return;
153   }
154
155   // time2 = 6496 + 3 * 64;     // (default: 6688 == 6496 + 3 * 64)
156   time2 = 6496 + 3 * 100;
157
158   if (YawnSleepCounter > time2)         // Murphy already went to sleep
159     return;
160
161   if (PlayField16[*si - 1] == 0)
162   {
163     if (PlayField16[*si + 1] == 0)
164     {
165       // no sleep -- go back to "wait and start yawning" phase
166       YawnSleepCounter = 144;
167
168       return;
169     }
170     else
171     {
172       // go to sleep (right side)
173       // (default: 3 animation frames with delay of 64)
174       subCopyAnimToScreen(*si, aniMurphySleepRight, YawnSleepCounter - time1);
175
176       return;
177     }
178   }
179
180   // go to sleep (left side)
181   // (default: 3 animation frames with delay of 64)
182   subCopyAnimToScreen(*si, aniMurphySleepLeft, YawnSleepCounter - time1);
183
184   return;
185
186   // end of YAWN-SLEEP-Sequence
187
188 #else
189
190   ax = (TimerVar & 3);
191   if (ax != 0)
192     return;
193
194   // ------------------------------------------------------------------
195   // Murphy's YAWN & SLEEP sequence, counted down by YawnSleepCounter:
196   YawnSleepCounter = YawnSleepCounter + 1;
197   if (YawnSleepCounter == 4)
198   {
199     subCopyFieldToScreen(*si, fiMurphy); // normal grin
200     return;
201   } // loc_g_5ECE:
202
203   if (YawnSleepCounter <= 500) // loc_g_5ED7:
204     return;
205
206   if (YawnSleepCounter <= 522)
207   {
208     bx = (YawnSleepCounter - 500) / 2;
209     subCopyFieldToScreen(*si, aniMurphyYawn + bx); // yawn! and look depressed afterwards...
210     return;
211   } // loc_g_5F00:
212
213   if (YawnSleepCounter <= 1000)
214     return;
215
216   if (YawnSleepCounter <= 1022)
217   {
218     bx = (YawnSleepCounter - 1000) / 2;
219     subCopyFieldToScreen(*si, aniMurphyYawn + bx); // yawn again!
220     return;
221   } // loc_g_5F32:
222
223   if (YawnSleepCounter <= 1600) // loc_g_5F3B:
224     return;
225
226   if (YawnSleepCounter <= 1622)
227   {
228     bx = (YawnSleepCounter - 1600) / 2;
229     subCopyFieldToScreen(*si, aniMurphyYawn + bx); // yawn again! - third time
230     return;
231   } // loc_g_5F64:
232
233   if (YawnSleepCounter > 1654)
234     return;
235
236   if (PlayField16[*si - 1] == 0)
237   {
238     if (PlayField16[*si + 1] == 0)
239     {
240       YawnSleepCounter = 36;
241       return;
242
243     }
244     else
245     {
246       bx = (YawnSleepCounter - 1622) / 16;
247       subCopyFieldToScreen(*si, aniMurphySleepRight + bx); // go to sleep
248       return;
249     }
250   } // loc_g_5F81:
251
252   bx = (YawnSleepCounter - 1622) / 16;
253   subCopyFieldToScreen(*si, aniMurphySleepLeft + bx); // go to sleep
254
255   return;
256
257   // end of YAWN-SLEEP-Sequence
258
259 #endif
260
261   // ------------------------------------------------------------------
262   // ==========================================================================
263   //                       (Direct Jump) a key was pressed
264   // ==========================================================================
265
266 locKeyPressed5FCF:
267   if (ScratchGravity == 0)
268     goto loc_g_6003;
269
270   if (PlayField16[*si + FieldWidth] != 0)
271     goto loc_g_6003;
272
273   if (bl == keyUp)
274   {
275     if (PlayField16[*si - FieldWidth] == fiBase)
276       goto loc_g_6003;
277
278   }
279   else if (bl == keyLeft)
280   {
281     if (PlayField16[*si - 1] == fiBase)
282       goto loc_g_6003;
283
284   }
285   else if (bl == keyRight)
286   {
287     if (PlayField16[*si + 1] == fiBase)
288       goto loc_g_6003;
289   } // loc_g_6001:
290
291   bl = keyDown;                      // force moving down!
292 loc_g_6003:
293   switch (bl)
294   {
295     case keyUp: // 1
296       RedDiskReleaseFlag = 0; // moving down to up ...
297       goto loc_g_6078;
298
299       break;
300
301     case keyLeft: // 2
302       RedDiskReleaseFlag = 0; // moving right to left ...
303       goto loc_g_60DA;
304
305       break;
306
307     case keyDown: // 3
308       RedDiskReleaseFlag = 0; // moving up to down ...
309       goto loc_g_6154;
310
311       break;
312
313     case keyRight: // 4
314       RedDiskReleaseFlag = 0; // moving left to right ...
315       goto loc_g_61B6;
316
317       break;
318
319     case keySpaceUp: // 5
320       RedDiskReleaseFlag = 0; // touching down to up ...
321       goto loc_g_622E;
322
323       break;
324
325     case keySpaceLeft: // 6
326       RedDiskReleaseFlag = 0; // touching right to left ...
327       goto loc_g_6258;
328
329       break;
330
331     case keySpaceDown: // 7
332       RedDiskReleaseFlag = 0; // touching up to down ...
333       goto loc_g_6288;
334
335       break;
336
337     case keySpaceRight: // 8
338       RedDiskReleaseFlag = 0; // touching left to right ...
339       goto loc_g_62B2;
340
341       break;
342
343     case keySpace: // 9
344       goto loc_g_62E2;                         // no move ...
345
346       break;
347
348     default:
349       RedDiskReleaseFlag = 0;
350       return;
351       break;
352   }
353
354   // ==========================================================================
355   // moving down to up ...
356   // ==========================================================================
357
358 loc_g_6078:
359   // FS:
360   MurphyDY = -2;
361   // end of FS
362   ax = PlayField16[*si - FieldWidth];
363   al = LowByte(ax);
364   if (ax == fiSpace)
365     goto loc_g_6312;
366
367   if (ax == fiBase)
368     goto loc_g_63D3;
369
370   if (al == fiBug)
371     goto loc_g_63C2;
372
373   if (ax == fiInfotron)
374     goto loc_g_65C6;
375
376   if (ax == fiExit)
377     goto loc_g_6756;
378
379   if (al == fiTerminal)
380     goto loc_g_6817;
381
382   if (al == fiPortUp || al == fiPortUpAndDown || al == fiPortAllDirections)
383     goto loc_g_6916;
384
385   if (al == fiRedDisk)
386     goto loc_g_69A6;
387
388   if (al == fiYellowDisk)
389     goto loc_g_6AB8;
390
391   if (! subMoveKillsMurphy(*si - FieldWidth, ax, bl))
392     goto loc_g_6078;
393
394   return;
395
396   // ==========================================================================
397   // moving right to left ...
398   // ==========================================================================
399
400 loc_g_60DA:
401   // FS:
402   MurphyDX = -2;
403   // end of FS
404   MurphyVarFaceLeft = 1;
405   ax = PlayField16[*si - 1];
406   al = LowByte(ax);
407   if (ax == fiSpace)
408     goto loc_g_6341;
409
410   if (ax == fiBase)
411     goto loc_g_641C;
412
413   if (al == fiBug)
414     goto loc_g_640B;
415
416   if (ax == fiInfotron)
417     goto loc_g_65FE;
418
419   if (ax == fiExit)
420     goto loc_g_6756;
421
422   if (ax == fiZonk)
423     goto loc_g_679B;
424
425   if (al == fiTerminal)
426     goto loc_g_684E;
427
428   if (al == fiPortLeft || al == fiPortLeftAndRight || al == fiPortAllDirections)
429     goto loc_g_693A;
430
431   if (ax == fiRedDisk)
432     goto loc_g_69CE;
433
434   if (ax == fiYellowDisk)
435     goto loc_g_6AF1;
436
437   if (ax == fiOrangeDisk)
438     goto loc_g_6B9B;
439
440   if (! subMoveKillsMurphy(*si - 1, ax, bl))
441     goto loc_g_60DA;
442
443   return;
444
445   // ==========================================================================
446   // moving up to down ...
447   // ==========================================================================
448
449 loc_g_6154:
450   // FS:
451   MurphyDY = 2;
452   // end of FS
453   ax = PlayField16[*si + FieldWidth];
454   al = LowByte(ax);
455   if (ax == fiSpace)
456     goto loc_g_6364;
457
458   if (ax == fiBase)
459     goto loc_g_6459;
460
461   if (al == fiBug)
462     goto loc_g_6448;
463
464   if (ax == fiInfotron)
465     goto loc_g_662A;
466
467   if (ax == fiExit)
468     goto loc_g_6756;
469
470   if (al == fiTerminal)
471     goto loc_g_6884;
472
473   if (al == fiPortDown || al == fiPortUpAndDown || al == fiPortAllDirections)
474     goto loc_g_695E;
475
476   if (al == fiRedDisk)
477     goto loc_g_69F7;
478
479   if (al == fiYellowDisk)
480     goto loc_g_6B2A;
481
482   if (! subMoveKillsMurphy(*si + FieldWidth, ax, bl))
483     goto loc_g_6154;
484
485   return;
486
487   // ==========================================================================
488   // moving left to right ...
489   // ==========================================================================
490
491 loc_g_61B6:
492   // FS:
493   MurphyDX = 2;
494   // end of FS
495   MurphyVarFaceLeft = 0;
496   ax = PlayField16[*si + 1];
497   al = LowByte(ax);
498   if (ax == fiSpace)
499     goto loc_g_6399;
500
501   if (ax == fiBase)
502     goto loc_g_64A2;
503
504   if (al == fiBug)
505     goto loc_g_6491;
506
507   if (ax == fiInfotron)
508     goto loc_g_6662;
509
510   if (ax == fiExit)
511     goto loc_g_6756;
512
513   if (ax == fiZonk)
514     goto loc_g_67D4;
515
516   if (al == fiTerminal)
517     goto loc_g_68BA;
518
519   if (al == fiPortRight || al == fiPortLeftAndRight || al == fiPortAllDirections)
520     goto loc_g_6982;
521
522   if (al == fiRedDisk)
523     goto loc_g_6A1F;
524
525   if (al == fiYellowDisk)
526     goto loc_g_6B63;
527
528   if (ax == fiOrangeDisk)
529     goto loc_g_6BD3;
530
531   if (! subMoveKillsMurphy(*si + 1, ax, bl))
532     goto loc_g_61B6;
533
534   return;
535
536   // ==========================================================================
537   // touching down to up ...
538   // ==========================================================================
539
540 loc_g_622E:
541   // FS:
542   ClearPos = -1;
543   dxPos = *si - FieldWidth;
544   // end of FS
545   ax = PlayField16[*si - FieldWidth];
546   al = LowByte(ax);
547   al = LowByte(ax);
548   if (ax == fiBase)
549     goto loc_g_64DF;
550
551   if (al == fiBug)
552     goto loc_g_64CE;
553
554   if (ax == fiInfotron)
555     goto loc_g_668E;
556
557   if (al == fiTerminal)
558     goto loc_g_6817;
559
560   if (al == fiRedDisk)
561     goto loc_g_6A48;
562
563   return;
564
565   // ==========================================================================
566   // touching right to left ...
567   // ==========================================================================
568
569 loc_g_6258:
570   // FS:
571   ClearPos = -1;
572   dxPos = *si - 1;
573   // end of FS
574   MurphyVarFaceLeft = 1;
575   ax = PlayField16[*si - 1];
576   al = LowByte(ax);
577   if (ax == fiBase)
578     goto loc_g_651D;
579
580   if (al == fiBug)
581     goto loc_g_650C;
582
583   if (ax == fiInfotron)
584     goto loc_g_66C0;
585
586   if (al == fiTerminal)
587     goto loc_g_684E;
588
589   if (al == fiRedDisk)
590     goto loc_g_6A64;
591
592   return;
593
594   // ==========================================================================
595   // touching up to down ...
596   // ==========================================================================
597
598 loc_g_6288:
599   // FS:
600   ClearPos = -1;
601   dxPos = *si + FieldWidth;
602   // end of FS
603   ax = PlayField16[*si + FieldWidth];
604   al = LowByte(ax);
605   if (ax == fiBase)
606     goto loc_g_655B;
607
608   if (al == fiBug)
609     goto loc_g_654A;
610
611   if (ax == fiInfotron)
612     goto loc_g_66F2;
613
614   if (al == fiTerminal)
615     goto loc_g_6884;
616
617   if (al == fiRedDisk)
618     goto loc_g_6A80;
619
620   return;
621
622   // ==========================================================================
623   // touching left to right ...
624   // ==========================================================================
625
626 loc_g_62B2:
627   // FS:
628   ClearPos = -1;
629   dxPos = *si + 1;
630   // end of FS
631   MurphyVarFaceLeft = 0;
632   ax = PlayField16[*si + 1];
633   al = LowByte(ax);
634   if (ax == fiBase)
635     goto loc_g_6599;
636
637   if (al == fiBug)
638     goto loc_g_6588;
639
640   if (ax == fiInfotron)
641     goto loc_g_6724;
642
643   if (al == fiTerminal)
644     goto loc_g_68BA;
645
646   if (al == fiRedDisk)
647     goto loc_g_6A9C;
648
649   return;
650
651   // ==========================================================================
652   // Release Red disk: no move ...
653   // ==========================================================================
654
655 loc_g_62E2:
656   // FS:
657   ClearPos = -1;
658   // end of FS
659   if (LowByte(RedDiskCount) == 0)
660     return;
661
662   if (LowByte(RedDiskReleasePhase) != 0)
663     return;
664
665   if (LowByte(RedDiskReleaseFlag) != 1)
666     return;
667
668   MovHighByte(&PlayField16[*si], 0x2A);
669   MovingPictureSequencePhase = 0x40; // init picture move sequence
670   dx = aniFramesRedDisk;
671   dx1 = aniRedDisk;
672   MovLowByte(&RedDiskReleasePhase, 1);
673   RedDiskReleaseMurphyPos = *si;             // remember Murphy's location
674   goto loc_Split;
675
676   // ==========================================================================
677   // SPACE moving down to up
678   // ==========================================================================
679
680 loc_g_6312:
681   dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
682   dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyMoveUpRight : aniMurphyMoveUpLeft);
683   PlayField16[*si - FieldWidth] = 0x103;
684   PlayField16[*si] = 0x300;
685   *si = *si - FieldWidth;
686   goto loc_StopNoSplit;
687
688   // ==========================================================================
689   // SPACE moving right to left
690   // ==========================================================================
691
692 loc_g_6341:
693   dx = aniFramesMurphyEatLeft;
694   dx1 = aniMurphyMoveLeft;
695   PlayField16[*si - 1] = 0x203;
696   PlayField16[*si] = 0x300;
697   *si = *si - 1;
698   goto loc_StopNoSplit;
699
700   // ==========================================================================
701   // SPACE moving up to down, and when gravity is pulling!
702   // ==========================================================================
703
704 loc_g_6364:
705   dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
706   dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyMoveUpRight : aniMurphyMoveUpLeft);
707   PlayField16[*si + FieldWidth] = 0x303;
708   PlayField16[*si] = 0x300;
709   *si = *si + FieldWidth;
710   goto loc_StopNoSplit;
711
712   // ==========================================================================
713   // SPACE moving left to right
714   // ==========================================================================
715
716 loc_g_6399:
717   dx = aniFramesMurphyEatRight;
718   dx1 = aniMurphyMoveRight;
719   PlayField16[*si + 1] = 0x403;
720   PlayField16[*si] = 0x300;
721   *si = *si + 1;
722   goto loc_StopNoSplit;
723
724   // ==========================================================================
725   // BUG moving down to up
726   // ==========================================================================
727
728 loc_g_63C2:
729   if (SgnHighByte(PlayField16[*si - FieldWidth]) >= 0)
730   {
731     ExplodeFieldSP(*si);                 // Explode
732
733     return;
734   }
735
736   PlayField16[*si - FieldWidth] = fiBase;
737   // ==========================================================================
738   // BASE moving down to up
739   // ==========================================================================
740
741 loc_g_63D3:
742 #if 1
743   subSoundFX(*si, fiBase, actDigging);
744 #else
745   subSoundFXBase();
746 #endif
747
748   dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
749   dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyDigUpRight : aniMurphyDigUpLeft);
750   PlayField16[*si - FieldWidth] = 0x503;
751   PlayField16[*si] = 0x300;
752   *si = *si - FieldWidth;
753   goto loc_StopNoSplit;
754
755   // ==========================================================================
756   // BUG moving right to left
757   // ==========================================================================
758
759 loc_g_640B:
760   if (SgnHighByte(PlayField16[*si - 1]) >= 0)
761   {
762     ExplodeFieldSP(*si);                 // Explode
763
764     return;
765   }
766
767   PlayField16[*si - 1] = fiBase;
768   // ==========================================================================
769   // BASE moving right to left
770   // ==========================================================================
771
772 loc_g_641C:
773 #if 1
774   subSoundFX(*si, fiBase, actDigging);
775 #else
776   subSoundFXBase();
777 #endif
778
779   dx = aniFramesMurphyEatLeft;
780   dx1 = aniMurphyDigLeft;
781   PlayField16[*si - 1] = 0x203;
782   PlayField16[*si] = 0x300;
783   *si = *si - 1;
784   goto loc_StopNoSplit;
785
786   // ==========================================================================
787   // BUG moving up to down
788   // ==========================================================================
789
790 loc_g_6448:
791   if (SgnHighByte(PlayField16[*si + FieldWidth]) >= 0)
792   {
793     ExplodeFieldSP(*si);                 // Explode
794
795     return;
796   }
797
798   PlayField16[*si + FieldWidth] = fiBase;
799   // ==========================================================================
800   // BASE moving up to down
801   // ==========================================================================
802
803 loc_g_6459:
804 #if 1
805   subSoundFX(*si, fiBase, actDigging);
806 #else
807   subSoundFXBase();
808 #endif
809
810   dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
811   dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyDigUpRight : aniMurphyDigUpLeft);
812   PlayField16[*si + FieldWidth] = 0x703;
813   PlayField16[*si] = 0x300;
814   *si = *si + FieldWidth;
815   goto loc_StopNoSplit;
816
817   // ==========================================================================
818   // BUG moving left to right
819   // ==========================================================================
820
821 loc_g_6491:
822   if (SgnHighByte(PlayField16[*si + 1]) >= 0)
823   {
824     ExplodeFieldSP(*si);                 // Explode
825
826     return;
827   }
828
829   PlayField16[*si + 1] = fiBase;
830   // ==========================================================================
831   // BASE moving left to right
832   // ==========================================================================
833
834 loc_g_64A2:
835 #if 1
836   subSoundFX(*si, fiBase, actDigging);
837 #else
838   subSoundFXBase();
839 #endif
840
841   dx = aniFramesMurphyEatRight;
842   dx1 = aniMurphyDigRight;
843   PlayField16[*si + 1] = 0x803;
844   PlayField16[*si] = 0x300;
845   *si = *si + 1;
846   goto loc_StopNoSplit;
847
848   // ==========================================================================
849   // BUG touching down to up
850   // ==========================================================================
851
852 loc_g_64CE:
853   if (SgnHighByte(PlayField16[*si - FieldWidth]) >= 0)
854   {
855     ExplodeFieldSP(*si);                 // Explode
856
857     return;
858   }
859
860   PlayField16[*si - FieldWidth] = fiBase;
861   // ==========================================================================
862   // BASE touching down to up
863   // ==========================================================================
864
865 loc_g_64DF:
866   subCopyImageToScreen(*si, aniMurphyTouchUp);
867 #if 1
868   subSoundFX(*si, fiBase, actDigging);
869 #else
870   subSoundFXBase();
871 #endif
872
873   dx = aniFramesTouchBase;
874   dx1 = aniTouchBase;
875   dxPos = *si - FieldWidth;
876   MovHighByte(&PlayField16[*si], 0x10);
877   goto loc_StopNoSplit;
878
879   // ==========================================================================
880   // BUG touching right to left
881   // ==========================================================================
882
883 loc_g_650C:
884   if (SgnHighByte(PlayField16[*si - 1]) >= 0)
885   {
886     ExplodeFieldSP(*si);                 // Explode
887
888     return;
889   }
890
891   PlayField16[*si - 1] = fiBase;
892   // ==========================================================================
893   // BASE touching right to left
894   // ==========================================================================
895
896 loc_g_651D:
897   subCopyImageToScreen(*si, aniMurphyTouchLeft);
898 #if 1
899   subSoundFX(*si, fiBase, actDigging);
900 #else
901   subSoundFXBase();
902 #endif
903
904   dx = aniFramesTouchBase;
905   dx1 = aniTouchBase;
906   dxPos = *si - 1;
907   MovHighByte(&PlayField16[*si], 0x11);
908   goto loc_StopNoSplit;
909
910   // ==========================================================================
911   // BUG touching up to down
912   // ==========================================================================
913
914 loc_g_654A:
915   if (SgnHighByte(PlayField16[*si + FieldWidth]) >= 0)
916   {
917     ExplodeFieldSP(*si);                 // Explode
918
919     return;
920   }
921
922   PlayField16[*si + FieldWidth] = fiBase;
923   // ==========================================================================
924   // BASE touching up to down
925   // ==========================================================================
926
927 loc_g_655B:
928   subCopyImageToScreen(*si, aniMurphyTouchDown);
929 #if 1
930   subSoundFX(*si, fiBase, actDigging);
931 #else
932   subSoundFXBase();
933 #endif
934
935   dx = aniFramesTouchBase;
936   dx1 = aniTouchBase;
937   dxPos = *si + FieldWidth;
938   MovHighByte(&PlayField16[*si], 0x12);
939   goto loc_StopNoSplit;
940
941   // ==========================================================================
942   // BUG touching left to right
943   // ==========================================================================
944
945 loc_g_6588:
946   if (SgnHighByte(PlayField16[*si + 1]) >= 0)
947   {
948     ExplodeFieldSP(*si);                 // Explode
949
950     return;
951   }
952
953   PlayField16[*si + 1] = fiBase;
954   // ==========================================================================
955   // BASE touching left to right
956   // ==========================================================================
957
958 loc_g_6599:
959   subCopyImageToScreen(*si, aniMurphyTouchRight);
960 #if 1
961   subSoundFX(*si, fiBase, actDigging);
962 #else
963   subSoundFXBase();
964 #endif
965
966   dx = aniFramesTouchBase;
967   dx1 = aniTouchBase;
968   dxPos = *si + 1;
969   MovHighByte(&PlayField16[*si], 0x13);
970   goto loc_StopNoSplit;
971
972   // ==========================================================================
973   // INFOTRON moving down to up
974   // ==========================================================================
975
976 loc_g_65C6:
977 #if 1
978   subSoundFX(*si, fiInfotron, actCollecting);
979 #else
980   subSoundFXInfotron();
981 #endif
982
983   dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
984   dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
985   PlayField16[*si - FieldWidth] = 0x903;
986   PlayField16[*si] = 0x300;
987   *si = *si - FieldWidth;
988   goto loc_StopNoSplit;
989
990   // ==========================================================================
991   // INFOTRON moving right to left
992   // ==========================================================================
993
994 loc_g_65FE:
995 #if 1
996   subSoundFX(*si, fiInfotron, actCollecting);
997 #else
998   subSoundFXInfotron();
999 #endif
1000
1001   dx = aniFramesEatInfotronLeft;
1002   dx1 = aniEatInfotronLeft;
1003 #if 0
1004   dx2 = fiInfotron;
1005   dx2Step = -1;
1006   ClearPos = -1;
1007 #endif
1008   PlayField16[*si - 1] = 0xA03;
1009   PlayField16[*si] = 0x300;
1010   *si = *si - 1;
1011   goto loc_StopNoSplit;
1012
1013   // ==========================================================================
1014   // INFOTRON moving up to down
1015   // ==========================================================================
1016
1017 loc_g_662A:
1018 #if 1
1019   subSoundFX(*si, fiInfotron, actCollecting);
1020 #else
1021   subSoundFXInfotron();
1022 #endif
1023
1024   dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
1025   dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
1026   PlayField16[*si + FieldWidth] = 0xB03;
1027   PlayField16[*si] = 0x300;
1028   *si = *si + FieldWidth;
1029   goto loc_StopNoSplit;
1030
1031   // ==========================================================================
1032   // INFOTRON moving left to right
1033   // ==========================================================================
1034
1035 loc_g_6662:
1036 #if 1
1037   subSoundFX(*si, fiInfotron, actCollecting);
1038 #else
1039   subSoundFXInfotron();
1040 #endif
1041
1042   dx = aniFramesEatInfotronRight;
1043   dx1 = aniEatInfotronRight;
1044 #if 0
1045   dx2 = fiInfotron;
1046   dx2Step = 1;
1047   ClearPos = -1;
1048 #endif
1049   PlayField16[*si + 1] = 0xC03;
1050   PlayField16[*si] = 0x300;
1051   *si = *si + 1;
1052   goto loc_StopNoSplit;
1053
1054   // ==========================================================================
1055   // INFOTRON touching down to up
1056   // ==========================================================================
1057
1058 loc_g_668E:
1059   subCopyImageToScreen(*si, aniMurphyTouchUp);
1060 #if 1
1061   subSoundFX(*si, fiInfotron, actCollecting);
1062 #else
1063   subSoundFXInfotron();
1064 #endif
1065
1066   dx = aniFramesTouchInfotron;
1067   dx1 = aniTouchInfotron;
1068   MovHighByte(&PlayField16[*si], 0x14);
1069   MovHighByte(&PlayField16[*si - FieldWidth], 0xFF);
1070   goto loc_StopNoSplit;
1071
1072   // ==========================================================================
1073   // INFOTRON touching right to left
1074   // ==========================================================================
1075
1076 loc_g_66C0:
1077   subCopyImageToScreen(*si, aniMurphyTouchLeft);
1078 #if 1
1079   subSoundFX(*si, fiInfotron, actCollecting);
1080 #else
1081   subSoundFXInfotron();
1082 #endif
1083
1084   dx = aniFramesTouchInfotron;
1085   dx1 = aniTouchInfotron;
1086   MovHighByte(&PlayField16[*si], 0x15);
1087   MovHighByte(&PlayField16[*si - 1], 0xFF);
1088   goto loc_StopNoSplit;
1089
1090   // ==========================================================================
1091   // INFOTRON touching up to down
1092   // ==========================================================================
1093
1094 loc_g_66F2:
1095   subCopyImageToScreen(*si, aniMurphyTouchDown);
1096 #if 1
1097   subSoundFX(*si, fiInfotron, actCollecting);
1098 #else
1099   subSoundFXInfotron();
1100 #endif
1101
1102   dx = aniFramesTouchInfotron;
1103   dx1 = aniTouchInfotron;
1104   MovHighByte(&PlayField16[*si], 0x16);
1105   MovHighByte(&PlayField16[*si + FieldWidth], 0xFF);
1106   goto loc_StopNoSplit;
1107
1108   // ==========================================================================
1109   // INFOTRON touching left to right
1110   // ==========================================================================
1111
1112 loc_g_6724:
1113   subCopyImageToScreen(*si, aniMurphyTouchRight);
1114 #if 1
1115   subSoundFX(*si, fiInfotron, actCollecting);
1116 #else
1117   subSoundFXInfotron();
1118 #endif
1119
1120   dx = aniFramesTouchInfotron;
1121   dx1 = aniTouchInfotron;
1122   MovHighByte(&PlayField16[*si], 0x17);
1123   MovHighByte(&PlayField16[*si + 1], 0xFF);
1124   goto loc_StopNoSplit;
1125
1126   // ==========================================================================
1127   // EXIT pressed from any direction
1128   // ==========================================================================
1129
1130 loc_g_6756:
1131   // FS
1132   ClearPos = -1;
1133   MurphyDX = 0;
1134   MurphyDY = 0;
1135   // end of FS
1136   if (LowByte(InfotronsNeeded) != 0)
1137     return;
1138
1139 #if 1
1140   if (!game_sp.LevelSolved)
1141     printf("::: Murphy.c: !!!!!!!!!! LEVEL %d SOLVED !!!!!!!!!!\n",LevelNumber);
1142 #endif
1143
1144 #if 1
1145   game_sp.LevelSolved = TRUE;
1146 #endif
1147
1148 #if 1
1149   subSoundFX(*si, fiExit, actPassing);
1150 #else
1151   subSoundFXExit();
1152 #endif
1153
1154   data_h_DemoDone = 1; // EP set level success bytes
1155   LevelStatus = 1; // set Level Status DONE
1156   EP_GameDemoVar0DAA = 0; // force demo for lead-out
1157   if (SavedGameFlag == 0) // saved game running?
1158   {
1159     if (UpdateTimeFlag != 0)    // update time?
1160     {
1161       UpdatedFlag = 1; // prevent double update
1162     }
1163   }
1164
1165 #if 0
1166   subUpdateHallOfFame(); // update time + Hall-Of-Fame
1167 #endif
1168
1169   LeadOutCounter = 0x40;          // quit: start lead-out
1170   dx = aniFramesMurphyExit;
1171   dx1 = aniMurphyExit;
1172   MovHighByte(&PlayField16[*si], 0xD);
1173   goto loc_StopNoSplit;
1174
1175   // ==========================================================================
1176   // ZONK moving right to left
1177   // ==========================================================================
1178
1179 loc_g_679B:
1180   ax = PlayField16[*si - 2];
1181   if (ax != 0)
1182     return;
1183
1184   MovHighByte(&PlayField16[*si - 2], 1);
1185   subCopyImageToScreen(*si, aniPushLeft); // draw pushing murphy
1186   dx = aniFramesZonkRollLeft;
1187   dx1 = aniZonkRollLeft;
1188   dxPos = *si - 1;
1189   dx2 = aniPushLeft;
1190   dx2Step = 1;
1191   MovHighByte(&PlayField16[*si], 0xE);
1192   goto loc_MoveNoSplit;
1193
1194   // ==========================================================================
1195   // ZONK moving left to right
1196   // ==========================================================================
1197
1198 loc_g_67D4:
1199   ax = PlayField16[*si + 2];
1200   if (ax != 0)
1201     return;
1202
1203   ax = PlayField16[*si + FieldWidth + 1];
1204   if (ax == 0) // zonk falls
1205     return;
1206
1207   MovHighByte(&PlayField16[*si + 2], 1);
1208   subCopyImageToScreen(*si, aniPushRight); // draw pushing murphy
1209   dx = aniFramesZonkRollRight;
1210   dx1 = aniZonkRollRight;
1211   dxPos = *si + 1;
1212   dx2 = aniPushRight;
1213   dx2Step = -1;
1214   MovHighByte(&PlayField16[*si], 0xF);
1215   goto loc_MoveNoSplit;
1216
1217   // ==========================================================================
1218   // TERMINAL moving/touching down to up
1219   // ==========================================================================
1220
1221 loc_g_6817:
1222   subCopyImageToScreen(*si, aniMurphyTouchUp);
1223   if (YellowDisksExploded != 0)
1224   {
1225     YawnSleepCounter = 40; // stay hypnotized
1226
1227     return;
1228   } // loc_g_6838:
1229
1230 #if 1
1231   // draw new terminal type
1232 #if 1
1233   GfxGraphic[GetX(*si - FieldWidth)][GetY(*si - FieldWidth)] = aniTerminalActive;
1234 #else
1235   subCopyImageToScreen(*si - FieldWidth, aniTerminalActive);
1236 #endif
1237 #else
1238   subCopyFieldToScreen(*si - FieldWidth, 0x88); // draw new terminal type
1239 #endif
1240   TerminalState[*si - FieldWidth] = 8;
1241   goto loc_g_68F0;
1242
1243   // ==========================================================================
1244   // TERMINAL moving/touching right to left
1245   // ==========================================================================
1246
1247 loc_g_684E:
1248   subCopyImageToScreen(*si, aniMurphyTouchLeft);
1249   if (YellowDisksExploded != 0)
1250   {
1251     YawnSleepCounter = 40; // stay hypnotized
1252
1253     return;
1254   } // loc_g_6838:
1255
1256 #if 1
1257   // draw new terminal type
1258 #if 1
1259   GfxGraphic[GetX(*si - 1)][GetY(*si - 1)] = aniTerminalActive;
1260 #else
1261   subCopyImageToScreen(*si - 1, aniTerminalActive);
1262 #endif
1263 #else
1264   subCopyFieldToScreen(*si - 1, 0x88); // draw new terminal type
1265 #endif
1266   TerminalState[*si - 1] = 8;
1267   goto loc_g_68F0;
1268
1269   // ==========================================================================
1270   // TERMINAL moving/touching up to down
1271   // ==========================================================================
1272
1273 loc_g_6884:
1274   subCopyImageToScreen(*si, aniMurphyTouchDown);
1275   if (YellowDisksExploded != 0)
1276   {
1277     YawnSleepCounter = 40; // stay hypnotized
1278
1279     return;
1280   } // loc_g_6838:
1281
1282 #if 1
1283   // draw new terminal type
1284 #if 1
1285   GfxGraphic[GetX(*si + FieldWidth)][GetY(*si + FieldWidth)] = aniTerminalActive;
1286 #else
1287   subCopyImageToScreen(*si + FieldWidth, aniTerminalActive);
1288 #endif
1289 #else
1290   subCopyFieldToScreen(*si + FieldWidth, 0x88); // draw new terminal type
1291 #endif
1292   TerminalState[*si + FieldWidth] = 8;
1293   goto loc_g_68F0;
1294
1295   // ==========================================================================
1296   // TERMINAL moving/touching left to right
1297   // ==========================================================================
1298
1299 loc_g_68BA:
1300   subCopyImageToScreen(*si, aniMurphyTouchRight);
1301   if (YellowDisksExploded != 0)
1302   {
1303     YawnSleepCounter = 40; // stay hypnotized
1304
1305     return;
1306   } // loc_g_6838:
1307
1308 #if 1
1309   // draw new terminal type
1310 #if 1
1311   GfxGraphic[GetX(*si + 1)][GetY(*si + 1)] = aniTerminalActive;
1312 #else
1313   subCopyImageToScreen(*si + 1, aniTerminalActive);
1314 #endif
1315 #else
1316   subCopyFieldToScreen(*si + 1, 0x88); // draw new terminal type
1317 #endif
1318   TerminalState[*si + 1] = 8;
1319   // ==========================================================================
1320   // common TERMINAL stuff moving/touching from all directions
1321   // ==========================================================================
1322
1323 loc_g_68F0:
1324   TerminalMaxCycles = 7;
1325   YellowDisksExploded = 1;
1326   for (i = 0; i <= LevelMax; i++)
1327   {
1328     if (PlayField16[i] == fiYellowDisk)
1329       ExplodeFieldSP (i);
1330   }
1331
1332   return;
1333
1334   // ==========================================================================
1335   // PORT down to up, VERTICAL PORT, CROSS PORT all moving down to up
1336   // ==========================================================================
1337
1338 loc_g_6916:
1339   if (PlayField16[*si - 2 * FieldWidth] != 0)
1340     return;
1341
1342   dx = aniFramesSplitUpDown;
1343   dx1 = aniSplitUpDown;
1344   dx2Step = -FieldWidth;
1345   PlayField16[*si] = 0x1803;
1346   PlayField16[*si - 2 * FieldWidth] = 0x300;
1347   goto loc_StopSplit;
1348
1349   // ==========================================================================
1350   // PORT right to left, HORIZONTAL PORT, CROSS PORT all moving right to left
1351   // ==========================================================================
1352
1353 loc_g_693A:
1354   if (PlayField16[*si - 2] != 0)
1355     return;
1356
1357   dx = aniFramesMurphyEatLeft;
1358   dx1 = aniMurphyMoveLeft;
1359   dx2Step = -1;
1360   PlayField16[*si] = 0x1903;
1361   PlayField16[*si - 2] = 0x300;
1362   goto loc_StopSplit;
1363
1364   // ==========================================================================
1365   // PORT up to down, VERTICAL PORT, CROSS PORT all moving up to down
1366   // ==========================================================================
1367
1368 loc_g_695E:
1369   if (PlayField16[*si + 2 * FieldWidth] != 0)
1370     return;
1371
1372   dx = aniFramesSplitUpDown;
1373   dx1 = aniSplitUpDown;
1374   dx2Step = FieldWidth;
1375   PlayField16[*si] = 0x1A03;
1376   PlayField16[*si + 2 * FieldWidth] = 0x300;
1377   goto loc_StopSplit;
1378
1379   // ==========================================================================
1380   // PORT left to right, HORIZONTAL PORT, CROSS PORT all moving left to right
1381   // ==========================================================================
1382
1383 loc_g_6982:
1384   if (PlayField16[*si + 2] != 0)
1385     return;
1386
1387   dx = aniFramesMurphyEatRight;
1388   dx1 = aniMurphyMoveRight;
1389   dx2Step = 1;
1390   PlayField16[*si] = 0x1B03;
1391   PlayField16[*si + 2] = 0x300;
1392
1393 loc_StopSplit:
1394   MovingPictureSequencePhase = 0; // stop picture move sequence
1395   SplitMoveFlag = 1; // port: split movement
1396   goto loc_Split;
1397
1398   // ==========================================================================
1399   // RED DISK moving down to up
1400   // ==========================================================================
1401
1402 loc_g_69A6:
1403   dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
1404   dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
1405   PlayField16[*si] = 0x1C03;
1406   PlayField16[*si - FieldWidth] = 0x300;
1407   goto loc_StopNoSplit;
1408
1409   // ==========================================================================
1410   // RED DISK moving right to left
1411   // ==========================================================================
1412
1413 loc_g_69CE:
1414   dx = aniFramesMurphyEatLeft;
1415   dx1 = aniMurphyEatLeft;
1416   PlayField16[*si] = 0x300; // !!!!!! this time we move murphy at sequence-start!
1417   PlayField16[*si - 1] = 0x1D03;
1418   *si = *si - 1;
1419   goto loc_StopNoSplit;
1420
1421   // ==========================================================================
1422   // RED DISK moving up to down
1423   // ==========================================================================
1424
1425 loc_g_69F7:
1426   dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
1427   dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
1428   PlayField16[*si] = 0x1E03;
1429   PlayField16[*si + FieldWidth] = 0x300;
1430   goto loc_StopNoSplit;
1431
1432   // ==========================================================================
1433   // RED DISK moving left to right
1434   // ==========================================================================
1435
1436 loc_g_6A1F:
1437   //  dx = aniFramesMurphyEatRightRedDisk 'this sequence is 9 steps long!
1438   dx = aniFramesMurphyEatRight;
1439   dx1 = aniMurphyEatRight;
1440   // --------------------------------------------------------------------------
1441   // BugFix
1442   // Table data_h_145A, pointed to by table data_h_105E, has a severe bug:
1443   // The Red Disk sequence is 8 pictures long, but 9 are displayed, because it
1444   // has 1 extra entry, which causes Murphy to end slightly shifted to the left!
1445   // We may not fix the table, because then the timing of the game changes
1446   // and several existing demo's do not run properly anymore.
1447   // We only correct Murphies x-location here, when the sequence starts.
1448   // Remember that this is not the real bug-fix, but we must live with
1449   // this existing bug and correct for the consequences of it.
1450
1451 #if 1
1452   if (0 == AllowEatRightRedDiskBug) // Murphy's screen x-position
1453     MurphyScreenXPos = MurphyScreenXPos - 2 * MurphyZoomFactor;
1454 #else
1455   if (0 == AllowEatRightRedDiskBug) // Murphy's screen x-position
1456     MurphyScreenXPos = MurphyScreenXPos - 2;
1457 #endif
1458
1459   SeqPos = -1;
1460   // FS: for me this means to blit the first animation frame twice
1461   // end of BugFix
1462   // --------------------------------------------------------------------------
1463   PlayField16[*si] = 0x300; // !!!!!! this time we move murphy at sequence-start!
1464   PlayField16[*si + 1] = 0x1F03;
1465   *si = *si + 1;
1466   goto loc_StopNoSplit;
1467
1468   // ==========================================================================
1469   // RED DISK touching down to up
1470   // ==========================================================================
1471
1472 loc_g_6A48:
1473   dx = aniFramesTouchRedDisk;
1474   dx1 = aniTouchRedDisk;
1475   MovHighByte(&PlayField16[*si], 0x20);
1476   MovHighByte(&PlayField16[*si - FieldWidth], 3);
1477   goto loc_StopNoSplit;
1478
1479   // ==========================================================================
1480   // RED DISK touching right to left
1481   // ==========================================================================
1482
1483 loc_g_6A64:
1484   dx = aniFramesTouchRedDisk;
1485   dx1 = aniTouchRedDisk;
1486   MovHighByte(&PlayField16[*si], 0x21);
1487   MovHighByte(&PlayField16[*si - 1], 3);
1488   goto loc_StopNoSplit;
1489
1490   // ==========================================================================
1491   // RED DISK touching up to down
1492   // ==========================================================================
1493
1494 loc_g_6A80:
1495   dx = aniFramesTouchRedDisk;
1496   dx1 = aniTouchRedDisk;
1497   MovHighByte(&PlayField16[*si], 0x22);
1498   MovHighByte(&PlayField16[*si + FieldWidth], 3);
1499   goto loc_StopNoSplit;
1500
1501   // ==========================================================================
1502   // RED DISK touching left to right
1503   // ==========================================================================
1504
1505 loc_g_6A9C:
1506   dx = aniFramesTouchRedDisk;
1507   dx1 = aniTouchRedDisk;
1508   MovHighByte(&PlayField16[*si], 0x23);
1509   MovHighByte(&PlayField16[*si + 1], 3);
1510
1511 loc_StopNoSplit:
1512   MovingPictureSequencePhase = 0; // stop picture move sequence
1513   goto loc_NoSplit;
1514
1515   // ==========================================================================
1516   // YELLOW DISK moving down to up
1517   // ==========================================================================
1518
1519 loc_g_6AB8:
1520   if (PlayField16[*si - 2 * FieldWidth] != 0)
1521     return;
1522
1523   PlayField16[*si - 2 * FieldWidth] = 0x1200;
1524 #if 0
1525   subCopyImageToScreen(*si, aniPushRight);
1526 #endif
1527   dx = aniFramesYellowDisk;
1528   dx1 = aniYellowDisk;
1529   dxPos = *si - FieldWidth;
1530 #if 1
1531   dx2 = (MurphyVarFaceLeft == 0 ? aniPushRight : aniPushLeft);
1532 #else
1533   dx2 = aniPushUpDown;
1534 #endif
1535   dx2Step = FieldWidth;
1536   PlayField16[*si] = 0x2403;
1537 #if 1
1538   subCopyImageToScreen(*si, dx2);
1539 #endif
1540   goto loc_MoveNoSplit;
1541
1542   // ==========================================================================
1543   // YELLOW DISK moving right to left
1544   // ==========================================================================
1545
1546 loc_g_6AF1:
1547   if (PlayField16[*si - 2] != 0)
1548     return;
1549
1550   PlayField16[*si - 2] = 0x1200;
1551   subCopyImageToScreen(*si, aniPushLeft);
1552   dx = aniFramesYellowDisk;
1553   dx1 = aniYellowDisk;
1554   dxPos = *si - 1;
1555   dx2 = aniPushLeft;
1556   dx2Step = 1;
1557   PlayField16[*si] = 0x2503;
1558   goto loc_MoveNoSplit;
1559
1560   // ==========================================================================
1561   // YELLOW DISK moving up to down
1562   // ==========================================================================
1563
1564 loc_g_6B2A:
1565   if (PlayField16[*si + 2 * FieldWidth] != 0)
1566     return;
1567
1568   PlayField16[*si + 2 * FieldWidth] = 0x1200;
1569 #if 0
1570   subCopyImageToScreen(*si, aniPushRight);
1571 #endif
1572   dx = aniFramesYellowDisk;
1573   dx1 = aniYellowDisk;
1574   dxPos = *si + FieldWidth;
1575 #if 1
1576   dx2 = (MurphyVarFaceLeft == 0 ? aniPushRight : aniPushLeft);
1577 #else
1578   dx2 = aniPushUpDown;
1579 #endif
1580   dx2Step = -FieldWidth;
1581   PlayField16[*si] = 0x2703;
1582 #if 1
1583   subCopyImageToScreen(*si, dx2);
1584 #endif
1585   goto loc_MoveNoSplit;
1586
1587   // ==========================================================================
1588   // YELLOW DISK moving left to right
1589   // ==========================================================================
1590
1591 loc_g_6B63:
1592   if (PlayField16[*si + 2] != 0)
1593     return;
1594
1595   PlayField16[*si + 2] = 0x1200;
1596   subCopyImageToScreen(*si, aniPushRight);
1597   dx = aniFramesYellowDisk;
1598   dx1 = aniYellowDisk;
1599   dxPos = *si + 1;
1600   dx2 = aniPushRight;
1601   dx2Step = -1;
1602   PlayField16[*si] = 0x2603;
1603   goto loc_MoveNoSplit;
1604
1605   // ==========================================================================
1606   // ORANGE DISK moving right to left
1607   // ==========================================================================
1608
1609 loc_g_6B9B:
1610   if (PlayField16[*si - 2] != 0)
1611     return;
1612
1613   PlayField16[*si - 2] = 0x800;
1614   subCopyImageToScreen(*si, aniPushLeft);
1615   dx = aniFramesOrangeDisk;
1616   dx1 = aniOrangeDisk;
1617   dxPos = *si - 1;
1618   dx2 = aniPushLeft;
1619   dx2Step = 1;
1620   PlayField16[*si] = 0x2803;
1621   goto loc_MoveNoSplit;
1622
1623   // ==========================================================================
1624   // ORANGE DISK moving left to right
1625   // ==========================================================================
1626
1627 loc_g_6BD3:
1628   if (PlayField16[*si + 2] != 0)
1629     return;
1630
1631   if (PlayField16[*si + FieldWidth + 1] == 0) // falling goes before pushing
1632     return;
1633
1634   PlayField16[*si + 2] = 0x100;
1635   subCopyImageToScreen(*si, aniPushRight);
1636   dx = aniFramesOrangeDisk;
1637   dx1 = aniOrangeDisk;
1638   dxPos = *si + 1;
1639   dx2 = aniPushRight;
1640   dx2Step = -1;
1641   PlayField16[*si] = 0x2903;
1642   // ==========================================================================
1643   // Copy screen animation action table to action work space
1644   // (To paint sequence: Push Zonk/Disk / release red disk / Port passing)
1645   // ==========================================================================
1646
1647 loc_MoveNoSplit:
1648   MovingPictureSequencePhase = 8; // init picture move sequence
1649
1650 loc_NoSplit:
1651   SplitMoveFlag = 0; // no port: no split movement
1652
1653 loc_Split:
1654   //  copy/store global move sequence info????????????????????????????????????
1655   //  ... dont think so ...(FS)
1656   // ==========================================================================
1657   // Proceed with all movements
1658   // ==========================================================================
1659
1660 locProceedMovingMurphy: // proceed moving murphy
1661   YawnSleepCounter = 0; // Wake up sleeping Murphy
1662   ax = MovingPictureSequencePhase;            // sequence busy?
1663   if (ax == 0)             // no -- start sequence!
1664     goto loc_g_6C8F;
1665
1666   ax = ax - 1;   // next picture of sequence
1667   MovingPictureSequencePhase = ax;            // store for later
1668
1669   if (ax == 0) // Sound effects
1670 #if 1
1671   {
1672     switch (HighByte(PlayField16[*si]))
1673     {
1674       case 0xE:
1675       case 0xF:
1676         subSoundFX(*si, fiZonk, actPushing);
1677         break;
1678
1679       case 0x28:
1680       case 0x29:
1681         subSoundFX(*si, fiOrangeDisk, actPushing);
1682         break;
1683
1684       case 0x24:
1685       case 0x25:
1686       case 0x26:
1687       case 0x27:
1688         subSoundFX(*si, fiYellowDisk, actPushing);
1689         break;
1690
1691       default:
1692         break;
1693     }
1694   }
1695 #else
1696     subSoundFXPush();
1697 #endif
1698
1699   bl = HighByte(PlayField16[*si]);
1700   if (bl == 0xE)        // Push Zonk to left
1701     goto loc_g_6F7E;
1702
1703   if (bl == 0xF)        // Push Zonk to right
1704     goto loc_g_6FBC;
1705
1706   if (bl == 0x28)       // Push orange disk to left
1707     goto loc_g_6FFA;
1708
1709   if (bl == 0x29)       // Push orange disk to right
1710     goto loc_g_7038;
1711
1712   if (bl == 0x24)       // Push yellow disk up
1713     goto loc_g_7076;
1714
1715   if (bl == 0x25)       // Push yellow disk to left
1716     goto loc_g_70B4;
1717
1718   if (bl == 0x27)       // Push yellow disk down
1719     goto loc_g_70F2;
1720
1721   if (bl == 0x26)       // Push yellow disk to right
1722     goto loc_g_7130;
1723
1724   if (bl == 0x2A)       // Red disk release timer
1725     goto loc_g_716E;
1726
1727   return;
1728
1729   // ==========================================================================
1730   // Paint frame of MOVING.DAT sequence
1731   // ==========================================================================
1732
1733 loc_g_6C8F:
1734
1735 #if 1
1736   if (SeqPos <= 0)
1737     dx1SequenceLength = getSequenceLength(dx1);
1738 #endif
1739
1740   if (SplitMoveFlag == 0)
1741   {
1742     // ++++++++++++++++++++++++++
1743     // Begin of normal movement
1744 #if 1
1745     MurphyScreenXPos = MurphyScreenXPos + MurphyDX * MurphyZoomFactor;
1746     MurphyScreenYPos = MurphyScreenYPos + MurphyDY * MurphyZoomFactor;
1747 #else
1748     MurphyScreenXPos = MurphyScreenXPos + MurphyDX;
1749     MurphyScreenYPos = MurphyScreenYPos + MurphyDY;
1750 #endif
1751
1752
1753 #if 0
1754   printf("::: %04d [%03ld, %02d] ----------> %s [%d] [%d, %d] [%d, %d] [%d]\n",
1755          TimerVar,
1756          DemoOffset - DemoPointer, DemoKeyRepeatCounter,
1757          (DemoKeyCode == keyNone        ? "(none)"              :
1758           DemoKeyCode == keyLeft        ? "left"                :
1759           DemoKeyCode == keyRight       ? "right"               :
1760           DemoKeyCode == keyUp          ? "up"                  :
1761           DemoKeyCode == keyDown        ? "down"                :
1762           DemoKeyCode == keySpace       ? "space"               :
1763           DemoKeyCode == keySpaceLeft   ? "space + left"        :
1764           DemoKeyCode == keySpaceRight  ? "space + right"       :
1765           DemoKeyCode == keySpaceUp     ? "space + up"          :
1766           DemoKeyCode == keySpaceDown   ? "space + down"        : "(unknown)"),
1767          DemoKeyCode,
1768          MurphyScreenXPos, MurphyScreenYPos,
1769          MurphyPosIndex % 60, MurphyPosIndex / 60,
1770          ClearPos);
1771 #endif
1772
1773 #if 0
1774   Delay(500);
1775 #endif
1776
1777 #if 1
1778     if (!(ClearPos < 0)) // clear field that murphy is leaving
1779       subCopyImageToScreen(ClearPos, aniSpace);
1780 #else
1781     if (! ClearPos < 0) // clear field that murphy is leaving
1782       subCopyFieldToScreen(ClearPos, 0);
1783 #endif
1784
1785 #if 0
1786     printf("::: ---------------> %d, %d [%d, %d]\n",
1787            MurphyScreenXPos, MurphyScreenYPos, MurphyDX, MurphyDY);
1788 #endif
1789
1790 #if 0
1791     // !!! special two-tile animation currently not used !!!
1792     if (dx2 == fiInfotron) // special case of infotron moving left or right
1793     {
1794       tDeltaX = 0;
1795       tDeltaY = 0;
1796     }
1797     else
1798 #endif
1799     {
1800       tDeltaX = MurphyDX * LocalStretch * (SeqPos + 1);
1801       tDeltaY = MurphyDY * LocalStretch * (SeqPos + 1);
1802     }
1803
1804     X = GetStretchX(dxPos) + tDeltaX;
1805     Y = GetStretchY(dxPos) + tDeltaY;
1806     Tmp = (SeqPos < 0 ? 0 : SeqPos); // 9StepBugFix!(red disk move right)
1807
1808 #if 1
1809     if (isSnappingSequence(dx1) && SeqPos == dx1SequenceLength - 1)
1810       dx1 = aniSpace;
1811 #endif
1812
1813 #if 1
1814     StretchedSprites.BltImg(X, Y, dx1, Tmp);
1815     GfxGraphic[GetX(*si)][GetY(*si)] = -1;      // (Murphy's position)
1816     GfxGraphic[GetX(dxPos)][GetY(dxPos)] = -1;  // (snapping position)
1817     // printf("::: Tmp: %d\n", Tmp);
1818 #else
1819     StretchedSprites.BltEx(X, Y, dx[Tmp]);
1820 #endif
1821
1822 #if 1
1823     if (!(dx2 < 0))
1824 #else
1825     if (! dx2 < 0)
1826 #endif
1827     {
1828       tPos = dxPos + dx2Step;
1829       X = GetStretchX(tPos);
1830       Y = GetStretchY(tPos);
1831 #if 0
1832     // !!! special two-tile animation currently not used !!!
1833       if (dx2 == fiInfotron) // special case of infotron moving left or right
1834       {
1835         StretchedSprites.BltEx(X, Y, dx[SeqPos] + dx2Step);
1836       }
1837       else // pushing something
1838 #endif
1839       {
1840 #if 1
1841         // (SeqPos iterates from 0 to 7 while pushing)
1842         StretchedSprites.BltImg(X + tDeltaX, Y + tDeltaY, dx2, SeqPos);
1843         // printf("::: SeqPos: %d\n", SeqPos);
1844 #else
1845         StretchedSprites.BltEx(X + tDeltaX, Y + tDeltaY, dx2);
1846 #endif
1847       }
1848     }
1849
1850     // End of normal movement
1851     // ------------------------
1852   }
1853   else
1854   {
1855     // ++++++++++++++++++++++++++++++++
1856     // Begin of split movement (port)
1857 #if 1
1858     MurphyScreenXPos = MurphyScreenXPos + 2 * MurphyDX * MurphyZoomFactor;
1859     MurphyScreenYPos = MurphyScreenYPos + 2 * MurphyDY * MurphyZoomFactor;
1860 #else
1861     MurphyScreenXPos = MurphyScreenXPos + 2 * MurphyDX;
1862     MurphyScreenYPos = MurphyScreenYPos + 2 * MurphyDY;
1863 #endif
1864     subCopyImageToScreen(ClearPos, aniSpace); // clear the field that murphy leaves
1865     tDeltaX = MurphyDX * LocalStretch * (SeqPos + 1);
1866     tDeltaY = MurphyDY * LocalStretch * (SeqPos + 1);
1867     X = GetStretchX(dxPos) + tDeltaX;
1868     Y = GetStretchY(dxPos) + tDeltaY;
1869 #if 1
1870     StretchedSprites.BltImg(X, Y, dx1, SeqPos); // plot first murphy
1871 #else
1872     StretchedSprites.BltEx(X, Y, dx[SeqPos]); // plot first murphy
1873 #endif
1874     tPos = dxPos + dx2Step;
1875     X = GetStretchX(tPos);
1876     Y = GetStretchY(tPos);
1877 #if 1
1878     StretchedSprites.BltImg(X + tDeltaX, Y + tDeltaY, dx1, SeqPos); // plot second murphy
1879     StretchedSprites.BltImg(X, Y, fiGraphic[LowByte(PlayField16[tPos])], 0); // replot the port on top
1880 #else
1881     StretchedSprites.BltEx(X + tDeltaX, Y + tDeltaY, dx[SeqPos]); // plot second murphy
1882     StretchedSprites.BltEx(X, Y, LowByte(PlayField16[tPos])); // replot the port on top
1883 #endif
1884     // End of split movement (port)
1885     // ------------------------------
1886   } // loc_g_6D1E:'loc_g_6D28:
1887
1888   SeqPos = SeqPos + 1;
1889 #if 1
1890   if (SeqPos < dx1SequenceLength)
1891     return;
1892 #else
1893   if (dx[SeqPos] > -1)
1894     return;
1895 #endif
1896
1897   // Follow-up after movement completed     'loc_g_6D35:
1898   MurphyXPos = MurphyXPos + MurphyDX;
1899   MurphyYPos = MurphyYPos + MurphyDY;
1900   bl = HighByte(PlayField16[*si]);  // animation phase
1901   MovHighByte(&PlayField16[*si], 0);
1902
1903   if (bl == 0x1)    // space, moving up
1904     goto loc_g_6EC8;
1905
1906   if (bl == 0x2)    // space, moving left
1907     goto loc_g_6EE6;
1908
1909   if (bl == 0x3)    // space, moving down
1910     goto loc_g_6F04;
1911
1912   if (bl == 0x4)    // space, moving right
1913     goto loc_g_71C4;
1914
1915   if (bl == 0x5)    // base , moving up
1916     goto loc_g_6EC8;
1917
1918   if (bl == 0x6)    // base , moving left -> 6 is not used, value is set to 2 instead of 6!
1919     goto loc_g_6EE6;
1920
1921   if (bl == 0x7)    // base , moving down
1922     goto loc_g_6F04;
1923
1924   if (bl == 0x8)    // base , moving right
1925     goto loc_g_71C4;
1926
1927   if (bl == 0x9)    // infotron, moving up
1928     goto loc_g_6EBA;
1929
1930   if (bl == 0xA)      // infotron, moving left
1931     goto loc_g_6ED8;
1932
1933   if (bl == 0xB)    // infotron, moving down
1934     goto loc_g_6EF6;
1935
1936   if (bl == 0xC)      // infotron, moving right
1937     goto loc_g_71B6;
1938
1939   if (bl == 0xD)      // exit
1940     goto loc_g_6F77;
1941
1942   if (bl == 0xE)      // zonk, pushing left
1943     goto loc_g_6F18;
1944
1945   if (bl == 0xF)      // zonk, pushing right
1946     goto loc_g_6F3B;
1947
1948   if (bl == 0x10)   // base , touching up
1949     goto loc_g_71E2;
1950
1951   if (bl == 0x11)   // base , touching left
1952     goto loc_g_71FE;
1953
1954   if (bl == 0x12)   // base , touching down
1955     goto loc_g_721A;
1956
1957   if (bl == 0x13)   // base , touching right
1958     goto loc_g_7236;
1959
1960   if (bl == 0x14)   // infotron touching up
1961     goto loc_g_71D4;
1962
1963   if (bl == 0x15)   // infotron touching left
1964     goto loc_g_71F0;
1965
1966   if (bl == 0x16)   // infotron touching down
1967     goto loc_g_720C;
1968
1969   if (bl == 0x17)   // infotron touching right
1970     goto loc_g_7228;
1971
1972   if (bl == 0x18)     // port up
1973     goto loc_g_7244;
1974
1975   if (bl == 0x19)     // port left
1976     goto loc_g_7272;
1977
1978   if (bl == 0x1A)     // port down
1979     goto loc_g_729F;
1980
1981   if (bl == 0x1B)     // port right
1982     goto loc_g_72CD;
1983
1984   if (bl == 0x1C)   // red disk, moving up
1985     goto loc_g_72FA;
1986
1987   if (bl == 0x1D)   // red disk, moving left
1988     goto loc_g_7318;
1989
1990   if (bl == 0x1E)   // red disk, moving down
1991     goto loc_g_7333;
1992
1993   if (bl == 0x1F)   // red disk, moving right -> 9-Step-Bug!
1994     goto loc_g_7351;
1995
1996   if (bl == 0x20)   // red disk, touching up
1997     goto loc_g_736C;
1998
1999   if (bl == 0x21)   // red disk, touching left
2000     goto loc_g_7381;
2001
2002   if (bl == 0x22)   // red disk, touching down
2003     goto loc_g_7396;
2004
2005   if (bl == 0x23)   // red disk, touching right
2006     goto loc_g_73AB;
2007
2008   if (bl == 0x24)     // yellow disk, pushing up
2009     goto loc_g_73C0;
2010
2011   if (bl == 0x25)     // yellow disk, pushing left
2012     goto loc_g_73DD;
2013
2014   if (bl == 0x26)     // yellow disk, pushing right -> order of "down" exchanged with "right"!
2015     goto loc_g_7417;
2016
2017   if (bl == 0x27)     // yellow disk, pushing down  -> order of "down" exchanged with "right"!
2018     goto loc_g_73FA;
2019
2020   if (bl == 0x28)     // orange disk, pushing left
2021     goto loc_g_7434;
2022
2023   if (bl == 0x29)     // orange disk, pushing right
2024     goto loc_g_7451;
2025
2026   if (bl == 0x2A)   // red disk, release
2027     goto loc_g_747F;
2028
2029   ExitToMenuFlag = 1;
2030
2031   return;
2032
2033   // ==========================================================================
2034   //                       infotron, moving up
2035   // ==========================================================================
2036
2037 loc_g_6EBA:
2038   if (0 < LowByte(InfotronsNeeded))
2039     InfotronsNeeded = InfotronsNeeded - 1;
2040
2041 loc_g_6EC8: // space, base
2042   PlayField16[*si] = fiMurphy;
2043   subAdjustZonksInfotronsAboveMurphy(*si + FieldWidth);
2044
2045   return;
2046
2047   // ==========================================================================
2048   //                       infotron, moving left
2049   // ==========================================================================
2050
2051 loc_g_6ED8:
2052   if (0 < LowByte(InfotronsNeeded))
2053     InfotronsNeeded = InfotronsNeeded - 1;
2054
2055 loc_g_6EE6: // space, base
2056   PlayField16[*si] = fiMurphy;
2057   subAdjustZonksInfotronsAboveMurphy(*si + 1);
2058
2059   return;
2060
2061   // ==========================================================================
2062   //                       infotron, moving down
2063   // ==========================================================================
2064
2065 loc_g_6EF6:
2066   if (0 < LowByte(InfotronsNeeded))
2067     InfotronsNeeded = InfotronsNeeded - 1;
2068
2069 loc_g_6F04: // space, base
2070   if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion)
2071     PlayField16[*si - FieldWidth] = 0;
2072
2073   PlayField16[*si] = fiMurphy;
2074
2075   return;
2076
2077   // ==========================================================================
2078   //                       infotron, moving right
2079   // ==========================================================================
2080
2081 loc_g_71B6:
2082   if (0 < LowByte(InfotronsNeeded))
2083     InfotronsNeeded = InfotronsNeeded - 1;
2084
2085 loc_g_71C4: // space, base
2086   subAdjustZonksInfotronsAboveMurphy(*si - 1);
2087   PlayField16[*si] = fiMurphy;
2088
2089   return;
2090
2091   // ==========================================================================
2092   //                       infotron, touching up
2093   // ==========================================================================
2094
2095 loc_g_71D4:
2096   if (0 < LowByte(InfotronsNeeded))
2097     InfotronsNeeded = InfotronsNeeded - 1;
2098
2099 loc_g_71E2: // base
2100   if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion)
2101     PlayField16[*si - FieldWidth] = 0;
2102
2103   return;
2104
2105   // ==========================================================================
2106   //                       infotron, touching left
2107   // ==========================================================================
2108
2109 loc_g_71F0:
2110   if (0 < LowByte(InfotronsNeeded))
2111     InfotronsNeeded = InfotronsNeeded - 1;
2112
2113 loc_g_71FE: // base
2114   if (LowByte(PlayField16[*si - 1]) != fiExplosion)
2115     PlayField16[*si - 1] = 0;
2116
2117   return;
2118
2119   // ==========================================================================
2120   //                       infotron, touching down
2121   // ==========================================================================
2122
2123 loc_g_720C:
2124   if (0 < LowByte(InfotronsNeeded))
2125     InfotronsNeeded = InfotronsNeeded - 1;
2126
2127 loc_g_721A: // base
2128   if (LowByte(PlayField16[*si + FieldWidth]) != fiExplosion)
2129     PlayField16[*si + FieldWidth] = 0;
2130
2131   return;
2132
2133   // ==========================================================================
2134   //                       infotron, touching right
2135   // ==========================================================================
2136
2137 loc_g_7228:
2138   if (0 < LowByte(InfotronsNeeded))
2139     InfotronsNeeded = InfotronsNeeded - 1;
2140
2141 loc_g_7236: // base
2142   if (LowByte(PlayField16[*si + 1]) != fiExplosion)
2143     PlayField16[*si + 1] = 0;
2144
2145   return;
2146
2147   // ==========================================================================
2148   //                       zonk, pushing left
2149   // ==========================================================================
2150
2151 loc_g_6F18:
2152   if (LowByte(PlayField16[*si]) != fiExplosion)
2153     PlayField16[*si] = 0;
2154
2155   PlayField16[*si - 1] = fiMurphy;
2156   PlayField16[*si - 2] = fiZonk;
2157   subExplodeSnikSnaksBelow(*si - 2);
2158   *si = *si - 1;
2159
2160   return;
2161
2162   // ==========================================================================
2163   //                       zonk, pushing right
2164   // ==========================================================================
2165
2166 loc_g_6F3B:
2167   if (LowByte(PlayField16[*si]) != fiExplosion)
2168     PlayField16[*si] = 0;
2169
2170   PlayField16[*si + 1] = fiMurphy;
2171   PlayField16[*si + 2] = fiZonk;
2172   subExplodeSnikSnaksBelow(*si + 2);
2173   *si = *si + 1;
2174
2175   return;
2176
2177   // ==========================================================================
2178   //                       exit
2179   // ==========================================================================
2180
2181 loc_g_6F77:
2182   ExitToMenuFlag = 1;
2183
2184 #if 1
2185   PlayField16[*si] = fiSpace;   // remove Murphy from playfield after exiting
2186 #endif
2187
2188   return;
2189
2190   // ==========================================================================
2191   //               Push Zonk from right to left
2192   // ==========================================================================
2193
2194 loc_g_6F7E:
2195   if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiZonk)
2196     return;
2197
2198   PlayField16[*si] = fiMurphy; // else restore - no more zonk pushing!
2199   PlayField16[*si - 1] = fiZonk;
2200   if (LowByte(PlayField16[*si - 2]) != fiExplosion)
2201     PlayField16[*si - 2] = 0;
2202
2203   subCopyImageToScreen(*si, aniMurphy);
2204
2205   return;
2206
2207   // ==========================================================================
2208   //                       Push Zonk from left to right
2209   // ==========================================================================
2210
2211 loc_g_6FBC:
2212   if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiZonk)
2213     return;
2214
2215   PlayField16[*si] = fiMurphy; // else restore - no more zonk pushing!
2216   PlayField16[*si + 1] = fiZonk;
2217   if (LowByte(PlayField16[*si + 2]) != fiExplosion)
2218     PlayField16[*si + 2] = 0;
2219
2220   subCopyImageToScreen(*si, aniMurphy);
2221
2222   return;
2223
2224   // ==========================================================================
2225   //               Push orange disk from right to left
2226   // ==========================================================================
2227
2228 loc_g_6FFA:
2229   if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiOrangeDisk)
2230     return;
2231
2232   PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2233   PlayField16[*si - 1] = fiOrangeDisk;
2234   if (LowByte(PlayField16[*si - 2]) != fiExplosion)
2235     PlayField16[*si - 2] = 0;
2236
2237   subCopyImageToScreen(*si, aniMurphy);
2238
2239   return;
2240
2241   // ==========================================================================
2242   //               Push orange disk from left to right
2243   // ==========================================================================
2244
2245 loc_g_7038:
2246   if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiOrangeDisk)
2247     return;
2248
2249   PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2250   PlayField16[*si + 1] = fiOrangeDisk;
2251   if (LowByte(PlayField16[*si + 2]) != fiExplosion)
2252     PlayField16[*si + 2] = 0;
2253
2254   subCopyImageToScreen(*si, aniMurphy);
2255
2256   return;
2257
2258   // ==========================================================================
2259   //               Push yellow disk from down to up
2260   // ==========================================================================
2261
2262 loc_g_7076:
2263   if (DemoKeyCode == keyUp && PlayField16[*si - FieldWidth] == fiYellowDisk)
2264     return;
2265
2266   PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2267   PlayField16[*si - FieldWidth] = fiYellowDisk;
2268   if (LowByte(PlayField16[*si - 2 * FieldWidth]) != fiExplosion)
2269     PlayField16[*si - 2 * FieldWidth] = 0;
2270
2271   subCopyImageToScreen(*si, aniMurphy);
2272
2273   return;
2274
2275   // ==========================================================================
2276   //               Push yellow disk from right to left
2277   // ==========================================================================
2278
2279 loc_g_70B4:
2280   if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiYellowDisk)
2281     return;
2282
2283   PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2284   PlayField16[*si - 1] = fiYellowDisk;
2285   if (LowByte(PlayField16[*si - 2]) != fiExplosion)
2286     PlayField16[*si - 2] = 0;
2287
2288   subCopyImageToScreen(*si, aniMurphy);
2289
2290   return;
2291
2292   // ==========================================================================
2293   //               Push yellow disk from up to down
2294   // ==========================================================================
2295
2296 loc_g_70F2:
2297   if (DemoKeyCode == keyDown && PlayField16[*si + FieldWidth] == fiYellowDisk)
2298     return;
2299
2300   PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2301   PlayField16[*si + FieldWidth] = fiYellowDisk;
2302   if (LowByte(PlayField16[*si + 2 * FieldWidth]) != fiExplosion)
2303     PlayField16[*si + 2 * FieldWidth] = 0;
2304
2305   subCopyImageToScreen(*si, aniMurphy);
2306
2307   return;
2308
2309   // ==========================================================================
2310   //               Push yellow disk from left to right
2311   // ==========================================================================
2312
2313 loc_g_7130:
2314   if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiYellowDisk)
2315     return;
2316
2317   PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2318   PlayField16[*si + 1] = fiYellowDisk;
2319   if (LowByte(PlayField16[*si + 2]) != fiExplosion)
2320     PlayField16[*si + 2] = 0;
2321
2322   subCopyImageToScreen(*si, aniMurphy);
2323
2324   return;
2325
2326   // ==========================================================================
2327   //               time red disk release (space)
2328   // ==========================================================================
2329
2330 loc_g_716E:
2331   if (DemoKeyCode != keySpace)
2332   {
2333     PlayField16[*si] = fiMurphy;
2334     subCopyImageToScreen(*si, aniMurphy);
2335     RedDiskReleasePhase = 0;
2336   }
2337   else if (MovingPictureSequencePhase == 0x20)
2338   {
2339 #if 1
2340     // anxious murphy, dropping red disk
2341     subCopyImageToScreen(*si, aniMurphyDropping);
2342 #else
2343     subCopyFieldToScreen(*si, 43);  // anxious murphy
2344 #endif
2345     RedDiskReleasePhase = 1;
2346   }
2347
2348   return;
2349
2350   // ==========================================================================
2351   // Special port down to up
2352   // ==========================================================================
2353
2354 loc_g_7244:
2355   if (LowByte(PlayField16[*si]) != fiExplosion)
2356     PlayField16[*si] = 0;
2357
2358   PlayField16[*si - 2 * FieldWidth] = fiMurphy;
2359   SplitMoveFlag = 0;
2360   *si = *si - FieldWidth;
2361   if (HighByte(PlayField16[*si]) == 1)
2362     subSpPortTest(*si);
2363
2364   *si = *si - FieldWidth;
2365
2366   return;
2367
2368   // ==========================================================================
2369   // Special port right to left
2370   // ==========================================================================
2371
2372 loc_g_7272:
2373   if (LowByte(PlayField16[*si]) != fiExplosion)
2374     PlayField16[*si] = 0;
2375
2376   PlayField16[*si - 2] = fiMurphy;
2377   SplitMoveFlag = 0;
2378   *si = *si - 1;
2379   if (HighByte(PlayField16[*si]) == 1)
2380     subSpPortTest(*si);
2381
2382   *si = *si - 1;
2383
2384   return;
2385
2386   // ==========================================================================
2387   // Special port up to down
2388   // ==========================================================================
2389
2390 loc_g_729F:
2391   if (LowByte(PlayField16[*si]) != fiExplosion)
2392     PlayField16[*si] = 0;
2393
2394   PlayField16[*si + 2 * FieldWidth] = fiMurphy;
2395   SplitMoveFlag = 0;
2396   *si = *si + FieldWidth;
2397   if (HighByte(PlayField16[*si]) == 1)
2398     subSpPortTest(*si);
2399
2400   *si = *si + FieldWidth;
2401
2402   return;
2403
2404   // ==========================================================================
2405   // Special port left to right
2406   // ==========================================================================
2407
2408 loc_g_72CD:
2409   if (LowByte(PlayField16[*si]) != fiExplosion)
2410     PlayField16[*si] = 0;
2411
2412   PlayField16[*si + 2] = fiMurphy;
2413   SplitMoveFlag = 0;
2414   *si = *si + 1;
2415   if (HighByte(PlayField16[*si]) == 1)
2416     subSpPortTest(*si);
2417
2418   *si = *si + 1;
2419
2420   return;
2421
2422   // ==========================================================================
2423   // Move Red Disk up
2424   // ==========================================================================
2425
2426 loc_g_72FA:
2427   if (LowByte(PlayField16[*si]) != fiExplosion)
2428     PlayField16[*si] = 0;
2429
2430   *si = *si - FieldWidth;
2431   PlayField16[*si] = fiMurphy;
2432   subEatRedDisk(*si); // inc+show Murphy's red disks
2433
2434   return;
2435
2436   // ==========================================================================
2437   // Move Red Disk left
2438   // ==========================================================================
2439
2440 loc_g_7318:
2441   if (LowByte(PlayField16[*si + 1]) != fiExplosion)
2442     PlayField16[*si + 1] = 0;
2443
2444   PlayField16[*si] = fiMurphy;
2445   subEatRedDisk(*si); // inc+show Murphy's red disks
2446
2447   return;
2448
2449   // ==========================================================================
2450   // Move Red Disk down
2451   // ==========================================================================
2452
2453 loc_g_7333:
2454   if (LowByte(PlayField16[*si]) != fiExplosion)
2455     PlayField16[*si] = 0;
2456
2457   *si = *si + FieldWidth;
2458   PlayField16[*si] = fiMurphy;
2459   subEatRedDisk(*si); // inc+show Murphy's red disks
2460
2461   return;
2462
2463   // ==========================================================================
2464   // Move Red Disk right
2465   // ==========================================================================
2466
2467 loc_g_7351:
2468   if (LowByte(PlayField16[*si - 1]) != fiExplosion)
2469     PlayField16[*si - 1] = 0;
2470
2471   PlayField16[*si] = fiMurphy;
2472   subEatRedDisk(*si); // inc+show Murphy's red disks
2473
2474   return;
2475
2476   // ==========================================================================
2477   // Eat Red Disk up
2478   // ==========================================================================
2479
2480 loc_g_736C:
2481   if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion)
2482     PlayField16[*si - FieldWidth] = 0;
2483
2484   subEatRedDisk(*si - FieldWidth); // inc+show Murphy's red disks
2485
2486   return;
2487
2488   // ==========================================================================
2489   // Eat Red Disk left
2490   // ==========================================================================
2491
2492 loc_g_7381:
2493   if (LowByte(PlayField16[*si - 1]) != fiExplosion)
2494     PlayField16[*si - 1] = 0;
2495
2496   subEatRedDisk(*si - 1); // inc+show Murphy's red disks
2497
2498   return;
2499
2500   // ==========================================================================
2501   // Eat Red Disk down
2502   // ==========================================================================
2503
2504 loc_g_7396:
2505   if (LowByte(PlayField16[*si + FieldWidth]) != fiExplosion)
2506     PlayField16[*si + FieldWidth] = 0;
2507
2508   subEatRedDisk(*si + FieldWidth); // inc+show Murphy's red disks
2509
2510   return;
2511
2512   // ==========================================================================
2513   // Eat Red Disk right
2514   // ==========================================================================
2515
2516 loc_g_73AB:
2517   if (LowByte(PlayField16[*si + 1]) != fiExplosion)
2518     PlayField16[*si + 1] = 0;
2519
2520   subEatRedDisk(*si + 1); // inc+show Murphy's red disks
2521
2522   return;
2523
2524   // ==========================================================================
2525   //                       yellow disk, pushing up
2526   // ==========================================================================
2527
2528 loc_g_73C0:
2529   if (LowByte(PlayField16[*si]) != fiExplosion)
2530     PlayField16[*si] = 0;
2531
2532   *si = *si - FieldWidth;
2533   PlayField16[*si] = fiMurphy;
2534   PlayField16[*si - FieldWidth] = fiYellowDisk;
2535
2536   return;
2537
2538   // ==========================================================================
2539   //                       yellow disk, pushing left
2540   // ==========================================================================
2541
2542 loc_g_73DD:
2543   if (LowByte(PlayField16[*si]) != fiExplosion)
2544     PlayField16[*si] = 0;
2545
2546   *si = *si - 1;
2547   PlayField16[*si] = fiMurphy;
2548   PlayField16[*si - 1] = fiYellowDisk;
2549
2550   return;
2551
2552   // ==========================================================================
2553   //                       yellow disk, pushing down
2554   // ==========================================================================
2555
2556 loc_g_73FA:
2557   if (LowByte(PlayField16[*si]) != fiExplosion)
2558     PlayField16[*si] = 0;
2559
2560   *si = *si + FieldWidth;
2561   PlayField16[*si] = fiMurphy;
2562   PlayField16[*si + FieldWidth] = fiYellowDisk;
2563
2564   return;
2565
2566   // ==========================================================================
2567   //                       yellow disk pushing right
2568   // ==========================================================================
2569
2570 loc_g_7417:
2571   if (LowByte(PlayField16[*si]) != fiExplosion)
2572     PlayField16[*si] = 0;
2573
2574   *si = *si + 1;
2575   PlayField16[*si] = fiMurphy;
2576   PlayField16[*si + 1] = fiYellowDisk;
2577
2578   return;
2579
2580   // ==========================================================================
2581   //                       orange disk, pushing left
2582   // ==========================================================================
2583
2584 loc_g_7434:
2585   if (LowByte(PlayField16[*si]) != fiExplosion)
2586     PlayField16[*si] = 0;
2587
2588   *si = *si - 1;
2589   PlayField16[*si] = fiMurphy;
2590   PlayField16[*si - 1] = fiOrangeDisk;
2591
2592   return;
2593
2594   // ==========================================================================
2595   //                       orange disk, pushing right
2596   // ==========================================================================
2597
2598 loc_g_7451:
2599   if (LowByte(PlayField16[*si]) != fiExplosion)
2600     PlayField16[*si] = 0;
2601
2602   *si = *si + 1;
2603   PlayField16[*si] = fiMurphy;
2604   PlayField16[*si + 1] = fiOrangeDisk;
2605   if (PlayField16[*si + FieldWidth + 1] == 0) // make it fall down if below is empty
2606   {
2607     MovHighByte(&PlayField16[*si + 1], 0x20);
2608     MovHighByte(&PlayField16[*si + FieldWidth + 1], fiOrangeDisk);
2609   }
2610
2611   return;
2612
2613   // ==========================================================================
2614   //                     Release a red disk
2615   // ==========================================================================
2616
2617 loc_g_747F:
2618   PlayField16[*si] = fiMurphy;
2619   RedDiskReleasePhase = 2;
2620   RedDiskCount = RedDiskCount - 1;
2621
2622 #if 1
2623   subSoundFX(*si, fiRedDisk, actDropping);
2624 #else
2625   subSoundFXPush();                 // Sound effects
2626 #endif
2627 } // subAnimateMurphy
2628
2629 // ==========================================================================
2630 //                              SUBROUTINE
2631 // ==========================================================================
2632 void subExplodeSnikSnaksBelow(int si)
2633 {
2634   int ax;
2635
2636   ax = LowByte(PlayField16[si + FieldWidth]);
2637   if (ax == 0x11 || ax == 0xBB)
2638     ExplodeFieldSP(si + FieldWidth);
2639 } // subExplodeSnikSnaksBelow
2640
2641 // ==========================================================================
2642 //                              SUBROUTINE
2643 // Does pushing against an object kill Murphy?
2644 // ==========================================================================
2645 static boolean subMoveKillsMurphy(int si, int ax, int bl)
2646 {
2647   static boolean subMoveKillsMurphy;
2648
2649   int al, ah;
2650
2651   al = LowByte(ax);
2652   ah = HighByte(ax);
2653   if (ax == 0xFFFF || ax == 0xAAAA || ah == 0)
2654     goto loc_g_752E;
2655
2656   if (al == fiZonk)
2657     goto loc_g_74E7;
2658
2659   if (al == fiExplosion)
2660     goto loc_g_7530;
2661
2662   if (fiOrangeDisk <= al && al <= fiPortUp)
2663     goto loc_g_752E;
2664
2665   ExplodeFieldSP(si);                 // Explode
2666   subMoveKillsMurphy = True;
2667   return subMoveKillsMurphy;
2668
2669 loc_g_74E7: // zonk
2670   if (bl == keyLeft)
2671     goto loc_g_74F6;
2672
2673   if (bl == keyRight)
2674     goto loc_g_7512;
2675
2676   ExplodeFieldSP(si);                 // Explode
2677   subMoveKillsMurphy = True;
2678   return subMoveKillsMurphy;
2679
2680 loc_g_74F6: // zonk left
2681   ah = ah & 0xF0;
2682   if (! (ah == 0x20 || ah == 0x40 || ah == 0x50 || ah == 0x70))
2683     ExplodeFieldSP(si);
2684
2685   subMoveKillsMurphy = True;                           // Set carry flag
2686   return subMoveKillsMurphy;
2687
2688 loc_g_7512: // zonk right
2689   ah = ah & 0xF0;
2690   if (! (ah == 0x30 || ah == 0x40 || ah == 0x60 || ah == 0x70))
2691     ExplodeFieldSP(si);
2692
2693 loc_g_752E: // Marked fields and Ports
2694   subMoveKillsMurphy = True;                           // Set carry flag
2695   return subMoveKillsMurphy;
2696
2697 loc_g_7530: // explosion
2698   if ((ah & 0x80) != 0)
2699     goto loc_g_753A;
2700
2701   if (ah >= 4)
2702     goto loc_g_753F;
2703
2704 loc_g_753A:
2705   ExplodeFieldSP(si);                 // Explode
2706   subMoveKillsMurphy = True;                           // Set carry flag
2707   return subMoveKillsMurphy;
2708
2709 loc_g_753F:
2710   PlayField16[si] = 0;
2711   subMoveKillsMurphy = False;
2712
2713   return subMoveKillsMurphy;
2714 } // subMoveKillsMurphy
2715
2716 // ==========================================================================
2717 //                              SUBROUTINE
2718 // Test If si 's a special (grav) port and If so Then fetch new values (see below)
2719 // change conditions to port specs
2720 // The 10-port data base is at data_h_0D28, 10 entries of 6 bytes each:
2721 // (hi),(lo),(gravity),(freeze zonks),(freeze enemies),(unused)
2722 // ==========================================================================
2723 int subSpPortTest(int si)
2724 {
2725   int subSpPortTest;
2726
2727   int i, cx, bx;
2728
2729 #if 1
2730   cx = LInfo.SpecialPortCount; // number of special ports
2731
2732   for (i = 0; i < cx; i++)
2733   {
2734 #if 1
2735     /* this assumes that PortLocation is stored as big endian */
2736     bx = LInfo.SpecialPort[i].PortLocation;
2737 #else
2738     /* this assumes that PortLocation is stored as little endian */
2739     bx = HighByte(LInfo.SpecialPort[i].PortLocation);
2740     MovHighByte(&bx, LowByte(LInfo.SpecialPort[i].PortLocation));
2741 #endif
2742
2743     if (bx / 2 == si)
2744     {
2745       GravityFlag = LInfo.SpecialPort[i].Gravity;
2746       FreezeZonks = LInfo.SpecialPort[i].FreezeZonks;
2747       SnikSnaksElectronsFrozen = LInfo.SpecialPort[i].FreezeEnemies;
2748
2749       // RandomTime = RandomTime Xor RandomSeed 'is RandomTime used at all? no!
2750
2751       break;
2752     }
2753   }
2754
2755 #else
2756
2757   cx = LInfo.SpecialPortCount; // number of special ports
2758   for (i = 1; i <= cx; i++)
2759   {
2760     {
2761       bx = HighByte(LInfo.SpecialPort[i].PortLocation);
2762       MovHighByte(&bx, LowByte(LInfo.SpecialPort[i].PortLocation));
2763       if (bx / 2 == si)
2764       {
2765         GravityFlag = LInfo.SpecialPort[i].Gravity;
2766         FreezeZonks = LInfo.SpecialPort[i].FreezeZonks;
2767         SnikSnaksElectronsFrozen = LInfo.SpecialPort[i].FreezeEnemies;
2768         //        RandomTime = RandomTime Xor RandomSeed 'is RandomTime used at all? no!
2769         i = cx + 1;
2770       }
2771     }
2772   }
2773 #endif
2774
2775   return subSpPortTest;
2776 } // subSpPortTest
2777
2778 #if 0
2779
2780 void subCopyFieldToScreen(int si, int fi)
2781 {
2782   int X, Y;
2783
2784   // +++++++++++++++++++++++++++++++++++++++++
2785   X = GetStretchX(si);
2786   Y = GetStretchY(si);
2787   StretchedSprites.BltEx(X, Y, fi);
2788   // +++++++++++++++++++++++++++++++++++++++++
2789 }
2790
2791 #endif
2792
2793 void subCopyAnimToScreen(int si, int graphic, int sync_frame)
2794 {
2795   int X, Y;
2796
2797   // +++++++++++++++++++++++++++++++++++++++++
2798   X = GetStretchX(si);
2799   Y = GetStretchY(si);
2800   StretchedSprites.BltImg(X, Y, graphic, sync_frame);
2801   // +++++++++++++++++++++++++++++++++++++++++
2802 }
2803
2804 void subCopyImageToScreen(int si, int graphic)
2805 {
2806   subCopyAnimToScreen(si, graphic, 0);
2807 }
2808
2809 static void subEatRedDisk(int si)
2810 {
2811   if (AllowRedDiskCheat == 0)
2812   {
2813     if (RedDiskReleasePhase != 0)
2814     {
2815       if (RedDiskReleaseMurphyPos == si)
2816         return;
2817     }
2818   }
2819
2820   RedDiskCount = (RedDiskCount + 1) % 256;
2821 }
2822
2823 void subAdjustZonksInfotronsAboveMurphy(int si)
2824 {
2825   int ax;
2826
2827   if (LowByte(PlayField16[si]) != fiExplosion)
2828     PlayField16[si] = 0;
2829
2830   ax = PlayField16[si - FieldWidth];
2831   if (ax == 0 || ax == 0x9999)
2832     goto loc_g_15A8;
2833
2834   if (ax == fiZonk || ax == fiInfotron)
2835   {
2836     MovHighByte(&PlayField16[si - FieldWidth], 0x40); // make falling straigt down
2837   }
2838
2839   return;
2840
2841 loc_g_15A8: // empty above
2842   ax = PlayField16[si - FieldWidth - 1];
2843   if (ax == fiZonk || ax == fiInfotron)
2844     goto loc_g_15C5;
2845
2846 loc_g_15B6:
2847   ax = PlayField16[si - FieldWidth + 1];
2848   if (ax == fiZonk || ax == fiInfotron)
2849     goto loc_g_15E8;
2850
2851   return;
2852
2853 loc_g_15C5: // zonk/infotron above left
2854   ax = PlayField16[si - 1];
2855   if (! (ax == fiZonk || ax == fiInfotron || ax == fiRAM)) // continue testing right above
2856     goto loc_g_15B6;
2857
2858   MovHighByte(&PlayField16[si - FieldWidth - 1], 0x60); // make roll right
2859   PlayField16[si - FieldWidth] = 0x8888;
2860
2861   return;
2862
2863 loc_g_15E8: // zonk/infotron above right
2864   ax = PlayField16[si + 1];
2865   if (ax == fiZonk || ax == fiInfotron || ax == fiRAM)
2866   {
2867     MovHighByte(&PlayField16[si - FieldWidth + 1], 0x50); // make roll left
2868     PlayField16[si - FieldWidth] = 0x8888;
2869   }
2870 } // subAdjustZonksInfotronsAboveMurphy