metadata = {}

for i in range(len(vanillaMusicData)):
    addr = musicDataTable+i*3
    ptr = snes_to_pc(rom.readLong(addr))
    if i < len(vanillaMusicData)-1:
        # vanilla data ptrs are conveniently sorted
        endptr = snes_to_pc(rom.readLong(addr+3))
    else:
        endptr = musicDataEnd
    rom.seek(addr)
    nspc_path = "%s/vanilla_%06x_%06x.nspc" % (nspc_dir, ptr, endptr-1)
    print("Writing %s ..." % nspc_path)
    rom.seek(ptr)
    with open(nspc_path, "wb") as nspc:
        nspc.write(rom.read(endptr-ptr))
    musicdata = vanillaMusicData[i]
    for j in range(len(musicdata)):
        track, spc_path, group = musicdata[j]
        h,t=os.path.split(nspc_path)
        metadata[track] = {
            'nspc_path':os.path.join(os.path.split(h)[1], t),
            'data_index':i,
            'track_index':j,
            'original_author':'Kenji Yamamoto',
            'port_author': '',
            'description': "Original track from vanilla Super Metroid",
            "group": group
        }
        if spc_path is not None:
            metadata[track]['spc_path'] = spc_path
def readRooms(romFileName):
    romFile = RealROM(romFileName)
    for roomInfo in rooms:
        romFile.seek(roomInfo['Address'])
        data = romFile.read(RoomHeader.Size)
        roomInfo['RoomIndex'] = data[RoomHeader.RoomIndex]
        roomInfo['Area'] = data[RoomHeader.Area]
        roomInfo['MapX'] = data[RoomHeader.MapX]
        roomInfo['MapY'] = data[RoomHeader.MapY]
        roomInfo['Width'] = data[RoomHeader.Width]
        roomInfo['Height'] = data[RoomHeader.Height]
        roomInfo['UpScroller'] = data[RoomHeader.UpScroller]
        roomInfo['DownScroller'] = data[RoomHeader.DownScroller]
        roomInfo['SpecialGfxBitflag'] = data[RoomHeader.SpecialGfxBitflag]
        roomInfo['DoorsPtr'] = snes_to_pc(
            concatBytes(data[RoomHeader.DoorsPtr1], data[RoomHeader.DoorsPtr2],
                        0x8F))
        #print("")
        #print("{} ({}) ({} x {}) in area: {}".format(roomInfo['Name'], hex(roomInfo['Address']), hex(roomInfo['Width']), hex(roomInfo['Height']), Areas.id2name[roomInfo['Area']]))

        readDoorsPtrs(romFile, roomInfo)
        readDoorsData(romFile, roomInfo)

    roomsGraph = {}
    for roomInfo in rooms:
        nodeName = removeChars(roomInfo['Name'], "][ '-")
        address = roomInfo['Address'] & 0xFFFF
        roomsGraph[address] = {
            'Name': nodeName,
            'Area': roomInfo['Area'],
            'Width': roomInfo['Width'],
            'Height': roomInfo['Height'],
            'Doors': {}
        }
        for doorData in roomInfo["DoorData"]:
            roomsGraph[address]['Doors'][doorData['doorPtr']] = {
                'roomPtr': doorData['roomPtr'],
                'exitScreenX': doorData['screenX'],
                'exitScreenY': doorData['screenY'],
                'exitDirection': doorData['direction']
            }

    # get screen data from corresponding door
    for (entryRoomAddress, entryRoom) in roomsGraph.items():
        for entryDoorData in entryRoom["Doors"].values():
            exitRoomAddress = entryDoorData['roomPtr']
            exitRoom = roomsGraph[exitRoomAddress]
            found = False
            for exitDoorData in exitRoom['Doors'].values():
                #if entryRoom['Name'] in ['GrappleTutorialRoom1', 'GrappleBeamRoom']:
                #print("entry doors count: {} exit doors count: {}".format(len(entryRoom["Doors"]), len(exitRoom['Doors'])))
                #print("{}/{} -> {}/{} ({})".format(entryRoom['Name'], hex(entryRoomAddress), exitRoom['Name'], hex(exitDoorData['roomPtr']), roomsGraph[exitDoorData['roomPtr']]['Name']))
                if exitDoorData['roomPtr'] == entryRoomAddress:
                    #if entryRoom['Name'] in ['GrappleTutorialRoom1', 'GrappleBeamRoom']:
                    #print("exitDoorData['roomPtr'] {} == entryRoomAddress {}".format(hex(exitDoorData['roomPtr']), hex(entryRoomAddress)))
                    for entryDoorData in entryRoom['Doors'].values():
                        if entryDoorData['roomPtr'] == exitRoomAddress:
                            entryDoorData['entryScreenX'] = exitDoorData[
                                'exitScreenX']
                            entryDoorData['entryScreenY'] = exitDoorData[
                                'exitScreenY']
                            entryDoorData['entryDirection'] = exitDoorData[
                                'exitDirection']
                            found = True
                #else:
                #if entryRoom['Name'] in ['GrappleTutorialRoom1', 'GrappleBeamRoom']:
                #print("exitDoorData['roomPtr'] {} != entryRoomAddress {}".format(hex(exitDoorData['roomPtr']), hex(entryRoomAddress)))
            #if found == False:
            #print("door not found ({} -> {})".format(entryRoom['Name'], exitRoom['Name']))
            #print("-----------------------------------------------------------------------------")

    #print(roomsGraph)

    print("""digraph {
size="30,30!";
graph [overlap=orthoxy, splines=false, nodesep="1"];
node [shape="plaintext",fontsize=30];
edge [color="#0025fa80"];
""")
    for (address, roomInfo) in roomsGraph.items():
        if roomInfo['Area'] == Areas.Tourian:
            src = roomInfo['Name']
            print("{} [label = {}];".format(
                roomInfo['Name'],
                genLabel(roomInfo['Name'], roomInfo["Width"],
                         roomInfo["Height"])))
            for doorData in roomInfo["Doors"].values():
                dstInfo = roomsGraph[doorData['roomPtr']]
                dst = dstInfo['Name']
                print("{}:x{}{}:{} -> {}:x{}{}:{};".format(
                    src, doorData.get('entryScreenX'),
                    doorData.get('entryScreenY'),
                    getDir(doorData.get('entryDirection')), dst,
                    doorData.get('exitScreenX'), doorData.get('exitScreenY'),
                    getDir(doorData.get('exitDirection'))))
    print("}")
