Просмотр исходного кода

Revert memory mapped support for LOD files (r881, r886 and r895) because on Windows these files get locked and other applications cannot access them anymore.

Frank Zago 16 лет назад
Родитель
Сommit
5eb067e3fd
5 измененных файлов с 142 добавлено и 131 удалено
  1. 13 8
      client/CBitmapHandler.cpp
  2. 115 106
      hch/CLodHandler.cpp
  3. 12 15
      hch/CLodHandler.h
  4. 1 1
      server/Makefile.am
  5. 1 1
      server/Makefile.in

+ 13 - 8
client/CBitmapHandler.cpp

@@ -17,6 +17,7 @@
  *
  */
 
+boost::mutex bitmap_handler_mx;
 int readNormalNr (int pos, int bytCon, unsigned char * str);
 
 extern DLL_EXPORT CLodHandler *bitmaph;
@@ -340,21 +341,25 @@ SDL_Surface * BitmapHandler::loadBitmap(std::string fname, bool setKey)
 			}
 		}
 	}
-
-	const unsigned char *data = bitmaph->dataptr();
-	data += e->offset;
+	bitmap_handler_mx.lock();
+	fseek(bitmaph->FLOD, e->offset, 0);
 	if (e->size==0) //file is not compressed
 	{
 		pcx = new unsigned char[e->realSize];
-		memcpy(pcx, data, e->realSize);
+		fread((char*)pcx, 1, e->realSize, bitmaph->FLOD);
+		bitmap_handler_mx.unlock();
 	}
 	else 
 	{
-		if (!bitmaph->infs2(data, e->size, e->realSize, pcx))
+		unsigned char * pcd = new unsigned char[e->size];
+		fread((char*)pcd, 1, e->size, bitmaph->FLOD);
+		bitmap_handler_mx.unlock();
+		int res=bitmaph->infs2(pcd,e->size,e->realSize,pcx);
+		if(res!=0)
 		{
-			tlog2<<"an error occurred while extracting file "<<fname<<std::endl;
-			return NULL;
+			tlog2<<"an error "<<res<<" occurred while extracting file "<<fname<<std::endl;
 		}
+		delete [] pcd;
 	}
 	CPCXConv cp;
 	cp.openPCX((char*)pcx,e->realSize);
@@ -362,4 +367,4 @@ SDL_Surface * BitmapHandler::loadBitmap(std::string fname, bool setKey)
 	if(setKey)
 		SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format,0,255,255));
 	return ret;
-}
+}

+ 115 - 106
hch/CLodHandler.cpp

@@ -10,7 +10,6 @@
 #include <boost/algorithm/string.hpp>
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/thread.hpp>
-#include <boost/iostreams/device/mapped_file.hpp>
 #ifdef max
 #undef max
 #endif
@@ -40,12 +39,6 @@ DLL_EXPORT int readNormalNr (int pos, int bytCon, unsigned char * str)
 	else return -1;
 	return ret;
 }
-
-const unsigned char *CLodHandler::dataptr()
-{ 
-	return (const unsigned char *)mmlod->data();
-}
-
 unsigned char * CLodHandler::giveFile(std::string defName, int * length)
 {
 	std::transform(defName.begin(), defName.end(), defName.begin(), (int(*)(int))toupper);
@@ -56,53 +49,43 @@ unsigned char * CLodHandler::giveFile(std::string defName, int * length)
 		return NULL;
 	}
 	if(length) *length = ourEntry->realSize;
-
-	const unsigned char *data = dataptr();
-	data += ourEntry->offset;
-
+	mutex->lock();
+	fseek(FLOD, ourEntry->offset, 0);
 	unsigned char * outp;
 	if (ourEntry->offset<0) //file is in the sprites/ folder; no compression
 	{
 		unsigned char * outp = new unsigned char[ourEntry->realSize];
-		char name[30];
-
-		memset(name,0, sizeof(name));
+		char name[30];memset(name,0,30);
 		strcat(name, myDir.c_str());
 		strcat(name, PATHSEPARATOR);
 		strcat(name,ourEntry->nameStr.c_str());
 		FILE * f = fopen(name,"rb");
 		int result = fread(outp,1,ourEntry->realSize,f);
-
-		if (result<0) {
-			tlog1<<"Error in file reading: " << name << std::endl;
-			delete[] outp;
-			return NULL;
-		}
+		mutex->unlock();
+		if(result<0) {tlog1<<"Error in file reading: "<<name<<std::endl;delete[] outp; return NULL;}
 		else
 			return outp;
 	}
-
-	else if (ourEntry->size==0)
+	else if (ourEntry->size==0) //file is not compressed
 	{
-		//file is not compressed
-		// TODO: we could try to avoid a copy here.
 		outp = new unsigned char[ourEntry->realSize];
-		memcpy(outp, data, ourEntry->realSize);
+		fread((char*)outp, 1, ourEntry->realSize, FLOD);
+		mutex->unlock();
 		return outp;
 	}
-	else
+	else //we will decompress file
 	{
-		//we will decompress file
+		outp = new unsigned char[ourEntry->size];
+		fread((char*)outp, 1, ourEntry->size, FLOD);
+		mutex->unlock();
 		unsigned char * decomp = NULL;
-		if (!infs2(data, ourEntry->size, ourEntry->realSize, decomp))
-		{
-			tlog2<<"an error occurred while extracting file "<<defName<<std::endl;
-		}
+		int decRes = infs2(outp, ourEntry->size, ourEntry->realSize, decomp);
+		delete[] outp;
 		return decomp;
 	}
 	return NULL;
 }
-int CLodHandler::infs(const unsigned char * in, int size, int realSize, std::ofstream & out, int wBits)
+int CLodHandler::infs(unsigned char * in, int size, int realSize, std::ofstream & out, int wBits)
 {
 	int ret;
 	unsigned have;
@@ -178,12 +161,15 @@ int CLodHandler::infs(const unsigned char * in, int size, int realSize, std::ofs
 	return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
 }
 
-DLL_EXPORT bool CLodHandler::infs2(const unsigned char * in, int size, int realSize, unsigned char *& out)
+DLL_EXPORT int CLodHandler::infs2(unsigned char * in, int size, int realSize, unsigned char *& out, int wBits)
 {
 	int ret;
+	unsigned have;
 	z_stream strm;
-
-	out = NULL;
+	unsigned char inx[NLoadHandlerHelp::fCHUNK];
+	unsigned char outx[NLoadHandlerHelp::fCHUNK];
+	out = new unsigned char [realSize];
+	int latPosOut = 0;
 
 	/* allocate inflate state */
 	strm.zalloc = Z_NULL;
@@ -191,33 +177,54 @@ DLL_EXPORT bool CLodHandler::infs2(const unsigned char * in, int size, int realS
 	strm.opaque = Z_NULL;
 	strm.avail_in = 0;
 	strm.next_in = Z_NULL;
-	ret = inflateInit(&strm);
+	ret = inflateInit2(&strm, wBits);
 	if (ret != Z_OK)
 		return ret;
-
-	out = new unsigned char [realSize];
-
-	strm.avail_in = size;
-	strm.next_in = (Bytef *)in;
-	strm.avail_out = realSize;
-	strm.next_out = out;
-	ret = inflate(&strm, Z_FINISH);
-
-	if (ret != Z_STREAM_END)
+	int chunkNumber = 0;
+	do
 	{
-		tlog2 << "Decompression of an object failed (" << (strm.msg ? strm.msg : "not ok")  << ")" << std::endl;
-		delete [] out;
-		out = NULL;
-	}
+		int readBytes = 0;
+		for(int i=0; i<NLoadHandlerHelp::fCHUNK && (chunkNumber * NLoadHandlerHelp::fCHUNK + i)<size; ++i)
+		{
+			inx[i] = in[chunkNumber * NLoadHandlerHelp::fCHUNK + i];
+			++readBytes;
+		}
+		++chunkNumber;
+		strm.avail_in = readBytes;
+		if (strm.avail_in == 0)
+			break;
+		strm.next_in = inx;
 
-	if (ret == Z_OK || strm.avail_out != 0) {
-		// An input parameter was bogus
-		tlog2 << "Warning: unexpected decompressed size" << std::endl;
-	}
+		/* run inflate() on input until output buffer not full */
+		do
+		{
+			strm.avail_out = NLoadHandlerHelp::fCHUNK;
+			strm.next_out = outx;
+			ret = inflate(&strm, Z_NO_FLUSH);
+			//assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
+			switch (ret)
+			{
+				case Z_NEED_DICT:
+					ret = Z_DATA_ERROR;	 /* and fall through */
+				case Z_DATA_ERROR:
+				case Z_MEM_ERROR:
+					(void)inflateEnd(&strm);
+					return ret;
+			}
+			have = NLoadHandlerHelp::fCHUNK - strm.avail_out;
+			for(int oo=0; oo<have; ++oo)
+			{
+				out[latPosOut] = outx[oo];
+				++latPosOut;
+			}
+		} while (strm.avail_out == 0);
 
-	inflateEnd(&strm);
+		/* done when inflate() says it's done */
+	} while (ret != Z_STREAM_END);
 
-	return ret == Z_STREAM_END;
+	/* clean up and return */
+	(void)inflateEnd(&strm);
+	return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
 }
 
 void CLodHandler::extract(std::string FName)
@@ -225,16 +232,13 @@ void CLodHandler::extract(std::string FName)
 	std::ofstream FOut;
 	for (int i=0;i<totalFiles;i++)
 	{
-		const unsigned char *data = dataptr();
-		data += entries[i].offset;
-
-		std::string bufff = (DATA_DIR + FName.substr(0, FName.size()-4) + PATHSEPARATOR + entries[i].nameStr);
+		fseek(FLOD, entries[i].offset, 0);
+		std::string bufff = (DATA_DIR + FName.substr(0, FName.size()-4) + PATHSEPARATOR + (char*)entries[i].name);
 		unsigned char * outp;
 		if (entries[i].size==0) //file is not compressed
 		{
-			// TODO: this could be better written
 			outp = new unsigned char[entries[i].realSize];
-			memcpy(outp, data, entries[i].realSize);
+			fread((char*)outp, 1, entries[i].realSize, FLOD);
 			std::ofstream out;
 			out.open(bufff.c_str(), std::ios::binary);
 			if(!out.is_open())
@@ -252,9 +256,9 @@ void CLodHandler::extract(std::string FName)
 		}
 		else
 		{
-			// TODO: this could be better written
 			outp = new unsigned char[entries[i].size];
-			memcpy(outp, data, entries[i].size);
+			fread((char*)outp, 1, entries[i].size, FLOD);
+			fseek(FLOD, 0, 0);
 			std::ofstream destin;
 			destin.open(bufff.c_str(), std::ios::binary);
 			//int decRes = decompress(outp, entries[i].size, entries[i].realSize, bufff);
@@ -267,6 +271,7 @@ void CLodHandler::extract(std::string FName)
 		}
 		delete[] outp;
 	}
+	fclose(FLOD);
 }
 
 void CLodHandler::extractFile(std::string FName, std::string name)
