/*
 * config.c - installs new explosion path in explode executable
 *
 * Bruno Costa - 30 Dec 89 - 31 Dec 89
 *
 */

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

#ifndef SEEK_END
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif

#define TRUE 1
#define FALSE 0

struct {
 unsigned long int code;
 char tag[TAGSIZE];
 int timedelay, pattern, nsteps;
 struct {
   struct {
     int x, y;
   } topleft, botright;
 } step[MAXSTEPS];
} global = {
 TAG_CODE,
 TAG_ID,
 DEFDELAY, DEFPAT, 21,
 {
  {    0,    0,    0,    0 },	/* left, top, right, bottom */
  {  135,  -22,  135,  -22 },
  {  265,  -30,  265,  -30 },
  {  389,  -25,  389,  -25 },
  {  506,   -6,  506,   -6 },
  {  615,   23,  615,   23 },
  {  717,   62,  717,   62 },
  {  811,  111,  811,  111 },
  {  895,  168,  895,  168 },
  {  971,  231,  971,  231 },
  { 1036,  300, 1036,  300 },
  { 1090,  373, 1090,  373 },
  { 1134,  449, 1134,  449 },
  { 1166,  527, 1166,  527 },
  { 1186,  605, 1186,  605 },
  { 1194,  683, 1194,  683 },
  { 1188,  759, 1188,  759 },
  { 1169,  833, 1169,  833 },
  { 1135,  902, 1135,  902 },
  { 1087,  966, 1087,  966 },
  { 1024, 1024, 1024, 1024 },	/* 21th entry */
  {    0,    0,    0,    0 },
  {    0,    0,    0,    0 },
  {    0,    0,    0,    0 },
  {    0,    0,    0,    0 },
  {    0,    0,    0,    0 },
  {    0,    0,    0,    0 },
  {    0,    0,    0,    0 },
  {    0,    0,    0,    0 },
  {    0,    0,    0,    0 }
 }
};
/*
 *  The points above were generated using an HP-28S and a bezier curve
 * plotting program. The curve was broken in 20 line segments and the
 * control points were: (0, 0) ; (922, -205) ; (1587, 665) ; (1024, 1024)
 */

void error (char *msg)
{
 fputs ("config: ", stderr);
 fputs (msg, stderr);
 fputc ('\n', stderr);
 exit (20);
}

void main (int argc, char *argv[])
{
 FILE *f;
 char *buffer, *p, *q, *match;
 int tagfound, i;
 long size;

 puts ("\x1b[33mConfig 1.2b\x1b[31m - \xa9 1989 by Bruno Costa");
 if (argc != 2)
 {
   puts ("installs a motion path read from stdin in given Explode 1.2b executable.");
   puts ("usage: \x1b[1mconfig\x1b[0m <executable>");
   exit (5);
 }

 /*
  * fill in global struct with data from stdin
  */
 puts ("reading new data ...");

 scanf ("%d %x", &global.timedelay, &global.pattern);
 i = 0;
 while (scanf("%d %d %d %d", &global.step[i].topleft.x, &global.step[i].topleft.y,
               &global.step[i].botright.x, &global.step[i].botright.y) == 4)
   if (++i >= MAXSTEPS)
     error ("too many steps");

 if (i)
   global.nsteps = i;

 puts ("installing ...");

 /*
  * read original file in buffer
  */
 f = fopen (argv[1], "rb+");	/* binary read and/or write */
 if (!f)
   error ("file not found");

 fseek (f, 0, SEEK_END);	/* go to EOF ... */
 size = ftell (f);		/* ... and get file size */
 rewind (f);

 if (size <= 0  ||  !(buffer = malloc (size)))
   error ("out of memory");

 if (fread (buffer, size, 1, f) != 1)
   error ("could not read file");

 /* 
  * search for tag in buffer
  */
 tagfound = FALSE;
 match = (char *)&global.code;
 for (p = buffer, q = buffer + size; p < q  && !tagfound; p++)
   if (*p == *match)
     tagfound = (*match++) ? FALSE : TRUE;
   else
     match = (char *)&global.code;

 if (!tagfound)
   error ("no tag found");

 /*
  * copy new information
  */
 for (q = global.tag + sizeof (global); match < q; p++, match++)
   *p = *match;

 /*
  * write out new program
  */
 rewind (f);

 if (fwrite (buffer, size, 1, f) != 1)
   error ("could not write file");

 fclose (f);
 free (buffer);

 puts ("done.");
 exit (0);
}
