/* LORD OF HOSTS - disk.c --- Lade- und Speicherroutinen */

#include "Lord.h"

struct ReqFileRequester MyFileReqStruct;
char filename[FCHARS+1];
char directoryname[DSIZE+1];
char load[] = "Wähle Spiel zum Laden...";
char save[] = "Spiel speichern als...";
char testplayers[2][16];
FILE *MyFile;
UBYTE testfval[16][8][8],testkval[16][8][8];
int testundopos,testundobot,testredotop,teststatus;
struct Piece testpieces[16];
struct Move testmoves[MAXUNDO];
extern struct Piece ThePieces[16];
extern UBYTE fval[16][8][8];
extern UBYTE kval[16][8][8];
extern UBYTE whatsonboard[8][8];
extern struct Move Moves[MAXUNDO];
extern int undopos, undobot, redotop, status, last_error;
extern int NumPieces[2];
extern char players[2][16];
extern BOOL joymouse_on, joymouse_allowed;

void FileError(int Error)
{
   switch(Error)
   {
      case ENOENT:
         SimpleRequest("Datei/Verzeichnis existiert nicht !");
         break;
      case EBADF:
         SimpleRequest("Falscher file descriptor !");
         break;
      case ENOMEM:
         SimpleRequest("Speichermangel !");
         break;
      case ENFILE:
         SimpleRequest("Zuviele offene Dateien !");
         break;
      case EACCES:
         SimpleRequest("Zugriff verweigert!");
         break;
      case EIO:
         SimpleRequest("E/A-Fehler (andere Disk)!");
         break;
      case ENOSPC:
         SimpleRequest("Diskette voll !");
         break;
      case EROFS:
         SimpleRequest("Nur Lesen möglich !");
         break;
      case EAGAIN:
         SimpleRequest("Datei ist leer !");
         break;
      default:
         SimpleRequest("Diskettenfehler !");
         break;
   }
}

BOOL checkrange(int Var, int lo, int hi)
{
   if (Var>=lo && Var<=hi) return TRUE;
   return FALSE;
}

void SaveGame(void)
{
   char filearray[DSIZE+FCHARS+2];
   int intsize=sizeof(int);
   int p,i,j;
   BOOL abort=FALSE;
   filearray[0] = 0;
   MyFileReqStruct.Title = save;
   MyFileReqStruct.PathName = filearray;  /* gesamter Pfad */
   MyFileReqStruct.Dir = directoryname;   /* Verzeichnis */
   MyFileReqStruct.File = filename;       /* File */
   MyFileReqStruct.Flags = FRQCACHINGM|FRQSAVINGM;
   MyFileReqStruct.dirnamescolor = 2;     /* andere Farben für Verzeichnisse */
   MyFileReqStruct.devicenamescolor = 2; /* und Devices */
   MyFileReqStruct.VersionNumber = REQVERSION;
   if (FileRequester(&MyFileReqStruct))
   {
      MyFile = fopen((const char *)filearray,"rb");
      if (MyFile)
      {
         fclose(MyFile);
         if (!TwoGadRequest("Datei existiert bereits.\nÜberschreiben?"))
            return;
      }
      MyFile = fopen((const char *)filearray,"wb");
      if (!MyFile)
      {
         FileError(errno);
         return;
      }
      fwrite(&undopos,intsize,1,MyFile);
      if (!ferror(MyFile)) fwrite(&undobot,intsize,1,MyFile);
      if (!ferror(MyFile)) fwrite(&redotop,intsize,1,MyFile);
      if (!ferror(MyFile)) fwrite(&status,intsize,1,MyFile);
      if (!ferror(MyFile)) fwrite(players,1,32,MyFile);
      if (!ferror(MyFile))
         for (p=0; p<=15; ++p)
         {
            fwrite(&ThePieces[p],sizeof(struct Piece),1,MyFile);
            for (i=0; i<=7; ++i)
               for (j=0; j<=7; ++j)
                  if (!ferror(MyFile))
                  {
                     fputc(fval[p][i][j],MyFile);
                     fputc(kval[p][i][j],MyFile);
                  }
         }
      if (!ferror(MyFile))
         for (i=0; i<MAXUNDO && abort == FALSE; ++i)
            if (!ferror(MyFile))
            {
               fwrite(&Moves[i],sizeof(struct Move),1,MyFile);
               if (Moves[i].fromx+Moves[i].fromy+Moves[i].tox+Moves[i].toy==0)
                  abort = TRUE;
            }
      if (ferror(MyFile)) FileError(errno);
      fclose(MyFile);
   }
}

