# OpenMFOR # credits manually reinstated due to the comments being lost from the object code decompilation # Original release is Copyright (C) 2022 Kazuto88 # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # Source Generated with Decompyle++ # File: GUI.pyc (Python 3.8) import PySimpleGUI as ui import zlib import time import threading import os ui.theme('SystemDefault') tt_race = ' Generating a race seed will not generate a spoiler log. ' tt_createpatch = ' Automatically creates a .bps patch after generating a randomized game, so you can easily share with others. ' tt_difficulty = ' Higher difficulty means harder tricks. Difficulty 0 means no tricks are expected outside of vanilla strategies. ' tt_itempool = ' Limit where important items can be placed. If checked, major upgrades will only be in Data rooms, \n at bosses, or at vanilla E-tank locations. If unchecked, any item can be anywhere within logic. ' tt_missileswithupgrades = ' If checked, collecting any major Missile item will enable Missiles. Logic will account for this setting. ' tt_pbswithoutbombs = ' If checked, Power Bombs can be used without having regular Bombs. Logic will account for this setting. ' tt_damageruns = ' Allow logic to require Samus to run through damaging environments to acquire important items. \n Examples include heated rooms, electrified water, and lava. ' tt_splitsecurity = ' If checked, each door color must be unlocked independently. \n If unchecked, unlocking higher security levels will unlock all security levels below it. \n E.G.: unlocking Level 2 (Green) doors will also unlock Level 1 (Blue) doors. ' tt_SectorShuffle = ' Randomly shuffle the arrangement of the Sectors. ' tt_HideItems = ' Make all items appear as ? tanks. ' generating = False def fileHash(fileName): with open(fileName, 'rb') as fh: hash = 0 while True: s = fh.read(65536) if not s: break hash = zlib.crc32(s, hash) return hash & 0xFFFFFFFF def rando_thread(window = None, values = None): global fileName, basegame, failedgen, randoerror, generating, finishGenerating values.update({ 'Difficulty': int(values.get('Difficulty')) }) if values['Num']: values.update({ 'Num': int(values.get('Num')) }) else: values.update({ 'Num': 1 }) if values['Num'] < 1: values.update({ 'Num': 1 }) values.pop(0) failedgen = False randoerror = False generating = True from Randomizer import start_randomizer if values['Debug']: fileName = start_randomizer(basegame, values) else: # FIXME: let it explode #try: fileName = start_randomizer(basegame, values) # finally: # pass #except SystemExit: # failedgen = True #except: # print('An error occurred, no game was generated.') # randoerror = True generating = False finishGenerating = True def main_window(debug): global fileName, basegame, generating, finishGenerating itemPool = [ [ ui.Text('Charge Beam'), ui.Radio('Shuffled', 'radioChargeBeam', default=True), ui.Radio('Starting', 'radioChargeBeam'), ui.Radio('Disabled', 'radioChargeBeam')], [ ui.Text('Wide Beam'), ui.Radio('Shuffled', 'radioWideBeam', default=True), ui.Radio('Starting', 'radioWideBeam'), ui.Radio('Disabled', 'radioWideBeam')], [ ui.Text('Plasma Beam'), ui.Radio('Shuffled', 'radioPlasmaBeam', default=True), ui.Radio('Starting', 'radioPlasmaBeam'), ui.Radio('Disabled', 'radioPlasmaBeam')], [ ui.Text('Wave Beam'), ui.Radio('Shuffled', 'radioWaveBeam', default=True), ui.Radio('Starting', 'radioWaveBeam'), ui.Radio('Disabled', 'radioWaveBeam')], [ ui.Text('Ice Beam'), ui.Radio('Shuffled', 'radioIceBeam', default=True), ui.Radio('Starting', 'radioIceBeam'), ui.Radio('Disabled', 'radioIceBeam')], [ ui.Text('Missile Data'), ui.Radio('Shuffled', 'radioMissileData', default=True), ui.Radio('Starting', 'radioMissileData'), ui.Radio('Disabled', 'radioMissileData')], [ ui.Text('Super Missile Data'), ui.Radio('Shuffled', 'radioSuperMissile', default=True), ui.Radio('Starting', 'radioSuperMissile'), ui.Radio('Disabled', 'radioSuperMissile')], [ ui.Text('Ice Missile Data'), ui.Radio('Shuffled', 'radioIceMissile', default=True), ui.Radio('Starting', 'radioIceMissile'), ui.Radio('Disabled', 'radioIceMissile')], [ ui.Text('Diffusion Data'), ui.Radio('Shuffled', 'radioDiffusion', default=True), ui.Radio('Starting', 'radioDiffusion'), ui.Radio('Disabled', 'radioDiffusion')], [ ui.Text('Bombs'), ui.Radio('Shuffled', 'radioBombs', default=True), ui.Radio('Starting', 'radioBombs'), ui.Radio('Disabled', 'radioBombs')], [ ui.Text('Power Bomb Data'), ui.Radio('Shuffled', 'radioPowerBombData', default=True), ui.Radio('Starting', 'radioPowerBombData'), ui.Radio('Disabled', 'radioPowerBombData')], [ ui.Text('Hi-Jump Boots'), ui.Radio('Shuffled', 'radioHiJump', default=True), ui.Radio('Starting', 'radioHiJump'), ui.Radio('Disabled', 'radioHiJump')], [ ui.Text('Speed Booster'), ui.Radio('Shuffled', 'radioSpeedBooster', default=True), ui.Radio('Starting', 'radioSpeedBooster'), ui.Radio('Disabled', 'radioSpeedBooster')], [ ui.Text('Space Jump'), ui.Radio('Shuffled', 'radioSpaceJump', default=True), ui.Radio('Starting', 'radioSpaceJump'), ui.Radio('Disabled', 'radioSpaceJump')], [ ui.Text('Screw Attack'), ui.Radio('Shuffled', 'radioScrewAttack', default=True), ui.Radio('Starting', 'radioScrewAttack'), ui.Radio('Disabled', 'radioScrewAttack')], [ ui.Text('Varia Suit'), ui.Radio('Shuffled', 'radioVariaSuit', default=True), ui.Radio('Starting', 'radioVariaSuit'), ui.Radio('Disabled', 'radioVariaSuit')], [ ui.Text('Gravity Suit'), ui.Radio('Shuffled', 'radioGravitySuit', default=True), ui.Radio('Starting', 'radioGravitySuit'), ui.Radio('Disabled', 'radioGravitySuit')], [ ui.Text('Morph Ball'), ui.Radio('Shuffled', 'radioMorphBall', default=True), ui.Radio('Starting', 'radioMorphBall'), ui.Radio('Disabled', 'radioMorphBall')], [ ui.Text('Blue Doors (Level 1)'), ui.Radio('Standard', 'radioBlueDoors', default=True), ui.Radio('Starting', 'radioBlueDoors'), ui.Radio('Shuffled', 'radioBlueDoors')], [ ui.Text('Green Doors (Level 2)'), ui.Radio('Standard', 'radioGreenDoors', default=True), ui.Radio('Starting', 'radioGreenDoors'), ui.Radio('Shuffled', 'radioGreenDoors')], [ ui.Text('Yellow Doors (Level 3)'), ui.Radio('Standard', 'radioYellowDoors', default=True), ui.Radio('Starting', 'radioYellowDoors'), ui.Radio('Shuffled', 'radioYellowDoors')], [ ui.Text('Red Doors (Level 4)'), ui.Radio('Standard', 'radioRedDoors', default=True), ui.Radio('Starting', 'radioRedDoors'), ui.Radio('Shuffled', 'radioRedDoors')]] settings = [ [ ui.Text('Difficulty'), ui.Slider(range=(0, 5), orientation='h', tooltip=tt_difficulty, key='Difficulty')], [ ui.Checkbox(text='Major/minor item split', key='MajorMinor', tooltip=tt_itempool)], [ ui.Checkbox(text='Missile upgrades enable Missiles', key='MissilesWithoutMainData', tooltip=tt_missileswithupgrades)], [ ui.Checkbox(text='Enable Power Bombs without Bombs', key='PowerBombsWithoutBombs', tooltip=tt_pbswithoutbombs)], [ ui.Checkbox(text='Damage runs', key='DamageRuns', tooltip=tt_damageruns)], [ ui.Checkbox(text='Split security levels', key='SplitSecurity', tooltip=tt_splitsecurity)], [ ui.Checkbox(text='Sector Shuffle', key='SectorShuffle', tooltip=tt_SectorShuffle)], [ ui.Checkbox(text='Hide item graphics', key='HideItems', tooltip=tt_HideItems)], [ ui.Checkbox(text='Race seed', key='RaceSeed', tooltip=tt_race)]] tabLayout = [ [ ui.TabGroup([ [ ui.Tab('Logic', settings)]], tab_location='topleft')]] layout = [ [ ui.Text('Seed value'), ui.Input(key='Seed')], [ tabLayout], [ ui.Text('Number of Seeds to generate:'), ui.Input(key='Num', size=5, justification='center', enable_events=True), ui.Push(), ui.Checkbox(text='Create patch', key='Patch', tooltip=tt_createpatch), ui.Button(button_text='Generate', bind_return_key=True)]] window = ui.Window('Open Metroid Fusion Open Randomizer', layout) fileName = str() finishGenerating = False oldNum = str() while True: (event, values) = window.read() if event == ui.WINDOW_CLOSED: break if event == 'Num': if len(values['Num']) > 3: window['Num'].update(oldNum) for x in range(4): if x < len(values['Num']): if values['Num'][x] not in '0123456789': window['Num'].update(oldNum) break else: oldNum = values['Num'] if event == 'Generate': basegame = ui.popup_get_file('Choose base game', no_titlebar=True, file_types=[('GBA File', '*.gba')], history=True, history_setting_filename=os.path.join('.', 'settings.json')) if basegame == '': ui.popup('Please select a Metroid Fusion (U) rom.', title='No source rom selected') if basegame != None and basegame != '': checksum = fileHash(basegame) if checksum != 1819625372: ui.popup('Only Metroid Fusion (U) is supported.\nCheck the CRC32 value: it should be 6C75479C', title='Bad Checksum') else: values.update({ 'Debug': debug }) threading.Thread(target=rando_thread, args=[window, values], daemon=True).start() window['Difficulty'].update(disabled=True) window['MajorMinor'].update(disabled=True) window['MissilesWithoutMainData'].update(disabled=True) window['PowerBombsWithoutBombs'].update(disabled=True) window['DamageRuns'].update(disabled=True) window['SplitSecurity'].update(disabled=True) window['SectorShuffle'].update(disabled=True) window['HideItems'].update(disabled=True) window['Seed'].update(disabled=True) window['RaceSeed'].update(disabled=True) window['Num'].update(disabled=True) window['Patch'].update(disabled=True) window['Generate'].update(disabled=True) while generating: ui.popup_animated(ui.DEFAULT_BASE64_LOADING_GIF, 'Generating game, please wait...', time_between_frames=20) window.Refresh() if finishGenerating: ui.popup_animated(None) if failedgen: ui.popup('Could not generate a game with the current settings. Try changing your settings.', title='Metroid Fusion Open Randomizer') elif randoerror: ui.popup('An error occurred, no game was generated.', title='Error') elif ui.Input.get(window['Num']) != '': if int(ui.Input.get(window['Num'])) > 1: ui.popup('Multiple games have been added to the seeds folder.', title='Success!') else: ui.popup('{}\nhas been added to the seeds folder.'.format(fileName), title='Success!') else: ui.popup('{}\nhas been added to the seeds folder.'.format(fileName), title='Success!') window['Difficulty'].update(disabled=False) window['MajorMinor'].update(disabled=False) window['MissilesWithoutMainData'].update(disabled=False) window['PowerBombsWithoutBombs'].update(disabled=False) window['DamageRuns'].update(disabled=False) window['SplitSecurity'].update(disabled=False) window['SectorShuffle'].update(disabled=False) window['HideItems'].update(disabled=False) window['Seed'].update(disabled=False) window['RaceSeed'].update(disabled=False) window['Num'].update(disabled=False) window['Patch'].update(disabled=False) window['Generate'].update(disabled=False) finishGenerating = False window.close()