home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 573b.lha / ST2Amiga / ST2Amiga.c < prev    next >
C/C++ Source or Header  |  1991-03-22  |  8KB  |  241 lines

  1. #include <stdio.h>
  2.  
  3. /* SET TABS TO 4 !!!! */
  4.  
  5. /* ST2Amiga  Format-convert ST Executables to Amiga Executables.
  6.  *
  7.  * (C) Copyright, Dave Campbell 90/91
  8.  *
  9.  * This software is freely distributable.  Modified versions may be
  10.  * redistributed provided that the modifications made are fully
  11.  * documented as such.
  12.  *
  13.  * Its purpose is to aid the binary conversion of ST executables into
  14.  * Amiga executables using the ReSource disassembler.  To do this
  15.  * you'll need some good books such as "Advanced MSDOS Programming" by
  16.  * Ray Duncan, and other books on GEM (books on PC-GEM are best).
  17.  * The ST's system call TRAPs map directly to PC and GEM calls.  Eg
  18.  * TRAP #1 is INT 21h.
  19.  *
  20.  * Don't forget to send me whatever you've converted (PD only)!!
  21.  *
  22.  * Many ST programs use very large BSS sections making them particularly
  23.  * memory-hungry.  The ST's memory allocation scheme is totally stuffed
  24.  * and so many programs do their own memory allocation from their huge
  25.  * BSS section.  The people who designed the ST's OS certainly made
  26.  * many more mistakes than Commodore did with the Amiga.
  27.  *
  28.  * There is a program called Dos-2-Dos which provides copying of files
  29.  * to/from ST format disks.
  30.  * Older ST disks are the same format as MSDOS 720k 3.5 inch, but the
  31.  * bootblock and possibly a few other small things are slightly different.
  32.  * All newer standard ST formatted disks will be identical to MSDOS
  33.  * formatted disks.
  34.  *
  35.  * The ST does not support scatter-loading.  All sections must be
  36.  * consecutive; CODE, DATA, BSS.  For this reason I merge the code
  37.  * and data sections, and besides, it makes the job easy for me.
  38.  * BSS comes out as a separate hunk -> its your responsibility to fix
  39.  * up the dependencies.
  40.  *
  41.  * Why don't I space my source out more?  I feel sorry for my space bar.
  42.  *
  43.  * Contact address:
  44.  *
  45.  * David Campbell
  46.  * 36 Hemsworth Street
  47.  * Acacia Ridge QLD 4110
  48.  * AUSTRALIA
  49.  *
  50.  * email: dave@csis.dit.csiro.au
  51.  *
  52.  * If you haven't heard of ReSource, its the ultimate disassembler.
  53.  * For ReSource contact:
  54.  *
  55.  * In OZ: Glen McDiarmid                    In the US: The Puzzle Factory
  56.  *        28 Marginson Street               PO Box 986
  57.  *        Ipswich QLD 4305                  Veneta OR 97487
  58.  *        AUSTRALIA                         USA
  59.  *
  60.  *        (07) 812-2963                        (503) 935 3709
  61.  */
  62.  
  63. struct st_header {
  64.     unsigned short branch;
  65.     unsigned long code_size;
  66.     unsigned long data_size;
  67.     unsigned long bss_size;
  68.     unsigned long sym_size;
  69.     unsigned long xx;
  70.     unsigned long flag0;
  71.     unsigned short xxxx;
  72. };
  73.  
  74. struct symbol {
  75.     unsigned long sym_name;
  76.     unsigned long sym_name2;                                    /* 8 character symbols */
  77.     unsigned short flags;
  78.     unsigned long offset;
  79. };
  80.  
  81. main(argc,argv)
  82. int argc;
  83. char **argv;
  84. {
  85.     struct st_header ah;
  86.     unsigned long codedata_size,bss_size;                        /* in longwords, not bytes */
  87.     unsigned long first_long,count;
  88.     unsigned char b;
  89.     long apos;
  90.     int r;
  91.     unsigned long l,num_hunks;
  92.     FILE *inf,*outf;
  93.     char *mem;
  94.     if(argc!=3) {
  95. usage:
  96.         printf(    "\2335;33mST2Amiga\2330;31m 1.1"
  97.                 "    Format-convert executables from ST -> Amiga.\n"
  98.                 "                For use with the ReSource disassembler.\n"
  99.                 "                by Dave Campbell (dave@csis.dit.csiro.au)."
  100.                 "\n\n\2335;33mUSAGE: ST2Amiga <ST-Exe> <Amiga-Exe>"
  101.                 "\2330;31m\n\n");
  102.         exit(0);
  103.     }
  104.     inf=fopen(argv[1],"r");
  105.     if(!inf) {
  106.         printf("Error reading file %s.\n",argv[1]);
  107.         exit(0);
  108.     }
  109.     outf=fopen(argv[2],"w");
  110.     if(!outf) {
  111.         printf("Error writing file %s.\n",argv[2]);
  112.         exit(0);
  113.     }
  114.     r=fread((char *)&ah,1,sizeof(ah),inf);
  115.     if(r!=sizeof(ah)) {
  116. inv_atari_exe:
  117.         printf("Invalid atari executable %s.\n",argv[1]);
  118.         exit(0);
  119.     }
  120.     if(ah.branch!=0x601a)
  121.         goto inv_atari_exe;                                        /* anti-goto people go jump */
  122.  
  123.     printf("Code size: $%lx\n",ah.code_size);
  124.     printf("Data size: $%lx\n",ah.data_size);
  125.     printf("Bss  size: $%lx\n",ah.bss_size);
  126.     if(!(ah.flag0&1))
  127.         printf("Warning: This Atari executable assumes a cleared heap.\n");
  128.  
  129.     codedata_size=(ah.code_size+ah.data_size+3)>>2;                /* up to next longword */
  130.     bss_size=(ah.bss_size+3)>>2;
  131.  
  132.     l=0x03f3; fwrite((char *)&l,sizeof(long),1,outf);            /* hunk_header */
  133.     l=0x0000; fwrite((char *)&l,sizeof(long),1,outf);            /* end of name list */
  134.     num_hunks=0;
  135.     if(codedata_size) ++num_hunks;
  136.     if(bss_size)  ++num_hunks;
  137.     fwrite((char *)&num_hunks,sizeof(long),1,outf);                /* table size */
  138.     l=0x0000; fwrite((char *)&l,sizeof(long),1,outf);            /* first hunk */
  139.     --num_hunks;
  140.     fwrite((char *)&num_hunks,sizeof(long),1,outf);                /* last hunk */
  141.     ++num_hunks;
  142.     if(codedata_size)                                            /* size of each hunk */
  143.         fwrite((char *)&codedata_size,sizeof(long),1,outf);
  144.     if(bss_size)
  145.         fwrite((char *)&bss_size,sizeof(long),1,outf);
  146.     if(codedata_size) {
  147.         l=0x03e9; fwrite((char *)&l,sizeof(long),1,outf);        /* hunk_code */
  148.         fwrite((char *)&codedata_size,sizeof(long),1,outf);
  149.         mem=(char *)malloc(codedata_size<<2);
  150.         if(!mem) {
  151.             printf("Cannot allocate %d bytes of memory.\n",codedata_size<<2);
  152.             exit(0);
  153.         }
  154.         r=fread(mem,1,ah.code_size+ah.data_size,inf);
  155.         if(r!=ah.code_size+ah.data_size) {
  156.             free(mem);
  157.             goto inv_atari_exe;
  158.         }
  159.         fwrite(mem,1,codedata_size<<2,outf);
  160.         free(mem);
  161.     }
  162.     if(ah.sym_size) {                                            /* symbols are present */
  163.         struct symbol sym;
  164.         int hunk_written=0;
  165.         count=ah.sym_size/sizeof(sym);
  166.         while(count) {
  167.             r=fread((char *)&sym,1,sizeof(sym),inf);
  168.             if(r!=sizeof(sym))
  169.                 goto inv_atari_exe;
  170.             if(!(sym.flags&0x4000)) {
  171.                 if(!hunk_written) {
  172.                     l=0x03f0; fwrite((char *)&l,sizeof(long),1,outf);
  173.                                                                 /* hunk_symbol */
  174.                     hunk_written=1;                                /* never again */
  175.                 }
  176.                 l=0x0002; fwrite((char *)&l,sizeof(long),1,outf);
  177.                                                                 /* length of symbols in longs */
  178. /*                printf("%04x %s\n",sym.flags,
  179.                     (sym.flags=0,(char *)&sym.sym_name)); */
  180.                 fwrite((char *)&sym.sym_name,1,8,outf);
  181.                 fwrite((char *)&sym.offset,sizeof(long),1,outf);
  182.             }
  183.             count--;
  184.         }
  185.         l=0x0000; fwrite((char *)&l,sizeof(long),1,outf);        /* terminator */
  186.     }
  187.     r=fread((char *)&first_long,1,sizeof(long),inf);            /* read first reloc long */
  188.     if(r!=sizeof(long))
  189.         goto inv_atari_exe;
  190.     if(first_long) {
  191.         count=1;
  192.         l=0x03ec; fwrite((char *)&l,sizeof(long),1,outf);        /* hunk_reloc32 */
  193.  
  194.         apos=ftell(inf);
  195.         r=fread((char *)&b,1,1,inf);                            /* first pass to count */
  196.         if(r!=1)
  197.             goto inv_atari_exe;
  198.         while(b) {
  199.             if(b>=2 && b<255)                                    /* only count the relocs */
  200.                 ++count;
  201.             fread((char *)&b,1,1,inf);
  202.         }
  203.         fwrite((char *)&count,1,sizeof(long),outf);
  204.         l=0; fwrite((char *)&l,sizeof(long),1,outf);            /* reloc on hunk 0 */
  205.         fwrite((char *)&first_long,1,sizeof(long),outf);
  206.         fseek(inf,apos,0);                                        /* back to where we were */
  207.         r=fread((char *)&b,1,1,inf);
  208.         if(r!=1)
  209.             goto inv_atari_exe;
  210.  
  211.         /* ST relocation scheme */
  212.  
  213.         while(b) {                                                /* 0 -> end of relocation */
  214.             if(b==1)
  215.                 first_long+=254;                                /* 1 -> skip 254 bytes */
  216.             else if(b&1)
  217.                 goto inv_atari_exe;                                /* other odds undefined */
  218.             else {                                                 /* other evens skip bytes and relocate */
  219.                 first_long+=b;
  220.                 fwrite((char *)&first_long,sizeof(long),1,outf);
  221.             }
  222.             r=fread((char *)&b,1,1,inf);
  223.             if(r!=1)
  224.                 goto inv_atari_exe;
  225.         }
  226.         l=0x0000; fwrite((char *)&l,sizeof(long),1,outf);        /* end of reloc */
  227.         l=0x03f2; fwrite((char *)&l,sizeof(long),1,outf);        /* hunk_end */
  228.     }
  229.     if(bss_size) {
  230.         l=0x03eb; fwrite((char *)&l,sizeof(long),1,outf);        /* hunk_bss */
  231.         fwrite((char *)&bss_size,sizeof(long),1,outf);
  232.         fseek(inf,ah.bss_size,1);
  233.     }
  234.     l=0x03f2; fwrite((char *)&l,sizeof(long),1,outf);            /* hunk_end */
  235.  
  236.     /* CLOSE UP SHOP */
  237.  
  238.     fclose(inf);
  239.     fclose(outf);
  240. }
  241.