Clean streamfile code

This commit is contained in:
bnnm 2020-03-09 00:58:50 +01:00
parent 86b252c7d5
commit 1ac69f90d4
14 changed files with 327 additions and 935 deletions

View File

@ -281,7 +281,7 @@
>
</File>
<File
RelativePath=".\meta\fsb5_interleave_streamfile.h"
RelativePath=".\meta\fsb5_streamfile.h"
>
</File>
<File
@ -365,7 +365,7 @@
>
</File>
<File
RelativePath=".\meta\ubi_lyn_ogg_streamfile.h"
RelativePath=".\meta\ubi_lyn_streamfile.h"
>
</File>
<File

View File

@ -112,7 +112,7 @@
<ClInclude Include="meta\ea_eaac_opus_streamfile.h" />
<ClInclude Include="meta\ea_schl_streamfile.h" />
<ClInclude Include="meta\fsb_interleave_streamfile.h" />
<ClInclude Include="meta\fsb5_interleave_streamfile.h" />
<ClInclude Include="meta\fsb5_streamfile.h" />
<ClInclude Include="meta\jstm_streamfile.h" />
<ClInclude Include="meta\kma9_streamfile.h" />
<ClInclude Include="meta\lrmd_streamfile.h" />
@ -133,7 +133,7 @@
<ClInclude Include="meta\txth_streamfile.h" />
<ClInclude Include="meta\ubi_bao_streamfile.h" />
<ClInclude Include="meta\ubi_sb_streamfile.h" />
<ClInclude Include="meta\ubi_lyn_ogg_streamfile.h" />
<ClInclude Include="meta\ubi_lyn_streamfile.h" />
<ClInclude Include="meta\meta.h" />
<ClInclude Include="meta\hca_keys.h" />
<ClInclude Include="meta\hca_keys_awb.h" />

View File

@ -107,7 +107,7 @@
<ClInclude Include="meta\fsb_interleave_streamfile.h">
<Filter>meta\Header Files</Filter>
</ClInclude>
<ClInclude Include="meta\fsb5_interleave_streamfile.h">
<ClInclude Include="meta\fsb5_streamfile.h">
<Filter>meta\Header Files</Filter>
</ClInclude>
<ClInclude Include="meta\jstm_streamfile.h">
@ -170,7 +170,7 @@
<ClInclude Include="meta\ubi_sb_streamfile.h">
<Filter>meta\Header Files</Filter>
</ClInclude>
<ClInclude Include="meta\ubi_lyn_ogg_streamfile.h">
<ClInclude Include="meta\ubi_lyn_streamfile.h">
<Filter>meta\Header Files</Filter>
</ClInclude>
<ClInclude Include="meta\meta.h">

View File

@ -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_ */

View File

@ -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))

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */