/exult/tags/Release0_35/tools/wud.c

# · C · 295 lines · 257 code · 6 blank · 32 comment · 41 complexity · 26d904298ff6aed65befdcd2e49ed965 MD5 · raw file

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "uctools.h"
  5. // Prints module's data segment
  6. void printdataseg(FILE* f, unsigned short ds)
  7. {
  8. long pos;
  9. unsigned short off = 0;
  10. unsigned char* p; unsigned char* pp;
  11. unsigned char* tempstr,*tempstr2;
  12. tempstr = malloc(60 + 1);
  13. pos = ftell(f);
  14. pp = p = malloc(ds);
  15. fread(p, 1, ds, f);
  16. fseek(f, pos, SEEK_SET);
  17. printf("\t\t.data\n");
  18. while( off < ds )
  19. {
  20. int len;
  21. unsigned short localoff = 0;
  22. while( (len = ( strlen(pp) > 60 ) ? 60 : strlen(pp)) )
  23. {
  24. memcpy(tempstr, pp, len);
  25. tempstr[len] = '\0';
  26. if (!localoff)
  27. printf("L%04X:",off);
  28. while (strchr(tempstr,13))
  29. {
  30. tempstr2=strchr(tempstr,13)+2;
  31. tempstr[strchr(tempstr,13) - (char *) tempstr]=0;
  32. printf("\tdb\t\'%s\'\n\tdb\t0d\n\tdb\t0a\n", tempstr);
  33. strcpy(tempstr,tempstr2);
  34. }
  35. if (tempstr)
  36. printf("\tdb\t\'%s\'\n", tempstr);
  37. localoff += len;
  38. pp += len;
  39. }
  40. pp++;
  41. printf("L%04X:\tdb\t00\n", off+localoff);
  42. off += localoff + 1;
  43. }
  44. free(p);
  45. free(tempstr);
  46. }
  47. // Prints single opcode
  48. // Return number of bytes to advance the code pointer
  49. // Prints first characters of strings referenced
  50. unsigned short print_opcode(unsigned char* ptrc, unsigned short coffset,
  51. unsigned char* pdataseg,unsigned short* pextern,
  52. unsigned short externsize)
  53. {
  54. unsigned short nbytes;
  55. unsigned short i;
  56. // Find the description
  57. opcode_desc* pdesc = ( *ptrc >= ( sizeof(opcode_table) / sizeof( opcode_desc ) ) ) ?
  58. NULL : opcode_table + ( *ptrc );
  59. if( pdesc && ( pdesc->mnemonic == NULL ) )
  60. {
  61. printf("Unknown opcode: %x\n",*ptrc);
  62. // Unknown opcode
  63. pdesc = NULL;
  64. }
  65. // Number of bytes to print
  66. nbytes = pdesc ? ( pdesc->nbytes + 1 ) : 1;
  67. // Print label
  68. printf("%04X: ", coffset);
  69. // Print bytes
  70. for( i = 0; i < nbytes; i++ )
  71. printf("%02X ", ptrc[i]);
  72. // Print mnemonic
  73. if( nbytes < 4 )
  74. printf("\t");
  75. if (pdesc)
  76. printf("\t%s", pdesc->mnemonic);
  77. else
  78. printf("\tdb %x\t???",ptrc[0]);
  79. // Print operands if any
  80. if( ( nbytes == 1 ) || ( pdesc == NULL && pdesc->type == 0) )
  81. {
  82. printf("\n");
  83. return nbytes;
  84. }
  85. switch( pdesc->type )
  86. {
  87. case BYTE:
  88. printf("\t%x\n",*(unsigned char*)(ptrc+1));
  89. break;
  90. case PUSH:
  91. for ( i = 1; i < nbytes; i++)
  92. printf("\n%04X:\t\t\tdb %x",coffset+i,ptrc[i]);
  93. printf("\n");
  94. break;
  95. case IMMED:
  96. // Print immediate operand
  97. printf("\t%04XH\t\t\t; %d\n", *(unsigned short*)( ptrc + 1 ), *(short*)( ptrc + 1 ));
  98. break;
  99. case DATA_STRING:
  100. {
  101. unsigned char* pstr;
  102. int len;
  103. // Print data string operand
  104. pstr = pdataseg + *(unsigned short*)( ptrc + 1 );
  105. len = strlen(pstr);
  106. if( len > 20 )
  107. len = 20 - 3;
  108. printf("\tL%04X\t\t\t; ", *(unsigned short*)( ptrc + 1 ));
  109. for( i = 0; i < len; i++ )
  110. printf("%c", pstr[i]);
  111. if( len < strlen(pstr) )
  112. // String truncated
  113. printf("...");
  114. printf("\n");
  115. }
  116. break;
  117. case RELATIVE_JUMP:
  118. // Print jump desination
  119. printf("\t%04X\n", *(short*)( ptrc + 1 ) + (short)coffset + 3);
  120. break;
  121. case IMMED_AND_RELATIVE_JUMP: /* JSF */
  122. printf("\t%04XH, %04X\n", *(unsigned short*)( ptrc + 1 ),
  123. *(short*)( ptrc + 3 ) + (short)coffset + 5);
  124. break;
  125. case CALL:
  126. {
  127. // Print call operand
  128. unsigned short func = *(unsigned short*)( ptrc + 1 );
  129. if( ( func < ( sizeof(func_table) / sizeof(const char *) ) ) &&
  130. func_table[func] )
  131. // Known function
  132. printf("\t_%s@%d\t\t; %04X\n", func_table[func], ptrc[3], func);
  133. else
  134. // Unknown function
  135. printf("\t%04X, %d\n", func, ptrc[3]);
  136. }
  137. break;
  138. case EXTCALL:
  139. {
  140. // Print extern call
  141. unsigned short externpos = *(unsigned short*)( ptrc + 1 );
  142. if( externpos < externsize )
  143. printf("\t[%04X]\t\t\t; %04XH\n", externpos, pextern[externpos]);
  144. else
  145. printf("\t[%04X]\t\t\t; ????\n", externpos);
  146. }
  147. break;
  148. case VARREF:
  149. // Print variable reference
  150. printf("\t[%04X]\n", *(unsigned short*)( ptrc + 1 ));
  151. break;
  152. case FLGREF:
  153. // Print global flag reference
  154. printf("\tflag:[%04X]\n", *(unsigned short*)( ptrc + 1 ));
  155. break;
  156. default:
  157. // Unknown type
  158. printf("\n");
  159. break;
  160. }
  161. return nbytes;
  162. }
  163. void printcodeseg(FILE* f, unsigned short ds, unsigned short s)
  164. {
  165. long pos;
  166. unsigned short size;
  167. unsigned short externsize;
  168. unsigned short i;
  169. unsigned short offset;
  170. unsigned short nbytes;
  171. unsigned char* p;
  172. unsigned char* pp;
  173. unsigned char* pdata;
  174. unsigned short* pextern;
  175. pos = ftell(f);
  176. size = s - ds - sizeof(unsigned short);
  177. pp = p = malloc(size);
  178. pdata = malloc(ds);
  179. fread(pdata, 1, ds, f);
  180. printf("\t\t.code\n");
  181. fread(p, 1, size, f);
  182. fseek(f, pos, SEEK_SET);
  183. // Print code segment header
  184. if( size < 3 * sizeof(unsigned short) )
  185. {
  186. printf("Code segment bad!\n");
  187. free(p);
  188. free(pdata);
  189. return;
  190. }
  191. // Print argument counter
  192. printf("\t\t.argc %04XH\n", *(unsigned short*)pp);
  193. pp += sizeof(unsigned short);
  194. // Print locals counter
  195. printf("\t\t.localc %04XH\n", *(unsigned short*)pp);
  196. pp += sizeof(unsigned short);
  197. // Print externs section
  198. externsize = *(unsigned short*)pp;
  199. printf("\t\t.externsize %04XH\n", externsize);
  200. pp += sizeof(unsigned short);
  201. if( size < ( ( 3 + externsize ) * sizeof(unsigned short) ) )
  202. {
  203. printf("Code segment bad!\n");
  204. free(p);
  205. free(pdata);
  206. return;
  207. }
  208. size -= ( ( 3 + externsize ) * sizeof(unsigned short) );
  209. pextern = (unsigned short*)pp;
  210. for( i = 0; i < externsize; i++ )
  211. {
  212. printf("\t\t.extern %04XH\n", *(unsigned short*)pp);
  213. pp += sizeof(unsigned short);
  214. }
  215. offset = 0;
  216. // Print opcodes
  217. while( offset < size )
  218. {
  219. nbytes = print_opcode(pp, offset, pdata, pextern, externsize);
  220. pp += nbytes;
  221. offset += nbytes;
  222. }
  223. free(p);
  224. free(pdata);
  225. }
  226. void printfunc(FILE* f, long func, int i)
  227. {
  228. unsigned short s, ds, funcnum;
  229. long off, bodyoff;
  230. // Save start offset
  231. off = ftell(f);
  232. // Read function header
  233. fread(&funcnum, sizeof(unsigned short), 1, f);
  234. fread(&s, sizeof(unsigned short), 1, f);
  235. // Save body offset
  236. bodyoff = ftell(f);
  237. fread(&ds, sizeof(unsigned short), 1, f);
  238. if( func == -1 )
  239. printf("\tFunction #%d (%04XH), offset = %08lx, size = %04x, data = %04x\n", i,
  240. funcnum, off, s, ds);
  241. if( funcnum == func )
  242. {
  243. printf("\t\t.funcnumber\t%04XH\n", funcnum);
  244. // Dump function contents
  245. printdataseg(f, ds);
  246. printcodeseg(f, ds, s);
  247. }
  248. // Seek back, then to next function
  249. fseek(f, bodyoff, SEEK_SET);
  250. fseek(f, s, SEEK_CUR);
  251. }
  252. int main(int argc, char** argv)
  253. {
  254. unsigned long func = -1;
  255. long sz;
  256. int i = 0;
  257. FILE* f;
  258. if(argc<2) {
  259. fprintf(stderr, "Usage\n%s usecode_file [func_num]\n", argv[0]);
  260. return -1;
  261. }
  262. f = fopen(argv[1], "rb");
  263. if( f == NULL )
  264. {
  265. fprintf(stderr,"Failed to open %s\n\n", argv[1]);
  266. return 0;
  267. }
  268. fseek(f, 0, SEEK_END);
  269. sz = ftell(f);
  270. fseek(f, 0, SEEK_SET);
  271. if( argc > 2 )
  272. {
  273. char* stopstr;
  274. func = strtoul(argv[2], &stopstr, 16);
  275. }
  276. while( ftell(f) < sz )
  277. {
  278. printfunc(f, func, i);
  279. i++;
  280. }
  281. if( func == -1 )
  282. {
  283. if( ftell(f) != sz )
  284. fprintf(stderr,"Problem, tell = %d!\n", ftell(f));
  285. printf("Functions: %d\n", i);
  286. }
  287. fclose(f);
  288. return 0;
  289. }