author | llornkcor <llornkcor> | 2002-07-20 22:07:31 (UTC) |
---|---|---|
committer | llornkcor <llornkcor> | 2002-07-20 22:07:31 (UTC) |
commit | 2342d48be31847e7ead9d1cc682452e8f0122351 (patch) (unidiff) | |
tree | 8329bb94e9d429c905a0ef6b881cf1c0f775bf14 /core/multimedia/opieplayer/modplug/load_ptm.cpp | |
parent | 0f24c1fb86d3bb58d8696358b824c0e01752b10d (diff) | |
download | opie-2342d48be31847e7ead9d1cc682452e8f0122351.zip opie-2342d48be31847e7ead9d1cc682452e8f0122351.tar.gz opie-2342d48be31847e7ead9d1cc682452e8f0122351.tar.bz2 |
initial commit of modplugin
Diffstat (limited to 'core/multimedia/opieplayer/modplug/load_ptm.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/modplug/load_ptm.cpp | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/modplug/load_ptm.cpp b/core/multimedia/opieplayer/modplug/load_ptm.cpp new file mode 100644 index 0000000..636ae56 --- a/dev/null +++ b/core/multimedia/opieplayer/modplug/load_ptm.cpp | |||
@@ -0,0 +1,210 @@ | |||
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 | * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC) | ||
9 | */ | ||
10 | |||
11 | ////////////////////////////////////////////// | ||
12 | // PTM PolyTracker module loader // | ||
13 | ////////////////////////////////////////////// | ||
14 | #include "stdafx.h" | ||
15 | #include "sndfile.h" | ||
16 | |||
17 | //#pragma warning(disable:4244) | ||
18 | |||
19 | #pragma pack(1) | ||
20 | |||
21 | typedef struct PTMFILEHEADER | ||
22 | { | ||
23 | CHAR songname[28]; // name of song, asciiz string | ||
24 | CHAR eof; // 26 | ||
25 | BYTE version_lo; // 03 version of file, currently 0203h | ||
26 | BYTE version_hi; // 02 | ||
27 | BYTE reserved1; // reserved, set to 0 | ||
28 | WORD norders; // number of orders (0..256) | ||
29 | WORD nsamples; // number of instruments (1..255) | ||
30 | WORD npatterns; // number of patterns (1..128) | ||
31 | WORD nchannels; // number of channels (voices) used (1..32) | ||
32 | WORD fileflags; // set to 0 | ||
33 | WORD reserved2; // reserved, set to 0 | ||
34 | DWORD ptmf_id; // song identification, 'PTMF' or 0x464d5450 | ||
35 | BYTE reserved3[16]; // reserved, set to 0 | ||
36 | BYTE chnpan[32]; // channel panning settings, 0..15, 0 = left, 7 = middle, 15 = right | ||
37 | BYTE orders[256]; // order list, valid entries 0..nOrders-1 | ||
38 | WORD patseg[128]; // pattern offsets (*16) | ||
39 | } Q_PACKED PTMFILEHEADER, *LPPTMFILEHEADER; | ||
40 | |||
41 | #define SIZEOF_PTMFILEHEADER608 | ||
42 | |||
43 | |||
44 | typedef struct PTMSAMPLE | ||
45 | { | ||
46 | BYTE sampletype; // sample type (bit array) | ||
47 | CHAR filename[12]; // name of external sample file | ||
48 | BYTE volume; // default volume | ||
49 | WORD nC4Spd; // C4 speed | ||
50 | WORD sampleseg; // sample segment (used internally) | ||
51 | WORD fileofs[2]; // offset of sample data | ||
52 | WORD length[2]; // sample size (in bytes) | ||
53 | WORD loopbeg[2]; // start of loop | ||
54 | WORD loopend[2]; // end of loop | ||
55 | WORD gusdata[8]; | ||
56 | char samplename[28];// name of sample, asciiz // changed from CHAR | ||
57 | DWORD ptms_id; // sample identification, 'PTMS' or 0x534d5450 | ||
58 | } Q_PACKED PTMSAMPLE; | ||
59 | |||
60 | #define SIZEOF_PTMSAMPLE80 | ||
61 | |||
62 | #pragma pack() | ||
63 | |||
64 | |||
65 | BOOL CSoundFile::ReadPTM(const BYTE *lpStream, DWORD dwMemLength) | ||
66 | //--------------------------------------------------------------- | ||
67 | { | ||
68 | PTMFILEHEADER pfh = *(LPPTMFILEHEADER)lpStream; | ||
69 | DWORD dwMemPos; | ||
70 | UINT nOrders; | ||
71 | |||
72 | pfh.norders = bswapLE16(pfh.norders); | ||
73 | pfh.nsamples = bswapLE16(pfh.nsamples); | ||
74 | pfh.npatterns = bswapLE16(pfh.npatterns); | ||
75 | pfh.nchannels = bswapLE16(pfh.nchannels); | ||
76 | pfh.fileflags = bswapLE16(pfh.fileflags); | ||
77 | pfh.reserved2 = bswapLE16(pfh.reserved2); | ||
78 | pfh.ptmf_id = bswapLE32(pfh.ptmf_id); | ||
79 | for (UINT j=0; j<128; j++) | ||
80 | { | ||
81 | pfh.patseg[j] = bswapLE16(pfh.patseg[j]); | ||
82 | } | ||
83 | |||
84 | if ((!lpStream) || (dwMemLength < 1024)) return FALSE; | ||
85 | if ((pfh.ptmf_id != 0x464d5450) || (!pfh.nchannels) | ||
86 | || (pfh.nchannels > 32) | ||
87 | || (pfh.norders > 256) || (!pfh.norders) | ||
88 | || (!pfh.nsamples) || (pfh.nsamples > 255) | ||
89 | || (!pfh.npatterns) || (pfh.npatterns > 128) | ||
90 | || (SIZEOF_PTMFILEHEADER+pfh.nsamples*SIZEOF_PTMSAMPLE >= (int)dwMemLength)) return FALSE; | ||
91 | memcpy(m_szNames[0], pfh.songname, 28); | ||
92 | m_szNames[0][28] = 0; | ||
93 | m_nType = MOD_TYPE_PTM; | ||
94 | m_nChannels = pfh.nchannels; | ||
95 | m_nSamples = (pfh.nsamples < MAX_SAMPLES) ? pfh.nsamples : MAX_SAMPLES-1; | ||
96 | dwMemPos = SIZEOF_PTMFILEHEADER; | ||
97 | nOrders = (pfh.norders < MAX_ORDERS) ? pfh.norders : MAX_ORDERS-1; | ||
98 | memcpy(Order, pfh.orders, nOrders); | ||
99 | for (UINT ipan=0; ipan<m_nChannels; ipan++) | ||
100 | { | ||
101 | ChnSettings[ipan].nVolume = 64; | ||
102 | ChnSettings[ipan].nPan = ((pfh.chnpan[ipan] & 0x0F) << 4) + 4; | ||
103 | } | ||
104 | for (UINT ismp=0; ismp<m_nSamples; ismp++, dwMemPos += SIZEOF_PTMSAMPLE) | ||
105 | { | ||
106 | MODINSTRUMENT *pins = &Ins[ismp+1]; | ||
107 | PTMSAMPLE *psmp = (PTMSAMPLE *)(lpStream+dwMemPos); | ||
108 | |||
109 | lstrcpyn(m_szNames[ismp+1], psmp->samplename, 28); | ||
110 | memcpy(pins->name, psmp->filename, 12); | ||
111 | pins->name[12] = 0; | ||
112 | pins->nGlobalVol = 64; | ||
113 | pins->nPan = 128; | ||
114 | pins->nVolume = psmp->volume << 2; | ||
115 | pins->nC4Speed = bswapLE16(psmp->nC4Spd) << 1; | ||
116 | pins->uFlags = 0; | ||
117 | if ((psmp->sampletype & 3) == 1) | ||
118 | { | ||
119 | UINT smpflg = RS_PCM8D; | ||
120 | DWORD samplepos; | ||
121 | pins->nLength = bswapLE32(*(LPDWORD)(psmp->length)); | ||
122 | pins->nLoopStart = bswapLE32(*(LPDWORD)(psmp->loopbeg)); | ||
123 | pins->nLoopEnd = bswapLE32(*(LPDWORD)(psmp->loopend)); | ||
124 | samplepos = bswapLE32(*(LPDWORD)(&psmp->fileofs)); | ||
125 | if (psmp->sampletype & 4) pins->uFlags |= CHN_LOOP; | ||
126 | if (psmp->sampletype & 8) pins->uFlags |= CHN_PINGPONGLOOP; | ||
127 | if (psmp->sampletype & 16) | ||
128 | { | ||
129 | pins->uFlags |= CHN_16BIT; | ||
130 | pins->nLength >>= 1; | ||
131 | pins->nLoopStart >>= 1; | ||
132 | pins->nLoopEnd >>= 1; | ||
133 | smpflg = RS_PTM8DTO16; | ||
134 | } | ||
135 | if ((pins->nLength) && (samplepos) && (samplepos < dwMemLength)) | ||
136 | { | ||
137 | ReadSample(pins, smpflg, (LPSTR)(lpStream+samplepos), dwMemLength-samplepos); | ||
138 | } | ||
139 | } | ||
140 | } | ||
141 | // Reading Patterns | ||
142 | for (UINT ipat=0; ipat<pfh.npatterns; ipat++) | ||
143 | { | ||
144 | dwMemPos = ((UINT)pfh.patseg[ipat]) << 4; | ||
145 | if ((!dwMemPos) || (dwMemPos >= dwMemLength)) continue; | ||
146 | PatternSize[ipat] = 64; | ||
147 | if ((Patterns[ipat] = AllocatePattern(64, m_nChannels)) == NULL) break; | ||
148 | // | ||
149 | MODCOMMAND *m = Patterns[ipat]; | ||
150 | for (UINT row=0; ((row < 64) && (dwMemPos < dwMemLength)); ) | ||
151 | { | ||
152 | UINT b = lpStream[dwMemPos++]; | ||
153 | |||
154 | if (dwMemPos >= dwMemLength) break; | ||
155 | if (b) | ||
156 | { | ||
157 | UINT nChn = b & 0x1F; | ||
158 | |||
159 | if (b & 0x20) | ||
160 | { | ||
161 | if (dwMemPos + 2 > dwMemLength) break; | ||
162 | m[nChn].note = lpStream[dwMemPos++]; | ||
163 | m[nChn].instr = lpStream[dwMemPos++]; | ||
164 | } | ||
165 | if (b & 0x40) | ||
166 | { | ||
167 | if (dwMemPos + 2 > dwMemLength) break; | ||
168 | m[nChn].command = lpStream[dwMemPos++]; | ||
169 | m[nChn].param = lpStream[dwMemPos++]; | ||
170 | if ((m[nChn].command == 0x0E) && ((m[nChn].param & 0xF0) == 0x80)) | ||
171 | { | ||
172 | m[nChn].command = CMD_S3MCMDEX; | ||
173 | } else | ||
174 | if (m[nChn].command < 0x10) | ||
175 | { | ||
176 | ConvertModCommand(&m[nChn]); | ||
177 | } else | ||
178 | { | ||
179 | switch(m[nChn].command) | ||
180 | { | ||
181 | case 16: | ||
182 | m[nChn].command = CMD_GLOBALVOLUME; | ||
183 | break; | ||
184 | case 17: | ||
185 | m[nChn].command = CMD_RETRIG; | ||
186 | break; | ||
187 | case 18: | ||
188 | m[nChn].command = CMD_FINEVIBRATO; | ||
189 | break; | ||
190 | default: | ||
191 | m[nChn].command = 0; | ||
192 | } | ||
193 | } | ||
194 | } | ||
195 | if (b & 0x80) | ||
196 | { | ||
197 | if (dwMemPos >= dwMemLength) break; | ||
198 | m[nChn].volcmd = VOLCMD_VOLUME; | ||
199 | m[nChn].vol = lpStream[dwMemPos++]; | ||
200 | } | ||
201 | } else | ||
202 | { | ||
203 | row++; | ||
204 | m += m_nChannels; | ||
205 | } | ||
206 | } | ||
207 | } | ||
208 | return TRUE; | ||
209 | } | ||
210 | |||