00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifdef HAVE_CONFIG_H
00036 # include <config.h>
00037 #endif
00038
00039 #include <cstdio>
00040 #include <cstdlib>
00041 #include <cstring>
00042 #include <string>
00043 #include <iomanip>
00044 #include <vector>
00045 #include <stack>
00046 #include <map>
00047
00048 #include "ucc.h"
00049 #include "ops.h"
00050 #include "ucdata.h"
00051 #include "ucfunc.h"
00052 #include "files/utils.h"
00053
00054
00055 #include "Configuration.h"
00056 #include "exult_constants.h"
00057 const std::string c_empty_string;
00058
00059
00060 void usage();
00061 void open_usecode_file(UCData &uc, const Configuration &config);
00062
00063 UCData uc;
00064
00065 using std::setw;
00066 using std::cerr;
00067 using std::cout;
00068 using std::ios;
00069 using std::string;
00070 using std::endl;
00071
00072 int main(int argc, char** argv)
00073 {
00074
00075 cout << std::setfill('0') << std::setbase(16);
00076 cout.setf(ios::uppercase);
00077
00078
00079 uc.parse_params(argc, argv);
00080 if(uc.options.verbose) cout << "Parameters parsed..." << endl;
00081
00082 Configuration config;
00083
00084
00085 if(uc.options.noconf == false)
00086 {
00087 if(uc.options.verbose) cout << "Loading exult configuration file..." << endl;
00088 if(config.read_config_file("exult.cfg") == false)
00089 {
00090 cout << "Failed to locate exult.cfg. Run exult before running ucxt or use the -nc switch. Exiting." << endl;
00091 exit(1);
00092 }
00093 }
00094
00095
00096 if(uc.options.verbose) cout << "Initing runtime tables..." << endl;
00097
00098 ucxtInit init;
00099 init.init(config, uc.options);
00100
00101 #if 0
00102 {
00103 cout << "<opcodes>" << endl;
00104
00105 for(typeof(opcode_table_data.begin()) i=opcode_table_data.begin(); i!=opcode_table_data.end(); i++)
00106 {
00107 if(i->opcode!=0 && i->name!="NULL")
00108 {
00109 cout << "\t<0x" << setw(2) << i->opcode << '>' << endl;
00110
00111 cout << "\t\t<name> " << i->name << " </>" << endl;
00112 cout << "\t\t<asm_nmo> `" << i->asm_nmo << "` </>" << endl;
00113 cout << "\t\t<asm_comment> `" << i->asm_comment << "` </>" << endl;
00114 cout << "\t\t<ucs_nmo> `" << i->ucs_nmo << "` </>" << endl;
00115 cout << "\t\t<num_bytes> " << i->num_bytes << " </>" << endl;
00116
00117 cout << "\t\t<param_types> {";
00118 for(typeof(i->param_types.begin()) j=i->param_types.begin(); j!=i->param_types.end(); j++)
00119 cout << *j << ',';
00120 cout << "} </>" << endl;
00121
00122 cout << "\t\t<num_pop> " << i->num_pop << " </>" << endl;
00123 cout << "\t\t<num_push> " << i->num_push << " </>" << endl;
00124 cout << "\t\t<call_effect> " << i->call_effect << " </>" << endl;
00125 if(i->flag_return) cout << "\t\t<return/>" << endl;
00126 if(i->flag_paren) cout << "\t\t<paren/>" << endl;
00127 if(i->flag_indent_inc) cout << "\t\t<indent_inc/>" << endl;
00128 if(i->flag_indent_dec) cout << "\t\t<indent_dec/>" << endl;
00129 if(i->flag_indent_tmpinc) cout << "\t\t<indent_tmpinc/>" << endl;
00130 if(i->flag_indent_tmpdec) cout << "\t\t<indent_tmpdec/>" << endl;
00131
00132 cout << "\t</>" << endl;
00133 }
00134 }
00135 cout << "</>" << endl;
00136 }
00137 #endif
00138
00139
00140
00141
00142
00143 std::ofstream outputstream;
00144 std::streambuf *coutbuf=0;
00145 if(uc.output_redirect().size())
00146 {
00147 U7open(outputstream, uc.output_redirect().c_str(), false);
00148 if(outputstream.fail())
00149 {
00150 cout << "error. failed to open " << uc.output_redirect() << " for writing. exiting." << endl;
00151 exit(1);
00152 }
00153 coutbuf = cout.rdbuf();
00154 cout.rdbuf(outputstream.rdbuf());
00155 }
00156
00157
00158 open_usecode_file(uc, config);
00159
00160 if(uc.opt().output_extern_header)
00161 {
00162 uc.output_extern_header(cout);
00163 }
00164 else if ( uc.options.mode_dis || uc.options.mode_all )
00165 {
00166 uc.disassamble();
00167 }
00168 else if( uc.options.output_flag )
00169 {
00170 uc.dump_flags(cout);
00171 }
00172 else
00173 usage();
00174
00175
00176 if(uc.output_redirect().size())
00177 {
00178 cout.rdbuf(coutbuf);
00179 }
00180
00181 return 0;
00182 }
00183
00184 void open_usecode_file(UCData &uc, const Configuration &config)
00185 {
00186 string bgpath;
00187 if(uc.options.noconf == false) config.value("config/disk/game/blackgate/path", bgpath);
00188 string sipath;
00189 if(uc.options.noconf == false) config.value("config/disk/game/serpentisle/path", sipath);
00190 string u8path;
00191 if(uc.options.noconf == false) config.value("config/disk/game/pagan/path", u8path);
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 string mucc_sl("static");
00221 string mucc_sc("STATIC");
00222 string mucc_ul("usecode");
00223 string mucc_uc("USECODE");
00224
00225 const string mucc_bgl("ultima7");
00226 const string mucc_bgc("ULTIMA7");
00227 const string mucc_sil("serpent");
00228 const string mucc_sic("SERPENT");
00229 const string mucc_u8l("pagan");
00230 const string mucc_u8c("PAGAN");
00231
00232 string path, ucspecial, mucc_l, mucc_c;
00233 if(uc.options.game_bg())
00234 {
00235 if(uc.options.verbose) cout << "Configuring for bg." << endl;
00236 path = bgpath;
00237 ucspecial = "usecode.bg";
00238 mucc_l = mucc_bgl;
00239 mucc_c = mucc_bgc;
00240 }
00241 else if(uc.options.game_si())
00242 {
00243 if(uc.options.verbose) cout << "Configuring for si." << endl;
00244 path = sipath;
00245 ucspecial = "usecode.si";
00246 mucc_l = mucc_sil;
00247 mucc_c = mucc_sic;
00248 }
00249 else if(uc.options.game_u8())
00250 {
00251 if(uc.options.verbose) cout << "Configuring for u8." << endl;
00252 path = u8path;
00253 ucspecial = "usecode.u8";
00254 mucc_l = mucc_u8l;
00255 mucc_c = mucc_u8c;
00256 mucc_sl = "usecode";
00257 mucc_sc = "USECODE";
00258 mucc_ul = "eusecode.flx";
00259 mucc_uc = "EUSECODE.FLX";
00260 }
00261 else
00262 {
00263 cerr << "Error: uc.game() was not set to GAME_U7 or GAME_SI or GAME_U8 this can't happen" << endl;
00264 assert(false); exit(1);
00265 }
00266
00267
00268
00269 const string mucc_ll(string("/") + mucc_sl + "/" + mucc_ul);
00270 const string mucc_cl(string("/") + mucc_sc + "/" + mucc_ul);
00271 const string mucc_lc(string("/") + mucc_sl + "/" + mucc_uc);
00272 const string mucc_cc(string("/") + mucc_sc + "/" + mucc_uc);
00273
00274
00275 if(uc.input_usecode_file().size())
00276 uc.open_usecode(uc.input_usecode_file());
00277 else if(uc.options.noconf==false)
00278 {
00279 uc.open_usecode(path + mucc_ll);
00280 if(uc.fail())
00281 uc.open_usecode(path + mucc_cl);
00282 if(uc.fail())
00283 uc.open_usecode(path + mucc_lc);
00284 if(uc.fail())
00285 uc.open_usecode(path + mucc_cc);
00286 if(uc.fail())
00287 uc.open_usecode(mucc_l + mucc_ll);
00288 }
00289 else
00290 uc.open_usecode(mucc_l + mucc_ll);
00291
00292 if(uc.fail())
00293 uc.open_usecode(mucc_l + mucc_cl);
00294 if(uc.fail())
00295 uc.open_usecode(mucc_l + mucc_lc);
00296 if(uc.fail())
00297 uc.open_usecode(mucc_l + mucc_cc);
00298 if(uc.fail())
00299 uc.open_usecode(mucc_c + mucc_ll);
00300 if(uc.fail())
00301 uc.open_usecode(mucc_c + mucc_cl);
00302 if(uc.fail())
00303 uc.open_usecode(mucc_c + mucc_lc);
00304 if(uc.fail())
00305 uc.open_usecode(mucc_c + mucc_cc);
00306 if(uc.fail())
00307 uc.open_usecode(mucc_ll);
00308 if(uc.fail())
00309 uc.open_usecode(mucc_cl);
00310 if(uc.fail())
00311 uc.open_usecode(mucc_lc);
00312 if(uc.fail())
00313 uc.open_usecode(mucc_cc);
00314 if(uc.fail())
00315 uc.open_usecode(ucspecial);
00316 if(uc.fail())
00317 uc.open_usecode(mucc_uc);
00318 if(uc.fail())
00319 uc.open_usecode(mucc_ul);
00320
00321
00322 if(uc.fail())
00323 {
00324 cout << "Failed to locate usecode file. Exiting." << endl;
00325 exit(1);
00326 }
00327 }
00328
00329 void usage()
00330 {
00331 cout << "Ultima 7/8 usecode disassembler v0.6.3" << endl
00332 #ifdef HAVE_CONFIG_H
00333 << " compiled with " << PACKAGE << " " << VERSION << endl
00334 #endif
00335 << endl;
00336
00337 cout << "Usage:" << endl
00338 << "\tucxt [options] -a" << endl
00339 << "\t\t- prints all of the functions" << endl
00340 << "\tucxt [options] <hex function number>" << endl
00341 << "\t\t- disassembles single function to stdout" << endl
00342
00343
00344
00345
00346
00347
00348 << endl
00349 << "\tMisc Flags (any/all of these):" << endl
00350 << "\t\t-nc\t- don't look for exult's .xml config file" << endl
00351 << "\t\t-v \t- turns on verbose output mode" << endl
00352 << "\t\t-ofile\t- output to the specified file" << endl
00353 << "\t\t-ifile\t- load the usecode file specified by the filename" << endl
00354 << "\t\t-ro\t- output the raw opcodes in addition to the -f format" << endl
00355 << "\t\t-ac\t- output automatically generated comments" << endl
00356 << "\t\t-uc\t- output automatically generated 'useless' comments" << endl
00357 << "\t\t-b\t- only do 'basic' optimisations" << endl
00358 << "\t\t-dbg\t- output debugging information if present in USECODE." << endl
00359 << "\t\t-ext32\t- 'convert' function to ext32 format if not already." << endl
00360 << "\tGame Specifier Flags (only one of these):" << endl
00361 << "\t\t-bg\t- select the black gate usecode file" << endl
00362 << "\t\t-si\t- select the serpent isle usecode file" << endl
00363 << "\t\t-u8\t- select the ultima 8/pagan usecode file (experimental)" << endl
00364 << "\tOutput Format Flags (only one of these):" << endl
00365 << "\t\t-fl\t- output using brief \"list\" format" << endl
00366 << "\t\t-fa\t- output using \"assembler\" format (default)" << endl
00367 << "\t\t-fs\t- output using \"exult script\" format" << endl
00368 << "\t\t-fz\t- output using \"exult script\" format" << endl
00369 << "\t\t-ftt\t- output using the translation table xml format" << endl
00370 << "\t\t-ff\t- outputs all flags referenced in the usecode file" << endl
00371 << "\t\t\t sorted both by \"flags within a function\" and" << endl
00372 << "\t\t\t \"functions using flag\"" << endl
00373 ;
00374 exit(1);
00375 }
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401