home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Large Pack of OldSkool DOS MOD Trackers
/
far100.zip
/
FILE.C
< prev
next >
Wrap
Text File
|
1994-08-05
|
57KB
|
2,277 lines
/* Farandole Composer 1.00 (c)'94 Daniel Potter */
/* This file contains code for all the loading and saving operations involved
in far. May it bring you many happy hours of hacking. */
#include "defaults.h"
#include "stdio.h"
#include "far.h"
#include "gus.h"
#include "alloc.h"
#include "dir.h"
#include "dos.h"
#include "kb.h"
#include "io.h"
#include "string.h"
void FormLoad(char *t) {
char str[80];
sprintf(str," Loading %s format",t);
Msgnw(str);
}
void FormSave(char *t) {
char str[80];
sprintf(str," Saving %s format",t);
Msgnw(str);
}
void LStat(int n) {
DrawF(120,42,11,9," %d ",n);
}
// ******************************************** Little directory selector box
char far *Names[1024]={NULL},*fnames[1024]={NULL};
extern Flag LoadName;
void NameSort(int l,int r) {
int i,j;
char x[32],y[32],q[32];
i=l; j=r; strcpy(x,Names[(l+r)/2]);
do {
while (strcmp(Names[i],x)<0) i++;
while (strcmp(x,Names[j])<0) j--;
if (i<=j) {
strcpy(y,Names[i]); strcpy(Names[i],Names[j]); strcpy(Names[j],y);
strcpy(q,fnames[i]);strcpy(fnames[i],fnames[j]);strcpy(fnames[j],q);
i++; j--;
}
} while (!(i>j));
if (l<j) NameSort(l,j);
if (i<r) NameSort(i,r);
}
void TNameSort(int l,int r) {
word q;
for (q=l;q<=r;q++)
if (!Names[q][0]) {
Names[q][0]='■';
Names[q][1]=0;
}
NameSort(l,r);
for (q=l;q<=r;q++)
if (Names[q][0]=='■') Names[q][0]=0;
}
void FNameSort(int l,int r) {
int i,j;
char x[32],y[32],q[32];
i=l; j=r; strcpy(x,fnames[(l+r)/2]);
do {
while (strcmp(fnames[i],x)<0) i++;
while (strcmp(x,fnames[j])<0) j--;
if (i<=j) {
strcpy(y,Names[i]); strcpy(Names[i],Names[j]); strcpy(Names[j],y);
strcpy(q,fnames[i]);strcpy(fnames[i],fnames[j]);strcpy(fnames[j],q);
i++; j--;
}
} while (!(i>j));
if (l<j) FNameSort(l,j);
if (i<r) FNameSort(i,r);
}
int ptr=0,namestart;
void Rescan(char *mask) {
struct ffblk ffblk;
char junk[4];
Flag Done;
word q;
FILE *f;
for (q=0;q<1024;q++) {
farfree(fnames[q]); fnames[q]=NULL;
farfree(Names[q]); Names[q]=NULL;
}
ptr=0;
Done=findfirst("*.*",&ffblk,FA_DIREC);
while (!Done) {
if (ffblk.ff_attrib&FA_DIREC) {
farfree(fnames[ptr]);
fnames[ptr]=farmalloc(14);
if (!fnames[ptr]) return;
farfree(Names[ptr]); Names[ptr]=NULL;
strcpy(fnames[ptr],ffblk.ff_name);
strupr(fnames[ptr]);
strcat(fnames[ptr],"\\");
if (strcmp(fnames[ptr],".\\")) ptr++;
}
Done=findnext(&ffblk);
}
UpdateStat();
namestart=ptr;
FNameSort(0,namestart-1);
Done=findfirst(mask,&ffblk,FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCH);
while (!Done) {
if (!(ffblk.ff_attrib&FA_DIREC)) {
farfree(Names[ptr]);
Names[ptr]=farmalloc(34);
if (!Names[ptr]) return;
farfree(fnames[ptr]);
fnames[ptr]=farmalloc(14);
if (!fnames[ptr]) return;
memset(Names[ptr],0,33);
memset(fnames[ptr],0,13);
strcpy(fnames[ptr],ffblk.ff_name);
q=strlen(fnames[ptr]);
strupr(fnames[ptr]);
if (LoadName) {
if (fnames[ptr][q-3]=='F' &&
(fnames[ptr][q-2]=='S' && fnames[ptr][q-1]=='M') ||
(fnames[ptr][q-2]=='A' && fnames[ptr][q-1]=='R') ||
(fnames[ptr][q-2]=='P' && fnames[ptr][q-1]=='T')) {
f=fopen(fnames[ptr],"rb");
fread(junk,4,1,f);
fread(Names[ptr],31,1,f);
fclose(f);
}
if (fnames[ptr][q-3]=='S' && fnames[ptr][q-2]=='T' &&
fnames[ptr][q-1]=='S') {
f=fopen(fnames[ptr],"rb");
fseek(f,0x30,SEEK_SET);
fread(Names[ptr],28,1,f);
fclose(f);
}
if (fnames[ptr][q-3]=='6' && fnames[ptr][q-2]=='6' &&
fnames[ptr][q-1]=='9') {
f=fopen(fnames[ptr],"rb");
fread(junk,2,1,f);
fread(Names[ptr],31,1,f);
fclose(f);
}
if (fnames[ptr][q-3]=='M' && fnames[ptr][q-2]=='O' &&
fnames[ptr][q-1]=='D') {
f=fopen(fnames[ptr],"rb");
fread(Names[ptr],20,1,f);
fclose(f);
}
if (fnames[ptr][q-3]=='M' && fnames[ptr][q-2]=='T' &&
fnames[ptr][q-1]=='M') {
f=fopen(fnames[ptr],"rb");
fseek(f,4,SEEK_SET);
fread(Names[ptr],20,1,f);
fclose(f);
}
if (fnames[ptr][q-3]=='U' && fnames[ptr][q-2]=='L' &&
fnames[ptr][q-1]=='T') {
f=fopen(fnames[ptr],"rb");
fseek(f,15,SEEK_SET);
fread(Names[ptr],32,1,f);
fclose(f);
}
if (fnames[ptr][q-3]=='S' &&
(fnames[ptr][q-2]=='T' || fnames[ptr][q-2]=='3') &&
fnames[ptr][q-1]=='M') {
f=fopen(fnames[ptr],"rb");
memset(Names[ptr],0,32);
switch (fnames[ptr][q-2]) {
case 'T':
fread(Names[ptr],20,1,f);
break;
case '3':
fread(Names[ptr],28,1,f);
break;
}
fclose(f);
}
}
ptr++;
}
Done=findnext(&ffblk);
}
for (q=ptr;q<1024;q++) {
farfree(Names[q]); Names[q]=NULL;
farfree(fnames[q]); fnames[q]=NULL;
}
switch (SortBoxBy) {
case 0:
FNameSort(namestart,ptr-1);
break;
case 1:
TNameSort(namestart,ptr-1);
break;
}
UpdateStat();
}
void ReDraw(int top,int CurFile) {
int q;
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 ");
DrawF(0,10,0,4," Filename Title ");
for (q=top;q<(ptr+top) && q<((42-12)+top);q++) {
if (fnames[q]!=NULL && Names[q]!=NULL) {
DrawF(0,12+(q-top),8,2,"%-13s %-32s",fnames[q],Names[q]);
}
if (fnames[q]!=NULL && Names[q]==NULL) {
DrawF(0,12+(q-top),8,2,"%-13s %-32s",fnames[q]," ");
}
if (fnames[q]==NULL && Names[q]!=NULL) {
DrawF(0,12+(q-top),8,2,"%-13s %-32s"," ",Names[q]);
}
if (fnames[q]==NULL && Names[q]==NULL) {
DrawF(0,12+(q-top),8,2,"%-13s %-32s"," "," ");
}
}
Color(0,12+(CurFile-top),131,12+(CurFile-top),2,8);
}
void LoadOneSmp(char *f);
word DirSelect(char *mask,char *out) {
int q,CurFile=0,k=0,top=0;
char d[80],rval;
Video(0);
MusicMode=OFF;
StopMusic();
UpdateStat();
Rescan(mask);
if (SaveBoxPos) {
CurFile=LastFile&0xFF;
top=LastFile>>8;
if (CurFile>=ptr) {
CurFile=0;
top=0;
}
}
Fill(0,9,131,41,8,2,' ');
ReDraw(top,CurFile);
while (k!=ENTER && k!=ESC) {
k=GetCh();
switch(k) {
case '/':
case '*':
case 'Q':
case 'Z':
LKHit=k;
CustomHandle();
break;
case F8:
GlobalKey(k);
break;
case 'D':
DrawF(0,42,11,9," Change drive: Enter new drive -> ");
k=0;
while (!k) k=GetCh();
if (k!=27) {
setdisk(k-'A');
Rescan(mask);
top=0;
CurFile=0;
Fill(0,9,131,41,8,2,' ');
ReDraw(top,CurFile);
}
UpdateStat();
break;
case CURSUP:
if (Shift) {
Color(0,12+(CurFile-top),131,12+(CurFile-top),8,2);
if (CurFile>0) {
CurFile--;
if (CurFile<top) {
top--;
ReDraw(top,CurFile);
}
}
Color(0,12+(CurFile-top),131,12+(CurFile-top),2,8);
}
else {
if (CurSample>0) CurSample--;
UpdateSamples();
}
break;
case CURSDN:
if (Shift) {
Color(0,12+(CurFile-top),131,12+(CurFile-top),8,2);
if (CurFile<ptr-1) {
CurFile++;
if ((CurFile-top)>(42-13)) {
top++;
ReDraw(top,CurFile);
}
}
Color(0,12+(CurFile-top),131,12+(CurFile-top),2,8);
}
else {
if (CurSample<63) CurSample++;
UpdateSamples();
}
break;
case ' ':
LoadOneSmp(fnames[CurFile]);
UpdateSamples();
break;
case PGDOWN:
Color(0,12+(CurFile-top),131,12+(CurFile-top),8,2);
if ((CurFile-top)==(42-13)) {
if ((top+13)<ptr) {
top+=(42-13);
if ((top+(42-13))>=ptr)top=ptr-(42-13)-1;
CurFile=top+(42-13);
ReDraw(top,CurFile);
}
}
else {
CurFile=top+(42-13);
}
Color(0,12+(CurFile-top),131,12+(CurFile-top),2,8);
break;
case PGUP:
Color(0,12+(CurFile-top),131,12+(CurFile-top),8,2);
if (CurFile==top) {
if (top>0) {
top-=(42-13);
if (top<0) top=0;
CurFile=top;
ReDraw(top,CurFile);
}
}
else
CurFile=top;
Color(0,12+(CurFile-top),131,12+(CurFile-top),2,8);
break;
case ENTER:
if (CurFile<namestart) {
Color(0,12+(CurFile-top),131,12+(CurFile-top),8,2);
strcpy(d,fnames[CurFile]);
d[strlen(d)-1]=0;
chdir(d);
CurFile=0;
top=0;
Rescan(mask);
Fill(0,9,131,41,8,2,' ');
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 ");
DrawF(0,10,0,4," Filename Title ");
ReDraw(top,CurFile);
k=0;
Color(0,12+(CurFile-top),131,12+(CurFile-top),2,8);
}
break;
}
}
Fill(0,9,131,41,8,2,' ');
UpdateChans();
ScrArea(CurArea);
MusicMode=ON;
if (k==ENTER) {
strcpy(out,fnames[CurFile]);
if (SaveBoxPos)
LastFile=CurFile|(top<<8);
else
LastFile=0;
rval=1;
}
else {
if (SaveBoxPos)
LastFile=CurFile|(top<<8);
else
LastFile=0;
rval=0;
}
Return:
for (q=0;q<1024;q++) {
if (fnames[q]) { farfree(fnames[q]); fnames[q]=NULL; }
if (Names[q]) { farfree(Names[q]); Names[q]=NULL; }
}
UpdateStat();
return rval;
}
// ******************** SAMPLE LOADING FUNCTIONS **************************
int 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 *)farmalloc(0xFFFF);
if (q) {
aq=fread(q,0xFFFF,1,f);
for (aq=0;aq<0xFFFF;aq++) q[aq]^=xv;
}
else return 0;
ss=HighPtr>>16; so=HighPtr&0xFFFF;
HighPtr=LoadSample(ss,so,
0xFFFF,
(char far *)q);
farfree(q);
}
if (len%0xFFFF) {
q=(char far *)farmalloc((len%0xFFFF)+32);
if (q) {
aq=fread(q,len%0xFFFF,1,f);
for (aq=0;aq<len%0xFFFF;aq++) q[aq]^=xv;
}
else return 0;
memcpy(&q[(len%0xFFFF)],&q[Sample[sn].Rep],32);
ss=HighPtr>>16; so=HighPtr&0xFFFF;
HighPtr=LoadSample(ss,so,
(len%0xFFFF)+32,
(char far *)q);
farfree(q);
}
return 1;
}
int GenSave(FILE *f,dword len,byte xv,dword segs,dword offs) {
byte far *q;
dword aq,a,ss,so,hp;
hp=(segs<<16)|offs;
for (a=0;a<(len/0xFFFF);a++) {
ss=hp>>16; so=hp&0xFFFF;
q=(char far *)farmalloc(0xFFFF);
if (q)
hp=GetSample(ss,so,0xFFFF,(char far *)q);
else return 0;
for (aq=0;aq<0xFFFF;aq++) q[aq]^=xv;
fwrite(q,0xFFFF,1,f); // Write sample data
farfree(q);
}
if (len%0xFFFF) {
ss=hp>>16; so=hp&0xFFFF;
q=(char far *)farmalloc(len%0xFFFF);
if (q)
hp=GetSample(ss,so,len%0xFFFF,(char far *)q);
else return 0;
for (aq=0;aq<len%0xFFFF;aq++) q[aq]^=xv;
fwrite(q,len%0xFFFF,1,f); // Write sample data
farfree(q);
}
return 1;
}
void CheckPreFile(char *fn,char *n) {
FILE *f;
char t[80],*q;
strupr(fn);
f=fopen(fn,"rb");
if (!f) return;
fread(t,32,1,f); t[32]=0;
if (strcmp(t+4,n)) {
q=strstr(fn,".")-1;
strcpy(t,q);
t[0]++;
if (t[0]>'Z') t[0]='A';
strcpy(q,t);
CheckPreFile(fn,n);
}
fclose(f);
}
int SaveFSM(char *fn, word n) {
byte far *q;
char header[4]="FSM■";
char k[3]={10,13,26};
dword kk;
FILE *f;
char t[80];
int retval=1;
Saving=ON;
strcpy(t,SampDir);
strcat(t,"\\");
strcat(t,fn);
CheckPreFile(t,Sample[n].Name);
f=fopen(t,"wb");
if (!f) {
Saving=OFF;
return;
}
Saved=TRUE;
if (Sample[n].LoopMode&(1<<3))
kk=Sample[n].RepEnd;
else
kk=2;
fwrite(header,4,1,f); // Write ident header
fwrite(&Sample[n].Name,32,1,f); // Write sample name
fwrite(&k,3,1,f); // Write end of file
fwrite(&Sample[n].Len,4,1,f); // Write sample length
fwrite(&Sample[n].FineTune,1,1,f); // Write finetune byte
fwrite(&Sample[n].Volume,1,1,f); // Write default volume byte
fwrite(&Sample[n].Rep,4,1,f); // Write repeat start
fwrite(&kk,4,1,f); // Write repeat end
fwrite(&Sample[n].SType,1,1,f); // Write sample type byte
fwrite(&Sample[n].LoopMode,1,1,f); // Write loop mode byte
if (Sample[n].Len>0)
if (!GenSave(f,Sample[n].Len,0,Sample[n].Seg,Sample[n].Off)) {
Msg("RAN OUT OF MEMORY!!! {push key}");
retval=0;
}
fclose(f);
Saving=OFF;
Alt=OFF;
return retval;
}
int LoadFSM(char *fn,word n) {
byte far *q;
char Header[5]={0};
FILE *f;
int retval=1;
Saving=ON;
StopMusic();
f=fopen(fn,"rb");
if (!f) {
Saving=OFF;
return;
}
fread(Header,4,1,f); // Read 'header'
if (strcmp(Header,"FSM■")) {
fclose(f);
Saving=OFF;
return;
}
Saved=FALSE;
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;
if (!GenLoad(f,Sample[n].Len,0,n)) {
Msg("RAN OUT OF MEMORY!!! {push key}");
retval=0;
}
}
else {
Sample[n].Seg=0;
Sample[n].Off=0;
}
fclose(f);
Saving=OFF;
return retval;
}
int LoadSTS(char *fn,int n) {
byte far *q;
char Header[5]={0};
FILE *f;
int retval=1;
Saving=ON;
StopMusic();
f=fopen(fn,"rb");
if (!f) {
Saving=OFF;
return;
}
fseek(f,0x4c,SEEK_SET);
fread(Header,4,1,f); Header[4]=0;
if (strcmp(Header,"SCRS")) {
fclose(f);
Saving=OFF;
return;
}
Saved=FALSE;
fseek(f,0x10,SEEK_SET); // Skip over header crap
fread(&Sample[n].Len,4,1,f);
fread(&Sample[n].Rep,4,1,f);
fread(&Sample[n].RepEnd,4,1,f);
fread(&Sample[n].Volume,1,1,f);
fgetc(f);
fread(&Sample[n].SType,1,1,f);
fseek(f,16,SEEK_CUR);
fread(Sample[n].Name,32,1,f); // Read sample name
if (Sample[n].SType&1)
Sample[n].LoopMode=(1<<3);
Sample[n].SType=0;
if (Sample[n].RepEnd<5) {
Sample[n].RepEnd=Sample[n].Len;
Sample[n].LoopMode=0;
}
else
Sample[n].LoopMode=(1<<3);
if (Sample[n].Len>0) {
Sample[n].Seg=HighPtr>>16;
Sample[n].Off=HighPtr&0xFFFF;
if (!GenLoad(f,Sample[n].Len,0,n)) {
Msg("RAN OUT OF MEMORY!!! {push key}");
retval=0;
}
}
else {
Sample[n].Seg=0;
Sample[n].Off=0;
}
fclose(f);
Saving=OFF;
return retval;
}
int SaveUnsigned(char *fn,word n) {
byte far *q;
long aq;
FILE *f;
char t[80];
int retval=1;
Saving=ON;
strcpy(t,SampDir);
strcat(t,"\\");
strcat(t,fn);
f=fopen(t,"wb");
if (!f) {
Saving=OFF;
return;
}
if (Sample[n].Len>0)
if (!GenSave(f,Sample[n].Len,128,Sample[n].Seg,Sample[n].Off)) {
Msg("RAN OUT OF MEMORY!!! {push key}");
retval=0;
}
fclose(f);
Saving=OFF;
Alt=OFF;
return retval;
}
int LoadUnsigned(char *fn,word n) {
byte far *q;
dword aq,a,ss,so;
FILE *f;
int retval=1;
Saving=ON;
StopMusic();
f=fopen(fn,"rb");
if (!f) {
Saving=OFF;
return;
}
Saved=FALSE;
strcpy(Sample[n].Name,fn);
Sample[n].Len=filelength(fileno(f));
Sample[n].FineTune=0;
Sample[n].Volume=0xF;
Sample[n].Rep=0;
Sample[n].RepEnd=0;
Sample[n].SType=0;
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;
if (!GenLoad(f,Sample[n].Len,128,n)) {
Msg("RAN OUT OF MEMORY!!! {push key}");
retval=0;
}
}
else {
Sample[n].Seg=0;
Sample[n].Off=0;
}
fclose(f);
Saving=OFF;
return retval;
}
int LoadPAT(char *fn,word n) {
FILE *f;
char Header[9]={0};
word NumSmp;
dword len,rep,repend,curpos;
Flag bit16=FALSE,loop=TRUE;
byte ToLoad=0xFF,Flags;
long k;
byte far *q,*q2;
int retval=1;
Saving=ON;
StopMusic();
f=fopen(fn,"rb");
if (!f) {
Saving=OFF;
return;
}
fread(Header,8,1,f);
if (strcmp(Header,"GF1PATCH")) {
fclose(f);
Saving=OFF;
return;
}
fseek(f,85,SEEK_SET);
fread(&NumSmp,2,1,f); // Read number of samples
fseek(f,239,SEEK_SET); // Skip to first sample block
if (NumSmp>1) {
DrawF(0,42,11,9," LOAD WHICH SAMPLE (0-%X) OR ESC TO ABORT ",NumSmp-1);
Saving=OFF;
while (ToLoad>(NumSmp-1)) {
do {
k=GetCh();
if (k>='0' && k<='9') break;
if (k>='A' && k<='F') break;
if (k==27) break;
} while(1);
if (k>='0' && k<='9') ToLoad=k-'0';
if (k>='A' && k<='F') ToLoad=k-'A'+10;
if (k==27) {
fclose(f);
Saving=OFF;
return;
}
}
UpdateStat();
Saving=ON;
}
Saved=FALSE;
if (ToLoad==255) ToLoad=0;
for (k=0;k<ToLoad;k++) {
curpos=ftell(f); // Store first of patch block
fseek(f,8,SEEK_CUR); // Skip to sample length
fread(&len,4,1,f);
fseek(f,curpos,SEEK_SET); // Skip past sample data+header
fseek(f,96+len,SEEK_CUR);
}
curpos=ftell(f);
fseek(f,8,SEEK_CUR);
fread(&len,4,1,f);
fread(&rep,4,1,f);
fread(&repend,4,1,f);
fseek(f,curpos,SEEK_SET); fseek(f,55,SEEK_CUR);
fread(&Flags,1,1,f); if (Flags&1) bit16=TRUE;
if (Flags&(1<<2)) loop=TRUE; else loop=FALSE;
fseek(f,curpos,SEEK_SET); fseek(f,96,SEEK_CUR);
if (len>0) {
q=(char far *)farmalloc(len);
if (bit16)
q2=(char far *)farmalloc(len/2);
else
q2=q;
if (q)
fread(q,len,1,f); // Read sample data
else {
Msg("RAN OUT OF MEMORY!!! {push key}");
fclose(f);
Saving=OFF;
return 0;
}
if (bit16) {
for (k=0;k<len;k++) q2[k/2]=q[k]^128;
Sample[n].Len=len/2;
Sample[n].Rep=rep/2;
Sample[n].RepEnd=repend/2;
}
else {
Sample[n].Len=len;
Sample[n].Rep=rep;
Sample[n].RepEnd=repend;
}
Sample[n].Seg=HighPtr>>16;
Sample[n].Off=HighPtr&0xFFFF;
HighPtr=LoadSample(Sample[n].Seg,Sample[n].Off,
Sample[n].Len,
(char far *)q2);
Sample[n].SType=0;
if (loop)
Sample[n].LoopMode=(1<<3);
else
Sample[n].LoopMode=0;
farfree(q2);
farfree(q);
}
else {
Sample[n].Seg=0;
Sample[n].Off=0;
}
strcpy(Sample[n].Name,fn);
itoa((int)ToLoad,Header,16); strcat(Sample[n].Name,"-");
strcat(Sample[n].Name,Header);
Saving=OFF;
fclose(f);
return 1;
}
// ******************** SONG SAVING FUNCTIONS ****************************
void SaveF3R(char *name) {
}
// ============================================================== F2R FORMAT
byte far *pat;
FILE *f;
byte bl;
word NumEvents(byte *p) {
word ne=0;
word cp;
for (cp=0;cp<16*4*(bl+1);cp+=4)
if (p[cp] || p[cp+2] || p[cp+3]) ne++;
return ne;
}
byte far StoreQue[4096];
dword QuePtr=0;
void TWrite(byte l) { StoreQue[QuePtr++]=l; }
void DoWrite() {
fwrite(&QuePtr,4,1,f);
fwrite(&StoreQue,QuePtr,1,f);
QuePtr=0;
}
extern int mTempo[];
void WriteEventData(byte *pos,byte et,byte fxparm,byte fxtype) {
byte tb;
switch(et) {
case 0: // Write new octave/note value
tb=(pos[0]-1)/12;
tb<<=4;
tb|=(pos[0]-1)%12;
TWrite(tb+0x10);
break;
case 3: // Write new volume value
if (pos[2]) {
tb=(pos[2]-1)*16;
TWrite(tb);
}
break;
case 1: // Write new instrument value
TWrite(pos[1]);
break;
case 4: // Special effect
TWrite(fxtype);
switch(fxtype) {
case 0x3:
TWrite(fxparm);
TWrite(pos[0]-1);
break;
case 0xa:
TWrite(fxparm);
TWrite((pos[2]-1)*16);
break;
case 0xf:
TWrite(mTempo[fxparm]);
break;
default:
TWrite(fxparm);
break;
}
break;
}
}
void WriteOnePattern() {
word ne=NumEvents(pat),oq,ce,q,TCount=0;
byte fxparm=0,fxtype=0;
Flag s1=TRUE,s2=TRUE,Quit=FALSE;
char sig[4]="JDC";
fwrite(&sig,3,1,f); // Write block signature
fwrite(&ne,2,1,f); // Write the number of events for this block
for (oq=0;oq<16*4*(bl+1);oq+=4) {
if (Quit) break;
if (pat[oq] || pat[oq+2] || pat[oq+3]) {
if (!s1)
TWrite(TCount); // Write qCycles for last note
else
s1=FALSE;
ce=0; // Clear event type
TCount=0; // Clear note wait
if ( (pat[oq]) && ((pat[oq+3]&0xF0)!=0x30) ) {
ce|=(1<<0); // New note value
ce|=(1<<2); // Start a new note
ce|=(1<<1); // New instrument value
ce|=(1<<3); // New volume value
}
if (pat[oq+2]) // Volume change
ce|=(1<<3);
if (pat[oq+3]&0xF0) { // Effect of some type
ce|=(1<<4);
fxtype=pat[oq+3]>>4;
fxparm=pat[oq+3]&0xF;
if (fxtype==0x3) ce|=(1<<5);
if (fxtype==0xA) ce|=(1<<5);
}
TWrite(ce); // Write event type
TWrite((oq/4)%16); // Write channel number
for (q=0;q<8;q++) { // Now write data for event
if (ce&(1<<q))
WriteEventData(&pat[oq],q,fxparm,fxtype);
}
}
if ((((oq/4)%16)==15) && (!s2)) TCount++;
s2=FALSE;
}
TWrite(TCount);
DoWrite(); // Now dump buffered data to disk with length
}
void SaveF2R() {
int q=strlen(DosName),tb;
char fm[7]="F2RFAR";
char name[80];
byte NumInstr,far *qq,NumPatterns;
char sId[4]="JDC";
dword qqq;
FormSave("F2R (<1.0)");
Saving=TRUE;
strcpy(name,DosName);
name[q-3]='F'; name[q-2]='2'; name[q-1]='R';
f=fopen(name,"wb");
fwrite(fm,6,1,f); // Write FileMagic
fwrite(SongName,40,1,f); // Write song name
fwrite(&STLen,2,1,f); // Write songtext length
fwrite(SongText,STLen,1,f); // Write songtext
tb=0x20; fwrite(&tb,1,1,f); // Write song version
tb=16; fwrite(&tb,1,1,f); // We're putting defaults for 16 channels
tb=mTempo[4];fwrite(&tb,1,1,f); // Write default tempo
fwrite(CurBalance,16,1,f); // Write Panning settings
for (q=254;q>=0;q--) {
if (Sample[q].Len || Sample[q].Name[0]) break;
}
NumInstr=q+1; fwrite(&NumInstr,1,1,f);
for (q=0;q<NumInstr;q++) {
fwrite(Sample[q].Name,32,1,f);
fwrite(&Sample[q].Len,4,1,f);
fwrite(&Sample[q].FineTune,1,1,f);
fwrite(&Sample[q].Volume,1,1,f);
fwrite(&Sample[q].Rep,4,1,f);
qqq=Sample[q].RepEnd; if (!(Sample[q].LoopMode&(1<<3))) qqq=0;
fwrite(&qqq,4,1,f);
fwrite(&Sample[q].SType,1,1,f);
if (Sample[q].Len) {
LStat(q);
if (!GenSave(f,Sample[q].Len,0,Sample[q].Seg,Sample[q].Off)) {
Msg("RAN OUT OF MEMORY!!! {push key}");
goto junk_it;
}
}
}
fwrite(&sId,3,1,f); // Write section signature
fwrite(&OrdLen,1,1,f); // Write song len
for (q=255;q>=0;q--) if (PatStore[q]) break;
NumPatterns=q+1; fwrite(&NumPatterns,1,1,f);
fwrite(&LoopTo,1,1,f);
fwrite(&Order,128,1,f);
PutAwayPat(CurPattern);
for (q=0;q<NumPatterns;q++) {
LStat(q);
GetPat(q);
bl=BreakLoc+1;
pat=Pattern;
WriteOnePattern();
}
GetPat(CurPattern);
junk_it:
fclose(f);
UpdateStat();
Saving=FALSE;
}
int SaveOneFSM(word n,FILE *i) {
byte far *q;
dword kk;
int retval=1;
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) {
if (!GenSave(i,Sample[n].Len,0,Sample[n].Seg,Sample[n].Off)) {
Msg("RAN OUT OF MEMORY!!! {push key}");
retval=0;
}
}
return retval;
}
void SaveFAR(char *fn) {
FILE *i;
char Magic1[]="FAR■";
char Magic2[]={13,10,26};
char t[80];
Flag SMap[64/8]={0};
word q,HLen=869+STLen;
FormSave("FAR (<1.0)");
Saving=ON;
Saved=TRUE;
StopMusic();
strcpy(t,SongDir);
strcat(t,"\\");
strcat(t,fn);
i=fopen(t,"wb");
if (!i) {
Saving=OFF;
return;
}
if (Playing) StopMusic();
PutAwayPat(CurPattern);
fwrite(Magic1,4,1,i);
fwrite(SongName,40,1,i);
fwrite(Magic2,3,1,i);
fwrite(&HLen,2,1,i);
fputc(0x10,i);
fwrite(ChanOn,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,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,STLen,1,i);
fwrite(Order,256,1,i);
fwrite(&NumPatterns,1,1,i);
fwrite(&OrdLen,1,1,i);
fwrite(&LoopTo,1,1,i);
for (q=0;q<256;q++) {
if (PatSize[q]) {
PatSize[q]++;
fwrite(&PatSize[q],2,1,i);
PatSize[q]--;
}
else {
fwrite(&PatSize[q],2,1,i);
}
}
for (q=0;q<256;q++)
if (PatStore[q]) {
LStat(q);
fputc(PatStore[q][0],i);
fputc(4,i);
fwrite(&PatStore[q][1],PatSize[q]-1,1,i);
}
for (q=0;q<64;q++) {
if (Sample[q].Len || Sample[q].Name[0]) {
SMap[q/8]|=(1<<(q%8));
}
}
fwrite(SMap,8,1,i);
for (q=0;q<255;q++) {
if (Sample[q].Len || Sample[q].Name[0]) {
LStat(q);
if (!SaveOneFSM(q,i)) goto junk_it;
}
}
junk_it:
fclose(i);
Saving=OFF;
UpdateStat();
}
// ******************** SONG LOADING FUNCTIONS ****************************
void FreeSong() {
word q;
for (q=0;q<256;q++) {
farfree(PatStore[q]);
PatStore[q]=NULL;
PatSize[q]=0;
UpdateStat();
}
}
void LoadF3R(char *name) {
}
void LoadF2R(char *name) {
}
int LoadOneFSM(word n,FILE *i) {
byte far *q;
int retval=1;
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;
if (!GenLoad(i,Sample[n].Len,0,n)) {
Msg("RAN OUT OF MEMORY!!! {push key}");
retval=0;
}
}
else {
Sample[n].Seg=0;
Sample[n].Off=0;
}
return retval;
}
void LoadFAR(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,4,1,i);
if (strcmp(Magic1,"FAR■")) {
fclose(i);
return;
}
Saving=ON;
if (Playing) StopMusic();
FreeSong();
FormLoad("FAR (<1.0)");
Saved=TRUE;
strcpy(DosName,fn);
fread(SongName,40,1,i);
fread(Magic2,3,1,i);
fread(&HdrLen,2,1,i);
fgetc(i);
fread(ChanOn,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,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,STLen,1,i);
else {
fread(SongText,5544,1,i);
fseek(i,STLen-5544,SEEK_CUR);
}
fread(Order,256,1,i);
fread(&NumPatterns,1,1,i);
fread(&OrdLen,1,1,i);
fread(&LoopTo,1,1,i);
fread(PatSize,256,2,i);
if (HdrLen-(869+STLen))
fseek(i,HdrLen-(869+STLen),SEEK_CUR);
for (q=0;q<256;q++)
if (PatSize[q]) {
LStat(q);
PatSize[q]--;
PatStore[q]=(char *)farmalloc(PatSize[q]);
PatStore[q][0]=fgetc(i);
fgetc(i);
fread(&PatStore[q][1],PatSize[q]-1,1,i);
}
fread(SMap,8,1,i);
memset(Sample,0,sizeof(Sample));
HighPtr=64;
for (q=0;q<255;q++)
if (SMap[q/8] & (1<<(q%8))) {
LStat(q);
if (!LoadOneFSM(q,i))
goto junk_it;
}
junk_it:
fclose(i);
memset(Pattern,0,sizeof(Pattern));
GetPat(CurPattern);
sScreen();
Saving=OFF;
}
// =============================================================== MOD format
int LoadMODSmp(FILE *i,word n) {
byte far *q;
dword d=0;
int retval=1;
Sample[n].SType=0;
if (Sample[n].RepEnd<5) {
Sample[n].RepEnd=Sample[n].Len;
Sample[n].LoopMode=0;
}
else
Sample[n].LoopMode=(1<<3);
if (Sample[n].Len>0) {
Sample[n].Seg=HighPtr>>16;
Sample[n].Off=HighPtr&0xFFFF;
if (!GenLoad(i,Sample[n].Len,0,n)) {
Msg("RAN OUT OF MEMORY!!! {push key}");
retval=0;
}
}
else {
Sample[n].Seg=0;
Sample[n].Off=0;
}
return retval;
}
word vals[]={
0x358,0x328,0x2FA,0x2D0,0x2A6,0x280,0x25C,0x23A,0x21A,0x1FC,0x1E0,0x1C5,
0x1AC,0x194,0x17D,0x168,0x153,0x140,0x12E,0x11D,0x10D,0x0FE,0x0F0,0x0E2,
0x0D6,0x0CA,0x0BE,0x0B4,0x0AA,0x0A0,0x097,0x08F,0x087,0x07F,0x078,0x071,
0x06B,0x065,0x05F,0x055,0x050,0x04B,0x047,0x043,0x03F,0x03C,0x038,0x035,
0x032,0x030,0x02D,0x02A,0x028,0x026,0x024,0x020,0x01E,0x01C,0x01B,0x019,
0x018,0x016,0x015,0x014,0x013,0x012,0x011,0x010,0x00F,0x00E,0x00D,0x00C,
0x00B,0x00A,0x009,0x008,0x007,0x006,0x005,0x004,0x003,0x002,0x001 };
byte GetNote(int p) {
word cp;
for (cp=0;cp<7*12;cp++) if (abs(p-vals[cp])<3) return cp%12;
return 0;
}
byte GetOctave(word p) {
if (p<=0x360 && p>=0x1C0) return 1;
if (p<=0x1BF && p>=0x0DA) return 2;
if (p<=0x0D9 && p>=0x06F) return 3;
if (p<=0x06E && p>=0x037) return 4;
if (p<=0x036 && p>=0x01B) return 5;
if (p<=0x01A && p>=0x00D) return 6;
if (p<=0x00C && p>=0x001) return 7;
return 8;
}
byte tM2F[]={0,0,1,1,2,3,3,4,5,5,6,7,7,8,8,9,10,10,11,12,12};
byte fM2F[]={0,0,0,1,1,1,2,2,2,3,3,3,4,4,5,5,5,6,6,6,7};
byte far p1[8192];
void LoadMODPat(FILE *i,byte NumChannels) {
byte cn[8];
word ptr,curper;
CurVoice=0;
memset(Pattern,0,sizeof(Pattern));
fread(p1,256*NumChannels,1,i);
CurRow=0;
for (ptr=0;ptr<(256*NumChannels);ptr+=4) {
memcpy(cn,&p1[ptr],4);
curper=((cn[0]&0xF)<<8)|cn[1];
if (curper)
Pattern[CurSpot]=((GetOctave(curper)-1)*12)+GetNote(curper)+1;
else
Pattern[CurSpot]=0;
Pattern[CurSpot+1]=(cn[0]&0xF0)|((cn[2]&0xF0)>>4);
if (Pattern[CurSpot+1])
Pattern[CurSpot+1]--;
else
Pattern[CurSpot]=0;
Pattern[CurSpot+2]=0;
if ((cn[2]&0xF)==0xC) Pattern[CurSpot+2]=(cn[3]/4)+1;
if (Pattern[CurSpot+2]>0x10) Pattern[CurSpot+2]=0x10;
if (!Pattern[CurSpot+2] && curper) Pattern[CurSpot+2]=0x10;
if ((cn[2]&0xF)==0xF) {
curper=((cn[3]*32)/50);
if (curper<0x30) Pattern[CurSpot+3]=0xF0|curper;
// if (ptr<(4*NumChannels)) CurTempo=curper;
/* Pattern[CurSpot+3]=0xF0|tM2F[cn[3]];
Pattern[CurRow*64+23]=0xD0;
Pattern[CurRow*64+27]=0xD0|fM2F[cn[3]]; */
}
if ((cn[2]&0xF)==0xD) BreakLoc=CurRow-1;
if (CurVoice==(NumChannels-1)) {
CurRow++;
CurVoice=0;
}
else
CurVoice++;
}
}
void LoadMOD(char *fn) {
FILE *i;
word m,q=strlen(fn);
word NumSamples=0;
byte bal[16]={2,13,13,2,2,13,13,2,2,13,13,2,2,13,13,2};
byte NumChannels=0;
char Magic[5]={0};
char ffn[80];
Saving=ON;
if (Playing) StopMusic();
i=fopen(fn,"rb");
if (!i) {
Saving=OFF;
return;
}
fseek(i,1080,SEEK_SET);
fread(Magic,4,1,i);
if (!strcmp(Magic,"M.K.")) NumChannels=4;
if (!strcmp(Magic,"FLT4")) NumChannels=4;
if (!strcmp(Magic,"FLT8")) NumChannels=8;
if (!strcmp(Magic,"6CHN")) NumChannels=6;
if (!strcmp(Magic,"8CHN")) NumChannels=8;
if (!strcmp(Magic,"14CH")) NumChannels=14;
if (!strcmp(Magic,"15CH")) NumChannels=15;
if (!strcmp(Magic,"16CH")) NumChannels=16;
if (!NumChannels) {
fclose(i);
Saving=OFF;
return;
}
FreeSong();
fseek(i,0,SEEK_SET);
strcpy(ffn,fn);
ffn[q-3]='F'; ffn[q-2]='A'; ffn[q-1]='R';
strcpy(DosName,ffn);
Saved=TRUE;
FormLoad(Magic);
memset(SongText,0,sizeof(SongText));
memset(SongName,0,sizeof(SongName)); fread(SongName,20,1,i);
NumSamples=31;
memset(Sample,0,sizeof(Sample));
for (m=0;m<NumSamples;m++) {
fread(Sample[m].Name,22,1,i);
fread(&Sample[m].Len,2,1,i);
Sample[m].Len=(Sample[m].Len>>8)|((Sample[m].Len&0xFF)<<8);
Sample[m].Len<<=1;
fread(&Sample[m].FineTune,1,1,i);
fread(&Sample[m].Volume,1,1,i); Sample[m].Volume>>=2;
fread(&Sample[m].Rep,2,1,i);
Sample[m].Rep=(Sample[m].Rep>>8)|((Sample[m].Rep&0xFF)<<8);
Sample[m].Rep<<=1;
fread(&Sample[m].RepEnd,2,1,i);
Sample[m].RepEnd=(Sample[m].RepEnd>>8)|((Sample[m].RepEnd&0xFF)<<8);
Sample[m].RepEnd<<=1;
if (Sample[m].RepEnd>5)
Sample[m].RepEnd+=Sample[m].Rep;
if (!Sample[m].Name[0] && Sample[m].Len) Sample[m].Name[0]=32;
}
fread(&OrdLen,1,1,i);
fread(&LoopTo,1,1,i); if (LoopTo>=0x7F) LoopTo=0;
memset(Order,0xFF,256); fread(Order,0x80,1,i);
fread(&Magic,4,1,i);
NumPatterns=0;
for (m=0;m<128;m++) if (Order[m]>NumPatterns) NumPatterns=Order[m];
memset(&Order[OrdLen],0xFF,256-OrdLen);
NumPatterns++;
for (m=0;m<NumPatterns;m++) {
LStat(m);
LoadMODPat(i,NumChannels);
if (!BreakLoc) BreakLoc=62;
if (!CurTempo) CurTempo=4;
PutAwayPat(m);
}
HighPtr=64;
for (m=0;m<NumSamples;m++) {
LStat(m);
if (!LoadMODSmp(i,m)) break;
}
fclose(i);
CurPattern=0; CurOrder=0;
CurVoice=0; CurRow=0; CurTop=0;
CurSample=0; CurVol=0x10;
CurTempo=4;
memset(ChanOn,1,sizeof(ChanOn));
memcpy(CurBalance,bal,sizeof(CurBalance));
MarkTop=1; MarkBot=0;
EditMode=ON;
MusicMode=ON;
memset(Pattern,0,sizeof(Pattern));
GetPat(CurPattern);
UpdateChans();
Saving=OFF;
sScreen();
}
// =============================================================== 669 format
void Load669Pat(FILE *i) {
byte p[0x600],cn[6];
word ptr;
memset(Pattern,0,sizeof(Pattern));
fread(p,0x600,1,i);
CurRow=0;
CurVoice=0;
for (ptr=0;ptr<0x600;ptr+=3) {
memcpy(cn,&p[ptr],3);
if (cn[2]==0xff) cn[2]=0;
switch(cn[2]&0xF0) {
case 0x20:
cn[2]=0x10-(cn[2]&0xf);
cn[2]|=0x30;
break;
case 0x30:
cn[2]=cn[2]&0xf;
cn[2]|=0x10;
break;
default:
cn[2]=0;
break;
}
if (cn[0]==0xfe) {
Pattern[CurSpot]=0;
Pattern[CurSpot+1]=0;
Pattern[CurSpot+2]=(cn[1]&0xF)+1;
Pattern[CurSpot+3]=cn[2];
}
if (cn[0]==0xff) {
Pattern[CurSpot]=0;
Pattern[CurSpot+1]=0;
Pattern[CurSpot+2]=0;
if (cn[2]!=0xFF)
Pattern[CurSpot+3]=cn[2];
else
Pattern[CurSpot+3]=0;
}
if (cn[0]!=0xff && cn[0]!=0xfe) {
if ( ((cn[0]>>2)+1) <=12)
Pattern[CurSpot]=((cn[0]>>2)+1);
else
Pattern[CurSpot]=((cn[0]>>2)+1)-12;
Pattern[CurSpot+1]=((cn[0]&3)<<4)|(cn[1]>>4);
Pattern[CurSpot+2]=(cn[1]&0xF)+1;
Pattern[CurSpot+3]=cn[2];
}
if (CurVoice==7) {
CurRow++;
CurVoice=0;
}
else
CurVoice++;
}
}
int Load669Smp(FILE *i,word n) {
byte far *q;
long aq;
dword d=0;
int retval=1;
Sample[n].FineTune=0;
Sample[n].Volume=0xF;
Sample[n].SType=0;
if (Sample[n].RepEnd<5) {
Sample[n].RepEnd=Sample[n].Len;
Sample[n].LoopMode=0;
}
else
Sample[n].LoopMode=(1<<3);
if (Sample[n].Len>0) {
Sample[n].Seg=HighPtr>>16;
Sample[n].Off=HighPtr&0xFFFF;
if (!GenLoad(i,Sample[n].Len,128,n)) {
Msg("RAN OUT OF MEMORY!!! {push key}");
retval=0;
}
}
else {
Sample[n].Seg=0;
Sample[n].Off=0;
}
return retval;
}
void Load669(char *fn) {
FILE *i;
word m,q=strlen(fn);
word NumSamples=0,qq;
byte Tempos[256]={0},Breaks[256]={0};
byte bal[16]={2,13,2,13,2,13,2,13,2,13,2,13,2,13,2,13};
char ffn[80];
Saving=ON;
if (Playing) StopMusic();
i=fopen(fn,"rb");
if (!i) {
Saving=OFF;
return;
}
fread(&m,2,1,i);
if (m!=0x6669 && m!=0x4E4A) {
fclose(i);
Saving=OFF;
return;
}
strcpy(ffn,fn);
ffn[q-3]='F'; ffn[q-2]='A'; ffn[q-1]='R';
strcpy(DosName,ffn);
Saved=TRUE;
FreeSong();
FormLoad("669");
memset(SongText,0,sizeof(SongText));
fread(SongText,108,1,i); STLen=108;
memset(SongName,0,32); memcpy(SongName,SongText,32);
fread(&NumSamples,1,1,i);
fread(&NumPatterns,1,1,i);
fread(&LoopTo,1,1,i); if (LoopTo==0x7e) LoopTo=0;
memset(Order,0,256); fread(Order,0x80,1,i);
memset(Tempos,0,256); fread(Tempos,0x80,1,i);
memset(Breaks,0,256); fread(Breaks,0x80,1,i);
memset(Sample,0,sizeof(Sample));
for (m=0;m<NumSamples;m++) {
memset(Sample[m].Name,0,13); fread(Sample[m].Name,13,1,i);
fread(&Sample[m].Len,4,1,i);
fread(&Sample[m].Rep,4,1,i);
fread(&Sample[m].RepEnd,4,1,i);
if (Sample[m].RepEnd>=0xFFFF) Sample[m].RepEnd=0;
}
for (m=0;m<NumPatterns;m++) {
LStat(m);
Load669Pat(i);
BreakLoc=Breaks[m]-1;
CurRow=0;
for (qq=0,CurVoice=0;CurVoice<15;CurVoice++) {
if ((Pattern[CurSpot+3]&0xF0)==0xF0) qq=1;
}
if (!qq) Pattern[CurSpot+3]=0xF0|Tempos[m];
PutAwayPat(m);
}
HighPtr=64;
for (m=0;m<NumSamples;m++) {
LStat(m);
if (!Load669Smp(i,m)) goto Done;
}
Done:
fclose(i);
CurPattern=0; CurOrder=0;
CurVoice=0; CurRow=0; CurTop=0;
CurSample=0; CurVol=0x10;
CurTempo=4;
memset(ChanOn,1,sizeof(ChanOn));
memcpy(CurBalance,bal,16);
MarkTop=1; MarkBot=0;
Grid=4; EditMode=ON;
memset(Pattern,0,sizeof(Pattern));
GetPat(CurPattern);
UpdateChans();
Saving=OFF;
sScreen();
}
// =============================================================== MTM format
int LoadMTMSmp(FILE *i,word n) {
byte far *q;
dword d=0,qq;
int retval=1;
Sample[n].SType=0;
if (Sample[n].RepEnd<5) {
Sample[n].RepEnd=Sample[n].Len;
Sample[n].LoopMode=0;
}
else
Sample[n].LoopMode=(1<<3);
if (Sample[n].Len>0) {
Sample[n].Seg=HighPtr>>16;
Sample[n].Off=HighPtr&0xFFFF;
if (!GenLoad(i,Sample[n].Len,128,n)) {
Msg("RAN OUT OF MEMORY!!! {push key}");
retval=0;
}
}
else {
Sample[n].Seg=0;
Sample[n].Off=0;
}
return retval;
}
byte far *tracks[2048];
byte far qBuffer[192];
word far TrakSeq[128][32];
void LoadMTM(char *fn) {
FILE *f;
byte tb;
word m,q=strlen(fn),w,op,e;
char t[80],ffn[80];
word NumTracks=0,NumOrder=0,NumSamples=0,bpt=0,NumTracksPlay=0;
word NumPatterns=0;
byte cn[8];
int cvol;
Saving=ON;
if (Playing) StopMusic();
f=fopen(fn,"rb");
if (!f) {
Saving=OFF;
return;
}
fread(t,3,1,f); t[3]=0;
if (strcmp(t,"MTM")) {
fclose(f);
Saving=OFF;
return;
}
FreeSong();
strcpy(ffn,fn);
ffn[q-3]='F'; ffn[q-2]='A'; ffn[q-1]='R';
strcpy(DosName,ffn);
Saved=TRUE;
FormLoad("MTM");
fgetc(f); // Version #
memset(SongText,0,sizeof(SongText));
memset(SongName,0,sizeof(SongName));
memset(Sample,0,sizeof(Sample));
memset(TrakSeq[0],0,sizeof(TrakSeq));
fread(SongName,20,1,f);
fread(&NumTracks,2,1,f);
NumPatterns=fgetc(f);
NumOrder=fgetc(f);
fread(&STLen,2,1,f);
NumSamples=fgetc(f);
fgetc(f); // Attribute byte
bpt=fgetc(f);
NumTracksPlay=fgetc(f);
fread(CurBalance,16,1,f); fseek(f,16,SEEK_CUR);
for (q=0;q<NumSamples;q++) {
fread(Sample[q].Name,22,1,f);
fread(&Sample[q].Len,4,1,f);
fread(&Sample[q].Rep,4,1,f);
fread(&Sample[q].RepEnd,4,1,f);
Sample[q].FineTune=fgetc(f);
Sample[q].Volume=fgetc(f);
tb=fgetc(f);
if (tb&1) {
Sample[CurSample].SType^=1;
Sample[CurSample].LoopMode^=(1<<2);
}
}
fread(Order,128,1,f);
for (q=NumOrder;q<256;q++) Order[q]=0xFF;
for (q=0;q<NumTracks;q++) {
LStat(q);
fread(qBuffer,192,1,f);
tracks[q]=(char far*)malloc(512);
cvol=0x40;
if (tracks[q]) {
memset(tracks[q],0,258);
for (w=0,op=0;w<64;w++,op+=4) {
memcpy(cn,&qBuffer[w*3],4);
if (cn[0]>>2) {
if ( ((cn[0]>>2)+1) <=12)
tracks[q][op]=((cn[0]>>2)+1);
else
tracks[q][op]=((cn[0]>>2)+1)-12;
cvol=0x40;
}
else tracks[q][op]=0;
tracks[q][op+1]=(((cn[0]&3)<<4) | (cn[1]>>4))-1;
if (tracks[q][op+1]==0xFF) tracks[q][op+1]=0;
tracks[q][op+2]=0;
if ((cn[1]&0xF)==0x1) tracks[q][op+3]=0x10|(cn[2]&0xF);
if ((cn[1]&0xF)==0x2) tracks[q][op+3]=0x20|(cn[2]&0xF);
if ((cn[1]&0xF)==0xC) tracks[q][op+2]=(cn[2]/4)+1;
if (((cn[1]&0xF)==0xC) && ((cn[2]%4)>=2)) tracks[q][op+2]++;
if (((cn[1]&0xF)==0xC) && (cn[2]) && (tracks[q][op+2]<2))
tracks[q][op+2]=2;
if ((cn[1]&0xF)==0xC) cvol=cn[2];
if ((cn[1]&0xF)==0xA || (cn[1]&0xF)==0x5 || (cn[1]&0xF)==0x6) {
if (cn[2]&0xF0) // Slide up
if (cvol<0x40) cvol+=cn[2]>>4;
if (cn[2]&0x0F) // Slide down
if (cvol>0) cvol-=cn[2];
if (cvol<0) cvol=0;
if (cvol>0x40) cvol=0x40;
tracks[q][op+2]=(cvol/4)+1;
if ((cvol%4)>=2) tracks[q][op+2]++;
if ((cvol) && (tracks[q][op+2]<2)) tracks[q][op+2]=2;
}
if (((cn[1]&0xF)==0xE) && ((cn[2]&0xF0)==0xa0 || (cn[2]&0xF0)==0xb0)) {
if ((cn[2]&0xF0)==0xa0) // Slide up
if (cvol<0x40) cvol+=cn[2]&0xF;
if ((cn[2]&0xF0)==0xb0) // Slide down
if (cvol>0) cvol-=cn[2]&0xF;
if (cvol<0) cvol=0;
if (cvol>0x40) cvol=0x40;
tracks[q][op+2]=(cvol/4)+1;
if ((cvol%4)>=2) tracks[q][op+2]++;
if ((cvol) && (tracks[q][op+2]<2)) tracks[q][op+2]=2;
}
if (tracks[q][op+2]>0x10) tracks[q][op+2]=0x10;
if (!tracks[q][op+2] && tracks[q][op]) tracks[q][op+2]=0x10;
if ((cn[1]&0xF)==0xF) {
m=((cn[2]*50)/64);
if (m<0x30) tracks[q][op+3]=0xF0|m;
}
if ((cn[1]&0xF)==0xD) tracks[q][256]=CurRow-1;
}
}
}
fread(TrakSeq[0],(NumPatterns+1)*64,1,f);
for (q=0;q<=NumPatterns;q++) {
LStat(q);
memset(Pattern,0,sizeof(Pattern));
for (w=0;w<16;w++) {
CurVoice=w;
if (TrakSeq[q][w]) {
for (e=0;e<bpt;e++) {
CurRow=e;
memcpy(&Pattern[CurSpot],&tracks[TrakSeq[q][w]-1][4*e],4);
}
if (tracks[TrakSeq[q][w]-1][256])
BreakLoc=tracks[TrakSeq[q][w]-1][256]-1;
else
BreakLoc=62;
}
}
PutAwayPat(q);
}
for (q=0;q<NumTracks;q++) free(tracks[q]);
if (STLen<=5543) {
for (q=0;q<STLen/40;q++)
fread(&SongText[q*132],40,1,f);
STLen=132*(STLen/40);
}
else {
fread(SongText,STLen,5543,f);
fseek(f,STLen-5543,SEEK_CUR);
}
HighPtr=64;
for (m=0;m<NumSamples;m++) {
LStat(q);
if (!LoadMTMSmp(f,m)) break;
}
fclose(f);
CurPattern=0; CurOrder=0;
CurVoice=0; CurRow=0; CurTop=0;
CurSample=0; CurVol=0x10;
CurTempo=4;
memset(ChanOn,1,sizeof(ChanOn));
MarkTop=1; MarkBot=0;
EditMode=ON;
memset(Pattern,0,sizeof(Pattern));
GetPat(CurPattern);
sScreen();
Saving=OFF;
return;
}
// =============================================================== S3M format
void LoadS3M(char *fn) {
FILE *i;
word q=strlen(fn),Magic;
char ffn[80];
Saving=ON;
if (Playing) StopMusic();
i=fopen(fn,"rb");
if (!i) {
Saving=OFF;
return;
}
fseek(i,28,SEEK_SET);
fread(&Magic,2,1,i);
if (Magic!=0x101a) {
fclose(i);
Saving=OFF;
return;
}
FreeSong();
strcpy(ffn,fn);
ffn[q-3]='F'; ffn[q-2]='A'; ffn[q-1]='R';
strcpy(DosName,ffn);
Saved=TRUE;
FormLoad("S3M");
memset(SongText,0,sizeof(SongText));
memset(SongName,0,sizeof(SongName));
memset(Sample,0,sizeof(Sample));
fclose(i);
sScreen();
Saving=OFF;
}
// =============================================================== STM format
byte Tempo=60,MaxVol=0x40;
byte tS2F[]={0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,8,8,9,9,10,10};
byte fS2F[]={0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,7,8,8,9};
void LoadSTMPat(FILE *i) {
byte p[1024],cn[8];
word ptr,curper;
memset(Pattern,0,sizeof(Pattern));
fread(p,256*4,1,i);
CurRow=0;
for (ptr=0;ptr<(256*4);ptr+=4) {
memcpy(cn,&p[ptr],4);
Pattern[CurSpot]=(((cn[0]>>4)-1)*12)+(cn[0]&0xF);
Pattern[CurSpot+1]=cn[1]>>3;
if (Pattern[CurSpot+1])
Pattern[CurSpot+1]--;
else
Pattern[CurSpot]=0;
Pattern[CurSpot+2]=((((cn[1]&7)<<4)|(cn[2]>>4))/4);
if (Pattern[CurSpot+2]) Pattern[CurSpot+2]++;
if (Pattern[CurSpot+2]>0x10) Pattern[CurSpot+2]=0x10;
if (!Pattern[CurSpot]) Pattern[CurSpot+2]=0;
if ((cn[2]&0xF)==0x1) {
curper=((cn[3]*Tempo)/64);
if (curper<0x30) Pattern[CurSpot+3]=0xF0|curper;
if (ptr<(4*4)) CurTempo=curper;
// Pattern[CurRow*64+23]=0xD0|((cn[3]*Tempo)%64);
/* Pattern[CurSpot+3]=0xF0|tS2F[cn[3]];
Pattern[CurRow*64+23]=0xD0;
Pattern[CurRow*64+27]=0xD0|fS2F[cn[3]]; */
}
if ((cn[2]&0xF)==0x3) BreakLoc=CurRow-1;
if (CurVoice==(4-1)) {
CurRow++;
CurVoice=0;
}
else
CurVoice++;
}
}
int LoadSTMSmp(FILE *i,word n) {
byte far *q;
dword d=0;
int retval=1;
Sample[n].SType=0;
if (Sample[n].RepEnd==0xFFFF) {
Sample[n].RepEnd=Sample[n].Len;
Sample[n].LoopMode=0;
}
else
Sample[n].LoopMode=(1<<3);
if (Sample[n].Len>0) {
Sample[n].Seg=HighPtr>>16;
Sample[n].Off=HighPtr&0xFFFF;
if (!GenLoad(i,Sample[n].Len,0,n)) {
Msg("RAN OUT OF MEMORY!!! {push key}");
retval=0;
}
}
else {
Sample[n].Seg=0;
Sample[n].Off=0;
}
return retval;
}
void LoadSTM(char *fn) {
FILE *i;
word m,q=strlen(fn);
word NumSamples=0;
byte bal[16]={2,13,13,2,2,13,13,2,2,13,13,2,2,13,13,2};
char Magic[16]={0};
char ffn[80];
Saving=ON;
if (Playing) StopMusic();
i=fopen(fn,"rb");
if (!i) {
Saving=OFF;
return;
}
memset(SongName,0,sizeof(SongName)); fread(SongName,20,1,i);
fread(Magic,8,1,i);
if (strcmp(Magic,"!Scream!")) {
fclose(i);
Saving=OFF;
return;
}
FreeSong();
strcpy(ffn,fn);
ffn[q-3]='F'; ffn[q-2]='A'; ffn[q-1]='R';
strcpy(DosName,ffn);
Saved=TRUE;
FormLoad("STM");
memset(SongText,0,sizeof(SongText));
fseek(i,4,SEEK_CUR);
Tempo=fgetc(i);
NumPatterns=fgetc(i);
MaxVol=fgetc(i);
fseek(i,13,SEEK_CUR);
NumSamples=31;
memset(Sample,0,sizeof(Sample));
for (m=0;m<NumSamples;m++) {
fread(Sample[m].Name,12,1,i);
fgetc(i); fgetc(i); fgetc(i); fgetc(i);
fread(&Sample[m].Len,2,1,i);
fread(&Sample[m].Rep,2,1,i);
fread(&Sample[m].RepEnd,2,1,i);
fread(&Sample[m].Volume,1,1,i); Sample[m].Volume>>=2;
fgetc(i);
fgetc(i); fgetc(i);
fgetc(i); fgetc(i); fgetc(i); fgetc(i);
fgetc(i); fgetc(i);
if (Sample[m].RepEnd!=0xFFFF)
Sample[m].LoopMode=(1<<3);
if (!Sample[m].Name[0] && Sample[m].Len) Sample[m].Name[0]=32;
}
memset(Order,0,256); fread(Order,128,1,i);
for (q=128;q>=0;q--) {
if (Order[q]!=63) {
OrdLen=q;
break;
}
}
for (q=0;q<128;q++)
if (Order[q]==63) Order[q]=0xFF;
for (m=0;m<NumPatterns;m++) {
LStat(q);
LoadSTMPat(i);
if (!BreakLoc) BreakLoc=62;
PutAwayPat(m);
}
HighPtr=64;
for (m=0;m<NumSamples;m++) {
LStat(q);
if (!LoadSTMSmp(i,m)) break;
}
fclose(i);
CurPattern=0; CurOrder=0;
CurVoice=0; CurRow=0; CurTop=0;
CurSample=0; CurVol=0x10;
if (!CurTempo || CurTempo>0xF) CurTempo=4;
memset(ChanOn,1,sizeof(ChanOn));
memcpy(CurBalance,bal,sizeof(CurBalance));
MarkTop=1; MarkBot=0;
Grid=4; EditMode=ON;
memset(Pattern,0,sizeof(Pattern));
GetPat(CurPattern);
UpdateChans();
Saving=OFF;
sScreen();
}
// =============================================================== ULT format
void LoadULTPatt(FILE *f,word n,byte nv) {
byte tb,f1,f2,p1,p2;
word q,rc;
byte far *ppp;
memset(Pattern,0,sizeof(Pattern));
for (CurVoice=0;CurVoice<nv;CurVoice++)
for (CurRow=0;CurRow<64;CurRow++) {
rc=0;
tb=fgetc(f);
if (tb==0xfc) {
rc=fgetc(f);
tb=fgetc(f);
}
if (CurVoice<16) {
if (tb>13)
Pattern[CurSpot]=tb-12;
else
Pattern[CurSpot]=tb;
Pattern[CurSpot+1]=fgetc(f);
Pattern[CurSpot+2]=0;
}
else fgetc(f);
f1=fgetc(f);
f2=f1&0xF; f1>>=4;
p2=fgetc(f); p1=fgetc(f);
if (CurVoice<16) {
if (f1==0xC) {
Pattern[CurSpot+2]=(p1/4)+1;
if (Pattern[CurSpot+2]>0x10) Pattern[CurSpot+2]=0x10;
}
if (f2==0xC) {
Pattern[CurSpot+2]=(p2/4)+1;
if (Pattern[CurSpot+2]>0x10) Pattern[CurSpot+2]=0x10;
}
if (f1==0xD || f2==0xD) BreakLoc=CurRow+1;
if (!Pattern[CurSpot+2] && tb) Pattern[CurSpot+2]=0x10;
ppp=&Pattern[CurSpot];
for (q=0;q<rc && CurRow<64;q++) {
CurRow++;
memcpy(&Pattern[CurSpot],ppp,4);
}
}
}
}
int LoadULTSmp(FILE *i,word n) {
int retval;
Sample[n].SType=0;
if (Sample[n].RepEnd<5) {
Sample[n].RepEnd=Sample[n].Len;
Sample[n].LoopMode=0;
}
else
Sample[n].LoopMode=(1<<3);
if (Sample[n].Len>0) {
Sample[n].Seg=HighPtr>>16;
Sample[n].Off=HighPtr&0xFFFF;
if (!GenLoad(i,Sample[n].Len,0,n)) {
Msg("RAN OUT OF MEMORY!!! {push key}");
retval=0;
}
}
else {
Sample[n].Seg=0;
Sample[n].Off=0;
}
return retval;
}
void LoadULT(char *fn) {
FILE *i;
dword t1,t2;
byte tb;
word q=strlen(fn);
word NumSamples=0,noc,nop;
char Magic[16]={0};
char ffn[80];
byte Vers=0,jv;
dword dd;
Saving=ON;
if (Playing) StopMusic();
i=fopen(fn,"rb");
if (!i) {
Saving=OFF;
return;
}
fread(Magic,15,1,i);
if (!strcmp(Magic,"MAS_UTrack_V001")) Vers=1;
if (!strcmp(Magic,"MAS_UTrack_V002")) Vers=2;
if (!strcmp(Magic,"MAS_UTrack_V003")) Vers=3;
if (!Vers) {
fclose(i);
Saving=OFF;
return;
}
FreeSong();
strcpy(ffn,fn);
ffn[q-3]='F'; ffn[q-2]='A'; ffn[q-1]='R';
strcpy(DosName,ffn);
Saved=TRUE;
FormLoad("ULT");
memset(SongText,0,sizeof(SongText));
memset(SongName,0,sizeof(SongName));
memset(Sample,0,sizeof(Sample));
fread(SongName,32,1,i);
jv=fgetc(i);
if (Vers>1) {
fread(SongText,32*jv,1,i); STLen=32*jv;
}
fread(&NumSamples,1,1,i);
for (q=0;q<NumSamples;q++) {
fread(Sample[q].Name,32,1,i); Sample[q].Name[31]=0;
fseek(i,12,SEEK_CUR);
fread(&Sample[q].Rep,4,1,i);
fread(&Sample[q].RepEnd,4,1,i);
fread(&t1,4,1,i);
fread(&t2,4,1,i);
Sample[q].Len=t2-t1;
fgetc(i);
tb=fgetc(i);
switch(tb) {
case 0:
Sample[q].LoopMode=0;
Sample[q].SType=0;
break;
case 4:
Sample[q].LoopMode=(1<<2);
Sample[q].SType=1;
break;
case 24:
case 8:
Sample[q].LoopMode=(1<<3);
Sample[q].SType=0;
break;
case 28:
case 12:
Sample[q].LoopMode=(1<<2)|(1<<3);
Sample[q].SType=1;
break;
}
if (Sample[q].LoopMode&(1<<2)) {
Sample[q].Len*=2;
Sample[q].Rep*=2;
Sample[q].RepEnd*=2;
}
fgetc(i); fgetc(i);
}
fread(Order,256,1,i);
noc=fgetc(i); nop=fgetc(i);
if (Vers>2) fread(CurBalance,noc,1,i);
for (q=0;q<nop-14;q++) {
LStat(q);
BreakLoc=0;
LoadULTPatt(i,q,noc);
if (!BreakLoc) BreakLoc=64;
PutAwayPat(q);
}
for (q=0;q<NumSamples;q++) {
LStat(q);
if (!LoadULTSmp(i,q)) break;
}
fclose(i);
CurRow=0; CurVoice=0;
CurPattern=0;
GetPat(CurPattern);
sScreen();
Saving=OFF;
}