00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "pent_include.h"
00022
00023 #include <fstream>
00024 #include <cstdio>
00025
00026 #include <map>
00027 using std::map;
00028
00029 #include <string>
00030 using std::string;
00031
00032 #include <algorithm>
00033 #include <cctype>
00034
00035 #include "Args.h"
00036 #if 0 // FIXME: Add conf/
00037 #include "Configuration.h"
00038 #endif
00039 #include "common_types.h"
00040
00041 #include "IDataSource.h"
00042 #include "FileSystem.h"
00043 #include "util.h"
00044
00045
00046
00047
00048 #ifdef DISASM_DEBUG
00049 #include <iomanip>
00050 #endif
00051
00052
00053
00054 class TempOp
00055 {
00056 public:
00057 TempOp(const uint32 offset_=0, const sint32 opcode_=0,
00058 const uint32 nextoffset_=0,
00059 const sint32 i0_=0, const sint32 i1_=0, const sint32 i2_=0,
00060 const sint32 i3_=0, const sint32 i4_=0, const string &str_=string())
00061 : offset(offset_), nextoffset(nextoffset_), i0(i0_), i1(i1_), i2(i2_),
00062 i3(i3_), i4(i4_), str(str_),
00063 sp_size(0), ret_size(0), opcode(opcode_) {};
00064
00065 ~TempOp() {};
00066
00067 void op(const uint32 opcode_) { opcode = opcode_; };
00068 uint32 op() const { return opcode; };
00069
00070 uint32 offset;
00071 uint32 nextoffset;
00072 sint32 i0, i1, i2, i3, i4;
00073 string str;
00074
00075
00076 uint32 sp_size;
00077 uint32 ret_size;
00078
00079 protected:
00080 uint32 opcode;
00081 };
00082
00083
00084
00085
00086 uint32 curOffset;
00087
00088 inline uint32 read1(IDataSource *ucfile) { curOffset+=1; return ucfile->read1(); };
00089 inline uint32 read2(IDataSource *ucfile) { curOffset+=2; return ucfile->read2(); };
00090 inline uint32 read4(IDataSource *ucfile) { curOffset+=4; return ucfile->read4(); };
00091
00092 inline std::string readstr(IDataSource *ucfile)
00093 {
00094 string s;
00095 while(char c = static_cast<char>(read1(ucfile)))
00096 s += c;
00097
00098
00099
00100 return s;
00101 }
00102
00103 inline std::string readnstr(IDataSource *ucfile, uint32 n)
00104 {
00105 string s;
00106 while(n-->0)
00107 s += static_cast<char>(read1(ucfile));
00108
00109
00110
00111 return s;
00112 }
00113
00114 std::map<sint32, string> ScriptExpressions;
00115
00116 map<uint32, uint32> EventMap;
00117
00118 class UsecodeHeader
00119 {
00120 public:
00121 UsecodeHeader()
00122 : routines(0), maxOffset(0), offset(0), externTable(0), fixupTable(0) {};
00123
00124 uint32 routines;
00125 uint32 maxOffset;
00126 uint32 offset;
00127 uint32 externTable;
00128 uint32 fixupTable;
00129 };
00130
00131 const char * const print_bp(const sint32 offset)
00132 {
00133 static char str[32];
00134 snprintf(str, 32, "[BP%c%02Xh]", offset>0x7F?'-':'+', offset>0x7F?0x100-offset:offset);
00135 return str;
00136 }
00137
00138 const char * const print_sp(const sint32 offset)
00139 {
00140 static char str[32];
00141 snprintf(str, 32, "[SP%c%02Xh]", offset>0x7F?'-':'+', offset>0x7F?0x100-offset:offset);
00142 return str;
00143 }
00144
00145 #include "u8/ConvertUsecodeU8.h"
00146 #include "crusader/ConvertUsecodeCrusader.h"
00147
00148 using std::endl;
00149 using std::pair;
00150
00151 #ifndef HAVE_SNPRINTF
00152 extern sint32 snprintf(char *, size_t, const char *, ...);
00153 namespace std {
00154 using ::snprintf;
00155 }
00156 #endif
00157
00158
00159
00160
00161 ConvertUsecode *convert = new ConvertUsecodeU8();
00162
00163
00164
00165 void printoverloads(IDataSource *ucfile, uint32 endpos);
00166
00167
00168 class GlobalName
00169 {
00170 public:
00171 GlobalName(const uint32 _offset=0, const uint32 _size=0,
00172 const string _name=string())
00173 : offset(_offset), size(_size), name(_name) {};
00174
00175 uint32 offset;
00176 uint32 size;
00177 string name;
00178 };
00179
00180
00181 map<uint32, GlobalName> GlobalNames;
00182
00183 map<string, string> FuncNames;
00184
00185 string gamelanguage;
00186 string gametype;
00187 string outputdir;
00188 bool print_globals=false;
00189 bool strings_only=false;
00190
00191 bool crusader=false;
00192
00193 void readglobals(IDataSource *ucfile)
00194 {
00195 char buf[60];
00196 char c;
00197 ucfile->seek(0x80);
00198 sint32 offset = read4(ucfile);
00199 sint32 length = read4(ucfile);
00200
00201 sint32 curoff = 0;
00202
00203 ucfile->seek(offset);
00204 while (curoff < length-1) {
00205 sint32 i = 0;
00206 do {
00207 c = read1(ucfile);
00208 ++curoff;
00209 buf[i++] = c;
00210 } while (c != 0);
00211 uint32 i0 = read1(ucfile);
00212 uint32 i1 = read1(ucfile);
00213 uint32 i2 = read1(ucfile);
00214 read1(ucfile);
00215 curoff+=4;
00216
00217 uint32 flag = i0 + (i1<<8);
00218 GlobalNames[flag] = GlobalName(flag, i2, buf);
00219 }
00220 }
00221
00222 void printglobals()
00223 {
00224 for(std::map<uint32, GlobalName>::iterator i=GlobalNames.begin(); i!=GlobalNames.end(); ++i)
00225 con.Printf("[%04X %02X] (%s)\n", i->first, i->second.size, i->second.name.c_str());
00226 }
00227
00228
00229 #ifdef FOLD
00230 #define con_Printf if(print_disasm && !strings_only) con.Printf
00231 #define con_Printf_s if(print_disasm && strings_only) con.Printf("\n"); if(print_disasm) con.Printf
00232
00233 #else
00234 #define con_Printf if (!strings_only) con.Printf
00235 #define con_Printf_s if (strings_only) con.Printf("\n"); con.Printf
00236 #endif
00237
00238
00239
00240
00241 #ifdef FOLD
00242 #include "Folder.h"
00243 Folder *folder = new Folder();
00244 #endif
00245
00246 void just_print(TempOp &op, IDataSource *ucfile);
00247 bool readfunction(IDataSource *ucfile, const char *name, const UsecodeHeader &uch, const uint32 func)
00248 {
00249 std::string str;
00250
00251 if (curOffset >= uch.maxOffset) return false;
00252
00253 con_Printf("Func_%X", curOffset);
00254
00255 std::map<uint32, uint32>::iterator it = EventMap.find(curOffset);
00256 if (it != EventMap.end())
00257 {
00258 if (it->second < 0x20)
00259 con_Printf(" (Event %X) %s::%s", it->second, name, convert->event_names()[it->second]);
00260 else
00261 con_Printf(" (Event %X) %s::ordinal%02X", it->second, name, it->second);
00262 }
00263 else
00264 con_Printf(" %s::%04X", name, curOffset);
00265
00266 con_Printf(":\n");
00267
00268 std::vector<DebugSymbol> debugSymbols;
00269 uint32 dbg_symbol_offset=0;
00270 bool done = false;
00271
00272 #ifdef FOLD
00273 folder->SelectUnit(func);
00274 #endif
00275
00276 while (!done)
00277 {
00278
00279 if(ucfile->getPos()>=ucfile->getSize())
00280 return false;
00281
00282 TempOp op;
00283 #ifdef FOLD
00284
00285 folder->fold(convert->readOp(ucfile, dbg_symbol_offset, debugSymbols, done));
00286 #else
00287 convert->readOp(op, ucfile, dbg_symbol_offset, debugSymbols, done);
00288 #endif
00289 just_print(op, ucfile);
00290
00291 }
00292
00293 return true;
00294 }
00295
00296 void just_print(TempOp &op, IDataSource *ucfile)
00297 {
00298
00299 con_Printf(" %04X:", op.offset);
00300
00301 con_Printf(" %02X\t", op.op());
00302
00303 switch(op.op()) {
00304
00305
00306 case 0x00:
00307 con_Printf("pop byte\t%s", print_bp(op.i0));
00308 break;
00309 case 0x01:
00310 con_Printf("pop\t\t%s", print_bp(op.i0));
00311 break;
00312 case 0x02:
00313 con_Printf("pop dword\t%s", print_bp(op.i0));
00314 break;
00315 case 0x03:
00316 con_Printf("pop huge\t%s %i", print_bp(op.i0), op.i1);
00317 break;
00318
00319 case 0x08:
00320 con_Printf("pop res");
00321 break;
00322 case 0x09:
00323 con_Printf("pop element\t%s (%02X) slist==%02X", print_bp(op.i0), op.i1, op.i2);
00324 break;
00325
00326
00327 case 0x0A:
00328 con_Printf("push byte\t%02Xh", op.i0);
00329 break;
00330 case 0x0B:
00331 con_Printf("push\t\t%04Xh", op.i0);
00332 break;
00333 case 0x0C:
00334 con_Printf("push dword\t%08Xh", op.i0);
00335 break;
00336 case 0x0D:
00337
00338 if (strings_only)
00339 {
00340 con_Printf_s("%s\n\n",op.str.c_str());
00341 }
00342 else
00343 {
00344 con_Printf("push string\t\"%s\"", op.str.c_str());
00345 }
00346 break;
00347 case 0x0E:
00348 con_Printf("create list\t%02X (%02X)", op.i1, op.i0);
00349 break;
00350
00351
00352 case 0x0F:
00353 con_Printf("calli\t\t%02Xh %04Xh (%s)", op.i0, op.i1, convert->intrinsics()[op.i1]);
00354 break;
00355 case 0x11:
00356 con_Printf("call\t\t%04X:%04X (%s)", op.i0, op.i1,
00357 convert->UsecodeFunctionAddressToString(op.i0, op.i1, ucfile, crusader).c_str());
00358 break;
00359 case 0x12:
00360 con_Printf("pop\t\ttemp");
00361 break;
00362
00363 case 0x14:
00364 con_Printf("add");
00365 break;
00366 case 0x15:
00367 con_Printf("add dword");
00368 break;
00369 case 0x16:
00370 con_Printf("concat");
00371 break;
00372 case 0x17:
00373 con_Printf("append");
00374 break;
00375 case 0x19:
00376 con_Printf("append slist\t(%02X)", op.i0);
00377 break;
00378 case 0x1A:
00379 con_Printf("remove slist\t(%02X)", op.i0);
00380 break;
00381 case 0x1B:
00382 con_Printf("remove list\t(%02X)", op.i0);
00383 break;
00384 case 0x1C:
00385 con_Printf("sub");
00386 break;
00387 case 0x1D:
00388 con_Printf("sub dword");
00389 break;
00390 case 0x1E:
00391 con_Printf("mul");
00392 break;
00393 case 0x1F:
00394 con_Printf("mul dword");
00395 break;
00396 case 0x20:
00397 con_Printf("div");
00398 break;
00399 case 0x21:
00400 con_Printf("div dword");
00401 break;
00402 case 0x22:
00403 con_Printf("mod");
00404 break;
00405 case 0x23:
00406 con_Printf("mod dword");
00407 assert(false);
00408 break;
00409 case 0x24:
00410 con_Printf("cmp");
00411 break;
00412 case 0x25:
00413 con_Printf("cmp dword");
00414 assert(false);
00415 break;
00416 case 0x26:
00417 con_Printf("strcmp");
00418 break;
00419 case 0x28:
00420 con_Printf("lt");
00421 break;
00422 case 0x29:
00423 con_Printf("lt dword");
00424 break;
00425 case 0x2A:
00426 con_Printf("le");
00427 break;
00428 case 0x2B:
00429 con_Printf("le dword");
00430 break;
00431 case 0x2C:
00432 con_Printf("gt");
00433 break;
00434 case 0x2D:
00435 con_Printf("gt dword");
00436 break;
00437 case 0x2E:
00438 con_Printf("ge");
00439 break;
00440 case 0x2F:
00441 con_Printf("ge dword");
00442 break;
00443 case 0x30:
00444 con_Printf("not");
00445 break;
00446 case 0x31:
00447 con_Printf("not dword");
00448 break;
00449 case 0x32:
00450 con_Printf("and");
00451 break;
00452 case 0x33:
00453 con_Printf("and dword");
00454 break;
00455 case 0x34:
00456 con_Printf("or");
00457 break;
00458 case 0x35:
00459 con_Printf("or dword");
00460 break;
00461 case 0x36:
00462 con_Printf("ne");
00463 break;
00464 case 0x37:
00465 con_Printf("ne dword");
00466 break;
00467
00468 case 0x38:
00469 con_Printf("in list\t\t%02X slist==%02X", op.i0, op.i1);
00470 break;
00471
00472 case 0x39:
00473 con_Printf("bit_and");
00474 break;
00475 case 0x3A:
00476 con_Printf("bit_or");
00477 break;
00478 case 0x3B:
00479 con_Printf("bit_not");
00480 break;
00481 case 0x3C:
00482 con_Printf("lsh");
00483 break;
00484 case 0x3D:
00485 con_Printf("rsh");
00486 break;
00487
00488 case 0x3E:
00489 con_Printf("push byte\t%s", print_bp(op.i0));
00490 break;
00491 case 0x3F:
00492 con_Printf("push\t\t%s", print_bp(op.i0));
00493 break;
00494 case 0x40:
00495 con_Printf("push dword\t%s", print_bp(op.i0));
00496 break;
00497 case 0x41:
00498 con_Printf("push string\t%s", print_bp(op.i0));
00499 break;
00500 case 0x42:
00501 con_Printf("push list\t%s (%02X)", print_bp(op.i0), op.i1);
00502 break;
00503 case 0x43:
00504 con_Printf("push slist\t%s", print_bp(op.i0));
00505 break;
00506 case 0x44:
00507 con_Printf("push element\t(%02X) slist==%02X", op.i0, op.i1);
00508 break;
00509 case 0x45:
00510 con_Printf("push huge\t%02X %02X", op.i0, op.i1);
00511 break;
00512 case 0x4B:
00513 con_Printf("push addr\t%s", print_bp(op.i0));
00514 break;
00515 case 0x4C:
00516 con_Printf("push indirect\t%02Xh bytes", op.i0);
00517 break;
00518 case 0x4D:
00519 con_Printf("pop indirect\t%02Xh bytes", op.i0);
00520 break;
00521
00522 case 0x4E:
00523 con_Printf("push\t\tglobal [%04X %02X] (%s)", op.i0, op.i1,
00524 GlobalNames[op.i0].name.c_str());
00525 break;
00526 case 0x4F:
00527 con_Printf("pop\t\tglobal [%04X %02X] (%s)", op.i0, op.i1,
00528 GlobalNames[op.i0].name.c_str());
00529 break;
00530
00531 case 0x50:
00532 con_Printf("ret");
00533 break;
00534 case 0x51:
00535 con_Printf("jne\t\t%04Xh\t(to %04X)", op.i0, op.nextoffset + static_cast<short>(op.i0));
00536 break;
00537 case 0x52:
00538 con_Printf("jmp\t\t%04Xh\t(to %04X)", op.i0, op.nextoffset + static_cast<short>(op.i0));
00539 break;
00540
00541 case 0x53:
00542 con_Printf("suspend");
00543 break;
00544
00545 case 0x54:
00546 con_Printf("implies\t\t%02X %02X", op.i0, op.i1);
00547 break;
00548
00549 case 0x57:
00550 con_Printf("spawn\t\t%02X %02X %04X:%04X (%s)",
00551 op.i0, op.i1, op.i2, op.i3, convert->UsecodeFunctionAddressToString(op.i2, op.i3, ucfile, crusader).c_str());
00552 break;
00553 case 0x58:
00554 con_Printf("spawn inline\t%04X:%04X+%04X=%04X %02X %02X (%s+%04X)",
00555 op.i0, op.i1, op.i2, op.i1+op.i2, op.i3, op.i4,
00556 convert->UsecodeFunctionAddressToString(op.i0, op.i1, ucfile, crusader).c_str(), op.i2);
00557 break;
00558 case 0x59:
00559 con_Printf("push\t\tpid");
00560 break;
00561
00562 case 0x5A:
00563 con_Printf("init\t\t%02X", op.i0);
00564 break;
00565
00566 case 0x5B:
00567 con_Printf ("line number\t%i (%04Xh)", op.i0, op.i0);
00568 break;
00569 case 0x5C:
00570 con_Printf("symbol info\toffset %04Xh = \"%s\"", op.i0, op.str.c_str());
00571 break;
00572
00573 case 0x5D:
00574 con_Printf("push byte\tretval");
00575 break;
00576 case 0x5E:
00577 con_Printf("push\t\tretval");
00578 break;
00579 case 0x5F:
00580 con_Printf("push dword\tretval");
00581 break;
00582
00583 case 0x60:
00584 con_Printf("word to dword");
00585 break;
00586 case 0x61:
00587 con_Printf("dword to word");
00588 break;
00589
00590 case 0x62:
00591 con_Printf("free string\t%s", print_bp(op.i0));
00592 break;
00593 case 0x63:
00594 con_Printf("free slist\t%s", print_bp(op.i0));
00595 break;
00596 case 0x64:
00597 con_Printf("free list\t%s", print_bp(op.i0));
00598 break;
00599 case 0x65:
00600 con_Printf("free string\t%s", print_sp(op.i0));
00601 break;
00602 case 0x66:
00603 con_Printf("free list\t%s", print_sp(op.i0));
00604 break;
00605 case 0x67:
00606 con_Printf("free slist\t%s", print_sp(op.i0));
00607 break;
00608 case 0x69:
00609 con_Printf("push strptr\t%s", print_bp(op.i0));
00610 break;
00611 case 0x6B:
00612 con_Printf("str to ptr");
00613 break;
00614
00615 case 0x6C:
00616 con_Printf("param pid chg\t%s %02X", print_bp(op.i0), op.i1);
00617 break;
00618
00619 case 0x6D:
00620 con_Printf("push dword\tprocess result");
00621 break;
00622 case 0x6E:
00623 con_Printf("add sp\t\t%s%02Xh", op.i0>0x7F?"-":"", op.i0>0x7F?0x100-op.i0:op.i0);
00624 break;
00625 case 0x6F:
00626 con_Printf("push addr\t%s", print_sp(0x100 - op.i0));
00627 break;
00628
00629 case 0x70:
00630 con_Printf("loop\t\t%s %02X %02X", print_bp(op.i0), op.i1, op.i2);
00631 break;
00632 case 0x73:
00633 con_Printf("loopnext");
00634 break;
00635 case 0x74:
00636 con_Printf("loopscr\t\t%02X \"%c\" - %s", op.i0, static_cast<char>(op.i0),ScriptExpressions[op.i0].c_str());
00637 break;
00638
00639 case 0x75:
00640 con_Printf("foreach list\t%s (%02X) %04X", print_bp(op.i0), op.i1, op.i2);
00641 break;
00642
00643 case 0x76:
00644 con_Printf("foreach slist\t%s (%02X) %04X", print_bp(op.i0), op.i1, op.i2);
00645 break;
00646
00647 case 0x77:
00648 con_Printf("set info");
00649 break;
00650
00651 case 0x78:
00652 con_Printf("process exclude");
00653 break;
00654
00655 case 0x79:
00656 con_Printf("global_address\t%04X", op.i0);
00657 break;
00658
00659 case 0x7A:
00660 con_Printf("end");
00661
00662 if(op.str.size())
00663 {
00664 con_Printf("\tsize of dbg symbols %04X", op.str.size());
00665 }
00666
00667 break;
00668
00669
00670 default:
00671 con_Printf("db\t\t%02x", op.op());
00672 assert(false);
00673 }
00674 con_Printf("\n");
00675 }
00676
00677
00678 void printfunc(const uint32 func, const uint32 nameoffset, IDataSource *ucfile)
00679 {
00680 ucfile->seek(0x80 + 8*(func+2));
00681 uint32 offset = read4(ucfile);
00682 uint32 length = read4(ucfile);
00683
00684 if (length == 0) return;
00685
00686 ucfile->seek(nameoffset + 4 + (13 * func));
00687
00688 char namebuf[9];
00689 ucfile->read(namebuf, 9);
00690
00691 ucfile->seek(offset);
00692
00693 UsecodeHeader uch;
00694
00695 convert->readheader(ucfile, uch, curOffset);
00696
00697 con_Printf_s("Usecode class %d (%04X %s)\n", func, func, namebuf);
00698
00699 convert->readevents(ucfile, uch);
00700
00701 while (readfunction(ucfile, namebuf, uch, func));
00702
00703 #ifdef FOLD
00704 folder->FinalUnit();
00705
00706
00707 folder->print_asm(con);
00708 folder->print_unk(con);
00709
00710
00711
00712 #endif
00713 }
00714 #undef con_Printf // undef the evil define
00715
00716 void readfunctionnames(void)
00717 {
00718 #if 0 // FIXME: conf/
00719 Configuration config;
00720 std::vector<std::string> functionnames;
00721 std::string functionaddress;
00722
00723 config.read_config_file("usecodemap.cfg");
00724 functionnames = config.listkeys("usecodemap",false);
00725 std::vector<std::string>::iterator it = functionnames.begin();
00726 while (it != functionnames.end())
00727 {
00728 config.value("usecodemap/" + *it + "/" + gamelanguage, functionaddress, "N/A");
00729 if (functionaddress == "N/A")
00730 perr << gamelanguage << " entry point for " << *it << " not found" << std::endl;
00731 else
00732 {
00733 for(std::string::iterator i=functionaddress.begin(); i!=functionaddress.end(); ++i)
00734 std::toupper(*i);
00735
00736 FuncNames[functionaddress] = *it;
00737 }
00738 it++;
00739 }
00740 #endif
00741 }
00742
00743 int main(int argc, char **argv)
00744 {
00745 if (argc < 3) {
00746 perr << "Usage: " << argv[0] << " <file> [<function number>|-a] {--game [u8|crusader]} {--lang [english|german|french|japanese]} {--odir <directory>}" << endl;
00747 perr << "or" << endl;
00748 perr << "Usage: " << argv[0] << " <file> -l" << endl;
00749 perr << "or" << endl;
00750 perr << "Usage: " << argv[0] << " <file> --globals {--game [u8|crusader]}" << endl;
00751
00752 perr << "or" << endl;
00753 perr << "Usage: " << argv[0] << " <file> -overload" << endl;
00754 return 1;
00755 }
00756
00757 con.DisableWordWrap();
00758
00759 Args parameters;
00760
00761 parameters.declare("--lang", &gamelanguage, "unknown");
00762 parameters.declare("--game", &gametype, "none");
00763 parameters.declare("--odir", &outputdir, "");
00764 parameters.declare("--globals", &print_globals, true);
00765 #ifdef FOLD
00766 parameters.declare("--disasm", &print_disasm, true);
00767 #endif
00768 parameters.declare("--strings", &strings_only, true);
00769
00770 parameters.process(argc, argv);
00771
00772
00773 char *stripped_filename = argv[1];
00774
00775
00776 for(uint32 i = 0; argv[1][i]; ++i)
00777 if (argv[1][i] == '\\' || argv[1][i] == '/' || argv[1][i] == ':') stripped_filename = argv[1]+i+1;
00778
00779 if (gamelanguage=="unknown")
00780 {
00781 switch (stripped_filename[0])
00782 {
00783 case 'g': case 'G':
00784 gamelanguage = "german";
00785 break;
00786 case 'e': case 'E':
00787 gamelanguage = "english";
00788 break;
00789 case 'f': case 'F':
00790 gamelanguage = "french";
00791 break;
00792 case 'j': case 'J':
00793 gamelanguage = "japanese";
00794 break;
00795 default:
00796 perr << "Could not determine game language. Defaulting to english." << std::endl;
00797 gamelanguage = "english";
00798 }
00799 }
00800 if ( (gamelanguage != "german") && (gamelanguage != "english") && (gamelanguage != "french") && (gamelanguage != "japanese"))
00801 {
00802 perr << "Warning: unknown language specified (" << gamelanguage << ")." << std::endl;
00803 }
00804
00805
00806 FileSystem filesys(true);
00807
00808
00809 IDataSource *ucfile = filesys.ReadFile(argv[1]);
00810
00811
00812 if(ucfile==0)
00813 {
00814 perr << "Error reading file \"" << argv[1] << "\"" << endl;
00815 return 1;
00816 }
00817
00818
00819 if (!Pentagram::strcasecmp(stripped_filename, "overload.dat"))
00820 {
00821 pout << "Using \"overload.dat\". Forcing crusader gametype." << std::endl;
00822 gametype="crusader";
00823 }
00824
00825 else if (gametype=="none")
00826 {
00827 ucfile->seek(0x80);
00828 sint32 nameoffset = read4(ucfile);
00829 sint32 namelength = read4(ucfile);
00830
00831
00832 if (nameoffset && namelength) gametype="u8";
00833
00834 else gametype="crusader";
00835 }
00836
00837
00838 pout << "Game type: " << gametype << std::endl <<
00839 "Language: " << gamelanguage << std::endl;
00840
00841 if(outputdir.size())
00842 pout << "Output Directory: `" << outputdir << "`" << endl;
00843
00844
00845 if (gametype=="crusader")
00846 {
00847 crusader=true;
00848 FORGET_OBJECT(convert);
00849 convert = new ConvertUsecodeCrusader();
00850 }
00851
00852
00853 readfunctionnames();
00854
00855
00856 if (!Pentagram::strcasecmp(argv[2], "-l")) {
00857
00858 pout << "Listing classes..." << endl << endl;
00859
00860
00861 ucfile->seek( 0x54);
00862 uint32 entries = read4(ucfile)-2;
00863
00864 ucfile->seek(0x80 + 8);
00865 sint32 nameoffset = read4(ucfile);
00866 read4(ucfile);
00867
00868 pout.setf(std::ios::uppercase);
00869
00870 con.Printf("Class Name Offset Routines MaxOffset Offset ExternTab FixupTab\n");
00871
00872 sint32 actual_num = 0;
00873 for(uint32 func = 0; func < entries; ++func)
00874 {
00875 ucfile->seek(0x80 + 8*(func+2));
00876 sint32 offset = read4(ucfile);
00877 sint32 length = read4(ucfile);
00878
00879 ucfile->seek(nameoffset + 4 + (13 * func));
00880 char namebuf[9];
00881 ucfile->read(namebuf, 9);
00882
00883 if (length == 0) continue;
00884
00885
00886
00887
00888 ucfile->seek(offset);
00889 UsecodeHeader uch;
00890 convert->readheader(ucfile, uch, curOffset);
00891
00892 con.Printf("%4d (0x%04X) %-8s 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08d\n",
00893 func, func, namebuf, offset, uch.routines, uch.maxOffset,
00894 uch.offset, uch.externTable, uch.fixupTable, uch.fixupTable - uch.externTable);
00895
00896 ++actual_num;
00897 }
00898 pout << endl << actual_num << " Usecode classes" << endl;
00899 return 0;
00900 }
00901
00902 else if (!Pentagram::strcasecmp(argv[2], "-overload")) {
00903 uint32 end;
00904
00905
00906 if (!Pentagram::strcasecmp(stripped_filename, "overload.dat"))
00907 {
00908 end = ucfile->getSize();
00909 ucfile->seek(0);
00910 }
00911
00912 else
00913 {
00914 ucfile->seek(0x88);
00915 uint32 offset = ucfile->read4();
00916 end = ucfile->read4();
00917 ucfile->seek(offset);
00918 end += offset;
00919 }
00920
00921 printoverloads(ucfile, end);
00922 return 0;
00923 }
00924
00925 pout.setf(std::ios::uppercase);
00926 pout << std::hex;
00927
00928 readglobals(ucfile);
00929
00930 if(print_globals)
00931 printglobals();
00932
00933
00934 ScriptExpressions[0] = "false";
00935 ScriptExpressions[1] = "true";
00936 ScriptExpressions['$'] = "end";
00937 ScriptExpressions['%'] = "int";
00938 ScriptExpressions['&'] = "&&";
00939 ScriptExpressions['+'] = "||";
00940 ScriptExpressions['!'] = "!";
00941 ScriptExpressions['?'] = "item->status";
00942 ScriptExpressions['*'] = "item->q";
00943 ScriptExpressions['#'] = "item->npc_num";
00944 ScriptExpressions['='] = "==";
00945 ScriptExpressions['>'] = ">";
00946 ScriptExpressions['<'] = "<";
00947 ScriptExpressions[']'] = ">=";
00948 ScriptExpressions['['] = "<=";
00949 ScriptExpressions[':'] = "item->family";
00950 ScriptExpressions['@'] = "item->shape";
00951 ScriptExpressions['`'] = "item->frame";
00952
00953 #ifdef FOLD
00954 initfolding();
00955 #endif
00956
00957 ucfile->seek(0x80 + 8);
00958 uint32 nameoffset = read4(ucfile);
00959 read4(ucfile);
00960
00961 if(std::strcmp(argv[2], "-a")==0)
00962 {
00963 ucfile->seek(0x54);
00964 uint32 entries = read4(ucfile)-2;
00965
00966 for(uint32 func=0; func<entries; ++func)
00967 printfunc(func, nameoffset, ucfile);
00968 }
00969
00970 uint32 func = std::strtol(argv[2], 0, 0);
00971
00972 printfunc(func, nameoffset, ucfile);
00973
00974 return 0;
00975 }
00976
00977
00978 void printoverloads(IDataSource *ucfile, uint32 endpos)
00979 {
00980 con.Printf ("Overload Table:\n");
00981
00982 uint32 f, i = 0;
00983 uint32 all_mask = 0;
00984
00985 while ((ucfile->getPos()) < endpos) {
00986 uint32 mask;
00987 char classname[9];
00988
00989 mask = ucfile->read4();
00990 ucfile->read(classname, 9);
00991
00992 if (classname[0]) {
00993 con.Printf ("%04d: %8s ", i, classname);
00994
00995 for (f=0; f<32; f++) con.Printf (" %i",(mask>>f) & 1);
00996
00997 con.Printf ("\n");
00998 }
00999 all_mask |= mask;
01000 i++;
01001 }
01002 con.Printf ("\n%i functions ", i);
01003
01004 con.Printf ("\nAll functions: ");
01005
01006 for (f=0; f<32; f++) con.Printf (" %i",(all_mask>>f) & 1);
01007
01008 con.Printf ("\n\nEvents used:\n");
01009 for (f=0; f<32; f++) {
01010 if ((all_mask>>f) & 1) con.Printf (" %i: %s\n", f, convert->event_names()[f]);
01011 }
01012 }