1 // ----------------------------------------------------------------------------
3 // ----------------------------------------------------------------------------
8 static void subEatRedDisk(int si);
9 static boolean subMoveKillsMurphy(int si, int ax, int bl);
11 #define LocalStretch (2)
12 #define MurphyZoomFactor (ZoomFactor)
15 // Variables that hold information about the animation sequence
16 static int dx1 = 0; // image/animation token
17 static int dx2 = 0; // an additional image position of a second sprite, for instance: yellow disk if pushed
18 static int MurphyDX = 0, MurphyDY = 0; // murphys move steps
19 static int SeqPos = 0; // index into dx()
20 static int ClearPos = 0; // Position to clear before blitting sprites, none=-1
21 static int dxPos = 0; // field-position to draw dx(SeqPos)
22 static int dx2Step = 0; // position of dx2 relative to dx-position
23 static int dx1SequenceLength = 0;
26 void SaveEngineSnapshotValues_SP_Murphy(ListNode **buffers)
28 SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(dx1));
29 SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(dx2));
30 SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(MurphyDX));
31 SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(MurphyDY));
32 SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(SeqPos));
33 SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(ClearPos));
34 SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(dxPos));
35 SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(dx2Step));
36 SaveSnapshotBuffer(buffers, ARGS_ADDRESS_AND_SIZEOF(dx1SequenceLength));
40 // ==========================================================================
42 // Move Murphy in any direction
43 // ==========================================================================
45 void subAnimateMurphy(int *si)
47 int ax, al, bl, i, X, Y;
49 int tDeltaX, tDeltaY, tPos, Tmp;
51 ax = PlayField16[*si];
56 MurphyMoveCounter = 0; // We have no Murphy! Exit!
61 MurphyMoveCounter = 1; // We have a Murphy!
62 MurphyExplodePos = *si;
64 // (check if high byte of PlayField16 has stored movement information)
65 if (ax != fiMurphy) // yes--go proceed moving murphy?
66 goto locProceedMovingMurphy;
68 // FS: reset moving sequence variables
78 ScratchGravity = 0; // scratch gravity off
79 if (GravityFlag != 0) // Gravity? (1=gravity on)
81 bl = LowByte(PlayField16[*si - FieldWidth]); // check above
82 if (! (bl == fiPortUp ||
83 bl == fiPortUpAndDown ||
84 bl == fiPortAllDirections))
86 if (PlayField16[*si + FieldWidth] == 0) // gravity on and space below!
92 if (bl != 0) // a key was pressed!
93 goto locKeyPressed5FCF;
95 RedDiskReleaseFlag = 1;
96 if (ScratchGravity != 0) // gravity pulls & space below?'-> force Space up to down
102 // ------------------------------------------------------------------
103 // Murphy's YAWN & SLEEP sequence, counted down by YawnSleepCounter:
105 YawnSleepCounter = YawnSleepCounter + 1;
107 if (YawnSleepCounter < 16)
110 if (YawnSleepCounter < 2000)
113 // (default: single graphic, no animation)
114 subCopyAnimToScreen(*si, aniMurphy, YawnSleepCounter - 16);
119 if (YawnSleepCounter < 4000)
121 // yawn! and look depressed afterwards...
122 // (default: 12 animation frames with delay of 8)
123 subCopyAnimToScreen(*si, aniMurphyYawn, YawnSleepCounter - 2000);
128 if (YawnSleepCounter < 6400)
131 // (default: 12 animation frames with delay of 8)
132 subCopyAnimToScreen(*si, aniMurphyYawn, YawnSleepCounter - 4000);
137 // time1 = 6400 + 12 * 8; // (default: 6496 == 6400 + 12 * 8)
138 time1 = 6400 + 12 * 10;
140 if (YawnSleepCounter < time1)
142 // yawn again! - third time
143 // (default: 12 animation frames with delay of 8)
144 subCopyAnimToScreen(*si, aniMurphyYawn, YawnSleepCounter - 6400);
149 // time2 = 6496 + 3 * 64; // (default: 6688 == 6496 + 3 * 64)
150 time2 = 6496 + 3 * 100;
152 if (YawnSleepCounter > time2) // Murphy already went to sleep
155 if (PlayField16[*si - 1] == 0)
157 if (PlayField16[*si + 1] == 0)
159 // no sleep -- go back to "wait and start yawning" phase
160 YawnSleepCounter = 144;
166 // go to sleep (right side)
167 // (default: 3 animation frames with delay of 64)
168 subCopyAnimToScreen(*si, aniMurphySleepRight, YawnSleepCounter - time1);
174 // go to sleep (left side)
175 // (default: 3 animation frames with delay of 64)
176 subCopyAnimToScreen(*si, aniMurphySleepLeft, YawnSleepCounter - time1);
180 // end of YAWN-SLEEP-Sequence
182 // ------------------------------------------------------------------
183 // ==========================================================================
184 // (Direct Jump) a key was pressed
185 // ==========================================================================
188 if (ScratchGravity == 0)
191 if (PlayField16[*si + FieldWidth] != 0)
196 if (PlayField16[*si - FieldWidth] == fiBase)
200 else if (bl == keyLeft)
202 if (PlayField16[*si - 1] == fiBase)
206 else if (bl == keyRight)
208 if (PlayField16[*si + 1] == fiBase)
212 bl = keyDown; // force moving down!
217 RedDiskReleaseFlag = 0; // moving down to up ...
223 RedDiskReleaseFlag = 0; // moving right to left ...
229 RedDiskReleaseFlag = 0; // moving up to down ...
235 RedDiskReleaseFlag = 0; // moving left to right ...
240 case keySpaceUp: // 5
241 RedDiskReleaseFlag = 0; // touching down to up ...
246 case keySpaceLeft: // 6
247 RedDiskReleaseFlag = 0; // touching right to left ...
252 case keySpaceDown: // 7
253 RedDiskReleaseFlag = 0; // touching up to down ...
258 case keySpaceRight: // 8
259 RedDiskReleaseFlag = 0; // touching left to right ...
265 goto loc_g_62E2; // no move ...
270 RedDiskReleaseFlag = 0;
275 // ==========================================================================
276 // moving down to up ...
277 // ==========================================================================
283 ax = PlayField16[*si - FieldWidth];
294 if (ax == fiInfotron)
300 if (al == fiTerminal)
303 if (al == fiPortUp || al == fiPortUpAndDown || al == fiPortAllDirections)
309 if (al == fiYellowDisk)
312 if (! subMoveKillsMurphy(*si - FieldWidth, ax, bl))
317 // ==========================================================================
318 // moving right to left ...
319 // ==========================================================================
325 MurphyVarFaceLeft = 1;
326 ax = PlayField16[*si - 1];
337 if (ax == fiInfotron)
346 if (al == fiTerminal)
349 if (al == fiPortLeft || al == fiPortLeftAndRight || al == fiPortAllDirections)
355 if (ax == fiYellowDisk)
358 if (ax == fiOrangeDisk)
361 if (! subMoveKillsMurphy(*si - 1, ax, bl))
366 // ==========================================================================
367 // moving up to down ...
368 // ==========================================================================
374 ax = PlayField16[*si + FieldWidth];
385 if (ax == fiInfotron)
391 if (al == fiTerminal)
394 if (al == fiPortDown || al == fiPortUpAndDown || al == fiPortAllDirections)
400 if (al == fiYellowDisk)
403 if (! subMoveKillsMurphy(*si + FieldWidth, ax, bl))
408 // ==========================================================================
409 // moving left to right ...
410 // ==========================================================================
416 MurphyVarFaceLeft = 0;
417 ax = PlayField16[*si + 1];
428 if (ax == fiInfotron)
437 if (al == fiTerminal)
440 if (al == fiPortRight || al == fiPortLeftAndRight || al == fiPortAllDirections)
446 if (al == fiYellowDisk)
449 if (ax == fiOrangeDisk)
452 if (! subMoveKillsMurphy(*si + 1, ax, bl))
457 // ==========================================================================
458 // touching down to up ...
459 // ==========================================================================
464 dxPos = *si - FieldWidth;
466 ax = PlayField16[*si - FieldWidth];
475 if (ax == fiInfotron)
478 if (al == fiTerminal)
486 // ==========================================================================
487 // touching right to left ...
488 // ==========================================================================
495 MurphyVarFaceLeft = 1;
496 ax = PlayField16[*si - 1];
504 if (ax == fiInfotron)
507 if (al == fiTerminal)
515 // ==========================================================================
516 // touching up to down ...
517 // ==========================================================================
522 dxPos = *si + FieldWidth;
524 ax = PlayField16[*si + FieldWidth];
532 if (ax == fiInfotron)
535 if (al == fiTerminal)
543 // ==========================================================================
544 // touching left to right ...
545 // ==========================================================================
552 MurphyVarFaceLeft = 0;
553 ax = PlayField16[*si + 1];
561 if (ax == fiInfotron)
564 if (al == fiTerminal)
572 // ==========================================================================
573 // Release Red disk: no move ...
574 // ==========================================================================
580 if (LowByte(RedDiskCount) == 0)
583 if (LowByte(RedDiskReleasePhase) != 0)
586 if (LowByte(RedDiskReleaseFlag) != 1)
589 MovHighByte(&PlayField16[*si], 0x2A);
590 MovingPictureSequencePhase = 0x40; // init picture move sequence
592 MovLowByte(&RedDiskReleasePhase, 1);
593 RedDiskReleaseMurphyPos = *si; // remember Murphy's location
596 // ==========================================================================
597 // SPACE moving down to up
598 // ==========================================================================
601 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyMoveUpRight : aniMurphyMoveUpLeft);
602 PlayField16[*si - FieldWidth] = 0x103;
603 PlayField16[*si] = 0x300;
604 *si = *si - FieldWidth;
605 goto loc_StopNoSplit;
607 // ==========================================================================
608 // SPACE moving right to left
609 // ==========================================================================
612 dx1 = aniMurphyMoveLeft;
613 PlayField16[*si - 1] = 0x203;
614 PlayField16[*si] = 0x300;
616 goto loc_StopNoSplit;
618 // ==========================================================================
619 // SPACE moving up to down, and when gravity is pulling!
620 // ==========================================================================
623 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyMoveUpRight : aniMurphyMoveUpLeft);
624 PlayField16[*si + FieldWidth] = 0x303;
625 PlayField16[*si] = 0x300;
626 *si = *si + FieldWidth;
627 goto loc_StopNoSplit;
629 // ==========================================================================
630 // SPACE moving left to right
631 // ==========================================================================
634 dx1 = aniMurphyMoveRight;
635 PlayField16[*si + 1] = 0x403;
636 PlayField16[*si] = 0x300;
638 goto loc_StopNoSplit;
640 // ==========================================================================
641 // BUG moving down to up
642 // ==========================================================================
645 if (SgnHighByte(PlayField16[*si - FieldWidth]) >= 0)
647 ExplodeFieldSP(*si); // Explode
652 PlayField16[*si - FieldWidth] = fiBase;
653 // ==========================================================================
654 // BASE moving down to up
655 // ==========================================================================
658 subSoundFX(*si, fiBase, actDigging);
660 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyDigUpRight : aniMurphyDigUpLeft);
661 PlayField16[*si - FieldWidth] = 0x503;
662 PlayField16[*si] = 0x300;
663 *si = *si - FieldWidth;
664 goto loc_StopNoSplit;
666 // ==========================================================================
667 // BUG moving right to left
668 // ==========================================================================
671 if (SgnHighByte(PlayField16[*si - 1]) >= 0)
673 ExplodeFieldSP(*si); // Explode
678 PlayField16[*si - 1] = fiBase;
679 // ==========================================================================
680 // BASE moving right to left
681 // ==========================================================================
684 subSoundFX(*si, fiBase, actDigging);
686 dx1 = aniMurphyDigLeft;
687 PlayField16[*si - 1] = 0x203;
688 PlayField16[*si] = 0x300;
690 goto loc_StopNoSplit;
692 // ==========================================================================
693 // BUG moving up to down
694 // ==========================================================================
697 if (SgnHighByte(PlayField16[*si + FieldWidth]) >= 0)
699 ExplodeFieldSP(*si); // Explode
704 PlayField16[*si + FieldWidth] = fiBase;
705 // ==========================================================================
706 // BASE moving up to down
707 // ==========================================================================
710 subSoundFX(*si, fiBase, actDigging);
712 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyDigUpRight : aniMurphyDigUpLeft);
713 PlayField16[*si + FieldWidth] = 0x703;
714 PlayField16[*si] = 0x300;
715 *si = *si + FieldWidth;
716 goto loc_StopNoSplit;
718 // ==========================================================================
719 // BUG moving left to right
720 // ==========================================================================
723 if (SgnHighByte(PlayField16[*si + 1]) >= 0)
725 ExplodeFieldSP(*si); // Explode
730 PlayField16[*si + 1] = fiBase;
731 // ==========================================================================
732 // BASE moving left to right
733 // ==========================================================================
736 subSoundFX(*si, fiBase, actDigging);
738 dx1 = aniMurphyDigRight;
739 PlayField16[*si + 1] = 0x803;
740 PlayField16[*si] = 0x300;
742 goto loc_StopNoSplit;
744 // ==========================================================================
745 // BUG touching down to up
746 // ==========================================================================
749 if (SgnHighByte(PlayField16[*si - FieldWidth]) >= 0)
751 ExplodeFieldSP(*si); // Explode
756 PlayField16[*si - FieldWidth] = fiBase;
757 // ==========================================================================
758 // BASE touching down to up
759 // ==========================================================================
762 subCopyImageToScreen(*si, aniMurphyTouchUp);
763 subSoundFX(*si, fiBase, actDigging);
766 dxPos = *si - FieldWidth;
767 MovHighByte(&PlayField16[*si], 0x10);
768 goto loc_StopNoSplit;
770 // ==========================================================================
771 // BUG touching right to left
772 // ==========================================================================
775 if (SgnHighByte(PlayField16[*si - 1]) >= 0)
777 ExplodeFieldSP(*si); // Explode
782 PlayField16[*si - 1] = fiBase;
783 // ==========================================================================
784 // BASE touching right to left
785 // ==========================================================================
788 subCopyImageToScreen(*si, aniMurphyTouchLeft);
789 subSoundFX(*si, fiBase, actDigging);
793 MovHighByte(&PlayField16[*si], 0x11);
794 goto loc_StopNoSplit;
796 // ==========================================================================
797 // BUG touching up to down
798 // ==========================================================================
801 if (SgnHighByte(PlayField16[*si + FieldWidth]) >= 0)
803 ExplodeFieldSP(*si); // Explode
808 PlayField16[*si + FieldWidth] = fiBase;
809 // ==========================================================================
810 // BASE touching up to down
811 // ==========================================================================
814 subCopyImageToScreen(*si, aniMurphyTouchDown);
815 subSoundFX(*si, fiBase, actDigging);
818 dxPos = *si + FieldWidth;
819 MovHighByte(&PlayField16[*si], 0x12);
820 goto loc_StopNoSplit;
822 // ==========================================================================
823 // BUG touching left to right
824 // ==========================================================================
827 if (SgnHighByte(PlayField16[*si + 1]) >= 0)
829 ExplodeFieldSP(*si); // Explode
834 PlayField16[*si + 1] = fiBase;
835 // ==========================================================================
836 // BASE touching left to right
837 // ==========================================================================
840 subCopyImageToScreen(*si, aniMurphyTouchRight);
841 subSoundFX(*si, fiBase, actDigging);
845 MovHighByte(&PlayField16[*si], 0x13);
846 goto loc_StopNoSplit;
848 // ==========================================================================
849 // INFOTRON moving down to up
850 // ==========================================================================
853 subSoundFX(*si, fiInfotron, actCollecting);
855 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
856 PlayField16[*si - FieldWidth] = 0x903;
857 PlayField16[*si] = 0x300;
858 *si = *si - FieldWidth;
859 goto loc_StopNoSplit;
861 // ==========================================================================
862 // INFOTRON moving right to left
863 // ==========================================================================
866 subSoundFX(*si, fiInfotron, actCollecting);
868 dx1 = aniEatInfotronLeft;
869 PlayField16[*si - 1] = 0xA03;
870 PlayField16[*si] = 0x300;
872 goto loc_StopNoSplit;
874 // ==========================================================================
875 // INFOTRON moving up to down
876 // ==========================================================================
879 subSoundFX(*si, fiInfotron, actCollecting);
881 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
882 PlayField16[*si + FieldWidth] = 0xB03;
883 PlayField16[*si] = 0x300;
884 *si = *si + FieldWidth;
885 goto loc_StopNoSplit;
887 // ==========================================================================
888 // INFOTRON moving left to right
889 // ==========================================================================
892 subSoundFX(*si, fiInfotron, actCollecting);
894 dx1 = aniEatInfotronRight;
895 PlayField16[*si + 1] = 0xC03;
896 PlayField16[*si] = 0x300;
898 goto loc_StopNoSplit;
900 // ==========================================================================
901 // INFOTRON touching down to up
902 // ==========================================================================
905 subCopyImageToScreen(*si, aniMurphyTouchUp);
906 subSoundFX(*si, fiInfotron, actCollecting);
908 dx1 = aniTouchInfotron;
909 MovHighByte(&PlayField16[*si], 0x14);
910 MovHighByte(&PlayField16[*si - FieldWidth], 0xFF);
911 goto loc_StopNoSplit;
913 // ==========================================================================
914 // INFOTRON touching right to left
915 // ==========================================================================
918 subCopyImageToScreen(*si, aniMurphyTouchLeft);
919 subSoundFX(*si, fiInfotron, actCollecting);
921 dx1 = aniTouchInfotron;
922 MovHighByte(&PlayField16[*si], 0x15);
923 MovHighByte(&PlayField16[*si - 1], 0xFF);
924 goto loc_StopNoSplit;
926 // ==========================================================================
927 // INFOTRON touching up to down
928 // ==========================================================================
931 subCopyImageToScreen(*si, aniMurphyTouchDown);
932 subSoundFX(*si, fiInfotron, actCollecting);
934 dx1 = aniTouchInfotron;
935 MovHighByte(&PlayField16[*si], 0x16);
936 MovHighByte(&PlayField16[*si + FieldWidth], 0xFF);
937 goto loc_StopNoSplit;
939 // ==========================================================================
940 // INFOTRON touching left to right
941 // ==========================================================================
944 subCopyImageToScreen(*si, aniMurphyTouchRight);
945 subSoundFX(*si, fiInfotron, actCollecting);
947 dx1 = aniTouchInfotron;
948 MovHighByte(&PlayField16[*si], 0x17);
949 MovHighByte(&PlayField16[*si + 1], 0xFF);
950 goto loc_StopNoSplit;
952 // ==========================================================================
953 // EXIT pressed from any direction
954 // ==========================================================================
962 if (LowByte(InfotronsNeeded) != 0)
965 game_sp.level_solved = TRUE;
967 subSoundFX(*si, fiExit, actPassing);
969 LeadOutCounter = 0x40; // quit: start lead-out
971 MovHighByte(&PlayField16[*si], 0xD);
972 goto loc_StopNoSplit;
974 // ==========================================================================
975 // ZONK moving right to left
976 // ==========================================================================
979 ax = PlayField16[*si - 2];
983 MovHighByte(&PlayField16[*si - 2], 1);
984 subCopyImageToScreen(*si, aniPushLeft); // draw pushing murphy
985 dx1 = aniZonkRollLeft;
989 MovHighByte(&PlayField16[*si], 0xE);
990 goto loc_MoveNoSplit;
992 // ==========================================================================
993 // ZONK moving left to right
994 // ==========================================================================
997 ax = PlayField16[*si + 2];
1001 ax = PlayField16[*si + FieldWidth + 1];
1002 if (ax == 0) // zonk falls
1005 MovHighByte(&PlayField16[*si + 2], 1);
1006 subCopyImageToScreen(*si, aniPushRight); // draw pushing murphy
1007 dx1 = aniZonkRollRight;
1011 MovHighByte(&PlayField16[*si], 0xF);
1012 goto loc_MoveNoSplit;
1014 // ==========================================================================
1015 // TERMINAL moving/touching down to up
1016 // ==========================================================================
1019 subCopyImageToScreen(*si, aniMurphyTouchUp);
1020 if (YellowDisksExploded != 0)
1022 YawnSleepCounter = 40; // stay hypnotized
1027 // draw new terminal type
1028 GfxGraphic[GetX(*si - FieldWidth)][GetY(*si - FieldWidth)] = aniTerminalActive;
1029 TerminalState[*si - FieldWidth] = 8;
1032 // ==========================================================================
1033 // TERMINAL moving/touching right to left
1034 // ==========================================================================
1037 subCopyImageToScreen(*si, aniMurphyTouchLeft);
1038 if (YellowDisksExploded != 0)
1040 YawnSleepCounter = 40; // stay hypnotized
1045 // draw new terminal type
1046 GfxGraphic[GetX(*si - 1)][GetY(*si - 1)] = aniTerminalActive;
1047 TerminalState[*si - 1] = 8;
1050 // ==========================================================================
1051 // TERMINAL moving/touching up to down
1052 // ==========================================================================
1055 subCopyImageToScreen(*si, aniMurphyTouchDown);
1056 if (YellowDisksExploded != 0)
1058 YawnSleepCounter = 40; // stay hypnotized
1063 // draw new terminal type
1064 GfxGraphic[GetX(*si + FieldWidth)][GetY(*si + FieldWidth)] = aniTerminalActive;
1065 TerminalState[*si + FieldWidth] = 8;
1068 // ==========================================================================
1069 // TERMINAL moving/touching left to right
1070 // ==========================================================================
1073 subCopyImageToScreen(*si, aniMurphyTouchRight);
1074 if (YellowDisksExploded != 0)
1076 YawnSleepCounter = 40; // stay hypnotized
1081 // draw new terminal type
1082 GfxGraphic[GetX(*si + 1)][GetY(*si + 1)] = aniTerminalActive;
1083 TerminalState[*si + 1] = 8;
1084 // ==========================================================================
1085 // common TERMINAL stuff moving/touching from all directions
1086 // ==========================================================================
1089 TerminalMaxCycles = 7;
1090 YellowDisksExploded = 1;
1091 for (i = 0; i <= LevelMax; i++)
1093 if (PlayField16[i] == fiYellowDisk)
1099 // ==========================================================================
1100 // PORT down to up, VERTICAL PORT, CROSS PORT all moving down to up
1101 // ==========================================================================
1104 if (PlayField16[*si - 2 * FieldWidth] != 0)
1107 dx1 = aniSplitUpDown;
1108 dx2Step = -FieldWidth;
1109 PlayField16[*si] = 0x1803;
1110 PlayField16[*si - 2 * FieldWidth] = 0x300;
1113 // ==========================================================================
1114 // PORT right to left, HORIZONTAL PORT, CROSS PORT all moving right to left
1115 // ==========================================================================
1118 if (PlayField16[*si - 2] != 0)
1121 dx1 = aniMurphyMoveLeft;
1123 PlayField16[*si] = 0x1903;
1124 PlayField16[*si - 2] = 0x300;
1127 // ==========================================================================
1128 // PORT up to down, VERTICAL PORT, CROSS PORT all moving up to down
1129 // ==========================================================================
1132 if (PlayField16[*si + 2 * FieldWidth] != 0)
1135 dx1 = aniSplitUpDown;
1136 dx2Step = FieldWidth;
1137 PlayField16[*si] = 0x1A03;
1138 PlayField16[*si + 2 * FieldWidth] = 0x300;
1141 // ==========================================================================
1142 // PORT left to right, HORIZONTAL PORT, CROSS PORT all moving left to right
1143 // ==========================================================================
1146 if (PlayField16[*si + 2] != 0)
1149 dx1 = aniMurphyMoveRight;
1151 PlayField16[*si] = 0x1B03;
1152 PlayField16[*si + 2] = 0x300;
1155 MovingPictureSequencePhase = 0; // stop picture move sequence
1156 SplitMoveFlag = 1; // port: split movement
1159 // ==========================================================================
1160 // RED DISK moving down to up
1161 // ==========================================================================
1164 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
1165 PlayField16[*si] = 0x1C03;
1166 PlayField16[*si - FieldWidth] = 0x300;
1167 goto loc_StopNoSplit;
1169 // ==========================================================================
1170 // RED DISK moving right to left
1171 // ==========================================================================
1174 dx1 = aniMurphyEatLeft;
1175 PlayField16[*si] = 0x300; // !!!!!! this time we move murphy at sequence-start!
1176 PlayField16[*si - 1] = 0x1D03;
1178 goto loc_StopNoSplit;
1180 // ==========================================================================
1181 // RED DISK moving up to down
1182 // ==========================================================================
1185 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
1186 PlayField16[*si] = 0x1E03;
1187 PlayField16[*si + FieldWidth] = 0x300;
1188 goto loc_StopNoSplit;
1190 // ==========================================================================
1191 // RED DISK moving left to right
1192 // ==========================================================================
1195 // dx = aniMurphyEatRightRedDisk 'this sequence is 9 steps long!
1196 dx1 = aniMurphyEatRight;
1197 // --------------------------------------------------------------------------
1199 // Table data_h_145A, pointed to by table data_h_105E, has a severe bug:
1200 // The Red Disk sequence is 8 pictures long, but 9 are displayed, because it
1201 // has 1 extra entry, which causes Murphy to end slightly shifted to the left!
1202 // We may not fix the table, because then the timing of the game changes
1203 // and several existing demo's do not run properly anymore.
1204 // We only correct Murphies x-location here, when the sequence starts.
1205 // Remember that this is not the real bug-fix, but we must live with
1206 // this existing bug and correct for the consequences of it.
1208 if (AllowEatRightRedDiskBug == 0) // Murphy's screen x-position
1209 MurphyScreenXPos = MurphyScreenXPos - 2 * MurphyZoomFactor;
1212 // FS: for me this means to blit the first animation frame twice
1214 // --------------------------------------------------------------------------
1215 PlayField16[*si] = 0x300; // !!!!!! this time we move murphy at sequence-start!
1216 PlayField16[*si + 1] = 0x1F03;
1218 goto loc_StopNoSplit;
1220 // ==========================================================================
1221 // RED DISK touching down to up
1222 // ==========================================================================
1225 dx1 = aniTouchRedDisk;
1226 MovHighByte(&PlayField16[*si], 0x20);
1227 MovHighByte(&PlayField16[*si - FieldWidth], 3);
1228 goto loc_StopNoSplit;
1230 // ==========================================================================
1231 // RED DISK touching right to left
1232 // ==========================================================================
1235 dx1 = aniTouchRedDisk;
1236 MovHighByte(&PlayField16[*si], 0x21);
1237 MovHighByte(&PlayField16[*si - 1], 3);
1238 goto loc_StopNoSplit;
1240 // ==========================================================================
1241 // RED DISK touching up to down
1242 // ==========================================================================
1245 dx1 = aniTouchRedDisk;
1246 MovHighByte(&PlayField16[*si], 0x22);
1247 MovHighByte(&PlayField16[*si + FieldWidth], 3);
1248 goto loc_StopNoSplit;
1250 // ==========================================================================
1251 // RED DISK touching left to right
1252 // ==========================================================================
1255 dx1 = aniTouchRedDisk;
1256 MovHighByte(&PlayField16[*si], 0x23);
1257 MovHighByte(&PlayField16[*si + 1], 3);
1260 MovingPictureSequencePhase = 0; // stop picture move sequence
1263 // ==========================================================================
1264 // YELLOW DISK moving down to up
1265 // ==========================================================================
1268 if (PlayField16[*si - 2 * FieldWidth] != 0)
1271 PlayField16[*si - 2 * FieldWidth] = 0x1200;
1272 dx1 = aniYellowDisk;
1273 dxPos = *si - FieldWidth;
1274 dx2 = (MurphyVarFaceLeft == 0 ? aniPushRight : aniPushLeft);
1275 dx2Step = FieldWidth;
1276 PlayField16[*si] = 0x2403;
1277 subCopyImageToScreen(*si, dx2);
1278 goto loc_MoveNoSplit;
1280 // ==========================================================================
1281 // YELLOW DISK moving right to left
1282 // ==========================================================================
1285 if (PlayField16[*si - 2] != 0)
1288 PlayField16[*si - 2] = 0x1200;
1289 subCopyImageToScreen(*si, aniPushLeft);
1290 dx1 = aniYellowDisk;
1294 PlayField16[*si] = 0x2503;
1295 goto loc_MoveNoSplit;
1297 // ==========================================================================
1298 // YELLOW DISK moving up to down
1299 // ==========================================================================
1302 if (PlayField16[*si + 2 * FieldWidth] != 0)
1305 PlayField16[*si + 2 * FieldWidth] = 0x1200;
1306 dx1 = aniYellowDisk;
1307 dxPos = *si + FieldWidth;
1308 dx2 = (MurphyVarFaceLeft == 0 ? aniPushRight : aniPushLeft);
1309 dx2Step = -FieldWidth;
1310 PlayField16[*si] = 0x2703;
1311 subCopyImageToScreen(*si, dx2);
1312 goto loc_MoveNoSplit;
1314 // ==========================================================================
1315 // YELLOW DISK moving left to right
1316 // ==========================================================================
1319 if (PlayField16[*si + 2] != 0)
1322 PlayField16[*si + 2] = 0x1200;
1323 subCopyImageToScreen(*si, aniPushRight);
1324 dx1 = aniYellowDisk;
1328 PlayField16[*si] = 0x2603;
1329 goto loc_MoveNoSplit;
1331 // ==========================================================================
1332 // ORANGE DISK moving right to left
1333 // ==========================================================================
1336 if (PlayField16[*si - 2] != 0)
1339 PlayField16[*si - 2] = 0x800;
1340 subCopyImageToScreen(*si, aniPushLeft);
1341 dx1 = aniOrangeDisk;
1345 PlayField16[*si] = 0x2803;
1346 goto loc_MoveNoSplit;
1348 // ==========================================================================
1349 // ORANGE DISK moving left to right
1350 // ==========================================================================
1353 if (PlayField16[*si + 2] != 0)
1356 if (PlayField16[*si + FieldWidth + 1] == 0) // falling goes before pushing
1359 PlayField16[*si + 2] = 0x100;
1360 subCopyImageToScreen(*si, aniPushRight);
1361 dx1 = aniOrangeDisk;
1365 PlayField16[*si] = 0x2903;
1366 // ==========================================================================
1367 // Copy screen animation action table to action work space
1368 // (To paint sequence: Push Zonk/Disk / release red disk / Port passing)
1369 // ==========================================================================
1372 MovingPictureSequencePhase = 8; // init picture move sequence
1375 SplitMoveFlag = 0; // no port: no split movement
1378 // copy/store global move sequence info????????????????????????????????????
1379 // ... dont think so ...(FS)
1380 // ==========================================================================
1381 // Proceed with all movements
1382 // ==========================================================================
1384 locProceedMovingMurphy: // proceed moving murphy
1385 YawnSleepCounter = 0; // Wake up sleeping Murphy
1386 ax = MovingPictureSequencePhase; // sequence busy?
1387 if (ax == 0) // no -- start sequence!
1390 ax = ax - 1; // next picture of sequence
1391 MovingPictureSequencePhase = ax; // store for later
1393 if (ax == 0) // Sound effects
1395 switch (HighByte(PlayField16[*si]))
1399 subSoundFX(*si, fiZonk, actPushing);
1404 subSoundFX(*si, fiOrangeDisk, actPushing);
1411 subSoundFX(*si, fiYellowDisk, actPushing);
1419 bl = HighByte(PlayField16[*si]);
1420 if (bl == 0xE) // Push Zonk to left
1423 if (bl == 0xF) // Push Zonk to right
1426 if (bl == 0x28) // Push orange disk to left
1429 if (bl == 0x29) // Push orange disk to right
1432 if (bl == 0x24) // Push yellow disk up
1435 if (bl == 0x25) // Push yellow disk to left
1438 if (bl == 0x27) // Push yellow disk down
1441 if (bl == 0x26) // Push yellow disk to right
1444 if (bl == 0x2A) // Red disk release timer
1449 // ==========================================================================
1450 // Paint frame of MOVING.DAT sequence
1451 // ==========================================================================
1456 dx1SequenceLength = getSequenceLength(dx1);
1458 if (SplitMoveFlag == 0)
1460 // ++++++++++++++++++++++++++
1461 // Begin of normal movement
1462 MurphyScreenXPos = MurphyScreenXPos + MurphyDX * MurphyZoomFactor;
1463 MurphyScreenYPos = MurphyScreenYPos + MurphyDY * MurphyZoomFactor;
1465 if (!(ClearPos < 0)) // clear field that murphy is leaving
1466 subCopyImageToScreen(ClearPos, aniSpace);
1468 tDeltaX = MurphyDX * LocalStretch * (SeqPos + 1);
1469 tDeltaY = MurphyDY * LocalStretch * (SeqPos + 1);
1471 X = GetStretchX(dxPos) + tDeltaX;
1472 Y = GetStretchY(dxPos) + tDeltaY;
1473 Tmp = (SeqPos < 0 ? 0 : SeqPos); // 9StepBugFix!(red disk move right)
1475 if (isSnappingSequence(dx1) && SeqPos == dx1SequenceLength - 1)
1478 DDSpriteBuffer_BltImg(X, Y, dx1, Tmp);
1479 GfxGraphic[GetX(*si)][GetY(*si)] = -1; // (Murphy's position)
1480 GfxGraphic[GetX(dxPos)][GetY(dxPos)] = -1; // (snapping position)
1484 tPos = dxPos + dx2Step;
1485 X = GetStretchX(tPos);
1486 Y = GetStretchY(tPos);
1488 // (SeqPos iterates from 0 to 7 while pushing)
1489 DDSpriteBuffer_BltImg(X + tDeltaX, Y + tDeltaY, dx2, SeqPos);
1492 // End of normal movement
1493 // ------------------------
1497 // ++++++++++++++++++++++++++++++++
1498 // Begin of split movement (port)
1499 MurphyScreenXPos = MurphyScreenXPos + 2 * MurphyDX * MurphyZoomFactor;
1500 MurphyScreenYPos = MurphyScreenYPos + 2 * MurphyDY * MurphyZoomFactor;
1501 subCopyImageToScreen(ClearPos, aniSpace); // clear the field that murphy leaves
1502 tDeltaX = MurphyDX * LocalStretch * (SeqPos + 1);
1503 tDeltaY = MurphyDY * LocalStretch * (SeqPos + 1);
1504 X = GetStretchX(dxPos) + tDeltaX;
1505 Y = GetStretchY(dxPos) + tDeltaY;
1506 DDSpriteBuffer_BltImg(X, Y, dx1, SeqPos); // plot first murphy
1508 tPos = dxPos + dx2Step;
1509 X = GetStretchX(tPos);
1510 Y = GetStretchY(tPos);
1511 DDSpriteBuffer_BltImg(X + tDeltaX, Y + tDeltaY, dx1, SeqPos); // plot second murphy
1512 DDSpriteBuffer_BltImg(X, Y, fiGraphic[LowByte(PlayField16[tPos])], 0); // replot the port on top
1513 // End of split movement (port)
1514 // ------------------------------
1515 } // loc_g_6D1E:'loc_g_6D28:
1517 SeqPos = SeqPos + 1;
1518 if (SeqPos < dx1SequenceLength)
1521 // Follow-up after movement completed 'loc_g_6D35:
1522 MurphyXPos = MurphyXPos + MurphyDX;
1523 MurphyYPos = MurphyYPos + MurphyDY;
1524 bl = HighByte(PlayField16[*si]); // animation phase
1525 MovHighByte(&PlayField16[*si], 0);
1527 if (bl == 0x1) // space, moving up
1530 if (bl == 0x2) // space, moving left
1533 if (bl == 0x3) // space, moving down
1536 if (bl == 0x4) // space, moving right
1539 if (bl == 0x5) // base , moving up
1542 if (bl == 0x6) // base , moving left -> 6 is not used, value is set to 2 instead of 6!
1545 if (bl == 0x7) // base , moving down
1548 if (bl == 0x8) // base , moving right
1551 if (bl == 0x9) // infotron, moving up
1554 if (bl == 0xA) // infotron, moving left
1557 if (bl == 0xB) // infotron, moving down
1560 if (bl == 0xC) // infotron, moving right
1563 if (bl == 0xD) // exit
1566 if (bl == 0xE) // zonk, pushing left
1569 if (bl == 0xF) // zonk, pushing right
1572 if (bl == 0x10) // base , touching up
1575 if (bl == 0x11) // base , touching left
1578 if (bl == 0x12) // base , touching down
1581 if (bl == 0x13) // base , touching right
1584 if (bl == 0x14) // infotron touching up
1587 if (bl == 0x15) // infotron touching left
1590 if (bl == 0x16) // infotron touching down
1593 if (bl == 0x17) // infotron touching right
1596 if (bl == 0x18) // port up
1599 if (bl == 0x19) // port left
1602 if (bl == 0x1A) // port down
1605 if (bl == 0x1B) // port right
1608 if (bl == 0x1C) // red disk, moving up
1611 if (bl == 0x1D) // red disk, moving left
1614 if (bl == 0x1E) // red disk, moving down
1617 if (bl == 0x1F) // red disk, moving right -> 9-Step-Bug!
1620 if (bl == 0x20) // red disk, touching up
1623 if (bl == 0x21) // red disk, touching left
1626 if (bl == 0x22) // red disk, touching down
1629 if (bl == 0x23) // red disk, touching right
1632 if (bl == 0x24) // yellow disk, pushing up
1635 if (bl == 0x25) // yellow disk, pushing left
1638 if (bl == 0x26) // yellow disk, pushing right -> order of "down" exchanged with "right"!
1641 if (bl == 0x27) // yellow disk, pushing down -> order of "down" exchanged with "right"!
1644 if (bl == 0x28) // orange disk, pushing left
1647 if (bl == 0x29) // orange disk, pushing right
1650 if (bl == 0x2A) // red disk, release
1657 // ==========================================================================
1658 // infotron, moving up
1659 // ==========================================================================
1662 if (0 < LowByte(InfotronsNeeded))
1663 InfotronsNeeded = InfotronsNeeded - 1;
1665 loc_g_6EC8: // space, base
1666 PlayField16[*si] = fiMurphy;
1667 subAdjustZonksInfotronsAboveMurphy(*si + FieldWidth);
1671 // ==========================================================================
1672 // infotron, moving left
1673 // ==========================================================================
1676 if (0 < LowByte(InfotronsNeeded))
1677 InfotronsNeeded = InfotronsNeeded - 1;
1679 loc_g_6EE6: // space, base
1680 PlayField16[*si] = fiMurphy;
1681 subAdjustZonksInfotronsAboveMurphy(*si + 1);
1685 // ==========================================================================
1686 // infotron, moving down
1687 // ==========================================================================
1690 if (0 < LowByte(InfotronsNeeded))
1691 InfotronsNeeded = InfotronsNeeded - 1;
1693 loc_g_6F04: // space, base
1694 if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion)
1695 PlayField16[*si - FieldWidth] = 0;
1697 PlayField16[*si] = fiMurphy;
1701 // ==========================================================================
1702 // infotron, moving right
1703 // ==========================================================================
1706 if (0 < LowByte(InfotronsNeeded))
1707 InfotronsNeeded = InfotronsNeeded - 1;
1709 loc_g_71C4: // space, base
1710 subAdjustZonksInfotronsAboveMurphy(*si - 1);
1711 PlayField16[*si] = fiMurphy;
1715 // ==========================================================================
1716 // infotron, touching up
1717 // ==========================================================================
1720 if (0 < LowByte(InfotronsNeeded))
1721 InfotronsNeeded = InfotronsNeeded - 1;
1724 if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion)
1725 PlayField16[*si - FieldWidth] = 0;
1729 // ==========================================================================
1730 // infotron, touching left
1731 // ==========================================================================
1734 if (0 < LowByte(InfotronsNeeded))
1735 InfotronsNeeded = InfotronsNeeded - 1;
1738 if (LowByte(PlayField16[*si - 1]) != fiExplosion)
1739 PlayField16[*si - 1] = 0;
1743 // ==========================================================================
1744 // infotron, touching down
1745 // ==========================================================================
1748 if (0 < LowByte(InfotronsNeeded))
1749 InfotronsNeeded = InfotronsNeeded - 1;
1752 if (LowByte(PlayField16[*si + FieldWidth]) != fiExplosion)
1753 PlayField16[*si + FieldWidth] = 0;
1757 // ==========================================================================
1758 // infotron, touching right
1759 // ==========================================================================
1762 if (0 < LowByte(InfotronsNeeded))
1763 InfotronsNeeded = InfotronsNeeded - 1;
1766 if (LowByte(PlayField16[*si + 1]) != fiExplosion)
1767 PlayField16[*si + 1] = 0;
1771 // ==========================================================================
1772 // zonk, pushing left
1773 // ==========================================================================
1776 if (LowByte(PlayField16[*si]) != fiExplosion)
1777 PlayField16[*si] = 0;
1779 PlayField16[*si - 1] = fiMurphy;
1780 PlayField16[*si - 2] = fiZonk;
1781 subExplodeSnikSnaksBelow(*si - 2);
1786 // ==========================================================================
1787 // zonk, pushing right
1788 // ==========================================================================
1791 if (LowByte(PlayField16[*si]) != fiExplosion)
1792 PlayField16[*si] = 0;
1794 PlayField16[*si + 1] = fiMurphy;
1795 PlayField16[*si + 2] = fiZonk;
1796 subExplodeSnikSnaksBelow(*si + 2);
1801 // ==========================================================================
1803 // ==========================================================================
1808 PlayField16[*si] = fiSpace; // remove Murphy from playfield after exiting
1812 // ==========================================================================
1813 // Push Zonk from right to left
1814 // ==========================================================================
1817 if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiZonk)
1820 PlayField16[*si] = fiMurphy; // else restore - no more zonk pushing!
1821 PlayField16[*si - 1] = fiZonk;
1822 if (LowByte(PlayField16[*si - 2]) != fiExplosion)
1823 PlayField16[*si - 2] = 0;
1825 subCopyImageToScreen(*si, aniMurphy);
1829 // ==========================================================================
1830 // Push Zonk from left to right
1831 // ==========================================================================
1834 if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiZonk)
1837 PlayField16[*si] = fiMurphy; // else restore - no more zonk pushing!
1838 PlayField16[*si + 1] = fiZonk;
1839 if (LowByte(PlayField16[*si + 2]) != fiExplosion)
1840 PlayField16[*si + 2] = 0;
1842 subCopyImageToScreen(*si, aniMurphy);
1846 // ==========================================================================
1847 // Push orange disk from right to left
1848 // ==========================================================================
1851 if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiOrangeDisk)
1854 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
1855 PlayField16[*si - 1] = fiOrangeDisk;
1856 if (LowByte(PlayField16[*si - 2]) != fiExplosion)
1857 PlayField16[*si - 2] = 0;
1859 subCopyImageToScreen(*si, aniMurphy);
1863 // ==========================================================================
1864 // Push orange disk from left to right
1865 // ==========================================================================
1868 if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiOrangeDisk)
1871 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
1872 PlayField16[*si + 1] = fiOrangeDisk;
1873 if (LowByte(PlayField16[*si + 2]) != fiExplosion)
1874 PlayField16[*si + 2] = 0;
1876 subCopyImageToScreen(*si, aniMurphy);
1880 // ==========================================================================
1881 // Push yellow disk from down to up
1882 // ==========================================================================
1885 if (DemoKeyCode == keyUp && PlayField16[*si - FieldWidth] == fiYellowDisk)
1888 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
1889 PlayField16[*si - FieldWidth] = fiYellowDisk;
1890 if (LowByte(PlayField16[*si - 2 * FieldWidth]) != fiExplosion)
1891 PlayField16[*si - 2 * FieldWidth] = 0;
1893 subCopyImageToScreen(*si, aniMurphy);
1897 // ==========================================================================
1898 // Push yellow disk from right to left
1899 // ==========================================================================
1902 if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiYellowDisk)
1905 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
1906 PlayField16[*si - 1] = fiYellowDisk;
1907 if (LowByte(PlayField16[*si - 2]) != fiExplosion)
1908 PlayField16[*si - 2] = 0;
1910 subCopyImageToScreen(*si, aniMurphy);
1914 // ==========================================================================
1915 // Push yellow disk from up to down
1916 // ==========================================================================
1919 if (DemoKeyCode == keyDown && PlayField16[*si + FieldWidth] == fiYellowDisk)
1922 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
1923 PlayField16[*si + FieldWidth] = fiYellowDisk;
1924 if (LowByte(PlayField16[*si + 2 * FieldWidth]) != fiExplosion)
1925 PlayField16[*si + 2 * FieldWidth] = 0;
1927 subCopyImageToScreen(*si, aniMurphy);
1931 // ==========================================================================
1932 // Push yellow disk from left to right
1933 // ==========================================================================
1936 if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiYellowDisk)
1939 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
1940 PlayField16[*si + 1] = fiYellowDisk;
1941 if (LowByte(PlayField16[*si + 2]) != fiExplosion)
1942 PlayField16[*si + 2] = 0;
1944 subCopyImageToScreen(*si, aniMurphy);
1948 // ==========================================================================
1949 // time red disk release (space)
1950 // ==========================================================================
1953 if (DemoKeyCode != keySpace)
1955 PlayField16[*si] = fiMurphy;
1956 subCopyImageToScreen(*si, aniMurphy);
1957 RedDiskReleasePhase = 0;
1959 else if (MovingPictureSequencePhase == 0x20)
1961 // anxious murphy, dropping red disk
1962 subCopyImageToScreen(*si, aniMurphyDropping);
1963 RedDiskReleasePhase = 1;
1968 // ==========================================================================
1969 // Special port down to up
1970 // ==========================================================================
1973 if (LowByte(PlayField16[*si]) != fiExplosion)
1974 PlayField16[*si] = 0;
1976 PlayField16[*si - 2 * FieldWidth] = fiMurphy;
1978 *si = *si - FieldWidth;
1979 if (HighByte(PlayField16[*si]) == 1)
1982 *si = *si - FieldWidth;
1986 // ==========================================================================
1987 // Special port right to left
1988 // ==========================================================================
1991 if (LowByte(PlayField16[*si]) != fiExplosion)
1992 PlayField16[*si] = 0;
1994 PlayField16[*si - 2] = fiMurphy;
1997 if (HighByte(PlayField16[*si]) == 1)
2004 // ==========================================================================
2005 // Special port up to down
2006 // ==========================================================================
2009 if (LowByte(PlayField16[*si]) != fiExplosion)
2010 PlayField16[*si] = 0;
2012 PlayField16[*si + 2 * FieldWidth] = fiMurphy;
2014 *si = *si + FieldWidth;
2015 if (HighByte(PlayField16[*si]) == 1)
2018 *si = *si + FieldWidth;
2022 // ==========================================================================
2023 // Special port left to right
2024 // ==========================================================================
2027 if (LowByte(PlayField16[*si]) != fiExplosion)
2028 PlayField16[*si] = 0;
2030 PlayField16[*si + 2] = fiMurphy;
2033 if (HighByte(PlayField16[*si]) == 1)
2040 // ==========================================================================
2042 // ==========================================================================
2045 if (LowByte(PlayField16[*si]) != fiExplosion)
2046 PlayField16[*si] = 0;
2048 *si = *si - FieldWidth;
2049 PlayField16[*si] = fiMurphy;
2050 subEatRedDisk(*si); // inc+show Murphy's red disks
2054 // ==========================================================================
2055 // Move Red Disk left
2056 // ==========================================================================
2059 if (LowByte(PlayField16[*si + 1]) != fiExplosion)
2060 PlayField16[*si + 1] = 0;
2062 PlayField16[*si] = fiMurphy;
2063 subEatRedDisk(*si); // inc+show Murphy's red disks
2067 // ==========================================================================
2068 // Move Red Disk down
2069 // ==========================================================================
2072 if (LowByte(PlayField16[*si]) != fiExplosion)
2073 PlayField16[*si] = 0;
2075 *si = *si + FieldWidth;
2076 PlayField16[*si] = fiMurphy;
2077 subEatRedDisk(*si); // inc+show Murphy's red disks
2081 // ==========================================================================
2082 // Move Red Disk right
2083 // ==========================================================================
2086 if (LowByte(PlayField16[*si - 1]) != fiExplosion)
2087 PlayField16[*si - 1] = 0;
2089 PlayField16[*si] = fiMurphy;
2090 subEatRedDisk(*si); // inc+show Murphy's red disks
2094 // ==========================================================================
2096 // ==========================================================================
2099 if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion)
2100 PlayField16[*si - FieldWidth] = 0;
2102 subEatRedDisk(*si - FieldWidth); // inc+show Murphy's red disks
2106 // ==========================================================================
2107 // Eat Red Disk left
2108 // ==========================================================================
2111 if (LowByte(PlayField16[*si - 1]) != fiExplosion)
2112 PlayField16[*si - 1] = 0;
2114 subEatRedDisk(*si - 1); // inc+show Murphy's red disks
2118 // ==========================================================================
2119 // Eat Red Disk down
2120 // ==========================================================================
2123 if (LowByte(PlayField16[*si + FieldWidth]) != fiExplosion)
2124 PlayField16[*si + FieldWidth] = 0;
2126 subEatRedDisk(*si + FieldWidth); // inc+show Murphy's red disks
2130 // ==========================================================================
2131 // Eat Red Disk right
2132 // ==========================================================================
2135 if (LowByte(PlayField16[*si + 1]) != fiExplosion)
2136 PlayField16[*si + 1] = 0;
2138 subEatRedDisk(*si + 1); // inc+show Murphy's red disks
2142 // ==========================================================================
2143 // yellow disk, pushing up
2144 // ==========================================================================
2147 if (LowByte(PlayField16[*si]) != fiExplosion)
2148 PlayField16[*si] = 0;
2150 *si = *si - FieldWidth;
2151 PlayField16[*si] = fiMurphy;
2152 PlayField16[*si - FieldWidth] = fiYellowDisk;
2156 // ==========================================================================
2157 // yellow disk, pushing left
2158 // ==========================================================================
2161 if (LowByte(PlayField16[*si]) != fiExplosion)
2162 PlayField16[*si] = 0;
2165 PlayField16[*si] = fiMurphy;
2166 PlayField16[*si - 1] = fiYellowDisk;
2170 // ==========================================================================
2171 // yellow disk, pushing down
2172 // ==========================================================================
2175 if (LowByte(PlayField16[*si]) != fiExplosion)
2176 PlayField16[*si] = 0;
2178 *si = *si + FieldWidth;
2179 PlayField16[*si] = fiMurphy;
2180 PlayField16[*si + FieldWidth] = fiYellowDisk;
2184 // ==========================================================================
2185 // yellow disk pushing right
2186 // ==========================================================================
2189 if (LowByte(PlayField16[*si]) != fiExplosion)
2190 PlayField16[*si] = 0;
2193 PlayField16[*si] = fiMurphy;
2194 PlayField16[*si + 1] = fiYellowDisk;
2198 // ==========================================================================
2199 // orange disk, pushing left
2200 // ==========================================================================
2203 if (LowByte(PlayField16[*si]) != fiExplosion)
2204 PlayField16[*si] = 0;
2207 PlayField16[*si] = fiMurphy;
2208 PlayField16[*si - 1] = fiOrangeDisk;
2212 // ==========================================================================
2213 // orange disk, pushing right
2214 // ==========================================================================
2217 if (LowByte(PlayField16[*si]) != fiExplosion)
2218 PlayField16[*si] = 0;
2221 PlayField16[*si] = fiMurphy;
2222 PlayField16[*si + 1] = fiOrangeDisk;
2223 if (PlayField16[*si + FieldWidth + 1] == 0) // make it fall down if below is empty
2225 MovHighByte(&PlayField16[*si + 1], 0x20);
2226 MovHighByte(&PlayField16[*si + FieldWidth + 1], fiOrangeDisk);
2231 // ==========================================================================
2232 // Release a red disk
2233 // ==========================================================================
2236 PlayField16[*si] = fiMurphy;
2237 RedDiskReleasePhase = 2;
2238 RedDiskCount = RedDiskCount - 1;
2240 subSoundFX(*si, fiRedDisk, actDropping);
2241 } // subAnimateMurphy
2243 // ==========================================================================
2245 // ==========================================================================
2246 void subExplodeSnikSnaksBelow(int si)
2250 ax = LowByte(PlayField16[si + FieldWidth]);
2251 if (ax == 0x11 || ax == 0xBB)
2252 ExplodeFieldSP(si + FieldWidth);
2253 } // subExplodeSnikSnaksBelow
2255 // ==========================================================================
2257 // Does pushing against an object kill Murphy?
2258 // ==========================================================================
2259 static boolean subMoveKillsMurphy(int si, int ax, int bl)
2261 static boolean subMoveKillsMurphy;
2267 if (ax == 0xFFFF || ax == 0xAAAA || ah == 0)
2273 if (al == fiExplosion)
2276 if (fiOrangeDisk <= al && al <= fiPortUp)
2279 ExplodeFieldSP(si); // Explode
2280 subMoveKillsMurphy = True;
2281 return subMoveKillsMurphy;
2290 ExplodeFieldSP(si); // Explode
2291 subMoveKillsMurphy = True;
2292 return subMoveKillsMurphy;
2294 loc_g_74F6: // zonk left
2296 if (! (ah == 0x20 || ah == 0x40 || ah == 0x50 || ah == 0x70))
2299 subMoveKillsMurphy = True; // Set carry flag
2300 return subMoveKillsMurphy;
2302 loc_g_7512: // zonk right
2304 if (! (ah == 0x30 || ah == 0x40 || ah == 0x60 || ah == 0x70))
2307 loc_g_752E: // Marked fields and Ports
2308 subMoveKillsMurphy = True; // Set carry flag
2309 return subMoveKillsMurphy;
2311 loc_g_7530: // explosion
2312 if ((ah & 0x80) != 0)
2319 ExplodeFieldSP(si); // Explode
2320 subMoveKillsMurphy = True; // Set carry flag
2321 return subMoveKillsMurphy;
2324 PlayField16[si] = 0;
2325 subMoveKillsMurphy = False;
2327 return subMoveKillsMurphy;
2328 } // subMoveKillsMurphy
2330 // ==========================================================================
2332 // Test If si 's a special (grav) port and If so Then fetch new values (see below)
2333 // change conditions to port specs
2334 // The 10-port data base is at data_h_0D28, 10 entries of 6 bytes each:
2335 // (hi),(lo),(gravity),(freeze zonks),(freeze enemies),(unused)
2336 // ==========================================================================
2338 void subSpPortTest(int si)
2342 for (i = 0; i < LInfo.SpecialPortCount; i++)
2344 if (LInfo.SpecialPort[i].PortLocation / 2 == si)
2346 GravityFlag = LInfo.SpecialPort[i].Gravity;
2347 FreezeZonks = LInfo.SpecialPort[i].FreezeZonks;
2348 SnikSnaksElectronsFrozen = LInfo.SpecialPort[i].FreezeEnemies;
2355 void subCopyAnimToScreen(int si, int graphic, int sync_frame)
2359 // +++++++++++++++++++++++++++++++++++++++++
2360 X = GetStretchX(si);
2361 Y = GetStretchY(si);
2362 DDSpriteBuffer_BltImg(X, Y, graphic, sync_frame);
2363 // +++++++++++++++++++++++++++++++++++++++++
2366 void subCopyImageToScreen(int si, int graphic)
2368 subCopyAnimToScreen(si, graphic, 0);
2371 static void subEatRedDisk(int si)
2373 if (AllowRedDiskCheat == 0)
2375 if (RedDiskReleasePhase != 0)
2377 if (RedDiskReleaseMurphyPos == si)
2382 RedDiskCount = (RedDiskCount + 1) % 256;
2385 void subAdjustZonksInfotronsAboveMurphy(int si)
2389 if (LowByte(PlayField16[si]) != fiExplosion)
2390 PlayField16[si] = 0;
2392 ax = PlayField16[si - FieldWidth];
2393 if (ax == 0 || ax == 0x9999)
2396 if (ax == fiZonk || ax == fiInfotron)
2398 MovHighByte(&PlayField16[si - FieldWidth], 0x40); // make falling straigt down
2403 loc_g_15A8: // empty above
2404 ax = PlayField16[si - FieldWidth - 1];
2405 if (ax == fiZonk || ax == fiInfotron)
2409 ax = PlayField16[si - FieldWidth + 1];
2410 if (ax == fiZonk || ax == fiInfotron)
2415 loc_g_15C5: // zonk/infotron above left
2416 ax = PlayField16[si - 1];
2417 if (! (ax == fiZonk || ax == fiInfotron || ax == fiRAM)) // continue testing right above
2420 MovHighByte(&PlayField16[si - FieldWidth - 1], 0x60); // make roll right
2421 PlayField16[si - FieldWidth] = 0x8888;
2425 loc_g_15E8: // zonk/infotron above right
2426 ax = PlayField16[si + 1];
2427 if (ax == fiZonk || ax == fiInfotron || ax == fiRAM)
2429 MovHighByte(&PlayField16[si - FieldWidth + 1], 0x50); // make roll left
2430 PlayField16[si - FieldWidth] = 0x8888;