diff --git a/src/libvgmstream.vcproj b/src/libvgmstream.vcproj index db855ca6..1edd21f4 100644 --- a/src/libvgmstream.vcproj +++ b/src/libvgmstream.vcproj @@ -296,6 +296,10 @@ RelativePath=".\meta\xvag_streamfile.h" > + + diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index fd45cb4f..530114a6 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -90,6 +90,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index dcfc64e8..8a0b50fc 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -170,6 +170,9 @@ meta\Header Files + + meta\Header Files + meta\Header Files diff --git a/src/meta/sfh.c b/src/meta/sfh.c index aa5cc026..b22a2205 100644 --- a/src/meta/sfh.c +++ b/src/meta/sfh.c @@ -32,7 +32,7 @@ VGMSTREAM * init_vgmstream_sfh(STREAMFILE *streamFile) { temp_streamFile = setup_sfh_streamfile(streamFile, 0x00, block_size, clean_size, "at3"); if (!temp_streamFile) goto fail; -dump_streamfile(temp_streamFile, 0); + vgmstream = init_vgmstream_riff(temp_streamFile); if (!vgmstream) goto fail; diff --git a/src/meta/xwma_konami.c b/src/meta/xwma_konami.c index b70dda64..350602a3 100644 --- a/src/meta/xwma_konami.c +++ b/src/meta/xwma_konami.c @@ -1,5 +1,6 @@ #include "meta.h" #include "../coding/coding.h" +#include "xwma_konami_streamfile.h" /* MSFC - Konami (Armature?) variation [Metal Gear Solid 2 HD (X360), Metal Gear Solid 3 HD (X360)] */ @@ -8,6 +9,7 @@ VGMSTREAM * init_vgmstream_xwma_konami(STREAMFILE *streamFile) { off_t start_offset; int loop_flag, channel_count, codec, sample_rate; size_t data_size; + STREAMFILE *temp_streamFile = NULL; /* checks */ @@ -19,11 +21,9 @@ VGMSTREAM * init_vgmstream_xwma_konami(STREAMFILE *streamFile) { codec = read_32bitBE(0x04,streamFile); channel_count = read_32bitBE(0x08,streamFile); sample_rate = read_32bitBE(0x0c,streamFile); - data_size = read_32bitBE(0x10,streamFile); + data_size = read_32bitBE(0x10,streamFile); /* data size without padding */ loop_flag = 0; start_offset = 0x20; - //if (data_size + start_offset != get_streamfile_size(streamFile)) - // goto fail; /* build the VGMSTREAM */ @@ -42,8 +42,12 @@ VGMSTREAM * init_vgmstream_xwma_konami(STREAMFILE *streamFile) { avg_bps = read_32bitBE(0x14, streamFile); block_align = read_32bitBE(0x18, streamFile); + /* data has padding (unrelated to KCEJ blocks) */ + temp_streamFile = setup_xwma_konami_streamfile(streamFile, start_offset, block_align); + if (!temp_streamFile) goto fail; + bytes = ffmpeg_make_riff_xwma(buf,0x100, codec, data_size, channel_count, sample_rate, avg_bps, block_align); - vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); + vgmstream->codec_data = init_ffmpeg_header_offset(temp_streamFile, buf,bytes, 0x00,data_size); if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; @@ -53,13 +57,14 @@ VGMSTREAM * init_vgmstream_xwma_konami(STREAMFILE *streamFile) { ms_sample_data msd = {0}; msd.channels = vgmstream->channels; - msd.data_offset = start_offset; + msd.data_offset = 0x00; msd.data_size = data_size; - if (codec == 0x0162) - ;//wmapro_get_samples(&msd, streamFile, block_align, vgmstream->sample_rate,0x00E0); //todo not correct - else - wma_get_samples(&msd, streamFile, block_align, vgmstream->sample_rate,0x001F); + + if (codec == 0x0161) + wma_get_samples(&msd, temp_streamFile, block_align, vgmstream->sample_rate,0x001F); + //else //todo not correct + // wmapro_get_samples(&msd, temp_streamFile, block_align, vgmstream->sample_rate,0x00E0); vgmstream->num_samples = msd.num_samples; if (vgmstream->num_samples == 0) @@ -71,9 +76,11 @@ VGMSTREAM * init_vgmstream_xwma_konami(STREAMFILE *streamFile) { goto fail; #endif + close_streamfile(temp_streamFile); return vgmstream; fail: + close_streamfile(temp_streamFile); close_vgmstream(vgmstream); return NULL; } diff --git a/src/meta/xwma_konami_streamfile.h b/src/meta/xwma_konami_streamfile.h new file mode 100644 index 00000000..d95df459 --- /dev/null +++ b/src/meta/xwma_konami_streamfile.h @@ -0,0 +1,125 @@ +#ifndef _XWMA_KONAMI_STREAMFILE_H_ +#define _XWMA_KONAMI_STREAMFILE_H_ +#include "../streamfile.h" + + +typedef struct { + /* config */ + off_t stream_offset; + size_t stream_size; + size_t block_align; + + /* state */ + off_t logical_offset; /* fake offset */ + off_t physical_offset; /* actual offset */ + size_t block_size; /* current size */ + size_t skip_size; /* size from block start to reach data */ + size_t data_size; /* usable size in a block */ + + size_t logical_size; +} xwma_konami_io_data; + + +static size_t xwma_konami_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, xwma_konami_io_data* data) { + size_t total_read = 0; + + + /* re-start when previous offset (can't map logical<>physical offsets) */ + if (data->logical_offset < 0 || offset < data->logical_offset) { + data->physical_offset = data->stream_offset; + data->logical_offset = 0x00; + data->data_size = 0; + } + + /* read blocks */ + while (length > 0) { + + /* ignore EOF */ + if (offset < 0 || data->physical_offset >= data->stream_offset + data->stream_size) { + break; + } + + /* process new block */ + if (data->data_size == 0) { + data->block_size = align_size_to_block(data->block_align, 0x10); + data->data_size = data->block_align; + data->skip_size = 0x00; + } + + /* move to next block */ + if (data->data_size == 0 || offset >= data->logical_offset + data->data_size) { + data->physical_offset += data->block_size; + data->logical_offset += data->data_size; + data->data_size = 0; + continue; + } + + /* read data */ + { + size_t bytes_consumed, bytes_done, to_read; + + bytes_consumed = offset - data->logical_offset; + to_read = data->data_size - bytes_consumed; + if (to_read > length) + to_read = length; + bytes_done = read_streamfile(dest, data->physical_offset + data->skip_size + bytes_consumed, to_read, streamfile); + + total_read += bytes_done; + dest += bytes_done; + offset += bytes_done; + length -= bytes_done; + + if (bytes_done != to_read || bytes_done == 0) { + break; /* error/EOF */ + } + } + } + + return total_read; +} + +static size_t xwma_konami_io_size(STREAMFILE *streamfile, xwma_konami_io_data* data) { + uint8_t buf[1]; + + if (data->logical_size) + return data->logical_size; + + /* force a fake read at max offset, to get max logical_offset (will be reset next read) */ + xwma_konami_io_read(streamfile, buf, 0x7FFFFFFF, 1, data); + data->logical_size = data->logical_offset; + + return data->logical_size; +} + +/* Handles de-padding Konami XWMA blocked streams */ +static STREAMFILE* setup_xwma_konami_streamfile(STREAMFILE *streamFile, off_t stream_offset, size_t block_align) { + STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; + xwma_konami_io_data io_data = {0}; + size_t io_data_size = sizeof(xwma_konami_io_data); + + io_data.stream_offset = stream_offset; + io_data.stream_size = get_streamfile_size(streamFile) - stream_offset; + io_data.block_align = block_align; + io_data.logical_offset = -1; /* force phys offset reset */ + + /* setup subfile */ + new_streamFile = open_wrap_streamfile(streamFile); + if (!new_streamFile) goto fail; + temp_streamFile = new_streamFile; + + new_streamFile = open_io_streamfile(new_streamFile, &io_data,io_data_size, xwma_konami_io_read,xwma_konami_io_size); + if (!new_streamFile) goto fail; + temp_streamFile = new_streamFile; + + new_streamFile = open_buffer_streamfile(new_streamFile,0); + if (!new_streamFile) goto fail; + temp_streamFile = new_streamFile; + + return temp_streamFile; + +fail: + close_streamfile(temp_streamFile); + return NULL; +} + +#endif /* _XWMA_KONAMI_STREAMFILE_H_ */