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

load_ams.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 // AMS module loader                        //
00013 #include "stdafx.h"
00014 #include "sndfile.h"
00015 
00016 //#pragma warning(disable:4244)
00017 
00018 #pragma pack(1)
00019 
00020 typedef struct AMSFILEHEADER
00021 {
00022         char szHeader[7];       // "Extreme"   // changed from CHAR
00023         BYTE verlo, verhi;      // 0x??,0x01
00024         BYTE chncfg;
00025         BYTE samples;
00026         WORD patterns;
00027         WORD orders;
00028         BYTE vmidi;
00029         WORD extra;
00030 } Q_PACKED AMSFILEHEADER;
00031 
00032 typedef struct AMSSAMPLEHEADER
00033 {
00034         DWORD length;
00035         DWORD loopstart;
00036         DWORD loopend;
00037         BYTE finetune_and_pan;
00038         WORD samplerate;        // C-2 = 8363
00039         BYTE volume;            // 0-127
00040         BYTE infobyte;
00041 } Q_PACKED AMSSAMPLEHEADER;
00042 
00043 
00044 #pragma pack()
00045 
00046 
00047 
00048 BOOL CSoundFile::ReadAMS(LPCBYTE lpStream, DWORD dwMemLength)
00049 //-----------------------------------------------------------
00050 {
00051         BYTE pkinf[MAX_SAMPLES];
00052         AMSFILEHEADER *pfh = (AMSFILEHEADER *)lpStream;
00053         DWORD dwMemPos;
00054         UINT tmp, tmp2;
00055         
00056         if ((!lpStream) || (dwMemLength < 1024)) return FALSE;
00057         if ((pfh->verhi != 0x01) || (strncmp(pfh->szHeader, "Extreme", 7))
00058          || (!pfh->patterns) || (!pfh->orders) || (!pfh->samples) || (pfh->samples > MAX_SAMPLES)
00059          || (pfh->patterns > MAX_PATTERNS) || (pfh->orders > MAX_ORDERS))
00060         {
00061                 return ReadAMS2(lpStream, dwMemLength);
00062         }
00063         dwMemPos = sizeof(AMSFILEHEADER) + pfh->extra;
00064         if (dwMemPos + pfh->samples * sizeof(AMSSAMPLEHEADER) + 256 >= dwMemLength) return FALSE;
00065         m_nType = MOD_TYPE_AMS;
00066         m_nInstruments = 0;
00067         m_nChannels = (pfh->chncfg & 0x1F) + 1;
00068         m_nSamples = pfh->samples;
00069         for (UINT nSmp=1; nSmp<=m_nSamples; nSmp++, dwMemPos += sizeof(AMSSAMPLEHEADER))
00070         {
00071                 AMSSAMPLEHEADER *psh = (AMSSAMPLEHEADER *)(lpStream + dwMemPos);
00072                 MODINSTRUMENT *pins = &Ins[nSmp];
00073                 pins->nLength = psh->length;
00074                 pins->nLoopStart = psh->loopstart;
00075                 pins->nLoopEnd = psh->loopend;
00076                 pins->nGlobalVol = 64;
00077                 pins->nVolume = psh->volume << 1;
00078                 pins->nC4Speed = psh->samplerate;
00079                 pins->nPan = (psh->finetune_and_pan & 0xF0);
00080                 if (pins->nPan < 0x80) pins->nPan += 0x10;
00081                 pins->nFineTune = MOD2XMFineTune(psh->finetune_and_pan & 0x0F);
00082                 pins->uFlags = (psh->infobyte & 0x80) ? CHN_16BIT : 0;
00083                 if ((pins->nLoopEnd <= pins->nLength) && (pins->nLoopStart+4 <= pins->nLoopEnd)) pins->uFlags |= CHN_LOOP;
00084                 pkinf[nSmp] = psh->infobyte;
00085         }
00086         // Read Song Name
00087         tmp = lpStream[dwMemPos++];
00088         if (dwMemPos + tmp + 1 >= dwMemLength) return TRUE;
00089         tmp2 = (tmp < 32) ? tmp : 31;
00090         if (tmp2) memcpy(m_szNames[0], lpStream+dwMemPos, tmp2);
00091         m_szNames[0][tmp2] = 0;
00092         dwMemPos += tmp;
00093         // Read sample names
00094         for (UINT sNam=1; sNam<=m_nSamples; sNam++)
00095         {
00096                 if (dwMemPos + 32 >= dwMemLength) return TRUE;
00097                 tmp = lpStream[dwMemPos++];
00098                 tmp2 = (tmp < 32) ? tmp : 31;
00099                 if (tmp2) memcpy(m_szNames[sNam], lpStream+dwMemPos, tmp2);
00100                 dwMemPos += tmp;
00101         }
00102         // Skip Channel names
00103         for (UINT cNam=0; cNam<m_nChannels; cNam++)
00104         {
00105                 if (dwMemPos + 32 >= dwMemLength) return TRUE;
00106                 tmp = lpStream[dwMemPos++];
00107                 dwMemPos += tmp;
00108         }
00109         // Read Pattern Names
00110         m_lpszPatternNames = new char[pfh->patterns * 32];  // changed from CHAR
00111         if (!m_lpszPatternNames) return TRUE;
00112         m_nPatternNames = pfh->patterns;
00113         memset(m_lpszPatternNames, 0, m_nPatternNames * 32);
00114         for (UINT pNam=0; pNam < m_nPatternNames; pNam++)
00115         {
00116                 if (dwMemPos + 32 >= dwMemLength) return TRUE;
00117                 tmp = lpStream[dwMemPos++];
00118                 tmp2 = (tmp < 32) ? tmp : 31;
00119                 if (tmp2) memcpy(m_lpszPatternNames+pNam*32, lpStream+dwMemPos, tmp2);
00120                 dwMemPos += tmp;
00121         }
00122         // Read Song Comments
00123         tmp = *((WORD *)(lpStream+dwMemPos));
00124         dwMemPos += 2;
00125         if (dwMemPos + tmp >= dwMemLength) return TRUE;
00126         if (tmp)
00127         {
00128                 m_lpszSongComments = new char[tmp+1];  // changed from CHAR
00129                 if (!m_lpszSongComments) return TRUE;
00130                 memset(m_lpszSongComments, 0, tmp+1);
00131                 memcpy(m_lpszSongComments, lpStream + dwMemPos, tmp);
00132                 dwMemPos += tmp;
00133         }
00134         // Read Order List
00135         for (UINT iOrd=0; iOrd<pfh->orders; iOrd++, dwMemPos += 2)
00136         {
00137                 UINT n = *((WORD *)(lpStream+dwMemPos));
00138                 Order[iOrd] = (BYTE)n;
00139         }
00140         // Read Patterns
00141         for (UINT iPat=0; iPat<pfh->patterns; iPat++)
00142         {
00143                 if (dwMemPos + 4 >= dwMemLength) return TRUE;
00144                 UINT len = *((DWORD *)(lpStream + dwMemPos));
00145                 dwMemPos += 4;
00146                 if ((len >= dwMemLength) || (dwMemPos + len > dwMemLength)) return TRUE;
00147                 PatternSize[iPat] = 64;
00148                 MODCOMMAND *m = AllocatePattern(PatternSize[iPat], m_nChannels);
00149                 if (!m) return TRUE;
00150                 Patterns[iPat] = m;
00151                 const BYTE *p = lpStream + dwMemPos;
00152                 UINT row = 0, i = 0;
00153                 while ((row < PatternSize[iPat]) && (i+2 < len))
00154                 {
00155                         BYTE b0 = p[i++];
00156                         BYTE b1 = p[i++];
00157                         BYTE b2 = 0;
00158                         UINT ch = b0 & 0x3F;
00159                         // Note+Instr
00160                         if (!(b0 & 0x40))
00161                         {
00162                                 b2 = p[i++];
00163                                 if (ch < m_nChannels)
00164                                 {
00165                                         if (b1 & 0x7F) m[ch].note = (b1 & 0x7F) + 25;
00166                                         m[ch].instr = b2;
00167                                 }
00168                                 if (b1 & 0x80)
00169                                 {
00170                                         b0 |= 0x40;
00171                                         b1 = p[i++];
00172                                 }
00173                         }
00174                         // Effect
00175                         if (b0 & 0x40)
00176                         {
00177                         anothercommand:
00178                                 if (b1 & 0x40)
00179                                 {
00180                                         if (ch < m_nChannels)
00181                                         {
00182                                                 m[ch].volcmd = VOLCMD_VOLUME;
00183                                                 m[ch].vol = b1 & 0x3F;
00184                                         }
00185                                 } else
00186                                 {
00187                                         b2 = p[i++];
00188                                         if (ch < m_nChannels)
00189                                         {
00190                                                 UINT cmd = b1 & 0x3F;
00191                                                 if (cmd == 0x0C)
00192                                                 {
00193                                                         m[ch].volcmd = VOLCMD_VOLUME;
00194                                                         m[ch].vol = b2 >> 1;
00195                                                 } else
00196                                                 if (cmd == 0x0E)
00197                                                 {
00198                                                         if (!m[ch].command)
00199                                                         {
00200                                                                 UINT command = CMD_S3MCMDEX;
00201                                                                 UINT param = b2;
00202                                                                 switch(param & 0xF0)
00203                                                                 {
00204                                                                 case 0x00:      if (param & 0x08) { param &= 0x07; param |= 0x90; } else {command=param=0;} break;
00205                                                                 case 0x10:      command = CMD_PORTAMENTOUP; param |= 0xF0; break;
00206                                                                 case 0x20:      command = CMD_PORTAMENTODOWN; param |= 0xF0; break;
00207                                                                 case 0x30:      param = (param & 0x0F) | 0x10; break;
00208                                                                 case 0x40:      param = (param & 0x0F) | 0x30; break;
00209                                                                 case 0x50:      param = (param & 0x0F) | 0x20; break;
00210                                                                 case 0x60:      param = (param & 0x0F) | 0xB0; break;
00211                                                                 case 0x70:      param = (param & 0x0F) | 0x40; break;
00212                                                                 case 0x90:      command = CMD_RETRIG; param &= 0x0F; break;
00213                                                                 case 0xA0:      if (param & 0x0F) { command = CMD_VOLUMESLIDE; param = (param << 4) | 0x0F; } else command=param=0; break;
00214                                                                 case 0xB0:      if (param & 0x0F) { command = CMD_VOLUMESLIDE; param |= 0xF0; } else command=param=0; break;
00215                                                                 }
00216                                                                 m[ch].command = command;
00217                                                                 m[ch].param = param;
00218                                                         }
00219                                                 } else
00220                                                 {
00221                                                         m[ch].command = cmd;
00222                                                         m[ch].param = b2;
00223                                                         ConvertModCommand(&m[ch]);
00224                                                 }
00225                                         }
00226                                 }
00227                                 if (b1 & 0x80)
00228                                 {
00229                                         b1 = p[i++];
00230                                         if (i <= len) goto anothercommand;
00231                                 }
00232                         }
00233                         if (b0 & 0x80)
00234                         {
00235                                 row++;
00236                                 m += m_nChannels;
00237                         }
00238                 }
00239                 dwMemPos += len;
00240         }
00241         // Read Samples
00242         for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) if (Ins[iSmp].nLength)
00243         {
00244                 if (dwMemPos >= dwMemLength - 9) return TRUE;
00245                 UINT flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_AMS16 : RS_AMS8;
00246                 dwMemPos += ReadSample(&Ins[iSmp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos);
00247         }
00248         return TRUE;
00249 }
00250 
00251 
00253 // AMS 2.2 loader
00254 
00255 #pragma pack(1)
00256 
00257 typedef struct AMS2FILEHEADER
00258 {
00259         DWORD dwHdr1;           // AMShdr
00260         WORD wHdr2;
00261         BYTE b1A;                       // 0x1A
00262         BYTE titlelen;          // 30-bytes max
00263         CHAR szTitle[30];       // [titlelen]
00264 } Q_PACKED AMS2FILEHEADER;
00265 
00266 typedef struct AMS2SONGHEADER
00267 {
00268         WORD version;
00269         BYTE instruments;
00270         WORD patterns;
00271         WORD orders;
00272         WORD bpm;
00273         BYTE speed;
00274         BYTE channels;
00275         BYTE commands;
00276         BYTE rows;
00277         WORD flags;
00278 } Q_PACKED AMS2SONGHEADER;
00279 
00280 typedef struct AMS2INSTRUMENT
00281 {
00282         BYTE samples;
00283         BYTE notemap[120];
00284 } Q_PACKED AMS2INSTRUMENT;
00285 
00286 typedef struct AMS2ENVELOPE
00287 {
00288         BYTE speed;
00289         BYTE sustain;
00290         BYTE loopbegin;
00291         BYTE loopend;
00292         BYTE points;
00293         BYTE info[3];
00294 } Q_PACKED AMS2ENVELOPE;
00295 
00296 typedef struct AMS2SAMPLE
00297 {
00298         DWORD length;
00299         DWORD loopstart;
00300         DWORD loopend;
00301         WORD frequency;
00302         BYTE finetune;
00303         WORD c4speed;
00304         CHAR transpose;
00305         BYTE volume;
00306         BYTE flags;
00307 } Q_PACKED AMS2SAMPLE;
00308 
00309 
00310 #pragma pack()
00311 
00312 
00313 BOOL CSoundFile::ReadAMS2(LPCBYTE lpStream, DWORD dwMemLength)
00314 //------------------------------------------------------------
00315 {
00316         AMS2FILEHEADER *pfh = (AMS2FILEHEADER *)lpStream;
00317         AMS2SONGHEADER *psh;
00318         DWORD dwMemPos;
00319         BYTE smpmap[16];
00320         BYTE packedsamples[MAX_SAMPLES];
00321 
00322         if ((pfh->dwHdr1 != 0x68534D41) || (pfh->wHdr2 != 0x7264)
00323          || (pfh->b1A != 0x1A) || (pfh->titlelen > 30)) return FALSE;
00324         dwMemPos = pfh->titlelen + 8;
00325         psh = (AMS2SONGHEADER *)(lpStream + dwMemPos);
00326         if (((psh->version & 0xFF00) != 0x0200) || (!psh->instruments)
00327          || (psh->instruments > MAX_INSTRUMENTS) || (!psh->patterns) || (!psh->orders)) return FALSE;
00328         dwMemPos += sizeof(AMS2SONGHEADER);
00329         if (pfh->titlelen)
00330         {
00331                 memcpy(m_szNames, pfh->szTitle, pfh->titlelen);
00332                 m_szNames[0][pfh->titlelen] = 0;
00333         }
00334         m_nType = MOD_TYPE_AMS;
00335         m_nChannels = 32;
00336         m_nDefaultTempo = psh->bpm >> 8;
00337         m_nDefaultSpeed = psh->speed;
00338         m_nInstruments = psh->instruments;
00339         m_nSamples = 0;
00340         if (psh->flags & 0x40) m_dwSongFlags |= SONG_LINEARSLIDES;
00341         for (UINT nIns=1; nIns<=m_nInstruments; nIns++)
00342         {
00343                 UINT insnamelen = lpStream[dwMemPos];
00344                 CHAR *pinsname = (CHAR *)(lpStream+dwMemPos+1);
00345                 dwMemPos += insnamelen + 1;
00346                 AMS2INSTRUMENT *pins = (AMS2INSTRUMENT *)(lpStream + dwMemPos);
00347                 dwMemPos += sizeof(AMS2INSTRUMENT);
00348                 if (dwMemPos + 1024 >= dwMemLength) return TRUE;
00349                 AMS2ENVELOPE *volenv, *panenv, *pitchenv;
00350                 volenv = (AMS2ENVELOPE *)(lpStream+dwMemPos);
00351                 dwMemPos += 5 + volenv->points*3;
00352                 panenv = (AMS2ENVELOPE *)(lpStream+dwMemPos);
00353                 dwMemPos += 5 + panenv->points*3;
00354                 pitchenv = (AMS2ENVELOPE *)(lpStream+dwMemPos);
00355                 dwMemPos += 5 + pitchenv->points*3;
00356                 INSTRUMENTHEADER *penv = new INSTRUMENTHEADER;
00357                 if (!penv) return TRUE;
00358                 memset(smpmap, 0, sizeof(smpmap));
00359                 memset(penv, 0, sizeof(INSTRUMENTHEADER));
00360                 for (UINT ismpmap=0; ismpmap<pins->samples; ismpmap++)
00361                 {
00362                         if ((ismpmap >= 16) || (m_nSamples+1 >= MAX_SAMPLES)) break;
00363                         m_nSamples++;
00364                         smpmap[ismpmap] = m_nSamples;
00365                 }
00366                 penv->nGlobalVol = 64;
00367                 penv->nPan = 128;
00368                 penv->nPPC = 60;
00369                 Headers[nIns] = penv;
00370                 if (insnamelen)
00371                 {
00372                         if (insnamelen > 31) insnamelen = 31;
00373                         memcpy(penv->name, pinsname, insnamelen);
00374                         penv->name[insnamelen] = 0;
00375                 }
00376                 for (UINT inotemap=0; inotemap<120; inotemap++)
00377                 {
00378                         penv->NoteMap[inotemap] = inotemap+1;
00379                         penv->Keyboard[inotemap] = smpmap[pins->notemap[inotemap] & 0x0F];
00380                 }
00381                 // Volume Envelope
00382                 {
00383                         UINT pos = 0;
00384                         penv->nVolEnv = (volenv->points > 16) ? 16 : volenv->points;
00385                         penv->nVolSustainBegin = penv->nVolSustainEnd = volenv->sustain;
00386                         penv->nVolLoopStart = volenv->loopbegin;
00387                         penv->nVolLoopEnd = volenv->loopend;
00388                         for (UINT i=0; i<penv->nVolEnv; i++)
00389                         {
00390                                 penv->VolEnv[i] = (BYTE)((volenv->info[i*3+2] & 0x7F) >> 1);
00391                                 pos += volenv->info[i*3] + ((volenv->info[i*3+1] & 1) << 8);
00392                                 penv->VolPoints[i] = (WORD)pos;
00393                         }
00394                 }
00395                 penv->nFadeOut = (((lpStream[dwMemPos+2] & 0x0F) << 8) | (lpStream[dwMemPos+1])) << 3;
00396                 UINT envflags = lpStream[dwMemPos+3];
00397                 if (envflags & 0x01) penv->dwFlags |= ENV_VOLLOOP;
00398                 if (envflags & 0x02) penv->dwFlags |= ENV_VOLSUSTAIN;
00399                 if (envflags & 0x04) penv->dwFlags |= ENV_VOLUME;
00400                 dwMemPos += 5;
00401                 // Read Samples
00402                 for (UINT ismp=0; ismp<pins->samples; ismp++)
00403                 {
00404                         MODINSTRUMENT *psmp = ((ismp < 16) && (smpmap[ismp])) ? &Ins[smpmap[ismp]] : NULL;
00405                         UINT smpnamelen = lpStream[dwMemPos];
00406                         if ((psmp) && (smpnamelen) && (smpnamelen <= 22))
00407                         {
00408                                 memcpy(m_szNames[smpmap[ismp]], lpStream+dwMemPos+1, smpnamelen);
00409                         }
00410                         dwMemPos += smpnamelen + 1;
00411                         if (psmp)
00412                         {
00413                                 AMS2SAMPLE *pams = (AMS2SAMPLE *)(lpStream+dwMemPos);
00414                                 psmp->nGlobalVol = 64;
00415                                 psmp->nPan = 128;
00416                                 psmp->nLength = pams->length;
00417                                 psmp->nLoopStart = pams->loopstart;
00418                                 psmp->nLoopEnd = pams->loopend;
00419                                 psmp->nC4Speed = pams->c4speed;
00420                                 psmp->RelativeTone = pams->transpose;
00421                                 psmp->nVolume = pams->volume / 2;
00422                                 packedsamples[smpmap[ismp]] = pams->flags;
00423                                 if (pams->flags & 0x04) psmp->uFlags |= CHN_16BIT;
00424                                 if (pams->flags & 0x08) psmp->uFlags |= CHN_LOOP;
00425                                 if (pams->flags & 0x10) psmp->uFlags |= CHN_PINGPONGLOOP;
00426                         }
00427                         dwMemPos += sizeof(AMS2SAMPLE);
00428                 }
00429         }
00430         if (dwMemPos + 256 >= dwMemLength) return TRUE;
00431         // Comments
00432         {
00433                 UINT composernamelen = lpStream[dwMemPos];
00434                 if (composernamelen)
00435                 {
00436                         m_lpszSongComments = new char[composernamelen+1]; // changed from CHAR
00437                         if (m_lpszSongComments)
00438                         {
00439                                 memcpy(m_lpszSongComments, lpStream+dwMemPos+1, composernamelen);
00440                                 m_lpszSongComments[composernamelen] = 0;
00441                         }
00442                 }
00443                 dwMemPos += composernamelen + 1;
00444                 // channel names
00445                 for (UINT i=0; i<32; i++)
00446                 {
00447                         UINT chnnamlen = lpStream[dwMemPos];
00448                         if ((chnnamlen) && (chnnamlen < MAX_CHANNELNAME))
00449                         {
00450                                 memcpy(ChnSettings[i].szName, lpStream+dwMemPos+1, chnnamlen);
00451                         }
00452                         dwMemPos += chnnamlen + 1;
00453                         if (dwMemPos + chnnamlen + 256 >= dwMemLength) return TRUE;
00454                 }
00455                 // packed comments (ignored)
00456                 UINT songtextlen = *((LPDWORD)(lpStream+dwMemPos));
00457                 dwMemPos += songtextlen;
00458                 if (dwMemPos + 256 >= dwMemLength) return TRUE;
00459         }
00460         // Order List
00461         {
00462                 for (UINT i=0; i<MAX_ORDERS; i++)
00463                 {
00464                         Order[i] = 0xFF;
00465                         if (dwMemPos + 2 >= dwMemLength) return TRUE;
00466                         if (i < psh->orders)
00467                         {
00468                                 Order[i] = lpStream[dwMemPos];
00469                                 dwMemPos += 2;
00470                         }
00471                 }
00472         }
00473         // Pattern Data
00474         for (UINT ipat=0; ipat<psh->patterns; ipat++)
00475         {
00476                 if (dwMemPos+8 >= dwMemLength) return TRUE;
00477                 UINT packedlen = *((LPDWORD)(lpStream+dwMemPos));
00478                 UINT numrows = 1 + (UINT)(lpStream[dwMemPos+4]);
00479                 //UINT patchn = 1 + (UINT)(lpStream[dwMemPos+5] & 0x1F);
00480                 //UINT patcmds = 1 + (UINT)(lpStream[dwMemPos+5] >> 5);
00481                 UINT patnamlen = lpStream[dwMemPos+6];
00482                 dwMemPos += 4;
00483                 if ((ipat < MAX_PATTERNS) && (packedlen < dwMemLength-dwMemPos) && (numrows >= 8))
00484                 {
00485                         if ((patnamlen) && (patnamlen < MAX_PATTERNNAME))
00486                         {
00487                                 char s[MAX_PATTERNNAME]; // changed from CHAR
00488                                 memcpy(s, lpStream+dwMemPos+3, patnamlen);
00489                                 s[patnamlen] = 0;
00490                                 SetPatternName(ipat, s);
00491                         }
00492                         PatternSize[ipat] = numrows;
00493                         Patterns[ipat] = AllocatePattern(numrows, m_nChannels);
00494                         if (!Patterns[ipat]) return TRUE;
00495                         // Unpack Pattern Data
00496                         LPCBYTE psrc = lpStream + dwMemPos;
00497                         UINT pos = 3 + patnamlen;
00498                         UINT row = 0;
00499                         while ((pos < packedlen) && (row < numrows))
00500                         {
00501                                 MODCOMMAND *m = Patterns[ipat] + row * m_nChannels;
00502                                 UINT byte1 = psrc[pos++];
00503                                 UINT ch = byte1 & 0x1F;
00504                                 // Read Note + Instr
00505                                 if (!(byte1 & 0x40))
00506                                 {
00507                                         UINT byte2 = psrc[pos++];
00508                                         UINT note = byte2 & 0x7F;
00509                                         if (note) m[ch].note = (note > 1) ? (note-1) : 0xFF;
00510                                         m[ch].instr = psrc[pos++];
00511                                         // Read Effect
00512                                         while (byte2 & 0x80)
00513                                         {
00514                                                 byte2 = psrc[pos++];
00515                                                 if (byte2 & 0x40)
00516                                                 {
00517                                                         m[ch].volcmd = VOLCMD_VOLUME;
00518                                                         m[ch].vol = byte2 & 0x3F;
00519                                                 } else
00520                                                 {
00521                                                         UINT command = byte2 & 0x3F;
00522                                                         UINT param = psrc[pos++];
00523                                                         if (command == 0x0C)
00524                                                         {
00525                                                                 m[ch].volcmd = VOLCMD_VOLUME;
00526                                                                 m[ch].vol = param / 2;
00527                                                         } else
00528                                                         if (command < 0x10)
00529                                                         {
00530                                                                 m[ch].command = command;
00531                                                                 m[ch].param = param;
00532                                                                 ConvertModCommand(&m[ch]);
00533                                                         } else
00534                                                         {
00535                                                                 // TODO: AMS effects
00536                                                         }
00537                                                 }
00538                                         }
00539                                 }
00540                                 if (byte1 & 0x80) row++;
00541                         }
00542                 }
00543                 dwMemPos += packedlen;
00544         }
00545         // Read Samples
00546         for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) if (Ins[iSmp].nLength)
00547         {
00548                 if (dwMemPos >= dwMemLength - 9) return TRUE;
00549                 UINT flags;
00550                 if (packedsamples[iSmp] & 0x03)
00551                 {
00552                         flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_AMS16 : RS_AMS8;
00553                 } else
00554                 {
00555                         flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S;
00556                 }
00557                 dwMemPos += ReadSample(&Ins[iSmp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos);
00558         }
00559         return TRUE;
00560 }
00561 
00562 
00564 // AMS Sample unpacking
00565 
00566 void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char packcharacter)
00567 {
00568         UINT tmplen = dmax;
00569         signed char *amstmp = new signed char[tmplen];
00570         
00571         if (!amstmp) return;
00572         // Unpack Loop
00573         {
00574                 signed char *p = amstmp;
00575                 UINT i=0, j=0;
00576                 while ((i < inputlen) && (j < tmplen))
00577                 {
00578                         signed char ch = psrc[i++];
00579                         if (ch == packcharacter)
00580                         {
00581                                 BYTE ch2 = psrc[i++];
00582                                 if (ch2)
00583                                 {
00584                                         ch = psrc[i++];
00585                                         while (ch2--)
00586                                         {
00587                                                 p[j++] = ch;
00588                                                 if (j >= tmplen) break;
00589                                         }
00590                                 } else p[j++] = packcharacter;
00591                         } else p[j++] = ch;
00592                 }
00593         }
00594         // Bit Unpack Loop
00595         {
00596                 signed char *p = amstmp;
00597                 UINT bitcount = 0x80, dh;
00598                 UINT k=0;
00599                 for (UINT i=0; i<dmax; i++)
00600                 {
00601                         BYTE al = *p++;
00602                         dh = 0;
00603                         for (UINT count=0; count<8; count++)
00604                         {
00605                                 UINT bl = al & bitcount;
00606                                 bl = ((bl|(bl<<8)) >> ((dh+8-count) & 7)) & 0xFF;
00607                                 bitcount = ((bitcount|(bitcount<<8)) >> 1) & 0xFF;
00608                                 pdest[k++] |= bl;
00609                                 if (k >= dmax)
00610                                 {
00611                                         k = 0;
00612                                         dh++;
00613                                 }
00614                         }
00615                         bitcount = ((bitcount|(bitcount<<8)) >> dh) & 0xFF;
00616                 }
00617         }
00618         // Delta Unpack
00619         {
00620                 signed char old = 0;
00621                 for (UINT i=0; i<dmax; i++)
00622                 {
00623                         int pos = ((LPBYTE)pdest)[i];
00624                         if ((pos != 128) && (pos & 0x80)) pos = -(pos & 0x7F);
00625                         old -= (signed char)pos;
00626                         pdest[i] = old;
00627                 }
00628         }
00629         delete amstmp;
00630 }
00631 

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