ucdata.cc
来自「一个制作3d游戏的源程序」· CC 代码 · 共 347 行
CC
347 行
/* * 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 <config.h>#endif#include <algorithm>#include <iostream>#include <iomanip>#include <cstring>#include <cstdlib>#include <vector>#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<argc; i++) { if (strcmp(argv[i], "-si" )==0) options._game = UCOptions::GAME_SI; else if(strcmp(argv[i], "-bg" )==0) options._game = UCOptions::GAME_BG; else if(strcmp(argv[i], "-u8" )==0) options._game = UCOptions::GAME_U8; else if(strcmp(argv[i], "-a" )==0) options.mode_all=true; else if(strcmp(argv[i], "-nc" )==0) options.noconf = true; else if(strcmp(argv[i], "-ro" )==0) options.rawops = true; else if(strcmp(argv[i], "-ac" )==0) options.autocomment = true; else if(strcmp(argv[i], "-uc" )==0) options.uselesscomment = true; else if(strcmp(argv[i], "-v" )==0) options.verbose = true; else if(strcmp(argv[i], "-vv" )==0) { options.verbose = options.very_verbose = true; } else if(strcmp(argv[i], "-dbg" )==0) options.ucdebug = true; else if(strcmp(argv[i], "-ext32")==0) options.force_ext32 = true; else if(strcmp(argv[i], "-b" )==0) options.basic = true; else if(strcmp(argv[i], "-fl" )==0) options.output_list = true; else if(strcmp(argv[i], "-fa" )==0) options.output_asm = true; else if(strcmp(argv[i], "-fz" )==0) options.output_ucs = true; else if(strcmp(argv[i], "-fs" )==0) options.output_ucs = true; else if(strcmp(argv[i], "-ff" )==0) options.output_flag = true; else if(strcmp(argv[i], "-ftt" )==0) options.output_trans_table = true; else if(strcmp(argv[i], "--extern-header" )==0) options.output_extern_header = true; else if(argv[i][0] != '-') { char* stopstr; /* Disassembly mode */ unsigned int search_func = strtoul(argv[i], &stopstr, 16); if( stopstr - argv[i] < static_cast<int>(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 everythingvoid UCData::disassamble(){ load_funcs(); if(options.verbose) { for(vector<unsigned int>::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 << "<trans>" << 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<FlagData> flags; // *BLEH* ugly! for(vector<UCFunc *>::iterator func=_funcs.begin(); func!=_funcs.end(); func++) for(vector<UCc>::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<flags.size(); i++) { if(currfunc!=flags[i].func()) { o << "Function: " << setw(4) << flags[i].func() << endl; currfunc=flags[i].func(); o << " flag offset" << endl; } o << " "; if(flags[i].access()==FlagData::GETFLAG) o << "push "; else if(flags[i].access()==FlagData::SETFLAG) o << "pop "; o << setw(4) << flags[i].flag() << " " << setw(4) << flags[i].offset() << endl; } } // output per flag { sort(flags.begin(), flags.end(), SortFlagDataLessFlag()); o << setbase(16) << setfill('0'); unsigned int currflag = static_cast<unsigned int>(-1); for(unsigned int i=0; i<flags.size(); i++) { if(currflag!=flags[i].flag()) { o << "Flag: " << setw(4) << flags[i].flag() << endl; currflag=flags[i].flag(); o << " func offset" << endl; } o << " "; if(flags[i].access()==FlagData::GETFLAG) o << "push "; else if(flags[i].access()==FlagData::SETFLAG) o << "pop "; o << setw(4) << flags[i].func() << " " << setw(4) << flags[i].offset() << endl; } }}void UCData::file_open(const string &filename){ /* Open a usecode file */ U7open(_file, filename.c_str(), false);}#undef LOAD_SPEED_TEST#ifdef LOAD_SPEED_TEST#include "tools/dbgutils.h"#endifvoid UCData::load_funcs(){ if(options.verbose) cout << "Loading functions..." << endl; #ifdef LOAD_SPEED_TEST dbg::DateDiff dd; dbg::timeDateDiff(cout); dd.start(); #endif bool eof=false; while( !eof ) { UCFunc *ucfunc = new UCFunc(); if(options.game_bg() || options.game_si()) readbin_U7UCFunc(_file, *ucfunc, options); else if(options.game_u8()) readbin_U8UCFunc(_file, *ucfunc); else exit(-1); // can't happen /* if we're forcing ext32 on output, this is where we do so. if we try doing it before reading it, it'll get corrupted. */ if(options.force_ext32) ucfunc->ext32=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<UCFunc *>::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<unsigned int, UCFuncSet>::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<UCFunc *>::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; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?