Skip to content
Browse files

Copied old VCMI sources to another project dir, updated them to use s…

…tatic libvcmi
  • Loading branch information...
1 parent b23ce53 commit 810da5591e1d642c7f7b6ae6d227bd5aa8d91fbf @pelya committed Jan 5, 2013
2 project/jni/application/commandergenius/commandergenius
@@ -1 +1 @@
-Subproject commit 9c3f6dab2c39372aa6bcc6d6eccd8cf78d2f4be7
+Subproject commit d1b8a7ae03b1a0960722abbab38bbb8fca98e7cd
2 project/jni/application/openarena/engine
@@ -1 +1 @@
-Subproject commit 82513e88619941eef9649a0ef73c2b866d3fd005
+Subproject commit 9104eb9749bd9ef21805cc1ac0d5a1840adf46d8
2 project/jni/application/openarena/vm
@@ -1 +1 @@
-Subproject commit 5c6363076d61fecfa97889f5c45ec422ba890d99
+Subproject commit 26cafdcdab7099d4992e747649f98ac42a3a8be8
View
1 project/jni/application/openttd/AndroidAppSettings.cfg
@@ -17,6 +17,7 @@ CompatibilityHacks=n
CompatibilityHacksStaticInit=n
CompatibilityHacksTextInputEmulatesHwKeyboard=n
CompatibilityHacksPreventAudioChopping=n
+CompatibilityHacksAppIgnoresAudioBufferSize=n
AppUsesMouse=y
AppNeedsTwoButtonMouse=y
ShowMouseCursor=n
View
10 project/jni/application/vcmi-r2387/.gitignore
@@ -0,0 +1,10 @@
+libvcmi.so
+libvcmi.a
+AI
+Scripting
+debug
+out
+vcmiserver
+vcmiserver.zip
+build.log
+AndroidData/binaries.zip
View
54 project/jni/application/vcmi-r2387/AndroidAppSettings.cfg
@@ -0,0 +1,54 @@
+# The application settings for Android libSDL port
+AppSettingVersion=17
+LibSdlVersion=1.2
+AppName="VCMI"
+AppFullName=eu.vcmi
+ScreenOrientation=h
+InhibitSuspend=n
+AppDataDownloadUrl="!Data files|data1.zip^!Data files|data2.zip^!Data files|data3.zip^"
+VideoDepthBpp=16
+NeedDepthBuffer=n
+NeedStencilBuffer=n
+NeedGles2=n
+SwVideoMode=y
+SdlVideoResize=y
+SdlVideoResizeKeepAspect=n
+CompatibilityHacks=y
+CompatibilityHacksStaticInit=n
+CompatibilityHacksTextInputEmulatesHwKeyboard=n
+CompatibilityHacksPreventAudioChopping=n
+CompatibilityHacksAppIgnoresAudioBufferSize=n
+AppUsesMouse=y
+AppNeedsTwoButtonMouse=y
+ShowMouseCursor=n
+ForceRelativeMouseMode=n
+AppNeedsArrowKeys=n
+AppNeedsTextInput=y
+AppUsesJoystick=n
+AppUsesAccelerometer=n
+AppUsesMultitouch=n
+NonBlockingSwapBuffers=n
+RedefinedKeys="LALT RETURN NO_REMAP NO_REMAP E"
+AppTouchscreenKeyboardKeysAmount=0
+AppTouchscreenKeyboardKeysAmountAutoFire=0
+RedefinedKeysScreenKb="LALT RETURN KP_PLUS KP_MINUS SPACE DELETE KP_PLUS KP_MINUS 1 2"
+StartupMenuButtonTimeout=3000
+HiddenMenuOptions='OptionalDownloadConfig'
+FirstStartMenuOptions=''
+MultiABI=y
+AppMinimumRAM=64
+AppVersionCode=08605
+AppVersionName="0.86.05"
+ResetSdlConfigForThisVersion=y
+DeleteFilesOnUpgrade="libsdl-DownloadFinished-0.flag libsdl-DownloadFinished-1.flag libsdl-DownloadFinished-2.flag libsdl-DownloadFinished-3.flag libsdl-DownloadFinished-4.flag libsdl-DownloadFinished-5.flag"
+CompiledLibraries="mad sdl_mixer sdl_image sdl_ttf avutil avcore avcodec avformat swscale boost_program_options boost_filesystem boost_iostreams boost_system boost_thread android"
+CustomBuildScript=y
+AppCflags=''
+AppLdflags=''
+AppSubdirsBuild=''
+AppCmdline=''
+ReadmeText='^You may press "Home" now - the data will be downloaded in background'
+MinimumScreenSize=s
+AdmobPublisherId=n
+AdmobTestDeviceId=
+AdmobBannerSize=
View
7 project/jni/application/vcmi-r2387/AndroidBuild.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+# For some reason I'm getting errors with "make -j4"
+make -k ARCH=$1 || exit 1
+[ -f libapplication-$1.so ] || exit 1
+[ -e libapplication.so ] || ln -s libapplication-armeabi.so libapplication.so
+exit 0
View
BIN project/jni/application/vcmi-r2387/AndroidData/data1.zip
Binary file not shown.
View
BIN project/jni/application/vcmi-r2387/AndroidData/data2.zip
Binary file not shown.
View
BIN project/jni/application/vcmi-r2387/AndroidData/data3.zip
Binary file not shown.
View
89 project/jni/application/vcmi-r2387/Makefile
@@ -0,0 +1,89 @@
+ifeq ($(ARCH),)
+ARCH:=armeabi
+endif
+
+$(shell mkdir -p $(ARCH)/AI debug/$(ARCH)/AI $(ARCH)/Scripting debug/$(ARCH)/Scripting \
+ $(ARCH)/out/vcmi/lib $(ARCH)/out/vcmi/server $(ARCH)/out/vcmi/AI/StupidAI \
+ $(ARCH)/out/vcmi/AI/GeniusAI $(ARCH)/out/vcmi/client $(ARCH)/out/vcmi/Scripting/ERM)
+
+LOCAL_PATH:=$(shell dirname $0)
+LOCAL_PATH:=`cd $LOCAL_PATH && pwd`
+
+SOURCES_LIB:=$(wildcard vcmi/lib/*.cpp vcmi/CConsoleHandler.cpp vcmi/CThreadHelper.cpp)
+OBJS_LIB:=$(patsubst %.cpp, $(ARCH)/out/%.o, $(SOURCES_LIB))
+
+SOURCES_SERVER:=$(wildcard vcmi/server/*.cpp)
+OBJS_SERVER:=$(patsubst %.cpp, $(ARCH)/out/%.o, $(SOURCES_SERVER))
+
+SOURCES_STUPIDAI:=$(wildcard vcmi/AI/StupidAI/*.cpp)
+OBJS_STUPIDAI:=$(patsubst %.cpp, $(ARCH)/out/%.o, $(SOURCES_STUPIDAI))
+
+SOURCES_GENIUSAI:=$(filter-out %/ExpertSystem.cpp, $(wildcard vcmi/AI/GeniusAI/*.cpp))
+OBJS_GENIUSAI:=$(patsubst %.cpp, $(ARCH)/out/%.o, $(SOURCES_GENIUSAI))
+
+SOURCES_ERM:=$(wildcard vcmi/Scripting/ERM/*.cpp)
+OBJS_ERM:=$(patsubst %.cpp, $(ARCH)/out/%.o, $(SOURCES_ERM))
+
+SOURCES_CLIENT:=$(wildcard vcmi/client/*.cpp vcmi/CCallback.cpp)
+OBJS_CLIENT:=$(patsubst %.cpp, $(ARCH)/out/%.o, $(SOURCES_CLIENT))
+
+all: AndroidData/binaries-$(ARCH).zip libapplication-$(ARCH).so
+
+AndroidData/binaries-$(ARCH).zip: $(ARCH)/vcmiserver $(ARCH)/AI/libGeniusAI.so $(ARCH)/AI/libStupidAI.so $(ARCH)/Scripting/libvcmiERM.so
+ rm -f $@
+ cd $(ARCH) && zip -r ../$@ $(foreach F, $^, $(patsubst $(ARCH)/%,%,$(F)))
+
+$(OBJS_SERVER) $(OBJS_LIB) $(OBJS_GENIUSAI) $(OBJS_STUPIDAI) $(OBJS_CLIENT) $(OBJS_ERM): $(ARCH)/out/%.o: %.cpp
+ ../setEnvironment-$(ARCH).sh sh -c \
+ "\$$CXX \
+ -c \$$CXXFLAGS -Ivcmi -Ivcmi/lib \
+ -DDATA_DIR=\\\"/sdcard/Android/data/eu.vcmi/files\\\" \
+ -DBIN_DIR=\\\"/data/data/eu.vcmi/files\\\" \
+ -DLIB_DIR=\\\"/data/data/eu.vcmi/files\\\" \
+ -DWITH_AVCODEC_DECODE_VIDEO2=1 \
+ -Wstrict-aliasing -Wcast-align -Wpointer-arith -Waddress \
+ $< -o $@"
+# -Werror=strict-aliasing -Werror=cast-align -Werror=pointer-arith -Werror=address
+
+$(ARCH)/libvcmi.a: $(OBJS_LIB)
+ ar rcs $@ $^
+
+LINK_LIB= \
+ env NO_SHARED_LIBS=1 ../setEnvironment-$(ARCH).sh sh -c \
+ "\$$CXX \
+ -Wl,--whole-archive $^ -Wl,--no-whole-archive -o $@ \
+ -shared \$$LDFLAGS \
+ -lboost_filesystem-1.45 -lboost_iostreams-1.45 -lboost_system-1.45 -lboost_thread-1.45 && \
+ cp $@ debug/$@ && \
+ \$$STRIP --strip-unneeded $@"
+
+$(ARCH)/AI/libGeniusAI.so: $(ARCH)/libvcmi.a $(OBJS_GENIUSAI)
+ $(LINK_LIB)
+
+$(ARCH)/AI/libStupidAI.so: $(ARCH)/libvcmi.a $(OBJS_STUPIDAI)
+ $(LINK_LIB)
+
+$(ARCH)/Scripting/libvcmiERM.so: $(ARCH)/libvcmi.a $(OBJS_ERM)
+ $(LINK_LIB)
+
+$(ARCH)/vcmiserver: $(ARCH)/libvcmi.a $(OBJS_SERVER)
+ env BUILD_EXECUTABLE=1 NO_SHARED_LIBS=1 ../setEnvironment-$(ARCH).sh sh -c \
+ "\$$CXX \
+ -Wl,--whole-archive $^ -Wl,--no-whole-archive -o $@ \
+ \$$LDFLAGS \
+ -lboost_filesystem-1.45 -lboost_iostreams-1.45 -lboost_system-1.45 -lboost_thread-1.45 && \
+ cp $@ debug/$@ && \
+ \$$STRIP --strip-unneeded $@"
+
+libapplication-$(ARCH).so: $(ARCH)/libvcmi.a $(OBJS_CLIENT)
+ env ../setEnvironment-$(ARCH).sh sh -c \
+ "\$$CXX \
+ -Wl,--whole-archive $^ -Wl,--no-whole-archive -o $@ \
+ \$$LDFLAGS -lboost_filesystem-1.45 -lboost_iostreams-1.45 -lboost_system-1.45 -lboost_thread-1.45 -lboost_program_options-1.45 && \
+ cp $@ debug/$@"
+# No need to strip, it's done inside build.sh script
+
+clean:
+ rm -rf armeabi* debug AndroidData/binaries-*.zip libapplication*.so
+
+.PHONY: clean
View
BIN project/jni/application/vcmi-r2387/icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
14 project/jni/application/vcmi-r2387/readme.txt
@@ -0,0 +1,14 @@
+Quick compilation guide:
+Download my GIT repo from https://github.com/pelya/commandergenius,
+then install Android SDK from http://developer.android.com,
+NDK r8d from http://crystax.net/ and "ant" tool, then launch commands
+ android update project -p project
+ rm project/jni/application/src
+ ln -s vcmi project/jni/application/src
+ echo > project/jni/application/vcmi/libvcmi.so
+then download VCMI revision 2387 into the dir project/jni/application/vcmi/vcmi
+(or create a symlink to it if you already have downloaded it), then apply patch vcmi-android.diff,
+then launch build.sh.
+
+To run it you should have complete installation of Heroes 3: Wake of Gods on your SD card on your device,
+in the directory Android/data/eu.vcmi/files
View
1 project/jni/application/vcmi-r2387/vcmi
View
1,553 project/jni/application/vcmi-r2387/vcmi-android.diff
@@ -0,0 +1,1553 @@
+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: AI/GeniusAI/CGeniusAI.cpp
+===================================================================
+--- AI/GeniusAI/CGeniusAI.cpp (revision 2387)
++++ AI/GeniusAI/CGeniusAI.cpp (working copy)
+@@ -1393,6 +1393,7 @@
+ }
+
+
++#ifndef ANDROID
+ //WTF?!? why is this needed?!?!?!
+ BattleAction CGlobalAI::activeStack( const CStack * stack )
+ {
+@@ -1400,4 +1401,5 @@
+ ba.stackNumber = stack->ID;
+ return ba;
+ }
++#endif
+
+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/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/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;
+
+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/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/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/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: 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: 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/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: 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: 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: 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: 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/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: 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()
View
1 project/jni/vcmi

0 comments on commit 810da55

Please sign in to comment.
Something went wrong with that request. Please try again.