#include /* SET TABS TO 4 !!!! */ /* ST2Amiga Format-convert ST Executables to Amiga Executables. * * (C) Copyright, Dave Campbell 90/91 * * This software is freely distributable. Modified versions may be * redistributed provided that the modifications made are fully * documented as such. * * Its purpose is to aid the binary conversion of ST executables into * Amiga executables using the ReSource disassembler. To do this * you'll need some good books such as "Advanced MSDOS Programming" by * Ray Duncan, and other books on GEM (books on PC-GEM are best). * The ST's system call TRAPs map directly to PC and GEM calls. Eg * TRAP #1 is INT 21h. * * Don't forget to send me whatever you've converted (PD only)!! * * Many ST programs use very large BSS sections making them particularly * memory-hungry. The ST's memory allocation scheme is totally stuffed * and so many programs do their own memory allocation from their huge * BSS section. The people who designed the ST's OS certainly made * many more mistakes than Commodore did with the Amiga. * * There is a program called Dos-2-Dos which provides copying of files * to/from ST format disks. * Older ST disks are the same format as MSDOS 720k 3.5 inch, but the * bootblock and possibly a few other small things are slightly different. * All newer standard ST formatted disks will be identical to MSDOS * formatted disks. * * The ST does not support scatter-loading. All sections must be * consecutive; CODE, DATA, BSS. For this reason I merge the code * and data sections, and besides, it makes the job easy for me. * BSS comes out as a separate hunk -> its your responsibility to fix * up the dependencies. * * Why don't I space my source out more? I feel sorry for my space bar. * * Contact address: * * David Campbell * 36 Hemsworth Street * Acacia Ridge QLD 4110 * AUSTRALIA * * email: dave@csis.dit.csiro.au * * If you haven't heard of ReSource, its the ultimate disassembler. * For ReSource contact: * * In OZ: Glen McDiarmid In the US: The Puzzle Factory * 28 Marginson Street PO Box 986 * Ipswich QLD 4305 Veneta OR 97487 * AUSTRALIA USA * * (07) 812-2963 (503) 935 3709 */ struct st_header { unsigned short branch; unsigned long code_size; unsigned long data_size; unsigned long bss_size; unsigned long sym_size; unsigned long xx; unsigned long flag0; unsigned short xxxx; }; struct symbol { unsigned long sym_name; unsigned long sym_name2; /* 8 character symbols */ unsigned short flags; unsigned long offset; }; main(argc,argv) int argc; char **argv; { struct st_header ah; unsigned long codedata_size,bss_size; /* in longwords, not bytes */ unsigned long first_long,count; unsigned char b; long apos; int r; unsigned long l,num_hunks; FILE *inf,*outf; char *mem; if(argc!=3) { usage: printf( "\2335;33mST2Amiga\2330;31m 1.1" " Format-convert executables from ST -> Amiga.\n" " For use with the ReSource disassembler.\n" " by Dave Campbell (dave@csis.dit.csiro.au)." "\n\n\2335;33mUSAGE: ST2Amiga " "\2330;31m\n\n"); exit(0); } inf=fopen(argv[1],"r"); if(!inf) { printf("Error reading file %s.\n",argv[1]); exit(0); } outf=fopen(argv[2],"w"); if(!outf) { printf("Error writing file %s.\n",argv[2]); exit(0); } r=fread((char *)&ah,1,sizeof(ah),inf); if(r!=sizeof(ah)) { inv_atari_exe: printf("Invalid atari executable %s.\n",argv[1]); exit(0); } if(ah.branch!=0x601a) goto inv_atari_exe; /* anti-goto people go jump */ printf("Code size: $%lx\n",ah.code_size); printf("Data size: $%lx\n",ah.data_size); printf("Bss size: $%lx\n",ah.bss_size); if(!(ah.flag0&1)) printf("Warning: This Atari executable assumes a cleared heap.\n"); codedata_size=(ah.code_size+ah.data_size+3)>>2; /* up to next longword */ bss_size=(ah.bss_size+3)>>2; l=0x03f3; fwrite((char *)&l,sizeof(long),1,outf); /* hunk_header */ l=0x0000; fwrite((char *)&l,sizeof(long),1,outf); /* end of name list */ num_hunks=0; if(codedata_size) ++num_hunks; if(bss_size) ++num_hunks; fwrite((char *)&num_hunks,sizeof(long),1,outf); /* table size */ l=0x0000; fwrite((char *)&l,sizeof(long),1,outf); /* first hunk */ --num_hunks; fwrite((char *)&num_hunks,sizeof(long),1,outf); /* last hunk */ ++num_hunks; if(codedata_size) /* size of each hunk */ fwrite((char *)&codedata_size,sizeof(long),1,outf); if(bss_size) fwrite((char *)&bss_size,sizeof(long),1,outf); if(codedata_size) { l=0x03e9; fwrite((char *)&l,sizeof(long),1,outf); /* hunk_code */ fwrite((char *)&codedata_size,sizeof(long),1,outf); mem=(char *)malloc(codedata_size<<2); if(!mem) { printf("Cannot allocate %d bytes of memory.\n",codedata_size<<2); exit(0); } r=fread(mem,1,ah.code_size+ah.data_size,inf); if(r!=ah.code_size+ah.data_size) { free(mem); goto inv_atari_exe; } fwrite(mem,1,codedata_size<<2,outf); free(mem); } if(ah.sym_size) { /* symbols are present */ struct symbol sym; int hunk_written=0; count=ah.sym_size/sizeof(sym); while(count) { r=fread((char *)&sym,1,sizeof(sym),inf); if(r!=sizeof(sym)) goto inv_atari_exe; if(!(sym.flags&0x4000)) { if(!hunk_written) { l=0x03f0; fwrite((char *)&l,sizeof(long),1,outf); /* hunk_symbol */ hunk_written=1; /* never again */ } l=0x0002; fwrite((char *)&l,sizeof(long),1,outf); /* length of symbols in longs */ /* printf("%04x %s\n",sym.flags, (sym.flags=0,(char *)&sym.sym_name)); */ fwrite((char *)&sym.sym_name,1,8,outf); fwrite((char *)&sym.offset,sizeof(long),1,outf); } count--; } l=0x0000; fwrite((char *)&l,sizeof(long),1,outf); /* terminator */ } r=fread((char *)&first_long,1,sizeof(long),inf); /* read first reloc long */ if(r!=sizeof(long)) goto inv_atari_exe; if(first_long) { count=1; l=0x03ec; fwrite((char *)&l,sizeof(long),1,outf); /* hunk_reloc32 */ apos=ftell(inf); r=fread((char *)&b,1,1,inf); /* first pass to count */ if(r!=1) goto inv_atari_exe; while(b) { if(b>=2 && b<255) /* only count the relocs */ ++count; fread((char *)&b,1,1,inf); } fwrite((char *)&count,1,sizeof(long),outf); l=0; fwrite((char *)&l,sizeof(long),1,outf); /* reloc on hunk 0 */ fwrite((char *)&first_long,1,sizeof(long),outf); fseek(inf,apos,0); /* back to where we were */ r=fread((char *)&b,1,1,inf); if(r!=1) goto inv_atari_exe; /* ST relocation scheme */ while(b) { /* 0 -> end of relocation */ if(b==1) first_long+=254; /* 1 -> skip 254 bytes */ else if(b&1) goto inv_atari_exe; /* other odds undefined */ else { /* other evens skip bytes and relocate */ first_long+=b; fwrite((char *)&first_long,sizeof(long),1,outf); } r=fread((char *)&b,1,1,inf); if(r!=1) goto inv_atari_exe; } l=0x0000; fwrite((char *)&l,sizeof(long),1,outf); /* end of reloc */ l=0x03f2; fwrite((char *)&l,sizeof(long),1,outf); /* hunk_end */ } if(bss_size) { l=0x03eb; fwrite((char *)&l,sizeof(long),1,outf); /* hunk_bss */ fwrite((char *)&bss_size,sizeof(long),1,outf); fseek(inf,ah.bss_size,1); } l=0x03f2; fwrite((char *)&l,sizeof(long),1,outf); /* hunk_end */ /* CLOSE UP SHOP */ fclose(inf); fclose(outf); }