mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-25 07:20:10 +01:00
commit
254791551b
@ -120,8 +120,9 @@ handling.
|
||||
A few extensions that vgmstream supports clash with common ones. Since players
|
||||
like foobar or Winamp don't react well to that, they may be renamed for
|
||||
vgmstream (mainly to get looping in some cases).
|
||||
- .ac3 to .lac3
|
||||
- .aac to .laac
|
||||
- .ac3 to .lac3
|
||||
- .aif to .aiffl or .aifcl
|
||||
- .asf to .sng (EA formats)
|
||||
- .mp4 to .lmp4
|
||||
- .ogg to .logg
|
||||
|
@ -28,9 +28,11 @@ static const char* extension_list[] = {
|
||||
"afc",
|
||||
"agsc",
|
||||
"ahx",
|
||||
"aifc",
|
||||
"aifcl",
|
||||
//"aif", //common
|
||||
"aifc", //common?
|
||||
"aifcl", //fake extension, for AIF???
|
||||
//"aiff", //common
|
||||
"aiffl", //fake extension, for AIF???
|
||||
"aix",
|
||||
"akb",
|
||||
"al2",
|
||||
@ -137,6 +139,7 @@ static const char* extension_list[] = {
|
||||
"gtd",
|
||||
"gwm",
|
||||
|
||||
"h4m",
|
||||
"hca",
|
||||
"hgc1",
|
||||
"his",
|
||||
@ -621,6 +624,7 @@ static const layout_info layout_info_list[] = {
|
||||
{layout_blocked_ea_wve_au00, "blocked (EA WVE au00)"},
|
||||
{layout_blocked_ea_wve_ad10, "blocked (EA WVE Ad10)"},
|
||||
{layout_blocked_sthd, "blocked (STHD)"},
|
||||
{layout_blocked_h4m, "blocked (H4M)"},
|
||||
};
|
||||
|
||||
static const meta_info meta_info_list[] = {
|
||||
@ -687,8 +691,8 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_SADL, "Procyon Studio SADL header"},
|
||||
{meta_PS2_BMDX, "Beatmania .bmdx header"},
|
||||
{meta_DSP_WSI, "Alone in the Dark .WSI header"},
|
||||
{meta_AIFC, "Audio Interchange File Format AIFF-C"},
|
||||
{meta_AIFF, "Audio Interchange File Format"},
|
||||
{meta_AIFC, "Apple AIFF-C (Audio Interchange File Format) header"},
|
||||
{meta_AIFF, "Apple AIFF (Audio Interchange File Format) header"},
|
||||
{meta_STR_SNDS, ".str SNDS SHDR chunk"},
|
||||
{meta_WS_AUD, "Westwood Studios .aud header"},
|
||||
{meta_WS_AUD_old, "Westwood Studios .aud (old) header"},
|
||||
@ -798,7 +802,7 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_YDSP, "Yuke's DSP (YDSP) Header"},
|
||||
{meta_MSVP, "MSVP Header"},
|
||||
{meta_NGC_SSM, "SSM DSP Header"},
|
||||
{meta_PS2_JOE, "Disney/Pixar JOE Header"},
|
||||
{meta_PS2_JOE, "Asobo Studio .JOE header"},
|
||||
{meta_VGS, "Guitar Hero VGS Header"},
|
||||
{meta_DC_DCSW_DCS, "Evil Twin DCS file with helper"},
|
||||
{meta_WII_SMP, "SMP DSP Header"},
|
||||
@ -1018,6 +1022,7 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_TA_AAC_VITA, "tri-Ace AAC (Vita) header"},
|
||||
{meta_OGG_GWM, "Ogg Vorbis (GWM header)"},
|
||||
{meta_DSP_SADF, "Procyon Studio SADF header"},
|
||||
{meta_H4M, "Hudson HVQM4 header"},
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
{meta_FFmpeg, "FFmpeg supported file format"},
|
||||
|
@ -202,6 +202,9 @@ static void block_update(VGMSTREAM * vgmstream) {
|
||||
case layout_blocked_sthd:
|
||||
block_update_sthd(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_blocked_h4m:
|
||||
block_update_h4m(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
102
src/layout/blocked_h4m.c
Normal file
102
src/layout/blocked_h4m.c
Normal file
@ -0,0 +1,102 @@
|
||||
#include "layout.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
|
||||
/* H4M video blocks with audio frames, based on h4m_audio_decode */
|
||||
void block_update_h4m(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
STREAMFILE* streamFile = vgmstream->ch[0].streamfile;
|
||||
int i;
|
||||
size_t block_size, block_samples;
|
||||
|
||||
|
||||
/* use full_block_size as counter (a bit hacky but whatevs) */
|
||||
if (vgmstream->full_block_size <= 0) {
|
||||
/* new full block */
|
||||
/* 0x00: last_full_block_size */
|
||||
uint32_t full_block_size = read_32bitBE(block_offset+0x04, streamFile);
|
||||
/* 0x08: vid_frame_count */
|
||||
/* 0x0c: aud_frame_count */
|
||||
/* 0x10: block_header_unk (0x01000000, except 0 in a couple of Bomberman Jetters files) */
|
||||
|
||||
vgmstream->full_block_size = full_block_size; /* not including 0x14 block header */
|
||||
block_size = 0x14; /* skip header and point to first frame in full block */
|
||||
block_samples = 0; /* signal new block_update_h4m */
|
||||
}
|
||||
else {
|
||||
/* new audio or video frames in the current full block */
|
||||
uint16_t frame_type = read_16bitBE(block_offset+0x00, streamFile);
|
||||
uint16_t frame_format = read_16bitBE(block_offset+0x02, streamFile);
|
||||
uint32_t frame_size = read_32bitBE(block_offset+0x04, streamFile); /* not including 0x08 frame header */
|
||||
|
||||
|
||||
if (frame_type == 0x00) {
|
||||
/* HVQM4_AUDIO (there are more checks with frame_format but not too relevant for vgmstream) */
|
||||
uint32_t frame_samples = read_32bitBE(block_offset+0x08, streamFile);
|
||||
size_t block_skip;
|
||||
|
||||
if (vgmstream->codec_version & 0x80) {
|
||||
frame_samples /= 2; /* ??? */
|
||||
}
|
||||
|
||||
block_skip = 0x08 + 0x04;
|
||||
block_size = 0x08 + frame_size;
|
||||
block_samples = frame_samples;
|
||||
|
||||
|
||||
/* skip data from other audio tracks */
|
||||
if (vgmstream->num_streams) {
|
||||
uint32_t audio_bytes = frame_size - 0x04;
|
||||
block_skip += (audio_bytes / vgmstream->num_streams) * vgmstream->stream_index;
|
||||
}
|
||||
|
||||
//VGM_ASSERT(frame_format < 1 && frame_format > 3, "H4M: unknown frame_format %x at %lx\n", frame_format, block_offset);
|
||||
VGM_ASSERT(frame_format == 1, "H4M: unknown frame_format %x at %lx\n", frame_format, block_offset);
|
||||
|
||||
//todo handle in the decoder?
|
||||
//todo right channel first?
|
||||
/* get ADPCM hist (usually every new block) */
|
||||
for (i = 0; i < vgmstream->channels; i++) {
|
||||
if (frame_format == 1) { /* combined hist+index */
|
||||
vgmstream->ch[i].adpcm_history1_32 = read_16bitBE(block_offset + block_skip + 0x02*i + 0x00,streamFile) & 0xFFFFFF80;
|
||||
vgmstream->ch[i].adpcm_step_index = read_8bit(block_offset + block_skip + 0x02*i + 0x01,streamFile) & 0x7f;
|
||||
vgmstream->ch[i].offset = block_offset + block_skip + 0x02*vgmstream->channels;
|
||||
}
|
||||
else if (frame_format == 3) { /* separate hist+index */
|
||||
vgmstream->ch[i].adpcm_history1_32 = read_16bitBE(block_offset + block_skip + 0x03*i + 0x00,streamFile);
|
||||
vgmstream->ch[i].adpcm_step_index = read_8bit(block_offset + block_skip + 0x03*i + 0x02,streamFile);
|
||||
vgmstream->ch[i].offset = block_offset + block_skip + 0x03*vgmstream->channels;
|
||||
}
|
||||
else if (frame_format == 2) { /* no hist/index */
|
||||
vgmstream->ch[i].offset = block_offset + block_skip;
|
||||
}
|
||||
}
|
||||
|
||||
//todo temp hack, at it must write header sample and ignore the last nibble to get fully correct output
|
||||
if (frame_format == 1 || frame_format == 3) {
|
||||
block_samples--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
block_size = 0x08 + frame_size;
|
||||
block_samples = 0; /* signal new block_update_h4m */
|
||||
}
|
||||
|
||||
vgmstream->full_block_size -= block_size;
|
||||
}
|
||||
|
||||
/* EOF check, there is some footer/garbage at the end */
|
||||
if (block_offset == get_streamfile_size(streamFile)
|
||||
|| block_offset + block_size > get_streamfile_size(streamFile)) {
|
||||
//block_samples = -1; /* signal end block */
|
||||
vgmstream->full_block_size = 0;
|
||||
vgmstream->current_block_samples = 0;
|
||||
vgmstream->current_block_offset = get_streamfile_size(streamFile);
|
||||
vgmstream->next_block_offset = get_streamfile_size(streamFile);
|
||||
return;
|
||||
}
|
||||
|
||||
vgmstream->current_block_samples = block_samples;
|
||||
vgmstream->current_block_offset = block_offset;
|
||||
vgmstream->next_block_offset = block_offset + block_size;
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ void block_update_xvag_subsong(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_ea_wve_au00(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_ea_wve_ad10(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_sthd(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_h4m(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
/* other layouts */
|
||||
void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
|
||||
|
@ -483,6 +483,10 @@
|
||||
<File
|
||||
RelativePath=".\meta\gtd.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\h4m.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\halpst.c"
|
||||
@ -1822,6 +1826,10 @@
|
||||
RelativePath=".\layout\blocked_gsb.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\layout\blocked_h4m.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\layout\blocked_halpst.c"
|
||||
>
|
||||
|
@ -235,6 +235,7 @@
|
||||
<ClCompile Include="meta\bar.c" />
|
||||
<ClCompile Include="meta\gsp_gsb.c" />
|
||||
<ClCompile Include="meta\gtd.c" />
|
||||
<ClCompile Include="meta\h4m.c" />
|
||||
<ClCompile Include="meta\halpst.c" />
|
||||
<ClCompile Include="meta\hca.c" />
|
||||
<ClCompile Include="meta\his.c" />
|
||||
@ -503,6 +504,7 @@
|
||||
<ClCompile Include="layout\blocked_emff.c" />
|
||||
<ClCompile Include="layout\blocked_filp.c" />
|
||||
<ClCompile Include="layout\blocked_gsb.c" />
|
||||
<ClCompile Include="layout\blocked_h4m.c" />
|
||||
<ClCompile Include="layout\blocked_halpst.c" />
|
||||
<ClCompile Include="layout\blocked_matx.c" />
|
||||
<ClCompile Include="layout\interleave.c" />
|
||||
|
@ -295,6 +295,9 @@
|
||||
<ClCompile Include="meta\gtd.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\h4m.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\halpst.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -1075,6 +1078,9 @@
|
||||
<ClCompile Include="layout\blocked_gsb.c">
|
||||
<Filter>layout\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="layout\blocked_h4m.c">
|
||||
<Filter>layout\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="layout\blocked_halpst.c">
|
||||
<Filter>layout\Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
145
src/meta/aifc.c
145
src/meta/aifc.c
@ -1,11 +1,6 @@
|
||||
#include "meta.h"
|
||||
#include "../layout/layout.h"
|
||||
#include "../util.h"
|
||||
|
||||
/* Audio Interchange File Format AIFF-C */
|
||||
/* also plain AIFF, for good measure */
|
||||
|
||||
/* Included primarily for 3DO */
|
||||
|
||||
/* for reading integers inexplicably packed into 80 bit floats */
|
||||
static uint32_t read80bitSANE(off_t offset, STREAMFILE *streamFile) {
|
||||
@ -53,9 +48,10 @@ static uint32_t find_marker(STREAMFILE *streamFile, off_t MarkerChunkOffset,
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Audio Interchange File Format AIFF/AIFF-C - from Mac/3DO games */
|
||||
VGMSTREAM * init_vgmstream_aifc(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
|
||||
off_t file_size = -1;
|
||||
int channel_count = 0;
|
||||
@ -82,22 +78,23 @@ VGMSTREAM * init_vgmstream_aifc(STREAMFILE *streamFile) {
|
||||
int InstrumentChunkFound =0;
|
||||
off_t InstrumentChunkOffset = -1;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (!strcasecmp("aifc",filename_extension(filename)) ||
|
||||
!strcasecmp("afc",filename_extension(filename)) ||
|
||||
!strcasecmp("aifcl",filename_extension(filename)) ||
|
||||
!strcasecmp("cbd2",filename_extension(filename)))
|
||||
{
|
||||
|
||||
/* checks */
|
||||
/* .aif: common (AIFF or AIFC), .aiff: common AIFF, .aifc: common AIFC
|
||||
* .cbd2: M2 games, .bgm: Super Street Fighter II Turbo (3DO), aifcl/aiffl: for plugins? */
|
||||
if (check_extensions(streamFile, "aif")) {
|
||||
AIFCext = 1;
|
||||
}
|
||||
else if (!strcasecmp("aiff",filename_extension(filename)) ||
|
||||
!strcasecmp("aif",filename_extension(filename)) ||
|
||||
!strcasecmp("aiffl",filename_extension(filename)))
|
||||
{
|
||||
AIFFext = 1;
|
||||
}
|
||||
else goto fail;
|
||||
else if (check_extensions(streamFile, "aifc,aifcl,afc,cbd2,bgm")) {
|
||||
AIFCext = 1;
|
||||
}
|
||||
else if (check_extensions(streamFile, "aiff,aiffl")) {
|
||||
AIFFext = 1;
|
||||
}
|
||||
else {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* check header */
|
||||
if ((uint32_t)read_32bitBE(0,streamFile)==0x464F524D && /* "FORM" */
|
||||
@ -115,13 +112,16 @@ VGMSTREAM * init_vgmstream_aifc(STREAMFILE *streamFile) {
|
||||
AIFF = 1;
|
||||
}
|
||||
else goto fail;
|
||||
} else goto fail;
|
||||
|
||||
}
|
||||
else {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
file_size = get_streamfile_size(streamFile);
|
||||
|
||||
/* read through chunks to verify format and find metadata */
|
||||
{
|
||||
off_t current_chunk = 0xc; /* start with first chunk within FORM */
|
||||
off_t current_chunk = 0x0c; /* start with first chunk within FORM */
|
||||
|
||||
while (current_chunk < file_size) {
|
||||
uint32_t chunk_type = read_32bitBE(current_chunk,streamFile);
|
||||
@ -134,54 +134,55 @@ VGMSTREAM * init_vgmstream_aifc(STREAMFILE *streamFile) {
|
||||
if (current_chunk+8+chunk_size > file_size) goto fail;
|
||||
|
||||
switch(chunk_type) {
|
||||
case 0x46564552: /* FVER */
|
||||
/* only one per file */
|
||||
case 0x46564552: /* "FVER" (version info) */
|
||||
if (FormatVersionChunkFound) goto fail;
|
||||
/* plain AIFF shouldn't have */
|
||||
if (AIFF) goto fail;
|
||||
if (AIFF) goto fail; /* plain AIFF shouldn't have */
|
||||
FormatVersionChunkFound = 1;
|
||||
|
||||
/* specific size */
|
||||
if (chunk_size != 4) goto fail;
|
||||
|
||||
/* Version 1 of AIFF-C spec timestamp */
|
||||
if ((uint32_t)read_32bitBE(current_chunk+8,streamFile) !=
|
||||
0xA2805140) goto fail;
|
||||
if ((uint32_t)read_32bitBE(current_chunk+8,streamFile) != 0xA2805140) goto fail;
|
||||
break;
|
||||
case 0x434F4D4D: /* COMM */
|
||||
/* only one per file */
|
||||
|
||||
case 0x434F4D4D: /* "COMM" (main header) */
|
||||
if (CommonChunkFound) goto fail;
|
||||
CommonChunkFound = 1;
|
||||
|
||||
channel_count = read_16bitBE(current_chunk+8,streamFile);
|
||||
if (channel_count <= 0) goto fail;
|
||||
|
||||
sample_count = (uint32_t)read_32bitBE(current_chunk+0xa,streamFile);
|
||||
|
||||
sample_size = read_16bitBE(current_chunk+0xe,streamFile);
|
||||
|
||||
sample_count = (uint32_t)read_32bitBE(current_chunk+0x0a,streamFile); /* number of blocks, actually */
|
||||
sample_size = read_16bitBE(current_chunk+0x0e,streamFile);
|
||||
sample_rate = read80bitSANE(current_chunk+0x10,streamFile);
|
||||
|
||||
if (AIFC) {
|
||||
switch (read_32bitBE(current_chunk+0x1a,streamFile)) {
|
||||
case 0x53445832: /* SDX2 */
|
||||
case 0x53445832: /* "SDX2" [3DO games: Super Street Fighter II Turbo (3DO), etc] */
|
||||
coding_type = coding_SDX2;
|
||||
interleave = 1;
|
||||
interleave = 0x01;
|
||||
break;
|
||||
case 0x43424432: /* CBD2 */
|
||||
case 0x43424432: /* "CBD2" [M2 (arcade 3DO) games: IMSA Racing (M2), etc] */
|
||||
coding_type = coding_CBD2;
|
||||
interleave = 1;
|
||||
interleave = 0x01;
|
||||
break;
|
||||
case 0x41445034: /* ADP4 */
|
||||
case 0x41445034: /* "ADP4" */
|
||||
coding_type = coding_DVI_IMA_int;
|
||||
/* don't know how stereo DVI is laid out */
|
||||
if (channel_count != 1) break;
|
||||
if (channel_count != 1) break; /* don't know how stereo DVI is laid out */
|
||||
break;
|
||||
case 0x696D6134: /* "ima4" [Alida (PC) Lunar SSS (iOS)] */
|
||||
coding_type = coding_APPLE_IMA4;
|
||||
interleave = 0x22;
|
||||
sample_count = sample_count * ((interleave-0x2)*2);
|
||||
break;
|
||||
default:
|
||||
/* we should probably support uncompressed here */
|
||||
VGM_LOG("AIFC: unknown codec\n");
|
||||
goto fail;
|
||||
}
|
||||
} else if (AIFF) {
|
||||
/* string size and human-readable AIFF-C codec follows */
|
||||
}
|
||||
else if (AIFF) {
|
||||
switch (sample_size) {
|
||||
case 8:
|
||||
coding_type = coding_PCM8;
|
||||
@ -191,39 +192,40 @@ VGMSTREAM * init_vgmstream_aifc(STREAMFILE *streamFile) {
|
||||
coding_type = coding_PCM16BE;
|
||||
interleave = 2;
|
||||
break;
|
||||
/* 32 is a possibility, but we don't see it and I
|
||||
* don't have a reader for it yet */
|
||||
default:
|
||||
VGM_LOG("AIFF: unknown codec\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* we don't check the human-readable portion of AIFF-C*/
|
||||
|
||||
break;
|
||||
case 0x53534E44: /* SSND */
|
||||
/* at most one per file */
|
||||
|
||||
case 0x53534E44: /* "SSND" (main data) */
|
||||
if (SoundDataChunkFound) goto fail;
|
||||
SoundDataChunkFound = 1;
|
||||
|
||||
start_offset = current_chunk + 16 + read_32bitBE(current_chunk+8,streamFile);
|
||||
break;
|
||||
case 0x4D41524B: /* MARK */
|
||||
|
||||
case 0x4D41524B: /* "MARK" (loops) */
|
||||
if (MarkerChunkFound) goto fail;
|
||||
MarkerChunkFound = 1;
|
||||
|
||||
MarkerChunkOffset = current_chunk;
|
||||
break;
|
||||
case 0x494E5354: /* INST */
|
||||
|
||||
case 0x494E5354: /* "INST" (loops) */
|
||||
if (InstrumentChunkFound) goto fail;
|
||||
InstrumentChunkFound = 1;
|
||||
|
||||
InstrumentChunkOffset = current_chunk;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* spec says we can skip unrecognized chunks */
|
||||
break;
|
||||
}
|
||||
|
||||
current_chunk += 8+chunk_size;
|
||||
current_chunk += 0x08+chunk_size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,6 +237,7 @@ VGMSTREAM * init_vgmstream_aifc(STREAMFILE *streamFile) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
/* read loop points */
|
||||
if (InstrumentChunkFound && MarkerChunkFound) {
|
||||
int start_marker;
|
||||
@ -262,49 +265,31 @@ VGMSTREAM * init_vgmstream_aifc(STREAMFILE *streamFile) {
|
||||
}
|
||||
}
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->num_samples = sample_count;
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
|
||||
vgmstream->coding_type = coding_type;
|
||||
if (channel_count > 1)
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
else
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
vgmstream->num_samples = sample_count;
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end;
|
||||
|
||||
vgmstream->coding_type = coding_type;
|
||||
vgmstream->layout_type = (channel_count > 1) ? layout_interleave : layout_none;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
|
||||
if (AIFC)
|
||||
vgmstream->meta_type = meta_AIFC;
|
||||
else if (AIFF)
|
||||
vgmstream->meta_type = meta_AIFF;
|
||||
|
||||
/* open the file, set up each channel */
|
||||
{
|
||||
int i;
|
||||
|
||||
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,
|
||||
STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!vgmstream->ch[0].streamfile) goto fail;
|
||||
|
||||
for (i=0;i<channel_count;i++) {
|
||||
vgmstream->ch[i].streamfile = vgmstream->ch[0].streamfile;
|
||||
vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset =
|
||||
start_offset+i*interleave;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
105
src/meta/h4m.c
Normal file
105
src/meta/h4m.c
Normal file
@ -0,0 +1,105 @@
|
||||
#include "meta.h"
|
||||
#include "../layout/layout.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* H4M - from Hudson HVQM4 videos [Resident Evil 0 (GC), Tales of Symphonia (GC)]
|
||||
* (info from hcs/Nisto's h4m_audio_decode) */
|
||||
VGMSTREAM * init_vgmstream_h4m(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
int loop_flag, channel_count;
|
||||
int format, extra_tracks, sample_rate;
|
||||
int total_subsongs, target_subsong = streamFile->stream_index;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "h4m"))
|
||||
goto fail;
|
||||
|
||||
if (read_32bitBE(0x00,streamFile) != 0x4856514D && /* "HVQM" */
|
||||
read_32bitBE(0x04,streamFile) != 0x3420312E) /* "4 1." */
|
||||
goto fail;
|
||||
if (read_32bitBE(0x08,streamFile) != 0x33000000 && /* "3\0\0\0" */
|
||||
read_32bitBE(0x08,streamFile) != 0x35000000) /* "5\0\0\0" */
|
||||
goto fail;
|
||||
|
||||
/* header */
|
||||
start_offset = read_32bitBE(0x10, streamFile); /* header_size */
|
||||
if (start_offset != 0x44) /* known size */
|
||||
goto fail;
|
||||
if (read_32bitBE(0x14, streamFile) != get_streamfile_size(streamFile) - start_offset) /* body_size */
|
||||
goto fail;
|
||||
if (read_32bitBE(0x18, streamFile) == 0) /* blocks */
|
||||
goto fail;
|
||||
/* 0x1c: video_frames */
|
||||
if (read_32bitBE(0x20, streamFile) == 0) /* audio_frames */
|
||||
goto fail;
|
||||
/* 0x24: frame interval */
|
||||
/* 0x28: max_video_frame_size */
|
||||
/* 0x2c: unk2C (0) */
|
||||
if (read_32bitBE(0x30, streamFile) == 0) /* max_audio_frame_size */
|
||||
goto fail;
|
||||
/* 0x34: hres */
|
||||
/* 0x36: vres */
|
||||
/* 0x38: h_srate */
|
||||
/* 0x39: v_srate */
|
||||
/* 0x3a: unk3A (0 or 0x12) */
|
||||
/* 0x3b: unk3B (0) */
|
||||
channel_count = read_8bit(0x3c,streamFile);
|
||||
if (read_8bit(0x3d,streamFile) != 16) /* bitdepth */ //todo Pikmin not working
|
||||
goto fail;
|
||||
format = read_8bit(0x3e,streamFile); /* flags? */
|
||||
extra_tracks = read_8bit(0x3f,streamFile);
|
||||
sample_rate = read_32bitBE(0x40,streamFile);
|
||||
|
||||
loop_flag = 0;
|
||||
|
||||
total_subsongs = extra_tracks + 1; /* tracks for languages [Pokemon Channel], or sometimes used to fake multichannel [Tales of Symphonia] */
|
||||
if (target_subsong == 0) target_subsong = 1;
|
||||
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->num_streams = total_subsongs;
|
||||
vgmstream->stream_size = get_streamfile_size(streamFile) / total_subsongs; /* approx... */
|
||||
vgmstream->codec_version = format; /* for blocks */
|
||||
vgmstream->meta_type = meta_H4M;
|
||||
vgmstream->layout_type = layout_blocked_h4m;
|
||||
|
||||
switch(format & 0x7F) {
|
||||
case 0x00:
|
||||
vgmstream->coding_type = coding_DVI_IMA; //todo H4M_IMA
|
||||
break;
|
||||
/* no games known to use this, h4m_audio_decode may decode them */
|
||||
case 0x01: /* Uncompressed PCM */
|
||||
case 0x04: /* 8-bit (A)DPCM */
|
||||
default:
|
||||
VGM_LOG("H4M: unknown codec %x\n", format);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
|
||||
/* calc num_samples manually */
|
||||
{
|
||||
vgmstream->next_block_offset = start_offset;
|
||||
do {
|
||||
block_update_h4m(vgmstream->next_block_offset,vgmstream);
|
||||
vgmstream->num_samples += vgmstream->current_block_samples;
|
||||
}
|
||||
while (vgmstream->next_block_offset < get_streamfile_size(streamFile));
|
||||
}
|
||||
|
||||
block_update_h4m(start_offset, vgmstream);
|
||||
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
@ -754,4 +754,7 @@ VGMSTREAM * init_vgmstream_ubi_bao_pk(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_dsp_switch_audio(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_dsp_sadf(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_h4m(STREAMFILE *streamFile);
|
||||
|
||||
#endif /*_META_H*/
|
||||
|
@ -1,114 +1,119 @@
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* JOE (found in Wall-E and some more Pixar games) */
|
||||
/* .JOE - from Asobo Studio games [Up (PS2), Wall-E (PS2)] */
|
||||
VGMSTREAM * init_vgmstream_ps2_joe(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
off_t start_offset;
|
||||
uint8_t testBuffer[0x10];
|
||||
off_t loopStart = 0;
|
||||
off_t loopEnd = 0;
|
||||
off_t readOffset = 0;
|
||||
off_t blockOffset = 0;
|
||||
off_t sampleOffset = 0;
|
||||
size_t fileLength;
|
||||
size_t dataLength;
|
||||
size_t dataInterleave;
|
||||
size_t file_size, data_size, unknown1, unknown2, interleave;
|
||||
int loop_flag;
|
||||
int channel_count;
|
||||
int channel_count;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("joe",filename_extension(filename))) goto fail;
|
||||
|
||||
/* check header */
|
||||
// if (read_32bitBE(0x0C,streamFile) != 0xCCCCCCCC)
|
||||
// goto fail;
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "joe"))
|
||||
goto fail;
|
||||
|
||||
loop_flag = 1;
|
||||
channel_count = 2;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
file_size = get_streamfile_size(streamFile);
|
||||
data_size = read_32bitLE(0x04,streamFile);
|
||||
unknown1 = read_32bitLE(0x08,streamFile);
|
||||
unknown2 = read_32bitLE(0x0c,streamFile);
|
||||
|
||||
/* detect version */
|
||||
if (data_size/2 == file_size - 0x10
|
||||
&& unknown1 == 0x0045039A && unknown2 == 0x00108920) { /* Super Farm */
|
||||
data_size = data_size / 2;
|
||||
interleave = 0x4000;
|
||||
}
|
||||
else if (data_size/2 == file_size - 0x10
|
||||
&& unknown1 == 0xCCCCCCCC && unknown2 == 0xCCCCCCCC) { /* Sitting Ducks */
|
||||
data_size = data_size / 2;
|
||||
interleave = 0x8000;
|
||||
}
|
||||
else if (data_size == file_size - 0x10
|
||||
&& unknown1 == 0xCCCCCCCC && unknown2 == 0xCCCCCCCC) { /* The Mummy: The Animated Series */
|
||||
data_size = data_size / 2;
|
||||
interleave = 0x8000;
|
||||
}
|
||||
else if (data_size == file_size - 0x4020) { /* CT Special Forces (and all games beyond) */
|
||||
data_size = data_size / 2;
|
||||
interleave = unknown1; /* always 0? */
|
||||
if (!interleave)
|
||||
interleave = 0x10;
|
||||
/* header padding contains garbage */
|
||||
}
|
||||
else {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
start_offset = file_size - data_size;
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
fileLength = get_streamfile_size(streamFile);
|
||||
dataLength = read_32bitLE(0x4,streamFile);
|
||||
dataInterleave = read_32bitLE(0x8,streamFile);
|
||||
|
||||
if (!dataInterleave)
|
||||
dataInterleave = 16; /* XXX */
|
||||
|
||||
/* fill in the vital statistics */
|
||||
start_offset = fileLength - dataLength;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitLE(0x0,streamFile);
|
||||
vgmstream->sample_rate = read_32bitLE(0x00,streamFile);
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->num_samples = dataLength*28/16/channel_count;
|
||||
|
||||
|
||||
readOffset = start_offset;
|
||||
do {
|
||||
off_t blockRead = (off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile);
|
||||
vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count);
|
||||
|
||||
readOffset += blockRead;
|
||||
blockOffset += blockRead;
|
||||
|
||||
if (blockOffset >= dataInterleave) {
|
||||
readOffset += dataInterleave;
|
||||
blockOffset -= dataInterleave;
|
||||
}
|
||||
|
||||
/* Loop Start */
|
||||
if(testBuffer[0x01]==0x06) {
|
||||
if(loopStart == 0) loopStart = sampleOffset;
|
||||
/* break; */
|
||||
}
|
||||
|
||||
sampleOffset += 28;
|
||||
|
||||
/* Loop End */
|
||||
if(testBuffer[0x01]==0x03) {
|
||||
if(loopEnd == 0) loopEnd = sampleOffset;
|
||||
/* break; */
|
||||
}
|
||||
|
||||
} while (streamFile->get_offset(streamFile)<(int32_t)fileLength);
|
||||
|
||||
if(loopStart == 0 && loopEnd == 0) {
|
||||
loop_flag = 0;
|
||||
vgmstream->num_samples = dataLength*28/16/channel_count;
|
||||
} else {
|
||||
loop_flag = 1;
|
||||
vgmstream->loop_start_sample = loopStart;
|
||||
vgmstream->loop_end_sample = loopEnd;
|
||||
}
|
||||
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = dataInterleave;
|
||||
vgmstream->meta_type = meta_PS2_JOE;
|
||||
|
||||
/* open the file for reading */
|
||||
//todo improve, not working 100% with early .joe
|
||||
{
|
||||
int i;
|
||||
STREAMFILE * file;
|
||||
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!file) goto fail;
|
||||
for (i=0;i<channel_count;i++) {
|
||||
vgmstream->ch[i].streamfile = file;
|
||||
uint8_t testBuffer[0x10];
|
||||
off_t blockOffset = 0;
|
||||
off_t sampleOffset = 0;
|
||||
off_t readOffset = 0;
|
||||
off_t loopStart = 0, loopEnd = 0;
|
||||
|
||||
vgmstream->ch[i].channel_start_offset=
|
||||
vgmstream->ch[i].offset=start_offset+
|
||||
vgmstream->interleave_block_size*i;
|
||||
readOffset = start_offset;
|
||||
do {
|
||||
off_t blockRead = (off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile);
|
||||
|
||||
readOffset += blockRead;
|
||||
blockOffset += blockRead;
|
||||
|
||||
if (blockOffset >= interleave) {
|
||||
readOffset += interleave;
|
||||
blockOffset -= interleave;
|
||||
}
|
||||
|
||||
/* Loop Start */
|
||||
if(testBuffer[0x01]==0x06) {
|
||||
if(loopStart == 0)
|
||||
loopStart = sampleOffset;
|
||||
/* break; */
|
||||
}
|
||||
|
||||
sampleOffset += 28;
|
||||
|
||||
/* Loop End */
|
||||
if(testBuffer[0x01]==0x03) {
|
||||
if(loopEnd == 0)
|
||||
loopEnd = sampleOffset;
|
||||
/* break; */
|
||||
}
|
||||
|
||||
} while (streamFile->get_offset(streamFile)<(int32_t)file_size);
|
||||
|
||||
if (loopStart == 0 && loopEnd == 0) {
|
||||
vgmstream->loop_flag = 0;
|
||||
} else {
|
||||
vgmstream->loop_start_sample = loopStart;
|
||||
vgmstream->loop_end_sample = loopEnd;
|
||||
}
|
||||
}
|
||||
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
vgmstream->meta_type = meta_PS2_JOE;
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -238,7 +238,7 @@ static int add_filename(txtp_header * txtp, char *filename) {
|
||||
if (sscanf(config, "%d~%d", &subsong_start, &subsong_end) == 2) {
|
||||
if (subsong_start > 0 && subsong_end > 0) {
|
||||
range_start = subsong_start-1;
|
||||
range_end = subsong_end-1;
|
||||
range_end = subsong_end;
|
||||
}
|
||||
}
|
||||
else if (sscanf(config, "%u", &subsong_start) == 1) {
|
||||
|
@ -4,26 +4,44 @@
|
||||
/* .XWC - Starbreeze games [Chronicles of Riddick: Assault on Dark Athena, Syndicate] */
|
||||
VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
off_t start_offset, extra_offset;
|
||||
size_t data_size;
|
||||
int loop_flag, channel_count, codec;
|
||||
int loop_flag, channel_count, codec, num_samples;
|
||||
|
||||
/* check extensions (.xwc is the extension of the bigfile, individual files don't have one) */
|
||||
if ( !check_extensions(streamFile,"xwc"))
|
||||
goto fail;
|
||||
|
||||
if(read_32bitBE(0x00,streamFile) != 0x00040000 && /* version? */
|
||||
read_32bitBE(0x04,streamFile) != 0x00900000)
|
||||
goto fail;
|
||||
|
||||
data_size = read_32bitLE(0x08, streamFile); /* including subheader */
|
||||
channel_count = read_32bitLE(0x0c, streamFile);
|
||||
/* 0x10: num_samples */
|
||||
/* 0x14: 0x8000? */
|
||||
codec = read_32bitBE(0x24, streamFile);
|
||||
/* 0x28: num_samples */
|
||||
/* 0x2c: config data? (first nibble: 0x4=mono, 0x8=stereo) */
|
||||
/* 0x30+: codec dependant */
|
||||
/* version */
|
||||
if (read_32bitBE(0x00,streamFile) == 0x00030000 &&
|
||||
read_32bitBE(0x04,streamFile) == 0x00900000) { /* The Darkness */
|
||||
data_size = read_32bitLE(0x08, streamFile); /* including subheader */
|
||||
channel_count = read_32bitLE(0x0c, streamFile);
|
||||
/* 0x10: num_samples */
|
||||
/* 0x14: 0x8000? */
|
||||
/* 0x18: null */
|
||||
codec = read_32bitBE(0x1c, streamFile);
|
||||
num_samples = read_32bitLE(0x20, streamFile);
|
||||
/* 0x24: config data >> 2? (0x00(1): channels; 0x01(2): ?, 0x03(2): sample_rate) */
|
||||
extra_offset = 0x28;
|
||||
}
|
||||
else if (read_32bitBE(0x00,streamFile) == 0x00040000 &&
|
||||
read_32bitBE(0x04,streamFile) == 0x00900000) { /* Riddick, Syndicate */
|
||||
data_size = read_32bitLE(0x08, streamFile); /* including subheader */
|
||||
channel_count = read_32bitLE(0x0c, streamFile);
|
||||
/* 0x10: num_samples */
|
||||
/* 0x14: 0x8000? */
|
||||
codec = read_32bitBE(0x24, streamFile);
|
||||
num_samples = read_32bitLE(0x28, streamFile);
|
||||
/* 0x2c: config data >> 2? (0x00(1): channels; 0x01(2): ?, 0x03(2): sample_rate) */
|
||||
/* 0x30+: codec dependant */
|
||||
extra_offset = 0x30;
|
||||
}
|
||||
else {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
loop_flag = 0; /* seemingly not in the file */
|
||||
|
||||
|
||||
@ -31,7 +49,7 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) {
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->num_samples = read_32bitLE(0x28, streamFile);
|
||||
vgmstream->num_samples = num_samples;
|
||||
vgmstream->meta_type = meta_XWC;
|
||||
|
||||
switch(codec) {
|
||||
@ -40,8 +58,8 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) {
|
||||
mpeg_custom_config cfg = {0};
|
||||
|
||||
start_offset = 0x800;
|
||||
vgmstream->num_samples = read_32bitLE(0x30, streamFile); /* with encoder delay */ //todo improve
|
||||
cfg.data_size = read_32bitLE(0x34, streamFile); //data_size - 0x28;
|
||||
vgmstream->num_samples = read_32bitLE(extra_offset+0x00, streamFile); /* with encoder delay */ //todo improve
|
||||
cfg.data_size = read_32bitLE(extra_offset+0x04, streamFile); //data_size - 0x28;
|
||||
|
||||
vgmstream->codec_data = init_mpeg_custom(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_STANDARD, &cfg);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
@ -56,13 +74,13 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) {
|
||||
uint8_t buf[0x100];
|
||||
int32_t bytes, seek_size, block_size, block_count, sample_rate;
|
||||
|
||||
seek_size = read_32bitLE(0x30, streamFile);
|
||||
start_offset = 0x34 + seek_size + read_32bitLE(0x34+seek_size, streamFile) + 0x08;
|
||||
seek_size = read_32bitLE(extra_offset+0x00, streamFile);
|
||||
start_offset = extra_offset+0x04 + seek_size + read_32bitLE(extra_offset+0x04+seek_size, streamFile) + 0x08;
|
||||
start_offset += (start_offset % 0x800) ? 0x800 - (start_offset % 0x800) : 0; /* padded */
|
||||
|
||||
sample_rate = read_32bitBE(0x34+seek_size+0x10, streamFile);
|
||||
block_size = read_32bitBE(0x34+seek_size+0x1c, streamFile);
|
||||
block_count = read_32bitBE(0x34+seek_size+0x28, streamFile);
|
||||
sample_rate = read_32bitBE(extra_offset+0x04+seek_size+0x10, streamFile);
|
||||
block_size = read_32bitBE(extra_offset+0x04+seek_size+0x1c, streamFile);
|
||||
block_count = read_32bitBE(extra_offset+0x04+seek_size+0x28, streamFile);
|
||||
/* others: scrambled RIFF fmt BE values */
|
||||
|
||||
bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, sample_rate, block_count, block_size);
|
||||
@ -93,10 +111,6 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (vgmstream->sample_rate != 48000) { /* get from config data instead of codecs? */
|
||||
VGM_LOG("XWC: unexpected sample rate %i\n",vgmstream->sample_rate);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
|
||||
goto fail;
|
||||
|
@ -410,6 +410,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_ubi_bao_pk,
|
||||
init_vgmstream_dsp_switch_audio,
|
||||
init_vgmstream_dsp_sadf,
|
||||
init_vgmstream_h4m,
|
||||
|
||||
init_vgmstream_txth, /* should go at the end (lower priority) */
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
@ -936,6 +937,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
|
||||
case layout_blocked_ea_wve_au00:
|
||||
case layout_blocked_ea_wve_ad10:
|
||||
case layout_blocked_sthd:
|
||||
case layout_blocked_h4m:
|
||||
render_vgmstream_blocked(buffer,sample_count,vgmstream);
|
||||
break;
|
||||
case layout_aix:
|
||||
|
@ -252,6 +252,7 @@ typedef enum {
|
||||
layout_blocked_ea_wve_au00, /* EA WVE au00 blocks */
|
||||
layout_blocked_ea_wve_ad10, /* EA WVE Ad10 blocks */
|
||||
layout_blocked_sthd, /* Dream Factory STHD */
|
||||
layout_blocked_h4m, /* H4M video */
|
||||
|
||||
/* otherwise odd */
|
||||
layout_aix, /* CRI AIX's wheels within wheels */
|
||||
@ -678,6 +679,7 @@ typedef enum {
|
||||
meta_DSP_SWITCH_AUDIO, /* Gal Gun 2 (Switch) */
|
||||
meta_TA_AAC_VITA, /* tri-Ace AAC (Judas Code) */
|
||||
meta_OGG_GWM, /* Ogg Vorbis with encryption [Metronomicon (PC)] */
|
||||
meta_H4M, /* Hudson HVQM4 video [Resident Evil 0 (GC), Tales of Symphonia (GC)] */
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
meta_FFmpeg,
|
||||
|
Loading…
Reference in New Issue
Block a user