/*
Name:
LOAD_MTM.C
Description:
MTM module 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 MTMHEADER{
byte id[]; /* MTM file marker */
short version; /* upper major, lower nibble minor version number */
byte songname[]; /* ASCIIZ songname */
short numtracks; /* number of tracks saved */
short lastpattern; /* last pattern number saved */
short lastorder; /* last order number to play (songlength-1) */
int commentsize; /* length of comment field */
short numsamples; /* number of samples saved */
short attribute; /* attribute byte (unused) */
short beatspertrack; /* */
short numchannels; /* number main_class.MLoader->of channels used */
short panpos[]; /* voice pan positions */
public MTMHEADER()
{
id = new byte[3];
songname = new byte[20];
panpos = new short[32];
}
}
class MTMSAMPLE{
byte samplename[];
int length;
int reppos;
int repend;
short finetune;
short volume;
short attribute;
public MTMSAMPLE()
{
samplename = new byte[22];
}
}
class MTMNOTE{
short a,b,c;
}
public class MTM_Loader extends clLOADER
{
protected MTMHEADER mh;
public MTMNOTE [] mtmtrk;
public short pat[]; //[32];
public final String MTM_Version="MTM";
public MTM_Loader(clMainBase theMain)
{
super(theMain);
mh = null;
type = new String("MTM");
version = new String("Portable MTM loader v0.1");
pat = new short[32];
}
public boolean Test()
{
byte id[] = new byte[3];
//if(!fread(id,3,1,m_.MLoader.modfp)) return 0;
if (m_.MLoader.modfp.read(id,0,3) != 3) return false;
//if(!memcmp(id,"MTM",3)) return 1;
if ( ((char)id[0] == 'M') && ((char)id[1] == 'T') && ((char)id[2] == 'M') )
return true;
return false;
}
public boolean Init()
{
int i;
mtmtrk=null;
mh=null;
//if(!(mtmtrk=(MTMNOTE *)m_.MLoader.MyCalloc(64,sizeof(MTMNOTE)))) return 0;
mtmtrk = new MTMNOTE[64];
for(i=0;i<64;i++)
mtmtrk[i] = new MTMNOTE();
for(i=0;i<64;i++)
{
mtmtrk[i].a = mtmtrk[i].b = mtmtrk[i].c = 0;
}
//if(!(mh=(MTMHEADER *)m_.MLoader.MyCalloc(1,sizeof(MTMHEADER)))) return 0;
mh = new MTMHEADER();
mh.version = mh.numtracks = mh.lastpattern = mh.lastorder =
mh.numsamples = mh.attribute =
mh.beatspertrack = mh.numchannels = (short)0;
mh.id[0] = mh.id[1] = mh.id[2] = (byte)0;
mh.commentsize = 0;
for(i=0;i<20;i++)
mh.songname[i] = 0;
for(i=0;i<32;i++)
mh.panpos[i] = 0;
return true;
}
public void Cleanup()
{
if (mtmtrk != null)
mtmtrk = null;
if (mh != null)
mh = null;
}
public short [] MTM_Convert()
{
int t;
short a,b,c,inst,note,eff,dat;
m_.MUniTrk.UniReset();
for(t=0;t<64;t++){
a=mtmtrk[t].a;
b=mtmtrk[t].b;
c=mtmtrk[t].c;
inst=(short)(((a&0x3)<<4)|(b>>4));
note=(short)(a>>2);
eff=(short)(b&0xf);
dat=c;
if(inst!=0){
m_.MUniTrk.UniInstrument((short)(inst-1));
}
if(note!=0){
m_.MUniTrk.UniNote((short)(note+24));
}
/* mtm bug bugfix: when the effect is volslide,
slide-up _always_ overrides slide-dn. */
if(eff==0xa && ((dat&0xf0) != 0)) dat&=0xf0;
m_.MUniTrk.UniPTEffect(eff,dat);
m_.MUniTrk.UniNewline();
}
return m_.MUniTrk.UniDup();
}
public boolean Load()
{
try {
MTMSAMPLE s = new MTMSAMPLE();
//INSTRUMENT *d;
//SAMPLE *q;
int inst_num;
int t,u;
/* try to read module header */
m_.mmIO._mm_read_SBYTES(mh.id,3,m_.MLoader.modfp);
mh.version =m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
m_.mmIO._mm_read_str(mh.songname,20,m_.MLoader.modfp);
mh.numtracks =(short)m_.mmIO._mm_read_I_UWORD(m_.MLoader.modfp);
mh.lastpattern =m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
mh.lastorder =m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
mh.commentsize =m_.mmIO._mm_read_I_UWORD(m_.MLoader.modfp);
mh.numsamples =m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
mh.attribute =m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
mh.beatspertrack=m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
mh.numchannels =m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
m_.mmIO._mm_read_UBYTES2(mh.panpos,32,m_.MLoader.modfp);
//if(feof(m_.MLoader.modfp)){
if (m_.MLoader.modfp.getFilePointer() >= m_.MLoader.modfp.length()) {
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.modtype=new String(MTM_Version);
m_.MLoader.of.numchn=mh.numchannels;
m_.MLoader.of.numtrk=(short)(mh.numtracks+1); /* get number m_.MLoader.of channels */
m_.MLoader.of.songname=m_.MLoader.DupStr(mh.songname,20); /* make a cstr m_.MLoader.of songname */
m_.MLoader.of.numpos=(short)(mh.lastorder+1); /* copy the songlength */
m_.MLoader.of.numpat=(short)(mh.lastpattern+1);
for(t=0;t<32;t++) m_.MLoader.of.panning[t]=(short)(mh.panpos[t]<<4);
m_.MLoader.of.numins=mh.numsamples;
if(!m_.MLoader.AllocInstruments()) return false;
//d=m_.MLoader.of.instruments;
inst_num = 0;
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;
/* try to read sample info */
m_.mmIO._mm_read_str(s.samplename,22,m_.MLoader.modfp);
s.length =m_.mmIO._mm_read_I_ULONG(m_.MLoader.modfp);
s.reppos =m_.mmIO._mm_read_I_ULONG(m_.MLoader.modfp);
s.repend =m_.mmIO._mm_read_I_ULONG(m_.MLoader.modfp);
s.finetune =m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
s.volume =m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
s.attribute =m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
//if(feof(m_.MLoader.modfp)){
if (m_.MLoader.modfp.getFilePointer() >= m_.MLoader.modfp.length()) {
m_.mmIO.myerr=m_.ERROR_LOADING_SAMPLEINFO;
return false;
}
m_.MLoader.of.instruments[inst_num].insname = m_.MLoader.DupStr(s.samplename,22);
m_.MLoader.of.instruments[inst_num].samples[0].seekpos = 0;
m_.MLoader.of.instruments[inst_num].samples[0].c2spd = m_.MLoader.finetune[s.finetune];
m_.MLoader.of.instruments[inst_num].samples[0].length = s.length;
m_.MLoader.of.instruments[inst_num].samples[0].loopstart = s.reppos;
m_.MLoader.of.instruments[inst_num].samples[0].loopend = s.repend;
m_.MLoader.of.instruments[inst_num].samples[0].volume = s.volume;
m_.MLoader.of.instruments[inst_num].samples[0].flags = 0;
if(s.repend-s.reppos>2)
m_.MLoader.of.instruments[inst_num].samples[0].flags|=(m_.MDriver.SF_LOOP); /* <- 1.00 bugfix */
if((s.attribute&1) != 0){
/* If the sample is 16-bits, convert the length
and replen byte-values into sample-values */
m_.MLoader.of.instruments[inst_num].samples[0].flags |= (m_.MDriver.SF_16BITS);
m_.MLoader.of.instruments[inst_num].samples[0].length >>= 1;
m_.MLoader.of.instruments[inst_num].samples[0].loopstart >>= 1;
m_.MLoader.of.instruments[inst_num].samples[0].loopend >>= 1;
}
inst_num++;
}
m_.mmIO._mm_read_UBYTES2(m_.MLoader.of.positions,128,m_.MLoader.modfp);
//if(feof(m_.MLoader.modfp)){
if (m_.MLoader.modfp.getFilePointer() >= m_.MLoader.modfp.length()) {
m_.mmIO.myerr=m_.ERROR_LOADING_HEADER;
return false;
}
if(!m_.MLoader.AllocTracks()) return false;
if(!m_.MLoader.AllocPatterns()) return false;
m_.MLoader.of.tracks[0]=MTM_Convert(); /* track 0 is empty */
for(t=1;t<m_.MLoader.of.numtrk;t++){
int s_;
for(s_=0;s_<64;s_++){
mtmtrk[s_].a=m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
mtmtrk[s_].b=m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
mtmtrk[s_].c=m_.mmIO._mm_read_UBYTE(m_.MLoader.modfp);
}
//if(feof(m_.MLoader.modfp)){
if (m_.MLoader.modfp.getFilePointer() >= m_.MLoader.modfp.length()) {
m_.mmIO.myerr="Error loading track";
return false;
}
if((m_.MLoader.of.tracks[t]=MTM_Convert()) == null) return false;
}
for(t=0;t<m_.MLoader.of.numpat;t++){
m_.mmIO._mm_read_I_SWORDS(pat,32,m_.MLoader.modfp);
for(u=0;u<m_.MLoader.of.numchn;u++){
m_.MLoader.of.patterns[((int)t*m_.MLoader.of.numchn)+u]=pat[u];
}
}
/* read comment field */
if(!m_.MLoader.ReadComment((short)mh.commentsize)) return false;
return true;
}
catch (IOException ioe1)
{
return false;
}
}
}