123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719 |
- /*
- dasm-tigcc - Disassembler for TI calculators
- Copyright (C) 2000-2002 Thomas Nussbaumer
- Copyright (C) 2005 Lionel Debroux
- Copyright (C) 2007 Kevin Kofler
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
- /* The code in this file is based on ttdasm, but with the VTI-derived code
- removed. Calls to VTI functions have been replaced with calls to the
- equivalent TiEmu functions. */
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include "main.h"
- #include "tt.h"
- #include "ti68k_def.h"
- #include "images.h"
- #include "timem.h"
- #include "mem.h"
- #include "romcalls.h"
- #include "disasm.h"
- //=============================================================================
- // outputs usage information of this tool
- //=============================================================================
- void PrintUsage() {
- fprintf(USAGE_OUT, "dasm-tigcc 1.00 - Disassembler for TI calculators\n\n" \
- "Copyright (C) 2000-2002 Thomas Nussbaumer\n" \
- "Copyright (C) 2005 Lionel Debroux\n" \
- "Copyright (C) 2007 Kevin Kofler\n" \
- "Portions (GDB) Copyright (C) 1986-2007 Free Software Foundation\n" \
- "Portions (TiEmu) Copyright (C) 2000-2007 Romain Lievin et. al.\n" \
- "Portions (ld-tigcc) Copyright (C) 2002-2004 Sebastian Reichelt\n\n" \
- "This program is free software; you may redistribute it under the\n" \
- "terms of the the GNU General Public License. There is NO warranty;\n" \
- "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"\
- "Usage: dasm-tigcc [flags] [<infile>]\n\n" \
- " -o <number> ... use given offset as start point\n" \
- " -l <bytes> ... disassemble number of given bytes\n" \
- " -r <romfile> ... disassemble given rom file\n" \
- " -f ... show ROM function table\n" \
- " -name ... show possible ROM calls\n" \
- " -virtual <number> ... use additionally virtual offset\n" \
- " -nolabels ... use no labels in output\n" \
- " -raw ... treat file as raw binary\n" \
- " -vti ... treat file as VTI save file\n" \
- " -stub ... prints additionally information of\n" \
- " kernel based programs\n\n" \
- " disassembles a TI89/TI92plus NOSTUB executable,\n" \
- " a TI89/TI92plus raw dump,parts of a given ROM file or\n" \
- " a VTI save file.\n\n" \
- " NOTE1: the offset and the length can be specified as\n" \
- " hex numbers, too (for example: -o 0x4c)\n\n" \
- " NOTE2: offsets are not treated as pure file offsets,\n" \
- " but are handled depending on the target.\n" \
- " Within executables offset 0 starts at file offset\n" \
- " 88 which is just behind the header and the length\n" \
- " information. Offsets within ROM files maps\n" \
- " directly to the real addresses within the calculator.\n\n");
- }
- int calc_type;
- unsigned char* rom;
- unsigned char* ram;
- int initialPC;
- int initIntTabOfs;
- unsigned char* mem[256];
- unsigned char unused[0x10000];
- int label_parse = 0;
- int no_labels = 0;
- uint32_t rom_base;
- uint32_t rom_size;
- uint32_t ram_size;
- uint32_t entry_point;
- static uint32_t abs_labels_start = 0;
- static uint32_t abs_labels_len = 0;
- #define GET_WORD(m) ((unsigned short)((((m)[0]) << 8) + ((m)[1])))
- uint32_t* label_list = NULL;
- int label_count = 0;
- int labels_allocated = 0;
- #define LABEL_ALLOC_STEP 10
- //=============================================================================
- // adds a label to the list
- //=============================================================================
- int AddLabel(uint32_t address) {
- int i = -1;
- if (label_count != 0) {
- for (i=0;i<label_count;i++) if (label_list[i] == address) return 1;
- }
- if (label_count == labels_allocated) {
- uint32_t* tmp = (uint32_t*)realloc(label_list,(labels_allocated+LABEL_ALLOC_STEP)*sizeof(uint32_t));
- if (!tmp) {
- label_parse = 0;
- return 0;
- }
- label_list = tmp;
- labels_allocated+=LABEL_ALLOC_STEP;
- }
- label_list[label_count++] = address;
- return 1;
- }
- //=============================================================================
- // adds a label to the list
- //=============================================================================
- char label_name[200];
- char* GetLabel(uint32_t address) {
- int i = -1;
- if (no_labels) return NULL;
- if (label_count != 0) {
- for (i=0;i<label_count;i++) if (label_list[i] == address) break;
- }
- if (i != label_count && i != -1) {
- sprintf(label_name,"__L%lX",(unsigned long)label_list[i]);
- return label_name;
- }
- return NULL;
- }
- void PrintAddress (int32_t reladdr, uint32_t absaddr, int flags, void *stream,
- void (*fprintf_f) (void *, const char *, ...),
- void (*fputs_f) (const char *, void *))
- {
- if ((flags & 4) && !(absaddr >= abs_labels_start && absaddr < abs_labels_start + abs_labels_len)) {
- fprintf_f(stream, "0x%lX", (unsigned long) absaddr);
- return;
- }
- if (label_parse) {
- AddLabel(absaddr);
- } else {
- char *s = GetLabel(absaddr);
- if (!s) {
- if (flags & 1) {
- if (reladdr < 0)
- fprintf_f(stream, ".-0x%X", (int) -reladdr);
- else
- fprintf_f(stream, ".+0x%X", (int) reladdr);
- } else {
- if (reladdr < 0)
- fprintf_f(stream, "-0x%X", (int) -reladdr);
- else
- fprintf_f(stream, "0x%X", (int) reladdr);
- }
- } else {
- fprintf_f(stream, "%s", s);
- if (flags & 2)
- fputs_f("-.", stream);
- }
- }
- }
- static void PrintROMInfo(IMG_INFO *info) {
- switch (info->calc_type) {
- case TI92: printf("TI92 "); break;
- case TI89: printf("TI89 "); break;
- case TI92p: printf("TI92p "); break;
- case V200: printf("V200 "); break;
- case TI89t: printf("TI89t "); break;
- }
- if (info->calc_type==TI92 && info->rom_base==0x20) printf("INTERNAL ");
- if (!info->has_boot) printf("UPDATE ");
- if (!info->flash==FLASH_ROM) printf("FLASHROM ");
- }
- //=============================================================================
- // frees buffers used for ROM
- //=============================================================================
- void CleanupROM() {
- if (rom) free(rom);
- if (ram) free(ram);
- rom = 0;
- }
- //=============================================================================
- // load a ROM file
- //=============================================================================
- int LoadROM(char* filename) {
- IMG_INFO info;
- rom = (unsigned char*)malloc(4096*1024+3);
- ram = (unsigned char*)malloc(256*1024+3);
- if (!rom || !ram) {
- CleanupROM();
- fprintf(stderr,"ERROR: cannot allocate memory for ROM\n");
- return 0;
- }
- memset(rom,0xff,4096*1024+3);
- if (ti68k_is_a_rom_file(filename)) {
- if (ti68k_get_rom_infos(filename,&info,1)) return 0;
- printf("/*[ ");PrintROMInfo(&info);printf("]*/\n");
- } else if (ti68k_is_a_tib_file(filename)) {
- if (ti68k_get_tib_infos(filename,&info,1)) return 0;
- printf("/*[ ");PrintROMInfo(&info);printf("]*/\n");
- } else if (ti68k_is_a_img_file(filename)) {
- if (ti68k_load_image(filename,&info)) return 0;
- printf("/*[ ");PrintROMInfo(&info);printf("]*/\n");
- } else {
- fprintf(stderr,"ERROR: invalid ROM filename %s (neither .ROM nor .TIB nor .IMG)\n",filename);
- CleanupROM();
- return 0;
- }
- calc_type = info.calc_type;
- if (info.has_boot)
- memcpy(rom,info.data,info.size);
- else
- ti68k_convert_tib_to_image(&info,rom);
- rom_base = info.rom_base << 16;
- rom_size = info.size;
- ram_size = (rom_size==1024*1024)?0x100000:0x200000;
- if (info.flash==FLASH_ROM) {
- initialPC = rd_long(&rom[0x1208c]);
- initIntTabOfs = 0x12088;
- }
- else {
- initialPC = rd_long(&rom[4]);
- initIntTabOfs = 0;
- }
- free(info.data);
- printf("/*[initialPC = 0x%x (%d)]*/\n",initialPC,initialPC);
- printf("/*[initIntTabOfs = 0x%x (%d)]*/\n\n",initIntTabOfs,initIntTabOfs);
- return 1;
- }
- //=============================================================================
- // initialize memory pointers
- //=============================================================================
- void InitMemoryPointers() {
- memset(ram, 0, 0x40000);
- memcpy(ram, rom+initIntTabOfs, 256);
- memset(unused, 0x14, 0x10000);
- hw_mem_init();
- }
- static const char* offsetname_ptr;
- //=============================================================================
- // helper function for disassembling engine
- //=============================================================================
- void Offset2Name(int addr) {
- offsetname_ptr = (romcalls_is_loaded() && !(addr & 3)
- && addr < (NMAX_ROMCALLS << 2))
- ? romcalls_get_name(addr >> 2) : 0;
- }
- //=============================================================================
- // disassemble given buffer until length bytes are processed
- // the given offset is used just for the address output in the comment
- //=============================================================================
- void Disassemble(unsigned char* mem,int length,int used_offset,
- int virtual_offset,int show_possible)
- {
- char buffer[1024];
- int start = 0;
- int bytes;
- int i;
- //printf("starting ...\n");
- if (!no_labels) {
- label_parse=1;
- while (start < length) {
- bytes = Dasm68000(mem+start,buffer,start+used_offset+virtual_offset);
- if (!label_parse) {
- printf("ERROR: OUT-OF-MEMORY - cannot add that much levels\n");
- return;
- }
- start+=bytes;
- }
- start = 0;
- label_parse = 0;
- }
- printf("asm(\"\n");
- while (start < length) {
- if (!no_labels) {
- char* s = GetLabel(start+used_offset+virtual_offset);
- if (s) printf("%s:\n",s);
- }
- offsetname_ptr = 0;
- bytes = Dasm68000(mem+start,buffer,start+used_offset+virtual_offset);
- printf("%s",buffer);
- for (i=strlen(buffer);i<30;i++) printf(" ");
- printf("/* [0x%X (%u)] ",start+used_offset+virtual_offset,start+used_offset+virtual_offset);
- for (i=0;i<bytes;i++) printf("%02x ",*(mem+start+i));
- for (i=bytes;i<6;i++) printf(" ");
- if (show_possible) {
- if (offsetname_ptr) printf("?%s? */\n",offsetname_ptr);
- else printf("*/\n");
- }
- else {
- printf("*/\n");
- }
- start+=bytes;
- }
- printf("\");\n");
- }
- //=============================================================================
- // outputs header details of kernel-based programs or libraries
- //=============================================================================
- void OutputStubDetails(unsigned char* mem) {
- int i,offset,count;
- printf("******** STUB-HEADER INFO *********\n");
- if ((!strncmp((char*)(mem+4),"68kP",4)) || (!strncmp((char*)(mem+4),"68kL",4))) {
- printf("signature: %c%c%c%c\n",*(mem+4),*(mem+5),*(mem+6),*(mem+7));
- printf("relcount: %d\n",GET_WORD(mem+8));
- printf("offset comment: 0x%04x\n",GET_WORD(mem+0xa));
- printf("offset main: 0x%04x\n",GET_WORD(mem+0xc));
- printf("offset exit: 0x%04x\n",GET_WORD(mem+0xe));
- printf("compatiblity: 0x%04x\n",GET_WORD(mem+0x10));
- printf("offset BSS: 0x%04x\n",GET_WORD(mem+0x14));
- offset = GET_WORD(mem+0x16);
- printf("offset export: 0x%04x\n",offset);
- printf("offset RAM table: 0x%04x\n",GET_WORD(mem+0x18));
- printf("********* EXPORT TABLE ************\n");
- count = GET_WORD(mem+offset);
- for (i=0;i<count;i++) printf("export@%04x: 0x%04x\n",i,GET_WORD(mem+offset+2+i*2));
- }
- else {
- printf("--- not found --- (missing 68kP or 68kL)\n");
- }
- }
- //=============================================================================
- // its a main ...
- //=============================================================================
- int main(int argc,char *argv[]) {
- char* infile = 0;
- FILE* ifp;
- char sig[9];
- int length;
- unsigned char* data;
- int n;
- int given_offset = -1;
- int given_length = -1;
- char* given_rom = 0;
- int show_functions = 0;
- int show_possible_functions = 0;
- int virtual_offset = 0;
- int raw = 0;
- int vti = 0;
- int stub = 0;
- //---------------------------------------------------------------
- // check for too less arguments
- //---------------------------------------------------------------
- if (argc < 2) {
- PrintUsage();
- return 1;
- }
- printf("/* Disassembled with dasm-tigcc\n\n"
- " Copyright (C) 2000-2002 Thomas Nussbaumer\n"
- " Copyright (C) 2005 Lionel Debroux\n"
- " Copyright (C) 2007 Kevin Kofler\n"
- " Portions (GDB) Copyright (C) 1986-2007 Free Software Foundation\n"
- " Portions (TiEmu) Copyright (C) 2000-2007 Romain Lievin et. al.\n"
- " Portions (ld-tigcc) Copyright (C) 2002-2004 Sebastian Reichelt */\n\n");
- //---------------------------------------------------------------
- // parse commandline arguments
- //---------------------------------------------------------------
- for (n=1; n<argc; n++) {
- if (!strcmp(argv[n], "-o")) {
- // handle offset commandline tag
- if (n == argc -1) {
- PrintUsage();
- return 1;
- }
- else {
- if (!strncmp(argv[n+1],"0x",2)) {
- if (sscanf(&argv[n+1][2],"%x",&given_offset) != 1) {
- PrintUsage();
- return 1;
- }
- }
- else {
- if (sscanf(argv[n+1],"%d",&given_offset) != 1) {
- PrintUsage();
- return 1;
- }
- }
- if (given_offset<0) {
- fprintf(stderr,"ERROR: offset cannot be negative\n");
- return 1;
- }
- n++;
- }
- }
- else if (!strcmp(argv[n], "-virtual")) {
- // handle virtual offset commandline tag
- if (n == argc -1) {
- PrintUsage();
- return 1;
- }
- else {
- if (!strncmp(argv[n+1],"0x",2)) {
- if (sscanf(&argv[n+1][2],"%x",&virtual_offset) != 1) {
- PrintUsage();
- return 1;
- }
- }
- else {
- if (sscanf(argv[n+1],"%d",&virtual_offset) != 1) {
- PrintUsage();
- return 1;
- }
- }
- if (virtual_offset<0) {
- fprintf(stderr,"ERROR: offset cannot be negative\n");
- return 1;
- }
- n++;
- }
- }
- else if (!strcmp(argv[n], "-l")) {
- // handle length commandline tag
- if (n == argc -1) {
- PrintUsage();
- return 1;
- }
- else {
- if (!strncmp(argv[n+1],"0x",2)) {
- if (sscanf(&argv[n+1][2],"%x",&given_length) != 1) {
- PrintUsage();
- return 1;
- }
- }
- else {
- if (sscanf(argv[n+1],"%d",&given_length) != 1) {
- PrintUsage();
- return 1;
- }
- }
- if (given_length<0) {
- fprintf(stderr,"ERROR: length cannot be negative\n");
- return 1;
- }
- n++;
- }
- }
- else if (!strcmp(argv[n], "-r")) {
- // handle romfile commandline tag
- if (n == argc -1) {
- PrintUsage();
- return 1;
- }
- else {
- given_rom = argv[n+1];
- n++;
- }
- }
- else if (!strcmp(argv[n], "-f")) {
- // handle show ROM functions commandline tag
- show_functions = 1;
- }
- else if (!strcmp(argv[n], "-vti")) {
- // handle show ROM functions commandline tag
- vti = 1;
- if (raw || given_rom) {
- fprintf(stderr,"ERROR: cannot use -vti with -r or -raw\n");
- return 1;
- }
- }
- else if (!strcmp(argv[n], "-stub")) {
- // shows additionally informations about kernel based programs
- stub = 1;
- }
- else if (!strcmp(argv[n], "-raw")) {
- // handle show ROM functions commandline tag
- raw = 1;
- if (vti || given_rom) {
- fprintf(stderr,"ERROR: cannot use -raw with -r or -vti\n");
- return 1;
- }
- }
- else if (!strcmp(argv[n], "-name")) {
- // handle show possible ROM functions commandline tag
- show_possible_functions = 1;
- }
- else if (!strcmp(argv[n], "-nolabels")) {
- // handle show possible ROM functions commandline tag
- no_labels = 1;
- }
- else if (argv[n][0] == '-') {
- fprintf(stderr,"ERROR: invalid option %s",argv[n]);
- return 1;
- }
- else if (!infile) infile = argv[n];
- else {
- PrintUsage();
- return 1;
- }
- }
- //---------------------------------------------------------------
- // some parameter validation checks
- //---------------------------------------------------------------
- if (!infile && !given_rom) {
- fprintf(stderr,"ERROR: neither file nor ROM is given\n");
- return 1;
- }
- if (infile && given_rom) {
- fprintf(stderr,"ERROR: cannot use file and ROM at the same time\n");
- return 1;
- }
- if (show_functions && infile) {
- fprintf(stderr,"WARNING: cannot show ROM functions (only possible with given ROM)\n");
- }
- //---------------------------------------------------------------
- // load ROM file if user had supplied a ROM filename
- //---------------------------------------------------------------
- if (given_rom) {
- if (!LoadROM(given_rom)) {
- fprintf(stderr,"/*[program terminated due to ROM loading error]*/\n");
- return 1;
- }
- InitMemoryPointers();
- romcalls_load(0);
- } else romcalls_load(1);
- //----------------------------------------------------
- // treat ROM disassembling
- //----------------------------------------------------
- if (given_rom) {
- if (show_functions) {
- uint32_t addr;
- int size;
- int i;
- romcalls_get_table_infos(&addr, (uint32_t *)&size);
- for(i = 0; i < size; i++) {
- const char *name = romcalls_get_name(i);
- addr = romcalls_get_addr(i);
- printf("%06x (%07d) %s\n",addr,addr,name);
- }
- CleanupROM();
- return 0;
- }
- if (given_offset == -1 || given_length == -1) {
- fprintf(stderr,"ERROR: please specify offset and length\n");
- CleanupROM();
- return 1;
- }
- if (!(data = malloc(given_length+20))) {
- fprintf(stderr,"ERROR: cannot allocate %d bytes\n",given_length+20);
- CleanupROM();
- return 1;
- }
- for (n=0;n<given_length;n++) data[n] = hw_get_byte(given_offset+n);
- abs_labels_start = given_offset + virtual_offset;
- abs_labels_len = given_length;
- Disassemble(data,given_length,given_offset,virtual_offset,show_possible_functions);
- if (label_list) free(label_list);
- CleanupROM();
- free(data);
- return 0;
- }
- //----------------------------------------------------
- // if we'll come here user wants to disassemble a file
- //----------------------------------------------------
- entry_point = virtual_offset;
- if (!(ifp = fopen(infile,"rb"))) {
- fprintf(stderr,"ERROR: cannot open inputfile %s\n",infile);
- if (given_rom) CleanupROM();
- return 1;
- }
- if (!vti && !raw) {
- memset(sig,0,9);
- if (fread(sig,1,8,ifp) < 8) {
- fprintf(stderr,"ERROR: read error\n");
- fclose(ifp);
- if (given_rom) CleanupROM();
- return 1;
- }
- if (strcmp(sig,SIGNATURE_TI89) && strcmp(sig,SIGNATURE_TI92P)) {
- fprintf(stderr,"ERROR: neither TI89 nor TI92p executable\n");
- fclose(ifp);
- if (given_rom) CleanupROM();
- return 1;
- }
- }
- fseek(ifp,0,SEEK_END);
- length = ftell(ifp);
- if (vti) {
- length -= 0x100;
- if (given_offset != -1 && given_offset >= 256000) {
- fprintf(stderr,"ERROR: given offset is too large (%d >= 256000)\n",given_offset);
- fclose(ifp);
- if (given_rom) CleanupROM();
- return 1;
- }
- if (length < 256000+0x100) {
- fprintf(stderr,"ERROR: given file no valid VTI save file (too short)\n");
- fclose(ifp);
- if (given_rom) CleanupROM();
- return 1;
- }
- }
- else {
- if (!raw) {
- length -= 90; // 86 bytes for header + 2 bytes for length + 2 bytes for trailing checksum
- }
- if (given_offset != -1 && given_offset >= length) {
- fprintf(stderr,"ERROR: given offset is too large (%d >= %d)\n",given_offset,length);
- fclose(ifp);
- if (given_rom) CleanupROM();
- return 1;
- }
- if (given_length != -1 && given_length >= length) {
- fprintf(stderr,"ERROR: given length is too large (%d >= %d)\n",given_length,length);
- fclose(ifp);
- if (given_rom) CleanupROM();
- return 1;
- }
- }
- rewind(ifp);
- if (!raw) {
- if (vti) fseek(ifp,0x100,SEEK_SET);
- else fseek(ifp,88,SEEK_SET);
- }
- if (!(data = malloc(length+20))) {
- fprintf(stderr,"ERROR: cannot allocate %d bytes\n",length+20);
- fclose(ifp);
- if (given_rom) CleanupROM();
- return 1;
- }
- memset(data,0,length+20);
- if (fread(data,1,length,ifp) < (size_t) length) {
- fprintf(stderr,"ERROR: read error\n");
- fclose(ifp);
- return 1;
- }
- fclose(ifp);
- if (given_length != -1) length = given_length;
- if (given_offset == -1) given_offset = 0;
- if (stub) OutputStubDetails(data+given_offset);
- Disassemble(data+given_offset,length,given_offset,virtual_offset,show_possible_functions);
- if (label_list) free(label_list);
- if (given_rom) CleanupROM();
- free(data);
- return 0;
- }
|