Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

load_ult.cpp

Go to the documentation of this file.
00001 /*
00002  * This program is  free software; you can redistribute it  and modify it
00003  * under the terms of the GNU  General Public License as published by the
00004  * Free Software Foundation; either version 2  of the license or (at your
00005  * option) any later version.
00006  *
00007  * Authors: Olivier Lapicque <olivierl@jps.net>
00008 */
00009 
00010 #include "stdafx.h"
00011 #include "sndfile.h"
00012 
00013 //#pragma warning(disable:4244)
00014 
00015 #define ULT_16BIT   0x04
00016 #define ULT_LOOP    0x08
00017 #define ULT_BIDI    0x10
00018 
00019 #pragma pack(1)
00020 
00021 // Raw ULT header struct:
00022 typedef struct tagULTHEADER
00023 {
00024         char id[15];             // changed from CHAR
00025         char songtitle[32];      // changed from CHAR
00026         BYTE reserved;
00027 } Q_PACKED ULTHEADER;
00028 
00029 
00030 // Raw ULT sampleinfo struct:
00031 typedef struct tagULTSAMPLE
00032 {
00033         CHAR samplename[32];
00034         CHAR dosname[12];
00035         LONG loopstart;
00036         LONG loopend;
00037         LONG sizestart;
00038         LONG sizeend;
00039         BYTE volume;
00040         BYTE flags;
00041         WORD finetune;
00042 } Q_PACKED ULTSAMPLE;
00043 
00044 #pragma pack()
00045 
00046 
00047 BOOL CSoundFile::ReadUlt(const BYTE *lpStream, DWORD dwMemLength)
00048 //---------------------------------------------------------------
00049 {
00050         ULTHEADER *pmh = (ULTHEADER *)lpStream;
00051         ULTSAMPLE *pus;
00052         UINT nos, nop;
00053         DWORD dwMemPos = 0;
00054 
00055         // try to read module header
00056         if ((!lpStream) || (dwMemLength < 0x100)) return FALSE;
00057         if (strncmp(pmh->id,"MAS_UTrack_V00",14)) return FALSE;
00058         // Warning! Not supported ULT format, trying anyway
00059         // if ((pmh->id[14] < '1') || (pmh->id[14] > '4')) return FALSE;
00060         m_nType = MOD_TYPE_ULT;
00061         m_nDefaultSpeed = 6;
00062         m_nDefaultTempo = 125;
00063         memcpy(m_szNames[0], pmh->songtitle, 32);
00064         // read songtext
00065         dwMemPos = sizeof(ULTHEADER);
00066         if ((pmh->reserved) && (dwMemPos + pmh->reserved * 32 < dwMemLength))
00067         {
00068                 UINT len = pmh->reserved * 32;
00069                 m_lpszSongComments = new char[len + 1 + pmh->reserved];
00070                 if (m_lpszSongComments)
00071                 {
00072                         for (UINT l=0; l<pmh->reserved; l++)
00073                         {
00074                                 memcpy(m_lpszSongComments+l*33, lpStream+dwMemPos+l*32, 32);
00075                                 m_lpszSongComments[l*33+32] = 0x0D;
00076                         }
00077                         m_lpszSongComments[len] = 0;
00078                 }
00079                 dwMemPos += len;
00080         }
00081         if (dwMemPos >= dwMemLength) return TRUE;
00082         nos = lpStream[dwMemPos++];
00083         m_nSamples = nos;
00084         if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1;
00085         UINT smpsize = 64;
00086         if (pmh->id[14] >= '4') smpsize += 2;
00087         if (dwMemPos + nos*smpsize + 256 + 2 > dwMemLength) return TRUE;
00088         for (UINT ins=1; ins<=nos; ins++, dwMemPos+=smpsize) if (ins<=m_nSamples)
00089         {
00090                 pus     = (ULTSAMPLE *)(lpStream+dwMemPos);
00091                 MODINSTRUMENT *pins = &Ins[ins];
00092                 memcpy(m_szNames[ins], pus->samplename, 32);
00093                 memcpy(pins->name, pus->dosname, 12);
00094                 pins->nLoopStart = pus->loopstart;
00095                 pins->nLoopEnd = pus->loopend;
00096                 pins->nLength = pus->sizeend - pus->sizestart;
00097                 pins->nVolume = pus->volume;
00098                 pins->nGlobalVol = 64;
00099                 pins->nC4Speed = 8363;
00100                 if (pmh->id[14] >= '4')
00101                 {
00102                         pins->nC4Speed = pus->finetune;
00103                 }
00104                 if (pus->flags & ULT_LOOP) pins->uFlags |= CHN_LOOP;
00105                 if (pus->flags & ULT_BIDI) pins->uFlags |= CHN_PINGPONGLOOP;
00106                 if (pus->flags & ULT_16BIT)
00107                 {
00108                         pins->uFlags |= CHN_16BIT;
00109                         pins->nLoopStart >>= 1;
00110                         pins->nLoopEnd >>= 1;
00111                 }
00112         }
00113         memcpy(Order, lpStream+dwMemPos, 256);
00114         dwMemPos += 256;
00115         m_nChannels = lpStream[dwMemPos] + 1;
00116         nop = lpStream[dwMemPos+1] + 1;
00117         dwMemPos += 2;
00118         if (m_nChannels > 32) m_nChannels = 32;
00119         // Default channel settings
00120         for (UINT nSet=0; nSet<m_nChannels; nSet++)
00121         {
00122                 ChnSettings[nSet].nVolume = 64;
00123                 ChnSettings[nSet].nPan = (nSet & 1) ? 0x40 : 0xC0;
00124         }
00125         // read pan position table for v1.5 and higher
00126         if(pmh->id[14]>='3')
00127         {
00128                 if (dwMemPos + m_nChannels > dwMemLength) return TRUE;
00129                 for(UINT t=0; t<m_nChannels; t++)
00130                 {
00131                         ChnSettings[t].nPan = (lpStream[dwMemPos++] << 4) + 8;
00132                         if (ChnSettings[t].nPan > 256) ChnSettings[t].nPan = 256;
00133                 }
00134         }
00135         // Allocating Patterns
00136         for (UINT nAllocPat=0; nAllocPat<nop; nAllocPat++)
00137         {
00138                 if (nAllocPat < MAX_PATTERNS)
00139                 {
00140                         PatternSize[nAllocPat] = 64;
00141                         Patterns[nAllocPat] = AllocatePattern(64, m_nChannels);
00142                 }
00143         }
00144         // Reading Patterns
00145         for (UINT nChn=0; nChn<m_nChannels; nChn++)
00146         {
00147                 for (UINT nPat=0; nPat<nop; nPat++)
00148                 {
00149                         MODCOMMAND *pat = NULL;
00150                         
00151                         if (nPat < MAX_PATTERNS)
00152                         {
00153                                 pat = Patterns[nPat];
00154                                 if (pat) pat += nChn;
00155                         }
00156                         UINT row = 0;
00157                         while (row < 64)
00158                         {
00159                                 if (dwMemPos + 6 > dwMemLength) return TRUE;
00160                                 UINT rep = 1;
00161                                 UINT note = lpStream[dwMemPos++];
00162                                 if (note == 0xFC)
00163                                 {
00164                                         rep = lpStream[dwMemPos];
00165                                         note = lpStream[dwMemPos+1];
00166                                         dwMemPos += 2;
00167                                 }
00168                                 UINT instr = lpStream[dwMemPos++];
00169                                 UINT eff = lpStream[dwMemPos++];
00170                                 UINT dat1 = lpStream[dwMemPos++];
00171                                 UINT dat2 = lpStream[dwMemPos++];
00172                                 UINT cmd1 = eff & 0x0F;
00173                                 UINT cmd2 = eff >> 4;
00174                                 if (cmd1 == 0x0C) dat1 >>= 2; else
00175                                 if (cmd1 == 0x0B) { cmd1 = dat1 = 0; }
00176                                 if (cmd2 == 0x0C) dat2 >>= 2; else
00177                                 if (cmd2 == 0x0B) { cmd2 = dat2 = 0; }
00178                                 while ((rep != 0) && (row < 64))
00179                                 {
00180                                         if (pat)
00181                                         {
00182                                                 pat->instr = instr;
00183                                                 if (note) pat->note = note + 36;
00184                                                 if (cmd1 | dat1)
00185                                                 {
00186                                                         if (cmd1 == 0x0C)
00187                                                         {
00188                                                                 pat->volcmd = VOLCMD_VOLUME;
00189                                                                 pat->vol = dat1;
00190                                                         } else
00191                                                         {
00192                                                                 pat->command = cmd1;
00193                                                                 pat->param = dat1;
00194                                                                 ConvertModCommand(pat);
00195                                                         }
00196                                                 }
00197                                                 if (cmd2 == 0x0C)
00198                                                 {
00199                                                         pat->volcmd = VOLCMD_VOLUME;
00200                                                         pat->vol = dat2;
00201                                                 } else
00202                                                 if ((cmd2 | dat2) && (!pat->command))
00203                                                 {
00204                                                         pat->command = cmd2;
00205                                                         pat->param = dat2;
00206                                                         ConvertModCommand(pat);
00207                                                 }
00208                                                 pat += m_nChannels;
00209                                         }
00210                                         row++;
00211                                         rep--;
00212                                 }
00213                         }
00214                 }
00215         }
00216         // Reading Instruments
00217         for (UINT smp=1; smp<=m_nSamples; smp++) if (Ins[smp].nLength)
00218         {
00219                 if (dwMemPos >= dwMemLength) return TRUE;
00220                 UINT flags = (Ins[smp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S;
00221                 dwMemPos += ReadSample(&Ins[smp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength - dwMemPos);
00222         }
00223         return TRUE;
00224 }
00225 

Generated on Sat Nov 5 16:15:40 2005 for OPIE by  doxygen 1.4.2