Пример #1
0
/**
 * 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;
}
Пример #2
0
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;
}