// Code fragments taken from the FARLOAD.CPP actually used in Farandole.
// This should allow you to use FAR files in your own programs.
// by Daniel Potter/Digital Infinity

void GenLoad(FILE *f,dword len,byte xv,int sn) {
  byte  far *q;
  dword aq,a,ss,so;

  for (a=0;a<(len/0xFFFF);a++) {
    q=(char far *)malloc(0xFFFF);
    if (q) {
      aq=fread(q,0xFFFF,1,f);
      for (aq=0;aq<0xFFFF;aq++) q[aq]^=xv;
    }
    ss=HighPtr>>16; so=HighPtr&0xFFFF;
    HighPtr=Music.LoadSample(ss,so,
                             0xFFFF,
                             (char far *)q);
    farfree(q);
  }
  if (len%0xFFFF) {
    q=(char far *)malloc(len%0xFFFF);
    if (q) {
      aq=fread(q,len%0xFFFF,1,f);
      for (aq=0;aq<len%0xFFFF;aq++) q[aq]^=xv;
    }
    ss=HighPtr>>16; so=HighPtr&0xFFFF;
    HighPtr=Music.LoadSample(ss,so,
                             len%0xFFFF,
                             (char far *)q);
    farfree(q);
  }
}

void LoadFSM(char *fn,word n) {
  byte far *q;
  char Header[5]={0};
  FILE *f;

  Saving=ON;
  StopMusic();

  f=fopen(fn,"rb");
  if (!f) {
    Saving=OFF;
    return;
  }

  Saved=FALSE;
  fread(&Header,4,1,f);                // Read 'header'
  if (strcmp(Header,"FSMū")) {
    fclose(f);
    Saving=OFF;
    return;
  }
  fread(&Sample[n].Name,32,1,f);       // Read sample name
  fread(&Header,3,1,f);                // Get past junk
  fread(&Sample[n].Len,4,1,f);         // Read sample length
  fread(&Sample[n].FineTune,1,1,f);    // Read finetune byte
  fread(&Sample[n].Volume,1,1,f);      // Read default volume byte
  fread(&Sample[n].Rep,4,1,f);         // Read repeat start
  fread(&Sample[n].RepEnd,4,1,f);      // Read repeat end
  fread(&Sample[n].SType,1,1,f);       // Read sample type byte
  fread(&Sample[n].LoopMode,1,1,f);    // 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) {
    Sample[n].Seg=HighPtr>>16;
    Sample[n].Off=HighPtr&0xFFFF;
    GenLoad(f,Sample[n].Len,0,n);
  }
  else {
    Sample[n].Seg=0;
    Sample[n].Off=0;
  }
  fclose(f);
  Saving=OFF;
}

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) {
    Sample[n].Seg=HighPtr>>16;
    Sample[n].Off=HighPtr&0xFFFF;
    GenLoad(i,Sample[n].Len,0,n);
  }
  else {
    Sample[n].Seg=0;
    Sample[n].Off=0;
  }
}

void LoadSong(char *fn) {
  FILE  *i;
  char  Magic1[]="FARū";
  char  Magic2[]={13,10,26};
  Flag  SMap[256/8]={0};
  word  q,HdrLen;

  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);
  if (STLen<=5544)
    fread(&SongText[0],STLen,1,i);
  else {
    fread(&SongText[0],5544,1,i);
    fseek(i,STLen-5544,SEEK_CUR);
  }
  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);

  memset(&Sample[0],0,sizeof(Sample));
  HighPtr=0;
  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;
}

