@@ -809,10 +809,11 @@ VGMSTREAM* init_vgmstream_ea_tmx(STREAMFILE* sf) {
809809
810810/* EA Harmony Sample Bank - used in 8th gen EA Sports games */
811811VGMSTREAM * init_vgmstream_ea_sbr_harmony (STREAMFILE * sf ) {
812- uint64_t set_sounds , base_offset , sound_offset ;
813- uint32_t chunk_id , data_offset , table_offset , dset_offset , sound_table_offset ;
812+ uint64_t base_offset , sound_offset , offset , prev_offset ;
813+ uint32_t chunk_id , data_offset , table_offset , dset_offset , set_values , set_sounds , sound_table_offset ;
814+ int32_t flag ;
814815 uint16_t num_dsets ;
815- uint8_t set_type , flag , offset_size ;
816+ uint8_t set_type , offset_size ;
816817 uint32_t i , j ;
817818 char sound_name [STREAM_NAME_SIZE ];
818819 STREAMFILE * sf_sbs = NULL , * sf_data = NULL ;
@@ -826,11 +827,11 @@ VGMSTREAM* init_vgmstream_ea_sbr_harmony(STREAMFILE* sf) {
826827 goto fail ;
827828
828829 /* check header */
829- if (read_u32be (0x00 , sf ) == 0x53426C65 ) { /* "SBle" */
830+ if (is_id32be (0x00 , sf , "SBle" )) {
830831 read_u64 = read_u64le ;
831832 read_u32 = read_u32le ;
832833 read_u16 = read_u16le ;
833- } else if (read_u32be (0x00 , sf ) == 0x53426265 ) { /* "SBbe" */
834+ } else if (is_id32be (0x00 , sf , "SBbe" )) {
834835 read_u64 = read_u64be ;
835836 read_u32 = read_u32be ;
836837 read_u16 = read_u16be ;
@@ -839,8 +840,8 @@ VGMSTREAM* init_vgmstream_ea_sbr_harmony(STREAMFILE* sf) {
839840 }
840841
841842 num_dsets = read_u16 (0x0a , sf );
843+ table_offset = read_u32 (0x18 , sf );
842844 data_offset = read_u32 (0x20 , sf );
843- table_offset = read_u32 (0x24 , sf );
844845
845846 if (target_stream == 0 ) target_stream = 1 ;
846847 if (target_stream < 0 )
@@ -849,14 +850,14 @@ VGMSTREAM* init_vgmstream_ea_sbr_harmony(STREAMFILE* sf) {
849850 total_sounds = 0 ;
850851 sound_offset = 0 ;
851852
852- /* The bank is split into DSET sections each of which references one or multiple sounds. */
853- /* Each set can contain RAM sounds (stored in SBR in data section) or streamed sounds (stored separately in SBS file). */
853+ /* the bank is split into DSET sections each of which references one or multiple sounds */
854+ /* each set can contain RAM sounds (stored in SBR in data section) or streamed sounds (stored separately in SBS file) */
854855 for (i = 0 ; i < num_dsets ; i ++ ) {
855856 dset_offset = read_u32 (table_offset + 0x08 * i , sf );
856857 if (read_u32 (dset_offset , sf ) != 0x44534554 ) /* "DSET" */
857858 goto fail ;
858859
859- set_sounds = read_u32 (dset_offset + 0x38 , sf );
860+ set_values = read_u32 (dset_offset + 0x38 , sf );
860861 local_target = target_stream - total_sounds - 1 ;
861862 dset_offset += 0x48 ;
862863
@@ -877,50 +878,60 @@ VGMSTREAM* init_vgmstream_ea_sbr_harmony(STREAMFILE* sf) {
877878 }
878879 }
879880
880- /* Different set types store offsets differently */
881+ /* different set types store offsets differently */
881882 set_type = read_u8 (dset_offset + 0x05 , sf );
882883
884+ /* data sets often contain duplicate offets, need to filter them out however we can */
885+ /* offsets are stored in ascending order which makes things easier */
883886 if (set_type == 0x00 ) {
884- total_sounds ++ ;
887+ set_sounds = 1 ;
888+ total_sounds += set_sounds ;
885889 if (local_target < 0 || local_target > 0 )
886890 continue ;
887891
888892 sound_offset = read_u64 (dset_offset + 0x08 , sf );
889893 } else if (set_type == 0x01 ) {
890- total_sounds += 2 ;
891- if (local_target < 0 || local_target > 1 )
892- continue ;
893-
894+ flag = (int16_t )read_u16 (dset_offset + 0x06 , sf );
894895 base_offset = read_u64 (dset_offset + 0x08 , sf );
895896
896- if (local_target == 0 ) {
897- sound_offset = base_offset ;
898- } else {
899- sound_offset = base_offset + read_u16 (dset_offset + 0x06 , sf );
900- }
897+ set_sounds = set_values ;
898+ total_sounds += set_sounds ;
899+ if (local_target < 0 || local_target >= set_sounds )
900+ continue ;
901+
902+ sound_offset = base_offset + flag * local_target ;
901903 } else if (set_type == 0x02 ) {
902904 flag = (read_u16 (dset_offset + 0x06 , sf ) >> 0 ) & 0xFF ;
903905 offset_size = (read_u16 (dset_offset + 0x06 , sf ) >> 8 ) & 0xFF ;
904906 base_offset = read_u64 (dset_offset + 0x08 , sf );
905907 sound_table_offset = read_u32 (dset_offset + 0x10 , sf );
906908
907- total_sounds += set_sounds ;
908- if (local_target < 0 || local_target >= set_sounds )
909- continue ;
909+ set_sounds = 0 ;
910+ prev_offset = UINT64_MAX ;
911+ for (j = 0 ; j < set_values ; j ++ ) {
912+ if (offset_size == 0x01 ) {
913+ offset = read_u8 (sound_table_offset + 0x01 * j , sf );
914+ } else if (offset_size == 0x02 ) {
915+ offset = read_u16 (sound_table_offset + 0x02 * j , sf );
916+ } else if (offset_size == 0x04 ) {
917+ offset = read_u32 (sound_table_offset + 0x04 * j , sf );
918+ } else {
919+ goto fail ;
920+ }
921+ offset <<= flag ;
922+ offset += base_offset ;
910923
911- if (offset_size == 0x01 ) {
912- sound_offset = read_u8 (sound_table_offset + 0x01 * local_target , sf );
913- for (j = 0 ; j < flag ; j ++ ) sound_offset *= 2 ;
914- } else if (offset_size == 0x02 ) {
915- sound_offset = read_u16 (sound_table_offset + 0x02 * local_target , sf );
916- for (j = 0 ; j < flag ; j ++ ) sound_offset *= 2 ;
917- } else if (offset_size == 0x04 ) {
918- sound_offset = read_u32 (sound_table_offset + 0x04 * local_target , sf );
919- } else {
920- goto fail ;
924+ if (offset != prev_offset ) {
925+ if (set_sounds == local_target )
926+ sound_offset = offset ;
927+ set_sounds ++ ;
928+ }
929+ prev_offset = offset ;
921930 }
922931
923- sound_offset += base_offset ;
932+ total_sounds += set_sounds ;
933+ if (local_target < 0 || local_target >= set_sounds )
934+ continue ;
924935 } else if (set_type == 0x03 ) {
925936 offset_size = (read_u16 (dset_offset + 0x06 , sf ) >> 8 ) & 0xFF ;
926937 set_sounds = read_u64 (dset_offset + 0x08 , sf );
@@ -940,12 +951,24 @@ VGMSTREAM* init_vgmstream_ea_sbr_harmony(STREAMFILE* sf) {
940951 goto fail ;
941952 }
942953 } else if (set_type == 0x04 ) {
954+ sound_table_offset = read_u32 (dset_offset + 0x10 , sf );
955+
956+ set_sounds = 0 ;
957+ prev_offset = UINT64_MAX ;
958+ for (j = 0 ; j < set_values ; j ++ ) {
959+ offset = read_u64 (sound_table_offset + 0x08 * j , sf );
960+
961+ if (sound_offset != prev_offset ) {
962+ if (set_sounds == local_target )
963+ sound_offset = offset ;
964+ set_sounds ++ ;
965+ }
966+ prev_offset = offset ;
967+ }
968+
943969 total_sounds += set_sounds ;
944970 if (local_target < 0 || local_target >= set_sounds )
945971 continue ;
946-
947- sound_table_offset = read_u32 (dset_offset + 0x10 , sf );
948- sound_offset = read_u32 (sound_table_offset + 0x08 * local_target , sf );
949972 } else {
950973 goto fail ;
951974 }
@@ -964,8 +987,8 @@ VGMSTREAM* init_vgmstream_ea_sbr_harmony(STREAMFILE* sf) {
964987
965988 if (!is_streamed ) {
966989 /* RAM asset */
967- if (read_u32be (data_offset , sf ) != 0x64617461 && /* "data" */
968- read_u32be (data_offset , sf ) != 0x44415441 ) /* "DATA" */
990+ if (! is_id32be (data_offset , sf , "data" ) &&
991+ ! is_id32be (data_offset , sf , "DATA" ))
969992 goto fail ;
970993
971994 sf_data = sf ;
@@ -976,13 +999,13 @@ VGMSTREAM* init_vgmstream_ea_sbr_harmony(STREAMFILE* sf) {
976999 if (!sf_sbs )
9771000 goto fail ;
9781001
979- if (read_u32be (0x00 , sf_sbs ) != 0x64617461 && /* "data" */
980- read_u32be (0x00 , sf_sbs ) != 0x44415441 ) /* "DATA" */
1002+ if (! is_id32be (0x00 , sf_sbs , "data" ) &&
1003+ ! is_id32be (0x00 , sf_sbs , "DATA" ))
9811004 goto fail ;
9821005
9831006 sf_data = sf_sbs ;
9841007
985- if (read_u32be (sound_offset , sf_data ) == 0x736C6F74 ) {
1008+ if (is_id32be (sound_offset , sf_data , "slot" ) ) {
9861009 /* skip "slot" section */
9871010 sound_offset += 0x30 ;
9881011 }
0 commit comments