Add Codemasters .3ds [F1 2011 (3DS)]

This commit is contained in:
bnnm 2025-01-19 00:26:22 +01:00
parent 7d967a2b49
commit 45ed922338
7 changed files with 79 additions and 28 deletions

View File

@ -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;
}

View File

@ -517,6 +517,7 @@
<ClCompile Include="meta\hgc1.c" />
<ClCompile Include="meta\his.c" />
<ClCompile Include="meta\hxd.c" />
<ClCompile Include="meta\i3ds.c" />
<ClCompile Include="meta\idsp_ie.c" />
<ClCompile Include="meta\idtech.c" />
<ClCompile Include="meta\ifs.c" />

View File

@ -1381,6 +1381,9 @@
<ClCompile Include="meta\hxd.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\i3ds.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\idsp_ie.c">
<Filter>meta\Source Files</Filter>
</ClCompile>

49
src/meta/i3ds.c Normal file
View File

@ -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);
}

View File

@ -1021,4 +1021,6 @@ VGMSTREAM* init_vgmstream_pphd(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_xabp(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_i3ds(STREAMFILE* sf);
#endif

View File

@ -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,

View File

@ -715,6 +715,7 @@ typedef enum {
meta_HD_BD,
meta_PPHD,
meta_XABP,
meta_I3DS,
} meta_t;