/******************************************************************************

File        : c.jumble

Date        : Saturday 18th March 1995

Author      : Gavin C. Cawley

Description : Jumble EPROM contents to account for address lines being
              connected out of order.

Notes       : Somewhat non-portable!

History     : 1.00 18/3/95
              1.01 14/5/95 updated to use !mylib

Copyright   : (c) Gavin C. Cawley, March 1995.

******************************************************************************/

#include <stdlib.h>
#include <stdio.h>

#include "error.h"

#define SWAP(type, a, b) { auto type __tmp_type = a; a = b; b = __tmp_type; }

typedef struct _EPROM
{
   int len;

   char *byte;   
}
EPROM;

typedef unsigned int (*Procedure)(unsigned int i);

unsigned int ands[] =
{
   0xE2102001,   /*            ANDS    a3, a1, #&1          */
   0xE2102002,   /*            ANDS    a3, a1, #&2          */
   0xE2102004,   /*            ANDS    a3, a1, #&4          */
   0xE2102008,   /*            ANDS    a3, a1, #&8          */
   0xE2102010,   /*            ANDS    a3, a1, #&10         */
   0xE2102020,   /*            ANDS    a3, a1, #&20         */
   0xE2102040,   /*            ANDS    a3, a1, #&40         */
   0xE2102080,   /*            ANDS    a3, a1, #&80         */
   0xE2102C01,   /*            ANDS    a3, a1, #&100        */
   0xE2102C02,   /*            ANDS    a3, a1, #&200        */
   0xE2102B01,   /*            ANDS    a3, a1, #&400        */
   0xE2102B02,   /*            ANDS    a3, a1, #&800        */
   0xE2102A01,   /*            ANDS    a3, a1, #&1000       */
   0xE2102A02,   /*            ANDS    a3, a1, #&2000       */
   0xE2102901,   /*            ANDS    a3, a1, #&4000       */
   0xE2102902,   /*            ANDS    a3, a1, #&8000       */
   0xE2102801,   /*            ANDS    a3, a1, #&10000      */
   0xE2102802,   /*            ANDS    a3, a1, #&20000      */
   0xE2102701,   /*            ANDS    a3, a1, #&40000      */
   0xE2102702,   /*            ANDS    a3, a1, #&80000      */
   0xE2102601,   /*            ANDS    a3, a1, #&100000     */
   0xE2102602,   /*            ANDS    a3, a1, #&200000     */
   0xE2102501,   /*            ANDS    a3, a1, #&400000     */
   0xE2102502,   /*            ANDS    a3, a1, #&800000     */
   0xE2102401,   /*            ANDS    a3, a1, #&1000000    */
   0xE2102402,   /*            ANDS    a3, a1, #&2000000    */
   0xE2102301,   /*            ANDS    a3, a1, #&4000000    */
   0xE2102302,   /*            ANDS    a3, a1, #&8000000    */
   0xE2102201,   /*            ANDS    a3, a1, #&10000000   */
   0xE2102202,   /*            ANDS    a3, a1, #&20000000   */
   0xE2102101,   /*            ANDS    a3, a1, #&40000000   */
   0xE2102102    /*            ANDS    a3, a1, #&80000000   */
};

