/** * Gets a resource from the currently loaded section */ byte *TLib::getResource(uint16 id, bool suppressErrors) { // Scan for an entry for the given Id ResourceEntry *re = NULL; ResourceList::iterator iter; for (iter = _resources.begin(); iter != _resources.end(); ++iter) { if ((*iter).id == id) { re = &(*iter); break; } } if (!re) { if (suppressErrors) return NULL; error("Could not find resource Id #%d", id); } if (!re->isCompressed) { // Read in the resource data and return it byte *dataP = _memoryManager.allocate2(re->size); _file.seek(_sections.fileOffset + re->fileOffset); _file.read(dataP, re->size); return dataP; } /* * Decompress the data block */ _file.seek(_sections.fileOffset + re->fileOffset); Common::ReadStream *compStream = _file.readStream(re->size); BitReader bitReader(*compStream); byte *dataOut = _memoryManager.allocate2(re->uncompressedSize); byte *destP = dataOut; uint bytesWritten = 0; uint16 ctrCurrent = 0x102, ctrMax = 0x200; uint16 word_48050 = 0, currentToken = 0, word_48054 =0; byte byte_49068 = 0, byte_49069 = 0; const uint tableSize = 0x1000; DecodeReference *table = (DecodeReference *)malloc(tableSize * sizeof(DecodeReference)); if (!table) error("[TLib::getResource] Cannot allocate table buffer"); for (uint i = 0; i < tableSize; ++i) { table[i].vByte = table[i].vWord = 0; } Common::Stack<uint16> tokenList; for (;;) { // Get the next decode token uint16 token = bitReader.readToken(); // Handle the token if (token == 0x101) { // End of compressed stream break; } else if (token == 0x100) { // Reset bit-rate bitReader.numBits = 9; ctrMax = 0x200; ctrCurrent = 0x102; // Set variables with next token currentToken = word_48050 = bitReader.readToken(); byte_49069 = byte_49068 = (byte)currentToken; ++bytesWritten; assert(bytesWritten <= re->uncompressedSize); *destP++ = byte_49069; } else { word_48054 = word_48050 = token; if (token >= ctrCurrent) { word_48050 = currentToken; tokenList.push(byte_49068); } while (word_48050 >= 0x100) { assert(word_48050 < 0x1000); tokenList.push(table[word_48050].vByte); word_48050 = table[word_48050].vWord; } byte_49069 = byte_49068 = (byte)word_48050; tokenList.push(word_48050); // Write out any cached tokens while (!tokenList.empty()) { ++bytesWritten; assert(bytesWritten <= re->uncompressedSize); *destP++ = tokenList.pop(); } assert(ctrCurrent < 0x1000); table[ctrCurrent].vByte = byte_49069; table[ctrCurrent].vWord = currentToken; ++ctrCurrent; currentToken = word_48054; if ((ctrCurrent >= ctrMax) && (bitReader.numBits != 12)) { // Move to the next higher bit-rate ++bitReader.numBits; ctrMax <<= 1; } } } free(table); assert(bytesWritten == re->uncompressedSize); delete compStream; return dataOut; }
bool AGOSEngine::loadVGASoundFile(uint16 id, uint8 type) { Common::File in; char filename[15]; byte *dst; uint32 srcSize, dstSize; if (getPlatform() == Common::kPlatformAmiga || getPlatform() == Common::kPlatformAtariST) { if (getGameType() == GType_ELVIRA1 && (getFeatures() & GF_DEMO) && getPlatform() == Common::kPlatformAmiga) { sprintf(filename, "%c%d.out", 48 + id, type); } else if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2) { sprintf(filename, "%.2d%d.out", id, type); } else if (getGameType() == GType_PN) { sprintf(filename, "%c%d.in", id + 48, type); } else { sprintf(filename, "%.3d%d.out", id, type); } } else { if (getGameType() == GType_ELVIRA1) { if (elvira1_soundTable[id] == 0) return false; sprintf(filename, "%.2d.SND", elvira1_soundTable[id]); } else if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) { sprintf(filename, "%.2d%d.VGA", id, type); } else if (getGameType() == GType_PN) { sprintf(filename, "%c%d.out", id + 48, type); } else { sprintf(filename, "%.3d%d.VGA", id, type); } } in.open(filename); if (in.isOpen() == false || in.size() == 0) { return false; } dstSize = srcSize = in.size(); if (getGameType() == GType_PN && (getFeatures() & GF_CRUNCHED)) { Common::Stack<uint32> data; byte *dataOut = 0; int dataOutSize = 0; for (uint i = 0; i < srcSize / 4; ++i) data.push(in.readUint32BE()); decompressPN(data, dataOut, dataOutSize); dst = allocBlock (dataOutSize); memcpy(dst, dataOut, dataOutSize); delete[] dataOut; } else if (getGameType() == GType_ELVIRA1 && getFeatures() & GF_DEMO) { byte *srcBuffer = (byte *)malloc(srcSize); if (in.read(srcBuffer, srcSize) != srcSize) error("loadVGASoundFile: Read failed"); dstSize = READ_BE_UINT32(srcBuffer + srcSize - 4); dst = allocBlock (dstSize); decrunchFile(srcBuffer, dst, srcSize); free(srcBuffer); } else { dst = allocBlock(dstSize); if (in.read(dst, dstSize) != dstSize) error("loadVGASoundFile: Read failed"); } in.close(); return true; }