home *** CD-ROM | disk | FTP | other *** search
/ Game Killer / Game_Killer.bin / 516.WMAPDATA.C < prev    next >
C/C++ Source or Header  |  1992-10-12  |  14KB  |  500 lines

  1. /*
  2.  
  3. ---------------------------------------------------------------------------
  4. | MapData class                |    (c) Oct 1992 Sysma Automatisering     |
  5. ---------------------------------------------------------------------------
  6. | Version 1.0         06/10/92 | First implementation.                    |
  7. |                              | J.P. Dijkstra, M.Sc.                     |
  8. | Version 1.05        11/10/92 | Removed all explicit references to far   |
  9. |                              | pointers and changed the memory model to |
  10. |                              | large.                                   |
  11. |                              | J.P. Dijkstra, M.Sc.                     |
  12. ---------------------------------------------------------------------------
  13. | A MapData is the smallest unit of information for the maze data of a    |
  14. | map. It holds the actual memory block plus the size. The routines that  |
  15. | are provided support the (re)allocation of the memory holding the data, |
  16. | and contains the actual (de)compression logic for each format.          |
  17. ---------------------------------------------------------------------------
  18.  
  19. */
  20.  
  21. #include "wolfmap.h"
  22. #include "alloc.h"
  23. #include "mem.h"
  24.  
  25. /*
  26.  
  27. ---------------------------------------------------------------------------
  28. | Public functions to implement the desired API.                          |
  29. ---------------------------------------------------------------------------
  30. | Function name               | Description.                              |
  31. ---------------------------------------------------------------------------
  32.  
  33. */
  34.  
  35. MapDataRec::MapDataRec ()
  36. {
  37.   //
  38.   //   Default constructor, intializes the fields to zero.
  39.   //
  40.   BlockData = NULL;
  41.   BlockSize = 0;
  42. }
  43.  
  44. MapDataRec::MapDataRec (unsigned MemSize)
  45. {
  46.   //
  47.   //   Constructor for initial allocation.
  48.   //
  49.   BlockData = (unsigned *) malloc (MemSize);
  50.   BlockSize = BlockData != NULL ? MemSize : 0;
  51. }
  52.  
  53. MapDataRec::~MapDataRec ()
  54. {
  55.   Free ();
  56. }
  57.  
  58. int MapDataRec::Allocate (unsigned Size)
  59. {
  60.   //
  61.   //   First free the current block if one is allocated.
  62.   //
  63.   if (BlockData != NULL) free (BlockData);
  64.  
  65.   //
  66.   //   Now allocate the new block.
  67.   //
  68.   BlockData = (unsigned *) malloc (Size);
  69.   BlockSize = BlockData != NULL ? Size : 0;
  70.  
  71.   return BlockData != NULL ? errOk : errNoMemory;
  72. }
  73.  
  74. int MapDataRec::Resize (unsigned NewSize)
  75. {
  76.   //
  77.   //   Change the size of the allocated block, if a block is present.
  78.   //
  79.   if (BlockData != NULL)
  80.   {
  81.     unsigned *NewBlock = (unsigned *) realloc (BlockData, NewSize);
  82.     if (NewBlock != NULL)
  83.     {
  84.       //
  85.       //   The resizing is successfull. Now set the fields to the new values.
  86.       //
  87.       BlockData = NewBlock;
  88.       BlockSize = NewSize;
  89.  
  90.       return errOk;
  91.     }
  92.  
  93.     //
  94.     //   Reallocation failed, so return an error.
  95.     //
  96.     return errNoMemory;
  97.   }
  98.  
  99.   //
  100.   //   No block was allocated in the first place, so return an error.
  101.   //
  102.   return errNotAllocated;
  103. }
  104.  
  105. int MapDataRec::Free ()
  106. {
  107.   //
  108.   //   Free the allocated memory, if any. Return Ok to indicate success.
  109.   //
  110.   if (BlockData != NULL) free (BlockData);
  111.   BlockData = NULL;
  112.   BlockSize = 0;
  113.  
  114.   return errOk;
  115. }
  116.  
  117. int MapDataRec::Copy (MapDataRec *Source)
  118. {
  119.   //
  120.   //   Copy the allocated block from the source to this target, if a block
  121.   //   is indeed allocated for the source.
  122.   //
  123.   if (Source->BlockData != NULL)
  124.   {
  125.     //
  126.     //   If a block is still allocated for the target, deallocate it now.
  127.     //
  128.     int Error = Allocate (Source->BlockSize);
  129.  
  130.     if (Error == errOk)
  131.     {
  132.       memcpy (BlockData, Source->BlockData, Source->BlockSize);
  133.       BlockSize = Source->BlockSize;
  134.     }
  135.  
  136.     return Error;
  137.   }
  138.  
  139.   //
  140.   //   No source block was allocated, so return an error and leave the target
  141.   //   block unchanged.
  142.   //
  143.   return errNotAllocated;
  144. }
  145.  
  146. int MapDataRec::CompressFormat10 (unsigned MagicValue)
  147. {
  148.   //
  149.   //   Calculate various sizes and allocate enough memory to write the
  150.   //   compressed data into. In worst case, no compression can take place.
  151.   //   In this case the size needed is the size of the old block plus 2 bytes
  152.   //   to hold the decompressed size. This, therefore, is the size of the
  153.   //   new block we will allocate.
  154.   //
  155.   unsigned *Source     = BlockData;
  156.   unsigned  SourceSize = BlockSize >> 1;
  157.   unsigned *NewBlock   = (unsigned *) malloc (BlockSize + 2);
  158.   unsigned *Target     = NewBlock;
  159.   unsigned  TargetSize = 0;
  160.  
  161.   //
  162.   //   If the allocation failed, leave the compressed data unchanged and
  163.   //   return the error code.
  164.   //
  165.   if (Target == NULL)
  166.   {
  167.     return errNoMemory;
  168.   }
  169.  
  170.   //
  171.   //   The allocation of the memory block was successful, so write the
  172.   //   decompressed size (ie. the size of the source block) into the target
  173.   //   memory block.
  174.   //
  175.   *(Target++) = BlockSize;
  176.   TargetSize++;
  177.  
  178.   //
  179.   //   Now compress the source block and write the compressed data into the
  180.   //   target memory block.
  181.   //
  182.   while (SourceSize > 0)
  183.   {
  184.     //
  185.     //   Try if the current word is the start of a secuence of equal values.
  186.     //   The sequence must at least contain 4 words to be considered, since
  187.     //   the compressed format of a sequence takes 3 words to store.
  188.     //
  189.     if (SourceSize > 3)
  190.     {
  191.       //
  192.       //   Initialize scan pointers and a counter.
  193.       //
  194.       unsigned *SrcPtr     = Source;
  195.       unsigned  FirstValue = *(SrcPtr++);
  196.       unsigned  SrcSize    = SourceSize - 1;
  197.       unsigned  Count      = 1;
  198.  
  199.       //
  200.       //   Scan the remainder of the source block until a different value
  201.       //   is found.
  202.       //
  203.       while (SrcSize > 0 && *SrcPtr == FirstValue)
  204.       {
  205.         SrcSize--;
  206.         SrcPtr++;
  207.         Count++;
  208.       }
  209.  
  210.       //
  211.       //   Write the source to the target.
  212.       //
  213.       if (Count > 3)
  214.       {
  215.         //
  216.         //   A sequence of more than 3 equal words was found, so write the
  217.         //   compressed format of this sequence to the target.
  218.         //
  219.         *(Target++) = MagicValue;
  220.         *(Target++) = Count;
  221.         *(Target++) = FirstValue;
  222.         SourceSize  = SrcSize;
  223.         Source      = SrcPtr;
  224.         TargetSize += 3;
  225.       }
  226.       else
  227.       {
  228.         //
  229.         //   A sequence of less than 4 equal words was found, so just copy
  230.         //   this sequence to the target.
  231.         //
  232.         SourceSize -= Count;
  233.         TargetSize += Count;
  234.         while (Count-- > 0)
  235.         {
  236.           *(Target++) = *(Source++);
  237.         }
  238.       }
  239.     }
  240.     else
  241.     {
  242.       //
  243.       //   At this point no relevant sequence of equal values could be found.
  244.       //   So copy just one word and contiue.
  245.       //
  246.       *(Target++) = *(Source++);
  247.       SourceSize--;
  248.       TargetSize++;
  249.     }
  250.   }
  251.  
  252.   //
  253.   //   The compression is complete. Now reallocate the target memory to the
  254.   //   real, compressed size. If this isn't successfull, return false and
  255.   //   retain the old, uncompressed memory block.
  256.   //
  257.   Target = (unsigned *) realloc (NewBlock, TargetSize << 1);
  258.   if (Target == NULL)
  259.   {
  260.     free (NewBlock);
  261.     return errMemoryCorrupted;
  262.   }
  263.  
  264.   //
  265.   //   The target block has been resized to the correct size, so free the
  266.   //   old block and set the map structure to the new block and size.
  267.   //
  268.   free (BlockData);
  269.   BlockData = Target;
  270.   BlockSize = TargetSize << 1;
  271.  
  272.   return errOk;
  273. }
  274.  
  275. int MapDataRec::CompressFormat11 ()
  276. {
  277.   //
  278.   //   Calculate various sizes and allocate enough memory to write the
  279.   //   compressed data into. In worst case, no compression can take place.
  280.   //   In this case the size needed is the size of the old block plus 2 bytes
  281.   //   to hold the decompressed size. This, therefore, is the size of the
  282.   //   new block we will allocate.
  283.   //
  284.   unsigned *Source     = BlockData;
  285.   unsigned  SourceSize = BlockSize >> 1;
  286.   unsigned *NewBlock   = (unsigned *) malloc (BlockSize + 2);
  287.   unsigned *Target     = NewBlock;
  288.   unsigned  TargetSize = 0;
  289.  
  290.   //
  291.   //   If the allocation failed, leave the compressed data unchanged and
  292.   //   return the error code.
  293.   //
  294.   if (Target == NULL)
  295.   {
  296.     return errNoMemory;
  297.   }
  298.  
  299.   //
  300.   //   The allocation of the memory block was successful, so write the
  301.   //   decompressed size (ie. the size of the source block) into the target
  302.   //   memory block.
  303.   //
  304.   *(Target++) = BlockSize;
  305.   TargetSize += 2;
  306.  
  307.   //
  308.   //   Now compress the source block and write the compressed data into the
  309.   //   target memory block.
  310.   //
  311.   //   For now we only copy the origional data uncompressed.
  312.   //
  313.   while (SourceSize-- > 0)
  314.   {
  315.     *(Target++) = *(Source++);
  316.     TargetSize += 2;
  317.   }
  318.  
  319.   //
  320.   //   The compression is complete. Now reallocate the target memory to the
  321.   //   real, compressed size. If this isn't successfull, return false and
  322.   //   retain the old, uncompressed memory block.
  323.   //
  324.   Target = (unsigned *) realloc (NewBlock, TargetSize);
  325.   if (Target == NULL)
  326.   {
  327.     free (NewBlock);
  328.     return errMemoryCorrupted;
  329.   }
  330.  
  331.   //
  332.   //   The target block has been resized to the correct size, so free the
  333.   //   old block and set the map structure to the new block and size.
  334.   //
  335.   free (BlockData);
  336.   BlockData = Target;
  337.   BlockSize = TargetSize;
  338.  
  339.   return errOk;
  340. }
  341.  
  342. int MapDataRec::DecompressFormat10 (unsigned MagicValue)
  343. {
  344.   //
  345.   //   Calculate various sizes and allocate enough memory to write the
  346.   //   decompressed data into. Currently, the size of the decompressed data
  347.   //   is stored as the first word in the compressed data stream, so that
  348.   //   can be used.
  349.   //
  350.   unsigned *Source     = BlockData;
  351.   unsigned  TargetSize = *(Source++);
  352.   unsigned  SourceSize = (BlockSize >> 1) - 1;
  353.   unsigned *NewBlock   = (unsigned *) malloc (TargetSize);
  354.   unsigned *Target     = NewBlock;
  355.  
  356.   //
  357.   //   If the allocation failed, leave the compressed data unchanged and
  358.   //   return the error code.
  359.   //
  360.   if (Target == NULL)
  361.   {
  362.     return errNoMemory;
  363.   }
  364.  
  365.   //
  366.   //   The allocation of the memory block was successful, so decompress the
  367.   //   source block into the target memory block.
  368.   //
  369.   while (SourceSize-- > 0)
  370.   {
  371.     unsigned Value = *(Source++);
  372.     if (Value == MagicValue)
  373.     {
  374.       //
  375.       //   The next word contains a count of words. It specifies the number
  376.       //   of times the word following that count must be written into the
  377.       //   target buffer.
  378.       //
  379.       unsigned Count = *(Source++);
  380.       Value          = *(Source++);
  381.       while (Count-- > 0)
  382.       {
  383.         *(Target++) = Value;
  384.       }
  385.       SourceSize -= 2;
  386.     }
  387.     else
  388.     {
  389.       *(Target++) = Value;
  390.     }
  391.   }
  392.  
  393.   //
  394.   //   The decompression is complete. Now free the old memory block, set
  395.   //   the map structure to the new block and size and return Ok.
  396.   //
  397.   free (BlockData);
  398.   BlockData = NewBlock;
  399.   BlockSize = TargetSize;
  400.  
  401.   return errOk;
  402. }
  403.  
  404. int MapDataRec::DecompressFormat11 ()
  405. {
  406.   //
  407.   //   Calculate various sizes and allocate enough memory to write the
  408.   //   decompressed data into. Currently, the size of the decompressed data
  409.   //   is stored as the first word in the compressed data stream, so that
  410.   //   can be used.
  411.   //
  412.   unsigned *Source     = BlockData;
  413.   unsigned  TargetSize = *(Source++);
  414.   unsigned  WriteSize  = TargetSize >> 1;
  415.   unsigned *NewBlock   = (unsigned *) malloc (TargetSize);
  416.   unsigned *Target     = NewBlock;
  417.  
  418.   //
  419.   //   If the allocation failed, leave the compressed data unchanged and
  420.   //   return the error code.
  421.   //
  422.   if (Target == NULL)
  423.   {
  424.     return errNoMemory;
  425.   }
  426.  
  427.   //
  428.   //   The allocation of the memory block was successful, so decompress the
  429.   //   source block into the target memory block.
  430.   //
  431.   while (WriteSize-- > 0)
  432.   {
  433.     unsigned Value = *(Source++);
  434.     if (Value == 0xA700 || Value == 0xA800)
  435.     {
  436.       //
  437.       //   The values A700 and A800 are special cases. The low byte must
  438.       //   be replaced with the next byte in the source stream and the
  439.       //   resulting word must be written to the target stream.
  440.       //
  441.       (char) Value =  *( ((char *) (Source))++ );
  442.       *(Target++) = Value;
  443.     }
  444.     else
  445.     {
  446.       unsigned HighWord = Value & 0xFF00;
  447.       if (HighWord == 0xA700 || HighWord == 0xA800)
  448.       {
  449.         unsigned  Count = Value & 0x00FF;
  450.         unsigned *TempSrc;
  451.  
  452.         //
  453.         //   Set the source pointer to the correct position.
  454.         //
  455.         if (HighWord == 0xA700)
  456.         {
  457.           //
  458.           //   The next byte indicates the number of words back from the
  459.           //   current target position from where copying must start.
  460.           //
  461.           TempSrc = Target - (unsigned) (*(( (unsigned char *) Source)++ ));
  462.         }
  463.         else
  464.         {
  465.           //
  466.           //   The next word indicates the number of words from the start of
  467.           //   the target buffer from where copying must start.
  468.           //
  469.           TempSrc = NewBlock + *(Source++);
  470.         }
  471.  
  472.         //
  473.         //   Copy the designated block in the decompressed target to the
  474.         //   current target position.
  475.         //
  476.         WriteSize -= (Count - 1);
  477.         while (Count-- > 0)
  478.         {
  479.           *(Target++) = *(TempSrc++);
  480.         }
  481.       }
  482.       else
  483.       {
  484.         *(Target++) = Value;
  485.       }
  486.     }
  487.   }
  488.  
  489.   //
  490.   //   The decompression is complete. Now free the old memory block, set
  491.   //   the map structure to the new block and size and return Ok.
  492.   //
  493.   free (BlockData);
  494.   BlockData = NewBlock;
  495.   BlockSize = TargetSize;
  496.  
  497.   return errOk;
  498. }
  499.  
  500.