diff --git a/src/meta/ubi_sb.c b/src/meta/ubi_sb.c index 3f8f4bd1..d06ea04d 100644 --- a/src/meta/ubi_sb.c +++ b/src/meta/ubi_sb.c @@ -29,7 +29,8 @@ typedef struct { off_t audio_stream_size; off_t audio_stream_offset; off_t audio_stream_type; - off_t audio_subblock_flag; + off_t audio_software_flag; + off_t audio_hwmodule_flag; off_t audio_streamed_flag; off_t audio_cd_streamed_flag; off_t audio_loop_flag; @@ -48,7 +49,8 @@ typedef struct { int audio_streamed_and; int audio_cd_streamed_and; int audio_loop_and; - int audio_subblock_and; + int audio_software_and; + int audio_hwmodule_and; int audio_loc_and; int audio_stereo_and; int audio_ram_streamed_and; @@ -1846,15 +1848,22 @@ static int parse_type_audio(ubi_sb_header* sb, off_t offset, STREAMFILE* sf) { sb->is_external = (int)!(read_32bit(offset + sb->cfg.audio_internal_flag, sf)); } - /* apparently, there may also be other subblocks based on various flags but they were not seen so far */ - if (sb->cfg.audio_subblock_flag && sb->cfg.audio_subblock_and) { - /* flag probably means "software decoded" */ - int subblock_flag = read_32bit(offset + sb->cfg.audio_subblock_flag, sf) & sb->cfg.audio_subblock_and; - sb->subblock_id = (!subblock_flag) ? 0 : 1; + if (sb->cfg.audio_software_flag && sb->cfg.audio_software_and) { + /* software decoded and hardware decoded sounds are stored in separate subblocks */ + int software_flag = read_32bit(offset + sb->cfg.audio_software_flag, sf) & sb->cfg.audio_software_and; + sb->subblock_id = (!software_flag) ? 0 : 1; + + if (sb->platform == UBI_PS2) { + /* flag appears to mean "load into IOP memory instead of SPU" */ + int hwmodule_flag = read_32bit(offset + sb->cfg.audio_hwmodule_flag, sf) & sb->cfg.audio_hwmodule_and; + sb->subblock_id = (!software_flag) ? ((!hwmodule_flag) ? 0 : 3) : 1; + } + + /* PC can have subblock 2 based on two fields near the end but it wasn't seen so far */ /* stream_type field is not used if the flag is not set (it even contains garbage in some versions) * except for PS3 which has two hardware codecs (PSX and AT3) */ - if (!subblock_flag && sb->platform != UBI_PS3) + if (!software_flag && sb->platform != UBI_PS3) sb->stream_type = 0x00; } else { sb->subblock_id = (sb->stream_type == 0x01) ? 0 : 1; @@ -2628,22 +2637,22 @@ static void config_sb_entry(ubi_sb_header* sb, size_t section1_size_entry, size_ sb->cfg.section2_entry_size = section2_size_entry; sb->cfg.section3_entry_size = 0x08; } -static void config_sb_audio_fs(ubi_sb_header* sb, off_t streamed_flag, off_t subblock_flag, off_t loop_flag) { +static void config_sb_audio_fs(ubi_sb_header* sb, off_t streamed_flag, off_t software_flag, off_t loop_flag) { /* audio header with standard flags */ sb->cfg.audio_streamed_flag = streamed_flag; - sb->cfg.audio_subblock_flag = subblock_flag; + sb->cfg.audio_software_flag = software_flag; sb->cfg.audio_loop_flag = loop_flag; sb->cfg.audio_streamed_and = 1; - sb->cfg.audio_subblock_and = 1; + sb->cfg.audio_software_and = 1; sb->cfg.audio_loop_and = 1; } -static void config_sb_audio_fb(ubi_sb_header* sb, off_t flag_bits, int streamed_and, int subblock_and, int loop_and) { +static void config_sb_audio_fb(ubi_sb_header* sb, off_t flag_bits, int streamed_and, int software_and, int loop_and) { /* audio header with bit flags */ sb->cfg.audio_streamed_flag = flag_bits; - sb->cfg.audio_subblock_flag = flag_bits; + sb->cfg.audio_software_flag = flag_bits; sb->cfg.audio_loop_flag = flag_bits; sb->cfg.audio_streamed_and = streamed_and; - sb->cfg.audio_subblock_and = subblock_and; + sb->cfg.audio_software_and = software_and; sb->cfg.audio_loop_and = loop_and; } static void config_sb_audio_hs(ubi_sb_header* sb, off_t channels, off_t sample_rate, off_t num_samples, off_t num_samples2, off_t stream_name, off_t stream_type) { @@ -2664,29 +2673,40 @@ static void config_sb_audio_he(ubi_sb_header* sb, off_t channels, off_t sample_r sb->cfg.audio_extra_name = extra_name; sb->cfg.audio_stream_type = stream_type; } +static void config_sb_audio_fb_ps2(ubi_sb_header* sb, off_t flag_bits, int streamed_and, int software_and, int loop_and, int hwmodule_and) { + /* audio header with bit flags */ + sb->cfg.audio_streamed_flag = flag_bits; + sb->cfg.audio_software_flag = flag_bits; + sb->cfg.audio_loop_flag = flag_bits; + sb->cfg.audio_hwmodule_flag = flag_bits; + sb->cfg.audio_streamed_and = streamed_and; + sb->cfg.audio_software_and = software_and; + sb->cfg.audio_loop_and = loop_and; + sb->cfg.audio_hwmodule_and = hwmodule_and; +} static void config_sb_audio_ps2_bnm(ubi_sb_header *sb, off_t flag_bits, int streamed_and, int cd_streamed_and, int loop_and, off_t channels, off_t sample_rate) { /* bit flags, channels and sample rate */ - sb->cfg.audio_streamed_flag = flag_bits; - sb->cfg.audio_cd_streamed_flag = flag_bits; - sb->cfg.audio_loop_flag = flag_bits; - sb->cfg.audio_streamed_and = streamed_and; - sb->cfg.audio_cd_streamed_and = cd_streamed_and; - sb->cfg.audio_loop_and = loop_and; - sb->cfg.audio_channels = channels; - sb->cfg.audio_sample_rate = sample_rate; + sb->cfg.audio_streamed_flag = flag_bits; + sb->cfg.audio_cd_streamed_flag = flag_bits; + sb->cfg.audio_loop_flag = flag_bits; + sb->cfg.audio_streamed_and = streamed_and; + sb->cfg.audio_cd_streamed_and = cd_streamed_and; + sb->cfg.audio_loop_and = loop_and; + sb->cfg.audio_channels = channels; + sb->cfg.audio_sample_rate = sample_rate; } static void config_sb_audio_ps2_old(ubi_sb_header *sb, off_t flag_bits, int streamed_and, int loop_and, int loc_and, int stereo_and, off_t pitch, off_t sample_rate) { /* bit flags, sample rate only */ - sb->cfg.audio_streamed_flag = flag_bits; - sb->cfg.audio_loop_flag = flag_bits; - sb->cfg.audio_loc_flag = flag_bits; - sb->cfg.audio_stereo_flag = flag_bits; - sb->cfg.audio_streamed_and = streamed_and; - sb->cfg.audio_loop_and = loop_and; - sb->cfg.audio_loc_and = loc_and; - sb->cfg.audio_stereo_and = stereo_and; - sb->cfg.audio_pitch = pitch; - sb->cfg.audio_sample_rate = sample_rate; + sb->cfg.audio_streamed_flag = flag_bits; + sb->cfg.audio_loop_flag = flag_bits; + sb->cfg.audio_loc_flag = flag_bits; + sb->cfg.audio_stereo_flag = flag_bits; + sb->cfg.audio_streamed_and = streamed_and; + sb->cfg.audio_loop_and = loop_and; + sb->cfg.audio_loc_and = loc_and; + sb->cfg.audio_stereo_and = stereo_and; + sb->cfg.audio_pitch = pitch; + sb->cfg.audio_sample_rate = sample_rate; } static void config_sb_sequence(ubi_sb_header* sb, off_t sequence_count, off_t entry_size) { /* sequence header and chain table */ @@ -3335,7 +3355,7 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { (sb->version == 0x0012000c && sb->platform == UBI_PS2)) { config_sb_entry(sb, 0x48, 0x6c); - config_sb_audio_fb(sb, 0x18, (1 << 2), (1 << 3), (1 << 4)); + config_sb_audio_fb_ps2(sb, 0x18, (1 << 2), (1 << 3), (1 << 4), (1 << 5)); config_sb_audio_hs(sb, 0x20, 0x24, 0x30, 0x38, 0x40, 0x68); /* num_samples may be null */ config_sb_sequence(sb, 0x28, 0x10); @@ -3352,7 +3372,7 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { if (sb->version == 0x000A0007 && sb->platform == UBI_PS2 && is_bia_ps2) { config_sb_entry(sb, 0x5c, 0x14c); - config_sb_audio_fb(sb, 0x18, (1 << 2), (1 << 3), (1 << 4)); + config_sb_audio_fb_ps2(sb, 0x18, (1 << 2), (1 << 3), (1 << 4), (1 << 5)); config_sb_audio_hs(sb, 0x20, 0x24, 0x30, 0x38, 0x40, 0x148); /* num_samples may be null */ config_sb_sequence(sb, 0x28, 0x10); @@ -3547,7 +3567,7 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { if (sb->version == 0x00130001 && sb->platform == UBI_PS2) { config_sb_entry(sb, 0x48, 0x4c); - config_sb_audio_fb(sb, 0x18, (1 << 2), (1 << 3), (1 << 4)); + config_sb_audio_fb_ps2(sb, 0x18, (1 << 2), (1 << 3), (1 << 4), (1 << 5)); config_sb_audio_he(sb, 0x20, 0x24, 0x30, 0x38, 0x40, 0x44); config_sb_sequence(sb, 0x28, 0x10); @@ -3589,7 +3609,7 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { if (sb->version == 0x00130004 && sb->platform == UBI_PS2) { config_sb_entry(sb, 0x48, 0x50); - config_sb_audio_fb(sb, 0x18, (1 << 2), (1 << 3), (1 << 4)); + config_sb_audio_fb_ps2(sb, 0x18, (1 << 2), (1 << 3), (1 << 4), (1 << 5)); config_sb_audio_he(sb, 0x20, 0x24, 0x30, 0x38, 0x40, 0x4c); sb->cfg.audio_interleave = 0x8000; @@ -3626,7 +3646,7 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { if (sb->version == 0x00150000 && sb->platform == UBI_PS2) { config_sb_entry(sb, 0x48, 0x5c); - config_sb_audio_fb(sb, 0x20, (1 << 2), (1 << 3), (1 << 4)); + config_sb_audio_fb_ps2(sb, 0x20, (1 << 2), (1 << 3), (1 << 4), (1 << 5)); config_sb_audio_he(sb, 0x2c, 0x30, 0x3c, 0x44, 0x4c, 0x50); config_sb_sequence(sb, 0x2c, 0x10); @@ -3683,7 +3703,7 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { (sb->version == 0x00180007 && sb->platform == UBI_PSP)) { config_sb_entry(sb, 0x48, 0x54); - config_sb_audio_fb(sb, 0x20, (1 << 2), (1 << 3), (1 << 4)); + config_sb_audio_fb_ps2(sb, 0x20, (1 << 2), (1 << 3), (1 << 4), (1 << 5)); config_sb_audio_he(sb, 0x28, 0x2c, 0x34, 0x3c, 0x44, 0x48); config_sb_sequence(sb, 0x2c, 0x10); @@ -3838,7 +3858,7 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { (sb->version == 0x00190005 && sb->platform == UBI_PSP)) { config_sb_entry(sb, 0x48, 0x58); - config_sb_audio_fb(sb, 0x20, (1 << 2), (1 << 3), (1 << 4)); /* assumed subblock_flag */ + config_sb_audio_fb(sb, 0x20, (1 << 2), (1 << 3), (1 << 4)); /* assumed software_flag */ config_sb_audio_he(sb, 0x28, 0x2c, 0x34, 0x3c, 0x44, 0x48); config_sb_sequence(sb, 0x2c, 0x10); @@ -3852,7 +3872,7 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { if (sb->version == 0x00190002 && sb->platform == UBI_PS2) { config_sb_entry(sb, 0x48, 0x5c); - config_sb_audio_fb(sb, 0x20, (1 << 2), (1 << 3), (1 << 4)); /* assumed subblock_flag */ + config_sb_audio_fb_ps2(sb, 0x20, (1 << 2), (1 << 3), (1 << 4), (1 << 5)); /* assumed software_flag */ config_sb_audio_he(sb, 0x28, 0x2c, 0x34, 0x3c, 0x44, 0x48); config_sb_sequence(sb, 0x2c, 0x10); @@ -3975,7 +3995,7 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { if (sb->version == 0x001D0000 && sb->platform == UBI_PSP) { config_sb_entry(sb, 0x40, 0x60); - config_sb_audio_fb(sb, 0x20, (1 << 2), (1 << 3), (1 << 5)); /* assumed subblock_flag */ + config_sb_audio_fb(sb, 0x20, (1 << 2), (1 << 3), (1 << 5)); /* assumed software_flag */ config_sb_audio_he(sb, 0x28, 0x30, 0x38, 0x40, 0x48, 0x4c); return 1; }