/*		   ACK-3D ( Animation Construction Kit 3D )		      */
/* Reading files      */
/* Author: Lary Myers */

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys/stat.h>
#include "ack3d.h"
#include "ackext.h"

/****************************************************************************
**									   **
****************************************************************************/
int LoadBitmap(int BitmapNumber,char *BitmapName,int BitmapType)
{
int   handle,bFlag;
int   x,y;
int   sPos,dPos;
unsigned char ch;
unsigned char *buf;
unsigned char *bmp;

	bFlag = 0;

	if (!(strcasecmp(GetExtent(BitmapName),"BBM"))) {
    		buf = Readiff(BitmapName);
    		if (buf == NULL)
			return(-1);

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

	bmp = malloc(BITMAP_SIZE);
	if (bmp == NULL) {
    		ErrorCode = ERR_NOMEMORY;
    		free(buf);
    		return(-1);
    	}

	if (BitmapType == TYPE_WALL)
    		bMaps[BitmapNumber] = bmp;

	if (BitmapType == TYPE_OBJECT)
    		oMaps[BitmapNumber] = bmp;

	if (!bFlag) {
    		handle = open(BitmapName,O_RDWR);
    		if (handle < 1) {
			free(buf);
			free(bmp);
			WrapUp();
			perror(BitmapName);
			ErrorCode = ERR_BADFILE;
			exit(1);
		}

    		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;
		}
    	}

	free(buf);
	return(0);
}

/****************************************************************************
**									   **
****************************************************************************/
int LoadPalette(char *PalName)
{
    int	    handle;
    char    *buf;

buf = malloc(800);
if (buf == NULL)
    return(-1);

handle = open(PalName,O_RDWR);
if (handle > 0)
    {
    read(handle,buf,768);
    close(handle);
    SetPalette(buf);
    }

free(buf);
return(0);
}

