00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
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;
00052 DWORD riff_len;
00053 DWORD id_DSMF;
00054 DWORD id_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
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
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
00187 case 0x11:
00188 case 0x12:
00189 command &= 0x0F;
00190 break;
00191
00192 case 0x13:
00193 command = 'X' - 55;
00194 param = 0x91;
00195 break;
00196 default:
00197
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
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