diff --git a/Fusion_Graph.py b/Fusion_Graph.py index c36018c..5675570 100644 --- a/Fusion_Graph.py +++ b/Fusion_Graph.py @@ -31,7 +31,58 @@ class Game: self.minorItemLocations.clear() self.itemLocations.clear() self.patcher.clear() - # WARNING: Decompyle incomplete + + try: + with open(vanillaGame, 'rb') as sourceRom: + sourceRom.seek(3967888, 0) + sourceArea = int.from_bytes(sourceRom.read(1), 'little') + sourceDoor = int.from_bytes(sourceRom.read(1), 'little') + targetOffset = sourceRom.tell() + targetArea = int.from_bytes(sourceRom.read(1), 'little') + if sourceArea != 255: + self.areaConnections.update({ + 'S{}-{:02X}'.format(sourceArea, sourceDoor): targetArea }) + self.areaConnectionOffsets.update({ + 'S{}-{:02X}'.format(sourceArea, sourceDoor): targetOffset }) + sourceArea = int.from_bytes(sourceRom.read(1), 'little') + sourceDoor = int.from_bytes(sourceRom.read(1), 'little') + targetOffset = sourceRom.tell() + targetArea = int.from_bytes(sourceRom.read(1), 'little') + continue + for currentArea in range(7): + sourceRom.seek(7977108 + currentArea * 4, 0) + data = sourceRom.read(4) + unpacked = struct.unpack(' 1 and re.search('^[a-zA-Z]', x[1]): + sym.update({ + x[1]: x[0][2:] }) + finally: + pass + os.remove(os.path.join('.', 'data', 'asm', 'temp.sym')) + roomEventOffset = int(sym.get('t_bossanddownloadevents'), 16) + itemEventOffset = int(sym.get('t_obtainitemevents'), 16) + securityOffset = int(sym.get('b_unlocklowerlevels'), 16) + print('roomEventOffset: 0x{:06X}'.format(roomEventOffset)) + print('itemEventOffset: 0x{:06X}'.format(itemEventOffset)) + print('securityOffset: 0x{:06X}'.format(securityOffset)) + roomEventOffset = 8326320 + itemEventOffset = 5726112 + securityOffset = 479192 + for area in RoomNodes: + areaIndex = list(RoomNodes.keys()).index(area) + for node in RoomNodes[area]: + name = node.get('Name') + nodeType = node.get('Type') + if nodeType != None: + itemName = '' + if 'Tank' in nodeType: + itemName = PlacedItems[UsedLocations.index(name)] + bg1 = int(node.get('BG1'), 16) + clipdata = int(node.get('Clipdata'), 16) + tileset = int(node.get('Tileset'), 16) + if SeedSettings['HideItems']: + if tileset == 33: + blockValue = 7 + elif tileset == 34: + blockValue = 7 + elif tileset == 40: + blockValue = 7 + elif tileset == 42: + blockValue = 7 + else: + blockValue = 3 + else: + blockValue = ItemList.index(itemName) + if blockValue < 2: + blockValue = blockValue ^ 1 + elif blockValue > 2: + if tileset == 33: + blockValue = 7 + elif tileset == 34: + blockValue = 7 + elif tileset == 40: + blockValue = 7 + elif tileset == 42: + blockValue = 7 + else: + blockValue = 3 + blockValue += 70 + if tileset == 9: + blockValue += 1 + elif tileset == 11: + blockValue += 1 + elif tileset == 25: + blockValue += 1 + elif tileset >= 30 and tileset <= 34: + blockValue += 1 + elif tileset == 40: + blockValue += 1 + elif tileset == 42: + blockValue += 1 + elif tileset == 48: + blockValue += 1 + elif tileset == 49: + blockValue += 1 + elif tileset == 52: + blockValue += 1 + elif tileset == 56: + blockValue += 1 + elif tileset == 61: + blockValue += 1 + elif tileset == 62: + blockValue += 1 + elif tileset == 64: + blockValue += 1 + elif tileset == 67: + blockValue += 1 + elif tileset == 72: + blockValue += 1 + clipValue = ItemList.index(itemName) + if clipValue < 2: + clipValue = clipValue ^ 99 + if 'Hidden' in nodeType: + clipValue += 2 + elif 'Underwater' in nodeType: + clipValue += 4 + elif clipValue == 2: + clipValue = 104 + if 'Hidden' in nodeType: + clipValue += 1 + elif 'Underwater' in nodeType: + clipValue += 2 + elif clipValue >= 3: + clipValue = (clipValue - 3) * 3 + 120 + if 'Hidden' in nodeType: + clipValue += 1 + elif 'Underwater' in nodeType: + clipValue += 2 + if 'Hidden' not in nodeType: + patchedGame.seek(bg1) + patchedGame.write(blockValue.to_bytes(1, 'little')) + patchedGame.seek(clipdata) + patchedGame.write(clipValue.to_bytes(1, 'little')) + elif 'Boss' in nodeType or 'Data' in nodeType: + itemName = PlacedItems[UsedLocations.index(name)] + itemValue = ItemList.index(itemName) + slot = BossDataList.index(name) + roomEvent = roomEventOffset + if roomEvent != None: + roomEvent = roomEvent + 3 + slot * 4 + if itemValue < 3: + itemValue += 1 + else: + itemValue -= 3 + itemEvent = itemEventOffset + if itemEvent != None: + itemEvent = itemEvent + 1 + itemValue + patchedGame.seek(itemEvent) + itemValue = int.from_bytes(patchedGame.read(1), 'little') + patchedGame.seek(roomEvent) + patchedGame.write(itemValue.to_bytes(1, 'little')) + if name == 'Data S5': + roomEvent = roomEventOffset + roomEvent = roomEvent + 3 + (slot + 1) * 4 + patchedGame.seek(roomEvent) + patchedGame.write(itemValue.to_bytes(1, 'little')) + if itemName in MajorItems: + offset = CreditsOffsets.get(itemName) + if 'Boss' in nodeType: + location = name + elif 'S0' in name: + location = 'Main Deck : ' + else: + location = 'Sector {} : '.format(name[6:7]) + if 'Tank' in nodeType: + location = location + name[8:] + else: + location = location + nodeType + ' Room' + spaces = ceiling(30 - len(location), 2) + location = ' ' * spaces + location + patchedGame.seek(offset) + patchedGame.write(location.encode('ascii')) + for x in range(len(location), 35): + patchedGame.write(0.to_bytes(1, 'little')) + if SeedSettings['HideItems']: + patchedGame.seek(3926048) + patchedGame.write(76.to_bytes(2, 'little')) + patchedGame.write(77.to_bytes(2, 'little')) + patchedGame.write(78.to_bytes(2, 'little')) + patchedGame.write(79.to_bytes(2, 'little')) + patchedGame.write(76.to_bytes(2, 'little')) + patchedGame.write(77.to_bytes(2, 'little')) + patchedGame.write(78.to_bytes(2, 'little')) + patchedGame.write(79.to_bytes(2, 'little')) + patchedGame.write(76.to_bytes(2, 'little')) + patchedGame.write(77.to_bytes(2, 'little')) + patchedGame.write(78.to_bytes(2, 'little')) + patchedGame.write(79.to_bytes(2, 'little')) + if SeedSettings['SplitSecurity'] == True: + security = securityOffset + patchedGame.seek(security) + patchedGame.write(0.to_bytes(2, 'little')) + if SeedSettings['MissilesWithoutMainData']: + patchedGame.seek(24828) + patchedGame.write(15.to_bytes(1, 'little')) + patchedGame.seek(395742) + patchedGame.write(15.to_bytes(1, 'little')) + patchedGame.seek(465582) + patchedGame.write(15.to_bytes(1, 'little')) + if SeedSettings['PowerBombsWithoutBombs']: + patchedGame.seek(24756) + patchedGame.write(32.to_bytes(1, 'little')) + patchedGame.seek(465672) + patchedGame.write(32.to_bytes(1, 'little')) + if SeedSettings['SectorShuffle'] == True: + for currentArea in range(7): + patchedGame.seek(7977108 + currentArea * 4, 0) + data = patchedGame.read(4) + unpacked = struct.unpack(' repeat: @@ -4729,7 +5103,76 @@ def start_randomizer(rom, settings): else: Patch = False settings.pop('Patch') - patch_game() - -# WARNING: Decompyle incomplete + for loop in range(repeat): + initialize() + SeedSettings = settings.copy() + if Debug: + print('Debug generation enabled') + if loop > 0: + SeedValue = str(random.randrange(sys.maxsize)) + Difficulty = SeedSettings['Difficulty'] + DamageRuns = SeedSettings['DamageRuns'] + random.seed(SeedValue + str(SeedSettings)) + World = Graph.Game(BaseGame) + World.RemoveNodeFromRoom('Room-S2-07', 'S2-10') + World.RemoveNodeFromRoom('Room-S2-0D', 'S2-1E') + World.RemoveNodeFromRoom('Room-S3-07', 'S3-10') + World.RemoveNodeFromRoom('Room-S3-12', 'S3-2B') + World.RemoveNodeFromRoom('Room-S5-15', 'S5-2A') + World.AddNodeToRoom('Room-S2-1F', 'S2-10') + World.AddNodeToRoom('Room-S2-2E', 'S2-1E') + World.AddNodeToRoom('Room-S3-16', 'S3-10') + World.AddNodeToRoom('Room-S3-17', 'S3-2B') + World.AddNodeToRoom('Room-S5-16', 'S5-2A') + World.UpdateDoorConnection('S0-4A', 'S0-61') + World.UpdateDoorConnection('S0-96', 'S0-22') + World.UpdateDoorConnection('S0-98', 'S0-20') + World.UpdateDoorConnection('S2-13', 'S2-45') + World.UpdateDoorConnection('S2-19', 'S2-2F') + World.UpdateDoorConnection('S2-1B', 'S2-68') + World.UpdateDoorConnection('S2-23', 'S2-69') + World.UpdateDoorConnection('S2-5F', 'S2-6A') + World.UpdateDoorConnection('S2-6E', 'S2-70') + World.UpdateDoorConnection('S3-2D', 'S3-2E') + World.UpdateDoorConnection('S5-28', 'S5-6C') + AreaItemLocations = list() + for area in range(7): + AreaItemLocations.append(list()) + with open(os.path.join('.', 'data', 'NodeData.json')) as jsonFile: + RoomNodes = json.load(jsonFile) + finally: + pass + for area in RoomNodes: + areaIndex = list(RoomNodes.keys()).index(area) + for node in RoomNodes[area]: + name = node.get('Name') + room = node.get('Room') + item = node.get('Item') + nodeType = node.get('Type') + World.AddNodeToRoom('Room-S{}-{:02X}'.format(areaIndex, int(room, 16)), name) + if item == 'Missile' or item == 'Power Bomb': + World.add_to_minors(name) + elif nodeType == 'Boss': + World.add_to_majors(name) + BossLocations.append(name) + elif nodeType == 'Data' or item == 'E-Tank': + World.add_to_majors(name) + if name == 'Data S3': + BossLocations.append(name) + if not 'Item' in name and nodeType == 'Boss': + if nodeType == 'Data': + AreaItemLocations[areaIndex].append(name) + continue + continue + World.ConnectAllNodes() + StartLocation = 'S0-00' + startTime = time.time() + randomize_game(World) + seedTime = time.time() - startTime + print(str(FileName)) + print('Randomized in:', seedTime) + continue + totalRandoTime = time.time() - totalRandoTime + print('All seeds took:', totalRandoTime) + return FileName