From 8ca5a0645cb06f3e69ee13207b85a7b67f1be28b Mon Sep 17 00:00:00 2001 From: manakoAT Date: Sat, 8 Nov 2008 19:03:28 +0000 Subject: [PATCH] support for newer MUSX formats git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@466 51a99a44-fe44-0410-b1ba-c3e57ba2b86b --- src/meta/meta.h | 6 +- src/meta/musx.c | 200 ++++++++++++++++++++++++++++++++++++++++++++---- src/vgmstream.c | 14 +++- src/vgmstream.h | 4 +- 4 files changed, 206 insertions(+), 18 deletions(-) diff --git a/src/meta/meta.h b/src/meta/meta.h index 09210928..b23def0a 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -141,7 +141,11 @@ VGMSTREAM * init_vgmstream_xa30(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_musc(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_musx(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_musx_v04(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_musx_v06(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_musx_v10(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_leg(STREAMFILE * streamFile); diff --git a/src/meta/musx.c b/src/meta/musx.c index aaad59c2..8b31eb8d 100644 --- a/src/meta/musx.c +++ b/src/meta/musx.c @@ -1,14 +1,15 @@ #include "meta.h" #include "../util.h" -/* MUSX (from Spyro, possibly more Vivendi games) */ -VGMSTREAM * init_vgmstream_musx(STREAMFILE *streamFile) { +/* MUSX */ +/* Old MUSX formats, found in Spyro, Ty and other games */ +VGMSTREAM * init_vgmstream_musx_v04(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[260]; off_t start_offset; - /*int musx_version;*/ /* 0x08 provides a "version" byte??? */ - int musx_type; + int musx_type; /* determining the decoder by strings like "PS2_", "GC__" and so on */ + int musx_version; /* 0x08 provides a "version" byte??? */ int loop_flag = 0; int channel_count; @@ -19,14 +20,22 @@ VGMSTREAM * init_vgmstream_musx(STREAMFILE *streamFile) { /* check header */ if (read_32bitBE(0x00,streamFile) != 0x4D555358) /* "MUSX" */ goto fail; - + + if (read_32bitBE(0x08,streamFile) != 0x04000000) /* "0x04000000" */ + goto fail; + + /* Determine if we have an old MUSX file, + hope this will work, but it seems every new MUSX type has a new "identifer" byte */ + + /* This is tricky, the header changes it's layout if the file is unlooped */ loop_flag = (read_32bitLE(0x840,streamFile)!=0xFFFFFFFF); channel_count = 2; - + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - + + /* fill in the vital statistics */ musx_type=(read_32bitBE(0x10,streamFile)); @@ -36,18 +45,183 @@ VGMSTREAM * init_vgmstream_musx(STREAMFILE *streamFile) { vgmstream->channels = channel_count; vgmstream->sample_rate = 32000; vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = (read_32bitLE(0x0C,streamFile))*28/16/channel_count;; + vgmstream->num_samples = (read_32bitLE(0x0C,streamFile))*28/16/channel_count; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x80; - vgmstream->meta_type = meta_MUSX; + vgmstream->meta_type = meta_MUSX_V04; if (loop_flag) { vgmstream->loop_start_sample = (read_32bitLE(0x890,streamFile))*28/16/channel_count; vgmstream->loop_end_sample = (read_32bitLE(0x89C,streamFile))*28/16/channel_count; } - - - - + break; + default: + goto fail; + + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + + +/* MUSX */ +/* Old MUSX formats, found in Spyro, Ty and other games */ +VGMSTREAM * init_vgmstream_musx_v06(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[260]; + off_t start_offset; + + int musx_type; /* determining the decoder by strings like "PS2_", "GC__" and so on */ + int musx_version; /* 0x08 provides a "version" byte??? */ + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("musx",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x4D555358) /* "MUSX" */ + goto fail; + + if (read_32bitBE(0x08,streamFile) != 0x06000000) /* "0x04000000" */ + goto fail; + + /* Determine if we have an old MUSX file, + hope this will work, but it seems every new MUSX type has a new "identifer" byte */ + + /* This is tricky, the header changes it's layout if the file is unlooped */ + loop_flag = (read_32bitLE(0x840,streamFile)!=0xFFFFFFFF); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + + /* fill in the vital statistics */ + musx_type=(read_32bitBE(0x10,streamFile)); + + switch (musx_type) { + case 0x5053325F: /* PS2_ */ + start_offset = read_32bitLE(0x28,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = 32000; + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (read_32bitLE(0x0C,streamFile))*28/16/channel_count; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x80; + vgmstream->meta_type = meta_MUSX_V06; + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitLE(0x890,streamFile))*28/16/channel_count; + vgmstream->loop_end_sample = (read_32bitLE(0x89C,streamFile))*28/16/channel_count; + } + break; + default: + goto fail; + + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + + + + + +/* MUSX */ +/* New MUSX formats, found in Quantum of Solace, The Mummy 3, possibly more */ +VGMSTREAM * init_vgmstream_musx_v10(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[260]; + off_t start_offset; + + int musx_type; /* determining the decoder by strings like "PS2_", "GC__" and so on */ + int musx_version; /* 0x08 provides a "version" byte??? */ + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("musx",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x4D555358) /* "MUSX" */ + goto fail; + + /* Determine if we have an old MUSX file, + hope this will work, but it seems every new MUSX type has a new "identifer" byte */ + if (read_32bitBE(0x08,streamFile) != 0x0A000000) /* "0x0A000000" */ + goto fail; + + /* This is tricky, the header changes it's layout if the file is unlooped */ + loop_flag = (read_32bitLE(0x44,streamFile)!=0xFFFFFFFF); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + musx_type=(read_32bitBE(0x10,streamFile)); + + switch (musx_type) { + case 0x5053325F: /* PS2_ */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 32000; + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x40,streamFile); + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x80; + vgmstream->meta_type = meta_MUSX_V10; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x44,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x40,streamFile); + } break; default: goto fail; diff --git a/src/vgmstream.c b/src/vgmstream.c index 6d544b7b..d479e2da 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -85,7 +85,9 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_xwb, init_vgmstream_xa30, init_vgmstream_musc, - init_vgmstream_musx, + init_vgmstream_musx_v04, + init_vgmstream_musx_v06, + init_vgmstream_musx_v10, init_vgmstream_leg, init_vgmstream_filp, init_vgmstream_ikm, @@ -1632,8 +1634,14 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) { case meta_MUSC: snprintf(temp,TEMPSIZE,"MUSC Header"); break; - case meta_MUSX: - snprintf(temp,TEMPSIZE,"MUSX Header"); + case meta_MUSX_V04: + snprintf(temp,TEMPSIZE,"MUSX / Version 04 Header"); + break; + case meta_MUSX_V06: + snprintf(temp,TEMPSIZE,"MUSX / Version 06 Header"); + break; + case meta_MUSX_V10: + snprintf(temp,TEMPSIZE,"MUSX / Version 10 Header"); break; case meta_LEG: snprintf(temp,TEMPSIZE,"Legaia 2 - Duel Saga LEG Header"); diff --git a/src/vgmstream.h b/src/vgmstream.h index d78c0132..7aac987c 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -208,7 +208,9 @@ typedef enum { meta_XWB, /* King of Fighters (XBOX) */ meta_XA30, /* Driver - Parallel Lines (PS2) */ meta_MUSC, /* Spyro Games, possibly more */ - meta_MUSX, /* Spyro Games, possibly more */ + meta_MUSX_V04, /* Spyro Games, possibly more */ + meta_MUSX_V06, /* Spyro Games, possibly more */ + meta_MUSX_V10, /* Spyro Games, possibly more */ meta_LEG, /* Legaia 2 */ meta_FILP, /* Resident Evil - Dead Aim */ meta_IKM, /* Zwei! */