/******************* ( Animation Construction Kit 3D ) ***********************/
/*			  Load Bitmap Routines				     */
/* CopyRight (c) 1993	   Author: Lary Myers				     */
/*****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <mem.h>
#include <alloc.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"
#include "xmslib.h"

char *GetExtent(char *s);
UCHAR far *AckReadiff(char *s);

/****************************************************************************
** The application should call this routine to load a bitmap into either   **
** real or XMS memory.							   **
**									   **
** BitmapNumber is the index number to place the file into.		   **
** BitmapType is either TYPE_WALL or TYPE_OBJECT			   **
** BitmapName is the filename of the bitmap to load.			   **
**									   **
** Bitmaps used by the ACK engine are 64x64 in size and may be either raw  **
** image (.IMG) files or Deluxe Paint brushes (.BBM) files.		   **
**									   **
****************************************************************************/
int AckLoadBitmap(ACKENG *ae,int BitmapNumber,int BitmapType,char *BitmapName)
{
    int	    handle,bFlag;
    int	    x,y;
    int	    sPos,dPos;
    unsigned char ch;
    XMSHANDLE	  xPtr;
    UCHAR    far  *buf;
    UCHAR    far  *bmp;

bFlag = 0;

if (!(stricmp(GetExtent(BitmapName),"BBM")))
    {
    buf = AckReadiff(BitmapName);
    if (buf == NULL)
	return(ERR_LOADINGBITMAP);

    memmove(buf,&buf[4],BITMAP_SIZE);
    bFlag = 1;
    }
else
    {
    buf = malloc(BITMAP_SIZE);
    if (buf == NULL)
	return(ERR_NOMEMORY);
    }

bmp = malloc(BITMAP_SIZE);
if (bmp == NULL)
    {
    free(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)
	{
	free(buf);
	free(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;
	}
    }

#if USE_XMS
    if (UseXMS > 0)
	{
	xPtr = XMSalloc(BITMAP_SIZE);
	if (xPtr != XMSHNULL)
	    {
	    if (BitmapType == TYPE_WALL)
		ae->bMaps[BitmapNumber] = (UCHAR far *)xPtr;
	    else
		ae->oMaps[BitmapNumber] = (UCHAR far *)xPtr;

	    XMSput(xPtr,bmp,BITMAP_SIZE);
	    free(bmp);
	    }
	}
#endif

free(buf);
return(0);
}

/****************************************************************************
** Internal routine to get the file extent from a filename.		   **
**									   **
****************************************************************************/
char *GetExtent(char *s)
{
    char    *e;

e = strchr(s,'.');
if (e == NULL)
    return(s);
e++;

return(e);
}


/****************************************************************************
** Simplified call to load a wall bitmap.				   **
**									   **
****************************************************************************/
int AckLoadWall(ACKENG *ae,int WallNumber,char *bmFileName)
{

return( AckLoadBitmap(ae,WallNumber,TYPE_WALL,bmFileName) );
}


/****************************************************************************
** Simplified call to load an object bitmap.				   **
**									   **
****************************************************************************/
int AckLoadObject(ACKENG *ae,int BmpNumber,char *bmFileName)
{

return( AckLoadBitmap(ae,BmpNumber,TYPE_OBJECT,bmFileName) );
}


/****************************************************************************
** The application should make this call to perform the necessary setup on **
** an object.								   **
**									   **
** ObjNumber is the object index					   **
** NumBitmaps is the total number of bitmaps that the object has (min 1).  **
** bmNums is a char array of the bitmap numbers the object uses.	   **
**									   **
** If an object has more than 1 bitmap and the OF_ANIMATE flag is NOT set  **
** then it is assumed the object has more than one side and will be seen   **
** from various angles. If the OF_ANIMATE flag IS set then the object will **
** animate through the multiple bitmaps in the supplied list.		   **
**									   **
****************************************************************************/
int AckCreateObject(ACKENG *ae,int ObjNumber,int NumBitmaps,UCHAR *bmNums)
{
    int	    i;


if (NumBitmaps >= MAX_VIEWS)
    return(ERR_TOMANYVIEWS);

if (!NumBitmaps)    /* Force to at least one bitmap */
    NumBitmaps++;

/* Setup index to which bitmap is displayed */
ae->ObjList[ObjNumber].CurNum = 0;
ae->ObjList[ObjNumber].MaxNum = NumBitmaps - 1;

/* Keep the maximum number current */
if (ObjNumber >= ae->MaxObjects && ObjNumber < MAX_OBJECTS)
    ae->MaxObjects = ObjNumber + 1;

/* Calculate sides if a multi-sided object */
ae->ObjList[ObjNumber].Sides = 0;
if (NumBitmaps > 1 && !(ae->ObjList[ObjNumber].Flags & OF_ANIMATE))
    ae->ObjList[ObjNumber].Sides = INT_ANGLE_360 / NumBitmaps;

/* Transfer bitmap numbers to object structure */
for (i = 0; i < NumBitmaps; i++)
    ae->ObjList[ObjNumber].bmNum[i] = bmNums[i];


return(0);
}

