]> 4ch.mooo.com Git - 16.git/blobdiff - 16/keen456/KEEN4-6/CK_MAIN.C
extrcted keen code remake
[16.git] / 16 / keen456 / KEEN4-6 / CK_MAIN.C
diff --git a/16/keen456/KEEN4-6/CK_MAIN.C b/16/keen456/KEEN4-6/CK_MAIN.C
new file mode 100755 (executable)
index 0000000..b8e7153
--- /dev/null
@@ -0,0 +1,531 @@
+/* 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
+// CK_MAIN.C\r
+/*\r
+=============================================================================\r
+\r
+                                                       COMMANDER KEEN\r
+\r
+                                       An Id Software production\r
+\r
+=============================================================================\r
+*/\r
+\r
+#include "CK_DEF.H"\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                GLOBAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+boolean tedlevel;\r
+Uint16 tedlevelnum;\r
+\r
+char str[80], str2[20];\r
+boolean storedemo, jerk;\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                LOCAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+//===========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= SizeText\r
+=\r
+= Calculates width and height of a string that contains line breaks\r
+= (Note: only the height is ever used, width is NOT calculated correctly)\r
+=\r
+=====================\r
+*/\r
+\r
+void SizeText(char *text, Uint16 *width, Uint16 *height)\r
+{\r
+       register char *ptr;\r
+       char c;\r
+       Uint16 w, h;\r
+       char strbuf[80];\r
+\r
+       *width = *height = 0;\r
+       ptr = &strbuf[0];\r
+       while ((c=*(text++)) != '\0')\r
+       {\r
+               *(ptr++) = c;\r
+               if (c == '\n' || !*text)\r
+               {\r
+                       USL_MeasureString(strbuf, &w, &h);      // BUG: strbuf may not have a terminating '\0' at the end!\r
+                       *height += h;\r
+                       if (*width < w)\r
+                       {\r
+                               *width = w;\r
+                       }\r
+                       ptr = &strbuf[0];\r
+               }\r
+       }\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+==========================\r
+=\r
+= ShutdownId\r
+=\r
+= Shuts down all ID_?? managers\r
+=\r
+==========================\r
+*/\r
+\r
+void ShutdownId(void)\r
+{\r
+       US_Shutdown();\r
+       SD_Shutdown();\r
+       IN_Shutdown();\r
+       RF_Shutdown();\r
+       VW_Shutdown();\r
+       CA_Shutdown();\r
+       MM_Shutdown();\r
+}\r
+\r
+\r
+//===========================================================================\r
+\r
+/*\r
+==========================\r
+=\r
+= InitGame\r
+=\r
+= Load a few things right away\r
+=\r
+==========================\r
+*/\r
+\r
+void InitGame(void)\r
+{\r
+       static char *ParmStrings[] = {"JERK", ""};\r
+       void MML_UseSpace (Uint16 segstart, Uint16 seglength);\r
+\r
+       Uint16 segstart,seglength;\r
+       Sint16 i;\r
+\r
+       // Note: The value of the jerk variable is replaced with the value\r
+       // read from the config file during US_Startup, which means the\r
+       // JERK parameter has absolutely no effect if a valid config file\r
+       // exists. The parameter check should be moved to some place after\r
+       // US_Startup to make it work reliably.\r
+       \r
+       for (i=1; i < _argc; i++)\r
+       {\r
+               if (US_CheckParm(_argv[i], ParmStrings) == 0)\r
+               {\r
+                       jerk = true;\r
+               }\r
+       }\r
+\r
+       US_TextScreen();\r
+\r
+       MM_Startup();\r
+       VW_Startup();\r
+       RF_Startup();\r
+       IN_Startup();\r
+       SD_Startup();\r
+       US_Startup();\r
+\r
+       US_UpdateTextScreen();\r
+\r
+       CA_Startup();\r
+       US_Setup();\r
+\r
+       US_SetLoadSaveHooks(&LoadTheGame, &SaveTheGame, &ResetGame);\r
+       drawcachebox = DialogDraw;\r
+       updatecachebox = DialogUpdate;\r
+       finishcachebox = DialogFinish;\r
+\r
+//\r
+// load in and lock down some basic chunks\r
+//\r
+\r
+       CA_ClearMarks();\r
+\r
+       CA_MarkGrChunk(STARTFONT);\r
+       CA_MarkGrChunk(STARTTILE8);\r
+       CA_MarkGrChunk(STARTTILE8M);\r
+#if GRMODE == EGAGR\r
+       CA_MarkGrChunk(CORDPICM);\r
+       CA_MarkGrChunk(METALPOLEPICM);\r
+#endif\r
+\r
+       CA_CacheMarks(NULL);\r
+\r
+       MM_SetLock(&grsegs[STARTFONT], true);\r
+       MM_SetLock(&grsegs[STARTTILE8], true);\r
+       MM_SetLock(&grsegs[STARTTILE8M], true);\r
+#if GRMODE == EGAGR\r
+       MM_SetLock(&grsegs[CORDPICM], true);\r
+       MM_SetLock(&grsegs[METALPOLEPICM], true);\r
+#endif\r
+\r
+       fontcolor = WHITE;\r
+\r
+       US_FinishTextScreen();\r
+\r
+//\r
+// reclaim the memory from the linked in text screen\r
+//\r
+       segstart = FP_SEG(&introscn);\r
+       seglength = 4000/16;\r
+       if (FP_OFF(&introscn))\r
+       {\r
+               segstart++;\r
+               seglength--;\r
+       }\r
+       MML_UseSpace (segstart,seglength);\r
+\r
+       VW_SetScreenMode(GRMODE);\r
+#if GRMODE == CGAGR\r
+       VW_ColorBorder(BROWN);\r
+#else\r
+       VW_ColorBorder(CYAN);\r
+#endif\r
+       VW_ClearVideo(BLACK);\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+==========================\r
+=\r
+= Quit\r
+=\r
+==========================\r
+*/\r
+\r
+void Quit(char *error)\r
+{\r
+       Uint16 finscreen;\r
+\r
+       if (!error)\r
+       {\r
+               CA_SetAllPurge();\r
+               CA_CacheGrChunk(ORDERSCREEN);\r
+               finscreen = (Uint16)grsegs[ORDERSCREEN];\r
+       }\r
+\r
+       // BUG: VW_ClearVideo may brick the system if screenseg is 0\r
+       // (i.e. VW_SetScreenMode has not been executed) - this may\r
+       // happen if the code runs into an error during InitGame\r
+       // (EMS/XMS errors, files not found etc.)\r
+       VW_ClearVideo(BLACK);\r
+       VW_SetLineWidth(40);\r
+\r
+       ShutdownId();\r
+       if (error && *error)\r
+       {\r
+               puts(error);\r
+               if (tedlevel)\r
+               {\r
+                       getch();\r
+                       execlp("TED5.EXE", "TED5.EXE", "/LAUNCH", NULL);\r
+               }\r
+               else if (US_ParmPresent("windows"))\r
+               {\r
+                       bioskey(0);\r
+               }\r
+               exit(1);\r
+       }\r
+\r
+       if (!NoWait)\r
+       {\r
+               movedata(finscreen, 7, 0xB800, 0, 4000);\r
+               gotoxy(1, 24);\r
+               if (US_ParmPresent("windows"))\r
+               {\r
+                       bioskey(0);\r
+               }\r
+       }\r
+\r
+       exit(0);\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+==================\r
+=\r
+= TEDDeath\r
+=\r
+==================\r
+*/\r
+\r
+void TEDDeath(void)\r
+{\r
+       ShutdownId();\r
+       execlp("TED5.EXE", "TED5.EXE", "/LAUNCH", NULL);\r
+       // BUG: should call exit(1); here in case starting TED5 fails\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+==================\r
+=\r
+= CheckMemory\r
+=\r
+==================\r
+*/\r
+\r
+void CheckMemory(void)\r
+{\r
+       Uint16 finscreen;\r
+\r
+       if (mminfo.nearheap+mminfo.farheap+mminfo.EMSmem+mminfo.XMSmem >= MINMEMORY)\r
+               return;\r
+\r
+       CA_CacheGrChunk (OUTOFMEM);\r
+       finscreen = (Uint16)grsegs[OUTOFMEM];\r
+       ShutdownId();\r
+       movedata (finscreen,7,0xb800,0,4000);\r
+       gotoxy (1,24);\r
+       exit(1);\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= DemoLoop\r
+=\r
+=====================\r
+*/\r
+\r
+void DemoLoop(void)\r
+{\r
+       static char *ParmStrings[] = {"easy", "normal", "hard", ""};\r
+\r
+       register Sint16 i, state;\r
+       Sint16 level;\r
+\r
+//\r
+// check for launch from ted\r
+//\r
+       if (tedlevel)\r
+       {\r
+               NewGame();\r
+               CA_LoadAllSounds();\r
+               gamestate.mapon = tedlevelnum;\r
+               restartgame = gd_Normal;\r
+               for (i = 1;i < _argc;i++)\r
+               {\r
+                       if ( (level = US_CheckParm(_argv[i],ParmStrings)) == -1)\r
+                               continue;\r
+\r
+                       restartgame = level+gd_Easy;\r
+                       break;\r
+               }\r
+               GameLoop();\r
+               TEDDeath();\r
+       }\r
+\r
+//\r
+// demo loop\r
+//\r
+       state = 0;\r
+       playstate = ex_stillplaying;\r
+       while (1)\r
+       {\r
+               switch (state++)\r
+               {\r
+               case 0:\r
+#if GRMODE == CGAGR\r
+                       ShowTitle();\r
+#else\r
+                       if (nopan)\r
+                       {\r
+                               ShowTitle();\r
+                       }\r
+                       else\r
+                       {\r
+                               Terminator();\r
+                       }\r
+#endif\r
+                       break;\r
+\r
+               case 1:\r
+                       RunDemo(0);\r
+                       break;\r
+\r
+               case 2:\r
+#if GRMODE == CGAGR\r
+                       ShowCredits();\r
+#else\r
+                       StarWars();\r
+#endif\r
+                       break;\r
+\r
+               case 3:\r
+                       RunDemo(1);\r
+                       break;\r
+\r
+               case 4:\r
+                       ShowHighScores();\r
+                       break;\r
+\r
+               case 5:\r
+                       RunDemo(2);\r
+                       break;\r
+\r
+               case 6:\r
+                       state = 0;\r
+                       RunDemo(3);\r
+                       break;\r
+               }\r
+\r
+               while (playstate == ex_resetgame || playstate == ex_loadedgame)\r
+               {\r
+                       GameLoop();\r
+                       ShowHighScores();\r
+                       if (playstate == ex_resetgame || playstate == ex_loadedgame)\r
+                       {\r
+                               continue;       // don't show title screen, go directly to GameLoop();\r
+                       }\r
+                       ShowTitle();\r
+                       ///////////////\r
+                       // this is completely useless:\r
+                       if (playstate == ex_resetgame || playstate == ex_loadedgame)\r
+                       {\r
+                               continue;\r
+                       }\r
+                       ///////////////\r
+               }\r
+       }\r
+}\r
+\r
+//===========================================================================\r
+\r
+#if (GRMODE == EGAGR) && !(defined KEEN6)\r
+/*\r
+=====================\r
+=\r
+= CheckCutFile\r
+=\r
+=====================\r
+*/\r
+\r
+#define FILE_GR1 GREXT"1."EXTENSION\r
+#define FILE_GR2 GREXT"2."EXTENSION\r
+#define FILE_GRAPH GREXT"GRAPH."EXTENSION\r
+\r
+static void CheckCutFile(void)\r
+{\r
+       register Sint16 ohandle, ihandle;\r
+       Sint16 handle;\r
+       Sint32 size;\r
+       void far *buffer;\r
+\r
+       if ( (handle = open(FILE_GRAPH, O_BINARY|O_RDONLY)) != -1)\r
+       {\r
+               close(handle);\r
+               return;\r
+       }\r
+       puts("Combining "FILE_GR1" and "FILE_GR2" into "FILE_GRAPH"...");\r
+       if (rename(FILE_GR1, FILE_GRAPH) == -1)\r
+       {\r
+               puts("Can't rename "FILE_GR1"!");\r
+               exit(1);\r
+       }\r
+       if ( (ohandle = open(FILE_GRAPH, O_BINARY|O_APPEND|O_WRONLY)) == -1)\r
+       {\r
+               puts("Can't open "FILE_GRAPH"!");\r
+               exit(1);\r
+       }\r
+       lseek(ohandle, 0, SEEK_END);\r
+       if ( (ihandle = open(FILE_GR2, O_BINARY|O_RDONLY)) == -1)\r
+       {\r
+               puts("Can't find "FILE_GR2"!");\r
+               exit(1);\r
+       }\r
+       size = filelength(ihandle);\r
+       buffer = farmalloc(32000);\r
+       while (size)\r
+       {\r
+               if (size > 32000)\r
+               {\r
+                       CA_FarRead(ihandle, buffer, 32000);\r
+                       CA_FarWrite(ohandle, buffer, 32000);\r
+                       size -= 32000;\r
+               }\r
+               else\r
+               {\r
+                       CA_FarRead(ihandle, buffer, size);\r
+                       CA_FarWrite(ohandle, buffer, size);\r
+                       size = 0;\r
+               }\r
+       }\r
+       farfree(buffer);\r
+       close(ohandle);\r
+       close(ihandle);\r
+       unlink(FILE_GR2);\r
+}\r
+#endif\r
+\r
+//===========================================================================\r
+\r
+\r
+/*\r
+==========================\r
+=\r
+= main\r
+=\r
+==========================\r
+*/\r
+\r
+void main(void)\r
+{\r
+#if (GRMODE == EGAGR) && !(defined KEEN6)\r
+       CheckCutFile();\r
+#endif\r
+\r
+       if (US_ParmPresent("DEMO"))\r
+               storedemo = true;\r
+\r
+       if (US_ParmPresent("JOYPAD"))\r
+               joypad = true;  // Note: the joypad variable is never used\r
+       \r
+       InitGame();\r
+       CheckMemory();\r
+       if (NoWait || tedlevel)\r
+               debugok = true;\r
+\r
+       DemoLoop();\r
+       Quit("Demo loop exited???");\r
+}
\ No newline at end of file