2020-04-04 22:08:13 +02:00
|
|
|
#ifndef _MUL_STREAMFILE_H_
|
|
|
|
#define _MUL_STREAMFILE_H_
|
|
|
|
#include "deblock_streamfile.h"
|
|
|
|
|
2020-09-06 19:26:37 +02:00
|
|
|
|
2020-04-04 22:08:13 +02:00
|
|
|
static void block_callback(STREAMFILE* sf, deblock_io_data* data) {
|
|
|
|
uint32_t (*read_u32)(off_t,STREAMFILE*) = data->cfg.big_endian ? read_u32be : read_u32le;
|
|
|
|
|
2020-09-06 19:26:37 +02:00
|
|
|
/* Blocks have base header + sub-blocks with track sub-header.
|
|
|
|
* Some blocks don't contain all channels (instead they begin next block). */
|
2020-04-04 22:08:13 +02:00
|
|
|
|
2020-09-06 19:26:37 +02:00
|
|
|
if (data->chunk_size && data->chunk_size < 0x10) {
|
|
|
|
/* padding after all sub-blocks */
|
|
|
|
data->block_size = data->chunk_size;
|
2020-04-04 22:08:13 +02:00
|
|
|
data->data_size = 0;
|
|
|
|
data->skip_size = 0;
|
2020-09-06 19:26:37 +02:00
|
|
|
data->chunk_size = 0;
|
2020-04-04 22:08:13 +02:00
|
|
|
}
|
2020-09-06 19:26:37 +02:00
|
|
|
else if (data->chunk_size) {
|
|
|
|
/* audio block sub-headers, ignore data for other tracks */
|
|
|
|
uint32_t track_size = read_u32(data->physical_offset + 0x00, sf);
|
|
|
|
uint32_t track_number = read_u32(data->physical_offset + 0x04, sf);
|
|
|
|
/* 0x08: dummy (may contain un-init'd data) */
|
|
|
|
/* 0x0c: dummy (may contain un-init'd data) */
|
2020-04-04 22:08:13 +02:00
|
|
|
|
2020-09-06 19:26:37 +02:00
|
|
|
data->block_size = 0x10 + track_size;
|
2020-04-04 22:08:13 +02:00
|
|
|
data->data_size = 0;
|
|
|
|
data->skip_size = 0;
|
|
|
|
|
2020-09-06 19:26:37 +02:00
|
|
|
if (track_number == data->cfg.track_number) {
|
|
|
|
data->data_size = track_size;
|
2020-04-04 22:08:13 +02:00
|
|
|
data->skip_size = 0x10;
|
|
|
|
}
|
2020-09-06 19:26:37 +02:00
|
|
|
|
|
|
|
data->chunk_size -= data->block_size;
|
2020-04-04 22:08:13 +02:00
|
|
|
}
|
|
|
|
else {
|
2020-09-06 19:26:37 +02:00
|
|
|
/* base block header */
|
|
|
|
uint32_t block_type = read_u32(data->physical_offset + 0x00, sf);
|
|
|
|
uint32_t block_size = read_u32(data->physical_offset + 0x04, sf);
|
|
|
|
/* 0x08: dummy */
|
|
|
|
/* 0x0c: dummy */
|
|
|
|
|
|
|
|
/* blocks are padded after all sub-blocks */
|
|
|
|
if (block_size % 0x10) {
|
|
|
|
block_size = block_size + 0x10 - (block_size % 0x10);
|
|
|
|
}
|
|
|
|
|
2020-04-04 22:08:13 +02:00
|
|
|
data->data_size = 0;
|
|
|
|
data->skip_size = 0;
|
2020-09-06 19:26:37 +02:00
|
|
|
|
|
|
|
if (block_type == 0x00 && block_size != 0) {
|
|
|
|
/* audio block */
|
|
|
|
data->block_size = 0x10;
|
|
|
|
data->chunk_size = block_size;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* non-audio block (or empty audio block) */
|
|
|
|
data->block_size = block_size + 0x10;
|
|
|
|
}
|
2020-04-04 22:08:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Deinterleaves MUL streams */
|
2020-09-06 19:26:37 +02:00
|
|
|
static STREAMFILE* setup_mul_streamfile(STREAMFILE* sf, off_t offset, int big_endian, int track_number, int track_count, const char* extension) {
|
2020-04-04 22:08:13 +02:00
|
|
|
STREAMFILE *new_sf = NULL;
|
|
|
|
deblock_config_t cfg = {0};
|
|
|
|
|
2020-09-06 19:26:37 +02:00
|
|
|
cfg.stream_start = offset;
|
2020-04-04 22:08:13 +02:00
|
|
|
cfg.big_endian = big_endian;
|
|
|
|
cfg.track_number = track_number;
|
|
|
|
cfg.track_count = track_count;
|
|
|
|
cfg.block_callback = block_callback;
|
|
|
|
|
|
|
|
new_sf = open_wrap_streamfile(sf);
|
|
|
|
new_sf = open_io_deblock_streamfile_f(new_sf, &cfg);
|
2020-09-06 19:26:37 +02:00
|
|
|
if (extension)
|
|
|
|
new_sf = open_fakename_streamfile_f(new_sf, NULL, extension);
|
2020-04-04 22:08:13 +02:00
|
|
|
return new_sf;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* _MUL_STREAMFILE_H_ */
|