[Scummvm-cvs-logs] CVS: scummvm/sword1 resman.cpp,1.26,1.27 resman.h,1.12,1.13

Robert Göffringmann lavosspawn at users.sourceforge.net
Sun Feb 20 10:54:36 CET 2005


Update of /cvsroot/scummvm/scummvm/sword1
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32754/sword1

Modified Files:
	resman.cpp resman.h 
Log Message:
cache datafile handles instead of opening and closing all files hundreds of times per second. I noticed that behaviour on the PS2. The cd/dvd drive was waaaay too slow for it. ;)

Index: resman.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword1/resman.cpp,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- resman.cpp	1 Jan 2005 16:09:25 -0000	1.26
+++ resman.cpp	20 Feb 2005 18:53:30 -0000	1.27
@@ -47,6 +47,8 @@
 #define MAX_PATH_LEN 260
 
 ResMan::ResMan(const char *resFile) {
+	_openCluStart = _openCluEnd = NULL;
+	_openClus = 0;
 	_memMan = new MemMan();
 	loadCluDescript(resFile);
 }
@@ -88,25 +90,29 @@
 
 	
 	_prj.noClu = resFile.readUint32LE();
-	_prj.clu = new Clu*[_prj.noClu];
+	_prj.clu = new Clu[_prj.noClu];
+	memset(_prj.clu, 0, _prj.noClu * sizeof(Clu));
 
 	uint32 *cluIndex = (uint32*)malloc(_prj.noClu * 4);
 	resFile.read(cluIndex, _prj.noClu * 4);
 
 	for (uint32 clusCnt = 0; clusCnt < _prj.noClu; clusCnt++)
 		if (cluIndex[clusCnt]) {
-			Clu *cluster = _prj.clu[clusCnt] = new Clu;
+			Clu *cluster = _prj.clu + clusCnt;
 			resFile.read(cluster->label, MAX_LABEL_SIZE);
 
+			cluster->file = NULL;
 			cluster->noGrp = resFile.readUint32LE();
-			cluster->grp = new Grp*[cluster->noGrp];
+			cluster->grp = new Grp[cluster->noGrp];
+			memset(cluster->grp, 0, cluster->noGrp * sizeof(Grp));
+			cluster->refCount = 0;
 
 			uint32 *grpIndex = (uint32*)malloc(cluster->noGrp * 4);
 			resFile.read(grpIndex, cluster->noGrp * 4);
 
 			for (uint32 grpCnt = 0; grpCnt < cluster->noGrp; grpCnt++)
 				if (grpIndex[grpCnt]) {
-					Grp *group = cluster->grp[grpCnt] = new Grp;
+					Grp *group = cluster->grp + grpCnt;
 					group->noRes = resFile.readUint32LE();
 					group->resHandle = new MemHandle[group->noRes];
 					group->offset = new uint32[group->noRes];
@@ -126,47 +132,59 @@
 						}
 					}
 					free(resIdIdx);
-				} else
-					cluster->grp[grpCnt] = NULL;
+				}
 			free(grpIndex);
-		} else
-			_prj.clu[clusCnt] = NULL;
+		}
 	free(cluIndex);
 	
