/exult/tags/Release0_98RC1/tools/wud.c

# · C · 326 lines · 280 code · 7 blank · 39 comment · 47 complexity · b6197afca4225a4e20e03b3ac34003cc 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, const char **func_table, int funsize)
  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. printf("\t%04X\n", *(short*)( ptrc + nbytes - 2) +
  121. (short)coffset + nbytes);
  122. // debugging printf("nbytes=%d, coffset=%d\n", nbytes, coffset);
  123. break;
  124. case SLOOP: /* WJP */
  125. printf("\t[%04X], [%04X], [%04X], [%04X], %04X\n",
  126. *(unsigned short*)( ptrc + nbytes - 10 ),
  127. *(unsigned short*)( ptrc + nbytes - 8 ),
  128. *(unsigned short*)( ptrc + nbytes - 6 ),
  129. *(unsigned short*)( ptrc + nbytes - 4 ),
  130. *(short*)( ptrc + nbytes - 2) + (short)coffset + nbytes);
  131. break;
  132. case IMMED_AND_RELATIVE_JUMP: /* JSF */
  133. printf("\t%04XH, %04X\n", *(unsigned short*)( ptrc + 1 ),
  134. *(short*)( ptrc + 3 ) + (short)coffset + 5);
  135. break;
  136. case CALL:
  137. {
  138. // Print call operand
  139. unsigned short func = *(unsigned short*)( ptrc + 1 );
  140. if( ( func < funsize ) &&
  141. func_table[func] )
  142. // Known function
  143. printf("\t_%s@%d (%04X)\n", func_table[func], ptrc[3], func);
  144. else
  145. // Unknown function
  146. printf("\t%04X, %d\n", func, ptrc[3]);
  147. }
  148. break;
  149. case EXTCALL:
  150. {
  151. // Print extern call
  152. unsigned short externpos = *(unsigned short*)( ptrc + 1 );
  153. if( externpos < externsize )
  154. printf("\t[%04X]\t\t\t; %04XH\n", externpos, pextern[externpos]);
  155. else
  156. printf("\t[%04X]\t\t\t; ????\n", externpos);
  157. }
  158. break;
  159. case VARREF:
  160. // Print variable reference
  161. printf("\t[%04X]\n", *(unsigned short*)( ptrc + 1 ));
  162. break;
  163. case FLGREF:
  164. // Print global flag reference
  165. printf("\tflag:[%04X]\n", *(unsigned short*)( ptrc + 1 ));
  166. break;
  167. default:
  168. // Unknown type
  169. printf("\n");
  170. break;
  171. }
  172. return nbytes;
  173. }
  174. void printcodeseg(FILE* f, unsigned short ds, unsigned short s,
  175. const char **func_table, int funsize)
  176. {
  177. long pos;
  178. unsigned short size;
  179. unsigned short externsize;
  180. unsigned short i;
  181. unsigned short offset;
  182. unsigned short nbytes;
  183. unsigned char* p;
  184. unsigned char* pp;
  185. unsigned char* pdata;
  186. unsigned short* pextern;
  187. pos = ftell(f);
  188. size = s - ds - sizeof(unsigned short);
  189. pp = p = malloc(size);
  190. pdata = malloc(ds);
  191. fread(pdata, 1, ds, f);
  192. printf("\t\t.code\n");
  193. fread(p, 1, size, f);
  194. fseek(f, pos, SEEK_SET);
  195. // Print code segment header
  196. if( size < 3 * sizeof(unsigned short) )
  197. {
  198. printf("Code segment bad!\n");
  199. free(p);
  200. free(pdata);
  201. return;
  202. }
  203. // Print argument counter
  204. printf("\t\t.argc %04XH\n", *(unsigned short*)pp);
  205. pp += sizeof(unsigned short);
  206. // Print locals counter
  207. printf("\t\t.localc %04XH\n", *(unsigned short*)pp);
  208. pp += sizeof(unsigned short);
  209. // Print externs section
  210. externsize = *(unsigned short*)pp;
  211. printf("\t\t.externsize %04XH\n", externsize);
  212. pp += sizeof(unsigned short);
  213. if( size < ( ( 3 + externsize ) * sizeof(unsigned short) ) )
  214. {
  215. printf("Code segment bad!\n");
  216. free(p);
  217. free(pdata);
  218. return;
  219. }
  220. size -= ( ( 3 + externsize ) * sizeof(unsigned short) );
  221. pextern = (unsigned short*)pp;
  222. for( i = 0; i < externsize; i++ )
  223. {
  224. printf("\t\t.extern %04XH\n", *(unsigned short*)pp);
  225. pp += sizeof(unsigned short);
  226. }
  227. offset = 0;
  228. // Print opcodes
  229. while( offset < size )
  230. {
  231. nbytes = print_opcode(pp, offset, pdata, pextern, externsize,
  232. func_table, funsize);
  233. pp += nbytes;
  234. offset += nbytes;
  235. }
  236. free(p);
  237. free(pdata);
  238. }
  239. /*
  240. * Note: func = -1 just to print header, funcnum to print it all, or
  241. * -2 for any function.
  242. */
  243. void printfunc(FILE* f, long func, int i, const char **func_table, int funsize)
  244. {
  245. unsigned short s, ds, funcnum;
  246. long off, bodyoff;
  247. // Save start offset
  248. off = ftell(f);
  249. // Read function header
  250. fread(&funcnum, sizeof(unsigned short), 1, f);
  251. fread(&s, sizeof(unsigned short), 1, f);
  252. // Save body offset
  253. bodyoff = ftell(f);
  254. fread(&ds, sizeof(unsigned short), 1, f);
  255. if( func == -1 )
  256. printf("\tFunction #%d (%04XH), offset = %08lx, size = %04x, data = %04x\n", i,
  257. funcnum, off, s, ds);
  258. if( funcnum == func || func == -2)
  259. {
  260. printf("\t\t.funcnumber\t%04XH\n", funcnum);
  261. // Dump function contents
  262. printdataseg(f, ds);
  263. printcodeseg(f, ds, s, func_table, funsize);
  264. }
  265. // Seek back, then to next function
  266. fseek(f, bodyoff, SEEK_SET);
  267. fseek(f, s, SEEK_CUR);
  268. }
  269. int main(int argc, char** argv)
  270. {
  271. unsigned long func = -1;
  272. long sz;
  273. int i = 0;
  274. FILE* f;
  275. int findex = 1; // Argv index of file.
  276. const char **func_table = bg_intrinsic_table;
  277. int funsize = bg_intrinsic_size;
  278. if(argc<2) {
  279. fprintf(stderr, "Usage\n%s [-s] usecode_file [func_num]\n", argv[0]);
  280. return -1;
  281. }
  282. // Serpent Isle?
  283. if (strcmp(argv[1], "-s") == 0)
  284. {
  285. findex++;
  286. func_table = si_intrinsic_table;
  287. funsize = si_intrinsic_size;
  288. }
  289. f = fopen(argv[findex], "rb");
  290. if( f == NULL )
  291. {
  292. fprintf(stderr,"Failed to open %s\n\n", argv[findex]);
  293. return 0;
  294. }
  295. fseek(f, 0, SEEK_END);
  296. sz = ftell(f);
  297. fseek(f, 0, SEEK_SET);
  298. if( argc > findex + 1 )
  299. {
  300. char* stopstr;
  301. if (strcmp(argv[findex + 1], "-a") == 0)
  302. func = -2; // Print ALL functions.
  303. else
  304. func = strtoul(argv[findex + 1], &stopstr, 16);
  305. }
  306. while( ftell(f) < sz )
  307. {
  308. printfunc(f, func, i, func_table, funsize);
  309. i++;
  310. }
  311. if( func == -1 )
  312. {
  313. if( ftell(f) != sz )
  314. fprintf(stderr,"Problem, tell = %ld!\n", ftell(f));
  315. printf("Functions: %d\n", i);
  316. }
  317. fclose(f);
  318. return 0;
  319. }