diff --git a/msvc-build.bat b/msvc-build.bat
index 2b026c25..00b6aa05 100644
--- a/msvc-build.bat
+++ b/msvc-build.bat
@@ -1 +1 @@
-powershell -ExecutionPolicy Bypass -NoProfile -File .\msvc-build.ps1 Build
+powershell -ExecutionPolicy Bypass -NoProfile -File .\msvc-build.ps1 Build
\ No newline at end of file
diff --git a/src/formats.c b/src/formats.c
index f7a90af4..823dc393 100644
--- a/src/formats.c
+++ b/src/formats.c
@@ -431,7 +431,7 @@ static const char* extension_list[] = {
"rxx", //txth/reserved [Full Auto (X360)]
"s14",
- "s3v", //txth/reserved [Sound Voltex 5 (AC)]
+ "s3v", //Sound Voltex (AC)
"sab",
"sad",
"saf",
@@ -1388,6 +1388,7 @@ static const meta_info meta_info_list[] = {
{meta_DSP_APEX, "Koei Tecmo APEX header"},
{meta_MPEG, "MPEG header"},
{meta_SSPF, "Konami SSPF header"},
+ {meta_S3V, "Konami S3V header"},
};
void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {
diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj
index f2d84dd6..01291886 100644
--- a/src/libvgmstream.vcxproj
+++ b/src/libvgmstream.vcxproj
@@ -245,6 +245,7 @@
+
diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters
index a3c74ab1..5dd9e6f2 100644
--- a/src/libvgmstream.vcxproj.filters
+++ b/src/libvgmstream.vcxproj.filters
@@ -1981,5 +1981,8 @@
meta\Source Files
+
+ meta\Source Files
+
\ No newline at end of file
diff --git a/src/meta/2dx9.c b/src/meta/2dx9.c
index 911b6f6a..cefd664e 100644
--- a/src/meta/2dx9.c
+++ b/src/meta/2dx9.c
@@ -24,7 +24,7 @@ VGMSTREAM * init_vgmstream_2dx9(STREAMFILE *streamFile) {
if (read_32bitBE(0x6a,streamFile) != 0x64617461) /* data */
goto fail;
- loop_flag = 0;
+ loop_flag = (read_16bitLE(0x0e,streamFile) > 0);
channel_count = read_16bitLE(0x2e,streamFile);
start_offset = 0x72;
@@ -35,6 +35,11 @@ VGMSTREAM * init_vgmstream_2dx9(STREAMFILE *streamFile) {
vgmstream->meta_type = meta_2DX9;
vgmstream->sample_rate = read_32bitLE(0x30,streamFile);
vgmstream->num_samples = read_32bitLE(0x66,streamFile);
+ if (loop_flag) {
+ vgmstream->loop_start_sample = 0;
+ vgmstream->loop_end_sample = vgmstream->num_samples;
+ }
+
vgmstream->coding_type = coding_MSADPCM;
vgmstream->layout_type = layout_none;
vgmstream->frame_size = read_16bitLE(0x38,streamFile);
diff --git a/src/meta/meta.h b/src/meta/meta.h
index 3a70308e..034751d2 100644
--- a/src/meta/meta.h
+++ b/src/meta/meta.h
@@ -980,4 +980,6 @@ VGMSTREAM* init_vgmstream_mpeg(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_sspf(STREAMFILE* sf);
+VGMSTREAM* init_vgmstream_s3v(STREAMFILE* sf);
+
#endif /*_META_H*/
diff --git a/src/meta/s3v.c b/src/meta/s3v.c
new file mode 100644
index 00000000..d309bed8
--- /dev/null
+++ b/src/meta/s3v.c
@@ -0,0 +1,62 @@
+#include "meta.h"
+#include "../coding/coding.h"
+
+/* S3V - from Konami arcade games [SOUND VOLTEX series (AC)] */
+VGMSTREAM * init_vgmstream_s3v(STREAMFILE *sf) {
+ VGMSTREAM * vgmstream = NULL;
+ off_t start_offset;
+ int32_t channel_count, loop_flag;
+ size_t data_size;
+
+ /* checks */
+ if (!check_extensions(sf, "s3v"))
+ goto fail;
+
+ /* check header */
+ if (read_32bitBE(0x00,sf) != 0x53335630) /* S3V0 */
+ goto fail;
+
+ /* No discernible loop_flag so we'll just use signatures.
+ Might have to update on a per game basis. */
+ switch (read_32bitBE(0x14, sf)) {
+ case 0x82FA0000: // SOUND VOLTEX EXCEED GEAR ver5
+ case 0x1BFD0000: // SOUND VOLTEX EXCEED GEAR ver6
+ loop_flag = 1;
+ break;
+
+ default:
+ loop_flag = 0;
+ }
+
+ start_offset = 0x20;
+ data_size = read_32bitLE(0x08, sf);
+ channel_count = 2;
+
+ /* build the VGMSTREAM */
+ vgmstream = allocate_vgmstream(channel_count,loop_flag);
+ if (!vgmstream) goto fail;
+ vgmstream->meta_type = meta_S3V;
+
+#ifdef VGM_USE_FFMPEG
+
+ vgmstream->codec_data = init_ffmpeg_offset(sf, start_offset, data_size);
+ if (!vgmstream->codec_data) goto fail;
+ vgmstream->sample_rate = ffmpeg_get_sample_rate(vgmstream->codec_data);
+ vgmstream->num_samples = ffmpeg_get_samples(vgmstream->codec_data);
+ if (loop_flag) {
+ vgmstream->loop_start_sample = read_32bitLE(0x10, sf);
+ vgmstream->loop_end_sample = vgmstream->num_samples;
+ }
+ vgmstream->coding_type = coding_FFmpeg;
+ vgmstream->layout_type = layout_none;
+
+#endif
+
+ if (!vgmstream_open_stream(vgmstream, sf, start_offset))
+ goto fail;
+ return vgmstream;
+
+fail:
+ close_vgmstream(vgmstream);
+ return NULL;
+}
diff --git a/src/meta/sd9.c b/src/meta/sd9.c
index dbe9d264..8fa47d35 100644
--- a/src/meta/sd9.c
+++ b/src/meta/sd9.c
@@ -22,12 +22,11 @@ VGMSTREAM * init_vgmstream_sd9(STREAMFILE *streamFile) {
if (read_32bitBE(0x72, streamFile) != 0x64617461) /* data */
goto fail;
- /* Probably better to check if loop end exists and use as loop flag.
- Blame SD9s from beatmania IIDX 21: Spada that have a flase flag
- but still "loop" */
+ /* Some SD9s may loop without any loop points specificed.
+ If loop_flag is set with no points, loop entire song. */
- //loop_flag = (read_16bitLE(0x0e,streamFile)==0x1);
- loop_flag = read_32bitLE(0x18, streamFile); // use loop end
+ loop_flag = read_16bitLE(0x0e,streamFile);
+ //loop_flag = read_32bitLE(0x18, streamFile); // use loop end
channel_count = read_16bitLE(0x36, streamFile);
start_offset = 0x7a;
@@ -37,7 +36,17 @@ VGMSTREAM * init_vgmstream_sd9(STREAMFILE *streamFile) {
vgmstream->sample_rate = read_32bitLE(0x38, streamFile);
vgmstream->num_samples = read_32bitLE(0x6e, streamFile);
- if (loop_flag) {
+ if (loop_flag > 0) {
+ vgmstream->loop_start_sample = read_32bitLE(0x14, streamFile) / 2 / channel_count;
+ vgmstream->loop_end_sample = read_32bitLE(0x18, streamFile) / 2 / channel_count;
+ if (vgmstream->loop_end_sample == 0) {
+ vgmstream->loop_end_sample = vgmstream->num_samples;
+ }
+ }
+
+ /* beatmania IIDX 21: Spada is a special case. Loop flag is false but loops exist.
+ Konami, Why? */
+ if ((loop_flag < 0) && (read_32bitLE(0x18, streamFile) !=0)) {
vgmstream->loop_start_sample = read_32bitLE(0x14, streamFile) / 2 / channel_count;
vgmstream->loop_end_sample = read_32bitLE(0x18, streamFile) / 2 / channel_count;
}
diff --git a/src/vgmstream.c b/src/vgmstream.c
index 3e0b9b95..bad69dc5 100644
--- a/src/vgmstream.c
+++ b/src/vgmstream.c
@@ -521,6 +521,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_ubi_ckd_cwav,
init_vgmstream_sspf,
init_vgmstream_opus_rsnd,
+ init_vgmstream_s3v,
/* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */
init_vgmstream_mpeg,
diff --git a/src/vgmstream.h b/src/vgmstream.h
index 690aed90..b3142e30 100644
--- a/src/vgmstream.h
+++ b/src/vgmstream.h
@@ -755,6 +755,7 @@ typedef enum {
meta_DSP_APEX,
meta_MPEG,
meta_SSPF,
+ meta_S3V,
} meta_t;