home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / far100.zip / FILE.C < prev    next >
Text File  |  1994-08-05  |  57KB  |  2,277 lines

  1. /* Farandole Composer 1.00 (c)'94 Daniel Potter */
  2.  
  3. /* This file contains code for all the loading and saving operations involved
  4.    in far. May it bring you many happy hours of hacking. */
  5.  
  6. #include "defaults.h"
  7. #include "stdio.h"
  8. #include "far.h"
  9. #include "gus.h"
  10. #include "alloc.h"
  11. #include "dir.h"
  12. #include "dos.h"
  13. #include "kb.h"
  14. #include "io.h"
  15. #include "string.h"
  16.  
  17. void FormLoad(char *t) {
  18.   char str[80];
  19.  
  20.   sprintf(str," Loading %s format",t);
  21.   Msgnw(str);
  22. }
  23.  
  24. void FormSave(char *t) {
  25.   char str[80];
  26.  
  27.   sprintf(str," Saving %s format",t);
  28.   Msgnw(str);
  29. }
  30.  
  31. void LStat(int n) {
  32.   DrawF(120,42,11,9,"   %d    ",n);
  33. }
  34.  
  35. // ******************************************** Little directory selector box
  36.  
  37. char far *Names[1024]={NULL},*fnames[1024]={NULL};
  38. extern Flag LoadName;
  39.  
  40. void NameSort(int l,int r) {
  41.   int  i,j;
  42.   char x[32],y[32],q[32];
  43.  
  44.   i=l; j=r; strcpy(x,Names[(l+r)/2]);
  45.   do {
  46.     while (strcmp(Names[i],x)<0) i++;
  47.     while (strcmp(x,Names[j])<0) j--;
  48.     if (i<=j) {
  49.       strcpy(y,Names[i]); strcpy(Names[i],Names[j]);  strcpy(Names[j],y);
  50.       strcpy(q,fnames[i]);strcpy(fnames[i],fnames[j]);strcpy(fnames[j],q);
  51.       i++; j--;
  52.     }
  53.   } while (!(i>j));
  54.   if (l<j) NameSort(l,j);
  55.   if (i<r) NameSort(i,r);
  56. }
  57.  
  58. void TNameSort(int l,int r)  {
  59.   word q;
  60.  
  61.   for (q=l;q<=r;q++)
  62.     if (!Names[q][0]) {
  63.       Names[q][0]='■';
  64.       Names[q][1]=0;
  65.     }
  66.   NameSort(l,r);
  67.   for (q=l;q<=r;q++)
  68.     if (Names[q][0]=='■') Names[q][0]=0;
  69. }
  70.  
  71. void FNameSort(int l,int r) {
  72.   int  i,j;
  73.   char x[32],y[32],q[32];
  74.  
  75.   i=l; j=r; strcpy(x,fnames[(l+r)/2]);
  76.   do {
  77.     while (strcmp(fnames[i],x)<0) i++;
  78.     while (strcmp(x,fnames[j])<0) j--;
  79.     if (i<=j) {
  80.       strcpy(y,Names[i]); strcpy(Names[i],Names[j]);  strcpy(Names[j],y);
  81.       strcpy(q,fnames[i]);strcpy(fnames[i],fnames[j]);strcpy(fnames[j],q);
  82.       i++; j--;
  83.     }
  84.   } while (!(i>j));
  85.   if (l<j) FNameSort(l,j);
  86.   if (i<r) FNameSort(i,r);
  87. }
  88.  
  89. int ptr=0,namestart;
  90. void Rescan(char *mask) {
  91.   struct ffblk ffblk;
  92.   char   junk[4];
  93.   Flag   Done;
  94.   word   q;
  95.   FILE   *f;
  96.  
  97.   for (q=0;q<1024;q++) {
  98.     farfree(fnames[q]); fnames[q]=NULL;
  99.     farfree(Names[q]); Names[q]=NULL;
  100.   }
  101.  
  102.   ptr=0;
  103.   Done=findfirst("*.*",&ffblk,FA_DIREC);
  104.   while (!Done) {
  105.     if (ffblk.ff_attrib&FA_DIREC) {
  106.       farfree(fnames[ptr]);
  107.       fnames[ptr]=farmalloc(14);
  108.       if (!fnames[ptr]) return;
  109.       farfree(Names[ptr]); Names[ptr]=NULL;
  110.  
  111.       strcpy(fnames[ptr],ffblk.ff_name);
  112.       strupr(fnames[ptr]);
  113.       strcat(fnames[ptr],"\\");
  114.       if (strcmp(fnames[ptr],".\\")) ptr++;
  115.     }
  116.     Done=findnext(&ffblk);
  117.   }
  118.   UpdateStat();
  119.   namestart=ptr;
  120.   FNameSort(0,namestart-1);
  121.   Done=findfirst(mask,&ffblk,FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCH);
  122.   while (!Done) {
  123.     if (!(ffblk.ff_attrib&FA_DIREC)) {
  124.       farfree(Names[ptr]);
  125.       Names[ptr]=farmalloc(34);
  126.       if (!Names[ptr]) return;
  127.       farfree(fnames[ptr]);
  128.       fnames[ptr]=farmalloc(14);
  129.       if (!fnames[ptr]) return;
  130.  
  131.       memset(Names[ptr],0,33);
  132.       memset(fnames[ptr],0,13);
  133.       strcpy(fnames[ptr],ffblk.ff_name);
  134.       q=strlen(fnames[ptr]);
  135.       strupr(fnames[ptr]);
  136.       if (LoadName) {
  137.         if (fnames[ptr][q-3]=='F' &&
  138.           (fnames[ptr][q-2]=='S' && fnames[ptr][q-1]=='M') ||
  139.           (fnames[ptr][q-2]=='A' && fnames[ptr][q-1]=='R') ||
  140.           (fnames[ptr][q-2]=='P' && fnames[ptr][q-1]=='T')) {
  141.           f=fopen(fnames[ptr],"rb");
  142.           fread(junk,4,1,f);
  143.           fread(Names[ptr],31,1,f);
  144.           fclose(f);
  145.         }
  146.         if (fnames[ptr][q-3]=='S' && fnames[ptr][q-2]=='T' &&
  147.             fnames[ptr][q-1]=='S') {
  148.           f=fopen(fnames[ptr],"rb");
  149.           fseek(f,0x30,SEEK_SET);
  150.           fread(Names[ptr],28,1,f);
  151.           fclose(f);
  152.         }
  153.         if (fnames[ptr][q-3]=='6' && fnames[ptr][q-2]=='6' &&
  154.             fnames[ptr][q-1]=='9') {
  155.           f=fopen(fnames[ptr],"rb");
  156.           fread(junk,2,1,f);
  157.           fread(Names[ptr],31,1,f);
  158.           fclose(f);
  159.         }
  160.         if (fnames[ptr][q-3]=='M' && fnames[ptr][q-2]=='O' &&
  161.             fnames[ptr][q-1]=='D') {
  162.           f=fopen(fnames[ptr],"rb");
  163.           fread(Names[ptr],20,1,f);
  164.           fclose(f);
  165.         }
  166.         if (fnames[ptr][q-3]=='M' && fnames[ptr][q-2]=='T' &&
  167.             fnames[ptr][q-1]=='M') {
  168.           f=fopen(fnames[ptr],"rb");
  169.           fseek(f,4,SEEK_SET);
  170.           fread(Names[ptr],20,1,f);
  171.           fclose(f);
  172.         }
  173.         if (fnames[ptr][q-3]=='U' && fnames[ptr][q-2]=='L' &&
  174.             fnames[ptr][q-1]=='T') {
  175.           f=fopen(fnames[ptr],"rb");
  176.           fseek(f,15,SEEK_SET);
  177.           fread(Names[ptr],32,1,f);
  178.           fclose(f);
  179.         }
  180.         if (fnames[ptr][q-3]=='S' &&
  181.             (fnames[ptr][q-2]=='T' || fnames[ptr][q-2]=='3') &&
  182.             fnames[ptr][q-1]=='M') {
  183.           f=fopen(fnames[ptr],"rb");
  184.           memset(Names[ptr],0,32);
  185.           switch (fnames[ptr][q-2]) {
  186.             case 'T':
  187.               fread(Names[ptr],20,1,f);
  188.               break;
  189.             case '3':
  190.               fread(Names[ptr],28,1,f);
  191.               break;
  192.           }
  193.           fclose(f);
  194.         }
  195.       }
  196.       ptr++;
  197.     }
  198.     Done=findnext(&ffblk);
  199.   }
  200.   for (q=ptr;q<1024;q++) {
  201.     farfree(Names[q]); Names[q]=NULL;
  202.     farfree(fnames[q]); fnames[q]=NULL;
  203.   }
  204.   switch (SortBoxBy) {
  205.     case 0:
  206.       FNameSort(namestart,ptr-1);
  207.       break;
  208.     case 1:
  209.       TNameSort(namestart,ptr-1);
  210.       break;
  211.   }
  212.   UpdateStat();
  213. }
  214.  
  215. void ReDraw(int top,int CurFile) {
  216.   int q;
  217.  
  218.   DrawF(0,9, 0,4,"      ,,PGUP,PGDN to move around, ENTER to load a file, ESC to abort, D to change drives, Z/Q/F8 to audition loaded samples       ");
  219.   DrawF(0,10,0,4,"  Filename                        Title                                                                                             ");
  220.   for (q=top;q<(ptr+top) && q<((42-12)+top);q++) {
  221.     if (fnames[q]!=NULL && Names[q]!=NULL) {
  222.       DrawF(0,12+(q-top),8,2,"%-13s                %-32s",fnames[q],Names[q]);
  223.     }
  224.     if (fnames[q]!=NULL && Names[q]==NULL) {
  225.       DrawF(0,12+(q-top),8,2,"%-13s                %-32s",fnames[q],"                                 ");
  226.     }
  227.     if (fnames[q]==NULL && Names[q]!=NULL) {
  228.       DrawF(0,12+(q-top),8,2,"%-13s                %-32s","             ",Names[q]);
  229.     }
  230.     if (fnames[q]==NULL && Names[q]==NULL) {
  231.       DrawF(0,12+(q-top),8,2,"%-13s                %-32s","             ","                                 ");
  232.     }
  233.   }
  234.   Color(0,12+(CurFile-top),131,12+(CurFile-top),2,8);
  235. }
  236.  
  237. void LoadOneSmp(char *f);
  238. word DirSelect(char *mask,char *out) {
  239.   int    q,CurFile=0,k=0,top=0;
  240.   char   d[80],rval;
  241.  
  242.   Video(0);
  243.   MusicMode=OFF;
  244.   StopMusic();
  245.   UpdateStat();
  246.   Rescan(mask);
  247.   if (SaveBoxPos) {
  248.     CurFile=LastFile&0xFF;
  249.     top=LastFile>>8;
  250.     if (CurFile>=ptr) {
  251.       CurFile=0;
  252.       top=0;
  253.     }
  254.   }
  255.   Fill(0,9,131,41,8,2,' ');
  256.   ReDraw(top,CurFile);
  257.   while (k!=ENTER && k!=ESC) {
  258.     k=GetCh();
  259.     switch(k) {
  260.       case '/':
  261.       case '*':
  262.       case 'Q':
  263.       case 'Z':
  264.         LKHit=k;
  265.         CustomHandle();
  266.         break;
  267.       case F8:
  268.         GlobalKey(k);
  269.         break;
  270.       case 'D':
  271.         DrawF(0,42,11,9," Change drive: Enter new drive ->                                                                                                   ");
  272.         k=0;
  273.         while (!k) k=GetCh();
  274.         if (k!=27) {
  275.           setdisk(k-'A');
  276.           Rescan(mask);
  277.           top=0;
  278.           CurFile=0;
  279.           Fill(0,9,131,41,8,2,' ');
  280.           ReDraw(top,CurFile);
  281.         }
  282.         UpdateStat();
  283.         break;
  284.       case CURSUP:
  285.         if (Shift) {
  286.           Color(0,12+(CurFile-top),131,12+(CurFile-top),8,2);
  287.           if (CurFile>0) {
  288.             CurFile--;
  289.             if (CurFile<top) {
  290.               top--;
  291.               ReDraw(top,CurFile);
  292.             }
  293.           }
  294.           Color(0,12+(CurFile-top),131,12+(CurFile-top),2,8);
  295.         }
  296.         else {
  297.           if (CurSample>0) CurSample--;
  298.           UpdateSamples();
  299.         }
  300.         break;
  301.       case CURSDN:
  302.         if (Shift) {
  303.           Color(0,12+(CurFile-top),131,12+(CurFile-top),8,2);
  304.           if (CurFile<ptr-1) {
  305.             CurFile++;
  306.             if ((CurFile-top)>(42-13)) {
  307.               top++;
  308.               ReDraw(top,CurFile);
  309.             }
  310.           }
  311.           Color(0,12+(CurFile-top),131,12+(CurFile-top),2,8);
  312.         }
  313.         else {
  314.           if (CurSample<63) CurSample++;
  315.           UpdateSamples();
  316.         }
  317.         break;
  318.       case ' ':
  319.         LoadOneSmp(fnames[CurFile]);
  320.         UpdateSamples();
  321.         break;
  322.       case PGDOWN:
  323.         Color(0,12+(CurFile-top),131,12+(CurFile-top),8,2);
  324.         if ((CurFile-top)==(42-13)) {
  325.           if ((top+13)<ptr) {
  326.             top+=(42-13);
  327.             if ((top+(42-13))>=ptr)top=ptr-(42-13)-1;
  328.             CurFile=top+(42-13);
  329.             ReDraw(top,CurFile);
  330.           }
  331.         }
  332.         else {
  333.           CurFile=top+(42-13);
  334.         }
  335.         Color(0,12+(CurFile-top),131,12+(CurFile-top),2,8);
  336.         break;
  337.       case PGUP:
  338.         Color(0,12+(CurFile-top),131,12+(CurFile-top),8,2);
  339.         if (CurFile==top) {
  340.           if (top>0) {
  341.             top-=(42-13);
  342.             if (top<0) top=0;
  343.             CurFile=top;
  344.             ReDraw(top,CurFile);
  345.           }
  346.         }
  347.         else
  348.           CurFile=top;
  349.         Color(0,12+(CurFile-top),131,12+(CurFile-top),2,8);
  350.         break;
  351.       case ENTER:
  352.         if (CurFile<namestart) {
  353.           Color(0,12+(CurFile-top),131,12+(CurFile-top),8,2);
  354.           strcpy(d,fnames[CurFile]);
  355.           d[strlen(d)-1]=0;
  356.           chdir(d);
  357.           CurFile=0;
  358.           top=0;
  359.           Rescan(mask);
  360.           Fill(0,9,131,41,8,2,' ');
  361.           DrawF(0,9, 0,4,"      ,,PGUP,PGDN to move around, ENTER to load a file, ESC to abort, D to change drives, Z/Q/F8 to audition loaded samples       ");
  362.           DrawF(0,10,0,4,"  Filename                        Title                                                                                             ");
  363.           ReDraw(top,CurFile);
  364.           k=0;
  365.           Color(0,12+(CurFile-top),131,12+(CurFile-top),2,8);
  366.         }
  367.         break;
  368.     }
  369.   }
  370.   Fill(0,9,131,41,8,2,' ');
  371.   UpdateChans();
  372.   ScrArea(CurArea);
  373.   MusicMode=ON;
  374.   if (k==ENTER) {
  375.     strcpy(out,fnames[CurFile]);
  376.     if (SaveBoxPos)
  377.       LastFile=CurFile|(top<<8);
  378.     else
  379.       LastFile=0;
  380.     rval=1;
  381.   }
  382.   else {
  383.     if (SaveBoxPos)
  384.       LastFile=CurFile|(top<<8);
  385.     else
  386.       LastFile=0;
  387.     rval=0;
  388.   }
  389. Return:
  390.   for (q=0;q<1024;q++) {
  391.     if (fnames[q]) { farfree(fnames[q]); fnames[q]=NULL; }
  392.     if (Names[q]) { farfree(Names[q]); Names[q]=NULL; }
  393.   }
  394.   UpdateStat();
  395.   return rval;
  396. }
  397.  
  398. // ******************** SAMPLE LOADING FUNCTIONS **************************
  399. int GenLoad(FILE *f,dword len,byte xv,int sn) {
  400.   byte  far *q;
  401.   dword aq,a,ss,so;
  402.  
  403.   for (a=0;a<(len/0xFFFF);a++) {
  404.     q=(char far *)farmalloc(0xFFFF);
  405.     if (q) {
  406.       aq=fread(q,0xFFFF,1,f);
  407.       for (aq=0;aq<0xFFFF;aq++) q[aq]^=xv;
  408.     }
  409.     else return 0;
  410.     ss=HighPtr>>16; so=HighPtr&0xFFFF;
  411.     HighPtr=LoadSample(ss,so,
  412.                        0xFFFF,
  413.                        (char far *)q);
  414.     farfree(q);
  415.   }
  416.   if (len%0xFFFF) {
  417.     q=(char far *)farmalloc((len%0xFFFF)+32);
  418.     if (q) {
  419.       aq=fread(q,len%0xFFFF,1,f);
  420.       for (aq=0;aq<len%0xFFFF;aq++) q[aq]^=xv;
  421.     }
  422.     else return 0;
  423.     memcpy(&q[(len%0xFFFF)],&q[Sample[sn].Rep],32);
  424.     ss=HighPtr>>16; so=HighPtr&0xFFFF;
  425.     HighPtr=LoadSample(ss,so,
  426.                        (len%0xFFFF)+32,
  427.                        (char far *)q);
  428.     farfree(q);
  429.   }
  430.   return 1;
  431. }
  432.  
  433. int GenSave(FILE *f,dword len,byte xv,dword segs,dword offs) {
  434.   byte  far *q;
  435.   dword aq,a,ss,so,hp;
  436.  
  437.   hp=(segs<<16)|offs;
  438.   for (a=0;a<(len/0xFFFF);a++) {
  439.     ss=hp>>16; so=hp&0xFFFF;
  440.     q=(char far *)farmalloc(0xFFFF);
  441.     if (q)
  442.       hp=GetSample(ss,so,0xFFFF,(char far *)q);
  443.     else return 0;
  444.     for (aq=0;aq<0xFFFF;aq++) q[aq]^=xv;
  445.     fwrite(q,0xFFFF,1,f);        // Write sample data
  446.     farfree(q);
  447.   }
  448.   if (len%0xFFFF) {
  449.     ss=hp>>16; so=hp&0xFFFF;
  450.     q=(char far *)farmalloc(len%0xFFFF);
  451.     if (q)
  452.       hp=GetSample(ss,so,len%0xFFFF,(char far *)q);
  453.     else return 0;
  454.     for (aq=0;aq<len%0xFFFF;aq++) q[aq]^=xv;
  455.     fwrite(q,len%0xFFFF,1,f);        // Write sample data
  456.     farfree(q);
  457.   }
  458.   return 1;
  459. }
  460.  
  461. void CheckPreFile(char *fn,char *n) {
  462.   FILE *f;
  463.   char  t[80],*q;
  464.  
  465.   strupr(fn);
  466.   f=fopen(fn,"rb");
  467.   if (!f) return;
  468.   fread(t,32,1,f); t[32]=0;
  469.   if (strcmp(t+4,n)) {
  470.     q=strstr(fn,".")-1;
  471.     strcpy(t,q);
  472.     t[0]++;
  473.     if (t[0]>'Z') t[0]='A';
  474.     strcpy(q,t);
  475.     CheckPreFile(fn,n);
  476.   }
  477.   fclose(f);
  478. }
  479.  
  480. int SaveFSM(char *fn, word n) {
  481.   byte  far *q;
  482.   char  header[4]="FSM■";
  483.   char  k[3]={10,13,26};
  484.   dword kk;
  485.   FILE  *f;
  486.   char  t[80];
  487.   int   retval=1;
  488.  
  489.   Saving=ON;
  490.   strcpy(t,SampDir);
  491.   strcat(t,"\\");
  492.   strcat(t,fn);
  493.   CheckPreFile(t,Sample[n].Name);
  494.   f=fopen(t,"wb");
  495.   if (!f) {
  496.     Saving=OFF;
  497.     return;
  498.   }
  499.  
  500.   Saved=TRUE;
  501.   if (Sample[n].LoopMode&(1<<3))
  502.     kk=Sample[n].RepEnd;
  503.   else
  504.     kk=2;
  505.  
  506.   fwrite(header,4,1,f);                 // Write ident header
  507.   fwrite(&Sample[n].Name,32,1,f);       // Write sample name
  508.   fwrite(&k,3,1,f);                     // Write end of file
  509.   fwrite(&Sample[n].Len,4,1,f);         // Write sample length
  510.   fwrite(&Sample[n].FineTune,1,1,f);    // Write finetune byte
  511.   fwrite(&Sample[n].Volume,1,1,f);      // Write default volume byte
  512.   fwrite(&Sample[n].Rep,4,1,f);         // Write repeat start
  513.   fwrite(&kk,4,1,f);                    // Write repeat end
  514.   fwrite(&Sample[n].SType,1,1,f);       // Write sample type byte
  515.   fwrite(&Sample[n].LoopMode,1,1,f);    // Write loop mode byte
  516.  
  517.   if (Sample[n].Len>0)
  518.     if (!GenSave(f,Sample[n].Len,0,Sample[n].Seg,Sample[n].Off)) {
  519.       Msg("RAN OUT OF MEMORY!!! {push key}");
  520.       retval=0;
  521.     }
  522.   fclose(f);
  523.   Saving=OFF;
  524.   Alt=OFF;
  525.  
  526.   return retval;
  527. }
  528.  
  529. int LoadFSM(char *fn,word n) {
  530.   byte far *q;
  531.   char Header[5]={0};
  532.   FILE *f;
  533.   int  retval=1;
  534.  
  535.   Saving=ON;
  536.   StopMusic();
  537.  
  538.   f=fopen(fn,"rb");
  539.   if (!f) {
  540.     Saving=OFF;
  541.     return;
  542.   }
  543.  
  544.   fread(Header,4,1,f);                // Read 'header'
  545.   if (strcmp(Header,"FSM■")) {
  546.     fclose(f);
  547.     Saving=OFF;
  548.     return;
  549.   }
  550.   Saved=FALSE;
  551.   fread(Sample[n].Name,32,1,f);       // Read sample name
  552.   fread(Header,3,1,f);                // Get past junk
  553.   fread(&Sample[n].Len,4,1,f);         // Read sample length
  554.   fread(&Sample[n].FineTune,1,1,f);    // Read finetune byte
  555.   fread(&Sample[n].Volume,1,1,f);      // Read default volume byte
  556.   fread(&Sample[n].Rep,4,1,f);         // Read repeat start
  557.   fread(&Sample[n].RepEnd,4,1,f);      // Read repeat end
  558.   fread(&Sample[n].SType,1,1,f);       // Read sample type byte
  559.   fread(&Sample[n].LoopMode,1,1,f);    // Read loop mode byte
  560.  
  561.   if (Sample[n].RepEnd<5) {
  562.     Sample[n].RepEnd=Sample[n].Len;
  563.     Sample[n].LoopMode=0;
  564.   }
  565.   else
  566.     Sample[n].LoopMode=(1<<3);
  567.  
  568.   if (Sample[n].SType&1) Sample[n].LoopMode|=(1<<2);
  569.  
  570.   if (Sample[n].Len>0) {
  571.     Sample[n].Seg=HighPtr>>16;
  572.     Sample[n].Off=HighPtr&0xFFFF;
  573.     if (!GenLoad(f,Sample[n].Len,0,n)) {
  574.       Msg("RAN OUT OF MEMORY!!! {push key}");
  575.       retval=0;
  576.     }
  577.   }
  578.   else {
  579.     Sample[n].Seg=0;
  580.     Sample[n].Off=0;
  581.   }
  582.   fclose(f);
  583.   Saving=OFF;
  584.   return retval;
  585. }
  586.  
  587. int LoadSTS(char *fn,int n) {
  588.   byte far *q;
  589.   char Header[5]={0};
  590.   FILE *f;
  591.   int  retval=1;
  592.  
  593.   Saving=ON;
  594.   StopMusic();
  595.  
  596.   f=fopen(fn,"rb");
  597.   if (!f) {
  598.     Saving=OFF;
  599.     return;
  600.   }
  601.  
  602.   fseek(f,0x4c,SEEK_SET);
  603.   fread(Header,4,1,f); Header[4]=0;
  604.   if (strcmp(Header,"SCRS")) {
  605.     fclose(f);
  606.     Saving=OFF;
  607.     return;
  608.   }
  609.  
  610.   Saved=FALSE;
  611.  
  612.   fseek(f,0x10,SEEK_SET);              // Skip over header crap
  613.   fread(&Sample[n].Len,4,1,f);
  614.   fread(&Sample[n].Rep,4,1,f);
  615.   fread(&Sample[n].RepEnd,4,1,f);
  616.   fread(&Sample[n].Volume,1,1,f);
  617.   fgetc(f);
  618.   fread(&Sample[n].SType,1,1,f);
  619.   fseek(f,16,SEEK_CUR);
  620.   fread(Sample[n].Name,32,1,f);       // Read sample name
  621.  
  622.   if (Sample[n].SType&1)
  623.     Sample[n].LoopMode=(1<<3);
  624.   Sample[n].SType=0;
  625.  
  626.   if (Sample[n].RepEnd<5) {
  627.     Sample[n].RepEnd=Sample[n].Len;
  628.     Sample[n].LoopMode=0;
  629.   }
  630.   else
  631.     Sample[n].LoopMode=(1<<3);
  632.  
  633.   if (Sample[n].Len>0) {
  634.     Sample[n].Seg=HighPtr>>16;
  635.     Sample[n].Off=HighPtr&0xFFFF;
  636.     if (!GenLoad(f,Sample[n].Len,0,n)) {
  637.       Msg("RAN OUT OF MEMORY!!! {push key}");
  638.       retval=0;
  639.     }
  640.   }
  641.   else {
  642.     Sample[n].Seg=0;
  643.     Sample[n].Off=0;
  644.   }
  645.   fclose(f);
  646.   Saving=OFF;
  647.   return retval;
  648. }
  649.  
  650. int SaveUnsigned(char *fn,word n) {
  651.   byte far *q;
  652.   long aq;
  653.   FILE *f;
  654.   char t[80];
  655.   int  retval=1;
  656.  
  657.   Saving=ON;
  658.   strcpy(t,SampDir);
  659.   strcat(t,"\\");
  660.   strcat(t,fn);
  661.   f=fopen(t,"wb");
  662.   if (!f) {
  663.     Saving=OFF;
  664.     return;
  665.   }
  666.  
  667.   if (Sample[n].Len>0)
  668.     if (!GenSave(f,Sample[n].Len,128,Sample[n].Seg,Sample[n].Off)) {
  669.       Msg("RAN OUT OF MEMORY!!! {push key}");
  670.       retval=0;
  671.     }
  672.   fclose(f);
  673.   Saving=OFF;
  674.   Alt=OFF;
  675.   return retval;
  676. }
  677.  
  678. int LoadUnsigned(char *fn,word n) {
  679.   byte  far *q;
  680.   dword aq,a,ss,so;
  681.   FILE  *f;
  682.   int   retval=1;
  683.  
  684.   Saving=ON;
  685.   StopMusic();
  686.  
  687.   f=fopen(fn,"rb");
  688.   if (!f) {
  689.     Saving=OFF;
  690.     return;
  691.   }
  692.  
  693.   Saved=FALSE;
  694.   strcpy(Sample[n].Name,fn);
  695.   Sample[n].Len=filelength(fileno(f));
  696.   Sample[n].FineTune=0;
  697.   Sample[n].Volume=0xF;
  698.   Sample[n].Rep=0;
  699.   Sample[n].RepEnd=0;
  700.   Sample[n].SType=0;
  701.  
  702.   if (Sample[n].RepEnd<5) {
  703.     Sample[n].RepEnd=Sample[n].Len;
  704.     Sample[n].LoopMode=0;
  705.   }
  706.   else
  707.     Sample[n].LoopMode=(1<<3);
  708.  
  709.   if (Sample[n].SType&1) Sample[n].LoopMode|=(1<<2);
  710.  
  711.   if (Sample[n].Len>0) {
  712.     Sample[n].Seg=HighPtr>>16;
  713.     Sample[n].Off=HighPtr&0xFFFF;
  714.     if (!GenLoad(f,Sample[n].Len,128,n)) {
  715.       Msg("RAN OUT OF MEMORY!!! {push key}");
  716.       retval=0;
  717.     }
  718.   }
  719.   else {
  720.     Sample[n].Seg=0;
  721.     Sample[n].Off=0;
  722.   }
  723.   fclose(f);
  724.   Saving=OFF;
  725.   return retval;
  726. }
  727.  
  728. int LoadPAT(char *fn,word n) {
  729.   FILE   *f;
  730.   char   Header[9]={0};
  731.   word   NumSmp;
  732.   dword  len,rep,repend,curpos;
  733.   Flag   bit16=FALSE,loop=TRUE;
  734.   byte   ToLoad=0xFF,Flags;
  735.   long   k;
  736.   byte far *q,*q2;
  737.   int    retval=1;
  738.  
  739.   Saving=ON;
  740.   StopMusic();
  741.  
  742.   f=fopen(fn,"rb");
  743.   if (!f) {
  744.     Saving=OFF;
  745.     return;
  746.   }
  747.   fread(Header,8,1,f);
  748.   if (strcmp(Header,"GF1PATCH")) {
  749.     fclose(f);
  750.     Saving=OFF;
  751.     return;
  752.   }
  753.   fseek(f,85,SEEK_SET);
  754.   fread(&NumSmp,2,1,f); // Read number of samples
  755.   fseek(f,239,SEEK_SET); // Skip to first sample block
  756.   if (NumSmp>1) {
  757.     DrawF(0,42,11,9," LOAD WHICH SAMPLE (0-%X) OR ESC TO ABORT                                                                                            ",NumSmp-1);
  758.     Saving=OFF;
  759.     while (ToLoad>(NumSmp-1)) {
  760.       do {
  761.         k=GetCh();
  762.         if (k>='0' && k<='9') break;
  763.         if (k>='A' && k<='F') break;
  764.         if (k==27) break;
  765.       } while(1);
  766.       if (k>='0' && k<='9') ToLoad=k-'0';
  767.       if (k>='A' && k<='F') ToLoad=k-'A'+10;
  768.       if (k==27) {
  769.         fclose(f);
  770.         Saving=OFF;
  771.         return;
  772.       }
  773.     }
  774.     UpdateStat();
  775.     Saving=ON;
  776.   }
  777.   Saved=FALSE;
  778.  
  779.   if (ToLoad==255) ToLoad=0;
  780.   for (k=0;k<ToLoad;k++) {
  781.     curpos=ftell(f);        // Store first of patch block
  782.     fseek(f,8,SEEK_CUR);    // Skip to sample length
  783.     fread(&len,4,1,f);
  784.     fseek(f,curpos,SEEK_SET); // Skip past sample data+header
  785.     fseek(f,96+len,SEEK_CUR);
  786.   }
  787.   curpos=ftell(f);
  788.   fseek(f,8,SEEK_CUR);
  789.   fread(&len,4,1,f);
  790.   fread(&rep,4,1,f);
  791.   fread(&repend,4,1,f);
  792.   fseek(f,curpos,SEEK_SET); fseek(f,55,SEEK_CUR);
  793.   fread(&Flags,1,1,f); if (Flags&1) bit16=TRUE;
  794.   if (Flags&(1<<2)) loop=TRUE; else loop=FALSE;
  795.   fseek(f,curpos,SEEK_SET); fseek(f,96,SEEK_CUR);
  796.   if (len>0) {
  797.     q=(char far *)farmalloc(len);
  798.     if (bit16)
  799.       q2=(char far *)farmalloc(len/2);
  800.     else
  801.       q2=q;
  802.     if (q)
  803.       fread(q,len,1,f);          // Read sample data
  804.     else {
  805.       Msg("RAN OUT OF MEMORY!!! {push key}");
  806.       fclose(f);
  807.       Saving=OFF;
  808.       return 0;
  809.     }
  810.     if (bit16) {
  811.       for (k=0;k<len;k++) q2[k/2]=q[k]^128;
  812.       Sample[n].Len=len/2;
  813.       Sample[n].Rep=rep/2;
  814.       Sample[n].RepEnd=repend/2;
  815.     }
  816.     else {
  817.       Sample[n].Len=len;
  818.       Sample[n].Rep=rep;
  819.       Sample[n].RepEnd=repend;
  820.     }
  821.  
  822.     Sample[n].Seg=HighPtr>>16;
  823.     Sample[n].Off=HighPtr&0xFFFF;
  824.     HighPtr=LoadSample(Sample[n].Seg,Sample[n].Off,
  825.                        Sample[n].Len,
  826.                        (char far *)q2);
  827.     Sample[n].SType=0;
  828.     if (loop)
  829.       Sample[n].LoopMode=(1<<3);
  830.     else
  831.       Sample[n].LoopMode=0;
  832.     farfree(q2);
  833.     farfree(q);
  834.   }
  835.   else {
  836.     Sample[n].Seg=0;
  837.     Sample[n].Off=0;
  838.   }
  839.   strcpy(Sample[n].Name,fn);
  840.   itoa((int)ToLoad,Header,16); strcat(Sample[n].Name,"-");
  841.   strcat(Sample[n].Name,Header);
  842.   Saving=OFF;
  843.   fclose(f);
  844.   return 1;
  845. }
  846.  
  847. // ******************** SONG SAVING FUNCTIONS ****************************
  848.  
  849. void SaveF3R(char *name) {
  850. }
  851.  
  852. // ============================================================== F2R FORMAT
  853. byte far *pat;
  854. FILE *f;
  855. byte bl;
  856.  
  857. word NumEvents(byte *p) {
  858.   word ne=0;
  859.   word cp;
  860.  
  861.   for (cp=0;cp<16*4*(bl+1);cp+=4)
  862.     if (p[cp] || p[cp+2] || p[cp+3]) ne++;
  863.   return ne;
  864. }
  865.  
  866. byte far StoreQue[4096];
  867. dword QuePtr=0;
  868.  
  869. void TWrite(byte l) { StoreQue[QuePtr++]=l; }
  870.  
  871. void DoWrite() {
  872.   fwrite(&QuePtr,4,1,f);
  873.   fwrite(&StoreQue,QuePtr,1,f);
  874.   QuePtr=0;
  875. }
  876.  
  877. extern int mTempo[];
  878.  
  879. void WriteEventData(byte *pos,byte et,byte fxparm,byte fxtype) {
  880.   byte tb;
  881.  
  882.   switch(et) {
  883.     case 0:                     // Write new octave/note value
  884.       tb=(pos[0]-1)/12;
  885.       tb<<=4;
  886.       tb|=(pos[0]-1)%12;
  887.       TWrite(tb+0x10);
  888.       break;
  889.     case 3:                     // Write new volume value
  890.       if (pos[2]) {
  891.         tb=(pos[2]-1)*16;
  892.         TWrite(tb);
  893.       }
  894.       break;
  895.     case 1:                     // Write new instrument value
  896.       TWrite(pos[1]);
  897.       break;
  898.     case 4:                     // Special effect
  899.       TWrite(fxtype);
  900.       switch(fxtype) {
  901.         case 0x3:
  902.           TWrite(fxparm);
  903.           TWrite(pos[0]-1);
  904.           break;
  905.         case 0xa:
  906.           TWrite(fxparm);
  907.           TWrite((pos[2]-1)*16);
  908.           break;
  909.         case 0xf:
  910.           TWrite(mTempo[fxparm]);
  911.           break;
  912.         default:
  913.           TWrite(fxparm);
  914.           break;
  915.       }
  916.       break;
  917.   }
  918. }
  919.  
  920. void WriteOnePattern() {
  921.   word ne=NumEvents(pat),oq,ce,q,TCount=0;
  922.   byte fxparm=0,fxtype=0;
  923.   Flag s1=TRUE,s2=TRUE,Quit=FALSE;
  924.   char sig[4]="JDC";
  925.  
  926.   fwrite(&sig,3,1,f);                // Write block signature
  927.   fwrite(&ne,2,1,f);                 // Write the number of events for this block
  928.  
  929.   for (oq=0;oq<16*4*(bl+1);oq+=4) {
  930.     if (Quit) break;
  931.     if (pat[oq] || pat[oq+2] || pat[oq+3]) {
  932.       if (!s1)
  933.         TWrite(TCount);           // Write qCycles for last note
  934.       else
  935.         s1=FALSE;
  936.       ce=0;                       // Clear event type
  937.       TCount=0;                   // Clear note wait
  938.  
  939.       if ( (pat[oq]) && ((pat[oq+3]&0xF0)!=0x30) )  {
  940.         ce|=(1<<0);               // New note value
  941.         ce|=(1<<2);               // Start a new note
  942.         ce|=(1<<1);               // New instrument value
  943.         ce|=(1<<3);               // New volume value
  944.       }
  945.  
  946.       if (pat[oq+2])              // Volume change
  947.         ce|=(1<<3);
  948.  
  949.       if (pat[oq+3]&0xF0) {       // Effect of some type
  950.         ce|=(1<<4);
  951.         fxtype=pat[oq+3]>>4;
  952.         fxparm=pat[oq+3]&0xF;
  953.         if (fxtype==0x3) ce|=(1<<5);
  954.         if (fxtype==0xA) ce|=(1<<5);
  955.       }
  956.  
  957.       TWrite(ce);                 // Write event type
  958.       TWrite((oq/4)%16);          // Write channel number
  959.       for (q=0;q<8;q++) {         // Now write data for event
  960.         if (ce&(1<<q))
  961.           WriteEventData(&pat[oq],q,fxparm,fxtype);
  962.       }
  963.     }
  964.     if ((((oq/4)%16)==15) && (!s2)) TCount++;
  965.     s2=FALSE;
  966.   }
  967.   TWrite(TCount);
  968.   DoWrite();                // Now dump buffered data to disk with length
  969. }
  970.  
  971. void SaveF2R() {
  972.   int   q=strlen(DosName),tb;
  973.   char  fm[7]="F2RFAR";
  974.   char  name[80];
  975.   byte  NumInstr,far *qq,NumPatterns;
  976.   char  sId[4]="JDC";
  977.   dword qqq;
  978.  
  979.   FormSave("F2R (<1.0)");
  980.  
  981.   Saving=TRUE;
  982.   strcpy(name,DosName);
  983.   name[q-3]='F'; name[q-2]='2'; name[q-1]='R';
  984.   f=fopen(name,"wb");
  985.   fwrite(fm,6,1,f);                   // Write FileMagic
  986.   fwrite(SongName,40,1,f);            // Write song name
  987.   fwrite(&STLen,2,1,f);               // Write songtext length
  988.   fwrite(SongText,STLen,1,f);         // Write songtext
  989.   tb=0x20; fwrite(&tb,1,1,f);         // Write song version
  990.   tb=16; fwrite(&tb,1,1,f);           // We're putting defaults for 16 channels
  991.   tb=mTempo[4];fwrite(&tb,1,1,f);     // Write default tempo
  992.   fwrite(CurBalance,16,1,f);          // Write Panning settings
  993.   for (q=254;q>=0;q--) {
  994.     if (Sample[q].Len || Sample[q].Name[0]) break;
  995.   }
  996.   NumInstr=q+1; fwrite(&NumInstr,1,1,f);
  997.   for (q=0;q<NumInstr;q++) {
  998.     fwrite(Sample[q].Name,32,1,f);
  999.     fwrite(&Sample[q].Len,4,1,f);
  1000.     fwrite(&Sample[q].FineTune,1,1,f);
  1001.     fwrite(&Sample[q].Volume,1,1,f);
  1002.     fwrite(&Sample[q].Rep,4,1,f);
  1003.     qqq=Sample[q].RepEnd; if (!(Sample[q].LoopMode&(1<<3))) qqq=0;
  1004.     fwrite(&qqq,4,1,f);
  1005.     fwrite(&Sample[q].SType,1,1,f);
  1006.     if (Sample[q].Len) {
  1007.       LStat(q);
  1008.       if (!GenSave(f,Sample[q].Len,0,Sample[q].Seg,Sample[q].Off)) {
  1009.         Msg("RAN OUT OF MEMORY!!! {push key}");
  1010.         goto junk_it;
  1011.       }
  1012.     }
  1013.   }
  1014.   fwrite(&sId,3,1,f);            // Write section signature
  1015.   fwrite(&OrdLen,1,1,f);         // Write song len
  1016.   for (q=255;q>=0;q--) if (PatStore[q]) break;
  1017.   NumPatterns=q+1; fwrite(&NumPatterns,1,1,f);
  1018.   fwrite(&LoopTo,1,1,f);
  1019.   fwrite(&Order,128,1,f);
  1020.   PutAwayPat(CurPattern);
  1021.   for (q=0;q<NumPatterns;q++) {
  1022.     LStat(q);
  1023.     GetPat(q);
  1024.     bl=BreakLoc+1;
  1025.     pat=Pattern;
  1026.     WriteOnePattern();
  1027.   }
  1028.   GetPat(CurPattern);
  1029. junk_it:
  1030.   fclose(f);
  1031.   UpdateStat();
  1032.   Saving=FALSE;
  1033.  
  1034. }
  1035.  
  1036. int SaveOneFSM(word n,FILE *i) {
  1037.   byte  far *q;
  1038.   dword kk;
  1039.   int   retval=1;
  1040.  
  1041.   if (Sample[n].LoopMode&(1<<3))
  1042.     kk=Sample[n].RepEnd;
  1043.   else
  1044.     kk=0;
  1045.  
  1046.   fwrite(&Sample[n].Name,32,1,i);       // Write sample name
  1047.   fwrite(&Sample[n].Len,4,1,i);         // Write sample length
  1048.   fwrite(&Sample[n].FineTune,1,1,i);    // Write finetune byte
  1049.   fwrite(&Sample[n].Volume,1,1,i);      // Write default volume byte
  1050.   fwrite(&Sample[n].Rep,4,1,i);         // Write repeat start
  1051.   fwrite(&kk,4,1,i);                    // Write repeat end
  1052.   fwrite(&Sample[n].SType,1,1,i);       // Write sample type byte
  1053.   fwrite(&Sample[n].LoopMode,1,1,i);    // Write loop mode byte
  1054.  
  1055.   if (Sample[n].Len>0) {
  1056.     if (!GenSave(i,Sample[n].Len,0,Sample[n].Seg,Sample[n].Off)) {
  1057.       Msg("RAN OUT OF MEMORY!!! {push key}");
  1058.       retval=0;
  1059.     }
  1060.   }
  1061.   return retval;
  1062. }
  1063.  
  1064. void SaveFAR(char *fn) {
  1065.   FILE  *i;
  1066.   char  Magic1[]="FAR■";
  1067.   char  Magic2[]={13,10,26};
  1068.   char  t[80];
  1069.   Flag  SMap[64/8]={0};
  1070.   word  q,HLen=869+STLen;
  1071.  
  1072.   FormSave("FAR (<1.0)");
  1073.  
  1074.   Saving=ON;
  1075.   Saved=TRUE;
  1076.   StopMusic();
  1077.   strcpy(t,SongDir);
  1078.   strcat(t,"\\");
  1079.   strcat(t,fn);
  1080.   i=fopen(t,"wb");
  1081.   if (!i) {
  1082.     Saving=OFF;
  1083.     return;
  1084.   }
  1085.  
  1086.   if (Playing) StopMusic();
  1087.   PutAwayPat(CurPattern);
  1088.  
  1089.   fwrite(Magic1,4,1,i);
  1090.   fwrite(SongName,40,1,i);
  1091.   fwrite(Magic2,3,1,i);
  1092.   fwrite(&HLen,2,1,i);
  1093.   fputc(0x10,i);
  1094.   fwrite(ChanOn,16,1,i);
  1095.   fwrite(&CurOct,1,1,i);
  1096.   fwrite(&CurVoice,1,1,i);
  1097.   fwrite(&CurRow,1,1,i);
  1098.   fwrite(&CurPattern,1,1,i);
  1099.   fwrite(&CurOrder,1,1,i);
  1100.   fwrite(&CurSample,1,1,i);
  1101.   fwrite(&CurVol,1,1,i);
  1102.   fwrite(&CurTop,1,1,i);
  1103.   fwrite(&CurArea,1,1,i);
  1104.   fwrite(&CurTempo,1,1,i);
  1105.   fwrite(CurBalance,16,1,i);
  1106.   fwrite(&MarkTop,1,1,i);
  1107.   fwrite(&MarkBot,1,1,i);
  1108.   fwrite(&Grid,1,1,i);
  1109.   fwrite(&EditMode,1,1,i);
  1110.   fwrite(&STLen,2,1,i);
  1111.   fwrite(SongText,STLen,1,i);
  1112.   fwrite(Order,256,1,i);
  1113.   fwrite(&NumPatterns,1,1,i);
  1114.   fwrite(&OrdLen,1,1,i);
  1115.   fwrite(&LoopTo,1,1,i);
  1116.  
  1117.   for (q=0;q<256;q++) {
  1118.     if (PatSize[q]) {
  1119.       PatSize[q]++;
  1120.       fwrite(&PatSize[q],2,1,i);
  1121.       PatSize[q]--;
  1122.     }
  1123.     else {
  1124.       fwrite(&PatSize[q],2,1,i);
  1125.     }
  1126.   }
  1127.  
  1128.   for (q=0;q<256;q++)
  1129.     if (PatStore[q]) {
  1130.       LStat(q);
  1131.       fputc(PatStore[q][0],i);
  1132.       fputc(4,i);
  1133.       fwrite(&PatStore[q][1],PatSize[q]-1,1,i);
  1134.     }
  1135.  
  1136.   for (q=0;q<64;q++) {
  1137.     if (Sample[q].Len || Sample[q].Name[0]) {
  1138.       SMap[q/8]|=(1<<(q%8));
  1139.     }
  1140.   }
  1141.  
  1142.   fwrite(SMap,8,1,i);
  1143.  
  1144.   for (q=0;q<255;q++) {
  1145.     if (Sample[q].Len || Sample[q].Name[0]) {
  1146.       LStat(q);
  1147.       if (!SaveOneFSM(q,i)) goto junk_it;
  1148.     }
  1149.   }
  1150.  
  1151. junk_it:
  1152.   fclose(i);
  1153.   Saving=OFF;
  1154.   UpdateStat();
  1155. }
  1156.  
  1157. // ******************** SONG LOADING FUNCTIONS ****************************
  1158.  
  1159. void FreeSong() {
  1160.   word q;
  1161.  
  1162.   for (q=0;q<256;q++) {
  1163.     farfree(PatStore[q]);
  1164.     PatStore[q]=NULL;
  1165.     PatSize[q]=0;
  1166.     UpdateStat();
  1167.   }
  1168. }
  1169.  
  1170. void LoadF3R(char *name) {
  1171. }
  1172.  
  1173. void LoadF2R(char *name) {
  1174. }
  1175.  
  1176. int LoadOneFSM(word n,FILE *i) {
  1177.   byte far *q;
  1178.   int  retval=1;
  1179.  
  1180.   fread(Sample[n].Name,32,1,i);       // Read sample name
  1181.   fread(&Sample[n].Len,4,1,i);         // Read sample length
  1182.   fread(&Sample[n].FineTune,1,1,i);    // Read finetune byte
  1183.   fread(&Sample[n].Volume,1,1,i);      // Read default volume byte
  1184.   fread(&Sample[n].Rep,4,1,i);         // Read repeat start
  1185.   fread(&Sample[n].RepEnd,4,1,i);      // Read repeat end
  1186.   fread(&Sample[n].SType,1,1,i);       // Read sample type byte
  1187.   fread(&Sample[n].LoopMode,1,1,i);    // Read loop mode byte
  1188.  
  1189.   if (Sample[n].RepEnd<5) {
  1190.     Sample[n].RepEnd=Sample[n].Len;
  1191.     Sample[n].LoopMode=0;
  1192.   }
  1193.   else
  1194.     Sample[n].LoopMode=(1<<3);
  1195.  
  1196.   if (Sample[n].SType&1) Sample[n].LoopMode|=(1<<2);
  1197.  
  1198.   if (Sample[n].Len>0) {
  1199.     Sample[n].Seg=HighPtr>>16;
  1200.     Sample[n].Off=HighPtr&0xFFFF;
  1201.     if (!GenLoad(i,Sample[n].Len,0,n)) {
  1202.       Msg("RAN OUT OF MEMORY!!! {push key}");
  1203.       retval=0;
  1204.     }
  1205.   }
  1206.   else {
  1207.     Sample[n].Seg=0;
  1208.     Sample[n].Off=0;
  1209.   }
  1210.   return retval;
  1211. }
  1212.  
  1213. void LoadFAR(char *fn) {
  1214.   FILE  *i;
  1215.   char  Magic1[]="FAR■";
  1216.   char  Magic2[]={13,10,26};
  1217.   Flag  SMap[256/8]={0};
  1218.   word  q,HdrLen;
  1219.  
  1220.   i=fopen(fn,"rb");
  1221.   if (!i) return;
  1222.   fread(Magic1,4,1,i);
  1223.   if (strcmp(Magic1,"FAR■")) {
  1224.     fclose(i);
  1225.     return;
  1226.   }
  1227.   Saving=ON;
  1228.   if (Playing) StopMusic();
  1229.   FreeSong();
  1230.   FormLoad("FAR (<1.0)");
  1231.   Saved=TRUE;
  1232.   strcpy(DosName,fn);
  1233.  
  1234.   fread(SongName,40,1,i);
  1235.   fread(Magic2,3,1,i);
  1236.   fread(&HdrLen,2,1,i);
  1237.   fgetc(i);
  1238.   fread(ChanOn,16,1,i);
  1239.   fread(&CurOct,1,1,i);
  1240.   fread(&CurVoice,1,1,i);
  1241.   fread(&CurRow,1,1,i);
  1242.   fread(&CurPattern,1,1,i);
  1243.   fread(&CurOrder,1,1,i);
  1244.   fread(&CurSample,1,1,i);
  1245.   fread(&CurVol,1,1,i);
  1246.   fread(&CurTop,1,1,i);
  1247.   fread(&CurArea,1,1,i);
  1248.   fread(&CurTempo,1,1,i);
  1249.   fread(CurBalance,16,1,i);
  1250.   fread(&MarkTop,1,1,i);
  1251.   fread(&MarkBot,1,1,i);
  1252.   fread(&Grid,1,1,i);
  1253.   fread(&EditMode,1,1,i);
  1254.   fread(&STLen,2,1,i);
  1255.   if (STLen<=5544)
  1256.     fread(SongText,STLen,1,i);
  1257.   else {
  1258.     fread(SongText,5544,1,i);
  1259.     fseek(i,STLen-5544,SEEK_CUR);
  1260.   }
  1261.   fread(Order,256,1,i);
  1262.   fread(&NumPatterns,1,1,i);
  1263.   fread(&OrdLen,1,1,i);
  1264.   fread(&LoopTo,1,1,i);
  1265.   fread(PatSize,256,2,i);
  1266.   if (HdrLen-(869+STLen))
  1267.     fseek(i,HdrLen-(869+STLen),SEEK_CUR);
  1268.  
  1269.   for (q=0;q<256;q++)
  1270.     if (PatSize[q]) {
  1271.       LStat(q);
  1272.       PatSize[q]--;
  1273.       PatStore[q]=(char *)farmalloc(PatSize[q]);
  1274.       PatStore[q][0]=fgetc(i);
  1275.       fgetc(i);
  1276.       fread(&PatStore[q][1],PatSize[q]-1,1,i);
  1277.     }
  1278.  
  1279.   fread(SMap,8,1,i);
  1280.  
  1281.   memset(Sample,0,sizeof(Sample));
  1282.   HighPtr=64;
  1283.   for (q=0;q<255;q++)
  1284.     if (SMap[q/8] & (1<<(q%8))) {
  1285.       LStat(q);
  1286.       if (!LoadOneFSM(q,i))
  1287.         goto junk_it;
  1288.     }
  1289.  
  1290. junk_it:
  1291.   fclose(i);
  1292.   memset(Pattern,0,sizeof(Pattern));
  1293.   GetPat(CurPattern);
  1294.   sScreen();
  1295.   Saving=OFF;
  1296. }
  1297.  
  1298. // =============================================================== MOD format
  1299.  
  1300. int LoadMODSmp(FILE *i,word n) {
  1301.   byte  far *q;
  1302.   dword d=0;
  1303.   int   retval=1;
  1304.  
  1305.   Sample[n].SType=0;
  1306.   if (Sample[n].RepEnd<5) {
  1307.     Sample[n].RepEnd=Sample[n].Len;
  1308.     Sample[n].LoopMode=0;
  1309.   }
  1310.   else
  1311.     Sample[n].LoopMode=(1<<3);
  1312.  
  1313.   if (Sample[n].Len>0) {
  1314.     Sample[n].Seg=HighPtr>>16;
  1315.     Sample[n].Off=HighPtr&0xFFFF;
  1316.     if (!GenLoad(i,Sample[n].Len,0,n)) {
  1317.       Msg("RAN OUT OF MEMORY!!! {push key}");
  1318.       retval=0;
  1319.     }
  1320.   }
  1321.   else {
  1322.     Sample[n].Seg=0;
  1323.     Sample[n].Off=0;
  1324.   }
  1325.   return retval;
  1326. }
  1327.  
  1328. word vals[]={
  1329.   0x358,0x328,0x2FA,0x2D0,0x2A6,0x280,0x25C,0x23A,0x21A,0x1FC,0x1E0,0x1C5,
  1330.   0x1AC,0x194,0x17D,0x168,0x153,0x140,0x12E,0x11D,0x10D,0x0FE,0x0F0,0x0E2,
  1331.   0x0D6,0x0CA,0x0BE,0x0B4,0x0AA,0x0A0,0x097,0x08F,0x087,0x07F,0x078,0x071,
  1332.   0x06B,0x065,0x05F,0x055,0x050,0x04B,0x047,0x043,0x03F,0x03C,0x038,0x035,
  1333.   0x032,0x030,0x02D,0x02A,0x028,0x026,0x024,0x020,0x01E,0x01C,0x01B,0x019,
  1334.   0x018,0x016,0x015,0x014,0x013,0x012,0x011,0x010,0x00F,0x00E,0x00D,0x00C,
  1335.   0x00B,0x00A,0x009,0x008,0x007,0x006,0x005,0x004,0x003,0x002,0x001 };
  1336.  
  1337. byte GetNote(int p) {
  1338.   word cp;
  1339.   for (cp=0;cp<7*12;cp++) if (abs(p-vals[cp])<3) return cp%12;
  1340.   return 0;
  1341. }
  1342.  
  1343. byte GetOctave(word p) {
  1344.   if (p<=0x360 && p>=0x1C0) return 1;
  1345.   if (p<=0x1BF && p>=0x0DA) return 2;
  1346.   if (p<=0x0D9 && p>=0x06F) return 3;
  1347.   if (p<=0x06E && p>=0x037) return 4;
  1348.   if (p<=0x036 && p>=0x01B) return 5;
  1349.   if (p<=0x01A && p>=0x00D) return 6;
  1350.   if (p<=0x00C && p>=0x001) return 7;
  1351.   return 8;
  1352. }
  1353.  
  1354. byte tM2F[]={0,0,1,1,2,3,3,4,5,5,6,7,7,8,8,9,10,10,11,12,12};
  1355. byte fM2F[]={0,0,0,1,1,1,2,2,2,3,3,3,4,4,5,5,5,6,6,6,7};
  1356. byte far p1[8192];
  1357.  
  1358. void LoadMODPat(FILE *i,byte NumChannels) {
  1359.   byte cn[8];
  1360.   word ptr,curper;
  1361.  
  1362.   CurVoice=0;
  1363.   memset(Pattern,0,sizeof(Pattern));
  1364.   fread(p1,256*NumChannels,1,i);
  1365.   CurRow=0;
  1366.   for (ptr=0;ptr<(256*NumChannels);ptr+=4) {
  1367.     memcpy(cn,&p1[ptr],4);
  1368.  
  1369.     curper=((cn[0]&0xF)<<8)|cn[1];
  1370.     if (curper)
  1371.       Pattern[CurSpot]=((GetOctave(curper)-1)*12)+GetNote(curper)+1;
  1372.     else
  1373.       Pattern[CurSpot]=0;
  1374.     Pattern[CurSpot+1]=(cn[0]&0xF0)|((cn[2]&0xF0)>>4);
  1375.     if (Pattern[CurSpot+1])
  1376.       Pattern[CurSpot+1]--;
  1377.     else
  1378.       Pattern[CurSpot]=0;
  1379.     Pattern[CurSpot+2]=0;
  1380.     if ((cn[2]&0xF)==0xC) Pattern[CurSpot+2]=(cn[3]/4)+1;
  1381.     if (Pattern[CurSpot+2]>0x10) Pattern[CurSpot+2]=0x10;
  1382.     if (!Pattern[CurSpot+2] && curper) Pattern[CurSpot+2]=0x10;
  1383.     if ((cn[2]&0xF)==0xF) {
  1384.       curper=((cn[3]*32)/50);
  1385.       if (curper<0x30) Pattern[CurSpot+3]=0xF0|curper;
  1386. //      if (ptr<(4*NumChannels)) CurTempo=curper;
  1387. /*      Pattern[CurSpot+3]=0xF0|tM2F[cn[3]];
  1388.       Pattern[CurRow*64+23]=0xD0;
  1389.       Pattern[CurRow*64+27]=0xD0|fM2F[cn[3]]; */
  1390.     }
  1391.     if ((cn[2]&0xF)==0xD) BreakLoc=CurRow-1;
  1392.     if (CurVoice==(NumChannels-1)) {
  1393.       CurRow++;
  1394.       CurVoice=0;
  1395.     }
  1396.     else
  1397.       CurVoice++;
  1398.   }
  1399. }
  1400.  
  1401. void LoadMOD(char *fn) {
  1402.   FILE  *i;
  1403.   word  m,q=strlen(fn);
  1404.   word  NumSamples=0;
  1405.   byte  bal[16]={2,13,13,2,2,13,13,2,2,13,13,2,2,13,13,2};
  1406.   byte  NumChannels=0;
  1407.   char  Magic[5]={0};
  1408.   char  ffn[80];
  1409.  
  1410.   Saving=ON;
  1411.   if (Playing) StopMusic();
  1412.   i=fopen(fn,"rb");
  1413.   if (!i) {
  1414.     Saving=OFF;
  1415.     return;
  1416.   }
  1417.   fseek(i,1080,SEEK_SET);
  1418.   fread(Magic,4,1,i);
  1419.   if (!strcmp(Magic,"M.K.")) NumChannels=4;
  1420.   if (!strcmp(Magic,"FLT4")) NumChannels=4;
  1421.   if (!strcmp(Magic,"FLT8")) NumChannels=8;
  1422.   if (!strcmp(Magic,"6CHN")) NumChannels=6;
  1423.   if (!strcmp(Magic,"8CHN")) NumChannels=8;
  1424.   if (!strcmp(Magic,"14CH")) NumChannels=14;
  1425.   if (!strcmp(Magic,"15CH")) NumChannels=15;
  1426.   if (!strcmp(Magic,"16CH")) NumChannels=16;
  1427.   if (!NumChannels) {
  1428.     fclose(i);
  1429.     Saving=OFF;
  1430.     return;
  1431.   }
  1432.   FreeSong();
  1433.   fseek(i,0,SEEK_SET);
  1434.   strcpy(ffn,fn);
  1435.   ffn[q-3]='F'; ffn[q-2]='A'; ffn[q-1]='R';
  1436.   strcpy(DosName,ffn);
  1437.   Saved=TRUE;
  1438.   FormLoad(Magic);
  1439.  
  1440.   memset(SongText,0,sizeof(SongText));
  1441.   memset(SongName,0,sizeof(SongName)); fread(SongName,20,1,i);
  1442.   NumSamples=31;
  1443.   memset(Sample,0,sizeof(Sample));
  1444.   for (m=0;m<NumSamples;m++) {
  1445.     fread(Sample[m].Name,22,1,i);
  1446.     fread(&Sample[m].Len,2,1,i);
  1447.     Sample[m].Len=(Sample[m].Len>>8)|((Sample[m].Len&0xFF)<<8);
  1448.     Sample[m].Len<<=1;
  1449.     fread(&Sample[m].FineTune,1,1,i);
  1450.     fread(&Sample[m].Volume,1,1,i); Sample[m].Volume>>=2;
  1451.     fread(&Sample[m].Rep,2,1,i);
  1452.     Sample[m].Rep=(Sample[m].Rep>>8)|((Sample[m].Rep&0xFF)<<8);
  1453.     Sample[m].Rep<<=1;
  1454.     fread(&Sample[m].RepEnd,2,1,i);
  1455.     Sample[m].RepEnd=(Sample[m].RepEnd>>8)|((Sample[m].RepEnd&0xFF)<<8);
  1456.     Sample[m].RepEnd<<=1;
  1457.       if (Sample[m].RepEnd>5)
  1458.         Sample[m].RepEnd+=Sample[m].Rep;
  1459.     if (!Sample[m].Name[0] && Sample[m].Len) Sample[m].Name[0]=32;
  1460.   }
  1461.  
  1462.   fread(&OrdLen,1,1,i);
  1463.   fread(&LoopTo,1,1,i); if (LoopTo>=0x7F) LoopTo=0;
  1464.   memset(Order,0xFF,256);  fread(Order,0x80,1,i);
  1465.   fread(&Magic,4,1,i);
  1466.   NumPatterns=0;
  1467.   for (m=0;m<128;m++) if (Order[m]>NumPatterns) NumPatterns=Order[m];
  1468.   memset(&Order[OrdLen],0xFF,256-OrdLen);
  1469.   NumPatterns++;
  1470.  
  1471.   for (m=0;m<NumPatterns;m++) {
  1472.     LStat(m);
  1473.     LoadMODPat(i,NumChannels);
  1474.     if (!BreakLoc) BreakLoc=62;
  1475.     if (!CurTempo) CurTempo=4;
  1476.     PutAwayPat(m);
  1477.   }
  1478.   HighPtr=64;
  1479.   for (m=0;m<NumSamples;m++) {
  1480.     LStat(m);
  1481.     if (!LoadMODSmp(i,m)) break;
  1482.   }
  1483.   fclose(i);
  1484.   CurPattern=0; CurOrder=0;
  1485.   CurVoice=0; CurRow=0; CurTop=0;
  1486.   CurSample=0; CurVol=0x10;
  1487.   CurTempo=4;
  1488.   memset(ChanOn,1,sizeof(ChanOn));
  1489.   memcpy(CurBalance,bal,sizeof(CurBalance));
  1490.   MarkTop=1; MarkBot=0;
  1491.   EditMode=ON;
  1492.   MusicMode=ON;
  1493.  
  1494.   memset(Pattern,0,sizeof(Pattern));
  1495.   GetPat(CurPattern);
  1496.   UpdateChans();
  1497.   Saving=OFF;
  1498.   sScreen();
  1499. }
  1500.  
  1501. // =============================================================== 669 format
  1502.  
  1503. void Load669Pat(FILE *i) {
  1504.   byte p[0x600],cn[6];
  1505.   word ptr;
  1506.  
  1507.   memset(Pattern,0,sizeof(Pattern));
  1508.   fread(p,0x600,1,i);
  1509.   CurRow=0;
  1510.   CurVoice=0;
  1511.   for (ptr=0;ptr<0x600;ptr+=3) {
  1512.     memcpy(cn,&p[ptr],3);
  1513.  
  1514.     if (cn[2]==0xff) cn[2]=0;
  1515.     switch(cn[2]&0xF0) {
  1516.       case 0x20:
  1517.         cn[2]=0x10-(cn[2]&0xf);
  1518.         cn[2]|=0x30;
  1519.         break;
  1520.       case 0x30:
  1521.         cn[2]=cn[2]&0xf;
  1522.         cn[2]|=0x10;
  1523.         break;
  1524.       default:
  1525.         cn[2]=0;
  1526.         break;
  1527.     }
  1528.     if (cn[0]==0xfe) {
  1529.       Pattern[CurSpot]=0;
  1530.       Pattern[CurSpot+1]=0;
  1531.       Pattern[CurSpot+2]=(cn[1]&0xF)+1;
  1532.       Pattern[CurSpot+3]=cn[2];
  1533.     }
  1534.     if (cn[0]==0xff) {
  1535.       Pattern[CurSpot]=0;
  1536.       Pattern[CurSpot+1]=0;
  1537.       Pattern[CurSpot+2]=0;
  1538.       if (cn[2]!=0xFF)
  1539.         Pattern[CurSpot+3]=cn[2];
  1540.       else
  1541.         Pattern[CurSpot+3]=0;
  1542.     }
  1543.     if (cn[0]!=0xff && cn[0]!=0xfe) {
  1544.       if ( ((cn[0]>>2)+1) <=12)
  1545.         Pattern[CurSpot]=((cn[0]>>2)+1);
  1546.       else
  1547.         Pattern[CurSpot]=((cn[0]>>2)+1)-12;
  1548.       Pattern[CurSpot+1]=((cn[0]&3)<<4)|(cn[1]>>4);
  1549.       Pattern[CurSpot+2]=(cn[1]&0xF)+1;
  1550.       Pattern[CurSpot+3]=cn[2];
  1551.     }
  1552.     if (CurVoice==7) {
  1553.       CurRow++;
  1554.       CurVoice=0;
  1555.     }
  1556.     else
  1557.       CurVoice++;
  1558.   }
  1559. }
  1560.  
  1561. int Load669Smp(FILE *i,word n) {
  1562.   byte  far *q;
  1563.   long  aq;
  1564.   dword d=0;
  1565.   int   retval=1;
  1566.  
  1567.   Sample[n].FineTune=0;
  1568.   Sample[n].Volume=0xF;
  1569.   Sample[n].SType=0;
  1570.  
  1571.   if (Sample[n].RepEnd<5) {
  1572.     Sample[n].RepEnd=Sample[n].Len;
  1573.     Sample[n].LoopMode=0;
  1574.   }
  1575.   else
  1576.     Sample[n].LoopMode=(1<<3);
  1577.  
  1578.   if (Sample[n].Len>0) {
  1579.     Sample[n].Seg=HighPtr>>16;
  1580.     Sample[n].Off=HighPtr&0xFFFF;
  1581.     if (!GenLoad(i,Sample[n].Len,128,n)) {
  1582.       Msg("RAN OUT OF MEMORY!!! {push key}");
  1583.       retval=0;
  1584.     }
  1585.   }
  1586.   else {
  1587.     Sample[n].Seg=0;
  1588.     Sample[n].Off=0;
  1589.   }
  1590.   return retval;
  1591. }
  1592.  
  1593. void Load669(char *fn) {
  1594.   FILE  *i;
  1595.   word  m,q=strlen(fn);
  1596.   word  NumSamples=0,qq;
  1597.   byte  Tempos[256]={0},Breaks[256]={0};
  1598.   byte  bal[16]={2,13,2,13,2,13,2,13,2,13,2,13,2,13,2,13};
  1599.   char  ffn[80];
  1600.  
  1601.  
  1602.   Saving=ON;
  1603.   if (Playing) StopMusic();
  1604.   i=fopen(fn,"rb");
  1605.   if (!i) {
  1606.     Saving=OFF;
  1607.     return;
  1608.   }
  1609.   fread(&m,2,1,i);
  1610.   if (m!=0x6669 && m!=0x4E4A) {
  1611.     fclose(i);
  1612.     Saving=OFF;
  1613.     return;
  1614.   }
  1615.   strcpy(ffn,fn);
  1616.   ffn[q-3]='F'; ffn[q-2]='A'; ffn[q-1]='R';
  1617.   strcpy(DosName,ffn);
  1618.   Saved=TRUE;
  1619.   FreeSong();
  1620.  
  1621.   FormLoad("669");
  1622.   memset(SongText,0,sizeof(SongText));
  1623.   fread(SongText,108,1,i); STLen=108;
  1624.   memset(SongName,0,32); memcpy(SongName,SongText,32);
  1625.   fread(&NumSamples,1,1,i);
  1626.   fread(&NumPatterns,1,1,i);
  1627.   fread(&LoopTo,1,1,i); if (LoopTo==0x7e) LoopTo=0;
  1628.   memset(Order,0,256);  fread(Order,0x80,1,i);
  1629.   memset(Tempos,0,256); fread(Tempos,0x80,1,i);
  1630.   memset(Breaks,0,256); fread(Breaks,0x80,1,i);
  1631.  
  1632.   memset(Sample,0,sizeof(Sample));
  1633.   for (m=0;m<NumSamples;m++) {
  1634.     memset(Sample[m].Name,0,13); fread(Sample[m].Name,13,1,i);
  1635.     fread(&Sample[m].Len,4,1,i);
  1636.     fread(&Sample[m].Rep,4,1,i);
  1637.     fread(&Sample[m].RepEnd,4,1,i);
  1638.     if (Sample[m].RepEnd>=0xFFFF) Sample[m].RepEnd=0;
  1639.   }
  1640.   for (m=0;m<NumPatterns;m++) {
  1641.     LStat(m);
  1642.     Load669Pat(i);
  1643.     BreakLoc=Breaks[m]-1;
  1644.     CurRow=0;
  1645.     for (qq=0,CurVoice=0;CurVoice<15;CurVoice++) {
  1646.       if ((Pattern[CurSpot+3]&0xF0)==0xF0) qq=1;
  1647.     }
  1648.     if (!qq) Pattern[CurSpot+3]=0xF0|Tempos[m];
  1649.     PutAwayPat(m);
  1650.   }
  1651.   HighPtr=64;
  1652.   for (m=0;m<NumSamples;m++) {
  1653.     LStat(m);
  1654.     if (!Load669Smp(i,m)) goto Done;
  1655.   }
  1656. Done:
  1657.   fclose(i);
  1658.   CurPattern=0; CurOrder=0;
  1659.   CurVoice=0; CurRow=0; CurTop=0;
  1660.   CurSample=0; CurVol=0x10;
  1661.   CurTempo=4;
  1662.   memset(ChanOn,1,sizeof(ChanOn));
  1663.   memcpy(CurBalance,bal,16);
  1664.   MarkTop=1; MarkBot=0;
  1665.   Grid=4; EditMode=ON;
  1666.  
  1667.   memset(Pattern,0,sizeof(Pattern));
  1668.   GetPat(CurPattern);
  1669.   UpdateChans();
  1670.   Saving=OFF;
  1671.   sScreen();
  1672. }
  1673.  
  1674.  
  1675. // =============================================================== MTM format
  1676.  
  1677. int LoadMTMSmp(FILE *i,word n) {
  1678.   byte  far *q;
  1679.   dword d=0,qq;
  1680.   int   retval=1;
  1681.  
  1682.   Sample[n].SType=0;
  1683.   if (Sample[n].RepEnd<5) {
  1684.     Sample[n].RepEnd=Sample[n].Len;
  1685.     Sample[n].LoopMode=0;
  1686.   }
  1687.   else
  1688.     Sample[n].LoopMode=(1<<3);
  1689.  
  1690.   if (Sample[n].Len>0) {
  1691.     Sample[n].Seg=HighPtr>>16;
  1692.     Sample[n].Off=HighPtr&0xFFFF;
  1693.     if (!GenLoad(i,Sample[n].Len,128,n)) {
  1694.       Msg("RAN OUT OF MEMORY!!! {push key}");
  1695.       retval=0;
  1696.     }
  1697.   }
  1698.   else {
  1699.     Sample[n].Seg=0;
  1700.     Sample[n].Off=0;
  1701.   }
  1702.   return retval;
  1703. }
  1704.  
  1705. byte far *tracks[2048];
  1706. byte far qBuffer[192];
  1707. word far TrakSeq[128][32];
  1708.  
  1709. void LoadMTM(char *fn) {
  1710.   FILE  *f;
  1711.   byte  tb;
  1712.   word  m,q=strlen(fn),w,op,e;
  1713.   char  t[80],ffn[80];
  1714.   word  NumTracks=0,NumOrder=0,NumSamples=0,bpt=0,NumTracksPlay=0;
  1715.   word  NumPatterns=0;
  1716.   byte  cn[8];
  1717.   int   cvol;
  1718.  
  1719.   Saving=ON;
  1720.   if (Playing) StopMusic();
  1721.   f=fopen(fn,"rb");
  1722.   if (!f) {
  1723.     Saving=OFF;
  1724.     return;
  1725.   }
  1726.   fread(t,3,1,f); t[3]=0;
  1727.   if (strcmp(t,"MTM")) {
  1728.     fclose(f);
  1729.     Saving=OFF;
  1730.     return;
  1731.   }
  1732.  
  1733.   FreeSong();
  1734.   strcpy(ffn,fn);
  1735.   ffn[q-3]='F'; ffn[q-2]='A'; ffn[q-1]='R';
  1736.   strcpy(DosName,ffn);
  1737.   Saved=TRUE;
  1738.  
  1739.   FormLoad("MTM");
  1740.   fgetc(f);    // Version #
  1741.   memset(SongText,0,sizeof(SongText));
  1742.   memset(SongName,0,sizeof(SongName));
  1743.   memset(Sample,0,sizeof(Sample));
  1744.   memset(TrakSeq[0],0,sizeof(TrakSeq));
  1745.  
  1746.   fread(SongName,20,1,f);
  1747.   fread(&NumTracks,2,1,f);
  1748.   NumPatterns=fgetc(f);
  1749.   NumOrder=fgetc(f);
  1750.   fread(&STLen,2,1,f);
  1751.   NumSamples=fgetc(f);
  1752.   fgetc(f);   // Attribute byte
  1753.   bpt=fgetc(f);
  1754.   NumTracksPlay=fgetc(f);
  1755.   fread(CurBalance,16,1,f); fseek(f,16,SEEK_CUR);
  1756.  
  1757.   for (q=0;q<NumSamples;q++) {
  1758.     fread(Sample[q].Name,22,1,f);
  1759.     fread(&Sample[q].Len,4,1,f);
  1760.     fread(&Sample[q].Rep,4,1,f);
  1761.     fread(&Sample[q].RepEnd,4,1,f);
  1762.     Sample[q].FineTune=fgetc(f);
  1763.     Sample[q].Volume=fgetc(f);
  1764.     tb=fgetc(f);
  1765.     if (tb&1) {
  1766.       Sample[CurSample].SType^=1;
  1767.       Sample[CurSample].LoopMode^=(1<<2);
  1768.     }
  1769.   }
  1770.   fread(Order,128,1,f);
  1771.   for (q=NumOrder;q<256;q++) Order[q]=0xFF;
  1772.  
  1773.   for (q=0;q<NumTracks;q++) {
  1774.     LStat(q);
  1775.     fread(qBuffer,192,1,f);
  1776.     tracks[q]=(char far*)malloc(512);
  1777.     cvol=0x40;
  1778.     if (tracks[q]) {
  1779.       memset(tracks[q],0,258);
  1780.       for (w=0,op=0;w<64;w++,op+=4) {
  1781.         memcpy(cn,&qBuffer[w*3],4);
  1782.  
  1783.         if (cn[0]>>2) {
  1784.           if ( ((cn[0]>>2)+1) <=12)
  1785.             tracks[q][op]=((cn[0]>>2)+1);
  1786.           else
  1787.             tracks[q][op]=((cn[0]>>2)+1)-12;
  1788.           cvol=0x40;
  1789.         }
  1790.         else tracks[q][op]=0;
  1791.         tracks[q][op+1]=(((cn[0]&3)<<4) | (cn[1]>>4))-1;
  1792.         if (tracks[q][op+1]==0xFF) tracks[q][op+1]=0;
  1793.         tracks[q][op+2]=0;
  1794.         if ((cn[1]&0xF)==0x1) tracks[q][op+3]=0x10|(cn[2]&0xF);
  1795.         if ((cn[1]&0xF)==0x2) tracks[q][op+3]=0x20|(cn[2]&0xF);
  1796.  
  1797.         if ((cn[1]&0xF)==0xC) tracks[q][op+2]=(cn[2]/4)+1;
  1798.         if (((cn[1]&0xF)==0xC) && ((cn[2]%4)>=2)) tracks[q][op+2]++;
  1799.         if (((cn[1]&0xF)==0xC) && (cn[2]) && (tracks[q][op+2]<2))
  1800.           tracks[q][op+2]=2;
  1801.  
  1802.         if ((cn[1]&0xF)==0xC) cvol=cn[2];
  1803.         if ((cn[1]&0xF)==0xA || (cn[1]&0xF)==0x5 || (cn[1]&0xF)==0x6) {
  1804.           if (cn[2]&0xF0)    // Slide up
  1805.             if (cvol<0x40) cvol+=cn[2]>>4;
  1806.           if (cn[2]&0x0F)    // Slide down
  1807.             if (cvol>0) cvol-=cn[2];
  1808.           if (cvol<0) cvol=0;
  1809.           if (cvol>0x40) cvol=0x40;
  1810.  
  1811.           tracks[q][op+2]=(cvol/4)+1;
  1812.           if ((cvol%4)>=2) tracks[q][op+2]++;
  1813.           if ((cvol) && (tracks[q][op+2]<2)) tracks[q][op+2]=2;
  1814.         }
  1815.         if (((cn[1]&0xF)==0xE) && ((cn[2]&0xF0)==0xa0 || (cn[2]&0xF0)==0xb0)) {
  1816.           if ((cn[2]&0xF0)==0xa0)    // Slide up
  1817.             if (cvol<0x40) cvol+=cn[2]&0xF;
  1818.           if ((cn[2]&0xF0)==0xb0)    // Slide down
  1819.             if (cvol>0) cvol-=cn[2]&0xF;
  1820.           if (cvol<0) cvol=0;
  1821.           if (cvol>0x40) cvol=0x40;
  1822.  
  1823.           tracks[q][op+2]=(cvol/4)+1;
  1824.           if ((cvol%4)>=2) tracks[q][op+2]++;
  1825.           if ((cvol) && (tracks[q][op+2]<2)) tracks[q][op+2]=2;
  1826.         }
  1827.         if (tracks[q][op+2]>0x10) tracks[q][op+2]=0x10;
  1828.         if (!tracks[q][op+2] && tracks[q][op]) tracks[q][op+2]=0x10;
  1829.         if ((cn[1]&0xF)==0xF) {
  1830.           m=((cn[2]*50)/64);
  1831.           if (m<0x30) tracks[q][op+3]=0xF0|m;
  1832.         }
  1833.         if ((cn[1]&0xF)==0xD) tracks[q][256]=CurRow-1;
  1834.       }
  1835.     }
  1836.   }
  1837.  
  1838.   fread(TrakSeq[0],(NumPatterns+1)*64,1,f);
  1839.   for (q=0;q<=NumPatterns;q++) {
  1840.     LStat(q);
  1841.     memset(Pattern,0,sizeof(Pattern));
  1842.     for (w=0;w<16;w++) {
  1843.       CurVoice=w;
  1844.       if (TrakSeq[q][w]) {
  1845.         for (e=0;e<bpt;e++) {
  1846.           CurRow=e;
  1847.           memcpy(&Pattern[CurSpot],&tracks[TrakSeq[q][w]-1][4*e],4);
  1848.         }
  1849.         if (tracks[TrakSeq[q][w]-1][256])
  1850.           BreakLoc=tracks[TrakSeq[q][w]-1][256]-1;
  1851.         else
  1852.           BreakLoc=62;
  1853.       }
  1854.     }
  1855.     PutAwayPat(q);
  1856.   }
  1857.  
  1858.   for (q=0;q<NumTracks;q++) free(tracks[q]);
  1859.  
  1860.   if (STLen<=5543) {
  1861.     for (q=0;q<STLen/40;q++)
  1862.       fread(&SongText[q*132],40,1,f);
  1863.     STLen=132*(STLen/40);
  1864.   }
  1865.   else {
  1866.     fread(SongText,STLen,5543,f);
  1867.     fseek(f,STLen-5543,SEEK_CUR);
  1868.   }
  1869.  
  1870.   HighPtr=64;
  1871.   for (m=0;m<NumSamples;m++) {
  1872.     LStat(q);
  1873.     if (!LoadMTMSmp(f,m)) break;
  1874.   }
  1875.   fclose(f);
  1876.   CurPattern=0; CurOrder=0;
  1877.   CurVoice=0; CurRow=0; CurTop=0;
  1878.   CurSample=0; CurVol=0x10;
  1879.   CurTempo=4;
  1880.   memset(ChanOn,1,sizeof(ChanOn));
  1881.   MarkTop=1; MarkBot=0;
  1882.   EditMode=ON;
  1883.  
  1884.   memset(Pattern,0,sizeof(Pattern));
  1885.   GetPat(CurPattern);
  1886.   sScreen();
  1887.   Saving=OFF;
  1888.   return;
  1889. }
  1890.  
  1891. // =============================================================== S3M format
  1892.  
  1893. void LoadS3M(char *fn) {
  1894.   FILE  *i;
  1895.   word  q=strlen(fn),Magic;
  1896.   char  ffn[80];
  1897.  
  1898.   Saving=ON;
  1899.   if (Playing) StopMusic();
  1900.   i=fopen(fn,"rb");
  1901.   if (!i) {
  1902.     Saving=OFF;
  1903.     return;
  1904.   }
  1905.   fseek(i,28,SEEK_SET);
  1906.   fread(&Magic,2,1,i);
  1907.   if (Magic!=0x101a) {
  1908.     fclose(i);
  1909.     Saving=OFF;
  1910.     return;
  1911.   }
  1912.  
  1913.   FreeSong();
  1914.   strcpy(ffn,fn);
  1915.   ffn[q-3]='F'; ffn[q-2]='A'; ffn[q-1]='R';
  1916.   strcpy(DosName,ffn);
  1917.   Saved=TRUE;
  1918.  
  1919.   FormLoad("S3M");
  1920.   memset(SongText,0,sizeof(SongText));
  1921.   memset(SongName,0,sizeof(SongName));
  1922.   memset(Sample,0,sizeof(Sample));
  1923.  
  1924.   fclose(i);
  1925.   sScreen();
  1926.   Saving=OFF;
  1927. }
  1928.  
  1929. // =============================================================== STM format
  1930.  
  1931. byte Tempo=60,MaxVol=0x40;
  1932. byte tS2F[]={0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,8,8,9,9,10,10};
  1933. byte fS2F[]={0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,7,8,8,9};
  1934.  
  1935. void LoadSTMPat(FILE *i) {
  1936.   byte p[1024],cn[8];
  1937.   word ptr,curper;
  1938.  
  1939.   memset(Pattern,0,sizeof(Pattern));
  1940.   fread(p,256*4,1,i);
  1941.   CurRow=0;
  1942.   for (ptr=0;ptr<(256*4);ptr+=4) {
  1943.     memcpy(cn,&p[ptr],4);
  1944.  
  1945.     Pattern[CurSpot]=(((cn[0]>>4)-1)*12)+(cn[0]&0xF);
  1946.     Pattern[CurSpot+1]=cn[1]>>3;
  1947.     if (Pattern[CurSpot+1])
  1948.       Pattern[CurSpot+1]--;
  1949.     else
  1950.       Pattern[CurSpot]=0;
  1951.     Pattern[CurSpot+2]=((((cn[1]&7)<<4)|(cn[2]>>4))/4);
  1952.     if (Pattern[CurSpot+2]) Pattern[CurSpot+2]++;
  1953.     if (Pattern[CurSpot+2]>0x10) Pattern[CurSpot+2]=0x10;
  1954.     if (!Pattern[CurSpot]) Pattern[CurSpot+2]=0;
  1955.     if ((cn[2]&0xF)==0x1) {
  1956.       curper=((cn[3]*Tempo)/64);
  1957.       if (curper<0x30) Pattern[CurSpot+3]=0xF0|curper;
  1958.       if (ptr<(4*4)) CurTempo=curper;
  1959. //      Pattern[CurRow*64+23]=0xD0|((cn[3]*Tempo)%64);
  1960. /*      Pattern[CurSpot+3]=0xF0|tS2F[cn[3]];
  1961.       Pattern[CurRow*64+23]=0xD0;
  1962.       Pattern[CurRow*64+27]=0xD0|fS2F[cn[3]]; */
  1963.     }
  1964.     if ((cn[2]&0xF)==0x3) BreakLoc=CurRow-1;
  1965.     if (CurVoice==(4-1)) {
  1966.       CurRow++;
  1967.       CurVoice=0;
  1968.     }
  1969.     else
  1970.       CurVoice++;
  1971.   }
  1972. }
  1973.  
  1974. int LoadSTMSmp(FILE *i,word n) {
  1975.   byte  far *q;
  1976.   dword d=0;
  1977.   int   retval=1;
  1978.  
  1979.   Sample[n].SType=0;
  1980.  
  1981.   if (Sample[n].RepEnd==0xFFFF) {
  1982.     Sample[n].RepEnd=Sample[n].Len;
  1983.     Sample[n].LoopMode=0;
  1984.   }
  1985.   else
  1986.     Sample[n].LoopMode=(1<<3);
  1987.  
  1988.   if (Sample[n].Len>0) {
  1989.     Sample[n].Seg=HighPtr>>16;
  1990.     Sample[n].Off=HighPtr&0xFFFF;
  1991.     if (!GenLoad(i,Sample[n].Len,0,n)) {
  1992.       Msg("RAN OUT OF MEMORY!!! {push key}");
  1993.       retval=0;
  1994.     }
  1995.   }
  1996.   else {
  1997.     Sample[n].Seg=0;
  1998.     Sample[n].Off=0;
  1999.   }
  2000.   return retval;
  2001. }
  2002.  
  2003. void LoadSTM(char *fn) {
  2004.   FILE  *i;
  2005.   word  m,q=strlen(fn);
  2006.   word  NumSamples=0;
  2007.   byte  bal[16]={2,13,13,2,2,13,13,2,2,13,13,2,2,13,13,2};
  2008.   char  Magic[16]={0};
  2009.   char  ffn[80];
  2010.  
  2011.   Saving=ON;
  2012.   if (Playing) StopMusic();
  2013.   i=fopen(fn,"rb");
  2014.   if (!i) {
  2015.     Saving=OFF;
  2016.     return;
  2017.   }
  2018.   memset(SongName,0,sizeof(SongName)); fread(SongName,20,1,i);
  2019.   fread(Magic,8,1,i);
  2020.   if (strcmp(Magic,"!Scream!")) {
  2021.     fclose(i);
  2022.     Saving=OFF;
  2023.     return;
  2024.   }
  2025.  
  2026.   FreeSong();
  2027.   strcpy(ffn,fn);
  2028.   ffn[q-3]='F'; ffn[q-2]='A'; ffn[q-1]='R';
  2029.   strcpy(DosName,ffn);
  2030.   Saved=TRUE;
  2031.  
  2032.   FormLoad("STM");
  2033.   memset(SongText,0,sizeof(SongText));
  2034.   fseek(i,4,SEEK_CUR);
  2035.   Tempo=fgetc(i);
  2036.   NumPatterns=fgetc(i);
  2037.   MaxVol=fgetc(i);
  2038.   fseek(i,13,SEEK_CUR);
  2039.  
  2040.   NumSamples=31;
  2041.   memset(Sample,0,sizeof(Sample));
  2042.   for (m=0;m<NumSamples;m++) {
  2043.     fread(Sample[m].Name,12,1,i);
  2044.     fgetc(i); fgetc(i); fgetc(i); fgetc(i);
  2045.     fread(&Sample[m].Len,2,1,i);
  2046.     fread(&Sample[m].Rep,2,1,i);
  2047.     fread(&Sample[m].RepEnd,2,1,i);
  2048.     fread(&Sample[m].Volume,1,1,i); Sample[m].Volume>>=2;
  2049.     fgetc(i);
  2050.     fgetc(i); fgetc(i);
  2051.     fgetc(i); fgetc(i); fgetc(i); fgetc(i);
  2052.     fgetc(i); fgetc(i);
  2053.     if (Sample[m].RepEnd!=0xFFFF)
  2054.       Sample[m].LoopMode=(1<<3);
  2055.     if (!Sample[m].Name[0] && Sample[m].Len) Sample[m].Name[0]=32;
  2056.   }
  2057.  
  2058.   memset(Order,0,256); fread(Order,128,1,i);
  2059.   for (q=128;q>=0;q--) {
  2060.     if (Order[q]!=63) {
  2061.       OrdLen=q;
  2062.       break;
  2063.     }
  2064.   }
  2065.   for (q=0;q<128;q++)
  2066.     if (Order[q]==63) Order[q]=0xFF;
  2067.  
  2068.   for (m=0;m<NumPatterns;m++) {
  2069.     LStat(q);
  2070.     LoadSTMPat(i);
  2071.     if (!BreakLoc) BreakLoc=62;
  2072.     PutAwayPat(m);
  2073.   }
  2074.   HighPtr=64;
  2075.   for (m=0;m<NumSamples;m++) {
  2076.     LStat(q);
  2077.     if (!LoadSTMSmp(i,m)) break;
  2078.   }
  2079.   fclose(i);
  2080.   CurPattern=0; CurOrder=0;
  2081.   CurVoice=0; CurRow=0; CurTop=0;
  2082.   CurSample=0; CurVol=0x10;
  2083.   if (!CurTempo || CurTempo>0xF) CurTempo=4;
  2084.   memset(ChanOn,1,sizeof(ChanOn));
  2085.   memcpy(CurBalance,bal,sizeof(CurBalance));
  2086.   MarkTop=1; MarkBot=0;
  2087.   Grid=4; EditMode=ON;
  2088.  
  2089.   memset(Pattern,0,sizeof(Pattern));
  2090.   GetPat(CurPattern);
  2091.   UpdateChans();
  2092.   Saving=OFF;
  2093.   sScreen();
  2094. }
  2095.  
  2096.  
  2097. // =============================================================== ULT format
  2098.  
  2099. void LoadULTPatt(FILE *f,word n,byte nv) {
  2100.   byte tb,f1,f2,p1,p2;
  2101.   word q,rc;
  2102.   byte far *ppp;
  2103.  
  2104.   memset(Pattern,0,sizeof(Pattern));
  2105.   for (CurVoice=0;CurVoice<nv;CurVoice++)
  2106.     for (CurRow=0;CurRow<64;CurRow++) {
  2107.       rc=0;
  2108.       tb=fgetc(f);
  2109.       if (tb==0xfc) {
  2110.         rc=fgetc(f);
  2111.         tb=fgetc(f);
  2112.       }
  2113.       if (CurVoice<16) {
  2114.         if (tb>13)
  2115.           Pattern[CurSpot]=tb-12;
  2116.         else
  2117.           Pattern[CurSpot]=tb;
  2118.         Pattern[CurSpot+1]=fgetc(f);
  2119.         Pattern[CurSpot+2]=0;
  2120.       }
  2121.       else fgetc(f);
  2122.       f1=fgetc(f);
  2123.       f2=f1&0xF; f1>>=4;
  2124.       p2=fgetc(f); p1=fgetc(f);
  2125.       if (CurVoice<16) {
  2126.         if (f1==0xC) {
  2127.           Pattern[CurSpot+2]=(p1/4)+1;
  2128.           if (Pattern[CurSpot+2]>0x10) Pattern[CurSpot+2]=0x10;
  2129.         }
  2130.         if (f2==0xC) {
  2131.           Pattern[CurSpot+2]=(p2/4)+1;
  2132.           if (Pattern[CurSpot+2]>0x10) Pattern[CurSpot+2]=0x10;
  2133.         }
  2134.         if (f1==0xD || f2==0xD) BreakLoc=CurRow+1;
  2135.         if (!Pattern[CurSpot+2] && tb) Pattern[CurSpot+2]=0x10;
  2136.         ppp=&Pattern[CurSpot];
  2137.         for (q=0;q<rc && CurRow<64;q++) {
  2138.           CurRow++;
  2139.           memcpy(&Pattern[CurSpot],ppp,4);
  2140.         }
  2141.       }
  2142.     }
  2143. }
  2144.  
  2145. int LoadULTSmp(FILE *i,word n) {
  2146.   int retval;
  2147.  
  2148.   Sample[n].SType=0;
  2149.   if (Sample[n].RepEnd<5) {
  2150.     Sample[n].RepEnd=Sample[n].Len;
  2151.     Sample[n].LoopMode=0;
  2152.   }
  2153.   else
  2154.     Sample[n].LoopMode=(1<<3);
  2155.  
  2156.   if (Sample[n].Len>0) {
  2157.     Sample[n].Seg=HighPtr>>16;
  2158.     Sample[n].Off=HighPtr&0xFFFF;
  2159.     if (!GenLoad(i,Sample[n].Len,0,n)) {
  2160.       Msg("RAN OUT OF MEMORY!!! {push key}");
  2161.       retval=0;
  2162.     }
  2163.   }
  2164.   else {
  2165.     Sample[n].Seg=0;
  2166.     Sample[n].Off=0;
  2167.   }
  2168.   return retval;
  2169. }
  2170.  
  2171. void LoadULT(char *fn) {
  2172.   FILE  *i;
  2173.   dword t1,t2;
  2174.   byte  tb;
  2175.   word  q=strlen(fn);
  2176.   word  NumSamples=0,noc,nop;
  2177.   char  Magic[16]={0};
  2178.   char  ffn[80];
  2179.   byte  Vers=0,jv;
  2180.   dword dd;
  2181.  
  2182.   Saving=ON;
  2183.   if (Playing) StopMusic();
  2184.   i=fopen(fn,"rb");
  2185.   if (!i) {
  2186.     Saving=OFF;
  2187.     return;
  2188.   }
  2189.   fread(Magic,15,1,i);
  2190.   if (!strcmp(Magic,"MAS_UTrack_V001")) Vers=1;
  2191.   if (!strcmp(Magic,"MAS_UTrack_V002")) Vers=2;
  2192.   if (!strcmp(Magic,"MAS_UTrack_V003")) Vers=3;
  2193.   if (!Vers) {
  2194.     fclose(i);
  2195.     Saving=OFF;
  2196.     return;
  2197.   }
  2198.  
  2199.   FreeSong();
  2200.   strcpy(ffn,fn);
  2201.   ffn[q-3]='F'; ffn[q-2]='A'; ffn[q-1]='R';
  2202.   strcpy(DosName,ffn);
  2203.   Saved=TRUE;
  2204.  
  2205.   FormLoad("ULT");
  2206.   memset(SongText,0,sizeof(SongText));
  2207.   memset(SongName,0,sizeof(SongName));
  2208.   memset(Sample,0,sizeof(Sample));
  2209.  
  2210.   fread(SongName,32,1,i);
  2211.   jv=fgetc(i);
  2212.   if (Vers>1) {
  2213.     fread(SongText,32*jv,1,i); STLen=32*jv;
  2214.   }
  2215.   fread(&NumSamples,1,1,i);
  2216.  
  2217.   for (q=0;q<NumSamples;q++) {
  2218.     fread(Sample[q].Name,32,1,i); Sample[q].Name[31]=0;
  2219.     fseek(i,12,SEEK_CUR);
  2220.     fread(&Sample[q].Rep,4,1,i);
  2221.     fread(&Sample[q].RepEnd,4,1,i);
  2222.     fread(&t1,4,1,i);
  2223.     fread(&t2,4,1,i);
  2224.     Sample[q].Len=t2-t1;
  2225.     fgetc(i);
  2226.     tb=fgetc(i);
  2227.     switch(tb) {
  2228.       case 0:
  2229.         Sample[q].LoopMode=0;
  2230.         Sample[q].SType=0;
  2231.         break;
  2232.       case 4:
  2233.         Sample[q].LoopMode=(1<<2);
  2234.         Sample[q].SType=1;
  2235.         break;
  2236.       case 24:
  2237.       case 8:
  2238.         Sample[q].LoopMode=(1<<3);
  2239.         Sample[q].SType=0;
  2240.         break;
  2241.       case 28:
  2242.       case 12:
  2243.         Sample[q].LoopMode=(1<<2)|(1<<3);
  2244.         Sample[q].SType=1;
  2245.         break;
  2246.     }
  2247.     if (Sample[q].LoopMode&(1<<2)) {
  2248.       Sample[q].Len*=2;
  2249.       Sample[q].Rep*=2;
  2250.       Sample[q].RepEnd*=2;
  2251.     }
  2252.     fgetc(i); fgetc(i);
  2253.   }
  2254.   fread(Order,256,1,i);
  2255.   noc=fgetc(i); nop=fgetc(i);
  2256.   if (Vers>2) fread(CurBalance,noc,1,i);
  2257.  
  2258.   for (q=0;q<nop-14;q++) {
  2259.     LStat(q);
  2260.     BreakLoc=0;
  2261.     LoadULTPatt(i,q,noc);
  2262.     if (!BreakLoc) BreakLoc=64;
  2263.     PutAwayPat(q);
  2264.   }
  2265.   for (q=0;q<NumSamples;q++) {
  2266.     LStat(q);
  2267.     if (!LoadULTSmp(i,q)) break;
  2268.   }
  2269.   fclose(i);
  2270.   CurRow=0; CurVoice=0;
  2271.   CurPattern=0;
  2272.   GetPat(CurPattern);
  2273.   sScreen();
  2274.   Saving=OFF;
  2275. }
  2276.  
  2277.