]> 4ch.mooo.com Git - 16.git/blobdiff - 16/keen456/KEEN4-6/KEEN5/K5_SPEC.C
extrcted keen code remake
[16.git] / 16 / keen456 / KEEN4-6 / KEEN5 / K5_SPEC.C
diff --git a/16/keen456/KEEN4-6/KEEN5/K5_SPEC.C b/16/keen456/KEEN4-6/KEEN5/K5_SPEC.C
new file mode 100755 (executable)
index 0000000..4248954
--- /dev/null
@@ -0,0 +1,1158 @@
+/* Reconstructed Commander Keen 4-6 Source Code\r
+ * Copyright (C) 2021 K1n9_Duk3\r
+ *\r
+ * This file is loosely based on:\r
+ * Keen Dreams Source Code\r
+ * Copyright (C) 2014 Javier M. Chavez\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License along\r
+ * with this program; if not, write to the Free Software Foundation, Inc.,\r
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ */\r
+\r
+/*\r
+K5_SPEC.C\r
+=========\r
+\r
+Contains (in this order):\r
+\r
+- lump definition\r
+- "Star Wars" crawl text\r
+- level names & messages\r
+- Airlock opening & closing code\r
+- ScanInfoPlane() - for spawning the level objects and marking required sprites\r
+- game over animation\r
+- messages for breaking fuses\r
+*/\r
+\r
+#include "CK_DEF.H"\r
+\r
+enum {\r
+       HELP_LUMP,        //  0\r
+       CONTROLS_LUMP,    //  1\r
+       KEENTALK_LUMP,    //  2\r
+       LOADING_LUMP,     //  3\r
+       PADDLE_LUMP,      //  4\r
+       KEEN_LUMP,        //  5\r
+       SUGAR1_LUMP,      //  6\r
+       SUGAR2_LUMP,      //  7\r
+       SUGAR3_LUMP,      //  8\r
+       SUGAR4_LUMP,      //  9\r
+       SUGAR5_LUMP,      // 10\r
+       SUGAR6_LUMP,      // 11\r
+       ONEUP_LUMP,       // 12\r
+       KEYGEM_LUMP,      // 13\r
+       AMMO_LUMP,        // 14\r
+       LASER_LUMP,       // 15\r
+       WORLDKEEN_LUMP,   // 16\r
+       MASTER_LUMP,      // 17\r
+       SHIKADI_LUMP,     // 18\r
+       SHOCKSHUND_LUMP,  // 19\r
+       SPHEREFUL_LUMP,   // 20\r
+       SPARKY_LUMP,      // 21\r
+       MINE_LUMP,        // 22\r
+       SLICESTAR_LUMP,   // 23\r
+       ROBORED_LUMP,     // 24\r
+       SPIRO_LUMP,       // 25\r
+       AMPTON_LUMP,      // 26\r
+       VOLTE_LUMP,       // 27\r
+       SLOTPLAT_LUMP,    // 28\r
+       SPINDRED_LUMP,    // 29\r
+       SHELLEY_LUMP,     // 30\r
+       PLATFORM_LUMP,    // 31\r
+       SMALLPLAT_LUMP,   // 32\r
+       KEYCARD_LUMP,     // 33\r
+       SCOTTIE_LUMP,     // 34\r
+       FUSE_LUMP,        // 35\r
+       STAREXPLODE_LUMP, // 36\r
+       TELEPORT_LUMP,    // 37\r
+\r
+       NUMLUMPS=42       // Keen 5 has 4 unused lumps at the end\r
+};\r
+\r
+Uint16 lumpstart[NUMLUMPS] = {\r
+       HELP_LUMP_START,\r
+       CONTROLS_LUMP_START,\r
+       KEENTALK_LUMP_START,\r
+       LOADING_LUMP_START,\r
+       PADDLE_LUMP_START,\r
+       KEEN_LUMP_START,\r
+       SUGAR1_LUMP_START,\r
+       SUGAR2_LUMP_START,\r
+       SUGAR3_LUMP_START,\r
+       SUGAR4_LUMP_START,\r
+       SUGAR5_LUMP_START,\r
+       SUGAR6_LUMP_START,\r
+       ONEUP_LUMP_START,\r
+       KEYGEM_LUMP_START,\r
+       AMMO_LUMP_START,\r
+       LASER_LUMP_START,\r
+       WORLDKEEN_LUMP_START,\r
+       MASTER_LUMP_START,\r
+       SHIKADI_LUMP_START,\r
+       SHOCKSHUND_LUMP_START,\r
+       SPHEREFUL_LUMP_START,\r
+       SPARKY_LUMP_START,\r
+       MINE_LUMP_START,\r
+       SLICESTAR_LUMP_START,\r
+       ROBORED_LUMP_START,\r
+       SPIRO_LUMP_START,\r
+       AMPTON_LUMP_START,\r
+       VOLTE_LUMP_START,\r
+       SLOTPLAT_LUMP_START,\r
+       SPINDRED_LUMP_START,\r
+       SHELLEY_LUMP_START,\r
+       PLATFORM_LUMP_START,\r
+       MINIPLAT_LUMP_START,\r
+       KEYCARD_LUMP_START,\r
+       SCOTTIE_LUMP_START,\r
+       FUSE_LUMP_START,\r
+       STAREXPLODE_LUMP_START,\r
+       TELEPORT_LUMP_START\r
+};\r
+\r
+Uint16 lumpend[NUMLUMPS] = {\r
+       HELP_LUMP_END,\r
+       CONTROLS_LUMP_END,\r
+       KEENTALK_LUMP_END,\r
+       LOADING_LUMP_END,\r
+       PADDLE_LUMP_END,\r
+       KEEN_LUMP_END,\r
+       SUGAR1_LUMP_END,\r
+       SUGAR2_LUMP_END,\r
+       SUGAR3_LUMP_END,\r
+       SUGAR4_LUMP_END,\r
+       SUGAR5_LUMP_END,\r
+       SUGAR6_LUMP_END,\r
+       ONEUP_LUMP_END,\r
+       KEYGEM_LUMP_END,\r
+       AMMO_LUMP_END,\r
+       LASER_LUMP_END,\r
+       WORLDKEEN_LUMP_END,\r
+       MASTER_LUMP_END,\r
+       SHIKADI_LUMP_END,\r
+       SHOCKSHUND_LUMP_END,\r
+       SPHEREFUL_LUMP_END,\r
+       SPARKY_LUMP_END,\r
+       MINE_LUMP_END,\r
+       SLICESTAR_LUMP_END,\r
+       ROBORED_LUMP_END,\r
+       SPIRO_LUMP_END,\r
+       AMPTON_LUMP_END,\r
+       VOLTE_LUMP_END,\r
+       SLOTPLAT_LUMP_END,\r
+       SPINDRED_LUMP_END,\r
+       SHELLEY_LUMP_END,\r
+       PLATFORM_LUMP_END,\r
+       MINIPLAT_LUMP_END,\r
+       KEYCARD_LUMP_END,\r
+       SCOTTIE_LUMP_END,\r
+       FUSE_LUMP_END,\r
+       STAREXPLODE_LUMP_END,\r
+       TELEPORT_LUMP_END\r
+};\r
+\r
+boolean lumpneeded[NUMLUMPS];\r
+\r
+#if GRMODE == EGAGR\r
+\r
+char far swtext[] =\r
+       "Episode Five\n"\r
+       "\n"\r
+       "The Armageddon Machine\n"\r
+       "\n"\r
+       "After learning the\n"\r
+       "location of the secret\n"\r
+       "Shikadi base, Keen\n"\r
+       "jumped in the trusty\n"\r
+       "Bean-with-Bacon\n"\r
+       "Megarocket and blasted\n"\r
+       "across interstellar\n"\r
+       "space.\n"\r
+       "\n"\r
+       "Seventy-five furious\n"\r
+       "games of Paddle War\n"\r
+       "later, Keen dropped\n"\r
+       "out of lightspeed near\n"\r
+       " the Korath system.\n"\r
+       "\n"\r
+       "He flew toward the\n"\r
+       "planet, keeping it\n"\r
+       "between him and the\n"\r
+       "base.\n"\r
+       "\n"\r
+       "Pulling up underside\n"\r
+       "and docking at the\n"\r
+       "Ion Ventilation System,\n"\r
+       "Keen must destroy the\n"\r
+       "Shikadi Armageddon\n"\r
+       "Machine before it\n"\r
+       "explodes and destroys\n"\r
+       "the Milky Way!  He\n"\r
+       "steps into the dark\n"\r
+       "ventilation duct and\n"\r
+       "begins his most\n"\r
+       "dangerous adventure\n"\r
+       "yet...\n";\r
+\r
+#endif\r
+\r
+char far l0n[] = "Omegamatic";\r
+char far l1n[] = "Ion Ventilation System";\r
+char far l2n[] = "Security Center";\r
+char far l3n[] = "Defense Tunnel Vlook";\r
+char far l4n[] = "Energy Flow Systems";\r
+char far l5n[] = "Defense Tunnel Burrh";\r
+char far l6n[] = "Regulation\nControl Center";\r
+char far l7n[] = "Defense Tunnel Sorra";\r
+char far l8n[] = "Neutrino\nBurst Injector";\r
+char far l9n[] = "Defense Tunnel Teln";\r
+char far l10n[] = "Brownian\nMotion Inducer";\r
+char far l11n[] = "Gravitational\nDamping Hub";\r
+char far l12n[] = "Quantum\nExplosion Dynamo";\r
+char far l13n[] = "Korath III Base";\r
+char far l14n[] = "BWBMegarocket";\r
+char far l15n[] = "High Scores";\r
+\r
+char far l0e[] = "Keen purposefully\nwanders about the\nOmegamatic";\r
+char far l1e[] = "Keen investigates the\nIon Ventilation System";\r
+char far l2e[] = "Keen struts through\nthe Security Center";\r
+char far l3e[] = "Keen invades\nDefense Tunnel Vlook";\r
+char far l4e[] = "Keen engages\nEnergy Flow Systems";\r
+char far l5e[] = "Keen barrels into\nDefense Tunnel Burrh";\r
+char far l6e[] = "Keen goes nuts in\nthe Regulation\nControl Center";\r
+char far l7e[] = "Keen regrets entering\nDefense Tunnel Sorra";\r
+char far l8e[] = "Keen blows through\nthe Neutrino\nBurst Injector";\r
+char far l9e[] = "Keen trots through\nDefense Tunnel Teln";\r
+char far l10e[] = "Keen breaks into\nthe Brownian\nMotion Inducer";\r
+char far l11e[] = "Keen hurries through\nthe Gravitational\nDamping Hub";\r
+char far l12e[] = "Keen explodes into\nthe Quantum\nExplosion Dynamo";\r
+char far l13e[] = "Keen faces danger\nin the secret\nKorath III Base";\r
+char far l14e[] = "Keen will not be\nin the BWBMegarocket";\r
+char far l15e[] = "Keen unexplainedly\nfinds himself by\ntheHigh Scores";      // sic!\r
+\r
+char far *levelnames[GAMELEVELS] = {\r
+       l0n,\r
+       l1n,\r
+       l2n,\r
+       l3n,\r
+       l4n,\r
+       l5n,\r
+       l6n,\r
+       l7n,\r
+       l8n,\r
+       l9n,\r
+       l10n,\r
+       l11n,\r
+       l12n,\r
+       l13n,\r
+       l14n,\r
+       l15n\r
+};\r
+\r
+char far *levelenter[GAMELEVELS] = {\r
+       l0e,\r
+       l1e,\r
+       l2e,\r
+       l3e,\r
+       l4e,\r
+       l5e,\r
+       l6e,\r
+       l7e,\r
+       l8e,\r
+       l9e,\r
+       l10e,\r
+       l11e,\r
+       l12e,\r
+       l13e,\r
+       l14e,\r
+       l15e\r
+};\r
+\r
+Uint16 bonuslump[] = {\r
+       KEYGEM_LUMP, KEYGEM_LUMP, KEYGEM_LUMP, KEYGEM_LUMP,\r
+       SUGAR1_LUMP, SUGAR2_LUMP, SUGAR3_LUMP,\r
+       SUGAR4_LUMP, SUGAR5_LUMP, SUGAR6_LUMP,\r
+       ONEUP_LUMP, AMMO_LUMP, KEYCARD_LUMP, 0, 0\r
+};\r
+\r
+//============================================================================\r
+\r
+/*\r
+===========================\r
+=\r
+= OpenMapDoor\r
+=\r
+===========================\r
+*/\r
+\r
+void OpenMapDoor(Sint16 tileX, Sint16 tileY)\r
+{\r
+       Sint16 x, y;\r
+       Uint16 tiles[2][2];\r
+\r
+       for (y=0; y<2; y++)\r
+       {\r
+               for (x=0; x<2; x++)\r
+               {\r
+                       tiles[y][x] = *(mapsegs[1]+mapbwidthtable[y]/2 + x + 10);\r
+               }\r
+       }\r
+       RF_MemToMap(&tiles[0][0], 1, tileX, tileY, 2, 2);\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= CloseMapDoor\r
+=\r
+===========================\r
+*/\r
+\r
+void CloseMapDoor(Sint16 tileX, Sint16 tileY)\r
+{\r
+       Sint16 x, y;\r
+       Uint16 tiles[2][2];\r
+\r
+       for (y=0; y<2; y++)\r
+       {\r
+               for (x=0; x<2; x++)\r
+               {\r
+                       tiles[y][x] = *(mapsegs[1]+mapbwidthtable[y]/2 + x);\r
+               }\r
+       }\r
+       RF_MemToMap(&tiles[0][0], 1, tileX, tileY, 2, 2);\r
+}\r
+\r
+//============================================================================\r
+\r
+/*\r
+==========================\r
+=\r
+= ScanInfoPlane\r
+=\r
+= Spawn all actors and mark down special places\r
+=\r
+==========================\r
+*/\r
+\r
+void ScanInfoPlane(void)\r
+{\r
+       Uint16 i, x, y, chunk;\r
+       Sint16 info;\r
+       Uint16 far *map;\r
+       objtype *ob;\r
+\r
+       InitObjArray();                  // start spawning things with a clean slate\r
+\r
+       memset(lumpneeded, 0, sizeof(lumpneeded));\r
+       gamestate.numfuses = 0;\r
+\r
+       map = mapsegs[2];\r
+\r
+       for (y=0; y<mapheight; y++)\r
+       {\r
+               for (x=0; x<mapwidth; x++)\r
+               {\r
+                       info = *map++;\r
+\r
+                       if (info == 0)\r
+                               continue;\r
+\r
+                       switch (info)\r
+                       {\r
+                       case 1:\r
+                               SpawnKeen(x, y, 1);\r
+                               SpawnScore();\r
+                               lumpneeded[KEEN_LUMP] = true;\r
+                               CA_MarkGrChunk(SCOREBOXSPR);\r
+                               break;\r
+\r
+                       case 2:\r
+                               SpawnKeen(x, y, -1);\r
+                               SpawnScore();\r
+                               lumpneeded[KEEN_LUMP] = true;\r
+                               CA_MarkGrChunk(SCOREBOXSPR);\r
+                               break;\r
+\r
+                       case 3:\r
+                               SpawnScore();\r
+                               lumpneeded[WORLDKEEN_LUMP] = true;\r
+                               CA_MarkGrChunk(SCOREBOXSPR);\r
+                               if (playstate == ex_portout)\r
+                                       break;\r
+                               SpawnWorldKeen(x, y);\r
+                               break;\r
+\r
+                       case 26:\r
+                               if (playstate != ex_portout)\r
+                                       break;\r
+                               SpawnWorldKeenPort(x, y);\r
+                               break;\r
+\r
+                       case 6:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 5:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 4:\r
+                               SpawnSparky(x, y);\r
+                               lumpneeded[SPARKY_LUMP] = true;\r
+                               break;\r
+\r
+                       case 9:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 8:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 7:\r
+                               SpawnMine(x, y);\r
+                               lumpneeded[MINE_LUMP] = true;\r
+                               break;\r
+\r
+                       case 12:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 11:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 10:\r
+                               SpawnSlicestarSlide(x, y, 0);\r
+                               lumpneeded[SLICESTAR_LUMP] = true;\r
+                               break;\r
+\r
+                       case 15:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 14:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 13:\r
+                               SpawnRoboRed(x, y);\r
+                               lumpneeded[ROBORED_LUMP] = true;\r
+                               break;\r
+\r
+                       case 18:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 17:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 16:\r
+                               SpawnSpirogrip(x, y);\r
+                               lumpneeded[SPIRO_LUMP] = true;\r
+                               break;\r
+\r
+                       case 21:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 20:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 19:\r
+                               SpawnSlicestarBounce(x, y);\r
+                               lumpneeded[SLICESTAR_LUMP] = true;\r
+                               break;\r
+\r
+                       case 24:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 23:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 22:\r
+                               SpawnSlicestarSlide(x, y, 1);\r
+                               lumpneeded[SLICESTAR_LUMP] = true;\r
+                               break;\r
+\r
+                       case 25:\r
+                               RF_SetScrollBlock(x, y, true);\r
+                               break;\r
+\r
+                       // case 26 (teleported map keen) is handled above\r
+\r
+                       case 27:\r
+                       case 28:\r
+                       case 29:\r
+                       case 30:\r
+                               SpawnPlatform(x, y, info-27, 0);\r
+                               lumpneeded[PLATFORM_LUMP] = true;\r
+                               break;\r
+\r
+                       // case 31 is the block icon\r
+\r
+                       case 32:\r
+                               SpawnDropPlat(x, y);\r
+                               lumpneeded[PLATFORM_LUMP] = true;\r
+                               break;\r
+\r
+                       case 35:\r
+                               SpawnStaticPlat(x, y);\r
+                               lumpneeded[PLATFORM_LUMP] = true;\r
+                               break;\r
+                       case 34:\r
+                               if (gamestate.difficulty > gd_Normal)\r
+                                       break;\r
+                               SpawnStaticPlat(x, y);\r
+                               lumpneeded[PLATFORM_LUMP] = true;\r
+                               break;\r
+                       case 33:\r
+                               if (gamestate.difficulty > gd_Easy)\r
+                                       break;\r
+                               SpawnStaticPlat(x, y);\r
+                               lumpneeded[PLATFORM_LUMP] = true;\r
+                               break;\r
+\r
+                       case 36:\r
+                       case 37:\r
+                       case 38:\r
+                       case 39:\r
+                               SpawnGoPlat(x, y, info-36, 0);\r
+                               lumpneeded[PLATFORM_LUMP] = true;\r
+                               break;\r
+\r
+                       case 40:\r
+                               SpawnSneakPlat(x, y);\r
+                               lumpneeded[PLATFORM_LUMP] = true;\r
+                               break;\r
+\r
+                       case 41:\r
+                               if (gamestate.mapon == 12)\r
+                               {\r
+                                       gamestate.numfuses = 4;\r
+                                       SpawnQed(x, y);\r
+                               }\r
+                               else\r
+                               {\r
+                                       gamestate.numfuses++;\r
+                               }\r
+                               lumpneeded[FUSE_LUMP] = true;\r
+                               break;\r
+\r
+                       case 44:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 43:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 42:\r
+                               SpawnAmpton(x, y);\r
+                               lumpneeded[AMPTON_LUMP] = true;\r
+                               break;\r
+\r
+                       case 53:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 49:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 45:\r
+                               SpawnCannon(x, y, 0);\r
+                               lumpneeded[LASER_LUMP] = true;\r
+                               break;\r
+\r
+                       case 54:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 50:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 46:\r
+                               SpawnCannon(x, y, 1);\r
+                               lumpneeded[LASER_LUMP] = true;\r
+                               break;\r
+\r
+                       case 55:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 51:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 47:\r
+                               SpawnCannon(x, y, 2);\r
+                               lumpneeded[LASER_LUMP] = true;\r
+                               break;\r
+\r
+                       case 56:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 52:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 48:\r
+                               SpawnCannon(x, y, 3);\r
+                               lumpneeded[LASER_LUMP] = true;\r
+                               break;\r
+\r
+                       case 69:\r
+                               if (gamestate.ammo >= 5)\r
+                                       break;\r
+                               info = 68;      // spawn ammo\r
+                               //no break here!\r
+                       case 57:\r
+                       case 58:\r
+                       case 59:\r
+                       case 60:\r
+                       case 61:\r
+                       case 62:\r
+                       case 63:\r
+                       case 64:\r
+                       case 65:\r
+                       case 66:\r
+                       case 67:\r
+                       case 68:\r
+                               SpawnBonus(x, y, info-57);\r
+                               lumpneeded[bonuslump[info-57]] = true;\r
+                               break;\r
+                       case 70:\r
+                               SpawnBonus(x, y, info-58);\r
+                               lumpneeded[bonuslump[info-58]] = true;\r
+                               break;\r
+\r
+                       case 73:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 72:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 71:\r
+                               SpawnVolte(x, y);\r
+                               lumpneeded[VOLTE_LUMP] = true;\r
+                               break;\r
+\r
+                       case 76:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 75:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 74:\r
+                               SpawnShelly(x, y);\r
+                               lumpneeded[SHELLEY_LUMP] = true;\r
+                               break;\r
+\r
+                       case 79:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 78:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 77:\r
+                               SpawnSpindread(x, y);\r
+                               lumpneeded[SPINDRED_LUMP] = true;\r
+                               break;\r
+\r
+                       case 80:\r
+                       case 81:\r
+                       case 82:\r
+                       case 83:\r
+                               SpawnGoPlat(x, y, info-80, 1);\r
+                               lumpneeded[SLOTPLAT_LUMP] = true;\r
+                               break;\r
+\r
+                       case 84:\r
+                       case 85:\r
+                       case 86:\r
+                       case 87:\r
+                               SpawnPlatform(x, y, info-84, 1);\r
+                               lumpneeded[SLOTPLAT_LUMP] = true;\r
+                               break;\r
+\r
+                       case 90:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 89:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 88:\r
+                               SpawnMaster(x, y);\r
+                               lumpneeded[MASTER_LUMP] = true;\r
+                               break;\r
+\r
+                       // cases 91 to 98 are direction arrows\r
+\r
+                       case 101:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 100:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 99:\r
+                               SpawnShikadi(x, y);\r
+                               lumpneeded[SHIKADI_LUMP] = true;\r
+                               break;\r
+\r
+                       case 104:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 103:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 102:\r
+                               SpawnPet(x, y);\r
+                               lumpneeded[SHOCKSHUND_LUMP] = true;\r
+                               break;\r
+\r
+                       case 107:\r
+                               if (gamestate.difficulty < gd_Hard)\r
+                                       break;\r
+                       case 106:\r
+                               if (gamestate.difficulty < gd_Normal)\r
+                                       break;\r
+                       case 105:\r
+                               SpawnSphereful(x, y);\r
+                               lumpneeded[SPHEREFUL_LUMP] = true;\r
+                               break;\r
+\r
+                       // cases 108 to 123 are wall collision icons for the WallDebug cheat\r
+\r
+                       case 124:\r
+                               SpawnScottie(x, y);\r
+                               lumpneeded[SCOTTIE_LUMP] = true;\r
+                               break;\r
+\r
+                       case 125:\r
+                               lumpneeded[TELEPORT_LUMP] = true;\r
+\r
+                       }\r
+               }\r
+       }\r
+\r
+       for (ob = player; ob; ob = ob->next)\r
+       {\r
+               if (ob->active != ac_allways)\r
+                       ob->active = ac_no;\r
+       }\r
+\r
+       for (i = 0; i < NUMLUMPS; i++)\r
+       {\r
+               if (lumpneeded[i])\r
+               {\r
+                       for (chunk = lumpstart[i]; chunk <= lumpend[i]; chunk++)\r
+                       {\r
+                               CA_MarkGrChunk(chunk);\r
+                       }\r
+               }\r
+       }\r
+\r
+       // Keen 5 addition to PatchWorldMap (PatchWorldMap is shared across Keen 4-6)\r
+       if (gamestate.mapon == 0)\r
+       {\r
+               info = CONVERT_GLOBAL_TO_TILE(player->y);\r
+               if (info < 75 || info > 100)\r
+               {\r
+                       CloseMapDoor(24, 76);\r
+                       OpenMapDoor(22, 55);\r
+               }\r
+               if (gamestate.leveldone[4] && gamestate.leveldone[6] && gamestate.leveldone[8] && gamestate.leveldone[10]\r
+                       && (info > 39 || info > 100) )\r
+               {\r
+                       OpenMapDoor(26, 55);\r
+               }\r
+               if (info <= 39 || info > 100)\r
+               {\r
+                       OpenMapDoor(24, 30);\r
+               }\r
+       }\r
+}\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                 GAME OVER SEQUENCE\r
+\r
+=============================================================================\r
+*/\r
+\r
+/*\r
+------------------------------------------------------------------------------\r
+The galaxy explosion chunk contains data in the following format:\r
+\r
+struct {\r
+       Uint16 posx[4000];\r
+       Uint16 velx[4000];\r
+       Uint16 posy[4000];\r
+       Uint16 vely[4000];\r
+};\r
+\r
+The values are stored as "fixed point" numbers (divide each number by 128 to\r
+get the amount in pixel units). The code in MoveStars basically does the\r
+following:\r
+\r
+1.     set all pixels on the screen to black\r
+\r
+2.     for each of the 4000 entries do:\r
+\r
+2.1    x := posx[i] + velx[i]\r
+\r
+2.2    if x (in pixels) is < 0 or > 320 then go to 2.8\r
+\r
+2.3    posx[i] := x\r
+\r
+2.4    y := posy[i] + vely[i]\r
+\r
+2.5    if y (in pixels) is < 0 or > 200 then go to 2.8\r
+\r
+2.6    posy[i] := y\r
+\r
+2.7    draw a white pixel at position (x, y) on the screen\r
+\r
+2.8    continue with the next entry\r
+\r
+------------------------------------------------------------------------------\r
+*/\r
+\r
+#if GRMODE == CGAGR\r
+\r
+Uint8 plotpixels[8] = {0xC0, 0x30, 0x0C, 0x03};\r
+\r
+/*\r
+===========================\r
+=\r
+= MoveStars   CGA\r
+=\r
+===========================\r
+*/\r
+\r
+void MoveStars(void)\r
+{\r
+       asm {\r
+               mov     ax, screenseg;\r
+               mov     es, ax;\r
+               mov     ds, word ptr grsegs + 2*GALAXY;\r
+               mov     cx, 2000h;\r
+               xor     ax, ax;\r
+               xor     di, di;\r
+               rep stosw;\r
+               mov     si, 7998;\r
+       }\r
+l1:\r
+       asm {\r
+               mov     ax, [si];               // get posx\r
+               add     ax, [si+8000];          // add velx\r
+               cmp     ax, 40960;              // check if new posx is on screen\r
+               ja      l2;\r
+               mov     [si], ax;               // set new posx\r
+               mov     bx, [si+16000];         // get posy\r
+               add     bx, [si+24000];         // add vely\r
+               cmp     bx, 25600;              // check if new posy is on screen\r
+               ja      l2;\r
+               mov     [si+16000], bx;         // set new posy\r
+               mov     cl, 7;\r
+               shr     bx, cl;\r
+               shl     bx, 1;\r
+               mov     di, word ptr ss:ylookup[bx];\r
+               mov     bx, ax;\r
+               mov     cl, 9;\r
+               shr     ax, cl;\r
+               add     di, ax;\r
+               mov     cl, 7;\r
+               shr     bx, cl;\r
+               and     bx, 3;\r
+               mov     al, BYTE PTR ss:plotpixels[bx];\r
+               or              es:[di], al;            // draw the pixel\r
+       }\r
+l2:\r
+       asm {\r
+               sub     si, 2;\r
+               jns     l1;\r
+               mov     ax, ss;\r
+               mov     ds, ax;\r
+       }\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= GameOver   CGA\r
+=\r
+===========================\r
+*/\r
+\r
+void GameOver(void)\r
+{\r
+       Sint16 i;\r
+\r
+       FreeGraphics();\r
+       CA_CacheGrChunk(MILKYWAYPIC);\r
+       CA_CacheGrChunk(GALAXY);\r
+       CA_CacheGrChunk(GAMEOVERPIC);\r
+       RF_FixOfs();\r
+       VW_ClearVideo(BLACK);\r
+       VWB_DrawPic(0, 0, MILKYWAYPIC);\r
+       VW_UpdateScreen();\r
+\r
+       SD_WaitSoundDone();\r
+       SD_PlaySound(SND_GAMEOVER2);\r
+       SD_WaitSoundDone();\r
+       SD_PlaySound(SND_GAMEOVER1);\r
+\r
+       IN_ClearKeysDown();\r
+       VW_SetLineWidth(80);\r
+\r
+       for (i=0; i<60; i++)\r
+       {\r
+               lasttimecount = TimeCount;\r
+               MoveStars();\r
+               VW_UpdateScreen();\r
+\r
+               do {} while (TimeCount-lasttimecount < 4);\r
+\r
+               if (LastScan)\r
+                       break;\r
+       }\r
+\r
+       VW_SetLineWidth(SCREENWIDTH);\r
+       VW_ClearVideo(BLACK);\r
+       StartMusic(18);\r
+       VWB_DrawPic(32, 80, GAMEOVERPIC);\r
+       VW_UpdateScreen();\r
+       IN_UserInput(24*TickBase, false);\r
+       StopMusic();\r
+}\r
+\r
+//============================================================================\r
+\r
+#else\r
+\r
+Uint16 dim[18] = {8, 8, 7, 15, 7, 8, 0, 8, 7, 15, 7, 8, 0, 0, 0, 0, 0, 0};\r
+Uint16 bright[18] = {7, 7, 7, 7, 7, 15, 7, 8, 0, 7, 15, 7, 8, 0, 0, 0, 0, 0};\r
+Uint8 galaxycolors[17] = {0, 1, 2, 3, 4, 5, 6, 7, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 3};\r
+Uint8 plotpixels[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};\r
+\r
+/*\r
+===========================\r
+=\r
+= MoveStars   EGA\r
+=\r
+===========================\r
+*/\r
+\r
+void MoveStars(Uint16 dest)\r
+{\r
+       asm {\r
+               mov     dx, GC_INDEX;\r
+               mov     al, GC_BITMASK;\r
+               out     dx, al;\r
+               inc     dx;\r
+               mov     ds, word ptr grsegs + 2*GALAXY;\r
+               mov     ax, 0A000h;\r
+               mov     es, ax;\r
+               mov     cx, 1000h;\r
+               xor     ax, ax;\r
+               mov     di, dest;\r
+               rep stosw;\r
+               mov     si, 7998;\r
+       }\r
+l1:\r
+       asm {\r
+               mov     ax, [si];               // get posx\r
+               add     ax, [si+8000];          // add velx\r
+               cmp     ax, 40960;              // check if new posx is on screen\r
+               ja      l2;\r
+               mov     [si], ax;               // set new posx\r
+               mov     bx, [si+16000];         // get posy\r
+               add     bx, [si+24000];         // add vely\r
+               cmp     bx, 25600;              // check if new posy is on screen\r
+               ja      l2;\r
+               mov     [si+16000], bx;         // set new posy\r
+               mov     cl, 7;\r
+               shr     bx, cl;\r
+               shl     bx, 1;\r
+               mov     di, word ptr ss:ylookup[bx];\r
+               add     di, dest;\r
+               mov     bx, ax;\r
+               mov     cl, 10;\r
+               shr     ax, cl;\r
+               add     di, ax;\r
+               mov     cl, 7;\r
+               shr     bx, cl;\r
+               and     bx, 7;\r
+               mov     al, BYTE PTR ss:plotpixels[bx];\r
+               out     dx, al;\r
+               mov     al, 0Fh;\r
+               xchg    al, es:[di];            // draw the pixel\r
+       }\r
+l2:\r
+       asm {\r
+               sub     si, 2;\r
+               jns     l1;\r
+               mov     ax, ss;\r
+               mov     ds, ax;\r
+               mov     al, 0FFh;\r
+               out     dx, al;\r
+       }\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= SetCrtc   EGA\r
+=\r
+===========================\r
+*/\r
+\r
+void SetCrtc(Uint16 addr)\r
+{\r
+       asm {\r
+               cli;\r
+               mov     cx, addr;\r
+               mov     dx, CRTC_INDEX;\r
+               mov     al, CRTC_STARTHIGH;\r
+               out     dx, al;\r
+               inc     dx;\r
+               mov     al, ch;\r
+               out     dx, al;\r
+               dec     dx;\r
+               mov     al, CRTC_STARTLOW;\r
+               out     dx, al;\r
+               inc     dx;\r
+               mov     al, cl;\r
+               out     dx, al;\r
+               sti;\r
+       }\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= GameOver   EGA\r
+=\r
+===========================\r
+*/\r
+\r
+void GameOver(void)\r
+{\r
+       Sint16 i;\r
+\r
+       FreeGraphics();\r
+       VW_FadeOut();\r
+       CA_CacheGrChunk(MILKYWAYPIC);\r
+       CA_CacheGrChunk(GALAXY);\r
+       CA_CacheGrChunk(GAMEOVERPIC);\r
+       VW_SetLineWidth(40);\r
+       VW_SetScreen(0, 0);\r
+       bufferofs = 0;\r
+       VW_ClearVideo(0);\r
+       VW_DrawPic(0, 0, MILKYWAYPIC);\r
+       VW_ScreenToScreen(0, 0x2000, 40, 200);\r
+       VW_FadeIn();\r
+       IN_ClearKeysDown();\r
+       SD_PlaySound(SND_GAMEOVER2);\r
+\r
+       for (i=0; i<18; i++)\r
+       {\r
+               galaxycolors[8] = dim[i];\r
+               galaxycolors[7] = bright[i];\r
+\r
+               SetPalette(galaxycolors);\r
+\r
+               VW_WaitVBL(10);\r
+               if (LastScan)\r
+                       goto gameover;\r
+       }\r
+\r
+       EGAWRITEMODE(2);\r
+       EGAMAPMASK(15);\r
+       SD_PlaySound(SND_GAMEOVER1);\r
+\r
+       for (i=0; i<30; i++)\r
+       {\r
+               lasttimecount = TimeCount;\r
+               MoveStars(0x2000);\r
+               SetCrtc(0x2000);\r
+               do {} while (TimeCount-lasttimecount < 4);\r
+\r
+               lasttimecount = TimeCount;\r
+               MoveStars(0);\r
+               SetCrtc(0);\r
+               do {} while (TimeCount-lasttimecount < 4);\r
+\r
+               if (LastScan)\r
+                       goto gameover;\r
+       }\r
+\r
+gameover:\r
+       EGAWRITEMODE(0);\r
+       VW_ClearVideo(BLACK);\r
+       VW_SetLineWidth(SCREENWIDTH);\r
+       VW_SetDefaultColors();\r
+       RF_FixOfs();\r
+       StartMusic(18);\r
+       VWB_DrawPic(32, 80, GAMEOVERPIC);\r
+       VW_UpdateScreen();\r
+       IN_UserInput(24*TickBase, false);\r
+       StopMusic();\r
+}\r
+\r
+#endif\r
+\r
+//============================================================================\r
+\r
+/*\r
+===========================\r
+=\r
+= FinishedFuse\r
+=\r
+===========================\r
+*/\r
+\r
+void FinishedFuse(void)\r
+{\r
+       SD_WaitSoundDone();\r
+       CA_UpLevel();\r
+#if 0\r
+       // bugfix:\r
+       CA_ClearMarks();        // don't cache more than we actually need here\r
+#endif\r
+       CA_MarkGrChunk(KEENTALK1PIC);\r
+       CA_MarkGrChunk(KEENTALK2PIC);\r
+       CA_CacheMarks(NULL);\r
+\r
+       VW_FixRefreshBuffer();\r
+       US_CenterWindow(26, 8);\r
+       WindowW -= 48;\r
+       VWB_DrawPic(WindowX+WindowW, WindowY, KEENTALK1PIC);\r
+       PrintY += 12;\r
+       if (gamestate.mapon == 13)\r
+       {\r
+               US_CPrint(\r
+                       "I wonder what that\n"\r
+                       "fuse was for....\n"\r
+                       );\r
+       }\r
+       else\r
+       {\r
+               US_CPrint(\r
+                       "One of the four\n"\r
+                       "machines protecting the\n"\r
+                       "main elevator shaft--\n"\r
+                       "toast!\n"\r
+                       );\r
+       }\r
+       VW_UpdateScreen();\r
+       VW_WaitVBL(30);\r
+       IN_ClearKeysDown();\r
+       IN_Ack();\r
+\r
+       VWB_DrawPic(WindowX+WindowW, WindowY, KEENTALK2PIC);\r
+       VW_UpdateScreen();\r
+       VW_WaitVBL(30);\r
+       IN_ClearKeysDown();\r
+       IN_Ack();\r
+\r
+       CA_DownLevel();\r
+       StopMusic();\r
+}
\ No newline at end of file