-	if (_prj.clu[3]->grp[5]->noRes == 29)
+	if (_prj.clu[3].grp[5].noRes == 29)
 		for (uint8 cnt = 0; cnt < 29; cnt++)
 			_srIdList[cnt] = 0x04050000 | cnt;
 }
 
 void ResMan::freeCluDescript(void) {
 	
-	for (uint32 clusCnt = 0; clusCnt < _prj.noClu; clusCnt++)
-		if (Clu *cluster = _prj.clu[clusCnt]) {
-			for (uint32 grpCnt = 0; grpCnt < cluster->noGrp; grpCnt++)
-				if (Grp *group = cluster->grp[grpCnt]) {
-					for (uint32 resCnt = 0; resCnt < group->noRes; resCnt++)
-						_memMan->freeNow(group->resHandle + resCnt);
-					delete[] group->resHandle;
-					delete[] group->offset;
-					delete[] group->length;
-					delete group;
-				}
-			delete[] cluster->grp;
-			delete cluster;
+	for (uint32 clusCnt = 0; clusCnt < _prj.noClu; clusCnt++) {
+		Clu *cluster = _prj.clu + clusCnt;
+		for (uint32 grpCnt = 0; grpCnt < cluster->noGrp; grpCnt++) {
+			Grp *group = cluster->grp + grpCnt;
+			if (group->resHandle != NULL) {
+				for (uint32 resCnt = 0; resCnt < group->noRes; resCnt++)
+					_memMan->freeNow(group->resHandle + resCnt);
+
+				delete[] group->resHandle;
+				delete[] group->offset;
+				delete[] group->length;
+			}
 		}
+		delete[] cluster->grp;
+
+		if (cluster->file != NULL)
+			delete cluster->file;
+	}
 	delete[] _prj.clu;
 }
 
 void ResMan::flush(void) {
-	for (uint32 clusCnt = 0; clusCnt < _prj.noClu; clusCnt++)
-		if (Clu *cluster = _prj.clu[clusCnt])
-			for (uint32 grpCnt = 0; grpCnt < cluster->noGrp; grpCnt++)
-				if (Grp *group = cluster->grp[grpCnt])
-					for (uint32 resCnt = 0; resCnt < group->noRes; resCnt++)
-						if (group->resHandle[resCnt].cond != MEM_FREED) {
-							_memMan->setCondition(group->resHandle + resCnt, MEM_CAN_FREE);
-							group->resHandle[resCnt].refCount = 0;
-						}
+	for (uint32 clusCnt = 0; clusCnt < _prj.noClu; clusCnt++) {
+		Clu *cluster = _prj.clu + clusCnt;
+		for (uint32 grpCnt = 0; grpCnt < cluster->noGrp; grpCnt++) {
+			Grp *group = cluster->grp + grpCnt;
+			for (uint32 resCnt = 0; resCnt < group->noRes; resCnt++)
+				if (group->resHandle[resCnt].cond != MEM_FREED) {
+					_memMan->setCondition(group->resHandle + resCnt, MEM_CAN_FREE);
+					group->resHandle[resCnt].refCount = 0;
+				}
+		}
+		if (cluster->file) {
+			cluster->file->close();
+			delete cluster->file;
+			cluster->file = NULL;
+			cluster->refCount = 0;
+		}
+	}
+	_openClus = 0;
+	_openCluStart = _openCluEnd = NULL;
 	// the memory manager cached the blocks we asked it to free, so explicitly make it free them
 	_memMan->flush();
 }
@@ -234,15 +252,15 @@
 	if (memHandle->cond == MEM_FREED) { // memory has been freed
 		uint32 size = resLength(id);
 		_memMan->alloc(memHandle, size);
-		File *clusFile = openClusterFile(id);
+		File *clusFile = resFile(id);
+		assert(clusFile);
 		clusFile->seek( resOffset(id) );
 		clusFile->read( memHandle->data, size);
 		if (clusFile->ioFailed())
 			error("Can't read %d bytes from cluster %d\n", size, id);
-		clusFile->close();
-		delete clusFile;
 	} else
 		_memMan->setCondition(memHandle, MEM_DONT_FREE);
+
 	memHandle->refCount++;
 	if (memHandle->refCount > 20) {
 		debug(1, "%d references to id %d. Guess there's something wrong.", memHandle->refCount, id);
@@ -269,19 +287,38 @@
 	return (FrameHeader*)frameFile;
 }
 
-File *ResMan::openClusterFile(uint32 id) {
-	File *clusFile = new File();
-	char fileName[15];
-	sprintf(fileName, "%s.CLU", _prj.clu[(id >> 24)-1]->label);
-	clusFile->open(fileName);
+File *ResMan::resFile(uint32 id) {
+	Clu *cluster = _prj.clu + ((id >> 24) - 1);
+	if (cluster->file == NULL) {
+		_openClus++;
+		if (_openCluEnd == NULL) {
+			_openCluStart = _openCluEnd = cluster;
+		} else {
+			_openCluEnd->nextOpen = cluster;
+			_openCluEnd = cluster;
+		}
+		cluster->file = new File();
+		char fileName[15];
+		sprintf(fileName, "%s.CLU", _prj.clu[(id >> 24)-1].label);
+		cluster->file->open(fileName);
 
-	if (!clusFile->isOpen()) {
-		char msg[512];
-		sprintf(msg, "Couldn't open game cluster file '%s'\n\nIf you are running from CD, please ensure you have read the ScummVM documentation regarding multi-cd games.", fileName);
-		guiFatalError(msg);
+		if (!cluster->file->isOpen()) {
+			char msg[512];
+			sprintf(msg, "Couldn't open game cluster file '%s'\n\nIf you are running from CD, please ensure you have read the ScummVM documentation regarding multi-cd games.", fileName);
+			guiFatalError(msg);
+		}
+		while (_openClus > MAX_OPEN_CLUS) {
+			assert(_openCluStart);
+			Clu *closeClu = _openCluStart;
+			_openCluStart = _openCluStart->nextOpen;
+			
+			closeClu->file->close();
+			delete closeClu->file;
+			closeClu->file = NULL;
+			closeClu->nextOpen = NULL;
+		}
 	}
-
-	return clusFile;
+	return cluster->file;
 }
 
 MemHandle *ResMan::resHandle(uint32 id) {
@@ -290,7 +327,7 @@
 	uint8 cluster = (uint8)((id >> 24) - 1);
 	uint8 group = (uint8)(id >> 16);
 
-	return &(_prj.clu[cluster]->grp[group]->resHandle[id & 0xFFFF]);
+	return &(_prj.clu[cluster].grp[group].resHandle[id & 0xFFFF]);
 }
 
 uint32 ResMan::resLength(uint32 id) {
@@ -299,7 +336,7 @@
 	uint8 cluster = (uint8)((id >> 24) - 1);
 	uint8 group = (uint8)(id >> 16);
 
-	return _prj.clu[cluster]->grp[group]->length[id & 0xFFFF];
+	return _prj.clu[cluster].grp[group].length[id & 0xFFFF];
 }
 
 uint32 ResMan::resOffset(uint32 id) {
@@ -308,7 +345,7 @@
 	uint8 cluster = (uint8)((id >> 24) - 1);
 	uint8 group = (uint8)(id >> 16);
 
-	return _prj.clu[cluster]->grp[group]->offset[id & 0xFFFF];
+	return _prj.clu[cluster].grp[group].offset[id & 0xFFFF];
 }
 
 void ResMan::openCptResourceBigEndian(uint32 id) {

Index: resman.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword1/resman.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- resman.h	1 Jan 2005 16:09:25 -0000	1.12
+++ resman.h	20 Feb 2005 18:53:30 -0000	1.13
@@ -29,6 +29,7 @@
 namespace Sword1 {
 
 #define MAX_LABEL_SIZE (31+1)
+#define MAX_OPEN_CLUS 8	// don't open more than 8 files at once
 
 struct Grp {
 	uint32 noRes;
@@ -38,14 +39,17 @@
 };
 
 struct Clu {
+	uint32 refCount;
+	File *file;
 	char label[MAX_LABEL_SIZE];
 	uint32 noGrp;
-	Grp **grp;
+	Grp *grp;
+	Clu *nextOpen;
 };
 
 struct Prj {
 	uint32 noClu;
-	Clu **clu;
+	Clu *clu;
 };
 
 class ResMan {
@@ -63,20 +67,22 @@
 	void unlockScript(uint32 scrID);
 	FrameHeader *fetchFrame(void *resourceData, uint32 frameNo);
 private:
-	uint32 filesInGroup(uint32 id);
-	uint32 resLength(uint32 id);
+	uint32	   resLength(uint32 id);
 	MemHandle *resHandle(uint32 id);
-	uint32 resOffset(uint32 id);
+	uint32     resOffset(uint32 id);
+	File      *resFile(uint32 id);
+
 	void openCptResourceBigEndian(uint32 id);
 	void openScriptResourceBigEndian(uint32 id);
 
-	File *openClusterFile(uint32 id);
 	void loadCluDescript(const char *fileName);
 	void freeCluDescript(void);
 	Prj _prj;
 	MemMan *_memMan;
 	static const uint32 _scriptList[TOTAL_SECTIONS];	//a table of resource tags
 	static uint32 _srIdList[29];
+	Clu *_openCluStart, *_openCluEnd;
+	int  _openClus;
 };
 
 } // End of namespace Sword1 





More information about the Scummvm-git-logs mailing list