+++ /dev/null
-/* Catacomb Apocalypse Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\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
-// C3_GAME.C\r
-\r
-#include <stdlib.h>\r
-\r
-#include "DEF.H"\r
-#include "gelib.h"\r
-#pragma hdrstop\r
-\r
-#ifdef PROFILE\r
-#include "TIME.H"\r
-#endif\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define NUMLUMPS 45\r
-\r
-#define EYESTALKLUMP 0\r
-#define BLOBLUMP 1\r
-#define BOLTLUMP 2\r
-#define NUKELUMP 3\r
-#define POTIONLUMP 4\r
-#define RKEYLUMP 5\r
-#define YKEYLUMP 6\r
-#define GKEYLUMP 7\r
-#define BKEYLUMP 8\r
-#define RGEMLUMP 9\r
-#define GGEMLUMP 10\r
-#define BGEMLUMP 11\r
-#define YGEMLUMP 12\r
-#define PGEMLUMP 13\r
-#define CHESTLUMP 14\r
-#define PLAYERLUMP 15\r
-#define FTIMELUMP 16\r
-#define PORTALLUMP 17\r
-#define COLUMN1LUMP 18\r
-#define FIREPOTLUMP 19\r
-#define COLUMN2LUMP 20\r
-#define EYELUMP 21\r
-#define FUTUREMAGELUMP 22\r
-#define FORCEFIELDLUMP 23\r
-#define ROBOTANKLUMP 24\r
-#define RAMBONELUMP 25\r
-#define STOMPYLUMP 26\r
-#define TROLLLUMP 27\r
-#define WIZARDLUMP 28\r
-#define HEADLUMP 29\r
-#define INVISDUDELUMP 30\r
-#define BUGLUMP 31\r
-#define CYBORGLUMP 32\r
-#define WATERCHESTLUMP 33\r
-#define GRELLUMP 34\r
-#define RAYLUMP 35\r
-#define COLUMN3LUMP 36\r
-#define OLDCHESTLUMP 37\r
-#define OLDFIREPOTLUMP 38\r
-#define COLUMN4LUMP 39\r
-#define TOMB1LUMP 40\r
-#define TOMB2LUMP 41\r
-#define DEMONLUMP 42\r
-#define COLUMN5LUMP 43\r
-\r
-int lumpstart[NUMLUMPS] = {\r
-EYESTALK_LUMP_START,\r
-BLOB_LUMP_START,\r
-BOLT_LUMP_START,\r
-NUKE_LUMP_START,\r
-POTION_LUMP_START,\r
-RKEY_LUMP_START,\r
-YKEY_LUMP_START,\r
-GKEY_LUMP_START,\r
-BKEY_LUMP_START,\r
-RGEM_LUMP_START,\r
-GGEM_LUMP_START,\r
-BGEM_LUMP_START,\r
-YGEM_LUMP_START,\r
-PGEM_LUMP_START,\r
-CHEST_LUMP_START,\r
-PLAYER_LUMP_START,\r
-TIME_LUMP_START,\r
-PORTAL_LUMP_START,\r
-COLUMN1_LUMP_START,\r
-FFIREPOT_LUMP_START,\r
-COLUMN2_LUMP_START,\r
-EYE_LUMP_START,\r
-FUTUREMAGE_LUMP_START,\r
-FORCEFIELD_LUMP_START,\r
-ROBOTANK_LUMP_START,\r
-RAMBONE_LUMP_START,\r
-STOMPY_LUMP_START,\r
-TROLL_LUMP_START,\r
-WIZARD_LUMP_START,\r
-HEAD_LUMP_START,\r
-INVISDUDE_LUMP_START,\r
-BUG_LUMP_START,\r
-CYBORG_LUMP_START,\r
-O_WATER_CHEST_LUMP_START,\r
-GREL_LUMP_START,\r
-RAY_LUMP_START,\r
-COLUMN3_LUMP_START,\r
-OLD_CHEST_LUMP_START,\r
-OFIREPOT_LUMP_START,\r
-COLUMN4_LUMP_START,\r
-TOMB1_LUMP_START,\r
-TOMB2_LUMP_START,\r
-DEMON_LUMP_START,\r
-COLUMN5_LUMP_START,\r
-};\r
-\r
-\r
-int lumpend[NUMLUMPS] = {\r
-EYESTALK_LUMP_END,\r
-BLOB_LUMP_END,\r
-BOLT_LUMP_END,\r
-NUKE_LUMP_END,\r
-POTION_LUMP_END,\r
-RKEY_LUMP_END,\r
-YKEY_LUMP_END,\r
-GKEY_LUMP_END,\r
-BKEY_LUMP_END,\r
-RGEM_LUMP_END,\r
-GGEM_LUMP_END,\r
-BGEM_LUMP_END,\r
-YGEM_LUMP_END,\r
-PGEM_LUMP_END,\r
-CHEST_LUMP_END,\r
-PLAYER_LUMP_END,\r
-TIME_LUMP_END,\r
-PORTAL_LUMP_END,\r
-COLUMN1_LUMP_END,\r
-FFIREPOT_LUMP_END,\r
-COLUMN2_LUMP_END,\r
-EYE_LUMP_END,\r
-FUTUREMAGE_LUMP_END,\r
-FORCEFIELD_LUMP_END,\r
-ROBOTANK_LUMP_END,\r
-RAMBONE_LUMP_END,\r
-STOMPY_LUMP_END,\r
-TROLL_LUMP_END,\r
-WIZARD_LUMP_END,\r
-HEAD_LUMP_END,\r
-INVISDUDE_LUMP_END,\r
-BUG_LUMP_END,\r
-CYBORG_LUMP_END,\r
-O_WATER_CHEST_LUMP_END,\r
-GREL_LUMP_END,\r
-RAY_LUMP_END,\r
-COLUMN3_LUMP_END,\r
-OLD_CHEST_LUMP_END,\r
-OFIREPOT_LUMP_END,\r
-COLUMN4_LUMP_END,\r
-TOMB1_LUMP_END,\r
-TOMB2_LUMP_END,\r
-DEMON_LUMP_END,\r
-COLUMN5_LUMP_END,\r
-};\r
-\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-unsigned latchpics[NUMLATCHPICS];\r
-unsigned tileoffsets[NUMTILE16];\r
-unsigned textstarts[27];\r
-\r
-boolean splitscreen=false;\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-boolean lumpneeded[NUMLUMPS];\r
-\r
-\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
- unsigned char hibyte;\r
- unsigned x,y,i,j;\r
- unsigned int tile;\r
- unsigned far *start;\r
-\r
- InitObjList(); // start spawning things with a clean slate\r
-\r
- scolor = gcolor = 0;\r
- skycolor = &scolor;\r
- groundcolor = &gcolor;\r
-\r
-\r
- memset (lumpneeded,0,sizeof(lumpneeded));\r
-\r
- start = mapsegs[2];\r
- for (y=0;y<mapheight;y++)\r
- for (x=0;x<mapwidth;x++)\r
- {\r
- tile = *start++;\r
- hibyte = tile >> 8;\r
- tile &= 0xff;\r
-\r
- switch (hibyte)\r
- {\r
- char hi;\r
-\r
- case 0xFB:\r
- wall_anim_time = tile;\r
- tile = 0;\r
- break;\r
-\r
- case 0xfa: // sky/ground color\r
- x++;\r
- tile = *start++;\r
- hi = tile >> 8;\r
- tile &= 0xff;\r
- switch (hibyte)\r
- {\r
- case 0xfa: // sky / ground color\r
- scolor = ((hi)|(hi<<8));\r
- gcolor = ((tile)|(tile<<8));\r
- skycolor = &scolor;\r
- groundcolor = &gcolor;\r
- break;\r
-\r
- }\r
- break;\r
- }\r
-\r
- if ((!tile) || (hibyte))\r
- continue;\r
-\r
- switch (tile)\r
- {\r
- case 1:\r
- case 2:\r
- case 3:\r
- case 4:\r
- lumpneeded[PLAYERLUMP] = true;\r
- SpawnPlayer(x,y,NORTH+tile-1);\r
- break;\r
-\r
- case 5:\r
- case 6:\r
- case 7:\r
- case 8:\r
- case 9:\r
- case 10:\r
- case 11:\r
- lumpneeded[tile-5+BOLTLUMP] = true;\r
- SpawnBonus(x,y,tile-5);\r
- break;\r
-\r
- case 12:\r
- lumpneeded[EYESTALKLUMP] = true;\r
- SpawnAquaMan(x, y);\r
- break;\r
-\r
-\r
- case 13:\r
- lumpneeded[BLOBLUMP] = true;\r
- SpawnBlob(x, y);\r
- break;\r
-\r
-\r
- case 14:\r
- lumpneeded[BUGLUMP] = true;\r
- SpawnBug(x, y);\r
- break;\r
-\r
- case 15:\r
- lumpneeded[CYBORGLUMP] = true;\r
- SpawnCyborgDemon(x, y);\r
- break;\r
-\r
- case 16:\r
- lumpneeded[EYELUMP] = true;\r
- SpawnShooterEye(x, y);\r
- break;\r
-\r
- case 17:\r
- lumpneeded[FUTUREMAGELUMP] = true;\r
- SpawnFutureMage(x, y);\r
- break;\r
-\r
- case 18:\r
- lumpneeded[INVISDUDELUMP] = true;\r
- SpawnInvisDude(x, y);\r
- break;\r
-\r
- case 19:\r
- lumpneeded[ROBOTANKLUMP] = true;\r
- SpawnRoboTank(x, y);\r
- break;\r
-\r
- case 20:\r
- lumpneeded[RAMBONELUMP] = true;\r
- SpawnRamBone(x, y);\r
- break;\r
-\r
- case 21:\r
- lumpneeded[STOMPYLUMP] = true;\r
- SpawnStompy(x, y);\r
- break;\r
-\r
- case 22:\r
- lumpneeded[TROLLLUMP] = true;\r
- SpawnTroll(x, y);\r
- break;\r
-\r
- case 23:\r
- lumpneeded[WIZARDLUMP] = true;\r
- SpawnWizard(x, y);\r
- break;\r
-\r
- case 24:\r
- SpawnBounce(x, y, 0);\r
- break;\r
-\r
- case 25:\r
- SpawnBounce(x, y, 1);\r
- break;\r
-\r
- case 26:\r
- lumpneeded[RKEYLUMP] = lumpneeded[GRELLUMP] = true;\r
- SpawnGrelminar (x,y);\r
- break;\r
-\r
- case 27:\r
- lumpneeded[EYELUMP] = true;\r
- SpawnRunningEye(x,y);\r
- break;\r
-\r
- case 28:\r
- lumpneeded[RAYLUMP] = true;\r
- SpawnRay(x, y);\r
- break;\r
-\r
- case 29:\r
- lumpneeded[HEADLUMP] = true;\r
- SpawnEgyptianHead(x, y);\r
- break;\r
-\r
- case 30:\r
- lumpneeded[DEMONLUMP] = true;\r
- SpawnDemon(x, y);\r
- break;\r
-\r
- case 31:\r
- lumpneeded[COLUMN5LUMP] = true;\r
- SpawnMiscObjects(x, y, 9);\r
- break;\r
-\r
- case 32:\r
- SpawnInvisWallCntroller(x, y);\r
- break;\r
-\r
- case 33:\r
- break;\r
-\r
- case 34:\r
- break;\r
-\r
- case 35:\r
- break;\r
-\r
- case 36:\r
- lumpneeded[COLUMN1LUMP] = true;\r
- SpawnMiscObjects(x, y, 1);\r
- break;\r
-\r
- case 37:\r
- lumpneeded[FIREPOTLUMP] = true;\r
- SpawnMiscObjects(x, y, 4);\r
- break;\r
-\r
- case 38:\r
- lumpneeded[PORTALLUMP] = true;\r
- SpawnWarp(x, y);\r
- break;\r
-\r
- case 39:\r
- lumpneeded[FTIMELUMP] = true;\r
- SpawnFTime(x,y);\r
- break;\r
-\r
-\r
- case 40:\r
- case 41:\r
- case 42:\r
- case 43:\r
- case 44:\r
- lumpneeded[tile-40+RGEMLUMP] = true;\r
- SpawnBonus(x,y,tile-40+B_RGEM);\r
- break;\r
-\r
- case 45:\r
- lumpneeded[COLUMN2LUMP] = true;\r
- SpawnMiscObjects(x, y, 2);\r
- break;\r
-\r
- case 46:\r
- lumpneeded[COLUMN3LUMP] = true;\r
- SpawnMiscObjects(x, y, 3);\r
- break;\r
-\r
- case 47:\r
- lumpneeded[FORCEFIELDLUMP] = true;\r
- SpawnForceField(x, y);\r
- break;\r
-\r
- case 48:\r
- lumpneeded[OLDCHESTLUMP] = true;\r
- SpawnBonus(x, y, B_OLDCHEST);\r
- break;\r
-\r
- case 49: // chest\r
- if (gcolor == 0x0101)\r
- lumpneeded[WATERCHESTLUMP] = true;\r
- else\r
- lumpneeded[CHESTLUMP] = true;\r
- SpawnBonus(x,y,B_CHEST);\r
- break;\r
-\r
- case 50:\r
- lumpneeded[COLUMN4LUMP] = true;\r
- SpawnMiscObjects(x, y, 5);\r
- break;\r
-\r
- case 51:\r
- lumpneeded[OLDFIREPOTLUMP] = true;\r
- SpawnMiscObjects(x, y, 6);\r
- break;\r
-\r
- case 52:\r
- lumpneeded[TOMB1LUMP] = true;\r
- SpawnMiscObjects(x, y, 7);\r
- break;\r
-\r
- case 53:\r
- lumpneeded[TOMB2LUMP] = true;\r
- SpawnMiscObjects(x, y, 8);\r
- break;\r
-\r
- case 54:\r
- break;\r
-\r
- case 55:\r
- break;\r
-\r
- case 56:\r
- break;\r
-\r
- case 57:\r
- break;\r
-\r
- case 58:\r
- break;\r
-\r
- case 59:\r
- break;\r
-\r
- case 60:\r
- break;\r
-\r
- case 61:\r
- break;\r
-\r
- case 62:\r
- break;\r
-\r
- case 63:\r
- break;\r
-\r
- case 64:\r
- break;\r
-\r
- case 65:\r
- break;\r
-\r
- case 66:\r
- break;\r
-\r
- case 67:\r
- break;\r
-\r
- case 68:\r
- break;\r
-\r
- case 69:\r
- break;\r
-\r
- case 70:\r
- break;\r
-\r
- case 71:\r
- break;\r
-\r
- }\r
- }\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= ScanText\r
-=\r
-==================\r
-*/\r
-\r
-void ScanText (void)\r
-{\r
- int i;\r
- char far *text;\r
-\r
- text = (char _seg *)grsegs[LEVEL1TEXT+mapon];\r
-\r
- textstarts[0] = 0;\r
-\r
- for (i=1;i<=26;i++)\r
- {\r
- while (*text != '\n')\r
- {\r
- if (*text == '\r')\r
- *text = 0;\r
- text++;\r
- }\r
- text++;\r
- textstarts[i] = FP_OFF(text);\r
- }\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= DrawEnterScreen\r
-=\r
-==================\r
-*/\r
-#if 0\r
-static char *levelnames[] =\r
- {\r
- "Programmers Test Map",\r
- "The Garden of Tears",\r
- "The Den of Zombies",\r
- "The Mausoleum Grounds",\r
- "The Main Floor of the Mausoleum",\r
- "Mike's Blastable Passage",\r
- "The Crypt of Nemesis the Undead",\r
- "The Subterranean Vault",\r
- "The Ancient Aqueduct",\r
- "The Orc Mines",\r
- "The Lair of the Troll",\r
- "The Demon's Inferno",\r
- "The Battleground of the Titans",\r
- "The Coven of Mages",\r
- "The Inner Sanctum",\r
- "The Haunt of Nemesis",\r
- "The Passage to the Surface",\r
- "Big Jim's Domain",\r
- "Nolan",\r
- "19",\r
- "20",\r
- "21",\r
- "22",\r
- "23",\r
- "24",\r
- "25",\r
- "26",\r
- "27",\r
- "28",\r
- "29",\r
- "30",\r
- "31",\r
- "32",\r
- "33",\r
- "34",\r
- "35",\r
- "36",\r
- "37",\r
- "38",\r
- "39",\r
- };\r
-#endif\r
-\r
-void DrawEnterScreen ()\r
-{\r
- int width;\r
-\r
- bufferofs = displayofs = screenloc[screenpage];\r
- VW_Bar(0,0,VIEWWIDTH,VIEWHEIGHT,0);\r
-\r
-// width = strlen(levelnames[gamestate.mapon]);\r
- width = strlen("A new challenge awaits you.");\r
- if (width < 20)\r
- width = 20;\r
- CenterWindow(width,3);\r
- US_CPrint("\nA new challenge awaits you.\n");\r
-// US_CPrint(levelnames[gamestate.mapon]);\r
-}\r
-\r
-//==========================================================================\r
-\r
-boolean tileneeded[NUMFLOORS];\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= CacheScaleds\r
-=\r
-==================\r
-*/\r
-\r
-void CacheScaleds (void)\r
-{\r
- int i,j;\r
- unsigned source,dest;\r
-\r
- FreeUpMemory ();\r
- CA_CacheGrChunk(LEVEL1TEXT+mapon);\r
- ScanText ();\r
-\r
-//\r
-// make sure we are displaying screenpage 0\r
-//\r
- if (screenpage)\r
- {\r
- source = screenloc[screenpage];\r
- dest = screenloc[0];\r
- VW_ScreenToScreen (source,dest,40,VIEWHEIGHT);\r
- screenpage = 0;\r
- VW_SetScreen (dest,0);\r
- displayofs = dest;\r
- }\r
-\r
-//\r
-// cache wall pictures\r
-//\r
- for (i=1;i<NUMFLOORS;i++)\r
- if (tileneeded[i])\r
- {\r
- SetupScaleWall (walllight1[i]);\r
- SetupScaleWall (walldark1[i]);\r
- }\r
-\r
-//\r
-// cache the actor pictures\r
-//\r
- for (i=0;i<NUMLUMPS;i++)\r
- if (lumpneeded[i])\r
- for (j=lumpstart[i];j<=lumpend[i];j++)\r
- SetupScalePic(j);\r
-\r
- source = screenloc[0];\r
- for (i=1;i<=2;i++)\r
- {\r
- dest = screenloc[i];\r
- VW_ScreenToScreen (source,dest,40,VIEWHEIGHT);\r
- }\r
-\r
- screenpage = 1;\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= SetupGameLevel\r
-=\r
-==================\r
-*/\r
-\r
-void SetupGameLevel ()\r
-{\r
- int x,y,i,loop;\r
- unsigned far *map,tile,far *spotptr,spot;\r
- unsigned search_tile;\r
- boolean exploding_walls_present = false;\r
-\r
- memset (tileneeded,0,sizeof(tileneeded));\r
-//\r
-// randomize if not a demo\r
-//\r
-#if 0\r
- if (DemoMode)\r
- {\r
- US_InitRndT(false);\r
- gamestate.difficulty = gd_Normal;\r
- }\r
- else\r
-#endif\r
- US_InitRndT(true);\r
-\r
-//\r
-// load the level\r
-//\r
- CA_CacheMap (gamestate.mapon);\r
-\r
- mapwidth = mapheaderseg[mapon]->width;\r
- mapheight = mapheaderseg[mapon]->height;\r
-\r
-//\r
-// make a lookup table for the maps left edge\r
-//\r
- spot = 0;\r
- for (y=0;y<mapheight;y++)\r
- {\r
- farmapylookup[y] = spot;\r
- spot += mapwidth;\r
- }\r
-\r
-\r
-//\r
-// copy the wall data to a data segment array\r
-//\r
- memset (tilemap,0,sizeof(tilemap));\r
- memset (actorat,0,sizeof(actorat));\r
- map = mapsegs[0];\r
- spotptr = mapsegs[2];\r
- for (y=0;y<mapheight;y++)\r
- for (x=0;x<mapwidth;x++)\r
- {\r
- tile = *map++;\r
-\r
- if (((*spotptr)>>8) == EXP_WALL_CODE)\r
- {\r
- exploding_walls_present = true;\r
- }\r
-\r
- if (tile<NUMFLOORS)\r
- {\r
-#if 0\r
- if (tile == WALL_SKELETON_CODE)\r
- {\r
- tileneeded[tile+1] = tileneeded[tile+2] = true;\r
- tilemap[x][y] = tile;\r
- }\r
-#endif\r
- if ((tile == 66) || (tile == 67) || (tile == 68) || (tile == 69))\r
- {\r
- if ((tile == 66) || (tile == 67))\r
- tileneeded[tile+2] = true;\r
- tileneeded[21] = tileneeded[tile] = true;\r
- tilemap[x][y] = tile;\r
- }\r
- else\r
- if (tile != INVISIBLEWALL)\r
- {\r
- tileneeded[tile] = true;\r
- tilemap[x][y] = tile;\r
- if (ANIM_FLAGS(tile))\r
- {\r
- search_tile = tile+(char signed)ANIM_FLAGS(tile);\r
-\r
- if (!tileneeded[search_tile])\r
- while (search_tile != tile)\r
- {\r
- tileneeded[search_tile] = true;\r
- if (ANIM_FLAGS(search_tile))\r
- search_tile += (char signed)ANIM_FLAGS(search_tile);\r
- else\r
- TrashProg("Unending Tile Animation!");\r
- }\r
- }\r
-\r
- }\r
- if (tile>0)\r
- (unsigned)actorat[x][y] = tile;\r
- }\r
- spotptr++;\r
- }\r
-\r
-\r
- //\r
- // Mark any gfx chunks needed\r
- //\r
-\r
-// CA_MarkGrChunk(NORTHICONSPR);\r
-// CA_CacheMarks(NULL);\r
-\r
-\r
-//\r
-// decide which graphics are needed and spawn actors\r
-//\r
- head_base_delay = 0; // (1*60) + random(1*60);\r
- ScanInfoPlane ();\r
- _fmemset(wall_anim_pos,0,sizeof(wall_anim_pos));\r
-\r
-\r
-//\r
-// mark which exploding walls are needed ---- the check for floor color\r
-// is preformed in ScanInfoPlane.\r
-//\r
-\r
- if (exploding_walls_present)\r
- {\r
- extern unsigned gnd_colors[];\r
-\r
- if (gcolor == 0x0101)\r
- tileneeded[WATEREXP] = tileneeded[WATEREXP+1] = tileneeded[WATEREXP+2] = true;\r
- else\r
- tileneeded[WALLEXP] = tileneeded[WALLEXP+1] = tileneeded[WALLEXP+2] = true;\r
-\r
- }\r
-\r
-\r
-//\r
-// have the caching manager load and purge stuff to make sure all marks\r
-// are in memory\r
-//\r
- CA_LoadAllSounds ();\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= LatchDrawPic\r
-=\r
-=====================\r
-*/\r
-\r
-void LatchDrawPic (unsigned x, unsigned y, unsigned picnum)\r
-{\r
- unsigned height, source, dest;\r
- unsigned wide;\r
-\r
- wide = pictable[picnum-STARTPICS].width;\r
- height = pictable[picnum-STARTPICS].height;\r
- dest = bufferofs + ylookup[y]+x;\r
- source = latchpics[picnum-FIRSTLATCHPIC];\r
-\r
- EGAWRITEMODE(1);\r
- EGAMAPMASK(15);\r
-\r
-asm mov bx,[linewidth]\r
-asm sub bx,[wide]\r
-\r
-asm mov ax,[screenseg]\r
-asm mov es,ax\r
-asm mov ds,ax\r
-\r
-asm mov si,[source]\r
-asm mov di,[dest]\r
-asm mov dx,[height] // scan lines to draw\r
-asm mov ax,[wide]\r
-\r
-lineloop:\r
-asm mov cx,ax\r
-asm rep movsb\r
-asm add di,bx\r
-\r
-asm dec dx\r
-asm jnz lineloop\r
-\r
-asm mov ax,ss\r
-asm mov ds,ax // restore turbo's data segment\r
-\r
- EGAWRITEMODE(0);\r
-}\r
-\r
-#if USE_STRIPS\r
-\r
-//--------------------------------------------------------------------------\r
-// LatchDrawPicStrip() - srcoff is distance into source file (in PIXELS!)\r
-//--------------------------------------------------------------------------\r
-void LatchDrawPicStrip (unsigned x, unsigned y, unsigned picnum, unsigned srcoff)\r
-{\r
- unsigned wide, height, source, dest, shift, srcmod;\r
-\r
- shift = (srcoff & 7) >> 1;\r
- srcoff >>= 3;\r
- wide = pictable[picnum-STARTPICS].width;\r
- srcmod = wide - linewidth + (shift != 3);\r
- if (wide > linewidth)\r
- wide = linewidth;\r
- height = pictable[picnum-STARTPICS].height;\r
- dest = bufferofs + ylookup[y]+x;\r
-\r
- picnum = ((picnum - (FIRSTSTRIPPIC+1)) >> 2) + (shift);\r
- source = latchpics[(FIRSTSTRIPPIC-FIRSTLATCHPIC+1)+picnum];\r
-\r
- EGAWRITEMODE(1);\r
- EGAMAPMASK(15);\r
-\r
-asm mov bx,[linewidth]\r
-asm sub bx,[wide]\r
-\r
-asm mov ax,[screenseg]\r
-asm mov es,ax\r
-asm mov ds,ax\r
-\r
-asm mov si,[source]\r
-asm add si,[srcoff]\r
-asm mov di,[dest]\r
-asm mov dx,[height] // scan lines to draw\r
-asm mov ax,[wide]\r
-\r
-lineloop:\r
-asm mov cx,ax\r
-asm rep movsb\r
-asm add di,bx\r
-asm add si,[srcmod]\r
-\r
-asm dec dx\r
-asm jnz lineloop\r
-\r
-asm mov ax,ss\r
-asm mov ds,ax // restore turbo's data segment\r
-\r
- EGAWRITEMODE(0);\r
-}\r
-\r
-#endif\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= Victory\r
-=\r
-=====================\r
-*/\r
-\r
-void Victory (boolean playsounds)\r
-{\r
- struct Shape shape;\r
-\r
- if (playsounds)\r
- {\r
- SD_PlaySound (GETBOLTSND);\r
- SD_WaitSoundDone ();\r
- SD_PlaySound (GETNUKESND);\r
- SD_WaitSoundDone ();\r
- SD_PlaySound (GETPOTIONSND);\r
- SD_WaitSoundDone ();\r
- SD_PlaySound (GETKEYSND);\r
- SD_WaitSoundDone ();\r
-// SD_PlaySound (GETSCROLLSND);\r
-// SD_WaitSoundDone ();\r
- SD_PlaySound (GETPOINTSSND);\r
- }\r
-\r
- FreeUpMemory();\r
-\r
- if (!screenfaded)\r
- VW_FadeOut();\r
-\r
- NormalScreen ();\r
-\r
- screenpage = bufferofs = 0;\r
-\r
- CA_CacheGrChunk (FINALEPIC);\r
- UNMARKGRCHUNK(FINALEPIC);\r
- VW_DrawPic(0, 0, FINALEPIC);\r
-\r
- VW_FadeIn();\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-#if 0\r
-/*\r
-===================\r
-=\r
-= Died\r
-=\r
-===================\r
-*/\r
-\r
-void Died (void)\r
-{\r
- unsigned page1,page2;\r
-//\r
-// fizzle fade screen to grey\r
-//\r
- FreeUpMemory ();\r
- SD_PlaySound (GAMEOVERSND);\r
- bufferofs = screenloc[(screenpage+1)%3];\r
- DisplayMsg("Though fallen, your Spirit ...",NULL);\r
-// LatchDrawPic(0,0,DEADPIC);\r
-// FizzleFade(bufferofs,displayofs,VIEWWIDTH,VIEWHEIGHT,false);\r
- IN_ClearKeysDown();\r
- while (!Keyboard[sc_Enter]);\r
-// IN_Ack();\r
- VW_SetScreen (bufferofs,0);\r
- VW_ColorBorder(0);\r
-}\r
-#endif\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===================\r
-=\r
-= NormalScreen\r
-=\r
-===================\r
-*/\r
-\r
-void NormalScreen (void)\r
-{\r
- VW_SetSplitScreen (200);\r
- bufferofs = displayofs = SCREEN1START;\r
- VW_Bar(0,0,320,200,0);\r
- bufferofs = SCREEN2START;\r
- VW_Bar(0,0,320,200,0);\r
- VW_SetScreen (displayofs,0);\r
- splitscreen = false;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===================\r
-=\r
-= DrawPlayScreen\r
-=\r
-===================\r
-*/\r
-\r
-void DrawPlayScreen (void)\r
-{\r
- int i,j,p,m;\r
-\r
- screenpage = 0;\r
-\r
- bufferofs = 0;\r
- VW_Bar (0,0,320,STATUSLINES,0);\r
- for (i=0;i<3;i++)\r
- {\r
- bufferofs = screenloc[i];\r
- VW_Bar (0,0,320,VIEWHEIGHT,0);\r
- }\r
-\r
- splitscreen = true;\r
- VW_SetSplitScreen(120);\r
- VW_SetScreen(screenloc[0],0);\r
-\r
- CA_CacheGrChunk (STATUSPIC);\r
-\r
- bufferofs = 0;\r
- VW_DrawPic (0,0,STATUSPIC);\r
-\r
- grneeded[STATUSPIC] &= ~ca_levelbit;\r
- MM_SetPurge(&grsegs[STATUSPIC],3);\r
-\r
-// RedrawStatusWindow ();\r
- bufferofs = displayofs = screenloc[0];\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===================\r
-=\r
-= LoadLatchMem\r
-=\r
-===================\r
-*/\r
-\r
-unsigned latchmemavail;\r
-\r
-void LoadLatchMem (void)\r
-{\r
- static unsigned base_destoff=0;\r
- static int base_numpics=0;\r
- int i,j,p,m,numpics;\r
- byte far *src, far *dest;\r
- unsigned destoff;\r
-\r
- EGAWRITEMODE(0);\r
-\r
-//\r
-// draw some pics into latch memory\r
-//\r
-\r
- if (!base_numpics)\r
- {\r
-\r
-//\r
-// tile 8s\r
-//\r
- latchpics[0] = freelatch;\r
- src = (byte _seg *)grsegs[STARTTILE8];\r
- dest = MK_FP(0xa000,freelatch);\r
-\r
- for (i=0;i<NUMTILE8;i++)\r
- {\r
- for (p=0;p<4;p++)\r
- {\r
- m = 1<<p;\r
- asm mov dx,SC_INDEX\r
- asm mov al,SC_MAPMASK\r
- asm mov ah,[BYTE PTR m]\r
- asm out dx,ax\r
- for (j=0;j<8;j++)\r
- *(dest+j)=*src++;\r
- }\r
- dest+=8;\r
- }\r
-\r
-//\r
-// tile 16s\r
-//\r
- src = (byte _seg *)grsegs[STARTTILE16];\r
-\r
- for (i=0;i<NUMTILE16;i++)\r
- {\r
- CA_CacheGrChunk (STARTTILE16+i);\r
- src = (byte _seg *)grsegs[STARTTILE16+i];\r
- if (src)\r
- {\r
- tileoffsets[i] = FP_OFF(dest);\r
- for (p=0;p<4;p++)\r
- {\r
- m = 1<<p;\r
- asm mov dx,SC_INDEX\r
- asm mov al,SC_MAPMASK\r
- asm mov ah,[BYTE PTR m]\r
- asm out dx,ax\r
- for (j=0;j<32;j++)\r
- *(dest+j)=*src++;\r
- }\r
- dest+=32;\r
- MM_FreePtr (&grsegs[STARTTILE16+i]);\r
- UNMARKGRCHUNK(STARTTILE16+i);\r
- }\r
- else\r
- tileoffsets[i] = 0;\r
- }\r
-\r
-\r
-//\r
-// pics\r
-//\r
- numpics=1;\r
- destoff = FP_OFF(dest);\r
- for (i=FIRSTLATCHPIC+1;i<FIRSTGROUNDPIC;i++)\r
- {\r
- latchpics[numpics++] = destoff;\r
- CA_CacheGrChunk (i);\r
- j = pictable[i-STARTPICS].width * pictable[i-STARTPICS].height;\r
- VW_MemToScreen (grsegs[i],destoff,j,1);\r
- destoff+=j;\r
- MM_FreePtr (&grsegs[i]);\r
- UNMARKGRCHUNK(i);\r
- }\r
-\r
- base_numpics = numpics;\r
- base_destoff = destoff;\r
-\r
- }\r
-\r
- numpics = base_numpics;\r
- destoff = base_destoff;\r
-\r
-#if USE_STRIPS\r
-//\r
-// ground pics\r
-//\r
- numpics++;\r
- for (i=FIRSTGROUNDPIC+1;i<FIRSTSTRIPPIC;i++)\r
- {\r
- int shape = (*groundcolor & 0xf0) - 16;\r
-\r
- // Is current shape needed?\r
- //\r
- if (shape != (i-(FIRSTGROUNDPIC+1)))\r
- {\r
- numpics++;\r
- continue;\r
- }\r
-\r
- latchpics[numpics++] = destoff;\r
- CA_CacheGrChunk (i);\r
- j = pictable[i-STARTPICS].width * pictable[i-STARTPICS].height;\r
- VW_MemToScreen (grsegs[i],destoff,j,1);\r
- destoff+=j;\r
- MM_FreePtr (&grsegs[i]);\r
- UNMARKGRCHUNK(i);\r
- }\r
-\r
-\r
-//\r
-// 'parallax' strips - used in place of a sky color\r
-//\r
-// Under current setup, each strip takes about 7k in latch memory.\r
-// To create 2 pixel scrolling, 4 strips are needed, that's 28k of\r
-// latch memory needed to produce this effect.\r
-//\r
- numpics++;\r
- for (i=FIRSTSTRIPPIC+1;i<FIRSTSCALEPIC;i++)\r
- {\r
- memptr work;\r
- unsigned workdest,stripsize,planesize;\r
- short loop,pic=i-STARTPICS;\r
- int shape = (*skycolor & 0xf0) - 16;\r
-\r
- // Is current shape needed?\r
- //\r
- if (shape != (i-(FIRSTSTRIPPIC+1)))\r
- {\r
- numpics++;\r
- continue;\r
- }\r
-\r
- // CAL_ShiftSprite() works with the SRC and DST in the same\r
- // segment. So we must allocate memory for two strips, and\r
- // move the base strip into that segment. Then we can use the\r
- // 2nd half of that memory for each shifted strip.\r
- //\r
- CA_CacheGrChunk (i);\r
- planesize = (pictable[pic].width+1) * pictable[pic].height;\r
- stripsize = planesize * 4;\r
-// MM_GetPtr(&work,(stripsize*2)+0000);\r
- MM_GetPtr(&work,65536);\r
- movedata((unsigned)grsegs[i],0,(unsigned)work,0,stripsize);\r
- workdest = 32768; //(stripsize+15) & 0xFFF0;\r
-\r
- // Free base strip\r
- //\r
- MM_FreePtr (&grsegs[i]);\r
- UNMARKGRCHUNK(i);\r
-\r
- // Create three shifted strips and move 'em to latch!\r
- //\r
- for (loop=3; loop; loop--)\r
- {\r
- // Produce current shift for this strip\r
- //\r
- latchpics[numpics++] = destoff;\r
- CAL_ShiftSprite ((unsigned)work,0,workdest,pictable[pic].width,\r
- pictable[pic].height,loop*2,false);\r
-\r
- // Copy this shift to latch memory\r
- //\r
- VW_MemToScreen ((memptr)((unsigned)work+(workdest>>4)),destoff,planesize,1);\r
- destoff+=planesize;\r
- }\r
-\r
- // Copy unshifted strip to latch\r
- //\r
- latchpics[numpics++] = destoff;\r
- planesize = pictable[pic].width * pictable[pic].height;\r
- VW_MemToScreen (work,destoff,planesize,1);\r
- destoff+=planesize;\r
-\r
- // Free work buffer\r
- //\r
- MM_FreePtr(&work);\r
- }\r
-#endif\r
-\r
-// Keep track of how much latch memory we have...\r
-//\r
- latchmemavail = 65535-destoff;\r
-\r
- EGAMAPMASK(15);\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===================\r
-=\r
-= FizzleOut\r
-=\r
-===================\r
-*/\r
-\r
-void FizzleOut (int showlevel)\r
-{\r
- unsigned page1,page2;\r
-//\r
-// fizzle fade screen to grey\r
-//\r
- bufferofs = screenloc[(screenpage+1)%3];\r
- if (showlevel)\r
- DrawEnterScreen ();\r
- FizzleFade(bufferofs,displayofs,VIEWWIDTH,VIEWHEIGHT,false);\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= FreeUpMemory\r
-=\r
-====================\r
-*/\r
-\r
-void FreeUpMemory (void)\r
-{\r
- int i;\r
-\r
- for (i=0;i<NUMSCALEPICS;i++)\r
- if (shapedirectory[i])\r
- MM_SetPurge (&(memptr)shapedirectory[i],3);\r
-\r
- for (i=0;i<NUMSCALEWALLS;i++)\r
- if (walldirectory[i])\r
- MM_SetPurge (&(memptr)walldirectory[i],3);\r
-}\r
-\r
-//==========================================================================\r
-\r
-#if 0\r
-\r
-/*\r
-==================\r
-=\r
-= DrawHighScores\r
-=\r
-==================\r
-*/\r
-\r
-void DrawHighScores(void)\r
-{\r
- char buffer[16],*str;\r
- word i,j,\r
- w,h,\r
- x,y;\r
- HighScore *s;\r
-\r
-\r
- CA_CacheGrChunk (HIGHSCORESPIC);\r
- VWB_DrawPic (0,0,HIGHSCORESPIC);\r
- MM_SetPurge (&grsegs[HIGHSCORESPIC],3);\r
- UNMARKGRCHUNK(HIGHSCORESPIC);\r
-\r
- for (i = 0,s = Scores;i < MaxScores;i++,s++)\r
- {\r
- PrintY = 68 + (16 * i);\r
-\r
- //\r
- // name\r
- //\r
- PrintX = 60;\r
- US_Print(s->name);\r
-\r
- //\r
- // level\r
- //\r
- ultoa(s->completed,buffer,10);\r
- for (str = buffer;*str;str++)\r
- *str = *str + (129 - '0'); // Used fixed-width numbers (129...)\r
- USL_MeasureString(buffer,&w,&h);\r
- PrintX = (25 * 8) - 8 - w;\r
- US_Print(buffer);\r
-\r
- //\r
- // score\r
- //\r
- ultoa(s->score,buffer,10);\r
- for (str = buffer;*str;str++)\r
- *str = *str + (129 - '0'); // Used fixed-width numbers (129...)\r
- USL_MeasureString(buffer,&w,&h);\r
- PrintX = (34 * 8) - 8 - w;\r
- US_Print(buffer);\r
- }\r
-\r
- fontcolor = F_BLACK;\r
-}\r
-\r
-\r
-\r
-/*\r
-=======================\r
-=\r
-= CheckHighScore\r
-=\r
-=======================\r
-*/\r
-\r
-void CheckHighScore (long score,word other)\r
-{\r
- word i,j;\r
- int n;\r
- HighScore myscore;\r
-\r
- strcpy(myscore.name,"");\r
- myscore.score = score;\r
- myscore.completed = other;\r
-\r
- for (i = 0,n = -1;i < MaxScores;i++)\r
- {\r
- if\r
- (\r
- (myscore.score > Scores[i].score)\r
- || (\r
- (myscore.score == Scores[i].score)\r
- && (myscore.completed > Scores[i].completed)\r
- )\r
- )\r
- {\r
- for (j = MaxScores;--j > i;)\r
- Scores[j] = Scores[j - 1];\r
- Scores[i] = myscore;\r
- n = i;\r
- HighScoresDirty = true;\r
- break;\r
- }\r
- }\r
-\r
- if (n != -1)\r
- {\r
- //\r
- // got a high score\r
- //\r
- DrawHighScores ();\r
- PrintY = 68 + (16 * n);\r
- PrintX = 60;\r
- US_LineInput(PrintX,PrintY,Scores[n].name,nil,true,MaxHighName,100);\r
- }\r
-}\r
-\r
-#endif\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===================\r
-=\r
-= GameLoop\r
-=\r
-===================\r
-*/\r
-\r
-void GameLoop (void)\r
-{\r
- boolean wait = false;\r
- int i,xl,yl,xh,yh;\r
- char num[20];\r
-#ifdef PROFILE\r
- clock_t start,end;\r
-#endif\r
-\r
- DrawPlayScreen ();\r
- IN_ClearKeysDown();\r
-\r
-restart:\r
- if (!loadedgame)\r
- {\r
- gamestate.difficulty = restartgame;\r
- restartgame = gd_Continue;\r
- DrawEnterScreen ();\r
- if (gamestate.mapon != 8)\r
- fizzlein = true;\r
- wait = true;\r
- }\r
-\r
- do\r
- {\r
- playstate = gd_Continue;\r
- if (!loadedgame)\r
- SetupGameLevel ();\r
- else\r
- loadedgame = false;\r
-\r
- FreeUpMemory();\r
- LoadLatchMem();\r
- CacheScaleds ();\r
-\r
- if (EASYMODEON)\r
- DisplaySMsg("*** NOVICE ***", NULL);\r
- else\r
- DisplaySMsg("*** WARRIOR ***", NULL);\r
-\r
- status_delay = 250;\r
-\r
- RedrawStatusWindow();\r
- if (wait)\r
- {\r
- VW_WaitVBL(120);\r
- wait = false;\r
- }\r
-\r
-#ifdef PROFILE\r
-start = clock();\r
-while (start == clock());\r
-start++;\r
-#endif\r
-\r
- PlayLoop ();\r
-\r
-#ifdef PROFILE\r
-end = clock();\r
-itoa(end-start,str,10);\r
- Quit (str);\r
-#endif\r
-\r
-\r
- switch (playstate)\r
- {\r
- case ex_abort:\r
- FreeUpMemory ();\r
- return;\r
- case ex_resetgame:\r
- NewGame();\r
- case ex_loadedgame:\r
- case ex_warped:\r
- FreeUpMemory();\r
- if (playstate != ex_resetgame)\r
- DisplayMsg(" ", NULL);\r
- DisplaySMsg(" ", NULL);\r
- goto restart;\r
- case ex_victorious:\r
- screenpage = 0;\r
- bufferofs = 0;\r
- status_flag = 0;\r
- return;\r
- }\r
-\r
- } while (1);\r
-\r
-}\r
-\r
-\r
-#if 0\r
-//\r
-// make wall pictures purgable\r
-//\r
- for (i=0;i<NUMSCALEWALLS;i++)\r
- if (walldirectory[i])\r
- MM_SetPurge (&(memptr)walldirectory[i],3);\r
-\r
-\r
-//\r
-// cache wall pictures back in\r
-//\r
- for (i=1;i<NUMFLOORS;i++)\r
- if (tileneeded[i])\r
- {\r
- SetupScaleWall (walllight1[i]);\r
- SetupScaleWall (walllight2[i]);\r
- SetupScaleWall (walldark1[i]);\r
- SetupScaleWall (walldark2[i]);\r
- }\r
-#endif\r