mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-05 13:28:04 +03:00
alice-ar: support extracting Ogg from afa v3
Support extracting audio archives from Evenicle 2 and beyond.
This commit is contained in:
@@ -45,6 +45,7 @@ static bool skip_dcf(struct buffer *r);
|
||||
static bool skip_flat(struct buffer *r);
|
||||
static bool skip_zlb(struct buffer *r);
|
||||
static bool skip_ex(struct buffer *r);
|
||||
static bool skip_ogg(struct buffer *r);
|
||||
|
||||
static struct file_magic file_magic[] = {
|
||||
{ ".ajp", "AJP", 4, skip_ajp },
|
||||
@@ -53,6 +54,7 @@ static struct file_magic file_magic[] = {
|
||||
{ ".flat", "ELNA", 4, skip_flat },
|
||||
{ ".zlb", "ZLB", 4, skip_zlb },
|
||||
{ ".ex", "HEAD", 4, skip_ex },
|
||||
{ ".ogg", "OggS", 4, skip_ogg },
|
||||
// TODO: ogg
|
||||
};
|
||||
|
||||
@@ -300,6 +302,74 @@ static bool skip_ex(struct buffer *r)
|
||||
return true;
|
||||
}
|
||||
|
||||
enum {
|
||||
OGG_INVALID,
|
||||
OGG_START,
|
||||
OGG_END,
|
||||
OGG_OTHER,
|
||||
};
|
||||
|
||||
static int skip_ogg_page(struct buffer *r)
|
||||
{
|
||||
if (buffer_remaining(r) < 27) {
|
||||
WARNING("Ogg page truncated?");
|
||||
return OGG_INVALID;
|
||||
}
|
||||
|
||||
// read header
|
||||
uint8_t *header = (uint8_t*)buffer_strdata(r);
|
||||
uint8_t type = header[5];
|
||||
uint8_t nr_segments = header[26];
|
||||
buffer_skip(r, 27);
|
||||
|
||||
if (buffer_remaining(r) < nr_segments) {
|
||||
WARNING("Ogg page truncated?");
|
||||
return OGG_INVALID;
|
||||
}
|
||||
|
||||
// read segment table
|
||||
uint8_t *segment_table = xmalloc(nr_segments);
|
||||
memcpy(segment_table, buffer_strdata(r), nr_segments);
|
||||
buffer_skip(r, nr_segments);
|
||||
|
||||
// skip segments
|
||||
for (unsigned i = 0; i < nr_segments; i++) {
|
||||
if (buffer_remaining(r) < segment_table[i]) {
|
||||
WARNING("Ogg segment truncated?");
|
||||
return OGG_INVALID;
|
||||
}
|
||||
buffer_skip(r, segment_table[i]);
|
||||
}
|
||||
|
||||
if (type & 2)
|
||||
return OGG_START;
|
||||
if (type & 4)
|
||||
return OGG_END;
|
||||
return OGG_OTHER;
|
||||
}
|
||||
|
||||
static bool skip_ogg(struct buffer *r)
|
||||
{
|
||||
int type = skip_ogg_page(r);
|
||||
if (type == OGG_INVALID)
|
||||
return false;
|
||||
if (type != OGG_START) {
|
||||
WARNING("First page in Ogg file has wrong type: %d", type);
|
||||
return false;
|
||||
}
|
||||
|
||||
while ((type = skip_ogg_page(r)) != OGG_END) {
|
||||
if (type == OGG_INVALID)
|
||||
return false;
|
||||
if (type == OGG_START) {
|
||||
WARNING("Begging of stream page in middle of Ogg file?");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool afa3_read_file(struct buffer *r, struct afa3_entry *file)
|
||||
{
|
||||
file->off = r->index;
|
||||
|
||||
Reference in New Issue
Block a user