import sys, os

# now that we're in directory 'tools/' we have to update sys.path
sys.path.append(os.path.dirname(sys.path[0]))

from graph.varia.graph_locations import locations as graphLocations
from rom.romloader import RomLoader

romLoader = RomLoader.factory(sys.argv[1], None)
romLoader.readNothingId()
majorsSplit = romLoader.assignItems(graphLocations)
for loc in graphLocations:
    print("{}: {}".format(loc.Name, loc.itemName))

Ejemplo n.º 2
0
#!/usr/bin/python3

from rom.romloader import RomLoader
from graph.graph_locations import locations
import os.path
import sys

# generate .json for a rom
if __name__ == "__main__":

    if len(sys.argv) == 2:
        romFileName = sys.argv[1]
    else:
        print("missing param: rom file")
        sys.exit(0)

    splited = os.path.splitext(romFileName)
    jsonFileName = splited[0] + '.json'

    romLoader = RomLoader.factory(romFileName)
    romLoader.assignItems(locations)
    romLoader.dump(jsonFileName)
Ejemplo n.º 3
0
    def loadRom(self, rom, interactive=False, magic=None, startLocation=None):
        self.scavengerOrder = []
        self.plandoScavengerOrder = []
        # startLocation param is only use for seedless
        if rom == None:
            # TODO::add a --logic parameter for seedless
            Logic.factory('vanilla')
            self.romFileName = 'seedless'
            self.majorsSplit = 'Full'
            self.masterMajorsSplit = 'Full'
            self.areaRando = True
            self.bossRando = True
            self.escapeRando = False
            self.escapeTimer = "03:00"
            self.startLocation = startLocation
            RomPatches.setDefaultPatches(startLocation)
            self.startArea = getAccessPoint(startLocation).Start['solveArea']
            # in seedless load all the vanilla transitions
            self.areaTransitions = vanillaTransitions[:]
            self.bossTransitions = vanillaBossesTransitions[:]
            self.escapeTransition = [vanillaEscapeTransitions[0]]
            # in seedless we allow mixing of area and boss transitions
            self.hasMixedTransitions = True
            self.curGraphTransitions = self.bossTransitions + self.areaTransitions + self.escapeTransition
            self.locations = Logic.locations
            for loc in self.locations:
                loc.itemName = 'Nothing'
            # set doors related to default patches
            DoorsManager.setDoorsColor()
            self.doorsRando = False
            self.hasNothing = False
            self.objectives.setVanilla()
            self.tourian = 'Vanilla'
        else:
            self.romFileName = rom
            self.romLoader = RomLoader.factory(rom, magic)
            Logic.factory(self.romLoader.readLogic())
            self.locations = Logic.locations
            (self.majorsSplit,
             self.masterMajorsSplit) = self.romLoader.assignItems(
                 self.locations)
            (self.startLocation, self.startArea,
             startPatches) = self.romLoader.getStartAP()
            if not GraphUtils.isStandardStart(
                    self.startLocation) and self.majorsSplit != 'Full':
                # update major/chozo locs in non standard start
                self.romLoader.updateSplitLocs(self.majorsSplit,
                                               self.locations)
            (self.areaRando, self.bossRando, self.escapeRando, hasObjectives,
             self.tourian) = self.romLoader.loadPatches()
            RomPatches.ActivePatches += startPatches
            self.escapeTimer = self.romLoader.getEscapeTimer()
            self.doorsRando = self.romLoader.loadDoorsColor()
            self.hasNothing = self.checkLocsForNothing()
            if self.majorsSplit == 'Scavenger':
                self.scavengerOrder = self.romLoader.loadScavengerOrder(
                    self.locations)
            if hasObjectives:
                self.romLoader.loadObjectives(self.objectives)
            else:
                if self.majorsSplit == "Scavenger":
                    self.objectives.setScavengerHunt()
                    self.objectives.tourianRequired = not self.romLoader.hasPatch(
                        'Escape_Trigger')
                else:
                    self.objectives.setVanilla()
            self.majorUpgrades = self.romLoader.loadMajorUpgrades()
            self.splitLocsByArea = self.romLoader.getSplitLocsByArea(
                self.locations)
            self.objectives.setSolverMode(self)

            if interactive == False:
                print(
                    "ROM {} majors: {} area: {} boss: {} escape: {} patches: {} activePatches: {}"
                    .format(rom, self.majorsSplit, self.areaRando,
                            self.bossRando, self.escapeRando,
                            sorted(self.romLoader.getPatches()),
                            sorted(RomPatches.ActivePatches)))
            else:
                print(
                    "majors: {} area: {} boss: {} escape: {} activepatches: {}"
                    .format(self.majorsSplit, self.areaRando,
                            self.bossRando, self.escapeRando,
                            sorted(RomPatches.ActivePatches)))

            (self.areaTransitions, self.bossTransitions, self.escapeTransition,
             self.hasMixedTransitions) = self.romLoader.getTransitions(
                 self.tourian)
            if interactive == True and self.debug == False:
                # in interactive area mode we build the graph as we play along
                if self.areaRando == True and self.bossRando == True:
                    self.curGraphTransitions = []
                elif self.areaRando == True:
                    self.curGraphTransitions = self.bossTransitions[:]
                elif self.bossRando == True:
                    self.curGraphTransitions = self.areaTransitions[:]
                else:
                    self.curGraphTransitions = self.bossTransitions + self.areaTransitions
                if self.escapeRando == False:
                    self.curGraphTransitions += self.escapeTransition
            else:
                self.curGraphTransitions = self.bossTransitions + self.areaTransitions + self.escapeTransition

        self.smbm = SMBoolManager()
        self.buildGraph()

        # store at each step how many locations are available
        self.nbAvailLocs = []

        if self.log.getEffectiveLevel() == logging.DEBUG:
            self.log.debug("Display items at locations:")
            for loc in self.locations:
                self.log.debug('{:>50}: {:>16}'.format(loc.Name, loc.itemName))
    def loadRom(self, rom, interactive=False, magic=None, startAP=None):
        # startAP param is only use for seedless
        if rom == None:
            # TODO::add a --logic parameter for seedless
            Logic.factory('varia')
            self.romFileName = 'seedless'
            self.majorsSplit = 'Full'
            self.areaRando = True
            self.bossRando = True
            self.escapeRando = False
            self.escapeTimer = "03:00"
            self.startAP = startAP
            RomPatches.setDefaultPatches(startAP)
            self.startArea = getAccessPoint(startAP).Start['solveArea']
            # in seedless load all the vanilla transitions
            self.areaTransitions = vanillaTransitions[:]
            self.bossTransitions = vanillaBossesTransitions[:]
            self.escapeTransition = [vanillaEscapeTransitions[0]]
            # in seedless we allow mixing of area and boss transitions
            self.hasMixedTransitions = True
            self.curGraphTransitions = self.bossTransitions + self.areaTransitions + self.escapeTransition
            self.locations = Logic.locations
            for loc in self.locations:
                loc.itemName = 'Nothing'
            # set doors related to default patches
            DoorsManager.setDoorsColor()
            self.doorsRando = False
        else:
            self.romFileName = rom
            self.romLoader = RomLoader.factory(rom, magic)
            Logic.factory(self.romLoader.readLogic())
            self.romLoader.readNothingId()
            self.locations = Logic.locations
            self.majorsSplit = self.romLoader.assignItems(self.locations)
            (self.startAP, self.startArea,
             startPatches) = self.romLoader.getStartAP()
            (self.areaRando, self.bossRando,
             self.escapeRando) = self.romLoader.loadPatches()
            RomPatches.ActivePatches += startPatches
            self.escapeTimer = self.romLoader.getEscapeTimer()
            self.doorsRando = self.romLoader.loadDoorsColor()

            if interactive == False:
                print(
                    "ROM {} majors: {} area: {} boss: {} escape: {} patches: {} activePatches: {}"
                    .format(rom, self.majorsSplit, self.areaRando,
                            self.bossRando, self.escapeRando,
                            sorted(self.romLoader.getPatches()),
                            sorted(RomPatches.ActivePatches)))
            else:
                print(
                    "majors: {} area: {} boss: {} escape: {} activepatches: {}"
                    .format(self.majorsSplit, self.areaRando,
                            self.bossRando, self.escapeRando,
                            sorted(RomPatches.ActivePatches)))

            (self.areaTransitions, self.bossTransitions, self.escapeTransition,
             self.hasMixedTransitions) = self.romLoader.getTransitions()
            if interactive == True and self.debug == False:
                # in interactive area mode we build the graph as we play along
                if self.areaRando == True and self.bossRando == True:
                    self.curGraphTransitions = []
                elif self.areaRando == True:
                    self.curGraphTransitions = self.bossTransitions[:]
                elif self.bossRando == True:
                    self.curGraphTransitions = self.areaTransitions[:]
                else:
                    self.curGraphTransitions = self.bossTransitions + self.areaTransitions
                if self.escapeRando == False:
                    self.curGraphTransitions += self.escapeTransition
            else:
                self.curGraphTransitions = self.bossTransitions + self.areaTransitions + self.escapeTransition

        self.smbm = SMBoolManager()
        self.areaGraph = AccessGraph(Logic.accessPoints,
                                     self.curGraphTransitions)

        # store at each step how many locations are available
        self.nbAvailLocs = []

        if self.log.getEffectiveLevel() == logging.DEBUG:
            self.log.debug("Display items at locations:")
            for loc in self.locations:
                self.log.debug('{:>50}: {:>16}'.format(loc.Name, loc.itemName))
