ack3d/ack_lib/ACKINIT.C

533 lines
18 KiB
C++
Raw Normal View History

// This file contains the key initialization functions for the ACK-3D engine.
// The main function AckInitialize() must be called first before any of the
// other ACK-3D functions are called. The internal functions defined in this file
// perform all of the set up work of loading tables and resource files.
#include <stdio.h>
#include <string.h>
#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "ack3d.h"
#include "ackeng.h"
#include "ackext.h"
extern char AckKeyboardSetup;
extern char AckTimerSetup;
short *LowerTable[2048];
short tmpLowerValue[400];
short LowerLen[2048];
char rsName[128];
long FloorCosTable[VIEW_WIDTH+1];
short AckBuildTables(ACKENG *ae);
void AckBuildHeightTables(ACKENG *ae);
void AckBuildGrid(ACKENG *ae);
void SetupFloors(ACKENG *ae);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Internal function called by AckInitialize(). This function sets up the
// internal variables that are required to support the off-screen buffer
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void AckSetupWindow(ACKENG *ae)
{
// Access the center row of the viewport
ae->CenterRow = ae->WinStartY + ((ae->WinEndY - ae->WinStartY) / 2);
// Access a memory location for the center row
ae->CenterOffset = ae->CenterRow * BYTES_PER_ROW;
// Access the starting memory location of the viewport
ae->WinStartOffset = ae->WinStartY * BYTES_PER_ROW;
// Calculate the window length in double words
ae->WinLength = ((ae->WinEndY - ae->WinStartY)+1) * DWORDS_PER_ROW;
// Calculates the viewport window width and height
ae->WinWidth = (ae->WinEndX - ae->WinStartX) + 1;
ae->WinHeight = (ae->WinEndY - ae->WinStartY) + 1;
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Initializes the ACK interface structure and reads in the TRIG tables
// from either the stand alone file TRIG.DAT or from a resource file that
// was opened previous to this call.
// This function MUST be called before AckBuildView() and AckDisplayScreen()
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
short AckInitialize(ACKENG *ae)
{
short i,result = 0;
short j;
UCHAR topcolor;
AckKeyboardSetup = 0; // Indicates keyboard interrupt has not been set up
AckTimerSetup = 0; // Indicates timer has not been set up
// Check to see if viewport coordinates are set up properly
if (!ae->WinEndY || !ae->WinEndX ||
(ae->WinEndY - ae->WinStartY) < 10 || // Height is less than 10 pixels
(ae->WinEndX - ae->WinStartX) < 10) // Width is less than 10 pixels
{
return(ERR_BADWINDOWSIZE); // Return error code for invalid viewport
}
result = AckBuildTables(ae); // Read in TRIG.DAT and allocate tables
if (result)
return(result);
AckSetupWindow(ae); // Set up the internal coordinates for the viewport
SetupFloors(ae); // Set up the floors
AckBuildHeightTables(ae); // Build height and adjustment tables
topcolor = ae->TopColor;
BackDropRows = 100;
for (i = 0; i < 640; i++)
{
2019-11-03 13:05:01 -05:00
BackArray[i] = (UCHAR*)AckMalloc(BackDropRows+1);
if (BackArray[i] == NULL)
return(ERR_NOMEMORY);
memset(BackArray[i],topcolor,BackDropRows);
}
return(result);
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Opens a resource file for use by any ACK routine that requires a
// filename. Only one resource file can be opened at a time.
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
short AckOpenResource(char *fName)
{
ULONG hLen;
if (rsHandle) // Is a resource file currently opened?
close(rsHandle); // Close it before opening a new one
rsHandle = open(fName,O_RDONLY|O_BINARY); // Open new resource file
if (rsHandle < 1) // Check to see if file is opened properly
{
rsHandle = 0; // Reset file handle
return(ERR_BADFILE); // Return error code for faliure
}
hLen = MAX_RBA * sizeof(long); // Get size of file
if (rbaTable == NULL)
rbaTable = (ULONG *)AckMalloc(hLen); // Allocate buffer for file
if (rbaTable == NULL) // Was memory available?
{
close(rsHandle); // Close file
rsHandle = 0; // Reset file handle
return(ERR_NOMEMORY); // Return error code
}
// Read in the file and check for byte count error
if (read(rsHandle,(ULONG *)rbaTable,hLen) != hLen)
{
close(rsHandle); // Close file
rsHandle = 0; // Reset file handle
AckFree(rbaTable); // Free up buffer
return(ERR_BADFILE); // Return file error code
}
strcpy(rsName,fName); // Store resource filename
return(0);
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Closes a resource file if one is opened.
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void AckCloseResource(void)
{
if (rsHandle) // Check to make sure resource file is opened
close(rsHandle); // Close the resource
if (rbaTable != NULL) // Do we need to free the memory for the file buffer?
{
AckFree(rbaTable); // Free up the file buffer
rbaTable = NULL;
}
rsHandle = 0; // Reset the file handle
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Internal function used to pre-define height tables for the wall
// drawing code.
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void BuildWallDstTables(void)
{
short i,j,dst,row,HiValue;
long ldst,value,LowValue,len;
short *lp;
for (ldst = 10;ldst < 2048; ldst++)
{
HiValue = value = 0;
row = 0;
while (HiValue < 64 && row < 100)
{
HiValue = (value >> 8) & 0xFF;
tmpLowerValue[row] = HiValue;
row++;
value += ldst;
}
LowerLen[ldst] = row;
len = row * 2;
j = 1;
if (row == LowerLen[ldst-1])
{
j = 0;
lp = LowerTable[ldst-1];
for (i = 0; i < row; i++)
{
if (tmpLowerValue[i] != lp[i])
{
j = 1;
break;
}
}
}
if (j)
{
2019-11-03 13:05:01 -05:00
lp = (short*)AckMalloc(len);
if (lp == NULL)
{
return;
}
LowerTable[ldst] = lp;
for (i = 0; i < row; i++)
lp[i] = tmpLowerValue[i];
}
else
{
LowerTable[ldst] = LowerTable[ldst-1];
}
}
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Internal function called from AckInitialize() to read in the trig tables
// and allocate memory for the various buffers.
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
short AckBuildTables(ACKENG *ae)
{
short handle,len,ca,na;
int c,s,ang;
long fAng,tu,tv;
SLICE *sa,*saNext;
BuildWallDstTables(); // Create the distance tables
if (!rsHandle) // Check to make sure resource file is not opened
{
handle = open("trig.dat",O_RDONLY|O_BINARY); // Open trig data file
if (handle < 1)
return(ERR_BADFILE); // File can't be opened; return error code
}
else
{
handle = rsHandle; // Get handle for resource file
lseek(handle,rbaTable[0],SEEK_SET);
}
// Allocate memory for trig and coordinate tables
LongTanTable = (long *)AckMalloc(sizeof(long) * INT_ANGLE_360);
LongInvTanTable = (long *)AckMalloc(sizeof(long) * INT_ANGLE_360);
CosTable = (long *)AckMalloc(sizeof(long) * INT_ANGLE_360);
SinTable = (long *)AckMalloc(sizeof(long) * INT_ANGLE_360);
LongCosTable = (long *)AckMalloc(sizeof(long) * INT_ANGLE_360);
xNextTable = (long *)AckMalloc(sizeof(long) * INT_ANGLE_360);
yNextTable = (long *)AckMalloc(sizeof(long) * INT_ANGLE_360);
ViewCosTable = (long *)AckMalloc(sizeof(long) * VIEW_WIDTH);
// Allocate memory for map grid and object grid
Grid = (unsigned short *)AckMalloc((GRID_MAX * 2)+1);
ObjGrid = (unsigned short *)AckMalloc((GRID_MAX * 2)+1);
// Allocate memory for height adjustment table
AdjustTable = (long *)AckMalloc((MAX_DISTANCE+1) * sizeof(long));
// Allocate memory for screen buffers
ae->ScreenBuffer = (UCHAR *)AckMalloc(SCREEN_SIZE+640);
ae->BkgdBuffer = (UCHAR *)AckMalloc(SCREEN_SIZE+640);
if (LongTanTable == NULL || // Make sure memory is allocated for tables
LongInvTanTable == NULL ||
CosTable == NULL ||
SinTable == NULL ||
LongCosTable == NULL ||
xNextTable == NULL ||
yNextTable == NULL ||
Grid == NULL ||
ObjGrid == NULL ||
AdjustTable == NULL ||
ae->ScreenBuffer == NULL ||
ae->BkgdBuffer == NULL ||
ViewCosTable == NULL)
{
if (!rsHandle)
close(handle);
return(ERR_NOMEMORY); // Return memory allocation error code
}
len = sizeof(long) * INT_ANGLE_360; // Calculate size for each trig table
read(handle,SinTable,len); // Read in trig data and place in appropriate tables
read(handle,CosTable,len);
read(handle,LongTanTable,len);
read(handle,LongInvTanTable,len);
read(handle,InvCosTable,len);
read(handle,InvSinTable,len);
read(handle,LongCosTable,len);
if (!rsHandle)
close(handle); // Done reading, close trig.dat
ca = INT_ANGLE_32;
na = -1;
// Set up viewing tables for 32 to -32 angle sweep
for (len = 0; len < VIEW_WIDTH; len++)
{
ViewCosTable[len] = LongCosTable[ca];
FloorCosTable[len] = InvCosTable[ca] >> 6;
ca += na;
if (ca <= 0) // Index is less than 0 so switch
{
ca = -ca;
na = -na;
}
}
// Adjust tables for 90, 180, and 270 degree angles
LongTanTable[INT_ANGLE_90] = LongTanTable[INT_ANGLE_90+1];
LongInvTanTable[INT_ANGLE_90] = LongInvTanTable[INT_ANGLE_90+1];
LongTanTable[INT_ANGLE_180] = LongTanTable[INT_ANGLE_180+1];
LongInvTanTable[INT_ANGLE_180] = LongInvTanTable[INT_ANGLE_180+1];
LongTanTable[INT_ANGLE_270] = LongTanTable[INT_ANGLE_270+1];
LongInvTanTable[INT_ANGLE_270] = LongInvTanTable[INT_ANGLE_270+1];
for (len = 0; len < INT_ANGLE_360; len++)
{
yNextTable[len] = (long)BITMAP_WIDTH * LongTanTable[len]; // Calculate y intercept increments
xNextTable[len] = (long)BITMAP_WIDTH * LongInvTanTable[len]; // Calculate x intercept increments
InvCosTable[len] = InvCosTable[len] >> 4; // Scale inverse tables
InvSinTable[len] = InvSinTable[len] >> 6;
}
// Set up the array od slice structures to represent the full width of the view
// Each slice structure is initialized by setting its data fields to 0s
// Each slice in the array is also linked to a second slice to reference a slice that
// could be visually behind the current slice
for (len = 0; len < VIEW_WIDTH; len++)
{
sa = &Slice[len]; // Initialize array of slice structures
memset(sa,0,sizeof(SLICE)); // Set all data to 0
for (ca = 0; ca < 8; ca++)
{
2019-11-03 13:05:01 -05:00
saNext = (SLICE*)AckMalloc(sizeof(SLICE)); // Create a slice structure to link in
if (saNext == NULL)
return(ERR_NOMEMORY); // Check for memory allocation
memset(saNext,0,sizeof(SLICE)); // Initialize all data to 0
sa->Next = saNext; // Link in slice
saNext->Prev = sa;
sa = saNext;
}
}
return(0);
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Reads a map file and processes any multi-height walls.
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
short AckReadMapFile(ACKENG *ae,char *fName)
{
short len,handle,rdlen,count,i,pos;
int mLen,aLen;
UCHAR buf[MAX_MULTI+2];
UCHAR *mPtr;
if (!rsHandle) // Check to see if resource file is open already
{ // No resource file so open new one
handle = open(fName,O_RDONLY|O_BINARY); // Open the specified resource
if (handle < 1)
return(ERR_BADMAPFILE); // File was not opened; return error code
}
else
{
handle = rsHandle; // Get handle to open resource
lseek(handle,rbaTable[(ULONG)fName],SEEK_SET); // Access opened resource file
}
aLen = GRID_ARRAY * 2;
mLen = GRID_MAX * 2;
if (read(handle,Grid,mLen) != mLen) // Read in grid map data
{
if (!rsHandle)
close(handle);
return(ERR_READINGMAP); // Return file read error code
}
if (read(handle,ObjGrid,mLen) != mLen) // Read in object map data
{
if (!rsHandle)
close(handle);
return(ERR_READINGMAP);
}
if (read(handle,ae->xGrid,aLen) != aLen) // Read in x grid data
{
if (!rsHandle)
close(handle);
return(ERR_READINGMAP);
}
if (read(handle,ae->yGrid,aLen) != aLen) // Read in y grid data
{
if (!rsHandle)
close(handle);
return(ERR_READINGMAP);
}
if (read(handle,FloorMap,mLen) != mLen) // Read in floor map data
{
if (!rsHandle)
close(handle);
return(ERR_READINGMAP);
}
if (read(handle,CeilMap,mLen) != mLen) // Read in ceiling map data
{
if (!rsHandle)
close(handle);
return(ERR_READINGMAP);
}
read(handle,&count,2); // Check counter for multi-height walls
if (count)
{
for (i = 0; i < count;i++) // Read in multi-height wall data
{
read(handle,&pos,2); // Get grid position for this multi-height wall
mPtr = (UCHAR *)AckMalloc(MAX_MULTI+1); // Allocate memory for multi-height wall data
if (mPtr == NULL)
{
if (!rsHandle)
close(handle);
return(ERR_NOMEMORY);
}
ae->mxGrid[pos] = mPtr; // Store pointer to multi-height wall
ae->myGrid[pos] = mPtr;
ae->mxGrid[pos+1] = mPtr;
ae->myGrid[pos+GRID_WIDTH] = mPtr;
read(handle,buf,MAX_MULTI);
buf[MAX_MULTI] = '\0';
2019-11-03 13:05:01 -05:00
len = strlen((char*)buf);
if (len > MAX_MULTI) len = MAX_MULTI;
*mPtr = len;
if (len)
memmove(&mPtr[1],buf,len);
}
}
if (!rsHandle) // Close handle
close(handle);
AckBuildGrid(ae); // Build object lists
return(0);
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Internal function to create height and distance tables for objects. In
// the DistanceTable[] each entry represents the distance from the player
// to a wall. The value stored in the array is the hight of the wall at
// the corresponding distance. For example, DistanceTable[100] indicates
// that the distance to the wall is 100 units. The value stored at this
// location is 81--the pixel height f the wall.
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void AckBuildHeightTables(ACKENG *ae)
{
short i,x;
short result;
long height;
height = BITMAP_WIDTH * 128L; // Calculate distance to height conversion factor
DistanceTable[0] = MAX_HEIGHT; // First entry = max. height (960)
//************ 64 * 65536 ********
AdjustTable[0] = 4194304L / height;
for (i = 1; i < MAX_DISTANCE; i++) // Loop to calculate each entry for the arrays
{
DistanceTable[i] = height / i;
if (height - (DistanceTable[i] * i) > (i / 2))
DistanceTable[i]++; // Add 1 to height value
if (DistanceTable[i] < MIN_HEIGHT) // Adjust for min. height (8)
DistanceTable[i] = MIN_HEIGHT;
if (DistanceTable[i] > MAX_HEIGHT) // Adjust for maax. height (960)
DistanceTable[i] = MAX_HEIGHT;
AdjustTable[i] = 2097152L / DistanceTable[i]; // Calculate entry for
}
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Internal function called by AckReadMapFile() to process the objects
// in the map. Moveable vs stationary objects are processed here.
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void AckBuildGrid(ACKENG *ae)
{
short i,j,CurIndex,pos,x1,y1;
USHORT MapCode,MapHiCode;
// Initialize doors
for (i = 0; i < MAX_DOORS; i++)
{
ae->Door[i].ColOffset = 0;
ae->Door[i].mPos = ae->Door[i].mPos1 = -1;
}
ae->SysFlags |= SYS_NO_WALLS; // Assume no floating walls
CurIndex = 1;
TotalSpecial = 0;
TotalSecret = 0;
for (i = 0; i < GRID_HEIGHT; i++) // Loop until entire grid has been checked
{
for (j = 0; j < GRID_WIDTH; j++)
{
pos = (i * GRID_WIDTH) + j;
MapCode = ObjGrid[pos]; // Check object at current grid position
if (MapCode) // Is there an object here?
{
CurIndex = MapCode & 0xFF;
if (CurIndex < MAX_OBJECTS) // Get the index of the object into
{
if (ae->ObjList[CurIndex] == NULL) // No object allocated yet
{
// Allocate memory for object
ae->ObjList[CurIndex] = (NEWOBJECT *)AckMalloc(sizeof(NEWOBJECT));
if (ae->ObjList[CurIndex] != NULL)
memset(ae->ObjList[CurIndex],0,sizeof(NEWOBJECT));
}
// If memory has been allocated calculate coordinates for object
if (ae->ObjList[CurIndex] != NULL)
{
x1 = (j * BITMAP_WIDTH) + (BITMAP_WIDTH/2);
y1 = (i * BITMAP_WIDTH) + (BITMAP_WIDTH/2);
ae->ObjList[CurIndex]->x = x1; // Store x,y position
ae->ObjList[CurIndex]->y = y1;
ae->ObjList[CurIndex]->mPos = pos; // Store map position
ae->ObjList[CurIndex]->Active = 1; // Indicates object is active
}
}
}
}
}
}
// **** End of Source ****