summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/modplug/load_669.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_669.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_669.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/modplug/load_669.cpp189
1 files changed, 189 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/modplug/load_669.cpp b/core/multimedia/opieplayer/modplug/load_669.cpp
new file mode 100644
index 0000000..905ca93
--- a/dev/null
+++ b/core/multimedia/opieplayer/modplug/load_669.cpp
@@ -0,0 +1,189 @@
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// 669 Composer / UNIS 669 module loader
13////////////////////////////////////////////////////////////
14
15#include "stdafx.h"
16#include "sndfile.h"
17
18//#pragma warning(disable:4244)
19
20typedef struct tagFILEHEADER669
21{
22 WORD sig; // 'if' or 'JN'
23 signed char songmessage[108];// Song Message
24 BYTE samples; // number of samples (1-64)
25 BYTE patterns; // number of patterns (1-128)
26 BYTE restartpos;
27 BYTE orders[128];
28 BYTE tempolist[128];
29 BYTE breaks[128];
30} Q_PACKED FILEHEADER669;
31
32
33typedef struct tagSAMPLE669
34{
35 BYTE filename[13];
36 BYTE length[4];// when will somebody think about DWORD align ???
37 BYTE loopstart[4];
38 BYTE loopend[4];
39} Q_PACKED SAMPLE669;
40
41
42BOOL CSoundFile::Read669(const BYTE *lpStream, DWORD dwMemLength)
43//---------------------------------------------------------------
44{
45 BOOL b669Ext;
46 const FILEHEADER669 *pfh = (const FILEHEADER669 *)lpStream;
47 const SAMPLE669 *psmp = (const SAMPLE669 *)(lpStream + 0x1F1);
48 DWORD dwMemPos = 0;
49
50 if ((!lpStream) || (dwMemLength < sizeof(FILEHEADER669))) return FALSE;
51 if ((bswapLE16(pfh->sig) != 0x6669) && (bswapLE16(pfh->sig) != 0x4E4A)) return FALSE;
52 b669Ext = (bswapLE16(pfh->sig) == 0x4E4A) ? TRUE : FALSE;
53 if ((!pfh->samples) || (pfh->samples > 64) || (pfh->restartpos >= 128)
54 || (!pfh->patterns) || (pfh->patterns > 128)) return FALSE;
55 DWORD dontfuckwithme = 0x1F1 + pfh->samples * sizeof(SAMPLE669) + pfh->patterns * 0x600;
56 if (dontfuckwithme > dwMemLength) return FALSE;
57 for (UINT ichk=0; ichk<pfh->samples; ichk++)
58 {
59 DWORD len = bswapLE32(*((DWORD *)(&psmp[ichk].length)));
60 dontfuckwithme += len;
61 }
62 if (dontfuckwithme > dwMemLength) return FALSE;
63 // That should be enough checking: this must be a 669 module.
64 m_nType = MOD_TYPE_669;
65 m_dwSongFlags |= SONG_LINEARSLIDES;
66 m_nMinPeriod = 28 << 2;
67 m_nMaxPeriod = 1712 << 3;
68 m_nDefaultTempo = 125;
69 m_nDefaultSpeed = 6;
70 m_nChannels = 8;
71 memcpy(m_szNames[0], pfh->songmessage, 16);
72 m_nSamples = pfh->samples;
73 for (UINT nins=1; nins<=m_nSamples; nins++, psmp++)
74 {
75 DWORD len = bswapLE32(*((DWORD *)(&psmp->length)));
76 DWORD loopstart = bswapLE32(*((DWORD *)(&psmp->loopstart)));
77 DWORD loopend = bswapLE32(*((DWORD *)(&psmp->loopend)));
78 if (len > MAX_SAMPLE_LENGTH) len = MAX_SAMPLE_LENGTH;
79 if ((loopend > len) && (!loopstart)) loopend = 0;
80 if (loopend > len) loopend = len;
81 if (loopstart + 4 >= loopend) loopstart = loopend = 0;
82 Ins[nins].nLength = len;
83 Ins[nins].nLoopStart = loopstart;
84 Ins[nins].nLoopEnd = loopend;
85 if (loopend) Ins[nins].uFlags |= CHN_LOOP;
86 memcpy(m_szNames[nins], psmp->filename, 13);
87 Ins[nins].nVolume = 256;
88 Ins[nins].nGlobalVol = 64;
89 Ins[nins].nPan = 128;
90 }
91 // Song Message
92 m_lpszSongComments = new char[109];
93 memcpy(m_lpszSongComments, pfh->songmessage, 108);
94 m_lpszSongComments[108] = 0;
95 // Reading Orders
96 memcpy(Order, pfh->orders, 128);
97 m_nRestartPos = pfh->restartpos;
98 if (Order[m_nRestartPos] >= pfh->patterns) m_nRestartPos = 0;
99 // Reading Pattern Break Locations
100 for (UINT npan=0; npan<8; npan++)
101 {
102 ChnSettings[npan].nPan = (npan & 1) ? 0x30 : 0xD0;
103 ChnSettings[npan].nVolume = 64;
104 }
105 // Reading Patterns
106 dwMemPos = 0x1F1 + pfh->samples * 25;
107 for (UINT npat=0; npat<pfh->patterns; npat++)
108 {
109 Patterns[npat] = AllocatePattern(64, m_nChannels);
110 if (!Patterns[npat]) break;
111 PatternSize[npat] = 64;
112 MODCOMMAND *m = Patterns[npat];
113 const BYTE *p = lpStream + dwMemPos;
114 for (UINT row=0; row<64; row++)
115 {
116 MODCOMMAND *mspeed = m;
117 if ((row == pfh->breaks[npat]) && (row != 63))
118 {
119 for (UINT i=0; i<8; i++)
120 {
121 m[i].command = CMD_PATTERNBREAK;
122 m[i].param = 0;
123 }
124 }
125 for (UINT n=0; n<8; n++, m++, p+=3)
126 {
127 UINT note = p[0] >> 2;
128 UINT instr = ((p[0] & 0x03) << 4) | (p[1] >> 4);
129 UINT vol = p[1] & 0x0F;
130 if (p[0] < 0xFE)
131 {
132 m->note = note + 37;
133 m->instr = instr + 1;
134 }
135 if (p[0] <= 0xFE)
136 {
137 m->volcmd = VOLCMD_VOLUME;
138 m->vol = (vol << 2) + 2;
139 }
140 if (p[2] != 0xFF)
141 {
142 UINT command = p[2] >> 4;
143 UINT param = p[2] & 0x0F;
144 switch(command)
145 {
146 case 0x00:command = CMD_PORTAMENTOUP; break;
147 case 0x01:command = CMD_PORTAMENTODOWN; break;
148 case 0x02:command = CMD_TONEPORTAMENTO; break;
149 case 0x03:command = CMD_MODCMDEX; param |= 0x50; break;
150 case 0x04:command = CMD_VIBRATO; param |= 0x40; break;
151 case 0x05:if (param) command = CMD_SPEED; else command = 0; param += 2; break;
152 case 0x06:if (param == 0) { command = CMD_PANNINGSLIDE; param = 0xFE; } else
153 if (param == 1) { command = CMD_PANNINGSLIDE; param = 0xEF; } else
154 command = 0;
155 break;
156 default:command = 0;
157 }
158 if (command)
159 {
160 if (command == CMD_SPEED) mspeed = NULL;
161 m->command = command;
162 m->param = param;
163 }
164 }
165 }
166 if ((!row) && (mspeed))
167 {
168 for (UINT i=0; i<8; i++) if (!mspeed[i].command)
169 {
170 mspeed[i].command = CMD_SPEED;
171 mspeed[i].param = pfh->tempolist[npat] + 2;
172 break;
173 }
174 }
175 }
176 dwMemPos += 0x600;
177 }
178 // Reading Samples
179 for (UINT n=1; n<=m_nSamples; n++)
180 {
181 UINT len = Ins[n].nLength;
182 if (dwMemPos >= dwMemLength) break;
183 if (len > 4) ReadSample(&Ins[n], RS_PCM8U, (LPSTR)(lpStream+dwMemPos), dwMemLength - dwMemPos);
184 dwMemPos += len;
185 }
186 return TRUE;
187}
188
189