Ejemplo n.º 5
0
    def __init__(self, romPatcher, settings, sprite):
        self.logger = utils.log.get('Palette')

        self.romPatcher = romPatcher
        if sprite is not None:
            palettes.update(sprite_palettes[sprite])
        self.romLoader = RomLoader.factory(palettes)
        self.palettesROM = self.romLoader.getROM()
        self.outFile = romPatcher.romFile

        self.max_degree = settings["max_degree"]
        self.min_degree = settings["min_degree"]
        self.invert = settings["invert"]

        #boss_tileset_palettes = [0x213510,0x213798,0x213A2C,0x213BC1]
        #boss_pointer_addresses = [0x7E792,0x7E79B,0x7E7A4,0x7E726]
        #gray doors + hud elements [0x28,0x2A,0x2C,0x2E]
        self.tileset_palette_offsets = [0x212D7C,0x212E5D,0x212F43,0x213015,0x2130E7,0x2131A6,0x213264,0x21335F,0x213447,0x2135E4,0x2136BB,0x21383C,0x21392E,0x213AED,0x213BC1,0x214104,0x2141E3,0x213C9C,0x213D7B,0x213E58,0x213F3D,0x214021,0x213510,0x213798,0x213A2C]
        self.bluedoor_bytes = [0x62,0x64,0x66]
        self.palette_single_bytes = [0x08,0x0A,0x0C,0x0E,0x48,0x4A,0x4C,0x4E,0x50,0x52,0x54,0x56,0x58,0x5A,0x68,0x6A,0x6C,0x6E,0x70,0x72,0x74,0x76,0x78,0x7A]  

        #replaced crateria $00 with $01 pointer for nicer colors on surface crateria (was [0x7E6A8,0x7E6B1,[...] before the change)
        self.pointer_addresses = [0x7E6A8,0x7E6B1,0x7E6BA,0x7E6C3,0x7E6CC,0x7E6D5,0x7E6DE,0x7E6E7,0x7E6F0,0x7E6F9,0x7E702,0x7E70B,0x7E714,0x7E71D,0x7E726,0x7E72F,0x7E738,0x7E765,0x7E76E,0x7E777,0x7E780,0x7E789,0x7E792,0x7E79B,0x7E7A4]
        self.pointers_to_insert = []


        #Fx1 palettes and the length of each individual color palette
        #Ridley room fade-in
        self.fx1_palettes_ri = [0x132509]
        self.fx1_length_ri = [0xD1]
        #Brinstar blue glow
        self.fx1_palettes_gb = [0x6ED9F,0x6EDA9,0x6EDB3,0x6EDBD,0x6EDC7,0x6EDD1,0x6EDDB,0x6EDE5,0x6EDEF,0x6EDF9,0x6EE03,0x6EE0D,0x6EE17,0x6EE21]
        self.fx1_length_gb = [0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02]
        #Red brinstar glow purple
        self.fx1_palettes_rb = [0x6EEDD,0x6EEF1,0x6EF05,0x6EF19,0x6EF2D,0x6EF41,0x6EF55,0x6EF69,0x6EF7D,0x6EF91,0x6EFA5,0x6EFB9,0x6EFCD,0x6EFE1]
        self.fx1_length_rb = [0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07]
        #Wrecked Ship green glow
        self.fx1_palettes_ws = [0x6EAE8,0x6EAF0,0x6EAF8,0x6EB00,0x6EB08,0x6EB10,0x6EB18,0x6EB20,0x13CA61]
        self.fx1_length_ws = [0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x6F]
        #Crateria pulse red, 
        self.fx1_palettes_cr = [0x6FD03,0x6FD15,0x6FD27,0x6FD39,0x6FD4B,0x6FD5D,0x6FD6F,0x6FD81,0x6FD93,0x6FDA5,0x6FDB7,0x6FDC9,0x6FDDB,0x6FDED]
        self.fx1_length_cr = [0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06]
        #Tourian slow pulse red/blue,
        self.fx1_palettes_tr = [0x6F640,0x6F656,0x6F66C,0x6F682,0x6F698,0x6F6AE,0x6F6C4,0x6F6DA,0x6F6F0,0x6F706,0x6F71C,0x6F7AF,0x6F7BF,0x6F7CF,0x6F7DF,0x6F7EF,0x6F7FF,0x6F80F,0x6F81F,0x6F82F,0x6F83F,0x6F84F,0x6F85F,0x6F86F,0x6F87F,0x6F94F,0x6F963,0x6F977,0x6F98B,0x6F99F,0x6F9B3,0x6F9C7,0x6F9DB,0x6F9EF,0x6FA03,0x6FA17,0x6FA2B,0x6FA3F,0x6FA53,0x6F897,0x6F8A3,0x6F8AF,0x6F8BB,0x6F8C7,0x6F8D3,0x6F8DF,0x6F8EB,0x6F8F7,0x6F903,0x6F90F,0x6F91B,0x6F927,0x6F933]
        self.fx1_length_tr = [0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03]
        #Maridia quicksand etc.
        self.fx1_palettes_ma = [0x6F4EF,0x6F503,0x6F517,0x6F52B,0x6F547,0x6F553,0x6F55F,0x6F56B,0x6F57F,0x6F593,0x6F5A7,0x6F5BB,0x6F5CF,0x6F5E3,0x6F5F7,0x6F60B]
        self.fx1_length_ma = [0x07,0x07,0x07,0x07,0x03,0x03,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07]
        #Lantern glow
        self.fx1_palettes_lanterns = [0x6EFFD,0x6F00B,0x6F019,0x6F027,0x6F035,0x6F043,0x6F054,0x6F062,0x6F070,0x6F07E]
        self.fx1_length_lanterns = [0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02]

        #this isn't implemented, the other elevator colors are probably managed via the global palette D01A0-0F
        self.ceres_elevator_palettes = [0x137871,0x137881,0x137891,0x1378A1,0x1378B1,0x1378C1,0x1378D1,0x1378E1]
        self.ceres_elevator_palettes_length = [0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05]

        self.beam_palettes = [0x843E1]
        self.beam_palettes_length = [0x4F]

        #This is in the general palette so as a side-effect it also changes things like energy drops, missile tip colors and other things
        self.wave_beam_trail_palettes = [0xD01AA]
        self.wave_beam_trail_length = [0x02]
        
        #Palette used for the tip of super missiles
        self.super_missile_palettes = [0xD01B0]
        self.super_missile_length = [0x02]

        #Single address for grapple extension color, shifted with same hue as beam palette
        self.grapple_beam_palettes = [0xDC687]
        self.grapple_beam_length = [0x00]
        
        #Space Pirate / Mbrain beam color | excluded for now as it also affects a lot of explosion effects
        self.mbrain_beam_palettes = [0xD01A4]
        self.mbrain_beam_length = [0x02]
        
        
        #Boss palettes
        #[sporespawn,kraid,phantoon,botwoon,draygon,crocomire,bomb-torizo,gold-torizo,ridley,mbrain]

        #Draygon, Kraid, Crocomire and Mother Brain have seperate colors hidden in tileset palettes which are addressed in the boss shift function
        #self.spore_spawn_palettes = [0x12E359,0x12E3D9]
        #self.spore_spawn_length = [0x3F,0x8F]
        self.spore_spawn_palettes = [0x12E359]
        self.spore_spawn_length = [0x3F]
        self.kraid_palettes = [0x138687,0x13B3F3,0x13B533,0x13AAB0,0x1386C7]
        self.kraid_length = [0x1F,0x8F,0x7F,0x03,0x0F]
        self.phantoon_palettes = [0x13CA01,0x13CB41]
        self.phantoon_length = [0x0F,0x7F]
        self.botwoon_palettes = [0x199319,0x19971B]
        self.botwoon_length = [0x0F,0x7F]
        #draygon projectiles: 12A237-0F , they are gray so wouldn't shift well to begin with, leaving this out
        self.draygon_palettes = [0x12A1F7,0x1296AF]
        self.draygon_length = [0x4F, 0x1F]
        self.crocomire_palettes = [0x12387D,0x1238CB,0x1238FD]
        self.crocomire_length = [0x1F, 0x08,0x0F]
        self.bomb_torizo_palettes = [0x1506C7,0x150707]
        self.bomb_torizo_length = [0x1F, 0x1F]
        self.gold_torizo_palettes = [0x150747,0x150787,0x020032]
        self.gold_torizo_length = [0x1F,0x1F,0xFF]
        self.ridley_palettes = [0x1362AA,0x13631A,0x13646A]
        self.ridley_length = [0x2F,0xA7,0x29]
        self.mbrain_palettes = [0x149472,0x1494B2,0x14D264,0x16E448,0x16E648,0x16E6AC,0x16E74C,0x16EA08,0x16EC08,0x16EDAC,0x16EF97,0x16F117,0x1494F2,0x14D082,0x16F281]
        self.mbrain_length = [0x1F,0x0F,0x3F,0xFF,0x2C,0x4A,0x4A,0xFF,0xC0,0x98,0xA8,0x78,0x1F,0x5F,0xC4]

        #All enemy palettes have a length of 0x0F
        #enemy_names = [boyon,tatori+young tatori,puyo,cacatac,owtch,mellow,mella,memu,multiviola,polyp,rio,squeept,geruta,holtz,oum,chute,gripper,ripperII,ripper,dragon,shutter1-4,kamer,waver,metaree,fireflea,skultera,sciser,zero,tripper,kamer,sbug+sbug(glitched),sidehopper,desgeega,big sidehopper,big sidehopper(tourian),big desgeega,zoa,viola,skree,yard,"samus" geemer,zeela,norfair geemer,geemer,grey geemer,boulder,ebi+projectile,fune,namihe,coven,yapping maw,kago,beetom,powamp,work robot+work robot(disabled),bull,alcoon,atomic,green kihunter,greenish kihunter,red kihunter,shaktool,zeb,zebbo,gamet,geega,grey zebesian,green zebesian,red zebesian,gold zebesian,pink zebesian,black zebesian]
        self.enemy_palettes = [0x110687,0x110B60,0x11198D,0x111E6A,0x11238B,0x112FF3,0x11320C,0x113264,0x1132BC,0x113A7B,0x113E1C,0x1140D1,0x1145FA,0x114A2B,0x11580C,0x11617B,0x1162C0,0x116457,0x11657B,0x116978,0x116DC7,0x118687,0x1188F0,0x118C0F,0x11900A,0x11965B,0x11980B,0x119B7B,0x119B9B,0x11A051,0x11B0A5,0x11B3A1,0x11B5B3,0x11C63E,0x11C8A6,0x11DFA2,0x11E23C,0x11E57C,0x11E5B0,0x11E5D0,0x130687,0x140687,0x141379,0x14159D,0x1419AC,0x141F4F,0x142AFE,0x14365E,0x144143,0x1446B3,0x145821,0x145BC7,0x146230,0x14699A,0x1469BA,0x1469DA,0x155911,0x19878B,0x1989FD,0x198AC1,0x198EDC,0x190687,0x1906A7,0x1906E7,0x190727,0x1906C7,0x190707 ]

        ####Enemy Palette Groups####
        #Animal "enemies"
        self.animal_palettes = [0x13E7FE,0x13F225,0x19E525,0x19E944]

        #Sidehopper enemies
        self.sidehopper_palettes = [0x11AA48, 0x11B085]

        #Desgeega enemies
        self.desgeega_palettes = [0x11AF85,0x11B217]

        #Lava enemies | not implementing these unless lava color gets randomized eventually | not sure if multiviola should be in here
        #hibashi,puromi,magdollite
        self.lava_enemy_palettes = [0x130CFB,0x131470,0x142C1C]

        #All Metroid-colored enemies:
        self.metroid_palettes = [0x11A725,0x11E9AF,0x14F8E6,0x1494D2]

        self.various_metroid_palettes = [0x14F6D1,0x16E892,0x16E7F2,0x16E8F0]
        self.various_metroid_length = [0x3F,0x27,0x47,0x61]

        #Crateria security eye + face tile
        self.crateria_special_enemies = [0x140F8C,0x1467AC]

        #Wrecked ship sparks
        self.wrecked_ship_special_enemies = [0x146587]

        #Tourian rinka and undocumented zebetite animation palette
        self.tourian_special_enemies = [0x113A5B,0x137D87]

        #Ship is treated as an enemy in the game
        self.ship_palette = 0x11259E

        #G4 statue 2nd half, 1st half is handled via one of the saveroom shifts
        self.statue_palette_ridley = 0x155745
        self.statue_palette_phantoon = 0x155765
        self.statue_base = 0x155785
        self.statue_fadeout_palettes = [0x6E242,0x6E256,0x6E26A,0x6E27E,0x6E292,0x6E2A6,0x6E2BA,0x6E2CE,0x3839C]
        self.statue_fadeout_size = [0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x07]

        #Degree shuffle array for individual tileset shuffles
        #Insert two entries for [0,1,2,4,5,6,7,8]
        #[0 0 1 1 2 2 3 4 4 5 5 6 6 7 7 8 8 9 10 11 12 13 14 15 16]
        self.degree_list=[]

        #Boss degree list follows this order: [sporespawn,kraid,phantoon,botwoon,draygon,crocomire,bomb-torizo,gold-torizo,ridley,mbrain]
        self.boss_degree_list=[]

        ###########################
        #Suit Palette Information:#
        ###########################
        #Loading and heat-damage glow palettes:
        #Every heat palette is seperated by 2 (unused?) bytes
        #Loader Power Suit: 0x6DB6B, 0x6DBBA, 0x6DC09, 0x6DC58, 0x6DCA4 
        #Heat Power Suit: 0x6E466, 0x6E488, 0x6E4AA, 0x6E4CC, 0x6E4EE, 0x6E510, 0x6E532, 0x6E554, 0x6E576, 0x6E598, 0x6E5BA, 0x6E5DC, 0x6E5FE, 0x6E620, 0x6E642, 0x6E664  |||| final one: 0x6E664 ?
        #Loader Varia Suit: 0x6DCD1, 0x6DD20, 0x6DD6F, 0x6DDBE, 0x6DE0A
        #Heat Varia Suit : 0x6E692, 0x6E6B4, 0x6E6D6, 0x6E6F8, 0x6E71A, 0x6E73C, 0x6E75E, 0x6E780, 0x6E7A2, 0x6E7C4, 0x6E7E6, 0x6E808, 0x6E82A, 0x6E84C, 0x6E86E, 0x6E890  |||| final one: 0x6E890 ?
        #Loader Gravity Suit: 0x6DE37, 0x6DE86, 0x6DED5, 0x6DF24, 0x6DF70
        #Heat Gravity Suit: 0x6E8BE, 0x6E8E0, 0x6E902, 0x6E924, 0x6E946, 0x6E968, 0x6E98A, 0x6E9AC, 0x6E9CE, 0x6E9F0, 0x6EA12, 0x6EA34, 0x6EA56, 0x6EA78, 0x6EA9A, 0x6EABC |||| final one: 0x6EABC ?
        #[$9B:9540-$9B:97E0] not suit palettes?
        #other_palette_offsets = [0x0D9400,0x0D9520,0x0D9540,0x0D9560,0x0D9580,0x0D95A0,0x0D95C0,0x0D95E0,0x0D9600,0x0D9620,0x0D9640,0x0D9660,0x0D9680,0x0D96A0,0x0D9780,0x0D97A0,0x0D97C0,0x0D97E0,0x0D9800,0x0D9820,0x0D9840,0x0D9860,0x0D9880,0x0D98A0,0x0D98C0,0x0D98E0,0x0D9900,0x0D9920,0x0D9940,0x0D9960,0x0D9980,0x0D99A0,0x0D99C0,0x0D99E0,0x0D9A00,0x0D9A20,0x0D9A40,0x0D9A60,0x0D9A80,0x0D9AA0,0x0D9AC0,0x0D9AE0,0x0D9B00,0x0D9B20,0x0D9B40,0x0D9B60,0x0D9B80,0x0D9BA0,0x0D9BC0,0x0D9BE0,0x0D9C00,0x0D9C20,0x0D9C40,0x0D9C60,0x0D9C80,0x0D9CA0,0x0D9CC0,0x0D9CE0,0x0D9D00,0x0D9D20,0x0D9D40,0x0D9D60,0x0D9D80,0x0D9DA0,0x0D9DC0,0x0D9DE0,0x0D9E00,0x0D9E20,0x0D9E40,0x0D9E60,0x0D9E80,0x0D9EA0,0x0D9EC0,0x0D9EE0,0x0D9F00,0x0D9F20,0x0D9F40,0x0D9F60,0x0D9F80,0x0D9FA0,0x0D9FC0,0x0D9FE0,0x0DA000,0x0DA020,0x0DA040,0x0DA060,0x0DA080,0x0DA0A0,0x0DA0C0,0x0DA0E0,0x0DA100]


        #########################
        #        SETTINGS        #
        #########################
        self.settings = settings

        #set to True if all suits should get a separate hue-shift degree
        #"individual_suit_shift": True,
        #set to True if all tileset palettes should get a separate hue-shift degree
        #"individual_tileset_shift": True,
        #Match ship palette with power suit palette
        #"match_ship_and_power": True,
        #Group up similar looking enemy palettes to give them similar looks after hue-shifting
        #(e.g. metroids, big+small sidehoppers)
        #"seperate_enemy_palette_groups": True,
        #Match boss palettes with boss room degree
        #"match_room_shift_with_boss": False,
        ### These variables define what gets shifted
        #"shift_tileset_palette": True,
        #"shift_boss_palettes": True,
        #"shift_suit_palettes": True,
        #"shift_enemy_palettes": True,
        #"shift_beam_palettes": True,
        #"shift_ship_palette": True

        #Change offsets to work with SM practice rom, this was just used for easier feature debugging, changes where new palettes are inserted.
        self.practice_rom = False

        # base address to relocate the compressed palettes
        if self.practice_rom == True:
            # practice rom free space 0x2F51C0 -> 0x2F7FFF
            self.base_address = 0x2F51C0
        else:
            # after the custom credits
            self.base_address = 0x2fe200

        self.power_palette_offsets = [0x0D9400,0x0D9820,0x0D9840,0x0D9860,0x0D9880,0x0D98A0,0x0D98C0,0x0D98E0,0x0D9900,0x0D9B20,0x0D9B40,0x0D9B60,0x0D9B80,0x0D9BA0,0x0D9BC0,0x0D9BE0,0x0D9C00,0x0D9C20,0x0D9C40,0x0D9C60,0x0D9C80,0x0D9CA0,0x0D9CC0,0x0D9CE0,0x0D9D00,0x6DB6B, 0x6DBBA, 0x6DC09, 0x6DC58, 0x6DCA4,0x6E466, 0x6E488, 0x6E4AA, 0x6E4CC, 0x6E4EE, 0x6E510, 0x6E532, 0x6E554, 0x6E576, 0x6E598, 0x6E5BA, 0x6E5DC, 0x6E5FE, 0x6E620, 0x6E642, 0x6E664,0x6DB8F,0x6DC2D,0x6DC7C,0x6DBDE]
        self.varia_palette_offsets = [0x0D9520,0x0D9920,0x0D9940,0x0D9960,0x0D9980,0x0D99A0,0x0D99C0,0x0D99E0,0x0D9A00,0x0D9D20,0x0D9D40,0x0D9D60,0x0D9D80,0x0D9DA0,0x0D9DC0,0x0D9DE0,0x0D9E00,0x0D9E20,0x0D9E40,0x0D9E60,0x0D9E80,0x0D9EA0,0x0D9EC0,0x0D9EE0,0x0D9F00,0x6DCD1, 0x6DD20, 0x6DD6F, 0x6DDBE, 0x6DE0A,0x6E692, 0x6E6B4, 0x6E6D6, 0x6E6F8, 0x6E71A, 0x6E73C, 0x6E75E, 0x6E780, 0x6E7A2, 0x6E7C4, 0x6E7E6, 0x6E808, 0x6E82A, 0x6E84C, 0x6E86E, 0x6E890,0x6DCF5,0x6DD44,0x6DD93,0x6DDE2]
        self.gravity_palette_offsets = [0x0D9540,0x0D9560,0x0D9580,0x0D95A0,0x0D95C0,0x0D95E0,0x0D9600,0x0D9620,0x0D9640,0x0D9660,0x0D9680,0x0D96A0,0x0D9780,0x0D97A0,0x0D97C0,0x0D97E0,0x0D9800,0x0D9A20,0x0D9A40,0x0D9A60,0x0D9A80,0x0D9AA0,0x0D9AC0,0x0D9AE0,0x0D9B00,0x0D9F20,0x0D9F40,0x0D9F60,0x0D9F80,0x0D9FA0,0x0D9FC0,0x0D9FE0,0x0DA000,0x0DA020,0x0DA040,0x0DA060,0x0DA080,0x0DA0A0,0x0DA0C0,0x0DA0E0,0x0DA100,0x6DE37, 0x6DE86, 0x6DED5, 0x6DF24, 0x6DF70,0x6E8BE, 0x6E8E0, 0x6E902, 0x6E924, 0x6E946, 0x6E968, 0x6E98A, 0x6E9AC, 0x6E9CE, 0x6E9F0, 0x6EA12, 0x6EA34, 0x6EA56, 0x6EA78, 0x6EA9A, 0x6EABC,0x6DE5B,0x6DEAA,0x6DEF9,0x6DF48]