[Scummvm-cvs-logs] SF.net SVN: scummvm:[43108] scummvm/branches/branch-1-0-0/engines/gob

drmccoy at users.sourceforge.net drmccoy at users.sourceforge.net
Sat Aug 8 04:23:40 CEST 2009


Revision: 43108
          http://scummvm.svn.sourceforge.net/scummvm/?rev=43108&view=rev
Author:   drmccoy
Date:     2009-08-08 02:23:40 +0000 (Sat, 08 Aug 2009)

Log Message:
-----------
Backport: When opening a data stream, don't read the whole file into memory if not necessary. This vastly improves the loading times of Gob3 on small devices

Modified Paths:
--------------
    scummvm/branches/branch-1-0-0/engines/gob/dataio.cpp
    scummvm/branches/branch-1-0-0/engines/gob/dataio.h

Modified: scummvm/branches/branch-1-0-0/engines/gob/dataio.cpp
===================================================================
--- scummvm/branches/branch-1-0-0/engines/gob/dataio.cpp	2009-08-08 02:23:04 UTC (rev 43107)
+++ scummvm/branches/branch-1-0-0/engines/gob/dataio.cpp	2009-08-08 02:23:40 UTC (rev 43108)
@@ -35,21 +35,22 @@
 
 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 @@
 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 @@
 	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 @@
 	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 @@
 
 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 @@
 	}
 }
 
+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::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 @@
 			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 @@
 }
 
 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 @@
 	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 @@
 }
 
 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 @@
 		strcat(path, ".stk");
 	}
 
+	int16 file;
 	for (file = 0; file < MAX_DATA_FILES; file++)
 		if (_dataFiles[file] == 0)
 			break;
@@ -388,17 +412,17 @@
 	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 @@
 		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 @@
 }
 
 byte *DataIO::getUnpackedData(const char *name) {
-	int32 realSize;
-	int16 chunk;
-	byte *unpackBuf;
-	byte *packBuf;
-	byte *ptr;
-	int32 sizeLeft;
+	int32 realSize, packSize;
 
-	realSize = getChunkSize(name);
-	if ((_packedSize == -1) || (realSize == -1))
+	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 @@
 }
 
 int16 DataIO::openData(const char *path) {
-	int16 handle;
-
-	handle = getChunk(path);
+	int16 handle = getChunk(path);
 	if (handle >= 0)
 		return handle;
 
@@ -492,7 +510,6 @@
 		return false;
 
 	int16 handle = openData(path);
-
 	if (handle < 0)
 		return false;
 
@@ -510,9 +527,7 @@
 }
 
 uint32 DataIO::getPos(int16 handle) {
-	uint32 resPos;
-
-	resPos = getChunkPos(handle);
+	uint32 resPos = getChunkPos(handle);
 	if (resPos != 0xFFFFFFFF)
 		return resPos;
 
@@ -520,9 +535,7 @@
 }
 
 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 @@
 }
 
 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::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 @@
 
 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
 
-	return new DataStream(data, size);
+		closeData(handle);
+
+		uint32 size = getDataSize(path);
+		byte  *data = getData(path);
+
+		return new DataStream(data, size);
+
+	} else
+		// Otherwise, we can just return a stream
+		return openAsStream(handle, true);
 }
 
 } // End of namespace Gob

Modified: scummvm/branches/branch-1-0-0/engines/gob/dataio.h
===================================================================
--- scummvm/branches/branch-1-0-0/engines/gob/dataio.h	2009-08-08 02:23:04 UTC (rev 43107)
+++ scummvm/branches/branch-1-0-0/engines/gob/dataio.h	2009-08-08 02:23:40 UTC (rev 43108)
@@ -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 @@
 
 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 @@
 
 	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 @@
 
 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


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list