From: Alyssa M. <fu...@us...> - 2011-04-25 10:57:08
|
gemrb: Infinity Engine emulator The branch master has been updated via 4a707c626ebdc6506cfdb557f5d1677b65b51a0c (commit) via fa62f77d5e43cabd0907d6b6de8db51537bb65d8 (commit) via 013dafed2d2f49ed0ff583cd87c600581d462c74 (commit) via 88d0fae352df7ce20b73c73b735e28411eac3519 (commit) via 93b3be4e25cbac6083a1ee3e88a7dffe13e5b0a3 (commit) Summary of changes: gemrb/core/CMakeLists.txt | 1 + gemrb/core/System/FileStream.cpp | 1 - .../System/{SlicedStream.cpp => MemoryStream.cpp} | 59 +++++++++----------- .../core/System/{SlicedStream.h => MemoryStream.h} | 14 ++--- gemrb/core/System/SlicedStream.cpp | 27 ++++++++- gemrb/core/System/SlicedStream.h | 2 + gemrb/plugins/AREImporter/AREImporter.cpp | 2 +- gemrb/plugins/BIFImporter/BIFImporter.cpp | 4 +- gemrb/plugins/GAMImporter/GAMImporter.cpp | 2 +- gemrb/plugins/KEYImporter/KEYImporter.cpp | 18 ++++-- gemrb/plugins/KEYImporter/KEYImporter.h | 9 +++ 11 files changed, 86 insertions(+), 53 deletions(-) copy gemrb/core/System/{SlicedStream.cpp => MemoryStream.cpp} (55%) copy gemrb/core/System/{SlicedStream.h => MemoryStream.h} (81%) from 2ffea7a5e8b2389f73437ab4f76a2a9219a95d29 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://gemrb.git.sourceforge.net/git/gitweb.cgi?p=gemrb/gemrb;a=commitdiff;h=4a707c626ebdc6506cfdb557f5d1677b65b51a0c commit 4a707c626ebdc6506cfdb557f5d1677b65b51a0c Author: Alyssa Milburn <fu...@fu...> Date: Mon Apr 25 12:47:24 2011 +0200 Read small (<16k) files into a MemoryStream. This makes reading these small files a lot faster. Heavily based on a patch by tomprince. diff --git a/gemrb/core/System/SlicedStream.cpp b/gemrb/core/System/SlicedStream.cpp index fb746a1..64d2014 100644 --- a/gemrb/core/System/SlicedStream.cpp +++ b/gemrb/core/System/SlicedStream.cpp @@ -20,6 +20,8 @@ #include "System/SlicedStream.h" +#include "System/MemoryStream.h" + #include "win32def.h" #include "errors.h" @@ -103,3 +105,22 @@ int SlicedStream::Seek(int newpos, int type) } return GEM_OK; } + +DataStream* SliceStream(DataStream* str, unsigned long startpos, unsigned long size, bool preservepos) +{ + if (size <= 16384) { + // small (or empty) substream, just read it into a buffer instead of expensive file I/O + unsigned long oldpos; + if (preservepos) + oldpos = str->GetPos(); + str->Seek(startpos, GEM_STREAM_START); + char *data = (char*)malloc(size); + str->Read(data, size); + if (preservepos) + str->Seek(oldpos, GEM_STREAM_START); + + DataStream *mem = new MemoryStream(str->originalfile, data, size); + return mem; + } else + return new SlicedStream(str, startpos, size); +} diff --git a/gemrb/core/System/SlicedStream.h b/gemrb/core/System/SlicedStream.h index a7518de..df11ec4 100644 --- a/gemrb/core/System/SlicedStream.h +++ b/gemrb/core/System/SlicedStream.h @@ -41,4 +41,6 @@ public: int Seek(int pos, int startpos); }; +GEM_EXPORT DataStream* SliceStream(DataStream* str, unsigned long startpos, unsigned long size, bool preservepos = false); + #endif diff --git a/gemrb/plugins/AREImporter/AREImporter.cpp b/gemrb/plugins/AREImporter/AREImporter.cpp index f3918e8..3952dc9 100644 --- a/gemrb/plugins/AREImporter/AREImporter.cpp +++ b/gemrb/plugins/AREImporter/AREImporter.cpp @@ -936,7 +936,7 @@ Map* AREImporter::GetMap(const char *ResRef, bool day_or_night) //actually, Flags&1 signs that the creature //is not loaded yet, so !(Flags&1) means it is embedded if (CreOffset != 0 && !(Flags&1) ) { - crefile = new SlicedStream( str, CreOffset, CreSize ); + crefile = SliceStream( str, CreOffset, CreSize, true ); } else { crefile = gamedata->GetResource( CreResRef, IE_CRE_CLASS_ID ); } diff --git a/gemrb/plugins/BIFImporter/BIFImporter.cpp b/gemrb/plugins/BIFImporter/BIFImporter.cpp index 9da964c..0107951 100644 --- a/gemrb/plugins/BIFImporter/BIFImporter.cpp +++ b/gemrb/plugins/BIFImporter/BIFImporter.cpp @@ -257,7 +257,7 @@ DataStream* BIFImporter::GetStream(unsigned long Resource, unsigned long Type) unsigned int srcResLoc = Resource & 0xFC000; for (unsigned int i = 0; i < tentcount; i++) { if (( tentries[i].resLocator & 0xFC000 ) == srcResLoc) { - return new SlicedStream( stream, tentries[i].dataOffset, + return SliceStream( stream, tentries[i].dataOffset, tentries[i].tileSize * tentries[i].tilesCount ); } } @@ -265,7 +265,7 @@ DataStream* BIFImporter::GetStream(unsigned long Resource, unsigned long Type) ieDword srcResLoc = Resource & 0x3FFF; for (ieDword i = 0; i < fentcount; i++) { if (( fentries[i].resLocator & 0x3FFF ) == srcResLoc) { - return new SlicedStream( stream, fentries[i].dataOffset, + return SliceStream( stream, fentries[i].dataOffset, fentries[i].fileSize ); } } diff --git a/gemrb/plugins/GAMImporter/GAMImporter.cpp b/gemrb/plugins/GAMImporter/GAMImporter.cpp index b2017ad..5c24e6d 100644 --- a/gemrb/plugins/GAMImporter/GAMImporter.cpp +++ b/gemrb/plugins/GAMImporter/GAMImporter.cpp @@ -463,7 +463,7 @@ Actor* GAMImporter::GetActor(Holder<ActorMgr> aM, bool is_in_party ) tmpWord = is_in_party ? (pcInfo.PartyOrder + 1) : 0; if (pcInfo.OffsetToCRE) { - SlicedStream* ms = new SlicedStream( str, pcInfo.OffsetToCRE, pcInfo.CRESize ); + DataStream* ms = SliceStream( str, pcInfo.OffsetToCRE, pcInfo.CRESize ); if (ms) { aM->Open(ms); actor = aM->GetActor(tmpWord); http://gemrb.git.sourceforge.net/git/gitweb.cgi?p=gemrb/gemrb;a=commitdiff;h=fa62f77d5e43cabd0907d6b6de8db51537bb65d8 commit fa62f77d5e43cabd0907d6b6de8db51537bb65d8 Author: Alyssa Milburn <fu...@fu...> Date: Mon Apr 25 12:46:29 2011 +0200 add a simple most-recent BIF cache to KEYImporter diff --git a/gemrb/plugins/KEYImporter/KEYImporter.cpp b/gemrb/plugins/KEYImporter/KEYImporter.cpp index 6c8fdc4..746676f 100644 --- a/gemrb/plugins/KEYImporter/KEYImporter.cpp +++ b/gemrb/plugins/KEYImporter/KEYImporter.cpp @@ -242,7 +242,7 @@ DataStream* KEYImporter::GetStream(const char *resname, ieWord type) if (type == 0) return NULL; if (resources.Lookup( resname, type, ResLocator )) { - int bifnum = ( ResLocator & 0xFFF00000 ) >> 20; + unsigned int bifnum = ( ResLocator & 0xFFF00000 ) >> 20; if (core->GameOnCD && (biffiles[bifnum].cd != 0)) FindBIFOnCD(&biffiles[bifnum]); @@ -252,12 +252,18 @@ DataStream* KEYImporter::GetStream(const char *resname, ieWord type) return NULL; } - PluginHolder<ArchiveImporter> ai(IE_BIF_CLASS_ID); - if (ai->OpenArchive( biffiles[bifnum].path ) == GEM_ERROR) { - print("Cannot open archive %s\n", biffiles[bifnum].path ); - return NULL; + // simple one-BIF cache to avoid opening the same BIF repeatedly + if (lastSeenCache.bifnum != bifnum) { + PluginHolder<ArchiveImporter> ai(IE_BIF_CLASS_ID); + if (ai->OpenArchive( biffiles[bifnum].path ) == GEM_ERROR) { + print("Cannot open archive %s\n", biffiles[bifnum].path ); + return NULL; + } + lastSeenCache.bifnum = bifnum; + lastSeenCache.plugin = ai; } - DataStream* ret = ai->GetStream( ResLocator, type ); + + DataStream* ret = lastSeenCache.plugin->GetStream( ResLocator, type ); if (ret) { strnlwrcpy( ret->filename, resname, 8 ); strcat( ret->filename, "." ); diff --git a/gemrb/plugins/KEYImporter/KEYImporter.h b/gemrb/plugins/KEYImporter/KEYImporter.h index 4ea85f9..fef6799 100644 --- a/gemrb/plugins/KEYImporter/KEYImporter.h +++ b/gemrb/plugins/KEYImporter/KEYImporter.h @@ -21,6 +21,7 @@ #ifndef KEYIMP_H #define KEYIMP_H +#include "ArchiveImporter.h" #include "ResourceSource.h" #include "Dictionary.h" @@ -45,12 +46,20 @@ struct BIFEntry { bool found; }; +struct KEYCache { + KEYCache() { bifnum = 0xffffffff; } + + unsigned int bifnum; + PluginHolder<ArchiveImporter> plugin; +}; class KEYImporter : public ResourceSource { private: std::vector< BIFEntry> biffiles; Dictionary resources; + KEYCache lastSeenCache; + /** Gets the stream assoicated to a RESKey */ DataStream *GetStream(const char *resname, ieWord type); public: http://gemrb.git.sourceforge.net/git/gitweb.cgi?p=gemrb/gemrb;a=commitdiff;h=013dafed2d2f49ed0ff583cd87c600581d462c74 commit 013dafed2d2f49ed0ff583cd87c600581d462c74 Author: Alyssa Milburn <fu...@fu...> Date: Mon Apr 25 12:44:09 2011 +0200 reduce the number of seeks that SlicedStream makes diff --git a/gemrb/core/System/SlicedStream.cpp b/gemrb/core/System/SlicedStream.cpp index 46e752d..fb746a1 100644 --- a/gemrb/core/System/SlicedStream.cpp +++ b/gemrb/core/System/SlicedStream.cpp @@ -33,6 +33,7 @@ SlicedStream::SlicedStream(DataStream* str, int startpos, int size) this->startpos = startpos; strncpy(originalfile, str->originalfile, _MAX_PATH); strncpy(filename, str->filename, sizeof(filename)); + this->str->Seek(this->startpos, GEM_STREAM_START); } SlicedStream::~SlicedStream() @@ -53,7 +54,7 @@ int SlicedStream::Read(void* dest, unsigned int length) return GEM_ERROR; } - str->Seek(startpos + Pos + (Encrypted ? 2 : 0), GEM_STREAM_START); + //str->Seek(startpos + Pos + (Encrypted ? 2 : 0), GEM_STREAM_START); unsigned int c = (unsigned int) str->Read(dest, length); if (c != length) { return GEM_ERROR; @@ -67,7 +68,7 @@ int SlicedStream::Read(void* dest, unsigned int length) int SlicedStream::Write(const void* src, unsigned int length) { - str->Seek(startpos + Pos, GEM_STREAM_START); + //str->Seek(startpos + Pos, GEM_STREAM_START); unsigned int c = (unsigned int) Write(src, length); if (c != length) { return GEM_ERROR; @@ -94,6 +95,7 @@ int SlicedStream::Seek(int newpos, int type) default: return GEM_ERROR; } + str->Seek(startpos + Pos /*+ (Encrypted ? 2 : 0)*/, GEM_STREAM_START); //we went past the buffer if (Pos>size) { print("[Streams]: Invalid seek position: %ld (limit: %ld)\n",Pos, size); http://gemrb.git.sourceforge.net/git/gitweb.cgi?p=gemrb/gemrb;a=commitdiff;h=88d0fae352df7ce20b73c73b735e28411eac3519 commit 88d0fae352df7ce20b73c73b735e28411eac3519 Author: Alyssa Milburn <fu...@fu...> Date: Mon Apr 25 12:43:35 2011 +0200 remove an unneeded seek in FileStream diff --git a/gemrb/core/System/FileStream.cpp b/gemrb/core/System/FileStream.cpp index 518af09..d24ee0b 100644 --- a/gemrb/core/System/FileStream.cpp +++ b/gemrb/core/System/FileStream.cpp @@ -170,7 +170,6 @@ void FileStream::Close() void FileStream::FindLength() { size = str->Length(); - str->SeekStart(0); Pos = 0; } http://gemrb.git.sourceforge.net/git/gitweb.cgi?p=gemrb/gemrb;a=commitdiff;h=93b3be4e25cbac6083a1ee3e88a7dffe13e5b0a3 commit 93b3be4e25cbac6083a1ee3e88a7dffe13e5b0a3 Author: Alyssa Milburn <fu...@fu...> Date: Mon Apr 25 12:42:39 2011 +0200 VFS: Add back MemoryStream. This is a slightly modified version of tomprince's patch. Signed-off-by: Tom Prince <tom...@ua...> diff --git a/gemrb/core/CMakeLists.txt b/gemrb/core/CMakeLists.txt index 2ddec9d..9287fd0 100644 --- a/gemrb/core/CMakeLists.txt +++ b/gemrb/core/CMakeLists.txt @@ -29,6 +29,7 @@ FILE(GLOB gemrb_core_LIB_SRCS "*.cpp" Scriptable/PCStatStruct.cpp System/DataStream.cpp System/FileStream.cpp + System/MemoryStream.cpp System/Logging.cpp System/SlicedStream.cpp System/VFS.cpp diff --git a/gemrb/core/System/MemoryStream.cpp b/gemrb/core/System/MemoryStream.cpp new file mode 100644 index 0000000..eed152c --- /dev/null +++ b/gemrb/core/System/MemoryStream.cpp @@ -0,0 +1,98 @@ +/* GemRB - Infinity Engine Emulator + * Copyright (C) 2003 The GemRB Project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * + */ + +#include "System/MemoryStream.h" + +#include "win32def.h" +#include "errors.h" + +#include "Interface.h" + +MemoryStream::MemoryStream(char *name, void* data, unsigned long size) + : data((char*)data) +{ + this->size = size; + ExtractFileFromPath(filename, name); + strncpy(originalfile, name, _MAX_PATH); +} + +MemoryStream::~MemoryStream() +{ + free(data); +} + +DataStream* MemoryStream::Clone() +{ + void *copy = malloc(size); + memcpy(copy, data, size); + return new MemoryStream(originalfile, copy, size); +} + +int MemoryStream::Read(void* dest, unsigned int length) +{ + //we don't allow partial reads anyway, so it isn't a problem that + //i don't adjust length here (partial reads are evil) + if (Pos+length>size ) { + return GEM_ERROR; + } + + memcpy(dest, data + Pos + (Encrypted ? 2 : 0), length); + if (Encrypted) { + ReadDecrypted( dest, length ); + } + Pos += length; + return length; +} + +int MemoryStream::Write(const void* src, unsigned int length) +{ + if (Pos+length>size ) { + //error("MemoryStream", "We don't support appending to memory streams yet."); + return GEM_ERROR; + } + memcpy(data+Pos, src, length); + Pos += length; + return length; +} + +int MemoryStream::Seek(int newpos, int type) +{ + switch (type) { + case GEM_CURRENT_POS: + Pos += newpos; + break; + + case GEM_STREAM_START: + Pos = newpos; + break; + + case GEM_STREAM_END: + Pos = size - newpos; + + default: + return GEM_ERROR; + } + //we went past the buffer + if (Pos>size) { + print("[Streams]: Invalid seek position: %ld (limit: %ld)\n", Pos, size); + return GEM_ERROR; + } + return GEM_OK; +} diff --git a/gemrb/core/System/MemoryStream.h b/gemrb/core/System/MemoryStream.h new file mode 100644 index 0000000..43b2e21 --- /dev/null +++ b/gemrb/core/System/MemoryStream.h @@ -0,0 +1,42 @@ +/* GemRB - Infinity Engine Emulator + * Copyright (C) 2003 The GemRB Project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * + */ + +#ifndef MEMORYSTREAM_H +#define MEMORYSTREAM_H + +#include "System/DataStream.h" + +#include "exports.h" + +class GEM_EXPORT MemoryStream : public DataStream +{ +private: + char *data; +public: + MemoryStream(char *name, void* data, unsigned long size); + ~MemoryStream(); + DataStream* Clone(); + + int Read(void* dest, unsigned int length); + int Write(const void* src, unsigned int length); + int Seek(int pos, int startpos); +}; + +#endif ----------------------------------------------------------------------- This is an automated email from the git hooks/post-receive script. -- gemrb: Infinity Engine emulator |