/***************************************************************************
 *
 *                MandelVroom Load/Save raw information
 *
 *                         Kevin L. Clague
 *
 *                        Copyright (C) 1987
 *
 **************************************************************************/

#include "mand.h"

extern struct NewScreen NewScreen;
extern struct Screen    *screen;
extern struct ViewPort  *vp;

extern float StartX,StartY,EndX,EndY;

extern SHORT Zoom;

extern SHORT CountX,CountY,MaxCount,*CountBase;
extern LONG  NavTop,NavBot,NavLeft,NavRight;

extern SHORT NumContours, *ContourBase;
extern UBYTE *ColorBase;

extern SHORT SavePalette[], Inited;

extern ULONG CalcTime;
extern UBYTE MandType;
extern ULONG BorderType;

/*
 * Save all the data needed to restore the system to current state.
 */
SaveCounts(SaveName)
  char *SaveName;
{
  FILE  *SaveFile;
  SHORT *CountPtr,Color;
  ULONG  i,Count,Word = 0;
  USHORT Cur,t;
  ULONG Version = VERSION;
  char   ErrMsg[80];

  /*
   * Change the mouse pointer to Sleepy pointer
   */
  SetSleepyPointer();

  /*
   * open the desired file for writing
   */
  SaveFile = fopen(SaveName,"w");

  if (SaveFile == (FILE *) NULL) {
    sprintf(ErrMsg, "Can't open file %s", SaveName);
    DispErrMsg(ErrMsg, 0);
    return(0);
  }

  /*
   * if there is data to save, save it
   */
  if (CountBase) {

    /*
     * Put out the file header
     */
    fwrite((char *) "MAND",    4,  1, SaveFile);

    /*
     * Put out the revision number
     */
    fwrite((char *) Version,   sizeof(Version), 1, SaveFile);

    /*
     * Put out the location on the complex plane
     */
    fwrite((char *) &StartX,   sizeof(float),   1, SaveFile);
    fwrite((char *) &StartY,   sizeof(float),   1, SaveFile);
    fwrite((char *) &EndX,     sizeof(float),   1, SaveFile);
    fwrite((char *) &EndY,     sizeof(float),   1, SaveFile);

    /*
     * Put out the Maximum iteration count for a given point
     */
    fwrite((char *) &MaxCount, sizeof(SHORT),    1, SaveFile);

    /*
     * Put out the generator type
     */
    fwrite((char *) &MandType, sizeof(MandType), 1, SaveFile);

    /*
     * Put out the time it took to generate
     */
    fwrite((char *) &CalcTime, sizeof(CalcTime), 1, SaveFile);

    /*
     * Put out the screen's viewmodes
     */
    fwrite((char *) &screen->ViewPort.Modes,
              sizeof(screen->ViewPort.Modes), 1, SaveFile);

    /*
     * Put out the number of bit planes
     */
    fwrite((char *) &screen->BitMap.Depth,
              sizeof(screen->BitMap.Depth), 1, SaveFile);

    /*
     * Put some window flags
     */
    fwrite((char *) &BorderType, sizeof(BorderType), 1, SaveFile);

    /*
     * Save the Color Palette
     */
    for (i = 0; i < 32; i++) {
      Color = GetRGB4(vp->ColorMap, i);
      fwrite((char *) &Color, sizeof(Color), 1, SaveFile);
    }

    /*
     * Save the number of contours
     */
    fwrite((char *) &NumContours, sizeof(NumContours), 1, SaveFile);

    /*
     * Save the contour's heights
     */
    fwrite((char *) ContourBase, sizeof(SHORT), (long) NumContours, SaveFile);

    /*
     * Save the contour's pen numbers (Color is a misnomer)
     */
    fwrite((char *) ColorBase, sizeof(UBYTE), (long) NumContours, SaveFile);

    /*
     * Put out the image dimensions
     */
    fwrite((char *) &CountX,   sizeof(SHORT),   1, SaveFile);
    fwrite((char *) &CountY,   sizeof(SHORT),   1, SaveFile);

    /* Save count information in pseudo RLL format */
    /* Bits 9-0 are iteration count.               */
    /* Bits 15-10 are how many iteration count of same height in a row */

    i = CountX*CountY;

    CountPtr = CountBase;
    Cur = *CountPtr;
    Count = 1;

    while (--i) {
      CountPtr++;

      /*
       * Count up how many in a row have same height
       */
      if (Cur == *CountPtr) {
        Count++;
      } else {

        /*
         * Break it up into chunks of 64
         */
        while (Count) {
          if (Count > 63) {
            t = 63 << 10 | Cur;
            Count -= 63;
          } else {
            t = Count << 10 | Cur;
            Count = 0;
          }
          fwrite(&t,sizeof(SHORT),1,SaveFile);
          Word++;
        }
        Count = 1;
        Cur = *CountPtr;
      }
    }

    /*
     * Break the last one up into chunks
     */
    while (Count) {
      if (Count > 63) {
        t = 63 << 10 | Cur;
        Count -= 63;
      } else {
        t = Count << 10 | Cur;
        Count = 0;
      }
      fwrite(&t,sizeof(SHORT),1,SaveFile);
      Word++;
    }

  } else {
    DispErrMsg("No Picture to save",0);
    fclose(SaveFile);
    return(0);
  }
  fclose(SaveFile);
} /* SaveCounts */

