1 /*  _______         ____    __         ___    ___
2  * \    _  \       \    /  \  /       \   \  /   /       '   '  '
3  *  |  | \  \       |  |    ||         |   \/   |         .      .
4  *  |  |  |  |      |  |    ||         ||\  /|  |
5  *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
6  *  |  |  |  |      |  |    ||         ||    |  |         .      .
7  *  |  |_/  /        \  \__//          ||    |  |
8  * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
9  *                                                      /  \
10  *                                                     / .  \
11  * readpsm.c - Code to read an old Protracker         / / \  \
12  *             Studio module from an open file.      | <  /   \_
13  *                                                   |  \/ /\   /
14  * By Chris Moeller.                                  \_  /  > /
15  *                                                      | \ / /
16  *                                                      |  ' /
17  *                                                       \__/
18  */
19 
20 #include <stdlib.h>
21 #include <string.h>
22 #include <math.h>
23 
24 #include "dumb.h"
25 #include "internal/it.h"
26 
psm_sample_compare(const void * e1,const void * e2)27 static int psm_sample_compare(const void *e1, const void *e2)
28 {
29 	const unsigned char * pa = e1;
30 	const unsigned char * pb = e2;
31 	int a = pa[37] | (pa[38] << 8) | (pa[39] << 16) | (pa[40] << 24);
32 	int b = pb[37] | (pb[38] << 8) | (pb[39] << 16) | (pb[40] << 24);
33 	return a - b;
34 }
35 
it_old_psm_read_samples(IT_SAMPLE ** sample,DUMBFILE * f,int * num)36 static int it_old_psm_read_samples(IT_SAMPLE ** sample, DUMBFILE * f, int * num)
37 {
38     int n, o, count = *num, true_num, snum, offset, flags, finetune, delta;
39 
40     unsigned char * buffer;
41 	const unsigned char * sdata;
42     long sample_bytes;
43 
44 	buffer = malloc(count * 64);
45 	if (!buffer) goto error;
46 
47     if (dumbfile_getnc((char *)buffer, count * 64, f) < count * 64) goto error_fb;
48 
49 	true_num = 0;
50 
51 	for (n = 0; n < count; n++) {
52 		snum = buffer[(n * 64) + 45] | (buffer[(n * 64) + 46] << 8);
53 		if ((snum < 1) || (snum > 255)) goto error_fb;
54 		if (true_num < snum) true_num = snum;
55 	}
56 
57 	if (true_num > count) {
58 		IT_SAMPLE * meh = realloc(*sample, true_num * sizeof(*meh));
59 		if (!meh) goto error_fb;
60 		for (n = count; n < true_num; n++) {
61 			meh[n].data = NULL;
62 		}
63 		*sample = meh;
64 		*num = true_num;
65 	}
66 
67 	qsort(buffer, count, 64, &psm_sample_compare);
68 
69 	for (n = 0; n < true_num; n++) {
70 		(*sample)[n].flags = 0;
71 	}
72 
73 	for (n = 0; n < count; n++) {
74 		IT_SAMPLE * s;
75 		snum = buffer[(n * 64) + 45] | (buffer[(n * 64) + 46] << 8);
76 		s = &((*sample)[snum - 1]);
77 		memcpy(s->filename, buffer + (n * 64), 13);
78 		s->filename[13] = 0;
79 		memcpy(s->name, buffer + (n * 64) + 13, 24);
80 		s->name[24] = 0;
81 		offset = buffer[(n * 64) + 37] | (buffer[(n * 64) + 38] << 8) |
82 				 (buffer[(n * 64) + 39] << 16) | (buffer[(n * 64) + 40] << 24);
83 		flags = buffer[(n * 64) + 47];
84 		s->length = buffer[(n * 64) + 48] | (buffer[(n * 64) + 49] << 8) |
85 					(buffer[(n * 64) + 50] << 16) | (buffer[(n * 64) + 51] << 24);
86 		s->loop_start = buffer[(n * 64) + 52] | (buffer[(n * 64) + 53] << 8) |
87 						(buffer[(n * 64) + 54] << 16) | (buffer[(n * 64) + 55] << 24);
88 		s->loop_end = buffer[(n * 64) + 56] | (buffer[(n * 64) + 57] << 8) |
89 					  (buffer[(n * 64) + 58] << 16) | (buffer[(n * 64) + 59] << 24);
90 
91 		if (s->length <= 0) continue;
92 
93 		finetune = buffer[(n * 64) + 60];
94 		s->default_volume = buffer[(n * 64) + 61];
95 		s->C5_speed = buffer[(n * 64) + 62] | (buffer[(n * 64) + 63] << 8);
96 		if (finetune & 15) {
97 			finetune &= 15;
98 			if (finetune >= 8) finetune -= 16;
99 			//s->C5_speed = (long)((double)s->C5_speed * pow(DUMB_PITCH_BASE, finetune*32));
100 			s->finetune = finetune * 32;
101 		}
102 		else s->finetune = 0;
103 
104 		s->flags |= IT_SAMPLE_EXISTS;
105 		if (flags & 0x41) {
106 			s->flags &= ~IT_SAMPLE_EXISTS;
107 			continue;
108 		}
109 		if (flags & 0x20) s->flags |= IT_SAMPLE_PINGPONG_LOOP;
110 		if (flags & 4) s->flags |= IT_SAMPLE_16BIT;
111 
112 		if (flags & 0x80) {
113 			s->flags |= IT_SAMPLE_LOOP;
114 			if ((unsigned int)s->loop_end > (unsigned int)s->length)
115 				s->loop_end = s->length;
116 			else if ((unsigned int)s->loop_start >= (unsigned int)s->loop_end)
117 				s->flags &= ~IT_SAMPLE_LOOP;
118 			else
119 				s->length = s->loop_end;
120 		}
121 
122 		s->global_volume = 64;
123 
124 		s->vibrato_speed = 0;
125 		s->vibrato_depth = 0;
126 		s->vibrato_rate = 0;
127 		s->vibrato_waveform = IT_VIBRATO_SINE;
128 		s->max_resampling_quality = -1;
129 
130         sample_bytes = s->length * ((flags & 4) ? 2 : 1);
131         s->data = malloc(sample_bytes);
132 		if (!s->data) goto error_fb;
133 
134         if (dumbfile_seek(f, offset, DFS_SEEK_SET) || dumbfile_getnc(s->data, sample_bytes, f) < sample_bytes) goto error_fb;
135         sdata = ( const unsigned char * ) s->data;
136 
137 		if (flags & 0x10) {
138 			if (flags & 8) {
139 				if (flags & 4) {
140 					for (o = 0; o < s->length; o++)
141 						((short *)s->data)[o] = (sdata[o * 2] | (sdata[(o * 2) + 1] << 8)) ^ 0x8000;
142 				} else {
143 					for (o = 0; o < s->length; o++)
144 						((signed char *)s->data)[o] = sdata[o] ^ 0x80;
145 				}
146 			} else {
147 				if (flags & 4) {
148 					for (o = 0; o < s->length; o++)
149 						((short *)s->data)[o] = sdata[o * 2] | (sdata[(o * 2) + 1] << 8);
150 				} else {
151 					memcpy(s->data, sdata, s->length);
152 				}
153 			}
154 		} else {
155 			delta = 0;
156 			if (flags & 8) {
157 				/* unsigned delta? mehhh, does anything even use this? */
158 				if (flags & 4) {
159 					for (o = 0; o < s->length; o++) {
160 						delta += (short)(sdata[o * 2] | (sdata[(o * 2) + 1] << 8));
161 						((short *)s->data)[o] = delta ^ 0x8000;
162 					}
163 				} else {
164 					for (o = 0; o < s->length; o++) {
165 						delta += (signed char)sdata[o];
166 						((signed char *)s->data)[o] = delta ^ 0x80;
167 					}
168 				}
169 			} else {
170 				if (flags & 4) {
171 					for (o = 0; o < s->length; o++) {
172 						delta += (signed short)(sdata[o * 2] | (sdata[(o * 2) + 1] << 8));
173 						((signed short *)s->data)[o] = delta;
174 					}
175 				} else {
176 					for (o = 0; o < s->length; o++) {
177 						delta += (signed char)sdata[o];
178 						((signed char *)s->data)[o] = delta;
179 					}
180 				}
181 			}
182 		}
183 	}
184 
185 	free(buffer);
186 
187 	return 0;
188 
189 error_fb:
190 	free(buffer);
191 error:
192 	return -1;
193 }
194 
it_old_psm_read_patterns(IT_PATTERN * pattern,DUMBFILE * f,int num,int size,int pchans)195 static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num, int size, int pchans)
196 {
197 	int n, offset, psize, rows, chans, row, flags, channel;
198 
199 	unsigned char * buffer, * ptr, * end;
200 
201 	IT_ENTRY * entry;
202 
203 	buffer = malloc(size);
204 	if (!buffer) goto error;
205 
206     if (dumbfile_getnc((char *)buffer, size, f) < size) goto error_fb;
207 
208 	offset = 0;
209 
210 	for (n = 0; n < num; n++) {
211 		IT_PATTERN * p = &pattern[n];
212 
213 		if (offset >= size) goto error_fb;
214 
215 		ptr = buffer + offset;
216 		psize = ptr[0] | (ptr[1] << 8);
217 		rows = ptr[2];
218 		chans = ptr[3];
219 
220 		if (!rows || !chans) {
221 			p->n_rows = 1;
222 			p->n_entries = 0;
223 			continue;
224 		}
225 
226 		psize = (psize + 15) & ~15;
227 
228 		end = ptr + psize;
229 		ptr += 4;
230 
231 		p->n_rows = rows;
232 		p->n_entries = rows;
233 		row = 0;
234 
235 		while ((row < rows) && (ptr < end)) {
236 			flags = *ptr++;
237 			if (!flags) {
238 				row++;
239 				continue;
240 			}
241 			if (flags & 0xE0) {
242 				p->n_entries++;
243 				if (flags & 0x80) ptr += 2;
244 				if (flags & 0x40) ptr++;
245 				if (flags & 0x20) {
246 					ptr++;
247 					if (*ptr == 40) ptr += 3;
248 					else ptr++;
249 				}
250 			}
251 		}
252 
253 		entry = malloc(p->n_entries * sizeof(*p->entry));
254 		if (!entry) goto error_fb;
255 
256 		p->entry = entry;
257 
258 		ptr = buffer + offset + 4;
259 		row = 0;
260 
261 		while ((row < rows) && (ptr < end)) {
262 			flags = *ptr++;
263 			if (!flags) {
264 				IT_SET_END_ROW(entry);
265 				entry++;
266 				row++;
267 				continue;
268 			}
269 			if (flags & 0xE0) {
270 				entry->mask = 0;
271 				entry->channel = channel = flags & 0x1F;
272 				if (channel >= chans)
273 				{
274 					//channel = 0;
275 					//goto error_fb;
276 				}
277 				if (flags & 0x80) {
278 					if ((*ptr < 60) && (channel < pchans)) {
279 						entry->mask |= IT_ENTRY_NOTE;
280 						entry->note = *ptr + 35;
281 					}
282 					ptr++;
283 					if (*ptr) {
284 						entry->mask |= IT_ENTRY_INSTRUMENT;
285 						entry->instrument = *ptr;
286 					}
287 					ptr++;
288 				}
289 				if (flags & 0x40) {
290 					if (*ptr <= 64) {
291 						entry->mask |= IT_ENTRY_VOLPAN;
292 						entry->volpan = *ptr;
293 					}
294 					ptr++;
295 				}
296 				if (flags & 0x20) {
297 					entry->mask |= IT_ENTRY_EFFECT;
298 
299 					switch (*ptr) {
300 						case 1:
301 							entry->effect = IT_XM_FINE_VOLSLIDE_UP;
302 							entry->effectvalue = ptr[1];
303 							break;
304 
305 						case 2:
306 							entry->effect = IT_VOLUME_SLIDE;
307 							entry->effectvalue = (ptr[1] << 4) & 0xF0;
308 							break;
309 
310 						case 3:
311 							entry->effect = IT_XM_FINE_VOLSLIDE_DOWN;
312 							entry->effectvalue = ptr[1];
313 							break;
314 
315 						case 4:
316 							entry->effect = IT_VOLUME_SLIDE;
317 							entry->effectvalue = ptr[1] & 0xF;
318 							break;
319 
320 						case 10:
321 							entry->effect = IT_PORTAMENTO_UP;
322 							entry->effectvalue = EFFECT_VALUE(0xF, ptr[1]);
323 							break;
324 
325 						case 11:
326 							entry->effect = IT_PORTAMENTO_UP;
327 							entry->effectvalue = ptr[1];
328 							break;
329 
330 						case 12:
331 							entry->effect = IT_PORTAMENTO_DOWN;
332 							entry->effectvalue = EFFECT_VALUE(ptr[1], 0xF);
333 							break;
334 
335 						case 13:
336 							entry->effect = IT_PORTAMENTO_DOWN;
337 							entry->effectvalue = ptr[1];
338 							break;
339 
340 						case 14:
341 							entry->effect = IT_TONE_PORTAMENTO;
342 							entry->effectvalue = ptr[1];
343 							break;
344 
345 						case 15:
346 							entry->effect = IT_S;
347 							entry->effectvalue = EFFECT_VALUE(IT_S_SET_GLISSANDO_CONTROL, ptr[1] & 15);
348 							break;
349 
350 						case 16:
351 							entry->effect = IT_VOLSLIDE_TONEPORTA;
352 							entry->effectvalue = ptr[1] << 4;
353 							break;
354 
355 						case 17:
356 							entry->effect = IT_VOLSLIDE_TONEPORTA;
357 							entry->effectvalue = ptr[1] & 0xF;
358 							break;
359 
360 						case 20:
361 							entry->effect = IT_VIBRATO;
362 							entry->effectvalue = ptr[1];
363 							break;
364 
365 						case 21:
366 							entry->effect = IT_S;
367 							entry->effectvalue = EFFECT_VALUE(IT_S_SET_VIBRATO_WAVEFORM, ptr[1] & 11);
368 							break;
369 
370 						case 22:
371 							entry->effect = IT_VOLSLIDE_VIBRATO;
372 							entry->effectvalue = ptr[1] << 4;
373 							break;
374 
375 						case 23:
376 							entry->effect = IT_VOLSLIDE_VIBRATO;
377 							entry->effectvalue = ptr[1] & 0xF;
378 							break;
379 
380 						case 30:
381 							entry->effect = IT_TREMOLO;
382 							entry->effectvalue = ptr[1];
383 							break;
384 
385 						case 31:
386 							entry->effect = IT_S;
387 							entry->effectvalue = EFFECT_VALUE(IT_S_SET_TREMOLO_WAVEFORM, ptr[1] & 11);
388 							break;
389 
390 						case 40:
391 							entry->effect = IT_SET_SAMPLE_OFFSET;
392 							entry->effectvalue = ptr[2];
393 							ptr += 2;
394 							break;
395 
396 						case 41:
397 							entry->effect = IT_XM_RETRIGGER_NOTE;
398 							entry->effectvalue = ptr[1];
399 							break;
400 
401 						case 42:
402 							entry->effect = IT_S;
403 							entry->effectvalue = EFFECT_VALUE(IT_S_DELAYED_NOTE_CUT, ptr[1] & 0xF);
404 							break;
405 
406 						case 43:
407 							entry->effect = IT_S;
408 							entry->effectvalue = EFFECT_VALUE(IT_S_NOTE_DELAY, ptr[1] & 0xF);
409 							break;
410 
411 						case 50:
412 							entry->effect = IT_JUMP_TO_ORDER;
413 							entry->effectvalue = ptr[1];
414 							break;
415 
416 						case 51:
417 							entry->effect = IT_BREAK_TO_ROW;
418 							entry->effectvalue = ptr[1];
419 							break;
420 
421 						case 52:
422 							entry->effect = IT_S;
423 							entry->effectvalue = EFFECT_VALUE(IT_S_PATTERN_LOOP, ptr[1] & 0xF);
424 							break;
425 
426 						case 53:
427 							entry->effect = IT_S;
428 							entry->effectvalue = EFFECT_VALUE(IT_S_PATTERN_DELAY, ptr[1] & 0xF);
429 							break;
430 
431 						case 60:
432 							entry->effect = IT_SET_SPEED;
433 							entry->effectvalue = ptr[1];
434 							break;
435 
436 						case 61:
437 							entry->effect = IT_SET_SONG_TEMPO;
438 							entry->effectvalue = ptr[1];
439 							break;
440 
441 						case 70:
442 							entry->effect = IT_ARPEGGIO;
443 							entry->effectvalue = ptr[1];
444 							break;
445 
446 						case 71:
447 							entry->effect = IT_S;
448 							entry->effectvalue = EFFECT_VALUE(IT_S_FINETUNE, ptr[1] & 0xF);
449 							break;
450 
451 						case 72:
452 							/* "balance" ... panning? */
453 							entry->effect = IT_SET_PANNING;
454 							entry->effectvalue = ((ptr[1] - ((ptr[1] & 8) >> 3)) << 5) / 7;
455 							break;
456 
457 						default:
458 							entry->mask &= ~IT_ENTRY_EFFECT;
459 					}
460 
461 					ptr += 2;
462 				}
463 				if (entry->mask) entry++;
464 			}
465 		}
466 
467 		p->n_entries = (int)(entry - p->entry);
468 		offset += psize;
469 	}
470 
471 	free(buffer);
472 
473 	return 0;
474 
475 error_fb:
476 	free(buffer);
477 error:
478 	return -1;
479 }
480 
481 #define PSM_COMPONENT_ORDERS            0
482 #define PSM_COMPONENT_PANPOS            1
483 #define PSM_COMPONENT_PATTERNS          2
484 #define PSM_COMPONENT_SAMPLE_HEADERS    3
485 #define PSM_COMPONENT_COMMENTS          4
486 
487 typedef struct PSM_COMPONENT
488 {
489 	unsigned char type;
490 	long offset;
491 }
492 PSM_COMPONENT;
493 
psm_component_compare(const void * e1,const void * e2)494 static int psm_component_compare(const void *e1, const void *e2)
495 {
496 	return (int)(((const PSM_COMPONENT *)e1)->offset -
497 	             ((const PSM_COMPONENT *)e2)->offset);
498 }
499 
it_old_psm_load_sigdata(DUMBFILE * f)500 static DUMB_IT_SIGDATA *it_old_psm_load_sigdata(DUMBFILE *f)
501 {
502 	DUMB_IT_SIGDATA *sigdata;
503 
504 	PSM_COMPONENT *component;
505 	int n_components = 0;
506 
507 	int n, flags, version, pver, n_orders, n_channels, total_pattern_size;
508 
509 	if (dumbfile_mgetl(f) != DUMB_ID('P','S','M',254)) goto error;
510 
511 	sigdata = malloc(sizeof(*sigdata));
512 	if (!sigdata) goto error;
513 
514     if (dumbfile_getnc((char *)sigdata->name, 60, f) < 60 ||
515 		sigdata->name[59] != 0x1A) goto error_sd;
516 	sigdata->name[59] = 0;
517 
518 	flags = dumbfile_getc(f);
519 	version = dumbfile_getc(f);
520 	pver = dumbfile_getc(f);
521 	sigdata->speed = dumbfile_getc(f);
522 	sigdata->tempo = dumbfile_getc(f);
523 	sigdata->mixing_volume = dumbfile_getc(f);
524 	sigdata->n_orders = dumbfile_igetw(f);
525 	n_orders = dumbfile_igetw(f);
526 	sigdata->n_patterns = dumbfile_igetw(f);
527 	sigdata->n_samples = dumbfile_igetw(f);
528 	sigdata->n_pchannels = dumbfile_igetw(f);
529 	n_channels = dumbfile_igetw(f);
530 
531 	if (dumbfile_error(f) ||
532 		(flags & 1) ||
533 		(version != 1 && version != 0x10) ||
534 		(pver) ||
535 		(sigdata->n_orders <= 0) ||
536 		(sigdata->n_orders > 255) ||
537 		(n_orders > 255) ||
538 		(n_orders < sigdata->n_orders) ||
539 		(sigdata->n_patterns > 255) ||
540 		(sigdata->n_samples > 255) ||
541 		(sigdata->n_pchannels > DUMB_IT_N_CHANNELS) ||
542 		(sigdata->n_pchannels > n_channels) ||
543 		(n_channels > DUMB_IT_N_CHANNELS))
544 		goto error_sd;
545 
546 	sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX;
547 
548 	sigdata->global_volume = 128;
549 	sigdata->pan_separation = 128;
550 
551 	sigdata->song_message = NULL;
552 	sigdata->order = NULL;
553 	sigdata->instrument = NULL;
554 	sigdata->sample = NULL;
555 	sigdata->pattern = NULL;
556 	sigdata->midi = NULL;
557 	sigdata->checkpoint = NULL;
558 
559 	sigdata->n_instruments = 0;
560 
561 	sigdata->restart_position = 0;
562 
563 	sigdata->order = malloc(sigdata->n_orders);
564 	if (!sigdata->order) goto error_usd;
565 
566 	if (sigdata->n_samples) {
567 		sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
568 		if (!sigdata->sample) goto error_usd;
569 		for (n = 0; n < sigdata->n_samples; n++)
570 			sigdata->sample[n].data = NULL;
571 	}
572 
573 	if (sigdata->n_patterns) {
574 		sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
575 		if (!sigdata->pattern) goto error_usd;
576 		for (n = 0; n < sigdata->n_patterns; n++)
577 			sigdata->pattern[n].entry = NULL;
578 	}
579 
580 	component = malloc(5 * sizeof(*component));
581 	if (!component) goto error_usd;
582 
583 	for (n = 0; n < 5; n++) {
584 		component[n_components].offset = dumbfile_igetl(f);
585 		if (component[n_components].offset) {
586 			component[n_components].type = n;
587 			n_components++;
588 		}
589 	}
590 
591 	if (!n_components) goto error_fc;
592 
593 	total_pattern_size = (int)dumbfile_igetl(f);
594 	if (!total_pattern_size) goto error_fc;
595 
596 	qsort(component, n_components, sizeof(PSM_COMPONENT), &psm_component_compare);
597 
598 	memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
599 
600 	for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) {
601 		int sep = 32 * dumb_it_default_panning_separation / 100;
602 		sigdata->channel_pan[n  ] = 32 - sep;
603 		sigdata->channel_pan[n+1] = 32 + sep;
604 		sigdata->channel_pan[n+2] = 32 + sep;
605 		sigdata->channel_pan[n+3] = 32 - sep;
606 	}
607 
608 	for (n = 0; n < n_components; n++)
609 	{
610 		int o;
611 
612         if ( dumbfile_seek(f, component[n].offset, DFS_SEEK_SET) ) goto error_fc;
613 
614 		switch (component[n].type) {
615 
616 			case PSM_COMPONENT_ORDERS:
617                 if (dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f) < sigdata->n_orders) goto error_fc;
618 				if (n_orders > sigdata->n_orders)
619 					if (dumbfile_skip(f, n_orders - sigdata->n_orders))
620                         goto error_fc;
621                 if (dumbfile_igetw(f)) goto error_fc;
622 				break;
623 
624 			case PSM_COMPONENT_PANPOS:
625                 if (dumbfile_getnc((char *)sigdata->channel_pan, sigdata->n_pchannels, f) < sigdata->n_pchannels) goto error_fc;
626 				for (o = 0; o < sigdata->n_pchannels; o++) {
627 					sigdata->channel_pan[o] -= (sigdata->channel_pan[o] & 8) >> 3;
628 					sigdata->channel_pan[o] = ((int)sigdata->channel_pan[o] << 5) / 7;
629 				}
630 				break;
631 
632 			case PSM_COMPONENT_PATTERNS:
633                 if (it_old_psm_read_patterns(sigdata->pattern, f, sigdata->n_patterns, total_pattern_size, sigdata->n_pchannels)) goto error_fc;
634 				break;
635 
636 			case PSM_COMPONENT_SAMPLE_HEADERS:
637                 if (it_old_psm_read_samples(&sigdata->sample, f, &sigdata->n_samples)) goto error_fc;
638 				break;
639 
640 			case PSM_COMPONENT_COMMENTS:
641 				if (dumbfile_mgetl(f) == DUMB_ID('T','E','X','T')) {
642 					o = dumbfile_igetw(f);
643 					if (o > 0) {
644 						sigdata->song_message = malloc(o + 1);
645                         if (dumbfile_getnc((char *)sigdata->song_message, o, f) < o) goto error_fc;
646 						sigdata->song_message[o] = 0;
647 					}
648 				}
649 				break;
650 		}
651 	}
652 
653 	_dumb_it_fix_invalid_orders(sigdata);
654 
655 	free(component);
656 
657 	return sigdata;
658 
659 error_fc:
660 	free(component);
661 error_usd:
662 	_dumb_it_unload_sigdata(sigdata);
663 	return NULL;
664 error_sd:
665 	free(sigdata);
666 error:
667 	return NULL;
668 }
669 
dumb_read_old_psm_quick(DUMBFILE * f)670 DUH *dumb_read_old_psm_quick(DUMBFILE *f)
671 {
672 	sigdata_t *sigdata;
673 
674 	DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
675 
676 	sigdata = it_old_psm_load_sigdata(f);
677 
678 	if (!sigdata)
679 		return NULL;
680 
681 	{
682 		const char *tag[2][2];
683 		tag[0][0] = "TITLE";
684         tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
685 		tag[1][0] = "FORMAT";
686 		tag[1][1] = "PSM (old)";
687 		return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
688 	}
689 }
690