int AL_PROTO ALCompressedObject::Insert( ALStorage AL_DLL_FAR &input_object ) { AL_ASSERT_OBJECT( this, ALCompressedObject, "Insert" ); AL_ASSERT_OBJECT( &input_object, ALStorage, "Insert" ); if ( mStatus < AL_SUCCESS ) return mStatus; // // Here is where we open the input and the output. // ALOpenFiles files( input_object, *mpStorageObject ); // // We first write out the uncompressed size, which we already know. We // then save the current position, and write placeholder longs out for // what will become the compressed size and the CRC-32. // mpStorageObject->WritePortableLong( input_object.GetSize() ); long saved_pos = mpStorageObject->Tell(); mpStorageObject->WritePortableLong( 0xfedcba98L ); //Temporary mpStorageObject->WritePortableLong( 0x01234567L ); //Temporary // // If a derived class has any header data to write out, this is where it // will be performed. The base class writes 0 bytes here. // WriteHeaderData( &input_object ); long start = mpStorageObject->Tell(); // // Next, perform the compression. Once that is done we can calculate // the compressed size. The CRC-32 will have been calculated on the fly // as the compression was performed. // mpCompressionEngine->Compress( input_object, *mpStorageObject ); long compressed_size = mpStorageObject->Tell() - start; if ( mpCompressionEngine->mStatus < 0 ) return mStatus = mpCompressionEngine->mStatus; // // Go back to the spot we remembered, and write out the compressed // size and the CRC. At that point, the compressed object is complete. // mpStorageObject->Seek( saved_pos ); mpStorageObject->WritePortableLong( compressed_size ); mpStorageObject->WritePortableLong( ~input_object.GetCrc32() ); if ( mpStorageObject->mStatus < 0 ) return mStatus = mpStorageObject->mStatus; return AL_SUCCESS; }
/* CheckpointHeader The header lives in its own file, so we can write it at any point we have a valid archive. This includes all the tables, as well as basic header info. */ bool trpgwArchive::CheckpointHeader() { trpgMemWriteBuffer buf(ness); if (!isValid()) return false; if (!header.isValid()) { if(header.getErrMess()) strcpy(errMess, header.getErrMess()); return false; } // This will close the appendable files if (tileFile) { tileFile->Flush(); } /* Build a Tile Table We need to build one from scratch here. However, we have all the relevant information collected during the WriteTile calls. */ if(header.GetIsLocal()) { int row = 0; int col = 0; header.GetBlocks(row,col); tileTable.SetCurrentBlock(row,col,true); } if (tileMode == TileExternal) { // External tiles are easy tileTable.SetMode(trpgTileTable::External); } else if( tileMode == TileExternalSaved) { if(!isRegenerate && firstHeaderWrite) { // Set up the sizes tileTable.SetMode(trpgTileTable::ExternalSaved); tileTable.SetNumLod(1); trpg2iPoint lodSize; header.GetLodSize(0,lodSize); tileTable.SetNumTiles(lodSize.x, lodSize.y, 0); firstHeaderWrite = false; } // Now set the individual tile locations for (unsigned int i=0;i<externalTiles.size();i++) { TileFileEntry &te = externalTiles[i]; trpgwAppAddress addr; addr.file = -1; addr.offset = -1; tileTable.SetTile(te.x,te.y,te.lod,addr,te.zmin,te.zmax); } externalTiles.clear(); } else { if (!isRegenerate && firstHeaderWrite) { // Local tiles require more work tileTable.SetMode(trpgTileTable::Local); if(majorVersion == 2 && minorVersion >= 1) { // Version 2.1, we store only lod 0 in the tile table // Set up the sizes tileTable.SetNumLod(1); trpg2iPoint lodSize; header.GetLodSize(0,lodSize); tileTable.SetNumTiles(lodSize.x, lodSize.y, 0); } else { // Set up the sizes int32 numLod; header.GetNumLods(numLod); tileTable.SetNumLod(numLod); for (int i=0;i<numLod;i++) { trpg2iPoint lodSize; header.GetLodSize(i,lodSize); tileTable.SetNumTiles(lodSize.x,lodSize.y,i); } } firstHeaderWrite = false; } // Now set the individual tile locations // Nothing special need to be done with version 2.1 since // only tile with lod 0 will be found in the tileFiles container for (unsigned int i=0;i<tileFiles.size();i++) { TileFile &tf = tileFiles[i]; for (unsigned int j=0;j<tf.tiles.size();j++) { TileFileEntry &te = tf.tiles[j]; trpgwAppAddress addr; addr.file = tf.id; addr.offset = te.offset; tileTable.SetTile(te.x,te.y,te.lod,addr,te.zmin,te.zmax); } tf.tiles.clear(); } } // Write all the headers into a buffer if (!header.Write(buf)) return false; // Do the mat table and texture table // These can be different depending on the version switch (majorVersion) { case 1: { trpgMatTable1_0 matTable1_0(matTable); trpgTexTable1_0 texTable1_0(texTable); trpgTileTable1_0 tileTable1_0(tileTable); if (!matTable1_0.Write(buf) || !texTable1_0.Write(buf) || !modelTable.Write(buf) || !tileTable1_0.Write(buf) || !lightTable.Write(buf) || !rangeTable.Write(buf)) return false; } break; case 2: if(!header.GetIsMaster()||texTable.isValid()) { if(!texTable.Write(buf)) { strcpy(errMess, "Error writing texture table"); if(texTable.getErrMess()) { strcat(errMess, ": "); strcat(errMess, texTable.getErrMess()); return false; } } } //These tables will not be populated if this is the master table. if(!header.GetIsMaster()) { if (!matTable.Write(buf)) { strcpy(errMess, "Error writing material table"); if(matTable.getErrMess()) { strcat(errMess, ": "); strcat(errMess, matTable.getErrMess()); return false; } } if(!modelTable.Write(buf) ) { strcpy(errMess, "Error writing model table"); if(modelTable.getErrMess()) { strcat(errMess, ": "); strcat(errMess, modelTable.getErrMess()); return false; } } } //always write the tile table, even if we are a master if(!tileTable.Write(buf)) { strcpy(errMess, "Error writing tile table"); if(tileTable.getErrMess()) { strcat(errMess, ": "); strcat(errMess, tileTable.getErrMess()); return false; } } if(!header.GetIsMaster()) { if(!lightTable.Write(buf)) { strcpy(errMess, "Error writing light table"); if(lightTable.getErrMess()) { strcat(errMess, ": "); strcat(errMess, lightTable.getErrMess()); return false; } } if(!rangeTable.Write(buf)) { strcpy(errMess, "Error writing range table"); if(rangeTable.getErrMess()) { strcat(errMess, ": "); strcat(errMess, rangeTable.getErrMess()); return false; } } if (!textStyleTable.Write(buf)) { strcpy(errMess,"Error writing text style table"); if (textStyleTable.getErrMess()) { strcat(errMess, ": "); strcat(errMess, textStyleTable.getErrMess()); return false; } } if (!supportStyleTable.Write(buf)) { strcpy(errMess,"Error writing support style table"); if (supportStyleTable.getErrMess()) { strcat(errMess, ": "); strcat(errMess, supportStyleTable.getErrMess()); return false; } } if (!labelPropertyTable.Write(buf)) { strcpy(errMess,"Error writing label property table"); if (labelPropertyTable.getErrMess()) { strcat(errMess, ": "); strcat(errMess, labelPropertyTable.getErrMess()); return false; } } } break; } // Write the disk header int32 magic = GetMagicNumber(); if (ness != cpuNess) magic = trpg_byteswap_int(magic); if (fwrite(&magic,sizeof(int32),1,fp) != 1) { strcpy(errMess, "Could not write the magic number"); return false; } // Write the header length int32 headerSize = buf.length(); int headLen = headerSize; if (ness != cpuNess) headerSize = trpg_byteswap_int(headerSize); if (fwrite(&headerSize,1,sizeof(int32),fp) != sizeof(int32)) { strcpy(errMess, "Could not write the header size"); return false; } // Write the buffer const char *data = buf.getData(); if (WriteHeaderData(data,headLen,fp) != headLen) { strcpy(errMess, "Could not write the buffer"); return false; } // Note: Not sure what this is char space[40]; if (fwrite(space,1,4,fp) != 4) return false; // Flush output fflush(fp); // Head back to the start of the file rewind(fp); return true; }