
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <mem.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys\stat.h>
#include "ack3d.h"
#include "ackeng.h"
#include "ackext.h"

char *GetExtent(char *s);
UCHAR *AckReadiff(char *s);
UCHAR *AckReadPCX(char *s);
short BlankSlice(short,UCHAR *);

//ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
// Determines if the column of the bitmap contains all transparent colors
// or not. If so then it is marked to be skipped during the draw phase.
//ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
short BlankSlice(short col,UCHAR *bmp)
{
    short     i,pos;

pos = col * 64;
for (i = 0; i < 64; i++)
    {
    if (bmp[pos++])
	return(1);
    }

return(0);
}


//ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
// Loads a bitmap of different formats based on the setting of bmLoadType
// in the ACKENG interface structure. The bitmap loaded is placed into
// either the wall bitmap array or the object array based on the value
// of BitmapType passed to this function.
// BitmapName can be either a filename or an index into the currently
// open resource file.
//ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
short AckLoadBitmap(ACKENG *ae,short BitmapNumber,short BitmapType,char *BitmapName)
{
    short    handle,bFlag;
    short    x,y,bLen;
    short    sPos,dPos;
    UCHAR    ch;
    UCHAR    *buf;
    UCHAR    *bmp;
    UCHAR    *bmpFlags;

bFlag = 0;

bLen = BITMAP_SIZE + BITMAP_WIDTH;
buf = NULL;

if (rsHandle || !(stricmp(GetExtent(BitmapName),"BBM")))
    {
    if (ae->bmLoadType == BMLOAD_BBM)
	buf = AckReadiff(BitmapName);

    if (ae->bmLoadType == BMLOAD_GIF)
	buf = AckReadgif(BitmapName);

    if (ae->bmLoadType == BMLOAD_PCX)
	buf = AckReadPCX(BitmapName);

    if (buf == NULL)
	return(ERR_LOADINGBITMAP);

    x = (*(short *)buf);
    y = (*(short *)&buf[2]);
    if ((x*y) != BITMAP_SIZE)
	{
	AckFree(buf);
	return(ERR_INVALIDFORM);
	}

    memmove(buf,&buf[4],BITMAP_SIZE);
    bFlag = 1;
    }
else
    {
    buf = AckMalloc(BITMAP_SIZE);
    if (buf == NULL)
	return(ERR_NOMEMORY);
    }

bmp = AckMalloc(bLen);
if (bmp == NULL)
    {
    AckFree(buf);
    return(ERR_NOMEMORY);
    }

if (BitmapType == TYPE_WALL)
    {
    ae->bMaps[BitmapNumber] = bmp;
    }

if (BitmapType == TYPE_OBJECT)
    {
    ae->oMaps[BitmapNumber] = bmp;
    }

if (!bFlag)
    {
    handle = open(BitmapName,O_RDWR|O_BINARY);
    if (handle < 1)
	{
	AckFree(buf);
	AckFree(bmp);
	return(ERR_BADFILE);
	}

    read(handle,buf,4);		/* Skip width and height for now */
    read(handle,buf,BITMAP_SIZE);
    close(handle);
    }

for (y = 0; y < BITMAP_HEIGHT; y++)
    {
    sPos = y;
    dPos = y * BITMAP_WIDTH;
    for (x = 0; x < BITMAP_WIDTH; x++)
	{
	ch = buf[sPos];
	bmp[dPos++] = ch;
	sPos += BITMAP_WIDTH;
	}
    }


bmpFlags = &bmp[BITMAP_SIZE];
memset(bmpFlags,0,BITMAP_WIDTH);

for (x = 0; x < BITMAP_WIDTH; x++)
    {
    if (!BlankSlice(x,bmp))
	bmpFlags[x] = 1;

    }

AckFree(buf);
return(0);
}

//ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
// Returns a pointer to the file extent
//ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
char *GetExtent(char *s)
{
    char    *e;

e = strchr(s,'.');
if (e == NULL)
    return(s);
e++;

return(e);
}

//ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
// Calls AckLoadBitmap with the TYPE_WALL flag set so the bitmap is placed
// in the wall array.
//ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
short AckLoadWall(ACKENG *ae,short WallNumber,char *bmFileName)
{
return( AckLoadBitmap(ae,WallNumber,TYPE_WALL,bmFileName) );
}

//ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
// Calls AckLoadBitmap with the TYPE_OBJECT flag set so the bitmap is
// placed in the object array.
//ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
short AckLoadObject(ACKENG *ae,short BmpNumber,char *bmFileName)
{
return( AckLoadBitmap(ae,BmpNumber,TYPE_OBJECT,bmFileName) );
}

//ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
// Creates an object structure. This function MUST be called before the
// object data can be initialized in the NEWOBJECT structure.
//ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
short AckCreateObject(ACKENG *ae,short ObjNumber)
{

if (ae->ObjList[ObjNumber] == NULL)
    {
    ae->ObjList[ObjNumber] = (NEWOBJECT *)AckMalloc(sizeof(NEWOBJECT));

    if (ae->ObjList[ObjNumber] == NULL)
	return(ERR_NOMEMORY);

    memset(ae->ObjList[ObjNumber],0,sizeof(NEWOBJECT));
    }

if (ObjNumber >= ae->MaxObjects)
    ae->MaxObjects = ObjNumber + 1;

return(0);
}

//ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
// Sets an object up into one of the predefined phase types (CREATE,DESTROY,
// etc.). Moveable objects are placed into a special list that is used
// later in the drawing phase.
//ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
short AckSetObjectType(ACKENG *ae,short oNum,short oType)
{
    short   i,j,result = 0;
    OBJSEQ  *os;


switch (oType)
    {
    case NO_CREATE:
	os = &ae->ObjList[oNum]->Create;
	break;

    case NO_DESTROY:
	os = &ae->ObjList[oNum]->Destroy;
	break;

    case NO_WALK:
	os = &ae->ObjList[oNum]->Walk;
	break;

    case NO_ATTACK:
	os = &ae->ObjList[oNum]->Attack;
	break;

    case NO_INTERACT:
	os = &ae->ObjList[oNum]->Interact;
	break;

    default:
	result = ERR_BADOBJTYPE;
	break;
    }

if (!result)
    {
    ae->ObjList[oNum]->CurrentBitmaps = &os->bitmaps;
    ae->ObjList[oNum]->Flags = os->flags;
    ae->ObjList[oNum]->Sides = os->bmSides;
    ae->ObjList[oNum]->BitmapsPerView = os->bmBitmapsPerView;
    ae->ObjList[oNum]->CurrentBm = 0;
    ae->ObjList[oNum]->Maxbm = os->MaxBitmaps;
    ae->ObjList[oNum]->CurrentType = oType;
    ae->ObjList[oNum]->aFactor = os->AngleFactor;
    }

if (ae->ObjList[oNum]->Flags & OF_MOVEABLE)
    {
    j = 0;
    for (i = 0; i < MoveObjectCount; i++)
	{
	if (MoveObjectList[i] == oNum)
	    {
	    j = 1;
	    break;
	    }
	}

    if (!j)
	MoveObjectList[MoveObjectCount++] = oNum;

    i = (ae->ObjList[oNum]->y & 0xFFC0) + (ae->ObjList[oNum]->x >> 6);
    ObjGrid[i] = 0;
    }

return(result);
}

//ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
// Fills in the object structure with a communication structure passed
// by the application. This allows the application to setup the fields
// such as number of sides to an object, what bitmaps are displayed for
// each side, etc. The object structures are defined in ACK3D.H
//ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
short AckSetupObject(ACKENG *ae,short oNum,short oType,OBJSEQ *os)
{
    short   result = 0;

if (ae->ObjList[oNum] == NULL)
    return(ERR_BADOBJECTNUM);

if (os->flags & OF_MULTIVIEW)
    {
    os->AngleFactor = INT_ANGLE_360 / os->bmSides;
    }

switch (oType)
    {
    case NO_CREATE:
	memmove(&ae->ObjList[oNum]->Create,os,sizeof(OBJSEQ));
	break;

    case NO_DESTROY:
	memmove(&ae->ObjList[oNum]->Destroy,os,sizeof(OBJSEQ));
	break;

    case NO_WALK:
	memmove(&ae->ObjList[oNum]->Walk,os,sizeof(OBJSEQ));
	break;

    case NO_ATTACK:
	memmove(&ae->ObjList[oNum]->Attack,os,sizeof(OBJSEQ));
	break;

    case NO_INTERACT:
	memmove(&ae->ObjList[oNum]->Interact,os,sizeof(OBJSEQ));
	break;

    default:
	result = ERR_BADOBJTYPE;
	break;
    }

if (!result && ae->ObjList[oNum]->CurrentBitmaps == NULL)
    result = AckSetObjectType(ae,oNum,oType);

return(result);
}


