aboutsummaryrefslogtreecommitdiff
path: root/sword1
diff options
context:
space:
mode:
authorRobert Göffringmann2005-02-20 18:53:30 +0000
committerRobert Göffringmann2005-02-20 18:53:30 +0000
commitb455a94e0fb2cb522a75cb1e2a98422f860de9b1 (patch)
tree767f4206869b970d4d4da44df890b62016669b74 /sword1
parent7c54b0af7dbe6a6f3710a738dffcdb87c13f032b (diff)
downloadscummvm-rg350-b455a94e0fb2cb522a75cb1e2a98422f860de9b1.tar.gz
scummvm-rg350-b455a94e0fb2cb522a75cb1e2a98422f860de9b1.tar.bz2
scummvm-rg350-b455a94e0fb2cb522a75cb1e2a98422f860de9b1.zip
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. ;)
svn-id: r16830
Diffstat (limited to 'sword1')
-rw-r--r--sword1/resman.cpp135
-rw-r--r--sword1/resman.h18
2 files changed, 98 insertions, 55 deletions
diff --git a/sword1/resman.cpp b/sword1/resman.cpp
index 7911d4ae8f..e421badaa2 100644
--- a/sword1/resman.cpp
+++ b/sword1/resman.cpp
@@ -47,6 +47,8 @@ namespace Sword1 {
#define MAX_PATH_LEN 260
ResMan::ResMan(const char *resFile) {
+ _openCluStart = _openCluEnd = NULL;
+ _openClus = 0;
_memMan = new MemMan();
loadCluDescript(resFile);
}
@@ -88,25 +90,29 @@ void ResMan::loadCluDescript(const char *fileName) {
_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 @@ void ResMan::loadCluDescript(const char *fileName) {
}
}
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 @@ void ResMan::resOpen(uint32 id) { // load resource ID into memory
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 @@ FrameHeader *ResMan::fetchFrame(void *resourceData, uint32 frameNo) {
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);
-
- 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);
+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 (!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 @@ MemHandle *ResMan::resHandle(uint32 id) {
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 @@ uint32 ResMan::resLength(uint32 id) {
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 @@ uint32 ResMan::resOffset(uint32 id) {
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) {
diff --git a/sword1/resman.h b/sword1/resman.h
index ca0b32fb0b..d2fcafc36f 100644
--- a/sword1/resman.h
+++ b/sword1/resman.h
@@ -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 Grp {
};
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 @@ public:
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