summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/modplug/load_ult.cpp
authorllornkcor <llornkcor>2002-07-20 22:07:31 (UTC)
committer llornkcor <llornkcor>2002-07-20 22:07:31 (UTC)
commit2342d48be31847e7ead9d1cc682452e8f0122351 (patch) (unidiff)
tree8329bb94e9d429c905a0ef6b881cf1c0f775bf14 /core/multimedia/opieplayer/modplug/load_ult.cpp
parent0f24c1fb86d3bb58d8696358b824c0e01752b10d (diff)
downloadopie-2342d48be31847e7ead9d1cc682452e8f0122351.zip
opie-2342d48be31847e7ead9d1cc682452e8f0122351.tar.gz
opie-2342d48be31847e7ead9d1cc682452e8f0122351.tar.bz2
initial commit of modplugin
Diffstat (limited to 'core/multimedia/opieplayer/modplug/load_ult.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/modplug/load_ult.cpp225
1 files changed, 225 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/modplug/load_ult.cpp b/core/multimedia/opieplayer/modplug/load_ult.cpp
new file mode 100644
index 0000000..c9b7118
--- a/dev/null
+++ b/core/multimedia/opieplayer/modplug/load_ult.cpp
@@ -0,0 +1,225 @@
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#include "stdafx.h"
11#include "sndfile.h"
12
13//#pragma warning(disable:4244)
14
15#define ULT_16BIT 0x04
16#define ULT_LOOP 0x08
17#define ULT_BIDI 0x10
18
19#pragma pack(1)
20
21// Raw ULT header struct:
22typedef struct tagULTHEADER
23{
24 char id[15]; // changed from CHAR
25 char songtitle[32]; // changed from CHAR
26 BYTE reserved;
27} Q_PACKED ULTHEADER;
28
29
30// Raw ULT sampleinfo struct:
31typedef struct tagULTSAMPLE
32{
33 CHAR samplename[32];
34 CHAR dosname[12];
35 LONG loopstart;
36 LONG loopend;
37 LONG sizestart;
38 LONG sizeend;
39 BYTE volume;
40 BYTE flags;
41 WORD finetune;
42} Q_PACKED ULTSAMPLE;
43
44#pragma pack()
45
46
47BOOL CSoundFile::ReadUlt(const BYTE *lpStream, DWORD dwMemLength)
48//---------------------------------------------------------------
49{
50 ULTHEADER *pmh = (ULTHEADER *)lpStream;
51 ULTSAMPLE *pus;
52 UINT nos, nop;
53 DWORD dwMemPos = 0;
54
55 // try to read module header
56 if ((!lpStream) || (dwMemLength < 0x100)) return FALSE;
57 if (strncmp(pmh->id,"MAS_UTrack_V00",14)) return FALSE;
58 // Warning! Not supported ULT format, trying anyway
59 // if ((pmh->id[14] < '1') || (pmh->id[14] > '4')) return FALSE;
60 m_nType = MOD_TYPE_ULT;
61 m_nDefaultSpeed = 6;
62 m_nDefaultTempo = 125;
63 memcpy(m_szNames[0], pmh->songtitle, 32);
64 // read songtext
65 dwMemPos = sizeof(ULTHEADER);
66 if ((pmh->reserved) && (dwMemPos + pmh->reserved * 32 < dwMemLength))
67 {
68 UINT len = pmh->reserved * 32;
69 m_lpszSongComments = new char[len + 1 + pmh->reserved];
70 if (m_lpszSongComments)
71 {
72 for (UINT l=0; l<pmh->reserved; l++)
73 {
74 memcpy(m_lpszSongComments+l*33, lpStream+dwMemPos+l*32, 32);
75 m_lpszSongComments[l*33+32] = 0x0D;
76 }
77 m_lpszSongComments[len] = 0;
78 }
79 dwMemPos += len;
80 }
81 if (dwMemPos >= dwMemLength) return TRUE;
82 nos = lpStream[dwMemPos++];
83 m_nSamples = nos;
84 if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1;
85 UINT smpsize = 64;
86 if (pmh->id[14] >= '4')smpsize += 2;
87 if (dwMemPos + nos*smpsize + 256 + 2 > dwMemLength) return TRUE;
88 for (UINT ins=1; ins<=nos; ins++, dwMemPos+=smpsize) if (ins<=m_nSamples)
89 {
90 pus= (ULTSAMPLE *)(lpStream+dwMemPos);
91 MODINSTRUMENT *pins = &Ins[ins];
92 memcpy(m_szNames[ins], pus->samplename, 32);
93 memcpy(pins->name, pus->dosname, 12);
94 pins->nLoopStart = pus->loopstart;
95 pins->nLoopEnd = pus->loopend;
96 pins->nLength = pus->sizeend - pus->sizestart;
97 pins->nVolume = pus->volume;
98 pins->nGlobalVol = 64;
99 pins->nC4Speed = 8363;
100 if (pmh->id[14] >= '4')
101 {
102 pins->nC4Speed = pus->finetune;
103 }
104 if (pus->flags & ULT_LOOP) pins->uFlags |= CHN_LOOP;
105 if (pus->flags & ULT_BIDI) pins->uFlags |= CHN_PINGPONGLOOP;
106 if (pus->flags & ULT_16BIT)
107 {
108 pins->uFlags |= CHN_16BIT;
109 pins->nLoopStart >>= 1;
110 pins->nLoopEnd >>= 1;
111 }
112 }
113 memcpy(Order, lpStream+dwMemPos, 256);
114 dwMemPos += 256;
115 m_nChannels = lpStream[dwMemPos] + 1;
116 nop = lpStream[dwMemPos+1] + 1;
117 dwMemPos += 2;
118 if (m_nChannels > 32) m_nChannels = 32;
119 // Default channel settings
120 for (UINT nSet=0; nSet<m_nChannels; nSet++)
121 {
122 ChnSettings[nSet].nVolume = 64;
123 ChnSettings[nSet].nPan = (nSet & 1) ? 0x40 : 0xC0;
124 }
125 // read pan position table for v1.5 and higher
126 if(pmh->id[14]>='3')
127 {
128 if (dwMemPos + m_nChannels > dwMemLength) return TRUE;
129 for(UINT t=0; t<m_nChannels; t++)
130 {
131 ChnSettings[t].nPan = (lpStream[dwMemPos++] << 4) + 8;
132 if (ChnSettings[t].nPan > 256) ChnSettings[t].nPan = 256;
133 }
134 }
135 // Allocating Patterns
136 for (UINT nAllocPat=0; nAllocPat<nop; nAllocPat++)
137 {
138 if (nAllocPat < MAX_PATTERNS)
139 {
140 PatternSize[nAllocPat] = 64;
141 Patterns[nAllocPat] = AllocatePattern(64, m_nChannels);
142 }
143 }
144 // Reading Patterns
145 for (UINT nChn=0; nChn<m_nChannels; nChn++)
146 {
147 for (UINT nPat=0; nPat<nop; nPat++)
148 {
149 MODCOMMAND *pat = NULL;
150
151 if (nPat < MAX_PATTERNS)
152 {
153 pat = Patterns[nPat];
154 if (pat) pat += nChn;
155 }
156 UINT row = 0;
157 while (row < 64)
158 {
159 if (dwMemPos + 6 > dwMemLength) return TRUE;
160 UINT rep = 1;
161 UINT note = lpStream[dwMemPos++];
162 if (note == 0xFC)
163 {
164 rep = lpStream[dwMemPos];
165 note = lpStream[dwMemPos+1];
166 dwMemPos += 2;
167 }
168 UINT instr = lpStream[dwMemPos++];
169 UINT eff = lpStream[dwMemPos++];
170 UINT dat1 = lpStream[dwMemPos++];
171 UINT dat2 = lpStream[dwMemPos++];
172 UINT cmd1 = eff & 0x0F;
173 UINT cmd2 = eff >> 4;
174 if (cmd1 == 0x0C) dat1 >>= 2; else
175 if (cmd1 == 0x0B) { cmd1 = dat1 = 0; }
176 if (cmd2 == 0x0C) dat2 >>= 2; else
177 if (cmd2 == 0x0B) { cmd2 = dat2 = 0; }
178 while ((rep != 0) && (row < 64))
179 {
180 if (pat)
181 {
182 pat->instr = instr;
183 if (note) pat->note = note + 36;
184 if (cmd1 | dat1)
185 {
186 if (cmd1 == 0x0C)
187 {
188 pat->volcmd = VOLCMD_VOLUME;
189 pat->vol = dat1;
190 } else
191 {
192 pat->command = cmd1;
193 pat->param = dat1;
194 ConvertModCommand(pat);
195 }
196 }
197 if (cmd2 == 0x0C)
198 {
199 pat->volcmd = VOLCMD_VOLUME;
200 pat->vol = dat2;
201 } else
202 if ((cmd2 | dat2) && (!pat->command))
203 {
204 pat->command = cmd2;
205 pat->param = dat2;
206 ConvertModCommand(pat);
207 }
208 pat += m_nChannels;
209 }
210 row++;
211 rep--;
212 }
213 }
214 }
215 }
216 // Reading Instruments
217 for (UINT smp=1; smp<=m_nSamples; smp++) if (Ins[smp].nLength)
218 {
219 if (dwMemPos >= dwMemLength) return TRUE;
220 UINT flags = (Ins[smp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S;
221 dwMemPos += ReadSample(&Ins[smp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength - dwMemPos);
222 }
223 return TRUE;
224}
225