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 #include #include @@ -2,2 +3,3 @@ #include +*/ @@ -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 +#ifdef WIN32 +#include +#else +#include +#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 -#include -#include +//#include +//#include #include #include #include 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() || !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 #include #include //std::find +#include //memcpy #include //std::find #include #include @@ -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(p)) -#define read_unaligned_u32(p) (* reinterpret_cast(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 //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 #include 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;iourImages.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: "<>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 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(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 + /* * 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 > 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 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: "<musich->setVolume(GDefaultOptions.musicVolume); tlog0<<"\tInitializing sound: "<(CGI)->setFromLib(); @@ -154,7 +158,9 @@ CCS->curh->show(); tlog0<<"Screen handler: "<loadHeroAnims(); tlog0<<"\tMain graphics: "<start(); atexit(dispose); tlog0 <<"Creating console and logfile: "<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 <(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 <(&de); + p = table; p += sizeof(de); - + int totalEntries=0; for (unsigned int z=0; z(p); + //tlog0<<"Megadebug 443 - read size " << p - table <(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(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(ret->pixels)+ftcp, &FDef[BaseOffset], SpriteWidth); + CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset + SpriteWidth); + CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + SpriteWidth) + else + memcpy(reinterpret_cast(ret->pixels)+ftcp, &FDef[BaseOffset], SpriteWidth); ftcp += SpriteWidth; BaseOffset += SpriteWidth; @@ -218,11 +261,12 @@ case 1: { - const unsigned int * RWEntriesLoc = reinterpret_cast(FDef+BaseOffset); + unsigned int RWEntriesLoc = BaseOffset; BaseOffset += sizeof(int) * SpriteHeight; for (unsigned int i=0;i0) 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(ret->pixels)+ftcp, FDef + BaseOffset, SegmentLength); + CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset + SegmentLength); + CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + SegmentLength) + else + memcpy(reinterpret_cast(ret->pixels)+ftcp, FDef + BaseOffset, SegmentLength); BaseOffset+=SegmentLength; } else { - memset(reinterpret_cast(ret->pixels)+ftcp, SegmentType, SegmentLength); + CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + SegmentLength) + else + memset(reinterpret_cast(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(ret->pixels)+ftcp, &FDef[BaseOffset], value); + CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset + value); + CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + value) + else + memcpy(reinterpret_cast(ret->pixels)+ftcp, &FDef[BaseOffset], value); ftcp += value; BaseOffset += value; } else { - memset(reinterpret_cast(ret->pixels)+ftcp, code, value); + CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + value) + else + memset(reinterpret_cast(ret->pixels)+ftcp, code, value); ftcp += value; } TotalRowLength+=value; @@ -304,6 +362,7 @@ { for (unsigned int i=0;i0) 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 <giveFile(defName, FILE_ANIMATION, &lodLength); + if(!data) { + tlog0<<"Bad def name: " << defName <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 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(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(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; isecond[frame]; - const SSpriteDef sd = * reinterpret_cast(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(FDef+currentOffset); + const unsigned char * RWEntriesLoc = FDef+currentOffset; currentOffset += sizeof(ui32) * sprite.height; for (unsigned int i=0; isurf->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; ifilename; - 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; ifilename; - 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;