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

load_far.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 // Farandole (FAR) module loader          //
00013 #include "stdafx.h"
00014 #include "sndfile.h"
00015 
00016 //#pragma warning(disable:4244)
00017 
00018 #define FARFILEMAGIC    0xFE524146      // "FAR"
00019 
00020 #pragma pack(1)
00021 
00022 typedef struct FARHEADER1
00023 {
00024         DWORD id;                               // file magic FAR=
00025         CHAR songname[40];              // songname
00026         CHAR magic2[3];                 // 13,10,26
00027         WORD headerlen;                 // remaining length of header in bytes
00028         BYTE version;                   // 0xD1
00029         BYTE onoff[16];
00030         BYTE edit1[9];
00031         BYTE speed;
00032         BYTE panning[16];
00033         BYTE edit2[4];
00034         WORD stlen;
00035 } Q_PACKED FARHEADER1;
00036 
00037 typedef struct FARHEADER2
00038 {
00039         BYTE orders[256];
00040         BYTE numpat;
00041         BYTE snglen;
00042         BYTE loopto;
00043         WORD patsiz[256];
00044 } Q_PACKED FARHEADER2;
00045 
00046 typedef struct FARSAMPLE
00047 {
00048         CHAR samplename[32];
00049         DWORD length;
00050         BYTE finetune;
00051         BYTE volume;
00052         DWORD reppos;
00053         DWORD repend;
00054         BYTE type;
00055         BYTE loop;
00056 } Q_PACKED FARSAMPLE;
00057 
00058 #pragma pack()
00059 
00060 
00061 BOOL CSoundFile::ReadFAR(const BYTE *lpStream, DWORD dwMemLength)
00062 //---------------------------------------------------------------
00063 {
00064         FARHEADER1 *pmh1 = (FARHEADER1 *)lpStream;
00065         FARHEADER2 *pmh2;
00066         DWORD dwMemPos = sizeof(FARHEADER1);
00067         UINT headerlen;
00068         BYTE samplemap[8];
00069 
00070         if ((!lpStream) || (dwMemLength < 1024) || (pmh1->id != FARFILEMAGIC)
00071          || (pmh1->magic2[0] != 13) || (pmh1->magic2[1] != 10) || (pmh1->magic2[2] != 26)) return FALSE;
00072         headerlen = pmh1->headerlen;
00073         if ((headerlen >= dwMemLength) || (dwMemPos + pmh1->stlen + sizeof(FARHEADER2) >= dwMemLength)) return FALSE;
00074         // Globals
00075         m_nType = MOD_TYPE_FAR;
00076         m_nChannels = 16;
00077         m_nInstruments = 0;
00078         m_nSamples = 0;
00079         m_nSongPreAmp = 0x20;
00080         m_nDefaultSpeed = pmh1->speed;
00081         m_nDefaultTempo = 80;
00082         m_nDefaultGlobalVolume = 256;
00083 
00084         memcpy(m_szNames[0], pmh1->songname, 32);
00085         // Channel Setting
00086         for (UINT nchpan=0; nchpan<16; nchpan++)
00087         {
00088                 ChnSettings[nchpan].dwFlags = 0;
00089                 ChnSettings[nchpan].nPan = ((pmh1->panning[nchpan] & 0x0F) << 4) + 8;
00090                 ChnSettings[nchpan].nVolume = 64;
00091         }
00092         // Reading comment
00093         if (pmh1->stlen)
00094         {
00095                 UINT szLen = pmh1->stlen;
00096                 if (szLen > dwMemLength - dwMemPos) szLen = dwMemLength - dwMemPos;
00097                 if ((m_lpszSongComments = new char[szLen + 1]) != NULL)
00098                 {
00099                         memcpy(m_lpszSongComments, lpStream+dwMemPos, szLen);
00100                         m_lpszSongComments[szLen] = 0;
00101                 }
00102                 dwMemPos += pmh1->stlen;
00103         }
00104         // Reading orders
00105         pmh2 = (FARHEADER2 *)(lpStream + dwMemPos);
00106         dwMemPos += sizeof(FARHEADER2);
00107         if (dwMemPos >= dwMemLength) return TRUE;
00108         for (UINT iorder=0; iorder<MAX_ORDERS; iorder++)
00109         {
00110                 Order[iorder] = (iorder <= pmh2->snglen) ? pmh2->orders[iorder] : 0xFF;
00111         }
00112         m_nRestartPos = pmh2->loopto;
00113         // Reading Patterns     
00114         dwMemPos += headerlen - (869 + pmh1->stlen);
00115         if (dwMemPos >= dwMemLength) return TRUE;
00116 
00117         WORD *patsiz = (WORD *)pmh2->patsiz;
00118         for (UINT ipat=0; ipat<256; ipat++) if (patsiz[ipat])
00119         {
00120                 UINT patlen = patsiz[ipat];
00121                 if ((ipat >= MAX_PATTERNS) || (patsiz[ipat] < 2))
00122                 {
00123                         dwMemPos += patlen;
00124                         continue;
00125                 }
00126                 if (dwMemPos + patlen >= dwMemLength) return TRUE;
00127                 UINT rows = (patlen - 2) >> 6;
00128                 if (!rows)
00129                 {
00130                         dwMemPos += patlen;
00131                         continue;
00132                 }
00133                 if (rows > 256) rows = 256;
00134                 if (rows < 16) rows = 16;
00135                 PatternSize[ipat] = rows;
00136                 if ((Patterns[ipat] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE;
00137                 MODCOMMAND *m = Patterns[ipat];
00138                 UINT patbrk = lpStream[dwMemPos];
00139                 const BYTE *p = lpStream + dwMemPos + 2;
00140                 UINT max = rows*16*4;
00141                 if (max > patlen-2) max = patlen-2;
00142                 for (UINT len=0; len<max; len += 4, m++)
00143                 {
00144                         BYTE note = p[len];
00145                         BYTE ins = p[len+1];
00146                         BYTE vol = p[len+2];
00147                         BYTE eff = p[len+3];
00148                         if (note)
00149                         {
00150                                 m->instr = ins + 1;
00151                                 m->note = note + 36;
00152                         }
00153                         if (vol & 0x0F)
00154                         {
00155                                 m->volcmd = VOLCMD_VOLUME;
00156                                 m->vol = (vol & 0x0F) << 2;
00157                                 if (m->vol <= 4) m->vol = 0;
00158                         }
00159                         switch(eff & 0xF0)
00160                         {
00161                         // 1.x: Portamento Up
00162                         case 0x10:
00163                                 m->command = CMD_PORTAMENTOUP;
00164                                 m->param = eff & 0x0F;
00165                                 break;
00166                         // 2.x: Portamento Down
00167                         case 0x20:
00168                                 m->command = CMD_PORTAMENTODOWN;
00169                                 m->param = eff & 0x0F;
00170                                 break;
00171                         // 3.x: Tone-Portamento
00172                         case 0x30:
00173                                 m->command = CMD_TONEPORTAMENTO;
00174                                 m->param = (eff & 0x0F) << 2;
00175                                 break;
00176                         // 4.x: Retrigger
00177                         case 0x40:
00178                                 m->command = CMD_RETRIG;
00179                                 m->param = 6 / (1+(eff&0x0F)) + 1;
00180                                 break;
00181                         // 5.x: Set Vibrato Depth
00182                         case 0x50:
00183                                 m->command = CMD_VIBRATO;
00184                                 m->param = (eff & 0x0F);
00185                                 break;
00186                         // 6.x: Set Vibrato Speed
00187                         case 0x60:
00188                                 m->command = CMD_VIBRATO;
00189                                 m->param = (eff & 0x0F) << 4;
00190                                 break;
00191                         // 7.x: Vol Slide Up
00192                         case 0x70:
00193                                 m->command = CMD_VOLUMESLIDE;
00194                                 m->param = (eff & 0x0F) << 4;
00195                                 break;
00196                         // 8.x: Vol Slide Down
00197                         case 0x80:
00198                                 m->command = CMD_VOLUMESLIDE;
00199                                 m->param = (eff & 0x0F);
00200                                 break;
00201                         // A.x: Port to vol
00202                         case 0xA0:
00203                                 m->volcmd = VOLCMD_VOLUME;
00204                                 m->vol = ((eff & 0x0F) << 2) + 4;
00205                                 break;
00206                         // B.x: Set Balance
00207                         case 0xB0:
00208                                 m->command = CMD_PANNING8;
00209                                 m->param = (eff & 0x0F) << 4;
00210                                 break;
00211                         // F.x: Set Speed
00212                         case 0xF0:
00213                                 m->command = CMD_SPEED;
00214                                 m->param = eff & 0x0F;
00215                                 break;
00216                         default:
00217                                 if ((patbrk) && (patbrk+1 == (len >> 6)) && (patbrk+1 != rows-1))
00218                                 {
00219                                         m->command = CMD_PATTERNBREAK;
00220                                         patbrk = 0;
00221                                 }
00222                         }
00223                 }
00224                 dwMemPos += patlen;
00225         }
00226         // Reading samples
00227         if (dwMemPos + 8 >= dwMemLength) return TRUE;
00228         memcpy(samplemap, lpStream+dwMemPos, 8);
00229         dwMemPos += 8;
00230         MODINSTRUMENT *pins = &Ins[1];
00231         for (UINT ismp=0; ismp<64; ismp++, pins++) if (samplemap[ismp >> 3] & (1 << (ismp & 7)))
00232         {
00233                 if (dwMemPos + sizeof(FARSAMPLE) > dwMemLength) return TRUE;
00234                 FARSAMPLE *pfs = (FARSAMPLE *)(lpStream + dwMemPos);
00235                 dwMemPos += sizeof(FARSAMPLE);
00236                 m_nSamples = ismp + 1;
00237                 memcpy(m_szNames[ismp+1], pfs->samplename, 32);
00238                 pins->nLength = pfs->length;
00239                 pins->nLoopStart = pfs->reppos;
00240                 pins->nLoopEnd = pfs->repend;
00241                 pins->nFineTune = 0;
00242                 pins->nC4Speed = 8363*2;
00243                 pins->nGlobalVol = 64;
00244                 pins->nVolume = pfs->volume << 4;
00245                 pins->uFlags = 0;
00246                 if ((pins->nLength > 3) && (dwMemPos + 4 < dwMemLength))
00247                 {
00248                         if (pfs->type & 1)
00249                         {
00250                                 pins->uFlags |= CHN_16BIT;
00251                                 pins->nLength >>= 1;
00252                                 pins->nLoopStart >>= 1;
00253                                 pins->nLoopEnd >>= 1;
00254                         }
00255                         if ((pfs->loop & 8) && (pins->nLoopEnd > 4)) pins->uFlags |= CHN_LOOP;
00256                         ReadSample(pins, (pins->uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S,
00257                                                 (LPSTR)(lpStream+dwMemPos), dwMemLength - dwMemPos);
00258                 }
00259                 dwMemPos += pfs->length;
00260         }
00261         return TRUE;
00262 }
00263 

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