diff options
author | Frank Gevaerts <frank@gevaerts.be> | 2010-12-12 15:03:30 +0000 |
---|---|---|
committer | Frank Gevaerts <frank@gevaerts.be> | 2010-12-12 15:03:30 +0000 |
commit | 26f2bfde03420edad4de1f22cb3d515dc063b20d (patch) | |
tree | 4a8c4abaf4795f38da70a4657c1a0fb3ba9debeb /apps/plugins/mikmod/load_mtm.c | |
parent | d192bdf11e06e50645ecb5726658d4b691480a9a (diff) | |
download | rockbox-26f2bfde03420edad4de1f22cb3d515dc063b20d.tar.gz rockbox-26f2bfde03420edad4de1f22cb3d515dc063b20d.zip |
Add MikMod plugin, ported by Jason Yu, with some minor work by Craig Mann and William Peters (FS#8806)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28810 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/mikmod/load_mtm.c')
-rw-r--r-- | apps/plugins/mikmod/load_mtm.c | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/apps/plugins/mikmod/load_mtm.c b/apps/plugins/mikmod/load_mtm.c new file mode 100644 index 0000000000..abd1da41f5 --- /dev/null +++ b/apps/plugins/mikmod/load_mtm.c | |||
@@ -0,0 +1,285 @@ | |||
1 | /* MikMod sound library | ||
2 | (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file | ||
3 | AUTHORS for complete list. | ||
4 | |||
5 | This library is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU Library General Public License as | ||
7 | published by the Free Software Foundation; either version 2 of | ||
8 | the License, or (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||
18 | 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /*============================================================================== | ||
22 | |||
23 | $Id: load_mtm.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ | ||
24 | |||
25 | MTM module loader | ||
26 | |||
27 | ==============================================================================*/ | ||
28 | |||
29 | #ifdef HAVE_CONFIG_H | ||
30 | #include "config.h" | ||
31 | #endif | ||
32 | |||
33 | #ifdef HAVE_UNISTD_H | ||
34 | #include <unistd.h> | ||
35 | #endif | ||
36 | |||
37 | #include <stdio.h> | ||
38 | #ifdef HAVE_MEMORY_H | ||
39 | #include <memory.h> | ||
40 | #endif | ||
41 | #include <string.h> | ||
42 | |||
43 | #include "mikmod_internals.h" | ||
44 | |||
45 | #ifdef SUNOS | ||
46 | extern int fprintf(FILE *, const char *, ...); | ||
47 | #endif | ||
48 | |||
49 | /*========== Module structure */ | ||
50 | |||
51 | typedef struct MTMHEADER { | ||
52 | UBYTE id[3]; /* MTM file marker */ | ||
53 | UBYTE version; /* upper major, lower nibble minor version number */ | ||
54 | CHAR songname[20]; /* ASCIIZ songname */ | ||
55 | UWORD numtracks; /* number of tracks saved */ | ||
56 | UBYTE lastpattern; /* last pattern number saved */ | ||
57 | UBYTE lastorder; /* last order number to play (songlength-1) */ | ||
58 | UWORD commentsize; /* length of comment field */ | ||
59 | UBYTE numsamples; /* number of samples saved */ | ||
60 | UBYTE attribute; /* attribute byte (unused) */ | ||
61 | UBYTE beatspertrack; | ||
62 | UBYTE numchannels; /* number of channels used */ | ||
63 | UBYTE panpos[32]; /* voice pan positions */ | ||
64 | } MTMHEADER; | ||
65 | |||
66 | typedef struct MTMSAMPLE { | ||
67 | CHAR samplename[22]; | ||
68 | ULONG length; | ||
69 | ULONG reppos; | ||
70 | ULONG repend; | ||
71 | UBYTE finetune; | ||
72 | UBYTE volume; | ||
73 | UBYTE attribute; | ||
74 | } MTMSAMPLE; | ||
75 | |||
76 | typedef struct MTMNOTE { | ||
77 | UBYTE a,b,c; | ||
78 | } MTMNOTE; | ||
79 | |||
80 | /*========== Loader variables */ | ||
81 | |||
82 | static MTMHEADER *mh = NULL; | ||
83 | static MTMNOTE *mtmtrk = NULL; | ||
84 | static UWORD pat[32]; | ||
85 | |||
86 | static CHAR MTM_Version[] = "MTM"; | ||
87 | |||
88 | /*========== Loader code */ | ||
89 | |||
90 | int MTM_Test(void) | ||
91 | { | ||
92 | UBYTE id[3]; | ||
93 | |||
94 | if(!_mm_read_UBYTES(id,3,modreader)) return 0; | ||
95 | if(!memcmp(id,"MTM",3)) return 1; | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | int MTM_Init(void) | ||
100 | { | ||
101 | if(!(mtmtrk=(MTMNOTE*)MikMod_calloc(64,sizeof(MTMNOTE)))) return 0; | ||
102 | if(!(mh=(MTMHEADER*)MikMod_malloc(sizeof(MTMHEADER)))) return 0; | ||
103 | |||
104 | return 1; | ||
105 | } | ||
106 | |||
107 | void MTM_Cleanup(void) | ||
108 | { | ||
109 | MikMod_free(mtmtrk); | ||
110 | MikMod_free(mh); | ||
111 | } | ||
112 | |||
113 | static UBYTE* MTM_Convert(void) | ||
114 | { | ||
115 | int t; | ||
116 | UBYTE a,b,inst,note,eff,dat; | ||
117 | |||
118 | UniReset(); | ||
119 | for(t=0;t<64;t++) { | ||
120 | a=mtmtrk[t].a; | ||
121 | b=mtmtrk[t].b; | ||
122 | inst=((a&0x3)<<4)|(b>>4); | ||
123 | note=a>>2; | ||
124 | eff=b&0xf; | ||
125 | dat=mtmtrk[t].c; | ||
126 | |||
127 | if(inst) UniInstrument(inst-1); | ||
128 | if(note) UniNote(note+2*OCTAVE); | ||
129 | |||
130 | /* MTM bug workaround : when the effect is volslide, slide-up *always* | ||
131 | overrides slide-down. */ | ||
132 | if(eff==0xa && (dat&0xf0)) dat&=0xf0; | ||
133 | |||
134 | /* Convert pattern jump from Dec to Hex */ | ||
135 | if(eff==0xd) | ||
136 | dat=(((dat&0xf0)>>4)*10)+(dat&0xf); | ||
137 | UniPTEffect(eff,dat); | ||
138 | UniNewline(); | ||
139 | } | ||
140 | return UniDup(); | ||
141 | } | ||
142 | |||
143 | int MTM_Load(int curious) | ||
144 | { | ||
145 | int t,u; | ||
146 | MTMSAMPLE s; | ||
147 | SAMPLE *q; | ||
148 | |||
149 | /* try to read module header */ | ||
150 | _mm_read_UBYTES(mh->id,3,modreader); | ||
151 | mh->version =_mm_read_UBYTE(modreader); | ||
152 | _mm_read_string(mh->songname,20,modreader); | ||
153 | mh->numtracks =_mm_read_I_UWORD(modreader); | ||
154 | mh->lastpattern =_mm_read_UBYTE(modreader); | ||
155 | mh->lastorder =_mm_read_UBYTE(modreader); | ||
156 | mh->commentsize =_mm_read_I_UWORD(modreader); | ||
157 | mh->numsamples =_mm_read_UBYTE(modreader); | ||
158 | mh->attribute =_mm_read_UBYTE(modreader); | ||
159 | mh->beatspertrack=_mm_read_UBYTE(modreader); | ||
160 | mh->numchannels =_mm_read_UBYTE(modreader); | ||
161 | _mm_read_UBYTES(mh->panpos,32,modreader); | ||
162 | |||
163 | if(_mm_eof(modreader)) { | ||
164 | _mm_errno = MMERR_LOADING_HEADER; | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | /* set module variables */ | ||
169 | of.initspeed = 6; | ||
170 | of.inittempo = 125; | ||
171 | of.modtype = StrDup(MTM_Version); | ||
172 | of.numchn = mh->numchannels; | ||
173 | of.numtrk = mh->numtracks+1; /* get number of channels */ | ||
174 | of.songname = DupStr(mh->songname,20,1); /* make a cstr of songname */ | ||
175 | of.numpos = mh->lastorder+1; /* copy the songlength */ | ||
176 | of.numpat = mh->lastpattern+1; | ||
177 | of.reppos = 0; | ||
178 | of.flags |= UF_PANNING; | ||
179 | for(t=0;t<32;t++) of.panning[t]=mh->panpos[t]<< 4; | ||
180 | of.numins=of.numsmp=mh->numsamples; | ||
181 | |||
182 | if(!AllocSamples()) return 0; | ||
183 | q=of.samples; | ||
184 | for(t=0;t<of.numins;t++) { | ||
185 | /* try to read sample info */ | ||
186 | _mm_read_string(s.samplename,22,modreader); | ||
187 | s.length =_mm_read_I_ULONG(modreader); | ||
188 | s.reppos =_mm_read_I_ULONG(modreader); | ||
189 | s.repend =_mm_read_I_ULONG(modreader); | ||
190 | s.finetune =_mm_read_UBYTE(modreader); | ||
191 | s.volume =_mm_read_UBYTE(modreader); | ||
192 | s.attribute =_mm_read_UBYTE(modreader); | ||
193 | |||
194 | if(_mm_eof(modreader)) { | ||
195 | _mm_errno = MMERR_LOADING_SAMPLEINFO; | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | q->samplename = DupStr(s.samplename,22,1); | ||
200 | q->seekpos = 0; | ||
201 | q->speed = finetune[s.finetune]; | ||
202 | q->length = s.length; | ||
203 | q->loopstart = s.reppos; | ||
204 | q->loopend = s.repend; | ||
205 | q->volume = s.volume; | ||
206 | if((s.repend-s.reppos)>2) q->flags |= SF_LOOP; | ||
207 | |||
208 | if(s.attribute&1) { | ||
209 | /* If the sample is 16-bits, convert the length and replen | ||
210 | byte-values into sample-values */ | ||
211 | q->flags|=SF_16BITS; | ||
212 | q->length>>=1; | ||
213 | q->loopstart>>=1; | ||
214 | q->loopend>>=1; | ||
215 | } | ||
216 | q++; | ||
217 | } | ||
218 | |||
219 | if(!AllocPositions(of.numpos)) return 0; | ||
220 | for(t=0;t<of.numpos;t++) | ||
221 | of.positions[t]=_mm_read_UBYTE(modreader); | ||
222 | for(;t<128;t++) _mm_read_UBYTE(modreader); | ||
223 | if(_mm_eof(modreader)) { | ||
224 | _mm_errno = MMERR_LOADING_HEADER; | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | if(!AllocTracks()) return 0; | ||
229 | if(!AllocPatterns()) return 0; | ||
230 | |||
231 | of.tracks[0]=MTM_Convert(); /* track 0 is empty */ | ||
232 | for(t=1;t<of.numtrk;t++) { | ||
233 | int s; | ||
234 | |||
235 | for(s=0;s<64;s++) { | ||
236 | mtmtrk[s].a=_mm_read_UBYTE(modreader); | ||
237 | mtmtrk[s].b=_mm_read_UBYTE(modreader); | ||
238 | mtmtrk[s].c=_mm_read_UBYTE(modreader); | ||
239 | } | ||
240 | |||
241 | if(_mm_eof(modreader)) { | ||
242 | _mm_errno = MMERR_LOADING_TRACK; | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | if(!(of.tracks[t]=MTM_Convert())) return 0; | ||
247 | } | ||
248 | |||
249 | for(t=0;t<of.numpat;t++) { | ||
250 | _mm_read_I_UWORDS(pat,32,modreader); | ||
251 | for(u=0;u<of.numchn;u++) | ||
252 | of.patterns[((long)t*of.numchn)+u]=pat[u]; | ||
253 | } | ||
254 | |||
255 | /* read comment field */ | ||
256 | if(mh->commentsize) | ||
257 | if(!ReadLinedComment(mh->commentsize, 40)) return 0; | ||
258 | |||
259 | return 1; | ||
260 | } | ||
261 | |||
262 | CHAR *MTM_LoadTitle(void) | ||
263 | { | ||
264 | CHAR s[20]; | ||
265 | |||
266 | _mm_fseek(modreader,4,SEEK_SET); | ||
267 | if(!_mm_read_UBYTES(s,20,modreader)) return NULL; | ||
268 | |||
269 | return(DupStr(s,20,1)); | ||
270 | } | ||
271 | |||
272 | /*========== Loader information */ | ||
273 | |||
274 | MIKMODAPI MLOADER load_mtm={ | ||
275 | NULL, | ||
276 | "MTM", | ||
277 | "MTM (MultiTracker Module editor)", | ||
278 | MTM_Init, | ||
279 | MTM_Test, | ||
280 | MTM_Load, | ||
281 | MTM_Cleanup, | ||
282 | MTM_LoadTitle | ||
283 | }; | ||
284 | |||
285 | /* ex:set ts=4: */ | ||