diff --git a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj index fe0ed4f17..eecf6bdf6 100644 --- a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj +++ b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj @@ -417,7 +417,6 @@ 836F704418BDC2190095E648 /* ws_aud.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0818BDC2190095E648 /* ws_aud.c */; }; 836F704518BDC2190095E648 /* wvs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0918BDC2190095E648 /* wvs.c */; }; 836F704618BDC2190095E648 /* x360_tra.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0A18BDC2190095E648 /* x360_tra.c */; }; - 836F704718BDC2190095E648 /* xbox_hlwav.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0B18BDC2190095E648 /* xbox_hlwav.c */; }; 836F704818BDC2190095E648 /* xbox_ims.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0C18BDC2190095E648 /* xbox_ims.c */; }; 836F704E18BDC2190095E648 /* xss.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1218BDC2190095E648 /* xss.c */; }; 836F704F18BDC2190095E648 /* xwb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1318BDC2190095E648 /* xwb.c */; }; @@ -545,7 +544,7 @@ 83C7282022BC893D00678B4A /* dcs_wav.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C7280C22BC893D00678B4A /* dcs_wav.c */; }; 83C7282122BC893D00678B4A /* msf_konami.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C7280D22BC893D00678B4A /* msf_konami.c */; }; 83C7282222BC893D00678B4A /* mta2_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C7280E22BC893D00678B4A /* mta2_streamfile.h */; }; - 83C7282722BC8C1500678B4A /* plugins.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C7282322BC8C1300678B4A /* plugins.h */; }; + 83C7282722BC8C1500678B4A /* plugins.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C7282322BC8C1300678B4A /* plugins.h */; settings = {ATTRIBUTES = (Public, ); }; }; 83C7282822BC8C1500678B4A /* mixing.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C7282422BC8C1400678B4A /* mixing.h */; }; 83C7282922BC8C1500678B4A /* mixing.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C7282522BC8C1400678B4A /* mixing.c */; }; 83C7282A22BC8C1500678B4A /* plugins.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C7282622BC8C1400678B4A /* plugins.c */; }; @@ -1105,7 +1104,6 @@ 836F6F0818BDC2190095E648 /* ws_aud.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ws_aud.c; sourceTree = ""; }; 836F6F0918BDC2190095E648 /* wvs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wvs.c; sourceTree = ""; }; 836F6F0A18BDC2190095E648 /* x360_tra.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x360_tra.c; sourceTree = ""; }; - 836F6F0B18BDC2190095E648 /* xbox_hlwav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xbox_hlwav.c; sourceTree = ""; }; 836F6F0C18BDC2190095E648 /* xbox_ims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xbox_ims.c; sourceTree = ""; }; 836F6F1218BDC2190095E648 /* xss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xss.c; sourceTree = ""; }; 836F6F1318BDC2190095E648 /* xwb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xwb.c; sourceTree = ""; }; @@ -1917,7 +1915,6 @@ 833A7A2D1ED11961003EC53E /* xau.c */, 837CEAEE23487F2C00E62A4A /* xavs_streamfile.h */, 837CEAE423487F2A00E62A4A /* xavs.c */, - 836F6F0B18BDC2190095E648 /* xbox_hlwav.c */, 836F6F0C18BDC2190095E648 /* xbox_ims.c */, 8350C0541E071881009E0A93 /* xma.c */, 834FE0DC215C79EA000A5D3D /* xmd.c */, @@ -1987,6 +1984,7 @@ 83A21F87201D8981000F04B9 /* fsb_keys.h in Headers */, 834FE0EC215C79ED000A5D3D /* kma9_streamfile.h in Headers */, 8349A90F1FE6258200E26435 /* aix_streamfile.h in Headers */, + 83C7282722BC8C1500678B4A /* plugins.h in Headers */, 834FE0ED215C79ED000A5D3D /* fsb_interleave_streamfile.h in Headers */, 8351F32E2212B57000A606E4 /* ubi_bao_streamfile.h in Headers */, 8349A9111FE6258200E26435 /* bar_streamfile.h in Headers */, @@ -2020,7 +2018,6 @@ 834FE0B5215C798C000A5D3D /* acm_decoder_libacm.h in Headers */, 839E21E61F2EDAF100EE54D7 /* vorbis_custom_data_wwise.h in Headers */, 834FE103215C79ED000A5D3D /* ea_schl_streamfile.h in Headers */, - 83C7282722BC8C1500678B4A /* plugins.h in Headers */, 83F0AA6021E2028C004BBC04 /* vsv_streamfile.h in Headers */, 83FBD506235D31F800D35BCD /* riff_ogg_streamfile.h in Headers */, 48C2650F1A5D420800A0A3D6 /* vorbisfile.h in Headers */, @@ -2622,7 +2619,6 @@ 834FE0EE215C79ED000A5D3D /* ue4opus.c in Sources */, 836F6FEA18BDC2190095E648 /* ps2_msa.c in Sources */, 836F6F3618BDC2190095E648 /* ogg_vorbis_decoder.c in Sources */, - 836F704718BDC2190095E648 /* xbox_hlwav.c in Sources */, 8306B0E520984590000302D4 /* ubi_lyn.c in Sources */, 836F6F7618BDC2190095E648 /* brstm.c in Sources */, 836F700718BDC2190095E648 /* ps2_vgv.c in Sources */, diff --git a/Frameworks/vgmstream/vgmstream/src/formats.c b/Frameworks/vgmstream/vgmstream/src/formats.c index ee93d9054..7bb2e1623 100644 --- a/Frameworks/vgmstream/vgmstream/src/formats.c +++ b/Frameworks/vgmstream/vgmstream/src/formats.c @@ -191,7 +191,6 @@ static const char* extension_list[] = { "hdr", "hgc1", "his", - "hlwav", "hps", "hsf", "hx2", @@ -1028,7 +1027,7 @@ static const meta_info meta_info_list[] = { {meta_EXAKT_SC, "assumed Activision / EXAKT SC by extension"}, {meta_WII_BNS, "Nintendo BNS header"}, {meta_WII_WAS, "Sumo Digital iSWS header"}, - {meta_XBOX_HLWAV, "Half Life 2 bgm header"}, + {meta_XBOX_HLWAV, "Half-Life 2 .WAV header"}, {meta_MYSPD, "U-Sing .MYSPD header"}, {meta_HIS, "Her Interactive HIS header"}, {meta_PS2_AST, "KOEI AST header"}, diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c index 538ffe7b5..4f98da9eb 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c @@ -561,8 +561,8 @@ static STREAMFILE *open_mapfile_pair(STREAMFILE *streamFile, int track, int num_ int i, j; size_t file_len, map_len; - /* if there's only one track, try opening MUS with the same name first (most common scenario) */ - if (num_tracks == 1) { + /* if loading the first track, try opening MUS with the same name first (most common scenario) */ + if (track == 0) { musFile = open_streamfile_by_ext(streamFile, "mus"); if (musFile) return musFile; } @@ -573,27 +573,40 @@ static STREAMFILE *open_mapfile_pair(STREAMFILE *streamFile, int track, int num_ for (i = 0; i < pair_count; i++) { const char *map_name = mapfile_pairs[i][0]; const char *mus_name = mapfile_pairs[i][1]; - char buf[PATH_LIMIT] = {0}; + char buf[PATH_LIMIT] = { 0 }; char *pch; + int use_mask = 0; map_len = strlen(map_name); /* replace map_name with expected mus_name */ if (file_len < map_len) continue; - if (strncasecmp(file_name + (file_len - map_len), map_name, map_len) != 0) - continue; - strncpy(buf, mus_name, map_len); + if (map_name[0] == '*') { + use_mask = 1; + map_name++; + map_len--; + + if (strncmp(file_name + (file_len - map_len), map_name, map_len) != 0) + continue; + } else { + if (strcmp(file_name, map_name) != 0) + continue; + } + + strncpy(buf, mus_name, PATH_LIMIT); pch = strtok(buf, ","); //TODO: not thread safe in std C for (j = 0; j < track && pch; j++) { pch = strtok(NULL, ","); } + if (!pch) continue; /* invalid track */ - if (!pch) - continue; - - file_name[file_len - map_len] = '\0'; - strcat(file_name, pch); + if (use_mask) { + file_name[file_len - map_len] = '\0'; + strncat(file_name, pch + 1, PATH_LIMIT); + } else { + strncpy(file_name, pch, PATH_LIMIT); + } musFile = open_streamfile_by_filename(streamFile, file_name); if (musFile) return musFile; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c index 297273f2e..ea6b09d1d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c @@ -626,7 +626,8 @@ fail: static STREAMFILE* open_mapfile_pair(STREAMFILE *streamFile, int track, int num_tracks) { static const char *const mapfile_pairs[][2] = { /* standard cases, replace map part with mus part (from the end to preserve prefixes) */ - {"mus_ctrl.mpf", "mus_str.mus"}, /* GoldenEye - Rogue Agent */ + {"MUS_CTRL.MPF", "MUS_STR.MUS"}, /* GoldenEye - Rogue Agent (PS2) */ + {"mus_ctrl.mpf", "mus_str.mus"}, /* GoldenEye - Rogue Agent (others) */ {"AKA_Mus.mpf", "Track.mus"}, /* Boogie */ {"SSX4.mpf", "moments0.mus,main.mus,load_loop0.mus"}, /* SSX Blur */ {"willow.mpf", "willow.mus,willow_o.mus"}, /* Harry Potter and the Chamber of Secrets */ @@ -634,16 +635,21 @@ static STREAMFILE* open_mapfile_pair(STREAMFILE *streamFile, int track, int num_ {"Peak1Amb.mpf", "Peak1_Strm.mus,Peak1_Ovr0.mus"}, /* SSX 3 */ {"Peak2Amb.mpf", "Peak2_Strm.mus,Peak2_Ovr0.mus"}, {"Peak3Amb.mpf", "Peak3_Strm.mus,Peak3_Ovr0.mus"}, - {".mpf", "_main.mus"}, /* 007 - Everything or Nothing */ - //TODO: improve pairs (needs better wildcard support) - //NSF2: - /* ZTRxxROK.MAP > ZTRxx.TRJ */ - /* ZTRxxTEC.MAP > ZTRxx.TRM */ - /* ZZSHOW.MAP and ZZSHOW2.MAP > ZZSHOW.MUS */ - //NSF3: - /* ZTRxxROK.MAP > ZZZTRxxA.TRJ */ - /* ZTRxxTEC.MAP > ZZZTRxxB.TRM */ - /* other extra files that may need the hack below */ + {"*.mpf", "*_main.mus"}, /* 007 - Everything or Nothing */ + /* TODO: need better wildcard support + * NSF2: + * ZTRxxROK.MAP > ZTRxx.TRJ + * ZTRxxTEC.MAP > ZTRxx.TRM + * ZZSHOW.MAP and ZZSHOW2.MAP > ZZSHOW.MUS + * NSF3: + * ZTRxxROK.MAP > ZZZTRxxA.TRJ + * ZTRxxTEC.MAP > ZZZTRxxB.TRM + * ZTR00R0A.MAP and ZTR00R0B.MAP > ZZZTR00A.TRJ + * other extra files that may need the hack below + * SSX 3: + * *.mpf > *.mus,xxloops0.mus + * really need to think of something for this + */ }; STREAMFILE *musFile = NULL; char file_name[PATH_LIMIT]; @@ -651,8 +657,8 @@ static STREAMFILE* open_mapfile_pair(STREAMFILE *streamFile, int track, int num_ int i, j; size_t file_len, map_len; - /* if there's only one track, try opening MUS with the same name first (most common scenario) */ - if (num_tracks == 1) { + /* if loading the first track, try opening MUS with the same name first (most common scenario) */ + if (track == 0) { musFile = open_streamfile_by_ext(streamFile, "mus"); if (musFile) return musFile; } @@ -665,25 +671,38 @@ static STREAMFILE* open_mapfile_pair(STREAMFILE *streamFile, int track, int num_ const char *mus_name = mapfile_pairs[i][1]; char buf[PATH_LIMIT] = {0}; char *pch; + int use_mask = 0; map_len = strlen(map_name); /* replace map_name with expected mus_name */ if (file_len < map_len) continue; - if (strncasecmp(file_name + (file_len - map_len), map_name, map_len) != 0) - continue; - strncpy(buf, mus_name, map_len); + if (map_name[0] == '*') { + use_mask = 1; + map_name++; + map_len--; + + if (strcmp(file_name + (file_len - map_len), map_name) != 0) + continue; + } else { + if (strcmp(file_name, map_name) != 0) + continue; + } + + strncpy(buf, mus_name, PATH_LIMIT); pch = strtok(buf, ","); //TODO: not thread safe in std C for (j = 0; j < track && pch; j++) { pch = strtok(NULL, ","); } + if (!pch) continue; /* invalid track */ - if (!pch) - continue; - - file_name[file_len - map_len] = '\0'; - strcat(file_name, pch); + if (use_mask) { + file_name[file_len - map_len] = '\0'; + strncat(file_name, pch + 1, PATH_LIMIT); + } else { + strncpy(file_name, pch, PATH_LIMIT); + } musFile = open_streamfile_by_filename(streamFile, file_name); if (musFile) return musFile; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mib_mih.c b/Frameworks/vgmstream/vgmstream/src/meta/mib_mih.c index 6e451b562..e015f56b3 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/mib_mih.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/mib_mih.c @@ -5,8 +5,8 @@ VGMSTREAM * init_vgmstream_mib_mih(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; STREAMFILE * streamHeader = NULL; - off_t start_offset; - size_t data_size, frame_size, frame_last, frame_count; + off_t header_offset, start_offset; + size_t data_size, frame_size, frame_last, frame_count, name_size; int channel_count, loop_flag, sample_rate; /* check extension */ @@ -16,18 +16,28 @@ VGMSTREAM * init_vgmstream_mib_mih(STREAMFILE *streamFile) { streamHeader = open_streamfile_by_ext(streamFile,"mih"); if (!streamHeader) goto fail; - if (read_32bitBE(0x00,streamHeader) != 0x40000000) /* header size */ - goto fail; + header_offset = 0x00; + + if (read_32bitLE(0x00,streamHeader) != 0x40) { /* header size */ + name_size = read_32bitLE(0x00, streamHeader); + if (read_32bitLE(0x04 + name_size, streamHeader) == 0x40 && + read_32bitLE(0x04 + name_size + 0x04, streamHeader) == 0x40) { + /* Marc Ecko's Getting Up (PS2) has a name at the start */ + header_offset = 0x04 + name_size + 0x04; + } else { + goto fail; + } + } loop_flag = 0; /* MIB+MIH don't loop (nor use PS-ADPCM flags) per spec */ start_offset = 0x00; /* 0x04: padding size (always 0x20, MIH header must be multiple of 0x40) */ - frame_last = (uint32_t)read_32bitLE(0x05,streamHeader) & 0x00FFFFFF; /* 24b */ - channel_count = read_32bitLE(0x08,streamHeader); - sample_rate = read_32bitLE(0x0c,streamHeader); - frame_size = read_32bitLE(0x10,streamHeader); - frame_count = read_32bitLE(0x14,streamHeader); + frame_last = (uint32_t)read_32bitLE(header_offset + 0x05,streamHeader) & 0x00FFFFFF; /* 24b */ + channel_count = read_32bitLE(header_offset + 0x08,streamHeader); + sample_rate = read_32bitLE(header_offset + 0x0c,streamHeader); + frame_size = read_32bitLE(header_offset + 0x10,streamHeader); + frame_count = read_32bitLE(header_offset + 0x14,streamHeader); if (frame_count == 0) { /* rarely [Gladius (PS2)] */ frame_count = get_streamfile_size(streamFile) / (frame_size * channel_count); } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c b/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c index 5bfdd28c7..bf059c810 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c @@ -207,22 +207,35 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) { /* SB HEADER */ /* SBx layout: header, section1, section2, extra section, section3, data (all except header can be null) */ sb.is_bank = 1; - sb.version = read_32bit(0x00, streamFile); + sb.version = read_32bit(0x00, streamFile); if (!config_sb_version(&sb, streamFile)) goto fail; - sb.section1_num = read_32bit(0x04, streamFile); - sb.section2_num = read_32bit(0x08, streamFile); - sb.section3_num = read_32bit(0x0c, streamFile); - sb.sectionX_size = read_32bit(0x10, streamFile); - sb.flag1 = read_32bit(0x14, streamFile); + if (sb.version <= 0x0000000B) { + sb.section1_num = read_32bit(0x04, streamFile); + sb.section2_num = read_32bit(0x0c, streamFile); + sb.section3_num = read_32bit(0x14, streamFile); + sb.sectionX_size = read_32bit(0x1c, streamFile); + + sb.section1_offset = 0x20; + } else if (sb.version <= 0x000A0000) { + sb.section1_num = read_32bit(0x04, streamFile); + sb.section2_num = read_32bit(0x08, streamFile); + sb.section3_num = read_32bit(0x0c, streamFile); + sb.sectionX_size = read_32bit(0x10, streamFile); + sb.flag1 = read_32bit(0x14, streamFile); - if (sb.version <= 0x000A0000) { sb.section1_offset = 0x18; } else { + sb.section1_num = read_32bit(0x04, streamFile); + sb.section2_num = read_32bit(0x08, streamFile); + sb.section3_num = read_32bit(0x0c, streamFile); + sb.sectionX_size = read_32bit(0x10, streamFile); + sb.flag1 = read_32bit(0x14, streamFile); + sb.flag2 = read_32bit(0x18, streamFile); + sb.section1_offset = 0x1c; - sb.flag2 = read_32bit(0x18, streamFile); } if (sb.cfg.is_padded_section1_offset) @@ -584,7 +597,7 @@ static VGMSTREAM * init_vgmstream_ubi_sb_base(ubi_sb_header *sb, STREAMFILE *str int block_align, encoder_delay; block_align = 0x98 * sb->channels; - encoder_delay = 0; /* TODO: this is may be incorrect */ + encoder_delay = 1024 + 69*2; /* approximate */ vgmstream->codec_data = init_ffmpeg_atrac3_raw(streamData, start_offset,sb->stream_size, sb->num_samples,sb->channels,sb->sample_rate, block_align, encoder_delay); if (!vgmstream->codec_data) goto fail; @@ -2351,6 +2364,21 @@ static int config_sb_version(ubi_sb_header * sb, STREAMFILE *streamFile) { return 1; } + /* Rainbow Six 3 (2003)(PC)-bank 0x0000000B */ + if (sb->version == 0x0000000B && sb->platform == UBI_PC) { + config_sb_entry(sb, 0x5c, 0x7c); + + config_sb_audio_fs(sb, 0x24, 0x00, 0x28); + config_sb_audio_hs(sb, 0x46, 0x40, 0x2c, 0x34, 0x4c, 0x48); + sb->cfg.audio_has_internal_names = 1; + + config_sb_sequence(sb, 0x28, 0x34); + + config_sb_layer_hs(sb, 0x20, 0x60, 0x58, 0x30); + config_sb_layer_sh(sb, 0x14, 0x00, 0x06, 0x08, 0x10); + return 1; + } + /* Prince of Persia: The Sands of Time Demo (2003)(Xbox)-bank 0x0000000D */ if (sb->version == 0x0000000D && sb->platform == UBI_XBOX) { config_sb_entry(sb, 0x5c, 0x74); @@ -2358,6 +2386,11 @@ static int config_sb_version(ubi_sb_header * sb, STREAMFILE *streamFile) { config_sb_audio_fs(sb, 0x24, 0x00, 0x28); config_sb_audio_hs(sb, 0x46, 0x40, 0x2c, 0x34, 0x4c, 0x48); sb->cfg.audio_has_internal_names = 1; + + config_sb_sequence(sb, 0x28, 0x34); + + config_sb_layer_hs(sb, 0x20, 0x60, 0x58, 0x30); + config_sb_layer_sh(sb, 0x14, 0x00, 0x06, 0x08, 0x10); return 1; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb_streamfile.h index 4d9f7e75d..a12f415ab 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb_streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb_streamfile.h @@ -178,6 +178,31 @@ static int ubi_sb_io_init(STREAMFILE *streamfile, ubi_sb_io_data* data) { data->block_data_start = 0x08 + data->layer_max*0x04; break; + case 0x00000003: /* Rainbow Six 3 */ + /* - layer header + * 0x04: layer count + * 0x08: stream size + * 0x0c: block header size + * 0x10: block size (fixed) + * 0x14: min layer data? + * 0x18: size of header sizes and headers + * 0x1c+(04*N): header size per layer + * - block header + * 0x00: block number + * 0x04: block offset + * 0x08+(04*N): layer size per layer + * 0xNN: layer data per layer */ + data->layer_max = read_32bit(offset+0x04, streamfile); + + data->header_next_start = 0x10; + data->header_sizes_start = 0x1c; + data->header_data_start = 0x1c + data->layer_max*0x04; + + data->block_next_start = 0; + data->block_sizes_start = 0x08; + data->block_data_start = 0x08 + data->layer_max*0x04; + break; + case 0x00000004: /* Prince of Persia: Sands of Time, Batman: Rise of Sin Tzu */ /* - layer header * 0x04: layer count @@ -186,7 +211,7 @@ static int ubi_sb_io_init(STREAMFILE *streamfile, ubi_sb_io_data* data) { * 0x10: block header size * 0x14: block size (fixed) * 0x18: min layer data? - * 0x1c: size of header sizes + * 0x1c: size of header sizes and headers * 0x20+(04*N): header size per layer * - block header * 0x00: block number @@ -214,7 +239,7 @@ static int ubi_sb_io_init(STREAMFILE *streamfile, ubi_sb_io_data* data) { * 0x14: block header size * 0x18: block size (fixed) * 0x1c+(04*8): min layer data? for 8 layers (-1 after layer count) - * 0x3c: size of header sizes + * 0x3c: size of header sizes and headers * 0x40+(04*N): header size per layer * 0xNN: header data per layer * - block header @@ -243,7 +268,7 @@ static int ubi_sb_io_init(STREAMFILE *streamfile, ubi_sb_io_data* data) { * 0x14: block header size * 0x18: block size (fixed) * 0x1c+(04*11): min layer data? for 11 layers (-1 after layer count) - * 0x48: size of header sizes + * 0x48: size of header sizes and headers * 0x4c+(04*N): header size per layer * 0xNN: header data per layer * - block header @@ -272,7 +297,7 @@ static int ubi_sb_io_init(STREAMFILE *streamfile, ubi_sb_io_data* data) { * 0x08: layer count * 0x0c: blocks count * 0x10: block header size - * 0x14: size of header sizes/data + * 0x14: size of header sizes and headers/data * 0x18: next block size * 0x1c+(04*N): layer header size * 0xNN: header data per layer @@ -298,7 +323,7 @@ static int ubi_sb_io_init(STREAMFILE *streamfile, ubi_sb_io_data* data) { * 0x08: layer count * 0x0c: blocks count * 0x10: block header size - * 0x14: size of header sizes/data + * 0x14: size of header sizes and headers/data * 0x18: next block size * 0x1c+(04*10): usable size per layer * 0x5c+(04*N): layer header size diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xbox_hlwav.c b/Frameworks/vgmstream/vgmstream/src/meta/xbox_hlwav.c deleted file mode 100644 index 6a62ec3c1..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/xbox_hlwav.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "meta.h" -#include "../util.h" - -/* HLWAV (from Half Life 2 [XBOX]) */ -VGMSTREAM * init_vgmstream_xbox_hlwav(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("hlwav",filename_extension(filename))) goto fail; - - /* check header and size */ - if ((read_32bitBE(0x00,streamFile) != 0x14000000)) goto fail; - if (((read_32bitLE(0x4,streamFile) + (read_32bitLE(0x8,streamFile))) != get_streamfile_size(streamFile))) goto fail; - - loop_flag = (read_32bitLE(0xC,streamFile)!= 0xFFFFFFFF); - channel_count = 2; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = read_32bitLE(0x8,streamFile); - vgmstream->channels = channel_count; - vgmstream->sample_rate = 22050; - vgmstream->coding_type = coding_PCM16LE; - vgmstream->num_samples = read_32bitLE(0x4,streamFile)/2/channel_count; - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x4,streamFile)/2/channel_count; - vgmstream->loop_end_sample = read_32bitLE(0xC,streamFile)/2/channel_count; - } - - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x2; - vgmstream->meta_type = meta_XBOX_HLWAV; - - /* 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; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xmv_valve.c b/Frameworks/vgmstream/vgmstream/src/meta/xmv_valve.c index 6bc81a28b..c0e587521 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xmv_valve.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xmv_valve.c @@ -1,10 +1,82 @@ #include "meta.h" #include "../coding/coding.h" -/* .360.WAV, .PS3.WAV - from Valve games running on Source Engine */ +/* .WAV - from Half-Life 2 (Xbox) */ +VGMSTREAM *init_vgmstream_xbox_hlwav(STREAMFILE *streamFile) { + VGMSTREAM *vgmstream = NULL; + uint32_t header_size, data_size, start_offset, sample_rate; + int32_t loop_start; + uint8_t format, freq_mode, channels; + int loop_flag; + + /* checks */ + if (!check_extensions(streamFile, "wav,lwav")) + goto fail; + + /* check header and size */ + header_size = read_u32le(0x00, streamFile); + if (header_size != 0x14) + goto fail; + + data_size = read_u32le(0x04, streamFile); + start_offset = read_u32le(0x08, streamFile); + if (data_size != get_streamfile_size(streamFile) - start_offset) + goto fail; + + loop_start = read_s32le(0x0c, streamFile); + format = read_u8(0x12, streamFile); + freq_mode = read_u8(0x13, streamFile) & 0x0F; + channels = (read_u8(0x13, streamFile) >> 4) & 0x0F; + + switch (freq_mode) { + case 0x00: sample_rate = 11025; break; + case 0x01: sample_rate = 22050; break; + case 0x02: sample_rate = 44100; break; + default: goto fail; + } + + loop_flag = (loop_start != -1); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->meta_type = meta_XBOX_HLWAV; + vgmstream->sample_rate = sample_rate; + vgmstream->loop_start_sample = loop_start; + + switch (format) { + case 0x00: /* PCM */ + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x02; + vgmstream->num_samples = pcm_bytes_to_samples(data_size, channels, 16); + vgmstream->loop_end_sample = vgmstream->num_samples; /* always loops from the end */ + break; + case 0x01: /* XBOX ADPCM */ + vgmstream->coding_type = coding_XBOX_IMA; + vgmstream->layout_type = layout_none; + vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, channels); + vgmstream->loop_end_sample = vgmstream->num_samples; + break; + default: + goto fail; + } + + if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + +/* .360.WAV, .PS3.WAV - from Valve games running on Source Engine, evolution of Xbox .WAV format */ /* [The Orange Box (X360), Portal 2 (PS3/X360), Counter-Strike: Global Offensive (PS3/X360)] */ -VGMSTREAM* init_vgmstream_xmv_valve(STREAMFILE* streamFile) { - VGMSTREAM* vgmstream = NULL; +VGMSTREAM *init_vgmstream_xmv_valve(STREAMFILE *streamFile) { + VGMSTREAM *vgmstream = NULL; int32_t loop_start; uint32_t start_offset, data_size, sample_rate, num_samples; uint16_t /*loop_block, loop_start_skip,*/ loop_end_skip; @@ -16,26 +88,26 @@ VGMSTREAM* init_vgmstream_xmv_valve(STREAMFILE* streamFile) { goto fail; /* check header magic */ - if (read_32bitBE(0x00, streamFile) != 0x58575620) /* "XMV " */ + if (read_u32be(0x00, streamFile) != 0x58575620) /* "XMV " */ goto fail; /* only version 4 is known */ - if (read_32bitBE(0x04, streamFile) != 0x04) + if (read_u32be(0x04, streamFile) != 0x04) goto fail; - start_offset = read_32bitBE(0x10, streamFile); - data_size = read_32bitBE(0x14, streamFile); - num_samples = read_32bitBE(0x18, streamFile); - loop_start = read_32bitBE(0x1c, streamFile); + start_offset = read_u32be(0x10, streamFile); + data_size = read_u32be(0x14, streamFile); + num_samples = read_u32be(0x18, streamFile); + loop_start = read_s32be(0x1c, streamFile); /* XMA only */ - //loop_block = read_16bitBE(0x20, streamFile); - //loop_start_skip = read_16bitBE(0x22, streamFile); - loop_end_skip = read_16bitBE(0x24, streamFile); + //loop_block = read_u16be(0x20, streamFile); + //loop_start_skip = read_u16be(0x22, streamFile); + loop_end_skip = read_u16be(0x24, streamFile); - format = read_8bit(0x28, streamFile); - freq_mode = read_8bit(0x2a, streamFile); - channels = read_8bit(0x2b, streamFile); + format = read_u8(0x28, streamFile); + freq_mode = read_u8(0x2a, streamFile); + channels = read_u8(0x2b, streamFile); switch (freq_mode) { case 0x00: sample_rate = 11025; break; @@ -64,7 +136,7 @@ VGMSTREAM* init_vgmstream_xmv_valve(STREAMFILE* streamFile) { break; #ifdef VGM_USE_FFMPEG case 0x01: { /* XMA */ - ffmpeg_codec_data* ffmpeg_data; + ffmpeg_codec_data *ffmpeg_data; uint8_t buf[0x100]; int block_count, block_size; size_t bytes;