Exemple #1
0
    virtual alure::SharedPtr<alure::Decoder> createDecoder(alure::UniquePtr<std::istream> &file)
    {
        static const std::array<DUH*(*)(DUMBFILE*),3> init_funcs{{
            dumb_read_it, dumb_read_xm, dumb_read_s3m
        }};

        auto dfs = alure::MakeUnique<DUMBFILE_SYSTEM>();
        dfs->open = nullptr;
        dfs->skip = cb_skip;
        dfs->getc = cb_read_char;
        dfs->getnc = cb_read;
        dfs->close = nullptr;
        dfs->seek = cb_seek;
        dfs->get_size = cb_get_size;

        DUMBFILE *dfile = dumbfile_open_ex(file.get(), dfs.get());
        if(!dfile) return nullptr;

        ALuint freq = alure::Context::GetCurrent()->getDevice()->getFrequency();
        DUH_SIGRENDERER *renderer;
        DUH *duh;

        for(auto init : init_funcs)
        {
            if((duh=init(dfile)) != nullptr)
            {
                if((renderer=duh_start_sigrenderer(duh, 0, 2, 0)) != nullptr)
                    return alure::MakeShared<DumbDecoder>(
                        std::move(file), std::move(dfs), dfile, duh, renderer, freq
                    );

                unload_duh(duh);
                duh = nullptr;
            }

            dumbfile_seek(dfile, 0, SEEK_SET);
        }

        if((duh=dumb_read_mod(dfile, 1)) != nullptr)
        {
            if((renderer=duh_start_sigrenderer(duh, 0, 2, 0)) != nullptr)
                return alure::MakeShared<DumbDecoder>(
                    std::move(file), std::move(dfs), dfile, duh, renderer, freq
                );

            unload_duh(duh);
            duh = nullptr;
        }

        dumbfile_close(dfile);
        return nullptr;
    }
Exemple #2
0
static int it_riff_dsmf_process_pattern( IT_PATTERN * pattern, DUMBFILE * f, int len )
{
    int length, row;
    unsigned flags;
    long start, end;
    int p, q, r;
    IT_ENTRY * entry;

    length = dumbfile_igetw( f );
    if ( length > len ) return -1;

    len = length - 2;

    pattern->n_rows = 64;
    pattern->n_entries = 64;

    row = 0;

    start = dumbfile_pos( f );
    end = start + len;

    while ( (row < 64) && !dumbfile_error( f ) && (dumbfile_pos( f ) < end) ) {
        p = dumbfile_getc( f );
        if ( ! p ) {
            ++ row;
            continue;
        }

        flags = p & 0xF0;

        if (flags) {
            ++ pattern->n_entries;
            if (flags & 0x80) dumbfile_skip( f, 1 );
            if (flags & 0x40) dumbfile_skip( f, 1 );
            if (flags & 0x20) dumbfile_skip( f, 1 );
            if (flags & 0x10) dumbfile_skip( f, 2 );
        }
    }

    if ( pattern->n_entries == 64 ) return 0;

    pattern->entry = malloc( pattern->n_entries * sizeof( * pattern->entry ) );
    if ( ! pattern->entry ) return -1;

    entry = pattern->entry;

    row = 0;

    if ( dumbfile_seek( f, start, DFS_SEEK_SET ) ) return -1;

    while ( ( row < 64 ) && !dumbfile_error( f ) && ( dumbfile_pos( f ) < end ) )
    {
        p = dumbfile_getc( f );
        if ( ! p )
        {
            IT_SET_END_ROW( entry );
            ++ entry;
            ++ row;
            continue;
        }

        flags = p;
        entry->channel = flags & 0x0F;
        entry->mask = 0;

        if ( flags & 0xF0 )
        {
            if ( flags & 0x80 )
            {
                q = dumbfile_getc( f );
                if ( q )
                {
                    entry->mask |= IT_ENTRY_NOTE;
                    entry->note = q - 1;
                }
            }

            if ( flags & 0x40 )
            {
                q = dumbfile_getc( f );
                if ( q )
                {
                    entry->mask |= IT_ENTRY_INSTRUMENT;
                    entry->instrument = q;
                }
            }

            if ( flags & 0x20 )
            {
                entry->mask |= IT_ENTRY_VOLPAN;
                entry->volpan = dumbfile_getc( f );
            }

            if ( flags & 0x10 )
            {
                q = dumbfile_getc( f );
                r = dumbfile_getc( f );
                _dumb_it_xm_convert_effect( q, r, entry, 0 );
            }

            if (entry->mask) entry++;
        }
    }

    while ( row < 64 )
    {
        IT_SET_END_ROW( entry );
        ++ entry;
        ++ row;
    }

    pattern->n_entries = entry - pattern->entry;
    if ( ! pattern->n_entries ) return -1;

    return 0;
}
Exemple #3
0
struct riff *riff_parse(DUMBFILE *f, long offset, long size, unsigned proper) {
    unsigned stream_size;
    struct riff *stream;

    if (size < 8)
        return 0;

    if (dumbfile_seek(f, offset, DFS_SEEK_SET))
        return 0;
    if (dumbfile_mgetl(f) != DUMB_ID('R', 'I', 'F', 'F'))
        return 0;