minAddr, maxAddr = (0xffffffff, 0x0)

# compare nspc data and dump if different than expected
for dataId, expected_nspc in expected_table.items():
    with open(expected_nspc, 'rb') as f:
        expected_music_data = f.read()
    sz = len(expected_music_data)
    snesAddr = rom.readLong(tableAddr + dataId)
    if snesAddr + sz > maxAddr:
        maxAddr = snesAddr + sz
    if snesAddr < minAddr:
        minAddr = snesAddr
    print("Data $%02x, $%06x - $%06x" % (dataId, snesAddr, snesAddr + sz - 1))
    addr = snes_to_pc(snesAddr)
    rom.seek(addr)
    music_data = rom.read(sz)
    if music_data != expected_music_data:
        print("Music data $%02x differ from the one of %s !" %
              (dataId, expected_nspc))
        out_nspc = "track_%02x.nspc" % dataId
        print("Dumping it in %s ..." % out_nspc)
        with open(out_nspc, 'wb') as f:
            f.write(music_data)
    else:
        # check if some block headers are cross-bank
        def isCrossBank(off):
            endBankOffset = (snesAddr + off + 4) & 0x7fff
            return endBankOffset == 1 or endBankOffset == 3

        offending = [
            off for off in nspcInfo[expected_nspc]['block_headers_offsets']