home *** CD-ROM | disk | FTP | other *** search
/ messroms.de / 2007-01-13_www.messroms.de.zip / CGENIE / TOOLS / DZ80.ZIP / dz80.c < prev    next >
C/C++ Source or Header  |  1999-12-09  |  10KB  |  410 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    1
  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_cgdos = 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_cgdos  = 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.  
  268.         if( (c = fgetc(dis_inp_file)) != ' ' )
  269.         {
  270.             fprintf(stderr, "file seems to be no machine code .VZ file (0000:%02X != 20)\n", c);
  271.             exit(1);
  272.         }
  273.         if( (c = fgetc(dis_inp_file)) != ' ' )
  274.         {
  275.             fprintf(stderr, "file seems to be no machine code .VZ file (0001:%02X != 20)\n", c);
  276.             exit(1);
  277.         }
  278.         if( (c = fgetc(dis_inp_file)) != 0x00 )
  279.         {
  280.             fprintf(stderr, "file seems to be no machine code .VZ file (0002:%02X != 00)\n", c);
  281.             exit(1);
  282.         }
  283.         if( (c = fgetc(dis_inp_file)) != 0x00 )
  284.         {
  285.             fprintf(stderr, "file seems to be no machine code .VZ file (0003:%02X != 00)\n", c);
  286.             exit(1);
  287.         }
  288.         for( i = 0; i < 17; i++ )
  289.         {
  290.             if( !isalnum(c = fgetc(dis_inp_file)) && (c != ' ') && (c != 0x00) )
  291.             {
  292.                 fprintf(stderr, "file seems to be no machine code .CAS file (%04X:%02X)\n", (int)ftell(dis_inp_file) - 1, c);
  293.                 exit(1);
  294.             }
  295.         }
  296.         addr = fgetc(dis_inp_file);
  297.         addr += 256 * fgetc(dis_inp_file);
  298.         dis_run_addr = addr;
  299.         dis_end_addr = addr;
  300.         if (flg_blkinfo)
  301.             printf("entry point is %04X\n", addr);
  302.         while( !feof(dis_inp_file) )
  303.         {
  304.             c = fgetc(dis_inp_file);
  305.             mem[addr++] = c;
  306.         }
  307.         if (flg_blkinfo)
  308.             printf("end address is %04X\n", addr);
  309.         if( addr > dis_end_addr )
  310.             dis_end_addr = addr;
  311.     }
  312. #endif
  313.     else
  314.     {
  315.         dis_beg_addr = dis_offset;
  316.         while( !feof(dis_inp_file) )
  317.         {
  318.             int cnt = fread(mem + dis_offset, 1, 0x10000 - dis_offset, dis_inp_file);
  319.             if (dis_beg_addr + cnt - 1 > dis_end_addr)
  320.                 dis_end_addr = dis_beg_addr + cnt - 1;
  321.             dis_offset = 0;
  322.         }
  323.     }
  324.  
  325. #if CGENIE
  326.     DEF_file_read("CGENIE.DEF");
  327.     if (flg_cgdos)            // include colour genie dos symbols?
  328.         DEF_file_read("CGDOS.DEF");
  329. #else
  330.     DEF_file_read("VZROM.DEF");
  331.     if (flg_cgdos)            // include VZ dos symbols?
  332.         DEF_file_read("VZDOS.DEF");
  333. #endif
  334.  
  335.     if (flg_colcom)         // colour compiler output ?
  336.     {
  337.         WORD data;
  338.         WORD strs;
  339.         WORD code;
  340.         char strname[6+1] = "str000";
  341.         char strchr = 0;
  342.         int strcnt = 0;
  343.         int i;
  344.  
  345.         dis_run_addr = 0x7C02;
  346.         DEF_file_read("COLCOM.DEF");
  347.  
  348.         if (*(WORD*)&mem[0x4802] != 0x4804)
  349.         {
  350.             dis_beg_addr = 0x5800;
  351.             code = *(WORD*)&mem[0x7FBF];
  352.             memcpy(mem + 0x5800, mem + 0x7380, 0x880);
  353.             memset(mem + 0x7380, 0, 0x800);
  354.         }
  355.         else
  356.         {
  357.             code = *(WORD*)&mem[0x7FBC];
  358.             dis_beg_addr = 0x4800;
  359.         }
  360.  
  361.         data = *(WORD*)&mem[0x7FB5];
  362.         OPT_def(data, MEM_DATA, 1, OPT_WORDS);
  363.         SYM_add(data, SYM_DATA, "__DATA");
  364.  
  365.         strs = *(WORD*)&mem[0x7FB3];
  366.         OPT_def(strs, MEM_DATA, 0, OPT_ASCII);
  367.  
  368.         strchr = 0;
  369.         strcnt = 0;
  370.         for (i = strs; i < code; i++)
  371.         {
  372.             if ((strchr == 0) && (strcnt < 500))
  373.             {
  374.                 sprintf(strname, "__STR%03d", strcnt++);
  375.                 SYM_add(i, SYM_DATA, strname);
  376.             }
  377.             strchr = mem[i];
  378.         }
  379.  
  380.         OPT_def(code, MEM_CODE, 0, OPT_NONE);
  381.         SYM_add(code, SYM_CODE, "__LINE1");
  382.     }
  383.  
  384.     strcpy(def_filename, inp_filename);
  385.     dst = strrchr(def_filename, '.');
  386.     if (!dst)
  387.         strcat(def_filename, ".DEF");
  388.     else
  389.         strcpy(dst, ".DEF");
  390.  
  391.     DEF_file_read(def_filename);
  392.     dst = strrchr(def_filename, '\\');
  393.     if (!dst)
  394.         dst = strrchr(def_filename, '/');
  395.     if (dst)
  396.     {
  397.         strcpy(def_filename, dst + 1);
  398.         DEF_file_read(def_filename);
  399.     }
  400.  
  401.     disasm_init(dis_beg_addr);
  402.  
  403.     SYM_add(dis_run_addr, SYM_CODE, "ENTRY");
  404.  
  405.     dis_range(dis_beg_addr, dis_end_addr);
  406.  
  407.     return 0;
  408. }
  409.  
  410.