    stream_size = (int)dumbfile_igetl(f);
    if (stream_size + 8 > size)
        return 0;
    if (stream_size < 4)
        return 0;

    stream = (struct riff *)malloc(sizeof(struct riff));
    if (!stream)
        return 0;

    stream->type = (int)dumbfile_mgetl(f);
    stream->chunk_count = 0;
    stream->chunks = 0;

    stream_size -= 4;

    while (stream_size && !dumbfile_error(f)) {
        struct riff_chunk *chunk;
        if (stream_size < 8)
            break;
        stream->chunks = (struct riff_chunk *)realloc(
            stream->chunks,
            (stream->chunk_count + 1) * sizeof(struct riff_chunk));
        if (!stream->chunks)
            break;
        chunk = stream->chunks + stream->chunk_count;
        chunk->type = (int)dumbfile_mgetl(f);
        chunk->size = (int)dumbfile_igetl(f);
        chunk->offset = dumbfile_pos(f);
        stream_size -= 8;
        if (stream_size < chunk->size)
            break;
        if (chunk->type == DUMB_ID('R', 'I', 'F', 'F')) {
            chunk->nested =
                riff_parse(f, chunk->offset - 8, chunk->size + 8, proper);
            if (!chunk->nested)
                break;
        } else {
            chunk->nested = 0;
        }
        dumbfile_seek(f, chunk->offset + chunk->size, DFS_SEEK_SET);
        stream_size -= chunk->size;
        if (proper && (chunk->size & 1)) {
            dumbfile_skip(f, 1);
            --stream_size;
        }
        ++stream->chunk_count;
    }

    if (stream_size) {
        riff_free(stream);
        stream = 0;
    }

    return stream;
}
Exemple #4
0
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;
}
Exemple #5
0
DUH *dumb_read_any_quick(DUMBFILE *f, int restrict_, int subsong) {
    unsigned char signature[maximum_signature_size];
    unsigned long signature_size;
    DUH *duh = NULL;

    /* signature_size = dumbfile_get_size(f); */

    signature_size =
        dumbfile_getnc((char *)signature, maximum_signature_size, f);
    dumbfile_seek(f, 0, DFS_SEEK_SET);

    if (signature_size >= 4 && signature[0] == 'I' && signature[1] == 'M' &&
        signature[2] == 'P' && signature[3] == 'M') {
        duh = dumb_read_it_quick(f);
    } else if (signature_size >= 17 &&
               !memcmp(signature, "Extended Module: ", 17)) {
        duh = dumb_read_xm_quick(f);
    } else if (signature_size >= 0x30 && signature[0x2C] == 'S' &&
               signature[0x2D] == 'C' && signature[0x2E] == 'R' &&
               signature[0x2F] == 'M') {
        duh = dumb_read_s3m_quick(f);
    } else if (signature_size >= 30 &&
               /*signature[28] == 0x1A &&*/ signature[29] == 2 &&
               (!strnicmp((const char *)signature + 20, "!Scream!", 8) ||
                !strnicmp((const char *)signature + 20, "BMOD2STM", 8) ||
                !strnicmp((const char *)signature + 20, "WUZAMOD!", 8))) {
        duh = dumb_read_stm_quick(f);
    } else if (signature_size >= 2 &&
               ((signature[0] == 0x69 && signature[1] == 0x66) ||
                (signature[0] == 0x4A && signature[1] == 0x4E))) {
        duh = dumb_read_669_quick(f);
    } else if (signature_size >= 0x30 && signature[0x2C] == 'P' &&
               signature[0x2D] == 'T' && signature[0x2E] == 'M' &&
               signature[0x2F] == 'F') {
        duh = dumb_read_ptm_quick(f);
    } else if (signature_size >= 4 && signature[0] == 'P' &&
               signature[1] == 'S' && signature[2] == 'M' &&
               signature[3] == ' ') {
        duh = dumb_read_psm_quick(f, subsong);
    } else if (signature_size >= 4 && signature[0] == 'P' &&
               signature[1] == 'S' && signature[2] == 'M' &&
               signature[3] == 254) {
        duh = dumb_read_old_psm_quick(f);
    } else if (signature_size >= 3 && signature[0] == 'M' &&
               signature[1] == 'T' && signature[2] == 'M') {
        duh = dumb_read_mtm_quick(f);
    } else if (signature_size >= 4 && signature[0] == 'R' &&
               signature[1] == 'I' && signature[2] == 'F' &&
               signature[3] == 'F') {
        duh = dumb_read_riff_quick(f);
    } else if (signature_size >= 24 &&
               !memcmp(signature, "ASYLUM Music Format", 19) &&
               !memcmp(signature + 19, " V1.0", 5)) {
        duh = dumb_read_asy_quick(f);
    } else if (signature_size >= 3 && signature[0] == 'A' &&
               signature[1] == 'M' && signature[2] == 'F') {
        duh = dumb_read_amf_quick(f);
    } else if (signature_size >= 8 && !memcmp(signature, "OKTASONG", 8)) {
        duh = dumb_read_okt_quick(f);
    }

    if (!duh) {
        dumbfile_seek(f, 0, DFS_SEEK_SET);
        duh = dumb_read_mod_quick(f, restrict_);
    }

    return duh;
}