Files
commandergenius/project/jni/application/vcmi/vcmi-android.diff

1163 lines
36 KiB
Diff

Index: server/stdafx.h
===================================================================
--- server/stdafx.h (revision 2183)
+++ 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 2183)
+++ 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->io_service());
boost::thread acc(boost::bind(vaccept,acceptor,s,&error));
+ /*
sr->setToTrueAndNotify();
delete mr;
+ */
acc.join();
if (error)
Index: lib/CLodHandler.cpp
===================================================================
--- lib/CLodHandler.cpp (revision 2183)
+++ lib/CLodHandler.cpp (working copy)
@@ -60,6 +60,9 @@
return ret;
}
+int CLodHandler::dbgLastFileSize = 0;
+std::string CLodHandler::dbgLastFileName;
+
unsigned char * CLodHandler::giveFile(const std::string defName, LodFileType type, int * length)
{
std::string fname = defName;
@@ -78,13 +81,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)
{
@@ -100,16 +105,25 @@
delete[] outp;
return NULL;
}
- else
+ else
+ {
+ dbgLastFileSize = ourEntry.realSize;
+ dbgLastFileName = defName;
+ //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();
+ dbgLastFileSize = ourEntry.realSize;
+ dbgLastFileName = defName;
+ //tlog0 << "Loaded file: " << fname << " size " << ourEntry.realSize << " ptr " << (void *)outp << " safety " << (int)SAFETY_MARGIN << std::endl;
return outp;
}
else //we will decompress file
@@ -122,7 +136,14 @@
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;
+ dbgLastFileSize = ourEntry.realSize;
+ dbgLastFileName = defName;
+ //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 2183)
+++ 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 2183)
+++ 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/CLodHandler.h
===================================================================
--- lib/CLodHandler.h (revision 2183)
+++ lib/CLodHandler.h (working copy)
@@ -116,6 +116,8 @@
void extractFile(const std::string FName, const std::string name); //extracts a specific file
static unsigned char * getUnpackedFile(const std::string & path, int * sizeOut); //loads given file, decompresses and returns
+ static int dbgLastFileSize;
+ static std::string dbgLastFileName;
};
Index: CConsoleHandler.cpp
===================================================================
--- CConsoleHandler.cpp (revision 2183)
+++ 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 2183)
+++ 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>
@@ -727,29 +728,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: CThreadHelper.cpp
===================================================================
--- CThreadHelper.cpp (revision 2183)
+++ CThreadHelper.cpp (working copy)
@@ -24,10 +24,16 @@
}
void CThreadHelper::run()
{
+#ifdef ANDROID
+ // For debug make it single-threaded
+ for(int i=0;i<tasks->size();i++)
+ (*tasks)[i]();
+#else
boost::thread_group grupa;
for(int i=0;i<threads;i++)
grupa.create_thread(boost::bind(&CThreadHelper::processTasks,this));
grupa.join_all();
+#endif
}
void CThreadHelper::processTasks()
{
Index: client/Graphics.cpp
===================================================================
--- client/Graphics.cpp (revision 2183)
+++ client/Graphics.cpp (working copy)
@@ -321,6 +321,7 @@
tasks += GET_DEF_ESS(abils82,"SECSK82.DEF");
tasks += GET_DEF_ESS(spellscr,"SPELLSCR.DEF");
tasks += GET_DEF_ESS(heroMoveArrows,"ADAG.DEF");
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
std::ifstream ifs(DATA_DIR "/config/cr_bgs.txt");
int id;
@@ -331,15 +332,21 @@
tasks += GET_SURFACE(backgrounds[id],name);
name.replace(0,5,"TPCAS");
tasks += GET_SURFACE(backgroundsm[id],name);
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
}
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
CThreadHelper th(&tasks,std::max((unsigned int)1,boost::thread::hardware_concurrency()));
th.run();
+
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ << " heroMoveArrows " << heroMoveArrows <<std::endl;
for(size_t y=0; y < heroMoveArrows->ourImages.size(); ++y)
{
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ << " heroMoveArrows " << y << "/" << heroMoveArrows->ourImages.size() <<std::endl;
CSDL_Ext::alphaTransform(heroMoveArrows->ourImages[y].bitmap);
}
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
//handling 32x32px imgs
smi->notFreeImgs = true;
@@ -354,9 +361,11 @@
bigImgs[i-2] = smi2->ourImages[i].bitmap;
}
delete smi2;
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
}
void Graphics::loadHeroPortraits()
{
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
std::ifstream of(DATA_DIR "/config/portrety.txt");
int numberOfPortraits;
of>>numberOfPortraits;
@@ -384,6 +393,7 @@
void Graphics::loadWallPositions()
{
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
std::ifstream inp;
inp.open(DATA_DIR "/config/wall_pos.txt", std::ios_base::in|std::ios_base::binary);
if(!inp.is_open())
@@ -417,24 +427,32 @@
void Graphics::loadHeroAnims()
{
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
std::vector<std::pair<int,int> > rotations; //first - group number to be rotated1, second - group number after rotation1
rotations += std::make_pair(6,10), std::make_pair(7,11), std::make_pair(8,12), std::make_pair(1,13),
std::make_pair(2,14), std::make_pair(3,15);
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
for(size_t i=0; i<F_NUMBER * 2; ++i)
{
std::ostringstream nm;
nm << "AH" << std::setw(2) << std::setfill('0') << i << "_.DEF";
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
loadHeroAnim(nm.str(), rotations, &Graphics::heroAnims);
std::string name = nm.str();
}
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
loadHeroAnim("AB01_.DEF", rotations, &Graphics::boatAnims);
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
loadHeroAnim("AB02_.DEF", rotations, &Graphics::boatAnims);
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
loadHeroAnim("AB03_.DEF", rotations, &Graphics::boatAnims);
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
}
void Graphics::loadHeroAnim( const std::string &name, const std::vector<std::pair<int,int> > &rotations, std::vector<CDefEssential *> Graphics::*dst )
{
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ << " load " << name <<std::endl;
CDefEssential *anim = CDefHandler::giveDefEss(name);
(this->*dst).push_back(anim);
int pom = 0; //how many groups has been rotated
@@ -472,12 +490,15 @@
void Graphics::loadHeroFlags(std::pair<std::vector<CDefEssential *> Graphics::*, std::vector<const char *> > &pr, bool mode)
{
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
for(int i=0;i<8;i++)
(this->*pr.first).push_back(CDefHandler::giveDefEss(pr.second[i]));
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
std::vector<std::pair<int,int> > rotations; //first - group number to be rotated1, second - group number after rotation1
rotations += std::make_pair(6,10), std::make_pair(7,11), std::make_pair(8,12);
for(int q=0; q<8; ++q)
{
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
std::vector<Cimage> &curImgs = (this->*pr.first)[q]->ourImages;
for(size_t o=0; o<curImgs.size(); ++o)
{
@@ -515,6 +536,7 @@
}
}
}
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
for(size_t ff=0; ff<curImgs.size(); ++ff)
{
SDL_SetColorKey(curImgs[ff].bitmap, SDL_SRCCOLORKEY,
@@ -522,31 +544,44 @@
);
}
}
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
}
void Graphics::loadHeroFlags()
{
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
using namespace boost::assign;
timeHandler th;
std::pair<std::vector<CDefEssential *> Graphics::*, std::vector<const char *> > pr[4];
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
pr[0].first = &Graphics::flags1;
pr[0].second+=("ABF01L.DEF"),("ABF01G.DEF"),("ABF01R.DEF"),("ABF01D.DEF"),("ABF01B.DEF"),
("ABF01P.DEF"),("ABF01W.DEF"),("ABF01K.DEF");
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
pr[1].first = &Graphics::flags2;
pr[1].second+=("ABF02L.DEF"),("ABF02G.DEF"),("ABF02R.DEF"),("ABF02D.DEF"),("ABF02B.DEF"),
("ABF02P.DEF"),("ABF02W.DEF"),("ABF02K.DEF");
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
pr[2].first = &Graphics::flags3;
pr[2].second+=("ABF03L.DEF"),("ABF03G.DEF"),("ABF03R.DEF"),("ABF03D.DEF"),("ABF03B.DEF"),
("ABF03P.DEF"),("ABF03W.DEF"),("ABF03K.DEF");
pr[3].first = &Graphics::flags4;
pr[3].second+=("AF00.DEF"),("AF01.DEF"),("AF02.DEF"),("AF03.DEF"),("AF04.DEF"),
("AF05.DEF"),("AF06.DEF"),("AF07.DEF");
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
+#ifdef ANDROID
+ 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();
+#endif
tlog0 << "Loading and transforming heroes' flags: "<<th.getDif()<<std::endl;
}
SDL_Surface * Graphics::getPic(int ID, bool fort, bool builded)
@@ -669,6 +704,7 @@
void Graphics::loadTrueType()
{
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
bool ttfPresent = false;//was TTF initialised or not
for(int i = 0; i < FONTS_NUMBER; i++)
fontsTrueType[i] = NULL;
@@ -702,6 +738,7 @@
Font * Graphics::loadFont( const char * name )
{
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
int len = 0;
unsigned char * hlp = bitmaph->giveFile(name, FILE_FONT, &len);
if(!hlp || !len)
@@ -725,6 +762,7 @@
void Graphics::loadFonts()
{
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
static const char *fontnames [] = {"BIGFONT.FNT", "CALLI10R.FNT", "CREDITS.FNT", "HISCORE.FNT", "MEDFONT.FNT",
"SMALFONT.FNT", "TIMES08R.FNT", "TINY.FNT", "VERD10B.FNT"} ;
@@ -745,6 +783,7 @@
void Graphics::loadErmuToPicture()
{
+ tlog0<<__FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ <<std::endl;
//loading ERMU to picture
std::ifstream etp(DATA_DIR "/config/ERMU_to_picture.txt");
Index: client/Client.cpp
===================================================================
--- client/Client.cpp (revision 2183)
+++ client/Client.cpp (working copy)
@@ -39,7 +39,7 @@
#include "../lib/RegisterTypes.cpp"
extern std::string NAME;
-namespace intpr = boost::interprocess;
+//namespace intpr = boost::interprocess;
/*
* Client.cpp, part of VCMI engine
@@ -498,9 +498,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);
@@ -628,18 +628,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();
@@ -654,27 +658,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 2183)
+++ 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
@@ -364,6 +365,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/CDefHandler.h
===================================================================
--- client/CDefHandler.h (revision 2183)
+++ 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
Index: client/Client.h
===================================================================
--- client/Client.h (revision 2183)
+++ 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/CMT.cpp
===================================================================
--- client/CMT.cpp (revision 2183)
+++ 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
@@ -137,10 +140,12 @@
CCS->soundh->init();
CCS->soundh->setVolume(GDefaultOptions.soundVolume);
CCS->musich = new CMusicHandler;
+
//CGI->musich->init();
//CGI->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 +159,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 +193,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 +248,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;
@@ -262,6 +272,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"))
@@ -270,6 +285,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"))
@@ -286,8 +302,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;
}
@@ -559,10 +584,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)
{
@@ -607,14 +634,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)))
@@ -633,7 +673,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)
{
@@ -642,7 +682,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)
{
@@ -672,7 +712,7 @@
}
delete ev;
- continue;
+ return true;
}
//tlog0 << " pushing ";
@@ -680,7 +720,7 @@
events.push(ev);
eventsM.unlock();
//tlog0 << " done\n";
- }
+ return true;
}
void startGame(StartInfo * options, CConnection *serv/* = NULL*/)
@@ -741,3 +781,4 @@
ev.user.code = 1;
SDL_PushEvent(&ev);
}
+
Index: client/CDefHandler.cpp
===================================================================
--- client/CDefHandler.cpp (revision 2183)
+++ client/CDefHandler.cpp (working copy)
@@ -50,10 +50,19 @@
SDL_FreeSurface(ourImages[i].bitmap);
}
+#define CHECK_LOD_MEM_BLOCK_SIZE1(S, FF, F, L) { \
+ if( CLodHandler::dbgLastFileSize < (S) ) \
+ tlog1<<"ERROR in " << FF << " " << F << ":" << L << ": reading past the end of LOD mem block at " << \
+ (S) << " memblock " << CLodHandler::dbgLastFileSize << " fname " << CLodHandler::dbgLastFileName << 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)
{
+ //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;
+ //tlog0<<"Megadebug 4491" << std::endl;
nimg.bitmap = getSprite(i, table, palette);
+ //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;
}
+
+#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 " << CLodHandler::dbgLastFileName << std::endl; }
+#define CHECK_OUTBUF_MEM_BLOCK_SIZE(S) CHECK_LOD_MEM_BLOCK_SIZE1(S, __FUNCTION__, __FILE__, __LINE__)
+
SDL_Surface * CDefHandler::getSprite (int SIndex, const unsigned char * FDef, const BMPPalette * palette) 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,6 +246,8 @@
if (LeftMargin>0)
ftcp += LeftMargin;
+ CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset + SpriteWidth);
+ CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + SpriteWidth);
memcpy(reinterpret_cast<char*>(ret->pixels)+ftcp, &FDef[BaseOffset], SpriteWidth);
ftcp += SpriteWidth;
BaseOffset += SpriteWidth;
@@ -218,11 +260,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,17 +273,22 @@
do
{
unsigned int SegmentLength;
+
+ CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset + 4);
SegmentType=FDef[BaseOffset++];
SegmentLength=FDef[BaseOffset++] + 1;
-
+
if (SegmentType==0xFF)
{
+ CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset + SegmentLength);
+ CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + SegmentLength);
memcpy(reinterpret_cast<char*>(ret->pixels)+ftcp, FDef + BaseOffset, SegmentLength);
BaseOffset+=SegmentLength;
}
else
{
+ CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + SegmentLength);
memset(reinterpret_cast<char*>(ret->pixels)+ftcp, SegmentType, SegmentLength);
}
ftcp += SegmentLength;
@@ -260,6 +308,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,17 +321,21 @@
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)
{
+ CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset + value);
+ CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + value);
memcpy(reinterpret_cast<char*>(ret->pixels)+ftcp, &FDef[BaseOffset], value);
ftcp += value;
BaseOffset += value;
}
else
{
+ CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + value);
memset(reinterpret_cast<char*>(ret->pixels)+ftcp, code, value);
ftcp += value;
}
@@ -304,6 +357,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 +366,7 @@
do
{
+ CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset+1);
SegmentType=FDef[BaseOffset++];
unsigned char code = SegmentType / 32;
unsigned char value = (SegmentType & 31) + 1;
@@ -321,12 +376,15 @@
if(code==7)
{
+ CHECK_LOD_MEM_BLOCK_SIZE(BaseOffset + len);
+ CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + len);
memcpy((ui8*)ret->pixels + ftcp, FDef + BaseOffset, len);
ftcp += len;
BaseOffset += len;
}
else
{
+ CHECK_OUTBUF_MEM_BLOCK_SIZE(ftcp + len);
memset((ui8*)ret->pixels + ftcp, code, len);
ftcp += len;
}
@@ -345,6 +403,7 @@
break;
default:
+ tlog1<<"getSprite: Unknown sprite format."<< std::endl;
throw std::string("Unknown sprite format.");
break;
}
@@ -365,9 +424,12 @@
CDefHandler * CDefHandler::giveDef(const std::string & defName)
{
+ tlog0<<"giveDef " << defName <<std::endl;
unsigned char * data = spriteh->giveFile(defName, FILE_ANIMATION);
- if(!data)
- throw "bad def name!";
+ if(!data) {
+ tlog0<<"Bad def name: " << defName <<std::endl;
+ throw std::runtime_error("bad def name!");
+ }
CDefHandler * nh = new CDefHandler();
nh->openFromMemory(data, defName);
delete [] data;
Index: client/GUIBase.h
===================================================================
--- client/GUIBase.h (revision 2183)
+++ client/GUIBase.h (working copy)
@@ -546,6 +546,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