Updated VGMStream to r1810-97-g408cada5

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
main
Christopher Snowhill 2023-02-04 23:45:54 -08:00
parent 66338e2c83
commit d5720e3944
No known key found for this signature in database
112 changed files with 3219 additions and 3665 deletions

View File

@ -386,45 +386,45 @@
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"HAVE_CONFIG_H=1",
"alg_quant=alg_quant",
"alg_unquant=alg_unquant",
"celt_decode=celt_0061_decode",
"celt_decoder_create=celt_0061_decoder_create",
"celt_decoder_create_custom=celt_0061_decoder_create_custom",
"celt_decoder_destroy=celt_0061_decoder_destroy",
"celt_mode_create=celt_0061_mode_create",
"celt_mode_destroy=celt_0061_mode_destroy",
"celt_mode_info=celt_0061_mode_info",
"celt_encoder_destroy=celt_0061_encoder_destroy",
"celt_encoder_create=celt_0061_encoder_create",
"celt_encode=celt_0061_encode",
"celt_encode_float=celt_0061_encode_float",
"celt_encoder_ctl=celt_0061_encoder_ctl",
"celt_decode_float=celt_0061_decode_float",
"celt_decoder_ctl=celt_0061_decoder_ctl",
"compute_allocation=compute_0061_allocation",
"compute_band_energies=compute_0061_band_energies",
"denormalise_bands=denormalise_0061_bands",
"ec_dec_init=ec_0061_dec_init",
"ec_decode=ec_0061_decode",
"ec_decode_bin=ec_0061_decode_bin",
"ec_dec_update=ec_0061_dec_update",
"ec_dec_uint=ec_0061_dec_uint",
"ec_dec_bits=ec_0061_dec_bits",
"ec_enc_init=ec_0061_enc_init",
"ec_encode=ec_0061_encode",
"ec_encode_bin=ec_0061_encode_bin",
"ec_enc_uint=ec_0061_enc_uint",
"ec_enc_bits=ec_0061_enc_bits",
"ec_enc_done=ec_0061_enc_done",
"normalise_bands=normalise_0061_bands",
"renormalise_vector=renormalise_0061_vector",
"quant_coarse_energy=quant_0061_coarse_energy",
"quant_fine_energy=quant_0061_fine_energy",
"quant_energy_finalise=quant_0061_energy_finalise",
"unquant_coarse_energy=unquant_0061_coarse_energy",
"unquant_energy_finalise=unquant_0061_energy_finalise",
"unquant_fine_energy=unquant_0061_fine_energy",
"alg_quant=alg_quant_0061",
"alg_unquant=alg_unquant_0061",
"celt_decode=celt_decode_0061",
"celt_decoder_create=celt_decoder_create_0061",
"celt_decoder_create_custom=celt_decoder_create_custom_0061",
"celt_decoder_destroy=celt_decoder_destroy_0061",
"celt_mode_create=celt_mode_create_0061",
"celt_mode_destroy=celt_mode_destroy_0061",
"celt_mode_info=celt_mode_info_0061",
"celt_encoder_destroy=celt_encoder_destroy_0061",
"celt_encoder_create=celt_encoder_create_0061",
"celt_encode=celt_encode_0061",
"celt_encode_float=celt_encode_float_0061",
"celt_encoder_ctl=celt_encoder_ctl_0061",
"celt_decode_float=celt_decode_float_0061",
"celt_decoder_ctl=celt_decoder_ctl_0061",
"compute_allocation=compute_allocation_0061",
"compute_band_energies=compute_band_energies_0061",
"denormalise_bands=denormalise_bands_0061",
"ec_dec_init=ec_dec_init_0061",
"ec_decode=ec_decode_0061",
"ec_decode_bin=ec_decode_bin_0061",
"ec_dec_update=ec_dec_update_0061",
"ec_dec_uint=ec_dec_uint_0061",
"ec_dec_bits=ec_dec_bits_0061",
"ec_enc_init=ec_enc_init_0061",
"ec_encode=ec_encode_0061",
"ec_encode_bin=ec_encode_bin_0061",
"ec_enc_uint=ec_enc_uint_0061",
"ec_enc_bits=ec_enc_bits_0061",
"ec_enc_done=ec_enc_done_0061",
"normalise_bands=normalise_bands_0061",
"renormalise_vector=renormalise_vector_0061",
"quant_coarse_energy=quant_coarse_energy_0061",
"quant_fine_energy=quant_fine_energy_0061",
"quant_energy_finalise=quant_energy_finalise_0061",
"unquant_coarse_energy=unquant_coarse_energy_0061",
"unquant_energy_finalise=unquant_energy_finalise_0061",
"unquant_fine_energy=unquant_fine_energy_0061",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
@ -487,45 +487,45 @@
GCC_NO_COMMON_BLOCKS = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
"HAVE_CONFIG_H=1",
"alg_quant=alg_quant",
"alg_unquant=alg_unquant",
"celt_decode=celt_0061_decode",
"celt_decoder_create=celt_0061_decoder_create",
"celt_decoder_create_custom=celt_0061_decoder_create_custom",
"celt_decoder_destroy=celt_0061_decoder_destroy",
"celt_mode_create=celt_0061_mode_create",
"celt_mode_destroy=celt_0061_mode_destroy",
"celt_mode_info=celt_0061_mode_info",
"celt_encoder_destroy=celt_0061_encoder_destroy",
"celt_encoder_create=celt_0061_encoder_create",
"celt_encode=celt_0061_encode",
"celt_encode_float=celt_0061_encode_float",
"celt_encoder_ctl=celt_0061_encoder_ctl",
"celt_decode_float=celt_0061_decode_float",
"celt_decoder_ctl=celt_0061_decoder_ctl",
"compute_allocation=compute_0061_allocation",
"compute_band_energies=compute_0061_band_energies",
"denormalise_bands=denormalise_0061_bands",
"ec_dec_init=ec_0061_dec_init",
"ec_decode=ec_0061_decode",
"ec_decode_bin=ec_0061_decode_bin",
"ec_dec_update=ec_0061_dec_update",
"ec_dec_uint=ec_0061_dec_uint",
"ec_dec_bits=ec_0061_dec_bits",
"ec_enc_init=ec_0061_enc_init",
"ec_encode=ec_0061_encode",
"ec_encode_bin=ec_0061_encode_bin",
"ec_enc_uint=ec_0061_enc_uint",
"ec_enc_bits=ec_0061_enc_bits",
"ec_enc_done=ec_0061_enc_done",
"normalise_bands=normalise_0061_bands",
"renormalise_vector=renormalise_0061_vector",
"quant_coarse_energy=quant_0061_coarse_energy",
"quant_fine_energy=quant_0061_fine_energy",
"quant_energy_finalise=quant_0061_energy_finalise",
"unquant_coarse_energy=unquant_0061_coarse_energy",
"unquant_energy_finalise=unquant_0061_energy_finalise",
"unquant_fine_energy=unquant_0061_fine_energy",
"alg_quant=alg_quant_0061",
"alg_unquant=alg_unquant_0061",
"celt_decode=celt_decode_0061",
"celt_decoder_create=celt_decoder_create_0061",
"celt_decoder_create_custom=celt_decoder_create_custom_0061",
"celt_decoder_destroy=celt_decoder_destroy_0061",
"celt_mode_create=celt_mode_create_0061",
"celt_mode_destroy=celt_mode_destroy_0061",
"celt_mode_info=celt_mode_info_0061",
"celt_encoder_destroy=celt_encoder_destroy_0061",
"celt_encoder_create=celt_encoder_create_0061",
"celt_encode=celt_encode_0061",
"celt_encode_float=celt_encode_float_0061",
"celt_encoder_ctl=celt_encoder_ctl_0061",
"celt_decode_float=celt_decode_float_0061",
"celt_decoder_ctl=celt_decoder_ctl_0061",
"compute_allocation=compute_allocation_0061",
"compute_band_energies=compute_band_energies_0061",
"denormalise_bands=denormalise_bands_0061",
"ec_dec_init=ec_dec_init_0061",
"ec_decode=ec_decode_0061",
"ec_decode_bin=ec_decode_bin_0061",
"ec_dec_update=ec_dec_update_0061",
"ec_dec_uint=ec_dec_uint_0061",
"ec_dec_bits=ec_dec_bits_0061",
"ec_enc_init=ec_enc_init_0061",
"ec_encode=ec_encode_0061",
"ec_encode_bin=ec_encode_bin_0061",
"ec_enc_uint=ec_enc_uint_0061",
"ec_enc_bits=ec_enc_bits_0061",
"ec_enc_done=ec_enc_done_0061",
"normalise_bands=normalise_bands_0061",
"renormalise_vector=renormalise_vector_0061",
"quant_coarse_energy=quant_coarse_energy_0061",
"quant_fine_energy=quant_fine_energy_0061",
"quant_energy_finalise=quant_energy_finalise_0061",
"unquant_coarse_energy=unquant_coarse_energy_0061",
"unquant_energy_finalise=unquant_energy_finalise_0061",
"unquant_fine_energy=unquant_fine_energy_0061",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;

View File

@ -374,45 +374,45 @@
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"HAVE_CONFIG_H=1",
"alg_quant=alg_quant",
"alg_unquant=alg_unquant",
"celt_decode=celt_0110_decode",
"celt_decoder_create=celt_0110_decoder_create",
"celt_decoder_create_custom=celt_0110_decoder_create_custom",
"celt_decoder_destroy=celt_0110_decoder_destroy",
"celt_mode_create=celt_0110_mode_create",
"celt_mode_destroy=celt_0110_mode_destroy",
"celt_mode_info=celt_0110_mode_info",
"celt_encoder_destroy=celt_0110_encoder_destroy",
"celt_encoder_create=celt_0110_encoder_create",
"celt_encode=celt_0110_encode",
"celt_encode_float=celt_0110_encode_float",
"celt_encoder_ctl=celt_0110_encoder_ctl",
"celt_decode_float=celt_0110_decode_float",
"celt_decoder_ctl=celt_0110_decoder_ctl",
"compute_allocation=compute_0110_allocation",
"compute_band_energies=compute_0110_band_energies",
"denormalise_bands=denormalise_0110_bands",
"ec_dec_init=ec_0110_dec_init",
"ec_decode=ec_0110_decode",
"ec_decode_bin=ec_0110_decode_bin",
"ec_dec_update=ec_0110_dec_update",
"ec_dec_uint=ec_0110_dec_uint",
"ec_dec_bits=ec_0110_dec_bits",
"ec_enc_init=ec_0110_enc_init",
"ec_encode=ec_0110_encode",
"ec_encode_bin=ec_0110_encode_bin",
"ec_enc_uint=ec_0110_enc_uint",
"ec_enc_bits=ec_0110_enc_bits",
"ec_enc_done=ec_0110_enc_done",
"normalise_bands=normalise_0110_bands",
"renormalise_vector=renormalise_0110_vector",
"quant_coarse_energy=quant_0110_coarse_energy",
"quant_fine_energy=quant_0110_fine_energy",
"quant_energy_finalise=quant_0110_energy_finalise",
"unquant_coarse_energy=unquant_0110_coarse_energy",
"unquant_energy_finalise=unquant_0110_energy_finalise",
"unquant_fine_energy=unquant_0110_fine_energy",
"alg_quant=alg_quant_0110",
"alg_unquant=alg_unquant_0110",
"celt_decode=celt_decode_0110",
"celt_decoder_create=celt_decoder_create_0110",
"celt_decoder_create_custom=celt_decoder_create_custom_0110",
"celt_decoder_destroy=celt_decoder_destroy_0110",
"celt_mode_create=celt_mode_create_0110",
"celt_mode_destroy=celt_mode_destroy_0110",
"celt_mode_info=celt_mode_info_0110",
"celt_encoder_destroy=celt_encoder_destroy_0110",
"celt_encoder_create=celt_encoder_create_0110",
"celt_encode=celt_encode_0110",
"celt_encode_float=celt_encode_float_0110",
"celt_encoder_ctl=celt_encoder_ctl_0110",
"celt_decode_float=celt_decode_float_0110",
"celt_decoder_ctl=celt_decoder_ctl_0110",
"compute_allocation=compute_allocation_0110",
"compute_band_energies=compute_band_energies_0110",
"denormalise_bands=denormalise_bands_0110",
"ec_dec_init=ec_dec_init_0110",
"ec_decode=ec_decode_0110",
"ec_decode_bin=ec_decode_bin_0110",
"ec_dec_update=ec_dec_update_0110",
"ec_dec_uint=ec_dec_uint_0110",
"ec_dec_bits=ec_dec_bits_0110",
"ec_enc_init=ec_enc_init_0110",
"ec_encode=ec_encode_0110",
"ec_encode_bin=ec_encode_bin_0110",
"ec_enc_uint=ec_enc_uint_0110",
"ec_enc_bits=ec_enc_bits_0110",
"ec_enc_done=ec_enc_done_0110",
"normalise_bands=normalise_bands_0110",
"renormalise_vector=renormalise_vector_0110",
"quant_coarse_energy=quant_coarse_energy_0110",
"quant_fine_energy=quant_fine_energy_0110",
"quant_energy_finalise=quant_energy_finalise_0110",
"unquant_coarse_energy=unquant_coarse_energy_0110",
"unquant_energy_finalise=unquant_energy_finalise_0110",
"unquant_fine_energy=unquant_fine_energy_0110",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
@ -475,45 +475,45 @@
GCC_NO_COMMON_BLOCKS = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
"HAVE_CONFIG_H=1",
"alg_quant=alg_quant",
"alg_unquant=alg_unquant",
"celt_decode=celt_0110_decode",
"celt_decoder_create=celt_0110_decoder_create",
"celt_decoder_create_custom=celt_0110_decoder_create_custom",
"celt_decoder_destroy=celt_0110_decoder_destroy",
"celt_mode_create=celt_0110_mode_create",
"celt_mode_destroy=celt_0110_mode_destroy",
"celt_mode_info=celt_0110_mode_info",
"celt_encoder_destroy=celt_0110_encoder_destroy",
"celt_encoder_create=celt_0110_encoder_create",
"celt_encode=celt_0110_encode",
"celt_encode_float=celt_0110_encode_float",
"celt_encoder_ctl=celt_0110_encoder_ctl",
"celt_decode_float=celt_0110_decode_float",
"celt_decoder_ctl=celt_0110_decoder_ctl",
"compute_allocation=compute_0110_allocation",
"compute_band_energies=compute_0110_band_energies",
"denormalise_bands=denormalise_0110_bands",
"ec_dec_init=ec_0110_dec_init",
"ec_decode=ec_0110_decode",
"ec_decode_bin=ec_0110_decode_bin",
"ec_dec_update=ec_0110_dec_update",
"ec_dec_uint=ec_0110_dec_uint",
"ec_dec_bits=ec_0110_dec_bits",
"ec_enc_init=ec_0110_enc_init",
"ec_encode=ec_0110_encode",
"ec_encode_bin=ec_0110_encode_bin",
"ec_enc_uint=ec_0110_enc_uint",
"ec_enc_bits=ec_0110_enc_bits",
"ec_enc_done=ec_0110_enc_done",
"normalise_bands=normalise_0110_bands",
"renormalise_vector=renormalise_0110_vector",
"quant_coarse_energy=quant_0110_coarse_energy",
"quant_fine_energy=quant_0110_fine_energy",
"quant_energy_finalise=quant_0110_energy_finalise",
"unquant_coarse_energy=unquant_0110_coarse_energy",
"unquant_energy_finalise=unquant_0110_energy_finalise",
"unquant_fine_energy=unquant_0110_fine_energy",
"alg_quant=alg_quant_0110",
"alg_unquant=alg_unquant_0110",
"celt_decode=celt_decode_0110",
"celt_decoder_create=celt_decoder_create_0110",
"celt_decoder_create_custom=celt_decoder_create_custom_0110",
"celt_decoder_destroy=celt_decoder_destroy_0110",
"celt_mode_create=celt_mode_create_0110",
"celt_mode_destroy=celt_mode_destroy_0110",
"celt_mode_info=celt_mode_info_0110",
"celt_encoder_destroy=celt_encoder_destroy_0110",
"celt_encoder_create=celt_encoder_create_0110",
"celt_encode=celt_encode_0110",
"celt_encode_float=celt_encode_float_0110",
"celt_encoder_ctl=celt_encoder_ctl_0110",
"celt_decode_float=celt_decode_float_0110",
"celt_decoder_ctl=celt_decoder_ctl_0110",
"compute_allocation=compute_allocation_0110",
"compute_band_energies=compute_band_energies_0110",
"denormalise_bands=denormalise_bands_0110",
"ec_dec_init=ec_dec_init_0110",
"ec_decode=ec_decode_0110",
"ec_decode_bin=ec_decode_bin_0110",
"ec_dec_update=ec_dec_update_0110",
"ec_dec_uint=ec_dec_uint_0110",
"ec_dec_bits=ec_dec_bits_0110",
"ec_enc_init=ec_enc_init_0110",
"ec_encode=ec_encode_0110",
"ec_encode_bin=ec_encode_bin_0110",
"ec_enc_uint=ec_enc_uint_0110",
"ec_enc_bits=ec_enc_bits_0110",
"ec_enc_done=ec_enc_done_0110",
"normalise_bands=normalise_bands_0110",
"renormalise_vector=renormalise_vector_0110",
"quant_coarse_energy=quant_coarse_energy_0110",
"quant_fine_energy=quant_fine_energy_0110",
"quant_energy_finalise=quant_energy_finalise_0110",
"unquant_coarse_energy=unquant_coarse_energy_0110",
"unquant_energy_finalise=unquant_energy_finalise_0110",
"unquant_fine_energy=unquant_fine_energy_0110",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;

View File

@ -25,7 +25,6 @@
83031EDC243C510500C3F3E0 /* vid1.c in Sources */ = {isa = PBXBuildFile; fileRef = 83031ED7243C510400C3F3E0 /* vid1.c */; };
83031EDD243C510500C3F3E0 /* xnb_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 83031ED8243C510500C3F3E0 /* xnb_streamfile.h */; };
830595D8277EEAA500EBFAAE /* ffmpeg_decoder_custom_mp4.c in Sources */ = {isa = PBXBuildFile; fileRef = 830595D7277EEAA500EBFAAE /* ffmpeg_decoder_custom_mp4.c */; };
8306B08420984518000302D4 /* at3plus_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B08120984517000302D4 /* at3plus_decoder.c */; };
8306B08520984518000302D4 /* yamaha_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B08220984517000302D4 /* yamaha_decoder.c */; };
8306B08620984518000302D4 /* fadpcm_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B08320984517000302D4 /* fadpcm_decoder.c */; };
8306B0A220984552000302D4 /* blocked_bdsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B0872098454C000302D4 /* blocked_bdsp.c */; };
@ -45,7 +44,6 @@
8306B0B120984552000302D4 /* blocked_halpst.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B0962098454F000302D4 /* blocked_halpst.c */; };
8306B0B220984552000302D4 /* blocked_mxch.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B0972098454F000302D4 /* blocked_mxch.c */; };
8306B0B320984552000302D4 /* blocked_thp.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B09820984550000302D4 /* blocked_thp.c */; };
8306B0B420984552000302D4 /* blocked_tra.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B09920984550000302D4 /* blocked_tra.c */; };
8306B0B620984552000302D4 /* blocked_hwas.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B09B20984550000302D4 /* blocked_hwas.c */; };
8306B0B720984552000302D4 /* blocked_str_snds.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B09C20984550000302D4 /* blocked_str_snds.c */; };
8306B0B820984552000302D4 /* blocked_ws_aud.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B09D20984551000302D4 /* blocked_ws_aud.c */; };
@ -99,8 +97,8 @@
831BA61B1EAC61A500CF89B0 /* sgxd.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6111EAC61A500CF89B0 /* sgxd.c */; };
831BA61C1EAC61A500CF89B0 /* sxd.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6121EAC61A500CF89B0 /* sxd.c */; };
831BA61D1EAC61A500CF89B0 /* ubi_raki.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6131EAC61A500CF89B0 /* ubi_raki.c */; };
831BA61F1EAC61A500CF89B0 /* x360_cxs.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6151EAC61A500CF89B0 /* x360_cxs.c */; };
831BA6211EAC61A500CF89B0 /* x360_pasx.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6171EAC61A500CF89B0 /* x360_pasx.c */; };
831BA61F1EAC61A500CF89B0 /* cxs.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6151EAC61A500CF89B0 /* cxs.c */; };
831BA6211EAC61A500CF89B0 /* pasx.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6171EAC61A500CF89B0 /* pasx.c */; };
831BA6281EAC61CB00CF89B0 /* coding_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6221EAC61CB00CF89B0 /* coding_utils.c */; };
8322ECE7240268BB009E9429 /* raw_al.c in Sources */ = {isa = PBXBuildFile; fileRef = 8322ECE6240268BA009E9429 /* raw_al.c */; };
832389501D2246C300482226 /* hca.c in Sources */ = {isa = PBXBuildFile; fileRef = 8323894F1D2246C300482226 /* hca.c */; };
@ -293,6 +291,11 @@
835C883722CC17BE001B4B3F /* ogg_vorbis_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 835C883522CC17BE001B4B3F /* ogg_vorbis_streamfile.h */; };
836C052B23F62F1A00FA07C7 /* libatrac9.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 835FC6C623F62AEF006960FA /* libatrac9.framework */; };
836C052C23F62F3100FA07C7 /* libatrac9.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 835FC6C623F62AEF006960FA /* libatrac9.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
836DF622298F83F400CD0580 /* cri_keys.h in Headers */ = {isa = PBXBuildFile; fileRef = 836DF61F298F83F400CD0580 /* cri_keys.h */; };
836DF623298F83F400CD0580 /* bitstream_msb.h in Headers */ = {isa = PBXBuildFile; fileRef = 836DF620298F83F400CD0580 /* bitstream_msb.h */; };
836DF624298F83F400CD0580 /* cri_keys.c in Sources */ = {isa = PBXBuildFile; fileRef = 836DF621298F83F400CD0580 /* cri_keys.c */; };
836DF627298F864100CD0580 /* cps.c in Sources */ = {isa = PBXBuildFile; fileRef = 836DF625298F864100CD0580 /* cps.c */; };
836DF628298F864100CD0580 /* ahx_keys.h in Headers */ = {isa = PBXBuildFile; fileRef = 836DF626298F864100CD0580 /* ahx_keys.h */; };
836EF0DB27BB975900BF35B2 /* libvorbis.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 836EF0D027BB960A00BF35B2 /* libvorbis.0.dylib */; };
836EF0DD27BB97C500BF35B2 /* libvorbisfile.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 836EF0DC27BB97BA00BF35B2 /* libvorbisfile.3.dylib */; };
836F46AE28208735005B9B87 /* blocked_tt_ad.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F46AD28208735005B9B87 /* blocked_tt_ad.c */; };
@ -380,7 +383,7 @@
836F6FA018BDC2190095E648 /* musx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6418BDC2180095E648 /* musx.c */; };
836F6FA118BDC2190095E648 /* myspd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6518BDC2180095E648 /* myspd.c */; };
836F6FA218BDC2190095E648 /* naomi_adpcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6618BDC2180095E648 /* naomi_adpcm.c */; };
836F6FA318BDC2190095E648 /* naomi_spsd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6718BDC2180095E648 /* naomi_spsd.c */; };
836F6FA318BDC2190095E648 /* spsd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6718BDC2180095E648 /* spsd.c */; };
836F6FA418BDC2190095E648 /* nds_hwas.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6818BDC2180095E648 /* nds_hwas.c */; };
836F6FA518BDC2190095E648 /* nds_rrds.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6918BDC2180095E648 /* nds_rrds.c */; };
836F6FA718BDC2190095E648 /* nds_strm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6B18BDC2180095E648 /* nds_strm.c */; };
@ -411,7 +414,6 @@
836F6FD018BDC2190095E648 /* ps2_b1s.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9418BDC2180095E648 /* ps2_b1s.c */; };
836F6FD118BDC2190095E648 /* ps2_bg00.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9518BDC2180095E648 /* ps2_bg00.c */; };
836F6FD218BDC2190095E648 /* ps2_bmdx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9618BDC2180095E648 /* ps2_bmdx.c */; };
836F6FD318BDC2190095E648 /* ps2_ccc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9718BDC2180095E648 /* ps2_ccc.c */; };
836F6FD418BDC2190095E648 /* hxd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9818BDC2180095E648 /* hxd.c */; };
836F6FD518BDC2190095E648 /* ps2_enth.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9918BDC2180095E648 /* ps2_enth.c */; };
836F6FD718BDC2190095E648 /* ps2_filp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9B18BDC2180095E648 /* ps2_filp.c */; };
@ -452,7 +454,6 @@
836F700D18BDC2190095E648 /* ps2_wmus.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED118BDC2190095E648 /* ps2_wmus.c */; };
836F700E18BDC2190095E648 /* ps2_xa2.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED218BDC2190095E648 /* ps2_xa2.c */; };
836F700F18BDC2190095E648 /* ps2_xa30.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED318BDC2190095E648 /* ps2_xa30.c */; };
836F701118BDC2190095E648 /* ps3_cps.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED518BDC2190095E648 /* ps3_cps.c */; };
836F701518BDC2190095E648 /* ps3_past.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED918BDC2190095E648 /* ps3_past.c */; };
836F701E18BDC2190095E648 /* redspark.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE218BDC2190095E648 /* redspark.c */; };
836F701F18BDC2190095E648 /* riff.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE318BDC2190095E648 /* riff.c */; };
@ -490,7 +491,6 @@
836F704318BDC2190095E648 /* wpd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0718BDC2190095E648 /* wpd.c */; };
836F704418BDC2190095E648 /* ws_aud.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0818BDC2190095E648 /* ws_aud.c */; };
836F704518BDC2190095E648 /* wvs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0918BDC2190095E648 /* wvs.c */; };
836F704618BDC2190095E648 /* x360_tra.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0A18BDC2190095E648 /* x360_tra.c */; };
836F704818BDC2190095E648 /* xbox_ims.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0C18BDC2190095E648 /* xbox_ims.c */; };
836F704E18BDC2190095E648 /* xss.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1218BDC2190095E648 /* xss.c */; };
836F704F18BDC2190095E648 /* xwb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1318BDC2190095E648 /* xwb.c */; };
@ -504,10 +504,10 @@
836F705718BDC2190095E648 /* util.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F6F1B18BDC2190095E648 /* util.h */; settings = {ATTRIBUTES = (Public, ); }; };
836F705818BDC2190095E648 /* vgmstream.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1C18BDC2190095E648 /* vgmstream.c */; };
836F705918BDC2190095E648 /* vgmstream.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F6F1D18BDC2190095E648 /* vgmstream.h */; settings = {ATTRIBUTES = (Public, ); }; };
83709E051ECBC1A4005C03D3 /* gtd.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709DFF1ECBC1A4005C03D3 /* gtd.c */; };
83709E051ECBC1A4005C03D3 /* ghs.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709DFF1ECBC1A4005C03D3 /* ghs.c */; };
83709E061ECBC1A4005C03D3 /* mc3.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E001ECBC1A4005C03D3 /* mc3.c */; };
83709E071ECBC1A4005C03D3 /* mss.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E011ECBC1A4005C03D3 /* mss.c */; };
83709E091ECBC1A4005C03D3 /* ta_aac.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E031ECBC1A4005C03D3 /* ta_aac.c */; };
83709E091ECBC1A4005C03D3 /* aac_triace.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E031ECBC1A4005C03D3 /* aac_triace.c */; };
83709E0D1ECBC1C3005C03D3 /* mc3_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E0B1ECBC1C3005C03D3 /* mc3_decoder.c */; };
83709E0E1ECBC1C3005C03D3 /* psv_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E0C1ECBC1C3005C03D3 /* psv_decoder.c */; };
8373341623F60C7B00DE14DC /* g7221_decoder_aes.h in Headers */ = {isa = PBXBuildFile; fileRef = 8373340E23F60C7A00DE14DC /* g7221_decoder_aes.h */; };
@ -541,7 +541,7 @@
837CEAF423487F2C00E62A4A /* xa_xa30.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEADF23487F2A00E62A4A /* xa_xa30.c */; };
837CEAF523487F2C00E62A4A /* ubi_hx.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEAE023487F2A00E62A4A /* ubi_hx.c */; };
837CEAF723487F2C00E62A4A /* nub.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEAE223487F2A00E62A4A /* nub.c */; };
837CEAF823487F2C00E62A4A /* xmv_valve.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEAE323487F2A00E62A4A /* xmv_valve.c */; };
837CEAF823487F2C00E62A4A /* xwv_valve.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEAE323487F2A00E62A4A /* xwv_valve.c */; };
837CEAF923487F2C00E62A4A /* xavs.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEAE423487F2A00E62A4A /* xavs.c */; };
837CEAFA23487F2C00E62A4A /* xa_04sw.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEAE523487F2B00E62A4A /* xa_04sw.c */; };
837CEAFB23487F2C00E62A4A /* ima.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEAE623487F2B00E62A4A /* ima.c */; };
@ -608,13 +608,12 @@
83A21F8C201D8982000F04B9 /* kma9.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A21F83201D8981000F04B9 /* kma9.c */; };
83A21F8D201D8982000F04B9 /* sqex_sead.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A21F84201D8981000F04B9 /* sqex_sead.c */; };
83A3F0741E3AD8B900D6A794 /* formats.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A3F0711E3AD8B900D6A794 /* formats.c */; };
83A3F0761E3AD8B900D6A794 /* stack_alloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A3F0731E3AD8B900D6A794 /* stack_alloc.h */; };
83A5F75F198DF021009AF94C /* bfwav.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A5F75E198DF021009AF94C /* bfwav.c */; };
83A8BADD256679C5000F5F3F /* wady_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A8BADC256679C5000F5F3F /* wady_decoder.c */; };
83A8BADF256679E3000F5F3F /* blocked_xwav.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A8BADE256679E3000F5F3F /* blocked_xwav.c */; };
83A8BAE525667AA8000F5F3F /* wady.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A8BAE025667AA7000F5F3F /* wady.c */; };
83A8BAE625667AA8000F5F3F /* ps2_enth_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A8BAE125667AA7000F5F3F /* ps2_enth_streamfile.h */; };
83A8BAE725667AA8000F5F3F /* xse.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A8BAE225667AA7000F5F3F /* xse.c */; };
83A8BAE725667AA8000F5F3F /* sdrh.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A8BAE225667AA7000F5F3F /* sdrh.c */; };
83A8BAE825667AA8000F5F3F /* xwav.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A8BAE325667AA7000F5F3F /* xwav.c */; };
83A8BAE925667AA8000F5F3F /* cpk.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A8BAE425667AA7000F5F3F /* cpk.c */; };
83AA5D161F6E2F600020821C /* ea_xa_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D0E1F6E2F5F0020821C /* ea_xa_decoder.c */; };
@ -631,7 +630,6 @@
83AA7D19279EBD0B00087AA4 /* libavutil.57.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 83AA7D16279EBCF900087AA4 /* libavutil.57.dylib */; };
83AA7D1A279EBD0D00087AA4 /* libswresample.4.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 83AA7D15279EBCF900087AA4 /* libswresample.4.dylib */; };
83AA7F722519BFEA004C5298 /* vorbis_bitreader.h in Headers */ = {isa = PBXBuildFile; fileRef = 83AA7F6D2519BFEA004C5298 /* vorbis_bitreader.h */; };
83AA7F732519BFEA004C5298 /* mpeg_bitreader.h in Headers */ = {isa = PBXBuildFile; fileRef = 83AA7F712519BFEA004C5298 /* mpeg_bitreader.h */; };
83AA7F7D2519C042004C5298 /* dsb.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA7F742519C041004C5298 /* dsb.c */; };
83AA7F7E2519C042004C5298 /* svag_kcet.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA7F752519C041004C5298 /* svag_kcet.c */; };
83AA7F7F2519C042004C5298 /* bsf.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA7F762519C042004C5298 /* bsf.c */; };
@ -645,7 +643,7 @@
83AA7F8B2519C076004C5298 /* render.h in Headers */ = {isa = PBXBuildFile; fileRef = 83AA7F872519C076004C5298 /* render.h */; };
83AA7F8C2519C076004C5298 /* render.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA7F882519C076004C5298 /* render.c */; };
83AA7F8D2519C076004C5298 /* decode.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA7F892519C076004C5298 /* decode.c */; };
83AB8C761E8072A100086084 /* x360_ast.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AB8C741E8072A100086084 /* x360_ast.c */; };
83AB8C761E8072A100086084 /* astb.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AB8C741E8072A100086084 /* astb.c */; };
83AF2CC926226BA500538240 /* gcub.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AF2CC526226BA400538240 /* gcub.c */; };
83AF2CCA26226BA500538240 /* exst.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AF2CC626226BA400538240 /* exst.c */; };
83AF2CCB26226BA500538240 /* ogv_3rdeye.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AF2CC726226BA400538240 /* ogv_3rdeye.c */; };
@ -653,7 +651,6 @@
83AFABBC23795202002F3947 /* xssb.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AFABB923795201002F3947 /* xssb.c */; };
83AFABBD23795202002F3947 /* ea_eaac_opus_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 83AFABBA23795202002F3947 /* ea_eaac_opus_streamfile.h */; };
83AFABBE23795202002F3947 /* isb.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AFABBB23795202002F3947 /* isb.c */; };
83B46FD12707FB2100847FC9 /* at3plus_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 83B46FCD2707FB2100847FC9 /* at3plus_decoder.h */; };
83B46FD52707FB9A00847FC9 /* endianness.h in Headers */ = {isa = PBXBuildFile; fileRef = 83B46FD42707FB9A00847FC9 /* endianness.h */; };
83B69B222845A26600D2435A /* bw_mp3_riff.c in Sources */ = {isa = PBXBuildFile; fileRef = 83B69B212845A26600D2435A /* bw_mp3_riff.c */; };
83B72E3A27904589006007A3 /* libfdk-aac.2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 83B72E342790452C006007A3 /* libfdk-aac.2.dylib */; };
@ -853,7 +850,6 @@
83031ED7243C510400C3F3E0 /* vid1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vid1.c; sourceTree = "<group>"; };
83031ED8243C510500C3F3E0 /* xnb_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xnb_streamfile.h; sourceTree = "<group>"; };
830595D7277EEAA500EBFAAE /* ffmpeg_decoder_custom_mp4.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffmpeg_decoder_custom_mp4.c; sourceTree = "<group>"; };
8306B08120984517000302D4 /* at3plus_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = at3plus_decoder.c; sourceTree = "<group>"; };
8306B08220984517000302D4 /* yamaha_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = yamaha_decoder.c; sourceTree = "<group>"; };
8306B08320984517000302D4 /* fadpcm_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fadpcm_decoder.c; sourceTree = "<group>"; };
8306B0872098454C000302D4 /* blocked_bdsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_bdsp.c; sourceTree = "<group>"; };
@ -873,7 +869,6 @@
8306B0962098454F000302D4 /* blocked_halpst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_halpst.c; sourceTree = "<group>"; };
8306B0972098454F000302D4 /* blocked_mxch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_mxch.c; sourceTree = "<group>"; };
8306B09820984550000302D4 /* blocked_thp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_thp.c; sourceTree = "<group>"; };
8306B09920984550000302D4 /* blocked_tra.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_tra.c; sourceTree = "<group>"; };
8306B09B20984550000302D4 /* blocked_hwas.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_hwas.c; sourceTree = "<group>"; };
8306B09C20984550000302D4 /* blocked_str_snds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_str_snds.c; sourceTree = "<group>"; };
8306B09D20984551000302D4 /* blocked_ws_aud.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_ws_aud.c; sourceTree = "<group>"; };
@ -927,8 +922,8 @@
831BA6111EAC61A500CF89B0 /* sgxd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sgxd.c; sourceTree = "<group>"; };
831BA6121EAC61A500CF89B0 /* sxd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sxd.c; sourceTree = "<group>"; };
831BA6131EAC61A500CF89B0 /* ubi_raki.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ubi_raki.c; sourceTree = "<group>"; };
831BA6151EAC61A500CF89B0 /* x360_cxs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x360_cxs.c; sourceTree = "<group>"; };
831BA6171EAC61A500CF89B0 /* x360_pasx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x360_pasx.c; sourceTree = "<group>"; };
831BA6151EAC61A500CF89B0 /* cxs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cxs.c; sourceTree = "<group>"; };
831BA6171EAC61A500CF89B0 /* pasx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pasx.c; sourceTree = "<group>"; };
831BA6221EAC61CB00CF89B0 /* coding_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = coding_utils.c; sourceTree = "<group>"; };
831BD11F1EEE1CF200198540 /* ngc_ulw.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ngc_ulw.c; sourceTree = "<group>"; };
8322ECE6240268BA009E9429 /* raw_al.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = raw_al.c; sourceTree = "<group>"; };
@ -1121,6 +1116,11 @@
835C883122CC17BD001B4B3F /* bwav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bwav.c; sourceTree = "<group>"; };
835C883522CC17BE001B4B3F /* ogg_vorbis_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ogg_vorbis_streamfile.h; sourceTree = "<group>"; };
835FC6C123F62AEE006960FA /* libatrac9.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libatrac9.xcodeproj; path = ../libatrac9/libatrac9.xcodeproj; sourceTree = "<group>"; };
836DF61F298F83F400CD0580 /* cri_keys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cri_keys.h; sourceTree = "<group>"; };
836DF620298F83F400CD0580 /* bitstream_msb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bitstream_msb.h; sourceTree = "<group>"; };
836DF621298F83F400CD0580 /* cri_keys.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cri_keys.c; sourceTree = "<group>"; };
836DF625298F864100CD0580 /* cps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cps.c; sourceTree = "<group>"; };
836DF626298F864100CD0580 /* ahx_keys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ahx_keys.h; sourceTree = "<group>"; };
836EF0D027BB960A00BF35B2 /* libvorbis.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libvorbis.0.dylib; path = ../../ThirdParty/vorbis/lib/libvorbis.0.dylib; sourceTree = "<group>"; };
836EF0DC27BB97BA00BF35B2 /* libvorbisfile.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libvorbisfile.3.dylib; path = ../../ThirdParty/vorbis/lib/libvorbisfile.3.dylib; sourceTree = "<group>"; };
836F46AD28208735005B9B87 /* blocked_tt_ad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_tt_ad.c; sourceTree = "<group>"; };
@ -1210,7 +1210,7 @@
836F6E6418BDC2180095E648 /* musx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = musx.c; sourceTree = "<group>"; };
836F6E6518BDC2180095E648 /* myspd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = myspd.c; sourceTree = "<group>"; };
836F6E6618BDC2180095E648 /* naomi_adpcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = naomi_adpcm.c; sourceTree = "<group>"; };
836F6E6718BDC2180095E648 /* naomi_spsd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = naomi_spsd.c; sourceTree = "<group>"; };
836F6E6718BDC2180095E648 /* spsd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = spsd.c; sourceTree = "<group>"; };
836F6E6818BDC2180095E648 /* nds_hwas.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nds_hwas.c; sourceTree = "<group>"; };
836F6E6918BDC2180095E648 /* nds_rrds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nds_rrds.c; sourceTree = "<group>"; };
836F6E6B18BDC2180095E648 /* nds_strm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nds_strm.c; sourceTree = "<group>"; };
@ -1241,7 +1241,6 @@
836F6E9418BDC2180095E648 /* ps2_b1s.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_b1s.c; sourceTree = "<group>"; };
836F6E9518BDC2180095E648 /* ps2_bg00.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_bg00.c; sourceTree = "<group>"; };
836F6E9618BDC2180095E648 /* ps2_bmdx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_bmdx.c; sourceTree = "<group>"; };
836F6E9718BDC2180095E648 /* ps2_ccc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_ccc.c; sourceTree = "<group>"; };
836F6E9818BDC2180095E648 /* hxd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hxd.c; sourceTree = "<group>"; };
836F6E9918BDC2180095E648 /* ps2_enth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_enth.c; sourceTree = "<group>"; };
836F6E9B18BDC2180095E648 /* ps2_filp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_filp.c; sourceTree = "<group>"; };
@ -1282,7 +1281,6 @@
836F6ED118BDC2190095E648 /* ps2_wmus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_wmus.c; sourceTree = "<group>"; };
836F6ED218BDC2190095E648 /* ps2_xa2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_xa2.c; sourceTree = "<group>"; };
836F6ED318BDC2190095E648 /* ps2_xa30.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_xa30.c; sourceTree = "<group>"; };
836F6ED518BDC2190095E648 /* ps3_cps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_cps.c; sourceTree = "<group>"; };
836F6ED918BDC2190095E648 /* ps3_past.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_past.c; sourceTree = "<group>"; };
836F6EE218BDC2190095E648 /* redspark.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = redspark.c; sourceTree = "<group>"; };
836F6EE318BDC2190095E648 /* riff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = riff.c; sourceTree = "<group>"; };
@ -1320,7 +1318,6 @@
836F6F0718BDC2190095E648 /* wpd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wpd.c; sourceTree = "<group>"; };
836F6F0818BDC2190095E648 /* ws_aud.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ws_aud.c; sourceTree = "<group>"; };
836F6F0918BDC2190095E648 /* wvs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wvs.c; sourceTree = "<group>"; };
836F6F0A18BDC2190095E648 /* x360_tra.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x360_tra.c; sourceTree = "<group>"; };
836F6F0C18BDC2190095E648 /* xbox_ims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xbox_ims.c; sourceTree = "<group>"; };
836F6F1218BDC2190095E648 /* xss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xss.c; sourceTree = "<group>"; };
836F6F1318BDC2190095E648 /* xwb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xwb.c; sourceTree = "<group>"; };
@ -1334,10 +1331,10 @@
836F6F1B18BDC2190095E648 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util.h; sourceTree = "<group>"; };
836F6F1C18BDC2190095E648 /* vgmstream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vgmstream.c; sourceTree = "<group>"; };
836F6F1D18BDC2190095E648 /* vgmstream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vgmstream.h; sourceTree = "<group>"; };
83709DFF1ECBC1A4005C03D3 /* gtd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gtd.c; sourceTree = "<group>"; };
83709DFF1ECBC1A4005C03D3 /* ghs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ghs.c; sourceTree = "<group>"; };
83709E001ECBC1A4005C03D3 /* mc3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mc3.c; sourceTree = "<group>"; };
83709E011ECBC1A4005C03D3 /* mss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mss.c; sourceTree = "<group>"; };
83709E031ECBC1A4005C03D3 /* ta_aac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ta_aac.c; sourceTree = "<group>"; };
83709E031ECBC1A4005C03D3 /* aac_triace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aac_triace.c; sourceTree = "<group>"; };
83709E0B1ECBC1C3005C03D3 /* mc3_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mc3_decoder.c; sourceTree = "<group>"; };
83709E0C1ECBC1C3005C03D3 /* psv_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psv_decoder.c; sourceTree = "<group>"; };
8373340E23F60C7A00DE14DC /* g7221_decoder_aes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = g7221_decoder_aes.h; sourceTree = "<group>"; };
@ -1372,7 +1369,7 @@
837CEADF23487F2A00E62A4A /* xa_xa30.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xa_xa30.c; sourceTree = "<group>"; };
837CEAE023487F2A00E62A4A /* ubi_hx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ubi_hx.c; sourceTree = "<group>"; };
837CEAE223487F2A00E62A4A /* nub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nub.c; sourceTree = "<group>"; };
837CEAE323487F2A00E62A4A /* xmv_valve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xmv_valve.c; sourceTree = "<group>"; };
837CEAE323487F2A00E62A4A /* xwv_valve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xwv_valve.c; sourceTree = "<group>"; };
837CEAE423487F2A00E62A4A /* xavs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xavs.c; sourceTree = "<group>"; };
837CEAE523487F2B00E62A4A /* xa_04sw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xa_04sw.c; sourceTree = "<group>"; };
837CEAE623487F2B00E62A4A /* ima.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ima.c; sourceTree = "<group>"; };
@ -1438,13 +1435,12 @@
83A21F83201D8981000F04B9 /* kma9.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kma9.c; sourceTree = "<group>"; };
83A21F84201D8981000F04B9 /* sqex_sead.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqex_sead.c; sourceTree = "<group>"; };
83A3F0711E3AD8B900D6A794 /* formats.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = formats.c; sourceTree = "<group>"; };
83A3F0731E3AD8B900D6A794 /* stack_alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stack_alloc.h; sourceTree = "<group>"; };
83A5F75E198DF021009AF94C /* bfwav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bfwav.c; sourceTree = "<group>"; };
83A8BADC256679C5000F5F3F /* wady_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wady_decoder.c; sourceTree = "<group>"; };
83A8BADE256679E3000F5F3F /* blocked_xwav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_xwav.c; sourceTree = "<group>"; };
83A8BAE025667AA7000F5F3F /* wady.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wady.c; sourceTree = "<group>"; };
83A8BAE125667AA7000F5F3F /* ps2_enth_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ps2_enth_streamfile.h; sourceTree = "<group>"; };
83A8BAE225667AA7000F5F3F /* xse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xse.c; sourceTree = "<group>"; };
83A8BAE225667AA7000F5F3F /* sdrh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sdrh.c; sourceTree = "<group>"; };
83A8BAE325667AA7000F5F3F /* xwav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xwav.c; sourceTree = "<group>"; };
83A8BAE425667AA7000F5F3F /* cpk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cpk.c; sourceTree = "<group>"; };
83AA5D0E1F6E2F5F0020821C /* ea_xa_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_xa_decoder.c; sourceTree = "<group>"; };
@ -1461,7 +1457,6 @@
83AA7D15279EBCF900087AA4 /* libswresample.4.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libswresample.4.dylib; path = ../../ThirdParty/ffmpeg/lib/libswresample.4.dylib; sourceTree = "<group>"; };
83AA7D16279EBCF900087AA4 /* libavutil.57.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libavutil.57.dylib; path = ../../ThirdParty/ffmpeg/lib/libavutil.57.dylib; sourceTree = "<group>"; };
83AA7F6D2519BFEA004C5298 /* vorbis_bitreader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vorbis_bitreader.h; sourceTree = "<group>"; };
83AA7F712519BFEA004C5298 /* mpeg_bitreader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mpeg_bitreader.h; sourceTree = "<group>"; };
83AA7F742519C041004C5298 /* dsb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsb.c; sourceTree = "<group>"; };
83AA7F752519C041004C5298 /* svag_kcet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = svag_kcet.c; sourceTree = "<group>"; };
83AA7F762519C042004C5298 /* bsf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bsf.c; sourceTree = "<group>"; };
@ -1475,7 +1470,7 @@
83AA7F872519C076004C5298 /* render.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = render.h; sourceTree = "<group>"; };
83AA7F882519C076004C5298 /* render.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = render.c; sourceTree = "<group>"; };
83AA7F892519C076004C5298 /* decode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = decode.c; sourceTree = "<group>"; };
83AB8C741E8072A100086084 /* x360_ast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x360_ast.c; sourceTree = "<group>"; };
83AB8C741E8072A100086084 /* astb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = astb.c; sourceTree = "<group>"; };
83AF2CC526226BA400538240 /* gcub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gcub.c; sourceTree = "<group>"; };
83AF2CC626226BA400538240 /* exst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = exst.c; sourceTree = "<group>"; };
83AF2CC726226BA400538240 /* ogv_3rdeye.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ogv_3rdeye.c; sourceTree = "<group>"; };
@ -1483,7 +1478,6 @@
83AFABB923795201002F3947 /* xssb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xssb.c; sourceTree = "<group>"; };
83AFABBA23795202002F3947 /* ea_eaac_opus_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ea_eaac_opus_streamfile.h; sourceTree = "<group>"; };
83AFABBB23795202002F3947 /* isb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = isb.c; sourceTree = "<group>"; };
83B46FCD2707FB2100847FC9 /* at3plus_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = at3plus_decoder.h; sourceTree = "<group>"; };
83B46FD42707FB9A00847FC9 /* endianness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = endianness.h; sourceTree = "<group>"; };
83B69B212845A26600D2435A /* bw_mp3_riff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bw_mp3_riff.c; sourceTree = "<group>"; };
83B72E342790452C006007A3 /* libfdk-aac.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libfdk-aac.2.dylib"; path = "../../ThirdParty/fdk-aac/lib/libfdk-aac.2.dylib"; sourceTree = "<group>"; };
@ -1775,7 +1769,6 @@
83AA7F882519C076004C5298 /* render.c */,
83AA7F872519C076004C5298 /* render.h */,
8347C7472796D76700FA8A7D /* seek.c */,
83A3F0731E3AD8B900D6A794 /* stack_alloc.h */,
836F6F1718BDC2190095E648 /* streamfile.c */,
836F6F1818BDC2190095E648 /* streamfile.h */,
836F6F1918BDC2190095E648 /* streamtypes.h */,
@ -1796,8 +1789,6 @@
836F6DE018BDC2180095E648 /* acm_decoder.c */,
836F6DE218BDC2180095E648 /* adx_decoder.c */,
8315958320FEC831007002F0 /* asf_decoder.c */,
8306B08120984517000302D4 /* at3plus_decoder.c */,
83B46FCD2707FB2100847FC9 /* at3plus_decoder.h */,
830EBE0F2004655D0023AA10 /* atrac9_decoder.c */,
834FE0B2215C798C000A5D3D /* celt_fsb_decoder.c */,
83031EBF243C50A800C3F3E0 /* circus_decoder_lib_data.h */,
@ -1843,7 +1834,6 @@
836F6DEC18BDC2180095E648 /* lsf_decoder.c */,
83709E0B1ECBC1C3005C03D3 /* mc3_decoder.c */,
836F6DEE18BDC2180095E648 /* mp4_aac_decoder.c */,
83AA7F712519BFEA004C5298 /* mpeg_bitreader.h */,
839E21D91F2EDAF000EE54D7 /* mpeg_custom_utils_ahx.c */,
83AA5D141F6E2F600020821C /* mpeg_custom_utils_awc.c */,
83AA5D131F6E2F5F0020821C /* mpeg_custom_utils_ealayer3.c */,
@ -1931,7 +1921,6 @@
8306B08F2098454E000302D4 /* blocked_sthd.c */,
8306B09C20984550000302D4 /* blocked_str_snds.c */,
8306B09820984550000302D4 /* blocked_thp.c */,
8306B09920984550000302D4 /* blocked_tra.c */,
836F46AD28208735005B9B87 /* blocked_tt_ad.c */,
83031ECA243C50CB00C3F3E0 /* blocked_ubi_sce.c */,
83AA5D1A1F6E2F7F0020821C /* blocked_vgs.c */,
@ -1964,6 +1953,7 @@
83C727FE22BC893900678B4A /* 9tav.c */,
8351F32A2212B57000A606E4 /* 208.c */,
834FE0C8215C79E7000A5D3D /* a2m.c */,
83709E031ECBC1A4005C03D3 /* aac_triace.c */,
836F6E2A18BDC2180095E648 /* aax.c */,
837CEAD623487E8300E62A4A /* acb.c */,
836F6E2B18BDC2180095E648 /* acm.c */,
@ -1979,6 +1969,7 @@
8349A9001FE6258000E26435 /* afc.c */,
836F6E2F18BDC2180095E648 /* agsc.c */,
834FE0E5215C79EC000A5D3D /* ahv.c */,
836DF626298F864100CD0580 /* ahx_keys.h */,
836F6E3018BDC2180095E648 /* ahx.c */,
834FE0C1215C79E5000A5D3D /* aif_asobo.c */,
836F6E3118BDC2180095E648 /* aifc.c */,
@ -1993,6 +1984,7 @@
835B9B8B2730BF2C00F87EE3 /* ast_mmv.c */,
835B9B8A2730BF2C00F87EE3 /* ast_mv.c */,
836F6E3518BDC2180095E648 /* ast.c */,
83AB8C741E8072A100086084 /* astb.c */,
8306B0D520984590000302D4 /* atsl.c */,
83A21F7C201D897F000F04B9 /* atx.c */,
83EED5D2203A8BC7008BEB45 /* aus.c */,
@ -2024,9 +2016,11 @@
834FE0E8215C79EC000A5D3D /* ck.c */,
8346D97825BF838C00D1A8B0 /* compresswave.c */,
83A8BAE425667AA7000F5F3F /* cpk.c */,
836DF625298F864100CD0580 /* cps.c */,
83FC176B23AC58D100E1025F /* csb.c */,
834FE0D8215C79EA000A5D3D /* csmp.c */,
836F6E3C18BDC2180095E648 /* cstr.c */,
831BA6151EAC61A500CF89B0 /* cxs.c */,
836F6E3D18BDC2180095E648 /* dc_asd.c */,
836F6E3F18BDC2180095E648 /* dc_idvi.c */,
836F6E4018BDC2180095E648 /* dc_kcey.c */,
@ -2080,9 +2074,9 @@
836F6E4E18BDC2180095E648 /* gcsw.c */,
83AF2CC526226BA400538240 /* gcub.c */,
836F6E4F18BDC2180095E648 /* genh.c */,
83709DFF1ECBC1A4005C03D3 /* ghs.c */,
8375737421F950EC00F01AF5 /* gin.c */,
836F6E5118BDC2180095E648 /* gsp_gsb.c */,
83709DFF1ECBC1A4005C03D3 /* gtd.c */,
8342469020C4D22F00926E48 /* h4m.c */,
836F6E5218BDC2180095E648 /* halpst.c */,
835B9B8D2730BF2D00F87EE3 /* hca_bf.h */,
@ -2157,7 +2151,6 @@
836F6E6518BDC2180095E648 /* myspd.c */,
8349A9061FE6258100E26435 /* naac.c */,
836F6E6618BDC2180095E648 /* naomi_adpcm.c */,
836F6E6718BDC2180095E648 /* naomi_spsd.c */,
836F6E6818BDC2180095E648 /* nds_hwas.c */,
836F6E6918BDC2180095E648 /* nds_rrds.c */,
830165991F256BD000CA0941 /* nds_strm_ffta2.c */,
@ -2197,6 +2190,7 @@
8306B0CE2098458E000302D4 /* opus.c */,
836F6E8318BDC2180095E648 /* otm.c */,
836F6E8418BDC2180095E648 /* p3d.c */,
831BA6171EAC61A500CF89B0 /* pasx.c */,
8349A8FE1FE6257F00E26435 /* pc_adp_otns.c */,
8349A8F01FE6257C00E26435 /* pc_ast.c */,
836F6E8618BDC2180095E648 /* pc_mxst.c */,
@ -2214,7 +2208,6 @@
836F6E9418BDC2180095E648 /* ps2_b1s.c */,
836F6E9518BDC2180095E648 /* ps2_bg00.c */,
836F6E9618BDC2180095E648 /* ps2_bmdx.c */,
836F6E9718BDC2180095E648 /* ps2_ccc.c */,
83A8BAE125667AA7000F5F3F /* ps2_enth_streamfile.h */,
836F6E9918BDC2180095E648 /* ps2_enth.c */,
836F6E9B18BDC2180095E648 /* ps2_filp.c */,
@ -2255,7 +2248,6 @@
8349A8FC1FE6257F00E26435 /* ps2_xa2_rrp.c */,
836F6ED218BDC2190095E648 /* ps2_xa2.c */,
836F6ED318BDC2190095E648 /* ps2_xa30.c */,
836F6ED518BDC2190095E648 /* ps3_cps.c */,
836F6ED918BDC2190095E648 /* ps3_past.c */,
8315868326F586E200803A3A /* psb.c */,
837CEAE823487F2B00E62A4A /* psf.c */,
@ -2290,6 +2282,7 @@
8349A8F51FE6257D00E26435 /* scd_pcm.c */,
836F6EEE18BDC2190095E648 /* sd9.c */,
834FE0E6215C79EC000A5D3D /* sdf.c */,
83A8BAE225667AA7000F5F3F /* sdrh.c */,
836F6EEF18BDC2190095E648 /* sdt.c */,
837CEB062348809400E62A4A /* seb.c */,
836F6EF018BDC2190095E648 /* seg.c */,
@ -2307,6 +2300,7 @@
835559FB2869102B005FE93A /* sndz.c */,
836F6EBE18BDC2190095E648 /* spm.c */,
83A21F82201D8981000F04B9 /* sps_n1.c */,
836F6E6718BDC2180095E648 /* spsd.c */,
836F6EF318BDC2190095E648 /* spt_spd.c */,
836F6EF418BDC2190095E648 /* sqex_scd.c */,
83A21F84201D8981000F04B9 /* sqex_sead.c */,
@ -2328,7 +2322,6 @@
836F6EF918BDC2190095E648 /* svs.c */,
83D0381724A4129A004CF90F /* swav.c */,
831BA6121EAC61A500CF89B0 /* sxd.c */,
83709E031ECBC1A4005C03D3 /* ta_aac.c */,
83E7FD6425EF2B2400683FD2 /* tac.c */,
8373342E23F60D4100DE14DC /* tgc.c */,
836F6EFA18BDC2190095E648 /* thp.c */,
@ -2386,10 +2379,6 @@
836F6F0918BDC2190095E648 /* wvs.c */,
83FF0EBB1E93282100C58054 /* wwise.c */,
839FBFF826C354E60016A78A /* wxd_wxh.c */,
83AB8C741E8072A100086084 /* x360_ast.c */,
831BA6151EAC61A500CF89B0 /* x360_cxs.c */,
831BA6171EAC61A500CF89B0 /* x360_pasx.c */,
836F6F0A18BDC2190095E648 /* x360_tra.c */,
837CEAE523487F2B00E62A4A /* xa_04sw.c */,
837CEADF23487F2A00E62A4A /* xa_xa30.c */,
832BF81521E0514A006F50F1 /* xa.c */,
@ -2402,14 +2391,12 @@
8350C0541E071881009E0A93 /* xma.c */,
834FE0DC215C79EA000A5D3D /* xmd.c */,
837CEAEC23487F2C00E62A4A /* xmu.c */,
837CEAE323487F2A00E62A4A /* xmv_valve.c */,
83031ED6243C510400C3F3E0 /* xnb_lz4mg.h */,
83031ED8243C510500C3F3E0 /* xnb_streamfile.h */,
830EBE112004656E0023AA10 /* xnb.c */,
832BF81921E0514A006F50F1 /* xopus.c */,
832BF80A21E05148006F50F1 /* xpcm.c */,
832BF80C21E05148006F50F1 /* xps.c */,
83A8BAE225667AA7000F5F3F /* xse.c */,
83FC417226D3304D009A2022 /* xsh_xsd_xss.c */,
836F6F1218BDC2190095E648 /* xss.c */,
83AFABB923795201002F3947 /* xssb.c */,
@ -2423,6 +2410,7 @@
83C7280222BC893A00678B4A /* xwma_konami_streamfile.h */,
83C7280B22BC893C00678B4A /* xwma_konami.c */,
832BF81621E0514A006F50F1 /* xwma.c */,
837CEAE323487F2A00E62A4A /* xwv_valve.c */,
836F6F1418BDC2190095E648 /* ydsp.c */,
836F6F1518BDC2190095E648 /* zsd.c */,
832BF80E21E05149006F50F1 /* zsnd_streamfile.h */,
@ -2445,8 +2433,11 @@
83D26A7C26E66DC2001A9475 /* util */ = {
isa = PBXGroup;
children = (
836DF620298F83F400CD0580 /* bitstream_msb.h */,
83D26A8026E66DC2001A9475 /* chunks.c */,
83D26A7E26E66DC2001A9475 /* chunks.h */,
836DF621298F83F400CD0580 /* cri_keys.c */,
836DF61F298F83F400CD0580 /* cri_keys.h */,
836F46B5282087A6005B9B87 /* cri_utf.c */,
836F46B6282087A6005B9B87 /* cri_utf.h */,
83B46FD42707FB9A00847FC9 /* endianness.h */,
@ -2524,6 +2515,7 @@
83C7282722BC8C1500678B4A /* plugins.h in Headers */,
83256CC128666C620036D9C0 /* index.h in Headers */,
834FE0ED215C79ED000A5D3D /* fsb_interleave_streamfile.h in Headers */,
836DF622298F83F400CD0580 /* cri_keys.h in Headers */,
8351F32E2212B57000A606E4 /* ubi_bao_streamfile.h in Headers */,
8349A9111FE6258200E26435 /* bar_streamfile.h in Headers */,
83256CE128666C620036D9C0 /* sample.h in Headers */,
@ -2540,7 +2532,6 @@
83AA7F722519BFEA004C5298 /* vorbis_bitreader.h in Headers */,
83256CD628666C620036D9C0 /* newhuffman.h in Headers */,
834FE0BA215C798C000A5D3D /* ea_mt_decoder_utk.h in Headers */,
83B46FD12707FB2100847FC9 /* at3plus_decoder.h in Headers */,
835C883722CC17BE001B4B3F /* ogg_vorbis_streamfile.h in Headers */,
837CEAFE23487F2C00E62A4A /* jstm_streamfile.h in Headers */,
832BF82021E0514B006F50F1 /* zsnd_streamfile.h in Headers */,
@ -2549,14 +2540,13 @@
83031EDB243C510500C3F3E0 /* xnb_lz4mg.h in Headers */,
836F705418BDC2190095E648 /* streamfile.h in Headers */,
835B9B922730BF2D00F87EE3 /* hca_bf.h in Headers */,
836DF623298F83F400CD0580 /* bitstream_msb.h in Headers */,
83256CDD28666C620036D9C0 /* l3tabs.h in Headers */,
83A3F0761E3AD8B900D6A794 /* stack_alloc.h in Headers */,
8373342723F60CDC00DE14DC /* lrmd_streamfile.h in Headers */,
83C7281122BC893D00678B4A /* 9tav_streamfile.h in Headers */,
83256CD928666C620036D9C0 /* costabs.h in Headers */,
83C7280F22BC893D00678B4A /* xwb_xsb.h in Headers */,
8315868B26F586F900803A3A /* m2_psb.h in Headers */,
83AA7F732519BFEA004C5298 /* mpeg_bitreader.h in Headers */,
83256CD428666C620036D9C0 /* icy.h in Headers */,
83256CDC28666C620036D9C0 /* icy2utf8.h in Headers */,
832FC36F278FAE3E0056A860 /* encrypted_mc161_streamfile.h in Headers */,
@ -2604,6 +2594,7 @@
8373341923F60C7B00DE14DC /* g7221_decoder_lib_data.h in Headers */,
83256CCC28666C620036D9C0 /* init_layer12.h in Headers */,
83AFABBD23795202002F3947 /* ea_eaac_opus_streamfile.h in Headers */,
836DF628298F864100CD0580 /* ahx_keys.h in Headers */,
83256CBF28666C620036D9C0 /* l12tabs.h in Headers */,
83256CCF28666C620036D9C0 /* synth_sse3d.h in Headers */,
83256CD528666C620036D9C0 /* fmt123.h in Headers */,
@ -2878,10 +2869,11 @@
8349A90A1FE6258200E26435 /* sab.c in Sources */,
83AF2CC926226BA500538240 /* gcub.c in Sources */,
8306B08620984518000302D4 /* fadpcm_decoder.c in Sources */,
83AB8C761E8072A100086084 /* x360_ast.c in Sources */,
83AB8C761E8072A100086084 /* astb.c in Sources */,
834FE105215C79ED000A5D3D /* xmd.c in Sources */,
837CEADA23487E8300E62A4A /* acb.c in Sources */,
834FE0F6215C79ED000A5D3D /* derf.c in Sources */,
836DF624298F83F400CD0580 /* cri_keys.c in Sources */,
83D20081248DDB770048BD24 /* sadl.c in Sources */,
836F6F8B18BDC2190095E648 /* genh.c in Sources */,
83C7281922BC893D00678B4A /* fsb5_fev.c in Sources */,
@ -2893,7 +2885,7 @@
836F703C18BDC2190095E648 /* wii_bns.c in Sources */,
830EBE132004656E0023AA10 /* xnb.c in Sources */,
835027131ED119E000C25929 /* mta2_decoder.c in Sources */,
83A8BAE725667AA8000F5F3F /* xse.c in Sources */,
83A8BAE725667AA8000F5F3F /* sdrh.c in Sources */,
8306B0DB20984590000302D4 /* nxap.c in Sources */,
836F6FA718BDC2190095E648 /* nds_strm.c in Sources */,
8349A91A1FE6258200E26435 /* vxn.c in Sources */,
@ -2936,7 +2928,6 @@
837CEAFB23487F2C00E62A4A /* ima.c in Sources */,
836F702D18BDC2190095E648 /* sfl.c in Sources */,
83D7318C1A749EEE00CA1366 /* g719_decoder.c in Sources */,
836F701118BDC2190095E648 /* ps3_cps.c in Sources */,
8306B0DA20984590000302D4 /* ea_wve_au00.c in Sources */,
83A21F85201D8981000F04B9 /* atx.c in Sources */,
83A8BADF256679E3000F5F3F /* blocked_xwav.c in Sources */,
@ -2951,7 +2942,7 @@
83AA7F812519C042004C5298 /* silence.c in Sources */,
834FE0B3215C798C000A5D3D /* acm_decoder_util.c in Sources */,
837CEA7A23487E2500E62A4A /* ffmpeg_decoder_utils.c in Sources */,
837CEAF823487F2C00E62A4A /* xmv_valve.c in Sources */,
837CEAF823487F2C00E62A4A /* xwv_valve.c in Sources */,
836F6F6718BDC2190095E648 /* acm.c in Sources */,
834FE0FD215C79ED000A5D3D /* vpk.c in Sources */,
8306B0DF20984590000302D4 /* ea_wve_ad10.c in Sources */,
@ -2986,7 +2977,6 @@
836F6FEF18BDC2190095E648 /* ps2_pnb.c in Sources */,
836F6FCB18BDC2190095E648 /* ads.c in Sources */,
834FE108215C79ED000A5D3D /* hd3_bd3.c in Sources */,
836F6FD318BDC2190095E648 /* ps2_ccc.c in Sources */,
83C7281C22BC893D00678B4A /* sfh.c in Sources */,
834FE0FC215C79ED000A5D3D /* vai.c in Sources */,
83D2007F248DDB770048BD24 /* mups.c in Sources */,
@ -3119,7 +3109,7 @@
83A16D2B22D2ADE800B90C4C /* awb.c in Sources */,
831BA6191EAC61A500CF89B0 /* ogl.c in Sources */,
83709E061ECBC1A4005C03D3 /* mc3.c in Sources */,
831BA61F1EAC61A500CF89B0 /* x360_cxs.c in Sources */,
831BA61F1EAC61A500CF89B0 /* cxs.c in Sources */,
836F6FCD18BDC2190095E648 /* ps2_ass.c in Sources */,
8349A90B1FE6258200E26435 /* ps2_pcm.c in Sources */,
836F6F4A18BDC2190095E648 /* interleave.c in Sources */,
@ -3133,7 +3123,6 @@
837CEAF223487F2C00E62A4A /* raw_pcm.c in Sources */,
836F6FA518BDC2190095E648 /* nds_rrds.c in Sources */,
836F702F18BDC2190095E648 /* spt_spd.c in Sources */,
836F704618BDC2190095E648 /* x360_tra.c in Sources */,
834FE0F0215C79ED000A5D3D /* apc.c in Sources */,
836F6FFA18BDC2190095E648 /* spm.c in Sources */,
83C7281B22BC893D00678B4A /* strm_abylight.c in Sources */,
@ -3182,14 +3171,13 @@
836F6FDB18BDC2190095E648 /* ps2_hsf.c in Sources */,
836F6FF618BDC2190095E648 /* ster.c in Sources */,
834FE10E215C79ED000A5D3D /* ahv.c in Sources */,
8306B08420984518000302D4 /* at3plus_decoder.c in Sources */,
8349A90E1FE6258200E26435 /* scd_pcm.c in Sources */,
834FE0F9215C79ED000A5D3D /* wavebatch.c in Sources */,
836F6F9518BDC2190095E648 /* kraw.c in Sources */,
836F6FB718BDC2190095E648 /* ngc_ssm.c in Sources */,
8306B0E920984590000302D4 /* opus.c in Sources */,
832BF80021E050B7006F50F1 /* mpeg_custom_utils_eamp3.c in Sources */,
83709E051ECBC1A4005C03D3 /* gtd.c in Sources */,
83709E051ECBC1A4005C03D3 /* ghs.c in Sources */,
8306B0A420984552000302D4 /* segmented.c in Sources */,
83A21F86201D8981000F04B9 /* xwc.c in Sources */,
8306B0A620984552000302D4 /* blocked_ea_wve_ad10.c in Sources */,
@ -3208,14 +3196,14 @@
836F6F3C18BDC2190095E648 /* xa_decoder.c in Sources */,
8317C24C26982CC1007DD0B8 /* sspr.c in Sources */,
832BF82521E0514B006F50F1 /* ogg_opus.c in Sources */,
83709E091ECBC1A4005C03D3 /* ta_aac.c in Sources */,
83709E091ECBC1A4005C03D3 /* aac_triace.c in Sources */,
836F6F9118BDC2190095E648 /* ios_psnd.c in Sources */,
836F700618BDC2190095E648 /* vgs_ps.c in Sources */,
834FE10F215C79ED000A5D3D /* sdf.c in Sources */,
834FE0FF215C79ED000A5D3D /* sscf.c in Sources */,
8373341A23F60C7B00DE14DC /* relic_decoder_mixfft.c in Sources */,
836F6FAA18BDC2190095E648 /* ngc_bh2pcm.c in Sources */,
831BA6211EAC61A500CF89B0 /* x360_pasx.c in Sources */,
831BA6211EAC61A500CF89B0 /* pasx.c in Sources */,
832BF82621E0514B006F50F1 /* nwav.c in Sources */,
836F6F3018BDC2190095E648 /* nds_procyon_decoder.c in Sources */,
8349A8E81FE6253900E26435 /* blocked_dec.c in Sources */,
@ -3238,6 +3226,7 @@
83A21F88201D8981000F04B9 /* ogg_vorbis.c in Sources */,
837CEAF923487F2C00E62A4A /* xavs.c in Sources */,
836F6F8E18BDC2190095E648 /* halpst.c in Sources */,
836DF627298F864100CD0580 /* cps.c in Sources */,
8319018128F67F1500B70711 /* ice_decoder_icelib.c in Sources */,
836F6FEE18BDC2190095E648 /* ps2_p2bt.c in Sources */,
836F702618BDC2190095E648 /* s14_sss.c in Sources */,
@ -3277,7 +3266,6 @@
836F6FA218BDC2190095E648 /* naomi_adpcm.c in Sources */,
837CEAF123487F2C00E62A4A /* xvas.c in Sources */,
836F6FBF18BDC2190095E648 /* otm.c in Sources */,
8306B0B420984552000302D4 /* blocked_tra.c in Sources */,
834FE0B8215C798C000A5D3D /* acm_decoder_decode.c in Sources */,
8399335F2591E8C1001855AF /* ifs.c in Sources */,
8373342A23F60CDC00DE14DC /* lrmd.c in Sources */,
@ -3305,7 +3293,7 @@
8349A9151FE6258200E26435 /* ps2_xa2_rrp.c in Sources */,
836F703518BDC2190095E648 /* svs.c in Sources */,
8347C7492796D76700FA8A7D /* seek.c in Sources */,
836F6FA318BDC2190095E648 /* naomi_spsd.c in Sources */,
836F6FA318BDC2190095E648 /* spsd.c in Sources */,
8306B0B920984552000302D4 /* blocked_matx.c in Sources */,
83A21F7B201D895B000F04B9 /* blocked_xvag.c in Sources */,
836F6FBA18BDC2190095E648 /* ngc_ymf.c in Sources */,

View File

@ -1,82 +0,0 @@
#include "coding.h"
#include "../util.h"
#ifdef VGM_USE_MAIATRAC3PLUS
#include "maiatrac3plus.h"
#include "at3plus_decoder.h"
maiatrac3plus_codec_data *init_at3plus() {
maiatrac3plus_codec_data *data = malloc(sizeof(maiatrac3plus_codec_data));
data->buffer = 0;
data->samples_discard = 0;
data->handle = Atrac3plusDecoder_openContext();
if (!data->handle) goto fail;
return data;
fail:
return NULL;
}
void decode_at3plus(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) {
VGMSTREAMCHANNEL *ch = &vgmstream->ch[0];
maiatrac3plus_codec_data *data = vgmstream->codec_data;
int i;
int first_sample = vgmstream->samples_into_block % 2048;
if (0 == channel && (0 == first_sample || data->samples_discard == first_sample))
{
uint8_t code_buffer[0x8000];
int blocks_to_decode = 1;
int max_blocks_to_decode = (ch->offset - ch->channel_start_offset) / vgmstream->interleave_block_size + 1;
if (data->samples_discard) blocks_to_decode = 8;
if (blocks_to_decode > max_blocks_to_decode) blocks_to_decode = max_blocks_to_decode;
while (blocks_to_decode--) {
ch->streamfile->read(ch->streamfile, code_buffer, ch->offset - blocks_to_decode * vgmstream->interleave_block_size, vgmstream->interleave_block_size);
Atrac3plusDecoder_decodeFrame(data->handle, code_buffer, vgmstream->interleave_block_size, &data->channels, (void**)&data->buffer);
}
data->samples_discard = 0;
}
for (i = 0; i < samples_to_do; i++) {
outbuf[i*channelspacing] = data->buffer[(first_sample+i)*data->channels+channel];
}
if (0 == channel && 2048 == first_sample + samples_to_do) {
ch->offset += vgmstream->interleave_block_size;
}
}
void reset_at3plus(VGMSTREAM *vgmstream) {
maiatrac3plus_codec_data *data = vgmstream->codec_data;
if (!data) return;
if (data->handle)
Atrac3plusDecoder_closeContext(data->handle);
data->handle = Atrac3plusDecoder_openContext();
data->samples_discard = 0;
}
void seek_at3plus(VGMSTREAM *vgmstream, int32_t num_sample) {
int blocks_to_skip = num_sample / 2048;
int samples_to_discard = num_sample % 2048;
maiatrac3plus_codec_data *data = (maiatrac3plus_codec_data *)(vgmstream->codec_data);
if (!data) return;
vgmstream->loop_ch[0].offset =
vgmstream->loop_ch[0].channel_start_offset +
vgmstream->interleave_block_size * blocks_to_skip;
data->samples_discard = samples_to_discard;
}
void free_at3plus(maiatrac3plus_codec_data *data) {
if (data) {
if (data->handle) Atrac3plusDecoder_closeContext(data->handle);
free(data);
}
}
#endif

View File

@ -1,11 +0,0 @@
#ifndef _AT3PLUS_DECODER_H
#define _AT3PLUS_DECODER_H
struct maiatrac3plus_codec_data {
sample_t* buffer;
int channels;
int samples_discard;
void* handle;
};
#endif

View File

@ -21,15 +21,15 @@ struct celt_codec_data {
int channel_mode;
celt_lib_t version;
void *mode_handle;
void *decoder_handle;
void* mode_handle;
void* decoder_handle;
};
/* FSB CELT, frames with custom header and standard data (API info from FMOD DLLs).
* FMOD used various libcelt versions, thus some tweaks are needed for them to coexist. */
celt_codec_data *init_celt_fsb(int channels, celt_lib_t version) {
celt_codec_data* init_celt_fsb(int channels, celt_lib_t version) {
int error = 0, lib_version = 0;
celt_codec_data* data = NULL;
@ -42,24 +42,24 @@ celt_codec_data *init_celt_fsb(int channels, celt_lib_t version) {
switch(data->version) {
case CELT_0_06_1: /* older FSB4 (FMOD ~4.33) */
data->mode_handle = celt_0061_mode_create(FSB_CELT_INTERNAL_SAMPLE_RATE, data->channel_mode, FSB_CELT_SAMPLES_PER_FRAME, &error);
data->mode_handle = celt_mode_create_0061(FSB_CELT_INTERNAL_SAMPLE_RATE, data->channel_mode, FSB_CELT_SAMPLES_PER_FRAME, &error);
if (!data->mode_handle || error != CELT_OK) goto fail;
error = celt_0061_mode_info(data->mode_handle, CELT_GET_BITSTREAM_VERSION, &lib_version);
error = celt_mode_info_0061(data->mode_handle, CELT_GET_BITSTREAM_VERSION, &lib_version);
if (error != CELT_OK || lib_version != FSB_CELT_0_06_1_VERSION) goto fail;
data->decoder_handle = celt_0061_decoder_create(data->mode_handle);
data->decoder_handle = celt_decoder_create_0061(data->mode_handle);
if (!data->decoder_handle) goto fail;
break;
case CELT_0_11_0: /* newer FSB4 (FMOD ~4.34), FSB5 */
data->mode_handle = celt_0110_mode_create(FSB_CELT_INTERNAL_SAMPLE_RATE, FSB_CELT_SAMPLES_PER_FRAME, &error); /* "custom" and not ok? */
data->mode_handle = celt_mode_create_0110(FSB_CELT_INTERNAL_SAMPLE_RATE, FSB_CELT_SAMPLES_PER_FRAME, &error); /* "custom" and not ok? */
if (!data->mode_handle || error != CELT_OK) goto fail;
error = celt_0110_mode_info(data->mode_handle, CELT_GET_BITSTREAM_VERSION, &lib_version);
error = celt_mode_info_0110(data->mode_handle, CELT_GET_BITSTREAM_VERSION, &lib_version);
if (error != CELT_OK || lib_version != FSB_CELT_0_11_0_VERSION) goto fail;
data->decoder_handle = celt_0110_decoder_create_custom(data->mode_handle, data->channel_mode, &error);
data->decoder_handle = celt_decoder_create_custom_0110(data->mode_handle, data->channel_mode, &error);
if (!data->decoder_handle || error != CELT_OK) goto fail;
break;
@ -136,11 +136,11 @@ void decode_celt_fsb(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_
switch(data->version) {
case CELT_0_06_1:
status = celt_0061_decode(data->decoder_handle, data_buffer,bytes, data->sample_buffer);
status = celt_decode_0061(data->decoder_handle, data_buffer,bytes, data->sample_buffer);
break;
case CELT_0_11_0:
status = celt_0110_decode(data->decoder_handle, data_buffer,bytes, data->sample_buffer, FSB_CELT_SAMPLES_PER_FRAME);
status = celt_decode_0110(data->decoder_handle, data_buffer,bytes, data->sample_buffer, FSB_CELT_SAMPLES_PER_FRAME);
break;
default:
@ -167,16 +167,16 @@ void reset_celt_fsb(celt_codec_data* data) {
/* recreate decoder (mode should not change) */
switch(data->version) {
case CELT_0_06_1:
if (data->decoder_handle) celt_0061_decoder_destroy(data->decoder_handle);
if (data->decoder_handle) celt_decoder_destroy_0061(data->decoder_handle);
data->decoder_handle = celt_0061_decoder_create(data->mode_handle);
data->decoder_handle = celt_decoder_create_0061(data->mode_handle);
if (!data->decoder_handle) goto fail;
break;
case CELT_0_11_0:
if (data->decoder_handle) celt_0110_decoder_destroy(data->decoder_handle);
if (data->decoder_handle) celt_decoder_destroy_0110(data->decoder_handle);
data->decoder_handle = celt_0110_decoder_create_custom(data->mode_handle, data->channel_mode, NULL);
data->decoder_handle = celt_decoder_create_custom_0110(data->mode_handle, data->channel_mode, NULL);
if (!data->decoder_handle) goto fail;
break;
@ -211,13 +211,13 @@ void free_celt_fsb(celt_codec_data* data) {
switch(data->version) {
case CELT_0_06_1:
if (data->decoder_handle) celt_0061_decoder_destroy(data->decoder_handle);
if (data->mode_handle) celt_0061_mode_destroy(data->mode_handle);
if (data->decoder_handle) celt_decoder_destroy_0061(data->decoder_handle);
if (data->mode_handle) celt_mode_destroy_0061(data->mode_handle);
break;
case CELT_0_11_0:
if (data->decoder_handle) celt_0110_decoder_destroy(data->decoder_handle);
if (data->mode_handle) celt_0110_mode_destroy(data->mode_handle);
if (data->decoder_handle) celt_decoder_destroy_0110(data->decoder_handle);
if (data->mode_handle) celt_mode_destroy_0110(data->mode_handle);
break;
default:

View File

@ -93,7 +93,9 @@ void decode_ulaw_int(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspac
void decode_alaw(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcmfloat(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian);
void decode_pcm24le(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm24be(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
int32_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample);
int32_t pcm24_bytes_to_samples(size_t bytes, int channels);
int32_t pcm16_bytes_to_samples(size_t bytes, int channels);
int32_t pcm8_bytes_to_samples(size_t bytes, int channels);
@ -473,6 +475,13 @@ typedef enum {
MPEG_EAMP3 /* custom frame header + MPEG frame + PCM blocks */
} mpeg_custom_t;
typedef struct {
int type;
uint16_t key1;
uint16_t key2;
uint16_t key3;
} crikey_t;
/* config for the above modes */
typedef struct {
int channels; /* max channels */
@ -485,11 +494,7 @@ typedef struct {
int encryption; /* encryption mode */
int big_endian;
int skip_samples;
/* for AHX */
int cri_type;
uint16_t cri_key1;
uint16_t cri_key2;
uint16_t cri_key3;
crikey_t crikey; /* for AHX */
} mpeg_custom_config;
mpeg_codec_data* init_mpeg(STREAMFILE* sf, off_t start_offset, coding_t *coding_type, int channels);
@ -504,6 +509,7 @@ long mpeg_bytes_to_samples(long bytes, const mpeg_codec_data* data);
uint32_t mpeg_get_tag_size(STREAMFILE* sf, uint32_t offset, uint32_t header);
int mpeg_get_frame_info(STREAMFILE* sf, off_t offset, mpeg_frame_info* info);
int test_ahx_key(STREAMFILE* sf, off_t offset, crikey_t* crikey);
#endif
@ -540,18 +546,6 @@ void free_mp4_aac(mp4_aac_codec_data* data);
#endif
#ifdef VGM_USE_MAIATRAC3PLUS
/* at3plus_decoder */
typedef struct maiatrac3plus_codec_data maiatrac3plus_codec_data;
maiatrac3plus_codec_data* init_at3plus();
void decode_at3plus(VGMSTREAM* vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel);
void reset_at3plus(VGMSTREAM* vgmstream);
void seek_at3plus(VGMSTREAM* vgmstream, int32_t num_sample);
void free_at3plus(maiatrac3plus_codec_data* data);
#endif
#ifdef VGM_USE_ATRAC9
/* atrac9_decoder */
typedef struct {
@ -627,8 +621,16 @@ STREAMFILE* ffmpeg_get_streamfile(ffmpeg_codec_data* data);
/* ffmpeg_decoder_utils.c (helper-things) */
ffmpeg_codec_data* init_ffmpeg_atrac3_raw(STREAMFILE* sf, off_t offset, size_t data_size, int sample_count, int channels, int sample_rate, int block_align, int encoder_delay);
ffmpeg_codec_data* init_ffmpeg_atrac3_riff(STREAMFILE* sf, off_t offset, int* out_samples);
ffmpeg_codec_data* init_ffmpeg_atrac3plus_raw(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int32_t sample_count, int channels, int sample_rate, int block_align, int encoder_delay);
ffmpeg_codec_data* init_ffmpeg_aac(STREAMFILE* sf, off_t offset, size_t size, int skip_samples);
ffmpeg_codec_data* init_ffmpeg_xwma(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int format, int channels, int sample_rate, int avg_bitrate, int block_size);
//TODO: make init_ffmpeg_xwma_fmt(be) too to pass fmt chunk?
ffmpeg_codec_data* init_ffmpeg_xma1_raw(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int channels, int sample_rate, int stream_mode);
ffmpeg_codec_data* init_ffmpeg_xma2_raw(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int32_t sample_count, int channels, int sample_rate, int block_size, int block_count);
ffmpeg_codec_data* init_ffmpeg_xma_chunk(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, uint32_t chunk_offset, uint32_t chunk_size);
ffmpeg_codec_data* init_ffmpeg_xma_chunk_split(STREAMFILE* sf_head, STREAMFILE* sf_data, uint32_t data_offset, uint32_t data_size, uint32_t chunk_offset, uint32_t chunk_size);
/* ffmpeg_decoder_custom_opus.c (helper-things) */
typedef struct {
@ -685,15 +687,6 @@ ffmpeg_codec_data* init_ffmpeg_mp4_custom_lyn(STREAMFILE* sf, mp4_custom_t* mp4)
#endif
/* coding_utils */
int ffmpeg_fmt_chunk_swap_endian(uint8_t* chunk, size_t chunk_size, uint16_t codec);
int ffmpeg_make_riff_atrac3plus(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int encoder_delay);
int ffmpeg_make_riff_xma1(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int stream_mode);
int ffmpeg_make_riff_xma2(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_count, int block_size);
int ffmpeg_make_riff_xma_from_fmt_chunk(uint8_t* buf, size_t buf_size, off_t fmt_offset, size_t fmt_size, size_t data_size, STREAMFILE* sf, int big_endian);
int ffmpeg_make_riff_xma2_from_xma2_chunk(uint8_t* buf, size_t buf_size, off_t xma2_offset, size_t xma2_size, size_t data_size, STREAMFILE* sf);
int ffmpeg_make_riff_xwma(uint8_t* buf, size_t buf_size, int codec, size_t data_size, int channels, int sample_rate, int avg_bps, int block_align);
/* MS audio format's sample info (struct to avoid passing so much stuff, separate for reusing) */
typedef struct {
/* input */

View File

@ -5,20 +5,14 @@
/**
* Various utils for formats that aren't handled their own decoder or meta
*
* ffmpeg_make_riff_* utils don't depend on FFmpeg, but rather, they make headers that FFmpeg
* can use (it doesn't understand all valid RIFF headers, nor the utils make 100% correct headers).
*/
/* ******************************************** */
/* INTERNAL UTILS */
/* XMA PARSING */
/* ******************************************** */
/**
* read num_bits (up to 25) from a bit offset.
* 25 since we read a 32 bit int, and need to adjust up to 7 bits from the byte-rounded fseek (32-7=25)
*/
/* read num_bits (up to 25) from a bit offset.
* 25 since we read a 32 bit int, and need to adjust up to 7 bits from the byte-rounded fseek (32-7=25) */
static uint32_t read_bitsBE_b(int64_t bit_offset, int num_bits, STREAMFILE* sf) {
uint32_t num, mask;
if (num_bits > 25) return -1; //???
@ -32,377 +26,6 @@ static uint32_t read_bitsBE_b(int64_t bit_offset, int num_bits, STREAMFILE* sf)
}
/* ******************************************** */
/* FAKE RIFF HELPERS */
/* ******************************************** */
/* All helpers copy a RIFF header to buf and returns the number of bytes in buf or -1 when buf is not big enough */
int ffmpeg_make_riff_atrac3plus(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int encoder_delay) {
uint16_t codec_ATRAC3plus = 0xfffe; /* wave format extensible */
size_t riff_size = 4+4+ 4 + 0x3c + 0x14 + 4+4;
if (buf_size < riff_size)
return -1;
memcpy(buf+0x00, "RIFF", 4);
put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */
memcpy(buf+0x08, "WAVE", 4);
memcpy(buf+0x0c, "fmt ", 4);
put_32bitLE(buf+0x10, 0x34);/*fmt size*/
put_16bitLE(buf+0x14, codec_ATRAC3plus);
put_16bitLE(buf+0x16, channels);
put_32bitLE(buf+0x18, sample_rate);
put_32bitLE(buf+0x1c, sample_rate*channels / sizeof(sample)); /* average bytes per second (wrong) */
put_32bitLE(buf+0x20, (int16_t)(block_align)); /* block align */
put_16bitLE(buf+0x24, 0x22); /* extra data size */
put_16bitLE(buf+0x26, 0x0800); /* samples per block */
put_32bitLE(buf+0x28, 0x0000003); /* unknown */
put_32bitBE(buf+0x2c, 0xBFAA23E9); /* GUID1 */
put_32bitBE(buf+0x30, 0x58CB7144); /* GUID2 */
put_32bitBE(buf+0x34, 0xA119FFFA); /* GUID3 */
put_32bitBE(buf+0x38, 0x01E4CE62); /* GUID4 */
put_16bitBE(buf+0x3c, 0x0010); /* unknown */
put_16bitBE(buf+0x3e, 0x0000); /* config */ //todo this varies with block size, but FFmpeg doesn't use it
put_32bitBE(buf+0x40, 0x00000000); /* empty */
put_32bitBE(buf+0x44, 0x00000000); /* empty */
memcpy(buf+0x48, "fact", 4);
put_32bitLE(buf+0x4c, 0x0c); /* fact size */
put_32bitLE(buf+0x50, sample_count);
put_32bitLE(buf+0x54, 0); /* unknown */
put_32bitLE(buf+0x58, encoder_delay);
memcpy(buf+0x5c, "data", 4);
put_32bitLE(buf+0x60, data_size); /* data size */
return riff_size;
}
int ffmpeg_make_riff_xma1(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int stream_mode) {
uint16_t codec_XMA1 = 0x0165;
size_t riff_size;
int streams, i;
/* stream disposition:
* 0: default (ex. 5ch = 2ch + 2ch + 1ch = 3 streams)
* 1: lineal (ex. 5ch = 1ch + 1ch + 1ch + 1ch + 1ch = 5 streams), unusual but exists
* others: not seen (ex. maybe 5ch = 2ch + 1ch + 1ch + 1ch = 4 streams) */
switch(stream_mode) {
case 0 : streams = (channels + 1) / 2; break;
case 1 : streams = channels; break;
default: return 0;
}
riff_size = 4+4+ 4 + 0x14 + 0x14*streams + 4+4;
if (buf_size < riff_size)
return -1;
memcpy(buf+0x00, "RIFF", 4);
put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */
memcpy(buf+0x08, "WAVE", 4);
memcpy(buf+0x0c, "fmt ", 4);
put_32bitLE(buf+0x10, 0xc + 0x14*streams);/*fmt size*/
put_16bitLE(buf+0x14, codec_XMA1);
put_16bitLE(buf+0x16, 16); /* bits per sample */
put_16bitLE(buf+0x18, 0x10D6); /* encoder options */
put_16bitLE(buf+0x1a, 0); /* largest stream skip (wrong, unneeded) */
put_16bitLE(buf+0x1c, streams); /* number of streams */
put_8bit (buf+0x1e, 0); /* loop count */
put_8bit (buf+0x1f, 2); /* version */
for (i = 0; i < streams; i++) {
int stream_channels;
uint32_t speakers;
off_t off = 0x20 + 0x14*i;/* stream riff offset */
if (stream_mode == 1) {
/* lineal */
stream_channels = 1;
switch(i) { /* per stream, values observed */
case 0: speakers = 0x0001; break;/* L */
case 1: speakers = 0x0002; break;/* R */
case 2: speakers = 0x0004; break;/* C */
case 3: speakers = 0x0008; break;/* LFE */
case 4: speakers = 0x0040; break;/* LB */
case 5: speakers = 0x0080; break;/* RB */
case 6: speakers = 0x0000; break;/* ? */
case 7: speakers = 0x0000; break;/* ? */
default: speakers = 0;
}
}
else {
/* with odd channels the last stream is mono */
stream_channels = channels / streams + (channels%2 != 0 && i+1 != streams ? 1 : 0);
switch(i) { /* per stream, values from xmaencode */
case 0: speakers = stream_channels == 1 ? 0x0001 : 0x0201; break;/* L R */
case 1: speakers = stream_channels == 1 ? 0x0004 : 0x0804; break;/* C LFE */
case 2: speakers = stream_channels == 1 ? 0x0040 : 0x8040; break;/* LB RB */
case 3: speakers = stream_channels == 1 ? 0x0000 : 0x0000; break;/* somehow empty (maybe should use 0x2010 LS RS) */
default: speakers = 0;
}
}
put_32bitLE(buf+off+0x00, sample_rate*stream_channels / sizeof(sample)); /* average bytes per second (wrong, unneeded) */
put_32bitLE(buf+off+0x04, sample_rate);
put_32bitLE(buf+off+0x08, 0); /* loop start */
put_32bitLE(buf+off+0x0c, 0); /* loop end */
put_8bit (buf+off+0x10, 0); /* loop subframe */
put_8bit (buf+off+0x11, stream_channels);
put_16bitLE(buf+off+0x12, speakers);
}
/* xmaencode decoding rejects XMA1 without "seek" chunk, though it doesn't seem to use it
* (needs to be have entries but can be bogus, also generates seek for even small sounds) */
memcpy(buf+riff_size-4-4, "data", 4);
put_32bitLE(buf+riff_size-4, data_size); /* data size */
return riff_size;
}
int ffmpeg_make_riff_xma2(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_count, int block_size) {
uint16_t codec_XMA2 = 0x0166;
size_t riff_size = 4+4+ 4 + 0x3c + 4+4;
size_t bytecount;
int streams;
uint32_t speakers;
/* info from xma2defs.h, xact3wb.h and audiodefs.h */
streams = (channels + 1) / 2;
switch (channels) {
case 1: speakers = 0x04; break; /* 1.0: FC */
case 2: speakers = 0x01 | 0x02; break; /* 2.0: FL FR */
case 3: speakers = 0x01 | 0x02 | 0x08; break; /* 2.1: FL FR LF */
case 4: speakers = 0x01 | 0x02 | 0x10 | 0x20; break; /* 4.0: FL FR BL BR */
case 5: speakers = 0x01 | 0x02 | 0x08 | 0x10 | 0x20; break; /* 4.1: FL FR LF BL BR */
case 6: speakers = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20; break; /* 5.1: FL FR FC LF BL BR */
case 7: speakers = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x0100; break; /* 6.1: FL FR FC LF BL BR BC */
case 8: speakers = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80; break; /* 7.1: FL FR FC LF BL BR FLC FRC */
default: speakers = 0; break;
}
if (buf_size < riff_size)
return -1;
bytecount = sample_count * channels * sizeof(sample);
memcpy(buf+0x00, "RIFF", 4);
put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */
memcpy(buf+0x08, "WAVE", 4);
memcpy(buf+0x0c, "fmt ", 4);
put_32bitLE(buf+0x10, 0x34);/*fmt size*/
put_16bitLE(buf+0x14, codec_XMA2);
put_16bitLE(buf+0x16, channels);
put_32bitLE(buf+0x18, sample_rate);
put_32bitLE(buf+0x1c, sample_rate*channels / sizeof(sample)); /* average bytes per second (wrong, unneeded) */
put_16bitLE(buf+0x20, (int16_t)(channels*sizeof(sample))); /* block align */
put_16bitLE(buf+0x22, 16); /* bits per sample */
put_16bitLE(buf+0x24, 0x22); /* extra data size */
put_16bitLE(buf+0x26, streams); /* number of streams */
put_32bitLE(buf+0x28, speakers); /* speaker position */
put_32bitLE(buf+0x2c, bytecount); /* PCM samples */
put_32bitLE(buf+0x30, block_size); /* XMA block size (can be zero, it's for seeking only) */
/* (looping values not set, expected to be handled externally) */
put_32bitLE(buf+0x34, 0); /* play begin */
put_32bitLE(buf+0x38, 0); /* play length */
put_32bitLE(buf+0x3c, 0); /* loop begin */
put_32bitLE(buf+0x40, 0); /* loop length */
put_8bit(buf+0x44, 0); /* loop count */
put_8bit(buf+0x45, 4); /* encoder version */
put_16bitLE(buf+0x46, block_count); /* blocks count (entries in seek table, can be zero) */
memcpy(buf+0x48, "data", 4);
put_32bitLE(buf+0x4c, data_size); /* data size */
return riff_size;
}
/* Makes a XMA1/2 RIFF header for FFmpeg using a "fmt " chunk (XMAWAVEFORMAT or XMA2WAVEFORMATEX) as a base:
* Useful to preserve the stream layout */
int ffmpeg_make_riff_xma_from_fmt_chunk(uint8_t* buf, size_t buf_size, off_t fmt_offset, size_t fmt_size, size_t data_size, STREAMFILE* sf, int big_endian) {
size_t riff_size = 4+4+ 4 + 4+4+fmt_size + 4+4;
uint8_t chunk[0x100];
if (buf_size < riff_size || fmt_size > 0x100)
goto fail;
if (read_streamfile(chunk,fmt_offset,fmt_size, sf) != fmt_size)
goto fail;
if (big_endian) {
int codec = read_16bitBE(fmt_offset,sf);
ffmpeg_fmt_chunk_swap_endian(chunk, fmt_size, codec);
}
memcpy(buf+0x00, "RIFF", 4);
put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */
memcpy(buf+0x08, "WAVE", 4);
memcpy(buf+0x0c, "fmt ", 4);
put_32bitLE(buf+0x10, fmt_size);/*fmt size*/
memcpy(buf+0x14, chunk, fmt_size);
memcpy(buf+0x14+fmt_size, "data", 4);
put_32bitLE(buf+0x14+fmt_size+4, data_size); /* data size */
return riff_size;
fail:
return -1;
}
/* Makes a XMA2 RIFF header for FFmpeg using a "XMA2" chunk (XMA2WAVEFORMAT) as a base.
* Useful to preserve the stream layout */
int ffmpeg_make_riff_xma2_from_xma2_chunk(uint8_t* buf, size_t buf_size, off_t xma2_offset, size_t xma2_size, size_t data_size, STREAMFILE* sf) {
uint8_t chunk[0x100];
size_t riff_size;
riff_size = 4+4+ 4 + 4+4+xma2_size + 4+4;
if (buf_size < riff_size || xma2_size > 0x100)
goto fail;
if (read_streamfile(chunk,xma2_offset,xma2_size, sf) != xma2_size)
goto fail;
memcpy(buf+0x00, "RIFF", 4);
put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */
memcpy(buf+0x08, "WAVE", 4);
memcpy(buf+0x0c, "XMA2", 4);
put_32bitLE(buf+0x10, xma2_size);
memcpy(buf+0x14, chunk, xma2_size);
memcpy(buf+0x14+xma2_size, "data", 4);
put_32bitLE(buf+0x14+xma2_size+4, data_size); /* data size */
return riff_size;
fail:
return -1;
}
int ffmpeg_make_riff_xwma(uint8_t* buf, size_t buf_size, int codec, size_t data_size, int channels, int sample_rate, int avg_bps, int block_align) {
size_t riff_size = 4+4+ 4 + 0x1a + 4+4;
if (buf_size < riff_size)
return -1;
/* XWMA encoder only allows a few channel/sample rate/bitrate combinations,
* but some create identical files with fake bitrate (1ch 22050hz at
* 20/48/192kbps are all 20kbps, with the exact same codec data).
* Decoder needs correct bitrate to work, so it's normalized here. */
/* (may be removed once FFmpeg fixes this) */
if (codec == 0x161) { /* WMAv2 only */
int ch = channels;
int sr = sample_rate;
int br = avg_bps * 8;
/* Must be a bug in MS's encoder, as later versions of xWMAEncode remove these bitrates */
if (ch == 1) {
if (sr == 22050 && (br==48000 || br==192000))
br = 20000;
else if (sr == 32000 && (br==48000 || br==192000))
br = 20000;
else if (sr == 44100 && (br==96000 || br==192000))
br = 48000;
}
else if (ch == 2) {
if (sr == 22050 && (br==48000 || br==192000))
br = 32000;
else if (sr == 32000 && (br==192000))
br = 48000;
}
avg_bps = br / 8;
}
memcpy(buf+0x00, "RIFF", 4);
put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */
memcpy(buf+0x08, "XWMA", 4);
memcpy(buf+0x0c, "fmt ", 4);
put_32bitLE(buf+0x10, 0x12);/*fmt size*/
put_16bitLE(buf+0x14, codec);
put_16bitLE(buf+0x16, channels);
put_32bitLE(buf+0x18, sample_rate);
put_32bitLE(buf+0x1c, avg_bps); /* average bytes per second, somehow vital for XWMA */
put_16bitLE(buf+0x20, block_align); /* block align */
put_16bitLE(buf+0x22, 16); /* bits per sample */
put_16bitLE(buf+0x24, 0); /* extra size */
/* here goes the "dpds" seek table, but it's optional and not needed by FFmpeg (and also buggy) */
memcpy(buf+0x26, "data", 4);
put_32bitLE(buf+0x2a, data_size); /* data size */
return riff_size;
}
int ffmpeg_fmt_chunk_swap_endian(uint8_t* chunk, size_t chunk_size, uint16_t codec) {
int i;
/* swap from LE to BE or the other way around, doesn't matter */
switch(codec) {
case 0x165: { /* XMA1 */
put_16bitLE(chunk + 0x00, get_16bitBE(chunk + 0x00));/*FormatTag*/
put_16bitLE(chunk + 0x02, get_16bitBE(chunk + 0x02));/*BitsPerSample*/
put_16bitLE(chunk + 0x04, get_16bitBE(chunk + 0x04));/*EncodeOptions*/
put_16bitLE(chunk + 0x06, get_16bitBE(chunk + 0x06));/*LargestSkip*/
put_16bitLE(chunk + 0x08, get_16bitBE(chunk + 0x08));/*NumStreams*/
// put_8bit(chunk + 0x0a, get_8bit(chunk + 0x0a));/*LoopCount*/
// put_8bit(chunk + 0x0b, get_8bit(chunk + 0x0b));/*Version*/
for (i = 0xc; i < chunk_size; i += 0x14) { /* reverse endianness for each stream */
put_32bitLE(chunk + i + 0x00, get_32bitBE(chunk + i + 0x00));/*PsuedoBytesPerSec*/
put_32bitLE(chunk + i + 0x04, get_32bitBE(chunk + i + 0x04));/*SampleRate*/
put_32bitLE(chunk + i + 0x08, get_32bitBE(chunk + i + 0x08));/*LoopStart*/
put_32bitLE(chunk + i + 0x0c, get_32bitBE(chunk + i + 0x0c));/*LoopEnd*/
// put_8bit(chunk + i + 0x10, get_8bit(chunk + i + 0x10));/*SubframeData*/
// put_8bit(chunk + i + 0x11, get_8bit(chunk + i + 0x11));/*Channels*/
put_16bitLE(chunk + i + 0x12, get_16bitBE(chunk + i + 0x12));/*ChannelMask*/
}
break;
}
case 0x166: { /* XMA2 */
put_16bitLE(chunk + 0x00, get_16bitBE(chunk + 0x00));/*wFormatTag*/
put_16bitLE(chunk + 0x02, get_16bitBE(chunk + 0x02));/*nChannels*/
put_32bitLE(chunk + 0x04, get_32bitBE(chunk + 0x04));/*nSamplesPerSec*/
put_32bitLE(chunk + 0x08, get_32bitBE(chunk + 0x08));/*nAvgBytesPerSec*/
put_16bitLE(chunk + 0x0c, get_16bitBE(chunk + 0x0c));/*nBlockAlign*/
put_16bitLE(chunk + 0x0e, get_16bitBE(chunk + 0x0e));/*wBitsPerSample*/
put_16bitLE(chunk + 0x10, get_16bitBE(chunk + 0x10));/*cbSize*/
put_16bitLE(chunk + 0x12, get_16bitBE(chunk + 0x12));/*NumStreams*/
put_32bitLE(chunk + 0x14, get_32bitBE(chunk + 0x14));/*ChannelMask*/
put_32bitLE(chunk + 0x18, get_32bitBE(chunk + 0x18));/*SamplesEncoded*/
put_32bitLE(chunk + 0x1c, get_32bitBE(chunk + 0x1c));/*BytesPerBlock*/
put_32bitLE(chunk + 0x20, get_32bitBE(chunk + 0x20));/*PlayBegin*/
put_32bitLE(chunk + 0x24, get_32bitBE(chunk + 0x24));/*PlayLength*/
put_32bitLE(chunk + 0x28, get_32bitBE(chunk + 0x28));/*LoopBegin*/
put_32bitLE(chunk + 0x2c, get_32bitBE(chunk + 0x2c));/*LoopLength*/
/* put_8bit(chunk + 0x30, get_8bit(chunk + 0x30));*//*LoopCount*/
/* put_8bit(chunk + 0x31, get_8bit(chunk + 0x31));*//*EncoderVersion*/
put_16bitLE(chunk + 0x32, get_16bitBE(chunk + 0x32));/*BlockCount*/
break;
}
default:
goto fail;
}
return 1;
fail:
return 0;
}
/* ******************************************** */
/* XMA PARSING */
/* ******************************************** */
static void ms_audio_parse_header(STREAMFILE* sf, int xma_version, int64_t offset_b, int bits_frame_size, size_t *first_frame_b, size_t *packet_skip_count, size_t *header_size_b) {
if (xma_version == 1) { /* XMA1 */
@ -845,7 +468,11 @@ void xma_fix_raw_samples_ch(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t stream_o
}
}
#ifdef VGM_USE_FFMPEG
#if 0
//TODO: ffmpeg now handles internal frame encoder delay, but not correctly in all cases
// without this in most cases should be equivalent as before
//#ifdef VGM_USE_FFMPEG
/* also fix FFmpeg, since we now know exact skips */
{
ffmpeg_codec_data* data = vgmstream->codec_data;
@ -951,18 +578,17 @@ void xma2_parse_xma2_chunk(STREAMFILE* sf, off_t chunk_offset, int* out_channels
int channels, sample_rate, loop_flag, num_samples, loop_start_sample, loop_end_sample;
off_t offset;
xma2_chunk_version = read_8bit(chunk_offset+0x00,sf);
num_streams = read_8bit(chunk_offset+0x01,sf);
xma2_chunk_version = read_u8(chunk_offset+0x00,sf);
num_streams = read_u8(chunk_offset+0x01,sf);
loop_start_sample = read_32bit(chunk_offset+0x04,sf);
loop_end_sample = read_32bit(chunk_offset+0x08,sf);
loop_flag = (uint8_t)read_8bit(chunk_offset+0x03,sf) > 0 || loop_end_sample; /* rarely not set, encoder default */
loop_flag = read_u8(chunk_offset+0x03,sf) > 0 || loop_end_sample; /* rarely not set, encoder default */
sample_rate = read_32bit(chunk_offset+0x0c,sf);
/* may need loop end +1 */
offset = xma2_chunk_version == 3 ? 0x14 : 0x1C;
num_samples = read_32bit(chunk_offset+offset+0x00,sf);
/* pcm_samples in original sample rate (not usable as file may be resampled) */
/* pcm_samples = read_32bitBE(chunk_offset+offset+0x04,sf)*/
//pcm_samples = read_32bitBE(chunk_offset+offset+0x04,sf) /* in original sample rate (not usable as file may be resampled) */
offset = xma2_chunk_version == 3 ? 0x20 : 0x28;
channels = 0; /* channels is the sum of all streams */

View File

@ -389,7 +389,8 @@ ffmpeg_codec_data* init_ffmpeg_header_offset_subsong(STREAMFILE* sf, uint8_t* he
if (data->skip_samples < 0)
data->skip_samples = 0;
#if 0 //LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 64, 100)
#if 0
//LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 64, 100)
/* exposed before but not too reliable either */
else if (stream->start_skip_samples) /* samples to skip in the first packet */
data->skip_samples = stream->start_skip_samples;
@ -404,7 +405,8 @@ ffmpeg_codec_data* init_ffmpeg_header_offset_subsong(STREAMFILE* sf, uint8_t* he
VGM_ASSERT(stream->codecpar->trailing_padding > 0, "FFMPEG: trailing_padding %i\n", (int)stream->codecpar->trailing_padding);
VGM_ASSERT(stream->codecpar->seek_preroll > 0, "FFMPEG: seek_preroll %i\n", (int)stream->codecpar->seek_preroll);//seek delay: OPUS
VGM_ASSERT(stream->start_time > 0, "FFMPEG: start_time %i\n", (int)stream->start_time); //delay
#if 0 //LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 64, 100)
#if 0
//LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 64, 100)
VGM_ASSERT(stream->first_discard_sample > 0, "FFMPEG: first_discard_sample %i\n", (int)stream->first_discard_sample); //padding: MP3
VGM_ASSERT(stream->last_discard_sample > 0, "FFMPEG: last_discard_sample %i\n", (int)stream->last_discard_sample); //padding: MP3
VGM_ASSERT(stream->skip_samples > 0, "FFMPEG: skip_samples %i\n", (int)stream->skip_samples); //delay: MP4

View File

@ -500,11 +500,22 @@ static size_t make_opus_header(uint8_t* buf, int buf_size, opus_config *cfg) {
size_t header_size = 0x13;
int mapping_family = 0;
/* special multichannel config */
/* Opus can't play a Nch file unless the channel mapping is properly configured (not implicit).
* A 8ch file may be 2ch+2ch+1ch+1ch+2ch; this is defined with a "channel mapping":
* - mapping family:
* 0 = standard (single stream mono/stereo, >2ch = error, and table MUST be ommited)
* 1 = standard multichannel (1..8ch), using Vorbis channel layout (needs table)
* 255 = undefined (1..255ch) application defined (needs table)
* - mapping table:
* - stream count: internal opus streams (>= 1), of 1/2ch
* - coupled count: internal stereo streams (<= streams)
* - mappings: one byte per channel with the channel position (0..Nch), or 255 (silence)
*/
/* set mapping family */
if (cfg->channels > 2 || cfg->stream_count > 1) {
/* channel config: 0=standard (single stream mono/stereo), 1=vorbis, 255: not defined */
mapping_family = 1;
header_size += 0x01+0x01+cfg->channels;
mapping_family = 1; //todo test 255
header_size += 0x01 + 0x01 + cfg->channels; /* table size */
}
if (cfg->skip < 0) {
@ -526,14 +537,15 @@ static size_t make_opus_header(uint8_t* buf, int buf_size, opus_config *cfg) {
put_u16le(buf+0x10, 0); /* output gain */
put_u8 (buf+0x12, mapping_family);
/* set mapping table */
if (mapping_family > 0) {
int i;
/* internal mono/stereo streams (N mono/stereo streams that make M channels) */
/* total streams (mono/stereo) */
put_u8(buf+0x13, cfg->stream_count);
/* joint stereo streams (rest would be mono, so 6ch can be 2ch+2ch+1ch+1ch = 2 coupled in 4 streams */
/* stereo streams (6ch can be 2ch+2ch+1ch+1ch = 2 coupled in 4 streams) */
put_u8(buf+0x14, cfg->coupled_count);
/* mapping per channel (order of channels, ex: 0x000104050203) */
/* mapping per channel (order of channels, ex: 00 01 04 05 02 03) */
for (i = 0; i < cfg->channels; i++) {
put_u8(buf+0x15+i, cfg->channel_mapping[i]);
}

View File

@ -2,47 +2,49 @@
#ifdef VGM_USE_FFMPEG
/* Helper inits for FFmpeg's codecs. RIFF utils make headers for FFmpeg (it doesn't understand all valid RIFF headers,
* nor the utils make 100% correct headers). */
static int ffmpeg_make_riff_atrac3(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int joint_stereo, int encoder_delay) {
uint16_t codec_ATRAC3 = 0x0270;
size_t riff_size = 4+4+ 4 + 0x28 + 0x10 + 4+4;
if (buf_size < riff_size)
return -1;
int buf_max = (0x04 * 2 + 0x04) + (0x04 * 2 + 0x20) + (0x04 * 2 + 0x08) + (0x04 * 2);
if (buf_max > buf_size)
return 0;
memcpy(buf+0x00, "RIFF", 4);
put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */
memcpy(buf+0x08, "WAVE", 4);
memcpy (buf+0x00, "RIFF", 0x04);
put_u32le(buf+0x04, buf_max - (0x04 * 2) + data_size); /* riff size */
memcpy (buf+0x08, "WAVE", 0x04);
memcpy(buf+0x0c, "fmt ", 4);
put_32bitLE(buf+0x10, 0x20);/*fmt size*/
put_16bitLE(buf+0x14, codec_ATRAC3);
put_16bitLE(buf+0x16, channels);
put_32bitLE(buf+0x18, sample_rate);
put_32bitLE(buf+0x1c, sample_rate*channels / sizeof(sample)); /* average bytes per second (wrong) */
put_32bitLE(buf+0x20, (int16_t)(block_align)); /* block align */
memcpy (buf+0x0c, "fmt ", 0x04);
put_u32le(buf+0x10, 0x20); /* fmt size */
put_u16le(buf+0x14, 0x0270); /* ATRAC3 codec */
put_u16le(buf+0x16, channels);
put_u32le(buf+0x18, sample_rate);
put_u32le(buf+0x1c, sample_rate * channels / sizeof(sample)); /* average bytes per second (wrong) */
put_u16le(buf+0x20, block_align); /* block align */
put_16bitLE(buf+0x24, 0x0e); /* extra data size */
put_16bitLE(buf+0x26, 1); /* unknown, always 1 */
put_16bitLE(buf+0x28, 0x0800 * channels); /* unknown (some size? 0x1000=2ch, 0x0800=1ch) */
put_16bitLE(buf+0x2a, 0); /* unknown, always 0 */
put_16bitLE(buf+0x2c, joint_stereo ? 0x0001 : 0x0000);
put_16bitLE(buf+0x2e, joint_stereo ? 0x0001 : 0x0000); /* repeated? */
put_16bitLE(buf+0x30, 1); /* unknown, always 1 (frame_factor?) */
put_16bitLE(buf+0x32, 0); /* unknown, always 0 */
put_u16le(buf+0x24, 0x0e); /* extra data size */
put_u16le(buf+0x26, 1); /* unknown, always 1 */
put_u16le(buf+0x28, 0x0800 * channels); /* unknown (some size? 0x1000=2ch, 0x0800=1ch) */
put_u16le(buf+0x2a, 0); /* unknown, always 0 */
put_u16le(buf+0x2c, joint_stereo ? 0x0001 : 0x0000);
put_u16le(buf+0x2e, joint_stereo ? 0x0001 : 0x0000); /* repeated? */
put_u16le(buf+0x30, 1); /* unknown, always 1 (frame_factor?) */
put_u16le(buf+0x32, 0); /* unknown, always 0 */
memcpy(buf+0x34, "fact", 4);
put_32bitLE(buf+0x38, 0x8); /* fact size */
put_32bitLE(buf+0x3c, sample_count);
put_32bitLE(buf+0x40, encoder_delay);
memcpy (buf+0x34, "fact", 0x04);
put_u32le(buf+0x38, 0x08); /* fact size */
put_u32le(buf+0x3c, sample_count);
put_u32le(buf+0x40, encoder_delay);
memcpy(buf+0x44, "data", 4);
put_32bitLE(buf+0x48, data_size); /* data size */
memcpy (buf+0x44, "data", 0x04);
put_u32le(buf+0x48, data_size); /* data size */
return riff_size;
return buf_max;
}
ffmpeg_codec_data* init_ffmpeg_atrac3_raw(STREAMFILE* sf, off_t offset, size_t data_size, int sample_count, int channels, int sample_rate, int block_align, int encoder_delay) {
ffmpeg_codec_data *ffmpeg_data = NULL;
ffmpeg_codec_data* data = NULL;
uint8_t buf[0x100];
int bytes;
int joint_stereo = (block_align == 0x60*channels) && channels > 1; /* only lowest block size does joint stereo */
@ -50,8 +52,8 @@ ffmpeg_codec_data* init_ffmpeg_atrac3_raw(STREAMFILE* sf, off_t offset, size_t d
/* create fake header + init ffmpeg + apply fixes to FFmpeg decoding */
bytes = ffmpeg_make_riff_atrac3(buf,sizeof(buf), sample_count, data_size, channels, sample_rate, block_align, joint_stereo, encoder_delay);
ffmpeg_data = init_ffmpeg_header_offset(sf, buf,bytes, offset,data_size);
if (!ffmpeg_data) goto fail;
data = init_ffmpeg_header_offset(sf, buf,bytes, offset,data_size);
if (!data) goto fail;
/* unlike with RIFF ATRAC3 we don't set implicit delay, as raw ATRAC3 headers often give loop/samples
* in offsets, so calcs are expected to be handled externally (presumably the game would call raw decoding API
@ -59,23 +61,23 @@ ffmpeg_codec_data* init_ffmpeg_atrac3_raw(STREAMFILE* sf, off_t offset, size_t d
/* encoder delay: encoder introduces some garbage (not always silent) samples to skip at the beginning (at least 1 frame)
* FFmpeg doesn't set this, and even if it ever does it's probably better to force it for the implicit skip. */
ffmpeg_set_skip_samples(ffmpeg_data, encoder_delay);
ffmpeg_set_skip_samples(data, encoder_delay);
//ffmpeg_set_samples(sample_count); /* useful? */
/* invert ATRAC3: waveform is inverted vs official tools (not noticeable but for accuracy) */
if (is_at3) {
ffmpeg_set_invert_floats(ffmpeg_data);
ffmpeg_set_invert_floats(data);
}
return ffmpeg_data;
return data;
fail:
free_ffmpeg(ffmpeg_data);
free_ffmpeg(data);
return NULL;
}
/* init ATRAC3/plus while adding some fixes */
ffmpeg_codec_data* init_ffmpeg_atrac3_riff(STREAMFILE* sf, off_t offset, int* p_samples) {
ffmpeg_codec_data *ffmpeg_data = NULL;
ffmpeg_codec_data* data = NULL;
int is_at3 = 0, is_at3p = 0, codec;
size_t riff_size;
int fact_samples, skip_samples, implicit_skip;
@ -84,11 +86,11 @@ ffmpeg_codec_data* init_ffmpeg_atrac3_riff(STREAMFILE* sf, off_t offset, int* p_
/* some simplified checks just in case */
if (read_32bitBE(offset + 0x00,sf) != 0x52494646) /* "RIFF" */
if (!is_id32be(offset + 0x00,sf, "RIFF"))
goto fail;
riff_size = read_32bitLE(offset + 0x04,sf) + 0x08;
codec = (uint16_t)read_16bitLE(offset + 0x14, sf);
riff_size = read_u32le(offset + 0x04,sf) + 0x08;
codec = read_u16le(offset + 0x14, sf);
switch(codec) {
case 0x0270: is_at3 = 1; break;
case 0xFFFE: is_at3p = 1; break;
@ -98,20 +100,20 @@ ffmpeg_codec_data* init_ffmpeg_atrac3_riff(STREAMFILE* sf, off_t offset, int* p_
/* init ffmpeg + apply fixes to FFmpeg decoding (with these fixes should be
* sample-accurate vs official tools, except usual +-1 float-to-pcm conversion) */
ffmpeg_data = init_ffmpeg_offset(sf, offset, riff_size);
if (!ffmpeg_data) goto fail;
data = init_ffmpeg_offset(sf, offset, riff_size);
if (!data) goto fail;
/* well behaved .at3 define "fact" but official tools accept files without it */
if (find_chunk_le(sf,0x66616374,offset + 0x0c,0, &fact_offset, &fact_size)) { /* "fact" */
if (find_chunk_le(sf, get_id32be("fact"), offset + 0x0c,0, &fact_offset, &fact_size)) {
if (fact_size == 0x08) { /* early AT3 (mainly PSP games) */
fact_samples = read_32bitLE(fact_offset + 0x00, sf);
skip_samples = read_32bitLE(fact_offset + 0x04, sf); /* base skip samples */
fact_samples = read_s32le(fact_offset + 0x00, sf);
skip_samples = read_s32le(fact_offset + 0x04, sf); /* base skip samples */
}
else if (fact_size == 0x0c) { /* late AT3 (mainly PS3 games and few PSP games) */
fact_samples = read_32bitLE(fact_offset + 0x00, sf);
fact_samples = read_s32le(fact_offset + 0x00, sf);
/* 0x04: base skip samples, ignored by decoder */
skip_samples = read_32bitLE(fact_offset + 0x08, sf); /* skip samples with implicit skip of 184 added */
skip_samples = read_s32le(fact_offset + 0x08, sf); /* skip samples with implicit skip of 184 added */
}
else {
VGM_LOG("ATRAC3: unknown fact size\n");
@ -137,7 +139,7 @@ ffmpeg_codec_data* init_ffmpeg_atrac3_riff(STREAMFILE* sf, off_t offset, int* p_
implicit_skip = 69;
}
else if (is_at3p && fact_size == 0x08) {
implicit_skip = 184*2;
implicit_skip = 184 * 2;
}
else if (is_at3p && fact_size == 0x0c) {
implicit_skip = 184; /* first 184 is already added to delay vs field at 0x08 */
@ -151,38 +153,112 @@ ffmpeg_codec_data* init_ffmpeg_atrac3_riff(STREAMFILE* sf, off_t offset, int* p_
/* encoder delay: encoder introduces some garbage (not always silent) samples to skip at the beginning (at least 1 frame)
* FFmpeg doesn't set this, and even if it ever does it's probably better to force it for the implicit skip. */
ffmpeg_set_skip_samples(ffmpeg_data, skip_samples + implicit_skip);
ffmpeg_set_skip_samples(data, skip_samples + implicit_skip);
//ffmpeg_set_samples(sample_count); /* useful? */
/* invert ATRAC3: waveform is inverted vs official tools (not noticeable but for accuracy) */
if (is_at3) {
ffmpeg_set_invert_floats(ffmpeg_data);
ffmpeg_set_invert_floats(data);
}
/* multichannel fix: LFE channel should be reordered on decode (ATRAC3Plus only, only 1/2/6/8ch exist):
* - 6ch: FL FR FC BL BR LFE > FL FR FC LFE BL BR
* - 8ch: FL FR FC BL BR SL SR LFE > FL FR FC LFE BL BR SL SR */
if (is_at3p && ffmpeg_get_channels(ffmpeg_data) == 6) {
if (is_at3p && ffmpeg_get_channels(data) == 6) {
/* LFE BR BL > LFE BL BR > same */
int channel_remap[] = { 0, 1, 2, 5, 5, 5, };
ffmpeg_set_channel_remapping(ffmpeg_data, channel_remap);
ffmpeg_set_channel_remapping(data, channel_remap);
}
else if (is_at3p && ffmpeg_get_channels(ffmpeg_data) == 8) {
else if (is_at3p && ffmpeg_get_channels(data) == 8) {
/* LFE BR SL SR BL > LFE BL SL SR BR > LFE BL BR SR SL > LFE BL BR SL SR > same */
int channel_remap[] = { 0, 1, 2, 7, 7, 7, 7, 7};
ffmpeg_set_channel_remapping(ffmpeg_data, channel_remap);
ffmpeg_set_channel_remapping(data, channel_remap);
}
if (p_samples)
*p_samples = fact_samples;
return ffmpeg_data;
return data;
fail:
free_ffmpeg(ffmpeg_data);
free_ffmpeg(data);
return NULL;
}
static int ffmpeg_make_riff_atrac3plus(uint8_t* buf, int buf_size, uint32_t data_size, int32_t sample_count, int channels, int sample_rate, int block_align, int encoder_delay) {
int buf_max = (0x04 * 2 + 0x04) + (0x04 * 2 + 0x34) + (0x04 * 2 + 0x0c) + (0x04 * 2);
if (buf_max > buf_size)
return 0;
/* standard */
int channel_layout = 0;
switch(channels) {
case 1: channel_layout = mapping_MONO; break;
case 2: channel_layout = mapping_STEREO; break;
case 3: channel_layout = mapping_2POINT1; break;
case 4: channel_layout = mapping_QUAD; break;
case 5: channel_layout = mapping_5POINT0; break;
case 6: channel_layout = mapping_5POINT1; break;
default: break;
}
memcpy (buf+0x00, "RIFF", 0x04);
put_u32le(buf+0x04, buf_max - (0x04 * 2) + data_size);
memcpy (buf+0x08, "WAVE", 0x04);
memcpy (buf+0x0c, "fmt ", 0x04);
put_u32le(buf+0x10, 0x34);
put_u16le(buf+0x14, 0xfffe); /* WAVEFORMATEXTENSIBLE */
put_u16le(buf+0x16, channels);
put_u32le(buf+0x18, sample_rate);
put_u32le(buf+0x1c, sample_rate * channels / sizeof(sample)); /* average bytes per second (wrong) */
put_u32le(buf+0x20, block_align); /* block align */
put_u16le(buf+0x24, 0x22); /* extra data size */
put_u16le(buf+0x26, 0x0800); /* samples per block */
put_u32le(buf+0x28, channel_layout);
put_u32be(buf+0x2c, 0xBFAA23E9); /* GUID1 */
put_u32be(buf+0x30, 0x58CB7144); /* GUID2 */
put_u32be(buf+0x34, 0xA119FFFA); /* GUID3 */
put_u32be(buf+0x38, 0x01E4CE62); /* GUID4 */
put_u16be(buf+0x3c, 0x0010); /* unknown */
put_u16be(buf+0x3e, 0x0000); /* unknown, atrac3plus config (varies with block size, FFmpeg doesn't use it) */
put_u32be(buf+0x40, 0x00000000); /* reserved? */
put_u32be(buf+0x44, 0x00000000); /* reserved? */
memcpy (buf+0x48, "fact", 0x04);
put_u32le(buf+0x4c, 0x0c); /* fact size */
put_u32le(buf+0x50, sample_count);
put_u32le(buf+0x54, 0); /* unknown */
put_u32le(buf+0x58, encoder_delay);
memcpy (buf+0x5c, "data", 0x04);
put_u32le(buf+0x60, data_size); /* data size */
return buf_max;
}
ffmpeg_codec_data* init_ffmpeg_atrac3plus_raw(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int32_t sample_count, int channels, int sample_rate, int block_align, int encoder_delay) {
ffmpeg_codec_data* data = NULL;
uint8_t buf[0x100];
int bytes;
bytes = ffmpeg_make_riff_atrac3plus(buf,sizeof(buf), data_size, sample_count, channels, sample_rate, block_align, encoder_delay);
data = init_ffmpeg_header_offset(sf, buf, bytes, data_offset, data_size);
if (!data) goto fail;
ffmpeg_set_skip_samples(data, encoder_delay);
return data;
fail:
free_ffmpeg(data);
return NULL;
}
ffmpeg_codec_data* init_ffmpeg_aac(STREAMFILE* sf, off_t offset, size_t size, int skip_samples) {
ffmpeg_codec_data* data = NULL;
@ -203,34 +279,366 @@ fail:
return NULL;
}
//TODO: make init_ffmpeg_xwma_fmt(be) too to pass fmt chunk
static int ffmpeg_make_riff_xwma(uint8_t* buf, size_t buf_size, uint32_t data_size, int format, int channels, int sample_rate, int avg_bps, int block_align) {
int buf_max = (0x04 * 2 + 0x04) + (0x04 * 2 + 0x12) + (0x04 * 2);
if (buf_max > buf_size)
return 0;
/* XWMA encoder only allows a few channel/sample rate/bitrate combinations,
* but some create identical files with fake bitrate (1ch 22050hz at
* 20/48/192kbps are all 20kbps, with the exact same codec data).
* Decoder needs correct bitrate to work, so it's normalized here. */
/* (may be removed once FFmpeg fixes this) */
if (format == 0x161) { /* WMAv2 only */
int ch = channels;
int sr = sample_rate;
int br = avg_bps * 8;
/* Must be a bug in MS's encoder, as later versions of xWMAEncode remove these bitrates */
if (ch == 1) {
if (sr == 22050 && (br==48000 || br==192000)) {
br = 20000;
}
else if (sr == 32000 && (br==48000 || br==192000))
br = 20000;
else if (sr == 44100 && (br==96000 || br==192000))
br = 48000;
}
else if (ch == 2) {
if (sr == 22050 && (br==48000 || br==192000))
br = 32000;
else if (sr == 32000 && (br==192000))
br = 48000;
}
avg_bps = br / 8;
}
memcpy (buf+0x00, "RIFF", 0x04);
put_u32le(buf+0x04, buf_max - (0x04 * 2) + data_size); /* riff size */
memcpy (buf+0x08, "XWMA", 0x04);
memcpy (buf+0x0c, "fmt ", 0x04);
put_u32le(buf+0x10, 0x12); /* fmt size */
put_u16le(buf+0x14, format);
put_u16le(buf+0x16, channels);
put_u32le(buf+0x18, sample_rate);
put_u32le(buf+0x1c, avg_bps); /* average bytes per second, somehow vital for XWMA */
put_u16le(buf+0x20, block_align); /* block align */
put_u16le(buf+0x22, 16); /* bits per sample */
put_u16le(buf+0x24, 0); /* extra size */
/* here goes the "dpds" seek table, but it's optional and not needed by FFmpeg (and also buggy) */
memcpy (buf+0x26, "data", 4);
put_u32le(buf+0x2a, data_size);
return buf_max;
}
ffmpeg_codec_data* init_ffmpeg_xwma(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int format, int channels, int sample_rate, int avg_bitrate, int block_size) {
ffmpeg_codec_data* data = NULL;
uint8_t buf[0x100];
int bytes;
bytes = ffmpeg_make_riff_xwma(buf, sizeof(buf), format, data_size, channels, sample_rate, avg_bitrate, block_size);
bytes = ffmpeg_make_riff_xwma(buf, sizeof(buf), data_size, format, channels, sample_rate, avg_bitrate, block_size);
data = init_ffmpeg_header_offset(sf, buf,bytes, data_offset, data_size);
if (!data) goto fail;
if (format == 0x161) {
int skip_samples = 0;
return data;
fail:
free_ffmpeg(data);
return NULL;
}
/* Skip WMA encoder delay, not specified in the flags or containers (ASF/XWMA),
* but verified compared to Microsoft's output. Seems to match frame_samples * 2 */
if (sample_rate >= 32000)
skip_samples = 4096;
else if (sample_rate >= 22050)
skip_samples = 2048;
else if (sample_rate >= 8000)
skip_samples = 1024;
ffmpeg_set_skip_samples(data, skip_samples);
static int ffmpeg_make_riff_xma1(uint8_t* buf, size_t buf_size, size_t data_size, int channels, int sample_rate, int stream_mode) {
/* stream disposition:
* 0: default (ex. 5ch = 2ch + 2ch + 1ch = 3 streams)
* 1: lineal (ex. 5ch = 1ch + 1ch + 1ch + 1ch + 1ch = 5 streams), unusual but exists
* others: not seen (ex. maybe 5ch = 2ch + 1ch + 1ch + 1ch = 4 streams) */
int streams;
switch(stream_mode) {
case 0 : streams = (channels + 1) / 2; break;
case 1 : streams = channels; break;
default: return 0;
}
//TODO WMAPro uses variable skips and is more complex
//TODO ffmpeg's WMA doesn't properly output trailing samples (ignored patch...)
int buf_max = (0x04 * 2 + 0x4) + (0x04 * 2 + 0x0c + 0x14 * streams) + (0x04 * 2);
if (buf_max > buf_size)
return 0;
memcpy (buf+0x00, "RIFF", 0x04);
put_u32le(buf+0x04, buf_max - (0x04 * 2) + data_size); /* riff size */
memcpy (buf+0x08, "WAVE", 0x04);
memcpy (buf+0x0c, "fmt ", 0x04);
put_u32le(buf+0x10, 0x0c + 0x14 * streams); /* fmt size */
put_u16le(buf+0x14, 0x0165); /* XMA1 */
put_u16le(buf+0x16, 16); /* bits per sample */
put_u16le(buf+0x18, 0x10D6); /* encoder options */
put_u16le(buf+0x1a, 0); /* largest stream skip (wrong, unneeded) */
put_u16le(buf+0x1c, streams); /* number of streams */
put_u8 (buf+0x1e, 0); /* loop count */
put_u8 (buf+0x1f, 2); /* version */
for (int i = 0; i < streams; i++) {
int stream_channels;
uint32_t speakers;
off_t off = 0x20 + 0x14 * i; /* stream riff offset */
if (stream_mode == 1) {
/* lineal */
stream_channels = 1;
switch(i) { /* per stream, values observed */
case 0: speakers = 0x0001; break;/* L */
case 1: speakers = 0x0002; break;/* R */
case 2: speakers = 0x0004; break;/* C */
case 3: speakers = 0x0008; break;/* LFE */
case 4: speakers = 0x0040; break;/* LB */
case 5: speakers = 0x0080; break;/* RB */
case 6: speakers = 0x0000; break;/* ? */
case 7: speakers = 0x0000; break;/* ? */
default: speakers = 0;
}
}
else {
/* with odd channels the last stream is mono */
stream_channels = channels / streams + (channels%2 != 0 && i+1 != streams ? 1 : 0);
switch(i) { /* per stream, values from xmaencode */
case 0: speakers = stream_channels == 1 ? 0x0001 : 0x0201; break;/* L R */
case 1: speakers = stream_channels == 1 ? 0x0004 : 0x0804; break;/* C LFE */
case 2: speakers = stream_channels == 1 ? 0x0040 : 0x8040; break;/* LB RB */
case 3: speakers = stream_channels == 1 ? 0x0000 : 0x0000; break;/* somehow empty (maybe should use 0x2010 LS RS) */
default: speakers = 0;
}
}
put_u32le(buf+off+0x00, sample_rate*stream_channels / sizeof(sample)); /* average bytes per second (wrong, unneeded) */
put_u32le(buf+off+0x04, sample_rate);
put_u32le(buf+off+0x08, 0); /* loop start */
put_u32le(buf+off+0x0c, 0); /* loop end */
put_u8 (buf+off+0x10, 0); /* loop subframe */
put_u8 (buf+off+0x11, stream_channels);
put_u16le(buf+off+0x12, speakers);
}
/* xmaencode decoding rejects XMA1 without "seek" chunk, though it doesn't seem to use it
* (needs to be have entries but can be bogus, also generates seek for even small sounds) */
memcpy (buf + buf_max - (0x04 * 2), "data", 0x04);
put_u32le(buf + buf_max - (0x04 * 1), data_size);
return buf_max;
}
ffmpeg_codec_data* init_ffmpeg_xma1_raw(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int channels, int sample_rate, int stream_mode) {
ffmpeg_codec_data* data = NULL;
uint8_t buf[0x100];
int bytes;
bytes = ffmpeg_make_riff_xma1(buf, sizeof(buf), data_size, channels, sample_rate, stream_mode);
data = init_ffmpeg_header_offset(sf, buf, bytes, data_offset, data_size);
if (!data) goto fail;
/* n5.1.2 XMA1 hangs on seeks near end (infinite loop), presumably due to missing flush in wmapro.c's ff_xma1_decoder + frame skip samples */
ffmpeg_set_force_seek(data);
return data;
fail:
free_ffmpeg(data);
return NULL;
}
static int ffmpeg_make_riff_xma2(uint8_t* buf, size_t buf_size, size_t data_size, int32_t sample_count, int channels, int sample_rate, int block_size, int block_count) {
size_t bytecount;
int streams;
uint32_t speakers;
int buf_max = (0x04 * 2 + 0x04) + (0x04 * 2 + 0x34) + (0x04 * 2);
if (buf_max > buf_size)
return 0;
/* info from xma2defs.h, xact3wb.h and audiodefs.h */
streams = (channels + 1) / 2;
switch (channels) {
case 1: speakers = 0x04; break; /* 1.0: FC */
case 2: speakers = 0x01 | 0x02; break; /* 2.0: FL FR */
case 3: speakers = 0x01 | 0x02 | 0x08; break; /* 2.1: FL FR LF */
case 4: speakers = 0x01 | 0x02 | 0x10 | 0x20; break; /* 4.0: FL FR BL BR */
case 5: speakers = 0x01 | 0x02 | 0x08 | 0x10 | 0x20; break; /* 4.1: FL FR LF BL BR */
case 6: speakers = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20; break; /* 5.1: FL FR FC LF BL BR */
case 7: speakers = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x100; break; /* 6.1: FL FR FC LF BL BR BC */
case 8: speakers = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80; break; /* 7.1: FL FR FC LF BL BR FLC FRC */
default: speakers = 0; break;
}
bytecount = sample_count * channels * sizeof(sample);
memcpy (buf+0x00, "RIFF", 0x04);
put_u32le(buf+0x04, buf_max - (0x04 * 2) + data_size); /* riff size */
memcpy (buf+0x08, "WAVE", 0x04);
memcpy (buf+0x0c, "fmt ", 0x04);
put_u32le(buf+0x10, 0x34); /* fmt size */
put_u16le(buf+0x14, 0x0166); /* XMA2 */
put_u16le(buf+0x16, channels);
put_u32le(buf+0x18, sample_rate);
put_u32le(buf+0x1c, sample_rate * channels / sizeof(sample)); /* average bytes per second (wrong, unneeded) */
put_u16le(buf+0x20, (uint16_t)(channels * sizeof(sample))); /* block align */
put_u16le(buf+0x22, 16); /* bits per sample */
put_u16le(buf+0x24, 0x22); /* extra data size */
put_u16le(buf+0x26, streams); /* number of streams */
put_u32le(buf+0x28, speakers); /* speaker position */
put_u32le(buf+0x2c, bytecount); /* PCM samples */
put_u32le(buf+0x30, block_size); /* XMA block size (can be zero, for seeking only) */
/* (looping values not set, expected to be handled externally) */
put_u32le(buf+0x34, 0); /* play begin */
put_u32le(buf+0x38, 0); /* play length */
put_u32le(buf+0x3c, 0); /* loop begin */
put_u32le(buf+0x40, 0); /* loop length */
put_u8 (buf+0x44, 0); /* loop count */
put_u8 (buf+0x45, 4); /* encoder version */
put_u16le(buf+0x46, block_count); /* blocks count (entries in seek table, can be zero) */
memcpy (buf+0x48, "data", 0x04);
put_u32le(buf+0x4c, data_size); /* data size */
return buf_max;
}
ffmpeg_codec_data* init_ffmpeg_xma2_raw(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int32_t sample_count, int channels, int sample_rate, int block_size, int block_count) {
ffmpeg_codec_data* data = NULL;
uint8_t buf[0x100];
int bytes;
/* seemingly not needed but just in case */
if (block_size <= 0)
block_size = 0x8000; /* default */
if (block_count <= 0)
block_count = (data_size / block_size) + (data_size % block_size != 0 ? 1 : 0); /* approx */
bytes = ffmpeg_make_riff_xma2(buf, sizeof(buf), data_size, sample_count, channels, sample_rate, block_size, block_count);
data = init_ffmpeg_header_offset(sf, buf, bytes, data_offset, data_size);
if (!data) goto fail;
return data;
fail:
free_ffmpeg(data);
return NULL;
}
/* swap from LE to BE or the other way around */
static int ffmpeg_fmt_chunk_swap_endian(uint8_t* chunk, uint32_t chunk_size, uint16_t codec) {
int i;
switch(codec) {
case 0x6501:
case 0x0165: /* XMA1 */
put_u16le(chunk + 0x00, get_u16be(chunk + 0x00)); /*FormatTag*/
put_u16le(chunk + 0x02, get_u16be(chunk + 0x02)); /*BitsPerSample*/
put_u16le(chunk + 0x04, get_u16be(chunk + 0x04)); /*EncodeOptions*/
put_u16le(chunk + 0x06, get_u16be(chunk + 0x06)); /*LargestSkip*/
put_u16le(chunk + 0x08, get_u16be(chunk + 0x08)); /*NumStreams*/
// put_u8(chunk + 0x0a, get_u8(chunk + 0x0a)); /*LoopCount*/
// put_u8(chunk + 0x0b, get_u8(chunk + 0x0b)); /*Version*/
for (i = 0xc; i < chunk_size; i += 0x14) { /* reverse endianness for each stream */
put_u32le(chunk + i + 0x00, get_u32be(chunk + i + 0x00)); /*PsuedoBytesPerSec*/
put_u32le(chunk + i + 0x04, get_u32be(chunk + i + 0x04)); /*SampleRate*/
put_u32le(chunk + i + 0x08, get_u32be(chunk + i + 0x08)); /*LoopStart*/
put_u32le(chunk + i + 0x0c, get_u32be(chunk + i + 0x0c)); /*LoopEnd*/
// put_u8(chunk + i + 0x10, get_u8(chunk + i + 0x10)); /*SubframeData*/
// put_u8(chunk + i + 0x11, get_u8(chunk + i + 0x11)); /*Channels*/
put_u16le(chunk + i + 0x12, get_u16be(chunk + i + 0x12)); /*ChannelMask*/
}
break;
case 0x6601:
case 0x0166: /* XMA2 */
put_u16le(chunk + 0x00, get_u16be(chunk + 0x00)); /*wFormatTag*/
put_u16le(chunk + 0x02, get_u16be(chunk + 0x02)); /*nChannels*/
put_u32le(chunk + 0x04, get_u32be(chunk + 0x04)); /*nSamplesPerSec*/
put_u32le(chunk + 0x08, get_u32be(chunk + 0x08)); /*nAvgBytesPerSec*/
put_u16le(chunk + 0x0c, get_u16be(chunk + 0x0c)); /*nBlockAlign*/
put_u16le(chunk + 0x0e, get_u16be(chunk + 0x0e)); /*wBitsPerSample*/
put_u16le(chunk + 0x10, get_u16be(chunk + 0x10)); /*cbSize*/
put_u16le(chunk + 0x12, get_u16be(chunk + 0x12)); /*NumStreams*/
put_u32le(chunk + 0x14, get_u32be(chunk + 0x14)); /*ChannelMask*/
put_u32le(chunk + 0x18, get_u32be(chunk + 0x18)); /*SamplesEncoded*/
put_u32le(chunk + 0x1c, get_u32be(chunk + 0x1c)); /*BytesPerBlock*/
put_u32le(chunk + 0x20, get_u32be(chunk + 0x20)); /*PlayBegin*/
put_u32le(chunk + 0x24, get_u32be(chunk + 0x24)); /*PlayLength*/
put_u32le(chunk + 0x28, get_u32be(chunk + 0x28)); /*LoopBegin*/
put_u32le(chunk + 0x2c, get_u32be(chunk + 0x2c)); /*LoopLength*/
// put_u8(chunk + 0x30, get_u8(chunk + 0x30)); /*LoopCount*/
// put_u8(chunk + 0x31, get_u8(chunk + 0x31)); /*EncoderVersion*/
put_u16le(chunk + 0x32, get_u16be(chunk + 0x32)); /*BlockCount*/
break;
default:
goto fail;
}
return 1;
fail:
return 0;
}
/* Makes a XMA1/2 RIFF header using a "fmt " chunk (XMAWAVEFORMAT/XMA2WAVEFORMATEX) or "XMA2" chunk (XMA2WAVEFORMAT), as a base:
* Useful to preserve the stream layout */
static int ffmpeg_make_riff_xma_chunk(STREAMFILE* sf, uint8_t* buf, int buf_size, uint32_t data_size, uint32_t chunk_offset, uint32_t chunk_size, int* p_is_xma1) {
int buf_max = (0x04 * 2 + 0x04) + (0x04 * 2 + chunk_size) + (0x04 * 2);
if (buf_max > buf_size)
return 0;
if (read_streamfile(buf+0x14, chunk_offset, chunk_size, sf) != chunk_size)
return 0;
/* checks info from the chunk itself */
int is_xma1 = 0;
int is_xma2_old = buf[0x14] == 0x03 || buf[0x14] == 0x04;
if (!is_xma2_old) {
uint16_t codec = get_u16le(buf+0x14);
int is_be = (codec > 0x1000);
if (is_be)
ffmpeg_fmt_chunk_swap_endian(buf+0x14, chunk_size, codec);
is_xma1 = codec == 0x0165 || codec == 0x6501;
}
memcpy (buf+0x00, "RIFF", 0x04);
put_u32le(buf+0x04, buf_max - (0x04 * 2)+ data_size); /* riff size */
memcpy (buf+0x08, "WAVE", 0x04);
memcpy (buf+0x0c, is_xma2_old ? "XMA2" : "fmt ", 0x04);
put_u32le(buf+0x10, chunk_size);
/* copied chunk in between */
memcpy (buf+0x14 + chunk_size + 0x00, "data", 0x04);
put_u32le(buf+0x14 + chunk_size + 0x04, data_size);
*p_is_xma1 = is_xma1;
return buf_max;
}
ffmpeg_codec_data* init_ffmpeg_xma_chunk(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, uint32_t chunk_offset, uint32_t chunk_size) {
return init_ffmpeg_xma_chunk_split(sf, sf, data_offset, data_size, chunk_offset, chunk_size);
}
ffmpeg_codec_data* init_ffmpeg_xma_chunk_split(STREAMFILE* sf_head, STREAMFILE* sf_data, uint32_t data_offset, uint32_t data_size, uint32_t chunk_offset, uint32_t chunk_size) {
ffmpeg_codec_data* data = NULL;
uint8_t buf[0x100];
int is_xma1 = 0;
int bytes = ffmpeg_make_riff_xma_chunk(sf_head, buf, sizeof(buf), data_size, chunk_offset, chunk_size, &is_xma1);
data = init_ffmpeg_header_offset(sf_data, buf, bytes, data_offset, data_size);
if (!data) goto fail;
/* n5.1.2 XMA1 hangs on seeks near end (infinite loop), presumably due to missing flush in wmapro.c's ff_xma1_decoder + frame skip samples */
if (is_xma1)
ffmpeg_set_force_seek(data);
return data;
fail:

View File

@ -26,9 +26,9 @@ typedef struct {
int filebuf_size;
/* custom IO */
void* arg;
void* arg;
int (*read)(void* dst, int size, int n, void* arg);
int (*seek)(void* arg, int offset, int whence);
int (*seek)(void* arg, int offset, int whence);
} icesnd_callback_t;

View File

@ -1,111 +1,223 @@
#include "mpeg_decoder.h"
#ifdef VGM_USE_MPEG
#include "mpeg_decoder.h"
#include "../util/bitstream_msb.h"
#include "coding.h"
#define MPEG_AHX_EXPECTED_FRAME_SIZE 0x414
static int ahx_decrypt_type08(uint8_t * buffer, mpeg_custom_config *config);
/* AHX is more or less VBR MP2 using a fixed header (0xFFF5E0C0) that sets frame size 0x414 (1ch, 160kbps, 22050Hz)
* but are typically much shorter (ignores padding), output sample rate is also ignored.
*
* MPEG1 Layer II (MP2) bitstream format for reference:
* - MPEG header, 32b
* - 'bit allocation' indexes (MP2's config determines bands and table with bit size per band, in AHX's case 30 bands and total 107 bits)
* - 16-bit CRC if set in header (never in AHX)
* - scale factor selection info (SCFSI), 2b per band/channel (if band has bit alloc set)
* - scale factors, bits depending on selection info (if band has bit alloc set)
* - quantized samples, bits depending on bit alloc info
* - padding (removed in AHX)
*/
/* writes data to the buffer and moves offsets, transforming AHX frames as needed */
int mpeg_custom_parse_frame_ahx(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream) {
mpeg_custom_stream *ms = data->streams[num_stream];
size_t current_data_size = 0;
size_t file_size = get_streamfile_size(stream->streamfile);
/* AHX has a 0xFFF5E0C0 header with frame size 0x414 (160kbps, 22050Hz) but they actually are much shorter */
#define AHX_BANDS 30
#define AHX_GRANULES 12
static const uint8_t AHX_BITALLOC_TABLE[32] = { 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 };
static const uint8_t AHX_OFFSET_TABLE[5][16] = {
{ 0 },
{ 0 },
{ 0, 1, 3, 4, },
{ 0, 1, 3, 4, 5, 6, 7, 8, },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }
};
static const int8_t AHX_QBITS_TABLE[17] = { -5, -7, 3, -10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
/* read supposed frame size first (to minimize reads) */
ms->bytes_in_buffer = read_streamfile(ms->buffer, stream->offset, MPEG_AHX_EXPECTED_FRAME_SIZE, stream->streamfile);
/* Decrypts and tests a AHX frame with current by reading all bits, as wrong keys should go over size. Reverse engineered
* from CRI libs. (MPEG1 Layer II code abridged for AHX, which is always mono and has fixed bands/tables, some info from ahx2wav.c) */
static int ahx_decrypt(uint8_t* buf, int curr_size, crikey_t* crikey) {
uint32_t bit_alloc[AHX_BANDS] = {0};
uint32_t scfsi[AHX_BANDS] = {0};
bitstream_t ib = {0};
bitstream_t ob = {0};
/* find actual frame size by looking for the next frame header */
{
uint32_t current_header = get_u32be(ms->buffer);
int next_pos = 0x04;
bm_setup(&ib, buf, curr_size); /* frame */
bm_setup(&ob, buf, curr_size); /* decrypted frame */
while (next_pos <= MPEG_AHX_EXPECTED_FRAME_SIZE) {
uint32_t next_header = get_u32be(ms->buffer + next_pos);
/* MPEG header (fixed in AHX, otherwise layer/bitrate/channels sets bands+tables) */
bm_skip(&ib, 32);
bm_skip(&ob, 32);
if (current_header == next_header) {
current_data_size = next_pos;
break;
}
/* read bit allocs for later */
for (int i = 0; i < AHX_BANDS; i++) {
int ba_bits = AHX_BITALLOC_TABLE[i];
/* AHXs end in a 0x0c footer (0x41485845 28632943 52490000 / "AHXE(c)CRI\0\0") */
if (stream->offset + next_pos + 0x0c >= file_size) {
current_data_size = next_pos;
break;
}
bm_get (&ib, ba_bits, &bit_alloc[i]);
bm_skip(&ob, ba_bits);
}
next_pos++;
/* get first scalefactor info to decide key */
if (bit_alloc[0]) {
bm_get (&ib, 2, &scfsi[0]);
bm_skip(&ob, 2);
}
uint16_t key;
switch(scfsi[0]) {
case 1: key = crikey->key1; break;
case 2: key = crikey->key2; break;
case 3: key = crikey->key3; break;
default: key = 0; /* 0: no key (common in null frames) */
}
/* decrypt rest of scalefactors (only first ones are encrypted though) */
for (int i = 1; i < AHX_BANDS; i++) {
if (bit_alloc[i]) {
bm_get (&ib, 2, &scfsi[i]);
scfsi[i] ^= (key & 3);
bm_put(&ob, 2, scfsi[i]);
}
key >>= 2;
}
/* read scalefactors (past this point no need to decrypt/write frame) */
for (int i = 0; i < AHX_BANDS; i++) {
if (bit_alloc[i] == 0)
continue;
switch(scfsi[i]) {
case 0: bm_skip(&ib, 6 * 3); break;
case 1:
case 3: bm_skip(&ib, 6 * 2); break;
case 2: bm_skip(&ib, 6 * 1); break;
default: break;
}
}
if (current_data_size == 0 || current_data_size > ms->buffer_size || current_data_size > MPEG_AHX_EXPECTED_FRAME_SIZE) {
VGM_LOG("MPEG AHX: incorrect data_size 0x%x\n", current_data_size);
/* read quants */
for (int gr = 0; gr < AHX_GRANULES; gr++) {
for (int i = 0; i < AHX_BANDS; i++) {
int ba_value = bit_alloc[i];
if (ba_value == 0)
continue;
int ba_bits = AHX_BITALLOC_TABLE[i];
int qb_index = AHX_OFFSET_TABLE[ba_bits][ba_value - 1];
int qbits = AHX_QBITS_TABLE[qb_index];
if (qbits < 0)
qbits = -qbits;
else
qbits = qbits * 3; /* 3 qs */
int ok = bm_skip(&ib, qbits);
if (!ok) goto fail;
}
}
/* read padding */
{
int bpos = bm_pos(&ib);
if (bpos % 8) {
bm_skip(&ib, 8 - (bpos % 8));
}
}
/* if file was properly read/decrypted this size should land in next frame header or near EOF */
return bm_pos(&ib) / 8;
fail:
return 0;
}
/* writes data to the buffer and moves offsets, transforming AHX frames as needed */
int mpeg_custom_parse_frame_ahx(VGMSTREAMCHANNEL* stream, mpeg_codec_data* data, int num_stream) {
mpeg_custom_stream *ms = data->streams[num_stream];
size_t curr_size = 0;
size_t file_size = get_streamfile_size(stream->streamfile);
/* Find actual frame size by looking for the next frame header. Not very elegant but simpler, works with encrypted AHX,
* and possibly faster than reading frame size's bits with ahx_decrypt */
{
ms->bytes_in_buffer = read_streamfile(ms->buffer, stream->offset, MPEG_AHX_EXPECTED_FRAME_SIZE + 0x04, stream->streamfile);
uint32_t curr_header = get_u32be(ms->buffer);
int pos = 0x04;
while (pos <= MPEG_AHX_EXPECTED_FRAME_SIZE) {
/* next sync test */
if (ms->buffer[pos] == 0xFF) {
uint32_t next_header = get_u32be(ms->buffer + pos);
if (curr_header == next_header) {
curr_size = pos;
break;
}
}
/* AHX footer (0x8001000C 41485845 28632943 52490000 = 0x8001 tag + size + "AHXE(c)CRI\0\0") */
if (stream->offset + pos + 0x10 >= file_size) {
curr_size = pos;
break;
}
pos++;
}
}
if (curr_size == 0 || curr_size > ms->buffer_size || curr_size > MPEG_AHX_EXPECTED_FRAME_SIZE) {
VGM_LOG("MPEG AHX: incorrect data_size 0x%x\n", curr_size);
goto fail;
}
/* 0-fill up to expected size to keep mpg123 happy */
memset(ms->buffer + current_data_size, 0, MPEG_AHX_EXPECTED_FRAME_SIZE - current_data_size);
memset(ms->buffer + curr_size, 0, MPEG_AHX_EXPECTED_FRAME_SIZE - curr_size);
ms->bytes_in_buffer = MPEG_AHX_EXPECTED_FRAME_SIZE;
/* decrypt if needed */
switch(data->config.encryption) {
case 0x00: break;
case 0x08: ahx_decrypt_type08(ms->buffer, &data->config); break;
default:
VGM_LOG("MPEG AHX: unknown encryption 0x%x\n", data->config.encryption);
break; /* garbled frame */
/* decrypt if needed (only 0x08 is known but 0x09 is probably the same) */
if (data->config.encryption == 0x08) {
ahx_decrypt(ms->buffer, curr_size, &data->config.crikey);
}
/* update offsets */
stream->offset += current_data_size;
if (stream->offset + 0x0c >= file_size)
stream->offset = file_size; /* skip 0x0c footer to reach EOF (shouldn't happen normally) */
stream->offset += curr_size;
if (stream->offset + 0x10 >= file_size)
stream->offset = file_size; /* skip footer to reach EOF (shouldn't happen normally) */
return 1;
fail:
return 0;
}
/* Decrypts an AHX type 0x08 (keystring) encrypted frame. Algorithm by Thealexbarney */
static int ahx_decrypt_type08(uint8_t * buffer, mpeg_custom_config *config) {
int i, index, encrypted_bits;
uint32_t value;
uint16_t current_key;
/* encryption 0x08 modifies a few bits every frame, here we decrypt and write to data buffer */
#define AHX_KEY_BUFFER 0x2000
#define AHX_KEY_TEST_FRAMES 15 /* wrong keys may work ok in some frames */
/* derive keystring to 3 primes, using the type 0x08 method, and assign each an index of 1/2/3 (0=no key) */
/* (externally done for now, see: https://github.com/Thealexbarney/VGAudio/blob/2.0/src/VGAudio/Codecs/CriAdx/CriAdxKey.cs) */
/* check if current key ends properly in frame syncs */
int test_ahx_key(STREAMFILE* sf, off_t offset, crikey_t* crikey) {
int bytes;
uint8_t buf[AHX_KEY_BUFFER];
const int buf_size = sizeof(buf);
int pos = 0;
uint32_t base_sync, curr_sync;
/* read 2b from a bitstream offset to decrypt, and use it as an index to get the key.
* AHX encrypted bitstream starts at 107b (0x0d*8+3), every frame, and seem to always use index 2 */
value = get_u32be(buffer + 0x0d);
index = (value >> (32-3-2)) & 0x03;
switch(index) {
case 0: current_key = 0; break;
case 1: current_key = config->cri_key1; break;
case 2: current_key = config->cri_key2; break;
case 3: current_key = config->cri_key3; break;
default: goto fail;
bytes = read_streamfile(buf, offset, buf_size, sf);
//if (bytes != buf_size) goto fail; /* possible in small AHX */
base_sync = get_u32be(buf + 0x00);
for (int i = 0; i < AHX_KEY_TEST_FRAMES; i++) {
int size = ahx_decrypt(buf + pos, bytes, crikey);
if (size <= 0 || size >= bytes - 0x04) goto fail;
bytes -= size;
pos += size;
curr_sync = get_u32be(buf + pos);
if (curr_sync == 0x00800100) /* EOF tag */
break;
if (base_sync != curr_sync)
goto fail;
}
/* AHX for DC: 16b, normal: 6b (no idea, probably some Layer II field) */
encrypted_bits = config->cri_type == 0x10 ? 16 : 6;
/* decrypt next bitstream 2b pairs, up to 16b (max key size):
* - read 2b from bitstream (from higher to lower)
* - read 2b from key (from lower to higher)
* - XOR them to decrypt */
for (i = 0; i < encrypted_bits; i+=2) {
uint32_t xor_2b = (current_key >> i) & 0x03;
value ^= ((xor_2b << (32-3-2-2)) >> i);
}
/* write output */
put_32bitBE(buffer + 0x0d, value);
return 1;
fail:
return 0;

View File

@ -1,5 +1,5 @@
#include "mpeg_decoder.h"
#include "mpeg_bitreader.h"
#include "../util/bitstream_msb.h"
#ifdef VGM_USE_MPEG
@ -108,7 +108,7 @@ int mpeg_custom_setup_init_ealayer3(STREAMFILE* sf, off_t start_offset, mpeg_cod
{
ib.sf = sf;
ib.offset = start_offset;
ib.is.buf = ib.buf;
bm_setup(&ib.is, ib.buf, 0); // filled later
ok = ealayer3_parse_frame(data, -1, &ib, &eaf);
if (!ok) goto fail;
@ -156,7 +156,7 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL* stream, mpeg_codec_data*
ib_0.sf = stream->streamfile;
ib_0.offset = stream->offset;
ib_0.is.buf = ib_0.buf;
bm_setup(&ib_0.is, ib_0.buf, 0); // filled later
ok = ealayer3_parse_frame(data, num_stream, &ib_0, &eaf_0);
if (!ok) goto fail;
@ -199,7 +199,7 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL* stream, mpeg_codec_data*
ib_1.sf = stream->streamfile;
ib_1.offset = stream->offset;
ib_1.is.buf = ib_1.buf;
bm_setup(&ib_1.is, ib_1.buf, 0); // filled later
ok = ealayer3_parse_frame(data, num_stream, &ib_1, &eaf_1);
if (!ok) goto fail;
@ -222,12 +222,12 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL* stream, mpeg_codec_data*
{
bitstream_t os = {0};
init_bitstream(&os, ms->buffer, ms->buffer_size);
bm_setup(&os, ms->buffer, ms->buffer_size);
ok = ealayer3_rebuild_mpeg_frame(&ib_0.is, &eaf_0, &ib_1.is, &eaf_1, &os);
if (!ok) goto fail;
ms->bytes_in_buffer = os.b_off / 8; /* wrote full MPEG frame, hopefully */
ms->bytes_in_buffer = bm_pos(&os) / 8; /* wrote full MPEG frame, hopefully */
}
return 1;
@ -267,8 +267,8 @@ static void fill_buf(ealayer3_buffer_t* ib, int bits) {
//;VGM_LOG("filled: %lx + %x (b=%i, m=%i)\n", ib->offset, bytes_size, bits, (mod > 0 ? 8 - mod : 0));
read_size = read_streamfile(ib->buf + ib->is.bufsize, ib->offset, bytes_size, ib->sf);
ib->is.bufsize += read_size;
read_size = read_streamfile(ib->buf + ib->is.bufsize, ib->offset, bytes_size, ib->sf); //TODO don't access internals
bm_fill(&ib->is, read_size);
ib->offset += read_size;
ib->leftover_bits = (mod > 0 ? 8 - mod : 0);
}
@ -309,7 +309,7 @@ static int ealayer3_parse_frame_v1(ealayer3_buffer_t* ib, ealayer3_frame_t* eaf,
/* read EA-frame V1 header */
fill_buf(ib, 8);
rb_bits(is, 8,&eaf->v1_pcm_flag);
bm_get(is, 8,&eaf->v1_pcm_flag);
eaf->pre_size = 1; /* 8b */
@ -331,15 +331,15 @@ static int ealayer3_parse_frame_v1(ealayer3_buffer_t* ib, ealayer3_frame_t* eaf,
/* check PCM block */
if (eaf->v1_pcm_flag == 0xEE) {
fill_buf(ib, 32);
rb_bits(is, 16,&eaf->v1_offset_samples); /* PCM block offset in the buffer */
rb_bits(is, 16,&eaf->v1_pcm_samples); /* number of PCM samples, can be 0 */
bm_get(is, 16,&eaf->v1_offset_samples); /* PCM block offset in the buffer */
bm_get(is, 16,&eaf->v1_pcm_samples); /* number of PCM samples, can be 0 */
eaf->pre_size += 2+2; /* 16b+16b */
eaf->pcm_size = (2*eaf->v1_pcm_samples * channels_per_frame);
if (is_v1b) { /* extra 32b in v1b */
fill_buf(ib, 32);
rb_bits(is, 32,&eaf->v1_pcm_unknown);
bm_get(is, 32,&eaf->v1_pcm_unknown);
eaf->pre_size += 4; /* 32b */
@ -363,19 +363,19 @@ static int ealayer3_parse_frame_v2(ealayer3_buffer_t* ib, ealayer3_frame_t* eaf)
/* read EA-frame V2 header */
fill_buf(ib, 16);
rb_bits(is, 1,&eaf->v2_extended_flag);
rb_bits(is, 1,&eaf->v2_stereo_flag);
rb_bits(is, 2,&eaf->v2_reserved);
rb_bits(is, 12,&eaf->v2_frame_size);
bm_get(is, 1,&eaf->v2_extended_flag);
bm_get(is, 1,&eaf->v2_stereo_flag);
bm_get(is, 2,&eaf->v2_reserved);
bm_get(is, 12,&eaf->v2_frame_size);
eaf->pre_size = 2; /* 16b */
if (eaf->v2_extended_flag) {
fill_buf(ib, 32);
rb_bits(is, 2,&eaf->v2_offset_mode);
rb_bits(is, 10,&eaf->v2_offset_samples);
rb_bits(is, 10,&eaf->v2_pcm_samples);
rb_bits(is, 10,&eaf->v2_common_size);
bm_get(is, 2,&eaf->v2_offset_mode);
bm_get(is, 10,&eaf->v2_offset_samples);
bm_get(is, 10,&eaf->v2_pcm_samples);
bm_get(is, 10,&eaf->v2_common_size);
eaf->pre_size += 4; /* 32b */
}
@ -423,16 +423,16 @@ static int ealayer3_parse_frame_common(ealayer3_buffer_t* ib, ealayer3_frame_t*
static const int channel_table[4] = { 2,2,2, 1 }; /* [channel_mode] */
bitstream_t* is = &ib->is;
off_t start_b_off = is->b_off;
off_t start_b_off = bm_pos(is);
int i, fill_bits, others_2_bits;
/* read main header */
fill_buf(ib, 8);
rb_bits(is, 2,&eaf->version_index);
rb_bits(is, 2,&eaf->sample_rate_index);
rb_bits(is, 2,&eaf->channel_mode);
rb_bits(is, 2,&eaf->mode_extension);
bm_get(is, 2,&eaf->version_index);
bm_get(is, 2,&eaf->sample_rate_index);
bm_get(is, 2,&eaf->channel_mode);
bm_get(is, 2,&eaf->mode_extension);
/* check empty frame */
@ -460,7 +460,7 @@ static int ealayer3_parse_frame_common(ealayer3_buffer_t* ib, ealayer3_frame_t*
/* read side info */
fill_buf(ib, 1);
rb_bits(is, 1,&eaf->granule_index);
bm_get(is, 1,&eaf->granule_index);
fill_bits = (eaf->mpeg1 && eaf->granule_index == 1) ? 4 * eaf->channels : 0;
fill_bits = fill_bits + (12 + 32 + others_2_bits) * eaf->channels;
@ -468,21 +468,21 @@ static int ealayer3_parse_frame_common(ealayer3_buffer_t* ib, ealayer3_frame_t*
if (eaf->mpeg1 && eaf->granule_index == 1) {
for (i = 0; i < eaf->channels; i++) {
rb_bits(is, 4,&eaf->scfsi[i]);
bm_get(is, 4,&eaf->scfsi[i]);
}
}
for (i = 0; i < eaf->channels; i++) {
rb_bits(is, 12,&eaf->main_data_size[i]);
bm_get(is, 12,&eaf->main_data_size[i]);
/* divided in 47b=32+15 (MPEG1) or 51b=32+19 (MPEG2), arbitrarily */
rb_bits(is, 32,&eaf->others_1[i]);
rb_bits(is, others_2_bits,&eaf->others_2[i]);
bm_get(is, 32,&eaf->others_1[i]);
bm_get(is, others_2_bits,&eaf->others_2[i]);
}
/* derived */
eaf->data_offset_b = is->b_off; /* header size + above size */
eaf->base_size_b = (is->b_off - start_b_off); /* above size without header */
eaf->data_offset_b = bm_pos(is); /* header size + above size */
eaf->base_size_b = (bm_pos(is) - start_b_off); /* above size without header */
for (i = 0; i < eaf->channels; i++) {
eaf->data_size_b += eaf->main_data_size[i]; /* can be 0, meaning a micro EA-frame */
}
@ -490,7 +490,7 @@ static int ealayer3_parse_frame_common(ealayer3_buffer_t* ib, ealayer3_frame_t*
eaf->padding_size_b = 8 - ((eaf->base_size_b+eaf->data_size_b) % 8);
fill_buf(ib, eaf->data_size_b + eaf->padding_size_b); /* read MPEG data (not PCM block) */
is->b_off += eaf->data_size_b + eaf->padding_size_b;
bm_skip(is, eaf->data_size_b + eaf->padding_size_b);
eaf->common_size = (eaf->base_size_b + eaf->data_size_b + eaf->padding_size_b)/8;
@ -542,55 +542,55 @@ static int ealayer3_rebuild_mpeg_frame(bitstream_t* is_0, ealayer3_frame_t* eaf_
#endif
/* write MPEG1/2 frame header */
wb_bits(os, 11, 0x7FF); /* sync */
wb_bits(os, 2, eaf_0->version_index);
wb_bits(os, 2, 0x01); /* layer III index */
wb_bits(os, 1, 1); /* "no CRC" flag */
wb_bits(os, 4, expected_bitrate_index);
wb_bits(os, 2, eaf_0->sample_rate_index);
wb_bits(os, 1, 0); /* padding */
wb_bits(os, 1, 0); /* private */
wb_bits(os, 2, eaf_0->channel_mode);
wb_bits(os, 2, eaf_0->mode_extension);
wb_bits(os, 1, 1); /* copyrighted */
wb_bits(os, 1, 1); /* original */
wb_bits(os, 2, 0); /* emphasis */
bm_put(os, 11, 0x7FF); /* sync */
bm_put(os, 2, eaf_0->version_index);
bm_put(os, 2, 0x01); /* layer III index */
bm_put(os, 1, 1); /* "no CRC" flag */
bm_put(os, 4, expected_bitrate_index);
bm_put(os, 2, eaf_0->sample_rate_index);
bm_put(os, 1, 0); /* padding */
bm_put(os, 1, 0); /* private */
bm_put(os, 2, eaf_0->channel_mode);
bm_put(os, 2, eaf_0->mode_extension);
bm_put(os, 1, 1); /* copyrighted */
bm_put(os, 1, 1); /* original */
bm_put(os, 2, 0); /* emphasis */
if (eaf_0->mpeg1) {
int private_bits = (eaf_0->channels==1 ? 5 : 3);
/* write MPEG1 side info */
wb_bits(os, 9, 0); /* main data start (no bit reservoir) */
wb_bits(os, private_bits, 0);
bm_put(os, 9, 0); /* main data start (no bit reservoir) */
bm_put(os, private_bits, 0);
for (i = 0; i < eaf_1->channels; i++) {
wb_bits(os, 4, eaf_1->scfsi[i]); /* saved in granule1 only */
bm_put(os, 4, eaf_1->scfsi[i]); /* saved in granule1 only */
}
for (i = 0; i < eaf_0->channels; i++) { /* granule0 */
wb_bits(os, 12, eaf_0->main_data_size[i]);
wb_bits(os, 32, eaf_0->others_1[i]);
wb_bits(os, 47-32, eaf_0->others_2[i]);
bm_put(os, 12, eaf_0->main_data_size[i]);
bm_put(os, 32, eaf_0->others_1[i]);
bm_put(os, 47-32, eaf_0->others_2[i]);
}
for (i = 0; i < eaf_1->channels; i++) { /* granule1 */
wb_bits(os, 12, eaf_1->main_data_size[i]);
wb_bits(os, 32, eaf_1->others_1[i]);
wb_bits(os, 47-32, eaf_1->others_2[i]);
bm_put(os, 12, eaf_1->main_data_size[i]);
bm_put(os, 32, eaf_1->others_1[i]);
bm_put(os, 47-32, eaf_1->others_2[i]);
}
/* write MPEG1 main data */
is_0->b_off = eaf_0->data_offset_b;
bm_set(is_0, eaf_0->data_offset_b);
for (i = 0; i < eaf_0->channels; i++) { /* granule0 */
for (j = 0; j < eaf_0->main_data_size[i]; j++) {
rb_bits(is_0, 1, &c);
wb_bits(os, 1, c);
bm_get(is_0, 1, &c);
bm_put(os, 1, c);
}
}
is_1->b_off = eaf_1->data_offset_b;
bm_set(is_1, eaf_1->data_offset_b);
for (i = 0; i < eaf_1->channels; i++) { /* granule1 */
for (j = 0; j < eaf_1->main_data_size[i]; j++) {
rb_bits(is_1, 1, &c);
wb_bits(os, 1, c);
bm_get(is_1, 1, &c);
bm_put(os, 1, c);
}
}
}
@ -598,43 +598,42 @@ static int ealayer3_rebuild_mpeg_frame(bitstream_t* is_0, ealayer3_frame_t* eaf_
int private_bits = (eaf_0->channels==1 ? 1 : 2);
/* write MPEG2 side info */
wb_bits(os, 8, 0); /* main data start (no bit reservoir) */
wb_bits(os, private_bits, 0);
bm_put(os, 8, 0); /* main data start (no bit reservoir) */
bm_put(os, private_bits, 0);
for (i = 0; i < eaf_0->channels; i++) {
wb_bits(os, 12, eaf_0->main_data_size[i]);
wb_bits(os, 32, eaf_0->others_1[i]);
wb_bits(os, 51-32, eaf_0->others_2[i]);
bm_put(os, 12, eaf_0->main_data_size[i]);
bm_put(os, 32, eaf_0->others_1[i]);
bm_put(os, 51-32, eaf_0->others_2[i]);
}
/* write MPEG2 main data */
is_0->b_off = eaf_0->data_offset_b;
bm_set(is_0, eaf_0->data_offset_b);
for (i = 0; i < eaf_0->channels; i++) {
for (j = 0; j < eaf_0->main_data_size[i]; j++) {
rb_bits(is_0, 1, &c);
wb_bits(os, 1, c);
bm_get(is_0, 1, &c);
bm_put(os, 1, c);
}
}
}
/* align to closest 8b */
if (os->b_off % 8) {
int align_bits = 8 - (os->b_off % 8);
wb_bits(os, align_bits, 0);
if (bm_pos(os) % 8) {
int align_bits = 8 - (bm_pos(os) % 8);
bm_put(os, align_bits, 0);
}
if (os->b_off/8 > expected_frame_size) {
if (bm_pos(os) / 8 > expected_frame_size) {
/* bit reservoir! shouldn't happen with free bitrate, otherwise it's hard to fix as needs complex buffering/calcs */
VGM_LOG("EAL3: written 0x%x but expected less than 0x%x\n", (uint32_t)(os->b_off/8), expected_frame_size);
VGM_LOG("EAL3: written 0x%x but expected less than 0x%x\n", (uint32_t)(bm_pos(os) / 8), expected_frame_size);
}
else {
/* fill ancillary data (should be ignored, but 0x00 seems to improve mpg123's free bitrate detection) */
memset(os->buf + os->b_off/8, 0x00, expected_frame_size - os->b_off/8);
memset(os->buf + bm_pos(os) / 8, 0x00, expected_frame_size - bm_pos(os) / 8);
}
os->b_off = expected_frame_size*8;
bm_set(os, expected_frame_size * 8);
return 1;
fail:
@ -835,7 +834,7 @@ static int ealayer3_skip_data(VGMSTREAMCHANNEL* stream, mpeg_codec_data* data, i
for (i = 0; i < skips; i++) {
ib.sf = stream->streamfile;
ib.offset = stream->offset;
ib.is.buf = ib.buf;
bm_setup(&ib.is, ib.buf, 0); // filled later
ok = ealayer3_parse_frame(data, num_stream, &ib, &eaf);
if (!ok) goto fail;

View File

@ -207,6 +207,9 @@ static mpg123_handle* init_mpg123_handle(void) {
mpg123_param(m,MPG123_REMOVE_FLAGS,MPG123_GAPLESS,0.0); /* wonky support */
mpg123_param(m,MPG123_RESYNC_LIMIT, -1, 0x2000); /* just in case, games shouldn't ever need this */
#ifndef VGM_DEBUG_OUTPUT
mpg123_param(m, MPG123_ADD_FLAGS, MPG123_QUIET, 1);
#endif
if (mpg123_open_feed(m) != MPG123_OK) {
goto fail;

View File

@ -43,6 +43,9 @@ ogg_vorbis_codec_data* init_ogg_vorbis(STREAMFILE* sf, off_t start, off_t size,
callbacks.close_func = ov_close_func;
callbacks.tell_func = ov_tell_func;
if (!size)
size = get_streamfile_size(sf) - start;
/* test if this is a proper Ogg Vorbis file, with the current (from init_x) STREAMFILE
* (quick test without having to malloc first, though if one invoked this it'll probably success) */
{

View File

@ -216,6 +216,17 @@ void decode_pcmfloat(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspac
}
}
void decode_pcm24be(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i;
int32_t sample_count;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count += channelspacing) {
off_t offset = stream->offset + i * 0x03;
int v = read_u8(offset+0x02, stream->streamfile) | (read_s16be(offset + 0x00, stream->streamfile) << 8);
outbuf[sample_count] = (v >> 8);
}
}
void decode_pcm24le(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i;
int32_t sample_count;
@ -232,6 +243,10 @@ int32_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample) {
return ((int64_t)bytes * 8) / channels / bits_per_sample;
}
int32_t pcm24_bytes_to_samples(size_t bytes, int channels) {
return pcm_bytes_to_samples(bytes, channels, 24);
}
int32_t pcm16_bytes_to_samples(size_t bytes, int channels) {
return pcm_bytes_to_samples(bytes, channels, 16);
}

View File

@ -33,32 +33,44 @@ static int16_t squares[256] = {
31250, 31752, 32258
};
/* for (i=-128;i<128;i++) { double j = (i/2)/2.0; cubes[i+128] = floor(j*j*j); } */
/*
for (uint16_t i = 0; i < 0x100; i += 1) {
int16_t v = i;
v -= 0x80;
v *= 0x100;
int32_t a = v;
a *= a;
a >>= 15;
a *= v;
a >>= 15;
cubes[i] = a;
}
*/
static int16_t cubes[256] = {
-32768,-31256,-31256,-29791,-29791,-28373,-28373,-27000,-27000,-25672,-25672,
-24389,-24389,-23149,-23149,-21952,-21952,-20797,-20797,-19683,-19683,-18610,
-18610,-17576,-17576,-16581,-16581,-15625,-15625,-14706,-14706,-13824,-13824,
-12978,-12978,-12167,-12167,-11391,-11391,-10648,-10648, -9938, -9938, -9261,
-9261, -8615, -8615, -8000, -8000, -7415, -7415, -6859, -6859, -6332, -6332,
-5832, -5832, -5359, -5359, -4913, -4913, -4492, -4492, -4096, -4096, -3724,
-3724, -3375, -3375, -3049, -3049, -2744, -2744, -2460, -2460, -2197, -2197,
-1953, -1953, -1728, -1728, -1521, -1521, -1331, -1331, -1158, -1158, -1000,
-1000, -857, -857, -729, -729, -614, -614, -512, -512, -422, -422,
-343, -343, -275, -275, -216, -216, -166, -166, -125, -125, -91,
-91, -64, -64, -43, -43, -27, -27, -16, -16, -8, -8,
-3, -3, -1, -1, 0, 0, 0, 0, 0, 0, 0,
1, 1, 3, 3, 8, 8, 16, 16, 27, 27, 43,
43, 64, 64, 91, 91, 125, 125, 166, 166, 216, 216,
275, 275, 343, 343, 422, 422, 512, 512, 614, 614, 729,
729, 857, 857, 1000, 1000, 1158, 1158, 1331, 1331, 1521, 1521,
1728, 1728, 1953, 1953, 2197, 2197, 2460, 2460, 2744, 2744, 3049,
3049, 3375, 3375, 3724, 3724, 4096, 4096, 4492, 4492, 4913, 4913,
5359, 5359, 5832, 5832, 6332, 6332, 6859, 6859, 7415, 7415, 8000,
8000, 8615, 8615, 9261, 9261, 9938, 9938, 10648, 10648, 11391, 11391,
12167, 12167, 12978, 12978, 13824, 13824, 14706, 14706, 15625, 15625, 16581,
16581, 17576, 17576, 18610, 18610, 19683, 19683, 20797, 20797, 21952, 21952,
23149, 23149, 24389, 24389, 25672, 25672, 27000, 27000, 28373, 28373, 29791,
29791, 31256, 31256
-32768,-32006,-31256,-30518,-29791,-29077,-28373,-27681,-27000,-26331,-25673,
-25026,-24389,-23764,-23150,-22546,-21952,-21370,-20797,-20235,-19683,-19142,
-18610,-18088,-17576,-17074,-16582,-16099,-15625,-15161,-14707,-14261,-13824,
-13397,-12978,-12569,-12167,-11775,-11391,-11016,-10648,-10290, -9939, -9596,
-9261, -8935, -8616, -8304, -8000, -7704, -7415, -7134, -6859, -6592, -6332,
-6079, -5832, -5593, -5360, -5133, -4913, -4700, -4493, -4292, -4096, -3907,
-3724, -3547, -3375, -3210, -3049, -2894, -2744, -2600, -2461, -2327, -2197,
-2073, -1954, -1839, -1728, -1623, -1521, -1424, -1331, -1243, -1158, -1077,
-1000, -927, -858, -792, -729, -670, -615, -562, -512, -466, -422,
-382, -343, -308, -275, -245, -216, -191, -167, -145, -125, -108,
-92, -77, -64, -53, -43, -35, -27, -21, -16, -12, -8,
-6, -4, -2, -1, -1, -1, -1, 0, 0, 0, 0,
1, 1, 3, 5, 8, 11, 15, 20, 27, 34, 42,
52, 64, 76, 91, 107, 125, 144, 166, 190, 216, 244,
274, 307, 343, 381, 421, 465, 512, 561, 614, 669, 729,
791, 857, 926, 1000, 1076, 1157, 1242, 1331, 1423, 1520, 1622,
1728, 1838, 1953, 2072, 2197, 2326, 2460, 2599, 2744, 2893, 3048,
3209, 3375, 3546, 3723, 3906, 4096, 4291, 4492, 4699, 4913, 5132,
5359, 5592, 5832, 6078, 6331, 6591, 6859, 7133, 7414, 7703, 8000,
8303, 8615, 8934, 9261, 9595, 9938, 10289, 10648, 11015, 11390, 11774,
12167, 12568, 12977, 13396, 13824, 14260, 14706, 15160, 15625, 16098, 16581,
17073, 17576, 18087, 18609, 19141, 19683, 20234, 20796, 21369, 21952, 22545,
23149, 23763, 24389, 25025, 25672, 26330, 27000, 27680, 28372, 29076, 29791,
30517, 31255, 32005
};
static void decode_delta_exact(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int16_t * table) {

View File

@ -4,9 +4,6 @@
#include "coding/coding.h"
#include "mixing.h"
#include "plugins.h"
#ifdef VGM_USE_MAIATRAC3PLUS
#include "at3plus_decoder.h"
#endif
/* custom codec handling, not exactly "decode" stuff but here to simplify adding new codecs */
@ -94,12 +91,6 @@ void free_codec(VGMSTREAM* vgmstream) {
}
#endif
#ifdef VGM_USE_MAIATRAC3PLUS
if (vgmstream->coding_type == coding_AT3plus) {
free_at3plus(vgmstream->codec_data);
}
#endif
#ifdef VGM_USE_ATRAC9
if (vgmstream->coding_type == coding_ATRAC9) {
free_atrac9(vgmstream->codec_data);
@ -188,12 +179,6 @@ void seek_codec(VGMSTREAM* vgmstream) {
}
#endif
#ifdef VGM_USE_MAIATRAC3PLUS
if (vgmstream->coding_type == coding_AT3plus) {
seek_at3plus(vgmstream, vgmstream->loop_current_sample);
}
#endif
#ifdef VGM_USE_ATRAC9
if (vgmstream->coding_type == coding_ATRAC9) {
seek_atrac9(vgmstream, vgmstream->loop_current_sample);
@ -305,12 +290,6 @@ void reset_codec(VGMSTREAM* vgmstream) {
}
#endif
#ifdef VGM_USE_MAIATRAC3PLUS
if (vgmstream->coding_type == coding_AT3plus) {
reset_at3plus(vgmstream);
}
#endif
#ifdef VGM_USE_ATRAC9
if (vgmstream->coding_type == coding_ATRAC9) {
reset_atrac9(vgmstream->codec_data);
@ -387,6 +366,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream) {
case coding_ALAW:
case coding_PCMFLOAT:
case coding_PCM24LE:
case coding_PCM24BE:
return 1;
#ifdef VGM_USE_VORBIS
case coding_OGG_VORBIS:
@ -557,10 +537,6 @@ int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream) {
case coding_MP4_AAC:
return ((mp4_aac_codec_data*)vgmstream->codec_data)->samples_per_frame;
#endif
#ifdef VGM_USE_MAIATRAC3PLUS
case coding_AT3plus:
return 2048 - ((maiatrac3plus_codec_data*)vgmstream->codec_data)->samples_discard;
#endif
#ifdef VGM_USE_ATRAC9
case coding_ATRAC9:
return 0; /* varies with config data, usually 256 or 1024 */
@ -619,6 +595,7 @@ int get_vgmstream_frame_size(VGMSTREAM* vgmstream) {
case coding_PCMFLOAT:
return 0x04;
case coding_PCM24LE:
case coding_PCM24BE:
return 0x03;
case coding_SDX2:
@ -734,9 +711,6 @@ int get_vgmstream_frame_size(VGMSTREAM* vgmstream) {
#ifdef VGM_USE_G719
case coding_G719:
#endif
#ifdef VGM_USE_MAIATRAC3PLUS
case coding_AT3plus:
#endif
#ifdef VGM_USE_FFMPEG
case coding_FFmpeg:
#endif
@ -925,6 +899,13 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
}
break;
case coding_PCM24BE:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_pcm24be(&vgmstream->ch[ch], buffer + ch,
vgmstream->channels, vgmstream->samples_into_block, samples_to_do);
}
break;
case coding_NDS_IMA:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_nds_ima(&vgmstream->ch[ch], buffer+ch,
@ -1304,13 +1285,6 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
}
break;
#endif
#ifdef VGM_USE_MAIATRAC3PLUS
case coding_AT3plus:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_at3plus(vgmstream, buffer+ch, vgmstream->channels, samples_to_do, ch);
}
break;
#endif
#ifdef VGM_USE_ATRAC9
case coding_ATRAC9:
decode_atrac9(vgmstream, buffer, samples_to_do, vgmstream->channels);

View File

@ -97,6 +97,7 @@ static const char* extension_list[] = {
"bar",
"bcstm",
"bcwav",
"bcv", //txth/reserved [The Bigs (PSP)]
"bd3",
"bdsp",
"bfstm",
@ -109,6 +110,7 @@ static const char* extension_list[] = {
"bik",
"bika", //fake extension for .bik (to be removed)
"bik2",
"binka", //FFmpeg/not parsed (BINK AUDIO)
//"bin", //common
"bk2",
"bkr", //txth/reserved [P.N.03 (GC), Viewtiful Joe (GC)]
@ -132,7 +134,6 @@ static const char* extension_list[] = {
"cads",
"caf",
"cbd2",
"ccc", //fake extension (to be removed)
"cd",
"cfn", //fake extension for CAF (renamed, to be removed?)
"chd", //txth/reserved [Donkey Konga (GC), Star Fox Assault (GC)]
@ -184,6 +185,7 @@ static const char* extension_list[] = {
"ezw",
"fag",
"fcb", //FFmpeg/not parsed (BINK AUDIO)
"fda",
"ffw",
"filp",
@ -438,7 +440,6 @@ static const char* extension_list[] = {
"rws",
"rwsd",
"rwx",
"rxw",
"rxx", //txth/reserved [Full Auto (X360)]
"s14",
@ -498,6 +499,7 @@ static const char* extension_list[] = {
"smp",
"smpl", //fake extension/header id for .v0/v1 (renamed, to be removed)
"smv",
"snb",
"snd",
"snds",
"sng",
@ -756,6 +758,7 @@ static const coding_info coding_info_list[] = {
{coding_ALAW, "8-bit a-Law"},
{coding_PCMFLOAT, "32-bit float PCM"},
{coding_PCM24LE, "24-bit Little Endian PCM"},
{coding_PCM24BE, "24-bit Big Endian PCM"},
{coding_CRI_ADX, "CRI ADX 4-bit ADPCM"},
{coding_CRI_ADX_fixed, "CRI ADX 4-bit ADPCM (fixed coefficients)"},
@ -884,9 +887,6 @@ static const coding_info coding_info_list[] = {
#ifdef VGM_USE_G719
{coding_G719, "ITU G.719 annex B (Polycom Siren 22)"},
#endif
#ifdef VGM_USE_MAIATRAC3PLUS
{coding_AT3plus, "ATRAC3plus"},
#endif
#ifdef VGM_USE_ATRAC9
{coding_ATRAC9, "ATRAC9"},
#endif
@ -937,7 +937,6 @@ static const layout_info layout_info_list[] = {
{layout_blocked_vs_str, "blocked (STR VS)"},
{layout_blocked_rws, "blocked (RWS)"},
{layout_blocked_hwas, "blocked (HWAS)"},
{layout_blocked_tra, "blocked (TRA)"},
{layout_blocked_ea_sns, "blocked (EA SNS)"},
{layout_blocked_awc, "blocked (AWC)"},
{layout_blocked_vgs, "blocked (VGS)"},
@ -998,7 +997,6 @@ static const meta_info meta_info_list[] = {
{meta_DSP_MSS, "Double DSP header stereo by .mss extension"},
{meta_DSP_GCM, "Double DSP header stereo by .gcm extension"},
{meta_IDSP_TT, "Traveller's Tales IDSP header"},
{meta_RSTM_SPM, "Nintendo RSTM header (brstmspm)"},
{meta_RAW_PCM, "PC .raw raw header"},
{meta_PS2_VAGi, "Sony VAGi header"},
{meta_PS2_VAGp, "Sony VAGp header"},
@ -1087,14 +1085,13 @@ static const meta_info meta_info_list[] = {
{meta_DC_IDVI, "Capcom IDVI header"},
{meta_KRAW, "Geometry Wars: Galaxies KRAW header"},
{meta_NGC_YMF, "YMF DSP Header"},
{meta_PS2_CCC, "CCC Header"},
{meta_FAG, "Radical .FAG Header"},
{meta_PS2_MIHB, "Sony MultiStream MIC header"},
{meta_DSP_WII_MUS, "mus header"},
{meta_WII_SNG, "SNG DSP Header"},
{meta_RSD, "Radical RSD header"},
{meta_DC_ASD, "ASD Header"},
{meta_NAOMI_SPSD, "Naomi SPSD header"},
{meta_SPSD, "Sega Naomi SPSD header"},
{meta_FFXI_BGW, "Square Enix .BGW header"},
{meta_FFXI_SPW, "Square Enix .SPW header"},
{meta_PS2_ASS, "SystemSoft .ASS header"},
@ -1122,7 +1119,6 @@ static const meta_info meta_info_list[] = {
{meta_PS2_P2BT, "Pop'n'Music 7 Header"},
{meta_PS2_GBTS, "Pop'n'Music 9 Header"},
{meta_NGC_DSP_IADP, "IADP Header"},
{meta_RSTM_shrunken, "Nintendo RSTM header, corrupted by Atlus"},
{meta_RIFF_WAVE_MWV, "RIFF WAVE header with .mwv flavoring"},
{meta_FFCC_STR, "Final Fantasy: Crystal Chronicles STR header"},
{meta_SAT_BAKA, "Konami BAKA header"},
@ -1195,7 +1191,7 @@ static const meta_info meta_info_list[] = {
{meta_DSP_DSPW, "Capcom DSPW header"},
{meta_PS2_JSTM, "JSTM Header"},
{meta_XVAG, "Sony XVAG header"},
{meta_PS3_CPS, "tri-Crescendo CPS Header"},
{meta_CPS, "tri-Crescendo CPS Header"},
{meta_SQEX_SCD, "Square-Enix SCD header"},
{meta_NGC_NST_DSP, "Animaniacs NST header"},
{meta_BAF, "Bizarre Creations .baf header"},
@ -1204,7 +1200,6 @@ static const meta_info meta_info_list[] = {
{meta_SGXD, "Sony SGXD header"},
{meta_WII_RAS, "RAS header"},
{meta_SPM, "Square SPM header"},
{meta_X360_TRA, "Terminal Reality .TRA raw header"},
{meta_VGS_PS, "Princess Soft VGS header"},
{meta_PS2_IAB, "Runtime .IAB header"},
{meta_VS_STR, "Square .VS STR* header"},
@ -1244,18 +1239,18 @@ static const meta_info meta_info_list[] = {
{meta_PS2_VDS_VDM, "Procyon Studio VDS/VDM header"},
{meta_FFMPEG, "FFmpeg supported format"},
{meta_FFMPEG_faulty, "FFmpeg supported format (check log)"},
{meta_X360_CXS, "tri-Crescendo CXS header"},
{meta_CXS, "tri-Crescendo CXS header"},
{meta_AKB, "Square-Enix AKB header"},
{meta_X360_PASX, "Premium Agency PASX header"},
{meta_PASX, "Premium Agency PASX header"},
{meta_XMA_RIFF, "Microsoft XMA RIFF header"},
{meta_X360_AST, "Capcom AST (X360) header"},
{meta_ASTB, "Capcom ASTB header"},
{meta_WWISE_RIFF, "Audiokinetic Wwise RIFF header"},
{meta_UBI_RAKI, "Ubisoft RAKI header"},
{meta_SXD, "Sony SXD header"},
{meta_OGL, "Shin'en OGL header"},
{meta_MC3, "Paradigm MC3 header"},
{meta_GTD, "GTD/GHS header"},
{meta_TA_AAC, "tri-Ace AAC header"},
{meta_GHS, "Hexadrive GHS/S_P_STH header"},
{meta_AAC_TRIACE, "tri-Ace AAC header"},
{meta_MTA2, "Konami MTA2 header"},
{meta_NGC_ULW, "Criterion ULW raw header"},
{meta_XA_XA30, "Reflections XA30 header"},
@ -1369,7 +1364,7 @@ static const meta_info meta_info_list[] = {
{meta_PSF, "Pivotal PSF header"},
{meta_DSP_ITL_i, "Infernal .ITL DSP header"},
{meta_IMA, "Blitz Games .IMA header"},
{meta_XMV_VALVE, "Valve XMV header"},
{meta_XWV_VALVE, "Valve XWV header"},
{meta_UBI_HX, "Ubisoft HXx header"},
{meta_BMP_KONAMI, "Konami BMP header"},
{meta_ISB, "Creative ISACT header"},

View File

@ -159,9 +159,6 @@ void block_update(off_t block_offset, VGMSTREAM* vgmstream) {
case layout_blocked_bdsp:
block_update_bdsp(block_offset,vgmstream);
break;
case layout_blocked_tra:
block_update_tra(block_offset,vgmstream);
break;
case layout_blocked_ps2_iab:
block_update_ps2_iab(block_offset,vgmstream);
break;

View File

@ -1,17 +0,0 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset (first 32bytes is useless for decoding) */
void block_update_tra(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = 0x400;
vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size+8;
vgmstream->current_block_size/=vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset+(vgmstream->current_block_size*i)+0x4*(i+1);
}
}

View File

@ -31,7 +31,6 @@ void block_update_ivaud(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_ea_swvr(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_adm(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_bdsp(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_tra(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_ps2_iab(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_vs_str(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_rws(off_t block_offset, VGMSTREAM* vgmstream);

View File

@ -15,28 +15,28 @@ typedef struct {
int32_t loop_end;
int loop_flag;
off_t stream_offset;
off_t stream_size;
off_t extra_offset;
uint32_t stream_offset;
uint32_t stream_size;
uint32_t extra_offset;
off_t name_offset;
uint32_t name_offset;
} aac_header;
static int parse_aac(STREAMFILE* sf, aac_header* aac);
/* AAC - tri-Ace (ASKA engine) Audio Container */
VGMSTREAM* init_vgmstream_ta_aac(STREAMFILE* sf) {
VGMSTREAM* init_vgmstream_aac_triace(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
aac_header aac = {0};
/* checks */
if (!is_id32be(0x00, sf, "AAC ") && !is_id32le(0x00, sf, "AAC "))
goto fail;
/* .aac: actual extension, .laac: for players to avoid hijacking MP4/AAC */
if (!check_extensions(sf, "aac,laac"))
goto fail;
if (!is_id32be(0x00, sf, "AAC ") && !is_id32le(0x00, sf, "AAC "))
goto fail;
if (!parse_aac(sf, &aac))
goto fail;
@ -46,7 +46,7 @@ VGMSTREAM* init_vgmstream_ta_aac(STREAMFILE* sf) {
vgmstream = allocate_vgmstream(aac.channels, aac.loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_TA_AAC;
vgmstream->meta_type = meta_AAC_TRIACE;
vgmstream->sample_rate = aac.sample_rate;
vgmstream->num_streams = aac.total_subsongs;
vgmstream->stream_size = aac.stream_size;
@ -55,11 +55,7 @@ VGMSTREAM* init_vgmstream_ta_aac(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 0x0165: { /* Infinite Undiscovery (X360), Star Ocean 4 (X360), Resonance of Fate (X360) */
uint8_t buf[0x100];
size_t bytes;
bytes = ffmpeg_make_riff_xma2(buf, sizeof(buf), aac.num_samples, aac.stream_size, aac.channels, aac.sample_rate, aac.block_count, aac.block_size);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf, bytes, aac.stream_offset, aac.stream_size);
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, aac.stream_offset, aac.stream_size, aac.num_samples, aac.channels, aac.sample_rate, aac.block_size, aac.block_count);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
@ -261,7 +257,7 @@ static int parse_aac_v1(STREAMFILE* sf, aac_header* aac) {
aac->block_count = read_u32be(offset + 0x2c, sf);
/* one UI file has a smaller header, early version? */
if (read_u32be(offset + 0x30, sf) == 0x7374726D) {
if (is_id32be(offset + 0x30, sf, "strm")) {
aac->loop_flag = 0; /* ? */
strm_offset = 0x30;
}

View File

@ -6,6 +6,7 @@
#include "meta.h"
#include "adx_keys.h"
#include "../coding/coding.h"
#include "../util/cri_keys.h"
#ifdef VGM_DEBUG_OUTPUT
@ -280,39 +281,32 @@ static int find_adx_key(STREAMFILE* sf, uint8_t type, uint16_t *xor_start, uint1
key_size = read_key_file(keybuf, sizeof(keybuf), sf);
if (key_size > 0) {
int is_ascii = 0;
int is_keystring = 0;
/* keystrings should be ASCII, also needed to tell apart 0x06 strings from derived keys */
if (type == 8) {
is_ascii = 1;
for (i = 0; i < key_size; i++) {
if (keybuf[i] < 0x20 || keybuf[i] > 0x7f) {
is_ascii = 0;
break;
}
}
is_keystring = cri_key8_valid_keystring(keybuf, key_size);
}
if (key_size == 0x06 && !is_ascii) {
if (key_size == 0x06 && !is_keystring) {
*xor_start = get_u16be(keybuf + 0x00);
*xor_mult = get_u16be(keybuf + 0x02);
*xor_add = get_u16be(keybuf + 0x04);
return 1;
}
else if (type == 8 && is_ascii) {
else if (type == 8 && is_keystring) {
const char* keystring = (const char*)keybuf;
derive_adx_key8(keystring, xor_start, xor_mult, xor_add);
cri_key8_derive(keystring, xor_start, xor_mult, xor_add);
return 1;
}
else if (type == 9 && key_size == 0x08) {
uint64_t keycode = get_u64be(keybuf);
derive_adx_key9(keycode, subkey, xor_start, xor_mult, xor_add);
cri_key9_derive(keycode, subkey, xor_start, xor_mult, xor_add);
return 1;
}
else if (type == 9 && key_size == 0x08+0x02) {
uint64_t file_keycode = get_u64be(keybuf+0x00);
uint16_t file_subkey = get_u16be(keybuf+0x08);
derive_adx_key9(file_keycode, file_subkey, xor_start, xor_mult, xor_add);
cri_key9_derive(file_keycode, file_subkey, xor_start, xor_mult, xor_add);
return 1;
}
}
@ -438,7 +432,7 @@ static int find_adx_key(STREAMFILE* sf, uint8_t type, uint16_t *xor_start, uint1
#ifdef ADX_BRUTEFORCE
if (buf) {
keycode = get_u64be(buf + key_id);
derive_adx_key9(keycode, subkey, &key_xor, &key_mul, &key_add);
cri_key9_derive(keycode, subkey, &key_xor, &key_mul, &key_add);
}
else
#endif
@ -450,11 +444,11 @@ static int find_adx_key(STREAMFILE* sf, uint8_t type, uint16_t *xor_start, uint1
key_add = keys[key_id].add;
}
else if (type == 8 && keys[key_id].key8) {
derive_adx_key8(keys[key_id].key8, &key_xor, &key_mul, &key_add);
cri_key8_derive(keys[key_id].key8, &key_xor, &key_mul, &key_add);
}
else if (type == 9 && keys[key_id].key9) {
uint64_t keycode = keys[key_id].key9;
derive_adx_key9(keycode, subkey, &key_xor, &key_mul, &key_add);
cri_key9_derive(keycode, subkey, &key_xor, &key_mul, &key_add);
}
else {
VGM_LOG("ADX: incorrectly defined key id=%i\n", key_id);
@ -474,13 +468,13 @@ static int find_adx_key(STREAMFILE* sf, uint8_t type, uint16_t *xor_start, uint1
mul = keys[key_id].mult;
add = keys[key_id].add;
if (type == 8 && keys[key_id].key8) {
derive_adx_key8(keys[key_id].key8, &test_xor, &test_mul, &test_add);
cri_key8_derive(keys[key_id].key8, &test_xor, &test_mul, &test_add);
VGM_LOG("key8: pre=%04x %04x %04x vs calc=%04x %04x %04x = %s (\"%s\")\n",
xor,mul,add, test_xor,test_mul,test_add,
xor==test_xor && mul==test_mul && add==test_add ? "ok" : "ko", keys[key_id].key8);
}
else if (type == 9 && keys[key_id].key9) {
derive_adx_key9(keys[key_id].key9, subkey, &test_xor, &test_mul, &test_add);
cri_key9_derive(keys[key_id].key9, subkey, &test_xor, &test_mul, &test_add);
VGM_LOG("key9: pre=%04x %04x %04x vs calc=%04x %04x %04x = %s (%"PRIu64")\n",
xor,mul,add, test_xor,test_mul,test_add,
xor==test_xor && mul==test_mul && add==test_add ? "ok" : "ko", keys[key_id].key9);

View File

@ -1,6 +1,8 @@
#ifndef _ADX_KEYS_H_
#define _ADX_KEYS_H_
#include <stdint.h>
#include <string.h>
typedef struct {
uint16_t start, mult, add; /* XOR values derived from the actual key */
@ -53,7 +55,7 @@ static const adxkey_info adxkey8_list[] = {
{0x55b7,0x6191,0x5a77, "morio",0},
/* Amagami (PS2) [Enterbrain] */
{0x5a17,0x509f,0x5bfd, "mituba",0}, /* also AHX key */
{0x5a17,0x509f,0x5bfd, "mituba",0},
/* Yamasa Digi Portable: Matsuri no Tatsujin (PSP) [Yamasa] */
{0x4c01,0x549d,0x676f, "7fa0xB9tw3",0},
@ -122,7 +124,7 @@ static const adxkey_info adxkey8_list[] = {
{0x4c73,0x4d8d,0x5827, "URABOKU-penguin",0},
/* StormLover!! (PSP), StormLover Kai!! (PSP) [Vridge] */
{0x5a11,0x67e5,0x6751, "HEXDPFMDKPQW",0}, /* unknown AHX key */
{0x5a11,0x67e5,0x6751, "HEXDPFMDKPQW",0},
/* Sora no Otoshimono: DokiDoki Summer Vacation (PSP) [Kadokawa Shoten] */
{0x5e75,0x4a89,0x4c61, "funen-gomi",0},
@ -131,25 +133,26 @@ static const adxkey_info adxkey8_list[] = {
{0x64ab,0x5297,0x632f, "sonic",0},
/* Lucky Star: Net Idol Meister (PSP) [Vridge, Kadokawa Shoten] */
{0x4d81,0x5243,0x58c7, "JJOLIFJLE",0}, /* unknown AHX key */
/* Baka to Test to Shoukanjuu Portable (PSP) */
{0x4d81,0x5243,0x58c7, "JJOLIFJLE",0},
/* Ishin Renka: Ryouma Gaiden (PSP) [Vridge] */
{0x54d1,0x526d,0x5e8b, "LQAFJOIEJ",0}, /* unknown AHX key */
{0x54d1,0x526d,0x5e8b, "LQAFJOIEJ",0},
/* Lucky Star: Ryouou Gakuen Outousai Portable (PSP) [Vridge] */
{0x4d05,0x663b,0x6343, "IUNOIRU",0}, /* unknown AHX key */
{0x4d05,0x663b,0x6343, "IUNOIRU",0},
/* Marriage Royale: Prism Story (PSP) [Vridge] */
{0x40a9,0x46b1,0x62ad, "ROYMAR",0}, /* unknown AHX key */
{0x40a9,0x46b1,0x62ad, "ROYMAR",0},
/* Nogizaka Haruka no Himitsu: Doujinshi Hajimemashita (PSP) [Vridge] */
{0x4609,0x671f,0x4b65, "CLKMEOUHFLIE",0}, /* unknown AHX key */
{0x4609,0x671f,0x4b65, "CLKMEOUHFLIE",0},
/* Slotter Mania P: Mach Go Go Go III (PSP) [Dorart] */
{0x41ef,0x463d,0x5507, "SGGK",0},
/* Nichijou: Uchuujin (PSP) [Vridge] */
{0x4369,0x486d,0x5461, "LJLOUHIU787",0}, /* unknown AHX key */
{0x4369,0x486d,0x5461, "LJLOUHIU787",0},
/* R-15 Portable (PSP) [Kadokawa Shoten] */
{0x6809,0x5fd5,0x5bb1, "R-15(Heart)Love",0},
@ -158,7 +161,7 @@ static const adxkey_info adxkey8_list[] = {
{0x5c33,0x4133,0x4ce7, "bi88a#fas",0},
/* StormLover Natsu Koi!! (PSP) [Vridge] */
{0x4133,0x5a01,0x5723, "LIKDFJUIDJOQ",0}, /* unknown AHX key */
{0x4133,0x5a01,0x5723, "LIKDFJUIDJOQ",0},
/* Shounen Onmyouji: Tsubasa yo Ima, Sora e Kaere (PS2) [Kadokawa Shoten] */
{0x55d9,0x46d3,0x5b01, "SONMYOJI",0},
@ -272,129 +275,4 @@ static const adxkey_info adxkey9_list[] = {
static const int adxkey8_list_count = sizeof(adxkey8_list) / sizeof(adxkey8_list[0]);
static const int adxkey9_list_count = sizeof(adxkey9_list) / sizeof(adxkey9_list[0]);
/* preloaded list used to derive keystrings from ADX_Decoder, found in executables (see VGAudio for how to calculate) */
static const uint16_t key8_primes[0x400] = {
0x401B,0x4021,0x4025,0x402B,0x4031,0x403F,0x4043,0x4045,0x405D,0x4061,0x4067,0x406D,0x4087,0x4091,0x40A3,0x40A9,
0x40B1,0x40B7,0x40BD,0x40DB,0x40DF,0x40EB,0x40F7,0x40F9,0x4109,0x410B,0x4111,0x4115,0x4121,0x4133,0x4135,0x413B,
0x413F,0x4159,0x4165,0x416B,0x4177,0x417B,0x4193,0x41AB,0x41B7,0x41BD,0x41BF,0x41CB,0x41E7,0x41EF,0x41F3,0x41F9,
0x4205,0x4207,0x4219,0x421F,0x4223,0x4229,0x422F,0x4243,0x4253,0x4255,0x425B,0x4261,0x4273,0x427D,0x4283,0x4285,
0x4289,0x4291,0x4297,0x429D,0x42B5,0x42C5,0x42CB,0x42D3,0x42DD,0x42E3,0x42F1,0x4307,0x430F,0x431F,0x4325,0x4327,
0x4333,0x4337,0x4339,0x434F,0x4357,0x4369,0x438B,0x438D,0x4393,0x43A5,0x43A9,0x43AF,0x43B5,0x43BD,0x43C7,0x43CF,
0x43E1,0x43E7,0x43EB,0x43ED,0x43F1,0x43F9,0x4409,0x440B,0x4417,0x4423,0x4429,0x443B,0x443F,0x4445,0x444B,0x4451,
0x4453,0x4459,0x4465,0x446F,0x4483,0x448F,0x44A1,0x44A5,0x44AB,0x44AD,0x44BD,0x44BF,0x44C9,0x44D7,0x44DB,0x44F9,
0x44FB,0x4505,0x4511,0x4513,0x452B,0x4531,0x4541,0x4549,0x4553,0x4555,0x4561,0x4577,0x457D,0x457F,0x458F,0x45A3,
0x45AD,0x45AF,0x45BB,0x45C7,0x45D9,0x45E3,0x45EF,0x45F5,0x45F7,0x4601,0x4603,0x4609,0x4613,0x4625,0x4627,0x4633,
0x4639,0x463D,0x4643,0x4645,0x465D,0x4679,0x467B,0x467F,0x4681,0x468B,0x468D,0x469D,0x46A9,0x46B1,0x46C7,0x46C9,
0x46CF,0x46D3,0x46D5,0x46DF,0x46E5,0x46F9,0x4705,0x470F,0x4717,0x4723,0x4729,0x472F,0x4735,0x4739,0x474B,0x474D,
0x4751,0x475D,0x476F,0x4771,0x477D,0x4783,0x4787,0x4789,0x4799,0x47A5,0x47B1,0x47BF,0x47C3,0x47CB,0x47DD,0x47E1,
0x47ED,0x47FB,0x4801,0x4807,0x480B,0x4813,0x4819,0x481D,0x4831,0x483D,0x4847,0x4855,0x4859,0x485B,0x486B,0x486D,
0x4879,0x4897,0x489B,0x48A1,0x48B9,0x48CD,0x48E5,0x48EF,0x48F7,0x4903,0x490D,0x4919,0x491F,0x492B,0x4937,0x493D,
0x4945,0x4955,0x4963,0x4969,0x496D,0x4973,0x4997,0x49AB,0x49B5,0x49D3,0x49DF,0x49E1,0x49E5,0x49E7,0x4A03,0x4A0F,
0x4A1D,0x4A23,0x4A39,0x4A41,0x4A45,0x4A57,0x4A5D,0x4A6B,0x4A7D,0x4A81,0x4A87,0x4A89,0x4A8F,0x4AB1,0x4AC3,0x4AC5,
0x4AD5,0x4ADB,0x4AED,0x4AEF,0x4B07,0x4B0B,0x4B0D,0x4B13,0x4B1F,0x4B25,0x4B31,0x4B3B,0x4B43,0x4B49,0x4B59,0x4B65,
0x4B6D,0x4B77,0x4B85,0x4BAD,0x4BB3,0x4BB5,0x4BBB,0x4BBF,0x4BCB,0x4BD9,0x4BDD,0x4BDF,0x4BE3,0x4BE5,0x4BE9,0x4BF1,
0x4BF7,0x4C01,0x4C07,0x4C0D,0x4C0F,0x4C15,0x4C1B,0x4C21,0x4C2D,0x4C33,0x4C4B,0x4C55,0x4C57,0x4C61,0x4C67,0x4C73,
0x4C79,0x4C7F,0x4C8D,0x4C93,0x4C99,0x4CCD,0x4CE1,0x4CE7,0x4CF1,0x4CF3,0x4CFD,0x4D05,0x4D0F,0x4D1B,0x4D27,0x4D29,
0x4D2F,0x4D33,0x4D41,0x4D51,0x4D59,0x4D65,0x4D6B,0x4D81,0x4D83,0x4D8D,0x4D95,0x4D9B,0x4DB1,0x4DB3,0x4DC9,0x4DCF,
0x4DD7,0x4DE1,0x4DED,0x4DF9,0x4DFB,0x4E05,0x4E0B,0x4E17,0x4E19,0x4E1D,0x4E2B,0x4E35,0x4E37,0x4E3D,0x4E4F,0x4E53,
0x4E5F,0x4E67,0x4E79,0x4E85,0x4E8B,0x4E91,0x4E95,0x4E9B,0x4EA1,0x4EAF,0x4EB3,0x4EB5,0x4EC1,0x4ECD,0x4ED1,0x4ED7,
0x4EE9,0x4EFB,0x4F07,0x4F09,0x4F19,0x4F25,0x4F2D,0x4F3F,0x4F49,0x4F63,0x4F67,0x4F6D,0x4F75,0x4F7B,0x4F81,0x4F85,
0x4F87,0x4F91,0x4FA5,0x4FA9,0x4FAF,0x4FB7,0x4FBB,0x4FCF,0x4FD9,0x4FDB,0x4FFD,0x4FFF,0x5003,0x501B,0x501D,0x5029,
0x5035,0x503F,0x5045,0x5047,0x5053,0x5071,0x5077,0x5083,0x5093,0x509F,0x50A1,0x50B7,0x50C9,0x50D5,0x50E3,0x50ED,
0x50EF,0x50FB,0x5107,0x510B,0x510D,0x5111,0x5117,0x5123,0x5125,0x5135,0x5147,0x5149,0x5171,0x5179,0x5189,0x518F,
0x5197,0x51A1,0x51A3,0x51A7,0x51B9,0x51C1,0x51CB,0x51D3,0x51DF,0x51E3,0x51F5,0x51F7,0x5209,0x5213,0x5215,0x5219,
0x521B,0x521F,0x5227,0x5243,0x5245,0x524B,0x5261,0x526D,0x5273,0x5281,0x5293,0x5297,0x529D,0x52A5,0x52AB,0x52B1,
0x52BB,0x52C3,0x52C7,0x52C9,0x52DB,0x52E5,0x52EB,0x52FF,0x5315,0x531D,0x5323,0x5341,0x5345,0x5347,0x534B,0x535D,
0x5363,0x5381,0x5383,0x5387,0x538F,0x5395,0x5399,0x539F,0x53AB,0x53B9,0x53DB,0x53E9,0x53EF,0x53F3,0x53F5,0x53FB,
0x53FF,0x540D,0x5411,0x5413,0x5419,0x5435,0x5437,0x543B,0x5441,0x5449,0x5453,0x5455,0x545F,0x5461,0x546B,0x546D,
0x5471,0x548F,0x5491,0x549D,0x54A9,0x54B3,0x54C5,0x54D1,0x54DF,0x54E9,0x54EB,0x54F7,0x54FD,0x5507,0x550D,0x551B,
0x5527,0x552B,0x5539,0x553D,0x554F,0x5551,0x555B,0x5563,0x5567,0x556F,0x5579,0x5585,0x5597,0x55A9,0x55B1,0x55B7,
0x55C9,0x55D9,0x55E7,0x55ED,0x55F3,0x55FD,0x560B,0x560F,0x5615,0x5617,0x5623,0x562F,0x5633,0x5639,0x563F,0x564B,
0x564D,0x565D,0x565F,0x566B,0x5671,0x5675,0x5683,0x5689,0x568D,0x568F,0x569B,0x56AD,0x56B1,0x56D5,0x56E7,0x56F3,
0x56FF,0x5701,0x5705,0x5707,0x570B,0x5713,0x571F,0x5723,0x5747,0x574D,0x575F,0x5761,0x576D,0x5777,0x577D,0x5789,
0x57A1,0x57A9,0x57AF,0x57B5,0x57C5,0x57D1,0x57D3,0x57E5,0x57EF,0x5803,0x580D,0x580F,0x5815,0x5827,0x582B,0x582D,
0x5855,0x585B,0x585D,0x586D,0x586F,0x5873,0x587B,0x588D,0x5897,0x58A3,0x58A9,0x58AB,0x58B5,0x58BD,0x58C1,0x58C7,
0x58D3,0x58D5,0x58DF,0x58F1,0x58F9,0x58FF,0x5903,0x5917,0x591B,0x5921,0x5945,0x594B,0x594D,0x5957,0x595D,0x5975,
0x597B,0x5989,0x5999,0x599F,0x59B1,0x59B3,0x59BD,0x59D1,0x59DB,0x59E3,0x59E9,0x59ED,0x59F3,0x59F5,0x59FF,0x5A01,
0x5A0D,0x5A11,0x5A13,0x5A17,0x5A1F,0x5A29,0x5A2F,0x5A3B,0x5A4D,0x5A5B,0x5A67,0x5A77,0x5A7F,0x5A85,0x5A95,0x5A9D,
0x5AA1,0x5AA3,0x5AA9,0x5ABB,0x5AD3,0x5AE5,0x5AEF,0x5AFB,0x5AFD,0x5B01,0x5B0F,0x5B19,0x5B1F,0x5B25,0x5B2B,0x5B3D,
0x5B49,0x5B4B,0x5B67,0x5B79,0x5B87,0x5B97,0x5BA3,0x5BB1,0x5BC9,0x5BD5,0x5BEB,0x5BF1,0x5BF3,0x5BFD,0x5C05,0x5C09,
0x5C0B,0x5C0F,0x5C1D,0x5C29,0x5C2F,0x5C33,0x5C39,0x5C47,0x5C4B,0x5C4D,0x5C51,0x5C6F,0x5C75,0x5C77,0x5C7D,0x5C87,
0x5C89,0x5CA7,0x5CBD,0x5CBF,0x5CC3,0x5CC9,0x5CD1,0x5CD7,0x5CDD,0x5CED,0x5CF9,0x5D05,0x5D0B,0x5D13,0x5D17,0x5D19,
0x5D31,0x5D3D,0x5D41,0x5D47,0x5D4F,0x5D55,0x5D5B,0x5D65,0x5D67,0x5D6D,0x5D79,0x5D95,0x5DA3,0x5DA9,0x5DAD,0x5DB9,
0x5DC1,0x5DC7,0x5DD3,0x5DD7,0x5DDD,0x5DEB,0x5DF1,0x5DFD,0x5E07,0x5E0D,0x5E13,0x5E1B,0x5E21,0x5E27,0x5E2B,0x5E2D,
0x5E31,0x5E39,0x5E45,0x5E49,0x5E57,0x5E69,0x5E73,0x5E75,0x5E85,0x5E8B,0x5E9F,0x5EA5,0x5EAF,0x5EB7,0x5EBB,0x5ED9,
0x5EFD,0x5F09,0x5F11,0x5F27,0x5F33,0x5F35,0x5F3B,0x5F47,0x5F57,0x5F5D,0x5F63,0x5F65,0x5F77,0x5F7B,0x5F95,0x5F99,
0x5FA1,0x5FB3,0x5FBD,0x5FC5,0x5FCF,0x5FD5,0x5FE3,0x5FE7,0x5FFB,0x6011,0x6023,0x602F,0x6037,0x6053,0x605F,0x6065,
0x606B,0x6073,0x6079,0x6085,0x609D,0x60AD,0x60BB,0x60BF,0x60CD,0x60D9,0x60DF,0x60E9,0x60F5,0x6109,0x610F,0x6113,
0x611B,0x612D,0x6139,0x614B,0x6155,0x6157,0x615B,0x616F,0x6179,0x6187,0x618B,0x6191,0x6193,0x619D,0x61B5,0x61C7,
0x61C9,0x61CD,0x61E1,0x61F1,0x61FF,0x6209,0x6217,0x621D,0x6221,0x6227,0x623B,0x6241,0x624B,0x6251,0x6253,0x625F,
0x6265,0x6283,0x628D,0x6295,0x629B,0x629F,0x62A5,0x62AD,0x62D5,0x62D7,0x62DB,0x62DD,0x62E9,0x62FB,0x62FF,0x6305,
0x630D,0x6317,0x631D,0x632F,0x6341,0x6343,0x634F,0x635F,0x6367,0x636D,0x6371,0x6377,0x637D,0x637F,0x63B3,0x63C1,
0x63C5,0x63D9,0x63E9,0x63EB,0x63EF,0x63F5,0x6401,0x6403,0x6409,0x6415,0x6421,0x6427,0x642B,0x6439,0x6443,0x6449,
0x644F,0x645D,0x6467,0x6475,0x6485,0x648D,0x6493,0x649F,0x64A3,0x64AB,0x64C1,0x64C7,0x64C9,0x64DB,0x64F1,0x64F7,
0x64F9,0x650B,0x6511,0x6521,0x652F,0x6539,0x653F,0x654B,0x654D,0x6553,0x6557,0x655F,0x6571,0x657D,0x658D,0x658F,
0x6593,0x65A1,0x65A5,0x65AD,0x65B9,0x65C5,0x65E3,0x65F3,0x65FB,0x65FF,0x6601,0x6607,0x661D,0x6629,0x6631,0x663B,
0x6641,0x6647,0x664D,0x665B,0x6661,0x6673,0x667D,0x6689,0x668B,0x6695,0x6697,0x669B,0x66B5,0x66B9,0x66C5,0x66CD,
0x66D1,0x66E3,0x66EB,0x66F5,0x6703,0x6713,0x6719,0x671F,0x6727,0x6731,0x6737,0x673F,0x6745,0x6751,0x675B,0x676F,
0x6779,0x6781,0x6785,0x6791,0x67AB,0x67BD,0x67C1,0x67CD,0x67DF,0x67E5,0x6803,0x6809,0x6811,0x6817,0x682D,0x6839,
};
static void derive_adx_key8(const char* key8, uint16_t* p_start, uint16_t* p_mult, uint16_t* p_add) {
size_t key_size;
uint16_t start = 0, mult = 0, add = 0;
int i;
if (key8 == NULL || key8[0] == '\0') /* strlen >= 1 */
goto end;
/* calcs as found in exes, though there is some unrolling in the original code */
key_size = strlen(key8);
start = key8_primes[0x100];
mult = key8_primes[0x200];
add = key8_primes[0x300];
for (i = 0; i < key_size; i++) {
char c = key8[i];
start = key8_primes[start * key8_primes[c + 0x80] % 0x400];
mult = key8_primes[mult * key8_primes[c + 0x80] % 0x400];
add = key8_primes[add * key8_primes[c + 0x80] % 0x400];
}
end:
*p_start = start;
*p_mult = mult;
*p_add = add;
}
static void derive_adx_key9(uint64_t key9, uint16_t subkey, uint16_t* p_start, uint16_t* p_mult, uint16_t* p_add) {
uint16_t start = 0, mult = 0, add = 0;
/* 0 is ignored by CRI's encoder, only from 1..18446744073709551615 */
if (key9 == 0)
goto end;
if (subkey) {
key9 = key9 * ( ((uint64_t)subkey << 16u) | ((uint16_t)~subkey + 2u) );
}
key9--;
start = (int)(((key9 >> 27) & 0x7fff));
mult = (int)(((key9 >> 12) & 0x7ffc) | 1);
add = (int)(((key9 << 1 ) & 0x7fff) | 1);
/* alt from ADX_Decoder, probably the same */
//start = ((key9 >> 27) & 0x7FFF);
//mult = ((key9 >> 12) & 0x7FFC) | 1;
//add = ((key9 << 1 ) & 0x7FFE) | 1;
//mult |= add << 16;
end:
*p_start = start;
*p_mult = mult;
*p_add = add;
}
#endif/*_ADX_KEYS_H_*/

View File

@ -1,10 +1,13 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util.h"
#if 0
#include "adx_keys.h"
#include "ahx_keys.h"
#include "../util/cri_keys.h"
#ifdef VGM_USE_MPEG
static int find_ahx_key(STREAMFILE* sf, off_t offset, crikey_t* crikey);
#endif
/* AHX - CRI voice format */
VGMSTREAM* init_vgmstream_ahx(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
@ -23,7 +26,7 @@ VGMSTREAM* init_vgmstream_ahx(STREAMFILE* sf) {
read_u32be(start_offset - 0x04,sf) != 0x29435249) /* ")CRI" */
goto fail;
/* types: 0x10 = AHX for DC with bigger frames, 0x11 = AHX, 0x0N = ADX */
/* types: 0x10 = AHX for DC with fixed MPEG frame bits (bigger frames), 0x11 = standard AHX, 0x0N = ADX */
type = read_u8(0x04,sf);
if (type != 0x10 && type != 0x11) goto fail;
@ -52,40 +55,13 @@ VGMSTREAM* init_vgmstream_ahx(STREAMFILE* sf) {
{
#ifdef VGM_USE_MPEG
mpeg_custom_config cfg = {0};
crikey_t* crikey = &cfg.crikey;
cfg.encryption = read_u8(0x13,sf); /* 0x08 = keyword encryption */
cfg.cri_type = type;
cfg.encryption = read_u8(0x13,sf); /* only type 0x08 is known */
crikey->type = cfg.encryption;
if (cfg.encryption) {
uint8_t keybuf[0x10+1] = {0}; /* approximate max for keystrings, +1 extra null for keystrings */
size_t key_size;
key_size = read_key_file(keybuf, sizeof(keybuf), sf);
if (key_size > 0) {
#if 0
int i, is_ascii;
is_ascii = 1;
for (i = 0; i < key_size; i++) {
if (keybuf[i] < 0x20 || keybuf[i] > 0x7f) {
is_ascii = 0;
break;
}
}
#endif
if (key_size == 0x06 /*&& !is_ascii*/) {
cfg.cri_key1 = get_u16be(keybuf + 0x00);
cfg.cri_key2 = get_u16be(keybuf + 0x02);
cfg.cri_key3 = get_u16be(keybuf + 0x04);
}
#if 0
else if (is_ascii) {
const char* keystring = (const char*)keybuf;
derive_adx_key8(keystring, &cfg.cri_key1, &cfg.cri_key2, &cfg.cri_key3);
VGM_LOG("ok: %x, %x, %x\n", cfg.cri_key1, cfg.cri_key2, cfg.cri_key3 );
}
#endif
}
find_ahx_key(sf, start_offset, crikey);
}
vgmstream->layout_type = layout_none;
@ -104,3 +80,80 @@ fail:
close_vgmstream(vgmstream);
return NULL;
}
#ifdef VGM_USE_MPEG
static int find_ahx_keyfile(STREAMFILE* sf, crikey_t* crikey) {
uint8_t keybuf[0x10+1] = {0}; /* approximate max for keystrings, +1 extra null for keystrings */
size_t key_size;
int is_keystring = 0;
key_size = read_key_file(keybuf, sizeof(keybuf) - 1, sf);
if (key_size <= 0)
goto fail;
if (crikey->type == 8) {
is_keystring = cri_key8_valid_keystring(keybuf, key_size);
}
if (key_size == 0x06 && !is_keystring) {
crikey->key1 = get_u16be(keybuf + 0x00);
crikey->key2 = get_u16be(keybuf + 0x02);
crikey->key3 = get_u16be(keybuf + 0x04);
}
else if (crikey->type == 8 && is_keystring) {
const char* keystring = (const char*)keybuf;
cri_key8_derive(keystring, &crikey->key1, &crikey->key2, &crikey->key3);
}
else {
goto fail;
}
return 1;
fail:
return 0;
}
static int find_ahx_keylist(STREAMFILE* sf, off_t offset, crikey_t* crikey) {
int i;
int keycount = ahxkey8_list_count;
const ahxkey_info* keys = ahxkey8_list;
for (i = 0; i < keycount; i++) {
if (crikey->type == 0x08) {
cri_key8_derive(keys[i].key8, &crikey->key1, &crikey->key2, &crikey->key3);
//;VGM_LOG("AHX: testing %s [%04x %04x %04x]\n", keys[i].key8, crikey->key1, crikey->key2, crikey->key3);
}
else {
continue;
}
if (test_ahx_key(sf, offset, crikey)) {
//;VGM_LOG("AHX key found\n");
return 1;
}
}
return 0;
}
static int find_ahx_key(STREAMFILE* sf, off_t offset, crikey_t* crikey) {
int ok;
ok = find_ahx_keyfile(sf, crikey);
if (ok)
return 1;
ok = find_ahx_keylist(sf, offset, crikey);
if (ok)
return 1;
crikey->key1 = 0;
crikey->key2 = 0;
crikey->key3 = 0;
vgm_logi("AHX: decryption key not found\n");
return 0;
}
#endif

View File

@ -0,0 +1,52 @@
#ifndef _AHX_KEYS_H_
#define _AHX_KEYS_H_
#include <stdint.h>
#include <string.h>
typedef struct {
const char* key8; /* keystring used by type 8 encryption */
uint64_t key9; /* reserved (not seen) */
} ahxkey_info;
/**
* List of known keys, from exes. Generally same as ADX keys as CRI's key init seems shared.
*/
static const ahxkey_info ahxkey8_list[] = {
/* Amagami (PS2) [Enterbrain] */
{"mituba",0},
/* StormLover!! (PSP), StormLover Kai!! (PSP) [Vridge] */
{"HEXDPFMDKPQW",0},
/* Lucky Star: Net Idol Meister (PSP) [Vridge, Kadokawa Shoten] */
/* Baka to Test to Shoukanjuu Portable (PSP) */
{"JJOLIFJLE",0},
/* Ishin Renka: Ryouma Gaiden (PSP) [Vridge] */
{"LQAFJOIEJ",0},
/* Lucky Star: Ryouou Gakuen Outousai Portable (PSP) [Vridge] */
{"IUNOIRU",0},
/* Marriage Royale: Prism Story (PSP) [Vridge] */
{"ROYMAR",0},
/* Nogizaka Haruka no Himitsu: Doujinshi Hajimemashita (PSP) [Vridge] */
{"CLKMEOUHFLIE",0},
/* Nichijou: Uchuujin (PSP) [Vridge] */
{"LJLOUHIU787",0},
/* StormLover Natsu Koi!! (PSP) [Vridge] */
{"LIKDFJUIDJOQ",0},
/* Corpse Party: Book of Shadows (PSP) */
{"\x83\x76\x83\x89\x83\x60\x83\x69Lovers_Day",0}, // "プラチナLovers_Day" in SHIFT-JIS
};
static const int ahxkey8_list_count = sizeof(ahxkey8_list) / sizeof(ahxkey8_list[0]);
#endif /* _AHX_KEYS_H_ */

View File

@ -3,38 +3,6 @@
#include "sqex_streamfile.h"
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
/* AKB (AAC only) - found in SQEX iOS games */
VGMSTREAM * init_vgmstream_akb_mp4(STREAMFILE *sf) {
VGMSTREAM * vgmstream = NULL;
size_t filesize;
uint32_t loop_start, loop_end;
if ((uint32_t)read_32bitBE(0, sf) != 0x414b4220) goto fail;
loop_start = read_s32le(0x14, sf);
loop_end = read_s32le(0x18, sf);
filesize = get_streamfile_size( sf );
vgmstream = init_vgmstream_mp4_aac_offset( sf, 0x20, filesize - 0x20 );
if ( !vgmstream ) goto fail;
if ( loop_start || loop_end ) {
vgmstream->loop_flag = 1;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
}
return vgmstream;
fail:
return NULL;
}
#endif
/* AKB - found in SQEX 'sdlib' iOS/Android games */
VGMSTREAM* init_vgmstream_akb(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;

View File

@ -0,0 +1,83 @@
#include "meta.h"
#include "../coding/coding.h"
/* ASTB - found in Dead Rising (X360) */
VGMSTREAM* init_vgmstream_astb(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset, data_size;
int loop_flag, channels;
int i, xma_streams;
/* check */
if (!is_id32be(0x00,sf, "ASTB"))
goto fail;
if (!check_extensions(sf,"ast"))
goto fail;
if (read_u32be(0x04,sf) != get_streamfile_size(sf))
goto fail;
if (read_u16be(0x30,sf) != 0x165) /* only seen XMA1 */
goto fail;
start_offset = read_u32be(0x10,sf);
data_size = read_u32be(0x20,sf);
xma_streams = read_u16be(0x38,sf);
loop_flag = read_u8(0x3a,sf);
channels = 0; /* sum of all stream channels (though only 1/2ch ever seen) */
for (i = 0; i < xma_streams; i++) {
channels += read_u8(0x3c + 0x14 * i + 0x11,sf);
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_s32be(0x40,sf);
vgmstream->meta_type = meta_ASTB;
{
/* manually find sample offsets (XMA1 nonsense again) */
ms_sample_data msd = {0};
msd.xma_version = 1;
msd.channels = channels;
msd.data_offset = start_offset;
msd.data_size = data_size;
msd.loop_flag = loop_flag;
msd.loop_start_b = read_u32be(0x44,sf);
msd.loop_end_b = read_u32be(0x48,sf);
msd.loop_start_subframe = read_u8(0x4c,sf) & 0xF; /* lower 4b: subframe where the loop starts, 0..4 */
msd.loop_end_subframe = read_u8(0x4c,sf) >> 4; /* upper 4b: subframe where the loop ends, 0..3 */
xma_get_samples(&msd, sf);
vgmstream->num_samples = msd.num_samples;
vgmstream->loop_start_sample = msd.loop_start_sample;
vgmstream->loop_end_sample = msd.loop_end_sample;
}
#ifdef VGM_USE_FFMPEG
{
off_t fmt_offset = 0x30;
size_t fmt_size = 0x0c + xma_streams * 0x14;
/* XMA1 "fmt" chunk @ 0x20 (BE, unlike the usual LE) */
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, data_size, fmt_offset, fmt_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, sf, start_offset, data_size, fmt_offset, 1,1);
}
#else
goto fail;
#endif
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,71 +1,48 @@
#include "meta.h"
#include "../util.h"
/* AUS (found in various Capcom games) */
VGMSTREAM * init_vgmstream_aus(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
/* AUS - Atomic Planet games [Jackie Chan Adventures (PS2), Mega Man Anniversary Collection (PS2/Xbox)] */
VGMSTREAM* init_vgmstream_aus(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag = 0;
int channel_count;
int loop_flag, channels, codec;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("aus",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x41555320) /* "AUS " */
/* checks */
if (!is_id32be(0x00, sf, "AUS "))
goto fail;
if (!check_extensions(sf, "aus"))
goto fail;
loop_flag = (read_32bitLE(0x0c,streamFile)!=0);
channel_count = read_32bitLE(0xC,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
channels = read_u32le(0x0c,sf);
start_offset = 0x800;
codec = read_u16le(0x06,sf);
loop_flag = (read_u32le(0x1c,sf) == 1); /* games seem to just do full loops, even when makes no sense (jingles/megaman stages) */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x800;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->num_samples = read_32bitLE(0x08,streamFile);
vgmstream->meta_type = meta_AUS;
vgmstream->sample_rate = read_s32le(0x10,sf); /* uses pretty odd values */
vgmstream->num_samples = read_s32le(0x08,sf);
vgmstream->loop_start_sample = read_s32le(0x14,sf); /* always 0? */
vgmstream->loop_end_sample = read_s32le(0x18,sf); /* always samples? */
if(read_16bitLE(0x06,streamFile)==0x02) {
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type=layout_none;
} else {
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x800;
}
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile);
vgmstream->loop_end_sample = read_32bitLE(0x08,streamFile);
}
vgmstream->meta_type = meta_AUS;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
if (codec == 0x02) {
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
}
else {
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x800;
}
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -70,9 +70,7 @@ VGMSTREAM* init_vgmstream_awc(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 0x05: { /* XMA2 (X360) */
uint8_t buf[0x100];
size_t bytes, block_size, block_count, substream_size;
off_t substream_offset;
uint32_t substream_size, substream_offset;
if (awc.is_music) {
/* 1ch XMAs in blocks, we'll use layered layout + custom IO to get multi-FFmpegs working */
@ -95,26 +93,22 @@ VGMSTREAM* init_vgmstream_awc(STREAMFILE* sf) {
data->layers[i] = allocate_vgmstream(layer_channels, 0);
if (!data->layers[i]) goto fail;
data->layers[i]->sample_rate = awc.sample_rate;
data->layers[i]->meta_type = meta_AWC;
data->layers[i]->coding_type = coding_FFmpeg;
data->layers[i]->layout_type = layout_none;
data->layers[i]->sample_rate = awc.sample_rate;
data->layers[i]->num_samples = awc.num_samples;
/* setup custom IO streamfile, pass to FFmpeg and hope it's fooled */
temp_sf = setup_awc_xma_streamfile(sf, awc.stream_offset, awc.stream_size, awc.block_chunk, awc.channels, i);
if (!temp_sf) goto fail;
substream_offset = 0; /* where FFmpeg thinks data starts, which our custom sf will clamp */
substream_offset = 0x00; /* where FFmpeg thinks data starts, which our custom sf will clamp */
substream_size = get_streamfile_size(temp_sf); /* data of one XMA substream without blocks */
block_size = 0x8000; /* no idea */
block_count = substream_size / block_size; /* not accurate but not needed */
bytes = ffmpeg_make_riff_xma2(buf, 0x100, awc.num_samples, substream_size, layer_channels, awc.sample_rate, block_count, block_size);
data->layers[i]->codec_data = init_ffmpeg_header_offset(temp_sf, buf,bytes, substream_offset,substream_size);
xma_fix_raw_samples(data->layers[i], temp_sf, substream_offset,substream_size, 0, 0,0); /* samples are ok? */
data->layers[i]->codec_data = init_ffmpeg_xma2_raw(temp_sf, substream_offset, substream_size, awc.num_samples, layer_channels, awc.sample_rate, 0, 0);
if (data->layers[i])
xma_fix_raw_samples(data->layers[i], temp_sf, substream_offset, substream_size, 0, 0,0); /* samples are ok? */
close_streamfile(temp_sf);
if (!data->layers[i]->codec_data) goto fail;
}
@ -125,11 +119,7 @@ VGMSTREAM* init_vgmstream_awc(STREAMFILE* sf) {
}
else {
/* regular XMA for sfx */
block_size = 0x8000; /* no idea */
block_count = awc.stream_size / block_size; /* not accurate but not needed */
bytes = ffmpeg_make_riff_xma2(buf, 0x100, awc.num_samples, awc.stream_size, awc.channels, awc.sample_rate, block_count, block_size);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, awc.stream_offset,awc.stream_size);
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, awc.stream_offset, awc.stream_size, awc.num_samples, awc.channels, awc.sample_rate, 0, 0);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -179,11 +179,7 @@ VGMSTREAM * init_vgmstream_baf(STREAMFILE *sf) {
#ifdef VGM_USE_FFMPEG
case 0x08: {
uint8_t buf[0x100];
int bytes;
bytes = ffmpeg_make_riff_xma1(buf,0x100, 0, stream_size, vgmstream->channels, vgmstream->sample_rate, 0);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,stream_size);
vgmstream->codec_data = init_ffmpeg_xma1_raw(sf, start_offset, stream_size, vgmstream->channels, vgmstream->sample_rate, 0);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
@ -229,58 +225,3 @@ fail:
close_vgmstream(vgmstream);
return NULL;
}
/* awful PS3 splits of the above with bad offsets and all */
VGMSTREAM * init_vgmstream_baf_badrip(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t WAVE_size, stream_size;
off_t start_offset;
long sample_count;
int sample_rate;
const int frame_size = 33;
const int frame_samples = (frame_size-1) * 2;
int channels;
int loop_flag = 0;
/* checks */
if ( !check_extensions(streamFile, "baf") )
goto fail;
if (read_32bitBE(0,streamFile) != 0x57415645) /* "WAVE" */
goto fail;
WAVE_size = read_32bitBE(4,streamFile);
if (WAVE_size != 0x4c) /* && WAVE_size != 0x50*/
goto fail;
if (read_32bitBE(WAVE_size,streamFile) != 0x44415441) /* "DATA"*/
goto fail;
/* check that WAVE size is data size */
stream_size = read_32bitBE(0x30,streamFile);
if (read_32bitBE(WAVE_size+4,streamFile)-8 != stream_size) goto fail;
sample_count = read_32bitBE(0x44,streamFile);
sample_rate = read_32bitBE(0x40,streamFile);
/* unsure how to detect channel count, so use a hack */
channels = (long long)stream_size / frame_size * frame_samples / sample_count;
start_offset = WAVE_size + 8;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = sample_count;
vgmstream->coding_type = coding_PSX_cfg;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = frame_size;
vgmstream->meta_type = meta_BAF;
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -28,10 +28,10 @@ VGMSTREAM* init_vgmstream_bfstm(STREAMFILE* sf) {
/* checks */
if (!check_extensions(sf,"bfstm"))
goto fail;
if (!is_id32be(0x00,sf, "FSTM"))
goto fail;
if (!check_extensions(sf,"bfstm"))
goto fail;
/* 0x06(2): header size (0x40)
* 0x08: version (0x00000400)
* 0x0c: file size */

View File

@ -54,7 +54,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
data_offset = read_u32(0x10,sf);
data_size = read_u32(0x14,sf);
/* when sblk_offset >= 0x20: */
/* 0x18: ZLSD small footer, rare [Yakuza 6's Puyo Puyo (PS4)] */
/* 0x18: ZLSD small footer, rare in earlier versions [Yakuza 6's Puyo Puyo (PS4)] */
/* 0x1c: ZLSD size */
/* SE banks, also used for music. Most table fields seems reserved/defaults and
@ -66,14 +66,17 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
if (read_u32(sblk_offset+0x00,sf) != get_id32be("klBS")) /* SBlk = SFX block */
goto fail;
sblk_version = read_u32(sblk_offset+0x04,sf);
/* 0x08: flags? (sblk_version>=0x0d?, 0x03=Vita, 0x06=PS4)
/* 0x08: flags? (sblk_version>=0x0d?, 0x03=Vita, 0x06=PS4, 0x05=PS5)
* - 04: non-fixed bank?
* - 100: has names
* - 200: has user data
*/
/* 0x0c: block id */
/* 0x10: block number */
/* 0x11: padding */
* - 200: has user data */
/* version < v0x1a:
* - 0x0c: block id
* - 0x10: block number
* - 0x11: padding
* version >= v0x1a:
* - 0x0c: hash (0x10)
* - 0x1c: filename (0x100?) */
//;VGM_LOG("BNK: sblk_offset=%lx, data_offset=%lx, sblk_version %x\n", sblk_offset, data_offset, sblk_version);
{
@ -141,6 +144,8 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
table2_suboffset = 0x00;
break;
case 0x1a: /* Demon's Souls (PS5) */
default:
vgm_logi("BNK: unknown version %x (report)\n", sblk_version);
goto fail;

View File

@ -1,168 +1,123 @@
#include "meta.h"
#include "../util.h"
#include "../coding/coding.h"
VGMSTREAM * init_vgmstream_brstm(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
VGMSTREAM* init_vgmstream_brstm(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
uint32_t start_offset, head_size, head_offset, info_offset;
int channels, loop_flag, codec, version;
coding_t coding_type;
off_t head_offset;
int codec_number;
int channel_count;
int loop_flag;
/* Certain Super Paper Mario tracks have a 44.1KHz sample rate in the
* header, but they should be played at 22.05KHz. We will make this
* correction if we see a file with a .brstmspm extension. */
int spm_flag = 0;
/* Trauma Center Second Opinion has an odd, semi-corrupt header */
int atlus_shrunken_head = 0;
off_t start_offset;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("brstm",filename_extension(filename))) {
if (strcasecmp("brstmspm",filename_extension(filename))) goto fail;
else spm_flag = 1;
}
/* check header */
if ((uint32_t)read_32bitBE(0,streamFile)!=0x5253544D) /* "RSTM" */
/* checks */
if (!is_id32be(0x00,sf, "RSTM"))
goto fail;
if ((uint32_t)read_32bitBE(4,streamFile)!=0xFEFF0100)
{
if ((uint32_t)read_32bitBE(4,streamFile)!=0xFEFF0001)
goto fail;
else
atlus_shrunken_head = 1;
/* .brstm: standard
* .brstmspm: fake hack */
if (!check_extensions(sf,"brstm,brstmspm"))
goto fail;
if (read_u16be(0x04, sf) != 0xFEFF) /* BE BOM for all Wii games */
goto fail;
version = read_u16be(0x06, sf); /* 0.1 (Trauma Center), 1.0 (all others) */
if (read_u32be(0x08, sf) != get_streamfile_size(sf))
goto fail;
head_size = read_u16be(0x0c, sf);
/* 0x0e: chunk count */
if (version == 0x0001) {
/* smaller simpler header found in some (beta?) files */
head_offset = head_size;
info_offset = head_offset + 0x08;
}
else {
/* chunk table: offset + sixe x N chunks */
head_offset = read_u32be(0x10,sf); /* in practice same as head_size */
info_offset = head_offset + 0x20;
/* HEAD starts with a sub-chunk table (info, )*/
}
/* get head offset, check */
head_offset = read_32bitBE(0x10,streamFile);
if (atlus_shrunken_head)
{
/* the HEAD chunk is where we would expect to find the offset of that
* chunk... */
if (!is_id32be(head_offset,sf, "HEAD"))
goto fail;
/* 0x04: chunk size (set to 0x8 in v0.1) */
if ((uint32_t)head_offset!=0x48454144 || read_32bitBE(0x14,streamFile) != 8)
goto fail;
codec = read_u8(info_offset+0x00,sf);
loop_flag = read_u8(info_offset+0x01,sf);
channels = read_u8(info_offset+0x02,sf);
head_offset = -8; /* most of the normal Nintendo RSTM offsets work
with this assumption */
}
else
{
if ((uint32_t)read_32bitBE(head_offset,streamFile)!=0x48454144) /* "HEAD" */
goto fail;
}
start_offset = read_u32be(info_offset+0x10,sf); /* inside DATA chunk */
/* check type details */
codec_number = read_8bit(head_offset+0x20,streamFile);
loop_flag = read_8bit(head_offset+0x21,streamFile);
channel_count = read_8bit(head_offset+0x22,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
switch (codec_number) {
vgmstream->meta_type = meta_RSTM;
vgmstream->sample_rate = read_u16be(info_offset+0x04,sf);
vgmstream->loop_start_sample = read_s32be(info_offset+0x08,sf);
vgmstream->num_samples = read_s32be(info_offset+0x0c,sf);
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->interleave_block_size = read_u32be(info_offset+0x18,sf);
vgmstream->interleave_last_block_size = read_u32be(info_offset+0x28,sf);
/* many Super Paper Mario tracks have a 44.1KHz sample rate in the header,
* but they should be played at 22.05KHz; detect with fake extension */
if (vgmstream->sample_rate == 44100 && check_extensions(sf, "brstmspm")) //TODO remove
vgmstream->sample_rate = 22050;
vgmstream->layout_type = (channels == 1) ? layout_none : layout_interleave;
switch(codec) {
case 0:
coding_type = coding_PCM8;
vgmstream->coding_type = coding_PCM8;
break;
case 1:
coding_type = coding_PCM16BE;
vgmstream->coding_type = coding_PCM16BE;
break;
case 2:
coding_type = coding_NGC_DSP;
vgmstream->coding_type = coding_NGC_DSP;
break;
default:
goto fail;
}
if (channel_count < 1) goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = read_32bitBE(head_offset+0x2c,streamFile);
vgmstream->sample_rate = (uint16_t)read_16bitBE(head_offset+0x24,streamFile);
/* channels and loop flag are set by allocate_vgmstream */
vgmstream->loop_start_sample = read_32bitBE(head_offset+0x28,streamFile);
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_type;
vgmstream->layout_type = (channel_count == 1) ? layout_none : layout_interleave;
vgmstream->meta_type = meta_RSTM;
if (atlus_shrunken_head)
vgmstream->meta_type = meta_RSTM_shrunken;
if (spm_flag&& vgmstream->sample_rate == 44100) {
vgmstream->meta_type = meta_RSTM_SPM;
vgmstream->sample_rate = 22050;
}
vgmstream->interleave_block_size = read_32bitBE(head_offset+0x38,streamFile);
vgmstream->interleave_last_block_size = read_32bitBE(head_offset+0x48,streamFile);
// TODO read hist
if (vgmstream->coding_type == coding_NGC_DSP) {
off_t coef_offset;
off_t head_part3_offset;
off_t adpcm_header_offset;
int i,j;
int coef_spacing;
int i, ch;
if (atlus_shrunken_head)
{
coef_offset = 0x50;
coef_spacing = 0x30;
for (j = 0; j < vgmstream->channels; j++) {
for (i = 0; i < 16; i++) {
vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(head_offset + coef_offset + j * coef_spacing + i * 2,streamFile);
}
}
if (version == 0x0001) {
/* standard */
VGM_LOG("ss=%x\n", head_offset + 0x38);
dsp_read_coefs_be(vgmstream, sf, head_offset + 0x38, 0x30);
}
else
{
head_part3_offset = read_32bitBE(head_offset + 0x1c, streamFile);
else {
uint32_t head_part3_offset = read_32bitBE(head_offset + 0x1c, sf);
for (j = 0; j < vgmstream->channels; j++) {
/* read from offset table */
for (ch = 0; ch < vgmstream->channels; ch++) {
adpcm_header_offset = head_offset + 0x08
+ head_part3_offset + 0x04 /* skip over HEAD part 3 */
+ j * 0x08 /* skip to channel's ADPCM offset table */
+ ch * 0x08 /* skip to channel's ADPCM offset table */
+ 0x04; /* ADPCM header offset field */
coef_offset = head_offset + 0x08
+ read_32bitBE(adpcm_header_offset, streamFile)
+ read_u32be(adpcm_header_offset, sf)
+ 0x08; /* coeffs field */
for (i = 0; i < 16; i++) {
vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_offset + i * 2, streamFile);
vgmstream->ch[ch].adpcm_coef[i] = read_s16be(coef_offset + i * 2, sf);
}
}
}
}
start_offset = read_32bitBE(head_offset+0x30,streamFile);
/* open the file for reading by each channel */
{
int i;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[i].streamfile) goto fail;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=
start_offset + i*vgmstream->interleave_block_size;
}
}
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,50 @@
#include "meta.h"
#include "../coding/coding.h"
/* CPS - tri-Crescendo games [Eternal Sonata (PS3)] */
VGMSTREAM* init_vgmstream_cps(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag, channels;
/* checks */
if (!is_id32be(0x00,sf, "CPS "))
goto fail;
if (!check_extensions(sf,"cps"))
goto fail;
start_offset = read_32bitBE(0x04,sf);
channels = read_32bitBE(0x08,sf);
loop_flag = read_32bitBE(0x18,sf);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_CPS;
vgmstream->channels = channels;
vgmstream->sample_rate = read_32bitBE(0x10,sf);
if (read_32bitBE(0x20,sf) == 0) {
vgmstream->coding_type = coding_PCM16BE;
vgmstream->layout_type = layout_interleave;
vgmstream->num_samples = pcm16_bytes_to_samples(read_32bitBE(0x0c,sf), channels);
vgmstream->interleave_block_size = 2;
}
else {
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->num_samples = ps_bytes_to_samples(read_32bitBE(0x0c,sf), channels);
vgmstream->interleave_block_size = 0x10;
vgmstream->loop_start_sample = ps_bytes_to_samples(read_32bitBE(0x14,sf), channels);
vgmstream->loop_end_sample = ps_bytes_to_samples(read_32bitBE(0x18,sf), channels);
}
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,56 @@
#include "meta.h"
#include "../coding/coding.h"
/* CXS - tri-Crescendo games [Eternal Sonata (X360)] */
VGMSTREAM* init_vgmstream_cxs(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag, channels;
/* checks */
if (!is_id32be(0x00,sf, "CXS "))
goto fail;
if (!check_extensions(sf,"cxs"))
goto fail;
loop_flag = read_32bitBE(0x18,sf) > 0;
channels = read_32bitBE(0x0c,sf);
start_offset = read_32bitBE(0x04,sf) + read_32bitBE(0x28,sf); /* assumed, seek table always at 0x800 */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
/* 0x04: data start? */
vgmstream->sample_rate = read_32bitBE(0x08,sf);
vgmstream->num_samples = read_32bitBE(0x10,sf);
vgmstream->loop_start_sample = read_32bitBE(0x14,sf);
vgmstream->loop_end_sample = read_32bitBE(0x18,sf);
/* 0x1c: below */
vgmstream->meta_type = meta_CXS;
#ifdef VGM_USE_FFMPEG
{
uint32_t block_count = read_32bitBE(0x1c,sf);
uint32_t block_size = read_32bitBE(0x20,sf);
uint32_t data_size = read_32bitBE(0x24,sf);
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, start_offset, data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, block_count);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, sf, start_offset, data_size, 0, 0,1); /* num samples are ok */
}
#else
goto fail;
#endif
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1847,8 +1847,7 @@ static layered_layout_data* build_layered_eaaudiocore(STREAMFILE *sf_data, eaac_
/* EA-XMA uses completely separate 1/2ch streams, unlike standard XMA that interleaves 1/2ch
* streams with a skip counter to reinterleave (so EA-XMA streams don't have skips set) */
case EAAC_CODEC_EAXMA: {
uint8_t buf[0x100];
int bytes, block_size, block_count;
int block_size;
size_t stream_size;
int is_xma1;
@ -1856,18 +1855,18 @@ static layered_layout_data* build_layered_eaaudiocore(STREAMFILE *sf_data, eaac_
if (!temp_sf) goto fail;
stream_size = get_streamfile_size(temp_sf);
block_size = 0x10000; /* unused */
block_count = stream_size / block_size + ((stream_size % block_size) ? 1 : 0);
block_size = 0x10000;
/* EA adopted XMA2 when it appeared around 2006, but detection isn't so easy
* (SNS with XMA2 do exist). Decoder should work when playing XMA1 as XMA2, but
* the other way around can cause issues, so it's safer to just use XMA2. */
is_xma1 = 0; //eaac->version == EAAC_VERSION_V0; /* approximate */
if (is_xma1)
bytes = ffmpeg_make_riff_xma1(buf, 0x100, data->layers[i]->num_samples, stream_size, data->layers[i]->channels, data->layers[i]->sample_rate, 0);
else
bytes = ffmpeg_make_riff_xma2(buf, 0x100, data->layers[i]->num_samples, stream_size, data->layers[i]->channels, data->layers[i]->sample_rate, block_count, block_size);
data->layers[i]->codec_data = init_ffmpeg_header_offset(temp_sf, buf,bytes, 0x00, stream_size);
if (is_xma1) {
data->layers[i]->codec_data = init_ffmpeg_xma1_raw(temp_sf, 0x00, stream_size, data->layers[i]->channels, data->layers[i]->sample_rate, 0);
}
else {
data->layers[i]->codec_data = init_ffmpeg_xma2_raw(temp_sf, 0x00, stream_size, data->layers[i]->num_samples, data->layers[i]->channels, data->layers[i]->sample_rate, block_size, 0);
}
if (!data->layers[i]->codec_data) goto fail;
data->layers[i]->coding_type = coding_FFmpeg;

View File

@ -1,25 +1,22 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
/* SWVR - from EA games, demuxed from .av/trk/mis/etc [Future Cop L.A.P.D. (PS/PC), Freekstyle (PS2/GC), EA Sports Supercross (PS)] */
VGMSTREAM* init_vgmstream_ea_swvr(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag = 0, channels, sample_rate, big_endian;
int loop_flag = 0, channels, sample_rate, big_endian, loop_block = 0;
coding_t coding;
uint32_t block_id;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
read_u32_t read_u32 = NULL;
read_u16_t read_u16 = NULL;
int total_subsongs, target_subsong = sf->stream_index;
/* checks */
/* .stream: common (found inside files)
* .str: shortened, probably unnecessary */
if (!check_extensions(sf,"stream,str"))
goto fail;
/* Files have no actual audio headers, so we inspect the first block for known values.
* Freekstyle uses multiblocks/subsongs (though some subsongs may be clones?) */
@ -27,40 +24,48 @@ VGMSTREAM* init_vgmstream_ea_swvr(STREAMFILE* sf) {
/* blocks ids are in machine endianness */
if (read_u32be(0x00,sf) == get_id32be("RVWS")) { /* PS1/PS2/PC */
big_endian = 0;
read_32bit = read_32bitLE;
read_16bit = read_16bitLE;
start_offset = read_32bit(0x04, sf);
read_u32 = read_u32le;
read_u16 = read_u16le;
start_offset = read_u32(0x04, sf);
/* 0x08: null */
loop_block = read_u32(0x0c, sf); /* uncommon [NASCAR Racing (PS1), Rumble Racing (PS2)] */
}
else if (read_u32be(0x00,sf) == get_id32be("SWVR")) { /* GC */
big_endian = 1;
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
start_offset = read_32bit(0x04, sf);
read_u32 = read_u32be;
read_u16 = read_u16be;
start_offset = read_u32(0x04, sf);
}
else if (read_u32be(0x00,sf) == get_id32be("MGAV")) { /* Freekstyle (PS2) raw movies */
big_endian = 0;
read_32bit = read_32bitLE;
read_16bit = read_16bitLE;
read_u32 = read_u32le;
read_u16 = read_u16le;
start_offset = 0x00;
}
else if (read_u32be(0x00,sf) == get_id32be("DSPM")) { /* Freekstyle (GC) raw movies */
big_endian = 1;
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
read_u32 = read_u32be;
read_u16 = read_u16be;
start_offset = 0x00;
}
else {
goto fail;
}
if (read_32bit(start_offset+0x00, sf) == get_id32be("PADD")) /* Freekstyle */
start_offset += read_32bit(start_offset+0x04, sf);
/* .stream: common (found inside files)
* .str: shortened, probably unnecessary */
if (!check_extensions(sf,"stream,str"))
goto fail;
if (read_32bit(start_offset+0x00, sf) == get_id32be("FILL")) /* Freekstyle */
start_offset += read_32bit(start_offset+0x04, sf);
if (read_u32(start_offset+0x00, sf) == get_id32be("PADD")) /* Freekstyle */
start_offset += read_u32(start_offset+0x04, sf);
if (read_u32(start_offset+0x00, sf) == get_id32be("FILL")) /* Freekstyle */
start_offset += read_u32(start_offset+0x04, sf);
total_subsongs = 1;
block_id = read_32bit(start_offset, sf);
block_id = read_u32(start_offset, sf);
/* value after block id (usually at 0x38) is number of blocks of 0x6000 (results in file size, including FILLs) */
/* intended sample rate for PSX music (verified in emus) should be 14260, but is found in ELF as pitch value
@ -69,8 +74,8 @@ VGMSTREAM* init_vgmstream_ea_swvr(STREAMFILE* sf) {
switch(block_id) {
case 0x5641474D: /* "VAGM" (stereo music) */
coding = coding_PSX;
if (read_16bit(start_offset+0x1a, sf) == 0x0024) {
total_subsongs = read_32bit(start_offset+0x0c, sf)+1;
if (read_u16(start_offset+0x1a, sf) == 0x0024) {
total_subsongs = read_u32(start_offset+0x0c, sf)+1;
sample_rate = 22050; /* Freekstyle (PS2) */
}
else {
@ -80,7 +85,7 @@ VGMSTREAM* init_vgmstream_ea_swvr(STREAMFILE* sf) {
break;
case 0x56414742: /* "VAGB" (mono sfx/voices)*/
coding = coding_PSX;
if (read_16bit(start_offset+0x1a, sf) == 0x6400) {
if (read_u16(start_offset+0x1a, sf) == 0x6400) {
sample_rate = 22050; /* Freekstyle (PS2) */
}
else {
@ -91,7 +96,7 @@ VGMSTREAM* init_vgmstream_ea_swvr(STREAMFILE* sf) {
break;
case 0x4453504D: /* "DSPM" (stereo music) */
coding = coding_NGC_DSP;
total_subsongs = read_32bit(start_offset+0x0c, sf)+1;
total_subsongs = read_u32(start_offset+0x0c, sf)+1;
sample_rate = 22050; /* Freekstyle (GC) */
channels = 2;
break;
@ -106,7 +111,7 @@ VGMSTREAM* init_vgmstream_ea_swvr(STREAMFILE* sf) {
sample_rate = 14291; /* assumed, by comparing vs PSX output [Future Cop (PC)] */
break;
case 0x53484F43: /* "SHOC" (a generic block but hopefully has PC sounds) */
if (read_32bit(start_offset+0x10, sf) == get_id32be("SHDR")) { /* Future Cop (PC) */
if (read_u32(start_offset+0x10, sf) == get_id32be("SHDR")) { /* Future Cop (PC) */
/* there is a mini header? after SHDR
* 0x00: 5
* 0x04: "snds"
@ -118,7 +123,7 @@ VGMSTREAM* init_vgmstream_ea_swvr(STREAMFILE* sf) {
* 0x1c: 1
* 0x20: 1
* 0x24: 0x4F430000 */
if (read_32bit(start_offset+0x18, sf) != get_id32be("snds"))
if (read_u32(start_offset+0x18, sf) != get_id32be("snds"))
goto fail;
coding = coding_PCM8_U_int;
channels = 1;
@ -139,7 +144,7 @@ VGMSTREAM* init_vgmstream_ea_swvr(STREAMFILE* sf) {
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
loop_flag = 0;//(channels > 1); /* some Future Cop LAPD tracks repeat but other games have fadeouts */
loop_flag = (loop_block > 0);//(channels > 1); /* some Future Cop LAPD tracks repeat but other games have fadeouts */
/* build the VGMSTREAM */
@ -162,9 +167,11 @@ VGMSTREAM* init_vgmstream_ea_swvr(STREAMFILE* sf) {
/* calc num_samples manually */
{
int num_samples;
int block, num_samples;
vgmstream->stream_index = target_subsong; /* needed to skip other subsong-blocks */
vgmstream->next_block_offset = start_offset;
block = 0;
do {
block_update(vgmstream->next_block_offset,vgmstream);
switch(vgmstream->coding_type) {
@ -174,15 +181,19 @@ VGMSTREAM* init_vgmstream_ea_swvr(STREAMFILE* sf) {
default: num_samples = 0; break;
}
vgmstream->num_samples += num_samples;
/* check loop on data blocks */
if (num_samples) {
block++;
if (loop_block == block) /* 1=first */
vgmstream->loop_start_sample = vgmstream->num_samples;
}
}
while (vgmstream->next_block_offset < get_streamfile_size(sf));
block_update(start_offset, vgmstream);
}
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
}
vgmstream->loop_end_sample = vgmstream->num_samples;
return vgmstream;

View File

@ -16,8 +16,8 @@ static void decrypt_chunk(uint8_t* buf, int buf_size, mc161_io_data* data) {
for (i = 0; i < buf_size; i++) {
buf[i] = (uint8_t)(buf[i] ^ ((hash >> 8) & 0xFF));
hash = (int32_t)(hash * 498729871) + (85731 * (int8_t)buf[i]); /* signed */
buf[i] = (uint8_t)(buf[i] ^ ((hash >> 8) & 0xFF));
hash = (int32_t)(hash * 498729871) + (85731 * (int8_t)buf[i]); /* signed */
}
data->curr_key = hash;

View File

@ -118,7 +118,7 @@ VGMSTREAM* init_vgmstream_fsb(STREAMFILE* sf) {
/* .fsb: standard
* .bnk: Hard Corps Uprising (PS3)
* .sfx: Geon Cube (Wii)
* .sfx: Geon Cube (Wii)
* .xen: Guitar Hero: World Tour (PC) */
if ( !check_extensions(sf, "fsb,bnk,sfx,xen") )
goto fail;
@ -388,19 +388,15 @@ VGMSTREAM* init_vgmstream_fsb(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case XMA: { /* FSB3: The Bourne Conspiracy 2008 (X360), FSB4: Armored Core V (X360), Hard Corps (X360) */
uint8_t buf[0x100];
size_t bytes, block_size, block_count;
int block_size = 0x8000; /* FSB default */
if (fsb.version != FMOD_FSB_VERSION_4_0) { /* 3.x, though no actual output changes [ex. Guitar Hero III (X360)] */
bytes = ffmpeg_make_riff_xma1(buf, sizeof(buf), fsb.num_samples, fsb.stream_size, fsb.channels, fsb.sample_rate, 0);
if (fsb.version != FMOD_FSB_VERSION_4_0) {
/* 3.x, though no actual output changes [ex. Guitar Hero III (X360), The Bourne Conspiracy (X360)] */
vgmstream->codec_data = init_ffmpeg_xma1_raw(sf, fsb.stream_offset, fsb.stream_size, fsb.channels, fsb.sample_rate, 0);
}
else {
block_size = 0x8000; /* FSB default */
block_count = fsb.stream_size / block_size; /* not accurate but not needed (custom_data_offset+0x14 -1?) */
bytes = ffmpeg_make_riff_xma2(buf, sizeof(buf), fsb.num_samples, fsb.stream_size, fsb.channels, fsb.sample_rate, block_count, block_size);
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, fsb.stream_offset, fsb.stream_size, fsb.num_samples, fsb.channels, fsb.sample_rate, block_size, 0);
}
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, fsb.stream_offset,fsb.stream_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -367,14 +367,9 @@ VGMSTREAM* init_vgmstream_fsb5(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 0x0A: {/* FMOD_SOUND_FORMAT_XMA [Minecraft Story Mode (X360)] */
uint8_t buf[0x100];
int bytes, block_size, block_count;
int block_size = 0x8000; /* FSB default */
block_size = 0x8000; /* FSB default */
block_count = fsb5.stream_size / block_size + (fsb5.stream_size % block_size ? 1 : 0);
bytes = ffmpeg_make_riff_xma2(buf, 0x100, vgmstream->num_samples, fsb5.stream_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
vgmstream->codec_data = init_ffmpeg_header_offset(sb, buf,bytes, fsb5.stream_offset, fsb5.stream_size);
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, fsb5.stream_offset, fsb5.stream_size, fsb5.num_samples, fsb5.channels, fsb5.sample_rate, block_size, 0);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -3,6 +3,8 @@
#include "fsb_encrypted_streamfile.h"
static VGMSTREAM* test_fsbkey(STREAMFILE* sf, const uint8_t* key, size_t key_size, uint8_t flags);
/* fully encrypted FSBs */
VGMSTREAM* init_vgmstream_fsb_encrypted(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
@ -18,58 +20,21 @@ VGMSTREAM* init_vgmstream_fsb_encrypted(STREAMFILE* sf) {
if (!check_extensions(sf, "fsb,ps3,xen"))
goto fail;
/* try fsbkey + all combinations of FSB4/5 and decryption algorithms */
{
STREAMFILE* temp_sf = NULL;
uint8_t key[FSB_KEY_MAX];
size_t key_size = read_key_file(key, FSB_KEY_MAX, sf);
if (key_size) {
{
temp_sf = setup_fsb_streamfile(sf, key,key_size, 0);
if (!temp_sf) goto fail;
if (!vgmstream) vgmstream = init_vgmstream_fsb(temp_sf);
if (!vgmstream) vgmstream = init_vgmstream_fsb5(temp_sf);
close_streamfile(temp_sf);
}
if (!vgmstream) {
temp_sf = setup_fsb_streamfile(sf, key,key_size, 1);
if (!temp_sf) goto fail;
if (!vgmstream) vgmstream = init_vgmstream_fsb(temp_sf);
if (!vgmstream) vgmstream = init_vgmstream_fsb5(temp_sf);
close_streamfile(temp_sf);
}
}
test_fsbkey(sf, key, key_size, MODE_FSBS_ALL);
}
/* try all keys until one works */
if (!vgmstream) {
int i;
STREAMFILE* temp_sf = NULL;
for (i = 0; i < fsbkey_list_count; i++) {
for (int i = 0; i < fsbkey_list_count; i++) {
fsbkey_info entry = fsbkey_list[i];
//;VGM_LOG("fsbkey: size=%i, is_fsb5=%i, is_alt=%i\n", entry.fsbkey_size,entry.is_fsb5, entry.is_alt);
temp_sf = setup_fsb_streamfile(sf, entry.fsbkey, entry.fsbkey_size, entry.is_alt);
if (!temp_sf) goto fail;
if (fsbkey_list[i].is_fsb5) {
vgmstream = init_vgmstream_fsb5(temp_sf);
} else {
vgmstream = init_vgmstream_fsb(temp_sf);
}
//;if (vgmstream) dump_streamfile(temp_sf, 0);
close_streamfile(temp_sf);
vgmstream = test_fsbkey(sf, (const uint8_t*)entry.key, entry.key_size, entry.flags);
if (vgmstream) break;
}
}
@ -83,3 +48,41 @@ fail:
close_vgmstream(vgmstream);
return NULL;
}
static VGMSTREAM* test_fsbkey(STREAMFILE* sf, const uint8_t* key, size_t key_size, uint8_t flags) {
STREAMFILE* temp_sf = NULL;
VGMSTREAM* vc = NULL;
if (!key_size)
return NULL;
int test_fsb4 = flags & FLAG_FSB4;
int test_fsb5 = flags & FLAG_FSB5;
int test_std = flags & FLAG_STD;
int test_alt = flags & FLAG_ALT;
if (!vc && test_std) {
temp_sf = setup_fsb_streamfile(sf, key, key_size, 0);
if (!temp_sf) return NULL;
if (!vc && test_fsb4) vc = init_vgmstream_fsb(temp_sf);
if (!vc && test_fsb5) vc = init_vgmstream_fsb5(temp_sf);
//;if (vgmstream) dump_streamfile(temp_sf, 0);
close_streamfile(temp_sf);
}
if (!vc && test_alt) {
temp_sf = setup_fsb_streamfile(sf, key, key_size, 1);
if (!temp_sf) return NULL;
if (!vc && test_fsb4) vc = init_vgmstream_fsb(temp_sf);
if (!vc && test_fsb5) vc = init_vgmstream_fsb5(temp_sf);
//;if (vgmstream) dump_streamfile(temp_sf, 0);
close_streamfile(temp_sf);
}
return vc;
}

View File

@ -1,100 +1,11 @@
#ifndef _FSB_KEYS_H_
#define _FSB_KEYS_H_
#include <stdint.h>
/**
/*
* List of known keys, found in aluigi's site (http://aluigi.altervista.org), forums, guessfsb.exe or manually.
*/
/* DJ Hero 2 (X360) */ //"nos71RiT"
static const uint8_t key_dj2[] = { 0x6E,0x6F,0x73,0x37,0x31,0x52,0x69,0x54 };
/* Double Fine Productions: Brutal Legend, Massive Chalice, etc (multi) */ //"DFm3t4lFTW"
static const uint8_t key_dfp[] = { 0x44,0x46,0x6D,0x33,0x74,0x34,0x6C,0x46,0x54,0x57 };
/* N++ (PC?) */ //"H$#FJa%7gRZZOlxLiN50&g5Q"
static const uint8_t key_npp[] = { 0x48,0x24,0x23,0x46,0x4A,0x61,0x25,0x37,0x67,0x52,0x5A,0x5A,0x4F,0x6C,0x78,0x4C,0x69,0x4E,0x35,0x30,0x26,0x67,0x35,0x51 };
/* Slightly Mad Studios: Project CARS (PC?), World of Speed (PC) */ //"sTOoeJXI2LjK8jBMOk8h5IDRNZl3jq3I"
static const uint8_t key_sms[] = { 0x73,0x54,0x4F,0x6F,0x65,0x4A,0x58,0x49,0x32,0x4C,0x6A,0x4B,0x38,0x6A,0x42,0x4D,0x4F,0x6B,0x38,0x68,0x35,0x49,0x44,0x52,0x4E,0x5A,0x6C,0x33,0x6A,0x71,0x33,0x49 };
/* Ghost in the Shell: First Assault (PC) */ //"%lAn2{Pi*Lhw3T}@7*!kV=?qS$@iNlJ"
static const uint8_t key_gfs[] = { 0x25,0x6C,0x41,0x6E,0x32,0x7B,0x50,0x69,0x2A,0x4C,0x68,0x77,0x33,0x54,0x7D,0x40,0x37,0x2A,0x21,0x6B,0x56,0x3D,0x3F,0x71,0x53,0x24,0x40,0x69,0x4E,0x6C,0x4A };
/* RevHeadz Engine Sounds (Mobile) */ //"1^7%82#&5$~/8sz"
static const uint8_t key_rev[] = { 0x31,0x5E,0x37,0x25,0x38,0x32,0x23,0x26,0x35,0x24,0x7E,0x2F,0x38,0x73,0x7A };
/* Dark Souls 3 (PC) */ //"FDPrVuT4fAFvdHJYAgyMzRF4EcBAnKg"
static const uint8_t key_ds3[] = { 0x46,0x44,0x50,0x72,0x56,0x75,0x54,0x34,0x66,0x41,0x46,0x76,0x64,0x48,0x4A,0x59,0x41,0x67,0x79,0x4D,0x7A,0x52,0x46,0x34,0x45,0x63,0x42,0x41,0x6E,0x4B,0x67 };
/* Mortal Kombat X/XL (PC) */ //"996164B5FC0F402983F61F220BB51DC6"
static const uint8_t key_mkx[] = { 0x39,0x39,0x36,0x31,0x36,0x34,0x42,0x35,0x46,0x43,0x30,0x46,0x34,0x30,0x32,0x39,0x38,0x33,0x46,0x36,0x31,0x46,0x32,0x32,0x30,0x42,0x42,0x35,0x31,0x44,0x43,0x36 };
/* Xian Xia Chuan (PC) */ //"gat@tcqs2010"
static const uint8_t key_xxc[] = { 0x67,0x61,0x74,0x40,0x74,0x63,0x71,0x73,0x32,0x30,0x31,0x30 };
/* Mirror War: Reincarnation of Holiness (PC) */ //"logicsounddesignmwsdev"
static const uint8_t key_mwr[] = { 0x6C,0x6F,0x67,0x69,0x63,0x73,0x6F,0x75,0x6E,0x64,0x64,0x65,0x73,0x69,0x67,0x6E,0x6D,0x77,0x73,0x64,0x65,0x76 };
/* Need for Speed Shift 2 Unleashed (PC demo?) */ //"p&oACY^c4LK5C2v^x5nIO6kg5vNH$tlj"
static const uint8_t key_n2u[] = { 0x70,0x26,0x6F,0x41,0x43,0x59,0x5E,0x63,0x34,0x4C,0x4B,0x35,0x43,0x32,0x76,0x5E,0x78,0x35,0x6E,0x49,0x4F,0x36,0x6B,0x67,0x35,0x76,0x4E,0x48,0x24,0x74,0x6C,0x6A };
/* Critter Crunch (PC), Superbrothers: Sword & Sworcery (PC) */ //"j1$Mk0Libg3#apEr42mo"
static const uint8_t key_ccr[] = { 0x6A,0x31,0x24,0x4D,0x6B,0x30,0x4C,0x69,0x62,0x67,0x33,0x23,0x61,0x70,0x45,0x72,0x34,0x32,0x6D,0x6F };
/* Cyphers */ //"@kdj43nKDN^k*kj3ndf02hd95nsl(NJG"
static const uint8_t key_cyp[] = { 0x40,0x6B,0x64,0x6A,0x34,0x33,0x6E,0x4B,0x44,0x4E,0x5E,0x6B,0x2A,0x6B,0x6A,0x33,0x6E,0x64,0x66,0x30,0x32,0x68,0x64,0x39,0x35,0x6E,0x73,0x6C,0x28,0x4E,0x4A,0x47 };
/* Xuan Dou Zhi Wang / King of Combat */ //"Xiayuwu69252.Sonicli81223#$*@*0"
static const uint8_t key_xdz[] = { 0x58,0x69,0x61,0x79,0x75,0x77,0x75,0x36,0x39,0x32,0x35,0x32,0x2E,0x53,0x6F,0x6E,0x69,0x63,0x6C,0x69,0x38,0x31,0x32,0x32,0x33,0x23,0x24,0x2A,0x40,0x2A,0x30 };
/* Ji Feng Zhi Ren / Kritika Online */ //"kri_tika_5050_"
static const uint8_t key_jzz[] = { 0x6B,0x72,0x69,0x5F,0x74,0x69,0x6B,0x61,0x5F,0x35,0x30,0x35,0x30,0x5F };
/* Invisible Inc. (PC?) */ //"mint78run52"
static const uint8_t key_inv[] = { 0x6D,0x69,0x6E,0x74,0x37,0x38,0x72,0x75,0x6E,0x35,0x32 };
/* Guitar Hero 3 */ //"5atu6w4zaw"
static const uint8_t key_gh3[] = { 0x35,0x61,0x74,0x75,0x36,0x77,0x34,0x7A,0x61,0x77 };
/* Supreme Commander 2 */ //"B2A7BB00"
static const uint8_t key_sc2[] = { 0x42,0x32,0x41,0x37,0x42,0x42,0x30,0x30 };
/* Cookie Run: Ovenbreak */ //"ghfxhslrghfxhslr"
static const uint8_t key_cro[] = { 0x67,0x68,0x66,0x78,0x68,0x73,0x6C,0x72,0x67,0x68,0x66,0x78,0x68,0x73,0x6C,0x72 };
/* Monster Jam (PS2) */ //"truck/impact/carbody"
static const uint8_t key_mtj[] = { 0x74,0x72,0x75,0x63,0x6B,0x2F,0x69,0x6D,0x70,0x61,0x63,0x74,0x2F,0x63,0x61,0x72,0x62,0x6F,0x64,0x79 };
/* Guitar Hero 5 (X360) */
static const uint8_t key_gh5[] = { 0xFC,0xF9,0xE4,0xB3,0xF5,0x57,0x5C,0xA5,0xAC,0x13,0xEC,0x4A,0x43,0x19,0x58,0xEB,0x4E,0xF3,0x84,0x0B,0x8B,0x78,0xFA,0xFD,0xBB,0x18,0x46,0x7E,0x31,0xFB,0xD0 };
/* Sekiro: Shadows Die Twice (PC) */ //"G0KTrWjS9syqF7vVD6RaVXlFD91gMgkC"
static const uint8_t key_sek[] = { 0x47,0x30,0x4B,0x54,0x72,0x57,0x6A,0x53,0x39,0x73,0x79,0x71,0x46,0x37,0x76,0x56,0x44,0x36,0x52,0x61,0x56,0x58,0x6C,0x46,0x44,0x39,0x31,0x67,0x4D,0x67,0x6B,0x43 };
/* SCP: Unity (PC) */ //"BasicEncryptionKey"
static const uint8_t key_scp[] = { 0x42,0x61,0x73,0x69,0x63,0x45,0x6E,0x63,0x72,0x79,0x70,0x74,0x69,0x6F,0x6E,0x4B,0x65,0x79 };
/* Guitar Hero: Metallica (X360) */
static const uint8_t key_ghm[] = { 0x8C,0xFA,0xF3,0x14,0xB1,0x53,0xDA,0xAB,0x2B,0x82,0x6B,0xD5,0x55,0x16,0xCF,0x01,0x90,0x20,0x28,0x14,0xB1,0x53,0xD8 };
/* Worms Rumble Beta (PC) */ //"FXnTffGJ9LS855Gc"
static const uint8_t key_wrb[] = { 0x46,0x58,0x6E,0x54,0x66,0x66,0x47,0x4A,0x39,0x4C,0x53,0x38,0x35,0x35,0x47,0x63 };
/* Bubble Fighter (PC) */ //"qjvkeoqkrdhkdckd"
static const uint8_t key_bbf[] = { 0x71,0x6A,0x76,0x6B,0x65,0x6F,0x71,0x6B,0x72,0x64,0x68,0x6B,0x64,0x63,0x6B,0x64 };
/* Fall Guys (PC) update ~2021-11 */ //"p@4_ih*srN:UJk&8"
static const uint8_t key_fg1[] = { 0x70,0x40,0x34,0x5F,0x69,0x68,0x2A,0x73,0x72,0x4E,0x3A,0x55,0x4A,0x6B,0x26,0x38 };
/* Fall Guys (PC) update ~2022-07 */ //",&.XZ8]fLu%caPF+"
static const uint8_t key_fg2[] = { 0x2c,0x26,0x2e,0x58,0x5a,0x38,0x5d,0x66,0x4c,0x75,0x25,0x63,0x61,0x50,0x46,0x2b };
/* Achilles: Legends Untold (PC) */ //"Achilles_0_15_DpG"
static const uint8_t key_alu[] = { 0x41,0x63,0x68,0x69,0x6C,0x6C,0x65,0x73,0x5F,0x30,0x5F,0x31,0x35,0x5F,0x44,0x70,0x47 };
/* Cult of the Lamb Demo (PC) */ //"4FB8CC894515617939F4E1B7D50972D27213B8E6"
static const uint8_t key_col[] = { 0x34,0x46,0x42,0x38,0x43,0x43,0x38,0x39,0x34,0x35,0x31,0x35,0x36,0x31,0x37,0x39,0x33,0x39,0x46,0x34,0x45,0x31,0x42,0x37,0x44,0x35,0x30,0x39,0x37,0x32,0x44,0x32,0x37,0x32,0x31,0x33,0x42,0x38,0x45,0x36 };
// Unknown:
// - Battle: Los Angeles
// - Guitar Hero: Warriors of Rock, DJ hero FSB
@ -102,70 +13,62 @@ static const uint8_t key_col[] = { 0x34,0x46,0x42,0x38,0x43,0x43,0x38,0x39,0x34,
// - Gas Guzzlers: Combat Carnage (PC?) "C5FA83EA64B34EC2BFE" hex or text? [FSB5]
typedef struct {
int is_fsb5; /* FSB5 or FSB4/3*/
int is_alt; /* alt XOR mode (seemingly not tied to FSB version or anything) */
size_t fsbkey_size;
const uint8_t* fsbkey;
uint8_t flags;
const char* key;
size_t key_size; /* precalc'd for speed */
} fsbkey_info;
#define FLAG_FSB4 (1 << 0) /* key is valid for FSB4/3 */
#define FLAG_FSB5 (1 << 1) /* key is valid for FSB5 */
#define FLAG_STD (1 << 2) /* regular XOR mode */
#define FLAG_ALT (1 << 3) /* alt XOR mode (seemingly not tied to FSB version or anything, maybe wrong key) */
#define MODE_FSB4_STD (FLAG_FSB4 | FLAG_STD)
#define MODE_FSB4_ALT (FLAG_FSB4 | FLAG_ALT)
#define MODE_FSB4_ALL (FLAG_FSB4 | FLAG_ALT)
#define MODE_FSB5_STD (FLAG_FSB5 | FLAG_STD)
#define MODE_FSB5_ALT (FLAG_FSB5 | FLAG_STD)
#define MODE_FSB5_ALL (FLAG_FSB5 | FLAG_STD | FLAG_ALT)
#define MODE_FSBS_STD (FLAG_FSB4 | FLAG_FSB5 | FLAG_STD)
#define MODE_FSBS_ALL (FLAG_FSB4 | FLAG_FSB5 | FLAG_STD | FLAG_ALT)
/* ugly macro for string + precomputed len (removing string's extra NULL)*/
#define FSBKEY_ADD(key) key, sizeof(key) - 1
static const fsbkey_info fsbkey_list[] = {
{ 0,0, sizeof(key_dj2),key_dj2 },
{ 0,0, sizeof(key_dfp),key_dfp },//FSB4
{ 1,0, sizeof(key_dfp),key_dfp },//FSB5
{ 1,0, sizeof(key_npp),key_npp },//FSB5
{ 1,0, sizeof(key_sms),key_sms },//FSB5
{ 1,0, sizeof(key_gfs),key_gfs },//FSB5
{ 1,0, sizeof(key_rev),key_rev },//FSB5
{ 1,0, sizeof(key_ds3),key_ds3 },//untested
{ 1,1, sizeof(key_ds3),key_ds3 },
{ 1,0, sizeof(key_mkx),key_mkx },//FSB5
{ 0,0, sizeof(key_xxc),key_xxc },//untested
{ 0,1, sizeof(key_xxc),key_xxc },//untested
{ 1,0, sizeof(key_xxc),key_xxc },//untested
{ 1,1, sizeof(key_xxc),key_xxc },//untested
{ 1,0, sizeof(key_mwr),key_mwr },//FSB5
{ 0,0, sizeof(key_n2u),key_n2u },//untested
{ 0,1, sizeof(key_n2u),key_n2u },//untested
{ 0,0, sizeof(key_ccr),key_ccr },//untested
{ 0,1, sizeof(key_ccr),key_ccr },//untested
{ 1,0, sizeof(key_ccr),key_ccr },//untested
{ 1,1, sizeof(key_ccr),key_ccr },//untested
{ 0,0, sizeof(key_cyp),key_cyp },//untested
{ 0,1, sizeof(key_cyp),key_cyp },//untested
{ 1,0, sizeof(key_cyp),key_cyp },//untested
{ 1,1, sizeof(key_cyp),key_cyp },//untested
{ 0,0, sizeof(key_xdz),key_xdz },//untested
{ 0,1, sizeof(key_xdz),key_xdz },//untested
{ 1,0, sizeof(key_xdz),key_xdz },//untested
{ 1,1, sizeof(key_xdz),key_xdz },//untested
{ 0,0, sizeof(key_jzz),key_jzz },//untested
{ 0,1, sizeof(key_jzz),key_jzz },//untested
{ 1,0, sizeof(key_jzz),key_jzz },//untested
{ 1,1, sizeof(key_jzz),key_jzz },//untested
{ 0,0, sizeof(key_inv),key_inv },//untested
{ 0,1, sizeof(key_inv),key_inv },//untested
{ 1,0, sizeof(key_inv),key_inv },//untested
{ 1,1, sizeof(key_inv),key_inv },//untested
{ 0,0, sizeof(key_gh3),key_gh3 },//untested
{ 0,1, sizeof(key_gh3),key_gh3 },//untested
{ 1,0, sizeof(key_gh3),key_gh3 },//untested
{ 1,1, sizeof(key_gh3),key_gh3 },//untested
{ 0,0, sizeof(key_sc2),key_sc2 },//untested
{ 0,1, sizeof(key_sc2),key_sc2 },//untested
{ 1,0, sizeof(key_sc2),key_sc2 },//untested
{ 1,1, sizeof(key_sc2),key_sc2 },//untested
{ 1,0, sizeof(key_cro),key_cro },
{ 0,1, sizeof(key_mtj),key_mtj },// FSB3
{ 0,1, sizeof(key_gh5),key_gh5 },// FSB4
{ 1,0, sizeof(key_sek),key_sek },// FSB5
{ 1,0, sizeof(key_scp),key_scp },// FSB5
{ 0,1, sizeof(key_ghm),key_ghm },// FSB4
{ 1,0, sizeof(key_wrb),key_wrb },// FSB5
{ 0,0, sizeof(key_bbf),key_bbf },// FSB4
{ 1,0, sizeof(key_fg1),key_fg1 },// FSB5
{ 1,0, sizeof(key_fg2),key_fg2 },// FSB5
{ 1,0, sizeof(key_alu),key_alu },// FSB5
{ 1,0, sizeof(key_col),key_col },// FSB5
{ MODE_FSBS_STD, FSBKEY_ADD("DFm3t4lFTW") }, // Double Fine Productions: Brutal Legend, Massive Chalice, etc (multi)
{ MODE_FSB4_STD, FSBKEY_ADD("nos71RiT") }, // DJ Hero 2 (X360)
{ MODE_FSB5_STD, FSBKEY_ADD("H$#FJa%7gRZZOlxLiN50&g5Q") }, // N++ (PC?)
{ MODE_FSB5_STD, FSBKEY_ADD("sTOoeJXI2LjK8jBMOk8h5IDRNZl3jq3I") }, // Slightly Mad Studios: Project CARS (PC?), World of Speed (PC)
{ MODE_FSB5_STD, FSBKEY_ADD("%lAn2{Pi*Lhw3T}@7*!kV=?qS$@iNlJ") }, // Ghost in the Shell: First Assault (PC)
{ MODE_FSB5_STD, FSBKEY_ADD("1^7%82#&5$~/8sz") }, // RevHeadz Engine Sounds (Mobile)
{ MODE_FSB5_ALL, FSBKEY_ADD("FDPrVuT4fAFvdHJYAgyMzRF4EcBAnKg") }, // Dark Souls 3 (PC) [untested]
{ MODE_FSB4_ALL, FSBKEY_ADD("p&oACY^c4LK5C2v^x5nIO6kg5vNH$tlj") }, // Need for Speed Shift 2 Unleashed (PC demo?)[untested]
{ MODE_FSB5_STD, FSBKEY_ADD("996164B5FC0F402983F61F220BB51DC6") }, // Mortal Kombat X/XL (PC)
{ MODE_FSB5_STD, FSBKEY_ADD("logicsounddesignmwsdev") }, // Mirror War: Reincarnation of Holiness (PC)
{ MODE_FSBS_ALL, FSBKEY_ADD("gat@tcqs2010") }, // Xian Xia Chuan (PC) [untested]
{ MODE_FSBS_ALL, FSBKEY_ADD("j1$Mk0Libg3#apEr42mo") }, // Critter Crunch (PC), Superbrothers: Sword & Sworcery (PC) [untested]
{ MODE_FSBS_ALL, FSBKEY_ADD("@kdj43nKDN^k*kj3ndf02hd95nsl(NJG") }, // Cyphers [untested]
{ MODE_FSBS_ALL, FSBKEY_ADD("Xiayuwu69252.Sonicli81223#$*@*0") }, // Xuan Dou Zhi Wang / King of Combat [untested]
{ MODE_FSBS_ALL, FSBKEY_ADD("kri_tika_5050_") }, // Ji Feng Zhi Ren / Kritika Online [untested]
{ MODE_FSBS_ALL, FSBKEY_ADD("mint78run52") }, // Invisible Inc. (PC?) [untested]
{ MODE_FSBS_ALL, FSBKEY_ADD("5atu6w4zaw") }, // Guitar Hero 3 [untested]
{ MODE_FSBS_ALL, FSBKEY_ADD("B2A7BB00") }, // Supreme Commander 2 [untested]
{ MODE_FSB4_STD, FSBKEY_ADD("ghfxhslrghfxhslr") }, // Cookie Run: Ovenbreak
{ MODE_FSB4_ALT, FSBKEY_ADD("truck/impact/carbody") },// Monster Jam (PS2) [FSB3]
{ MODE_FSB4_ALT, FSBKEY_ADD("\xFC\xF9\xE4\xB3\xF5\x57\x5C\xA5\xAC\x13\xEC\x4A\x43\x19\x58\xEB\x4E\xF3\x84\x0B\x8B\x78\xFA\xFD\xBB\x18\x46\x7E\x31\xFB\xD0") },
{ MODE_FSB4_ALT, FSBKEY_ADD("\x8C\xFA\xF3\x14\xB1\x53\xDA\xAB\x2B\x82\x6B\xD5\x55\x16\xCF\x01\x90\x20\x28\x14\xB1\x53\xD8") },
{ MODE_FSB5_STD, FSBKEY_ADD("G0KTrWjS9syqF7vVD6RaVXlFD91gMgkC") }, // Sekiro: Shadows Die Twice (PC)
{ MODE_FSB5_STD, FSBKEY_ADD("BasicEncryptionKey") }, // SCP: Unity (PC)
{ MODE_FSB5_STD, FSBKEY_ADD("FXnTffGJ9LS855Gc") }, // Worms Rumble Beta (PC)
{ MODE_FSB4_STD, FSBKEY_ADD("qjvkeoqkrdhkdckd") }, // Bubble Fighter (PC)
{ MODE_FSB5_STD, FSBKEY_ADD("p@4_ih*srN:UJk&8") }, // Fall Guys (PC) update ~2021-11
{ MODE_FSB5_STD, FSBKEY_ADD(",&.XZ8]fLu%caPF+") }, // Fall Guys (PC) update ~2022-07
{ MODE_FSB5_STD, FSBKEY_ADD("Achilles_0_15_DpG") }, // Achilles: Legends Untold (PC)
{ MODE_FSB5_STD, FSBKEY_ADD("4FB8CC894515617939F4E1B7D50972D27213B8E6") }, // Cult of the Lamb Demo (PC)
{ MODE_FSB5_STD, FSBKEY_ADD("X3EK%Bbga-%Y9HZZ%gkc*C512*$$DhRxWTGgjUG@=rUD") }, // Signalis (PC)
{ MODE_FSB5_STD, FSBKEY_ADD("281ad163160cfc16f9a22c6755a64fad") }, // Ash Echoes beta (Android)
};
static const int fsbkey_list_count = sizeof(fsbkey_list) / sizeof(fsbkey_list[0]);

View File

@ -3,39 +3,37 @@
#include "../util.h"
/* GCA - Terminal Reality games [Metal Slug Anthology (Wii), BlowOut (GC)] */
VGMSTREAM * init_vgmstream_gca(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_gca(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
int loop_flag, channels;
/* checks */
if (!check_extensions(streamFile, "gca"))
if (!is_id32be(0x00,sf, "GCA1"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x47434131) /* "GCA1" */
if (!check_extensions(sf, "gca"))
goto fail;
start_offset = 0x40;
loop_flag = 0;
channel_count = 1;
channels = 1;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitBE(0x2A,streamFile);
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = dsp_nibbles_to_samples(read_32bitBE(0x26,streamFile));//read_32bitBE(0x26,streamFile)*7/8;
vgmstream->layout_type = layout_none; /* we have no interleave, so we have no layout */
vgmstream->meta_type = meta_GCA;
vgmstream->sample_rate = read_32bitBE(0x2A,sf);
vgmstream->num_samples = dsp_nibbles_to_samples(read_32bitBE(0x26,sf));//read_32bitBE(0x26,streamFile)*7/8;
dsp_read_coefs_be(vgmstream,streamFile,0x04,0x00);
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_none;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
dsp_read_coefs_be(vgmstream, sf, 0x04, 0x00);
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;

View File

@ -70,21 +70,21 @@ typedef struct {
static int parse_genh(STREAMFILE * streamFile, genh_header * genh);
/* GENH is an artificial "generic" header for headerless streams */
VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_genh(STREAMFILE *sf) {
VGMSTREAM* vgmstream = NULL;
genh_header genh = {0};
coding_t coding;
int i, j;
/* check extension, case insensitive */
if (!check_extensions(streamFile,"genh")) goto fail;
/* check header magic */
if (read_32bitBE(0x0,streamFile) != 0x47454e48) goto fail;
/* checks */
if (!is_id32be(0x0,sf, "GENH"))
goto fail;
if (!check_extensions(sf,"genh"))
goto fail;
/* process the header */
if (!parse_genh(streamFile, &genh))
if (!parse_genh(sf, &genh))
goto fail;
@ -277,13 +277,13 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
/* normal/split coefs */
if ((genh.coef_type & 1) == 0) { /* normal mode */
for (j = 0; j < 16; j++) {
vgmstream->ch[i].adpcm_coef[j] = read_16bit(genh.coef_offset + i*genh.coef_spacing + j*2, streamFile);
vgmstream->ch[i].adpcm_coef[j] = read_16bit(genh.coef_offset + i*genh.coef_spacing + j*2, sf);
}
}
else { /* split coefs, 8 coefs in the main array, additional offset to 2nd array given at 0x34 for left, 0x38 for right */
for (j = 0; j < 8; j++) {
vgmstream->ch[i].adpcm_coef[j*2] = read_16bit(genh.coef_offset + i*genh.coef_spacing + j*2, streamFile);
vgmstream->ch[i].adpcm_coef[j*2+1] = read_16bit(genh.coef_split_offset + i*genh.coef_split_spacing + j*2, streamFile);
vgmstream->ch[i].adpcm_coef[j*2] = read_16bit(genh.coef_offset + i*genh.coef_spacing + j*2, sf);
vgmstream->ch[i].adpcm_coef[j*2+1] = read_16bit(genh.coef_split_offset + i*genh.coef_split_spacing + j*2, sf);
}
}
}
@ -292,7 +292,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
#ifdef VGM_USE_MPEG
case coding_MPEG_layer3:
vgmstream->layout_type = layout_none;
vgmstream->codec_data = init_mpeg(streamFile, genh.start_offset, &coding, vgmstream->channels);
vgmstream->codec_data = init_mpeg(sf, genh.start_offset, &coding, vgmstream->channels);
if (!vgmstream->codec_data) goto fail;
break;
@ -303,60 +303,48 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
if (genh.codec == FFMPEG || genh.codec == AC3 || genh.codec == AAC) {
/* default FFmpeg */
ffmpeg_data = init_ffmpeg_offset(streamFile, genh.start_offset,genh.data_size);
ffmpeg_data = init_ffmpeg_offset(sf, genh.start_offset,genh.data_size);
if ( !ffmpeg_data ) goto fail;
//if (vgmstream->num_samples == 0)
// vgmstream->num_samples = ffmpeg_get_samples(ffmpeg_data); /* sometimes works */
}
else if (genh.codec == ATRAC3) {
int block_align, encoder_delay;
block_align = genh.interleave;
encoder_delay = genh.skip_samples;
ffmpeg_data = init_ffmpeg_atrac3_raw(sf, genh.start_offset,genh.data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
if (!ffmpeg_data) goto fail;
}
else if (genh.codec == ATRAC3PLUS) {
int block_size = genh.interleave;
ffmpeg_data = init_ffmpeg_atrac3plus_raw(sf, genh.start_offset, genh.data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, genh.skip_samples);
if (!ffmpeg_data) goto fail;
}
else if (genh.codec == XMA1) {
int xma_stream_mode = genh.codec_mode == 1 ? 1 : 0;
ffmpeg_data = init_ffmpeg_xma1_raw(sf, genh.start_offset, genh.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
if (!ffmpeg_data) goto fail;
}
else if (genh.codec == XMA2) {
int block_size = genh.interleave;
ffmpeg_data = init_ffmpeg_xma2_raw(sf, genh.start_offset, genh.data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, 0);
if (!ffmpeg_data) goto fail;
}
else {
/* fake header FFmpeg */
uint8_t buf[200];
int32_t bytes;
if (genh.codec == ATRAC3) {
int block_align, encoder_delay;
block_align = genh.interleave;
encoder_delay = genh.skip_samples;
ffmpeg_data = init_ffmpeg_atrac3_raw(streamFile, genh.start_offset,genh.data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
if (!ffmpeg_data) goto fail;
}
else if (genh.codec == ATRAC3PLUS) {
int block_size = genh.interleave;
bytes = ffmpeg_make_riff_atrac3plus(buf, 200, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, block_size, genh.skip_samples);
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, genh.start_offset,genh.data_size);
if ( !ffmpeg_data ) goto fail;
}
else if (genh.codec == XMA1) {
int xma_stream_mode = genh.codec_mode == 1 ? 1 : 0;
bytes = ffmpeg_make_riff_xma1(buf, 100, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, genh.start_offset,genh.data_size);
if ( !ffmpeg_data ) goto fail;
}
else if (genh.codec == XMA2) {
int block_count, block_size;
block_size = genh.interleave ? genh.interleave : 2048;
block_count = genh.data_size / block_size;
bytes = ffmpeg_make_riff_xma2(buf, 200, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, genh.start_offset,genh.data_size);
if ( !ffmpeg_data ) goto fail;
}
else {
goto fail;
}
goto fail;
}
vgmstream->codec_data = ffmpeg_data;
vgmstream->layout_type = layout_none;
if (genh.codec == XMA1 || genh.codec == XMA2) {
xma_fix_raw_samples(vgmstream, streamFile, genh.start_offset,genh.data_size, 0, 0,0);
xma_fix_raw_samples(vgmstream, sf, genh.start_offset,genh.data_size, 0, 0,0);
} else if (genh.skip_samples_mode && genh.skip_samples >= 0 && genh.codec != ATRAC3) { /* force encoder delay */
ffmpeg_set_skip_samples(ffmpeg_data, genh.skip_samples);
}
@ -373,7 +361,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
vgmstream->allow_dual_stereo = 1;
if ( !vgmstream_open_stream(vgmstream,streamFile,genh.start_offset) )
if ( !vgmstream_open_stream(vgmstream,sf,genh.start_offset) )
goto fail;
return vgmstream;

View File

@ -0,0 +1,163 @@
#include "meta.h"
#include "../coding/coding.h"
typedef enum { XMA2, ATRAC9 } gtd_codec;
//TODO rename gtd to ghs
/* GHS - Hexadrive's HexaEngine games [Knights Contract (X360), Valhalla Knights 3 (Vita)] */
VGMSTREAM* init_vgmstream_ghs(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset, chunk_offset, stpr_offset, name_offset = 0, loop_start_offset, loop_end_offset;
size_t data_size, chunk_size;
int loop_flag, channels, sample_rate;
int num_samples, loop_start_sample, loop_end_sample;
uint32_t at9_config_data;
gtd_codec codec;
/* checks */
if (!is_id32be(0x00,sf, "GHS "))
goto fail;
if ( !check_extensions(sf,"gtd"))
goto fail;
/* header type, not formally specified */
if (read_32bitBE(0x04,sf) == 1 && read_16bitBE(0x0C,sf) == 0x0166) { /* XMA2 */
/* 0x08(4): seek table size */
chunk_offset = 0x0c; /* custom header with a "fmt " data chunk inside */
chunk_size = 0x34;
channels = read_16bitBE(chunk_offset+0x02,sf);
sample_rate = read_32bitBE(chunk_offset+0x04,sf);
xma2_parse_fmt_chunk_extra(sf, chunk_offset, &loop_flag, &num_samples, &loop_start_sample, &loop_end_sample, 1);
start_offset = read_32bitBE(0x58,sf); /* always 0x800 */
data_size = read_32bitBE(0x5c,sf);
/* 0x34(18): null, 0x54(4): seek table offset, 0x58(4): seek table size, 0x5c(8): null, 0x64: seek table */
stpr_offset = read_32bitBE(chunk_offset+0x54,sf) + read_32bitBE(chunk_offset+0x58,sf);
if (is_id32be(stpr_offset,sf, "STPR")) {
/* SRPR encases the original "S_P_STH" header (no data) */
name_offset = stpr_offset + 0xB8; /* there are offsets fields but seems to work */
}
codec = XMA2;
}
else if (0x34 + read_32bitLE(0x30,sf) + read_32bitLE(0x0c,sf) == get_streamfile_size(sf)) { /* ATRAC9 */
data_size = read_32bitLE(0x0c,sf);
start_offset = 0x34 + read_32bitLE(0x30,sf);
channels = read_32bitLE(0x10,sf);
sample_rate = read_32bitLE(0x14,sf);
loop_start_offset = read_32bitLE(0x1c, sf);
loop_end_offset = read_32bitLE(0x20, sf);
loop_flag = loop_end_offset > loop_start_offset;
at9_config_data = read_32bitBE(0x28,sf);
/* 0x18-0x28: fixed/unknown values */
stpr_offset = 0x2c;
if (is_id32be(stpr_offset,sf, "STPR")) {
/* STPR encases the original "S_P_STH" header (no data) */
name_offset = stpr_offset + 0xE8; /* there are offsets fields but seems to work */
}
codec = ATRAC9;
}
else {
goto fail;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
vgmstream->loop_start_sample = loop_start_sample;
vgmstream->loop_end_sample = loop_end_sample;
vgmstream->meta_type = meta_GHS;
if (name_offset) //encoding is Shift-Jis in some PSV files
read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,sf);
switch(codec) {
#ifdef VGM_USE_FFMPEG
case XMA2:
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, data_size, chunk_offset, chunk_size);
if ( !vgmstream->codec_data ) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = num_samples;
xma_fix_raw_samples(vgmstream, sf, start_offset, data_size, chunk_offset, 1,1);
break;
#endif
#ifdef VGM_USE_ATRAC9
case ATRAC9: {
atrac9_config cfg = {0};
cfg.channels = vgmstream->channels;
cfg.config_data = at9_config_data;
vgmstream->codec_data = init_atrac9(&cfg);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_ATRAC9;
vgmstream->layout_type = layout_none;
if (loop_flag) {
vgmstream->loop_start_sample = atrac9_bytes_to_samples(loop_start_offset - start_offset, vgmstream->codec_data);
vgmstream->loop_end_sample = atrac9_bytes_to_samples(loop_end_offset - start_offset, vgmstream->codec_data);
}
vgmstream->num_samples = atrac9_bytes_to_samples(data_size, vgmstream->codec_data);
break;
}
#endif
default:
goto fail;
}
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
/* S_P_STH - Hexadrive's HexaEngine games [Knights Contract (PS3)] */
VGMSTREAM* init_vgmstream_s_p_sth(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
STREAMFILE* temp_sf = NULL;
uint32_t subfile_offset, subfile_size, name_offset;
/* checks */
if (!is_id64be(0x00,sf,"S_P_STH\x01"))
goto fail;
if (!check_extensions(sf,"gtd"))
goto fail;
subfile_offset = read_u32be(0x08, sf);
subfile_size = get_streamfile_size(sf) - subfile_offset;
temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, "msf");
if (!temp_sf) goto fail;
vgmstream = init_vgmstream_msf(temp_sf);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_GHS;
name_offset = 0xB0; /* there are offsets fields but seems to work */
read_string(vgmstream->stream_name, STREAM_NAME_SIZE, name_offset, sf);
close_streamfile(temp_sf);
return vgmstream;
fail:
close_streamfile(temp_sf);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -3,53 +3,53 @@
#include "../coding/coding.h"
/* GSP+GSB - from Tecmo's Super Swing Golf 1 & 2 (Wii), Quantum Theory (PS3/X360) */
VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamHeader = NULL;
VGMSTREAM* init_vgmstream_gsp_gsb(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
STREAMFILE* sf_head = NULL;
int loop_flag, channel_count, sample_rate, num_samples, loop_start, loop_end;
off_t start_offset, chunk_offset, first_offset;
size_t data_size;
int codec;
/* checks */
if (!check_extensions(streamFile,"gsb"))
if (!check_extensions(sf,"gsb"))
goto fail;
streamHeader = open_streamfile_by_ext(streamFile, "gsp");
if (!streamHeader) goto fail;
sf_head = open_streamfile_by_ext(sf, "gsp");
if (!sf_head) goto fail;
if (read_32bitBE(0x00,streamHeader) != 0x47534E44) /* "GSND" */
if (!is_id32be(0x00,sf_head, "GSND"))
goto fail;
/* 0x04: version? */
/* 0x08: 1? */
/* 0x0c: 0? */
first_offset = read_32bitBE(0x10,streamHeader); /* usually 0x14 */
first_offset = read_32bitBE(0x10,sf_head); /* usually 0x14 */
if (!find_chunk_be(streamHeader, 0x48454144,first_offset,1, &chunk_offset,NULL)) /* "HEAD" */
if (!find_chunk_be(sf_head, 0x48454144,first_offset,1, &chunk_offset,NULL)) /* "HEAD" */
goto fail;
/* 0x00: header size */
/* 0x04: num_chunks */
if (!find_chunk_be(streamHeader, 0x44415441,first_offset,1, &chunk_offset,NULL)) /* "DATA" */
if (!find_chunk_be(sf_head, 0x44415441,first_offset,1, &chunk_offset,NULL)) /* "DATA" */
goto fail;
data_size = read_32bitBE(chunk_offset + 0x00,streamHeader);
codec = read_32bitBE(chunk_offset + 0x04,streamHeader);
sample_rate = read_32bitBE(chunk_offset + 0x08,streamHeader);
data_size = read_32bitBE(chunk_offset + 0x00,sf_head);
codec = read_32bitBE(chunk_offset + 0x04,sf_head);
sample_rate = read_32bitBE(chunk_offset + 0x08,sf_head);
/* 0x0c: always 16? */
channel_count = read_16bitBE(chunk_offset + 0x0e,streamHeader);
channel_count = read_16bitBE(chunk_offset + 0x0e,sf_head);
/* 0x10: always 0? */
num_samples = read_32bitBE(chunk_offset + 0x14,streamHeader);
num_samples = read_32bitBE(chunk_offset + 0x14,sf_head);
/* 0x18: always 0? */
/* 0x1c: unk (varies with codec_id) */
if (!find_chunk_be(streamHeader, 0x42534943,first_offset,1, &chunk_offset,NULL)) /* "BSIC" */
if (!find_chunk_be(sf_head, 0x42534943,first_offset,1, &chunk_offset,NULL)) /* "BSIC" */
goto fail;
/* 0x00/0x04: probably volume/pan/etc floats (1.0) */
/* 0x08: null? */
loop_flag = read_8bit(chunk_offset+0x0c,streamHeader);
loop_start = read_32bitBE(chunk_offset+0x10,streamHeader);
loop_end = read_32bitBE(chunk_offset+0x14,streamHeader);
loop_flag = read_8bit(chunk_offset+0x0c,sf_head);
loop_start = read_32bitBE(chunk_offset+0x10,sf_head);
loop_end = read_32bitBE(chunk_offset+0x14,sf_head);
//if (!find_chunk_be(streamHeader, 0x4E414D45,first_offset,1, &chunk_offset,NULL)) /* "NAME" */
// goto fail;
@ -79,16 +79,16 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_blocked_gsb;
if (!find_chunk_be(streamHeader, 0x47434558,first_offset,1, &chunk_offset,NULL)) /* "GCEX" */
if (!find_chunk_be(sf_head, 0x47434558,first_offset,1, &chunk_offset,NULL)) /* "GCEX" */
goto fail;
//vgmstream->current_block_size = read_32bitBE(chunk_offset+0x00,streamHeader);
block_header_size = read_32bitBE(chunk_offset+0x04,streamHeader);
num_blocks = read_32bitBE(chunk_offset+0x08,streamHeader);
block_header_size = read_32bitBE(chunk_offset+0x04,sf_head);
num_blocks = read_32bitBE(chunk_offset+0x08,sf_head);
vgmstream->num_samples = (data_size - block_header_size * num_blocks) / 8 / vgmstream->channels * 14;
/* 0x0c+: unk */
dsp_read_coefs_be(vgmstream, streamHeader, chunk_offset+0x18, 0x30);
dsp_read_coefs_be(vgmstream, sf_head, chunk_offset+0x18, 0x30);
break;
}
#ifdef VGM_USE_FFMPEG
@ -100,7 +100,7 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
vgmstream->num_samples = atrac3_bytes_to_samples(data_size, block_align) - encoder_delay;
/* fix num_samples as header samples seem to be modified to match altered (49999/48001) sample rates somehow */
vgmstream->codec_data = init_ffmpeg_atrac3_raw(streamFile, start_offset,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
vgmstream->codec_data = init_ffmpeg_atrac3_raw(sf, start_offset,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
@ -112,21 +112,17 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
}
case 0x09: { /* XMA2 [Quantum Theory (PS3)] */
uint8_t buf[0x100];
int32_t bytes;
if (!find_chunk_be(streamHeader, 0x584D4558,first_offset,1, &chunk_offset,NULL)) /* "XMEX" */
if (!find_chunk_be(sf_head, 0x584D4558,first_offset,1, &chunk_offset,NULL)) /* "XMEX" */
goto fail;
/* 0x00: fmt0x166 header (BE) */
/* 0x34: seek table */
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, chunk_offset,0x34, data_size, streamHeader, 1);
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk_split(sf_head, sf, start_offset, data_size, chunk_offset, 0x34);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, start_offset,data_size, 0, 0,0); /* samples are ok */
xma_fix_raw_samples(vgmstream, sf, start_offset,data_size, 0, 0,0); /* samples are ok */
break;
}
#endif
@ -135,13 +131,13 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
}
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
close_streamfile(streamHeader);
close_streamfile(sf_head);
return vgmstream;
fail:
close_streamfile(streamHeader);
close_streamfile(sf_head);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,136 +0,0 @@
#include "meta.h"
#include "../coding/coding.h"
typedef enum { XMA2, ATRAC9 } gtd_codec;
/* GTD - found in Knights Contract (X360, PS3), Valhalla Knights 3 (PSV) */
VGMSTREAM * init_vgmstream_gtd(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset, chunk_offset, stpr_offset, name_offset = 0, loop_start_offset, loop_end_offset;
size_t data_size, chunk_size;
int loop_flag, channel_count, sample_rate;
int num_samples, loop_start_sample, loop_end_sample;
uint32_t at9_config_data;
gtd_codec codec;
/* check extension, case insensitive */
if ( !check_extensions(streamFile,"gtd"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x47485320) /* "GHS " */
goto fail;
/* header type, not formally specified */
if (read_32bitBE(0x04,streamFile) == 1 && read_16bitBE(0x0C,streamFile) == 0x0166) { /* XMA2 */
/* 0x08(4): seek table size */
chunk_offset = 0x0c; /* custom header with a "fmt " data chunk inside */
chunk_size = 0x34;
channel_count = read_16bitBE(chunk_offset+0x02,streamFile);
sample_rate = read_32bitBE(chunk_offset+0x04,streamFile);
xma2_parse_fmt_chunk_extra(streamFile, chunk_offset, &loop_flag, &num_samples, &loop_start_sample, &loop_end_sample, 1);
start_offset = read_32bitBE(0x58,streamFile); /* always 0x800 */
data_size = read_32bitBE(0x5c,streamFile);
/* 0x34(18): null, 0x54(4): seek table offset, 0x58(4): seek table size, 0x5c(8): null, 0x64: seek table */
stpr_offset = read_32bitBE(chunk_offset+0x54,streamFile) + read_32bitBE(chunk_offset+0x58,streamFile);
if (read_32bitBE(stpr_offset,streamFile) == 0x53545052) { /* "STPR" */
name_offset = stpr_offset + 0xB8; /* there are offsets fields but seems to work */
}
codec = XMA2;
}
else if (0x34 + read_32bitLE(0x30,streamFile) + read_32bitLE(0x0c,streamFile) == get_streamfile_size(streamFile)) { /* ATRAC9 */
data_size = read_32bitLE(0x0c,streamFile);
start_offset = 0x34 + read_32bitLE(0x30,streamFile);
channel_count = read_32bitLE(0x10,streamFile);
sample_rate = read_32bitLE(0x14,streamFile);
loop_start_offset = read_32bitLE(0x1c, streamFile);
loop_end_offset = read_32bitLE(0x20, streamFile);
loop_flag = loop_end_offset > loop_start_offset;
at9_config_data = read_32bitBE(0x28,streamFile);
/* 0x18-0x28: fixed/unknown values */
stpr_offset = 0x2c;
if (read_32bitBE(stpr_offset,streamFile) == 0x53545052) { /* "STPR" */
name_offset = stpr_offset + 0xE8; /* there are offsets fields but seems to work */
}
codec = ATRAC9;
}
else {
/* apparently there is a PS3 variation (MSF inside?) */
goto fail;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
vgmstream->loop_start_sample = loop_start_sample;
vgmstream->loop_end_sample = loop_end_sample;
vgmstream->meta_type = meta_GTD;
if (name_offset) //encoding is Shift-Jis in some PSV files
read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,streamFile);
switch(codec) {
#ifdef VGM_USE_FFMPEG
case XMA2: {
uint8_t buf[0x100];
size_t bytes;
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, chunk_offset,chunk_size, data_size, streamFile, 1);
if (bytes <= 0) goto fail;
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
if ( !vgmstream->codec_data ) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = num_samples;
xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, chunk_offset, 1,1);
break;
}
#endif
#ifdef VGM_USE_ATRAC9
case ATRAC9: {
atrac9_config cfg = {0};
cfg.channels = vgmstream->channels;
cfg.config_data = at9_config_data;
vgmstream->codec_data = init_atrac9(&cfg);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_ATRAC9;
vgmstream->layout_type = layout_none;
if (loop_flag) {
vgmstream->loop_start_sample = atrac9_bytes_to_samples(loop_start_offset - start_offset, vgmstream->codec_data);
vgmstream->loop_end_sample = atrac9_bytes_to_samples(loop_end_offset - start_offset, vgmstream->codec_data);
}
vgmstream->num_samples = atrac9_bytes_to_samples(data_size, vgmstream->codec_data);
break;
}
#endif
default:
goto fail;
}
/* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,7 +1,7 @@
#ifndef _HCA_KEYS_H_
#define _HCA_KEYS_H_
#include "hca_keys_awb.h"
#include <stdint.h>
//#include "hca_keys_awb.h"
typedef struct {
uint64_t key; /* hca key or seed ('user') key */
@ -1091,12 +1091,18 @@ static const hcakey_info hcakey_list[] = {
// P Sengoku Otome 6 ~Akatsuki no Sekigahara~ (Android)
{97648135}, // 0000000005d1fe07
// CHUNITHM International Version (AC)
{33426922444908636}, // 0076C19BDE43685C
// Star Ocean: The Divine Force (PC)
{68308868861462528}, // 00f2ae8de77f0800
// Sin Chronicle (Android)
{4385672148314579020}, // 3CDD0995259D604C
// The Eminence in Shadow: Master of Garden (Android)
{8115775984160473168}, // 70A1074224880050
};
#endif/*_HCA_KEYS_H_*/

View File

@ -3,10 +3,10 @@
/* HIS - Her Interactive games [Nancy Drew series (PC)] */
VGMSTREAM * init_vgmstream_his(STREAMFILE *sf) {
VGMSTREAM * vgmstream = NULL;
int channels, loop_flag = 0, bps, sample_rate, num_samples, version;
off_t start_offset;
VGMSTREAM* init_vgmstream_his(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
int channels, loop_flag = 0, bps, sample_rate, num_samples, version, codec;
uint32_t start_offset;
/* checks */
@ -17,8 +17,10 @@ VGMSTREAM * init_vgmstream_his(STREAMFILE *sf) {
goto fail;
if (is_id32be(0x00,sf, "Her ")) { /* "Her Interactive Sound\x1a" */
/* Nancy Drew: Secrets Can Kill (PC) */
version = 0;
codec = 1;
/* Nancy Drew: Secrets Can Kill (PC) */
channels = read_u16le(0x16,sf);
sample_rate = read_u32le(0x18,sf);
/* 0x1c: bitrate */
@ -34,7 +36,7 @@ VGMSTREAM * init_vgmstream_his(STREAMFILE *sf) {
else if (is_id32be(0x00,sf, "HIS\0")) {
/* most(?) others */
version = read_u32le(0x04,sf);
/* 0x08: codec */
/* 0x08: format? (always 1) */
channels = read_u16le(0x0a,sf);
sample_rate = read_u32le(0x0c,sf);
/* 0x10: bitrate */
@ -42,28 +44,51 @@ VGMSTREAM * init_vgmstream_his(STREAMFILE *sf) {
bps = read_u16le(0x16,sf);
num_samples = pcm_bytes_to_samples(read_u32le(0x18,sf), channels, bps); /* true even for Ogg */
if (version >= 2) {
codec = read_u16le(0x1c,sf); /* 1:pcm, 2:ogg */
/* 0x1e: data or null in later(?) games */
}
else {
codec = 1;
}
/* later games use "OggS" */
if (version == 1)
if (version == 1) {
start_offset = 0x1c; /* Nancy Drew: The Final Scene (PC) */
else if (version == 2 && is_id32be(0x1e,sf, "OggS"))
start_offset = 0x1e; /* Nancy Drew: The Haunted Carousel (PC) */
else if (version == 2 && is_id32be(0x20,sf, "OggS"))
start_offset = 0x20; /* Nancy Drew: The Silent Spy (PC) */
else
}
else if (version == 2) {
if (codec == 1) {
uint32_t left_size = get_streamfile_size(sf) - 0x1e;
if (num_samples == pcm_bytes_to_samples(left_size, channels, bps))
start_offset = 0x1e; /* Nancy Drew: Ghost Dogs of Moon Lake (PC) */
else
start_offset = 0x20; /* assumed */
}
else if (codec == 2) {
if (read_u16le(0x1e, sf) != 0)
start_offset = 0x1e; /* Nancy Drew: The Haunted Carousel (PC) */
else
start_offset = 0x20; /* Nancy Drew: The Silent Spy (PC) */
}
else {
goto fail;
}
}
else {
goto fail;
}
}
else {
goto fail;
}
if (version == 2) {
/*
if (codec == 2) {
ogg_vorbis_meta_info_t ovmi = {0};
ovmi.meta_type = meta_HIS;
return init_vgmstream_ogg_vorbis_config(sf, start_offset, &ovmi);
}
*/
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
@ -73,17 +98,32 @@ VGMSTREAM * init_vgmstream_his(STREAMFILE *sf) {
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;
switch (bps) {
case 8:
vgmstream->coding_type = coding_PCM8_U;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x01;
switch (codec) {
case 1:
switch (bps) {
case 8:
vgmstream->coding_type = coding_PCM8_U;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x01;
break;
case 16:
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x02;
break;
default:
goto fail;
}
break;
case 16:
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x02;
case 2:
#ifdef VGM_USE_VORBIS
vgmstream->codec_data = init_ogg_vorbis(sf, start_offset, 0, NULL);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_OGG_VORBIS;
vgmstream->layout_type = layout_none;
break;
#endif
default:
goto fail;
}

View File

@ -13,14 +13,14 @@ VGMSTREAM* init_vgmstream_mzrt_v0(STREAMFILE* sf) {
/* checks */
if (!is_id32be(0x00,sf, "mzrt"))
goto fail;
if (read_u32be(0x04, sf) != 0) /* version */
goto fail;
if (!check_extensions(sf, "idwav,idmsf,idxma"))
goto fail;
if (!is_id32be(0x00,sf, "mzrt"))
goto fail;
if (read_u32be(0x04, sf) != 0) /* version */
goto fail;
/* this format is bizarrely mis-aligned (and mis-designed too) */
@ -111,12 +111,9 @@ VGMSTREAM* init_vgmstream_mzrt_v0(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 0x0166: {
uint8_t buf[0x100];
int bytes;
size_t stream_size = get_streamfile_size(temp_sf);
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,sizeof(buf), 0x15,0x34, stream_size, sf, 0);
vgmstream->codec_data = init_ffmpeg_header_offset(temp_sf, buf,bytes, 0x00,stream_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk_split(sf, temp_sf, 0x00, stream_size, 0x15, 0x34);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
@ -167,14 +164,14 @@ VGMSTREAM* init_vgmstream_mzrt_v1(STREAMFILE* sf) {
/* checks */
if (!check_extensions(sf, "idmsf")) //idmsa: untested
goto fail;
if (!is_id32be(0x00,sf, "mzrt"))
goto fail;
if (read_u32be(0x04, sf) != 1) /* version */
goto fail;
if (!check_extensions(sf, "idmsf")) //idmsa: untested
goto fail;
type = read_s32be(0x09,sf);
if (type == 0) { /* Rage */
/* 0x0d: null */
@ -314,14 +311,14 @@ VGMSTREAM* init_vgmstream_bsnf(STREAMFILE* sf) {
/* checks */
if (!check_extensions(sf, "bsnd"))
goto fail;
if (!is_id32be(0x00,sf, "bsnf")) /* null-terminated string */
goto fail;
if (read_u32be(0x05, sf) != 0x00000100) /* version */
goto fail;
if (!check_extensions(sf, "bsnd"))
goto fail;
offset = 0x18;
stream_size = read_u32be(offset + 0x00,sf);
@ -430,14 +427,9 @@ VGMSTREAM* init_vgmstream_bsnf(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 0x0166: {
uint8_t buf[0x100];
size_t bytes, block_size, block_count;
int block_size = 0x800;
block_size = 0x800;
block_count = stream_size / block_size;
bytes = ffmpeg_make_riff_xma2(buf, sizeof(buf), num_samples, stream_size, channels, sample_rate, block_count, block_size);
vgmstream->codec_data = init_ffmpeg_header_offset(sb, buf, bytes, start_offset, stream_size);
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, start_offset, stream_size, num_samples, channels, sample_rate, block_size, 0);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -238,8 +238,6 @@ VGMSTREAM* init_vgmstream_isb(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 0x04: {
uint8_t buf[0x100];
size_t bytes;
off_t fmt_offset = start_offset;
size_t fmt_size = 0x20;
@ -247,8 +245,7 @@ VGMSTREAM* init_vgmstream_isb(STREAMFILE* sf) {
stream_size -= fmt_size;
/* XMA1 "fmt" chunk (BE, unlike the usual LE) */
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,sizeof(buf), fmt_offset,fmt_size, stream_size, sf, 1);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset, stream_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, stream_size, fmt_offset, fmt_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -62,16 +62,12 @@ VGMSTREAM* init_vgmstream_ivaud(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 0x0000: { /* XMA2 (X360) */
uint8_t buf[0x100];
size_t bytes;
if (ivaud.is_music) {
goto fail;
}
else {
/* regular XMA for sfx */
bytes = ffmpeg_make_riff_xma1(buf, 0x100, ivaud.num_samples, ivaud.stream_size, ivaud.channel_count, ivaud.sample_rate, 0);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, ivaud.stream_offset, ivaud.stream_size);
vgmstream->codec_data = init_ffmpeg_xma1_raw(sf, ivaud.stream_offset, ivaud.stream_size, ivaud.channel_count, ivaud.sample_rate, 0);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -2,7 +2,7 @@
#include "../coding/coding.h"
#include "../layout/layout.h"
typedef enum { NONE, MSADPCM, DSP, GCADPCM, ATRAC9, RIFF_ATRAC9, KOVS, /*KNS*/ } ktsr_codec;
typedef enum { NONE, MSADPCM, DSP, GCADPCM, ATRAC9, RIFF_ATRAC9, KOVS, KTSS, } ktsr_codec;
#define MAX_CHANNELS 8
@ -33,9 +33,9 @@ typedef struct {
static int parse_ktsr(ktsr_header* ktsr, STREAMFILE* sf);
static layered_layout_data* build_layered_atrac9(ktsr_header* ktsr, STREAMFILE *sf, uint32_t config_data);
static VGMSTREAM* init_vgmstream_ktsr_sub(STREAMFILE* sf_b, ktsr_header* ktsr, VGMSTREAM* (*init_vgmstream)(STREAMFILE* sf), const char* ext);
/* KTSR - Koei Tecmo sound resource countainer */
/* KTSR - Koei Tecmo sound resource container */
VGMSTREAM* init_vgmstream_ktsr(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
STREAMFILE* sf_b = NULL;
@ -76,6 +76,26 @@ VGMSTREAM* init_vgmstream_ktsr(STREAMFILE* sf) {
}
/* subfiles */
{
VGMSTREAM* (*init_vgmstream)(STREAMFILE* sf) = NULL;
const char* ext;
switch(ktsr.codec) {
case RIFF_ATRAC9: init_vgmstream = init_vgmstream_riff; ext = "at9"; break;
case KOVS: init_vgmstream = init_vgmstream_ogg_vorbis; ext = "kvs"; break;
case KTSS: init_vgmstream = init_vgmstream_ktss; ext = "ktss"; break;
default: break;
}
if (init_vgmstream) {
vgmstream = init_vgmstream_ktsr_sub(sf_b, &ktsr, init_vgmstream, ext);
if (!vgmstream) goto fail;
if (sf_b != sf) close_streamfile(sf_b);
return vgmstream;
}
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(ktsr.channels, ktsr.loop_flag);
if (!vgmstream) goto fail;
@ -125,49 +145,6 @@ VGMSTREAM* init_vgmstream_ktsr(STREAMFILE* sf) {
break;
}
#endif
case RIFF_ATRAC9: {
VGMSTREAM* riff_vgmstream = NULL; //TODO: meh
STREAMFILE* temp_sf = setup_subfile_streamfile(sf_b, ktsr.stream_offsets[0], ktsr.stream_sizes[0], "at9");
if (!temp_sf) goto fail;
riff_vgmstream = init_vgmstream_riff(temp_sf);
close_streamfile(temp_sf);
if (!riff_vgmstream) goto fail;
riff_vgmstream->stream_size = vgmstream->stream_size;
riff_vgmstream->num_streams = vgmstream->num_streams;
riff_vgmstream->channel_layout = vgmstream->channel_layout;
strcpy(riff_vgmstream->stream_name, vgmstream->stream_name);
close_vgmstream(vgmstream);
if (sf_b != sf) close_streamfile(sf_b);
return riff_vgmstream;
}
#ifdef VGM_USE_VORBIS
case KOVS: {
VGMSTREAM* ogg_vgmstream = NULL; //TODO: meh
STREAMFILE* temp_sf = setup_subfile_streamfile(sf_b, ktsr.stream_offsets[0], ktsr.stream_sizes[0], "kvs");
if (!temp_sf) goto fail;
ogg_vgmstream = init_vgmstream_ogg_vorbis(temp_sf);
close_streamfile(temp_sf);
if (!ogg_vgmstream) goto fail;
ogg_vgmstream->stream_size = vgmstream->stream_size;
ogg_vgmstream->num_streams = vgmstream->num_streams;
ogg_vgmstream->channel_layout = vgmstream->channel_layout;
/* loops look shared */
strcpy(ogg_vgmstream->stream_name, vgmstream->stream_name);
close_vgmstream(vgmstream);
if (sf_b != sf) close_streamfile(sf_b);
return ogg_vgmstream;
}
#endif
default:
goto fail;
}
@ -193,6 +170,26 @@ fail:
return NULL;
}
// TODO improve, unity with other metas that do similar stuff
static VGMSTREAM* init_vgmstream_ktsr_sub(STREAMFILE* sf_b, ktsr_header* ktsr, VGMSTREAM* (*init_vgmstream)(STREAMFILE* sf), const char* ext) {
VGMSTREAM* sub_vgmstream = NULL;
STREAMFILE* temp_sf = setup_subfile_streamfile(sf_b, ktsr->stream_offsets[0], ktsr->stream_sizes[0], ext);
if (!temp_sf) return NULL;
sub_vgmstream = init_vgmstream(temp_sf);
close_streamfile(temp_sf);
if (!sub_vgmstream) return NULL;
sub_vgmstream->stream_size = ktsr->stream_sizes[0];
sub_vgmstream->num_streams = ktsr->total_subsongs;
sub_vgmstream->channel_layout = ktsr->channel_layout;
strcpy(sub_vgmstream->stream_name, ktsr->name);
return sub_vgmstream;
}
static layered_layout_data* build_layered_atrac9(ktsr_header* ktsr, STREAMFILE* sf, uint32_t config_data) {
STREAMFILE* temp_sf = NULL;
layered_layout_data* data = NULL;
@ -256,12 +253,12 @@ static int parse_codec(ktsr_header* ktsr) {
case 0x01: /* PC */
if (ktsr->is_external) {
if (ktsr->format == 0x0005)
ktsr->codec = KOVS;
ktsr->codec = KOVS; // Atelier Ryza (PC)
else
goto fail;
}
else if (ktsr->format == 0x0000) {
ktsr->codec = MSADPCM;
ktsr->codec = MSADPCM; // Warrior Orochi 4 (PC)
}
else {
goto fail;
@ -271,21 +268,25 @@ static int parse_codec(ktsr_header* ktsr) {
case 0x03: /* PS4/VITA */
if (ktsr->is_external) {
if (ktsr->format == 0x1001)
ktsr->codec = RIFF_ATRAC9;
ktsr->codec = RIFF_ATRAC9; // Nioh (PS4)
else
goto fail;
}
else if (ktsr->format == 0x0001)
ktsr->codec = ATRAC9;
ktsr->codec = ATRAC9; // Attack on Titan: Wings of Freedom (Vita)
else
goto fail;
break;
case 0x04: /* Switch */
if (ktsr->is_external)
goto fail; /* KTSS? */
if (ktsr->is_external) {
if (ktsr->format == 0x0005)
ktsr->codec = KTSS; // [Ultra Kaiju Monster Rancher (Switch)]
else
goto fail;
}
else if (ktsr->format == 0x0000)
ktsr->codec = DSP;
ktsr->codec = DSP; // Fire Emblem: Three Houses (Switch)
else
goto fail;
break;
@ -296,7 +297,7 @@ static int parse_codec(ktsr_header* ktsr) {
return 1;
fail:
VGM_LOG("ktsr: unknown codec combo: ext=%x, fmt=%x, ptf=%x\n", ktsr->is_external, ktsr->format, ktsr->platform);
VGM_LOG("ktsr: unknown codec combo: external=%x, format=%x, platform=%x\n", ktsr->is_external, ktsr->format, ktsr->platform);
return 0;
}

View File

@ -215,16 +215,11 @@ static VGMSTREAM* init_vgmstream_koei_wavebank(kwb_header* kwb, STREAMFILE* sf_h
#ifdef VGM_USE_FFMPEG
case XMA2: {
uint8_t buf[0x100];
size_t bytes, block_size, block_count;
int block_size = 0x800; /* ? */
if (kwb->channels > 1) goto fail;
block_size = 0x800; /* ? */
block_count = kwb->stream_size / block_size;
bytes = ffmpeg_make_riff_xma2(buf, sizeof(buf), vgmstream->num_samples, kwb->stream_size, kwb->channels, kwb->sample_rate, block_count, block_size);
vgmstream->codec_data = init_ffmpeg_header_offset(sf_b, buf,bytes, kwb->stream_offset, kwb->stream_size);
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf_b, kwb->stream_offset, kwb->stream_size, vgmstream->num_samples, kwb->channels, kwb->sample_rate, block_size, 0);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -85,7 +85,6 @@ VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_xa(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_rxws(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_rxws_badrip(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_raw_int(STREAMFILE *streamFile);
@ -159,8 +158,6 @@ VGMSTREAM* init_vgmstream_mp4_aac_ffmpeg(STREAMFILE* sf);
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
VGMSTREAM * init_vgmstream_mp4_aac(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_mp4_aac_offset(STREAMFILE *streamFile, uint64_t start, uint64_t size);
VGMSTREAM * init_vgmstream_akb_mp4(STREAMFILE *streamFile);
#endif
VGMSTREAM * init_vgmstream_sli_ogg(STREAMFILE * streamFile);
@ -299,8 +296,6 @@ VGMSTREAM * init_vgmstream_ngc_ymf(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_sadl(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ps2_ccc(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_fag(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ps2_mihb(STREAMFILE * streamFile);
@ -314,7 +309,7 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_dc_asd(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_naomi_spsd(STREAMFILE * streamFile);
VGMSTREAM* init_vgmstream_spsd(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_bgw(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_spw(STREAMFILE * streamFile);
@ -490,14 +485,13 @@ VGMSTREAM * init_vgmstream_jstm(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_xvag(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps3_cps(STREAMFILE* streamFile);
VGMSTREAM* init_vgmstream_cps(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ngc_nst_dsp(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_baf(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_baf_badrip(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_msf(STREAMFILE* streamFile);
@ -509,8 +503,6 @@ VGMSTREAM * init_vgmstream_wii_ras(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_spm(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_x360_tra(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_iab(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_vs_str(STREAMFILE* streamFile);
@ -582,21 +574,21 @@ VGMSTREAM * init_vgmstream_bik(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_vds_vdm(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_x360_cxs(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_cxs(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_dsp_adx(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile);
VGMSTREAM* init_vgmstream_astb(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_wwise(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_wwise_bnk(STREAMFILE* sf, int* p_prefetch);
VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_x360_pasx(STREAMFILE *streamFile);
VGMSTREAM* init_vgmstream_pasx(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile);
@ -604,9 +596,10 @@ VGMSTREAM * init_vgmstream_ogl(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_mc3(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_gtd(STREAMFILE *streamFile);
VGMSTREAM* init_vgmstream_ghs(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_s_p_sth(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_ta_aac(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_aac_triace(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_va3(STREAMFILE *streamFile);
@ -875,7 +868,7 @@ VGMSTREAM * init_vgmstream_nub_dsp(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_nub_idsp(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_nub_is14(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_xmv_valve(STREAMFILE * streamFile);
VGMSTREAM* init_vgmstream_xwv_valve(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_ubi_hx(STREAMFILE * streamFile);
@ -927,8 +920,8 @@ VGMSTREAM* init_vgmstream_dsb(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_bsf(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_xse_new(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_xse_old(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_sdrh_new(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_sdrh_old(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_wady(STREAMFILE* sf);

View File

@ -252,8 +252,6 @@ static layered_layout_data* build_layered_mul(STREAMFILE* sf, off_t offset, int
switch(codec) {
#ifdef VGM_USE_FFMPEG
case XMA1: {
uint8_t buf[0x100];
int bytes;
size_t stream_size;
int layer_channels = 1;
@ -269,12 +267,11 @@ static layered_layout_data* build_layered_mul(STREAMFILE* sf, off_t offset, int
data->layers[i]->sample_rate = vgmstream->sample_rate;
data->layers[i]->num_samples = vgmstream->num_samples;
bytes = ffmpeg_make_riff_xma1(buf, 0x100, data->layers[i]->num_samples, stream_size, data->layers[i]->channels, data->layers[i]->sample_rate, 0);
data->layers[i]->codec_data = init_ffmpeg_header_offset(temp_sf, buf,bytes, 0x00, stream_size);
data->layers[i]->codec_data = init_ffmpeg_xma1_raw(temp_sf, 0x00, stream_size, data->layers[i]->channels, data->layers[i]->sample_rate, 0);
if (!data->layers[i]->codec_data) goto fail;
data->layers[i]->coding_type = coding_FFmpeg;
data->layers[i]->layout_type = layout_none;
data->layers[i]->stream_size = stream_size;
xma_fix_raw_samples(data->layers[i], temp_sf, 0x00,stream_size, 0, 0,0); /* ? */

View File

@ -11,8 +11,8 @@ struct dsp_header {
uint32_t sample_rate; /* 0x08 (generally 22/32/44/48kz but games like Wario World set 32028hz to adjust for GC's rate) */
uint16_t loop_flag; /* 0x0c */
uint16_t format; /* 0x0e (always 0 for ADPCM) */
uint32_t loop_start_offset; /* 0x10 */
uint32_t loop_end_offset; /* 0x14 */
uint32_t loop_start_offset; /* 0x10 (in nibbles, should be 2 if 0/not set) */
uint32_t loop_end_offset; /* 0x14 (in nibbles) */
uint32_t initial_offset; /* 0x18 ("ca", in nibbles, should be 2) */
int16_t coef[16]; /* 0x1c (eight pairs) */
uint16_t gain; /* 0x3c (always 0 for ADPCM) */
@ -23,7 +23,7 @@ struct dsp_header {
int16_t loop_hist1; /* 0x46 */
int16_t loop_hist2; /* 0x48 */
int16_t channels; /* 0x4a (DSPADPCM.exe ~v2.7 extension) */
int16_t block_size; /* 0x4c */
uint16_t block_size; /* 0x4c */
/* padding/reserved up to 0x60, DSPADPCM.exe from GC adds garbage here (uninitialized MSVC memory?)
* [ex. Batallion Wars (GC), Timesplitters 2 (GC)], 0xcccc...cccc with DSPADPCMD */
};
@ -291,7 +291,7 @@ fail:
/* ********************************* */
/* .dsp - standard dsp as generated by DSPADPCM.exe */
/* .dsp - standard mono dsp as generated by DSPADPCM.exe */
VGMSTREAM* init_vgmstream_ngc_dsp_std(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
struct dsp_header header;
@ -304,7 +304,7 @@ VGMSTREAM* init_vgmstream_ngc_dsp_std(STREAMFILE* sf) {
goto fail;
/* .dsp: standard
* .adp: Dr. Muto/Battalion Wars (GC) mono files
* .adp: Dr. Muto/Battalion Wars (GC), Tale of Despereaux (Wii)
* (extensionless): Tony Hawk's Downhill Jam (Wii) */
if (!check_extensions(sf, "dsp,adp,"))
goto fail;
@ -319,7 +319,8 @@ VGMSTREAM* init_vgmstream_ngc_dsp_std(STREAMFILE* sf) {
* out thoroughly, we're probably not dealing with a genuine mono DSP.
* In many cases these will pass all the other checks, including the
* predictor/scale check if the first byte is 0 */
//todo maybe this meta should be after others, so they have a chance to detect >1ch .dsp
//TODO: maybe this meta should be after others, so they have a better chance to detect >1ch .dsp
// (but .dsp is the common case, so it'd be slower)
{
int ko;
struct dsp_header header2;
@ -344,6 +345,21 @@ VGMSTREAM* init_vgmstream_ngc_dsp_std(STREAMFILE* sf) {
header.loop_flag == header2.loop_flag) {
goto fail;
}
/* ignore ddsp, that set samples/nibbles counting both channels so can't be detected
* (could check for .dsp but most files don't need this) */
if (check_extensions(sf, "adp")) {
uint32_t interleave = (get_streamfile_size(sf) / 2);
ko = !read_dsp_header_be(&header2, interleave, sf);
if (!ko &&
header.sample_count == header2.sample_count &&
header.nibble_count == header2.nibble_count &&
header.sample_rate == header2.sample_rate &&
header.loop_flag == header2.loop_flag) {
goto fail;
}
}
}
if (header.loop_flag) {
@ -822,14 +838,15 @@ fail:
return NULL;
}
/* .ddsp - full interleaved dsp [Shark Tale, (GC), The Sims 2: Pets (Wii), Wacky Races: Crash & Dash (Wii)] */
/* .ddsp - full interleaved dsp [Shark Tale (GC), The Sims 2: Pets (Wii), Wacky Races: Crash & Dash (Wii)] */
VGMSTREAM* init_vgmstream_dsp_ddsp(STREAMFILE* sf) {
dsp_meta dspm = {0};
/* checks */
/* .ddsp: assumed?
/* .adp: Tale of Despereaux (Wii) */
/* .ddsp: fake extension (games have bigfiles without names, but has references to .wav)
* .wav: Wacky Races: Crash & Dash (Wii) */
if (!check_extensions(sf, "ddsp,wav,lwav"))
if (!check_extensions(sf, "adp,ddsp,wav,lwav"))
goto fail;
dspm.channels = 2;
@ -840,6 +857,9 @@ VGMSTREAM* init_vgmstream_dsp_ddsp(STREAMFILE* sf) {
dspm.start_offset = 0x60;
dspm.interleave = dspm.header_spacing;
/* this format has nibbles in both headers matching all data (not just for that channel),
* and interleave is exact half even for files that aren't aligned to 0x10 */
dspm.meta_type = meta_DSP_DDSP;
return init_vgmstream_dsp_common(sf, &dspm);
fail:

View File

@ -489,15 +489,7 @@ VGMSTREAM* init_vgmstream_nub_xma(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
{
uint8_t buf[0x100];
size_t bytes;
if (nus_codec == 0x04) {
bytes = ffmpeg_make_riff_xma2_from_xma2_chunk(buf,0x100, chunk_offset,chunk_size, data_size, sf);
} else {
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, chunk_offset,chunk_size, data_size, sf, 1);
}
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,data_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, data_size, chunk_offset, chunk_size);
if ( !vgmstream->codec_data ) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -103,8 +103,10 @@ static VGMSTREAM* init_vgmstream_opus(STREAMFILE* sf, meta_t meta_type, off_t of
vgmstream->layout_type = layout_none;
vgmstream->channel_layout = ffmpeg_get_channel_layout(vgmstream->codec_data);
if (vgmstream->num_samples == 0) {
if (vgmstream->num_samples <= 0) {
vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, sf) - skip;
if (num_samples < 0 && vgmstream->loop_end_sample > vgmstream->num_samples) /* special flag for weird cases */
vgmstream->loop_end_sample = vgmstream->num_samples;
}
}
#else
@ -293,18 +295,21 @@ VGMSTREAM* init_vgmstream_opus_shinen(STREAMFILE* sf) {
/* checks */
if (read_u32be(0x08,sf) != 0x01000080)
goto fail;
if ( !check_extensions(sf,"opus,lopus"))
if (!check_extensions(sf,"opus,lopus"))
goto fail;
offset = 0x08;
num_samples = 0;
loop_start = read_32bitLE(0x00,sf);
loop_end = read_32bitLE(0x04,sf); /* 0 if no loop */
loop_start = read_s32le(0x00,sf);
loop_end = read_s32le(0x04,sf); /* 0 if no loop */
/* tepaneca.opus has loop_end slightly bigger than samples, but doesn't seem an encoder delay thing since
* several tracks do full loops to 0 and sound ok. Mark with a special flag to allow this case. */
num_samples = -1;
if (loop_start > loop_end)
goto fail; /* just in case */
return init_vgmstream_opus(sf, meta_OPUS, offset, num_samples,loop_start,loop_end);
return init_vgmstream_opus(sf, meta_OPUS, offset, num_samples, loop_start, loop_end);
fail:
return NULL;
}

View File

@ -180,12 +180,8 @@ VGMSTREAM* init_vgmstream_p3d(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 0x786D6100: { /* "xma\0" (X360) */
uint8_t buf[0x100];
size_t bytes;
//TODO: some in Spider-Man 4 beta use 18ch but ffmpeg supports max 16ch XMA2
bytes = ffmpeg_make_riff_xma2_from_xma2_chunk(buf, sizeof(buf), xma2_offset, xma2_size, data_size, sf);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,data_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, data_size, xma2_offset, xma2_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -0,0 +1,66 @@
#include "meta.h"
#include "../coding/coding.h"
/* PASX - from Premium Agency games [SoulCalibur II HD (X360), Death By Cube (X360)] */
VGMSTREAM* init_vgmstream_pasx(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset, chunk_offset;
size_t data_size, chunk_size;
int loop_flag, channels, sample_rate;
int num_samples, loop_start_sample, loop_end_sample;
/* checks */
if (!is_id32be(0x00,sf, "PASX"))
goto fail;
/* .past: Soul Calibur II HD
* .sgb: Death By Cube */
if (!check_extensions(sf,"past,sgb"))
goto fail;
/* custom header with a "fmt " data chunk inside */
chunk_size = read_32bitBE(0x08,sf);
data_size = read_32bitBE(0x0c,sf);
chunk_offset = read_32bitBE(0x10,sf); /* 0x14: fmt offset end */
start_offset = read_32bitBE(0x18,sf);
channels = read_16bitBE(chunk_offset+0x02,sf);
sample_rate = read_32bitBE(chunk_offset+0x04,sf);
xma2_parse_fmt_chunk_extra(sf, chunk_offset, &loop_flag, &num_samples, &loop_start_sample, &loop_end_sample, 1);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start_sample;
vgmstream->loop_end_sample = loop_end_sample;
vgmstream->meta_type = meta_PASX;
#ifdef VGM_USE_FFMPEG
{
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, data_size, chunk_offset, chunk_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, sf, start_offset, data_size, chunk_offset, 1,1);
}
#else
goto fail;
#endif
/* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, sf, start_offset) )
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,68 +0,0 @@
#include "meta.h"
#include "../util.h"
/* CCC */
VGMSTREAM * init_vgmstream_ps2_ccc(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("ccc",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x01000000)
goto fail;
/* check file size */
if (read_32bitLE(0x0C,streamFile)+0x50 != get_streamfile_size(streamFile))
goto fail;
loop_flag = 0;
channel_count = 2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x50;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x04,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = (read_32bitLE(0x08,streamFile))/channel_count/0x10*28;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (read_32bitLE(0x08,streamFile))/channel_count/0x10*28;
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x2000;
vgmstream->meta_type = meta_PS2_CCC;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,74 +0,0 @@
#include "meta.h"
#include "../util.h"
/* CPS (from Eternal Sonata) */
VGMSTREAM * init_vgmstream_ps3_cps(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("cps",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x43505320) /* "CPS" */
goto fail;
loop_flag = read_32bitBE(0x18,streamFile);
channel_count = read_32bitBE(0x8,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = read_32bitBE(0x4,streamFile);
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x10,streamFile);
if (read_32bitBE(0x20,streamFile)==0x00000000){
vgmstream->coding_type = coding_PCM16BE;
vgmstream->num_samples = read_32bitBE(0xc,streamFile)/4;
vgmstream->interleave_block_size = 2;
}
else {
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = read_32bitBE(0xc,streamFile)*28/32;
vgmstream->interleave_block_size = 0x10;
}
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile)*28/32;
vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile)*28/32;
}
vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = meta_PS3_CPS;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -168,7 +168,7 @@ VGMSTREAM* init_vgmstream_psb(STREAMFILE* sf) {
break;
#ifdef VGM_USE_FFMPEG
case XWMA: { /* [Senxin Aleste (AC)] */
case XWMA: { /* Senxin Aleste (AC) */
vgmstream->codec_data = init_ffmpeg_xwma(sf, psb.stream_offset[0], psb.stream_size[0], psb.format, psb.channels, psb.sample_rate, psb.avg_bitrate, psb.block_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
@ -182,11 +182,7 @@ VGMSTREAM* init_vgmstream_psb(STREAMFILE* sf) {
}
case XMA2: { /* Sega Vintage Collection (X360) */
uint8_t buf[0x100];
size_t bytes;
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf, sizeof(buf), psb.fmt_offset, psb.fmt_size, psb.stream_size[0], sf, 1);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf, bytes, psb.stream_offset[0], psb.stream_size[0]);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, psb.stream_offset[0], psb.stream_size[0], psb.fmt_offset, psb.fmt_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -95,7 +95,7 @@ typedef struct {
int is_at9;
} riff_fmt_chunk;
static int read_fmt(int big_endian, STREAMFILE* sf, off_t offset, riff_fmt_chunk* fmt, int mwv) {
static int read_fmt(int big_endian, STREAMFILE* sf, off_t offset, riff_fmt_chunk* fmt) {
uint32_t (*read_u32)(off_t,STREAMFILE*) = big_endian ? read_u32be : read_u32le;
uint16_t (*read_u16)(off_t,STREAMFILE*) = big_endian ? read_u16be : read_u16le;
@ -227,7 +227,6 @@ static int read_fmt(int big_endian, STREAMFILE* sf, off_t offset, riff_fmt_chunk
break;
case 0x0555: /* Level-5 0x555 ADPCM (unofficial) */
if (!mwv) goto fail;
fmt->coding_type = coding_L5_555;
fmt->interleave = 0x12;
break;
@ -278,13 +277,6 @@ static int read_fmt(int big_endian, STREAMFILE* sf, off_t offset, riff_fmt_chunk
fmt->coding_type = coding_FFmpeg;
fmt->is_at3p = 1;
break;
#elif defined(VGM_USE_MAIATRAC3PLUS)
uint16_t bztmp = read_u16(offset+0x32,sf);
bztmp = (bztmp >> 8) | (bztmp << 8);
fmt->coding_type = coding_AT3plus;
fmt->block_size = (bztmp & 0x3FF) * 8 + 8; /* should match fmt->block_size */
fmt->is_at3p = 1;
break;
#else
goto fail;
#endif
@ -337,9 +329,8 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
int FormatChunkFound = 0, DataChunkFound = 0, JunkFound = 0;
int mwv = 0;
off_t mwv_pflt_offset = -1;
off_t mwv_ctrl_offset = -1;
off_t mwv_pflt_offset = 0;
off_t mwv_ctrl_offset = 0;
int ignore_riff_size = 0;
@ -347,6 +338,13 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
if (!is_id32be(0x00,sf,"RIFF"))
goto fail;
riff_size = read_u32le(0x04,sf);
if (!is_id32be(0x08,sf, "WAVE"))
goto fail;
file_size = get_streamfile_size(sf);
/* .lwav: to avoid hijacking .wav
* .xwav: fake for Xbox games (not needed anymore)
* .da: The Great Battle VI (PS1)
@ -379,24 +377,12 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
* .ogg/logg: Luftrausers (Vita)[ATRAC9]
* .p1d: Farming Simulator 15 (Vita)[ATRAC9]
* .xms: Ty the Tasmanian Tiger (Xbox)
* .mus: Burnout Legends/Dominator (PSP)
*/
if ( check_extensions(sf, "wav,lwav,xwav,da,dax,cd,med,snd,adx,adp,xss,xsew,adpcm,adw,wd,,sbv,wvx,str,at3,rws,aud,at9,ckd,saf,ima,nsa,pcm,xvag,ogg,logg,p1d,xms") ) {
;
}
else if ( check_extensions(sf, "mwv") ) {
mwv = 1;
}
else {
if (!check_extensions(sf, "wav,lwav,xwav,mwv,da,dax,cd,med,snd,adx,adp,xss,xsew,adpcm,adw,wd,,sbv,wvx,str,at3,rws,aud,at9,ckd,saf,ima,nsa,pcm,xvag,ogg,logg,p1d,xms,mus")) {
goto fail;
}
riff_size = read_u32le(0x04,sf);
if (!is_id32be(0x08,sf, "WAVE"))
goto fail;
file_size = get_streamfile_size(sf);
/* some games have wonky sizes, selectively fix to catch bad rips and new mutations */
if (file_size != riff_size + 0x08) {
uint16_t codec = read_u16le(0x14,sf);
@ -425,7 +411,7 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
else if (codec == 0xFFFE && riff_size + 0x08 + 0x18 == file_size)
riff_size += 0x18; /* [F1 2011 (Vita)] (adds a "pada" chunk but RIFF size wasn't updated) */
else if (mwv) {
else if (codec == 0x0555) {
int channels = read_u16le(0x16, sf); /* [Dragon Quest VIII (PS2), Rogue Galaxy (PS2)] */
size_t file_size_fixed = riff_size + 0x08 + 0x04 * (channels - 1);
@ -486,7 +472,7 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
if (FormatChunkFound) goto fail; /* only one per file */
FormatChunkFound = 1;
if (!read_fmt(0, sf, current_chunk, &fmt, mwv))
if (!read_fmt(0, sf, current_chunk, &fmt))
goto fail;
/* some Dreamcast/Naomi games again [Headhunter (DC), Bomber hehhe (DC), Rayman 2 (DC)] */
@ -574,12 +560,10 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
goto fail; /* parsed elsewhere */
case 0x70666c74: /* "pflt" (.mwv extension) */
if (!mwv) break; /* ignore if not in an mwv */
mwv_pflt_offset = current_chunk; /* predictor filters */
break;
case 0x6374726c: /* "ctrl" (.mwv extension) */
if (!mwv) break;
loop_flag = read_32bitLE(current_chunk+0x08, sf);
mwv_ctrl_offset = current_chunk;
break;
@ -688,9 +672,6 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case coding_FFmpeg:
#endif
#ifdef VGM_USE_MAIATRAC3PLUS
case coding_AT3plus:
#endif
#ifdef VGM_USE_ATRAC9
case coding_ATRAC9:
#endif
@ -725,7 +706,6 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
break;
case coding_L5_555:
if (!mwv) goto fail;
vgmstream->num_samples = data_size / 0x12 / fmt.channels * 32;
/* coefs */
@ -735,7 +715,7 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
int filter_count = read_32bitLE(mwv_pflt_offset+0x0c, sf);
if (filter_count > 0x20) goto fail;
if (mwv_pflt_offset == -1 ||
if (!mwv_pflt_offset ||
read_32bitLE(mwv_pflt_offset+0x08, sf) != filter_order ||
read_32bitLE(mwv_pflt_offset+0x04, sf) < 8 + filter_count * 4 * filter_order)
goto fail;
@ -799,17 +779,6 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
break;
}
#endif
#ifdef VGM_USE_MAIATRAC3PLUS
case coding_AT3plus: {
vgmstream->codec_data = init_at3plus();
/* get rough total samples but favor fact_samples if available (skip isn't correctly handled for now) */
vgmstream->num_samples = atrac3plus_bytes_to_samples(data_size, fmt.block_size);
if (fact_sample_count > 0 && fact_sample_count + fact_sample_skip < vgmstream->num_samples)
vgmstream->num_samples = fact_sample_count + fact_sample_skip;
break;
}
#endif
#ifdef VGM_USE_ATRAC9
case coding_ATRAC9: {
atrac9_config cfg = {0};
@ -908,9 +877,10 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
vgmstream->loop_end_sample = loop_end_wsmp;
vgmstream->meta_type = meta_RIFF_WAVE_wsmp;
}
else if (mwv && mwv_ctrl_offset != -1) {
vgmstream->loop_start_sample = read_32bitLE(mwv_ctrl_offset+12, sf);
else if (fmt.coding_type == coding_L5_555 && mwv_ctrl_offset) {
vgmstream->loop_start_sample = read_s32le(mwv_ctrl_offset + 0x0c, sf);
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->meta_type = meta_RIFF_WAVE_MWV;
}
else if (loop_start_cue != -1) {
vgmstream->loop_start_sample = loop_start_cue;
@ -927,9 +897,6 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
}
}
}
if (mwv) {
vgmstream->meta_type = meta_RIFF_WAVE_MWV;
}
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
@ -1105,7 +1072,7 @@ VGMSTREAM* init_vgmstream_rifx(STREAMFILE* sf) {
if (FormatChunkFound) goto fail;
FormatChunkFound = 1;
if (!read_fmt(1, sf, current_chunk, &fmt, 0))
if (!read_fmt(1, sf, current_chunk, &fmt))
goto fail;
break;

View File

@ -13,9 +13,9 @@ VGMSTREAM* init_vgmstream_rsd(STREAMFILE* sf) {
/* checks */
if (!check_extensions(sf,"rsd,rsp"))
if ((read_u32be(0x00,sf) & 0xFFFFFF00) != get_id32be("RSD\00"))
goto fail;
if ((read_u32be(0x00,sf) & 0xFFFFFF00) != 0x52534400) /* "RSD\00" */
if (!check_extensions(sf,"rsd,rsp"))
goto fail;
loop_flag = 0;
@ -168,40 +168,34 @@ VGMSTREAM* init_vgmstream_rsd(STREAMFILE* sf) {
}
case 0x584D4120: { /* "XMA " [Crash of the Titans (X360)-v1, Crash: Mind over Mutant (X360)-v2] */
uint8_t buf[0x100];
size_t bytes, xma_size, block_size, block_count;
int xma_version;
uint32_t chunk_size = read_32bitBE(0x800, sf);
uint32_t seek_size = read_32bitBE(0x804, sf);
uint32_t stream_size = read_32bitBE(0x808, sf);
uint32_t chunk_offset = 0x80c;
int old_xma2_version = read_u8(chunk_offset + 0x00, sf);
start_offset = chunk_offset + chunk_size + seek_size;
/* skip mini header */
start_offset = 0x800 + read_32bitBE(0x800, sf) + read_32bitBE(0x804, sf) + 0xc; /* assumed, seek table always at 0x800 */
xma_size = read_32bitBE(0x808, sf);
xma_version = read_u8(0x80C, sf);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, stream_size, chunk_offset, chunk_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
switch (xma_version) {
/* read PCM samples rather than full samples (dev trickery?) */
switch (old_xma2_version) {
case 0x03:
vgmstream->sample_rate = read_32bitBE(0x818, sf);
vgmstream->num_samples = read_32bitBE(0x824, sf);
block_count = read_32bitBE(0x828, sf);
block_size = 0x10000;
vgmstream->sample_rate = read_32bitBE(chunk_offset + 0x0c, sf);
vgmstream->num_samples = read_32bitBE(chunk_offset + 0x18, sf);
break;
case 0x04:
vgmstream->num_samples = read_32bitBE(0x814, sf);
vgmstream->sample_rate = read_32bitBE(0x818, sf);
block_count = read_32bitBE(0x830, sf);
block_size = 0x10000;
vgmstream->num_samples = read_32bitBE(chunk_offset + 0x08, sf);
vgmstream->sample_rate = read_32bitBE(chunk_offset + 0x0c, sf);
break;
default:
goto fail;
}
bytes = ffmpeg_make_riff_xma2(buf,sizeof(buf), vgmstream->num_samples, xma_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf, bytes, start_offset, xma_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
/* for some reason (dev trickery?) .rsd don't set skip in the bitstream, though they should */
/* for some reason (dev trickery?) .rsd don't set skips in the bitstream, though they should */
//xma_fix_raw_samples(vgmstream, sf, start_offset,xma_size, 0, 0,0);
ffmpeg_set_skip_samples(vgmstream->codec_data, 512+64);
break;
@ -218,7 +212,6 @@ VGMSTREAM* init_vgmstream_rsd(STREAMFILE* sf) {
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;

View File

@ -106,6 +106,12 @@ VGMSTREAM* init_vgmstream_rwsd(STREAMFILE* sf) {
stream_size = read_32bitBE(wave_offset + 0x50,sf);
/* this meta is a hack as WSD is just note info, and data offsets are elsewhere in the brsar,
* while this assumes whatever data follows RWSD must belong to it (common but fails in Wii Sports),
* detect data excess and reject (probably should use brawlbox's info offsets) */
if (stream_size * channels + 0x10000 < get_streamfile_size(sf) - start_offset)
goto fail;
/* open the file for reading by each channel */
{
int i;

View File

@ -191,52 +191,3 @@ fail:
close_vgmstream(vgmstream);
return NULL;
}
/* .RXW - legacy fake ext/header for poorly split XWH+XWB files generated by old tools (incorrect header/chunk sizes) */
VGMSTREAM* init_vgmstream_rxws_badrip(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
int loop_flag=0, channels;
off_t start_offset;
/* check extension, case insensitive */
if (!check_extensions(sf,"rxw"))
goto fail;
/* check RXWS/FORM Header */
if (!((read_32bitBE(0x00,sf) == 0x52585753) &&
(read_32bitBE(0x10,sf) == 0x464F524D)))
goto fail;
loop_flag = (read_u32le(0x3C,sf)!=0xFFFFFFFF);
channels=2; /* Always stereo files */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(0x2E,sf);
vgmstream->num_samples = (read_32bitLE(0x38,sf)*28/16)/2;
/* Get loop point values */
if(vgmstream->loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x3C,sf)/16*14;
vgmstream->loop_end_sample = read_32bitLE(0x38,sf)/16*14;
}
vgmstream->interleave_block_size = read_32bitLE(0x1c,sf)+0x10;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = meta_RXWS;
start_offset = 0x40;
/* open the file for reading */
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -5,7 +5,7 @@
VGMSTREAM * init_vgmstream_s3v(STREAMFILE *sf) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int32_t channel_count, loop_flag;
int32_t channel_count, loop_flag;
size_t data_size;
/* checks */
@ -18,7 +18,7 @@ VGMSTREAM * init_vgmstream_s3v(STREAMFILE *sf) {
/* No discernible loop_flag so we'll just use signatures.
Might have to update on a per game basis. */
switch (read_32bitBE(0x14, sf)) {
switch (read_32bitBE(0x14, sf)) {
case 0x82FA0000: // SOUND VOLTEX EXCEED GEAR ver5 Theme BGM
case 0x1BFD0000: // SOUND VOLTEX EXCEED GEAR ver6 Theme BGM
case 0x9AFD0000: // SOUND VOLTEX Custom song selection BGM TypeA

View File

@ -0,0 +1,359 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
/* SDRH - banks for newer feelplus-related ("FeelEngine") games [Mindjack (PS3/X360), Moon Diver (PS3/X360)] */
VGMSTREAM* init_vgmstream_sdrh_new(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
uint32_t start_offset, stream_size;
int loop_flag = 0, channels, codec, sample_rate, seek_count;
int32_t num_samples, loop_start, loop_end;
int total_subsongs, target_subsong = sf->stream_index;
/* checks */
if (!is_id32le(0x00,sf, "SDRH")) /* LE */
goto fail;
if (!check_extensions(sf, "xse"))
goto fail;
/* similar to older version but BE and a bit less complex */
/* 0x04: version/config?
* 0x08: data size
* 0x30: file name in a custom 40-char (RADIX style) encoding
* others: ?
*/
/* parse section */
{
uint32_t offset, base_size, stream_offset, data_size = 0, entry_size = 0;
int i;
int tables = read_u16be(0x1C,sf);
int entries;
offset = 0;
/* read sections: FE=cues? (same in platforms), WV=header position + sample rate?, FT=? (same in platforms), XW=waves */
for (i = 0; i < tables; i++) {
uint16_t id = read_u16be(0x40 + 0x10 * i + 0x00,sf);
/* 0x02: offset in 0x40s */
/* 0x04: section size */
/* 0x08: always 1 */
/* 0x0c: null */
if (id == 0x5857) { /* "XW" */
offset += read_u16be(0x40 + 0x10 * i + 0x02,sf) * 0x40;
break;
}
}
/* section header (other sections have a similar header) */
/* 0x00: section size (including data) */
base_size = read_u16be(offset + 0x04,sf);
entries = read_u16be(offset + 0x06,sf);
/* 0x08: null */
start_offset = read_u32be(offset + 0x0c,sf) + offset; /* size including padding up to start */
offset += base_size;
total_subsongs = entries;
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
/* find stream header (entries can be variable-sized) */
for (i = 0; i < entries; i++) {
entry_size = read_u16be(offset + 0x04,sf) * 0x10;
if (i + 1 == target_subsong)
break;
offset += entry_size;
}
/* parse target header (similar to xwav) */
data_size = read_u32be(offset + 0x00,sf) - entry_size;
/* 0x00: data/entry size */
/* 0x04: entry size */
codec = read_u8(offset + 0x06,sf); /* assumed */
loop_flag = read_u8(offset + 0x07,sf); /* assumed */
/* 0x08: bps? flags? */
channels = read_u8(offset + 0x09,sf);
seek_count = read_u16be(offset + 0x0a,sf);
num_samples = read_u32be(offset + 0x0c,sf);
sample_rate = read_u32be(offset + 0x10,sf);
loop_start = read_u32be(offset + 0x14,sf);
loop_end = read_u32be(offset + 0x18,sf);
/* 0x1c: flags? */
stream_offset = read_u32be(offset + 0x20,sf);
/* Mindjack uses full offsets here (aligned to 0x800), while Moon Diver points to a sub-offset
* (offsets also aren't ordered) */
if ((stream_offset & 0x000007FF) != 0) {
stream_offset = read_u16be(offset + stream_offset, sf) * 0x800;
//TODO some files that loop have wrong size/num_samples? (ex.MJ system.xse #23 #138)
}
/* other values change per game (seek table, etc) */
start_offset += stream_offset;
stream_size = data_size;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_SDRH;
vgmstream->num_samples = num_samples;
vgmstream->sample_rate = sample_rate;
vgmstream->stream_size = stream_size;
vgmstream->num_streams = total_subsongs;
switch(codec) {
case 2: /* Mindjack (PS3), Moon Diver (PS3) */
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10;
/* seen in a few Mindjack files */
if (loop_end > num_samples && loop_end - 8 <= num_samples)
loop_end = num_samples;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
break;
#ifdef VGM_USE_FFMPEG
case 1: { /* Mindjack (X360), Moon Diver (X360) */
int block_size = 0x10000; /* XWAV new default */
int block_count = seek_count;
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, start_offset, stream_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, block_count);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
//TODO fix loops/samples vs ATRAC3
/* may be only applying end_skip to num_samples? */
xma_fix_raw_samples(vgmstream, sf, start_offset, stream_size, 0, 0,0);
break;
}
case 7: { /* Mindjack (PS3) */
int block_align, encoder_delay;
block_align = 0x98 * vgmstream->channels;
encoder_delay = 1024 + 69*2; /* observed default, but seems files run out of space */
vgmstream->codec_data = init_ffmpeg_atrac3_raw(sf, start_offset, stream_size, vgmstream->num_samples, vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
/* set offset samples (offset 0 jumps to sample 0 > pre-applied delay, and offset end loops after sample end > adjusted delay) */
vgmstream->loop_start_sample = atrac3_bytes_to_samples(loop_start, block_align); //- encoder_delay
vgmstream->loop_end_sample = atrac3_bytes_to_samples(loop_end, block_align) - encoder_delay;
break;
}
#endif
default:
goto fail;
}
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
/* SDRH - banks for older feelplus-related games [Lost Odyssey (X360), Lost Odyssey Demo (X360)] */
VGMSTREAM* init_vgmstream_sdrh_old(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
uint32_t start_offset, stream_size;
int loop_flag = 0, channels = 0, codec, sample_rate, seek_count;
int32_t num_samples, loop_start, loop_end;
int total_subsongs, target_subsong = sf->stream_index;
/* checks */
if (!is_id32be(0x00,sf, "SDRH"))
goto fail;
/* .xse: actual extension (LO demo) */
if (!check_extensions(sf, "xse"))
goto fail;
/* similar to older version but LE and a bit more complex */
/* 0x04: version/config?
* 0x08: data size
* 0x30: file name in a custom 40-char (RADIX style) encoding
* others: ? (change in old/new)
*/
/* parse section */
{
uint32_t offset, base_size, stream_offset, data_size = 0, entry_size = 0;
int i;
int tables = read_u8(0x15,sf);
int entries;
offset = 0x40;
/* read sections (FE=cues?, WV=mini-headers + XW offset, FT=?, FQ=?, XW=waves) */
for (i = 0; i < tables; i++) {
uint16_t id = read_u16be(0x40 + 0x08 * i + 0x00,sf);
/* 0x02: null? */
/* 0x04: offset from table start */
if (id == 0x5857) { /* "XW" */
offset += read_u32le(0x40 + 0x08 * i + 0x04,sf);
break;
}
}
/* section header (other sections have a similar header) */
/* 0x00: section size (including data) */
base_size = read_u16le(offset + 0x04,sf);
/* 0x06: ? */
entries = read_u16le(offset + 0x08,sf);
start_offset = read_u32le(offset + 0x0c,sf) + offset; /* size including padding up to start */
offset += base_size;
total_subsongs = entries;
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
/* find stream header */
stream_offset = 0;
for (i = 0; i < entries; i++) {
data_size = read_u32le(offset + 0x00,sf);
entry_size = read_u16le(offset + 0x04,sf) * 0x10;
data_size -= entry_size;
if (i + 1 == target_subsong)
break;
offset += entry_size;
stream_offset += data_size; /* no offset */
}
/* parse target header (similar to xwav) */
/* 0x00: data size + entry size */
/* 0x04: entry size */
codec = read_u8(offset + 0x06,sf); /* assumed */
/* 0x07: flag? */
/* 0x08: bps? */
/* 0x09: codec? */
/* 0x0a: null (seek size?) */
num_samples = read_u32le(offset + 0x0c,sf); /* XMA1: loop start/end info */
seek_count = read_u16le(offset + 0x10,sf); /* XMA1: loop start/end bytes? */
sample_rate = read_u16le(offset + 0x14,sf);
if (entry_size == 0x20) {
channels = read_u8(offset + 0x17,sf);
}
loop_start = 0; //read_u32le(offset + 0x18,sf); /* ? */
loop_end = 0; //read_u32le(offset + 0x1c,sf); /* ? */
if (entry_size >= 0x30) {
/* 0x20: null */
/* 0x24: ? */
/* 0x26: channel layout */
channels = read_u8(offset + 0x27,sf);
/* 0x28: ? */
/* 0x2c: null? */
}
loop_flag = loop_end > 0;
start_offset += stream_offset;
stream_size = data_size;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_SDRH;
vgmstream->num_samples = num_samples;
vgmstream->sample_rate = sample_rate;
vgmstream->stream_size = stream_size;
vgmstream->num_streams = total_subsongs;
switch(codec) {
#ifdef VGM_USE_FFMPEG
case 1: { /* Lost Odyssey Demo (X360) */
vgmstream->codec_data = init_ffmpeg_xma1_raw(sf, start_offset, stream_size, vgmstream->channels, vgmstream->sample_rate, 0);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
{
ms_sample_data msd = {0};
msd.xma_version = 1;
msd.channels = channels;
msd.data_offset = start_offset;
msd.data_size = stream_size;
msd.loop_flag = loop_flag;
msd.loop_start_b= 0; //loop_start_b;
msd.loop_end_b = 0; //loop_end_b;
msd.loop_start_subframe = 0; //loop_subframe & 0xF; /* lower 4b: subframe where the loop starts, 0..4 */
msd.loop_end_subframe = 0; //loop_subframe >> 4; /* upper 4b: subframe where the loop ends, 0..3 */
msd.chunk_offset = 0;
xma_get_samples(&msd, sf);
vgmstream->num_samples = msd.num_samples;
//loop_start_sample = msd.loop_start_sample;
//loop_end_sample = msd.loop_end_sample;
}
xma_fix_raw_samples(vgmstream, sf, start_offset, stream_size, 0, 0, 1);
break;
}
case 4: { /* Lost Odyssey (X360) */
int block_size = 0x8000; /* XWAV old default */
int block_count = seek_count;
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, start_offset, stream_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, block_count);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
xma_fix_raw_samples(vgmstream, sf, start_offset, stream_size, 0, 0, 1);
break;
}
#endif
default:
goto fail;
}
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -2,8 +2,8 @@
#include "../coding/coding.h"
/* SEG - from Stormfront games [Eragon (multi), Forgotten Realms: Demon Stone (multi) */
VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_seg(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
size_t data_size;
@ -12,24 +12,24 @@ VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) {
/* checks */
if (!check_extensions(streamFile, "seg"))
if (!is_id32be(0x00,sf, "seg\0"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x73656700) /* "seg\0" */
if (!check_extensions(sf, "seg"))
goto fail;
codec = read_32bitBE(0x04,streamFile);
codec = read_32bitBE(0x04,sf);
/* 0x08: version? (2: Eragon, Spiderwick Chronicles Wii / 3: Spiderwick Chronicles X360 / 4: Spiderwick Chronicles PC) */
if (guess_endianness32bit(0x08,streamFile)) {
if (guess_endianness32bit(0x08,sf)) {
read_32bit = read_32bitBE;
} else {
read_32bit = read_32bitLE;
}
/* 0x0c: file size */
data_size = read_32bit(0x10, streamFile); /* including interleave padding */
data_size = read_32bit(0x10, sf); /* including interleave padding */
/* 0x14: null */
loop_flag = read_32bit(0x20,streamFile); /* rare */
channel_count = read_32bit(0x24,streamFile);
loop_flag = read_32bit(0x20,sf); /* rare */
channel_count = read_32bit(0x24,sf);
/* 0x28: extradata 1 entries (0x08 per entry, unknown) */
/* 0x2c: extradata 1 offset */
/* 0x30: extradata 2 entries (0x10 or 0x14 per entry, seek/hist table?) */
@ -43,13 +43,13 @@ VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) {
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_SEG;
vgmstream->sample_rate = read_32bit(0x18,streamFile);
vgmstream->num_samples = read_32bit(0x1c,streamFile);
vgmstream->sample_rate = read_32bit(0x18,sf);
vgmstream->num_samples = read_32bit(0x1c,sf);
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
}
read_string(vgmstream->stream_name,0x20+1, 0x38,streamFile);
read_string(vgmstream->stream_name,0x20+1, 0x38,sf);
switch(codec) {
case 0x70733200: /* "ps2\0" */
@ -71,8 +71,8 @@ VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) {
vgmstream->interleave_first_block_size = vgmstream->interleave_block_size - vgmstream->interleave_first_skip;
/* standard dsp header at start_offset */
dsp_read_coefs_be(vgmstream, streamFile, start_offset+0x1c, vgmstream->interleave_block_size);
dsp_read_hist_be(vgmstream, streamFile, start_offset+0x40, vgmstream->interleave_block_size);
dsp_read_coefs_be(vgmstream, sf, start_offset+0x1c, vgmstream->interleave_block_size);
dsp_read_hist_be(vgmstream, sf, start_offset+0x40, vgmstream->interleave_block_size);
start_offset += vgmstream->interleave_first_skip;
break;
@ -84,19 +84,14 @@ VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) {
#ifdef VGM_USE_FFMPEG
case 0x78623300: { /* "xb3\0" */
uint8_t buf[0x100];
int bytes, block_size, block_count;
int block_size = 0x4000;
block_size = 0x4000;
block_count = data_size / block_size + (data_size % block_size ? 1 : 0);
bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, start_offset, data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, 0);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, start_offset,data_size, 0, 0,0); /* samples are ok */
xma_fix_raw_samples(vgmstream, sf, start_offset,data_size, 0, 0,0); /* samples are ok */
break;
}
#endif
@ -105,10 +100,9 @@ VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) {
goto fail;
}
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;

View File

@ -43,6 +43,9 @@ VGMSTREAM* init_vgmstream_smk(STREAMFILE *sf) {
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
// wrong decoding otherwise
ffmpeg_set_force_seek(vgmstream->codec_data);
#else
goto fail;
#endif

View File

@ -11,14 +11,16 @@ VGMSTREAM* init_vgmstream_smp(STREAMFILE* sf) {
/* checks */
if (!check_extensions(sf, "smp"))
goto fail;
version = read_u32le(0x00,sf);
if (version != 0x05 && /* Ghostbusters (PS2), Mushroom Men (Wii) */
version != 0x06 && /* Ghostbusters (PS3/X360/PC) */
version != 0x07 && /* Ghostbusters (PSP) */
version != 0x08) /* Chandragupta (PS2/PSP), Street Cricket Champions 1/2 (PSP), Guilty Party (Wii) */
version != 0x08) /* Def Jam Rapstar (X360), Chandragupta (PS2/PSP), Street Cricket Champions 1/2 (PSP), Guilty Party (Wii) */
goto fail;
/* .smp: common
* .snb: Def Jam Rapstar (X360)-few files */
if (!check_extensions(sf, "smp,snb"))
goto fail;
/* 0x04~14: guid? */
@ -28,6 +30,9 @@ VGMSTREAM* init_vgmstream_smp(STREAMFILE* sf) {
start_offset = read_u32le(0x1c,sf);
data_size = read_u32le(0x20,sf);
codec = read_u32le(0x24,sf);
if (start_offset + data_size != get_streamfile_size(sf))
goto fail;
/* smaller header found in Guilty Party (Wii) */
if (version == 0x08 && start_offset == 0x80) {
channels = read_u8(0x28,sf);
@ -102,17 +107,14 @@ VGMSTREAM* init_vgmstream_smp(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 0x07: {
uint8_t buf[0x100];
int bytes, block_size, block_count;
int block_size, block_count;
if (bps != 16) goto fail;
/* 0x34(0x28): XMA config/table? */
/* 0x34(0x28): XMA config/table? (unknown format) */
block_size = read_u16le(0x3e,sf);
block_count = read_u16le(0x54,sf);
block_size = 0x8000; /* assumed, @0x3e(2)? */
block_count = data_size / block_size + (data_size % block_size ? 1 : 0); /* @0x54(2)? */
bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,data_size);
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, start_offset, data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, block_count);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
@ -130,7 +132,6 @@ VGMSTREAM* init_vgmstream_smp(STREAMFILE* sf) {
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;

View File

@ -2,66 +2,66 @@
#include "../coding/coding.h"
/* SPSD - Naomi (arcade) and early Dreamcast streams [Guilty Gear X (Naomi), Crazy Taxi (Naomi), Virtua Tennis 2 (Naomi)] */
VGMSTREAM * init_vgmstream_naomi_spsd(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_spsd(STREAMFILE *sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
size_t data_size;
int loop_flag, channel_count, codec, flags, index;
int loop_flag, channels, codec, flags, index;
/* checks */
if (!is_id32be(0x00,sf, "SPSD"))
goto fail;
/* .str: actual extension, rare [Shenmue (DC)]
* .spsd: header id */
if (!check_extensions(streamFile, "str,spsd"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x53505344) /* "SPSD" */
* .spsd: header id (maybe real ext is .PSD, similar to "SMLT" > .MLT) */
if (!check_extensions(sf, "str,spsd"))
goto fail;
if (read_32bitBE(0x04,streamFile) != 0x01010004 && /* standard version */
read_32bitBE(0x04,streamFile) != 0x00010004) /* uncommon version [Crazy Taxi (Naomi)] */
if (read_32bitBE(0x04,sf) != 0x01010004 && /* standard version */
read_32bitBE(0x04,sf) != 0x00010004) /* uncommon version [Crazy Taxi (Naomi)] */
goto fail;
codec = read_8bit(0x08,streamFile);
flags = read_8bit(0x09,streamFile);
index = read_16bitLE(0x0a,streamFile);
data_size = read_32bitLE(0x0c,streamFile);
codec = read_8bit(0x08,sf);
flags = read_8bit(0x09,sf);
index = read_16bitLE(0x0a,sf);
data_size = read_32bitLE(0x0c,sf);
//if (data_size + start_offset != get_streamfile_size(streamFile))
// goto fail; /* some rips out there have incorrect padding */
//todo with 0x80 seems 0x2c is a loop_start_sample but must be adjusted to +1 block? (uncommon flag though)
loop_flag = (flags & 0x80);
channel_count = ((flags & 0x01) || (flags & 0x02)) ? 2 : 1; /* 0x02 is rare but looks normal (Virtua Tennis 2) */
channels = ((flags & 0x01) || (flags & 0x02)) ? 2 : 1; /* 0x02 is rare but looks normal (Virtua Tennis 2) */
start_offset = 0x40;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = (uint16_t)read_16bitLE(0x2A,streamFile);
vgmstream->sample_rate = (uint16_t)read_16bitLE(0x2A,sf);
vgmstream->meta_type = meta_NAOMI_SPSD;
vgmstream->meta_type = meta_SPSD;
switch (codec) {
case 0x00: /* [Virtua Tennis 2 (Naomi), Club Kart - European Session (Naomi)] */
case 0x00: /* [Virtua Tennis 2 (Naomi), Club Kart: European Session (Naomi)] */
vgmstream->coding_type = coding_PCM16LE;
vgmstream->num_samples = pcm_bytes_to_samples(data_size,channel_count,16);
vgmstream->loop_start_sample = read_32bitLE(0x2c,streamFile) + pcm_bytes_to_samples(0x2000*channel_count,channel_count,16);
vgmstream->num_samples = pcm_bytes_to_samples(data_size,channels,16);
vgmstream->loop_start_sample = read_32bitLE(0x2c,sf) + pcm_bytes_to_samples(0x2000*channels,channels,16);
vgmstream->loop_end_sample = vgmstream->num_samples;
break;
case 0x01: /* [Virtua Tennis 2 (Naomi)] */
vgmstream->coding_type = coding_PCM8;
vgmstream->num_samples = pcm_bytes_to_samples(data_size,channel_count,8);
vgmstream->loop_start_sample = read_32bitLE(0x2c,streamFile) + pcm_bytes_to_samples(0x2000*channel_count,channel_count,8);
vgmstream->num_samples = pcm_bytes_to_samples(data_size,channels,8);
vgmstream->loop_start_sample = read_32bitLE(0x2c,sf) + pcm_bytes_to_samples(0x2000*channels,channels,8);
vgmstream->loop_end_sample = vgmstream->num_samples;
break;
case 0x03: /* standard */
vgmstream->coding_type = coding_AICA_int;
vgmstream->num_samples = yamaha_bytes_to_samples(data_size,channel_count);
vgmstream->loop_start_sample = /*read_32bitLE(0x2c,streamFile) +*/ yamaha_bytes_to_samples(0x2000*channel_count,channel_count);
vgmstream->num_samples = yamaha_bytes_to_samples(data_size,channels);
vgmstream->loop_start_sample = /*read_32bitLE(0x2c,streamFile) +*/ yamaha_bytes_to_samples(0x2000*channels,channels);
vgmstream->loop_end_sample = vgmstream->num_samples;
break;
@ -72,7 +72,7 @@ VGMSTREAM * init_vgmstream_naomi_spsd(STREAMFILE *streamFile) {
/* interleave index, maybe */
switch(index) {
case 0x0000:
if (channel_count != 1) goto fail;
if (channels != 1) goto fail;
vgmstream->layout_type = layout_none;
break;
@ -85,7 +85,7 @@ VGMSTREAM * init_vgmstream_naomi_spsd(STREAMFILE *streamFile) {
case 0x00ff:
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = data_size / channel_count;
vgmstream->interleave_block_size = data_size / channels;
break;
default:
@ -97,13 +97,13 @@ VGMSTREAM * init_vgmstream_naomi_spsd(STREAMFILE *streamFile) {
* at 0x30(4*ch) is some config per channel but doesn't seem to affect ADPCM (found with PCM too) */
{
int i;
for (i = 0; i < channel_count; i++) {
for (i = 0; i < channels; i++) {
vgmstream->ch[i].adpcm_step_index = 0x7f;
}
}
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;

View File

@ -310,14 +310,10 @@ VGMSTREAM* init_vgmstream_sqex_scd(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 0x0B: { /* XMA2 [Final Fantasy (X360), Lightning Returns (X360) sfx, Kingdom Hearts 2.8 (X1)] */
uint8_t buf[0x100];
int32_t bytes;
/* extradata:
* 0x00: fmt0x166 header (BE X360, LE XBone)
* 0x34: seek table */
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, extradata_offset,0x34, stream_size, sf, big_endian);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf, bytes, start_offset, stream_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, stream_size, extradata_offset, 0x34);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -10,13 +10,14 @@ VGMSTREAM* init_vgmstream_ster(STREAMFILE* sf) {
/* checks */
if (!is_id32be(0x00,sf, "STER"))
goto fail;
/* .ster: header id (no apparent names/extensions)
* .sfs: generic bigfile extension (to be removed?)*/
if (!check_extensions(sf, "ster,sfs"))
goto fail;
if (!is_id32be(0x00,sf, "STER"))
goto fail;
channel_size = read_u32le(0x04, sf);
loop_start = read_u32le(0x08, sf); /* absolute (ex. offset 0x50 for full loops) */
/* 0x0c: data size BE */
@ -28,7 +29,7 @@ VGMSTREAM* init_vgmstream_ster(STREAMFILE* sf) {
start_offset = 0x30;
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;

View File

@ -160,16 +160,10 @@ VGMSTREAM* init_vgmstream_str_wav(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case XMA2: {
uint8_t buf[0x100];
size_t stream_size;
size_t bytes, block_size, block_count;
uint32_t stream_size = get_streamfile_size(sf);
int block_size = 0x10000;
stream_size = get_streamfile_size(sf);
block_size = 0x10000;
block_count = stream_size / block_size; /* not accurate? */
bytes = ffmpeg_make_riff_xma2(buf,0x100, strwav.num_samples, stream_size, strwav.channels, strwav.sample_rate, block_count, block_size);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, 0x00,stream_size);
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, 0x00, stream_size, strwav.num_samples, strwav.channels, strwav.sample_rate, block_size, 0);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -44,6 +44,8 @@ typedef enum {
ASF = 30, /* Argonaut ASF 4-bit ADPCM */
EAXA = 31, /* Electronic Arts EA-XA 4-bit ADPCM v1 */
OKI4S = 32, /* OKI ADPCM with 16-bit output (unlike OKI/VOX/Dialogic ADPCM's 12-bit) */
PCM24LE = 33, /* 24-bit Little Endian PCM */
PCM24BE = 34, /* 24-bit Big Endian PCM */
XA,
XA_EA,
CP_YM,
@ -226,6 +228,8 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
case PSX_bf:
case HEVAG: interleave = 0x10; break;
case NGC_DSP: interleave = 0x08; break;
case PCM24LE: interleave = 0x03; break;
case PCM24BE: interleave = 0x03; break;
case PCM16LE:
case PCM16BE: interleave = 0x02; break;
case PCM8:
@ -246,6 +250,8 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
case HEVAG: coding = coding_HEVAG; break;
case XBOX: coding = coding_XBOX_IMA; break;
case NGC_DTK: coding = coding_NGC_DTK; break;
case PCM24LE: coding = coding_PCM24LE; break;
case PCM24BE: coding = coding_PCM24BE; break;
case PCM16LE: coding = coding_PCM16LE; break;
case PCM16BE: coding = coding_PCM16BE; break;
case PCM8: coding = coding_PCM8; break;
@ -318,6 +324,8 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
case coding_PCM8_U_int:
vgmstream->layout_type = layout_none;
break;
case coding_PCM24LE:
case coding_PCM24BE:
case coding_PCM16LE:
case coding_PCM16BE:
case coding_PCM8:
@ -550,47 +558,35 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
ffmpeg_data = init_ffmpeg_aac(txth.sf_body, txth.start_offset, txth.data_size, 0);
if (!ffmpeg_data) goto fail;
}
else if (txth.codec == ATRAC3) {
int block_align, encoder_delay;
block_align = txth.interleave;
encoder_delay = txth.skip_samples;
ffmpeg_data = init_ffmpeg_atrac3_raw(txth.sf_body, txth.start_offset,txth.data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
if (!ffmpeg_data) goto fail;
}
else if (txth.codec == ATRAC3PLUS) {
int block_size = txth.interleave;
ffmpeg_data = init_ffmpeg_atrac3plus_raw(txth.sf_body, txth.start_offset, txth.data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, txth.skip_samples);
if (!ffmpeg_data) goto fail;
}
else if (txth.codec == XMA1) {
int xma_stream_mode = txth.codec_mode == 1 ? 1 : 0;
ffmpeg_data = init_ffmpeg_xma1_raw(txth.sf_body, txth.start_offset, txth.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
if (!ffmpeg_data) goto fail;
}
else if (txth.codec == XMA2) {
int block_size = txth.interleave;
ffmpeg_data = init_ffmpeg_xma2_raw(sf, txth.start_offset, txth.data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, 0);
if (!ffmpeg_data) goto fail;
}
else {
/* fake header FFmpeg */
uint8_t buf[0x100];
int32_t bytes;
if (txth.codec == ATRAC3) {
int block_align, encoder_delay;
block_align = txth.interleave;
encoder_delay = txth.skip_samples;
ffmpeg_data = init_ffmpeg_atrac3_raw(txth.sf_body, txth.start_offset,txth.data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
if (!ffmpeg_data) goto fail;
}
else if (txth.codec == ATRAC3PLUS) {
int block_size = txth.interleave;
bytes = ffmpeg_make_riff_atrac3plus(buf, sizeof(buf), vgmstream->num_samples, txth.data_size, vgmstream->channels, vgmstream->sample_rate, block_size, txth.skip_samples);
ffmpeg_data = init_ffmpeg_header_offset(txth.sf_body, buf,bytes, txth.start_offset,txth.data_size);
if ( !ffmpeg_data ) goto fail;
}
else if (txth.codec == XMA1) {
int xma_stream_mode = txth.codec_mode == 1 ? 1 : 0;
bytes = ffmpeg_make_riff_xma1(buf, sizeof(buf), vgmstream->num_samples, txth.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
ffmpeg_data = init_ffmpeg_header_offset(txth.sf_body, buf,bytes, txth.start_offset,txth.data_size);
if ( !ffmpeg_data ) goto fail;
}
else if (txth.codec == XMA2) {
int block_count, block_size;
block_size = txth.interleave ? txth.interleave : 2048;
block_count = txth.data_size / block_size;
bytes = ffmpeg_make_riff_xma2(buf, sizeof(buf), vgmstream->num_samples, txth.data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
ffmpeg_data = init_ffmpeg_header_offset(txth.sf_body, buf,bytes, txth.start_offset,txth.data_size);
if ( !ffmpeg_data ) goto fail;
}
else {
goto fail;
}
goto fail;
}
vgmstream->codec_data = ffmpeg_data;
@ -598,7 +594,7 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
if (txth.codec == XMA1 || txth.codec == XMA2) {
xma_fix_raw_samples(vgmstream, txth.sf_body, txth.start_offset,txth.data_size, 0, 0,0);
} else if (txth.skip_samples_set && txth.codec != ATRAC3) { /* force encoder delay */
} else if (txth.skip_samples_set && txth.codec != ATRAC3 && txth.codec != ATRAC3PLUS) { /* force encoder delay */
ffmpeg_set_skip_samples(ffmpeg_data, txth.skip_samples);
}
@ -953,6 +949,8 @@ static txth_codec_t parse_codec(txth_header* txth, const char* val) {
else if (is_string(val,"XBOX")) return XBOX;
else if (is_string(val,"NGC_DTK")) return NGC_DTK;
else if (is_string(val,"DTK")) return NGC_DTK;
else if (is_string(val,"PCM24BE")) return PCM24BE;
else if (is_string(val,"PCM24LE")) return PCM24LE;
else if (is_string(val,"PCM16BE")) return PCM16BE;
else if (is_string(val,"PCM16LE")) return PCM16LE;
else if (is_string(val,"PCM8")) return PCM8;
@ -2103,6 +2101,10 @@ static int get_bytes_to_samples(txth_header* txth, uint32_t bytes) {
case PSX_bf:
case HEVAG:
return ps_bytes_to_samples(bytes, txth->channels);
case PCM24BE:
return pcm24_bytes_to_samples(bytes, txth->channels);
case PCM24LE:
return pcm24_bytes_to_samples(bytes, txth->channels);
case PCM16BE:
case PCM16LE:
return pcm16_bytes_to_samples(bytes, txth->channels);

View File

@ -275,7 +275,7 @@ static VGMSTREAM* init_vgmstream_ubi_bao_base(ubi_bao_header* bao, STREAMFILE* s
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = bao->stream_size / bao->channels;
VGM_LOG("dsp=%x, %x, %x\n", bao->header_offset, bao->header_size, bao->extra_size);
/* mini DSP header (first 0x10 seem to contain DSP header fields like nibbles and format) */
dsp_read_coefs_be(vgmstream, streamHead, bao->header_offset + bao->header_size + bao->extra_size + 0x10, 0x40);
dsp_read_hist_be (vgmstream, streamHead, bao->header_offset + bao->header_size + bao->extra_size + 0x34, 0x40); /* after gain/initial ps */
@ -286,10 +286,9 @@ VGM_LOG("dsp=%x, %x, %x\n", bao->header_offset, bao->header_size, bao->extra_siz
case RAW_XMA1:
case RAW_XMA2_OLD:
case RAW_XMA2_NEW: {
uint8_t buf[0x100];
size_t bytes, chunk_size, data_size;
size_t chunk_size, data_size;
off_t chunk_offset;
STREAMFILE* streamXMA;
STREAMFILE* sf_xma;
switch(bao->codec) {
case RAW_XMA1: chunk_size = 0x20; break;
@ -339,26 +338,19 @@ VGM_LOG("dsp=%x, %x, %x\n", bao->header_offset, bao->header_size, bao->extra_siz
header_size += align_size_to_block(sec2_num * bits_per_frame, 32) / 8; /* bitstream seek table? */
header_size += sec3_num * 0x08;
streamXMA = streamData;
sf_xma = streamData;
chunk_offset = 0x00;
start_offset += header_size;
data_size = sec2_num * frame_size;
}
else {
streamXMA = streamHead;
sf_xma = streamHead;
chunk_offset = bao->header_offset + bao->header_size;
start_offset = 0x00;
data_size = bao->stream_size;
}
if (bao->codec == RAW_XMA2_OLD) {
bytes = ffmpeg_make_riff_xma2_from_xma2_chunk(buf,0x100, chunk_offset, chunk_size, data_size, streamXMA);
}
else {
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, chunk_offset, chunk_size, data_size, streamXMA, 1);
}
vgmstream->codec_data = init_ffmpeg_header_offset(streamData, buf, bytes, start_offset, data_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf_xma, start_offset, data_size, chunk_offset, chunk_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
@ -1368,7 +1360,7 @@ static STREAMFILE* open_atomic_bao(ubi_bao_file file_type, uint32_t file_id, int
snprintf(buf,buf_size, "%08x.bao", file_id);
sf_bao = open_streamfile_by_filename(sf, buf);
if (sf_bao) return sf_bao;
}
}
else {
/* %08x.sbao nomenclature (in addition to %08x.bao) present in Shaun White Snowboarding (Windows Vista) exe. */
snprintf(buf,buf_size, "%08x.sbao", file_id);

View File

@ -148,11 +148,7 @@ VGMSTREAM* init_vgmstream_ubi_ckd(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case XMA2: {
uint8_t buf[0x100];
int bytes;
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf, sizeof(buf), 0x14, 0x34, data_size, sf, 1);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,data_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, data_size, 0x14, 0x34);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -745,14 +745,9 @@ static VGMSTREAM* init_vgmstream_ubi_hx_header(ubi_hx_header* hx, STREAMFILE* sf
#ifdef VGM_USE_FFMPEG
case XMA2: {
int bytes, block_count, block_size;
uint8_t buf[0x200];
int block_size = 0x800;
block_size = 0x800;
block_count = hx->stream_size / block_size;
bytes = ffmpeg_make_riff_xma2(buf,0x200, hx->num_samples, hx->stream_size, hx->channels, hx->sample_rate, block_count, block_size);
vgmstream->codec_data = init_ffmpeg_header_offset(sb, buf,bytes, hx->stream_offset,hx->stream_size);
vgmstream->codec_data = init_ffmpeg_xma2_raw(sb, hx->stream_offset, hx->stream_size, hx->num_samples, hx->channels, hx->sample_rate, block_size, 0);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -273,8 +273,6 @@ VGMSTREAM* init_vgmstream_ubi_lyn(STREAMFILE* sf) {
}
case 0x0166: { /* XMA (X360), standard */
uint8_t buf[0x100];
int bytes;
off_t chunk_offset;
size_t chunk_size, seek_size;
@ -286,9 +284,8 @@ VGMSTREAM* init_vgmstream_ubi_lyn(STREAMFILE* sf) {
start_offset += (0x04 + 0x04 + chunk_size + 0x04 + seek_size);
data_size -= (0x04 + 0x04 + chunk_size + 0x04 + seek_size);
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, chunk_offset,chunk_size, data_size, sf, 1);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,data_size);
if ( !vgmstream->codec_data ) goto fail;
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, data_size, chunk_offset, chunk_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -3,8 +3,8 @@
/* RAKI - Ubisoft audio format [Rayman Legends, Just Dance 2017 (multi)] */
VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *sf) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_ubi_raki(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset, offset, fmt_offset;
size_t header_size, data_size;
int big_endian;
@ -16,19 +16,22 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *sf) {
/* checks */
/* some games (ex. Rayman Legends PS3) have a 32b file type before the RAKI data. However offsets are
* absolute and expect the type exists, so it's part of the file and not an extraction defect.
* Type varies between platforms (0x09, 0x0b, etc). */
if ((is_id32be(0x00,sf, "RAKI")))
offset = 0x00;
else if (is_id32be(0x04,sf, "RAKI"))
offset = 0x04;
else
goto fail;
/* .rak: Just Dance 2017
* .ckd: Rayman Legends (technically .wav.ckd/rak) */
if (!check_extensions(sf,"rak,ckd"))
goto fail;
/* some games (ex. Rayman Legends PS3) have a 32b file type before the RAKI data. However
* offsets are absolute and expect the type exists, so it's part of the file and not an extraction defect. */
if ((read_32bitBE(0x00,sf) == 0x52414B49)) /* "RAKI" */
offset = 0x00;
else if ((read_32bitBE(0x04,sf) == 0x52414B49)) /* type varies between platforms (0x09, 0x0b) so ignore */
offset = 0x04;
else
goto fail;
/* 0x04: version? (0x00, 0x07, 0x0a, etc); */
platform = read_32bitBE(offset+0x08,sf); /* string */
@ -182,20 +185,15 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *sf) {
#ifdef VGM_USE_FFMPEG
case 0x58333630786D6132: { /* "X360xma2" */
/* chunks: "seek" (XMA2 seek table), "data" */
uint8_t buf[100];
int bytes, block_count;
if (!block_align) goto fail;
block_count = data_size / block_align + (data_size % block_align ? 1 : 0);
vgmstream->num_samples = read_32bit(fmt_offset+0x18,sf);
bytes = ffmpeg_make_riff_xma2(buf, 100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_align);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,data_size);
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, start_offset, data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_align, 0);
if ( !vgmstream->codec_data ) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = read_32bit(fmt_offset+0x18,sf);
xma_fix_raw_samples(vgmstream, sf, start_offset,data_size, 0, 0,0); /* should apply to num_samples? */
break;
}

View File

@ -1118,10 +1118,9 @@ static VGMSTREAM* init_vgmstream_ubi_sb_base(ubi_sb_header* sb, STREAMFILE* sf_h
// Probably a beta/custom encoder that creates some buggy frames, that a real X360 handles ok, but trips FFmpeg
// xmaencode decodes correctly if counters are fixed (otherwise has clicks on every frame).
case FMT_XMA1: {
uint8_t buf[0x100];
uint32_t sec1_num, sec2_num, sec3_num, bits_per_frame;
uint8_t flag;
size_t bytes, chunk_size, header_size, data_size;
size_t chunk_size, header_size, data_size;
off_t header_offset;
chunk_size = 0x20;
@ -1146,9 +1145,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_base(ubi_sb_header* sb, STREAMFILE* sf_h
start_offset += header_size;
data_size = sec2_num * 0x800;
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf, 0x100, header_offset, chunk_size, data_size, sf_data, 1);
vgmstream->codec_data = init_ffmpeg_header_offset(sf_data, buf, bytes, start_offset, data_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf_data, start_offset, data_size, header_offset, chunk_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
@ -1158,8 +1155,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_base(ubi_sb_header* sb, STREAMFILE* sf_h
}
case RAW_XMA1: {
uint8_t buf[0x100];
size_t bytes, chunk_size;
size_t chunk_size;
off_t header_offset;
VGM_ASSERT(sb->is_streamed, "UBI SB: Raw XMA used for streamed sound\n");
@ -1170,9 +1166,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_base(ubi_sb_header* sb, STREAMFILE* sf_h
if (header_offset == 0)
header_offset = sb->extra_offset;
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf, 0x100, header_offset, chunk_size, sb->stream_size, sf_head, 1);
vgmstream->codec_data = init_ffmpeg_header_offset(sf_data, buf, bytes, start_offset, sb->stream_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk_split(sf_head, sf_data, start_offset, sb->stream_size, header_offset, chunk_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -246,12 +246,19 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) {
channel_size = channel_size / channels;
}
else if (version == 0x00000020 && reserved == 0x01010101) {
/* Gift (PS2) */
/* Eko Software */
start_offset = 0x800;
channels = 2; /* mono VAGs in this game are standard, without reserved value */
interleave = 0x2000;
if (read_u32be(0x4800,sf) == 0x00000000) /* one file has bigger interleave, detectable with ch2's null frame */
/* detect interleave with ch2's null frame */
if (read_u32be(0x800 + 0x400,sf) == 0x00000000) /* Woody Woodpecker: Escape from Buzz Buzzard Park (PS2) */
interleave = 0x400;
else if (read_u32be(0x800 + 0x4000,sf) == 0x00000000) /* Gift (PS2), one file */
interleave = 0x4000;
else if (read_u32be(0x800 + 0x2000,sf) == 0x00000000) /* Gift (PS2) */
interleave = 0x2000;
else
goto fail;
channel_size = channel_size / channels;
has_interleave_last = 1;

View File

@ -4,27 +4,26 @@
#include "../layout/layout.h"
/* VGS - from Guitar Hero Encore - Rocks the 80s, Guitar Hero II PS2 */
VGMSTREAM * init_vgmstream_vgs(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_vgs(STREAMFILE *sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
size_t channel_size = 0, stream_data_size, stream_frame_count;
int channel_count = 0, loop_flag = 0, sample_rate = 0, stream_sample_rate;
int channels = 0, loop_flag = 0, sample_rate = 0, stream_sample_rate;
int i;
/* check extension, case insensitive */
if (!check_extensions(streamFile,"vgs"))
goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x56675321) /* "VgS!" */
/* checks */
if (!is_id32be(0x00,sf, "VgS!"))
goto fail;
/* 0x04: version? */
if (!check_extensions(sf,"vgs"))
goto fail;
/* contains N streams, which can have one less frame, or half frame and sample rate */
for (i = 0; i < 8; i++) {
stream_sample_rate = read_32bitLE(0x08 + 0x08*i + 0x00,streamFile);
stream_frame_count = read_32bitLE(0x08 + 0x08*i + 0x04,streamFile);
stream_sample_rate = read_32bitLE(0x08 + 0x08*i + 0x00,sf);
stream_frame_count = read_32bitLE(0x08 + 0x08*i + 0x04,sf);
stream_data_size = stream_frame_count*0x10;
if (stream_sample_rate == 0)
@ -47,24 +46,24 @@ VGMSTREAM * init_vgmstream_vgs(STREAMFILE *streamFile) {
break;
}
channel_count++;
channels++;
}
start_offset = 0x80;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_VGS;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = ps_bytes_to_samples(channel_size*channel_count, channel_count);
vgmstream->num_samples = ps_bytes_to_samples(channel_size * channels, channels);
vgmstream->coding_type = coding_PSX_badflags; /* flag = stream/channel number */
vgmstream->layout_type = layout_blocked_vgs;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:

View File

@ -301,9 +301,8 @@ VGMSTREAM* init_vgmstream_wbk_nslb(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 0x30: { /* RIFF XMA */
uint8_t buf[0x100];
off_t riff_fmt_offset, riff_data_offset;
size_t bytes, riff_fmt_size, riff_data_size;
size_t riff_fmt_size, riff_data_size;
sound_offset += 0x0c;
sound_size -= 0x0c;
@ -317,9 +316,8 @@ VGMSTREAM* init_vgmstream_wbk_nslb(STREAMFILE* sf) {
goto fail;
sound_offset = riff_data_offset;
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf, 0x100, riff_fmt_offset, riff_fmt_size, riff_data_size, sf, 0);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf, bytes, riff_data_offset, riff_data_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, riff_data_offset, riff_data_size, riff_fmt_offset, riff_fmt_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -365,9 +365,6 @@ VGMSTREAM* init_vgmstream_wwise_bnk(STREAMFILE* sf, int* p_prefetch) {
#ifdef VGM_USE_FFMPEG
case XMA2: { /* X360/XBone */
uint8_t buf[0x100];
int bytes;
/* endian check should be enough */
//if (ww.fmt_size != ...) goto fail; /* XMA1 0x20, XMA2old: 0x34, XMA2new: 0x40, XMA2 Guitar Hero Live/padded: 0x64, etc */
@ -375,14 +372,7 @@ VGMSTREAM* init_vgmstream_wwise_bnk(STREAMFILE* sf, int* p_prefetch) {
if (!(ww.big_endian || (!ww.big_endian && check_extensions(sf,"wem,bnk"))))
goto fail;
if (ww.xma2_offset) { /* older */
bytes = ffmpeg_make_riff_xma2_from_xma2_chunk(buf, sizeof(buf), ww.xma2_offset, ww.xma2_size, ww.data_size, sf);
}
else { /* newer */
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf, sizeof(buf), ww.fmt_offset, ww.fmt_size, ww.data_size, sf, ww.big_endian);
}
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, ww.data_offset,ww.data_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, ww.data_offset, ww.data_size, ww.xma2_offset ? ww.xma2_offset : ww.fmt_offset, ww.xma2_size ? ww.xma2_size : ww.fmt_size);
if ( !vgmstream->codec_data ) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -1,89 +0,0 @@
#include "meta.h"
#include "../coding/coding.h"
/* ASTB - found in Dead Rising (X360) */
VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset, data_size;
int loop_flag, channel_count;
int i, xma_streams;
/* check extension, case insensitive */
if ( !check_extensions(streamFile,"ast"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x41535442) /* "ASTB" */
goto fail;
if (read_32bitBE(0x04,streamFile) != get_streamfile_size(streamFile)) goto fail;
if (read_16bitBE(0x30,streamFile) != 0x165) goto fail; /* only seen XMA1 */
xma_streams = read_16bitBE(0x38,streamFile);
loop_flag = read_8bit(0x3a,streamFile);
channel_count = 0; /* sum of all stream channels (though only 1/2ch ever seen) */
for (i = 0; i < xma_streams; i++) {
channel_count += read_8bit(0x3c + 0x14*i + 0x11,streamFile);
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
start_offset = read_32bitBE(0x10,streamFile);
data_size = read_32bitBE(0x20,streamFile);
vgmstream->sample_rate = read_32bitBE(0x40,streamFile);
vgmstream->meta_type = meta_X360_AST;
{
/* manually find sample offsets (XMA1 nonsense again) */
ms_sample_data msd = {0};
msd.xma_version = 1;
msd.channels = channel_count;
msd.data_offset = start_offset;
msd.data_size = data_size;
msd.loop_flag = loop_flag;
msd.loop_start_b = read_32bitBE(0x44,streamFile);
msd.loop_end_b = read_32bitBE(0x48,streamFile);
msd.loop_start_subframe = read_8bit(0x4c,streamFile) & 0xF; /* lower 4b: subframe where the loop starts, 0..4 */
msd.loop_end_subframe = read_8bit(0x4c,streamFile) >> 4; /* upper 4b: subframe where the loop ends, 0..3 */
xma_get_samples(&msd, streamFile);
vgmstream->num_samples = msd.num_samples;
vgmstream->loop_start_sample = msd.loop_start_sample;
vgmstream->loop_end_sample = msd.loop_end_sample;
}
#ifdef VGM_USE_FFMPEG
{
uint8_t buf[100];
size_t bytes;
off_t fmt_offset = 0x30;
size_t fmt_size = 0x0c + xma_streams * 0x14;
/* XMA1 "fmt" chunk @ 0x20 (BE, unlike the usual LE) */
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,100, fmt_offset,fmt_size, data_size, streamFile, 1);
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
if ( !vgmstream->codec_data ) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, fmt_offset, 1,1);
}
#else
goto fail;
#endif
/* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,63 +0,0 @@
#include "meta.h"
#include "../coding/coding.h"
/* CXS - found in Eternal Sonata (X360) */
VGMSTREAM* init_vgmstream_x360_cxs(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
/* checks */
if ( !check_extensions(sf,"cxs"))
goto fail;
if (read_32bitBE(0x00,sf) != 0x43585320) /* "CXS " */
goto fail;
loop_flag = read_32bitBE(0x18,sf) > 0;
channel_count = read_32bitBE(0x0c,sf);
start_offset = read_32bitBE(0x04,sf) + read_32bitBE(0x28,sf); /* assumed, seek table always at 0x800 */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* 0x04: data start? */
vgmstream->sample_rate = read_32bitBE(0x08,sf);
vgmstream->num_samples = read_32bitBE(0x10,sf);
vgmstream->loop_start_sample = read_32bitBE(0x14,sf);
vgmstream->loop_end_sample = read_32bitBE(0x18,sf);
/* 0x1c: below */
vgmstream->meta_type = meta_X360_CXS;
#ifdef VGM_USE_FFMPEG
{
uint8_t buf[0x100];
size_t bytes, datasize, block_size, block_count;
block_count = read_32bitBE(0x1c,sf);
block_size = read_32bitBE(0x20,sf);
datasize = read_32bitBE(0x24,sf);
bytes = ffmpeg_make_riff_xma2(buf,100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
if (bytes <= 0) goto fail;
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,datasize);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, sf, start_offset,datasize, 0, 0,1); /* num samples are ok */
}
#else
goto fail;
#endif
if ( !vgmstream_open_stream(vgmstream, sf, start_offset) )
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,71 +0,0 @@
#include "meta.h"
#include "../coding/coding.h"
/* PASX - from Premium Agency games [SoulCalibur II HD (X360), Death By Cube (X360)] */
VGMSTREAM * init_vgmstream_x360_pasx(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset, chunk_offset;
size_t data_size, chunk_size;
int loop_flag, channel_count, sample_rate;
int num_samples, loop_start_sample, loop_end_sample;
/* checks */
/* .past: Soul Calibur II HD
* .sgb: Death By Cube */
if ( !check_extensions(streamFile,"past,sgb"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x50415358) /* "PASX" */
goto fail;
/* custom header with a "fmt " data chunk inside */
chunk_size = read_32bitBE(0x08,streamFile);
data_size = read_32bitBE(0x0c,streamFile);
chunk_offset = read_32bitBE(0x10,streamFile); /* 0x14: fmt offset end */
start_offset = read_32bitBE(0x18,streamFile);
channel_count = read_16bitBE(chunk_offset+0x02,streamFile);
sample_rate = read_32bitBE(chunk_offset+0x04,streamFile);
xma2_parse_fmt_chunk_extra(streamFile, chunk_offset, &loop_flag, &num_samples, &loop_start_sample, &loop_end_sample, 1);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start_sample;
vgmstream->loop_end_sample = loop_end_sample;
vgmstream->meta_type = meta_X360_PASX;
#ifdef VGM_USE_FFMPEG
{
uint8_t buf[0x100];
size_t bytes;
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, chunk_offset,chunk_size, data_size, streamFile, 1);
if (bytes <= 0) goto fail;
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
if ( !vgmstream->codec_data ) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, chunk_offset, 1,1);
}
#else
goto fail;
#endif
/* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,61 +0,0 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../util.h"
/* TRA
TRA is an headerless format which can be found on DefJam Rapstar (X360)
known extensions : WAVM
2010-12-03 - Fastelbja : First version ...
*/
VGMSTREAM * init_vgmstream_x360_tra(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int loop_flag=0;
int channel_count;
int i;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("tra",filename_extension(filename))) goto fail;
/* No loop on wavm */
loop_flag = 0;
/* Always stereo files */
channel_count=2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
/* allways 2 channels @ 44100 Hz */
vgmstream->channels = 2;
vgmstream->sample_rate = 24000;
vgmstream->coding_type = coding_DVI_IMA_int;
vgmstream->num_samples = (int32_t)(get_streamfile_size(streamFile) - ((get_streamfile_size(streamFile)/0x204)*4));
vgmstream->layout_type = layout_blocked_tra;
vgmstream->meta_type = meta_X360_TRA;
/* open the file for reading by each channel */
{
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
block_update_tra(0,vgmstream);
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -141,17 +141,7 @@ VGMSTREAM* init_vgmstream_xma(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
{
uint8_t buf[0x100];
int bytes;
if (is_xma2_old) {
bytes = ffmpeg_make_riff_xma2_from_xma2_chunk(buf, sizeof(buf), chunk_offset,chunk_size, data_size, sf);
}
else {
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf, sizeof(buf), chunk_offset,chunk_size, data_size, sf, fmt_be);
}
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf, bytes, start_offset, data_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, data_size, chunk_offset, chunk_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
@ -162,11 +152,9 @@ VGMSTREAM* init_vgmstream_xma(STREAMFILE* sf) {
goto fail;
#endif
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;

View File

@ -2,36 +2,36 @@
#include "../coding/coding.h"
/* XMA from Unreal Engine games */
VGMSTREAM* init_vgmstream_xma_ue3(STREAMFILE *sf) {
VGMSTREAM* init_vgmstream_xma_ue3(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset, chunk_offset;
int loop_flag, channel_count, sample_rate, is_xma2_old = 0;
uint32_t start_offset, chunk_offset;
int loop_flag, channel_count, sample_rate;
int num_samples, loop_start_sample, loop_end_sample;
size_t file_size, fmt_size, seek_size, data_size;
uint32_t file_size, chunk_size, seek_size, data_size;
/* checks */
/* .xma: assumed */
/* .x360audio: fake produced by UE Viewer */
if (!check_extensions(sf, "xma,x360audio,"))
goto fail;
/* UE3 uses class-like chunks called "SoundNodeWave" to store info and (rarely multi) raw audio data. Other
* platforms use standard formats (PC=Ogg, PS3=MSF), while X360 has mutant XMA. Extractors transmogrify
* UE3 XMA into RIFF XMA (discarding seek table and changing endianness) but we'll support actual raw
* data for completeness. UE4 has .uexp which are very similar so XBone may use the same XMA. */
/* checks */
file_size = get_streamfile_size(sf);
fmt_size = read_u32be(0x00, sf);
chunk_size = read_u32be(0x00, sf);
seek_size = read_u32be(0x04, sf);
data_size = read_u32be(0x08, sf);
if (0x0c + fmt_size + seek_size + data_size != file_size)
if (0x0c + chunk_size + seek_size + data_size != file_size)
goto fail;
/* .xma: assumed */
/* .x360audio: fake produced by UE Viewer */
if (!check_extensions(sf, "xma,x360audio,"))
goto fail;
chunk_offset = 0x0c;
/* parse sample data (always BE unlike real XMA) */
if (fmt_size != 0x34) { /* old XMA2 [The Last Remnant (X360)] */
is_xma2_old = 1;
if (chunk_size != 0x34) { /* old XMA2 [The Last Remnant (X360)] */
xma2_parse_xma2_chunk(sf, chunk_offset, &channel_count,&sample_rate, &loop_flag, &num_samples, &loop_start_sample, &loop_end_sample);
}
else { /* new XMA2 [Shadows of the Damned (X360)] */
@ -40,7 +40,7 @@ VGMSTREAM* init_vgmstream_xma_ue3(STREAMFILE *sf) {
xma2_parse_fmt_chunk_extra(sf, chunk_offset, &loop_flag, &num_samples, &loop_start_sample, &loop_end_sample, 1);
}
start_offset = 0x0c + fmt_size + seek_size;
start_offset = 0x0c + chunk_size + seek_size;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
@ -54,15 +54,7 @@ VGMSTREAM* init_vgmstream_xma_ue3(STREAMFILE *sf) {
#ifdef VGM_USE_FFMPEG
{
uint8_t buf[0x100];
size_t bytes;
if (is_xma2_old) {
bytes = ffmpeg_make_riff_xma2_from_xma2_chunk(buf,0x100, chunk_offset,fmt_size, data_size, sf);
} else {
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, chunk_offset,fmt_size, data_size, sf, 1);
}
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,data_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, data_size, chunk_offset, chunk_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
@ -91,7 +83,6 @@ VGMSTREAM* init_vgmstream_xma_ue3(STREAMFILE *sf) {
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;

View File

@ -259,14 +259,9 @@ VGMSTREAM* init_vgmstream_xnb(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 0x166: { /* Terraria (X360) */
uint8_t buf[0x100];
int32_t bytes, block_size, block_count;
int block_size = 0x10000; /* guessed */
block_size = 0x10000; /* guessed */
block_count = data_size / block_size + (data_size % block_size ? 1 : 0);
bytes = ffmpeg_make_riff_xma2(buf,0x100, num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
vgmstream->codec_data = init_ffmpeg_header_offset(sf_h, buf,bytes, start_offset,data_size);
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf_h, start_offset, data_size, num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, 0);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -1,301 +0,0 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
/* SDRH - banks for newer feelplus-related games [Mindjack (PS3/X360)] */
VGMSTREAM* init_vgmstream_xse_new(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset, data_size, stream_size;
int loop_flag = 0, channels, codec, sample_rate, seek_count;
int32_t num_samples, loop_start, loop_end;
off_t offset;
int total_subsongs, target_subsong = sf->stream_index;
/* checks */
if (!check_extensions(sf, "xse"))
goto fail;
if (read_u32be(0x00,sf) != 0x48524453) /* "HRDS" */
goto fail;
/* similar to older version but BE and a bit less complex */
/* 0x04: version/config?
* 0x08: data size
* 0x30: file name in some strange encoding/compression?
* others: ? (change in old/new)
*/
/* parse section */
{
int i;
int tables = read_u16be(0x1C,sf);
off_t base_size, stream_offset;
int entries;
offset = 0;
/* read sections (FE=cues?, WV=mini-headers?, XW=waves) */
for (i = 0; i < tables; i++) {
uint16_t id = read_u16be(0x40 + 0x10 * i + 0x00,sf);
/* 0x02: offset in 0x40s */
/* 0x04: section size */
/* 0x08: always 1 */
/* 0x0c: null */
if (id == 0x5857) { /* "XW" */
offset += read_u16be(0x40 + 0x10 * i + 0x02,sf) * 0x40;
break;
}
}
/* section header (other sections have a similar header) */
/* 0x00: section size */
base_size = read_u16be(offset + 0x04,sf);
entries = read_u16be(offset + 0x06,sf);
/* 0x08: null */
start_offset = read_u32be(offset + 0x0c,sf) + offset; /* size including padding up to start */
offset += base_size;
total_subsongs = entries;
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
/* find stream header (entries can be variable-sized) */
for (i = 0; i < entries; i++) {
size_t seek_size = read_u16be(offset + 0x0a,sf) * 0x04;
size_t entry_size = align_size_to_block(0x30 + seek_size, 0x10);
if (i + 1 == target_subsong)
break;
offset += entry_size;
}
/* parse target header (similar to xwav) */
stream_size = read_u32be(offset + 0x00,sf);
/* 0x04: codec? (16=PS3, 03=X360) */
codec = read_u8(offset + 0x06,sf); /* assumed */
loop_flag = read_u8(offset + 0x07,sf); /* assumed */
/* 0x08: bps? */
channels = read_u8(offset + 0x09,sf);
seek_count = read_u16be(offset + 0x0a,sf);
num_samples = read_u32be(offset + 0x0c,sf);
sample_rate = read_u32be(offset + 0x10,sf);
loop_start = read_u32be(offset + 0x14,sf);
loop_end = read_u32be(offset + 0x18,sf);
/* 0x1c: ? */
stream_offset = read_u32be(offset + 0x20,sf); /* within data */
/* 0x24: ? */
/* 0x26 seek entries */
/* 0x28: ? */
/* 0x2c: null? */
start_offset += stream_offset;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_SDRH;
vgmstream->num_samples = num_samples;
vgmstream->sample_rate = sample_rate;
vgmstream->stream_size = stream_size;
vgmstream->num_streams = total_subsongs;
switch(codec) {
case 2: /* Mindjack (PS3) */
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
break;
#ifdef VGM_USE_FFMPEG
case 1: { /* Mindjack (X360) */
uint8_t buf[0x100];
int32_t bytes, block_size, block_count;
data_size = get_streamfile_size(sf) - start_offset;
block_size = 0x10000; /* XWAV new default */
block_count = seek_count;
bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,data_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
//todo fix loops/samples vs ATRAC3
/* may be only applying end_skip to num_samples? */
xma_fix_raw_samples(vgmstream, sf, start_offset,data_size, 0, 0,0);
break;
}
#endif
default:
goto fail;
}
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
/* SDRH - banks for older feelplus-related games [Lost Odyssey (X360)] */
VGMSTREAM* init_vgmstream_xse_old(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset, data_size, stream_size;
int loop_flag = 0, channels, codec, sample_rate, seek_count;
int32_t num_samples, loop_start, loop_end;
off_t offset;
int total_subsongs, target_subsong = sf->stream_index;
/* checks */
/* .xse: assumed */
if (!check_extensions(sf, "xse"))
goto fail;
if (read_u32be(0x00,sf) != 0x53445248) /* "SDRH" */
goto fail;
/* similar to older version but LE and a bit more complex */
/* 0x04: version/config?
* 0x08: data size
* 0x30: file name in some strange encoding/compression?
* others: ? (change in old/new)
*/
/* parse section */
{
int i;
int tables = read_u8(0x15,sf);
off_t base_size, stream_offset;
int entries;
offset = 0x40;
/* read sections (FE=cues?, WV=mini-headers?, FT=?, FQ=?, XW=waves) */
for (i = 0; i < tables; i++) {
uint16_t id = read_u16be(0x40 + 0x08 * i + 0x00,sf);
/* 0x02: null? */
/* 0x04: offset from table start */
if (id == 0x5857) { /* "XW" */
offset += read_u32le(0x40 + 0x08 * i + 0x04,sf);
break;
}
}
/* section header (other sections have a similar header) */
/* 0x00: section size */
base_size = read_u16le(offset + 0x04,sf);
/* 0x06: ? */
entries = read_u16le(offset + 0x08,sf);
start_offset = read_u32le(offset + 0x0c,sf) + offset; /* size including padding up to start */
offset += base_size;
total_subsongs = entries;
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
/* find stream header */
stream_offset = 0;
for (i = 0; i < entries; i++) {
size_t data_size = read_u32le(offset + 0x00,sf) - 0x30;
size_t seek_size = 0; //read_u16be(offset + 0x0a,sf) * 0x04; /* not seen */
size_t entry_size = align_size_to_block(0x30 + seek_size, 0x10);
if (i + 1 == target_subsong)
break;
offset += entry_size;
stream_offset += data_size; /* no offset? */
}
/* parse target header (similar to xwav) */
stream_size = read_u32le(offset + 0x00,sf) - 0x30; /* adds entry size */
/* 0x04: codec? (16=PS3, 03=X360) */
codec = read_u8(offset + 0x06,sf); /* assumed */
/* 0x07: flag? */
/* 0x08: bps? */
/* 0x09: codec? */
/* 0x0a: null */
num_samples = read_u32le(offset + 0x0c,sf);
seek_count = read_u16le(offset + 0x10,sf);
sample_rate = read_u32le(offset + 0x14,sf);
loop_start = 0; //read_u32le(offset + 0x18,sf); /* ? */
loop_end = 0; //read_u32le(offset + 0x1c,sf); /* ? */
/* 0x20: null */
/* 0x24: ? */
/* 0x26: channel layout */
channels = read_u8(offset + 0x27,sf);
/* 0x28: ? */
/* 0x2c: null? */
loop_flag = loop_end > 0;
start_offset += stream_offset;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_SDRH;
vgmstream->num_samples = num_samples;
vgmstream->sample_rate = sample_rate;
vgmstream->stream_size = stream_size;
vgmstream->num_streams = total_subsongs;
switch(codec) {
#ifdef VGM_USE_FFMPEG
case 4: { /* Lost Odyssey (X360) */
uint8_t buf[0x100];
int32_t bytes, block_size, block_count;
data_size = get_streamfile_size(sf) - start_offset;
block_size = 0x8000; /* XWAV old default */
block_count = seek_count;
bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,data_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
xma_fix_raw_samples(vgmstream, sf, start_offset, data_size, 0, 0, 1);
break;
}
#endif
default:
goto fail;
}
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -12,12 +12,13 @@ VGMSTREAM* init_vgmstream_xwav_new(STREAMFILE* sf) {
/* checks */
if (!is_id32le(0x00,sf, "XWAV"))
goto fail;
/* .xwv: actual extension [Moon Diver (PS3/X360)]
* .vawx: header id */
if (!check_extensions(sf, "xwv,vawx"))
goto fail;
if (read_u32be(0x00,sf) != 0x56415758) /* "VAWX" */
goto fail;
/* similar to older version but BE and a bit less complex */
/* 0x04: data size
@ -29,7 +30,7 @@ VGMSTREAM* init_vgmstream_xwav_new(STREAMFILE* sf) {
* 0x16: file number
* 0x18: null
* 0x1c: null
* 0x20: file name in some strange encoding/compression?
* 0x20: file name in a custom 40-char (RADIX style) encoding
*/
start_offset = 0x800;
@ -71,15 +72,12 @@ VGMSTREAM* init_vgmstream_xwav_new(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 1: { /* No Nore Heroes (X360), Moon Diver (X360), Ninety-Nine Nights 2 (X360) */
uint8_t buf[0x100];
int32_t bytes, block_size, block_count;
int block_size = 0x10000; /* XWAV new default */
int block_count = read_u16be(0x30 + 0x0A, sf); /* also at 0x56 */
data_size = get_streamfile_size(sf) - start_offset;
block_size = 0x10000; /* XWAV new default */
block_count = read_u16be(0x30 + 0x0A, sf); /* also at 0x56 */
bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,data_size);
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, start_offset, data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, block_count);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
@ -136,10 +134,11 @@ VGMSTREAM* init_vgmstream_xwav_old(STREAMFILE* sf) {
/* checks */
/* .xwv: actual extension [Bullet Witch (X360)] */
if (!check_extensions(sf, "xwv"))
if (!is_id32be(0x00,sf, "XWAV"))
goto fail;
if (read_u32be(0x00,sf) != 0x58574156) /* "XWAV" */
/* .xwv: actual extension [Bullet Witch (X360), Lost Odyssey Demo (X360)] */
if (!check_extensions(sf, "xwv"))
goto fail;
/* similar to newer version but LE and a bit more complex */
@ -224,15 +223,12 @@ VGMSTREAM* init_vgmstream_xwav_old(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 4: { /* Lost Odyssey (X360) */
uint8_t buf[0x100];
int32_t bytes, block_size, block_count;
int block_size = 0x8000; /* XWAV old default */
int block_count = read_u16be(0x30, sf);
data_size = get_streamfile_size(sf) - start_offset;
block_size = 0x8000; /* XWAV old default */
block_count = read_u16be(0x30, sf);
bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,data_size);
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, start_offset, data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, block_count);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
@ -253,7 +249,6 @@ VGMSTREAM* init_vgmstream_xwav_old(STREAMFILE* sf) {
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;

Some files were not shown because too many files have changed in this diff Show More