1 /* Extended Module Player
2 * Copyright (C) 1996-2021 Claudio Matsuoka and Hipolito Carraro Jr
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23 #include <limits.h>
24 #include "loader.h"
25 #include "period.h"
26
27 #define STM_TYPE_SONG 0x01
28 #define STM_TYPE_MODULE 0x02
29
30 struct stm_instrument_header {
31 uint8 name[12]; /* ASCIIZ instrument name */
32 uint8 id; /* Id=0 */
33 uint8 idisk; /* Instrument disk */
34 uint16 rsvd1; /* Reserved */
35 uint16 length; /* Sample length */
36 uint16 loopbeg; /* Loop begin */
37 uint16 loopend; /* Loop end */
38 uint8 volume; /* Playback volume */
39 uint8 rsvd2; /* Reserved */
40 uint16 c2spd; /* C4 speed */
41 uint32 rsvd3; /* Reserved */
42 uint16 paralen; /* Length in paragraphs */
43 };
44
45 /* v1 format header based on disassembled ST2 */
46 struct stm_file_subheader_v1 {
47 uint16 insnum; /* Number of instruments */
48 uint16 ordnum; /* Number of orders */
49 uint16 patnum; /* Number of patterns */
50 uint16 srate; /* Sample rate? */
51 uint8 tempo; /* Playback tempo */
52 uint8 channels; /* Number of channels */
53 uint16 psize; /* Pattern size */
54 uint16 rsvd2; /* Reserved */
55 uint16 skip; /* Bytes to skip */
56 };
57
58 struct stm_file_subheader_v2 {
59 uint8 tempo; /* Playback tempo */
60 uint8 patterns; /* Number of patterns */
61 uint8 gvol; /* Global volume */
62 uint8 rsvd2[13]; /* Reserved */
63 };
64
65 struct stm_file_header {
66 uint8 name[20]; /* ASCIIZ song name */
67 uint8 magic[8]; /* '!Scream!' */
68 uint8 rsvd1; /* '\x1a' */
69 uint8 type; /* 1=song, 2=module */
70 uint8 vermaj; /* Major version number */
71 uint8 vermin; /* Minor version number */
72 union {
73 struct stm_file_subheader_v1 v1;
74 struct stm_file_subheader_v2 v2;
75 } sub;
76 struct stm_instrument_header ins[32];
77 };
78
79 static int stm_test(HIO_HANDLE *, char *, const int);
80 static int stm_load(struct module_data *, HIO_HANDLE *, const int);
81
82 const struct format_loader libxmp_loader_stm = {
83 "Scream Tracker 2",
84 stm_test,
85 stm_load
86 };
87
stm_test(HIO_HANDLE * f,char * t,const int start)88 static int stm_test(HIO_HANDLE * f, char *t, const int start)
89 {
90 uint8 buf[8];
91
92 hio_seek(f, start + 20, SEEK_SET);
93 if (hio_read(buf, 1, 8, f) < 8)
94 return -1;
95
96 if (libxmp_test_name(buf, 8)) /* Tracker name should be ASCII */
97 return -1;
98
99 if (hio_read8(f) != 0x1a)
100 return -1;
101
102 if (hio_read8(f) > STM_TYPE_MODULE)
103 return -1;
104
105 hio_seek(f, start + 60, SEEK_SET);
106 if (hio_read(buf, 1, 4, f) < 4)
107 return -1;
108 if (!memcmp(buf, "SCRM", 4)) /* We don't want STX files */
109 return -1;
110
111 hio_seek(f, start + 0, SEEK_SET);
112 libxmp_read_title(f, t, 20);
113
114 return 0;
115 }
116
117 #define FX_NONE 0xff
118
119 /*
120 * Skaven's note from http://www.futurecrew.com/skaven/oldies_music.html
121 *
122 * FYI for the tech-heads: In the old Scream Tracker 2 the Arpeggio command
123 * (Jxx), if used in a single row with a 0x value, caused the note to skip
124 * the specified amount of halftones upwards halfway through the row. I used
125 * this in some songs to give the lead some character. However, when played
126 * in ModPlug Tracker, this effect doesn't work the way it did back then.
127 */
128 static const uint8 fx[16] = {
129 FX_NONE,
130 FX_SPEED, /* A - Set tempo to [INFO]. 60 normal. */
131 FX_JUMP, /* B - Break pattern and jmp to order [INFO] */
132 FX_BREAK, /* C - Break pattern */
133 FX_VOLSLIDE, /* D - Slide volume; Hi-nibble=up, Lo-nibble=down */
134 FX_PORTA_DN, /* E - Slide down at speed [INFO] */
135 FX_PORTA_UP, /* F - Slide up at speed [INFO] */
136 FX_TONEPORTA, /* G - Slide to the note specified at speed [INFO] */
137 FX_VIBRATO, /* H - Vibrato; Hi-nibble, speed. Lo-nibble, size */
138 FX_TREMOR, /* I - Tremor; Hi-nibble, ontime. Lo-nibble, offtime */
139 FX_ARPEGGIO, /* J - Arpeggio */
140 FX_NONE,
141 FX_NONE,
142 FX_NONE,
143 FX_NONE,
144 FX_NONE
145 };
146
stm_load(struct module_data * m,HIO_HANDLE * f,const int start)147 static int stm_load(struct module_data *m, HIO_HANDLE * f, const int start)
148 {
149 struct xmp_module *mod = &m->mod;
150 struct xmp_event *event;
151 struct stm_file_header sfh;
152 uint8 b;
153 uint16 version;
154 int i, j;
155
156 LOAD_INIT();
157
158 hio_read(sfh.name, 20, 1, f); /* ASCIIZ song name */
159 hio_read(sfh.magic, 8, 1, f); /* '!Scream!' */
160 sfh.rsvd1 = hio_read8(f); /* '\x1a' */
161 sfh.type = hio_read8(f); /* 1=song, 2=module */
162 sfh.vermaj = hio_read8(f); /* Major version number */
163 sfh.vermin = hio_read8(f); /* Minor version number */
164 version = (100 * sfh.vermaj) + sfh.vermin;
165
166 if (version != 110 &&
167 version != 200 && version != 210 &&
168 version != 220 && version != 221) {
169 D_(D_CRIT "Unknown version: %d", version);
170 return -1;
171 }
172
173 // TODO: improve robustness of the loader against bad parameters
174
175 if (version >= 200) {
176 sfh.sub.v2.tempo = hio_read8(f); /* Playback tempo */
177 sfh.sub.v2.patterns = hio_read8(f); /* Number of patterns */
178 sfh.sub.v2.gvol = hio_read8(f); /* Global volume */
179 hio_read(sfh.sub.v2.rsvd2, 13, 1, f); /* Reserved */
180 mod->chn = 4;
181 mod->pat = sfh.sub.v2.patterns;
182 mod->spd = (version < 221) ? LSN(sfh.sub.v2.tempo / 10) : MSN(sfh.sub.v2.tempo);
183 mod->ins = 31;
184 mod->len = (version == 200) ? 64 : 128;
185 } else {
186 if ((sfh.sub.v1.insnum = hio_read16l(f)) > 32) { /* Number of instruments */
187 D_(D_CRIT "Wrong number of instruments: %d (max 32)", sfh.sub.v1.insnum);
188 return -1;
189 }
190 if ((sfh.sub.v1.ordnum = hio_read16l(f)) > XMP_MAX_MOD_LENGTH) { /* Number of orders */
191 D_(D_CRIT "Wrong number of orders: %d (max %d)", sfh.sub.v1.ordnum, XMP_MAX_MOD_LENGTH);
192 return -1;
193 }
194 if ((sfh.sub.v1.patnum = hio_read16l(f)) > XMP_MAX_MOD_LENGTH) { /* Number of patterns */
195 D_(D_CRIT "Wrong number of patterns: %d (max %d)", sfh.sub.v1.patnum, XMP_MAX_MOD_LENGTH);
196 return -1;
197 }
198 sfh.sub.v1.srate = hio_read16l(f); /* Sample rate? */
199 sfh.sub.v1.tempo = hio_read8(f); /* Playback tempo */
200 if ((sfh.sub.v1.channels = hio_read8(f)) != 4) { /* Number of channels */
201 D_(D_CRIT "Wrong number of sound channels: %d", sfh.sub.v1.channels);
202 return -1;
203 }
204 if ((sfh.sub.v1.psize = hio_read16l(f)) != 64) { /* Pattern size */
205 D_(D_CRIT "Wrong number of rows per pattern: %d", sfh.sub.v1.psize);
206 return -1;
207 }
208 sfh.sub.v1.rsvd2 = hio_read16l(f); /* Reserved */
209 sfh.sub.v1.skip = hio_read16l(f); /* Bytes to skip */
210 hio_seek(f, sfh.sub.v1.skip, SEEK_CUR); /* Skip bytes */
211 mod->chn = sfh.sub.v1.channels;
212 mod->pat = sfh.sub.v1.patnum;
213 mod->spd = (version != 100) ? LSN(sfh.sub.v1.tempo / 10) : LSN(sfh.sub.v1.tempo);
214 mod->ins = sfh.sub.v1.insnum;
215 mod->len = sfh.sub.v1.ordnum;
216 }
217
218 for (i = 0; i < mod->ins; i++) {
219 hio_read(sfh.ins[i].name, 12, 1, f); /* Instrument name */
220 sfh.ins[i].id = hio_read8(f); /* Id=0 */
221 sfh.ins[i].idisk = hio_read8(f); /* Instrument disk */
222 sfh.ins[i].rsvd1 = hio_read16l(f); /* Reserved */
223 sfh.ins[i].length = hio_read16l(f); /* Sample length */
224 sfh.ins[i].loopbeg = hio_read16l(f); /* Loop begin */
225 sfh.ins[i].loopend = hio_read16l(f); /* Loop end */
226 sfh.ins[i].volume = hio_read8(f); /* Playback volume */
227 sfh.ins[i].rsvd2 = hio_read8(f); /* Reserved */
228 sfh.ins[i].c2spd = hio_read16l(f); /* C4 speed */
229 sfh.ins[i].rsvd3 = hio_read32l(f); /* Reserved */
230 sfh.ins[i].paralen = hio_read16l(f); /* Length in paragraphs */
231 }
232
233 if (hio_error(f)) {
234 return -1;
235 }
236
237 mod->trk = mod->pat * mod->chn;
238 mod->smp = mod->ins;
239 m->c4rate = C4_NTSC_RATE;
240
241 libxmp_copy_adjust(mod->name, sfh.name, 20);
242
243 if (!sfh.magic[0] || !strncmp((char *)sfh.magic, "PCSTV", 5) || !strncmp((char *)sfh.magic, "!Scream!", 8))
244 libxmp_set_type(m, "Scream Tracker %d.%02d", sfh.vermaj, sfh.vermin);
245 else if (!strncmp((char *)sfh.magic, "SWavePro", 8))
246 libxmp_set_type(m, "SoundWave Pro %d.%02d", sfh.vermaj, sfh.vermin);
247 else
248 libxmp_copy_adjust(mod->type, sfh.magic, 8);
249
250 MODULE_INFO();
251
252 if (libxmp_init_instrument(m) < 0)
253 return -1;
254
255 /* Read and convert instruments and samples */
256 for (i = 0; i < mod->ins; i++) {
257 if (libxmp_alloc_subinstrument(mod, i, 1) < 0)
258 return -1;
259
260 mod->xxs[i].len = sfh.ins[i].length;
261 mod->xxs[i].lps = sfh.ins[i].loopbeg;
262 mod->xxs[i].lpe = sfh.ins[i].loopend;
263 if (mod->xxs[i].lpe == 0xffff)
264 mod->xxs[i].lpe = 0;
265 mod->xxs[i].flg = mod->xxs[i].lpe > 0 ? XMP_SAMPLE_LOOP : 0;
266 mod->xxi[i].sub[0].vol = sfh.ins[i].volume;
267 mod->xxi[i].sub[0].pan = 0x80;
268 mod->xxi[i].sub[0].sid = i;
269
270 if (mod->xxs[i].len > 0)
271 mod->xxi[i].nsm = 1;
272
273 libxmp_instrument_name(mod, i, sfh.ins[i].name, 12);
274
275 D_(D_INFO "[%2X] %-14.14s %04x %04x %04x %c V%02x %5d", i,
276 mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps,
277 mod->xxs[i].lpe,
278 mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ',
279 mod->xxi[i].sub[0].vol, sfh.ins[i].c2spd);
280
281 libxmp_c2spd_to_note(sfh.ins[i].c2spd, &mod->xxi[i].sub[0].xpo,
282 &mod->xxi[i].sub[0].fin);
283 }
284
285 if (hio_read(mod->xxo, 1, mod->len, f) < mod->len)
286 return -1;
287
288 for (i = 0; i < mod->len; i++)
289 if (mod->xxo[i] >= mod->pat)
290 break;
291
292 mod->len = i;
293
294 D_(D_INFO "Module length: %d", mod->len);
295
296 if (libxmp_init_pattern(mod) < 0)
297 return -1;
298
299 /* Read and convert patterns */
300 D_(D_INFO "Stored patterns: %d", mod->pat);
301
302 for (i = 0; i < mod->pat; i++) {
303 if (libxmp_alloc_pattern_tracks(mod, i, 64) < 0)
304 return -1;
305
306 if (hio_error(f))
307 return -1;
308
309 for (j = 0; j < 64 * mod->chn; j++) {
310 event = &EVENT(i, j % mod->chn, j / mod->chn);
311 b = hio_read8(f);
312 memset(event, 0, sizeof(struct xmp_event));
313 switch (b) {
314 case 251:
315 case 252:
316 break; /* Empty note */
317 case 253:
318 event->note = XMP_KEY_OFF;
319 break; /* Key off */
320 default:
321 if (b == 254)
322 event->note = XMP_KEY_OFF;
323 else if (b == 255)
324 event->note = 0;
325 else
326 event->note = 1 + LSN(b) + 12 * (3 + MSN(b));
327
328 b = hio_read8(f);
329 event->vol = b & 0x07;
330 event->ins = (b & 0xf8) >> 3;
331
332 b = hio_read8(f);
333 event->vol += (b & 0xf0) >> 1;
334 if (version >= 200) {
335 event->vol = (event->vol > 0x40) ? 0 : event->vol + 1;
336 } else {
337 if (event->vol > 0) {
338 event->vol = (event->vol > 0x40) ? 1 : event->vol + 1;
339 }
340 }
341
342 event->fxt = fx[LSN(b)];
343 event->fxp = hio_read8(f);
344 switch (event->fxt) {
345 case FX_SPEED:
346 event->fxp = (version < 221) ? LSN(event->fxp / 10) : MSN(event->fxp);
347 break;
348 case FX_NONE:
349 event->fxp = event->fxt = 0;
350 break;
351 }
352 }
353 }
354 }
355
356 /* Read samples */
357 D_(D_INFO "Stored samples: %d", mod->smp);
358
359 for (i = 0; i < mod->ins; i++) {
360 if (!sfh.ins[i].volume || !sfh.ins[i].length) {
361 mod->xxi[i].nsm = 0;
362 continue;
363 }
364
365 if (sfh.type == STM_TYPE_SONG) {
366 HIO_HANDLE *s;
367 char sn[PATH_MAX];
368 char tmpname[32];
369 const char *instname = mod->xxi[i].name;
370
371 if (!instname[0] || !m->dirname)
372 continue;
373
374 if (libxmp_copy_name_for_fopen(tmpname, instname, 32))
375 continue;
376
377 snprintf(sn, PATH_MAX, "%s%s", m->dirname, tmpname);
378
379 if ((s = hio_open(sn, "rb"))) {
380 if (libxmp_load_sample(m, s, SAMPLE_FLAG_UNS, &mod->xxs[i], NULL) < 0) {
381 hio_close(s);
382 return -1;
383 }
384 hio_close(s);
385 }
386 } else {
387 hio_seek(f, start + (sfh.ins[i].rsvd1 << 4), SEEK_SET);
388 if (libxmp_load_sample(m, f, 0, &mod->xxs[i], NULL) < 0)
389 return -1;
390 }
391 }
392
393 m->quirk |= QUIRK_VSALL | QUIRKS_ST3;
394 m->read_event_type = READ_EVENT_ST3;
395
396 return 0;
397 }
398