1 // ----------------------------------------------------------------------------
3 // ----------------------------------------------------------------------------
7 static void subEatRedDisk(int si);
8 static boolean subMoveKillsMurphy(int si, int ax, int bl);
10 // static char *VB_Name = "modMurphy";
12 // --- Option Explicit
16 #define LocalStretch (2)
17 #define MurphyZoomFactor (ZoomFactor)
21 #define LocalStretch (1)
22 #define MurphyZoomFactor (1)
26 // ==========================================================================
28 // Move Murphy in any direction
29 // ==========================================================================
31 int subAnimateMurphy(int *si)
35 // int ax, al, ah, bx, bl, i, X, Y;
36 // int tX, tY, tDeltaX, tDeltaY, tPos, Tmp;
38 int ax, al, bl, i, X, Y;
41 int ax, al, bx, bl, i, X, Y;
43 int tDeltaX, tDeltaY, tPos, Tmp;
45 // Variables that hold information about the animation sequence
46 static int *dx = 0; // an array of image positions in moving.mpx, finalized with -1
47 static int dx2 = 0; // an additional image position of a second sprite, for instance: yellow disk if pushed
48 static int MurphyDX = 0, MurphyDY = 0; // murphys move steps
49 static int SeqPos = 0; // index into dx()
50 static int ClearPos = 0; // Position to clear before blitting sprites, none=-1
51 static int dxPos = 0; // field-position to draw dx(SeqPos)
52 static int dx2Step = 0; // position of dx2 relative to dx-position
54 ax = PlayField16[*si];
58 printf("::: Murphy.c: subAnimateMurphy(): %d [%d, %d] %d, %d [%d]\n",
59 *si, *si % 60, *si / 60, ax, al, (al == fiMurphy));
63 printf("::: Murphy.c: subAnimateMurphy(): %d [%d] [%d]\n",
64 YawnSleepCounter, FrameCounter, TimerVar);
69 MurphyMoveCounter = 0; // We have no Murphy! Exit!
70 return subAnimateMurphy;
73 MurphyMoveCounter = 1; // We have a Murphy!
74 MurphyExplodePos = *si;
75 if (ax != 3) // yes--go proceed moving murphy?
76 goto locProceedMovingMurphy;
78 // FS: reset moving sequence variables
86 ScratchGravity = 0; // scratch gravity off
87 if (GravityFlag != 0) // Gravity? (1=gravity on)
89 bl = LowByte(PlayField16[*si - FieldWidth]); // check above
90 if (! (bl == fiPortUp || bl == fiPortUpAndDown || bl == fiPortAllDirections))
92 if (PlayField16[*si + FieldWidth] == 0) // gravity on and space below!
98 if (bl != 0) // a key was pressed!
99 goto locKeyPressed5FCF;
102 printf("::: Murphy.c: !!! %d [%d]\n", DemoKeyCode, GravityFlag);
105 RedDiskReleaseFlag = 1;
106 if (ScratchGravity != 0) // gravity pulls & space below?'-> force Space up to down
117 return subAnimateMurphy;
120 // ------------------------------------------------------------------
121 // Murphy's YAWN & SLEEP sequence, counted down by YawnSleepCounter:
123 YawnSleepCounter = YawnSleepCounter + 1;
125 if (YawnSleepCounter < 16)
126 return subAnimateMurphy;
128 if (YawnSleepCounter < 2000)
131 // (default: single graphic, no animation)
132 subCopyImageToScreen(*si, aniMurphy, YawnSleepCounter - 16);
134 return subAnimateMurphy;
137 if (YawnSleepCounter < 4000)
139 // yawn! and look depressed afterwards...
140 // (default: 12 animation frames with delay of 8)
141 subCopyImageToScreen(*si, aniMurphyYawn, YawnSleepCounter - 2000);
143 return subAnimateMurphy;
146 if (YawnSleepCounter < 6400)
149 // (default: 12 animation frames with delay of 8)
150 subCopyImageToScreen(*si, aniMurphyYawn, YawnSleepCounter - 4000);
152 return subAnimateMurphy;
155 // time1 = 6400 + 12 * 8; // (default: 6496 == 6400 + 12 * 8)
156 time1 = 6400 + 12 * 10;
158 if (YawnSleepCounter < time1)
160 // yawn again! - third time
161 // (default: 12 animation frames with delay of 8)
162 subCopyImageToScreen(*si, aniMurphyYawn, YawnSleepCounter - 6400);
164 return subAnimateMurphy;
167 // time2 = 6496 + 3 * 64; // (default: 6688 == 6496 + 3 * 64)
168 time2 = 6496 + 3 * 100;
170 if (YawnSleepCounter > time2) // Murphy already went to sleep
171 return subAnimateMurphy;
173 if (PlayField16[*si - 1] == 0)
175 if (PlayField16[*si + 1] == 0)
177 // no sleep -- go back to "wait and start yawning" phase
178 YawnSleepCounter = 144;
180 return subAnimateMurphy;
184 // go to sleep (right side)
185 // (default: 3 animation frames with delay of 64)
186 subCopyImageToScreen(*si, aniMurphySleepRight, YawnSleepCounter - time1);
188 return subAnimateMurphy;
192 // go to sleep (left side)
193 // (default: 3 animation frames with delay of 64)
194 subCopyImageToScreen(*si, aniMurphySleepLeft, YawnSleepCounter - time1);
196 return subAnimateMurphy;
198 // end of YAWN-SLEEP-Sequence
204 return subAnimateMurphy;
206 // ------------------------------------------------------------------
207 // Murphy's YAWN & SLEEP sequence, counted down by YawnSleepCounter:
208 YawnSleepCounter = YawnSleepCounter + 1;
209 if (YawnSleepCounter == 4)
211 subCopyFieldToScreen(*si, fiMurphy); // normal grin
212 return subAnimateMurphy;
215 if (YawnSleepCounter <= 500) // loc_g_5ED7:
216 return subAnimateMurphy;
218 if (YawnSleepCounter <= 522)
220 bx = (YawnSleepCounter - 500) / 2;
221 subCopyFieldToScreen(*si, aniMurphyYawn + bx); // yawn! and look depressed afterwards...
222 return subAnimateMurphy;
225 if (YawnSleepCounter <= 1000)
226 return subAnimateMurphy;
228 if (YawnSleepCounter <= 1022)
230 bx = (YawnSleepCounter - 1000) / 2;
231 subCopyFieldToScreen(*si, aniMurphyYawn + bx); // yawn again!
232 return subAnimateMurphy;
235 if (YawnSleepCounter <= 1600) // loc_g_5F3B:
236 return subAnimateMurphy;
238 if (YawnSleepCounter <= 1622)
240 bx = (YawnSleepCounter - 1600) / 2;
241 subCopyFieldToScreen(*si, aniMurphyYawn + bx); // yawn again! - third time
242 return subAnimateMurphy;
245 if (YawnSleepCounter > 1654)
246 return subAnimateMurphy;
248 if (PlayField16[*si - 1] == 0)
250 if (PlayField16[*si + 1] == 0)
252 YawnSleepCounter = 36;
253 return subAnimateMurphy;
258 bx = (YawnSleepCounter - 1622) / 16;
259 subCopyFieldToScreen(*si, aniMurphySleepRight + bx); // go to sleep
260 return subAnimateMurphy;
264 bx = (YawnSleepCounter - 1622) / 16;
265 subCopyFieldToScreen(*si, aniMurphySleepLeft + bx); // go to sleep
267 return subAnimateMurphy;
269 // end of YAWN-SLEEP-Sequence
273 // ------------------------------------------------------------------
274 // ==========================================================================
275 // (Direct Jump) a key was pressed
276 // ==========================================================================
279 if (ScratchGravity == 0)
282 if (PlayField16[*si + FieldWidth] != 0)
287 if (PlayField16[*si - FieldWidth] == fiBase)
291 else if (bl == keyLeft)
293 if (PlayField16[*si - 1] == fiBase)
297 else if (bl == keyRight)
299 if (PlayField16[*si + 1] == fiBase)
303 bl = keyDown; // force moving down!
308 RedDiskReleaseFlag = 0; // moving down to up ...
314 RedDiskReleaseFlag = 0; // moving right to left ...
320 RedDiskReleaseFlag = 0; // moving up to down ...
326 RedDiskReleaseFlag = 0; // moving left to right ...
331 case keySpaceUp: // 5
332 RedDiskReleaseFlag = 0; // touching down to up ...
337 case keySpaceLeft: // 6
338 RedDiskReleaseFlag = 0; // touching right to left ...
343 case keySpaceDown: // 7
344 RedDiskReleaseFlag = 0; // touching up to down ...
349 case keySpaceRight: // 8
350 RedDiskReleaseFlag = 0; // touching left to right ...
356 goto loc_g_62E2; // no move ...
361 RedDiskReleaseFlag = 0;
362 return subAnimateMurphy;
366 // ==========================================================================
367 // moving down to up ...
368 // ==========================================================================
374 ax = PlayField16[*si - FieldWidth];
385 if (ax == fiInfotron)
391 if (al == fiTerminal)
394 if (al == fiPortUp || al == fiPortUpAndDown || al == fiPortAllDirections)
400 if (al == fiYellowDisk)
403 if (! subMoveKillsMurphy(*si - FieldWidth, ax, bl))
406 return subAnimateMurphy;
408 // ==========================================================================
409 // moving right to left ...
410 // ==========================================================================
416 MurphyVarFaceLeft = 1;
417 ax = PlayField16[*si - 1];
428 if (ax == fiInfotron)
437 if (al == fiTerminal)
440 if (al == fiPortLeft || al == fiPortLeftAndRight || al == fiPortAllDirections)
446 if (ax == fiYellowDisk)
449 if (ax == fiOrangeDisk)
452 if (! subMoveKillsMurphy(*si - 1, ax, bl))
455 return subAnimateMurphy;
457 // ==========================================================================
458 // moving up to down ...
459 // ==========================================================================
465 ax = PlayField16[*si + FieldWidth];
476 if (ax == fiInfotron)
482 if (al == fiTerminal)
485 if (al == fiPortDown || al == fiPortUpAndDown || al == fiPortAllDirections)
491 if (al == fiYellowDisk)
494 if (! subMoveKillsMurphy(*si + FieldWidth, ax, bl))
497 return subAnimateMurphy;
499 // ==========================================================================
500 // moving left to right ...
501 // ==========================================================================
507 MurphyVarFaceLeft = 0;
508 ax = PlayField16[*si + 1];
519 if (ax == fiInfotron)
528 if (al == fiTerminal)
531 if (al == fiPortRight || al == fiPortLeftAndRight || al == fiPortAllDirections)
537 if (al == fiYellowDisk)
540 if (ax == fiOrangeDisk)
543 if (! subMoveKillsMurphy(*si + 1, ax, bl))
546 return subAnimateMurphy;
548 // ==========================================================================
549 // touching down to up ...
550 // ==========================================================================
555 dxPos = *si - FieldWidth;
557 ax = PlayField16[*si - FieldWidth];
566 if (ax == fiInfotron)
569 if (al == fiTerminal)
575 return subAnimateMurphy;
577 // ==========================================================================
578 // touching right to left ...
579 // ==========================================================================
586 MurphyVarFaceLeft = 1;
587 ax = PlayField16[*si - 1];
595 if (ax == fiInfotron)
598 if (al == fiTerminal)
604 return subAnimateMurphy;
606 // ==========================================================================
607 // touching up to down ...
608 // ==========================================================================
613 dxPos = *si + FieldWidth;
615 ax = PlayField16[*si + FieldWidth];
623 if (ax == fiInfotron)
626 if (al == fiTerminal)
632 return subAnimateMurphy;
634 // ==========================================================================
635 // touching left to right ...
636 // ==========================================================================
643 MurphyVarFaceLeft = 0;
644 ax = PlayField16[*si + 1];
652 if (ax == fiInfotron)
655 if (al == fiTerminal)
661 return subAnimateMurphy;
663 // ==========================================================================
664 // Release Red disk: no move ...
665 // ==========================================================================
671 if (LowByte(RedDiskCount) == 0)
672 return subAnimateMurphy;
674 if (LowByte(RedDiskReleasePhase) != 0)
675 return subAnimateMurphy;
677 if (LowByte(RedDiskReleaseFlag) != 1)
678 return subAnimateMurphy;
680 MovHighByte(&PlayField16[*si], 0x2A);
681 MovingPictureSequencePhase = 0x40; // init picture move sequence
683 MovLowByte(&RedDiskReleasePhase, 1);
684 Mov(&RedDiskReleaseMurphyPos, *si); // remember Murphy's location
687 // ==========================================================================
688 // SPACE moving down to up
689 // ==========================================================================
692 dx = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
693 PlayField16[*si - FieldWidth] = 0x103;
694 PlayField16[*si] = 0x300;
695 *si = *si - FieldWidth;
696 goto loc_StopNoSplit;
698 // ==========================================================================
699 // SPACE moving right to left
700 // ==========================================================================
703 dx = aniMurphyEatLeft;
704 PlayField16[*si - 1] = 0x203;
705 PlayField16[*si] = 0x300;
707 goto loc_StopNoSplit;
709 // ==========================================================================
710 // SPACE moving up to down, and when gravity is pulling!
711 // ==========================================================================
714 dx = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
715 PlayField16[*si + FieldWidth] = 0x303;
716 PlayField16[*si] = 0x300;
717 *si = *si + FieldWidth;
718 goto loc_StopNoSplit;
720 // ==========================================================================
721 // SPACE moving left to right
722 // ==========================================================================
725 dx = aniMurphyEatRight;
726 PlayField16[*si + 1] = 0x403;
727 PlayField16[*si] = 0x300;
729 goto loc_StopNoSplit;
731 // ==========================================================================
732 // BUG moving down to up
733 // ==========================================================================
736 if (SgnHighByte(PlayField16[*si - FieldWidth]) >= 0)
738 ExplodeFieldSP(*si); // Explode
739 return subAnimateMurphy;
742 PlayField16[*si - FieldWidth] = fiBase;
743 // ==========================================================================
744 // BASE moving down to up
745 // ==========================================================================
749 dx = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
750 PlayField16[*si - FieldWidth] = 0x503;
751 PlayField16[*si] = 0x300;
752 *si = *si - FieldWidth;
753 goto loc_StopNoSplit;
755 // ==========================================================================
756 // BUG moving right to left
757 // ==========================================================================
760 if (SgnHighByte(PlayField16[*si - 1]) >= 0)
762 ExplodeFieldSP(*si); // Explode
763 return subAnimateMurphy;
766 PlayField16[*si - 1] = fiBase;
767 // ==========================================================================
768 // BASE moving right to left
769 // ==========================================================================
773 dx = aniMurphyEatLeft;
774 PlayField16[*si - 1] = 0x203;
775 PlayField16[*si] = 0x300;
777 goto loc_StopNoSplit;
779 // ==========================================================================
780 // BUG moving up to down
781 // ==========================================================================
784 if (SgnHighByte(PlayField16[*si + FieldWidth]) >= 0)
786 ExplodeFieldSP(*si); // Explode
787 return subAnimateMurphy;
790 PlayField16[*si + FieldWidth] = fiBase;
791 // ==========================================================================
792 // BASE moving up to down
793 // ==========================================================================
797 dx = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
798 PlayField16[*si + FieldWidth] = 0x703;
799 PlayField16[*si] = 0x300;
800 *si = *si + FieldWidth;
801 goto loc_StopNoSplit;
803 // ==========================================================================
804 // BUG moving left to right
805 // ==========================================================================
808 if (SgnHighByte(PlayField16[*si + 1]) >= 0)
810 ExplodeFieldSP(*si); // Explode
811 return subAnimateMurphy;
814 PlayField16[*si + 1] = fiBase;
815 // ==========================================================================
816 // BASE moving left to right
817 // ==========================================================================
821 dx = aniMurphyEatRight;
822 PlayField16[*si + 1] = 0x803;
823 PlayField16[*si] = 0x300;
825 goto loc_StopNoSplit;
827 // ==========================================================================
828 // BUG touching down to up
829 // ==========================================================================
832 if (SgnHighByte(PlayField16[*si - FieldWidth]) >= 0)
834 ExplodeFieldSP(*si); // Explode
835 return subAnimateMurphy;
838 PlayField16[*si - FieldWidth] = fiBase;
839 // ==========================================================================
840 // BASE touching down to up
841 // ==========================================================================
844 subCopyFieldToScreen(*si, aniMurphyTouchUp);
847 dxPos = *si - FieldWidth;
848 MovHighByte(&PlayField16[*si], 0x10);
849 goto loc_StopNoSplit;
851 // ==========================================================================
852 // BUG touching right to left
853 // ==========================================================================
856 if (SgnHighByte(PlayField16[*si - 1]) >= 0)
858 ExplodeFieldSP(*si); // Explode
859 return subAnimateMurphy;
862 PlayField16[*si - 1] = fiBase;
863 // ==========================================================================
864 // BASE touching right to left
865 // ==========================================================================
868 subCopyFieldToScreen(*si, aniMurphyTouchLeft);
872 MovHighByte(&PlayField16[*si], 0x11);
873 goto loc_StopNoSplit;
875 // ==========================================================================
876 // BUG touching up to down
877 // ==========================================================================
880 if (SgnHighByte(PlayField16[*si + FieldWidth]) >= 0)
882 ExplodeFieldSP(*si); // Explode
883 return subAnimateMurphy;
886 PlayField16[*si + FieldWidth] = fiBase;
887 // ==========================================================================
888 // BASE touching up to down
889 // ==========================================================================
892 subCopyFieldToScreen(*si, aniMurphyTouchDown);
895 dxPos = *si + FieldWidth;
896 MovHighByte(&PlayField16[*si], 0x12);
897 goto loc_StopNoSplit;
899 // ==========================================================================
900 // BUG touching left to right
901 // ==========================================================================
904 if (SgnHighByte(PlayField16[*si + 1]) >= 0)
906 ExplodeFieldSP(*si); // Explode
907 return subAnimateMurphy;
910 PlayField16[*si + 1] = fiBase;
911 // ==========================================================================
912 // BASE touching left to right
913 // ==========================================================================
916 subCopyFieldToScreen(*si, aniMurphyTouchRight);
920 MovHighByte(&PlayField16[*si], 0x13);
921 goto loc_StopNoSplit;
923 // ==========================================================================
924 // INFOTRON moving down to up
925 // ==========================================================================
928 subSoundFXInfotron();
929 dx = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
930 PlayField16[*si - FieldWidth] = 0x903;
931 PlayField16[*si] = 0x300;
932 *si = *si - FieldWidth;
933 goto loc_StopNoSplit;
935 // ==========================================================================
936 // INFOTRON moving right to left
937 // ==========================================================================
940 subSoundFXInfotron();
941 dx = aniEatInfotronLeft;
945 PlayField16[*si - 1] = 0xA03;
946 PlayField16[*si] = 0x300;
948 goto loc_StopNoSplit;
950 // ==========================================================================
951 // INFOTRON moving up to down
952 // ==========================================================================
955 subSoundFXInfotron();
956 dx = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
957 PlayField16[*si + FieldWidth] = 0xB03;
958 PlayField16[*si] = 0x300;
959 *si = *si + FieldWidth;
960 goto loc_StopNoSplit;
962 // ==========================================================================
963 // INFOTRON moving left to right
964 // ==========================================================================
967 subSoundFXInfotron();
968 dx = aniEatInfotronRight;
972 PlayField16[*si + 1] = 0xC03;
973 PlayField16[*si] = 0x300;
975 goto loc_StopNoSplit;
977 // ==========================================================================
978 // INFOTRON touching down to up
979 // ==========================================================================
982 subCopyFieldToScreen(*si, aniMurphyTouchUp);
983 subSoundFXInfotron();
984 dx = aniTouchInfotron;
985 MovHighByte(&PlayField16[*si], 0x14);
986 MovHighByte(&PlayField16[*si - FieldWidth], 0xFF);
987 goto loc_StopNoSplit;
989 // ==========================================================================
990 // INFOTRON touching right to left
991 // ==========================================================================
994 subCopyFieldToScreen(*si, aniMurphyTouchLeft);
995 subSoundFXInfotron();
996 dx = aniTouchInfotron;
997 MovHighByte(&PlayField16[*si], 0x15);
998 MovHighByte(&PlayField16[*si - 1], 0xFF);
999 goto loc_StopNoSplit;
1001 // ==========================================================================
1002 // INFOTRON touching up to down
1003 // ==========================================================================
1006 subCopyFieldToScreen(*si, aniMurphyTouchDown);
1007 subSoundFXInfotron();
1008 dx = aniTouchInfotron;
1009 MovHighByte(&PlayField16[*si], 0x16);
1010 MovHighByte(&PlayField16[*si + FieldWidth], 0xFF);
1011 goto loc_StopNoSplit;
1013 // ==========================================================================
1014 // INFOTRON touching left to right
1015 // ==========================================================================
1018 subCopyFieldToScreen(*si, aniMurphyTouchRight);
1019 subSoundFXInfotron();
1020 dx = aniTouchInfotron;
1021 MovHighByte(&PlayField16[*si], 0x17);
1022 MovHighByte(&PlayField16[*si + 1], 0xFF);
1023 goto loc_StopNoSplit;
1025 // ==========================================================================
1026 // EXIT pressed from any direction
1027 // ==========================================================================
1035 if (LowByte(InfotronsNeeded) != 0)
1036 return subAnimateMurphy;
1039 if (!game_sp_info.LevelSolved)
1040 printf("::: Murphy.c: !!!!!!!!!! LEVEL %d SOLVED !!!!!!!!!!\n",LevelNumber);
1044 game_sp_info.LevelSolved = TRUE;
1048 data_h_DemoDone = 1; // EP set level success bytes
1049 LevelStatus = 1; // set Level Status DONE
1050 EP_GameDemoVar0DAA = 0; // force demo for lead-out
1051 if (SavedGameFlag == 0) // saved game running?
1053 if (UpdateTimeFlag != 0) // update time?
1055 UpdatedFlag = 1; // prevent double update
1056 subUpdatePlayingTime(); // update playing time
1061 subUpdateHallOfFame(); // update time + Hall-Of-Fame
1064 LeadOutCounter = 0x40; // quit: start lead-out
1066 MovHighByte(&PlayField16[*si], 0xD);
1067 goto loc_StopNoSplit;
1069 // ==========================================================================
1070 // ZONK moving right to left
1071 // ==========================================================================
1074 ax = PlayField16[*si - 2];
1076 return subAnimateMurphy;
1078 MovHighByte(&PlayField16[*si - 2], 1);
1079 subCopyFieldToScreen(*si, aniPushLeft); // draw pushing murphy
1080 dx = aniZonkRollLeft;
1084 MovHighByte(&PlayField16[*si], 0xE);
1085 goto loc_MoveNoSplit;
1087 // ==========================================================================
1088 // ZONK moving left to right
1089 // ==========================================================================
1092 ax = PlayField16[*si + 2];
1094 return subAnimateMurphy;
1096 ax = PlayField16[*si + FieldWidth + 1];
1097 if (ax == 0) // zonk falls
1098 return subAnimateMurphy;
1100 MovHighByte(&PlayField16[*si + 2], 1);
1101 subCopyFieldToScreen(*si, aniPushRight); // draw pushing murphy
1102 dx = aniZonkRollRight;
1106 MovHighByte(&PlayField16[*si], 0xF);
1107 goto loc_MoveNoSplit;
1109 // ==========================================================================
1110 // TERMINAL moving/touching down to up
1111 // ==========================================================================
1114 subCopyFieldToScreen(*si, aniMurphyTouchUp);
1115 if (YellowDisksExploded != 0)
1117 YawnSleepCounter = 40; // stay hypnotized
1118 return subAnimateMurphy;
1121 subCopyFieldToScreen(*si - FieldWidth, 0x88); // draw new terminal type
1122 TerminalState[*si - FieldWidth] = 8;
1125 // ==========================================================================
1126 // TERMINAL moving/touching right to left
1127 // ==========================================================================
1130 subCopyFieldToScreen(*si, aniMurphyTouchLeft);
1131 if (YellowDisksExploded != 0)
1133 YawnSleepCounter = 40; // stay hypnotized
1134 return subAnimateMurphy;
1137 subCopyFieldToScreen(*si - 1, 0x88); // draw new terminal type
1138 TerminalState[*si - 1] = 8;
1141 // ==========================================================================
1142 // TERMINAL moving/touching up to down
1143 // ==========================================================================
1146 subCopyFieldToScreen(*si, aniMurphyTouchDown);
1147 if (YellowDisksExploded != 0)
1149 YawnSleepCounter = 40; // stay hypnotized
1150 return subAnimateMurphy;
1153 subCopyFieldToScreen(*si + FieldWidth, 0x88); // draw new terminal type
1154 TerminalState[*si + FieldWidth] = 8;
1157 // ==========================================================================
1158 // TERMINAL moving/touching left to right
1159 // ==========================================================================
1162 subCopyFieldToScreen(*si, aniMurphyTouchRight);
1163 if (YellowDisksExploded != 0)
1165 YawnSleepCounter = 40; // stay hypnotized
1166 return subAnimateMurphy;
1169 subCopyFieldToScreen(*si + 1, 0x88); // draw new terminal type
1170 TerminalState[*si + 1] = 8;
1171 // ==========================================================================
1172 // common TERMINAL stuff moving/touching from all directions
1173 // ==========================================================================
1176 TerminalMaxCycles = 7;
1177 YellowDisksExploded = 1;
1178 for (i = 0; i <= LevelMax; i++)
1180 if (PlayField16[i] == fiYellowDisk)
1184 return subAnimateMurphy;
1186 // ==========================================================================
1187 // PORT down to up, VERTICAL PORT, CROSS PORT all moving down to up
1188 // ==========================================================================
1191 if (PlayField16[*si - 2 * FieldWidth] != 0)
1192 return subAnimateMurphy;
1194 dx = aniSplitUpDown;
1195 dx2Step = -FieldWidth;
1196 PlayField16[*si] = 0x1803;
1197 PlayField16[*si - 2 * FieldWidth] = 0x300;
1200 // ==========================================================================
1201 // PORT right to left, HORIZONTAL PORT, CROSS PORT all moving right to left
1202 // ==========================================================================
1205 if (PlayField16[*si - 2] != 0)
1206 return subAnimateMurphy;
1208 dx = aniMurphyEatLeft;
1210 PlayField16[*si] = 0x1903;
1211 PlayField16[*si - 2] = 0x300;
1214 // ==========================================================================
1215 // PORT up to down, VERTICAL PORT, CROSS PORT all moving up to down
1216 // ==========================================================================
1219 if (PlayField16[*si + 2 * FieldWidth] != 0)
1220 return subAnimateMurphy;
1222 dx = aniSplitUpDown;
1223 dx2Step = FieldWidth;
1224 PlayField16[*si] = 0x1A03;
1225 PlayField16[*si + 2 * FieldWidth] = 0x300;
1228 // ==========================================================================
1229 // PORT left to right, HORIZONTAL PORT, CROSS PORT all moving left to right
1230 // ==========================================================================
1233 if (PlayField16[*si + 2] != 0)
1234 return subAnimateMurphy;
1236 dx = aniMurphyEatRight;
1238 PlayField16[*si] = 0x1B03;
1239 PlayField16[*si + 2] = 0x300;
1242 MovingPictureSequencePhase = 0; // stop picture move sequence
1243 SplitMoveFlag = 1; // port: split movement
1246 // ==========================================================================
1247 // RED DISK moving down to up
1248 // ==========================================================================
1251 dx = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
1252 PlayField16[*si] = 0x1C03;
1253 PlayField16[*si - FieldWidth] = 0x300;
1254 goto loc_StopNoSplit;
1256 // ==========================================================================
1257 // RED DISK moving right to left
1258 // ==========================================================================
1261 dx = aniMurphyEatLeft;
1262 PlayField16[*si] = 0x300; // !!!!!! this time we move murphy at sequence-start!
1263 PlayField16[*si - 1] = 0x1D03;
1265 goto loc_StopNoSplit;
1267 // ==========================================================================
1268 // RED DISK moving up to down
1269 // ==========================================================================
1272 dx = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
1273 PlayField16[*si] = 0x1E03;
1274 PlayField16[*si + FieldWidth] = 0x300;
1275 goto loc_StopNoSplit;
1277 // ==========================================================================
1278 // RED DISK moving left to right
1279 // ==========================================================================
1282 // dx = aniMurphyEatRightRedDisk 'this sequence is 9 steps long!
1283 dx = aniMurphyEatRight;
1284 // --------------------------------------------------------------------------
1286 // Table data_h_145A, pointed to by table data_h_105E, has a severe bug:
1287 // The Red Disk sequence is 8 pictures long, but 9 are displayed, because it
1288 // has 1 extra entry, which causes Murphy to end slightly shifted to the left!
1289 // We may not fix the table, because then the timing of the game changes
1290 // and several existing demo's do not run properly anymore.
1291 // We only correct Murphies x-location here, when the sequence starts.
1292 // Remember that this is not the real bug-fix, but we must live with
1293 // this existing bug and correct for the consequences of it.
1296 if (0 == AllowEatRightRedDiskBug) // Murphy's screen x-position
1297 MurphyScreenXPos = MurphyScreenXPos - 2 * MurphyZoomFactor;
1299 if (0 == AllowEatRightRedDiskBug) // Murphy's screen x-position
1300 MurphyScreenXPos = MurphyScreenXPos - 2;
1304 // FS: for me this means to blit the first animation frame twice
1306 // --------------------------------------------------------------------------
1307 PlayField16[*si] = 0x300; // !!!!!! this time we move murphy at sequence-start!
1308 PlayField16[*si + 1] = 0x1F03;
1310 goto loc_StopNoSplit;
1312 // ==========================================================================
1313 // RED DISK touching down to up
1314 // ==========================================================================
1317 dx = aniTouchRedDisk;
1318 MovHighByte(&PlayField16[*si], 0x20);
1319 MovHighByte(&PlayField16[*si - FieldWidth], 3);
1320 goto loc_StopNoSplit;
1322 // ==========================================================================
1323 // RED DISK touching right to left
1324 // ==========================================================================
1327 dx = aniTouchRedDisk;
1328 MovHighByte(&PlayField16[*si], 0x21);
1329 MovHighByte(&PlayField16[*si - 1], 3);
1330 goto loc_StopNoSplit;
1332 // ==========================================================================
1333 // RED DISK touching up to down
1334 // ==========================================================================
1337 dx = aniTouchRedDisk;
1338 MovHighByte(&PlayField16[*si], 0x22);
1339 MovHighByte(&PlayField16[*si + FieldWidth], 3);
1340 goto loc_StopNoSplit;
1342 // ==========================================================================
1343 // RED DISK touching left to right
1344 // ==========================================================================
1347 dx = aniTouchRedDisk;
1348 MovHighByte(&PlayField16[*si], 0x23);
1349 MovHighByte(&PlayField16[*si + 1], 3);
1352 MovingPictureSequencePhase = 0; // stop picture move sequence
1355 // ==========================================================================
1356 // YELLOW DISK moving down to up
1357 // ==========================================================================
1360 if (PlayField16[*si - 2 * FieldWidth] != 0)
1361 return subAnimateMurphy;
1363 PlayField16[*si - 2 * FieldWidth] = 0x1200;
1364 subCopyFieldToScreen(*si, aniPushRight);
1366 dxPos = *si - FieldWidth;
1367 dx2 = aniPushUpDown;
1368 dx2Step = FieldWidth;
1369 PlayField16[*si] = 0x2403;
1370 goto loc_MoveNoSplit;
1372 // ==========================================================================
1373 // YELLOW DISK moving right to left
1374 // ==========================================================================
1377 if (PlayField16[*si - 2] != 0)
1378 return subAnimateMurphy;
1380 PlayField16[*si - 2] = 0x1200;
1381 subCopyFieldToScreen(*si, aniPushLeft);
1386 PlayField16[*si] = 0x2503;
1387 goto loc_MoveNoSplit;
1389 // ==========================================================================
1390 // YELLOW DISK moving up to down
1391 // ==========================================================================
1394 if (PlayField16[*si + 2 * FieldWidth] != 0)
1395 return subAnimateMurphy;
1397 PlayField16[*si + 2 * FieldWidth] = 0x1200;
1398 subCopyFieldToScreen(*si, aniPushRight);
1400 dxPos = *si + FieldWidth;
1401 dx2 = aniPushUpDown;
1402 dx2Step = -FieldWidth;
1403 PlayField16[*si] = 0x2703;
1404 goto loc_MoveNoSplit;
1406 // ==========================================================================
1407 // YELLOW DISK moving left to right
1408 // ==========================================================================
1411 if (PlayField16[*si + 2] != 0)
1412 return subAnimateMurphy;
1414 PlayField16[*si + 2] = 0x1200;
1415 subCopyFieldToScreen(*si, aniPushRight);
1420 PlayField16[*si] = 0x2603;
1421 goto loc_MoveNoSplit;
1423 // ==========================================================================
1424 // ORANGE DISK moving right to left
1425 // ==========================================================================
1428 if (PlayField16[*si - 2] != 0)
1429 return subAnimateMurphy;
1431 PlayField16[*si - 2] = 0x800;
1432 subCopyFieldToScreen(*si, aniPushLeft);
1437 PlayField16[*si] = 0x2803;
1438 goto loc_MoveNoSplit;
1440 // ==========================================================================
1441 // ORANGE DISK moving left to right
1442 // ==========================================================================
1445 if (PlayField16[*si + 2] != 0)
1446 return subAnimateMurphy;
1448 if (PlayField16[*si + FieldWidth + 1] == 0) // falling goes before pushing
1449 return subAnimateMurphy;
1451 PlayField16[*si + 2] = 0x100;
1452 subCopyFieldToScreen(*si, aniPushRight);
1457 PlayField16[*si] = 0x2903;
1458 // ==========================================================================
1459 // Copy screen animation action table to action work space
1460 // (To paint sequence: Push Zonk/Disk / release red disk / Port passing)
1461 // ==========================================================================
1464 MovingPictureSequencePhase = 8; // init picture move sequence
1467 SplitMoveFlag = 0; // no port: no split movement
1470 // copy/store global move sequence info????????????????????????????????????
1471 // ... dont think so ...(FS)
1472 // ==========================================================================
1473 // Proceed with all movements
1474 // ==========================================================================
1476 locProceedMovingMurphy: // proceed moving murphy
1477 YawnSleepCounter = 0; // Wake up sleeping Murphy
1478 ax = MovingPictureSequencePhase; // sequence busy?
1479 if (ax == 0) // no -- start sequence!
1482 ax = ax - 1; // next picture of sequence
1483 MovingPictureSequencePhase = ax; // store for later
1484 if (ax == 0) // Sound effects
1487 bl = HighByte(PlayField16[*si]);
1488 if (bl == 0xE) // Push Zonk to left
1491 if (bl == 0xF) // Push Zonk to right
1494 if (bl == 0x28) // Push orange disk to left
1497 if (bl == 0x29) // Push orange disk to right
1500 if (bl == 0x24) // Push yellow disk up
1503 if (bl == 0x25) // Push yellow disk to left
1506 if (bl == 0x27) // Push yellow disk down
1509 if (bl == 0x26) // Push yellow disk to right
1512 if (bl == 0x2A) // Red disk release timer
1515 return subAnimateMurphy;
1517 // ==========================================================================
1518 // Paint frame of MOVING.DAT sequence
1519 // ==========================================================================
1522 if (SplitMoveFlag == 0)
1524 // ++++++++++++++++++++++++++
1525 // Begin of normal movement
1527 MurphyScreenXPos = MurphyScreenXPos + MurphyDX * MurphyZoomFactor;
1528 MurphyScreenYPos = MurphyScreenYPos + MurphyDY * MurphyZoomFactor;
1530 MurphyScreenXPos = MurphyScreenXPos + MurphyDX;
1531 MurphyScreenYPos = MurphyScreenYPos + MurphyDY;
1536 printf("::: %04d [%03ld, %02d] ----------> %s [%d] [%d, %d] [%d, %d] [%d]\n",
1538 DemoOffset - DemoPointer, DemoKeyRepeatCounter,
1539 (DemoKeyCode == keyNone ? "(none)" :
1540 DemoKeyCode == keyLeft ? "left" :
1541 DemoKeyCode == keyRight ? "right" :
1542 DemoKeyCode == keyUp ? "up" :
1543 DemoKeyCode == keyDown ? "down" :
1544 DemoKeyCode == keySpace ? "space" :
1545 DemoKeyCode == keySpaceLeft ? "space + left" :
1546 DemoKeyCode == keySpaceRight ? "space + right" :
1547 DemoKeyCode == keySpaceUp ? "space + up" :
1548 DemoKeyCode == keySpaceDown ? "space + down" : "(unknown)"),
1550 MurphyScreenXPos, MurphyScreenYPos,
1551 MurphyPosIndex % 60, MurphyPosIndex / 60,
1560 if (!(ClearPos < 0)) // clear field that murphy is leaving
1561 subCopyFieldToScreen(ClearPos, 0);
1563 if (! ClearPos < 0) // clear field that murphy is leaving
1564 subCopyFieldToScreen(ClearPos, 0);
1568 printf("::: ---------------> %d, %d [%d, %d]\n",
1569 MurphyScreenXPos, MurphyScreenYPos, MurphyDX, MurphyDY);
1572 if (dx2 == fiInfotron) // special case of infotron moving left or right
1579 tDeltaX = MurphyDX * LocalStretch * (SeqPos + 1);
1580 tDeltaY = MurphyDY * LocalStretch * (SeqPos + 1);
1583 X = GetStretchX(dxPos) + tDeltaX;
1584 Y = GetStretchY(dxPos) + tDeltaY;
1585 Tmp = (SeqPos < 0 ? 0 : SeqPos); // 9StepBugFix!(red disk move right)
1586 StretchedSprites.BltEx(X, Y, dx[Tmp]);
1594 tPos = dxPos + dx2Step;
1595 X = GetStretchX(tPos);
1596 Y = GetStretchY(tPos);
1597 if (dx2 == fiInfotron) // special case of infotron moving left or right
1599 StretchedSprites.BltEx(X, Y, dx[SeqPos] + dx2Step);
1601 else // pushing something
1603 StretchedSprites.BltEx(X + tDeltaX, Y + tDeltaY, dx2);
1607 // End of normal movement
1608 // ------------------------
1612 // ++++++++++++++++++++++++++++++++
1613 // Begin of split movement (port)
1615 MurphyScreenXPos = MurphyScreenXPos + 2 * MurphyDX * MurphyZoomFactor;
1616 MurphyScreenYPos = MurphyScreenYPos + 2 * MurphyDY * MurphyZoomFactor;
1618 MurphyScreenXPos = MurphyScreenXPos + 2 * MurphyDX;
1619 MurphyScreenYPos = MurphyScreenYPos + 2 * MurphyDY;
1621 subCopyFieldToScreen(ClearPos, 0); // clear the field that murphy leaves
1622 tDeltaX = MurphyDX * LocalStretch * (SeqPos + 1);
1623 tDeltaY = MurphyDY * LocalStretch * (SeqPos + 1);
1624 X = GetStretchX(dxPos) + tDeltaX;
1625 Y = GetStretchY(dxPos) + tDeltaY;
1626 StretchedSprites.BltEx(X, Y, dx[SeqPos]); // plot first murphy
1627 tPos = dxPos + dx2Step;
1628 X = GetStretchX(tPos);
1629 Y = GetStretchY(tPos);
1630 StretchedSprites.BltEx(X + tDeltaX, Y + tDeltaY, dx[SeqPos]); // plot second murphy
1631 StretchedSprites.BltEx(X, Y, LowByte(PlayField16[tPos])); // replot the port on top
1632 // End of split movement (port)
1633 // ------------------------------
1634 } // loc_g_6D1E:'loc_g_6D28:
1636 SeqPos = SeqPos + 1;
1637 if (dx[SeqPos] > -1)
1638 return subAnimateMurphy;
1640 // Follow-up after movement completed 'loc_g_6D35:
1641 MurphyXPos = MurphyXPos + MurphyDX;
1642 MurphyYPos = MurphyYPos + MurphyDY;
1643 bl = HighByte(PlayField16[*si]); // animation phase
1644 MovHighByte(&PlayField16[*si], 0);
1646 if (bl == 0x1) // space, moving up
1649 if (bl == 0x2) // space, moving left
1652 if (bl == 0x3) // space, moving down
1655 if (bl == 0x4) // space, moving right
1658 if (bl == 0x5) // base , moving up
1661 if (bl == 0x6) // base , moving left -> 6 is not used, value is set to 2 instead of 6!
1664 if (bl == 0x7) // base , moving down
1667 if (bl == 0x8) // base , moving right
1670 if (bl == 0x9) // infotron, moving up
1673 if (bl == 0xA) // infotron, moving left
1676 if (bl == 0xB) // infotron, moving down
1679 if (bl == 0xC) // infotron, moving right
1682 if (bl == 0xD) // exit
1685 if (bl == 0xE) // zonk, pushing left
1688 if (bl == 0xF) // zonk, pushing right
1691 if (bl == 0x10) // base , touching up
1694 if (bl == 0x11) // base , touching left
1697 if (bl == 0x12) // base , touching down
1700 if (bl == 0x13) // base , touching right
1703 if (bl == 0x14) // infotron touching up
1706 if (bl == 0x15) // infotron touching left
1709 if (bl == 0x16) // infotron touching down
1712 if (bl == 0x17) // infotron touching right
1715 if (bl == 0x18) // port up
1718 if (bl == 0x19) // port left
1721 if (bl == 0x1A) // port down
1724 if (bl == 0x1B) // port right
1727 if (bl == 0x1C) // red disk, moving up
1730 if (bl == 0x1D) // red disk, moving left
1733 if (bl == 0x1E) // red disk, moving down
1736 if (bl == 0x1F) // red disk, moving right -> 9-Step-Bug!
1739 if (bl == 0x20) // red disk, touching up
1742 if (bl == 0x21) // red disk, touching left
1745 if (bl == 0x22) // red disk, touching down
1748 if (bl == 0x23) // red disk, touching right
1751 if (bl == 0x24) // yellow disk, pushing up
1754 if (bl == 0x25) // yellow disk, pushing left
1757 if (bl == 0x26) // yellow disk, pushing right -> order of "down" exchanged with "right"!
1760 if (bl == 0x27) // yellow disk, pushing down -> order of "down" exchanged with "right"!
1763 if (bl == 0x28) // orange disk, pushing left
1766 if (bl == 0x29) // orange disk, pushing right
1769 if (bl == 0x2A) // red disk, release
1773 return subAnimateMurphy;
1775 // ==========================================================================
1776 // infotron, moving up
1777 // ==========================================================================
1780 if (0 < LowByte(InfotronsNeeded))
1781 InfotronsNeeded = InfotronsNeeded - 1;
1783 subDisplayInfotronsNeeded();
1784 loc_g_6EC8: // space, base
1785 PlayField16[*si] = fiMurphy;
1786 subAdjustZonksInfotronsAboveMurphy(*si + FieldWidth);
1787 return subAnimateMurphy;
1789 // ==========================================================================
1790 // infotron, moving left
1791 // ==========================================================================
1794 if (0 < LowByte(InfotronsNeeded))
1795 InfotronsNeeded = InfotronsNeeded - 1;
1797 subDisplayInfotronsNeeded();
1798 loc_g_6EE6: // space, base
1799 PlayField16[*si] = fiMurphy;
1800 subAdjustZonksInfotronsAboveMurphy(*si + 1);
1801 return subAnimateMurphy;
1803 // ==========================================================================
1804 // infotron, moving down
1805 // ==========================================================================
1808 if (0 < LowByte(InfotronsNeeded))
1809 InfotronsNeeded = InfotronsNeeded - 1;
1811 subDisplayInfotronsNeeded();
1812 loc_g_6F04: // space, base
1813 if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion)
1814 PlayField16[*si - FieldWidth] = 0;
1816 PlayField16[*si] = fiMurphy;
1817 return subAnimateMurphy;
1819 // ==========================================================================
1820 // infotron, moving right
1821 // ==========================================================================
1824 if (0 < LowByte(InfotronsNeeded))
1825 InfotronsNeeded = InfotronsNeeded - 1;
1827 subDisplayInfotronsNeeded();
1828 loc_g_71C4: // space, base
1829 subAdjustZonksInfotronsAboveMurphy(*si - 1);
1830 PlayField16[*si] = fiMurphy;
1831 return subAnimateMurphy;
1833 // ==========================================================================
1834 // infotron, touching up
1835 // ==========================================================================
1838 if (0 < LowByte(InfotronsNeeded))
1839 InfotronsNeeded = InfotronsNeeded - 1;
1841 subDisplayInfotronsNeeded();
1843 if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion)
1844 PlayField16[*si - FieldWidth] = 0;
1846 return subAnimateMurphy;
1848 // ==========================================================================
1849 // infotron, touching left
1850 // ==========================================================================
1853 if (0 < LowByte(InfotronsNeeded))
1854 InfotronsNeeded = InfotronsNeeded - 1;
1856 subDisplayInfotronsNeeded();
1858 if (LowByte(PlayField16[*si - 1]) != fiExplosion)
1859 PlayField16[*si - 1] = 0;
1861 return subAnimateMurphy;
1863 // ==========================================================================
1864 // infotron, touching down
1865 // ==========================================================================
1868 if (0 < LowByte(InfotronsNeeded))
1869 InfotronsNeeded = InfotronsNeeded - 1;
1871 subDisplayInfotronsNeeded();
1873 if (LowByte(PlayField16[*si + FieldWidth]) != fiExplosion)
1874 PlayField16[*si + FieldWidth] = 0;
1876 return subAnimateMurphy;
1878 // ==========================================================================
1879 // infotron, touching right
1880 // ==========================================================================
1883 if (0 < LowByte(InfotronsNeeded))
1884 InfotronsNeeded = InfotronsNeeded - 1;
1886 subDisplayInfotronsNeeded();
1888 if (LowByte(PlayField16[*si + 1]) != fiExplosion)
1889 PlayField16[*si + 1] = 0;
1891 return subAnimateMurphy;
1893 // ==========================================================================
1894 // zonk, pushing left
1895 // ==========================================================================
1898 if (LowByte(PlayField16[*si]) != fiExplosion)
1899 PlayField16[*si] = 0;
1901 PlayField16[*si - 1] = fiMurphy;
1902 PlayField16[*si - 2] = fiZonk;
1903 subExplodeSnikSnaksBelow(*si - 2);
1905 return subAnimateMurphy;
1907 // ==========================================================================
1908 // zonk, pushing right
1909 // ==========================================================================
1912 if (LowByte(PlayField16[*si]) != fiExplosion)
1913 PlayField16[*si] = 0;
1915 PlayField16[*si + 1] = fiMurphy;
1916 PlayField16[*si + 2] = fiZonk;
1917 subExplodeSnikSnaksBelow(*si + 2);
1919 return subAnimateMurphy;
1921 // ==========================================================================
1923 // ==========================================================================
1929 PlayField16[*si] = fiSpace; // remove Murphy from playfield after exiting
1932 return subAnimateMurphy;
1934 // ==========================================================================
1935 // Push Zonk from right to left
1936 // ==========================================================================
1939 if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiZonk)
1940 return subAnimateMurphy;
1942 PlayField16[*si] = fiMurphy; // else restore - no more zonk pushing!
1943 PlayField16[*si - 1] = fiZonk;
1944 if (LowByte(PlayField16[*si - 2]) != fiExplosion)
1945 PlayField16[*si - 2] = 0;
1947 subCopyFieldToScreen(*si, fiMurphy);
1948 return subAnimateMurphy;
1950 // ==========================================================================
1951 // Push Zonk from left to right
1952 // ==========================================================================
1955 if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiZonk)
1956 return subAnimateMurphy;
1958 PlayField16[*si] = fiMurphy; // else restore - no more zonk pushing!
1959 PlayField16[*si + 1] = fiZonk;
1960 if (LowByte(PlayField16[*si + 2]) != fiExplosion)
1961 PlayField16[*si + 2] = 0;
1963 subCopyFieldToScreen(*si, fiMurphy);
1964 return subAnimateMurphy;
1966 // ==========================================================================
1967 // Push orange disk from right to left
1968 // ==========================================================================
1971 if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiOrangeDisk)
1972 return subAnimateMurphy;
1974 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
1975 PlayField16[*si - 1] = fiOrangeDisk;
1976 if (LowByte(PlayField16[*si - 2]) != fiExplosion)
1977 PlayField16[*si - 2] = 0;
1979 subCopyFieldToScreen(*si, fiMurphy);
1980 return subAnimateMurphy;
1982 // ==========================================================================
1983 // Push orange disk from left to right
1984 // ==========================================================================
1987 if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiOrangeDisk)
1988 return subAnimateMurphy;
1990 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
1991 PlayField16[*si + 1] = fiOrangeDisk;
1992 if (LowByte(PlayField16[*si + 2]) != fiExplosion)
1993 PlayField16[*si + 2] = 0;
1995 subCopyFieldToScreen(*si, fiMurphy);
1996 return subAnimateMurphy;
1998 // ==========================================================================
1999 // Push yellow disk from down to up
2000 // ==========================================================================
2003 if (DemoKeyCode == keyUp && PlayField16[*si - FieldWidth] == fiYellowDisk)
2004 return subAnimateMurphy;
2006 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2007 PlayField16[*si - FieldWidth] = fiYellowDisk;
2008 if (LowByte(PlayField16[*si - 2 * FieldWidth]) != fiExplosion)
2009 PlayField16[*si - 2 * FieldWidth] = 0;
2011 subCopyFieldToScreen(*si, fiMurphy);
2012 return subAnimateMurphy;
2014 // ==========================================================================
2015 // Push yellow disk from right to left
2016 // ==========================================================================
2019 if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiYellowDisk)
2020 return subAnimateMurphy;
2022 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2023 PlayField16[*si - 1] = fiYellowDisk;
2024 if (LowByte(PlayField16[*si - 2]) != fiExplosion)
2025 PlayField16[*si - 2] = 0;
2027 subCopyFieldToScreen(*si, fiMurphy);
2028 return subAnimateMurphy;
2030 // ==========================================================================
2031 // Push yellow disk from up to down
2032 // ==========================================================================
2035 if (DemoKeyCode == keyDown && PlayField16[*si + FieldWidth] == fiYellowDisk)
2036 return subAnimateMurphy;
2038 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2039 PlayField16[*si + FieldWidth] = fiYellowDisk;
2040 if (LowByte(PlayField16[*si + 2 * FieldWidth]) != fiExplosion)
2041 PlayField16[*si + 2 * FieldWidth] = 0;
2043 subCopyFieldToScreen(*si, fiMurphy);
2044 return subAnimateMurphy;
2046 // ==========================================================================
2047 // Push yellow disk from left to right
2048 // ==========================================================================
2051 if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiYellowDisk)
2052 return subAnimateMurphy;
2054 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2055 PlayField16[*si + 1] = fiYellowDisk;
2056 if (LowByte(PlayField16[*si + 2]) != fiExplosion)
2057 PlayField16[*si + 2] = 0;
2059 subCopyFieldToScreen(*si, fiMurphy);
2060 return subAnimateMurphy;
2062 // ==========================================================================
2063 // time red disk release (space)
2064 // ==========================================================================
2067 if (DemoKeyCode != keySpace)
2069 PlayField16[*si] = fiMurphy;
2070 subCopyFieldToScreen(*si, fiMurphy);
2071 RedDiskReleasePhase = 0;
2073 else if (MovingPictureSequencePhase == 0x20)
2075 subCopyFieldToScreen(*si, 43); // anxious murphy
2076 RedDiskReleasePhase = 1;
2079 return subAnimateMurphy;
2081 // ==========================================================================
2082 // Special port down to up
2083 // ==========================================================================
2086 if (LowByte(PlayField16[*si]) != fiExplosion)
2087 PlayField16[*si] = 0;
2089 PlayField16[*si - 2 * FieldWidth] = fiMurphy;
2091 *si = *si - FieldWidth;
2092 if (HighByte(PlayField16[*si]) == 1)
2095 *si = *si - FieldWidth;
2096 return subAnimateMurphy;
2098 // ==========================================================================
2099 // Special port right to left
2100 // ==========================================================================
2103 if (LowByte(PlayField16[*si]) != fiExplosion)
2104 PlayField16[*si] = 0;
2106 PlayField16[*si - 2] = fiMurphy;
2109 if (HighByte(PlayField16[*si]) == 1)
2113 return subAnimateMurphy;
2115 // ==========================================================================
2116 // Special port up to down
2117 // ==========================================================================
2120 if (LowByte(PlayField16[*si]) != fiExplosion)
2121 PlayField16[*si] = 0;
2123 PlayField16[*si + 2 * FieldWidth] = fiMurphy;
2125 *si = *si + FieldWidth;
2126 if (HighByte(PlayField16[*si]) == 1)
2129 *si = *si + FieldWidth;
2130 return subAnimateMurphy;
2132 // ==========================================================================
2133 // Special port left to right
2134 // ==========================================================================
2137 if (LowByte(PlayField16[*si]) != fiExplosion)
2138 PlayField16[*si] = 0;
2140 PlayField16[*si + 2] = fiMurphy;
2143 if (HighByte(PlayField16[*si]) == 1)
2147 return subAnimateMurphy;
2149 // ==========================================================================
2151 // ==========================================================================
2154 if (LowByte(PlayField16[*si]) != fiExplosion)
2155 PlayField16[*si] = 0;
2157 *si = *si - FieldWidth;
2158 PlayField16[*si] = fiMurphy;
2159 subEatRedDisk(*si); // inc+show Murphy's red disks
2160 return subAnimateMurphy;
2162 // ==========================================================================
2163 // Move Red Disk left
2164 // ==========================================================================
2167 if (LowByte(PlayField16[*si + 1]) != fiExplosion)
2168 PlayField16[*si + 1] = 0;
2170 PlayField16[*si] = fiMurphy;
2171 subEatRedDisk(*si); // inc+show Murphy's red disks
2172 return subAnimateMurphy;
2174 // ==========================================================================
2175 // Move Red Disk down
2176 // ==========================================================================
2179 if (LowByte(PlayField16[*si]) != fiExplosion)
2180 PlayField16[*si] = 0;
2182 *si = *si + FieldWidth;
2183 PlayField16[*si] = fiMurphy;
2184 subEatRedDisk(*si); // inc+show Murphy's red disks
2185 return subAnimateMurphy;
2187 // ==========================================================================
2188 // Move Red Disk right
2189 // ==========================================================================
2192 if (LowByte(PlayField16[*si - 1]) != fiExplosion)
2193 PlayField16[*si - 1] = 0;
2195 PlayField16[*si] = fiMurphy;
2196 subEatRedDisk(*si); // inc+show Murphy's red disks
2197 return subAnimateMurphy;
2199 // ==========================================================================
2201 // ==========================================================================
2204 if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion)
2205 PlayField16[*si - FieldWidth] = 0;
2207 subEatRedDisk(*si - FieldWidth); // inc+show Murphy's red disks
2208 return subAnimateMurphy;
2210 // ==========================================================================
2211 // Eat Red Disk left
2212 // ==========================================================================
2215 if (LowByte(PlayField16[*si - 1]) != fiExplosion)
2216 PlayField16[*si - 1] = 0;
2218 subEatRedDisk(*si - 1); // inc+show Murphy's red disks
2219 return subAnimateMurphy;
2221 // ==========================================================================
2222 // Eat Red Disk down
2223 // ==========================================================================
2226 if (LowByte(PlayField16[*si + FieldWidth]) != fiExplosion)
2227 PlayField16[*si + FieldWidth] = 0;
2229 subEatRedDisk(*si + FieldWidth); // inc+show Murphy's red disks
2230 return subAnimateMurphy;
2232 // ==========================================================================
2233 // Eat Red Disk right
2234 // ==========================================================================
2237 if (LowByte(PlayField16[*si + 1]) != fiExplosion)
2238 PlayField16[*si + 1] = 0;
2240 subEatRedDisk(*si + 1); // inc+show Murphy's red disks
2241 return subAnimateMurphy;
2243 // ==========================================================================
2244 // yellow disk, pushing up
2245 // ==========================================================================
2248 if (LowByte(PlayField16[*si]) != fiExplosion)
2249 PlayField16[*si] = 0;
2251 *si = *si - FieldWidth;
2252 PlayField16[*si] = fiMurphy;
2253 PlayField16[*si - FieldWidth] = fiYellowDisk;
2254 return subAnimateMurphy;
2256 // ==========================================================================
2257 // yellow disk, pushing left
2258 // ==========================================================================
2261 if (LowByte(PlayField16[*si]) != fiExplosion)
2262 PlayField16[*si] = 0;
2265 PlayField16[*si] = fiMurphy;
2266 PlayField16[*si - 1] = fiYellowDisk;
2267 return subAnimateMurphy;
2269 // ==========================================================================
2270 // yellow disk, pushing down
2271 // ==========================================================================
2274 if (LowByte(PlayField16[*si]) != fiExplosion)
2275 PlayField16[*si] = 0;
2277 *si = *si + FieldWidth;
2278 PlayField16[*si] = fiMurphy;
2279 PlayField16[*si + FieldWidth] = fiYellowDisk;
2280 return subAnimateMurphy;
2282 // ==========================================================================
2283 // yellow disk pushing right
2284 // ==========================================================================
2287 if (LowByte(PlayField16[*si]) != fiExplosion)
2288 PlayField16[*si] = 0;
2291 PlayField16[*si] = fiMurphy;
2292 PlayField16[*si + 1] = fiYellowDisk;
2293 return subAnimateMurphy;
2295 // ==========================================================================
2296 // orange disk, pushing left
2297 // ==========================================================================
2300 if (LowByte(PlayField16[*si]) != fiExplosion)
2301 PlayField16[*si] = 0;
2304 PlayField16[*si] = fiMurphy;
2305 PlayField16[*si - 1] = fiOrangeDisk;
2306 return subAnimateMurphy;
2308 // ==========================================================================
2309 // orange disk, pushing right
2310 // ==========================================================================
2313 if (LowByte(PlayField16[*si]) != fiExplosion)
2314 PlayField16[*si] = 0;
2317 PlayField16[*si] = fiMurphy;
2318 PlayField16[*si + 1] = fiOrangeDisk;
2319 if (PlayField16[*si + FieldWidth + 1] == 0) // make it fall down if below is empty
2321 MovHighByte(&PlayField16[*si + 1], 0x20);
2322 MovHighByte(&PlayField16[*si + FieldWidth + 1], fiOrangeDisk);
2325 return subAnimateMurphy;
2327 // ==========================================================================
2328 // Release a red disk
2329 // ==========================================================================
2332 PlayField16[*si] = fiMurphy;
2333 RedDiskReleasePhase = 2;
2334 RedDiskCount = RedDiskCount - 1;
2335 subDisplayRedDiskCount();
2336 subSoundFXPush(); // Sound effects
2338 return subAnimateMurphy;
2339 } // subAnimateMurphy
2341 // ==========================================================================
2343 // ==========================================================================
2344 int subExplodeSnikSnaksBelow(int si)
2346 int subExplodeSnikSnaksBelow;
2350 ax = LowByte(PlayField16[si + FieldWidth]);
2351 if (ax == 0x11 || ax == 0xBB)
2352 ExplodeFieldSP(si + FieldWidth);
2354 return subExplodeSnikSnaksBelow;
2355 } // subExplodeSnikSnaksBelow
2357 // ==========================================================================
2359 // Does pushing against an object kill Murphy?
2360 // ==========================================================================
2361 static boolean subMoveKillsMurphy(int si, int ax, int bl)
2363 static boolean subMoveKillsMurphy;
2369 if (ax == 0xFFFF || ax == 0xAAAA || ah == 0)
2375 if (al == fiExplosion)
2378 if (fiOrangeDisk <= al && al <= fiPortUp)
2381 ExplodeFieldSP(si); // Explode
2382 subMoveKillsMurphy = True;
2383 return subMoveKillsMurphy;
2392 ExplodeFieldSP(si); // Explode
2393 subMoveKillsMurphy = True;
2394 return subMoveKillsMurphy;
2396 loc_g_74F6: // zonk left
2398 if (! (ah == 0x20 || ah == 0x40 || ah == 0x50 || ah == 0x70))
2401 subMoveKillsMurphy = True; // Set carry flag
2402 return subMoveKillsMurphy;
2404 loc_g_7512: // zonk right
2406 if (! (ah == 0x30 || ah == 0x40 || ah == 0x60 || ah == 0x70))
2409 loc_g_752E: // Marked fields and Ports
2410 subMoveKillsMurphy = True; // Set carry flag
2411 return subMoveKillsMurphy;
2413 loc_g_7530: // explosion
2414 if ((ah & 0x80) != 0)
2421 ExplodeFieldSP(si); // Explode
2422 subMoveKillsMurphy = True; // Set carry flag
2423 return subMoveKillsMurphy;
2426 PlayField16[si] = 0;
2427 subMoveKillsMurphy = False;
2429 return subMoveKillsMurphy;
2430 } // subMoveKillsMurphy
2432 // ==========================================================================
2434 // Test If si 's a special (grav) port and If so Then fetch new values (see below)
2435 // change conditions to port specs
2436 // The 10-port data base is at data_h_0D28, 10 entries of 6 bytes each:
2437 // (hi),(lo),(gravity),(freeze zonks),(freeze enemies),(unused)
2438 // ==========================================================================
2439 int subSpPortTest(int si)
2446 cx = LInfo.SpecialPortCount; // number of special ports
2448 for (i = 0; i < cx; i++)
2451 /* this assumes that PortLocation is stored as big endian */
2452 bx = LInfo.SpecialPort[i].PortLocation;
2454 /* this assumes that PortLocation is stored as little endian */
2455 bx = HighByte(LInfo.SpecialPort[i].PortLocation);
2456 MovHighByte(&bx, LowByte(LInfo.SpecialPort[i].PortLocation));
2461 GravityFlag = LInfo.SpecialPort[i].Gravity;
2462 FreezeZonks = LInfo.SpecialPort[i].FreezeZonks;
2463 SnikSnaksElectronsFrozen = LInfo.SpecialPort[i].FreezeEnemies;
2465 // RandomTime = RandomTime Xor RandomSeed 'is RandomTime used at all? no!
2473 cx = LInfo.SpecialPortCount; // number of special ports
2474 for (i = 1; i <= cx; i++)
2477 bx = HighByte(LInfo.SpecialPort[i].PortLocation);
2478 MovHighByte(&bx, LowByte(LInfo.SpecialPort[i].PortLocation));
2481 GravityFlag = LInfo.SpecialPort[i].Gravity;
2482 FreezeZonks = LInfo.SpecialPort[i].FreezeZonks;
2483 SnikSnaksElectronsFrozen = LInfo.SpecialPort[i].FreezeEnemies;
2484 // RandomTime = RandomTime Xor RandomSeed 'is RandomTime used at all? no!
2491 return subSpPortTest;
2494 void subCopyFieldToScreen(int si, int fi)
2498 // +++++++++++++++++++++++++++++++++++++++++
2499 X = GetStretchX(si);
2500 Y = GetStretchY(si);
2501 StretchedSprites.BltEx(X, Y, fi);
2502 // +++++++++++++++++++++++++++++++++++++++++
2505 void subCopyImageToScreen(int si, int graphic, int sync_frame)
2509 // +++++++++++++++++++++++++++++++++++++++++
2510 X = GetStretchX(si);
2511 Y = GetStretchY(si);
2512 StretchedSprites.BltImg(X, Y, graphic, sync_frame);
2513 // +++++++++++++++++++++++++++++++++++++++++
2516 static void subEatRedDisk(int si)
2518 if (AllowRedDiskCheat == 0)
2520 if (RedDiskReleasePhase != 0)
2522 if (RedDiskReleaseMurphyPos == si)
2527 RedDiskCount = (RedDiskCount + 1) % 256;
2528 subDisplayRedDiskCount();
2531 int subAdjustZonksInfotronsAboveMurphy(int si)
2533 int subAdjustZonksInfotronsAboveMurphy;
2537 if (LowByte(PlayField16[si]) != fiExplosion)
2538 PlayField16[si] = 0;
2540 ax = PlayField16[si - FieldWidth];
2541 if (ax == 0 || ax == 0x9999)
2544 if (ax == fiZonk || ax == fiInfotron)
2546 MovHighByte(&PlayField16[si - FieldWidth], 0x40); // make falling straigt down
2549 return subAdjustZonksInfotronsAboveMurphy;
2551 loc_g_15A8: // empty above
2552 ax = PlayField16[si - FieldWidth - 1];
2553 if (ax == fiZonk || ax == fiInfotron)
2557 ax = PlayField16[si - FieldWidth + 1];
2558 if (ax == fiZonk || ax == fiInfotron)
2561 return subAdjustZonksInfotronsAboveMurphy;
2563 loc_g_15C5: // zonk/infotron above left
2564 ax = PlayField16[si - 1];
2565 if (! (ax == fiZonk || ax == fiInfotron || ax == fiRAM)) // continue testing right above
2568 MovHighByte(&PlayField16[si - FieldWidth - 1], 0x60); // make roll right
2569 PlayField16[si - FieldWidth] = 0x8888;
2570 return subAdjustZonksInfotronsAboveMurphy;
2572 loc_g_15E8: // zonk/infotron above right
2573 ax = PlayField16[si + 1];
2574 if (ax == fiZonk || ax == fiInfotron || ax == fiRAM)
2576 MovHighByte(&PlayField16[si - FieldWidth + 1], 0x50); // make roll left
2577 PlayField16[si - FieldWidth] = 0x8888;
2580 return subAdjustZonksInfotronsAboveMurphy;
2581 } // subAdjustZonksInfotronsAboveMurphy