Skip to content
Permalink
master
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
954 lines (817 sloc) 22.5 KB
/*
* Copyright (c) 2009, The MilkyTracker Team.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the <ORGANIZATION> nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* LoaderUNI.cpp
* MilkyPlay Module Loader: MikMod UNIversal Module
*
* Warning: This is an one-by-one conversion of my pascal uni2xm converter ;)
*
*/
#include "Loaders.h"
//#define VERBOSE
struct Uniheader
{
mp_ubyte FileID[4];
mp_ubyte NumChannels;
mp_uword SongLength;
mp_uword RepeatPos;
mp_uword NumPatterns;
mp_uword NumTracks;
mp_uword NumIns;
mp_ubyte InitSpeed;
mp_ubyte InitTempo;
mp_ubyte OrderList[256];
mp_ubyte DefPanning[32];
mp_ubyte Flags;
};
struct Uniinstrument
{
mp_ubyte NumSamps;
mp_ubyte SampleNums[96];
mp_ubyte volflg;
mp_ubyte volpts;
mp_ubyte volsus;
mp_ubyte volbeg;
mp_ubyte volend;
mp_sword VolPoints[12*2];
mp_ubyte panflg;
mp_ubyte panpts;
mp_ubyte pansus;
mp_ubyte panbeg;
mp_ubyte panend;
mp_sword PanPoints[12*2];
mp_ubyte vibtype;
mp_ubyte vibsweep;
mp_ubyte vibdepth;
mp_ubyte vibrate;
mp_uword volfade;
};
struct Unisample
{
mp_uword C2spd;
mp_sbyte relnotenum;
mp_ubyte volume;
mp_ubyte panning;
mp_uint32 smplength;
mp_uint32 smploopstart;
mp_uint32 smploopend;
mp_uword flags;
};
struct MytrackSlot
{
mp_ubyte note, instrument;
mp_ubyte effects[7];
mp_ubyte operands[7];
};
const char* LoaderUNI::identifyModule(const mp_ubyte* buffer)
{
// check for .UNI module
if (!memcmp(buffer,"UN0",3))
{
if (buffer[3] != '4' &&
buffer[3] != '5')
return NULL;
return "UNI";
}
return NULL;
}
static mp_sint32 getMaxEffectsFromTrack(mp_ubyte* track)
{
mp_sint32 y;
mp_sint32 i = 0;
mp_sint32 rowcnt = 0;
mp_sint32 effectCnt = 1;
mp_sint32 maxEffectsPerRow = 0;
do
{
mp_ubyte x = track[i];
mp_ubyte rep = x >> 5;
mp_ubyte len = x & 31;
for (mp_ubyte repcnt = 0; repcnt <= rep; repcnt++)
{
y = 1;
if (len > 1)
{
for (mp_ubyte c = 1; c <= len-1; c++)
{
if (track[y+i])
{
switch (track[y+i])
{
case 1:
//DeTrack[rowcnt].Note:=Track[y+i+1]+1;
y+=2;
c++;
break;
case 2:
//DeTrack[rowcnt].Instrument:=Track[y+i+1]+1;
y+=2;
c++;
break;
case 13:
//if (track[y+i+1]) {
//DeTrack[rowcnt].Effect:=$A;
//DeTrack[rowcnt].Operand:=Track[y+i+1];
//}
//else {
//DeTrack[rowcnt].Effect:=0;
//DeTrack[rowcnt].Operand:=0;
//}
y+=2;
c++;
effectCnt++;
break;
case 15:
//DeTrack[rowcnt].Volume:=Track[y+i+1]+$10
y+=2;
c++;
break;
case 19:
//DeTrack[rowcnt].Effect:=$F;
//DeTrack[rowcnt].Operand:=Track[y+i+1];
y+=2;
c++;
effectCnt++;
break;
case 20:
//DeTrack[rowcnt].Effect:=250;
//DeTrack[rowcnt].Operand:=Track[y+i+1];
y+=2;
c++;
effectCnt++;
break;
case 21:
//DeTrack[rowcnt].Effect:=251;
//DeTrack[rowcnt].Operand:=Track[y+i+1];
y+=2;
c++;
effectCnt++;
break;
case 22:
//DeTrack[rowcnt].Effect:=252;
//DeTrack[rowcnt].Operand:=Track[y+i+1];
y+=2;
c++;
effectCnt++;
break;
case 23:
//DeTrack[rowcnt].Effect:=29;
//DeTrack[rowcnt].Operand:=Track[y+i+1];
y+=2;
c++;
effectCnt++;
break;
case 24:
//DeTrack[rowcnt].Effect:=27;
//DeTrack[rowcnt].Operand:=Track[y+i+1];
y+=2;
c++;
effectCnt++;
break;
case 25:
//DeTrack[rowcnt].Effect:=$F;
//DeTrack[rowcnt].Operand:=Track[y+i+1];
y+=2;
c++;
effectCnt++;
break;
case 26:
//DeTrack[rowcnt].Effect:=$A;
//DeTrack[rowcnt].Operand:=Track[y+i+1];
y+=2;
c++;
effectCnt++;
break;
case 27:
//DeTrack[rowcnt].Effect:=$14;
//DeTrack[rowcnt].Operand:=Track[y+i+1];
y+=2;
c++;
effectCnt++;
break;
default:
//DeTrack[rowcnt].Effect:=Track[y+i]-3;
//DeTrack[rowcnt].Operand:=Track[y+i+1];
y+=2;
c++;
effectCnt++;
}
}
}
}
/*if Detrack[rowcnt].Effect = $E then
if Detrack[rowcnt].Operand shr 4 = 8 then begin
Detrack[rowcnt].Effect:=8;
Detrack[rowcnt].Operand:=(Detrack[rowcnt].Operand and $F) shl 4;
end;
if modeffmode then begin
if (Detrack[rowcnt].Effect=5) and (Detrack[rowcnt].Operand=0) then
Detrack[rowcnt].Effect:=3;
if (Detrack[rowcnt].Effect=6) and (Detrack[rowcnt].Operand=0) then
Detrack[rowcnt].Effect:=4;
if (Detrack[rowcnt].Effect=$A) and (Detrack[rowcnt].Operand=0) then begin
Detrack[rowcnt].Effect:=0;
Detrack[rowcnt].Operand:=0;
end;
end;*/
rowcnt++;
if (effectCnt > maxEffectsPerRow)
maxEffectsPerRow = effectCnt;
effectCnt = 1;
}
i+=len;
} while (rowcnt<256);
return maxEffectsPerRow;
}
static void demuxTrack(mp_ubyte* track, MytrackSlot* deTrack)
{
memset(deTrack, 0, sizeof(MytrackSlot)*256);
mp_sint32 y;
mp_sint32 i = 0;
mp_sint32 rowcnt = 0;
mp_sint32 effectCnt = 1;
mp_sint32 maxEffectsPerRow = 0;
do
{
mp_ubyte x = track[i];
mp_ubyte rep = x >> 5;
mp_ubyte len = x & 31;
for (mp_ubyte repcnt = 0; repcnt <= rep; repcnt++)
{
y = 1;
if (len > 1)
{
for (mp_ubyte c = 1; c <= len-1; c++)
{
if (track[y+i])
{
switch (track[y+i])
{
case 1:
deTrack[rowcnt].note = track[y+i+1]+1;
if (deTrack[rowcnt].note == 97)
deTrack[rowcnt].note = XModule::NOTE_OFF;
y+=2;
c++;
break;
case 2:
deTrack[rowcnt].instrument = track[y+i+1]+1;
y+=2;
c++;
break;
case 13:
if (track[y+i+1]) {
deTrack[rowcnt].effects[effectCnt] = 0xA;
deTrack[rowcnt].operands[effectCnt] = track[y+i+1];
}
else {
deTrack[rowcnt].effects[effectCnt] = 0;
deTrack[rowcnt].operands[effectCnt] = 0;
}
y+=2;
c++;
effectCnt++;
break;
case 15:
deTrack[rowcnt].effects[0] = 0x0C;
deTrack[rowcnt].operands[0] = XModule::vol64to255(track[y+i+1]);
y+=2;
c++;
break;
case 19:
deTrack[rowcnt].effects[effectCnt] = 0xF;
deTrack[rowcnt].operands[effectCnt] = track[y+i+1];
y+=2;
c++;
effectCnt++;
break;
case 20:
deTrack[rowcnt].effects[effectCnt] = 0x49;
deTrack[rowcnt].operands[effectCnt] = track[y+i+1];
y+=2;
c++;
effectCnt++;
break;
case 21:
deTrack[rowcnt].effects[effectCnt] = 0x48;
deTrack[rowcnt].operands[effectCnt] = track[y+i+1];
y+=2;
c++;
effectCnt++;
break;
case 22:
deTrack[rowcnt].effects[effectCnt] = 0x47;
deTrack[rowcnt].operands[effectCnt] = track[y+i+1];
y+=2;
c++;
effectCnt++;
break;
case 23:
// key off?
deTrack[rowcnt].effects[effectCnt] = 51;
deTrack[rowcnt].operands[effectCnt] = track[y+i+1];
y+=2;
c++;
effectCnt++;
break;
case 24:
deTrack[rowcnt].effects[effectCnt] = 27;
deTrack[rowcnt].operands[effectCnt] = track[y+i+1];
y+=2;
c++;
effectCnt++;
break;
case 25:
deTrack[rowcnt].effects[effectCnt] = 0x0F;
deTrack[rowcnt].operands[effectCnt] = track[y+i+1];
y+=2;
c++;
effectCnt++;
break;
case 26:
deTrack[rowcnt].effects[effectCnt] = 0x0A;
deTrack[rowcnt].operands[effectCnt] = track[y+i+1];
y+=2;
c++;
effectCnt++;
break;
case 27:
deTrack[rowcnt].effects[effectCnt] = 0x14;
deTrack[rowcnt].operands[effectCnt] = track[y+i+1];
y+=2;
c++;
effectCnt++;
break;
default:
deTrack[rowcnt].effects[effectCnt] = track[y+i]-3;
deTrack[rowcnt].operands[effectCnt] = track[y+i+1];
if (deTrack[rowcnt].effects[effectCnt] == 0xC)
{
deTrack[rowcnt].operands[effectCnt] = XModule::vol64to255(deTrack[rowcnt].operands[effectCnt]);
}
else if (deTrack[rowcnt].effects[effectCnt] == 0xE)
{
deTrack[rowcnt].effects[effectCnt] = (deTrack[rowcnt].operands[effectCnt]>>4)+0x30;
deTrack[rowcnt].operands[effectCnt]&=0x0F;
}
else if (deTrack[rowcnt].effects[effectCnt] == 0xD)
{
deTrack[rowcnt].operands[effectCnt] = ((deTrack[rowcnt].operands[effectCnt]/10)<<4) + (deTrack[rowcnt].operands[effectCnt]%10);
}
else if (deTrack[rowcnt].effects[effectCnt] == 0)
{
deTrack[rowcnt].effects[effectCnt] = 0x20;
}
y+=2;
c++;
effectCnt++;
}
}
}
}
/*if (detrack[rowcnt].Effect = $E then
if Detrack[rowcnt].Operand shr 4 = 8 then begin
Detrack[rowcnt].Effect:=8;
Detrack[rowcnt].Operand:=(Detrack[rowcnt].Operand and $F) shl 4;
end;
if modeffmode then begin
if (Detrack[rowcnt].Effect=5) and (Detrack[rowcnt].Operand=0) then
Detrack[rowcnt].Effect:=3;
if (Detrack[rowcnt].Effect=6) and (Detrack[rowcnt].Operand=0) then
Detrack[rowcnt].Effect:=4;
if (Detrack[rowcnt].Effect=$A) and (Detrack[rowcnt].Operand=0) then begin
Detrack[rowcnt].Effect:=0;
Detrack[rowcnt].Operand:=0;
end;
end;*/
rowcnt++;
if (effectCnt > maxEffectsPerRow)
maxEffectsPerRow = effectCnt;
effectCnt = 1;
}
i+=len;
} while (rowcnt<256);
}
mp_sint32 LoaderUNI::load(XMFileBase& f, XModule* module)
{
Uniheader uniheader;
Uniinstrument uniinstrument;
Unisample unisample;
mp_uint32 i,j;
module->cleanUp();
// this will make code much easier to read
TXMHeader* header = &module->header;
TXMInstrument* instr = module->instr;
TXMSample* smp = module->smp;
TXMPattern* phead = module->phead;
// we're already out of memory here
if (!phead || !instr || !smp)
return MP_OUT_OF_MEMORY;
f.read(uniheader.FileID, 1, 4);
mp_sbyte uniVersion = -1;
uniheader.NumChannels = f.readByte();
uniheader.SongLength = f.readWord();
if (uniheader.FileID[3] == '4')
uniVersion = 4;
else if (uniheader.FileID[3] == '5')
uniVersion = 5;
if (uniVersion == -1)
return MP_LOADER_FAILED;
if (uniVersion == 5)
uniheader.RepeatPos = f.readWord();
else
uniheader.RepeatPos = 0;
uniheader.NumPatterns = f.readWord();
uniheader.NumTracks = f.readWord();
uniheader.NumIns = f.readWord();
uniheader.InitSpeed = f.readByte();
uniheader.InitTempo = f.readByte();
//f.read(uniheader.OrderList, 1, 256);
f.read(header->ord, 1, 256);
f.read(uniheader.DefPanning, 1, 32);
uniheader.Flags = f.readByte();
i = f.readWord();
mp_ubyte* text = new mp_ubyte[i];
if (text == NULL)
return MP_OUT_OF_MEMORY;
f.read(text, 1, i);
if (i > 32) i = 32;
memcpy(header->name, text, i);
delete[] text;
i = f.readWord();
text = new mp_ubyte[i];
if (text == NULL)
return MP_OUT_OF_MEMORY;
f.read(text, 1, i);
if (i > 16) i = 16;
memcpy(header->sig, text, i);
delete[] text;
i = f.readWord();
f.seekWithBaseOffset(f.posWithBaseOffset() + i);
// convert header data
header->ordnum = (mp_uword)uniheader.SongLength;
header->restart = (mp_uword)uniheader.RepeatPos;
header->channum = (mp_uword)uniheader.NumChannels;
header->patnum = (mp_uword)uniheader.NumPatterns;
header->insnum = (mp_uword)uniheader.NumIns;
header->tempo = uniheader.InitSpeed;
header->speed = uniheader.InitTempo;
header->freqtab = (uniheader.Flags>>1)&1;
header->mainvol = 255;
mp_sint32 s = 0;
mp_sint32 e = 0;
for (i = 0; i < uniheader.NumIns; i++)
{
uniinstrument.NumSamps = f.readByte();
f.read(uniinstrument.SampleNums, 1, 96);
uniinstrument.volflg = f.readByte();
uniinstrument.volpts = f.readByte();
uniinstrument.volsus = f.readByte();
uniinstrument.volbeg = f.readByte();
uniinstrument.volend = f.readByte();
f.readWords((mp_uword*)uniinstrument.VolPoints, 12*2);
uniinstrument.panflg = f.readByte();
uniinstrument.panpts = f.readByte();
uniinstrument.pansus = f.readByte();
uniinstrument.panbeg = f.readByte();
uniinstrument.panend = f.readByte();
f.readWords((mp_uword*)uniinstrument.PanPoints, 12*2);
uniinstrument.vibtype = f.readByte();
uniinstrument.vibsweep = f.readByte();
uniinstrument.vibdepth = f.readByte();
uniinstrument.vibrate = f.readByte();
uniinstrument.volfade = f.readWord();
mp_sint32 len = f.readWord();
text = new mp_ubyte[len];
if (text == NULL)
return MP_OUT_OF_MEMORY;
f.read(text, 1, len);
if (len > 32) len = 32;
memcpy(instr[i].name, text, len);
delete[] text;
#ifdef VERBOSE
printf("%s\n",text);
#endif
// convert instrument data
instr[i].samp = uniinstrument.NumSamps;
for (j = 0; j < 96; j++)
instr[i].snum[j] = uniinstrument.SampleNums[j] + s;
//memcpy(instr[i].name, text, len);
// envelopes
TEnvelope venv;
TEnvelope penv;
memset(&venv,0,sizeof(venv));
memset(&penv,0,sizeof(penv));
mp_sint32 k;
for (k = 0; k < 12; k++)
{
venv.env[k][0] = uniinstrument.VolPoints[k*2];
venv.env[k][1] = uniinstrument.VolPoints[k*2+1];
}
for (k = 0; k < 12; k++)
{
penv.env[k][0] = uniinstrument.PanPoints[k*2];
penv.env[k][1] = uniinstrument.PanPoints[k*2+1];
}
venv.num = uniinstrument.volpts;
penv.num = uniinstrument.panpts;
venv.sustain = uniinstrument.volsus;
venv.loops = uniinstrument.volbeg;
venv.loope = uniinstrument.volend;
penv.sustain = uniinstrument.pansus;
penv.loops = uniinstrument.panbeg;
penv.loope = uniinstrument.panend;
venv.type = uniinstrument.volflg;
penv.type = uniinstrument.panflg;
if (!module->addVolumeEnvelope(venv))
return MP_OUT_OF_MEMORY;
if (!module->addPanningEnvelope(penv))
return MP_OUT_OF_MEMORY;
for (j = 0; j < uniinstrument.NumSamps; j++)
{
unisample.C2spd = f.readWord();
unisample.relnotenum = f.readByte();
unisample.volume = f.readByte();
unisample.panning = f.readByte();
unisample.smplength = f.readDword();
unisample.smploopstart = f.readDword();
unisample.smploopend = f.readDword();
unisample.flags = f.readWord();
mp_sint32 len = f.readWord();
text = new mp_ubyte[len];
if (text == NULL)
return MP_OUT_OF_MEMORY;
f.read(text, 1, len);
if (len > 32) len = 32;
memcpy(smp[s].name, text, len);
delete[] text;
// convert sample data
smp[s].vibtype = uniinstrument.vibtype;
smp[s].vibsweep = uniinstrument.vibsweep;
smp[s].vibdepth = uniinstrument.vibdepth << 1;
smp[s].vibrate = uniinstrument.vibrate;
smp[s].volfade = uniinstrument.volfade << 1;
smp[s].venvnum = e + 1;
smp[s].penvnum = e + 1;
if (uniVersion == 4)
{
if ((unisample.flags & 32) == 0) smp[s].flags |= 128; // no delta
if ((unisample.flags & 4) == 0) smp[s].flags |= 64; // usigned
}
else
{
if ((unisample.flags & 4) == 0) smp[s].flags |= 128; // no delta
if ((unisample.flags & 2) == 0) smp[s].flags |= 64; // unsigned
}
// 16 bit sample
/*if (unisample.flags & 1)
{
unisample.smplength <<= 1;
unisample.smploopstart <<= 1;
unisample.smploopend <<= 1;
}*/
//memcpy(smp[s].name, text, len);
smp[s].vol = XModule::vol64to255(unisample.volume);
smp[s].pan = unisample.panning;
smp[s].samplen = unisample.smplength;
smp[s].loopstart = unisample.smploopstart;
smp[s].looplen = unisample.smploopend - unisample.smploopstart;
smp[s].flags |= 3;
mp_ubyte type = 0;
if (uniVersion == 4)
{
type=0;
if ((unisample.flags & 8) == 8) type = 1;
if ((unisample.flags & 16) == 16) type = 2;
if ((unisample.flags & 1) == 1) type+=16;
}
else if (uniVersion == 5)
{
if (((unisample.flags>>4) & 3) == 0) type = 0;
if (((unisample.flags>>4) & 3) == 1) type = 1;
if (((unisample.flags>>4) & 3) == 3) type = 2;
if (unisample.flags&1) type+=16;
}
smp[s].type = type;
if (!(uniheader.Flags&1))
{
mp_sbyte rnn = 0;
mp_sbyte ft = 0;
switch (unisample.C2spd)
{
case 8280:
ft=-16;
break;
case 8232:
ft=-32;
break;
case 8169:
ft=-48;
break;
case 8107:
ft=-64;
break;
case 8046:
ft=-80;
break;
case 7985:
ft=-96;
break;
case 7941:
ft=-112;
break;
case 7895:
ft=-128;
break;
case 8363:
ft=0;
break;
case 8413:
ft=16;
break;
case 8463:
ft=32;
break;
case 8529:
ft=48;
break;
case 8581:
ft=64;
break;
case 8651:
ft=96;
break;
case 8723:
ft=112;
break;
case 8757:
ft=127;
break;
default:
XModule::convertc4spd(unisample.C2spd, &ft, &rnn);
break;
}
smp[s].relnote = rnn;
smp[s].finetune = ft;
}
else
{
smp[s].finetune = (mp_sbyte)(unisample.C2spd - 128);
smp[s].relnote = unisample.relnotenum;
}
s++;
}
e++;
}
header->smpnum = s;
mp_uword* patternRows = new mp_uword[uniheader.NumPatterns];
mp_uword* trackSeq = new mp_uword[uniheader.NumPatterns*uniheader.NumChannels];
f.readWords(patternRows, uniheader.NumPatterns);
f.readWords(trackSeq, uniheader.NumPatterns*uniheader.NumChannels);
mp_ubyte** tracks = new mp_ubyte*[uniheader.NumTracks];
for (i = 0; i < uniheader.NumTracks; i++)
{
mp_uint32 len = f.readWord();
tracks[i] = new mp_ubyte[len];
f.read(tracks[i], 1, len);
#ifdef VERBOSE
printf("Maximum number of effects in track %i: %i\n",i,getMaxEffectsFromTrack(tracks[i]));
#endif
}
MytrackSlot* deTrack = new MytrackSlot[256];
mp_sint32 trackIndex = 0;
for (i = 0; i < uniheader.NumPatterns; i++)
{
mp_sint32 maxEffects = 0;
for (j = 0; j < uniheader.NumChannels; j++)
{
#ifdef VERBOSE
printf("%i, ",trackSeq[trackIndex]);
#endif
if ((s=getMaxEffectsFromTrack(tracks[trackSeq[trackIndex]])) > maxEffects)
maxEffects = s;
trackIndex++;
}
trackIndex-=uniheader.NumChannels;
#ifdef VERBOSE
printf("Maxeffects for pattern %i: %i\n", i, maxEffects);
#endif
phead[i].rows = patternRows[i];
phead[i].effnum = maxEffects;
phead[i].channum = uniheader.NumChannels;
mp_sint32 slotSize = (phead[i].effnum * 2 + 2);
phead[i].patternData = new mp_ubyte[phead[i].rows*header->channum * slotSize];
// out of memory?
if (phead[i].patternData == NULL)
{
delete[] deTrack;
for (i = 0; i < uniheader.NumTracks; i++)
delete[] tracks[i];
delete[] tracks;
delete[] trackSeq;
delete[] patternRows;
return MP_OUT_OF_MEMORY;
}
memset(phead[i].patternData, 0, phead[i].rows*header->channum * slotSize);
mp_ubyte* pattern = phead[i].patternData;
for (mp_sint32 c = 0; c < uniheader.NumChannels; c++)
{
demuxTrack(tracks[trackSeq[trackIndex]], deTrack);
for (mp_sint32 rows = 0; rows < phead[i].rows; rows++)
{
mp_sint32 offset = (rows * slotSize*uniheader.NumChannels) + (slotSize * c);
pattern[offset++] = deTrack[rows].note;
pattern[offset++] = deTrack[rows].instrument;
for (mp_sint32 eff = 0; eff < phead[i].effnum; eff++)
{
pattern[offset++] = deTrack[rows].effects[eff];
pattern[offset++] = deTrack[rows].operands[eff];
#ifdef VERBOSE
if (c == 9 && i == 1 && eff == 1)
{
printf("%x, %x\n",deTrack[rows].effects[eff],deTrack[rows].operands[eff]);
}
#endif
}
}
trackIndex++;
}
}
delete[] deTrack;
for (i = 0; i < uniheader.NumTracks; i++)
delete[] tracks[i];
delete[] tracks;
delete[] trackSeq;
delete[] patternRows;
// lad ma samples du penner
for (i=0;i<header->smpnum;i++) {
#ifdef VERBOSE
printf("%i\n",smp[i].type);
#endif
//if (!smp[i].samplen)
// continue;
if (smp[i].type & 16)
smp[i].sample = (mp_sbyte*)module->allocSampleMem(smp[i].samplen<<1);
else
smp[i].sample = (mp_sbyte*)module->allocSampleMem(smp[i].samplen);
if (smp[i].sample == NULL)
{
return MP_OUT_OF_MEMORY;
}
mp_sint32 loadFlags = XModule::ST_DEFAULT;
if (smp[i].type & 16)
loadFlags |= XModule::ST_16BIT;
if (((smp[i].flags >> 7) & 1) == 0)
loadFlags |= XModule::ST_DELTA;
if (((smp[i].flags >> 6) & 1) == 1)
loadFlags |= XModule::ST_UNSIGNED;
// 16bit sample
if (smp[i].type & 16)
{
if (!module->loadSample(f,smp[i].sample,smp[i].samplen<<1,smp[i].samplen,loadFlags))
{
return MP_OUT_OF_MEMORY;
}
}
// 8bit sample
else
{
if (!module->loadSample(f,smp[i].sample,smp[i].samplen,smp[i].samplen,loadFlags))
{
return MP_OUT_OF_MEMORY;
}
}
}
header->volenvnum = module->numVEnvs;
header->panenvnum = module->numPEnvs;
strcpy(header->tracker,"..converted..");
module->setDefaultPanning();
module->postProcessSamples();
return MP_OK;
}