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

load_dsm.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 
00011 // DSIK Internal Format (DSM) module loader //
00013 #include "stdafx.h"
00014 #include "sndfile.h"
00015 
00016 #pragma pack(1)
00017 
00018 #define DSMID_RIFF      0x46464952      // "RIFF"
00019 #define DSMID_DSMF      0x464d5344      // "DSMF"
00020 #define DSMID_SONG      0x474e4f53      // "SONG"
00021 #define DSMID_INST      0x54534e49      // "INST"
00022 #define DSMID_PATT      0x54544150      // "PATT"
00023 
00024 
00025 typedef struct DSMNOTE
00026 {
00027         BYTE note,ins,vol,cmd,inf;
00028 } Q_PACKED DSMNOTE;
00029 
00030 
00031 typedef struct DSMINST
00032 {
00033         DWORD id_INST;
00034         DWORD inst_len;
00035         CHAR filename[13];
00036         BYTE flags;
00037         BYTE flags2;
00038         BYTE volume;
00039         DWORD length;
00040         DWORD loopstart;
00041         DWORD loopend;
00042         DWORD reserved1;
00043         WORD c2spd;
00044         WORD reserved2;
00045         CHAR samplename[28];
00046 } Q_PACKED DSMINST;
00047 
00048 
00049 typedef struct DSMFILEHEADER
00050 {
00051         DWORD id_RIFF;  // "RIFF"
00052         DWORD riff_len;
00053         DWORD id_DSMF;  // "DSMF"
00054         DWORD id_SONG;  // "SONG"
00055         DWORD song_len;
00056 } Q_PACKED DSMFILEHEADER;
00057 
00058 
00059 typedef struct DSMSONG
00060 {
00061         CHAR songname[28];
00062         WORD reserved1;
00063         WORD flags;
00064         DWORD reserved2;
00065         WORD numord;
00066         WORD numsmp;
00067         WORD numpat;
00068         WORD numtrk;
00069         BYTE globalvol;
00070         BYTE mastervol;
00071         BYTE speed;
00072         BYTE bpm;
00073         BYTE panpos[16];
00074         BYTE orders[128];
00075 } Q_PACKED DSMSONG;
00076 
00077 typedef struct DSMPATT
00078 {
00079         DWORD id_PATT;
00080         DWORD patt_len;
00081         BYTE dummy1;
00082         BYTE dummy2;
00083 } Q_PACKED DSMPATT;
00084 
00085 #pragma pack()
00086 
00087 
00088 BOOL CSoundFile::ReadDSM(LPCBYTE lpStream, DWORD dwMemLength)
00089 //-----------------------------------------------------------
00090 {
00091         DSMFILEHEADER *pfh = (DSMFILEHEADER *)lpStream;
00092         DSMSONG *psong;
00093         DWORD dwMemPos;
00094         UINT nPat, nSmp;
00095 
00096         if ((!lpStream) || (dwMemLength < 1024) || (pfh->id_RIFF != DSMID_RIFF)
00097          || (pfh->riff_len + 8 > dwMemLength) || (pfh->riff_len < 1024)
00098          || (pfh->id_DSMF != DSMID_DSMF) || (pfh->id_SONG != DSMID_SONG)
00099          || (pfh->song_len > dwMemLength)) return FALSE;
00100         psong = (DSMSONG *)(lpStream + sizeof(DSMFILEHEADER));
00101         dwMemPos = sizeof(DSMFILEHEADER) + pfh->song_len;
00102         m_nType = MOD_TYPE_DSM;
00103         m_nChannels = psong->numtrk;
00104         if (m_nChannels < 4) m_nChannels = 4;
00105         if (m_nChannels > 16) m_nChannels = 16;
00106         m_nSamples = psong->numsmp;
00107         if (m_nSamples > MAX_SAMPLES) m_nSamples = MAX_SAMPLES;
00108         m_nDefaultSpeed = psong->speed;
00109         m_nDefaultTempo = psong->bpm;
00110         m_nDefaultGlobalVolume = psong->globalvol << 2;
00111         if ((!m_nDefaultGlobalVolume) || (m_nDefaultGlobalVolume > 256)) m_nDefaultGlobalVolume = 256;
00112         m_nSongPreAmp = psong->mastervol & 0x7F;
00113         for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++)
00114         {
00115                 Order[iOrd] = (BYTE)((iOrd < psong->numord) ? psong->orders[iOrd] : 0xFF);
00116         }
00117         for (UINT iPan=0; iPan<16; iPan++)
00118         {
00119                 ChnSettings[iPan].nPan = 0x80;
00120                 if (psong->panpos[iPan] <= 0x80)
00121                 {
00122                         ChnSettings[iPan].nPan = psong->panpos[iPan] << 1;
00123                 }
00124         }
00125         memcpy(m_szNames[0], psong->songname, 28);
00126         nPat = 0;
00127         nSmp = 1;
00128         while (dwMemPos < dwMemLength - 8)
00129         {
00130                 DSMPATT *ppatt = (DSMPATT *)(lpStream + dwMemPos);
00131                 DSMINST *pins = (DSMINST *)(lpStream+dwMemPos);
00132                 // Reading Patterns
00133                 if (ppatt->id_PATT == DSMID_PATT)
00134                 {
00135                         dwMemPos += 8;
00136                         if (dwMemPos + ppatt->patt_len >= dwMemLength) break;
00137                         DWORD dwPos = dwMemPos;
00138                         dwMemPos += ppatt->patt_len;
00139                         MODCOMMAND *m = AllocatePattern(64, m_nChannels);
00140                         if (!m) break;
00141                         PatternSize[nPat] = 64;
00142                         Patterns[nPat] = m;
00143                         UINT row = 0;
00144                         while ((row < 64) && (dwPos + 2 <= dwMemPos))
00145                         {
00146                                 UINT flag = lpStream[dwPos++];
00147                                 if (flag)
00148                                 {
00149                                         UINT ch = (flag & 0x0F) % m_nChannels;
00150                                         if (flag & 0x80)
00151                                         {
00152                                                 UINT note = lpStream[dwPos++];
00153                                                 if (note)
00154                                                 {
00155                                                         if (note <= 12*9) note += 12;
00156                                                         m[ch].note = (BYTE)note;
00157                                                 }
00158                                         }
00159                                         if (flag & 0x40)
00160                                         {
00161                                                 m[ch].instr = lpStream[dwPos++];
00162                                         }
00163                                         if (flag & 0x20)
00164                                         {
00165                                                 m[ch].volcmd = VOLCMD_VOLUME;
00166                                                 m[ch].vol = lpStream[dwPos++];
00167                                         }
00168                                         if (flag & 0x10)
00169                                         {
00170                                                 UINT command = lpStream[dwPos++];
00171                                                 UINT param = lpStream[dwPos++];
00172                                                 switch(command)
00173                                                 {
00174                                                 // 4-bit Panning
00175                                                 case 0x08:
00176                                                         switch(param & 0xF0)
00177                                                         {
00178                                                         case 0x00: param <<= 4; break;
00179                                                         case 0x10: command = 0x0A; param = (param & 0x0F) << 4; break;
00180                                                         case 0x20: command = 0x0E; param = (param & 0x0F) | 0xA0; break;
00181                                                         case 0x30: command = 0x0E; param = (param & 0x0F) | 0x10; break;
00182                                                         case 0x40: command = 0x0E; param = (param & 0x0F) | 0x20; break;
00183                                                         default: command = 0;
00184                                                         }
00185                                                         break;
00186                                                 // Portamentos
00187                                                 case 0x11:
00188                                                 case 0x12:
00189                                                         command &= 0x0F;
00190                                                         break;
00191                                                 // 3D Sound (?)
00192                                                 case 0x13:
00193                                                         command = 'X' - 55;
00194                                                         param = 0x91;
00195                                                         break;
00196                                                 default:
00197                                                         // Volume + Offset (?)
00198                                                         command = ((command & 0xF0) == 0x20) ? 0x09 : 0;
00199                                                 }
00200                                                 m[ch].command = (BYTE)command;
00201                                                 m[ch].param = (BYTE)param;
00202                                                 if (command) ConvertModCommand(&m[ch]);
00203                                         }
00204                                 } else
00205                                 {
00206                                         m += m_nChannels;
00207                                         row++;
00208                                 }
00209                         }
00210                         nPat++;
00211                 } else
00212                 // Reading Samples
00213                 if ((nSmp <= m_nSamples) && (pins->id_INST == DSMID_INST))
00214                 {
00215                         if (dwMemPos + pins->inst_len >= dwMemLength - 8) break;
00216                         DWORD dwPos = dwMemPos + sizeof(DSMINST);
00217                         dwMemPos += 8 + pins->inst_len;
00218                         memcpy(m_szNames[nSmp], pins->samplename, 28);
00219                         MODINSTRUMENT *psmp = &Ins[nSmp];
00220                         memcpy(psmp->name, pins->filename, 13);
00221                         psmp->nGlobalVol = 64;
00222                         psmp->nC4Speed = pins->c2spd;
00223                         psmp->uFlags = (WORD)((pins->flags & 1) ? CHN_LOOP : 0);
00224                         psmp->nLength = pins->length;
00225                         psmp->nLoopStart = pins->loopstart;
00226                         psmp->nLoopEnd = pins->loopend;
00227                         psmp->nVolume = (WORD)(pins->volume << 2);
00228                         if (psmp->nVolume > 256) psmp->nVolume = 256;
00229                         UINT smptype = (pins->flags & 2) ? RS_PCM8S : RS_PCM8U;
00230                         ReadSample(psmp, smptype, (LPCSTR)(lpStream+dwPos), dwMemLength - dwPos);
00231                         nSmp++;
00232                 } else
00233                 {
00234                         break;
00235                 }
00236         }
00237         return TRUE;
00238 }
00239 

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