home *** CD-ROM | disk | FTP | other *** search
/ messroms.de / 2007-01-13_www.messroms.de.zip / VZ200 / TOOLS / DZ80.ZIP / dz80.c < prev    next >
C/C++ Source or Header  |  1999-12-11  |  10KB  |  420 lines

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include "z80.h"
  6. #include "dis.h"
  7.  
  8. #define CGENIE    0
  9.  
  10. BYTE mem[0x10000];   // memory image
  11.  
  12. static BOOL flg_dump = 1;
  13. static BOOL flg_cassette = 0;
  14. static BOOL flg_blkinfo = 0;
  15. static BOOL flg_dos_def = 0;
  16. static BOOL flg_colcom = 0;
  17. static WORD dis_offset = 0x0000;
  18. static WORD dis_beg_addr = 0xFFFF;
  19. static WORD dis_end_addr = 0x0000;
  20. static WORD dis_run_addr = 0x0000;
  21. static int dis_line_cnt = 0;
  22. static int dis_line_max = 0x7FFFFFFF;
  23. static char * inp_filename = NULL;
  24. static char * out_filename = NULL;
  25. static char def_filename[160];
  26. static FILE * dis_inp_file = NULL;
  27. static FILE * dis_out_file = NULL;
  28.  
  29. BOOL dis_output(char * src)
  30. {
  31.     while (*src)
  32.     {
  33.         if (*src == '\n')
  34.         {
  35.             if (++dis_line_cnt >= dis_line_max)
  36.                 return 1;
  37.         }
  38.         fputc(*src, dis_out_file);
  39.         src++;
  40.     }
  41.     fputc('\n', dis_out_file);
  42.     if (++dis_line_cnt >= dis_line_max)
  43.         return 1;
  44.     return 0;
  45. }
  46.  
  47. void dis_range(WORD beg, WORD end)
  48. {
  49.     WORD addr = beg;
  50.     WORD old;
  51.     do
  52.     {
  53.         old = addr;
  54.         if (dis_output(disasm(&addr, flg_dump)))
  55.             return;
  56.     } while( addr >= old && addr <= end );
  57. }
  58.  
  59. int main(int ac, char ** av)
  60. {
  61.     int i;
  62.     char * dst;
  63.  
  64.     if( ac < 2 )
  65.     {
  66.         fprintf(stderr, "usage: dz80 [-a|-c|-i|-o xxxx] inputfile [outputfile]\n");
  67.         fprintf(stderr, "options:\n");
  68.         fprintf(stderr, "\t-a\tASM output (no addr/data columns)\n");
  69. #if CGENIE
  70.         fprintf(stderr, "\t-c\tfile is in .CAS format\n");
  71. #else
  72.         fprintf(stderr, "\t-v\tfile is in .VZ format\n");
  73. #endif
  74.         fprintf(stderr, "\t-i\tprint block info\n");
  75.         fprintf(stderr, "\t-o\tload from offset xxxx\n");
  76.         fprintf(stderr, "\t-j\tDEF file options\n");
  77.         fprintf(stderr, "\t-jd\tinclude CGDOS.DEF\n");
  78.         fprintf(stderr, "\t-jc\tfile is Colour Compiler output\n");
  79.         exit(1);
  80.     }
  81.  
  82.     for (i = 1; i < ac; i++)
  83.     {
  84.         if (av[i][0] == '-')
  85.         {
  86.             switch (av[i][1])
  87.             {
  88.                 case 'a': case 'A':
  89.                     flg_dump = 0;
  90.                     break;
  91. #if CGENIE
  92.                 case 'c': case 'C':
  93.                     flg_cassette = 1;
  94.                     break;
  95. #else
  96.                 case 'v': case 'V':
  97.                     flg_cassette = 1;
  98.                     break;
  99. #endif
  100.                 case 'i': case 'I':
  101.                     flg_blkinfo = 1;
  102.                     break;
  103.                 case 'j': case 'J':
  104.                     if (toupper(av[i][2]) == 'C')
  105.                         flg_colcom = 1;
  106.                     if (toupper(av[i][2]) == 'D')
  107.                         flg_dos_def  = 1;
  108.                     break;
  109.                 case 'o': case 'O':
  110.                     i++;
  111.                     dis_offset = hextoi(av[i]);
  112.                     dis_run_addr = dis_offset;
  113.                     break;
  114.                 default:
  115.                     fprintf(stderr, "unknown option %x\n", av[i][1]);
  116.                     exit(1);
  117.                     break;
  118.             }
  119.         }
  120.         else
  121.         {
  122.             if (!inp_filename)
  123.                 inp_filename = av[i];
  124.             else
  125.             if (!out_filename)
  126.                 out_filename = av[i];
  127.         }
  128.     }
  129.  
  130.     if (!inp_filename)
  131.     {
  132.         fprintf(stderr, "no input filename given\n");
  133.         exit(1);
  134.     }
  135.  
  136.     dis_inp_file = fopen(inp_filename, "rb");
  137.     if (!dis_inp_file)
  138.     {
  139.         fprintf(stderr, "input file %s not found\n", inp_filename);
  140.         exit(1);
  141.     }
  142.         
  143.     if (out_filename)
  144.     {
  145.         dis_out_file = fopen(out_filename, "wa");
  146.         if (!dis_out_file)
  147.         {
  148.             fprintf(stderr, "can't create output file %s\n", out_filename);
  149.             exit(1);
  150.         }
  151.     }
  152.     else
  153.     {
  154.         dis_out_file = stdout;
  155.     }
  156.  
  157. #if CGENIE
  158.     if( flg_cassette )
  159.     {
  160.         WORD cnt;
  161.         WORD addr;
  162.         BYTE sum;
  163.         BYTE c;
  164.         if( (c = fgetc(dis_inp_file)) != 0x66 )
  165.         {
  166.             fprintf(stderr, "file seems to be no .CAS file (0000:%02X != 66)\n", c);
  167.             exit(1);
  168.         }
  169.         if( (c = fgetc(dis_inp_file)) != 0x55 )
  170.         {
  171.             fprintf(stderr, "file seems to be no machine code .CAS file (0001:%02X != 55)\n", c);
  172.             exit(1);
  173.         }
  174.         for( i = 0; i < 6; i++ )
  175.         {
  176.             if (!isalnum(c = fgetc(dis_inp_file)) && (c != ' '))
  177.             {
  178.                 fprintf(stderr, "file seems to be no machine code .CAS file (%04X:%02X)\n", (int)ftell(dis_inp_file) - 1, c);
  179.                 exit(1);
  180.             }
  181.         }
  182.         while( !feof(dis_inp_file) )
  183.         {
  184.             c = fgetc(dis_inp_file);
  185.             if (c == 0x78)
  186.             {
  187.                 c    = fgetc(dis_inp_file);
  188.                 addr = c;
  189.                                 c    = fgetc(dis_inp_file);
  190.                 addr += 256 * c;
  191.                 dis_run_addr = addr;
  192.                 if (flg_blkinfo)
  193.                     printf("entry point is %04X\n", addr);
  194. #if 0
  195.                 if (!feof(dis_inp_file))
  196.                 {
  197.                     if (flg_blkinfo)
  198.                         printf("reading excess data at %04X\n", (int) ftell(dis_inp_file));
  199.                     while( !feof(dis_inp_file) )
  200.                         c = fgetc(dis_inp_file);
  201.                 }
  202. #else
  203.                 break;
  204. #endif
  205.                 continue;
  206.             }
  207.             if (c != 0x3C)
  208.             {
  209.                 fprintf(stderr, "expected block header 3C (%04X:%02X)\n", (int)ftell(dis_inp_file) - 1, c);
  210.                 exit(1);
  211.             }
  212.             cnt  = fgetc(dis_inp_file);
  213.             if (!cnt)
  214.                 cnt = 256;
  215.             sum  = 0;
  216.             c    = fgetc(dis_inp_file);
  217.             sum += c;
  218.             addr = c;
  219.             c    = fgetc(dis_inp_file);
  220.             sum += c;
  221.             addr+= 256 * c;
  222.             if( addr < dis_beg_addr )
  223.                 dis_beg_addr = addr;
  224.             if (flg_blkinfo)
  225.                 printf("loading %3d bytes to %04X\n", cnt, addr);
  226.             while (cnt-- > 0)
  227.             {
  228.                 c = fgetc(dis_inp_file);
  229.                 sum += c;
  230.                 mem[addr++] = c;
  231.             }
  232.             if (addr > dis_end_addr)
  233.                 dis_end_addr = addr;
  234.             c = fgetc(dis_inp_file);
  235.             if (c != sum)
  236.             {
  237.                 fprintf(stderr, "bad block checksum (%04X:%02X != %02X)\n", (int)ftell(dis_inp_file) - 1, c, sum);
  238.                                 exit(1);
  239.             }
  240.         }
  241.         if( mem[dis_run_addr]     == 0xf3 &&   // DI
  242.             mem[dis_run_addr+1]  == 0x21 &&   // LD   HL,....
  243.             mem[dis_run_addr+4]  == 0x11 &&   // LD   DE,....
  244.             mem[dis_run_addr+7]  == 0x01 &&   // LD   BC,....
  245.             mem[dis_run_addr+10] == 0xed &&   // LDIR
  246.             mem[dis_run_addr+11] == 0xb0 &&
  247.             mem[dis_run_addr+12] == 0xc3 )      // JP   xxxx
  248.         {
  249.             WORD    src = *(WORD*)&mem[dis_run_addr+2];
  250.             WORD    dst = *(WORD*)&mem[dis_run_addr+5];
  251.             WORD    cnt = *(WORD*)&mem[dis_run_addr+8];
  252.             if (flg_blkinfo)
  253.                 printf("DOS offset loader at: %04X\n", dis_run_addr);
  254.             dis_run_addr  = *(WORD*)&mem[dis_run_addr+13];
  255.             memmove(mem + dst, mem + src, cnt);
  256.             dis_beg_addr += dst - src;
  257.             dis_end_addr += dst - src;
  258.             if (flg_blkinfo)
  259.                 printf("real start:%04X, end:%04X, entry:%04X\n", dis_beg_addr, dis_end_addr, dis_run_addr);
  260.         }
  261.     }
  262. #else    /* CGENIE */
  263.     if( flg_cassette )
  264.     {
  265.         WORD addr;
  266.         BYTE c;
  267.         int basic = 0;
  268.  
  269.         if( (c = fgetc(dis_inp_file)) != ' ' && c != 'V' )
  270.         {
  271.             fprintf(stderr, "file seems to be no .VZ file (0000:%02X != 20/56)\n", c);
  272.             exit(1);
  273.         }
  274.         if( (c = fgetc(dis_inp_file)) != ' ' && c != 'Z' )
  275.         {
  276.             fprintf(stderr, "file seems to be no .VZ file (0001:%02X != 20/5A)\n", c);
  277.             exit(1);
  278.         }
  279.         if( (c = fgetc(dis_inp_file)) != 0x00 && c != 'F' )
  280.         {
  281.             fprintf(stderr, "file seems to be no .VZ file (0002:%02X != 00/46)\n", c);
  282.             exit(1);
  283.         }
  284.         if( (c = fgetc(dis_inp_file)) != 0x00 && c != '0' )
  285.         {
  286.             fprintf(stderr, "file seems to be no .VZ file (0003:%02X != 00/30)\n", c);
  287.             exit(1);
  288.         }
  289.         for( i = 0; i < 17; i++ )
  290.         {
  291.             if( !isalnum(c = fgetc(dis_inp_file)) && (c != ' ') && (c != 0x00) )
  292.             {
  293.                 fprintf(stderr, "file seems to be no .VZ file (%04X:%02X)\n", (int)ftell(dis_inp_file) - 1, c);
  294.                 exit(1);
  295.             }
  296.         }
  297.         if( (c = fgetc(dis_inp_file)) != 0xf0 && c != 0xf1 )
  298.         {
  299.             fprintf(stderr, "file seems to be no .VZ file (%04X:%02X != 00/30)\n", (int)ftell(dis_inp_file) - 1, c);
  300.             exit(1);
  301.         }
  302.         basic = (c == 0xf0);
  303.  
  304.         addr = fgetc(dis_inp_file);
  305.         addr += 256 * fgetc(dis_inp_file);
  306.         dis_beg_addr = addr;
  307.         dis_run_addr = addr;
  308.         dis_end_addr = addr;
  309.         if( flg_blkinfo )
  310.             printf("entry point is %04X\n", addr);
  311.         while( !feof(dis_inp_file) )
  312.         {
  313.             c = fgetc(dis_inp_file);
  314.             mem[addr++] = c;
  315.         }
  316.         if( flg_blkinfo )
  317.             printf("end address is %04X\n", addr);
  318.         if( addr > dis_end_addr )
  319.             dis_end_addr = addr;
  320.         if( dis_offset == 0 )
  321.             dis_offset = dis_beg_addr;
  322.     }
  323. #endif
  324.     else
  325.     {
  326.         dis_beg_addr = dis_offset;
  327.         while( !feof(dis_inp_file) )
  328.         {
  329.             int cnt = fread(mem + dis_offset, 1, 0x10000 - dis_offset, dis_inp_file);
  330.             if (dis_beg_addr + cnt - 1 > dis_end_addr)
  331.                 dis_end_addr = dis_beg_addr + cnt - 1;
  332.             dis_offset = 0;
  333.         }
  334.     }
  335.  
  336. #if CGENIE
  337.     DEF_file_read("cgenie.def");
  338.     if (flg_dos_def)        /* include colour genie dos symbols? */
  339.         DEF_file_read("cgdos.def");
  340.     if( flg_colcom )        /* colour compiler output ? */
  341.     {
  342.         WORD data;
  343.         WORD strs;
  344.         WORD code;
  345.         char strname[6+1] = "str000";
  346.         char strchr = 0;
  347.         int strcnt = 0;
  348.         int i;
  349.  
  350.         dis_run_addr = 0x7C02;
  351.         DEF_file_read("colcom.def");
  352.  
  353.         if (*(WORD*)&mem[0x4802] != 0x4804)
  354.         {
  355.             dis_beg_addr = 0x5800;
  356.             code = *(WORD*)&mem[0x7FBF];
  357.             memcpy(mem + 0x5800, mem + 0x7380, 0x880);
  358.             memset(mem + 0x7380, 0, 0x800);
  359.         }
  360.         else
  361.         {
  362.             code = *(WORD*)&mem[0x7FBC];
  363.             dis_beg_addr = 0x4800;
  364.         }
  365.  
  366.         data = *(WORD*)&mem[0x7FB5];
  367.         OPT_def(data, MEM_DATA, 1, OPT_WORDS);
  368.         SYM_add(data, SYM_DATA, "__DATA");
  369.  
  370.         strs = *(WORD*)&mem[0x7FB3];
  371.         OPT_def(strs, MEM_DATA, 0, OPT_ASCII);
  372.  
  373.         strchr = 0;
  374.         strcnt = 0;
  375.         for (i = strs; i < code; i++)
  376.         {
  377.             if ((strchr == 0) && (strcnt < 500))
  378.             {
  379.                 sprintf(strname, "__STR%03d", strcnt++);
  380.                 SYM_add(i, SYM_DATA, strname);
  381.             }
  382.             strchr = mem[i];
  383.         }
  384.  
  385.         OPT_def(code, MEM_CODE, 0, OPT_NONE);
  386.         SYM_add(code, SYM_CODE, "__LINE1");
  387.     }
  388. #else
  389.     DEF_file_read("vzrom.def");
  390.     if( flg_dos_def )        /* include VZ dos symbols? */
  391.         DEF_file_read("vzdos.def");
  392. #endif
  393.  
  394.     strcpy(def_filename, inp_filename);
  395.     dst = strrchr(def_filename, '.');
  396.     if (!dst)
  397.         strcat(def_filename, ".def");
  398.     else
  399.         strcpy(dst, ".def");
  400.  
  401.     DEF_file_read(def_filename);
  402.     dst = strrchr(def_filename, '\\');
  403.     if (!dst)
  404.         dst = strrchr(def_filename, '/');
  405.     if (dst)
  406.     {
  407.         strcpy(def_filename, dst + 1);
  408.         DEF_file_read(def_filename);
  409.     }
  410.  
  411.     disasm_init(dis_beg_addr);
  412.  
  413.     SYM_add(dis_run_addr, SYM_CODE, "ENTRY");
  414.  
  415.     dis_range(dis_beg_addr, dis_end_addr);
  416.  
  417.     return 0;
  418. }
  419.  
  420.