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 void subAnimateMurphy(int *si)
33 // int ax, al, ah, bx, bl, i, X, Y;
34 // int tX, tY, tDeltaX, tDeltaY, tPos, Tmp;
36 int ax, al, bl, i, X, Y;
39 int ax, al, bx, bl, i, X, Y;
41 int tDeltaX, tDeltaY, tPos, Tmp;
43 // Variables that hold information about the animation sequence
44 static int *dx = 0; // an array of image positions in moving.mpx, finalized with -1
45 static int dx1 = 0; // same as "*dx" above, but as image/animation token
46 static int dx2 = 0; // an additional image position of a second sprite, for instance: yellow disk if pushed
47 static int MurphyDX = 0, MurphyDY = 0; // murphys move steps
48 static int SeqPos = 0; // index into dx()
49 static int ClearPos = 0; // Position to clear before blitting sprites, none=-1
50 static int dxPos = 0; // field-position to draw dx(SeqPos)
51 static int dx2Step = 0; // position of dx2 relative to dx-position
52 static int dx1SequenceLength = 0;
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!
74 MurphyMoveCounter = 1; // We have a Murphy!
75 MurphyExplodePos = *si;
77 // (check if high byte of PlayField16 has stored movement information)
78 if (ax != fiMurphy) // yes--go proceed moving murphy?
79 goto locProceedMovingMurphy;
81 // FS: reset moving sequence variables
90 ScratchGravity = 0; // scratch gravity off
91 if (GravityFlag != 0) // Gravity? (1=gravity on)
93 bl = LowByte(PlayField16[*si - FieldWidth]); // check above
94 if (! (bl == fiPortUp || bl == fiPortUpAndDown || bl == fiPortAllDirections))
96 if (PlayField16[*si + FieldWidth] == 0) // gravity on and space below!
102 if (bl != 0) // a key was pressed!
103 goto locKeyPressed5FCF;
106 printf("::: Murphy.c: !!! %d [%d]\n", DemoKeyCode, GravityFlag);
109 RedDiskReleaseFlag = 1;
110 if (ScratchGravity != 0) // gravity pulls & space below?'-> force Space up to down
124 // ------------------------------------------------------------------
125 // Murphy's YAWN & SLEEP sequence, counted down by YawnSleepCounter:
127 YawnSleepCounter = YawnSleepCounter + 1;
129 if (YawnSleepCounter < 16)
132 if (YawnSleepCounter < 2000)
135 // (default: single graphic, no animation)
136 subCopyAnimToScreen(*si, aniMurphy, YawnSleepCounter - 16);
141 if (YawnSleepCounter < 4000)
143 // yawn! and look depressed afterwards...
144 // (default: 12 animation frames with delay of 8)
145 subCopyAnimToScreen(*si, aniMurphyYawn, YawnSleepCounter - 2000);
150 if (YawnSleepCounter < 6400)
153 // (default: 12 animation frames with delay of 8)
154 subCopyAnimToScreen(*si, aniMurphyYawn, YawnSleepCounter - 4000);
159 // time1 = 6400 + 12 * 8; // (default: 6496 == 6400 + 12 * 8)
160 time1 = 6400 + 12 * 10;
162 if (YawnSleepCounter < time1)
164 // yawn again! - third time
165 // (default: 12 animation frames with delay of 8)
166 subCopyAnimToScreen(*si, aniMurphyYawn, YawnSleepCounter - 6400);
171 // time2 = 6496 + 3 * 64; // (default: 6688 == 6496 + 3 * 64)
172 time2 = 6496 + 3 * 100;
174 if (YawnSleepCounter > time2) // Murphy already went to sleep
177 if (PlayField16[*si - 1] == 0)
179 if (PlayField16[*si + 1] == 0)
181 // no sleep -- go back to "wait and start yawning" phase
182 YawnSleepCounter = 144;
188 // go to sleep (right side)
189 // (default: 3 animation frames with delay of 64)
190 subCopyAnimToScreen(*si, aniMurphySleepRight, YawnSleepCounter - time1);
196 // go to sleep (left side)
197 // (default: 3 animation frames with delay of 64)
198 subCopyAnimToScreen(*si, aniMurphySleepLeft, YawnSleepCounter - time1);
202 // end of YAWN-SLEEP-Sequence
210 // ------------------------------------------------------------------
211 // Murphy's YAWN & SLEEP sequence, counted down by YawnSleepCounter:
212 YawnSleepCounter = YawnSleepCounter + 1;
213 if (YawnSleepCounter == 4)
215 subCopyFieldToScreen(*si, fiMurphy); // normal grin
219 if (YawnSleepCounter <= 500) // loc_g_5ED7:
222 if (YawnSleepCounter <= 522)
224 bx = (YawnSleepCounter - 500) / 2;
225 subCopyFieldToScreen(*si, aniMurphyYawn + bx); // yawn! and look depressed afterwards...
229 if (YawnSleepCounter <= 1000)
232 if (YawnSleepCounter <= 1022)
234 bx = (YawnSleepCounter - 1000) / 2;
235 subCopyFieldToScreen(*si, aniMurphyYawn + bx); // yawn again!
239 if (YawnSleepCounter <= 1600) // loc_g_5F3B:
242 if (YawnSleepCounter <= 1622)
244 bx = (YawnSleepCounter - 1600) / 2;
245 subCopyFieldToScreen(*si, aniMurphyYawn + bx); // yawn again! - third time
249 if (YawnSleepCounter > 1654)
252 if (PlayField16[*si - 1] == 0)
254 if (PlayField16[*si + 1] == 0)
256 YawnSleepCounter = 36;
262 bx = (YawnSleepCounter - 1622) / 16;
263 subCopyFieldToScreen(*si, aniMurphySleepRight + bx); // go to sleep
268 bx = (YawnSleepCounter - 1622) / 16;
269 subCopyFieldToScreen(*si, aniMurphySleepLeft + bx); // go to sleep
273 // end of YAWN-SLEEP-Sequence
277 // ------------------------------------------------------------------
278 // ==========================================================================
279 // (Direct Jump) a key was pressed
280 // ==========================================================================
283 if (ScratchGravity == 0)
286 if (PlayField16[*si + FieldWidth] != 0)
291 if (PlayField16[*si - FieldWidth] == fiBase)
295 else if (bl == keyLeft)
297 if (PlayField16[*si - 1] == fiBase)
301 else if (bl == keyRight)
303 if (PlayField16[*si + 1] == fiBase)
307 bl = keyDown; // force moving down!
312 RedDiskReleaseFlag = 0; // moving down to up ...
318 RedDiskReleaseFlag = 0; // moving right to left ...
324 RedDiskReleaseFlag = 0; // moving up to down ...
330 RedDiskReleaseFlag = 0; // moving left to right ...
335 case keySpaceUp: // 5
336 RedDiskReleaseFlag = 0; // touching down to up ...
341 case keySpaceLeft: // 6
342 RedDiskReleaseFlag = 0; // touching right to left ...
347 case keySpaceDown: // 7
348 RedDiskReleaseFlag = 0; // touching up to down ...
353 case keySpaceRight: // 8
354 RedDiskReleaseFlag = 0; // touching left to right ...
360 goto loc_g_62E2; // no move ...
365 RedDiskReleaseFlag = 0;
370 // ==========================================================================
371 // moving down to up ...
372 // ==========================================================================
378 ax = PlayField16[*si - FieldWidth];
389 if (ax == fiInfotron)
395 if (al == fiTerminal)
398 if (al == fiPortUp || al == fiPortUpAndDown || al == fiPortAllDirections)
404 if (al == fiYellowDisk)
407 if (! subMoveKillsMurphy(*si - FieldWidth, ax, bl))
412 // ==========================================================================
413 // moving right to left ...
414 // ==========================================================================
420 MurphyVarFaceLeft = 1;
421 ax = PlayField16[*si - 1];
432 if (ax == fiInfotron)
441 if (al == fiTerminal)
444 if (al == fiPortLeft || al == fiPortLeftAndRight || al == fiPortAllDirections)
450 if (ax == fiYellowDisk)
453 if (ax == fiOrangeDisk)
456 if (! subMoveKillsMurphy(*si - 1, ax, bl))
461 // ==========================================================================
462 // moving up to down ...
463 // ==========================================================================
469 ax = PlayField16[*si + FieldWidth];
480 if (ax == fiInfotron)
486 if (al == fiTerminal)
489 if (al == fiPortDown || al == fiPortUpAndDown || al == fiPortAllDirections)
495 if (al == fiYellowDisk)
498 if (! subMoveKillsMurphy(*si + FieldWidth, ax, bl))
503 // ==========================================================================
504 // moving left to right ...
505 // ==========================================================================
511 MurphyVarFaceLeft = 0;
512 ax = PlayField16[*si + 1];
523 if (ax == fiInfotron)
532 if (al == fiTerminal)
535 if (al == fiPortRight || al == fiPortLeftAndRight || al == fiPortAllDirections)
541 if (al == fiYellowDisk)
544 if (ax == fiOrangeDisk)
547 if (! subMoveKillsMurphy(*si + 1, ax, bl))
552 // ==========================================================================
553 // touching down to up ...
554 // ==========================================================================
559 dxPos = *si - FieldWidth;
561 ax = PlayField16[*si - FieldWidth];
570 if (ax == fiInfotron)
573 if (al == fiTerminal)
581 // ==========================================================================
582 // touching right to left ...
583 // ==========================================================================
590 MurphyVarFaceLeft = 1;
591 ax = PlayField16[*si - 1];
599 if (ax == fiInfotron)
602 if (al == fiTerminal)
610 // ==========================================================================
611 // touching up to down ...
612 // ==========================================================================
617 dxPos = *si + FieldWidth;
619 ax = PlayField16[*si + FieldWidth];
627 if (ax == fiInfotron)
630 if (al == fiTerminal)
638 // ==========================================================================
639 // touching left to right ...
640 // ==========================================================================
647 MurphyVarFaceLeft = 0;
648 ax = PlayField16[*si + 1];
656 if (ax == fiInfotron)
659 if (al == fiTerminal)
667 // ==========================================================================
668 // Release Red disk: no move ...
669 // ==========================================================================
675 if (LowByte(RedDiskCount) == 0)
678 if (LowByte(RedDiskReleasePhase) != 0)
681 if (LowByte(RedDiskReleaseFlag) != 1)
684 MovHighByte(&PlayField16[*si], 0x2A);
685 MovingPictureSequencePhase = 0x40; // init picture move sequence
686 dx = aniFramesRedDisk;
688 MovLowByte(&RedDiskReleasePhase, 1);
689 Mov(&RedDiskReleaseMurphyPos, *si); // remember Murphy's location
692 // ==========================================================================
693 // SPACE moving down to up
694 // ==========================================================================
697 dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
698 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyMoveUpRight : aniMurphyMoveUpLeft);
699 PlayField16[*si - FieldWidth] = 0x103;
700 PlayField16[*si] = 0x300;
701 *si = *si - FieldWidth;
702 goto loc_StopNoSplit;
704 // ==========================================================================
705 // SPACE moving right to left
706 // ==========================================================================
709 dx = aniFramesMurphyEatLeft;
710 dx1 = aniMurphyMoveLeft;
711 PlayField16[*si - 1] = 0x203;
712 PlayField16[*si] = 0x300;
714 goto loc_StopNoSplit;
716 // ==========================================================================
717 // SPACE moving up to down, and when gravity is pulling!
718 // ==========================================================================
721 dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
722 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyMoveUpRight : aniMurphyMoveUpLeft);
723 PlayField16[*si + FieldWidth] = 0x303;
724 PlayField16[*si] = 0x300;
725 *si = *si + FieldWidth;
726 goto loc_StopNoSplit;
728 // ==========================================================================
729 // SPACE moving left to right
730 // ==========================================================================
733 dx = aniFramesMurphyEatRight;
734 dx1 = aniMurphyMoveRight;
735 PlayField16[*si + 1] = 0x403;
736 PlayField16[*si] = 0x300;
738 goto loc_StopNoSplit;
740 // ==========================================================================
741 // BUG moving down to up
742 // ==========================================================================
745 if (SgnHighByte(PlayField16[*si - FieldWidth]) >= 0)
747 ExplodeFieldSP(*si); // Explode
752 PlayField16[*si - FieldWidth] = fiBase;
753 // ==========================================================================
754 // BASE moving down to up
755 // ==========================================================================
759 dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
760 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyDigUpRight : aniMurphyDigUpLeft);
761 PlayField16[*si - FieldWidth] = 0x503;
762 PlayField16[*si] = 0x300;
763 *si = *si - FieldWidth;
764 goto loc_StopNoSplit;
766 // ==========================================================================
767 // BUG moving right to left
768 // ==========================================================================
771 if (SgnHighByte(PlayField16[*si - 1]) >= 0)
773 ExplodeFieldSP(*si); // Explode
778 PlayField16[*si - 1] = fiBase;
779 // ==========================================================================
780 // BASE moving right to left
781 // ==========================================================================
785 dx = aniFramesMurphyEatLeft;
786 dx1 = aniMurphyDigLeft;
787 PlayField16[*si - 1] = 0x203;
788 PlayField16[*si] = 0x300;
790 goto loc_StopNoSplit;
792 // ==========================================================================
793 // BUG moving up to down
794 // ==========================================================================
797 if (SgnHighByte(PlayField16[*si + FieldWidth]) >= 0)
799 ExplodeFieldSP(*si); // Explode
804 PlayField16[*si + FieldWidth] = fiBase;
805 // ==========================================================================
806 // BASE moving up to down
807 // ==========================================================================
811 dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
812 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyDigUpRight : aniMurphyDigUpLeft);
813 PlayField16[*si + FieldWidth] = 0x703;
814 PlayField16[*si] = 0x300;
815 *si = *si + FieldWidth;
816 goto loc_StopNoSplit;
818 // ==========================================================================
819 // BUG moving left to right
820 // ==========================================================================
823 if (SgnHighByte(PlayField16[*si + 1]) >= 0)
825 ExplodeFieldSP(*si); // Explode
830 PlayField16[*si + 1] = fiBase;
831 // ==========================================================================
832 // BASE moving left to right
833 // ==========================================================================
837 dx = aniFramesMurphyEatRight;
838 dx1 = aniMurphyDigRight;
839 PlayField16[*si + 1] = 0x803;
840 PlayField16[*si] = 0x300;
842 goto loc_StopNoSplit;
844 // ==========================================================================
845 // BUG touching down to up
846 // ==========================================================================
849 if (SgnHighByte(PlayField16[*si - FieldWidth]) >= 0)
851 ExplodeFieldSP(*si); // Explode
856 PlayField16[*si - FieldWidth] = fiBase;
857 // ==========================================================================
858 // BASE touching down to up
859 // ==========================================================================
862 subCopyImageToScreen(*si, aniMurphyTouchUp);
864 dx = aniFramesTouchBase;
866 dxPos = *si - FieldWidth;
867 MovHighByte(&PlayField16[*si], 0x10);
868 goto loc_StopNoSplit;
870 // ==========================================================================
871 // BUG touching right to left
872 // ==========================================================================
875 if (SgnHighByte(PlayField16[*si - 1]) >= 0)
877 ExplodeFieldSP(*si); // Explode
882 PlayField16[*si - 1] = fiBase;
883 // ==========================================================================
884 // BASE touching right to left
885 // ==========================================================================
888 subCopyImageToScreen(*si, aniMurphyTouchLeft);
890 dx = aniFramesTouchBase;
893 MovHighByte(&PlayField16[*si], 0x11);
894 goto loc_StopNoSplit;
896 // ==========================================================================
897 // BUG touching up to down
898 // ==========================================================================
901 if (SgnHighByte(PlayField16[*si + FieldWidth]) >= 0)
903 ExplodeFieldSP(*si); // Explode
908 PlayField16[*si + FieldWidth] = fiBase;
909 // ==========================================================================
910 // BASE touching up to down
911 // ==========================================================================
914 subCopyImageToScreen(*si, aniMurphyTouchDown);
916 dx = aniFramesTouchBase;
918 dxPos = *si + FieldWidth;
919 MovHighByte(&PlayField16[*si], 0x12);
920 goto loc_StopNoSplit;
922 // ==========================================================================
923 // BUG touching left to right
924 // ==========================================================================
927 if (SgnHighByte(PlayField16[*si + 1]) >= 0)
929 ExplodeFieldSP(*si); // Explode
934 PlayField16[*si + 1] = fiBase;
935 // ==========================================================================
936 // BASE touching left to right
937 // ==========================================================================
940 subCopyImageToScreen(*si, aniMurphyTouchRight);
942 dx = aniFramesTouchBase;
945 MovHighByte(&PlayField16[*si], 0x13);
946 goto loc_StopNoSplit;
948 // ==========================================================================
949 // INFOTRON moving down to up
950 // ==========================================================================
953 subSoundFXInfotron();
954 dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
955 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
956 PlayField16[*si - FieldWidth] = 0x903;
957 PlayField16[*si] = 0x300;
958 *si = *si - FieldWidth;
959 goto loc_StopNoSplit;
961 // ==========================================================================
962 // INFOTRON moving right to left
963 // ==========================================================================
966 subSoundFXInfotron();
967 dx = aniFramesEatInfotronLeft;
968 dx1 = aniEatInfotronLeft;
974 PlayField16[*si - 1] = 0xA03;
975 PlayField16[*si] = 0x300;
977 goto loc_StopNoSplit;
979 // ==========================================================================
980 // INFOTRON moving up to down
981 // ==========================================================================
984 subSoundFXInfotron();
985 dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
986 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
987 PlayField16[*si + FieldWidth] = 0xB03;
988 PlayField16[*si] = 0x300;
989 *si = *si + FieldWidth;
990 goto loc_StopNoSplit;
992 // ==========================================================================
993 // INFOTRON moving left to right
994 // ==========================================================================
997 subSoundFXInfotron();
998 dx = aniFramesEatInfotronRight;
999 dx1 = aniEatInfotronRight;
1005 PlayField16[*si + 1] = 0xC03;
1006 PlayField16[*si] = 0x300;
1008 goto loc_StopNoSplit;
1010 // ==========================================================================
1011 // INFOTRON touching down to up
1012 // ==========================================================================
1015 subCopyImageToScreen(*si, aniMurphyTouchUp);
1016 subSoundFXInfotron();
1017 dx = aniFramesTouchInfotron;
1018 dx1 = aniTouchInfotron;
1019 MovHighByte(&PlayField16[*si], 0x14);
1020 MovHighByte(&PlayField16[*si - FieldWidth], 0xFF);
1021 goto loc_StopNoSplit;
1023 // ==========================================================================
1024 // INFOTRON touching right to left
1025 // ==========================================================================
1028 subCopyImageToScreen(*si, aniMurphyTouchLeft);
1029 subSoundFXInfotron();
1030 dx = aniFramesTouchInfotron;
1031 dx1 = aniTouchInfotron;
1032 MovHighByte(&PlayField16[*si], 0x15);
1033 MovHighByte(&PlayField16[*si - 1], 0xFF);
1034 goto loc_StopNoSplit;
1036 // ==========================================================================
1037 // INFOTRON touching up to down
1038 // ==========================================================================
1041 subCopyImageToScreen(*si, aniMurphyTouchDown);
1042 subSoundFXInfotron();
1043 dx = aniFramesTouchInfotron;
1044 dx1 = aniTouchInfotron;
1045 MovHighByte(&PlayField16[*si], 0x16);
1046 MovHighByte(&PlayField16[*si + FieldWidth], 0xFF);
1047 goto loc_StopNoSplit;
1049 // ==========================================================================
1050 // INFOTRON touching left to right
1051 // ==========================================================================
1054 subCopyImageToScreen(*si, aniMurphyTouchRight);
1055 subSoundFXInfotron();
1056 dx = aniFramesTouchInfotron;
1057 dx1 = aniTouchInfotron;
1058 MovHighByte(&PlayField16[*si], 0x17);
1059 MovHighByte(&PlayField16[*si + 1], 0xFF);
1060 goto loc_StopNoSplit;
1062 // ==========================================================================
1063 // EXIT pressed from any direction
1064 // ==========================================================================
1072 if (LowByte(InfotronsNeeded) != 0)
1076 if (!game_sp.LevelSolved)
1077 printf("::: Murphy.c: !!!!!!!!!! LEVEL %d SOLVED !!!!!!!!!!\n",LevelNumber);
1081 game_sp.LevelSolved = TRUE;
1085 data_h_DemoDone = 1; // EP set level success bytes
1086 LevelStatus = 1; // set Level Status DONE
1087 EP_GameDemoVar0DAA = 0; // force demo for lead-out
1088 if (SavedGameFlag == 0) // saved game running?
1090 if (UpdateTimeFlag != 0) // update time?
1092 UpdatedFlag = 1; // prevent double update
1093 subUpdatePlayingTime(); // update playing time
1098 subUpdateHallOfFame(); // update time + Hall-Of-Fame
1101 LeadOutCounter = 0x40; // quit: start lead-out
1102 dx = aniFramesMurphyExit;
1103 dx1 = aniMurphyExit;
1104 MovHighByte(&PlayField16[*si], 0xD);
1105 goto loc_StopNoSplit;
1107 // ==========================================================================
1108 // ZONK moving right to left
1109 // ==========================================================================
1112 ax = PlayField16[*si - 2];
1116 MovHighByte(&PlayField16[*si - 2], 1);
1117 subCopyImageToScreen(*si, aniPushLeft); // draw pushing murphy
1118 dx = aniFramesZonkRollLeft;
1119 dx1 = aniZonkRollLeft;
1123 MovHighByte(&PlayField16[*si], 0xE);
1124 goto loc_MoveNoSplit;
1126 // ==========================================================================
1127 // ZONK moving left to right
1128 // ==========================================================================
1131 ax = PlayField16[*si + 2];
1135 ax = PlayField16[*si + FieldWidth + 1];
1136 if (ax == 0) // zonk falls
1139 MovHighByte(&PlayField16[*si + 2], 1);
1140 subCopyImageToScreen(*si, aniPushRight); // draw pushing murphy
1141 dx = aniFramesZonkRollRight;
1142 dx1 = aniZonkRollRight;
1146 MovHighByte(&PlayField16[*si], 0xF);
1147 goto loc_MoveNoSplit;
1149 // ==========================================================================
1150 // TERMINAL moving/touching down to up
1151 // ==========================================================================
1154 subCopyImageToScreen(*si, aniMurphyTouchUp);
1155 if (YellowDisksExploded != 0)
1157 YawnSleepCounter = 40; // stay hypnotized
1163 // draw new terminal type
1165 GfxGraphic[GetX(*si - FieldWidth)][GetY(*si - FieldWidth)] = aniTerminalActive;
1167 subCopyImageToScreen(*si - FieldWidth, aniTerminalActive);
1170 subCopyFieldToScreen(*si - FieldWidth, 0x88); // draw new terminal type
1172 TerminalState[*si - FieldWidth] = 8;
1175 // ==========================================================================
1176 // TERMINAL moving/touching right to left
1177 // ==========================================================================
1180 subCopyImageToScreen(*si, aniMurphyTouchLeft);
1181 if (YellowDisksExploded != 0)
1183 YawnSleepCounter = 40; // stay hypnotized
1189 // draw new terminal type
1191 GfxGraphic[GetX(*si - 1)][GetY(*si - 1)] = aniTerminalActive;
1193 subCopyImageToScreen(*si - 1, aniTerminalActive);
1196 subCopyFieldToScreen(*si - 1, 0x88); // draw new terminal type
1198 TerminalState[*si - 1] = 8;
1201 // ==========================================================================
1202 // TERMINAL moving/touching up to down
1203 // ==========================================================================
1206 subCopyImageToScreen(*si, aniMurphyTouchDown);
1207 if (YellowDisksExploded != 0)
1209 YawnSleepCounter = 40; // stay hypnotized
1215 // draw new terminal type
1217 GfxGraphic[GetX(*si + FieldWidth)][GetY(*si + FieldWidth)] = aniTerminalActive;
1219 subCopyImageToScreen(*si + FieldWidth, aniTerminalActive);
1222 subCopyFieldToScreen(*si + FieldWidth, 0x88); // draw new terminal type
1224 TerminalState[*si + FieldWidth] = 8;
1227 // ==========================================================================
1228 // TERMINAL moving/touching left to right
1229 // ==========================================================================
1232 subCopyImageToScreen(*si, aniMurphyTouchRight);
1233 if (YellowDisksExploded != 0)
1235 YawnSleepCounter = 40; // stay hypnotized
1241 // draw new terminal type
1243 GfxGraphic[GetX(*si + 1)][GetY(*si + 1)] = aniTerminalActive;
1245 subCopyImageToScreen(*si + 1, aniTerminalActive);
1248 subCopyFieldToScreen(*si + 1, 0x88); // draw new terminal type
1250 TerminalState[*si + 1] = 8;
1251 // ==========================================================================
1252 // common TERMINAL stuff moving/touching from all directions
1253 // ==========================================================================
1256 TerminalMaxCycles = 7;
1257 YellowDisksExploded = 1;
1258 for (i = 0; i <= LevelMax; i++)
1260 if (PlayField16[i] == fiYellowDisk)
1266 // ==========================================================================
1267 // PORT down to up, VERTICAL PORT, CROSS PORT all moving down to up
1268 // ==========================================================================
1271 if (PlayField16[*si - 2 * FieldWidth] != 0)
1274 dx = aniFramesSplitUpDown;
1275 dx1 = aniSplitUpDown;
1276 dx2Step = -FieldWidth;
1277 PlayField16[*si] = 0x1803;
1278 PlayField16[*si - 2 * FieldWidth] = 0x300;
1281 // ==========================================================================
1282 // PORT right to left, HORIZONTAL PORT, CROSS PORT all moving right to left
1283 // ==========================================================================
1286 if (PlayField16[*si - 2] != 0)
1289 dx = aniFramesMurphyEatLeft;
1290 dx1 = aniMurphyMoveLeft;
1292 PlayField16[*si] = 0x1903;
1293 PlayField16[*si - 2] = 0x300;
1296 // ==========================================================================
1297 // PORT up to down, VERTICAL PORT, CROSS PORT all moving up to down
1298 // ==========================================================================
1301 if (PlayField16[*si + 2 * FieldWidth] != 0)
1304 dx = aniFramesSplitUpDown;
1305 dx1 = aniSplitUpDown;
1306 dx2Step = FieldWidth;
1307 PlayField16[*si] = 0x1A03;
1308 PlayField16[*si + 2 * FieldWidth] = 0x300;
1311 // ==========================================================================
1312 // PORT left to right, HORIZONTAL PORT, CROSS PORT all moving left to right
1313 // ==========================================================================
1316 if (PlayField16[*si + 2] != 0)
1319 dx = aniFramesMurphyEatRight;
1320 dx1 = aniMurphyMoveRight;
1322 PlayField16[*si] = 0x1B03;
1323 PlayField16[*si + 2] = 0x300;
1326 MovingPictureSequencePhase = 0; // stop picture move sequence
1327 SplitMoveFlag = 1; // port: split movement
1330 // ==========================================================================
1331 // RED DISK moving down to up
1332 // ==========================================================================
1335 dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
1336 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
1337 PlayField16[*si] = 0x1C03;
1338 PlayField16[*si - FieldWidth] = 0x300;
1339 goto loc_StopNoSplit;
1341 // ==========================================================================
1342 // RED DISK moving right to left
1343 // ==========================================================================
1346 dx = aniFramesMurphyEatLeft;
1347 dx1 = aniMurphyEatLeft;
1348 PlayField16[*si] = 0x300; // !!!!!! this time we move murphy at sequence-start!
1349 PlayField16[*si - 1] = 0x1D03;
1351 goto loc_StopNoSplit;
1353 // ==========================================================================
1354 // RED DISK moving up to down
1355 // ==========================================================================
1358 dx = (MurphyVarFaceLeft == 0 ? aniFramesMurphyEatUpRight : aniFramesMurphyEatUpLeft);
1359 dx1 = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpLeft);
1360 PlayField16[*si] = 0x1E03;
1361 PlayField16[*si + FieldWidth] = 0x300;
1362 goto loc_StopNoSplit;
1364 // ==========================================================================
1365 // RED DISK moving left to right
1366 // ==========================================================================
1369 // dx = aniFramesMurphyEatRightRedDisk 'this sequence is 9 steps long!
1370 dx = aniFramesMurphyEatRight;
1371 dx1 = aniMurphyEatRight;
1372 // --------------------------------------------------------------------------
1374 // Table data_h_145A, pointed to by table data_h_105E, has a severe bug:
1375 // The Red Disk sequence is 8 pictures long, but 9 are displayed, because it
1376 // has 1 extra entry, which causes Murphy to end slightly shifted to the left!
1377 // We may not fix the table, because then the timing of the game changes
1378 // and several existing demo's do not run properly anymore.
1379 // We only correct Murphies x-location here, when the sequence starts.
1380 // Remember that this is not the real bug-fix, but we must live with
1381 // this existing bug and correct for the consequences of it.
1384 if (0 == AllowEatRightRedDiskBug) // Murphy's screen x-position
1385 MurphyScreenXPos = MurphyScreenXPos - 2 * MurphyZoomFactor;
1387 if (0 == AllowEatRightRedDiskBug) // Murphy's screen x-position
1388 MurphyScreenXPos = MurphyScreenXPos - 2;
1392 // FS: for me this means to blit the first animation frame twice
1394 // --------------------------------------------------------------------------
1395 PlayField16[*si] = 0x300; // !!!!!! this time we move murphy at sequence-start!
1396 PlayField16[*si + 1] = 0x1F03;
1398 goto loc_StopNoSplit;
1400 // ==========================================================================
1401 // RED DISK touching down to up
1402 // ==========================================================================
1405 dx = aniFramesTouchRedDisk;
1406 dx1 = aniTouchRedDisk;
1407 MovHighByte(&PlayField16[*si], 0x20);
1408 MovHighByte(&PlayField16[*si - FieldWidth], 3);
1409 goto loc_StopNoSplit;
1411 // ==========================================================================
1412 // RED DISK touching right to left
1413 // ==========================================================================
1416 dx = aniFramesTouchRedDisk;
1417 dx1 = aniTouchRedDisk;
1418 MovHighByte(&PlayField16[*si], 0x21);
1419 MovHighByte(&PlayField16[*si - 1], 3);
1420 goto loc_StopNoSplit;
1422 // ==========================================================================
1423 // RED DISK touching up to down
1424 // ==========================================================================
1427 dx = aniFramesTouchRedDisk;
1428 dx1 = aniTouchRedDisk;
1429 MovHighByte(&PlayField16[*si], 0x22);
1430 MovHighByte(&PlayField16[*si + FieldWidth], 3);
1431 goto loc_StopNoSplit;
1433 // ==========================================================================
1434 // RED DISK touching left to right
1435 // ==========================================================================
1438 dx = aniFramesTouchRedDisk;
1439 dx1 = aniTouchRedDisk;
1440 MovHighByte(&PlayField16[*si], 0x23);
1441 MovHighByte(&PlayField16[*si + 1], 3);
1444 MovingPictureSequencePhase = 0; // stop picture move sequence
1447 // ==========================================================================
1448 // YELLOW DISK moving down to up
1449 // ==========================================================================
1452 if (PlayField16[*si - 2 * FieldWidth] != 0)
1455 PlayField16[*si - 2 * FieldWidth] = 0x1200;
1457 subCopyImageToScreen(*si, aniPushRight);
1459 dx = aniFramesYellowDisk;
1460 dx1 = aniYellowDisk;
1461 dxPos = *si - FieldWidth;
1463 dx2 = (MurphyVarFaceLeft == 0 ? aniPushRight : aniPushLeft);
1465 dx2 = aniPushUpDown;
1467 dx2Step = FieldWidth;
1468 PlayField16[*si] = 0x2403;
1470 subCopyImageToScreen(*si, dx2);
1472 goto loc_MoveNoSplit;
1474 // ==========================================================================
1475 // YELLOW DISK moving right to left
1476 // ==========================================================================
1479 if (PlayField16[*si - 2] != 0)
1482 PlayField16[*si - 2] = 0x1200;
1483 subCopyImageToScreen(*si, aniPushLeft);
1484 dx = aniFramesYellowDisk;
1485 dx1 = aniYellowDisk;
1489 PlayField16[*si] = 0x2503;
1490 goto loc_MoveNoSplit;
1492 // ==========================================================================
1493 // YELLOW DISK moving up to down
1494 // ==========================================================================
1497 if (PlayField16[*si + 2 * FieldWidth] != 0)
1500 PlayField16[*si + 2 * FieldWidth] = 0x1200;
1502 subCopyImageToScreen(*si, aniPushRight);
1504 dx = aniFramesYellowDisk;
1505 dx1 = aniYellowDisk;
1506 dxPos = *si + FieldWidth;
1508 dx2 = (MurphyVarFaceLeft == 0 ? aniPushRight : aniPushLeft);
1510 dx2 = aniPushUpDown;
1512 dx2Step = -FieldWidth;
1513 PlayField16[*si] = 0x2703;
1515 subCopyImageToScreen(*si, dx2);
1517 goto loc_MoveNoSplit;
1519 // ==========================================================================
1520 // YELLOW DISK moving left to right
1521 // ==========================================================================
1524 if (PlayField16[*si + 2] != 0)
1527 PlayField16[*si + 2] = 0x1200;
1528 subCopyImageToScreen(*si, aniPushRight);
1529 dx = aniFramesYellowDisk;
1530 dx1 = aniYellowDisk;
1534 PlayField16[*si] = 0x2603;
1535 goto loc_MoveNoSplit;
1537 // ==========================================================================
1538 // ORANGE DISK moving right to left
1539 // ==========================================================================
1542 if (PlayField16[*si - 2] != 0)
1545 PlayField16[*si - 2] = 0x800;
1546 subCopyImageToScreen(*si, aniPushLeft);
1547 dx = aniFramesOrangeDisk;
1548 dx1 = aniOrangeDisk;
1552 PlayField16[*si] = 0x2803;
1553 goto loc_MoveNoSplit;
1555 // ==========================================================================
1556 // ORANGE DISK moving left to right
1557 // ==========================================================================
1560 if (PlayField16[*si + 2] != 0)
1563 if (PlayField16[*si + FieldWidth + 1] == 0) // falling goes before pushing
1566 PlayField16[*si + 2] = 0x100;
1567 subCopyImageToScreen(*si, aniPushRight);
1568 dx = aniFramesOrangeDisk;
1569 dx1 = aniOrangeDisk;
1573 PlayField16[*si] = 0x2903;
1574 // ==========================================================================
1575 // Copy screen animation action table to action work space
1576 // (To paint sequence: Push Zonk/Disk / release red disk / Port passing)
1577 // ==========================================================================
1580 MovingPictureSequencePhase = 8; // init picture move sequence
1583 SplitMoveFlag = 0; // no port: no split movement
1586 // copy/store global move sequence info????????????????????????????????????
1587 // ... dont think so ...(FS)
1588 // ==========================================================================
1589 // Proceed with all movements
1590 // ==========================================================================
1592 locProceedMovingMurphy: // proceed moving murphy
1593 YawnSleepCounter = 0; // Wake up sleeping Murphy
1594 ax = MovingPictureSequencePhase; // sequence busy?
1595 if (ax == 0) // no -- start sequence!
1598 ax = ax - 1; // next picture of sequence
1599 MovingPictureSequencePhase = ax; // store for later
1600 if (ax == 0) // Sound effects
1603 bl = HighByte(PlayField16[*si]);
1604 if (bl == 0xE) // Push Zonk to left
1607 if (bl == 0xF) // Push Zonk to right
1610 if (bl == 0x28) // Push orange disk to left
1613 if (bl == 0x29) // Push orange disk to right
1616 if (bl == 0x24) // Push yellow disk up
1619 if (bl == 0x25) // Push yellow disk to left
1622 if (bl == 0x27) // Push yellow disk down
1625 if (bl == 0x26) // Push yellow disk to right
1628 if (bl == 0x2A) // Red disk release timer
1633 // ==========================================================================
1634 // Paint frame of MOVING.DAT sequence
1635 // ==========================================================================
1641 dx1SequenceLength = getSequenceLength(dx1);
1644 if (SplitMoveFlag == 0)
1646 // ++++++++++++++++++++++++++
1647 // Begin of normal movement
1649 MurphyScreenXPos = MurphyScreenXPos + MurphyDX * MurphyZoomFactor;
1650 MurphyScreenYPos = MurphyScreenYPos + MurphyDY * MurphyZoomFactor;
1652 MurphyScreenXPos = MurphyScreenXPos + MurphyDX;
1653 MurphyScreenYPos = MurphyScreenYPos + MurphyDY;
1658 printf("::: %04d [%03ld, %02d] ----------> %s [%d] [%d, %d] [%d, %d] [%d]\n",
1660 DemoOffset - DemoPointer, DemoKeyRepeatCounter,
1661 (DemoKeyCode == keyNone ? "(none)" :
1662 DemoKeyCode == keyLeft ? "left" :
1663 DemoKeyCode == keyRight ? "right" :
1664 DemoKeyCode == keyUp ? "up" :
1665 DemoKeyCode == keyDown ? "down" :
1666 DemoKeyCode == keySpace ? "space" :
1667 DemoKeyCode == keySpaceLeft ? "space + left" :
1668 DemoKeyCode == keySpaceRight ? "space + right" :
1669 DemoKeyCode == keySpaceUp ? "space + up" :
1670 DemoKeyCode == keySpaceDown ? "space + down" : "(unknown)"),
1672 MurphyScreenXPos, MurphyScreenYPos,
1673 MurphyPosIndex % 60, MurphyPosIndex / 60,
1682 if (!(ClearPos < 0)) // clear field that murphy is leaving
1683 subCopyImageToScreen(ClearPos, aniSpace);
1685 if (! ClearPos < 0) // clear field that murphy is leaving
1686 subCopyFieldToScreen(ClearPos, 0);
1690 printf("::: ---------------> %d, %d [%d, %d]\n",
1691 MurphyScreenXPos, MurphyScreenYPos, MurphyDX, MurphyDY);
1695 // !!! special two-tile animation currently not used !!!
1696 if (dx2 == fiInfotron) // special case of infotron moving left or right
1704 tDeltaX = MurphyDX * LocalStretch * (SeqPos + 1);
1705 tDeltaY = MurphyDY * LocalStretch * (SeqPos + 1);
1708 X = GetStretchX(dxPos) + tDeltaX;
1709 Y = GetStretchY(dxPos) + tDeltaY;
1710 Tmp = (SeqPos < 0 ? 0 : SeqPos); // 9StepBugFix!(red disk move right)
1713 if (isSnappingSequence(dx1) && SeqPos == dx1SequenceLength - 1)
1718 StretchedSprites.BltImg(X, Y, dx1, Tmp);
1719 GfxGraphic[GetX(*si)][GetY(*si)] = -1; // (Murphy's position)
1720 GfxGraphic[GetX(dxPos)][GetY(dxPos)] = -1; // (snapping position)
1721 // printf("::: Tmp: %d\n", Tmp);
1723 StretchedSprites.BltEx(X, Y, dx[Tmp]);
1732 tPos = dxPos + dx2Step;
1733 X = GetStretchX(tPos);
1734 Y = GetStretchY(tPos);
1736 // !!! special two-tile animation currently not used !!!
1737 if (dx2 == fiInfotron) // special case of infotron moving left or right
1739 StretchedSprites.BltEx(X, Y, dx[SeqPos] + dx2Step);
1741 else // pushing something
1745 // (SeqPos iterates from 0 to 7 while pushing)
1746 StretchedSprites.BltImg(X + tDeltaX, Y + tDeltaY, dx2, SeqPos);
1747 // printf("::: SeqPos: %d\n", SeqPos);
1749 StretchedSprites.BltEx(X + tDeltaX, Y + tDeltaY, dx2);
1754 // End of normal movement
1755 // ------------------------
1759 // ++++++++++++++++++++++++++++++++
1760 // Begin of split movement (port)
1762 MurphyScreenXPos = MurphyScreenXPos + 2 * MurphyDX * MurphyZoomFactor;
1763 MurphyScreenYPos = MurphyScreenYPos + 2 * MurphyDY * MurphyZoomFactor;
1765 MurphyScreenXPos = MurphyScreenXPos + 2 * MurphyDX;
1766 MurphyScreenYPos = MurphyScreenYPos + 2 * MurphyDY;
1768 subCopyImageToScreen(ClearPos, aniSpace); // clear the field that murphy leaves
1769 tDeltaX = MurphyDX * LocalStretch * (SeqPos + 1);
1770 tDeltaY = MurphyDY * LocalStretch * (SeqPos + 1);
1771 X = GetStretchX(dxPos) + tDeltaX;
1772 Y = GetStretchY(dxPos) + tDeltaY;
1774 StretchedSprites.BltImg(X, Y, dx1, SeqPos); // plot first murphy
1776 StretchedSprites.BltEx(X, Y, dx[SeqPos]); // plot first murphy
1778 tPos = dxPos + dx2Step;
1779 X = GetStretchX(tPos);
1780 Y = GetStretchY(tPos);
1782 StretchedSprites.BltImg(X + tDeltaX, Y + tDeltaY, dx1, SeqPos); // plot second murphy
1783 StretchedSprites.BltImg(X, Y, fiGraphic[LowByte(PlayField16[tPos])], 0); // replot the port on top
1785 StretchedSprites.BltEx(X + tDeltaX, Y + tDeltaY, dx[SeqPos]); // plot second murphy
1786 StretchedSprites.BltEx(X, Y, LowByte(PlayField16[tPos])); // replot the port on top
1788 // End of split movement (port)
1789 // ------------------------------
1790 } // loc_g_6D1E:'loc_g_6D28:
1792 SeqPos = SeqPos + 1;
1794 if (SeqPos < dx1SequenceLength)
1797 if (dx[SeqPos] > -1)
1801 // Follow-up after movement completed 'loc_g_6D35:
1802 MurphyXPos = MurphyXPos + MurphyDX;
1803 MurphyYPos = MurphyYPos + MurphyDY;
1804 bl = HighByte(PlayField16[*si]); // animation phase
1805 MovHighByte(&PlayField16[*si], 0);
1807 if (bl == 0x1) // space, moving up
1810 if (bl == 0x2) // space, moving left
1813 if (bl == 0x3) // space, moving down
1816 if (bl == 0x4) // space, moving right
1819 if (bl == 0x5) // base , moving up
1822 if (bl == 0x6) // base , moving left -> 6 is not used, value is set to 2 instead of 6!
1825 if (bl == 0x7) // base , moving down
1828 if (bl == 0x8) // base , moving right
1831 if (bl == 0x9) // infotron, moving up
1834 if (bl == 0xA) // infotron, moving left
1837 if (bl == 0xB) // infotron, moving down
1840 if (bl == 0xC) // infotron, moving right
1843 if (bl == 0xD) // exit
1846 if (bl == 0xE) // zonk, pushing left
1849 if (bl == 0xF) // zonk, pushing right
1852 if (bl == 0x10) // base , touching up
1855 if (bl == 0x11) // base , touching left
1858 if (bl == 0x12) // base , touching down
1861 if (bl == 0x13) // base , touching right
1864 if (bl == 0x14) // infotron touching up
1867 if (bl == 0x15) // infotron touching left
1870 if (bl == 0x16) // infotron touching down
1873 if (bl == 0x17) // infotron touching right
1876 if (bl == 0x18) // port up
1879 if (bl == 0x19) // port left
1882 if (bl == 0x1A) // port down
1885 if (bl == 0x1B) // port right
1888 if (bl == 0x1C) // red disk, moving up
1891 if (bl == 0x1D) // red disk, moving left
1894 if (bl == 0x1E) // red disk, moving down
1897 if (bl == 0x1F) // red disk, moving right -> 9-Step-Bug!
1900 if (bl == 0x20) // red disk, touching up
1903 if (bl == 0x21) // red disk, touching left
1906 if (bl == 0x22) // red disk, touching down
1909 if (bl == 0x23) // red disk, touching right
1912 if (bl == 0x24) // yellow disk, pushing up
1915 if (bl == 0x25) // yellow disk, pushing left
1918 if (bl == 0x26) // yellow disk, pushing right -> order of "down" exchanged with "right"!
1921 if (bl == 0x27) // yellow disk, pushing down -> order of "down" exchanged with "right"!
1924 if (bl == 0x28) // orange disk, pushing left
1927 if (bl == 0x29) // orange disk, pushing right
1930 if (bl == 0x2A) // red disk, release
1937 // ==========================================================================
1938 // infotron, moving up
1939 // ==========================================================================
1942 if (0 < LowByte(InfotronsNeeded))
1943 InfotronsNeeded = InfotronsNeeded - 1;
1945 subDisplayInfotronsNeeded();
1946 loc_g_6EC8: // space, base
1947 PlayField16[*si] = fiMurphy;
1948 subAdjustZonksInfotronsAboveMurphy(*si + FieldWidth);
1952 // ==========================================================================
1953 // infotron, moving left
1954 // ==========================================================================
1957 if (0 < LowByte(InfotronsNeeded))
1958 InfotronsNeeded = InfotronsNeeded - 1;
1960 subDisplayInfotronsNeeded();
1961 loc_g_6EE6: // space, base
1962 PlayField16[*si] = fiMurphy;
1963 subAdjustZonksInfotronsAboveMurphy(*si + 1);
1967 // ==========================================================================
1968 // infotron, moving down
1969 // ==========================================================================
1972 if (0 < LowByte(InfotronsNeeded))
1973 InfotronsNeeded = InfotronsNeeded - 1;
1975 subDisplayInfotronsNeeded();
1976 loc_g_6F04: // space, base
1977 if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion)
1978 PlayField16[*si - FieldWidth] = 0;
1980 PlayField16[*si] = fiMurphy;
1984 // ==========================================================================
1985 // infotron, moving right
1986 // ==========================================================================
1989 if (0 < LowByte(InfotronsNeeded))
1990 InfotronsNeeded = InfotronsNeeded - 1;
1992 subDisplayInfotronsNeeded();
1993 loc_g_71C4: // space, base
1994 subAdjustZonksInfotronsAboveMurphy(*si - 1);
1995 PlayField16[*si] = fiMurphy;
1999 // ==========================================================================
2000 // infotron, touching up
2001 // ==========================================================================
2004 if (0 < LowByte(InfotronsNeeded))
2005 InfotronsNeeded = InfotronsNeeded - 1;
2007 subDisplayInfotronsNeeded();
2009 if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion)
2010 PlayField16[*si - FieldWidth] = 0;
2014 // ==========================================================================
2015 // infotron, touching left
2016 // ==========================================================================
2019 if (0 < LowByte(InfotronsNeeded))
2020 InfotronsNeeded = InfotronsNeeded - 1;
2022 subDisplayInfotronsNeeded();
2024 if (LowByte(PlayField16[*si - 1]) != fiExplosion)
2025 PlayField16[*si - 1] = 0;
2029 // ==========================================================================
2030 // infotron, touching down
2031 // ==========================================================================
2034 if (0 < LowByte(InfotronsNeeded))
2035 InfotronsNeeded = InfotronsNeeded - 1;
2037 subDisplayInfotronsNeeded();
2039 if (LowByte(PlayField16[*si + FieldWidth]) != fiExplosion)
2040 PlayField16[*si + FieldWidth] = 0;
2044 // ==========================================================================
2045 // infotron, touching right
2046 // ==========================================================================
2049 if (0 < LowByte(InfotronsNeeded))
2050 InfotronsNeeded = InfotronsNeeded - 1;
2052 subDisplayInfotronsNeeded();
2054 if (LowByte(PlayField16[*si + 1]) != fiExplosion)
2055 PlayField16[*si + 1] = 0;
2059 // ==========================================================================
2060 // zonk, pushing left
2061 // ==========================================================================
2064 if (LowByte(PlayField16[*si]) != fiExplosion)
2065 PlayField16[*si] = 0;
2067 PlayField16[*si - 1] = fiMurphy;
2068 PlayField16[*si - 2] = fiZonk;
2069 subExplodeSnikSnaksBelow(*si - 2);
2074 // ==========================================================================
2075 // zonk, pushing right
2076 // ==========================================================================
2079 if (LowByte(PlayField16[*si]) != fiExplosion)
2080 PlayField16[*si] = 0;
2082 PlayField16[*si + 1] = fiMurphy;
2083 PlayField16[*si + 2] = fiZonk;
2084 subExplodeSnikSnaksBelow(*si + 2);
2089 // ==========================================================================
2091 // ==========================================================================
2097 PlayField16[*si] = fiSpace; // remove Murphy from playfield after exiting
2102 // ==========================================================================
2103 // Push Zonk from right to left
2104 // ==========================================================================
2107 if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiZonk)
2110 PlayField16[*si] = fiMurphy; // else restore - no more zonk pushing!
2111 PlayField16[*si - 1] = fiZonk;
2112 if (LowByte(PlayField16[*si - 2]) != fiExplosion)
2113 PlayField16[*si - 2] = 0;
2115 subCopyImageToScreen(*si, aniMurphy);
2119 // ==========================================================================
2120 // Push Zonk from left to right
2121 // ==========================================================================
2124 if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiZonk)
2127 PlayField16[*si] = fiMurphy; // else restore - no more zonk pushing!
2128 PlayField16[*si + 1] = fiZonk;
2129 if (LowByte(PlayField16[*si + 2]) != fiExplosion)
2130 PlayField16[*si + 2] = 0;
2132 subCopyImageToScreen(*si, aniMurphy);
2136 // ==========================================================================
2137 // Push orange disk from right to left
2138 // ==========================================================================
2141 if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiOrangeDisk)
2144 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2145 PlayField16[*si - 1] = fiOrangeDisk;
2146 if (LowByte(PlayField16[*si - 2]) != fiExplosion)
2147 PlayField16[*si - 2] = 0;
2149 subCopyImageToScreen(*si, aniMurphy);
2153 // ==========================================================================
2154 // Push orange disk from left to right
2155 // ==========================================================================
2158 if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiOrangeDisk)
2161 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2162 PlayField16[*si + 1] = fiOrangeDisk;
2163 if (LowByte(PlayField16[*si + 2]) != fiExplosion)
2164 PlayField16[*si + 2] = 0;
2166 subCopyImageToScreen(*si, aniMurphy);
2170 // ==========================================================================
2171 // Push yellow disk from down to up
2172 // ==========================================================================
2175 if (DemoKeyCode == keyUp && PlayField16[*si - FieldWidth] == fiYellowDisk)
2178 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2179 PlayField16[*si - FieldWidth] = fiYellowDisk;
2180 if (LowByte(PlayField16[*si - 2 * FieldWidth]) != fiExplosion)
2181 PlayField16[*si - 2 * FieldWidth] = 0;
2183 subCopyImageToScreen(*si, aniMurphy);
2187 // ==========================================================================
2188 // Push yellow disk from right to left
2189 // ==========================================================================
2192 if (DemoKeyCode == keyLeft && PlayField16[*si - 1] == fiYellowDisk)
2195 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2196 PlayField16[*si - 1] = fiYellowDisk;
2197 if (LowByte(PlayField16[*si - 2]) != fiExplosion)
2198 PlayField16[*si - 2] = 0;
2200 subCopyImageToScreen(*si, aniMurphy);
2204 // ==========================================================================
2205 // Push yellow disk from up to down
2206 // ==========================================================================
2209 if (DemoKeyCode == keyDown && PlayField16[*si + FieldWidth] == fiYellowDisk)
2212 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2213 PlayField16[*si + FieldWidth] = fiYellowDisk;
2214 if (LowByte(PlayField16[*si + 2 * FieldWidth]) != fiExplosion)
2215 PlayField16[*si + 2 * FieldWidth] = 0;
2217 subCopyImageToScreen(*si, aniMurphy);
2221 // ==========================================================================
2222 // Push yellow disk from left to right
2223 // ==========================================================================
2226 if (DemoKeyCode == keyRight && PlayField16[*si + 1] == fiYellowDisk)
2229 PlayField16[*si] = fiMurphy; // else restore - no more pushing!
2230 PlayField16[*si + 1] = fiYellowDisk;
2231 if (LowByte(PlayField16[*si + 2]) != fiExplosion)
2232 PlayField16[*si + 2] = 0;
2234 subCopyImageToScreen(*si, aniMurphy);
2238 // ==========================================================================
2239 // time red disk release (space)
2240 // ==========================================================================
2243 if (DemoKeyCode != keySpace)
2245 PlayField16[*si] = fiMurphy;
2246 subCopyImageToScreen(*si, aniMurphy);
2247 RedDiskReleasePhase = 0;
2249 else if (MovingPictureSequencePhase == 0x20)
2252 // anxious murphy, dropping red disk
2253 subCopyImageToScreen(*si, aniMurphyDropping);
2255 subCopyFieldToScreen(*si, 43); // anxious murphy
2257 RedDiskReleasePhase = 1;
2262 // ==========================================================================
2263 // Special port down to up
2264 // ==========================================================================
2267 if (LowByte(PlayField16[*si]) != fiExplosion)
2268 PlayField16[*si] = 0;
2270 PlayField16[*si - 2 * FieldWidth] = fiMurphy;
2272 *si = *si - FieldWidth;
2273 if (HighByte(PlayField16[*si]) == 1)
2276 *si = *si - FieldWidth;
2280 // ==========================================================================
2281 // Special port right to left
2282 // ==========================================================================
2285 if (LowByte(PlayField16[*si]) != fiExplosion)
2286 PlayField16[*si] = 0;
2288 PlayField16[*si - 2] = fiMurphy;
2291 if (HighByte(PlayField16[*si]) == 1)
2298 // ==========================================================================
2299 // Special port up to down
2300 // ==========================================================================
2303 if (LowByte(PlayField16[*si]) != fiExplosion)
2304 PlayField16[*si] = 0;
2306 PlayField16[*si + 2 * FieldWidth] = fiMurphy;
2308 *si = *si + FieldWidth;
2309 if (HighByte(PlayField16[*si]) == 1)
2312 *si = *si + FieldWidth;
2316 // ==========================================================================
2317 // Special port left to right
2318 // ==========================================================================
2321 if (LowByte(PlayField16[*si]) != fiExplosion)
2322 PlayField16[*si] = 0;
2324 PlayField16[*si + 2] = fiMurphy;
2327 if (HighByte(PlayField16[*si]) == 1)
2334 // ==========================================================================
2336 // ==========================================================================
2339 if (LowByte(PlayField16[*si]) != fiExplosion)
2340 PlayField16[*si] = 0;
2342 *si = *si - FieldWidth;
2343 PlayField16[*si] = fiMurphy;
2344 subEatRedDisk(*si); // inc+show Murphy's red disks
2348 // ==========================================================================
2349 // Move Red Disk left
2350 // ==========================================================================
2353 if (LowByte(PlayField16[*si + 1]) != fiExplosion)
2354 PlayField16[*si + 1] = 0;
2356 PlayField16[*si] = fiMurphy;
2357 subEatRedDisk(*si); // inc+show Murphy's red disks
2361 // ==========================================================================
2362 // Move Red Disk down
2363 // ==========================================================================
2366 if (LowByte(PlayField16[*si]) != fiExplosion)
2367 PlayField16[*si] = 0;
2369 *si = *si + FieldWidth;
2370 PlayField16[*si] = fiMurphy;
2371 subEatRedDisk(*si); // inc+show Murphy's red disks
2375 // ==========================================================================
2376 // Move Red Disk right
2377 // ==========================================================================
2380 if (LowByte(PlayField16[*si - 1]) != fiExplosion)
2381 PlayField16[*si - 1] = 0;
2383 PlayField16[*si] = fiMurphy;
2384 subEatRedDisk(*si); // inc+show Murphy's red disks
2388 // ==========================================================================
2390 // ==========================================================================
2393 if (LowByte(PlayField16[*si - FieldWidth]) != fiExplosion)
2394 PlayField16[*si - FieldWidth] = 0;
2396 subEatRedDisk(*si - FieldWidth); // inc+show Murphy's red disks
2400 // ==========================================================================
2401 // Eat Red Disk left
2402 // ==========================================================================
2405 if (LowByte(PlayField16[*si - 1]) != fiExplosion)
2406 PlayField16[*si - 1] = 0;
2408 subEatRedDisk(*si - 1); // inc+show Murphy's red disks
2412 // ==========================================================================
2413 // Eat Red Disk down
2414 // ==========================================================================
2417 if (LowByte(PlayField16[*si + FieldWidth]) != fiExplosion)
2418 PlayField16[*si + FieldWidth] = 0;
2420 subEatRedDisk(*si + FieldWidth); // inc+show Murphy's red disks
2424 // ==========================================================================
2425 // Eat Red Disk right
2426 // ==========================================================================
2429 if (LowByte(PlayField16[*si + 1]) != fiExplosion)
2430 PlayField16[*si + 1] = 0;
2432 subEatRedDisk(*si + 1); // inc+show Murphy's red disks
2436 // ==========================================================================
2437 // yellow disk, pushing up
2438 // ==========================================================================
2441 if (LowByte(PlayField16[*si]) != fiExplosion)
2442 PlayField16[*si] = 0;
2444 *si = *si - FieldWidth;
2445 PlayField16[*si] = fiMurphy;
2446 PlayField16[*si - FieldWidth] = fiYellowDisk;
2450 // ==========================================================================
2451 // yellow disk, pushing left
2452 // ==========================================================================
2455 if (LowByte(PlayField16[*si]) != fiExplosion)
2456 PlayField16[*si] = 0;
2459 PlayField16[*si] = fiMurphy;
2460 PlayField16[*si - 1] = fiYellowDisk;
2464 // ==========================================================================
2465 // yellow disk, pushing down
2466 // ==========================================================================
2469 if (LowByte(PlayField16[*si]) != fiExplosion)
2470 PlayField16[*si] = 0;
2472 *si = *si + FieldWidth;
2473 PlayField16[*si] = fiMurphy;
2474 PlayField16[*si + FieldWidth] = fiYellowDisk;
2478 // ==========================================================================
2479 // yellow disk pushing right
2480 // ==========================================================================
2483 if (LowByte(PlayField16[*si]) != fiExplosion)
2484 PlayField16[*si] = 0;
2487 PlayField16[*si] = fiMurphy;
2488 PlayField16[*si + 1] = fiYellowDisk;
2492 // ==========================================================================
2493 // orange disk, pushing left
2494 // ==========================================================================
2497 if (LowByte(PlayField16[*si]) != fiExplosion)
2498 PlayField16[*si] = 0;
2501 PlayField16[*si] = fiMurphy;
2502 PlayField16[*si - 1] = fiOrangeDisk;
2506 // ==========================================================================
2507 // orange disk, pushing right
2508 // ==========================================================================
2511 if (LowByte(PlayField16[*si]) != fiExplosion)
2512 PlayField16[*si] = 0;
2515 PlayField16[*si] = fiMurphy;
2516 PlayField16[*si + 1] = fiOrangeDisk;
2517 if (PlayField16[*si + FieldWidth + 1] == 0) // make it fall down if below is empty
2519 MovHighByte(&PlayField16[*si + 1], 0x20);
2520 MovHighByte(&PlayField16[*si + FieldWidth + 1], fiOrangeDisk);
2525 // ==========================================================================
2526 // Release a red disk
2527 // ==========================================================================
2530 PlayField16[*si] = fiMurphy;
2531 RedDiskReleasePhase = 2;
2532 RedDiskCount = RedDiskCount - 1;
2533 subDisplayRedDiskCount();
2534 subSoundFXPush(); // Sound effects
2535 } // subAnimateMurphy
2537 // ==========================================================================
2539 // ==========================================================================
2540 void subExplodeSnikSnaksBelow(int si)
2544 ax = LowByte(PlayField16[si + FieldWidth]);
2545 if (ax == 0x11 || ax == 0xBB)
2546 ExplodeFieldSP(si + FieldWidth);
2547 } // subExplodeSnikSnaksBelow
2549 // ==========================================================================
2551 // Does pushing against an object kill Murphy?
2552 // ==========================================================================
2553 static boolean subMoveKillsMurphy(int si, int ax, int bl)
2555 static boolean subMoveKillsMurphy;
2561 if (ax == 0xFFFF || ax == 0xAAAA || ah == 0)
2567 if (al == fiExplosion)
2570 if (fiOrangeDisk <= al && al <= fiPortUp)
2573 ExplodeFieldSP(si); // Explode
2574 subMoveKillsMurphy = True;
2575 return subMoveKillsMurphy;
2584 ExplodeFieldSP(si); // Explode
2585 subMoveKillsMurphy = True;
2586 return subMoveKillsMurphy;
2588 loc_g_74F6: // zonk left
2590 if (! (ah == 0x20 || ah == 0x40 || ah == 0x50 || ah == 0x70))
2593 subMoveKillsMurphy = True; // Set carry flag
2594 return subMoveKillsMurphy;
2596 loc_g_7512: // zonk right
2598 if (! (ah == 0x30 || ah == 0x40 || ah == 0x60 || ah == 0x70))
2601 loc_g_752E: // Marked fields and Ports
2602 subMoveKillsMurphy = True; // Set carry flag
2603 return subMoveKillsMurphy;
2605 loc_g_7530: // explosion
2606 if ((ah & 0x80) != 0)
2613 ExplodeFieldSP(si); // Explode
2614 subMoveKillsMurphy = True; // Set carry flag
2615 return subMoveKillsMurphy;
2618 PlayField16[si] = 0;
2619 subMoveKillsMurphy = False;
2621 return subMoveKillsMurphy;
2622 } // subMoveKillsMurphy
2624 // ==========================================================================
2626 // Test If si 's a special (grav) port and If so Then fetch new values (see below)
2627 // change conditions to port specs
2628 // The 10-port data base is at data_h_0D28, 10 entries of 6 bytes each:
2629 // (hi),(lo),(gravity),(freeze zonks),(freeze enemies),(unused)
2630 // ==========================================================================
2631 int subSpPortTest(int si)
2638 cx = LInfo.SpecialPortCount; // number of special ports
2640 for (i = 0; i < cx; i++)
2643 /* this assumes that PortLocation is stored as big endian */
2644 bx = LInfo.SpecialPort[i].PortLocation;
2646 /* this assumes that PortLocation is stored as little endian */
2647 bx = HighByte(LInfo.SpecialPort[i].PortLocation);
2648 MovHighByte(&bx, LowByte(LInfo.SpecialPort[i].PortLocation));
2653 GravityFlag = LInfo.SpecialPort[i].Gravity;
2654 FreezeZonks = LInfo.SpecialPort[i].FreezeZonks;
2655 SnikSnaksElectronsFrozen = LInfo.SpecialPort[i].FreezeEnemies;
2657 // RandomTime = RandomTime Xor RandomSeed 'is RandomTime used at all? no!
2665 cx = LInfo.SpecialPortCount; // number of special ports
2666 for (i = 1; i <= cx; i++)
2669 bx = HighByte(LInfo.SpecialPort[i].PortLocation);
2670 MovHighByte(&bx, LowByte(LInfo.SpecialPort[i].PortLocation));
2673 GravityFlag = LInfo.SpecialPort[i].Gravity;
2674 FreezeZonks = LInfo.SpecialPort[i].FreezeZonks;
2675 SnikSnaksElectronsFrozen = LInfo.SpecialPort[i].FreezeEnemies;
2676 // RandomTime = RandomTime Xor RandomSeed 'is RandomTime used at all? no!
2683 return subSpPortTest;
2688 void subCopyFieldToScreen(int si, int fi)
2692 // +++++++++++++++++++++++++++++++++++++++++
2693 X = GetStretchX(si);
2694 Y = GetStretchY(si);
2695 StretchedSprites.BltEx(X, Y, fi);
2696 // +++++++++++++++++++++++++++++++++++++++++
2701 void subCopyAnimToScreen(int si, int graphic, int sync_frame)
2705 // +++++++++++++++++++++++++++++++++++++++++
2706 X = GetStretchX(si);
2707 Y = GetStretchY(si);
2708 StretchedSprites.BltImg(X, Y, graphic, sync_frame);
2709 // +++++++++++++++++++++++++++++++++++++++++
2712 void subCopyImageToScreen(int si, int graphic)
2714 subCopyAnimToScreen(si, graphic, 0);
2717 static void subEatRedDisk(int si)
2719 if (AllowRedDiskCheat == 0)
2721 if (RedDiskReleasePhase != 0)
2723 if (RedDiskReleaseMurphyPos == si)
2728 RedDiskCount = (RedDiskCount + 1) % 256;
2729 subDisplayRedDiskCount();
2732 void subAdjustZonksInfotronsAboveMurphy(int si)
2736 if (LowByte(PlayField16[si]) != fiExplosion)
2737 PlayField16[si] = 0;
2739 ax = PlayField16[si - FieldWidth];
2740 if (ax == 0 || ax == 0x9999)
2743 if (ax == fiZonk || ax == fiInfotron)
2745 MovHighByte(&PlayField16[si - FieldWidth], 0x40); // make falling straigt down
2750 loc_g_15A8: // empty above
2751 ax = PlayField16[si - FieldWidth - 1];
2752 if (ax == fiZonk || ax == fiInfotron)
2756 ax = PlayField16[si - FieldWidth + 1];
2757 if (ax == fiZonk || ax == fiInfotron)
2762 loc_g_15C5: // zonk/infotron above left
2763 ax = PlayField16[si - 1];
2764 if (! (ax == fiZonk || ax == fiInfotron || ax == fiRAM)) // continue testing right above
2767 MovHighByte(&PlayField16[si - FieldWidth - 1], 0x60); // make roll right
2768 PlayField16[si - FieldWidth] = 0x8888;
2772 loc_g_15E8: // zonk/infotron above right
2773 ax = PlayField16[si + 1];
2774 if (ax == fiZonk || ax == fiInfotron || ax == fiRAM)
2776 MovHighByte(&PlayField16[si - FieldWidth + 1], 0x50); // make roll left
2777 PlayField16[si - FieldWidth] = 0x8888;
2779 } // subAdjustZonksInfotronsAboveMurphy