mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-12 01:30:49 +01:00
misc issues and cleanup
This commit is contained in:
parent
bdd641d218
commit
7bb2434b56
@ -463,7 +463,7 @@ You can also choose which channels to play using *TXTP*. For example, create
|
||||
a file named `song.adx#C1,2.txtp` to play only channels 1 and 2 from `song.adx`.
|
||||
*TXTP* also has command to set how files are downmixed.
|
||||
|
||||
### Logged errors and unplayable supported files
|
||||
## Logged errors and unplayable supported files
|
||||
Some formats should normally play, but somehow don't. In those cases plugins
|
||||
can print vgmstream's error info to console (for example, `.fsb` with an unknown
|
||||
codec, `.hca/awb` with missing decryption key, bank has no audio, `.txth` is
|
||||
|
@ -456,7 +456,7 @@ static size_t make_oggs_page(uint8_t* buf, int buf_size, size_t data_size, int p
|
||||
}
|
||||
|
||||
segment_count = (int)(data_size / 0xFF + 1);
|
||||
put_u32be(buf+0x00, 0x4F676753); /* capture pattern ("OggS") */
|
||||
put_u32be(buf+0x00, get_id32be("OggS")); /* capture pattern */
|
||||
put_u8 (buf+0x04, 0); /* stream structure version, fixed */
|
||||
put_u8 (buf+0x05, header_type_flag); /* bitflags (0: normal, continued = 1, first = 2, last = 4) */
|
||||
put_u32le(buf+0x06, (uint32_t)(absolute_granule >> 0 & 0xFFFFFFFF)); /* lower */
|
||||
@ -517,8 +517,8 @@ static size_t make_opus_header(uint8_t* buf, int buf_size, opus_config *cfg) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
put_u32be(buf+0x00, 0x4F707573); /* "Opus" header magic */
|
||||
put_u32be(buf+0x04, 0x48656164); /* "Head" header magic */
|
||||
put_u32be(buf+0x00, get_id32be("Opus"));
|
||||
put_u32be(buf+0x04, get_id32be("Head"));
|
||||
put_u8 (buf+0x08, 1); /* version */
|
||||
put_u8 (buf+0x09, cfg->channels);
|
||||
put_s16le(buf+0x0A, cfg->skip);
|
||||
@ -575,19 +575,23 @@ fail:
|
||||
static size_t make_oggs_first(uint8_t* buf, int buf_size, opus_config* cfg) {
|
||||
int buf_done = 0;
|
||||
size_t bytes;
|
||||
size_t page_size = 0x1c; /* fixed for header page */
|
||||
|
||||
if (buf_size < 0x100) /* approx */
|
||||
goto fail;
|
||||
|
||||
/* make header */
|
||||
bytes = make_opus_header(buf+buf_done + 0x1c,buf_size, cfg);
|
||||
make_oggs_page(buf+buf_done + 0x00,buf_size, bytes, 0, 0);
|
||||
buf_done += 0x1c + bytes;
|
||||
/* make header (first data, then page for checksum) */
|
||||
bytes = make_opus_header(buf + page_size, buf_size - page_size, cfg);
|
||||
make_oggs_page(buf, buf_size, bytes, 0, 0);
|
||||
buf_done += (page_size + bytes);
|
||||
|
||||
buf += buf_done;
|
||||
buf_size -= buf_done;
|
||||
|
||||
/* make comment */
|
||||
bytes = make_opus_comment(buf+buf_done + 0x1c,buf_size);
|
||||
make_oggs_page(buf+buf_done + 0x00,buf_size, bytes, 1, 0);
|
||||
buf_done += 0x1c + bytes;
|
||||
bytes = make_opus_comment(buf + page_size, buf_size - page_size);
|
||||
make_oggs_page(buf, buf_size, bytes, 1, 0);
|
||||
buf_done += (page_size + bytes);
|
||||
|
||||
return buf_done;
|
||||
fail:
|
||||
|
@ -177,9 +177,6 @@ int setup_layout_segmented(segmented_layout_data* data) {
|
||||
for (i = 0; i < data->segment_count; i++) {
|
||||
int segment_input_channels, segment_output_channels;
|
||||
|
||||
/* allow config if set for fine-tuned parts (usually TXTP only) */
|
||||
data->segments[i]->config_enabled = data->segments[i]->config.config_set;
|
||||
|
||||
if (data->segments[i] == NULL) {
|
||||
VGM_LOG("SEGMENTED: no vgmstream in segment %i\n", i);
|
||||
goto fail;
|
||||
@ -190,6 +187,9 @@ int setup_layout_segmented(segmented_layout_data* data) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* allow config if set for fine-tuned parts (usually TXTP only) */
|
||||
data->segments[i]->config_enabled = data->segments[i]->config.config_set;
|
||||
|
||||
/* disable so that looping is controlled by render_vgmstream_segmented */
|
||||
if (data->segments[i]->loop_flag != 0) {
|
||||
VGM_LOG("SEGMENTED: segment %i is looped\n", i);
|
||||
|
164
src/meta/awb.c
164
src/meta/awb.c
@ -1,7 +1,7 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
typedef enum { ADX, HCA, VAG, RIFF, CWAV, DSP, CWAC, M4A } awb_type;
|
||||
//typedef enum { ADX, HCA, VAG, RIFF, CWAV, DSP, CWAC, M4A } awb_type_t;
|
||||
|
||||
static void load_awb_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstream, int waveid);
|
||||
|
||||
@ -13,26 +13,21 @@ VGMSTREAM* init_vgmstream_awb(STREAMFILE* sf) {
|
||||
VGMSTREAM* init_vgmstream_awb_memory(STREAMFILE* sf, STREAMFILE* sf_acb) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
STREAMFILE* temp_sf = NULL;
|
||||
off_t offset, subfile_offset, subfile_next;
|
||||
size_t subfile_size;
|
||||
uint32_t offset, subfile_offset, subfile_next, subfile_size;
|
||||
int total_subsongs, target_subsong = sf->stream_index;
|
||||
//uint32_t flags;
|
||||
uint8_t offset_size;
|
||||
uint16_t alignment, subkey;
|
||||
awb_type type;
|
||||
const char* extension = NULL;
|
||||
int waveid;
|
||||
|
||||
|
||||
/* checks
|
||||
* .awb: standard
|
||||
/* checks */
|
||||
if (!is_id32be(0x00,sf, "AFS2"))
|
||||
goto fail;
|
||||
/* .awb: standard
|
||||
* .afs2: sometimes [Okami HD (PS4)] */
|
||||
if (!check_extensions(sf, "awb,afs2"))
|
||||
goto fail;
|
||||
if (read_u32be(0x00,sf) != 0x41465332) /* "AFS2" */
|
||||
goto fail;
|
||||
|
||||
//flags = read_32bitLE(0x08,sf);
|
||||
/* 0x04(1): version? 0x01=common, 0x02=2018+ (no apparent differences) */
|
||||
offset_size = read_u8(0x05,sf);
|
||||
/* 0x06(2): always 0x0002? */
|
||||
@ -45,9 +40,9 @@ VGMSTREAM* init_vgmstream_awb_memory(STREAMFILE* sf, STREAMFILE* sf_acb) {
|
||||
|
||||
offset = 0x10;
|
||||
|
||||
/* id(?) table: read target */
|
||||
/* id table: read target */
|
||||
{
|
||||
off_t waveid_offset = offset + (target_subsong-1) * 0x02;
|
||||
uint32_t waveid_offset = offset + (target_subsong-1) * 0x02;
|
||||
|
||||
waveid = read_u16le(waveid_offset,sf);
|
||||
|
||||
@ -56,7 +51,7 @@ VGMSTREAM* init_vgmstream_awb_memory(STREAMFILE* sf, STREAMFILE* sf_acb) {
|
||||
|
||||
/* offset table: find target */
|
||||
{
|
||||
off_t file_size = get_streamfile_size(sf);
|
||||
uint32_t file_size = get_streamfile_size(sf);
|
||||
|
||||
/* last sub-offset is always file end, so table entries = total_subsongs+1 */
|
||||
offset += (target_subsong-1) * offset_size;
|
||||
@ -71,7 +66,7 @@ VGMSTREAM* init_vgmstream_awb_memory(STREAMFILE* sf, STREAMFILE* sf_acb) {
|
||||
subfile_next = read_u16le(offset+0x02,sf);
|
||||
break;
|
||||
default:
|
||||
VGM_LOG("AWB: unknown offset size\n");
|
||||
vgm_logi("AWB: unknown offset size (report)\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -83,97 +78,70 @@ VGMSTREAM* init_vgmstream_awb_memory(STREAMFILE* sf, STREAMFILE* sf_acb) {
|
||||
subfile_size = subfile_next - subfile_offset;
|
||||
}
|
||||
|
||||
//;VGM_LOG("AWB: subfile offset=%lx + %x\n", subfile_offset, subfile_size);
|
||||
//;VGM_LOG("awb: subfile offset=%x + %x\n", subfile_offset, subfile_size);
|
||||
|
||||
/* autodetect as there isn't anything, plus can mix types
|
||||
* (waveid<>codec info is usually in the companion .acb) */
|
||||
if (read_u16be(subfile_offset, sf) == 0x8000) { /* ADX id (type 0) */
|
||||
type = ADX;
|
||||
extension = "adx";
|
||||
}
|
||||
else if ((read_u32be(subfile_offset,sf) & 0x7f7f7f7f) == 0x48434100) { /* "HCA\0" (type 2=HCA, 6=HCA-MX) */
|
||||
type = HCA;
|
||||
extension = "hca";
|
||||
}
|
||||
else if (read_u32be(subfile_offset,sf) == 0x56414770) { /* "VAGp" (type 7=VAG, 10=HEVAG) */
|
||||
type = VAG;
|
||||
extension = "vag";
|
||||
}
|
||||
else if (read_u32be(subfile_offset,sf) == 0x52494646) { /* "RIFF" (type 8=ATRAC3, 11=ATRAC9) */
|
||||
type = RIFF;
|
||||
extension = "wav";
|
||||
subfile_size = read_u32le(subfile_offset + 0x04,sf) + 0x08; /* rough size, use RIFF's */
|
||||
}
|
||||
else if (read_u32be(subfile_offset,sf) == 0x43574156) { /* "CWAV" (type 9) */
|
||||
type = CWAV;
|
||||
extension = "bcwav";
|
||||
}
|
||||
else if (read_u32be(subfile_offset + 0x08,sf) >= 8000 &&
|
||||
read_u32be(subfile_offset + 0x08,sf) <= 48000 &&
|
||||
read_u16be(subfile_offset + 0x0e,sf) == 0 &&
|
||||
read_u32be(subfile_offset + 0x18,sf) == 2 &&
|
||||
read_u32be(subfile_offset + 0x50,sf) == 0) { /* probably should call some check function (type 13) */
|
||||
type = DSP;
|
||||
extension = "dsp";
|
||||
}
|
||||
else if (is_id32be(subfile_offset,sf, "CWAC")) { /* type 13 again */
|
||||
type = CWAC;
|
||||
extension = "dsp";
|
||||
}
|
||||
else if (read_u32be(subfile_offset+0x00,sf) == 0x00000018 &&
|
||||
read_u32be(subfile_offset+0x04,sf) == 0x66747970) { /* chunk size + "ftyp" (type 19) */
|
||||
type = M4A;
|
||||
extension = "m4a";
|
||||
}
|
||||
else {
|
||||
VGM_LOG("AWB: unknown codec\n");
|
||||
goto fail;
|
||||
}
|
||||
{
|
||||
VGMSTREAM* (*init_vgmstream)(STREAMFILE* sf) = NULL;
|
||||
VGMSTREAM* (*init_vgmstream_subkey)(STREAMFILE* sf, uint16_t subkey) = NULL;
|
||||
const char* extension = NULL;
|
||||
|
||||
|
||||
temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, extension);
|
||||
if (!temp_sf) goto fail;
|
||||
|
||||
switch(type) {
|
||||
case HCA: /* most common */
|
||||
vgmstream = init_vgmstream_hca_subkey(temp_sf, subkey);
|
||||
if (!vgmstream) goto fail;
|
||||
break;
|
||||
case ADX: /* Okami HD (PS4) */
|
||||
vgmstream = init_vgmstream_adx_subkey(temp_sf, subkey);
|
||||
if (!vgmstream) goto fail;
|
||||
break;
|
||||
case VAG: /* Ukiyo no Roushi (Vita) */
|
||||
vgmstream = init_vgmstream_vag(temp_sf);
|
||||
if (!vgmstream) goto fail;
|
||||
break;
|
||||
case RIFF: /* Ukiyo no Roushi (Vita) */
|
||||
vgmstream = init_vgmstream_riff(temp_sf);
|
||||
if (!vgmstream) goto fail;
|
||||
break;
|
||||
case CWAV: /* Sonic: Lost World (3DS) */
|
||||
vgmstream = init_vgmstream_rwsd(temp_sf);
|
||||
if (!vgmstream) goto fail;
|
||||
break;
|
||||
case DSP: /* Sonic: Lost World (WiiU) */
|
||||
vgmstream = init_vgmstream_ngc_dsp_std(temp_sf);
|
||||
if (!vgmstream) goto fail;
|
||||
break;
|
||||
case CWAC: /* Mario & Sonic at the Rio 2016 Olympic Games (WiiU) */
|
||||
vgmstream = init_vgmstream_dsp_cwac(temp_sf);
|
||||
if (!vgmstream) goto fail;
|
||||
break;
|
||||
if (read_u16be(subfile_offset, sf) == 0x8000) { /* (type 0=ADX) */
|
||||
init_vgmstream_subkey = init_vgmstream_adx_subkey; /* Okami HD (PS4) */
|
||||
extension = "adx";
|
||||
}
|
||||
else if ((read_u32be(subfile_offset,sf) & 0x7f7f7f7f) == get_id32be("HCA\0")) { /* (type 2=HCA, 6=HCA-MX) */
|
||||
init_vgmstream_subkey = init_vgmstream_hca_subkey; /* most common */
|
||||
extension = "hca";
|
||||
}
|
||||
else if (is_id32be(subfile_offset,sf, "VAGp") == 0x56414770) { /* (type 7=VAG, 10=HEVAG) */
|
||||
init_vgmstream = init_vgmstream_vag; /* Ukiyo no Roushi (Vita) */
|
||||
extension = "vag";
|
||||
}
|
||||
else if (is_id32be(subfile_offset,sf, "RIFF")) { /* (type 8=ATRAC3, 11=ATRAC9) */
|
||||
init_vgmstream = init_vgmstream_riff; /* Ukiyo no Roushi (Vita) */
|
||||
extension = "wav";
|
||||
subfile_size = read_u32le(subfile_offset + 0x04,sf) + 0x08; /* padded size, use RIFF's */
|
||||
}
|
||||
else if (is_id32be(subfile_offset,sf, "CWAV")) { /* (type 9=CWAV) */
|
||||
init_vgmstream = init_vgmstream_rwsd; /* Sonic: Lost World (3DS) */
|
||||
extension = "bcwav";
|
||||
}
|
||||
else if (read_u32be(subfile_offset + 0x08,sf) >= 8000 && read_u32be(subfile_offset + 0x08,sf) <= 48000 &&
|
||||
read_u16be(subfile_offset + 0x0e,sf) == 0 &&
|
||||
read_u32be(subfile_offset + 0x18,sf) == 2 &&
|
||||
read_u32be(subfile_offset + 0x50,sf) == 0) { /* (type 13=DSP), probably should call some check function */
|
||||
init_vgmstream = init_vgmstream_ngc_dsp_std; /* Sonic: Lost World (WiiU) */
|
||||
extension = "dsp";
|
||||
}
|
||||
else if (is_id32be(subfile_offset,sf, "CWAC")) { /* (type 13=DSP, again) */
|
||||
init_vgmstream = init_vgmstream_dsp_cwac; /* Mario & Sonic at the Rio 2016 Olympic Games (WiiU) */
|
||||
extension = "dsp";
|
||||
}
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
case M4A: /* Imperial SaGa Eclipse (Browser) */
|
||||
vgmstream = init_vgmstream_mp4_aac_ffmpeg(temp_sf);
|
||||
if (!vgmstream) goto fail;
|
||||
break;
|
||||
else if (read_u32be(subfile_offset+0x00,sf) == 0x00000018 && is_id32be(subfile_offset+0x04,sf, "ftyp")) { /* (type 19=M4A) */
|
||||
init_vgmstream = init_vgmstream_mp4_aac_ffmpeg; /* Imperial SaGa Eclipse (Browser) */
|
||||
extension = "m4a";
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
else {
|
||||
vgm_logi("AWB: unknown codec (report)\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
vgmstream->num_streams = total_subsongs;
|
||||
|
||||
temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, extension);
|
||||
if (!temp_sf) goto fail;
|
||||
|
||||
if (init_vgmstream_subkey)
|
||||
vgmstream = init_vgmstream_subkey(temp_sf, subkey);
|
||||
else
|
||||
vgmstream = init_vgmstream(temp_sf);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->num_streams = total_subsongs;
|
||||
}
|
||||
|
||||
/* try to load cue names */
|
||||
load_awb_name(sf, sf_acb, vgmstream, waveid);
|
||||
|
@ -19,15 +19,15 @@ typedef struct {
|
||||
int32_t num_samples;
|
||||
int32_t loop_start;
|
||||
int loop_flag;
|
||||
off_t extra_offset;
|
||||
uint32_t extra_offset;
|
||||
uint32_t channel_layout;
|
||||
|
||||
int is_external;
|
||||
uint32_t stream_offsets[MAX_CHANNELS];
|
||||
uint32_t stream_sizes[MAX_CHANNELS];
|
||||
|
||||
off_t sound_name_offset;
|
||||
off_t config_name_offset;
|
||||
uint32_t sound_name_offset;
|
||||
uint32_t config_name_offset;
|
||||
char name[255+1];
|
||||
} ktsr_header;
|
||||
|
||||
@ -266,12 +266,12 @@ static int parse_codec(ktsr_header* ktsr) {
|
||||
|
||||
return 1;
|
||||
fail:
|
||||
VGM_LOG("KTSR: unknown codec combo: ext=%x, fmt=%x, ptf=%x\n", ktsr->is_external, ktsr->format, ktsr->platform);
|
||||
VGM_LOG("ktsr: unknown codec combo: ext=%x, fmt=%x, ptf=%x\n", ktsr->is_external, ktsr->format, ktsr->platform);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_ktsr_subfile(ktsr_header* ktsr, STREAMFILE* sf, off_t offset) {
|
||||
off_t suboffset, starts_offset, sizes_offset;
|
||||
static int parse_ktsr_subfile(ktsr_header* ktsr, STREAMFILE* sf, uint32_t offset) {
|
||||
uint32_t suboffset, starts_offset, sizes_offset;
|
||||
int i;
|
||||
uint32_t type;
|
||||
|
||||
@ -318,7 +318,7 @@ static int parse_ktsr_subfile(ktsr_header* ktsr, STREAMFILE* sf, off_t offset) {
|
||||
ktsr->is_external = 1;
|
||||
|
||||
if (ktsr->format != 0x05) {
|
||||
VGM_LOG("KTSR: unknown subcodec at %lx\n", offset);
|
||||
VGM_LOG("ktsr: unknown subcodec at %x\n", offset);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -362,7 +362,7 @@ static int parse_ktsr_subfile(ktsr_header* ktsr, STREAMFILE* sf, off_t offset) {
|
||||
suboffset = offset + 0x30;
|
||||
|
||||
if (ktsr->channels > MAX_CHANNELS) {
|
||||
VGM_LOG("KTSR: max channels found\n");
|
||||
VGM_LOG("ktsr: max channels found\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -379,7 +379,7 @@ static int parse_ktsr_subfile(ktsr_header* ktsr, STREAMFILE* sf, off_t offset) {
|
||||
|
||||
default:
|
||||
/* streams also have their own chunks like 0x09D4F415, not needed here */
|
||||
VGM_LOG("KTSR: unknown subheader at %lx\n", offset);
|
||||
VGM_LOG("ktsr: unknown subheader at %x\n", offset);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -388,7 +388,7 @@ static int parse_ktsr_subfile(ktsr_header* ktsr, STREAMFILE* sf, off_t offset) {
|
||||
|
||||
return 1;
|
||||
fail:
|
||||
VGM_LOG("KTSR: error parsing subheader\n");
|
||||
VGM_LOG("ktsr: error parsing subheader\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -419,7 +419,7 @@ static void build_name(ktsr_header* ktsr, STREAMFILE* sf) {
|
||||
|
||||
static void parse_longname(ktsr_header* ktsr, STREAMFILE* sf, uint32_t target_id) {
|
||||
/* more configs than sounds is possible so we need target_id first */
|
||||
off_t offset, end, name_offset;
|
||||
uint32_t offset, end, name_offset;
|
||||
uint32_t stream_id;
|
||||
|
||||
offset = 0x40;
|
||||
@ -447,7 +447,7 @@ static void parse_longname(ktsr_header* ktsr, STREAMFILE* sf, uint32_t target_id
|
||||
}
|
||||
|
||||
static int parse_ktsr(ktsr_header* ktsr, STREAMFILE* sf) {
|
||||
off_t offset, end, header_offset, name_offset;
|
||||
uint32_t offset, end, header_offset, name_offset;
|
||||
uint32_t stream_id = 0, stream_count;
|
||||
|
||||
/* 00: KTSR
|
||||
@ -486,7 +486,6 @@ static int parse_ktsr(ktsr_header* ktsr, STREAMFILE* sf) {
|
||||
break;
|
||||
|
||||
case 0xC5CCCB70: /* sound (internal data or external stream) */
|
||||
//VGM_LOG("info at %lx\n", offset);
|
||||
ktsr->total_subsongs++;
|
||||
|
||||
/* sound table:
|
||||
@ -503,13 +502,12 @@ static int parse_ktsr(ktsr_header* ktsr, STREAMFILE* sf) {
|
||||
|
||||
|
||||
if (ktsr->total_subsongs == ktsr->target_subsong) {
|
||||
//;VGM_LOG("KTSR: target at %lx\n", offset);
|
||||
|
||||
stream_id = read_u32be(offset + 0x08,sf);
|
||||
//ktsr->is_external = read_u16le(offset + 0x0e,sf);
|
||||
stream_count = read_u32le(offset + 0x10,sf);
|
||||
if (stream_count != 1) {
|
||||
VGM_LOG("KTSR: unknown stream count\n");
|
||||
VGM_LOG("ktsr: unknown stream count\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -527,7 +525,7 @@ static int parse_ktsr(ktsr_header* ktsr, STREAMFILE* sf) {
|
||||
|
||||
default:
|
||||
/* streams also have their own chunks like 0x09D4F415, not needed here */
|
||||
VGM_LOG("KTSR: unknown chunk at %lx\n", offset);
|
||||
VGM_LOG("ktsr: unknown chunk at %x\n", offset);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -542,5 +540,6 @@ static int parse_ktsr(ktsr_header* ktsr, STREAMFILE* sf) {
|
||||
|
||||
return 1;
|
||||
fail:
|
||||
vgm_logi("KTSR: unknown variation (report)\n");
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user