planet-strike/JM_FREE.C
2013-07-08 00:00:00 +00:00

2350 lines
No EOL
48 KiB
C

// JM_FREE.C
//
// Warning!
//
// All functions in this source file are designated usable by the memory
// manager after program initialization.
//
#include "ID_HEADS.H"
#pragma hdrstop
#include "3d_def.h"
#define SKIP_CHECKSUMS (true)
#define SHOW_CHECKSUM (false)
#if GAME_VERSION == SHAREWARE_VERSION
#define AUDIOT_CHECKSUM 0xFFF87142
#define MAPTEMP_CHECKSUM 0x000370C9
#define VGAGRAPH_CHECKSUM 0xFFFFDE44
#define DIZFILE_CHECKSUM 0x00000879l
#elif GAME_VERSION == MISSIONS_1_THR_3
#define AUDIOT_CHECKSUM 0xFFF87142
#define MAPTEMP_CHECKSUM 0x00084F1F
#define VGAGRAPH_CHECKSUM 0xFFFFDE44
#define DIZFILE_CHECKSUM 0x00000879l
#else
#define AUDIOT_CHECKSUM 0xfff912C9
#define MAPTEMP_CHECKSUM 0x00107739
#define VGAGRAPH_CHECKSUM 0xffff6C9A
#define DIZFILE_CHECKSUM 0x00000879l
#endif
#pragma warn -pro
#pragma warn -use
void SDL_SBSetDMA(byte channel);
void SDL_SetupDigi(void);
//=========================================================================
//
// FAR FREE DATA
//
//=========================================================================
#if FREE_DATA
char far JM_FREE_DATA_START[1]={0};
#endif
#if TECH_SUPPORT_VERSION
char far EnterBetaCode[]="\n TECH SUPPORT VERSION!\n\n NO DISTRIBUTING!";
#elif BETA_TEST
char far EnterBetaCode[]=" !BETA VERSION!\n DO NOT DISTRIBUTE\n UNDER PENALTY OF DEATH\n\n ENTER BETA CODE";
#endif
char far * far JHParmStrings[] = {"no386","is386",nil};
char far show_text1[]="\n SYSTEM INFO\n";
char far show_text2[]="=======================\n\n";
char far show_text3[]="-- Memory avail after game is loaded --\n\n";
char far show_text4[]=" ** Insufficient memory to run the game **";
char far show_text5[]="---- Extra Devices ----\n\n";
static char far * far ParmStrings[] = {"HIDDENCARD",""};
static byte far wolfdigimap[] =
{
// These first sounds are in the upload version
ATKIONCANNONSND, 0,
ATKCHARGEDSND, 1,
ATKBURSTRIFLESND, 2,
ATKGRENADESND, 46,
OPENDOORSND, 3,
CLOSEDOORSND, 4,
HTECHDOOROPENSND, 5,
HTECHDOORCLOSESND, 6,
INFORMANTDEATHSND, 7,
SCIENTISTHALTSND, 19,
SCIENTISTDEATHSND, 20,
GOLDSTERNHALTSND, 8,
GOLDSTERNLAUGHSND, 24,
HALTSND, 9, // Rent-A-Cop 1st sighting
RENTDEATH1SND, 10, // Rent-A-Cop Death
EXPLODE1SND, 11,
GGUARDHALTSND, 12,
GGUARDDEATHSND, 17,
PROHALTSND, 16,
PROGUARDDEATHSND, 13,
BLUEBOYDEATHSND, 18,
BLUEBOYHALTSND, 51,
SWATHALTSND, 22,
SWATDIESND, 47,
SCANHALTSND, 15,
SCANDEATHSND, 23,
PODHATCHSND, 26,
PODHALTSND, 50,
PODDEATHSND, 49,
ELECTSHOTSND, 27,
DOGBOYHALTSND, 14,
DOGBOYDEATHSND, 21,
ELECARCDAMAGESND, 25,
ELECAPPEARSND, 28,
ELECDIESND, 29,
INFORMDEATH2SND, 39, // Informant Death #2
RENTDEATH2SND, 34, // Rent-A-Cop Death #2
PRODEATH2SND, 42, // PRO Death #2
SWATDEATH2SND, 48, // SWAT Death #2
SCIDEATH2SND, 53, // Gen. Sci Death #2
LIQUIDDIESND, 30,
GURNEYSND, 31,
GURNEYDEATHSND, 41,
WARPINSND, 32,
WARPOUTSND, 33,
EXPLODE2SND, 35,
LCANHALTSND, 36,
LCANDEATHSND, 37,
// RENTDEATH3SND, 38, // Rent-A-Cop Death #3
INFORMDEATH3SND, 40, // Informant Death #3
// PRODEATH3SND, 43, // PRO Death #3
// SWATDEATH3SND, 52, // Swat Guard #3
SCIDEATH3SND, 54, // Gen. Sci Death #3
LCANBREAKSND, 44,
SCANBREAKSND, 45,
CLAWATTACKSND, 56,
SPITATTACKSND, 55,
PUNCHATTACKSND, 57,
LASTSOUND
};
#if 0
static byte far wolfdigimap[] =
{
// These first sounds are in the upload version
ATKIONCANNONSND, 0,
ATKCHARGEDSND, 1,
ATKBURSTRIFLESND, 2,
ATKGRENADESND, 46,
OPENDOORSND, 3,
CLOSEDOORSND, 4,
HTECHDOOROPENSND, 5,
HTECHDOORCLOSESND, 6,
INFORMANTDEATHSND, 7,
SCIENTISTHALTSND, 19,
SCIENTISTDEATHSND, 20,
GOLDSTERNHALTSND, 8,
GOLDSTERNLAUGHSND, 24,
HALTSND, 9, // Rent-A-Cop 1st sighting
RENTDEATH1SND, 10, // Rent-A-Cop Death
EXPLODE1SND, 11,
GGUARDHALTSND, 12,
GGUARDDEATHSND, 17,
PROHALTSND, 16,
PROGUARDDEATHSND, 13,
BLUEBOYDEATHSND, 18,
BLUEBOYHALTSND, 51,
SWATHALTSND, 22,
SWATDIESND, 47,
SCANHALTSND, 15,
SCANDEATHSND, 23,
PODHATCHSND, 26,
PODHALTSND, 50,
PODDEATHSND, 49,
ELECTSHOTSND, 27,
DOGBOYHALTSND, 14,
DOGBOYDEATHSND, 21,
ELECARCDAMAGESND, 25,
ELECAPPEARSND, 28,
ELECDIESND, 29,
INFORMDEATH2SND, 39, // Informant Death #2
RENTDEATH2SND, 34, // Rent-A-Cop Death #2
PRODEATH2SND, 42, // PRO Death #2
SWATDEATH2SND, 48, // SWAT Death #2
SCIDEATH2SND, 53, // Gen. Sci Death #2
LIQUIDDIESND, 30,
GURNEYSND, 31,
GURNEYDEATHSND, 41,
WARPINSND, 32,
WARPOUTSND, 33,
EXPLODE2SND, 35,
LCANHALTSND, 36,
LCANDEATHSND, 37,
// RENTDEATH3SND, 38, // Rent-A-Cop Death #3
INFORMDEATH3SND, 40, // Informant Death #3
// PRODEATH3SND, 43, // PRO Death #3
// SWATDEATH3SND, 52, // Swat Guard #3
SCIDEATH3SND, 54, // Gen. Sci Death #3
LCANBREAKSND, 44,
SCANBREAKSND, 45,
CLAWATTACKSND, 56,
SPITATTACKSND, 55,
PUNCHATTACKSND, 57,
LASTSOUND
};
#endif
char far cinfo_text[]= "\n"
"Planet Strike\n"
"Copyright (c) 1993 - JAM Productions, Inc.\n"
"All rights reserved.\n";
#if BETA_TEST
char far dver_text[]="Download the latest version pal!";
#endif
#if FREE_DATA
char far JM_FREE_DATA_END[1]={0};
#endif
extern byte far colormap[];
byte far * lightsource;
//=========================================================================
//
// FREE FUNCTIONS
//
//=========================================================================
#if FREE_FUNCTIONS
// This function is used as a label for the start of the
// functions used by the memory manager.
//
void JM_FREE_START()
{
}
#endif
// ------------------ ID Software 'startup' functions ---------------------
/*
======================
=
= CA_Startup
=
= Open all files and load in headers
=
======================
*/
void CA_Startup (void)
{
#ifdef PROFILE
unlink ("PROFILE.TXT");
profilehandle = open("PROFILE.TXT", O_CREAT | O_WRONLY | O_TEXT);
#endif
CAL_SetupMapFile ();
CAL_SetupGrFile ();
CAL_SetupAudioFile ();
mapon = -1;
ca_levelbit = 1;
ca_levelnum = 0;
}
//#if !IN_DEVELOPMENT
extern boolean IN_Started;
extern char far * far IN_ParmStrings[];
extern boolean INL_StartJoy(word joy);
extern boolean INL_StartMouse(void);
extern void INL_StartKbd(void);
///////////////////////////////////////////////////////////////////////////
//
// INL_StartJoy() - Detects & auto-configures the specified joystick
// The auto-config assumes the joystick is centered
//
///////////////////////////////////////////////////////////////////////////
boolean
INL_StartJoy(word joy)
{
word x,y;
IN_GetJoyAbs(joy,&x,&y);
if
(
((x == 0) || (x > MaxJoyValue - 10))
|| ((y == 0) || (y > MaxJoyValue - 10))
)
return(false);
else
{
IN_SetupJoy(joy,0,x * 2,0,y * 2);
return(true);
}
}
///////////////////////////////////////////////////////////////////////////
//
// IN_Startup() - Starts up the Input Mgr
//
///////////////////////////////////////////////////////////////////////////
void
IN_Startup(void)
{
boolean checkjoys,checkmouse,checkNG;
word i;
if (IN_Started)
return;
checkjoys = true;
checkmouse = true;
checkNG = false;
for (i = 1;i < _argc;i++)
{
switch (US_CheckParm(_argv[i],IN_ParmStrings))
{
case 0:
checkjoys = false;
break;
case 1:
checkmouse = false;
break;
case 2:
checkNG = true;
break;
}
}
if (checkNG)
{
#define WORD_CODE(c1,c2) ((c2)|(c1<<8))
NGjoy(0xf0);
if ((_AX==WORD_CODE('S','G')) && _BX)
NGinstalled=true;
}
INL_StartKbd();
MousePresent = checkmouse? INL_StartMouse() : false;
for (i = 0;i < MaxJoys;i++)
JoysPresent[i] = checkjoys? INL_StartJoy(i) : false;
IN_Started = true;
}
//#endif
/*
===================
=
= MM_Startup
=
= Grabs all space from turbo with malloc/farmalloc
= Allocates bufferseg misc buffer
=
===================
*/
extern boolean mmstarted,bombonerror;
extern mmblocktype far mmblocks[], far *mmhead, far *mmfree,
far *mmnew, far *mmrover;
extern void far *farheap;
extern void *nearheap;
void MM_Startup (void)
{
int i;
unsigned long length;
void far *start;
unsigned segstart,seglength,endfree;
if (mmstarted)
MM_Shutdown ();
mmstarted = true;
bombonerror = true;
//
// set up the linked list (everything in the free list;
//
mmhead = NULL;
mmfree = &mmblocks[0];
for (i=0;i<MAXBLOCKS-1;i++)
mmblocks[i].next = &mmblocks[i+1];
mmblocks[i].next = NULL;
//
// locked block of all memory until we punch out free space
//
GETNEWBLOCK;
mmhead = mmnew; // this will allways be the first node
mmnew->start = 0;
mmnew->length = 0xffff;
mmnew->attributes = LOCKBIT;
mmnew->next = NULL;
mmrover = mmhead;
//
// get all available near conventional memory segments
//
length=coreleft();
start = (void far *)(nearheap = malloc(length));
length -= 16-(FP_OFF(start)&15);
length -= SAVENEARHEAP;
seglength = length / 16; // now in paragraphs
segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;
MML_UseSpace (segstart,seglength);
mminfo.nearheap = length;
//
// get all available far conventional memory segments
//
length=farcoreleft();
start = farheap = farmalloc(length);
length -= 16-(FP_OFF(start)&15);
length -= SAVEFARHEAP;
seglength = length / 16; // now in paragraphs
segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;
MML_UseSpace (segstart,seglength);
mminfo.farheap = length;
mminfo.mainmem = mminfo.nearheap + mminfo.farheap;
// __SEGS_AVAILABLE__ = (long)(mminfo.EMSmem + mminfo.XMSmem + mminfo.mainmem) / 16;
//
// allocate the misc buffer
//
mmrover = mmhead; // start looking for space after low block
MM_GetPtr (&bufferseg,BUFFERSIZE);
}
//
// PML_StartupEMS() - Sets up EMS for Page Mgr's use
// Checks to see if EMS driver is present
// Verifies that EMS hardware is present
// Make sure that EMS version is 3.2 or later
// If there's more than our minimum (2 pages) available, allocate it (up
// to the maximum we need)
//
#if !DUAL_SWAP_FILES
char EMMDriverName[9] = "EMMXXXX0";
extern word EMSAvail,EMSPagesAvail,EMSHandle,
EMSPageFrame,EMSPhysicalPage;
extern EMSListStruct EMSList[];
boolean
PML_StartupEMS(void)
{
int i;
long size;
EMSPresent = false; // Assume that we'll fail
EMSAvail = 0;
_DX = (word)EMMDriverName;
_AX = 0x3d00;
geninterrupt(0x21); // try to open EMMXXXX0 device
asm jnc gothandle
goto error;
gothandle:
_BX = _AX;
_AX = 0x4400;
geninterrupt(0x21); // get device info
asm jnc gotinfo;
goto error;
gotinfo:
asm and dx,0x80
if (!_DX)
goto error;
_AX = 0x4407;
geninterrupt(0x21); // get status
asm jc error
if (!_AL)
goto error;
_AH = 0x3e;
geninterrupt(0x21); // close handle
_AH = EMS_STATUS;
geninterrupt(EMS_INT);
if (_AH)
goto error; // make sure EMS hardware is present
_AH = EMS_VERSION;
geninterrupt(EMS_INT);
if (_AH || (_AL < 0x32)) // only work on EMS 3.2 or greater (silly, but...)
goto error;
_AH = EMS_GETFRAME;
geninterrupt(EMS_INT);
if (_AH)
goto error; // find the page frame address
EMSPageFrame = _BX;
_AH = EMS_GETPAGES;
geninterrupt(EMS_INT);
if (_AH)
goto error;
if (_BX < 2)
goto error; // Require at least 2 pages (32k)
EMSAvail = _BX;
// Don't hog all available EMS
size = EMSAvail * (long)EMSPageSize;
if (size - (EMSPageSize * 2) > (ChunksInFile * (long)PMPageSize))
{
size = (ChunksInFile * (long)PMPageSize) + EMSPageSize;
EMSAvail = size / EMSPageSize;
}
_AH = EMS_ALLOCPAGES;
_BX = EMSAvail;
geninterrupt(EMS_INT);
if (_AH)
goto error;
EMSHandle = _DX;
mminfo.EMSmem += EMSAvail * (long)EMSPageSize;
// Initialize EMS mapping cache
for (i = 0;i < EMSFrameCount;i++)
EMSList[i].baseEMSPage = -1;
EMSPresent = true; // We have EMS
error:
return(EMSPresent);
}
//
// PML_StartupXMS() - Starts up XMS for the Page Mgr's use
// Checks for presence of an XMS driver
// Makes sure that there's at least a page of XMS available
// Allocates any remaining XMS (rounded down to the nearest page size)
//
extern boolean XMSPresent;
extern word XMSAvail,XMSPagesAvail,XMSHandle;
extern longword XMSDriver;
extern int XMSProtectPage;
boolean
PML_StartupXMS(void)
{
XMSPresent = false; // Assume failure
XMSAvail = 0;
asm mov ax,0x4300
asm int XMS_INT // Check for presence of XMS driver
if (_AL != 0x80)
goto error;
asm mov ax,0x4310
asm int XMS_INT // Get address of XMS driver
asm mov [WORD PTR XMSDriver],bx
asm mov [WORD PTR XMSDriver+2],es // function pointer to XMS driver
XMS_CALL(XMS_QUERYFREE); // Find out how much XMS is available
XMSAvail = _AX;
if (!_AX) // AJR: bugfix 10/8/92
goto error;
XMSAvail &= ~(PMPageSizeKB - 1); // Round off to nearest page size
if (XMSAvail < (PMPageSizeKB * 2)) // Need at least 2 pages
goto error;
_DX = XMSAvail;
XMS_CALL(XMS_ALLOC); // And do the allocation
XMSHandle = _DX;
if (!_AX) // AJR: bugfix 10/8/92
{
XMSAvail = 0;
goto error;
}
mminfo.XMSmem += XMSAvail * 1024;
XMSPresent = true;
error:
return(XMSPresent);
}
//
//
// PML_StartupMainMem() - Allocates as much main memory as is possible for
// the Page Mgr. The memory is allocated as non-purgeable, so if it's
// necessary to make requests of the Memory Mgr, PM_UnlockMainMem()
// needs to be called.
//
extern boolean MainPresent;
extern memptr MainMemPages[PMMaxMainMem];
extern PMBlockAttr MainMemUsed[PMMaxMainMem];
extern int MainPagesAvail;
void
PML_StartupMainMem(void)
{
int i,n;
memptr *p;
MainPagesAvail = 0;
MM_BombOnError(false);
for (i = 0,p = MainMemPages;i < PMMaxMainMem;i++,p++)
{
MM_GetPtr(p,PMPageSize);
if (mmerror)
break;
MainPagesAvail++;
MainMemUsed[i] = pmba_Allocated;
}
MM_BombOnError(true);
if (mmerror)
mmerror = false;
if (MainPagesAvail < PMMinMainMem)
PM_ERROR(PML_STARTUPMAINMEM_LOW);
MainPresent = true;
}
//
// PM_Startup() - Start up the Page Mgr
//
extern boolean PMStarted;
extern char far * far PM_ParmStrings[];
void
PM_Startup(void)
{
boolean nomain,noems,noxms;
int i;
if (PMStarted)
return;
nomain = noems = noxms = false;
for (i = 1;i < _argc;i++)
{
switch (US_CheckParm(_argv[i],PM_ParmStrings))
{
case 0:
nomain = true;
break;
case 1:
noems = true;
break;
case 2:
noxms = true;
break;
}
}
OpenPageFile();
if (!noems)
PML_StartupEMS();
if (!noxms)
PML_StartupXMS();
if (nomain && !EMSPresent)
PM_ERROR(PM_STARTUP_NO_MAIN_EMS);
else
PML_StartupMainMem();
PM_Reset();
PMStarted = true;
}
#endif
///////////////////////////////////////////////////////////////////////////
//
// US_Startup() - Starts the User Mgr
//
///////////////////////////////////////////////////////////////////////////
extern boolean US_Started;
extern char far * far US_ParmStrings[];
extern char far * far US_ParmStrings2[];
extern int USL_HardError(word errval,int ax,int bp,int si);
void
US_Startup(void)
{
int i,n;
if (US_Started)
return;
harderr(USL_HardError); // Install the fatal error handler
US_InitRndT(true); // Initialize the random number generator
for (i = 1;i < _argc;i++)
{
switch (US_CheckParm(_argv[i],US_ParmStrings2))
{
case 0:
compatability = true;
break;
case 1:
compatability = false;
break;
}
}
// Check for TED launching here
for (i = 1;i < _argc;i++)
{
n = US_CheckParm(_argv[i],US_ParmStrings);
switch(n)
{
case 0:
#if 0
tedlevelnum = atoi(_argv[i + 1]);
// if (tedlevelnum >= 0)
tedlevel = true;
#endif
break;
// case 1:
// NoWait = true;
// break;
}
}
US_Started = true;
}
/*
=======================
=
= VL_Startup // WOLFENSTEIN HACK
=
=======================
*/
void VL_Startup (void)
{
int i,videocard;
asm cld;
videocard = VL_VideoID ();
for (i = 1;i < _argc;i++)
if (US_CheckParm(_argv[i],ParmStrings) == 0)
{
videocard = 5;
break;
}
if (videocard != 5)
Quit ("Improper video card! Try the -HIDDENCARD command line parameter!");
}
#if !RESTART_PICTURE_PAUSE
/*
=======================
=
= VL_SetVGAPlaneMode
=
=======================
*/
void VL_SetVGAPlaneMode (void)
{
asm mov ax,0x13
asm int 0x10
VL_DePlaneVGA ();
VGAMAPMASK(15);
VL_SetLineWidth (40);
}
/*
=================
=
= VL_ClearVideo
=
= Fill the entire video buffer with a given color
=
=================
*/
void VL_ClearVideo (byte color)
{
asm mov dx,GC_INDEX
asm mov al,GC_MODE
asm out dx,al
asm inc dx
asm in al,dx
asm and al,0xfc // write mode 0 to store directly to video
asm out dx,al
asm mov dx,SC_INDEX
asm mov ax,SC_MAPMASK+15*256
asm out dx,ax // write through all four planes
asm mov ax,SCREENSEG
asm mov es,ax
asm mov al,[color]
asm mov ah,al
asm mov cx,0x8000 // 0x8000 words, clearing 8 video bytes/word
asm xor di,di
asm rep stosw
}
/*
=================
=
= VL_DePlaneVGA
=
=================
*/
void VL_DePlaneVGA (void)
{
//
// change CPU addressing to non linear mode
//
//
// turn off chain 4 and odd/even
//
outportb (SC_INDEX,SC_MEMMODE);
outportb (SC_INDEX+1,(inportb(SC_INDEX+1)&~8)|4);
outportb (SC_INDEX,SC_MAPMASK); // leave this set throughought
//
// turn off odd/even and set write mode 0
//
outportb (GC_INDEX,GC_MODE);
outportb (GC_INDEX+1,inportb(GC_INDEX+1)&~0x13);
//
// turn off chain
//
outportb (GC_INDEX,GC_MISCELLANEOUS);
outportb (GC_INDEX+1,inportb(GC_INDEX+1)&~2);
//
// clear the entire buffer space, because int 10h only did 16 k / plane
//
VL_ClearVideo (0);
//
// change CRTC scanning from doubleword to byte mode, allowing >64k scans
//
outportb (CRTC_INDEX,CRTC_UNDERLINE);
outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1)&~0x40);
outportb (CRTC_INDEX,CRTC_MODE);
outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1)|0x40);
}
/*
====================
=
= VL_SetLineWidth
=
= Line witdh is in WORDS, 40 words is normal width for vgaplanegr
=
====================
*/
void VL_SetLineWidth (unsigned width)
{
int i,offset;
//
// set wide virtual screen
//
outport (CRTC_INDEX,CRTC_OFFSET+width*256);
//
// set up lookup tables
//
linewidth = width*2;
offset = 0;
for (i=0;i<MAXSCANLINES;i++)
{
ylookup[i]=offset;
offset += linewidth;
}
}
#endif
/*
==================
=
= BuildTables
=
= Calculates:
=
= scale projection constant
= sintable/costable overlapping fractional tables
=
==================
*/
const float radtoint = (float)FINEANGLES/2/PI;
void BuildTables (void)
{
int i;
float angle,anglestep;
double tang;
fixed value;
byte far * temp;
//
// calculate fine tangents
//
for (i=0;i<FINEANGLES/8;i++)
{
tang = tan( (i+0.5)/radtoint);
finetangent[i] = tang*TILEGLOBAL;
finetangent[FINEANGLES/4-1-i] = 1/tang*TILEGLOBAL;
}
//
// costable overlays sintable with a quarter phase shift
// ANGLES is assumed to be divisable by four
//
// The low word of the value is the fraction, the high bit is the sign bit,
// bits 16-30 should be 0
//
angle = 0;
anglestep = PI/2/ANGLEQUAD;
for (i=0;i<=ANGLEQUAD;i++)
{
value=GLOBAL1*sin(angle);
sintable[i]=
sintable[i+ANGLES]=
sintable[ANGLES/2-i] = value;
sintable[ANGLES-i]=
sintable[ANGLES/2+i] = value | 0x80000000l;
angle += anglestep;
}
// Fix ColorMap
MM_GetPtr(&(memptr)temp,16896);
_fmemcpy(temp,colormap,16896);
lightsource=(byte far *)(((long)colormap + 255)&~0xff);
_fmemcpy(lightsource,temp,16384);
}
/*
===================
=
= SetupWalls
=
= Map tile values to scaled pics
=
===================
*/
void SetupWalls (void)
{
int i;
//
// Hey! Yea You! This is where you can VERY easly setup to use a
// specific 'BANK' of wall graphics.... JTR
//
for (i=1;i<MAXWALLTILES;i++)
{
horizwall[i]=(i-1)*2;
vertwall[i]=(i-1)*2+1;
}
}
/*
=====================
=
= InitDigiMap
=
=====================
*/
// 3D_GAME.C
void InitDigiMap (void)
{
char far *map;
for (map = wolfdigimap;*map != LASTSOUND;map += 2)
DigiMap[map[0]] = map[1];
}
/*
======================
=
= CAL_SetupAudioFile
=
======================
*/
void CAL_SetupAudioFile (void)
{
int handle;
long length;
char fname[13];
//
// load maphead.ext (offsets and tileinfo for map file)
//
#ifndef AUDIOHEADERLINKED
strcpy(fname,aheadname);
strcat(fname,extension);
if ((handle = open(fname,
O_RDONLY | O_BINARY, S_IREAD)) == -1)
CA_CannotOpen(fname);
length = filelength(handle);
MM_GetPtr (&(memptr)audiostarts,length);
CA_FarRead(handle, (byte far *)audiostarts, length);
close(handle);
#else
audiohuffman = (huffnode *)&audiodict;
CAL_OptimizeNodes (audiohuffman);
audiostarts = (long _seg *)FP_SEG(&audiohead);
#endif
//
// open the data file
//
OpenAudioFile();
}
/*
======================
=
= CAL_SetupGrFile
=
======================
*/
void CAL_SetupGrFile (void)
{
char fname[13];
int handle;
memptr compseg;
#ifdef GRHEADERLINKED
grhuffman = (huffnode *)&EGAdict;
grstarts = (long _seg *)FP_SEG(&EGAhead);
CAL_OptimizeNodes (grhuffman);
#else
//
// load ???dict.ext (huffman dictionary for graphics files)
//
strcpy(fname,gdictname);
strcat(fname,extension);
if ((handle = open(fname,
O_RDONLY | O_BINARY, S_IREAD)) == -1)
CA_CannotOpen(fname);
read(handle, &grhuffman, sizeof(grhuffman));
close(handle);
CAL_OptimizeNodes (grhuffman);
//
// load the data offsets from ???head.ext
//
MM_GetPtr (&(memptr)grstarts,(NUMCHUNKS+1)*FILEPOSSIZE);
strcpy(fname,gheadname);
strcat(fname,extension);
if ((handle = open(fname,
O_RDONLY | O_BINARY, S_IREAD)) == -1)
CA_CannotOpen(fname);
CA_FarRead(handle, (memptr)grstarts, (NUMCHUNKS+1)*FILEPOSSIZE);
close(handle);
#endif
//
// Open the graphics file, leaving it open until the game is finished
//
OpenGrFile();
//
// load the pic and sprite headers into the arrays in the data segment
//
MM_GetPtr(&(memptr)pictable,NUMPICS*sizeof(pictabletype));
CAL_GetGrChunkLength(STRUCTPIC); // position file pointer
MM_GetPtr(&compseg,chunkcomplen);
CA_FarRead (grhandle,compseg,chunkcomplen);
CAL_HuffExpand (compseg, (byte huge *)pictable,NUMPICS*sizeof(pictabletype),grhuffman,false);
MM_FreePtr(&compseg);
// MDM begin
#if 0
MM_GetPtr(&(memptr)picmtable,NUMPICM*sizeof(pictabletype));
CAL_GetGrChunkLength(STRUCTPICM); // position file pointer
MM_GetPtr(&compseg,chunkcomplen);
CA_FarRead (grhandle,compseg,chunkcomplen);
CAL_HuffExpand (compseg, (byte huge *)picmtable,NUMPICS*sizeof(pictabletype),grhuffman,false);
MM_FreePtr(&compseg);
#endif
// MDM end
}
/*
======================
=
= CAL_SetupMapFile
=
======================
*/
void CAL_SetupMapFile (void)
{
int i;
int handle;
long length,pos;
char fname[13];
//
// load maphead.ext (offsets and tileinfo for map file)
//
#ifndef MAPHEADERLINKED
strcpy(fname,mheadname);
strcat(fname,extension);
if ((handle = open(fname,
O_RDONLY | O_BINARY, S_IREAD)) == -1)
CA_CannotOpen(fname);
length = filelength(handle);
MM_GetPtr (&(memptr)tinf,length);
CA_FarRead(handle, tinf, length);
close(handle);
#else
tinf = (byte _seg *)FP_SEG(&maphead);
#endif
//
// open the data file
//
OpenMapFile();
//
// load all map header
//
for (i=0;i<NUMMAPS;i++)
{
pos = ((mapfiletype _seg *)tinf)->headeroffsets[i];
if (pos<0) // $FFFFFFFF start is a sparse map
continue;
MM_GetPtr(&(memptr)mapheaderseg[i],sizeof(maptype));
MM_SetLock(&(memptr)mapheaderseg[i],true);
lseek(maphandle,pos,SEEK_SET);
CA_FarRead (maphandle,(memptr)mapheaderseg[i],sizeof(maptype));
}
//
// allocate space for 3 64*64 planes
//
for (i=0;i<MAPPLANES;i++)
{
MM_GetPtr (&(memptr)mapsegs[i],64*64*2);
MM_SetLock (&(memptr)mapsegs[i],true);
}
#if FORCE_FILE_CLOSE
CloseMapFile();
#endif
}
// --------------------- Other general functions ------------------------
/*
====================
=
= ReadConfig
=
====================
*/
void ReadConfig(void)
{
int file;
SDMode sd;
SMMode sm;
SDSMode sds;
boolean config_found=false;
unsigned flags=gamestate.flags;
MakeDestPath(configname);
if ( (file = open(tempPath,O_BINARY | O_RDONLY)) != -1)
{
//
// valid config file
//
read(file,Scores,sizeof(HighScore) * MaxScores);
read(file,&sd,sizeof(sd));
read(file,&sm,sizeof(sm));
read(file,&sds,sizeof(sds));
read(file,&mouseenabled,sizeof(mouseenabled));
read(file,&joystickenabled,sizeof(joystickenabled));
read(file,&joypadenabled,sizeof(joypadenabled));
read(file,&joystickprogressive,sizeof(joystickprogressive));
read(file,&joystickport,sizeof(joystickport));
read(file,&dirscan,sizeof(dirscan));
read(file,&buttonscan,sizeof(buttonscan));
read(file,&buttonmouse,sizeof(buttonmouse));
read(file,&buttonjoy,sizeof(buttonjoy));
read(file,&viewsize,sizeof(viewsize));
read(file,&mouseadjustment,sizeof(mouseadjustment));
read(file,&flags,sizeof(flags)); // Use temp so we don't destroy pre-sets.
flags &= GS_HEARTB_SOUND|GS_ATTACK_INFOAREA|GS_LIGHTING|GS_DRAW_CEILING|GS_DRAW_FLOOR; // Mask out the useful flags!
gamestate.flags |= flags; // Must "OR", some flags are already set.
close(file);
#if 0
#ifdef CEILING_FLOOR_COLORS
if (gamestate.flags & GS_DRAW_FLOOR)
{
PM_Shutdown();
PM_Startup ();
PM_UnlockMainMem ();
}
#endif
#endif
if (sd == sdm_AdLib &&
(!AdLibPresent || !SoundBlasterPresent))
{
sd = sdm_PC;
sd = smm_Off;
}
if ((sds == sds_SoundBlaster && !SoundBlasterPresent) ||
(sds == sds_SoundSource && !SoundSourcePresent))
sds = sds_Off;
if (!MousePresent)
mouseenabled = false;
if (!JoysPresent[joystickport])
joystickenabled = false;
MainMenu[6].active=1;
MainItems.curpos=0;
config_found=true;
}
if ((!config_found) || (!viewsize))
{
//
// no config file, so select by hardware
//
if (SoundBlasterPresent || AdLibPresent)
{
sd = sdm_AdLib;
sm = smm_AdLib;
}
else
{
sd = sdm_PC;
sm = smm_Off;
}
if (SoundBlasterPresent)
sds = sds_SoundBlaster;
else if (SoundSourcePresent)
sds = sds_SoundSource;
else
sds = sds_Off;
if (MousePresent)
mouseenabled = true;
joystickenabled = false;
joypadenabled = false;
joystickport = 0;
joystickprogressive = false;
viewsize = 17;
mouseadjustment=5;
gamestate.flags |= GS_HEARTB_SOUND|GS_ATTACK_INFOAREA;
#ifdef CEILING_FLOOR_COLORS
gamestate.flags |= GS_DRAW_CEILING|GS_DRAW_FLOOR|GS_LIGHTING;
#else
gamestate.flags |= GS_LIGHTING;
#endif
#if 0
PM_Shutdown();
PM_Startup ();
PM_UnlockMainMem ();
#endif
}
SD_SetMusicMode (sm);
SD_SetSoundMode (sd);
SD_SetDigiDevice (sds);
}
/*
========================
=
= Patch386
=
= Patch ldiv to use 32 bit instructions
=
========================
*/
void Patch386 (void)
{
extern void far jabhack2(void);
extern int far CheckIs386(void);
int i;
for (i = 1;i < _argc;i++)
switch (US_CheckParm(_argv[i],JHParmStrings))
{
case 0:
IsA386 = false;
return;
case 1:
IsA386 = true;
return;
}
if (CheckIs386())
{
IsA386 = true;
jabhack2();
}
else
IsA386 = false;
}
#pragma warn -rvl
#if 0
//------------------------------------------------------------------------
// CheckIs386()
//------------------------------------------------------------------------
int CheckIs386()
{
asm pushf // Save flag registers, we use them here
asm xor ax,ax // Clear AX and...
asm push ax // ...push it onto the stack
asm popf // Pop 0 into flag registers (all bits to 0),
asm pushf // attempting to set bits 12-15 of flags to 0's
asm pop ax // Recover the save flags
asm and ax,08000h // If bits 12-15 of flags are set to
asm cmp ax,08000h // zero then it's 8088/86 or 80188/186
asm jz not386
asm mov ax,07000h // Try to set flag bits 12-14 to 1's
asm push ax // Push the test value onto the stack
asm popf // Pop it into the flag register
asm pushf // Push it back onto the stack
asm pop ax // Pop it into AX for check
asm and ax,07000h // if bits 12-14 are cleared then
asm jz not386 // the chip is an 80286
asm mov ax,1 // We now assume it's a 80386 or better
asm popf
asm retf
not386:
asm xor ax,ax
asm popf
asm retf
}
#endif
#pragma warn +rvl
#define CHECK_FOR_EPISODES
extern CP_itemtype far NewEmenu[];
extern int EpisodeSelect[];
//-------------------------------------------------------------------------
// CheckForEpisodes() - CHECK FOR VERSION/EXTESION
//-------------------------------------------------------------------------
void CheckForEpisodes(void)
{
struct ffblk f;
short i;
#if (GAME_VERSION != SHAREWARE_VERSION)
if (!findfirst("*.VSI",&f,FA_ARCH))
strcpy(extension,"VSI");
#else
if (!findfirst("*.FSW",&f,FA_ARCH))
strcpy(extension,"FSW");
#endif
else
{
printf("No Fire Strike data files found!");
exit(0);
}
for (i=0;i<mv_NUM_MOVIES;i++)
strcat(Movies[i].FName,extension);
#ifdef ACTIVATE_TERMINAL
strcat(term_com_name,extension);
strcat(term_msg_name,extension);
#endif
strcat(configname,extension);
_fstrcat(SaveName,extension);
strcat(PageFileName,extension);
strcat(audioname,extension);
strcat(demoname,extension);
#if DUAL_SWAP_FILES
strcat(AltPageFileName,extension);
ShadowsAvail = (!findfirst(AltPageFileName,&f,FA_ARCH));
#endif
}
#if 0
//
// ORGINAL used in Aliens of Gold
//
//-------------------------------------------------------------------------
// CheckForEpisodes() - CHECK FOR EPISODES
//-------------------------------------------------------------------------
void CheckForEpisodes(void)
{
struct ffblk f;
short i;
#if (GAME_VERSION != SHAREWARE_VERSION)
#ifdef CHECK_FOR_EPISODES
if (!findfirst("*.BS6",&f,FA_ARCH))
#else
if (!findfirst("*.BS1",&f,FA_ARCH))
#endif
{
#ifdef CHECK_FOR_EPISODES
strcpy(extension,"BS6");
#else
strcpy(extension,"BS1");
#endif
NewEmenu[1].active =
NewEmenu[2].active =
NewEmenu[3].active =
NewEmenu[4].active =
NewEmenu[5].active =
EpisodeSelect[1] =
EpisodeSelect[2] =
EpisodeSelect[3] =
EpisodeSelect[4] =
EpisodeSelect[5] = AT_ENABLED;
}
else
#ifdef CHECK_FOR_EPISODES
if (!findfirst("*.BS3",&f,FA_ARCH))
#else
if (!findfirst("*.BS1",&f,FA_ARCH))
#endif
{
#ifdef CHECK_FOR_EPISODES
strcpy(extension,"BS3");
#else
strcpy(extension,"BS1");
#endif
NewEmenu[1].active =
NewEmenu[2].active =
EpisodeSelect[1] =
EpisodeSelect[2] = AT_ENABLED;
}
else
#endif
if (!findfirst("*.BS1",&f,FA_ARCH))
{
strcpy(extension,"BS1");
}
else
{
printf("No Blake Stone data files found!");
exit(0);
}
#if BETA_TEST
// This enables specific missions for beta testers.
//
NewEmenu[1].active =
EpisodeSelect[1] =
NewEmenu[2].active =
EpisodeSelect[2] =
NewEmenu[3].active =
EpisodeSelect[3] =
NewEmenu[4].active =
EpisodeSelect[4] =
NewEmenu[5].active =
EpisodeSelect[5] = AT_ENABLED;
#endif
for (i=0;i<mv_NUM_MOVIES;i++)
strcat(Movies[i].FName,extension);
#ifdef ACTIVATE_TERMINAL
strcat(term_com_name,extension);
strcat(term_msg_name,extension);
#endif
strcat(configname,extension);
_fstrcat(SaveName,extension);
strcat(PageFileName,extension);
strcat(audioname,extension);
strcat(demoname,extension);
#if DUAL_SWAP_FILES
strcat(AltPageFileName,extension);
ShadowsAvail = (!findfirst(AltPageFileName,&f,FA_ARCH));
#endif
}
#endif
extern char far * far MainStrs[];
extern char far bc_buffer[];
//------------------------------------------------------------------------
// PreDemo()
//------------------------------------------------------------------------
void PreDemo()
{
int i;
#if TECH_SUPPORT_VERSION
fontnumber=4;
SETFONTCOLOR(0,15*3);
CenterWindow (26,7);
US_Print(EnterBetaCode);
VW_UpdateScreen();
CA_LoadAllSounds();
PM_CheckMainMem();
SD_PlaySound(INFORMDEATH2SND); // Nooooo!
IN_UserInput(TickBase*20);
ClearMemory();
#elif BETA_TEST
boolean param=false;
for (i=1; i<_argc; i++)
switch (US_CheckParm(_argv[i],MainStrs))
{
case 13:
param=true;
break;
}
if (!param)
{
char buffer[15] = {0};
fontnumber=4;
CenterWindow (26,7);
US_Print(EnterBetaCode);
VW_UpdateScreen();
SETFONTCOLOR(0,15*3);
US_LineInput(24*8,92,buffer,buffer,true,14,100);
if (_fstricmp(buffer,bc_buffer))
Quit("Bad beta code!");
}
#endif
#if GAME_VERSION == SHAREWARE_VERSION
#if IN_DEVELOPMENT || GEORGE_CHEAT
if (!MS_CheckParm("nochex"))
#endif
{
#if (!SKIP_CHECKSUMS)
// CheckValidity("MAPTEMP.",MAPTEMP_CHECKSUM,"LEVELS");
CheckValidity("MAPTEMP.",MAPTEMP_CHECKSUM);
#endif
}
#else
#if (!SKIP_CHECKSUMS)
if (ChecksumFile("FILE_ID.DIZ",0) != DIZFILE_CHECKSUM)
gamestate.flags |= GS_BAD_DIZ_FILE;
#endif
#endif
VL_SetPaletteIntensity(0,255,&vgapal,0);
if (!(gamestate.flags & GS_NOWAIT))
{
#if (0) // GAME_VERSION != SHAREWARE_VERSION
//---------------------
// Anti-piracy screen
//---------------------
// Cache pic
//
CA_CacheScreen(PIRACYPIC);
// Cache and set palette. AND Fade it in!
//
CA_CacheGrChunk(PIRACYPALETTE);
VL_SetPalette (0,256,grsegs[PIRACYPALETTE]);
VL_SetPaletteIntensity(0,255,grsegs[PIRACYPALETTE],0);
VW_UpdateScreen();
VL_FadeOut (0, 255, 0, 0, 25, 20);
VL_FadeIn(0,255,grsegs[PIRACYPALETTE],30);
// Wait a little
//
IN_UserInput(TickBase*20);
// Free palette
//
UNCACHEGRCHUNK(PIRACYPALETTE);
VL_FadeOut (0, 255, 0, 0, 25, 20);
VW_FadeOut();
// Cleanup screen for upcoming SetPalette call
//
{
unsigned old_bufferofs=bufferofs;
bufferofs=displayofs;
VL_Bar(0,0,320,200,0);
bufferofs=old_bufferofs;
}
#endif
//---------------------
// Apogee presents
//---------------------
// Cache pic
//
CA_CacheScreen(APOGEEPIC);
// Load and start music
//
CA_CacheAudioChunk(STARTMUSIC+APOGFNFM_MUS);
SD_StartMusic((MusicGroup far *)audiosegs[STARTMUSIC+APOGFNFM_MUS]);
// Cache and set palette. AND Fade it in!
//
CA_CacheGrChunk(APOGEEPALETTE);
VL_SetPalette (0,256,grsegs[APOGEEPALETTE]);
VL_SetPaletteIntensity(0,255,grsegs[APOGEEPALETTE],0);
VW_UpdateScreen();
VL_FadeOut (0, 255, 25, 29, 53, 20);
VL_FadeIn(0,255,grsegs[APOGEEPALETTE],30);
// Wait for end of fanfare
//
if (MusicMode==smm_AdLib)
{
IN_StartAck();
while ((!sqPlayedOnce) && (!IN_CheckAck()));
}
else
IN_UserInput(TickBase*6);
SD_MusicOff();
// Free palette and music. AND Restore palette
//
UNCACHEGRCHUNK(APOGEEPALETTE);
MM_FreePtr((memptr *)&audiosegs[STARTMUSIC+APOGFNFM_MUS]);
// Do A Blue Flash!
VL_FadeOut (0, 255, 25, 29, 53, 20);
VL_FadeOut (0, 255, 0, 0, 0, 30);
//---------------------
// JAM logo intro
//---------------------
// Load and start music
//
CA_CacheAudioChunk(STARTMUSIC+TITLE_LOOP_MUSIC);
SD_StartMusic((MusicGroup far *)audiosegs[STARTMUSIC+TITLE_LOOP_MUSIC]);
// Show JAM logo
//
if (!DoMovie(mv_intro,0))
MAIN_ERROR(PREDEMO_NOJAM);
if (PowerBall)
{
int i;
for (i=0;i<60 && (!DebugOk);i++)
{
VL_WaitVBL(1);
if (Keyboard[sc_LShift] && Keyboard[sc_RShift])
{
CA_LoadAllSounds();
PM_CheckMainMem();
SD_MusicOff();
SD_PlaySound(SHOOTDOORSND);
SD_WaitSoundDone();
ClearMemory();
DebugOk = 1;
CA_CacheAudioChunk(STARTMUSIC+TITLE_LOOP_MUSIC);
SD_StartMusic((MusicGroup far *)audiosegs[STARTMUSIC+TITLE_LOOP_MUSIC]);
}
}
}
//---------------------
// PC-13
//---------------------
VL_Bar(0,0,320,200,0x14);
VW_MarkUpdateBlock(0,0,319,199);
CacheDrawPic(0,64,PC13PIC);
VW_UpdateScreen();
VW_FadeIn();
IN_UserInput(TickBase*2);
// Do A Red Flash!
VL_FadeOut (0, 255, 39, 0, 0, 20);
VW_FadeOut();
}
}
//------------------------------------------------------------------------
// InitGame()
//------------------------------------------------------------------------
void InitGame (void)
{
int i,x,y;
unsigned *blockstart;
//long mmsize;
MM_Startup (); // so the signon screen can be freed
#if IN_DEVELOPMENT || GEORGE_CHEAT || SHOW_CHECKSUM
if (MS_CheckParm("checksum"))
{
ShowChecksums();
MM_Shutdown();
exit(0);
}
#endif
CA_Startup ();
// Any problems with this version of the game?
//
#if IN_DEVELOPMENT || TECH_SUPPORT_VERSION
if (!MS_CheckParm("nochex"))
#endif
#if !SKIP_CHECKSUMS
CheckValidity("MAPTEMP.",MAPTEMP_CHECKSUM);
#if GAME_VERSION != SHAREWARE_VERSION
if (ChecksumFile("FILE_ID.DIZ",0) != DIZFILE_CHECKSUM)
gamestate.flags |= GS_BAD_DIZ_FILE;
#endif
#endif
VL_SetVGAPlaneMode ();
VL_SetPalette (0,256,&vgapal);
VW_Startup ();
IN_Startup ();
PM_Startup ();
PM_UnlockMainMem ();
SD_Startup ();
US_Startup ();
if (CheckForSpecialCode(POWERBALLTEXT))
#if IN_DEVELOPMENT
DebugOk = true;
#else
PowerBall = true;
#endif
if (CheckForSpecialCode(TICSTEXT))
gamestate.flags |= GS_TICS_FOR_SCORE;
if (CheckForSpecialCode(MUSICTEXT))
gamestate.flags |= GS_MUSIC_TEST;
if (CheckForSpecialCode(RADARTEXT))
gamestate.flags |= GS_SHOW_OVERHEAD;
//mmsize = mminfo.mainmem;
#if (!IN_DEVELOPMENT)
if (mminfo.mainmem < MIN_MEM_NEEDED)
{
memptr screen;
CA_CacheGrChunk (ERRORSCREEN);
screen = grsegs[ERRORSCREEN];
ShutdownId();
movedata ((unsigned)screen,7+7*160,0xb800,0,17*160);
gotoxy (1,23);
exit(0);
}
#endif
#if IN_DEVELOPMENT
//
// Clear Monocrome
//
_fmemset(MK_FP(0xb000,0x0000),0,4000);
#endif
//
// build some tables
//
InitDigiMap ();
for (i=0;i<MAPSIZE;i++)
{
nearmapylookup[i] = &tilemap[0][0]+MAPSIZE*i;
farmapylookup[i] = i*64;
}
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;
updateptr = &update[0];
bufferofs = 0;
displayofs = 0;
ReadConfig ();
//
// draw intro screen stuff
//
// if (!(gamestate.flags & GS_QUICKRUN))
// IntroScreen ();
//
// load in and lock down some basic chunks
//
LoadFonts();
LoadLatchMem ();
BuildTables (); // trig tables
SetupWalls ();
NewViewSize (viewsize);
//
// initialize variables
//
InitRedShifts ();
}
//-------------------------------------------------------------------------
// ShowSystem()
//-------------------------------------------------------------------------
void ShowSystem()
{
char avail[2][8]={"None","Present"};
MM_Startup ();
CA_Startup ();
IN_Startup ();
PM_Startup ();
SD_Startup ();
fprint(show_text1);
fprint(show_text2);
fprint(show_text3);
printf(" MAIN: %ld",mminfo.nearheap+mminfo.farheap);
if (mminfo.nearheap+mminfo.farheap < MIN_MEM_NEEDED)
fprint(show_text4);
printf("\n");
printf(" EMS: %ld\n",4l*EMSPagesAvail*1024l);
printf(" XMS: %ld\n\n",4l*XMSPagesAvail*1024l);
fprint(show_text5);
printf(" Mouse: %s\n",avail[MousePresent]);
printf(" Joystick: %s\n",avail[JoysPresent[0]||JoysPresent[1]]);
printf(" AdLib: %s\n",avail[AdLibPresent&&!SoundBlasterPresent]);
printf("Sound Blaster: %s\n",avail[SoundBlasterPresent]);
printf(" Sound Source: %s\n\n",avail[SoundSourcePresent]);
fprint(show_text2);
SD_Shutdown ();
PM_Shutdown ();
IN_Shutdown ();
CA_Shutdown ();
MM_Shutdown ();
}
//-------------------------------------------------------------------------
// scan_atoi()
//-------------------------------------------------------------------------
unsigned scan_atoi(char *s)
{
while (*s && (!isdigit(*s))) // First scans for a digit...
s++;
return(atoi(s)); // Then converts to integer...
}
extern char far * far MainStrs[];
extern short starting_episode,starting_level,starting_difficulty;
//-------------------------------------------------------------------------
// freed_main()
//-------------------------------------------------------------------------
void freed_main()
{
int i;
struct dosdate_t d;
// Setup for APOGEECD thingie.
//
InitDestPath();
// Make sure there's room to play the game
//
CheckDiskSpace(DISK_SPACE_NEEDED,CANT_PLAY_TXT,cds_dos_print);
// Which version is this? (SHAREWARE? 1-3? 1-6?)
//
CheckForEpisodes();
Patch386();
for (i=1; i<_argc; i++)
switch (US_CheckParm(_argv[i],MainStrs))
{
#if IN_DEVELOPMENT || TECH_SUPPORT_VERSION
case 0: // quick run
gamestate.flags |= GS_QUICKRUN;
case 1: // no wait
gamestate.flags |= GS_NOWAIT;
break;
#endif
case 2: // starting level
gamestate.flags |= GS_STARTLEVEL;
starting_level=scan_atoi(_argv[i]);
break;
case 3:
gamestate.flags |= GS_STARTLEVEL;
starting_episode=scan_atoi(_argv[i])-1;
break;
case 4:
fprint(cinfo_text);
printf("\n"
" Version: %s\n"
"COMPILE DATE: %s\n\n",
__VERSION__,__DATE__);
exit(0);
break;
case 5:
ShowSystem();
exit(0);
break;
#if IN_DEVELOPMENT
#ifdef DEBUG_VALUE
case 6:
debug_value=scan_atoi(_argv[i]);
break;
#endif
#endif
case 7:
gamestate.flags |= GS_TICS_FOR_SCORE;
break;
case 8:
// gamestate.flags |= GS_MEM_FOR_SCORE;
break;
case 9:
PowerBall = 1;
break;
case 11:
gamestate.flags |= GS_STARTLEVEL;
starting_difficulty=scan_atoi(_argv[i])-1;
break;
case 10:
gamestate.flags |= GS_MUSIC_TEST;
break;
case 12:
gamestate.flags |= GS_SHOW_OVERHEAD;
break;
}
#if BETA_TEST
//
// THIS IS FOR BETA ONLY!
//
_dos_getdate(&d);
if ((d.year > BETA_YEAR) ||
((d.year == BETA_YEAR) && (d.month > BETA_MONTH)) ||
((d.year == BETA_YEAR) && (d.month == BETA_MONTH) && (d.day >= BETA_DAY)))
{
FILE *out;
char name[20]="VSWAP.";
strcat(name,extension);
out = fopen(name,"w");
fprintf(out,"\n\n SELF DESTRUCTED \n");
fclose(out);
remove("vswap.bs1");
fprint(dver_text);
exit(0);
}
#endif
InitGame ();
if (!IsA386)
Quit(NULL);
bufferofs=SCREENSIZE;
PreDemo();
}
//-------------------------------------------------------------------------
// CheckValidity()
//-------------------------------------------------------------------------
void CheckValidity(char *file, long valid_checksum)
{
char filename[13];
long checksum;
if (strlen(file) > 9)
MAIN_ERROR(CHECK_FILENAME_TOO_LONG);
strcpy(filename,file);
strcat(filename,extension);
checksum=ChecksumFile(filename,0);
if (checksum != valid_checksum)
#if GAME_VERSION != SHAREWARE_VERSION
if (strstr(file,"MAP"))
InvalidLevels();
#else
BadChecksum();
#endif
}
#define CFC_BUFFERSIZE 65535
memptr cfc_buffer;
//-------------------------------------------------------------------------
// ChecksumFile()
//-------------------------------------------------------------------------
long ChecksumFile(char *file, long checksum)
{
#define JUMPSIZE 8
int handle;
long size,readlen,i;
char far *p;
MM_GetPtr(&cfc_buffer,CFC_BUFFERSIZE);
p=cfc_buffer;
if ((handle=open(file,O_RDONLY|O_BINARY)) == -1)
{
checksum=0;
goto exit_func;
}
size=filelength(handle);
while (size)
{
if (size >= CFC_BUFFERSIZE)
readlen = CFC_BUFFERSIZE;
else
readlen = size;
IO_FarRead(handle,cfc_buffer,readlen);
for (i=0;i<readlen-JUMPSIZE;i += JUMPSIZE)
checksum += p[i]^p[i+1];
size -= readlen;
}
close(handle);
exit_func:;
MM_FreePtr(&cfc_buffer);
return(checksum);
}
#if IN_DEVELOPMENT || GEORGE_CHEAT || SHOW_CHECKSUM
//-------------------------------------------------------------------------
// ShowChecksums()
//-------------------------------------------------------------------------
void ShowChecksums()
{
#if GAME_VERSION == SHAREWARE_VERSION
char mapname[23]="SWMAPS\\MAPTEMP.";
#elif GAME_VERSION == MISSIONS_1_THR_3
char mapname[23]="1_3MAPS\\MAPTEMP.";
#else
char mapname[13]="MAPTEMP.";
#endif
char gfxname[13]="VGAGRAPH.";
char audioname[13]="AUDIOT.";
char dizname[]="FILE_ID.DIZ";
strcat(gfxname,extension);
strcat(mapname,extension);
strcat(audioname,extension);
printf("\n");
printf("%s: %lx\n",audioname,ChecksumFile(audioname,0));
printf("%s: %lx\n",mapname,ChecksumFile(mapname,0));
printf("%s: %lx\n",gfxname,ChecksumFile(gfxname,0));
printf("%s: %lx\n",dizname,ChecksumFile(dizname,0));
printf("\n");
}
#endif
#if GAME_VERSION != SHAREWARE_VERSION
//-------------------------------------------------------------------------
// InvalidLevels()
//-------------------------------------------------------------------------
void InvalidLevels()
{
char far *chunkptr;
CA_CacheGrChunk(BADLEVELSTEXT);
chunkptr = grsegs[BADLEVELSTEXT];
*(_fstrstr(chunkptr,"^XX"))=0;
fprint(chunkptr);
while (!bioskey(1));
bioskey(0);
UNCACHEGRCHUNK(BADLEVELSTEXT);
}
#endif
#if GAME_VERSION == SHAREWARE_VERSION
//-------------------------------------------------------------------------
// BadChecksum()
//-------------------------------------------------------------------------
void BadChecksum()
{
char far *chunkptr;
CA_CacheGrChunk(BADCHECKSUMTEXT);
chunkptr = grsegs[BADCHECKSUMTEXT];
*(_fstrstr(chunkptr,"^XX")) = 0;
CA_Shutdown();
MM_Shutdown();
fprint(chunkptr);
exit(0);
}
#endif
#if FREE_FUNCTIONS
// This function is used as a label for the end of the
// functions used by the memory manager.
//
void JM_FREE_END()
{
}
#endif