ack3d/fdemo/FDEMO.C
2019-11-03 13:05:01 -05:00

2186 lines
44 KiB
C

// Example using Watcom FLAT model Animation Construction Kit
// Started: 01/02/94
// Author: Lary Myers
// Module: FDEMO.C
// (c) CopyRight 1994 All Rights Reserved
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <mem.h>
#include <string.h>
#include <ctype.h>
#include <dos.h>
#include <time.h>
#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>
#include "ack3d.h"
#include "ackeng.h"
#include "ackext.h"
#include "kit.h"
#include "modplay.h"
#define DEMO_RESOURCE 69
#define HAND1_RESOURCE 135
#define HAND2_RESOURCE 136
#define KEYBD 0x9 /* INTERRUPT 9 */
#define RIGHT_ARROW_KEY 77
#define UP_ARROW_KEY 72
#define LEFT_ARROW_KEY 75
#define DOWN_ARROW_KEY 80
#define MINUS_KEY 74
#define PLUS_KEY 78
#define NUMBER_5_KEY 76
#define ESCAPE_KEY 1
#define PGUP_KEY 73
#define PGDN_KEY 81
#define B_KEY 48
#define C_KEY 46
#define F_KEY 33
#define I_KEY 23
#define R_KEY 19
#define S_KEY 31
#define W_KEY 17
#define NUM_1_KEY 2
#define NUM_2_KEY 3
#define NUM_3_KEY 4
#define NUM_4_KEY 5
#define NUM_5_KEY 6
#define NUM_6_KEY 7
#define NUM_7_KEY 8
#define NUM_8_KEY 9
#define NUM_9_KEY 10
typedef struct {
int mdx;
int mdy;
int mButtons;
} MOUSE;
#define MAX_AMOUNT 64
#define MAX_MAG_AMOUNT 64
#define MAX_STR_AMOUNT 128
#define MAX_STR_HALF_AMOUNT 64
extern long mFactor;
extern long dFactor;
extern UCHAR colordat[];
ACKENG *ae;
// These are the ranges used for distance shading. Will need to be modified
// for the new color palette used.
ColorRange ranges[64] = {
16,15,
32,16,
48,16,
64,16,
80,16,
96,8,
104,8,
112,8,
120,8,
128,8,
136,8,
144,8,
152,8,
160,8,
168,8,
176,8,
184,16,
200,16,
216,16,
232,16,
248,16,
0,0
};
int HaveMouse;
short FlashIndex;
short FlashCount;
UCHAR *bmFlash[2];
UCHAR *bmFlash1[2];
char LineBuffer[200];
char *smFont;
UCHAR FontTransparent;
UCHAR FontColor;
UCHAR TextBGcolor;
int Throwing;
int Shooting;
int ShutDownFlag;
short MagAmount;
short StrAmount;
int ShowHitFlag;
int MapResource;
int PalResource;
int ResScreenBack;
int ResScrollBack;
void *BGmusic;
UCHAR *DemoPtr;
short Demoht;
short Demowt;
UCHAR *pHand1;
short Handw1;
short Handh1;
UCHAR *pHand2;
short Handw2;
short Handh2;
long ObjCounter[64];
short LastObjectIndex;
//-----------------------------------------------------------------------------
// Globals used by the frame counting routines
//-----------------------------------------------------------------------------
volatile short framespersec = 0;
volatile short cframes=0, count=0, ticks=0;
char *ErrorMsgs[] = {
"ERR_BADFILE ",
"ERR_BADCOMMAND ",
"ERR_BADOBJNUMBER ",
"ERR_BADSYNTAX ",
"ERR_LOADINGBITMAP",
"ERR_BADDIRECTION ",
"ERR_BADSTARTX ",
"ERR_BADSTARTY ",
"ERR_BADANGLE ",
"ERR_BADMAPFILE ",
"ERR_READINGMAP ",
"ERR_BADPICNAME ",
"ERR_INVALIDFORM ",
"ERR_NOPBM ",
"ERR_BADPICFILE ",
"ERR_NOMEMORY ",
"ERR_BADPALFILE ",
"ERR_BADWINDOWSIZE",
"ERR_TOMANYVIEWS ",
"ERR_BADOBJECTNUM ",
"ERR_BADOBJTYPE "
};
void ShowStatus(void);
//=============================================================================
//
//=============================================================================
/* MOD loading routines */
void *MODLoadModule(char *Path)
{
int handle;
unsigned modsize;
void *modfile = NULL;
if ((handle = open(Path,O_RDONLY | O_BINARY)) != -1) {
modsize = lseek(handle,0L,SEEK_END);
lseek(handle,0L,SEEK_SET);
if ((modfile=(void*)AckMalloc(modsize)) != NULL) {
if (read(handle,modfile,modsize) != modsize) {
AckFree(modfile);
modfile = NULL;
}
}
close(handle);
}
return modfile;
}
//=============================================================================
//
//=============================================================================
void MODFreeModule(void *Module)
{
if (Module) AckFree(Module);
}
//=============================================================================
//
//=============================================================================
short StartBGmusic(void)
{
if ((BGmusic = MODLoadModule("SAHARA.MOD")) == NULL)
return(-1);
if (MODPlayModule(BGmusic,5,22000,0x220,5,1))
return(-2);
return(0);
}
//=============================================================================
//
//=============================================================================
void EndBGmusic(void)
{
if (BGmusic == NULL)
return;
MODStopModule();
MODFreeModule(BGmusic);
}
//=============================================================================
//
//=============================================================================
short LoadSmallFont(void)
{
short ht,wt;
int len;
ht = 2;
smFont = (char*)AckReadiff((char*)ht);
if (smFont == NULL)
return(-1);
ht = (*(short *)smFont);
wt = (*(short *)&smFont[2]);
len = ht * wt;
memmove(smFont,&smFont[4],len);
return(0);
}
//=============================================================================
//
//=============================================================================
void smWriteChar(short x,short y,unsigned char ch)
{
int FontOffset,VidOffset;
int row,col;
UCHAR *Video;
VidOffset = (y * 320) + x;
Video = (UCHAR *)0xA0000;
Video += VidOffset;
FontOffset = ((ch-32) * 5);
if (FontTransparent)
Video = ae->ScreenBuffer + VidOffset;
for (row = 0; row < 5; row++)
{
if (!FontTransparent)
{
Video[0] = TextBGcolor;
Video[1] = TextBGcolor;
Video[2] = TextBGcolor;
Video[3] = TextBGcolor;
}
if (smFont[FontOffset])
Video[0] = FontColor;
if (smFont[FontOffset+1])
Video[1] = FontColor;
if (smFont[FontOffset+2])
Video[2] = FontColor;
if (smFont[FontOffset+3])
Video[3] = FontColor;
Video += 320;
FontOffset += 294;
}
}
//=============================================================================
//
//=============================================================================
short smWriteString(short x,short y,char *s)
{
short OrgX;
char ch;
OrgX = x;
while (*s)
{
ch = *s++;
if (ch == 10)
{
x = OrgX;
y += 8;
continue;
}
if (ch < ' ')
continue;
ch = toupper(ch);
smWriteChar(x,y,ch);
x += 5;
}
return(y);
}
//=============================================================================
//
//=============================================================================
void smWriteHUD(short x,short y,UCHAR color,char *s)
{
FontTransparent = 1;
FontColor = color;
smWriteString(x,y,s);
FontTransparent = 0;
FontColor = 15;
}
//=============================================================================
// Checks mouse movement and calculates delta movement in X and Y directions
//=============================================================================
void CheckMouse(MOUSE *m)
{
int dx,dy;
short x,y,buttons;
buttons = ReadMouseCursor(&y,&x);
dx = x - 160;
dy = y - 120;
m->mButtons = buttons;
SetMouseCursor(120,160);
if (abs(dy) > 10 && abs(dx) < 32)
dx >>= 2;
m->mdx = dx;
m->mdy = dy;
}
//=============================================================================
// Reads a text line from the resource file
//=============================================================================
int ReadLine(void)
{
int len;
char ch;
len = 0;
while (len < 200)
{
if (read(rsHandle,&LineBuffer[len],1) != 1)
break;
ch = LineBuffer[len];
if (ch == 10)
continue;
if (ch == 13)
break;
len++;
}
LineBuffer[len] = '\0';
return(len);
}
//=============================================================================
// Skips to the next parameter in a text line
//=============================================================================
char *GetNextParm(char *s)
{
char ch;
while (*s)
{
ch = *s++;
if (ch == ',')
{
while (*s)
{
ch = *s;
if (ch != ',' && ch != ' ' && ch != '\t')
return(s);
s++;
}
return(NULL);
}
}
return(NULL);
}
//=============================================================================
// Loads a wall bitmap specified in info file
//=============================================================================
int LoadWall(void)
{
int wnum,rnum,result;
long pos;
char *lb;
lb = LineBuffer; // Info file buffer
wnum = atoi(lb); // Wall number to load into
lb = GetNextParm(lb);
if (lb == NULL)
return(-1);
rnum = atoi(lb); // Resource number
pos = lseek(rsHandle,0L,SEEK_CUR);
result = AckLoadWall(ae,wnum,(char *)rnum);
lseek(rsHandle,pos,SEEK_SET);
return(result);
}
//=============================================================================
// Loads an object bitmap specified in info file
//=============================================================================
int LoadObject(void)
{
int onum,rnum,result;
long pos;
char *lb;
lb = LineBuffer;
onum = atoi(lb); // Object bitmap number
lb = GetNextParm(lb);
if (lb == NULL)
return(-2);
rnum = atoi(lb); // Resource number
pos = lseek(rsHandle,0L,SEEK_CUR);
result = AckLoadObject(ae,onum,(char *)rnum);
lseek(rsHandle,pos,SEEK_SET);
return(result);
}
//=============================================================================
// Skip any leading spaces in the string
// NOTE: Actually modifies the string passed!
//=============================================================================
char *SkipSpaces(char *s)
{
while (*s == ' ' || *s == '\t' || *s == ',')
strcpy(s,&s[1]);
return(s);
}
//=============================================================================
// Creates and object of the desired style
//=============================================================================
int CreateObject(void)
{
int onum,vnum,speed;
short result,oType;
short NumViews,bmPerView;
UINT flags;
char *lb;
OBJSEQ os;
lb = LineBuffer;
if (!strnicmp(lb,"NUMBER:",7))
{
lb = &lb[7];
onum = atoi(lb);
if (onum < 1 || onum > MAX_OBJECTS)
return(-3);
result = AckCreateObject(ae,onum);
if (result)
return(result);
LastObjectIndex = onum;
lb = GetNextParm(lb);
if (lb == NULL)
return(-4);
ae->ObjList[onum]->Speed = atoi(lb);
return(0);
}
onum = LastObjectIndex; // Object number
oType = 0;
if (!strnicmp(lb,"CREATE:",7))
{
oType = NO_CREATE;
lb = &lb[7];
}
if (!strnicmp(lb,"DESTROY:",8))
{
oType = NO_DESTROY;
lb = &lb[8];
}
if (!strnicmp(lb,"WALK:",5))
{
oType = NO_WALK;
lb = &lb[5];
}
if (!strnicmp(lb,"ATTACK:",7))
{
oType = NO_ATTACK;
lb = &lb[7];
}
if (!strnicmp(lb,"INTERACT:",9))
{
oType = NO_INTERACT;
lb = &lb[9];
}
if (!oType)
return(-5);
lb = SkipSpaces(lb);
if (lb == NULL)
return(-6);
flags = 0;
strupr(lb);
if (strstr(lb,"ANIMATE") != NULL)
flags |= OF_ANIMATE;
if (strstr(lb,"MOVEABLE") != NULL)
flags |= OF_MOVEABLE;
if (strstr(lb,"PASSABLE") != NULL)
flags |= OF_PASSABLE;
if (strstr(lb,"MULTIVIEW") != NULL)
flags |= OF_MULTIVIEW;
if (strstr(lb,"SHOWONCE") != NULL)
flags |= OF_ANIMONCE;
lb = GetNextParm(lb);
if (lb == NULL)
return(-5);
NumViews = atoi(lb);
if (NumViews < 1)
return(-6);
lb = GetNextParm(lb);
if (lb == NULL)
return(-7);
bmPerView = atoi(lb);
if (bmPerView < 1)
return(-7);
vnum = NumViews * bmPerView;
if (vnum > MAX_OBJ_BITMAPS)
return(-8);
lb = GetNextParm(lb);
if (lb == NULL)
return(-9);
vnum = 0;
while (lb != NULL && vnum < MAX_OBJ_BITMAPS)
{
os.bitmaps[vnum++] = atoi(lb);
lb = GetNextParm(lb);
}
os.bmBitmapsPerView = bmPerView;
os.flags = flags;
os.MaxBitmaps = bmPerView;
os.bmSides = NumViews;
result = AckSetupObject(ae,onum,oType,&os);
return(result);
}
//=============================================================================
// Reads the ASCII info file and processes the commands.
//=============================================================================
int ProcessInfoFile(short QuietFlag)
{
int result;
int mode;
long pos;
char *lb;
// Position to start of info file within resource file
lseek(rsHandle,rbaTable[0],SEEK_SET);
mode = result = 0;
while (!result)
{
if (!ReadLine())
continue;
if (*LineBuffer == ';')
continue;
if (!strnicmp(LineBuffer,"END:",4))
break;
if (!QuietFlag)
printf(".");
switch (mode)
{
case 1: // Read walls
if (!strnicmp(LineBuffer,"LOADTYPE:",9))
{
ae->bmLoadType = atoi(&LineBuffer[9]); // Sets for GIF or BBM
break;
}
if (!strnicmp(LineBuffer,"ENDBITMAPS:",11))
mode = 4;
else
result = LoadWall();
break;
case 2: // Object bitmaps
if (!strnicmp(LineBuffer,"LOADTYPE:",9)) // Sets for GIF or BBM
{
ae->bmLoadType = atoi(&LineBuffer[9]);
break;
}
if (!strnicmp(LineBuffer,"ENDBITMAPS:",11))
mode = 5;
else
result = LoadObject();
break;
case 3: // Create Object
if (!strnicmp(LineBuffer,"ENDDESC:",8))
mode = 5;
else
result = CreateObject();
break;
case 4: // Walls topic
if (!strnicmp(LineBuffer,"BITMAPS:",8))
mode = 1;
if (!strnicmp(LineBuffer,"ENDWALLS:",9))
mode = 0;
break;
case 5: // Objects topic
if (!strnicmp(LineBuffer,"BITMAPS:",8))
mode = 2;
if (!strnicmp(LineBuffer,"OBJDESC:",8))
mode = 3;
if (!strnicmp(LineBuffer,"ENDOBJECTS:",11))
mode = 0;
break;
default:
if (!strnicmp(LineBuffer,"WALLS:",6))
{
mode = 4;
break;
}
if (!strnicmp(LineBuffer,"OBJECTS:",8))
{
mode = 5;
break;
}
if (!strnicmp(LineBuffer,"MAPFILE:",8))
{
MapResource = atoi(&LineBuffer[8]);
pos = lseek(rsHandle,0L,SEEK_CUR);
result = AckReadMapFile(ae,(char *)MapResource);
lseek(rsHandle,pos,SEEK_SET);
break;
}
if (!strnicmp(LineBuffer,"PALFILE:",8))
{
PalResource = atoi(&LineBuffer[8]);
break;
}
if (!strnicmp(LineBuffer,"XPLAYER:",8))
{
ae->xPlayer = atoi(&LineBuffer[8]);
break;
}
if (!strnicmp(LineBuffer,"YPLAYER:",8))
{
ae->yPlayer = atoi(&LineBuffer[8]);
break;
}
if (!strnicmp(LineBuffer,"PLAYERANGLE:",12))
{
ae->PlayerAngle = atoi(&LineBuffer[12]);
break;
}
if (!strnicmp(LineBuffer,"SCREENBACK:",11))
{
ResScreenBack = atoi(&LineBuffer[11]);
break;
}
if (!strnicmp(LineBuffer,"SCROLLBACK:",11))
{
ResScrollBack = atoi(&LineBuffer[11]);
break;
}
if (!strnicmp(LineBuffer,"TOPCOLOR:",9))
{
ae->TopColor = atoi(&LineBuffer[9]);
break;
}
if (!strnicmp(LineBuffer,"BOTTOMCOLOR:",12))
{
ae->BottomColor = atoi(&LineBuffer[12]);
break;
}
if (!strnicmp(LineBuffer,"SHADING:",8))
{
strupr(LineBuffer);
if (strstr(&LineBuffer[8],"OFF") != NULL)
ae->LightFlag = SHADING_OFF;
else
ae->LightFlag = SHADING_ON;
break;
}
if (!strnicmp(LineBuffer,"FLOORS:",7))
{
strupr(LineBuffer);
if (strstr(&LineBuffer[7],"OFF") != NULL)
ae->SysFlags |= SYS_SOLID_FLOOR;
else
{
ae->SysFlags &= ~SYS_SOLID_FLOOR;
}
break;
}
if (!strnicmp(LineBuffer,"RESOLUTION:",11))
{
Resolution = atoi(&LineBuffer[11]);
break;
}
if (!strnicmp(LineBuffer,"LOADTYPE:",9))
{
ae->bmLoadType = atoi(&LineBuffer[9]); // Sets for GIF or BBM
break;
}
break;
}
}
if (!result)
{
result = AckCreateObject(ae,0); // Create a dummy object for later
if (!result)
ae->ObjList[0]->Active = 0; // Turn off checking the object
}
if (!QuietFlag)
printf("done\n");
return(result);
}
//=============================================================================
// Quick routine to display a bitmap into the desired buffer. Handles
// transparent colors. Currently used to display the ACK3D Demo bitmap.
//=============================================================================
void ShowBitmap(short x,short y,UCHAR *dst,short ht,short wt,UCHAR *bm)
{
int offset,col;
short endy;
UCHAR ch;
offset = (y*320) + x;
dst += offset;
endy = ae->WinEndY + 2;
while (ht-- > 0 && y++ <= endy)
{
for (col = 0; col < wt; col++)
{
ch = *bm++;
if (ch)
dst[col] = ch;
}
dst += 320;
}
}
//=============================================================================
//
//=============================================================================
void LoadDemoBitmap(void)
{
UCHAR *d;
DemoPtr = AckReadiff((char *)DEMO_RESOURCE);
if (DemoPtr == NULL)
return;
d = DemoPtr;
Demowt = (*(short *)d);
d += 2;
Demoht = (*(short *)d);
pHand1 = AckReadiff((char *)HAND1_RESOURCE);
if (pHand1 == NULL)
return;
d = pHand1;
Handw1 = (*(short *)d);
d += 2;
Handh1 = (*(short *)d);
pHand2 = AckReadiff((char *)HAND2_RESOURCE);
if (pHand2 == NULL)
return;
d = pHand2;
Handw2 = (*(short *)d);
d += 2;
Handh2 = (*(short *)d);
}
//=============================================================================
//
//=============================================================================
short Initialize(short iFlag)
{
short i,bnum;
if (MouseInstalled() != -1)
{
printf("Mouse is required to run.\n");
return(1);
}
ae = (ACKENG*)AckMalloc(sizeof(ACKENG));
if (ae == NULL)
{
printf("Unable to get required memory.\n");
return(2);
}
memset(ae,0,sizeof(ACKENG));
ae->WinStartX = 20;
ae->WinEndX = 299;
ae->WinStartY = 0;
ae->WinEndY = 156;
// ae->WinStartX = 0;
// ae->WinEndX = 319;
// ae->WinStartY = 0;
// ae->WinEndY = 156;
ae->LightFlag = SHADING_OFF;
ae->xPlayer = 192;
ae->yPlayer = 640;
ae->PlayerAngle = 0;
ae->TopColor = 0;
ae->BottomColor = 24;
ae->DoorSpeed = 6;
ae->NonSecretCode = 1;
ae->SysFlags |= SYS_SOLID_BACK;
if (iFlag & 1)
{
ae->SysFlags |= SYS_SINGLE_BMP;
ae->FloorBitmap = 33;
ae->CeilBitmap = 45;
}
printf("Initializing.\n");
i = AckOpenResource("kit.ovl");
if (i)
{
printf("Unable to open resource KIT.OVL\n");
return(3);
}
i = LoadSmallFont();
if (i)
{
printf("Error loading font BBM.\n");
return(5);
}
i = AckInitialize(ae);
AckCloseResource();
if (i)
{
printf("Error initializing. Error code: %d\n",i);
return(3);
}
printf("Processing DTF file ");
i = AckOpenResource("pics.dtf");
if (i)
{
printf("Unable to open resource PICS.DTF\n");
return(3);
}
i = ProcessInfoFile(0);
if (i)
{
printf("Error reading INF file.\n");
if (i > 100 && i < 121)
printf("Last error was %s\n",ErrorMsgs[i-100]);
else
printf("Error code: %d\n",i);
printf("Line was: \"%s\"\n",LineBuffer);
return(4);
}
bmFlash[0] = ae->bMaps[4];
bmFlash[1] = ae->bMaps[8];
bmFlash1[0] = ae->bMaps[24];
bmFlash1[1] = ae->bMaps[2];
FlashIndex = 0;
LoadDemoBitmap();
return(0);
}
//=============================================================================
// Loads and displays the full screen picture and sets the palette to the one
// loaded with the picture.
//=============================================================================
short LoadAndShow(char *fName)
{
short i,j;
UINT pos,begpos;
UCHAR pMask;
UCHAR *buf,*bPtr;
UCHAR *Video;
buf = AckReadiff(fName);
if (buf == NULL)
return(-1);
Video = (UCHAR*)0xA0000;
memmove(Video,&buf[4],64000);
AckSetPalette(colordat);
AckFree(buf);
return(0);
}
//=============================================================================
// Loads a background image (mountains) and processes the image into the
// separate slices for use at display time. Currently a background image
// can be 640 columns wide. This number can be made dynamic if needbe and would
// need to be changed in the routine below and in the DrawBackground routine
// in the ACK engine.
//=============================================================================
int LoadBackDrop(void)
{
int result;
int i,j,pos;
UCHAR *bPtr;
UCHAR *aPtr;
result = 0;
if (ResScrollBack)
{
printf("Loading background image....\n");
bPtr = AckReadiff((char *)ResScrollBack);
printf("Processing background image.\n");
if (bPtr != NULL)
{
for (i = 0; i < 320; i++)
{
pos = i + 4;
aPtr = BackArray[i];
for (j = 0; j < 100; j++)
{
*aPtr++ = bPtr[pos];
pos += 320;
}
}
for (i = 320; i < 640; i++)
{
pos = (i - 320) + 32004;
aPtr = BackArray[i];
for (j = 0; j < 100; j++)
{
*aPtr++ = bPtr[pos];
pos += 320;
}
}
AckFree(bPtr);
}
else
{
printf("Unable to load background image.\n");
result = 8;
}
}
return(result);
}
//=============================================================================
//
//=============================================================================
void ShowHit(void)
{
int x,y,result,wNum;
int flag;
short oNum,mPos;
ae->ObjList[0]->x = ae->xPlayer;
ae->ObjList[0]->y = ae->yPlayer;
wNum = 32;
oNum = 0;
flag = 0;
while (wNum--)
{
result = AckMoveObjectPOV(0,ae->PlayerAngle,12);
if (result == POV_OBJECT)
{
flag = 1;
oNum = AckGetObjectHit();
break;
}
if (result == POV_XWALL)
{
flag = 2;
oNum = ae->xGrid[AckGetWallHit()];
if (oNum & (DOOR_TYPE_SLIDE+DOOR_TYPE_SPLIT))
flag = 4;
oNum &= 0xFF;
break;
}
if (result == POV_YWALL)
{
flag = 3;
oNum = ae->yGrid[AckGetWallHit()];
if (oNum & (DOOR_TYPE_SLIDE+DOOR_TYPE_SPLIT))
flag = 4;
oNum &= 0xFF;
break;
}
}
if (flag)
{
mPos = (ae->ObjList[0]->y & 0xFFC0) + (ae->ObjList[0]->x >> 6);
switch (flag)
{
case 1:
sprintf(LineBuffer,"Object %d hit\nat location %d",oNum,mPos);
break;
case 2:
sprintf(LineBuffer,"Xwall %d hit\nat location %d",oNum,mPos);
break;
case 3:
sprintf(LineBuffer,"Ywall %d hit\nat location %d",oNum,mPos);
break;
case 4:
sprintf(LineBuffer,"Door %d hit\nat location %d",oNum,mPos);
break;
default:
*LineBuffer = '\0';
break;
}
ShowHitFlag = 1;
}
}
//=============================================================================
//
//=============================================================================
void UpdateBlast(void)
{
short j;
if (ae->ObjList[99]->Flags & OF_ANIMDONE &&
ae->ObjList[99]->CurrentType != NO_WALK)
{
AckSetObjectType(ae,99,NO_WALK);
ae->ObjList[99]->Flags &= ~OF_ANIMDONE;
}
j = AckMoveObjectPOV(99,ae->ObjList[99]->Dir,ae->ObjList[99]->Speed);
if (j > 0 && j != POV_PLAYER)
{
if (j != POV_OBJECT)
{
ae->ObjList[99]->Active = 0;
Shooting = 0;
return;
}
j = AckGetObjectHit();
if (j > 4 && j < 13)
{
if (ae->ObjList[j]->CurrentType == NO_WALK)
{
AckSetObjectType(ae,j,NO_INTERACT);
ObjCounter[j] = AckTimerCounter + 18 + (rand() % 120);
}
}
if (j == 51)
ae->ObjList[j]->Active = 0;
ae->ObjList[99]->Active = 0;
Shooting = 0;
}
}
//=============================================================================
//
//=============================================================================
void CheckMonsters(void)
{
int i,tFlag,xp,yp;
int pMap,oMap,oRow,oCol;
int row,col,offset;
long dx,dy,dx2,dy2,dist;
short cType;
UCHAR oFlags;
xp = ae->xPlayer;
yp = ae->yPlayer;
pMap = (yp & 0xFFC0) + (xp >> 6);
i = 5;
//for (i = 5; i < 13; i++)
while (1)
{
if (ae->ObjList[i]->Active)
{
oFlags = ae->ObjList[i]->Flags;
cType = ae->ObjList[i]->CurrentType;
dx = xp - ae->ObjList[i]->x;
dy = yp - ae->ObjList[i]->y;
dx2 = dx * dx;
dy2 = dy * dy;
if ((dx2+dy2) < 128000)
{
ae->ObjList[i]->Dir = AckGetObjectAngle(dx,dy);
if (cType == NO_WALK)
{
ae->ObjList[i]->Flags |= OF_ANIMATE;
oFlags |= OF_ANIMATE;
}
if (cType == NO_CREATE && !(oFlags & OF_ANIMATE))
{
if (i < 50)
{
ae->ObjList[i]->Flags |= OF_ANIMATE;
oFlags |= OF_ANIMATE;
}
else
AckSetObjectType(ae,i,NO_WALK);
}
}
if (cType == NO_WALK && (oFlags & OF_ANIMATE))
{
tFlag = AckMoveObjectPOV(i,ae->ObjList[i]->Dir,8);
oRow = ae->ObjList[i]->Dir / INT_ANGLE_90;
switch (tFlag)
{
case POV_PLAYER:
StrAmount--;
if (StrAmount < 0) StrAmount = 0;
ShowStatus();
break;
case POV_NOTHING:
break;
case POV_SLIDEX:
if (oRow > 1) ae->ObjList[i]->Dir = INT_ANGLE_270;
else ae->ObjList[i]->Dir = INT_ANGLE_90;
break;
case POV_SLIDEY:
if (oRow > 0 && oRow < 3)
ae->ObjList[i]->Dir = INT_ANGLE_180;
else
ae->ObjList[i]->Dir = 0;
break;
case POV_OBJECT:
ae->ObjList[i]->Dir = rand() % INT_ANGLE_360;
break;
default:
if (i < 50)
ae->ObjList[i]->Flags &= ~OF_ANIMATE;
break;
}
}
}
i++;
if (i == 13) i = 51;
if (i == 52) break;
}
}
//=============================================================================
//
//=============================================================================
void ShowStatus(void)
{
UCHAR *Video;
int row,offset,rlen,glen;
offset = (163 * 320) + 34;
glen = MagAmount;
if (glen > MAX_MAG_AMOUNT) glen = MAX_MAG_AMOUNT;
rlen = MAX_MAG_AMOUNT - glen;
Video = (UCHAR *)0xA0000;
Video += offset;
for (row = 0; row < 11; row++)
{
if (glen)
memset(Video,105,glen);
if (rlen)
memset(&Video[glen],39,rlen);
Video += 320;
}
offset = (183 * 320) + 34;
glen = StrAmount >> 1;
if (glen > MAX_STR_HALF_AMOUNT) glen = MAX_STR_HALF_AMOUNT;
rlen = MAX_STR_HALF_AMOUNT - glen;
Video = (UCHAR *)0xA0000;
Video += offset;
for (row = 0; row < 11; row++)
{
if (glen)
memset(Video,105,glen);
if (rlen)
memset(&Video[glen],39,rlen);
Video += 320;
}
}
//=============================================================================
//
//=============================================================================
void DrawBmpBox(int x1,int y1,int x2,int y2,long d1,long d2)
{
long NumCols,DeltaDist;
long htStep,dst;
long ht1,ht2,bmht;
long offset,xpos,ypos,bmPos,yposLow;
long bmCol,bmColStep;
UCHAR *Video,*bmp,*VidOrg,*VidEnd;
UCHAR *vPtr;
dst = d1;
if (d1 > d2) dst = d2;
bmht = 64 * 256;
DeltaDist = labs(d2 - d1);
ht1 = bmht / dst;
NumCols = ht1;
if (DeltaDist)
NumCols = (ht1 * (64 - DeltaDist)) / 64;
if (NumCols < 1) NumCols = 1;
bmColStep = (64*65536) / NumCols;
htStep = (DeltaDist<<16) / NumCols;
if (d2 < d1) htStep = -htStep;
bmp = ae->bMaps[1];
VidOrg = Video = ae->ScreenBuffer;
VidEnd = VidOrg + 64000;
offset = (y1 * 320) + x1;
Video += offset;
bmCol = 0;
d2 = (d1<<16);
for (xpos = 0; xpos < NumCols; xpos++)
{
vPtr = Video;
ypos = 0x1FFF;
yposLow = 0x1F;
bmPos = (bmCol>>16) * 64;
d1 = (d2>>16);
while (yposLow > 0 && vPtr > VidOrg)
{
*vPtr = bmp[bmPos+yposLow];
vPtr -= 320;
ypos -= d1;
yposLow = ypos >> 8;
}
vPtr = Video + 320;
ypos = 0x2000;
yposLow = 0x20;
while (yposLow < 64 && vPtr < VidEnd)
{
*vPtr = bmp[bmPos+yposLow];
vPtr += 320;
ypos += d1;
yposLow = ypos >> 8;
}
d2 += htStep;
bmCol += bmColStep;
Video++;
}
}
//=============================================================================
//
//=============================================================================
void ClsBmpBox(int x1,int y1,int x2,int y2)
{
int offset,wt;
UCHAR *Video;
Video = (UCHAR *)0xA0000;
offset = (y1 * 320) + x1;
wt = (x2 - x1) + 1;
Video += offset;
while (y1++ <= y2)
{
memset(Video,0,wt);
Video += 320;
}
}
typedef struct {
int x1;
int y1;
int x2;
int y2;
int d1;
int d2;
} AWALL;
short near long_sqrt(long v);
//=============================================================================
//
//=============================================================================
void DoTest(void)
{
int done,cnt,Total;
int xp,yp,ColX;
long dx,dy;
UCHAR *Video;
AWALL aw[2];
short i,minAngle,maxAngle,objAngle;
AckRegisterStructure(ae);
memset(ae->xGrid,0,(GRID_ARRAY*2));
memset(ae->yGrid,0,(GRID_ARRAY*2));
memset(Grid,0,(GRID_ARRAY*2));
aw[0].x1 = 64;
aw[0].y1 = 128;
aw[0].x2 = 128;
aw[0].y2 = 128;
aw[1].x1 = 128;
aw[1].y1 = 128;
aw[1].x2 = 128;
aw[1].y2 = 64;
Total = 2;
Video = (UCHAR *)0xA0000;
done = 0;
xp = yp = 256;
while (!done)
{
memset(ae->ScreenBuffer,0,64000);
minAngle = ae->PlayerAngle - (INT_ANGLE_32 + 10);
if (minAngle < 0)
minAngle += INT_ANGLE_360;
maxAngle = ae->PlayerAngle + (INT_ANGLE_32 + 10);
if (maxAngle >= INT_ANGLE_360)
maxAngle -= INT_ANGLE_360;
xp = ae->xPlayer;
yp = ae->yPlayer;
for (cnt = 0; cnt < Total; cnt++)
{
dx = aw[cnt].x1 - xp;
dy = aw[cnt].y1 - yp;
aw[cnt].d1 = long_sqrt((dx*dx)+(dy*dy));
objAngle = AckGetObjectAngle(dx,dy);
dx = aw[cnt].x2 - xp;
dy = aw[cnt].y2 - yp;
aw[cnt].d2 = long_sqrt((dx*dx)+(dy*dy));
if (minAngle > maxAngle)
{
if (objAngle >= minAngle)
ColX = objAngle - minAngle;
else
ColX = (objAngle+INT_ANGLE_360) - minAngle;
}
else
{
ColX = objAngle - minAngle;
}
if (ColX > -40 && ColX < 320)
DrawBmpBox(ColX,100,aw[cnt].x2,100,aw[cnt].d1,aw[cnt].d2);
}
memmove(Video,ae->ScreenBuffer,64000);
if (AckKeys[ESCAPE_KEY])
break;
if (AckKeys[LEFT_ARROW_KEY])
{
ae->PlayerAngle--;
if (ae->PlayerAngle < 0)
ae->PlayerAngle += INT_ANGLE_360;
}
if (AckKeys[RIGHT_ARROW_KEY])
{
ae->PlayerAngle++;
if (ae->PlayerAngle >= INT_ANGLE_360)
ae->PlayerAngle -= INT_ANGLE_360;
}
if (AckKeys[UP_ARROW_KEY])
{
AckMovePOV(ae->PlayerAngle,16);
}
if (AckKeys[DOWN_ARROW_KEY])
{
i = ae->PlayerAngle + INT_ANGLE_180;
if (i >= INT_ANGLE_360)
i -= INT_ANGLE_360;
AckMovePOV(i,16);
}
}
}
//=============================================================================
//
//=============================================================================
short LoadNewLevel(char *LevelName)
{
short i;
i = AckOpenResource(LevelName);
if (i)
return(-1);
for (i = 1; i < MAX_WALLBMPS; i++)
{
if (ae->bMaps[i] != NULL)
{
AckFree(ae->bMaps[i]);
ae->bMaps[i] = NULL;
}
}
for (i = 1; i < MAX_OBJBMPS; i++)
{
if (ae->oMaps[i] != NULL)
{
AckFree(ae->oMaps[i]);
ae->oMaps[i] = NULL;
}
}
for (i = 1; i < ae->MaxObjects; i++)
{
if (ae->ObjList[i] != NULL)
{
AckFree(ae->ObjList[i]);
ae->ObjList[i] = NULL;
}
}
ae->MaxObjects = 0;
for (i = 0; i < (GRID_ARRAY - GRID_WIDTH); i++)
{
if (ae->myGrid[i] != NULL)
AckFree(ae->myGrid[i]);
ae->mxGrid[i] = NULL;
ae->mxGrid[i+1] = NULL;
ae->myGrid[i] = NULL;
ae->myGrid[i+GRID_WIDTH] = NULL;
}
i = ProcessInfoFile(1);
if (i)
return(i);
AckCloseResource();
AckRegisterStructure(ae);
return(0);
}
short LevelFlag;
//=============================================================================
//
//=============================================================================
short main(short argc,char **argv)
{
short i,j,done,fpos;
char ch;
MOUSE mouse;
UCHAR *Video;
int Spin,MoveAmount;
int SpinAngle,MoveAngle;
long TimerEnd;
short DemoFlag;
short lpx,lpy,lpa;
int StartTime,EndTime,InfoFlag;
int CkStart,CkEnd;
int TurnFactor,MoveFactor,MoveHalfFactor;
int HandX,HandY,HandDY;
long x1,y1;
i = 0;
if (argc > 1)
{
for (j = 1; j <= argc; j++)
{
if (!strnicmp(argv[j],"-1",2))
i |= 1;
}
}
if ((done = Initialize(i)) != 0)
return(done);
if ((done = LoadBackDrop()) != 0)
return(done);
// Do some test setup of our GooMonsters
AckSetObjectType(ae,6,NO_WALK);
ae->ObjList[5]->Flags &= ~OF_ANIMATE;
ae->ObjList[7]->Flags &= ~OF_ANIMATE;
ae->ObjList[8]->Flags &= ~OF_ANIMATE;
ae->ObjList[9]->Flags &= ~OF_ANIMATE;
ae->ObjList[10]->Flags &= ~OF_ANIMATE;
ae->ObjList[11]->Flags &= ~OF_ANIMATE;
ae->ObjList[12]->Flags &= ~OF_ANIMATE;
ae->ObjList[99]->Active = 0;
ae->ObjList[99]->Speed = 48;
Shooting = 0;
MagAmount = MAX_MAG_AMOUNT;
StrAmount = MAX_STR_AMOUNT;
// Setup keyboard and timer interrupts
AckSetupKeyboard();
AckSetupTimer();
AckTmDelay = 3;
AckSpeedUp(AckTmDelay); // Set the timer interrupt at 3 times normal
StartBGmusic();
// Switch to mode 13
AckSetVGAmode();
// Put up the main screen
LoadAndShow((char *)ResScreenBack);
//DoTest();
// Set palette for shading if needed
AckSetupPalRanges(ae,ranges);
ShowStatus();
LevelFlag = 0;
done = 0;
SpinAngle = Spin = MoveAmount = 0;
MouseReleased();
SetMouseCursor(120,160);
fpos = 64;
DemoFlag = 0;
if (DemoPtr != NULL) DemoFlag = 1;
TimerEnd = AckTimerCounter + 180;
// MUST register each ACKENG structure once before use and after AckInitialize
AckRegisterStructure(ae);
StartTime = AckTimerCounter;
AckBuildView();
AckDisplayScreen();
EndTime = AckTimerCounter - StartTime;
if (!EndTime) EndTime = 1;
TurnFactor = INT_ANGLE_1 * EndTime;
MoveFactor = 3 * EndTime;
MoveHalfFactor = MoveFactor >> 1;
StartTime = clock();
EndTime = StartTime;
InfoFlag = 0;
HandX = 134;
HandY = 132;
HandDY = -2;
Throwing = 0;
while (!done)
{
if (SpinAngle)
{
ae->PlayerAngle += SpinAngle;
if (ae->PlayerAngle >= INT_ANGLE_360)
ae->PlayerAngle -= INT_ANGLE_360;
if (ae->PlayerAngle < 0)
ae->PlayerAngle += INT_ANGLE_360;
SpinAngle >>= 3;
if (SpinAngle == -1) SpinAngle = 0;
}
if (MoveAmount)
{
HandY += HandDY;
if (HandY < 125) HandDY = 2;
if (HandY > 132) HandDY = -2;
j = AckMovePOV(MoveAngle,MoveAmount);
AckCheckDoorOpen(ae->xPlayer,ae->yPlayer,MoveAngle);
MoveAmount >>= 1;
if (j == POV_OBJECT)
{
j = AckGetObjectHit();
if (j > 4 && j < 13)
{
StrAmount--;
if (StrAmount < 0)
StrAmount = 0;
ShowStatus();
}
if (j >= 36 && j <= 49)
{
ae->ObjList[j]->Active = 0;
MagAmount += 4;
if (MagAmount > MAX_MAG_AMOUNT)
MagAmount = MAX_MAG_AMOUNT;
ShowStatus();
}
if (j == 50 && ae->ObjList[50]->CurrentType == NO_CREATE)
{
AckSetObjectType(ae,j,NO_WALK);
StrAmount = MAX_STR_AMOUNT;
ShowStatus();
}
}
}
else
{
if (HandY < 132)
HandY++;
}
AckCheckObjectMovement(); // Animate objects if needed
for (j = 5; j < 13; j++)
{
if (ae->ObjList[j]->Flags & OF_ANIMDONE &&
ae->ObjList[j]->CurrentType == NO_DESTROY)
{
AckSetObjectType(ae,j,NO_CREATE);
ae->ObjList[j]->Flags &= ~OF_ANIMDONE;
ae->ObjList[j]->Flags &= ~OF_ANIMATE;
ae->ObjList[j]->Active = 0;
}
if (ae->ObjList[j]->Flags & OF_ANIMDONE &&
ae->ObjList[j]->CurrentType != NO_WALK)
{
AckSetObjectType(ae,j,NO_WALK);
ae->ObjList[j]->Flags &= ~OF_ANIMDONE;
ObjCounter[j] = AckTimerCounter + 18 + (rand() % 120);
}
if (AckTimerCounter > ObjCounter[j])
{
ObjCounter[j] = AckTimerCounter + 180 + (rand() % 180);
if (ae->ObjList[j]->CurrentType == NO_WALK)
AckSetObjectType(ae,j,NO_ATTACK);
else
{
if (ae->ObjList[j]->CurrentType == NO_INTERACT)
AckSetObjectType(ae,j,NO_DESTROY);
}
}
}
if (Shooting)
UpdateBlast();
CheckMonsters();
CkStart = AckTimerCounter;
AckBuildView(); // Build floor, ceiling, and walls into ScrnBuffer
if (DemoFlag)
{
switch (DemoFlag)
{
case 1:
if (AckTimerCounter > TimerEnd)
{
DemoFlag++;
TimerEnd = AckTimerCounter + 540;
}
break;
case 2:
ShowBitmap(130,20,ae->ScreenBuffer,Demoht,Demowt,&DemoPtr[4]);
if (AckTimerCounter > TimerEnd)
{
DemoFlag = 1;
TimerEnd = AckTimerCounter + 2160;
}
break;
default:
break;
}
}
switch (Throwing)
{
case 0:
ShowBitmap(HandX,HandY,ae->ScreenBuffer,Handh1,Handw1,&pHand1[4]);
break;
case 1:
HandY -= 20;
if (HandY < 97)
{
HandY = 97;
Throwing++;
}
ShowBitmap(HandX,HandY,ae->ScreenBuffer,Handh1,Handw1,&pHand1[4]);
break;
case 2:
HandY -= 5;
Throwing++;
ShowBitmap(HandX,HandY,ae->ScreenBuffer,Handh2,Handw2,&pHand2[4]);
break;
case 3:
ae->ObjList[99]->Active = 1;
ae->ObjList[99]->x = ae->xPlayer;
ae->ObjList[99]->y = ae->yPlayer;
ae->ObjList[99]->Dir = ae->PlayerAngle;
ae->ObjList[99]->mPos = (ae->yPlayer & 0xFFC0) + ae->xPlayer >> 6;
AckSetObjectType(ae,99,NO_CREATE);
Shooting = 1;
MagAmount--;
ShowStatus();
Throwing++;
ShowBitmap(HandX,HandY,ae->ScreenBuffer,Handh2,Handw2,&pHand2[4]);
break;
case 4:
HandY += 5;
Throwing++;
ShowBitmap(HandX,HandY,ae->ScreenBuffer,Handh2,Handw2,&pHand2[4]);
break;
case 5:
HandY += 20;
if (HandY > 132)
Throwing = 0;
ShowBitmap(HandX,HandY,ae->ScreenBuffer,Handh1,Handw1,&pHand1[4]);
break;
default:
break;
}
if (InfoFlag)
{
EndTime = clock();
if (EndTime > StartTime+100 )
{
StartTime = EndTime;
cframes = framespersec;
framespersec = 0;
}
sprintf(LineBuffer,"FPS: %6ld,%d,%d,%d",
(long)cframes,ae->xPlayer,ae->yPlayer,ae->PlayerAngle);
smWriteHUD(10,20,32,LineBuffer);
framespersec++;
}
// sprintf(LineBuffer,"MEM: %ld",AckMemUsed);
// smWriteHUD(22,30,32,LineBuffer);
if (ShowHitFlag)
smWriteHUD(10,10,32,LineBuffer);
AckDisplayScreen(); // Copy ScrnBuffer to actual video
CkEnd = AckTimerCounter - CkStart;
if (!CkEnd) CkEnd = 1;
TurnFactor = INT_ANGLE_1 * CkEnd;
MoveFactor = 3 * CkEnd;
MoveHalfFactor = MoveFactor >> 1;
i = (ae->yPlayer & 0xFFC0) + (ae->xPlayer >> 6);
if (FloorMap[i] == 0x28)
{
StrAmount--;
if (StrAmount < 1)
break;
ShowStatus();
}
CheckMouse(&mouse);
if (mouse.mButtons & 1)
{
if (!(ae->ObjList[99]->Active) && MagAmount > 0 && !Throwing)
{
Throwing = 1;
#if 0
ae->ObjList[99]->Active = 1;
ae->ObjList[99]->x = ae->xPlayer;
ae->ObjList[99]->y = ae->yPlayer;
ae->ObjList[99]->Dir = ae->PlayerAngle;
ae->ObjList[99]->mPos = (ae->yPlayer & 0xFFC0) + ae->xPlayer >> 6;
AckSetObjectType(ae,99,NO_CREATE);
Shooting = 1;
MagAmount--;
ShowStatus();
#endif
}
}
if (mouse.mButtons & 2)
{
MoveAmount += MoveFactor; // 16;
if (MoveAmount > MAX_AMOUNT)
MoveAmount = MAX_AMOUNT;
MoveAngle = ae->PlayerAngle;
}
if (mouse.mdx < 0)
{
Spin = -mouse.mdx;
Spin >>= 5;
SpinAngle = -TurnFactor * Spin; // -INT_ANGLE_1 * Spin;
Spin = 1;
}
if (mouse.mdx > 0)
{
Spin = mouse.mdx;
Spin >>= 5;
SpinAngle = TurnFactor * Spin; // INT_ANGLE_1 * Spin;
Spin = 1;
}
if (mouse.mdy < 0)
{
i = -mouse.mdy;
i >>= 2;
i += MoveHalfFactor;
MoveAmount += i;
if (MoveAmount > MAX_AMOUNT)
MoveAmount = MAX_AMOUNT;
MoveAngle = ae->PlayerAngle;
}
if (mouse.mdy > 20)
{
i = mouse.mdy;
i >>= 3;
i += MoveHalfFactor;
j = ae->PlayerAngle + INT_ANGLE_180;
if (j >= INT_ANGLE_360)
j -= INT_ANGLE_360;
MoveAmount += i;
if (MoveAmount > MAX_AMOUNT)
MoveAmount = MAX_AMOUNT;
MoveAngle = j;
}
if (AckKeys[ESCAPE_KEY])
break;
if(AckKeys[RIGHT_ARROW_KEY])
{
Spin += 1;
SpinAngle += TurnFactor; // INT_ANGLE_1 * Spin;
}
if(AckKeys[LEFT_ARROW_KEY])
{
Spin += 1;
SpinAngle -= TurnFactor; // -INT_ANGLE_1 * Spin;
}
if(AckKeys[UP_ARROW_KEY])
{
MoveAmount += (MoveFactor + MoveHalfFactor); // 12;
if (MoveAmount > MAX_AMOUNT)
MoveAmount = MAX_AMOUNT;
MoveAngle = ae->PlayerAngle;
}
if(AckKeys[DOWN_ARROW_KEY])
{
j = ae->PlayerAngle + INT_ANGLE_180;
if (j >= INT_ANGLE_360)
j -= INT_ANGLE_360;
MoveAmount += (MoveFactor + MoveHalfFactor); // 12;
if (MoveAmount > MAX_AMOUNT)
MoveAmount = MAX_AMOUNT;
MoveAngle = j;
}
if (AckKeys[C_KEY])
{
ae->SysFlags ^= SYS_SOLID_CEIL;
ae->SysFlags &= ~SYS_SOLID_BACK;
AckKeys[C_KEY] = 0;
if ((ae->SysFlags & SYS_SOLID_CEIL) && (ResScrollBack != 0))
ae->SysFlags |= SYS_SOLID_BACK;
AckRegisterStructure(ae);
}
if (AckKeys[R_KEY])
{
AckKeys[R_KEY] = 0;
Resolution++;
if (Resolution > 2)
Resolution = 0;
}
if (AckKeys[F_KEY])
{
ae->SysFlags ^= SYS_SOLID_FLOOR;
AckKeys[F_KEY] = 0;
AckRegisterStructure(ae);
}
if (AckKeys[PGUP_KEY] && ViewHeight < 60)
{
ViewHeight++;
CeilingHeight++;
}
if (AckKeys[PGDN_KEY] && ViewHeight > 4)
{
ViewHeight--;
CeilingHeight--;
}
if (AckKeys[NUM_1_KEY])
{
AckKeys[NUM_1_KEY]=0;
dFactor--;
}
if (AckKeys[NUM_2_KEY])
{
AckKeys[NUM_2_KEY]=0;
dFactor++;
}
if (AckKeys[MINUS_KEY])
{
AckKeys[MINUS_KEY]=0;
mFactor--;
}
if (AckKeys[PLUS_KEY])
{
AckKeys[PLUS_KEY]=0;
mFactor++;
}
if (AckKeys[I_KEY])
{
AckKeys[I_KEY] = 0;
InfoFlag ^= 1;
}
if (AckKeys[B_KEY])
{
AckKeys[B_KEY]=0;
// mFactor -= 64;
if (!LevelFlag)
LoadNewLevel("MALL.DTF");
else
{
LoadNewLevel("PICS.DTF");
ae->ObjList[99]->Active = 0;
ae->ObjList[99]->Speed = 48;
}
LevelFlag ^= 1;
}
if (AckKeys[S_KEY])
{
AckKeys[S_KEY] = 0;
mFactor += 64;
}
}
EndBGmusic();
ShutDownFlag = 1;
AckSlowDown(); // Set the timer back to normal speed
AckWrapUp(ae);
AckSetTextMode();
return(0);
}