git-svn-id: https://clonekeenplus.svn.sourceforge.net/svnroot/clonekeenplus/cgenius/trunk@152 4df4b0f3-56ce-47cb-b001-ed939b7d65a6
185 lines
3.6 KiB
C++
185 lines
3.6 KiB
C++
/*
|
|
* CPatcher.cpp
|
|
*
|
|
* Created on: 19.07.2009
|
|
* Author: gerstrong
|
|
*/
|
|
|
|
#include "CPatcher.h"
|
|
#include <dirent.h>
|
|
#include <string.h>
|
|
#include <fstream>
|
|
#include "../FindFile.h"
|
|
|
|
CPatcher::CPatcher(int episode, int version,unsigned char *data, const std::string& datadir) {
|
|
m_episode = episode;
|
|
m_version = version;
|
|
m_data = data;
|
|
m_datadirectory = datadir;
|
|
if(m_datadirectory != "") m_datadirectory += "/";
|
|
}
|
|
|
|
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.c_str());
|
|
|
|
// 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.c_str());
|
|
// 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;
|
|
std::ifstream Patchfile; OpenGameFileR(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 std::string& patch_file_name, int offset)
|
|
{
|
|
unsigned char *buf_to_patch;
|
|
unsigned char byte;
|
|
|
|
std::ifstream Patchfile; OpenGameFileR(Patchfile, patch_file_name, std::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();
|
|
}
|