#include "meta.h" #include "../coding/coding.h" #include "../layout/layout.h" #include "9tav_streamfile.h" /* 9TAV - from Metal Gear Solid 2/3 HD (Vita) */ VGMSTREAM * init_vgmstream_9tav(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; int loop_flag, channel_count, sample_rate, track_count; int32_t num_samples, loop_start, loop_end; size_t track_size; uint32_t config_data; int i, is_padded; layered_layout_data * data = NULL; STREAMFILE* temp_streamFile = NULL; /* checks */ /* .9tav: header id */ if (!check_extensions(streamFile, "9tav")) goto fail; if (read_32bitBE(0x00,streamFile) != 0x39544156) /* "9TAV" */ goto fail; /* 0x04: always 0x09 */ channel_count = read_16bitLE(0x08,streamFile); track_count = read_16bitLE(0x0a,streamFile); /* MGS3 uses multitracks */ sample_rate = read_32bitLE(0x0c,streamFile); track_size = read_32bitLE(0x10,streamFile); /* without padding */ //data_size = read_32bitLE(0x14,streamFile); /* without padding */ num_samples = read_32bitLE(0x18,streamFile); config_data = read_32bitBE(0x1c,streamFile); if (read_32bitBE(0x20,streamFile) == 0x4D544146) { /* "MTAF" */ /* MGS3 has a MTAF header (data size and stuff don't match, probably for track info) */ loop_start = read_32bitLE(0x78, streamFile); loop_end = read_32bitLE(0x7c, streamFile); loop_flag = read_32bitLE(0x90, streamFile) & 1; is_padded = 1; /* data also has padding and other oddities */ start_offset = 0x00; } else { /* MGS2 doesn't */ loop_start = 0; loop_end = 0; loop_flag = 0; is_padded = 0; start_offset = 0x20; } /* init layout */ data = init_layout_layered(track_count); if (!data) goto fail; /* open each layer subfile */ for (i = 0; i < data->layer_count; i++) { data->layers[i] = allocate_vgmstream(channel_count, loop_flag); if (!data->layers[i]) goto fail; data->layers[i]->meta_type = meta_9TAV; data->layers[i]->sample_rate = sample_rate; data->layers[i]->num_samples = num_samples; data->layers[i]->loop_start_sample = loop_start; data->layers[i]->loop_end_sample = loop_end; #ifdef VGM_USE_ATRAC9 { atrac9_config cfg = {0}; cfg.channels = channel_count; cfg.config_data = config_data; cfg.encoder_delay = atrac9_bytes_to_samples_cfg(track_size, cfg.config_data) - num_samples; /* seems ok */ if (cfg.encoder_delay > 4096) /* doesn't seem too normal */ cfg.encoder_delay = 0; data->layers[i]->codec_data = init_atrac9(&cfg); if (!data->layers[i]->codec_data) goto fail; data->layers[i]->coding_type = coding_ATRAC9; data->layers[i]->layout_type = layout_none; } #else goto fail; #endif if (is_padded) { temp_streamFile = setup_9tav_streamfile(streamFile, 0xFE4, track_size, i, track_count); if (!temp_streamFile) goto fail; } if (!vgmstream_open_stream(data->layers[i],temp_streamFile == NULL ? streamFile : temp_streamFile,start_offset)) goto fail; close_streamfile(temp_streamFile); temp_streamFile = NULL; } /* setup layered VGMSTREAMs */ if (!setup_layout_layered(data)) goto fail; /* build the layered VGMSTREAM */ vgmstream = allocate_layered_vgmstream(data); if (!vgmstream) goto fail; return vgmstream; fail: close_streamfile(temp_streamFile); close_vgmstream(vgmstream); if (!vgmstream) free_layout_layered(data); return NULL; }