home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Game Killer
/
Game_Killer.bin
/
529.WMAPDATA.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-12
|
14KB
|
500 lines
/*
---------------------------------------------------------------------------
| MapData class | (c) Oct 1992 Sysma Automatisering |
---------------------------------------------------------------------------
| Version 1.0 06/10/92 | First implementation. |
| | J.P. Dijkstra, M.Sc. |
| Version 1.05 11/10/92 | Removed all explicit references to far |
| | pointers and changed the memory model to |
| | large. |
| | J.P. Dijkstra, M.Sc. |
---------------------------------------------------------------------------
| A MapData is the smallest unit of information for the maze data of a |
| map. It holds the actual memory block plus the size. The routines that |
| are provided support the (re)allocation of the memory holding the data, |
| and contains the actual (de)compression logic for each format. |
---------------------------------------------------------------------------
*/
#include "wolfmap.h"
#include "alloc.h"
#include "mem.h"
/*
---------------------------------------------------------------------------
| Public functions to implement the desired API. |
---------------------------------------------------------------------------
| Function name | Description. |
---------------------------------------------------------------------------
*/
MapDataRec::MapDataRec ()
{
//
// Default constructor, intializes the fields to zero.
//
BlockData = NULL;
BlockSize = 0;
}
MapDataRec::MapDataRec (unsigned MemSize)
{
//
// Constructor for initial allocation.
//
BlockData = (unsigned *) malloc (MemSize);
BlockSize = BlockData != NULL ? MemSize : 0;
}
MapDataRec::~MapDataRec ()
{
Free ();
}
int MapDataRec::Allocate (unsigned Size)
{
//
// First free the current block if one is allocated.
//
if (BlockData != NULL) free (BlockData);
//
// Now allocate the new block.
//
BlockData = (unsigned *) malloc (Size);
BlockSize = BlockData != NULL ? Size : 0;
return BlockData != NULL ? errOk : errNoMemory;
}
int MapDataRec::Resize (unsigned NewSize)
{
//
// Change the size of the allocated block, if a block is present.
//
if (BlockData != NULL)
{
unsigned *NewBlock = (unsigned *) realloc (BlockData, NewSize);
if (NewBlock != NULL)
{
//
// The resizing is successfull. Now set the fields to the new values.
//
BlockData = NewBlock;
BlockSize = NewSize;
return errOk;
}
//
// Reallocation failed, so return an error.
//
return errNoMemory;
}
//
// No block was allocated in the first place, so return an error.
//
return errNotAllocated;
}
int MapDataRec::Free ()
{
//
// Free the allocated memory, if any. Return Ok to indicate success.
//
if (BlockData != NULL) free (BlockData);
BlockData = NULL;
BlockSize = 0;
return errOk;
}
int MapDataRec::Copy (MapDataRec *Source)
{
//
// Copy the allocated block from the source to this target, if a block
// is indeed allocated for the source.
//
if (Source->BlockData != NULL)
{
//
// If a block is still allocated for the target, deallocate it now.
//
int Error = Allocate (Source->BlockSize);
if (Error == errOk)
{
memcpy (BlockData, Source->BlockData, Source->BlockSize);
BlockSize = Source->BlockSize;
}
return Error;
}
//
// No source block was allocated, so return an error and leave the target
// block unchanged.
//
return errNotAllocated;
}
int MapDataRec::CompressFormat10 (unsigned MagicValue)
{
//
// Calculate various sizes and allocate enough memory to write the
// compressed data into. In worst case, no compression can take place.
// In this case the size needed is the size of the old block plus 2 bytes
// to hold the decompressed size. This, therefore, is the size of the
// new block we will allocate.
//
unsigned *Source = BlockData;
unsigned SourceSize = BlockSize >> 1;
unsigned *NewBlock = (unsigned *) malloc (BlockSize + 2);
unsigned *Target = NewBlock;
unsigned TargetSize = 0;
//
// If the allocation failed, leave the compressed data unchanged and
// return the error code.
//
if (Target == NULL)
{
return errNoMemory;
}
//
// The allocation of the memory block was successful, so write the
// decompressed size (ie. the size of the source block) into the target
// memory block.
//
*(Target++) = BlockSize;
TargetSize++;
//
// Now compress the source block and write the compressed data into the
// target memory block.
//
while (SourceSize > 0)
{
//
// Try if the current word is the start of a secuence of equal values.
// The sequence must at least contain 4 words to be considered, since
// the compressed format of a sequence takes 3 words to store.
//
if (SourceSize > 3)
{
//
// Initialize scan pointers and a counter.
//
unsigned *SrcPtr = Source;
unsigned FirstValue = *(SrcPtr++);
unsigned SrcSize = SourceSize - 1;
unsigned Count = 1;
//
// Scan the remainder of the source block until a different value
// is found.
//
while (SrcSize > 0 && *SrcPtr == FirstValue)
{
SrcSize--;
SrcPtr++;
Count++;
}
//
// Write the source to the target.
//
if (Count > 3)
{
//
// A sequence of more than 3 equal words was found, so write the
// compressed format of this sequence to the target.
//
*(Target++) = MagicValue;
*(Target++) = Count;
*(Target++) = FirstValue;
SourceSize = SrcSize;
Source = SrcPtr;
TargetSize += 3;
}
else
{
//
// A sequence of less than 4 equal words was found, so just copy
// this sequence to the target.
//
SourceSize -= Count;
TargetSize += Count;
while (Count-- > 0)
{
*(Target++) = *(Source++);
}
}
}
else
{
//
// At this point no relevant sequence of equal values could be found.
// So copy just one word and contiue.
//
*(Target++) = *(Source++);
SourceSize--;
TargetSize++;
}
}
//
// The compression is complete. Now reallocate the target memory to the
// real, compressed size. If this isn't successfull, return false and
// retain the old, uncompressed memory block.
//
Target = (unsigned *) realloc (NewBlock, TargetSize << 1);
if (Target == NULL)
{
free (NewBlock);
return errMemoryCorrupted;
}
//
// The target block has been resized to the correct size, so free the
// old block and set the map structure to the new block and size.
//
free (BlockData);
BlockData = Target;
BlockSize = TargetSize << 1;
return errOk;
}
int MapDataRec::CompressFormat11 ()
{
//
// Calculate various sizes and allocate enough memory to write the
// compressed data into. In worst case, no compression can take place.
// In this case the size needed is the size of the old block plus 2 bytes
// to hold the decompressed size. This, therefore, is the size of the
// new block we will allocate.
//
unsigned *Source = BlockData;
unsigned SourceSize = BlockSize >> 1;
unsigned *NewBlock = (unsigned *) malloc (BlockSize + 2);
unsigned *Target = NewBlock;
unsigned TargetSize = 0;
//
// If the allocation failed, leave the compressed data unchanged and
// return the error code.
//
if (Target == NULL)
{
return errNoMemory;
}
//
// The allocation of the memory block was successful, so write the
// decompressed size (ie. the size of the source block) into the target
// memory block.
//
*(Target++) = BlockSize;
TargetSize += 2;
//
// Now compress the source block and write the compressed data into the
// target memory block.
//
// For now we only copy the origional data uncompressed.
//
while (SourceSize-- > 0)
{
*(Target++) = *(Source++);
TargetSize += 2;
}
//
// The compression is complete. Now reallocate the target memory to the
// real, compressed size. If this isn't successfull, return false and
// retain the old, uncompressed memory block.
//
Target = (unsigned *) realloc (NewBlock, TargetSize);
if (Target == NULL)
{
free (NewBlock);
return errMemoryCorrupted;
}
//
// The target block has been resized to the correct size, so free the
// old block and set the map structure to the new block and size.
//
free (BlockData);
BlockData = Target;
BlockSize = TargetSize;
return errOk;
}
int MapDataRec::DecompressFormat10 (unsigned MagicValue)
{
//
// Calculate various sizes and allocate enough memory to write the
// decompressed data into. Currently, the size of the decompressed data
// is stored as the first word in the compressed data stream, so that
// can be used.
//
unsigned *Source = BlockData;
unsigned TargetSize = *(Source++);
unsigned SourceSize = (BlockSize >> 1) - 1;
unsigned *NewBlock = (unsigned *) malloc (TargetSize);
unsigned *Target = NewBlock;
//
// If the allocation failed, leave the compressed data unchanged and
// return the error code.
//
if (Target == NULL)
{
return errNoMemory;
}
//
// The allocation of the memory block was successful, so decompress the
// source block into the target memory block.
//
while (SourceSize-- > 0)
{
unsigned Value = *(Source++);
if (Value == MagicValue)
{
//
// The next word contains a count of words. It specifies the number
// of times the word following that count must be written into the
// target buffer.
//
unsigned Count = *(Source++);
Value = *(Source++);
while (Count-- > 0)
{
*(Target++) = Value;
}
SourceSize -= 2;
}
else
{
*(Target++) = Value;
}
}
//
// The decompression is complete. Now free the old memory block, set
// the map structure to the new block and size and return Ok.
//
free (BlockData);
BlockData = NewBlock;
BlockSize = TargetSize;
return errOk;
}
int MapDataRec::DecompressFormat11 ()
{
//
// Calculate various sizes and allocate enough memory to write the
// decompressed data into. Currently, the size of the decompressed data
// is stored as the first word in the compressed data stream, so that
// can be used.
//
unsigned *Source = BlockData;
unsigned TargetSize = *(Source++);
unsigned WriteSize = TargetSize >> 1;
unsigned *NewBlock = (unsigned *) malloc (TargetSize);
unsigned *Target = NewBlock;
//
// If the allocation failed, leave the compressed data unchanged and
// return the error code.
//
if (Target == NULL)
{
return errNoMemory;
}
//
// The allocation of the memory block was successful, so decompress the
// source block into the target memory block.
//
while (WriteSize-- > 0)
{
unsigned Value = *(Source++);
if (Value == 0xA700 || Value == 0xA800)
{
//
// The values A700 and A800 are special cases. The low byte must
// be replaced with the next byte in the source stream and the
// resulting word must be written to the target stream.
//
(char) Value = *( ((char *) (Source))++ );
*(Target++) = Value;
}
else
{
unsigned HighWord = Value & 0xFF00;
if (HighWord == 0xA700 || HighWord == 0xA800)
{
unsigned Count = Value & 0x00FF;
unsigned *TempSrc;
//
// Set the source pointer to the correct position.
//
if (HighWord == 0xA700)
{
//
// The next byte indicates the number of words back from the
// current target position from where copying must start.
//
TempSrc = Target - (unsigned) (*(( (unsigned char *) Source)++ ));
}
else
{
//
// The next word indicates the number of words from the start of
// the target buffer from where copying must start.
//
TempSrc = NewBlock + *(Source++);
}
//
// Copy the designated block in the decompressed target to the
// current target position.
//
WriteSize -= (Count - 1);
while (Count-- > 0)
{
*(Target++) = *(TempSrc++);
}
}
else
{
*(Target++) = Value;
}
}
}
//
// The decompression is complete. Now free the old memory block, set
// the map structure to the new block and size and return Ok.
//
free (BlockData);
BlockData = NewBlock;
BlockSize = TargetSize;
return errOk;
}