diff options
author | Robert Göffringmann | 2005-02-20 18:53:30 +0000 |
---|---|---|
committer | Robert Göffringmann | 2005-02-20 18:53:30 +0000 |
commit | b455a94e0fb2cb522a75cb1e2a98422f860de9b1 (patch) | |
tree | 767f4206869b970d4d4da44df890b62016669b74 /sword1 | |
parent | 7c54b0af7dbe6a6f3710a738dffcdb87c13f032b (diff) | |
download | scummvm-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.cpp | 135 | ||||
-rw-r--r-- | sword1/resman.h | 18 |
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 |