// THIS IS THE SAVE/LOAD MODULE FROM FARANDOLE COMPOSER! THIS IS NOT COMPLETE
// BUT YOU MAY USE ANY PIECE OF CODE FROM HERE IF YOU CREDIT ME!

#include "Far.HPP"
#include <IO.H>

void LoadOneFSM(word n,FILE *i) {
  byte far *q;

  fread(&Sample[n].Name,32,1,i);       // Read sample name
  fread(&Sample[n].Len,4,1,i);         // Read sample length
  fread(&Sample[n].FineTune,1,1,i);    // Read finetune byte
  fread(&Sample[n].Volume,1,1,i);      // Read default volume byte
  fread(&Sample[n].Rep,4,1,i);         // Read repeat start
  fread(&Sample[n].RepEnd,4,1,i);      // Read repeat end
  fread(&Sample[n].SType,1,1,i);       // Read sample type byte
  fread(&Sample[n].LoopMode,1,1,i);    // Read loop mode byte

  if (Sample[n].RepEnd<5) {
    Sample[n].RepEnd=Sample[n].Len;
    Sample[n].LoopMode=0;
  }
  else
    Sample[n].LoopMode=(1<<3);

  if (Sample[n].SType&1) Sample[n].LoopMode|=(1<<2);

  if (Sample[n].Len>0) {
    q=(char far *)malloc(Sample[n].Len);
    if (q) {
      fread(q,Sample[n].Len,1,i);          // Read sample data
    }
    Sample[n].Seg=HighPtr>>16;
    Sample[n].Off=HighPtr&0xFFFF;
    HighPtr=Music.LoadSample(Sample[n].Seg,Sample[n].Off,
                             Sample[n].Len,
                             (char far *)q);
    farfree(q);
  }
  else {
    Sample[n].Seg=0;
    Sample[n].Off=0;
  }
}

void SaveOneFSM(word n,FILE *i) {
  byte  far *q;
  dword kk;

  if (Sample[n].LoopMode&(1<<3))
    kk=Sample[n].RepEnd;
  else
    kk=0;

  fwrite(&Sample[n].Name,32,1,i);       // Write sample name
  fwrite(&Sample[n].Len,4,1,i);         // Write sample length
  fwrite(&Sample[n].FineTune,1,1,i);    // Write finetune byte
  fwrite(&Sample[n].Volume,1,1,i);      // Write default volume byte
  fwrite(&Sample[n].Rep,4,1,i);         // Write repeat start
  fwrite(&kk,4,1,i);                    // Write repeat end
  fwrite(&Sample[n].SType,1,1,i);       // Write sample type byte
  fwrite(&Sample[n].LoopMode,1,1,i);    // Write loop mode byte

  if (Sample[n].Len>0) {
    q=(char far *)malloc(Sample[n].Len);
    if (q)
      Music.SaveSample(Sample[n].Seg,Sample[n].Off,
                       Sample[n].Len,(char far *)q);

    fwrite(q,Sample[n].Len,1,i);        // Write sample data
    farfree(q);
  }
}

