Skip to content

Commit 88a74ac

Browse files
Merge pull request vgmstream#909 from NicknineTheEagle/ea
Improved EA Harmony bank support
2 parents 0ad117e + 52ceaef commit 88a74ac

File tree

1 file changed

+65
-42
lines changed

1 file changed

+65
-42
lines changed

src/meta/ea_eaac.c

Lines changed: 65 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -809,10 +809,11 @@ VGMSTREAM* init_vgmstream_ea_tmx(STREAMFILE* sf) {
809809

810810
/* EA Harmony Sample Bank - used in 8th gen EA Sports games */
811811
VGMSTREAM* 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

Comments
 (0)