int AgiEngine::loadObjects(const char *fname) { Common::File fp; uint32 flen; uint8 *mem; _objects = NULL; _game.numObjects = 0; debugC(5, kDebugLevelResources, "(Loading objects '%s')", fname); if (!fp.open(fname)) return errBadFileOpen; fp.seek(0, SEEK_END); flen = fp.pos(); fp.seek(0, SEEK_SET); if ((mem = (uint8 *)calloc(1, flen + 32)) == NULL) { fp.close(); return errNotEnoughMemory; } fp.read(mem, flen); fp.close(); decodeObjects(mem, flen); free(mem); return errOK; }
void SoundHE::setupHEMusicFile() { int i, total_size; Common::File musicFile; Common::String buf(_vm->generateFilename(-4)); if (musicFile.open(buf) == true) { musicFile.seek(4, SEEK_SET); total_size = musicFile.readUint32BE(); musicFile.seek(16, SEEK_SET); _heMusicTracks = musicFile.readUint32LE(); debug(5, "Total music tracks %d", _heMusicTracks); int musicStart = (_vm->_game.heversion >= 80) ? 56 : 20; musicFile.seek(musicStart, SEEK_SET); _heMusic = (HEMusic *)malloc((_heMusicTracks + 1) * sizeof(HEMusic)); for (i = 0; i < _heMusicTracks; i++) { _heMusic[i].id = musicFile.readUint32LE(); _heMusic[i].offset = musicFile.readUint32LE(); _heMusic[i].size = musicFile.readUint32LE(); if (_vm->_game.heversion >= 80) { musicFile.seek(+9, SEEK_CUR); } else { musicFile.seek(+13, SEEK_CUR); } } musicFile.close(); } }
int AgiEngine::loadWords(const char *fname) { Common::File fp; uint32 flen; uint8 *mem = NULL; words = NULL; if (!fp.open(fname)) { warning("loadWords: can't open %s", fname); return errOK; // err_BadFileOpen } debug(0, "Loading dictionary: %s", fname); fp.seek(0, SEEK_END); flen = fp.pos(); wordsFlen = flen; fp.seek(0, SEEK_SET); if ((mem = (uint8 *)calloc(1, flen + 32)) == NULL) { fp.close(); return errNotEnoughMemory; } fp.read(mem, flen); fp.close(); words = mem; return errOK; }
void MoviePlayerDXA::readSoundData(Common::SeekableReadStream *stream) { uint32 tag = stream->readUint32BE(); if (tag == MKTAG('W','A','V','E')) { uint32 size = stream->readUint32BE(); if (_sequenceNum) { Common::File in; stream->skip(size); in.open("audio.wav"); if (!in.isOpen()) { error("Can't read offset file 'audio.wav'"); } in.seek(_sequenceNum * 8, SEEK_SET); uint32 offset = in.readUint32LE(); size = in.readUint32LE(); in.seek(offset, SEEK_SET); _bgSoundStream = Audio::makeWAVStream(in.readStream(size), DisposeAfterUse::YES); in.close(); } else { _bgSoundStream = Audio::makeWAVStream(stream->readStream(size), DisposeAfterUse::YES); } } else { _bgSoundStream = Audio::SeekableAudioStream::openStreamFile(baseName); } }
// FIXME/TODO: 아래는 코드 중복 모음 void loadEmergencyFont() { Common::File fp; int numChar = 0; numChar = 2350; if (fp.open("korean.fnt")) { fp.seek(2, SEEK_CUR); _korFontWidth = fp.readByte(); _korFontHeight = fp.readByte(); _korFontPtr = new byte[((_korFontWidth + 7) / 8) * _korFontHeight * numChar]; fp.read(_korFontPtr, ((_korFontWidth + 7) / 8) * _korFontHeight * numChar); fp.close(); warning("V1 한글 폰트가 로드되었습니다.\n"); } else { warning("V1 한글 폰트를 로드할 수 없습니다!\n"); } numChar = 256; if (fp.open("english.fnt")) { fp.seek(2, SEEK_CUR); _engFontWidth = fp.readByte(); _engFontHeight = fp.readByte(); _engFontPtr = new byte[((_engFontWidth + 7) / 8) * _engFontHeight * numChar]; fp.read(_engFontPtr, ((_engFontWidth + 7) / 8) * _engFontHeight * numChar); fp.close(); warning("V1 영문 폰트가 로드되었습니다.\n"); } else { warning("V1 영문 폰트를 로드할 수 없습니다!\n"); } }
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 writeResponseTree() { outputFile.seek(dataOffset); const uint OFFSETS[3] = { 0x619520, 0x618340, 0x617380 }; for (int idx = 0; idx < 1022; ++idx) { inputFile.seek(OFFSETS[_version] - FILE_DIFF[_version] + idx * 8); uint id = inputFile.readLong(); uint offset = inputFile.readLong(); outputFile.writeLong(id); if (!id) { // An end of list id } else if (offset >= OFFSETS[_version] && offset <= (OFFSETS[_version] + 0x1FF0)) { // Offset to another table outputFile.writeByte(0); outputFile.writeLong((offset - OFFSETS[_version]) / 8); } else { // Offset to ASCIIZ string outputFile.writeByte(1); writeString(offset); } } uint size = outputFile.size() - dataOffset; writeEntryHeader("TEXT/TREE", dataOffset, size); dataOffset += size; }
void MoviePlayerDXA::startSound() { uint32 offset, size; if (getSoundTag() == MKID_BE('WAVE')) { size = _fileStream->readUint32BE(); if (_sequenceNum) { Common::File in; _fileStream->seek(size, SEEK_CUR); in.open((const char *)"audio.wav"); if (!in.isOpen()) { error("Can't read offset file 'audio.wav'"); } in.seek(_sequenceNum * 8, SEEK_SET); offset = in.readUint32LE(); size = in.readUint32LE(); in.seek(offset, SEEK_SET); _bgSoundStream = Audio::makeWAVStream(in.readStream(size), DisposeAfterUse::YES); in.close(); } else { _bgSoundStream = Audio::makeWAVStream(_fileStream->readStream(size), DisposeAfterUse::YES); } } else { _bgSoundStream = Audio::SeekableAudioStream::openStreamFile(baseName); } if (_bgSoundStream != NULL) { _vm->_mixer->stopHandle(_bgSound); _vm->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_bgSound, _bgSoundStream); } }
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 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; }
int AgiEngine::loadWords(const char *fname) { Common::File fp; if (!fp.open(fname)) { warning("loadWords: can't open %s", fname); return errOK; // err_BadFileOpen } debug(0, "Loading dictionary: %s", fname); // Loop through alphabet, as words in the dictionary file are sorted by // first character for (int i = 0; i < 26; i++) { fp.seek(i * 2, SEEK_SET); int offset = fp.readUint16BE(); if (offset == 0) continue; fp.seek(offset, SEEK_SET); int k = fp.readByte(); while (!fp.eos() && !fp.err()) { // Read next word char c, str[64]; do { c = fp.readByte(); str[k++] = (c ^ 0x7F) & 0x7F; } while (!(c & 0x80) && k < (int)sizeof(str) - 1); str[k] = 0; // WORKAROUND: // The SQ0 fan game stores words starting with numbers (like '7up') // in its dictionary under the 'a' entry. We skip these. // See bug #3615061 if (str[0] == 'a' + i) { // And store it in our internal dictionary AgiWord *w = new AgiWord; w->word = myStrndup(str, k); w->id = fp.readUint16BE(); _game.words[i].push_back(w); } k = fp.readByte(); // Are there more words with an already known prefix? // WORKAROUND: We only break after already seeing words with the // right prefix, for the SQ0 words starting with digits filed under // 'a'. See above comment and bug #3615061. if (k == 0 && str[0] >= 'a' + i) break; } } return errOK; }
void ExtractCine::unpackFile(Common::File &file) { char fileName[15]; unsigned int entryCount = file.readUint16BE(); // How many entries? unsigned int entrySize = file.readUint16BE(); // How many bytes per entry? assert(entrySize == 0x1e); while (entryCount--) { file.read_throwsOnError(fileName, 14); fileName[14] = '\0'; Common::Filename outPath(_outputPath); outPath.setFullName(fileName); uint32 offset = file.readUint32BE(); unsigned int packedSize = file.readUint32BE(); unsigned int unpackedSize = file.readUint32BE(); // Skip one file.readUint32BE(); unsigned int savedPos = file.pos(); print("unpacking '%s' ... ", outPath.getFullName().c_str()); Common::File fpOut(outPath, "wb"); file.seek(offset, SEEK_SET); assert(unpackedSize >= packedSize); uint8 *data = (uint8 *)calloc(unpackedSize, 1); uint8 *packedData = (uint8 *)calloc(packedSize, 1); assert(data); assert(packedData); file.read_throwsOnError(packedData, packedSize); bool status = true; if (packedSize != unpackedSize) { CineUnpacker cineUnpacker; status = cineUnpacker.unpack(packedData, packedSize, data, unpackedSize); } else { memcpy(data, packedData, packedSize); } free(packedData); fpOut.write(data, unpackedSize); free(data); if (!status) { print("CRC ERROR"); } else { print("ok"); } print(", packedSize %u unpackedSize %u", packedSize, unpackedSize); file.seek(savedPos, SEEK_SET); } }
byte *Sword2Engine::fetchPsxBackground(uint32 location) { Common::File file; PSXScreensEntry header; uint32 screenOffset, dataOffset; uint32 totSize; // Total size of background, counting data, offset table and additional header byte *buffer; if (!file.open("screens.clu")) { GUIErrorMessage("Broken Sword 2: Cannot open screens.clu"); return NULL; } file.seek(location * 4, SEEK_SET); screenOffset = file.readUint32LE(); if (screenOffset == 0) { // We don't have screen data for this location number. file.close(); return NULL; } // Get to the beginning of PSXScreensEntry file.seek(screenOffset + ResHeader::size(), SEEK_SET); buffer = (byte *)malloc(PSXScreensEntry::size()); file.read(buffer, PSXScreensEntry::size()); // Prepare the header header.read(buffer); free(buffer); file.seek(screenOffset + header.bgOffset + 4, SEEK_SET); dataOffset = file.readUint32LE(); file.seek(screenOffset + header.bgOffset, SEEK_SET); totSize = header.bgSize + (dataOffset - header.bgOffset) + 8; buffer = (byte *)malloc(totSize); // Write some informations before background data WRITE_LE_UINT16(buffer, header.bgXres); WRITE_LE_UINT16(buffer + 2, header.bgYres); WRITE_LE_UINT32(buffer + 4, header.bgOffset); file.read(buffer + 8, totSize - 8); // Do not write on the header file.close(); return buffer; }
void AGOSEngine::decompressData(const char *srcName, byte *dst, uint32 offset, uint32 srcSize, uint32 dstSize) { #ifdef USE_ZLIB Common::File in; in.open(srcName); if (in.isOpen() == false) error("decompressData: Can't load %s", srcName); in.seek(offset, SEEK_SET); if (srcSize != dstSize) { byte *srcBuffer = (byte *)malloc(srcSize); if (in.read(srcBuffer, srcSize) != srcSize) error("decompressData: Read failed"); unsigned long decompressedSize = dstSize; if (!Common::uncompress(dst, &decompressedSize, srcBuffer, srcSize)) error("decompressData: Zlib uncompress error"); free(srcBuffer); } else { if (in.read(dst, dstSize) != dstSize) error("decompressData: Read failed"); } in.close(); #else error("Zlib support is required for Amiga and Macintosh versions"); #endif }
Common::SeekableReadStream *Hqr::createReadStreamForIndex(int index) const { if (index >= _numIndices) return 0; uint32 realSize; uint32 compressedSize; uint16 mode; Common::File *file = new Common::File(); file->open(_hqrFileName); file->seek(_indices[index]); realSize = file->readUint32LE(); compressedSize = file->readUint32LE(); mode = file->readUint16LE(); uint32 begin = _indices[index] + 10; uint32 end = 0; if (mode == 0) { end = begin + realSize; } else { end = begin + compressedSize; } Common::SeekableReadStream *stream = new Common::SeekableSubReadStream(file, begin, end, DisposeAfterUse::YES); if (mode != 0) { stream = new LzssReadStream(stream, mode, realSize); } return stream; }
/** * Read the encrypted text from the boot file and print it */ void FileManager::printBootText() { debugC(1, kDebugFile, "printBootText()"); Common::File ofp; if (!ofp.open(getBootFilename())) { if (_vm->_gameVariant == kGameVariantH1Dos) { //TODO initialize properly _boot structure warning("printBootText - Skipping as H1 Dos may be a freeware"); return; } else { error("Missing startup file '%s'", getBootFilename()); } } // Allocate space for the text and print it char *buf = (char *)malloc(_vm->_boot.exit_len + 1); if (buf) { // Skip over the boot structure (already read) and read exit text ofp.seek((long)sizeof(_vm->_boot), SEEK_SET); if (ofp.read(buf, _vm->_boot.exit_len) != (size_t)_vm->_boot.exit_len) error("Error while reading startup file"); // Decrypt the exit text, using CRYPT substring int i; for (i = 0; i < _vm->_boot.exit_len; i++) buf[i] ^= s_bootCyper[i % s_bootCyperLen]; buf[i] = '\0'; Utils::notifyBox(buf); } free(buf); ofp.close(); }
// Dumps all of the game's music in external XMIDI *.xmi files void dumpMusic() { Common::File midiFile; Common::DumpFile outFile; char outName[20]; midiFile.open(MIDI_FILE); int outFileSize = 0; char buffer[20000]; const int total = 155; // maximum (SCN version) for (int i = 0; i < total; i++) { if (midiOffsets[i] == 0) break; sprintf(outName, "track%03d.xmi", i + 1); outFile.open(outName); if (i < total - 1) outFileSize = midiOffsets[i + 1] - midiOffsets[i] - 4; else outFileSize = midiFile.size() - midiOffsets[i] - 4; midiFile.seek(midiOffsets[i] + 4, SEEK_SET); assert(outFileSize < 20000); midiFile.read(buffer, outFileSize); outFile.write(buffer, outFileSize); outFile.close(); } midiFile.close(); }
/** * This function does noting but load a raw resource into memory, * if further decoding is required, it must be done by another * routine. NULL is returned if unsucsessfull. */ uint8 *AgiLoader_v2::loadVolRes(struct AgiDir *agid) { uint8 *data = NULL; char x[MAXPATHLEN], *path; Common::File fp; unsigned int sig; sprintf(x, "vol.%i", agid->volume); path = x; debugC(3, kDebugLevelResources, "Vol res: path = %s", path); if (agid->offset != _EMPTY && fp.open(path)) { debugC(3, kDebugLevelResources, "loading resource at offset %d", agid->offset); fp.seek(agid->offset, SEEK_SET); fp.read(&x, 5); if ((sig = READ_BE_UINT16((uint8 *) x)) == 0x1234) { agid->len = READ_LE_UINT16((uint8 *) x + 3); data = (uint8 *) calloc(1, agid->len + 32); if (data != NULL) { fp.read(data, agid->len); } else { exit(1); } } else { warning("AgiLoader_v2::loadVolRes: bad signature %04x", sig); return 0; } fp.close(); } else { // we have a bad volume resource // set that resource to NA agid->offset = _EMPTY; } return data; }
int AgiEngine::loadWords_v1(Common::File &f) { char str[64]; int k; debug(0, "Loading dictionary"); // Loop through alphabet, as words in the dictionary file are sorted by // first character f.seek(f.pos() + 26 * 2, SEEK_SET); do { // Read next word for (k = 0; k < (int)sizeof(str) - 1; k++) { str[k] = f.readByte(); if (str[k] == 0 || (uint8)str[k] == 0xFF) break; } // And store it in our internal dictionary if (k > 0) { AgiWord *w = new AgiWord; w->word = myStrndup(str, k + 1); w->id = f.readUint16LE(); _game.words[str[0] - 'a'].push_back(w); debug(3, "'%s' (%d)", w->word, w->id); } } while((uint8)str[0] != 0xFF); return errOK; }
void writeSentenceMappings(const char *name, uint offset, int numValues) { inputFile.seek(offset - FILE_DIFF[_version]); outputFile.seek(dataOffset); uint id; while ((id = inputFile.readLong()) != 0) { outputFile.writeLong(id); for (int ctr = 0; ctr < numValues; ++ctr) outputFile.writeLong(inputFile.readLong()); } uint size = outputFile.size() - dataOffset; writeEntryHeader(name, dataOffset, size); dataOffset += size; }
Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::String &name) const { CCEntry ccEntry; if (getHeaderEntry(name, ccEntry)) { // Open the correct CC file Common::File f; if (!f.open(_filename)) error("Could not open CC file"); // Read in the data for the specific resource f.seek(ccEntry._offset); byte *data = (byte *)malloc(ccEntry._size); f.read(data, ccEntry._size); if (_encoded) { // Decrypt the data for (int i = 0; i < ccEntry._size; ++i) data[i] ^= 0x35; } // Return the data as a stream return new Common::MemoryReadStream(data, ccEntry._size, DisposeAfterUse::YES); } return nullptr; }
/*! \brief Write the body of the STK archive * \param stk STK/ITK archive file * \param chunks Chunk list * * This function writes the body of the STK archive by storing or compressing * (or skipping duplicate files) the files. It also updates the chunk information * with the size of the chunk in the archive, the compression method (if modified), * ... */ void CompressGob::writeBody(Common::Filename *inpath, Common::File &stk, Chunk *chunks) { Chunk *curChunk = chunks; Common::File src; while (curChunk) { inpath->setFullName(curChunk->name); src.open(*inpath, "rb"); if (curChunk->packed == 2) print("Identical file %12s\t(compressed size %d bytes)", curChunk->name, curChunk->replChunk->size); curChunk->offset = stk.pos(); if (curChunk->packed == 1) { curChunk->size = writeBodyPackFile(stk, src); if (curChunk->size >= curChunk->realSize) { // If compressed size >= realsize, compression is useless // => Store instead curChunk->packed = 0; stk.seek(curChunk->offset, SEEK_SET); src.rewind(); } else print("Compressing %12s\t%d -> %d bytes", curChunk->name, curChunk->realSize, curChunk->size); } if (curChunk->packed == 0) { curChunk->size = writeBodyStoreFile(stk, src); print("Storing %12s\t%d bytes", curChunk->name, curChunk->size); } curChunk = curChunk->next; } }
/** * Read uif item into supplied buffer. */ void FileManager::readUIFItem(const int16 id, byte *buf) { debugC(1, kDebugFile, "readUIFItem(%d, ...)", id); // Open uif file to read data Common::File ip; // UIF_FILE handle if (!ip.open(getUifFilename())) error("File not found: %s", getUifFilename()); // Seek to data UifHdr *_UIFHeaderPtr = getUIFHeader((Uif)id); ip.seek(_UIFHeaderPtr->_offset, SEEK_SET); // We support pcx images and straight data Seq *dummySeq; // Dummy Seq for image data switch (id) { case UIF_IMAGES: // Read uif images file dummySeq = readPCX(ip, 0, buf, true, getUifFilename()); free(dummySeq); break; default: // Read file data into supplied array if (ip.read(buf, _UIFHeaderPtr->_size) != _UIFHeaderPtr->_size) error("Wrong UIF file format"); break; } ip.close(); }
void NDSFile::load() { Common::File nds; open(nds); if (!isNDS(nds)) throw Common::Exception("Not a support NDS ROM file"); nds.seek(0x40); uint32 fileNameTableOffset = nds.readUint32LE(); uint32 fileNameTableLength = nds.readUint32LE(); uint32 fatOffset = nds.readUint32LE(); //uint32 fatLength = nds.readUint32LE(); try { readNames(nds, fileNameTableOffset, fileNameTableLength); readFAT(nds, fatOffset); if (nds.err()) throw Common::Exception(Common::kReadError); } catch (Common::Exception &e) { e.add("Failed reading NDS file"); throw; } }
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 writeString(uint offset) { inputFile.seek(offset - FILE_DIFF[_version]); char c; do { c = inputFile.readByte(); outputFile.writeByte(c); } while (c); }
void writeSentenceEntries(const char *name, uint tableOffset) { outputFile.seek(dataOffset); uint v1, v2, v9, v11, v12, v13; uint offset3, offset5, offset6, offset7, offset8, offset10; for (uint idx = 0; ; ++idx) { inputFile.seek(tableOffset - FILE_DIFF[_version] + idx * 0x34); v1 = inputFile.readLong(); if (!v1) // Reached end of list break; // Read data fields v2 = inputFile.readLong(); offset3 = inputFile.readLong(); /* v4 = */inputFile.readLong(); offset5 = inputFile.readLong(); offset6 = inputFile.readLong(); offset7 = inputFile.readLong(); offset8 = inputFile.readLong(); v9 = inputFile.readLong(); offset10 = inputFile.readLong(); v11 = inputFile.readLong(); v12 = inputFile.readLong(); v13 = inputFile.readLong(); outputFile.writeLong(v1); outputFile.writeLong(v2); writeString(offset3); outputFile.writeLong(v1); writeString(offset5); writeString(offset6); writeString(offset7); writeString(offset8); outputFile.writeLong(v9); writeString(offset10); outputFile.writeLong(v11); outputFile.writeLong(v12); outputFile.writeLong(v13); } uint size = outputFile.size() - dataOffset; writeEntryHeader(name, dataOffset, size); dataOffset += size; }
Common::SeekableReadStream *MADSResourceManager::loadResource(const char *resourceName, bool loadFlag) { Common::File hagFile; uint32 offset = 0, size = 0; // If the first character is a '@' then look for an external file if (*resourceName == '@') { ++resourceName; hagFile.open(resourceName); if (loadFlag) return hagFile.readStream(hagFile.size()); else return new Common::SeekableSubReadStream(&hagFile, 0, hagFile.size()); } // If the first character is the wildcard (resource indicator), skip over it if (*resourceName == '*') ++resourceName; char resName[20]; strcpy(resName, resourceName); str_upper(resName); hagFile.open(getResourceFilename(resName)); // Validate hag file header char headerBuffer[16]; if ((hagFile.read(headerBuffer, 16) != 16) || (strncmp(headerBuffer, madsConcatString, 10) != 0)) error("Invalid HAG file opened"); int numEntries = hagFile.readUint16LE(); int resIndex = -1; while (++resIndex < numEntries) { // Read in the details of the next resource char resourceBuffer[14]; offset = hagFile.readUint32LE(); size = hagFile.readUint32LE(); hagFile.read(resourceBuffer, 14); if (!strcmp(resName, resourceBuffer)) break; } if (resIndex == numEntries) error("Invalid resource '%s' specified", resourceName); // Get the resource, either loading it in it's entirely or getting a stream reference if (loadFlag) { hagFile.seek(offset); return hagFile.readStream(size); } else { return new Common::SeekableSubReadStream(&hagFile, offset, offset + size); } }
void writeEntryHeader(const char *name, uint offset, uint size) { assert(headerOffset < HEADER_SIZE); outputFile.seek(headerOffset); outputFile.writeLong(offset); outputFile.writeLong(size); outputFile.writeString(name); headerOffset += 8 + strlen(name) + 1; }