Guest

IceDragon

By: a guest on Oct 12th, 2007  |  syntax: C++  |  size: 5.23 KB  |  hits: 136  |  expires: Never
download  |  raw  |  embed  |  report abuse
Copied
  1. /* .-=[ rch2extract ]======================================================-. *\
  2.  * |    RCH 2.0 File Extractor 0.1 (c) 2007 by IceDragon of QuickFox.org    | *
  3.  * |---------------------------------------------[ icedragon@quickfox.org ]-| *
  4.  * | This little program finds and extracts the RCH2 package from DEP's     | *
  5.  * | Furcadia installer executable (furcsetup*.exe) and stores it on disk   | *
  6.  * | for further manipulation.                                              | *
  7.  * |                                                                        | *
  8.  * | This program is fully compatible with compatible with furcsetup023.exe | *
  9.  * | and furcsetup024.exe installers. Others were not tested, but should    | *
  10.  * | work regardless.                                                       | *
  11.  * |--[ Changelog ]---------------------------------------------------------| *
  12.  * | 0.1 - Initial release.                                                 | *
  13. \* '-==============================================================[ 0.1 ]=-' */
  14.  
  15. /*** Includes ***/
  16. #include <iostream>
  17. #include <fstream>
  18. #include <string>
  19. #include <cstdlib>
  20. #include <cstring>
  21.  
  22. /*** Definitions ***/
  23. #define min(a,b)    (a > b) ? b : a
  24. #define RCH2_HEADER "RCH2.0FZ"
  25.  
  26. using namespace std;
  27.  
  28. /*** Global Variables ***/
  29. // List of possible offsets.
  30. int rch2offsets[] = { 0x2f000, 0x30000, -1 };
  31.  
  32. // Input file descriptor.
  33. ifstream fd;
  34.  
  35.  
  36. /*** Functions ***/
  37. // This function locates the RCH2.0 header within the file. First it tries the
  38. // built-in locations in rch2offsets[] above, but if the header is not there,
  39. // the system would perform a more primitive search to try and find the header
  40. // manually.
  41. int findHeader
  42. ()
  43. {
  44.         char header[6];
  45.         int  i = 0;
  46.        
  47.         // Preset offset search.
  48.         while( rch2offsets[ i ] >= 0 )
  49.         {
  50.                 fd.seekg( rch2offsets[i], ios::beg );
  51.                 fd.read( header, 6 );
  52.                
  53.                 if( !strncmp( header, RCH2_HEADER, 6 ) )
  54.                 {
  55.                         fd.seekg( rch2offsets[i], ios::beg );
  56.                         cout << " " << rch2offsets[i];
  57.                         return rch2offsets[i];
  58.                 }
  59.                
  60.                 i++;
  61.         }
  62.        
  63.         // Searching further.
  64.         fd.seekg( 0, ios::beg );
  65.        
  66.         int  j,count;  
  67.         char buffer[4096];
  68.         bool loop = true;
  69.  
  70.         while( loop )
  71.         {
  72.                 fd.read( buffer, 4096 );
  73.                 count = fd.gcount();
  74.                
  75.                 for( i = 0; (i+8) < count; i++ )
  76.                 {
  77.                         for( j = 0; j < 8; j++ )
  78.                                 if( buffer[i+j] != RCH2_HEADER[j] )
  79.                                         break;
  80.                        
  81.                         if( j >= 8 )
  82.                         {
  83.                                 fd.seekg( (count * -1) + i, ios::cur );
  84.                                 cout << " " << fd.tellg();
  85.                                 return fd.tellg();
  86.                         }
  87.                 }
  88.                
  89.                 if( fd.eof() )
  90.                         loop = false;
  91.         }
  92.        
  93.         return -1; // Not found
  94. }
  95.  
  96.  
  97. // This function searches for the overall filesize of the RCH2 file so we can
  98. // later extract it in an easy way from the EXE. Of course we could extract
  99. // during the read, but it's a lot more complex and bug-prone IMO.
  100. streamsize getFilesize
  101. ()
  102. {
  103.         streamsize startPoint = fd.tellg();
  104.         streamsize fileSize;
  105.        
  106.         fd.seekg( 6, ios::cur );
  107.        
  108.         char buffer[4096];
  109.         bool loop = true;
  110.         int  fnSize;
  111.         int  fSize;
  112.         while ( loop )
  113.         {
  114.                 fd.read( buffer, 2 );
  115.                 if( strncmp( buffer, "FZ", 2 ) )
  116.                 {
  117.                         fd.seekg( -2, ios::cur );
  118.                         break;
  119.                 }
  120.                
  121.                 fd.read( buffer, 2 );
  122.                 memcpy( &fnSize, buffer, 2 );
  123.                
  124.                 if( fnSize > 20000 )
  125.                 {
  126.                         fd.seekg( -2, ios::cur );
  127.                         break;
  128.                 }
  129.                
  130.                 fd.seekg( fnSize, ios::cur );
  131.                
  132.                 fd.read( buffer, 4 );
  133.                 memcpy( &fSize, buffer, 4 );
  134.                
  135.                 fd.seekg( 4+fSize, ios::cur );
  136.                
  137.                 if( fd.eof() )
  138.                         loop = false;
  139.         }
  140.        
  141.         fileSize = (streamsize)fd.tellg() - startPoint;
  142.         fd.seekg( startPoint, ios::beg );
  143.        
  144.         return fileSize;
  145. }
  146.  
  147.  
  148.  
  149. /*** Main Function ***/
  150. int main
  151. ( int argc, char *argv[] )
  152. {
  153.         string fileName;
  154.         string targetFilename;
  155.  
  156.        
  157.         // Banner
  158.         cout << "--+ RCH2.0 Extractor (c) 2007 by IceDragon <icedragon@quickfox.org> +--" << endl << endl;
  159.  
  160.  
  161.         // Setting filename
  162.         if( argc < 2 )
  163.         {
  164.                 cout << "Syntax: " << argv[0] << " <filename> [output_file]" << endl;
  165.                 return -1;
  166.         }
  167.         else
  168.         {
  169.                 fileName       = argv[1];
  170.                 targetFilename = ( argc > 2 ) ? argv[2] : "output.rc2";
  171.         }
  172.  
  173.        
  174.         // Opening installer
  175.         cout << ".. Opening file...";
  176.         fd.open( fileName.c_str(), ios::binary );
  177.         if( !fd.is_open() )
  178.         {
  179.                 cout << " FAILED!" << endl;
  180.                 return -2;
  181.         }
  182.         else
  183.                 cout << " OK" << endl;
  184.        
  185.        
  186.         // Looking for RCH2 inside installer.
  187.         cout << ".. Searching for RCH2 signature...";
  188.         if( findHeader() < 0 )
  189.         {
  190.                 fd.close();
  191.                 cout << " FAILED!" << endl;
  192.                 return -3;
  193.         }
  194.         else
  195.                 cout << " OK" << endl;
  196.        
  197.        
  198.         // Calculating file size.
  199.         cout << ".. Calculating size...";
  200.         streamsize fileSize = getFilesize();
  201.         cout << " " << fileSize << " bytes" << endl;
  202.        
  203.        
  204.         // Extracting data.
  205.         cout << ".. Extracting data...";
  206.         ofstream fdOut ( targetFilename.c_str(), ios::binary );
  207.        
  208.         if( !fdOut.is_open() )
  209.         {
  210.                 cout << "ERROR - Unable to open target file " << targetFilename << "!" << endl;
  211.                 fd.close();
  212.                 return -4;
  213.         }
  214.        
  215.         char buffer[4096];
  216.        
  217.         while( fileSize )
  218.         {
  219.                 fd.read( buffer, min( 4096, fileSize ) );
  220.                 if( fd.bad() )
  221.                 {
  222.                         fd.close();
  223.                         fdOut.close();
  224.                         cout << "ERROR - Reading interrupted!" << endl;
  225.                         return -5;
  226.                 }
  227.                
  228.                 fdOut.write( buffer, fd.gcount() );
  229.                 fileSize -= fd.gcount();
  230.         }
  231.        
  232.         fd.close();
  233.         fdOut.close();
  234.        
  235.         cout << " OK" << endl;
  236.        
  237.         return EXIT_SUCCESS;
  238. }
  239.  
  240. /*** End of File ***/