1 /*  _______         ____    __         ___    ___
2  * \    _  \       \    /  \  /       \   \  /   /       '   '  '
3  *  |  | \  \       |  |    ||         |   \/   |         .      .
4  *  |  |  |  |      |  |    ||         ||\  /|  |
5  *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
6  *  |  |  |  |      |  |    ||         ||    |  |         .      .
7  *  |  |_/  /        \  \__//          ||    |  |
8  * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
9  *                                                      /  \
10  *                                                     / .  \
11  * readamf.c - Code to read a DSMI AMF module from    / / \  \
12  *             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 
27 
28 
it_amf_process_track(IT_ENTRY * entry_table,unsigned char * track,int rows,int channels)29 static void it_amf_process_track( IT_ENTRY *entry_table, unsigned char *track, int rows, int channels )
30 {
31 	int last_instrument = 0;
32 	int tracksize = track[ 0 ] + ( track[ 1 ] << 8 ) + ( track[ 2 ] << 16 );
33 	track += 3;
34 	while ( tracksize-- ) {
35 		unsigned int row = track[ 0 ];
36 		unsigned int command = track[ 1 ];
37 		unsigned int argument = track[ 2 ];
38 		IT_ENTRY * entry = entry_table + row * channels;
39 		if ( row >= ( unsigned int ) rows ) break;
40 		if ( command < 0x7F ) {
41 			entry->mask |= IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT | IT_ENTRY_VOLPAN;
42 			entry->note = command;
43 			if ( ! entry->instrument ) entry->instrument = last_instrument;
44 			entry->volpan = argument;
45 		}
46 		else if ( command == 0x7F ) {
47 			signed char row_delta = ( signed char ) argument;
48 			int row_source = ( int ) row + ( int ) row_delta;
49 			if ( row_source >= 0 && row_source < ( int ) rows ) {
50 				*entry = entry_table[ row_source * channels ];
51 			}
52 		}
53 		else if ( command == 0x80 ) {
54 			entry->mask |= IT_ENTRY_INSTRUMENT;
55 			last_instrument = argument + 1;
56 			entry->instrument = last_instrument;
57 		}
58 		else if ( command == 0x83 ) {
59 			entry->mask |= IT_ENTRY_VOLPAN;
60 			entry->volpan = argument;
61 		}
62 		else {
63 			unsigned int effect = command & 0x7F;
64 			unsigned int effectvalue = argument;
65 			switch (effect) {
66 				case 0x01: effect = IT_SET_SPEED; break;
67 
68 				case 0x02: effect = IT_VOLUME_SLIDE;
69 				case 0x0A: if ( effect == 0x0A ) effect = IT_VOLSLIDE_TONEPORTA;
70 				case 0x0B: if ( effect == 0x0B ) effect = IT_VOLSLIDE_VIBRATO;
71 					if ( effectvalue & 0x80 ) effectvalue = ( -( signed char ) effectvalue ) & 0x0F;
72 					else effectvalue = ( effectvalue & 0x0F ) << 4;
73 					break;
74 
75 				case 0x04:
76 					if ( effectvalue & 0x80 ) {
77 						effect = IT_PORTAMENTO_UP;
78 						effectvalue = ( -( signed char ) effectvalue ) & 0x7F;
79 					}
80 					else {
81 						effect = IT_PORTAMENTO_DOWN;
82 					}
83 					break;
84 
85 				case 0x06: effect = IT_TONE_PORTAMENTO; break;
86 
87 				case 0x07: effect = IT_TREMOR; break;
88 
89 				case 0x08: effect = IT_ARPEGGIO; break;
90 
91 				case 0x09: effect = IT_VIBRATO; break;
92 
93 				case 0x0C: effect = IT_BREAK_TO_ROW; break;
94 
95 				case 0x0D: effect = IT_JUMP_TO_ORDER; break;
96 
97 				case 0x0F: effect = IT_RETRIGGER_NOTE; break;
98 
99 				case 0x10: effect = IT_SET_SAMPLE_OFFSET; break;
100 
101 				case 0x11:
102 					if ( effectvalue ) {
103 						effect = IT_VOLUME_SLIDE;
104 						if ( effectvalue & 0x80 )
105 							effectvalue = 0xF0 | ( ( -( signed char ) effectvalue ) & 0x0F );
106 						else
107 							effectvalue = 0x0F | ( ( effectvalue & 0x0F ) << 4 );
108 					}
109 					else
110 						effect = 0;
111 					break;
112 
113 				case 0x12:
114 				case 0x16:
115 					if ( effectvalue ) {
116 						int mask = ( effect == 0x16 ) ? 0xE0 : 0xF0;
117 						effect = ( effectvalue & 0x80 ) ? IT_PORTAMENTO_UP : IT_PORTAMENTO_DOWN;
118 						if ( effectvalue & 0x80 )
119 							effectvalue = mask | ( ( -( signed char ) effectvalue ) & 0x0F );
120 						else
121 							effectvalue = mask | ( effectvalue & 0x0F );
122                     }
123 					else
124 						effect = 0;
125 					break;
126 
127 				case 0x13:
128 					effect = IT_S;
129 					effectvalue = EFFECT_VALUE( IT_S_NOTE_DELAY, effectvalue & 0x0F );
130 					break;
131 
132 				case 0x14:
133 					effect = IT_S;
134 					effectvalue = EFFECT_VALUE( IT_S_DELAYED_NOTE_CUT, effectvalue & 0x0F );
135 					break;
136 
137 				case 0x15: effect = IT_SET_SONG_TEMPO; break;
138 
139 				case 0x17:
140 					effectvalue = ( effectvalue + 64 ) & 0x7F;
141 					if ( entry->mask & IT_ENTRY_EFFECT ) {
142 						if ( !( entry->mask & IT_ENTRY_VOLPAN ) ) {
143 							entry->mask |= IT_ENTRY_VOLPAN;
144 							entry->volpan = ( effectvalue / 2 ) + 128;
145 						}
146 						effect = 0;
147 					}
148 					else {
149 						effect = IT_SET_PANNING;
150 					}
151 					break;
152 
153 				default: effect = effectvalue = 0;
154 			}
155 			if ( effect ) {
156 				entry->mask |= IT_ENTRY_EFFECT;
157 				entry->effect = effect;
158 				entry->effectvalue = effectvalue;
159 			}
160 		}
161 		track += 3;
162 	}
163 }
164 
it_amf_process_pattern(IT_PATTERN * pattern,IT_ENTRY * entry_table,int rows,int channels)165 static int it_amf_process_pattern( IT_PATTERN *pattern, IT_ENTRY *entry_table, int rows, int channels )
166 {
167 	int i, j;
168 	int n_entries = rows;
169 	IT_ENTRY * entry;
170 
171 	pattern->n_rows = rows;
172 
173 	for ( i = 0, j = channels * rows; i < j; i++ ) {
174 		if ( entry_table[ i ].mask ) {
175 			n_entries++;
176 		}
177 	}
178 
179 	pattern->n_entries = n_entries;
180 
181 	pattern->entry = entry = malloc( n_entries * sizeof( IT_ENTRY ) );
182 	if ( !entry ) {
183 		return -1;
184 	}
185 
186 	for ( i = 0; i < rows; i++ ) {
187 		for ( j = 0; j < channels; j++ ) {
188 			if ( entry_table[ i * channels + j ].mask ) {
189 				*entry = entry_table[ i * channels + j ];
190 				entry->channel = j;
191 				entry++;
192 			}
193 		}
194 		IT_SET_END_ROW( entry );
195 		entry++;
196 	}
197 
198 	return 0;
199 }
200 
it_amf_read_sample_header(IT_SAMPLE * sample,DUMBFILE * f,int * offset,int ver)201 static int it_amf_read_sample_header( IT_SAMPLE *sample, DUMBFILE *f, int * offset, int ver )
202 {
203 	int exists;
204 
205 	exists = dumbfile_getc( f );
206 
207     dumbfile_getnc( (char *) sample->name, 32, f );
208 	sample->name[32] = 0;
209 
210     dumbfile_getnc( (char *) sample->filename, 13, f );
211 	sample->filename[13] = 0;
212 
213 	*offset = (int)dumbfile_igetl( f );
214 	sample->length = dumbfile_igetl( f );
215 	sample->C5_speed = dumbfile_igetw( f );
216 	sample->default_volume = dumbfile_getc( f );
217 	sample->global_volume = 64;
218 	if ( sample->default_volume > 64 ) sample->default_volume = 64;
219 
220 	if ( ver >= 11 ) {
221 		sample->loop_start = dumbfile_igetl( f );
222 		sample->loop_end = dumbfile_igetl( f );
223 	} else {
224 		sample->loop_start = dumbfile_igetw( f );
225 		sample->loop_end = sample->length;
226 	}
227 
228 	if ( sample->length <= 0 ) {
229 		sample->flags = 0;
230 		return 0;
231 	}
232 
233 	sample->flags = exists == 1 ? IT_SAMPLE_EXISTS : 0;
234 
235 	sample->default_pan = 0;
236 	sample->finetune = 0;
237 
238 	if ( sample->loop_end > sample->loop_start + 2 && sample->loop_end <= sample->length )
239 		sample->flags |= IT_SAMPLE_LOOP;
240 
241 	sample->vibrato_speed = 0;
242 	sample->vibrato_depth = 0;
243 	sample->vibrato_rate = 0;
244 	sample->vibrato_waveform = 0; // do we have to set _all_ these?
245 	sample->max_resampling_quality = -1;
246 
247 	return dumbfile_error(f);
248 }
249 
250 
251 
it_amf_read_sample_data(IT_SAMPLE * sample,DUMBFILE * f)252 static int it_amf_read_sample_data( IT_SAMPLE *sample, DUMBFILE *f )
253 {
254 	int i, read_length = 0;
255 
256 	sample->data = malloc( sample->length );
257 
258 	if ( !sample->data )
259 		return -1;
260 
261 	if ( sample->length )
262 		read_length = (int)dumbfile_getnc( sample->data, sample->length, f );
263 
264 	for ( i = 0; i < read_length; i++ ) {
265 		( ( signed char * ) sample->data )[ i ] ^= 0x80;
266 	}
267 
268 	for ( i = read_length; i < sample->length; i++ ) {
269 		( ( signed char * ) sample->data )[ i ] = 0;
270 	}
271 
272 	return 0; /* Sometimes the last sample is truncated :( */
273 }
274 
it_amf_load_sigdata(DUMBFILE * f,int * version)275 static DUMB_IT_SIGDATA *it_amf_load_sigdata(DUMBFILE *f, int * version)
276 {
277 	DUMB_IT_SIGDATA *sigdata;
278 	int i, j, ver, ntracks, realntracks, nchannels;
279 
280 	int maxsampleseekpos = 0;
281 	int sampleseekpos[256];
282 
283 	unsigned short *orderstotracks;
284 	unsigned short *trackmap;
285 	unsigned int tracksize[256];
286 
287 	unsigned char **track;
288 
289 	static const char sig[] = "AMF";
290 
291 	char signature [3];
292 
293 	if ( dumbfile_getnc( signature, 3, f ) != 3 ||
294 		memcmp( signature, sig, 3 ) ) {
295 		return NULL;
296 	}
297 
298 	*version = ver = dumbfile_getc( f );
299 	if ( ver < 10 || ver > 14) {
300 		return NULL;
301 	}
302 
303 	sigdata = malloc(sizeof(*sigdata));
304 	if (!sigdata) {
305 		return NULL;
306 	}
307 
308     dumbfile_getnc( (char *) sigdata->name, 32, f );
309 	sigdata->name[ 32 ] = 0;
310 	sigdata->n_samples = dumbfile_getc( f );
311 	sigdata->n_orders = dumbfile_getc( f );
312 	ntracks = dumbfile_igetw( f );
313 	nchannels = dumbfile_getc( f );
314 
315 	if ( dumbfile_error( f ) ||
316 		sigdata->n_samples < 1 || sigdata->n_samples > 255 ||
317 		sigdata->n_orders < 1 || sigdata->n_orders > 255 ||
318 		! ntracks ||
319 		nchannels < 1 || nchannels > 32 ) {
320 		free( sigdata );
321 		return NULL;
322 	}
323 
324     sigdata->n_pchannels = nchannels;
325 
326 	memset( sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS );
327 
328 	if ( ver >= 11 ) {
329 		int nchannels = ( ver >= 13 ) ? 32 : 16;
330 		for ( i = 0; i < nchannels; i++ ) {
331 			signed char panpos = dumbfile_getc( f );
332 			int pan = ( panpos + 64 ) / 2;
333 			if ( pan < 0 ) pan = 0;
334 			else if ( pan > 64 ) pan = IT_SURROUND;
335 			sigdata->channel_pan[ i ] = pan;
336 		}
337 	}
338 	else {
339 		int sep = 32 * dumb_it_default_panning_separation / 100;
340 		for ( i = 0; i < 16; i++ ) {
341 			sigdata->channel_pan[ i ] = ( dumbfile_getc( f ) & 1 ) ? 32 - sep : 32 + sep;
342 		}
343 	}
344 
345 	sigdata->tempo = 125;
346 	sigdata->speed = 6;
347 	if ( ver >= 13 ) {
348 		i = dumbfile_getc( f );
349 		if ( i >= 32 ) sigdata->tempo = i;
350 		i = dumbfile_getc( f );
351 		if ( i <= 32 ) sigdata->speed = i;
352 	}
353 
354 	sigdata->order = malloc( sigdata->n_orders );
355 	if ( !sigdata->order ) {
356 		free( sigdata );
357 		return NULL;
358 	}
359 
360 	orderstotracks = malloc( sigdata->n_orders * nchannels * sizeof( unsigned short ) );
361 	if ( !orderstotracks ) {
362 		free( sigdata->order );
363 		free( sigdata );
364 		return NULL;
365 	}
366 
367 	for ( i = 0; i < sigdata->n_orders; i++ ) {
368 		sigdata->order[ i ] = i;
369 		tracksize[ i ] = 64;
370 		if ( ver >= 14 ) {
371 			tracksize[ i ] = dumbfile_igetw( f );
372 		}
373 		for ( j = 0; j < nchannels; j++ ) {
374 			orderstotracks[ i * nchannels + j ] = dumbfile_igetw( f );
375 		}
376 	}
377 
378 	if ( dumbfile_error( f ) ) {
379 		free( orderstotracks );
380 		free( sigdata->order );
381 		free( sigdata );
382 		return NULL;
383 	}
384 
385 	sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) );
386 	if ( !sigdata->sample ) {
387 		free( orderstotracks );
388 		free( sigdata->order );
389 		free( sigdata );
390 		return NULL;
391 	}
392 
393 	sigdata->restart_position = 0;
394 
395 	sigdata->song_message = NULL;
396 	sigdata->instrument = NULL;
397 	sigdata->pattern = NULL;
398 	sigdata->midi = NULL;
399 	sigdata->checkpoint = NULL;
400 
401 	sigdata->n_instruments = 0;
402 
403 	for ( i = 0; i < sigdata->n_samples; ++i )
404 		sigdata->sample[i].data = NULL;
405 
406 	for ( i = 0; i < sigdata->n_samples; ++i ) {
407 		int offset;
408 		if ( it_amf_read_sample_header( &sigdata->sample[i], f, &offset, ver ) ) {
409 			goto error_ott;
410 		}
411 		sampleseekpos[ i ] = offset;
412 		if ( offset > maxsampleseekpos ) maxsampleseekpos = offset;
413 	}
414 
415 	sigdata->n_patterns = sigdata->n_orders;
416 
417 	sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) );
418 	if ( !sigdata->pattern ) {
419 		goto error_ott;
420 	}
421 	for (i = 0; i < sigdata->n_patterns; ++i)
422 		sigdata->pattern[i].entry = NULL;
423 
424 	trackmap = malloc( ntracks * sizeof( unsigned short ) );
425 	if ( !trackmap ) {
426 		goto error_ott;
427 	}
428 
429 	if ( dumbfile_getnc( ( char * ) trackmap, ntracks * sizeof( unsigned short ), f ) != (long)(ntracks * sizeof( unsigned short )) ) {
430 		goto error_tm;
431 	}
432 
433 	realntracks = 0;
434 
435 	for ( i = 0; i < ntracks; i++ ) {
436 		if ( trackmap[ i ] > realntracks ) realntracks = trackmap[ i ];
437 	}
438 
439 	track = calloc( realntracks, sizeof( unsigned char * ) );
440 	if ( !track ) {
441 		goto error_tm;
442 	}
443 
444 	for ( i = 0; i < realntracks; i++ ) {
445 		int tracksize = dumbfile_igetw( f );
446 		tracksize += dumbfile_getc( f ) << 16;
447 		track[ i ] = malloc( tracksize * 3 + 3 );
448 		if ( !track[ i ] ) {
449 			goto error_all;
450 		}
451 		track[ i ][ 0 ] = tracksize & 255;
452 		track[ i ][ 1 ] = ( tracksize >> 8 ) & 255;
453 		track[ i ][ 2 ] = ( tracksize >> 16 ) & 255;
454         if ( dumbfile_getnc( (char *) track[ i ] + 3, tracksize * 3, f ) != tracksize * 3 ) {
455 			goto error_all;
456 		}
457 	}
458 
459 	for ( i = 1; i <= maxsampleseekpos; i++ ) {
460 		for ( j = 0; j < sigdata->n_samples; j++ ) {
461 			if ( sampleseekpos[ j ] == i ) {
462 				if ( it_amf_read_sample_data( &sigdata->sample[ j ], f ) ) {
463 					goto error_all;
464 				}
465 				break;
466 			}
467 		}
468 	}
469 
470 	/* Process tracks into patterns */
471 	for ( i = 0; i < sigdata->n_patterns; i++ ) {
472 		IT_ENTRY * entry_table = calloc( tracksize[ i ] * nchannels, sizeof( IT_ENTRY ) );
473 		if ( !entry_table ) {
474 			goto error_all;
475 		}
476 		for ( j = 0; j < nchannels; j++ ) {
477 			int ntrack = orderstotracks[ i * nchannels + j ];
478 			if ( ntrack && ntrack <= ntracks ) {
479 				int realtrack = trackmap[ ntrack - 1 ];
480 				if ( realtrack ) {
481 					realtrack--;
482 					if ( realtrack < realntracks && track[ realtrack ] ) {
483 						it_amf_process_track( entry_table + j, track[ realtrack ], tracksize[ i ], nchannels );
484 					}
485 				}
486 			}
487 		}
488 		if ( it_amf_process_pattern( &sigdata->pattern[ i ], entry_table, tracksize[ i ], nchannels ) ) {
489 			free( entry_table );
490 			goto error_all;
491 		}
492 		free( entry_table );
493 	}
494 
495 	/* Now let's initialise the remaining variables, and we're done! */
496 	sigdata->flags = IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO | IT_WAS_AN_S3M;
497 
498 	sigdata->global_volume = 128;
499 	sigdata->mixing_volume = 48;
500 	sigdata->pan_separation = 128;
501 
502 	_dumb_it_fix_invalid_orders(sigdata);
503 
504 	for ( i = 0; i < realntracks; i++ ) {
505 		if ( track[ i ] ) {
506 			free( track[ i ] );
507 		}
508 	}
509 	free( track );
510 	free( trackmap );
511 	free( orderstotracks );
512 
513 	return sigdata;
514 
515 error_all:
516 	for ( i = 0; i < realntracks; i++ ) {
517 		if ( track[ i ] ) {
518 			free( track[ i ] );
519 		}
520 	}
521 	free( track );
522 error_tm:
523 	free( trackmap );
524 error_ott:
525 	free( orderstotracks );
526 	_dumb_it_unload_sigdata( sigdata );
527 	return NULL;
528 }
529 
530 
531 
dumb_read_amf_quick(DUMBFILE * f)532 DUH *dumb_read_amf_quick(DUMBFILE *f)
533 {
534 	sigdata_t *sigdata;
535 
536 	DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
537 
538 	int version;
539 
540 	sigdata = it_amf_load_sigdata(f, &version);
541 
542 	if (!sigdata)
543 		return NULL;
544 
545 	{
546 		const char *tag[2][2];
547 		char ver_string[14];
548 		tag[0][0] = "TITLE";
549         tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
550 		tag[1][0] = "FORMAT";
551 		memcpy( ver_string, "DSMI AMF v", 10 );
552 		ver_string[10] = '0' + version / 10;
553 		ver_string[11] = '.';
554 		ver_string[12] = '0' + version % 10;
555 		ver_string[13] = 0;
556 		tag[1][1] = ver_string;
557 		return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
558 	}
559 }
560