1 // ----------------------------------------------------------------------------
3 // ----------------------------------------------------------------------------
8 static void subEatRedDisk(int si);
9 static boolean subMoveKillsMurphy(int si, int ax, int bl);
13 #define LocalStretch (2)
14 #define MurphyZoomFactor (ZoomFactor)
18 #define LocalStretch (1)
19 #define MurphyZoomFactor (1)
23 // ==========================================================================
25 // Move Murphy in any direction
26 // ==========================================================================
28 void subAnimateMurphy(int *si)
30 int ax, al, bl, i, X, Y;
32 int tDeltaX, tDeltaY, tPos, Tmp;
34 // Variables that hold information about the animation sequence
36 static int *dx = 0; // an array of image positions in moving.mpx, finalized with -1
38 static int dx1 = 0; // same as "*dx" above, but as image/animation token
39 static int dx2 = 0; // an additional image position of a second sprite, for instance: yellow disk if pushed
40 static int MurphyDX = 0, MurphyDY = 0; // murphys move steps
41 static int SeqPos = 0; // index into dx()
42 static int ClearPos = 0; // Position to clear before blitting sprites, none=-1
43 static int dxPos = 0; // field-position to draw dx(SeqPos)
44 static int dx2Step = 0; // position of dx2 relative to dx-position
45 static int dx1SequenceLength = 0;
47 ax = PlayField16[*si];
52 MurphyMoveCounter = 0; // We have no Murphy! Exit!
57 MurphyMoveCounter = 1; // We have a Murphy!
58 MurphyExplodePos = *si;
60 // (check if high byte of PlayField16 has stored movement information)
61 if (ax != fiMurphy) // yes--go proceed moving murphy?
62 goto locProceedMovingMurphy;
64 // FS: reset moving sequence variables
74 ScratchGravity = 0; // scratch gravity off
75 if (GravityFlag != 0) // Gravity? (1=gravity on)
77 bl = LowByte(PlayField16[*si - FieldWidth]); // check above
78 if (! (bl == fiPortUp ||
79 bl == fiPortUpAndDown ||
80 bl == fiPortAllDirections))
82 if (PlayField16[*si + FieldWidth] == 0) // gravity on and space below!
88 if (bl != 0) // a key was pressed!
89 goto locKeyPressed5FCF;
92 printf("::: Murphy.c: !!! %d [%d]\n", DemoKeyCode, GravityFlag);
95 RedDiskReleaseFlag = 1;
96 if (ScratchGravity != 0) // gravity pulls & space below?'-> force Space up to down
110 // ------------------------------------------------------------------
111 // Murphy's YAWN & SLEEP sequence, counted down by YawnSleepCounter:
113 YawnSleepCounter = YawnSleepCounter + 1;
115 if (YawnSleepCounter < 16)
118 if (YawnSleepCounter < 2000)
121 // (default: single graphic, no animation)
122 subCopyAnimToScreen(*si, aniMurphy, YawnSleepCounter - 16);
127 if (YawnSleepCounter < 4000)
129 // yawn! and look depressed afterwards...
130 // (default: 12 animation frames with delay of 8)
131 subCopyAnimToScreen(*si, aniMurphyYawn, YawnSleepCounter - 2000);
136 if (YawnSleepCounter < 6400)
139 // (default: 12 animation frames with delay of 8)
140 subCopyAnimToScreen(*si, aniMurphyYawn, YawnSleepCounter - 4000);
145 // time1 = 6400 + 12 * 8; // (default: 6496 == 6400 + 12 * 8)
146 time1 = 6400 + 12 * 10;
148 if (YawnSleepCounter < time1)
150 // yawn again! - third time
151 // (default: 12 animation frames with delay of 8)
152 subCopyAnimToScreen(*si, aniMurphyYawn, YawnSleepCounter - 6400);
157 // time2 = 6496 + 3 * 64; // (default: 6688 == 6496 + 3 * 64)
158 time2 = 6496 + 3 * 100;
160 if (YawnSleepCounter > time2) // Murphy already went to sleep
163 if (PlayField16[*si - 1] == 0)
165 if (PlayField16[*si + 1] == 0)
167 // no sleep -- go back to "wait and start yawning" phase
168 YawnSleepCounter = 144;
174 // go to sleep (right side)
175 // (default: 3 animation frames with delay of 64)
176 subCopyAnimToScreen(*si, aniMurphySleepRight, YawnSleepCounter - time1);
182 // go to sleep (left side)
183 // (default: 3 animation frames with delay of 64)
184 subCopyAnimToScreen(*si, aniMurphySleepLeft, YawnSleepCounter - time1);
188 // end of YAWN-SLEEP-Sequence
196 // ------------------------------------------------------------------
197 // Murphy's YAWN & SLEEP sequence, counted down by YawnSleepCounter:
198 YawnSleepCounter = YawnSleepCounter + 1;
199 if (YawnSleepCounter == 4)
201 subCopyFieldToScreen(*si, fiMurphy); // normal grin
205 if (YawnSleepCounter <= 500) // loc_g_5ED7:
208 if (YawnSleepCounter <= 522)
210 bx = (YawnSleepCounter - 500) / 2;
211 subCopyFieldToScreen(*si, aniMurphyYawn + bx); // yawn! and look depressed afterwards...
215 if (YawnSleepCounter <= 1000)
218 if (YawnSleepCounter <= 1022)
220 bx = (YawnSleepCounter - 1000) / 2;
221 subCopyFieldToScreen(*si, aniMurphyYawn + bx); // yawn again!
225 if (YawnSleepCounter <= 1600) // loc_g_5F3B:
228 if (YawnSleepCounter <= 1622)
230 bx = (YawnSleepCounter - 1600) / 2;
231 subCopyFieldToScreen(*si, aniMurphyYawn + bx); // yawn again! - third time
235 if (YawnSleepCounter > 1654)
238 if (PlayField16[*si - 1] == 0)
240 if (PlayField16[*si + 1] == 0)
242 YawnSleepCounter = 36;
248 bx = (YawnSleepCounter - 1622) / 16;
249 subCopyFieldToScreen(*si, aniMurphySleepRight + bx); // go to sleep
254 bx = (YawnSleepCounter - 1622) / 16;
255 subCopyFieldToScreen(*si, aniMurphySleepLeft + bx); // go to sleep
259 // end of YAWN-SLEEP-Sequence
263 // ------------------------------------------------------------------
264 // ==========================================================================
265 // (Direct Jump) a key was pressed
266 // ==========================================================================
269 if (ScratchGravity == 0)
272 if (PlayField16[*si + FieldWidth] != 0)
277 if (PlayField16[*si - FieldWidth] == fiBase)
281 else if (bl == keyLeft)
283 if (PlayField16[*si - 1] == fiBase)
287 else if (bl == keyRight)
289 if (PlayField16[*si + 1] == fiBase)
293 bl = keyDown; // force moving down!
298 RedDiskReleaseFlag = 0; // moving down to up ...
304 RedDiskReleaseFlag = 0; // moving right to left ...
310 RedDiskReleaseFlag = 0; // moving up to down ...
316 RedDiskReleaseFlag = 0; // moving left to right ...
321 case keySpaceUp: // 5
322 RedDiskReleaseFlag = 0; // touching down to up ...
327 case keySpaceLeft: // 6
328 RedDiskReleaseFlag = 0; // touching right to left ...
333 case keySpaceDown: // 7
334 RedDiskReleaseFlag = 0; // touching up to down ...
339 case keySpaceRight: // 8
340 RedDiskReleaseFlag = 0; // touching left to right ...
346 goto loc_g_62E2; // no move ...
351 RedDiskReleaseFlag = 0;
356 // ==========================================================================
357 // moving down to up ...
358 // ==========================================================================
364 ax = PlayField16[*si - FieldWidth];
375 if (ax == fiInfotron)
381 if (al == fiTerminal)
384 if (al == fiPortUp || al == fiPortUpAndDown || al == fiPortAllDirections)
390 if (al == fiYellowDisk)
393 if (! subMoveKillsMurphy(*si - FieldWidth, ax, bl))
398 // ==========================================================================
399 // moving right to left ...
400 // ==========================================================================
406 MurphyVarFaceLeft = 1;
407 ax = PlayField16[*si - 1];
418 if (ax == fiInfotron)
427 if (al == fiTerminal)
430 if (al == fiPortLeft || al == fiPortLeftAndRight || al == fiPortAllDirections)
436 if (ax == fiYellowDisk)
439 if (ax == fiOrangeDisk)
442 if (! subMoveKillsMurphy(*si - 1, ax, bl))
447 // ==========================================================================
448 // moving up to down ...
449 // ==========================================================================
455 ax = PlayField16[*si + FieldWidth];
466 if (ax == fiInfotron)
472 if (al == fiTerminal)
475 if (al == fiPortDown || al == fiPortUpAndDown || al == fiPortAllDirections)
481 if (al == fiYellowDisk)
484 if (! subMoveKillsMurphy(*si + FieldWidth, ax, bl))
489 // ==========================================================================
490 // moving left to right ...
491 // ==========================================================================
497 MurphyVarFaceLeft = 0;
498 ax = PlayField16[*si + 1];
509 if (ax == fiInfotron)
518 if (al == fiTerminal)
521 if (al == fiPortRight || al == fiPortLeftAndRight || al == fiPortAllDirections)
527 if (al == fiYellowDisk)
530 if (ax == fiOrangeDisk)
533 if (! subMoveKillsMurphy(*si + 1, ax, bl))
538 // ==========================================================================
539 // touching down to up ...
540 // ==========================================================================
545 dxPos = *si - FieldWidth;
547 ax = PlayField16[*si - FieldWidth];
556 if (ax == fiInfotron)
559 if (al == fiTerminal)
567 // ==========================================================================
568 // touching right to left ...
569 // ==========================================================================
576 MurphyVarFaceLeft = 1;
577 ax = PlayField16[*si - 1];
585 if (ax == fiInfotron)
588 if (al == fiTerminal)
596 // ==========================================================================
597 // touching up to down ...
598 // ==========================================================================
603 dxPos = *si + FieldWidth;
605 ax = PlayField16[*si + FieldWidth];
613 if (ax == fiInfotron)
616 if (al == fiTerminal)
624 // ==========================================================================
625 // touching left to right ...
626 // ==========================================================================
633 MurphyVarFaceLeft = 0;
634 ax = PlayField16[*si + 1];
642 if (ax == fiInfotron)
645 if (al == fiTerminal)
653 // ==========================================================================
654 // Release Red disk: no move ...
655 // ==========================================================================
661 if (LowByte(RedDiskCount) == 0)
664 if (LowByte(RedDiskReleasePhase) != 0)
667 if (LowByte(RedDiskReleaseFlag) != 1)
670 MovHighByte(&PlayField16[*si], 0x2A);
671 MovingPictureSequencePhase = 0x40; // init picture move sequence
673 dx = aniFramesRedDisk;
677 MovLowByte(&RedDiskReleasePhase, 1);
678 RedDiskReleaseMurphyPos = *si; // remember Murphy's location
681 // ==========================================================================
682 // SPACE moving down to up
683 // ==========================================================================
687 dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
689 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyMoveUpRight : aniMurphyMoveUpLeft);
691 PlayField16[*si - FieldWidth] = 0x103;
692 PlayField16[*si] = 0x300;
693 *si = *si - FieldWidth;
694 goto loc_StopNoSplit;
696 // ==========================================================================
697 // SPACE moving right to left
698 // ==========================================================================
702 dx = aniFramesMurphyEatLeft;
704 dx1 = aniMurphyMoveLeft;
706 PlayField16[*si - 1] = 0x203;
707 PlayField16[*si] = 0x300;
709 goto loc_StopNoSplit;
711 // ==========================================================================
712 // SPACE moving up to down, and when gravity is pulling!
713 // ==========================================================================
717 dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
719 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyMoveUpRight : aniMurphyMoveUpLeft);
721 PlayField16[*si + FieldWidth] = 0x303;
722 PlayField16[*si] = 0x300;
723 *si = *si + FieldWidth;
724 goto loc_StopNoSplit;
726 // ==========================================================================
727 // SPACE moving left to right
728 // ==========================================================================
732 dx = aniFramesMurphyEatRight;
734 dx1 = aniMurphyMoveRight;
736 PlayField16[*si + 1] = 0x403;
737 PlayField16[*si] = 0x300;
739 goto loc_StopNoSplit;
741 // ==========================================================================
742 // BUG moving down to up
743 // ==========================================================================
746 if (SgnHighByte(PlayField16[*si - FieldWidth]) >= 0)
748 ExplodeFieldSP(*si); // Explode
753 PlayField16[*si - FieldWidth] = fiBase;
754 // ==========================================================================
755 // BASE moving down to up
756 // ==========================================================================
760 subSoundFX(*si, fiBase, actDigging);
766 dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
768 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyDigUpRight : aniMurphyDigUpLeft);
770 PlayField16[*si - FieldWidth] = 0x503;
771 PlayField16[*si] = 0x300;
772 *si = *si - FieldWidth;
773 goto loc_StopNoSplit;
775 // ==========================================================================
776 // BUG moving right to left
777 // ==========================================================================
780 if (SgnHighByte(PlayField16[*si - 1]) >= 0)
782 ExplodeFieldSP(*si); // Explode
787 PlayField16[*si - 1] = fiBase;
788 // ==========================================================================
789 // BASE moving right to left
790 // ==========================================================================
794 subSoundFX(*si, fiBase, actDigging);
800 dx = aniFramesMurphyEatLeft;
802 dx1 = aniMurphyDigLeft;
804 PlayField16[*si - 1] = 0x203;
805 PlayField16[*si] = 0x300;
807 goto loc_StopNoSplit;
809 // ==========================================================================
810 // BUG moving up to down
811 // ==========================================================================
814 if (SgnHighByte(PlayField16[*si + FieldWidth]) >= 0)
816 ExplodeFieldSP(*si); // Explode
821 PlayField16[*si + FieldWidth] = fiBase;
822 // ==========================================================================
823 // BASE moving up to down
824 // ==========================================================================
828 subSoundFX(*si, fiBase, actDigging);
834 dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
836 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyDigUpRight : aniMurphyDigUpLeft);
838 PlayField16[*si + FieldWidth] = 0x703;
839 PlayField16[*si] = 0x300;
840 *si = *si + FieldWidth;
841 goto loc_StopNoSplit;
843 // ==========================================================================
844 // BUG moving left to right
845 // ==========================================================================
848 if (SgnHighByte(PlayField16[*si + 1]) >= 0)
850 ExplodeFieldSP(*si); // Explode
855 PlayField16[*si + 1] = fiBase;
856 // ==========================================================================
857 // BASE moving left to right
858 // ==========================================================================
862 subSoundFX(*si, fiBase, actDigging);
868 dx = aniFramesMurphyEatRight;
870 dx1 = aniMurphyDigRight;
872 PlayField16[*si + 1] = 0x803;
873 PlayField16[*si] = 0x300;
875 goto loc_StopNoSplit;
877 // ==========================================================================
878 // BUG touching down to up
879 // ==========================================================================
882 if (SgnHighByte(PlayField16[*si - FieldWidth]) >= 0)
884 ExplodeFieldSP(*si); // Explode
889 PlayField16[*si - FieldWidth] = fiBase;
890 // ==========================================================================
891 // BASE touching down to up
892 // ==========================================================================
895 subCopyImageToScreen(*si, aniMurphyTouchUp);
897 subSoundFX(*si, fiBase, actDigging);
903 dx = aniFramesTouchBase;
907 dxPos = *si - FieldWidth;
908 MovHighByte(&PlayField16[*si], 0x10);
909 goto loc_StopNoSplit;
911 // ==========================================================================
912 // BUG touching right to left
913 // ==========================================================================
916 if (SgnHighByte(PlayField16[*si - 1]) >= 0)
918 ExplodeFieldSP(*si); // Explode
923 PlayField16[*si - 1] = fiBase;
924 // ==========================================================================
925 // BASE touching right to left
926 // ==========================================================================
929 subCopyImageToScreen(*si, aniMurphyTouchLeft);
931 subSoundFX(*si, fiBase, actDigging);
937 dx = aniFramesTouchBase;
942 MovHighByte(&PlayField16[*si], 0x11);
943 goto loc_StopNoSplit;
945 // ==========================================================================
946 // BUG touching up to down
947 // ==========================================================================
950 if (SgnHighByte(PlayField16[*si + FieldWidth]) >= 0)
952 ExplodeFieldSP(*si); // Explode
957 PlayField16[*si + FieldWidth] = fiBase;
958 // ==========================================================================
959 // BASE touching up to down
960 // ==========================================================================
963 subCopyImageToScreen(*si, aniMurphyTouchDown);
965 subSoundFX(*si, fiBase, actDigging);
971 dx = aniFramesTouchBase;
975 dxPos = *si + FieldWidth;
976 MovHighByte(&PlayField16[*si], 0x12);
977 goto loc_StopNoSplit;
979 // ==========================================================================
980 // BUG touching left to right
981 // ==========================================================================
984 if (SgnHighByte(PlayField16[*si + 1]) >= 0)
986 ExplodeFieldSP(*si); // Explode
991 PlayField16[*si + 1] = fiBase;
992 // ==========================================================================
993 // BASE touching left to right
994 // ==========================================================================
997 subCopyImageToScreen(*si, aniMurphyTouchRight);
999 subSoundFX(*si, fiBase, actDigging);
1005 dx = aniFramesTouchBase;
1010 MovHighByte(&PlayField16[*si], 0x13);
1011 goto loc_StopNoSplit;
1013 // ==========================================================================
1014 // INFOTRON moving down to up
1015 // ==========================================================================
1019 subSoundFX(*si, fiInfotron, actCollecting);
1021 subSoundFXInfotron();
1025 dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
1027 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
1029 PlayField16[*si - FieldWidth] = 0x903;
1030 PlayField16[*si] = 0x300;
1031 *si = *si - FieldWidth;
1032 goto loc_StopNoSplit;
1034 // ==========================================================================
1035 // INFOTRON moving right to left
1036 // ==========================================================================
1040 subSoundFX(*si, fiInfotron, actCollecting);
1042 subSoundFXInfotron();
1046 dx = aniFramesEatInfotronLeft;
1048 dx1 = aniEatInfotronLeft;
1055 PlayField16[*si - 1] = 0xA03;
1056 PlayField16[*si] = 0x300;
1058 goto loc_StopNoSplit;
1060 // ==========================================================================
1061 // INFOTRON moving up to down
1062 // ==========================================================================
1066 subSoundFX(*si, fiInfotron, actCollecting);
1068 subSoundFXInfotron();
1072 dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
1074 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
1076 PlayField16[*si + FieldWidth] = 0xB03;
1077 PlayField16[*si] = 0x300;
1078 *si = *si + FieldWidth;
1079 goto loc_StopNoSplit;
1081 // ==========================================================================
1082 // INFOTRON moving left to right
1083 // ==========================================================================
1087 subSoundFX(*si, fiInfotron, actCollecting);
1089 subSoundFXInfotron();
1093 dx = aniFramesEatInfotronRight;
1095 dx1 = aniEatInfotronRight;
1102 PlayField16[*si + 1] = 0xC03;
1103 PlayField16[*si] = 0x300;
1105 goto loc_StopNoSplit;
1107 // ==========================================================================
1108 // INFOTRON touching down to up
1109 // ==========================================================================
1112 subCopyImageToScreen(*si, aniMurphyTouchUp);
1114 subSoundFX(*si, fiInfotron, actCollecting);
1116 subSoundFXInfotron();
1120 dx = aniFramesTouchInfotron;
1122 dx1 = aniTouchInfotron;
1124 MovHighByte(&PlayField16[*si], 0x14);
1125 MovHighByte(&PlayField16[*si - FieldWidth], 0xFF);
1126 goto loc_StopNoSplit;
1128 // ==========================================================================
1129 // INFOTRON touching right to left
1130 // ==========================================================================
1133 subCopyImageToScreen(*si, aniMurphyTouchLeft);
1135 subSoundFX(*si, fiInfotron, actCollecting);
1137 subSoundFXInfotron();
1141 dx = aniFramesTouchInfotron;
1143 dx1 = aniTouchInfotron;
1145 MovHighByte(&PlayField16[*si], 0x15);
1146 MovHighByte(&PlayField16[*si - 1], 0xFF);
1147 goto loc_StopNoSplit;
1149 // ==========================================================================
1150 // INFOTRON touching up to down
1151 // ==========================================================================
1154 subCopyImageToScreen(*si, aniMurphyTouchDown);
1156 subSoundFX(*si, fiInfotron, actCollecting);
1158 subSoundFXInfotron();
1162 dx = aniFramesTouchInfotron;
1164 dx1 = aniTouchInfotron;
1166 MovHighByte(&PlayField16[*si], 0x16);
1167 MovHighByte(&PlayField16[*si + FieldWidth], 0xFF);
1168 goto loc_StopNoSplit;
1170 // ==========================================================================
1171 // INFOTRON touching left to right
1172 // ==========================================================================
1175 subCopyImageToScreen(*si, aniMurphyTouchRight);
1177 subSoundFX(*si, fiInfotron, actCollecting);
1179 subSoundFXInfotron();
1183 dx = aniFramesTouchInfotron;
1185 dx1 = aniTouchInfotron;
1187 MovHighByte(&PlayField16[*si], 0x17);
1188 MovHighByte(&PlayField16[*si + 1], 0xFF);
1189 goto loc_StopNoSplit;
1191 // ==========================================================================
1192 // EXIT pressed from any direction
1193 // ==========================================================================
1201 if (LowByte(InfotronsNeeded) != 0)
1205 if (!game_sp.LevelSolved)
1206 printf("::: Murphy.c: !!!!!!!!!! LEVEL %d SOLVED !!!!!!!!!!\n",LevelNumber);
1210 game_sp.LevelSolved = TRUE;
1214 subSoundFX(*si, fiExit, actPassing);
1219 LeadOutCounter = 0x40; // quit: start lead-out
1221 dx = aniFramesMurphyExit;
1223 dx1 = aniMurphyExit;
1225 MovHighByte(&PlayField16[*si], 0xD);
1226 goto loc_StopNoSplit;
1228 // ==========================================================================
1229 // ZONK moving right to left
1230 // ==========================================================================
1233 ax = PlayField16[*si - 2];
1237 MovHighByte(&PlayField16[*si - 2], 1);
1238 subCopyImageToScreen(*si, aniPushLeft); // draw pushing murphy
1240 dx = aniFramesZonkRollLeft;
1242 dx1 = aniZonkRollLeft;
1247 MovHighByte(&PlayField16[*si], 0xE);
1248 goto loc_MoveNoSplit;
1250 // ==========================================================================
1251 // ZONK moving left to right
1252 // ==========================================================================
1255 ax = PlayField16[*si + 2];
1259 ax = PlayField16[*si + FieldWidth + 1];
1260 if (ax == 0) // zonk falls
1263 MovHighByte(&PlayField16[*si + 2], 1);
1264 subCopyImageToScreen(*si, aniPushRight); // draw pushing murphy
1266 dx = aniFramesZonkRollRight;
1268 dx1 = aniZonkRollRight;
1273 MovHighByte(&PlayField16[*si], 0xF);
1274 goto loc_MoveNoSplit;
1276 // ==========================================================================
1277 // TERMINAL moving/touching down to up
1278 // ==========================================================================
1281 subCopyImageToScreen(*si, aniMurphyTouchUp);
1282 if (YellowDisksExploded != 0)
1284 YawnSleepCounter = 40; // stay hypnotized
1290 // draw new terminal type
1292 GfxGraphic[GetX(*si - FieldWidth)][GetY(*si - FieldWidth)] = aniTerminalActive;
1294 subCopyImageToScreen(*si - FieldWidth, aniTerminalActive);
1297 subCopyFieldToScreen(*si - FieldWidth, 0x88); // draw new terminal type
1299 TerminalState[*si - FieldWidth] = 8;
1302 // ==========================================================================
1303 // TERMINAL moving/touching right to left
1304 // ==========================================================================
1307 subCopyImageToScreen(*si, aniMurphyTouchLeft);
1308 if (YellowDisksExploded != 0)
1310 YawnSleepCounter = 40; // stay hypnotized
1316 // draw new terminal type
1318 GfxGraphic[GetX(*si - 1)][GetY(*si - 1)] = aniTerminalActive;
1320 subCopyImageToScreen(*si - 1, aniTerminalActive);
1323 subCopyFieldToScreen(*si - 1, 0x88); // draw new terminal type
1325 TerminalState[*si - 1] = 8;
1328 // ==========================================================================
1329 // TERMINAL moving/touching up to down
1330 // ==========================================================================
1333 subCopyImageToScreen(*si, aniMurphyTouchDown);
1334 if (YellowDisksExploded != 0)
1336 YawnSleepCounter = 40; // stay hypnotized
1342 // draw new terminal type
1344 GfxGraphic[GetX(*si + FieldWidth)][GetY(*si + FieldWidth)] = aniTerminalActive;
1346 subCopyImageToScreen(*si + FieldWidth, aniTerminalActive);
1349 subCopyFieldToScreen(*si + FieldWidth, 0x88); // draw new terminal type
1351 TerminalState[*si + FieldWidth] = 8;
1354 // ==========================================================================
1355 // TERMINAL moving/touching left to right
1356 // ==========================================================================
1359 subCopyImageToScreen(*si, aniMurphyTouchRight);
1360 if (YellowDisksExploded != 0)
1362 YawnSleepCounter = 40; // stay hypnotized
1368 // draw new terminal type
1370 GfxGraphic[GetX(*si + 1)][GetY(*si + 1)] = aniTerminalActive;
1372 subCopyImageToScreen(*si + 1, aniTerminalActive);
1375 subCopyFieldToScreen(*si + 1, 0x88); // draw new terminal type
1377 TerminalState[*si + 1] = 8;
1378 // ==========================================================================
1379 // common TERMINAL stuff moving/touching from all directions
1380 // ==========================================================================
1383 TerminalMaxCycles = 7;
1384 YellowDisksExploded = 1;
1385 for (i = 0; i <= LevelMax; i++)
1387 if (PlayField16[i] == fiYellowDisk)
1393 // ==========================================================================
1394 // PORT down to up, VERTICAL PORT, CROSS PORT all moving down to up
1395 // ==========================================================================
1398 if (PlayField16[*si - 2 * FieldWidth] != 0)
1402 dx = aniFramesSplitUpDown;
1404 dx1 = aniSplitUpDown;
1406 dx2Step = -FieldWidth;
1407 PlayField16[*si] = 0x1803;
1408 PlayField16[*si - 2 * FieldWidth] = 0x300;
1411 // ==========================================================================
1412 // PORT right to left, HORIZONTAL PORT, CROSS PORT all moving right to left
1413 // ==========================================================================
1416 if (PlayField16[*si - 2] != 0)
1420 dx = aniFramesMurphyEatLeft;
1422 dx1 = aniMurphyMoveLeft;
1425 PlayField16[*si] = 0x1903;
1426 PlayField16[*si - 2] = 0x300;
1429 // ==========================================================================
1430 // PORT up to down, VERTICAL PORT, CROSS PORT all moving up to down
1431 // ==========================================================================
1434 if (PlayField16[*si + 2 * FieldWidth] != 0)
1438 dx = aniFramesSplitUpDown;
1440 dx1 = aniSplitUpDown;
1442 dx2Step = FieldWidth;
1443 PlayField16[*si] = 0x1A03;
1444 PlayField16[*si + 2 * FieldWidth] = 0x300;
1447 // ==========================================================================
1448 // PORT left to right, HORIZONTAL PORT, CROSS PORT all moving left to right
1449 // ==========================================================================
1452 if (PlayField16[*si + 2] != 0)
1456 dx = aniFramesMurphyEatRight;
1458 dx1 = aniMurphyMoveRight;
1461 PlayField16[*si] = 0x1B03;
1462 PlayField16[*si + 2] = 0x300;
1465 MovingPictureSequencePhase = 0; // stop picture move sequence
1466 SplitMoveFlag = 1; // port: split movement
1469 // ==========================================================================
1470 // RED DISK moving down to up
1471 // ==========================================================================
1475 dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
1477 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
1479 PlayField16[*si] = 0x1C03;
1480 PlayField16[*si - FieldWidth] = 0x300;
1481 goto loc_StopNoSplit;
1483 // ==========================================================================
1484 // RED DISK moving right to left
1485 // ==========================================================================
1489 dx = aniFramesMurphyEatLeft;
1491 dx1 = aniMurphyEatLeft;
1493 PlayField16[*si] = 0x300; // !!!!!! this time we move murphy at sequence-start!
1494 PlayField16[*si - 1] = 0x1D03;
1496 goto loc_StopNoSplit;
1498 // ==========================================================================
1499 // RED DISK moving up to down
1500 // ==========================================================================
1504 dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
1506 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
1508 PlayField16[*si] = 0x1E03;
1509 PlayField16[*si + FieldWidth] = 0x300;
1510 goto loc_StopNoSplit;
1512 // ==========================================================================
1513 // RED DISK moving left to right
1514 // ==========================================================================
1518 // dx = aniFramesMurphyEatRightRedDisk 'this sequence is 9 steps long!
1519 dx = aniFramesMurphyEatRight;
1521 dx1 = aniMurphyEatRight;
1523 // --------------------------------------------------------------------------
1525 // Table data_h_145A, pointed to by table data_h_105E, has a severe bug:
1526 // The Red Disk sequence is 8 pictures long, but 9 are displayed, because it
1527 // has 1 extra entry, which causes Murphy to end slightly shifted to the left!
1528 // We may not fix the table, because then the timing of the game changes
1529 // and several existing demo's do not run properly anymore.
1530 // We only correct Murphies x-location here, when the sequence starts.
1531 // Remember that this is not the real bug-fix, but we must live with
1532 // this existing bug and correct for the consequences of it.
1534 if (AllowEatRightRedDiskBug == 0) // Murphy's screen x-position
1535 MurphyScreenXPos = MurphyScreenXPos - 2 * MurphyZoomFactor;
1538 // FS: for me this means to blit the first animation frame twice
1540 // --------------------------------------------------------------------------
1541 PlayField16[*si] = 0x300; // !!!!!! this time we move murphy at sequence-start!
1542 PlayField16[*si + 1] = 0x1F03;
1544 goto loc_StopNoSplit;
1546 // ==========================================================================
1547 // RED DISK touching down to up
1548 // ==========================================================================
1552 dx = aniFramesTouchRedDisk;
1554 dx1 = aniTouchRedDisk;
1556 MovHighByte(&PlayField16[*si], 0x20);
1557 MovHighByte(&PlayField16[*si - FieldWidth], 3);
1558 goto loc_StopNoSplit;
1560 // ==========================================================================
1561 // RED DISK touching right to left
1562 // ==========================================================================
1566 dx = aniFramesTouchRedDisk;
1568 dx1 = aniTouchRedDisk;
1570 MovHighByte(&PlayField16[*si], 0x21);
1571 MovHighByte(&PlayField16[*si - 1], 3);
1572 goto loc_StopNoSplit;
1574 // ==========================================================================
1575 // RED DISK touching up to down
1576 // ==========================================================================
1580 dx = aniFramesTouchRedDisk;
1582 dx1 = aniTouchRedDisk;
1584 MovHighByte(&PlayField16[*si], 0x22);
1585 MovHighByte(&PlayField16[*si + FieldWidth], 3);
1586 goto loc_StopNoSplit;
1588 // ==========================================================================
1589 // RED DISK touching left to right
1590 // ==========================================================================
1594 dx = aniFramesTouchRedDisk;
1596 dx1 = aniTouchRedDisk;
1598 MovHighByte(&PlayField16[*si], 0x23);
1599 MovHighByte(&PlayField16[*si + 1], 3);
1602 MovingPictureSequencePhase = 0; // stop picture move sequence
1605 // ==========================================================================
1606 // YELLOW DISK moving down to up
1607 // ==========================================================================
1610 if (PlayField16[*si - 2 * FieldWidth] != 0)
1613 PlayField16[*si - 2 * FieldWidth] = 0x1200;
1615 subCopyImageToScreen(*si, aniPushRight);
1618 dx = aniFramesYellowDisk;
1620 dx1 = aniYellowDisk;
1622 dxPos = *si - FieldWidth;
1624 dx2 = (MurphyVarFaceLeft == 0 ? aniPushRight : aniPushLeft);
1626 dx2 = aniPushUpDown;
1628 dx2Step = FieldWidth;
1629 PlayField16[*si] = 0x2403;
1631 subCopyImageToScreen(*si, dx2);
1633 goto loc_MoveNoSplit;
1635 // ==========================================================================
1636 // YELLOW DISK moving right to left
1637 // ==========================================================================
1640 if (PlayField16[*si - 2] != 0)
1643 PlayField16[*si - 2] = 0x1200;
1644 subCopyImageToScreen(*si, aniPushLeft);
1646 dx = aniFramesYellowDisk;
1648 dx1 = aniYellowDisk;
1653 PlayField16[*si] = 0x2503;
1654 goto loc_MoveNoSplit;
1656 // ==========================================================================
1657 // YELLOW DISK moving up to down
1658 // ==========================================================================
1661 if (PlayField16[*si + 2 * FieldWidth] != 0)
1664 PlayField16[*si + 2 * FieldWidth] = 0x1200;
1666 subCopyImageToScreen(*si, aniPushRight);
1669 dx = aniFramesYellowDisk;
1671 dx1 = aniYellowDisk;
1673 dxPos = *si + FieldWidth;
1675 dx2 = (MurphyVarFaceLeft == 0 ? aniPushRight : aniPushLeft);
1677 dx2 = aniPushUpDown;
1679 dx2Step = -FieldWidth;
1680 PlayField16[*si] = 0x2703;
1682 subCopyImageToScreen(*si, dx2);
1684 goto loc_MoveNoSplit;
1686 // ==========================================================================
1687 // YELLOW DISK moving left to right
1688 // ==========================================================================
1691 if (PlayField16[*si + 2] != 0)
1694 PlayField16[*si + 2] = 0x1200;
1695 subCopyImageToScreen(*si, aniPushRight);
1697 dx = aniFramesYellowDisk;
1699 dx1 = aniYellowDisk;
1704 PlayField16[*si] = 0x2603;
1705 goto loc_MoveNoSplit;
1707 // ==========================================================================
1708 // ORANGE DISK moving right to left
1709 // ==========================================================================
1712 if (PlayField16[*si - 2] != 0)
1715 PlayField16[*si - 2] = 0x800;
1716 subCopyImageToScreen(*si, aniPushLeft);
1718 dx = aniFramesOrangeDisk;
1720 dx1 = aniOrangeDisk;
1725 PlayField16[*si] = 0x2803;
1726 goto loc_MoveNoSplit;
1728 // ==========================================================================
1729 // ORANGE DISK moving left to right
1730 // ==========================================================================
1733 if (PlayField16[*si + 2] != 0)
1736 if (PlayField16[*si + FieldWidth + 1] == 0) // falling goes before pushing
1739 PlayField16[*si + 2] = 0x100;
1740 subCopyImageToScreen(*si, aniPushRight);
1742 dx = aniFramesOrangeDisk;
1744 dx1 = aniOrangeDisk;
1749 PlayField16[*si] = 0x2903;
1750 // ==========================================================================
1751 // Copy screen animation action table to action work space
1752 // (To paint sequence: Push Zonk/Disk / release red disk / Port passing)
1753 // ==========================================================================
1756 MovingPictureSequencePhase = 8; // init picture move sequence
1759 SplitMoveFlag = 0; // no port: no split movement
1762 // copy/store global move sequence info????????????????????????????????????
1763 // ... dont think so ...(FS)
1764 // ==========================================================================
1765 // Proceed with all movements
1766 // ==========================================================================
1768 locProceedMovingMurphy: // proceed moving murphy
1769 YawnSleepCounter = 0; // Wake up sleeping Murphy
1770 ax = MovingPictureSequencePhase; // sequence busy?
1771 if (ax == 0) // no -- start sequence!
1774 ax = ax - 1; // next picture of sequence
1775 MovingPictureSequencePhase = ax; // store for later
1777 if (ax == 0) // Sound effects
1780 switch (HighByte(PlayField16[*si]))
1784 subSoundFX(*si, fiZonk, actPushing);
1789 subSoundFX(*si, fiOrangeDisk, actPushing);
1796 subSoundFX(*si, fiYellowDisk, actPushing);
1807 bl = HighByte(PlayField16[*si]);
1808 if (bl == 0xE) // Push Zonk to left
1811 if (bl == 0xF) // Push Zonk to right
1814 if (bl == 0x28) // Push orange disk to left
1817 if (bl == 0x29) // Push orange disk to right
1820 if (bl == 0x24) // Push yellow disk up
1823 if (bl == 0x25) // Push yellow disk to left
1826 if (bl == 0x27) // Push yellow disk down
1829 if (bl == 0x26) // Push yellow disk to right
1832 if (bl == 0x2A) // Red disk release timer
1837 // ==========================================================================
1838 // Paint frame of MOVING.DAT sequence
1839 // ==========================================================================
1845 dx1SequenceLength = getSequenceLength(dx1);
1848 if (SplitMoveFlag == 0)
1850 // ++++++++++++++++++++++++++
1851 // Begin of normal movement
1852 MurphyScreenXPos = MurphyScreenXPos + MurphyDX * MurphyZoomFactor;
1853 MurphyScreenYPos = MurphyScreenYPos + MurphyDY * MurphyZoomFactor;
1855 if (!(ClearPos < 0)) // clear field that murphy is leaving
1856 subCopyImageToScreen(ClearPos, aniSpace);
1859 // !!! special two-tile animation currently not used !!!
1860 if (dx2 == fiInfotron) // special case of infotron moving left or right
1868 tDeltaX = MurphyDX * LocalStretch * (SeqPos + 1);
1869 tDeltaY = MurphyDY * LocalStretch * (SeqPos + 1);
1872 X = GetStretchX(dxPos) + tDeltaX;
1873 Y = GetStretchY(dxPos) + tDeltaY;
1874 Tmp = (SeqPos < 0 ? 0 : SeqPos); // 9StepBugFix!(red disk move right)
1877 if (isSnappingSequence(dx1) && SeqPos == dx1SequenceLength - 1)
1882 DDSpriteBuffer_BltImg(X, Y, dx1, Tmp);
1883 GfxGraphic[GetX(*si)][GetY(*si)] = -1; // (Murphy's position)
1884 GfxGraphic[GetX(dxPos)][GetY(dxPos)] = -1; // (snapping position)
1885 // printf("::: Tmp: %d\n", Tmp);
1887 StretchedSprites.BltEx(X, Y, dx[Tmp]);
1896 tPos = dxPos + dx2Step;
1897 X = GetStretchX(tPos);
1898 Y = GetStretchY(tPos);
1900 // !!! special two-tile animation currently not used !!!
1901 if (dx2 == fiInfotron) // special case of infotron moving left or right
1903 StretchedSprites.BltEx(X, Y, dx[SeqPos] + dx2Step);
1905 else // pushing something
1908 // (SeqPos iterates from 0 to 7 while pushing)
1909 DDSpriteBuffer_BltImg(X + tDeltaX, Y + tDeltaY, dx2, SeqPos);
1913 // End of normal movement
1914 // ------------------------
1918 // ++++++++++++++++++++++++++++++++
1919 // Begin of split movement (port)
1920 MurphyScreenXPos = MurphyScreenXPos + 2 * MurphyDX * MurphyZoomFactor;
1921 MurphyScreenYPos = MurphyScreenYPos + 2 * MurphyDY * MurphyZoomFactor;
1922 subCopyImageToScreen(ClearPos, aniSpace); // clear the field that murphy leaves
1923 tDeltaX = MurphyDX * LocalStretch * (SeqPos + 1);
1924 tDeltaY = MurphyDY * LocalStretch * (SeqPos + 1);
1925 X = GetStretchX(dxPos) + tDeltaX;
1926 Y = GetStretchY(dxPos) + tDeltaY;
1927 DDSpriteBuffer_BltImg(X, Y, dx1, SeqPos); // plot first murphy
1929 tPos = dxPos + dx2Step;
1930 X = GetStretchX(tPos);
1931 Y = GetStretchY(tPos);
1932 DDSpriteBuffer_BltImg(X + tDeltaX, Y + tDeltaY, dx1, SeqPos); // plot second murphy
1933 DDSpriteBuffer_BltImg(X, Y, fiGraphic[LowByte(PlayField16[tPos])], 0); // replot the port on top
1934 // End of split movement (port)
1935 // ------------------------------
1936 } // loc_g_6D1E:'loc_g_6D28:
1938 SeqPos = SeqPos + 1;
1940 if (SeqPos < dx1SequenceLength)
1943 if (dx[SeqPos] > -1)
1947 // Follow-up after movement completed 'loc_g_6D35:
1948 MurphyXPos = MurphyXPos + MurphyDX;
1949 MurphyYPos = MurphyYPos + MurphyDY;
1950 bl = HighByte(PlayField16[*si]); // animation phase
1951 MovHighByte(&PlayField16[*si], 0);
1953 if (bl == 0x1) // space, moving up
1956 if (bl == 0x2) // space, moving left
1959 if (bl == 0x3) // space, moving down
1962 if (bl == 0x4) // space, moving right
1965 if (bl == 0x5) // base , moving up
1968 if (bl == 0x6) // base , moving left -> 6 is not used, value is set to 2 instead of 6!
1971 if (bl == 0x7) // base , moving down
1974 if (bl == 0x8) // base , moving right
1977 if (bl == 0x9) // infotron, moving up
1980 if (bl == 0xA) // infotron, moving left
1983 if (bl == 0xB) // infotron, moving down
1986 if (bl == 0xC) // infotron, moving right
1989 if (bl == 0xD) // exit
1992 if (bl == 0xE) // zonk, pushing left
1995 if (bl == 0xF) // zonk, pushing right
1998 if (bl == 0x10) // base , touching up
2001 if (bl == 0x11) // base , touching left
2004 if (bl == 0x12) // base , touching down
2007 if (bl == 0x13) // base , touching right
2010 if (bl == 0x14) // infotron touching up
2013 if (bl == 0x15) // infotron touching left
2016 if (bl == 0x16) // infotron touching down
2019 if (bl == 0x17) // infotron touching right
2022 if (bl == 0x18) // port up
2025 if (bl == 0x19) // port left
2028 if (bl == 0x1A) // port down
2031 if (bl == 0x1B) // port right
2034 if (bl == 0x1C) // red disk, moving up
2037 if (bl == 0x1D) // red disk, moving left
2040 if (bl == 0x1E) // red disk, moving down
2043 if (bl == 0x1F) // red disk, moving right -> 9-Step-Bug!
2046 if (bl == 0x20) // red disk, touching up
2049 if (bl == 0x21) // red disk, touching left
2052 if (bl == 0x22) // red disk, touching down
2055 if (bl == 0x23) // red disk, touching right
2058 if (bl == 0x24) // yellow disk, pushing up
2061 if (bl == 0x25) // yellow disk, pushing left
2064 if (bl == 0x26) // yellow disk, pushing right -> order of "down" exchanged with "right"!
2067 if (bl == 0x27) // yellow disk, pushing down -> order of "down" exchanged with "right"!
2070 if (bl == 0x28) // orange disk, pushing left
2073 if (bl == 0x29) // orange disk, pushing right
2076 if (bl == 0x2A) // red disk, release
2083 // ==========================================================================
2084 // infotron, moving up
2085 // ==========================================================================
2088 if (0 < LowByte(InfotronsNeeded))
2089 InfotronsNeeded = InfotronsNeeded - 1;
2091 loc_g_6EC8: // space, base
2092 PlayField16[*si] = fiMurphy;
2093 subAdjustZonksInfotronsAboveMurphy(*si + FieldWidth);
2097 // ==========================================================================
2098 // infotron, moving left
2099 // ==========================================================================
2102 if (0 < LowByte(InfotronsNeeded))
2103 InfotronsNeeded = InfotronsNeeded - 1;
2105 loc_g_6EE6: // space, base
2106 PlayField16[*si] = fiMurphy;
2107 subAdjustZonksInfotronsAboveMurphy(*si + 1);
2111 // ==========================================================================
2112 // infotron, moving down
2113 // ==========================================================================
2116 if (0 < LowByte(InfotronsNeeded))
2117 InfotronsNeeded = InfotronsNeeded - 1;
2119 loc_g_6F04: // space, base
2120 if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion)
2121 PlayField16[*si - FieldWidth] = 0;
2123 PlayField16[*si] = fiMurphy;
2127 // ==========================================================================
2128 // infotron, moving right
2129 // ==========================================================================
2132 if (0 < LowByte(InfotronsNeeded))
2133 InfotronsNeeded = InfotronsNeeded - 1;
2135 loc_g_71C4: // space, base
2136 subAdjustZonksInfotronsAboveMurphy(*si - 1);
2137 PlayField16[*si] = fiMurphy;
2141 // ==========================================================================
2142 // infotron, touching up
2143 // ==========================================================================
2146 if (0 < LowByte(InfotronsNeeded))
2147 InfotronsNeeded = InfotronsNeeded - 1;
2150 if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion)
2151 PlayField16[*si - FieldWidth] = 0;
2155 // ==========================================================================
2156 // infotron, touching left
2157 // ==========================================================================
2160 if (0 < LowByte(InfotronsNeeded))
2161 InfotronsNeeded = InfotronsNeeded - 1;
2164 if (LowByte(PlayField16[*si - 1]) != fiExplosion)
2165 PlayField16[*si - 1] = 0;
2169 // ==========================================================================
2170 // infotron, touching down
2171 // ==========================================================================
2174 if (0 < LowByte(InfotronsNeeded))
2175 InfotronsNeeded = InfotronsNeeded - 1;
2178 if (LowByte(PlayField16[*si + FieldWidth]) != fiExplosion)
2179 PlayField16[*si + FieldWidth] = 0;
2183 // ==========================================================================
2184 // infotron, touching right
2185 // ==========================================================================
2188 if (0 < LowByte(InfotronsNeeded))
2189 InfotronsNeeded = InfotronsNeeded - 1;
2192 if (LowByte(PlayField16[*si + 1]) != fiExplosion)
2193 PlayField16[*si + 1] = 0;
2197 // ==========================================================================
2198 // zonk, pushing left
2199 // ==========================================================================
2202 if (LowByte(PlayField16[*si]) != fiExplosion)
2203 PlayField16[*si] = 0;
2205 PlayField16[*si - 1] = fiMurphy;
2206 PlayField16[*si - 2] = fiZonk;
2207 subExplodeSnikSnaksBelow(*si - 2);
2212 // ==========================================================================
2213 // zonk, pushing right
2214 // ==========================================================================
2217 if (LowByte(PlayField16[*si]) != fiExplosion)
2218 PlayField16[*si] = 0;
2220 PlayField16[*si + 1] = fiMurphy;
2221 PlayField16[*si + 2] = fiZonk;
2222 subExplodeSnikSnaksBelow(*si + 2);
2227 // ==========================================================================
2229 // ==========================================================================
2235 PlayField16[*si] = fiSpace; // remove Murphy from playfield after exiting
2240 // ==========================================================================
2241 // Push Zonk from right to left
2242 // ==========================================================================
2245 if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiZonk)
2248 PlayField16[*si] = fiMurphy; // else restore - no more zonk pushing!
2249 PlayField16[*si - 1] = fiZonk;
2250 if (LowByte(PlayField16[*si - 2]) != fiExplosion)
2251 PlayField16[*si - 2] = 0;
2253 subCopyImageToScreen(*si, aniMurphy);
2257 // ==========================================================================
2258 // Push Zonk from left to right
2259 // ==========================================================================
2262 if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiZonk)
2265 PlayField16[*si] = fiMurphy; // else restore - no more zonk pushing!
2266 PlayField16[*si + 1] = fiZonk;
2267 if (LowByte(PlayField16[*si + 2]) != fiExplosion)
2268 PlayField16[*si + 2] = 0;
2270 subCopyImageToScreen(*si, aniMurphy);
2274 // ==========================================================================
2275 // Push orange disk from right to left
2276 // ==========================================================================
2279 if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiOrangeDisk)
2282 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2283 PlayField16[*si - 1] = fiOrangeDisk;
2284 if (LowByte(PlayField16[*si - 2]) != fiExplosion)
2285 PlayField16[*si - 2] = 0;
2287 subCopyImageToScreen(*si, aniMurphy);
2291 // ==========================================================================
2292 // Push orange disk from left to right
2293 // ==========================================================================
2296 if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiOrangeDisk)
2299 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2300 PlayField16[*si + 1] = fiOrangeDisk;
2301 if (LowByte(PlayField16[*si + 2]) != fiExplosion)
2302 PlayField16[*si + 2] = 0;
2304 subCopyImageToScreen(*si, aniMurphy);
2308 // ==========================================================================
2309 // Push yellow disk from down to up
2310 // ==========================================================================
2313 if (DemoKeyCode == keyUp && PlayField16[*si - FieldWidth] == fiYellowDisk)
2316 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2317 PlayField16[*si - FieldWidth] = fiYellowDisk;
2318 if (LowByte(PlayField16[*si - 2 * FieldWidth]) != fiExplosion)
2319 PlayField16[*si - 2 * FieldWidth] = 0;
2321 subCopyImageToScreen(*si, aniMurphy);
2325 // ==========================================================================
2326 // Push yellow disk from right to left
2327 // ==========================================================================
2330 if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiYellowDisk)
2333 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2334 PlayField16[*si - 1] = fiYellowDisk;
2335 if (LowByte(PlayField16[*si - 2]) != fiExplosion)
2336 PlayField16[*si - 2] = 0;
2338 subCopyImageToScreen(*si, aniMurphy);
2342 // ==========================================================================
2343 // Push yellow disk from up to down
2344 // ==========================================================================
2347 if (DemoKeyCode == keyDown && PlayField16[*si + FieldWidth] == fiYellowDisk)
2350 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2351 PlayField16[*si + FieldWidth] = fiYellowDisk;
2352 if (LowByte(PlayField16[*si + 2 * FieldWidth]) != fiExplosion)
2353 PlayField16[*si + 2 * FieldWidth] = 0;
2355 subCopyImageToScreen(*si, aniMurphy);
2359 // ==========================================================================
2360 // Push yellow disk from left to right
2361 // ==========================================================================
2364 if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiYellowDisk)
2367 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2368 PlayField16[*si + 1] = fiYellowDisk;
2369 if (LowByte(PlayField16[*si + 2]) != fiExplosion)
2370 PlayField16[*si + 2] = 0;
2372 subCopyImageToScreen(*si, aniMurphy);
2376 // ==========================================================================
2377 // time red disk release (space)
2378 // ==========================================================================
2381 if (DemoKeyCode != keySpace)
2383 PlayField16[*si] = fiMurphy;
2384 subCopyImageToScreen(*si, aniMurphy);
2385 RedDiskReleasePhase = 0;
2387 else if (MovingPictureSequencePhase == 0x20)
2390 // anxious murphy, dropping red disk
2391 subCopyImageToScreen(*si, aniMurphyDropping);
2393 subCopyFieldToScreen(*si, 43); // anxious murphy
2395 RedDiskReleasePhase = 1;
2400 // ==========================================================================
2401 // Special port down to up
2402 // ==========================================================================
2405 if (LowByte(PlayField16[*si]) != fiExplosion)
2406 PlayField16[*si] = 0;
2408 PlayField16[*si - 2 * FieldWidth] = fiMurphy;
2410 *si = *si - FieldWidth;
2411 if (HighByte(PlayField16[*si]) == 1)
2414 *si = *si - FieldWidth;
2418 // ==========================================================================
2419 // Special port right to left
2420 // ==========================================================================
2423 if (LowByte(PlayField16[*si]) != fiExplosion)
2424 PlayField16[*si] = 0;
2426 PlayField16[*si - 2] = fiMurphy;
2429 if (HighByte(PlayField16[*si]) == 1)
2436 // ==========================================================================
2437 // Special port up to down
2438 // ==========================================================================
2441 if (LowByte(PlayField16[*si]) != fiExplosion)
2442 PlayField16[*si] = 0;
2444 PlayField16[*si + 2 * FieldWidth] = fiMurphy;
2446 *si = *si + FieldWidth;
2447 if (HighByte(PlayField16[*si]) == 1)
2450 *si = *si + FieldWidth;
2454 // ==========================================================================
2455 // Special port left to right
2456 // ==========================================================================
2459 if (LowByte(PlayField16[*si]) != fiExplosion)
2460 PlayField16[*si] = 0;
2462 PlayField16[*si + 2] = fiMurphy;
2465 if (HighByte(PlayField16[*si]) == 1)
2472 // ==========================================================================
2474 // ==========================================================================
2477 if (LowByte(PlayField16[*si]) != fiExplosion)
2478 PlayField16[*si] = 0;
2480 *si = *si - FieldWidth;
2481 PlayField16[*si] = fiMurphy;
2482 subEatRedDisk(*si); // inc+show Murphy's red disks
2486 // ==========================================================================
2487 // Move Red Disk left
2488 // ==========================================================================
2491 if (LowByte(PlayField16[*si + 1]) != fiExplosion)
2492 PlayField16[*si + 1] = 0;
2494 PlayField16[*si] = fiMurphy;
2495 subEatRedDisk(*si); // inc+show Murphy's red disks
2499 // ==========================================================================
2500 // Move Red Disk down
2501 // ==========================================================================
2504 if (LowByte(PlayField16[*si]) != fiExplosion)
2505 PlayField16[*si] = 0;
2507 *si = *si + FieldWidth;
2508 PlayField16[*si] = fiMurphy;
2509 subEatRedDisk(*si); // inc+show Murphy's red disks
2513 // ==========================================================================
2514 // Move Red Disk right
2515 // ==========================================================================
2518 if (LowByte(PlayField16[*si - 1]) != fiExplosion)
2519 PlayField16[*si - 1] = 0;
2521 PlayField16[*si] = fiMurphy;
2522 subEatRedDisk(*si); // inc+show Murphy's red disks
2526 // ==========================================================================
2528 // ==========================================================================
2531 if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion)
2532 PlayField16[*si - FieldWidth] = 0;
2534 subEatRedDisk(*si - FieldWidth); // inc+show Murphy's red disks
2538 // ==========================================================================
2539 // Eat Red Disk left
2540 // ==========================================================================
2543 if (LowByte(PlayField16[*si - 1]) != fiExplosion)
2544 PlayField16[*si - 1] = 0;
2546 subEatRedDisk(*si - 1); // inc+show Murphy's red disks
2550 // ==========================================================================
2551 // Eat Red Disk down
2552 // ==========================================================================
2555 if (LowByte(PlayField16[*si + FieldWidth]) != fiExplosion)
2556 PlayField16[*si + FieldWidth] = 0;
2558 subEatRedDisk(*si + FieldWidth); // inc+show Murphy's red disks
2562 // ==========================================================================
2563 // Eat Red Disk right
2564 // ==========================================================================
2567 if (LowByte(PlayField16[*si + 1]) != fiExplosion)
2568 PlayField16[*si + 1] = 0;
2570 subEatRedDisk(*si + 1); // inc+show Murphy's red disks
2574 // ==========================================================================
2575 // yellow disk, pushing up
2576 // ==========================================================================
2579 if (LowByte(PlayField16[*si]) != fiExplosion)
2580 PlayField16[*si] = 0;
2582 *si = *si - FieldWidth;
2583 PlayField16[*si] = fiMurphy;
2584 PlayField16[*si - FieldWidth] = fiYellowDisk;
2588 // ==========================================================================
2589 // yellow disk, pushing left
2590 // ==========================================================================
2593 if (LowByte(PlayField16[*si]) != fiExplosion)
2594 PlayField16[*si] = 0;
2597 PlayField16[*si] = fiMurphy;
2598 PlayField16[*si - 1] = fiYellowDisk;
2602 // ==========================================================================
2603 // yellow disk, pushing down
2604 // ==========================================================================
2607 if (LowByte(PlayField16[*si]) != fiExplosion)
2608 PlayField16[*si] = 0;
2610 *si = *si + FieldWidth;
2611 PlayField16[*si] = fiMurphy;
2612 PlayField16[*si + FieldWidth] = fiYellowDisk;
2616 // ==========================================================================
2617 // yellow disk pushing right
2618 // ==========================================================================
2621 if (LowByte(PlayField16[*si]) != fiExplosion)
2622 PlayField16[*si] = 0;
2625 PlayField16[*si] = fiMurphy;
2626 PlayField16[*si + 1] = fiYellowDisk;
2630 // ==========================================================================
2631 // orange disk, pushing left
2632 // ==========================================================================
2635 if (LowByte(PlayField16[*si]) != fiExplosion)
2636 PlayField16[*si] = 0;
2639 PlayField16[*si] = fiMurphy;
2640 PlayField16[*si - 1] = fiOrangeDisk;
2644 // ==========================================================================
2645 // orange disk, pushing right
2646 // ==========================================================================
2649 if (LowByte(PlayField16[*si]) != fiExplosion)
2650 PlayField16[*si] = 0;
2653 PlayField16[*si] = fiMurphy;
2654 PlayField16[*si + 1] = fiOrangeDisk;
2655 if (PlayField16[*si + FieldWidth + 1] == 0) // make it fall down if below is empty
2657 MovHighByte(&PlayField16[*si + 1], 0x20);
2658 MovHighByte(&PlayField16[*si + FieldWidth + 1], fiOrangeDisk);
2663 // ==========================================================================
2664 // Release a red disk
2665 // ==========================================================================
2668 PlayField16[*si] = fiMurphy;
2669 RedDiskReleasePhase = 2;
2670 RedDiskCount = RedDiskCount - 1;
2673 subSoundFX(*si, fiRedDisk, actDropping);
2675 subSoundFXPush(); // Sound effects
2677 } // subAnimateMurphy
2679 // ==========================================================================
2681 // ==========================================================================
2682 void subExplodeSnikSnaksBelow(int si)
2686 ax = LowByte(PlayField16[si + FieldWidth]);
2687 if (ax == 0x11 || ax == 0xBB)
2688 ExplodeFieldSP(si + FieldWidth);
2689 } // subExplodeSnikSnaksBelow
2691 // ==========================================================================
2693 // Does pushing against an object kill Murphy?
2694 // ==========================================================================
2695 static boolean subMoveKillsMurphy(int si, int ax, int bl)
2697 static boolean subMoveKillsMurphy;
2703 if (ax == 0xFFFF || ax == 0xAAAA || ah == 0)
2709 if (al == fiExplosion)
2712 if (fiOrangeDisk <= al && al <= fiPortUp)
2715 ExplodeFieldSP(si); // Explode
2716 subMoveKillsMurphy = True;
2717 return subMoveKillsMurphy;
2726 ExplodeFieldSP(si); // Explode
2727 subMoveKillsMurphy = True;
2728 return subMoveKillsMurphy;
2730 loc_g_74F6: // zonk left
2732 if (! (ah == 0x20 || ah == 0x40 || ah == 0x50 || ah == 0x70))
2735 subMoveKillsMurphy = True; // Set carry flag
2736 return subMoveKillsMurphy;
2738 loc_g_7512: // zonk right
2740 if (! (ah == 0x30 || ah == 0x40 || ah == 0x60 || ah == 0x70))
2743 loc_g_752E: // Marked fields and Ports
2744 subMoveKillsMurphy = True; // Set carry flag
2745 return subMoveKillsMurphy;
2747 loc_g_7530: // explosion
2748 if ((ah & 0x80) != 0)
2755 ExplodeFieldSP(si); // Explode
2756 subMoveKillsMurphy = True; // Set carry flag
2757 return subMoveKillsMurphy;
2760 PlayField16[si] = 0;
2761 subMoveKillsMurphy = False;
2763 return subMoveKillsMurphy;
2764 } // subMoveKillsMurphy
2766 // ==========================================================================
2768 // Test If si 's a special (grav) port and If so Then fetch new values (see below)
2769 // change conditions to port specs
2770 // The 10-port data base is at data_h_0D28, 10 entries of 6 bytes each:
2771 // (hi),(lo),(gravity),(freeze zonks),(freeze enemies),(unused)
2772 // ==========================================================================
2773 int subSpPortTest(int si)
2780 cx = LInfo.SpecialPortCount; // number of special ports
2782 for (i = 0; i < cx; i++)
2785 /* this assumes that PortLocation is stored as big endian */
2786 bx = LInfo.SpecialPort[i].PortLocation;
2788 /* this assumes that PortLocation is stored as little endian */
2789 bx = HighByte(LInfo.SpecialPort[i].PortLocation);
2790 MovHighByte(&bx, LowByte(LInfo.SpecialPort[i].PortLocation));
2795 GravityFlag = LInfo.SpecialPort[i].Gravity;
2796 FreezeZonks = LInfo.SpecialPort[i].FreezeZonks;
2797 SnikSnaksElectronsFrozen = LInfo.SpecialPort[i].FreezeEnemies;
2799 // RandomTime = RandomTime Xor RandomSeed 'is RandomTime used at all? no!
2807 cx = LInfo.SpecialPortCount; // number of special ports
2808 for (i = 1; i <= cx; i++)
2811 bx = HighByte(LInfo.SpecialPort[i].PortLocation);
2812 MovHighByte(&bx, LowByte(LInfo.SpecialPort[i].PortLocation));
2815 GravityFlag = LInfo.SpecialPort[i].Gravity;
2816 FreezeZonks = LInfo.SpecialPort[i].FreezeZonks;
2817 SnikSnaksElectronsFrozen = LInfo.SpecialPort[i].FreezeEnemies;
2818 // RandomTime = RandomTime Xor RandomSeed 'is RandomTime used at all? no!
2825 return subSpPortTest;
2830 void subCopyFieldToScreen(int si, int fi)
2834 // +++++++++++++++++++++++++++++++++++++++++
2835 X = GetStretchX(si);
2836 Y = GetStretchY(si);
2837 StretchedSprites.BltEx(X, Y, fi);
2838 // +++++++++++++++++++++++++++++++++++++++++
2843 void subCopyAnimToScreen(int si, int graphic, int sync_frame)
2847 // +++++++++++++++++++++++++++++++++++++++++
2848 X = GetStretchX(si);
2849 Y = GetStretchY(si);
2850 DDSpriteBuffer_BltImg(X, Y, graphic, sync_frame);
2851 // +++++++++++++++++++++++++++++++++++++++++
2854 void subCopyImageToScreen(int si, int graphic)
2856 subCopyAnimToScreen(si, graphic, 0);
2859 static void subEatRedDisk(int si)
2861 if (AllowRedDiskCheat == 0)
2863 if (RedDiskReleasePhase != 0)
2865 if (RedDiskReleaseMurphyPos == si)
2870 RedDiskCount = (RedDiskCount + 1) % 256;
2873 void subAdjustZonksInfotronsAboveMurphy(int si)
2877 if (LowByte(PlayField16[si]) != fiExplosion)
2878 PlayField16[si] = 0;
2880 ax = PlayField16[si - FieldWidth];
2881 if (ax == 0 || ax == 0x9999)
2884 if (ax == fiZonk || ax == fiInfotron)
2886 MovHighByte(&PlayField16[si - FieldWidth], 0x40); // make falling straigt down
2891 loc_g_15A8: // empty above
2892 ax = PlayField16[si - FieldWidth - 1];
2893 if (ax == fiZonk || ax == fiInfotron)
2897 ax = PlayField16[si - FieldWidth + 1];
2898 if (ax == fiZonk || ax == fiInfotron)
2903 loc_g_15C5: // zonk/infotron above left
2904 ax = PlayField16[si - 1];
2905 if (! (ax == fiZonk || ax == fiInfotron || ax == fiRAM)) // continue testing right above
2908 MovHighByte(&PlayField16[si - FieldWidth - 1], 0x60); // make roll right
2909 PlayField16[si - FieldWidth] = 0x8888;
2913 loc_g_15E8: // zonk/infotron above right
2914 ax = PlayField16[si + 1];
2915 if (ax == fiZonk || ax == fiInfotron || ax == fiRAM)
2917 MovHighByte(&PlayField16[si - FieldWidth + 1], 0x50); // make roll left
2918 PlayField16[si - FieldWidth] = 0x8888;
2920 } // subAdjustZonksInfotronsAboveMurphy