unsigned int orrne[] =
{
   0x13811001,   /*            ORRNE   a2, a2, #&1          */
   0x13811002,   /*            ORRNE   a2, a2, #&2          */
   0x13811004,   /*            ORRNE   a2, a2, #&4          */
   0x13811008,   /*            ORRNE   a2, a2, #&8          */
   0x13811010,   /*            ORRNE   a2, a2, #&10         */
   0x13811020,   /*            ORRNE   a2, a2, #&20         */
   0x13811040,   /*            ORRNE   a2, a2, #&40         */
   0x13811080,   /*            ORRNE   a2, a2, #&80         */
   0x13811C01,   /*            ORRNE   a2, a2, #&100        */
   0x13811C02,   /*            ORRNE   a2, a2, #&200        */
   0x13811B01,   /*            ORRNE   a2, a2, #&400        */
   0x13811B02,   /*            ORRNE   a2, a2, #&800        */
   0x13811A01,   /*            ORRNE   a2, a2, #&1000       */
   0x13811A02,   /*            ORRNE   a2, a2, #&2000       */
   0x13811901,   /*            ORRNE   a2, a2, #&4000       */
   0x13811902,   /*            ORRNE   a2, a2, #&8000       */
   0x13811801,   /*            ORRNE   a2, a2, #&10000      */
   0x13811802,   /*            ORRNE   a2, a2, #&20000      */
   0x13811701,   /*            ORRNE   a2, a2, #&40000      */
   0x13811702,   /*            ORRNE   a2, a2, #&80000      */
   0x13811601,   /*            ORRNE   a2, a2, #&100000     */
   0x13811602,   /*            ORRNE   a2, a2, #&200000     */
   0x13811501,   /*            ORRNE   a2, a2, #&400000     */
   0x13811502,   /*            ORRNE   a2, a2, #&800000     */
   0x13811401,   /*            ORRNE   a2, a2, #&1000000    */
   0x13811402,   /*            ORRNE   a2, a2, #&2000000    */
   0x13811301,   /*            ORRNE   a2, a2, #&4000000    */
   0x13811302,   /*            ORRNE   a2, a2, #&8000000    */
   0x13811201,   /*            ORRNE   a2, a2, #&10000000   */
   0x13811202,   /*            ORRNE   a2, a2, #&20000000   */
   0x13811101,   /*            ORRNE   a2, a2, #&40000000   */
   0x13811102    /*            ORRNE   a2, a2, #&80000000   */
};

unsigned int *make_jumble(int n, int *a)
{
   int i, j;

   unsigned int *jumble = E_VECTOR_ALLOC(unsigned int, 1+64+2);

   i = 0;

   /* preamble */

   jumble[i++] = 0xE3A01000;    /* MOV   a2, #0 */ 

   /* body of jumble procedure */

   for (j = 0; j < n; j++)
   {
      jumble[i++] = ands[j];
      jumble[i++] = orrne[a[j]];
   }

   /* epilogue */

   jumble[i++] = 0xE1A00001;    /* MOV   a1, a2 */ 
   jumble[i++] = 0xE1B0F00E;    /* MOVS  pc, lr */

   /* return pointer to jumble code */

   return jumble;
}

EPROM *eprom_loadhex(FILE *fd)
{
   int i, n;

   EPROM *e = E_MALLOC(EPROM);

   /* read number of bytes */

   fscanf(fd, "%d", &(e->len));

   /* allocate memory */

   e->byte = E_VECTOR_ALLOC(char, e->len);

   /* load bytes */

   for (i = 0; i < e->len; i++)
   {
      if (fscanf(fd, "%02x ", &n) == EOF)
      {
         error(Warning, "unexpected end of file");

         e->len = i;

         break;
      }

      e->byte[i] = n;
   }

   return e;
}

void eprom_savehex(EPROM *e, FILE *fd)
{
   int i;

   /* write length */

   fprintf(fd, "%d", e->len);

   for (i = 0; i < e->len; i++)
   {
      fprintf(fd, i % 16 == 0 ? "\n%02x " : "%02x ", e->byte[i]);
   }

   fprintf(fd, "\n");
}

int main(int argc, char *argv[])
{
   int i, j, a[32];

   FILE *fd;

   Procedure jumble;

   EPROM *e;

   /* check number of command line args */

   if (argc == 1)
   {
      error(Usage, "%s <infile> <outfile>  a0 a1 ... a31", argv[0]);
   }

   /* parse command line args */

   for (i = 0, j = 3; j < argc; i++, j++)
   {
      a[i] = atoi(argv[j]);
   }

   jumble = (Procedure) make_jumble(argc-3, a);

   /* load eprom */

   fd = efopen(argv[1], "r");

   e = eprom_loadhex(fd);

   fclose(fd);

   /* jumble eprom */

   for (i = 0; i < e->len; i++)
   {
      j = jumble(i);

      if (i < j) SWAP(char, e->byte[i], e->byte[j]); 
   }

   /* save eprom */

   fd = efopen(argv[2], "w");

   eprom_savehex(e, fd);

   fclose(fd);

   /* bye bye... */

   return EXIT_SUCCESS;
}

/*************************** That's all Folks! *******************************/

