00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 # include <config.h>
00024 #endif
00025
00026
00027 #include <cstring>
00028 #include <cstdio>
00029 #include <iostream>
00030
00031 #ifndef UNDER_CE
00032 using std::strlen;
00033 using std::cout;
00034 #endif
00035
00036 #include "ucinternal.h"
00037 #include "uctools.h"
00038 #include "utils.h"
00039 #include "useval.h"
00040 #include "game.h"
00041 #include "stackframe.h"
00042
00043 int Usecode_internal::get_opcode_length(int opcode)
00044 {
00045 if (opcode >=0 &&
00046 opcode < (sizeof(opcode_table)/sizeof(opcode_table[0]))) {
00047
00048 return opcode_table[opcode].nbytes + 1;
00049 } else {
00050 return 0;
00051 }
00052 }
00053
00054 void Usecode_internal::uc_trace_disasm(Stack_frame* frame)
00055 {
00056 uc_trace_disasm(frame->locals,
00057 frame->num_args + frame->num_vars,
00058 frame->data,
00059 frame->externs,
00060 frame->code,
00061 frame->ip);
00062 }
00063
00064 void Usecode_internal::uc_trace_disasm(Usecode_value* locals, int num_locals,
00065 uint8* data, uint8* externals, uint8* code,
00066 uint8* ip)
00067 {
00068 int func_ip = (int)(ip - code);
00069 int opcode = *ip++;
00070 uint8* param_ip = ip;
00071 _opcode_desc* pdesc;
00072
00073 if (opcode >=0 && opcode < (sizeof(opcode_table)/sizeof(opcode_table[0])))
00074 pdesc = &(opcode_table[opcode]);
00075 signed short immed;
00076 unsigned short varref;
00077 unsigned short func;
00078 int immed32;
00079 int offset;
00080
00081 std::printf(" %04X: ", func_ip);
00082
00083 if (pdesc && pdesc->mnemonic) {
00084 std::printf("%s", pdesc->mnemonic);
00085 if (strlen(pdesc->mnemonic) < 4)
00086 std::printf("\t");
00087 } else {
00088 std::printf("<unknown>");
00089 }
00090
00091 if (pdesc && pdesc->nbytes > 0) {
00092 switch( pdesc->type )
00093 {
00094 case BYTE:
00095 std::printf("\t%02x", *ip++);
00096 break;
00097 case IMMED:
00098
00099 immed = Read2(ip);
00100 std::printf("\t%04hXH\t\t; %d", immed, immed);
00101 break;
00102 case IMMED32:
00103 immed32 = (sint32)Read4(ip);
00104 std::printf("\t%04hXH\t\t; %d", immed32, immed32);
00105 break;
00106 case DATA_STRING:
00107 case DATA_STRING32:
00108 {
00109 char* pstr;
00110 int len;
00111
00112 if (pdesc->type == DATA_STRING)
00113 offset = Read2(ip);
00114 else
00115 offset = (sint32)Read4(ip);
00116
00117 pstr = (char*)data + offset;
00118 len = strlen(pstr);
00119 if( len > 20 )
00120 len = 20 - 3;
00121 std::printf("\tL%04X\t\t; ", offset);
00122 for(int i = 0; i < len; i++ )
00123 std::printf("%c", pstr[i]);
00124 if( len < strlen(pstr) )
00125
00126 std::printf("...");
00127 }
00128 break;
00129 case RELATIVE_JUMP:
00130
00131 offset = Read2(ip);
00132 std::printf("\t%04X",
00133 (offset + func_ip+1+pdesc->nbytes)&0xFFFF);
00134 break;
00135 case RELATIVE_JUMP32:
00136 offset = (sint32)Read4(ip);
00137 std::printf("\t%04X", offset + func_ip+1+pdesc->nbytes);
00138 break;
00139 case SLOOP:
00140 if (pdesc->nbytes == 11)
00141 ip++;
00142 Read2(ip);
00143 Read2(ip);
00144 Read2(ip);
00145 varref = Read2(ip);
00146 offset = Read2(ip);
00147 std::printf("\t[%04X], %04X\t= ", varref,
00148 (offset +func_ip+1+pdesc->nbytes)&0xFFFF);
00149 locals[varref].print(cout, true);
00150 break;
00151 case SLOOP32:
00152 if (pdesc->nbytes == 13)
00153 ip++;
00154 Read2(ip);
00155 Read2(ip);
00156 Read2(ip);
00157 varref = Read2(ip);
00158 offset = (sint32)Read4(ip);
00159 std::printf("\t[%04X], %04X\t= ", varref,
00160 offset +func_ip+1+pdesc->nbytes);
00161 locals[varref].print(cout, true);
00162 break;
00163 case IMMED_AND_RELATIVE_JUMP:
00164 immed = Read2(ip);
00165 offset = Read2(ip);
00166 std::printf("\t%04hXH, %04X", immed,
00167 (offset + func_ip+1+pdesc->nbytes)&0xFFFF);
00168 break;
00169 case IMMED_RELJUMP32:
00170 immed = Read2(ip);
00171 offset = (sint32)Read4(ip);
00172 std::printf("\t%04hXH, %04X", immed,
00173 offset + func_ip+1+pdesc->nbytes);
00174 break;
00175 case CALL:
00176 {
00177 func = Read2(ip);
00178 immed = *ip++;
00179 const char **func_table = bg_intrinsic_table;
00180 if (Game::get_game_type() == SERPENT_ISLE)
00181 func_table = si_intrinsic_table;
00182 std::printf("\t_%s@%d\t; %04X", func_table[func], immed, func);
00183 }
00184 break;
00185 case EXTCALL:
00186 {
00187
00188 offset = Read2(ip);
00189 std::printf("\t[%04X]\t\t; %04XH", offset,
00190 externals[2*offset] + 256*externals[2*offset + 1]);
00191 }
00192 break;
00193 case VARREF:
00194
00195 varref = Read2(ip);
00196 std::printf("\t[%04X]\t\t= ", varref);
00197 locals[varref].print(cout, true);
00198 break;
00199 case FLGREF:
00200
00201 offset = Read2(ip);
00202 std::printf("\tflag:[%04X]\t= ", offset);
00203 if (gflags[offset])
00204 std::printf("set");
00205 else
00206 std::printf("unset");
00207 break;
00208 default:
00209
00210 break;
00211 }
00212 }
00213 ip = param_ip;
00214
00215
00216 switch (opcode) {
00217 case 0x05:
00218 {
00219 Usecode_value val;
00220 if (sp <= stack)
00221 val = Usecode_value(0);
00222 else
00223 val = *(sp - 1);
00224
00225 if (val.is_false())
00226 std::printf("\t\t(jump taken)");
00227 else
00228 std::printf("\t\t(jump not taken)");
00229 break;
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 }
00257
00258 std::printf("\n");
00259 }