1536 lines
48 KiB
Diff
1536 lines
48 KiB
Diff
Index: lib/CLodHandler.cpp
|
|
===================================================================
|
|
--- lib/CLodHandler.cpp (revision 2387)
|
|
+++ lib/CLodHandler.cpp (working copy)
|
|
@@ -87,13 +87,15 @@
|
|
Entry ourEntry = *en_it;
|
|
|
|
if(length) *length = ourEntry.realSize;
|
|
+ enum { SAFETY_MARGIN = 4096 }; // VCMI functions tend to read past the array end, crashing at random
|
|
mutex->lock();
|
|
|
|
unsigned char * outp;
|
|
if (ourEntry.offset<0) //file is in the sprites/ folder; no compression
|
|
{
|
|
int result;
|
|
- outp = new unsigned char[ourEntry.realSize];
|
|
+ outp = new unsigned char[ourEntry.realSize+SAFETY_MARGIN];
|
|
+ memset(outp+ourEntry.realSize, 0, SAFETY_MARGIN);
|
|
FILE * f = fopen((myDir + "/" + ourEntry.realName).c_str(), "rb");
|
|
if (f)
|
|
{
|
|
@@ -109,16 +111,21 @@
|
|
delete[] outp;
|
|
return NULL;
|
|
}
|
|
- else
|
|
+ else
|
|
+ {
|
|
+ //tlog0 << "Loaded file: " << fname << " size " << ourEntry.realSize << " ptr " << (void *)outp << " safety " << (int)SAFETY_MARGIN << std::endl;
|
|
return outp;
|
|
+ }
|
|
}
|
|
else if (ourEntry.size==0) //file is not compressed
|
|
{
|
|
- outp = new unsigned char[ourEntry.realSize];
|
|
+ outp = new unsigned char[ourEntry.realSize+SAFETY_MARGIN];
|
|
+ memset(outp+ourEntry.realSize, 0, SAFETY_MARGIN);
|
|
|
|
LOD.seekg(ourEntry.offset, std::ios::beg);
|
|
LOD.read((char*)outp, ourEntry.realSize);
|
|
mutex->unlock();
|
|
+ //tlog0 << "Loaded file: " << fname << " size " << ourEntry.realSize << " ptr " << (void *)outp << " safety " << (int)SAFETY_MARGIN << std::endl;
|
|
return outp;
|
|
}
|
|
else //we will decompress file
|
|
@@ -131,7 +138,12 @@
|
|
infs2(outp, ourEntry.size, ourEntry.realSize, decomp);
|
|
mutex->unlock();
|
|
delete[] outp;
|
|
- return decomp;
|
|
+ outp = new unsigned char[ourEntry.realSize+SAFETY_MARGIN];
|
|
+ memset(outp+ourEntry.realSize, 0, SAFETY_MARGIN);
|
|
+ memcpy(outp, decomp, ourEntry.realSize);
|
|
+ delete [] decomp;
|
|
+ //tlog0 << "Loaded file: " << fname << " size " << ourEntry.realSize << " ptr " << (void *)outp << " safety " << (int)SAFETY_MARGIN << std::endl;
|
|
+ return outp;
|
|
}
|
|
return NULL;
|
|
}
|
|
Index: lib/Interprocess.h
|
|
===================================================================
|
|
--- lib/Interprocess.h (revision 2387)
|
|
+++ lib/Interprocess.h (working copy)
|
|
@@ -1,3 +1,4 @@
|
|
+/*
|
|
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
|
#include <boost/interprocess/sync/interprocess_condition.hpp>
|
|
#include <boost/interprocess/mapped_region.hpp>
|
|
@@ -2,2 +3,3 @@
|
|
#include <boost/interprocess/shared_memory_object.hpp>
|
|
+*/
|
|
|
|
@@ -13,6 +15,7 @@
|
|
*
|
|
*/
|
|
|
|
+/*
|
|
struct ServerReady
|
|
{
|
|
bool ready;
|
|
@@ -51,4 +54,48 @@
|
|
delete mr;
|
|
boost::interprocess::shared_memory_object::remove("vcmi_memory");
|
|
}
|
|
-};
|
|
\ No newline at end of file
|
|
+};
|
|
+*/
|
|
+
|
|
+#include <stdio.h>
|
|
+#ifdef WIN32
|
|
+#include <windows.h>
|
|
+#else
|
|
+#include <unistd.h>
|
|
+#endif
|
|
+#include "VCMIDirs.h"
|
|
+
|
|
+#define SERVER_READY_FILENAME "/VcmiServerReadyFlag.lock"
|
|
+
|
|
+void clearServerReady()
|
|
+{
|
|
+ unlink((GVCMIDirs.UserPath + SERVER_READY_FILENAME).c_str());
|
|
+}
|
|
+
|
|
+void waitServerReady()
|
|
+{
|
|
+ while(true)
|
|
+ {
|
|
+ FILE * ff = fopen((GVCMIDirs.UserPath + SERVER_READY_FILENAME).c_str(), "r");
|
|
+ if(ff)
|
|
+ {
|
|
+ fclose(ff);
|
|
+ clearServerReady();
|
|
+ break;
|
|
+ }
|
|
+#ifdef WIN32
|
|
+ Sleep(200);
|
|
+#else
|
|
+ usleep(200000);
|
|
+#endif
|
|
+ }
|
|
+}
|
|
+
|
|
+void notifyServerReady()
|
|
+{
|
|
+ FILE * ff = fopen((GVCMIDirs.UserPath + SERVER_READY_FILENAME).c_str(), "w");
|
|
+ if(!ff)
|
|
+ return;
|
|
+ fwrite("1", 1, 1, ff);
|
|
+ fclose(ff);
|
|
+}
|
|
Index: lib/Connection.h
|
|
===================================================================
|
|
--- lib/Connection.h (revision 2387)
|
|
+++ lib/Connection.h (working copy)
|
|
@@ -82,7 +82,9 @@
|
|
{
|
|
bool operator()(const std::type_info *a, const std::type_info *b) const
|
|
{
|
|
- return a->before(*b);
|
|
+ // Comparing pointers is bad bad practice, because type_info pointers to the same types
|
|
+ // are different inside shared library and the executable that links to that library
|
|
+ return strcmp(a->name(), b->name()) > 0;
|
|
}
|
|
};
|
|
|
|
Index: server/stdafx.h
|
|
===================================================================
|
|
--- server/stdafx.h (revision 2387)
|
|
+++ server/stdafx.h (working copy)
|
|
@@ -15,8 +15,8 @@
|
|
#include "../global.h"
|
|
|
|
#include <boost/crc.hpp>
|
|
-#include <boost/interprocess/mapped_region.hpp>
|
|
-#include <boost/interprocess/shared_memory_object.hpp>
|
|
+//#include <boost/interprocess/mapped_region.hpp>
|
|
+//#include <boost/interprocess/shared_memory_object.hpp>
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <boost/asio.hpp>
|
|
Index: server/CVCMIServer.cpp
|
|
===================================================================
|
|
--- server/CVCMIServer.cpp (revision 2387)
|
|
+++ server/CVCMIServer.cpp (working copy)
|
|
@@ -29,7 +29,7 @@
|
|
using namespace boost;
|
|
using namespace boost::asio;
|
|
using namespace boost::asio::ip;
|
|
-namespace intpr = boost::interprocess;
|
|
+//namespace intpr = boost::interprocess;
|
|
bool end2 = false;
|
|
int port = 3030;
|
|
VCMIDirs GVCMIDirs;
|
|
@@ -379,6 +379,7 @@
|
|
|
|
void CVCMIServer::start()
|
|
{
|
|
+ /*
|
|
ServerReady *sr = NULL;
|
|
intpr::mapped_region *mr;
|
|
try
|
|
@@ -395,13 +396,17 @@
|
|
mr = new intpr::mapped_region(smo,intpr::read_write);
|
|
sr = new(mr->get_address())ServerReady();
|
|
}
|
|
+ */
|
|
+ notifyServerReady();
|
|
|
|
boost::system::error_code error;
|
|
tlog0<<"Listening for connections at port " << acceptor->local_endpoint().port() << std::endl;
|
|
tcp::socket * s = new tcp::socket(acceptor->get_io_service());
|
|
boost::thread acc(boost::bind(vaccept,acceptor,s,&error));
|
|
+ /*
|
|
sr->setToTrueAndNotify();
|
|
delete mr;
|
|
+ */
|
|
|
|
acc.join();
|
|
if (error)
|
|
Index: server/CGameHandler.cpp
|
|
===================================================================
|
|
--- server/CGameHandler.cpp (revision 2387)
|
|
+++ server/CGameHandler.cpp (working copy)
|
|
@@ -638,6 +638,7 @@
|
|
(packType != typeList.getTypeID<ArrangeStacks>() || !isAllowedArrangePack((ArrangeStacks*)pack)) && // for dialogs like garrison
|
|
states[getCurrentPlayer()].queries.size())
|
|
{
|
|
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ << std::endl;
|
|
complain("Answer the query before attempting any further actions!");
|
|
PackageApplied applied;
|
|
applied.result = false;
|
|
@@ -650,6 +651,7 @@
|
|
else if(apply)
|
|
{
|
|
bool result = apply->applyOnGH(this,&c,pack);
|
|
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ << std::endl;
|
|
tlog5 << "Message successfully applied (result=" << result << ")!\n";
|
|
|
|
//send confirmation that we've applied the package
|
|
@@ -1833,7 +1835,7 @@
|
|
iw.player = h1->tempOwner;
|
|
iw.components.push_back(Component(Component::SEC_SKILL, 18, ScholarLevel, 0));
|
|
|
|
- iw.text.addTxt(MetaString::GENERAL_TXT, 139);//"%s, who has studied magic extensively,
|
|
+ iw.text.addTxt(MetaString::GENERAL_TXT, 139);//%s, who has studied magic extensively,
|
|
iw.text.addReplacement(h1->name);
|
|
|
|
if (cs2.spells.size())//if found new spell - apply
|
|
Index: CConsoleHandler.cpp
|
|
===================================================================
|
|
--- CConsoleHandler.cpp (revision 2387)
|
|
+++ CConsoleHandler.cpp (working copy)
|
|
@@ -143,6 +143,7 @@
|
|
|
|
void CConsoleHandler::setColor(int level)
|
|
{
|
|
+#ifndef ANDROID
|
|
TColor color;
|
|
switch(level)
|
|
{
|
|
@@ -179,6 +180,7 @@
|
|
#else
|
|
std::cout << color;
|
|
#endif
|
|
+#endif
|
|
}
|
|
|
|
int CConsoleHandler::run()
|
|
Index: global.h
|
|
===================================================================
|
|
--- global.h (revision 2387)
|
|
+++ global.h (working copy)
|
|
@@ -4,6 +4,7 @@
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <algorithm> //std::find
|
|
+#include <string.h> //memcpy
|
|
#include <string> //std::find
|
|
#include <boost/logic/tribool.hpp>
|
|
#include <boost/unordered_set.hpp>
|
|
@@ -725,29 +726,21 @@
|
|
}
|
|
|
|
|
|
-#if defined(linux) && defined(sparc)
|
|
-/* SPARC does not support unaligned memory access. Let gcc know when
|
|
- * to emit the right code. */
|
|
-struct unaligned_Uint16 { ui16 val __attribute__(( packed )); };
|
|
-struct unaligned_Uint32 { ui32 val __attribute__(( packed )); };
|
|
|
|
static inline ui16 read_unaligned_u16(const void *p)
|
|
{
|
|
- const struct unaligned_Uint16 *v = (const struct unaligned_Uint16 *)p;
|
|
- return v->val;
|
|
+ ui16 out;
|
|
+ memcpy(&out, p, sizeof(out));
|
|
+ return out;
|
|
}
|
|
|
|
static inline ui32 read_unaligned_u32(const void *p)
|
|
{
|
|
- const struct unaligned_Uint32 *v = (const struct unaligned_Uint32 *)p;
|
|
- return v->val;
|
|
+ ui32 out;
|
|
+ memcpy(&out, p, sizeof(out));
|
|
+ return out;
|
|
}
|
|
|
|
-#else
|
|
-#define read_unaligned_u16(p) (* reinterpret_cast<const Uint16 *>(p))
|
|
-#define read_unaligned_u32(p) (* reinterpret_cast<const Uint32 *>(p))
|
|
-#endif
|
|
-
|
|
//for explicit overrides
|
|
#ifdef _MSC_VER
|
|
#define OVERRIDE override
|
|
Index: AI/GeniusAI/neuralNetwork.cpp
|
|
===================================================================
|
|
--- AI/GeniusAI/neuralNetwork.cpp (revision 2387)
|
|
+++ AI/GeniusAI/neuralNetwork.cpp (working copy)
|
|
@@ -14,9 +14,9 @@
|
|
static bool in = 0;
|
|
if(!in)
|
|
{
|
|
- float x = (rand()+1)/float(RAND_MAX+1);
|
|
+ float x = (rand())/float(RAND_MAX);
|
|
float f = sqrtf( - 2.0f * log(x) );
|
|
- x = (rand()+1)/float(RAND_MAX+1);
|
|
+ x = (rand())/float(RAND_MAX);
|
|
kept = f * cosf( 2.0f * M_PI * x );
|
|
in = true;
|
|
return f * sinf( 2.0f * M_PI * x );
|
|
Index: Scripting/ERM/ERMParser.cpp
|
|
===================================================================
|
|
--- Scripting/ERM/ERMParser.cpp (revision 2387)
|
|
+++ Scripting/ERM/ERMParser.cpp (working copy)
|
|
@@ -2,7 +2,7 @@
|
|
#include <boost/version.hpp>
|
|
//To make compilation with older boost versions possible
|
|
//Don't know exact version - 1.46 works while 1.42 not
|
|
-#if BOOST_VERSION >= 104600
|
|
+#if BOOST_VERSION >= 104500
|
|
|
|
#include <boost/spirit/include/qi.hpp>
|
|
#include <boost/bind.hpp>
|
|
Index: client/Graphics.cpp
|
|
===================================================================
|
|
--- client/Graphics.cpp (revision 2387)
|
|
+++ client/Graphics.cpp (working copy)
|
|
@@ -315,8 +315,15 @@
|
|
tasks += GET_SURFACE(backgroundsm[id], b["bg120"].String());
|
|
}
|
|
|
|
+#ifdef ANDROID
|
|
+ // For debug make it single-threaded
|
|
+ for(int i=0;i<tasks.size();i++)
|
|
+ tasks[i]();
|
|
+#else
|
|
CThreadHelper th(&tasks,std::max((unsigned int)1,boost::thread::hardware_concurrency()));
|
|
th.run();
|
|
+#endif
|
|
+
|
|
|
|
for(size_t y=0; y < heroMoveArrows->ourImages.size(); ++y)
|
|
{
|
|
@@ -508,13 +515,20 @@
|
|
pr[3].first = &Graphics::flags4;
|
|
pr[3].second+=("AF00.DEF"),("AF01.DEF"),("AF02.DEF"),("AF03.DEF"),("AF04.DEF"),
|
|
("AF05.DEF"),("AF06.DEF"),("AF07.DEF");
|
|
+#ifdef ANDROID
|
|
+ // We ain't no need any filthy multithreading
|
|
+ for(int g=0; g<4; g++)
|
|
+ {
|
|
+ loadHeroFlags(pr[g],true);
|
|
+ }
|
|
+#else
|
|
boost::thread_group grupa;
|
|
for(int g=3; g>=0; --g)
|
|
{
|
|
grupa.create_thread(boost::bind(&Graphics::loadHeroFlags,this,boost::ref(pr[g]),true));
|
|
}
|
|
grupa.join_all();
|
|
- tlog0 << "Loading and transforming heroes' flags: "<<th.getDif()<<std::endl;
|
|
+#endif
|
|
}
|
|
SDL_Surface * Graphics::getPic(int ID, bool fort, bool builded)
|
|
{
|
|
@@ -677,7 +691,7 @@
|
|
return NULL;
|
|
}
|
|
|
|
- int magic = *(const int*)hlp;
|
|
+ int magic = read_unaligned_u32(hlp);
|
|
if(len < 10000 || (magic != 589598 && magic != 589599))
|
|
{
|
|
tlog1 << "Suspicious font file (length " << len <<", fname " << name << "), logging to suspicious_" << name << ".fnt\n";
|
|
Index: client/SDL_Extensions.cpp
|
|
===================================================================
|
|
--- client/SDL_Extensions.cpp (revision 2387)
|
|
+++ client/SDL_Extensions.cpp (working copy)
|
|
@@ -119,8 +119,8 @@
|
|
if(incrementPtr == -1)
|
|
ptr -= 2;
|
|
|
|
- Uint16 * const px = (Uint16*)ptr;
|
|
- *px = (B>>3) + ((G>>2) << 5) + ((R>>3) << 11); //drop least significant bits of 24 bpp encoded color
|
|
+ Uint16 px = (B>>3) + ((G>>2) << 5) + ((R>>3) << 11); //drop least significant bits of 24 bpp encoded color
|
|
+ memcpy(ptr, &px, sizeof(px));
|
|
|
|
if(incrementPtr == 1)
|
|
ptr += 2; //bpp
|
|
@@ -150,9 +150,9 @@
|
|
const int rmask = 0xF800, gmask = 0x7E0, bmask = 0x1F;
|
|
const int rshift = 11, gshift = 5, bshift = 0;
|
|
|
|
- const Uint8 r5 = (*((Uint16 *)ptr) & rmask) >> rshift,
|
|
- b5 = (*((Uint16 *)ptr) & bmask) >> bshift,
|
|
- g5 = (*((Uint16 *)ptr) & gmask) >> gshift;
|
|
+ const Uint8 r5 = (read_unaligned_u16(ptr) & rmask) >> rshift,
|
|
+ b5 = (read_unaligned_u16(ptr) & bmask) >> bshift,
|
|
+ g5 = (read_unaligned_u16(ptr) & gmask) >> gshift;
|
|
|
|
const Uint32 r8 = (r5 << (8 - rbit)) | (r5 >> (2*rbit - 8)),
|
|
g8 = (g5 << (8 - gbit)) | (g5 >> (2*gbit - 8)),
|
|
@@ -649,7 +649,7 @@
|
|
return *p;
|
|
|
|
case 2:
|
|
- return *(Uint16 *)p;
|
|
+ return read_unaligned_u16(p);
|
|
|
|
case 3:
|
|
/*
|
|
@@ -661,7 +661,7 @@
|
|
//#endif
|
|
|
|
case 4:
|
|
- return *(Uint32 *)p;
|
|
+ return read_unaligned_u32(p);
|
|
|
|
default:
|
|
return 0; // shouldn't happen, but avoids warnings
|
|
Index: client/Client.cpp
|
|
===================================================================
|
|
--- client/Client.cpp (revision 2387)
|
|
+++ client/Client.cpp (working copy)
|
|
@@ -41,7 +41,7 @@
|
|
#include "../lib/RegisterTypes.cpp"
|
|
|
|
extern std::string NAME;
|
|
-namespace intpr = boost::interprocess;
|
|
+//namespace intpr = boost::interprocess;
|
|
|
|
/*
|
|
* Client.cpp, part of VCMI engine
|
|
@@ -476,9 +476,9 @@
|
|
|
|
void CClient::handlePack( CPack * pack )
|
|
{
|
|
- CBaseForCLApply *apply = applier->apps[typeList.getTypeID(pack)]; //find the applier
|
|
- if(apply)
|
|
+ if(applier->apps.find(typeList.getTypeID(pack)) != applier->apps.end())
|
|
{
|
|
+ CBaseForCLApply *apply = applier->apps[typeList.getTypeID(pack)]; //find the applier
|
|
apply->applyOnClBefore(this,pack);
|
|
tlog5 << "\tMade first apply on cl\n";
|
|
gs->apply(pack);
|
|
@@ -639,18 +639,22 @@
|
|
startServer();
|
|
|
|
th.update();
|
|
+ /*
|
|
intpr::scoped_lock<intpr::interprocess_mutex> slock(shared->sr->mutex);
|
|
while(!shared->sr->ready)
|
|
{
|
|
shared->sr->cond.wait(slock);
|
|
}
|
|
+ */
|
|
+ tlog0 << "Waiting for server..." << std::endl;
|
|
+ waitServerReady();
|
|
if(verbose)
|
|
tlog0 << "Waiting for server: " << th.getDif() << std::endl;
|
|
}
|
|
|
|
CConnection * CServerHandler::connectToServer()
|
|
{
|
|
- if(!shared->sr->ready)
|
|
+ if(!serverThread)
|
|
waitForServer();
|
|
|
|
th.update();
|
|
@@ -665,27 +669,31 @@
|
|
CServerHandler::CServerHandler(bool runServer /*= false*/)
|
|
{
|
|
serverThread = NULL;
|
|
- shared = NULL;
|
|
+ //shared = NULL;
|
|
port = boost::lexical_cast<std::string>(conf.cc.port);
|
|
verbose = false;
|
|
|
|
+ /*
|
|
boost::interprocess::shared_memory_object::remove("vcmi_memory"); //if the application has previously crashed, the memory may not have been removed. to avoid problems - try to destroy it
|
|
try
|
|
{
|
|
shared = new SharedMem();
|
|
} HANDLE_EXCEPTIONC(tlog1 << "Cannot open interprocess memory: ";)
|
|
+ */
|
|
}
|
|
|
|
CServerHandler::~CServerHandler()
|
|
{
|
|
- delete shared;
|
|
+ //delete shared;
|
|
delete serverThread; //detaches, not kills thread
|
|
}
|
|
|
|
void CServerHandler::callServer()
|
|
{
|
|
+ clearServerReady();
|
|
setThreadName(-1, "CServerHandler::callServer");
|
|
std::string comm = std::string(BIN_DIR PATH_SEPARATOR SERVER_NAME " ") + port + " > server_log.txt";
|
|
+ tlog0 << "Invoking VCMI server : " << comm << std::endl;
|
|
std::system(comm.c_str());
|
|
tlog0 << "Server finished\n";
|
|
}
|
|
Index: client/GUIBase.cpp
|
|
===================================================================
|
|
--- client/GUIBase.cpp (revision 2387)
|
|
+++ client/GUIBase.cpp (working copy)
|
|
@@ -11,6 +11,7 @@
|
|
#include "../CThreadHelper.h"
|
|
#include "CConfigHandler.h"
|
|
#include <boost/lexical_cast.hpp>
|
|
+
|
|
|
|
/*
|
|
* GUIBase.cpp, part of VCMI engine
|
|
@@ -365,6 +366,26 @@
|
|
}
|
|
} HANDLE_EXCEPTION
|
|
}
|
|
+
|
|
+void CGuiHandler::loopInitFromMainThread()
|
|
+{
|
|
+ setThreadName(-1, "CGuiHandler::run");
|
|
+ CCS->curh->centerCursor();
|
|
+ mainFPSmng->init(); // resets internal clock, needed for FPS manager
|
|
+}
|
|
+
|
|
+bool CGuiHandler::loopFromMainThread()
|
|
+{
|
|
+ if(terminate)
|
|
+ return false;
|
|
+ if(curInt)
|
|
+ curInt->update(); // calls a update and drawing process of the loaded game interface object at the moment
|
|
+
|
|
+ mainFPSmng->framerateDelay(); // holds a constant FPS
|
|
+ return true;
|
|
+}
|
|
+
|
|
+
|
|
|
|
CGuiHandler::CGuiHandler()
|
|
:lastClick(-500, -500)
|
|
Index: client/CAnimation.h
|
|
===================================================================
|
|
--- client/CAnimation.h (revision 2387)
|
|
+++ client/CAnimation.h (working copy)
|
|
@@ -47,6 +47,8 @@
|
|
std::map<size_t, std::vector <size_t> > offset;
|
|
|
|
unsigned char * data;
|
|
+ int lodLength;
|
|
+ std::string fname;
|
|
SDL_Color * palette;
|
|
|
|
public:
|
|
@@ -125,6 +127,8 @@
|
|
* 2nd byte = size of segment
|
|
* raw data (if any)
|
|
*/
|
|
+// Buggy, disabled for Android
|
|
+/*
|
|
class CompImage : public IImage
|
|
{
|
|
//x,y - margins, w,h - sprite size
|
|
@@ -158,8 +162,8 @@
|
|
|
|
friend class CompImageLoader;
|
|
};
|
|
+*/
|
|
|
|
-
|
|
/// Class for handling animation
|
|
class CAnimation
|
|
{
|
|
Index: client/CDefHandler.h
|
|
===================================================================
|
|
--- client/CDefHandler.h (revision 2387)
|
|
+++ client/CDefHandler.h (working copy)
|
|
@@ -30,7 +30,6 @@
|
|
ui32 totalInBlock;
|
|
ui32 unknown2;
|
|
ui32 unknown3;
|
|
- unsigned char data[0];
|
|
};
|
|
|
|
// Def entry in file. Integer fields are all little endian and will
|
|
@@ -94,9 +93,9 @@
|
|
|
|
CDefHandler(); //c-tor
|
|
~CDefHandler(); //d-tor
|
|
- SDL_Surface * getSprite (int SIndex, const unsigned char * FDef, const BMPPalette * palette) const; //saves picture with given number to "testtt.bmp"
|
|
+ SDL_Surface * getSprite (int SIndex, const unsigned char * FDef, const BMPPalette * palette, const std::string & name, int lodLength) const; //saves picture with given number to "testtt.bmp"
|
|
static void expand(unsigned char N,unsigned char & BL, unsigned char & BR);
|
|
- void openFromMemory(unsigned char * table, const std::string & name);
|
|
+ void openFromMemory(unsigned char * table, const std::string & name, int lodLength);
|
|
CDefEssential * essentialize();
|
|
|
|
static CDefHandler * giveDef(const std::string & defName);
|
|
Index: client/CCreatureAnimation.h
|
|
===================================================================
|
|
--- client/CCreatureAnimation.h (revision 2387)
|
|
+++ client/CCreatureAnimation.h (working copy)
|
|
@@ -66,6 +66,8 @@
|
|
int curFrame, internalFrame; //number of currently displayed frame
|
|
unsigned int frames; //number of frames
|
|
CCreatureAnim::EAnimType type; //type of animation being displayed (-1 - whole animation, >0 - specified part [default: -1])
|
|
+ int lodLength;
|
|
+ std::string fname;
|
|
|
|
template<int bpp>
|
|
int nextFrameT(SDL_Surface * dest, int x, int y, bool attacker, unsigned char animCount, bool incrementFrame = true, bool yellowBorder = false, bool blueBorder = false, SDL_Rect * destRect = NULL); //0 - success, any other - error //print next
|
|
Index: client/CMT.cpp
|
|
===================================================================
|
|
--- client/CMT.cpp (revision 2387)
|
|
+++ client/CMT.cpp (working copy)
|
|
@@ -92,8 +92,10 @@
|
|
void dispose();
|
|
void playIntro();
|
|
static void listenForEvents();
|
|
+static bool loopListenForEvents(bool block);
|
|
void requestChangingResolution();
|
|
void startGame(StartInfo * options, CConnection *serv = NULL);
|
|
+
|
|
|
|
#ifndef _WIN32
|
|
#ifndef _GNU_SOURCE
|
|
@@ -128,6 +130,7 @@
|
|
GDefaultOptions.settingsChanged();
|
|
}
|
|
}
|
|
+
|
|
THC tlog0<<"\tLoading default system settings: "<<pomtime.getDif()<<std::endl;
|
|
|
|
//initializing audio
|
|
@@ -141,6 +144,7 @@
|
|
CCS->musich->setVolume(GDefaultOptions.musicVolume);
|
|
tlog0<<"\tInitializing sound: "<<pomtime.getDif()<<std::endl;
|
|
tlog0<<"Initializing screen and sound handling: "<<tmh.getDif()<<std::endl;
|
|
+
|
|
|
|
initDLL(::console,logfile);
|
|
const_cast<CGameInfo*>(CGI)->setFromLib();
|
|
@@ -154,7 +158,9 @@
|
|
CCS->curh->show();
|
|
tlog0<<"Screen handler: "<<pomtime.getDif()<<std::endl;
|
|
pomtime.getDif();
|
|
+ tlog0<<"Megadebug 1"<<std::endl;
|
|
graphics = new Graphics();
|
|
+ tlog0<<"Megadebug 2"<<std::endl;
|
|
graphics->loadHeroAnims();
|
|
tlog0<<"\tMain graphics: "<<tmh.getDif()<<std::endl;
|
|
tlog0<<"Initializing game graphics: "<<tmh.getDif()<<std::endl;
|
|
@@ -186,11 +192,15 @@
|
|
}
|
|
|
|
|
|
+#ifdef ANDROID
|
|
+int SDL_main(int argc, char** argv)
|
|
+#else
|
|
#ifdef _WIN32
|
|
int _tmain(int argc, _TCHAR* argv[])
|
|
#else
|
|
int main(int argc, char** argv)
|
|
#endif
|
|
+#endif
|
|
{
|
|
tlog0 << "Starting... " << std::endl;
|
|
po::options_description opts("Allowed options");
|
|
@@ -237,7 +247,6 @@
|
|
console->start();
|
|
atexit(dispose);
|
|
tlog0 <<"Creating console and logfile: "<<pomtime.getDif() << std::endl;
|
|
-
|
|
conf.init();
|
|
tlog0 <<"Loading settings: "<<pomtime.getDif() << std::endl;
|
|
tlog0 << NAME << std::endl;
|
|
@@ -266,6 +275,11 @@
|
|
tlog0<<"\tInitializing video: "<<pomtime.getDif()<<std::endl;
|
|
|
|
//we can properly play intro only in the main thread, so we have to move loading to the separate thread
|
|
+#if defined(ANDROID) || defined(LINUX)
|
|
+ init();
|
|
+ if(!vm.count("battle") && !vm.count("nointro"))
|
|
+ playIntro();
|
|
+#else
|
|
boost::thread loading(init);
|
|
|
|
if(!vm.count("battle") && !vm.count("nointro"))
|
|
@@ -274,6 +288,7 @@
|
|
SDL_FillRect(screen,NULL,0);
|
|
CSDL_Ext::update(screen);
|
|
loading.join();
|
|
+#endif
|
|
tlog0<<"Initialization of VCMI (together): "<<total.getDif()<<std::endl;
|
|
|
|
if(!vm.count("battle"))
|
|
@@ -290,8 +305,17 @@
|
|
si->playerInfos[1].color = 1;
|
|
startGame(si);
|
|
}
|
|
+ // Drawing and running event loop from non-main thread does not work at all on Andorid and crashes often on Linux
|
|
+#if defined(ANDROID) || defined(LINUX)
|
|
+ GH.loopInitFromMainThread();
|
|
+ while( GH.loopFromMainThread() )
|
|
+ {
|
|
+ while( loopListenForEvents(false) );
|
|
+ }
|
|
+#else
|
|
mainGUIThread = new boost::thread(&CGuiHandler::run, boost::ref(GH));
|
|
listenForEvents();
|
|
+#endif
|
|
|
|
return 0;
|
|
}
|
|
@@ -561,10 +585,12 @@
|
|
tlog2 << "Warning: SDL says that " << bpp << "bpp is wrong and suggests " << suggestedBpp << std::endl;
|
|
}
|
|
|
|
+#ifndef ANDROID
|
|
if(screen) //screen has been already initialized
|
|
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
|
|
|
SDL_InitSubSystem(SDL_INIT_VIDEO);
|
|
+#endif
|
|
|
|
if((screen = SDL_SetVideoMode(w, h, suggestedBpp, SDL_SWSURFACE|(fullscreen?SDL_FULLSCREEN:0))) == NULL)
|
|
{
|
|
@@ -609,14 +635,27 @@
|
|
setResolution = true;
|
|
}
|
|
|
|
+
|
|
static void listenForEvents()
|
|
{
|
|
- while(1) //main SDL events loop
|
|
- {
|
|
+ while(loopListenForEvents(true)); //main SDL events loop
|
|
+}
|
|
+
|
|
+static bool loopListenForEvents(bool block)
|
|
+{
|
|
SDL_Event *ev = new SDL_Event();
|
|
|
|
//tlog0 << "Waiting... ";
|
|
- int ret = SDL_WaitEvent(ev);
|
|
+ int ret = 1;
|
|
+ if( block )
|
|
+ ret = SDL_WaitEvent(ev);
|
|
+ else
|
|
+ {
|
|
+ if(!SDL_PollEvent(ev)) {
|
|
+ delete ev;
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
//tlog0 << "got " << (int)ev->type;
|
|
if (ret == 0 || (ev->type==SDL_QUIT) ||
|
|
(ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4 && (ev->key.keysym.mod & KMOD_ALT)))
|
|
@@ -635,7 +674,7 @@
|
|
SDL_Delay(750);
|
|
SDL_Quit();
|
|
tlog0 << "Ending...\n";
|
|
- break;
|
|
+ return false;
|
|
}
|
|
else if(LOCPLINT && ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4)
|
|
{
|
|
@@ -644,7 +683,7 @@
|
|
setScreenRes(conf.cc.screenx, conf.cc.screeny, conf.cc.bpp, full);
|
|
GH.totalRedraw();
|
|
delete ev;
|
|
- continue;
|
|
+ return true;
|
|
}
|
|
else if(ev->type == SDL_USEREVENT)
|
|
{
|
|
@@ -674,7 +713,7 @@
|
|
}
|
|
|
|
delete ev;
|
|
- continue;
|
|
+ return true;
|
|
}
|
|
|
|
//tlog0 << " pushing ";
|
|
@@ -682,7 +721,7 @@
|
|
events.push(ev);
|
|
eventsM.unlock();
|
|
//tlog0 << " done\n";
|
|
- }
|
|
+ return true;
|
|
}
|
|
|
|
void startGame(StartInfo * options, CConnection *serv/* = NULL*/)
|
|
@@ -742,3 +781,4 @@
|
|
ev.user.code = 1;
|
|
SDL_PushEvent(&ev);
|
|
}
|
|
+
|
|
Index: client/Client.h
|
|
===================================================================
|
|
--- client/Client.h (revision 2387)
|
|
+++ client/Client.h (working copy)
|
|
@@ -43,7 +43,7 @@
|
|
public:
|
|
timeHandler th;
|
|
boost::thread *serverThread; //thread that called system to run server
|
|
- SharedMem *shared; //interprocess memory (for waiting for server)
|
|
+ //SharedMem *shared; //interprocess memory (for waiting for server)
|
|
bool verbose; //whether to print log msgs
|
|
std::string port; //port number in text form
|
|
|
|
Index: client/CDefHandler.cpp
|
|
===================================================================
|
|
--- client/CDefHandler.cpp (revision 2387)
|
|
+++ client/CDefHandler.cpp (working copy)
|
|
@@ -50,10 +50,19 @@
|
|
SDL_FreeSurface(ourImages[i].bitmap);
|
|
}
|
|
|
|
-void CDefHandler::openFromMemory(unsigned char *table, const std::string & name)
|
|
+#define CHECK_LOD_MEM_BLOCK_SIZE1(S, FF, F, L) { \
|
|
+ if( lodLength < (S) ) \
|
|
+ tlog1<<"ERROR in " << FF << " " << F << ":" << L << ": reading past the end of LOD mem block by " << \
|
|
+ (S) - lodLength << " bytes, fname " << name << " size " << lodLength << std::endl; }
|
|
+#define CHECK_LOD_MEM_BLOCK_SIZE(S) CHECK_LOD_MEM_BLOCK_SIZE1(S, __FUNCTION__, __FILE__, __LINE__)
|
|
+
|
|
+void CDefHandler::openFromMemory(unsigned char *table, const std::string & name, int lodLength)
|
|
{
|
|
+ //tlog0<<"openFromMemory ptr " << (void *)table <<std::endl;
|
|
+
|
|
BMPPalette palette[256];
|
|
- SDefEntry &de = * reinterpret_cast<SDefEntry *>(table);
|
|
+ SDefEntry de;
|
|
+ memcpy(&de, table, sizeof(de));
|
|
unsigned char *p;
|
|
|
|
defName = name;
|
|
@@ -61,6 +70,8 @@
|
|
width = SDL_SwapLE32(de.width);
|
|
height = SDL_SwapLE32(de.height);
|
|
unsigned int totalBlocks = SDL_SwapLE32(de.totalBlocks);
|
|
+
|
|
+ //tlog0<<"openFromMemory w " << width << " h " << height << " totalBlocks " << totalBlocks <<std::endl;
|
|
|
|
for (unsigned int it=0;it<256;it++)
|
|
{
|
|
@@ -71,13 +82,15 @@
|
|
}
|
|
|
|
// The SDefEntryBlock starts just after the SDefEntry
|
|
- p = reinterpret_cast<unsigned char *>(&de);
|
|
+ p = table;
|
|
p += sizeof(de);
|
|
-
|
|
+
|
|
int totalEntries=0;
|
|
for (unsigned int z=0; z<totalBlocks; z++)
|
|
{
|
|
- SDefEntryBlock &block = * reinterpret_cast<SDefEntryBlock *>(p);
|
|
+ //tlog0<<"Megadebug 443 - read size " << p - table <<std::endl;
|
|
+ SDefEntryBlock block;
|
|
+ memcpy(&block, p, sizeof(block));
|
|
unsigned int totalInBlock;
|
|
|
|
totalInBlock = SDL_SwapLE32(read_unaligned_u32(&block.totalInBlock));
|
|
@@ -85,7 +98,8 @@
|
|
for (unsigned int j=SEntries.size(); j<totalEntries+totalInBlock; j++)
|
|
SEntries.push_back(SEntry());
|
|
|
|
- p = block.data;
|
|
+ p += sizeof(block);
|
|
+ //tlog0<<"Megadebug 444 - read size " << p - table << " totalInBlock " << totalInBlock <<std::endl;
|
|
for (unsigned int j=0; j<totalInBlock; j++)
|
|
{
|
|
char Buffer[13];
|
|
@@ -93,11 +107,13 @@
|
|
Buffer[12] = 0;
|
|
SEntries[totalEntries+j].name=Buffer;
|
|
p += 13;
|
|
+ //tlog0<<"Megadebug 445 - read size " << p - table <<std::endl;
|
|
}
|
|
for (unsigned int j=0; j<totalInBlock; j++)
|
|
{
|
|
SEntries[totalEntries+j].offset = SDL_SwapLE32(read_unaligned_u32(p));
|
|
p += 4;
|
|
+ //tlog0<<"Megadebug 446 - read size " << p - table <<std::endl;
|
|
}
|
|
//totalEntries+=totalInBlock;
|
|
for(unsigned int hh=0; hh<totalInBlock; ++hh)
|
|
@@ -105,21 +121,30 @@
|
|
SEntries[totalEntries].group = z;
|
|
++totalEntries;
|
|
}
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(p - table);
|
|
}
|
|
|
|
+ //tlog0<<"Megadebug 448" << std::endl;
|
|
for(unsigned int j=0; j<SEntries.size(); ++j)
|
|
{
|
|
- SEntries[j].name = SEntries[j].name.substr(0, SEntries[j].name.find('.')+4);
|
|
+ std::string::size_type pos = SEntries[j].name.find('.');
|
|
+ if(pos != std::string::npos)
|
|
+ pos += 4;
|
|
+ SEntries[j].name = SEntries[j].name.substr(0, pos);
|
|
}
|
|
+ //tlog0<<"Megadebug 449" << std::endl;
|
|
//RWEntries = new unsigned int[height];
|
|
for(unsigned int i=0; i < SEntries.size(); ++i)
|
|
{
|
|
Cimage nimg;
|
|
- nimg.bitmap = getSprite(i, table, palette);
|
|
+ //tlog0<<"Megadebug 4491" << std::endl;
|
|
+ nimg.bitmap = getSprite(i, table, palette, name, lodLength);
|
|
+ //tlog0<<"Megadebug 4492" << std::endl;
|
|
nimg.imName = SEntries[i].name;
|
|
nimg.groupNumber = SEntries[i].group;
|
|
ourImages.push_back(nimg);
|
|
}
|
|
+ //tlog0<<"Megadebug 4499" << std::endl;
|
|
}
|
|
|
|
void CDefHandler::expand(unsigned char N,unsigned char & BL, unsigned char & BR)
|
|
@@ -128,9 +153,17 @@
|
|
BR = N & 0x1F;
|
|
}
|
|
|
|
-SDL_Surface * CDefHandler::getSprite (int SIndex, const unsigned char * FDef, const BMPPalette * palette) const
|
|
+
|
|
+#define CHECK_OUTBUF_MEM_BLOCK_SIZE1(S, FF, F, L) \
|
|
+ if( FullHeight*FullWidth < (S) ) { \
|
|
+ tlog1<<"ERROR in " << FF << " " << F << ":" << L << ": writing past the end of SDL surface at " << \
|
|
+ (S) << " memblock " << FullHeight*FullWidth << " fname " << name << std::endl; }
|
|
+#define CHECK_OUTBUF_MEM_BLOCK_SIZE(S) CHECK_OUTBUF_MEM_BLOCK_SIZE1(S, __FUNCTION__, __FILE__, __LINE__)
|
|
+
|
|
+SDL_Surface * CDefHandler::getSprite (int SIndex, const unsigned char * FDef, const BMPPalette * palette, const std::string & name, int lodLength) const
|
|
{
|
|
SDL_Surface * ret=NULL;
|
|
+ //tlog0<<"getSprite ptr " << (void *)FDef << std::endl;
|
|
|
|
unsigned int BaseOffset,
|
|
SpriteWidth, SpriteHeight, //format of sprite
|
|
@@ -145,7 +178,10 @@
|
|
unsigned char SegmentType;//, BL, BR; //TODO use me
|
|
|
|
BaseOffset = SEntries[SIndex].offset;
|
|
- SSpriteDef sd = * reinterpret_cast<const SSpriteDef *>(FDef + BaseOffset);
|
|
+ SSpriteDef sd;
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset + sizeof(sd));
|
|
+
|
|
+ memcpy(&sd, FDef + BaseOffset, sizeof(sd));
|
|
|
|
prSize = SDL_SwapLE32(sd.prSize); //TODO use me
|
|
defType2 = SDL_SwapLE32(sd.defType2);
|
|
@@ -170,12 +206,14 @@
|
|
if (add==4)
|
|
add=0;
|
|
|
|
+ //tlog0<<"getSprite: 11: SDL_CreateRGBSurface " << FullWidth << ":" << FullHeight << std::endl;
|
|
ret = SDL_CreateRGBSurface(SDL_SWSURFACE, FullWidth, FullHeight, 8, 0, 0, 0, 0);
|
|
//int tempee2 = readNormalNr(0,4,((unsigned char *)tempee.c_str()));
|
|
|
|
BaseOffset += sizeof(SSpriteDef);
|
|
int BaseOffsetor = BaseOffset;
|
|
|
|
+ //tlog0<<"getSprite: 12: set palette" << std::endl;
|
|
for(int i=0; i<256; ++i)
|
|
{
|
|
SDL_Color pr;
|
|
@@ -188,6 +226,7 @@
|
|
|
|
int ftcp=0;
|
|
|
|
+ //tlog0<<"getSprite: 13" << std::endl;
|
|
// If there's a margin anywhere, just blank out the whole surface.
|
|
if (TopMargin > 0 || BottomMargin > 0 || LeftMargin > 0 || RightMargin > 0) {
|
|
memset( reinterpret_cast<char*>(ret->pixels), 0, FullHeight*FullWidth);
|
|
@@ -197,6 +236,7 @@
|
|
if (TopMargin > 0)
|
|
ftcp += TopMargin*(FullWidth+add);
|
|
|
|
+ //tlog0<<"getSprite: 14: defType2 " << defType2 << std::endl;
|
|
switch(defType2)
|
|
{
|
|
case 0:
|
|
@@ -206,7 +246,10 @@
|
|
if (LeftMargin>0)
|
|
ftcp += LeftMargin;
|
|
|
|
- memcpy(reinterpret_cast<char*>(ret->pixels)+ftcp, &FDef[BaseOffset], SpriteWidth);
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset + SpriteWidth);
|
|
+ CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + SpriteWidth)
|
|
+ else
|
|
+ memcpy(reinterpret_cast<char*>(ret->pixels)+ftcp, &FDef[BaseOffset], SpriteWidth);
|
|
ftcp += SpriteWidth;
|
|
BaseOffset += SpriteWidth;
|
|
|
|
@@ -218,11 +261,12 @@
|
|
|
|
case 1:
|
|
{
|
|
- const unsigned int * RWEntriesLoc = reinterpret_cast<const unsigned int *>(FDef+BaseOffset);
|
|
+ unsigned int RWEntriesLoc = BaseOffset;
|
|
BaseOffset += sizeof(int) * SpriteHeight;
|
|
for (unsigned int i=0;i<SpriteHeight;i++)
|
|
{
|
|
- BaseOffset=BaseOffsetor + SDL_SwapLE32(read_unaligned_u32(RWEntriesLoc + i));
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(RWEntriesLoc + i*4 + 4);
|
|
+ BaseOffset=BaseOffsetor + SDL_SwapLE32(read_unaligned_u32(FDef+RWEntriesLoc + i*4));
|
|
if (LeftMargin>0)
|
|
ftcp += LeftMargin;
|
|
|
|
@@ -230,18 +274,25 @@
|
|
do
|
|
{
|
|
unsigned int SegmentLength;
|
|
+
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset + 4);
|
|
|
|
SegmentType=FDef[BaseOffset++];
|
|
SegmentLength=FDef[BaseOffset++] + 1;
|
|
-
|
|
+
|
|
if (SegmentType==0xFF)
|
|
{
|
|
- memcpy(reinterpret_cast<char*>(ret->pixels)+ftcp, FDef + BaseOffset, SegmentLength);
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset + SegmentLength);
|
|
+ CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + SegmentLength)
|
|
+ else
|
|
+ memcpy(reinterpret_cast<char*>(ret->pixels)+ftcp, FDef + BaseOffset, SegmentLength);
|
|
BaseOffset+=SegmentLength;
|
|
}
|
|
else
|
|
{
|
|
- memset(reinterpret_cast<char*>(ret->pixels)+ftcp, SegmentType, SegmentLength);
|
|
+ CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + SegmentLength)
|
|
+ else
|
|
+ memset(reinterpret_cast<char*>(ret->pixels)+ftcp, SegmentType, SegmentLength);
|
|
}
|
|
ftcp += SegmentLength;
|
|
TotalRowLength += SegmentLength;
|
|
@@ -260,6 +311,7 @@
|
|
|
|
case 2:
|
|
{
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(BaseOffsetor+2);
|
|
BaseOffset = BaseOffsetor + SDL_SwapLE16(read_unaligned_u16(FDef + BaseOffsetor));
|
|
|
|
for (unsigned int i=0;i<SpriteHeight;i++)
|
|
@@ -272,18 +324,24 @@
|
|
|
|
do
|
|
{
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset+1);
|
|
SegmentType=FDef[BaseOffset++];
|
|
unsigned char code = SegmentType / 32;
|
|
unsigned char value = (SegmentType & 31) + 1;
|
|
if(code==7)
|
|
{
|
|
- memcpy(reinterpret_cast<char*>(ret->pixels)+ftcp, &FDef[BaseOffset], value);
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset + value);
|
|
+ CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + value)
|
|
+ else
|
|
+ memcpy(reinterpret_cast<char*>(ret->pixels)+ftcp, &FDef[BaseOffset], value);
|
|
ftcp += value;
|
|
BaseOffset += value;
|
|
}
|
|
else
|
|
{
|
|
- memset(reinterpret_cast<char*>(ret->pixels)+ftcp, code, value);
|
|
+ CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + value)
|
|
+ else
|
|
+ memset(reinterpret_cast<char*>(ret->pixels)+ftcp, code, value);
|
|
ftcp += value;
|
|
}
|
|
TotalRowLength+=value;
|
|
@@ -304,6 +362,7 @@
|
|
{
|
|
for (unsigned int i=0;i<SpriteHeight;i++)
|
|
{
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(BaseOffsetor+i*2*(SpriteWidth/32+2));
|
|
BaseOffset = BaseOffsetor + SDL_SwapLE16(read_unaligned_u16(FDef + BaseOffsetor+i*2*(SpriteWidth/32)));
|
|
if (LeftMargin>0)
|
|
ftcp += LeftMargin;
|
|
@@ -312,6 +371,7 @@
|
|
|
|
do
|
|
{
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset+1);
|
|
SegmentType=FDef[BaseOffset++];
|
|
unsigned char code = SegmentType / 32;
|
|
unsigned char value = (SegmentType & 31) + 1;
|
|
@@ -321,13 +381,18 @@
|
|
|
|
if(code==7)
|
|
{
|
|
- memcpy((ui8*)ret->pixels + ftcp, FDef + BaseOffset, len);
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset + len);
|
|
+ CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + len)
|
|
+ else
|
|
+ memcpy((ui8*)ret->pixels + ftcp, FDef + BaseOffset, len);
|
|
ftcp += len;
|
|
BaseOffset += len;
|
|
}
|
|
else
|
|
{
|
|
- memset((ui8*)ret->pixels + ftcp, code, len);
|
|
+ CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + len)
|
|
+ else
|
|
+ memset((ui8*)ret->pixels + ftcp, code, len);
|
|
ftcp += len;
|
|
}
|
|
TotalRowLength+=( LeftMargin>=0 ? value : value+LeftMargin );
|
|
@@ -345,6 +410,7 @@
|
|
break;
|
|
|
|
default:
|
|
+ tlog1<<"getSprite: Unknown sprite format."<< std::endl;
|
|
throw std::string("Unknown sprite format.");
|
|
break;
|
|
}
|
|
@@ -365,11 +431,15 @@
|
|
|
|
CDefHandler * CDefHandler::giveDef(const std::string & defName)
|
|
{
|
|
- unsigned char * data = spriteh->giveFile(defName, FILE_ANIMATION);
|
|
- if(!data)
|
|
- throw "bad def name!";
|
|
+ //tlog0<<"giveDef " << defName <<std::endl;
|
|
+ int lodLength = 0;
|
|
+ unsigned char * data = spriteh->giveFile(defName, FILE_ANIMATION, &lodLength);
|
|
+ if(!data) {
|
|
+ tlog0<<"Bad def name: " << defName <<std::endl;
|
|
+ throw std::runtime_error("bad def name!");
|
|
+ }
|
|
CDefHandler * nh = new CDefHandler();
|
|
- nh->openFromMemory(data, defName);
|
|
+ nh->openFromMemory(data, defName, lodLength);
|
|
delete [] data;
|
|
return nh;
|
|
}
|
|
Index: client/CCreatureAnimation.cpp
|
|
===================================================================
|
|
--- client/CCreatureAnimation.cpp (revision 2387)
|
|
+++ client/CCreatureAnimation.cpp (working copy)
|
|
@@ -37,15 +37,23 @@
|
|
}
|
|
}
|
|
|
|
+#define CHECK_LOD_MEM_BLOCK_SIZE1(S, FF, F, L) { \
|
|
+ if( lodLength < (S) ) \
|
|
+ tlog1<<"ERROR in " << FF << " " << F << ":" << L << ": reading past the end of LOD mem block by " << \
|
|
+ (S) - lodLength << " bytes, fname " << fname << " size " << lodLength << std::endl; }
|
|
+#define CHECK_LOD_MEM_BLOCK_SIZE(S) CHECK_LOD_MEM_BLOCK_SIZE1(S, __FUNCTION__, __FILE__, __LINE__)
|
|
+
|
|
CCreatureAnimation::CCreatureAnimation(std::string name) : internalFrame(0), once(false)
|
|
{
|
|
- FDef = spriteh->giveFile(name, FILE_ANIMATION); //load main file
|
|
+ FDef = spriteh->giveFile(name, FILE_ANIMATION, &lodLength); //load main file
|
|
+ fname = name;
|
|
|
|
//init anim data
|
|
int i,j, totalInBlock;
|
|
|
|
defName=name;
|
|
i = 0;
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(i+0x310);
|
|
DEFType = readNormalNr<4>(i,FDef); i+=4;
|
|
fullWidth = readNormalNr<4>(i,FDef); i+=4;
|
|
fullHeight = readNormalNr<4>(i,FDef); i+=4;
|
|
@@ -64,6 +72,7 @@
|
|
totalEntries=0;
|
|
for (int z=0; z<totalBlocks; z++)
|
|
{
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(i+16);
|
|
std::vector<int> frameIDs;
|
|
int group = readNormalNr<4>(i,FDef); i+=4; //block ID
|
|
totalInBlock = readNormalNr<4>(i,FDef); i+=4;
|
|
@@ -76,6 +85,7 @@
|
|
/*int unknown2 = readNormalNr<4>(i,FDef);*/ i+=4; //TODO use me
|
|
/*int unknown3 = readNormalNr<4>(i,FDef);*/ i+=4; //TODO use me
|
|
i+=13*totalInBlock; //ommiting names
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(i+totalInBlock*4);
|
|
for (j=0; j<totalInBlock; j++)
|
|
{
|
|
SEntries[totalEntries+j].offset = readNormalNr<4>(i,FDef); i+=4;
|
|
@@ -173,6 +183,7 @@
|
|
unsigned char SegmentType, SegmentLength;
|
|
|
|
i = BaseOffset = SEntries[SIndex].offset;
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(i+32);
|
|
/*int prSize = readNormalNr<4>(i, FDef);*/ i += 4; //TODO use me
|
|
int defType2 = readNormalNr<4>(i, FDef); i += 4;
|
|
FullWidth = readNormalNr<4>(i, FDef); i += 4;
|
|
@@ -194,11 +205,12 @@
|
|
{
|
|
ftcp += FullWidth * TopMargin;
|
|
}
|
|
- int *RLEntries = (int*)(FDef + BaseOffset);
|
|
+ unsigned char *RLEntries = (FDef + BaseOffset);
|
|
BaseOffset += sizeof(int) * SpriteHeight;
|
|
for (int i = 0; i < SpriteHeight; i++)
|
|
{
|
|
- BaseOffset = BaseOffsetor + RLEntries[i];
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(RLEntries+i*4-FDef);
|
|
+ BaseOffset = BaseOffsetor + read_unaligned_u32(RLEntries+i*4);
|
|
if (LeftMargin > 0)
|
|
{
|
|
ftcp += LeftMargin;
|
|
@@ -213,6 +225,7 @@
|
|
|
|
do
|
|
{
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset+2);
|
|
SegmentType = FDef[BaseOffset++];
|
|
SegmentLength = FDef[BaseOffset++];
|
|
|
|
@@ -227,6 +240,8 @@
|
|
{
|
|
if(!destRect || (destRect->x <= xB && destRect->x + destRect->w > xB && destRect->y <= yB && destRect->y + destRect->h > yB))
|
|
{
|
|
+ if(SegmentType == 0xff)
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset+k+1);
|
|
const ui8 colorNr = SegmentType == 0xff ? FDef[BaseOffset+k] : SegmentType;
|
|
putPixel<bpp>(dest, xB, yB, palette[colorNr], colorNr, yellowBorder, blueBorder, aCountMod);
|
|
}
|
|
Index: client/CAnimation.cpp
|
|
===================================================================
|
|
--- client/CAnimation.cpp (revision 2387)
|
|
+++ client/CAnimation.cpp (working copy)
|
|
@@ -46,6 +46,8 @@
|
|
~SDLImageLoader();
|
|
};
|
|
|
|
+// It's buggy, disabled for Android build
|
|
+/*
|
|
class CompImageLoader
|
|
{
|
|
CompImage * image;
|
|
@@ -69,11 +71,18 @@
|
|
CompImageLoader(CompImage * Img);
|
|
~CompImageLoader();
|
|
};
|
|
-
|
|
+*/
|
|
/*************************************************************************
|
|
* DefFile, class used for def loading *
|
|
*************************************************************************/
|
|
|
|
+
|
|
+#define CHECK_LOD_MEM_BLOCK_SIZE1(S, FF, F, L) { \
|
|
+ if( lodLength < (S) ) \
|
|
+ tlog1<<"ERROR in " << FF << " " << F << ":" << L << ": reading past the end of LOD mem block by " << \
|
|
+ (S) - lodLength << " bytes, fname " << fname << " size " << lodLength << std::endl; }
|
|
+#define CHECK_LOD_MEM_BLOCK_SIZE(S) CHECK_LOD_MEM_BLOCK_SIZE1(S, __FUNCTION__, __FILE__, __LINE__)
|
|
+
|
|
CDefFile::CDefFile(std::string Name):
|
|
data(NULL),
|
|
palette(NULL)
|
|
@@ -91,15 +100,18 @@
|
|
{ 0, 0, 0, 192} // 75% - shadow border below selection
|
|
};
|
|
|
|
- data = spriteh->giveFile(Name, FILE_ANIMATION);
|
|
+ fname = Name;
|
|
+ data = spriteh->giveFile(Name, FILE_ANIMATION, &lodLength);
|
|
palette = new SDL_Color[256];
|
|
int it = 0;
|
|
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(it+4);
|
|
unsigned int type = readNormalNr(data, it);
|
|
it+=4;
|
|
//int width = readNormalNr(data, it); it+=4;//not used
|
|
//int height = readNormalNr(data, it); it+=4;
|
|
it+=8;
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(it+4);
|
|
unsigned int totalBlocks = readNormalNr(data, it);
|
|
it+=4;
|
|
|
|
@@ -117,6 +129,7 @@
|
|
|
|
for (unsigned int i=0; i<totalBlocks; i++)
|
|
{
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(it+8);
|
|
size_t blockID = readNormalNr(data, it);
|
|
it+=4;
|
|
size_t totalEntries = readNormalNr(data, it);
|
|
@@ -128,6 +141,7 @@
|
|
|
|
for (unsigned int j=0; j<totalEntries; j++)
|
|
{
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(it+4);
|
|
size_t currOffset = readNormalNr(data, it);
|
|
offset[blockID].push_back(currOffset);
|
|
it += 4;
|
|
@@ -144,7 +158,9 @@
|
|
|
|
const ui8 * FDef = data+it->second[frame];
|
|
|
|
- const SSpriteDef sd = * reinterpret_cast<const SSpriteDef *>(FDef);
|
|
+ SSpriteDef sd;
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE((FDef-data)+sizeof(sd));
|
|
+ memcpy(&sd, FDef, sizeof(sd));
|
|
SSpriteDef sprite;
|
|
|
|
//sprite.size = SDL_SwapLE32(sd.size);//unused
|
|
@@ -170,6 +186,7 @@
|
|
//pixel data is not compressed, copy data to surface
|
|
for (unsigned int i=0; i<sprite.height; i++)
|
|
{
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE((FDef-data)+currentOffset);
|
|
loader.Load(sprite.width, FDef[currentOffset]);
|
|
currentOffset += sprite.width;
|
|
loader.EndLine();
|
|
@@ -179,22 +196,33 @@
|
|
case 1:
|
|
{
|
|
//for each line we have offset of pixel data
|
|
- const ui32 * RWEntriesLoc = reinterpret_cast<const ui32 *>(FDef+currentOffset);
|
|
+ const unsigned char * RWEntriesLoc = FDef+currentOffset;
|
|
currentOffset += sizeof(ui32) * sprite.height;
|
|
|
|
for (unsigned int i=0; i<sprite.height; i++)
|
|
{
|
|
+ //tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ << " data " << (void *)data << " RWEntriesLoc " << (void *) RWEntriesLoc << " reading at offset " << ((RWEntriesLoc+i*4)-data)+4 << std::endl;
|
|
+
|
|
//get position of the line
|
|
- currentOffset=BaseOffset + SDL_SwapLE32(read_unaligned_u32(RWEntriesLoc + i));
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE(((RWEntriesLoc+i*4)-data)+4);
|
|
+ ui32 offset2 = SDL_SwapLE32(read_unaligned_u32(RWEntriesLoc + i*4));
|
|
+ currentOffset=BaseOffset + offset2;
|
|
unsigned int TotalRowLength = 0;
|
|
+
|
|
+ /*
|
|
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ << " data " << (void *)data << " RWEntriesLoc " << (void *) RWEntriesLoc <<
|
|
+ " currentOffset " << currentOffset << " BaseOffset " << BaseOffset << " offset2 " << offset2 << std::endl;
|
|
+ */
|
|
|
|
while (TotalRowLength<sprite.width)
|
|
{
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE((FDef-data)+currentOffset+1);
|
|
unsigned char type=FDef[currentOffset++];
|
|
unsigned int length=FDef[currentOffset++] + 1;
|
|
|
|
if (type==0xFF)//Raw data
|
|
{
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE((FDef-data)+currentOffset+length);
|
|
loader.Load(length, FDef + currentOffset);
|
|
currentOffset+=length;
|
|
}
|
|
@@ -219,12 +247,14 @@
|
|
|
|
while (TotalRowLength<sprite.width)
|
|
{
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE((FDef-data)+currentOffset+1);
|
|
unsigned char SegmentType=FDef[currentOffset++];
|
|
unsigned char code = SegmentType / 32;
|
|
unsigned char length = (SegmentType & 31) + 1;
|
|
|
|
if (code==7)//Raw data
|
|
{
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE((FDef-data)+currentOffset+length);
|
|
loader.Load(length, FDef[currentOffset]);
|
|
currentOffset += length;
|
|
}
|
|
@@ -242,17 +272,20 @@
|
|
{
|
|
for (unsigned int i=0; i<sprite.height; i++)
|
|
{
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE((FDef-data)+BaseOffset+i*2*(sprite.width/32)+2);
|
|
currentOffset = BaseOffset + SDL_SwapLE16(read_unaligned_u16(FDef + BaseOffset+i*2*(sprite.width/32)));
|
|
unsigned int TotalRowLength=0;
|
|
|
|
while (TotalRowLength<sprite.width)
|
|
{
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE((FDef-data)+currentOffset+1);
|
|
unsigned char segment = FDef[currentOffset++];
|
|
unsigned char code = segment / 32;
|
|
unsigned char length = (segment & 31) + 1;
|
|
|
|
if (code==7)//Raw data
|
|
{
|
|
+ CHECK_LOD_MEM_BLOCK_SIZE((FDef-data)+currentOffset+length);
|
|
loader.Load(length, FDef + currentOffset);
|
|
currentOffset += length;
|
|
}
|
|
@@ -270,6 +303,7 @@
|
|
tlog0<<"Error: unsupported format of def file:"<<sprite.format<<"\n";
|
|
break;
|
|
}
|
|
+ //tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
|
|
};
|
|
|
|
CDefFile::~CDefFile()
|
|
@@ -314,7 +348,7 @@
|
|
|
|
inline void SDLImageLoader::Load(size_t size, const ui8 * data)
|
|
{
|
|
- if (size)
|
|
+ if (size && (ui8 *)image->surf->pixels + image->surf->h*image->surf->pitch >= position + size )
|
|
{
|
|
memcpy((void *)position, data, size);
|
|
position += size;
|
|
@@ -323,7 +357,7 @@
|
|
|
|
inline void SDLImageLoader::Load(size_t size, ui8 color)
|
|
{
|
|
- if (size)
|
|
+ if (size && (ui8 *)image->surf->pixels + image->surf->h*image->surf->pitch >= position + size)
|
|
{
|
|
memset((void *)position, color, size);
|
|
position += size;
|
|
@@ -345,6 +379,7 @@
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
+/*
|
|
CompImageLoader::CompImageLoader(CompImage * Img):
|
|
image(Img),
|
|
position(NULL),
|
|
@@ -518,6 +553,7 @@
|
|
image->surf = newPtr;
|
|
}
|
|
|
|
+*/
|
|
/*************************************************************************
|
|
* Classes for images, support loading from file and drawing on surface *
|
|
*************************************************************************/
|
|
@@ -625,6 +661,8 @@
|
|
SDL_FreeSurface(surf);
|
|
}
|
|
|
|
+// Buggy, disabled for Android
|
|
+/*
|
|
CompImage::CompImage(const CDefFile *data, size_t frame, size_t group):
|
|
surf(NULL),
|
|
line(NULL),
|
|
@@ -845,6 +883,7 @@
|
|
delete [] line;
|
|
delete [] palette;
|
|
}
|
|
+*/
|
|
|
|
/*************************************************************************
|
|
* CAnimation for animations handling, can load part of file if needed *
|
|
@@ -889,9 +928,11 @@
|
|
//try to get image from def
|
|
if (source[group][frame].getType() == JsonNode::DATA_NULL)
|
|
{
|
|
+ /*
|
|
if (compressed)
|
|
images[group][frame] = new CompImage(file, frame, group);
|
|
else
|
|
+ */
|
|
images[group][frame] = new SDLImage(file, frame, group);
|
|
}
|
|
else //load from separate file
|
|
Index: client/GUIBase.h
|
|
===================================================================
|
|
--- client/GUIBase.h (revision 2387)
|
|
+++ client/GUIBase.h (working copy)
|
|
@@ -558,6 +558,8 @@
|
|
CGuiHandler();
|
|
~CGuiHandler();
|
|
void run(); // holds the main loop for the whole program after initialization and manages the update/rendering system
|
|
+ void loopInitFromMainThread();
|
|
+ bool loopFromMainThread();
|
|
|
|
void totalRedraw(); //forces total redraw (using showAll), sets a flag, method gets called at the end of the rendering
|
|
void simpleRedraw(); //update only top interface and draw background from buffer, sets a flag, method gets called at the end of the rendering
|
|
Index: client/CSndHandler.cpp
|
|
===================================================================
|
|
--- client/CSndHandler.cpp (revision 2387)
|
|
+++ client/CSndHandler.cpp (working copy)
|
|
@@ -151,16 +151,17 @@
|
|
}
|
|
|
|
const char *data = mfile->data();
|
|
- unsigned int numFiles = SDL_SwapLE32(*(Uint32 *)&data[0]);
|
|
- struct soundEntry *se = (struct soundEntry *)&data[4];
|
|
+ unsigned int numFiles = SDL_SwapLE32(read_unaligned_u32(&data[0]));
|
|
+ struct soundEntry se;
|
|
|
|
- for (unsigned int i=0; i<numFiles; i++, se++)
|
|
+ for (unsigned int i=0; i<numFiles; i++)
|
|
{
|
|
Entry entry;
|
|
+ memcpy(&se, &data[4+i*sizeof(se)], sizeof(se));
|
|
|
|
- entry.name = se->filename;
|
|
- entry.offset = SDL_SwapLE32(se->offset);
|
|
- entry.size = SDL_SwapLE32(se->size);
|
|
+ entry.name = se.filename;
|
|
+ entry.offset = SDL_SwapLE32(se.offset);
|
|
+ entry.size = SDL_SwapLE32(se.size);
|
|
entry.data = mfile->data() + entry.offset;
|
|
|
|
entries.push_back(entry);
|
|
@@ -186,24 +187,26 @@
|
|
return;
|
|
}
|
|
const unsigned char *data = (const unsigned char *)mfile->data();
|
|
- unsigned int numFiles = SDL_SwapLE32(*(Uint32 *)&data[0]);
|
|
- struct videoEntry *ve = (struct videoEntry *)&data[4];
|
|
+ unsigned int numFiles = SDL_SwapLE32(read_unaligned_u32(&data[0]));
|
|
+ struct videoEntry ve;
|
|
|
|
- for (unsigned int i=0; i<numFiles; i++, ve++)
|
|
+ for (unsigned int i=0; i<numFiles; i++)
|
|
{
|
|
Entry entry;
|
|
+ memcpy(&ve, &data[4+i*sizeof(ve)], sizeof(ve));
|
|
|
|
- entry.name = ve->filename;
|
|
- entry.offset = SDL_SwapLE32(ve->offset);
|
|
+ entry.name = ve.filename;
|
|
+ entry.offset = SDL_SwapLE32(ve.offset);
|
|
entry.name.erase(entry.name.find_last_of('.'));
|
|
|
|
// There is no size, so check where the next file is
|
|
if (i == numFiles - 1) {
|
|
entry.size = mfile->size() - entry.offset;
|
|
} else {
|
|
- struct videoEntry *ve_next = ve+1;
|
|
+ struct videoEntry ve_next;
|
|
+ memcpy(&ve_next, &data[4+(i+1)*sizeof(ve)], sizeof(ve));
|
|
|
|
- entry.size = SDL_SwapLE32(ve_next->offset) - entry.offset;
|
|
+ entry.size = SDL_SwapLE32(ve_next.offset) - entry.offset;
|
|
}
|
|
entry.data = mfile->data() + entry.offset;
|
|
|