mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-23 22:41:05 +01:00
Merge pull request #1634 from bnnm/awc-etc
- Add .awc Opus/RIFF [Red Dead Redemption (PC)] - Add HCA key - CLI: fix infinite loop with non-ascii filenames
This commit is contained in:
commit
73ef7c6c15
@ -79,7 +79,8 @@ void replace_filename(char* dst, size_t dstsize, cli_config_t* cfg, VGMSTREAM* v
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* not recognized */
|
/* not recognized */
|
||||||
continue;
|
// TO-DO should move buf or swap "?" with "_"? may happen with non-ascii on Windows; for now break to avoid infinite loops
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy result to buf again, so it can be used as format in next replace
|
/* copy result to buf again, so it can be used as format in next replace
|
||||||
|
@ -156,7 +156,7 @@ VGMSTREAM* init_vgmstream_awc(STREAMFILE* sf) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef VGM_USE_ATRAC9
|
#ifdef VGM_USE_ATRAC9
|
||||||
case 0x0F: { /* ATRAC9 (PC) [Red Dead Redemption (PS4)] */
|
case 0x0F: { /* ATRAC9 (PS4) [Red Dead Redemption (PS4)] */
|
||||||
if (awc.is_streamed) {
|
if (awc.is_streamed) {
|
||||||
vgmstream->layout_data = build_layered_awc(sf_body, &awc);
|
vgmstream->layout_data = build_layered_awc(sf_body, &awc);
|
||||||
if (!vgmstream->layout_data) goto fail;
|
if (!vgmstream->layout_data) goto fail;
|
||||||
@ -205,6 +205,50 @@ VGMSTREAM* init_vgmstream_awc(STREAMFILE* sf) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifdef VGM_USE_ATRAC9
|
||||||
|
case 0x0D: { /* OPUS (PC) [Red Dead Redemption (PC)] */
|
||||||
|
if (awc.is_streamed) {
|
||||||
|
vgmstream->layout_data = build_layered_awc(sf_body, &awc);
|
||||||
|
if (!vgmstream->layout_data) goto fail;
|
||||||
|
vgmstream->layout_type = layout_layered;
|
||||||
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
VGM_LOG("AWC: unknown non-streamed Opus mode\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case 0x11: { /* RIFF-MSADPCM (PC) [Red Dead Redemption (PC)] */
|
||||||
|
if (awc.is_streamed) {
|
||||||
|
VGM_LOG("AWC: unknown streamed mode for codec 0x%02x\n", awc.codec);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
VGMSTREAM* temp_vs = NULL;
|
||||||
|
STREAMFILE* temp_sf = NULL;
|
||||||
|
|
||||||
|
temp_sf = setup_subfile_streamfile(sf_body, awc.stream_offset, awc.stream_size, "wav");
|
||||||
|
if (!temp_sf) goto fail;
|
||||||
|
|
||||||
|
temp_vs = init_vgmstream_riff(temp_sf);
|
||||||
|
close_streamfile(temp_sf);
|
||||||
|
if (!temp_vs) goto fail;
|
||||||
|
|
||||||
|
temp_vs->num_streams = vgmstream->num_streams;
|
||||||
|
temp_vs->stream_size = vgmstream->stream_size;
|
||||||
|
temp_vs->meta_type = vgmstream->meta_type;
|
||||||
|
strcpy(temp_vs->stream_name, vgmstream->stream_name);
|
||||||
|
|
||||||
|
close_vgmstream(vgmstream);
|
||||||
|
//vgmstream = temp_vs;
|
||||||
|
return temp_vs;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 0xFF:
|
case 0xFF:
|
||||||
vgmstream->coding_type = coding_SILENCE;
|
vgmstream->coding_type = coding_SILENCE;
|
||||||
snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "[%s]", "midi");
|
snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "[%s]", "midi");
|
||||||
@ -617,6 +661,24 @@ static VGMSTREAM* build_blocks_vgmstream(STREAMFILE* sf, awc_header* awc, int ch
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef VGM_USE_FFMPEG
|
||||||
|
case 0x0D: {
|
||||||
|
opus_config cfg = {0};
|
||||||
|
|
||||||
|
/* read from first block (all blocks have it but same thing), see awc_streamfile.h */
|
||||||
|
uint32_t frame_size_offset = awc->stream_offset + 0x10 * awc->channels + 0x70 * channel + 0x04;
|
||||||
|
|
||||||
|
cfg.frame_size = read_u16le(frame_size_offset, sf); // always 0x50?
|
||||||
|
cfg.channels = 1;
|
||||||
|
|
||||||
|
vgmstream->codec_data = init_ffmpeg_fixed_opus(temp_sf, substream_offset, substream_size, &cfg);
|
||||||
|
if (!vgmstream->codec_data) goto fail;
|
||||||
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
|
vgmstream->layout_type = layout_none;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef VGM_USE_ATRAC9
|
#ifdef VGM_USE_ATRAC9
|
||||||
case 0x0F: {
|
case 0x0F: {
|
||||||
atrac9_config cfg = {0};
|
atrac9_config cfg = {0};
|
||||||
@ -669,9 +731,8 @@ fail:
|
|||||||
// independently.
|
// independently.
|
||||||
//
|
//
|
||||||
// This can be simulated by making one decoder per block (segmented, but opens too many SFs and can't skip
|
// This can be simulated by making one decoder per block (segmented, but opens too many SFs and can't skip
|
||||||
// samples correctly), or with a custom STREAMFILE that skips repeated block (works ok-ish but not all codecs).
|
// samples correctly), or with a custom STREAMFILE that skips repeated block (works ok-ish).
|
||||||
static layered_layout_data* build_layered_awc(STREAMFILE* sf, awc_header* awc) {
|
static layered_layout_data* build_layered_awc(STREAMFILE* sf, awc_header* awc) {
|
||||||
int i;
|
|
||||||
layered_layout_data* data = NULL;
|
layered_layout_data* data = NULL;
|
||||||
|
|
||||||
|
|
||||||
@ -680,7 +741,7 @@ static layered_layout_data* build_layered_awc(STREAMFILE* sf, awc_header* awc) {
|
|||||||
if (!data) goto fail;
|
if (!data) goto fail;
|
||||||
|
|
||||||
/* open each layer subfile */
|
/* open each layer subfile */
|
||||||
for (i = 0; i < awc->channels; i++) {
|
for (int i = 0; i < awc->channels; i++) {
|
||||||
data->layers[i] = build_blocks_vgmstream(sf, awc, i);
|
data->layers[i] = build_blocks_vgmstream(sf, awc, i);
|
||||||
if (!data->layers[i]) goto fail;
|
if (!data->layers[i]) goto fail;
|
||||||
}
|
}
|
||||||
|
@ -61,9 +61,9 @@ typedef struct {
|
|||||||
* 0x00: "D11A"
|
* 0x00: "D11A"
|
||||||
* 0x04: frame size
|
* 0x04: frame size
|
||||||
* 0x06: frame samples
|
* 0x06: frame samples
|
||||||
* 0x08: flags? (0x0103=AT9, 0x0104=DSP)
|
* 0x08: flags? (0x0101=OPUS, 0x0103=AT9, 0x0104=DSP)
|
||||||
* 0x0a: sample rate
|
* 0x0a: sample rate
|
||||||
* 0x0c: ATRAC9 config (repeated but same for all blocks) or "D11E" (DSP)
|
* 0x0c: ATRAC9 config (repeated but same for all blocks) or "D11E" (OPUS/DSP)
|
||||||
* 0x10-0x70: padding with 0x77 (ATRAC3) or standard DSP header for original full file (DSP)
|
* 0x10-0x70: padding with 0x77 (ATRAC3) or standard DSP header for original full file (DSP)
|
||||||
* - padding up to data start, depending on codec (DSP/ATRAC9: none, others: aligned to 0x800)
|
* - padding up to data start, depending on codec (DSP/ATRAC9: none, others: aligned to 0x800)
|
||||||
*/
|
*/
|
||||||
@ -91,6 +91,7 @@ static bool read_awc_block(STREAMFILE* sf, awc_block_info_t* bi) {
|
|||||||
extra_entry_size = 0x00;
|
extra_entry_size = 0x00;
|
||||||
header_padding = 0x800;
|
header_padding = 0x800;
|
||||||
break;
|
break;
|
||||||
|
case 0x0D: /* OPUS */
|
||||||
case 0x0F: /* ATRAC9 */
|
case 0x0F: /* ATRAC9 */
|
||||||
channel_entry_size = 0x10;
|
channel_entry_size = 0x10;
|
||||||
seek_entry_size = 0x00;
|
seek_entry_size = 0x00;
|
||||||
@ -136,6 +137,7 @@ static bool read_awc_block(STREAMFILE* sf, awc_block_info_t* bi) {
|
|||||||
bi->blk[ch].chunk_size = align_size_to_block(bi->blk[ch].channel_size, 0x10);
|
bi->blk[ch].chunk_size = align_size_to_block(bi->blk[ch].channel_size, 0x10);
|
||||||
//bi->blk[ch].channel_size = (pre-loaded);
|
//bi->blk[ch].channel_size = (pre-loaded);
|
||||||
break;
|
break;
|
||||||
|
case 0x0D: /* OPUS */
|
||||||
case 0x0F: /* ATRAC9 */
|
case 0x0F: /* ATRAC9 */
|
||||||
bi->blk[ch].frame_size = read_u16(offset + 0x04, sf);
|
bi->blk[ch].frame_size = read_u16(offset + 0x04, sf);
|
||||||
bi->blk[ch].chunk_size = bi->blk[ch].entries * bi->blk[ch].frame_size;
|
bi->blk[ch].chunk_size = bi->blk[ch].entries * bi->blk[ch].frame_size;
|
||||||
@ -217,6 +219,7 @@ static uint32_t get_block_repeated_size(STREAMFILE* sf, awc_block_info_t* bi, in
|
|||||||
return skip_size; /* skip_size fills frame size */
|
return skip_size; /* skip_size fills frame size */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 0x0D: /* OPUS */
|
||||||
case 0x0F: /* ATRAC9 */
|
case 0x0F: /* ATRAC9 */
|
||||||
default:
|
default:
|
||||||
VGM_LOG("AWC: found channel skip in codec %x\n", bi->codec); /* not seen */
|
VGM_LOG("AWC: found channel skip in codec %x\n", bi->codec); /* not seen */
|
||||||
|
2612
src/meta/hca_keys.h
2612
src/meta/hca_keys.h
File diff suppressed because it is too large
Load Diff
@ -109,7 +109,7 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) {
|
|||||||
uint32_t stream_offset;
|
uint32_t stream_offset;
|
||||||
chunk_offset += 0x08 + 0x38 * (target_subsong-1); /* position in target header*/
|
chunk_offset += 0x08 + 0x38 * (target_subsong-1); /* position in target header*/
|
||||||
|
|
||||||
/* 0x00: ? (00/01/02) */
|
/* 0x00: flags? (00/01/02) */
|
||||||
name_offset = read_u32le(chunk_offset+0x04,sf_head);
|
name_offset = read_u32le(chunk_offset+0x04,sf_head);
|
||||||
codec = read_u8(chunk_offset+0x08,sf_head);
|
codec = read_u8(chunk_offset+0x08,sf_head);
|
||||||
channels = read_u8(chunk_offset+0x09,sf_head);
|
channels = read_u8(chunk_offset+0x09,sf_head);
|
||||||
@ -119,16 +119,14 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) {
|
|||||||
/* 0x10: info_type, meaning of the next value
|
/* 0x10: info_type, meaning of the next value
|
||||||
* (00=null, 30/40=data size without padding (ADPCM, ATRAC3plus), 80/A0=block size (AC3) */
|
* (00=null, 30/40=data size without padding (ADPCM, ATRAC3plus), 80/A0=block size (AC3) */
|
||||||
/* 0x14: info_value (see above) */
|
/* 0x14: info_value (see above) */
|
||||||
/* 0x18: unknown (ex. 0x0008/0010/3307/CC02/etc, RGND related?) x2 */
|
/* 0x18: vol L + vol R? */
|
||||||
/* 0x1c: null */
|
/* 0x1c: null */
|
||||||
|
|
||||||
num_samples = read_s32le(chunk_offset+0x20,sf_head);
|
num_samples = read_s32le(chunk_offset+0x20,sf_head);
|
||||||
loop_start_sample = read_s32le(chunk_offset+0x24,sf_head);
|
loop_start_sample = read_s32le(chunk_offset+0x24,sf_head);
|
||||||
loop_end_sample = read_s32le(chunk_offset+0x28,sf_head);
|
loop_end_sample = read_s32le(chunk_offset+0x28,sf_head);
|
||||||
stream_size = read_u32le(chunk_offset+0x2c,sf_head); /* stream size (without padding) / interleave (for type3) */
|
stream_size = read_u32le(chunk_offset+0x2c,sf_head); /* stream size (without padding) / interleave (for type3) */
|
||||||
|
|
||||||
stream_offset = read_u32le(chunk_offset+0x30,sf_head);
|
stream_offset = read_u32le(chunk_offset+0x30,sf_head);
|
||||||
|
|
||||||
/* 0x34: SGD/SGH = stream size (with padding) / interleave */
|
/* 0x34: SGD/SGH = stream size (with padding) / interleave */
|
||||||
|
|
||||||
loop_flag = loop_start_sample != -1 && loop_end_sample != -1;
|
loop_flag = loop_start_sample != -1 && loop_end_sample != -1;
|
||||||
@ -216,6 +214,8 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// 0x00: PCM16LE?
|
||||||
|
// https://github.com/Nenkai/010GameTemplates/blob/main/Sony/SGXD.bt
|
||||||
default:
|
default:
|
||||||
VGM_LOG("SGDX: unknown codec %i\n", codec);
|
VGM_LOG("SGDX: unknown codec %i\n", codec);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
Loading…
Reference in New Issue
Block a user