@@ -274,21 +279,17 @@ void CLodHandler::extractFile(std::string FName, std::string name)
 	std::transform(name.begin(), name.end(), name.begin(), (int(*)(int))toupper);
 	for (int i=0;i<totalFiles;i++)
 	{
-		std::string buf1 = entries[i].nameStr;
+		std::string buf1 = std::string((char*)entries[i].name);
 		std::transform(buf1.begin(), buf1.end(), buf1.begin(), (int(*)(int))toupper);
 		if(buf1!=name)
 			continue;
-
-		const unsigned char *data = dataptr();
-		data += entries[i].offset;
-
+		fseek(FLOD, entries[i].offset, 0);
 		std::string bufff = (FName);
 		unsigned char * outp;
 		if (entries[i].size==0) //file is not compressed
 		{
-			// TODO: this could be better written
 			outp = new unsigned char[entries[i].realSize];
-			memcpy(outp, data, entries[i].realSize);
+			fread((char*)outp, 1, entries[i].realSize, FLOD);
 			std::ofstream out;
 			out.open(bufff.c_str(), std::ios::binary);
 			if(!out.is_open())
@@ -306,9 +307,9 @@ void CLodHandler::extractFile(std::string FName, std::string name)
 		}
 		else //we will decompressing file
 		{
-			// TODO: this could be better written
 			outp = new unsigned char[entries[i].size];
-			memcpy(outp, data, entries[i].size);
+			fread((char*)outp, 1, entries[i].size, FLOD);
+			fseek(FLOD, 0, 0);
 			std::ofstream destin;
 			destin.open(bufff.c_str(), std::ios::binary);
 			//int decRes = decompress(outp, entries[i].size, entries[i].realSize, bufff);
@@ -323,7 +324,7 @@ void CLodHandler::extractFile(std::string FName, std::string name)
 	}
 }
 