void LoadGame(void)
{
   char filearray[DSIZE+FCHARS+2];
   int intsize=sizeof(int);
   int p,i,j,c;
   BOOL abort=FALSE;
   filearray[0] = 0;
   MyFileReqStruct.Title = load;
   MyFileReqStruct.PathName = filearray;  /* gesamter Pfad */
   MyFileReqStruct.Dir = directoryname;   /* Verzeichnis */
   MyFileReqStruct.File = filename;       /* File */
   MyFileReqStruct.Flags = FRQCACHINGM|FRQLOADINGM;
   MyFileReqStruct.dirnamescolor = 2;     /* andere Farben für Verzeichnisse */
   MyFileReqStruct.devicenamescolor = 2; /* und Devices */
   MyFileReqStruct.VersionNumber = REQVERSION;
   if (FileRequester(&MyFileReqStruct))
   {
      MyFile = fopen((const char *)filearray,"rb");
      if (!MyFile)
      {
         FileError(errno);
         return;
      }
      fread(&testundopos,intsize,1,MyFile);
      if (!(ferror(MyFile) || feof(MyFile))) fread(&testundobot,intsize,1,MyFile);
      if (!(ferror(MyFile) || feof(MyFile))) fread(&testredotop,intsize,1,MyFile);
      if (!(ferror(MyFile) || feof(MyFile))) fread(&teststatus,intsize,1,MyFile);
      if (!(ferror(MyFile) || feof(MyFile))) fread(testplayers,1,32,MyFile);
      if (!(ferror(MyFile) || feof(MyFile)))
         for (p=0; p<=15; ++p)
         {
            fread(&testpieces[p],sizeof(struct Piece),1,MyFile);
            for (i=0; i<=7; ++i)
               for (j=0; j<=7; ++j)
                  if (!(ferror(MyFile) || feof(MyFile)))
                  {
                     testfval[p][i][j]= fgetc(MyFile);
                     testkval[p][i][j]= fgetc(MyFile);
                  }
         }
      if (!(ferror(MyFile) || feof(MyFile)))
         for (c=0; c<MAXUNDO && abort == FALSE; ++c)
            if (!(ferror(MyFile) || feof(MyFile)))
            {
               fread(&testmoves[c],sizeof(struct Move),1,MyFile);
               if (testmoves[c].fromx+testmoves[c].fromy+
                   testmoves[c].tox+testmoves[c].toy==0)
                  abort = TRUE;
            }
      if (feof(MyFile))
      {
         SimpleRequest("Keine Lord Of Hosts Datei!\nDatei zu kurz!");
         fclose(MyFile);
         return;
      }
      if (ferror(MyFile))
      {
         FileError(errno);
         fclose(MyFile);
         return;
      }
      fclose(MyFile);
      if (!checkrange(testundopos,0,MAXUNDO-1) ||
          !checkrange(testundobot,0,MAXUNDO-1) ||
          !checkrange(testredotop,0,MAXUNDO-1))
      {
         SimpleRequest("Keine Lord Of Hosts Datei!\nIllegale Undo/Redo Daten!");
         return;
      }
      abort = FALSE;
      for (p=0; p<=15 && abort == FALSE; ++p)
         for (i=0; i<=7 && abort == FALSE; ++i)
            for (j=0; j<=7 && abort == FALSE; ++j)
               if (!checkrange(testfval[p][i][j],0,7) ||
                   !checkrange(testkval[p][i][j],0,7))
                  abort = TRUE;
      if (abort)
      {
         SimpleRequest("Keine Lord Of Hosts Datei!\nFalsche Werte!");
         return;
      }
      for (i=0; i<=c && abort == FALSE; ++i)
         if (!checkrange(testmoves[i].fromx,0,7) ||
             !checkrange(testmoves[i].fromy,0,7) ||
             !checkrange(testmoves[i].tox,0,7) ||
             !checkrange(testmoves[i].toy,0,7))
            abort = TRUE;
      if (abort)
      {
         SimpleRequest("Keine Lord Of Hosts Datei! Falsche Züge!");
         return;
      }
      /* File scheint OK, wenn er bis hierhin gekommen ist */
      clear_board();
      drawboard();
      undopos=testundopos;
      undobot=testundobot;
      redotop=testredotop;
      status =teststatus;
      strcpy(players[0],testplayers[0]);
      strcpy(players[1],testplayers[1]);
      drawplayers(players[0],players[1]);
      for (i=0; i<=c; ++i)
         Moves[i] = testmoves[i];
      NumPieces[0]=NumPieces[1]=0;
      for (p=0; p<=15; ++p)
      {
         for (i=0; i<=7; ++i)
            for (j=0; j<=7; ++j)
            {
               fval[p][i][j] = testfval[p][i][j];
               kval[p][i][j] = testkval[p][i][j];
            }
         ThePieces[p]=testpieces[p];
         if (ThePieces[p].StillAlive)
         {
            NumPieces[(p>7)]++;
            whatsonboard[ThePieces[p].x][ThePieces[p].y] = p;
            SetPiece(ThePieces[p],FALSE,FALSE);
         }
      }
      if (status & PLAYER1_TO_MOVE)
      {
         NextPlayer(RED);
      }
      else NextPlayer(WHITE);
      last_error = 0;
   }
}
