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,