diff --git a/src/formats.c b/src/formats.c index 960b88a2..516fd322 100644 --- a/src/formats.c +++ b/src/formats.c @@ -67,7 +67,7 @@ static const char* extension_list[] = { "bar", "bcstm", "bcwav", - "bd3", //txth/reserved [Elevator Action Deluxe (PS3)] + "bd3", "bdsp", "bfstm", "bfwav", @@ -1062,6 +1062,7 @@ static const meta_info meta_info_list[] = { {meta_CKB, "Cricket Audio CKB header"}, {meta_WV6, "Gorilla Systems WV6 header"}, {meta_WAVEBATCH, "Firebrand Games WBAT header"}, + {meta_HD3_BD3, "Sony HD3+BD3 header"}, #ifdef VGM_USE_FFMPEG {meta_FFmpeg, "FFmpeg supported file format"}, diff --git a/src/libvgmstream.vcproj b/src/libvgmstream.vcproj index 7af45d56..650fac8e 100644 --- a/src/libvgmstream.vcproj +++ b/src/libvgmstream.vcproj @@ -512,6 +512,10 @@ RelativePath=".\meta\hca.c" > + + diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 5dc4b206..58f3d0c5 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -243,6 +243,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index f5b7dc0e..695b1b0b 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -316,6 +316,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files diff --git a/src/meta/hd3_bd3.c b/src/meta/hd3_bd3.c new file mode 100644 index 00000000..1fbad671 --- /dev/null +++ b/src/meta/hd3_bd3.c @@ -0,0 +1,115 @@ +#include "meta.h" +#include "../coding/coding.h" + + /* HD3+BD3 - Sony PS3 bank format [Elevator Action Deluxe (PS3), R-Type Dimensions (PS3)] */ +VGMSTREAM * init_vgmstream_hd3_bd3(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamHeader = NULL; + off_t start_offset; + int channel_count, loop_flag, sample_rate; + size_t interleave, stream_size; + int total_subsongs, target_subsong = streamFile->stream_index; + + + /* checks */ + if (!check_extensions(streamFile, "bd3")) + goto fail; + + streamHeader = open_streamfile_by_ext(streamFile,"hd3"); + if (!streamHeader) goto fail; + + if (read_32bitBE(0x00,streamHeader) != 0x50334844) /* "P3HD" */ + goto fail; + + /* 0x04: section size (not including first 0x08) */ + /* 0x08: version? 0x00020000 */ + /* 0x10: "P3PG" offset (seems mostly empty and contains number of subsongs towards the end) */ + /* 0x14: "P3TN" offset (some kind of config?) */ + /* 0x18: "P3VA" offset (VAG headers) */ + { + off_t section_offset = read_32bitBE(0x18,streamHeader); + off_t header_offset; + size_t section_size; + int i, entries, is_bgm = 0; + + if (read_32bitBE(section_offset+0x00,streamHeader) != 0x50335641) /* "P3VA" */ + goto fail; + section_size = read_32bitBE(section_offset+0x04,streamHeader); /* (not including first 0x08) */ + /* 0x08 always 0x10? */ + entries = read_32bitBE(section_offset+0x14,streamHeader) + 1; + if (entries != (section_size-0x18) / 0x10) + goto fail; + + /* autodetect use of N bank entries as channels [Elevator Action Deluxe (PS3)] */ + if (entries > 1) { + size_t channel_size = read_32bitBE(section_offset+0x20+0x08,streamHeader); + is_bgm = 1; + + for (i = 1; i < entries; i++) { + size_t next_size = read_32bitBE(section_offset+0x20+(i*0x10)+0x08,streamHeader); + if (channel_size != next_size) { + is_bgm = 0; + break; + } + } + } + + if (is_bgm) { + total_subsongs = 1; + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + + header_offset = section_offset+0x20+(0)*0x10; + start_offset = read_32bitBE(header_offset+0x00,streamHeader); /* 0x00 */ + sample_rate = read_32bitBE(header_offset+0x04,streamHeader); + stream_size = get_streamfile_size(streamFile); + if (read_32bitBE(header_offset+0x0c,streamHeader) != -1) + goto fail; + + channel_count = entries; + interleave = stream_size / channel_count; + } + else { + total_subsongs = entries; + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + + header_offset = section_offset+0x20+(target_subsong-1)*0x10; + start_offset = read_32bitBE(header_offset+0x00,streamHeader); + sample_rate = read_32bitBE(header_offset+0x04,streamHeader); + stream_size = read_32bitBE(header_offset+0x08,streamHeader); + if (read_32bitBE(header_offset+0x0c,streamHeader) != -1) + goto fail; + + channel_count = 1; + interleave = 0; + } + } + + loop_flag = 0; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = ps_bytes_to_samples(stream_size, channel_count); + vgmstream->num_streams = total_subsongs; + vgmstream->stream_size = stream_size; + + vgmstream->meta_type = meta_HD3_BD3; + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = (channel_count == 1) ? layout_none : layout_interleave; + vgmstream->interleave_block_size = interleave; + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + + close_streamfile(streamHeader); + return vgmstream; +fail: + close_streamfile(streamHeader); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/meta.h b/src/meta/meta.h index f853e09d..fecb21d0 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -769,4 +769,6 @@ VGMSTREAM * init_vgmstream_str_wav(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_wavebatch(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_hd3_bd3(STREAMFILE *streamFile); + #endif /*_META_H*/ diff --git a/src/vgmstream.c b/src/vgmstream.c index 8873175a..71cf04b1 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -421,6 +421,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_wv6, init_vgmstream_str_wav, init_vgmstream_wavebatch, + init_vgmstream_hd3_bd3, init_vgmstream_txth, /* should go at the end (lower priority) */ #ifdef VGM_USE_FFMPEG diff --git a/src/vgmstream.h b/src/vgmstream.h index fd064cb0..3876a5c7 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -697,6 +697,7 @@ typedef enum { meta_CKB, /* Cricket Audio bank [Fire Emblem Heroes (Android), Mega Man 1-6 (Android)] */ meta_WV6, /* Gorilla Systems PC games */ meta_WAVEBATCH, /* Firebrand Games */ + meta_HD3_BD3, /* Sony PS3 bank */ #ifdef VGM_USE_FFMPEG meta_FFmpeg,