1 /*
2 * Schism Tracker - a cross-platform Impulse Tracker clone
3 * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com>
4 * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org>
5 * copyright (c) 2009 Storlek & Mrs. Brisby
6 * copyright (c) 2010-2012 Storlek
7 * URL: http://schismtracker.org/
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #define NEED_BYTESWAP
25 #include "headers.h"
26 #include "slurp.h"
27 #include "fmt.h"
28 #include "log.h"
29
30 #include "sndfile.h"
31
32 /* --------------------------------------------------------------------------------------------------------- */
33
34 /* None of the sfx files on Modland are of the 31-instrument type that xmp recognizes.
35 However, there are a number of 31-instrument files with a different tag, under "SoundFX 2". */
36
37 static struct sfxfmt {
38 size_t tagpos;
39 const char tag[4];
40 int nsmp;
41 int dunno;
42 const char *id;
43 } sfxfmts[] = {
44 {124, "SO31", 31, 4, "SoundFX 2"},
45 {124, "SONG", 31, 0, "SoundFX 2 (?)"},
46 { 60, "SONG", 15, 0, "SoundFX"},
47 { 0, "" , 0, 0, NULL},
48 };
49
50
fmt_sfx_read_info(dmoz_file_t * file,const uint8_t * data,size_t length)51 int fmt_sfx_read_info(dmoz_file_t *file, const uint8_t *data, size_t length)
52 {
53 int n;
54 for (n = 0; sfxfmts[n].nsmp; n++) {
55 if (length >= sfxfmts[n].tagpos + 4
56 && memcmp(data + sfxfmts[n].tagpos, sfxfmts[n].tag, 4) == 0) {
57 file->description = sfxfmts[n].id;
58 /*file->extension = str_dup("sfx");*/
59 file->title = strdup(""); // whatever
60 file->type = TYPE_MODULE_MOD;
61 return 1;
62 }
63 }
64 return 0;
65 }
66
67 /* --------------------------------------------------------------------------------------------------------- */
68
69 /* Loader taken mostly from XMP.
70
71 Why did I write a loader for such an obscure format? That is, besides the fact that neither Modplug nor
72 Mikmod support SFX (and for good reason; it's a particularly dumb format) */
73
fmt_sfx_load_song(song_t * song,slurp_t * fp,unsigned int lflags)74 int fmt_sfx_load_song(song_t *song, slurp_t *fp, unsigned int lflags)
75 {
76 uint8_t tag[4];
77 int n, nord, npat, pat, chan, restart, nsmp = 0;
78 uint32_t smpsize[31];
79 uint16_t tmp;
80 song_note_t *note;
81 song_sample_t *sample;
82 unsigned int effwarn = 0;
83 struct sfxfmt *fmt = sfxfmts;
84
85 do {
86 slurp_seek(fp, fmt->tagpos, SEEK_SET);
87 slurp_read(fp, tag, 4);
88 if (memcmp(tag, fmt->tag, 4) == 0) {
89 nsmp = fmt->nsmp;
90 break;
91 }
92 fmt++;
93 } while (fmt->nsmp);
94
95 if (!nsmp)
96 return LOAD_UNSUPPORTED;
97
98
99 slurp_rewind(fp);
100 slurp_read(fp, smpsize, 4 * nsmp);
101 slurp_seek(fp, 4, SEEK_CUR); /* the tag again */
102 slurp_read(fp, &tmp, 2);
103 if (!tmp)
104 return LOAD_UNSUPPORTED; // erf
105 tmp = 14565 * 122 / bswapBE16(tmp);
106 song->initial_tempo = CLAMP(tmp, 31, 255);
107
108 slurp_seek(fp, 14, SEEK_CUR); /* unknown bytes (reserved?) - see below */
109
110 if (lflags & LOAD_NOSAMPLES) {
111 slurp_seek(fp, 30 * nsmp, SEEK_CUR);
112 } else {
113 for (n = 0, sample = song->samples + 1; n < nsmp; n++, sample++) {
114 slurp_read(fp, sample->name, 22);
115 sample->name[22] = 0;
116 slurp_read(fp, &tmp, 2); /* seems to be half the sample size, minus two bytes? */
117 tmp = bswapBE16(tmp);
118 sample->length = bswapBE32(smpsize[n]);
119
120 song->samples[n].c5speed = MOD_FINETUNE(slurp_getc(fp)); // ?
121 sample->volume = slurp_getc(fp);
122 if (sample->volume > 64)
123 sample->volume = 64;
124 sample->volume *= 4; //mphack
125 sample->global_volume = 64;
126 slurp_read(fp, &tmp, 2);
127 sample->loop_start = bswapBE16(tmp);
128 slurp_read(fp, &tmp, 2);
129 tmp = bswapBE16(tmp) * 2; /* loop length */
130 if (tmp > 2) {
131 sample->loop_end = sample->loop_start + tmp;
132 sample->flags |= CHN_LOOP;
133 } else {
134 sample->loop_start = sample->loop_end = 0;
135 }
136 }
137 }
138
139 /* pattern/order stuff */
140 nord = slurp_getc(fp);
141 nord = MIN(nord, 127);
142 restart = slurp_getc(fp);
143 slurp_read(fp, song->orderlist, nord);
144 slurp_seek(fp, 128 - nord, SEEK_CUR);
145 npat = 0;
146 for (n = 0; n < nord; n++) {
147 if (song->orderlist[n] > npat)
148 npat = song->orderlist[n];
149 }
150 npat++;
151
152 /* Not sure what this is about, but skipping a few bytes here seems to make SO31's load right.
153 (they all seem to have zero here) */
154 slurp_seek(fp, fmt->dunno, SEEK_CUR);
155
156 if (lflags & LOAD_NOPATTERNS) {
157 slurp_seek(fp, npat * 1024, SEEK_CUR);
158 } else {
159 for (pat = 0; pat < npat; pat++) {
160 note = song->patterns[pat] = csf_allocate_pattern(64);
161 song->pattern_size[pat] = song->pattern_alloc_size[pat] = 64;
162 for (n = 0; n < 64; n++, note += 60) {
163 for (chan = 0; chan < 4; chan++, note++) {
164 uint8_t p[4];
165 slurp_read(fp, p, 4);
166 mod_import_note(p, note);
167 /* Note events starting with FF all seem to be special in some way:
168 bytes apparent use example file on modland
169 ----- ------------ -----------------------
170 FF FE note cut 1st intro.sfx
171 FF FD unknown! another world (intro).sfx
172 FF FC pattern break orbit wanderer.sfx2 */
173 if (p[0] == 0xff) {
174 switch (p[1]) {
175 case 0xfc:
176 note->note = NOTE_NONE;
177 note->instrument = 0;
178 // stuff a C00 in channel 5
179 note[4 - chan].effect = FX_PATTERNBREAK;
180 break;
181 case 0xfe:
182 note->note = NOTE_CUT;
183 note->instrument = 0;
184 break;
185 }
186 }
187 switch (note->effect) {
188 case 0:
189 break;
190 case 1: /* arpeggio */
191 note->effect = FX_ARPEGGIO;
192 break;
193 case 2: /* pitch bend */
194 if (note->param >> 4) {
195 note->effect = FX_PORTAMENTODOWN;
196 note->param >>= 4;
197 } else if (note->param & 0xf) {
198 note->effect = FX_PORTAMENTOUP;
199 note->param &= 0xf;
200 } else {
201 note->effect = 0;
202 }
203 break;
204 case 5: /* volume up */
205 note->effect = FX_VOLUMESLIDE;
206 note->param = (note->param & 0xf) << 4;
207 break;
208 case 6: /* set volume */
209 if (note->param > 64)
210 note->param = 64;
211 note->voleffect = VOLFX_VOLUME;
212 note->volparam = 64 - note->param;
213 note->effect = 0;
214 note->param = 0;
215 break;
216 case 3: /* LED on (wtf!) */
217 case 4: /* LED off (ditto) */
218 case 7: /* set step up */
219 case 8: /* set step down */
220 default:
221 effwarn |= (1 << note->effect);
222 note->effect = FX_UNIMPLEMENTED;
223 break;
224 }
225 }
226 }
227 }
228 for (n = 0; n < 16; n++) {
229 if (effwarn & (1 << n))
230 log_appendf(4, " Warning: Unimplemented effect %Xxx", n);
231 }
232
233 if (restart < npat)
234 csf_insert_restart_pos(song, restart);
235 }
236
237 /* sample data */
238 if (!(lflags & LOAD_NOSAMPLES)) {
239 for (n = 0, sample = song->samples + 1; n < fmt->nsmp; n++, sample++) {
240 uint32_t ssize;
241
242 if (sample->length <= 2)
243 continue;
244 ssize = csf_read_sample(sample, SF_8 | SF_LE | SF_PCMS | SF_M,
245 fp->data + fp->pos, fp->length - fp->pos);
246 slurp_seek(fp, ssize, SEEK_CUR);
247 }
248 }
249
250 /* more header info */
251 song->flags = SONG_ITOLDEFFECTS | SONG_COMPATGXX;
252 for (n = 0; n < 4; n++)
253 song->channels[n].panning = PROTRACKER_PANNING(n); /* ??? */
254 for (; n < MAX_CHANNELS; n++)
255 song->channels[n].flags = CHN_MUTE;
256
257 strcpy(song->tracker_id, fmt->id);
258 song->pan_separation = 64;
259
260 // if (ferror(fp)) {
261 // return LOAD_FILE_ERROR;
262 // }
263
264 /* done! */
265 return LOAD_SUCCESS;
266 }
267
268
269 /*
270 most of modland's sfx files have all zeroes for those 14 "unknown" bytes, with the following exceptions:
271
272 64 00 00 00 00 00 00 00 00 00 00 00 00 00 d............. - unknown/antitrax.sfx
273 74 63 68 33 00 00 00 00 00 00 00 00 00 00 tch3.......... - unknown/axel f.sfx
274 61 6c 6b 00 00 00 00 00 00 00 00 00 00 00 alk........... Andreas Hommel/cyberblast-intro.sfx
275 21 00 00 00 00 00 00 00 00 00 00 00 00 00 !............. - unknown/dugger.sfx
276 00 00 00 00 00 0d 00 00 00 00 00 00 00 00 .............. Jean Baudlot/future wars - time travellers - dugger (title).sfx
277 00 00 00 00 00 00 00 00 0d 00 00 00 00 00 .............. Jean Baudlot/future wars - time travellers - escalator.sfx
278 6d 65 31 34 00 00 00 00 00 00 00 00 00 00 me14.......... - unknown/melodious.sfx
279 0d 0d 0d 53 46 58 56 31 2e 38 00 00 00 00 ...SFXV1.8.... AM-FM/sunday morning.sfx
280 61 6c 6b 00 00 00 00 00 00 00 00 00 00 00 alk........... - unknown/sunday morning.sfx
281 6f 67 00 00 00 00 00 00 00 00 00 00 00 00 og............ Philip Jespersen/supaplex.sfx
282 6e 74 20 73 6f 6e 67 00 00 00 00 00 00 00 nt song....... - unknown/sweety.sfx
283 61 6c 6b 00 00 00 00 00 00 00 00 00 00 00 alk........... - unknown/thrust.sfx
284 */
285
286