ucdata.cc

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2001-2002  The Exult Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 #ifdef HAVE_CONFIG_H
00020 #  include <config.h>
00021 #endif
00022 
00023 #include <algorithm>
00024 #include <iostream>
00025 #include <iomanip>
00026 #include <cstring>
00027 #include <cstdlib>
00028 #include <vector>
00029 #include "ucdata.h"
00030 #include "ops.h"
00031 #include "files/utils.h"
00032 
00033 using std::cout;
00034 using std::setw;
00035 using std::endl;
00036 using std::vector;
00037 using std::setbase;
00038 using std::setfill;
00039 using std::string;
00040 using std::ostream;
00041 
00042 UCData::UCData() : _search_opcode(-1), _search_intrinsic(-1)
00043 {
00044 }
00045 
00046 UCData::~UCData()
00047 {
00048   _file.close();
00049   for(unsigned int i=0; i<_funcs.size(); i++)
00050     delete _funcs[i];
00051 }
00052 
00053 void UCData::parse_params(const unsigned int argc, char **argv)
00054 {
00055   /* Parse command line */
00056   for(unsigned int i=1; i<argc; i++)
00057   {
00058     if     (strcmp(argv[i], "-si"   )==0) options._game = UCOptions::GAME_SI;
00059     else if(strcmp(argv[i], "-bg"   )==0) options._game = UCOptions::GAME_BG;
00060     else if(strcmp(argv[i], "-u8"   )==0) options._game = UCOptions::GAME_U8;
00061 
00062     else if(strcmp(argv[i], "-a"    )==0) options.mode_all=true;
00063 
00064     else if(strcmp(argv[i], "-nc"   )==0) options.noconf  = true;
00065     else if(strcmp(argv[i], "-ro"   )==0) options.rawops  = true;
00066     else if(strcmp(argv[i], "-ac"   )==0) options.autocomment = true;
00067     else if(strcmp(argv[i], "-uc"   )==0) options.uselesscomment = true;
00068     else if(strcmp(argv[i], "-v"    )==0) options.verbose = true;
00069     else if(strcmp(argv[i], "-vv"   )==0) { options.verbose = options.very_verbose = true; }
00070     else if(strcmp(argv[i], "-dbg"  )==0) options.ucdebug = true;
00071     else if(strcmp(argv[i], "-ext32")==0) options.force_ext32 = true;
00072     else if(strcmp(argv[i], "-b"    )==0) options.basic = true;
00073 
00074     else if(strcmp(argv[i], "-fl"   )==0) options.output_list = true;
00075     else if(strcmp(argv[i], "-fa"   )==0) options.output_asm  = true;
00076     else if(strcmp(argv[i], "-fz"   )==0) options.output_ucs  = true;
00077     else if(strcmp(argv[i], "-fs"   )==0) options.output_ucs  = true;
00078     else if(strcmp(argv[i], "-ff"   )==0) options.output_flag = true;
00079     else if(strcmp(argv[i], "-ftt"  )==0) options.output_trans_table = true;
00080 
00081     else if(strcmp(argv[i], "--extern-header" )==0) options.output_extern_header = true;
00082     
00083     else if(argv[i][0] != '-')
00084     {
00085       char* stopstr;
00086       /* Disassembly mode */
00087       unsigned int search_func = strtoul(argv[i], &stopstr, 16);
00088       if( stopstr - argv[i] < static_cast<int>(strlen(argv[i])) )
00089         /* Invalid number */
00090       { /* Do Nothing */ }
00091       else
00092       {
00093         search_funcs.push_back(search_func);
00094         if(options.verbose) cout << "Disassembling Function: " << search_func << endl;
00095         options.mode_dis = true;
00096       }
00097     }
00098     else if((string(argv[i]).size()>2) && string(argv[i]).substr(0, 2)=="-o")
00099     {
00100       _output_redirect = string(argv[i]).substr(2, string(argv[i]).size()-2);
00101       if(options.verbose) cout << "Outputting to filename: " << _output_redirect << endl;
00102     }
00103     else if((string(argv[i]).size()>2) && string(argv[i]).substr(0, 2)=="-i")
00104     {
00105       _input_usecode_file = string(argv[i]).substr(2, string(argv[i]).size()-2);
00106       if(options.verbose) cout << "Inputting from file: " << _input_usecode_file << endl;
00107     }
00108     else
00109     {
00110       cout << "unsupported parameter " << argv[i] << " detected. countinuing." << endl;
00111     }
00112   }
00113 }
00114 
00115 void UCData::open_usecode(const string &filename)
00116 {
00117   file_open(filename);
00118   
00119   if(fail())
00120     return;
00121 }
00122 
00123 // FIXME: Pass ostream to this, rather then cout-ing everything
00124 void UCData::disassamble()
00125 {
00126   load_funcs();
00127 
00128   if(options.verbose)
00129   {
00130     for(vector<unsigned int>::iterator i=search_funcs.begin(); i!=search_funcs.end(); i++)
00131       cout << "Looking for function number " << setw(8) << (*i) << endl;
00132     cout << endl;
00133   }
00134   
00135   if(options.output_list)
00136     cout << "Function       offset    size  data  code" << (options.ucdebug ? " funcname" : "") << endl;
00137 
00138   if(options.output_trans_table)
00139     cout << "<trans>" << endl;
00140     
00141   bool _foundfunc=false; //did we find and print the function?
00142   for(unsigned int i=0; i<_funcs.size(); i++)
00143   {
00144     if(options.mode_all || (options.mode_dis && count(search_funcs.begin(), search_funcs.end(), _funcs[i]->_funcid)))
00145     {
00146       _foundfunc=true;
00147       bool _func_printed=false; // to test if we've actually printed a function ouput
00148 
00149       if(options.output_list)
00150         _func_printed = _funcs[i]->output_list(cout, i, options);
00151       
00152       if(options.output_ucs)
00153       {
00154         _funcs[i]->parse_ucs(_funcmap, uc_intrinsics, options);
00155         _func_printed = _funcs[i]->output_ucs(cout, _funcmap, uc_intrinsics, options);
00156         //_func_printed=true;
00157       }
00158 
00159       if(options.output_trans_table)
00160       {
00161         _func_printed=_funcs[i]->output_tt(cout);
00162         //_func_printed=true;
00163       }
00164       
00165       // if we haven't printed one by now, we'll print an asm output.
00166       if(options.output_asm || (_func_printed==false))
00167         _funcs[i]->output_asm(cout, _funcmap, uc_intrinsics, options);
00168     }
00169   }
00170 
00171   if(!_foundfunc)
00172     printf("Function not found.\n");
00173 
00174   if(search_funcs.size()==0)
00175   {
00176     printf("Functions: %d\n", _funcs.size());
00177   }
00178 
00179   if(options.output_list)
00180     cout << endl << "Functions: " << setbase(10) << _funcs.size() << setbase(16) << endl;
00181   
00182   if(options.output_trans_table)
00183     cout << "</>" << endl;
00184     
00185   cout << endl;
00186 }
00187 
00188 /* FIXME: Need to remove the hard coded opcode numbers (0x42 and 0x43) and replace them
00189   with 'variables' in the opcodes.txt file, that signify if it's a pop/push and a flag */
00190 void UCData::dump_flags(ostream &o)
00191 {
00192   if(!(options.game_bg() || options.game_si()))
00193   {
00194     o << "This option only works for U7:BG and U7:SI" << endl;
00195     return;
00196   }
00197   load_funcs();
00198   
00199   if(options.verbose) cout << "Finding flags..." << endl;
00200   vector<FlagData> flags;
00201 
00202   // *BLEH* ugly!
00203   for(vector<UCFunc *>::iterator func=_funcs.begin(); func!=_funcs.end(); func++)
00204     for(vector<UCc>::iterator op=(*func)->_opcodes.begin(); op!=(*func)->_opcodes.end(); op++)
00205     {
00206       if(op->_id==0x42)
00207         flags.push_back(FlagData((*func)->_funcid, op->_offset, op->_params_parsed[0], FlagData::GETFLAG));
00208       else if(op->_id==0x43)
00209         flags.push_back(FlagData((*func)->_funcid, op->_offset, op->_params_parsed[0], FlagData::SETFLAG));
00210     }
00211     
00212   o << "Number of flags found: " << setbase(10) << flags.size() << endl << endl;
00213 
00214   // output per function
00215   {
00216     sort(flags.begin(), flags.end(), SortFlagDataLessFunc());
00217     
00218     o << setbase(16) << setfill('0');
00219     int currfunc = -1;
00220     for(unsigned int i=0; i<flags.size(); i++)
00221     {
00222       if(currfunc!=flags[i].func())
00223       {
00224         o << "Function: " << setw(4) << flags[i].func() << endl;
00225         currfunc=flags[i].func();
00226         o << "              flag  offset" << endl;
00227       }
00228       
00229       o << "        ";
00230       if(flags[i].access()==FlagData::GETFLAG)
00231         o << "push  ";
00232       else if(flags[i].access()==FlagData::SETFLAG)
00233         o << "pop   ";
00234       o << setw(4) << flags[i].flag()   << "  "
00235         << setw(4) << flags[i].offset() << endl;
00236     }
00237   }
00238   
00239   // output per flag
00240   {
00241     sort(flags.begin(), flags.end(), SortFlagDataLessFlag());
00242     
00243     o << setbase(16) << setfill('0');
00244     unsigned int currflag = static_cast<unsigned int>(-1);
00245     for(unsigned int i=0; i<flags.size(); i++)
00246     {
00247       if(currflag!=flags[i].flag())
00248       {
00249         o << "Flag: " << setw(4) << flags[i].flag() << endl;
00250         currflag=flags[i].flag();
00251         o << "              func  offset" << endl;
00252       }
00253     
00254     o << "        ";
00255     if(flags[i].access()==FlagData::GETFLAG)
00256       o << "push  ";
00257     else if(flags[i].access()==FlagData::SETFLAG)
00258       o << "pop   ";
00259     o << setw(4) << flags[i].func()   << "  "
00260       << setw(4) << flags[i].offset() << endl;
00261     }
00262   }
00263 }
00264 
00265 void UCData::file_open(const string &filename)
00266 {
00267   /* Open a usecode file */
00268   U7open(_file, filename.c_str(), false);
00269 }
00270 
00271 #undef LOAD_SPEED_TEST
00272 
00273 #ifdef LOAD_SPEED_TEST
00274 #include "tools/dbgutils.h"
00275 #endif
00276 
00277 void UCData::load_funcs()
00278 {
00279   if(options.verbose) cout << "Loading functions..." << endl;
00280   
00281   #ifdef LOAD_SPEED_TEST
00282   dbg::DateDiff dd;
00283   dbg::timeDateDiff(cout);
00284   dd.start();
00285   #endif
00286   
00287   bool eof=false;
00288   while( !eof )
00289   {
00290     UCFunc *ucfunc = new UCFunc();
00291 
00292     if(options.game_bg() || options.game_si())
00293       readbin_U7UCFunc(_file, *ucfunc, options);
00294     else if(options.game_u8())
00295       readbin_U8UCFunc(_file, *ucfunc);
00296     else
00297       exit(-1); // can't happen
00298     
00299     /* if we're forcing ext32 on output, this is where we do so.
00300       if we try doing it before reading it, it'll get corrupted. */
00301     if(options.force_ext32) ucfunc->ext32=true;
00302     
00303     _funcs.push_back(ucfunc);
00304     {
00305       _file.get();
00306       eof = _file.eof();
00307       _file.unget();
00308     }
00309   }
00310   
00311   #ifdef LOAD_SPEED_TEST
00312   dd.end();
00313   cout << setbase(10) << setfill(' ');
00314   dd.print_start(cout) << endl;
00315   dd.print_end(cout) << endl;
00316   dd.print_diff(cout) << endl;
00317   cout << setbase(16) << setfill('0');
00318   #endif
00319   
00320   if(options.verbose) cout << "Creating function map..." << endl;
00321   
00322   for(vector<UCFunc *>::iterator i=_funcs.begin(); i!=_funcs.end(); i++)
00323   {
00324     _funcmap.insert(FuncMapPair((*i)->_funcid, UCFuncSet((*i)->_funcid, (*i)->_num_args, (*i)->return_var, (*i)->funcname)));
00325   }
00326 /*  for(map<unsigned int, UCFuncSet>::iterator i=_funcmap.begin(); i!=_funcmap.end(); i++)
00327     cout << i->first << "\t" << i->second.num_args << endl;*/
00328 }
00329 
00330 void UCData::output_extern_header(ostream &o)
00331 {
00332   if(!(options.game_bg() || options.game_si()))
00333   {
00334     o << "This option only works for U7:BG and U7:SI" << endl;
00335     return;
00336   }
00337   load_funcs();
00338 
00339   for(vector<UCFunc *>::iterator func=_funcs.begin(); func!=_funcs.end(); func++)
00340   {
00341     //(*func)->output_ucs_funcname(o << "extern ", _funcmap, (*func)->_funcid, (*func)->_num_args, (*func)->return_var) << ';' << endl;
00342     (*func)->output_ucs_funcname(o << "extern ", _funcmap) << ';' << endl;
00343   }
00344 }
00345 
00346 

Generated on Mon Jul 9 14:42:52 2007 for ExultEngine by  doxygen 1.5.1