1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-09-16 09:26:28 +02:00

* (hopefully) full reading of h3c

* minor changes
This commit is contained in:
mateuszb
2010-02-12 15:04:01 +00:00
parent e79507ab0d
commit 8637b021cc
16 changed files with 223 additions and 69 deletions

View File

@@ -45,11 +45,11 @@ CCreatureAnimation::CCreatureAnimation(std::string name) : internalFrame(0), onc
char Buffer[13];
defName=name;
i = 0;
DEFType = readNormalNr(i,4); i+=4;
fullWidth = readNormalNr(i,4); i+=4;
fullHeight = readNormalNr(i,4); i+=4;
DEFType = readNormalNr<4>(i,FDef); i+=4;
fullWidth = readNormalNr<4>(i,FDef); i+=4;
fullHeight = readNormalNr<4>(i,FDef); i+=4;
i=0xc;
totalBlocks = readNormalNr(i,4); i+=4;
totalBlocks = readNormalNr<4>(i,FDef); i+=4;
i=0x10;
for (int it=0;it<256;it++)
@@ -64,20 +64,20 @@ CCreatureAnimation::CCreatureAnimation(std::string name) : internalFrame(0), onc
for (int z=0; z<totalBlocks; z++)
{
std::vector<int> frameIDs;
int group = readNormalNr(i,4); i+=4; //block ID
totalInBlock = readNormalNr(i,4); i+=4;
int group = readNormalNr<4>(i,FDef); i+=4; //block ID
totalInBlock = readNormalNr<4>(i,FDef); i+=4;
for (j=SEntries.size(); j<totalEntries+totalInBlock; j++)
{
SEntries.push_back(SEntry());
SEntries[j].group = group;
frameIDs.push_back(j);
}
int unknown2 = readNormalNr(i,4); i+=4; //TODO use me
int unknown3 = readNormalNr(i,4); i+=4; //TODO use me
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
for (j=0; j<totalInBlock; j++)
{
SEntries[totalEntries+j].offset = readNormalNr(i,4); i+=4;
SEntries[totalEntries+j].offset = readNormalNr<4>(i,FDef); i+=4;
}
//totalEntries+=totalInBlock;
for(int hh=0; hh<totalInBlock; ++hh)
@@ -93,32 +93,11 @@ CCreatureAnimation::CCreatureAnimation(std::string name) : internalFrame(0), onc
frames = totalEntries;
}
int CCreatureAnimation::readNormalNr (int pos, int bytCon, unsigned char * str) const
{
int ret=0;
int amp=1;
if (str)
{
for (int i=0; i<bytCon; i++)
{
ret+=str[pos+i]*amp;
amp<<=8; //amp*=256;
}
}
else
{
for (int i=0; i<bytCon; i++)
{
ret+=FDef[pos+i]*amp;
amp<<=8; //amp*=256;
}
}
return ret;
}
int CCreatureAnimation::nextFrameMiddle(SDL_Surface *dest, int x, int y, bool attacker, unsigned char animCount, bool incrementFrame, bool yellowBorder, bool blueBorder, SDL_Rect * destRect)
{
return nextFrame(dest, x-fullWidth/2, y-fullHeight/2, attacker, animCount, incrementFrame, yellowBorder, blueBorder, destRect);
}
void CCreatureAnimation::incrementFrame()
{
if(type!=-1) //when a specific part of animation is played
@@ -190,14 +169,14 @@ int CCreatureAnimation::nextFrame(SDL_Surface *dest, int x, int y, bool attacker
unsigned char SegmentType, SegmentLength;
i=BaseOffset=SEntries[SIndex].offset;
int prSize=readNormalNr(i,4,FDef);i+=4;//TODO use me
int defType2 = readNormalNr(i,4,FDef);i+=4;
FullWidth = readNormalNr(i,4,FDef);i+=4;
FullHeight = readNormalNr(i,4,FDef);i+=4;
SpriteWidth = readNormalNr(i,4,FDef);i+=4;
SpriteHeight = readNormalNr(i,4,FDef);i+=4;
LeftMargin = readNormalNr(i,4,FDef);i+=4;
TopMargin = readNormalNr(i,4,FDef);i+=4;
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;
FullHeight = readNormalNr<4>(i,FDef);i+=4;
SpriteWidth = readNormalNr<4>(i,FDef);i+=4;
SpriteHeight = readNormalNr<4>(i,FDef);i+=4;
LeftMargin = readNormalNr<4>(i,FDef);i+=4;
TopMargin = readNormalNr<4>(i,FDef);i+=4;
RightMargin = FullWidth - SpriteWidth - LeftMargin;
BottomMargin = FullHeight - SpriteHeight - TopMargin;
@@ -205,7 +184,7 @@ int CCreatureAnimation::nextFrame(SDL_Surface *dest, int x, int y, bool attacker
int ftcp = 0;
if (defType2==1) //as it should be allways in creature animations
if (defType2==1) //as it should be always in creature animations
{
if (TopMargin>0)
{

View File

@@ -29,7 +29,20 @@ private:
} ;
std::vector<SEntry> SEntries ;
std::string defName, curDir;
int readNormalNr (int pos, int bytCon, unsigned char * str=NULL) const;
template< int bytCon > static int readNormalNr (int pos, unsigned char * str)
{
int ret=0;
int amp=1;
for (int i=0; i<bytCon; i++)
{
ret+=str[pos+i]*amp;
amp<<=8; //amp*=256;
}
return ret;
}
void putPixel(
SDL_Surface * dest,
const int & ftcp,

View File

@@ -110,7 +110,7 @@ CMenuScreen::CMenuScreen( EState which )
////just for testing
CCampaignHandler * ch = new CCampaignHandler();
ch->getCampaignHeaders();
//ch->getCampaign("./Maps/1 Test cmpgn.h3c");
ch->getCampaign("./Maps/ALEXIS.h3c");
}
break;
}

View File

@@ -17,6 +17,7 @@
#include "../CCallback.h"
#include "../hch/CTownHandler.h"
#include "../hch/CObjectHandler.h"
#include "../hch/CGeneralTextHandler.h"
using namespace boost::assign;
using namespace CSDL_Ext;

View File

@@ -5,6 +5,8 @@
#include <stdio.h>
#include <boost/algorithm/string/predicate.hpp>
#include "CLodHandler.h"
#include "../lib/VCMI_Lib.h"
#include "CGeneralTextHandler.h"
namespace fs = boost::filesystem;
@@ -68,9 +70,34 @@ CCampaign * CCampaignHandler::getCampaign( const std::string & name )
int it = 0; //iterator for reading
ret->header = readHeaderFromMemory(cmpgn, it);
it += 112; //omitting rubbish
CCampaignScenario sc = readScenarioFromMemory(cmpgn, it);
CCampaignScenario sc2 = readScenarioFromMemory(cmpgn, it);
int howManyScenarios = VLC->generaltexth->campaignRegionNames[ret->header.mapVersion].size();
for(int g=0; g<howManyScenarios; ++g)
{
CCampaignScenario sc = readScenarioFromMemory(cmpgn, it);
ret->scenarios.push_back(sc);
}
std::vector<ui32> h3mStarts = locateH3mStarts(cmpgn, it, realSize);
if(h3mStarts.size() != howManyScenarios)
{
tlog1<<"Our heuristic for h3m start points gave wrong results for campaign " << name <<std::endl;
tlog1<<"Please send this campaign to VCMI Project team to help us fix this problem" << std::endl;
delete [] cmpgn;
return NULL;
}
for (int g=0; g<howManyScenarios; ++g)
{
if(g == howManyScenarios - 1)
{
ret->mapPieces.push_back(std::string( cmpgn + h3mStarts[g], cmpgn + realSize ));
}
else
{
ret->mapPieces.push_back(std::string( cmpgn + h3mStarts[g], cmpgn + h3mStarts[g+1] ));
}
}
delete [] cmpgn;
@@ -86,6 +113,10 @@ CCampaignHeader CCampaignHandler::readHeaderFromMemory( const unsigned char *buf
ret.description = readString(buffer, outIt);
ret.difficultyChoosenByPlayer = readChar(buffer, outIt);
ret.music = readChar(buffer, outIt);
if(ret.version == 4) //I saw one campaign with this version, without either difficulty or music - it's
{ //not editable by any editor so I'll just go back by one byte.
outIt--;
}
return ret;
}
@@ -162,7 +193,7 @@ CScenarioTravel CCampaignHandler::readScenarioTravelFromMemory( const unsigned c
}
case 2: //building
{
//TODO
bonus.info1 = buffer[outIt++]; //building ID (0 - town hall, 1 - city hall, 2 - capitol, etc)
break;
}
case 3: //artifact
@@ -239,4 +270,89 @@ CScenarioTravel CCampaignHandler::readScenarioTravelFromMemory( const unsigned c
}
return ret;
}
std::vector<ui32> CCampaignHandler::locateH3mStarts( const unsigned char * buffer, int start, int size )
{
std::vector<ui32> ret;
for(int g=start; g<size; ++g)
{
if(startsAt(buffer, size, g))
{
ret.push_back(g);
}
}
return ret;
}
bool CCampaignHandler::startsAt( const unsigned char * buffer, int size, int pos )
{
struct HLP
{
static unsigned char at(const unsigned char * buffer, int size, int place)
{
if(place < size)
return buffer[place];
throw std::string("Out of bounds!");
}
};
try
{
//check minimal length of given region
HLP::at(buffer, size, 100);
//check version
unsigned char tmp = HLP::at(buffer, size, pos);
if(!(tmp == 0x0e || tmp == 0x15 || tmp == 0x1c || tmp == 0x33))
{
return false;
}
//3 bytes following version
if(HLP::at(buffer, size, pos+1) != 0 || HLP::at(buffer, size, pos+2) != 0 || HLP::at(buffer, size, pos+3) != 0)
{
return false;
}
//unknown strange byte
tmp = HLP::at(buffer, size, pos+4);
if(tmp != 0 && tmp != 1 )
{
return false;
}
//size of map
int mapsize = readNormalNr(buffer, pos+5);
if(mapsize < 10 || mapsize > 530)
{
return false;
}
//underground or not
tmp = HLP::at(buffer, size, pos+9);
if( tmp != 0 && tmp != 1 )
{
return false;
}
//map name
int len = readNormalNr(buffer, pos+10);
if(len < 0 || len > 100)
{
return false;
}
for(int t=0; t<len; ++t)
{
tmp = HLP::at(buffer, size, pos+14+t);
if(tmp == 0 || (tmp > 15 && tmp < 32)) //not a valid character
{
return false;
}
}
}
catch (...)
{
return false;
}
return true;
}

View File

@@ -101,10 +101,11 @@ class DLL_EXPORT CCampaign
public:
CCampaignHeader header;
std::vector<CCampaignScenario> scenarios;
std::vector<std::string> mapPieces; //binary h3ms
template <typename Handler> void serialize(Handler &h, const int formatVersion)
{
h & header & scenarios;
h & header & scenarios & mapPieces;
}
};
@@ -114,6 +115,8 @@ class DLL_EXPORT CCampaignHandler
CCampaignScenario readScenarioFromMemory( const unsigned char *buffer, int & outIt );
CScenarioTravel readScenarioTravelFromMemory( const unsigned char * buffer, int & outIt );
CCampaignHeader getHeader( const std::string & name, int size );
std::vector<ui32> locateH3mStarts(const unsigned char * buffer, int start, int size);
static bool startsAt( const unsigned char * buffer, int size, int pos ); //a simple heuristic that checks if a h3m starts at given pos
public:
std::vector<CCampaignHeader> getCampaignHeaders();

View File

@@ -18,7 +18,7 @@
*
*/
std::string readTo(std::string &in, int &it, char end)
std::string readTo(const std::string &in, int &it, char end)
{
int pom = it;
int last = in.find_first_of(end,it);
@@ -470,7 +470,7 @@ void CGeneralTextHandler::load()
quests[i].resize(5);
for (j = 0; j < 5; ++j)
{
loadToIt (dump, buf, it, 4); //front desciption
loadToIt (dump, buf, it, 4); //front description
quests[i][j].resize(6);
for (k = 0; k < 5; ++k)
{
@@ -500,10 +500,41 @@ void CGeneralTextHandler::load()
for (i = 14; i < 48; ++i)
loadToIt(seerNames[i], buf, it, 3);
//campaigns
buf = bitmaph->getTextFile ("CAMPTEXT.TXT");
it = 0;
loadToIt (dump, buf, it, 3); //comment
std::string nameBuf;
do //map names
{
loadToIt(nameBuf, buf, it, 3);
if(nameBuf.size())
{
campaignMapNames.push_back(nameBuf);
}
} while (nameBuf.size());
campaignRegionNames.resize(campaignMapNames.size()); //allocating space
for(int g=0; g<campaignMapNames.size(); ++g) //region names
{
do //dump comments and empty lines
{
loadToIt(nameBuf, buf, it, 3);
} while (nameBuf[0] != '/');
do //actual names
{
loadToIt(nameBuf, buf, it, 3);
if(nameBuf.size())
{
campaignRegionNames[g].push_back(nameBuf);
}
} while (nameBuf.size());
}
}
std::string CGeneralTextHandler::getTitle(std::string text)
std::string CGeneralTextHandler::getTitle(const std::string & text)
{
std::string ret;
int i=0;
@@ -512,7 +543,8 @@ std::string CGeneralTextHandler::getTitle(std::string text)
ret+=text[i++];
return ret;
}
std::string CGeneralTextHandler::getDescr(std::string text)
std::string CGeneralTextHandler::getDescr(const std::string & text)
{
std::string ret;
int i=0;

View File

@@ -14,8 +14,8 @@
*
*/
DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mode);
std::string readTo(std::string &in, int &it, char end);
DLL_EXPORT void loadToIt(std::string &dest, const std::string &src, int &iter, int mode);
std::string readTo(const std::string &in, int &it, char end);
class DLL_EXPORT CGeneralTextHandler //Handles general texts
{
public:
@@ -73,8 +73,12 @@ public:
std::vector <std::vector <std::string> > skillInfoTexts; //[id][level] : level 0 - basic; 2 - advanced
std::vector<std::string> levels;
std::string getTitle(std::string text);
std::string getDescr(std::string text);
//campaigns
std::vector <std::string> campaignMapNames;
std::vector < std::vector <std::string> > campaignRegionNames;
std::string getTitle(const std::string & text);
std::string getDescr(const std::string & text);
void load();
CGeneralTextHandler();

View File

@@ -7,7 +7,7 @@
#include <iomanip>
extern CLodHandler * bitmaph;
void loadToIt(std::string &dest, std::string &src, int &iter, int mode);
void loadToIt(std::string &dest, const std::string &src, int &iter, int mode);
/*
* CHeroHandler.cpp, part of VCMI engine

View File

@@ -276,7 +276,7 @@ std::string CLodHandler::getTextFile(std::string name)
unsigned char* data = giveFile(name,&length);
if (!data) {
tlog1<<"Fatal error. Missing game file. Aborting!"<<std::endl;
tlog1<<"Fatal error. Missing game file: " << name << ". Aborting!"<<std::endl;
exit(1);
}

View File

@@ -38,7 +38,7 @@ using namespace boost::assign;
std::map<int,std::map<int, std::vector<int> > > CGTeleport::objs;
std::vector<std::pair<int, int> > CGTeleport::gates;
IGameCallback * IObjectInterface::cb = NULL;
DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mode);
DLL_EXPORT void loadToIt(std::string &dest, const std::string &src, int &iter, int mode);
extern CLodHandler * bitmaph;
extern boost::rand48 ran;
std::map <ui8, std::set <ui8> > CGKeys::playerKeyMap;

View File

@@ -7,7 +7,7 @@
#include "CGeneralTextHandler.h"
extern CLodHandler * bitmaph;
void loadToIt(std::string &dest, std::string &src, int &iter, int mode);
void loadToIt(std::string &dest, const std::string &src, int &iter, int mode);
/*
* CTownHandler.cpp, part of VCMI engine

View File

@@ -48,7 +48,7 @@ DLL_EXPORT void initDLL(CConsoleHandler *Console, std::ostream *Logfile)
} HANDLE_EXCEPTION
}
DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mode)
DLL_EXPORT void loadToIt(std::string &dest, const std::string &src, int &iter, int mode)
{
switch(mode)
{
@@ -156,7 +156,7 @@ DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mod
}
DLL_EXPORT void loadToIt(si32 &dest, std::string &src, int &iter, int mode)
DLL_EXPORT void loadToIt(si32 &dest, const std::string &src, int &iter, int mode)
{
std::string pom;
loadToIt(pom,src,iter,mode);
@@ -247,3 +247,10 @@ LibClasses::LibClasses()
//init pointers to handlers
makeNull();
}
void LibClasses::callWhenDeserializing()
{
generaltexth = new CGeneralTextHandler;
generaltexth->load();
arth->loadArtifacts(true);
}

View File

@@ -2,9 +2,6 @@
#define __VCMI_LIB_H__
#include "../global.h"
#include "../hch/CArtHandler.h"
#include "../hch/CGeneralTextHandler.h"
/*
* VCMI_Lib.h, part of VCMI engine
*
@@ -49,15 +46,15 @@ public:
void init(); //uses standard config file
void clear(); //deletes all handlers and its data
void makeNull(); //sets all handler (except of lodhs) pointers to null
void callWhenDeserializing(); //should be called only by serialize !!!
template <typename Handler> void serialize(Handler &h, const int version)
{
h & heroh & arth & creh & townh & objh & dobjinfo & buildh & spellh;
if(!h.saving)
{
generaltexth = new CGeneralTextHandler;
generaltexth->load();
arth->loadArtifacts(true);
callWhenDeserializing();
}
}
};
@@ -65,8 +62,8 @@ public:
extern DLL_EXPORT LibClasses * VLC;
extern DLL_EXPORT CLodHandler * bitmaph, *spriteh;
DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mode);
DLL_EXPORT void loadToIt(si32 &dest, std::string &src, int &iter, int mode);
DLL_EXPORT void loadToIt(std::string &dest, const std::string &src, int &iter, int mode);
DLL_EXPORT void loadToIt(si32 &dest, const std::string &src, int &iter, int mode);
DLL_EXPORT void initDLL(CConsoleHandler *Console, std::ostream *Logfile);

View File

@@ -7,6 +7,7 @@
#include <zlib.h>
#include <boost/crc.hpp>
#include "../hch/CLodHandler.h"
#include "../hch/CArtHandler.h"
#include <boost/bind.hpp>
#include <assert.h>

View File

@@ -5,6 +5,7 @@
#include "../hch/CHeroHandler.h"
#include "../hch/CObjectHandler.h"
#include "../hch/CSpellHandler.h"
#include "../hch/CGeneralTextHandler.h"
#include "../hch/CTownHandler.h"
#include "../lib/CGameState.h"
#include "../lib/CondSh.h"