applied changes from 0.3pre6 (patch from rev40 to rev49)
git-svn-id: https://clonekeenplus.svn.sourceforge.net/svnroot/clonekeenplus/cgenius/trunk@79 4df4b0f3-56ce-47cb-b001-ed939b7d65a6
This commit is contained in:
222
src/fileio/CExeFile.cpp
Normal file
222
src/fileio/CExeFile.cpp
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* CExeFile.cpp
|
||||
*
|
||||
* Created on: 17.07.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#include "CExeFile.h"
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
using namespace std;
|
||||
|
||||
CExeFile::CExeFile(int episode, char *datadirectory) {
|
||||
m_episode = episode;
|
||||
m_datadirectory = datadirectory;
|
||||
m_data = NULL;
|
||||
}
|
||||
|
||||
CExeFile::~CExeFile() {
|
||||
if(m_data) delete m_data;
|
||||
}
|
||||
|
||||
bool CExeFile::readData()
|
||||
{
|
||||
char filename[256];
|
||||
unsigned char *m_data_temp;
|
||||
|
||||
sprintf(filename, "data/%skeen%d.exe", m_datadirectory, m_episode);
|
||||
|
||||
ifstream File(filename,ios::binary);
|
||||
|
||||
if(!File) return false;
|
||||
|
||||
File.seekg(0,ios::end);
|
||||
m_datasize = File.tellg();
|
||||
File.seekg(0,ios::beg);
|
||||
|
||||
m_data_temp = new unsigned char[m_datasize];
|
||||
File.read((char*)m_data_temp, m_datasize);
|
||||
|
||||
File.close();
|
||||
|
||||
vector<unsigned char> *decdata;
|
||||
decdata = new vector<unsigned char>;
|
||||
|
||||
if(unlzexe(m_data_temp, decdata))
|
||||
{
|
||||
m_datasize = decdata->size();
|
||||
m_data = new unsigned char[m_datasize];
|
||||
memcpy(m_data, decdata->data(), m_datasize);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_datasize -= 512; // if already decompressed subtract the header
|
||||
m_data = new unsigned char[m_datasize];
|
||||
memcpy(m_data, m_data_temp+512,m_datasize);
|
||||
}
|
||||
delete m_data_temp;
|
||||
|
||||
if(!decdata->empty()) decdata->clear();
|
||||
delete decdata;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CExeFile::get_bit(int *p_bit_count, unsigned char *fin, int *posin)
|
||||
{
|
||||
static unsigned short bits;
|
||||
int bit;
|
||||
|
||||
bit = bits & 1;
|
||||
(*p_bit_count)--;
|
||||
|
||||
if ((*p_bit_count) <= 0)
|
||||
{
|
||||
unsigned short a,b;
|
||||
a = (unsigned char) fin[(*posin)++];
|
||||
b = (unsigned char) fin[(*posin)++] << 8;
|
||||
bits = a | b;
|
||||
|
||||
if ((*p_bit_count) == -1) /* special case for first bit word */
|
||||
{
|
||||
bit = bits & 1;
|
||||
bits >>= 1;
|
||||
}
|
||||
|
||||
(*p_bit_count) += 16;
|
||||
}
|
||||
else
|
||||
bits >>= 1;
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
// return how much was unpacked or zero if nothing was unpacked
|
||||
int CExeFile::unlzexe(unsigned char *fin, vector<unsigned char> *outbuffer)
|
||||
{
|
||||
int bit_count;
|
||||
short offset;
|
||||
int pos, repeat;
|
||||
int posin = 0; // position of input
|
||||
|
||||
pos = 0;
|
||||
bit_count = 0;
|
||||
|
||||
/* skip header */
|
||||
posin = 32;
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
if (get_bit(&bit_count, fin, &posin))
|
||||
{
|
||||
outbuffer->push_back(fin[posin]);
|
||||
//outbuffer[pos] = fin[posin];
|
||||
pos++;
|
||||
posin++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (get_bit(&bit_count, fin, &posin))
|
||||
{
|
||||
unsigned char tmp[2];
|
||||
memcpy(tmp,fin+posin,2);
|
||||
posin+=2;
|
||||
repeat = (tmp[1] & 0x07);
|
||||
|
||||
offset = ((tmp[1] & ~0x07) << 5) | tmp[0] | 0xE000;
|
||||
|
||||
if (repeat == 0)
|
||||
{
|
||||
repeat = fin[posin++];
|
||||
|
||||
if (repeat == 0)
|
||||
break;
|
||||
else if (repeat == 1)
|
||||
continue;
|
||||
else
|
||||
repeat++;
|
||||
}
|
||||
else
|
||||
repeat += 2;
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
repeat = get_bit(&bit_count, fin, &posin) << 1;
|
||||
repeat |= get_bit(&bit_count, fin, &posin);
|
||||
repeat += 2;
|
||||
offset = fin[posin++] | 0xFF00;
|
||||
}
|
||||
|
||||
while (repeat > 0)
|
||||
{
|
||||
outbuffer->push_back(outbuffer->at(pos + offset));
|
||||
//outbuffer[pos] = outbuffer[pos + offset];
|
||||
pos++;
|
||||
repeat--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
int CExeFile::getEXEVersion()
|
||||
{
|
||||
switch (m_datasize)
|
||||
{
|
||||
case 99762:
|
||||
if(m_episode != 1)
|
||||
return -1;
|
||||
else
|
||||
return 110;
|
||||
case 99972:
|
||||
if(m_episode != 1)
|
||||
return -1;
|
||||
else
|
||||
return 131;
|
||||
|
||||
case 398:
|
||||
if(m_episode != 1)
|
||||
return -1;
|
||||
else
|
||||
return 134;
|
||||
|
||||
case 118114:
|
||||
if(m_episode != 2)
|
||||
return -1;
|
||||
else
|
||||
return 100;
|
||||
|
||||
case 118160:
|
||||
|
||||
if(m_episode != 2)
|
||||
return -1;
|
||||
else
|
||||
return 131;
|
||||
|
||||
case 127086:
|
||||
|
||||
if(m_episode != 3)
|
||||
return -1;
|
||||
else
|
||||
return 100;
|
||||
|
||||
case 127104:
|
||||
if(m_episode != 3)
|
||||
return -1;
|
||||
else
|
||||
return 131;
|
||||
|
||||
default: return -2;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char* CExeFile::getData()
|
||||
{ return m_data; }
|
||||
|
||||
36
src/fileio/CExeFile.h
Normal file
36
src/fileio/CExeFile.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* CExeFile.h
|
||||
*
|
||||
* Created on: 17.07.2009
|
||||
* Author: gerstrong
|
||||
*
|
||||
* This special class reads the whole exe-file
|
||||
* into the memory and decompresses if necessary
|
||||
*/
|
||||
|
||||
#ifndef CEXEFILE_H_
|
||||
#define CEXEFILE_H_
|
||||
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
class CExeFile {
|
||||
public:
|
||||
CExeFile(int episode, char *datadirectory);
|
||||
virtual ~CExeFile();
|
||||
|
||||
bool readData();
|
||||
int getEXEVersion();
|
||||
unsigned char* getData();
|
||||
|
||||
private:
|
||||
int m_datasize;
|
||||
int m_episode;
|
||||
unsigned char *m_data;
|
||||
char *m_datadirectory;
|
||||
|
||||
int get_bit(int *p_bit_count, unsigned char *fin, int *posin);
|
||||
int unlzexe(unsigned char *fin, vector<unsigned char> *outbuffer);
|
||||
};
|
||||
|
||||
#endif /* CEXEFILE_H_ */
|
||||
@@ -60,7 +60,7 @@ bool CParser::loadParseFile(void) // Open, read the list and close the file
|
||||
while(!feof(fp))
|
||||
{
|
||||
line = (char*) calloc(256,sizeof(char));
|
||||
fgets(line,256,fp);
|
||||
fgets(line,256,fp); // No return value assigned. Be careful!
|
||||
//fscanf(fp,"%s\n",line);
|
||||
m_filebuffer.push_back(line);
|
||||
m_isOpen = true;
|
||||
|
||||
182
src/fileio/CPatcher.cpp
Normal file
182
src/fileio/CPatcher.cpp
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* CPatcher.cpp
|
||||
*
|
||||
* Created on: 19.07.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#include "CPatcher.h"
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <fstream>
|
||||
|
||||
CPatcher::CPatcher(int episode, int version,unsigned char *data, char *datadir) {
|
||||
m_episode = episode;
|
||||
m_version = version;
|
||||
m_data = data;
|
||||
strcpy(m_datadirectory, datadir);
|
||||
}
|
||||
|
||||
CPatcher::~CPatcher() {
|
||||
while(!m_TextList.empty())
|
||||
{
|
||||
delete *(m_TextList.begin());
|
||||
m_TextList.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
void CPatcher::patchMemory()
|
||||
{
|
||||
if(!loadPatchfile()) return;
|
||||
|
||||
// If the file was found and read into the m_TextList,
|
||||
// then read out of the list the patch commands and apply them to the
|
||||
// Exe-file data m_data
|
||||
|
||||
// change to the proper directory
|
||||
chdir("data");
|
||||
chdir(m_datadirectory);
|
||||
|
||||
// TODO: Extend this part further with more commands
|
||||
while(!m_TextList.empty())
|
||||
{
|
||||
char line[256];
|
||||
|
||||
strcpy(line,*(m_TextList.begin()));
|
||||
|
||||
if(strncmp(line,"\%version",strlen("\%version")) == 0)
|
||||
{
|
||||
char *verstring;
|
||||
char detected_version[5];
|
||||
|
||||
verstring = line + strlen("\%version");
|
||||
|
||||
sscanf(verstring,"%s",detected_version);
|
||||
|
||||
if((!strcmp(detected_version,"1.31") && m_version == 131 )
|
||||
|| (!strcmp(detected_version,"1.1") && m_version == 110 )
|
||||
|| !strcmp(detected_version,"ALL"))
|
||||
{
|
||||
while(!m_TextList.empty())
|
||||
{
|
||||
// Get the next line
|
||||
strcpy(line,*(m_TextList.begin()));
|
||||
|
||||
// Now we really start to process the commands
|
||||
if( strncmp(line,"\%patchfile",strlen("\%patchfile")) == 0 )
|
||||
{
|
||||
unsigned long offset;
|
||||
char *newbuf;
|
||||
char patch_file_name[256];
|
||||
newbuf = line + strlen("\%patchfile");
|
||||
sscanf(newbuf,"%lx %s",&offset,patch_file_name); // Only hexadecimal numbers supported
|
||||
patchMemfromFile((const char*)patch_file_name,offset);
|
||||
}
|
||||
|
||||
if(!m_TextList.empty())
|
||||
{
|
||||
delete *(m_TextList.begin());
|
||||
m_TextList.pop_front();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!m_TextList.empty())
|
||||
{
|
||||
delete *(m_TextList.begin());
|
||||
m_TextList.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
// change back to "data" dir
|
||||
char curdir[256];
|
||||
while(1)
|
||||
{
|
||||
char *reldir;
|
||||
getcwd(curdir,256);
|
||||
reldir = curdir+strlen(curdir)-strlen("data");
|
||||
if(strcmp(reldir,"data"))
|
||||
chdir("..");
|
||||
else
|
||||
break;
|
||||
}
|
||||
chdir("..");
|
||||
}
|
||||
|
||||
bool CPatcher::loadPatchfile()
|
||||
{
|
||||
bool ret = false;
|
||||
chdir("data");
|
||||
chdir(m_datadirectory);
|
||||
// Detect the patchfile
|
||||
DIR *dir = opendir(".");
|
||||
struct dirent *dp;
|
||||
|
||||
if(dir)
|
||||
{
|
||||
while( ( dp = readdir(dir) ) )
|
||||
{
|
||||
if(strstr(dp->d_name,".pat"))
|
||||
{
|
||||
// The file was found! now read it into the memory!
|
||||
|
||||
char* buf;
|
||||
ifstream Patchfile(dp->d_name);
|
||||
|
||||
while(!Patchfile.eof())
|
||||
{
|
||||
buf = new char[256];
|
||||
Patchfile.getline(buf,256);
|
||||
m_TextList.push_back(buf);
|
||||
}
|
||||
|
||||
Patchfile.close();
|
||||
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char curdir[256];
|
||||
while(1)
|
||||
{
|
||||
char *reldir;
|
||||
getcwd(curdir,256);
|
||||
reldir = curdir+strlen(curdir)-strlen("data");
|
||||
if(strcmp(reldir,"data"))
|
||||
chdir("..");
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
chdir("..");
|
||||
closedir(dir);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CPatcher::patchMemfromFile(const char *patch_file_name, int offset)
|
||||
{
|
||||
unsigned char *buf_to_patch;
|
||||
unsigned char byte;
|
||||
|
||||
ifstream Patchfile(patch_file_name, ios::binary);
|
||||
|
||||
if(!Patchfile) return;
|
||||
|
||||
buf_to_patch = m_data + offset;
|
||||
|
||||
// TODO: Add a routine which checks the sizes of the file.
|
||||
long counter = 0;
|
||||
|
||||
while(!Patchfile.eof())
|
||||
{
|
||||
byte = (unsigned char) Patchfile.get();
|
||||
memcpy(buf_to_patch+counter,&byte,1); // one byte every time ;-)
|
||||
counter++;
|
||||
}
|
||||
|
||||
Patchfile.close();
|
||||
}
|
||||
35
src/fileio/CPatcher.h
Normal file
35
src/fileio/CPatcher.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* CPatcher.h
|
||||
*
|
||||
* Created on: 19.07.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#ifndef CPATCHER_H_
|
||||
#define CPATCHER_H_
|
||||
|
||||
#include <list>
|
||||
using namespace std;
|
||||
|
||||
class CPatcher {
|
||||
public:
|
||||
CPatcher(int episode, int version,unsigned char *data, char *datadir);
|
||||
virtual ~CPatcher();
|
||||
|
||||
void patchMemory();
|
||||
void patchMemfromFile(const char *patch_file_name, int offset);
|
||||
|
||||
private:
|
||||
|
||||
bool loadPatchfile();
|
||||
|
||||
int m_episode;
|
||||
int m_version;
|
||||
unsigned char *m_data;
|
||||
char m_datadirectory[256];
|
||||
|
||||
list<char*> m_TextList;
|
||||
|
||||
};
|
||||
|
||||
#endif /* CPATCHER_H_ */
|
||||
203
src/fileio/CTileLoader.cpp
Normal file
203
src/fileio/CTileLoader.cpp
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* CTileLoader.cpp
|
||||
*
|
||||
* Created on: 19.07.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#include "CTileLoader.h"
|
||||
#include "../CLogFile.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_STRING_LENGTH 256
|
||||
extern stTile tiles[MAX_TILES+1];
|
||||
|
||||
CTileLoader::CTileLoader(int episode, int version, unsigned char *data) {
|
||||
TileProperty = NULL;
|
||||
m_episode = episode;
|
||||
m_version = version;
|
||||
m_data = data;
|
||||
m_offset = 0;
|
||||
}
|
||||
|
||||
CTileLoader::~CTileLoader() {
|
||||
// Here we really start reading the tiles
|
||||
if(TileProperty != NULL)
|
||||
{
|
||||
for(int i = 0 ; i < 1000 ; i++)
|
||||
{
|
||||
if(TileProperty[i] != NULL)
|
||||
{
|
||||
delete [] TileProperty[i];
|
||||
TileProperty[i] = NULL;
|
||||
}
|
||||
}
|
||||
delete [] TileProperty;
|
||||
TileProperty = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool CTileLoader::setProperOffset()
|
||||
{
|
||||
// Identify the offset
|
||||
switch (m_episode)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
numtiles = 611;
|
||||
switch(m_version)
|
||||
{
|
||||
case 110: m_offset = 0x131F8; break;
|
||||
case 131: m_offset = 0x130F8; break;
|
||||
case 134: m_offset = 0x130F8; // This is incorrect!
|
||||
g_pLogFile->textOut(PURPLE,"If you want to use Episode 1 Version 1.34, assure that is was unpacked before (with unpklite for example).<br>");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
numtiles = 689;
|
||||
switch(m_version)
|
||||
{
|
||||
case 100: m_offset = 0x17938; break;
|
||||
case 131: m_offset = 0x17828; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
numtiles = 715;
|
||||
switch(m_version)
|
||||
{
|
||||
case 100: m_offset = 0x199F8; break;
|
||||
case 131: m_offset = 0x198C8; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
g_pLogFile->textOut(PURPLE,"CAUTION: The version was not detected correctly. The game muy be unplayable!<br>");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_data += m_offset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CTileLoader::load()
|
||||
{
|
||||
int t,a,b;
|
||||
char fname[MAX_STRING_LENGTH];
|
||||
int i,j; // standard counters
|
||||
|
||||
if(!setProperOffset()) return false;
|
||||
|
||||
//TileProperty = (int**) malloc(1000*sizeof(int*));
|
||||
TileProperty = new int*[1000];
|
||||
|
||||
for(i = 0 ; i < 1000 ; i++)
|
||||
{
|
||||
TileProperty[i] = NULL;
|
||||
TileProperty[i] = new int[6];
|
||||
}
|
||||
|
||||
for(j=0 ; j < 1000 ; j++ )
|
||||
{
|
||||
for(i=0; i < 6 ; i++)
|
||||
TileProperty[j][i]=0;
|
||||
}
|
||||
|
||||
if(TileProperty == NULL)
|
||||
{
|
||||
g_pLogFile->textOut(RED,"TileLoader: The memory couldn't be allocated for this version of game!<br>");
|
||||
return false;
|
||||
}
|
||||
|
||||
for(i=0 ; i < 6 ; i++)
|
||||
{
|
||||
for(j=0 ; j < numtiles ; j++)
|
||||
{
|
||||
TileProperty[j][i] = m_data[i*2*(numtiles)+2*j];
|
||||
TileProperty[j][i] += m_data[i*2*(numtiles)+2*j+1]<<8;
|
||||
}
|
||||
}
|
||||
|
||||
int value;
|
||||
|
||||
for( j=0 ; j < numtiles ; j++ )
|
||||
{
|
||||
value = TileProperty[j][0];
|
||||
|
||||
// stuff for animated tiles
|
||||
if(value == 1)
|
||||
{
|
||||
tiles[j].animOffset = 0; // starting offset from the base frame
|
||||
}
|
||||
else if( value == 2 )
|
||||
{
|
||||
tiles[j++].animOffset = 0; // starting offset from the base frame
|
||||
tiles[j].animOffset = 1; // starting offset from the base frame
|
||||
}
|
||||
else
|
||||
{
|
||||
tiles[j++].animOffset = 0; // starting offset from the base frame
|
||||
tiles[j++].animOffset = 1; // starting offset from the base frame
|
||||
tiles[j++].animOffset = 2; // starting offset from the base frame
|
||||
tiles[j].animOffset = 3; // starting offset from the base frame
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(fname, "ep%dattr.dat", m_episode);
|
||||
|
||||
FILE *fp;
|
||||
fp = fopen(fname, "rb");
|
||||
if (!fp)
|
||||
{
|
||||
g_pLogFile->textOut(RED,"TileLoader: Cannot open tile attribute file!<br>");
|
||||
return false;
|
||||
}
|
||||
|
||||
// load additional information the tiles
|
||||
for(t=0;t<numtiles-1;t++)
|
||||
{
|
||||
a = fgetc(fp); b = fgetc(fp);
|
||||
tiles[t].chgtile = (a<<8)+b;
|
||||
if(tiles[t].chgtile > numtiles)
|
||||
tiles[t].chgtile = 0;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
// Those Tile data files are an good option, but they are not very well seen.
|
||||
// Especially in mods. The one of Episode 2 has an error with items already
|
||||
// I'm to lazy to write a program which fixes the file so a new assignTilePointer is
|
||||
// used, which in future will replace the files making them obsolete
|
||||
assignChangeTileAttribute(tiles);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CTileLoader::assignChangeTileAttribute(stTile *tile)
|
||||
{
|
||||
// This special call is used for workarounds which are wrong in the tiles attributes file of CG.
|
||||
// I hope those attributes can be read out of the exe-files in future.
|
||||
switch(m_episode)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
for(int i=306 ; i<=311 ; i++) // Workaround in Level 12 of Episode 2, where the tiles are solid after a taken item.
|
||||
tile[i].chgtile = 276;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
41
src/fileio/CTileLoader.h
Normal file
41
src/fileio/CTileLoader.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* CTileLoader.h
|
||||
*
|
||||
* Created on: 19.07.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#ifndef CTILELOADER_H_
|
||||
#define CTILELOADER_H_
|
||||
|
||||
#define MAX_TILES 800
|
||||
|
||||
extern int numtiles;
|
||||
extern int **TileProperty; // This version will replace the old stTile Structure and save memory
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int masktile; // if nonzero, specifies a mask for this tile
|
||||
int chgtile; // tile to change to when level completed (for wm)
|
||||
// or tile to change to when picked up (in-level)
|
||||
unsigned int animOffset; // starting offset from the base frame
|
||||
} stTile;
|
||||
|
||||
class CTileLoader {
|
||||
public:
|
||||
CTileLoader(int episode, int version, unsigned char *data);
|
||||
virtual ~CTileLoader();
|
||||
|
||||
bool load();
|
||||
|
||||
private:
|
||||
int m_episode;
|
||||
int m_version;
|
||||
long m_offset;
|
||||
unsigned char *m_data;
|
||||
|
||||
void assignChangeTileAttribute(stTile *tile);
|
||||
bool setProperOffset();
|
||||
};
|
||||
|
||||
#endif /* CTILELOADER_H_ */
|
||||
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
* lzexe.c
|
||||
*
|
||||
* Created on: 24.01.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int get_bit(int *p_bit_count, FILE **fin)
|
||||
{
|
||||
static unsigned short bits;
|
||||
int bit;
|
||||
|
||||
bit = bits & 1;
|
||||
(*p_bit_count)--;
|
||||
|
||||
if ((*p_bit_count) <= 0)
|
||||
{
|
||||
bits = getc(*fin) | getc(*fin) << 8;
|
||||
|
||||
if ((*p_bit_count) == -1) /* special case for first bit word */
|
||||
{
|
||||
bit = bits & 1;
|
||||
bits >>= 1;
|
||||
}
|
||||
|
||||
(*p_bit_count) += 16;
|
||||
}
|
||||
else
|
||||
bits >>= 1;
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
int getEXEVersion(int episode, int bufsize)
|
||||
{
|
||||
switch (bufsize)
|
||||
{
|
||||
case 99762:
|
||||
if(episode != 1)
|
||||
return -1;
|
||||
else
|
||||
return 110;
|
||||
case 99972:
|
||||
if(episode != 1)
|
||||
return -1;
|
||||
else
|
||||
return 131;
|
||||
|
||||
case 398:
|
||||
if(episode != 1)
|
||||
return -1;
|
||||
else
|
||||
return 134;
|
||||
|
||||
case 118114:
|
||||
if(episode != 2)
|
||||
return -1;
|
||||
else
|
||||
return 100;
|
||||
|
||||
case 118160:
|
||||
|
||||
if(episode != 2)
|
||||
return -1;
|
||||
else
|
||||
return 131;
|
||||
|
||||
case 127086:
|
||||
|
||||
if(episode != 3)
|
||||
return -1;
|
||||
else
|
||||
return 100;
|
||||
|
||||
case 127104:
|
||||
if(episode != 3)
|
||||
return -1;
|
||||
else
|
||||
return 131;
|
||||
|
||||
default: return -2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// return how much was unpacked or zero if nothing was unpacked
|
||||
int unlzexe(FILE *fin, unsigned char *outbuffer)
|
||||
{
|
||||
int bit_count;
|
||||
short offset;
|
||||
int pos, repeat;
|
||||
|
||||
pos = 0;
|
||||
bit_count = 0;
|
||||
|
||||
/* skip header */
|
||||
fseek(fin, 32, SEEK_SET);
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
if (get_bit(&bit_count, &fin))
|
||||
{
|
||||
outbuffer[pos++] = getc(fin);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (get_bit(&bit_count, &fin))
|
||||
{
|
||||
unsigned char tmp[2];
|
||||
fread(tmp, 1, 2, fin);
|
||||
repeat = (tmp[1] & 0x07);
|
||||
|
||||
offset = ((tmp[1] & ~0x07) << 5) | tmp[0] | 0xE000;
|
||||
|
||||
if (repeat == 0)
|
||||
{
|
||||
repeat = getc (fin);
|
||||
|
||||
|
||||
if (repeat == 0)
|
||||
break;
|
||||
else if (repeat == 1)
|
||||
continue;
|
||||
else
|
||||
repeat++;
|
||||
}
|
||||
else
|
||||
repeat += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
repeat = ((get_bit(&bit_count, &fin) << 1) | get_bit(&bit_count, &fin)) + 2;
|
||||
offset = getc(fin) | 0xFF00;
|
||||
}
|
||||
|
||||
while (repeat > 0)
|
||||
{
|
||||
outbuffer[pos] = outbuffer[pos + offset];
|
||||
pos++;
|
||||
repeat--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
@@ -9,8 +9,8 @@
|
||||
*/
|
||||
|
||||
#include "../keen.h"
|
||||
#include "../include/fileio/lzexe.h"
|
||||
#include "../include/fileio.h"
|
||||
#include "../fileio/CExeFile.h"
|
||||
#include "../CLogFile.h"
|
||||
|
||||
int readStoryText(char **ptext, int episode, char *path)
|
||||
@@ -32,27 +32,11 @@ int readStoryText(char **ptext, int episode, char *path)
|
||||
if((fp=fopen(buf,"rb"))!=NULL)
|
||||
{
|
||||
unsigned char *filebuf;
|
||||
int bufsize;
|
||||
int startflag=0, endflag=0; // where story begins and ends!
|
||||
|
||||
filebuf = (unsigned char*) malloc(500000*sizeof(unsigned char));
|
||||
|
||||
bufsize = unlzexe(fp, filebuf);
|
||||
|
||||
rewind(fp);
|
||||
|
||||
if ( bufsize == 0 ) // Program was not unpacked, so read it normally
|
||||
{
|
||||
while(!feof(fp))
|
||||
{
|
||||
filebuf[bufsize] = getc(fp);
|
||||
bufsize++;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
int startflag=0, endflag=0, version=0; // where story begins and ends!
|
||||
|
||||
version = getEXEVersion(episode, bufsize);
|
||||
CExeFile *ExeFile = new CExeFile(episode, buf2);
|
||||
ExeFile->readData();
|
||||
filebuf = ExeFile->getData();
|
||||
|
||||
if(episode == 2)
|
||||
{
|
||||
@@ -74,8 +58,7 @@ int readStoryText(char **ptext, int episode, char *path)
|
||||
*ptext = (char*) malloc((endflag-startflag+10)*sizeof(char));
|
||||
strncpy((*ptext),(char*)filebuf+startflag,(endflag-startflag)*sizeof(char));
|
||||
}
|
||||
|
||||
free(filebuf);
|
||||
delete ExeFile;
|
||||
|
||||
return (endflag-startflag);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user