1 /* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * readpsm.c - Code to read a Protracker Studio / / \ \
12 * module from an open file. | < / \_
13 * | \/ /\ /
14 * By Chris Moeller. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include "dumb.h"
24 #include "internal/it.h"
25
26 #ifndef min
27 #define min(a, b) (((a) < (b)) ? (a) : (b))
28 #endif
29
30 #ifdef _MSC_VER
31 #define snprintf sprintf_s
32 #endif
33
34 #define PSMV_OLD 940730
35 #define PSMV_NEW 940902
36
37 typedef struct _PSMCHUNK
38 {
39 int id;
40 int len;
41 unsigned char * data;
42 } PSMCHUNK;
43
44 typedef struct _PSMEVENT
45 {
46 int type;
47 unsigned char data[8];
48 } PSMEVENT;
49
50 #define PSM_EVENT_END 0
51 #define PSM_EVENT_PLAY_PATTERN 1
52 #define PSM_EVENT_JUMP_TO_LINE 4
53 #define PSM_EVENT_SET_SPEED 7
54 #define PSM_EVENT_SET_BPM 8
55 #define PSM_EVENT_SAMPLE_MAP_TABLE 12
56 #define PSM_EVENT_CHANGE_PAN 13
57 #define PSM_EVENT_CHANGE_VOL 14
58
it_psm_process_sample(IT_SAMPLE * sample,const unsigned char * data,int len,int id,int version)59 static int it_psm_process_sample(IT_SAMPLE * sample, const unsigned char * data, int len, int id, int version) {
60 int flags;
61 int insno;
62 int length;
63 int loopstart;
64 int loopend;
65 int panpos;
66 int defvol;
67 int samplerate;
68
69 if (len < 0x60) return -1;
70
71 flags = data[0];
72
73 if (version == PSMV_OLD) {
74 memcpy(sample->name, data + 0x0D, 34);
75 sample->name[34] = 0;
76
77 insno = data[0x34] | (data[0x35] << 8);
78 length = data[0x36] | (data[0x37] << 8) | (data[0x38] << 16) | (data[0x39] << 24);
79 loopstart = data[0x3A] | (data[0x3B] << 8) | (data[0x3C] << 16) | (data[0x3D] << 24);
80 loopend = data[0x3E] | (data[0x3F] << 8) | (data[0x40] << 16) | (data[0x41] << 24);
81 panpos = data[0x43];
82 defvol = data[0x44];
83 samplerate = data[0x49] | (data[0x4A] << 8) | (data[0x4B] << 16) | (data[0x4C] << 24);
84 } else /*if (version == PSMV_NEW)*/ {
85 memcpy(sample->name, data + 0x11, 34);
86 sample->name[34] = 0;
87
88 insno = data[0x38] | (data[0x39] << 8);
89 length = data[0x3A] | (data[0x3B] << 8) | (data[0x3C] << 16) | (data[0x3D] << 24);
90 loopstart = data[0x3E] | (data[0x3F] << 8) | (data[0x40] << 16) | (data[0x41] << 24);
91 loopend = data[0x42] | (data[0x43] << 8) | (data[0x44] << 16) | (data[0x45] << 24);
92 panpos = data[0x48];
93 defvol = data[0x49];
94 samplerate = data[0x4E] | (data[0x4F] << 8) | (data[0x50] << 16) | (data[0x51] << 24);
95 }
96
97 if (insno != id) return -1;
98
99 if (!length) {
100 sample->flags &= ~IT_SAMPLE_EXISTS;
101 return 0;
102 }
103
104 if ((length > len - 0x60) || ((flags & 0x7F) != 0)) return -1;
105
106 sample->flags = IT_SAMPLE_EXISTS;
107 sample->length = length;
108 sample->loop_start = loopstart;
109 sample->loop_end = loopend;
110 sample->C5_speed = samplerate;
111 sample->default_volume = defvol >> 1;
112 sample->default_pan = 0;
113 sample->filename[0] = 0;
114 sample->global_volume = 64;
115 sample->vibrato_speed = 0;
116 sample->vibrato_depth = 0;
117 sample->vibrato_rate = 0;
118 sample->vibrato_waveform = IT_VIBRATO_SINE;
119 sample->finetune = 0;
120 sample->max_resampling_quality = -1;
121
122 if (flags & 0x80) {
123 if (((unsigned int)sample->loop_end <= (unsigned int)sample->length) &&
124 ((unsigned int)sample->loop_start < (unsigned int)sample->loop_end)) {
125 sample->length = sample->loop_end;
126 sample->flags |= IT_SAMPLE_LOOP;
127 }
128 }
129
130 sample->data = malloc(sample->length);
131 if (!sample->data)
132 return -1;
133
134 flags = 0;
135 data += 0x60;
136
137 for (insno = 0; insno < sample->length; insno++) {
138 flags += (signed char)(*data++);
139 ((signed char *)sample->data)[insno] = flags;
140 }
141
142 return 0;
143 }
144
it_psm_process_pattern(IT_PATTERN * pattern,const unsigned char * data,int len,int speed,int bpm,const unsigned char * pan,const int * vol,int version)145 static int it_psm_process_pattern(IT_PATTERN * pattern, const unsigned char * data, int len, int speed, int bpm, const unsigned char * pan, const int * vol, int version) {
146 int length, nrows, row, rowlen, pos;
147 unsigned flags, chan;
148 IT_ENTRY * entry;
149
150 length = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
151 if (len > length) len = length;
152
153 if (version == PSMV_OLD) {
154 if (len < 10) return -1;
155 data += 8;
156 len -= 8;
157 } else /*if (version == PSMV_NEW)*/ {
158 if (len < 14) return -1;
159 data += 12;
160 len -= 12;
161 }
162
163 nrows = data[0] | (data[1] << 8);
164
165 if (!nrows) return 0;
166
167 pattern->n_rows = nrows;
168
169 data += 2;
170 len -= 2;
171
172 pattern->n_entries = 0;
173
174 row = 0;
175 pos = 2;
176 rowlen = data[0] | (data[1] << 8);
177
178 while ((row < nrows) && (pos < len)) {
179 if (pos >= rowlen) {
180 row++;
181 rowlen += data[pos] | (data[pos+1] << 8);
182 pos += 2;
183 continue;
184 }
185
186 flags = data[pos++];
187 chan = data[pos++];
188
189 if (chan > 63) return -1;
190
191 if (flags & 0xF0) {
192 pattern->n_entries++;
193 if (flags & 0x80) pos++;
194 if (flags & 0x40) pos++;
195 if (flags & 0x20) pos++;
196 if (flags & 0x10) {
197 switch (data[pos]) {
198 case 0x29:
199 pos++;
200 case 0x33:
201 pos++;
202 default:
203 pos += 2;
204 }
205 }
206 }
207 }
208
209 if (!pattern->n_entries) return 0;
210
211 pattern->n_entries += nrows;
212 if (speed) pattern->n_entries++;
213 if (bpm >= 0x20) pattern->n_entries++;
214
215 for (pos = 0; pos < 32; pos++) {
216 if (!(pan[pos*2+1] & 0xF9)) pattern->n_entries++;
217 if (vol[pos] != -1) pattern->n_entries++;
218 }
219
220 pattern->entry = malloc(pattern->n_entries * sizeof(*pattern->entry));
221 if (!pattern->entry) return -1;
222
223 entry = pattern->entry;
224
225 if (speed) {
226 entry->channel = 0;
227 entry->mask = IT_ENTRY_EFFECT;
228 entry->effect = IT_SET_SPEED;
229 entry->effectvalue = speed;
230 entry++;
231 }
232
233 if (bpm >= 0x20) {
234 entry->channel = 0;
235 entry->mask = IT_ENTRY_EFFECT;
236 entry->effect = IT_SET_SONG_TEMPO;
237 entry->effectvalue = bpm;
238 entry++;
239 }
240
241 for (pos = 0; pos < 32; pos++) {
242 if (!(pan[pos*2+1] & 0xF9)) {
243 entry->channel = pos;
244 entry->mask = IT_ENTRY_EFFECT;
245 switch (pan[pos*2+1]) {
246 case 0:
247 entry->effect = IT_SET_PANNING;
248 entry->effectvalue = pan[pos*2] ^ 128;
249 break;
250 case 2:
251 entry->effect = IT_S;
252 entry->effectvalue = EFFECT_VALUE(IT_S_SET_SURROUND_SOUND,1);
253 break;
254 case 4:
255 entry->effect = IT_SET_PANNING;
256 entry->effectvalue = 128;
257 break;
258 }
259 entry++;
260 }
261 if (vol[pos] != -1) {
262 entry->channel = pos;
263 entry->mask = IT_ENTRY_EFFECT;
264 entry->effect = IT_SET_CHANNEL_VOLUME;
265 entry->effectvalue = (vol[pos] + 2) >> 2;
266 entry++;
267 }
268 }
269
270 row = 0;
271 pos = 2;
272 rowlen = data[0] | (data[1] << 8);
273
274 while ((row < nrows) && (pos < len)) {
275 if (pos >= rowlen) {
276 IT_SET_END_ROW(entry);
277 entry++;
278 row++;
279 rowlen += data[pos] | (data[pos+1] << 8);
280 pos += 2;
281 continue;
282 }
283
284 flags = data[pos++];
285 entry->channel = data[pos++];
286 entry->mask = 0;
287
288 if (flags & 0xF0) {
289 if (flags & 0x80) {
290 entry->mask |= IT_ENTRY_NOTE;
291 if (version == PSMV_OLD) {
292 if ((data[pos] < 0x80)) entry->note = (data[pos]>>4)*12+(data[pos]&0x0f)+12;
293 else entry->mask &= ~IT_ENTRY_NOTE;
294 } else /*if (version == PSMV_NEW)*/ {
295 if ((data[pos]) && (data[pos] < 84)) entry->note = data[pos] + 35;
296 else entry->mask &= ~IT_ENTRY_NOTE;
297 }
298 pos++;
299 }
300
301 if (flags & 0x40) {
302 entry->mask |= IT_ENTRY_INSTRUMENT;
303 entry->instrument = data[pos++] + 1;
304 }
305
306 if (flags & 0x20) {
307 entry->mask |= IT_ENTRY_VOLPAN;
308 entry->volpan = (data[pos++] + 1) >> 1;
309 }
310
311 if (flags & 0x10) {
312 entry->mask |= IT_ENTRY_EFFECT;
313 length = data[pos+1];
314 switch (data[pos]) {
315 case 1:
316 entry->effect = IT_VOLUME_SLIDE;
317 if (version == PSMV_OLD) entry->effectvalue = ((length&0x1e)<<3) | 0xF;
318 else /*if (version == PSMV_NEW)*/ entry->effectvalue = (length<<4) | 0xF;
319 break;
320
321 case 2:
322 entry->effect = IT_VOLUME_SLIDE;
323 if (version == PSMV_OLD) entry->effectvalue = (length << 3) & 0xF0;
324 else /*if (version == PSMV_NEW)*/ entry->effectvalue = (length << 4) & 0xF0;
325 break;
326
327 case 3:
328 entry->effect = IT_VOLUME_SLIDE;
329 if (version == PSMV_OLD) entry->effectvalue = (length >> 1) | 0xF0;
330 else /*if (version == PSMV_NEW)*/ entry->effectvalue = length | 0xF0;
331 break;
332
333 case 4:
334 entry->effect = IT_VOLUME_SLIDE;
335 if (version == PSMV_OLD) entry->effectvalue = (length >> 1) & 0xF;
336 else /*if (version == PSMV_NEW)*/ entry->effectvalue = length & 0xF;
337 break;
338
339 case 12:
340 entry->effect = IT_PORTAMENTO_UP;
341 if (version == PSMV_OLD) {
342 if (length < 4) entry->effectvalue = length | 0xF0;
343 else entry->effectvalue = length >> 2;
344 } else /*if (version == PSMV_NEW)*/ {
345 entry->effectvalue = length;
346 }
347 break;
348
349 case 14:
350 entry->effect = IT_PORTAMENTO_DOWN;
351 if (version == PSMV_OLD) {
352 if (length < 4) entry->effectvalue = length | 0xF0;
353 else entry->effectvalue = length >> 2;
354 } else /*if (version == PSMV_NEW)*/ {
355 entry->effectvalue = length;
356 }
357 break;
358
359 case 15:
360 entry->effect = IT_TONE_PORTAMENTO;
361 if (version == PSMV_OLD) entry->effectvalue = length >> 2;
362 else /*if (version == PSMV_NEW)*/ entry->effectvalue = length;
363 break;
364
365 case 0x15:
366 entry->effect = IT_VIBRATO;
367 entry->effectvalue = length;
368 break;
369
370 case 0x18:
371 entry->effect = IT_VOLSLIDE_VIBRATO;
372 entry->effectvalue = length;
373 break;
374
375 case 0x29:
376 entry->effect = IT_SET_SAMPLE_OFFSET;
377 entry->effectvalue = data[pos+2];
378 pos += 2;
379 break;
380
381 case 0x2A:
382 entry->effect = IT_RETRIGGER_NOTE;
383 entry->effectvalue = length;
384 break;
385
386 case 0x33:
387 #if 0
388 entry->effect = IT_POSITION_JUMP;
389 entry->effectvalue = data[pos+2];
390 #else
391 entry->mask &= ~IT_ENTRY_EFFECT;
392 #endif
393 pos++;
394 break;
395
396 case 0x34:
397 entry->effect = IT_BREAK_TO_ROW;
398 entry->effectvalue = length;
399 break;
400
401 case 0x3D:
402 entry->effect = IT_SET_SPEED;
403 entry->effectvalue = length;
404 break;
405
406 case 0x3E:
407 if (length >= 0x20) {
408 entry->effect = IT_SET_SONG_TEMPO;
409 entry->effectvalue = length;
410 } else {
411 entry->mask &= ~IT_ENTRY_EFFECT;
412 }
413 break;
414
415 case 0x47:
416 entry->effect = IT_ARPEGGIO;
417 entry->effectvalue = length;
418 break;
419
420 default:
421 return -1;
422 }
423 pos += 2;
424 }
425 if (entry->mask) entry++;
426 }
427 }
428
429 while (row < nrows) {
430 IT_SET_END_ROW(entry);
431 entry++;
432 row++;
433 }
434
435 pattern->n_entries = entry - pattern->entry;
436 if (!pattern->n_entries) return -1;
437
438 return 0;
439 }
440
441
free_chunks(PSMCHUNK * chunk,int count)442 static void free_chunks(PSMCHUNK * chunk, int count) {
443 int n;
444
445 for (n = 0; n < count; n++) {
446 if (chunk[n].data)
447 free(chunk[n].data);
448 }
449
450 free(chunk);
451 }
452
453 static void dumb_it_optimize_orders(DUMB_IT_SIGDATA * sigdata);
454
455 static int pattcmp( const unsigned char *, const unsigned char *, size_t );
456
it_psm_load_sigdata(DUMBFILE * f,int * ver,int subsong)457 static DUMB_IT_SIGDATA *it_psm_load_sigdata(DUMBFILE *f, int * ver, int subsong)
458 {
459 DUMB_IT_SIGDATA *sigdata;
460
461 PSMCHUNK *chunk;
462 int n_chunks = 0;
463
464 PSMCHUNK *songchunk;
465 int n_song_chunks = 0;
466
467 PSMEVENT *event = 0;
468 int n_events = 0;
469
470 unsigned char * ptr;
471
472 int n, length, o;
473
474 int found;
475
476 int n_patterns = 0;
477
478 int first_pattern_line = -1;
479 int first_pattern;
480
481 int speed, bpm;
482 unsigned char pan[64];
483 int vol[32];
484
485 if (dumbfile_mgetl(f) != DUMB_ID('P','S','M',' ')) goto error;
486
487 length = dumbfile_igetl(f);
488
489 if (dumbfile_mgetl(f) != DUMB_ID('F','I','L','E')) goto error;
490
491 chunk = calloc(768, sizeof(*chunk));
492
493 while (length >= 8) {
494 chunk[n_chunks].id = dumbfile_mgetl(f);
495 n = dumbfile_igetl(f);
496 length -= 8;
497 if (n < 0 || n > length)
498 goto error_fc;
499 chunk[n_chunks].len = n;
500 if (n) {
501 ptr = malloc(n);
502 if (!ptr) goto error_fc;
503 if (dumbfile_getnc((char *)ptr, n, f) < n)
504 {
505 free(ptr);
506 goto error_fc;
507 }
508 chunk[n_chunks].data = ptr;
509 }
510 n_chunks++;
511 length -= n;
512 }
513
514 if (!n_chunks) goto error_fc;
515
516 sigdata = malloc(sizeof(*sigdata));
517 if (!sigdata) goto error_fc;
518
519 sigdata->n_patterns = 0;
520 sigdata->n_samples = 0;
521 sigdata->name[0] = 0;
522
523 found = 0;
524
525 for (n = 0; n < n_chunks; n++) {
526 PSMCHUNK * c = &chunk[n];
527 switch(c->id) {
528 case DUMB_ID('S','D','F','T'):
529 /* song data format? */
530 if ((found & 1) || (c->len != 8) || memcmp(c->data, "MAINSONG", 8)) goto error_sd;
531 found |= 1;
532 break;
533
534 case DUMB_ID('S','O','N','G'):
535 if (/*(found & 2) ||*/ (c->len < 11) /*|| memcmp(c->data, "MAINSONG", 8)*/) goto error_sd;
536 found |= 2;
537 break;
538
539 case DUMB_ID('D','S','M','P'):
540 sigdata->n_samples++;
541 break;
542
543 case DUMB_ID('T','I','T','L'):
544 length = min(sizeof(sigdata->name) - 1, (unsigned)c->len);
545 memcpy(sigdata->name, c->data, length);
546 sigdata->name[length] = 0;
547 }
548 }
549
550 if (found != 3 || !sigdata->n_samples) goto error_sd;
551
552 sigdata->song_message = NULL;
553 sigdata->order = NULL;
554 sigdata->instrument = NULL;
555 sigdata->sample = NULL;
556 sigdata->pattern = NULL;
557 sigdata->midi = NULL;
558 sigdata->checkpoint = NULL;
559
560 sigdata->n_instruments = 0;
561 sigdata->n_orders = 0;
562
563 for (n = 0; n < n_chunks; n++) {
564 PSMCHUNK * c = &chunk[n];
565 if (c->id == DUMB_ID('S','O','N','G')) {
566 if (subsong == 0) break;
567 subsong--;
568 }
569 }
570
571 if (n == n_chunks) return NULL;
572 subsong = n;
573
574 /*for (n = 0; n < n_chunks; n++) {
575 PSMCHUNK * c = &chunk[n];
576 if (c->id == DUMB_ID('S','O','N','G')) {*/
577 {
578 PSMCHUNK * c = &chunk[subsong];
579 {
580 ptr = c->data;
581 if (ptr[10] > 32) goto error_usd;
582 sigdata->n_pchannels = ptr[10];
583 length = c->len - 11;
584 ptr += 11;
585 songchunk = 0;
586 if (length >= 8) {
587 songchunk = malloc(128 * sizeof(*songchunk));
588 if (!songchunk) goto error_usd;
589 while (length >= 8) {
590 songchunk[n_song_chunks].id = DUMB_ID(ptr[0], ptr[1], ptr[2], ptr[3]);
591 n = ptr[4] | (ptr[5] << 8) | (ptr[6] << 16) | (ptr[7] << 24);
592 length -= 8;
593 if (n > length) goto error_sc;
594 songchunk[n_song_chunks].len = n;
595 songchunk[n_song_chunks].data = ptr + 8;
596 n_song_chunks++;
597 length -= n;
598 ptr += 8 + n;
599 }
600 }
601 /*break;*/
602 }
603 }
604
605 if (!n_song_chunks) goto error_sc;
606
607 found = 0;
608
609 for (n = 0; n < n_song_chunks; n++) {
610 PSMCHUNK * c = &songchunk[n];
611
612 if (c->id == DUMB_ID('D','A','T','E')) {
613 /* date of the library build / format spec */
614 if (c->len == 6) {
615 length = c->len;
616 ptr = c->data;
617 while (length > 0) {
618 if (*ptr >= '0' && *ptr <= '9') {
619 found = (found * 10) + (*ptr - '0');
620 } else {
621 found = 0;
622 break;
623 }
624 ptr++;
625 length--;
626 }
627 }
628 break;
629 }
630 }
631
632 /*
633 if (found != 940506 &&
634 found != 940509 &&
635 found != 940510 &&
636 found != 940530 &&
637 found != 940629 &&
638 found != PSMV_OLD &&
639 found != 941011 &&
640 found != PSMV_NEW &&
641 found != 940906 &&
642 found != 940903 &&
643 found != 940914 &&
644 found != 941213 &&
645 found != 800211) WTF?
646 goto error_sc;
647 */
648
649 *ver = found;
650
651 if (found == 800211 ||
652 found == PSMV_NEW ||
653 found == 940903 ||
654 found == 940906 ||
655 found == 940914 ||
656 found == 941213) found = PSMV_NEW;
657 else found = PSMV_OLD;
658
659 memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
660
661 for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) {
662 int sep = 32 * dumb_it_default_panning_separation / 100;
663 sigdata->channel_pan[n ] = 32 - sep;
664 sigdata->channel_pan[n+1] = 32 + sep;
665 sigdata->channel_pan[n+2] = 32 + sep;
666 sigdata->channel_pan[n+3] = 32 - sep;
667 }
668
669 for (n = 0; n < n_song_chunks; n++) {
670 PSMCHUNK * c = &songchunk[n];
671
672 switch (c->id) {
673 case DUMB_ID('O','P','L','H'):
674 if (c->len < 2) goto error_sc;
675 ptr = c->data;
676 o = ptr[0] | (ptr[1] << 8);
677 if (!o) goto error_sc;
678 event = malloc(o * sizeof(*event));
679 if (!event) goto error_sc;
680 length = c->len - 2;
681 ptr += 2;
682 while ((length > 0) && (n_events < o)) {
683 event[n_events].type = *ptr;
684 switch (*ptr) {
685 case PSM_EVENT_END:
686 ptr++;
687 length--;
688 break;
689
690 case PSM_EVENT_PLAY_PATTERN:
691 if (found == PSMV_OLD) {
692 if (length < 5) goto error_ev;
693 memcpy(event[n_events].data, ptr + 1, 4);
694 ptr += 5;
695 length -= 5;
696 } else /*if (found == PSMV_NEW)*/ {
697 if (length < 9) goto error_ev;
698 memcpy(event[n_events].data, ptr + 1, 8);
699 ptr += 9;
700 length -= 9;
701 }
702 break;
703
704 case PSM_EVENT_SET_SPEED:
705 case PSM_EVENT_SET_BPM:
706 if (length < 2) goto error_ev;
707 event[n_events].data[0] = ptr[1];
708 ptr += 2;
709 length -= 2;
710 break;
711
712 case PSM_EVENT_JUMP_TO_LINE:
713 case PSM_EVENT_CHANGE_VOL:
714 if (length < 3) goto error_ev;
715 memcpy(event[n_events].data, ptr + 1, 2);
716 ptr += 3;
717 length -= 3;
718 break;
719
720 case PSM_EVENT_SAMPLE_MAP_TABLE:
721 if (length < 7) goto error_ev;
722 memcpy(event[n_events].data, ptr + 1, 6);
723 ptr += 7;
724 length -= 7;
725 break;
726
727 case PSM_EVENT_CHANGE_PAN:
728 if (length < 4) goto error_ev;
729 memcpy(event[n_events].data, ptr + 1, 3);
730 ptr += 4;
731 length -= 4;
732 break;
733
734 default:
735 goto error_ev;
736 }
737 n_events++;
738 }
739 break;
740
741 case DUMB_ID('P','P','A','N'):
742 length = c->len;
743 if (length & 1) goto error_ev;
744 ptr = c->data;
745 o = 0;
746 while (length > 0) {
747 switch (ptr[0]) {
748 case 0:
749 sigdata->channel_pan[o] = ((((int)(signed char)ptr[1]) * 32) / 127) + 32;
750 break;
751 case 2:
752 sigdata->channel_pan[o] = IT_SURROUND;
753 break;
754 case 4:
755 sigdata->channel_pan[o] = 32;
756 break;
757 }
758 ptr += 2;
759 length -= 2;
760 if (++o >= DUMB_IT_N_CHANNELS) break;
761 }
762 break;
763
764 /*
765 case DUMB_ID('P','A','T','T'):
766 case DUMB_ID('D','S','A','M'):
767 */
768 }
769 }
770
771 sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX;
772
773 sigdata->global_volume = 128;
774 sigdata->speed = 6;
775 sigdata->tempo = 125;
776 sigdata->mixing_volume = 48;
777 sigdata->pan_separation = 128;
778
779 speed = 0;
780 bpm = 0;
781 memset(pan, 255, sizeof(pan));
782 memset(vol, 255, sizeof(vol));
783
784 sigdata->n_patterns = n_events;
785 sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
786 if (!sigdata->pattern) goto error_ev;
787 for (n = 0; n < sigdata->n_patterns; n++)
788 sigdata->pattern[n].entry = NULL;
789
790 for (n = 0; n < n_events; n++) {
791 PSMEVENT * e = &event[n];
792 switch (e->type) {
793 case PSM_EVENT_END:
794 n = n_events;
795 break;
796
797 case PSM_EVENT_PLAY_PATTERN:
798 for (o = 0; o < n_chunks; o++) {
799 PSMCHUNK * c = &chunk[o];
800 if (c->id == DUMB_ID('P','B','O','D')) {
801 ptr = c->data;
802 length = c->len;
803 if (found == PSMV_OLD) {
804 if (length < 8) goto error_ev;
805 if (!pattcmp(ptr + 4, e->data, 4)) {
806 if (it_psm_process_pattern(&sigdata->pattern[n_patterns], ptr, length, speed, bpm, pan, vol, found)) goto error_ev;
807 if (first_pattern_line < 0) {
808 first_pattern_line = n;
809 first_pattern = o;
810 }
811 e->data[0] = n_patterns;
812 e->data[1] = n_patterns >> 8;
813 n_patterns++;
814 break;
815 }
816 } else /*if (found == PSMV_NEW)*/ {
817 if (length < 12) goto error_ev;
818 if (!pattcmp(ptr + 4, e->data, 8)) {
819 if (it_psm_process_pattern(&sigdata->pattern[n_patterns], ptr, length, speed, bpm, pan, vol, found)) goto error_ev;
820 if (first_pattern_line < 0) {
821 first_pattern_line = n;
822 first_pattern = o;
823 }
824 e->data[0] = n_patterns;
825 e->data[1] = n_patterns >> 8;
826 n_patterns++;
827 break;
828 }
829 }
830 }
831 }
832 if (o == n_chunks) goto error_ev;
833
834 speed = 0;
835 bpm = 0;
836 memset(pan, 255, sizeof(pan));
837 memset(vol, 255, sizeof(vol));
838
839 e->type = PSM_EVENT_END;
840 break;
841
842 case PSM_EVENT_JUMP_TO_LINE:
843 o = e->data[0] | (e->data[1] << 8);
844 if (o >= n_events) goto error_ev;
845 if (o == 0) {
846 /* whew! easy case! */
847 sigdata->restart_position = 0;
848 n = n_events;
849 } else if (o == n) {
850 /* freeze */
851 n = n_events;
852 } else if (o > n) {
853 /* jump ahead, setting played event numbers to zero will prevent endless looping */
854 n = o - 1;
855 } else if (o >= first_pattern_line) {
856 /* another semi-easy case */
857 sigdata->restart_position = event[o].data[0] | (event[o].data[1] << 8);
858 n = n_events;
859 } else {
860 /* crud, try to simulate rerunning all of the commands from the indicated
861 * line up to the first pattern, then dupe the first pattern again.
862 */
863 /*
864 PSMCHUNK * c = &chunk[first_pattern];
865
866 for (; o < first_pattern_line; o++) {
867 PSMEVENT * ev = &event[o];
868 switch (ev->type) {
869 case PSM_EVENT_SET_SPEED:
870 speed = ev->data[0];
871 break;
872 case PSM_EVENT_SET_BPM:
873 bpm = ev->data[0];
874 break;
875 case PSM_EVENT_CHANGE_PAN:
876 if (ev->data[0] > 31) goto error_ev;
877 pan[ev->data[0] * 2] = ev->data[1];
878 pan[ev->data[0] * 2 + 1] = ev->data[2];
879 break;
880 case PSM_EVENT_CHANGE_VOL:
881 if (ev->data[0] > 31) goto error_ev;
882 vol[ev->data[0]] = ev->data[1];
883 break;
884 }
885 }
886
887 if (it_psm_process_pattern(&sigdata->pattern[n_patterns], c->data, c->len, speed, bpm, pan, vol, found)) goto error_ev;
888 n_patterns++;
889 sigdata->restart_position = 1;
890 n = n_events;
891
892 Eh, what the hell? PSM has no panning commands anyway.
893 */
894 sigdata->restart_position = 0;
895 n = n_events;
896 }
897 e->type = PSM_EVENT_END;
898 break;
899
900 case PSM_EVENT_SET_SPEED:
901 speed = e->data[0];
902 break;
903
904 case PSM_EVENT_SET_BPM:
905 bpm = e->data[0];
906 break;
907
908 case PSM_EVENT_CHANGE_PAN:
909 o = e->data[0];
910 if (o > 31) goto error_ev;
911 pan[o * 2] = e->data[1];
912 pan[o * 2 + 1] = e->data[2];
913 break;
914
915 case PSM_EVENT_CHANGE_VOL:
916 o = e->data[0];
917 if (o > 31) goto error_ev;
918 vol[o] = e->data[1];
919 break;
920
921 case PSM_EVENT_SAMPLE_MAP_TABLE:
922 if (e->data[0] != 0 || e->data[1] != 0xFF ||
923 e->data[2] != 0 || e->data[3] != 0 ||
924 e->data[4] != 1 || e->data[5] != 0)
925 goto error_ev;
926 break;
927 }
928 }
929
930 if (n_patterns > 256) goto error_ev;
931
932 sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
933 if (!sigdata->sample) goto error_ev;
934 for (n = 0; n < sigdata->n_samples; n++) {
935 sigdata->sample[n].data = NULL;
936 sigdata->sample[n].flags = 0;
937 }
938
939 o = 0;
940 for (n = 0; n < n_chunks; n++) {
941 PSMCHUNK * c = &chunk[n];
942 if (c->id == DUMB_ID('D','S','M','P')) {
943 if (it_psm_process_sample(&sigdata->sample[o], c->data, c->len, o, found)) goto error_ev;
944 o++;
945 }
946 }
947
948 sigdata->n_orders = n_patterns;
949 sigdata->n_patterns = n_patterns;
950
951 sigdata->order = malloc(n_patterns);
952
953 for (n = 0; n < n_patterns; n++) {
954 sigdata->order[n] = n;
955 }
956
957 free(event);
958 free(songchunk);
959 free_chunks(chunk, n_chunks);
960
961 _dumb_it_fix_invalid_orders(sigdata);
962
963 dumb_it_optimize_orders(sigdata);
964
965 return sigdata;
966
967 error_ev:
968 free(event);
969 error_sc:
970 if (songchunk) free(songchunk);
971 error_usd:
972 _dumb_it_unload_sigdata(sigdata);
973 goto error_fc;
974 error_sd:
975 free(sigdata);
976 error_fc:
977 free_chunks(chunk, n_chunks);
978 error:
979 return NULL;
980 }
981
it_order_compare(const void * e1,const void * e2)982 static int it_order_compare(const void *e1, const void *e2) {
983 if (*((const char *)e1) < *((const char *)e2))
984 return -1;
985
986 if (*((const char *)e1) > *((const char *)e2))
987 return 1;
988
989 return 0;
990 }
991
992 /*
993 static int it_optimize_compare(const void *e1, const void *e2) {
994 if (((const IT_ENTRY *)e1)->channel < ((const IT_ENTRY *)e2)->channel)
995 return -1;
996
997 if (((const IT_ENTRY *)e1)->channel > ((const IT_ENTRY *)e2)->channel)
998 return 1;
999
1000 return 0;
1001 }
1002 */
1003
it_entry_compare(const IT_ENTRY * e1,const IT_ENTRY * e2)1004 static int it_entry_compare(const IT_ENTRY * e1, const IT_ENTRY * e2) {
1005 if (IT_IS_END_ROW(e1) && IT_IS_END_ROW(e2)) return 1;
1006 if (e1->channel != e2->channel) return 0;
1007 if (e1->mask != e2->mask) return 0;
1008 if ((e1->mask & IT_ENTRY_NOTE) && (e1->note != e2->note)) return 0;
1009 if ((e1->mask & IT_ENTRY_INSTRUMENT) && (e1->instrument != e2->instrument)) return 0;
1010 if ((e1->mask & IT_ENTRY_VOLPAN) && (e1->volpan != e2->volpan)) return 0;
1011 if ((e1->mask & IT_ENTRY_EFFECT) && ((e1->effect != e2->effect) || (e1->effectvalue != e2->effectvalue))) return 0;
1012 return 1;
1013 }
1014
1015 /*
1016 static void dumb_it_optimize_pattern(IT_PATTERN * pattern) {
1017 IT_ENTRY * entry, * end;
1018 IT_ENTRY * rowstart, * rowend;
1019 IT_ENTRY * current;
1020
1021 if (!pattern->n_entries || !pattern->entry) return;
1022
1023 current = entry = pattern->entry;
1024 end = entry + pattern->n_entries;
1025
1026 while (entry < end) {
1027 rowstart = entry;
1028 while (!IT_IS_END_ROW(entry)) entry++;
1029 rowend = entry;
1030 if (rowend > rowstart + 1)
1031 qsort(rowstart, rowend - rowstart, sizeof(IT_ENTRY), &it_optimize_compare);
1032 entry = rowstart;
1033 while (entry < rowend) {
1034 if (!(entry->mask)) {}
1035 else if (it_entry_compare(entry, current)) {}
1036 else if (!(current->mask) ||
1037 ((entry->channel == current->channel) &&
1038 ((entry->mask | current->mask) == (entry->mask ^ current->mask)))) {
1039 current->mask |= entry->mask;
1040 if (entry->mask & IT_ENTRY_NOTE) current->note = entry->note;
1041 if (entry->mask & IT_ENTRY_INSTRUMENT) current->instrument = entry->instrument;
1042 if (entry->mask & IT_ENTRY_VOLPAN) current->volpan = entry->volpan;
1043 if (entry->mask & IT_ENTRY_EFFECT) {
1044 current->effect = entry->effect;
1045 current->effectvalue = entry->effectvalue;
1046 }
1047 } else {
1048 if (++current < entry) *current = *entry;
1049 }
1050 entry++;
1051 }
1052 if (++current < entry) *current = *entry;
1053 entry++;
1054 }
1055
1056 current++;
1057
1058 if (current < end) {
1059 IT_ENTRY * opt;
1060 pattern->n_entries = current - pattern->entry;
1061 opt = realloc(pattern->entry, pattern->n_entries * sizeof(*pattern->entry));
1062 if (opt) pattern->entry = opt;
1063 }
1064 }
1065 */
1066
it_pattern_compare(const IT_PATTERN * p1,const IT_PATTERN * p2)1067 static int it_pattern_compare(const IT_PATTERN * p1, const IT_PATTERN * p2) {
1068 IT_ENTRY * e1, * end;
1069 IT_ENTRY * e2;
1070
1071 if (p1 == p2) return 1;
1072 if (p1->n_entries != p2->n_entries) return 0;
1073
1074 e1 = p1->entry; end = e1 + p1->n_entries;
1075 e2 = p2->entry;
1076
1077 while (e1 < end) {
1078 if (!it_entry_compare(e1, e2)) return 0;
1079 e1++; e2++;
1080 }
1081
1082 return 1;
1083 }
1084
dumb_it_optimize_orders(DUMB_IT_SIGDATA * sigdata)1085 static void dumb_it_optimize_orders(DUMB_IT_SIGDATA * sigdata) {
1086 int n, o, p;
1087
1088 /*int last_invalid = (sigdata->flags & IT_WAS_AN_XM) ? 255 : 253;*/
1089
1090 unsigned char * order_list;
1091 int n_patterns;
1092
1093 IT_PATTERN * pattern;
1094
1095 if (!sigdata->n_orders || !sigdata->n_patterns) return;
1096
1097 n_patterns = 0;
1098 order_list = malloc(sigdata->n_orders);
1099
1100 if (!order_list) return;
1101
1102 for (n = 0; n < sigdata->n_orders; n++) {
1103 if (sigdata->order[n] < sigdata->n_patterns) {
1104 for (o = 0; o < n_patterns; o++) {
1105 if (sigdata->order[n] == order_list[o]) break;
1106 }
1107 if (o == n_patterns) {
1108 order_list[n_patterns++] = sigdata->order[n];
1109 }
1110 }
1111 }
1112
1113 if (!n_patterns) {
1114 free(order_list);
1115 return;
1116 }
1117
1118 /*for (n = 0; n < n_patterns; n++) {
1119 dumb_it_optimize_pattern(&sigdata->pattern[order_list[n]]);
1120 }*/
1121
1122 for (n = 0; n < n_patterns; n++) {
1123 for (o = n + 1; o < n_patterns; o++) {
1124 if ((order_list[n] != order_list[o]) &&
1125 it_pattern_compare(&sigdata->pattern[order_list[n]], &sigdata->pattern[order_list[o]])) {
1126 for (p = 0; p < sigdata->n_orders; p++) {
1127 if (sigdata->order[p] == order_list[o]) {
1128 sigdata->order[p] = order_list[n];
1129 }
1130 }
1131 for (p = o + 1; p < n_patterns; p++) {
1132 if (order_list[p] == order_list[o]) {
1133 order_list[p] = order_list[n];
1134 }
1135 }
1136 order_list[o] = order_list[n];
1137 }
1138 }
1139 }
1140
1141 qsort(order_list, n_patterns, sizeof(*order_list), &it_order_compare);
1142
1143 for (n = 0, o = 0; n < n_patterns; n++) {
1144 if (order_list[n] != order_list[o]) {
1145 if (++o < n) order_list[o] = order_list[n];
1146 }
1147 }
1148
1149 n_patterns = o + 1;
1150
1151 pattern = malloc(n_patterns * sizeof(*pattern));
1152 if (!pattern) {
1153 free(order_list);
1154 return;
1155 }
1156
1157 for (n = 0; n < n_patterns; n++) {
1158 pattern[n] = sigdata->pattern[order_list[n]];
1159 }
1160
1161 for (n = 0; n < sigdata->n_patterns; n++) {
1162 for (o = 0; o < n_patterns; o++) {
1163 if (order_list[o] == n) break;
1164 }
1165 if (o == n_patterns) {
1166 if (sigdata->pattern[n].entry)
1167 free(sigdata->pattern[n].entry);
1168 }
1169 }
1170
1171 free(sigdata->pattern);
1172 sigdata->pattern = pattern;
1173 sigdata->n_patterns = n_patterns;
1174
1175 for (n = 0; n < sigdata->n_orders; n++) {
1176 for (o = 0; o < n_patterns; o++) {
1177 if (sigdata->order[n] == order_list[o]) {
1178 sigdata->order[n] = o;
1179 break;
1180 }
1181 }
1182 }
1183
1184 free(order_list);
1185 }
1186
dumb_get_psm_subsong_count(DUMBFILE * f)1187 int dumb_get_psm_subsong_count(DUMBFILE *f) {
1188 int length, subsongs;
1189 long l;
1190
1191 if (dumbfile_mgetl(f) != DUMB_ID('P','S','M',' ')) return 0;
1192
1193 length = dumbfile_igetl(f);
1194
1195 if (dumbfile_mgetl(f) != DUMB_ID('F','I','L','E')) return 0;
1196
1197 subsongs = 0;
1198
1199 while (length >= 8 && !dumbfile_error(f)) {
1200 if (dumbfile_mgetl(f) == DUMB_ID('S','O','N','G')) subsongs++;
1201 l = dumbfile_igetl(f);
1202 dumbfile_skip(f, l);
1203 length -= l + 8;
1204 }
1205
1206 if (dumbfile_error(f)) return 0;
1207
1208 return subsongs;
1209 }
1210
1211
1212
1213 /* Eww */
pattcmp(const unsigned char * a,const unsigned char * b,size_t l)1214 int pattcmp( const unsigned char * a, const unsigned char * b, size_t l )
1215 {
1216 size_t i, j, na, nb;
1217 char * p;
1218
1219 na = nb = 0;
1220
1221 i = memcmp( a, b, l );
1222 if ( !i ) return i;
1223
1224 /* damnit */
1225
1226 for ( i = 0; i < l; ++i )
1227 {
1228 if ( a [i] >= '0' && a [i] <= '9' ) break;
1229 }
1230
1231 if ( i < l )
1232 {
1233 na = strtoul( (const char *)a + i, &p, 10 );
1234 if ( (const unsigned char *)p == a + i ) return 1;
1235 }
1236
1237 for ( j = 0; j < l; ++j )
1238 {
1239 if ( b [j] >= '0' && b [j] <= '9' ) break;
1240 }
1241
1242 if ( j < l )
1243 {
1244 nb = strtoul( (const char *)b + j, &p, 10 );
1245 if ( (const unsigned char *)p == b + j ) return -1;
1246 }
1247
1248 if ( i < j ) return -1;
1249 else if ( i > j ) return 1;
1250
1251 i = memcmp( a, b, j );
1252 if ( i ) return i;
1253
1254 return na - nb;
1255 }
1256
1257
1258
dumb_read_psm_quick(DUMBFILE * f,int subsong)1259 DUH *dumb_read_psm_quick(DUMBFILE *f, int subsong)
1260 {
1261 sigdata_t *sigdata;
1262 int ver;
1263
1264 DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
1265
1266 sigdata = it_psm_load_sigdata(f, &ver, subsong);
1267
1268 if (!sigdata)
1269 return NULL;
1270
1271 {
1272 int n_tags = 2;
1273 char version[16];
1274 const char *tag[3][2];
1275 tag[0][0] = "TITLE";
1276 tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
1277 tag[1][0] = "FORMAT";
1278 tag[1][1] = "PSM";
1279 if ( ver )
1280 {
1281 tag[2][0] = "FORMATVERSION";
1282 snprintf( version, 15, "%d", ver );
1283 version[15] = 0;
1284 tag[2][1] = (const char *) &version;
1285 ++n_tags;
1286 }
1287 return make_duh(-1, n_tags, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
1288 }
1289 }
1290