-/* 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