-int CLodHandler::readNormalNr (const unsigned char* bufor, int bytCon, bool cyclic)
+int CLodHandler::readNormalNr (unsigned char* bufor, int bytCon, bool cyclic)
 {
 	int ret=0;
 	int amp=1;
@@ -339,47 +340,56 @@ int CLodHandler::readNormalNr (const unsigned char* bufor, int bytCon, bool cycl
 	return ret;
 }
 
-void CLodHandler::init(const std::string lodFile, const std::string dirName)
+void CLodHandler::init(std::string lodFile, std::string dirName)
 {
 	myDir = dirName;
+	mutex = new boost::mutex;
 	std::string Ts;
-
-	mmlod = new boost::iostreams::mapped_file_source(lodFile);
-	if(!mmlod->is_open())
+	FLOD = fopen(lodFile.c_str(), "rb");
+	if(!FLOD)
 	{
-		delete mmlod;
-		mmlod = NULL;
 		tlog1 << "Cannot open " << lodFile << std::endl;
 		return;
 	}
-
-	const unsigned char *data = dataptr();
-
-	totalFiles = readNormalNr(&data[8], 4);
-	data += 0x5c;
-
-	for (unsigned int i=0; i<totalFiles; i++)
+	fseek(FLOD, 8, 0);
+	unsigned char temp[4];
+	fread((char*)temp, 1, 4, FLOD);
+	totalFiles = readNormalNr(temp,4);
+	fseek(FLOD, 0x5c, 0);
+	for (int i=0; i<totalFiles; i++)
 	{
 		Entry entry;
-
+		char * bufc = new char;
+		bool appending = true;
 		for(int kk=0; kk<12; ++kk)
-        {
-            if (data[kk] !=0 )
-				entry.nameStr+=toupper(data[kk]);
-            else
-				break;
-        }
-		data += 16;
-
-		entry.offset=readNormalNr(data, 4);
-		data += 4;
-
-		entry.realSize=readNormalNr(data, 4);
-		data += 8;
-
-		entry.size=readNormalNr(data, 4);
-		data += 4;
-
+		{
+			//FLOD.read(bufc, 1);
+			fread(bufc, 1, 1, FLOD);
+			if(appending)
+			{
+				entry.name[kk] = toupper(*bufc);
+			}
+			else
+			{
+				entry.name[kk] = 0;
+				appending = false;
+			}
+		}
+		delete bufc;
+		fread((char*)entry.hlam_1, 1, 4, FLOD);
+		fread((char*)temp, 1, 4, FLOD);
+		entry.offset=readNormalNr(temp,4);
+		fread((char*)temp, 1, 4, FLOD);
+		entry.realSize=readNormalNr(temp,4);
+		fread((char*)entry.hlam_2, 1, 4, FLOD);
+		fread((char*)temp, 1, 4, FLOD);
+		entry.size=readNormalNr(temp,4);
+		for (int z=0;z<12;z++)
+		{
+			if (entry.name[z])
+				entry.nameStr+=entry.name[z];
+			else break;
+		}
 		entries.push_back(entry);
 	}
 	boost::filesystem::directory_iterator enddir;
@@ -418,7 +428,6 @@ std::string CLodHandler::getTextFile(std::string name)
 {
 	int length=-1;
 	unsigned char* data = giveFile(name,&length);
-
 	std::string ret;
 	ret.reserve(length);
 	for(int i=0;i<length;i++)

+ 12 - 15
hch/CLodHandler.h

@@ -19,7 +19,8 @@
 struct SDL_Surface;
 class CDefHandler;
 class CDefEssential;
-namespace boost{ namespace iostreams { class mapped_file_source; }};
+namespace boost
+{class mutex;};
 namespace NLoadHandlerHelp
 {
 	const int dmHelp=0, dmNoExtractingMask=1;
@@ -29,13 +30,13 @@ namespace NLoadHandlerHelp
 
 struct Entry
 {
-	// Info extracted from LOD file
+	unsigned char name[12], //filename
+		hlam_1[4], //???
+		hlam_2[4]; //probably type of file
+	std::string nameStr;
 	int offset, //from beginning
 		realSize, //size without compression
 		size;	//and with
-
-	std::string nameStr;
-
 	bool operator<(const std::string & comp) const
 	{
 		return nameStr<comp;
@@ -50,25 +51,21 @@ struct Entry
 };
  class DLL_EXPORT CLodHandler
 {
-private:
-	boost::iostreams::mapped_file_source* mmlod;
-
 public:
+	FILE* FLOD;
 	nodrze<Entry> entries;
 	unsigned int totalFiles;
+	boost::mutex *mutex;
 	std::string myDir; //load files from this dir instead of .lod file
 
-    CLodHandler(): mmlod(NULL), totalFiles(0) {};
-	int readNormalNr (const unsigned char* bufor, int bytCon, bool cyclic=false); //lod header reading helper
-	int infs(const unsigned char * in, int size, int realSize, std::ofstream & out, int wBits=15); //zlib fast handler
-	bool infs2(const unsigned char * in, int size, int realSize, unsigned char*& out); //zlib fast handler
+	int readNormalNr (unsigned char* bufor, int bytCon, bool cyclic=false); //lod header reading helper
+	int infs(unsigned char * in, int size, int realSize, std::ofstream & out, int wBits=15); //zlib fast handler
+	int infs2(unsigned char * in, int size, int realSize, unsigned char*& out, int wBits=15); //zlib fast handler
 	unsigned char * giveFile(std::string defName, int * length=NULL); //returns pointer to the decompressed data - it must be deleted when no longer needed!
 	std::string getTextFile(std::string name); //extracts one file
 	void extract(std::string FName);
 	void extractFile(std::string FName, std::string name); //extracts a specific file
-	void init(const std::string lodFile, const std::string dirName);
-
-	const unsigned char *dataptr();	// Returns ptr to FLOD data array
+	void init(std::string lodFile, std::string dirName);
 };
 
 

+ 1 - 1
server/Makefile.am

@@ -1,6 +1,6 @@
 bin_PROGRAMS = vcmiserver
 
-vcmiserver_LDADD = $(top_builddir)/lib/libvcmi.la @BOOST_SYSTEM_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_THREAD_LIB@ @BOOST_IOSTREAMS_LIB@ -lz
+vcmiserver_LDADD = $(top_builddir)/lib/libvcmi.la @BOOST_SYSTEM_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_THREAD_LIB@ -lz
 vcmiserver_LDFLAGS = -L$(top_builddir)/lib
 vcmiserver_SOURCES = \
 	CGameHandler.cpp \

+ 1 - 1
server/Makefile.in

@@ -211,7 +211,7 @@ target_alias = @target_alias@
 top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-vcmiserver_LDADD = $(top_builddir)/lib/libvcmi.la @BOOST_SYSTEM_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_THREAD_LIB@ @BOOST_IOSTREAMS_LIB@ -lz
+vcmiserver_LDADD = $(top_builddir)/lib/libvcmi.la @BOOST_SYSTEM_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_THREAD_LIB@ -lz
 vcmiserver_LDFLAGS = -L$(top_builddir)/lib
 vcmiserver_SOURCES = \
 	CGameHandler.cpp \