/*! \brief Rewrites the header of the archive file * \param stk STK/ITK archive file * \param chunkCount Number of chunks * \param chunks List of chunks * * This function rewrites the header of the archive, replacing dummy values * by the one computed during execution. * The structure of the header is the following : * + 2 bytes : numbers of files archived in the .stk/.itk * Then, for each files : * + 13 bytes : the filename, terminated by '\0'. In original, there's * garbage after if the filename has not the maximum length * + 4 bytes : size of the chunk * + 4 bytes : start position of the chunk in the file * + 1 byte : If 0 : not compressed, if 1 : compressed * * The duplicate files are defined using the same information * as the one of the replacement file. */ void CompressGob::rewriteHeader(Common::File &stk, uint16 chunkCount, Chunk *chunks) { uint16 i; char buffer[1024]; Chunk *curChunk = chunks; stk.rewind(); buffer[0] = chunkCount & 0xFF; buffer[1] = chunkCount >> 8; stk.write(buffer, 2); // TODO : Implement STK21 while (curChunk) { for (i = 0; i < 13; i++) if (i < strlen(curChunk->name)) buffer[i] = curChunk->name[i]; else buffer[i] = '\0'; stk.write(buffer, 13); if (curChunk->packed == 2) { buffer[0] = curChunk->replChunk->size; buffer[1] = curChunk->replChunk->size >> 8; buffer[2] = curChunk->replChunk->size >> 16; buffer[3] = curChunk->replChunk->size >> 24; buffer[4] = curChunk->replChunk->offset; buffer[5] = curChunk->replChunk->offset >> 8; buffer[6] = curChunk->replChunk->offset >> 16; buffer[7] = curChunk->replChunk->offset >> 24; buffer[8] = curChunk->replChunk->packed; } else {
void writeSoundNames(const char *sourceFilename, Common::File &target, uint offset) { Common::File source; if (!source.open(sourceFilename)) { error("Unable to open '%s'", sourceFilename); } source.seek(offset); // Count the sounds uint count = 0; while (1) { uint32 id = source.readUint32LE(); if (!id) break; source.skip(32); count++; } target.writeLong(count); source.seek(offset); for (uint i = 0; i < count; i++) { uint32 id = source.readUint32LE(); char name[32]; source.read(name, sizeof(name)); target.writeLong(id); target.write(name, sizeof(name)); } source.close(); }
void writeBitmap(const char *name, Common::File *file) { outputFile.seek(dataOffset); // Write out the necessary bitmap header so that the ScummVM // BMP decoder can properly handle decoding the bitmaps outputFile.write("BM", 2); outputFile.writeLong(file->size() + 14); // Filesize outputFile.writeLong(0); // res1 & res2 outputFile.writeLong(0x436); // image offset outputFile.write(*file, file->size()); writeEntryHeader(name, dataOffset, file->size() + 14); dataOffset += file->size() + 14; delete file; }
void writeParrotLobbyLinkUpdaterEntries() { static const int OFFSETS[3] = { 0x5A5B38, 0x5A5320, 0x5A4360 }; static const int COUNTS[5] = { 7, 5, 6, 9, 1 }; static const int SKIP[5] = { 36, 36, 40, 36, 0 }; uint recordOffset = OFFSETS[_version], linkOffset; byte vals[8]; outputFile.seek(dataOffset); for (int groupNum = 0; groupNum < 4; ++groupNum) { for (int entryNum = 0; entryNum < COUNTS[groupNum]; ++entryNum, recordOffset += 36) { inputFile.seek(recordOffset - FILE_DIFF[_version]); linkOffset = inputFile.readUint32LE(); for (int idx = 0; idx < 8; ++idx) vals[idx] = inputFile.readUint32LE(); // Write out the entry inputFile.seek(linkOffset - FILE_DIFF[_version]); outputFile.writeString(inputFile); outputFile.write(vals, 8); } // Skip space between groups recordOffset += SKIP[groupNum]; } uint size = outputFile.size() - dataOffset; writeEntryHeader("DATA/PARROT_LOBBY_LINK_UPDATOR", dataOffset, size); dataOffset += size; }
void MemoryBlock::saveToFile(const Common::String &filename) { Common::File *f = new Common::File(); f->open(filename.c_str(), Common::File::kFileWriteMode); f->write(_data, _size); f->close(); delete f; }
void writeResource(const char *name, Common::File *file) { outputFile.seek(dataOffset); outputFile.write(*file, file->size()); writeEntryHeader(name, dataOffset, file->size()); dataOffset += file->size(); delete file; }
void writeHeader() { // Write out magic string const char *MAGIC_STR = "SVTN"; outputFile.write(MAGIC_STR, 4); // Write out version number outputFile.writeWord(VERSION_NUMBER); }
void copyData(Common::File &temp, Common::File &target) { uint dataSize = temp.size(); byte *data = new byte[dataSize]; temp.seek(0); temp.read(data, dataSize); target.write(data, dataSize); delete[] data; }
void writeStarfieldPoints2() { outputFile.seek(dataOffset); const int OFFSETS[3] = { 0x5A2F28, 0x5A2CC8, 0x5A1CF8 }; for (int rootCtr = 0; rootCtr < 80; ++rootCtr) { inputFile.seek(OFFSETS[_version] - FILE_DIFF[_version] + rootCtr * 8); uint offset = inputFile.readUint32LE(); uint count = inputFile.readUint32LE(); outputFile.writeLong(count); inputFile.seek(offset - FILE_DIFF[_version]); outputFile.write(inputFile, count * 4 * 4); } uint size = outputFile.size() - dataOffset; outputFile.write(inputFile, size); writeEntryHeader("STARFIELD/POINTS2", dataOffset, size); dataOffset += size; }
void writeStarfieldPoints() { outputFile.seek(dataOffset); const int OFFSETS[3] = { 0x59DE4C, 0x59DBEC, 0x59CC1C }; inputFile.seek(OFFSETS[_version] - FILE_DIFF[_version]); uint size = 876 * 12; outputFile.write(inputFile, size); writeEntryHeader("STARFIELD/POINTS", dataOffset, size); dataOffset += size; }
uint32 CompressTouche::compress_sound_data_file(uint32 current_offset, Common::File &output, Common::File &input, uint32 *offs_table, uint32 *size_table, int len) { int i, size; uint8 buf[2048]; uint32 start_offset = current_offset; /* write 0 offsets/sizes table */ for (i = 0; i < len; ++i) { offs_table[i] = input.readUint32LE(); size_table[i] = input.readUint32LE(); output.writeUint32LE(0); output.writeUint32LE(0); current_offset += 8; } for (i = 0; i < len; ++i) { if (size_table[i] == 0) { offs_table[i] = 0; } else { input.seek(offs_table[i], SEEK_SET); input.read_throwsOnError(buf, 8); if (memcmp(buf, "Creative", 8) != 0) { error("Invalid VOC data found"); } print("VOC found (pos = %d) :", offs_table[i]); input.seek(18, SEEK_CUR); extractAndEncodeVOC(TEMP_RAW, input, _format); /* append converted data to output file */ Common::File temp(tempEncoded, "rb"); size_table[i] = 0; while ((size = temp.read_noThrow(buf, 2048)) > 0) { output.write(buf, size); size_table[i] += size; } offs_table[i] = current_offset; current_offset += size_table[i]; } } /* fix data offsets table */ output.seek(start_offset, SEEK_SET); for (i = 0; i < len; ++i) { output.writeUint32LE(offs_table[i]); output.writeUint32LE(size_table[i]); } output.seek(0, SEEK_END); return current_offset; }
void writeScriptData(const char *sourceFilename, Common::File &target, RoomScripts *scripts, uint scriptCount) { Common::File source; if (!source.open(sourceFilename)) { error("Unable to open '%s'", sourceFilename); } for (uint i = 0; i < scriptCount; i++) { source.seek(scripts[i].sourceOffset); scripts[i].targetOffset = target.pos(); byte *buffer = new byte[scripts[i].size]; source.read(buffer, scripts[i].size); target.write(buffer, scripts[i].size); delete[] buffer; } source.close(); }
uint32 CompressSword2::append_to_file(Common::File &f1, const char *filename) { uint32 length, orig_length; size_t size; char fbuf[2048]; Common::File f2(filename, "rb"); orig_length = length = f2.size(); while (length > 0) { size = f2.read_noThrow(fbuf, length > sizeof(fbuf) ? sizeof(fbuf) : length); if (size <= 0) { break; } length -= size; f1.write(fbuf, size); } return orig_length; }
int16 readVolCnf() { int i; Common::File fileHandle; short int sizeHEntry; volumeDataLoaded = 0; for (i = 0; i < 20; i++) { volumeData[i].ident[0] = 0; volumeData[i].ptr = NULL; volumeData[i].diskNumber = i + 1; volumeData[i].size = 0; } fileHandle.open("VOL.CNF"); if (!fileHandle.isOpen()) { return (0); } numOfDisks = fileHandle.readSint16BE(); sizeHEntry = fileHandle.readSint16BE(); // size of one header entry - 20 bytes for (i = 0; i < numOfDisks; i++) { // fread(&volumeData[i],20,1,fileHandle); fileHandle.read(&volumeData[i].ident, 10); fileHandle.read(&volumeData[i].ptr, 4); volumeData[i].diskNumber = fileHandle.readSint16BE(); volumeData[i].size = fileHandle.readSint32BE(); debug(1, "Disk number: %d", volumeData[i].diskNumber); } for (i = 0; i < numOfDisks; i++) { dataFileName *ptr; volumeData[i].size = fileHandle.readSint32BE(); ptr = (dataFileName *) mallocAndZero(volumeData[i].size); volumeData[i].ptr = ptr; if (!ptr) { fileHandle.close(); return (-2); } fileHandle.read(ptr, volumeData[i].size); } fileHandle.close(); volumeDataLoaded = 1; //#define dumpResources #ifdef dumpResources for (i = 0; i < numOfDisks; i++) { int j; char nameBuffer[256]; fileEntry *buffer; sprintf(nameBuffer, "D%d.", i + 1); fileHandle.open(nameBuffer); short int numEntry; short int sizeEntry; numEntry = fileHandle.readSint16BE(); sizeEntry = fileHandle.readSint16BE(); buffer = (fileEntry *) mallocAndZero(numEntry * sizeEntry); for (j = 0; j < numEntry; j++) { fileHandle.seek(4 + j*0x1E); fileHandle.read(buffer[j].name, 14); buffer[j].offset = fileHandle.readSint32BE(); buffer[j].size = fileHandle.readSint32BE(); buffer[j].extSize = fileHandle.readSint32BE(); buffer[j].unk3 = fileHandle.readSint32BE(); fileHandle.seek(buffer[j].offset); char *bufferLocal; bufferLocal = (char *)mallocAndZero(buffer[j].size); fileHandle.read(bufferLocal, buffer[j].size); char nameBuffer[256]; sprintf(nameBuffer, "%s", buffer[j].name); if (buffer[j].size == buffer[j].extSize) { Common::DumpFile fout; fout.open(nameBuffer); if (fout.isOpen()) fout.write(bufferLocal, buffer[j].size); } else { char *uncompBuffer = (char *)mallocAndZero(buffer[j].extSize + 500); delphineUnpack((uint8 *) uncompBuffer, (const uint8 *) bufferLocal, buffer[j].size); Common::File fout; fout.open(nameBuffer, Common::File::kFileWriteMode); if (fout.isOpen()) fout.write(uncompBuffer, buffer[j].extSize); //MemFree(uncompBuffer); } MemFree(bufferLocal); } fileHandle.close(); } #endif return (1); }
byte *ResourceManager::openResource(uint32 res, bool dump) { assert(res < _totalResFiles); // Is the resource in memory already? If not, load it. if (!_resList[res].ptr) { // Fetch the correct file and read in the correct portion. uint16 cluFileNum = _resConvTable[res * 2]; // points to the number of the ascii filename assert(cluFileNum != 0xffff); // Relative resource within the file // First we have to find the file via the _resConvTable uint16 actual_res = _resConvTable[(res * 2) + 1]; debug(5, "openResource %s res %d", _resFiles[cluFileNum].fileName, res); // If we're loading a cluster that's only available from one // of the CDs, remember which one so that we can play the // correct speech and music. setCD(_resFiles[cluFileNum].cd); // Actually, as long as the file can be found we don't really // care which CD it's on. But if we can't find it, keep asking // for the CD until we do. Common::File *file = openCluFile(cluFileNum); if (_resFiles[cluFileNum].entryTab == NULL) { // we didn't read from this file before, get its index table readCluIndex(cluFileNum, file); } uint32 pos = _resFiles[cluFileNum].entryTab[actual_res * 2 + 0]; uint32 len = _resFiles[cluFileNum].entryTab[actual_res * 2 + 1]; file->seek(pos, SEEK_SET); debug(6, "res len %d", len); // Ok, we know the length so try and allocate the memory. _resList[res].ptr = _vm->_memory->memAlloc(len, res); _resList[res].size = len; _resList[res].refCount = 0; file->read(_resList[res].ptr, len); debug(3, "Loaded resource '%s' from '%s' on CD %d (%d)", fetchName(_resList[res].ptr), _resFiles[cluFileNum].fileName, getCD(), _resFiles[cluFileNum].cd); if (dump) { char buf[256]; const char *tag; Common::File out; switch (fetchType(_resList[res].ptr)) { case ANIMATION_FILE: tag = "anim"; break; case SCREEN_FILE: tag = "layer"; break; case GAME_OBJECT: tag = "object"; break; case WALK_GRID_FILE: tag = "walkgrid"; break; case GLOBAL_VAR_FILE: tag = "globals"; break; case PARALLAX_FILE_null: tag = "parallax"; // Not used! break; case RUN_LIST: tag = "runlist"; break; case TEXT_FILE: tag = "text"; break; case SCREEN_MANAGER: tag = "screen"; break; case MOUSE_FILE: tag = "mouse"; break; case WAV_FILE: tag = "wav"; break; case ICON_FILE: tag = "icon"; break; case PALETTE_FILE: tag = "palette"; break; default: tag = "unknown"; break; } #if defined(MACOS_CARBON) sprintf(buf, ":dumps:%s-%d.dmp", tag, res); #else sprintf(buf, "dumps/%s-%d.dmp", tag, res); #endif if (!Common::File::exists(buf)) { if (out.open(buf, Common::File::kFileWriteMode)) out.write(_resList[res].ptr, len); } } // close the cluster file->close(); delete file; _usedMem += len; checkMemUsage(); } else if (_resList[res].refCount == 0) removeFromCacheList(_resList + res); _resList[res].refCount++; return _resList[res].ptr; }
void ExtractFascinationCD::execute(void) { if (_outputPath.empty()) _outputPath.setFullPath("./"); // Open ISO file Common::File file(_inputPaths[0].path, "rb"); assert(file.isOpen()); uint32 fileSize = file.size(); // Sanity check the file size if (fileSize > (16 * 1024 * 1024)) { error("'%s' is too large to be a Fascination mode1/2048 ISO", _inputPaths[0].path.c_str()); } if (fileSize < (8 * 1024 * 1024)) { error("'%s' is too small to be a Fascination mode1/2048 ISO", _inputPaths[0].path.c_str()); } if (fileSize % 2048) { error("'%s' doesn't appear to be a mode1/2048 ISO", _inputPaths[0].path.c_str()); } // Load ISO file to memory. (Should only be ~10MB, and this simplifies the code) byte *data = new byte[fileSize]; file.read_noThrow(data, fileSize); file.close(); print("Loaded '%s' (%d bytes)\n", _inputPaths[0].path.c_str(), fileSize); for (uint32 i = 0; i < ARRAYSIZE(stkFile); i++) { // initialize curPos to start of file byte *curPos = data; while (curPos < data + fileSize) { // search for known first entry of STK files if (!memcmp(curPos, stkFile[i].firstEntryName, strlen(stkFile[i].firstEntryName))) { byte *stkFileStart = curPos - 2; // the actual STK start is 2 bytes prior uint16 numStkEntries = READ_LE_UINT16(stkFileStart); // read number of entries in STK file assert(numStkEntries > 0 && numStkEntries < 0xFF); // Determine length of file by adding offset and size of the last entry const uint32 lastEntrySize = READ_LE_UINT32(curPos + ((numStkEntries - 1) * STK_HEADER_ENTRY_SIZE) + 13); const uint32 lastEntryOffset = READ_LE_UINT32(curPos + ((numStkEntries - 1) * STK_HEADER_ENTRY_SIZE) + 17); const uint32 stkEntrySize = lastEntryOffset + lastEntrySize; print("Found '%s' at %x (size: %d). Extracting...\n", stkFile[i].stkFilename, curPos - data - 2, stkEntrySize); // write STK file Common::File output; _outputPath.setFullName(stkFile[i].stkFilename); output.open(_outputPath, "wb"); assert(output.isOpen()); output.write(stkFileStart, stkEntrySize); output.close(); stkFile[i].extracted = true; curPos += stkEntrySize; } curPos++; } } for (int i = 0; i < ARRAYSIZE(stkFile); i++) { if (!stkFile[i].extracted) error("A problem occurred: '%s' has NOT been extracted", stkFile[i].stkFilename); } delete[] data; }