/*
Name:
LOAD_M15.C
Description:
15 instrument MOD loader
Portability:
All systems - all compilers (hopefully)
*/
/*************************************************************************
*************************************************************************/
package audio.jmikmod.MikMod.Loaders;
import java.io.IOException;
import audio.jmikmod.MikMod.clLOADER;
import audio.jmikmod.MikMod.clMainBase;
class M15_MSAMPINFO{ /* sample header as it appears in a module */
byte samplename[];
int length;
short finetune;
short volume;
int reppos;
int replen;
public M15_MSAMPINFO()
{
samplename = new byte[22];
}
}
class M15_MODULEHEADER{ /* verbatim module header */
byte songname[]; /* the songname.. */
M15_MSAMPINFO samples[]; /* all sampleinfo */
short songlength; /* number of patterns used */
short magic1; /* should be 127 */
byte positions[]; /* which pattern to play at pos */
public M15_MODULEHEADER()
{
songname = new byte[20];
samples = new M15_MSAMPINFO[15];
int i;
for(i=0;i<15;i++)
samples[i] = new M15_MSAMPINFO();
positions = new byte[128];
}
}
class M15_MODNOTE{
short a,b,c,d;
};
/*************************************************************************
*************************************************************************/
public class M15_Loader extends clLOADER
{
protected M15_MODULEHEADER mh; /* raw as-is module header */
protected M15_MODNOTE patbuf[];
final public short M15_npertab[] = {
/* -> Tuning 0 */
1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906,
856,808,762,720,678,640,604,570,538,508,480,453,
428,404,381,360,339,320,302,285,269,254,240,226,
214,202,190,180,170,160,151,143,135,127,120,113,
107,101,95,90,85,80,75,71,67,63,60,56
};
public M15_Loader(clMainBase theMain)
{
super(theMain);
mh = null;
patbuf = null;
type = new String("15-instrument module");
version = new String("Portable MOD-15 loader v0.1");
}
public boolean LoadModuleHeader(M15_MODULEHEADER mh)
{
try {
int t;
m_.mmIO._mm_read_str(mh.songname,20,m_.MLoader.modfp);
for(t=0;t<15;t++){
//M15_MSAMPINFO *s= &mh.samples[t];
m_.mmIO._mm_read_str(mh.samples[t].samplename,22,m_.MLoader.modfp);
mh.samples[t].length =m_.mmIO._mm_read_M_UWORD(m_.MLoader.modfp);
mh.samples[t].finetune =m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
mh.samples[t].volume =m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
mh.samples[t].reppos =m_.mmIO._mm_read_M_UWORD(m_.MLoader.modfp);
mh.samples[t].replen =m_.mmIO._mm_read_M_UWORD(m_.MLoader.modfp);
}
mh.songlength =m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
mh.magic1 =m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp); /* should be 127 */
m_.mmIO._mm_read_SBYTES(mh.positions,128,m_.MLoader.modfp);
//return(!feof(m_.MLoader.modfp));
return (m_.MLoader.modfp.getFilePointer() < m_.MLoader.modfp.length());
}
catch (IOException ioe1)
{
return false;
}
}
public boolean Test()
{
int t;
M15_MODULEHEADER mh = new M15_MODULEHEADER();
if(!LoadModuleHeader(mh)) return false;
for(t=0;t<15;t++){
/* all finetunes should be zero */
if(mh.samples[t].finetune!=0) return false;
/* all volumes should be <=64 */
if(mh.samples[t].volume>64) return false;
}
if(mh.magic1>127) return false; /* and magic1 should be <128 */
return true;
}
public boolean Init()
{
int i,j;
patbuf=null;
// if(!(mh=(M15_MODULEHEADER *)m_.MLoader.MyCalloc(1,sizeof(M15_MODULEHEADER)))) return 0;
mh = new M15_MODULEHEADER();
mh.songlength = mh.magic1 = 0;
for(i=0;i<20;i++)
mh.songname[i] = 0;
for(i=0;i<128;i++)
mh.positions[i] = 0;
for(i=0;i<15;i++)
{
mh.samples[i].length = mh.samples[i].reppos =
mh.samples[i].replen = 0;
mh.samples[i].finetune = mh.samples[i].volume = (short)0;
for(j=0;j<22;j++)
mh.samples[i].samplename[j] = 0;
}
return true;
}
public void Cleanup()
{
if (mh != null) mh = null;
if(patbuf!=null) patbuf = null;
}
/*
Old (amiga) noteinfo:
_____byte 1_____ byte2_ _____byte 3_____ byte4_
/ \ / \ / \ / \
0000 0000-00000000 0000 0000-00000000
Upper four 12 bits for Lower four Effect command.
bits m_.MLoader.of sam- note period. bits m_.MLoader.of sam-
ple number. ple number.
*/
public void M15_ConvertNote(M15_MODNOTE n)
{
short instrument,effect,effdat,note;
int period;
/* extract the various information from the 4 bytes that
make up a single note */
instrument=(short)((n.a&0x10)|(n.c>>4));
period=(((int)n.a&0xf)<<8)+n.b;
effect=(short)(n.c&0xf);
effdat=n.d;
/* Convert the period to a note number */
note=0;
if(period!=0){
for(note=0;note<60;note++){
if(period>=M15_npertab[note]) break;
}
note++;
if(note==61) note=0;
}
if(instrument!=0){
m_.MUniTrk.UniInstrument((short)(instrument-1));
}
if(note!=0){
m_.MUniTrk.UniNote((short)(note+23));
}
m_.MUniTrk.UniPTEffect(effect,effdat);
}
public short [] M15_ConvertTrack(M15_MODNOTE [] n, int offset)
{
int t;
m_.MUniTrk.UniReset();
int n_ptr = offset;
for(t=0;t<64;t++){
M15_ConvertNote(n[n_ptr]);
m_.MUniTrk.UniNewline();
n_ptr+=m_.MLoader.of.numchn;
}
return m_.MUniTrk.UniDup();
}
public boolean M15_LoadPatterns()
/*
Loads all patterns of a modfile and converts them into the
3 byte format.
*/
{
int t,s,tracks=0;
if(!m_.MLoader.AllocPatterns()) return false;
if(!m_.MLoader.AllocTracks()) return false;
/* Allocate temporary buffer for loading
and converting the patterns */
// if(!(patbuf=(MODNOTE *)m_.MLoader.MyCalloc(64*m_.MLoader.of.numchn,sizeof(MODNOTE)))) return 0;
patbuf = new M15_MODNOTE[64*m_.MLoader.of.numchn];
for(t=0;t<64*m_.MLoader.of.numchn;t++)
patbuf[t] = new M15_MODNOTE();
for(t=0;t<64*m_.MLoader.of.numchn;t++)
{
patbuf[t].a = patbuf[t].b = patbuf[t].c = patbuf[t].d = 0;
}
for(t=0;t<m_.MLoader.of.numpat;t++){
/* Load the pattern into the temp buffer
and convert it */
for(s=0;s<(64*m_.MLoader.of.numchn);s++){
patbuf[s].a=m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
patbuf[s].b=m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
patbuf[s].c=m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
patbuf[s].d=m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
}
for(s=0;s<m_.MLoader.of.numchn;s++){
if((m_.MLoader.of.tracks[tracks++]=M15_ConvertTrack(patbuf, s)) == null) return false;
}
}
return true;
}
public boolean Load()
{
int t;
//INSTRUMENT *d; /* new sampleinfo structure */
//SAMPLE *q;
//M15_MSAMPINFO *s; /* old module sampleinfo */
int inst_num, smpinfo_num;
/* try to read module header */
if(!LoadModuleHeader(mh)){
m_.mmIO.myerr=m_.ERROR_LOADING_HEADER;
return false;
}
/* set module variables */
m_.MLoader.of.initspeed=6;
m_.MLoader.of.inittempo=125;
m_.MLoader.of.numchn=4; /* get number m_.MLoader.of channels */
m_.MLoader.of.modtype=new String("15-instrument"); /* get ascii type m_.MLoader.of mod */
m_.MLoader.of.songname=m_.MLoader.DupStr(mh.songname,20); /* make a cstr m_.MLoader.of songname */
m_.MLoader.of.numpos=mh.songlength; /* copy the songlength */
/* copy the position array */
for(t=0;t<128;t++)
{
m_.MLoader.of.positions[t] = mh.positions[t];
}
/* Count the of patterns */
m_.MLoader.of.numpat=0;
for(t=0;t<128;t++){ /* <-- BUGFIX... have to check ALL positions */
if(m_.MLoader.of.positions[t] > m_.MLoader.of.numpat){
m_.MLoader.of.numpat=m_.MLoader.of.positions[t];
}
}
m_.MLoader.of.numpat++;
m_.MLoader.of.numtrk= (short)(m_.MLoader.of.numpat * m_.MLoader.of.numchn);
/* Finally, init the sampleinfo structures */
m_.MLoader.of.numins=15;
if(!m_.MLoader.AllocInstruments())
return false;
//s=mh.samples; /* init source pointer */
//d=m_.MLoader.of.instruments; /* init dest pointer */
smpinfo_num = 0; /* init source pointer */
inst_num = 0; /* init dest pointer */
for(t=0;t<m_.MLoader.of.numins;t++){
m_.MLoader.of.instruments[inst_num].numsmp=1;
if(!m_.MLoader.AllocSamples((m_.MLoader.of.instruments[inst_num])))
return false;
//q=m_.MLoader.of.instruments[inst_num].samples;
/* convert the samplename */
m_.MLoader.of.instruments[inst_num].insname=m_.MLoader.DupStr(mh.samples[smpinfo_num].samplename,22);
/* init the sampleinfo variables and
convert the size pointers to longword format */
m_.MLoader.of.instruments[inst_num].samples[0].c2spd=m_.MLoader.finetune[mh.samples[smpinfo_num].finetune&0xf];
m_.MLoader.of.instruments[inst_num].samples[0].volume=mh.samples[smpinfo_num].volume;
m_.MLoader.of.instruments[inst_num].samples[0].loopstart=mh.samples[smpinfo_num].reppos;
m_.MLoader.of.instruments[inst_num].samples[0].loopend=m_.MLoader.of.instruments[inst_num].samples[0].loopstart + (mh.samples[smpinfo_num].replen<<1);
m_.MLoader.of.instruments[inst_num].samples[0].length=mh.samples[smpinfo_num].length<<1;
m_.MLoader.of.instruments[inst_num].samples[0].seekpos=0;
m_.MLoader.of.instruments[inst_num].samples[0].flags = (m_.MDriver.SF_SIGNED);
if(mh.samples[smpinfo_num].replen>1)
m_.MLoader.of.instruments[inst_num].samples[0].flags |= (m_.MDriver.SF_LOOP);
/* fix replen if repend>length */
if(m_.MLoader.of.instruments[inst_num].samples[0].loopend > m_.MLoader.of.instruments[inst_num].samples[0].length)
m_.MLoader.of.instruments[inst_num].samples[0].loopend = m_.MLoader.of.instruments[inst_num].samples[0].length;
smpinfo_num++; /* point to next source sampleinfo */
inst_num++; /* point to next destiny sampleinfo */
}
if(!M15_LoadPatterns()) return false;
return true;
}
}