summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/modplug/load_far.cpp
Unidiff
Diffstat (limited to 'core/multimedia/opieplayer/modplug/load_far.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/modplug/load_far.cpp263
1 files changed, 263 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/modplug/load_far.cpp b/core/multimedia/opieplayer/modplug/load_far.cpp
new file mode 100644
index 0000000..32bc431
--- a/dev/null
+++ b/core/multimedia/opieplayer/modplug/load_far.cpp
@@ -0,0 +1,263 @@
1/*
2 * This program is free software; you can redistribute it and modify it
3 * under the terms of the GNU General Public License as published by the
4 * Free Software Foundation; either version 2 of the license or (at your
5 * option) any later version.
6 *
7 * Authors: Olivier Lapicque <olivierl@jps.net>
8*/
9
10////////////////////////////////////////
11 // Farandole (FAR) module loader //
12////////////////////////////////////////
13#include "stdafx.h"
14#include "sndfile.h"
15
16//#pragma warning(disable:4244)
17
18 #define FARFILEMAGIC 0xFE524146// "FAR"
19
20#pragma pack(1)
21
22typedef struct FARHEADER1
23{
24 DWORD id; // file magic FAR=
25 CHAR songname[40]; // songname
26 CHAR magic2[3]; // 13,10,26
27 WORD headerlen; // remaining length of header in bytes
28 BYTE version; // 0xD1
29 BYTE onoff[16];
30 BYTE edit1[9];
31 BYTE speed;
32 BYTE panning[16];
33 BYTE edit2[4];
34 WORD stlen;
35} Q_PACKED FARHEADER1;
36
37typedef struct FARHEADER2
38{
39 BYTE orders[256];
40 BYTE numpat;
41 BYTE snglen;
42 BYTE loopto;
43 WORD patsiz[256];
44} Q_PACKED FARHEADER2;
45
46typedef struct FARSAMPLE
47{
48 CHAR samplename[32];
49 DWORD length;
50 BYTE finetune;
51 BYTE volume;
52 DWORD reppos;
53 DWORD repend;
54 BYTE type;
55 BYTE loop;
56} Q_PACKED FARSAMPLE;
57
58#pragma pack()
59
60
61BOOL CSoundFile::ReadFAR(const BYTE *lpStream, DWORD dwMemLength)
62//---------------------------------------------------------------
63{
64 FARHEADER1 *pmh1 = (FARHEADER1 *)lpStream;
65 FARHEADER2 *pmh2;
66 DWORD dwMemPos = sizeof(FARHEADER1);
67 UINT headerlen;
68 BYTE samplemap[8];
69
70 if ((!lpStream) || (dwMemLength < 1024) || (pmh1->id != FARFILEMAGIC)
71 || (pmh1->magic2[0] != 13) || (pmh1->magic2[1] != 10) || (pmh1->magic2[2] != 26)) return FALSE;
72 headerlen = pmh1->headerlen;
73 if ((headerlen >= dwMemLength) || (dwMemPos + pmh1->stlen + sizeof(FARHEADER2) >= dwMemLength)) return FALSE;
74 // Globals
75 m_nType = MOD_TYPE_FAR;
76 m_nChannels = 16;
77 m_nInstruments = 0;
78 m_nSamples = 0;
79 m_nSongPreAmp = 0x20;
80 m_nDefaultSpeed = pmh1->speed;
81 m_nDefaultTempo = 80;
82 m_nDefaultGlobalVolume = 256;
83
84 memcpy(m_szNames[0], pmh1->songname, 32);
85 // Channel Setting
86 for (UINT nchpan=0; nchpan<16; nchpan++)
87 {
88 ChnSettings[nchpan].dwFlags = 0;
89 ChnSettings[nchpan].nPan = ((pmh1->panning[nchpan] & 0x0F) << 4) + 8;
90 ChnSettings[nchpan].nVolume = 64;
91 }
92 // Reading comment
93 if (pmh1->stlen)
94 {
95 UINT szLen = pmh1->stlen;
96 if (szLen > dwMemLength - dwMemPos) szLen = dwMemLength - dwMemPos;
97 if ((m_lpszSongComments = new char[szLen + 1]) != NULL)
98 {
99 memcpy(m_lpszSongComments, lpStream+dwMemPos, szLen);
100 m_lpszSongComments[szLen] = 0;
101 }
102 dwMemPos += pmh1->stlen;
103 }
104 // Reading orders
105 pmh2 = (FARHEADER2 *)(lpStream + dwMemPos);
106 dwMemPos += sizeof(FARHEADER2);
107 if (dwMemPos >= dwMemLength) return TRUE;
108 for (UINT iorder=0; iorder<MAX_ORDERS; iorder++)
109 {
110 Order[iorder] = (iorder <= pmh2->snglen) ? pmh2->orders[iorder] : 0xFF;
111 }
112 m_nRestartPos = pmh2->loopto;
113 // Reading Patterns
114 dwMemPos += headerlen - (869 + pmh1->stlen);
115 if (dwMemPos >= dwMemLength) return TRUE;
116
117 WORD *patsiz = (WORD *)pmh2->patsiz;
118 for (UINT ipat=0; ipat<256; ipat++) if (patsiz[ipat])
119 {
120 UINT patlen = patsiz[ipat];
121 if ((ipat >= MAX_PATTERNS) || (patsiz[ipat] < 2))
122 {
123 dwMemPos += patlen;
124 continue;
125 }
126 if (dwMemPos + patlen >= dwMemLength) return TRUE;
127 UINT rows = (patlen - 2) >> 6;
128 if (!rows)
129 {
130 dwMemPos += patlen;
131 continue;
132 }
133 if (rows > 256) rows = 256;
134 if (rows < 16) rows = 16;
135 PatternSize[ipat] = rows;
136 if ((Patterns[ipat] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE;
137 MODCOMMAND *m = Patterns[ipat];
138 UINT patbrk = lpStream[dwMemPos];
139 const BYTE *p = lpStream + dwMemPos + 2;
140 UINT max = rows*16*4;
141 if (max > patlen-2) max = patlen-2;
142 for (UINT len=0; len<max; len += 4, m++)
143 {
144 BYTE note = p[len];
145 BYTE ins = p[len+1];
146 BYTE vol = p[len+2];
147 BYTE eff = p[len+3];
148 if (note)
149 {
150 m->instr = ins + 1;
151 m->note = note + 36;
152 }
153 if (vol & 0x0F)
154 {
155 m->volcmd = VOLCMD_VOLUME;
156 m->vol = (vol & 0x0F) << 2;
157 if (m->vol <= 4) m->vol = 0;
158 }
159 switch(eff & 0xF0)
160 {
161 // 1.x: Portamento Up
162 case 0x10:
163 m->command = CMD_PORTAMENTOUP;
164 m->param = eff & 0x0F;
165 break;
166 // 2.x: Portamento Down
167 case 0x20:
168 m->command = CMD_PORTAMENTODOWN;
169 m->param = eff & 0x0F;
170 break;
171 // 3.x: Tone-Portamento
172 case 0x30:
173 m->command = CMD_TONEPORTAMENTO;
174 m->param = (eff & 0x0F) << 2;
175 break;
176 // 4.x: Retrigger
177 case 0x40:
178 m->command = CMD_RETRIG;
179 m->param = 6 / (1+(eff&0x0F)) + 1;
180 break;
181 // 5.x: Set Vibrato Depth
182 case 0x50:
183 m->command = CMD_VIBRATO;
184 m->param = (eff & 0x0F);
185 break;
186 // 6.x: Set Vibrato Speed
187 case 0x60:
188 m->command = CMD_VIBRATO;
189 m->param = (eff & 0x0F) << 4;
190 break;
191 // 7.x: Vol Slide Up
192 case 0x70:
193 m->command = CMD_VOLUMESLIDE;
194 m->param = (eff & 0x0F) << 4;
195 break;
196 // 8.x: Vol Slide Down
197 case 0x80:
198 m->command = CMD_VOLUMESLIDE;
199 m->param = (eff & 0x0F);
200 break;
201 // A.x: Port to vol
202 case 0xA0:
203 m->volcmd = VOLCMD_VOLUME;
204 m->vol = ((eff & 0x0F) << 2) + 4;
205 break;
206 // B.x: Set Balance
207 case 0xB0:
208 m->command = CMD_PANNING8;
209 m->param = (eff & 0x0F) << 4;
210 break;
211 // F.x: Set Speed
212 case 0xF0:
213 m->command = CMD_SPEED;
214 m->param = eff & 0x0F;
215 break;
216 default:
217 if ((patbrk) &&(patbrk+1 == (len >> 6)) && (patbrk+1 != rows-1))
218 {
219 m->command = CMD_PATTERNBREAK;
220 patbrk = 0;
221 }
222 }
223 }
224 dwMemPos += patlen;
225 }
226 // Reading samples
227 if (dwMemPos + 8 >= dwMemLength) return TRUE;
228 memcpy(samplemap, lpStream+dwMemPos, 8);
229 dwMemPos += 8;
230 MODINSTRUMENT *pins = &Ins[1];
231 for (UINT ismp=0; ismp<64; ismp++, pins++) if (samplemap[ismp >> 3] & (1 << (ismp & 7)))
232 {
233 if (dwMemPos + sizeof(FARSAMPLE) > dwMemLength) return TRUE;
234 FARSAMPLE *pfs = (FARSAMPLE *)(lpStream + dwMemPos);
235 dwMemPos += sizeof(FARSAMPLE);
236 m_nSamples = ismp + 1;
237 memcpy(m_szNames[ismp+1], pfs->samplename, 32);
238 pins->nLength = pfs->length;
239 pins->nLoopStart = pfs->reppos;
240 pins->nLoopEnd = pfs->repend;
241 pins->nFineTune = 0;
242 pins->nC4Speed = 8363*2;
243 pins->nGlobalVol = 64;
244 pins->nVolume = pfs->volume << 4;
245 pins->uFlags = 0;
246 if ((pins->nLength > 3) && (dwMemPos + 4 < dwMemLength))
247 {
248 if (pfs->type & 1)
249 {
250 pins->uFlags |= CHN_16BIT;
251 pins->nLength >>= 1;
252 pins->nLoopStart >>= 1;
253 pins->nLoopEnd >>= 1;
254 }
255 if ((pfs->loop & 8) && (pins->nLoopEnd > 4)) pins->uFlags |= CHN_LOOP;
256 ReadSample(pins, (pins->uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S,
257 (LPSTR)(lpStream+dwMemPos), dwMemLength - dwMemPos);
258 }
259 dwMemPos += pfs->length;
260 }
261 return TRUE;
262}
263