/* * Copyright (C) 2001-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include "ucdata.h" #include "ops.h" #include "files/utils.h" using std::cout; using std::setw; using std::endl; using std::vector; using std::setbase; using std::setfill; using std::string; using std::ostream; UCData::UCData() : _search_opcode(-1), _search_intrinsic(-1) { } UCData::~UCData() { _file.close(); for(unsigned int i=0; i<_funcs.size(); i++) delete _funcs[i]; } void UCData::parse_params(const unsigned int argc, char **argv) { /* Parse command line */ for(unsigned int i=1; i(strlen(argv[i])) ) /* Invalid number */ { /* Do Nothing */ } else { search_funcs.push_back(search_func); if(options.verbose) cout << "Disassembling Function: " << search_func << endl; options.mode_dis = true; } } else if((string(argv[i]).size()>2) && string(argv[i]).substr(0, 2)=="-o") { _output_redirect = string(argv[i]).substr(2, string(argv[i]).size()-2); if(options.verbose) cout << "Outputting to filename: " << _output_redirect << endl; } else if((string(argv[i]).size()>2) && string(argv[i]).substr(0, 2)=="-i") { _input_usecode_file = string(argv[i]).substr(2, string(argv[i]).size()-2); if(options.verbose) cout << "Inputting from file: " << _input_usecode_file << endl; } else { cout << "unsupported parameter " << argv[i] << " detected. countinuing." << endl; } } } void UCData::open_usecode(const string &filename) { file_open(filename); if(fail()) return; } // FIXME: Pass ostream to this, rather then cout-ing everything void UCData::disassamble() { load_funcs(); if(options.verbose) { for(vector::iterator i=search_funcs.begin(); i!=search_funcs.end(); i++) cout << "Looking for function number " << setw(8) << (*i) << endl; cout << endl; } if(options.output_list) cout << "Function offset size data code" << (options.ucdebug ? " funcname" : "") << endl; if(options.output_trans_table) cout << "" << endl; bool _foundfunc=false; //did we find and print the function? for(unsigned int i=0; i<_funcs.size(); i++) { if(options.mode_all || (options.mode_dis && count(search_funcs.begin(), search_funcs.end(), _funcs[i]->_funcid))) { _foundfunc=true; bool _func_printed=false; // to test if we've actually printed a function ouput if(options.output_list) _func_printed = _funcs[i]->output_list(cout, i, options); if(options.output_ucs) { _funcs[i]->parse_ucs(_funcmap, uc_intrinsics, options); _func_printed = _funcs[i]->output_ucs(cout, _funcmap, uc_intrinsics, options); //_func_printed=true; } if(options.output_trans_table) { _func_printed=_funcs[i]->output_tt(cout); //_func_printed=true; } // if we haven't printed one by now, we'll print an asm output. if(options.output_asm || (_func_printed==false)) _funcs[i]->output_asm(cout, _funcmap, uc_intrinsics, options); } } if(!_foundfunc) printf("Function not found.\n"); if(search_funcs.size()==0) { printf("Functions: %d\n", _funcs.size()); } if(options.output_list) cout << endl << "Functions: " << setbase(10) << _funcs.size() << setbase(16) << endl; if(options.output_trans_table) cout << "" << endl; cout << endl; } /* FIXME: Need to remove the hard coded opcode numbers (0x42 and 0x43) and replace them with 'variables' in the opcodes.txt file, that signify if it's a pop/push and a flag */ void UCData::dump_flags(ostream &o) { if(!(options.game_bg() || options.game_si())) { o << "This option only works for U7:BG and U7:SI" << endl; return; } load_funcs(); if(options.verbose) cout << "Finding flags..." << endl; vector flags; // *BLEH* ugly! for(vector::iterator func=_funcs.begin(); func!=_funcs.end(); func++) for(vector::iterator op=(*func)->_opcodes.begin(); op!=(*func)->_opcodes.end(); op++) { if(op->_id==0x42) flags.push_back(FlagData((*func)->_funcid, op->_offset, op->_params_parsed[0], FlagData::GETFLAG)); else if(op->_id==0x43) flags.push_back(FlagData((*func)->_funcid, op->_offset, op->_params_parsed[0], FlagData::SETFLAG)); } o << "Number of flags found: " << setbase(10) << flags.size() << endl << endl; // output per function { sort(flags.begin(), flags.end(), SortFlagDataLessFunc()); o << setbase(16) << setfill('0'); int currfunc = -1; for(unsigned int i=0; i(-1); for(unsigned int i=0; iext32=true; _funcs.push_back(ucfunc); { _file.get(); eof = _file.eof(); _file.unget(); } } #ifdef LOAD_SPEED_TEST dd.end(); cout << setbase(10) << setfill(' '); dd.print_start(cout) << endl; dd.print_end(cout) << endl; dd.print_diff(cout) << endl; cout << setbase(16) << setfill('0'); #endif if(options.verbose) cout << "Creating function map..." << endl; for(vector::iterator i=_funcs.begin(); i!=_funcs.end(); i++) { _funcmap.insert(FuncMapPair((*i)->_funcid, UCFuncSet((*i)->_funcid, (*i)->_num_args, (*i)->return_var, (*i)->funcname))); } /* for(map::iterator i=_funcmap.begin(); i!=_funcmap.end(); i++) cout << i->first << "\t" << i->second.num_args << endl;*/ } void UCData::output_extern_header(ostream &o) { if(!(options.game_bg() || options.game_si())) { o << "This option only works for U7:BG and U7:SI" << endl; return; } load_funcs(); for(vector::iterator func=_funcs.begin(); func!=_funcs.end(); func++) { //(*func)->output_ucs_funcname(o << "extern ", _funcmap, (*func)->_funcid, (*func)->_num_args, (*func)->return_var) << ';' << endl; (*func)->output_ucs_funcname(o << "extern ", _funcmap) << ';' << endl; } }