void SaveSong(char *fn) {
  FILE  *i;
  char  Magic1[]="FARū";
  char  Magic2[]={13,10,26};
  char  t[80];
  Flag  SMap[256/8]={0};
  word  q,HLen=869+STLen;
  byte  lq;

  Saving=ON;
  Saved=TRUE;
  strcpy(t,SongDir);
  strcat(t,"\\");
  strcat(t,fn);
  i=fopen(t,"wb");
  if (!i) {
    Saving=OFF;
    return;
  }

  if (Playing) StopMusic();
  PutAwayPat(CurPattern);

  fwrite(&Magic1[0],4,1,i);
  fwrite(&SongName[0],40,1,i);
  fwrite(&Magic2[0],3,1,i);
  fwrite(&HLen,2,1,i);
  fputc(0x10,i);
  fwrite(&ChanOn[0],16,1,i);
  fwrite(&CurOct,1,1,i);
  fwrite(&CurVoice,1,1,i);
  fwrite(&CurRow,1,1,i);
  fwrite(&CurPattern,1,1,i);
  fwrite(&CurOrder,1,1,i);
  fwrite(&CurSample,1,1,i);
  fwrite(&CurVol,1,1,i);
  fwrite(&CurTop,1,1,i);
  fwrite(&CurArea,1,1,i);
  fwrite(&CurTempo,1,1,i);
  fwrite(&CurBalance[0],16,1,i);
  fwrite(&MarkTop,1,1,i);
  fwrite(&MarkBot,1,1,i);
  fwrite(&Grid,1,1,i);
  fwrite(&EditMode,1,1,i);
  fwrite(&STLen,2,1,i);
  fwrite(&SongText[0],STLen,1,i);
  fwrite(&Order[0],256,1,i);
  fwrite(&NumPatterns,1,1,i);
  fwrite(&OrdLen,1,1,i);
  fwrite(&LoopTo,1,1,i);
  fwrite(&PatSize,sizeof(PatSize),1,i);

  for (q=0;q<256;q++) if (PatStore[q]) fwrite(PatStore[q],PatSize[q],1,i);

  for (q=0;q<255;q++) {
    if (Sample[q].Len || Sample[q].Name[0]) {
      SMap[q/8]|=(1<<(q%8));
    }
  }

  fwrite(&SMap[0],8,1,i);

  for (q=0;q<255;q++) {
    if (Sample[q].Len || Sample[q].Name[0]) {
      SaveOneFSM(q,i);
    }
  }

  fclose(i);
  Saving=OFF;
}

void LoadSong(char *fn) {
  FILE  *i;
  char  Magic1[]="FARū";
  char  Magic2[]={13,10,26};
  char  t[80];
  Flag  SMap[256/8]={0};
  word  q,HdrLen;
  byte  lq;

  i=fopen(fn,"rb");
  if (!i) return;
  fread(&Magic1[0],4,1,i);
  if (strcmp(Magic1,"FARū")) {
    fclose(i);
    return;
  }
  Saving=ON;
  if (Playing) StopMusic();
  FreeSong();
  Saved=TRUE;
  strcpy(DosName,fn);

  fread(&SongName[0],40,1,i);
  fread(&Magic2[0],3,1,i);
  fread(&HdrLen,2,1,i);
  fgetc(i);
  fread(&ChanOn[0],16,1,i);
  fread(&CurOct,1,1,i);
  fread(&CurVoice,1,1,i);
  fread(&CurRow,1,1,i);
  fread(&CurPattern,1,1,i);
  fread(&CurOrder,1,1,i);
  fread(&CurSample,1,1,i);
  fread(&CurVol,1,1,i);
  fread(&CurTop,1,1,i);
  fread(&CurArea,1,1,i);
  fread(&CurTempo,1,1,i);
  fread(&CurBalance[0],16,1,i);
  fread(&MarkTop,1,1,i);
  fread(&MarkBot,1,1,i);
  fread(&Grid,1,1,i);
  fread(&EditMode,1,1,i);
  fread(&STLen,2,1,i);
  fread(&SongText[0],STLen,1,i);
  fread(&Order[0],256,1,i);
  fread(&NumPatterns,1,1,i);
  fread(&OrdLen,1,1,i);
  fread(&LoopTo,1,1,i);
  fread(&PatSize,sizeof(PatSize),1,i);
  if (HdrLen-(869+STLen))
    fseek(i,HdrLen-(869+STLen),SEEK_CUR);

  for (q=0;q<256;q++)
    if (PatSize[q]) {
      PatStore[q]=(char *)malloc(PatSize[q]);
      fread(PatStore[q],PatSize[q],1,i);
    }

  fread(&SMap[0],8,1,i);

  for (q=0;q<255;q++)
    if (SMap[q/8] & (1<<(q%8)))
      LoadOneFSM(q,i);

  fclose(i);
  memset(&Pattern[0],0,sizeof(Pattern));
  GetPat(CurPattern);
  sScreen();
  Saving=OFF;
}

