Skip to content

Commit

Permalink
Merge 'Fix fanfares killing music bug and add credits music into the …
Browse files Browse the repository at this point in the history
…music pool as a setting' (#2050)
  • Loading branch information
cjohnson57 committed Aug 26, 2023
2 parents 1f06fa4 + c4db142 commit 69c4e08
Show file tree
Hide file tree
Showing 11 changed files with 27,366 additions and 27,283 deletions.
1,526 changes: 763 additions & 763 deletions ASM/build/asm_symbols.txt

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions ASM/src/audio.asm
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@fanfare_audioseq_size equ 0x1000
@fanfare_audiobank_size equ 0x4800
@fanfare_unk_size equ 0
@bgm_audioseq_size equ 0x7000
@bgm_audioseq_size equ 0xE000
@bgm_audiobank_size equ 0x4800
@bgm_unk_size equ 0

Expand All @@ -27,11 +27,11 @@ AUDIO_THREAD_INFO_MEM_SIZE:

.align 0x10
AUDIOBANK_TABLE_EXTENDED:
.area 0x800, 0
.area 0xA00, 0
.endarea

FONTLOADSTATUS_EXTENDED:
.area 0x80, 0
.area 0xA0, 0
.endarea

.align 0x10
Expand Down
2 changes: 1 addition & 1 deletion ASM/src/hacks.asm
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ Gameplay_InitSkybox:
; addiu v0, v0 0x5660
; addiu v1, v1, 0x5630
li v1, FONTLOADSTATUS_EXTENDED
li v0, FONTLOADSTATUS_EXTENDED + 0x80
li v0, FONTLOADSTATUS_EXTENDED + 0xA0

.org 0x800B3554
; Replaces:
Expand Down
79 changes: 70 additions & 9 deletions Music.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
("Zelda Turns Around", 0x51),
("Master Sword", 0x53),
("Door of Time", 0x59),
("Gannons Rainbow Bridge", 0x5D),
)

ocarina_sequence_ids: tuple[tuple[str, int], ...] = (
Expand All @@ -103,6 +104,18 @@
("Song of Storms", 0x49),
)

credit_sequence_ids: tuple[tuple[str, int], ...] = (
("Zeldas Theme Orchestra", 0x52),
("Zeldas Ocarina Song", 0x66),
("Ending Credits Part 1", 0x67),
("Ending Credits Part 2", 0x68),
("Ending Credits Part 3", 0x69),
("Ending Credits Part 4", 0x6A),
)

fileselect_sequence_id: tuple[tuple[str, int], ...] = (
("File Select", 0x57),
)

