#include <exec/types.h>
#include <dos/dos.h>

struct Key
{
   UBYTE Product[10];
   UBYTE Junk1[10];
   UBYTE Name[50];
   UBYTE Junk[182];
   ULONG Serial;
};

ULONG checksums[16];

struct Key key;
UBYTE *keybuf,*longbuf;

main(int argc, char **argv)
{
   ULONG c;
   UBYTE xor;
   ULONG add,mult,bit,bit2,add2,zeromult,mult3,mult4,add3,rol,add4,bit3,bit4,zm2,zm3,tjo;
   BPTR fh;
   UBYTE buf[60];

   srand(time(NULL));

   keybuf=(UBYTE *)&key;

   for(c=0;c<sizeof(struct Key);c++)
      keybuf[c]=rand()%256;

   strcpy(key.Product,"CrashMail");
   strcpy(key.Name,argv[1]);
   key.Serial=atoi(argv[2]);

   add=0;
   mult=1;
   bit=0;
   bit2=0;
   add2=0;
   zeromult=0;
   mult3=0;
   mult4=0;
   add3=0;
   rol=0;
   add4=0;
   bit2=0;
   bit3=0;
   bit4=0;
   zm2=0;
   zm3=0;
   tjo=0;

   for(c=0;c<sizeof(struct Key);c++)
      if(c<70 || c>=252 || c%2==0)
      {
         add<<=add%3;
         add+=keybuf[c];

         if(keybuf[c]) mult*=keybuf[c];
         if(mult>4000000) mult>>=1;
         mult+=keybuf[c];

         bit|=mult;
         bit&=add;

         bit2|=add*mult*bit*bit2;
         bit2+=add;

         add2^=add*mult*bit*bit2;
         add2^=add*mult;

         mult3^=c*keybuf[c];
         mult3<<=c%3;

         zeromult^=(c+3)*(keybuf[c]+3);
         zeromult<<=c%3;

         mult4^=c*keybuf[c];
         mult4|=mult3+1;
         mult4<<=c%3;

         if(c%3 == 0)
         {
            add3+=keybuf[c]+c;
            add3<<=1;
         }

         rol|=1;
         rol<<=keybuf[c]%4;

         add4+=keybuf[c]+c;
         add4<<=1;

         bit3|=keybuf[c]+c & 0x0f0f0f0f;
         bit3<<=2;

         bit4^=keybuf[c]+c;
         bit4<<=1;

         zm2^=c*(keybuf[c]+c);
         zm2<<=c%3;

         zm3&=0xFFFFFFF0;
         zm3|=(c*(keybuf[c]+c))%256;
         zm3<<=2;

         tjo+=(keybuf[c]+c)|'tjo';
         tjo<<=3;
      }

   xor=255;

   checksums[0]=add;
   checksums[1]=add2;
   checksums[2]=mult;
   checksums[3]=bit;
   checksums[4]=bit2;
   checksums[5]=zeromult;
   checksums[6]=mult3;
   checksums[7]=mult4;
   checksums[8]=add3;
   checksums[9]=rol;
   checksums[10]=add4;
   checksums[11]=bit3;
   checksums[12]=bit4;
   checksums[13]=zm2;
   checksums[14]=zm3;
   checksums[15]=tjo;

   Printf("\nChecksums:\n\n");

   for(c=0;c<16;c++)
      Printf("%2lu: 0x%08lx\n",c,checksums[c]);

   Printf("\n");

   longbuf=(UBYTE *)checksums;

   for(c=0;c<4*16;c++)
      keybuf[70+c*2+1]=longbuf[c];

   for(c=0;c<sizeof(struct Key);c++)
   {
      keybuf[c]^=xor;
      xor=keybuf[c];
   }

   strcpy(buf,"ram:");
   strcat(buf,argv[1]);
   for(c=0;c<strlen(buf);c++) if(buf[c]==' ') buf[c]='_';
   strcat(buf,".key");

   if(!(fh=Open(buf,MODE_NEWFILE)))
   {
      Printf("Unable to open %s for writing\n",buf);
      exit(10);
   }

   Write(fh,&key,sizeof(struct Key));
   Close(fh);

   exit(10);
}