diff --git a/src/formats.c b/src/formats.c
index 39f00422..7c99d037 100644
--- a/src/formats.c
+++ b/src/formats.c
@@ -25,7 +25,7 @@ static const char* extension_list[] = {
"208",
"2dx9",
"3do",
- "3ds", //txth/reserved [F1 2011 (3DS)]
+ "3ds",
"4", //for Game.com audio
"8", //txth/reserved [Gungage (PS1)]
"800",
@@ -765,17 +765,17 @@ const char** vgmstream_get_common_formats(size_t* size) {
typedef struct {
coding_t type;
- const char *description;
+ const char* description;
} coding_info;
typedef struct {
layout_t type;
- const char *description;
+ const char* description;
} layout_info;
typedef struct {
meta_t type;
- const char *description;
+ const char* description;
} meta_info;
@@ -1459,11 +1459,10 @@ static const meta_info meta_info_list[] = {
{meta_HD_BD, "Sony HD+BD header"},
{meta_PPHD, "Sony PPHD header"},
{meta_XABP, "cavia XABp header"},
+ {meta_I3DS, "Codemasters i3DS header"},
};
void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {
- int i, list_length;
- const char *description;
#ifdef VGM_USE_FFMPEG
if (vgmstream->coding_type == coding_FFmpeg) {
@@ -1481,7 +1480,7 @@ void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t ou
}
#endif
- description = "CANNOT DECODE";
+ const char* description = "CANNOT DECODE";
switch (vgmstream->coding_type) {
#ifdef VGM_USE_FFMPEG
@@ -1491,23 +1490,22 @@ void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t ou
description = "FFmpeg";
break;
#endif
- default:
- list_length = sizeof(coding_info_list) / sizeof(coding_info);
- for (i = 0; i < list_length; i++) {
+ default: {
+ int list_length = sizeof(coding_info_list) / sizeof(coding_info);
+ for (int i = 0; i < list_length; i++) {
if (coding_info_list[i].type == vgmstream->coding_type)
description = coding_info_list[i].description;
}
break;
+ }
}
strncpy(out, description, out_size);
}
static const char* get_layout_name(layout_t layout_type) {
- int i, list_length;
-
- list_length = sizeof(layout_info_list) / sizeof(layout_info);
- for (i = 0; i < list_length; i++) {
+ int list_length = sizeof(layout_info_list) / sizeof(layout_info);
+ for (int i = 0; i < list_length; i++) {
if (layout_info_list[i].type == layout_type)
return layout_info_list[i].description;
}
@@ -1515,13 +1513,12 @@ static const char* get_layout_name(layout_t layout_type) {
return NULL;
}
-static int has_sublayouts(VGMSTREAM** vgmstreams, int count) {
- int i;
- for (i = 0; i < count; i++) {
+static bool has_sublayouts(VGMSTREAM** vgmstreams, int count) {
+ for (int i = 0; i < count; i++) {
if (vgmstreams[i]->layout_type == layout_segmented || vgmstreams[i]->layout_type == layout_layered)
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* Makes a mixed description, considering a segments/layers can contain segments/layers infinitely, like:
@@ -1539,7 +1536,7 @@ static int has_sublayouts(VGMSTREAM** vgmstreams, int count) {
* ("mixed" is added externally)
*/
static int get_layout_mixed_description(VGMSTREAM* vgmstream, char* dst, int dst_size) {
- int i, count, done = 0;
+ int count, done = 0;
VGMSTREAM** vgmstreams = NULL;
if (vgmstream->layout_type == layout_layered) {
@@ -1565,7 +1562,7 @@ static int get_layout_mixed_description(VGMSTREAM* vgmstream, char* dst, int dst
dst[done++] = '[';
}
- for (i = 0; i < count; i++) {
+ for (int i = 0; i < count; i++) {
done += get_layout_mixed_description(vgmstreams[i], dst + done, dst_size - done);
}
@@ -1578,7 +1575,7 @@ static int get_layout_mixed_description(VGMSTREAM* vgmstream, char* dst, int dst
void get_vgmstream_layout_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {
const char* description;
- int mixed = 0;
+ bool mixed = false;
description = get_layout_name(vgmstream->layout_type);
if (!description) description = "INCONCEIVABLE";
@@ -1609,13 +1606,10 @@ void get_vgmstream_layout_description(VGMSTREAM* vgmstream, char* out, size_t ou
}
void get_vgmstream_meta_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {
- int i, list_length;
- const char* description;
+ const char* description = "THEY SHOULD HAVE SENT A POET";
- description = "THEY SHOULD HAVE SENT A POET";
-
- list_length = sizeof(meta_info_list) / sizeof(meta_info);
- for (i=0; i < list_length; i++) {
+ int list_length = sizeof(meta_info_list) / sizeof(meta_info);
+ for (int i = 0; i < list_length; i++) {
if (meta_info_list[i].type == vgmstream->meta_type)
description = meta_info_list[i].description;
}
diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj
index 32cd2276..a411b9ca 100644
--- a/src/libvgmstream.vcxproj
+++ b/src/libvgmstream.vcxproj
@@ -517,6 +517,7 @@
+
diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters
index ba57fe07..470db619 100644
--- a/src/libvgmstream.vcxproj.filters
+++ b/src/libvgmstream.vcxproj.filters
@@ -1381,6 +1381,9 @@
meta\Source Files
+
+ meta\Source Files
+
meta\Source Files
diff --git a/src/meta/i3ds.c b/src/meta/i3ds.c
new file mode 100644
index 00000000..1e74df9f
--- /dev/null
+++ b/src/meta/i3ds.c
@@ -0,0 +1,49 @@
+#include "meta.h"
+#include "../util/meta_utils.h"
+#include "../coding/coding.h"
+
+
+/* i3DS - interleaved dsp [F1 2011 (3DS)] */
+VGMSTREAM* init_vgmstream_i3ds(STREAMFILE* sf) {
+
+ /* checks */
+ if (!is_id32be(0x00,sf, "i3DS"))
+ return NULL;
+ if (!check_extensions(sf, "3ds"))
+ return NULL;
+
+ meta_header_t h = {
+ .meta = meta_I3DS
+ };
+
+ // 04: data start? (0x10)
+ h.data_size = read_u32le(0x08,sf);
+ h.interleave = read_u32le(0x0c,sf);
+
+ // 2 mono CWAV headers pasted together then "DATA" then stream, no loop info but many tracks repeat
+ if (!is_id32be(0x10,sf, "CWAV"))
+ return NULL;
+
+ h.sample_rate = read_s32le(0x10 + 0x4c, sf);
+ h.num_samples = read_s32le(0x10 + 0x54, sf);
+ h.coefs_offset = 0x10 + 0x7c;
+ h.coefs_spacing = 0xC0;
+ //h.hists_offset = 0x00; //?
+ //h.hists_spacing = h.coefs_spacing;
+
+ // interleaved data starts from 0x10 after DATA (chunk *2), so unsure if header's offset are actually used
+ uint32_t chdt_offset = 0x08 + 0x08; //read_u32le(0x10 + 0x6c, sf) + 0x08;
+
+ h.channels = h.interleave ? 2 : 1;
+ h.stream_offset = 0x10 + 0xc0 * h.channels + chdt_offset;
+ h.stream_size = h.data_size - h.stream_offset;
+ if (h.interleave > 0)
+ h.interleave_last = (h.stream_size % (h.interleave * h.channels)) / h.channels;
+
+ h.coding = coding_NGC_DSP;
+ h.layout = layout_interleave;
+ h.open_stream = true;
+ h.sf = sf;
+
+ return alloc_metastream(&h);
+}
diff --git a/src/meta/meta.h b/src/meta/meta.h
index 90c0b363..556eff51 100644
--- a/src/meta/meta.h
+++ b/src/meta/meta.h
@@ -1021,4 +1021,6 @@ VGMSTREAM* init_vgmstream_pphd(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_xabp(STREAMFILE* sf);
+VGMSTREAM* init_vgmstream_i3ds(STREAMFILE* sf);
+
#endif
diff --git a/src/vgmstream_init.c b/src/vgmstream_init.c
index b6a54e37..6ac3c928 100644
--- a/src/vgmstream_init.c
+++ b/src/vgmstream_init.c
@@ -514,6 +514,7 @@ init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_hd_bd,
init_vgmstream_pphd,
init_vgmstream_xabp,
+ init_vgmstream_i3ds,
/* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */
init_vgmstream_agsc,
diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h
index 71c70822..11363bda 100644
--- a/src/vgmstream_types.h
+++ b/src/vgmstream_types.h
@@ -715,6 +715,7 @@ typedef enum {
meta_HD_BD,
meta_PPHD,
meta_XABP,
+ meta_I3DS,
} meta_t;