aboutsummaryrefslogtreecommitdiff
path: root/scumm
diff options
context:
space:
mode:
authorPaweł Kołodziejski2004-01-07 03:34:41 +0000
committerPaweł Kołodziejski2004-01-07 03:34:41 +0000
commit329fd80efd7f693baf02dacfff9f33a2b953b70e (patch)
treea2d173d5bd9663650f2f2ac1c0deb6330aad4565 /scumm
parenteb32f751f725c708fa746c4fe0fafa3510c387cf (diff)
downloadscummvm-rg350-329fd80efd7f693baf02dacfff9f33a2b953b70e.tar.gz
scummvm-rg350-329fd80efd7f693baf02dacfff9f33a2b953b70e.tar.bz2
scummvm-rg350-329fd80efd7f693baf02dacfff9f33a2b953b70e.zip
optimized i/o access in bundle manager
svn-id: r12199
Diffstat (limited to 'scumm')
-rw-r--r--scumm/imuse_digi/dimuse_bndmgr.cpp181
-rw-r--r--scumm/imuse_digi/dimuse_bndmgr.h21
2 files changed, 126 insertions, 76 deletions
diff --git a/scumm/imuse_digi/dimuse_bndmgr.cpp b/scumm/imuse_digi/dimuse_bndmgr.cpp
index 8f8f625bdb..e89235ca61 100644
--- a/scumm/imuse_digi/dimuse_bndmgr.cpp
+++ b/scumm/imuse_digi/dimuse_bndmgr.cpp
@@ -25,16 +25,23 @@
namespace Scumm {
+struct FileDirChache {
+ char fileName[20];
+ BundleMgr::AudioTable *bundleTable;
+ int32 numFiles;
+ int32 instance;
+} budleDirChache[4];
+
BundleMgr::BundleMgr() {
- _compTable = NULL;
_bundleTable = NULL;
+ _compTable = NULL;
_numFiles = 0;
_curSample = -1;
+ _fileBundleId = -1;
}
BundleMgr::~BundleMgr() {
- free(_bundleTable);
- free(_compTable);
+ closeFile();
}
bool BundleMgr::openFile(const char *filename, const char *directory) {
@@ -48,51 +55,83 @@ bool BundleMgr::openFile(const char *filename, const char *directory) {
return false;
}
-/*
- TODO / FIXME
-This is another spot were lots and lots of time is wasted, because the same data is read over
-and over again from the disk. Disk I/O is *slooow*.
-This function by itself actually isn't what is really slow - normally we would call
-it once and then be done with it.
-However, for whatever strange reasons, the higher level code constantly keeps creating
-new BundleMgr, uses them to open a file, play a piece of sound, then delete the BundleMgr.
-Repeat ad infinitum -> extremly slow.
-*/
-
- tag = _file.readUint32BE();
- offset = _file.readUint32BE();
- _numFiles = _file.readUint32BE();
-
- _bundleTable = (AudioTable *) malloc(_numFiles * sizeof(AudioTable));
-
- _file.seek(offset, SEEK_SET);
-
- for (int32 i = 0; i < _numFiles; i++) {
- char name[13], c;
- int32 z = 0;
- int32 z2;
-
- for (z2 = 0; z2 < 8; z2++)
- if ((c = _file.readByte()) != 0)
- name[z++] = c;
- name[z++] = '.';
- for (z2 = 0; z2 < 4; z2++)
- if ((c = _file.readByte()) != 0)
- name[z++] = c;
- name[z] = '\0';
- strcpy(_bundleTable[i].filename, name);
- _bundleTable[i].offset = _file.readUint32BE();
- _bundleTable[i].size = _file.readUint32BE();
+ bool found = false;
+ int freeSlot = -1;
+ int fileId;
+
+ for (fileId = 0; fileId < ARRAYSIZE(budleDirChache); fileId++) {
+ if ((budleDirChache[fileId].instance == 0) && (freeSlot == -1)) {
+ freeSlot = fileId;
+ }
+ if (scumm_stricmp(filename, budleDirChache[fileId].fileName) == 0) {
+ found = true;
+ }
}
+ if (!found) {
+ if (freeSlot == -1)
+ error("BundleMgr::openFile() Can't find free slot for file bundle dir cache");
+
+ tag = _file.readUint32BE();
+ offset = _file.readUint32BE();
+
+ strcpy(budleDirChache[freeSlot].fileName, filename);
+ budleDirChache[freeSlot].numFiles = _numFiles = _file.readUint32BE();
+ budleDirChache[freeSlot].bundleTable = _bundleTable = (AudioTable *) malloc(_numFiles * sizeof(AudioTable));
+
+ _file.seek(offset, SEEK_SET);
+
+ for (int32 i = 0; i < _numFiles; i++) {
+ char name[13], c;
+ int32 z = 0;
+ int32 z2;
+
+ for (z2 = 0; z2 < 8; z2++)
+ if ((c = _file.readByte()) != 0)
+ name[z++] = c;
+ name[z++] = '.';
+ for (z2 = 0; z2 < 4; z2++)
+ if ((c = _file.readByte()) != 0)
+ name[z++] = c;
+
+ name[z] = '\0';
+ strcpy(_bundleTable[i].filename, name);
+ _bundleTable[i].offset = _file.readUint32BE();
+ _bundleTable[i].size = _file.readUint32BE();
+ }
+ budleDirChache[freeSlot].instance++;
+ _fileBundleId = freeSlot;
+ } else {
+ _fileBundleId = fileId;
+ _numFiles = budleDirChache[fileId].numFiles;
+ _bundleTable = budleDirChache[fileId].bundleTable;
+ budleDirChache[fileId].instance++;
+ }
+
+ _compTableLoaded = false;
+ _lastCacheOutputSize = 0;
+ _lastBlock = -1;
+
return true;
}
void BundleMgr::closeFile() {
if (_file.isOpen()) {
_file.close();
- free(_bundleTable);
+ if (--budleDirChache[_fileBundleId].instance <= 0) {
+ free (budleDirChache[_fileBundleId].bundleTable);
+ budleDirChache[_fileBundleId].instance = 0;
+ budleDirChache[_fileBundleId].fileName[0] = 0;
+ budleDirChache[_fileBundleId].numFiles = 0;
+ }
_bundleTable = NULL;
+ _numFiles = 0;
+ _compTableLoaded = false;
+ _lastBlock = -1;
+ _lastCacheOutputSize = 0;
+ _curSample = -1;
+ free(_compTable);
+ _compTable = NULL;
}
}
@@ -112,31 +151,26 @@ int32 BundleMgr::decompressSampleByIndex(int32 index, int32 offset, int32 size,
return 0;
}
-/*
-FIXME / TODO
- This function is a major speed hog. It re-reads the same data over and over and over again.
- Disk I/O is about the slowest thing on any modern computer. We used to cache all this data,
- with good reason... this will have to be done again.
-*/
-
- _file.seek(_bundleTable[index].offset, SEEK_SET);
- tag = _file.readUint32BE();
- num = _file.readUint32BE();
- _file.readUint32BE();
- _file.readUint32BE();
-
- if (tag != MKID_BE('COMP')) {
- warning("BundleMgr::decompressSampleByIndex() Compressed sound %d invalid (%s)", index, tag2str(tag));
- return 0;
- }
-
- free(_compTable);
- _compTable = (CompTable *)malloc(sizeof(CompTable) * num);
- for (i = 0; i < num; i++) {
- _compTable[i].offset = _file.readUint32BE();
- _compTable[i].size = _file.readUint32BE();
- _compTable[i].codec = _file.readUint32BE();
+ if (!_compTableLoaded) {
+ _file.seek(_bundleTable[index].offset, SEEK_SET);
+ tag = _file.readUint32BE();
+ num = _file.readUint32BE();
_file.readUint32BE();
+ _file.readUint32BE();
+
+ if (tag != MKID_BE('COMP')) {
+ warning("BundleMgr::decompressSampleByIndex() Compressed sound %d invalid (%s)", index, tag2str(tag));
+ return 0;
+ }
+
+ _compTable = (CompTable *)malloc(sizeof(CompTable) * num);
+ for (i = 0; i < num; i++) {
+ _compTable[i].offset = _file.readUint32BE();
+ _compTable[i].size = _file.readUint32BE();
+ _compTable[i].codec = _file.readUint32BE();
+ _file.readUint32BE();
+ }
+ _compTableLoaded = true;
}
int first_block = (offset + header_size) / 0x2000;
@@ -154,20 +188,29 @@ FIXME / TODO
comp_input = (byte *)malloc(_compTable[i].size + 1);
comp_input[_compTable[i].size] = 0;
- _file.seek(_bundleTable[index].offset + _compTable[i].offset, SEEK_SET);
- _file.read(comp_input, _compTable[i].size);
+ if (_lastBlock != i) {
+ _file.seek(_bundleTable[index].offset + _compTable[i].offset, SEEK_SET);
+ _file.read(comp_input, _compTable[i].size);
+
+ output_size = BundleCodecs::decompressCodec(_compTable[i].codec, comp_input, comp_output, _compTable[i].size);
+ assert(output_size <= 0x2000);
+ _lastBlock = i;
+ _lastCacheOutputSize = output_size;
+ memcpy(&_blockChache, comp_output, output_size);
+ } else {
+ output_size = _lastCacheOutputSize;
+ memcpy(comp_output, &_blockChache, output_size);
+ }
- output_size = BundleCodecs::decompressCodec(_compTable[i].codec, comp_input, comp_output, _compTable[i].size);
- assert(output_size <= 0x2000);
if ((header_size != 0) && (skip > header_size))
output_size -= skip;
if (output_size > size)
output_size = size;
+
memcpy(*comp_final + final_size, comp_output + skip, output_size);
final_size += output_size;
size -= output_size;
- if (skip > 0)
- skip = 0;
+ skip = 0;
free(comp_input);
}
diff --git a/scumm/imuse_digi/dimuse_bndmgr.h b/scumm/imuse_digi/dimuse_bndmgr.h
index 11560f1ee5..350cfeca6b 100644
--- a/scumm/imuse_digi/dimuse_bndmgr.h
+++ b/scumm/imuse_digi/dimuse_bndmgr.h
@@ -27,6 +27,13 @@
namespace Scumm {
class BundleMgr {
+public:
+
+ struct AudioTable {
+ char filename[13];
+ int32 size;
+ int32 offset;
+ };
private:
@@ -36,19 +43,19 @@ private:
int32 codec;
};
- struct AudioTable {
- char filename[13];
- int32 size;
- int32 offset;
- };
-
- CompTable *_compTable;
AudioTable *_bundleTable;
+ CompTable *_compTable;
int32 _numFiles;
int32 _curSample;
File _file;
+ bool _compTableLoaded;
+ int _fileBundleId;
+ byte _blockChache[0x2000];
+ int32 _lastCacheOutputSize;
+ int32 _lastBlock;
public:
+
BundleMgr();
~BundleMgr();