//we only write to the ToD data format. public void writeToDat(string filename) { fileSize = inputBlockCache.fileSize; freeHead = inputBlockCache.freeHead; freeTail = inputBlockCache.freeTail; freeCount = inputBlockCache.freeCount; StreamWriter outputFile = new StreamWriter(new FileStream(filename, FileMode.Create, FileAccess.Write)); Console.WriteLine("Writing data to {0}...", filename); Stopwatch timer = new Stopwatch(); timer.Start(); ////keep some free blocks //if (inputBlockCache.freeCount < 1000) // inputBlockCache.addNewFreeBlocks(1000 - (int)inputBlockCache.freeCount); //rootDirectory.updateBlockData(this, inputBlockCache); //foreach (KeyValuePair<uint, cDatFileBlock> entry in inputBlockCache.blocks) //{ // outputFile.BaseStream.Seek(entry.Key, SeekOrigin.Begin); // entry.Value.writeToDat(outputFile, blockSize); //} //fileSize = inputBlockCache.fileSize; //freeHead = inputBlockCache.fileSize; //freeTail = inputBlockCache.fileSize; //freeCount = inputBlockCache.fileSize; bTree = new cBTree(31); foreach (KeyValuePair <uint, cDatFileEntry> entry in fileCache) { bTree.Insert(entry.Key); } outputBlockCache = new cDatFileBlockCache(blockSize, 1024); rootDirectory = buildBtreeStructure(bTree.Root, outputBlockCache); rootDirectory.updateBlockData(this, outputBlockCache); foreach (KeyValuePair <uint, cDatFileBlock> entry in outputBlockCache.blocks) { outputFile.BaseStream.Seek(entry.Key, SeekOrigin.Begin); entry.Value.writeToDat(outputFile, blockSize); } if (outputBlockCache.freeCount < 1000) { outputBlockCache.addNewFreeBlocks(1000 - (int)outputBlockCache.freeCount); } rootDirectoryOffset = rootDirectory.startBlockOffset; fileSize = outputBlockCache.fileSize; freeHead = outputBlockCache.fileSize; freeTail = outputBlockCache.fileSize; freeCount = outputBlockCache.fileSize; outputFile.BaseStream.Seek(256, SeekOrigin.Begin); //skip acVersionStr which is empty Utils.writeBytes(acTransactionRecord, outputFile); Utils.writeUInt32(fileType, outputFile); Utils.writeInt32(blockSize, outputFile); Utils.writeUInt32(fileSize, outputFile); Utils.writeUInt32(dataSet, outputFile); Utils.writeUInt32(dataSubset, outputFile); Utils.writeUInt32(freeHead, outputFile); Utils.writeUInt32(freeTail, outputFile); Utils.writeUInt32(freeCount, outputFile); Utils.writeUInt32(rootDirectoryOffset, outputFile); Utils.writeUInt32(youngLRU, outputFile); Utils.writeUInt32(oldLRU, outputFile); Utils.writeUInt32(useLRU, outputFile); Utils.writeUInt32(masterMapId, outputFile); Utils.writeUInt32(enginePackVersion, outputFile); Utils.writeUInt32(gamePackVersion, outputFile); Utils.writeBytes(versionMajor, outputFile); Utils.writeUInt32(versionMinor, outputFile); outputFile.Close(); timer.Stop(); Console.WriteLine("{0} blocks written in {1} seconds.", outputBlockCache.blocks.Count, timer.ElapsedMilliseconds / 1000f); //exportDirTree(rootDirectory); }
public void updateBlockData(cDatFile datFile, cDatFileBlockCache blockCache) { MemoryStream memoryStream = new MemoryStream(new byte[sizeToD]); StreamWriter writer = new StreamWriter(memoryStream); for (int i = 0; i < 62; i++) { if (i == 0 && subFolders.Count == 0) { Utils.writeUInt32(0, writer); } else if (i < subFolders.Count && i < files.Count + 1) //directory is allowed to have (files + 1) subdirectories { cDatFileNode subFolder = subFolders[i]; subFolder.updateBlockData(datFile, blockCache); Utils.writeUInt32(subFolder.startBlockOffset, writer); } else { Utils.writeUInt32(0xcdcdcdcd, writer); } } Utils.writeUInt32((uint)files.Count, writer); foreach (KeyValuePair <uint, cDatFileEntry> entry in files) { cDatFileEntry fileEntry = entry.Value; if (fileEntry.fileContent != null) { fileEntry.fileSize = (int)fileEntry.fileContent.Length; blockCache.dataToBlocks(fileEntry.listOfBlocks, fileEntry.fileContent); if (fileEntry.listOfBlocks.Count > 0) { fileEntry.startBlockOffset = fileEntry.listOfBlocks[0].blockOffset; } } else { fileEntry.fileSize = 0; } fileEntry.writeHeader(writer); } cDatFileEntry emptyFileEntry = new cDatFileEntry(0, datFile.fileFormat); for (int i = files.Count; i < 61; i++) { emptyFileEntry.writeHeader(writer); } writer.Flush(); blockCache.dataToBlocks(listOfBlocks, memoryStream); if (listOfBlocks.Count > 0) { startBlockOffset = listOfBlocks[0].blockOffset; } }