/* * CPatcher.cpp * * Created on: 19.07.2009 * Author: gerstrong */ #include "CPatcher.h" #include #include #include #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(); }