ref: db718382dfb187fbdaa16a9dd4904c073fb8004d
parent: 19527c25846226fe8d5479aaefc5bee0f3274d1a
author: Chris Moeller <[email protected]>
date: Mon Jan 11 04:02:15 EST 2010
{10/12/2009 11:53:02 AM~10/12/2009 11:53:04 AM}- Implemented DSMI AMF reader - Changed MO3 unpacker to use unmo3.dll - Version is now 0.9.9.5 git-tfs-id: [http://localhost:8080/tfs/DefaultCollection/]$/foobar2000/files/plugins.root;C348
--- a/dumb/include/dumb.h
+++ b/dumb/include/dumb.h
@@ -392,6 +392,7 @@
DUH *dumb_load_mtm(const char *filename);
DUH *dumb_load_riff(const char *filename);
DUH *dumb_load_asy(const char *filename);
+DUH *dumb_load_amf(const char *filename);
DUH *dumb_read_it(DUMBFILE *f);
DUH *dumb_read_xm(DUMBFILE *f);
@@ -405,6 +406,7 @@
DUH *dumb_read_mtm(DUMBFILE *f);
DUH *dumb_read_riff(DUMBFILE *f);
DUH *dumb_read_asy(DUMBFILE *f);
+DUH *dumb_read_amf(DUMBFILE *f);
DUH *dumb_load_it_quick(const char *filename);
DUH *dumb_load_xm_quick(const char *filename);
@@ -418,6 +420,7 @@
DUH *dumb_load_mtm_quick(const char *filename);
DUH *dumb_load_riff_quick(const char *filename);
DUH *dumb_load_asy_quick(const char *filename);
+DUH *dumb_load_amf_quick(const char *filename);
DUH *dumb_read_it_quick(DUMBFILE *f);
DUH *dumb_read_xm_quick(DUMBFILE *f);
@@ -431,6 +434,7 @@
DUH *dumb_read_mtm_quick(DUMBFILE *f);
DUH *dumb_read_riff_quick(DUMBFILE *f);
DUH *dumb_read_asy_quick(DUMBFILE *f);
+DUH *dumb_read_amf_quick(DUMBFILE *f);
long dumb_it_build_checkpoints(DUMB_IT_SIGDATA *sigdata, int startorder);
void dumb_it_do_initial_runthrough(DUH *duh);
--- /dev/null
+++ b/dumb/src/it/loadamf.c
@@ -1,0 +1,42 @@
+/* _______ ____ __ ___ ___
+ * \ _ \ \ / \ / \ \ / / ' ' '
+ * | | \ \ | | || | \/ | . .
+ * | | | | | | || ||\ /| |
+ * | | | | | | || || \/ | | ' ' '
+ * | | | | | | || || | | . .
+ * | |_/ / \ \__// || | |
+ * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
+ * / \
+ * / . \
+ * loadamf.c - Code to read a DSMI AMF module file, / / \ \
+ * opening and closing it for you. | < / \_
+ * | \/ /\ /
+ * \_ / > /
+ * By Chris Moeller. | \ / /
+ * | ' /
+ * \__/
+ */
+
+#include "dumb.h"
+#include "internal/it.h"
+
+
+
+/* dumb_load_amf_quick(): loads a AMF file into a DUH struct, returning a
+ * pointer to the DUH struct. When you have finished with it, you must
+ * pass the pointer to unload_duh() so that the memory can be freed.
+ */
+DUH *dumb_load_amf_quick(const char *filename)
+{
+ DUH *duh;
+ DUMBFILE *f = dumbfile_open(filename);
+
+ if (!f)
+ return NULL;
+
+ duh = dumb_read_amf_quick(f);
+
+ dumbfile_close(f);
+
+ return duh;
+}
--- /dev/null
+++ b/dumb/src/it/loadamf2.c
@@ -1,0 +1,34 @@
+/* _______ ____ __ ___ ___
+ * \ _ \ \ / \ / \ \ / / ' ' '
+ * | | \ \ | | || | \/ | . .
+ * | | | | | | || ||\ /| |
+ * | | | | | | || || \/ | | ' ' '
+ * | | | | | | || || | | . .
+ * | |_/ / \ \__// || | |
+ * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
+ * / \
+ * / . \
+ * loadamf2.c - Code to read a DSMI AMF module file, / / \ \
+ * opening and closing it for you, and | < / \_
+ * do an initial run-through. | \/ /\ /
+ * \_ / > /
+ * | \ / /
+ * By Chris Moeller. | ' /
+ * \__/
+ */
+
+#include "dumb.h"
+#include "internal/it.h"
+
+
+
+/* dumb_load_amf(): loads a AMF file into a DUH struct, returning a pointer
+ * to the DUH struct. When you have finished with it, you must pass the
+ * pointer to unload_duh() so that the memory can be freed.
+ */
+DUH *dumb_load_amf(const char *filename)
+{
+ DUH *duh = dumb_load_amf_quick(filename);
+ dumb_it_do_initial_runthrough(duh);
+ return duh;
+}
--- /dev/null
+++ b/dumb/src/it/readamf.c
@@ -1,0 +1,521 @@
+/* _______ ____ __ ___ ___
+ * \ _ \ \ / \ / \ \ / / ' ' '
+ * | | \ \ | | || | \/ | . .
+ * | | | | | | || ||\ /| |
+ * | | | | | | || || \/ | | ' ' '
+ * | | | | | | || || | | . .
+ * | |_/ / \ \__// || | |
+ * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
+ * / \
+ * / . \
+ * readamf.c - Code to read a DSMI AMF module from / / \ \
+ * an open file. | < / \_
+ * | \/ /\ /
+ * By Chris Moeller. \_ / > /
+ * | \ / /
+ * | ' /
+ * \__/
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "dumb.h"
+#include "internal/it.h"
+
+
+
+static void it_amf_process_track( IT_ENTRY *entry_table, unsigned char *track, int rows, int channels )
+{
+ int last_instrument = 0;
+ int tracksize = track[ 0 ] + ( track[ 1 ] << 8 ) + ( track[ 2 ] << 16 );
+ track += 3;
+ while ( tracksize-- ) {
+ unsigned int row = track[ 0 ];
+ unsigned int command = track[ 1 ];
+ unsigned int argument = track[ 2 ];
+ IT_ENTRY * entry = entry_table + row * channels;
+ if ( row >= ( unsigned int ) rows ) break;
+ if ( command < 0x7F ) {
+ entry->mask |= IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT | IT_ENTRY_VOLPAN;
+ entry->note = command;
+ if ( ! entry->instrument ) entry->instrument = last_instrument;
+ entry->volpan = argument;
+ }
+ else if ( command == 0x7F ) {
+ signed char row_delta = ( signed char ) argument;
+ int row_source = ( int ) row + ( int ) row_delta;
+ if ( row_source >= 0 && row_source < ( int ) rows ) {
+ *entry = entry_table[ row_source * channels ];
+ }
+ }
+ else if ( command == 0x80 ) {
+ entry->mask |= IT_ENTRY_INSTRUMENT;
+ last_instrument = argument + 1;
+ entry->instrument = last_instrument;
+ }
+ else if ( command == 0x83 ) {
+ entry->mask |= IT_ENTRY_VOLPAN;
+ entry->volpan = argument;
+ }
+ else {
+ unsigned int effect = command & 0x7F;
+ unsigned int effectvalue = argument;
+ switch (effect) {
+ case 0x01: effect = IT_SET_SPEED; break;
+
+ case 0x02: effect = IT_VOLUME_SLIDE;
+ case 0x0A: if ( effect == 0x0A ) effect = IT_VOLSLIDE_TONEPORTA;
+ case 0x0B: if ( effect == 0x0B ) effect = IT_VOLSLIDE_VIBRATO;
+ if ( effectvalue & 0x80 ) effectvalue = ( -( signed char ) effectvalue ) & 0x0F;
+ else effectvalue = ( effectvalue & 0x0F ) << 4;
+ break;
+
+ case 0x04: if ( effectvalue & 0x80 ) { effect = IT_PORTAMENTO_UP; effectvalue = ( -( signed char ) effectvalue ) & 0x7F; }
+ else { effect = IT_PORTAMENTO_DOWN; }
+ break;
+
+ case 0x06: effect = IT_TONE_PORTAMENTO; break;
+
+ case 0x07: effect = IT_TREMOR; break;
+
+ case 0x08: effect = IT_ARPEGGIO; break;
+
+ case 0x09: effect = IT_VIBRATO; break;
+
+ case 0x0C: effect = IT_BREAK_TO_ROW; break;
+
+ case 0x0D: effect = IT_JUMP_TO_ORDER; break;
+
+ case 0x0F: effect = IT_RETRIGGER_NOTE; break;
+
+ case 0x10: effect = IT_SET_SAMPLE_OFFSET; break;
+
+ case 0x11: if ( effectvalue ) { effect = IT_VOLUME_SLIDE;
+ if ( effectvalue & 0x80 ) effectvalue = 0xF0 | ( ( -( signed char ) effectvalue ) & 0x0F );
+ else effectvalue = 0x0F | ( ( effectvalue & 0x0F ) << 4 );
+ } else effect = 0;
+ break;
+
+ case 0x12:
+ case 0x16: if ( effectvalue ) { int mask = ( effect == 0x16 ) ? 0xE0 : 0xF0;
+ effect = ( effectvalue & 0x80 ) ? IT_PORTAMENTO_UP : IT_PORTAMENTO_DOWN;
+ if ( effectvalue & 0x80 ) effectvalue = mask | ( ( -( signed char ) effectvalue ) & 0x0F );
+ else effectvalue = mask | ( effectvalue & 0x0F );
+ } else effect = 0;
+ break;
+
+ case 0x13: effect = IT_S; effectvalue = EFFECT_VALUE( IT_S_NOTE_DELAY, effectvalue & 0x0F ); break;
+
+ case 0x14: effect = IT_S; effectvalue = EFFECT_VALUE( IT_S_DELAYED_NOTE_CUT, effectvalue & 0x0F ); break;
+
+ case 0x15: effect = IT_SET_SONG_TEMPO; break;
+
+ case 0x17: effectvalue = ( effectvalue + 64 ) & 0x7F;
+ if ( entry->mask & IT_ENTRY_EFFECT ) { if ( !( entry->mask & IT_ENTRY_VOLPAN ) ) { entry->volpan = ( effectvalue / 2 ) + 128; } effect = 0; }
+ else { effect = IT_SET_PANNING; }
+ break;
+
+ default: effect = effectvalue = 0;
+ }
+ if ( effect ) {
+ entry->mask |= IT_ENTRY_EFFECT;
+ entry->effect = effect;
+ entry->effectvalue = effectvalue;
+ }
+ }
+ track += 3;
+ }
+}
+
+static int it_amf_process_pattern( IT_PATTERN *pattern, IT_ENTRY *entry_table, int rows, int channels )
+{
+ int i, j;
+ int n_entries = rows;
+ IT_ENTRY * entry;
+
+ pattern->n_rows = rows;
+
+ for ( i = 0, j = channels * rows; i < j; i++ ) {
+ if ( entry_table[ i ].mask ) {
+ n_entries++;
+ }
+ }
+
+ pattern->n_entries = n_entries;
+
+ pattern->entry = entry = malloc( n_entries * sizeof( IT_ENTRY ) );
+ if ( !entry ) {
+ return -1;
+ }
+
+ for ( i = 0; i < rows; i++ ) {
+ for ( j = 0; j < channels; j++ ) {
+ if ( entry_table[ i * channels + j ].mask ) {
+ *entry = entry_table[ i * channels + j ];
+ entry->channel = j;
+ entry++;
+ }
+ }
+ IT_SET_END_ROW( entry );
+ entry++;
+ }
+
+ return 0;
+}
+
+static int it_amf_read_sample_header( IT_SAMPLE *sample, DUMBFILE *f, int * offset, int ver )
+{
+ int exists;
+
+ exists = dumbfile_getc( f );
+
+ dumbfile_getnc( sample->name, 32, f );
+ sample->name[32] = 0;
+
+ dumbfile_getnc( sample->filename, 13, f );
+ sample->filename[13] = 0;
+
+ *offset = dumbfile_igetl( f );
+ sample->length = dumbfile_igetl( f );
+ sample->C5_speed = dumbfile_igetw( f );
+ sample->default_volume = dumbfile_getc( f );
+ sample->global_volume = 64;
+ if ( sample->default_volume > 64 ) sample->default_volume = 64;
+
+ if ( ver >= 11 ) {
+ sample->loop_start = dumbfile_igetl( f );
+ sample->loop_end = dumbfile_igetl( f );
+ } else {
+ sample->loop_start = dumbfile_igetw( f );
+ sample->loop_end = sample->length;
+ }
+
+ if ( sample->length <= 0 ) {
+ sample->flags = 0;
+ return 0;
+ }
+
+ sample->flags = exists == 1 ? IT_SAMPLE_EXISTS : 0;
+
+ sample->default_pan = 0;
+ sample->finetune = 0;
+
+ if ( sample->loop_start != 0 )
+ sample->flags |= IT_SAMPLE_LOOP;
+
+ sample->vibrato_speed = 0;
+ sample->vibrato_depth = 0;
+ sample->vibrato_rate = 0;
+ sample->vibrato_waveform = 0; // do we have to set _all_ these?
+ sample->max_resampling_quality = -1;
+
+ return dumbfile_error(f);
+}
+
+
+
+static int it_amf_read_sample_data( IT_SAMPLE *sample, DUMBFILE *f )
+{
+ int i, read_length = 0;
+
+ sample->data = malloc( sample->length );
+
+ if ( !sample->data )
+ return -1;
+
+ if ( sample->length )
+ read_length = dumbfile_getnc( sample->data, sample->length, f );
+
+ for ( i = 0; i < read_length; i++ ) {
+ ( ( char * ) sample->data )[ i ] ^= 0x80;
+ }
+
+ for ( i = read_length; i < sample->length; i++ ) {
+ ( ( char * ) sample->data )[ i ] = 0;
+ }
+
+ return 0; /* Sometimes the last sample is truncated :( */
+}
+
+static DUMB_IT_SIGDATA *it_amf_load_sigdata(DUMBFILE *f, int * version)
+{
+ DUMB_IT_SIGDATA *sigdata;
+ int i, j, ver, ntracks, realntracks, nchannels;
+
+ int maxsampleseekpos = 0;
+ int sampleseekpos[256];
+
+ unsigned short *orderstotracks;
+ unsigned short *trackmap;
+ unsigned int tracksize[256];
+
+ unsigned char **track;
+
+ static const char sig[] = "AMF";
+
+ char signature [3];
+
+ if ( dumbfile_getnc( signature, 3, f ) != 3 ||
+ memcmp( signature, sig, 3 ) ) {
+ return NULL;
+ }
+
+ *version = ver = dumbfile_getc( f );
+ if ( ver < 10 || ver > 14) {
+ return NULL;
+ }
+
+ sigdata = malloc(sizeof(*sigdata));
+ if (!sigdata) {
+ return NULL;
+ }
+
+ dumbfile_getnc( sigdata->name, 32, f );
+ sigdata->name[ 32 ] = 0;
+ sigdata->n_samples = dumbfile_getc( f );
+ sigdata->n_orders = dumbfile_getc( f );
+ ntracks = dumbfile_igetw( f );
+ nchannels = dumbfile_getc( f );
+
+ if ( dumbfile_error( f ) ||
+ sigdata->n_samples < 1 || sigdata->n_samples > 255 ||
+ sigdata->n_orders < 1 || sigdata->n_orders > 255 ||
+ ! ntracks ||
+ nchannels < 1 || nchannels > 32 ) {
+ free( sigdata );
+ return NULL;
+ }
+
+ if ( ver >= 11 ) {
+ int nchannels = ( ver >= 13 ) ? 32 : 16;
+ for ( i = 0; i < nchannels; i++ ) {
+ signed char panpos = dumbfile_getc( f );
+ int pan = ( panpos + 64 ) / 2;
+ if ( pan < 0 ) pan = 0;
+ else if ( pan > 64 ) pan = IT_SURROUND;
+ sigdata->channel_pan[ i ] = pan;
+ }
+ }
+ else {
+ for ( i = 0; i < 16; i++ ) {
+ sigdata->channel_pan[ i ] = ( dumbfile_getc( f ) & 1 ) ? 16 : 48;
+ }
+ }
+
+ sigdata->tempo = 125;
+ sigdata->speed = 6;
+ if ( ver >= 13 ) {
+ i = dumbfile_getc( f );
+ if ( i >= 32 ) sigdata->tempo = i;
+ i = dumbfile_getc( f );
+ if ( i <= 32 ) sigdata->speed = i;
+ }
+
+ sigdata->order = malloc( sigdata->n_orders );
+ if ( !sigdata->order ) {
+ free( sigdata );
+ return NULL;
+ }
+
+ orderstotracks = malloc( sigdata->n_orders * nchannels * sizeof( unsigned short ) );
+ if ( !orderstotracks ) {
+ free( sigdata->order );
+ free( sigdata );
+ return NULL;
+ }
+
+ for ( i = 0; i < sigdata->n_orders; i++ ) {
+ sigdata->order[ i ] = i;
+ tracksize[ i ] = 64;
+ if ( ver >= 14 ) {
+ tracksize[ i ] = dumbfile_igetw( f );
+ }
+ for ( j = 0; j < nchannels; j++ ) {
+ orderstotracks[ i * nchannels + j ] = dumbfile_igetw( f );
+ }
+ }
+
+ if ( dumbfile_error( f ) ) {
+ free( orderstotracks );
+ free( sigdata->order );
+ free( sigdata );
+ return NULL;
+ }
+
+ sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) );
+ if ( !sigdata->sample ) {
+ free( orderstotracks );
+ free( sigdata->order );
+ free( sigdata );
+ return NULL;
+ }
+
+ sigdata->restart_position = 0;
+
+ 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 ) {
+ int offset;
+ if ( it_amf_read_sample_header( &sigdata->sample[i], f, &offset, ver ) ) {
+ goto error_ott;
+ }
+ sampleseekpos[ i ] = offset;
+ if ( offset > maxsampleseekpos ) maxsampleseekpos = offset;
+ }
+
+ sigdata->n_patterns = sigdata->n_orders;
+
+ sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) );
+ if ( !sigdata->pattern ) {
+ goto error_ott;
+ }
+ for (i = 0; i < sigdata->n_patterns; ++i)
+ sigdata->pattern[i].entry = NULL;
+
+ trackmap = malloc( ntracks * sizeof( unsigned short ) );
+ if ( !trackmap ) {
+ goto error_ott;
+ }
+
+ if ( dumbfile_getnc( ( char * ) trackmap, ntracks * sizeof( unsigned short ), f ) != ntracks * sizeof( unsigned short ) ) {
+ goto error_tm;
+ }
+
+ realntracks = 0;
+
+ for ( i = 0; i < ntracks; i++ ) {
+ if ( trackmap[ i ] > realntracks ) realntracks = trackmap[ i ];
+ }
+
+ track = calloc( realntracks, sizeof( unsigned char * ) );
+ if ( !track ) {
+ goto error_tm;
+ }
+
+ for ( i = 0; i < realntracks; i++ ) {
+ int tracksize = dumbfile_igetw( f );
+ tracksize += dumbfile_getc( f ) << 16;
+ track[ i ] = malloc( tracksize * 3 + 3 );
+ if ( !track[ i ] ) {
+ goto error_all;
+ }
+ track[ i ][ 0 ] = tracksize & 255;
+ track[ i ][ 1 ] = ( tracksize >> 8 ) & 255;
+ track[ i ][ 2 ] = ( tracksize >> 16 ) & 255;
+ if ( dumbfile_getnc( track[ i ] + 3, tracksize * 3, f ) != tracksize * 3 ) {
+ goto error_all;
+ }
+ }
+
+ for ( i = 1; i <= maxsampleseekpos; i++ ) {
+ for ( j = 0; j < sigdata->n_samples; j++ ) {
+ if ( sampleseekpos[ j ] == i ) {
+ if ( it_amf_read_sample_data( &sigdata->sample[ j ], f ) ) {
+ goto error_all;
+ }
+ break;
+ }
+ }
+ }
+
+ /* Process tracks into patterns */
+ for ( i = 0; i < sigdata->n_patterns; i++ ) {
+ IT_ENTRY * entry_table = calloc( tracksize[ i ] * nchannels, sizeof( IT_ENTRY ) );
+ if ( !entry_table ) {
+ goto error_all;
+ }
+ for ( j = 0; j < nchannels; j++ ) {
+ int ntrack = orderstotracks[ i * nchannels + j ];
+ if ( ntrack && ntrack <= ntracks ) {
+ int realtrack = trackmap[ ntrack - 1 ];
+ if ( realtrack ) {
+ realtrack--;
+ if ( realtrack < realntracks && track[ realtrack ] ) {
+ it_amf_process_track( entry_table + j, track[ realtrack ], tracksize[ i ], nchannels );
+ }
+ }
+ }
+ }
+ if ( it_amf_process_pattern( &sigdata->pattern[ i ], entry_table, tracksize[ i ], nchannels ) ) {
+ free( entry_table );
+ goto error_all;
+ }
+ free( entry_table );
+ }
+
+ /* 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;
+
+ _dumb_it_fix_invalid_orders(sigdata);
+
+ for ( i = 0; i < realntracks; i++ ) {
+ if ( track[ i ] ) {
+ free( track[ i ] );
+ }
+ }
+ free( track );
+ free( trackmap );
+ free( orderstotracks );
+
+ return sigdata;
+
+error_all:
+ for ( i = 0; i < realntracks; i++ ) {
+ if ( track[ i ] ) {
+ free( track[ i ] );
+ }
+ }
+ free( track );
+error_tm:
+ free( trackmap );
+error_ott:
+ free( orderstotracks );
+ _dumb_it_unload_sigdata( sigdata );
+ return NULL;
+}
+
+
+
+DUH *dumb_read_amf_quick(DUMBFILE *f)
+{
+ sigdata_t *sigdata;
+
+ DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
+
+ int version;
+
+ sigdata = it_amf_load_sigdata(f, &version);
+
+ if (!sigdata)
+ return NULL;
+
+ {
+ const char *tag[2][2];
+ char ver_string[14];
+ tag[0][0] = "TITLE";
+ tag[0][1] = ((DUMB_IT_SIGDATA *)sigdata)->name;
+ tag[1][0] = "FORMAT";
+ memcpy( ver_string, "DSMI AMF v", 10 );
+ ver_string[10] = '0' + version / 10;
+ ver_string[11] = '.';
+ ver_string[12] = '0' + version % 10;
+ ver_string[13] = 0;
+ tag[1][1] = ver_string;
+ return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
+ }
+}
--- /dev/null
+++ b/dumb/src/it/readamf2.c
@@ -1,0 +1,29 @@
+/* _______ ____ __ ___ ___
+ * \ _ \ \ / \ / \ \ / / ' ' '
+ * | | \ \ | | || | \/ | . .
+ * | | | | | | || ||\ /| |
+ * | | | | | | || || \/ | | ' ' '
+ * | | | | | | || || | | . .
+ * | |_/ / \ \__// || | |
+ * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
+ * / \
+ * / . \
+ * readamf2.c - Function to read a DSMI AMF module / / \ \
+ * from an open file and do an initial | < / \_
+ * run-through. | \/ /\ /
+ * \_ / > /
+ * | \ / /
+ * | ' /
+ * \__/
+ */
+
+#include "dumb.h"
+
+
+
+DUH *dumb_read_amf(DUMBFILE *f)
+{
+ DUH *duh = dumb_read_amf_quick(f);
+ dumb_it_do_initial_runthrough(duh);
+ return duh;
+}
--- a/dumb/vc6/dumb/dumb.vcproj
+++ b/dumb/vc6/dumb/dumb.vcproj
@@ -1302,6 +1302,14 @@
>
</File>
<File
+ RelativePath="..\..\src\it\loadamf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\it\loadamf2.c"
+ >
+ </File>
+ <File
RelativePath="..\..\src\it\loadasy.c"
>
</File>
@@ -1651,6 +1659,14 @@
</File>
<File
RelativePath="..\..\src\it\readam.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\it\readamf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\it\readamf2.c"
>
</File>
<File