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

load_okt.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  *          Adam Goode       <adam@evdebs.org> (endian and char fixes for PPC)
00009 */
00010 
00012 // Oktalyzer (OKT) module loader            //
00014 #include "stdafx.h"
00015 #include "sndfile.h"
00016 
00017 //#pragma warning(disable:4244)
00018 
00019 typedef struct OKTFILEHEADER
00020 {
00021         DWORD okta;             // "OKTA"
00022         DWORD song;             // "SONG"
00023         DWORD cmod;             // "CMOD"
00024         DWORD fixed8;
00025         BYTE chnsetup[8];
00026         DWORD samp;             // "SAMP"
00027         DWORD samplen;
00028 } Q_PACKED OKTFILEHEADER;
00029 
00030 
00031 typedef struct OKTSAMPLE
00032 {
00033         CHAR name[20];
00034         DWORD length;
00035         WORD loopstart;
00036         WORD looplen;
00037         BYTE pad1;
00038         BYTE volume;
00039         BYTE pad2;
00040         BYTE pad3;
00041 } Q_PACKED OKTSAMPLE;
00042 
00043 
00044 BOOL CSoundFile::ReadOKT(const BYTE *lpStream, DWORD dwMemLength)
00045 //---------------------------------------------------------------
00046 {
00047         OKTFILEHEADER *pfh = (OKTFILEHEADER *)lpStream;
00048         DWORD dwMemPos = sizeof(OKTFILEHEADER);
00049         UINT nsamples = 0, npatterns = 0, norders = 0;
00050 
00051         if ((!lpStream) || (dwMemLength < 1024)) return FALSE;
00052         if ((pfh->okta != 0x41544B4F) || (pfh->song != 0x474E4F53)
00053          || (pfh->cmod != 0x444F4D43) || (pfh->chnsetup[0]) || (pfh->chnsetup[2])
00054          || (pfh->chnsetup[4]) || (pfh->chnsetup[6]) || (pfh->fixed8 != 0x08000000)
00055          || (pfh->samp != 0x504D4153)) return FALSE;
00056         m_nType = MOD_TYPE_OKT;
00057         m_nChannels = 4 + pfh->chnsetup[1] + pfh->chnsetup[3] + pfh->chnsetup[5] + pfh->chnsetup[7];
00058         if (m_nChannels > MAX_CHANNELS) m_nChannels = MAX_CHANNELS;
00059         nsamples = bswapBE32(pfh->samplen) >> 5;
00060         m_nSamples = nsamples;
00061         if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1;
00062         // Reading samples
00063         for (UINT smp=1; smp <= nsamples; smp++)
00064         {
00065                 if (dwMemPos >= dwMemLength) return TRUE;
00066                 if (smp < MAX_SAMPLES)
00067                 {
00068                         OKTSAMPLE *psmp = (OKTSAMPLE *)(lpStream + dwMemPos);
00069                         MODINSTRUMENT *pins = &Ins[smp];
00070 
00071                         memcpy(m_szNames[smp], psmp->name, 20);
00072                         pins->uFlags = 0;
00073                         pins->nLength = bswapBE32(psmp->length) & ~1;
00074                         pins->nLoopStart = bswapBE16(psmp->loopstart);
00075                         pins->nLoopEnd = pins->nLoopStart + bswapBE16(psmp->looplen);
00076                         if (pins->nLoopStart + 2 < pins->nLoopEnd) pins->uFlags |= CHN_LOOP;
00077                         pins->nGlobalVol = 64;
00078                         pins->nVolume = psmp->volume << 2;
00079                         pins->nC4Speed = 8363;
00080                 }
00081                 dwMemPos += sizeof(OKTSAMPLE);
00082         }
00083         // SPEE
00084         if (dwMemPos >= dwMemLength) return TRUE;
00085         if (*((DWORD *)(lpStream + dwMemPos)) == 0x45455053)
00086         {
00087                 m_nDefaultSpeed = lpStream[dwMemPos+9];
00088                 dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
00089         }
00090         // SLEN
00091         if (dwMemPos >= dwMemLength) return TRUE;
00092         if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C53)
00093         {
00094                 npatterns = lpStream[dwMemPos+9];
00095                 dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
00096         }
00097         // PLEN
00098         if (dwMemPos >= dwMemLength) return TRUE;
00099         if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C50)
00100         {
00101                 norders = lpStream[dwMemPos+9];
00102                 dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
00103         }
00104         // PATT
00105         if (dwMemPos >= dwMemLength) return TRUE;
00106         if (*((DWORD *)(lpStream + dwMemPos)) == 0x54544150)
00107         {
00108                 UINT orderlen = norders;
00109                 if (orderlen >= MAX_ORDERS) orderlen = MAX_ORDERS-1;
00110                 for (UINT i=0; i<orderlen; i++) Order[i] = lpStream[dwMemPos+10+i];
00111                 for (UINT j=orderlen; j>1; j--) { if (Order[j-1]) break; Order[j-1] = 0xFF; }
00112                 dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
00113         }
00114         // PBOD
00115         UINT npat = 0;
00116         while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4250))
00117         {
00118                 DWORD dwPos = dwMemPos + 10;
00119                 UINT rows = lpStream[dwMemPos+9];
00120                 if (!rows) rows = 64;
00121                 if (npat < MAX_PATTERNS)
00122                 {
00123                         if ((Patterns[npat] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE;
00124                         MODCOMMAND *m = Patterns[npat];
00125                         PatternSize[npat] = rows;
00126                         UINT imax = m_nChannels*rows;
00127                         for (UINT i=0; i<imax; i++, m++, dwPos+=4)
00128                         {
00129                                 if (dwPos+4 > dwMemLength) break;
00130                                 const BYTE *p = lpStream+dwPos;
00131                                 UINT note = p[0];
00132                                 if (note)
00133                                 {
00134                                         m->note = note + 48;
00135                                         m->instr = p[1] + 1;
00136                                 }
00137                                 UINT command = p[2];
00138                                 UINT param = p[3];
00139                                 m->param = param;
00140                                 switch(command)
00141                                 {
00142                                 // 0: no effect
00143                                 case 0:
00144                                         break;
00145                                 // 1: Portamento Up
00146                                 case 1:
00147                                 case 17:
00148                                 case 30:
00149                                         if (param) m->command = CMD_PORTAMENTOUP;
00150                                         break;
00151                                 // 2: Portamento Down
00152                                 case 2:
00153                                 case 13:
00154                                 case 21:
00155                                         if (param) m->command = CMD_PORTAMENTODOWN;
00156                                         break;
00157                                 // 10: Arpeggio
00158                                 case 10:
00159                                 case 11:
00160                                 case 12:
00161                                         m->command = CMD_ARPEGGIO;
00162                                         break;
00163                                 // 15: Filter
00164                                 case 15:
00165                                         m->command = CMD_MODCMDEX;
00166                                         m->param = param & 0x0F;
00167                                         break;
00168                                 // 25: Position Jump
00169                                 case 25:
00170                                         m->command = CMD_POSITIONJUMP;
00171                                         break;
00172                                 // 28: Set Speed
00173                                 case 28:
00174                                         m->command = CMD_SPEED;
00175                                         break;
00176                                 // 31: Volume Control
00177                                 case 31:
00178                                         if (param <= 0x40) m->command = CMD_VOLUME; else
00179                                         if (param <= 0x50) { m->command = CMD_VOLUMESLIDE; m->param &= 0x0F; if (!m->param) m->param = 0x0F; } else
00180                                         if (param <= 0x60) { m->command = CMD_VOLUMESLIDE; m->param = (param & 0x0F) << 4; if (!m->param) m->param = 0xF0; } else
00181                                         if (param <= 0x70) { m->command = CMD_MODCMDEX; m->param = 0xB0 | (param & 0x0F); if (!(param & 0x0F)) m->param = 0xBF; } else
00182                                         if (param <= 0x80) { m->command = CMD_MODCMDEX; m->param = 0xA0 | (param & 0x0F); if (!(param & 0x0F)) m->param = 0xAF; }
00183                                         break;
00184                                 }
00185                         }
00186                 }
00187                 npat++;
00188                 dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
00189         }
00190         // SBOD
00191         UINT nsmp = 1;
00192         while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4253))
00193         {
00194                 if (nsmp < MAX_SAMPLES) ReadSample(&Ins[nsmp], RS_PCM8S, (LPSTR)(lpStream+dwMemPos+8), dwMemLength-dwMemPos-8);
00195                 dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
00196                 nsmp++;
00197         }
00198         return TRUE;
00199 }
00200 

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