main.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. /*
  2. dasm-tigcc - Disassembler for TI calculators
  3. Copyright (C) 2000-2002 Thomas Nussbaumer
  4. Copyright (C) 2005 Lionel Debroux
  5. Copyright (C) 2007 Kevin Kofler
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software Foundation,
  16. Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. */
  18. /* The code in this file is based on ttdasm, but with the VTI-derived code
  19. removed. Calls to VTI functions have been replaced with calls to the
  20. equivalent TiEmu functions. */
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <stdlib.h>
  24. #include "main.h"
  25. #include "tt.h"
  26. #include "ti68k_def.h"
  27. #include "images.h"
  28. #include "timem.h"
  29. #include "mem.h"
  30. #include "romcalls.h"
  31. #include "disasm.h"
  32. //=============================================================================
  33. // outputs usage information of this tool
  34. //=============================================================================
  35. void PrintUsage() {
  36. fprintf(USAGE_OUT, "dasm-tigcc 1.00 - Disassembler for TI calculators\n\n" \
  37. "Copyright (C) 2000-2002 Thomas Nussbaumer\n" \
  38. "Copyright (C) 2005 Lionel Debroux\n" \
  39. "Copyright (C) 2007 Kevin Kofler\n" \
  40. "Portions (GDB) Copyright (C) 1986-2007 Free Software Foundation\n" \
  41. "Portions (TiEmu) Copyright (C) 2000-2007 Romain Lievin et. al.\n" \
  42. "Portions (ld-tigcc) Copyright (C) 2002-2004 Sebastian Reichelt\n\n" \
  43. "This program is free software; you may redistribute it under the\n" \
  44. "terms of the the GNU General Public License. There is NO warranty;\n" \
  45. "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"\
  46. "Usage: dasm-tigcc [flags] [<infile>]\n\n" \
  47. " -o <number> ... use given offset as start point\n" \
  48. " -l <bytes> ... disassemble number of given bytes\n" \
  49. " -r <romfile> ... disassemble given rom file\n" \
  50. " -f ... show ROM function table\n" \
  51. " -name ... show possible ROM calls\n" \
  52. " -virtual <number> ... use additionally virtual offset\n" \
  53. " -nolabels ... use no labels in output\n" \
  54. " -raw ... treat file as raw binary\n" \
  55. " -vti ... treat file as VTI save file\n" \
  56. " -stub ... prints additionally information of\n" \
  57. " kernel based programs\n\n" \
  58. " disassembles a TI89/TI92plus NOSTUB executable,\n" \
  59. " a TI89/TI92plus raw dump,parts of a given ROM file or\n" \
  60. " a VTI save file.\n\n" \
  61. " NOTE1: the offset and the length can be specified as\n" \
  62. " hex numbers, too (for example: -o 0x4c)\n\n" \
  63. " NOTE2: offsets are not treated as pure file offsets,\n" \
  64. " but are handled depending on the target.\n" \
  65. " Within executables offset 0 starts at file offset\n" \
  66. " 88 which is just behind the header and the length\n" \
  67. " information. Offsets within ROM files maps\n" \
  68. " directly to the real addresses within the calculator.\n\n");
  69. }
  70. int calc_type;
  71. unsigned char* rom;
  72. unsigned char* ram;
  73. int initialPC;
  74. int initIntTabOfs;
  75. unsigned char* mem[256];
  76. unsigned char unused[0x10000];
  77. int label_parse = 0;
  78. int no_labels = 0;
  79. uint32_t rom_base;
  80. uint32_t rom_size;
  81. uint32_t ram_size;
  82. uint32_t entry_point;
  83. static uint32_t abs_labels_start = 0;
  84. static uint32_t abs_labels_len = 0;
  85. #define GET_WORD(m) ((unsigned short)((((m)[0]) << 8) + ((m)[1])))
  86. uint32_t* label_list = NULL;
  87. int label_count = 0;
  88. int labels_allocated = 0;
  89. #define LABEL_ALLOC_STEP 10
  90. //=============================================================================
  91. // adds a label to the list
  92. //=============================================================================
  93. int AddLabel(uint32_t address) {
  94. int i = -1;
  95. if (label_count != 0) {
  96. for (i=0;i<label_count;i++) if (label_list[i] == address) return 1;
  97. }
  98. if (label_count == labels_allocated) {
  99. uint32_t* tmp = (uint32_t*)realloc(label_list,(labels_allocated+LABEL_ALLOC_STEP)*sizeof(uint32_t));
  100. if (!tmp) {
  101. label_parse = 0;
  102. return 0;
  103. }
  104. label_list = tmp;
  105. labels_allocated+=LABEL_ALLOC_STEP;
  106. }
  107. label_list[label_count++] = address;
  108. return 1;
  109. }
  110. //=============================================================================
  111. // adds a label to the list
  112. //=============================================================================
  113. char label_name[200];
  114. char* GetLabel(uint32_t address) {
  115. int i = -1;
  116. if (no_labels) return NULL;
  117. if (label_count != 0) {
  118. for (i=0;i<label_count;i++) if (label_list[i] == address) break;
  119. }
  120. if (i != label_count && i != -1) {
  121. sprintf(label_name,"__L%lX",(unsigned long)label_list[i]);
  122. return label_name;
  123. }
  124. return NULL;
  125. }
  126. void PrintAddress (int32_t reladdr, uint32_t absaddr, int flags, void *stream,
  127. void (*fprintf_f) (void *, const char *, ...),
  128. void (*fputs_f) (const char *, void *))
  129. {
  130. if ((flags & 4) && !(absaddr >= abs_labels_start && absaddr < abs_labels_start + abs_labels_len)) {
  131. fprintf_f(stream, "0x%lX", (unsigned long) absaddr);
  132. return;
  133. }
  134. if (label_parse) {
  135. AddLabel(absaddr);
  136. } else {
  137. char *s = GetLabel(absaddr);
  138. if (!s) {
  139. if (flags & 1) {
  140. if (reladdr < 0)
  141. fprintf_f(stream, ".-0x%X", (int) -reladdr);
  142. else
  143. fprintf_f(stream, ".+0x%X", (int) reladdr);
  144. } else {
  145. if (reladdr < 0)
  146. fprintf_f(stream, "-0x%X", (int) -reladdr);
  147. else
  148. fprintf_f(stream, "0x%X", (int) reladdr);
  149. }
  150. } else {
  151. fprintf_f(stream, "%s", s);
  152. if (flags & 2)
  153. fputs_f("-.", stream);
  154. }
  155. }
  156. }
  157. static void PrintROMInfo(IMG_INFO *info) {
  158. switch (info->calc_type) {
  159. case TI92: printf("TI92 "); break;
  160. case TI89: printf("TI89 "); break;
  161. case TI92p: printf("TI92p "); break;
  162. case V200: printf("V200 "); break;
  163. case TI89t: printf("TI89t "); break;
  164. }
  165. if (info->calc_type==TI92 && info->rom_base==0x20) printf("INTERNAL ");
  166. if (!info->has_boot) printf("UPDATE ");
  167. if (!info->flash==FLASH_ROM) printf("FLASHROM ");
  168. }
  169. //=============================================================================
  170. // frees buffers used for ROM
  171. //=============================================================================
  172. void CleanupROM() {
  173. if (rom) free(rom);
  174. if (ram) free(ram);
  175. rom = 0;
  176. }
  177. //=============================================================================
  178. // load a ROM file
  179. //=============================================================================
  180. int LoadROM(char* filename) {
  181. IMG_INFO info;
  182. rom = (unsigned char*)malloc(4096*1024+3);
  183. ram = (unsigned char*)malloc(256*1024+3);
  184. if (!rom || !ram) {
  185. CleanupROM();
  186. fprintf(stderr,"ERROR: cannot allocate memory for ROM\n");
  187. return 0;
  188. }
  189. memset(rom,0xff,4096*1024+3);
  190. if (ti68k_is_a_rom_file(filename)) {
  191. if (ti68k_get_rom_infos(filename,&info,1)) return 0;
  192. printf("/*[ ");PrintROMInfo(&info);printf("]*/\n");
  193. } else if (ti68k_is_a_tib_file(filename)) {
  194. if (ti68k_get_tib_infos(filename,&info,1)) return 0;
  195. printf("/*[ ");PrintROMInfo(&info);printf("]*/\n");
  196. } else if (ti68k_is_a_img_file(filename)) {
  197. if (ti68k_load_image(filename,&info)) return 0;
  198. printf("/*[ ");PrintROMInfo(&info);printf("]*/\n");
  199. } else {
  200. fprintf(stderr,"ERROR: invalid ROM filename %s (neither .ROM nor .TIB nor .IMG)\n",filename);
  201. CleanupROM();
  202. return 0;
  203. }
  204. calc_type = info.calc_type;
  205. if (info.has_boot)
  206. memcpy(rom,info.data,info.size);
  207. else
  208. ti68k_convert_tib_to_image(&info,rom);
  209. rom_base = info.rom_base << 16;
  210. rom_size = info.size;
  211. ram_size = (rom_size==1024*1024)?0x100000:0x200000;
  212. if (info.flash==FLASH_ROM) {
  213. initialPC = rd_long(&rom[0x1208c]);
  214. initIntTabOfs = 0x12088;
  215. }
  216. else {
  217. initialPC = rd_long(&rom[4]);
  218. initIntTabOfs = 0;
  219. }
  220. free(info.data);
  221. printf("/*[initialPC = 0x%x (%d)]*/\n",initialPC,initialPC);
  222. printf("/*[initIntTabOfs = 0x%x (%d)]*/\n\n",initIntTabOfs,initIntTabOfs);
  223. return 1;
  224. }
  225. //=============================================================================
  226. // initialize memory pointers
  227. //=============================================================================
  228. void InitMemoryPointers() {
  229. memset(ram, 0, 0x40000);
  230. memcpy(ram, rom+initIntTabOfs, 256);
  231. memset(unused, 0x14, 0x10000);
  232. hw_mem_init();
  233. }
  234. static const char* offsetname_ptr;
  235. //=============================================================================
  236. // helper function for disassembling engine
  237. //=============================================================================
  238. void Offset2Name(int addr) {
  239. offsetname_ptr = (romcalls_is_loaded() && !(addr & 3)
  240. && addr < (NMAX_ROMCALLS << 2))
  241. ? romcalls_get_name(addr >> 2) : 0;
  242. }
  243. //=============================================================================
  244. // disassemble given buffer until length bytes are processed
  245. // the given offset is used just for the address output in the comment
  246. //=============================================================================
  247. void Disassemble(unsigned char* mem,int length,int used_offset,
  248. int virtual_offset,int show_possible)
  249. {
  250. char buffer[1024];
  251. int start = 0;
  252. int bytes;
  253. int i;
  254. //printf("starting ...\n");
  255. if (!no_labels) {
  256. label_parse=1;
  257. while (start < length) {
  258. bytes = Dasm68000(mem+start,buffer,start+used_offset+virtual_offset);
  259. if (!label_parse) {
  260. printf("ERROR: OUT-OF-MEMORY - cannot add that much levels\n");
  261. return;
  262. }
  263. start+=bytes;
  264. }
  265. start = 0;
  266. label_parse = 0;
  267. }
  268. printf("asm(\"\n");
  269. while (start < length) {
  270. if (!no_labels) {
  271. char* s = GetLabel(start+used_offset+virtual_offset);
  272. if (s) printf("%s:\n",s);
  273. }
  274. offsetname_ptr = 0;
  275. bytes = Dasm68000(mem+start,buffer,start+used_offset+virtual_offset);
  276. printf("%s",buffer);
  277. for (i=strlen(buffer);i<30;i++) printf(" ");
  278. printf("/* [0x%X (%u)] ",start+used_offset+virtual_offset,start+used_offset+virtual_offset);
  279. for (i=0;i<bytes;i++) printf("%02x ",*(mem+start+i));
  280. for (i=bytes;i<6;i++) printf(" ");
  281. if (show_possible) {
  282. if (offsetname_ptr) printf("?%s? */\n",offsetname_ptr);
  283. else printf("*/\n");
  284. }
  285. else {
  286. printf("*/\n");
  287. }
  288. start+=bytes;
  289. }
  290. printf("\");\n");
  291. }
  292. //=============================================================================
  293. // outputs header details of kernel-based programs or libraries
  294. //=============================================================================
  295. void OutputStubDetails(unsigned char* mem) {
  296. int i,offset,count;
  297. printf("******** STUB-HEADER INFO *********\n");
  298. if ((!strncmp((char*)(mem+4),"68kP",4)) || (!strncmp((char*)(mem+4),"68kL",4))) {
  299. printf("signature: %c%c%c%c\n",*(mem+4),*(mem+5),*(mem+6),*(mem+7));
  300. printf("relcount: %d\n",GET_WORD(mem+8));
  301. printf("offset comment: 0x%04x\n",GET_WORD(mem+0xa));
  302. printf("offset main: 0x%04x\n",GET_WORD(mem+0xc));
  303. printf("offset exit: 0x%04x\n",GET_WORD(mem+0xe));
  304. printf("compatiblity: 0x%04x\n",GET_WORD(mem+0x10));
  305. printf("offset BSS: 0x%04x\n",GET_WORD(mem+0x14));
  306. offset = GET_WORD(mem+0x16);
  307. printf("offset export: 0x%04x\n",offset);
  308. printf("offset RAM table: 0x%04x\n",GET_WORD(mem+0x18));
  309. printf("********* EXPORT TABLE ************\n");
  310. count = GET_WORD(mem+offset);
  311. for (i=0;i<count;i++) printf("export@%04x: 0x%04x\n",i,GET_WORD(mem+offset+2+i*2));
  312. }
  313. else {
  314. printf("--- not found --- (missing 68kP or 68kL)\n");
  315. }
  316. }
  317. //=============================================================================
  318. // its a main ...
  319. //=============================================================================
  320. int main(int argc,char *argv[]) {
  321. char* infile = 0;
  322. FILE* ifp;
  323. char sig[9];
  324. int length;
  325. unsigned char* data;
  326. int n;
  327. int given_offset = -1;
  328. int given_length = -1;
  329. char* given_rom = 0;
  330. int show_functions = 0;
  331. int show_possible_functions = 0;
  332. int virtual_offset = 0;
  333. int raw = 0;
  334. int vti = 0;
  335. int stub = 0;
  336. //---------------------------------------------------------------
  337. // check for too less arguments
  338. //---------------------------------------------------------------
  339. if (argc < 2) {
  340. PrintUsage();
  341. return 1;
  342. }
  343. printf("/* Disassembled with dasm-tigcc\n\n"
  344. " Copyright (C) 2000-2002 Thomas Nussbaumer\n"
  345. " Copyright (C) 2005 Lionel Debroux\n"
  346. " Copyright (C) 2007 Kevin Kofler\n"
  347. " Portions (GDB) Copyright (C) 1986-2007 Free Software Foundation\n"
  348. " Portions (TiEmu) Copyright (C) 2000-2007 Romain Lievin et. al.\n"
  349. " Portions (ld-tigcc) Copyright (C) 2002-2004 Sebastian Reichelt */\n\n");
  350. //---------------------------------------------------------------
  351. // parse commandline arguments
  352. //---------------------------------------------------------------
  353. for (n=1; n<argc; n++) {
  354. if (!strcmp(argv[n], "-o")) {
  355. // handle offset commandline tag
  356. if (n == argc -1) {
  357. PrintUsage();
  358. return 1;
  359. }
  360. else {
  361. if (!strncmp(argv[n+1],"0x",2)) {
  362. if (sscanf(&argv[n+1][2],"%x",&given_offset) != 1) {
  363. PrintUsage();
  364. return 1;
  365. }
  366. }
  367. else {
  368. if (sscanf(argv[n+1],"%d",&given_offset) != 1) {
  369. PrintUsage();
  370. return 1;
  371. }
  372. }
  373. if (given_offset<0) {
  374. fprintf(stderr,"ERROR: offset cannot be negative\n");
  375. return 1;
  376. }
  377. n++;
  378. }
  379. }
  380. else if (!strcmp(argv[n], "-virtual")) {
  381. // handle virtual offset commandline tag
  382. if (n == argc -1) {
  383. PrintUsage();
  384. return 1;
  385. }
  386. else {
  387. if (!strncmp(argv[n+1],"0x",2)) {
  388. if (sscanf(&argv[n+1][2],"%x",&virtual_offset) != 1) {
  389. PrintUsage();
  390. return 1;
  391. }
  392. }
  393. else {
  394. if (sscanf(argv[n+1],"%d",&virtual_offset) != 1) {
  395. PrintUsage();
  396. return 1;
  397. }
  398. }
  399. if (virtual_offset<0) {
  400. fprintf(stderr,"ERROR: offset cannot be negative\n");
  401. return 1;
  402. }
  403. n++;
  404. }
  405. }
  406. else if (!strcmp(argv[n], "-l")) {
  407. // handle length commandline tag
  408. if (n == argc -1) {
  409. PrintUsage();
  410. return 1;
  411. }
  412. else {
  413. if (!strncmp(argv[n+1],"0x",2)) {
  414. if (sscanf(&argv[n+1][2],"%x",&given_length) != 1) {
  415. PrintUsage();
  416. return 1;
  417. }
  418. }
  419. else {
  420. if (sscanf(argv[n+1],"%d",&given_length) != 1) {
  421. PrintUsage();
  422. return 1;
  423. }
  424. }
  425. if (given_length<0) {
  426. fprintf(stderr,"ERROR: length cannot be negative\n");
  427. return 1;
  428. }
  429. n++;
  430. }
  431. }
  432. else if (!strcmp(argv[n], "-r")) {
  433. // handle romfile commandline tag
  434. if (n == argc -1) {
  435. PrintUsage();
  436. return 1;
  437. }
  438. else {
  439. given_rom = argv[n+1];
  440. n++;
  441. }
  442. }
  443. else if (!strcmp(argv[n], "-f")) {
  444. // handle show ROM functions commandline tag
  445. show_functions = 1;
  446. }
  447. else if (!strcmp(argv[n], "-vti")) {
  448. // handle show ROM functions commandline tag
  449. vti = 1;
  450. if (raw || given_rom) {
  451. fprintf(stderr,"ERROR: cannot use -vti with -r or -raw\n");
  452. return 1;
  453. }
  454. }
  455. else if (!strcmp(argv[n], "-stub")) {
  456. // shows additionally informations about kernel based programs
  457. stub = 1;
  458. }
  459. else if (!strcmp(argv[n], "-raw")) {
  460. // handle show ROM functions commandline tag
  461. raw = 1;
  462. if (vti || given_rom) {
  463. fprintf(stderr,"ERROR: cannot use -raw with -r or -vti\n");
  464. return 1;
  465. }
  466. }
  467. else if (!strcmp(argv[n], "-name")) {
  468. // handle show possible ROM functions commandline tag
  469. show_possible_functions = 1;
  470. }
  471. else if (!strcmp(argv[n], "-nolabels")) {
  472. // handle show possible ROM functions commandline tag
  473. no_labels = 1;
  474. }
  475. else if (argv[n][0] == '-') {
  476. fprintf(stderr,"ERROR: invalid option %s",argv[n]);
  477. return 1;
  478. }
  479. else if (!infile) infile = argv[n];
  480. else {
  481. PrintUsage();
  482. return 1;
  483. }
  484. }
  485. //---------------------------------------------------------------
  486. // some parameter validation checks
  487. //---------------------------------------------------------------
  488. if (!infile && !given_rom) {
  489. fprintf(stderr,"ERROR: neither file nor ROM is given\n");
  490. return 1;
  491. }
  492. if (infile && given_rom) {
  493. fprintf(stderr,"ERROR: cannot use file and ROM at the same time\n");
  494. return 1;
  495. }
  496. if (show_functions && infile) {
  497. fprintf(stderr,"WARNING: cannot show ROM functions (only possible with given ROM)\n");
  498. }
  499. //---------------------------------------------------------------
  500. // load ROM file if user had supplied a ROM filename
  501. //---------------------------------------------------------------
  502. if (given_rom) {
  503. if (!LoadROM(given_rom)) {
  504. fprintf(stderr,"/*[program terminated due to ROM loading error]*/\n");
  505. return 1;
  506. }
  507. InitMemoryPointers();
  508. romcalls_load(0);
  509. } else romcalls_load(1);
  510. //----------------------------------------------------
  511. // treat ROM disassembling
  512. //----------------------------------------------------
  513. if (given_rom) {
  514. if (show_functions) {
  515. uint32_t addr;
  516. int size;
  517. int i;
  518. romcalls_get_table_infos(&addr, (uint32_t *)&size);
  519. for(i = 0; i < size; i++) {
  520. const char *name = romcalls_get_name(i);
  521. addr = romcalls_get_addr(i);
  522. printf("%06x (%07d) %s\n",addr,addr,name);
  523. }
  524. CleanupROM();
  525. return 0;
  526. }
  527. if (given_offset == -1 || given_length == -1) {
  528. fprintf(stderr,"ERROR: please specify offset and length\n");
  529. CleanupROM();
  530. return 1;
  531. }
  532. if (!(data = malloc(given_length+20))) {
  533. fprintf(stderr,"ERROR: cannot allocate %d bytes\n",given_length+20);
  534. CleanupROM();
  535. return 1;
  536. }
  537. for (n=0;n<given_length;n++) data[n] = hw_get_byte(given_offset+n);
  538. abs_labels_start = given_offset + virtual_offset;
  539. abs_labels_len = given_length;
  540. Disassemble(data,given_length,given_offset,virtual_offset,show_possible_functions);
  541. if (label_list) free(label_list);
  542. CleanupROM();
  543. free(data);
  544. return 0;
  545. }
  546. //----------------------------------------------------
  547. // if we'll come here user wants to disassemble a file
  548. //----------------------------------------------------
  549. entry_point = virtual_offset;
  550. if (!(ifp = fopen(infile,"rb"))) {
  551. fprintf(stderr,"ERROR: cannot open inputfile %s\n",infile);
  552. if (given_rom) CleanupROM();
  553. return 1;
  554. }
  555. if (!vti && !raw) {
  556. memset(sig,0,9);
  557. if (fread(sig,1,8,ifp) < 8) {
  558. fprintf(stderr,"ERROR: read error\n");
  559. fclose(ifp);
  560. if (given_rom) CleanupROM();
  561. return 1;
  562. }
  563. if (strcmp(sig,SIGNATURE_TI89) && strcmp(sig,SIGNATURE_TI92P)) {
  564. fprintf(stderr,"ERROR: neither TI89 nor TI92p executable\n");
  565. fclose(ifp);
  566. if (given_rom) CleanupROM();
  567. return 1;
  568. }
  569. }
  570. fseek(ifp,0,SEEK_END);
  571. length = ftell(ifp);
  572. if (vti) {
  573. length -= 0x100;
  574. if (given_offset != -1 && given_offset >= 256000) {
  575. fprintf(stderr,"ERROR: given offset is too large (%d >= 256000)\n",given_offset);
  576. fclose(ifp);
  577. if (given_rom) CleanupROM();
  578. return 1;
  579. }
  580. if (length < 256000+0x100) {
  581. fprintf(stderr,"ERROR: given file no valid VTI save file (too short)\n");
  582. fclose(ifp);
  583. if (given_rom) CleanupROM();
  584. return 1;
  585. }
  586. }
  587. else {
  588. if (!raw) {
  589. length -= 90; // 86 bytes for header + 2 bytes for length + 2 bytes for trailing checksum
  590. }
  591. if (given_offset != -1 && given_offset >= length) {
  592. fprintf(stderr,"ERROR: given offset is too large (%d >= %d)\n",given_offset,length);
  593. fclose(ifp);
  594. if (given_rom) CleanupROM();
  595. return 1;
  596. }
  597. if (given_length != -1 && given_length >= length) {
  598. fprintf(stderr,"ERROR: given length is too large (%d >= %d)\n",given_length,length);
  599. fclose(ifp);
  600. if (given_rom) CleanupROM();
  601. return 1;
  602. }
  603. }
  604. rewind(ifp);
  605. if (!raw) {
  606. if (vti) fseek(ifp,0x100,SEEK_SET);
  607. else fseek(ifp,88,SEEK_SET);
  608. }
  609. if (!(data = malloc(length+20))) {
  610. fprintf(stderr,"ERROR: cannot allocate %d bytes\n",length+20);
  611. fclose(ifp);
  612. if (given_rom) CleanupROM();
  613. return 1;
  614. }
  615. memset(data,0,length+20);
  616. if (fread(data,1,length,ifp) < (size_t) length) {
  617. fprintf(stderr,"ERROR: read error\n");
  618. fclose(ifp);
  619. return 1;
  620. }
  621. fclose(ifp);
  622. if (given_length != -1) length = given_length;
  623. if (given_offset == -1) given_offset = 0;
  624. if (stub) OutputStubDetails(data+given_offset);
  625. Disassemble(data+given_offset,length,given_offset,virtual_offset,show_possible_functions);
  626. if (label_list) free(label_list);
  627. if (given_rom) CleanupROM();
  628. free(data);
  629. return 0;
  630. }