00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
00087 unsigned int search_func = strtoul(argv[i], &stopstr, 16);
00088 if( stopstr - argv[i] < static_cast<int>(strlen(argv[i])) )
00089
00090 { }
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
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;
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;
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
00157 }
00158
00159 if(options.output_trans_table)
00160 {
00161 _func_printed=_funcs[i]->output_tt(cout);
00162
00163 }
00164
00165
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
00189
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
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
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
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
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);
00298
00299
00300
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
00327
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
00342 (*func)->output_ucs_funcname(o << "extern ", _funcmap) << ';' << endl;
00343 }
00344 }
00345
00346