/* James K. Lawless
 * DOS-version independent EXE to BIN converter
 * This program may be used freely.
 */


#include <stdio.h>

typedef unsigned int WORD;
main(int argc,char **argv)
{
   FILE *fp,*fout;
   struct {
      char  sig[2];
      WORD  remainder;
      WORD  pages;
      WORD  relo_items;
      WORD  hdr_size;
      WORD  min_alloc;
      WORD  max_alloc;
      WORD  stack_disp;
      WORD  SP_reg;
      WORD  checksum;
      WORD  IP_reg;
      WORD  CS_disp;
      WORD  relo_disp;
      WORD  ovl_number;
   } ehdr;

   long header_size,prg_size,l;
   static char buff[512];

   if(argc<3) {
      fprintf(stderr,"SYNTAX:\n"
         "%s <infile.EXE> <outfile.ext>\n",
         argv[0]);
      exit(1);
   }

   if((fp=fopen(argv[1],"rb"))==NULL) {
      fprintf(stderr,
         "Cannot open input file %s\n",argv[1]);
      exit(1);
   }

   if((fout=fopen(argv[2],"wb"))==NULL) {
      fprintf(stderr,
         "Cannot open output file %s\n",argv[2]);
      exit(1);
   }

   if(!fread(&ehdr,sizeof(ehdr),1,fp)) {
      fprintf(stderr,"Cannot read header\n");
      exit(1);
   }

   /* First two chars must be "MZ" */
   if((ehdr.sig[0]!='M')||(ehdr.sig[1]!='Z')){
      fprintf(stderr,"Invalid .EXE signature\n");
      exit(1);
   }

   /* Fail if EXE has a stack */
   if((ehdr.stack_disp!=0)||(ehdr.SP_reg!=0)) {
      fprintf(stderr,"Module has a stack\n");
      exit(1);
   }

   /* IP must be either 100h or 0h */
   if( (ehdr.IP_reg!=0x100) && (ehdr.IP_reg!=0)) {
      fprintf(stderr,"Invalid IP value %x\n",
         ehdr.IP_reg);
      exit(1);
   }

   /* Module must not have relocatable references */
   if(ehdr.relo_items){
      fprintf(stderr,
         "Module has %u relocatable items\n",
            ehdr.relo_items);
      exit(1);
   }

   /* Overlay number must be 0 */
   if(ehdr.ovl_number!=0) {
      fprintf(stderr,"Invalid overlay number %u\n",
         ehdr.ovl_number);
      exit(1);
   }

   /* Compute the size and offset of the program */
   header_size=(long) ehdr.hdr_size;
   header_size<<=4;
   prg_size=(long) ehdr.pages-1;
   prg_size*=512L;
   prg_size+=ehdr.remainder;
   prg_size-=header_size;
   prg_size-=ehdr.IP_reg;

   /* seek the block that is our BIN module */
   rewind(fp);
   fseek(fp,header_size+(long) ehdr.IP_reg,SEEK_SET);

   for(l=0L; l+512<prg_size; l+=512L) {
      if(!fread(buff,512,1,fp)) {
         fprintf(stderr,"Unexpected EOF\n");
         exit(1);
      }
      if(!fwrite(buff,512,1,fout)) {
         fprintf(stderr,"Write error\n");
         exit(1);
      }
   }
   if(prg_size%512L) {
      if(!fread(buff,(int) prg_size%512L,1,fp)) {
         fprintf(stderr,"Unexpected EOF\n");
         exit(1);
      }
      if(!fwrite(buff,prg_size%512L,1,fout)) {
         fprintf(stderr,"Write error\n");
         exit(1);
      }
   }
   fclose(fp);
   fclose(fout);
   exit(0);
}
