diff options
| -rw-r--r-- | engines/gob/dataio.cpp | 262 | ||||
| -rw-r--r-- | engines/gob/dataio.h | 66 | 
2 files changed, 182 insertions, 146 deletions
diff --git a/engines/gob/dataio.cpp b/engines/gob/dataio.cpp index 99cf7c1193..3b7a61d485 100644 --- a/engines/gob/dataio.cpp +++ b/engines/gob/dataio.cpp @@ -35,21 +35,22 @@ namespace Gob {  DataStream::DataStream(DataIO &io, int16 handle, uint32 dSize, bool dispose) {  	_io = &io; -	_handle = handle; -	_size = dSize; + +	_handle  = handle; +	_size    = dSize;  	_dispose = dispose; -	_data = 0; +	_data   = 0;  	_stream = 0;  }  DataStream::DataStream(byte *buf, uint32 dSize, bool dispose) { -	_data = buf; -	_size = dSize; -	_stream = new Common::MemoryReadStream(_data, _size); +	_data    = buf; +	_size    = dSize; +	_stream  = new Common::MemoryReadStream(_data, _size);  	_dispose = dispose; -	_io = 0; +	_io     =  0;  	_handle = -1;  } @@ -84,7 +85,7 @@ int32 DataStream::size() const {  bool DataStream::seek(int32 offset, int whence) {  	if (_stream)  		return _stream->seek(offset, whence); -	else if ((_handle < 50) || (_handle >= 128)) +	else if (!_io->isDataFileChunk(_handle))  		return _io->file_getHandle(_handle)->seek(offset, whence);  	else {  		_io->seekChunk(_handle, offset, whence); @@ -103,7 +104,7 @@ uint32 DataStream::read(void *dataPtr, uint32 dataSize) {  	if (_stream)  		return _stream->read(dataPtr, dataSize); -	if ((_handle < 50) || (_handle >= 128)) +	if (!_io->isDataFileChunk(_handle))  		return _io->file_getHandle(_handle)->read((byte *) dataPtr, dataSize);  	byte *data = (byte *) dataPtr; @@ -111,7 +112,7 @@ uint32 DataStream::read(void *dataPtr, uint32 dataSize) {  	while (dataSize > 0x3FFF) {  		_io->readChunk(_handle, (byte *) data, 0x3FFF);  		dataSize -= 0x3FFF; -		data += 0x3FFF; +		data     += 0x3FFF;  		haveRead += 0x3FFF;  	}  	_io->readChunk(_handle, (byte *) data, dataSize); @@ -121,11 +122,10 @@ uint32 DataStream::read(void *dataPtr, uint32 dataSize) {  DataIO::DataIO(GobEngine *vm) : _vm(vm) {  	for (int i = 0; i < MAX_DATA_FILES; i++) { -		_dataFiles[i] = 0; -		_numDataChunks[i] = 0; +		_dataFiles[i]       =  0; +		_numDataChunks[i]   =  0;  		_dataFileHandles[i] = -1;  	} -	_packedSize = 0;  }  DataIO::~DataIO() { @@ -136,6 +136,46 @@ DataIO::~DataIO() {  	}  } +bool DataIO::isDataFileChunk(int16 handle) const { +	return (handle >= 50) && (handle < 128); +} + +bool DataIO::isPacked(int16 handle) const { +	if (!isDataFileChunk(handle)) +		return false; + +	return _chunk[getIndex(handle)]->packed != 0; +} + +int DataIO::getFile(int16 handle) const { +	if (!isDataFileChunk(handle)) +		return -1; + +	return (handle - 50) / 10; +} + +int DataIO::getSlot(int16 handle) const { +	if (!isDataFileChunk(handle)) +		return -1; + +	return (handle - 50) % 10; +} + +int DataIO::getIndex(int16 handle) const { +	if (!isDataFileChunk(handle)) +		return -1; + +	return getIndex(getFile(handle), getSlot(handle)); +} + +int DataIO::getIndex(int file, int slot) const { +	return file * MAX_SLOT_COUNT + slot; +} + +int16 DataIO::getHandle(int file, int slot) const { +	return file * 10 + slot + 50; +} +  int32 DataIO::unpackData(byte *src, byte *dest) {  	uint32 realSize;  	uint32 counter; @@ -222,13 +262,11 @@ int16 DataIO::file_open(const char *path) {  }  int16 DataIO::getChunk(const char *chunkName) { -	int16 slot; -	struct ChunkDesc *dataDesc; -  	for (int16 file = 0; file < MAX_DATA_FILES; file++) {  		if (_dataFiles[file] == 0)  			return -1; +		int16 slot;  		for (slot = 0; slot < MAX_SLOT_COUNT; slot++)  			if (_chunkPos[file * MAX_SLOT_COUNT + slot] == -1)  				break; @@ -238,59 +276,55 @@ int16 DataIO::getChunk(const char *chunkName) {  			return -1;  		} -		dataDesc = _dataFiles[file]; +		ChunkDesc *dataDesc = _dataFiles[file];  		for (uint16 chunk = 0; chunk < _numDataChunks[file]; chunk++, dataDesc++) {  			if (scumm_stricmp(chunkName, dataDesc->chunkName) != 0)  				continue; -			_isCurrentSlot[file * MAX_SLOT_COUNT + slot] = false; -			_chunkSize[file * MAX_SLOT_COUNT + slot] = dataDesc->size; -			_chunkOffset[file * MAX_SLOT_COUNT + slot] = dataDesc->offset; -			_chunkPos[file * MAX_SLOT_COUNT + slot] = 0; -			return file * 10 + slot + 50; +			int index = getIndex(file, slot); + +			_isCurrentSlot[index] = false; +			_chunk        [index] = dataDesc; +			_chunkPos     [index] = 0; + +			return getHandle(file, slot);  		}  	}  	return -1;  }  char DataIO::freeChunk(int16 handle) { -	if ((handle >= 50) && (handle < 128)) { -		handle -= 50; -		_chunkPos[(handle / 10) * MAX_SLOT_COUNT + (handle % 10)] = -1; +	if (isDataFileChunk(handle)) { +		_chunkPos[getIndex(handle)] = -1;  		return 0;  	}  	return 1;  }  int32 DataIO::readChunk(int16 handle, byte *buf, uint16 size) { -	int16 file; -	int16 slot; -	int16 i; -	int32 offset; - -	if ((handle < 50) || (handle >= 128)) +	if (!isDataFileChunk(handle))  		return -2; -	file = (handle - 50) / 10; -	slot = (handle - 50) % 10; -	int index = file * MAX_SLOT_COUNT + slot; +	int file  = getFile(handle); +	int slot  = getSlot(handle); +	int index = getIndex(file, slot); -	_chunkPos[index] = CLIP<int32>(_chunkPos[index], 0, _chunkSize[index]); +	_chunkPos[index] = CLIP<int32>(_chunkPos[index], 0, _chunk[index]->size);  	if (!_isCurrentSlot[index]) { -		for (i = 0; i < MAX_SLOT_COUNT; i++) +		for (int16 i = 0; i < MAX_SLOT_COUNT; i++)  			_isCurrentSlot[file * MAX_SLOT_COUNT + i] = false; -		offset = _chunkOffset[index] + _chunkPos[index]; +		int32 offset = _chunk[index]->offset + _chunkPos[index]; -		debugC(7, kDebugFileIO, "seek: %d, %d", _chunkOffset[index], _chunkPos[index]); +		debugC(7, kDebugFileIO, "seek: %d, %d", _chunk[index]->offset, _chunkPos[index]);  		file_getHandle(_dataFileHandles[file])->seek(offset, SEEK_SET);  	}  	_isCurrentSlot[index] = true; -	if ((_chunkPos[index] + size) > (_chunkSize[index])) -		size = _chunkSize[index] - _chunkPos[index]; +	if ((_chunkPos[index] + size) > (int32) (_chunk[index]->size)) +		size = _chunk[index]->size - _chunkPos[index];  	file_getHandle(_dataFileHandles[file])->read(buf, size);  	_chunkPos[index] += size; @@ -298,15 +332,12 @@ int32 DataIO::readChunk(int16 handle, byte *buf, uint16 size) {  }  int16 DataIO::seekChunk(int16 handle, int32 pos, int16 from) { -	int16 file; -	int16 slot; - -	if ((handle < 50) || (handle >= 128)) +	if (!isDataFileChunk(handle))  		return -1; -	file = (handle - 50) / 10; -	slot = (handle - 50) % 10; -	int index = file * MAX_SLOT_COUNT + slot; +	int file  = getFile(handle); +	int slot  = getSlot(handle); +	int index = getIndex(file, slot);  	_isCurrentSlot[index] = false;  	if (from == SEEK_SET) @@ -314,50 +345,45 @@ int16 DataIO::seekChunk(int16 handle, int32 pos, int16 from) {  	else if (from == SEEK_CUR)  		_chunkPos[index] += pos;  	else if (from == SEEK_END) -		_chunkPos[index] = _chunkSize[index] - pos; +		_chunkPos[index] = _chunk[index]->size - pos;  	return _chunkPos[index];  }  uint32 DataIO::getChunkPos(int16 handle) const { -	int16 file; -	int16 slot; - -	if ((handle < 50) || (handle >= 128)) +	if (!isDataFileChunk(handle))  		return 0xFFFFFFFF; -	file = (handle - 50) / 10; -	slot = (handle - 50) % 10; +	int file = getFile(handle); +	int slot = getSlot(handle);  	return _chunkPos[file * MAX_SLOT_COUNT + slot];  } -int32 DataIO::getChunkSize(const char *chunkName) { -	int16 file; -	struct ChunkDesc *dataDesc; -	int16 slot; -	int32 realSize; - -	for (file = 0; file < MAX_DATA_FILES; file++) { +int32 DataIO::getChunkSize(const char *chunkName, int32 &packSize) { +	for (int16 file = 0; file < MAX_DATA_FILES; file++) {  		if (_dataFiles[file] == 0)  			return -1; -		dataDesc = _dataFiles[file]; +		ChunkDesc *dataDesc = _dataFiles[file];  		for (uint16 chunk = 0; chunk < _numDataChunks[file]; chunk++, dataDesc++) {  			if (scumm_stricmp(chunkName, dataDesc->chunkName) != 0)  				continue;  			if (dataDesc->packed == 0) { -				_packedSize = -1; +				packSize = -1;  				return dataDesc->size;  			} -			for (slot = 0; slot < MAX_SLOT_COUNT; slot++) +			for (int16 slot = 0; slot < MAX_SLOT_COUNT; slot++)  				_isCurrentSlot[slot] = false; +			int32 realSize; +  			file_getHandle(_dataFileHandles[file])->seek(dataDesc->offset, SEEK_SET);  			realSize = file_getHandle(_dataFileHandles[file])->readUint32LE(); -			_packedSize = dataDesc->size; +			packSize = dataDesc->size; +  			return realSize;  		}  	} @@ -365,10 +391,7 @@ int32 DataIO::getChunkSize(const char *chunkName) {  }  void DataIO::openDataFile(const char *src, bool itk) { -	ChunkDesc *dataDesc;  	char path[128]; -	int16 file; -	char *fakeTotPtr;  	strncpy0(path, src, 127);  	if (!strchr(path, '.')) { @@ -376,6 +399,7 @@ void DataIO::openDataFile(const char *src, bool itk) {  		strcat(path, ".stk");  	} +	int16 file;  	for (file = 0; file < MAX_DATA_FILES; file++)  		if (_dataFiles[file] == 0)  			break; @@ -388,17 +412,17 @@ void DataIO::openDataFile(const char *src, bool itk) {  	if (_dataFileHandles[file] == -1)  		error("DataIO::openDataFile(): Can't open data file \"%s\"", path); -	_dataFileItk[file] = itk; +	_dataFileItk  [file] = itk;  	_numDataChunks[file] = file_getHandle(_dataFileHandles[file])->readUint16LE();  	debugC(7, kDebugFileIO, "DataChunks: %d [for %s]", _numDataChunks[file], path); -	dataDesc = new ChunkDesc[_numDataChunks[file]]; +	ChunkDesc *dataDesc = new ChunkDesc[_numDataChunks[file]];  	_dataFiles[file] = dataDesc;  	for (int i = 0; i < _numDataChunks[file]; i++) {  		file_getHandle(_dataFileHandles[file])->read(dataDesc[i].chunkName, 13); -		dataDesc[i].size = file_getHandle(_dataFileHandles[file])->readUint32LE(); +		dataDesc[i].size   = file_getHandle(_dataFileHandles[file])->readUint32LE();  		dataDesc[i].offset = file_getHandle(_dataFileHandles[file])->readUint32LE();  		dataDesc[i].packed = file_getHandle(_dataFileHandles[file])->readByte(); @@ -410,7 +434,7 @@ void DataIO::openDataFile(const char *src, bool itk) {  		Util::replaceChar(dataDesc[i].chunkName, (char) 0x92, 'T');  		// Geisha use 0ot files, which are compressed TOT files without the packed byte set. -		fakeTotPtr = strstr(dataDesc[i].chunkName, "0OT"); +		char *fakeTotPtr = strstr(dataDesc[i].chunkName, "0OT");  		if (fakeTotPtr != 0) {  			strncpy(fakeTotPtr, "TOT", 3);  			dataDesc[i].packed = 1; @@ -436,33 +460,29 @@ void DataIO::closeDataFile(bool itk) {  }  byte *DataIO::getUnpackedData(const char *name) { -	int32 realSize; -	int16 chunk; -	byte *unpackBuf; -	byte *packBuf; -	byte *ptr; -	int32 sizeLeft; - -	realSize = getChunkSize(name); -	if ((_packedSize == -1) || (realSize == -1)) +	int32 realSize, packSize; + +	realSize = getChunkSize(name, packSize); + +	if ((packSize == -1) || (realSize == -1))  		return 0; -	chunk = getChunk(name); +	int16 chunk = getChunk(name);  	if (chunk == -1)  		return 0; -	unpackBuf = new byte[realSize]; +	byte *unpackBuf = new byte[realSize];  	assert(unpackBuf); -	packBuf = new byte[_packedSize]; +	byte *packBuf = new byte[packSize];  	assert(packBuf); -	sizeLeft = _packedSize; -	ptr = packBuf; +	int32 sizeLeft = packSize; +	byte *ptr = packBuf;  	while (sizeLeft > 0x4000) {  		readChunk(chunk, ptr, 0x4000);  		sizeLeft -= 0x4000; -		ptr += 0x4000; +		ptr      += 0x4000;  	}  	readChunk(chunk, ptr, sizeLeft);  	freeChunk(chunk); @@ -478,9 +498,7 @@ void DataIO::closeData(int16 handle) {  }  int16 DataIO::openData(const char *path) { -	int16 handle; - -	handle = getChunk(path); +	int16 handle = getChunk(path);  	if (handle >= 0)  		return handle; @@ -492,7 +510,6 @@ bool DataIO::existData(const char *path) {  		return false;  	int16 handle = openData(path); -  	if (handle < 0)  		return false; @@ -510,9 +527,7 @@ DataStream *DataIO::openAsStream(int16 handle, bool dispose) {  }  uint32 DataIO::getPos(int16 handle) { -	uint32 resPos; - -	resPos = getChunkPos(handle); +	uint32 resPos = getChunkPos(handle);  	if (resPos != 0xFFFFFFFF)  		return resPos; @@ -520,9 +535,7 @@ uint32 DataIO::getPos(int16 handle) {  }  void DataIO::seekData(int16 handle, int32 pos, int16 from) { -	int32 resPos; - -	resPos = seekChunk(handle, pos, from); +	int32 resPos = seekChunk(handle, pos, from);  	if (resPos != -1)  		return; @@ -530,9 +543,7 @@ void DataIO::seekData(int16 handle, int32 pos, int16 from) {  }  int32 DataIO::readData(int16 handle, byte *buf, uint16 size) { -	int32 res; - -	res = readChunk(handle, buf, size); +	int16 res = readChunk(handle, buf, size);  	if (res >= 0)  		return res; @@ -541,45 +552,42 @@ int32 DataIO::readData(int16 handle, byte *buf, uint16 size) {  int32 DataIO::getDataSize(const char *name) {  	char buf[128]; -	int32 chunkSz; -	Common::File file;  	strncpy0(buf, name, 127); -	chunkSz = getChunkSize(buf); -	if (chunkSz >= 0) -		return chunkSz; +	int32 chunkSize, packSize; + +	chunkSize = getChunkSize(buf, packSize); +	if (chunkSize >= 0) +		return chunkSize; +	Common::File file;  	if (!file.open(buf))  		error("DataIO::getDataSize(): Can't find data \"%s\"", name); -	chunkSz = file.size(); +	chunkSize = file.size();  	file.close(); -	return chunkSz; +	return chunkSize;  }  byte *DataIO::getData(const char *path) { -	byte *data; -	byte *ptr; -	int32 size; -	int16 handle; - -	data = getUnpackedData(path); +	byte *data = getUnpackedData(path);  	if (data)  		return data; -	size = getDataSize(path); +	int32 size = getDataSize(path); +  	data = new byte[size];  	assert(data); -	handle = openData(path); +	int16 handle = openData(path); -	ptr = data; +	byte *ptr = data;  	while (size > 0x4000) {  		readData(handle, ptr, 0x4000);  		size -= 0x4000; -		ptr += 0x4000; +		ptr  += 0x4000;  	}  	readData(handle, ptr, size);  	closeData(handle); @@ -588,12 +596,26 @@ byte *DataIO::getData(const char *path) {  DataStream *DataIO::getDataStream(const char *path) {  	if (!existData(path)) +	return 0; + +	int16 handle = openData(path); +	if (handle < 0)  		return 0; -	uint32 size = getDataSize(path); -	byte *data = getData(path); +	if (isDataFileChunk(handle) && isPacked(handle)) { +		// It's a packed chunk in the data files, packed, +		// so we have to read it in completely and unpack it + +		closeData(handle); + +		uint32 size = getDataSize(path); +		byte  *data = getData(path); + +		return new DataStream(data, size); -	return new DataStream(data, size); +	} else +		// Otherwise, we can just return a stream +		return openAsStream(handle, true);  }  } // End of namespace Gob diff --git a/engines/gob/dataio.h b/engines/gob/dataio.h index 1f55cac90d..6a86667e1b 100644 --- a/engines/gob/dataio.h +++ b/engines/gob/dataio.h @@ -26,16 +26,14 @@  #ifndef GOB_DATAIO_H  #define GOB_DATAIO_H -  #include "common/endian.h" -  #include "common/file.h"  namespace Gob { -#define MAX_FILES	30 -#define MAX_DATA_FILES	8 -#define MAX_SLOT_COUNT	8 +#define MAX_FILES      30 +#define MAX_DATA_FILES  8 +#define MAX_SLOT_COUNT  8  class DataIO; @@ -56,20 +54,20 @@ public:  private:  	DataIO *_io; -	int16 _handle; -	uint32 _size; -	byte *_data; +	int16   _handle; +	uint32  _size; +	byte   *_data; +	bool    _dispose;  	Common::MemoryReadStream *_stream; -	bool _dispose;  };  class DataIO {  public:  	struct ChunkDesc { -		char chunkName[13]; +		char   chunkName[13];  		uint32 size;  		uint32 offset; -		byte packed; +		byte   packed;  		ChunkDesc() : size(0), offset(0), packed(0) { chunkName[0] = 0; }  	}; @@ -77,10 +75,13 @@ public:  	void openDataFile(const char *src, bool itk = 0);  	void closeDataFile(bool itk = 0); +  	byte *getUnpackedData(const char *name); -	void closeData(int16 handle); + +	void  closeData(int16 handle);  	int16 openData(const char *path); -	bool existData(const char *path); +	bool  existData(const char *path); +  	DataStream *openAsStream(int16 handle, bool dispose = false);  	int32 getDataSize(const char *name); @@ -92,34 +93,47 @@ public:  protected:  	Common::File _filesHandles[MAX_FILES]; -	struct ChunkDesc *_dataFiles[MAX_DATA_FILES]; -	uint16 _numDataChunks[MAX_DATA_FILES]; -	int16 _dataFileHandles[MAX_DATA_FILES]; -	bool _dataFileItk[MAX_DATA_FILES]; -	int32 _chunkPos[MAX_SLOT_COUNT * MAX_DATA_FILES]; -	int32 _chunkOffset[MAX_SLOT_COUNT * MAX_DATA_FILES]; -	int32 _chunkSize[MAX_SLOT_COUNT * MAX_DATA_FILES]; -	bool _isCurrentSlot[MAX_SLOT_COUNT * MAX_DATA_FILES]; -	int32 _packedSize; + +	ChunkDesc *_dataFiles      [MAX_DATA_FILES]; +	uint16     _numDataChunks  [MAX_DATA_FILES]; +	int16      _dataFileHandles[MAX_DATA_FILES]; +	bool       _dataFileItk    [MAX_DATA_FILES]; + +	ChunkDesc *_chunk        [MAX_SLOT_COUNT * MAX_DATA_FILES]; +	int32      _chunkPos     [MAX_SLOT_COUNT * MAX_DATA_FILES]; +	bool       _isCurrentSlot[MAX_SLOT_COUNT * MAX_DATA_FILES];  	class GobEngine *_vm; +	bool isDataFileChunk(int16 handle) const; +	bool isPacked       (int16 handle) const; + +	int getFile (int16 handle) const; +	int getSlot (int16 handle) const; +	int getIndex(int16 handle) const; + +	int   getIndex (int file, int slot) const; +	int16 getHandle(int file, int slot) const; +  	int16 file_open(const char *path);  	Common::File *file_getHandle(int16 handle);  	const Common::File *file_getHandle(int16 handle) const;  	int16 getChunk(const char *chunkName); -	char freeChunk(int16 handle); +	char  freeChunk(int16 handle);  	int32 readChunk(int16 handle, byte *buf, uint16 size);  	int16 seekChunk(int16 handle, int32 pos, int16 from); +  	uint32 getChunkPos(int16 handle) const; -	int32 getChunkSize(const char *chunkName); + +	int32 getChunkSize(const char *chunkName, int32 &packSize);  	uint32 getPos(int16 handle); -	void seekData(int16 handle, int32 pos, int16 from); +	void   seekData(int16 handle, int32 pos, int16 from); +  	int32 readData(int16 handle, byte *buf, uint16 size); -friend class DataStream; +	friend class DataStream;  };  } // End of namespace Gob  | 
