Posted by IceDragon on Fri 12 Oct 21:12
report abuse | download | new post
- /* .-=[ rch2extract ]======================================================-. *\
- * | RCH 2.0 File Extractor 0.1 (c) 2007 by IceDragon of QuickFox.org | *
- * |---------------------------------------------[ icedragon@quickfox.org ]-| *
- * | This little program finds and extracts the RCH2 package from DEP's | *
- * | Furcadia installer executable (furcsetup*.exe) and stores it on disk | *
- * | for further manipulation. | *
- * | | *
- * | This program is fully compatible with compatible with furcsetup023.exe | *
- * | and furcsetup024.exe installers. Others were not tested, but should | *
- * | work regardless. | *
- * |--[ Changelog ]---------------------------------------------------------| *
- * | 0.1 - Initial release. | *
- \* '-==============================================================[ 0.1 ]=-' */
- /*** Includes ***/
- #include <iostream>
- #include <fstream>
- #include <string>
- #include <cstdlib>
- #include <cstring>
- /*** Definitions ***/
- #define min(a,b) (a > b) ? b : a
- #define RCH2_HEADER "RCH2.0FZ"
- using namespace std;
- /*** Global Variables ***/
- // List of possible offsets.
- int rch2offsets[] = { 0x2f000, 0x30000, -1 };
- // Input file descriptor.
- ifstream fd;
- /*** Functions ***/
- // This function locates the RCH2.0 header within the file. First it tries the
- // built-in locations in rch2offsets[] above, but if the header is not there,
- // the system would perform a more primitive search to try and find the header
- // manually.
- int findHeader
- ()
- {
- char header[6];
- int i = 0;
- // Preset offset search.
- while( rch2offsets[ i ] >= 0 )
- {
- fd.seekg( rch2offsets[i], ios::beg );
- fd.read( header, 6 );
- if( !strncmp( header, RCH2_HEADER, 6 ) )
- {
- fd.seekg( rch2offsets[i], ios::beg );
- cout << " " << rch2offsets[i];
- return rch2offsets[i];
- }
- i++;
- }
- // Searching further.
- fd.seekg( 0, ios::beg );
- int j,count;
- char buffer[4096];
- bool loop = true;
- while( loop )
- {
- fd.read( buffer, 4096 );
- count = fd.gcount();
- for( i = 0; (i+8) < count; i++ )
- {
- for( j = 0; j < 8; j++ )
- if( buffer[i+j] != RCH2_HEADER[j] )
- break;
- if( j >= 8 )
- {
- fd.seekg( (count * -1) + i, ios::cur );
- cout << " " << fd.tellg();
- return fd.tellg();
- }
- }
- if( fd.eof() )
- loop = false;
- }
- return -1; // Not found
- }
- // This function searches for the overall filesize of the RCH2 file so we can
- // later extract it in an easy way from the EXE. Of course we could extract
- // during the read, but it's a lot more complex and bug-prone IMO.
- streamsize getFilesize
- ()
- {
- streamsize startPoint = fd.tellg();
- streamsize fileSize;
- fd.seekg( 6, ios::cur );
- char buffer[4096];
- bool loop = true;
- int fnSize;
- int fSize;
- while ( loop )
- {
- fd.read( buffer, 2 );
- if( strncmp( buffer, "FZ", 2 ) )
- {
- fd.seekg( -2, ios::cur );
- break;
- }
- fd.read( buffer, 2 );
- memcpy( &fnSize, buffer, 2 );
- if( fnSize > 20000 )
- {
- fd.seekg( -2, ios::cur );
- break;
- }
- fd.seekg( fnSize, ios::cur );
- fd.read( buffer, 4 );
- memcpy( &fSize, buffer, 4 );
- fd.seekg( 4+fSize, ios::cur );
- if( fd.eof() )
- loop = false;
- }
- fileSize = (streamsize)fd.tellg() - startPoint;
- fd.seekg( startPoint, ios::beg );
- return fileSize;
- }
- /*** Main Function ***/
- int main
- ( int argc, char *argv[] )
- {
- string fileName;
- string targetFilename;
- // Banner
- cout << "--+ RCH2.0 Extractor (c) 2007 by IceDragon <icedragon@quickfox.org> +--" << endl << endl;
- // Setting filename
- if( argc < 2 )
- {
- cout << "Syntax: " << argv[0] << " <filename> [output_file]" << endl;
- return -1;
- }
- else
- {
- fileName = argv[1];
- targetFilename = ( argc > 2 ) ? argv[2] : "output.rc2";
- }
- // Opening installer
- cout << ".. Opening file...";
- fd.open( fileName.c_str(), ios::binary );
- if( !fd.is_open() )
- {
- cout << " FAILED!" << endl;
- return -2;
- }
- else
- cout << " OK" << endl;
- // Looking for RCH2 inside installer.
- cout << ".. Searching for RCH2 signature...";
- if( findHeader() < 0 )
- {
- fd.close();
- cout << " FAILED!" << endl;
- return -3;
- }
- else
- cout << " OK" << endl;
- // Calculating file size.
- cout << ".. Calculating size...";
- streamsize fileSize = getFilesize();
- cout << " " << fileSize << " bytes" << endl;
- // Extracting data.
- cout << ".. Extracting data...";
- ofstream fdOut ( targetFilename.c_str(), ios::binary );
- if( !fdOut.is_open() )
- {
- cout << "ERROR - Unable to open target file " << targetFilename << "!" << endl;
- fd.close();
- return -4;
- }
- char buffer[4096];
- while( fileSize )
- {
- fd.read( buffer, min( 4096, fileSize ) );
- if( fd.bad() )
- {
- fd.close();
- fdOut.close();
- cout << "ERROR - Reading interrupted!" << endl;
- return -5;
- }
- fdOut.write( buffer, fd.gcount() );
- fileSize -= fd.gcount();
- }
- fd.close();
- fdOut.close();
- cout << " OK" << endl;
- return EXIT_SUCCESS;
- }
- /*** End of File ***/
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.