Diffstat (limited to 'core/multimedia/opieplayer/modplug/load_okt.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/modplug/load_okt.cpp | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/modplug/load_okt.cpp b/core/multimedia/opieplayer/modplug/load_okt.cpp new file mode 100644 index 0000000..4030bbd --- a/dev/null +++ b/core/multimedia/opieplayer/modplug/load_okt.cpp | |||
@@ -0,0 +1,200 @@ | |||
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 | // Oktalyzer (OKT) module loader // | ||
13 | ////////////////////////////////////////////// | ||
14 | #include "stdafx.h" | ||
15 | #include "sndfile.h" | ||
16 | |||
17 | //#pragma warning(disable:4244) | ||
18 | |||
19 | typedef struct OKTFILEHEADER | ||
20 | { | ||
21 | DWORD okta; // "OKTA" | ||
22 | DWORD song; // "SONG" | ||
23 | DWORD cmod; // "CMOD" | ||
24 | DWORD fixed8; | ||
25 | BYTE chnsetup[8]; | ||
26 | DWORD samp; // "SAMP" | ||
27 | DWORD samplen; | ||
28 | } Q_PACKED OKTFILEHEADER; | ||
29 | |||
30 | |||
31 | typedef struct OKTSAMPLE | ||
32 | { | ||
33 | CHAR name[20]; | ||
34 | DWORD length; | ||
35 | WORD loopstart; | ||
36 | WORD looplen; | ||
37 | BYTE pad1; | ||
38 | BYTE volume; | ||
39 | BYTE pad2; | ||
40 | BYTE pad3; | ||
41 | } Q_PACKED OKTSAMPLE; | ||
42 | |||
43 | |||
44 | BOOL CSoundFile::ReadOKT(const BYTE *lpStream, DWORD dwMemLength) | ||
45 | //--------------------------------------------------------------- | ||
46 | { | ||
47 | OKTFILEHEADER *pfh = (OKTFILEHEADER *)lpStream; | ||
48 | DWORD dwMemPos = sizeof(OKTFILEHEADER); | ||
49 | UINT nsamples = 0, npatterns = 0, norders = 0; | ||
50 | |||
51 | if ((!lpStream) || (dwMemLength < 1024)) return FALSE; | ||
52 | if ((pfh->okta != 0x41544B4F) || (pfh->song != 0x474E4F53) | ||
53 | || (pfh->cmod != 0x444F4D43) || (pfh->chnsetup[0]) || (pfh->chnsetup[2]) | ||
54 | || (pfh->chnsetup[4]) || (pfh->chnsetup[6]) || (pfh->fixed8 != 0x08000000) | ||
55 | || (pfh->samp != 0x504D4153)) return FALSE; | ||
56 | m_nType = MOD_TYPE_OKT; | ||
57 | m_nChannels = 4 + pfh->chnsetup[1] + pfh->chnsetup[3] + pfh->chnsetup[5] + pfh->chnsetup[7]; | ||
58 | if (m_nChannels > MAX_CHANNELS) m_nChannels = MAX_CHANNELS; | ||
59 | nsamples = bswapBE32(pfh->samplen) >> 5; | ||
60 | m_nSamples = nsamples; | ||
61 | if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1; | ||
62 | // Reading samples | ||
63 | for (UINT smp=1; smp <= nsamples; smp++) | ||
64 | { | ||
65 | if (dwMemPos >= dwMemLength) return TRUE; | ||
66 | if (smp < MAX_SAMPLES) | ||
67 | { | ||
68 | OKTSAMPLE *psmp = (OKTSAMPLE *)(lpStream + dwMemPos); | ||
69 | MODINSTRUMENT *pins = &Ins[smp]; | ||
70 | |||
71 | memcpy(m_szNames[smp], psmp->name, 20); | ||
72 | pins->uFlags = 0; | ||
73 | pins->nLength = bswapBE32(psmp->length) & ~1; | ||
74 | pins->nLoopStart = bswapBE16(psmp->loopstart); | ||
75 | pins->nLoopEnd = pins->nLoopStart + bswapBE16(psmp->looplen); | ||
76 | if (pins->nLoopStart + 2 < pins->nLoopEnd) pins->uFlags |= CHN_LOOP; | ||
77 | pins->nGlobalVol = 64; | ||
78 | pins->nVolume = psmp->volume << 2; | ||
79 | pins->nC4Speed = 8363; | ||
80 | } | ||
81 | dwMemPos += sizeof(OKTSAMPLE); | ||
82 | } | ||
83 | // SPEE | ||
84 | if (dwMemPos >= dwMemLength) return TRUE; | ||
85 | if (*((DWORD *)(lpStream + dwMemPos)) == 0x45455053) | ||
86 | { | ||
87 | m_nDefaultSpeed = lpStream[dwMemPos+9]; | ||
88 | dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; | ||
89 | } | ||
90 | // SLEN | ||
91 | if (dwMemPos >= dwMemLength) return TRUE; | ||
92 | if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C53) | ||
93 | { | ||
94 | npatterns = lpStream[dwMemPos+9]; | ||
95 | dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; | ||
96 | } | ||
97 | // PLEN | ||
98 | if (dwMemPos >= dwMemLength) return TRUE; | ||
99 | if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C50) | ||
100 | { | ||
101 | norders = lpStream[dwMemPos+9]; | ||
102 | dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; | ||
103 | } | ||
104 | // PATT | ||
105 | if (dwMemPos >= dwMemLength) return TRUE; | ||
106 | if (*((DWORD *)(lpStream + dwMemPos)) == 0x54544150) | ||
107 | { | ||
108 | UINT orderlen = norders; | ||
109 | if (orderlen >= MAX_ORDERS) orderlen = MAX_ORDERS-1; | ||
110 | for (UINT i=0; i<orderlen; i++) Order[i] = lpStream[dwMemPos+10+i]; | ||
111 | for (UINT j=orderlen; j>1; j--) { if (Order[j-1]) break; Order[j-1] = 0xFF; } | ||
112 | dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; | ||
113 | } | ||
114 | // PBOD | ||
115 | UINT npat = 0; | ||
116 | while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4250)) | ||
117 | { | ||
118 | DWORD dwPos = dwMemPos + 10; | ||
119 | UINT rows = lpStream[dwMemPos+9]; | ||
120 | if (!rows) rows = 64; | ||
121 | if (npat < MAX_PATTERNS) | ||
122 | { | ||
123 | if ((Patterns[npat] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE; | ||
124 | MODCOMMAND *m = Patterns[npat]; | ||
125 | PatternSize[npat] = rows; | ||
126 | UINT imax = m_nChannels*rows; | ||
127 | for (UINT i=0; i<imax; i++, m++, dwPos+=4) | ||
128 | { | ||
129 | if (dwPos+4 > dwMemLength) break; | ||
130 | const BYTE *p = lpStream+dwPos; | ||
131 | UINT note = p[0]; | ||
132 | if (note) | ||
133 | { | ||
134 | m->note = note + 48; | ||
135 | m->instr = p[1] + 1; | ||
136 | } | ||
137 | UINT command = p[2]; | ||
138 | UINT param = p[3]; | ||
139 | m->param = param; | ||
140 | switch(command) | ||
141 | { | ||
142 | // 0: no effect | ||
143 | case 0: | ||
144 | break; | ||
145 | // 1: Portamento Up | ||
146 | case 1: | ||
147 | case 17: | ||
148 | case 30: | ||
149 | if (param) m->command = CMD_PORTAMENTOUP; | ||
150 | break; | ||
151 | // 2: Portamento Down | ||
152 | case 2: | ||
153 | case 13: | ||
154 | case 21: | ||
155 | if (param) m->command = CMD_PORTAMENTODOWN; | ||
156 | break; | ||
157 | // 10: Arpeggio | ||
158 | case 10: | ||
159 | case 11: | ||
160 | case 12: | ||
161 | m->command = CMD_ARPEGGIO; | ||
162 | break; | ||
163 | // 15: Filter | ||
164 | case 15: | ||
165 | m->command = CMD_MODCMDEX; | ||
166 | m->param = param & 0x0F; | ||
167 | break; | ||
168 | // 25: Position Jump | ||
169 | case 25: | ||
170 | m->command = CMD_POSITIONJUMP; | ||
171 | break; | ||
172 | // 28: Set Speed | ||
173 | case 28: | ||
174 | m->command = CMD_SPEED; | ||
175 | break; | ||
176 | // 31: Volume Control | ||
177 | case 31: | ||
178 | if (param <= 0x40) m->command = CMD_VOLUME; else | ||
179 | if (param <= 0x50) { m->command = CMD_VOLUMESLIDE; m->param &= 0x0F; if (!m->param) m->param = 0x0F; } else | ||
180 | if (param <= 0x60) { m->command = CMD_VOLUMESLIDE; m->param = (param & 0x0F) << 4; if (!m->param) m->param = 0xF0; } else | ||
181 | if (param <= 0x70) { m->command = CMD_MODCMDEX; m->param = 0xB0 | (param & 0x0F); if (!(param & 0x0F)) m->param = 0xBF; } else | ||
182 | if (param <= 0x80) { m->command = CMD_MODCMDEX; m->param = 0xA0 | (param & 0x0F); if (!(param & 0x0F)) m->param = 0xAF; } | ||
183 | break; | ||
184 | } | ||
185 | } | ||
186 | } | ||
187 | npat++; | ||
188 | dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; | ||
189 | } | ||
190 | // SBOD | ||
191 | UINT nsmp = 1; | ||
192 | while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4253)) | ||
193 | { | ||
194 | if (nsmp < MAX_SAMPLES) ReadSample(&Ins[nsmp], RS_PCM8S, (LPSTR)(lpStream+dwMemPos+8), dwMemLength-dwMemPos-8); | ||
195 | dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; | ||
196 | nsmp++; | ||
197 | } | ||
198 | return TRUE; | ||
199 | } | ||
200 | |||