static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f) { DUMB_IT_SIGDATA *sigdata; unsigned n_channels; unsigned i, j, k, l; IFF_CHUNKED *mod; const IFF_CHUNK *chunk; char signature[8]; if (dumbfile_getnc(signature, 8, f) < 8 || memcmp(signature, "OKTASONG", 8)) { return NULL; } mod = dumbfile_read_okt(f); if (!mod) return NULL; sigdata = (DUMB_IT_SIGDATA *) malloc(sizeof(*sigdata)); if (!sigdata) { free_okt(mod); return NULL; } sigdata->name[0] = 0; chunk = get_chunk_by_type(mod, DUMB_ID('S','P','E','E'), 0); if (!chunk || chunk->size < 2) { free(sigdata); free_okt(mod); return NULL; } sigdata->speed = (chunk->data[0] << 8) | chunk->data[1]; chunk = get_chunk_by_type(mod, DUMB_ID('S','A','M','P'), 0); if (!chunk || chunk->size < 32) { free(sigdata); free_okt(mod); return NULL; } sigdata->n_samples = chunk->size / 32; chunk = get_chunk_by_type(mod, DUMB_ID('C','M','O','D'), 0); if (!chunk || chunk->size < 8) { free(sigdata); free_okt(mod); return NULL; } n_channels = 0; for (i = 0; i < 4; i++) { j = (chunk->data[i * 2] << 8) | chunk->data[i * 2 + 1]; if (!j) n_channels++; else if (j == 1) n_channels += 2; } if (!n_channels) { free(sigdata); free_okt(mod); return NULL; } sigdata->n_pchannels = n_channels; sigdata->sample = (IT_SAMPLE *) malloc(sigdata->n_samples * sizeof(*sigdata->sample)); if (!sigdata->sample) { free(sigdata); free_okt(mod); return NULL; } sigdata->song_message = NULL; sigdata->order = NULL; sigdata->instrument = NULL; sigdata->pattern = NULL; sigdata->midi = NULL; sigdata->checkpoint = NULL; sigdata->n_instruments = 0; for (i = 0; i < (unsigned)sigdata->n_samples; i++) sigdata->sample[i].data = NULL; chunk = get_chunk_by_type(mod, DUMB_ID('S','A','M','P'), 0); for (i = 0; i < (unsigned)sigdata->n_samples; i++) { it_okt_read_sample_header(&sigdata->sample[i], chunk->data + 32 * i); } sigdata->restart_position = 0; chunk = get_chunk_by_type(mod, DUMB_ID('P','L','E','N'), 0); if (!chunk || chunk->size < 2) { _dumb_it_unload_sigdata(sigdata); free_okt(mod); return NULL; } sigdata->n_orders = (chunk->data[0] << 8) | chunk->data[1]; // what if this is > 128? if (sigdata->n_orders <= 0 || sigdata->n_orders > 128) { _dumb_it_unload_sigdata(sigdata); free_okt(mod); return NULL; } chunk = get_chunk_by_type(mod, DUMB_ID('P','A','T','T'), 0); if (!chunk || chunk->size < (unsigned)sigdata->n_orders) { _dumb_it_unload_sigdata(sigdata); free_okt(mod); return NULL; } sigdata->order = (unsigned char *) malloc(sigdata->n_orders); if (!sigdata->order) { _dumb_it_unload_sigdata(sigdata); free_okt(mod); return NULL; } memcpy(sigdata->order, chunk->data, sigdata->n_orders); /* Work out how many patterns there are. */ chunk = get_chunk_by_type(mod, DUMB_ID('S','L','E','N'), 0); if (!chunk || chunk->size < 2) { _dumb_it_unload_sigdata(sigdata); free_okt(mod); return NULL; } sigdata->n_patterns = (chunk->data[0] << 8) | chunk->data[1]; j = get_chunk_count(mod, DUMB_ID('P','B','O','D')); if (sigdata->n_patterns > (int)j) sigdata->n_patterns = (int)j; if (!sigdata->n_patterns) { _dumb_it_unload_sigdata(sigdata); free_okt(mod); return NULL; } sigdata->pattern = (IT_PATTERN *) malloc(sigdata->n_patterns * sizeof(*sigdata->pattern)); if (!sigdata->pattern) { _dumb_it_unload_sigdata(sigdata); free_okt(mod); return NULL; } for (i = 0; i < (unsigned)sigdata->n_patterns; i++) sigdata->pattern[i].entry = NULL; /* Read in the patterns */ for (i = 0; i < (unsigned)sigdata->n_patterns; i++) { chunk = get_chunk_by_type(mod, DUMB_ID('P','B','O','D'), i); if (it_okt_read_pattern(&sigdata->pattern[i], chunk->data, chunk->size, n_channels) != 0) { _dumb_it_unload_sigdata(sigdata); free_okt(mod); return NULL; } } /* And finally, the sample data */ k = get_chunk_count(mod, DUMB_ID('S','B','O','D')); for (i = 0, j = 0; i < (unsigned)sigdata->n_samples && j < k; i++) { if (sigdata->sample[i].flags & IT_SAMPLE_EXISTS) { chunk = get_chunk_by_type(mod, DUMB_ID('S','B','O','D'), j); if (it_okt_read_sample_data(&sigdata->sample[i], (const char *)chunk->data, chunk->size)) { _dumb_it_unload_sigdata(sigdata); free_okt(mod); return NULL; } j++; } } for (; i < (unsigned)sigdata->n_samples; i++) { sigdata->sample[i].flags = 0; } chunk = get_chunk_by_type(mod, DUMB_ID('C','M','O','D'), 0); for (i = 0, j = 0; i < n_channels && j < 4; j++) { k = (chunk->data[j * 2] << 8) | chunk->data[j * 2 + 1]; l = (j == 1 || j == 2) ? 48 : 16; if (k == 0) { sigdata->channel_pan[i++] = l; } else if (k == 1) { sigdata->channel_pan[i++] = l; sigdata->channel_pan[i++] = l; } } free_okt(mod); /* Now let's initialise the remaining variables, and we're done! */ sigdata->flags = IT_WAS_AN_OKT | IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO; sigdata->global_volume = 128; sigdata->mixing_volume = 48; /* We want 50 ticks per second; 50/6 row advances per second; * 50*10=500 row advances per minute; 500/4=125 beats per minute. */ sigdata->tempo = 125; sigdata->pan_separation = 128; memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS); memset(sigdata->channel_pan + n_channels, 32, DUMB_IT_N_CHANNELS - n_channels); _dumb_it_fix_invalid_orders(sigdata); return sigdata; }
static DUMB_IT_SIGDATA *it_asy_load_sigdata(DUMBFILE *f) { DUMB_IT_SIGDATA *sigdata; int i; static const char sig_part[] = "ASYLUM Music Format"; static const char sig_rest[] = " V1.0"; /* whee, string space optimization with format type below */ char signature[32]; if (dumbfile_getnc(signature, 32, f) != 32 || memcmp(signature, sig_part, 19) || memcmp(signature + 19, sig_rest, 5)) { return NULL; } sigdata = malloc(sizeof(*sigdata)); if (!sigdata) { return NULL; } sigdata->speed = dumbfile_getc(f); /* XXX seems to fit the files I have */ sigdata->tempo = dumbfile_getc(f); /* ditto */ sigdata->n_samples = dumbfile_getc(f); /* ditto */ sigdata->n_patterns = dumbfile_getc(f); sigdata->n_orders = dumbfile_getc(f); sigdata->restart_position = dumbfile_getc(f); if (dumbfile_error(f) || !sigdata->n_samples || sigdata->n_samples > 64 || !sigdata->n_patterns || !sigdata->n_orders) { free(sigdata); return NULL; } if (sigdata->restart_position > sigdata->n_orders) /* XXX */ sigdata->restart_position = 0; sigdata->order = malloc(sigdata->n_orders); if (!sigdata->order) { free(sigdata); return NULL; } if (dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f) != sigdata->n_orders || dumbfile_skip(f, 256 - sigdata->n_orders)) { free(sigdata->order); free(sigdata); return NULL; } sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample)); if (!sigdata->sample) { free(sigdata->order); free(sigdata); return NULL; } sigdata->song_message = NULL; sigdata->instrument = NULL; sigdata->pattern = NULL; sigdata->midi = NULL; sigdata->checkpoint = NULL; sigdata->n_instruments = 0; for (i = 0; i < sigdata->n_samples; ++i) sigdata->sample[i].data = NULL; for (i = 0; i < sigdata->n_samples; ++i) { if (it_asy_read_sample_header(&sigdata->sample[i], f)) { _dumb_it_unload_sigdata(sigdata); return NULL; } } if (dumbfile_skip(f, 37 * (64 - sigdata->n_samples))) { _dumb_it_unload_sigdata(sigdata); return NULL; } sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern)); if (!sigdata->pattern) { _dumb_it_unload_sigdata(sigdata); return NULL; } for (i = 0; i < sigdata->n_patterns; ++i) sigdata->pattern[i].entry = NULL; /* Read in the patterns */ { unsigned char *buffer = malloc(64 * 8 * 4); /* 64 rows * 8 channels * 4 bytes */ if (!buffer) { _dumb_it_unload_sigdata(sigdata); return NULL; } for (i = 0; i < sigdata->n_patterns; ++i) { if (it_asy_read_pattern(&sigdata->pattern[i], f, buffer) != 0) { free(buffer); _dumb_it_unload_sigdata(sigdata); return NULL; } } free(buffer); } /* And finally, the sample data */ for (i = 0; i < sigdata->n_samples; ++i) { if (it_asy_read_sample_data(&sigdata->sample[i], f)) { _dumb_it_unload_sigdata(sigdata); return NULL; } } /* Now let's initialise the remaining variables, and we're done! */ sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO; sigdata->global_volume = 128; sigdata->mixing_volume = 48; sigdata->pan_separation = 128; sigdata->n_pchannels = 8; sigdata->name[0] = 0; memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS); for (i = 0; i < DUMB_IT_N_CHANNELS; i += 4) { int sep = 32 * dumb_it_default_panning_separation / 100; sigdata->channel_pan[i + 0] = 32 - sep; sigdata->channel_pan[i + 1] = 32 + sep; sigdata->channel_pan[i + 2] = 32 + sep; sigdata->channel_pan[i + 3] = 32 - sep; } if (_dumb_it_fix_invalid_orders(sigdata) < 0) { _dumb_it_unload_sigdata(sigdata); return NULL; } return sigdata; }
static DUMB_IT_SIGDATA *it_riff_dsmf_load_sigdata( DUMBFILE * f, struct riff * stream ) { DUMB_IT_SIGDATA *sigdata; int n, o, found; if ( ! stream ) goto error; if ( stream->type != DUMB_ID( 'D', 'S', 'M', 'F' ) ) goto error; sigdata = malloc(sizeof(*sigdata)); if ( ! sigdata ) goto error; sigdata->n_patterns = 0; sigdata->n_samples = 0; sigdata->name[0] = 0; found = 0; for ( n = 0; (unsigned)n < stream->chunk_count; ++n ) { struct riff_chunk * c = stream->chunks + n; switch( c->type ) { case DUMB_ID( 'S' ,'O' ,'N' ,'G' ): /* initialization data */ if ( ( found ) || ( c->size < 192 ) ) goto error_sd; found = 1; break; case DUMB_ID( 'P', 'A', 'T', 'T' ): ++ sigdata->n_patterns; break; case DUMB_ID( 'I', 'N', 'S', 'T' ): ++ sigdata->n_samples; break; } } if ( !found || !sigdata->n_samples || !sigdata->n_patterns ) goto error_sd; if ( sigdata->n_samples > 255 || sigdata->n_patterns > 255 ) goto error_sd; sigdata->song_message = NULL; sigdata->order = NULL; sigdata->instrument = NULL; sigdata->sample = NULL; sigdata->pattern = NULL; sigdata->midi = NULL; sigdata->checkpoint = NULL; sigdata->mixing_volume = 48; sigdata->pan_separation = 128; sigdata->n_instruments = 0; sigdata->n_orders = 0; sigdata->restart_position = 0; memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS); for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) { int sep = 32 * dumb_it_default_panning_separation / 100; sigdata->channel_pan[n ] = 32 - sep; sigdata->channel_pan[n+1] = 32 + sep; sigdata->channel_pan[n+2] = 32 + sep; sigdata->channel_pan[n+3] = 32 - sep; } for ( n = 0; (unsigned)n < stream->chunk_count; ++n ) { struct riff_chunk * c = stream->chunks + n; switch ( c->type ) { case DUMB_ID( 'S', 'O', 'N', 'G' ): if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd; dumbfile_getnc( (char *) sigdata->name, 28, f ); sigdata->name[ 28 ] = 0; sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX; dumbfile_skip( f, 36 - 28 ); sigdata->n_orders = dumbfile_igetw( f ); //sigdata->n_samples = ptr[ 38 ] | ( ptr[ 39 ] << 8 ); // whatever //sigdata->n_patterns = ptr[ 40 ] | ( ptr[ 41 ] << 8 ); dumbfile_skip( f, 42 - 38 ); sigdata->n_pchannels = dumbfile_igetw( f ); sigdata->global_volume = dumbfile_getc( f ); sigdata->mixing_volume = dumbfile_getc( f ); sigdata->speed = dumbfile_getc( f ); sigdata->tempo = dumbfile_getc( f ); for ( o = 0; o < 16; ++o ) { sigdata->channel_pan[ o ] = dumbfile_getc( f ) / 2; } sigdata->order = malloc( 128 ); if ( ! sigdata->order ) goto error_usd; dumbfile_getnc( (char *) sigdata->order, 128, f ); break; } } sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) ); if ( ! sigdata->pattern ) goto error_usd; for ( n = 0; n < sigdata->n_patterns; ++n ) sigdata->pattern[ n ].entry = NULL; sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) ); if ( ! sigdata->sample ) goto error_usd; for ( n = 0; n < sigdata->n_samples; ++n ) { IT_SAMPLE * sample = sigdata->sample + n; sample->data = NULL; } sigdata->n_samples = 0; sigdata->n_patterns = 0; for ( n = 0; (unsigned)n < stream->chunk_count; ++n ) { struct riff_chunk * c = stream->chunks + n; switch ( c->type ) { case DUMB_ID( 'P', 'A', 'T', 'T' ): if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd; if ( it_riff_dsmf_process_pattern( sigdata->pattern + sigdata->n_patterns, f, c->size ) ) goto error_usd; ++ sigdata->n_patterns; break; case DUMB_ID( 'I', 'N', 'S', 'T' ): if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd; if ( it_riff_dsmf_process_sample( sigdata->sample + sigdata->n_samples, f, c->size ) ) goto error_usd; ++ sigdata->n_samples; break; } } _dumb_it_fix_invalid_orders( sigdata ); return sigdata; error_usd: _dumb_it_unload_sigdata( sigdata ); goto error; error_sd: free( sigdata ); error: return NULL; }
static DUMB_IT_SIGDATA *it_riff_dsmf_load_sigdata( struct riff * stream ) { DUMB_IT_SIGDATA *sigdata; int n, o, found; unsigned char * ptr; if ( ! stream ) goto error; if ( stream->type != DUMB_ID( 'D', 'S', 'M', 'F' ) ) goto error; sigdata = malloc(sizeof(*sigdata)); if ( ! sigdata ) goto error; sigdata->n_patterns = 0; sigdata->n_samples = 0; sigdata->name[0] = 0; found = 0; for ( n = 0; (unsigned int)n < stream->chunk_count; ++n ) { struct riff_chunk * c = stream->chunks + n; switch( c->type ) { case DUMB_ID( 'S' ,'O' ,'N' ,'G' ): /* initialization data */ if ( ( found ) || ( c->size < 192 ) ) goto error_sd; found = 1; break; case DUMB_ID( 'P', 'A', 'T', 'T' ): ++ sigdata->n_patterns; break; case DUMB_ID( 'I', 'N', 'S', 'T' ): ++ sigdata->n_samples; break; } } if ( !found || !sigdata->n_samples || !sigdata->n_patterns ) goto error_sd; if ( sigdata->n_samples > 255 || sigdata->n_patterns > 255 ) goto error_sd; sigdata->song_message = NULL; sigdata->order = NULL; sigdata->instrument = NULL; sigdata->sample = NULL; sigdata->pattern = NULL; sigdata->midi = NULL; sigdata->checkpoint = NULL; sigdata->mixing_volume = 48; sigdata->pan_separation = 128; sigdata->n_instruments = 0; sigdata->n_orders = 0; sigdata->restart_position = 0; memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS); for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) { sigdata->channel_pan[n ] = 16; sigdata->channel_pan[n+1] = 48; sigdata->channel_pan[n+2] = 48; sigdata->channel_pan[n+3] = 16; } for ( n = 0; (unsigned int)n < stream->chunk_count; ++n ) { struct riff_chunk * c = stream->chunks + n; switch ( c->type ) { case DUMB_ID( 'S', 'O', 'N', 'G' ): ptr = ( unsigned char * ) c->data; memcpy( sigdata->name, c->data, 28 ); sigdata->name[ 28 ] = 0; sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX; sigdata->n_orders = ptr[ 36 ] | ( ptr[ 37 ] << 8 ); //sigdata->n_samples = ptr[ 38 ] | ( ptr[ 39 ] << 8 ); // whatever //sigdata->n_patterns = ptr[ 40 ] | ( ptr[ 41 ] << 8 ); sigdata->n_pchannels = ptr[ 42 ] | ( ptr[ 43 ] << 8 ); sigdata->global_volume = ptr[ 44 ]; sigdata->mixing_volume = ptr[ 45 ]; sigdata->speed = ptr[ 46 ]; sigdata->tempo = ptr[ 47 ]; for ( o = 0; o < 16; ++o ) { sigdata->channel_pan[ o ] = ptr[ 48 + o ] / 2; } sigdata->order = malloc( 128 ); if ( ! sigdata->order ) goto error_usd; memcpy( sigdata->order, ptr + 64, 128 ); break; } } sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) ); if ( ! sigdata->pattern ) goto error_usd; for ( n = 0; n < sigdata->n_patterns; ++n ) sigdata->pattern[ n ].entry = NULL; sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) ); if ( ! sigdata->sample ) goto error_usd; for ( n = 0; n < sigdata->n_samples; ++n ) { IT_SAMPLE * sample = sigdata->sample + n; sample->data = NULL; } sigdata->n_samples = 0; sigdata->n_patterns = 0; for ( n = 0; (unsigned int)n < stream->chunk_count; ++n ) { struct riff_chunk * c = stream->chunks + n; switch ( c->type ) { case DUMB_ID( 'P', 'A', 'T', 'T' ): if ( it_riff_dsmf_process_pattern( sigdata->pattern + sigdata->n_patterns, ( unsigned char * ) c->data, c->size ) ) goto error_usd; ++ sigdata->n_patterns; break; case DUMB_ID( 'I', 'N', 'S', 'T' ): if ( it_riff_dsmf_process_sample( sigdata->sample + sigdata->n_samples, ( unsigned char * ) c->data, c->size ) ) goto error_usd; ++ sigdata->n_samples; break; } } _dumb_it_fix_invalid_orders( sigdata ); return sigdata; error_usd: _dumb_it_unload_sigdata( sigdata ); goto error; error_sd: free( sigdata ); error: return NULL; }