home *** CD-ROM | disk | FTP | other *** search
/ Game Programming in C++ - Start to Finish / GameProgrammingS.iso / developer_install / ReplicaNetFreewareV5_4.exe / data1.cab / Program_Executable_Files / Example4 / MyReplicaNet.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2005-10-30  |  4.3 KB  |  163 lines

  1. /* START_LICENSE_HEADER
  2.  
  3. Copyright (C) 2000 Martin Piper, original design and program code
  4. Copyright (C) 2001-2005 Replica Software
  5.  
  6. This program file is copyright (C) Replica Software and can only be used under license.
  7. For more information visit: http://www.replicanet.com/
  8. Or email: info@replicanet.com
  9.  
  10. END_LICENSE_HEADER */
  11. /*
  12. This expands ReplicaNet by adding compressed storage of data for recording and playback.
  13. */
  14. #include <assert.h>
  15. #include "MyReplicaNet.h"
  16. #include "RNXPCompression/Inc/XPCompression.h"
  17. #include "RNPlatform/Inc/MessageHelper.h"
  18.  
  19. // MyReplicaNet implementation.
  20. MyReplicaNet::MyReplicaNet() : mFP(0) , mOutBytesUsed(0) , mInBytesUsed(0) , mInBufferPosition(0)
  21. {
  22. }
  23.  
  24. MyReplicaNet::~MyReplicaNet()
  25. {
  26.     // It is safe to call these two functions even if a session is not being recorded or playing back.
  27.     StopSessionRecord();
  28.     StopSessionPlayback();
  29.  
  30.     // Make sure any remaining data in the buffer is compressed to the file.
  31.     ForceCompress();
  32.  
  33.     // Close any open recording file if it exists.
  34.     if (mFP)
  35.     {
  36.         fclose(mFP);
  37.         mFP = 0;
  38.     }
  39. }
  40.  
  41. void MyReplicaNet::SetRecordingFilePointer(FILE *fp)
  42. {
  43.     mFP = fp;
  44. }
  45.  
  46. void MyReplicaNet::ForceCompress(void)
  47. {
  48.     // Nothing to compress so don't do anything.
  49.     if (mOutBytesUsed == 0)
  50.     {
  51.         return;
  52.     }
  53.  
  54.     RNReplicaNet::XPCompression compress;
  55.  
  56.     // Allocate enough buffer to accept the worst case compressed size plus an extra int for the size of the compressed chunk.
  57.     char *tempBuffer = (char *)malloc(compress.CalculateMaximumMemory(mOutBytesUsed)+sizeof(int));
  58.     assert(tempBuffer);
  59.     int resultLength = 0;
  60.     compress.Compress(mBuffer,mOutBytesUsed,tempBuffer+sizeof(int),&resultLength);
  61.     // The message helper class preserves endian.
  62.     RNReplicaNet::MessageHelper message;
  63.     message.SetBuffer(tempBuffer);
  64.     message.AddInteger(resultLength);
  65.  
  66.     // Write the compressed data and header.
  67.     fwrite(tempBuffer,1,resultLength+sizeof(int),mFP);
  68.  
  69.     // Free the working buffer.
  70.     free(tempBuffer);
  71.  
  72.     // Reset the number of bytes used in the buffer to zero.
  73.     mOutBytesUsed = 0;
  74. }
  75.  
  76. bool MyReplicaNet::CallbackSessionRecord(const void *data,const int length)
  77. {
  78.     if (!mFP)
  79.     {
  80.         return false;
  81.     }
  82.     if ( (length + mOutBytesUsed) >= kBufferSize)
  83.     {
  84.         ForceCompress();
  85.     }
  86.  
  87.     // Copy the data in to the buffer.
  88.     memcpy(mBuffer + mOutBytesUsed,data,(size_t)length);
  89.     // Increment the number of bytes used in the buffer.
  90.     mOutBytesUsed += length;
  91.     return true;
  92. }
  93.  
  94. bool MyReplicaNet::CallbackSessionPlayback(void *data,const int length)
  95. {
  96.     if (!mFP)
  97.     {
  98.         return false;
  99.     }
  100.  
  101.     // If there is no input data then try to get some from the file.
  102.     if (!mInBufferPosition)
  103.     {
  104.         // First reset the input variables to a known state.
  105.         mInBufferPosition = mBuffer;
  106.         mInBytesUsed = 0;
  107.  
  108.         // Read the header size
  109.         size_t nextChunkSize = 0;
  110.         int temp;
  111.         size_t ret = fread(&temp,1,sizeof(temp),mFP);
  112.         // Failed to read the header size so return false.
  113.         if (ret != sizeof(int))
  114.         {
  115.             return false;
  116.         }
  117.  
  118.         // Read the endian preserved header size
  119.         RNReplicaNet::MessageHelper message;
  120.         message.SetBuffer(&temp);
  121.         nextChunkSize = (size_t)message.GetInteger();
  122.  
  123.         // Allocate enough buffer for the compressed data
  124.         char *tempBuffer = (char *)malloc(nextChunkSize);
  125.         assert(tempBuffer);
  126.         // Read the compressed data
  127.         ret = fread(tempBuffer,1,nextChunkSize,mFP);
  128.         // Failed to read the header size so return false.
  129.         if (ret != nextChunkSize)
  130.         {
  131.             return false;
  132.         }
  133.         int resultLength = 0;
  134.         // Decompress the data and mInBytesUsed is updated with how much real data there is.
  135.         RNReplicaNet::XPCompression compress;
  136.         compress.Decompress(tempBuffer,nextChunkSize,mBuffer,&resultLength);
  137.         mInBytesUsed = (size_t)resultLength;
  138.         free(tempBuffer);
  139.     }
  140.  
  141.     // If we have really run out of data then return false.
  142.     if (mInBytesUsed < (size_t)length)
  143.     {
  144.         return false;
  145.     }
  146.  
  147.     // Check we have a valid input buffer position
  148.     assert(mInBufferPosition);
  149.  
  150.     // Copy the data from the input buffer.
  151.     memcpy(data,mInBufferPosition,length);
  152.  
  153.     // Prepare the input buffer length and position for the next time this function is called.
  154.     mInBytesUsed -= length;
  155.     mInBufferPosition += length;
  156.     if (mInBytesUsed == 0)
  157.     {
  158.         // If there is no more data in this buffer then force a fetch of the next chunk.
  159.         mInBufferPosition = 0;
  160.     }
  161.     return true;
  162. }
  163.