mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-15 11:07:40 +01:00
Add Media.Vision ATX subfiles (decrypted) [Shining Blade (PSP)]
This commit is contained in:
parent
8c7eba151a
commit
d8c81bc14a
@ -44,6 +44,7 @@ static const char* extension_list[] = {
|
|||||||
"at3",
|
"at3",
|
||||||
"at9",
|
"at9",
|
||||||
"atsl3",
|
"atsl3",
|
||||||
|
"atx",
|
||||||
"aud",
|
"aud",
|
||||||
"aus",
|
"aus",
|
||||||
"awc",
|
"awc",
|
||||||
|
@ -279,6 +279,10 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath=".\meta\atsl3.c"
|
RelativePath=".\meta\atsl3.c"
|
||||||
>
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\meta\atx.c"
|
||||||
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\meta\awc.c"
|
RelativePath=".\meta\awc.c"
|
||||||
|
@ -186,6 +186,7 @@
|
|||||||
<ClCompile Include="meta\apple_caff.c" />
|
<ClCompile Include="meta\apple_caff.c" />
|
||||||
<ClCompile Include="meta\ast.c" />
|
<ClCompile Include="meta\ast.c" />
|
||||||
<ClCompile Include="meta\atsl3.c" />
|
<ClCompile Include="meta\atsl3.c" />
|
||||||
|
<ClCompile Include="meta\atx.c" />
|
||||||
<ClCompile Include="meta\baf.c" />
|
<ClCompile Include="meta\baf.c" />
|
||||||
<ClCompile Include="meta\bgw.c" />
|
<ClCompile Include="meta\bgw.c" />
|
||||||
<ClCompile Include="meta\bik.c" />
|
<ClCompile Include="meta\bik.c" />
|
||||||
|
@ -172,6 +172,9 @@
|
|||||||
<ClCompile Include="meta\atsl3.c">
|
<ClCompile Include="meta\atsl3.c">
|
||||||
<Filter>meta\Source Files</Filter>
|
<Filter>meta\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="meta\atx.c">
|
||||||
|
<Filter>meta\Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="meta\baf.c">
|
<ClCompile Include="meta\baf.c">
|
||||||
<Filter>meta\Source Files</Filter>
|
<Filter>meta\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
109
src/meta/atx.c
Normal file
109
src/meta/atx.c
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
#include "meta.h"
|
||||||
|
#include "../coding/coding.h"
|
||||||
|
|
||||||
|
#define ATX_MAX_SEGMENTS 2
|
||||||
|
|
||||||
|
static STREAMFILE* setup_atx_streamfile(STREAMFILE *streamFile);
|
||||||
|
|
||||||
|
/* .ATX - Media.Vision's segmented RIFF AT3 wrapper [Senjo no Valkyria 3 (PSP), Shining Blade (PSP)] */
|
||||||
|
VGMSTREAM * init_vgmstream_atx(STREAMFILE *streamFile) {
|
||||||
|
VGMSTREAM *vgmstream = NULL;
|
||||||
|
STREAMFILE *temp_streamFile = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/* check extensions */
|
||||||
|
if ( !check_extensions(streamFile,"atx"))
|
||||||
|
goto fail;
|
||||||
|
if (read_32bitBE(0x00,streamFile) != 0x41504133) /* "APA3" */
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* .ATX is made of subfile segments, handled by the streamFile.
|
||||||
|
* Each segment has a header/footer, and part of the whole data
|
||||||
|
* (i.e. ATRAC3 data ends in a subfile and continues in the next) */
|
||||||
|
temp_streamFile = setup_atx_streamfile(streamFile);
|
||||||
|
if (!temp_streamFile) goto fail;
|
||||||
|
|
||||||
|
vgmstream = init_vgmstream_riff(temp_streamFile);
|
||||||
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
|
close_streamfile(temp_streamFile);
|
||||||
|
return vgmstream;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
close_streamfile(temp_streamFile);
|
||||||
|
close_vgmstream(vgmstream);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static STREAMFILE* setup_atx_streamfile(STREAMFILE *streamFile) {
|
||||||
|
STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL;
|
||||||
|
STREAMFILE *segment_streamFiles[ATX_MAX_SEGMENTS] = {0};
|
||||||
|
char filename[PATH_LIMIT];
|
||||||
|
size_t filename_len;
|
||||||
|
int i, num_segments = 0;
|
||||||
|
size_t riff_size;
|
||||||
|
VGM_LOG("1\n");
|
||||||
|
|
||||||
|
if (read_16bitLE(0x1c,streamFile) != 0) goto fail; /* this must be first segment */
|
||||||
|
if (read_16bitLE(0x1e,streamFile) < 1 || read_16bitLE(0x1e,streamFile) > ATX_MAX_SEGMENTS) goto fail;
|
||||||
|
num_segments = read_16bitLE(0x1e,streamFile);
|
||||||
|
|
||||||
|
/* expected segment name: X_XXX_XXX_0n.ATX, starting from n=1 */
|
||||||
|
get_streamfile_name(streamFile, filename,PATH_LIMIT);
|
||||||
|
filename_len = strlen(filename);
|
||||||
|
if (filename_len < 7 || filename[filename_len - 5] != '1') goto fail;
|
||||||
|
|
||||||
|
/* setup segments (could avoid reopening first segment but meh) */
|
||||||
|
for (i = 0; i < num_segments; i++) {
|
||||||
|
off_t subfile_offset;
|
||||||
|
size_t subfile_size;
|
||||||
|
VGM_LOG("loop\n");
|
||||||
|
filename[filename_len - 5] = ('0'+i+1); /* ghetto digit conversion */
|
||||||
|
new_streamFile = open_stream_name(streamFile, filename);
|
||||||
|
if (!new_streamFile) goto fail;
|
||||||
|
segment_streamFiles[i] = new_streamFile;
|
||||||
|
|
||||||
|
if (read_32bitBE(0x00,segment_streamFiles[i]) != 0x41504133) /* "APA3" */
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* parse block/segment header (other Media.Vision's files use it too) */
|
||||||
|
subfile_offset = read_32bitLE(0x08,segment_streamFiles[i]); /* header size */
|
||||||
|
subfile_size = read_32bitLE(0x14,segment_streamFiles[i]); /* can be 0 in other containers */
|
||||||
|
VGM_LOG("subfile: %lx, %x\n", subfile_offset, subfile_size);
|
||||||
|
if (read_16bitLE(0x1c,segment_streamFiles[i]) != i)
|
||||||
|
goto fail; /* segment sequence */
|
||||||
|
/* 0x04: block size (should match subfile_size in .ATX) */
|
||||||
|
/* 0x0c: flags? also in other files, 0x10/18: null, 0x1e: segments */
|
||||||
|
|
||||||
|
/* clamp to ignore header/footer during next reads */
|
||||||
|
new_streamFile = open_clamp_streamfile(segment_streamFiles[i], subfile_offset,subfile_size);
|
||||||
|
if (!new_streamFile) goto fail;
|
||||||
|
segment_streamFiles[i] = new_streamFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup with all segments and clamp further using riff_size (last segment has padding) */
|
||||||
|
riff_size = read_32bitLE(read_32bitLE(0x08,streamFile) + 0x04,streamFile) + 0x08;
|
||||||
|
|
||||||
|
new_streamFile = open_multifile_streamfile(segment_streamFiles, num_segments);
|
||||||
|
if (!new_streamFile) goto fail;
|
||||||
|
temp_streamFile = new_streamFile;
|
||||||
|
|
||||||
|
new_streamFile = open_clamp_streamfile(temp_streamFile, 0,riff_size);
|
||||||
|
if (!new_streamFile) goto fail;
|
||||||
|
temp_streamFile = new_streamFile;
|
||||||
|
|
||||||
|
new_streamFile = open_fakename_streamfile(temp_streamFile, NULL, "at3");
|
||||||
|
if (!new_streamFile) goto fail;
|
||||||
|
temp_streamFile = new_streamFile;
|
||||||
|
|
||||||
|
return temp_streamFile;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (!temp_streamFile) {
|
||||||
|
for (i = 0; i < num_segments; i++)
|
||||||
|
close_streamfile(segment_streamFiles[i]);
|
||||||
|
} else {
|
||||||
|
close_streamfile(temp_streamFile); /* closes all segments */
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
@ -702,4 +702,6 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile);
|
|||||||
VGMSTREAM * init_vgmstream_atsl3(STREAMFILE *streamFile);
|
VGMSTREAM * init_vgmstream_atsl3(STREAMFILE *streamFile);
|
||||||
|
|
||||||
VGMSTREAM * init_vgmstream_sps_n1(STREAMFILE *streamFile);
|
VGMSTREAM * init_vgmstream_sps_n1(STREAMFILE *streamFile);
|
||||||
|
|
||||||
|
VGMSTREAM * init_vgmstream_atx(STREAMFILE *streamFile);
|
||||||
#endif /*_META_H*/
|
#endif /*_META_H*/
|
||||||
|
@ -378,6 +378,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
|||||||
init_vgmstream_xwc,
|
init_vgmstream_xwc,
|
||||||
init_vgmstream_atsl3,
|
init_vgmstream_atsl3,
|
||||||
init_vgmstream_sps_n1,
|
init_vgmstream_sps_n1,
|
||||||
|
init_vgmstream_atx,
|
||||||
|
|
||||||
init_vgmstream_txth, /* should go at the end (lower priority) */
|
init_vgmstream_txth, /* should go at the end (lower priority) */
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
|
Loading…
Reference in New Issue
Block a user