class Bank:
def __init__(self, index: int, meta: bytearray, data: bytes) -> None:
Expand Down Expand Up @@ -348,6 +361,11 @@ def rebuild_sequences(rom: Rom, sequences: list[Sequence], log: CosmeticsLog, sy
replacement_dict = {seq.replaces: seq for seq in sequences}
# List of sequences (actual sequence data objects) containing the vanilla sequence data
old_sequences = []
bgmlist = [sequence_id for title, sequence_id in bgm_sequence_ids]
fanfarelist = [sequence_id for title, sequence_id in fanfare_sequence_ids]
ocarinalist = [sequence_id for title, sequence_id in ocarina_sequence_ids]
creditlist = [sequence_id for title, sequence_id in credit_sequence_ids]
fileselectlist = [sequence_id for title, sequence_id in fileselect_sequence_id]

for i in range(0x6E):
# Create new sequence object, an entry for the audio sequence
Expand Down Expand Up @@ -440,11 +458,33 @@ def rebuild_sequences(rom: Rom, sequences: list[Sequence], log: CosmeticsLog, sy
rom.write_int32(0xB89AE0 + (i * 0x10), new_sequences[i].address)
rom.write_int32(0xB89AE0 + (i * 0x10) + 0x04, new_sequences[i].size)
seq = replacement_dict.get(i, None)
if seq:
rom.write_int16(0xB89AE0 + (i * 0x10) + 0x08, seq.type)

# Update instrument sets
for i in range(0x6E):
# Update instrument sets for bgm sequences
for i in bgmlist:
base = 0xB89911 + 0xDD + (i * 2)
j = replacement_dict.get(i if new_sequences[i].size else new_sequences[i].address, None)
if j:
rom.write_byte(base, j.instrument_set)
# Update instrument sets for fanfare sequences
for i in fanfarelist:
base = 0xB89911 + 0xDD + (i * 2)
j = replacement_dict.get(i if new_sequences[i].size else new_sequences[i].address, None)
if j:
rom.write_byte(base, j.instrument_set + 0x26)
#Update instrument sets for ocarina fanfare sequences
for i in ocarinalist:
base = 0xB89911 + 0xDD + (i * 2)
j = replacement_dict.get(i if new_sequences[i].size else new_sequences[i].address, None)
if j:
rom.write_byte(base, j.instrument_set + 0x26)
#Update instrument sets for credits sequences
for i in creditlist:
base = 0xB89911 + 0xDD + (i * 2)
j = replacement_dict.get(i if new_sequences[i].size else new_sequences[i].address, None)
if j:
rom.write_byte(base, j.instrument_set)
#Update instrument set for file select sequence
for i in fileselectlist:
base = 0xB89911 + 0xDD + (i * 2)
j = replacement_dict.get(i if new_sequences[i].size else new_sequences[i].address, None)
if j:
Expand All @@ -457,7 +497,7 @@ def rebuild_sequences(rom: Rom, sequences: list[Sequence], log: CosmeticsLog, sy

added_banks = [] # Store copies of all the banks we've added
added_instruments = [] # Store copies of all the instruments we've added
new_bank_index = 0x26
new_bank_index = 0x4C
instr_data = bytearray(0) # Store all the new instrument data that will be added to the end of audiotable

audiobank_dma_entry = rom.dma[AUDIOBANK_DMADATA_INDEX]
Expand Down Expand Up @@ -520,6 +560,20 @@ def rebuild_sequences(rom: Rom, sequences: list[Sequence], log: CosmeticsLog, sy
# Update the sequence's bank (instrument set)
rom.write_byte(seq_bank_base, bank.index)

# Writes new audiobank index from /data/custom_audiobank_index.bin to audiobank index
file_path = "data/custom_audiobank_index.bin"
byte_list = []
bank_table_base = (rom.read_int32(symbols['CFG_AUDIOBANK_TABLE_EXTENDED_ADDR']) - 0x80400000) + 0x3480000
with open(file_path, "rb") as file:
byte = file.read(1)
while byte:
byte_list.append(ord(byte))
byte = file.read(1)
rom.write_bytes(bank_table_base + 0x270, byte_list)
file.close()
rom.write_byte(bank_table_base + 0x01, 0x4C) # Updates AudioBank Index Header if no custom banks are present as this would be 0x26 which would crash the game if a fanfare was played


# Patch the new instrument data into the ROM in a new file.
# If there is any instrument data to add, move the entire audiotable file to a new location in the ROM.
if len(instr_data) > 0:
Expand Down Expand Up @@ -551,8 +605,8 @@ def rebuild_sequences(rom: Rom, sequences: list[Sequence], log: CosmeticsLog, sy
new_bank_data += bank.data
new_bank_offset += len(bank.data)

# If we have new banks to add, move the entire audiobank file to a new place in ROM. Update the existing dmadata record
if len(new_bank_data) > 0:
# move the entire audiobank file to a new place in ROM. Update the existing dmadata record
if len(new_bank_data):
# Zeroize existing file
rom.write_bytes(audiobank_start, [0] * audiobank_size)
# Add the new data
Expand Down Expand Up @@ -594,6 +648,7 @@ def randomize_music(rom: Rom, settings: Settings, log: CosmeticsLog, symbols: di
bgm_ids = {bgm[0]: bgm for bgm in bgm_sequence_ids}
ff_ids = {bgm[0]: bgm for bgm in fanfare_sequence_ids}
ocarina_ids = {bgm[0]: bgm for bgm in ocarina_sequence_ids}
credits_ids = {bgm[0]: bgm for bgm in credit_sequence_ids}

# If generating a patch file, disallow custom sequences.
custom_sequences_enabled = not settings.generating_patch_file
Expand All @@ -611,10 +666,11 @@ def randomize_music(rom: Rom, settings: Settings, log: CosmeticsLog, symbols: di
log.errors.append("Custom music is not supported by this patch version. Only randomizing vanilla music.")
custom_sequences_enabled = False

# Check if we have mapped music for BGM, Fanfares, or Ocarina Fanfares
# Check if we have mapped music for BGM, Fanfares, Ocarina Songs or Credits Sequences
bgm_mapped = any(name in music_mapping for name in bgm_ids)
ff_mapped = any(name in music_mapping for name in ff_ids)
ocarina_mapped = any(name in music_mapping for name in ocarina_ids)
credits_mapped = any(name in music_mapping for name in credits_ids)

# Flag sequence locations that are set to off for disabling.
disabled_ids = []
Expand All @@ -640,6 +696,8 @@ def randomize_music(rom: Rom, settings: Settings, log: CosmeticsLog, symbols: di
normal_ids += [music_id for music_id in ff_ids.values()]
if settings.fanfares == 'normal' and ocarina_mapped:
normal_ids += [music_id for music_id in ocarina_ids.values()]
if settings.credits_music == 'false' and credits_mapped:
normal_ids += [music_id for music_id in credits_mapped.values()]
for bgm in normal_ids:
if bgm[0] not in music_mapping:
music_mapping[bgm[0]] = bgm[0]
Expand All @@ -648,6 +706,10 @@ def randomize_music(rom: Rom, settings: Settings, log: CosmeticsLog, symbols: di
if settings.ocarina_fanfares or ocarina_mapped:
ff_ids.update(ocarina_ids)

# Include credits sequences in music pool if checked
if settings.credits_music or credits_mapped:
bgm_ids.update(credits_ids)

# Grab our lists of sequences.
if settings.background_music in ['random', 'random_custom_only'] or bgm_mapped:
sequences, target_sequences, bgm_groups = process_sequences(rom, bgm_ids.values(), 'bgm', disabled_source_sequences, disabled_target_sequences, custom_sequences_enabled, include_custom_audiobanks=custom_audiobanks_enabled)
Expand Down Expand Up @@ -779,7 +841,6 @@ def restore_music(rom: Rom) -> None:
rom.write_bytes(start, [0] * size)
dma_entry.update(orig_start, orig_end, start)


def chain_groups(group_list: list[tuple[str, list[str] | str]], sequences: dict[str, Sequence]) -> dict[str, list[str]]:
result = {}
for group_name, sequence_names in group_list:
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ issue. You should always Hard Reset to avoid this issue entirely.
* `remove_stones`: When defined, each gossip stone in the list will be excluded from receiving this hint type. For example, if `ToT (Left)` is inserted into the `remove_stones` list inside the dictionary for `always` hints, then no `always` hint will be placed on `ToT (Left)`.
* `priority_stones`: When defined, gossip stones in this list will be given priority when placing the specified hint type, in the order they're defined. For example, if `ToT (Left)` and `ToT (Right)` are inserted into the `priority_stones` list, in that order, inside the dictionary for `always` hints, the first `always` hint will be placed on `ToT (Left)` and the second `always` hint will be placed on `ToT (Right)`.
* New Dual hint for King Zora checks: Unfreezing him and trading the prescription for an eyeball frog.
* The credits music can now be shuffled into the music pool.
* **Other**
* When picking up a small key, the text box will now inform you how many you've found total.
* The longstanding vanilla bug where using Din's Fire on a white bubble crashes the game has been fixed.
Expand All @@ -165,6 +166,7 @@ issue. You should always Hard Reset to avoid this issue entirely.
* A minor bug related to checking time of day access has been corrected.
* Fix a softlock caused by 8-note Sun's Songs when using `Randomize Ocarina Song Notes`, again.
* Fix pause screen rendering causing graphical issues on some platforms.
* Fix a long-standing bug where certain fanfares kill the currently-playing backgroud music.
* **Hints**
* Fix the cryptic hint for Ganon's Castle Boss Key.
* Fix missing punctuation in dual hints.
Expand Down
19 changes: 19 additions & 0 deletions SettingsList.py
Original file line number Diff line number Diff line change
Expand Up @@ -4552,6 +4552,25 @@ class SettingInfos:
default = False,
)

credits_music = Checkbutton(
gui_text = 'Credits music as BGM',
shared = False,
cosmetic = True,
gui_tooltip = '''\
Include the songs that play when the credits
roll as part of the music pool when
shuffling music.
''',
gui_params = {
"hide_when_disabled": False,
'randomize_key': 'randomize_all_sfx',
'distribution': [
(True, 1),
],
},
default = False,
)

sfx_ocarina = Combobox(
gui_text = 'Ocarina',
shared = False,
Expand Down
Binary file added data/custom_audiobank_index.bin
Binary file not shown.
Loading

0 comments on commit 69c4e08

Please sign in to comment.