/****************************************************************************
**									   **
****************************************************************************/
int ReadMasterFile(char *fname)
{
    FILE    *fp;
    int	    bType,bNum,result;
    int	    value,ObjIndex;
    int	    Mode = 0;
    int	    fMode = 0;
    char    *s;
    char    bName[128];
    char    fBuf[80];

fp = fopen(fname,"r");
if (fp == NULL)
    {
    printf("Master file %s not found.\n");
    ErrorCode = ERR_BADFILE;
    return(-1);
    }

bNum = 1;
bType = TYPE_WALL;
result = 0;

while (!result)
    {
    if (feof(fp))
	break;

    *bName = '\0';
    fgets(bName,127,fp);

    if (*bName == ';')
	continue;

    StripEndOfLine(bName);
    SkipSpaces(bName);

    if (!strlen(bName))
	continue;

    if (!strcasecmp(bName,"WALLS:"))
	{
	bType = TYPE_WALL;
	bNum = 1;
	Mode = 1;
	continue;
	}

    if (!strcasecmp(bName,"ENDWALLS:"))
	{
	if (Mode != 1)
	    {
	    printf("Invalid place for command: %s.\n",bName);
	    ErrorCode = ERR_BADCOMMAND;
	    result = -1;
	    }

	Mode = 0;
	continue;
	}

    if (!strcasecmp(bName,"OBJECTS:"))
	{
	bType = TYPE_OBJECT;
	bNum = 40;
	ObjIndex = 1;
	Mode = 2;
	continue;
	}

    if (!strcasecmp(bName,"FILES:"))
	{
	fMode = 1;
	continue;
	}

    if (!strcasecmp(bName,"ENDFILES:"))
	{
	fMode = 0;
	continue;
	}

    if (fMode)
	{
	value = atoi(bName);
	if (value < 1 || value > 255)
	    {
	    printf("Invalid number for object: %s.\n",bName);
	    ErrorCode = ERR_BADOBJNUMBER;
	    result = -1;
	    continue;
	    }

	s = strpbrk(bName,", \t");
	if (s == NULL)
	    {
	    printf("Unable to locate bitmap name for object: %s.\n",bName);
	    ErrorCode = ERR_BADSYNTAX;
	    result = -1;
	    continue;
	    }

	strcpy(fBuf,SkipSpaces(s));
	AddExtent(fBuf,".img");

	if (LoadBitmap(value,fBuf,bType))
	    {
	    printf("Error loading bitmap \"%s\".\n",fBuf);

	#if 0
	    ErrorCode = ERR_LOADINGBITMAP;
	#endif
	    result = -1;
	    }
	continue;
	}



    if (Mode == 2)
	{
	if (!strncasecmp(bName,"NUMBER:",7))
	    {
	    value = atoi(&bName[7]);

	    if (value < 1 || value >= MAX_OBJECTS)
		{
		printf("Invalid object number:\n%s\n",bName);
		ErrorCode = ERR_BADOBJNUMBER;
		result = -1;
		break;
		}
	    ObjIndex = value;
	    if (value >= MaxObjects)
		MaxObjects = value + 1;
	    continue;
	    }

	if (!strncasecmp(bName,"DIRECTION:",10))
	    {
	    value = atoi(&bName[10]);
	    if (value < 0 || value > 10)
		{
		printf("Invalid direction: %d.\n",value);
		ErrorCode = ERR_BADDIRECTION;
		result = -1;
		continue;
		}

	    ObjList[ObjIndex].Dir = value;
	    if (value == 10)
		ObjList[ObjIndex].Sides = 0;

	    continue;
	    }

	if (!strncasecmp(bName,"SPEED:",6))
	    {
	    ObjList[ObjIndex].Speed = atoi(&bName[6]);
	    continue;
	    }

	if (!strncasecmp(bName,"BITMAPS:",8))
	    {
	    strcpy(bName,SkipSpaces(&bName[8]));
	    value = 0;
	    while (value < MAX_VIEWS && *bName)
		{
		strcpy(bName,CopyToComma(fBuf,bName));
		SkipSpaces(fBuf);
		bNum = atoi(fBuf);

		if (bNum < 1 || bNum > 255)
		    {
		    printf("Invalid bitmap number for object: %d\n",ObjIndex);
		    ErrorCode = ERR_BADOBJNUMBER;
		    result = -1;
		    break;
		    }

		ObjList[ObjIndex].bmNum[value] = bNum;
		value++;
		}

	    ObjList[ObjIndex].MaxNum = value - 1;
	    ObjList[ObjIndex].Sides = 0;
	    if (value > 1 && ObjList[ObjIndex].Dir != 10)
		ObjList[ObjIndex].Sides = INT_ANGLE_360 / value;
	    continue;
	    }

	if (!strncasecmp(bName,"ENDOBJECTS:",11))
	    {
	    Mode = 0;
	    continue;
	    }

	}

    if (!strncasecmp(bName,"PALFILE:",8))
	{
	strcpy(PalFile,SkipSpaces(&bName[8]));
	continue;
	}

    if (!strncasecmp(bName,"MAPFILE:",8))
	{
	strcpy(GridFile,SkipSpaces(&bName[8]));
	continue;
	}

    if (!strncasecmp(bName,"GOALSCREEN:",11))
	{
	strcpy(GoalFile,SkipSpaces(&bName[11]));
	continue;
	}

    if (!strncasecmp(bName,"GOALPAL:",8))
	{
	strcpy(GoalPalFile,SkipSpaces(&bName[8]));
	continue;
	}

    if (!strncasecmp(bName,"SKYCOLOR:",9))
	{
	SkyColor = atoi(&bName[9]);
	continue;
	}

    if (!strncasecmp(bName,"FLOORCOLOR:",11))
	{
	FloorColor = atoi(&bName[11]);
	continue;
	}

    if (!strncasecmp(bName,"FLASHCOLOR:",11))
	{
	FlashColor = atoi(&bName[11]);
	continue;
	}

    if (!strncasecmp(bName,"DOORSPEED:",10))
	{
	DoorSpeed = atoi(&bName[10]);
	continue;
	}

    if (!strncasecmp(bName,"NONSECRETCODE:",14))
	{
	NonSecretCode = atoi(&bName[14]);
	continue;
	}


    if (!strncasecmp(bName,"STARTX:",7))
	{
	StartX = atoi(&bName[7]);
	if (StartX < 0 || StartX > GRID_XMAX)
	    {
	    printf("Invalid start X coordinate: %d\n",StartX);
	    ErrorCode = ERR_BADSTARTX;
	    result = -1;
	    break;
	    }

	continue;
	}

    if (!strncasecmp(bName,"STARTY:",7))
	{
	StartY = atoi(&bName[7]);
	if (StartY < 0 || StartY > GRID_YMAX)
	    {
	    printf("Invalid start Y coordinate: %d\n",StartX);
	    ErrorCode = ERR_BADSTARTY;
	    result = -1;
	    break;
	    }

	continue;
	}

    if (!strncasecmp(bName,"STARTANGLE:",11))
	{
	StartAngle = atoi(&bName[11]);
	if (StartAngle < 0 || StartAngle > INT_ANGLE_360)
	    {
	    printf("Invalid start angle: %d\n",StartAngle);
	    ErrorCode = ERR_BADANGLE;
	    result = -1;
	    break;
	    }
	continue;
	}

    }

fclose(fp);
return(result);
}

/****************************************************************************
**									   **
****************************************************************************/
int ReadMapFile(void)
{
    int	    len,handle;


handle = open(GridFile,O_RDWR);
if (handle < 1)
    {
    printf("Error opening map file %s.\n",GridFile);
    ErrorCode = ERR_BADMAPFILE;
    return(-1);
    }

len = read(handle,Grid,GRID_MAX);
close(handle);

if (len != GRID_MAX)
    {
    printf("Error reading map file %s.\n",GridFile);
    ErrorCode = ERR_READINGMAP;
    return(-1);
    }

return(0);
}

/****************************************************************************
**									   **
****************************************************************************/
int ReadNewLevel(void)
{
    int	    i,result;
    unsigned char *bmp;
    char    fName[14];

for (i = 0; i < 255; i++)
    {
    if (bMaps[i] != NULL)
	free(bMaps[i]);

    if (oMaps[i] != NULL)
	free(oMaps[i]);

    bMaps[i] = NULL;
    oMaps[i] = NULL;
    }

MaxObjects = 0;
result	   = 0;
ErrorCode  = 0;

sprintf(fName,"ack3d.l%02d",CurrentLevel);

if (ReadMasterFile(fName))
    result = -1;

if (ReadMapFile())
    result = -2;

LoadPalette(PalFile);

BuildXYgrid();

if (result)
    {
    WrapUp();
    printf("A fatal error occurred reading level %d data, %s!\n",CurrentLevel,fName);
    printf("Error code = %d\n",ErrorCode);
    exit(1);
    }

return(0);
}

