From 8616c76adc494fba849c3191906a9651ce7df0ba Mon Sep 17 00:00:00 2001 From: Timothy GFO Date: Mon, 27 Nov 2023 18:53:29 -0400 Subject: [PATCH] Layout overhaul and added button to reset to factory --- README.md | 5 +- mmm-nsf-changer.py | 155 +++++++++++++++++++++++++++++++-------------- 2 files changed, 110 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index ce90b71..6840ebb 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,11 @@ To use it just launch the executable file (if available for your os) or type "py * -NEW- Support for "permanently" replacing a specific song to one of your liking, with restoring capabilities. ## Support -If you have any issues, which is probable, make a gitlab issue. There may be bugs. +If you have any issues make a gitlab issue. There may be bugs. ## Roadmap +* figure out way to spawn popups close to main window +* "now playing" text * ability to preserve changes through Mega Man Maker updates, by using a config file and/or a downloaded zip of the game. * stop using os.path in favour of pathlib * switch to using a config file (or database) for keeping track of which tracks have been changed, that way only having one original_music folder and being able to *show* the user which song you used to replace which file. @@ -31,7 +33,6 @@ If you have any issues, which is probable, make a gitlab issue. There may be bug * add a way to change boss music separate from level music and menu music * add a way to show the available nsf files in the selected folder, like a playlist. * Instead of duplicating a single file a lot of times, maybe I'll implement symlink support. -* add autoupdater?? ## Contributing You can help with the project by testing it and reporting issues, or by making pull requests. Windows testers are especially needed since I don't daily drive Windows. diff --git a/mmm-nsf-changer.py b/mmm-nsf-changer.py index 9ea08a7..624a434 100644 --- a/mmm-nsf-changer.py +++ b/mmm-nsf-changer.py @@ -9,26 +9,52 @@ import requests import base64 import zipfile import io +import threading from packaging import version ##Here goes the actual code + #this checks if the folder structure is correct. It will output a list of the files that we will then use to recreate the structure with a single file def safelist(): safe_files = ['MetalMan - (GB II).nsf', 'IceMan - (GB I).nsf', 'CutMan - (GB I).nsf', 'Neptune - (GB V).nsf', 'GBVWily2.nsf', 'WoodMan - (GB II).nsf', 'Saturn - (GB V).nsf', 'Jupiter - (GB V).nsf', 'Terra - (GB V).nsf', 'Venus - (GB V).nsf', 'GBIIIWily2.nsf', 'AirMan - (GB II).nsf', 'Uranus - (GB V).nsf', 'Pluto - (GB V).nsf', 'GBVWily1.nsf', 'Mercury - (GB V).nsf', 'GBIIWily2.nsf', 'MagnetMan - (GB II).nsf', 'Mars - (GB V).nsf', 'GBIIIWily1.nsf', 'ElecMan - (GB I).nsf', 'GBIWily2.nsf', 'TopMan - (GB II).nsf', 'CrashMan - (GB II).nsf', 'GBIWily1.nsf', 'Punk - (GB III).nsf', 'HardMan - (GB II).nsf', 'NeedleMan - (GB II).nsf', 'FireMan - (GB I).nsf', 'GBIVWily1.nsf', 'GBIIWily1.nsf', 'FreezeMan.nsf', 'JunkMan.nsf', 'SlashMan.nsf', 'CloudMan.nsf', 'SpringMan.nsf', 'Wily4.nsf', 'RobotMuseum.nsf', 'Wily1.nsf', 'Intro.nsf', 'Wily3.nsf', 'ShadeMan.nsf', 'ShadeManAlt.nsf', 'TurboMan.nsf', 'BurstMan.nsf', 'Wily2.nsf', 'WilyTower2.nsf', 'HyperStormH.nsf', 'WilyTower1.nsf', 'WilyTower3.nsf', 'MegaWaterS.nsf', 'WilyTower4.nsf', 'BusterRodG.nsf', 'GravityMan.nsf', 'WaveMan.nsf', 'StoneMan.nsf', 'MM5WilyCirno.nsf', 'MM5Wily.nsf', 'StarMan.nsf', 'NapalmMan.nsf', 'CrystalMan.nsf', 'ProtoCastle.nsf', 'ChargeMan.nsf', 'GyroMan.nsf', 'FlameMan.nsf', 'MrX.nsf', 'YamatoMan.nsf', 'CentaurMan.nsf', 'WindMan.nsf', 'PlantMan.nsf', 'MM6Wily.nsf', 'KnightMan.nsf', 'BlizzardMan.nsf', 'TomahawkMan.nsf', 'MM2Wily2.nsf', 'Crashman.nsf', 'MM2Wily1.nsf', 'MM2Wily6.nsf', 'Metalman.nsf', 'Flashman.nsf', 'Bubbleman.nsf', 'Woodman.nsf', 'Heatman.nsf', 'Quickman.nsf', 'Airman.nsf', 'GameOver.nsf', 'WilyIntro3.nsf', 'StageStart.nsf', 'WilyIntro2.nsf', 'WilyIntro1.nsf', 'Victory.nsf', 'ProtoWhistle.nsf', 'Bombman.nsf', 'MM1Wily1.nsf', 'MM1Wily2.nsf', 'Fireman.nsf', 'Iceman.nsf', 'Cutman.nsf', 'Elecman.nsf', 'PUIntroStage.nsf', 'Timeman.nsf', 'Oilman.nsf', 'Gutsman.nsf', 'FrostMan.nsf', 'GrenadeMan.nsf', 'AquaMan.nsf', 'AstroMan.nsf', 'Wily4.nsf', 'TenguMan(SS).nsf', 'Wily1.nsf', 'IntroStage(Underwater).nsf', 'SwordMan.nsf', 'Wily3.nsf', 'SearchMan.nsf', 'IntroStage.nsf', 'ClownMan.nsf', 'Wily2.nsf', 'TenguMan(PSX).nsf', 'Megaman4.nsf', 'ToadMan.nsf', 'MM4Wily2.nsf', 'RingMan.nsf', 'MM4Wily1.nsf', 'DrillMan.nsf', 'BrightMan.nsf', 'DiveMan.nsf', 'SkullMan.nsf', 'DustMan.nsf', 'Cossack1.nsf', 'PharaohMan.nsf', 'Cossack2.nsf', 'MagnetMan.nsf', 'MM3Wily2.nsf', 'MM3Wily3.nsf', 'SnakeMan.nsf', 'Megaman3.nsf', 'MM3Wily1.nsf', 'GeminiMan.nsf', 'ShadowMan.nsf', 'HardMan.nsf', 'TopMan.nsf', 'NeedleMan.nsf', 'SparkMan.nsf', 'KazeYoTsutaete.nsf', 'MMB_-_King_Nix.nsf', '30XXTitleLooped.nsf', 'FakeMan.nsf', 'PlugMan.nsf', 'GalaxyMan.nsf', 'EndlessAttack.nsf', 'SplashWoman.nsf', 'Wily4.nsf', 'Wily1.nsf', 'MagmaMan.nsf', 'JewelMan.nsf', 'ConcreteMan.nsf', 'Wily3.nsf', 'TornadoMan.nsf', 'Wily2.nsf', 'HornetMan.nsf', 'StrikeMan.nsf', 'Challenges.nsf', 'Wily1Outside.nsf', 'SolarMan.nsf', 'EndlessAttack.nsf', 'Wily4.nsf', 'NitroMan.nsf', 'Wily1Inside.nsf', 'CommandoMan.nsf', 'Punk.nsf', 'Wily5.nsf', 'Wily3.nsf', 'Enker.nsf', 'Ballade.nsf', 'ChillMan.nsf', 'BladeMan.nsf', 'PumpMan.nsf', 'Wily2.nsf', 'SheepMan.nsf', 'MM4.nsf', 'MM&B.nsf', 'MM8Wily.nsf', 'Sunstar - (GB V).nsf', 'MM7WilyCapsule.nsf', 'GBIVWilyBoss.nsf', 'MM10WilyCapsule.nsf', 'MMPUWilyBoss.nsf', 'MM11WilyCapsule.nsf', 'GBIV.nsf', 'MM3.nsf', 'MM&BKingBoss.nsf', 'MM3Wily.nsf', 'MM10WilyBoss.nsf', 'MM10WilyMachine.nsf', 'MM1Wily.nsf', 'MM10.nsf', 'MM2.nsf', 'MM5.nsf', 'BassMM8.nsf', 'MMPUWilyMachine.nsf', 'MM7Wily.nsf', 'MMWilyWars.nsf', 'MM8WoodMan.nsf', 'Duo.nsf', 'MM6Wily.nsf', 'MM11.nsf', 'BassMM7.nsf', 'MM5Wily.nsf', 'MM6.nsf', 'MM8CutMan.nsf', 'BossIntro.nsf', 'MM7.nsf', 'MMPU.nsf', 'MM4Wily.nsf', 'GBI.nsf', 'GBIVBalladeBoss.nsf', 'MM1.nsf', 'MM11WilyBoss.nsf', 'GBV.nsf', 'MM11WilyMachine.nsf', 'Midboss.nsf', 'GBII.nsf', 'MM9.nsf', 'MM8.nsf', 'MM8WilyCapsule.nsf', 'MM9Wily.nsf', 'EditorB.nsf', 'Credits.nsf', 'EditorD.nsf', '30XXTitle.nsf', 'Title.nsf', 'OnlineMenu.nsf', 'Menu.nsf', 'Editor.nsf', 'EditorC.nsf', 'ChallengeCredits.nsf', 'Tutorial.nsf', 'MagicMan.nsf', 'ColdMan.nsf', 'MM&BWily1.nsf', 'MM&BKing1.nsf', 'PirateMan.nsf', 'DynamoMan.nsf', 'GroundMan.nsf', 'AstroMan.nsf', 'Intro.nsf', 'TenguMan.nsf', 'CrystalGate.nsf', 'BurnerMan.nsf', 'BounceMan.nsf', 'FuseMan.nsf', 'TorchMan.nsf', 'Challenges.nsf', 'WilyStage.nsf', 'TundraMan.nsf', 'AcidMan.nsf', 'DrLightTrial.nsf', 'BlockMan.nsf', 'BlastMan.nsf', 'ImpactMan.nsf'] return safe_files -def get_original_songs(): +def changed_nsf_files(megamaker_folder): + megamaker_folder = os.path.abspath(megamaker_folder) + music_folder = os.path.join(megamaker_folder, "original_specific_songs") + file_names = [] + glob_search = os.path.join(music_folder,"*","*.nsf") + file_paths = (glob(glob_search)) + for files in file_paths: + files_no_path = os.path.basename(files) + if files_no_path == 'TMP_BURNER_MAN.nsf': + print("skipping",files_no_path) + elif files_no_path == 'TMP_COLD_MAN.nsf': + print("skipping", files_no_path) + else: + file_names.append(files_no_path) + return file_names + + +def get_original_songs(megamaker_folder): mmm_version = check_version(version=True) + print(mmm_version) parsed_version = mmm_version.replace(".", "_") url = f"https://megamanmaker.com/downloads/MegaManMaker_v{parsed_version}.zip" + print(url) request = requests.get(url) + print("downloaded") zip_file = zipfile.ZipFile(io.BytesIO(request.content)) + print("got zip") for file in zip_file.namelist(): + print(file) if file.startswith('Music/'): - zip_file.extract(file, "original_music") + zip_file.extract(file, megamaker_folder) + window.write_event_value('-THREAD DONE-', True) + return True -app_version = "v1.2" +app_version = "v1.3" def check_if_new_version(): response = requests.get("https://gitlab.com/api/v4/projects/51771052/repository/tags") newest_version = response.json()[0]["name"] @@ -153,6 +179,7 @@ def restore_song(old_song_name, megamaker_folder): # print("Cutman.nsf and Oilman.nsf match in Music folder.") # return False + def recreate_structure(new_nsf, original_paths_list): for path in original_paths_list: if not os.path.exists(os.path.dirname(path)): @@ -208,80 +235,112 @@ def nsf_changer (nsf_path, megamaker_folder): print("nsf changer returning false") return False -sg.theme('LightBlue') +sg.theme('Material1') icon = b"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAArlBMVEUAAAAAAAB5eXmioqIwUYJBksNh0+Oi//MwYUFJomlx45Ki/8s4bQBJqhBx80Gi86I4aQBRogCa6wDL84JJWQCKigDr0yD/85J5QQDDcQD/ogD/26KiMADjUQD/eTD/y7qyEDDbQWH/YbL/uuuaIHnbQcPzYf/jsv9hEKKSQfOicf/Dsv8oALpBQf9Rgv+iuv8gALJBYfthov+S0/95eXmysrLr6+v///8Aaf9DkP8A2fKiAAAAOnRSTlMA////////////////////////////////////////////////////////////////////////////ncmmFQAAAK5JREFUOI21k1sSgCAIRb2rYtz/xpKnpIz1UcyUAkcEldYfpL0DwN8iGRja6g7EgLkix3Jg8ScqAyVxrOJDgIjGhHSQMQw8WwA3+4QBxFoxj8BKSmkMzMXoGZW6a4CzMw0OmJO3I6khkhVA0hBVCNoBuMrhPR4KwKNgZqSAhjZTQmEnaUQcD9Bjz+aXHT+9g3gCbV5LLf8BWw7HR3t/53e/d1bVNhkoGy911kkegQvP3acj3R2TXgAAAABJRU5ErkJggg==" gif = b"R0lGODdhQgAmAHcAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAAACwAAAAAQgAmAIAAAAAAefsCzISPqcvtD6OctNqLs95chg92YgOGT/mNExpArOqhrgzPpW3WznvSHM8AknwbocK4QGKUBybCWYFCDdMV8XhNZpfbZvf5BUjD1fFteA6GqeR2WvtWxxPmHNwux9PdevAc++cVyDYotmZYWJeCaFLGt5i3yON4NvnYwih5aFl5Sdi4ScPZJwjaeWo3qpko2ooKmYmpKutqaruaWou7S/vae4v5ySv8OxxLjFxqPJvMfKxcHN2sK/087XsNnA3r3E29HfzsjS3+rXOOnn5QAAAh+QQJCgAAACwCAAYAPgAeAIAAAAAAefsClYSPqcvtD6OctNqLcw28a9R5W0hy31FaZXoCLLWSrSuPsdm+0y2eusTD+Wqw4OwXCQaOxJ0x1wQ+hyHV9IOEKJlV243bc/IM2QerTH6iG+doYkvrFrtr+JrRli/stXr/T6cGGKaQJ2IYkxa4eDiIg7ii2Mj46LgUN/mFWUl5CSnJqfm56WkJWjpGerqq2go5CmvqSlIAACH5BAkKAAAALAIABgA+AB4AgAAAAAB5+wKthI+pF+0Lo5zTPYqzBrbtDyZdEJbfaKYYqm4s9C5xOYudVIM5c0e724MFZUNaj/XjFEPI4xKRzDQthqT1qaRmL1et0GvTTi9fMhEMdYqxVfbWc+aqzYounbfO39Po8P5NAtjWxyenB1c3B2e3qBiYeBjIKOlY1hiJUykYd2n4N+jZiegnSkmIF2o6kgpa2qrqCjgWOwtr+1r7qruZK6vZC+wYjMn7u0o8zFpsUQAAIfkECQoAAAAsAgAGAD4AHgCAAAAAAHn7AqGEb6GL7Q+jfIvNi3OrSvsPcQFIkmKJAifFpaW4ru4Ht6o9e3WV4K7M2o1uvBzQIewQLbPjJtkrNn1I6FI5LcaszpdtK4wyf99y+DrMWsA7MVbDVsZh7jTcvMbX6vzIvJ809OenJ1g42HWAeFjYF9KIVrcoFZSnxXiZOValKYdpCerZaTgqCTkZSpqKKpoK+Nkaqyr7Oso6i1u7espbGolWAAAh+QQJCgAAACwCAAgAPgAcAIAAAAAAefsCooSPCcGtD6OcqTmKs142bNl5nxKOUGkiaKp27LG+nCXPVx2nObuPvfnbBD/DzPDokiFpkd/y9ngyDCGp6JTEMqvZaJf0rSS5TC0UXPZuydPm+J1GX9htcxtlpdJB8Hm4tcbGF+gXJ0bIpYcogvcH05docwfJ6KhYSHY5uah5pYYZ2cgp6Sm3mUnaqZrKKorqehpbOUo3C2oruwpbpUvZS9tRAAA7" mute_nsf = "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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - +print("Checking Version...") if check_version(): version_color = "black" version_message = f"Works with Mega Man Maker {mmm_version}" else: version_color = "red" version_message = f"Mega Man Maker has been updated to {check_version(version=True)}. \nThis tool works with {mmm_version} and may not work properly. Make an Issue at GitLab." - -layout = [ - [sg.Text("Mega Man Maker NSF Music Changer | Made by Timothy GFO", justification="center")], - [sg.Text("YouTube", enable_events = True, key="-YT-", text_color="red"), sg.Text("GitLab",enable_events = True,key="-GIT-", text_color="purple"), sg.Text("Blog",enable_events = True,key="-SITE-", text_color="blue")], - [sg.Text(version_message, text_color=version_color)], - [sg.Text("Input NSF File:"), sg.Input(sg.user_settings_get_entry('-INPUT_NSF-', ''), key="-IN-"),sg.FileBrowse(file_types=(("Supported Formats",".nsf .spc .vgm .nsfe .gbs .gym .ay .hes .kss .sap"),("NSF Files", "*.nsf*"),("NSFe Files", "*.nsfe*"),("SNES Files", "*.spc*"),("Gameboy Files", "*.gbs*"), ("Sega Genesis VGM", "*.vgm*"),("Sega Genesis GYM", "*.gym*"), ("ZX Spectrum", "*.ay*"), ("TurboGrafx 16", "*.hes*"), ("MSX Home Computer", "*.kss*"), ("Atari Pokey", "*.sap*"),))], - [sg.Text("MegaMaker Folder:"), sg.Input(sg.user_settings_get_entry('-MEGAMAKER_FOLDER-', ''), key="-OUT-"), sg.FolderBrowse()], - [sg.Button("Mute All"), sg.Button("Replace All NSF Music"), sg.Button("Restore All Original Music"),sg.Image(data=gif, key='_IMAGE_')], - [sg.Text("Output NSF File:"),sg.Combo(safelist(),default_value="ClownMan.nsf", key="-DROPDOWN-")], - [sg.Button("Replace Song"), sg.Button("Restore Original Song")], - [sg.Exit(),sg.Button("About")], +print(" done") +title = [ + [sg.Push(),sg.Text("Mega Man Maker NSF Music Changer | Made by Timothy GFO", font=("Any", 12, "bold")),sg.Push()], + [sg.Push(), sg.Text("YouTube", enable_events = True, key="-YT-", text_color="red"), sg.Text("GitLab",enable_events = True,key="-GIT-", text_color="purple"), sg.Text("Blog",enable_events = True,key="-SITE-", text_color="blue"), sg.Push()], + [sg.Push(), sg.Text(version_message, text_color=version_color), sg.Push()], ] +change_all = [ + [sg.Button("Mute All"), sg.Button("Apply Music"), sg.Button("Restore Music")], +] + +change_one = [ + [sg.Text("Output NSF File:"),sg.Combo(safelist(),default_value="ClownMan.nsf", key="-DROPDOWN-"), sg.StatusBar("",size=(15,1), key="-LAST-CHANGED-")], + [sg.Button("Replace Song"), sg.Button("Restore Original Song"), sg.Button("Download and Restore Music")], +] + +layout = [ + [title], + [sg.Text("Input NSF File:"), sg.Input(sg.user_settings_get_entry('-INPUT_NSF-', ''), key="-IN-"),sg.FileBrowse(file_types=(("Supported Formats",".nsf .spc .vgm .nsfe .gbs .gym .ay .hes .kss .sap"),("NSF Files", "*.nsf*"),("NSFe Files", "*.nsfe*"),("SNES Files", "*.spc*"),("Gameboy Files", "*.gbs*"), ("Sega Genesis VGM", "*.vgm*"),("Sega Genesis GYM", "*.gym*"), ("ZX Spectrum", "*.ay*"), ("TurboGrafx 16", "*.hes*"), ("MSX Home Computer", "*.kss*"), ("Atari Pokey", "*.sap*"),))], + [sg.Text("MegaMaker Folder:"), sg.Input(sg.user_settings_get_entry('-MEGAMAKER_FOLDER-', ''), key="-OUT-"), sg.FolderBrowse()], + [sg.TabGroup([[sg.Tab("Play Now", change_all), sg.Tab("Switch a Song", change_one)]]), sg.Image(data=gif, key='_IMAGE_')], + [sg.Exit(),sg.Button("About")], +] how_to_use = "I made this tool to be able to change the music for any Mega Man Maker level while playing the game. It works by replacing every nsf file with a custom one, but while preserving the original folders and file names.\n\nTo use it, just choose a nsf file and then tell the program where you store the *game* folder. That is where the .exe is, not the user folder.\n\nIf you find this useful, you can check out my YouTube Channel or my blog since I will keep making tools like this. Also, if you find any bugs or errors remember to notify me at GitLab by making an Issue." window = sg.Window(f"MMM NSF Music Changer {app_version}", layout) #disclaimer = sg.popup_yes_no('NSF Changer, by Timothy GFO', 'This program is not complete, there WILL be bugs. Use at your own risk.', 'Do you want to continue?') + if check_if_new_version(): sg.popup(f"There is a new update for MMM NSF Changer. Get it at the GitLab repo.") +running = False while True: event,values = window.read(timeout=50) window.set_icon(icon) + window.refresh() if event in (sg.WINDOW_CLOSED,"Exit"): sg.user_settings_set_entry('-INPUT_NSF-', values['-IN-']) sg.user_settings_set_entry('-MEGAMAKER_FOLDER-', values['-OUT-']) break window.Element('_IMAGE_').UpdateAnimation(gif, time_between_frames=100) - if event == "-YT-": - webbrowser.open("https://youtube.com/gamefeveronline") - if event == "-SITE-": - webbrowser.open("https://gamefeveronline.gitlab.io") - if event == "-GIT-": - webbrowser.open("https://gitlab.com/gamefeveronline") - if event == "About": - sg.popup(how_to_use) - if event == "Mute All": - create_mute_file(mute_nsf) - if not nsf_changer(os.path.join(os.path.dirname(__file__), "mmm_nsf_changer_mute.nsf"), values["-OUT-"]): - restore_ogmusic(values["-OUT-"]) + if running: + if event == "-THREAD DONE-": + running = False + sg.PopupAnimated(None) + else: + window.refresh() + sg.popup_animated(sg.DEFAULT_BASE64_LOADING_GIF, message='Loading', time_between_frames=100, location=window.current_location()) + else: + if event == "-YT-": + webbrowser.open("https://youtube.com/gamefeveronline") + if event == "-SITE-": + webbrowser.open("https://gamefeveronline.gitlab.io") + if event == "-GIT-": + webbrowser.open("https://gitlab.com/gamefeveronline") + if event == "About": + sg.popup(how_to_use) + if event == "Mute All": + create_mute_file(mute_nsf) if not nsf_changer(os.path.join(os.path.dirname(__file__), "mmm_nsf_changer_mute.nsf"), values["-OUT-"]): - sg.popup_error("MegaMaker folder is not valid or definitions are out of date.") - if event == "Replace Song": - if values["-DROPDOWN-"] == "": - sg.popup_error('Please select which Output NSF File to replace. If not, use "Replace *All* NSF Music".') - else: - replace_song(values["-IN-"], values["-DROPDOWN-"], values["-OUT-"]) - if event == "Restore Original Song": - if values["-DROPDOWN-"] == "": - sg.popup_error('Please select which Output NSF File to replace. If not, use "Replace *All* NSF Music".') - else: - if restore_song(values["-DROPDOWN-"], values["-OUT-"]) == False: - sg.popup_error("The selected song has not been changed, cannot restore.") - if event == "Replace All NSF Music": - if not nsf_changer(values["-IN-"], values["-OUT-"]): - restore_ogmusic(values["-OUT-"]) + restore_ogmusic(values["-OUT-"]) + if not nsf_changer(os.path.join(os.path.dirname(__file__), "mmm_nsf_changer_mute.nsf"), values["-OUT-"]): + sg.popup_error("MegaMaker folder is not valid or definitions are out of date.") + if event == "Replace Song": + if values["-DROPDOWN-"] == "": + sg.popup_error('Please select which Output NSF File to replace. If not, use "Replace *All* NSF Music".') + else: + replace_song(values["-IN-"], values["-DROPDOWN-"], values["-OUT-"]) + window["-LAST-CHANGED-"].update(values["-DROPDOWN-"]) + if event == "Restore Original Song": + if values["-DROPDOWN-"] == "": + sg.popup_error('Please select which Output NSF File to replace. If not, use "Replace *All* NSF Music".') + else: + if restore_song(values["-DROPDOWN-"], values["-OUT-"]) == False: + sg.popup_error("The selected song has not been changed, cannot restore.") + else: + window["-LAST-CHANGED-"].update("") + if event == "Apply Music": if not nsf_changer(values["-IN-"], values["-OUT-"]): - sg.popup_error("MegaMaker folder is not valid or definitions out of date.") - if event == "Restore All Original Music": - # sg.popup_error("DOESNT WORK EITHER HAHAHAHAHAHAA") - if not restore_ogmusic(values["-OUT-"]): - sg.popup_error("Unexpected folder structure or differing files") + restore_ogmusic(values["-OUT-"]) + if not nsf_changer(values["-IN-"], values["-OUT-"]): + sg.popup_error("MegaMaker folder is not valid or definitions out of date.") + if event == "Restore Music": # Needs testing + # sg.popup_error("DOESNT WORK EITHER HAHAHAHAHAHAA") + if not restore_ogmusic(values["-OUT-"]): + sg.popup_error("Unexpected folder structure or differing files") + if event == "Download and Restore Music": + sg.popup_yes_no("WARNING: This will erase all custom songs.\nDo you want to continue?", location=window.current_location()) + window["-LAST-CHANGED-"].update("") + threading.Thread(target=get_original_songs, args=(values["-OUT-"], ), daemon=True).start() + running = True + #if not restore_ogmusic(values["-OUT-"]): + # sg.popup_error("Unexpected folder structure or differing files") + window.close()