#!/usr/bin/env python3
# SPDX-FileCopyrightText: © 2024 ZeldaRET
# SPDX-License-Identifier: CC0-1.0
#
#   Configures and runs baserom audio extraction
#

import argparse

import version_config

from audio.extraction.audio_extract import extract_audio_for_version, GameVersionInfo
from audio.extraction.disassemble_sequence import MMLVersion, SequenceTableSpec, SqSection

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="baserom audio asset extractor")
    parser.add_argument("-b", "--baserom-segments-dir", required=True, help="Directory of uncompressed ROM segments")
    parser.add_argument("-o", "--output-dir", required=True, help="path to output directory")
    parser.add_argument("-v", "--version", required=True, help="version name")
    parser.add_argument("--read-xml", required=False, action="store_true", help="Read extraction xml files")
    parser.add_argument("--write-xml", required=False, action="store_true", help="Write extraction xml files")
    args = parser.parse_args()
    
    version = args.version

    config = version_config.load_version_config(version)

    code_vram = config.dmadata_segments["code"].vram
    soundfont_table_code_offset = config.variables["gSoundFontTable"] - code_vram
    seq_font_table_code_offset = config.variables["gSequenceFontTable"] - code_vram
    seq_table_code_offset = config.variables["gSequenceTable"] - code_vram
    sample_bank_table_code_offset = config.variables["gSampleBankTable"] - code_vram

    # List any sequences that are "handwritten", we don't extract these by
    # default as we want these checked in for documentation.
    handwritten_sequences = (0, 1, 2, 109)

    # Sequence enum names for extraction purposes.
    seq_enum_names = (
        "NA_BGM_GENERAL_SFX",
        "NA_BGM_NATURE_AMBIENCE",
        "NA_BGM_FIELD_LOGIC",
        "NA_BGM_FIELD_INIT",
        "NA_BGM_FIELD_DEFAULT_1",
        "NA_BGM_FIELD_DEFAULT_2",
        "NA_BGM_FIELD_DEFAULT_3",
        "NA_BGM_FIELD_DEFAULT_4",
        "NA_BGM_FIELD_DEFAULT_5",
        "NA_BGM_FIELD_DEFAULT_6",
        "NA_BGM_FIELD_DEFAULT_7",
        "NA_BGM_FIELD_DEFAULT_8",
        "NA_BGM_FIELD_DEFAULT_9",
        "NA_BGM_FIELD_DEFAULT_A",
        "NA_BGM_FIELD_DEFAULT_B",
        "NA_BGM_FIELD_ENEMY_INIT",
        "NA_BGM_FIELD_ENEMY_1",
        "NA_BGM_FIELD_ENEMY_2",
        "NA_BGM_FIELD_ENEMY_3",
        "NA_BGM_FIELD_ENEMY_4",
        "NA_BGM_FIELD_STILL_1",
        "NA_BGM_FIELD_STILL_2",
        "NA_BGM_FIELD_STILL_3",
        "NA_BGM_FIELD_STILL_4",
        "NA_BGM_DUNGEON",
        "NA_BGM_KAKARIKO_ADULT",
        "NA_BGM_ENEMY",
        "NA_BGM_BOSS",
        "NA_BGM_INSIDE_DEKU_TREE",
        "NA_BGM_MARKET",
        "NA_BGM_TITLE",
        "NA_BGM_LINK_HOUSE",
        "NA_BGM_GAME_OVER",
        "NA_BGM_BOSS_CLEAR",
        "NA_BGM_ITEM_GET",
        "NA_BGM_OPENING_GANON",
        "NA_BGM_HEART_GET",
        "NA_BGM_OCA_LIGHT",
        "NA_BGM_JABU_JABU",
        "NA_BGM_KAKARIKO_KID",
        "NA_BGM_GREAT_FAIRY",
        "NA_BGM_ZELDA_THEME",
        "NA_BGM_FIRE_TEMPLE",
        "NA_BGM_OPEN_TRE_BOX",
        "NA_BGM_FOREST_TEMPLE",
        "NA_BGM_COURTYARD",
        "NA_BGM_GANON_TOWER",
        "NA_BGM_LONLON",
        "NA_BGM_GORON_CITY",
        "NA_BGM_FIELD_MORNING",
        "NA_BGM_SPIRITUAL_STONE",
        "NA_BGM_OCA_BOLERO",
        "NA_BGM_OCA_MINUET",
        "NA_BGM_OCA_SERENADE",
        "NA_BGM_OCA_REQUIEM",
        "NA_BGM_OCA_NOCTURNE",
        "NA_BGM_MINI_BOSS",
        "NA_BGM_SMALL_ITEM_GET",
        "NA_BGM_TEMPLE_OF_TIME",
        "NA_BGM_EVENT_CLEAR",
        "NA_BGM_KOKIRI",
        "NA_BGM_OCA_FAIRY_GET",
        "NA_BGM_SARIA_THEME",
        "NA_BGM_SPIRIT_TEMPLE",
        "NA_BGM_HORSE",
        "NA_BGM_HORSE_GOAL",
        "NA_BGM_INGO",
        "NA_BGM_MEDALLION_GET",
        "NA_BGM_OCA_SARIA",
        "NA_BGM_OCA_EPONA",
        "NA_BGM_OCA_ZELDA",
        "NA_BGM_OCA_SUNS",
        "NA_BGM_OCA_TIME",
        "NA_BGM_OCA_STORM",
        "NA_BGM_NAVI_OPENING",
        "NA_BGM_DEKU_TREE_CS",
        "NA_BGM_WINDMILL",
        "NA_BGM_HYRULE_CS",
        "NA_BGM_MINI_GAME",
        "NA_BGM_SHEIK",
        "NA_BGM_ZORA_DOMAIN",
        "NA_BGM_APPEAR",
        "NA_BGM_ADULT_LINK",
        "NA_BGM_MASTER_SWORD",
        "NA_BGM_INTRO_GANON",
        "NA_BGM_SHOP",
        "NA_BGM_CHAMBER_OF_SAGES",
        "NA_BGM_FILE_SELECT",
        "NA_BGM_ICE_CAVERN",
        "NA_BGM_DOOR_OF_TIME",
        "NA_BGM_OWL",
        "NA_BGM_SHADOW_TEMPLE",
        "NA_BGM_WATER_TEMPLE",
        "NA_BGM_BRIDGE_TO_GANONS",
        "NA_BGM_SEAL_OF_SAGES",
        "NA_BGM_GERUDO_VALLEY",
        "NA_BGM_POTION_SHOP",
        "NA_BGM_KOTAKE_KOUME",
        "NA_BGM_ESCAPE",
        "NA_BGM_UNDERGROUND",
        "NA_BGM_GANONDORF_BOSS",
        "NA_BGM_GANON_BOSS",
        "NA_BGM_OCARINA_OF_TIME",
        "NA_BGM_STAFF_1",
        "NA_BGM_STAFF_2",
        "NA_BGM_STAFF_3",
        "NA_BGM_STAFF_4",
        "NA_BGM_FIRE_BOSS",
        "NA_BGM_TIMED_MINI_GAME",
        "NA_BGM_CUTSCENE_EFFECTS",
    )

    # Some bugged soundfonts report the wrong samplebank. Map them to the correct samplebank for proper sample discovery.
    fake_banks = { 37 : 2 }

    # Some audiotable banks have a buffer clearing bug. Indicate which banks suffer from this.
    audiotable_buffer_bugs = (0,)

    # Tables have no clear start and end in a sequence. Mark the locations of all tables that appear in sequences.
    seq_disas_tables = {
        # sequence number : (spec, ...)
        0 : (
                SequenceTableSpec(0x00E1, 128, 0, SqSection.CHAN),
                SequenceTableSpec(0x0EE3,  80, 0, SqSection.CHAN),
                SequenceTableSpec(0x16D5, 248, 0, SqSection.CHAN),
                SequenceTableSpec(0x315E, 499, 0, SqSection.CHAN),
                SequenceTableSpec(0x5729,  72, 0, SqSection.CHAN),
                SequenceTableSpec(0x5EE5,   8, 0, SqSection.CHAN),
                SequenceTableSpec(0x5FF2, 128, 0, SqSection.CHAN),
            ),
        1 : (
                SequenceTableSpec(0x0192, 20, 0, SqSection.LAYER),
                SequenceTableSpec(0x01BA, 20, 0, SqSection.LAYER),
                SequenceTableSpec(0x01E2, 20, 0, SqSection.LAYER),
                SequenceTableSpec(0x020A, 20, 0, SqSection.LAYER),
                SequenceTableSpec(0x0232, 20, 1, SqSection.LAYER),
                SequenceTableSpec(0x025A, 20, 1, SqSection.LAYER),
                SequenceTableSpec(0x0282, 20, 1, SqSection.LAYER),
            ),
        2 : (
                SequenceTableSpec(0x00BC, 2, 0, SqSection.SEQ),
                SequenceTableSpec(0x00C0, 2, 0, SqSection.ARRAY),
            ),
        109 : (
                SequenceTableSpec(0x0646, 16, 0, SqSection.CHAN),
            ),
    }

    version_info = GameVersionInfo(version,
                                   MMLVersion.OOT,
                                   soundfont_table_code_offset,
                                   seq_font_table_code_offset,
                                   seq_table_code_offset,
                                   sample_bank_table_code_offset,
                                   seq_enum_names,
                                   handwritten_sequences,
                                   fake_banks,
                                   audiotable_buffer_bugs,
                                   seq_disas_tables)

    extract_audio_for_version(version_info, args.output_dir, args.baserom_segments_dir, args.read_xml, args.write_xml)
