예제 #1
0
/*! \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 {
예제 #2
0
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();
}
예제 #3
0
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;
}
예제 #4
0
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;
}
예제 #5
0
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;
}
예제 #6
0
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;
}
예제 #7
0
void writeHeader() {
	// Write out magic string
	const char *MAGIC_STR = "SVTN";
	outputFile.write(MAGIC_STR, 4);

	// Write out version number
	outputFile.writeWord(VERSION_NUMBER);
}
예제 #8
0
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;
}
예제 #9
0
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;
}
예제 #10
0
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;
}
예제 #11
0
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;
}
예제 #12
0
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();
}
예제 #13
0
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;
}
예제 #14
0
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);
}
예제 #15
0
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;
}