diff --git a/src/libvgmstream.vcproj b/src/libvgmstream.vcproj index 8e13f764..75077171 100644 --- a/src/libvgmstream.vcproj +++ b/src/libvgmstream.vcproj @@ -281,7 +281,7 @@ > - + @@ -133,7 +133,7 @@ - + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 7b5afbf1..00c31baf 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -107,7 +107,7 @@ meta\Header Files - + meta\Header Files @@ -170,7 +170,7 @@ meta\Header Files - + meta\Header Files diff --git a/src/meta/awc_xma_streamfile.h b/src/meta/awc_xma_streamfile.h index 54106624..17b9799c 100644 --- a/src/meta/awc_xma_streamfile.h +++ b/src/meta/awc_xma_streamfile.h @@ -1,245 +1,114 @@ -#ifndef _AWC_XMA_STREAMFILE_H_ -#define _AWC_XMA_STREAMFILE_H_ -#include "../streamfile.h" - - -typedef struct { - /* config */ - int channel; - int channel_count; - size_t block_size; - off_t stream_offset; - size_t stream_size; - - /* state */ - off_t logical_offset; /* offset that corresponds to physical_offset */ - off_t physical_offset; /* actual file offset */ - - size_t skip_size; /* size to skip from a block start to reach data start */ - size_t data_size; /* logical size of the block */ - - size_t logical_size; -} awc_xma_io_data; - - -static size_t get_block_header_size(STREAMFILE *streamFile, off_t offset, awc_xma_io_data *data); -static size_t get_repeated_data_size(STREAMFILE *streamFile, off_t next_offset, size_t repeat_samples); -static size_t get_block_skip_count(STREAMFILE *streamFile, off_t offset, int channel); - -/* Reads plain XMA data of a single stream. Each block has a header and channels have different num_samples/frames. - * Channel data is separate within the block (first all frames of ch0, then ch1, etc), padded, and sometimes - * the last few frames of a channel are repeated in the new block (marked with the "discard samples" field). */ -static size_t awc_xma_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, awc_xma_io_data* data) { - size_t total_read = 0; - size_t frame_size = 0x800; - - /* ignore bad reads */ - if (offset < 0 || offset > data->logical_size) { - return 0; - } - - /* previous offset: re-start as we can't map logical<>physical offsets - * (kinda slow as it trashes buffers, but shouldn't happen often) */ - if (offset < data->logical_offset) { - data->logical_offset = 0x00; - data->physical_offset = data->stream_offset; - data->data_size = 0; - } - - /* read blocks, one at a time */ - while (length > 0) { - - /* ignore EOF */ - if (data->logical_offset >= data->logical_size) { - break; - } - - /* process new block */ - if (data->data_size == 0) { - size_t header_size = get_block_header_size(streamfile, data->physical_offset, data); - /* header table entries = frames... I hope */ - size_t others_size = get_block_skip_count(streamfile, data->physical_offset, data->channel) * frame_size; - //size_t skip_size = read_32bitBE(data->physical_offset + 0x10*data->channel + 0x00, streamfile) * frame_size; - size_t data_size = read_32bitBE(data->physical_offset + 0x10*data->channel + 0x04, streamfile) * frame_size; - size_t repeat_samples = read_32bitBE(data->physical_offset + 0x10*data->channel + 0x08, streamfile); - size_t repeat_size = 0; - - - /* if there are repeat samples current block repeats some frames from last block, find out size */ - if (repeat_samples) { - off_t data_offset = data->physical_offset + header_size + others_size; - repeat_size = get_repeated_data_size(streamfile, data_offset, repeat_samples); - } - - data->skip_size = header_size + others_size + repeat_size; - data->data_size = data_size - repeat_size; - } - - /* move to next block */ - if (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); - - offset += bytes_done; - total_read += bytes_done; - length -= bytes_done; - dest += bytes_done; - - if (bytes_done != to_read || bytes_done == 0) { - break; /* error/EOF */ - } - } - - } - - return total_read; -} - -static size_t awc_xma_io_size(STREAMFILE *streamfile, awc_xma_io_data* data) { - off_t physical_offset, max_physical_offset; - size_t frame_size = 0x800; - size_t logical_size = 0; - - if (data->logical_size) - return data->logical_size; - - physical_offset = data->stream_offset; - max_physical_offset = data->stream_offset + data->stream_size; - - /* get size of the logical stream */ - while (physical_offset < max_physical_offset) { - size_t header_size = get_block_header_size(streamfile, physical_offset, data); - /* header table entries = frames... I hope */ - size_t skip_size = get_block_skip_count(streamfile, physical_offset, data->channel) * frame_size; - //size_t skip_size = read_32bitBE(physical_offset + 0x10*data->channel + 0x00, streamfile) * frame_size; - size_t data_size = read_32bitBE(physical_offset + 0x10*data->channel + 0x04, streamfile) * frame_size; - size_t repeat_samples = read_32bitBE(physical_offset + 0x10*data->channel + 0x08, streamfile); - size_t repeat_size = 0; - - /* if there are repeat samples current block repeats some frames from last block, find out size */ - if (repeat_samples) { - off_t data_offset = physical_offset + header_size + skip_size; - repeat_size = get_repeated_data_size(streamfile, data_offset, repeat_samples); - } - - logical_size += data_size - repeat_size; - physical_offset += data->block_size; - } - - data->logical_size = logical_size; - return data->logical_size; -} - - -/* Prepares custom IO for AWC XMA, which is interleaved XMA in AWC blocks */ -static STREAMFILE* setup_awc_xma_streamfile(STREAMFILE *streamFile, off_t stream_offset, size_t stream_size, size_t block_size, int channel_count, int channel) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - awc_xma_io_data io_data = {0}; - size_t io_data_size = sizeof(awc_xma_io_data); - - io_data.channel = channel; - io_data.channel_count = channel_count; - io_data.stream_offset = stream_offset; - io_data.stream_size = stream_size; - io_data.block_size = block_size; - io_data.physical_offset = stream_offset; - io_data.logical_size = awc_xma_io_size(streamFile, &io_data); /* force init */ - - if (io_data.logical_size > io_data.stream_size) { - VGM_LOG("AWC XMA: wrong logical size\n"); - goto fail; - } - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, awc_xma_io_read,awc_xma_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; -} - -/* block header size, aligned/padded to 0x800 */ -static size_t get_block_header_size(STREAMFILE *streamFile, off_t offset, awc_xma_io_data *data) { - size_t header_size = 0; - int i; - int entries = data->channel_count; - - for (i = 0; i < entries; i++) { - header_size += 0x10; - header_size += read_32bitBE(offset + 0x10*i + 0x04, streamFile) * 0x04; /* entries in the table */ - } - - if (header_size % 0x800) /* padded */ - header_size += 0x800 - (header_size % 0x800); - - return header_size; -} - - -/* find data that repeats in the beginning of a new block at the end of last block */ -static size_t get_repeated_data_size(STREAMFILE *streamFile, off_t next_offset, size_t repeat_samples) { - const size_t frame_size = 0x800; - const size_t samples_per_subframe = 512; - size_t samples_this_frame; - uint8_t subframes; - - //todo: fix this - /* Repeat samples are the number of decoded samples to discard, but in this streamfile we can't do that. - * Also XMA is VBR, and may encode silent frames with up to 63 subframes yet we may have few repeat samples. - * We could find out how many subframes of 512 samples to skip, then adjust the XMA frame header, though - * output will be slightly off since subframes are related. - * - * For now just skip a full frame depending on the number of subframes vs repeat samples. - * Most files work ok-ish but channels may desync slightly. */ - - subframes = ((uint8_t)read_8bit(next_offset,streamFile) >> 2) & 0x3F; /* peek into frame header */ - samples_this_frame = subframes*samples_per_subframe; - if (repeat_samples >= (int)(samples_this_frame*0.13)) { /* skip mosts */ - return frame_size; - } - else { - return 0; - } -} - -/* header has a skip value, but somehow it's sometimes bigger than expected (WHY!?!?) so just sum all */ -static size_t get_block_skip_count(STREAMFILE *streamFile, off_t offset, int channel) { - size_t skip_count = 0; - int i; - - //skip_size = read_32bitBE(offset + 0x10*channel + 0x00, streamFile); /* wrong! */ - for (i = 0; i < channel; i++) { - skip_count += read_32bitBE(offset + 0x10*i + 0x04, streamFile); /* number of frames of this channel */ - } - - return skip_count; -} - - -#endif /* _AWC_XMA_STREAMFILE_H_ */ +#ifndef _AWC_XMA_STREAMFILE_H_ +#define _AWC_XMA_STREAMFILE_H_ +#include "deblock_streamfile.h" + + +static size_t get_block_header_size(STREAMFILE* sf, off_t offset, int channels); +static size_t get_repeated_data_size(STREAMFILE* sf, off_t next_offset, size_t repeat_samples); +static size_t get_block_skip_count(STREAMFILE* sf, off_t offset, int channel); + +static void block_callback(STREAMFILE *sf, deblock_io_data* data) { + const size_t frame_size = 0x800; + int channel = data->cfg.track_number; + int channels = data->cfg.track_count; + + /* Blocks have a header then data per channel, each with a different num_samples/frames, + * separate (first all frames of ch0, then ch1, etc), padded, and sometimes the last few + * frames of a channel are repeated in the new block (marked with "repeat samples"). */ + size_t header_size = get_block_header_size(sf, data->physical_offset, channels); + /* header table entries = frames... I hope */ + size_t others_size = get_block_skip_count(sf, data->physical_offset, channel) * frame_size; + //size_t skip_size = read_u32be(data->physical_offset + 0x10*channel + 0x00, sf) * frame_size; + size_t data_size = read_u32be(data->physical_offset + 0x10*channel + 0x04, sf) * frame_size; + size_t repeat_samples = read_u32be(data->physical_offset + 0x10*channel + 0x08, sf); + size_t repeat_size = 0; + + data->block_size = data->cfg.chunk_size; + + /* if there are repeat samples current block repeats some frames from last block, find out size */ + if (repeat_samples) { + off_t data_offset = data->physical_offset + header_size + others_size; + repeat_size = get_repeated_data_size(sf, data_offset, repeat_samples); + } + + data->skip_size = header_size + others_size + repeat_size; + data->data_size = data_size - repeat_size; +} + +/* block header size, aligned/padded to 0x800 */ +static size_t get_block_header_size(STREAMFILE* sf, off_t offset, int channels) { + size_t header_size = 0; + int i; + + for (i = 0; i < channels; i++) { + header_size += 0x10; + header_size += read_u32be(offset + 0x10*i + 0x04, sf) * 0x04; /* entries in the table */ + } + + if (header_size % 0x800) /* padded */ + header_size += 0x800 - (header_size % 0x800); + + return header_size; +} + +/* find data that repeats in the beginning of a new block at the end of last block */ +static size_t get_repeated_data_size(STREAMFILE* sf, off_t next_offset, size_t repeat_samples) { + const size_t frame_size = 0x800; + const size_t samples_per_subframe = 512; + size_t samples_this_frame; + uint8_t subframes; + + //todo: fix this + /* Repeat samples are the number of decoded samples to discard, but in this streamfile we can't do that. + * Also XMA is VBR, and may encode silent frames with up to 63 subframes yet we may have few repeat samples. + * We could find out how many subframes of 512 samples to skip, then adjust the XMA frame header, though + * output will be slightly off since subframes are related. + * + * For now just skip a full frame depending on the number of subframes vs repeat samples. + * Most files work ok-ish but channels may desync slightly. */ + + subframes = ((uint8_t)read_8bit(next_offset,sf) >> 2) & 0x3F; /* peek into frame header */ + samples_this_frame = subframes*samples_per_subframe; + if (repeat_samples >= (int)(samples_this_frame*0.13)) { /* skip mosts */ + return frame_size; + } + else { + return 0; + } +} + +/* header has a skip value, but somehow it's sometimes bigger than expected (WHY!?!?) so just sum all */ +static size_t get_block_skip_count(STREAMFILE* sf, off_t offset, int channel) { + size_t skip_count = 0; + int i; + + //skip_size = read_u32be(offset + 0x10*channel + 0x00, sf); /* wrong! */ + for (i = 0; i < channel; i++) { + skip_count += read_u32be(offset + 0x10*i + 0x04, sf); /* number of frames of this channel */ + } + + return skip_count; +} + + +/* Deblocks interleaved XMA in AWC blocks */ +static STREAMFILE* setup_awc_xma_streamfile(STREAMFILE *sf, off_t stream_offset, size_t stream_size, size_t block_size, int channel_count, int channel) { + STREAMFILE *new_sf = NULL; + deblock_config_t cfg = {0}; + + cfg.track_number = channel; + cfg.track_count = channel_count; + cfg.stream_start = stream_offset; + cfg.stream_size = stream_size; + cfg.chunk_size = block_size; + //cfg.physical_offset = stream_offset; + //cfg.logical_size = awc_xma_io_size(sf, &cfg); /* force init */ + cfg.block_callback = block_callback; + + new_sf = open_wrap_streamfile(sf); + new_sf = open_io_deblock_streamfile_f(new_sf, &cfg); + //new_sf = open_buffer_streamfile_f(new_sf, 0); + return new_sf; +} + +#endif /* _AWC_XMA_STREAMFILE_H_ */ diff --git a/src/meta/fsb5.c b/src/meta/fsb5.c index 9dafb211..58107cd4 100644 --- a/src/meta/fsb5.c +++ b/src/meta/fsb5.c @@ -1,7 +1,7 @@ #include "meta.h" #include "../coding/coding.h" #include "../layout/layout.h" -#include "fsb5_interleave_streamfile.h" +#include "fsb5_streamfile.h" typedef struct { @@ -533,7 +533,7 @@ static layered_layout_data* build_layered_fsb5_celt(STREAMFILE *streamFile, fsb5 goto fail; #endif - temp_streamFile = setup_fsb5_interleave_streamfile(streamFile, fsb5->stream_offset, fsb5->stream_size, layers, i, FSB5_INT_CELT, interleave); + temp_streamFile = setup_fsb5_streamfile(streamFile, fsb5->stream_offset, fsb5->stream_size, layers, i, interleave); if (!temp_streamFile) goto fail; if (!vgmstream_open_stream(data->layers[i], temp_streamFile, 0x00)) @@ -609,7 +609,7 @@ static layered_layout_data* build_layered_fsb5_atrac9(STREAMFILE *streamFile, fs goto fail; #endif - temp_streamFile = setup_fsb5_interleave_streamfile(streamFile, fsb5->stream_offset, fsb5->stream_size, layers, i, FSB5_INT_ATRAC9, interleave); + temp_streamFile = setup_fsb5_streamfile(streamFile, fsb5->stream_offset, fsb5->stream_size, layers, i, interleave); if (!temp_streamFile) goto fail; if (!vgmstream_open_stream(data->layers[i], temp_streamFile, 0x00)) diff --git a/src/meta/fsb5_interleave_streamfile.h b/src/meta/fsb5_interleave_streamfile.h deleted file mode 100644 index d9cb14c2..00000000 --- a/src/meta/fsb5_interleave_streamfile.h +++ /dev/null @@ -1,201 +0,0 @@ -#ifndef _FSB5_INTERLEAVE_STREAMFILE_H_ -#define _FSB5_INTERLEAVE_STREAMFILE_H_ -#include "../streamfile.h" - -typedef enum { FSB5_INT_CELT, FSB5_INT_ATRAC9 } fsb_interleave_codec_t; -typedef struct { - /* state */ - off_t logical_offset; /* offset that corresponds to physical_offset */ - off_t physical_offset; /* actual file offset */ - int skip_frames; /* frames to skip from other streams at points */ - - /* config */ - fsb_interleave_codec_t codec; - size_t interleave; - int stream_count; - int stream_number; - size_t stream_size; - off_t start_offset; /* pointing to the stream's beginning */ - size_t total_size; /* size of the resulting substream */ -} fsb_interleave_io_data; - - - -/* Reads skipping other streams */ -static size_t fsb_interleave_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, fsb_interleave_io_data* data) { - size_t total_read = 0; - - /* ignore bad reads */ - if (offset < 0 || offset > data->total_size) { - return total_read; - } - - /* previous offset: re-start as we can't map logical<>physical offsets - * (kinda slow as it trashes buffers, but shouldn't happen often) */ - if (offset < data->logical_offset) { - data->physical_offset = data->start_offset; - data->logical_offset = 0x00; - data->skip_frames = data->stream_number; - } - - /* read doing one frame at a time */ - while (length > 0) { - size_t to_read, bytes_read; - off_t intrablock_offset, intradata_offset; - uint32_t data_size; - - if (offset >= data->total_size) - break; - - /* get current data */ - switch (data->codec) { - case FSB5_INT_CELT: - case FSB5_INT_ATRAC9: - data_size = data->interleave; - break; - - default: - return 0; - } - - /* skip frames from other streams */ - if (data->skip_frames) { - data->physical_offset += data_size; - data->skip_frames--; - continue; - } - - /* requested offset is outside current block, try next */ - if (offset >= data->logical_offset + data_size) { - data->physical_offset += data_size; - data->logical_offset += data_size; - data->skip_frames = data->stream_count - 1; - continue; - } - - /* reads could fall in the middle of the block */ - intradata_offset = offset - data->logical_offset; - intrablock_offset = intradata_offset; - - /* clamp reads up to this block's end */ - to_read = (data_size - intradata_offset); - if (to_read > length) - to_read = length; - if (to_read == 0) - break; /* should never happen... */ - - /* finally read and move buffer/offsets */ - bytes_read = read_streamfile(dest, data->physical_offset + intrablock_offset, to_read, streamfile); - total_read += bytes_read; - if (bytes_read != to_read) - break; /* couldn't read fully */ - - dest += bytes_read; - offset += bytes_read; - length -= bytes_read; - - /* block fully read, go next */ - if (intradata_offset + bytes_read == data_size) { - data->physical_offset += data_size; - data->logical_offset += data_size; - data->skip_frames = data->stream_count - 1; - } - } - - return total_read; -} - -static size_t fsb_interleave_io_size(STREAMFILE *streamfile, fsb_interleave_io_data* data) { - off_t physical_offset, max_physical_offset; - size_t total_size = 0; - int skip_frames = 0; - - if (data->total_size) - return data->total_size; - - physical_offset = data->start_offset; - max_physical_offset = physical_offset + data->stream_size; - skip_frames = data->stream_number; - - /* get size of the underlying stream, skipping other streams - * (all streams should have the same frame count) */ - while (physical_offset < max_physical_offset) { - size_t data_size; - - data_size = data->interleave; - switch(data->codec) { - case FSB5_INT_CELT: - case FSB5_INT_ATRAC9: - data_size = data->interleave; - break; - - default: - return 0; - } - - /* there may be padding at the end, so this doubles as EOF marker */ - if (data_size == 0) - break; - if (physical_offset+data_size > max_physical_offset) - break; - - /* skip frames from other streams */ - if (skip_frames) { - physical_offset += data_size; - skip_frames--; - continue; - } - - physical_offset += data_size; - total_size += data_size; - skip_frames = data->stream_count - 1; - } - - data->total_size = total_size; - return data->total_size; -} - - -/* Prepares custom IO for multistreams, interleaves 1 packet per stream */ -static STREAMFILE* setup_fsb5_interleave_streamfile(STREAMFILE *streamFile, off_t start_offset, size_t stream_size, int stream_count, int stream_number, fsb_interleave_codec_t codec, size_t interleave) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - fsb_interleave_io_data io_data = {0}; - size_t io_data_size = sizeof(fsb_interleave_io_data); - - io_data.start_offset = start_offset; - io_data.physical_offset = start_offset; - io_data.skip_frames = stream_number; /* adjust since start_offset points to the first */ - io_data.codec = codec; - io_data.interleave = interleave; - io_data.stream_count = stream_count; - io_data.stream_number = stream_number; - io_data.stream_size = stream_size; /* full size for all streams */ - - io_data.total_size = fsb_interleave_io_size(streamFile, &io_data); /* force init, size of a single stream */ - - if (io_data.total_size == 0 || io_data.total_size > io_data.stream_size) { - VGM_LOG("FSB5 INTERLEAVE: wrong total_size %x vs %x\n", io_data.total_size,io_data.stream_size); - goto fail; - } - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, fsb_interleave_io_read,fsb_interleave_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 /* _FSB_INTERLEAVE_STREAMFILE_H_ */ diff --git a/src/meta/fsb5_streamfile.h b/src/meta/fsb5_streamfile.h new file mode 100644 index 00000000..19175148 --- /dev/null +++ b/src/meta/fsb5_streamfile.h @@ -0,0 +1,21 @@ +#ifndef _FSB5_STREAMFILE_H_ +#define _FSB5_STREAMFILE_H_ +#include "deblock_streamfile.h" + +static STREAMFILE* setup_fsb5_streamfile(STREAMFILE* sf, off_t stream_start, size_t stream_size, int stream_count, int stream_number, size_t interleave) { + STREAMFILE* new_sf = NULL; + deblock_config_t cfg = {0}; + + cfg.stream_start = stream_start; + cfg.stream_size = stream_size; + cfg.chunk_size = interleave; + cfg.step_start = stream_number; + cfg.step_count = stream_count; + + /* setup sf */ + new_sf = open_wrap_streamfile(sf); + new_sf = open_io_deblock_streamfile_f(new_sf, &cfg); + return new_sf; +} + +#endif /* _FSB5_STREAMFILE_H_ */ diff --git a/src/meta/opus.c b/src/meta/opus.c index 5213a065..932ecef2 100644 --- a/src/meta/opus.c +++ b/src/meta/opus.c @@ -172,7 +172,7 @@ VGMSTREAM * init_vgmstream_opus_capcom(STREAMFILE *streamFile) { /* 0x30+: extra chunks (0x00: 0x7f, 0x04: num_sample), alt loop starts/regions? */ if (channel_count == 6) { - /* 2ch multistream hacky-hacks, don't try this at home. We'll end up with: + /* 2ch multistream hacky-hacks in RE:RE, don't try this at home. We'll end up with: * main vgmstream > N vgmstream layers > substream IO deinterleaver > opus meta > Opus IO transmogrifier (phew) */ layered_layout_data* data = NULL; int layers = channel_count / 2; @@ -193,11 +193,11 @@ VGMSTREAM * init_vgmstream_opus_capcom(STREAMFILE *streamFile) { /* open each layer subfile */ for (i = 0; i < layers; i++) { - STREAMFILE* temp_streamFile = setup_opus_interleave_streamfile(streamFile, offset+0x28*i, layers); - if (!temp_streamFile) goto fail; + STREAMFILE* temp_sf = setup_opus_interleave_streamfile(streamFile, offset, i, layers); + if (!temp_sf) goto fail; - data->layers[i] = init_vgmstream_opus(temp_streamFile, meta_OPUS, 0x00, num_samples,loop_start,loop_end); - close_streamfile(temp_streamFile); + data->layers[i] = init_vgmstream_opus(temp_sf, meta_OPUS, 0x00, num_samples,loop_start,loop_end); + close_streamfile(temp_sf); if (!data->layers[i]) goto fail; } diff --git a/src/meta/opus_interleave_streamfile.h b/src/meta/opus_interleave_streamfile.h index 503e8341..4985e403 100644 --- a/src/meta/opus_interleave_streamfile.h +++ b/src/meta/opus_interleave_streamfile.h @@ -1,136 +1,47 @@ -#ifndef _OPUS_INTERLEAVE_STREAMFILE_H_ -#define _OPUS_INTERLEAVE_STREAMFILE_H_ -#include "../streamfile.h" - - -typedef struct { - /* config */ - int streams; - off_t stream_offset; - - /* state */ - off_t logical_offset; /* offset that corresponds to physical_offset */ - off_t physical_offset; /* actual file offset */ - int skip_frames; /* frames to skip from other streams at points */ - - size_t logical_size; -} opus_interleave_io_data; - - -/* Reads skipping other streams */ -static size_t opus_interleave_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, opus_interleave_io_data* data) { - size_t total_read = 0; - - /* ignore bad reads */ - if (offset < 0 || offset > data->logical_size) { - return total_read; - } - - /* previous offset: re-start as we can't map logical<>physical offsets (may be VBR) */ - if (offset < data->logical_offset) { - data->physical_offset = data->stream_offset; - data->logical_offset = 0x00; - data->skip_frames = 0; - } - - /* read doing one frame at a time */ - while (length > 0) { - size_t data_size; - - /* ignore EOF */ - if (data->logical_offset >= data->logical_size) { - break; - } - - /* process block (must be read every time since skip frame sizes may vary) */ - { - data_size = read_32bitBE(data->physical_offset,streamfile); - if ((uint32_t)data_size == 0x01000080) //todo not ok if offset between 0 and header_size - data_size = read_32bitLE(data->physical_offset+0x10,streamfile) + 0x08; - else - data_size += 0x08; - } - - /* skip frames from other streams */ - if (data->skip_frames) { - data->physical_offset += data_size; - data->skip_frames--; - continue; - } - - /* move to next block */ - if (offset >= data->logical_offset + data_size) { - data->physical_offset += data_size; - data->logical_offset += data_size; - data->skip_frames = data->streams - 1; - continue; - } - - /* read data */ - { - size_t bytes_consumed, bytes_done, to_read; - - bytes_consumed = offset - data->logical_offset; - to_read = data_size - bytes_consumed; - if (to_read > length) - to_read = length; - bytes_done = read_streamfile(dest, data->physical_offset + bytes_consumed, to_read, streamfile); - - offset += bytes_done; - total_read += bytes_done; - length -= bytes_done; - dest += bytes_done; - - if (bytes_done != to_read || bytes_done == 0) { - break; /* error/EOF */ - } - } - } - - return total_read; -} - -static size_t opus_interleave_io_size(STREAMFILE *streamfile, opus_interleave_io_data* data) { - off_t info_offset; - - if (data->logical_size) - return data->logical_size; - - info_offset = read_32bitLE(data->stream_offset+0x10,streamfile); - data->logical_size = (0x08+info_offset) + read_32bitLE(data->stream_offset+info_offset+0x04,streamfile); - return data->logical_size; -} - - -/* Prepares custom IO for multistream, interleaves 1 packet per stream */ -static STREAMFILE* setup_opus_interleave_streamfile(STREAMFILE *streamFile, off_t start_offset, int streams) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - opus_interleave_io_data io_data = {0}; - size_t io_data_size = sizeof(opus_interleave_io_data); - - io_data.stream_offset = start_offset; - io_data.streams = streams; - io_data.physical_offset = start_offset; - io_data.logical_size = opus_interleave_io_size(streamFile, &io_data); /* force init */ - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, opus_interleave_io_read,opus_interleave_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 /* _OPUS_INTERLEAVE_STREAMFILE_H_ */ +#ifndef _OPUS_INTERLEAVE_STREAMFILE_H_ +#define _OPUS_INTERLEAVE_STREAMFILE_H_ +#include "deblock_streamfile.h" + + +static void block_callback(STREAMFILE* sf, deblock_io_data* data) { + uint32_t chunk_size = read_u32be(data->physical_offset, sf); + + //todo not ok if offset between 0 and header_size + if (chunk_size == 0x01000080) /* header */ + chunk_size = read_u32le(data->physical_offset + 0x10, sf) + 0x08; + else + chunk_size += 0x08; + data->block_size = chunk_size; + data->data_size = data->block_size; +} + +/* Deblocks NXOPUS streams that interleave 1 packet per stream */ +static STREAMFILE* setup_opus_interleave_streamfile(STREAMFILE* sf, off_t start_offset, int stream_number, int stream_count) { + STREAMFILE* new_sf = NULL; + deblock_config_t cfg = {0}; + + cfg.stream_start = start_offset; + cfg.step_start = stream_number; + cfg.step_count = stream_count; + { + int i; + off_t offset = start_offset; + /* read full size from NXOPUS header N */ + for (i = 0; i < stream_number + 1; i++) { + off_t start = read_s32le(offset + 0x10, sf); + off_t size = read_s32le(offset + start + 0x04, sf); + + if (i == stream_number) + cfg.logical_size = 0x08 + start + size; + offset += 0x08 + start; + } + } + cfg.block_callback = block_callback; + + new_sf = open_wrap_streamfile(sf); + new_sf = open_io_deblock_streamfile_f(new_sf, &cfg); + //new_sf = open_buffer_streamfile_f(new_sf, 0); + return new_sf; +} + +#endif /* _OPUS_INTERLEAVE_STREAMFILE_H_ */ diff --git a/src/meta/sqex_sead_streamfile.h b/src/meta/sqex_sead_streamfile.h index 98cad928..25f567c8 100644 --- a/src/meta/sqex_sead_streamfile.h +++ b/src/meta/sqex_sead_streamfile.h @@ -1,86 +1,67 @@ -#ifndef _SQEX_SEAD_STREAMFILE_H_ -#define _SQEX_SEAD_STREAMFILE_H_ -#include "../streamfile.h" - -static STREAMFILE* setup_sqex_sead_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, int encryption, size_t header_size, size_t key_start); - - -typedef struct { - size_t header_size; - size_t key_start; -} sqex_sead_decryption_data; - - -static size_t sqex_sead_decryption_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, sqex_sead_decryption_data* data) { - /* Found in FFXII_TZA.exe (same key in SCD Ogg V3) */ - static const uint8_t encryption_key[0x100] = { - 0x3A,0x32,0x32,0x32,0x03,0x7E,0x12,0xF7,0xB2,0xE2,0xA2,0x67,0x32,0x32,0x22,0x32, // 00-0F - 0x32,0x52,0x16,0x1B,0x3C,0xA1,0x54,0x7B,0x1B,0x97,0xA6,0x93,0x1A,0x4B,0xAA,0xA6, // 10-1F - 0x7A,0x7B,0x1B,0x97,0xA6,0xF7,0x02,0xBB,0xAA,0xA6,0xBB,0xF7,0x2A,0x51,0xBE,0x03, // 20-2F - 0xF4,0x2A,0x51,0xBE,0x03,0xF4,0x2A,0x51,0xBE,0x12,0x06,0x56,0x27,0x32,0x32,0x36, // 30-3F - 0x32,0xB2,0x1A,0x3B,0xBC,0x91,0xD4,0x7B,0x58,0xFC,0x0B,0x55,0x2A,0x15,0xBC,0x40, // 40-4F - 0x92,0x0B,0x5B,0x7C,0x0A,0x95,0x12,0x35,0xB8,0x63,0xD2,0x0B,0x3B,0xF0,0xC7,0x14, // 50-5F - 0x51,0x5C,0x94,0x86,0x94,0x59,0x5C,0xFC,0x1B,0x17,0x3A,0x3F,0x6B,0x37,0x32,0x32, // 60-6F - 0x30,0x32,0x72,0x7A,0x13,0xB7,0x26,0x60,0x7A,0x13,0xB7,0x26,0x50,0xBA,0x13,0xB4, // 70-7F - 0x2A,0x50,0xBA,0x13,0xB5,0x2E,0x40,0xFA,0x13,0x95,0xAE,0x40,0x38,0x18,0x9A,0x92, // 80-8F - 0xB0,0x38,0x00,0xFA,0x12,0xB1,0x7E,0x00,0xDB,0x96,0xA1,0x7C,0x08,0xDB,0x9A,0x91, // 90-9F - 0xBC,0x08,0xD8,0x1A,0x86,0xE2,0x70,0x39,0x1F,0x86,0xE0,0x78,0x7E,0x03,0xE7,0x64, // A0-AF - 0x51,0x9C,0x8F,0x34,0x6F,0x4E,0x41,0xFC,0x0B,0xD5,0xAE,0x41,0xFC,0x0B,0xD5,0xAE, // B0-BF - 0x41,0xFC,0x3B,0x70,0x71,0x64,0x33,0x32,0x12,0x32,0x32,0x36,0x70,0x34,0x2B,0x56, // C0-CF - 0x22,0x70,0x3A,0x13,0xB7,0x26,0x60,0xBA,0x1B,0x94,0xAA,0x40,0x38,0x00,0xFA,0xB2, // D0-DF - 0xE2,0xA2,0x67,0x32,0x32,0x12,0x32,0xB2,0x32,0x32,0x32,0x32,0x75,0xA3,0x26,0x7B, // E0-EF - 0x83,0x26,0xF9,0x83,0x2E,0xFF,0xE3,0x16,0x7D,0xC0,0x1E,0x63,0x21,0x07,0xE3,0x01, // F0-FF - }; - size_t bytes_read; - off_t encrypted_offset = data->header_size; - int i; - - bytes_read = streamfile->read(streamfile, dest, offset, length); - - /* decrypt data (xor) */ - if (offset >= encrypted_offset) { - for (i = 0; i < bytes_read; i++) { - dest[i] ^= encryption_key[(data->key_start + (offset - encrypted_offset) + i) % 0x100]; - } - } - - return bytes_read; -} - -/* decrypts subfile if neccessary */ -static STREAMFILE* setup_sqex_sead_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, int encryption, size_t header_size, size_t key_start) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - if (encryption) { - sqex_sead_decryption_data io_data = {0}; - size_t io_data_size = sizeof(sqex_sead_decryption_data); - - io_data.header_size = header_size; - io_data.key_start = key_start; - - new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, sqex_sead_decryption_read,NULL); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - } - - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,"hca"); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} - -#endif /* _SQEX_SEAD_STREAMFILE_H_ */ +#ifndef _SQEX_SEAD_STREAMFILE_H_ +#define _SQEX_SEAD_STREAMFILE_H_ +#include "../streamfile.h" + + +typedef struct { + size_t start; + size_t key_start; +} sqex_sead_io_data; + + +static size_t sqex_sead_io_read(STREAMFILE *sf, uint8_t *dest, off_t offset, size_t length, sqex_sead_io_data* data) { + /* Found in FFXII_TZA.exe (same key in SCD Ogg V3) */ + static const uint8_t key[0x100] = { + 0x3A,0x32,0x32,0x32,0x03,0x7E,0x12,0xF7,0xB2,0xE2,0xA2,0x67,0x32,0x32,0x22,0x32, // 00-0F + 0x32,0x52,0x16,0x1B,0x3C,0xA1,0x54,0x7B,0x1B,0x97,0xA6,0x93,0x1A,0x4B,0xAA,0xA6, // 10-1F + 0x7A,0x7B,0x1B,0x97,0xA6,0xF7,0x02,0xBB,0xAA,0xA6,0xBB,0xF7,0x2A,0x51,0xBE,0x03, // 20-2F + 0xF4,0x2A,0x51,0xBE,0x03,0xF4,0x2A,0x51,0xBE,0x12,0x06,0x56,0x27,0x32,0x32,0x36, // 30-3F + 0x32,0xB2,0x1A,0x3B,0xBC,0x91,0xD4,0x7B,0x58,0xFC,0x0B,0x55,0x2A,0x15,0xBC,0x40, // 40-4F + 0x92,0x0B,0x5B,0x7C,0x0A,0x95,0x12,0x35,0xB8,0x63,0xD2,0x0B,0x3B,0xF0,0xC7,0x14, // 50-5F + 0x51,0x5C,0x94,0x86,0x94,0x59,0x5C,0xFC,0x1B,0x17,0x3A,0x3F,0x6B,0x37,0x32,0x32, // 60-6F + 0x30,0x32,0x72,0x7A,0x13,0xB7,0x26,0x60,0x7A,0x13,0xB7,0x26,0x50,0xBA,0x13,0xB4, // 70-7F + 0x2A,0x50,0xBA,0x13,0xB5,0x2E,0x40,0xFA,0x13,0x95,0xAE,0x40,0x38,0x18,0x9A,0x92, // 80-8F + 0xB0,0x38,0x00,0xFA,0x12,0xB1,0x7E,0x00,0xDB,0x96,0xA1,0x7C,0x08,0xDB,0x9A,0x91, // 90-9F + 0xBC,0x08,0xD8,0x1A,0x86,0xE2,0x70,0x39,0x1F,0x86,0xE0,0x78,0x7E,0x03,0xE7,0x64, // A0-AF + 0x51,0x9C,0x8F,0x34,0x6F,0x4E,0x41,0xFC,0x0B,0xD5,0xAE,0x41,0xFC,0x0B,0xD5,0xAE, // B0-BF + 0x41,0xFC,0x3B,0x70,0x71,0x64,0x33,0x32,0x12,0x32,0x32,0x36,0x70,0x34,0x2B,0x56, // C0-CF + 0x22,0x70,0x3A,0x13,0xB7,0x26,0x60,0xBA,0x1B,0x94,0xAA,0x40,0x38,0x00,0xFA,0xB2, // D0-DF + 0xE2,0xA2,0x67,0x32,0x32,0x12,0x32,0xB2,0x32,0x32,0x32,0x32,0x75,0xA3,0x26,0x7B, // E0-EF + 0x83,0x26,0xF9,0x83,0x2E,0xFF,0xE3,0x16,0x7D,0xC0,0x1E,0x63,0x21,0x07,0xE3,0x01, // F0-FF + }; + int i; + size_t bytes = read_streamfile(dest, offset, length, sf); + + /* decrypt data (xor) */ + //if (offset >= data->start) { + for (i = 0; i < bytes; i++) { + if (offset + i >= data->start) { //todo recheck + dest[i] ^= key[(data->key_start + (offset - data->start) + i) % sizeof(key)]; + } + } + //} + + return bytes; +} + +/* decrypts subfile if needed */ +static STREAMFILE* setup_sqex_sead_streamfile(STREAMFILE* sf, off_t subfile_offset, size_t subfile_size, int encryption, size_t header_size, size_t key_start) { + STREAMFILE* new_sf = NULL; + + /* setup sf */ + new_sf = open_wrap_streamfile(sf); + new_sf = open_clamp_streamfile_f(new_sf, subfile_offset, subfile_size); + if (encryption) { + sqex_sead_io_data io_data = {0}; + + io_data.start = header_size; + io_data.key_start = key_start; + + new_sf = open_io_streamfile_f(new_sf, &io_data, sizeof(sqex_sead_io_data), sqex_sead_io_read, NULL); + } + + new_sf = open_fakename_streamfile_f(new_sf, NULL, "hca"); + return new_sf; +} + +#endif /* _SQEX_SEAD_STREAMFILE_H_ */ diff --git a/src/meta/ubi_lyn.c b/src/meta/ubi_lyn.c index 90f1897c..4e8200b8 100644 --- a/src/meta/ubi_lyn.c +++ b/src/meta/ubi_lyn.c @@ -1,9 +1,8 @@ #include "meta.h" #include "../layout/layout.h" #include "../coding/coding.h" -#include "ubi_lyn_ogg_streamfile.h" +#include "ubi_lyn_streamfile.h" -static STREAMFILE* setup_lyn_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size); /* LyN RIFF - from Ubisoft LyN engine games [Red Steel 2 (Wii), Adventures of Tintin (Multi), From Dust (Multi), Just Dance 3/4 (multi)] */ VGMSTREAM * init_vgmstream_ubi_lyn(STREAMFILE *streamFile) { @@ -111,7 +110,7 @@ VGMSTREAM * init_vgmstream_ubi_lyn(STREAMFILE *streamFile) { #ifdef VGM_USE_VORBIS case 0x3157: { /* Ogg (PC), interleaved 1ch */ - size_t interleave_size, stride_size; + size_t interleave_size; layered_layout_data* data = NULL; int i; @@ -119,7 +118,6 @@ VGMSTREAM * init_vgmstream_ubi_lyn(STREAMFILE *streamFile) { goto fail; interleave_size = read_32bitLE(start_offset+0x04,streamFile); - stride_size = interleave_size * channel_count; /* interleave is adjusted so there is no smaller last block, it seems */ vgmstream->coding_type = coding_OGG_VORBIS; @@ -132,15 +130,15 @@ VGMSTREAM * init_vgmstream_ubi_lyn(STREAMFILE *streamFile) { /* open each layer subfile */ for (i = 0; i < channel_count; i++) { - STREAMFILE* temp_streamFile = NULL; - size_t total_size = read_32bitLE(start_offset+0x08 + 0x04*i,streamFile); - off_t layer_offset = start_offset+0x08 + 0x04*channel_count + interleave_size*i; + STREAMFILE* temp_sf = NULL; + size_t logical_size = read_32bitLE(start_offset+0x08 + 0x04*i,streamFile); + off_t layer_offset = start_offset + 0x08 + 0x04*channel_count; //+ interleave_size*i; - temp_streamFile = setup_lyn_ogg_streamfile(streamFile, layer_offset, interleave_size, stride_size, total_size); - if (!temp_streamFile) goto fail; + temp_sf = setup_ubi_lyn_streamfile(streamFile, layer_offset, interleave_size, i, channel_count, logical_size); + if (!temp_sf) goto fail; - data->layers[i] = init_vgmstream_ogg_vorbis(temp_streamFile); - close_streamfile(temp_streamFile); + data->layers[i] = init_vgmstream_ogg_vorbis(temp_sf); + close_streamfile(temp_sf); if (!data->layers[i]) goto fail; /* could validate between layers, meh */ @@ -229,7 +227,7 @@ fail: /* LyN RIFF in containers */ VGMSTREAM * init_vgmstream_ubi_lyn_container(STREAMFILE *streamFile) { VGMSTREAM *vgmstream = NULL; - STREAMFILE *temp_streamFile = NULL; + STREAMFILE *temp_sf = NULL; off_t subfile_offset; size_t subfile_size; @@ -259,35 +257,16 @@ VGMSTREAM * init_vgmstream_ubi_lyn_container(STREAMFILE *streamFile) { subfile_size = read_32bitLE(subfile_offset+0x04,streamFile) + 0x04+0x04; - temp_streamFile = setup_lyn_streamfile(streamFile, subfile_offset,subfile_size); - if (!temp_streamFile) goto fail; + temp_sf = setup_subfile_streamfile(streamFile, subfile_offset, subfile_size, NULL); + if (!temp_sf) goto fail; - vgmstream = init_vgmstream_ubi_lyn(temp_streamFile); + vgmstream = init_vgmstream_ubi_lyn(temp_sf); - close_streamfile(temp_streamFile); + close_streamfile(temp_sf); return vgmstream; fail: - close_streamfile(temp_streamFile); + close_streamfile(temp_sf); close_vgmstream(vgmstream); return NULL; } - -static STREAMFILE* setup_lyn_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} diff --git a/src/meta/ubi_lyn_ogg_streamfile.h b/src/meta/ubi_lyn_ogg_streamfile.h deleted file mode 100644 index 364718d3..00000000 --- a/src/meta/ubi_lyn_ogg_streamfile.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef _LYN_OGG_STREAMFILE_H_ -#define _LYN_OGG_STREAMFILE_H_ -#include "../streamfile.h" - - -typedef struct { - off_t start_physical_offset; /* interleaved data start, for this substream */ - size_t interleave_block_size; /* max size that can be read before encountering other substreams */ - size_t stride_size; /* step size between interleave blocks (interleave*channels) */ - size_t total_size; /* final size of the deinterleaved substream */ -} lyn_ogg_io_data; - - -/* Handles deinterleaving of complete files, skipping portions or other substreams. */ -static size_t lyn_ogg_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, lyn_ogg_io_data* data) { - size_t total_read = 0; - - while (length > 0) { - size_t to_read; - size_t length_available; - off_t block_num; - off_t intrablock_offset; - off_t physical_offset; - - block_num = offset / data->interleave_block_size; - intrablock_offset = offset % data->interleave_block_size; - physical_offset = data->start_physical_offset + block_num*data->stride_size + intrablock_offset; - length_available = data->interleave_block_size - intrablock_offset; - - if (length < length_available) { - to_read = length; - } - else { - to_read = length_available; - } - - if (to_read > 0) { - size_t bytes_read; - - bytes_read = read_streamfile(dest, physical_offset, to_read, streamfile); - total_read += bytes_read; - - if (bytes_read != to_read) { - return total_read; - } - - dest += bytes_read; - offset += bytes_read; - length -= bytes_read; - } - } - - return total_read; -} - -static size_t lyn_ogg_io_size(STREAMFILE *streamfile, lyn_ogg_io_data* data) { - return data->total_size; -} - - -static STREAMFILE* setup_lyn_ogg_streamfile(STREAMFILE *streamFile, off_t start_offset, size_t interleave_block_size, size_t stride_size, size_t total_size) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - lyn_ogg_io_data io_data = {0}; - size_t io_data_size = sizeof(lyn_ogg_io_data); - - io_data.start_physical_offset = start_offset; - io_data.interleave_block_size = interleave_block_size; - io_data.stride_size = stride_size; - io_data.total_size = total_size; - - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, lyn_ogg_io_read,lyn_ogg_io_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,"ogg"); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} - -#endif /* _LYN_OGG_STREAMFILE_H_ */ diff --git a/src/meta/ubi_lyn_streamfile.h b/src/meta/ubi_lyn_streamfile.h new file mode 100644 index 00000000..ecef0f6d --- /dev/null +++ b/src/meta/ubi_lyn_streamfile.h @@ -0,0 +1,23 @@ +#ifndef _UBI_LYN_STREAMFILE_H_ +#define _UBI_LYN_STREAMFILE_H_ +#include "deblock_streamfile.h" + +/* Deinterleaves LYN streams */ +static STREAMFILE* setup_ubi_lyn_streamfile(STREAMFILE* sf, off_t stream_offset, size_t interleave_size, int stream_number, int stream_count, size_t logical_size) { + STREAMFILE *new_sf = NULL; + deblock_config_t cfg = {0}; +VGM_LOG("so=%lx, chu=%x, n=%i, c=%i, lo=%x\n", stream_offset, interleave_size, stream_number, stream_count, logical_size); + cfg.stream_start = stream_offset; + cfg.chunk_size = interleave_size; + cfg.step_start = stream_number; + cfg.step_count = stream_count; + cfg.logical_size = logical_size; + + new_sf = open_wrap_streamfile(sf); + new_sf = open_io_deblock_streamfile_f(new_sf, &cfg); + //new_sf = open_buffer_streamfile_f(new_sf, 0); + new_sf = open_fakename_streamfile_f(new_sf, NULL, "ogg"); + return new_sf; +} + +#endif /* _UBI_LYN_STREAMFILE_H_ */ diff --git a/src/meta/xwma_konami_streamfile.h b/src/meta/xwma_konami_streamfile.h index d95df459..2332695c 100644 --- a/src/meta/xwma_konami_streamfile.h +++ b/src/meta/xwma_konami_streamfile.h @@ -1,125 +1,26 @@ -#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_ */ +#ifndef _XWMA_KONAMI_STREAMFILE_H_ +#define _XWMA_KONAMI_STREAMFILE_H_ +#include "deblock_streamfile.h" + +static void block_callback(STREAMFILE* sf, deblock_io_data* data) { + data->block_size = align_size_to_block(data->cfg.chunk_size, 0x10); + data->data_size = data->cfg.chunk_size; + data->skip_size = 0x00; +} + +/* De-pads Konami XWMA streams */ +static STREAMFILE* setup_xwma_konami_streamfile(STREAMFILE* sf, off_t stream_offset, size_t block_align) { + STREAMFILE* new_sf = NULL; + deblock_config_t cfg = {0}; + + cfg.stream_start = stream_offset; + cfg.chunk_size = block_align; + cfg.block_callback = block_callback; + + new_sf = open_wrap_streamfile(sf); + new_sf = open_io_deblock_streamfile_f(new_sf, &cfg); + //new_sf = open_buffer_streamfile_f(new_sf, 0); + return new_sf; +} + +#endif /* _XWMA_KONAMI_STREAMFILE_H_ */