00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef CONVERT_H
00020 #define CONVERT_H
00021
00022 #include "IDataSource.h"
00023 #include "common_types.h"
00024 #include "Console.h"
00025 #include <vector>
00026 #include <string>
00027 #include "GenericNodes.h"
00028 #include "LoopScriptNodes.h"
00029
00030 class DebugSymbol
00031 {
00032 public:
00033 uint32 number;
00034 uint32 unknown1;
00035 uint32 type;
00036 uint32 unknown2;
00037 uint32 unknown3;
00038 std::string name;
00039
00040 };
00041
00042 class ConvertUsecode
00043 {
00044
00045 public:
00046 ConvertUsecode() {};
00047 virtual ~ConvertUsecode() {};
00048
00049 virtual const char* const *intrinsics()=0;
00050 virtual const char* const *event_names()=0;
00051 virtual void readheader(IDataSource *ucfile, UsecodeHeader &uch, uint32 &curOffset)=0;
00052 virtual void readevents(IDataSource *ucfile, const UsecodeHeader &uch)=0;
00053 virtual void readOp(TempOp &op, IDataSource *ucfile, uint32 &dbg_symbol_offset, std::vector<DebugSymbol> &debugSymbols, bool &done)=0;
00054 virtual Node *readOp(IDataSource *ucfile, uint32 &dbg_symbol_offset, std::vector<DebugSymbol> &debugSymbols, bool &done)=0;
00055
00056 void readDbgSymbols(IDataSource *ucfile, std::vector<DebugSymbol> &debugSymbols);
00057 void readOpGeneric(TempOp &op, IDataSource *ucfile, uint32 &dbg_symbol_offset, std::vector<DebugSymbol> &debugSymbols,
00058 bool &done, const bool crusader);
00059 Node *readOpGeneric(IDataSource *ucfile, uint32 &dbg_symbol_offset, std::vector<DebugSymbol> &debugSymbols,
00060 bool &done, const bool crusader);
00061 void printDbgSymbols(std::vector<DebugSymbol> &debugSymbols);
00062
00063 std::string UsecodeFunctionAddressToString(const sint32 uclass, const sint32 coffset, IDataSource *ucfile, const bool crusader);
00064
00065 private:
00066 static const uint32 MAX_UCFUNC_NAMELEN = 256;
00067 };
00068
00069
00070 void ConvertUsecode::readDbgSymbols(IDataSource *ucfile, std::vector<DebugSymbol> &debugSymbols)
00071 {
00072 uint32 count=read1(ucfile);
00073
00074 for(uint32 i=0; i<count; ++i)
00075 {
00076 DebugSymbol ds;
00077
00078 ds.number = i;
00079 ds.unknown1 = read1(ucfile);
00080 ds.type = read1(ucfile);
00081 ds.unknown2 = read1(ucfile);
00082 ds.unknown3 = read1(ucfile);
00083 uint32 tchar;
00084 while ((tchar = read1(ucfile)))
00085 ds.name += static_cast<char>(tchar);
00086
00087 debugSymbols.push_back(ds);
00088 }
00089 }
00090
00091 void ConvertUsecode::printDbgSymbols(std::vector<DebugSymbol> &debugSymbols)
00092 {
00093 for(uint32 i=0; i<debugSymbols.size(); ++i)
00094 {
00095 DebugSymbol &ds = debugSymbols[i];
00096
00097 con.Printf("%02X: %02X type=%02X (%c) %s (%02X) %02X %s\n",
00098 ds.number, ds.unknown1, ds.type, ds.type, print_bp(ds.unknown2), ds.unknown2, ds.unknown3, ds.name.c_str());
00099 }
00100 };
00101
00102 void printbytes(IDataSource *f, uint32 num)
00103 {
00104
00105 while(num>0)
00106 {
00107 uint8 c = f->read1();
00108 con.Printf("%02X %c ", c, std::isprint(c) ? c : '.');
00109 --num;
00110 }
00111 }
00112
00113
00114
00115 void ConvertUsecode::readOpGeneric(TempOp &op, IDataSource *ucfile, uint32 &dbg_symbol_offset, std::vector<DebugSymbol> &debugSymbols,
00116 bool &done, const bool crusader)
00117 {
00118 if(dbg_symbol_offset==curOffset)
00119 {
00120 readDbgSymbols(ucfile, debugSymbols);
00121 op.op(read1(ucfile));
00122 assert(op.op()==0x7a);
00123 }
00124 else
00125 op.op(read1(ucfile));
00126
00127 op.offset = curOffset-1;
00128
00129
00130
00131
00132
00133
00134
00135 switch(op.op()) {
00136
00137
00138 case 0x00:
00139
00140
00141 op.i0 = read1(ucfile);
00142 break;
00143 case 0x01:
00144
00145
00146 op.i0 = read1(ucfile);
00147 break;
00148 case 0x02:
00149
00150
00151 op.i0 = read1(ucfile);
00152 break;
00153 case 0x03:
00154
00155
00156 op.i0 = read1(ucfile); op.i1 = read1(ucfile);
00157 break;
00158
00159 case 0x08:
00160
00161
00162 break;
00163 case 0x09:
00164
00165
00166 op.i0 = read1(ucfile); op.i1 = read1(ucfile); op.i2 = read1(ucfile);
00167 break;
00168
00169
00170 case 0x0A:
00171
00172
00173 op.i0 = read1(ucfile);
00174 break;
00175 case 0x0B:
00176
00177
00178 op.i0 = read2(ucfile);
00179 break;
00180 case 0x0C:
00181
00182
00183 op.i0 = read4(ucfile);
00184 break;
00185 case 0x0D:
00186
00187
00188 op.i0 = read2(ucfile);
00189 op.str = "";
00190 while ((op.i1 = read1(ucfile))) op.str += static_cast<char>(op.i1);
00191 break;
00192 case 0x0E:
00193
00194
00195 op.i0 = read1(ucfile);
00196 op.i1 = read1(ucfile);
00197 break;
00198
00199
00200 case 0x0F:
00201
00202
00203 op.i0 = read1(ucfile);
00204 op.i1 = read2(ucfile);
00205 break;
00206 case 0x11:
00207
00208
00209 op.i0 = read2(ucfile);
00210 op.i1 = read2(ucfile);
00211 break;
00212 case 0x12:
00213
00214
00215 break;
00216
00217 case 0x14:
00218
00219
00220 break;
00221 case 0x15:
00222
00223
00224 break;
00225 case 0x16:
00226
00227
00228 break;
00229 case 0x17:
00230
00231
00232 break;
00233 case 0x19:
00234
00235
00236 op.i0 = read1(ucfile);
00237 break;
00238 case 0x1A:
00239
00240
00241 op.i0 = read1(ucfile);
00242 break;
00243 case 0x1B:
00244
00245
00246 op.i0 = read1(ucfile);
00247 break;
00248 case 0x1C:
00249
00250
00251 break;
00252 case 0x1D:
00253
00254
00255 break;
00256 case 0x1E:
00257
00258
00259 break;
00260 case 0x1F:
00261
00262
00263 break;
00264 case 0x20:
00265
00266
00267 break;
00268 case 0x21:
00269
00270
00271 break;
00272 case 0x22:
00273
00274
00275 break;
00276 case 0x23:
00277
00278
00279 assert(false);
00280 break;
00281 case 0x24:
00282
00283
00284 break;
00285 case 0x25:
00286
00287
00288 assert(false);
00289 break;
00290 case 0x26:
00291
00292
00293 break;
00294 case 0x28:
00295
00296
00297 break;
00298 case 0x29:
00299
00300
00301 break;
00302 case 0x2A:
00303
00304
00305 break;
00306 case 0x2B:
00307
00308
00309 break;
00310 case 0x2C:
00311
00312
00313 break;
00314 case 0x2D:
00315
00316
00317 break;
00318 case 0x2E:
00319
00320
00321 break;
00322 case 0x2F:
00323
00324
00325 break;
00326 case 0x30:
00327
00328
00329 break;
00330 case 0x31:
00331
00332
00333 break;
00334 case 0x32:
00335
00336
00337 break;
00338 case 0x33:
00339
00340
00341 break;
00342 case 0x34:
00343
00344
00345 break;
00346 case 0x35:
00347
00348
00349 break;
00350 case 0x36:
00351
00352
00353 break;
00354 case 0x37:
00355
00356
00357 break;
00358
00359 case 0x38:
00360
00361
00362
00363
00364
00365
00366 op.i0 = read1(ucfile); op.i1 = read1(ucfile);
00367 break;
00368
00369 case 0x39:
00370
00371
00372 break;
00373 case 0x3A:
00374
00375
00376 break;
00377 case 0x3B:
00378
00379
00380 break;
00381 case 0x3C:
00382
00383
00384 break;
00385 case 0x3D:
00386
00387
00388 break;
00389
00390 case 0x3E:
00391
00392
00393 op.i0 = read1(ucfile);
00394 break;
00395 case 0x3F:
00396
00397
00398 op.i0 = read1(ucfile);
00399 break;
00400 case 0x40:
00401
00402
00403 op.i0 = read1(ucfile);
00404 break;
00405 case 0x41:
00406
00407
00408 op.i0 = read1(ucfile);
00409 break;
00410 case 0x42:
00411
00412
00413 op.i0 = read1(ucfile); op.i1 = read1(ucfile);
00414 break;
00415 case 0x43:
00416
00417
00418 op.i0 = read1(ucfile);
00419 break;
00420 case 0x44:
00421
00422
00423
00424
00425
00426 op.i0 = read1(ucfile); op.i1 = read1(ucfile);
00427 break;
00428 case 0x45:
00429
00430
00431 op.i0 = read1(ucfile); op.i1 = read1(ucfile);
00432 break;
00433 case 0x4B:
00434
00435
00436 op.i0 = read1(ucfile);
00437 break;
00438 case 0x4C:
00439
00440
00441
00442
00443 op.i0 = read1(ucfile);
00444 break;
00445 case 0x4D:
00446
00447
00448
00449
00450 op.i0 = read1(ucfile);
00451 break;
00452
00453 case 0x4E:
00454
00455
00456 op.i0 = read2(ucfile); op.i1 = read1(ucfile);
00457 break;
00458 case 0x4F:
00459
00460
00461 op.i0 = read2(ucfile); op.i1 = read1(ucfile);
00462 break;
00463
00464 case 0x50:
00465
00466
00467 break;
00468 case 0x51:
00469
00470
00471 op.i0 = read2(ucfile);
00472 break;
00473 case 0x52:
00474
00475
00476 op.i0 = read2(ucfile);
00477 break;
00478
00479 case 0x53:
00480
00481
00482 break;
00483
00484 case 0x54:
00485
00486
00487
00488
00489 op.i0 = read1(ucfile); op.i1 = read1(ucfile);
00490 break;
00491
00492 case 0x57:
00493
00494
00495
00496
00497
00498 op.i0 = read1(ucfile); op.i1 = read1(ucfile);
00499 op.i2 = read2(ucfile); op.i3 = read2(ucfile);
00500 break;
00501 case 0x58:
00502
00503
00504
00505
00506 op.i0 = read2(ucfile); op.i1 = read2(ucfile);
00507 op.i2 = read2(ucfile);
00508 op.i3 = read1(ucfile); op.i4 = read1(ucfile);
00509 break;
00510 case 0x59:
00511
00512
00513 break;
00514
00515 case 0x5A:
00516
00517
00518
00519 op.i0 = read1(ucfile);
00520 break;
00521
00522 case 0x5B:
00523
00524
00525 op.i0 = read2(ucfile);
00526 break;
00527 case 0x5C:
00528 {
00529
00530
00531
00532
00533
00534
00535 op.i0 = read2(ucfile);
00536
00537 op.i0 = curOffset + (static_cast<short>(op.i0));
00538 op.str = "";
00539 for (uint32 i=0; i < 8; ++i)
00540 op.str += static_cast<char>(read1(ucfile));
00541 if(read1(ucfile)!=0) assert(false);
00542 dbg_symbol_offset = op.i0;
00543
00544 break;
00545 }
00546
00547 case 0x5D:
00548
00549
00550 break;
00551 case 0x5E:
00552
00553
00554 break;
00555 case 0x5F:
00556
00557
00558 break;
00559
00560 case 0x60:
00561
00562
00563 break;
00564 case 0x61:
00565
00566
00567 break;
00568
00569 case 0x62:
00570
00571
00572 op.i0 = read1(ucfile);
00573 break;
00574 case 0x63:
00575
00576
00577
00578
00579 op.i0 = read1(ucfile);
00580 break;
00581 case 0x64:
00582
00583
00584 op.i0 = read1(ucfile);
00585 break;
00586 case 0x65:
00587
00588
00589 op.i0 = read1(ucfile);
00590 break;
00591 case 0x66:
00592
00593
00594 op.i0 = read1(ucfile);
00595 break;
00596 case 0x67:
00597
00598
00599 op.i0 = read1(ucfile);
00600 break;
00601 case 0x69:
00602
00603
00604 op.i0 = read1(ucfile);
00605 break;
00606 case 0x6B:
00607
00608
00609 break;
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675 case 0x6C:
00676
00677
00678 op.i0 = read1(ucfile); op.i1 = read1(ucfile);
00679 break;
00680
00681 case 0x6D:
00682
00683
00684 break;
00685 case 0x6E:
00686
00687
00688 op.i0 = read1(ucfile);
00689 break;
00690 case 0x6F:
00691
00692
00693 op.i0 = read1(ucfile);
00694 break;
00695
00696
00697
00698
00699
00700
00701
00702
00703 case 0x70:
00704
00705
00706
00707
00708 op.i0 = read1(ucfile); op.i1 = read1(ucfile); op.i2 = read1(ucfile);
00709 break;
00710 case 0x73:
00711
00712
00713 break;
00714 case 0x74:
00715
00716
00717 op.i0 = read1(ucfile);
00718 break;
00719
00720
00721 case 0x75:
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 op.i0 = read1(ucfile); op.i1 = read1(ucfile); op.i2 = read2(ucfile);
00737 break;
00738
00739
00740 case 0x76:
00741
00742 op.i0 = read1(ucfile); op.i1 = read1(ucfile); op.i2 = read2(ucfile);
00743 break;
00744
00745 case 0x77:
00746
00747
00748
00749 break;
00750
00751 case 0x78:
00752
00753
00754
00755
00756
00757 break;
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779 case 0x79:
00780
00781
00782
00783
00784
00785 if (crusader)
00786 {
00787 op.i0 = read2(ucfile);
00788 }
00789 else
00790 {
00791 op.op(0x7A);
00792 done = true;
00793 }
00794 break;
00795
00796 case 0x7A:
00797
00798 printDbgSymbols(debugSymbols);
00799 done = true;
00800 break;
00801
00802
00803 default:
00804 con.Printf("db\t\t%02X", op.op());
00805 assert(false);
00806 }
00807
00808 op.nextoffset=curOffset;
00809 }
00810
00811 #include "FuncNodes.h"
00812 #include "VarNodes.h"
00813 #include "CallNodes.h"
00814 #include "OperatorNodes.h"
00815 #include "IfNode.h"
00816
00817
00818
00819 Node *ConvertUsecode::readOpGeneric(IDataSource *ucfile, uint32 &dbg_symbol_offset, std::vector<DebugSymbol> &debugSymbols,
00820 bool &done, const bool crusader)
00821 {
00822 Node *n=0;
00823 uint32 opcode=0;
00824 static std::string tstring;
00825
00826 if(dbg_symbol_offset==curOffset)
00827 {
00828 readDbgSymbols(ucfile, debugSymbols);
00829 opcode = read1(ucfile);
00830 assert(opcode==0x7a);
00831 }
00832 else
00833 opcode = read1(ucfile);
00834
00835 uint32 offset = curOffset-1;
00836
00837 switch(opcode) {
00838 case 0x01:
00839 n = new PopVarNode(opcode, offset, read1(ucfile));
00840 break;
00841 case 0x0A:
00842 n = new PushVarNode(opcode, offset, read1(ucfile));
00843 break;
00844 case 0x0B:
00845 n = new PushVarNode(opcode, offset, read2(ucfile));
00846 break;
00847 case 0x0C:
00848 n = new PushVarNode(opcode, offset, read4(ucfile));
00849 break;
00850 case 0x0D:
00851 {
00852 uint32 tint = read2(ucfile);
00853 tstring.clear();
00854 while (char c = static_cast<char>(read1(ucfile))) tstring += c;
00855 n = new PushVarNode(opcode, offset, tint, tstring);
00856 }
00857 break;
00858 case 0x0F:
00859 {
00860 uint32 tint=read1(ucfile);
00861 n = new DCCallNode(opcode, offset, tint, read2(ucfile));
00862 }
00863 break;
00864 case 0x11:
00865 {
00866 uint32 tint=read2(ucfile);
00867 n = new DCCallNode(opcode, offset, tint, read2(ucfile));
00868 }
00869 break;
00870 case 0x12:
00871 n = new PopVarNode(opcode, offset);
00872 break;
00873 case 0x14:
00874 case 0x1C:
00875 case 0x1E:
00876 case 0x24:
00877 case 0x28:
00878 case 0x2A:
00879 case 0x2C:
00880 n = new BinOperatorNode(opcode, offset);
00881 break;
00882 case 0x30:
00883 n = new UniOperatorNode(opcode, offset);
00884 break;
00885 case 0x32:
00886 n = new BinOperatorNode(opcode, offset);
00887 break;
00888 case 0x34:
00889 n = new BinOperatorNode(opcode, offset);
00890 break;
00891 case 0x36:
00892 n = new BinOperatorNode(opcode, offset);
00893 break;
00894 case 0x3F:
00895 n = new PushVarNode(opcode, offset, read1(ucfile));
00896 break;
00897 case 0x40:
00898 n = new PushVarNode(opcode, offset, read1(ucfile));
00899 break;
00900 case 0x4B:
00901 n = new PushVarNode(opcode, offset, read1(ucfile));
00902 break;
00903 case 0x4C:
00904 n = new DCCallMutatorNode(opcode, offset, read1(ucfile));
00905 break;
00906 case 0x4E:
00907 {
00908 uint32 tint = read2(ucfile);
00909 n = new PushVarNode(opcode, offset, tint, read1(ucfile));
00910 }
00911 break;
00912 case 0x50:
00913 n = new FuncMutatorNode(opcode, offset);
00914 break;
00915 case 0x51:
00916 n = new IfNode(opcode, offset, offset + 3 + static_cast<uint16>(read2(ucfile)));
00917 break;
00918 case 0x52:
00919 n = new EndNode(opcode, offset, offset + 3 + static_cast<uint16>(read2(ucfile)));
00920 break;
00921 case 0x53:
00922 n = new FuncMutatorNode(opcode, offset);
00923 break;
00924 case 0x54:
00925 {
00926 uint32 tint1 = read1(ucfile);
00927 uint32 tint2 = read1(ucfile);
00928 assert(tint1==1 && tint2==1);
00929 n = new BinOperatorNode(opcode, offset);
00930 }
00931 break;
00932 case 0x57:
00933 {
00934 uint32 tint1 = read1(ucfile);
00935 uint32 tint2 = read1(ucfile);
00936 uint32 tint3 = read2(ucfile);
00937 n = new DCCallNode(opcode, offset, tint1, tint2, tint3, read2(ucfile));
00938 }
00939 break;
00940 case 0x59:
00941 n = new PushVarNode(opcode, offset);
00942 break;
00943 case 0x5A:
00944 n = new FuncMutatorNode(opcode, offset, read1(ucfile));
00945 break;
00946 case 0x5B:
00947 n = new FuncMutatorNode(opcode, offset, read2(ucfile));
00948 break;
00949 case 0x5C:
00950 {
00951 uint32 tint = offset + 3 + static_cast<sint16>(read2(ucfile));
00952 dbg_symbol_offset = tint;
00953 n = new FuncMutatorNode(opcode, offset, tint, readnstr(ucfile, 9));
00954 }
00955 break;
00956 case 0x5D:
00957 case 0x5E:
00958 n = new DCCallPostfixNode(opcode, offset);
00959 break;
00960 case 0x65:
00961 n = new DCCallPostfixNode(opcode, offset, read1(ucfile));
00962 break;
00963 case 0x6B:
00964 n = new UniOperatorNode(opcode, offset);
00965 break;
00966 case 0x6E:
00967 n = new DCCallPostfixNode(opcode, offset, read1(ucfile));
00968 break;
00969 case 0x70:
00970 {
00971 uint32 currobj = read1(ucfile);
00972 uint32 strsize = read1(ucfile);
00973 uint32 type = read1(ucfile);
00974 n = new LoopNode(opcode, offset, currobj, strsize, type);
00975 }
00976 break;
00977
00978
00979
00980 case 0x74:
00981 n = new LoopScriptNode(opcode, offset, read1(ucfile));
00982 break;
00983 case 0x77:
00984 n = new DCCallMutatorNode(opcode, offset);
00985 break;
00986 case 0x78:
00987 n = new DCCallMutatorNode(opcode, offset);
00988 break;
00989 case 0x79:
00990 if (crusader)
00991 {
00992 assert(false);
00993 }
00994 else
00995 {
00996 n = new FuncMutatorNode(0x7A, offset);
00997 done = true;
00998 }
00999 break;
01000 case 0x7A:
01001 n = new FuncMutatorNode(opcode, offset);
01002 done = true;
01003 break;
01004
01005
01006 default:
01007 con.Printf("\n*** ERROR?:");
01008 con.Printf("\n*** potential opcode:\t%02X", opcode);
01009 con.Printf("\n*** next four bytes:\t");
01010 printbytes(ucfile, 4);
01011 con.Putchar('\n');
01012 return 0;
01013 }
01014
01015 return n;
01016 }
01017
01018
01019
01020
01021
01022
01023 std::string ConvertUsecode::UsecodeFunctionAddressToString(const sint32 uclass, const sint32 coffset, IDataSource *ucfile, const bool crusader)
01024 {
01025 char buf[MAX_UCFUNC_NAMELEN];
01026
01027 #if 0 // FuncName stuff doesn't seem to be used anymore...
01028 std::map<string, string>::iterator funcoffset = FuncNames.find(buf);
01029
01030 snprintf(buf, MAX_UCFUNC_NAMELEN, "%04X:%04X", uclass, coffset);
01031 funcoffset = FuncNames.find(buf);
01032 if (funcoffset != FuncNames.end())
01033 return funcoffset->second;
01034 #endif
01035
01036
01037
01038
01039 uint32 origpos = ucfile->getPos();
01040
01041
01042 ucfile->seek(0x80 + 8);
01043
01044
01045 sint32 offset = ucfile->read4();
01046 ucfile->read4();
01047
01048
01049 ucfile->seek(offset + uclass*13 + 4);
01050
01051
01052 buf[0]='\0';
01053 ucfile->read(buf, 9);
01054
01055
01056 ucfile->seek(origpos);
01057
01058
01059 if (!buf[0]) snprintf(buf, MAX_UCFUNC_NAMELEN, "%04X", uclass);
01060
01061
01062 std::string str = buf;
01063
01064
01065 if (crusader)
01066 {
01067 if (coffset < 0x20)
01068 {
01069 return str + "::" + event_names()[coffset];
01070 }
01071 else
01072 {
01073 snprintf(buf, MAX_UCFUNC_NAMELEN, "%02X", coffset);
01074 return str + "::ordinal" + buf;
01075 }
01076 }
01077
01078 else
01079 {
01080 snprintf(buf, MAX_UCFUNC_NAMELEN, "%04X", coffset);
01081 return str + "::" + buf;
01082 }
01083
01084 CANT_HAPPEN();
01085
01086 return "unknown";
01087 }
01088
01089 #endif