Files
Catacomb3D/C3_MAIN.C
2026-03-12 19:22:23 +01:00

757 lines
14 KiB
C

/* Catacomb 3-D Source Code
* Copyright (C) 1993-2014 Flat Rock Software
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// C3_MAIN.C
#include "C3_DEF.H"
#pragma hdrstop
/*
=============================================================================
CATACOMB 3-D
An Id Software production
by John Carmack
=============================================================================
*/
/*
=============================================================================
LOCAL CONSTANTS
=============================================================================
*/
/*
=============================================================================
GLOBAL VARIABLES
=============================================================================
*/
memptr scalesegs[NUMPICS];
char str[80],str2[20];
unsigned tedlevelnum;
boolean tedlevel;
gametype gamestate;
exittype playstate;
/*
=============================================================================
LOCAL VARIABLES
=============================================================================
*/
//===========================================================================
// JAB Hack begin
#define MyInterrupt 0x60
void interrupt (*intaddr)();
void interrupt (*oldintaddr)();
char *JHParmStrings[] = {"no386",nil};
void
jabhack(void)
{
extern void far jabhack2(void);
extern int far CheckIs386(void);
int i;
oldintaddr = getvect(MyInterrupt);
for (i = 1;i < _argc;i++)
if (US_CheckParm(_argv[i],JHParmStrings) == 0)
return;
if (CheckIs386())
{
jabhack2();
setvect(MyInterrupt,intaddr);
}
}
void
jabunhack(void)
{
setvect(MyInterrupt,oldintaddr);
}
// JAB Hack end
//===========================================================================
/*
=====================
=
= NewGame
=
= Set up new game to start from the beginning
=
=====================
*/
void NewGame (void)
{
memset (&gamestate,0,sizeof(gamestate));
gamestate.mapon = 0;
gamestate.body = MAXBODY;
}
//===========================================================================
#define RLETAG 0xABCD
/*
==================
=
= SaveTheGame
=
==================
*/
boolean SaveTheGame(int file)
{
word i,compressed,expanded;
objtype *o;
memptr bigbuffer;
if (!CA_FarWrite(file,(void far *)&gamestate,sizeof(gamestate)))
return(false);
expanded = mapwidth * mapheight * 2;
MM_GetPtr (&bigbuffer,expanded);
for (i = 0;i < 3;i+=2) // Write planes 0 and 2
{
//
// leave a word at start of compressed data for compressed length
//
compressed = (unsigned)CA_RLEWCompress ((unsigned huge *)mapsegs[i]
,expanded,((unsigned huge *)bigbuffer)+1,RLETAG);
*(unsigned huge *)bigbuffer = compressed;
if (!CA_FarWrite(file,(void far *)bigbuffer,compressed+2) )
{
MM_FreePtr (&bigbuffer);
return(false);
}
}
for (o = player;o;o = o->next)
if (!CA_FarWrite(file,(void far *)o,sizeof(objtype)))
{
MM_FreePtr (&bigbuffer);
return(false);
}
MM_FreePtr (&bigbuffer);
return(true);
}
//===========================================================================
/*
==================
=
= LoadTheGame
=
==================
*/
boolean LoadTheGame(int file)
{
unsigned i,x,y;
objtype *obj,*prev,*next,*followed;
unsigned compressed,expanded;
unsigned far *map,tile;
memptr bigbuffer;
if (!CA_FarRead(file,(void far *)&gamestate,sizeof(gamestate)))
return(false);
SetupGameLevel (); // load in and cache the base old level
expanded = mapwidth * mapheight * 2;
MM_GetPtr (&bigbuffer,expanded);
for (i = 0;i < 3;i+=2) // Read planes 0 and 2
{
if (!CA_FarRead(file,(void far *)&compressed,sizeof(compressed)) )
{
MM_FreePtr (&bigbuffer);
return(false);
}
if (!CA_FarRead(file,(void far *)bigbuffer,compressed) )
{
MM_FreePtr (&bigbuffer);
return(false);
}
CA_RLEWexpand ((unsigned huge *)bigbuffer,
(unsigned huge *)mapsegs[i],expanded,RLETAG);
}
MM_FreePtr (&bigbuffer);
//
// copy the wall data to a data segment array again, to handle doors and
// bomb walls that are allready opened
//
memset (tilemap,0,sizeof(tilemap));
memset (actorat,0,sizeof(actorat));
map = mapsegs[0];
for (y=0;y<mapheight;y++)
for (x=0;x<mapwidth;x++)
{
tile = *map++;
if (tile<NUMFLOORS)
{
tilemap[x][y] = tile;
if (tile>0)
(unsigned)actorat[x][y] = tile;
}
}
// Read the object list back in - assumes at least one object in list
InitObjList ();
new = player;
while (true)
{
prev = new->prev;
next = new->next;
if (!CA_FarRead(file,(void far *)new,sizeof(objtype)))
return(false);
followed = new->next;
new->prev = prev;
new->next = next;
actorat[new->tilex][new->tiley] = new; // drop a new marker
if (followed)
GetNewObj (false);
else
break;
}
return(true);
}
//===========================================================================
/*
==================
=
= ResetGame
=
==================
*/
void ResetGame(void)
{
NewGame ();
ca_levelnum--;
ca_levelbit>>=1;
CA_ClearMarks();
ca_levelbit<<=1;
ca_levelnum++;
}
//===========================================================================
/*
==========================
=
= ShutdownId
=
= Shuts down all ID_?? managers
=
==========================
*/
void ShutdownId (void)
{
US_Shutdown ();
#ifndef PROFILE
SD_Shutdown ();
IN_Shutdown ();
#endif
VW_Shutdown ();
CA_Shutdown ();
MM_Shutdown ();
}
//===========================================================================
/*
==========================
=
= InitGame
=
= Load a few things right away
=
==========================
*/
void InitGame (void)
{
unsigned segstart,seglength;
int i,x,y;
unsigned *blockstart;
// US_TextScreen();
MM_Startup ();
VW_Startup ();
#ifndef PROFILE
IN_Startup ();
SD_Startup ();
#endif
US_Startup ();
// US_UpdateTextScreen();
CA_Startup ();
US_Setup ();
US_SetLoadSaveHooks(LoadTheGame,SaveTheGame,ResetGame);
//
// load in and lock down some basic chunks
//
CA_ClearMarks ();
CA_MarkGrChunk(STARTFONT);
CA_MarkGrChunk(STARTTILE8);
CA_MarkGrChunk(STARTTILE8M);
CA_MarkGrChunk(HAND1PICM);
CA_MarkGrChunk(HAND2PICM);
CA_MarkGrChunk(ENTERPLAQUEPIC);
CA_CacheMarks (NULL);
MM_SetLock (&grsegs[STARTFONT],true);
MM_SetLock (&grsegs[STARTTILE8],true);
MM_SetLock (&grsegs[STARTTILE8M],true);
MM_SetLock (&grsegs[HAND1PICM],true);
MM_SetLock (&grsegs[HAND2PICM],true);
MM_SetLock (&grsegs[ENTERPLAQUEPIC],true);
fontcolor = WHITE;
//
// build some tables
//
for (i=0;i<MAPSIZE;i++)
nearmapylookup[i] = &tilemap[0][0]+MAPSIZE*i;
for (i=0;i<PORTTILESHIGH;i++)
uwidthtable[i] = UPDATEWIDE*i;
blockstart = &blockstarts[0];
for (y=0;y<UPDATEHIGH;y++)
for (x=0;x<UPDATEWIDE;x++)
*blockstart++ = SCREENWIDTH*16*y+x*TILEWIDTH;
BuildTables (); // 3-d tables
SetupScaling ();
#ifndef PROFILE
// US_FinishTextScreen();
#endif
//
// reclaim the memory from the linked in text screen
//
segstart = FP_SEG(&introscn);
seglength = 4000/16;
if (FP_OFF(&introscn))
{
segstart++;
seglength--;
}
MML_UseSpace (segstart,seglength);
VW_SetScreenMode (GRMODE);
VW_ColorBorder (3);
VW_ClearVideo (BLACK);
//
// initialize variables
//
updateptr = &update[0];
*(unsigned *)(updateptr + UPDATEWIDE*PORTTILESHIGH) = UPDATETERMINATE;
bufferofs = 0;
displayofs = 0;
VW_SetLineWidth(SCREENWIDTH);
}
//===========================================================================
void clrscr (void); // can't include CONIO.H because of name conflicts...
/*
==========================
=
= Quit
=
==========================
*/
void Quit (char *error)
{
unsigned finscreen;
#if 0
if (!error)
{
CA_SetAllPurge ();
CA_CacheGrChunk (PIRACY);
finscreen = (unsigned)grsegs[PIRACY];
}
#endif
ShutdownId ();
if (error && *error)
{
puts(error);
exit(1);
}
#if 0
if (!NoWait)
{
movedata (finscreen,0,0xb800,0,4000);
bioskey (0);
clrscr();
}
#endif
exit(0);
}
//===========================================================================
/*
==================
=
= TEDDeath
=
==================
*/
void TEDDeath(void)
{
ShutdownId();
execlp("TED5.EXE","TED5.EXE","/LAUNCH",NULL);
}
//===========================================================================
/*
=====================
=
= DemoLoop
=
=====================
*/
static char *ParmStrings[] = {"easy","normal","hard",""};
void DemoLoop (void)
{
int i,level;
//
// check for launch from ted
//
if (tedlevel)
{
NewGame();
gamestate.mapon = tedlevelnum;
restartgame = gd_Normal;
for (i = 1;i < _argc;i++)
{
if ( (level = US_CheckParm(_argv[i],ParmStrings)) == -1)
continue;
restartgame = gd_Easy+level;
break;
}
GameLoop();
TEDDeath();
}
//
// main game cycle
//
displayofs = bufferofs = 0;
VW_Bar (0,0,320,200,0);
while (1)
{
CA_CacheGrChunk (TITLEPIC);
bufferofs = SCREEN2START;
displayofs = SCREEN1START;
VWB_DrawPic (0,0,TITLEPIC);
MM_SetPurge (&grsegs[TITLEPIC],3);
UNMARKGRCHUNK(TITLEPIC);
FizzleFade (bufferofs,displayofs,320,200,true);
if (!IN_UserInput(TickBase*3,false))
{
CA_CacheGrChunk (CREDITSPIC);
VWB_DrawPic (0,0,CREDITSPIC);
MM_SetPurge (&grsegs[CREDITSPIC],3);
UNMARKGRCHUNK(CREDITSPIC);
FizzleFade (bufferofs,displayofs,320,200,true);
}
if (!IN_UserInput(TickBase*3,false))
{
highscores:
DrawHighScores ();
FizzleFade (bufferofs,displayofs,320,200,true);
IN_UserInput(TickBase*3,false);
}
if (IN_IsUserInput())
{
US_ControlPanel ();
if (restartgame || loadedgame)
{
GameLoop ();
goto highscores;
}
}
}
}
//===========================================================================
/*
==========================
=
= SetupScalePic
=
==========================
*/
void SetupScalePic (unsigned picnum)
{
unsigned scnum;
scnum = picnum-FIRSTSCALEPIC;
if (shapedirectory[scnum])
{
MM_SetPurge (&(memptr)shapedirectory[scnum],0);
return; // allready in memory
}
CA_CacheGrChunk (picnum);
DeplanePic (picnum);
shapesize[scnum] = BuildCompShape (&shapedirectory[scnum]);
grneeded[picnum]&= ~ca_levelbit;
MM_FreePtr (&grsegs[picnum]);
}
//===========================================================================
/*
==========================
=
= SetupScaleWall
=
==========================
*/
void SetupScaleWall (unsigned picnum)
{
int x,y;
unsigned scnum;
byte far *dest;
scnum = picnum-FIRSTWALLPIC;
if (walldirectory[scnum])
{
MM_SetPurge (&walldirectory[scnum],0);
return; // allready in memory
}
CA_CacheGrChunk (picnum);
DeplanePic (picnum);
MM_GetPtr(&walldirectory[scnum],64*64);
dest = (byte far *)walldirectory[scnum];
for (x=0;x<64;x++)
for (y=0;y<64;y++)
*dest++ = spotvis[y][x];
grneeded[picnum]&= ~ca_levelbit;
MM_FreePtr (&grsegs[picnum]);
}
//===========================================================================
/*
==========================
=
= SetupScaling
=
==========================
*/
void SetupScaling (void)
{
int i,x,y;
byte far *dest;
//
// build the compiled scalers
//
for (i=1;i<=VIEWWIDTH/2;i++)
BuildCompScale (i*2,&scaledirectory[i]);
}
//===========================================================================
int showscorebox;
void RF_FixOfs (void)
{
}
void HelpScreens (void)
{
}
/*
==================
=
= CheckMemory
=
==================
*/
#define MINMEMORY 335000l
void CheckMemory(void)
{
unsigned finscreen;
if (mminfo.nearheap+mminfo.farheap+mminfo.EMSmem+mminfo.XMSmem
>= MINMEMORY)
return;
CA_CacheGrChunk (OUTOFMEM);
finscreen = (unsigned)grsegs[OUTOFMEM];
ShutdownId ();
movedata (finscreen,7,0xb800,0,4000);
gotoxy (1,24);
exit(1);
}
//===========================================================================
/*
==========================
=
= main
=
==========================
*/
void main (void)
{
short i;
if (stricmp(_argv[1], "/VER") == 0)
{
printf("Catacomb 3-D version 1.22 (Rev 1)\n");
printf("Copyright 1991-93 Softdisk Publishing\n");
printf("Developed for use with 100%% IBM compatibles\n");
printf("that have 640K memory and DOS version 3.3 or later\n");
printf("and EGA graphics or better.\n");
exit(0);
}
if (stricmp(_argv[1], "/?") == 0)
{
printf("Catacomb 3-D version 1.22\n");
printf("Copyright 1991-93 Softdisk Publishing\n\n");
printf("Syntax:\n");
printf("CAT3D [/<switch>]\n\n");
printf("Switch What it does\n");
printf("/? This Information\n");
printf("/VER Display Program Version Information\n");
printf("/COMP Fix problems with SVGA screens\n");
printf("/NOAL No AdLib or SoundBlaster detection\n");
printf("/NOJOYS Tell program to ignore joystick\n");
printf("/NOMOUSE Tell program to ignore mouse\n");
printf("/HIDDENCARD Overrides video detection\n\n");
printf("Each switch must include a '/' and multiple switches\n");
printf("must be seperated by at least one space.\n\n");
exit(0);
}
jabhack();
InitGame ();
CheckMemory ();
LoadLatchMem ();
#ifdef PROFILE
NewGame ();
GameLoop ();
#endif
//NewGame ();
//GameLoop ();
DemoLoop();
Quit("Demo loop exited???");
}