mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-05 00:36:57 +00:00
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
This commit is contained in:
parent
7c54b0af7d
commit
b455a94e0f
@ -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);
|
||||
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 @@ 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) {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user