/*
 * Load the state of the program from file
 */
LoadCounts(LoadName)
  char *LoadName;
{
  FILE  *LoadFile;
  SHORT *CountPtr;
  LONG   i;
  ULONG  Count,Word = 0;
  USHORT t;
  USHORT ViewModes;
  UBYTE  Depth;
  UBYTE  Header[5];
  ULONG  Version;
  char   ErrMsg[80];

  /*
   * Change the mouse pointer to Sleepy pointer
   */

  SetSleepyPointer();

  LoadFile = fopen(LoadName,"r");

  if (CountBase) {
    FreeMem(CountBase,CountX*CountY*sizeof(SHORT));
    CountBase = (SHORT *) NULL;
  }

  if (LoadFile == (FILE *) NULL) {

    /*
     * can't read a non-existant file
     */
    sprintf(ErrMsg, "File %s not found", LoadName);
    DispErrMsg(ErrMsg, 0);
    return(-1);
  } else {
    /*
     * Read and check the file header
     */
    fread((char *) &Header[0], 4, 1, LoadFile);
    Header[4] = '\0';

    if (strcmp(&Header[0], "MAND") != 0) {

      /*
       * File of improper format
       */
      sprintf(ErrMsg, "File %s is not a MAND file",LoadName);
      DispErrMsg(ErrMsg, 0);
      fclose(LoadFile);
      return(-1);

    } else {

      /*
       * Read in the version
       */
      fread((char *) &Version, sizeof(Version), 1, LoadFile);

      /*
       * Read in the locationin the complex plane
       */
      fread((char *) &StartX, sizeof(float), 1, LoadFile);
      fread((char *) &StartY, sizeof(float), 1, LoadFile);
      fread((char *) &EndX,   sizeof(float), 1, LoadFile);
      fread((char *) &EndY,   sizeof(float), 1, LoadFile);

      /*
       * Read in the maximum iteration count for a given point
       */
      fread((char *) &MaxCount, sizeof(SHORT), 1, LoadFile);

      /*
       * Read in the generator type
       */
      fread((char *) &MandType, sizeof(MandType), 1, LoadFile);

      /*
       * Read in the calculation time
       */
      fread((char *) &CalcTime, sizeof(CalcTime), 1, LoadFile);

      /*
       * Read in the screen's viewmodes
       */
      fread((char *) &ViewModes, sizeof(ViewModes), 1, LoadFile);

      /*
       * Read in the number of bit planes
       */
      fread((char *) &Depth, sizeof(Depth), 1, LoadFile);

      /*
       * Read in the window flags
       */
      fread((char *) &BorderType, sizeof(BorderType), 1, LoadFile);

      /*
       * Read in the color palette information
       */
      fread((char *) &SavePalette[0], sizeof(SHORT), 32, LoadFile);

      /*
       * Read in the number of contours
       */
      fread((char *) &NumContours, sizeof(NumContours), 1, LoadFile);

      /*
       * Read in the heights
       */
      fread((char *) ContourBase, sizeof(SHORT), (long) NumContours, LoadFile);

      /*
       * Read in the pen numbers (Color is a misnomer)
       */
      fread((char *) ColorBase, sizeof(UBYTE), (long) NumContours, LoadFile);

      /*
       * Put out the image dimensions
       */
      fread((char *) &CountX,   sizeof(SHORT),  1, LoadFile);
      fread((char *) &CountY,   sizeof(SHORT),  1, LoadFile);

      /*
       * try to allocate the space for the picture's iteration counts
       */
      CountBase = (SHORT *) AllocMem(CountX*CountY*sizeof(SHORT),0);

      if (CountBase == (SHORT *) NULL) {
        DispErrMsg("Can't load counts. Out of RAM!!",0);
        fclose(LoadFile);
        return(0);
      }

      CountPtr = CountBase;

      /* Load count information in pseudo RLL format */
      /* Bits 9-0 are iteration count.               */
      /* Bits 15-10 are how many iteration count of same height in a row */

      i = CountX*CountY;

      while (i > 0) {
        Word++;
        if (fread((char *) &t, sizeof(t), 1, LoadFile) == 0) {
          DispErrMsg("Premature EOF on source file",0);
          fclose(LoadFile);
          return(0);
        }
        Count = t >> 10;
        t = t & 0x3ff;
        for (; Count > 0; Count--) {
          *(CountPtr++) = t;
          i--;
        }
      }

      CalculateGaps();
    }
  }

  /*
   * Open a new screen
   */
  NewScreen.ViewModes = ViewModes;
  NewScreen.Depth = Depth;

  Inited = 0;
  CloseDisp();
  Inited = 1;
  OpenDisp();

  /*
   * Let's show it to them
   */
  ReColor();

  /*
   * Set No ZOOM
   */
  Zoom = 0;
  fclose(LoadFile);
} /* NewLoadCounts */

