This is the source code to the CMappy plug-in - which was my last plug-in for DBPro.
Usual compiling rules apply - you'll also need the Mappy program installed.
/* The following ifdef block is the standard way of creating macros which make exporting
from a DLL simpler. All files within this DLL are compiled with the CMAPPY_EXPORTS
symbol defined on the command line. this symbol should not be defined on any project
that uses this DLL. This way any other project whose source files include this file see
CMAPPY_API functions as being imported from a DLL, whereas this DLL sees symbols
defined with this macro as being exported.
*/
#ifdef CMAPPY_EXPORTS
#define CMAPPY_API __declspec(dllexport)
#else
#define CMAPPY_API __declspec(dllimport)
#endif
#pragma once
#include "stdio.h"
#include "stdlib.h"
#include "mapdefs.h"
#define ERROR_INVALIDCOORD -1
#define ERROR_OK 0
#define ERROR_NOFILENAME -2
#define ERROR_FILENOTFOUND -3
#define ERROR_FILENOTOPENED -4
#define ERROR_INVALIDHEADER -5
#define ERROR_OUTOFMEM -6
#define ERROR_INVALIDLAYER -7
#define ERROR_UNKNOWNVERSION -8
#define ERROR_TILENOTFOUND -9
#define ERROR_LAYERNOTINUSE -10
#define ERROR_LAYERINUSE -11
#define ERROR_MAPNOTLOADED -12
#define FMP05 0
#define FMP10 1
#define FMP10RLE 2
#define MAX_LAYERS 8
#define FOREGROUND1 0
#define FOREGROUND2 1
#define FOREGROUND3 2
#define HEADER_AUTHOR "ATHR"
#define HEADER_MAP "MPHD"
#define HEADER_PALETTE "CMAP"
#define HEADER_BLOCKGRFX "BGFX"
#define HEADER_BODY "BODY"
#define HEADER_LAYER "LYR"
#define HEADER_ANIMATION "ANDT"
#define HEADER_BLOCKDATA "BKDT"
#define HEADER_EDITOR "EDHD"
#define HEADER_EPHD "EPHD"
#define MAPPY_HEADER1 "FORM"
#define MAPPY_HEADER2 "FMAP"
typedef struct __RGB {
char r;
char g;
char b;
} __RGB;
// This class is exported from the CMappy.dll
class CMappy {
public:
CMappy(void);
~CMappy();
void destroyMap(void);
int loadMappyFile(char *fileName,int extraBytes=0);
int m_dTileSizeInBytes;
int GetNumberOfLayers(void);
int GetMappyIndex(int x,int y);
signed short GetTileAtPosition(int x,int y,int layerLevel);
signed short WriteTileAtPosition(int x,int y,int layerLevel,signed short value);
int FindTile(int layerNum,int *xP,int *yP,int tile);
BLKSTR *GetBlockData(int block);
ANISTR *GetAnimationData(int index);
struct __RGB *GetPaletteColour(int index);
char *GetExtraDataPointer(int x,int y,int layer);
int CalculateExtraPosition(int x,int y);
int returnBackgroundOffset(int blockNum);
int returnForegroundOffset(int blockNum,short which);
int returnCurrentAnimationBlock(int block);
int addLayer(int layer);
int deleteLayer(int layer);
int copyLayer(int fromLayer,int toLayer);
int clearLayer(int layer);
int moveLayer(int fromLayer,int toLayer);
void UpdateAnimations(void);
// TODO: add your methods here.
char *m_cpAuthor,*m_cpGraphics;
int m_dMapType;
int m_dMapWidth,m_dMapHeight;
int m_dBlockWidth,m_dBlockHeight;
int m_dMapVersion,m_dLSB;
int m_dBlockDepth,m_dMapDepth;
int m_dNumBlockStructs,m_dNumBlockGFX;
int m_dBlockGapX,m_dBlockGapY;
int m_dBlockStaggerX,m_dBlockStaggerY;
int m_dClipMask;
int m_dMapTrans8,m_dMapTransRed,m_dMapTransGreen,m_dMapTransBlue;
int m_dNumAnimations;
int m_dExtraBytesSize;
private:
bool readHeader(FILE *handle,int *Mappy_FileSize);
int swapByteOrder(int Thislong);
int getMappySize(FILE *handle,char *store);
void MapInitAnims(void);
signed short loadMappyWord(FILE *handle,bool order);
void loadMappySkipSection(FILE *handle,int size);
int processMapHeader(FILE *handle,int size);
void processPalette(FILE *handle,int sectionLen);
int processGraphics(FILE *handle,int ChunkSize);
signed short getTileMapLayer(FILE *handle,int sectionLen,int layerLevel,int extraBytesSize);
int processAnimation(FILE *handle,int ChunkSize);
int processBlockData(FILE *handle,int ChunkSize);
int allocateLayer(int layerLevel,int ChunkSize,int extraBytes);
int returnDiv(void);
ANISTR *animations;
long *animationSeq;
struct __RGB rgb[256];
signed short *layer[MAX_LAYERS];
char *extraBytesLayer[MAX_LAYERS];
BLKSTR *blockStructs;
};
[code// CMappy.cpp : Defines the entry point for the DLL application.
//
#include "CMappy.hpp"
#include "stdlib.h"
#include "stdio.h"
#include "memory.h"
#include "fcntl.h"
#ifdef MACOS
#include "unistd.h"
#endif
CMappy::CMappy()
{
register int loop;
for (loop=0; loop<MAX_LAYERS; loop++)
{
layer[loop]=NULL;
extraBytesLayer[loop]=NULL;
}
m_dExtraBytesSize=0;
m_cpAuthor=NULL;
//SecureZeroMemory(&rgb,sizeof(rgb));
memset((char *) &rgb,(char) 0,sizeof(rgb));
m_dMapType=0;
m_dMapWidth=0; m_dMapHeight=0;
m_dBlockWidth=0; m_dBlockHeight=0;
m_dMapVersion=0; m_dLSB=0;
m_dBlockDepth=0;
m_dNumBlockStructs=0; m_dNumBlockGFX=0;
m_cpGraphics=NULL; m_dMapDepth=0;
m_dBlockGapX=0; m_dBlockGapY=0;
m_dBlockStaggerX=0; m_dBlockStaggerY=0;
m_dClipMask=0;
m_dMapTrans8=0;
m_dMapTransRed=0;
m_dMapTransGreen=0;
m_dMapTransBlue=0;
animations=NULL; animationSeq=NULL;
blockStructs=NULL;
}
CMappy::~CMappy()
{
destroyMap();
}
bool CMappy::readHeader(FILE *handle,int *Mappy_FileSize)
{
char buffer[4];
long size;
if (fread((char *) &buffer,1,sizeof(buffer),handle)==sizeof(buffer))
{
if (memcmp((char *) &buffer,MAPPY_HEADER1,sizeof(buffer))!=0) return (false);
// Read in the file size
if (fread((char *) &size,1,sizeof(size),handle)==sizeof(size))
{
// Swap the size around
*(Mappy_FileSize)=swapByteOrder(size);
// Now read the second header
if (fread((char *) &buffer,1,sizeof(buffer),handle)==sizeof(buffer))
{
if (memcmp((char *) &buffer,MAPPY_HEADER2,sizeof(buffer))!=0) return (false);
return (true);
}
}
}
return (false);
}
int CMappy::swapByteOrder(int Thislong)
{
int hWord,ThisLong;
hWord=((Thislong & 0xFFFF0000)/65536) & 65535;
ThisLong=((Thislong & 255)*16777216)+((Thislong & 65280)*256)+((hWord & 255)*256)+((hWord & 65280)/256);
return (ThisLong);
}
int CMappy::getMappySize(FILE *handle,char *store)
{
char header[4];
int value;
fread((char *) &header,1,sizeof(header),handle);
if (store)
{
memcpy(store,(char *) &header,sizeof(header));
}
fread((char *) &value,1,sizeof(value),handle);
return (swapByteOrder(value));
}
void CMappy::destroyMap(void)
{
register int loop;
if (m_cpAuthor)
{
free((void *) m_cpAuthor);
m_cpAuthor=NULL;
}
for (loop=0; loop<MAX_LAYERS; loop++)
{
if (layer[loop])
{
free(layer[loop]);
layer[loop]=NULL;
}
if (extraBytesLayer[loop])
{
free(extraBytesLayer[loop]);
extraBytesLayer[loop]=NULL;
}
}
m_dExtraBytesSize=0;
if (animations)
{
free(animations);
animations=NULL;
}
if (blockStructs)
{
free(blockStructs);
blockStructs=NULL;
}
if (animationSeq)
{
free(animationSeq);
animationSeq=NULL;
}
if (m_cpGraphics)
{
free(m_cpGraphics);
m_cpGraphics=NULL;
}
}
int CMappy::loadMappyFile(char *fileName,int extraBytes)
{
FILE *handle;
int FilePosition;
bool DecodeFlag;
char ChunkHeader[4];
int Mappy_FileSize,ChunkSize;
if ((fileName==NULL) || strlen(fileName)==0) return (ERROR_NOFILENAME);
if (access(fileName,00)==-1) return (ERROR_FILENOTFOUND);
m_dExtraBytesSize=extraBytes;
handle=fopen(fileName,"rb");
if (handle!=NULL)
{
if (readHeader(handle,&Mappy_FileSize)==false)
{
fflush(handle);
fclose(handle);
return (ERROR_INVALIDHEADER);
}
FilePosition=12;
do {
DecodeFlag=false;
ChunkSize=getMappySize(handle,(char *) &ChunkHeader);
FilePosition+=8;
if (memcmp(ChunkHeader,HEADER_AUTHOR,strlen(HEADER_AUTHOR))==0)
{
// Strings of author information
// Allocate memory for this chunk
if ((m_cpAuthor=(char *) calloc(1,ChunkSize+1))!=NULL)
{
fread((char *) m_cpAuthor,1,ChunkSize,handle);
}
else
{
fclose(handle);
return (ERROR_OUTOFMEM);
}
DecodeFlag=true;
}
else
if (memcmp(ChunkHeader,HEADER_MAP,strlen(HEADER_MAP))==0)
{
processMapHeader(handle,ChunkSize);
DecodeFlag=true;
}
else
if (memcmp(ChunkHeader,HEADER_PALETTE,strlen(HEADER_PALETTE))==0)
{
processPalette(handle,ChunkSize);
DecodeFlag=true;
}
else
if (memcmp(ChunkHeader,HEADER_BLOCKGRFX,strlen(HEADER_BLOCKGRFX))==0)
{
int status;
if ((status=processGraphics(handle,ChunkSize))!=ERROR_OK)
{
fclose(handle);
return (status);
}
DecodeFlag=true;
}
else
if (memcmp(ChunkHeader,HEADER_BODY,strlen(HEADER_BODY))==0)
{
int status;
if ((status=getTileMapLayer(handle,ChunkSize,0,m_dExtraBytesSize))!=ERROR_OK)
{
fclose(handle);
return (status);
}
DecodeFlag=true;
}
else
if (memcmp((char *) &ChunkHeader,HEADER_LAYER,strlen(HEADER_LAYER))==0)
{
int layer;
int status;
layer=ChunkHeader[strlen(HEADER_LAYER)]-(char) '0';
if (layer>=0 && layer<MAX_LAYERS)
{
if ((status=getTileMapLayer(handle,ChunkSize,layer,m_dExtraBytesSize))!=ERROR_OK)
{
fclose(handle);
return (status);
}
}
else
{
fclose(handle);
return (ERROR_INVALIDLAYER);
}
DecodeFlag=true;
}
else
if (memcmp(ChunkHeader,HEADER_ANIMATION,strlen(HEADER_ANIMATION))==0)
{
int status;
if ((status=processAnimation(handle,ChunkSize))!=ERROR_OK)
{
fclose(handle);
return (status);
}
}
else
if (memcmp(ChunkHeader,HEADER_BLOCKDATA,strlen(HEADER_BLOCKDATA))==0)
{
int status;
if ((status=processBlockData(handle,ChunkSize))!=ERROR_OK)
{
fclose(handle);
return (status);
}
DecodeFlag=true;
}
else
if (memcmp(ChunkHeader,HEADER_EDITOR,strlen(HEADER_EDITOR))==0)
{
loadMappySkipSection(handle,ChunkSize);
DecodeFlag=true;
}
else
if (memcmp(ChunkHeader,HEADER_EPHD,strlen(HEADER_EPHD))==0)
{
loadMappySkipSection(handle,ChunkSize);
DecodeFlag=true;
}
if (DecodeFlag)
{
FilePosition+=ChunkSize;
}
} while (FilePosition<Mappy_FileSize);
fflush(handle);
fclose(handle);
return (ERROR_OK);
}
else
{
return (ERROR_FILENOTOPENED);
}
}
BLKSTR *CMappy::GetBlockData(int block)
{
if (block>=0 && block<m_dNumBlockStructs)
{
return ((BLKSTR *) &blockStructs[block]);
}
return (NULL);
}
int CMappy::processBlockData(FILE *handle,int ChunkSize)
{
register int loop,i;
BLKSTR *temp;
char one;
i=0;
blockStructs=(BLKSTR *) calloc(m_dNumBlockStructs,sizeof(BLKSTR));
if (blockStructs!=NULL)
{
temp=blockStructs;
for (loop=0; loop<m_dNumBlockStructs; loop++)
{
fread((char *) &temp->bgoff,1,sizeof(temp->bgoff),handle);
fread((char *) &temp->fgoff,1,sizeof(temp->fgoff),handle);
fread((char *) &temp->fgoff2,1,sizeof(temp->fgoff2),handle);
fread((char *) &temp->fgoff3,1,sizeof(temp->fgoff3),handle);
fread((char *) &temp->user1,1,sizeof(temp->user1),handle);
fread((char *) &temp->user2,1,sizeof(temp->user2),handle);
fread((char *) &temp->user3,1,sizeof(temp->user3),handle);
fread((char *) &temp->user4,1,sizeof(temp->user4),handle);
fread((char *) &temp->user5,1,sizeof(temp->user5),handle);
fread((char *) &temp->user6,1,sizeof(temp->user6),handle);
fread((char *) &temp->user7,1,sizeof(temp->user7),handle);
fread((char *) &one,1,sizeof(one),handle);
temp->tl=(one & 1 ? true : false);
temp->tr=(one & 2 ? true : false);
temp->bl=(one & 4 ? true : false);
temp->br=(one & 8 ? true : false);
temp->trigger=(one & 16 ? true : false);
temp->unused1=(one & 32 ? true : false);
temp->unused2=(one & 64 ? true : false);
temp->unused3=(one & 128 ? true : false);
temp++;
i+=sizeof(BLKSTR);
}
}
else
{
return (ERROR_OUTOFMEM);
}
loadMappySkipSection(handle,ChunkSize-i);
return (ERROR_OK);
}
int CMappy::processAnimation(FILE *handle,int ChunkSize)
{
char *tempBuffer,*temp;
ANISTR *tempAnim;
register int loop;
register long sequenceSize;
long *ptr;
if ((tempBuffer=(char *) calloc(1,ChunkSize))==NULL)
{
return (ERROR_OUTOFMEM);
}
fread(tempBuffer,1,ChunkSize,handle);
// Now to count backwards to get the number of animations
m_dNumAnimations=0;
sequenceSize=ChunkSize;
temp=(char *) (tempBuffer+ChunkSize);
while (1) {
temp-=sizeof(ANISTR);
sequenceSize-=sizeof(ANISTR);
m_dNumAnimations++;
if (*(temp)==AN_END)
{
break;
}
}
sequenceSize/=4;
if ((animations=(ANISTR *) calloc(m_dNumAnimations,sizeof(ANISTR)))==NULL)
{
return (ERROR_OUTOFMEM);
}
tempAnim=(ANISTR *) temp; //(tempBuffer+ChunkSize); //(ChunkSize-sizeof(ANISTR)));
for (loop=0; loop<m_dNumAnimations; loop++)
{
animations[loop].antype=tempAnim->antype;
animations[loop].anuser=tempAnim->anuser;
animations[loop].andelay=tempAnim->andelay;
animations[loop].ancount=tempAnim->ancount;
animations[loop].ancuroff=(tempAnim->ancuroff+ChunkSize)/(m_dMapType==FMP05 ? 4 : 1);
animations[loop].anstartoff=(tempAnim->anstartoff+ChunkSize)/(m_dMapType==FMP05 ? 4 : 1);
animations[loop].anendoff=(tempAnim->anendoff+ChunkSize)/(m_dMapType==FMP05 ? 4 : 1);
tempAnim++;
}
if ((animationSeq=(long *) calloc(sizeof(long),sequenceSize))==NULL)
{
return (ERROR_OUTOFMEM);
}
ptr=(long *) tempBuffer;
for (loop=0; loop<(int) sequenceSize; loop++)
{
animationSeq[loop]=*(ptr);
if (m_dMapType==FMP05)
{
animationSeq[loop]/=m_dBlockDepth;
}
ptr++;
}
// Now we've done that, we get the animation
free(tempBuffer);
// Initilise the animations
MapInitAnims();
return (ERROR_OK);
}
void CMappy::MapInitAnims(void)
{
int loop;
if (m_dNumAnimations>0)
{
for (loop=0; loop<m_dNumAnimations; loop++)
{
switch (animations[loop].antype) {
case AN_PPFR : animations[loop].antype=AN_PPFF;
break;
case AN_ONCES: animations[loop].antype=AN_ONCE;
break;
};
if (animations[loop].antype==AN_LOOPR || animations[loop].antype==AN_PPRF || animations[loop].antype==AN_PPRR)
{
if (animations[loop].antype==AN_PPRF)
{
animations[loop].antype=AN_PPRR;
}
animations[loop].ancuroff=animations[loop].anstartoff;
if (animations[loop].anstartoff!=animations[loop].anendoff)
{
animations[loop].ancuroff=animations[loop].anendoff-1;
}
}
else
{
animations[loop].ancuroff=animations[loop].anstartoff;
}
animations[loop].ancount=animations[loop].andelay;
}
}
}
ANISTR *CMappy::GetAnimationData(int index)
{
if (index>=0 && index<m_dNumAnimations)
{
return ((ANISTR *) &animations[index]);
}
return (NULL);
}
signed short CMappy::loadMappyWord(FILE *handle,bool order)
{
signed short value;
fread((char *) &value,1,sizeof(value),handle);
if (order)
{
value=((value/256) & 255)+(( value & 255)*256);
}
return (value);
}
int CMappy::processMapHeader(FILE *handle,int size)
{
int i;
m_dMapVersion=(int) (fgetc(handle)<<8)+(int) fgetc(handle);
m_dLSB=(char) fgetc(handle);
m_dMapType=(char) fgetc(handle);
if (m_dMapType!=FMP05 && m_dMapType!=FMP10 && m_dMapType!=FMP10RLE)
{
return (ERROR_UNKNOWNVERSION);
}
i=4;
m_dMapWidth=(int) loadMappyWord(handle,false); // 4
m_dMapHeight=(int) loadMappyWord(handle,false);
loadMappyWord(handle,false); // Reserved 1
loadMappyWord(handle,false); // Reserved 2
i+=8;
m_dBlockWidth=(int) loadMappyWord(handle,false);
m_dBlockHeight=(int) loadMappyWord(handle,false);
m_dMapDepth=(int) loadMappyWord(handle,false);
m_dBlockDepth=(int) loadMappyWord(handle,false);
i+=8;
m_dNumBlockStructs=(int) loadMappyWord(handle,false);
m_dNumBlockGFX=(int) loadMappyWord(handle,false);
i+=4;
m_dTileSizeInBytes=m_dMapWidth*m_dMapHeight;
switch (m_dBlockDepth) {
case 15:
case 16 : m_dTileSizeInBytes*=2; break;
case 24 : m_dTileSizeInBytes*=3; break;
case 32 : m_dTileSizeInBytes*=4; break;
};
if (size>24)
{
// Read next 4 bytes
m_dMapTrans8=(int) fgetc(handle);
m_dMapTransRed=(int) fgetc(handle);
m_dMapTransGreen=(int) fgetc(handle);
m_dMapTransBlue=(int) fgetc(handle);
i+=4;
}
else
{
m_dMapTrans8=(int) 0;
m_dMapTransRed=(int) 0xFF;
m_dMapTransGreen=(int) 0;
m_dMapTransBlue=(int) 0xFF;
}
if (size>28)
{
m_dBlockGapX=(int) loadMappyWord(handle,false);
m_dBlockGapY=(int) loadMappyWord(handle,false);
m_dBlockStaggerX=(int) loadMappyWord(handle,false);
m_dBlockStaggerY=(int) loadMappyWord(handle,false);
i+=8;
}
else
{
m_dBlockGapX=m_dBlockWidth;
m_dBlockGapY=m_dBlockHeight;
m_dBlockStaggerX=0;
m_dBlockStaggerY=0;
}
if (size>36)
{
m_dClipMask=(int) loadMappyWord(handle,false);
i+=2;
}
else
{
m_dClipMask=0;
}
if (i!=size)
{
loadMappySkipSection(handle,size-i);
}
return (ERROR_OK);
}
struct __RGB *CMappy::GetPaletteColour(int index)
{
if (index>=0 && index<(int) (1<<m_dBlockDepth))
{
return ((struct __RGB *) &rgb[index]);
}
else
{
return (NULL);
}
}
void CMappy::processPalette(FILE *handle,int sectionLen)
{
int i,lp;
i=0;
if (m_dBlockDepth<=8)
{
for (lp=0; lp<(int) (1<<m_dBlockDepth); lp++)
{
rgb[lp].r=(char) fgetc(handle);
rgb[lp].g=(char) fgetc(handle);
rgb[lp].b=(char) fgetc(handle);
i+=sizeof(struct __RGB);
}
}
if (i!=sectionLen)
{
loadMappySkipSection(handle,sectionLen-i);
}
}
int CMappy::processGraphics(FILE *handle,int ChunkSize)
{
if ((m_cpGraphics=(char *) calloc(1,ChunkSize))!=NULL)
{
fread(m_cpGraphics,1,ChunkSize,handle);
return (ERROR_OK);
}
return (ERROR_OUTOFMEM);
}
int CMappy::GetNumberOfLayers(void)
{
register int loop,count;
count=0;
for (loop=0; loop<MAX_LAYERS; loop++)
{
if (layer[loop]) count++;
}
return (count);
}
int CMappy::GetMappyIndex(int x,int y)
{
return (x+(y*m_dMapWidth));
}
signed short CMappy::GetTileAtPosition(int x,int y,int layerLevel)
{
if (x>=0 && y>=0 && x<m_dMapWidth && y<m_dMapHeight)
{
if (layerLevel>=0 && layerLevel<MAX_LAYERS)
{
if (layer[layerLevel])
{
return ((signed short) *(layer[layerLevel]+GetMappyIndex(x,y)));
}
}
}
return (0);
}
signed short CMappy::WriteTileAtPosition(int x,int y,int layerLevel,signed short value)
{
if (x>=0 && y>=0 && x<m_dMapWidth && y<m_dMapHeight)
{
if (layerLevel>=0 && layerLevel<MAX_LAYERS)
{
*(layer[layerLevel]+GetMappyIndex(x,y))=value;
return (ERROR_OK);
}
}
return (ERROR_INVALIDCOORD);
}
void CMappy::loadMappySkipSection(FILE *handle,int size)
{
register int lp;
register char ignore;
if (size==0) return;
for (lp=0; lp<size; lp++)
{
ignore=(char) fgetc(handle);
}
}
int CMappy::allocateLayer(int layerLevel,int ChunkSize,int extraBytes)
{
if ((layer[layerLevel]=(signed short *) calloc(1,ChunkSize*sizeof(signed short)))==NULL)
{
return (ERROR_OUTOFMEM);
}
if (extraBytes>0)
{
if ((extraBytesLayer[layerLevel]=(char *) calloc(extraBytes,m_dMapWidth*m_dMapHeight))==NULL)
{
return (ERROR_OUTOFMEM);
}
}
return ERROR_OK;
}
signed short CMappy::getTileMapLayer(FILE *handle,int sectionLen,int layerLevel,int extraBytesSize)
{
register int lp;
signed short data,rleCount;
signed short *ptr;
int status;
if ((status=allocateLayer(layerLevel,sectionLen,extraBytesSize))==ERROR_OK)
{
ptr=layer[layerLevel];
switch (m_dMapType) {
case FMP05 : // FMP 0.5, I think
case FMP10 : // FMP 1.0
for (lp=0; lp<sectionLen; lp+=sizeof(signed short))
{
fread((char *) &data,1,sizeof(data),handle);
if (m_dMapType==FMP05)
{
if (data<0)
{
*(ptr)=data/16;
}
else
{
*(ptr)=(signed short) (data/m_dBlockDepth);
}
}
else
{
*(ptr)=data;
}
ptr++;
}
break;
case FMP10RLE: // FMP 1.0 compressed
lp=0;
while (lp<sectionLen)
{
fread((char *) &rleCount,1,sizeof(rleCount),handle);
if (rleCount>0)
{
while (rleCount)
{
fread((char *) &data,1,sizeof(data),handle);
*(ptr)=data;
ptr++;
rleCount--;
lp+=sizeof(data);
}
}
else
if (rleCount<0)
{
fread((char *) &data,1,sizeof(data),handle);
while (rleCount)
{
*(ptr)=data;
ptr++;
rleCount++;
lp+=sizeof(data);
}
}
}
break;
};
}
return (status);
}
int CMappy::CalculateExtraPosition(int x,int y)
{
return ((x*m_dExtraBytesSize)+(y*m_dMapWidth*m_dExtraBytesSize));
}
char *CMappy::GetExtraDataPointer(int x,int y,int layer)
{
if (layer>=0 && layer<MAX_LAYERS)
{
if (extraBytesLayer[layer])
{
return ((char *) (extraBytesLayer[layer]+CalculateExtraPosition(x,y)));
}
}
return (NULL);
}
int CMappy::FindTile(int layerNum,int *xP,int *yP,int tile)
{
register int x,y;
if (layerNum>=0 && layerNum<MAX_LAYERS)
{
if (layer[layerNum])
{
for (x=0; x<m_dMapWidth; x++)
{
for (y=0; y<m_dMapHeight; y++)
{
if (GetTileAtPosition(x,y,layerNum)==tile)
{
// Found
if (xP) *(xP)=x;
if (yP) *(yP)=y;
return (ERROR_OK);
}
}
}
return (ERROR_TILENOTFOUND);
}
else
{
return (ERROR_LAYERNOTINUSE);
}
}
return (ERROR_INVALIDLAYER);
}
int CMappy::returnDiv(void)
{
int div;
div=m_dBlockWidth*m_dBlockHeight;
if (m_dMapDepth==15)
{
return div<<1;
}
else
{
return div*(m_dMapDepth/8);
}
}
int CMappy::returnBackgroundOffset(int blockNum)
{
BLKSTR *block;
if ((block=GetBlockData(blockNum))!=NULL)
{
return block->bgoff/returnDiv();
}
return 0;
}
int CMappy::returnForegroundOffset(int blockNum,short which)
{
BLKSTR *block;
register int index;
if ((block=GetBlockData(blockNum))!=NULL)
{
switch (which) {
case FOREGROUND1 : index=block->fgoff; break;
case FOREGROUND2 : index=block->fgoff2; break;
case FOREGROUND3 : index=block->fgoff3; break;
default : index=0; break;
};
return index/returnDiv();
}
return 0;
}
int CMappy::returnCurrentAnimationBlock(int block)
{
ANISTR *a;
if (block<0)
{
block=0-block;
}
if ((a=GetAnimationData(m_dNumAnimations-block))!=NULL)
{
return animationSeq[a->ancuroff];
}
return 0;
}
int CMappy::addLayer(int layers)
{
if (layers>=0 && layers<MAX_LAYERS)
{
if (layer[layers]) return ERROR_LAYERINUSE;
if (m_dMapWidth>0 && m_dMapHeight>0)
{
return allocateLayer(layers,m_dMapWidth*m_dMapHeight, m_dExtraBytesSize);
}
else
{
return ERROR_MAPNOTLOADED;
}
}
return ERROR_INVALIDLAYER;
}
int CMappy::deleteLayer(int layers)
{
if (layers>=0 && layers<MAX_LAYERS)
{
if (layer[layers]==NULL)
{
return ERROR_LAYERNOTINUSE;
}
else
{
free(layer[layers]);
layer[layers]=NULL;
return ERROR_OK;
}
}
else
{
return ERROR_INVALIDLAYER;
}
}
int CMappy::copyLayer(int fromLayer,int toLayer)
{
int status;
if (fromLayer>=0 && fromLayer<MAX_LAYERS && toLayer>=0 && toLayer<MAX_LAYERS)
{
if (layer[fromLayer]==NULL)
{
return ERROR_LAYERNOTINUSE;
}
if (layer[toLayer]==NULL)
{
if ((status=allocateLayer(toLayer,m_dMapWidth*m_dMapHeight, m_dExtraBytesSize))!=ERROR_OK)
{
return status;
}
memcpy(layer[toLayer],layer[fromLayer],m_dMapWidth*m_dMapHeight*sizeof(signed short));
return ERROR_OK;
}
}
return ERROR_INVALIDLAYER;
}
int CMappy::clearLayer(int layers)
{
if (layers>=0 && layers<MAX_LAYERS)
{
if (layer[layers]==NULL)
{
return ERROR_LAYERNOTINUSE;
}
memset((char *) layer[layers],0,m_dMapWidth*m_dMapHeight*sizeof(signed short));
return ERROR_OK;
}
return ERROR_INVALIDLAYER;
}
int CMappy::moveLayer(int fromLayer,int toLayer)
{
int status;
if (fromLayer>=0 && fromLayer<MAX_LAYERS && toLayer>=0 && toLayer<MAX_LAYERS)
{
if (layer[fromLayer]==NULL)
{
return ERROR_LAYERNOTINUSE;
}
if (layer[toLayer]==NULL)
{
status=allocateLayer(toLayer,m_dMapWidth*m_dMapHeight, m_dExtraBytesSize);
if (status!=ERROR_OK)
{
return status;
}
memcpy((char *) layer[toLayer] ,(char *) layer[fromLayer],m_dMapWidth*m_dMapHeight*sizeof(signed short));
return clearLayer(fromLayer);
}
else
{
return ERROR_LAYERINUSE;
}
}
return ERROR_INVALIDLAYER;
}
void CMappy::UpdateAnimations(void)
{
int loop;
if (m_dNumAnimations!=0)
{
for (loop=0; loop<m_dNumAnimations; loop++)
{
if (animations[loop].antype!=AN_NONE)
{
animations[loop].ancount--;
if (animations[loop].ancount & 128)
{
animations[loop].ancount=animations[loop].andelay;
switch (animations[loop].antype) {
case AN_LOOPF : if (animations[loop].anstartoff!=animations[loop].anendoff)
{
animations[loop].ancuroff++;
if (animations[loop].ancuroff==animations[loop].anendoff)
{
animations[loop].ancuroff=animations[loop].anstartoff;
}
}
break;
case AN_LOOPR : if (animations[loop].anstartoff!=animations[loop].anendoff)
{
animations[loop].ancuroff--;
if (animations[loop].ancuroff==animations[loop].anstartoff-1)
{
animations[loop].ancuroff=animations[loop].anendoff;
}
}
break;
case AN_ONCE : if (animations[loop].anstartoff!=animations[loop].anendoff)
{
animations[loop].ancuroff++;
if (animations[loop].ancuroff==animations[loop].anendoff)
{
animations[loop].antype=AN_ONCES;
animations[loop].ancuroff=animations[loop].anendoff;
}
}
break;
case AN_ONCEH : if (animations[loop].anstartoff!=animations[loop].anendoff)
{
if (animations[loop].ancuroff!=animations[loop].anendoff-1)
{
animations[loop].ancuroff++;
}
}
break;
case AN_PPFF : if (animations[loop].anstartoff!=animations[loop].anendoff)
{
animations[loop].ancuroff++;
if (animations[loop].ancuroff==animations[loop].anendoff)
{
animations[loop].ancuroff-=2;
animations[loop].antype=AN_PPFR;
if (animations[loop].ancuroff<animations[loop].anstartoff)
{
animations[loop].ancuroff++;
}
}
}
break;
case AN_PPFR : if (animations[loop].anstartoff!=animations[loop].anendoff)
{
animations[loop].ancuroff--;
if (animations[loop].ancuroff==animations[loop].anstartoff-1)
{
animations[loop].ancuroff+=2;
animations[loop].antype=AN_PPFF;
if (animations[loop].ancuroff>animations[loop].anendoff)
{
animations[loop].ancuroff--;
}
}
}
break;
case AN_PPRR : if (animations[loop].anstartoff!=animations[loop].anendoff)
{
animations[loop].ancuroff--;
if (animations[loop].ancuroff==animations[loop].anstartoff-1)
{
animations[loop].ancuroff+=2;
animations[loop].antype=AN_PPRF;
if (animations[loop].ancuroff>animations[loop].anendoff)
{
animations[loop].ancuroff--;
}
}
}
break;
case AN_PPRF : if (animations[loop].anstartoff!=animations[loop].anendoff)
{
animations[loop].ancuroff--;
if (animations[loop].ancuroff==animations[loop].anendoff)
{
animations[loop].ancuroff-=2;
animations[loop].antype=AN_PPRR;
if (animations[loop].ancuroff<animations[loop].anstartoff)
{
animations[loop].ancuroff++;
}
}
}
break;
}
}
}
}
}
}