123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804 |
- //---------------------------------------------------------------------------
- //
- // Packet.cpp -- File contains the actual code for the Packet File class
- //
- //---------------------------------------------------------------------------//
- // Copyright (C) Microsoft Corporation. All rights reserved. //
- //===========================================================================//
- //---------------------------------------------------------------------------
- // Include Files
- #ifndef PACKET_H
- #include "packet.h"
- #endif
- #ifndef HEAP_H
- #include "heap.h"
- #endif
- #ifndef LZ_H
- #include "lz.h"
- #endif
- #include "zlib.h"
- #ifndef _MBCS
- #include <gameos.hpp>
- #else
- #include <assert.h>
- #define gosASSERT assert
- #define gos_Malloc malloc
- #define gos_Free free
- #endif
- #include <string.h>
- //---------------------------------------------------------------------------
- extern MemoryPtr LZPacketBuffer;
- extern unsigned long LZPacketBufferSize;
- //---------------------------------------------------------------------------
- // class PacketFile
- void PacketFile::clear (void)
- {
- currentPacket = -1;
- packetSize =
- packetBase =
- numPackets = 0;
- if (seekTable)
- systemHeap->Free(seekTable);
- seekTable = NULL;
- }
- //---------------------------------------------------------------------------
- void PacketFile::atClose (void)
- {
- if (isOpen() && fileMode != READ) // update filesize
- {
- long endPtr = getLength();
-
- //seek(sizeof(long)); //Move Past Version Marker
- //writeLong(endPtr); //Write File length
-
- long tableEntry;
- currentPacket = numPackets;
- if (!seekTable)
- {
- while (--currentPacket >= 0)
- {
- seek(TABLE_ENTRY(currentPacket));
- tableEntry = readLong();
-
- if (GetPacketType(tableEntry) == STORAGE_TYPE_NUL)
- {
- seek(TABLE_ENTRY(currentPacket));
- writeLong(SetPacketType(endPtr,STORAGE_TYPE_NUL));
- }
- else
- {
- endPtr = GetPacketOffset(tableEntry);
- }
- }
- }
- else
- {
- while (--currentPacket >= 0)
- {
- tableEntry = seekTable[currentPacket];
-
- if (GetPacketType(tableEntry) == STORAGE_TYPE_NUL)
- {
- seekTable[currentPacket] = SetPacketType(endPtr,STORAGE_TYPE_NUL);
- }
- else
- {
- endPtr = GetPacketOffset(tableEntry);
- }
- }
- }
- //-----------------------------------------------------
- // If seekTable was being used, write it back to file
- if (seekTable)
- {
- seek(sizeof(long)*2); //File Version & File Length
- write(MemoryPtr(seekTable),(numPackets*sizeof(long)));
- }
- //------------------------------------------------------
- // Is we were using a checkSum, calc it and write it to
- // the beginning of the file.
- if (usesCheckSum)
- {
- long checkSum = checkSumFile();
- seek(0);
- writeLong(checkSum);
- }
- }
-
- clear();
- }
- //---------------------------------------------------------------------------
- long PacketFile::checkSumFile (void)
- {
- //-----------------------------------------
- long currentPosition = logicalPosition;
- seek(4);
- MemoryPtr fileMap = (MemoryPtr)malloc(fileSize());
- read(fileMap,fileSize());
- long sum = 0;
- MemoryPtr curFileByte = fileMap;
- for (unsigned long i=4;i<fileSize();i++,curFileByte++)
- {
- sum += *curFileByte;
- }
- free(fileMap);
- seek (currentPosition);
- return sum;
- }
- //---------------------------------------------------------------------------
- long PacketFile::afterOpen (void)
- {
- if (!numPackets && getLength() >= 12)
- {
- long firstPacketOffset;
- long firstCheck = readLong();
- if (firstCheck == PACKET_FILE_VERSION && !usesCheckSum)
- {
-
- }
- else
- {
- //---------------------------------------
- // This is probably a checksum. Check it
- long checkSum = checkSumFile();
- if (checkSum != firstCheck)
- return PACKET_OUT_OF_RANGE;
- }
- firstPacketOffset = readLong();
-
- numPackets = (firstPacketOffset/sizeof(long))-2;
- }
- currentPacket = -1;
- if (fileMode == READ || fileMode == RDWRITE)
- {
- if (numPackets && !seekTable)
- {
- seekTable = (long *)systemHeap->Malloc(numPackets * sizeof(long));
- gosASSERT(seekTable != NULL);
-
- seek(sizeof(long)*2); //File Version & File Length
- read(MemoryPtr(seekTable),(numPackets*sizeof(long)));
- }
- }
-
- return(NO_ERR);
- }
- //---------------------------------------------------------------------------
- PacketFile::PacketFile (void)
- {
- seekTable = NULL;
- usesCheckSum = FALSE;
- clear();
- }
- //---------------------------------------------------------------------------
- PacketFile::~PacketFile (void)
- {
- close();
- }
- //---------------------------------------------------------------------------
- long PacketFile::open (char* fName, FileMode _mode, long numChild)
- {
- long openResult = File::open(fName,_mode,numChild);
-
- if (openResult != NO_ERR)
- {
- return(openResult);
- }
- openResult = afterOpen();
- return(openResult);
- }
- //---------------------------------------------------------------------------
- long PacketFile::open (FilePtr _parent, unsigned long fileSize, long numChild)
- {
- long result = File::open(_parent,fileSize,numChild);
-
- if (result != NO_ERR)
- return(result);
-
- result = afterOpen();
- return(result);
- }
-
- //---------------------------------------------------------------------------
- long PacketFile::create (char* fName)
- {
- long openResult = File::create(fName);
-
- if (openResult != NO_ERR)
- {
- return(openResult);
- }
-
- openResult = afterOpen();
- return(openResult);
- }
- long PacketFile::createWithCase( char* fName )
- {
- long openResult = File::createWithCase(fName);
-
- if (openResult != NO_ERR)
- {
- return(openResult);
- }
-
- openResult = afterOpen();
- return(openResult);
- }
- //---------------------------------------------------------------------------
- void PacketFile::close (void)
- {
- atClose();
- File::close();
- }
- //---------------------------------------------------------------------------
- long PacketFile::readPacketOffset (long packet, long *lastType)
- {
- long offset = -1;
- if (packet < numPackets)
- {
- if (seekTable)
- offset = seekTable[packet];
- if (lastType)
- *lastType = GetPacketType(offset);
- offset = GetPacketOffset(offset);
- }
- return offset;
- }
- //---------------------------------------------------------------------------
- long PacketFile::readPacket (long packet, unsigned char *buffer)
- {
- long result = 0;
- if ((packet==-1) || (packet == currentPacket) || (seekPacket(packet) == NO_ERR))
- {
- if ((getStorageType() == STORAGE_TYPE_RAW) || (getStorageType() == STORAGE_TYPE_FWF))
- {
- seek(packetBase);
- result = read(buffer, packetSize);
- }
- else
- {
- switch (getStorageType())
- {
- case STORAGE_TYPE_LZD:
- {
- seek(packetBase+sizeof(long));
- if (!LZPacketBuffer)
- {
- LZPacketBuffer = (MemoryPtr)malloc(LZPacketBufferSize);
- gosASSERT(LZPacketBuffer);
- }
-
- if ((long)LZPacketBufferSize < packetSize)
- {
- LZPacketBufferSize = packetSize;
-
- free(LZPacketBuffer);
- LZPacketBuffer = (MemoryPtr)malloc(LZPacketBufferSize);
- gosASSERT(LZPacketBuffer);
- }
-
- if (LZPacketBuffer)
- {
- read(LZPacketBuffer,(packetSize-sizeof(long)));
- long decompLength = LZDecomp(buffer,LZPacketBuffer,packetSize-sizeof(long));
- if (decompLength != packetUnpackedSize)
- result = 0;
- else
- result = decompLength;
- }
- }
- break;
- case STORAGE_TYPE_ZLIB:
- {
- seek(packetBase+sizeof(long));
- if (!LZPacketBuffer)
- {
- LZPacketBuffer = (MemoryPtr)malloc(LZPacketBufferSize);
- gosASSERT(LZPacketBuffer);
- }
-
- if ((long)LZPacketBufferSize < packetSize)
- {
- LZPacketBufferSize = packetSize;
-
- free(LZPacketBuffer);
- LZPacketBuffer = (MemoryPtr)malloc(LZPacketBufferSize);
- gosASSERT(LZPacketBuffer);
- }
-
- if (LZPacketBuffer)
- {
- read(LZPacketBuffer,(packetSize-sizeof(long)));
- unsigned long decompLength = LZPacketBufferSize;
- long decompResult = uncompress(buffer,&decompLength,LZPacketBuffer,packetSize-sizeof(long));
- if ((decompResult != Z_OK) || ((long)decompLength != packetUnpackedSize))
- result = 0;
- else
- result = decompLength;
- }
- }
- break;
- case STORAGE_TYPE_HF:
- STOP(("Tried to read a Huffman Compressed Packet. No Longer Supported!!"));
- break;
- }
- }
- }
- return result;
- }
- //---------------------------------------------------------------------------
- long PacketFile::readPackedPacket (long packet, unsigned char *buffer)
- {
- long result = 0;
- if ((packet==-1) || (packet == currentPacket) || (seekPacket(packet) == NO_ERR))
- {
- if ((getStorageType() == STORAGE_TYPE_RAW) || (getStorageType() == STORAGE_TYPE_FWF))
- {
- seek(packetBase);
- result = read(buffer, packetSize);
- }
- else
- {
- switch (getStorageType())
- {
- case STORAGE_TYPE_LZD:
- {
- seek(packetBase+sizeof(long));
- read(buffer,packetSize);
- }
- break;
- case STORAGE_TYPE_ZLIB:
- {
- seek(packetBase+sizeof(long));
- read(buffer,packetSize);
- }
- break;
- }
- }
- }
- return result;
- }
- //---------------------------------------------------------------------------
- long PacketFile::seekPacket (long packet)
- {
- long offset, next;
- if (packet < 0)
- {
- return(PACKET_OUT_OF_RANGE);
- }
-
- offset = readPacketOffset(packet, &packetType);
- currentPacket = packet++;
- if (packet == numPackets)
- next = getLength();
- else
- next = readPacketOffset(packet);
- packetSize = next-offset;
- packetBase = offset; // seek to beginning of packet
- seek(packetBase);
-
- switch (getStorageType())
- {
- case STORAGE_TYPE_LZD:
- // the first DWORD of a compressed packet is the unpacked length
- packetUnpackedSize = readLong();
- break;
- case STORAGE_TYPE_ZLIB:
- // the first DWORD of a compressed packet is the unpacked length
- packetUnpackedSize = readLong();
- break;
- case STORAGE_TYPE_RAW:
- packetUnpackedSize = packetSize;
- break;
- case STORAGE_TYPE_NUL:
- packetUnpackedSize = 0;
- break;
-
- default:
- return(BAD_PACKET_VERSION);
- }
- if (offset > 0)
- return(NO_ERR);
-
- return (PACKET_OUT_OF_RANGE);
- }
- //---------------------------------------------------------------------------
- void PacketFile::operator ++ (void)
- {
- if (++currentPacket >= numPackets)
- {
- currentPacket = numPackets-1;
- }
- seekPacket(currentPacket);
- }
- //---------------------------------------------------------------------------
- void PacketFile::operator -- (void)
- {
- if (currentPacket-- <= 0)
- {
- currentPacket = 0;
- }
- seekPacket(currentPacket);
- }
- //---------------------------------------------------------------------------
- long PacketFile::getNumPackets (void)
- {
- return numPackets;
- }
- //---------------------------------------------------------------------------
- long PacketFile::getCurrentPacket (void)
- {
- return currentPacket;
- }
- //---------------------------------------------------------------------------
- inline long PacketFile::getPacketOffset(void)
- {
- return packetBase;
- }
- //---------------------------------------------------------------------------
- long PacketFile::getPackedPacketSize (void)
- {
- return packetSize;
- }
- //---------------------------------------------------------------------------
- long PacketFile::getStorageType (void)
- {
- return packetType;
- }
- //---------------------------------------------------------------------------
- void PacketFile::reserve (long count, bool useCheckSum)
- {
- //---------------------------------------------------
- // If we already have packets, reserve does nothing.
- // Otherwise, reserve sets up the file. Must be
- // called before any writing to a newly created file.
- if (numPackets)
- {
- return;
- }
- usesCheckSum = useCheckSum;
- numPackets = count;
- long firstPacketOffset = TABLE_ENTRY(numPackets);
- writeLong(PACKET_FILE_VERSION);
- writeLong(firstPacketOffset);
- //----------------------------
- // initialize the seek table
- while (count-- > 0)
- writeLong(SetPacketType(firstPacketOffset,STORAGE_TYPE_NUL));
- //-------------------------------------------------------------
- // If we called this, chances are we are writing a packet file
- // from start to finish. It is MUCH faster if this table is
- // updated in memory and flushed when the file is closed.
- if (!seekTable)
- {
- seekTable = (long *)systemHeap->Malloc(numPackets * sizeof(long));
-
- if (seekTable != NULL)
- {
- seek(sizeof(long)*2); //File Version & File Length
- read(MemoryPtr(seekTable),(numPackets*sizeof(long)));
- }
- }
- }
- //---------------------------------------------------------------------------
- long PacketFile::writePacket (long packet, MemoryPtr buffer, long nbytes, unsigned char pType)
- {
- //--------------------------------------------------------
- // This function writes the packet to the current end
- // of file and stores the packet address in the seek
- // table. NOTE that this cannot be used to replace
- // a packet. That function is writePacket which takes
- // a packet number and a buffer. The size cannot change
- // and, as such, is irrelevant. You must write the
- // same sized packet each time, if the packet already
- // exists. In theory, it could be smaller but the check
- // right now doesn't allow anything but same size.
- long result = 0;
- MemoryPtr workBuffer = NULL;
- if (pType == ANY_PACKET_TYPE || pType == STORAGE_TYPE_LZD || pType == STORAGE_TYPE_ZLIB)
- {
- if ((nbytes<<1) < 4096)
- workBuffer = (MemoryPtr)malloc(4096);
- else
- workBuffer = (MemoryPtr)malloc(nbytes<<1);
-
- gosASSERT(workBuffer != NULL);
- }
- gosASSERT((packet > 0) || (packet < numPackets));
- packetBase = getLength();
- currentPacket = packet;
- packetSize = packetUnpackedSize = nbytes;
- //-----------------------------------------------
- // Code goes in here to pick the best compressed
- // version of the packet. Otherwise, default
- // to RAW.
- if ((pType == ANY_PACKET_TYPE) || (pType == STORAGE_TYPE_LZD) || (pType == STORAGE_TYPE_ZLIB))
- {
- if (pType == ANY_PACKET_TYPE)
- pType = STORAGE_TYPE_RAW;
-
- //-----------------------------
- // Find best compression here.
- // This USED to use LZ. Use ZLib from now on.
- // Game will ALWAYS be able to READ LZ Packets!!
- unsigned long actualSize = nbytes << 1;
- if (actualSize < 4096)
- actualSize = 4096;
- unsigned long workBufferSize = actualSize;
- unsigned long oldBufferSize = nbytes;
- long compressedResult = compress2(workBuffer,&workBufferSize,buffer,nbytes,Z_DEFAULT_COMPRESSION);
- if (compressedResult != Z_OK)
- STOP(("Unable to write packet %d to file %s. Error %d",packet,fileName,compressedResult));
-
- compressedResult = uncompress(buffer,&oldBufferSize,workBuffer,nbytes);
- if ((long)oldBufferSize != nbytes)
- STOP(("Packet size changed after compression. Was %d is now %d",nbytes,oldBufferSize));
- if ((pType == STORAGE_TYPE_LZD) || (pType == STORAGE_TYPE_ZLIB) || ((long)workBufferSize < nbytes))
- {
- pType = STORAGE_TYPE_ZLIB;
- packetSize = workBufferSize;
- }
- }
-
- packetType = pType;
- seek(packetBase);
- if (packetType == STORAGE_TYPE_ZLIB)
- {
- writeLong(packetUnpackedSize);
- result = write(workBuffer, packetSize);
- }
- else
- {
- result = write(buffer, packetSize);
- }
- if (!seekTable)
- {
- seek(TABLE_ENTRY(packet));
- writeLong(SetPacketType(packetBase,packetType));
- }
- else
- {
- seekTable[packet] = SetPacketType(packetBase,packetType);
- }
- long *currentEntry = NULL;
- if (seekTable)
- {
- packet++;
- currentEntry = &(seekTable[packet]);
- }
- long tableData = SetPacketType(getLength(),STORAGE_TYPE_NUL);
- while (packet < (numPackets - 1))
- {
- if (!seekTable)
- {
- writeLong(tableData);
- }
- else
- {
- *currentEntry = tableData;
- currentEntry++;
- }
- packet++;
- }
-
- if (workBuffer)
- free(workBuffer);
-
- return result;
- }
- #define DEFAULT_MAX_PACKET 65535
- //---------------------------------------------------------------------------
- long PacketFile::insertPacket (long packet, MemoryPtr buffer, long nbytes, unsigned char pType)
- {
- //--------------------------------------------------------
- // This function writes the packet to the current end
- // of file and stores the packet address in the seek
- // table. Originally, replace was a NONO. No, we check
- // for the size and, if it is different, insert the new
- // packet into a new file and basically spend many timeparts doing it.
- // Necessary for the teditor.
- // I Love it.
- long result = 0;
- if (packet < 0)
- {
- return result;
- }
- //---------------------------------------------------------------
- // Only used here, so OK if regular WINDOWS(tm) malloc!
- MemoryPtr workBuffer = (MemoryPtr)malloc(DEFAULT_MAX_PACKET);
-
- //-------------------------------------------------------------
- // All new code here. Basically, open a new packet file,
- // write each of the old packets and this new one. Close all
- // and copy the new one over the old one. Open the new one and
- // set pointers accordingly.
- PacketFile tmpFile;
- result = tmpFile.create("AF3456AF.788");
- if (packet >= numPackets)
- {
- numPackets++;
- }
-
- tmpFile.reserve(numPackets);
-
- for (long i=0;i<numPackets;i++)
- {
- if (i == packet)
- {
- if (nbytes >= DEFAULT_MAX_PACKET)
- {
- //----------------------------------------------------
- // Not sure what to do here. We'll try reallocating
- ::free(workBuffer);
- workBuffer = (MemoryPtr)malloc(packetSize);
- }
-
- tmpFile.writePacket(i,buffer,nbytes,pType);
- }
- else
- {
- seekPacket(i);
- long storageType = getStorageType();
- long packetSize = getPacketSize();
- if (packetSize >= DEFAULT_MAX_PACKET)
- {
- //----------------------------------------------------
- // Not sure what to do here. We'll try reallocating
- ::free(workBuffer);
- workBuffer = (MemoryPtr)malloc(packetSize);
- }
-
- readPacket(i,workBuffer);
- tmpFile.writePacket(i,workBuffer,packetSize,storageType);
- }
- }
- //------------------------------------
- // Now close and reassign everything.
- char ourFileName[250];
- long ourFileMode = 0;
-
- strcpy(ourFileName,fileName);
- ourFileMode = fileMode;
-
- tmpFile.close();
- close();
-
- remove(ourFileName);
- rename("AF3456AF.788",ourFileName);
- remove("AF3456AF.788");
-
- open(ourFileName,(FileMode)ourFileMode);
-
- seekPacket(packet);
-
- return result;
- }
- //---------------------------------------------------------------------------
- long PacketFile::writePacket (long packet, MemoryPtr buffer)
- {
- //--------------------------------------------------------
- // This function replaces the packet with the contents
- // of buffer. There are two restrictions. The first is
- // that the packet must be the same length as the existing
- // packet. If not, buffer over/under run will occur.
- // The second is that the packet cannot be compressed since
- // there is no gaurantee that the new data will compress
- // to exactly the same length. Returns NO_ERR if packet
- // written successfully. Otherwise returns error.
-
- long result = 0;
- if ((packet < 0) || (packet >= numPackets))
- {
- return 0;
- }
- seekPacket(packet);
- if (packetType == STORAGE_TYPE_LZD || packetType == STORAGE_TYPE_HF || packetType == STORAGE_TYPE_ZLIB)
- {
- return (PACKET_WRONG_SIZE);
- }
- else
- {
- result = write(buffer, packetSize);
- }
- if (result == packetUnpackedSize)
- {
- return(NO_ERR);
- }
-
- return BAD_WRITE_ERR;
- }
|